pax_global_header00006660000000000000000000000064134576632270014531gustar00rootroot0000000000000052 comment=257f784804d81afcafe996d4d96b0e93c17a11dc gajim-gajim-1.1.3/000077500000000000000000000000001345766322700137075ustar00rootroot00000000000000gajim-gajim-1.1.3/.gitignore000066400000000000000000000006301345766322700156760ustar00rootroot00000000000000syntax: glob *.orig *.swp *.gmo *.in *.m4 *.pyc *.pyo *~ *# autom4te.cache data/org.gajim.Gajim.appdata.xml data/org.gajim.Gajim.desktop libtool po/.intltool-merge-cache data/gajim-remote.desktop po/gajim.pot po/POTFILES po/stamp-it stamp-h1 Makefile __pycache__/ .mypy_cache/ build/ dist/ gajim.egg-info/ src/gtk/ win/_build_root .vscode syntax: regexp ^config\.* ^config\/ ^scripts\/gajim.* !MANIFEST.in gajim-gajim-1.1.3/.gitlab-ci.yml000066400000000000000000000031051345766322700163420ustar00rootroot00000000000000before_script: - sudo apt-get update -qq && sudo apt-get install -y -qq libtool pkg-config gir1.2-gtk-3.0 python3-gi python3-cairo - sudo apt-get build-dep -y -qq gajim-default-nightly stages: - test - build run-tests: stage: test script: - rm -rf civenv-master - virtualenv --system-site-packages civenv - . ./civenv/bin/activate - pip3 install mypy - pip3 install nbxmpp - pip3 install pylint==2.1.1 - mypy gajim - scripts/dev/pylint-ci.sh --jobs=2 gajim - python3 setup.py test -s test.no_gui - deactivate - rm -rf civenv-master run-appdata: stage: test script: - appstream-util validate data/org.gajim.Gajim.appdata.xml.in run-build: stage: build script: - python3 setup.py sdist - cd dist - export FN="gajim-default-"$(date +%F)".tar" - mv gajim-*.tar.gz $FN.gz - mkdir tmp_add_plugins - mv $FN.gz tmp_add_plugins/ - cd tmp_add_plugins/ - tar xzf $FN.gz - rm $FN.gz - export GF=$(find . -maxdepth 1 -type d -name 'gajim-*') - mkdir -p $GF/gajim/data/plugins/ - cd $GF/gajim/data/plugins/ - curl -O https://ftp.gajim.org/plugins_1/plugin_installer.zip - unzip plugin_installer.zip - rm plugin_installer.zip - cd ../../../.. - tar czf ../$FN.gz gajim-* - cd .. - rm -rf tmp_add_plugins - scp $FN.gz panoramix:/var/www/gajim/downloads/snap/ci/gajim-default-$CI_COMMIT_SHA.tar.gz artifacts: name: "gajim-default-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHA" expire_in: 1 week paths: - gajim-default-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHA.tar.gz gajim-gajim-1.1.3/.gitlab/000077500000000000000000000000001345766322700152275ustar00rootroot00000000000000gajim-gajim-1.1.3/.gitlab/issue_templates/000077500000000000000000000000001345766322700204355ustar00rootroot00000000000000gajim-gajim-1.1.3/.gitlab/issue_templates/Bug.md000066400000000000000000000004021345766322700214700ustar00rootroot00000000000000**Please first check if another issue has been opened for your problem** ## Versions - OS: - Gajim version: - GTK version: - Python-nbxmpp version: ## Steps to reproduce the problem 1. 1. 1. ## Expected behavior ## Actual behavior gajim-gajim-1.1.3/.gitlab/issue_templates/Enhancement.md000066400000000000000000000001761345766322700232100ustar00rootroot00000000000000**Please note by far the quickest way to get a new feature is to file a Merge Request.** ## Description of the new feature gajim-gajim-1.1.3/AUTHORS000066400000000000000000000000001345766322700147450ustar00rootroot00000000000000gajim-gajim-1.1.3/CONTRIBUTING.md000066400000000000000000000003341345766322700161400ustar00rootroot00000000000000 - master - Development branch - gajim_1.0 - Stable Gajim 1.0.x branch - gajim_0.16 - Stable Gajim 0.16.x branch If you are not familiar with Git please read the [HowTo](https://dev.gajim.org/gajim/gajim/wikis/howtogit)gajim-gajim-1.1.3/COPYING000066400000000000000000001045131345766322700147460ustar00rootroot00000000000000 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 . gajim-gajim-1.1.3/ChangeLog000066400000000000000000000723211345766322700154660ustar00rootroot00000000000000Gajim 1.1.3 (24 April 2019) New * Add a mobile phone indicator to the chat window * Rework HTTPUpload dialog * Add a "paste as quote" option to the message input Bug fixes * #8822 Fix memory leak when using spell checker * #9514 Fix jingle filetransfers not working in some circumstances * #9573 Dont leak DNS query when connecting over proxy * #9578 Determine Windows version more reliably * #9622 Fix an error while quitting Gajim * #9633 Fix an error while sending a file * #9637 Restore window size correctly on wayland * #9660 GPG Agent setting is ignored * #9645 Make zeroconf IPV6 compatible * Improve dark theme colors * Fix access to GnuPG keys * Use UUID4 item ids for pubsub posts * Dont send invalid show values * Windows: Dont override format region settings * Various smaller improvements Gajim 1.1.2 (15 January 2019) Bug fixes * #9518 Windows: Pressing "^" yields "^^" * #9522 Windows: Switching keyboard layouts leads to a crash * #9525 Windows/Mac: Links are not clickable in the About dialog * #9535 Jingle Audio: Update codecs * #9537 DiscoveryWindow: Fix bookmarking a group chat * DBus: Correctly raise NewMessage signal * Clicking on tray notifications does not open the chat Gajim 1.1.1 (23 December 2018) Bug fixes * #8362 DBus: Incorrect unread message count * #9427 Placeholder not cleared if pasting text into message input * #9444 Determine the delay timestamp correctly when using mam:1 * #9453 Fix opening links inside the group chat subject (MacOS/Windows) * #9465 Allow the full range of possible nicknames in group chats * #9067 Gajim crashes when receiving xhtml messages * #9096 Error when clicking on a subscription notification * #9446 Chatstate error in MUC conversation * #9471 Conversation Textview: Error on key press * #9472 Handle presences without from attr correctly * #9473 Error when creating a new group chat * #9491 Identify group chat subject changes correctly * #9496 Error on MUC roster selection change * Determine soundplayer correctly on unix systems * In some circumstances plugins could not be deleted * Show correct contact status on tabs * Dont answer group chat receipt requests * Fix receipts for private messages * Pressing the back button in the Accounts window leads to an error * Better handle not available keyring backends * Dont show incorrect contact on private messages * Join group chat menu is disabled when there are no bookmarks * Error on start chat menu action * Error when opening sign-in/out notification * Copying text does not work with different keyboard layouts Gajim 1.1.0 (06 November 2018) New * Remove support for XEP-0091 Bug fixes * #8968 Windows: Gajim loads DLLs from wrong location * #9322 Error when adding contact * #9357 Acquire sleep inhibtor correctly after sleep * #9385 Ignore invalid bookmarks * #9386 Discovery: Browsing nodes without identity * #9393 Error when parsing invalid timestamps * #9398 Error on jingle file transfer Gajim 1.0.99.1 (07 October 2018) New * Implement XEP-0398 * MUC: Set Threshold for requesting history * Show icon for unencrypted messages * Support more media players for broadcasting the current tune * Windows: Add a debug logging switch in preferences * Preferences: enable/disable dark theme * Preferences: enable/disable the MUC subject beeing shown on join * Preferences: enable/disable ascii emoji conversion Bug fixes * #9198 Creating new MUCs with captial letters is not possible * #9210 Error when clicking on new message indicator * #9280 Inviting users to a MUC causes error * #9301 Error when opening service discovery window * #9309 Error when clicking on a groupchat invite notification * #9311 Error when requesting server info * #9117 Windows UAC changes status not available * #9324 No menus/dialogs on Win7 * #9326 IPV6 Connection problem on Win10 * #9334 Joining big MUCs takes very long * #9339 Error caused by remote_control Gajim 1.0.99 (19 August 2018) New * Support for setting a MUC Avatar * Support for PKIX over Secure HTTP (POSH) * Support idle time for GNOME on Wayland * New Emoji chooser * Noto Emoji theme updated to Unicode 11 * Twitter Emoji theme added * Gajim Theming reworked * Design updates to many dialogs - Join Groupchat - Bookmarks - Add new contact - History - Profile - Accounts Bug fixes * #8658 Translation doesnt work on Windows * #8750 Increase time frame for duplicate search in MUCs * #9138 Translation in Flatpak does not work * #9140 Error when clicking on the notification of an incoming message * #9159 Wrong form type when responding to a voice request * #9069 Send cancel IQ if muc configuration is aborted * #9167 Flatpak fails to determine locale settings * #9171 Gajim requests vcard multiple times * #9198 Creating new MUCs with capital letters is not possible * #9211 Punycode and Unicode with Internationalized Domain Names Other changes * Support http:upload:0 * Remove forward message adhoc commands * Remove support for XEP-0090 * Remove RC4-SHA because it is insecure (Was not used with current OpenSSL versions) * Improve speed when loading the roster * Handle new MUC status code 333 * Switch to GDBus for Gajim remote * Removed support for ESessions * Improvements to the dark theme of Gajim * New dependency: python3-cssutils >= 1.0.2 * New dependency: python3-keyring * Removed dependency: python3-avahi * Removed dependency: python3-pyasn1 Gajim 1.0.3 (20 May 2018) Bugs fixed: * #8296 Fix errors on roster updates after stream management resume * #9106 Convert font weight from pango to css values * #9124 Bring ChatControl to front when notification is clicked * Set no-store hint on groupchat chatstates * Dont show OOB uri if message body is the same * Add missing bybonjour dependency for Windows zeroconf Flatpak: * Limit dbus access Gajim 1.0.2 (30 April 2018) Bugs fixed: * #7879 Server name is rejected for group chat bookmarks * #8964 setup.py install misses some files if used with "--skip-build" * #9017 Password was sometimes stored in plaintext * #9022 Dont show error when receiving invalid avatars * #9031 Windows: Always hide roster window on X * #9038 No License in About dialog * #9039 Encode filenames before sending * #9044 Catch invalid IQ stanzas and log them * #9049 XMPP logo in "Add New Contact" window instead Gajim logo * #9050 Mark some strings as translatable * #9054 Error on file send completion * #9055 Removing a bookmark causes error * #9057 Avatar is deleted when updating vCard * #9065 Account label isn't change in tooltip of notification area icon * #9066 Placeholder text does't disappear * #9068 Missing pulseaudio in Flatpak image * #9070 Fix History Manager search * #9074 Proxy comobobox in accounts/connections doesn't get update after ManageProxies * #9094 problem receiving file * #9101 Notification never autohides in gnome * Correctly reload Plugins * Save history export with utf8 encoding * Dont allow plain BOSH by default Gajim 1.0.1 (1 April 2018) * Improve MAM support * Image preview in file chooser dialog * Groupchat: Set minimize on auto join default True * Delete bookmark when we destroy a room * Fix account deletion * Fix custom font handling * Fix OpenPGP message decryption * Fix window position restore on multi-head setups * Fix scrolling in message window * Improve Windows build and build for 64 bits Gajim 1.0.0 (17 March 2018) * Ported to GTK3 / Python3 * Integrate HTTPUpload * Add Navigation buttons in History Window * Improvements for HiDPI Screens * Depend on the python keyring package for password storage * Flatpak support * Lots of refactoring * New Emoji support * New Chat Window design * New StartChat Window (Ctrl+N) * New ServerInfo Window * AccountWindow Redesign * Moved some encryption code out into Plugins (see PGP Plugin, Esessions Plugin) * OTR Plugin was not ported, use OMEMO * Added mam:1 and mam:2 support (mam:0 was removed) * Added MAM for MUCs support * Added support for showing XEP-0084 Avatars * Add support for geo: URIs * Added xmpp URI handling directly in Gajim * Removed Gajim-Remote * Removed XEP-0012 (Last Activity) * Removed XEP-0136 (Message Archiving) * Added XEP-0156 (Discovering Alternative XMPP Connection Methods) * Added XEP-0319 (Last User Interaction in Presence) * Added XEP-0368 (SRV records for XMPP over TLS) * Added XEP-0380 (Explicit Message Encryption) * Added Jingle FT:5 support * Lots of other small bugfixes KNOWN ISSUES: - Meta Contacts: Filtering the roster could lead to a crash in some circumstances. Use CTRL + N for starting new chats as a workaround - Audio/Video support is currently not maintained and most likely not working - Windows: Translation is not working currently Gajim 0.16.9 (30 November 2017) * Improve Zeroconf behavior * Fix showing normal message event * remove usage of OpenSSL.rand * a few minor bugfixes Gajim 0.16.8 (04 June 2017) * Fix rejoining MUCs after connection loss * Fix Groupchat invites * Fix encoding problems with newer GnuPG versions * Fix old messages randomly reappearing in the chat window * Fix some problems with IBB filetransfer * Make XEP-0146 Commands opt-in * Improve sending messages to your own resources * Improve reliability of delivery recipes * Many minor bugfixes Gajim 0.16.7 (30 January 2017) * Better compatibility with XEP-0191: Blocking Command * Windows Credential Vault is used for password storage on Windows * Gajim now depends on python-gnupg for PGP encryption * Add portable installer for Windows * Remove usage of demandimport * Many minor bugfixes Gajim 0.16.6 (02 October 2016) * Fix using gpg2 * Improve message receipts usage * Improve roster filtering * several minor bugs Gajim 0.16.5 (28 December 2015) * Improve MAM implementation * Improve security on connexion and for roster managment * Ability for emoticons to be sorted in menu Gajim 0.16.4 (26 September 2015) * Fix trusting GPG keys * Ability to disable synchronization of logs with server * Improve MAM usage Gajim 0.16.3 (31 July 2015) * Fix reading secret file * Fix reconnection after suspend * Fix sending GPG-encrypted file to non-trusted key Gajim 0.16.2 (24 July 2015) * improve Zeroconf under windows and with IPv6 * Fix errors with GnuPG * Minor fixes and improvements Gajim 0.16.1 (28 February 2015) * Fix sending Zeroconf messages * Make ipython compatible to version >= 1.0 * Support XEP-0313 MAM * Minor fixes and improvements Gajim 0.16 (04 October 2014) * Improve File transfer support by adding Jingle file transfer * use external python-nbxmpp library * Improve audio / Video calls and add screensharing feature * Support audio under windows * Support systemd-logind * Support XEP-0308 Last message correction * Support XEP-0224 Attention * Support XEP-0191 Blocking command * Better RTL languages support * use host command to resolve SRV records if it is available Gajim 0.15.4 (25 May 2013) * Fix usage of OTR plugin * Fix connection to non-SSL server * Fix receiving GPG-encrypted messages while offline. Gajim 0.15.3 (17 March 2013) * Better handling of SSL errors * Better handling of canceling file transfer * Improve farstream calls * Minor fixes and improvements Gajim 0.15.2 (30 October 2012) * Show punycode encoded urls if they contain non-ascii chars * Fix crash when pressing Esc in chat window * Support Network Manager 0.9 * decrypt GPG messages in the correct order Gajim 0.15.1 (29 August 2012) * Switch from python-farsight to python-farstream * improve performances * Fix roster filter with unicode chars * Fix connection to msn jabber server * Fix some GPG issues * Fix other small issues Gajim 0.15 (18 March 2012) * Plugin system * Whiteboard (via a plugin) * Message archiving * Stream managment * IBB * Nested roster group * Roster filtrering * UPower support * GPG support for windows * Spell checking support for windows Gajim 0.14.4 (22 July 2011) * Fix translation issue * other minor fixes Gajim 0.14.3 (19 June 2011) * Fix history viewer * Fix closing roster window * Prevent some erros with metacontacts Gajim 0.14.2 (07 June 2011) * Fix CPU usage when testing file transfer proxies * Fix invalid XML char regex * Fix subscription request window handling * Fix URL display in chat message banner * Other minor bugfixes Gajim 0.14.1 (26 October 2010) * Fix changing account name * Fix sending XHTML * Fix GnomeKayring usage * Fix some GPG bugs * Minor bugfixes Gajim 0.14 (02 September 2010) * Jingle audio / video chat * Improve Startup time * Copy emoticons, LaTeX expressions when they are selected * Fix status icon transparency by using gtk.statusicon * Groupchat auto-rejoin * geolocation (with geoclue) * use XDG standards * SCRAM-SHA-1 and SASL EXTERNAL authentication * MUC captcha * Lots of refactoring Gajim 0.13.4 (02 April 2010) * Add japanese translation * Fix some TLS connection * Don't raise a lot of "DB Error" dialog * Fix contact synchronisation * Minor fixes Gajim 0.13.3 (23 February 2010) * Fix facebook xmpp server connection * Fix copy / paste with Ctrl+C on non-latin keyboard * Fix sending PEP information when connecting * Fix parsing HTML messages that have ascii markup Gajim 0.13.2 (14 January 2010) * Fix some translations * Fix string comparison according to locales * Fix resizing of groupchat occupant treeview * Fix some gnomekeyring glitches * better SRV usage with libasyncns * copy emoticons when we copy / paste in conversations Gajim 0.13.1 (28 November 2009) * Fix a bug when no account exists and bonjour is not available * Fix a bug when opening advanced option in MUC * Fix a bug when using non-BOSH proxies Gajim 0.13 (24 November 2009) * Improve gtkspell (fix memleak) * BOSH connection * Roster versioning * Ability to send contacts * GUI to send XHTML messages * Improve sessions handling * pubsub storage (for bookmarks) * Ability to select account when joining a groupchat * Better Gnome keyring support * Ability to ignore occupants in groupchats * Ability to show / hide self contact row * Automatically go away when screensaver is enabled under windows * Ability to enable / disable accounts * better URL recognition * groupchat autoreconnect * Store passwords in KDE wallet if available * Better MUC errors handling * Fix sound player launch (don't create zombies anymore) * Optional shell like completion * New color theme Gajim 0.12.5 (08 August 2009) * Don't depend on GTK 2.14 Gajim 0.12.4 (07 August 2009) * Fix History manager * Fix file transfer proxy discovering at connection * Improve filetransfer with IPv6 * Fix zeroconf when receiving badly encoded info Gajim 0.12.3 (12 June 2009) * Fix PLAIN authentication (in particular with Gtalk * fix PEP discovery Gajim 0.12.2 (07 June 2009) * Better keepalive / ping behaviour * Fix custom port handling * Improve error messages handling * Totem support for played music * Fix SSL with some servers * Handle XFCE notification-daemon * Restore old behaviour of click on systray: left click to open events * Network manager 0.7 support * Move logs file under windows to $APPDATA/gajim * Improve Kerberos support * Many bugfixes here and there * Add -c option to history_manager Gajim 0.12.1 (21 December 2008) * Fix filetransfer * Updated german translation * Fix click on notifications when text string is empty * Improve systray popup menu Gajim 0.12 (17 December 2008) * Fix text rendering in notifications * Fix forward unread messages under Windows * Better sessions support * Better auto-away support * Fix banshee support * Quodlibet support * Fix GSSAPI authentification * Fix IPV4 filetransfer on Windows Vista when IPV6 is used too * Fix caps usage * Fix end to end encryption autonegotiation Gajim 0.12-beta1 (11 November 2008) * SECURITY * Implement Kerberos (GSSAPI) SASL Authentication mechanism * Prevent affiliation spoofing in groupchats * Improve GPG and E2E support * GUI * Highlight all valid IANA schemes * Improved E2E, Mood and Activity dialogs * Show number of participants in groupchats * Connection * Correctly parse IDNA names in SRV records * Disable proxy resolution (#4299) * Fix handling of namespace invalid XML * Do not freeze on connection failures (#4366, #4107) * OTHERS * Do not crash on fluxbox restarts * Update several hotkeys and make them work on non-latin keyboards * Prevent a user from sending invalid XML chars * Do not try to save a file with a too long filename when a nick is long * Implement XEP-0203 (Delayed Delivery) * Improved windows installer * Latex support for windows Gajim 0.12-alpha1 (12 August 2008) * Change licence from GPLv2 to GPLv3 * SECURITY * Support for End-To-End encryption (XEP-0116) * SSL certificate verification * Improve GPG support (#2390, #2783) * Ability to disable message previews in notify popups * GROUP CHATS * Support for sending files over group chats * List of bookmarked rooms is now sorted alphabetically * Support for transforming a one-to-one chat into a groupchat * Send invitation by drag-and-dropping a contact from roster * Send messages to conference using gajim-remote * Ability to destroy a room when we are owner, give a reason and alternative room jid * Ability to minimize group chats in roster * USABILITY * Files transfers using drag and drop * Ability to select and interact with status messages in chat windows (using libsexy) * Ability to set a custom avatar for a contact * Better handling of resource collisions * Option to Sign On as a Certain Status (#3314) * Block/Unblock contact directly from roster using privacy lists * GUI * Single window mode * Close change status windows after 15 seconds of inactivity * Simplified "Accounts" dialog * Preferences window redesign * New GUI for chat window * Roster treeview now uses modelfilter (way way much faster) * OTHER * Support of PEP (Personal Eventing Protocol) (XEP-0163) * User Mood (XEP-0107) * User Activity (XEP-0108) * User Tune (XEP-0118) * User Nickname (XEP-0172) * Support for Google Talk accounts with non gmail.com domain (+ GMail notifications) * Modified the format of emoticons list file, so we can choose the default code (#3696) * New Remote Controlling Option (XEP-0146): forward unread messages * Support for User Search (XEP-0055) * Support for jabber:x:data in message elements (Part of XEP-0004) * Added a «supported features» window * Latex support (#2796) * Link-local messaging with Windows (#2883) * Ability to send a custom status to a group, a contact or a transport * Support of Message Receipts (XEP-0184) Gajim 0.11.4 (06 December 2007) * Fix /nick command in groupchats * Better Metacontacts sorting * Fix Ctrl + PageUP/Down behaviour * Fix saving files from filetransfer under windows Gajim 0.11.3 (17 November 2007) * Fix bookmarks support detection * Improve file transfer on windows * Fix some zeroconf bugs * Fix focus bug in chat window * Fix nickname changement behaviour in groupchats Gajim 0.11.2 (22 September 2007) * Improve idle, transports support * Enable ellipsization in roster and chatwindow * Fixed some metacontacts problems (#2156, #2761) * Beter support of XEP-0070 (Verifying HTTP Requests via XMPP) * Make the same height of a banner for all chat tabs * Fix a bug with french translation and invitations (#3043) * Fix a bug with UTF-8 and emoticons * Corrected many bugs with passwords and gnome-keyring * Improve xhtml-im and pictures support * Improve Ad-Hoc support * And many other bufixes Gajim 0.11.1 (18 February 2007) * Fixes in gajim-remote and the way XMPP URI are handled * Fix Idle under Windows * Fix Gajim under non-ascii languages Windows * Fix International Domain Name usage * Fix when removing active privacy list * Fix problem with adhoc command and multi-step forms * Fixed avatars cache problems in group chats * KDE integration for XMPP URI * Support of Banshee Music player * Support of XEP-0202 (Entity Time) * Support of XEP-0199 (XMPP Ping) Gajim 0.11 (19 December 2006) * New build system, using GNU autotools. See README.html * Support for link-local messaging via Zeroconf using Avahi (XEP-0174) * Automatically connect and disconnect to accounts according to network availability (if Network Manager is present) * IPV6 support to connect to server * Ad-Hoc commands * GNOME Keyring Support (if GNOME keyring is available, manage passwords and save them in an encrypted file) * Introducing View Menu (GNOME HIG) * Ability to now hide the Transports group * Support for notify-python. So if notification-daemon is not available, we still can show cool popups * Connection lost is now a non-intrusive popup * Try to get contact desired nick when we add him to roster aka User Nickname (XEP-0172) * Support for Privacy Lists (XEP-0016) * Better design of User Profile window, with a progress bar * New Add User dialog, with possibility to register to transport directly from it * Completion for "Start Chat" input dialog * Metacontacts across accounts (#1596) * Ability to have a different spellchecking language in each chat window. (#2383 and #746) * Forbid to run multiple instances (but you can use differents profiles) * Ability to save avatar with right click on avatar in chat banner * Annotations (XEP-0145) * XHTML Support * Rhythmbox and Muine song change notification * Ability to operate on more than one contact at once in roster (#1514) * Send single message to a whole group * Delete a whole group * Gajim now remembers if GPG encyption was enabled per contact * Priority can be changed automatically when we change status * Fuzzyclock support * Mute sounds from systray menu * Add possibility to start a chat or see contact's infos from subscription request window * Use different colors for each participant in groupchats * Ability to show only Join/Leave in groupchats instead of all status changes * New possibilities to insert nickname of a participant in groupchat conversations: Tab in an empty line now cycles through nicks, maj+right click->inserts nickname, maj+click on name in gc-roster, /names command to show all users presence * Fixed bugs when removing or renaming an account with tabs open (#2369 and #2370) * New translations: Croatian, Esperanto, British English, Belarusian Gajim 0.10.1 (06 June 2006) * Freeze and lost contacts in roster (#1953) * Popup menus are correctly placed * High CPU usage on FreeBSD (#1963) * Nickname can contain '|' (#1913) * Update pl, cs, fr translations * Don't play sound when no event is shown (#1970) * Set gajim icon for history manager * gajim.desktop is generated with translation (#834) * Preventing several TBs and annoyances (r6273, r6275, r6279, r6301, r6308, r6311, r6323, r6326, r6327, r6335, r6342, r6346, r6348) Gajim 0.10 (01 May 2006) * One Messages Window ability (default to it) with tab reordering ability * Non blocking socket connections. Gajim no longer remains unresponsive. * Gajim now uses less memory * File Transfer improvements (now should work out of the box for all) * Meta Contacts ability (relationships between contacts) * Support for legacy composing event (JEP-0022). Now 'Contact is composing a message' will always work * Gajim now defaults to theme that uses GTK colors * Roster Management Improvements (f.e. editablity of transport names, extended Drag and Drop Functionality) * History (chat logs) Manager (search globally, delete, etc) * Animated Emoticons ability * Support for GTalk email notifications for GMail * Room administrators can modify room ban list * Gajim no longer optionally depends on pydns or dnspython. Requires dnsutils (or whatever package provides the nslookup binary) * gajim-remote has extended functionality * Improved Preset Status Messages Experience * Detection for CRUX as user's operating system * New art included, appropriate sizes of icons used where available * Translations under Windows now work okay * Tons of fixes for bugs and annoyances: http://trac.gajim.org/query?status=closed&milestone=0.10 Gajim 0.9.1 (27 December 2005) * Fix bug when joining a Groupchat * Fix bug when starting Gajim without old logs Gajim 0.9 (23 December 2005) * Avatars and status messages in roster window * Improved service discovery window * Emoticons selector, Cooler Popup Windows (notification-daemon). Read more information in case you did not notice something different in http://trac.gajim.org/wiki/GajimDBus#notif_daemon * Caching of Avatars, Less UI freezing * New Account creation wizard * Better History Window with searching capabilities * Gajim now tries to reconnect to a jabber server if connection is lost * Queue for all events (File Transfer, private messages, etc) * A lot of new irc-like commands in group chat. Do for example /help invite * X11 Session Management support * Gajim registers and handles xmpp: and xmpp:// (GNOME/gconfd only) * Use pysqlite for conversation history. Automigration for old logs * New translations: Italian, Swedish, Slovak, Basque Gajim 0.8.2 (06 Sep 2005) * Fix so Gajim runs in pygtk2.8.x * Gajim can use pydns too (apart from dnspython) to do SRV lookup * Other minor fixes Gajim 0.8.1 (02 Sep 2005) * Systray icon for windows * Gajim is available in Dutch * Gajim can use gpg-agent Gajim 0.8 (18 Aug 2005) * Avatars (JEP-0153) * Chat state notifications aka. typing notification (JEP-0085) * Bookmark storage (JEP-0048) * File Transfer (JEP-0096) * Major changes to adhere to GNOME HIG * Complete vcard fields support * New and better user interface for chat and groupchat windows * SRV capabilities and custom hostname/port * Many improvements in group chat and IRC emulation (eg. nick autocompletation and cycling) * Gajim can now send and receive single messages * New iconsets and new dialog for customizing the user interface * Mouseover information for contacts in the roster window (aka tooltips) * DBus Capabilities. Now Gajim can be remote controlled * Authenticating HTTP Requests via XMPP (JEP-0070) * Now you can lookup a word in Wikipedia, dictionary or in search engine * XML Console * Gajim is now also available in norwegian and czech language Gajim 0.7.1 (5 Jun 2005) * Transports icon as an option and error/mesage icon for transports * Gajim is more HIG compatible * Editing registration information on transports * Messages stanza without element are not printed * SASL bugfix * GtkSpell capabilities * Support SSL (legacy) connection * Assign gpg key to specific contact * Contacts are sortable by status * Gajim remembers last lines when reopening chat * New translations available: German, Russian, Spanish, Bulgarian Gajim 0.7 (23 May 2005) * Ability for groupchat reserved rooms with full affiliations and roles support * Popup notification for incoming events * Protocol icons for contacts from transports * Gajim's user interface is now more HIG compliant * Gajim now detects and can send operating system information * Gajim now can inform the user about new version availability * Gajim jabber library migration from jabberpy to xmpppy * Rewrite the plugin system to remove threads and improve latency * Gajim now supports Nodes in Service Discovery * Greek and Polish translations Gajim 0.6.1 (03 April 2005) * Rewrite of service discovery. It doesn't freeze Gajim anymore. * More HIG Compliant. * Gajim is faster (do not redraw preferences_window each time we open it, use of psyco if available) Gajim 0.6 (23 March 2005) * Gajim's user interface is now nicer. * Groupchat just got better. * URL, mailto and ascii formatin (* / _) detection * Better transports detection, group management, and many minor additions/bugfixes Gajim 0.5.1 (27 February 2005) * Minor bugfixes. Gajim 0.5 (26 February 2005) * Possibility to use tabbed chat window * Sound support under GNU/linux * Autoaway available under Microsoft Windows Gajim 0.4.1 (23 January 2005) * Bugfix in config file parser (fix config file parser to handle emoticons) * Bugfix with GPG signatures Gajim 0.4 (21 January 2005) * New option: regroup accounts * Emoticons support with a binder * GUI improvements * Bugfixes Gajim 0.3 (18 December 2004) * GUI improvements * group chat support with MUC (JEP 45) * New agent browser (JEP 30) * GnuPG support * Autoconnect at startup * New socket plugin Gajim 0.2.1 (1 July 2004) * bugfixes : when configfile is incomplete * icon in systray with popup menu (for linux) * "auto away even if not online" option * always show contacts with unread messages * new imageCellRenderer to show animated gifs * allow agents unregistration Gajim 0.2 (8 June 2004) * bugfix for french translation * multi-resource support * auto away support (for linux) * invisible support * priority support Gajim 0.1 (21 May 2004) * Initial release. gajim-gajim-1.1.3/MANIFEST.in000066400000000000000000000002001345766322700154350ustar00rootroot00000000000000include COPYING recursive-include po *.po recursive-include data *.1 *.in recursive-include test *.py recursive-exclude * *.pyc gajim-gajim-1.1.3/README.md000066400000000000000000000044061345766322700151720ustar00rootroot00000000000000# Welcome to Gajim ### Runtime Requirements - python3.5 or higher - python3-gi - python3-gi-cairo - gir1.2-gtk-3.0 (>=3.22) - python3-nbxmpp (>=0.6.9,<0.7.0) - python3-openssl (>=0.14) - python3-cssutils (>=1.0.2) - python3-keyring - python3-precis-i18n ### Optional Runtime Requirements - python3-pil (pillow) for support of webp avatars - python3-gnupg to enable GPG encryption - For zeroconf you need python3-dbus on Linux or [pybonjour](https://dev.gajim.org/lovetox/pybonjour-python3) on Windows/macOS - gir1.2-gspell-1 and hunspell-LANG where lang is your locale eg. en, fr etc - gir1.2-secret-1 for GNOME Keyring or KDE support as password storage - D-Bus running to have gajim-remote working - gir1.2-farstream-0.2, gir1.2-gstreamer-1.0 and gir1.2-gst-plugins-base-1.0 for audio and video calls - gir1.2-gupnpigd-1.0 for better NAT traversing - gir1.2-networkmanager-1.0 for network lose detection - gir1.2-geoclue-2.0 for sharing your location ### Compile-time Requirements - python-setuptools ### Installation Procedure #### Packages - [Arch](https://aur.archlinux.org/packages/gajim-git/) - [Debian](https://packages.debian.org/source/experimental/gajim) (tested with Debian ``testing`` and ``unstable``) #### Snapshots - [Daily Linux](https://www.gajim.org/downloads/snap/?M=D) - [Daily Windows](https://gajim.org/downloads/snap/win) #### Linux ``./setup.py install --root=/`` or ``pip install .`` (python-pip is required) #### Mac see [Wiki](https://dev.gajim.org/gajim/gajim/wikis/help/gajimmacosx#python3brew) #### Developing For developing you don't have to install Gajim. After installing all dependencies execute ``./launch.py`` #### Flatpak see [README](./flatpak/README.md) #### Windows see [README](./win/README.md) ### Miscellaneous #### Debugging Execute gajim with --verbose #### Links - [FAQ](https://dev.gajim.org/gajim/gajim/wikis/help/gajimfaq) - [Wiki](https://dev.gajim.org/gajim/gajim/wikis/home) That is all, **enjoy**! (C) 2003-2019 The Gajim Team [https://gajim.org](https://gajim.org) We use original art and parts of sounds and other art from Psi, Gossip, Gnomebaker, Gaim and some icons from various gnome-icons (mostly Dropline Etiquette) we found at art.gnome.org. If you think we're violating a license please inform us. Thank you. gajim-gajim-1.1.3/appveyor.yml000066400000000000000000000035501345766322700163020ustar00rootroot00000000000000environment: matrix: - MSYSTEM: MINGW64 MSYS_ARCH: "x86_64" ARCH: "64bit" - MSYSTEM: MINGW32 MSYS_ARCH: "i686" ARCH: "32bit" branches: only: - gajim_1.1 clone_depth: 1 # init: # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) build_script: - del C:\Windows\System32\libssl-*.dll C:\Windows\system32\libcrypto-*.dll - del C:\Windows\SysWOW64\libssl-*.dll C:\Windows\SysWOW64\libcrypto-*.dll - C:\msys64\usr\bin\pacman -Syuu --needed --noconfirm --noprogressbar --overwrite \\* - ps: | $env:TIME_STRING=(get-date -UFormat "%Y-%m-%d").ToString() $env:BUILDROOT="C:\msys64\home\appveyor\gajim\win\_build_root" function bash($command) { Write-Host $command -NoNewline C:\msys64\usr\bin\sh.exe --login -c $command } bash "git clone C:/projects/gajim C:/msys64/home/appveyor/gajim" bash "C:/msys64/home/appveyor/gajim/win/build.sh $($env:MSYS_ARCH)" Push-AppveyorArtifact "$($env:BUILDROOT)/Gajim.exe" -FileName "Gajim-1.1.2-$($env:ARCH)-$($env:TIME_STRING).exe" Push-AppveyorArtifact "$($env:BUILDROOT)/Gajim-Portable.exe" -FileName "Gajim-Portable-1.1.2-$($env:ARCH)-$($env:TIME_STRING).exe" # on_finish: # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) deploy: # FTP deployment provider settings - provider: FTP protocol: ftp host: panoramix.gajim.org username: secure: SNcOJDhUtBjfddbKXudE2w== password: secure: tQkYbcUb6nChCp0cdqo4CA== folder: win_snap active_mode: false beta: true # enable alternative FTP library for 'ftp' and 'ftps' modes debug: true gajim-gajim-1.1.3/data/000077500000000000000000000000001345766322700146205ustar00rootroot00000000000000gajim-gajim-1.1.3/data/gajim-history-manager.1000066400000000000000000000043561345766322700211100ustar00rootroot00000000000000.Dd January 21, 2018 .Dt GAJIM-HISTORY-MANAGER 1 URM .Os UNIX .Sh NAME .Nm gajim-history-manager .Nd a tool to manage .Xr gajim 1 logs .Sh SYNOPSIS .Nm .Fl h .Nm .Op Fl c Ar directory .Sh DESCRIPTION .Nm is a tool to manage .Po do some cleanup Pc log file of .Xr gajim 1 . Use this program to delete or export logs. For more information on database logs see . .Sh OPTIONS .Bl -tag -width Ds .It Fl h Fl Fl help Show help options .It Fl c Fl Fl config-path Em directory Where to look for logs file .El .Sh FILES .Bl -tag -width Ds .It $XDG_DATA_HOME/gajim/logs.db The history database log file used when .Op Fl c is not specified. .El .Sh AUTHORS .An -nosplit .Nm is written and maintained by .An Yann Leboulanger , and .An Denis Fomin , with contributions and patches merged from many individuals around the world. See files .Pa AUTHORS and .Pa THANKS , for a complete list. .Sh COPYRIGHT Copyright (C) 2003-2019 Gajim Team .Pp .Nm is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 only. .Pp .Nm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. .Pp You should have received a copy of the GNU General Public License along with .Nm . If not, see . .Sh FEEDBACK You can report bugs or feature requests in our bug tracker at .Em https://dev.gajim.org/gajim/gajim/issues or in the .Em gajim-devel mailing list; if you want to send us a patch, please do so in our bug tracker. You can also find us in our chat room. .Sh WWW https://www.gajim.org/ .Sh XMPP You are welcome to join us at gajim@conference.gajim.org .Sh MAILING LIST Below are public mailing lists on lists.gajim.org .Bd -literal -offset indent https://lists.gajim.org/cgi-bin/listinfo/gajim-devel https://lists.gajim.org/cgi-bin/listinfo/translators .Ed .Pp More mailing lists at .Bd -literal -offset indent https://lists.gajim.org/cgi-bin/listinfo .Ed .Sh BUGS Please submit bugs at https://dev.gajim.org/gajim/gajim/issues .Sh SEE ALSO .Xr gajim 1 .Xr gajim-remote 1 gajim-gajim-1.1.3/data/gajim-remote.1000066400000000000000000000103131345766322700172600ustar00rootroot00000000000000.Dd January 21, 2018 .Dt GAJIM-REMOTE 1 URM .Os UNIX .Sh NAME .Nm gajim-remote .Nd a remote control utility for .Xr gajim 1 .Sh SYNOPSIS .Nm .Ar command .Sh DESCRIPTION .Nm is a script to control and communicate with a running instance of .Xr gajim 1 by D-Bus. .Sh OPTIONS .Bl -tag -width Ds .It Available commands .El .Ss account_info Aq account Gets detailed info on a account .Ss change_avatar Ao picture Ac Bq account Change the avatar .Ss change_status Bo status Bc Bo message Bc Bq account Changes the status of account or accounts .Ss check_gajim_running Check if Gajim is running .Ss contact_info Aq jid Gets detailed info on a contact .Ss get_status Bq account Returns current status (the global one unless account is specified) .Ss get_status_message Bq account Returns current status message (the global one unless account is specified) .Ss get_unread_msgs_number Returns number of unread messages .Ss help Bq command Shows a help on specific command .Ss list_accounts Prints a list of registered accounts .Ss list_contacts Bq account Prints a list of all contacts in the roster. Each contact appears on a separate line .Ss prefs_del Aq key Deletes a preference item .Ss prefs_list Lists all preferences and their values .Ss prefs_put Aq key=value Sets value of 'key' to 'value'. .Ss prefs_store Writes the current state of Gajim preferences to the .config file .Ss remove_contact Ao jid Ac Bq account Removes contact from roster .Ss send_chat_message Ao jid Ac Ao message Ac Bo PGP key Bc Bq account Sends new chat message to a contact in the roster. Both OpenPGP key and account are optional. If you want to set only 'account', without 'OpenPGP key', just set 'OpenPGP key' to ''. .Ss send_file Ao file Ac Ao jid Ac Bq account Sends file to a contact .Ss send_groupchat_message Ao room_jid Ac Ao message Ac Bq account Sends new message to a groupchat you've joined. .Ss send_single_message Ao jid subject Ac Ao message Ac Bo PGP key Bc Bq account Sends new single message to a contact in the roster. Both OpenPGP key and account are optional. If you want to set only 'account', without 'OpenPGP key', just set 'OpenPGP key' to ''. .Ss send_xml Ao xml Ac Bq account Sends custom XML .Ss set_priority Ao priority Ac Bq account Changes the priority of account or accounts .Ss show_next_pending_event Pops up a window with the next pending event .Ss toggle_ipython Shows or hides the ipython window .Ss toggle_roster_appearance Shows or hides the roster window .Sh EXAMPLES Open a URI of group chat gajim .Pp .Dl $ gajim-remote handle_uri xmpp:gajim@conference.gajim.org?join .Pp Send custom XML .Pp .Dl $ gajim-remote send_xml $(cat Pa filename.xml ) Qq your@jabber.id .Sh AUTHORS .An -nosplit .Nm is written and maintained by .An Yann Leboulanger , and .An Denis Fomin , with contributions and patches merged from many individuals around the world. See files .Pa AUTHORS and .Pa THANKS , for a complete list. .Sh COPYRIGHT Copyright (C) 2003-2019 Gajim Team .Pp .Nm is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 only. .Pp .Nm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. .Pp You should have received a copy of the GNU General Public License along with .Nm . If not, see . .Sh FEEDBACK You can report bugs or feature requests in our bug tracker at .Em https://dev.gajim.org/gajim/gajim/issues or in the .Em gajim-devel mailing list; if you want to send us a patch, please do so in our bug tracker. You can also find us in our chat room. .Sh WWW https://www.gajim.org/ .Sh XMPP You are welcome to join us at gajim@conference.gajim.org .Sh MAILING LIST Below are public mailing lists on lists.gajim.org .Bd -literal -offset indent https://lists.gajim.org/cgi-bin/listinfo/gajim-devel https://lists.gajim.org/cgi-bin/listinfo/translators .Ed .Pp More mailing lists at .Bd -literal -offset indent https://lists.gajim.org/cgi-bin/listinfo .Ed .Sh BUGS Please submit bugs at https://dev.gajim.org/gajim/gajim/issues .Sh SEE ALSO .Xr gajim 1 .Xr gajim-history-manager 1 gajim-gajim-1.1.3/data/gajim.1000066400000000000000000000074571345766322700160060ustar00rootroot00000000000000.Dd January 21, 2018 .Dt GAJIM 1 URM .Os UNIX .Sh NAME .Nm gajim .Nd a Jabber/XMPP client .Sh SYNOPSIS .Nm .Fl h .Nm .Op Fl q .Op Fl v .Op Fl w .Op Fl l Ar subsystem=level .Op Fl p Ar name .Op Fl s .Op Fl c Ar directory .Sh DESCRIPTION .Nm is a Jabber/XMPP client written in Python and GTK+. .Nm works nicely with GNOME, yet it does not require it to run. .Nm is designed for novice and advanced users as one, as well for XMPP server admins. .Pp XMPP is the Extensible Messaging and Presence Protocol, a set of open technologies for instant messaging, presence, multi-party chat, voice and video calls, collaboration, lightweight middleware, content syndication, and generalized routing of XML data. For more information on the XMPP protocol see . .Sh OPTIONS .Bl -tag -width Ds .It Fl h Fl Fl help Show help options .It Fl q Fl Fl quiet Show only critical errors .It Fl s Fl Fl separate Separate profiles completely (even history db and plugins) .It Fl v Fl Fl verbose Print xml stanzas and other debug information .It Fl w Fl Fl warnings Show all GTK warnings with traceback .It Fl l Fl Fl loglevel Em subsystem=level Bq , Em subsystem=level Bq Em ... Configure logging system. Subsystem can be .Em gajim.interface , .Em gajim.c.connection , .Em .nbxmpp.client_nb , etc. Level can be .Em DEBUG , .Em INFO , .Em WARNING , .Em ERROR or .Em CRITICAL . .It Fl p Fl Fl profile Em name Run .Nm using .Pa config.name in configuration directory .It Fl c Fl Fl config-path Em directory Where to look for configuration files .El .Sh FILES .Bl -tag -width Ds .It $XDG_CACHE_HOME/gajim/cache.db Cache database file of transports, caps, roster entry, and roster group. .It $XDG_CACHE_HOME/gajim/avatars/ Cache directory of avatars. .It $XDG_CACHE_HOME/gajim/vcards/ Cache directory of vCards (virtual cards). .It $XDG_CONFIG_HOME/gajim/ The config-path used when .Op Fl c is not specified. .It $XDG_DATA_HOME/gajim/certs/ Directory where certificates are stored. .It $XDG_DATA_HOME/gajim/logs.db The history database log file. For more information on database logs see . .El .Sh AUTHORS .An -nosplit .Nm is written and maintained by .An Yann Leboulanger and .An Philipp Hörist , with contributions and patches merged from many individuals around the world. See the About Dialog for a complete list. .Sh COPYRIGHT Copyright (C) 2003-2019 Gajim Team .Pp .Nm is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 only. .Pp .Nm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. .Pp You should have received a copy of the GNU General Public License along with .Nm . If not, see . .Sh FEEDBACK You can report bugs or feature requests in our bug tracker at .Em https://dev.gajim.org/gajim/gajim/issues or in the .Em gajim-devel mailing list; if you want to send us a patch, please do so in our bug tracker. You can also find us in our chat room. .Sh WWW https://www.gajim.org/ .Sh XMPP You are welcome to join us at gajim@conference.gajim.org .Sh MAILING LIST Below are public mailing lists on lists.gajim.org .Bd -literal -offset indent https://lists.gajim.org/cgi-bin/listinfo/gajim-devel https://lists.gajim.org/cgi-bin/listinfo/translators .Ed .Pp More mailing lists at .Bd -literal -offset indent https://lists.gajim.org/cgi-bin/listinfo .Ed .Sh BUGS Please submit bugs at .Bd -literal -offset indent https://dev.gajim.org/gajim/gajim/issues https://dev.gajim.org/gajim/gajim-plugins https://dev.gajim.org/gajim/python-nbxmpp .Ed .Sh SEE ALSO .Xr gajim-remote 1 .Xr gajim-history-manager 1 gajim-gajim-1.1.3/data/org.gajim.Gajim.appdata.xml.in000066400000000000000000000126141345766322700222670ustar00rootroot00000000000000 org.gajim.Gajim.desktop gajim.desktop CC-BY-SA-3.0 GPL-3.0 Gajim A GTK+ XMPP client

Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim you can chat through various XMPP services of your choice (e.g. Jabber.org) as well as transports (e.g. Facebook, IRC).

Just chat with your friends or family, easily share pictures and thoughts or discuss the news with your groups.

Gajim integrates well with your other devices: just chat and see what's been said on your mobile device.

Features:

  • Never miss a message, keep all your chat clients synchronized
  • Invite friends to group chats or join one
  • Easily send pictures, videos or other files to friends and groups
  • Chat securely with End-to-End encryption via OMEMO or PGP
  • Use your favorite emoticons, set your own profile picture
  • Keep and manage all your chat history
  • Organize your chats with tabs
  • Automatic spell-checking for your messages
  • Connect to other Messengers via Transports (Facebook, IRC, ...)
  • Lookup things on Wikipedia, dictionaries or other search engines directly from the chat window
  • Set your activity, tune, and mood to show your friends how you are feeling
  • Support for multiple accounts
  • Group multiple contacts from one friend to a single Meta-Contact
  • XML console to see what's happening on the protocol layer
  • Serverless messaging (Bonjour/Zeroconf), BOSH
  • Support for service discovery including nodes and search for users
  • Even more features via plugins
GNOME GTK InstantMessaging Network https://gajim.org/imgs/gajim_single_window_mode.png Roster, list of contacts https://gajim.org/imgs/gajim_tabbed_chat.png Tabbed chat window https://gajim.org/imgs/groupchat_window.png Group chat support https://gajim.org/imgs/history_window.png Chat history https://gajim.org/imgs/gajim_plugins.png Plugin manager org.gajim.Gajim.desktop Gajim Team gajim-devel_AT_gajim.org https://gajim.org/ https://dev.gajim.org/gajim/gajim https://dev.gajim.org/gajim/gajim/wikis/help/gajimfaq https://dev.gajim.org/gajim/gajim/wikis/help/Help https://gajim.org/dev.php#donate https://dev.gajim.org/gajim/gajim/wikis/development/DevTranslate gajim none none none none none none none none none none none none none intense none intense none none none none
gajim-gajim-1.1.3/data/org.gajim.Gajim.desktop.in000066400000000000000000000014441345766322700215260ustar00rootroot00000000000000[Desktop Entry] Categories=Network;InstantMessaging;GTK;GNOME; Name=Gajim GenericName=Jabber IM Client Comment=A GTK+ Jabber client #Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! Keywords=chat;messaging;im;xmpp;bonjour;voip; Exec=gajim %u #Translators: Do NOT translate or transliterate this text (this is an icon file name)! Icon=org.gajim.Gajim StartupNotify=true StartupWMClass=Gajim Terminal=false Type=Application MimeType=x-scheme-handler/xmpp; Actions=StartChat;ShowNextPendingEvent; [Desktop Action StartChat] Exec=gajim --start-chat Name=Start a new chat Icon=org.gajim.Gajim [Desktop Action ShowNextPendingEvent] Exec=gajim --show-next-pending-event Name=Show next pending event Icon=org.gajim.Gajim gajim-gajim-1.1.3/flatpak/000077500000000000000000000000001345766322700153315ustar00rootroot00000000000000gajim-gajim-1.1.3/flatpak/README.md000066400000000000000000000035111345766322700166100ustar00rootroot00000000000000# Install Gajim via Flatpak **Prerequisites:** You need to have `flatpak` and `flatpak-builder` installed. For this example, we use `git` for downloading/updating Gajim's sources. ### Download Gajim's sources In this example, we do a `git clone` of the repository, so you need to have `git` installed. Alternatively, you can also download the sources from our Gitlab via webbrowser. `git clone https://dev.gajim.org/gajim/gajim.git ~/Gajim` `cd ~/Gajim` *Note: Source tarballs and snapshots do _not_ include 'org.gajim.Gajim.json', which is necessary for installation via Flatpak.* ### Install Gajim and dependencies Replace install path `~/Gajim/gajim_flatpak` with an install path of your choice. *Note: Remove `--user` if you want a system-wide installation.* 1. `flatpak --user remote-add --from gnome https://sdk.gnome.org/gnome.flatpakrepo` 2. `flatpak --user install gnome org.gnome.Platform//3.30` 3. `flatpak --user install gnome org.gnome.Sdk//3.30` 4. `flatpak-builder --repo=gajim_flatpak_repo ~/Gajim/gajim_flatpak ~/Gajim/flatpak/org.gajim.Gajim.yaml` 5. `flatpak --user remote-add --no-gpg-verify gajim_flatpak_repo gajim_flatpak_repo` 6. `flatpak --user install gajim_flatpak_repo org.gajim.Gajim` 7. `flatpak run org.gajim.Gajim` Thats it, you are now running Gajim via Flatpak! ## How to update ### Update Gajim's sources In this example, we use `git` to update the repository. You can also download the sources from our Gitlab via webbrowser. `cd ~/Gajim` `git pull --rebase` ### Remove previous Flatpak directory `rm -r ~/Gajim/gajim_flatpak` ### Install and update Gajim 1. `flatpak-builder --repo=gajim_flatpak_repo ~/Gajim/gajim_flatpak ~/Gajim/flatpak/org.gajim.Gajim.yaml` 2. `flatpak --user update` 3. `flatpak run org.gajim.Gajim` Gajim is now updated. gajim-gajim-1.1.3/flatpak/org.gajim.Gajim.yaml000066400000000000000000000160201345766322700211170ustar00rootroot00000000000000app-id: org.gajim.Gajim runtime: org.gnome.Platform runtime-version: 3.30 sdk: org.gnome.Sdk command: gajim finish-args: - --share=ipc - --share=network - --socket=fallback-x11 - --socket=wayland - --socket=pulseaudio - --system-talk-name=org.freedesktop.GeoClue2 - --system-talk-name=org.freedesktop.login1 - --talk-name=org.gnome.ScreenSaver - --talk-name=org.mpris.MediaPlayer2.* # Keyring - --talk-name=org.freedesktop.secrets # dconf - --filesystem=xdg-run/dconf - --filesystem=~/.config/dconf:ro - --talk-name=ca.desrt.dconf - --env=DCONF_USER_CONFIG_DIR=.config/dconf # GnuPG - --filesystem=~/.gnupg # extensions - --env=PYTHONPATH=/app/plugins/lib/python3.7/site-packages add-extensions: org.gajim.Gajim.Plugin: directory: plugins merge-dirs: lib/python3.7/site-packages subdirectories: true no-autodownload: true autodelete: true cleanup: - '/bin/easy*' - /include - /lib/debug - /lib/pkgconfig - /lib/python2.7 - /share/aclocal - /share/doc - /share/gtk-doc - /share/man - '*.a' - '*.la' modules: - name: python3-pycparser buildsystem: simple build-commands: - pip3 install --prefix=/app . sources: - type: archive url: https://files.pythonhosted.org/packages/68/9e/49196946aee219aead1290e00d1e7fdeab8567783e83e1b9ab5585e6206a/pycparser-2.19.tar.gz sha256: a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3 - name: python3-cffi buildsystem: simple build-commands: - pip3 install --prefix=/app . sources: - type: archive url: https://files.pythonhosted.org/packages/64/7c/27367b38e6cc3e1f49f193deb761fe75cda9f95da37b67b422e62281fcac/cffi-1.12.2.tar.gz sha256: e113878a446c6228669144ae8a56e268c91b7f1fafae927adc4879d9849e0ea7 - name: python3-asn1crypto buildsystem: simple build-commands: - pip3 install --prefix=/app asn1crypto-0.24.0-py2.py3-none-any.whl sources: - type: file url: https://pypi.python.org/packages/ea/cd/35485615f45f30a510576f1a56d1e0a7ad7bd8ab5ed7cdc600ef7cd06222/asn1crypto-0.24.0-py2.py3-none-any.whl sha256: 2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87 - name: python3-idna buildsystem: simple build-commands: - pip3 install --prefix=/app idna-2.8-py2.py3-none-any.whl sources: - type: file url: https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl sha256: ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c - name: python3-cryptography buildsystem: simple build-commands: - pip3 install --prefix=/app . sources: - type: archive url: https://files.pythonhosted.org/packages/07/ca/bc827c5e55918ad223d59d299fff92f3563476c3b00d0a9157d9c0217449/cryptography-2.6.1.tar.gz sha256: 26c821cbeb683facb966045e2064303029d572a87ee69ca5a1bf54bf55f93ca6 - name: python3-pyopenssl buildsystem: simple build-commands: - pip3 install --prefix=/app pyOpenSSL-19.0.0-py2.py3-none-any.whl sources: - type: file url: https://files.pythonhosted.org/packages/01/c8/ceb170d81bd3941cbeb9940fc6cc2ef2ca4288d0ca8929ea4db5905d904d/pyOpenSSL-19.0.0-py2.py3-none-any.whl sha256: c727930ad54b10fc157015014b666f2d8b41f70c0d03e83ab67624fd3dd5d1e6 - name: python3-dbus-python build-options: env: PYTHON_VERSION: '3' sources: - type: archive url: https://files.pythonhosted.org/packages/3f/e7/4edb582d1ffd5ac3c84188deea32e960b5c8c0fe1da56ce70224f85ce542/dbus-python-1.2.8.tar.gz sha256: abf12bbb765e300bf8e2a1b2f32f85949eab06998dbda127952c31cb63957b6f - name: python3-jeepney buildsystem: simple build-commands: - pip3 install --prefix=/app jeepney-0.4-py3-none-any.whl sources: - type: file url: https://files.pythonhosted.org/packages/2b/f7/ff23b9b59534f501d47c327576aadda59da5b83d76ff837e6075bc325b9f/jeepney-0.4-py3-none-any.whl sha256: f6f8b1428403b4afad04b6b82f9ab9fc426c253d7504c9031c41712a2c01dc74 - name: python3-secretstorage buildsystem: simple build-commands: - pip3 install --prefix=/app SecretStorage-3.1.1-py3-none-any.whl sources: - type: file url: https://files.pythonhosted.org/packages/82/59/cb226752e20d83598d7fdcabd7819570b0329a61db07cfbdd21b2ef546e3/SecretStorage-3.1.1-py3-none-any.whl sha256: 7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a - name: python3-entrypoints buildsystem: simple build-commands: - pip3 install --prefix=/app entrypoints-0.3-py2.py3-none-any.whl sources: - type: file url: https://files.pythonhosted.org/packages/ac/c6/44694103f8c221443ee6b0041f69e2740d89a25641e62fb4f2ee568f2f9c/entrypoints-0.3-py2.py3-none-any.whl sha256: 589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 - name: python3-keyring buildsystem: simple build-commands: - pip3 install --prefix=/app keyring-18.0.0-py2.py3-none-any.whl cleanup: - /bin sources: - type: file url: https://files.pythonhosted.org/packages/a1/28/0058032477bfdf2003e605d175629963759220661615443e20711446bfa7/keyring-18.0.0-py2.py3-none-any.whl sha256: ca33f5ccc542b9ffaa196ee9a33488069e5e7eac77d5b81969f8a3ce74d0230c - name: python3-cssutils buildsystem: simple build-commands: - pip3 install --prefix=/app cssutils-1.0.2-py3-none-any.whl cleanup: - /bin sources: - type: file url: https://files.pythonhosted.org/packages/6b/15/a9fb9010f58d1c55dd0b7779db2334feb9a572d407024f39a60f44293861/cssutils-1.0.2-py3-none-any.whl sha256: c74dbe19c92f5052774eadb15136263548dd013250f1ed1027988e7fef125c8d - name: python3-precis_i18n buildsystem: simple build-commands: - pip3 install --prefix=/app precis_i18n-1.0.0-py3-none-any.whl sources: - type: file url: https://files.pythonhosted.org/packages/08/9d/d32f1b7c6d280c82a786b629ba89bd9e3e8409b9e23a7309f76a78e46971/precis_i18n-1.0.0-py3-none-any.whl sha256: f6942bbffec698d0d7e30c42f589f3f6da13e723d047997d0761a41facf2986f - name: gspell cleanup: - /bin sources: - type: archive url: https://download.gnome.org/sources/gspell/1.8/gspell-1.8.1.tar.xz sha256: 819a1d23c7603000e73f5e738bdd284342e0cd345fb0c7650999c31ec741bbe5 - name: python3-nbxmpp buildsystem: simple build-commands: - pip3 install --prefix=/app . sources: - type: archive url: https://files.pythonhosted.org/packages/d6/01/34b2a441926780f26edd21490158afe0eb76beae4efbb6bc4d3323eae69a/nbxmpp-0.6.10.tar.gz sha256: cd73417777e4847fdd8d0d96c7cafc606952edbd2b9d52a2a72bb2aaa04d08ef - name: gajim buildsystem: simple build-commands: - pip3 install --prefix=/app . - touch /app/share/run-as-flatpak sources: - type: git url: https://dev.gajim.org/gajim/gajim.git branch: gajim_1.1 post-install: - install -d /app/plugins gajim-gajim-1.1.3/gajim/000077500000000000000000000000001345766322700147765ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/__init__.py000066400000000000000000000006451345766322700171140ustar00rootroot00000000000000import os import subprocess __version__ = "1.1.3" IS_FLATPAK = False if os.path.exists('/app/share/run-as-flatpak'): IS_FLATPAK = True try: p = subprocess.Popen('git rev-parse --short=12 HEAD', shell=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) node = p.communicate()[0] if node: __version__ += '+' + node.decode('utf-8').strip() except Exception: pass gajim-gajim-1.1.3/gajim/adhoc_commands.py000066400000000000000000000467731345766322700203300ustar00rootroot00000000000000# Copyright (C) 2006 Nikos Kouremenos # Copyright (C) 2006-2007 Tomasz Melcer # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2008 Jonathan Schleifer # Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # FIXME: think if we need caching command list. it may be wrong if there will # be entities that often change the list, it may be slow to fetch it every time from gi.repository import Gtk import nbxmpp from gajim.common import app from gajim.common.i18n import _ from gajim.common.modules import dataforms from gajim.common import ged from gajim import gtkgui_helpers from gajim import dataforms_widget from gajim.gtk.dialogs import HigDialog class CommandWindow: """ Class for a window for single ad-hoc commands session Note, that there might be more than one for one account/jid pair in one moment. TODO: Maybe put this window into MessageWindow? consider this when it will be possible to manage more than one window of one. TODO: Account/jid pair in MessageWindowMgr. TODO: GTK 2.10 has a special wizard-widget, consider using it... """ def __init__(self, account, jid, commandnode=None): """ Create new window """ # an account object self._con = app.connections[account] self.jid = jid self.commandnode = commandnode self.data_form_widget = None self.stage_finish_cb = None self.stage_back_button_cb = None self.stage_forward_button_cb = None self.stage_execute_button_cb = None self.stage_finish_button_cb = None self.stage_close_button_cb = None self.stage_restart_button_cb = None self.stage_window_delete_cb = None # retrieving widgets from xml self.xml = gtkgui_helpers.get_gtk_builder('adhoc_commands_window.ui') self.window = self.xml.get_object('adhoc_commands_window') self.window.connect('delete-event', self.on_adhoc_commands_window_delete_event) for name in ('restart_button', 'back_button', 'forward_button', 'execute_button', 'finish_button', 'close_button', 'stages_notebook', 'retrieving_commands_stage_vbox', 'retrieving_commands_spinner', 'command_list_stage_vbox', 'command_treeview', 'sending_form_stage_vbox', 'sending_form_spinner', 'notes_label', 'no_commands_stage_vbox', 'error_stage_vbox', 'error_description_label'): setattr(self, name, self.xml.get_object(name)) self.command_store = Gtk.ListStore(str, str) self.command_treeview.set_model(self.command_store) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("Command", renderer, text=0) self.command_treeview.append_column(column) app.ged.register_event_handler( 'adhoc-command-error', ged.CORE, self._on_command_error) app.ged.register_event_handler( 'adhoc-command-list', ged.CORE, self._on_command_list) app.ged.register_event_handler('adhoc-command-action-response', ged.CORE, self._on_action_response) self.initiate() def initiate(self): self.commandlist = None # a list of (commandname, commanddescription) # command's data self.sessionid = None self.dataform = None self.allow_stage3_close = False # creating data forms widget if self.data_form_widget: self.sending_form_stage_vbox.remove(self.data_form_widget) self.data_form_widget.destroy() self.data_form_widget = dataforms_widget.DataFormWidget() self.data_form_widget.show() self.sending_form_stage_vbox.pack_start(self.data_form_widget, True, True, 0) if self.commandnode: # Execute command self.stage3() else: # setting initial stage self.stage1() # displaying the window self.window.set_title(_('Ad-hoc Commands - Gajim')) self.xml.connect_signals(self) self.window.show_all() self.restart_button.set_sensitive(False) # These functions are set up by appropriate stageX methods. def stage_finish(self, *anything): if self.stage_finish_cb: self.stage_finish_cb(*anything) # Widget callbacks... def on_back_button_clicked(self, *anything): if self.stage_back_button_cb: return self.stage_back_button_cb(*anything) return False def on_forward_button_clicked(self, *anything): if self.stage_forward_button_cb: return self.stage_forward_button_cb(*anything) return False def on_execute_button_clicked(self, *anything): if self.stage_execute_button_cb: return self.stage_execute_button_cb(*anything) return False def on_finish_button_clicked(self, *anything): if self.stage_finish_button_cb: return self.stage_finish_button_cb(*anything) return False def on_close_button_clicked(self, *anything): if self.stage_close_button_cb: return self.stage_close_button_cb(*anything) return False def on_restart_button_clicked(self, *anything): if self.stage_restart_button_cb: return self.stage_restart_button_cb(*anything) return False def on_adhoc_commands_window_destroy(self, *anything): app.ged.remove_event_handler( 'adhoc-command-error', ged.CORE, self._on_command_error) app.ged.remove_event_handler( 'adhoc-command-list', ged.CORE, self._on_command_list) app.ged.remove_event_handler('adhoc-command-action-response', ged.CORE, self._on_action_response) def on_adhoc_commands_window_delete_event(self, *anything): if self.stage_window_delete_cb: return self.stage_window_delete_cb(self.window) return False def __del__(self): print('Object has been deleted.') # stage 1: waiting for command list def stage1(self): """ Prepare the first stage. Request command list, set appropriate state of widgets """ # close old stage... self.stage_finish() # show the stage self.stages_notebook.set_current_page( self.stages_notebook.page_num( self.retrieving_commands_stage_vbox)) # set widgets' state self.close_button.set_sensitive(True) self.back_button.set_sensitive(False) self.forward_button.set_sensitive(False) self.execute_button.set_sensitive(False) self.finish_button.set_sensitive(False) # request command list self._con.get_module('AdHocCommands').request_command_list(self.jid) self.retrieving_commands_spinner.start() # setup the callbacks self.stage_finish_cb = self.stage1_finish self.stage_close_button_cb = self.stage1_close_button_clicked self.stage_restart_button_cb = self.stage1_restart_button_clicked self.stage_window_delete_cb = \ self.stage1_adhoc_commands_window_delete_event def stage1_finish(self): self.retrieving_commands_spinner.stop() def stage1_close_button_clicked(self, widget): # cancelling in this stage is not critical, so we don't # show any popups to user self.stage_finish() self.window.destroy() def stage1_restart_button_clicked(self, widget): self.stage_finish() self.restart() def stage1_adhoc_commands_window_delete_event(self, widget): self.stage1_finish() return True # stage 2: choosing the command to execute def stage2(self): """ Populate the command list """ # close old stage self.stage_finish() assert self.commandlist self.stages_notebook.set_current_page( self.stages_notebook.page_num(self.command_list_stage_vbox)) self.close_button.set_sensitive(True) self.back_button.set_sensitive(False) self.forward_button.set_sensitive(True) self.execute_button.set_sensitive(False) self.finish_button.set_sensitive(False) # build the commands list self.command_store.clear() for (commandnode, commandname) in self.commandlist: self.command_store.append([commandname, commandnode]) self.command_treeview.get_selection().select_iter(self.command_store.get_iter_first()) self.stage_finish_cb = self.stage2_finish self.stage_close_button_cb = self.stage2_close_button_clicked self.stage_restart_button_cb = self.stage2_restart_button_clicked self.stage_forward_button_cb = self.stage2_forward_button_clicked self.stage_window_delete_cb = None def stage2_finish(self): """ Save selected command to self.commandnode """ model, treeiter = self.command_treeview.get_selection().get_selected() self.commandnode = model[treeiter][1] def stage2_close_button_clicked(self, widget): self.stage_finish() self.window.destroy() def stage2_restart_button_clicked(self, widget): self.stage_finish() self.restart() def stage2_forward_button_clicked(self, widget): self.stage3() def on_check_commands_1_button_clicked(self, widget): self.stage1() # stage 3: command invocation def stage3(self): # close old stage self.stage_finish() self.form_status = None self.stages_notebook.set_current_page( self.stages_notebook.page_num( self.sending_form_stage_vbox)) self.restart_button.set_sensitive(True) self.close_button.set_sensitive(True) self.back_button.set_sensitive(False) self.forward_button.set_sensitive(False) self.execute_button.set_sensitive(False) self.finish_button.set_sensitive(False) self.stage3_submit_form() self.stage_finish_cb = None self.stage_back_button_cb = self.stage3_back_button_clicked self.stage_forward_button_cb = self.stage3_forward_button_clicked self.stage_execute_button_cb = self.stage3_execute_button_clicked self.stage_finish_button_cb = self.stage3_finish_button_clicked self.stage_close_button_cb = self.stage3_close_button_clicked self.stage_restart_button_cb = self.stage3_restart_button_clicked self.stage_window_delete_cb = self.stage3_close_button_clicked def stage3_can_close(self, cb): if self.form_status == 'completed': cb() return def on_yes(button): self._con.get_module('AdHocCommands').send_cancel( self.jid, self.commandnode, self.sessionid) dialog.destroy() cb() dialog = HigDialog(self.window, Gtk.MessageType.WARNING, Gtk.ButtonsType.YES_NO, _('Cancel confirmation'), _('You are in process of executing command. Do you really want to ' 'cancel it?'), on_response_yes=on_yes) dialog.popup() def stage3_close_button_clicked(self, widget): """ We are in the middle of executing command. Ask user if he really want to cancel the process, then cancel it """ # this works also as a handler for window_delete_event, so we have to # return appropriate values if self.allow_stage3_close: return False def on_ok(): self.allow_stage3_close = True self.window.destroy() self.stage3_can_close(on_ok) return True # Block event, don't close window def stage3_restart_button_clicked(self, widget): def on_ok(): self.restart() self.stage3_can_close(on_ok) def stage3_back_button_clicked(self, widget): self.stage3_submit_form('prev') def stage3_forward_button_clicked(self, widget): self.stage3_submit_form('next') def stage3_execute_button_clicked(self, widget): self.stage3_submit_form('execute') def stage3_finish_button_clicked(self, widget): self.stage3_submit_form('complete') def stage3_submit_form(self, action='execute'): self.data_form_widget.set_sensitive(False) if self.data_form_widget.get_data_form(): df = self.data_form_widget.get_data_form() if not df.is_valid(): app.interface.raise_dialog( 'invalid-form', transient_for=self.window) self.data_form_widget.set_sensitive(True) return self.data_form_widget.data_form.type_ = 'submit' else: self.data_form_widget.hide() self.close_button.set_sensitive(True) self.back_button.set_sensitive(False) self.forward_button.set_sensitive(False) self.execute_button.set_sensitive(False) self.finish_button.set_sensitive(False) self.sending_form_spinner.start() self._con.get_module('AdHocCommands').send_command( self.jid, self.commandnode, self.sessionid, self.data_form_widget.data_form, action) def stage3_next_form(self, command): if not isinstance(command, nbxmpp.Node): self.stage5(error=_('Service sent malformed data'), senderror=True) return self.sending_form_spinner.stop() if not self.sessionid: self.sessionid = command.getAttr('sessionid') elif self.sessionid != command.getAttr('sessionid'): self.stage5(error=_('Service changed the session identifier.'), senderror=True) return self.form_status = command.getAttr('status') self.commandnode = command.getAttr('node') if command.getTag('x'): self.dataform = dataforms.extend_form(node=command.getTag('x')) self.data_form_widget.set_sensitive(True) try: self.data_form_widget.selectable = True self.data_form_widget.data_form = self.dataform except dataforms.Error: self.stage5(error=_('Service sent malformed data'), senderror=True) return self.data_form_widget.show() if self.data_form_widget.title: self.window.set_title(_('%s - Ad-hoc Commands - Gajim') % \ self.data_form_widget.title) else: self.data_form_widget.hide() actions = command.getTag('actions') if actions: # actions, actions, actions... self.close_button.set_sensitive(True) self.back_button.set_sensitive(actions.getTag('prev') is not None) self.forward_button.set_sensitive( actions.getTag('next') is not None) self.execute_button.set_sensitive(True) self.finish_button.set_sensitive(actions.getTag('complete') is not \ None) else: self.close_button.set_sensitive(True) self.back_button.set_sensitive(False) self.forward_button.set_sensitive(False) self.execute_button.set_sensitive(True) self.finish_button.set_sensitive(False) if self.form_status == 'completed': self.close_button.set_sensitive(True) self.back_button.hide() self.forward_button.hide() self.execute_button.hide() self.finish_button.hide() self.close_button.show() self.stage_window_delete_cb = self.stage3_close_button_clicked note = command.getTag('note') if note: self.notes_label.set_text(note.getData()) self.notes_label.set_no_show_all(False) self.notes_label.show() else: self.notes_label.set_no_show_all(True) self.notes_label.hide() def restart(self): self.commandnode = None self.initiate() # stage 4: no commands are exposed def stage4(self): """ Display the message. Wait for user to close the window """ # close old stage self.stage_finish() self.stages_notebook.set_current_page( self.stages_notebook.page_num(self.no_commands_stage_vbox)) self.close_button.set_sensitive(True) self.back_button.set_sensitive(False) self.forward_button.set_sensitive(False) self.execute_button.set_sensitive(False) self.finish_button.set_sensitive(False) self.stage_finish_cb = None self.stage_close_button_cb = self.stage4_close_button_clicked self.stage_restart_button_cb = self.stage4_restart_button_clicked self.stage_window_delete_cb = None def stage4_close_button_clicked(self, widget): self.window.destroy() def stage4_restart_button_clicked(self, widget): self.restart() def on_check_commands_2_button_clicked(self, widget): self.stage1() # stage 5: an error has occurred def stage5(self, error=None, errorid=None, senderror=False): """ Display the error message. Wait for user to close the window """ # FIXME: sending error to responder # close old stage self.stage_finish() assert errorid or error if errorid: # we've got error code, display appropriate message try: errorname = nbxmpp.NS_STANZAS + ' ' + str(errorid) errordesc = nbxmpp.ERRORS[errorname][2] error = errordesc del errorname, errordesc except KeyError: # when stanza doesn't have error description error = _('Service returned an error.') elif error: # we've got error message pass else: # we don't know what's that, bailing out assert False self.stages_notebook.set_current_page( self.stages_notebook.page_num(self.error_stage_vbox)) self.close_button.set_sensitive(True) self.back_button.hide() self.forward_button.hide() self.execute_button.hide() self.finish_button.hide() self.error_description_label.set_text(error) self.stage_finish_cb = None self.stage_close_button_cb = self.stage5_close_button_clicked self.stage_restart_button_cb = self.stage5_restart_button_clicked self.stage_window_delete_cb = None def stage5_close_button_clicked(self, widget): self.window.destroy() def stage5_restart_button_clicked(self, widget): self.restart() def _on_command_error(self, obj): self.stage5(errorid=obj.error) def _on_command_list(self, obj): self.commandlist = obj.commandlist if not self.commandlist: self.stage4() else: self.stage2() def _on_action_response(self, obj): self.stage3_next_form(obj.command) gajim-gajim-1.1.3/gajim/app_actions.py000066400000000000000000000245631345766322700176620ustar00rootroot00000000000000# Copyright (C) 2017 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gtk from gi.repository import Gdk from gajim.common import app from gajim.common import helpers from gajim.common.app import interface from gajim.common.exceptions import GajimGeneralException from gajim import config from gajim import dialogs from gajim import disco import gajim.plugins.gui from gajim.gtk.dialogs import ShortcutsWindow from gajim.gtk.history_sync import HistorySyncAssistant from gajim.gtk.server_info import ServerInfoDialog from gajim.gtk.mam_preferences import MamPreferences from gajim.gtk.preferences import Preferences from gajim.gtk.join_groupchat import JoinGroupchatWindow from gajim.gtk.start_chat import StartChatDialog from gajim.gtk.add_contact import AddNewContactWindow from gajim.gtk.single_message import SingleMessageWindow from gajim.gtk.xml_console import XMLConsoleWindow from gajim.gtk.about import AboutDialog from gajim.gtk.privacy_list import PrivacyListsWindow from gajim.gtk.bookmarks import ManageBookmarksWindow from gajim.gtk.features import FeaturesDialog from gajim.gtk.account_wizard import AccountCreationWizard from gajim.gtk.history import HistoryWindow from gajim.gtk.accounts import AccountsWindow # General Actions def on_add_contact_jid(action, param): AddNewContactWindow(None, param.get_string()) # Application Menu Actions def on_preferences(action, param): window = app.get_app_window(Preferences) if window is None: Preferences() else: window.present() def on_plugins(action, param): if 'plugins' in interface.instances: interface.instances['plugins'].window.present() else: interface.instances['plugins'] = gajim.plugins.gui.PluginsWindow() def on_accounts(action, param): window = app.get_app_window(AccountsWindow) if window is None: AccountsWindow() else: window.present() def on_history_manager(action, param): from gajim.history_manager import HistoryManager HistoryManager() def on_manage_bookmarks(action, param): ManageBookmarksWindow() def on_quit(action, param): interface.roster.on_quit_request() def on_new_chat(action, param): if 'start_chat' in app.interface.instances: app.interface.instances['start_chat'].present() else: app.interface.instances['start_chat'] = StartChatDialog() # Accounts Actions def on_profile(action, param): interface.edit_own_details(param.get_string()) def on_activate_bookmark(action, param): dict_ = param.unpack() account, jid, nick, password = \ dict_['account'], dict_['jid'], None, None if 'nick' in dict_: nick = dict_['nick'] if 'password' in dict_: password = dict_['password'] interface.join_gc_room(account, jid, nick, password) def on_send_server_message(action, param): account = param.get_string() server = app.config.get_per('accounts', account, 'hostname') server += '/announce/online' SingleMessageWindow(account, server, 'send') def on_service_disco(action, param): account = param.get_string() server_jid = app.config.get_per('accounts', account, 'hostname') if server_jid in interface.instances[account]['disco']: interface.instances[account]['disco'][server_jid].\ window.present() else: try: # Object will add itself to the window dict disco.ServiceDiscoveryWindow(account, address_entry=True) except GajimGeneralException: pass def on_join_gc(_action, param): account, jid = None, None if param is None: if not app.get_connected_accounts(): return else: account, jid = param.get_strv() if not jid: jid = None window = app.get_app_window(JoinGroupchatWindow) if window is None: JoinGroupchatWindow(account, jid) else: window.present() def on_add_contact(_action, param): account, jid = param.get_strv() if not jid: jid = None window = app.get_app_window(AddNewContactWindow, account) if window is None: AddNewContactWindow(account, jid) else: window.present() def on_single_message(action, param): SingleMessageWindow(param.get_string(), action='send') def on_merge_accounts(action, param): action.set_state(param) value = param.get_boolean() app.config.set('mergeaccounts', value) # Do not merge accounts if only one active if len(app.connections) >= 2: app.interface.roster.regroup = value else: app.interface.roster.regroup = False app.interface.roster.setup_and_draw_roster() def on_use_pgp_agent(action, param): action.set_state(param) app.config.set('use_gpg_agent', param.get_boolean()) def on_add_account(action, param): if 'account_creation_wizard' in app.interface.instances: app.interface.instances['account_creation_wizard'].window.present() else: app.interface.instances['account_creation_wizard'] = \ AccountCreationWizard() def on_import_contacts(action, param): account = param.get_string() if 'import_contacts' in app.interface.instances: app.interface.instances['import_contacts'].dialog.present() else: app.interface.instances['import_contacts'] = \ dialogs.SynchroniseSelectAccountDialog(account) # Advanced Actions def on_mam_preferences(action, param): account = param.get_string() window = app.get_app_window(MamPreferences, account) if window is None: MamPreferences(account) else: window.present() def on_history_sync(action, param): account = param.get_string() if 'history_sync' in interface.instances[account]: interface.instances[account]['history_sync'].present() else: interface.instances[account]['history_sync'] = \ HistorySyncAssistant(account, interface.roster.window) def on_privacy_lists(action, param): account = param.get_string() if 'privacy_lists' in interface.instances[account]: interface.instances[account]['privacy_lists'].window.present() else: interface.instances[account]['privacy_lists'] = \ PrivacyListsWindow(account) def on_server_info(action, param): account = param.get_string() if 'server_info' in interface.instances[account]: interface.instances[account]['server_info'].present() else: interface.instances[account]['server_info'] = \ ServerInfoDialog(account) def on_xml_console(action, param): account = param.get_string() if 'xml_console' in interface.instances[account]: interface.instances[account]['xml_console'].present() else: interface.instances[account]['xml_console'] = \ XMLConsoleWindow(account) def on_manage_proxies(action, param): if 'manage_proxies' in app.interface.instances: app.interface.instances['manage_proxies'].window.present() else: app.interface.instances['manage_proxies'] = \ config.ManageProxiesWindow(interface.roster.window) # Admin Actions def on_set_motd(action, param): account = param.get_string() server = app.config.get_per('accounts', account, 'hostname') server += '/announce/motd' SingleMessageWindow(account, server, 'send') def on_update_motd(action, param): account = param.get_string() server = app.config.get_per('accounts', account, 'hostname') server += '/announce/motd/update' SingleMessageWindow(account, server, 'send') def on_delete_motd(action, param): account = param.get_string() server = app.config.get_per('accounts', account, 'hostname') server += '/announce/motd/delete' app.connections[account].send_motd(server) # Help Actions def on_contents(action, param): helpers.launch_browser_mailer( 'url', 'https://dev.gajim.org/gajim/gajim/wikis') def on_faq(action, param): helpers.launch_browser_mailer( 'url', 'https://dev.gajim.org/gajim/gajim/wikis/help/gajimfaq') def on_keyboard_shortcuts(action, param): ShortcutsWindow() def on_features(action, param): FeaturesDialog() def on_about(action, param): AboutDialog() # View Actions def on_file_transfers(action, param): if interface.instances['file_transfers']. \ window.get_property('visible'): interface.instances['file_transfers'].window.present() else: interface.instances['file_transfers'].window.show_all() def on_history(action, param): if 'logs' in interface.instances: interface.instances['logs'].window.present() else: interface.instances['logs'] = HistoryWindow() def on_open_event(action, param): dict_ = param.unpack() app.interface.handle_event( dict_['account'], dict_['jid'], dict_['type_']) # Other Actions def toggle_ipython(action, param): """ Show/hide the ipython window """ win = app.ipython_window if win and win.window.is_visible(): win.present() else: app.interface.create_ipython_window() def show_next_pending_event(action, param): """ Show the window(s) with next pending event in tabbed/group chats """ if app.events.get_nb_events(): account, jid, event = app.events.get_first_systray_event() if not event: return app.interface.handle_event(account, jid, event.type_) def open_link(_action, param): kind, link = param.get_strv() helpers.launch_browser_mailer(kind, link) def copy_link(_action, param): text = param.get_string() clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clip.set_text(text, -1) def start_chat(_action, param): account, jid = param.get_strv() app.interface.new_chat_from_jid(account, jid) def join_groupchat(_action, param): account, jid = param.get_strv() room_jid = jid.split('?')[0] app.interface.join_gc_minimal(account, room_jid) gajim-gajim-1.1.3/gajim/application.py000066400000000000000000000437131345766322700176630ustar00rootroot00000000000000# Copyright (C) 2003-2017 Yann Leboulanger # Copyright (C) 2004-2005 Vincent Hanquez # Copyright (C) 2005 Alex Podaras # Norman Rasmussen # Stéphan Kochen # Copyright (C) 2005-2006 Dimitur Kirov # Alex Mauer # Copyright (C) 2005-2007 Travis Shirk # Nikos Kouremenos # Copyright (C) 2006 Junglecow J # Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # James Newton # Copyright (C) 2007-2008 Brendan Taylor # Julien Pivotto # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # Copyright (C) 2016-2017 Emmanuel Gil Peyrot # Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import sys from datetime import datetime from pathlib import Path from urllib.parse import unquote from gi.repository import GLib, Gio, Gtk import gajim from gajim.common import app from gajim.common import configpaths from gajim.common import logging_helpers from gajim.common import exceptions from gajim.common import caps_cache from gajim.common import logger from gajim.common.i18n import _ class GajimApplication(Gtk.Application): '''Main class handling activation and command line.''' def __init__(self): flags = (Gio.ApplicationFlags.HANDLES_COMMAND_LINE | Gio.ApplicationFlags.HANDLES_OPEN) Gtk.Application.__init__(self, application_id='org.gajim.Gajim', flags=flags) self.add_main_option( 'version', ord('V'), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Show the application\'s version')) self.add_main_option( 'quiet', ord('q'), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Show only critical errors')) self.add_main_option( 'separate', ord('s'), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Separate profile files completely ' '(even history database and plugins)')) self.add_main_option( 'verbose', ord('v'), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Print XML stanzas and other debug information')) self.add_main_option( 'profile', ord('p'), GLib.OptionFlags.NONE, GLib.OptionArg.STRING, _('Use defined profile in configuration directory'), 'NAME') self.add_main_option( 'config-path', ord('c'), GLib.OptionFlags.NONE, GLib.OptionArg.STRING, _('Set configuration directory'), 'PATH') self.add_main_option( 'loglevel', ord('l'), GLib.OptionFlags.NONE, GLib.OptionArg.STRING, _('Configure logging system'), 'LEVEL') self.add_main_option( 'warnings', ord('w'), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Show all warnings')) self.add_main_option( 'ipython', ord('i'), GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Open IPython shell')) self.add_main_option( 'show-next-pending-event', 0, GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Pops up a window with the next pending event')) self.add_main_option( 'start-chat', 0, GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Start a new chat')) self.add_main_option( 'simulate-network-lost', 0, GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Simulate loss of connectivity')) self.add_main_option( 'simulate-network-connected', 0, GLib.OptionFlags.NONE, GLib.OptionArg.NONE, _('Simulate regaining connectivity')) self.add_main_option_entries(self._get_remaining_entry()) self.connect('handle-local-options', self._handle_local_options) self.connect('command-line', self._handle_remote_options) self.connect('startup', self._startup) self.connect('activate', self._activate) self.interface = None GLib.set_prgname('gajim') if GLib.get_application_name() != 'Gajim': GLib.set_application_name('Gajim') @staticmethod def _get_remaining_entry(): option = GLib.OptionEntry() option.arg = GLib.OptionArg.STRING_ARRAY option.arg_data = None option.arg_description = ('[URI …]') option.flags = GLib.OptionFlags.NONE option.long_name = GLib.OPTION_REMAINING option.short_name = 0 return [option] def _startup(self, application): # Create and initialize Application Paths & Databases app.detect_dependencies() configpaths.create_paths() try: app.logger = logger.Logger() caps_cache.initialize(app.logger) except exceptions.DatabaseMalformed as error: dlg = Gtk.MessageDialog( None, Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _('Database Error')) dlg.format_secondary_text(str(error)) dlg.run() dlg.destroy() sys.exit() # Set Application Menu app.app = self from gajim.gtk.util import get_builder builder = get_builder('application_menu.ui') menubar = builder.get_object("menubar") appmenu = builder.get_object("appmenu") if app.prefers_app_menu(): self.set_app_menu(appmenu) else: # Add it to the menubar instead menubar.prepend_submenu('Gajim', appmenu) self.set_menubar(menubar) def _activate(self, application): if self.interface is not None: self.interface.roster.window.present() return from gajim.gui_interface import Interface self.interface = Interface() self.interface.run(self) self.add_actions() from gajim import gui_menu_builder gui_menu_builder.build_accounts_menu() def _open_uris(self, uris): for uri in uris: app.log('uri_handler').info('open %s', uri) if not uri.startswith('xmpp:'): continue # remove xmpp: uri = uri[5:] try: jid, cmd = uri.split('?') except ValueError: # No query argument jid, cmd = uri, 'message' if cmd == 'join': self.interface.join_gc_minimal(None, jid) elif cmd == 'roster': self.activate_action('add-contact', GLib.Variant('s', jid)) elif cmd.startswith('message'): attributes = cmd.split(';') message = None for key in attributes: if not key.startswith('body'): continue try: message = unquote(key.split('=')[1]) except Exception: app.log('uri_handler').error('Invalid URI: %s', cmd) accounts = list(app.connections.keys()) if not accounts: continue if len(accounts) == 1: app.interface.new_chat_from_jid(accounts[0], jid, message) else: self.activate_action('start-chat') start_chat_window = app.interface.instances['start_chat'] start_chat_window.search_entry.set_text(jid) def do_shutdown(self, *args): Gtk.Application.do_shutdown(self) # Shutdown GUI and save config if hasattr(self.interface, 'roster') and self.interface.roster: self.interface.roster.prepare_quit() # Commit any outstanding SQL transactions app.logger.commit() def _handle_remote_options(self, application, command_line): # Parse all options that should be executed on a remote instance options = command_line.get_options_dict() remote_commands = [ 'ipython', 'show-next-pending-event', 'start-chat', ] remaining = options.lookup_value(GLib.OPTION_REMAINING, GLib.VariantType.new('as')) for cmd in remote_commands: if options.contains(cmd): self.activate_action(cmd) return 0 if options.contains('simulate-network-lost'): app.interface.network_status_changed(None, False) return 0 if options.contains('simulate-network-connected'): app.interface.network_status_changed(None, True) return 0 if remaining is not None: self._open_uris(remaining.unpack()) return 0 self.activate() return 0 def _handle_local_options(self, application: Gtk.Application, options: GLib.VariantDict) -> int: # Parse all options that have to be executed before ::startup if options.contains('version'): print(gajim.__version__) return 0 if options.contains('profile'): # Incorporate profile name into application id # to have a single app instance for each profile. profile = options.lookup_value('profile').get_string() app_id = '%s.%s' % (self.get_application_id(), profile) self.set_application_id(app_id) configpaths.set_profile(profile) if options.contains('separate'): configpaths.set_separation(True) if options.contains('config-path'): path = options.lookup_value('config-path').get_string() configpaths.set_config_root(path) configpaths.init() if app.get_win_debug_mode(): # Redirect has to happen before logging init self._redirect_output() logging_helpers.init() logging_helpers.set_verbose() else: logging_helpers.init() if options.contains('quiet'): logging_helpers.set_quiet() if options.contains('verbose'): logging_helpers.set_verbose() if options.contains('loglevel'): loglevel = options.lookup_value('loglevel').get_string() logging_helpers.set_loglevels(loglevel) if options.contains('warnings'): self.show_warnings() return -1 def show_warnings(self): import traceback import warnings def warn_with_traceback(message, category, filename, lineno, file=None, line=None): traceback.print_stack(file=sys.stderr) sys.stderr.write(warnings.formatwarning(message, category, filename, lineno, line)) warnings.showwarning = warn_with_traceback warnings.filterwarnings(action="always") @staticmethod def _redirect_output(): debug_folder = Path(configpaths.get('DEBUG')) date = datetime.today().strftime('%Y-%m-%d') filename = '%s-debug.log' % date fd = open(debug_folder / filename, 'a') sys.stderr = sys.stdout = fd def add_actions(self): ''' Build Application Actions ''' from gajim import app_actions # General Stateful Actions act = Gio.SimpleAction.new_stateful( 'merge', None, GLib.Variant.new_boolean(app.config.get('mergeaccounts'))) act.connect('change-state', app_actions.on_merge_accounts) self.add_action(act) act = Gio.SimpleAction.new_stateful( 'agent', None, GLib.Variant.new_boolean(app.config.get('use_gpg_agent'))) act.connect('change-state', app_actions.on_use_pgp_agent) self.add_action(act) # General Actions general_actions = [ ('quit', app_actions.on_quit), ('accounts', app_actions.on_accounts), ('add-account', app_actions.on_add_account), ('join-groupchat', app_actions.on_join_gc), ('manage-proxies', app_actions.on_manage_proxies), ('start-chat', app_actions.on_new_chat), ('bookmarks', app_actions.on_manage_bookmarks), ('history-manager', app_actions.on_history_manager), ('preferences', app_actions.on_preferences), ('plugins', app_actions.on_plugins), ('file-transfer', app_actions.on_file_transfers), ('history', app_actions.on_history), ('shortcuts', app_actions.on_keyboard_shortcuts), ('features', app_actions.on_features), ('content', app_actions.on_contents), ('about', app_actions.on_about), ('faq', app_actions.on_faq), ('ipython', app_actions.toggle_ipython), ('show-next-pending-event', app_actions.show_next_pending_event), ] act = Gio.SimpleAction.new('add-contact', GLib.VariantType.new('s')) act.connect("activate", app_actions.on_add_contact_jid) self.add_action(act) act = Gio.SimpleAction.new('copy-link', GLib.VariantType.new('s')) act.connect("activate", app_actions.copy_link) self.add_action(act) act = Gio.SimpleAction.new('open-link', GLib.VariantType.new('as')) act.connect("activate", app_actions.open_link) self.add_action(act) for action in general_actions: action_name, func = action act = Gio.SimpleAction.new(action_name, None) act.connect("activate", func) self.add_action(act) accounts_list = sorted(app.config.get_per('accounts')) if not accounts_list: return if len(accounts_list) > 1: for acc in accounts_list: self.add_account_actions(acc) else: self.add_account_actions(accounts_list[0]) def _get_account_actions(self, account): from gajim import app_actions as a if account == 'Local': return [ ('-xml-console', a.on_xml_console, 'always', 's') ] return [ ('-start-single-chat', a.on_single_message, 'online', 's'), ('-start-chat', a.start_chat, 'online', 'as'), ('-join-groupchat', a.on_join_gc, 'online', 'as'), ('-add-contact', a.on_add_contact, 'online', 'as'), ('-services', a.on_service_disco, 'online', 's'), ('-profile', a.on_profile, 'feature', 's'), ('-xml-console', a.on_xml_console, 'always', 's'), ('-server-info', a.on_server_info, 'online', 's'), ('-archive', a.on_mam_preferences, 'feature', 's'), ('-sync-history', a.on_history_sync, 'online', 's'), ('-privacylists', a.on_privacy_lists, 'feature', 's'), ('-send-server-message', a.on_send_server_message, 'online', 's'), ('-set-motd', a.on_set_motd, 'online', 's'), ('-update-motd', a.on_update_motd, 'online', 's'), ('-delete-motd', a.on_delete_motd, 'online', 's'), ('-activate-bookmark', a.on_activate_bookmark, 'online', 'a{sv}'), ('-open-event', a.on_open_event, 'always', 'a{sv}'), ('-import-contacts', a.on_import_contacts, 'online', 's'), ] def add_account_actions(self, account): for action in self._get_account_actions(account): action_name, func, state, type_ = action action_name = account + action_name if self.lookup_action(action_name): # We already added this action continue act = Gio.SimpleAction.new( action_name, GLib.VariantType.new(type_)) act.connect("activate", func) if state != 'always': act.set_enabled(False) self.add_action(act) def remove_account_actions(self, account): for action in self._get_account_actions(account): action_name = account + action[0] self.remove_action(action_name) def set_account_actions_state(self, account, new_state=False): for action in self._get_account_actions(account): action_name, _, state, _ = action if not new_state and state in ('online', 'feature'): # We go offline self.lookup_action(account + action_name).set_enabled(False) elif new_state and state == 'online': # We go online self.lookup_action(account + action_name).set_enabled(True) gajim-gajim-1.1.3/gajim/atom_window.py000066400000000000000000000122301345766322700176750ustar00rootroot00000000000000# Copyright (C) 2006 Tomasz Melcer # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Nikos Kouremenos # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import List # pylint: disable=unused-import from typing import Any # pylint: disable=unused-import from gi.repository import Gdk from gi.repository import GLib from gajim.common import helpers from gajim.common import i18n from gajim.common.i18n import _ from gajim import gtkgui_helpers class AtomWindow: window = None entries = [] # type: List[Any] @classmethod def newAtomEntry(cls, entry): """ Queue new entry, open window if there's no one opened """ cls.entries.append(entry) if cls.window is None: cls.window = AtomWindow() else: cls.window.updateCounter() @classmethod def windowClosed(cls): cls.window = None def __init__(self): """ Create new window... only if we have anything to show """ assert self.__class__.entries self.entry = None # the entry actually displayed self.xml = gtkgui_helpers.get_gtk_builder('atom_entry_window.ui') self.window = self.xml.get_object('atom_entry_window') for name in ('new_entry_label', 'feed_title_label', 'feed_title_eventbox', 'feed_tagline_label', 'entry_title_label', 'entry_title_eventbox', 'last_modified_label', 'close_button', 'next_button'): self.__dict__[name] = self.xml.get_object(name) self.displayNextEntry() self.xml.connect_signals(self) self.window.show_all() self.entry_title_eventbox.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.feed_title_eventbox.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) def displayNextEntry(self): """ Get next entry from the queue and display it in the window """ assert self.__class__.entries newentry = self.__class__.entries.pop(0) # fill the fields if newentry.feed_link is not None: self.feed_title_label.set_markup( '%s' % \ GLib.markup_escape_text(newentry.feed_title)) else: self.feed_title_label.set_markup(GLib.markup_escape_text( newentry.feed_title)) self.feed_tagline_label.set_markup( '%s' % GLib.markup_escape_text( newentry.feed_tagline)) if newentry.title: if newentry.uri is not None: self.entry_title_label.set_markup( '%s' % \ GLib.markup_escape_text(newentry.title)) else: self.entry_title_label.set_markup(GLib.markup_escape_text( newentry.title)) else: self.entry_title_label.set_markup('') self.last_modified_label.set_text(newentry.updated) # update the counters self.updateCounter() self.entry = newentry def updateCounter(self): """ Display number of events on the top of window, sometimes it needs to be changed """ count = len(self.__class__.entries) if count: self.new_entry_label.set_text(i18n.ngettext( 'You have received new entries (and %d not displayed):', 'You have received new entries (and %d not displayed):', count, count, count)) self.next_button.set_sensitive(True) else: self.new_entry_label.set_text(_('You have received new entry:')) self.next_button.set_sensitive(False) def on_close_button_clicked(self, widget): self.window.destroy() self.windowClosed() def on_next_button_clicked(self, widget): self.displayNextEntry() def on_entry_title_eventbox_button_press_event(self, widget, event): #FIXME: make it using special gtk2.10 widget if event.button == 1: # left click uri = self.entry.uri if uri is not None: helpers.launch_browser_mailer('url', uri) return True def on_feed_title_eventbox_button_press_event(self, widget, event): #FIXME: make it using special gtk2.10 widget if event.button == 1: # left click uri = self.entry.feed_uri if uri is not None: helpers.launch_browser_mailer('url', uri) return True gajim-gajim-1.1.3/gajim/cell_renderer_image.py000066400000000000000000000134751345766322700213310ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Vincent Hanquez # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2006 Travis Shirk # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import GLib from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject class CellRendererImage(Gtk.CellRendererPixbuf): __gproperties__ = { 'image': (GObject.TYPE_OBJECT, 'Image', 'Image', GObject.ParamFlags.READWRITE), } def __init__(self, col_index, tv_index): super(CellRendererImage, self).__init__() self.image = None self.col_index = col_index self.tv_index = tv_index self.iters = {} def do_set_property(self, pspec, value): setattr(self, pspec.name, value) def do_get_property(self, pspec): return getattr(self, pspec.name) def do_activate(self, *args, **kwargs): """Renderers cannot be activated; always return True.""" return True def do_editing_started(self, *args, **kwargs): """Renderers cannot be edited; always return None.""" return None def func(self, model, path, iter_, image_tree): image, tree = image_tree if model.get_value(iter_, self.tv_index) != image: return self.redraw = 1 col = tree.get_column(self.col_index) cell_area = tree.get_cell_area(path, col) tree.queue_draw_area(cell_area.x, cell_area.y, cell_area.width, cell_area.height) def animation_timeout(self, tree, image): if image.get_storage_type() != Gtk.ImageType.ANIMATION: return self.redraw = 0 iter_ = self.iters[image] timeval = GLib.TimeVal() timeval.tv_sec = GLib.get_monotonic_time() / 1000000 iter_.advance(timeval) model = tree.get_model() if model: model.foreach(self.func, (image, tree)) if self.redraw: GLib.timeout_add(iter_.get_delay_time(), self.animation_timeout, tree, image) elif image in self.iters: del self.iters[image] def do_render(self, ctx, widget, background_area, cell_area, flags): if not self.image: return if self.image.get_storage_type() == Gtk.ImageType.ANIMATION: if self.image not in self.iters: if not isinstance(widget, Gtk.TreeView): return animation = self.image.get_animation() timeval = GLib.TimeVal() timeval.tv_sec = GLib.get_monotonic_time() / 1000000 iter_ = animation.get_iter(timeval) self.iters[self.image] = iter_ GLib.timeout_add(iter_.get_delay_time(), self.animation_timeout, widget, self.image) pix = self.iters[self.image].get_pixbuf() elif self.image.get_storage_type() == Gtk.ImageType.PIXBUF: pix = self.image.get_pixbuf() else: return calc_width = self.get_property('xpad') * 2 + pix.get_width() calc_height = self.get_property('ypad') * 2 + pix.get_height() x_pos = cell_area.x + self.get_property('xalign') * \ (cell_area.width - calc_width - self.get_property('xpad')) y_pos = cell_area.y + self.get_property('yalign') * \ (cell_area.height - calc_height - self.get_property('ypad')) Gdk.cairo_set_source_pixbuf(ctx, pix, x_pos, y_pos) ctx.paint() def do_get_preferred_height(self, widget): """ Return the height we need for this cell. Each cell is drawn individually and is only as wide as it needs to be, we let the TreeViewColumn take care of making them all line up. """ if not self.image: return 0, 0 if self.image.get_storage_type() == Gtk.ImageType.ANIMATION: animation = self.image.get_animation() timeval = GLib.TimeVal() timeval.tv_sec = GLib.get_monotonic_time() / 1000000 pix = animation.get_iter(timeval).get_pixbuf() elif self.image.get_storage_type() == Gtk.ImageType.PIXBUF: pix = self.image.get_pixbuf() else: return 0, 0, 0, 0 calc_height = self.get_property('ypad') * 2 + pix.get_height() return calc_height, calc_height def do_get_preferred_width(self, widget): """ Return the width we need for this cell. Each cell is drawn individually and is only as wide as it needs to be, we let the TreeViewColumn take care of making them all line up. """ if not self.image: return 0, 0 if self.image.get_storage_type() == Gtk.ImageType.ANIMATION: animation = self.image.get_animation() timeval = GLib.TimeVal() timeval.tv_sec = GLib.get_monotonic_time() / 1000000 pix = animation.get_iter(timeval).get_pixbuf() elif self.image.get_storage_type() == Gtk.ImageType.PIXBUF: pix = self.image.get_pixbuf() else: return 0, 0, 0, 0 calc_width = self.get_property('xpad') * 2 + pix.get_width() return calc_width, calc_width gajim-gajim-1.1.3/gajim/chat_control.py000066400000000000000000001757211345766322700200440ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2006-2008 Jean-Marie Traissard # Nikos Kouremenos # Travis Shirk # Copyright (C) 2007 Lukas Petrovicky # Julien Pivotto # Copyright (C) 2007-2008 Brendan Taylor # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import ClassVar # pylint: disable=unused-import from typing import Type # pylint: disable=unused-import import os import time from gi.repository import Gtk from gi.repository import Gio from gi.repository import Pango from gi.repository import GLib from nbxmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC from nbxmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO from nbxmpp.protocol import NS_JINGLE_ICE_UDP, NS_JINGLE_FILE_TRANSFER_5 from gajim.common import app from gajim.common import helpers from gajim.common import ged from gajim.common import i18n from gajim.common.i18n import _ from gajim.common.helpers import AdditionalDataDict from gajim.common.contacts import GC_Contact from gajim.common.const import AvatarSize from gajim.common.const import KindConstant from gajim.common.const import Chatstate from gajim import gtkgui_helpers from gajim import gui_menu_builder from gajim import message_control from gajim import dialogs from gajim.gtk.dialogs import ConfirmationDialog from gajim.gtk.add_contact import AddNewContactWindow from gajim.command_system.implementation.hosts import ChatCommands from gajim.command_system.framework import CommandHost # pylint: disable=unused-import from gajim.chat_control_base import ChatControlBase ################################################################################ class ChatControl(ChatControlBase): """ A control for standard 1-1 chat """ ( JINGLE_STATE_NULL, JINGLE_STATE_CONNECTING, JINGLE_STATE_CONNECTION_RECEIVED, JINGLE_STATE_CONNECTED, JINGLE_STATE_ERROR ) = range(5) TYPE_ID = message_control.TYPE_CHAT old_msg_kind = None # last kind of the printed message # Set a command host to bound to. Every command given through a chat will be # processed with this command host. COMMAND_HOST = ChatCommands # type: ClassVar[Type[CommandHost]] def __init__(self, parent_win, contact, acct, session, resource=None): ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'chat_control', contact, acct, resource) self.last_recv_message_id = None self.last_recv_message_marks = None self.last_message_timestamp = None self._formattings_button = self.xml.get_object('formattings_button') self.emoticons_button = self.xml.get_object('emoticons_button') self.toggle_emoticons() self.widget_set_visible(self.xml.get_object('banner_eventbox'), app.config.get('hide_chat_banner')) self.authentication_button = self.xml.get_object( 'authentication_button') id_ = self.authentication_button.connect('clicked', self._on_authentication_button_clicked) self.handlers[id_] = self.authentication_button self.sendfile_button = self.xml.get_object('sendfile_button') self.sendfile_button.set_action_name('win.send-file-' + \ self.control_id) # Add lock image to show chat encryption self.lock_image = self.xml.get_object('lock_image') # Menu for the HeaderBar self.control_menu = gui_menu_builder.get_singlechat_menu( self.control_id) settings_menu = self.xml.get_object('settings_menu') settings_menu.set_menu_model(self.control_menu) self._audio_banner_image = self.xml.get_object('audio_banner_image') self._video_banner_image = self.xml.get_object('video_banner_image') self.audio_sid = None self.audio_state = self.JINGLE_STATE_NULL self.audio_available = False self.video_sid = None self.video_state = self.JINGLE_STATE_NULL self.video_available = False self.update_toolbar() self._pep_images = {} self._pep_images['mood'] = self.xml.get_object('mood_image') self._pep_images['activity'] = self.xml.get_object('activity_image') self._pep_images['tune'] = self.xml.get_object('tune_image') self._pep_images['geoloc'] = self.xml.get_object('location_image') self.update_all_pep_types() self.show_avatar() # Hook up signals widget = self.xml.get_object('avatar_eventbox') widget.set_property('height-request', AvatarSize.CHAT) id_ = widget.connect('button-press-event', self.on_avatar_eventbox_button_press_event) self.handlers[id_] = widget widget = self.xml.get_object('location_eventbox') id_ = widget.connect('button-release-event', self.on_location_eventbox_button_release_event) self.handlers[id_] = widget id_ = widget.connect('enter-notify-event', self.on_location_eventbox_enter_notify_event) self.handlers[id_] = widget id_ = widget.connect('leave-notify-event', self.on_location_eventbox_leave_notify_event) self.handlers[id_] = widget for key in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'): widget = self.xml.get_object(key + '_button') id_ = widget.connect('pressed', self.on_num_button_pressed, key) self.handlers[id_] = widget id_ = widget.connect('released', self.on_num_button_released) self.handlers[id_] = widget self.dtmf_window = self.xml.get_object('dtmf_window') self.dtmf_window.get_child().set_direction(Gtk.TextDirection.LTR) id_ = self.dtmf_window.connect('focus-out-event', self.on_dtmf_window_focus_out_event) self.handlers[id_] = self.dtmf_window widget = self.xml.get_object('dtmf_button') id_ = widget.connect('clicked', self.on_dtmf_button_clicked) self.handlers[id_] = widget widget = self.xml.get_object('mic_hscale') id_ = widget.connect('value_changed', self.on_mic_hscale_value_changed) self.handlers[id_] = widget widget = self.xml.get_object('sound_hscale') id_ = widget.connect('value_changed', self.on_sound_hscale_value_changed) self.handlers[id_] = widget self.info_bar = Gtk.InfoBar() content_area = self.info_bar.get_content_area() self.info_bar_label = Gtk.Label() self.info_bar_label.set_use_markup(True) self.info_bar_label.set_halign(Gtk.Align.START) self.info_bar_label.set_valign(Gtk.Align.START) content_area.add(self.info_bar_label) self.info_bar.set_no_show_all(True) widget = self.xml.get_object('vbox2') widget.pack_start(self.info_bar, False, True, 5) widget.reorder_child(self.info_bar, 1) # List of waiting infobar messages self.info_bar_queue = [] self.subscribe_events() if not session: # Don't use previous session if we want to a specific resource # and it's not the same if not resource: resource = contact.resource session = app.connections[self.account].find_controlless_session( self.contact.jid, resource) self.setup_seclabel() if session: session.control = self self.session = session # Enable encryption if needed self.no_autonegotiation = False self.add_actions() self.update_ui() self.set_lock_image() self.encryption_menu = self.xml.get_object('encryption_menu') self.encryption_menu.set_menu_model( gui_menu_builder.get_encryption_menu( self.control_id, self.type_id, self.account == 'Local')) self.set_encryption_menu_icon() # restore previous conversation self.restore_conversation() self.msg_textview.grab_focus() app.ged.register_event_handler('pep-received', ged.GUI1, self._nec_pep_received) app.ged.register_event_handler('update-client-info', ged.GUI1, self._on_update_client_info) if self.TYPE_ID == message_control.TYPE_CHAT: # Dont connect this when PrivateChatControl is used app.ged.register_event_handler('update-roster-avatar', ged.GUI1, self._nec_update_avatar) app.ged.register_event_handler('chatstate-received', ged.GUI1, self._nec_chatstate_received) app.ged.register_event_handler('caps-update', ged.GUI1, self._nec_caps_received) app.ged.register_event_handler('message-sent', ged.OUT_POSTCORE, self._message_sent) app.ged.register_event_handler( 'mam-decrypted-message-received', ged.GUI1, self._nec_mam_decrypted_message_received) app.ged.register_event_handler( 'decrypted-message-received', ged.GUI1, self._nec_decrypted_message_received) app.ged.register_event_handler( 'receipt-received', ged.GUI1, self._receipt_received) # PluginSystem: adding GUI extension point for this ChatControl # instance object app.plugin_manager.gui_extension_point('chat_control', self) self.update_actions() def add_actions(self): super().add_actions() actions = [ ('invite-contacts-', self._on_invite_contacts), ('add-to-roster-', self._on_add_to_roster), ('information-', self._on_information), ] for action in actions: action_name, func = action act = Gio.SimpleAction.new(action_name + self.control_id, None) act.connect("activate", func) self.parent_win.window.add_action(act) self.audio_action = Gio.SimpleAction.new_stateful( 'toggle-audio-' + self.control_id, None, GLib.Variant.new_boolean(False)) self.audio_action.connect('change-state', self._on_audio) self.parent_win.window.add_action(self.audio_action) self.video_action = Gio.SimpleAction.new_stateful( 'toggle-video-' + self.control_id, None, GLib.Variant.new_boolean(False)) self.video_action.connect('change-state', self._on_video) self.parent_win.window.add_action(self.video_action) def update_actions(self): win = self.parent_win.window online = app.account_is_connected(self.account) con = app.connections[self.account] # Add to roster if not isinstance(self.contact, GC_Contact) \ and _('Not in Roster') in self.contact.groups and \ app.connections[self.account].roster_supported and online: win.lookup_action( 'add-to-roster-' + self.control_id).set_enabled(True) else: win.lookup_action( 'add-to-roster-' + self.control_id).set_enabled(False) # Audio win.lookup_action('toggle-audio-' + self.control_id).set_enabled( online and self.audio_available) # Video win.lookup_action('toggle-video-' + self.control_id).set_enabled( online and self.video_available) # Send file (HTTP File Upload) httpupload = win.lookup_action( 'send-file-httpupload-' + self.control_id) httpupload.set_enabled( online and con.get_module('HTTPUpload').available) # Send file (Jingle) jingle_conditions = ( (self.contact.supports(NS_FILE) or self.contact.supports(NS_JINGLE_FILE_TRANSFER_5)) and self.contact.show != 'offline') jingle = win.lookup_action('send-file-jingle-' + self.control_id) jingle.set_enabled(online and jingle_conditions) # Send file win.lookup_action( 'send-file-' + self.control_id).set_enabled( jingle.get_enabled() or httpupload.get_enabled()) # Set File Transfer Button tooltip if online and (httpupload.get_enabled() or jingle.get_enabled()): tooltip_text = _('Send File…') else: tooltip_text = _('No File Transfer available') self.sendfile_button.set_tooltip_text(tooltip_text) # Convert to GC if app.config.get_per('accounts', self.account, 'is_zeroconf'): win.lookup_action( 'invite-contacts-' + self.control_id).set_enabled(False) else: if self.contact.supports(NS_MUC) and online: win.lookup_action( 'invite-contacts-' + self.control_id).set_enabled(True) else: win.lookup_action( 'invite-contacts-' + self.control_id).set_enabled(False) # Information win.lookup_action( 'information-' + self.control_id).set_enabled(online) def _on_add_to_roster(self, action, param): AddNewContactWindow(self.account, self.contact.jid) def _on_information(self, action, param): app.interface.roster.on_info(None, self.contact, self.account) def _on_invite_contacts(self, action, param): """ User wants to invite some friends to chat """ dialogs.TransformChatToMUC(self.account, [self.contact.jid]) def _on_audio(self, action, param): action.set_state(param) state = param.get_boolean() self.on_jingle_button_toggled(state, 'audio') def _on_video(self, action, param): action.set_state(param) state = param.get_boolean() self.on_jingle_button_toggled(state, 'video') def subscribe_events(self): """ Register listeners to the events class """ app.events.event_added_subscribe(self.on_event_added) app.events.event_removed_subscribe(self.on_event_removed) def unsubscribe_events(self): """ Unregister listeners to the events class """ app.events.event_added_unsubscribe(self.on_event_added) app.events.event_removed_unsubscribe(self.on_event_removed) def _update_toolbar(self): # Formatting # TODO: find out what encryption allows for xhtml and which not if self.contact.supports(NS_XHTML_IM): self._formattings_button.set_sensitive(True) self._formattings_button.set_tooltip_text(_( 'Show a list of formattings')) else: self._formattings_button.set_sensitive(False) if self.contact.supports(NS_XHTML_IM): self._formattings_button.set_tooltip_text(_('Formatting is not ' 'available so long as GPG is active')) else: self._formattings_button.set_tooltip_text(_('This contact does ' 'not support HTML')) # Jingle detection if self.contact.supports(NS_JINGLE_ICE_UDP) and \ app.is_installed('FARSTREAM') and self.contact.resource: self.audio_available = self.contact.supports(NS_JINGLE_RTP_AUDIO) self.video_available = self.contact.supports(NS_JINGLE_RTP_VIDEO) else: if self.video_available or self.audio_available: self.stop_jingle() self.video_available = False self.audio_available = False def update_all_pep_types(self): for pep_type in self._pep_images: self.update_pep(pep_type) def update_pep(self, pep_type): if isinstance(self.contact, GC_Contact): return if pep_type not in self._pep_images: return pep = self.contact.pep img = self._pep_images[pep_type] if pep_type in pep: img.set_from_pixbuf(gtkgui_helpers.get_pep_as_pixbuf(pep[pep_type])) img.set_tooltip_markup(pep[pep_type].as_markup_text()) img.show() else: img.hide() def _nec_pep_received(self, obj): if obj.conn.name != self.account: return if obj.jid != self.contact.jid: return if obj.pep_type == 'nick': self.update_ui() self.parent_win.redraw_tab(self) self.parent_win.show_title() else: self.update_pep(obj.pep_type) def _on_update_client_info(self, event): if event.account != self.account: return if event.jid != self.contact.jid: return contact = app.contacts.get_contact( self.account, event.jid, event.resource) if contact is None: return self.xml.get_object('phone_image').set_visible(contact.uses_phone) def _update_jingle(self, jingle_type): if jingle_type not in ('audio', 'video'): return banner_image = getattr(self, '_' + jingle_type + '_banner_image') state = getattr(self, jingle_type + '_state') if state == self.JINGLE_STATE_NULL: banner_image.hide() else: banner_image.show() if state == self.JINGLE_STATE_CONNECTING: banner_image.set_from_icon_name( Gtk.STOCK_CONVERT, Gtk.IconSize.MENU) elif state == self.JINGLE_STATE_CONNECTION_RECEIVED: banner_image.set_from_icon_name( "network-workgroup", Gtk.IconSize.MENU) elif state == self.JINGLE_STATE_CONNECTED: banner_image.set_from_icon_name( Gtk.STOCK_CONNECT, Gtk.IconSize.MENU) elif state == self.JINGLE_STATE_ERROR: banner_image.set_from_icon_name( "dialog-warning", Gtk.IconSize.MENU) self.update_toolbar() def update_audio(self): self._update_jingle('audio') hbox = self.xml.get_object('audio_buttons_hbox') if self.audio_state == self.JINGLE_STATE_CONNECTED: # Set volume from config input_vol = app.config.get('audio_input_volume') output_vol = app.config.get('audio_output_volume') input_vol = max(min(input_vol, 100), 0) output_vol = max(min(output_vol, 100), 0) self.xml.get_object('mic_hscale').set_value(input_vol) self.xml.get_object('sound_hscale').set_value(output_vol) # Show vbox hbox.set_no_show_all(False) hbox.show_all() elif not self.audio_sid: hbox.set_no_show_all(True) hbox.hide() def update_video(self): self._update_jingle('video') def change_resource(self, resource): old_full_jid = self.get_full_jid() self.resource = resource new_full_jid = self.get_full_jid() # update app.last_message_time if old_full_jid in app.last_message_time[self.account]: app.last_message_time[self.account][new_full_jid] = \ app.last_message_time[self.account][old_full_jid] # update events app.events.change_jid(self.account, old_full_jid, new_full_jid) # update MessageWindow._controls self.parent_win.change_jid(self.account, old_full_jid, new_full_jid) def stop_jingle(self, sid=None, reason=None): if self.audio_sid and sid in (self.audio_sid, None): self.close_jingle_content('audio') if self.video_sid and sid in (self.video_sid, None): self.close_jingle_content('video') def _set_jingle_state(self, jingle_type, state, sid=None, reason=None): if jingle_type not in ('audio', 'video'): return if state in ('connecting', 'connected', 'stop', 'error') and reason: info = _('%(type)s state : %(state)s, reason: %(reason)s') % { 'type': jingle_type.capitalize(), 'state': state, 'reason': reason} self.print_conversation(info, 'info') states = {'connecting': self.JINGLE_STATE_CONNECTING, 'connection_received': self.JINGLE_STATE_CONNECTION_RECEIVED, 'connected': self.JINGLE_STATE_CONNECTED, 'stop': self.JINGLE_STATE_NULL, 'error': self.JINGLE_STATE_ERROR} jingle_state = states[state] if getattr(self, jingle_type + '_state') == jingle_state or state == 'error': return if state == 'stop' and getattr(self, jingle_type + '_sid') not in (None, sid): return setattr(self, jingle_type + '_state', jingle_state) if jingle_state == self.JINGLE_STATE_NULL: setattr(self, jingle_type + '_sid', None) if state in ('connection_received', 'connecting'): setattr(self, jingle_type + '_sid', sid) v = GLib.Variant.new_boolean(jingle_state != self.JINGLE_STATE_NULL) getattr(self, jingle_type + '_action').change_state(v) getattr(self, 'update_' + jingle_type)() def set_audio_state(self, state, sid=None, reason=None): self._set_jingle_state('audio', state, sid=sid, reason=reason) def set_video_state(self, state, sid=None, reason=None): self._set_jingle_state('video', state, sid=sid, reason=reason) def _get_audio_content(self): session = app.connections[self.account].get_jingle_session( self.contact.get_full_jid(), self.audio_sid) return session.get_content('audio') def on_num_button_pressed(self, widget, num): self._get_audio_content()._start_dtmf(num) def on_num_button_released(self, released): self._get_audio_content()._stop_dtmf() def on_dtmf_button_clicked(self, widget): self.dtmf_window.show_all() def on_dtmf_window_focus_out_event(self, widget, event): self.dtmf_window.hide() def on_mic_hscale_value_changed(self, widget, value): self._get_audio_content().set_mic_volume(value / 100) # Save volume to config app.config.set('audio_input_volume', value) def on_sound_hscale_value_changed(self, widget, value): self._get_audio_content().set_out_volume(value / 100) # Save volume to config app.config.set('audio_output_volume', value) def on_avatar_eventbox_button_press_event(self, widget, event): """ If right-clicked, show popup """ if event.button == 3: # right click menu = Gtk.Menu() menuitem = Gtk.MenuItem.new_with_mnemonic(_('Save _As')) if self.TYPE_ID == message_control.TYPE_CHAT: sha = app.contacts.get_avatar_sha( self.account, self.contact.jid) name = self.contact.get_shown_name() else: sha = self.gc_contact.avatar_sha name = self.gc_contact.get_shown_name() id_ = menuitem.connect('activate', gtkgui_helpers.on_avatar_save_as_menuitem_activate, sha, name) self.handlers[id_] = menuitem menu.append(menuitem) menu.show_all() menu.connect('selection-done', lambda w: w.destroy()) # show the menu menu.show_all() menu.attach_to_widget(widget, None) menu.popup(None, None, None, None, event.button, event.time) return True def on_location_eventbox_button_release_event(self, widget, event): if 'geoloc' in self.contact.pep: location = self.contact.pep['geoloc'].data if ('lat' in location) and ('lon' in location): uri = 'https://www.openstreetmap.org/?' + \ 'mlat=%(lat)s&mlon=%(lon)s&zoom=16' % {'lat': location['lat'], 'lon': location['lon']} helpers.launch_browser_mailer('url', uri) def on_location_eventbox_leave_notify_event(self, widget, event): """ Just moved the mouse so show the cursor """ cursor = gtkgui_helpers.get_cursor('LEFT_PTR') self.parent_win.window.get_window().set_cursor(cursor) def on_location_eventbox_enter_notify_event(self, widget, event): cursor = gtkgui_helpers.get_cursor('HAND2') self.parent_win.window.get_window().set_cursor(cursor) def update_ui(self): # The name banner is drawn here ChatControlBase.update_ui(self) self.update_toolbar() def _update_banner_state_image(self): contact = app.contacts.get_contact_with_highest_priority( self.account, self.contact.jid) if not contact or self.resource: # For transient contacts contact = self.contact show = contact.show # Set banner image icon = gtkgui_helpers.get_iconset_name_for(show) banner_status_img = self.xml.get_object('banner_status_image') banner_status_img.set_from_icon_name(icon, Gtk.IconSize.DND) def draw_banner_text(self): """ Draw the text in the fat line at the top of the window that houses the name, jid """ contact = self.contact jid = contact.jid banner_name_label = self.xml.get_object('banner_name_label') name = contact.get_shown_name() if self.resource: name += '/' + self.resource if self.TYPE_ID == message_control.TYPE_PM: name = i18n.direction_mark + _( '%(nickname)s from group chat %(room_name)s') % \ {'nickname': name, 'room_name': self.room_name} name = i18n.direction_mark + GLib.markup_escape_text(name) # We know our contacts nick, but if another contact has the same nick # in another account we need to also display the account. # except if we are talking to two different resources of the same contact acct_info = '' for account in app.contacts.get_accounts(): if account == self.account: continue if acct_info: # We already found a contact with same nick break for jid in app.contacts.get_jid_list(account): other_contact_ = \ app.contacts.get_first_contact_from_jid(account, jid) if other_contact_.get_shown_name() == \ self.contact.get_shown_name(): acct_info = i18n.direction_mark + ' (%s)' % \ GLib.markup_escape_text( app.get_account_label(self.account)) break status = contact.status if status is not None: banner_name_label.set_ellipsize(Pango.EllipsizeMode.END) self.banner_status_label.set_ellipsize(Pango.EllipsizeMode.END) status_reduced = helpers.reduce_chars_newlines(status, max_lines=1) else: status_reduced = '' status_escaped = GLib.markup_escape_text(status_reduced) st = app.config.get('displayed_chat_state_notifications') if self.TYPE_ID == 'pm': cs = self.gc_contact.chatstate else: cs = app.contacts.get_combined_chatstate( self.account, self.contact.jid) if cs and st in ('composing_only', 'all'): if contact.show == 'offline': chatstate = '' elif st == 'all' or cs == 'composing': chatstate = helpers.get_uf_chatstate(cs) else: chatstate = '' label_text = '%s%s %s' \ % (name, acct_info, chatstate) if acct_info: acct_info = i18n.direction_mark + ' ' + acct_info label_tooltip = '%s%s %s' % (name, acct_info, chatstate) else: label_text = '%s%s' % \ (name, acct_info) if acct_info: acct_info = i18n.direction_mark + ' ' + acct_info label_tooltip = '%s%s' % (name, acct_info) if status_escaped: status_text = self.urlfinder.sub(self.make_href, status_escaped) status_text = '%s' % status_text self.banner_status_label.set_tooltip_text(status) self.banner_status_label.set_no_show_all(False) self.banner_status_label.show() else: status_text = '' self.banner_status_label.hide() self.banner_status_label.set_no_show_all(True) self.banner_status_label.set_markup(status_text) # setup the label that holds name and jid banner_name_label.set_markup(label_text) banner_name_label.set_tooltip_text(label_tooltip) def close_jingle_content(self, jingle_type): sid = getattr(self, jingle_type + '_sid') if not sid: return setattr(self, jingle_type + '_sid', None) setattr(self, jingle_type + '_state', self.JINGLE_STATE_NULL) session = app.connections[self.account].get_jingle_session( self.contact.get_full_jid(), sid) if session: content = session.get_content(jingle_type) if content: session.remove_content(content.creator, content.name) v = GLib.Variant.new_boolean(False) getattr(self, jingle_type + '_action').change_state(v) getattr(self, 'update_' + jingle_type)() def on_jingle_button_toggled(self, state, jingle_type): if state: if getattr(self, jingle_type + '_state') == \ self.JINGLE_STATE_NULL: if jingle_type == 'video': video_hbox = self.xml.get_object('video_hbox') video_hbox.set_no_show_all(False) if app.config.get('video_see_self'): fixed = self.xml.get_object('outgoing_fixed') fixed.set_no_show_all(False) video_hbox.show_all() out_da = self.xml.get_object('outgoing_drawingarea') out_da.realize() if os.name == 'nt': out_xid = out_da.get_window().handle else: out_xid = out_da.get_window().get_xid() else: out_xid = None video_hbox.show_all() in_da = self.xml.get_object('incoming_drawingarea') in_da.realize() in_xid = in_da.get_window().get_xid() sid = app.connections[self.account].start_video( self.contact.get_full_jid(), in_xid, out_xid) else: sid = getattr(app.connections[self.account], 'start_' + jingle_type)(self.contact.get_full_jid()) getattr(self, 'set_' + jingle_type + '_state')('connecting', sid) else: video_hbox = self.xml.get_object('video_hbox') video_hbox.set_no_show_all(True) video_hbox.hide() fixed = self.xml.get_object('outgoing_fixed') fixed.set_no_show_all(True) self.close_jingle_content(jingle_type) def set_lock_image(self): encryption_state = {'visible': self.encryption is not None, 'enc_type': self.encryption, 'authenticated': False} if self.encryption: app.plugin_manager.extension_point( 'encryption_state' + self.encryption, self, encryption_state) self._show_lock_image(**encryption_state) def _show_lock_image(self, visible, enc_type='', authenticated=False): """ Set lock icon visibility and create tooltip """ if authenticated: authenticated_string = _('and authenticated') self.lock_image.set_from_icon_name( 'security-high', Gtk.IconSize.MENU) else: authenticated_string = _('and NOT authenticated') self.lock_image.set_from_icon_name( 'security-low', Gtk.IconSize.MENU) tooltip = _('%(type)s encryption is active %(authenticated)s.') % {'type': enc_type, 'authenticated': authenticated_string} self.authentication_button.set_tooltip_text(tooltip) self.widget_set_visible(self.authentication_button, not visible) self.lock_image.set_sensitive(visible) def _on_authentication_button_clicked(self, widget): if self.encryption: app.plugin_manager.extension_point( 'encryption_dialog' + self.encryption, self) def _nec_mam_decrypted_message_received(self, obj): if obj.conn.name != self.account: return if obj.muc_pm: if not obj.with_ == self.contact.get_full_jid(): return else: if not obj.with_.bareMatch(self.contact.jid): return kind = '' # incoming if obj.kind == KindConstant.CHAT_MSG_SENT: kind = 'outgoing' self.print_conversation( obj.msgtxt, kind, tim=obj.timestamp, encrypted=obj.encrypted, correct_id=obj.correct_id, msg_stanza_id=obj.message_id, additional_data=obj.additional_data) def _nec_decrypted_message_received(self, obj): if not obj.msgtxt: return True if obj.conn.name != self.account: return if obj.mtype != 'chat': return if obj.session.control != self: return typ = '' xep0184_id = None if obj.mtype == 'error': typ = 'error' if obj.forwarded and obj.sent: typ = 'out' if obj.jid != app.get_jid_from_account(obj.conn.name): xep0184_id = obj.id_ self.print_conversation(obj.msgtxt, typ, tim=obj.timestamp, encrypted=obj.encrypted, subject=obj.subject, xhtml=obj.xhtml, displaymarking=obj.displaymarking, msg_log_id=obj.msg_log_id, msg_stanza_id=obj.id_, correct_id=obj.correct_id, xep0184_id=xep0184_id, additional_data=obj.additional_data) if obj.msg_log_id: pw = self.parent_win end = self.conv_textview.autoscroll if not pw or (pw.get_active_control() and self \ == pw.get_active_control() and pw.is_active() and end): app.logger.set_read_messages([obj.msg_log_id]) def _message_sent(self, obj): if obj.conn.name != self.account: return if obj.jid != self.contact.jid: return if not obj.message: return self.last_sent_msg = obj.stanza_id id_ = obj.msg_iq.getID() xep0184_id = None if self.contact.jid != app.get_jid_from_account(self.account): if app.config.get_per('accounts', self.account, 'request_receipt'): xep0184_id = id_ if obj.label: displaymarking = obj.label.getTag('displaymarking') else: displaymarking = None if self.correcting: self.correcting = False gtkgui_helpers.remove_css_class( self.msg_textview, 'gajim-msg-correcting') self.print_conversation(obj.message, self.contact.jid, tim=obj.timestamp, encrypted=obj.encrypted, xep0184_id=xep0184_id, xhtml=obj.xhtml, displaymarking=displaymarking, msg_stanza_id=id_, correct_id=obj.correct_id, additional_data=obj.additional_data) def send_message(self, message, keyID='', xhtml=None, process_commands=True, attention=False): """ Send a message to contact """ if self.encryption: self.sendmessage = True app.plugin_manager.extension_point( 'send_message' + self.encryption, self) if not self.sendmessage: return message = helpers.remove_invalid_xml_chars(message) if message in ('', None, '\n'): return None contact = self.contact keyID = contact.keyID ChatControlBase.send_message(self, message, keyID, type_='chat', xhtml=xhtml, process_commands=process_commands, attention=attention) def get_our_nick(self): return app.nicks[self.account] def print_conversation(self, text, frm='', tim=None, encrypted=None, subject=None, xhtml=None, simple=False, xep0184_id=None, displaymarking=None, msg_log_id=None, correct_id=None, msg_stanza_id=None, additional_data=None): """ Print a line in the conversation If frm is set to status: it's a status message. if frm is set to error: it's an error message. The difference between status and error is mainly that with error, msg count as a new message (in systray and in control). If frm is set to info: it's a information message. If frm is set to print_queue: it is incoming from queue. If frm is set to another value: it's an outgoing message. If frm is not set: it's an incoming message. """ contact = self.contact if additional_data is None: additional_data = AdditionalDataDict() if frm == 'status': if not app.config.get('print_status_in_chats'): return kind = 'status' name = '' elif frm == 'error': kind = 'error' name = '' elif frm == 'info': kind = 'info' name = '' else: if not frm: kind = 'incoming' name = contact.get_shown_name() elif frm == 'print_queue': # incoming message, but do not update time kind = 'incoming_queue' name = contact.get_shown_name() else: kind = 'outgoing' name = self.get_our_nick() if not xhtml and not encrypted and \ app.config.get('rst_formatting_outgoing_messages'): from gajim.common.rst_xhtml_generator import create_xhtml xhtml = create_xhtml(text) if xhtml: xhtml = '%s' % (NS_XHTML, xhtml) ChatControlBase.print_conversation_line(self, text, kind, name, tim, subject=subject, old_kind=self.old_msg_kind, xhtml=xhtml, simple=simple, xep0184_id=xep0184_id, displaymarking=displaymarking, msg_log_id=msg_log_id, msg_stanza_id=msg_stanza_id, correct_id=correct_id, additional_data=additional_data, encrypted=encrypted) if text.startswith('/me ') or text.startswith('/me\n'): self.old_msg_kind = None else: self.old_msg_kind = kind def _receipt_received(self, event): if event.conn.name != self.account: return if event.jid != self.contact.jid: return self.conv_textview.show_xep0184_ack(event.receipt_id) def get_tab_label(self): unread = '' if self.resource: jid = self.contact.get_full_jid() else: jid = self.contact.jid num_unread = len(app.events.get_events(self.account, jid, ['printed_' + self.type_id, self.type_id])) if num_unread == 1 and not app.config.get('show_unread_tab_icon'): unread = '*' elif num_unread > 1: unread = '[' + str(num_unread) + ']' name = self.contact.get_shown_name() if self.resource: name += '/' + self.resource label_str = GLib.markup_escape_text(name) if num_unread: # if unread, text in the label becomes bold label_str = '' + unread + label_str + '' return label_str def get_tab_image(self, count_unread=True): if self.resource: jid = self.contact.get_full_jid() else: jid = self.contact.jid if app.config.get('show_avatar_in_tabs'): scale = self.parent_win.window.get_scale_factor() surface = app.contacts.get_avatar( self.account, jid, AvatarSize.TAB, scale) if surface is not None: return surface if count_unread: num_unread = len(app.events.get_events(self.account, jid, ['printed_' + self.type_id, self.type_id])) else: num_unread = 0 # Set tab image (always 16x16); unread messages show the 'event' image tab_img = None if num_unread and app.config.get('show_unread_tab_icon'): img_16 = app.interface.roster.get_appropriate_state_images( self.contact.jid, icon_name='event') tab_img = img_16['event'] else: contact = app.contacts.get_contact_with_highest_priority( self.account, self.contact.jid) if not contact or self.resource: # For transient contacts contact = self.contact img_16 = app.interface.roster.get_appropriate_state_images( self.contact.jid, icon_name=contact.show) tab_img = img_16[contact.show] return tab_img def prepare_context_menu(self, hide_buttonbar_items=False): """ Set compact view menuitem active state sets active and sensitivity state for history_menuitem (False for tranasports) and file_transfer_menuitem and hide()/show() for add_to_roster_menuitem """ if app.jid_is_transport(self.contact.jid): menu = gui_menu_builder.get_transport_menu(self.contact, self.account) else: menu = gui_menu_builder.get_contact_menu(self.contact, self.account, use_multiple_contacts=False, show_start_chat=False, show_encryption=True, control=self, show_buttonbar_items=not hide_buttonbar_items) return menu def shutdown(self): # PluginSystem: removing GUI extension points connected with ChatControl # instance object app.plugin_manager.remove_gui_extension_point('chat_control', self) app.ged.remove_event_handler('pep-received', ged.GUI1, self._nec_pep_received) app.ged.remove_event_handler('update-client-info', ged.GUI1, self._on_update_client_info) if self.TYPE_ID == message_control.TYPE_CHAT: app.ged.remove_event_handler('update-roster-avatar', ged.GUI1, self._nec_update_avatar) app.ged.remove_event_handler('chatstate-received', ged.GUI1, self._nec_chatstate_received) app.ged.remove_event_handler('caps-update', ged.GUI1, self._nec_caps_received) app.ged.remove_event_handler('message-sent', ged.OUT_POSTCORE, self._message_sent) app.ged.remove_event_handler( 'mam-decrypted-message-received', ged.GUI1, self._nec_mam_decrypted_message_received) app.ged.remove_event_handler( 'decrypted-message-received', ged.GUI1, self._nec_decrypted_message_received) app.ged.remove_event_handler( 'receipt-received', ged.GUI1, self._receipt_received) self.unsubscribe_events() # Send 'gone' chatstate con = app.connections[self.account] con.get_module('Chatstate').set_chatstate(self.contact, Chatstate.GONE) for jingle_type in ('audio', 'video'): self.close_jingle_content(jingle_type) # disconnect self from session if self.session: self.session.control = None # Clean events app.events.remove_events(self.account, self.get_full_jid(), types=['printed_' + self.type_id, self.type_id]) # Remove contact instance if contact has been removed key = (self.contact.jid, self.account) roster = app.interface.roster if key in roster.contacts_to_be_removed.keys() and \ not roster.contact_has_pending_roster_events(self.contact, self.account): backend = roster.contacts_to_be_removed[key]['backend'] del roster.contacts_to_be_removed[key] roster.remove_contact(self.contact.jid, self.account, force=True, backend=backend) # remove all register handlers on widgets, created by self.xml # to prevent circular references among objects for i in list(self.handlers.keys()): if self.handlers[i].handler_is_connected(i): self.handlers[i].disconnect(i) del self.handlers[i] self.conv_textview.del_handlers() self.msg_textview.destroy() # PluginSystem: calling shutdown of super class (ChatControlBase) to let # it remove it's GUI extension points super(ChatControl, self).shutdown() def minimizable(self): return False def safe_shutdown(self): return False def allow_shutdown(self, method, on_yes, on_no, on_minimize): if time.time() - app.last_message_time[self.account]\ [self.get_full_jid()] < 2: # 2 seconds def on_ok(): on_yes(self) def on_cancel(): on_no(self) ConfirmationDialog( #%s is being replaced in the code with JID _('You just received a new message from "%s"') % \ self.contact.jid, _('If you close this tab and you have history disabled, '\ 'this message will be lost.'), on_response_ok=on_ok, on_response_cancel=on_cancel, transient_for=self.parent_win.window) return on_yes(self) def _nec_chatstate_received(self, event): if event.account != self.account: return if self.TYPE_ID == 'pm': if event.contact != self.gc_contact: return else: if event.contact.jid != self.contact.jid: return self.draw_banner_text() # update chatstate in tab for this chat if event.contact.is_gc_contact: chatstate = event.contact.chatstate else: chatstate = app.contacts.get_combined_chatstate( self.account, self.contact.jid) self.parent_win.redraw_tab(self, chatstate) def _nec_caps_received(self, obj): if obj.conn.name != self.account: return if self.TYPE_ID == 'chat' and obj.jid != self.contact.jid: return if self.TYPE_ID == 'pm' and obj.fjid != self.contact.jid: return self.update_ui() def _nec_ping(self, obj): if self.contact != obj.contact: return if obj.name == 'ping-sent': self.print_conversation(_('Ping?'), 'status') elif obj.name == 'ping-reply': self.print_conversation( _('Pong! (%s seconds)') % obj.seconds, 'status') elif obj.name == 'ping-error': self.print_conversation(_('Error.'), 'status') def show_avatar(self): if not app.config.get('show_avatar_in_chat'): return scale = self.parent_win.window.get_scale_factor() if self.TYPE_ID == message_control.TYPE_CHAT: surface = app.contacts.get_avatar( self.account, self.contact.jid, AvatarSize.CHAT, scale) else: surface = app.interface.get_avatar( self.gc_contact.avatar_sha, AvatarSize.CHAT, scale) image = self.xml.get_object('avatar_image') if surface is None: image.set_from_icon_name('avatar-default', Gtk.IconSize.DIALOG) else: image.set_from_surface(surface) def _nec_update_avatar(self, obj): if obj.account != self.account: return if obj.jid != self.contact.jid: return self.show_avatar() def _on_drag_data_received(self, widget, context, x, y, selection, target_type, timestamp): if not selection.get_data(): return # get contact info (check for PM = private chat) if self.TYPE_ID == message_control.TYPE_PM: c = self.gc_contact.as_contact() else: c = self.contact if target_type == self.TARGET_TYPE_URI_LIST: # file drag and drop (handled in chat_control_base) self.drag_data_file_transfer(c, selection, self) else: # chat2muc treeview = app.interface.roster.tree model = treeview.get_model() data = selection.get_data() path = treeview.get_selection().get_selected_rows()[1][0] iter_ = model.get_iter(path) type_ = model[iter_][2] if type_ != 'contact': # source is not a contact return dropped_jid = data dropped_transport = app.get_transport_name_from_jid(dropped_jid) c_transport = app.get_transport_name_from_jid(c.jid) if dropped_transport or c_transport: return # transport contacts cannot be invited dialogs.TransformChatToMUC(self.account, [c.jid], [dropped_jid]) def restore_conversation(self): jid = self.contact.jid # don't restore lines if it's a transport if app.jid_is_transport(jid): return # number of messages that are in queue and are already logged, we want # to avoid duplication pending = len(app.events.get_events(self.account, jid, ['chat', 'pm'])) if self.resource: pending += len(app.events.get_events(self.account, self.contact.get_full_jid(), ['chat', 'pm'])) rows = app.logger.get_last_conversation_lines( self.account, jid, pending) local_old_kind = None self.conv_textview.just_cleared = True for row in rows: # time, kind, message, subject, additional_data msg = row.message additional_data = row.additional_data if not msg: # message is empty, we don't print it continue if row.kind in (KindConstant.CHAT_MSG_SENT, KindConstant.SINGLE_MSG_SENT): kind = 'outgoing' name = self.get_our_nick() elif row.kind in (KindConstant.SINGLE_MSG_RECV, KindConstant.CHAT_MSG_RECV): kind = 'incoming' name = self.contact.get_shown_name() elif row.kind == KindConstant.ERROR: kind = 'status' name = self.contact.get_shown_name() tim = float(row.time) if app.config.get('restored_messages_small'): small_attr = ['small'] else: small_attr = [] xhtml = None if msg.startswith(' # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2006-2008 Jean-Marie Traissard # Nikos Kouremenos # Travis Shirk # Copyright (C) 2007 Lukas Petrovicky # Julien Pivotto # Copyright (C) 2007-2008 Brendan Taylor # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import re import time from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gio from gajim.common import events from gajim.common import app from gajim.common import helpers from gajim.common import ged from gajim.common import i18n from gajim.common.i18n import _ from gajim.common.helpers import AdditionalDataDict from gajim.common.contacts import GC_Contact from gajim.common.connection_handlers_events import MessageOutgoingEvent from gajim.common.const import StyleAttr from gajim.common.const import Chatstate from gajim import notify from gajim import gtkgui_helpers from gajim import message_control from gajim.message_control import MessageControl from gajim.conversation_textview import ConversationTextview from gajim.message_textview import MessageTextView from gajim.gtk.dialogs import NonModalConfirmationDialog from gajim.gtk.util import convert_rgb_to_hex from gajim.gtk.util import get_primary_accel_mod from gajim.gtk.util import get_hardware_key_codes from gajim.gtk.emoji_chooser import emoji_chooser from gajim.command_system.implementation.middleware import ChatCommandProcessor from gajim.command_system.implementation.middleware import CommandTools # The members of these modules are not referenced directly anywhere in this # module, but still they need to be kept around. Importing them automatically # registers the contained CommandContainers with the command system, thereby # populating the list of available commands. # pylint: disable=unused-import from gajim.command_system.implementation import standard from gajim.command_system.implementation import execute # pylint: enable=unused-import if app.is_installed('GSPELL'): from gi.repository import Gspell ################################################################################ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): """ A base class containing a banner, ConversationTextview, MessageTextView """ # This is needed so copying text from the conversation textview # works with different language layouts. Pressing the key c on a russian # layout yields another keyval than with the english layout. # So we match hardware keycodes instead of keyvals. # Multiple hardware keycodes can trigger a keyval like Gdk.KEY_c. keycodes_c = get_hardware_key_codes(Gdk.KEY_c) def make_href(self, match): url_color = app.css_config.get_value('.gajim-url', StyleAttr.COLOR) color = convert_rgb_to_hex(url_color) url = match.group() if '://' not in url: url = 'http://' + url return '%s' % ( url, color, match.group()) def get_nb_unread(self): jid = self.contact.jid if self.resource: jid += '/' + self.resource type_ = self.type_id return len(app.events.get_events(self.account, jid, ['printed_' + type_, type_])) def draw_banner(self): """ Draw the fat line at the top of the window that houses the icon, jid, etc Derived types MAY implement this. """ self.draw_banner_text() self._update_banner_state_image() app.plugin_manager.gui_extension_point('chat_control_base_draw_banner', self) def update_toolbar(self): """ update state of buttons in toolbar """ self._update_toolbar() app.plugin_manager.gui_extension_point( 'chat_control_base_update_toolbar', self) def draw_banner_text(self): """ Derived types SHOULD implement this """ pass def update_ui(self): """ Derived types SHOULD implement this """ self.draw_banner() def repaint_themed_widgets(self): """ Derived types MAY implement this """ self.draw_banner() def _update_banner_state_image(self): """ Derived types MAY implement this """ pass def _update_toolbar(self): """ Derived types MAY implement this """ pass def _nec_our_status(self, obj): if self.account != obj.conn.name: return if obj.show == 'offline' or (obj.show == 'invisible' and \ obj.conn.is_zeroconf): self.got_disconnected() else: # Other code rejoins all GCs, so we don't do it here if not self.type_id == message_control.TYPE_GC: self.got_connected() if self.parent_win: self.parent_win.redraw_tab(self) def status_url_clicked(self, widget, url): helpers.launch_browser_mailer('url', url) def setup_seclabel(self): self.seclabel_combo.hide() self.seclabel_combo.set_no_show_all(True) lb = Gtk.ListStore(str) self.seclabel_combo.set_model(lb) cell = Gtk.CellRendererText() cell.set_property('xpad', 5) # padding for status text self.seclabel_combo.pack_start(cell, True) # text to show is in in first column of liststore self.seclabel_combo.add_attribute(cell, 'text', 0) con = app.connections[self.account] jid = self.contact.jid if self.TYPE_ID == 'pm': jid = self.gc_contact.room_jid if con.get_module('SecLabels').supported: con.get_module('SecLabels').request_catalog(jid) def _sec_labels_received(self, event): if event.account != self.account: return jid = self.contact.jid if self.TYPE_ID == 'pm': jid = self.gc_contact.room_jid if event.jid != jid: return model = self.seclabel_combo.get_model() model.clear() sel = 0 _label, labellist, default = event.catalog for index, label in enumerate(labellist): model.append([label]) if label == default: sel = index self.seclabel_combo.set_active(sel) self.seclabel_combo.set_no_show_all(False) self.seclabel_combo.show_all() def __init__(self, type_id, parent_win, widget_name, contact, acct, resource=None): # Undo needs this variable to know if space has been pressed. # Initialize it to True so empty textview is saved in undo list self.space_pressed = True if resource is None: # We very likely got a contact with a random resource. # This is bad, we need the highest for caps etc. c = app.contacts.get_contact_with_highest_priority(acct, contact.jid) if c and not isinstance(c, GC_Contact): contact = c MessageControl.__init__(self, type_id, parent_win, widget_name, contact, acct, resource=resource) if self.TYPE_ID != message_control.TYPE_GC: # Create banner and connect signals widget = self.xml.get_object('banner_eventbox') id_ = widget.connect('button-press-event', self._on_banner_eventbox_button_press_event) self.handlers[id_] = widget self.urlfinder = re.compile( r"(www\.(?!\.)|[a-z][a-z0-9+.-]*://)[^\s<>'\"]+[^!,\.\s<>\)'\"\]]") self.banner_status_label = self.xml.get_object('banner_label') if self.banner_status_label is not None: id_ = self.banner_status_label.connect('populate_popup', self.on_banner_label_populate_popup) self.handlers[id_] = self.banner_status_label # Init DND self.TARGET_TYPE_URI_LIST = 80 self.dnd_list = [Gtk.TargetEntry.new('text/uri-list', 0, self.TARGET_TYPE_URI_LIST), Gtk.TargetEntry.new('MY_TREE_MODEL_ROW', Gtk.TargetFlags.SAME_APP, 0)] id_ = self.widget.connect('drag_data_received', self._on_drag_data_received) self.handlers[id_] = self.widget self.widget.drag_dest_set(Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP, self.dnd_list, Gdk.DragAction.COPY) # Create textviews and connect signals self.conv_textview = ConversationTextview(self.account) id_ = self.conv_textview.connect('quote', self.on_quote) self.handlers[id_] = self.conv_textview.tv id_ = self.conv_textview.tv.connect('key_press_event', self._conv_textview_key_press_event) self.handlers[id_] = self.conv_textview.tv # FIXME: DND on non editable TextView, find a better way self.drag_entered = False id_ = self.conv_textview.tv.connect('drag_data_received', self._on_drag_data_received) self.handlers[id_] = self.conv_textview.tv id_ = self.conv_textview.tv.connect('drag_motion', self._on_drag_motion) self.handlers[id_] = self.conv_textview.tv id_ = self.conv_textview.tv.connect('drag_leave', self._on_drag_leave) self.handlers[id_] = self.conv_textview.tv self.conv_textview.tv.drag_dest_set(Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP, self.dnd_list, Gdk.DragAction.COPY) self.conv_scrolledwindow = self.xml.get_object( 'conversation_scrolledwindow') self.conv_scrolledwindow.add(self.conv_textview.tv) widget = self.conv_scrolledwindow.get_vadjustment() id_ = widget.connect('changed', self.on_conversation_vadjustment_changed) self.handlers[id_] = widget vscrollbar = self.conv_scrolledwindow.get_vscrollbar() id_ = vscrollbar.connect('button-release-event', self._on_scrollbar_button_release) self.handlers[id_] = vscrollbar self.correcting = False self.last_sent_msg = None # add MessageTextView to UI and connect signals self.msg_textview = MessageTextView() self.msg_scrolledwindow = ScrolledWindow() self.msg_scrolledwindow.add(self.msg_textview) hbox = self.xml.get_object('hbox') hbox.pack_start(self.msg_scrolledwindow, True, True, 0) id_ = self.msg_textview.connect('key_press_event', self._on_message_textview_key_press_event) self.handlers[id_] = self.msg_textview id_ = self.msg_textview.connect('populate_popup', self.on_msg_textview_populate_popup) self.handlers[id_] = self.msg_textview # Setup DND id_ = self.msg_textview.connect('drag_data_received', self._on_drag_data_received) self.handlers[id_] = self.msg_textview self.msg_textview.drag_dest_set(Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT, self.dnd_list, Gdk.DragAction.COPY) # the following vars are used to keep history of user's messages self.sent_history = [] self.sent_history_pos = 0 self.received_history = [] self.received_history_pos = 0 self.orig_msg = None self.set_emoticon_popover() # Attach speller self.set_speller() self.conv_textview.tv.show() # For XEP-0172 self.user_nick = None self.command_hits = [] self.last_key_tabs = False # Security Labels self.seclabel_combo = self.xml.get_object('label_selector') con = app.connections[self.account] con.get_module('Chatstate').set_active(self.contact.jid) id_ = self.msg_textview.connect('text-changed', self._on_message_tv_buffer_changed) self.handlers[id_] = self.msg_textview if parent_win is not None: id_ = parent_win.window.connect('motion-notify-event', self._on_window_motion_notify) self.handlers[id_] = parent_win.window self.encryption = self.get_encryption_state() self.conv_textview.encryption_enabled = self.encryption is not None # PluginSystem: adding GUI extension point for ChatControlBase # instance object (also subclasses, eg. ChatControl or GroupchatControl) app.plugin_manager.gui_extension_point('chat_control_base', self) app.ged.register_event_handler('our-show', ged.GUI1, self._nec_our_status) app.ged.register_event_handler('ping-sent', ged.GUI1, self._nec_ping) app.ged.register_event_handler('ping-reply', ged.GUI1, self._nec_ping) app.ged.register_event_handler('ping-error', ged.GUI1, self._nec_ping) app.ged.register_event_handler('sec-catalog-received', ged.GUI1, self._sec_labels_received) app.ged.register_event_handler('style-changed', ged.GUI1, self._style_changed) # This is basically a very nasty hack to surpass the inability # to properly use the super, because of the old code. CommandTools.__init__(self) def add_actions(self): action = Gio.SimpleAction.new_stateful( "set-encryption-%s" % self.control_id, GLib.VariantType.new("s"), GLib.Variant("s", self.encryption or 'disabled')) action.connect("change-state", self.change_encryption) self.parent_win.window.add_action(action) action = Gio.SimpleAction.new( 'browse-history-%s' % self.control_id, GLib.VariantType.new('s')) action.connect('activate', self._on_history) self.parent_win.window.add_action(action) action = Gio.SimpleAction.new( 'send-file-%s' % self.control_id, None) action.connect('activate', self._on_send_file) action.set_enabled(False) self.parent_win.window.add_action(action) action = Gio.SimpleAction.new( 'send-file-httpupload-%s' % self.control_id, None) action.connect('activate', self._on_send_httpupload) action.set_enabled(False) self.parent_win.window.add_action(action) action = Gio.SimpleAction.new( 'send-file-jingle-%s' % self.control_id, None) action.connect('activate', self._on_send_jingle) action.set_enabled(False) self.parent_win.window.add_action(action) # Actions def _on_history(self, action, param): """ When history menuitem is pressed: call history window """ jid = param.get_string() if jid == 'none': jid = self.contact.jid if 'logs' in app.interface.instances: app.interface.instances['logs'].window.present() app.interface.instances['logs'].open_history(jid, self.account) else: from gajim.gtk.history import HistoryWindow app.interface.instances['logs'] = HistoryWindow(jid, self.account) def change_encryption(self, action, param): encryption = param.get_string() if encryption == 'disabled': encryption = None if self.encryption == encryption: return if encryption: plugin = app.plugin_manager.encryption_plugins[encryption] if not plugin.activate_encryption(self): return action.set_state(param) self.set_encryption_state(encryption) self.set_encryption_menu_icon() self.set_lock_image() def set_encryption_state(self, encryption): config_key = '%s-%s' % (self.account, self.contact.jid) self.encryption = encryption self.conv_textview.encryption_enabled = encryption is not None app.config.set_per('encryption', config_key, 'encryption', self.encryption or '') def get_encryption_state(self): config_key = '%s-%s' % (self.account, self.contact.jid) state = app.config.get_per('encryption', config_key, 'encryption') if not state: return None if state not in app.plugin_manager.encryption_plugins: self.set_encryption_state(None) return None return state def set_encryption_menu_icon(self): image = self.encryption_menu.get_image() if image is None: image = Gtk.Image() self.encryption_menu.set_image(image) if not self.encryption: image.set_from_icon_name('channel-insecure-symbolic', Gtk.IconSize.MENU) else: image.set_from_icon_name('channel-secure-symbolic', Gtk.IconSize.MENU) def set_speller(self): if not app.is_installed('GSPELL') or not app.config.get('use_speller'): return gspell_lang = self.get_speller_language() if gspell_lang is None: return spell_checker = Gspell.Checker.new(gspell_lang) spell_buffer = Gspell.TextBuffer.get_from_gtk_text_buffer( self.msg_textview.get_buffer()) spell_buffer.set_spell_checker(spell_checker) spell_view = Gspell.TextView.get_from_gtk_text_view(self.msg_textview) spell_view.set_inline_spell_checking(False) spell_view.set_enable_language_menu(True) spell_checker.connect('notify::language', self.on_language_changed) def get_speller_language(self): per_type = 'contacts' if self.type_id == 'gc': per_type = 'rooms' lang = app.config.get_per( per_type, self.contact.jid, 'speller_language') if not lang: # use the default one lang = app.config.get('speller_language') if not lang: lang = i18n.LANG gspell_lang = Gspell.language_lookup(lang) if gspell_lang is None: gspell_lang = Gspell.language_get_default() return gspell_lang def on_language_changed(self, checker, param): gspell_lang = checker.get_language() per_type = 'contacts' if self.type_id == message_control.TYPE_GC: per_type = 'rooms' if not app.config.get_per(per_type, self.contact.jid): app.config.add_per(per_type, self.contact.jid) app.config.set_per(per_type, self.contact.jid, 'speller_language', gspell_lang.get_code()) def on_banner_label_populate_popup(self, label, menu): """ Override the default context menu and add our own menuitems """ item = Gtk.SeparatorMenuItem.new() menu.prepend(item) menu2 = self.prepare_context_menu() i = 0 for item in menu2: menu2.remove(item) menu.prepend(item) menu.reorder_child(item, i) i += 1 menu.show_all() def shutdown(self): super(ChatControlBase, self).shutdown() # PluginSystem: removing GUI extension points connected with ChatControlBase # instance object app.plugin_manager.remove_gui_extension_point('chat_control_base', self) app.plugin_manager.remove_gui_extension_point( 'chat_control_base_draw_banner', self) app.ged.remove_event_handler('our-show', ged.GUI1, self._nec_our_status) app.ged.remove_event_handler('sec-catalog-received', ged.GUI1, self._sec_labels_received) app.ged.remove_event_handler('style-changed', ged.GUI1, self._style_changed) def on_msg_textview_populate_popup(self, textview, menu): """ Override the default context menu and we prepend an option to switch languages """ item = Gtk.MenuItem.new_with_mnemonic(_('_Undo')) menu.prepend(item) id_ = item.connect('activate', self.msg_textview.undo) self.handlers[id_] = item item = Gtk.SeparatorMenuItem.new() menu.prepend(item) item = Gtk.MenuItem.new_with_mnemonic(_('_Clear')) menu.prepend(item) id_ = item.connect('activate', self.msg_textview.clear) self.handlers[id_] = item paste_item = Gtk.MenuItem.new_with_label(_('Paste as quote')) id_ = paste_item.connect('activate', self.paste_clipboard_as_quote) self.handlers[id_] = paste_item menu.append(paste_item) menu.show_all() def insert_as_quote(self, text: str) -> None: self.msg_textview.remove_placeholder() text = '> ' + text.replace('\n', '\n> ') + '\n' message_buffer = self.msg_textview.get_buffer() message_buffer.insert_at_cursor(text) def paste_clipboard_as_quote(self, _item: Gtk.MenuItem) -> None: clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) text = clipboard.wait_for_text() self.insert_as_quote(text) def on_quote(self, widget, text): self.insert_as_quote(text) # moved from ChatControl def _on_banner_eventbox_button_press_event(self, widget, event): """ If right-clicked, show popup """ if event.button == 3: # right click self.parent_win.popup_menu(event) def _conv_textview_key_press_event(self, _widget, event): if (event.get_state() & get_primary_accel_mod() and event.hardware_keycode in self.keycodes_c): return Gdk.EVENT_PROPAGATE if (event.get_state() & Gdk.ModifierType.SHIFT_MASK and event.keyval in (Gdk.KEY_Page_Down, Gdk.KEY_Page_Up)): self._on_scroll(None, event.keyval) return Gdk.EVENT_PROPAGATE self.parent_win.notebook.event(event) return Gdk.EVENT_STOP def _on_message_textview_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_space: self.space_pressed = True elif (self.space_pressed or self.msg_textview.undo_pressed) and \ event.keyval not in (Gdk.KEY_Control_L, Gdk.KEY_Control_R) and \ not (event.keyval == Gdk.KEY_z and event.get_state() & Gdk.ModifierType.CONTROL_MASK): # If the space key has been pressed and now it hasn't, # we save the buffer into the undo list. But be careful we're not # pressing Control again (as in ctrl+z) _buffer = widget.get_buffer() start_iter, end_iter = _buffer.get_bounds() self.msg_textview.save_undo(_buffer.get_text(start_iter, end_iter, True)) self.space_pressed = False # Ctrl [+ Shift] + Tab are not forwarded to notebook. We handle it here if self.widget_name == 'groupchat_control': if event.keyval not in (Gdk.KEY_ISO_Left_Tab, Gdk.KEY_Tab): self.last_key_tabs = False if event.get_state() & Gdk.ModifierType.SHIFT_MASK: # CTRL + SHIFT + TAB if event.get_state() & Gdk.ModifierType.CONTROL_MASK and \ event.keyval == Gdk.KEY_ISO_Left_Tab: self.parent_win.move_to_next_unread_tab(False) return True # SHIFT + PAGE_[UP|DOWN]: send to conv_textview if event.keyval == Gdk.KEY_Page_Down or \ event.keyval == Gdk.KEY_Page_Up: self.conv_textview.tv.event(event) return True if event.get_state() & Gdk.ModifierType.CONTROL_MASK: if event.keyval == Gdk.KEY_Tab: # CTRL + TAB self.parent_win.move_to_next_unread_tab(True) return True message_buffer = self.msg_textview.get_buffer() event_state = event.get_state() if event.keyval == Gdk.KEY_Tab: start, end = message_buffer.get_bounds() position = message_buffer.get_insert() end = message_buffer.get_iter_at_mark(position) text = message_buffer.get_text(start, end, False) splitted = text.split() if (text.startswith(self.COMMAND_PREFIX) and not text.startswith(self.COMMAND_PREFIX * 2) and len(splitted) == 1): text = splitted[0] bare = text.lstrip(self.COMMAND_PREFIX) if len(text) == 1: self.command_hits = [] for command in self.list_commands(): for name in command.names: self.command_hits.append(name) else: if (self.last_key_tabs and self.command_hits and self.command_hits[0].startswith(bare)): self.command_hits.append(self.command_hits.pop(0)) else: self.command_hits = [] for command in self.list_commands(): for name in command.names: if name.startswith(bare): self.command_hits.append(name) if self.command_hits: message_buffer.delete(start, end) message_buffer.insert_at_cursor(self.COMMAND_PREFIX + \ self.command_hits[0] + ' ') self.last_key_tabs = True return True if self.widget_name != 'groupchat_control': self.last_key_tabs = False if event.keyval == Gdk.KEY_Up: if event_state & Gdk.ModifierType.CONTROL_MASK: if event_state & Gdk.ModifierType.SHIFT_MASK: # Ctrl+Shift+UP self.scroll_messages('up', message_buffer, 'received') else: # Ctrl+UP self.scroll_messages('up', message_buffer, 'sent') return True elif event.keyval == Gdk.KEY_Down: if event_state & Gdk.ModifierType.CONTROL_MASK: if event_state & Gdk.ModifierType.SHIFT_MASK: # Ctrl+Shift+Down self.scroll_messages('down', message_buffer, 'received') else: # Ctrl+Down self.scroll_messages('down', message_buffer, 'sent') return True elif event.keyval == Gdk.KEY_Return or \ event.keyval == Gdk.KEY_KP_Enter: # ENTER message_textview = widget message_buffer = message_textview.get_buffer() message_textview.replace_emojis() start_iter, end_iter = message_buffer.get_bounds() message = message_buffer.get_text(start_iter, end_iter, False) xhtml = self.msg_textview.get_xhtml() if event_state & Gdk.ModifierType.SHIFT_MASK: send_message = False else: is_ctrl_enter = bool(event_state & Gdk.ModifierType.CONTROL_MASK) send_message = is_ctrl_enter == app.config.get('send_on_ctrl_enter') if send_message and app.connections[self.account].connected < 2: # we are not connected app.interface.raise_dialog('not-connected-while-sending') elif send_message: self.send_message(message, xhtml=xhtml) else: message_buffer.insert_at_cursor('\n') mark = message_buffer.get_insert() iter_ = message_buffer.get_iter_at_mark(mark) if message_buffer.get_end_iter().equal(iter_): GLib.idle_add(gtkgui_helpers.scroll_to_end, self.msg_scrolledwindow) return True elif event.keyval == Gdk.KEY_z: # CTRL+z if event_state & Gdk.ModifierType.CONTROL_MASK: self.msg_textview.undo() return True return False def _on_drag_data_received(self, widget, context, x, y, selection, target_type, timestamp): """ Derived types SHOULD implement this """ pass def _on_drag_leave(self, *args): # FIXME: DND on non editable TextView, find a better way self.drag_entered = False self.conv_textview.tv.set_editable(False) def _on_drag_motion(self, *args): # FIXME: DND on non editable TextView, find a better way if not self.drag_entered: # We drag new data over the TextView, make it editable to catch dnd self.drag_entered_conv = True self.conv_textview.tv.set_editable(True) def drag_data_file_transfer(self, contact, selection, widget): # get file transfer preference ft_pref = app.config.get_per('accounts', self.account, 'filetransfer_preference') win = self.parent_win.window con = app.connections[self.account] httpupload = win.lookup_action( 'send-file-httpupload-%s' % self.control_id) jingle = win.lookup_action('send-file-jingle-%s' % self.control_id) # we may have more than one file dropped uri_splitted = selection.get_uris() for uri in uri_splitted: path = helpers.get_file_path_from_dnd_dropped_uri(uri) if not os.path.isfile(path): # is it a file? continue if self.type_id == message_control.TYPE_GC: # groupchat only supports httpupload on drag and drop if httpupload.get_enabled(): # use httpupload con.get_module('HTTPUpload').check_file_before_transfer( path, self.encryption, contact, self.session, groupchat=True) else: if httpupload.get_enabled() and jingle.get_enabled(): if ft_pref == 'httpupload': con.get_module('HTTPUpload').check_file_before_transfer( path, self.encryption, contact, self.session) else: ft = app.interface.instances['file_transfers'] ft.send_file(self.account, contact, path) elif httpupload.get_enabled(): con.get_module('HTTPUpload').check_file_before_transfer( path, self.encryption, contact, self.session) elif jingle.get_enabled(): ft = app.interface.instances['file_transfers'] ft.send_file(self.account, contact, path) def get_seclabel(self): idx = self.seclabel_combo.get_active() if idx == -1: return con = app.connections[self.account] jid = self.contact.jid if self.TYPE_ID == 'pm': jid = self.gc_contact.room_jid catalog = con.get_module('SecLabels').get_catalog(jid) labels, label_list, _ = catalog lname = label_list[idx] label = labels[lname] return label def send_message(self, message, keyID='', type_='chat', resource=None, xhtml=None, process_commands=True, attention=False): """ Send the given message to the active tab. Doesn't return None if error """ if not message or message == '\n': return None if process_commands and self.process_as_command(message): return label = self.get_seclabel() if self.correcting and self.last_sent_msg: correct_id = self.last_sent_msg else: correct_id = None con = app.connections[self.account] chatstate = con.get_module('Chatstate').get_active_chatstate( self.contact) app.nec.push_outgoing_event(MessageOutgoingEvent(None, account=self.account, jid=self.contact.jid, message=message, keyID=keyID, type_=type_, chatstate=chatstate, resource=resource, user_nick=self.user_nick, xhtml=xhtml, label=label, control=self, attention=attention, correct_id=correct_id, automatic_message=False, encryption=self.encryption)) # Record the history of sent messages self.save_message(message, 'sent') # Be sure to send user nickname only once according to JEP-0172 self.user_nick = None # Clear msg input message_buffer = self.msg_textview.get_buffer() message_buffer.set_text('') # clear message buffer (and tv of course) def _on_window_motion_notify(self, *args): """ It gets called no matter if it is the active window or not """ if not self.parent_win: # when a groupchat is minimized there is no parent window return if self.parent_win.get_active_jid() == self.contact.jid: # if window is the active one, set last interaction con = app.connections[self.account] con.get_module('Chatstate').set_mouse_activity(self.contact) def _on_message_tv_buffer_changed(self, textview, textbuffer): if textbuffer.get_char_count() and self.encryption: app.plugin_manager.extension_point( 'typing' + self.encryption, self) con = app.connections[self.account] con.get_module('Chatstate').set_keyboard_activity(self.contact) if not textview.has_text(): con.get_module('Chatstate').set_chatstate(self.contact, Chatstate.ACTIVE) return con.get_module('Chatstate').set_chatstate(self.contact, Chatstate.COMPOSING) def save_message(self, message, msg_type): # save the message, so user can scroll though the list with key up/down if msg_type == 'sent': history = self.sent_history pos = self.sent_history_pos else: history = self.received_history pos = self.received_history_pos size = len(history) scroll = False if pos == size else True # are we scrolling? # we don't want size of the buffer to grow indefinitely max_size = app.config.get('key_up_lines') for _i in range(size - max_size + 1): if pos == 0: break history.pop(0) pos -= 1 history.append(message) if not scroll or msg_type == 'sent': pos = len(history) if msg_type == 'sent': self.sent_history_pos = pos self.orig_msg = None else: self.received_history_pos = pos def print_conversation_line(self, text, kind, name, tim, other_tags_for_name=None, other_tags_for_time=None, other_tags_for_text=None, count_as_new=True, subject=None, old_kind=None, xhtml=None, simple=False, xep0184_id=None, graphics=True, displaymarking=None, msg_log_id=None, msg_stanza_id=None, correct_id=None, additional_data=None, encrypted=None): """ Print 'chat' type messages correct_id = (message_id, correct_id) """ jid = self.contact.jid full_jid = self.get_full_jid() textview = self.conv_textview end = False if self.conv_textview.autoscroll or kind == 'outgoing': end = True if other_tags_for_name is None: other_tags_for_name = [] if other_tags_for_time is None: other_tags_for_time = [] if other_tags_for_text is None: other_tags_for_text = [] if additional_data is None: additional_data = AdditionalDataDict() textview.print_conversation_line(text, jid, kind, name, tim, other_tags_for_name, other_tags_for_time, other_tags_for_text, subject, old_kind, xhtml, simple=simple, graphics=graphics, displaymarking=displaymarking, msg_stanza_id=msg_stanza_id, correct_id=correct_id, additional_data=additional_data, encrypted=encrypted) if xep0184_id is not None: textview.add_xep0184_mark(xep0184_id) if not count_as_new: return if kind == 'incoming': if not self.type_id == message_control.TYPE_GC or \ app.config.get('notify_on_all_muc_messages') or \ app.config.get_per('rooms', jid, 'notify_on_all_messages') or \ 'marked' in other_tags_for_text: # it's a normal message, or a muc message with want to be # notified about if quitting just after # other_tags_for_text == ['marked'] --> highlighted gc message app.last_message_time[self.account][full_jid] = time.time() if kind in ('incoming', 'incoming_queue'): # Record the history of received messages self.save_message(text, 'received') if kind in ('incoming', 'incoming_queue', 'error'): gc_message = False if self.type_id == message_control.TYPE_GC: gc_message = True if ((self.parent_win and (not self.parent_win.get_active_control() or \ self != self.parent_win.get_active_control() or \ not self.parent_win.is_active() or not end)) or \ (gc_message and \ jid in app.interface.minimized_controls[self.account])) and \ kind in ('incoming', 'incoming_queue', 'error'): # we want to have save this message in events list # other_tags_for_text == ['marked'] --> highlighted gc message if gc_message: if 'marked' in other_tags_for_text: event_type = events.PrintedMarkedGcMsgEvent else: event_type = events.PrintedGcMsgEvent event = 'gc_message_received' else: if self.type_id == message_control.TYPE_CHAT: event_type = events.PrintedChatEvent else: event_type = events.PrintedPmEvent event = 'message_received' show_in_roster = notify.get_show_in_roster(event, self.account, self.contact.jid, self.session) show_in_systray = notify.get_show_in_systray(event, self.account, self.contact.jid, event_type.type_) event = event_type(text, subject, self, msg_log_id, show_in_roster=show_in_roster, show_in_systray=show_in_systray) app.events.add_event(self.account, full_jid, event) # We need to redraw contact if we show in roster if show_in_roster: app.interface.roster.draw_contact(self.contact.jid, self.account) if not self.parent_win: return if (not self.parent_win.get_active_control() or \ self != self.parent_win.get_active_control() or \ not self.parent_win.is_active() or not end) and \ kind in ('incoming', 'incoming_queue', 'error'): self.parent_win.redraw_tab(self) if not self.parent_win.is_active(): self.parent_win.show_title(True, self) # Enabled Urgent hint else: self.parent_win.show_title(False, self) # Disabled Urgent hint def toggle_emoticons(self): """ Hide show emoticons_button """ if app.config.get('emoticons_theme'): self.emoticons_button.set_no_show_all(False) self.emoticons_button.show() else: self.emoticons_button.set_no_show_all(True) self.emoticons_button.hide() def set_emoticon_popover(self): if not app.config.get('emoticons_theme'): return if not self.parent_win: return emoji_chooser.text_widget = self.msg_textview emoticons_button = self.xml.get_object('emoticons_button') emoticons_button.set_popover(emoji_chooser) def on_color_menuitem_activate(self, widget): color_dialog = Gtk.ColorChooserDialog(None, self.parent_win.window) color_dialog.set_use_alpha(False) color_dialog.connect('response', self.msg_textview.color_set) color_dialog.show_all() def on_font_menuitem_activate(self, widget): font_dialog = Gtk.FontChooserDialog(None, self.parent_win.window) start, finish = self.msg_textview.get_active_iters() font_dialog.connect('response', self.msg_textview.font_set, start, finish) font_dialog.show_all() def on_formatting_menuitem_activate(self, widget): tag = widget.get_name() self.msg_textview.set_tag(tag) def on_clear_formatting_menuitem_activate(self, widget): self.msg_textview.clear_tags() def _style_changed(self, *args): self.update_tags() def update_tags(self): self.conv_textview.update_tags() def clear(self, tv): buffer_ = tv.get_buffer() start, end = buffer_.get_bounds() buffer_.delete(start, end) def _on_history_menuitem_activate(self, widget=None, jid=None): """ When history menuitem is pressed: call history window """ if not jid: jid = self.contact.jid if 'logs' in app.interface.instances: app.interface.instances['logs'].window.present() app.interface.instances['logs'].open_history(jid, self.account) else: from gajim.gtk.history import HistoryWindow app.interface.instances['logs'] = HistoryWindow(jid, self.account) def _on_send_file(self, action, param): # get file transfer preference ft_pref = app.config.get_per('accounts', self.account, 'filetransfer_preference') win = self.parent_win.window httpupload = win.lookup_action( 'send-file-httpupload-%s' % self.control_id) jingle = win.lookup_action('send-file-jingle-%s' % self.control_id) if httpupload.get_enabled() and jingle.get_enabled(): if ft_pref == 'httpupload': httpupload.activate() else: jingle.activate() elif httpupload.get_enabled(): httpupload.activate() elif jingle.get_enabled(): jingle.activate() def _on_send_httpupload(self, action, param): app.interface.send_httpupload(self) def _on_send_jingle(self, action, param): self._on_send_file_jingle() def _on_send_file_jingle(self, gc_contact=None): """ gc_contact can be set when we are in a groupchat control """ def _on_ok(c): app.interface.instances['file_transfers'].show_file_send_request( self.account, c) if self.type_id == message_control.TYPE_PM: gc_contact = self.gc_contact if gc_contact: # gc or pm gc_control = app.interface.msg_win_mgr.get_gc_control( gc_contact.room_jid, self.account) self_contact = app.contacts.get_gc_contact(self.account, gc_control.room_jid, gc_control.nick) if gc_control.is_anonymous and gc_contact.affiliation not in ['admin', 'owner'] and self_contact.affiliation in ['admin', 'owner']: contact = app.contacts.get_contact(self.account, gc_contact.jid) if not contact or contact.sub not in ('both', 'to'): prim_text = _('Really send file?') sec_text = _('If you send a file to %s, your real JID will ' 'be revealed.') % gc_contact.name dialog = NonModalConfirmationDialog(prim_text, sec_text, on_response_ok=(_on_ok, gc_contact)) dialog.popup() return _on_ok(gc_contact) return _on_ok(self.contact) def on_minimize_menuitem_toggled(self, widget): """ When a groupchat is minimized, unparent the tab, put it in roster etc """ old_value = True non_minimized_gc = app.config.get_per('accounts', self.account, 'non_minimized_gc').split() if self.contact.jid in non_minimized_gc: old_value = False minimize = widget.get_active() if not minimize and not self.contact.jid in non_minimized_gc: non_minimized_gc.append(self.contact.jid) if minimize and self.contact.jid in non_minimized_gc: non_minimized_gc.remove(self.contact.jid) if old_value != minimize: app.config.set_per('accounts', self.account, 'non_minimized_gc', ' '.join(non_minimized_gc)) def on_notify_menuitem_toggled(self, widget): app.config.set_per('rooms', self.contact.jid, 'notify_on_all_messages', widget.get_active()) def set_control_active(self, state): con = app.connections[self.account] if state: self.set_emoticon_popover() jid = self.contact.jid if self.conv_textview.autoscroll: # we are at the end type_ = ['printed_' + self.type_id] if self.type_id == message_control.TYPE_GC: type_ = ['printed_gc_msg', 'printed_marked_gc_msg'] if not app.events.remove_events(self.account, self.get_full_jid(), types=type_): # There were events to remove self.redraw_after_event_removed(jid) # send chatstate inactive to the one we're leaving # and active to the one we visit if self.msg_textview.has_text(): con.get_module('Chatstate').set_chatstate(self.contact, Chatstate.PAUSED) else: con.get_module('Chatstate').set_chatstate(self.contact, Chatstate.ACTIVE) else: con.get_module('Chatstate').set_chatstate(self.contact, Chatstate.INACTIVE) def scroll_to_end(self, force=False): self.conv_textview.scroll_to_end(force) def _on_edge_reached(self, scrolledwindow, pos): if pos != Gtk.PositionType.BOTTOM: return # Remove all events and set autoscroll True app.log('autoscroll').info('Autoscroll enabled') self.conv_textview.autoscroll = True if self.resource: jid = self.contact.get_full_jid() else: jid = self.contact.jid types_list = [] type_ = self.type_id if type_ == message_control.TYPE_GC: type_ = 'gc_msg' types_list = ['printed_' + type_, type_, 'printed_marked_gc_msg'] else: # Not a GC types_list = ['printed_' + type_, type_] if not app.events.get_events(self.account, jid, types_list): return if not self.parent_win: return if self.parent_win.get_active_control() == self and \ self.parent_win.window.is_active(): # we are at the end if not app.events.remove_events( self.account, jid, types=types_list): # There were events to remove self.redraw_after_event_removed(jid) def _on_scrollbar_button_release(self, scrollbar, event): if event.get_button()[1] != 1: # We want only to catch the left mouse button return if not gtkgui_helpers.at_the_end(scrollbar.get_parent()): app.log('autoscroll').info('Autoscroll disabled') self.conv_textview.autoscroll = False def has_focus(self): if self.parent_win: if self.parent_win.window.get_property('has-toplevel-focus'): if self == self.parent_win.get_active_control(): return True return False def _on_scroll(self, widget, event): if not self.conv_textview.autoscroll: # autoscroll is already disabled return if widget is None: # call from _conv_textview_key_press_event() # SHIFT + Gdk.KEY_Page_Up if event != Gdk.KEY_Page_Up: return else: # On scrolling UP disable autoscroll # get_scroll_direction() sets has_direction only TRUE # if smooth scrolling is deactivated. If we have smooth # smooth scrolling we have to use get_scroll_deltas() has_direction, direction = event.get_scroll_direction() if not has_direction: direction = None smooth, delta_x, delta_y = event.get_scroll_deltas() if smooth: if delta_y < 0: direction = Gdk.ScrollDirection.UP elif delta_y > 0: direction = Gdk.ScrollDirection.DOWN elif delta_x < 0: direction = Gdk.ScrollDirection.LEFT elif delta_x > 0: direction = Gdk.ScrollDirection.RIGHT else: app.log('autoscroll').warning( 'Scroll directions cant be determined') if direction != Gdk.ScrollDirection.UP: return # Check if we have a Scrollbar adjustment = self.conv_scrolledwindow.get_vadjustment() if adjustment.get_upper() != adjustment.get_page_size(): app.log('autoscroll').info('Autoscroll disabled') self.conv_textview.autoscroll = False def on_conversation_vadjustment_changed(self, adjustment): self.scroll_to_end() def redraw_after_event_removed(self, jid): """ We just removed a 'printed_*' event, redraw contact in roster or gc_roster and titles in roster and msg_win """ self.parent_win.redraw_tab(self) self.parent_win.show_title() # TODO : get the contact and check notify.get_show_in_roster() if self.type_id == message_control.TYPE_PM: room_jid, nick = app.get_room_and_nick_from_fjid(jid) groupchat_control = app.interface.msg_win_mgr.get_gc_control( room_jid, self.account) if room_jid in app.interface.minimized_controls[self.account]: groupchat_control = \ app.interface.minimized_controls[self.account][room_jid] contact = app.contacts.get_contact_with_highest_priority( self.account, room_jid) if contact: app.interface.roster.draw_contact(room_jid, self.account) if groupchat_control: groupchat_control.draw_contact(nick) if groupchat_control.parent_win: groupchat_control.parent_win.redraw_tab(groupchat_control) else: app.interface.roster.draw_contact(jid, self.account) app.interface.roster.show_title() def scroll_messages(self, direction, msg_buf, msg_type): if msg_type == 'sent': history = self.sent_history pos = self.sent_history_pos self.received_history_pos = len(self.received_history) else: history = self.received_history pos = self.received_history_pos self.sent_history_pos = len(self.sent_history) size = len(history) if self.orig_msg is None: # user was typing something and then went into history, so save # whatever is already typed start_iter = msg_buf.get_start_iter() end_iter = msg_buf.get_end_iter() self.orig_msg = msg_buf.get_text(start_iter, end_iter, False) if pos == size and size > 0 and direction == 'up' and \ msg_type == 'sent' and not self.correcting and (not \ history[pos - 1].startswith('/') or history[pos - 1].startswith('/me')): self.correcting = True gtkgui_helpers.add_css_class( self.msg_textview, 'gajim-msg-correcting') message = history[pos - 1] msg_buf.set_text(message) return if self.correcting: # We were previously correcting gtkgui_helpers.remove_css_class( self.msg_textview, 'gajim-msg-correcting') self.correcting = False pos += -1 if direction == 'up' else +1 if pos == -1: return if pos >= size: pos = size message = self.orig_msg self.orig_msg = None else: message = history[pos] if msg_type == 'sent': self.sent_history_pos = pos else: self.received_history_pos = pos if self.orig_msg is not None: message = '> %s\n' % message.replace('\n', '\n> ') msg_buf.set_text(message) def widget_set_visible(self, widget, state): """ Show or hide a widget """ # make the last message visible, when changing to "full view" if not state: self.scroll_to_end() widget.set_no_show_all(state) if state: widget.hide() else: widget.show_all() def got_connected(self): self.msg_textview.set_sensitive(True) self.msg_textview.set_editable(True) self.update_toolbar() def got_disconnected(self): self.msg_textview.set_sensitive(False) self.msg_textview.set_editable(False) self.conv_textview.tv.grab_focus() self.no_autonegotiation = False self.update_toolbar() class ScrolledWindow(Gtk.ScrolledWindow): def __init__(self, *args, **kwargs): Gtk.ScrolledWindow.__init__(self, *args, **kwargs) self.set_overlay_scrolling(False) self.set_max_content_height(100) self.set_propagate_natural_height(True) self.get_style_context().add_class('scrolled-no-border') self.get_style_context().add_class('no-scroll-indicator') self.get_style_context().add_class('scrollbar-style') self.set_shadow_type(Gtk.ShadowType.IN) def do_get_preferred_height(self): min_height, natural_height = Gtk.ScrolledWindow.do_get_preferred_height(self) # Gtk Bug: If policy is set to Automatic, the ScrolledWindow # has a min size of around 46-82 depending on the System. Because # we want it smaller, we set policy NEVER if the height is < 90 # so the ScrolledWindow will shrink to around 26 (1 line height). # Once it gets over 90 its no problem to restore the policy. if natural_height < 90: GLib.idle_add(self.set_policy, Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER) else: GLib.idle_add(self.set_policy, Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) return min_height, natural_height gajim-gajim-1.1.3/gajim/command_system/000077500000000000000000000000001345766322700200205ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/command_system/__init__.py000066400000000000000000000016031345766322700221310ustar00rootroot00000000000000# Copyright (C) 2009-2010 Alexander Cherniuk # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ The command system providing scalable, clean and convenient architecture in combination with declarative way of defining commands and a fair amount of automatization for routine processes. """ gajim-gajim-1.1.3/gajim/command_system/dispatcher.py000066400000000000000000000075021345766322700225240ustar00rootroot00000000000000# Copyright (c) 2010, Alexander Cherniuk (ts33kr@gmail.com) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ Backbone of the command system. Provides smart and controllable dispatching mechanism with an auto-discovery functionality. In addition to automatic discovery and dispatching, also features manual control over the process. """ from typing import Any # pylint: disable=unused-import from typing import Dict # pylint: disable=unused-import from gajim.command_system.tools import remove COMMANDS = {} # type: Dict[Any, Any] CONTAINERS = {} # type: Dict[Any, Any] def add_host(host): CONTAINERS[host] = [] def remove_host(host): remove(CONTAINERS, host) def add_container(container): for host in container.HOSTS: CONTAINERS[host].append(container) def remove_container(container): for host in container.HOSTS: remove(CONTAINERS[host], container) def add_commands(container): commands = COMMANDS.setdefault(container, {}) for command in traverse_commands(container): for name in command.names: commands[name] = command def remove_commands(container): remove(COMMANDS, container) def traverse_commands(container): for name in dir(container): attribute = getattr(container, name) if is_command(attribute): yield attribute def is_command(attribute): from gajim.command_system.framework import Command return isinstance(attribute, Command) def is_root(namespace): metaclass = namespace.get("__metaclass__", None) if not metaclass: return False return issubclass(metaclass, Dispatchable) def get_command(host, name): for container in CONTAINERS[host]: command = COMMANDS[container].get(name) if command: return command def list_commands(host): for container in CONTAINERS[host]: commands = COMMANDS[container] for name, command in commands.items(): yield name, command class Dispatchable(type): # pylint: disable=no-value-for-parameter def __init__(cls, name, bases, namespace): parents = super(Dispatchable, cls) parents.__init__(name, bases, namespace) if not is_root(namespace): cls.dispatch() def dispatch(cls): if cls.AUTOMATIC: cls.enable() class Host(Dispatchable): def enable(cls): add_host(cls) def disable(cls): remove_host(cls) class Container(Dispatchable): def enable(cls): add_container(cls) add_commands(cls) def disable(cls): remove_commands(cls) remove_container(cls) gajim-gajim-1.1.3/gajim/command_system/errors.py000066400000000000000000000030601345766322700217050ustar00rootroot00000000000000# Copyright (C) 2009-2010 Alexander Cherniuk # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . class BaseError(Exception): """ Common base for errors which relate to a specific command. Encapsulates everything needed to identify a command, by either its object or name. """ def __init__(self, message, command=None, name=None): self.message = message self.command = command self.name = name if command and not name: self.name = command.first_name super(BaseError, self).__init__() def __str__(self): return self.message class DefinitionError(BaseError): """ Used to indicate errors occurred on command definition. """ pass class CommandError(BaseError): """ Used to indicate errors occurred during command execution. """ pass class NoCommandError(BaseError): """ Used to indicate an inability to find the specified command. """ pass gajim-gajim-1.1.3/gajim/command_system/framework.py000066400000000000000000000303451345766322700223740ustar00rootroot00000000000000# Copyright (C) 2009-2010 Alexander Cherniuk # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ Provides a tiny framework with simple, yet powerful and extensible architecture to implement commands in a straight and flexible, declarative way. """ from types import FunctionType from inspect import getargspec, getdoc from gajim.command_system.dispatcher import Host, Container from gajim.command_system.dispatcher import get_command, list_commands from gajim.command_system.mapping import parse_arguments, adapt_arguments from gajim.command_system.errors import DefinitionError, CommandError, NoCommandError class CommandHost(metaclass=Host): """ Command host is a hub between numerous command processors and command containers. Aimed to participate in a dispatching process in order to provide clean and transparent architecture. The AUTOMATIC class variable, which must be defined by a command host, specifies whether the command host should be automatically dispatched and enabled by the dispatcher or not. """ __metaclass__ = Host class CommandContainer(metaclass=Container): """ Command container is an entity which holds defined commands, allowing them to be dispatched and processed correctly. Each command container may be bound to a one or more command hosts. The AUTOMATIC class variable, which must be defined by a command processor, specifies whether the command processor should be automatically dispatched and enabled by the dispatcher or not. Bounding is controlled by the HOSTS class variable, which must be defined by the command container. This variable should contain a sequence of hosts to bound to, as a tuple or list. """ __metaclass__ = Container class CommandProcessor: """ Command processor is an immediate command emitter. It does not participate in the dispatching process directly, but must define a host to bound to. Bounding is controlled by the COMMAND_HOST variable, which must be defined in the body of the command processor. This variable should be set to a specific command host. """ # This defines a command prefix (or an initializer), which should # precede a text in order for it to be processed as a command. COMMAND_PREFIX = '/' def process_as_command(self, text): """ Try to process text as a command. Returns True if it has been processed as a command and False otherwise. """ # pylint: disable=assignment-from-no-return prefix = text.startswith(self.COMMAND_PREFIX) length = len(text) > len(self.COMMAND_PREFIX) if not (prefix and length): return False body = text[len(self.COMMAND_PREFIX):] body = body.strip() parts = body.split(None, 1) name, arguments = parts if len(parts) > 1 else (parts[0], None) flag = self.looks_like_command(text, body, name, arguments) if flag is not None: return flag self.execute_command(name, arguments) return True def execute_command(self, name, arguments): cmd = self.get_command(name) args, opts = parse_arguments(arguments) if arguments else ([], []) args, kwargs = adapt_arguments(cmd, arguments, args, opts) if self.command_preprocessor(cmd, name, arguments, args, kwargs): return value = cmd(self, *args, **kwargs) self.command_postprocessor(cmd, name, arguments, args, kwargs, value) def command_preprocessor(self, cmd, name, arguments, args, kwargs): """ Redefine this method in the subclass to execute custom code before command gets executed. If returns True then command execution will be interrupted and command will not be executed. """ pass def command_postprocessor(self, cmd, name, arguments, args, kwargs, value): """ Redefine this method in the subclass to execute custom code after command gets executed. """ pass def looks_like_command(self, text, body, name, arguments): """ This hook is being called before any processing, but after it was determined that text looks like a command. If returns value other then None - then further processing will be interrupted and that value will be used to return from process_as_command. """ pass def get_command(self, name): cmd = get_command(self.COMMAND_HOST, name) if not cmd: raise NoCommandError("Command does not exist", name=name) return cmd def list_commands(self): commands = list_commands(self.COMMAND_HOST) commands = dict(commands) return sorted(set(commands.values()), key=lambda k: k.__repr__()) class Command: def __init__(self, handler, *names, **properties): self.handler = handler self.names = names # Automatically set all the properties passed to a constructor # by the command decorator. for key, value in properties.items(): setattr(self, key, value) def __call__(self, *args, **kwargs): try: return self.handler(*args, **kwargs) # This allows to use a shortcut way of raising an exception # inside a handler. That is to raise a CommandError without # command or name attributes set. They will be set to a # corresponding values right here in case if they was not set by # the one who raised an exception. except CommandError as error: if not error.command and not error.name: raise CommandError(error.message, self) raise # This one is a little bit too wide, but as Python does not have # anything more constrained - there is no other choice. Take a # look here if command complains about invalid arguments while # they are ok. except TypeError: raise CommandError("Command received invalid arguments", self) def __repr__(self): return "" % ', '.join(self.names) def __cmp__(self, other): if self.first_name > other.first_name: return 1 if self.first_name < other.first_name: return -1 return 0 @property def first_name(self): return self.names[0] @property def native_name(self): return self.handler.__name__ def extract_documentation(self): """ Extract handler's documentation which is a doc-string and transform it to a usable format. """ return getdoc(self.handler) def extract_description(self): """ Extract handler's description (which is a first line of the documentation). Try to keep them simple yet meaningful. """ documentation = self.extract_documentation() return documentation.split('\n', 1)[0] if documentation else None def extract_specification(self): """ Extract handler's arguments specification, as it was defined preserving their order. """ names, var_args, var_kwargs, defaults = getargspec(self.handler) # pylint: disable=W1505 # Behavior of this code need to be checked. Might yield # incorrect results on some rare occasions. spec_args = names[:-len(defaults) if defaults else len(names)] spec_kwargs = list(zip(names[-len(defaults):], defaults)) if defaults else {} # Removing self from arguments specification. Command handler # should receive the processors as a first argument, which # should be self by the canonical means. if spec_args.pop(0) != 'self': raise DefinitionError("First argument must be self", self) return spec_args, spec_kwargs, var_args, var_kwargs def command(*names, **properties): """ A decorator for defining commands in a declarative way. Provides facilities for setting command's names and properties. Names should contain a set of names (aliases) by which the command can be reached. If no names are given - the native name (the one extracted from the command handler) will be used. If native=True is given (default) and names is non-empty - then the native name of the command will be prepended in addition to the given names. If usage=True is given (default) - then command help will be appended with autogenerated usage info, based of the command handler arguments introspection. If source=True is given - then the first argument of the command will receive the source arguments, as a raw, unprocessed string. The further mapping of arguments and options will not be affected. If raw=True is given - then command considered to be raw and should define positional arguments only. If it defines only one positional argument - this argument will receive all the raw and unprocessed arguments. If the command defines more then one positional argument - then all the arguments except the last one will be processed normally; the last argument will get what is left after the processing as raw and unprocessed string. If empty=True is given - this will allow to call a raw command without arguments. If extra=True is given - then all the extra arguments passed to a command will be collected into a sequence and given to the last positional argument. If overlap=True is given - then all the extra arguments will be mapped as if they were values for the keyword arguments. If expand=True is given (default) - then short, one-letter options will be expanded to a verbose ones, based of the comparison of the first letter. If more then one option with the same first letter is given - then only first one will be used in the expansion. """ names = list(names) native = properties.get('native', True) usage = properties.get('usage', True) source = properties.get('source', False) raw = properties.get('raw', False) empty = properties.get('empty', False) extra = properties.get('extra', False) overlap = properties.get('overlap', False) expand = properties.get('expand', True) if empty and not raw: raise DefinitionError("Empty option can be used only with raw commands") if extra and overlap: raise DefinitionError("Extra and overlap options can not be used together") properties = { 'usage': usage, 'source': source, 'raw': raw, 'extra': extra, 'overlap': overlap, 'empty': empty, 'expand': expand } def decorator(handler): """ Decorator which receives handler as a first argument and then wraps it in the command which then returns back. """ cmd = Command(handler, *names, **properties) # Extract and inject a native name if either no other names are # specified or native property is enabled, while making # sure it is going to be the first one in the list. if not names or native: names.insert(0, cmd.native_name) cmd.names = tuple(names) return cmd # Workaround if we are getting called without parameters. Keep in # mind that in that case - first item in the names will be the # handler. if names and isinstance(names[0], FunctionType): return decorator(names.pop(0)) return decorator def doc(text): """ This decorator is used to bind a documentation (a help) to a command. """ def decorator(target): if isinstance(target, Command): target.handler.__doc__ = text else: target.__doc__ = text return target return decorator gajim-gajim-1.1.3/gajim/command_system/implementation/000077500000000000000000000000001345766322700230455ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/command_system/implementation/__init__.py000066400000000000000000000015321345766322700251570ustar00rootroot00000000000000# Copyright (C) 2009-2010 Alexander Cherniuk # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ The implementation and auxiliary systems which implement the standard Gajim commands and also provide an infrastructure for adding custom commands. """ gajim-gajim-1.1.3/gajim/command_system/implementation/custom.py000066400000000000000000000110621345766322700247310ustar00rootroot00000000000000# Copyright (c) 2009-2010, Alexander Cherniuk (ts33kr@gmail.com) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ This module contains examples of how to create your own commands, by creating a new command container, bounded to a specific command host, and defining a set of commands inside of it. Keep in mind that this module is not being loaded from anywhere, so the code in here will not be executed and commands defined here will not be detected. """ from gajim.common.i18n import _ from gajim.command_system.framework import CommandContainer, command, doc from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands class CustomCommonCommands(CommandContainer): """ The AUTOMATIC class variable, set to a positive value, instructs the command system to automatically discover the command container and enable it. This command container bounds to all three available in the default implementation command hosts. This means that commands defined in this container will be available to all: chat, private chat and a group chat. """ AUTOMATIC = True HOSTS = ChatCommands, PrivateChatCommands, GroupChatCommands @command def dance(self): """ First line of the doc string is called a description and will be programmatically extracted and formatted. After that you can give more help, like explanation of the options. This one will be programmatically extracted and formatted too. After all the documentation - there will be autogenerated (based on the method signature) usage information appended. You can turn it off, if you want. """ return "I don't dance." class CustomChatCommands(CommandContainer): """ This command container bounds only to the ChatCommands command host. Therefore commands defined inside of the container will be available only to a chat. """ AUTOMATIC = True HOSTS = (ChatCommands,) @command("squal", "bawl") def sing(self): """ This command has an additional aliases. It means the command will be available under three names: sing (the native name), squal (the first alias), bawl (the second alias). You can turn off the usage of the native name, if you want, and specify a name or a set of names, as aliases, under which a command will be available. """ return "Buy yourself a stereo." class CustomPrivateChatCommands(CommandContainer): """ This command container bounds only to the PrivateChatCommands command host. Therefore commands defined inside of the container will be available only to a private chat. """ AUTOMATIC = True HOSTS = (PrivateChatCommands,) @command #Example string. Do not translate @doc(_("The same as using a doc-string, except it supports translation")) def make_coffee(self): return "I'm not a coffee machine!" class CustomGroupChatCommands(CommandContainer): """ This command container bounds only to the GroupChatCommands command host. Therefore commands defined inside of the container will be available only to a group chat. """ AUTOMATIC = True HOSTS = (GroupChatCommands,) @command def fetch(self): return "Buy yourself a dog." gajim-gajim-1.1.3/gajim/command_system/implementation/execute.py000066400000000000000000000102041345766322700250560ustar00rootroot00000000000000# Copyright (c) 2010, Alexander Cherniuk (ts33kr@gmail.com) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ Provides facilities to safely execute expressions inside a shell process and capture the resulting output, in an asynchronous fashion, avoiding deadlocks. If the process execution time reaches the threshold - it is forced to terminate. Consists of a tiny framework and a couple of commands as a frontend. """ from subprocess import Popen, PIPE from os.path import expanduser from gi.repository import GLib from gajim.common.i18n import _ from gajim.command_system.framework import CommandContainer, command, doc from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands class Execute(CommandContainer): AUTOMATIC = True HOSTS = ChatCommands, PrivateChatCommands, GroupChatCommands DIRECTORY = "~" POLL_INTERVAL = 100 POLL_COUNT = 5 @command("exec", raw=True) @doc(_("Execute expression inside a shell, show output")) def execute(self, expression): Execute.spawn(self, expression) @classmethod def spawn(cls, processor, expression): pipes = dict(stdout=PIPE, stderr=PIPE) directory = expanduser(cls.DIRECTORY) popen = Popen(expression, shell=True, cwd=directory, **pipes) cls.monitor(processor, popen) @classmethod def monitor(cls, processor, popen): poller = cls.poller(processor, popen) GLib.timeout_add(cls.POLL_INTERVAL, next, poller) @classmethod def poller(cls, processor, popen): for _ in range(cls.POLL_COUNT): yield cls.brush(processor, popen) cls.overdue(processor, popen) yield False @classmethod def brush(cls, processor, popen): if popen.poll() is not None: cls.terminated(processor, popen) return False return True @classmethod def terminated(cls, processor, popen): stdout, stderr = cls.fetch(popen) success = popen.returncode == 0 if success and stdout: processor.echo(stdout) elif not success and stderr: processor.echo_error(stderr) @classmethod def overdue(cls, processor, popen): popen.terminate() @classmethod def fetch(cls, popen): data = popen.communicate() return map(cls.clean, data) @staticmethod def clean(text): strip = chr(10) + chr(32) return text.decode().strip(strip) class Show(Execute): @command("sh", raw=True) @doc(_("Execute expression inside a shell, send output")) def show(self, expression): Show.spawn(self, expression) @classmethod def terminated(cls, processor, popen): stdout, stderr = cls.fetch(popen) success = popen.returncode == 0 if success and stdout: processor.send(stdout) elif not success and stderr: processor.echo_error(stderr) gajim-gajim-1.1.3/gajim/command_system/implementation/hosts.py000066400000000000000000000026231345766322700245620ustar00rootroot00000000000000# Copyright (C) 2009-2010 Alexander Cherniuk # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ The module defines a set of command hosts, which are bound to a different command processors, which are the source of commands. """ from gajim.command_system.framework import CommandHost class ChatCommands(CommandHost): """ This command host is bound to the command processor which processes commands from a chat. """ AUTOMATIC = True class PrivateChatCommands(CommandHost): """ This command host is bound to the command processor which processes commands from a private chat. """ AUTOMATIC = True class GroupChatCommands(CommandHost): """ This command host is bound to the command processor which processes commands from a group chat. """ AUTOMATIC = True gajim-gajim-1.1.3/gajim/command_system/implementation/middleware.py000066400000000000000000000157011345766322700255400ustar00rootroot00000000000000# Copyright (c) 2009-2010, Alexander Cherniuk (ts33kr@gmail.com) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ Provides a glue to tie command system framework and the actual code where it would be dropped in. Defines a little bit of scaffolding to support interaction between the two and a few utility methods so you don't need to dig up the code itself to write basic commands. """ from traceback import print_exc from gi.repository import Pango from gajim.common import app from gajim.common.i18n import _ from gajim.command_system.framework import CommandProcessor from gajim.command_system.errors import CommandError, NoCommandError class ChatCommandProcessor(CommandProcessor): """ A basic scaffolding to provide convenient interaction between the command system and chat controls. It will be merged directly into the controls, by ChatCommandProcessor being among superclasses of the controls. """ def process_as_command(self, text): self.command_succeeded = False parents = super(ChatCommandProcessor, self) flag = parents.process_as_command(text) if flag and self.command_succeeded: self.add_history(text) self.clear_input() return flag def execute_command(self, name, arguments): try: parents = super(ChatCommandProcessor, self) parents.execute_command(name, arguments) except NoCommandError as error: details = dict(name=error.name, message=error.message) message = "%(name)s: %(message)s\n" % details message += "Try using the //%(name)s or /say /%(name)s " % details message += "construct if you intended to send it as a text." self.echo_error(message) except CommandError as error: self.echo_error("%s: %s" % (error.name, error.message)) except Exception: self.echo_error(_("Error during command execution!")) print_exc() else: self.command_succeeded = True def looks_like_command(self, text, body, name, arguments): # Command escape stuff goes here. If text was prepended by the # command prefix twice, like //not_a_command (if prefix is set # to /) then it will be escaped, that is sent just as a regular # message with one (only one) prefix removed, so message will be # /not_a_command. if body.startswith(self.COMMAND_PREFIX): self.send(body) return True def command_preprocessor(self, command, name, arguments, args, kwargs): # If command argument contain h or help option - forward it to # the /help command. Don't forget to pass self, as all commands # are unbound. And also don't forget to print output. if 'h' in kwargs or 'help' in kwargs: help_ = self.get_command('help') self.echo(help_(self, name)) return True def command_postprocessor(self, command, name, arguments, args, kwargs, value): # If command returns a string - print it to a user. A convenient # and sufficient in most simple cases shortcut to a using echo. if value and isinstance(value, str): self.echo(value) class CommandTools: """ Contains a set of basic tools and shortcuts you can use in your commands to perform some simple operations. These will be merged directly into the controls, by CommandTools being among superclasses of the controls. """ def __init__(self): self.install_tags() def install_tags(self): buffer_ = self.conv_textview.tv.get_buffer() name = "Monospace" font = Pango.FontDescription(name) command_ok_tag = buffer_.create_tag("command_ok") command_ok_tag.set_property("font-desc", font) command_ok_tag.set_property("foreground", "#3465A4") command_error_tag = buffer_.create_tag("command_error") command_error_tag.set_property("font-desc", font) command_error_tag.set_property("foreground", "#F57900") def shift_line(self): buffer_ = self.conv_textview.tv.get_buffer() iter_ = buffer_.get_end_iter() if iter_.ends_line() and not iter_.is_start(): buffer_.insert_with_tags_by_name(iter_, "\n", "eol") def append_with_tags(self, text, *tags): buffer_ = self.conv_textview.tv.get_buffer() iter_ = buffer_.get_end_iter() buffer_.insert_with_tags_by_name(iter_, text, *tags) def echo(self, text, tag="command_ok"): """ Print given text to the user, as a regular command output. """ self.shift_line() self.append_with_tags(text, tag) def echo_error(self, text): """ Print given text to the user, as an error command output. """ self.echo(text, "command_error") def send(self, text): """ Send a message to the contact. """ self.send_message(text, process_commands=False) def set_input(self, text): """ Set given text into the input. """ buffer = self.msg_textview.get_buffer() buffer.set_text(text) def clear_input(self): """ Clear input. """ self.set_input(str()) def add_history(self, text): """ Add given text to the input history, so user can scroll through it using ctrl + up/down arrow keys. """ self.save_message(text, 'sent') @property def connection(self): """ Get the current connection object. """ return app.connections[self.account] @property def full_jid(self): """ Get a full JID of the contact. """ return self.contact.get_full_jid() gajim-gajim-1.1.3/gajim/command_system/implementation/standard.py000066400000000000000000000342741345766322700252310ustar00rootroot00000000000000# Copyright (C) 2009-2010 Alexander Cherniuk # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ Provides an actual implementation for the standard commands. """ from time import localtime, strftime from datetime import date from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.const import KindConstant from gajim.command_system.errors import CommandError from gajim.command_system.framework import CommandContainer, command, doc from gajim.command_system.mapping import generate_usage from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands class StandardCommonCommands(CommandContainer): """ This command container contains standard commands which are common to all - chat, private chat, group chat. """ AUTOMATIC = True HOSTS = ChatCommands, PrivateChatCommands, GroupChatCommands @command(overlap=True) @doc(_("Show help on a given command or a list of available commands if -a is given")) def help(self, cmd=None, all_=False): if cmd: cmd = self.get_command(cmd) documentation = _(cmd.extract_documentation()) usage = generate_usage(cmd) text = [] if documentation: text.append(documentation) if cmd.usage: text.append(usage) return '\n\n'.join(text) if all_: for cmd_ in self.list_commands(): names = ', '.join(cmd_.names) description = cmd_.extract_description() self.echo("%s - %s" % (names, description)) else: help_ = self.get_command('help') self.echo(help_(self, 'help')) @command(raw=True) @doc(_("Send a message to the contact")) def say(self, message): self.send(message) @command(raw=True) @doc(_("Send action (in the third person) to the current chat")) def me(self, action): self.send("/me %s" % action) @command('lastlog', overlap=True) @doc(_("Show logged messages which mention given text")) def grep(self, text, limit=None): results = app.logger.search_log(self.account, self.contact.jid, text) if not results: raise CommandError(_("%s: Nothing found") % text) if limit: try: results = results[len(results) - int(limit):] except ValueError: raise CommandError(_("Limit must be an integer")) for row in results: contact = row.contact_name if not contact: if row.kind == KindConstant.CHAT_MSG_SENT: contact = app.nicks[self.account] else: contact = self.contact.name time_obj = localtime(row.time) date_obj = date.fromtimestamp(row.time) date_ = strftime('%Y-%m-%d', time_obj) time_ = strftime('%H:%M:%S', time_obj) if date_obj == date.today(): formatted = "[%s] %s: %s" % (time_, contact, row.message) else: formatted = "[%s, %s] %s: %s" % (date_, time_, contact, row.message) self.echo(formatted) @command(raw=True, empty=True) #Do not translate online, away, chat, xa, dnd @doc(_(""" Set the current status Status can be given as one of the following values: online, away, chat, xa, dnd. """)) def status(self, status, message): if status not in ('online', 'away', 'chat', 'xa', 'dnd'): raise CommandError("Invalid status given") for connection in app.connections.values(): if not app.config.get_per('accounts', connection.name, 'sync_with_global_status'): continue if connection.connected < 2: continue connection.change_status(status, message) @command(raw=True, empty=True) @doc(_("Set the current status to away")) def away(self, message): if not message: message = _("Away") for connection in app.connections.values(): if not app.config.get_per('accounts', connection.name, 'sync_with_global_status'): continue if connection.connected < 2: continue connection.change_status('away', message) @command('back', raw=True, empty=True) @doc(_("Set the current status to online")) def online(self, message): if not message: message = _("Available") for connection in app.connections.values(): if not app.config.get_per('accounts', connection.name, 'sync_with_global_status'): continue if connection.connected < 2: continue connection.change_status('online', message) class StandardCommonChatCommands(CommandContainer): """ This command container contains standard commands, which are common to a chat and a private chat only. """ AUTOMATIC = True HOSTS = ChatCommands, PrivateChatCommands @command @doc(_("Clear the text window")) def clear(self): self.conv_textview.clear() @command @doc(_("Send a ping to the contact")) def ping(self): if self.account == app.ZEROCONF_ACC_NAME: raise CommandError(_('Command is not supported for zeroconf accounts')) app.connections[self.account].get_module('Ping').send_ping(self.contact) @command @doc(_("Send DTMF sequence through an open audio session")) def dtmf(self, sequence): if not self.audio_sid: raise CommandError(_("No open audio sessions with the contact")) for tone in sequence: if not (tone in ("*", "#") or tone.isdigit()): raise CommandError(_("%s is not a valid tone") % tone) gjs = self.connection.get_jingle_session session = gjs(self.full_jid, self.audio_sid) content = session.get_content("audio") content.batch_dtmf(sequence) @command @doc(_("Toggle audio session")) def audio(self): if not self.audio_available: raise CommandError(_("Audio sessions are not available")) # An audio session is toggled by inverting the state of the # appropriate button. state = self._audio_button.get_active() self._audio_button.set_active(not state) @command @doc(_("Toggle video session")) def video(self): if not self.video_available: raise CommandError(_("Video sessions are not available")) # A video session is toggled by inverting the state of the # appropriate button. state = self._video_button.get_active() self._video_button.set_active(not state) @command(raw=True) @doc(_("Send a message to the contact that will attract their attention")) def attention(self, message): self.send_message(message, process_commands=False, attention=True) class StandardChatCommands(CommandContainer): """ This command container contains standard commands which are unique to a chat. """ AUTOMATIC = True HOSTS = (ChatCommands,) class StandardPrivateChatCommands(CommandContainer): """ This command container contains standard commands which are unique to a private chat. """ AUTOMATIC = True HOSTS = (PrivateChatCommands,) class StandardGroupChatCommands(CommandContainer): """ This command container contains standard commands which are unique to a group chat. """ AUTOMATIC = True HOSTS = (GroupChatCommands,) @command @doc(_("Clear the text window")) def clear(self): self.conv_textview.clear() self.gc_count_nicknames_colors = -1 self.gc_custom_colors = {} @command(raw=True) @doc(_("Change your nickname in a group chat")) def nick(self, new_nick): try: new_nick = helpers.parse_resource(new_nick) except Exception: raise CommandError(_("Invalid nickname")) self.connection.join_gc(new_nick, self.room_jid, None, change_nick=True) self.new_nick = new_nick @command('query', raw=True) @doc(_("Open a private chat window with a specified occupant")) def chat(self, nick): nicks = app.contacts.get_nick_list(self.account, self.room_jid) if nick in nicks: self.on_send_pm(nick=nick) else: raise CommandError(_("Nickname not found")) @command('msg', raw=True) @doc(_("Open a private chat window with a specified occupant and send him a message")) def message(self, nick, a_message): nicks = app.contacts.get_nick_list(self.account, self.room_jid) if nick in nicks: self.on_send_pm(nick=nick, msg=a_message) else: raise CommandError(_("Nickname not found")) @command(raw=True, empty=True) @doc(_("Display or change a group chat topic")) def topic(self, new_topic): if new_topic: self.connection.get_module('MUC').set_subject( self.room_jid, new_topic) else: return self.subject @command(raw=True, empty=True) @doc(_("Invite a user to a room for a reason")) def invite(self, jid, reason): self.connection.get_module('MUC').invite(self.room_jid, jid, reason) return _("Invited %(jid)s to %(room_jid)s") % {'jid': jid, 'room_jid': self.room_jid} @command(raw=True, empty=True) @doc(_("Join a group chat given by a JID")) def join(self, jid): if '@' not in jid: jid = jid + '@' + app.get_server_from_jid(self.room_jid) app.interface.join_gc_minimal(self.account, room_jid=jid) @command('part', 'close', raw=True, empty=True) @doc(_("Leave the groupchat, optionally giving a reason, and close tab or window")) def leave(self, reason): self.parent_win.remove_tab(self, self.parent_win.CLOSE_COMMAND, reason) @command(raw=True, empty=True) @doc(_(""" Ban user by a nick or a JID from a groupchat If given nickname is not found it will be treated as a JID. """)) def ban(self, who, reason=''): if who in app.contacts.get_nick_list(self.account, self.room_jid): contact = app.contacts.get_gc_contact(self.account, self.room_jid, who) who = contact.jid self.connection.get_module('MUC').set_affiliation( self.room_jid, {who: {'affiliation': 'outcast', 'reason': reason}}) @command(raw=True, empty=True) @doc(_("Kick user by a nick from a groupchat")) def kick(self, who, reason): if not who in app.contacts.get_nick_list(self.account, self.room_jid): raise CommandError(_("Nickname not found")) self.connection.get_module('MUC').set_role( self.room_jid, who, 'none', reason or str()) @command(raw=True) #Do not translate moderator, participant, visitor, none @doc(_("""Set occupant role in group chat. Role can be given as one of the following values: moderator, participant, visitor, none""")) def role(self, who, role): if role not in ('moderator', 'participant', 'visitor', 'none'): raise CommandError(_("Invalid role given")) if not who in app.contacts.get_nick_list(self.account, self.room_jid): raise CommandError(_("Nickname not found")) self.connection.get_module('MUC').set_role(self.room_jid, who, role) @command(raw=True) #Do not translate owner, admin, member, outcast, none @doc(_("""Set occupant affiliation in group chat. Affiliation can be given as one of the following values: owner, admin, member, outcast, none""")) def affiliate(self, who, affiliation): if affiliation not in ('owner', 'admin', 'member', 'outcast', 'none'): raise CommandError(_("Invalid affiliation given")) if who not in app.contacts.get_nick_list(self.account, self.room_jid): raise CommandError(_("Nickname not found")) contact = app.contacts.get_gc_contact(self.account, self.room_jid, who) self.connection.get_module('MUC').set_affiliation( self.room_jid, {contact.jid: {'affiliation': affiliation}}) @command @doc(_("Display names of all group chat occupants")) def names(self, verbose=False): ggc = app.contacts.get_gc_contact gnl = app.contacts.get_nick_list get_contact = lambda nick: ggc(self.account, self.room_jid, nick) get_role = lambda nick: get_contact(nick).role nicks = gnl(self.account, self.room_jid) nicks = sorted(nicks) nicks = sorted(nicks, key=get_role) if not verbose: return ", ".join(nicks) for nick in nicks: contact = get_contact(nick) role = helpers.get_uf_role(contact.role) affiliation = helpers.get_uf_affiliation(contact.affiliation) self.echo("%s - %s - %s" % (nick, role, affiliation)) @command('ignore', raw=True) @doc(_("Forbid an occupant to send you public or private messages")) def block(self, who): self.on_block(None, who) @command('unignore', raw=True) @doc(_("Allow an occupant to send you public or private messages")) def unblock(self, who): self.on_unblock(None, who) @command @doc(_("Send a ping to the contact")) def ping(self, nick): if self.account == app.ZEROCONF_ACC_NAME: raise CommandError(_('Command is not supported for zeroconf accounts')) gc_c = app.contacts.get_gc_contact(self.account, self.room_jid, nick) app.connections[self.account].get_module('Ping').send_ping(gc_c) gajim-gajim-1.1.3/gajim/command_system/mapping.py000066400000000000000000000325631345766322700220360ustar00rootroot00000000000000# Copyright (C) 2009-2010 Alexander Cherniuk # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ The module contains routines to parse command arguments and map them to the command handler's positional and keyword arguments. Mapping is done in two stages: 1) parse arguments into positional arguments and options; 2) adapt them to the specific command handler according to the command properties. """ import re from operator import itemgetter from gajim.common.i18n import _ from gajim.command_system.errors import DefinitionError, CommandError # Quite complex piece of regular expression logic to parse options and # arguments. Might need some tweaking along the way. ARG_PATTERN = re.compile(r'(\'|")?(?P(?(1).+?|\S+))(?(1)\1)') OPT_PATTERN = re.compile(r'(?[\w-]+)(?:(?:=|\s)(\'|")?(?P(?(2)[^-]+?|[^-\s]+))(?(2)\2))?') # Option keys needs to be encoded to a specific encoding as Python does # not allow to expand dictionary with raw Unicode strings as keys from a # **kwargs. KEY_ENCODING = 'UTF-8' # Defines how complete representation of command usage (generated based # on command handler argument specification) will be rendered. USAGE_PATTERN = 'Usage: %s %s' def parse_arguments(arguments): """ Simple yet effective and sufficient in most cases parser which parses command arguments and returns them as two lists. First list represents positional arguments as (argument, position), and second representing options as (key, value, position) tuples, where position is a (start, end) span tuple of where it was found in the string. Options may be given in --long or -short format. As --option=value or --option value or -option value. Keys without values will get None as value. Arguments and option values that contain spaces may be given as 'one two three' or "one two three"; that is between single or double quotes. """ args, opts = [], [] def intersects_opts(given_start, given_end): """ Check if given span intersects with any of options. """ for _key, _value, (start, end) in opts: if given_start >= start and given_end <= end: return True return False def intersects_args(given_start, given_end): """ Check if given span intersects with any of arguments. """ for _arg, (start, end) in args: if given_start >= start and given_end <= end: return True return False for match in re.finditer(OPT_PATTERN, arguments): if match: key = match.group('key') value = match.group('value') or None position = match.span() opts.append((key, value, position)) for match in re.finditer(ARG_PATTERN, arguments): if match: body = match.group('body') position = match.span() args.append((body, position)) # Primitive but sufficiently effective way of disposing of # conflicted sectors. Remove any arguments that intersect with # options. for arg, position in args[:]: if intersects_opts(*position): args.remove((arg, position)) # Primitive but sufficiently effective way of disposing of # conflicted sectors. Remove any options that intersect with # arguments. for key, value, position in opts[:]: if intersects_args(*position): opts.remove((key, value, position)) return args, opts def adapt_arguments(command, arguments, args, opts): """ Adapt args and opts got from the parser to a specific handler by means of arguments specified on command definition. That is transform them to *args and **kwargs suitable for passing to a command handler. Dashes (-) in the option names will be converted to underscores. So you can map --one-more-option to a one_more_option=None. If the initial value of a keyword argument is a boolean (False in most cases) - then this option will be treated as a switch, that is an option which does not take an argument. If a switch is followed by an argument - then this argument will be treated just like a normal positional argument. """ spec_args, spec_kwargs, var_args, _var_kwargs = command.extract_specification() norm_kwargs = dict(spec_kwargs) # Quite complex piece of neck-breaking logic to extract raw # arguments if there is more, then one positional argument specified # by the command. In case if it's just one argument which is the # collector - this is fairly easy. But when it's more then one # argument - the neck-breaking logic of how to retrieve residual # arguments as a raw, all in one piece string, kicks in. if command.raw: if arguments: spec_fix = 1 if command.source else 0 spec_len = len(spec_args) - spec_fix arguments_end = len(arguments) - 1 # If there are any optional arguments given they should be # either an unquoted positional argument or part of the raw # argument. So we find all optional arguments that can # possibly be unquoted argument and append them as is to the # args. for key, value, (start, end) in opts[:spec_len]: if value: end -= len(value) + 1 args.append((arguments[start:end], (start, end))) args.append((value, (end, end + len(value) + 1))) else: args.append((arguments[start:end], (start, end))) # We need in-place sort here because after manipulations # with options order of arguments might be wrong and we just # can't have more complex logic to not let that happen. args.sort(key=itemgetter(1)) if spec_len > 1: try: _stopper, (start, end) = args[spec_len - 2] except IndexError: raise CommandError(_("Missing arguments"), command) # The essential point of the whole play. After # boundaries are being determined (supposedly correct) # we separate raw part from the rest of arguments, which # should be normally processed. raw = arguments[end:] raw = raw.strip() or None if not raw and not command.empty: raise CommandError(_("Missing arguments"), command) # Discard residual arguments and all of the options as # raw command does not support options and if an option # is given it is rather a part of a raw argument. args = args[:spec_len - 1] opts = [] args.append((raw, (end, arguments_end))) else: # Substitute all of the arguments with only one, which # contain raw and unprocessed arguments as a string. And # discard all the options, as raw command does not # support them. args = [(arguments, (0, arguments_end))] opts = [] else: if command.empty: args.append((None, (0, 0))) else: raise CommandError(_("Missing arguments"), command) # The first stage of transforming options we have got to a format # that can be used to associate them with declared keyword # arguments. Substituting dashes (-) in their names with # underscores (_). for index, (key, value, position) in enumerate(opts): if '-' in key: opts[index] = (key.replace('-', '_'), value, position) # The second stage of transforming options to an associable state. # Expanding short, one-letter options to a verbose ones, if # corresponding opt-in has been given. if command.expand: expanded = [] for spec_key in norm_kwargs.keys(): letter = spec_key[0] if len(spec_key) > 1 else None if letter and letter not in expanded: for index, (key, value, position) in enumerate(opts): if key == letter: expanded.append(letter) opts[index] = (spec_key, value, position) break # Detect switches and set their values accordingly. If any of them # carries a value - append it to args. for index, (key, value, position) in enumerate(opts): if isinstance(norm_kwargs.get(key), bool): opts[index] = (key, True, position) if value: args.append((value, position)) # Sorting arguments and options (just to be sure) in regarding to # their positions in the string. args.sort(key=itemgetter(1)) opts.sort(key=itemgetter(2)) # Stripping down position information supplied with arguments and # options as it won't be needed again. args = list(map(lambda t: t[0], args)) opts = list(map(lambda t: (t[0], t[1]), opts)) # If command has extra option enabled - collect all extra arguments # and pass them to a last positional argument command defines as a # list. if command.extra: if not var_args: spec_fix = 1 if not command.source else 2 spec_len = len(spec_args) - spec_fix extra = args[spec_len:] args = args[:spec_len] args.append(extra) else: raise DefinitionError("Can not have both, extra and *args") # Detect if positional arguments overlap keyword arguments. If so # and this is allowed by command options - then map them directly to # their options, so they can get proper further processing. spec_fix = 1 if command.source else 0 spec_len = len(spec_args) - spec_fix if len(args) > spec_len: if command.overlap: overlapped = args[spec_len:] args = args[:spec_len] for arg, spec_key, _spec_value in zip(overlapped, spec_kwargs): opts.append((spec_key, arg)) else: raise CommandError(_("Too many arguments"), command) # Detect every switch and ensure it will not receive any arguments. # Normally this does not happen unless overlapping is enabled. for key, value in opts: initial = norm_kwargs.get(key) if isinstance(initial, bool): if not isinstance(value, bool): raise CommandError("%s: Switch can not take an argument" % key, command) # Inject the source arguments as a string as a first argument, if # command has enabled the corresponding option. if command.source: args.insert(0, arguments) # Return *args and **kwargs in the form suitable for passing to a # command handler and being expanded. return tuple(args), dict(opts) def generate_usage(command, complete=True): """ Extract handler's arguments specification and wrap them in a human-readable format usage information. If complete is given - then USAGE_PATTERN will be used to render the specification completely. """ spec_args, spec_kwargs, var_args, var_kwargs = command.extract_specification() # Remove some special positional arguments from the specification, # but store their names so they can be used for usage info # generation. _sp_source = spec_args.pop(0) if command.source else None sp_extra = spec_args.pop() if command.extra else None kwargs = [] letters = [] for key, value in spec_kwargs: letter = key[0] key = key.replace('_', '-') if isinstance(value, bool): value = str() else: value = '=%s' % value if letter not in letters: kwargs.append('-(-%s)%s%s' % (letter, key[1:], value)) letters.append(letter) else: kwargs.append('--%s%s' % (key, value)) usage = str() args = str() if command.raw: spec_len = len(spec_args) - 1 if spec_len: args += ('<%s>' % ', '.join(spec_args[:spec_len])) + ' ' args += ('(|%s|)' if command.empty else '|%s|') % spec_args[-1] else: if spec_args: args += '<%s>' % ', '.join(spec_args) if var_args or sp_extra: args += (' ' if spec_args else str()) + '<<%s>>' % (var_args or sp_extra) usage += args if kwargs or var_kwargs: if kwargs: usage += (' ' if args else str()) + '[%s]' % ', '.join(kwargs) if var_kwargs: usage += (' ' if args else str()) + '[[%s]]' % var_kwargs # Native name will be the first one if it is included. Otherwise, # names will be in the order they were specified. if len(command.names) > 1: names = '%s (%s)' % (command.first_name, ', '.join(command.names[1:])) else: names = command.first_name return USAGE_PATTERN % (names, usage) if complete else usage gajim-gajim-1.1.3/gajim/command_system/tools.py000066400000000000000000000031001345766322700215240ustar00rootroot00000000000000# Copyright (c) 2010, Alexander Cherniuk (ts33kr@gmail.com) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. def remove(sequence, target): if isinstance(sequence, list): if target in sequence: sequence.remove(target) elif isinstance(sequence, dict): if target in sequence: del sequence[target] gajim-gajim-1.1.3/gajim/common/000077500000000000000000000000001345766322700162665ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/__init__.py000066400000000000000000000000001345766322700203650ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/account.py000066400000000000000000000020021345766322700202660ustar00rootroot00000000000000# Copyright (C) 2009 Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . class Account: def __init__(self, name, contacts, gc_contacts): self.name = name self.contacts = contacts self.gc_contacts = gc_contacts def change_contact_jid(self, old_jid, new_jid): self.contacts.change_contact_jid(old_jid, new_jid) def __repr__(self): return self.name def __hash__(self): return hash(self.name) gajim-gajim-1.1.3/gajim/common/app.py000066400000000000000000000527431345766322700174330ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Dimitur Kirov # Travis Shirk # Nikos Kouremenos # Copyright (C) 2006 Junglecow J # Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007-2008 Brendan Taylor # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Any # pylint: disable=unused-import from typing import Dict # pylint: disable=unused-import from typing import List # pylint: disable=unused-import from typing import Optional # pylint: disable=unused-import from typing import cast import os import sys import logging import uuid from pathlib import Path from distutils.version import LooseVersion as V from collections import namedtuple import nbxmpp from gi.repository import Gdk import gajim from gajim.common import config as c_config from gajim.common import configpaths from gajim.common import ged as ged_module from gajim.common.const import Display from gajim.common.contacts import LegacyContactsAPI from gajim.common.events import Events from gajim.common.types import NetworkEventsControllerT # pylint: disable=unused-import from gajim.common.types import InterfaceT # pylint: disable=unused-import from gajim.common.types import LoggerT # pylint: disable=unused-import from gajim.common.types import ConnectionT # pylint: disable=unused-import interface = cast(InterfaceT, None) thread_interface = lambda *args: None # Interface to run a thread and then a callback config = c_config.Config() version = gajim.__version__ connections = {} # type: Dict[str, ConnectionT] avatar_cache = {} # type: Dict[str, Dict[str, Any]] ipython_window = None app = None # Gtk.Application ged = ged_module.GlobalEventsDispatcher() # Global Events Dispatcher nec = cast(NetworkEventsControllerT, None) plugin_manager = None # Plugins Manager logger = cast(LoggerT, None) # For backwards compatibility needed # some plugins use that gajimpaths = configpaths.gajimpaths RecentGroupchat = namedtuple('RecentGroupchat', ['room', 'server', 'nickname']) css_config = None os_info = None # used to cache os information transport_type = {} # type: Dict[str, str] # dict of time of the latest incoming message per jid # {acct1: {jid1: time1, jid2: time2}, } last_message_time = {} # type: Dict[str, Dict[str, float]] contacts = LegacyContactsAPI() # tell if we are connected to the room or not # {acct: {room_jid: True}} gc_connected = {} # type: Dict[str, Dict[str, bool]] # dict of the pass required to enter a room # {room_jid: password} gc_passwords = {} # type: Dict[str, str] # dict of rooms that must be automaticaly configured # and for which we have a list of invities # {account: {room_jid: {'invities': []}}} automatic_rooms = {} # type: Dict[str, Dict[str, Dict[str, List[str]]]] # dict of groups, holds if they are expanded or not groups = {} # type: Dict[str, Dict[str, Dict[str, bool]]] # list of contacts that has just signed in newly_added = {} # type: Dict[str, List[str]] # list of contacts that has just signed out to_be_removed = {} # type: Dict[str, List[str]] events = Events() notification = None # list of our nick names in each account nicks = {} # type: Dict[str, str] # should we block 'contact signed in' notifications for this account? # this is only for the first 30 seconds after we change our show # to something else than offline # can also contain account/transport_jid to block notifications for contacts # from this transport block_signed_in_notifications = {} # type: Dict[str, bool] # type of each connection (ssl, tls, tcp, ...) con_types = {} # type: Dict[str, Optional[str]] # whether we pass auto away / xa or not #'off': don't use sleeper for this account #'online': online and use sleeper #'autoaway': autoaway and use sleeper #'autoxa': autoxa and use sleeper sleeper_state = {} # type: Dict[str, str] status_before_autoaway = {} # type: Dict[str, str] # Is Gnome configured to activate on single click ? single_click = False SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd', 'invisible', 'error'] # zeroconf account name ZEROCONF_ACC_NAME = 'Local' # These will be set in app.gui_interface. idlequeue = None # type: nbxmpp.idlequeue.IdleQueue socks5queue = None gupnp_igd = None gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'} gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE, nbxmpp.NS_MUC, nbxmpp.NS_MUC_USER, nbxmpp.NS_MUC_ADMIN, nbxmpp.NS_MUC_OWNER, nbxmpp.NS_MUC_CONFIG, nbxmpp.NS_COMMANDS, nbxmpp.NS_DISCO_INFO, 'ipv6', 'jabber:iq:gateway', nbxmpp.NS_LAST, nbxmpp.NS_PRIVACY, nbxmpp.NS_PRIVATE, nbxmpp.NS_REGISTER, nbxmpp.NS_VERSION, nbxmpp.NS_DATA, nbxmpp.NS_ENCRYPTED, 'msglog', 'sslc2s', 'stringprep', nbxmpp.NS_PING, nbxmpp.NS_TIME_REVISED, nbxmpp.NS_SSN, nbxmpp.NS_MOOD, nbxmpp.NS_ACTIVITY, nbxmpp.NS_NICK, nbxmpp.NS_ROSTERX, nbxmpp.NS_SECLABEL, nbxmpp.NS_HASHES_2, nbxmpp.NS_HASHES_MD5, nbxmpp.NS_HASHES_SHA1, nbxmpp.NS_HASHES_SHA256, nbxmpp.NS_HASHES_SHA512, nbxmpp.NS_CONFERENCE, nbxmpp.NS_CORRECT, nbxmpp.NS_EME, 'urn:xmpp:avatar:metadata+notify'] # Optional features gajim supports per account gajim_optional_features = {} # type: Dict[str, List[str]] # Capabilities hash per account caps_hash = {} # type: Dict[str, List[str]] _dependencies = { 'PYTHON-DBUS': False, 'PYBONJOUR': False, 'PYGPG': False, 'GPG_BINARY': False, 'FARSTREAM': False, 'GEOCLUE': False, 'UPNP': False, 'PYCURL': False, 'GSPELL': False, 'IDLE': False, } def is_installed(dependency): if dependency == 'GPG': # Alias for checking python-gnupg and the GPG binary return _dependencies['PYGPG'] and _dependencies['GPG_BINARY'] if dependency == 'ZEROCONF': # Alias for checking zeroconf libs return _dependencies['PYTHON-DBUS'] or _dependencies['PYBONJOUR'] return _dependencies[dependency] def is_flatpak(): return gajim.IS_FLATPAK def is_display(display): # XWayland reports as Display X11, so try with env var is_wayland = os.environ.get('XDG_SESSION_TYPE') == 'wayland' if is_wayland and display == Display.WAYLAND: return True default = Gdk.Display.get_default() if default is None: log('gajim').warning('Could not determine window manager') return False return default.__class__.__name__ == display.value def disable_dependency(dependency): _dependencies[dependency] = False def detect_dependencies(): import gi # ZEROCONF try: import pybonjour # pylint: disable=unused-variable _dependencies['PYBONJOUR'] = True except Exception: pass try: import dbus # pylint: disable=unused-variable _dependencies['PYTHON-DBUS'] = True except Exception: pass # python-gnupg try: import gnupg # We need https://pypi.python.org/pypi/python-gnupg # but https://pypi.python.org/pypi/gnupg shares the same package name. # It cannot be used as a drop-in replacement. # We test with a version check if python-gnupg is installed as it is # on a much lower version number than gnupg # Also we need at least python-gnupg 0.3.8 v_gnupg = gnupg.__version__ if V(v_gnupg) < V('0.3.8') or V(v_gnupg) > V('1.0.0'): log('gajim').info('Gajim needs python-gnupg >= 0.3.8') raise ImportError _dependencies['PYGPG'] = True except ImportError: pass # GPG BINARY import subprocess def test_gpg(binary='gpg'): if os.name == 'nt': gpg_cmd = binary + ' -h >nul 2>&1' else: gpg_cmd = binary + ' -h >/dev/null 2>&1' if subprocess.call(gpg_cmd, shell=True): return False return True if test_gpg(binary='gpg2'): _dependencies['GPG_BINARY'] = 'gpg2' elif test_gpg(binary='gpg'): _dependencies['GPG_BINARY'] = 'gpg' # FARSTREAM try: if os.name == 'nt': root_path = Path(sys.executable).parents[1] fs_plugin_path = str(root_path / 'lib' / 'farstream-0.2') gst_plugin_path = str(root_path / 'lib' / 'gstreamer-1.0') os.environ['FS_PLUGIN_PATH'] = fs_plugin_path os.environ['GST_PLUGIN_PATH'] = gst_plugin_path gi.require_version('Farstream', '0.2') from gi.repository import Farstream gi.require_version('Gst', '1.0') from gi.repository import Gst try: Gst.init(None) conference = Gst.ElementFactory.make('fsrtpconference', None) conference.new_session(Farstream.MediaType.AUDIO) except Exception as error: log('gajim').info(error) _dependencies['FARSTREAM'] = True except (ImportError, ValueError): pass # GEOCLUE try: gi.require_version('Geoclue', '2.0') from gi.repository import Geoclue # pylint: disable=unused-variable _dependencies['GEOCLUE'] = True except (ImportError, ValueError): pass # UPNP try: gi.require_version('GUPnPIgd', '1.0') from gi.repository import GUPnPIgd global gupnp_igd gupnp_igd = GUPnPIgd.SimpleIgd() _dependencies['UPNP'] = True except ValueError: pass # PYCURL try: import pycurl # pylint: disable=unused-variable _dependencies['PYCURL'] = True except ImportError: pass # IDLE try: from gajim.common import idle if idle.Monitor.is_available(): _dependencies['IDLE'] = True except Exception: pass # GSPELL try: gi.require_version('Gspell', '1') from gi.repository import Gspell langs = Gspell.language_get_available() for lang in langs: log('gajim').info('%s (%s) dict available', lang.get_name(), lang.get_code()) if langs: _dependencies['GSPELL'] = True except (ImportError, ValueError): pass # Print results for dep, val in _dependencies.items(): log('gajim').info('%-13s %s', dep, val) def get_gpg_binary(): return _dependencies['GPG_BINARY'] def get_an_id(): return str(uuid.uuid4()) def get_nick_from_jid(jid): pos = jid.find('@') return jid[:pos] def get_server_from_jid(jid): pos = jid.find('@') + 1 # after @ return jid[pos:] def get_name_and_server_from_jid(jid): name = get_nick_from_jid(jid) server = get_server_from_jid(jid) return name, server def get_room_and_nick_from_fjid(jid): # fake jid is the jid for a contact in a room # gaim@conference.jabber.no/nick/nick-continued # return ('gaim@conference.jabber.no', 'nick/nick-continued') l = jid.split('/', 1) if len(l) == 1: # No nick l.append('') return l def get_real_jid_from_fjid(account, fjid): """ Return real jid or returns None, if we don't know the real jid """ room_jid, nick = get_room_and_nick_from_fjid(fjid) if not nick: # It's not a fake_jid, it is a real jid return fjid # we return the real jid real_jid = fjid if interface.msg_win_mgr.get_gc_control(room_jid, account): # It's a pm, so if we have real jid it's in contact.jid gc_contact = contacts.get_gc_contact(account, room_jid, nick) if not gc_contact: return # gc_contact.jid is None when it's not a real jid (we don't know real jid) real_jid = gc_contact.jid return real_jid def get_room_from_fjid(jid): return get_room_and_nick_from_fjid(jid)[0] def get_contact_name_from_jid(account, jid): c = contacts.get_first_contact_from_jid(account, jid) return c.name def get_jid_without_resource(jid): return jid.split('/')[0] def construct_fjid(room_jid, nick): # fake jid is the jid for a contact in a room # gaim@conference.jabber.org/nick return room_jid + '/' + nick def get_resource_from_jid(jid): jids = jid.split('/', 1) if len(jids) > 1: return jids[1] # abc@doremi.org/res/res-continued return '' def get_number_of_accounts(): """ Return the number of ALL accounts """ return len(connections.keys()) def get_number_of_connected_accounts(accounts_list=None): """ Returns the number of CONNECTED accounts. Uou can optionally pass an accounts_list and if you do those will be checked, else all will be checked """ connected_accounts = 0 if accounts_list is None: accounts = connections.keys() else: accounts = accounts_list for account in accounts: if account_is_connected(account): connected_accounts = connected_accounts + 1 return connected_accounts def get_connected_accounts(): """ Returns a list of CONNECTED accounts """ account_list = [] for account in connections: if account_is_connected(account): account_list.append(account) return account_list def get_enabled_accounts_with_labels(exclude_local=True, connected_only=False, private_storage_only=False): """ Returns a list with [account, account_label] entries. Order by account_label """ accounts = [] for acc in connections: if exclude_local and account_is_zeroconf(acc): continue if connected_only and not account_is_connected(acc): continue if private_storage_only and not account_supports_private_storage(acc): continue accounts.append([acc, get_account_label(acc)]) accounts.sort(key=lambda xs: str.lower(xs[1])) return accounts def get_account_label(account): return config.get_per('accounts', account, 'account_label') or account def account_is_zeroconf(account): return connections[account].is_zeroconf def account_supports_private_storage(account): # If Delimiter module is not available we can assume # Private Storage is not available return connections[account].get_module('Delimiter').available def account_is_connected(account): if account not in connections: return False # 0 is offline, 1 is connecting return connections[account].connected > 1 def is_invisible(account): return SHOW_LIST[connections[account].connected] == 'invisible' def account_is_disconnected(account): return not account_is_connected(account) def zeroconf_is_connected(): return account_is_connected(ZEROCONF_ACC_NAME) and \ config.get_per('accounts', ZEROCONF_ACC_NAME, 'is_zeroconf') def in_groupchat(account, room_jid): if room_jid not in gc_connected[account]: return False return gc_connected[account][room_jid] def get_number_of_securely_connected_accounts(): """ Return the number of the accounts that are SSL/TLS connected """ num_of_secured = 0 for account in connections: if account_is_securely_connected(account): num_of_secured += 1 return num_of_secured def account_is_securely_connected(account): if not account_is_connected(account): return False return con_types.get(account) in ('tls', 'ssl') def get_transport_name_from_jid(jid, use_config_setting=True): """ Returns 'gg', 'irc' etc If JID is not from transport returns None. """ #FIXME: jid can be None! one TB I saw had this problem: # in the code block # it is a groupchat presence in handle_event_notify # jid was None. Yann why? if not jid or (use_config_setting and not config.get('use_transports_iconsets')): return host = get_server_from_jid(jid) if host in transport_type: return transport_type[host] # host is now f.e. icq.foo.org or just icq (sometimes on hacky transports) host_splitted = host.split('.') if host_splitted: # now we support both 'icq.' and 'icq' but not icqsucks.org host = host_splitted[0] if host in ('irc', 'icq', 'sms', 'weather', 'mrim', 'facebook'): return host if host == 'gg': return 'gadu-gadu' if host == 'jit': return 'icq' if host == 'facebook': return 'facebook' return None def jid_is_transport(jid): # if not '@' or '@' starts the jid then it is transport if jid.find('@') <= 0: return True return False def get_jid_from_account(account_name): """ Return the jid we use in the given account """ name = config.get_per('accounts', account_name, 'name') hostname = config.get_per('accounts', account_name, 'hostname') jid = name + '@' + hostname return jid def get_account_from_jid(jid): for account in config.get_per('accounts'): if jid == get_jid_from_account(account): return account def get_our_jids(): """ Returns a list of the jids we use in our accounts """ our_jids = list() for account in contacts.get_accounts(): our_jids.append(get_jid_from_account(account)) return our_jids def get_hostname_from_account(account_name, use_srv=False): """ Returns hostname (if custom hostname is used, that is returned) """ if use_srv and connections[account_name].connected_hostname: return connections[account_name].connected_hostname if config.get_per('accounts', account_name, 'use_custom_host'): return config.get_per('accounts', account_name, 'custom_host') return config.get_per('accounts', account_name, 'hostname') def get_notification_image_prefix(jid): """ Returns the prefix for the notification images """ transport_name = get_transport_name_from_jid(jid) if transport_name in ('icq', 'facebook'): prefix = transport_name else: prefix = 'jabber' return prefix def get_name_from_jid(account, jid): """ Return from JID's shown name and if no contact returns jids """ contact = contacts.get_first_contact_from_jid(account, jid) if contact: actor = contact.get_shown_name() else: actor = jid return actor def get_muc_domain(account): return connections[account].muc_jid.get('jabber', None) def get_recent_groupchats(account): recent_groupchats = config.get_per( 'accounts', account, 'recent_groupchats').split() recent_list = [] for groupchat in recent_groupchats: jid = nbxmpp.JID(groupchat) recent = RecentGroupchat( jid.getNode(), jid.getDomain(), jid.getResource()) recent_list.append(recent) return recent_list def add_recent_groupchat(account, room_jid, nickname): recent = config.get_per( 'accounts', account, 'recent_groupchats').split() full_jid = room_jid + '/' + nickname if full_jid in recent: recent.remove(full_jid) recent.insert(0, full_jid) if len(recent) > 10: recent = recent[0:9] config_value = ' '.join(recent) config.set_per( 'accounts', account, 'recent_groupchats', config_value) def get_priority(account, show): """ Return the priority an account must have """ if not show: show = 'online' if show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible') and \ config.get_per('accounts', account, 'adjust_priority_with_status'): prio = config.get_per('accounts', account, 'autopriority_' + show) else: prio = config.get_per('accounts', account, 'priority') if prio < -128: prio = -128 elif prio > 127: prio = 127 return prio def log(domain): if domain != 'gajim': domain = 'gajim.%s' % domain return logging.getLogger(domain) def prefers_app_menu(): if sys.platform == 'darwin': return True if sys.platform == 'win32': return False return app.prefers_app_menu() def get_app_window(cls, account=None): for win in app.get_windows(): if isinstance(cls, str): if type(win).__name__ == cls: if account is not None: if account != win.account: continue return win elif isinstance(win, cls): if account is not None: if account != win.account: continue return win return None def load_css_config(): global css_config from gajim.gtk.css_config import CSSConfig css_config = CSSConfig() def set_win_debug_mode(enable: bool) -> None: debug_folder = Path(configpaths.get('DEBUG')) debug_enabled = debug_folder / 'debug-enabled' if enable: debug_enabled.touch() else: if debug_enabled.exists(): debug_enabled.unlink() def get_win_debug_mode() -> bool: if sys.platform != 'win32': return False debug_folder = Path(configpaths.get('DEBUG')) debug_enabled = debug_folder / 'debug-enabled' return debug_enabled.exists() gajim-gajim-1.1.3/gajim/common/caps_cache.py000066400000000000000000000406331345766322700207170ustar00rootroot00000000000000# Copyright (C) 2007 Tomasz Melcer # Travis Shirk # Copyright (C) 2007-2014 Yann Leboulanger # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # Copyright (C) 2008-2009 Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Module containing all XEP-115 (Entity Capabilities) related classes Basic Idea: CapsCache caches features to hash relationships. The cache is queried through ClientCaps objects which are hold by contact instances. """ import base64 import hashlib from collections import namedtuple import logging log = logging.getLogger('gajim.c.caps_cache') import nbxmpp from nbxmpp import (NS_XHTML_IM, NS_ESESSION, NS_CHATSTATES, NS_JINGLE_ICE_UDP, NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_FILE_TRANSFER_5) # Features where we cannot safely assume that the other side supports them FEATURE_BLACKLIST = [NS_CHATSTATES, NS_XHTML_IM, NS_ESESSION, NS_JINGLE_ICE_UDP, NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_FILE_TRANSFER_5] # Query entry status codes NEW = 0 QUERIED = 1 CACHED = 2 # got the answer FAKED = 3 # allow NullClientCaps to behave as it has a cached item ################################################################################ ### Public API of this module ################################################################################ capscache = None muc_caps_cache = None def initialize(logger): """ Initialize this module """ global capscache global muc_caps_cache capscache = CapsCache(logger) muc_caps_cache = MucCapsCache() def client_supports(client_caps, requested_feature): lookup_item = client_caps.get_cache_lookup_strategy() cache_item = lookup_item(capscache) supported_features = cache_item.features if requested_feature in supported_features: return True if not supported_features and cache_item.status in (NEW, QUERIED, FAKED): # assume feature is supported, if we don't know yet, what the client # is capable of return requested_feature not in FEATURE_BLACKLIST return False def get_client_identity(client_caps): lookup_item = client_caps.get_cache_lookup_strategy() cache_item = lookup_item(capscache) for identity in cache_item.identities: if identity.get('category') == 'client': return identity.get('type') def create_suitable_client_caps(node, caps_hash, hash_method, fjid=None): """ Create and return a suitable ClientCaps object for the given node, caps_hash, hash_method combination. """ if not node or not caps_hash: if fjid: client_caps = NoClientCaps(fjid) else: # improper caps, ignore client capabilities. client_caps = NullClientCaps() elif not hash_method: client_caps = OldClientCaps(caps_hash, node) else: client_caps = ClientCaps(caps_hash, node, hash_method) return client_caps def compute_caps_hash(identities, features, dataforms=None, hash_method='sha-1'): """ Compute caps hash according to XEP-0115, V1.5 dataforms are nbxmpp.DataForms objects as common.dataforms don't allow several values without a field type list-multi """ if dataforms is None: dataforms = [] def sort_identities_key(i): return (i['category'], i.get('type', ''), i.get('xml:lang', '')) def sort_dataforms_key(dataform): f = dataform.getField('FORM_TYPE') return (bool(f), f.getValue()) S = '' identities.sort(key=sort_identities_key) for i in identities: c = i['category'] type_ = i.get('type', '') lang = i.get('xml:lang', '') name = i.get('name', '') S += '%s/%s/%s/%s<' % (c, type_, lang, name) features.sort() for f in features: S += '%s<' % f dataforms.sort(key=sort_dataforms_key) for dataform in dataforms: # fields indexed by var fields = {} for f in dataform.getChildren(): fields[f.getVar()] = f form_type = fields.get('FORM_TYPE') if form_type: S += form_type.getValue() + '<' del fields['FORM_TYPE'] for var in sorted(fields.keys()): S += '%s<' % var values = sorted(fields[var].getValues()) for value in values: S += '%s<' % value if hash_method == 'sha-1': hash_ = hashlib.sha1(S.encode('utf-8')) elif hash_method == 'md5': hash_ = hashlib.md5(S.encode('utf-8')) else: return '' return base64.b64encode(hash_.digest()).decode('utf-8') ################################################################################ ### Internal classes of this module ################################################################################ class AbstractClientCaps: """ Base class representing a client and its capabilities as advertised by a caps tag in a presence """ def __init__(self, caps_hash, node): self._hash = caps_hash self._node = node self._hash_method = None def get_discover_strategy(self): return self._discover def _discover(self, connection, jid): """ To be implemented by subclasses """ raise NotImplementedError def get_cache_lookup_strategy(self): return self._lookup_in_cache def _lookup_in_cache(self, caps_cache): """ To be implemented by subclasses """ raise NotImplementedError def get_hash_validation_strategy(self): return self._is_hash_valid def _is_hash_valid(self, identities, features, dataforms): """ To be implemented by subclasses """ raise NotImplementedError class ClientCaps(AbstractClientCaps): """ The current XEP-115 implementation """ def __init__(self, caps_hash, node, hash_method): AbstractClientCaps.__init__(self, caps_hash, node) assert hash_method != 'old' self._hash_method = hash_method def _lookup_in_cache(self, caps_cache): return caps_cache[(self._hash_method, self._hash)] def _discover(self, connection, jid): connection.get_module('Discovery').disco_contact( jid, '%s#%s' % (self._node, self._hash)) def _is_hash_valid(self, identities, features, dataforms): computed_hash = compute_caps_hash( identities, features, dataforms=dataforms, hash_method=self._hash_method) return computed_hash == self._hash class OldClientCaps(AbstractClientCaps): """ Old XEP-115 implementation. Kept around for background compatibility """ def __init__(self, caps_hash, node): AbstractClientCaps.__init__(self, caps_hash, node) self._hash_method = 'old' def _lookup_in_cache(self, caps_cache): return caps_cache[('old', self._node + '#' + self._hash)] def _discover(self, connection, jid): connection.get_module('Discovery').disco_contact(jid) def _is_hash_valid(self, identities, features, dataforms): return True class NoClientCaps(AbstractClientCaps): """ For clients that don't support XEP-0115 """ def __init__(self, fjid): AbstractClientCaps.__init__(self, fjid, fjid) self._hash_method = 'no' def _lookup_in_cache(self, caps_cache): return caps_cache[('no', self._node)] def _discover(self, connection, jid): connection.get_module('Discovery').disco_contact(jid) def _is_hash_valid(self, identities, features, dataforms): return True class NullClientCaps(AbstractClientCaps): """ This is a NULL-Object to streamline caps handling if a client has not advertised any caps or has advertised them in an improper way Assumes (almost) everything is supported. """ _instance = None def __new__(cls, *args, **kwargs): """ Make it a singleton. """ if not cls._instance: cls._instance = super(NullClientCaps, cls).__new__( cls, *args, **kwargs) return cls._instance def __init__(self): AbstractClientCaps.__init__(self, None, None) self._hash_method = 'dummy' def _lookup_in_cache(self, caps_cache): # lookup something which does not exist to get a new CacheItem created cache_item = caps_cache[('dummy', '')] # Mark the item as cached so that protocol/caps.py does not update it cache_item.status = FAKED return cache_item def _discover(self, connection, jid): pass def _is_hash_valid(self, identities, features, dataforms): return False class CapsCache: """ This object keeps the mapping between caps data and real disco features they represent, and provides simple way to query that info """ def __init__(self, logger=None): # our containers: # __cache is a dictionary mapping: pair of hash method and hash maps # to CapsCacheItem object # __CacheItem is a class that stores data about particular # client (hash method/hash pair) self.__cache = {} class CacheItem: # __names is a string cache; every string long enough is given # another object, and we will have plenty of identical long # strings. therefore we can cache them __names = {} def __init__(self, hash_method, hash_, logger): # cached into db self.hash_method = hash_method self.hash = hash_ self._features = [] self._identities = [] self._logger = logger self.status = NEW self._recently_seen = False def _get_features(self): return self._features def _set_features(self, value): self._features = [] for feature in value: self._features.append(self.__names.setdefault(feature, feature)) features = property(_get_features, _set_features) def _get_identities(self): list_ = [] for i in self._identities: # transforms it back in a dict d = dict() d['category'] = i[0] if i[1]: d['type'] = i[1] if i[2]: d['xml:lang'] = i[2] if i[3]: d['name'] = i[3] list_.append(d) return list_ def _set_identities(self, value): self._identities = [] for identity in value: # dict are not hashable, so transform it into a tuple t = (identity['category'], identity.get('type'), identity.get('xml:lang'), identity.get('name')) self._identities.append(self.__names.setdefault(t, t)) identities = property(_get_identities, _set_identities) def set_and_store(self, identities, features): self.identities = identities self.features = features if self.hash_method != 'no': self._logger.add_caps_entry(self.hash_method, self.hash, identities, features) self.status = CACHED def update_last_seen(self): if not self._recently_seen: self._recently_seen = True if self.hash_method != 'no': self._logger.update_caps_time(self.hash_method, self.hash) def is_valid(self): """ Returns True if identities and features for this cache item are known. """ return self.status in (CACHED, FAKED) self.__CacheItem = CacheItem self.logger = logger def initialize_from_db(self): self._remove_outdated_caps() for hash_method, hash_, identities, features in \ self.logger.iter_caps_data(): x = self[(hash_method, hash_)] x.identities = identities x.features = features x.status = CACHED def _remove_outdated_caps(self): """ Remove outdated values from the db """ self.logger.clean_caps_table() def __getitem__(self, caps): if caps in self.__cache: return self.__cache[caps] hash_method, hash_ = caps x = self.__CacheItem(hash_method, hash_, self.logger) self.__cache[(hash_method, hash_)] = x return x def query_client_of_jid_if_unknown(self, connection, jid, client_caps): """ Start a disco query to determine caps (node, ver, exts). Won't query if the data is already in cache """ lookup_cache_item = client_caps.get_cache_lookup_strategy() q = lookup_cache_item(self) if q.status == NEW: # do query for bare node+hash pair # this will create proper object q.status = QUERIED discover = client_caps.get_discover_strategy() discover(connection, jid) else: q.update_last_seen() def forget_caps(self, client_caps): hash_method = client_caps._hash_method hash_ = client_caps._hash key = (hash_method, hash_) if key in self.__cache: del self.__cache[key] class MucCapsCache: DiscoInfo = namedtuple('DiscoInfo', ['identities', 'features', 'data']) def __init__(self): self.cache = {} def append(self, stanza): jid = stanza.getFrom() identities, features, data = [], [], [] query_childs = stanza.getQueryChildren() if not query_childs: log.warning('%s returned empty disco info', jid) return for child in query_childs: if child.getName() == 'identity': attr = {} for key in child.getAttrs().keys(): attr[key] = child.getAttr(key) identities.append(attr) elif child.getName() == 'feature': features.append(child.getAttr('var')) elif child.getName() == 'x': if child.getNamespace() == nbxmpp.NS_DATA: from gajim.common.modules import dataforms data.append(dataforms.extend_form(node=child)) if nbxmpp.NS_MUC not in features: # Not a MUC, don't cache info return self.cache[jid] = self.DiscoInfo(identities, features, data) def is_cached(self, jid): return jid in self.cache def supports(self, jid, feature): if jid in self.cache: if feature in self.cache[jid].features: return True return False def has_mam(self, jid): try: if nbxmpp.NS_MAM_2 in self.cache[jid].features: return True if nbxmpp.NS_MAM_1 in self.cache[jid].features: return True return False except (KeyError, AttributeError): return False def get_mam_namespace(self, jid): try: if nbxmpp.NS_MAM_2 in self.cache[jid].features: return nbxmpp.NS_MAM_2 if nbxmpp.NS_MAM_1 in self.cache[jid].features: return nbxmpp.NS_MAM_1 except (KeyError, AttributeError): return def is_subject_change_allowed(self, jid, affiliation): allowed = True if affiliation in ('owner', 'admin'): return allowed if jid in self.cache: for form in self.cache[jid].data: try: allowed = form['muc#roominfo_changesubject'].value except KeyError: pass return allowed gajim-gajim-1.1.3/gajim/common/config.py000066400000000000000000001337631345766322700201220ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2004-2005 Vincent Hanquez # Copyright (C) 2005 Stéphan Kochen # Copyright (C) 2005-2006 Dimitur Kirov # Alex Mauer # Nikos Kouremenos # Copyright (C) 2005-2007 Travis Shirk # Copyright (C) 2006 Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 James Newton # Julien Pivotto # Copyright (C) 2007-2008 Brendan Taylor # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Any # pylint: disable=unused-import from typing import Dict # pylint: disable=unused-import from typing import List # pylint: disable=unused-import from typing import Tuple # pylint: disable=unused-import import re from enum import IntEnum, unique from gi.repository import GLib import gajim from gajim.common.i18n import _ @unique class Option(IntEnum): TYPE = 0 VAL = 1 DESC = 2 # If Option.RESTART is True - we need restart to use our changed option # Option.DESC also should be there RESTART = 3 opt_int = ['integer', 0] opt_str = ['string', 0] opt_bool = ['boolean', 0] opt_color = ['color', r'(#[0-9a-fA-F]{6})|rgb\(\d+,\d+,\d+\)|rgba\(\d+,\d+,\d+,[01]\.?\d*\)'] opt_one_window_types = ['never', 'always', 'always_with_roster', 'peracct', 'pertype'] opt_show_roster_on_startup = ['always', 'never', 'last_state'] opt_treat_incoming_messages = ['', 'chat', 'normal'] class Config: DEFAULT_ICONSET = 'dcraven' DEFAULT_MOOD_ICONSET = 'default' DEFAULT_ACTIVITY_ICONSET = 'default' DEFAULT_OPENWITH = 'xdg-open' DEFAULT_BROWSER = 'firefox' DEFAULT_MAILAPP = 'mozilla-thunderbird -compose' DEFAULT_FILE_MANAGER = 'xffm' __options = ({ # name: [ type, default_value, help_string ] 'verbose': [opt_bool, False, '', True], 'autopopup': [opt_bool, False], 'notify_on_signin': [opt_bool, True], 'notify_on_signout': [opt_bool, False], 'notify_on_new_message': [opt_bool, True], 'autopopupaway': [opt_bool, False], 'autopopup_chat_opened': [opt_bool, False, _('Show desktop notification even when a chat window is opened for this contact and does not have focus')], 'sounddnd': [opt_bool, False, _('Play sound when user is busy')], 'showoffline': [opt_bool, True], 'show_only_chat_and_online': [opt_bool, False, _('Show only online and free for chat contacts in roster.')], 'show_transports_group': [opt_bool, True], 'autoaway': [opt_bool, True], 'autoawaytime': [opt_int, 5, _('Time in minutes, after which your status changes to away.')], 'autoaway_message': [opt_str, _('$S (Away as a result of being idle more than $T min)'), _('$S will be replaced by current status message, $T by autoawaytime.')], 'autoxa': [opt_bool, True], 'autoxatime': [opt_int, 15, _('Time in minutes, after which your status changes to not available.')], 'autoxa_message': [opt_str, _('$S (Not available as a result of being idle more than $T min)'), _('$S will be replaced by current status message, $T by autoxatime.')], 'ask_online_status': [opt_bool, False], 'ask_offline_status': [opt_bool, False], 'trayicon': [opt_str, 'always', _("When to show notification area icon. Can be 'never', 'on_event', 'always'."), False], 'allow_hide_roster': [opt_bool, False, _("Allow to hide the roster window even if the tray icon is not shown."), False], 'iconset': [opt_str, DEFAULT_ICONSET, '', True], 'mood_iconset': [opt_str, DEFAULT_MOOD_ICONSET, '', True], 'activity_iconset': [opt_str, DEFAULT_ACTIVITY_ICONSET, '', True], 'use_transports_iconsets': [opt_bool, True, '', True], 'notif_signin_color': [opt_color, '#32CD32', _('Contact signed in notification color.')], # limegreen 'notif_signout_color': [opt_color, '#FF0000', _('Contact signout notification color')], # red 'notif_message_color': [opt_color, '#1E90FF', _('New message notification color.')], # dodgerblue 'notif_ftrequest_color': [opt_color, '#F0E68C', _('File transfer request notification color.')], # khaki 'notif_fterror_color': [opt_color, '#B22222', _('File transfer error notification color.')], # firebrick 'notif_ftcomplete_color': [opt_color, '#9ACD32', _('File transfer complete or stopped notification color.')], # yellowgreen 'notif_invite_color': [opt_color, '#D2B48C', _('Groupchat invitation notification color')], # tan1 'notif_status_color': [opt_color, '#D8BFD8', _('Background color of status changed notification')], # thistle2 'notif_other_color': [opt_color, '#FFFFFF', _('Other dialogs color.')], # white 'collapsed_rows': [opt_str, '', _('List (space separated) of rows (accounts and groups) that are collapsed.'), True], 'roster_theme': [opt_str, _('default'), '', True], 'mergeaccounts': [opt_bool, False, '', True], 'sort_by_show_in_roster': [opt_bool, True, '', True], 'sort_by_show_in_muc': [opt_bool, False, '', True], 'use_speller': [opt_bool, False, ], 'ignore_incoming_xhtml': [opt_bool, False, ], 'speller_language': [opt_str, '', _('Language used by speller')], 'print_time': [opt_str, 'always', _('\'always\' - print time for every message.\n\'sometimes\' - print time every print_ichat_every_foo_minutes minute.\n\'never\' - never print time.')], 'print_time_fuzzy': [opt_int, 0, _('Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. This is used only if print_time is \'sometimes\'.')], 'emoticons_theme': [opt_str, 'noto-emoticons', '', True], 'ascii_emoticons': [opt_bool, True, _('When enabled, ASCII emojis will be converted to graphical emojis.'), True], 'ascii_formatting': [opt_bool, True, _('Treat * / _ pairs as possible formatting characters.'), True], 'show_ascii_formatting_chars': [opt_bool, True, _('If true, do not ' 'remove */_ . So *abc* will be bold but with * * not removed.')], 'rst_formatting_outgoing_messages': [opt_bool, False, _('Uses ReStructured text markup to send HTML, plus ascii formatting if selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html (If you want to use this, install docutils)')], 'sounds_on': [opt_bool, True], # 'aplay', 'play', 'esdplay', 'artsplay' detected first time only 'soundplayer': [opt_str, ''], 'openwith': [opt_str, DEFAULT_OPENWITH], 'custombrowser': [opt_str, DEFAULT_BROWSER], 'custommailapp': [opt_str, DEFAULT_MAILAPP], 'custom_file_manager': [opt_str, DEFAULT_FILE_MANAGER], 'gc-hpaned-position': [opt_int, 430], 'gc_refer_to_nick_char': [opt_str, ',', _('Character to add after nickname when using nick completion (tab) in group chat.')], 'gc_proposed_nick_char': [opt_str, '_', _('Character to propose to add after desired nickname when desired nickname is used by someone else in group chat.')], 'msgwin-max-state': [opt_bool, False], 'msgwin-x-position': [opt_int, -1], # Default is to let the window manager decide 'msgwin-y-position': [opt_int, -1], # Default is to let the window manager decide 'msgwin-width': [opt_int, 500], 'msgwin-height': [opt_int, 440], 'chat-msgwin-x-position': [opt_int, -1], # Default is to let the window manager decide 'chat-msgwin-y-position': [opt_int, -1], # Default is to let the window manager decide 'chat-msgwin-width': [opt_int, 480], 'chat-msgwin-height': [opt_int, 440], 'gc-msgwin-x-position': [opt_int, -1], # Default is to let the window manager decide 'gc-msgwin-y-position': [opt_int, -1], # Default is to let the window manager decide 'gc-msgwin-width': [opt_int, 600], 'gc-msgwin-height': [opt_int, 440], 'pm-msgwin-x-position': [opt_int, -1], # Default is to let the window manager decide 'pm-msgwin-y-position': [opt_int, -1], # Default is to let the window manager decide 'pm-msgwin-width': [opt_int, 480], 'pm-msgwin-height': [opt_int, 440], 'single-msg-x-position': [opt_int, 0], 'single-msg-y-position': [opt_int, 0], 'single-msg-width': [opt_int, 400], 'single-msg-height': [opt_int, 280], 'save-roster-position': [opt_bool, True, _('If true, Gajim will save roster position when hiding roster, and restore it when showing roster.')], 'roster_x-position': [opt_int, 0], 'roster_y-position': [opt_int, 0], 'roster_width': [opt_int, 200], 'roster_height': [opt_int, 400], 'roster_hpaned_position': [opt_int, 200], 'roster_on_the_right': [opt_bool, False, _('Place the roster on the right in single window mode'), True], 'history_window_width': [opt_int, -1], 'history_window_height': [opt_int, 450], 'history_window_x-position': [opt_int, 0], 'history_window_y-position': [opt_int, 0], 'latest_disco_addresses': [opt_str, ''], 'time_stamp': [opt_str, '[%X] ', _('This option let you customize timestamp that is printed in conversation. For exemple "[%H:%M] " will show "[hour:minute] ". See python doc on strftime for full documentation: http://docs.python.org/lib/module-time.html')], 'before_nickname': [opt_str, '', _('Characters that are printed before the nickname in conversations')], 'after_nickname': [opt_str, ':', _('Characters that are printed after the nickname in conversations')], 'use_gpg_agent': [opt_bool, False], 'change_roster_title': [opt_bool, True, _('Add * and [n] in roster title?')], 'restore_lines': [opt_int, 10, _('How many history messages should be restored when a chat tab/window is reopened?')], 'restore_timeout': [opt_int, -1, _('How far back in time (minutes) history is restored. -1 means no limit.')], 'muc_restore_lines': [opt_int, 100, _('How many lines to request from server when entering a groupchat. -1 means no limit')], 'muc_restore_timeout': [opt_int, -1, _('Minutes of backlog to request when entering a groupchat. -1 means no limit')], 'muc_autorejoin_timeout': [opt_int, 1, _('How many seconds to wait before trying to autorejoin to a conference you are being disconnected from. Set to 0 to disable autorejoining.')], 'muc_autorejoin_on_kick': [opt_bool, False, _('Should autorejoin be activated when kicked from a conference?')], 'send_on_ctrl_enter': [opt_bool, False, _('Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ Client default behaviour).')], 'last_roster_visible': [opt_bool, True], 'key_up_lines': [opt_int, 25, _('How many lines to store for Ctrl+KeyUP.')], 'version': [opt_str, gajim.__version__], # which version created the config 'search_engine': [opt_str, 'https://www.google.com/search?&q=%s&sourceid=gajim'], 'dictionary_url': [opt_str, 'WIKTIONARY', _("Either custom URL with %%s in it where %%s is the word/phrase or 'WIKTIONARY' which means use Wikitionary.")], 'always_english_wikipedia': [opt_bool, False], 'always_english_wiktionary': [opt_bool, True], 'remote_control': [opt_bool, False, _('If checked, Gajim can be controlled remotely using gajim-remote.'), True], 'outgoing_chat_state_notifications': [opt_str, 'all', _('Sent chat state notifications. Can be one of all, composing_only, disabled.')], 'displayed_chat_state_notifications': [opt_str, 'all', _('Displayed chat state notifications in chat windows. Can be one of all, composing_only, disabled.')], 'autodetect_browser_mailer': [opt_bool, True, '', True], 'print_ichat_every_foo_minutes': [opt_int, 5, _('When not printing time for every message (print_time==sometimes), print it every x minutes.')], 'confirm_close_muc': [opt_bool, True, _('Ask before closing a group chat tab/window.')], 'confirm_close_muc_rooms': [opt_str, '', _('Always ask for confirmation before closing groupchats with any of the JIDs on this space separated list.')], 'noconfirm_close_muc_rooms': [opt_str, '', _('Never ask for confirmation before closing groupchats with any of the JIDs on this space separated list.')], 'confirm_close_multiple_tabs': [opt_bool, True, _('Ask before closing tabbed chat window if there are controls that can lose data (chat, private chat, groupchat that will not be minimized)')], 'notify_on_file_complete': [opt_bool, True], 'file_transfers_port': [opt_int, 28011], 'ft_add_hosts_to_send': [opt_str, '', _('Comma separated list of sent hosts, in addition of local interfaces, for File Transfer in case of address translation/port forwarding.')], 'use_kib_mib': [opt_bool, False, _('IEC standard says KiB = 1024 bytes, KB = 1000 bytes.')], 'notify_on_all_muc_messages': [opt_bool, False], 'trayicon_notification_on_events': [opt_bool, True, _('Notify of events in the notification area.')], 'trayicon_blink': [opt_bool, True, _('If False, Gajim will display a static event icon instead of the blinking status icon in the notification area when notifying on event.')], 'last_save_dir': [opt_str, ''], 'last_send_dir': [opt_str, ''], 'last_emoticons_dir': [opt_str, ''], 'last_sounds_dir': [opt_str, ''], 'tabs_position': [opt_str, 'top'], 'tabs_always_visible': [opt_bool, False, _('Show tab when only one conversation?')], 'tabs_border': [opt_bool, False, _('Show tabbed notebook border in chat windows?')], 'tabs_close_button': [opt_bool, True, _('Show close button in tab?')], 'tooltip_status_online_color': [opt_color, '#73D216'], 'tooltip_status_free_for_chat_color': [opt_color, '#3465A4'], 'tooltip_status_away_color': [opt_color, '#EDD400'], 'tooltip_status_busy_color': [opt_color, '#F57900'], 'tooltip_status_na_color': [opt_color, '#CC0000'], 'tooltip_status_offline_color': [opt_color, '#555753'], 'tooltip_affiliation_none_color': [opt_color, '#555753'], 'tooltip_affiliation_member_color': [opt_color, '#73D216'], 'tooltip_affiliation_administrator_color': [opt_color, '#F57900'], 'tooltip_affiliation_owner_color': [opt_color, '#CC0000'], 'tooltip_account_name_color': [opt_color, '#888A85'], 'tooltip_idle_color': [opt_color, '#888A85'], 'notification_preview_message': [opt_bool, True, _('Preview new messages in notification popup?')], 'notification_position_x': [opt_int, -1], 'notification_position_y': [opt_int, -1], 'muc_highlight_words': [opt_str, '', _('A semicolon-separated list of words that will be highlighted in group chats.')], 'quit_on_roster_x_button': [opt_bool, False, _('If true, quits Gajim when X button of Window Manager is clicked. This setting is taken into account only if notification icon is used.')], 'hide_on_roster_x_button': [opt_bool, False, _('If true, Gajim hides the Roster window on pressing the X button instead of minimizing into the Dock.')], 'show_unread_tab_icon': [opt_bool, False, _('If true, Gajim will display an icon on each tab containing unread messages. Depending on the theme, this icon may be animated.')], 'show_status_msgs_in_roster': [opt_bool, True, _('If true, Gajim will display the status message, if not empty, for every contact under the contact name in roster window.'), True], 'show_avatars_in_roster': [opt_bool, True, '', True], 'show_mood_in_roster': [opt_bool, True, '', True], 'show_activity_in_roster': [opt_bool, True, '', True], 'show_tunes_in_roster': [opt_bool, True, '', True], 'show_location_in_roster': [opt_bool, True, '', True], 'avatar_position_in_roster': [opt_str, 'right', _('Define the position of the avatar in roster. Can be left or right'), True], 'print_status_in_chats': [opt_bool, False, _('If False, Gajim will no longer print status line in chats when a contact changes their status and/or their status message.')], 'print_status_in_muc': [opt_str, 'none', _('Can be "none", "all" or "in_and_out". If "none", Gajim will no longer print status line in groupchats when a member changes their status and/or their status message. If "all" Gajim will print all status messages. If "in_and_out", Gajim will only print FOO enters/leaves group chat.')], 'log_contact_status_changes': [opt_bool, False], 'log_xhtml_messages': [opt_bool, False, _('Log XHTML messages instead of plain text messages.')], 'restored_messages_small': [opt_bool, True, _('If true, restored messages will use a smaller font than the default one.')], 'hide_avatar_of_transport': [opt_bool, False, _('Don\'t show avatar for the transport itself.')], 'roster_window_skip_taskbar': [opt_bool, False, _('Don\'t show roster in the system taskbar.')], 'use_urgency_hint': [opt_bool, True, _('If true, make the window flash (the default behaviour in most Window Managers) when holding pending events.')], 'notification_timeout': [opt_int, 5], 'one_message_window': [opt_str, 'always', #always, never, peracct, pertype should not be translated _('Controls the window where new messages are placed.\n\'always\' - All messages are sent to a single window.\n\'always_with_roster\' - Like \'always\' but the messages are in a single window along with the roster.\n\'never\' - All messages get their own window.\n\'peracct\' - Messages for each account are sent to a specific window.\n\'pertype\' - Each message type (e.g. chats vs. groupchats) is sent to a specific window.')], 'show_roster_on_startup':[opt_str, 'always', _('Show roster on startup.\n\'always\' - Always show roster.\n\'never\' - Never show roster.\n\'last_state\' - Restore the last state roster.')], 'show_avatar_in_chat': [opt_bool, True, _('If False, you will no longer see the avatar in the chat window.')], 'escape_key_closes': [opt_bool, True, _('If true, pressing the escape key closes a tab/window.')], 'hide_groupchat_banner': [opt_bool, False, _('Hides the banner in a group chat window')], 'hide_chat_banner': [opt_bool, False, _('Hides the banner in two persons chat window')], 'hide_groupchat_occupants_list': [opt_bool, False, _('Hides the group chat occupants list in group chat window.')], 'chat_merge_consecutive_nickname': [opt_bool, False, _('In a chat, show the nickname at the beginning of a line only when it\'s not the same person talking than in previous message.')], 'chat_merge_consecutive_nickname_indent': [opt_str, ' ', _('Indentation when using merge consecutive nickname.')], 'gc_nicknames_colors': [opt_str, '#4e9a06:#f57900:#ce5c00:#3465a4:#204a87:#75507b:#5c3566:#c17d11:#8f5902:#ef2929:#cc0000:#a40000', _('List of colors, separated by ":", that will be used to color nicknames in group chats.'), True], 'ctrl_tab_go_to_next_composing': [opt_bool, True, _('Ctrl-Tab go to next composing tab when none is unread.')], 'confirm_metacontacts': [opt_str, '', _('Show the confirm metacontacts creation dialog or not? Empty string means never show the dialog.')], 'confirm_block': [opt_str, '', _('Show the confirm block contact dialog or not? Empty string means never show the dialog.')], 'confirm_custom_status': [opt_str, '', _('Show the confirm custom status dialog or not? Empty string means never show the dialog.')], 'enable_negative_priority': [opt_bool, False, _('If true, you will be able to set a negative priority to your account in account modification window. BE CAREFUL, when you are logged in with a negative priority, you will NOT receive any message from your server.')], 'show_contacts_number': [opt_bool, True, _('If true, Gajim will show number of online and total contacts in account and group rows.')], 'treat_incoming_messages': [opt_str, '', _('Can be empty, \'chat\' or \'normal\'. If not empty, treat all incoming messages as if they were of this type')], 'scroll_roster_to_last_message': [opt_bool, True, _('If true, Gajim will scroll and select the contact who sent you the last message, if chat window is not already opened.')], 'change_status_window_timeout': [opt_int, 15, _('Time of inactivity needed before the change status window closes down.')], 'max_conversation_lines': [opt_int, 500, _('Maximum number of lines that are printed in conversations. Oldest lines are cleared.')], 'attach_notifications_to_systray': [opt_bool, False, _('If true, notification windows from notification-daemon will be attached to notification icon.')], 'check_idle_every_foo_seconds': [opt_int, 2, _('Choose interval between 2 checks of idleness.')], 'uri_schemes': [opt_str, 'aaa:// aaas:// acap:// cap:// cid: crid:// data: dav: dict:// dns: fax: file:/ ftp:// geo: go: gopher:// h323: http:// https:// iax: icap:// im: imap:// info: ipp:// iris: iris.beep: iris.xpc: iris.xpcs: iris.lwz: ldap:// mid: modem: msrp:// msrps:// mtqp:// mupdate:// news: nfs:// nntp:// opaquelocktoken: pop:// pres: prospero:// rtsp:// service: shttp:// sip: sips: sms: snmp:// soap.beep:// soap.beeps:// tag: tel: telnet:// tftp:// thismessage:/ tip:// tv: urn:// vemmi:// xmlrpc.beep:// xmlrpc.beeps:// z39.50r:// z39.50s:// about: apt: cvs:// daap:// ed2k:// feed: fish:// git:// iax2: irc:// ircs:// ldaps:// magnet: mms:// rsync:// ssh:// svn:// sftp:// smb:// webcal:// aesgcm://', _('Valid uri schemes. Only schemes in this list will be accepted as "real" uri. (mailto and xmpp are handled separately)'), True], 'shell_like_completion': [opt_bool, False, _('If true, completion in groupchats will be like a shell auto-completion')], 'show_self_contact': [opt_str, 'when_other_resource', _('When is self contact row displayed. Can be "always", "when_other_resource" or "never"'), True], 'audio_input_device': [opt_str, 'autoaudiosrc ! volume name=gajim_vol'], 'audio_output_device': [opt_str, 'autoaudiosink'], 'video_input_device': [opt_str, 'autovideosrc'], 'video_output_device': [opt_str, 'autovideosink'], 'video_framerate': [opt_str, '', _('Optionally fix jingle output video framerate. Example: 10/1 or 25/2')], 'video_size': [opt_str, '', _('Optionally resize jingle output video. Example: 320x240')], 'video_see_self': [opt_bool, True, _('If true, You will also see your webcam')], 'audio_input_volume': [opt_int, 50], 'audio_output_volume': [opt_int, 50], 'use_stun_server': [opt_bool, False, _('If true, Gajim will try to use a STUN server when using Jingle. The one in "stun_server" option, or the one given by the XMPP server.')], 'stun_server': [opt_str, '', _('STUN server to use when using Jingle')], 'show_affiliation_in_groupchat': [opt_bool, True, _('If true, Gajim will show affiliation of groupchat occupants by adding a colored square to the status icon')], 'global_proxy': [opt_str, '', _('Proxy used for all outgoing connections if the account does not have a specific proxy configured')], 'ignore_incoming_attention': [opt_bool, False, _('If true, Gajim will ignore incoming attention requestd ("wizz").')], 'remember_opened_chat_controls': [opt_bool, True, _('If enabled, Gajim will reopen chat windows that were opened last time Gajim was closed.')], 'positive_184_ack': [opt_bool, False, _('If enabled, Gajim will show an icon to show that sent message has been received by your contact')], 'show_avatar_in_tabs': [opt_bool, False, _('Show a mini avatar in chat window tabs and in window icon')], 'use_keyring': [opt_bool, True, _('If true, Gajim will use the Systems Keyring to store account passwords.')], 'pgp_encoding': [opt_str, '', _('Sets the encoding used by python-gnupg'), True], 'remote_commands': [opt_bool, False, _('If true, Gajim will execute XEP-0146 Commands.')], 'dark_theme': [opt_int, 2, _('2: System, 1: Enabled, 0: Disabled')], 'threshold_options': [opt_str, '1, 2, 4, 10, 0', _('Options in days which can be chosen in the sync threshold menu'), True], 'public_room_sync_threshold': [opt_int, 1, _('Maximum history in days we request from a public room archive. 0: As much as possible')], 'private_room_sync_threshold': [opt_int, 0, _('Maximum history in days we request from a private room archive. 0: As much as possible')], 'show_subject_on_join': [opt_bool, True, _('If the room subject is shown in chat on join')], }, {}) # type: Tuple[Dict[str, List[Any]], Dict[Any, Any]] __options_per_key = { 'accounts': ({ 'name': [opt_str, '', '', True], 'account_label': [opt_str, '', '', False], 'hostname': [opt_str, '', '', True], 'anonymous_auth': [opt_bool, False], 'avatar_sha': [opt_str, '', '', False], 'client_cert': [opt_str, '', '', True], 'client_cert_encrypted': [opt_bool, False, '', False], 'savepass': [opt_bool, False], 'password': [opt_str, ''], 'resource': [opt_str, 'gajim.$rand', '', True], 'priority': [opt_int, 5, '', True], 'adjust_priority_with_status': [opt_bool, True, _('Priority will change automatically according to your status. Priorities are defined in autopriority_* options.')], 'autopriority_online': [opt_int, 50], 'autopriority_chat': [opt_int, 50], 'autopriority_away': [opt_int, 40], 'autopriority_xa': [opt_int, 30], 'autopriority_dnd': [opt_int, 20], 'autopriority_invisible': [opt_int, 10], 'autoconnect': [opt_bool, False, '', True], 'autoconnect_as': [opt_str, 'online', _('Status used to autoconnect as. Can be online, chat, away, xa, dnd, invisible. NOTE: this option is used only if restore_last_status is disabled'), True], 'restore_last_status': [opt_bool, False, _('If enabled, restore the last status that was used.')], 'autoreconnect': [opt_bool, True], 'autoauth': [opt_bool, False, _('If true, Contacts requesting authorization will be automatically accepted.')], 'active': [opt_bool, True, _('If False, this account will be disabled and will not appear in roster window.'), True], 'proxy': [opt_str, '', '', True], 'keyid': [opt_str, '', '', True], 'gpg_sign_presence': [opt_bool, True, _('If disabled, don\'t sign presences with GPG key, even if GPG is configured.')], 'keyname': [opt_str, '', '', True], 'allow_plaintext_connection': [opt_bool, False, _('Allow plaintext connections')], 'tls_version': [opt_str, '1.2', ''], 'cipher_list': [opt_str, 'HIGH:!aNULL', ''], 'authentication_mechanisms': [opt_str, '', _('List (space separated) of authentication mechanisms to try. Can contain ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, PLAIN, X-MESSENGER-OAUTH2 or XEP-0078')], 'action_when_plaintext_connection': [opt_str, 'warn', _('Show a warning dialog before sending password on an plaintext connection. Can be \'warn\', \'connect\', \'disconnect\'')], 'warn_when_insecure_ssl_connection': [opt_bool, True, _('Show a warning dialog before using standard SSL library.')], 'warn_when_insecure_password': [opt_bool, True, _('Show a warning dialog before sending PLAIN password over a plain connection.')], 'ignore_ssl_errors': [opt_str, '', _('Space separated list of ssl errors to ignore.')], 'use_srv': [opt_bool, True, '', True], 'use_custom_host': [opt_bool, False, '', True], 'custom_port': [opt_int, 5222, '', True], 'custom_host': [opt_str, '', '', True], 'sync_with_global_status': [opt_bool, False, ], 'no_log_for': [opt_str, '', _('Space separated list of JIDs for which you do not want to store logs. You can also add account name to log nothing for this account.')], 'sync_logs_with_server': [opt_bool, True, _('On startup, Gajim will download logs stored on server, provided the server supports XEP-0313')], 'allow_no_log_for': [opt_str, '', _('Space separated list of JIDs for which you accept to not log conversations if he does not want to.')], 'non_minimized_gc': [opt_str, ''], 'attached_gpg_keys': [opt_str, ''], 'keep_alives_enabled': [opt_bool, True, _('Whitespace sent after inactivity')], 'ping_alives_enabled': [opt_bool, True, _('XMPP ping sent after inactivity')], # send keepalive every N seconds of inactivity 'keep_alive_every_foo_secs': [opt_int, 55], 'ping_alive_every_foo_secs': [opt_int, 120], 'time_for_ping_alive_answer': [opt_int, 60, _('How many seconds to wait for the answer of ping alive packet before trying to reconnect?')], # try for 1 minutes before giving up (aka. timeout after those seconds) 'try_connecting_for_foo_secs': [opt_int, 60], 'http_auth': [opt_str, 'ask'], # yes, no, ask 'dont_ack_subscription': [opt_bool, False, _('Jabberd2 workaround')], # proxy65 for FT 'file_transfer_proxies': [opt_str, ''], 'use_ft_proxies': [opt_bool, False, _('If checked, Gajim will use your IP and proxies defined in file_transfer_proxies option for file transfer.'), True], 'test_ft_proxies_on_startup': [opt_bool, False, _('If true, Gajim will test file transfer proxies on startup to be sure it works. Openfire\'s proxies are known to fail this test even if they work.')], 'msgwin-x-position': [opt_int, -1], # Default is to let the wm decide 'msgwin-y-position': [opt_int, -1], # Default is to let the wm decide 'msgwin-width': [opt_int, 480], 'msgwin-height': [opt_int, 440], 'is_zeroconf': [opt_bool, False], 'last_status': [opt_str, 'online'], 'last_status_msg': [opt_str, ''], 'zeroconf_first_name': [opt_str, '', '', True], 'zeroconf_last_name': [opt_str, '', '', True], 'zeroconf_jabber_id': [opt_str, '', '', True], 'zeroconf_email': [opt_str, '', '', True], 'use_env_http_proxy': [opt_bool, False], 'answer_receipts': [opt_bool, True, _('Answer to receipt requests')], 'request_receipt': [opt_bool, True, _('Sent receipt requests')], 'publish_tune': [opt_bool, False], 'publish_location': [opt_bool, False], 'subscribe_mood': [opt_bool, True], 'subscribe_activity': [opt_bool, True], 'subscribe_tune': [opt_bool, True], 'subscribe_nick': [opt_bool, True], 'subscribe_location': [opt_bool, True], 'ignore_unknown_contacts': [opt_bool, False], 'send_os_info': [opt_bool, True, _("Allow Gajim to send information about the operating system you are running.")], 'send_time_info': [opt_bool, True, _("Allow Gajim to send your local time.")], 'send_idle_time': [opt_bool, True], 'roster_version': [opt_str, ''], 'subscription_request_msg': [opt_str, '', _('Message that is sent to contacts you want to add')], 'enable_message_carbons': [opt_bool, True, _('If enabled and if server supports this feature, Gajim will receive messages sent and received by other resources.')], 'ft_send_local_ips': [opt_bool, True, _('If enabled, Gajim will send your local IPs so your contact can connect to your machine to transfer files.')], 'oauth2_refresh_token': [opt_str, '', _('Latest token for OAuth 2.0 authentication.')], 'oauth2_client_id': [opt_str, '0000000044077801', _('client_id for OAuth 2.0 authentication.')], 'oauth2_redirect_url': [opt_str, 'https%3A%2F%2Fgajim.org%2Fmsnauth%2Findex.cgi', _('redirect_url for OAuth 2.0 authentication.')], 'opened_chat_controls': [opt_str, '', _('Space separated list of JIDs for which chat window will be re-opened on next startup.')], 'recent_groupchats': [opt_str, ''], 'httpupload_verify': [opt_bool, True, _('HTTP Upload: Enable HTTPS Verification')], 'filetransfer_preference' : [opt_str, 'httpupload', _('Preferred file transfer mechanism for file drag&drop on chat window. Can be \'httpupload\' (default) or \'jingle\'')], 'allow_posh': [opt_bool, True, _('Allow cert verification with POSH')], }, {}), 'statusmsg': ({ 'message': [opt_str, ''], 'activity': [opt_str, ''], 'subactivity': [opt_str, ''], 'activity_text': [opt_str, ''], 'mood': [opt_str, ''], 'mood_text': [opt_str, ''], }, {}), 'defaultstatusmsg': ({ 'enabled': [opt_bool, False], 'message': [opt_str, ''], }, {}), 'soundevents': ({ 'enabled': [opt_bool, True], 'path': [opt_str, ''], }, {}), 'proxies': ({ 'type': [opt_str, 'http'], 'host': [opt_str, ''], 'port': [opt_int, 3128], 'useauth': [opt_bool, False], 'user': [opt_str, ''], 'pass': [opt_str, ''], 'bosh_uri': [opt_str, ''], 'bosh_useproxy': [opt_bool, False], 'bosh_wait': [opt_int, 30], 'bosh_hold': [opt_int, 2], 'bosh_content': [opt_str, 'text/xml; charset=utf-8'], 'bosh_http_pipelining': [opt_bool, False], 'bosh_wait_for_restart_response': [opt_bool, False], }, {}), 'contacts': ({ 'speller_language': [opt_str, '', _('Language for which misspelled words will be checked')], }, {}), 'encryption': ({ 'encryption': [opt_str, '', _('The currently active encryption for that contact')], }, {}), 'rooms': ({ 'speller_language': [opt_str, '', _('Language for which misspelled words will be checked')], 'muc_restore_lines': [opt_int, -2, _('How many lines to request from server when entering a groupchat. -1 means no limit, -2 means global value')], 'muc_restore_timeout': [opt_int, -2, _('Minutes of backlog to request when entering a groupchat. -1 means no limit, -2 means global value')], 'notify_on_all_messages': [opt_bool, False, _('State whether a notification is created for every message in this room')], }, {}), 'plugins': ({ 'active': [opt_bool, False, _('State whether plugins should be activated on startup (this is saved on Gajim exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI instead.')], }, {}), } # type: Dict[str, Tuple[Dict[str, List[Any]], Dict[Any, Any]]] statusmsg_default = { _('Sleeping'): ['ZZZZzzzzzZZZZZ', 'inactive', 'sleeping', '', 'sleepy', ''], _('Back soon'): [_('Back in some minutes.'), '', '', '', '', ''], _('Eating'): [_("I'm eating, so leave me a message."), 'eating', 'other', '', '', ''], _('Movie'): [_("I'm watching a movie."), 'relaxing', 'watching_a_movie', '', '', ''], _('Working'): [_("I'm working."), 'working', 'other', '', '', ''], _('Phone'): [_("I'm on the phone."), 'talking', 'on_the_phone', '', '', ''], _('Out'): [_("I'm out enjoying life."), 'relaxing', 'going_out', '', '', ''], '_last_online': ['', '', '', '', '', ''], '_last_chat': ['', '', '', '', '', ''], '_last_away': ['', '', '', '', '', ''], '_last_xa': ['', '', '', '', '', ''], '_last_dnd': ['', '', '', '', '', ''], '_last_invisible': ['', '', '', '', '', ''], '_last_offline': ['', '', '', '', '', ''], } defaultstatusmsg_default = { 'online': [False, _("I'm available.")], 'chat': [False, _("I'm free for chat.")], 'away': [False, _('Be right back.')], 'xa': [False, _("I'm not available.")], 'dnd': [False, _('Do not disturb.')], 'invisible': [False, _('Bye!')], 'offline': [False, _('Bye!')], } soundevents_default = { 'attention_received': [True, 'attention.wav'], 'first_message_received': [True, 'message1.wav'], 'next_message_received_focused': [True, 'message2.wav'], 'next_message_received_unfocused': [True, 'message2.wav'], 'contact_connected': [False, 'connected.wav'], 'contact_disconnected': [False, 'disconnected.wav'], 'message_sent': [False, 'sent.wav'], 'muc_message_highlight': [True, 'gc_message1.wav', _('Sound to play when a group chat message contains one of the words in muc_highlight_words, or when a group chat message contains your nickname.')], 'muc_message_received': [False, 'gc_message2.wav', _('Sound to play when any MUC message arrives.')], } proxies_default = { _('Tor'): ['socks5', 'localhost', 9050], } def foreach(self, cb, data=None): for opt in self.__options[1]: cb(data, opt, None, self.__options[1][opt]) for opt in self.__options_per_key: cb(data, opt, None, None) dict_ = self.__options_per_key[opt][1] for opt2 in dict_.keys(): cb(data, opt2, [opt], None) for opt3 in dict_[opt2]: cb(data, opt3, [opt, opt2], dict_[opt2][opt3]) def get_children(self, node=None): """ Tree-like interface """ if node is None: for child, option in self.__options[1].items(): yield (child, ), option for grandparent in self.__options_per_key: yield (grandparent, ), None elif len(node) == 1: grandparent, = node for parent in self.__options_per_key[grandparent][1]: yield (grandparent, parent), None elif len(node) == 2: grandparent, parent = node children = self.__options_per_key[grandparent][1][parent] for child, option in children.items(): yield (grandparent, parent, child), option else: raise ValueError('Invalid node') def is_valid_int(self, val): try: ival = int(val) except Exception: return None return ival def is_valid_bool(self, val): if val == 'True': return True if val == 'False': return False ival = self.is_valid_int(val) if ival: return True if ival is None: return None return False def is_valid_string(self, val): return val def is_valid(self, type_, val): if not type_: return None if type_[0] == 'boolean': return self.is_valid_bool(val) if type_[0] == 'integer': return self.is_valid_int(val) if type_[0] == 'string': return self.is_valid_string(val) if re.match(type_[1], val): return val return None def set(self, optname, value): if optname not in self.__options[1]: return value = self.is_valid(self.__options[0][optname][Option.TYPE], value) if value is None: return self.__options[1][optname] = value self._timeout_save() def get(self, optname=None): if not optname: return list(self.__options[1].keys()) if optname not in self.__options[1]: return None return self.__options[1][optname] def get_default(self, optname): if optname not in self.__options[0]: return None return self.__options[0][optname][Option.VAL] def get_type(self, optname): if optname not in self.__options[0]: return None return self.__options[0][optname][Option.TYPE][0] def get_desc(self, optname): if optname not in self.__options[0]: return None if len(self.__options[0][optname]) > Option.DESC: return self.__options[0][optname][Option.DESC] def get_restart(self, optname): if optname not in self.__options[0]: return None if len(self.__options[0][optname]) > Option.RESTART: return self.__options[0][optname][Option.RESTART] def add_per(self, typename, name): # per_group_of_option if typename not in self.__options_per_key: return opt = self.__options_per_key[typename] if name in opt[1]: # we already have added group name before return 'you already have added %s before' % name opt[1][name] = {} for o in opt[0]: opt[1][name][o] = opt[0][o][Option.VAL] self._timeout_save() def del_per(self, typename, name, subname=None): # per_group_of_option if typename not in self.__options_per_key: return opt = self.__options_per_key[typename] if subname is None: del opt[1][name] # if subname is specified, delete the item in the group. elif subname in opt[1][name]: del opt[1][name][subname] self._timeout_save() def set_per(self, optname, key, subname, value): # per_group_of_option if optname not in self.__options_per_key: return if not key: return dict_ = self.__options_per_key[optname][1] if key not in dict_: self.add_per(optname, key) obj = dict_[key] if subname not in obj: return typ = self.__options_per_key[optname][0][subname][Option.TYPE] value = self.is_valid(typ, value) if value is None: return obj[subname] = value self._timeout_save() def get_per(self, optname, key=None, subname=None): # per_group_of_option if optname not in self.__options_per_key: return None dict_ = self.__options_per_key[optname][1] if not key: return list(dict_.keys()) if key not in dict_: if subname in self.__options_per_key[optname][0]: return self.__options_per_key[optname][0][subname][1] return None obj = dict_[key] if not subname: return obj if subname not in obj: return None return obj[subname] def get_default_per(self, optname, subname): if optname not in self.__options_per_key: return None dict_ = self.__options_per_key[optname][0] if subname not in dict_: return None return dict_[subname][Option.VAL] def get_type_per(self, optname, subname): if optname not in self.__options_per_key: return None dict_ = self.__options_per_key[optname][0] if subname not in dict_: return None return dict_[subname][Option.TYPE][0] def get_desc_per(self, optname, subname=None): if optname not in self.__options_per_key: return None dict_ = self.__options_per_key[optname][0] if subname not in dict_: return None obj = dict_[subname] if len(obj) > Option.DESC: return obj[Option.DESC] return None def get_restart_per(self, optname, key=None, subname=None): if optname not in self.__options_per_key: return False dict_ = self.__options_per_key[optname][0] if not key: return False if key not in dict_: return False obj = dict_[key] if not subname: return False if subname not in obj: return False if len(obj[subname]) > Option.RESTART: return obj[subname][Option.RESTART] return False def should_log(self, account, jid): """ Should conversations between a local account and a remote jid be logged? """ no_log_for = self.get_per('accounts', account, 'no_log_for') if not no_log_for: no_log_for = '' no_log_for = no_log_for.split() return (account not in no_log_for) and (jid not in no_log_for) def _init_options(self): for opt in self.__options[0]: self.__options[1][opt] = self.__options[0][opt][Option.VAL] def _really_save(self): from gajim.common import app if app.interface: app.interface.save_config() self.save_timeout_id = None return False def _timeout_save(self): if self.save_timeout_id: return self.save_timeout_id = GLib.timeout_add(1000, self._really_save) def __init__(self): #init default values self._init_options() self.save_timeout_id = None for event in self.soundevents_default: default = self.soundevents_default[event] self.add_per('soundevents', event) self.set_per('soundevents', event, 'enabled', default[0]) self.set_per('soundevents', event, 'path', default[1]) for status in self.defaultstatusmsg_default: default = self.defaultstatusmsg_default[status] self.add_per('defaultstatusmsg', status) self.set_per('defaultstatusmsg', status, 'enabled', default[0]) self.set_per('defaultstatusmsg', status, 'message', default[1]) gajim-gajim-1.1.3/gajim/common/configpaths.py000066400000000000000000000210001345766322700211360ustar00rootroot00000000000000# Copyright (C) 2006 Jean-Marie Traissard # Junglecow J # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Brendan Taylor # Copyright (C) 2008 Jonathan Schleifer # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Dict # pylint: disable=unused-import from typing import List from typing import Generator from typing import Optional # pylint: disable=unused-import from typing import Tuple import os import sys import tempfile from pathlib import Path import gajim from gajim.common.i18n import _ from gajim.common.const import PathType, PathLocation from gajim.common.types import PathTuple def get(key: str) -> str: return _paths[key] def get_plugin_dirs() -> List[str]: if gajim.IS_FLATPAK: return ['/app/plugins', _paths['PLUGINS_BASE']] return [_paths['PLUGINS_BASE'], _paths['PLUGINS_USER']] def get_paths(type_: PathType) -> Generator[str, None, None]: for key, value in _paths.items(): path_type = value[2] if type_ != path_type: continue yield _paths[key] def override_path(*args, **kwargs): _paths.add(*args, **kwargs) def set_separation(active: bool) -> None: _paths.profile_separation = active def set_profile(profile: str) -> None: _paths.profile = profile def set_config_root(config_root: str) -> None: _paths.custom_config_root = str(Path(config_root).resolve()) def init() -> None: _paths.init() def create_paths() -> None: for path in get_paths(PathType.FOLDER): if not isinstance(path, Path): path_ = Path(path) if path_.is_file(): print(_('%s is a file but it should be a directory') % path_) print(_('Gajim will now exit')) sys.exit() if not path_.exists(): for parent_path in reversed(path_.parents): # Create all parent folders # don't use mkdir(parent=True), as it ignores `mode` # when creating the parents if not parent_path.exists(): print(('creating %s directory') % parent_path) parent_path.mkdir(mode=0o700) print(('creating %s directory') % path_) path_.mkdir(mode=0o700) class ConfigPaths: def __init__(self) -> None: self._paths = {} # type: Dict[str, PathTuple] self.profile = '' self.profile_separation = False self.custom_config_root = None # type: Optional[str] if os.name == 'nt': try: # Documents and Settings\[User Name]\Application Data\Gajim self.config_root = self.cache_root = self.data_root = \ os.path.join(os.environ['appdata'], 'Gajim') except KeyError: # win9x, in cwd self.config_root = self.cache_root = self.data_root = '.' else: expand = os.path.expanduser base = os.getenv('XDG_CONFIG_HOME') if base is None or base[0] != '/': base = expand('~/.config') self.config_root = os.path.join(base, 'gajim') base = os.getenv('XDG_CACHE_HOME') if base is None or base[0] != '/': base = expand('~/.cache') self.cache_root = os.path.join(base, 'gajim') base = os.getenv('XDG_DATA_HOME') if base is None or base[0] != '/': base = expand('~/.local/share') self.data_root = os.path.join(base, 'gajim') import pkg_resources basedir = pkg_resources.resource_filename("gajim", ".") source_paths = [ ('DATA', os.path.join(basedir, 'data')), ('STYLE', os.path.join(basedir, 'data', 'style')), ('EMOTICONS', os.path.join(basedir, 'data', 'emoticons')), ('GUI', os.path.join(basedir, 'data', 'gui')), ('ICONS', os.path.join(basedir, 'data', 'icons')), ('HOME', os.path.expanduser('~')), ('PLUGINS_BASE', os.path.join(basedir, 'data', 'plugins')), ] for path in source_paths: self.add(*path) def __getitem__(self, key: str) -> str: location, path, _ = self._paths[key] if location == PathLocation.CONFIG: return os.path.join(self.config_root, path) if location == PathLocation.CACHE: return os.path.join(self.cache_root, path) if location == PathLocation.DATA: return os.path.join(self.data_root, path) return path def items(self) -> Generator[Tuple[str, PathTuple], None, None]: for key, value in self._paths.items(): yield (key, value) def _prepare(self, path: str, unique: bool) -> str: if os.name == 'nt': path = path.capitalize() if self.profile: if unique or self.profile_separation: return '%s.%s' % (path, self.profile) return path def add(self, name: str, path: str, location: PathLocation = None, path_type: PathType = None, unique: bool = False) -> None: if path and location is not None: path = self._prepare(path, unique) self._paths[name] = (location, path, path_type) def init(self): if self.custom_config_root: self.config_root = self.custom_config_root self.cache_root = self.data_root = self.custom_config_root user_dir_paths = [ ('TMP', tempfile.gettempdir()), ('MY_CONFIG', '', PathLocation.CONFIG, PathType.FOLDER), ('MY_CACHE', '', PathLocation.CACHE, PathType.FOLDER), ('MY_DATA', '', PathLocation.DATA, PathType.FOLDER), ] for path in user_dir_paths: self.add(*path) # These paths are unique per profile unique_profile_paths = [ # Data paths ('SECRETS_FILE', 'secrets', PathLocation.DATA, PathType.FILE), ('MY_PEER_CERTS', 'certs', PathLocation.DATA, PathType.FOLDER), ('DEBUG', 'debug', PathLocation.DATA, PathType.FOLDER), ('PLUGINS_DATA', 'plugins_data', PathLocation.DATA, PathType.FOLDER), # Config paths ('CONFIG_FILE', 'config', PathLocation.CONFIG, PathType.FILE), ('PLUGINS_CONFIG_DIR', 'pluginsconfig', PathLocation.CONFIG, PathType.FOLDER), ('MY_CERT', 'localcerts', PathLocation.CONFIG, PathType.FOLDER), ] for path in unique_profile_paths: self.add(*path, unique=True) # These paths are only unique per profile if the commandline arg # `separate` is passed paths = [ # Data paths ('LOG_DB', 'logs.db', PathLocation.DATA, PathType.FILE), ('MY_CACERTS', 'cacerts.pem', PathLocation.DATA, PathType.FILE), ('PLUGINS_DOWNLOAD', 'plugins_download', PathLocation.CACHE, PathType.FOLDER), ('PLUGINS_USER', 'plugins', PathLocation.DATA, PathType.FOLDER), ('MY_EMOTS', 'emoticons', PathLocation.DATA, PathType.FOLDER_OPTIONAL), ('MY_ICONSETS', 'iconsets', PathLocation.DATA, PathType.FOLDER_OPTIONAL), ('MY_MOOD_ICONSETS', 'moods', PathLocation.DATA, PathType.FOLDER_OPTIONAL), ('MY_ACTIVITY_ICONSETS', 'activities', PathLocation.DATA, PathType.FOLDER_OPTIONAL), # Cache paths ('CACHE_DB', 'cache.db', PathLocation.CACHE, PathType.FILE), ('AVATAR', 'avatars', PathLocation.CACHE, PathType.FOLDER), # Config paths ('MY_THEME', 'theme', PathLocation.CONFIG, PathType.FOLDER), ] for path in paths: self.add(*path) _paths = ConfigPaths() # For backwards compatibility needed # some plugins use that gajimpaths = _paths gajim-gajim-1.1.3/gajim/common/connection.py000066400000000000000000002241231345766322700210030ustar00rootroot00000000000000# Copyright (C) 2003-2005 Vincent Hanquez # Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Alex Mauer # Stéphan Kochen # Copyright (C) 2005-2006 Dimitur Kirov # Travis Shirk # Nikos Kouremenos # Copyright (C) 2006 Junglecow J # Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Tomasz Melcer # Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import sys import random import socket import operator import string import time import hashlib import json import logging import base64 import ssl from functools import partial from string import Template from urllib.request import urlopen from urllib.error import URLError if sys.platform in ('win32', 'darwin'): import certifi import OpenSSL.crypto import nbxmpp from nbxmpp import Smacks from gajim import common from gajim.common import helpers from gajim.common import app from gajim.common import gpg from gajim.common import passwords from gajim.common import idle from gajim.common import i18n from gajim.common.i18n import _ from gajim.common.connection_handlers import * from gajim.common.contacts import GC_Contact from gajim.common import modules log = logging.getLogger('gajim.c.connection') SERVICE_START_TLS = 'xmpp-client' SERVICE_DIRECT_TLS = 'xmpps-client' class CommonConnection: """ Common connection class, can be derived for normal connection or zeroconf connection """ def __init__(self, name): self.name = name self._modules = {} # self.connected: # 0=>offline, # 1=>connection in progress, # 2=>online # 3=>free for chat # ... self.connected = 0 self.connection = None # xmpppy ClientCommon instance self.on_purpose = False self.is_zeroconf = False self.password = '' self.server_resource = self._compute_resource() self.gpg = None self.USE_GPG = False if app.is_installed('GPG'): self.USE_GPG = True self.gpg = gpg.GnuPG() self.status = '' self.old_show = '' self.priority = app.get_priority(name, 'offline') self.time_to_reconnect = None self.pep = {} # Do we continue connection when we get roster (send presence,get vcard..) self.continue_connect_info = None # Remember where we are in the register agent process self.agent_registrations = {} # To know the groupchat jid associated with a stanza ID. Useful to # request vcard or os info... to a real JID but act as if it comes from # the fake jid self.groupchat_jids = {} # {ID : groupchat_jid} self.roster_supported = True self.addressing_supported = False self.avatar_conversion = False self.muc_jid = {} # jid of muc server for each transport type self._stun_servers = [] # STUN servers of our jabber server self.awaiting_cids = {} # Used for XEP-0231 # Tracks the calls of the connect_machine() method self._connect_machine_calls = 0 self.get_config_values_or_default() def _compute_resource(self): resource = app.config.get_per('accounts', self.name, 'resource') # All valid resource substitution strings should be added to this hash. if resource: rand = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8)) resource = Template(resource).safe_substitute({ 'hostname': socket.gethostname(), 'rand': rand }) app.config.set_per('accounts', self.name, 'resource', resource) return resource def dispatch(self, event, data): """ Always passes account name as first param """ app.ged.raise_event(event, self.name, data) def get_module(self, name): return modules.get(self.name, name) def reconnect(self): """ To be implemented by derived classes """ raise NotImplementedError def quit(self, kill_core): if kill_core and app.account_is_connected(self.name): self.disconnect(on_purpose=True) def test_gpg_passphrase(self, password): """ Returns 'ok', 'bad_pass' or 'expired' """ if not self.gpg: return False self.gpg.passphrase = password keyID = app.config.get_per('accounts', self.name, 'keyid') signed = self.gpg.sign('test', keyID) self.gpg.password = None if signed == 'KEYEXPIRED': return 'expired' if signed == 'BAD_PASSPHRASE': return 'bad_pass' return 'ok' def get_signed_msg(self, msg, callback=None): """ Returns the signed message if possible or an empty string if gpg is not used or None if waiting for passphrase callback is the function to call when user give the passphrase """ signed = '' keyID = app.config.get_per('accounts', self.name, 'keyid') if keyID and self.USE_GPG: if self.gpg.passphrase is None and not self.gpg.use_agent: # We didn't set a passphrase return None signed = self.gpg.sign(msg, keyID) if signed == 'BAD_PASSPHRASE': self.USE_GPG = False signed = '' app.nec.push_incoming_event(BadGPGPassphraseEvent(None, conn=self)) return signed def _on_disconnected(self): """ Called when a disconnect request has completed successfully """ self.disconnect(on_purpose=True) app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) def get_status(self): return app.SHOW_LIST[self.connected] def check_jid(self, jid): """ This function must be implemented by derived classes. It has to return the valid jid, or raise a helpers.InvalidFormat exception """ raise NotImplementedError def _prepare_message(self, obj): if not self.connection or self.connected < 2: return 1 if isinstance(obj.jid, list): for jid in obj.jid: try: self.check_jid(jid) except helpers.InvalidFormat: app.nec.push_incoming_event(InformationEvent( None, dialog_name='invalid-jid', args=jid)) return else: try: self.check_jid(obj.jid) except helpers.InvalidFormat: app.nec.push_incoming_event(InformationEvent( None, dialog_name='invalid-jid', args=obj.jid)) return if obj.message and not obj.xhtml and app.config.get( 'rst_formatting_outgoing_messages'): from gajim.common.rst_xhtml_generator import create_xhtml obj.xhtml = create_xhtml(obj.message) if not obj.message and obj.chatstate is None and obj.form_node is None: return self._build_message_stanza(obj) def _build_message_stanza(self, obj): if obj.jid == app.get_jid_from_account(self.name): fjid = obj.jid else: fjid = obj.get_full_jid() if obj.type_ == 'chat': msg_iq = nbxmpp.Message(body=obj.message, typ=obj.type_, xhtml=obj.xhtml) else: if obj.subject: msg_iq = nbxmpp.Message(body=obj.message, typ='normal', subject=obj.subject, xhtml=obj.xhtml) else: msg_iq = nbxmpp.Message(body=obj.message, typ='normal', xhtml=obj.xhtml) if obj.correct_id: msg_iq.setTag('replace', attrs={'id': obj.correct_id}, namespace=nbxmpp.NS_CORRECT) # XEP-0359 obj.stanza_id = self.connection.getAnID() msg_iq.setID(obj.stanza_id) if obj.message: msg_iq.setOriginID(obj.stanza_id) if obj.form_node: msg_iq.addChild(node=obj.form_node) if obj.label: msg_iq.addChild(node=obj.label) # XEP-0172: user_nickname if obj.user_nick: msg_iq.setTag('nick', namespace=nbxmpp.NS_NICK).setData( obj.user_nick) # XEP-0203 if obj.delayed: our_jid = app.get_jid_from_account(self.name) + '/' + \ self.server_resource timestamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(obj.delayed)) msg_iq.addChild('delay', namespace=nbxmpp.NS_DELAY2, attrs={'from': our_jid, 'stamp': timestamp}) # XEP-0224 if obj.attention: msg_iq.setTag('attention', namespace=nbxmpp.NS_ATTENTION) if isinstance(obj.jid, list): if self.addressing_supported: msg_iq.setTo(app.config.get_per('accounts', self.name, 'hostname')) addresses = msg_iq.addChild('addresses', namespace=nbxmpp.NS_ADDRESS) for j in obj.jid: addresses.addChild('address', attrs={'type': 'to', 'jid': j}) else: iqs = [] for j in obj.jid: iq = nbxmpp.Message(node=msg_iq) iq.setTo(j) iqs.append(iq) msg_iq = iqs else: msg_iq.setTo(fjid) r_ = obj.resource if not r_ and obj.jid != fjid: # Only if we're not in a pm r_ = app.get_resource_from_jid(fjid) if r_: contact = app.contacts.get_contact(self.name, obj.jid, r_) else: contact = app.contacts.get_contact_with_highest_priority( self.name, obj.jid) # Mark Message as MUC PM if isinstance(contact, GC_Contact): msg_iq.setTag('x', namespace=nbxmpp.NS_MUC_USER) # chatstates - if peer supports xep85, send chatstates # please note that the only valid tag inside a message containing a # tag is the active event if obj.chatstate is not None: msg_iq.setTag(obj.chatstate, namespace=nbxmpp.NS_CHATSTATES) if not obj.message: msg_iq.setTag('no-store', namespace=nbxmpp.NS_MSG_HINTS) # XEP-0184 if obj.jid != app.get_jid_from_account(self.name): request = app.config.get_per('accounts', self.name, 'request_receipt') if obj.message and request: msg_iq.setTag('request', namespace=nbxmpp.NS_RECEIPTS) if obj.session: # XEP-0201 obj.session.last_send = time.time() msg_iq.setThread(obj.session.thread_id) self._push_stanza_message_outgoing(obj, msg_iq) def _push_stanza_message_outgoing(self, obj, msg_iq): obj.conn = self if isinstance(msg_iq, list): for iq in msg_iq: obj.msg_iq = iq app.nec.push_incoming_event( StanzaMessageOutgoingEvent(None, **vars(obj))) else: obj.msg_iq = msg_iq app.nec.push_incoming_event( StanzaMessageOutgoingEvent(None, **vars(obj))) def log_message(self, obj, jid): if not obj.is_loggable: return if obj.session and not obj.session.is_loggable(): return if not app.config.should_log(self.name, jid): return if obj.xhtml and app.config.get('log_xhtml_messages'): obj.message = '%s' % (nbxmpp.NS_XHTML, obj.xhtml) if obj.message is None: return app.logger.insert_into_logs(self.name, jid, obj.timestamp, obj.kind, message=obj.message, subject=obj.subject, additional_data=obj.additional_data, stanza_id=obj.stanza_id) def unsubscribe_agent(self, agent): """ To be implemented by derived classes """ raise NotImplementedError def update_contact(self, jid, name, groups): if self.connection: self.getRoster().set_item(jid=jid, name=name, groups=groups) def update_contacts(self, contacts): """ Update multiple roster items """ if self.connection: self.getRoster().set_item_multi(contacts) def new_account(self, name, config, sync=False): """ To be implemented by derived classes """ raise NotImplementedError def _on_new_account(self, con=None, con_type=None): """ To be implemented by derived classes """ raise NotImplementedError def account_changed(self, new_name): self.name = new_name def send_agent_status(self, agent, ptype): """ To be implemented by derived classes """ raise NotImplementedError def gpg_passphrase(self, passphrase): if self.gpg: if self.gpg.use_agent: self.gpg.passphrase = None else: self.gpg.passphrase = passphrase def ask_gpg_keys(self, keyID=None): if self.gpg: if keyID: return self.gpg.get_key(keyID) return self.gpg.get_keys() return None def ask_gpg_secrete_keys(self): if self.gpg: return self.gpg.get_secret_keys() return None def _event_dispatcher(self, realm, event, data): if realm == '': if event == 'STANZA RECEIVED': app.nec.push_incoming_event(StanzaReceivedEvent( None, conn=self, stanza_str=str(data))) elif event == 'DATA SENT': app.nec.push_incoming_event(StanzaSentEvent( None, conn=self, stanza_str=str(data))) def change_status(self, show, msg, auto=False): if not msg: msg = '' sign_msg = False if not auto and not show == 'offline': sign_msg = True if show != 'invisible': # We save it only when privacy list is accepted self.status = msg if show != 'offline' and self.connected < 1: # set old_show to requested 'show' in case we need to # recconect before we auth to server self.old_show = show self.on_purpose = False self.server_resource = self._compute_resource() if app.is_installed('GPG'): self.USE_GPG = True self.gpg = gpg.GnuPG() app.nec.push_incoming_event(BeforeChangeShowEvent(None, conn=self, show=show, message=msg)) self.connect_and_init(show, msg, sign_msg) return if show == 'offline': self.connected = 0 if self.connection: app.nec.push_incoming_event(BeforeChangeShowEvent(None, conn=self, show=show, message=msg)) p = self.get_module('Presence').get_presence( typ='unavailable', status=msg, caps=False) self.connection.RegisterDisconnectHandler(self._on_disconnected) self.connection.send(p, now=True) self.connection.start_disconnect() else: self._on_disconnected() return if show != 'offline' and self.connected > 0: # dont'try to connect, when we are in state 'connecting' if self.connected == 1: return if show == 'invisible': app.nec.push_incoming_event(BeforeChangeShowEvent(None, conn=self, show=show, message=msg)) self._change_to_invisible(msg) return if show not in ['offline', 'online', 'chat', 'away', 'xa', 'dnd']: return -1 was_invisible = self.connected == app.SHOW_LIST.index('invisible') self.connected = app.SHOW_LIST.index(show) idle_time = None if auto: if app.is_installed('IDLE') and app.config.get('autoaway'): idle_sec = idle.Monitor.get_idle_sec() idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(time.time() - idle_sec)) app.nec.push_incoming_event(BeforeChangeShowEvent(None, conn=self, show=show, message=msg)) if was_invisible: self._change_from_invisible() self._update_status(show, msg, idle_time=idle_time) class Connection(CommonConnection, ConnectionHandlers): def __init__(self, name): CommonConnection.__init__(self, name) ConnectionHandlers.__init__(self) # increase/decrease default timeout for server responses self.try_connecting_for_foo_secs = 45 # holds the actual hostname to which we are connected self.connected_hostname = None # Holds the full jid we received on the bind event self.registered_name = None self.last_time_to_reconnect = None self.new_account_info = None self.new_account_form = None self.last_sent = [] self.password = passwords.get_password(name) self.music_track_info = 0 self.register_supported = False # Do we auto accept insecure connection self.connection_auto_accepted = False self.pasword_callback = None self.on_connect_success = None self.on_connect_failure = None self.retrycount = 0 self.available_transports = {} # list of available transports on this # server {'icq': ['icq.server.com', 'icq2.server.com'], } self.streamError = '' self.removing_account = False # We only request POSH once self._posh_requested = False # Fingerprints received via POSH self._posh_hashes = [] # The SSL Errors that we can override with POSH self._posh_errors = [18, 19] self.sm = Smacks(self) # Stream Management # Register all modules modules.register(self) app.ged.register_event_handler('message-outgoing', ged.OUT_CORE, self._nec_message_outgoing) app.ged.register_event_handler('gc-message-outgoing', ged.OUT_CORE, self._nec_gc_message_outgoing) app.ged.register_event_handler('gc-stanza-message-outgoing', ged.OUT_CORE, self._nec_gc_stanza_message_outgoing) app.ged.register_event_handler('stanza-message-outgoing', ged.OUT_CORE, self._nec_stanza_message_outgoing) # END __init__ def cleanup(self): ConnectionHandlers.cleanup(self) modules.unregister(self) app.ged.remove_event_handler('message-outgoing', ged.OUT_CORE, self._nec_message_outgoing) app.ged.remove_event_handler('gc-message-outgoing', ged.OUT_CORE, self._nec_gc_message_outgoing) app.ged.remove_event_handler('gc-stanza-message-outgoing', ged.OUT_CORE, self._nec_gc_stanza_message_outgoing) app.ged.remove_event_handler('stanza-message-outgoing', ged.OUT_CORE, self._nec_stanza_message_outgoing) def get_config_values_or_default(self): if app.config.get_per('accounts', self.name, 'keep_alives_enabled'): self.keepalives = app.config.get_per('accounts', self.name, 'keep_alive_every_foo_secs') else: self.keepalives = 0 if app.config.get_per('accounts', self.name, 'ping_alives_enabled'): self.pingalives = app.config.get_per('accounts', self.name, 'ping_alive_every_foo_secs') else: self.pingalives = 0 self.client_cert = app.config.get_per('accounts', self.name, 'client_cert') self.client_cert_passphrase = '' def check_jid(self, jid): return helpers.parse_jid(jid) def get_own_jid(self, warn=False): """ Return the last full JID we received on a bind event. In case we were never connected it returns the bare JID from config. """ if self.registered_name: # This returns the full jid we received on the bind event return self.registered_name if warn: log.warning('only bare JID available') # This returns the bare jid return nbxmpp.JID(app.get_jid_from_account(self.name)) def reconnect(self): # Do not try to reco while we are already trying self.time_to_reconnect = None if self.connected < 2: # connection failed log.info('Reconnect') self.connected = 1 app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='connecting')) self.retrycount += 1 self.on_connect_auth = self._discover_server_at_connection self.connect_and_init(self.old_show, self.status, self.USE_GPG) else: log.info('Reconnect successfull') # reconnect succeeded self.time_to_reconnect = None self.retrycount = 0 # We are doing disconnect at so many places, better use one function in all def disconnect(self, on_purpose=False): log.info('Disconnect: on_purpose: %s', on_purpose) app.interface.music_track_changed(None, None, self.name) self.get_module('PEP').reset_stored_publish() self.on_purpose = on_purpose self.connected = 0 self.time_to_reconnect = None self.get_module('VCardAvatars').avatar_advertised = False if on_purpose: self.sm = Smacks(self) if self.connection: # make sure previous connection is completely closed app.proxy65_manager.disconnect(self.connection) self.terminate_sessions() self.remove_all_transfers() self.connection.disconnect() ConnectionHandlers._unregister_handlers(self) self.connection = None def set_oldst(self): # Set old state if self.old_show: self.connected = app.SHOW_LIST.index(self.old_show) app.nec.push_incoming_event(OurShowEvent( None, conn=self, show=self.old_show)) else: # we default to online self.connected = 2 app.nec.push_incoming_event(OurShowEvent( None, conn=self, show=app.SHOW_LIST[self.connected])) def disconnectedReconnCB(self): """ Called when we are disconnected """ log.info('disconnectedReconnCB called') if app.account_is_connected(self.name): # we cannot change our status to offline or connecting # after we auth to server self.old_show = app.SHOW_LIST[self.connected] self.connected = 0 if not self.on_purpose: if not (self.sm and self.sm.resumption): app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) else: self.sm.enabled = False app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='error')) if self.connection: self.connection.UnregisterDisconnectHandler( self.disconnectedReconnCB) self.disconnect() if app.config.get_per('accounts', self.name, 'autoreconnect'): self.connected = -1 app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='error')) if app.status_before_autoaway[self.name]: # We were auto away. So go back online self.status = app.status_before_autoaway[self.name] app.status_before_autoaway[self.name] = '' self.old_show = 'online' # this check has moved from reconnect method # do exponential backoff until less than 5 minutes if self.retrycount < 2 or self.last_time_to_reconnect is None: self.last_time_to_reconnect = 5 self.last_time_to_reconnect += random.randint(0, 5) if self.last_time_to_reconnect < 200: self.last_time_to_reconnect *= 1.5 self.time_to_reconnect = int(self.last_time_to_reconnect) log.info("Reconnect to %s in %ss", self.name, self.time_to_reconnect) app.idlequeue.set_alarm(self._reconnect_alarm, self.time_to_reconnect) elif self.on_connect_failure: self.on_connect_failure() self.on_connect_failure = None else: # show error dialog self._connection_lost() else: self.disconnect() self.on_purpose = False # END disconnectedReconnCB def _connection_lost(self): log.info('_connection_lost') self.disconnect(on_purpose=False) if self.removing_account: return app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Connection with account "%s" has been lost') % self.name, msg=_('Reconnect manually.'))) def _on_resume_failed(self): # SM resume failed, set all MUCs offline # and lose the presence state of all contacts app.nec.push_incoming_event(OurShowEvent( None, conn=self, show='offline')) def _event_dispatcher(self, realm, event, data): CommonConnection._event_dispatcher(self, realm, event, data) if realm == nbxmpp.NS_STREAM_MGMT: if event == 'RESUME FAILED': log.info('Resume failed') self._on_resume_failed() elif realm == nbxmpp.NS_REGISTER: if event == nbxmpp.features_nb.REGISTER_DATA_RECEIVED: # data is (agent, DataFrom, is_form, error_msg) if self.new_account_info and \ self.new_account_info['hostname'] == data[0]: # it's a new account if not data[1]: # wrong answer reason = _('Server %(name)s answered wrongly to ' 'register request: %(error)s') % {'name': data[0], 'error': data[3]} app.nec.push_incoming_event(AccountNotCreatedEvent( None, conn=self, reason=reason)) return is_form = data[2] conf = data[1] if data[4] != '': helpers.replace_dataform_media(conf, data[4]) if self.new_account_form: def _on_register_result(result): if not nbxmpp.isResultNode(result): reason = result.getErrorMsg() or result.getError() app.nec.push_incoming_event(AccountNotCreatedEvent( None, conn=self, reason=reason)) return if app.is_installed('GPG'): self.USE_GPG = True self.gpg = gpg.GnuPG() app.nec.push_incoming_event( AccountCreatedEvent(None, conn=self, account_info=self.new_account_info)) self.new_account_info = None self.new_account_form = None if self.connection: self.connection.UnregisterDisconnectHandler( self._on_new_account) self.disconnect(on_purpose=True) # it's the second time we get the form, we have info user # typed, so send them if is_form: #TODO: Check if form has changed iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=self._hostname) iq.setTag('query').addChild(node=self.new_account_form) self.connection.SendAndCallForResponse(iq, _on_register_result) else: if list(self.new_account_form.keys()).sort() != \ list(conf.keys()).sort(): # requested config has changed since first connection reason = _('Server %s provided a different ' 'registration form') % data[0] app.nec.push_incoming_event(AccountNotCreatedEvent( None, conn=self, reason=reason)) return nbxmpp.features_nb.register(self.connection, self._hostname, self.new_account_form, _on_register_result) return app.nec.push_incoming_event(NewAccountConnectedEvent(None, conn=self, config=conf, is_form=is_form)) self.connection.UnregisterDisconnectHandler( self._on_new_account) self.disconnect(on_purpose=True) return if not data[1]: # wrong answer app.nec.push_incoming_event(InformationEvent( None, dialog_name='invalid-answer', kwargs={'name': data[0], 'error': data[3]})) return def _select_next_host(self, hosts): """ Selects the next host according to RFC2782 p.3 based on it's priority. Chooses between hosts with the same priority randomly, where the probability of being selected is proportional to the weight of the host """ hosts_by_prio = sorted(hosts, key=operator.itemgetter('prio')) try: lowest_prio = hosts_by_prio[0]['prio'] except IndexError: raise ValueError("No hosts to choose from!") hosts_lowest_prio = [h for h in hosts_by_prio if h['prio'] == lowest_prio] if len(hosts_lowest_prio) == 1: return hosts_lowest_prio[0] rndint = random.randint(0, sum(h['weight'] for h in hosts_lowest_prio)) weightsum = 0 for host in sorted(hosts_lowest_prio, key=operator.itemgetter('weight')): weightsum += host['weight'] if weightsum >= rndint: return host def connect(self, data=None): """ Start a connection to the XMPP server Returns connection, and connection type ('tls', 'ssl', 'plain', '') data MUST contain hostname, proxy, use_custom_host, custom_host (if use_custom_host), custom_port (if use_custom_host) """ if self.connection: return self.connection, '' log.info('Connect') if self.sm.resuming and self.sm.location: # If resuming and server gave a location, connect from there hostname = self.sm.location self.try_connecting_for_foo_secs = app.config.get_per('accounts', self.name, 'try_connecting_for_foo_secs') use_custom = False proxy = helpers.get_proxy_info(self.name) elif data: hostname = data['hostname'] self.try_connecting_for_foo_secs = 45 p = data['proxy'] if p and p in app.config.get_per('proxies'): proxy = {} proxyptr = app.config.get_per('proxies', p) for key in proxyptr.keys(): proxy[key] = proxyptr[key] else: proxy = None use_srv = True use_custom = data['use_custom_host'] if use_custom: custom_h = data['custom_host'] custom_p = data['custom_port'] else: hostname = app.config.get_per('accounts', self.name, 'hostname') self.try_connecting_for_foo_secs = app.config.get_per('accounts', self.name, 'try_connecting_for_foo_secs') proxy = helpers.get_proxy_info(self.name) use_srv = app.config.get_per('accounts', self.name, 'use_srv') use_custom = app.config.get_per('accounts', self.name, 'use_custom_host') if use_custom: custom_h = app.config.get_per('accounts', self.name, 'custom_host') custom_p = app.config.get_per('accounts', self.name, 'custom_port') try: helpers.idn_to_ascii(custom_h) except Exception: app.nec.push_incoming_event(InformationEvent( None, dialog_name='invalid-custom-hostname', args=custom_h)) use_custom = False # create connection if it doesn't already exist self.connected = 1 h = hostname p = 5222 ssl_p = 5223 if use_custom: h = custom_h p = custom_p ssl_p = custom_p use_srv = False # SRV resolver self._proxy = proxy self._hosts = [ {'host': h, 'port': p, 'type': 'tls', 'prio': 10, 'weight': 10, 'alpn': False}, {'host': h, 'port': ssl_p, 'type': 'ssl', 'prio': 10, 'weight': 10, 'alpn': False}, {'host': h, 'port': p, 'type': 'plain', 'prio': 10, 'weight': 10, 'alpn': False} ] self._hostname = hostname if use_srv and self._proxy is None: self._srv_hosts = [] services = [SERVICE_START_TLS, SERVICE_DIRECT_TLS] self._num_pending_srv_records = len(services) for service in services: record_name = '_' + service + '._tcp.' + helpers.idn_to_ascii(h) app.resolver.resolve(record_name, self._on_resolve_srv) app.resolver.resolve('_xmppconnect.' + helpers.idn_to_ascii(h), self._on_resolve_txt, type_='txt') else: self._connect_to_next_host() def _append_srv_record(self, record, con_type): tmp = record.copy() tmp['type'] = con_type if tmp in self._srv_hosts: return self._srv_hosts.append(tmp) def _on_resolve_srv(self, host, result): for record in result: service = host[1:] if service.startswith(SERVICE_START_TLS): record['alpn'] = False self._append_srv_record(record, 'tls') self._append_srv_record(record, 'plain') elif service.startswith(SERVICE_DIRECT_TLS): record['alpn'] = True self._append_srv_record(record, 'ssl') self._num_pending_srv_records -= 1 if self._num_pending_srv_records: return if self._srv_hosts: self._hosts = self._srv_hosts.copy() self._connect_to_next_host() def _on_resolve_txt(self, host, result_array): for res in result_array: if res.startswith('_xmpp-client-xbosh='): url = res[19:] found = False proxies = app.config.get_per('proxies') for p in proxies: if app.config.get_per('proxies', p, 'type') == 'bosh' \ and app.config.get_per('proxies', p, 'bosh_uri') == url: found = True break if not found: h = app.config.get_per('accounts', self.name, 'hostname') p = 'bosh_' + h i = 0 while p in proxies: i += 1 p = 'bosh_' + h + str(i) app.config.add_per('proxies', p) app.config.set_per('proxies', p, 'type', 'bosh') app.config.set_per('proxies', p, 'bosh_uri', url) def _connect_to_next_host(self, retry=False): log.debug('Connection to next host') if not self._hosts: if not retry and self.retrycount == 0: log.debug("Out of hosts, giving up connecting to %s", self.name) self.time_to_reconnect = None if self.on_connect_failure: self.on_connect_failure() self.on_connect_failure = None else: # shown error dialog self._connection_lost() else: # try reconnect if connection has failed before auth to server self.disconnectedReconnCB() return connection_types = ['tls', 'ssl'] allow_plaintext_connection = app.config.get_per('accounts', self.name, 'allow_plaintext_connection') if allow_plaintext_connection: connection_types.append('plain') if self._proxy and self._proxy['type'] == 'bosh': # with BOSH, we can't do TLS negotiation with , we do only "plain" # connection and TLS with handshake right after TCP connecting ("ssl") scheme = nbxmpp.transports_nb.urisplit(self._proxy['bosh_uri'])[0] if scheme == 'https': connection_types = ['ssl'] else: if allow_plaintext_connection: connection_types = ['plain'] else: connection_types = [] host = self._select_next_host(self._hosts) self._hosts.remove(host) # Skip record if connection type is not supported. if host['type'] not in connection_types: log.info("Skipping connection record with unsupported type: %s", host['type']) self._connect_to_next_host(retry) return self._current_host = host self._current_type = self._current_host['type'] port = self._current_host['port'] cacerts = '' if sys.platform in ('win32', 'darwin'): cacerts = certifi.where() mycerts = common.configpaths.get('MY_CACERTS') tls_version = app.config.get_per('accounts', self.name, 'tls_version') cipher_list = app.config.get_per('accounts', self.name, 'cipher_list') secure_tuple = (self._current_type, cacerts, mycerts, tls_version, cipher_list, self._current_host['alpn']) con = nbxmpp.NonBlockingClient( domain=self._hostname, caller=self, idlequeue=app.idlequeue, lang=i18n.LANG) # increase default timeout for server responses nbxmpp.dispatcher_nb.DEFAULT_TIMEOUT_SECONDS = \ self.try_connecting_for_foo_secs # FIXME: this is a hack; need a better way if self.on_connect_success == self._on_new_account: # pylint: disable=comparison-with-callable con.RegisterDisconnectHandler(self._on_new_account) if self.client_cert and app.config.get_per('accounts', self.name, 'client_cert_encrypted'): app.nec.push_incoming_event(ClientCertPassphraseEvent( None, conn=self, con=con, port=port, secure_tuple=secure_tuple)) return self.on_client_cert_passphrase('', con, port, secure_tuple) def on_client_cert_passphrase(self, passphrase, con, port, secure_tuple): self.client_cert_passphrase = passphrase self.log_hosttype_info(port) con.connect( hostname=self._current_host['host'], port=port, on_connect=self.on_connect_success, on_proxy_failure=self.on_proxy_failure, on_connect_failure=self._connect_to_next_host, on_stream_error_cb=self._StreamCB, proxy=self._proxy, secure_tuple=secure_tuple) def log_hosttype_info(self, port): msg = '>>>>>> Connecting to %s [%s:%d], type = %s' % (self.name, self._current_host['host'], port, self._current_type) log.info(msg) if self._proxy: msg = '>>>>>> ' if self._proxy['type'] == 'bosh': msg = '%s over BOSH %s' % (msg, self._proxy['bosh_uri']) if self._proxy['type'] in ['http', 'socks5'] or self._proxy['bosh_useproxy']: msg = '%s over proxy %s:%s' % (msg, self._proxy['host'], self._proxy['port']) log.info(msg) def _connect_failure(self, con_type=None): if not con_type: # we are not retrying, and not conecting if not self.retrycount and self.connected != 0: self.disconnect(on_purpose=True) if self._proxy: pritxt = _('Could not connect to "%(host)s" via proxy "%(proxy)s"') %\ {'host': self._hostname, 'proxy': self._proxy['host']} else: pritxt = _('Could not connect to "%(host)s"') % {'host': \ self._hostname} sectxt = _('Check your connection or try again later.') if self.streamError: # show error dialog key = nbxmpp.NS_XMPP_STREAMS + ' ' + self.streamError if key in nbxmpp.ERRORS: sectxt2 = _('Server replied: %s') % nbxmpp.ERRORS[key][2] app.nec.push_incoming_event(InformationEvent(None, conn=self, level='error', pri_txt=pritxt, sec_txt='%s\n%s' % (sectxt2, sectxt))) return # show popup app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=pritxt, msg=sectxt)) def on_proxy_failure(self, reason): log.error('Connection to proxy failed: %s', reason) self.time_to_reconnect = None self.on_connect_failure = None self.disconnect(on_purpose=True) app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Connection to proxy failed'), msg=reason)) def _connect_success(self, con, con_type): if not self.connected: # We went offline during connecting process # FIXME - not possible, maybe it was when we used threads return log.info('Connect successfull') _con_type = con_type if _con_type != self._current_type: log.info('Connecting to next host beacuse desired type ' 'is %s and returned is %s', self._current_type, _con_type) self._connect_to_next_host() return con.RegisterDisconnectHandler(self._on_disconnected) if _con_type == 'plain' and app.config.get_per('accounts', self.name, 'action_when_plaintext_connection') == 'warn': app.nec.push_incoming_event(PlainConnectionEvent(None, conn=self, xmpp_client=con)) return True if _con_type == 'plain' and app.config.get_per('accounts', self.name, 'action_when_plaintext_connection') == 'disconnect': self.disconnect(on_purpose=True) app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) return False if _con_type in ('tls', 'ssl') and con.Connection.ssl_lib != 'PYOPENSSL' \ and app.config.get_per('accounts', self.name, 'warn_when_insecure_ssl_connection') and \ not self.connection_auto_accepted: # Pyopenssl is not used app.nec.push_incoming_event(InsecureSSLConnectionEvent(None, conn=self, xmpp_client=con, conn_type=_con_type)) return True return self.connection_accepted(con, con_type) def connection_accepted(self, con, con_type): if not con or not con.Connection: self.disconnect(on_purpose=True) app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not connect to account %s') % self.name, msg=_('Connection with account %s has been lost. Retry ' 'connecting.') % self.name)) return log.info('Connection accepted') self._hosts = [] self.connection_auto_accepted = False self.connected_hostname = self._current_host['host'] self.on_connect_failure = None con.UnregisterDisconnectHandler(self._on_disconnected) con.RegisterDisconnectHandler(self.disconnectedReconnCB) log.debug('Connected to server %s:%s with %s', self._current_host['host'], self._current_host['port'], con_type) self.connection = con ssl_errors = con.Connection.ssl_errors ignored_ssl_errors = self._get_ignored_ssl_errors() self._ssl_errors = [n for n in ssl_errors if n not in ignored_ssl_errors] self._ssl_errors.reverse() self.process_ssl_errors() def _get_ignored_ssl_errors(self): ignore_ssl_errors = app.config.get_per( 'accounts', self.name, 'ignore_ssl_errors').split() return [int(err) for err in ignore_ssl_errors] def process_ssl_errors(self): if not self._ssl_errors: self.ssl_certificate_accepted() return cert = self.connection.Connection.ssl_certificate errnum = self._ssl_errors.pop() # Check if we can verify the cert with POSH if errnum in self._posh_errors: # Request the POSH json file self._get_posh_file(self._hostname) self._posh_requested = True cert_hash256 = self._calculate_cert_sha256(cert) if cert_hash256 in self._posh_hashes: # Ignore this error if this cert is # verifyed with POSH self.process_ssl_errors() return app.nec.push_incoming_event(SSLErrorEvent(None, conn=self, error_num=errnum, cert=cert)) @staticmethod def _calculate_cert_sha256(cert): der_encoded = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_ASN1, cert) hash_obj = hashlib.sha256(der_encoded) hash256 = base64.b64encode(hash_obj.digest()).decode('utf8') return hash256 def _get_posh_file(self, hostname=None, redirect=None): if self._posh_requested: # We already have requested POSH return if not app.config.get_per('accounts', self.name, 'allow_posh'): return if hostname is None and redirect is None: raise ValueError('There must be either a hostname or a url') url = redirect if hostname is not None: url = 'https://%s/.well-known/posh/xmpp-client.json' % hostname cafile = None if sys.platform in ('win32', 'darwin'): cafile = certifi.where() log.info('Request POSH from %s', url) try: file = urlopen( url, cafile=cafile, timeout=2) except (URLError, ssl.CertificateError) as exc: log.info('Error while requesting POSH: %s', exc) return if file.getcode() != 200: log.info('No POSH file found at %s', url) return try: posh = json.loads(file.read()) except json.decoder.JSONDecodeError as json_error: log.warning(json_error) return # Redirect if 'url' in posh and redirect is None: # We dont allow redirects in redirects log.info('POSH redirect found') self._get_posh_file(redirect=posh['url']) return if 'fingerprints' in posh: fingerprints = posh['fingerprints'] for fingerprint in fingerprints: if 'sha-256' not in fingerprint: continue self._posh_hashes.append(fingerprint['sha-256']) log.info('POSH sha-256 fingerprints found: %s', self._posh_hashes) def ssl_certificate_accepted(self): if not self.connection: self.disconnect(on_purpose=True) app.nec.push_incoming_event( ConnectionLostEvent( None, conn=self, title=_('Could not connect to account %s') % self.name, msg=_('Connection with account %s has been lost. ' 'Retry connecting.') % self.name)) return log.info('SSL Cert accepted') name = None if not app.config.get_per('accounts', self.name, 'anonymous_auth'): name = app.config.get_per('accounts', self.name, 'name') self._register_handlers(self.connection, self._current_type) auth_mechs = app.config.get_per( 'accounts', self.name, 'authentication_mechanisms').split() for mech in auth_mechs: if mech not in nbxmpp.auth_nb.SASL_AUTHENTICATION_MECHANISMS | set(['XEP-0078']): log.warning('Unknown authentication mechanisms %s', mech) if not auth_mechs: auth_mechs = None else: auth_mechs = set(auth_mechs) self.connection.auth(user=name, password=self.password, resource=self.server_resource, sasl=True, on_auth=self.__on_auth, auth_mechs=auth_mechs) def _register_handlers(self, con, con_type): self.peerhost = con.get_peerhost() app.con_types[self.name] = con_type # notify the gui about con_type app.nec.push_incoming_event(ConnectionTypeEvent(None, conn=self, connection_type=con_type)) ConnectionHandlers._register_handlers(self, con, con_type) def __on_auth(self, con, auth): log.info('auth') if not con: self.disconnect(on_purpose=True) app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not connect to "%s"') % self._hostname, msg=_('Check your connection or try again later.'))) if self.on_connect_auth: self.on_connect_auth(None) self.on_connect_auth = None return if not self.connected: # We went offline during connecting process if self.on_connect_auth: self.on_connect_auth(None) self.on_connect_auth = None return if hasattr(con, 'Resource'): self.server_resource = con.Resource if con._registered_name is not None: log.info('Bound JID: %s', con._registered_name) self.registered_name = con._registered_name if app.config.get_per('accounts', self.name, 'anonymous_auth'): # Get jid given by server old_jid = app.get_jid_from_account(self.name) app.config.set_per('accounts', self.name, 'name', con.User) new_jid = app.get_jid_from_account(self.name) app.nec.push_incoming_event(AnonymousAuthEvent(None, conn=self, old_jid=old_jid, new_jid=new_jid)) if auth: self.connected = 2 self.retrycount = 0 if self.on_connect_auth: self.on_connect_auth(con) self.on_connect_auth = None else: if not app.config.get_per('accounts', self.name, 'savepass'): # Forget password, it's wrong self.password = None log.debug("Couldn't authenticate to %s", self._hostname) self.disconnect(on_purpose=True) app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) app.nec.push_incoming_event(InformationEvent(None, conn=self, level='error', pri_txt=_('Authentication failed with "%s"') % \ self._hostname, sec_txt=_('Please check your login and password' ' for correctness.'))) if self.on_connect_auth: self.on_connect_auth(None) self.on_connect_auth = None # END connect def send_keepalive(self): # nothing received for the last foo seconds if self.connection: self.connection.send(' ') def send_invisible_presence(self, msg, signed, initial=False): if not app.account_is_connected(self.name): return if not self.get_module('PrivacyLists').supported: app.nec.push_incoming_event(OurShowEvent(None, conn=self, show=app.SHOW_LIST[self.connected])) app.nec.push_incoming_event(InformationEvent( None, dialog_name='invisibility-not-supported', args=self.name)) return # If we are already connected, and privacy rules are supported, send # offline presence first as it's required by XEP-0126 if self.connected > 1 and self.get_module('PrivacyLists').supported: self.on_purpose = True self.remove_all_transfers() self.get_module('Presence').send_presence( typ='unavailable', status=msg, caps=False) # try to set the privacy rule self.get_module('PrivacyLists').set_invisible_rule( callback=self._continue_invisible, msg=msg, signed=signed, initial=initial) def _continue_invisible(self, con, iq_obj, msg, signed, initial): if iq_obj.getType() == 'error': # server doesn't support privacy lists return # active the privacy rule self.get_module('PrivacyLists').set_active_list('invisible') self.connected = app.SHOW_LIST.index('invisible') self.status = msg priority = app.get_priority(self.name, 'invisible') self.get_module('Presence').send_presence( priority=priority, status=msg, sign=signed) self.priority = priority app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='invisible')) if initial: if not self.avatar_conversion: # ask our VCard self.get_module('VCardTemp').request_vcard() # Get bookmarks self.get_module('Bookmarks').get_bookmarks() # Get annotations self.get_module('Annotations').get_annotations() # Blocking self.get_module('Blocking').get_blocking_list() # Inform GUI we just signed in app.nec.push_incoming_event(SignedInEvent(None, conn=self)) def get_signed_presence(self, msg, callback=None): if app.config.get_per('accounts', self.name, 'gpg_sign_presence'): return self.get_signed_msg(msg, callback) return '' def connect_and_auth(self): self.on_connect_success = self._connect_success self.on_connect_failure = self._connect_failure self.connect() def connect_and_init(self, show, msg, sign_msg): self.continue_connect_info = [show, msg, sign_msg] self.on_connect_auth = self._discover_server_at_connection self.connect_and_auth() def _discover_server_at_connection(self, con): self.connection = con if not app.account_is_connected(self.name): return self.connection.set_send_timeout(self.keepalives, self.send_keepalive) self.connection.set_send_timeout2( self.pingalives, self.get_module('Ping').send_keepalive_ping) self.connection.onreceive(None) # If we are not resuming, we ask for discovery info # and archiving preferences if not self.sm.supports_sm or (not self.sm.resuming and self.sm.enabled): # This starts the connect_machine self.get_module('Discovery').discover_server_info() self.get_module('Discovery').discover_account_info() self.get_module('Discovery').discover_server_items() self.sm.resuming = False # back to previous state # Discover Stun server(s) if self._proxy is None: hostname = app.config.get_per('accounts', self.name, 'hostname') app.resolver.resolve( '_stun._udp.' + helpers.idn_to_ascii(hostname), self._on_stun_resolved) def _on_stun_resolved(self, host, result_array): if result_array: self._stun_servers = self._hosts = [i for i in result_array] @helpers.call_counter def connect_machine(self, restart=False): log.info('Connect machine state: %s', self._connect_machine_calls) if self._connect_machine_calls == 1: self.get_module('MetaContacts').get_metacontacts() elif self._connect_machine_calls == 2: self.get_module('Delimiter').get_roster_delimiter() elif self._connect_machine_calls == 3: self.get_module('Roster').request_roster() elif self._connect_machine_calls == 4: self.send_first_presence() def send_custom_status(self, show, msg, jid): if show not in app.SHOW_LIST: return -1 if not app.account_is_connected(self.name): return sshow = helpers.get_xmpp_show(show) if not msg: msg = '' if show == 'offline': self.get_module('Presence').send_presence( jid, 'unavailable', caps=False, status=msg) else: signed = self.get_signed_presence(msg) priority = app.get_priority(self.name, sshow) self.get_module('Presence').send_presence( jid, priority=priority, show=sshow, status=msg, sign=signed) def _change_to_invisible(self, msg): signed = self.get_signed_presence(msg) self.send_invisible_presence(msg, signed) def _change_from_invisible(self): if self.get_module('PrivacyLists').supported: self.get_module('PrivacyLists').set_active_list(None) def _update_status(self, show, msg, idle_time=None): xmpp_show = helpers.get_xmpp_show(show) priority = app.get_priority(self.name, xmpp_show) signed = self.get_signed_presence(msg) self.get_module('Presence').send_presence( priority=priority, show=xmpp_show, status=msg, sign=signed, idle_time=idle_time) if self.connection: self.priority = priority app.nec.push_incoming_event(OurShowEvent(None, conn=self, show=show)) def send_motd(self, jid, subject='', msg='', xhtml=None): if not app.account_is_connected(self.name): return msg_iq = nbxmpp.Message(to=jid, body=msg, subject=subject, xhtml=xhtml) self.connection.send(msg_iq) def _nec_message_outgoing(self, obj): if obj.account != self.name: return self._prepare_message(obj) def _nec_stanza_message_outgoing(self, obj): if obj.conn.name != self.name: return config_key = '%s-%s' % (self.name, obj.jid) encryption = app.config.get_per('encryption', config_key, 'encryption') if encryption: app.plugin_manager.extension_point( 'encrypt' + encryption, self, obj, self.send_message) if not obj.encrypted: # Dont propagate event return True else: self.send_message(obj) def send_message(self, obj): obj.timestamp = time.time() obj.stanza_id = self.connection.send(obj.msg_iq, now=obj.now) app.nec.push_incoming_event(MessageSentEvent(None, **vars(obj))) if isinstance(obj.jid, list): for j in obj.jid: if obj.session is None: obj.session = self.get_or_create_session(j, '') self.log_message(obj, j) else: self.log_message(obj, obj.jid) def send_stanza(self, stanza): """ Send a stanza untouched """ if not self.connection: return self.connection.send(stanza) def unsubscribe_agent(self, agent): if not app.account_is_connected(self.name): return iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent) iq.setQuery().setTag('remove') id_ = self.connection.getAnID() iq.setID(id_) self.awaiting_answers[id_] = (AGENT_REMOVED, agent) self.connection.send(iq) self.getRoster().del_item(agent) def send_new_account_infos(self, form, is_form): if is_form: # Get username and password and put them in new_account_info for field in form.iter_fields(): if field.var == 'username': self.new_account_info['name'] = field.value if field.var == 'password': self.new_account_info['password'] = field.value else: # Get username and password and put them in new_account_info if 'username' in form: self.new_account_info['name'] = form['username'] if 'password' in form: self.new_account_info['password'] = form['password'] self.new_account_form = form self.new_account(self.name, self.new_account_info) def new_account(self, name, config, sync=False): # If a connection already exist we cannot create a new account if self.connection: return self._hostname = config['hostname'] self.new_account_info = config self.name = name self.on_connect_success = self._on_new_account self.on_connect_failure = self._on_new_account self.connect(config) app.resolver.resolve('_xmppconnect.' + helpers.idn_to_ascii( self._hostname), self._on_resolve_txt, type_='txt') def _on_new_account(self, con=None, con_type=None): if not con_type: if self._hosts: # There are still other way to try to connect return reason = _('Could not connect to "%s"') % self._hostname app.nec.push_incoming_event(NewAccountNotConnectedEvent(None, conn=self, reason=reason)) return self.on_connect_failure = None self.connection = con nbxmpp.features_nb.getRegInfo(con, self._hostname) def request_gateway_prompt(self, jid, prompt=None): def _on_prompt_result(resp): app.nec.push_incoming_event(GatewayPromptReceivedEvent(None, conn=self, stanza=resp)) if prompt: typ_ = 'set' else: typ_ = 'get' iq = nbxmpp.Iq(typ=typ_, to=jid) query = iq.addChild(name='query', namespace=nbxmpp.NS_GATEWAY) if prompt: query.setTagData('prompt', prompt) self.connection.SendAndCallForResponse(iq, _on_prompt_result) def getRoster(self): return self.get_module('Roster') def send_agent_status(self, agent, ptype): if not app.account_is_connected(self.name): return show = helpers.get_xmpp_show(app.SHOW_LIST[self.connected]) self.get_module('Presence').send_presence( agent, ptype, show=show, caps=ptype != 'unavailable') def send_captcha(self, jid, form_node): if not app.account_is_connected(self.name): return iq = nbxmpp.Iq(typ='set', to=jid) captcha = iq.addChild(name='captcha', namespace=nbxmpp.NS_CAPTCHA) captcha.addChild(node=form_node) self.connection.send(iq) def check_unique_room_id_support(self, server, instance): if not app.account_is_connected(self.name): return iq = nbxmpp.Iq(typ='get', to=server) iq.setAttr('id', 'unique1') iq.addChild('unique', namespace=nbxmpp.NS_MUC_UNIQUE) def _on_response(resp): if not nbxmpp.isResultNode(resp): app.nec.push_incoming_event(UniqueRoomIdNotSupportedEvent( None, conn=self, instance=instance, server=server)) return app.nec.push_incoming_event(UniqueRoomIdSupportedEvent(None, conn=self, instance=instance, server=server, room_id=resp.getTag('unique').getData())) self.connection.SendAndCallForResponse(iq, _on_response) def join_gc(self, nick, room_jid, password, change_nick=False, rejoin=False): # FIXME: This room JID needs to be normalized; see #1364 if not app.account_is_connected(self.name): return show = helpers.get_xmpp_show(app.SHOW_LIST[self.connected]) if show == 'invisible': # Never join a room when invisible return self.get_module('Discovery').disco_muc( room_jid, partial(self._join_gc, nick, show, room_jid, password, change_nick, rejoin)) def _join_gc(self, nick, show, room_jid, password, change_nick, rejoin): if change_nick: self.get_module('Presence').send_presence( '%s/%s' % (room_jid, nick), show=show, status=self.status) else: self.get_module('MUC').send_muc_join_presence( '%s/%s' % (room_jid, nick), show=show, status=self.status, room_jid=room_jid, password=password, rejoin=rejoin) def _nec_gc_message_outgoing(self, obj): if obj.account != self.name: return if not app.account_is_connected(self.name): return if not obj.xhtml and app.config.get('rst_formatting_outgoing_messages'): from gajim.common.rst_xhtml_generator import create_xhtml obj.xhtml = create_xhtml(obj.message) msg_iq = nbxmpp.Message(obj.jid, obj.message, typ='groupchat', xhtml=obj.xhtml) obj.stanza_id = self.connection.getAnID() msg_iq.setID(obj.stanza_id) if obj.message: msg_iq.setOriginID(obj.stanza_id) if obj.correct_id: msg_iq.setTag('replace', attrs={'id': obj.correct_id}, namespace=nbxmpp.NS_CORRECT) if obj.chatstate is not None: msg_iq.setTag(obj.chatstate, namespace=nbxmpp.NS_CHATSTATES) if not obj.message: msg_iq.setTag('no-store', namespace=nbxmpp.NS_MSG_HINTS) if obj.label is not None: msg_iq.addChild(node=obj.label) obj.msg_iq = msg_iq obj.conn = self app.nec.push_incoming_event(GcStanzaMessageOutgoingEvent(None, **vars(obj))) def _nec_gc_stanza_message_outgoing(self, obj): if obj.conn.name != self.name: return config_key = '%s-%s' % (self.name, obj.jid) encryption = app.config.get_per('encryption', config_key, 'encryption') if encryption: app.plugin_manager.extension_point( 'gc_encrypt' + encryption, self, obj, self.send_gc_message) else: self.send_gc_message(obj) def send_gc_message(self, obj): obj.stanza_id = self.connection.send(obj.msg_iq) app.nec.push_incoming_event(MessageSentEvent( None, conn=self, jid=obj.jid, message=obj.message, keyID=None, automatic_message=obj.automatic_message, stanza_id=obj.stanza_id, additional_data=obj.additional_data)) def send_gc_status(self, nick, jid, show, status, auto=False): if not app.account_is_connected(self.name): return if show == 'invisible': show = 'offline' ptype = None if show == 'offline': ptype = 'unavailable' xmpp_show = helpers.get_xmpp_show(show) idle_time = None if auto and app.is_installed('IDLE') and app.config.get('autoaway'): idle_sec = idle.Monitor.get_idle_sec() idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(time.time() - idle_sec)) self.get_module('Presence').send_presence( '%s/%s' % (jid, nick), typ=ptype, show=xmpp_show, status=status, caps=ptype != 'unavailable', idle_time=idle_time) def get_password(self, callback, type_): if app.config.get_per('accounts', self.name, 'anonymous_auth') and \ type_ != 'ANONYMOUS': app.nec.push_incoming_event( NonAnonymousServerErrorEvent(None, conn=self)) self._on_disconnected() return self.pasword_callback = (callback, type_) if type_ == 'X-MESSENGER-OAUTH2': client_id = app.config.get_per('accounts', self.name, 'oauth2_client_id') refresh_token = app.config.get_per('accounts', self.name, 'oauth2_refresh_token') if refresh_token: renew_url = ( 'https://oauth.live.com/token?client_id=' '%s&redirect_uri=https%%3A%%2F%%2Foauth.live.' 'com%%2Fdesktop&grant_type=refresh_token&' 'refresh_token=%s') % (client_id, refresh_token) result = helpers.download_image(self.name, {'src': renew_url})[0] if result: dict_ = json.loads(result) if 'access_token' in dict_: self.set_password(dict_['access_token']) return script_url = app.config.get_per('accounts', self.name, 'oauth2_redirect_url') token_url = ( 'https://oauth.live.com/authorize?client_id=' '%s&scope=wl.messenger%%20wl.offline_access&' 'response_type=code&redirect_uri=%s') % (client_id, script_url) helpers.launch_browser_mailer('url', token_url) self.disconnect(on_purpose=True) app.nec.push_incoming_event( Oauth2CredentialsRequiredEvent(None, conn=self)) return if self.password: self.set_password(self.password) return app.nec.push_incoming_event(PasswordRequiredEvent(None, conn=self)) def set_password(self, password): self.password = password if self.pasword_callback: callback, type_ = self.pasword_callback if self._current_type == 'plain' and type_ == 'PLAIN' and \ app.config.get_per('accounts', self.name, 'warn_when_insecure_password'): app.nec.push_incoming_event(InsecurePasswordEvent(None, conn=self)) return callback(password) self.pasword_callback = None def accept_insecure_password(self): if self.pasword_callback: callback = self.pasword_callback[0] callback(self.password) self.pasword_callback = None def unregister_account(self, on_remove_success): # no need to write this as a class method and keep the value of # on_remove_success as a class property as pass it as an argument def _on_unregister_account_connect(con): self.on_connect_auth = None self.removing_account = True if app.account_is_connected(self.name): hostname = app.config.get_per('accounts', self.name, 'hostname') iq = nbxmpp.Iq(typ='set', to=hostname) id_ = self.connection.getAnID() iq.setID(id_) iq.setTag(nbxmpp.NS_REGISTER + ' query').setTag('remove') def _on_answer(con, result): if result.getID() == id_: on_remove_success(True) return app.nec.push_incoming_event(InformationEvent( None, dialog_name='unregister-error', kwargs={'server': hostname, 'error': result.getErrorMsg()})) on_remove_success(False) con.RegisterHandler('iq', _on_answer, 'result', system=True) con.SendAndWaitForResponse(iq) return on_remove_success(False) self.removing_account = False if self.connected == 0: self.on_connect_auth = _on_unregister_account_connect self.connect_and_auth() else: _on_unregister_account_connect(self.connection) def _reconnect_alarm(self): if not app.config.get_per('accounts', self.name, 'active'): # Account may have been disabled return if self.time_to_reconnect: if self.connected < 2: self.reconnect() else: self.time_to_reconnect = None gajim-gajim-1.1.3/gajim/common/connection_handlers.py000066400000000000000000000606421345766322700226670ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # Junglecow J # Copyright (C) 2006-2007 Tomasz Melcer # Travis Shirk # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Julien Pivotto # Copyright (C) 2007-2008 Brendan Taylor # Jean-Marie Traissard # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import operator from time import time as time_time import nbxmpp from gajim.common import modules from gajim.common import helpers from gajim.common import app from gajim.common import jingle_xtls from gajim.common.caps_cache import muc_caps_cache from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream from gajim.common.protocol.bytestream import ConnectionIBBytestream from gajim.common.connection_handlers_events import * from gajim.common import ged from gajim.common.nec import NetworkEvent from gajim.common.const import KindConstant from gajim.common.jingle import ConnectionJingle import logging log = logging.getLogger('gajim.c.connection_handlers') # kind of events we can wait for an answer AGENT_REMOVED = 'agent_removed' # basic connection handlers used here and in zeroconf class ConnectionHandlersBase: def __init__(self): # List of IDs we are waiting answers for {id: (type_of_request, data), } self.awaiting_answers = {} # List of IDs that will produce a timeout is answer doesn't arrive # {time_of_the_timeout: (id, message to send to gui), } self.awaiting_timeouts = {} # keep track of sessions this connection has with other JIDs self.sessions = {} # IDs of sent messages (https://trac.gajim.org/ticket/8222) self.sent_message_ids = [] # We decrypt GPG messages one after the other. Keep queue in mem self.gpg_messages_to_decrypt = [] app.ged.register_event_handler('presence-received', ged.CORE, self._nec_presence_received) app.ged.register_event_handler('gc-message-received', ged.CORE, self._nec_gc_message_received) def cleanup(self): app.ged.remove_event_handler('presence-received', ged.CORE, self._nec_presence_received) app.ged.remove_event_handler('gc-message-received', ged.CORE, self._nec_gc_message_received) def _nec_presence_received(self, obj): account = obj.conn.name if account != self.name: return jid = obj.jid resource = obj.resource or '' statuss = ['offline', 'error', 'online', 'chat', 'away', 'xa', 'dnd', 'invisible'] obj.old_show = 0 obj.new_show = statuss.index(obj.show) obj.contact_list = [] highest = app.contacts.get_contact_with_highest_priority(account, jid) obj.was_highest = (highest and highest.resource == resource) # Update contact obj.contact_list = app.contacts.get_contacts(account, jid) obj.contact = None resources = [] for c in obj.contact_list: resources.append(c.resource) if c.resource == resource: obj.contact = c break if obj.contact: if obj.contact.show in statuss: obj.old_show = statuss.index(obj.contact.show) # nick changed if obj.contact_nickname is not None and \ obj.contact.contact_name != obj.contact_nickname: obj.contact.contact_name = obj.contact_nickname obj.need_redraw = True elif obj.old_show != obj.new_show or obj.contact.status != \ obj.status: obj.need_redraw = True else: obj.contact = app.contacts.get_first_contact_from_jid(account, jid) if not obj.contact: # Presence of another resource of our jid # Create self contact and add to roster if resource == obj.conn.server_resource: return # Ignore offline presence of unknown self resource if obj.new_show < 2: return obj.contact = app.contacts.create_self_contact(jid=jid, account=account, show=obj.show, status=obj.status, priority=obj.prio, keyID=obj.keyID, resource=obj.resource) app.contacts.add_contact(account, obj.contact) obj.contact_list.append(obj.contact) elif obj.contact.show in statuss: obj.old_show = statuss.index(obj.contact.show) if (resources != [''] and (len(obj.contact_list) != 1 or \ obj.contact_list[0].show not in ('not in roster', 'offline'))) and \ not app.jid_is_transport(jid): # Another resource of an existing contact connected obj.old_show = 0 obj.contact = app.contacts.copy_contact(obj.contact) obj.contact_list.append(obj.contact) obj.contact.resource = resource obj.need_redraw = True obj.need_add_in_roster = True if not app.jid_is_transport(jid) and len(obj.contact_list) == 1: # It's not an agent if obj.old_show == 0 and obj.new_show > 1: if not jid in app.newly_added[account]: app.newly_added[account].append(jid) if jid in app.to_be_removed[account]: app.to_be_removed[account].remove(jid) elif obj.old_show > 1 and obj.new_show == 0 and \ obj.conn.connected > 1: if not jid in app.to_be_removed[account]: app.to_be_removed[account].append(jid) if jid in app.newly_added[account]: app.newly_added[account].remove(jid) obj.need_redraw = True obj.contact.show = obj.show obj.contact.status = obj.status obj.contact.priority = obj.prio attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys: obj.contact.keyID = attached_keys[attached_keys.index(jid) + 1] else: # Do not override assigned key obj.contact.keyID = obj.keyID obj.contact.contact_nickname = obj.contact_nickname obj.contact.idle_time = obj.idle_time if app.jid_is_transport(jid): return # It isn't an agent # (when contact signs out or has errors) if obj.show in ('offline', 'error'): # TODO: This causes problems when another # resource signs off! self.stop_all_active_file_transfers(obj.contact) if app.config.get('log_contact_status_changes') and \ app.config.should_log(self.name, obj.jid): show = app.logger.convert_show_values_to_db_api_values(obj.show) if show is not None: app.logger.insert_into_logs(self.name, nbxmpp.JID(obj.jid).getStripped(), time_time(), KindConstant.STATUS, message=obj.status, show=show) def _check_for_mam_compliance(self, room_jid, stanza_id): namespace = muc_caps_cache.get_mam_namespace(room_jid) if stanza_id is None and namespace == nbxmpp.NS_MAM_2: log.warning('%s announces mam:2 without stanza-id', room_jid) def _nec_gc_message_received(self, obj): if obj.conn.name != self.name: return if obj.stanza.getType() == 'error': return self._check_for_mam_compliance(obj.jid, obj.stanza_id) if (app.config.should_log(obj.conn.name, obj.jid) and obj.msgtxt and obj.nick): # if not obj.nick, it means message comes from room itself # usually it hold description and can be send at each connection # so don't store it in logs app.logger.insert_into_logs(self.name, obj.jid, obj.timestamp, KindConstant.GC_MSG, message=obj.msgtxt, contact_name=obj.nick, additional_data=obj.additional_data, stanza_id=obj.stanza_id) app.logger.set_room_last_message_time(obj.room_jid, obj.timestamp) self.get_module('MAM').save_archive_id( obj.room_jid, obj.stanza_id, obj.timestamp) # process and dispatch an error message def dispatch_error_message(self, msg, msgtxt, session, frm, tim): error_msg = msg.getErrorMsg() if not error_msg: error_msg = msgtxt msgtxt = None subject = msg.getSubject() if session.is_loggable(): app.logger.insert_into_logs(self.name, nbxmpp.JID(frm).getStripped(), tim, KindConstant.ERROR, message=error_msg, subject=subject) app.nec.push_incoming_event(MessageErrorEvent(None, conn=self, fjid=frm, error_code=msg.getErrorCode(), error_msg=error_msg, msg=msgtxt, time_=tim, session=session, stanza=msg)) def get_sessions(self, jid): """ Get all sessions for the given full jid """ if not app.interface.is_pm_contact(jid, self.name): jid = app.get_jid_without_resource(jid) try: return list(self.sessions[jid].values()) except KeyError: return [] def get_or_create_session(self, fjid, thread_id): """ Return an existing session between this connection and 'jid', returns a new one if none exist """ pm = True jid = fjid if not app.interface.is_pm_contact(fjid, self.name): pm = False jid = app.get_jid_without_resource(fjid) session = self.find_session(jid, thread_id) if session: return session if pm: return self.make_new_session(fjid, thread_id, type_='pm') return self.make_new_session(fjid, thread_id) def find_session(self, jid, thread_id): try: if not thread_id: return self.find_null_session(jid) return self.sessions[jid][thread_id] except KeyError: return None def terminate_sessions(self): self.sessions = {} def delete_session(self, jid, thread_id): if not jid in self.sessions: jid = app.get_jid_without_resource(jid) if not jid in self.sessions: return del self.sessions[jid][thread_id] if not self.sessions[jid]: del self.sessions[jid] def find_null_session(self, jid): """ Find all of the sessions between us and a remote jid in which we haven't received a thread_id yet and returns the session that we last sent a message to """ sessions = list(self.sessions[jid].values()) # sessions that we haven't received a thread ID in idless = [s for s in sessions if not s.received_thread_id] # filter out everything except the default session type chat_sessions = [s for s in idless if isinstance(s, app.default_session_type)] if chat_sessions: # return the session that we last sent a message in return sorted(chat_sessions, key=operator.attrgetter('last_send'))[-1] return None def get_latest_session(self, jid): """ Get the session that we last sent a message to """ if jid not in self.sessions: return None sessions = self.sessions[jid].values() if not sessions: return None return sorted(sessions, key=operator.attrgetter('last_send'))[-1] def find_controlless_session(self, jid, resource=None): """ Find an active session that doesn't have a control attached """ try: sessions = list(self.sessions[jid].values()) # filter out everything except the default session type chat_sessions = [s for s in sessions if isinstance(s, app.default_session_type)] orphaned = [s for s in chat_sessions if not s.control] if resource: orphaned = [s for s in orphaned if s.resource == resource] return orphaned[0] except (KeyError, IndexError): return None def make_new_session(self, jid, thread_id=None, type_='chat', cls=None): """ Create and register a new session thread_id=None to generate one. type_ should be 'chat' or 'pm'. """ if not cls: cls = app.default_session_type sess = cls(self, nbxmpp.JID(jid), thread_id, type_) # determine if this session is a pm session # if not, discard the resource so that all sessions are stored bare if type_ != 'pm': jid = app.get_jid_without_resource(jid) if not jid in self.sessions: self.sessions[jid] = {} self.sessions[jid][sess.thread_id] = sess return sess class ConnectionHandlers(ConnectionSocks5Bytestream, ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream): def __init__(self): ConnectionSocks5Bytestream.__init__(self) ConnectionIBBytestream.__init__(self) # Handle presences BEFORE caps app.nec.register_incoming_event(PresenceReceivedEvent) ConnectionJingle.__init__(self) ConnectionHandlersBase.__init__(self) # IDs of disco#items requests self.disco_items_ids = [] # IDs of disco#info requests self.disco_info_ids = [] self.continue_connect_info = None # If handlers have been registered self.handlers_registered = False app.nec.register_incoming_event(StreamConflictReceivedEvent) app.nec.register_incoming_event(NotificationEvent) app.ged.register_event_handler('agent-removed', ged.CORE, self._nec_agent_removed) def cleanup(self): ConnectionHandlersBase.cleanup(self) app.ged.remove_event_handler('agent-removed', ged.CORE, self._nec_agent_removed) def _ErrorCB(self, con, iq_obj): log.debug('ErrorCB') app.nec.push_incoming_event(IqErrorReceivedEvent(None, conn=self, stanza=iq_obj)) def _IqCB(self, con, iq_obj): id_ = iq_obj.getID() app.nec.push_incoming_event(NetworkEvent('raw-iq-received', conn=self, stanza=iq_obj)) # Check if we were waiting a timeout for this id found_tim = None for tim in self.awaiting_timeouts: if id_ == self.awaiting_timeouts[tim][0]: found_tim = tim break if found_tim: del self.awaiting_timeouts[found_tim] if id_ not in self.awaiting_answers: return if self.awaiting_answers[id_][0] == AGENT_REMOVED: jid = self.awaiting_answers[id_][1] app.nec.push_incoming_event(AgentRemovedEvent(None, conn=self, agent=jid)) del self.awaiting_answers[id_] def _dispatch_gc_msg_with_captcha(self, stanza, msg_obj): msg_obj.stanza = stanza app.nec.push_incoming_event(GcMessageReceivedEvent(None, conn=self, msg_obj=msg_obj)) def _on_bob_received(self, conn, result, cid): """ Called when we receive BoB data """ if cid not in self.awaiting_cids: return if result.getType() == 'result': data = result.getTags('data', namespace=nbxmpp.NS_BOB) if data.getAttr('cid') == cid: for func in self.awaiting_cids[cid]: cb = func[0] args = func[1] pos = func[2] bob_data = data.getData() def recurs(node, cid, data): if node.getData() == 'cid:' + cid: node.setData(data) else: for child in node.getChildren(): recurs(child, cid, data) recurs(args[pos], cid, bob_data) cb(*args) del self.awaiting_cids[cid] return # An error occured, call callback without modifying data. for func in self.awaiting_cids[cid]: cb = func[0] args = func[1] cb(*args) del self.awaiting_cids[cid] def get_bob_data(self, cid, to, callback, args, position): """ Request for BoB (XEP-0231) and when data will arrive, call callback with given args, after having replaced cid by it's data in args[position] """ if cid in self.awaiting_cids: self.awaiting_cids[cid].appends((callback, args, position)) else: self.awaiting_cids[cid] = [(callback, args, position)] iq = nbxmpp.Iq(to=to, typ='get') iq.addChild(name='data', attrs={'cid': cid}, namespace=nbxmpp.NS_BOB) self.connection.SendAndCallForResponse(iq, self._on_bob_received, {'cid': cid}) def _nec_agent_removed(self, obj): if obj.conn.name != self.name: return for jid in obj.jid_list: log.debug('Removing contact %s due to unregistered transport %s', jid, obj.agent) self.get_module('Presence').unsubscribe(jid) # Transport contacts can't have 2 resources if jid in app.to_be_removed[self.name]: # This way we'll really remove it app.to_be_removed[self.name].remove(jid) def discover_ft_proxies(self): cfg_proxies = app.config.get_per('accounts', self.name, 'file_transfer_proxies') our_jid = helpers.parse_jid(app.get_jid_from_account(self.name) + \ '/' + self.server_resource) testit = app.config.get_per('accounts', self.name, 'test_ft_proxies_on_startup') if cfg_proxies: proxies = [e.strip() for e in cfg_proxies.split(',')] for proxy in proxies: app.proxy65_manager.resolve(proxy, self.connection, our_jid, testit=testit) def send_first_presence(self): if self.connected > 1 and self.continue_connect_info: msg = self.continue_connect_info[1] sign_msg = self.continue_connect_info[2] signed = '' send_first_presence = True if sign_msg: signed = self.get_signed_presence(msg, self._send_first_presence) if signed is None: app.nec.push_incoming_event(GPGPasswordRequiredEvent(None, conn=self, callback=self._send_first_presence)) # _send_first_presence will be called when user enter # passphrase send_first_presence = False if send_first_presence: self._send_first_presence(signed) def _send_first_presence(self, signed=''): show = self.continue_connect_info[0] msg = self.continue_connect_info[1] sign_msg = self.continue_connect_info[2] if sign_msg and not signed: signed = self.get_signed_presence(msg) if signed is None: app.nec.push_incoming_event(BadGPGPassphraseEvent(None, conn=self)) self.USE_GPG = False signed = '' self.connected = app.SHOW_LIST.index(show) sshow = helpers.get_xmpp_show(show) # send our presence if show == 'invisible': self.send_invisible_presence(msg, signed, True) return if show not in ['offline', 'online', 'chat', 'away', 'xa', 'dnd']: return priority = app.get_priority(self.name, sshow) self.get_module('Presence').send_presence( priority=priority, show=sshow, status=msg, sign=signed) if self.connection: self.priority = priority app.nec.push_incoming_event(OurShowEvent(None, conn=self, show=show)) if not self.avatar_conversion: # ask our VCard self.get_module('VCardTemp').request_vcard() self.get_module('Bookmarks').get_bookmarks() self.get_module('Annotations').get_annotations() self.get_module('Blocking').get_blocking_list() # Inform GUI we just signed in app.nec.push_incoming_event(SignedInEvent(None, conn=self)) self.get_module('PEP').send_stored_publish() self.continue_connect_info = None def _PubkeyGetCB(self, con, iq_obj): log.info('PubkeyGetCB') jid_from = helpers.get_full_jid_from_iq(iq_obj) sid = iq_obj.getAttr('id') jingle_xtls.send_cert(con, jid_from, sid) raise nbxmpp.NodeProcessed def _PubkeyResultCB(self, con, iq_obj): log.info('PubkeyResultCB') jid_from = helpers.get_full_jid_from_iq(iq_obj) jingle_xtls.handle_new_cert(con, iq_obj, jid_from) def _StreamCB(self, con, obj): log.debug('StreamCB') app.nec.push_incoming_event(StreamReceivedEvent(None, conn=self, stanza=obj)) def _register_handlers(self, con, con_type): # try to find another way to register handlers in each class # that defines handlers con.RegisterHandler('iq', self._siSetCB, 'set', nbxmpp.NS_SI) con.RegisterHandler('iq', self._siErrorCB, 'error', nbxmpp.NS_SI) con.RegisterHandler('iq', self._siResultCB, 'result', nbxmpp.NS_SI) con.RegisterHandler('iq', self._bytestreamSetCB, 'set', nbxmpp.NS_BYTESTREAM) con.RegisterHandler('iq', self._bytestreamResultCB, 'result', nbxmpp.NS_BYTESTREAM) con.RegisterHandler('iq', self._bytestreamErrorCB, 'error', nbxmpp.NS_BYTESTREAM) con.RegisterHandlerOnce('iq', self.IBBAllIqHandler) con.RegisterHandler('iq', self.IBBIqHandler, ns=nbxmpp.NS_IBB) con.RegisterHandler('message', self.IBBMessageHandler, ns=nbxmpp.NS_IBB) con.RegisterHandler('iq', self._JingleCB, 'result') con.RegisterHandler('iq', self._JingleCB, 'error') con.RegisterHandler('iq', self._JingleCB, 'set', nbxmpp.NS_JINGLE) con.RegisterHandler('iq', self._ErrorCB, 'error') con.RegisterHandler('iq', self._IqCB) con.RegisterHandler('iq', self._ResultCB, 'result') con.RegisterHandler('unknown', self._StreamCB, nbxmpp.NS_XMPP_STREAMS, xmlns=nbxmpp.NS_STREAMS) con.RegisterHandler('iq', self._PubkeyGetCB, 'get', nbxmpp.NS_PUBKEY_PUBKEY) con.RegisterHandler('iq', self._PubkeyResultCB, 'result', nbxmpp.NS_PUBKEY_PUBKEY) for handler in modules.get_handlers(self): con.RegisterHandler(*handler) self.handlers_registered = True def _unregister_handlers(self): if not self.connection: return for handler in modules.get_handlers(self): self.connection.UnregisterHandler(*handler) self.handlers_registered = False gajim-gajim-1.1.3/gajim/common/connection_handlers_events.py000066400000000000000000001312661345766322700242540ustar00rootroot00000000000000# Copyright (C) 2010-2014 Yann Leboulanger # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # pylint: disable=no-init # pylint: disable=attribute-defined-outside-init import logging from time import time as time_time import OpenSSL.crypto import nbxmpp from gajim.common import nec from gajim.common import helpers from gajim.common import app from gajim.common import i18n from gajim.common.i18n import _ from gajim.common.helpers import AdditionalDataDict from gajim.common.modules import dataforms from gajim.common.modules.misc import parse_idle from gajim.common.modules.misc import parse_delay from gajim.common.const import KindConstant, SSLError from gajim.common.pep import SUPPORTED_PERSONAL_USER_EVENTS from gajim.common.jingle_transport import JingleTransportSocks5 from gajim.common.file_props import FilesProp log = logging.getLogger('gajim.c.connection_handlers_events') CONDITION_TO_CODE = { 'realjid-public': 100, 'affiliation-changed': 101, 'unavailable-shown': 102, 'unavailable-not-shown': 103, 'configuration-changed': 104, 'self-presence': 110, 'logging-enabled': 170, 'logging-disabled': 171, 'non-anonymous': 172, 'semi-anonymous': 173, 'fully-anonymous': 174, 'room-created': 201, 'nick-assigned': 210, 'banned': 301, 'new-nick': 303, 'kicked': 307, 'removed-affiliation': 321, 'removed-membership': 322, 'removed-shutdown': 332, } class HelperEvent: def get_jid_resource(self, check_fake_jid=False): if check_fake_jid and hasattr(self, 'id_') and \ self.id_ in self.conn.groupchat_jids: self.fjid = self.conn.groupchat_jids[self.id_] del self.conn.groupchat_jids[self.id_] else: self.fjid = helpers.get_full_jid_from_iq(self.stanza) if self.fjid is None: self.jid = None else: self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) def get_id(self): self.id_ = self.stanza.getID() def get_gc_control(self): self.gc_control = app.interface.msg_win_mgr.get_gc_control(self.jid, self.conn.name) # If gc_control is missing - it may be minimized. Try to get it # from there. If it's not there - then it's missing anyway and # will remain set to None. if not self.gc_control: minimized = app.interface.minimized_controls[self.conn.name] self.gc_control = minimized.get(self.jid) def get_oob_data(self, stanza): oob_node = stanza.getTag('x', namespace=nbxmpp.NS_X_OOB) if oob_node is not None: oob_url = oob_node.getTagData('url') if oob_url is not None: self.additional_data.set_value('gajim', 'oob_url', oob_url) oob_desc = oob_node.getTagData('desc') if oob_desc is not None: self.additional_data.set_value('gajim', 'oob_desc', oob_desc) def get_stanza_id(self, stanza, query=False): if query: # On a MAM query the stanza-id is maybe not set, so # get the id of the stanza return stanza.getAttr('id') stanza_id, by = stanza.getStanzaIDAttrs() if by is None: # We can not verify who set this stanza-id, ignore it. return if stanza.getType() == 'groupchat': if stanza.getFrom().bareMatch(by): # by attribute must match the server return stanza_id elif self.conn.get_own_jid().bareMatch(by): # by attribute must match the server return stanza_id return @staticmethod def get_forwarded_message(stanza): forwarded = stanza.getTag('forwarded', namespace=nbxmpp.NS_FORWARD, protocol=True) if forwarded is not None: return forwarded.getTag('message', protocol=True) def _is_self_message(self, message): if self.self_message is not None: return self.self_message own_jid = self.conn.get_own_jid() frm = message.getFrom() to = message.getTo() # If 'to' is not set we assume own jid self.self_message = frm.bareMatch(to or own_jid) return self.self_message def _is_muc_pm(self, message): if self.muc_pm is not None: return self.muc_pm self.muc_pm = False muc_user = message.getTag('x', namespace=nbxmpp.NS_MUC_USER) if muc_user is not None: self.muc_pm = muc_user.getChildren() == [] return self.muc_pm class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'iq-error-received' def generate(self): self.get_id() self.get_jid_resource(check_fake_jid=True) self.errmsg = self.stanza.getErrorMsg() self.errcode = self.stanza.getErrorCode() return True class StreamReceivedEvent(nec.NetworkIncomingEvent): name = 'stream-received' class StreamConflictReceivedEvent(nec.NetworkIncomingEvent): name = 'stream-conflict-received' base_network_events = ['stream-received'] def generate(self): if self.base_event.stanza.getTag('conflict'): self.conn = self.base_event.conn return True class PresenceHelperEvent: def _generate_show(self): self.show = self.stanza.getShow() if self.show not in ('chat', 'away', 'xa', 'dnd'): self.show = '' # We ignore unknown show if not self.ptype and not self.show: self.show = 'online' elif self.ptype == 'unavailable': self.show = 'offline' def _generate_ptype(self): self.ptype = self.stanza.getType() if self.ptype == 'available': self.ptype = None rfc_types = ('unavailable', 'error', 'subscribe', 'subscribed', 'unsubscribe', 'unsubscribed') if self.ptype and not self.ptype in rfc_types: self.ptype = None class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent, PresenceHelperEvent): name = 'presence-received' base_network_events = ['raw-pres-received'] def _generate_keyID(self, sig_tag): self.keyID = '' if sig_tag and self.conn.USE_GPG and self.ptype != 'error': # error presences contain our own signature # verify sig_msg = sig_tag.getData() self.keyID = self.conn.gpg.verify(self.status, sig_msg) self.keyID = helpers.prepare_and_validate_gpg_keyID(self.conn.name, self.jid, self.keyID) def _generate_prio(self): self.prio = self.stanza.getPriority() try: self.prio = int(self.prio) except Exception: self.prio = 0 def generate(self): self.conn = self.base_event.conn self.stanza = self.base_event.stanza self.need_add_in_roster = False self.need_redraw = False self.popup = False # Do we want to open chat window ? if not self.conn or self.conn.connected < 2: log.debug('account is no more connected') return self._generate_ptype() try: self.get_jid_resource() except Exception: log.warning('Invalid JID: %s, ignoring it', self.stanza.getFrom()) return jid_list = app.contacts.get_jid_list(self.conn.name) self.timestamp = None self.get_id() self.is_gc = False # is it a GC presence ? sig_tag = None self.avatar_sha = None # XEP-0172 User Nickname self.user_nick = self.stanza.getTagData('nick') or '' self.contact_nickname = None self.transport_auto_auth = False # XEP-0203 self.timestamp = parse_delay(self.stanza) if self.timestamp is None: self.timestamp = time_time() # XEP-0319 self.idle_time = parse_idle(self.stanza) xtags = self.stanza.getTags('x') for x in xtags: namespace = x.getNamespace() if namespace in (nbxmpp.NS_MUC_USER, nbxmpp.NS_MUC): self.is_gc = True elif namespace == nbxmpp.NS_SIGNED: sig_tag = x self.status = self.stanza.getStatus() or '' self._generate_show() self._generate_prio() self._generate_keyID(sig_tag) self.errcode = self.stanza.getErrorCode() self.errmsg = self.stanza.getErrorMsg() if self.is_gc: app.nec.push_incoming_event( GcPresenceReceivedEvent( None, conn=self.conn, stanza=self.stanza, presence_obj=self)) return if self.ptype == 'error': return if not self.ptype or self.ptype == 'unavailable': our_jid = app.get_jid_from_account(self.conn.name) if self.jid == our_jid and self.resource == self.conn.server_resource: # We got our own presence app.nec.push_incoming_event(OurShowEvent(None, conn=self.conn, show=self.show)) elif self.jid in jid_list or self.jid == our_jid: return True class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent): name = 'presence-received' def generate(self): self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) self.resource = 'local' self.prio = 0 self.keyID = None self.idle_time = None self.timestamp = 0 self.contact_nickname = None self.avatar_sha = None self.need_add_in_roster = False self.need_redraw = False if self.show == 'offline': self.ptype = 'unavailable' else: self.ptype = None self.is_gc = False self.user_nick = '' self.transport_auto_auth = False self.errcode = None self.errmsg = '' self.popup = False # Do we want to open chat window ? return True class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'gc-presence-received' def generate(self): self.ptype = self.presence_obj.ptype self.fjid = self.presence_obj.fjid self.jid = self.presence_obj.jid self.room_jid = self.presence_obj.jid self.nick = self.presence_obj.resource self.show = self.presence_obj.show self.status = self.presence_obj.status self.avatar_sha = self.presence_obj.avatar_sha self.errcode = self.presence_obj.errcode self.errmsg = self.presence_obj.errmsg self.errcon = self.stanza.getError() self.get_gc_control() self.gc_contact = app.contacts.get_gc_contact(self.conn.name, self.room_jid, self.nick) if self.ptype == 'error': return True if self.ptype and self.ptype != 'unavailable': return if app.config.get('log_contact_status_changes') and \ app.config.should_log(self.conn.name, self.room_jid): if self.gc_contact: jid = self.gc_contact.jid else: jid = self.stanza.getJid() st = self.status if jid: # we know real jid, save it in db st += ' (%s)' % jid show = app.logger.convert_show_values_to_db_api_values(self.show) if show is not None: fjid = nbxmpp.JID(self.fjid) app.logger.insert_into_logs(self.conn.name, fjid.getStripped(), time_time(), KindConstant.GCSTATUS, contact_name=fjid.getResource(), message=st, show=show) # NOTE: if it's a gc presence, don't ask vcard here. # We may ask it to real jid in gui part. self.status_code = [] ns_muc_user_x = self.stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER) if ns_muc_user_x: destroy = ns_muc_user_x.getTag('destroy') else: destroy = None if ns_muc_user_x and destroy: # Room has been destroyed. see # http://www.xmpp.org/extensions/xep-0045.html#destroyroom self.reason = _('Room has been destroyed') r = destroy.getTagData('reason') if r: self.reason += ' (%s)' % r if destroy.getAttr('jid'): try: jid = helpers.parse_jid(destroy.getAttr('jid')) self.reason += '\n' + \ _('You can join this room instead: %s') % jid except helpers.InvalidFormat: pass self.status_code = ['destroyed'] else: self.reason = self.stanza.getReason() conditions = self.stanza.getStatusConditions() if conditions: self.status_code = [] for condition in conditions: if condition in CONDITION_TO_CODE: self.status_code.append(CONDITION_TO_CODE[condition]) else: self.status_code = self.stanza.getStatusCode() self.role = self.stanza.getRole() self.affiliation = self.stanza.getAffiliation() self.real_jid = self.stanza.getJid() self.actor = self.stanza.getActor() self.new_nick = self.stanza.getNewNick() return True class OurShowEvent(nec.NetworkIncomingEvent): name = 'our-show' class BeforeChangeShowEvent(nec.NetworkIncomingEvent): name = 'before-change-show' class GcMessageReceivedEvent(nec.NetworkIncomingEvent): name = 'gc-message-received' def generate(self): self.stanza = self.msg_obj.stanza if not hasattr(self.msg_obj, 'additional_data'): self.additional_data = AdditionalDataDict() else: self.additional_data = self.msg_obj.additional_data self.id_ = self.msg_obj.stanza.getID() self.unique_id = self.msg_obj.unique_id self.fjid = self.msg_obj.fjid self.msgtxt = self.msg_obj.msgtxt self.jid = self.msg_obj.jid self.room_jid = self.msg_obj.jid self.nickname = self.msg_obj.resource self.timestamp = self.msg_obj.timestamp self.xhtml_msgtxt = self.stanza.getXHTML() self.encrypted = self.msg_obj.encrypted self.correct_id = None # XEP-0308 self.delayed = self.msg_obj.delayed if app.config.get('ignore_incoming_xhtml'): self.xhtml_msgtxt = None if self.msg_obj.resource: # message from someone self.nick = self.msg_obj.resource else: # message from server self.nick = '' conditions = self.stanza.getStatusConditions() if conditions: self.status_code = [] for condition in conditions: if condition in CONDITION_TO_CODE: self.status_code.append(CONDITION_TO_CODE[condition]) else: self.status_code = self.stanza.getStatusCode() if not self.stanza.getTag('body'): # no # It could be a config change. See # http://www.xmpp.org/extensions/xep-0045.html#roomconfig-notify if self.stanza.getTag('x'): if self.status_code != []: app.nec.push_incoming_event(GcConfigChangedReceivedEvent( None, conn=self.conn, msg_event=self)) if self.msg_obj.form_node: # It could be a voice request. See # http://www.xmpp.org/extensions/xep-0045.html#voiceapprove from gajim.gtk.single_message import SingleMessageWindow SingleMessageWindow( self.conn.name, self.fjid, action='receive', from_whom=self.fjid, subject='', message='', resource='', session=None, form_node=self.msg_obj.form_node) return from gajim.common.modules.security_labels import parse_securitylabel self.displaymarking = parse_securitylabel(self.stanza) self.captcha_form = None captcha_tag = self.stanza.getTag('captcha', namespace=nbxmpp.NS_CAPTCHA) if captcha_tag: self.captcha_form = captcha_tag.getTag('x', namespace=nbxmpp.NS_DATA) for field in self.captcha_form.getTags('field'): for media in field.getTags('media'): for uri in media.getTags('uri'): uri_data = uri.getData() if uri_data.startswith('cid:'): uri_data = uri_data[4:] found = False for data in self.stanza.getTags('data', namespace=nbxmpp.NS_BOB): if data.getAttr('cid') == uri_data: uri.setData(data.getData()) found = True if not found: self.conn.get_bob_data(uri_data, self.fjid, self.conn._dispatch_gc_msg_with_captcha, [self.stanza, self.msg_obj], 0) return from gajim.common.modules.misc import parse_correction self.correct_id = parse_correction(self.stanza) return True class GcConfigChangedReceivedEvent(nec.NetworkIncomingEvent): name = 'gc-config-changed-received' def generate(self): self.conn = self.msg_event.conn self.stanza = self.msg_event.stanza self.room_jid = self.msg_event.room_jid self.status_code = self.msg_event.status_code return True class MessageSentEvent(nec.NetworkIncomingEvent): name = 'message-sent' def generate(self): if not self.automatic_message: self.conn.sent_message_ids.append(self.stanza_id) # only record the last 20000 message ids (should be about 1MB [36 byte per uuid] # and about 24 hours if you send out a message every 5 seconds) self.conn.sent_message_ids = self.conn.sent_message_ids[-20000:] return True class MessageNotSentEvent(nec.NetworkIncomingEvent): name = 'message-not-sent' class MessageErrorEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'message-error' def init(self): self.zeroconf = False def generate(self): if self.zeroconf: return True self.get_id() #only alert for errors of explicitly sent messages (see https://trac.gajim.org/ticket/8222) if self.id_ in self.conn.sent_message_ids: self.conn.sent_message_ids.remove(self.id_) return True return False class AnonymousAuthEvent(nec.NetworkIncomingEvent): name = 'anonymous-auth' class JingleRequestReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-request-received' def generate(self): self.fjid = self.jingle_session.peerjid self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) self.sid = self.jingle_session.sid return True class JingleConnectedReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-connected-received' def generate(self): self.fjid = self.jingle_session.peerjid self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) self.sid = self.jingle_session.sid return True class JingleDisconnectedReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-disconnected-received' def generate(self): self.fjid = self.jingle_session.peerjid self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) self.sid = self.jingle_session.sid return True class JingleTransferCancelledEvent(nec.NetworkIncomingEvent): name = 'jingleFT-cancelled-received' def generate(self): self.fjid = self.jingle_session.peerjid self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) self.sid = self.jingle_session.sid return True class JingleErrorReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-error-received' def generate(self): self.fjid = self.jingle_session.peerjid self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) self.sid = self.jingle_session.sid return True class AccountCreatedEvent(nec.NetworkIncomingEvent): name = 'account-created' class AccountNotCreatedEvent(nec.NetworkIncomingEvent): name = 'account-not-created' class NewAccountConnectedEvent(nec.NetworkIncomingEvent): name = 'new-account-connected' def generate(self): try: self.errnum = self.conn.connection.Connection.ssl_errnum except AttributeError: self.errnum = 0 # we don't have an errnum self.ssl_msg = '' if self.errnum > 0: self.ssl_msg = SSLError.get(self.errnum, _('Unknown SSL error: %d') % self.errnum) self.ssl_cert = '' self.ssl_fingerprint_sha1 = '' self.ssl_fingerprint_sha256 = '' if self.conn.connection.Connection.ssl_certificate: cert = self.conn.connection.Connection.ssl_certificate self.ssl_cert = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, cert).decode('utf-8') self.ssl_fingerprint_sha1 = cert.digest('sha1').decode('utf-8') self.ssl_fingerprint_sha256 = cert.digest('sha256').decode('utf-8') return True class NewAccountNotConnectedEvent(nec.NetworkIncomingEvent): name = 'new-account-not-connected' class ConnectionTypeEvent(nec.NetworkIncomingEvent): name = 'connection-type' class StanzaReceivedEvent(nec.NetworkIncomingEvent): name = 'stanza-received' class StanzaSentEvent(nec.NetworkIncomingEvent): name = 'stanza-sent' class AgentRemovedEvent(nec.NetworkIncomingEvent): name = 'agent-removed' def generate(self): self.jid_list = [] for jid in app.contacts.get_jid_list(self.conn.name): if jid.endswith('@' + self.agent): self.jid_list.append(jid) return True class BadGPGPassphraseEvent(nec.NetworkIncomingEvent): name = 'bad-gpg-passphrase' def generate(self): self.account = self.conn.name self.use_gpg_agent = app.config.get('use_gpg_agent') self.keyID = app.config.get_per('accounts', self.conn.name, 'keyid') return True class ConnectionLostEvent(nec.NetworkIncomingEvent): name = 'connection-lost' def generate(self): app.nec.push_incoming_event(OurShowEvent(None, conn=self.conn, show='offline')) return True class GPGTrustKeyEvent(nec.NetworkIncomingEvent): name = 'gpg-trust-key' class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent): name = 'gpg-password-required' def generate(self): self.keyid = app.config.get_per('accounts', self.conn.name, 'keyid') return True class PEPReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'pep-received' def generate(self): if not self.stanza.getTag('event'): return if self.stanza.getTag('error'): log.debug('PEPReceivedEvent received error stanza. Ignoring') return try: self.get_jid_resource() except Exception: return self.event_tag = self.stanza.getTag('event') for pep_class in SUPPORTED_PERSONAL_USER_EVENTS: pep = pep_class.get_tag_as_PEP(self.fjid, self.conn.name, self.event_tag) if pep: self.pep_type = pep.type_ return True class PlainConnectionEvent(nec.NetworkIncomingEvent): name = 'plain-connection' class InsecurePasswordEvent(nec.NetworkIncomingEvent): name = 'insecure-password' class InsecureSSLConnectionEvent(nec.NetworkIncomingEvent): name = 'insecure-ssl-connection' class SSLErrorEvent(nec.NetworkIncomingEvent): name = 'ssl-error' class UniqueRoomIdSupportedEvent(nec.NetworkIncomingEvent): name = 'unique-room-id-supported' class UniqueRoomIdNotSupportedEvent(nec.NetworkIncomingEvent): name = 'unique-room-id-not-supported' class NonAnonymousServerErrorEvent(nec.NetworkIncomingEvent): name = 'non-anonymous-server-error' class UpdateGCAvatarEvent(nec.NetworkIncomingEvent): name = 'update-gc-avatar' def generate(self): return True class UpdateRosterAvatarEvent(nec.NetworkIncomingEvent): name = 'update-roster-avatar' def generate(self): return True class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent): name = 'update-room-avatar' def generate(self): return True class ZeroconfNameConflictEvent(nec.NetworkIncomingEvent): name = 'zeroconf-name-conflict' class PasswordRequiredEvent(nec.NetworkIncomingEvent): name = 'password-required' class Oauth2CredentialsRequiredEvent(nec.NetworkIncomingEvent): name = 'oauth2-credentials-required' class SignedInEvent(nec.NetworkIncomingEvent): name = 'signed-in' class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'file-request-received' def init(self): self.jingle_content = None self.FT_content = None def generate(self): self.get_id() self.fjid = self.conn._ft_get_from(self.stanza) self.jid = app.get_jid_without_resource(self.fjid) if self.jingle_content: secu = self.jingle_content.getTag('security') self.FT_content.use_security = bool(secu) if secu: fingerprint = secu.getTag('fingerprint') if fingerprint: self.FT_content.x509_fingerprint = fingerprint.getData() if not self.FT_content.transport: self.FT_content.transport = JingleTransportSocks5() self.FT_content.transport.set_our_jid( self.FT_content.session.ourjid) self.FT_content.transport.set_connection( self.FT_content.session.connection) sid = self.stanza.getTag('jingle').getAttr('sid') self.file_props = FilesProp.getNewFileProp(self.conn.name, sid) self.file_props.transport_sid = self.FT_content.transport.sid self.FT_content.file_props = self.file_props self.FT_content.transport.set_file_props(self.file_props) self.file_props.streamhosts.extend( self.FT_content.transport.remote_candidates) for host in self.file_props.streamhosts: host['initiator'] = self.FT_content.session.initiator host['target'] = self.FT_content.session.responder self.file_props.session_type = 'jingle' self.file_props.stream_methods = nbxmpp.NS_BYTESTREAM desc = self.jingle_content.getTag('description') if self.jingle_content.getAttr('creator') == 'initiator': file_tag = desc.getTag('file') self.file_props.sender = self.fjid self.file_props.receiver = self.conn._ft_get_our_jid() else: file_tag = desc.getTag('file') h = file_tag.getTag('hash') h = h.getData() if h else None n = file_tag.getTag('name') n = n.getData() if n else None pjid = app.get_jid_without_resource(self.fjid) file_info = self.conn.get_file_info( pjid, hash_=h, name=n, account=self.conn.name) self.file_props.file_name = file_info['file-name'] self.file_props.sender = self.conn._ft_get_our_jid() self.file_props.receiver = self.fjid self.file_props.type_ = 's' for child in file_tag.getChildren(): name = child.getName() val = child.getData() if val is None: continue if name == 'name': self.file_props.name = val if name == 'size': self.file_props.size = int(val) if name == 'hash': self.file_props.algo = child.getAttr('algo') self.file_props.hash_ = val if name == 'date': self.file_props.date = val else: si = self.stanza.getTag('si') self.file_props = FilesProp.getNewFileProp(self.conn.name, si.getAttr('id')) self.file_props.transport_sid = self.file_props.sid profile = si.getAttr('profile') if profile != nbxmpp.NS_FILE: self.conn.send_file_rejection(self.file_props, code='400', typ='profile') raise nbxmpp.NodeProcessed feature_tag = si.getTag('feature', namespace=nbxmpp.NS_FEATURE) if not feature_tag: return form_tag = feature_tag.getTag('x', namespace=nbxmpp.NS_DATA) if not form_tag: return self.dataform = dataforms.extend_form(node=form_tag) for f in self.dataform.iter_fields(): if f.var == 'stream-method' and f.type_ == 'list-single': values = [o[1] for o in f.options] self.file_props.stream_methods = ' '.join(values) if nbxmpp.NS_BYTESTREAM in values or \ nbxmpp.NS_IBB in values: break else: self.conn.send_file_rejection(self.file_props, code='400', typ='stream') raise nbxmpp.NodeProcessed file_tag = si.getTag('file') for name, val in file_tag.getAttrs().items(): if val is None: continue if name == 'name': self.file_props.name = val if name == 'size': self.file_props.size = int(val) mime_type = si.getAttr('mime-type') if mime_type is not None: self.file_props.mime_type = mime_type self.file_props.sender = self.fjid self.file_props.receiver = self.conn._ft_get_our_jid() self.file_props.request_id = self.id_ file_desc_tag = file_tag.getTag('desc') if file_desc_tag is not None: self.file_props.desc = file_desc_tag.getData() self.file_props.transfered_size = [] return True class FileRequestErrorEvent(nec.NetworkIncomingEvent): name = 'file-request-error' def generate(self): self.jid = app.get_jid_without_resource(self.jid) return True class FileTransferCompletedEvent(nec.NetworkIncomingEvent): name = 'file-transfer-completed' def generate(self): jid = str(self.file_props.receiver) self.jid = app.get_jid_without_resource(jid) return True class GatewayPromptReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'gateway-prompt-received' def generate(self): self.get_jid_resource() query = self.stanza.getTag('query') if query: self.desc = query.getTagData('desc') self.prompt = query.getTagData('prompt') self.prompt_jid = query.getTagData('jid') else: self.desc = None self.prompt = None self.prompt_jid = None return True class NotificationEvent(nec.NetworkIncomingEvent): name = 'notification' base_network_events = ['decrypted-message-received', 'gc-message-received', 'presence-received'] def generate(self): # what's needed to compute output self.account = self.base_event.conn.name self.conn = self.base_event.conn self.jid = '' self.control = None self.control_focused = False self.first_unread = False # For output self.do_sound = False self.sound_file = '' self.sound_event = '' # gajim sound played if not sound_file is set self.show_popup = False self.do_popup = False self.popup_title = '' self.popup_text = '' self.popup_event_type = '' self.popup_msg_type = '' self.icon_name = None self.transport_name = None self.show = None self.popup_timeout = -1 self.do_command = False self.command = '' self.show_in_notification_area = False self.show_in_roster = False self.detect_type() if self.notif_type == 'msg': self.handle_incoming_msg_event(self.base_event) elif self.notif_type == 'gc-msg': self.handle_incoming_gc_msg_event(self.base_event) elif self.notif_type == 'pres': self.handle_incoming_pres_event(self.base_event) return True def detect_type(self): if self.base_event.name == 'decrypted-message-received': self.notif_type = 'msg' if self.base_event.name == 'gc-message-received': self.notif_type = 'gc-msg' if self.base_event.name == 'presence-received': self.notif_type = 'pres' def handle_incoming_msg_event(self, msg_obj): # don't alert for carbon copied messages from ourselves if msg_obj.sent: return if not msg_obj.msgtxt: return self.jid = msg_obj.jid if msg_obj.mtype == 'pm': self.jid = msg_obj.fjid self.control = app.interface.msg_win_mgr.search_control( msg_obj.jid, self.account, msg_obj.resource) if self.control is None: if len(app.events.get_events( self.account, msg_obj.jid, [msg_obj.mtype])) <= 1: self.first_unread = True else: self.control_focused = self.control.has_focus() if msg_obj.mtype == 'pm': nick = msg_obj.resource else: nick = app.get_name_from_jid(self.conn.name, self.jid) if self.first_unread: self.sound_event = 'first_message_received' elif self.control_focused: self.sound_event = 'next_message_received_focused' else: self.sound_event = 'next_message_received_unfocused' if app.config.get('notification_preview_message'): self.popup_text = msg_obj.msgtxt if self.popup_text and (self.popup_text.startswith('/me ') or \ self.popup_text.startswith('/me\n')): self.popup_text = '* ' + nick + self.popup_text[3:] else: # We don't want message preview, do_preview = False self.popup_text = '' if msg_obj.mtype == 'normal': # single message self.popup_msg_type = 'normal' self.popup_event_type = _('New Single Message') elif msg_obj.mtype == 'pm': self.popup_msg_type = 'pm' self.popup_event_type = _('New Private Message') else: # chat message self.popup_msg_type = 'chat' self.popup_event_type = _('New Message') num_unread = len(app.events.get_events(self.conn.name, self.jid, ['printed_' + self.popup_msg_type, self.popup_msg_type])) self.popup_title = i18n.ngettext( 'New message from %(nickname)s', '%(n_msgs)i unread messages from %(nickname)s', num_unread) % {'nickname': nick, 'n_msgs': num_unread} if app.config.get('notify_on_new_message'): if self.first_unread or (app.config.get('autopopup_chat_opened') \ and not self.control_focused): if app.config.get('autopopupaway'): # always show notification self.do_popup = True if app.connections[self.conn.name].connected in (2, 3): # we're online or chat self.do_popup = True if msg_obj.attention and not app.config.get( 'ignore_incoming_attention'): self.popup_timeout = 0 self.do_popup = True else: self.popup_timeout = app.config.get('notification_timeout') if msg_obj.attention and not app.config.get( 'ignore_incoming_attention') and app.config.get_per('soundevents', 'attention_received', 'enabled'): self.sound_event = 'attention_received' self.do_sound = True elif self.first_unread and helpers.allow_sound_notification( self.conn.name, 'first_message_received'): self.do_sound = True elif not self.first_unread and self.control_focused and \ helpers.allow_sound_notification(self.conn.name, 'next_message_received_focused'): self.do_sound = True elif not self.first_unread and not self.control_focused and \ helpers.allow_sound_notification(self.conn.name, 'next_message_received_unfocused'): self.do_sound = True def handle_incoming_gc_msg_event(self, msg_obj): if not msg_obj.msg_obj.gc_control: # we got a message from a room we're not in? ignore it return self.jid = msg_obj.jid sound = msg_obj.msg_obj.gc_control.highlighting_for_message( msg_obj.msgtxt, msg_obj.timestamp)[1] if msg_obj.nickname != msg_obj.msg_obj.gc_control.nick: self.do_sound = True if sound == 'received': self.sound_event = 'muc_message_received' elif sound == 'highlight': self.sound_event = 'muc_message_highlight' else: self.do_sound = False else: self.do_sound = False self.do_popup = False def handle_incoming_pres_event(self, pres_obj): if app.jid_is_transport(pres_obj.jid): return True account = pres_obj.conn.name self.jid = pres_obj.jid resource = pres_obj.resource or '' # It isn't an agent for c in pres_obj.contact_list: if c.resource == resource: # we look for other connected resources continue if c.show not in ('offline', 'error'): return True # no other resource is connected, let's look in metacontacts family = app.contacts.get_metacontacts_family(account, self.jid) for info in family: acct_ = info['account'] jid_ = info['jid'] c_ = app.contacts.get_contact_with_highest_priority(acct_, jid_) if not c_: continue if c_.jid == self.jid: continue if c_.show not in ('offline', 'error'): return True if pres_obj.old_show < 2 and pres_obj.new_show > 1: event = 'contact_connected' server = app.get_server_from_jid(self.jid) account_server = account + '/' + server block_transport = False if account_server in app.block_signed_in_notifications and \ app.block_signed_in_notifications[account_server]: block_transport = True if helpers.allow_showing_notification(account, 'notify_on_signin') \ and not app.block_signed_in_notifications[account] and \ not block_transport: self.do_popup = True if app.config.get_per('soundevents', 'contact_connected', 'enabled') and not app.block_signed_in_notifications[account] and\ not block_transport and helpers.allow_sound_notification(account, 'contact_connected'): self.sound_event = event self.do_sound = True elif pres_obj.old_show > 1 and pres_obj.new_show < 2: event = 'contact_disconnected' if helpers.allow_showing_notification(account, 'notify_on_signout'): self.do_popup = True if app.config.get_per('soundevents', 'contact_disconnected', 'enabled') and helpers.allow_sound_notification(account, event): self.sound_event = event self.do_sound = True # Status change (not connected/disconnected or error (<1)) elif pres_obj.new_show > 1: event = 'status_change' else: return True if app.jid_is_transport(self.jid): self.transport_name = app.get_transport_name_from_jid(self.jid) self.show = pres_obj.show self.popup_timeout = app.config.get('notification_timeout') nick = i18n.direction_mark + app.get_name_from_jid(account, self.jid) if event == 'status_change': self.popup_title = _('%(nick)s Changed Status') % \ {'nick': nick} self.popup_text = _('%(nick)s is now %(status)s') % \ {'nick': nick, 'status': helpers.get_uf_show(pres_obj.show)} if pres_obj.status: self.popup_text = self.popup_text + " : " + pres_obj.status self.popup_event_type = _('Contact Changed Status') elif event == 'contact_connected': self.popup_title = _('%(nickname)s Signed In') % {'nickname': nick} self.popup_text = '' if pres_obj.status: self.popup_text = pres_obj.status self.popup_event_type = _('Contact Signed In') elif event == 'contact_disconnected': self.popup_title = _('%(nickname)s Signed Out') % {'nickname': nick} self.popup_text = '' if pres_obj.status: self.popup_text = pres_obj.status self.popup_event_type = _('Contact Signed Out') class MessageOutgoingEvent(nec.NetworkOutgoingEvent): name = 'message-outgoing' def init(self): self.additional_data = AdditionalDataDict() self.message = None self.keyID = None self.type_ = 'chat' self.kind = None self.timestamp = None self.subject = '' self.chatstate = None self.stanza_id = None self.resource = None self.user_nick = None self.xhtml = None self.label = None self.session = None self.form_node = None self.delayed = None self.callback = None self.callback_args = [] self.now = False self.is_loggable = True self.control = None self.attention = False self.correct_id = None self.automatic_message = True self.encryption = '' self.encrypted = False def get_full_jid(self): if self.resource: return self.jid + '/' + self.resource if self.session: return self.session.get_to() return self.jid def generate(self): if self.type_ == 'chat': self.kind = KindConstant.CHAT_MSG_SENT else: self.kind = KindConstant.SINGLE_MSG_SENT return True class StanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent): name = 'stanza-message-outgoing' class GcStanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent): name = 'gc-stanza-message-outgoing' class GcMessageOutgoingEvent(nec.NetworkOutgoingEvent): name = 'gc-message-outgoing' def init(self): self.additional_data = AdditionalDataDict() self.message = '' self.chatstate = None self.xhtml = None self.stanza_id = None self.label = None self.callback = None self.callback_args = [] self.is_loggable = True self.control = None self.correct_id = None self.automatic_message = True def generate(self): return True class ClientCertPassphraseEvent(nec.NetworkIncomingEvent): name = 'client-cert-passphrase' class InformationEvent(nec.NetworkIncomingEvent): name = 'information' def init(self): self.args = None self.kwargs = {} self.dialog_name = None self.popup = True def generate(self): if self.args is None: self.args = () else: self.args = (self.args,) return True class StyleChanged(nec.NetworkIncomingEvent): name = 'style-changed' def generate(self): return True gajim-gajim-1.1.3/gajim/common/const.py000066400000000000000000000304051345766322700177700ustar00rootroot00000000000000from enum import IntEnum, Enum, unique from collections import namedtuple from gajim.common.i18n import _ Option = namedtuple('Option', 'kind label type value name callback data desc enabledif props') Option.__new__.__defaults__ = (None,) * len(Option._fields) # type: ignore DialogButton = namedtuple('DialogButton', 'text callback action') DialogButton.__new__.__defaults__ = (None, None) # type: ignore @unique class OptionKind(IntEnum): ENTRY = 0 SWITCH = 1 SPIN = 2 ACTION = 3 LOGIN = 4 DIALOG = 5 CALLBACK = 6 PROXY = 7 HOSTNAME = 8 PRIORITY = 9 FILECHOOSER = 10 CHANGEPASSWORD = 11 GPG = 12 @unique class OptionType(IntEnum): ACCOUNT_CONFIG = 0 CONFIG = 1 VALUE = 2 ACTION = 3 DIALOG = 4 class AvatarSize(IntEnum): TAB = 16 ROSTER = 32 CHAT = 48 NOTIFICATION = 48 TOOLTIP = 125 VCARD = 200 PUBLISH = 200 class ArchiveState(IntEnum): NEVER = 0 ALL = 1 @unique class PathLocation(IntEnum): CONFIG = 0 CACHE = 1 DATA = 2 @unique class PathType(IntEnum): FILE = 0 FOLDER = 1 FOLDER_OPTIONAL = 2 @unique class KindConstant(IntEnum): STATUS = 0 GCSTATUS = 1 GC_MSG = 2 SINGLE_MSG_RECV = 3 CHAT_MSG_RECV = 4 SINGLE_MSG_SENT = 5 CHAT_MSG_SENT = 6 ERROR = 7 def __str__(self): return str(self.value) @unique class ShowConstant(IntEnum): ONLINE = 0 CHAT = 1 AWAY = 2 XA = 3 DND = 4 OFFLINE = 5 @unique class TypeConstant(IntEnum): AIM = 0 GG = 1 HTTP_WS = 2 ICQ = 3 MSN = 4 QQ = 5 SMS = 6 SMTP = 7 TLEN = 8 YAHOO = 9 NEWMAIL = 10 RSS = 11 WEATHER = 12 MRIM = 13 NO_TRANSPORT = 14 @unique class SubscriptionConstant(IntEnum): NONE = 0 TO = 1 FROM = 2 BOTH = 3 @unique class JIDConstant(IntEnum): NORMAL_TYPE = 0 ROOM_TYPE = 1 @unique class StyleAttr(Enum): COLOR = 'color' BACKGROUND = 'background' FONT = 'font' @unique class CSSPriority(IntEnum): APPLICATION = 600 APPLICATION_DARK = 601 DEFAULT_THEME = 610 DEFAULT_THEME_DARK = 611 USER_THEME = 650 @unique class ButtonAction(Enum): DESTRUCTIVE = 'destructive-action' SUGGESTED = 'suggested-action' @unique class IdleState(IntEnum): UNKNOWN = 0 XA = 1 AWAY = 2 AWAKE = 3 @unique class RequestAvatar(IntEnum): SELF = 0 ROOM = 1 USER = 2 @unique class BookmarkStorageType(IntEnum): PRIVATE = 0 PUBSUB = 1 @unique class PEPEventType(IntEnum): ABSTRACT = 0 ACTIVITY = 1 TUNE = 2 MOOD = 3 LOCATION = 4 NICKNAME = 5 AVATAR = 6 ATOM = 7 @unique class Chatstate(IntEnum): COMPOSING = 0 PAUSED = 1 ACTIVE = 2 INACTIVE = 3 GONE = 4 def __str__(self): return self.name.lower() class SyncThreshold(IntEnum): NO_THRESHOLD = 0 def __str__(self): return str(self.value) class Display(Enum): X11 = 'X11Display' WAYLAND = 'GdkWaylandDisplay' WIN32 = 'GdkWin32Display' QUARTZ = 'GdkQuartzDisplay' ACTIVITIES = { 'doing_chores': { 'category': _('Doing Chores'), 'buying_groceries': _('Buying Groceries'), 'cleaning': _('Cleaning'), 'cooking': _('Cooking'), 'doing_maintenance': _('Doing Maintenance'), 'doing_the_dishes': _('Doing the Dishes'), 'doing_the_laundry': _('Doing the Laundry'), 'gardening': _('Gardening'), 'running_an_errand': _('Running an Errand'), 'walking_the_dog': _('Walking the Dog')}, 'drinking': { 'category': _('Drinking'), 'having_a_beer': _('Having a Beer'), 'having_coffee': _('Having Coffee'), 'having_tea': _('Having Tea')}, 'eating': { 'category': _('Eating'), 'having_a_snack': _('Having a Snack'), 'having_breakfast': _('Having Breakfast'), 'having_dinner': _('Having Dinner'), 'having_lunch': _('Having Lunch')}, 'exercising': { 'category': _('Exercising'), 'cycling': _('Cycling'), 'dancing': _('Dancing'), 'hiking': _('Hiking'), 'jogging': _('Jogging'), 'playing_sports': _('Playing Sports'), 'running': _('Running'), 'skiing': _('Skiing'), 'swimming': _('Swimming'), 'working_out': _('Working out')}, 'grooming': { 'category': _('Grooming'), 'at_the_spa': _('At the Spa'), 'brushing_teeth': _('Brushing Teeth'), 'getting_a_haircut': _('Getting a Haircut'), 'shaving': _('Shaving'), 'taking_a_bath': _('Taking a Bath'), 'taking_a_shower': _('Taking a Shower')}, 'having_appointment': { 'category': _('Having an Appointment')}, 'inactive': { 'category': _('Inactive'), 'day_off': _('Day Off'), 'hanging_out': _('Hanging out'), 'hiding': _('Hiding'), 'on_vacation': _('On Vacation'), 'praying': _('Praying'), 'scheduled_holiday': _('Scheduled Holiday'), 'sleeping': _('Sleeping'), 'thinking': _('Thinking')}, 'relaxing': { 'category': _('Relaxing'), 'fishing': _('Fishing'), 'gaming': _('Gaming'), 'going_out': _('Going out'), 'partying': _('Partying'), 'reading': _('Reading'), 'rehearsing': _('Rehearsing'), 'shopping': _('Shopping'), 'smoking': _('Smoking'), 'socializing': _('Socializing'), 'sunbathing': _('Sunbathing'), 'watching_tv': _('Watching TV'), 'watching_a_movie': _('Watching a Movie')}, 'talking': { 'category': _('Talking'), 'in_real_life': _('In Real Life'), 'on_the_phone': _('On the Phone'), 'on_video_phone': _('On Video Phone')}, 'traveling': { 'category': _('Traveling'), 'commuting': _('Commuting'), 'cycling': _('Cycling'), 'driving': _('Driving'), 'in_a_car': _('In a Car'), 'on_a_bus': _('On a Bus'), 'on_a_plane': _('On a Plane'), 'on_a_train': _('On a Train'), 'on_a_trip': _('On a Trip'), 'walking': _('Walking')}, 'working': { 'category': _('Working'), 'coding': _('Coding'), 'in_a_meeting': _('In a Meeting'), 'studying': _('Studying'), 'writing': _('Writing')}} MOODS = { 'afraid': _('Afraid'), 'amazed': _('Amazed'), 'amorous': _('Amorous'), 'angry': _('Angry'), 'annoyed': _('Annoyed'), 'anxious': _('Anxious'), 'aroused': _('Aroused'), 'ashamed': _('Ashamed'), 'bored': _('Bored'), 'brave': _('Brave'), 'calm': _('Calm'), 'cautious': _('Cautious'), 'cold': _('Cold'), 'confident': _('Confident'), 'confused': _('Confused'), 'contemplative': _('Contemplative'), 'contented': _('Contented'), 'cranky': _('Cranky'), 'crazy': _('Crazy'), 'creative': _('Creative'), 'curious': _('Curious'), 'dejected': _('Dejected'), 'depressed': _('Depressed'), 'disappointed': _('Disappointed'), 'disgusted': _('Disgusted'), 'dismayed': _('Dismayed'), 'distracted': _('Distracted'), 'embarrassed': _('Embarrassed'), 'envious': _('Envious'), 'excited': _('Excited'), 'flirtatious': _('Flirtatious'), 'frustrated': _('Frustrated'), 'grateful': _('Grateful'), 'grieving': _('Grieving'), 'grumpy': _('Grumpy'), 'guilty': _('Guilty'), 'happy': _('Happy'), 'hopeful': _('Hopeful'), 'hot': _('Hot'), 'humbled': _('Humbled'), 'humiliated': _('Humiliated'), 'hungry': _('Hungry'), 'hurt': _('Hurt'), 'impressed': _('Impressed'), 'in_awe': _('In Awe'), 'in_love': _('In Love'), 'indignant': _('Indignant'), 'interested': _('Interested'), 'intoxicated': _('Intoxicated'), 'invincible': _('Invincible'), 'jealous': _('Jealous'), 'lonely': _('Lonely'), 'lost': _('Lost'), 'lucky': _('Lucky'), 'mean': _('Mean'), 'moody': _('Moody'), 'nervous': _('Nervous'), 'neutral': _('Neutral'), 'offended': _('Offended'), 'outraged': _('Outraged'), 'playful': _('Playful'), 'proud': _('Proud'), 'relaxed': _('Relaxed'), 'relieved': _('Relieved'), 'remorseful': _('Remorseful'), 'restless': _('Restless'), 'sad': _('Sad'), 'sarcastic': _('Sarcastic'), 'satisfied': _('Satisfied'), 'serious': _('Serious'), 'shocked': _('Shocked'), 'shy': _('Shy'), 'sick': _('Sick'), 'sleepy': _('Sleepy'), 'spontaneous': _('Spontaneous'), 'stressed': _('Stressed'), 'strong': _('Strong'), 'surprised': _('Surprised'), 'thankful': _('Thankful'), 'thirsty': _('Thirsty'), 'tired': _('Tired'), 'undefined': _('Undefined'), 'weak': _('Weak'), 'worried': _('Worried') } LOCATION_DATA = { 'accuracy': _('accuracy'), 'alt': _('alt'), 'area': _('area'), 'bearing': _('bearing'), 'building': _('building'), 'country': _('country'), 'countrycode': _('countrycode'), 'datum': _('datum'), 'description': _('description'), 'error': _('error'), 'floor': _('floor'), 'lat': _('lat'), 'locality': _('locality'), 'lon': _('lon'), 'postalcode': _('postalcode'), 'region': _('region'), 'room': _('room'), 'speed': _('speed'), 'street': _('street'), 'text': _('text'), 'timestamp': _('timestamp'), 'uri': _('URI') } SSLError = { 2: _("Unable to get issuer certificate"), 3: _("Unable to get certificate CRL"), 4: _("Unable to decrypt certificate's signature"), 5: _("Unable to decrypt CRL's signature"), 6: _("Unable to decode issuer public key"), 7: _("Certificate signature failure"), 8: _("CRL signature failure"), 9: _("Certificate is not yet valid"), 10: _("Certificate has expired"), 11: _("CRL is not yet valid"), 12: _("CRL has expired"), 13: _("Format error in certificate's notBefore field"), 14: _("Format error in certificate's notAfter field"), 15: _("Format error in CRL's lastUpdate field"), 16: _("Format error in CRL's nextUpdate field"), 17: _("Out of memory"), 18: _("Self signed certificate"), 19: _("Self signed certificate in certificate chain"), 20: _("Unable to get local issuer certificate"), 21: _("Unable to verify the first certificate"), 22: _("Certificate chain too long"), 23: _("Certificate revoked"), 24: _("Invalid CA certificate"), 25: _("Path length constraint exceeded"), 26: _("Unsupported certificate purpose"), 27: _("Certificate not trusted"), 28: _("Certificate rejected"), 29: _("Subject issuer mismatch"), 30: _("Authority and subject key identifier mismatch"), 31: _("Authority and issuer serial number mismatch"), 32: _("Key usage does not include certificate signing"), 50: _("Application verification failure"), } THANKS = u"""\ Alexander Futász Alexander V. Butenko Alexey Nezhdanov Alfredo Junix Anaël Verrier Anders Ström Andrew Sayman Anton Shmigirilov Christian Bjälevik Christophe Got Christoph Neuroth David Campey Dennis Craven Fabian Neumann Filippos Papadopoulos Francisco Alburquerque Parra (Membris Khan) Frederic Lory Fridtjof Bussefor Geobert Quach Guillaume Morin Gustavo J. A. M. Carneiro Ivo Anjo Josef Vybíral Juraj Michalek Kjell Braden Luis Peralta Michael Scherer Michele Campeotto Mike Albon Miguel Fonseca Norman Rasmussen Oscar Hellström Peter Saint-Andre Petr Menšík Sergey Kuleshov Stavros Giannouris Stian B. Barmen Thilo Molitor Thomas Klein-Hitpaß Urtzi Alfaro Witold Kieraś Yakov Bezrukov Yavor Doganov """.strip().split("\n") ARTISTS = u"""\ Anders Ström Christophe Got Dennis Craven Dmitry Korzhevin Guillaume Morin Gvorcek Spajreh Josef Vybíral Membris Khan Rederick Asher Jakub Szypulka """.strip().split("\n") DEVS_CURRENT = u"""\ Yann Leboulanger (asterix AT lagaule.org) Philipp Hörist (philipp AT hoerist.com) """.strip().split("\n") DEVS_PAST = u"""\ Stefan Bethge (stefan AT lanpartei.de) Alexander Cherniuk (ts33kr AT gmail.com) Stephan Erb (steve-e AT h3c.de) Vincent Hanquez (tab AT snarc.org) Dimitur Kirov (dkirov AT gmail.com) Nikos Kouremenos (kourem AT gmail.com) Julien Pivotto (roidelapluie AT gmail.com) Jonathan Schleifer (js-gajim AT webkeks.org) Travis Shirk (travis AT pobox.com) Brendan Taylor (whateley AT gmail.com) Jean-Marie Traissard (jim AT lapin.org) """.strip().split("\n") gajim-gajim-1.1.3/gajim/common/contacts.py000066400000000000000000001020201345766322700204510ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # Travis Shirk # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # Tomasz Melcer # Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . try: from gajim.common import caps_cache from gajim.common.i18n import _ from gajim.common.account import Account from gajim import common from gajim.common.const import Chatstate except ImportError as e: if __name__ != "__main__": raise ImportError(str(e)) class XMPPEntity: """ Base representation of entities in XMPP """ def __init__(self, jid, account, resource): self.jid = jid self.resource = resource self.account = account class CommonContact(XMPPEntity): def __init__(self, jid, account, resource, show, status, name, chatstate, client_caps=None): XMPPEntity.__init__(self, jid, account, resource) self.show = show self.status = status self.name = name self.client_caps = client_caps or caps_cache.NullClientCaps() # this is contact's chatstate self._chatstate = chatstate self._is_pm_contact = False @property def show(self): return self._show @show.setter def show(self, value): if not isinstance(value, str): raise TypeError('show must be a string') self._show = value @property def chatstate_enum(self): return self._chatstate @property def chatstate(self): if self._chatstate is None: return return str(self._chatstate) @chatstate.setter def chatstate(self, value): if value is None: self._chatstate = value else: self._chatstate = Chatstate[value.upper()] @property def is_gc_contact(self): return isinstance(self, GC_Contact) @property def is_pm_contact(self): return self._is_pm_contact def get_full_jid(self): raise NotImplementedError def get_shown_name(self): raise NotImplementedError def supports(self, requested_feature): """ Return True if the contact has advertised to support the feature identified by the given namespace. False otherwise. """ if self.show == 'offline': # Unfortunately, if all resources are offline, the contact # includes the last resource that was online. Check for its # show, so we can be sure it's existant. Otherwise, we still # return caps for a contact that has no resources left. return False return caps_cache.client_supports(self.client_caps, requested_feature) @property def uses_phone(self): return caps_cache.get_client_identity(self.client_caps) == 'phone' class Contact(CommonContact): """ Information concerning a contact """ def __init__(self, jid, account, name='', groups=None, show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, chatstate=None, idle_time=None, avatar_sha=None, groupchat=False, is_pm_contact=False): if not isinstance(jid, str): print('no str') if groups is None: groups = [] CommonContact.__init__(self, jid, account, resource, show, status, name, chatstate, client_caps=client_caps) self.contact_name = '' # nick choosen by contact self.groups = [i if i else _('General') for i in set(groups)] # filter duplicate values self.avatar_sha = avatar_sha self._is_groupchat = groupchat self._is_pm_contact = is_pm_contact self.sub = sub self.ask = ask self.priority = priority self.keyID = keyID self.idle_time = idle_time self.pep = {} def get_full_jid(self): if self.resource: return self.jid + '/' + self.resource return self.jid def get_shown_name(self): if self.name: return self.name if self.contact_name: return self.contact_name return self.jid.split('@')[0] def get_shown_groups(self): if self.is_observer(): return [_('Observers')] if self.is_groupchat(): return [_('Groupchats')] if self.is_transport(): return [_('Transports')] if not self.groups: return [_('General')] return self.groups def is_hidden_from_roster(self): """ If contact should not be visible in roster """ # XEP-0162: http://www.xmpp.org/extensions/xep-0162.html if self.is_transport(): return False if self.sub in ('both', 'to'): return False if self.sub in ('none', 'from') and self.ask == 'subscribe': return False if self.sub in ('none', 'from') and (self.name or self.groups): return False if _('Not in Roster') in self.groups: return False return True def is_observer(self): # XEP-0162: http://www.xmpp.org/extensions/xep-0162.html is_observer = False if self.sub == 'from' and not self.is_transport()\ and self.is_hidden_from_roster(): is_observer = True return is_observer def is_groupchat(self): return self._is_groupchat def is_transport(self): # if not '@' or '@' starts the jid then contact is transport return self.jid.find('@') <= 0 class GC_Contact(CommonContact): """ Information concerning each groupchat contact """ def __init__(self, room_jid, account, name='', show='', status='', role='', affiliation='', jid='', resource='', chatstate=None, avatar_sha=None): CommonContact.__init__(self, jid, account, resource, show, status, name, chatstate) self.room_jid = room_jid self.role = role self.affiliation = affiliation self.avatar_sha = avatar_sha def get_full_jid(self): return self.room_jid + '/' + self.name def get_shown_name(self): return self.name def get_avatar(self, *args, **kwargs): return common.app.interface.get_avatar(self.avatar_sha, *args, **kwargs) def as_contact(self): """ Create a Contact instance from this GC_Contact instance """ return Contact(jid=self.get_full_jid(), account=self.account, name=self.name, groups=[], show=self.show, status=self.status, sub='none', client_caps=self.client_caps, avatar_sha=self.avatar_sha, is_pm_contact=True) class LegacyContactsAPI: """ This is a GOD class for accessing contact and groupchat information. The API has several flaws: * it mixes concerns because it deals with contacts, groupchats, groupchat contacts and metacontacts * some methods like get_contact() may return None. This leads to a lot of duplication all over Gajim because it is not sure if we receive a proper contact or just None. It is a long way to cleanup this API. Therefore just stick with it and use it as before. We will try to figure out a migration path. """ def __init__(self): self._metacontact_manager = MetacontactManager(self) self._accounts = {} def change_account_name(self, old_name, new_name): self._accounts[new_name] = self._accounts[old_name] self._accounts[new_name].name = new_name del self._accounts[old_name] self._metacontact_manager.change_account_name(old_name, new_name) def add_account(self, account_name): self._accounts[account_name] = Account(account_name, Contacts(), GC_Contacts()) self._metacontact_manager.add_account(account_name) def get_accounts(self, zeroconf=True): accounts = list(self._accounts.keys()) if not zeroconf: if 'Local' in accounts: accounts.remove('Local') return accounts def remove_account(self, account): del self._accounts[account] self._metacontact_manager.remove_account(account) def create_contact(self, jid, account, name='', groups=None, show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, chatstate=None, idle_time=None, avatar_sha=None, groupchat=False): if groups is None: groups = [] # Use Account object if available account = self._accounts.get(account, account) return Contact(jid=jid, account=account, name=name, groups=groups, show=show, status=status, sub=sub, ask=ask, resource=resource, priority=priority, keyID=keyID, client_caps=client_caps, chatstate=chatstate, idle_time=idle_time, avatar_sha=avatar_sha, groupchat=groupchat) def create_self_contact(self, jid, account, resource, show, status, priority, name='', keyID=''): conn = common.app.connections[account] nick = name or common.app.nicks[account] account = self._accounts.get(account, account) # Use Account object if available self_contact = self.create_contact(jid=jid, account=account, name=nick, groups=['self_contact'], show=show, status=status, sub='both', ask='none', priority=priority, keyID=keyID, resource=resource) self_contact.pep = conn.pep return self_contact def create_not_in_roster_contact(self, jid, account, resource='', name='', keyID=''): # Use Account object if available account = self._accounts.get(account, account) return self.create_contact(jid=jid, account=account, resource=resource, name=name, groups=[_('Not in Roster')], show='not in roster', status='', sub='none', keyID=keyID) def copy_contact(self, contact): return self.create_contact(contact.jid, contact.account, name=contact.name, groups=contact.groups, show=contact.show, status=contact.status, sub=contact.sub, ask=contact.ask, resource=contact.resource, priority=contact.priority, keyID=contact.keyID, client_caps=contact.client_caps, chatstate=contact.chatstate_enum, idle_time=contact.idle_time, avatar_sha=contact.avatar_sha) def add_contact(self, account, contact): if account not in self._accounts: self.add_account(account) return self._accounts[account].contacts.add_contact(contact) def remove_contact(self, account, contact): if account not in self._accounts: return return self._accounts[account].contacts.remove_contact(contact) def remove_jid(self, account, jid, remove_meta=True): self._accounts[account].contacts.remove_jid(jid) if remove_meta: self._metacontact_manager.remove_metacontact(account, jid) def get_groupchat_contact(self, account, jid): return self._accounts[account].contacts.get_groupchat_contact(jid) def get_contacts(self, account, jid): return self._accounts[account].contacts.get_contacts(jid) def get_contact(self, account, jid, resource=None): return self._accounts[account].contacts.get_contact(jid, resource=resource) def get_avatar(self, account, *args, **kwargs): return self._accounts[account].contacts.get_avatar(*args, **kwargs) def get_avatar_sha(self, account, jid): return self._accounts[account].contacts.get_avatar_sha(jid) def set_avatar(self, account, jid, sha): self._accounts[account].contacts.set_avatar(jid, sha) def iter_contacts(self, account): for contact in self._accounts[account].contacts.iter_contacts(): yield contact def get_contact_from_full_jid(self, account, fjid): return self._accounts[account].contacts.get_contact_from_full_jid(fjid) def get_first_contact_from_jid(self, account, jid): return self._accounts[account].contacts.get_first_contact_from_jid(jid) def get_contacts_from_group(self, account, group): return self._accounts[account].contacts.get_contacts_from_group(group) def get_contacts_jid_list(self, account): return self._accounts[account].contacts.get_contacts_jid_list() def get_jid_list(self, account): return self._accounts[account].contacts.get_jid_list() def change_contact_jid(self, old_jid, new_jid, account): return self._accounts[account].change_contact_jid(old_jid, new_jid) def get_highest_prio_contact_from_contacts(self, contacts): if not contacts: return None prim_contact = contacts[0] for contact in contacts[1:]: if int(contact.priority) > int(prim_contact.priority): prim_contact = contact return prim_contact def get_contact_with_highest_priority(self, account, jid): contacts = self.get_contacts(account, jid) if not contacts and '/' in jid: # jid may be a fake jid, try it room, nick = jid.split('/', 1) contact = self.get_gc_contact(account, room, nick) return contact return self.get_highest_prio_contact_from_contacts(contacts) def get_nb_online_total_contacts(self, accounts=None, groups=None): """ Return the number of online contacts and the total number of contacts """ if not accounts: accounts = self.get_accounts() if groups is None: groups = [] nbr_online = 0 nbr_total = 0 for account in accounts: our_jid = common.app.get_jid_from_account(account) for jid in self.get_jid_list(account): if jid == our_jid: continue if (common.app.jid_is_transport(jid) and _('Transports') not in groups): # do not count transports continue if self.has_brother(account, jid, accounts) and not \ self.is_big_brother(account, jid, accounts): # count metacontacts only once continue contact = self._accounts[account].contacts._contacts[jid][0] if _('Not in roster') in contact.groups: continue in_groups = False if groups == []: in_groups = True else: for group in groups: if group in contact.get_shown_groups(): in_groups = True break if in_groups: if contact.show not in ('offline', 'error'): nbr_online += 1 nbr_total += 1 return nbr_online, nbr_total def __getattr__(self, attr_name): # Only called if self has no attr_name if hasattr(self._metacontact_manager, attr_name): return getattr(self._metacontact_manager, attr_name) raise AttributeError(attr_name) def create_gc_contact(self, room_jid, account, name='', show='', status='', role='', affiliation='', jid='', resource='', avatar_sha=None): account = self._accounts.get(account, account) # Use Account object if available return GC_Contact(room_jid, account, name, show, status, role, affiliation, jid, resource, avatar_sha=avatar_sha) def add_gc_contact(self, account, gc_contact): return self._accounts[account].gc_contacts.add_gc_contact(gc_contact) def remove_gc_contact(self, account, gc_contact): return self._accounts[account].gc_contacts.remove_gc_contact(gc_contact) def remove_room(self, account, room_jid): return self._accounts[account].gc_contacts.remove_room(room_jid) def get_gc_list(self, account): return self._accounts[account].gc_contacts.get_gc_list() def get_nick_list(self, account, room_jid): return self._accounts[account].gc_contacts.get_nick_list(room_jid) def get_gc_contact(self, account, room_jid, nick): return self._accounts[account].gc_contacts.get_gc_contact(room_jid, nick) def is_gc_contact(self, account, jid): return self._accounts[account].gc_contacts.is_gc_contact(jid) def get_nb_role_total_gc_contacts(self, account, room_jid, role): return self._accounts[account].gc_contacts.get_nb_role_total_gc_contacts(room_jid, role) def set_gc_avatar(self, account, room_jid, nick, sha): contact = self.get_gc_contact(account, room_jid, nick) if contact is None: return contact.avatar_sha = sha def get_combined_chatstate(self, account, jid): return self._accounts[account].contacts.get_combined_chatstate(jid) class Contacts(): """ This is a breakout of the contact related behavior of the old Contacts class (which is not called LegacyContactsAPI) """ def __init__(self): # list of contacts {jid1: [C1, C2]}, } one Contact per resource self._contacts = {} def add_contact(self, contact): if contact.jid not in self._contacts or contact.is_groupchat(): self._contacts[contact.jid] = [contact] return contacts = self._contacts[contact.jid] # We had only one that was offline, remove it if len(contacts) == 1 and contacts[0].show == 'offline': # Do not use self.remove_contact: it deletes # self._contacts[account][contact.jid] contacts.remove(contacts[0]) # If same JID with same resource already exists, use the new one for c in contacts: if c.resource == contact.resource: self.remove_contact(c) break contacts.append(contact) def remove_contact(self, contact): if contact.jid not in self._contacts: return if contact in self._contacts[contact.jid]: self._contacts[contact.jid].remove(contact) if not self._contacts[contact.jid]: del self._contacts[contact.jid] def remove_jid(self, jid): """ Remove all contacts for a given jid """ if jid in self._contacts: del self._contacts[jid] def get_contacts(self, jid): """ Return the list of contact instances for this jid """ return self._contacts.get(jid, []) def get_contact(self, jid, resource=None): ### WARNING ### # This function returns a *RANDOM* resource if resource = None! # Do *NOT* use if you need to get the contact to which you # send a message for example, as a bare JID in Jabber means # highest available resource, which this function ignores! """ Return the contact instance for the given resource if it's given else the first contact is no resource is given or None if there is not """ if jid in self._contacts: if not resource: return self._contacts[jid][0] for c in self._contacts[jid]: if c.resource == resource: return c return self._contacts[jid][0] def get_contact_strict(self, jid, resource): """ Return the contact instance for the given resource or None """ if jid in self._contacts: for c in self._contacts[jid]: if c.resource == resource: return c def get_groupchat_contact(self, jid): if jid in self._contacts: contacts = self._contacts[jid] if contacts[0].is_groupchat(): return contacts[0] def get_avatar(self, jid, size=None, scale=None): if jid not in self._contacts: return None for resource in self._contacts[jid]: if resource.avatar_sha is None: continue avatar = common.app.interface.get_avatar( resource.avatar_sha, size, scale) if avatar is None: self.set_avatar(jid, None) return avatar def get_avatar_sha(self, jid): if jid not in self._contacts: return None for resource in self._contacts[jid]: if resource.avatar_sha is not None: return resource.avatar_sha return None def set_avatar(self, jid, sha): if jid not in self._contacts: return for resource in self._contacts[jid]: resource.avatar_sha = sha def iter_contacts(self): for jid in list(self._contacts.keys()): for contact in self._contacts[jid][:]: yield contact def get_jid_list(self): return list(self._contacts.keys()) def get_contacts_jid_list(self): return [jid for jid, contact in self._contacts.items() if not contact[0].is_groupchat()] def get_contact_from_full_jid(self, fjid): """ Get Contact object for specific resource of given jid """ barejid, resource = common.app.get_room_and_nick_from_fjid(fjid) return self.get_contact_strict(barejid, resource) def get_first_contact_from_jid(self, jid): if jid in self._contacts: return self._contacts[jid][0] def get_contacts_from_group(self, group): """ Return all contacts in the given group """ group_contacts = [] for jid in self._contacts: contacts = self.get_contacts(jid) if group in contacts[0].groups: group_contacts += contacts return group_contacts def change_contact_jid(self, old_jid, new_jid): if old_jid not in self._contacts: return self._contacts[new_jid] = [] for _contact in self._contacts[old_jid]: _contact.jid = new_jid self._contacts[new_jid].append(_contact) del self._contacts[old_jid] def get_combined_chatstate(self, jid): if jid not in self._contacts: return contacts = self._contacts[jid] states = [] for contact in contacts: if contact.chatstate_enum is None: continue states.append(contact.chatstate_enum) return str(min(states)) if states else None class GC_Contacts(): def __init__(self): # list of contacts that are in gc {room_jid: {nick: C}}} self._rooms = {} def add_gc_contact(self, gc_contact): if gc_contact.room_jid not in self._rooms: self._rooms[gc_contact.room_jid] = {gc_contact.name: gc_contact} else: self._rooms[gc_contact.room_jid][gc_contact.name] = gc_contact def remove_gc_contact(self, gc_contact): if gc_contact.room_jid not in self._rooms: return if gc_contact.name not in self._rooms[gc_contact.room_jid]: return del self._rooms[gc_contact.room_jid][gc_contact.name] # It was the last nick in room ? if not self._rooms[gc_contact.room_jid]: del self._rooms[gc_contact.room_jid] def remove_room(self, room_jid): if room_jid in self._rooms: del self._rooms[room_jid] def get_gc_list(self): return self._rooms.keys() def get_nick_list(self, room_jid): gc_list = self.get_gc_list() if not room_jid in gc_list: return [] return list(self._rooms[room_jid].keys()) def get_gc_contact(self, room_jid, nick): try: return self._rooms[room_jid][nick] except KeyError: return None def is_gc_contact(self, jid): """ >>> gc = GC_Contacts() >>> gc._rooms = {'gajim@conference.gajim.org' : {'test' : True}} >>> gc.is_gc_contact('gajim@conference.gajim.org/test') True >>> gc.is_gc_contact('test@jabbim.com') False """ jid = jid.split('/') if len(jid) != 2: return False gcc = self.get_gc_contact(jid[0], jid[1]) return gcc is not None def get_nb_role_total_gc_contacts(self, room_jid, role): """ Return the number of group chat contacts for the given role and the total number of group chat contacts """ if room_jid not in self._rooms: return 0, 0 nb_role = nb_total = 0 for nick in self._rooms[room_jid]: if self._rooms[room_jid][nick].role == role: nb_role += 1 nb_total += 1 return nb_role, nb_total class MetacontactManager(): def __init__(self, contacts): self._metacontacts_tags = {} self._contacts = contacts def change_account_name(self, old_name, new_name): self._metacontacts_tags[new_name] = self._metacontacts_tags[old_name] del self._metacontacts_tags[old_name] def add_account(self, account): if account not in self._metacontacts_tags: self._metacontacts_tags[account] = {} def remove_account(self, account): del self._metacontacts_tags[account] def define_metacontacts(self, account, tags_list): self._metacontacts_tags[account] = tags_list def _get_new_metacontacts_tag(self, jid): if not jid in self._metacontacts_tags: return jid #FIXME: can this append ? assert False def iter_metacontacts_families(self, account): for tag in self._metacontacts_tags[account]: family = self._get_metacontacts_family_from_tag(account, tag) yield family def _get_metacontacts_tag(self, account, jid): """ Return the tag of a jid """ if not account in self._metacontacts_tags: return None for tag in self._metacontacts_tags[account]: for data in self._metacontacts_tags[account][tag]: if data['jid'] == jid: return tag return None def add_metacontact(self, brother_account, brother_jid, account, jid, order=None): tag = self._get_metacontacts_tag(brother_account, brother_jid) if not tag: tag = self._get_new_metacontacts_tag(brother_jid) self._metacontacts_tags[brother_account][tag] = [{'jid': brother_jid, 'tag': tag}] if brother_account != account: con = common.app.connections[brother_account] con.get_module('MetaContacts').store_metacontacts( self._metacontacts_tags[brother_account]) # be sure jid has no other tag old_tag = self._get_metacontacts_tag(account, jid) while old_tag: self.remove_metacontact(account, jid) old_tag = self._get_metacontacts_tag(account, jid) if tag not in self._metacontacts_tags[account]: self._metacontacts_tags[account][tag] = [{'jid': jid, 'tag': tag}] else: if order: self._metacontacts_tags[account][tag].append({'jid': jid, 'tag': tag, 'order': order}) else: self._metacontacts_tags[account][tag].append({'jid': jid, 'tag': tag}) con = common.app.connections[account] con.get_module('MetaContacts').store_metacontacts( self._metacontacts_tags[account]) def remove_metacontact(self, account, jid): if account not in self._metacontacts_tags: return found = None for tag in self._metacontacts_tags[account]: for data in self._metacontacts_tags[account][tag]: if data['jid'] == jid: found = data break if found: self._metacontacts_tags[account][tag].remove(found) con = common.app.connections[account] con.get_module('MetaContacts').store_metacontacts( self._metacontacts_tags[account]) break def has_brother(self, account, jid, accounts): tag = self._get_metacontacts_tag(account, jid) if not tag: return False meta_jids = self._get_metacontacts_jids(tag, accounts) return len(meta_jids) > 1 or len(meta_jids[account]) > 1 def is_big_brother(self, account, jid, accounts): family = self.get_metacontacts_family(account, jid) if family: nearby_family = [data for data in family if account in accounts] bb_data = self._get_metacontacts_big_brother(nearby_family) if bb_data['jid'] == jid and bb_data['account'] == account: return True return False def _get_metacontacts_jids(self, tag, accounts): """ Return all jid for the given tag in the form {acct: [jid1, jid2],.} """ answers = {} for account in self._metacontacts_tags: if tag in self._metacontacts_tags[account]: if account not in accounts: continue answers[account] = [] for data in self._metacontacts_tags[account][tag]: answers[account].append(data['jid']) return answers def get_metacontacts_family(self, account, jid): """ Return the family of the given jid, including jid in the form: [{'account': acct, 'jid': jid, 'order': order}, ] 'order' is optional """ tag = self._get_metacontacts_tag(account, jid) return self._get_metacontacts_family_from_tag(account, tag) def _get_metacontacts_family_from_tag(self, account, tag): if not tag: return [] answers = [] if tag in self._metacontacts_tags[account]: for data in self._metacontacts_tags[account][tag]: data['account'] = account answers.append(data) return answers def _metacontact_key(self, data): """ Data is {'jid': jid, 'account': account, 'order': order} order is optional """ show_list = ['not in roster', 'error', 'offline', 'invisible', 'dnd', 'xa', 'away', 'chat', 'online', 'requested', 'message'] jid = data['jid'] account = data['account'] # contact can be null when a jid listed in the metacontact data # is not in our roster contact = self._contacts.get_contact_with_highest_priority( account, jid) show = show_list.index(contact.show) if contact else 0 priority = contact.priority if contact else 0 has_order = 'order' in data order = data.get('order', 0) transport = common.app.get_transport_name_from_jid(jid) server = common.app.get_server_from_jid(jid) myserver = common.app.config.get_per('accounts', account, 'hostname') return (bool(contact), show > 2, has_order, order, bool(transport), show, priority, server == myserver, jid, account) def get_nearby_family_and_big_brother(self, family, account): """ Return the nearby family and its Big Brother Nearby family is the part of the family that is grouped with the metacontact. A metacontact may be over different accounts. If accounts are not merged then the given family is split account wise. (nearby_family, big_brother_jid, big_brother_account) """ if common.app.config.get('mergeaccounts'): # group all together nearby_family = family else: # we want one nearby_family per account nearby_family = [data for data in family if account == data['account']] if not nearby_family: return (None, None, None) big_brother_data = self._get_metacontacts_big_brother(nearby_family) big_brother_jid = big_brother_data['jid'] big_brother_account = big_brother_data['account'] return (nearby_family, big_brother_jid, big_brother_account) def _get_metacontacts_big_brother(self, family): """ Which of the family will be the big brother under which all others will be ? """ return max(family, key=self._metacontact_key) if __name__ == "__main__": import doctest doctest.testmod() gajim-gajim-1.1.3/gajim/common/dbus/000077500000000000000000000000001345766322700172235ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/dbus/__init__.py000066400000000000000000000000001345766322700213220ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/dbus/location.py000066400000000000000000000072251345766322700214130ustar00rootroot00000000000000# Copyright (C) 2009-2014 Yann Leboulanger # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging from datetime import datetime from gi.repository import GLib from gajim.common import app if app.is_installed('GEOCLUE'): from gi.repository import Geoclue log = logging.getLogger('gajim.c.dbus.location') class LocationListener: _instance = None @classmethod def get(cls): if cls._instance is None: cls._instance = cls() return cls._instance def __init__(self): self._data = {} # Note: do not remove third parameter `paramSpec` # because notify signal expects three parameters def _on_location_update(self, simple, paramSpec=None): location = simple.get_location() timestamp = location.get_property("timestamp")[0] lat = location.get_property("latitude") lon = location.get_property("longitude") alt = location.get_property("altitude") # in XEP-0080 it's horizontal accuracy acc = location.get_property("accuracy") # update data with info we just received self._data = {'lat': lat, 'lon': lon, 'alt': alt, 'accuracy': acc} self._data['timestamp'] = self._timestamp_to_utc(timestamp) self._send_location() def _on_simple_ready(self, obj, result): try: self.simple = Geoclue.Simple.new_finish(result) except GLib.Error as e: if e.domain == 'g-dbus-error-quark': log.warning("Could not enable geolocation: %s", e.message) else: raise else: self.simple.connect('notify::location', self._on_location_update) self._on_location_update(self.simple) def get_data(self): Geoclue.Simple.new("org.gajim.Gajim", Geoclue.AccuracyLevel.EXACT, None, self._on_simple_ready) def start(self): self.location_info = {} self.get_data() def _send_location(self): accounts = app.connections.keys() for acct in accounts: if not app.account_is_connected(acct): continue if not app.config.get_per('accounts', acct, 'publish_location'): continue if self.location_info == self._data: continue if 'timestamp' in self.location_info and 'timestamp' in self._data: last_data = self.location_info.copy() del last_data['timestamp'] new_data = self._data.copy() del new_data['timestamp'] if last_data == new_data: continue app.connections[acct].get_module('UserLocation').send(self._data) self.location_info = self._data.copy() def _timestamp_to_utc(self, timestamp): time = datetime.utcfromtimestamp(timestamp) return time.strftime('%Y-%m-%dT%H:%MZ') def enable(): if not app.is_installed('GEOCLUE'): log.warning('GeoClue not installed') return listener = LocationListener.get() listener.start() gajim-gajim-1.1.3/gajim/common/dbus/logind.py000066400000000000000000000113261345766322700210540ustar00rootroot00000000000000# Copyright (C) 2014 Kamil Paral # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' Watch for system sleep using systemd-logind. Documentation: http://www.freedesktop.org/wiki/Software/systemd/inhibit ''' import os import logging from gi.repository import Gio from gi.repository import GLib from gajim.common import app from gajim.common.i18n import _ log = logging.getLogger('gajim.c.dbus.logind') class LogindListener: _instance = None @classmethod def get(cls): if cls._instance is None: cls._instance = cls() return cls._instance def __init__(self): # file descriptor object of the inhibitor self._inhibit_fd = None Gio.bus_watch_name( Gio.BusType.SYSTEM, 'org.freedesktop.login1', Gio.BusNameWatcherFlags.NONE, self._on_appear_logind, self._on_vanish_logind) def _on_prepare_for_sleep(self, connection, _sender_name, _object_path, interface_name, signal_name, parameters, *_user_data): '''Signal handler for PrepareForSleep event''' log.debug('Received signal %s.%s%s', interface_name, signal_name, parameters) before = parameters[0] # Signal is either before or after sleep occurs if before: warn = self._inhibit_fd is None log.log( logging.WARNING if warn else logging.INFO, 'Preparing for sleep by disconnecting from network%s', ', without holding a sleep inhibitor' if warn else '') for name, conn in app.connections.items(): if app.account_is_connected(name): conn.old_show = app.SHOW_LIST[conn.connected] st = conn.status conn.change_status('offline', _('Machine is going to sleep')) conn.status = st conn.time_to_reconnect = 5 self._disinhibit_sleep() else: self._inhibit_sleep(connection) for conn in app.connections.values(): if conn.connected <= 0 and conn.time_to_reconnect: conn.reconnect() def _inhibit_sleep(self, connection): '''Obtain a sleep delay inhibitor from logind''' if self._inhibit_fd is not None: # Something is wrong, we have an inhibitor fd, and we are asking for # yet another one. log.warning('Trying to obtain a sleep inhibitor ' 'while already holding one.') ret, ret_fdlist = connection.call_with_unix_fd_list_sync( 'org.freedesktop.login1', '/org/freedesktop/login1', 'org.freedesktop.login1.Manager', 'Inhibit', GLib.Variant('(ssss)', ( 'sleep', 'org.gajim.Gajim', _('Disconnect from the network'), 'delay' # Inhibitor will delay but not block sleep )), GLib.VariantType.new('(h)'), Gio.DBusCallFlags.NONE, -1, None, None) log.info('Inhibit sleep') self._inhibit_fd = ret_fdlist.get(ret.unpack()[0]) def _disinhibit_sleep(self): '''Relinquish our sleep delay inhibitor''' if self._inhibit_fd is not None: os.close(self._inhibit_fd) self._inhibit_fd = None log.info('Disinhibit sleep') def _on_appear_logind(self, connection, name, name_owner, *_user_data): '''Use signal and locks provided by org.freedesktop.login1''' log.info('Name %s appeared, owned by %s', name, name_owner) connection.signal_subscribe( 'org.freedesktop.login1', 'org.freedesktop.login1.Manager', 'PrepareForSleep', '/org/freedesktop/login1', None, Gio.DBusSignalFlags.NONE, self._on_prepare_for_sleep, None) self._inhibit_sleep(connection) def _on_vanish_logind(self, _connection, name, *_user_data): '''Release remaining resources related to org.freedesktop.login1''' log.info('Name %s vanished', name) self._disinhibit_sleep() def enable(): LogindListener.get() gajim-gajim-1.1.3/gajim/common/dbus/music_track.py000066400000000000000000000150651345766322700221100ustar00rootroot00000000000000# Copyright (C) 2006 Gustavo Carneiro # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2008 Jean-Marie Traissard # Jonathan Schleifer # Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging from gi.repository import GObject from gi.repository import Gio, GLib log = logging.getLogger('gajim.c.dbus.music_track') MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.' class MusicTrackInfo: __slots__ = ['title', 'album', 'artist', 'duration', 'track_number', 'paused'] class MusicTrackListener(GObject.GObject): __gsignals__ = { 'music-track-changed': (GObject.SignalFlags.RUN_LAST, None, (object,)), } _instance = None @classmethod def get(cls): if cls._instance is None: cls._instance = cls() return cls._instance def __init__(self): super().__init__() self.players = {} def start(self): proxy = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, 'org.freedesktop.DBus', '/org/freedesktop/DBus', 'org.freedesktop.DBus', None) self.connection = proxy.get_connection() self.connection.signal_subscribe( 'org.freedesktop.DBus', 'org.freedesktop.DBus', 'NameOwnerChanged', '/org/freedesktop/DBus', None, Gio.DBusSignalFlags.NONE, self._signal_name_owner_changed) try: result = proxy.call_sync( 'ListNames', None, Gio.DBusCallFlags.NONE, -1, None) except GLib.Error as error: if error.domain == 'g-dbus-error-quark': log.debug("Could not list names: %s", error.message) return raise for name in result[0]: if name.startswith(MPRIS_PLAYER_PREFIX): self._add_player(name) def stop(self): for name in list(self.players): if name.startswith(MPRIS_PLAYER_PREFIX): self._remove_player(name) def _signal_name_owner_changed(self, connection, sender_name, object_path, interface_name, signal_name, parameters, *user_data): name, oldOwner, newOwner = parameters if name.startswith(MPRIS_PLAYER_PREFIX): if newOwner and not oldOwner: self._add_player(name) else: self._remove_player(name) def _add_player(self, name): '''Set up a listener for music player signals''' log.info('%s appeared', name) if name in self.players: return self.players[name] = self.connection.signal_subscribe( name, 'org.freedesktop.DBus.Properties', 'PropertiesChanged', '/org/mpris/MediaPlayer2', None, Gio.DBusSignalFlags.NONE, self._signal_received, name) info = self.get_playing_track(name) if info is not None: self.emit('music-track-changed', info) def _remove_player(self, name): log.info('%s vanished', name) if name in self.players: self.connection.signal_unsubscribe( self.players[name]) self.players.pop(name) self.emit('music-track-changed', None) def _signal_received(self, connection, sender_name, object_path, interface_name, signal_name, parameters, *user_data): '''Signal handler for PropertiesChanged event''' if 'PlaybackStatus' not in parameters[1]: return log.info('Signal received: %s - %s', interface_name, parameters) info = self.get_playing_track(user_data[0]) self.emit('music-track-changed', info) def _properties_extract(self, properties): meta = properties.get('Metadata') if meta is None or not meta: return None info = MusicTrackInfo() info.title = meta.get('xesam:title') info.album = meta.get('xesam:album') artist = meta.get('xesam:artist') if artist: info.artist = artist[0] else: info.artist = None info.duration = float(meta.get('mpris:length', 0)) info.track_number = meta.get('xesam:trackNumber', 0) status = properties.get('PlaybackStatus') info.paused = status is not None and status == 'Paused' return info def get_playing_track(self, name): '''Return a MusicTrackInfo for the currently playing song, or None if no song is playing''' proxy = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, name, '/org/mpris/MediaPlayer2', 'org.freedesktop.DBus.Properties', None) try: result = proxy.call_sync( "GetAll", GLib.Variant('(s)', ('org.mpris.MediaPlayer2.Player',)), Gio.DBusCallFlags.NONE, -1, None) except GLib.Error as error: if error.domain == 'g-dbus-error-quark': log.debug("Could not enable music listener: %s", error.message) return None raise else: info = self._properties_extract(result[0]) return info # here we test :) if __name__ == '__main__': def music_track_change_cb(_listener, music_track_info): if music_track_info is None or music_track_info.paused: print('Stop!') else: print(music_track_info.title) listener = MusicTrackListener.get() listener.connect('music-track-changed', music_track_change_cb) listener.start() GLib.MainLoop().run() gajim-gajim-1.1.3/gajim/common/dbus/screensaver.py000066400000000000000000000074511345766322700221240ustar00rootroot00000000000000# Copyright (C) 2018 André Apitzsch # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging from gi.repository import Gio from gajim.common import app log = logging.getLogger('gajim.c.dbus.screensaver') class ScreensaverListener: _instance = None @classmethod def get(cls): if cls._instance is None: cls._instance = cls() return cls._instance def __init__(self): Gio.bus_watch_name( Gio.BusType.SESSION, 'org.gnome.ScreenSaver', Gio.BusNameWatcherFlags.NONE, self._appeared, None) @staticmethod def _signal_received(_connection, _sender_name, _object_path, interface_name, _signal_name, parameters, *_user_data): '''Signal handler for screensaver active change''' log.info('Signal received: %s - %s', interface_name, parameters) roster = app.interface.roster if not parameters[0]: for account in app.connections: if app.account_is_connected(account) and \ app.sleeper_state[account] == 'autoaway-forced': # We came back online after screensaver # autoaway roster.send_status(account, 'online', app.status_before_autoaway[account]) app.status_before_autoaway[account] = '' app.sleeper_state[account] = 'online' return if not app.config.get('autoaway'): # Don't go auto away if user disabled the option return for account in app.connections: if account not in app.sleeper_state or not app.sleeper_state[account]: continue if app.sleeper_state[account] == 'online': if not app.account_is_connected(account): continue # we save our online status app.status_before_autoaway[account] = \ app.connections[account].status # we go away (no auto status) [we pass True to auto param] auto_message = app.config.get('autoaway_message') if not auto_message: auto_message = app.connections[account].status else: auto_message = auto_message.replace('$S', '%(status)s') auto_message = auto_message.replace('$T', '%(time)s') auto_message = auto_message % { 'status': app.status_before_autoaway[account], 'time': app.config.get('autoxatime')} roster.send_status(account, 'away', auto_message, auto=True) app.sleeper_state[account] = 'autoaway-forced' def _appeared(self, connection, name, _name_owner, *_user_data): '''Set up a listener for screensaver signals''' log.info('%s appeared', name) connection.signal_subscribe( 'org.gnome.ScreenSaver', 'org.gnome.ScreenSaver', 'ActiveChanged', '/org/gnome/ScreenSaver', None, Gio.DBusSignalFlags.NONE, self._signal_received, None) def enable(): ScreensaverListener.get() gajim-gajim-1.1.3/gajim/common/dbus_support.py000066400000000000000000000122021345766322700213660ustar00rootroot00000000000000# Copyright (C) 2005 Andrew Sayman # Dimitur Kirov # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006 Jean-Marie Traissard # Stefan Bethge # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import sys import logging from gajim.common import exceptions from gajim.common.i18n import _ _GAJIM_ERROR_IFACE = 'org.gajim.dbus.Error' log = logging.getLogger('gajim.c.dbus') try: import dbus from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) except ImportError: supported = False if sys.platform not in ('win32', 'darwin'): print(_('D-Bus python bindings are missing in this computer')) print(_('D-Bus capabilities of Gajim cannot be used')) else: try: # test if dbus-x11 is installed _bus = dbus.SystemBus() _bus = dbus.SessionBus() supported = True # does user have D-Bus bindings? except dbus.DBusException: supported = False if sys.platform not in ('win32', 'darwin'): print(_('D-Bus does not run correctly on this machine')) print(_('D-Bus capabilities of Gajim cannot be used')) except exceptions.SystemBusNotPresent: print(_('D-Bus does not run correctly on this machine: system bus not ' 'present')) except exceptions.SessionBusNotPresent: print(_('D-Bus does not run correctly on this machine: session bus not ' 'present')) class SystemBus: """ A Singleton for the DBus SystemBus """ def __init__(self): self.system_bus = None def SystemBus(self): if not supported: raise exceptions.DbusNotSupported if not self.present(): raise exceptions.SystemBusNotPresent return self.system_bus def bus(self): return self.SystemBus() def present(self): if not supported: return False if self.system_bus is None: try: self.system_bus = dbus.SystemBus() except dbus.DBusException: self.system_bus = None return False if self.system_bus is None: return False # Don't exit Gajim when dbus is stopped self.system_bus.set_exit_on_disconnect(False) return True system_bus = SystemBus() class SessionBus: """ A Singleton for the D-Bus SessionBus """ def __init__(self): self.session_bus = None def SessionBus(self): if not supported: raise exceptions.DbusNotSupported if not self.present(): raise exceptions.SessionBusNotPresent return self.session_bus def bus(self): return self.SessionBus() def present(self): if not supported: return False if self.session_bus is None: try: self.session_bus = dbus.SessionBus() except dbus.DBusException: self.session_bus = None return False if self.session_bus is None: return False return True session_bus = SessionBus() def get_interface(interface, path, start_service=True): """ Get an interface on the current SessionBus. If the interface isn't running, try to start it first """ if not supported: return None if session_bus.present(): bus = session_bus.SessionBus() else: return None try: obj = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') dbus_iface = dbus.Interface(obj, 'org.freedesktop.DBus') running_services = dbus_iface.ListNames() started = True if interface not in running_services: # try to start the service started = start_service and dbus_iface.StartServiceByName( interface, dbus.UInt32(0)) == 1 if not started: return None obj = bus.get_object(interface, path) return dbus.Interface(obj, interface) except Exception as error: log.debug(error) return None if supported: class MissingArgument(dbus.DBusException): _dbus_error_name = _GAJIM_ERROR_IFACE + '.MissingArgument' class InvalidArgument(dbus.DBusException): '''Raised when one of the provided arguments is invalid.''' _dbus_error_name = _GAJIM_ERROR_IFACE + '.InvalidArgument' gajim-gajim-1.1.3/gajim/common/dh.py000066400000000000000000000232301345766322700172330ustar00rootroot00000000000000# Copyright (C) 2007-2014 Yann Leboulanger # Copyright (C) 2008 Brendan Taylor # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ This module defines a number of constants; specifically, large primes suitable for use with the Diffie-Hellman key exchange These constants have been obtained from RFC2409 and RFC3526. """ import string generators = [ None, # one to get the right offset 2, 2, None, None, 2, None, None, None, None, None, None, None, None, 2, # group 14 2, 2, 2, 2 ] _HEX_PRIMES = [ None, # group 1 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF''', # group 2 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 FFFFFFFF FFFFFFFF''', # XXX how do I obtain these? None, None, # group 5 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF''', None, None, None, None, None, None, None, None, # group 14 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF''', # group 15 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF''', # group 16 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199 FFFFFFFF FFFFFFFF''', # group 17 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E 6DCC4024 FFFFFFFF FFFFFFFF''', # group 18 '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4 38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300 741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568 3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9 22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B 4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A 062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36 4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1 B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92 4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47 9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71 60C980DD 98EDD3DF FFFFFFFF FFFFFFFF''' ] _ALL_ASCII = ''.join(map(chr, range(256))) def hex_to_decimal(stripee): if not stripee: return None return int(stripee.translate(_ALL_ASCII).translate( str.maketrans("", "", string.whitespace)), 16) primes = list(map(hex_to_decimal, _HEX_PRIMES)) gajim-gajim-1.1.3/gajim/common/events.py000066400000000000000000000400161345766322700201450ustar00rootroot00000000000000# Copyright (C) 2006 Jean-Marie Traissard # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import time class Event: """ Information concerning each event """ def __init__(self, time_=None, show_in_roster=False, show_in_systray=True): """ type_ in chat, normal, file-request, file-error, file-completed, file-request-error, file-send-error, file-stopped, gc_msg, pm, printed_chat, printed_gc_msg, printed_marked_gc_msg, printed_pm, gc-invitation, subscription_request, unsubscribedm jingle-incoming parameters is (per type_): chat, normal, pm: [message, subject, kind, time, encrypted, resource, msg_log_id] where kind in error, incoming file-*: file_props gc_msg: None printed_chat: [message, subject, control, msg_log_id] printed_*: None messages that are already printed in chat, but not read gc-invitation: [room_jid, reason, password, is_continued, jid_from] subscription_request: [text, nick] unsubscribed: contact jingle-incoming: (fulljid, sessionid, content_types) """ if time_: self.time_ = time_ else: self.time_ = time.time() self.show_in_roster = show_in_roster self.show_in_systray = show_in_systray # Set when adding the event self.jid = None self.account = None class ChatEvent(Event): type_ = 'chat' def __init__(self, message, subject, kind, time_, encrypted, resource, msg_log_id, correct_id=None, xhtml=None, session=None, form_node=None, displaymarking=None, sent_forwarded=False, show_in_roster=False, show_in_systray=True, additional_data=None): Event.__init__(self, time_, show_in_roster=show_in_roster, show_in_systray=show_in_systray) self.message = message self.subject = subject self.kind = kind self.time = time_ self.encrypted = encrypted self.resource = resource self.msg_log_id = msg_log_id self.correct_id = correct_id self.xhtml = xhtml self.session = session self.form_node = form_node self.displaymarking = displaymarking self.sent_forwarded = sent_forwarded if additional_data is None: from gajim.common.helpers import AdditionalDataDict additional_data = AdditionalDataDict() self.additional_data = additional_data class NormalEvent(ChatEvent): type_ = 'normal' class PmEvent(ChatEvent): type_ = 'pm' class PrintedChatEvent(Event): type_ = 'printed_chat' def __init__(self, message, subject, control, msg_log_id, time_=None, show_in_roster=False, show_in_systray=True): Event.__init__(self, time_, show_in_roster=show_in_roster, show_in_systray=show_in_systray) self.message = message self.subject = subject self.control = control self.msg_log_id = msg_log_id class PrintedGcMsgEvent(PrintedChatEvent): type_ = 'printed_gc_msg' class PrintedMarkedGcMsgEvent(PrintedChatEvent): type_ = 'printed_marked_gc_msg' class PrintedPmEvent(PrintedChatEvent): type_ = 'printed_pm' class SubscriptionRequestEvent(Event): type_ = 'subscription_request' def __init__(self, text, nick, time_=None, show_in_roster=False, show_in_systray=True): Event.__init__(self, time_, show_in_roster=show_in_roster, show_in_systray=show_in_systray) self.text = text self.nick = nick class UnsubscribedEvent(Event): type_ = 'unsubscribed' def __init__(self, contact, time_=None, show_in_roster=False, show_in_systray=True): Event.__init__(self, time_, show_in_roster=show_in_roster, show_in_systray=show_in_systray) self.contact = contact class GcInvitationtEvent(Event): type_ = 'gc-invitation' def __init__(self, room_jid, reason, password, is_continued, jid_from, time_=None, show_in_roster=False, show_in_systray=True): Event.__init__(self, time_, show_in_roster=show_in_roster, show_in_systray=show_in_systray) self.room_jid = room_jid self.reason = reason self.password = password self.is_continued = is_continued self.jid_from = jid_from class FileRequestEvent(Event): type_ = 'file-request' def __init__(self, file_props, time_=None, show_in_roster=False, show_in_systray=True): Event.__init__(self, time_, show_in_roster=show_in_roster, show_in_systray=show_in_systray) self.file_props = file_props class FileSendErrorEvent(FileRequestEvent): type_ = 'file-send-error' class FileErrorEvent(FileRequestEvent): type_ = 'file-error' class FileRequestErrorEvent(FileRequestEvent): type_ = 'file-request-error' class FileCompletedEvent(FileRequestEvent): type_ = 'file-completed' class FileStoppedEvent(FileRequestEvent): type_ = 'file-stopped' class FileHashErrorEvent(FileRequestEvent): type_ = 'file-hash-error' class JingleIncomingEvent(Event): type_ = 'jingle-incoming' def __init__(self, peerjid, sid, content_types, time_=None, show_in_roster=False, show_in_systray=True): Event.__init__(self, time_, show_in_roster=show_in_roster, show_in_systray=show_in_systray) self.peerjid = peerjid self.sid = sid self.content_types = content_types class Events: """ Information concerning all events """ def __init__(self): self._events = {} # list of events {acct: {jid1: [E1, E2]}, } self._event_added_listeners = [] self._event_removed_listeners = [] def event_added_subscribe(self, listener): """ Add a listener when an event is added to the queue """ if not listener in self._event_added_listeners: self._event_added_listeners.append(listener) def event_added_unsubscribe(self, listener): """ Remove a listener when an event is added to the queue """ if listener in self._event_added_listeners: self._event_added_listeners.remove(listener) def event_removed_subscribe(self, listener): """ Add a listener when an event is removed from the queue """ if not listener in self._event_removed_listeners: self._event_removed_listeners.append(listener) def event_removed_unsubscribe(self, listener): """ Remove a listener when an event is removed from the queue """ if listener in self._event_removed_listeners: self._event_removed_listeners.remove(listener) def fire_event_added(self, event): for listener in self._event_added_listeners: listener(event) def fire_event_removed(self, event_list): for listener in self._event_removed_listeners: listener(event_list) def change_account_name(self, old_name, new_name): if old_name in self._events: self._events[new_name] = self._events[old_name] del self._events[old_name] def add_account(self, account): self._events[account] = {} def get_accounts(self): return self._events.keys() def remove_account(self, account): del self._events[account] def add_event(self, account, jid, event): # No such account before ? if account not in self._events: self._events[account] = {jid: [event]} # no such jid before ? elif jid not in self._events[account]: self._events[account][jid] = [event] else: self._events[account][jid].append(event) event.jid = jid event.account = account self.fire_event_added(event) def remove_events(self, account, jid, event=None, types=None): """ If event is not specified, remove all events from this jid, optionally only from given type return True if no such event found """ if types is None: types = [] if account not in self._events: return True if jid not in self._events[account]: return True if event: # remove only one event if event in self._events[account][jid]: if len(self._events[account][jid]) == 1: del self._events[account][jid] else: self._events[account][jid].remove(event) self.fire_event_removed([event]) return else: return True if types: new_list = [] # list of events to keep removed_list = [] # list of removed events for ev in self._events[account][jid]: if ev.type_ not in types: new_list.append(ev) else: removed_list.append(ev) if len(new_list) == len(self._events[account][jid]): return True if new_list: self._events[account][jid] = new_list else: del self._events[account][jid] self.fire_event_removed(removed_list) return # no event nor type given, remove them all self.fire_event_removed(self._events[account][jid]) del self._events[account][jid] def change_jid(self, account, old_jid, new_jid): if account not in self._events: return if old_jid not in self._events[account]: return if new_jid in self._events[account]: self._events[account][new_jid] += self._events[account][old_jid] else: self._events[account][new_jid] = self._events[account][old_jid] del self._events[account][old_jid] def get_nb_events(self, types=None, account=None): if types is None: types = [] return self._get_nb_events(types=types, account=account) def get_events(self, account, jid=None, types=None): """ Return all events from the given account of the form {jid1: [], jid2: []}. If jid is given, returns all events from the given jid in a list: [] optionally only from given type """ if types is None: types = [] if account not in self._events: return [] if not jid: events_list = {} # list of events for jid_ in self._events[account]: events = [] for ev in self._events[account][jid_]: if not types or ev.type_ in types: events.append(ev) if events: events_list[jid_] = events return events_list if jid not in self._events[account]: return [] events_list = [] # list of events for ev in self._events[account][jid]: if not types or ev.type_ in types: events_list.append(ev) return events_list def get_first_event(self, account=None, jid=None, type_=None): """ Return the first event of type type_ if given """ if not account: return self._get_first_event_with_attribute(self._events) events_list = self.get_events(account, jid, type_) # be sure it's bigger than latest event first_event_time = time.time() + 1 first_event = None for event in events_list: if event.time_ < first_event_time: first_event_time = event.time_ first_event = event return first_event def _get_nb_events(self, account=None, jid=None, attribute=None, types=None): """ Return the number of pending events """ if types is None: types = [] nb = 0 if account: accounts = [account] else: accounts = self._events.keys() for acct in accounts: if acct not in self._events: continue if jid: jids = [jid] else: jids = self._events[acct].keys() for j in jids: if j not in self._events[acct]: continue for event in self._events[acct][j]: if types and event.type_ not in types: continue if not attribute or \ attribute == 'systray' and event.show_in_systray or \ attribute == 'roster' and event.show_in_roster: nb += 1 return nb def _get_some_events(self, attribute): """ Attribute in systray, roster """ events = {} for account in self._events: events[account] = {} for jid in self._events[account]: events[account][jid] = [] for event in self._events[account][jid]: if attribute == 'systray' and event.show_in_systray or \ attribute == 'roster' and event.show_in_roster: events[account][jid].append(event) if not events[account][jid]: del events[account][jid] if not events[account]: del events[account] return events def _get_first_event_with_attribute(self, events): """ Get the first event events is in the form {account1: {jid1: [ev1, ev2], },. } """ # be sure it's bigger than latest event first_event_time = time.time() + 1 first_account = None first_jid = None first_event = None for account in events: for jid in events[account]: for event in events[account][jid]: if event.time_ < first_event_time: first_event_time = event.time_ first_account = account first_jid = jid first_event = event return first_account, first_jid, first_event def get_nb_systray_events(self, types=None): """ Return the number of events displayed in roster """ if types is None: types = [] return self._get_nb_events(attribute='systray', types=types) def get_systray_events(self): """ Return all events that must be displayed in systray: {account1: {jid1: [ev1, ev2], },. } """ return self._get_some_events('systray') def get_first_systray_event(self): events = self.get_systray_events() return self._get_first_event_with_attribute(events) def get_nb_roster_events(self, account=None, jid=None, types=None): """ Return the number of events displayed in roster """ if types is None: types = [] return self._get_nb_events(attribute='roster', account=account, jid=jid, types=types) def get_roster_events(self): """ Return all events that must be displayed in roster: {account1: {jid1: [ev1, ev2], },. } """ return self._get_some_events('roster') gajim-gajim-1.1.3/gajim/common/exceptions.py000066400000000000000000000076531345766322700210340ustar00rootroot00000000000000# Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006 Jean-Marie Traissard # Copyright (C) 2007 Brendan Taylor # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gajim.common.i18n import _ class PysqliteOperationalError(Exception): """ Sqlite2 raised pysqlite2.dbapi2.OperationalError """ def __init__(self, text=''): Exception.__init__(self) self.text = text def __str__(self): return self.text class DatabaseMalformed(Exception): """ The databas can't be read """ def __init__(self, path=''): Exception.__init__(self) self.path = path def __str__(self): return _('The database file (%s) cannot be read. ' 'Try to repair it (see ' 'https://dev.gajim.org/gajim/gajim/wikis/help/DatabaseBackup)' ' or remove it (all history will be lost).') % self.path class ServiceNotAvailable(Exception): """ This exception is raised when we cannot use Gajim remotely' """ def __init__(self): Exception.__init__(self) def __str__(self): return _('Service not available: Gajim is not running, or remote_control is False') class DbusNotSupported(Exception): """ D-Bus is not installed or python bindings are missing """ def __init__(self): Exception.__init__(self) def __str__(self): return _('D-Bus is not present on this machine or python module is missing') class SessionBusNotPresent(Exception): """ This exception indicates that there is no session daemon """ def __init__(self): Exception.__init__(self) def __str__(self): return _('Session bus is not available.\nTry reading %(url)s') % \ {'url': 'https://dev.gajim.org/gajim/gajim/wikis/help/GajimDBus'} class SystemBusNotPresent(Exception): """ This exception indicates that there is no session daemon """ def __init__(self): Exception.__init__(self) def __str__(self): return _('System bus is not available.\nTry reading %(url)s') % \ {'url': 'https://dev.gajim.org/gajim/gajim/wikis/help/GajimDBus'} class NegotiationError(Exception): """ A session negotiation failed """ pass class Cancelled(Exception): """ The user cancelled an operation """ pass class LatexError(Exception): """ LaTeX processing failed for some reason """ def __init__(self, text=''): Exception.__init__(self) self.text = text def __str__(self): return self.text class GajimGeneralException(Exception): """ This exception is our general exception """ def __init__(self, text=''): Exception.__init__(self) self.text = text def __str__(self): return self.text class PluginsystemError(Exception): """ Error in the pluginsystem """ def __init__(self, text=''): Exception.__init__(self) self.text = text def __str__(self): return self.text class StanzaMalformed(Exception): """ Malfromed Stanza """ def __init__(self, message, stanza=''): Exception.__init__(self, message, stanza) self._msg = '{}\n{}'.format(message, stanza) def __str__(self): return self._msg gajim-gajim-1.1.3/gajim/common/file_props.py000066400000000000000000000123271345766322700210070ustar00rootroot00000000000000""" This module is in charge of taking care of all the information related to individual files. Files are identified by the account name and its sid. >>> print(FilesProp.getFileProp('jabberid', '10')) None >>> fp = FilesProp() Traceback (most recent call last): ... Exception: this class should not be instatiated >>> print(FilesProp.getAllFileProp()) [] >>> fp = FilesProp.getNewFileProp('jabberid', '10') >>> fp2 = FilesProp.getFileProp('jabberid', '10') >>> fp == fp2 True """ from typing import Any # pylint: disable=unused-import from typing import ClassVar # pylint: disable=unused-import from typing import Dict # pylint: disable=unused-import from typing import Tuple # pylint: disable=unused-import class FilesProp: _files_props = {} # type: ClassVar[Dict[Tuple[str, str], Any]] def __init__(self): raise Exception('this class should not be instantiated') @classmethod def getNewFileProp(cls, account, sid): fp = FileProp(account, sid) cls.setFileProp(fp, account, sid) return fp @classmethod def getFileProp(cls, account, sid): if (account, sid) in cls._files_props.keys(): return cls._files_props[account, sid] @classmethod def getFilePropByAccount(cls, account): # Returns a list of file_props in one account file_props = [] for account_, sid in cls._files_props: if account_ == account: file_props.append(cls._files_props[account, sid]) return file_props @classmethod def getFilePropByType(cls, type_, sid): # This method should be deleted. Getting fileprop by type and sid is not # unique enough. More than one fileprop might have the same type and sid files_prop = cls.getAllFileProp() for fp in files_prop: if fp.type_ == type_ and fp.sid == sid: return fp @classmethod def getFilePropBySid(cls, sid): # This method should be deleted. It is kept to make things compatible # This method should be replaced and instead get the file_props by # account and sid files_prop = cls.getAllFileProp() for fp in files_prop: if fp.sid == sid: return fp @classmethod def getFilePropByTransportSid(cls, account, sid): files_prop = cls.getAllFileProp() for fp in files_prop: if fp.account == account and fp.transport_sid == sid: return fp @classmethod def getAllFileProp(cls): return list(cls._files_props.values()) @classmethod def setFileProp(cls, fp, account, sid): cls._files_props[account, sid] = fp @classmethod def deleteFileProp(cls, file_prop): files_props = cls._files_props a = s = None for account, sid in files_props: fp = files_props[account, sid] if fp is file_prop: a = account s = sid if a is not None and s is not None: del files_props[a, s] class FileProp: def __init__(self, account, sid): # Do not instantiate this class directly. Call FilesProp.getNeFileProp # instead self.streamhosts = [] self.transfered_size = [] self.started = False self.completed = False self.paused = False self.stalled = False self.connected = False self.stopped = False self.is_a_proxy = False self.proxyhost = None self.proxy_sender = None self.proxy_receiver = None self.streamhost_used = None # method callback called in case of transfer failure self.failure_cb = None # method callback called when disconnecting self.disconnect_cb = None self.continue_cb = None self.sha_str = None # transfer type: 's' for sending and 'r' for receiving self.type_ = None self.error = None # Elapsed time of the file transfer self.elapsed_time = 0 self.last_time = None self.received_len = None # full file path self.file_name = None self.name = None self.date = None self.desc = None self.offset = None self.sender = None self.receiver = None self.tt_account = None self.size = None self._sid = sid self.transport_sid = None self.account = account self.mime_type = None self.algo = None self.direction = None self.syn_id = None self.seq = None self.hash_ = None self.fd = None self.startexmpp = None # Type of the session, if it is 'jingle' or 'si' self.session_type = None self.request_id = None self.proxyhosts = None self.dstaddr = None def getsid(self): # Getter of the property sid return self._sid def setsid(self, value): # The sid value will change # we need to change the in _files_props key as well del FilesProp._files_props[self.account, self._sid] self._sid = value FilesProp._files_props[self.account, self._sid] = self sid = property(getsid, setsid) if __name__ == "__main__": import doctest doctest.testmod() gajim-gajim-1.1.3/gajim/common/fuzzyclock.py000077500000000000000000000060001345766322700210420ustar00rootroot00000000000000# Copyright (C) 2006 Christoph Neuroth # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Jean-Marie Traissard # Copyright (C) 2009 Benjamin Richter
# # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Python class to show a "fuzzy clock". Homepage of the original: http://home.gna.org/fuzzyclock/ Project Page of the original: http://gna.org/projects/fuzzyclock The class is based on a port from PHP code by Henrique Recidive which was in turn based on the Fuzzy Clock Applet of Frerich Raabe (KDE). So most of the credit goes to this guys, thanks :-) """ from gajim.common.i18n import _ class FuzzyClock: HOUR_NAMES = [ _('twelve'), _('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'), _('ten'), _('eleven') ] # Strings to use for the output. %(0)s will be replaced with # the preceding hour (e.g. "x PAST %(0)s"), %(1)s with the coming hour # (e.g. "x TO %(0)s") FUZZY_TIME = [ _("%(0)s o'clock"), _('five past %(0)s'), _('ten past %(0)s'), _('quarter past %(0)s'), _('twenty past %(0)s'), _('twenty five past %(0)s'), _('half past %(0)s'), _('twenty five to %(1)s'), _('twenty to %(1)s'), _('quarter to %(1)s'), _('ten to %(1)s'), _('five to %(1)s'), _("%(1)s o'clock") ] FUZZY_DAYTIME = [ _('Night'), _('Early morning'), _('Morning'), _('Almost noon'), _('Noon'), _('Afternoon'), _('Evening'), _('Late evening'), _('Night') ] FUZZY_WEEK = [ _('Start of week'), _('Middle of week'), _('Middle of week'), _('Middle of week'), _('End of week'), _('Weekend!'), _('Weekend!') ] def fuzzy_time(self, fuzzyness, now): if fuzzyness in (1, 2): if fuzzyness == 1: sector = int(round(now.tm_min / 5.0)) else: sector = int(round(now.tm_min / 15.0)) * 3 return self.FUZZY_TIME[sector] % { '0': self.HOUR_NAMES[now.tm_hour % 12], '1': self.HOUR_NAMES[(now.tm_hour + 1) % 12]} elif fuzzyness == 3: return self.FUZZY_DAYTIME[int(round(now.tm_hour / 3.0))] else: return self.FUZZY_WEEK[now.tm_wday] gajim-gajim-1.1.3/gajim/common/ged.py000066400000000000000000000067411345766322700174070ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' Global Events Dispatcher module. :author: Mateusz Biliński :since: 8th August 2008 :copyright: Copyright (2008) Mateusz Biliński :copyright: Copyright (2011) Yann Leboulanger :license: GPL ''' import logging import traceback import inspect from nbxmpp import NodeProcessed log = logging.getLogger('gajim.c.ged') PRECORE = 10 CORE = 20 POSTCORE = 30 PREGUI = 40 PREGUI1 = 50 GUI1 = 60 POSTGUI1 = 70 PREGUI2 = 80 GUI2 = 90 POSTGUI2 = 100 POSTGUI = 110 OUT_PREGUI = 10 OUT_PREGUI1 = 20 OUT_GUI1 = 30 OUT_POSTGUI1 = 40 OUT_PREGUI2 = 50 OUT_GUI2 = 60 OUT_POSTGUI2 = 70 OUT_POSTGUI = 80 OUT_PRECORE = 90 OUT_CORE = 100 OUT_POSTCORE = 110 class GlobalEventsDispatcher: def __init__(self): self.handlers = {} def register_event_handler(self, event_name, priority, handler): if event_name in self.handlers: handlers_list = self.handlers[event_name] i = 0 for i, handler_tuple in enumerate(handlers_list): if priority < handler_tuple[0]: break else: # no event with smaller prio found, put it at the end i += 1 handlers_list.insert(i, (priority, handler)) else: self.handlers[event_name] = [(priority, handler)] def remove_event_handler(self, event_name, priority, handler): if event_name in self.handlers: try: self.handlers[event_name].remove((priority, handler)) except ValueError as error: log.warning( '''Function (%s) with priority "%s" never registered as handler of event "%s". Couldn\'t remove. Error: %s''', handler, priority, event_name, error) def raise_event(self, event_name, *args, **kwargs): log.debug('Raise event: %s', event_name) if event_name in self.handlers: node_processed = False # Iterate over a copy of the handlers list, so while iterating # the original handlers list can be modified for _priority, handler in list(self.handlers[event_name]): try: if inspect.ismethod(handler): log.debug('Call handler %s on %s', handler.__name__, handler.__self__) else: log.debug('Call handler %s', handler.__name__) if handler(*args, **kwargs): return True except NodeProcessed: node_processed = True except Exception: log.error('Error while running an event handler: %s', handler) traceback.print_exc() if node_processed: raise NodeProcessed gajim-gajim-1.1.3/gajim/common/gpg.py000066400000000000000000000130261345766322700174170ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Alex Mauer # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2007 Stephan Erb # Copyright (C) 2008 Jean-Marie Traissard # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import logging from gajim.common import app if app.is_installed('GPG'): import gnupg gnupg.logger = logging.getLogger('gajim.c.gnupg') class GnuPG(gnupg.GPG): def __init__(self): use_agent = app.config.get('use_gpg_agent') gnupg.GPG.__init__(self, gpgbinary=app.get_gpg_binary(), use_agent=use_agent) encoding = app.config.get('pgp_encoding') if encoding: self.encoding = encoding self.decode_errors = 'replace' self.passphrase = None self.always_trust = [] # list of keyID to always trust def encrypt(self, str_, recipients, always_trust=False): trust = always_trust if not trust: # check if we trust all keys trust = True for key in recipients: if key not in self.always_trust: trust = False if not trust: # check that we'll be able to encrypt result = super(GnuPG, self).list_keys(keys=recipients) for key in result: if key['trust'] not in ('f', 'u'): if key['keyid'][-8:] not in self.always_trust: return '', 'NOT_TRUSTED ' + key['keyid'][-8:] trust = True result = super(GnuPG, self).encrypt(str_.encode('utf8'), recipients, always_trust=trust, passphrase=self.passphrase) if result.ok: error = '' else: error = result.status return self._stripHeaderFooter(str(result)), error def decrypt(self, str_, keyID): data = self._addHeaderFooter(str_, 'MESSAGE') result = super(GnuPG, self).decrypt(data.encode('utf8'), passphrase=self.passphrase) return result.data.decode('utf8') def sign(self, str_, keyID): result = super(GnuPG, self).sign(str_.encode('utf8'), keyid=keyID, detach=True, passphrase=self.passphrase) if result.fingerprint: return self._stripHeaderFooter(str(result)) if hasattr(result, 'status') and result.status == 'key expired': return 'KEYEXPIRED' return 'BAD_PASSPHRASE' def verify(self, str_, sign): if str_ is None: return '' # Hash algorithm is not transfered in the signed presence stanza so try # all algorithms. Text name for hash algorithms from RFC 4880 - section 9.4 hash_algorithms = ['SHA512', 'SHA384', 'SHA256', 'SHA224', 'SHA1', 'RIPEMD160'] for algo in hash_algorithms: data = os.linesep.join( ['-----BEGIN PGP SIGNED MESSAGE-----', 'Hash: ' + algo, '', str_, self._addHeaderFooter(sign, 'SIGNATURE')] ) result = super(GnuPG, self).verify(data.encode('utf8')) if result.valid: return result.key_id return '' def get_key(self, keyID): return super(GnuPG, self).list_keys(keys=[keyID]) def get_keys(self, secret=False): keys = {} result = super(GnuPG, self).list_keys(secret=secret) for key in result: # Take first not empty uid keys[key['keyid'][8:]] = [uid for uid in key['uids'] if uid][0] return keys def get_secret_keys(self): return self.get_keys(True) def _stripHeaderFooter(self, data): """ Remove header and footer from data """ if not data: return '' lines = data.splitlines() while lines[0] != '': lines.remove(lines[0]) while lines[0] == '': lines.remove(lines[0]) i = 0 for line in lines: if line: if line[0] == '-': break i = i+1 line = '\n'.join(lines[0:i]) return line def _addHeaderFooter(self, data, type_): """ Add header and footer from data """ out = "-----BEGIN PGP %s-----" % type_ + os.linesep out = out + "Version: PGP" + os.linesep out = out + os.linesep out = out + data + os.linesep out = out + "-----END PGP %s-----" % type_ + os.linesep return out gajim-gajim-1.1.3/gajim/common/helpers.py000066400000000000000000001477541345766322700203240ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Dimitur Kirov # Nikos Kouremenos # Copyright (C) 2006 Alex Mauer # Copyright (C) 2006-2007 Travis Shirk # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # James Newton # Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import sys import re import os import subprocess import urllib import webbrowser import errno import select import base64 import hashlib import shlex import socket import time import logging import json import shutil import collections from io import StringIO from datetime import datetime, timedelta from distutils.version import LooseVersion as V from encodings.punycode import punycode_encode from string import Template import nbxmpp from nbxmpp.stringprepare import nameprep import precis_i18n.codec # pylint: disable=unused-import from gajim.common import app from gajim.common import caps_cache from gajim.common import configpaths from gajim.common.i18n import Q_ from gajim.common.i18n import _ from gajim.common.i18n import ngettext from gajim.common.const import Display if app.is_installed('PYCURL'): import pycurl log = logging.getLogger('gajim.c.helpers') special_groups = (_('Transports'), _('Not in Roster'), _('Observers'), _('Groupchats')) class InvalidFormat(Exception): pass def decompose_jid(jidstring): user = None server = None resource = None # Search for delimiters user_sep = jidstring.find('@') res_sep = jidstring.find('/') if user_sep == -1: if res_sep == -1: # host server = jidstring else: # host/resource server = jidstring[0:res_sep] resource = jidstring[res_sep + 1:] else: if res_sep == -1: # user@host user = jidstring[0:user_sep] server = jidstring[user_sep + 1:] else: if user_sep < res_sep: # user@host/resource user = jidstring[0:user_sep] server = jidstring[user_sep + 1:user_sep + (res_sep - user_sep)] resource = jidstring[res_sep + 1:] else: # server/resource (with an @ in resource) server = jidstring[0:res_sep] resource = jidstring[res_sep + 1:] return user, server, resource def parse_jid(jidstring): """ Perform stringprep on all JID fragments from a string and return the full jid """ # This function comes from http://svn.twistedmatrix.com/cvs/trunk/twisted/words/protocols/jabber/jid.py return prep(*decompose_jid(jidstring)) def idn_to_ascii(host): """ Convert IDN (Internationalized Domain Names) to ACE (ASCII-compatible encoding) """ from encodings import idna labels = idna.dots.split(host) converted_labels = [] for label in labels: if label: converted_labels.append(idna.ToASCII(label).decode('utf-8')) else: converted_labels.append('') return ".".join(converted_labels) def ascii_to_idn(host): """ Convert ACE (ASCII-compatible encoding) to IDN (Internationalized Domain Names) """ from encodings import idna labels = idna.dots.split(host) converted_labels = [] for label in labels: converted_labels.append(idna.ToUnicode(label)) return ".".join(converted_labels) def puny_encode_url(url): _url = url if '//' not in _url: _url = '//' + _url try: o = urllib.parse.urlparse(_url) p_loc = idn_to_ascii(o.netloc) except Exception: log.debug('urlparse failed: %s', url) return False return url.replace(o.netloc, p_loc) def parse_resource(resource): """ Perform stringprep on resource and return it """ if resource: try: return resource.encode('OpaqueString').decode('utf-8') except UnicodeError: raise InvalidFormat('Invalid character in resource.') def prep(user, server, resource): """ Perform stringprep on all JID fragments and return the full jid """ # This function comes from #http://svn.twistedmatrix.com/cvs/trunk/twisted/words/protocols/jabber/jid.py ip_address = False try: socket.inet_aton(server) ip_address = True except socket.error: pass if not ip_address and hasattr(socket, 'inet_pton'): try: socket.inet_pton(socket.AF_INET6, server.strip('[]')) server = '[%s]' % server.strip('[]') ip_address = True except (socket.error, ValueError): pass if not ip_address: if server is not None: if server.endswith('.'): # RFC7622, 3.2 server = server[:-1] if not server or len(server.encode('utf-8')) > 1023: raise InvalidFormat(_('Server must be between 1 and 1023 bytes')) try: server = nameprep.prepare(server) except UnicodeError: raise InvalidFormat(_('Invalid character in hostname.')) else: raise InvalidFormat(_('Server address required.')) if user is not None: if not user or len(user.encode('utf-8')) > 1023: raise InvalidFormat(_('Username must be between 1 and 1023 bytes')) try: user = user.encode('UsernameCaseMapped').decode('utf-8') except UnicodeError: raise InvalidFormat(_('Invalid character in username.')) else: user = None if resource is not None: if not resource or len(resource.encode('utf-8')) > 1023: raise InvalidFormat(_('Resource must be between 1 and 1023 bytes')) try: resource = resource.encode('OpaqueString').decode('utf-8') except UnicodeError: raise InvalidFormat(_('Invalid character in resource.')) else: resource = None if user: if resource: return '%s@%s/%s' % (user, server, resource) return '%s@%s' % (user, server) if resource: return '%s/%s' % (server, resource) return server def windowsify(s): if os.name == 'nt': return s.capitalize() return s def temp_failure_retry(func, *args, **kwargs): while True: try: return func(*args, **kwargs) except (os.error, IOError, select.error) as ex: if ex.errno == errno.EINTR: continue else: raise def get_uf_show(show, use_mnemonic=False): """ Return a userfriendly string for dnd/xa/chat and make all strings translatable If use_mnemonic is True, it adds _ so GUI should call with True for accessibility issues """ if show == 'dnd': if use_mnemonic: uf_show = _('_Busy') else: uf_show = _('Busy') elif show == 'xa': if use_mnemonic: uf_show = _('_Not Available') else: uf_show = _('Not Available') elif show == 'chat': if use_mnemonic: uf_show = _('_Free for Chat') else: uf_show = _('Free for Chat') elif show == 'online': if use_mnemonic: uf_show = Q_('?user status:_Available') else: uf_show = Q_('?user status:Available') elif show == 'connecting': uf_show = _('Connecting') elif show == 'away': if use_mnemonic: uf_show = _('A_way') else: uf_show = _('Away') elif show == 'offline': if use_mnemonic: uf_show = _('_Offline') else: uf_show = _('Offline') elif show == 'invisible': if use_mnemonic: uf_show = _('_Invisible') else: uf_show = _('Invisible') elif show == 'not in roster': uf_show = _('Not in Roster') elif show == 'requested': uf_show = Q_('?contact has status:Unknown') else: uf_show = Q_('?contact has status:Has errors') return uf_show def get_css_show_color(show): if show in ('online', 'chat', 'invisible'): return 'status-online' if show in ('offline', 'not in roster', 'requested'): return None if show in ('xa', 'dnd'): return 'status-dnd' if show == 'away': return 'status-away' def get_uf_sub(sub): if sub == 'none': uf_sub = Q_('?Subscription we already have:None') elif sub == 'to': uf_sub = _('To') elif sub == 'from': uf_sub = _('From') elif sub == 'both': uf_sub = _('Both') else: uf_sub = _('Unknown') return uf_sub def get_uf_ask(ask): if ask is None: uf_ask = Q_('?Ask (for Subscription):None') elif ask == 'subscribe': uf_ask = _('Subscribe') else: uf_ask = ask return uf_ask def get_uf_role(role, plural=False): ''' plural determines if you get Moderators or Moderator''' if role == 'none': role_name = Q_('?Group Chat Contact Role:None') elif role == 'moderator': if plural: role_name = _('Moderators') else: role_name = _('Moderator') elif role == 'participant': if plural: role_name = _('Participants') else: role_name = _('Participant') elif role == 'visitor': if plural: role_name = _('Visitors') else: role_name = _('Visitor') return role_name def get_uf_affiliation(affiliation): '''Get a nice and translated affilition for muc''' if affiliation == 'none': affiliation_name = Q_('?Group Chat Contact Affiliation:None') elif affiliation == 'owner': affiliation_name = _('Owner') elif affiliation == 'admin': affiliation_name = _('Administrator') elif affiliation == 'member': affiliation_name = _('Member') else: # Argl ! An unknown affiliation ! affiliation_name = affiliation.capitalize() return affiliation_name def get_sorted_keys(adict): keys = sorted(adict.keys()) return keys def to_one_line(msg): msg = msg.replace('\\', '\\\\') msg = msg.replace('\n', '\\n') # s1 = 'test\ntest\\ntest' # s11 = s1.replace('\\', '\\\\') # s12 = s11.replace('\n', '\\n') # s12 # 'test\\ntest\\\\ntest' return msg def from_one_line(msg): # (? 48: hash_ = hashlib.md5(filename.encode('utf-8')) filename = base64.b64encode(hash_.digest()).decode('utf-8') # make it latin chars only filename = punycode_encode(filename).decode('utf-8') filename = filename.replace('/', '_') if os.name == 'nt': filename = filename.replace('?', '_').replace(':', '_')\ .replace('\\', '_').replace('"', "'").replace('|', '_')\ .replace('*', '_').replace('<', '_').replace('>', '_') return filename def reduce_chars_newlines(text, max_chars=0, max_lines=0): """ Cut the chars after 'max_chars' on each line and show only the first 'max_lines' If any of the params is not present (None or 0) the action on it is not performed """ def _cut_if_long(string): if len(string) > max_chars: string = string[:max_chars - 3] + '…' return string if max_lines == 0: lines = text.split('\n') else: lines = text.split('\n', max_lines)[:max_lines] if max_chars > 0: if lines: lines = [_cut_if_long(e) for e in lines] if lines: reduced_text = '\n'.join(lines) if reduced_text != text: reduced_text += '…' else: reduced_text = '' return reduced_text def get_account_status(account): status = reduce_chars_newlines(account['status_line'], 100, 1) return status def datetime_tuple(timestamp): """ Convert timestamp using strptime and the format: %Y%m%dT%H:%M:%S Because of various datetime formats are used the following exceptions are handled: - Optional milliseconds appened to the string are removed - Optional Z (that means UTC) appened to the string are removed - XEP-082 datetime strings have all '-' cahrs removed to meet the above format. """ date, tim = timestamp.split('T', 1) date = date.replace('-', '') tim = tim.replace('z', '') tim = tim.replace('Z', '') zone = None if '+' in tim: sign = -1 tim, zone = tim.split('+', 1) if '-' in tim: sign = 1 tim, zone = tim.split('-', 1) tim = tim.split('.')[0] tim = time.strptime(date + 'T' + tim, '%Y%m%dT%H:%M:%S') if zone: zone = zone.replace(':', '') tim = datetime.fromtimestamp(time.mktime(tim)) if len(zone) > 2: zone = time.strptime(zone, '%H%M') else: zone = time.strptime(zone, '%H') zone = timedelta(hours=zone.tm_hour, minutes=zone.tm_min) tim += zone * sign tim = tim.timetuple() return tim def convert_bytes(string): suffix = '' # IEC standard says KiB = 1024 bytes KB = 1000 bytes # but do we use the standard? use_kib_mib = app.config.get('use_kib_mib') align = 1024. bytes_ = float(string) if bytes_ >= align: bytes_ = round(bytes_/align, 1) if bytes_ >= align: bytes_ = round(bytes_/align, 1) if bytes_ >= align: bytes_ = round(bytes_/align, 1) if use_kib_mib: #GiB means gibibyte suffix = _('%s GiB') else: #GB means gigabyte suffix = _('%s GB') else: if use_kib_mib: #MiB means mibibyte suffix = _('%s MiB') else: #MB means megabyte suffix = _('%s MB') else: if use_kib_mib: #KiB means kibibyte suffix = _('%s KiB') else: #KB means kilo bytes suffix = _('%s KB') else: #B means bytes suffix = _('%s B') return suffix % str(bytes_) def get_contact_dict_for_account(account): """ Create a dict of jid, nick -> contact with all contacts of account. Can be used for completion lists """ contacts_dict = {} for jid in app.contacts.get_jid_list(account): contact = app.contacts.get_contact_with_highest_priority(account, jid) contacts_dict[jid] = contact name = contact.name if name in contacts_dict: contact1 = contacts_dict[name] del contacts_dict[name] contacts_dict['%s (%s)' % (name, contact1.jid)] = contact1 contacts_dict['%s (%s)' % (name, jid)] = contact elif contact.name: if contact.name == app.get_nick_from_jid(jid): del contacts_dict[jid] contacts_dict[name] = contact return contacts_dict def launch_browser_mailer(kind, uri): # kind = 'url' or 'mail' if kind == 'url' and uri.startswith('file://'): launch_file_manager(uri) return if kind in ('mail', 'sth_at_sth') and not uri.startswith('mailto:'): uri = 'mailto:' + uri if kind == 'url' and uri.startswith('www.'): uri = 'http://' + uri if not app.config.get('autodetect_browser_mailer'): if kind == 'url': command = app.config.get('custombrowser') elif kind in ('mail', 'sth_at_sth'): command = app.config.get('custommailapp') if command == '': # if no app is configured return command = build_command(command, uri) try: exec_command(command) except Exception: pass else: webbrowser.open(uri) def launch_file_manager(path_to_open): if os.name == 'nt': try: os.startfile(path_to_open) # if pywin32 is installed we open except Exception: pass else: if not app.config.get('autodetect_browser_mailer'): command = app.config.get('custom_file_manager') if command == '': # if no app is configured return else: command = 'xdg-open' command = build_command(command, path_to_open) try: exec_command(command) except Exception: pass def play_sound(event): if not app.config.get('sounds_on'): return path_to_soundfile = app.config.get_per('soundevents', event, 'path') play_sound_file(path_to_soundfile) def check_soundfile_path(file_, dirs=None): """ Check if the sound file exists :param file_: the file to check, absolute or relative to 'dirs' path :param dirs: list of knows paths to fallback if the file doesn't exists (eg: ~/.gajim/sounds/, DATADIR/sounds...). :return the path to file or None if it doesn't exists. """ if dirs is None: dirs = [configpaths.get('MY_DATA'), configpaths.get('DATA')] if not file_: return None if os.path.exists(file_): return file_ for d in dirs: d = os.path.join(d, 'sounds', file_) if os.path.exists(d): return d return None def strip_soundfile_path(file_, dirs=None, abs_=True): """ Remove knowns paths from a sound file Filechooser returns absolute path. If path is a known fallback path, we remove it. So config have no hardcoded path to DATA_DIR and text in textfield is shorther. param: file_: the filename to strip. param: dirs: list of knowns paths from which the filename should be stripped. param: abs_: force absolute path on dirs """ if not file_: return None if dirs is None: dirs = [configpaths.get('MY_DATA'), configpaths.get('DATA')] name = os.path.basename(file_) for d in dirs: d = os.path.join(d, 'sounds', name) if abs_: d = os.path.abspath(d) if file_ == d: return name return file_ def play_sound_file(path_to_soundfile): path_to_soundfile = check_soundfile_path(path_to_soundfile) if path_to_soundfile is None: return if sys.platform == 'win32': import winsound try: winsound.PlaySound(path_to_soundfile, winsound.SND_FILENAME|winsound.SND_ASYNC) except Exception: log.exception('Sound Playback Error') elif sys.platform == 'darwin': try: from AppKit import NSSound except ImportError: log.exception('Sound Playback Error') return sound = NSSound.alloc() sound.initWithContentsOfFile_byReference_(path_to_soundfile, True) sound.play() elif app.config.get('soundplayer') == '': try: import wave import ossaudiodev except Exception: log.exception('Sound Playback Error') return def _oss_play(): sndfile = wave.open(path_to_soundfile, 'rb') nc, sw, fr, nf, _comptype, _compname = sndfile.getparams() dev = ossaudiodev.open('/dev/dsp', 'w') dev.setparameters(sw * 8, nc, fr) dev.write(sndfile.readframes(nf)) sndfile.close() dev.close() app.thread_interface(_oss_play) else: player = app.config.get('soundplayer') command = build_command(player, path_to_soundfile) exec_command(command) def get_global_show(): maxi = 0 for account in app.connections: if not app.config.get_per('accounts', account, 'sync_with_global_status'): continue connected = app.connections[account].connected if connected > maxi: maxi = connected return app.SHOW_LIST[maxi] def get_global_status(): maxi = 0 for account in app.connections: if not app.config.get_per('accounts', account, 'sync_with_global_status'): continue connected = app.connections[account].connected if connected > maxi: maxi = connected status = app.connections[account].status return status def statuses_unified(): """ Test if all statuses are the same """ reference = None for account in app.connections: if not app.config.get_per('accounts', account, 'sync_with_global_status'): continue if reference is None: reference = app.connections[account].connected elif reference != app.connections[account].connected: return False return True def get_icon_name_to_show(contact, account=None): """ Get the icon name to show in online, away, requested, etc """ if account and app.events.get_nb_roster_events(account, contact.jid): return 'event' if account and app.events.get_nb_roster_events( account, contact.get_full_jid()): return 'event' if account and account in app.interface.minimized_controls and \ contact.jid in app.interface.minimized_controls[account] and app.interface.\ minimized_controls[account][contact.jid].get_nb_unread_pm() > 0: return 'event' if account and contact.jid in app.gc_connected[account]: if app.gc_connected[account][contact.jid]: return 'muc_active' return 'muc_inactive' if contact.jid.find('@') <= 0: # if not '@' or '@' starts the jid ==> agent return contact.show if contact.sub in ('both', 'to'): return contact.show if contact.ask == 'subscribe': return 'requested' transport = app.get_transport_name_from_jid(contact.jid) if transport: return contact.show if contact.show in app.SHOW_LIST: return contact.show return 'not in roster' def get_full_jid_from_iq(iq_obj): """ Return the full jid (with resource) from an iq """ jid = iq_obj.getFrom() if jid is None: return None return parse_jid(str(iq_obj.getFrom())) def get_jid_from_iq(iq_obj): """ Return the jid (without resource) from an iq """ jid = get_full_jid_from_iq(iq_obj) return app.get_jid_without_resource(jid) def get_auth_sha(sid, initiator, target): """ Return sha of sid + initiator + target used for proxy auth """ return hashlib.sha1(("%s%s%s" % (sid, initiator, target)).encode('utf-8')).\ hexdigest() def remove_invalid_xml_chars(string): if string: string = re.sub(app.interface.invalid_XML_chars_re, '', string) return string def get_random_string_16(): """ Create random string of length 16 """ rng = list(range(65, 90)) rng.extend(range(48, 57)) char_sequence = [chr(e) for e in rng] from random import sample return ''.join(sample(char_sequence, 16)) def get_os_info(): if app.os_info: return app.os_info app.os_info = 'N/A' if os.name == 'nt' or sys.platform == 'darwin': import platform app.os_info = platform.system() + " " + platform.release() elif os.name == 'posix': try: import distro app.os_info = distro.name(pretty=True) except ImportError: import platform app.os_info = platform.system() return app.os_info def allow_showing_notification(account, type_='notify_on_new_message', is_first_message=True): """ Is it allowed to show nofication? Check OUR status and if we allow notifications for that status type is the option that need to be True e.g.: notify_on_signing is_first_message: set it to false when it's not the first message """ if type_ and (not app.config.get(type_) or not is_first_message): return False if app.config.get('autopopupaway'): # always show notification return True if app.connections[account].connected in (2, 3): # we're online or chat return True return False def allow_popup_window(account): """ Is it allowed to popup windows? """ autopopup = app.config.get('autopopup') autopopupaway = app.config.get('autopopupaway') if autopopup and (autopopupaway or \ app.connections[account].connected in (2, 3)): # we're online or chat return True return False def allow_sound_notification(account, sound_event): if app.config.get('sounddnd') or app.connections[account].connected != \ app.SHOW_LIST.index('dnd') and app.config.get_per('soundevents', sound_event, 'enabled'): return True return False def get_chat_control(account, contact): full_jid_with_resource = contact.jid if contact.resource: full_jid_with_resource += '/' + contact.resource highest_contact = app.contacts.get_contact_with_highest_priority( account, contact.jid) # Look for a chat control that has the given resource, or default to # one without resource ctrl = app.interface.msg_win_mgr.get_control(full_jid_with_resource, account) if ctrl: return ctrl if (highest_contact and highest_contact.resource and contact.resource != highest_contact.resource): return None # unknown contact or offline message return app.interface.msg_win_mgr.get_control(contact.jid, account) def get_notification_icon_tooltip_dict(): """ Return a dict of the form {acct: {'show': show, 'message': message, 'event_lines': [list of text lines to show in tooltip]} """ # How many events must there be before they're shown summarized, not per-user max_ungrouped_events = 10 accounts = get_accounts_info() # Gather events. (With accounts, when there are more.) for account in accounts: account_name = account['name'] account['event_lines'] = [] # Gather events per-account pending_events = app.events.get_events(account=account_name) messages, non_messages, total_messages, total_non_messages = {}, {}, 0, 0 for jid in pending_events: for event in pending_events[jid]: if event.type_.count('file') > 0: # This is a non-messagee event. messages[jid] = non_messages.get(jid, 0) + 1 total_non_messages = total_non_messages + 1 else: # This is a message. messages[jid] = messages.get(jid, 0) + 1 total_messages = total_messages + 1 # Display unread messages numbers, if any if total_messages > 0: if total_messages > max_ungrouped_events: text = ngettext( '%d message pending', '%d messages pending', total_messages, total_messages, total_messages) account['event_lines'].append(text) else: for jid in messages: text = ngettext( '%d message pending', '%d messages pending', messages[jid], messages[jid], messages[jid]) contact = app.contacts.get_first_contact_from_jid( account['name'], jid) text += ' ' if jid in app.gc_connected[account['name']]: text += _('from room %s') % (jid) elif contact: name = contact.get_shown_name() text += _('from user %s') % (name) else: text += _('from %s') % (jid) account['event_lines'].append(text) # Display unseen events numbers, if any if total_non_messages > 0: if total_non_messages > max_ungrouped_events: text = ngettext( '%d event pending', '%d events pending', total_non_messages, total_non_messages, total_non_messages) account['event_lines'].append(text) else: for jid in non_messages: text = ngettext('%d event pending', '%d events pending', non_messages[jid], non_messages[jid], non_messages[jid]) text += ' ' + _('from user %s') % (jid) account[account]['event_lines'].append(text) return accounts def get_notification_icon_tooltip_text(): text = None # How many events must there be before they're shown summarized, not per-user # max_ungrouped_events = 10 # Character which should be used to indent in the tooltip. indent_with = ' ' accounts = get_notification_icon_tooltip_dict() if not accounts: # No configured account return _('Gajim') # at least one account present # Is there more that one account? if len(accounts) == 1: show_more_accounts = False else: show_more_accounts = True # If there is only one account, its status is shown on the first line. if show_more_accounts: text = _('Gajim') else: text = _('Gajim - %s') % (get_account_status(accounts[0])) # Gather and display events. (With accounts, when there are more.) for account in accounts: account_name = account['name'] # Set account status, if not set above if show_more_accounts: message = '\n' + indent_with + ' %s - %s' text += message % (account_name, get_account_status(account)) # Account list shown, messages need to be indented more indent_how = 2 else: # If no account list is shown, messages could have default indenting. indent_how = 1 for line in account['event_lines']: text += '\n' + indent_with * indent_how + ' ' text += line return text def get_accounts_info(): """ Helper for notification icon tooltip """ accounts = [] accounts_list = sorted(app.contacts.get_accounts()) for account in accounts_list: status_idx = app.connections[account].connected # uncomment the following to hide offline accounts # if status_idx == 0: continue status = app.SHOW_LIST[status_idx] message = app.connections[account].status single_line = get_uf_show(status) if message is None: message = '' else: message = message.strip() if message != '': single_line += ': ' + message account_label = app.get_account_label(account) accounts.append({'name': account, 'account_label': account_label, 'status_line': single_line, 'show': status, 'message': message}) return accounts def get_current_show(account): if account not in app.connections: return 'offline' status = app.connections[account].connected return app.SHOW_LIST[status] def get_iconset_path(iconset): if os.path.isdir(os.path.join(configpaths.get('DATA'), 'iconsets', iconset)): return os.path.join(configpaths.get('DATA'), 'iconsets', iconset) if os.path.isdir(os.path.join(configpaths.get('MY_ICONSETS'), iconset)): return os.path.join(configpaths.get('MY_ICONSETS'), iconset) def get_mood_iconset_path(iconset): if os.path.isdir(os.path.join(configpaths.get('DATA'), 'moods', iconset)): return os.path.join(configpaths.get('DATA'), 'moods', iconset) if os.path.isdir( os.path.join(configpaths.get('MY_MOOD_ICONSETS'), iconset)): return os.path.join(configpaths.get('MY_MOOD_ICONSETS'), iconset) def get_activity_iconset_path(iconset): if os.path.isdir(os.path.join(configpaths.get('DATA'), 'activities', iconset)): return os.path.join(configpaths.get('DATA'), 'activities', iconset) if os.path.isdir(os.path.join(configpaths.get('MY_ACTIVITY_ICONSETS'), iconset)): return os.path.join(configpaths.get('MY_ACTIVITY_ICONSETS'), iconset) def get_transport_path(transport): if os.path.isdir(os.path.join(configpaths.get('DATA'), 'iconsets', 'transports', transport)): return os.path.join(configpaths.get('DATA'), 'iconsets', 'transports', transport) if os.path.isdir(os.path.join(configpaths.get('MY_ICONSETS'), 'transports', transport)): return os.path.join(configpaths.get('MY_ICONSETS'), 'transports', transport) # No transport folder found, use default jabber one return get_iconset_path(app.config.get('iconset')) def prepare_and_validate_gpg_keyID(account, jid, keyID): """ Return an eight char long keyID that can be used with for GPG encryption with this contact If the given keyID is None, return UNKNOWN; if the key does not match the assigned key XXXXXXXXMISMATCH is returned. If the key is trusted and not yet assigned, assign it. """ if app.connections[account].USE_GPG: if keyID and len(keyID) == 16: keyID = keyID[8:] attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys and keyID: attachedkeyID = attached_keys[attached_keys.index(jid) + 1] if attachedkeyID != keyID: # Get signing subkeys for the attached key subkeys = [] for key in app.connections[account].gpg.list_keys(): if key['keyid'][8:] == attachedkeyID: subkeys = [subkey[0][8:] for subkey in key['subkeys'] \ if subkey[1] == 's'] break if keyID not in subkeys: # Mismatch! Another gpg key was expected keyID += 'MISMATCH' elif jid in attached_keys: # An unsigned presence, just use the assigned key keyID = attached_keys[attached_keys.index(jid) + 1] elif keyID: full_key = app.connections[account].ask_gpg_keys(keyID=keyID) # Assign the corresponding key, if we have it in our keyring if full_key: for u in app.contacts.get_contacts(account, jid): u.keyID = keyID keys_str = app.config.get_per('accounts', account, 'attached_gpg_keys') keys_str += jid + ' ' + keyID + ' ' app.config.set_per('accounts', account, 'attached_gpg_keys', keys_str) elif keyID is None: keyID = 'UNKNOWN' return keyID def update_optional_features(account=None): if account: accounts = [account] else: accounts = [a for a in app.connections] for a in accounts: app.gajim_optional_features[a] = [] if app.config.get_per('accounts', a, 'subscribe_mood'): app.gajim_optional_features[a].append(nbxmpp.NS_MOOD + '+notify') if app.config.get_per('accounts', a, 'subscribe_activity'): app.gajim_optional_features[a].append(nbxmpp.NS_ACTIVITY + \ '+notify') if app.config.get_per('accounts', a, 'publish_tune'): app.gajim_optional_features[a].append(nbxmpp.NS_TUNE) if app.config.get_per('accounts', a, 'publish_location'): app.gajim_optional_features[a].append(nbxmpp.NS_LOCATION) if app.config.get_per('accounts', a, 'subscribe_tune'): app.gajim_optional_features[a].append(nbxmpp.NS_TUNE + '+notify') if app.config.get_per('accounts', a, 'subscribe_nick'): app.gajim_optional_features[a].append(nbxmpp.NS_NICK + '+notify') if app.config.get_per('accounts', a, 'subscribe_location'): app.gajim_optional_features[a].append(nbxmpp.NS_LOCATION + \ '+notify') if app.config.get('outgoing_chat_state_notifactions') != 'disabled': app.gajim_optional_features[a].append(nbxmpp.NS_CHATSTATES) if not app.config.get('ignore_incoming_xhtml'): app.gajim_optional_features[a].append(nbxmpp.NS_XHTML_IM) if app.config.get_per('accounts', a, 'answer_receipts'): app.gajim_optional_features[a].append(nbxmpp.NS_RECEIPTS) app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE) if app.is_installed('FARSTREAM'): app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP) app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP_AUDIO) app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP_VIDEO) app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_ICE_UDP) app.gajim_optional_features[a].append( nbxmpp.NS_JINGLE_FILE_TRANSFER_5) app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_XTLS) app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_BYTESTREAM) app.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_IBB) # Give plugins the possibility to add their features app.plugin_manager.extension_point('update_caps', a) app.caps_hash[a] = caps_cache.compute_caps_hash([app.gajim_identity], app.gajim_common_features + app.gajim_optional_features[a]) # re-send presence with new hash connected = app.connections[a].connected if connected > 1 and app.SHOW_LIST[connected] != 'invisible': app.connections[a].change_status(app.SHOW_LIST[connected], app.connections[a].status) def jid_is_blocked(account, jid): con = app.connections[account] return (jid in con.get_module('Blocking').blocked or jid in con.get_module('PrivacyLists').blocked_contacts or con.get_module('PrivacyLists').blocked_all) def group_is_blocked(account, group): con = app.connections[account] return (group in con.get_module('PrivacyLists').blocked_groups or con.get_module('PrivacyLists').blocked_all) def get_subscription_request_msg(account=None): s = app.config.get_per('accounts', account, 'subscription_request_msg') if s: return s s = _('I would like to add you to my contact list.') if account: s = _('Hello, I am $name.') + ' ' + s name = app.connections[account].get_module('VCardTemp').get_vard_name() nick = app.nicks[account] if name and nick: name += ' (%s)' % nick elif nick: name = nick s = Template(s).safe_substitute({'name': name}) return s def replace_dataform_media(form, stanza): found = False for field in form.getTags('field'): for media in field.getTags('media'): for uri in media.getTags('uri'): uri_data = uri.getData() if uri_data.startswith('cid:'): uri_data = uri_data[4:] for data in stanza.getTags('data', namespace=nbxmpp.NS_BOB): if data.getAttr('cid') == uri_data: uri.setData(data.getData()) found = True return found def get_proxy_info(account): p = app.config.get_per('accounts', account, 'proxy') if not p: if app.config.get_per('accounts', account, 'use_env_http_proxy'): try: try: env_http_proxy = os.environ['HTTP_PROXY'] except Exception: env_http_proxy = os.environ['http_proxy'] env_http_proxy = env_http_proxy.strip('"') # Dispose of the http:// prefix env_http_proxy = env_http_proxy.split('://')[-1] env_http_proxy = env_http_proxy.split('@') if len(env_http_proxy) == 2: login = env_http_proxy[0].split(':') addr = env_http_proxy[1].split(':') else: login = ['', ''] addr = env_http_proxy[0].split(':') proxy = {'host': addr[0], 'type' : 'http', 'user':login[0]} if len(addr) == 2: proxy['port'] = addr[1] else: proxy['port'] = 3128 if len(login) == 2: proxy['pass'] = login[1] proxy['useauth'] = True else: proxy['pass'] = '' return proxy except Exception: proxy = None p = app.config.get('global_proxy') if p and p in app.config.get_per('proxies'): proxy = {} proxyptr = app.config.get_per('proxies', p) if not proxyptr: return proxy for key in proxyptr.keys(): proxy[key] = proxyptr[key] return proxy def _get_img_direct(attrs): """ Download an image. This function should be launched in a separated thread. """ mem = b'' alt = '' max_size = 2*1024*1024 if 'max_size' in attrs: max_size = attrs['max_size'] # Wait maximum 10s for connection socket.setdefaulttimeout(10) try: req = urllib.request.Request(attrs['src']) req.add_header('User-Agent', 'Gajim ' + app.version) f = urllib.request.urlopen(req) except Exception as ex: log.debug('Error loading image %s ', attrs['src'] + str(ex)) alt = attrs.get('alt', 'Broken image') else: # Wait 2s between each byte try: f.fp._sock.fp._sock.settimeout(2) except Exception: pass # On a slow internet connection with ~1000kbps you need ~10 seconds for 1 MB deadline = time.time() + (10 * (max_size / 1048576)) while True: if time.time() > deadline: log.debug('Timeout loading image %s ', attrs['src']) mem = '' alt = attrs.get('alt', '') if alt: alt += '\n' alt += _('Timeout loading image') break try: temp = f.read(100) except socket.timeout as ex: log.debug('Timeout loading image %s ', attrs['src'] + str(ex)) alt = attrs.get('alt', '') if alt: alt += '\n' alt += _('Timeout loading image') break if temp: mem += temp else: break if len(mem) > max_size: alt = attrs.get('alt', '') if alt: alt += '\n' alt += _('Image is too big') break f.close() return (mem, alt) def _get_img_proxy(attrs, proxy): """ Download an image through a proxy. This function should be launched in a separated thread. """ if not app.is_installed('PYCURL'): return '', _('PyCURL is not installed') alt, max_size = '', 2*1024*1024 if 'max_size' in attrs: max_size = attrs['max_size'] try: b = StringIO() c = pycurl.Curl() c.setopt(pycurl.URL, attrs['src'].encode('utf-8')) c.setopt(pycurl.FOLLOWLOCATION, 1) # Wait maximum 10s for connection c.setopt(pycurl.CONNECTTIMEOUT, 10) # On a slow internet connection with ~1000kbps you need ~10 seconds for 1 MB c.setopt(pycurl.TIMEOUT, 10 * (max_size / 1048576)) c.setopt(pycurl.MAXFILESIZE, max_size) c.setopt(pycurl.WRITEFUNCTION, b.write) c.setopt(pycurl.USERAGENT, 'Gajim ' + app.version) # set proxy c.setopt(pycurl.PROXY, proxy['host'].encode('utf-8')) c.setopt(pycurl.PROXYPORT, proxy['port']) if proxy['useauth']: c.setopt(pycurl.PROXYUSERPWD, proxy['user'].encode('utf-8')\ + ':' + proxy['pass'].encode('utf-8')) c.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY) if proxy['type'] == 'http': c.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_HTTP) elif proxy['type'] == 'socks5': c.setopt(pycurl.PROXYTYPE, pycurl.PROXYTYPE_SOCKS5) c.close() t = b.getvalue() return (t, attrs.get('alt', '')) except pycurl.error as ex: alt = attrs.get('alt', '') if alt: alt += '\n' if ex.errno == pycurl.E_FILESIZE_EXCEEDED: alt += _('Image is too big') elif ex.errno == pycurl.E_OPERATION_TIMEOUTED: alt += _('Timeout loading image') else: alt += _('Error loading image') except Exception as ex: log.debug('Error loading image %s ', attrs['src'] + str(ex)) alt = attrs.get('alt', 'Broken image') return ('', alt) def download_image(account, attrs): proxy = get_proxy_info(account) if proxy and proxy['type'] in ('http', 'socks5'): return _get_img_proxy(attrs, proxy) return _get_img_direct(attrs) def version_condition(current_version, required_version): if V(current_version) < V(required_version): return False return True def get_available_emoticon_themes(): emoticons_themes = ['font'] files = [] dir_iterator = os.scandir(configpaths.get('EMOTICONS')) for folder in dir_iterator: if not folder.is_dir(): continue file_iterator = os.scandir(folder.path) for theme in file_iterator: if theme.is_file(): files.append(theme.name) if os.path.isdir(configpaths.get('MY_EMOTS')): files += os.listdir(configpaths.get('MY_EMOTS')) for file in files: if file.endswith('.png'): emoticons_themes.append(file[:-4]) emoticons_themes.sort() return emoticons_themes def call_counter(func): def helper(self, restart=False): if restart: self._connect_machine_calls = 0 self._connect_machine_calls += 1 return func(self, restart=False) return helper def get_sync_threshold(jid, archive_info): cache = caps_cache.muc_caps_cache if archive_info is None or archive_info.sync_threshold is None: if cache.supports(jid, 'muc#roomconfig_membersonly'): threshold = app.config.get('private_room_sync_threshold') else: threshold = app.config.get('public_room_sync_threshold') app.logger.set_archive_infos(jid, sync_threshold=threshold) return threshold return archive_info.sync_threshold def load_json(path, key=None, default=None): try: with open(path, 'r') as file: json_dict = json.loads(file.read()) except Exception: log.exception('Parsing error') return default if key is None: return json_dict return json_dict.get(key, default) class AdditionalDataDict(collections.UserDict): def __init__(self, initialdata=None): collections.UserDict.__init__(self, initialdata) @staticmethod def _get_path_childs(full_path): path_childs = [full_path] if ':' in full_path: path_childs = full_path.split(':') return path_childs def set_value(self, full_path, key, value): path_childs = self._get_path_childs(full_path) _dict = self.data for path in path_childs: try: _dict = _dict[path] except KeyError: _dict[path] = {} _dict = _dict[path] _dict[key] = value def get_value(self, full_path, key, default=None): path_childs = self._get_path_childs(full_path) _dict = self.data for path in path_childs: try: _dict = _dict[path] except KeyError: return default try: return _dict[key] except KeyError: return default def remove_value(self, full_path, key): path_childs = self._get_path_childs(full_path) _dict = self.data for path in path_childs: try: _dict = _dict[path] except KeyError: return try: del _dict[key] except KeyError: return def save_roster_position(window): if not app.config.get('save-roster-position'): return if app.is_display(Display.WAYLAND): return x_pos, y_pos = window.get_position() log.debug('Save roster position: %s %s', x_pos, y_pos) app.config.set('roster_x-position', x_pos) app.config.set('roster_y-position', y_pos) gajim-gajim-1.1.3/gajim/common/i18n.py000066400000000000000000000123701345766322700174220ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2004 Vincent Hanquez # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2009 Benjamin Richter
# Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys import locale import gettext import unicodedata from pathlib import Path DOMAIN = 'gajim' LANG = 'en' direction_mark = '\u200E' _translation = gettext.NullTranslations() def get_locale_dirs(): if os.name == 'nt': return path = gettext.find(DOMAIN) if path is not None: # gettext can find the location itself # so we dont need the localedir return if Path('/app/share/run-as-flatpak').exists(): # Check if we run as flatpak return [Path('/app/share/')] data_dirs = os.getenv('XDG_DATA_DIRS') if data_dirs: return list(map(Path, data_dirs.split(':'))) return [Path('/usr/local/share/'), Path('/usr/share/')] def iter_locale_dirs(): locale_dirs = get_locale_dirs() if locale_dirs is None: yield None return # gettext fallback locale_dirs.append(Path(sys.base_prefix) / 'share') found_paths = [] for path in locale_dirs: locale_dir = path / 'locale' if locale_dir in found_paths: continue found_paths.append(locale_dir) if locale_dir.is_dir(): yield str(locale_dir) def get_default_lang(): if os.name == "nt": import ctypes windll = ctypes.windll.kernel32 lang = locale.windows_locale[windll.GetUserDefaultUILanguage()] return lang[:2] if sys.platform == "darwin": from AppKit import NSLocale return NSLocale.currentLocale().languageCode() default = locale.getdefaultlocale()[0] if default is not None: return default[:2] return 'en' def initialize_direction_mark(): from gi.repository import Gtk global direction_mark if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: direction_mark = '\u200F' def paragraph_direction_mark(text): """ Determine paragraph writing direction according to http://www.unicode.org/reports/tr9/#The_Paragraph_Level Returns either Unicode LTR mark or RTL mark. """ for char in text: bidi = unicodedata.bidirectional(char) if bidi == 'L': return '\u200E' if bidi in ('AL', 'R'): return '\u200F' return '\u200E' def Q_(text): """ Translate the given text, optionally qualified with a special construction, which will help translators to disambiguate between same terms, but in different contexts. When translated text is returned - this rudimentary construction will be stripped off, if it's present. Here is the construction to use: Q_("?vcard:Unknown") Everything between ? and : - is the qualifier to convey the context to the translators. Everything after : - is the text itself. """ text = _(text) if text.startswith('?'): text = text.split(':', 1)[1] return text def ngettext(s_sing, s_plural, n, replace_sing=None, replace_plural=None): """ Use as: i18n.ngettext( 'leave room %s', 'leave rooms %s', len(rooms), 'a', 'a, b, c') In other words this is a hack to ngettext() to support %s %d etc.. """ text = _translation.ngettext(s_sing, s_plural, n) if n == 1 and replace_sing is not None: text = text % replace_sing elif n > 1 and replace_plural is not None: text = text % replace_plural return text try: locale.setlocale(locale.LC_ALL, '') except locale.Error as error: print(error, file=sys.stderr) try: LANG = get_default_lang() if os.name == 'nt': # Set the env var on Windows because gettext.find() uses it to # find the translation # Use LANGUAGE instead of LANG, LANG sets LC_ALL and thus # doesn't retain other region settings like LC_TIME os.environ['LANGUAGE'] = LANG except Exception as error: print('Failed to determine default language', file=sys.stderr) import traceback traceback.print_exc() # Search for the translation in all locale dirs for dir_ in iter_locale_dirs(): try: _translation = gettext.translation(DOMAIN, dir_) _ = _translation.gettext if hasattr(locale, 'bindtextdomain'): locale.bindtextdomain(DOMAIN, dir_) # type: ignore except OSError: continue else: break else: print('No translations found', file=sys.stderr) print('Dirs searched: %s' % get_locale_dirs(), file=sys.stderr) _ = _translation.gettext gajim-gajim-1.1.3/gajim/common/idle.py000066400000000000000000000213071345766322700175600ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2007 Jean-Marie Traissard # Copyright (C) 2008 Mateusz Biliński # Copyright (C) 2008 Thorsten P. 'dGhvcnN0ZW5wIEFUIHltYWlsIGNvbQ==\n'.decode("base64") # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import sys import time import ctypes import ctypes.util import logging from gi.repository import Gio from gi.repository import GLib from gajim.common.const import IdleState log = logging.getLogger('gajim.c.idle') class DBusGnomeIdleMonitor: def __init__(self): self.last_idle_time = 0 log.debug('Connecting to D-Bus') self.dbus_gnome_proxy = Gio.DBusProxy.new_for_bus_sync( Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, 'org.gnome.Mutter.IdleMonitor', '/org/gnome/Mutter/IdleMonitor/Core', 'org.gnome.Mutter.IdleMonitor', None ) log.debug('D-Bus connected') # Only the following call will trigger exceptions if the D-Bus # interface/method/... does not exist. Using the failing method # for class init to allow other idle monitors to be used on failure. self._get_idle_sec_fail() log.debug('D-Bus call test successful') def _get_idle_sec_fail(self): (idle_time,) = self.dbus_gnome_proxy.call_sync( 'GetIdletime', None, Gio.DBusCallFlags.NO_AUTO_START, -1, None ) return int(idle_time / 1000) def get_idle_sec(self): try: self.last_idle_time = self._get_idle_sec_fail() except GLib.Error as error: log.warning( 'org.gnome.Mutter.IdleMonitor.GetIdletime() failed: %s', error) return self.last_idle_time def is_extended_away(self): return False class XssIdleMonitor: def __init__(self): class XScreenSaverInfo(ctypes.Structure): _fields_ = [ ('window', ctypes.c_ulong), ('state', ctypes.c_int), ('kind', ctypes.c_int), ('til_or_since', ctypes.c_ulong), ('idle', ctypes.c_ulong), ('eventMask', ctypes.c_ulong) ] XScreenSaverInfo_p = ctypes.POINTER(XScreenSaverInfo) display_p = ctypes.c_void_p xid = ctypes.c_ulong c_int_p = ctypes.POINTER(ctypes.c_int) libX11path = ctypes.util.find_library('X11') if libX11path is None: raise OSError('libX11 could not be found.') libX11 = ctypes.cdll.LoadLibrary(libX11path) libX11.XOpenDisplay.restype = display_p libX11.XOpenDisplay.argtypes = (ctypes.c_char_p,) libX11.XDefaultRootWindow.restype = xid libX11.XDefaultRootWindow.argtypes = (display_p,) libXsspath = ctypes.util.find_library('Xss') if libXsspath is None: raise OSError('libXss could not be found.') self.libXss = ctypes.cdll.LoadLibrary(libXsspath) self.libXss.XScreenSaverQueryExtension.argtypes = display_p, c_int_p, c_int_p self.libXss.XScreenSaverAllocInfo.restype = XScreenSaverInfo_p self.libXss.XScreenSaverQueryInfo.argtypes = ( display_p, xid, XScreenSaverInfo_p) self.dpy_p = libX11.XOpenDisplay(None) if self.dpy_p is None: raise OSError('Could not open X Display.') _event_basep = ctypes.c_int() _error_basep = ctypes.c_int() extension = self.libXss.XScreenSaverQueryExtension( self.dpy_p, ctypes.byref(_event_basep), ctypes.byref(_error_basep)) if extension == 0: raise OSError('XScreenSaver Extension not available on display.') self.xss_info_p = self.libXss.XScreenSaverAllocInfo() if self.xss_info_p is None: raise OSError('XScreenSaverAllocInfo: Out of Memory.') self.rootwindow = libX11.XDefaultRootWindow(self.dpy_p) def get_idle_sec(self): info = self.libXss.XScreenSaverQueryInfo( self.dpy_p, self.rootwindow, self.xss_info_p) if info == 0: return info return int(self.xss_info_p.contents.idle / 1000) def is_extended_away(self): return False class WindowsIdleMonitor: def __init__(self): self.OpenInputDesktop = ctypes.windll.user32.OpenInputDesktop self.CloseDesktop = ctypes.windll.user32.CloseDesktop self.SystemParametersInfo = ctypes.windll.user32.SystemParametersInfoW self.GetTickCount = ctypes.windll.kernel32.GetTickCount self.GetLastInputInfo = ctypes.windll.user32.GetLastInputInfo self._locked_time = None class LASTINPUTINFO(ctypes.Structure): _fields_ = [('cbSize', ctypes.c_uint), ('dwTime', ctypes.c_uint)] self.lastInputInfo = LASTINPUTINFO() self.lastInputInfo.cbSize = ctypes.sizeof(self.lastInputInfo) def get_idle_sec(self): self.GetLastInputInfo(ctypes.byref(self.lastInputInfo)) return float(self.GetTickCount() - self.lastInputInfo.dwTime) / 1000 def is_extended_away(self): # Check if Screen Saver is running # 0x72 is SPI_GETSCREENSAVERRUNNING saver_runing = ctypes.c_int(0) info = self.SystemParametersInfo( 0x72, 0, ctypes.byref(saver_runing), 0) if info and saver_runing.value: return True # Check if Screen is locked # Also a UAC prompt counts as locked # So just return True if we are more than 10 seconds locked desk = self.OpenInputDesktop(0, False, 0) unlocked = bool(desk) self.CloseDesktop(desk) if unlocked: self._locked_time = None return False if self._locked_time is None: self._locked_time = time.time() return False threshold = time.time() - 10 if threshold > self._locked_time: return True class IdleMonitor: def __init__(self): self.set_interval() self._state = IdleState.AWAKE self._idle_monitor = self._get_idle_monitor() def set_interval(self, away_interval=60, xa_interval=120): log.info('Set interval: away: %s, xa: %s', away_interval, xa_interval) self._away_interval = away_interval self._xa_interval = xa_interval def is_available(self): return self._idle_monitor is not None @property def state(self): if not self.is_available(): return IdleState.UNKNOWN return self._state def is_xa(self): return self.state == IdleState.XA def is_away(self): return self.state == IdleState.AWAY def is_awake(self): return self.state == IdleState.AWAKE def is_unknown(self): return self.state == IdleState.UNKNOWN def _get_idle_monitor(self): if sys.platform == 'win32': return WindowsIdleMonitor() try: return DBusGnomeIdleMonitor() except GLib.Error as error: log.info('Idle time via D-Bus not available: %s', error) try: return XssIdleMonitor() except OSError as error: log.info('Idle time via XScreenSaverInfo ' 'not available: %s', error) def get_idle_sec(self): return self._idle_monitor.get_idle_sec() def poll(self): """ Check to see if we should change state """ if not self.is_available(): return False if self._idle_monitor.is_extended_away(): log.info('Extended Away: Screensaver or Locked Screen') self._state = IdleState.XA return True idle_time = self.get_idle_sec() # xa is stronger than away so check for xa first if idle_time > self._xa_interval: self._state = IdleState.XA elif idle_time > self._away_interval: self._state = IdleState.AWAY else: self._state = IdleState.AWAKE return True Monitor = IdleMonitor() gajim-gajim-1.1.3/gajim/common/jingle.py000066400000000000000000000216631345766322700201200ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Handles the jingle signalling protocol """ #TODO: # * things in XEP 0176, including: # - http://xmpp.org/extensions/xep-0176.html#protocol-restarts # - http://xmpp.org/extensions/xep-0176.html#fallback # * XEP 0177 (raw udp) # * UI: # - make state and codec informations available to the user # - video integration # * config: # - codecs import logging import nbxmpp from gajim.common import helpers from gajim.common import app from gajim.common.jingle_session import JingleSession, JingleStates from gajim.common.jingle_ft import JingleFileTransfer from gajim.common.jingle_transport import JingleTransportSocks5, JingleTransportIBB if app.is_installed('FARSTREAM'): from gajim.common.jingle_rtp import JingleAudio, JingleVideo logger = logging.getLogger('gajim.c.jingle') class ConnectionJingle: """ This object depends on that it is a part of Connection class. """ def __init__(self): # dictionary: sessionid => JingleSession object self._sessions = {} # dictionary: (jid, iq stanza id) => JingleSession object, # one time callbacks self.__iq_responses = {} self.files = [] def delete_jingle_session(self, sid): """ Remove a jingle session from a jingle stanza dispatcher """ if sid in self._sessions: #FIXME: Move this elsewhere? for content in list(self._sessions[sid].contents.values()): content.destroy() self._sessions[sid].callbacks = [] del self._sessions[sid] def _JingleCB(self, con, stanza): """ The jingle stanza dispatcher Route jingle stanza to proper JingleSession object, or create one if it is a new session. TODO: Also check if the stanza isn't an error stanza, if so route it adequately. """ # get data try: jid = helpers.get_full_jid_from_iq(stanza) except helpers.InvalidFormat: logger.warning('Invalid JID: %s, ignoring it', stanza.getFrom()) return id_ = stanza.getID() if (jid, id_) in self.__iq_responses.keys(): self.__iq_responses[(jid, id_)].on_stanza(stanza) del self.__iq_responses[(jid, id_)] raise nbxmpp.NodeProcessed jingle = stanza.getTag('jingle') # a jingle element is not necessary in iq-result stanza # don't check for that if jingle: sid = jingle.getAttr('sid') else: sid = None for sesn in self._sessions.values(): if id_ in sesn.iq_ids: sesn.on_stanza(stanza) return # do we need to create a new jingle object if sid not in self._sessions: #TODO: tie-breaking and other things... newjingle = JingleSession(con=self, weinitiate=False, jid=jid, iq_id=id_, sid=sid) self._sessions[sid] = newjingle # we already have such session in dispatcher... self._sessions[sid].collect_iq_id(id_) self._sessions[sid].on_stanza(stanza) # Delete invalid/unneeded sessions if sid in self._sessions and \ self._sessions[sid].state == JingleStates.ENDED: self.delete_jingle_session(sid) raise nbxmpp.NodeProcessed def start_audio(self, jid): if self.get_jingle_session(jid, media='audio'): return self.get_jingle_session(jid, media='audio').sid jingle = self.get_jingle_session(jid, media='video') if jingle: jingle.add_content('voice', JingleAudio(jingle)) else: jingle = JingleSession(self, weinitiate=True, jid=jid) self._sessions[jingle.sid] = jingle jingle.add_content('voice', JingleAudio(jingle)) jingle.start_session() return jingle.sid def start_video(self, jid, in_xid, out_xid): if self.get_jingle_session(jid, media='video'): return self.get_jingle_session(jid, media='video').sid jingle = self.get_jingle_session(jid, media='audio') if jingle: jingle.add_content('video', JingleVideo(jingle, in_xid=in_xid, out_xid=out_xid)) else: jingle = JingleSession(self, weinitiate=True, jid=jid) self._sessions[jingle.sid] = jingle jingle.add_content('video', JingleVideo(jingle, in_xid=in_xid, out_xid=out_xid)) jingle.start_session() return jingle.sid def start_file_transfer(self, jid, file_props, request=False): logger.info("start file transfer with file: %s", file_props) contact = app.contacts.get_contact_with_highest_priority(self.name, app.get_jid_without_resource(jid)) if app.contacts.is_gc_contact(self.name, jid): gcc = jid.split('/') if len(gcc) == 2: contact = app.contacts.get_gc_contact(self.name, gcc[0], gcc[1]) if contact is None: return use_security = contact.supports(nbxmpp.NS_JINGLE_XTLS) jingle = JingleSession(self, weinitiate=True, jid=jid, werequest=request) # this is a file transfer jingle.session_type_ft = True self._sessions[jingle.sid] = jingle file_props.sid = jingle.sid if contact.supports(nbxmpp.NS_JINGLE_BYTESTREAM): transport = JingleTransportSocks5() elif contact.supports(nbxmpp.NS_JINGLE_IBB): transport = JingleTransportIBB() senders = 'initiator' if request: senders = 'responder' c = JingleFileTransfer(jingle, transport=transport, file_props=file_props, use_security=use_security, senders=senders) file_props.transport_sid = transport.sid file_props.algo = self.__hash_support(contact) jingle.add_content('file' + helpers.get_random_string_16(), c) jingle.start_session() return c.transport.sid def __hash_support(self, contact): if contact.supports(nbxmpp.NS_HASHES_2): if contact.supports(nbxmpp.NS_HASHES_BLAKE2B_512): return 'blake2b-512' if contact.supports(nbxmpp.NS_HASHES_BLAKE2B_256): return 'blake2b-256' if contact.supports(nbxmpp.NS_HASHES_SHA3_512): return 'sha3-512' if contact.supports(nbxmpp.NS_HASHES_SHA3_256): return 'sha3-256' if contact.supports(nbxmpp.NS_HASHES_SHA512): return 'sha-512' if contact.supports(nbxmpp.NS_HASHES_SHA256): return 'sha-256' return None def iter_jingle_sessions(self, jid, sid=None, media=None): if sid: return (session for session in self._sessions.values() if \ session.sid == sid) sessions = (session for session in self._sessions.values() if \ session.peerjid == jid) if media: if media not in ('audio', 'video', 'file'): return tuple() return (session for session in sessions if session.get_content(media)) return sessions def set_file_info(self, file_): # Saves information about the files we have transferred in case they need # to be requested again. self.files.append(file_) def get_file_info(self, peerjid, hash_=None, name=None, account=None): if hash_: for f in self.files: # DEBUG #if f['hash'] == '1294809248109223': if f['hash'] == hash_ and f['peerjid'] == peerjid: return f elif name: for f in self.files: if f['name'] == name and f['peerjid'] == peerjid: return f def get_jingle_session(self, jid, sid=None, media=None): if sid: if sid in self._sessions: return self._sessions[sid] return None if media: if media not in ('audio', 'video', 'file'): return None for session in self._sessions.values(): if session.peerjid == jid and session.get_content(media): return session return None gajim-gajim-1.1.3/gajim/common/jingle_content.py000066400000000000000000000223741345766322700216520ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Handles Jingle contents (XEP 0166) """ from typing import Any # pylint: disable=unused-import from typing import Dict # pylint: disable=unused-import import os import nbxmpp from gajim.common import app from gajim.common import configpaths from gajim.common.jingle_xtls import SELF_SIGNED_CERTIFICATE from gajim.common.jingle_xtls import load_cert_file contents = {} # type: Dict[str, Any] def get_jingle_content(node): namespace = node.getNamespace() if namespace in contents: return contents[namespace](node) class JingleContentSetupException(Exception): """ Exception that should be raised when a content fails to setup. """ class JingleContent: """ An abstraction of content in Jingle sessions """ def __init__(self, session, transport, senders): self.session = session self.transport = transport # will be filled by JingleSession.add_content() # don't uncomment these lines, we will catch more buggy code then # (a JingleContent not added to session shouldn't send anything) self.creator = None self.name = None self.accepted = False self.sent = False self.negotiated = False self.media = None self.senders = senders if self.senders is None: self.senders = 'both' self.allow_sending = True # Used for stream direction, attribute 'senders' # These were found by the Politie self.file_props = None self.use_security = None self.callbacks = { # these are called when *we* get stanzas 'content-accept': [self.__on_transport_info, self.__on_content_accept], 'content-add': [self.__on_transport_info], 'content-modify': [], 'content-reject': [], 'content-remove': [], 'description-info': [], 'security-info': [], 'session-accept': [self.__on_transport_info, self.__on_content_accept], 'session-info': [], 'session-initiate': [self.__on_transport_info], 'session-terminate': [], 'transport-info': [self.__on_transport_info], 'transport-replace': [self.__on_transport_replace], 'transport-accept': [], 'transport-reject': [], 'iq-result': [], 'iq-error': [], # these are called when *we* sent these stanzas 'content-accept-sent': [self.__fill_jingle_stanza, self.__on_content_accept], 'content-add-sent': [self.__fill_jingle_stanza], 'session-initiate-sent': [self.__fill_jingle_stanza], 'session-accept-sent': [self.__fill_jingle_stanza, self.__on_content_accept], 'session-terminate-sent': [], } def is_ready(self): return self.accepted and not self.sent def __on_content_accept(self, stanza, content, error, action): self.on_negotiated() def on_negotiated(self): if self.accepted: self.negotiated = True self.session.content_negotiated(self.media) def add_remote_candidates(self, candidates): """ Add a list of candidates to the list of remote candidates """ self.transport.remote_candidates = candidates def on_stanza(self, stanza, content, error, action): """ Called when something related to our content was sent by peer """ if action in self.callbacks: for callback in self.callbacks[action]: callback(stanza, content, error, action) def __on_transport_replace(self, stanza, content, error, action): content.addChild(node=self.transport.make_transport()) def __on_transport_info(self, stanza, content, error, action): """ Got a new transport candidate """ candidates = self.transport.parse_transport_stanza( content.getTag('transport')) if candidates: self.add_remote_candidates(candidates) def __content(self, payload=None): """ Build a XML content-wrapper for our data """ if payload is None: payload = [] return nbxmpp.Node('content', attrs={'name': self.name, 'creator': self.creator, 'senders': self.senders}, payload=payload) def send_candidate(self, candidate): """ Send a transport candidate for a previously defined transport. """ content = self.__content() content.addChild(node=self.transport.make_transport([candidate])) self.session.send_transport_info(content) def send_error_candidate(self): """ Sends a candidate-error when we can't connect to a candidate. """ content = self.__content() tp = self.transport.make_transport(add_candidates=False) tp.addChild(name='candidate-error') content.addChild(node=tp) self.session.send_transport_info(content) def send_description_info(self): content = self.__content() self._fill_content(content) self.session.send_description_info(content) def __fill_jingle_stanza(self, stanza, content, error, action): """ Add our things to session-initiate stanza """ self._fill_content(content) self.sent = True content.addChild(node=self.transport.make_transport()) def _fill_content(self, content): description_node = nbxmpp.simplexml.Node( tag=nbxmpp.NS_JINGLE_FILE_TRANSFER_5 + ' description') file_tag = description_node.setTag('file') if self.file_props.name: node = nbxmpp.simplexml.Node(tag='name') node.addData(self.file_props.name) file_tag.addChild(node=node) if self.file_props.date: node = nbxmpp.simplexml.Node(tag='date') node.addData(self.file_props.date) file_tag.addChild(node=node) if self.file_props.size: node = nbxmpp.simplexml.Node(tag='size') node.addData(self.file_props.size) file_tag.addChild(node=node) if self.file_props.type_ == 'r': if self.file_props.hash_: file_tag.addChild('hash', attrs={'algo': self.file_props.algo}, namespace=nbxmpp.NS_HASHES_2, payload=self.file_props.hash_) else: # if the file is less than 10 mb, then it is small # lets calculate it right away if self.file_props.size < 10000000 and not self.file_props.hash_: hash_data = self._compute_hash() if hash_data: file_tag.addChild(node=hash_data) pjid = app.get_jid_without_resource(self.session.peerjid) file_info = {'name' : self.file_props.name, 'file-name' : self.file_props.file_name, 'hash' : self.file_props.hash_, 'size' : self.file_props.size, 'date' : self.file_props.date, 'peerjid' : pjid } self.session.connection.set_file_info(file_info) desc = file_tag.setTag('desc') if self.file_props.desc: desc.setData(self.file_props.desc) if self.use_security: security = nbxmpp.simplexml.Node( tag=nbxmpp.NS_JINGLE_XTLS + ' security') certpath = os.path.join( configpaths.get('MY_CERT'), SELF_SIGNED_CERTIFICATE) + '.cert' cert = load_cert_file(certpath) if cert: try: digest_algo = (cert.get_signature_algorithm() .decode('utf-8').split('With')[0]) except AttributeError: # Old py-OpenSSL is missing get_signature_algorithm digest_algo = "sha256" security.addChild('fingerprint').addData(cert.digest( digest_algo).decode('utf-8')) for m in ('x509', ): # supported authentication methods method = nbxmpp.simplexml.Node(tag='method') method.setAttr('name', m) security.addChild(node=method) content.addChild(node=security) content.addChild(node=description_node) def destroy(self): self.callbacks = None del self.session.contents[(self.creator, self.name)] gajim-gajim-1.1.3/gajim/common/jingle_ft.py000066400000000000000000000422411345766322700206040ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Handles Jingle File Transfer (XEP 0234) """ import hashlib import logging import os import threading from enum import IntEnum, unique import nbxmpp from gajim.common import app from gajim.common import configpaths from gajim.common import jingle_xtls from gajim.common.jingle_content import contents, JingleContent from gajim.common.jingle_transport import JingleTransportSocks5, TransportType from gajim.common import helpers from gajim.common.connection_handlers_events import FileRequestReceivedEvent from gajim.common.jingle_ftstates import ( StateInitialized, StateCandSent, StateCandReceived, StateTransfering, StateCandSentAndRecv, StateTransportReplace) log = logging.getLogger('gajim.c.jingle_ft') @unique class State(IntEnum): NOT_STARTED = 0 INITIALIZED = 1 # We send the candidates and we are waiting for a reply CAND_SENT = 2 # We received the candidates and we are waiting to reply CAND_RECEIVED = 3 # We have sent and received the candidates # This also includes any candidate-error received or sent CAND_SENT_AND_RECEIVED = 4 TRANSPORT_REPLACE = 5 # We are transfering the file TRANSFERING = 6 class JingleFileTransfer(JingleContent): def __init__(self, session, transport=None, file_props=None, use_security=False, senders=None): JingleContent.__init__(self, session, transport, senders) log.info("transport value: %s", transport) # events we might be interested in self.callbacks['session-initiate'] += [self.__on_session_initiate] self.callbacks['session-initiate-sent'] += [ self.__on_session_initiate_sent] self.callbacks['content-add'] += [self.__on_session_initiate] self.callbacks['session-accept'] += [self.__on_session_accept] self.callbacks['session-terminate'] += [self.__on_session_terminate] self.callbacks['session-info'] += [self.__on_session_info] self.callbacks['transport-accept'] += [self.__on_transport_accept] self.callbacks['transport-replace'] += [self.__on_transport_replace] self.callbacks['session-accept-sent'] += [self.__transport_setup] # fallback transport method self.callbacks['transport-reject'] += [self.__on_transport_reject] self.callbacks['transport-info'] += [self.__on_transport_info] self.callbacks['iq-result'] += [self.__on_iq_result] self.use_security = use_security self.x509_fingerprint = None self.file_props = file_props self.weinitiate = self.session.weinitiate self.werequest = self.session.werequest if self.file_props is not None: if self.session.werequest: self.file_props.sender = self.session.peerjid self.file_props.receiver = self.session.ourjid else: self.file_props.sender = self.session.ourjid self.file_props.receiver = self.session.peerjid self.file_props.session_type = 'jingle' self.file_props.sid = session.sid self.file_props.transfered_size = [] self.file_props.transport_sid = self.transport.sid log.info("FT request: %s", file_props) if transport is None: self.transport = JingleTransportSocks5() self.transport.set_connection(session.connection) self.transport.set_file_props(self.file_props) self.transport.set_our_jid(session.ourjid) log.info('ourjid: %s', session.ourjid) self.session = session self.media = 'file' self.nominated_cand = {} if app.contacts.is_gc_contact(session.connection.name, session.peerjid): roomjid = session.peerjid.split('/')[0] dstaddr = hashlib.sha1(('%s%s%s' % (self.file_props.sid, session.ourjid, roomjid)) .encode('utf-8')).hexdigest() self.file_props.dstaddr = dstaddr self.state = State.NOT_STARTED self.states = { State.INITIALIZED : StateInitialized(self), State.CAND_SENT : StateCandSent(self), State.CAND_RECEIVED : StateCandReceived(self), State.TRANSFERING : StateTransfering(self), State.TRANSPORT_REPLACE : StateTransportReplace(self), State.CAND_SENT_AND_RECEIVED : StateCandSentAndRecv(self) } if jingle_xtls.PYOPENSSL_PRESENT: cert_name = os.path.join(configpaths.get('MY_CERT'), jingle_xtls.SELF_SIGNED_CERTIFICATE) if not (os.path.exists(cert_name + '.cert') and os.path.exists(cert_name + '.pkey')): jingle_xtls.make_certs(cert_name, 'gajim') def __state_changed(self, nextstate, args=None): # Executes the next state action and sets the next state current_state = self.state st = self.states[nextstate] st.action(args) # state can have been changed during the action. Don't go back. if self.state == current_state: self.state = nextstate def __on_session_initiate(self, stanza, content, error, action): log.debug("Jingle FT request received") app.nec.push_incoming_event(FileRequestReceivedEvent(None, conn=self.session.connection, stanza=stanza, jingle_content=content, FT_content=self)) if self.session.request: # accept the request self.session.approve_content(self.media, self.name) self.session.accept_session() def __on_session_initiate_sent(self, stanza, content, error, action): pass def __send_hash(self): # Send hash in a session info checksum = nbxmpp.Node(tag='checksum', payload=[nbxmpp.Node(tag='file', payload=[self._compute_hash()])]) checksum.setNamespace(nbxmpp.NS_JINGLE_FILE_TRANSFER_5) self.session.__session_info(checksum) pjid = app.get_jid_without_resource(self.session.peerjid) file_info = {'name' : self.file_props.name, 'file-name' : self.file_props.file_name, 'hash' : self.file_props.hash_, 'size' : self.file_props.size, 'date' : self.file_props.date, 'peerjid' : pjid } self.session.connection.set_file_info(file_info) def _compute_hash(self): # Caculates the hash and returns a xep-300 hash stanza if self.file_props.algo is None: return try: file_ = open(self.file_props.file_name, 'rb') except IOError: # can't open file return h = nbxmpp.Hashes2() hash_ = h.calculateHash(self.file_props.algo, file_) file_.close() # DEBUG #hash_ = '1294809248109223' if not hash_: # Hash alogrithm not supported return self.file_props.hash_ = hash_ h.addHash(hash_, self.file_props.algo) return h def on_cert_received(self): self.session.approve_session() self.session.approve_content('file', name=self.name) def __on_session_accept(self, stanza, content, error, action): log.info("__on_session_accept") con = self.session.connection security = content.getTag('security') if not security: # responder can not verify our fingerprint self.use_security = False else: fingerprint = security.getTag('fingerprint') if fingerprint: fingerprint = fingerprint.getData() self.x509_fingerprint = fingerprint if not jingle_xtls.check_cert(app.get_jid_without_resource( self.session.responder), fingerprint): id_ = jingle_xtls.send_cert_request(con, self.session.responder) jingle_xtls.key_exchange_pend(id_, self.continue_session_accept, [stanza]) raise nbxmpp.NodeProcessed self.continue_session_accept(stanza) def continue_session_accept(self, stanza): if self.state == State.TRANSPORT_REPLACE: # If we are requesting we don't have the file if self.session.werequest: raise nbxmpp.NodeProcessed # We send the file self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed self.file_props.streamhosts = self.transport.remote_candidates # Calculate file hash in a new thread # if we haven't sent the hash already. if self.file_props.hash_ is None and self.file_props.algo and \ not self.werequest: self.hash_thread = threading.Thread(target=self.__send_hash) self.hash_thread.start() for host in self.file_props.streamhosts: host['initiator'] = self.session.initiator host['target'] = self.session.responder host['sid'] = self.file_props.sid fingerprint = None if self.use_security: fingerprint = 'client' if self.transport.type_ == TransportType.SOCKS5: sid = self.file_props.transport_sid app.socks5queue.connect_to_hosts(self.session.connection.name, sid, self.on_connect, self._on_connect_error, fingerprint=fingerprint, receiving=False) raise nbxmpp.NodeProcessed self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed def __on_session_terminate(self, stanza, content, error, action): log.info("__on_session_terminate") def __on_session_info(self, stanza, content, error, action): pass def __on_transport_accept(self, stanza, content, error, action): log.info("__on_transport_accept") def __on_transport_replace(self, stanza, content, error, action): log.info("__on_transport_replace") def __on_transport_reject(self, stanza, content, error, action): log.info("__on_transport_reject") def __on_transport_info(self, stanza, content, error, action): log.info("__on_transport_info") cand_error = content.getTag('transport').getTag('candidate-error') cand_used = content.getTag('transport').getTag('candidate-used') if (cand_error or cand_used) and \ self.state >= State.CAND_SENT_AND_RECEIVED: raise nbxmpp.NodeProcessed if cand_error: if not app.socks5queue.listener.connections: app.socks5queue.listener.disconnect() self.nominated_cand['peer-cand'] = False if self.state == State.CAND_SENT: if not self.nominated_cand['our-cand'] and \ not self.nominated_cand['peer-cand']: if not self.weinitiate: return self.__state_changed(State.TRANSPORT_REPLACE) else: response = stanza.buildReply('result') response.delChild(response.getQuery()) self.session.connection.connection.send(response) self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed else: args = {'candError' : True} self.__state_changed(State.CAND_RECEIVED, args) return if cand_used: streamhost_cid = cand_used.getAttr('cid') streamhost_used = None for cand in self.transport.candidates: if cand['candidate_id'] == streamhost_cid: streamhost_used = cand break if streamhost_used is None or streamhost_used['type'] == 'proxy': if app.socks5queue.listener and \ not app.socks5queue.listener.connections: app.socks5queue.listener.disconnect() if content.getTag('transport').getTag('activated'): self.state = State.TRANSFERING app.socks5queue.send_file(self.file_props, self.session.connection.name, 'client') return args = {'content': content, 'sendCand': False} if self.state == State.CAND_SENT: self.__state_changed(State.CAND_SENT_AND_RECEIVED, args) self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed else: self.__state_changed(State.CAND_RECEIVED, args) def __on_iq_result(self, stanza, content, error, action): log.info("__on_iq_result") if self.state == State.NOT_STARTED: self.__state_changed(State.INITIALIZED) elif self.state == State.CAND_SENT_AND_RECEIVED: if not self.nominated_cand['our-cand'] and \ not self.nominated_cand['peer-cand']: if not self.weinitiate: return self.__state_changed(State.TRANSPORT_REPLACE) return # initiate transfer self.__state_changed(State.TRANSFERING) def __transport_setup(self, stanza=None, content=None, error=None, action=None): # Sets up a few transport specific things for the file transfer if self.transport.type_ == TransportType.IBB: # No action required, just set the state to transfering self.state = State.TRANSFERING else: self._listen_host() def on_connect(self, streamhost): """ send candidate-used stanza """ log.info('send_candidate_used') if streamhost is None: return args = {'streamhost' : streamhost, 'sendCand' : True} self.nominated_cand['our-cand'] = streamhost self.__send_candidate(args) def _on_connect_error(self, sid): log.info('connect error, sid=%s', sid) args = {'candError' : True, 'sendCand' : True} self.__send_candidate(args) def __send_candidate(self, args): if self.state == State.CAND_RECEIVED: self.__state_changed(State.CAND_SENT_AND_RECEIVED, args) else: self.__state_changed(State.CAND_SENT, args) def _store_socks5_sid(self, sid, hash_id): # callback from socsk5queue.start_listener self.file_props.hash_ = hash_id def _listen_host(self): receiver = self.file_props.receiver sender = self.file_props.sender sha_str = helpers.get_auth_sha(self.file_props.sid, sender, receiver) self.file_props.sha_str = sha_str port = app.config.get('file_transfers_port') fingerprint = None if self.use_security: fingerprint = 'server' listener = app.socks5queue.start_listener(port, sha_str, self._store_socks5_sid, self.file_props, fingerprint=fingerprint, typ='sender' if self.weinitiate else 'receiver') if not listener: # send error message, notify the user return def is_our_candidate_used(self): ''' If this method returns true then the candidate we nominated will be used, if false, the candidate nominated by peer will be used ''' if not self.nominated_cand['peer-cand']: return True if not self.nominated_cand['our-cand']: return False peer_pr = int(self.nominated_cand['peer-cand']['priority']) our_pr = int(self.nominated_cand['our-cand']['priority']) if peer_pr != our_pr: return our_pr > peer_pr return self.weinitiate def start_ibb_transfer(self): if self.file_props.type_ == 's': self.__state_changed(State.TRANSFERING) def get_content(desc): return JingleFileTransfer contents[nbxmpp.NS_JINGLE_FILE_TRANSFER_5] = get_content gajim-gajim-1.1.3/gajim/common/jingle_ftstates.py000066400000000000000000000212051345766322700220250ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import nbxmpp from gajim.common import app from gajim.common.jingle_transport import TransportType from gajim.common.socks5 import Socks5ReceiverClient, Socks5SenderClient import logging log = logging.getLogger('gajim.c.jingle_ftstates') class JingleFileTransferStates: ''' This class implements the state machine design pattern ''' def __init__(self, jingleft): self.jft = jingleft def action(self, args=None): ''' This method MUST be overriden by a subclass ''' raise NotImplementedError('This is an abstract method!') class StateInitialized(JingleFileTransferStates): ''' This state initializes the file transfer ''' def action(self, args=None): if self.jft.weinitiate: # update connection's fileprops self.jft._listen_host() # Listen on configured port for file transfer else: fingerprint = None if self.jft.use_security: fingerprint = 'client' # Connect to the candidate host, on success call on_connect method app.socks5queue.connect_to_hosts(self.jft.session.connection.name, self.jft.file_props.transport_sid, self.jft.on_connect, self.jft._on_connect_error, fingerprint=fingerprint) class StateCandSent(JingleFileTransferStates): ''' This state sends our nominated candidate ''' def _send_candidate(self, args): if 'candError' in args: self.jft.nominated_cand['our-cand'] = False self.jft.send_error_candidate() return # Send candidate used streamhost = args['streamhost'] self.jft.nominated_cand['our-cand'] = streamhost content = nbxmpp.Node('content') content.setAttr('creator', 'initiator') content.setAttr('name', self.jft.name) transport = nbxmpp.Node('transport') transport.setNamespace(nbxmpp.NS_JINGLE_BYTESTREAM) transport.setAttr('sid', self.jft.transport.sid) candidateused = nbxmpp.Node('candidate-used') candidateused.setAttr('cid', streamhost['candidate_id']) transport.addChild(node=candidateused) content.addChild(node=transport) self.jft.session.send_transport_info(content) def action(self, args=None): self._send_candidate(args) class StateCandReceived(JingleFileTransferStates): ''' This state happens when we receive a candidate. It takes the arguments: canError if we receive a candidate-error ''' def _recv_candidate(self, args): if 'candError' in args: return content = args['content'] streamhost_cid = content.getTag('transport').getTag('candidate-used').\ getAttr('cid') streamhost_used = None for cand in self.jft.transport.candidates: if cand['candidate_id'] == streamhost_cid: streamhost_used = cand break if streamhost_used is None: log.info("unknow streamhost") return # We save the candidate nominated by peer self.jft.nominated_cand['peer-cand'] = streamhost_used def action(self, args=None): self._recv_candidate(args) class StateCandSentAndRecv(StateCandSent, StateCandReceived): ''' This state happens when we have received and sent the candidates. It takes the boolean argument: sendCand in order to decide whether we should execute the action of when we receive or send a candidate. ''' def action(self, args=None): if args['sendCand']: self._send_candidate(args) else: self._recv_candidate(args) class StateTransportReplace(JingleFileTransferStates): ''' This state initiates transport replace ''' def action(self, args=None): self.jft.session.transport_replace() class StateTransfering(JingleFileTransferStates): ''' This state will start the transfer depeding on the type of transport we have. ''' def _start_ibb_transfer(self, con): self.jft.file_props.transport_sid = self.jft.transport.sid fp = open(self.jft.file_props.file_name, 'rb') con.OpenStream(self.jft.file_props.sid, self.jft.session.peerjid, fp, blocksize=4096) def _start_sock5_transfer(self): # It tells wether we start the transfer as client or server mode = None if self.jft.is_our_candidate_used(): mode = 'client' streamhost_used = self.jft.nominated_cand['our-cand'] app.socks5queue.remove_server(self.jft.file_props.transport_sid) else: mode = 'server' streamhost_used = self.jft.nominated_cand['peer-cand'] app.socks5queue.remove_client(self.jft.file_props.transport_sid) app.socks5queue.remove_other_servers(streamhost_used['host']) if streamhost_used['type'] == 'proxy': self.jft.file_props.is_a_proxy = True if self.jft.file_props.type_ == 's' and self.jft.weinitiate: self.jft.file_props.proxy_sender = streamhost_used['initiator'] self.jft.file_props.proxy_receiver = streamhost_used['target'] else: self.jft.file_props.proxy_sender = streamhost_used['target'] self.jft.file_props.proxy_receiver = streamhost_used[ 'initiator'] if self.jft.file_props.type_ == 's': s = app.socks5queue.senders for sender in s: if s[sender].host == streamhost_used['host'] and \ s[sender].connected: return elif self.jft.file_props.type_ == 'r': r = app.socks5queue.readers for reader in r: if r[reader].host == streamhost_used['host'] and \ r[reader].connected: return else: raise TypeError self.jft.file_props.streamhost_used = True streamhost_used['sid'] = self.jft.file_props.transport_sid self.jft.file_props.streamhosts = [] self.jft.file_props.streamhosts.append(streamhost_used) self.jft.file_props.proxyhosts = [] self.jft.file_props.proxyhosts.append(streamhost_used) if self.jft.file_props.type_ == 's': app.socks5queue.idx += 1 idx = app.socks5queue.idx sockobj = Socks5SenderClient(app.idlequeue, idx, app.socks5queue, _sock=None, host=str(streamhost_used['host']), port=int(streamhost_used['port']), fingerprint=None, connected=False, file_props=self.jft.file_props) else: sockobj = Socks5ReceiverClient(app.idlequeue, streamhost_used, transport_sid=self.jft.file_props.transport_sid, file_props=self.jft.file_props, fingerprint=None) sockobj.proxy = True sockobj.streamhost = streamhost_used app.socks5queue.add_sockobj(self.jft.session.connection.name, sockobj) streamhost_used['idx'] = sockobj.queue_idx # If we offered the nominated candidate used, we activate # the proxy if not self.jft.is_our_candidate_used(): app.socks5queue.on_success[self.jft.file_props.transport_sid]\ = self.jft.transport._on_proxy_auth_ok # TODO: add on failure else: app.socks5queue.send_file(self.jft.file_props, self.jft.session.connection.name, mode) def action(self, args=None): if self.jft.transport.type_ == TransportType.IBB: self._start_ibb_transfer(self.jft.session.connection) elif self.jft.transport.type_ == TransportType.SOCKS5: self._start_sock5_transfer() gajim-gajim-1.1.3/gajim/common/jingle_rtp.py000066400000000000000000000474651345766322700210150ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Handles Jingle RTP sessions (XEP 0167) """ import logging import socket import nbxmpp import gi from gi.repository import Farstream gi.require_version('Gst', '1.0') from gi.repository import Gst from gi.repository import GLib from gajim.common import app from gajim.common.i18n import _ from gajim.common.jingle_transport import JingleTransportICEUDP from gajim.common.jingle_content import contents, JingleContent, JingleContentSetupException from gajim.common.connection_handlers_events import InformationEvent from gajim.common.jingle_session import FailedApplication from collections import deque log = logging.getLogger('gajim.c.jingle_rtp') class JingleRTPContent(JingleContent): def __init__(self, session, media, transport=None): if transport is None: transport = JingleTransportICEUDP(None) JingleContent.__init__(self, session, transport, None) self.media = media self._dtmf_running = False self.farstream_media = { 'audio': Farstream.MediaType.AUDIO, 'video': Farstream.MediaType.VIDEO}[media] self.pipeline = None self.src_bin = None self.stream_failed_once = False self.candidates_ready = False # True when local candidates are prepared # TODO self.conference = None self.funnel = None self.p2psession = None self.p2pstream = None self.callbacks['session-initiate'] += [self.__on_remote_codecs] self.callbacks['content-add'] += [self.__on_remote_codecs] self.callbacks['description-info'] += [self.__on_remote_codecs] self.callbacks['content-accept'] += [self.__on_remote_codecs] self.callbacks['session-accept'] += [self.__on_remote_codecs] self.callbacks['session-terminate'] += [self.__stop] self.callbacks['session-terminate-sent'] += [self.__stop] def setup_stream(self, on_src_pad_added): # pipeline and bus self.pipeline = Gst.Pipeline() bus = self.pipeline.get_bus() bus.add_signal_watch() bus.connect('message', self._on_gst_message) # conference self.conference = Gst.ElementFactory.make('fsrtpconference', None) self.pipeline.add(self.conference) self.funnel = None self.p2psession = self.conference.new_session(self.farstream_media) participant = self.conference.new_participant() # FIXME: Consider a workaround, here... # pidgin and telepathy-gabble don't follow the XEP, and it won't work # due to bad controlling-mode params = {'controlling-mode': self.session.weinitiate, 'debug': False} if app.config.get('use_stun_server'): stun_server = app.config.get('stun_server') if not stun_server and self.session.connection._stun_servers: stun_server = self.session.connection._stun_servers[0]['host'] if stun_server: try: ip = socket.getaddrinfo(stun_server, 0, socket.AF_UNSPEC, socket.SOCK_STREAM)[0][4][0] except socket.gaierror as e: log.warning('Lookup of stun ip failed: %s', str(e)) else: params['stun-ip'] = ip self.p2pstream = self.p2psession.new_stream(participant, Farstream.StreamDirection.BOTH) self.p2pstream.connect('src-pad-added', on_src_pad_added) self.p2pstream.set_transmitter_ht('nice', params) def is_ready(self): return JingleContent.is_ready(self) and self.candidates_ready def make_bin_from_config(self, config_key, pipeline, text): pipeline = pipeline % app.config.get(config_key) try: gst_bin = Gst.parse_bin_from_description(pipeline, True) return gst_bin except GLib.GError as e: app.nec.push_incoming_event( InformationEvent( None, conn=self.session.connection, level='error', pri_txt=_('%s configuration error') % text.capitalize(), sec_txt=_('Couldn’t set up %(text)s. Check your ' 'configuration.\n\nPipeline was:\n%(pipeline)s\n\n' 'Error was:\n%(error)s') % {'text': text, 'pipeline': pipeline, 'error': str(e)})) raise JingleContentSetupException def add_remote_candidates(self, candidates): JingleContent.add_remote_candidates(self, candidates) # FIXME: connectivity should not be etablished yet # Instead, it should be etablished after session-accept! if self.sent: self.p2pstream.add_remote_candidates(candidates) def batch_dtmf(self, events): """ Send several DTMF tones """ if self._dtmf_running: raise Exception("There is a DTMF batch already running") events = deque(events) self._dtmf_running = True self._start_dtmf(events.popleft()) GLib.timeout_add(500, self._next_dtmf, events) def _next_dtmf(self, events): self._stop_dtmf() if events: self._start_dtmf(events.popleft()) GLib.timeout_add(500, self._next_dtmf, events) else: self._dtmf_running = False def _start_dtmf(self, event): if event in ('*', '#'): event = {'*': Farstream.DTMFEvent.STAR, '#': Farstream.DTMFEvent.POUND}[event] else: event = int(event) self.p2psession.start_telephony_event(event, 2) def _stop_dtmf(self): self.p2psession.stop_telephony_event() def _fill_content(self, content): content.addChild(nbxmpp.NS_JINGLE_RTP + ' description', attrs={'media': self.media}, payload=list(self.iter_codecs())) def _setup_funnel(self): self.funnel = Gst.ElementFactory.make('funnel', None) self.pipeline.add(self.funnel) self.funnel.link(self.sink) self.sink.set_state(Gst.State.PLAYING) self.funnel.set_state(Gst.State.PLAYING) def _on_src_pad_added(self, stream, pad, codec): if not self.funnel: self._setup_funnel() pad.link(self.funnel.get_request_pad('sink_%u')) def _on_gst_message(self, bus, message): if message.type == Gst.MessageType.ELEMENT: name = message.get_structure().get_name() log.debug('gst element message: %s: %s', name, message) if name == 'farstream-new-active-candidate-pair': pass elif name == 'farstream-recv-codecs-changed': pass elif name == 'farstream-codecs-changed': if self.sent and self.p2psession.props.codecs_without_config: self.send_description_info() if self.transport.remote_candidates: # those lines MUST be done after we get info on our # codecs self.p2pstream.add_remote_candidates( self.transport.remote_candidates) self.transport.remote_candidates = [] self.p2pstream.set_property('direction', Farstream.StreamDirection.BOTH) elif name == 'farstream-local-candidates-prepared': self.candidates_ready = True if self.is_ready(): self.session.on_session_state_changed(self) elif name == 'farstream-new-local-candidate': candidate = self.p2pstream.parse_new_local_candidate(message)[1] self.transport.candidates.append(candidate) if self.sent: # FIXME: Is this case even possible? self.send_candidate(candidate) elif name == 'farstream-component-state-changed': state = message.get_structure().get_value('state') if state == Farstream.StreamState.FAILED: reason = nbxmpp.Node('reason') reason.setTag('failed-transport') self.session.remove_content(self.creator, self.name, reason) elif name == 'farstream-error': log.error('Farstream error #%d!\nMessage: %s', message.get_structure().get_value('error-no'), message.get_structure().get_value('error-msg')) elif message.type == Gst.MessageType.ERROR: # TODO: Fix it to fallback to videotestsrc anytime an error occur, # or raise an error, Jingle way # or maybe one-sided stream? if not self.stream_failed_once: app.nec.push_incoming_event( InformationEvent( None, dialog_name='gstreamer-error', kwargs={'error': message.get_structure().get_value('gerror'), 'debug': message.get_structure().get_value('debug')})) sink_pad = self.p2psession.get_property('sink-pad') # Remove old source self.src_bin.get_static_pad('src').unlink(sink_pad) self.src_bin.set_state(Gst.State.NULL) self.pipeline.remove(self.src_bin) if not self.stream_failed_once: # Add fallback source self.src_bin = self.get_fallback_src() self.pipeline.add(self.src_bin) self.src_bin.get_static_pad('src').link(sink_pad) self.stream_failed_once = True else: reason = nbxmpp.Node('reason') reason.setTag('failed-application') self.session.remove_content(self.creator, self.name, reason) # Start playing again self.pipeline.set_state(Gst.State.PLAYING) @staticmethod def get_fallback_src(): return Gst.ElementFactory.make('fakesrc', None) def on_negotiated(self): if self.accepted: if self.p2psession.get_property('codecs'): # those lines MUST be done after we get info on our codecs if self.transport.remote_candidates: self.p2pstream.add_remote_candidates( self.transport.remote_candidates) self.transport.remote_candidates = [] # TODO: Farstream.StreamDirection.BOTH only if senders='both' # self.p2pstream.set_property('direction', # Farstream.StreamDirection.BOTH) JingleContent.on_negotiated(self) def __on_remote_codecs(self, stanza, content, error, action): """ Get peer codecs from what we get from peer """ codecs = [] for codec in content.getTag('description').iterTags('payload-type'): if not codec['id'] or not codec['name'] or not codec['clockrate']: # ignore invalid payload-types continue c = Farstream.Codec.new(int(codec['id']), codec['name'], self.farstream_media, int(codec['clockrate'])) if 'channels' in codec: c.channels = int(codec['channels']) else: c.channels = 1 for p in codec.iterTags('parameter'): c.add_optional_parameter(p['name'], str(p['value'])) codecs.append(c) if codecs: try: self.p2pstream.set_remote_codecs(codecs) except GLib.Error: raise FailedApplication def iter_codecs(self): codecs = self.p2psession.props.codecs_without_config for codec in codecs: attrs = { 'name': codec.encoding_name, 'id': codec.id, } if codec.channels > 0: attrs['channels'] = codec.channels if codec.clock_rate: attrs['clockrate'] = codec.clock_rate if codec.optional_params: payload = [nbxmpp.Node('parameter', {'name': p.name, 'value': p.value}) for p in codec.optional_params] else: payload = [] yield nbxmpp.Node('payload-type', attrs, payload) def __stop(self, *things): self.pipeline.set_state(Gst.State.NULL) def __del__(self): self.__stop() def destroy(self): JingleContent.destroy(self) self.p2pstream.disconnect_by_func(self._on_src_pad_added) self.pipeline.get_bus().disconnect_by_func(self._on_gst_message) class JingleAudio(JingleRTPContent): """ Jingle VoIP sessions consist of audio content transported over an ICE UDP protocol """ def __init__(self, session, transport=None): JingleRTPContent.__init__(self, session, 'audio', transport) self.setup_stream() def set_mic_volume(self, vol): """ vol must be between 0 ans 1 """ self.mic_volume.set_property('volume', vol) def set_out_volume(self, vol): """ vol must be between 0 ans 1 """ self.out_volume.set_property('volume', vol) def setup_stream(self): JingleRTPContent.setup_stream(self, self._on_src_pad_added) # list of codecs that are explicitly allowed allow_codecs = [ Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'OPUS', Farstream.MediaType.AUDIO, 48000), Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'SPEEX', Farstream.MediaType.AUDIO, 32000), Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'SPEEX', Farstream.MediaType.AUDIO, 16000), Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'G722', Farstream.MediaType.AUDIO, 8000), Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'SPEEX', Farstream.MediaType.AUDIO, 8000), Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'PCMA', Farstream.MediaType.AUDIO, 8000), Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'PCMU', Farstream.MediaType.AUDIO, 8000)] # disable all other codecs disable_codecs = [] codecs_without_config = self.p2psession.props.codecs_without_config allowed_encoding_names = [c.encoding_name for c in allow_codecs] + ['telephone-event'] for codec in codecs_without_config: if codec.encoding_name not in allowed_encoding_names: disable_codecs.append(Farstream.Codec.new(Farstream.CODEC_ID_DISABLE, codec.encoding_name, Farstream.MediaType.AUDIO, codec.clock_rate)) self.p2psession.set_codec_preferences(allow_codecs + disable_codecs) # the local parts # TODO: Add queues? self.src_bin = self.make_bin_from_config('audio_input_device', '%s ! audioconvert', _("audio input")) self.sink = self.make_bin_from_config('audio_output_device', 'audioconvert ! volume name=gajim_out_vol ! %s', _("audio output")) self.mic_volume = self.src_bin.get_by_name('gajim_vol') self.out_volume = self.sink.get_by_name('gajim_out_vol') # link gst elements self.pipeline.add(self.sink) self.pipeline.add(self.src_bin) self.src_bin.get_static_pad('src').link(self.p2psession.get_property( 'sink-pad')) # The following is needed for farstream to process ICE requests: self.pipeline.set_state(Gst.State.PLAYING) class JingleVideo(JingleRTPContent): def __init__(self, session, transport=None, in_xid=0, out_xid=0): JingleRTPContent.__init__(self, session, 'video', transport) self.in_xid = in_xid self.out_xid = out_xid self.out_xid_set = False self.setup_stream() def setup_stream(self): # TODO: Everything is not working properly: # sometimes, one window won't show up, # sometimes it'll freeze... JingleRTPContent.setup_stream(self, self._on_src_pad_added) bus = self.pipeline.get_bus() bus.enable_sync_message_emission() bus.connect('sync-message::element', self._on_sync_message) # the local parts if app.config.get('video_framerate'): framerate = 'videorate ! video/x-raw,framerate=%s ! ' % \ app.config.get('video_framerate') else: framerate = '' try: w, h = app.config.get('video_size').split('x') except Exception: w = h = None if w and h: video_size = 'video/x-raw,width=%s,height=%s ! ' % (w, h) else: video_size = '' if app.config.get('video_see_self'): tee = '! tee name=t ! queue ! videoscale ! ' + \ 'video/x-raw,width=160,height=120 ! videoconvert ! ' + \ '%s t. ! queue ' % app.config.get( 'video_output_device') else: tee = '' self.src_bin = self.make_bin_from_config('video_input_device', '%%s %s! %svideoscale ! %svideoconvert' % (tee, framerate, video_size), _("video input")) self.pipeline.add(self.src_bin) self.pipeline.set_state(Gst.State.PLAYING) self.sink = self.make_bin_from_config('video_output_device', 'videoscale ! videoconvert ! %s', _("video output")) self.pipeline.add(self.sink) self.src_bin.get_static_pad('src').link(self.p2psession.get_property( 'sink-pad')) # The following is needed for farstream to process ICE requests: self.pipeline.set_state(Gst.State.PLAYING) def _on_sync_message(self, bus, message): if message.get_structure() is None: return False if message.get_structure().get_name() == 'prepare-window-handle': message.src.set_property('force-aspect-ratio', True) imagesink = message.src if app.config.get('video_see_self') and not self.out_xid_set: imagesink.set_window_handle(self.out_xid) self.out_xid_set = True else: imagesink.set_window_handle(self.in_xid) def get_fallback_src(self): # TODO: Use avatar? pipeline = 'videotestsrc is-live=true ! video/x-raw,framerate=10/1 ! videoconvert' return Gst.parse_bin_from_description(pipeline, True) def destroy(self): JingleRTPContent.destroy(self) self.pipeline.get_bus().disconnect_by_func(self._on_sync_message) def get_content(desc): if desc['media'] == 'audio': return JingleAudio if desc['media'] == 'video': return JingleVideo contents[nbxmpp.NS_JINGLE_RTP] = get_content gajim-gajim-1.1.3/gajim/common/jingle_session.py000066400000000000000000001063161345766322700216620ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Handles Jingle sessions (XEP 0166) """ #TODO: # * 'senders' attribute of 'content' element # * security preconditions # * actions: # - content-modify # - session-info # - security-info # - transport-accept, transport-reject # - Tie-breaking # * timeout import logging from enum import Enum, unique import nbxmpp from gajim.common import app from gajim.common.jingle_transport import get_jingle_transport, JingleTransportIBB from gajim.common.jingle_content import get_jingle_content, JingleContentSetupException from gajim.common.jingle_ft import State from gajim.common.connection_handlers_events import ( FilesProp, JingleRequestReceivedEvent, JingleDisconnectedReceivedEvent, JingleTransferCancelledEvent, JingleConnectedReceivedEvent, JingleErrorReceivedEvent) log = logging.getLogger("app.c.jingle_session") # FIXME: Move it to JingleSession.States? @unique class JingleStates(Enum): """ States in which jingle session may exist """ ENDED = 0 PENDING = 1 ACTIVE = 2 class OutOfOrder(Exception): """ Exception that should be raised when an action is received when in the wrong state """ class TieBreak(Exception): """ Exception that should be raised in case of a tie, when we overrule the other action """ class FailedApplication(Exception): """ Exception that should be raised in case responder supports none of the payload-types offered by the initiator """ class JingleSession: """ This represents one jingle session, that is, one or more content types negotiated between an initiator and a responder. """ def __init__(self, con, weinitiate, jid, iq_id=None, sid=None, werequest=False): """ con -- connection object, weinitiate -- boolean, are we the initiator? jid - jid of the other entity """ self.contents = {} # negotiated contents self.connection = con # connection to use # our full jid self.ourjid = app.get_jid_from_account(self.connection.name) if con.server_resource: self.ourjid = self.ourjid + '/' + con.server_resource self.peerjid = jid # jid we connect to # jid we use as the initiator self.initiator = self.ourjid if weinitiate else self.peerjid # jid we use as the responder self.responder = self.peerjid if weinitiate else self.ourjid # are we an initiator? self.weinitiate = weinitiate # Are we requesting or offering a file? self.werequest = werequest self.request = False # what state is session in? (one from JingleStates) self.state = JingleStates.ENDED if not sid: sid = con.connection.getAnID() self.sid = sid # sessionid # iq stanza id, used to determine which sessions to summon callback # later on when iq-result stanza arrives if iq_id is not None: self.iq_ids = [iq_id] else: self.iq_ids = [] self.accepted = True # is this session accepted by user # Tells whether this session is a file transfer or not self.session_type_ft = False # callbacks to call on proper contents # use .prepend() to add new callbacks, especially when you're going # to send error instead of ack self.callbacks = { 'content-accept': [self.__ack, self.__on_content_accept, self.__broadcast], 'content-add': [self.__ack, self.__on_content_add, self.__broadcast ], #TODO 'content-modify': [self.__ack], #TODO 'content-reject': [self.__ack, self.__on_content_remove], 'content-remove': [self.__ack, self.__on_content_remove], 'description-info': [self.__ack, self.__broadcast], #TODO 'security-info': [self.__ack], #TODO 'session-accept': [self.__ack, self.__on_session_accept, self.__on_content_accept, self.__broadcast], 'session-info': [self.__ack, self.__broadcast, self.__on_session_info], 'session-initiate': [self.__ack, self.__on_session_initiate, self.__broadcast], 'session-terminate': [self.__ack, self.__on_session_terminate, self.__broadcast_all], 'transport-info': [self.__ack, self.__broadcast], 'transport-replace': [self.__ack, self.__broadcast, self.__on_transport_replace], #TODO 'transport-accept': [self.__ack], #TODO 'transport-reject': [self.__ack], #TODO 'iq-result': [self.__broadcast], 'iq-error': [self.__on_error], } def collect_iq_id(self, iq_id): if iq_id is not None: self.iq_ids.append(iq_id) def approve_session(self): """ Called when user accepts session in UI (when we aren't the initiator) """ self.accept_session() def decline_session(self): """ Called when user declines session in UI (when we aren't the initiator) """ reason = nbxmpp.Node('reason') reason.addChild('decline') self._session_terminate(reason) def cancel_session(self): """ Called when user declines session in UI (when we aren't the initiator) """ reason = nbxmpp.Node('reason') reason.addChild('cancel') self._session_terminate(reason) def approve_content(self, media, name=None): content = self.get_content(media, name) if content: content.accepted = True self.on_session_state_changed(content) def reject_content(self, media, name=None): content = self.get_content(media, name) if content: if self.state == JingleStates.ACTIVE: self.__content_reject(content) content.destroy() self.on_session_state_changed() def end_session(self): """ Called when user stops or cancel session in UI """ reason = nbxmpp.Node('reason') if self.state == JingleStates.ACTIVE: reason.addChild('success') else: reason.addChild('cancel') self._session_terminate(reason) def get_content(self, media=None, name=None): if media is None: return for content in self.contents.values(): if content.media == media: if name is None or content.name == name: return content def add_content(self, name, content, creator='we'): """ Add new content to session. If the session is active, this will send proper stanza to update session Creator must be one of ('we', 'peer', 'initiator', 'responder') """ assert creator in ('we', 'peer', 'initiator', 'responder') if (creator == 'we' and self.weinitiate) or (creator == 'peer' and \ not self.weinitiate): creator = 'initiator' elif (creator == 'peer' and self.weinitiate) or (creator == 'we' and \ not self.weinitiate): creator = 'responder' content.creator = creator content.name = name self.contents[(creator, name)] = content if (creator == 'initiator') == self.weinitiate: # The content is from us, accept it content.accepted = True def remove_content(self, creator, name, reason=None): """ Remove the content `name` created by `creator` by sending content-remove, or by sending session-terminate if there is no content left. """ if (creator, name) in self.contents: content = self.contents[(creator, name)] self.__content_remove(content, reason) self.contents[(creator, name)].destroy() if not self.contents: self.end_session() def modify_content(self, creator, name, transport=None): ''' Currently used for transport replacement ''' content = self.contents[(creator, name)] transport.set_sid(content.transport.sid) transport.set_file_props(content.transport.file_props) content.transport = transport # The content will have to be resend now that it is modified content.sent = False content.accepted = True def on_session_state_changed(self, content=None): if self.state == JingleStates.ENDED: # Session not yet started, only one action possible: session-initiate if self.is_ready() and self.weinitiate: self.__session_initiate() elif self.state == JingleStates.PENDING: # We can either send a session-accept or a content-add if self.is_ready() and not self.weinitiate: self.__session_accept() elif content and (content.creator == 'initiator') == self.weinitiate: self.__content_add(content) elif content and self.weinitiate: self.__content_accept(content) elif self.state == JingleStates.ACTIVE: # We can either send a content-add or a content-accept. However, if # we are sending a file we can only use session_initiate. if not content: return we_created_content = (content.creator == 'initiator') \ == self.weinitiate if we_created_content and content.media == 'file': self.__session_initiate() if we_created_content: # We initiated this content. It's a pending content-add. self.__content_add(content) else: # The other side created this content, we accept it. self.__content_accept(content) def is_ready(self): """ Return True when all codecs and candidates are ready (for all contents) """ return (any((content.is_ready() for content in self.contents.values())) and self.accepted) def accept_session(self): """ Mark the session as accepted """ self.accepted = True self.on_session_state_changed() def start_session(self): """ Mark the session as ready to be started """ self.accepted = True self.on_session_state_changed() def send_session_info(self): pass def send_content_accept(self, content): assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-accept') jingle.addChild(node=content) self.connection.connection.send(stanza) def send_transport_info(self, content): assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('transport-info') jingle.addChild(node=content) self.connection.connection.send(stanza) self.collect_iq_id(stanza.getID()) def send_description_info(self, content): assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('description-info') jingle.addChild(node=content) self.connection.connection.send(stanza) def on_stanza(self, stanza): """ A callback for ConnectionJingle. It gets stanza, then tries to send it to all internally registered callbacks. First one to raise nbxmpp.NodeProcessed breaks function """ jingle = stanza.getTag('jingle') error = stanza.getTag('error') if error: # it's an iq-error stanza action = 'iq-error' elif jingle: # it's a jingle action action = jingle.getAttr('action') if action not in self.callbacks: self.__send_error(stanza, 'bad-request') return # FIXME: If we aren't initiated and it's not a session-initiate... if action not in ['session-initiate', 'session-terminate'] \ and self.state == JingleStates.ENDED: self.__send_error(stanza, 'item-not-found', 'unknown-session') return else: # it's an iq-result (ack) stanza action = 'iq-result' callables = self.callbacks[action] try: for call in callables: call(stanza=stanza, jingle=jingle, error=error, action=action) except nbxmpp.NodeProcessed: pass except TieBreak: self.__send_error(stanza, 'conflict', 'tiebreak') except OutOfOrder: # FIXME self.__send_error(stanza, 'unexpected-request', 'out-of-order') except FailedApplication: reason = nbxmpp.Node('reason') reason.addChild('failed-application') self._session_terminate(reason) def __ack(self, stanza, jingle, error, action): """ Default callback for action stanzas -- simple ack and stop processing """ response = stanza.buildReply('result') response.delChild(response.getQuery()) self.connection.connection.send(response) def __on_error(self, stanza, jingle, error, action): # FIXME text = error.getTagData('text') error_name = None for child in error.getChildren(): if child.getNamespace() == nbxmpp.NS_JINGLE_ERRORS: error_name = child.getName() break elif child.getNamespace() == nbxmpp.NS_STANZAS: error_name = child.getName() self.__dispatch_error(error_name, text, error.getAttr('type')) def transport_replace(self): transport = JingleTransportIBB() # For debug only, delete this and replace for a function # that will identify contents by its sid for creator, name in self.contents: self.modify_content(creator, name, transport) cont = self.contents[(creator, name)] cont.transport = transport stanza, jingle = self.__make_jingle('transport-replace') self.__append_contents(jingle) self.__broadcast(stanza, jingle, None, 'transport-replace') self.connection.connection.send(stanza) self.state = JingleStates.PENDING def __on_transport_replace(self, stanza, jingle, error, action): for content in jingle.iterTags('content'): creator = content['creator'] name = content['name'] if (creator, name) in self.contents: transport_ns = content.getTag('transport').getNamespace() if transport_ns == nbxmpp.NS_JINGLE_ICE_UDP: # FIXME: We don't manage anything else than ICE-UDP now... # What was the previous transport?!? # Anyway, content's transport is not modifiable yet pass elif transport_ns == nbxmpp.NS_JINGLE_IBB: transport = JingleTransportIBB() self.modify_content(creator, name, transport) self.state = JingleStates.PENDING self.contents[(creator, name)].state = State.TRANSPORT_REPLACE self.__ack(stanza, jingle, error, action) self.__session_accept() else: stanza, jingle = self.__make_jingle('transport-reject') content = jingle.setTag('content', attrs={'creator': creator, 'name': name}) content.setTag('transport', namespace=transport_ns) self.connection.connection.send(stanza) raise nbxmpp.NodeProcessed else: # FIXME: This resource is unknown to us, what should we do? # For now, reject the transport stanza, jingle = self.__make_jingle('transport-reject') content = jingle.setTag('content', attrs={'creator': creator, 'name': name}) content.setTag('transport', namespace=transport_ns) self.connection.connection.send(stanza) raise nbxmpp.NodeProcessed def __on_session_info(self, stanza, jingle, error, action): # TODO: active, (un)hold, (un)mute payload = jingle.getPayload() if payload[0].getName() == 'ringing': # ignore ringing raise nbxmpp.NodeProcessed if self.state != JingleStates.ACTIVE: raise OutOfOrder for child in payload: if child.getName() == 'checksum': hash_ = child.getTag('file').getTag(name='hash', namespace=nbxmpp.NS_HASHES_2) if hash_ is None: continue algo = hash_.getAttr('algo') if algo in nbxmpp.Hashes2.supported: file_props = FilesProp.getFileProp(self.connection.name, self.sid) file_props.algo = algo file_props.hash_ = hash_.getData() raise nbxmpp.NodeProcessed self.__send_error(stanza, 'feature-not-implemented', 'unsupported-info', type_='modify') raise nbxmpp.NodeProcessed def __on_content_remove(self, stanza, jingle, error, action): for content in jingle.iterTags('content'): creator = content['creator'] name = content['name'] if (creator, name) in self.contents: content = self.contents[(creator, name)] # TODO: this will fail if content is not an RTP content app.nec.push_incoming_event(JingleDisconnectedReceivedEvent( None, conn=self.connection, jingle_session=self, media=content.media, reason='removed')) content.destroy() if not self.contents: reason = nbxmpp.Node('reason') reason.setTag('success') self._session_terminate(reason) def __on_session_accept(self, stanza, jingle, error, action): # FIXME if self.state != JingleStates.PENDING: raise OutOfOrder self.state = JingleStates.ACTIVE @staticmethod def __on_content_accept(stanza, jingle, error, action): """ Called when we get content-accept stanza or equivalent one (like session-accept) """ # check which contents are accepted # for content in jingle.iterTags('content'): # creator = content['creator'] # name = content['name'] return def __on_content_add(self, stanza, jingle, error, action): if self.state == JingleStates.ENDED: raise OutOfOrder parse_result = self.__parse_contents(jingle) contents = parse_result[0] # rejected_contents = parse_result[1] # for name, creator in rejected_contents: # content = JingleContent() # self.add_content(name, content, creator) # self.__content_reject(content) # self.contents[(content.creator, content.name)].destroy() app.nec.push_incoming_event(JingleRequestReceivedEvent(None, conn=self.connection, jingle_session=self, contents=contents)) def __on_session_initiate(self, stanza, jingle, error, action): """ We got a jingle session request from other entity, therefore we are the receiver... Unpack the data, inform the user """ if self.state != JingleStates.ENDED: raise OutOfOrder self.initiator = jingle['initiator'] self.responder = self.ourjid self.peerjid = self.initiator self.accepted = False # user did not accept this session yet # TODO: If the initiator is unknown to the receiver (e.g., via presence # subscription) and the receiver has a policy of not communicating via # Jingle with unknown entities, it SHOULD return a # error. # Lets check what kind of jingle session does the peer want contents, _contents_rejected, reason_txt = self.__parse_contents(jingle) # If there's no content we understand... if not contents: # TODO: http://xmpp.org/extensions/xep-0166.html#session-terminate reason = nbxmpp.Node('reason') reason.setTag(reason_txt) self.__ack(stanza, jingle, error, action) self._session_terminate(reason) raise nbxmpp.NodeProcessed # If we are not receiving a file # Check if there's already a session with this user: if contents[0].media != 'file': for session in self.connection.iter_jingle_sessions(self.peerjid): if session is not self: reason = nbxmpp.Node('reason') alternative_session = reason.setTag('alternative-session') alternative_session.setTagData('sid', session.sid) self.__ack(stanza, jingle, error, action) self._session_terminate(reason) raise nbxmpp.NodeProcessed else: # Stop if we don't have the requested file or the peer is not # allowed to request the file request = contents[0].senders == 'responder' if request: self.request = True hash_tag = request.getTag('file').getTag('hash') hash_data = hash_tag.getData() if hash_tag else None n = request.getTag('file').getTag('name') n = n.getData() if n else None pjid = app.get_jid_without_resource(self.peerjid) file_info = self.connection.get_file_info(pjid, hash_data, n, self.connection.name) if not file_info: log.warning('The peer %s is requesting a ' \ 'file that we dont have or ' \ 'it is not allowed to request', pjid) self.decline_session() raise nbxmpp.NodeProcessed self.state = JingleStates.PENDING # Send event about starting a session app.nec.push_incoming_event(JingleRequestReceivedEvent(None, conn=self.connection, jingle_session=self, contents=contents[0])) def __broadcast(self, stanza, jingle, error, action): """ Broadcast the stanza contents to proper content handlers """ #if jingle is None: # it is a iq-result stanza # for cn in self.contents.values(): # cn.on_stanza(stanza, None, error, action) # return # special case: iq-result stanza does not come with a jingle element if action == 'iq-result': for cn in self.contents.values(): cn.on_stanza(stanza, None, error, action) return for content in jingle.iterTags('content'): name = content['name'] creator = content['creator'] if (creator, name) not in self.contents: text = 'Content %s (created by %s) does not exist' % (name, creator) self.__send_error(stanza, 'bad-request', text=text, type_='_modify') raise nbxmpp.NodeProcessed else: cn = self.contents[(creator, name)] cn.on_stanza(stanza, content, error, action) def __on_session_terminate(self, stanza, jingle, error, action): self.connection.delete_jingle_session(self.sid) reason, text = self.__reason_from_stanza(jingle) if reason not in ('success', 'cancel', 'decline'): self.__dispatch_error(reason, text) if text: text = '%s (%s)' % (reason, text) else: # TODO text = reason if reason == 'cancel' and self.session_type_ft: app.nec.push_incoming_event(JingleTransferCancelledEvent(None, conn=self.connection, jingle_session=self, media=None, reason=text)) def __broadcast_all(self, stanza, jingle, error, action): """ Broadcast the stanza to all content handlers """ for content in self.contents.values(): content.on_stanza(stanza, None, error, action) def __parse_contents(self, jingle): # TODO: Needs some reworking contents = [] contents_rejected = [] reasons = set() for element in jingle.iterTags('content'): transport = get_jingle_transport(element.getTag('transport')) if transport: transport.ourjid = self.ourjid content_type = get_jingle_content(element.getTag('description')) if content_type: try: if transport: content = content_type(self, transport=transport) self.add_content(element['name'], content, 'peer') contents.append(content) else: reasons.add('unsupported-transports') contents_rejected.append((element['name'], 'peer')) except JingleContentSetupException: reasons.add('failed-application') else: contents_rejected.append((element['name'], 'peer')) reasons.add('unsupported-applications') failure_reason = None # Store the first reason of failure for reason in ('failed-application', 'unsupported-transports', 'unsupported-applications'): if reason in reasons: failure_reason = reason break return (contents, contents_rejected, failure_reason) def __dispatch_error(self, error=None, text=None, type_=None): if text: text = '%s (%s)' % (error, text) if type_ != 'modify': app.nec.push_incoming_event(JingleErrorReceivedEvent(None, conn=self.connection, jingle_session=self, reason=text or error)) @staticmethod def __reason_from_stanza(stanza): # TODO: Move to GUI? reason = 'success' reasons = [ 'success', 'busy', 'cancel', 'connectivity-error', 'decline', 'expired', 'failed-application', 'failed-transport', 'general-error', 'gone', 'incompatible-parameters', 'media-error', 'security-error', 'timeout', 'unsupported-applications', 'unsupported-transports' ] tag = stanza.getTag('reason') text = '' if tag: text = tag.getTagData('text') for r in reasons: if tag.getTag(r): reason = r break return (reason, text) def __make_jingle(self, action, reason=None): stanza = nbxmpp.Iq(typ='set', to=nbxmpp.JID(self.peerjid), frm=self.ourjid) attrs = { 'action': action, 'sid': self.sid, 'initiator' : self.initiator } jingle = stanza.addChild('jingle', attrs=attrs, namespace=nbxmpp.NS_JINGLE) if reason is not None: jingle.addChild(node=reason) return stanza, jingle def __send_error(self, stanza, error, jingle_error=None, text=None, type_=None): err_stanza = nbxmpp.Error(stanza, '%s %s' % (nbxmpp.NS_STANZAS, error)) err = err_stanza.getTag('error') if type_: err.setAttr('type', type_) if jingle_error: err.setTag(jingle_error, namespace=nbxmpp.NS_JINGLE_ERRORS) if text: err.setTagData('text', text) self.connection.connection.send(err_stanza) self.__dispatch_error(jingle_error or error, text, type_) @staticmethod def __append_content(jingle, content): """ Append element to element """ jingle.addChild('content', attrs={'name': content.name, 'creator': content.creator, 'senders': content.senders}) def __append_contents(self, jingle): """ Append all elements to """ # TODO: integrate with __appendContent? # TODO: parameters 'name', 'content'? for content in self.contents.values(): if content.is_ready(): self.__append_content(jingle, content) def __session_initiate(self): assert self.state == JingleStates.ENDED stanza, jingle = self.__make_jingle('session-initiate') self.__append_contents(jingle) self.__broadcast(stanza, jingle, None, 'session-initiate-sent') self.connection.connection.send(stanza) self.collect_iq_id(stanza.getID()) self.state = JingleStates.PENDING def __session_accept(self): assert self.state == JingleStates.PENDING stanza, jingle = self.__make_jingle('session-accept') self.__append_contents(jingle) self.__broadcast(stanza, jingle, None, 'session-accept-sent') self.connection.connection.send(stanza) self.collect_iq_id(stanza.getID()) self.state = JingleStates.ACTIVE def __session_info(self, payload=None): assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('session-info') if payload: jingle.addChild(node=payload) self.connection.connection.send(stanza) def _JingleFileTransfer__session_info(self, payload): # For some strange reason when I call # self.session.__session_info(payload) from the jingleFileTransfer object # within a thread, this method gets called instead. Even though, it # isn't being called explicitly. self.__session_info(payload) def _session_terminate(self, reason=None): stanza, jingle = self.__make_jingle('session-terminate', reason=reason) self.__broadcast_all(stanza, jingle, None, 'session-terminate-sent') if self.connection.connection and self.connection.connected >= 2: self.connection.connection.send(stanza) # TODO: Move to GUI? reason, text = self.__reason_from_stanza(jingle) if reason not in ('success', 'cancel', 'decline'): self.__dispatch_error(reason, text) if text: text = '%s (%s)' % (reason, text) else: text = reason self.connection.delete_jingle_session(self.sid) app.nec.push_incoming_event(JingleDisconnectedReceivedEvent(None, conn=self.connection, jingle_session=self, media=None, reason=text)) def __content_add(self, content): # TODO: test assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-add') self.__append_content(jingle, content) self.__broadcast(stanza, jingle, None, 'content-add-sent') id_ = self.connection.connection.send(stanza) self.collect_iq_id(id_) def __content_accept(self, content): # TODO: test assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-accept') self.__append_content(jingle, content) self.__broadcast(stanza, jingle, None, 'content-accept-sent') id_ = self.connection.connection.send(stanza) self.collect_iq_id(id_) def __content_reject(self, content): assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-reject') self.__append_content(jingle, content) self.connection.connection.send(stanza) # TODO: this will fail if content is not an RTP content app.nec.push_incoming_event(JingleDisconnectedReceivedEvent(None, conn=self.connection, jingle_session=self, media=content.media, reason='rejected')) def __content_modify(self): assert self.state != JingleStates.ENDED def __content_remove(self, content, reason=None): assert self.state != JingleStates.ENDED if self.connection.connection and self.connection.connected > 1: stanza, jingle = self.__make_jingle('content-remove', reason=reason) self.__append_content(jingle, content) self.connection.connection.send(stanza) # TODO: this will fail if content is not an RTP content app.nec.push_incoming_event(JingleDisconnectedReceivedEvent(None, conn=self.connection, jingle_session=self, media=content.media, reason='removed')) def content_negotiated(self, media): app.nec.push_incoming_event(JingleConnectedReceivedEvent(None, conn=self.connection, jingle_session=self, media=media)) gajim-gajim-1.1.3/gajim/common/jingle_transport.py000066400000000000000000000423041345766322700222270ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Handles Jingle Transports (currently only ICE-UDP) """ from typing import Any # pylint: disable=unused-import from typing import Dict # pylint: disable=unused-import import logging import socket from enum import IntEnum, unique import nbxmpp from gajim.common import app log = logging.getLogger('gajim.c.jingle_transport') transports = {} # type: Dict[str, Any] def get_jingle_transport(node): namespace = node.getNamespace() if namespace in transports: return transports[namespace](node) @unique class TransportType(IntEnum): """ Possible types of a JingleTransport """ ICEUDP = 1 SOCKS5 = 2 IBB = 3 class JingleTransport: """ An abstraction of a transport in Jingle sessions """ __slots__ = ['type_', 'candidates', 'remote_candidates', 'connection', 'file_props', 'ourjid', 'sid'] def __init__(self, type_): self.type_ = type_ self.candidates = [] self.remote_candidates = [] self.connection = None self.file_props = None self.ourjid = None self.sid = None def _iter_candidates(self): for candidate in self.candidates: yield self.make_candidate(candidate) def make_candidate(self, candidate): """ Build a candidate stanza for the given candidate """ pass def make_transport(self, candidates=None): """ Build a transport stanza with the given candidates (or self.candidates if candidates is None) """ if not candidates: candidates = list(self._iter_candidates()) else: candidates = (self.make_candidate(candidate) for candidate in candidates) transport = nbxmpp.Node('transport', payload=candidates) return transport def parse_transport_stanza(self, transport): """ Return the list of transport candidates from a transport stanza """ return [] def set_connection(self, conn): self.connection = conn if not self.sid: self.sid = self.connection.connection.getAnID() def set_file_props(self, file_props): self.file_props = file_props def set_our_jid(self, jid): self.ourjid = jid def set_sid(self, sid): self.sid = sid class JingleTransportSocks5(JingleTransport): """ Socks5 transport in jingle scenario Note: Don't forget to call set_file_props after initialization """ def __init__(self, node=None): JingleTransport.__init__(self, TransportType.SOCKS5) self.connection = None self.remote_candidates = [] self.sid = None if node and node.getAttr('sid'): self.sid = node.getAttr('sid') def make_candidate(self, candidate): log.info('candidate dict, %s', candidate) attrs = { 'cid': candidate['candidate_id'], 'host': candidate['host'], 'jid': candidate['jid'], 'port': candidate['port'], 'priority': candidate['priority'], 'type': candidate['type'] } return nbxmpp.Node('candidate', attrs=attrs) def make_transport(self, candidates=None, add_candidates=True): if add_candidates: self._add_local_ips_as_candidates() self._add_additional_candidates() self._add_proxy_candidates() transport = JingleTransport.make_transport(self, candidates) else: transport = nbxmpp.Node('transport') transport.setNamespace(nbxmpp.NS_JINGLE_BYTESTREAM) transport.setAttr('sid', self.sid) if self.file_props.dstaddr: transport.setAttr('dstaddr', self.file_props.dstaddr) return transport def parse_transport_stanza(self, transport): candidates = [] for candidate in transport.iterTags('candidate'): typ = 'direct' # default value if candidate.has_attr('type'): typ = candidate['type'] cand = { 'state': 0, 'target': self.ourjid, 'host': candidate['host'], 'port': int(candidate['port']), 'candidate_id': candidate['cid'], 'type': typ, 'priority': candidate['priority'] } candidates.append(cand) # we need this when we construct file_props on session-initiation if candidates: self.remote_candidates = candidates return candidates def _add_candidates(self, candidates): for cand in candidates: in_remote = False for cand2 in self.remote_candidates: if cand['host'] == cand2['host'] and \ cand['port'] == cand2['port']: in_remote = True break if not in_remote: self.candidates.append(cand) def _add_local_ips_as_candidates(self): if not app.config.get_per('accounts', self.connection.name, 'ft_send_local_ips'): return if not self.connection: return port = int(app.config.get('file_transfers_port')) #type preference of connection type. XEP-0260 section 2.2 type_preference = 126 priority = (2**16) * type_preference hosts = set() local_ip_cand = [] candidate = { 'host': self.connection.peerhost[0], 'candidate_id': self.connection.connection.getAnID(), 'port': port, 'type': 'direct', 'jid': self.ourjid, 'priority': priority } hosts.add(self.connection.peerhost[0]) local_ip_cand.append(candidate) try: for addrinfo in socket.getaddrinfo(socket.gethostname(), None): addr = addrinfo[4][0] if not addr in hosts and not addr.startswith('127.') and \ addr != '::1': candidate = { 'host': addr, 'candidate_id': self.connection.connection.getAnID(), 'port': port, 'type': 'direct', 'jid': self.ourjid, 'priority': priority, 'initiator': self.file_props.sender, 'target': self.file_props.receiver } hosts.add(addr) local_ip_cand.append(candidate) except socket.gaierror: pass # ignore address-related errors for getaddrinfo try: from netifaces import interfaces, ifaddresses, AF_INET, AF_INET6 for ifaceName in interfaces(): addresses = ifaddresses(ifaceName) if AF_INET in addresses: for address in addresses[AF_INET]: addr = address['addr'] if addr in hosts or addr.startswith('127.'): continue candidate = { 'host': addr, 'candidate_id': self.connection.connection.getAnID(), 'port': port, 'type': 'direct', 'jid': self.ourjid, 'priority': priority, 'initiator': self.file_props.sender, 'target': self.file_props.receiver } hosts.add(addr) local_ip_cand.append(candidate) if AF_INET6 in addresses: for address in addresses[AF_INET6]: addr = address['addr'] if addr in hosts or addr.startswith('::1') or \ addr.count(':') != 7: continue candidate = { 'host': addr, 'candidate_id': self.connection.connection.getAnID(), 'port': port, 'type': 'direct', 'jid': self.ourjid, 'priority': priority, 'initiator': self.file_props.sender, 'target': self.file_props.receiver } hosts.add(addr) local_ip_cand.append(candidate) except ImportError: pass self._add_candidates(local_ip_cand) def _add_additional_candidates(self): if not self.connection: return type_preference = 126 priority = (2**16) * type_preference additional_ip_cand = [] port = int(app.config.get('file_transfers_port')) ft_add_hosts = app.config.get('ft_add_hosts_to_send') if ft_add_hosts: hosts = [e.strip() for e in ft_add_hosts.split(',')] for host in hosts: candidate = { 'host': host, 'candidate_id': self.connection.connection.getAnID(), 'port': port, 'type': 'direct', 'jid': self.ourjid, 'priority': priority, 'initiator': self.file_props.sender, 'target': self.file_props.receiver } additional_ip_cand.append(candidate) self._add_candidates(additional_ip_cand) def _add_proxy_candidates(self): if not self.connection: return type_preference = 10 priority = (2**16) * type_preference proxy_cand = [] socks5conn = self.connection proxyhosts = socks5conn._get_file_transfer_proxies_from_config(self.file_props) if proxyhosts: self.file_props.proxyhosts = proxyhosts for proxyhost in proxyhosts: candidate = { 'host': proxyhost['host'], 'candidate_id': self.connection.connection.getAnID(), 'port': int(proxyhost['port']), 'type': 'proxy', 'jid': proxyhost['jid'], 'priority': priority, 'initiator': self.file_props.sender, 'target': self.file_props.receiver } proxy_cand.append(candidate) self._add_candidates(proxy_cand) def get_content(self): sesn = self.connection.get_jingle_session(self.ourjid, self.file_props.sid) for content in sesn.contents.values(): if content.transport == self: return content def _on_proxy_auth_ok(self, proxy): log.info('proxy auth ok for %s', str(proxy)) # send activate request to proxy, send activated confirmation to peer if not self.connection: return sesn = self.connection.get_jingle_session(self.ourjid, self.file_props.sid) if sesn is None: return iq = nbxmpp.Iq(to=proxy['jid'], frm=self.ourjid, typ='set') auth_id = "au_" + proxy['sid'] iq.setID(auth_id) query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM) query.setAttr('sid', proxy['sid']) activate = query.setTag('activate') activate.setData(sesn.peerjid) iq.setID(auth_id) self.connection.connection.send(iq) content = nbxmpp.Node('content') content.setAttr('creator', 'initiator') content_object = self.get_content() content.setAttr('name', content_object.name) transport = nbxmpp.Node('transport') transport.setNamespace(nbxmpp.NS_JINGLE_BYTESTREAM) transport.setAttr('sid', proxy['sid']) activated = nbxmpp.Node('activated') cid = None if 'cid' in proxy: cid = proxy['cid'] else: for host in self.candidates: if host['host'] == proxy['host'] and host['jid'] == proxy['jid'] \ and host['port'] == proxy['port']: cid = host['candidate_id'] break if cid is None: raise Exception('cid is missing') activated.setAttr('cid', cid) transport.addChild(node=activated) content.addChild(node=transport) sesn.send_transport_info(content) class JingleTransportIBB(JingleTransport): def __init__(self, node=None, block_sz=None): JingleTransport.__init__(self, TransportType.IBB) if block_sz: self.block_sz = block_sz else: self.block_sz = '4096' self.connection = None self.sid = None if node and node.getAttr('sid'): self.sid = node.getAttr('sid') def make_transport(self): transport = nbxmpp.Node('transport') transport.setNamespace(nbxmpp.NS_JINGLE_IBB) transport.setAttr('block-size', self.block_sz) transport.setAttr('sid', self.sid) return transport try: from gi.repository import Farstream except ImportError: pass class JingleTransportICEUDP(JingleTransport): def __init__(self, node): JingleTransport.__init__(self, TransportType.ICEUDP) def make_candidate(self, candidate): types = { Farstream.CandidateType.HOST: 'host', Farstream.CandidateType.SRFLX: 'srflx', Farstream.CandidateType.PRFLX: 'prflx', Farstream.CandidateType.RELAY: 'relay', Farstream.CandidateType.MULTICAST: 'multicast' } attrs = { 'component': candidate.component_id, 'foundation': '1', # hack 'generation': '0', 'ip': candidate.ip, 'network': '0', 'port': candidate.port, 'priority': int(candidate.priority), # hack 'id': app.get_an_id() } if candidate.type in types: attrs['type'] = types[candidate.type] if candidate.proto == Farstream.NetworkProtocol.UDP: attrs['protocol'] = 'udp' else: # we actually don't handle properly different tcp options in jingle attrs['protocol'] = 'tcp' return nbxmpp.Node('candidate', attrs=attrs) def make_transport(self, candidates=None): transport = JingleTransport.make_transport(self, candidates) transport.setNamespace(nbxmpp.NS_JINGLE_ICE_UDP) if self.candidates and self.candidates[0].username and \ self.candidates[0].password: transport.setAttr('ufrag', self.candidates[0].username) transport.setAttr('pwd', self.candidates[0].password) return transport def parse_transport_stanza(self, transport): candidates = [] for candidate in transport.iterTags('candidate'): foundation = str(candidate['foundation']) component_id = int(candidate['component']) ip = str(candidate['ip']) port = int(candidate['port']) base_ip = None base_port = 0 if candidate['protocol'] == 'udp': proto = Farstream.NetworkProtocol.UDP else: # we actually don't handle properly different tcp options in # jingle proto = Farstream.NetworkProtocol.TCP priority = int(candidate['priority']) types = { 'host': Farstream.CandidateType.HOST, 'srflx': Farstream.CandidateType.SRFLX, 'prflx': Farstream.CandidateType.PRFLX, 'relay': Farstream.CandidateType.RELAY, 'multicast': Farstream.CandidateType.MULTICAST } if 'type' in candidate and candidate['type'] in types: type_ = types[candidate['type']] else: log.warning('Unknown type %s', candidate['type']) type_ = Farstream.CandidateType.HOST username = str(transport['ufrag']) password = str(transport['pwd']) ttl = 0 cand = Farstream.Candidate.new_full(foundation, component_id, ip, port, base_ip, base_port, proto, priority, type_, username, password, ttl) candidates.append(cand) self.remote_candidates.extend(candidates) return candidates transports[nbxmpp.NS_JINGLE_ICE_UDP] = JingleTransportICEUDP transports[nbxmpp.NS_JINGLE_BYTESTREAM] = JingleTransportSocks5 transports[nbxmpp.NS_JINGLE_IBB] = JingleTransportIBB gajim-gajim-1.1.3/gajim/common/jingle_xtls.py000066400000000000000000000240371345766322700211700ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging import os import nbxmpp from gajim.common import app from gajim.common import configpaths log = logging.getLogger('gajim.c.jingle_xtls') PYOPENSSL_PRESENT = False # key-exchange id -> [callback, args], accept that session once key-exchange completes pending_contents = {} def key_exchange_pend(id_, cb, args): # args is a list pending_contents[id_] = [cb, args] def approve_pending_content(id_): cb = pending_contents[id_][0] args = pending_contents[id_][1] cb(*args) try: import OpenSSL.SSL PYOPENSSL_PRESENT = True except ImportError: log.info("PyOpenSSL not available") if PYOPENSSL_PRESENT: from OpenSSL import SSL, crypto TYPE_RSA = crypto.TYPE_RSA TYPE_DSA = crypto.TYPE_DSA SELF_SIGNED_CERTIFICATE = 'localcert' DH_PARAMS = 'dh_params.pem' DEFAULT_DH_PARAMS = 'dh4096.pem' def default_callback(connection, certificate, error_num, depth, return_code): log.info("certificate: %s", certificate) return return_code def load_cert_file(cert_path, cert_store=None): """ This is almost identical to the one in nbxmpp.tls_nb """ if not os.path.isfile(cert_path): return None try: f = open(cert_path) except IOError as e: log.warning('Unable to open certificate file %s: %s', cert_path, str(e)) return None lines = f.readlines() i = 0 begin = -1 for line in lines: if 'BEGIN CERTIFICATE' in line: begin = i elif 'END CERTIFICATE' in line and begin > -1: cert = ''.join(lines[begin:i+2]) try: x509cert = OpenSSL.crypto.load_certificate( OpenSSL.crypto.FILETYPE_PEM, cert) if cert_store: cert_store.add_cert(x509cert) f.close() return x509cert except OpenSSL.crypto.Error as exception_obj: log.warning('Unable to load a certificate from file %s: %s', cert_path, exception_obj.args[0][0][2]) except Exception: log.warning('Unknown error while loading certificate from file ' '%s', cert_path) begin = -1 i += 1 f.close() def get_context(fingerprint, verify_cb=None, remote_jid=None): """ constructs and returns the context objects """ ctx = SSL.Context(SSL.SSLv23_METHOD) flags = (SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3 | SSL.OP_SINGLE_DH_USE \ | SSL.OP_NO_TICKET) ctx.set_options(flags) ctx.set_cipher_list(b'HIGH:!aNULL:!3DES') if fingerprint == 'server': # for testing purposes only ctx.set_verify(SSL.VERIFY_NONE|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb or default_callback) elif fingerprint == 'client': ctx.set_verify(SSL.VERIFY_PEER, verify_cb or default_callback) cert_name = os.path.join(configpaths.get('MY_CERT'), SELF_SIGNED_CERTIFICATE) ctx.use_privatekey_file((cert_name + '.pkey').encode('utf-8')) ctx.use_certificate_file((cert_name + '.cert').encode('utf-8')) # Try to load Diffie-Hellman parameters. # First try user DH parameters, if this fails load the default DH parameters dh_params_name = os.path.join(configpaths.get('MY_CERT'), DH_PARAMS) try: with open(dh_params_name, "r"): ctx.load_tmp_dh(dh_params_name.encode('utf-8')) except FileNotFoundError as err: default_dh_params_name = os.path.join(configpaths.get('DATA'), 'other', DEFAULT_DH_PARAMS) try: with open(default_dh_params_name, "r"): ctx.load_tmp_dh(default_dh_params_name.encode('utf-8')) except FileNotFoundError as err: log.error('Unable to load default DH parameter file: %s, %s', default_dh_params_name, err) raise if remote_jid: store = ctx.get_cert_store() path = os.path.join(os.path.expanduser(configpaths.get('MY_PEER_CERTS')), remote_jid) + '.cert' if os.path.exists(path): load_cert_file(path, cert_store=store) log.debug('certificate file %s loaded fingerprint %s', path, fingerprint) return ctx def read_cert(certpath): certificate = '' with open(certpath, 'r') as certfile: for line in certfile.readlines(): if not line.startswith('-'): certificate += line return certificate def send_cert(con, jid_from, sid): certpath = os.path.join(configpaths.get('MY_CERT'), SELF_SIGNED_CERTIFICATE) + \ '.cert' certificate = read_cert(certpath) iq = nbxmpp.Iq('result', to=jid_from) iq.setAttr('id', sid) pubkey = iq.setTag('pubkeys') pubkey.setNamespace(nbxmpp.NS_PUBKEY_PUBKEY) keyinfo = pubkey.setTag('keyinfo') name = keyinfo.setTag('name') name.setData('CertificateHash') cert = keyinfo.setTag('x509cert') cert.setData(certificate) con.send(iq) def handle_new_cert(con, obj, jid_from): jid = app.get_jid_without_resource(jid_from) certpath = os.path.join(os.path.expanduser(configpaths.get('MY_PEER_CERTS')), jid) certpath += '.cert' id_ = obj.getAttr('id') x509cert = obj.getTag('pubkeys').getTag('keyinfo').getTag('x509cert') cert = x509cert.getData() f = open(certpath, 'w') f.write('-----BEGIN CERTIFICATE-----\n') f.write(cert) f.write('-----END CERTIFICATE-----\n') f.close() approve_pending_content(id_) def check_cert(jid, fingerprint): certpath = os.path.join(os.path.expanduser(configpaths.get('MY_PEER_CERTS')), jid) certpath += '.cert' if os.path.exists(certpath): cert = load_cert_file(certpath) if cert: try: digest_algo = cert.get_signature_algorithm().decode('utf-8').\ split('With')[0] except AttributeError: # Old py-OpenSSL is missing get_signature_algorithm digest_algo = "sha256" if cert.digest(digest_algo) == fingerprint: return True return False def send_cert_request(con, to_jid): iq = nbxmpp.Iq('get', to=to_jid) id_ = con.connection.getAnID() iq.setAttr('id', id_) pubkey = iq.setTag('pubkeys') pubkey.setNamespace(nbxmpp.NS_PUBKEY_PUBKEY) con.connection.send(iq) return str(id_) # the following code is partly due to pyopenssl examples def createKeyPair(type_, bits): """ Create a public/private key pair. Arguments: type_ - Key type, must be one of TYPE_RSA and TYPE_DSA bits - Number of bits to use in the key Returns: The public/private key pair in a PKey object """ pkey = crypto.PKey() pkey.generate_key(type_, bits) return pkey def createCertRequest(pkey, digest="sha256", **name): """ Create a certificate request. Arguments: pkey - The key to associate with the request digest - Digestion method to use for signing, default is sha256 **name - The name of the subject of the request, possible arguments are: C - Country name ST - State or province name L - Locality name O - Organization name OU - Organizational unit name CN - Common name emailAddress - E-mail address Returns: The certificate request in an X509Req object """ req = crypto.X509Req() subj = req.get_subject() for (key, value) in name.items(): setattr(subj, key, value) req.set_pubkey(pkey) req.sign(pkey, digest) return req def createCertificate(req, issuerCert, issuerKey, serial, notBefore, notAfter, digest="sha256"): """ Generate a certificate given a certificate request. Arguments: req - Certificate reqeust to use issuerCert - The certificate of the issuer issuerKey - The private key of the issuer serial - Serial number for the certificate notBefore - Timestamp (relative to now) when the certificate starts being valid notAfter - Timestamp (relative to now) when the certificate stops being valid digest - Digest method to use for signing, default is sha256 Returns: The signed certificate in an X509 object """ cert = crypto.X509() cert.set_serial_number(serial) cert.gmtime_adj_notBefore(notBefore) cert.gmtime_adj_notAfter(notAfter) cert.set_issuer(issuerCert.get_subject()) cert.set_subject(req.get_subject()) cert.set_pubkey(req.get_pubkey()) cert.sign(issuerKey, digest) return cert def make_certs(filepath, CN): """ make self signed certificates filepath : absolute path of certificate file, will be appended the '.pkey' and '.cert' extensions CN : common name """ key = createKeyPair(TYPE_RSA, 4096) req = createCertRequest(key, CN=CN) cert = createCertificate(req, req, key, 0, 0, 60*60*24*365*5) # five years with open(filepath + '.pkey', 'wb') as f: os.chmod(filepath + '.pkey', 0o600) f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key)) with open(filepath + '.cert', 'wb') as f: f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) if __name__ == '__main__': make_certs('./selfcert', 'gajim') gajim-gajim-1.1.3/gajim/common/logger.py000066400000000000000000001434171345766322700201310ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2004-2005 Vincent Hanquez # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Tomasz Melcer # Julien Pivotto # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ This module allows to access the on-disk database of logs """ import os import sys import time import datetime import calendar import json import logging import sqlite3 as sqlite from collections import namedtuple from gzip import GzipFile from io import BytesIO from gi.repository import GLib from gajim.common import exceptions from gajim.common import app from gajim.common import configpaths from gajim.common.helpers import AdditionalDataDict from gajim.common.i18n import _ from gajim.common.const import ( JIDConstant, KindConstant, ShowConstant, TypeConstant, SubscriptionConstant) LOGS_SQL_STATEMENT = ''' CREATE TABLE jids( jid_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, jid TEXT UNIQUE, type INTEGER ); CREATE TABLE unread_messages( message_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, jid_id INTEGER, shown BOOLEAN default 0 ); CREATE INDEX idx_unread_messages_jid_id ON unread_messages (jid_id); CREATE TABLE logs( log_line_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, account_id INTEGER, jid_id INTEGER, contact_name TEXT, time INTEGER, kind INTEGER, show INTEGER, message TEXT, subject TEXT, additional_data TEXT, stanza_id TEXT, encryption TEXT, encryption_state TEXT, marker INTEGER ); CREATE TABLE last_archive_message( jid_id INTEGER PRIMARY KEY UNIQUE, last_mam_id TEXT, oldest_mam_timestamp TEXT, last_muc_timestamp TEXT, sync_threshold INTEGER ); CREATE INDEX idx_logs_jid_id_time ON logs (jid_id, time DESC); CREATE INDEX idx_logs_stanza_id ON logs (stanza_id); PRAGMA user_version=2; ''' CACHE_SQL_STATEMENT = ''' CREATE TABLE transports_cache ( transport TEXT UNIQUE, type INTEGER ); CREATE TABLE caps_cache ( hash_method TEXT, hash TEXT, data BLOB, last_seen INTEGER); CREATE TABLE rooms_last_message_time( jid_id INTEGER PRIMARY KEY UNIQUE, time INTEGER ); CREATE TABLE roster_entry( account_jid_id INTEGER, jid_id INTEGER, name TEXT, subscription INTEGER, ask BOOLEAN, avatar_sha TEXT, PRIMARY KEY (account_jid_id, jid_id) ); CREATE TABLE roster_group( account_jid_id INTEGER, jid_id INTEGER, group_name TEXT, PRIMARY KEY (account_jid_id, jid_id, group_name) ); PRAGMA user_version=1; ''' log = logging.getLogger('gajim.c.logger') class Logger: def __init__(self): self._jid_ids = {} self._jid_ids_reversed = {} self._con = None self._commit_timout_id = None self._log_db_path = configpaths.get('LOG_DB') self._cache_db_path = configpaths.get('CACHE_DB') self._create_databases() self._migrate_databases() self._connect_databases() self._get_jid_ids_from_db() def _create_databases(self): if os.path.isdir(self._log_db_path): log.error(_('%s is a directory but should be a file'), self._log_db_path) sys.exit() if os.path.isdir(self._cache_db_path): log.error(_('%s is a directory but should be a file'), self._cache_db_path) sys.exit() if not os.path.exists(self._log_db_path): if os.path.exists(self._cache_db_path): os.remove(self._cache_db_path) self._create(LOGS_SQL_STATEMENT, self._log_db_path) if not os.path.exists(self._cache_db_path): self._create(CACHE_SQL_STATEMENT, self._cache_db_path) @staticmethod def _connect(*args, **kwargs): con = sqlite.connect(*args, **kwargs) con.execute("PRAGMA secure_delete=1") return con @classmethod def _create(cls, statement, path): log.info(_('Creating %s'), path) con = cls._connect(path) os.chmod(path, 0o600) try: con.executescript(statement) except Exception: log.exception('Error') con.close() os.remove(path) sys.exit() con.commit() con.close() @staticmethod def _get_user_version(con: sqlite.Connection) -> int: """ Return the value of PRAGMA user_version. """ return con.execute('PRAGMA user_version').fetchone()[0] def _migrate_databases(self): try: con = self._connect(self._log_db_path) self._migrate_logs(con) con.close() con = self._connect(self._cache_db_path) self._migrate_cache(con) con.close() except Exception: log.exception('Error') sys.exit() def _migrate_logs(self, con): if self._get_user_version(con) == 0: # All migrations from 0.16.9 until 1.0.0 statements = [ 'ALTER TABLE logs ADD COLUMN "account_id" INTEGER', 'ALTER TABLE logs ADD COLUMN "stanza_id" TEXT', 'ALTER TABLE logs ADD COLUMN "encryption" TEXT', 'ALTER TABLE logs ADD COLUMN "encryption_state" TEXT', 'ALTER TABLE logs ADD COLUMN "marker" INTEGER', 'ALTER TABLE logs ADD COLUMN "additional_data" TEXT', '''CREATE TABLE IF NOT EXISTS last_archive_message( jid_id INTEGER PRIMARY KEY UNIQUE, last_mam_id TEXT, oldest_mam_timestamp TEXT, last_muc_timestamp TEXT )''', '''CREATE INDEX IF NOT EXISTS idx_logs_stanza_id ON logs(stanza_id)''', 'PRAGMA user_version=1' ] self._execute_multiple(con, statements) if self._get_user_version(con) < 2: statements = [ 'ALTER TABLE last_archive_message ADD COLUMN "sync_threshold" INTEGER', 'PRAGMA user_version=2' ] self._execute_multiple(con, statements) def _migrate_cache(self, con): if self._get_user_version(con) == 0: # All migrations from 0.16.9 until 1.0.0 statements = [ 'ALTER TABLE roster_entry ADD COLUMN "avatar_sha" TEXT', 'PRAGMA user_version=1' ] self._execute_multiple(con, statements) if self._get_user_version(con) < 2: pass @staticmethod def _execute_multiple(con, statements): """ Execute mutliple statements with the option to fail on duplicates but still continue """ for sql in statements: try: con.execute(sql) con.commit() except sqlite.OperationalError as error: if str(error).startswith('duplicate column name:'): log.info(error) else: log.exception('Error') sys.exit() def namedtuple_factory(self, cursor, row): """ Usage: con.row_factory = namedtuple_factory """ fields = [col[0] for col in cursor.description] Row = namedtuple("Row", fields) named_row = Row(*row) if 'additional_data' in fields: _dict = json.loads(named_row.additional_data or '{}') named_row = named_row._replace( additional_data=AdditionalDataDict(_dict)) # if an alias `account` for the field `account_id` is used for the # query, the account_id is converted to the account jid if 'account' in fields: if named_row.account: jid = self._jid_ids_reversed[named_row.account].jid named_row = named_row._replace(account=jid) return named_row def dispatch(self, event, error): app.ged.raise_event(event, None, str(error)) def _connect_databases(self): self._con = self._connect( self._log_db_path, timeout=20.0, isolation_level='IMMEDIATE') self._con.row_factory = self.namedtuple_factory # DB functions self._con.create_function("like", 1, self._like) self._con.create_function("get_timeout", 0, self._get_timeout) self._set_synchronous(False) try: self._con.execute("ATTACH DATABASE '%s' AS cache" % self._cache_db_path.replace("'", "''")) except Exception: log.exception('Error') self._con.close() sys.exit() def _set_synchronous(self, sync): try: if sync: self._con.execute("PRAGMA synchronous = NORMAL") else: self._con.execute("PRAGMA synchronous = OFF") except sqlite.Error: log.exception('Error') @staticmethod def _get_timeout(): """ returns the timeout in epoch """ timeout = app.config.get('restore_timeout') now = int(time.time()) if timeout > 0: timeout = now - (timeout * 60) return timeout @staticmethod def _like(search_str): return '%{}%'.format(search_str) def commit(self): try: self._con.commit() except sqlite.OperationalError as e: print(str(e), file=sys.stderr) self._commit_timout_id = None return False def _timeout_commit(self): if self._commit_timout_id: return self._commit_timout_id = GLib.timeout_add(500, self.commit) def simple_commit(self, sql_to_commit): """ Helper to commit """ self._con.execute(sql_to_commit) self._timeout_commit() def _get_jid_ids_from_db(self): """ Load all jid/jid_id tuples into a dict for faster access """ rows = self._con.execute( 'SELECT jid_id, jid, type FROM jids').fetchall() for row in rows: self._jid_ids[row.jid] = row self._jid_ids_reversed[row.jid_id] = row def get_jids_in_db(self): return self._jid_ids.keys() def jid_is_from_pm(self, jid): """ If jid is gajim@conf/nkour it's likely a pm one, how we know gajim@conf is not a normal guy and nkour is not his resource? we ask if gajim@conf is already in jids (with type room jid) this fails if user disables logging for room and only enables for pm (so higly unlikely) and if we fail we do not go chaos (user will see the first pm as if it was message in room's public chat) and after that all okay """ if jid.find('/') > -1: possible_room_jid = jid.split('/', 1)[0] return self.jid_is_room_jid(possible_room_jid) # it's not a full jid, so it's not a pm one return False def jid_is_room_jid(self, jid): """ Return True if it's a room jid, False if it's not, None if we don't know """ jid_ = self._jid_ids.get(jid) if jid_ is None: return return jid_.type == JIDConstant.ROOM_TYPE @staticmethod def _get_family_jids(account, jid): """ Get all jids of the metacontacts family :param account: The account :param jid: The JID returns a list of JIDs' """ family = app.contacts.get_metacontacts_family(account, jid) if family: return [user['jid'] for user in family] return [jid] def get_account_id(self, account): jid = app.get_jid_from_account(account) return self.get_jid_id(jid, type_=JIDConstant.NORMAL_TYPE) def get_jid_id(self, jid, kind=None, type_=None): """ Get the jid id from a jid. In case the jid id is not found create a new one. :param jid: The JID :param kind: The KindConstant :param type_: The JIDConstant return the jid id """ if kind in (KindConstant.GC_MSG, KindConstant.GCSTATUS): type_ = JIDConstant.ROOM_TYPE elif kind is not None: type_ = JIDConstant.NORMAL_TYPE result = self._jid_ids.get(jid, None) if result is not None: return result.jid_id sql = 'SELECT jid_id, jid, type FROM jids WHERE jid = ?' row = self._con.execute(sql, [jid]).fetchone() if row is not None: self._jid_ids[jid] = row return row.jid_id if type_ is None: raise ValueError( 'Unable to insert new JID because type is missing') sql = 'INSERT INTO jids (jid, type) VALUES (?, ?)' lastrowid = self._con.execute(sql, (jid, type_)).lastrowid Row = namedtuple('Row', 'jid_id jid type') self._jid_ids[jid] = Row(lastrowid, jid, type_) self._timeout_commit() return lastrowid def convert_kind_values_to_db_api_values(self, kind): """ Convert from string style to constant ints for db """ if kind == 'status': kind_col = KindConstant.STATUS elif kind == 'gcstatus': kind_col = KindConstant.GCSTATUS elif kind == 'gc_msg': kind_col = KindConstant.GC_MSG elif kind == 'single_msg_recv': kind_col = KindConstant.SINGLE_MSG_RECV elif kind == 'single_msg_sent': kind_col = KindConstant.SINGLE_MSG_SENT elif kind == 'chat_msg_recv': kind_col = KindConstant.CHAT_MSG_RECV elif kind == 'chat_msg_sent': kind_col = KindConstant.CHAT_MSG_SENT elif kind == 'error': kind_col = KindConstant.ERROR return kind_col def convert_show_values_to_db_api_values(self, show): """ Convert from string style to constant ints for db """ if show == 'online': return ShowConstant.ONLINE if show == 'chat': return ShowConstant.CHAT if show == 'away': return ShowConstant.AWAY if show == 'xa': return ShowConstant.XA if show == 'dnd': return ShowConstant.DND if show == 'offline': return ShowConstant.OFFLINE if show is None: return ShowConstant.ONLINE # invisible in GC when someone goes invisible # it's a RFC violation .... but we should not crash return None def convert_human_transport_type_to_db_api_values(self, type_): """ Convert from string style to constant ints for db """ if type_ == 'aim': return TypeConstant.AIM if type_ == 'gadu-gadu': return TypeConstant.GG if type_ == 'http-ws': return TypeConstant.HTTP_WS if type_ == 'icq': return TypeConstant.ICQ if type_ == 'msn': return TypeConstant.MSN if type_ == 'qq': return TypeConstant.QQ if type_ == 'sms': return TypeConstant.SMS if type_ == 'smtp': return TypeConstant.SMTP if type_ in ('tlen', 'x-tlen'): return TypeConstant.TLEN if type_ == 'newmail': return TypeConstant.NEWMAIL if type_ == 'rss': return TypeConstant.RSS if type_ == 'weather': return TypeConstant.WEATHER if type_ == 'mrim': return TypeConstant.MRIM if type_ == 'jabber': return TypeConstant.NO_TRANSPORT return None def convert_api_values_to_human_transport_type(self, type_id): """ Convert from constant ints for db to string style """ if type_id == TypeConstant.AIM: return 'aim' if type_id == TypeConstant.GG: return 'gadu-gadu' if type_id == TypeConstant.HTTP_WS: return 'http-ws' if type_id == TypeConstant.ICQ: return 'icq' if type_id == TypeConstant.MSN: return 'msn' if type_id == TypeConstant.QQ: return 'qq' if type_id == TypeConstant.SMS: return 'sms' if type_id == TypeConstant.SMTP: return 'smtp' if type_id == TypeConstant.TLEN: return 'tlen' if type_id == TypeConstant.NEWMAIL: return 'newmail' if type_id == TypeConstant.RSS: return 'rss' if type_id == TypeConstant.WEATHER: return 'weather' if type_id == TypeConstant.MRIM: return 'mrim' if type_id == TypeConstant.NO_TRANSPORT: return 'jabber' def convert_xmpp_sub(self, sub): """ Convert from string style to constant ints for db """ if sub == 'none': return SubscriptionConstant.NONE if sub == 'to': return SubscriptionConstant.TO if sub == 'from': return SubscriptionConstant.FROM if sub == 'both': return SubscriptionConstant.BOTH def convert_db_sub(self, sub): """ Convert from constant ints for db to string style """ if sub == SubscriptionConstant.NONE: return 'none' if sub == SubscriptionConstant.TO: return 'to' if sub == SubscriptionConstant.FROM: return 'from' if sub == SubscriptionConstant.BOTH: return 'both' def insert_unread_events(self, message_id, jid_id): """ Add unread message with id: message_id """ sql = '''INSERT INTO unread_messages (message_id, jid_id, shown) VALUES (?, ?, 0)''' self._con.execute(sql, (message_id, jid_id)) self._timeout_commit() def set_read_messages(self, message_ids): """ Mark all messages with ids in message_ids as read """ ids = ','.join([str(i) for i in message_ids]) sql = 'DELETE FROM unread_messages WHERE message_id IN (%s)' % ids self.simple_commit(sql) def set_shown_unread_msgs(self, msg_log_id): """ Mark unread message as shown un GUI """ sql = 'UPDATE unread_messages SET shown = 1 where message_id = %s' % \ msg_log_id self.simple_commit(sql) def reset_shown_unread_messages(self): """ Set shown field to False in unread_messages table """ sql = 'UPDATE unread_messages SET shown = 0' self.simple_commit(sql) def get_unread_msgs(self): """ Get all unread messages """ all_messages = [] try: unread_results = self._con.execute( 'SELECT message_id, shown from unread_messages').fetchall() except Exception: unread_results = [] for message in unread_results: msg_log_id = message.message_id shown = message.shown # here we get infos for that message, and related jid from jids table # do NOT change order of SELECTed things, unless you change function(s) # that called this function result = self._con.execute(''' SELECT logs.log_line_id, logs.message, logs.time, logs.subject, jids.jid, logs.additional_data FROM logs, jids WHERE logs.log_line_id = %d AND logs.jid_id = jids.jid_id ''' % msg_log_id ).fetchone() if result is None: # Log line is no more in logs table. remove it from unread_messages self.set_read_messages([msg_log_id]) continue all_messages.append((result, shown)) return all_messages def get_last_conversation_lines(self, account, jid, pending): """ Get recent messages Pending messages are already in queue to be printed when the ChatControl is opened, so we dont want to request those messages. How many messages are requested depends on the 'restore_lines' config value. How far back in time messages are requested depends on _get_timeout(). :param account: The account :param jid: The jid from which we request the conversation lines :param pending: How many messages are currently pending so we dont request those messages returns a list of namedtuples """ restore = app.config.get('restore_lines') if restore <= 0: return [] kinds = map(str, [KindConstant.SINGLE_MSG_RECV, KindConstant.SINGLE_MSG_SENT, KindConstant.CHAT_MSG_RECV, KindConstant.CHAT_MSG_SENT, KindConstant.ERROR]) jids = self._get_family_jids(account, jid) sql = ''' SELECT time, kind, message, subject, additional_data FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND kind IN ({kinds}) AND time > get_timeout() ORDER BY time DESC, log_line_id DESC LIMIT ? OFFSET ? '''.format(jids=', '.join('?' * len(jids)), kinds=', '.join(kinds)) try: messages = self._con.execute( sql, tuple(jids) + (restore, pending)).fetchall() except sqlite.DatabaseError: self.dispatch('DB_ERROR', exceptions.DatabaseMalformed(self._log_db_path)) return [] messages.reverse() return messages def get_unix_time_from_date(self, year, month, day): # year (fe 2005), month (fe 11), day (fe 25) # returns time in seconds for the second that starts that date since epoch # gimme unixtime from year month day: d = datetime.date(year, month, day) local_time = d.timetuple() # time tuple (compat with time.localtime()) # we have time since epoch baby :) start_of_day = int(time.mktime(local_time)) return start_of_day def get_conversation_for_date(self, account, jid, date): """ Load the complete conversation with a given jid on a specific date :param account: The account :param jid: The jid for which we request the conversation :param date: datetime.datetime instance example: datetime.datetime(year, month, day) returns a list of namedtuples """ jids = self._get_family_jids(account, jid) delta = datetime.timedelta( hours=23, minutes=59, seconds=59, microseconds=999999) sql = ''' SELECT contact_name, time, kind, show, message, subject, additional_data, log_line_id FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND time BETWEEN ? AND ? ORDER BY time, log_line_id '''.format(jids=', '.join('?' * len(jids))) return self._con.execute(sql, tuple(jids) + (date.timestamp(), (date + delta).timestamp())).fetchall() def search_log(self, account, jid, query, date=None): """ Search the conversation log for messages containing the `query` string. The search can either span the complete log for the given `account` and `jid` or be restriced to a single day by specifying `date`. :param account: The account :param jid: The jid for which we request the conversation :param query: A search string :param date: datetime.datetime instance example: datetime.datetime(year, month, day) returns a list of namedtuples """ jids = self._get_family_jids(account, jid) if date: delta = datetime.timedelta( hours=23, minutes=59, seconds=59, microseconds=999999) between = ''' AND time BETWEEN {start} AND {end} '''.format(start=date.timestamp(), end=(date + delta).timestamp()) sql = ''' SELECT contact_name, time, kind, show, message, subject, additional_data, log_line_id FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND message LIKE like(?) {date_search} ORDER BY time, log_line_id '''.format(jids=', '.join('?' * len(jids)), date_search=between if date else '') return self._con.execute(sql, tuple(jids) + (query,)).fetchall() def get_days_with_logs(self, account, jid, year, month): """ Request the days in a month where we received messages for a given `jid`. :param account: The account :param jid: The jid for which we request the days :param year: The year :param month: The month returns a list of namedtuples """ jids = self._get_family_jids(account, jid) kinds = map(str, [KindConstant.STATUS, KindConstant.GCSTATUS]) # Calculate the start and end datetime of the month date = datetime.datetime(year, month, 1) days = calendar.monthrange(year, month)[1] - 1 delta = datetime.timedelta( days=days, hours=23, minutes=59, seconds=59, microseconds=999999) sql = """ SELECT DISTINCT CAST(strftime('%d', time, 'unixepoch', 'localtime') AS INTEGER) AS day FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND time BETWEEN ? AND ? AND kind NOT IN ({kinds}) ORDER BY time """.format(jids=', '.join('?' * len(jids)), kinds=', '.join(kinds)) return self._con.execute(sql, tuple(jids) + (date.timestamp(), (date + delta).timestamp())).fetchall() def get_last_date_that_has_logs(self, account, jid): """ Get the timestamp of the last message we received for the jid. :param account: The account :param jid: The jid for which we request the last timestamp returns a timestamp or None """ jids = self._get_family_jids(account, jid) kinds = map(str, [KindConstant.STATUS, KindConstant.GCSTATUS]) sql = ''' SELECT MAX(time) as time FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND kind NOT IN ({kinds}) '''.format(jids=', '.join('?' * len(jids)), kinds=', '.join(kinds)) # fetchone() returns always at least one Row with all # attributes set to None because of the MAX() function return self._con.execute(sql, tuple(jids)).fetchone().time def get_first_date_that_has_logs(self, account, jid): """ Get the timestamp of the first message we received for the jid. :param account: The account :param jid: The jid for which we request the first timestamp returns a timestamp or None """ jids = self._get_family_jids(account, jid) kinds = map(str, [KindConstant.STATUS, KindConstant.GCSTATUS]) sql = ''' SELECT MIN(time) as time FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND kind NOT IN ({kinds}) '''.format(jids=', '.join('?' * len(jids)), kinds=', '.join(kinds)) # fetchone() returns always at least one Row with all # attributes set to None because of the MIN() function return self._con.execute(sql, tuple(jids)).fetchone().time def get_date_has_logs(self, account, jid, date): """ Get single timestamp of a message we received for the jid in the time range of one day. :param account: The account :param jid: The jid for which we request the first timestamp :param date: datetime.datetime instance example: datetime.datetime(year, month, day) returns a timestamp or None """ jids = self._get_family_jids(account, jid) delta = datetime.timedelta( hours=23, minutes=59, seconds=59, microseconds=999999) start = date.timestamp() end = (date + delta).timestamp() sql = ''' SELECT time FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND time BETWEEN ? AND ? '''.format(jids=', '.join('?' * len(jids))) return self._con.execute( sql, tuple(jids) + (start, end)).fetchone() def get_room_last_message_time(self, account, jid): """ Get the timestamp of the last message we received in a room. :param account: The account :param jid: The jid for which we request the last timestamp returns a timestamp or None """ sql = ''' SELECT time FROM rooms_last_message_time NATURAL JOIN jids WHERE jid = ? ''' row = self._con.execute(sql, (jid,)).fetchone() if not row: return self.get_last_date_that_has_logs(account, jid) return row.time def set_room_last_message_time(self, jid, timestamp): """ Set the timestamp of the last message we received in a room. :param jid: The jid :param timestamp: The timestamp in epoch """ jid_id = self.get_jid_id(jid, type_=JIDConstant.ROOM_TYPE) sql = '''REPLACE INTO rooms_last_message_time VALUES (:jid_id, COALESCE( (SELECT time FROM rooms_last_message_time WHERE jid_id = :jid_id AND time >= :time), :time))''' self._con.execute(sql, {"jid_id": jid_id, "time": timestamp}) self._timeout_commit() def save_transport_type(self, jid, type_): """ Save the type of the transport in DB """ type_id = self.convert_human_transport_type_to_db_api_values(type_) if not type_id: # unknown type return result = self._con.execute( 'SELECT type from transports_cache WHERE transport = "%s"' % jid).fetchone() if result: if result.type == type_id: return sql = 'UPDATE transports_cache SET type = %d WHERE transport = "%s"' %\ (type_id, jid) self.simple_commit(sql) return sql = 'INSERT INTO transports_cache (transport, type) VALUES (?, ?)' self._con.execute(sql, (jid, type_id)) self._timeout_commit() def get_transports_type(self): """ Return all the type of the transports in DB """ results = self._con.execute('SELECT * from transports_cache').fetchall() if not results: return {} answer = {} for result in results: answer[result.transport] = self.convert_api_values_to_human_transport_type( result.type) return answer # A longer note here: # The database contains a blob field. Pysqlite seems to need special care for # such fields. # When storing, we need to convert string into buffer object (1). # When retrieving, we need to convert it back to a string to decompress it. # (2) # GzipFile needs a file-like object, StringIO emulates file for plain strings def iter_caps_data(self): """ Iterate over caps cache data stored in the database The iterator values are pairs of (node, ver, ext, identities, features): identities == {'category':'foo', 'type':'bar', 'name':'boo'}, features being a list of feature namespaces. """ # get data from table # the data field contains binary object (gzipped data), this is a hack # to get that data without trying to convert it to unicode try: rows = self._con.execute('SELECT hash_method, hash, data FROM caps_cache;') except sqlite.OperationalError: # might happen when there's no caps_cache table yet # -- there's no data to read anyway then return # list of corrupted entries that will be removed to_be_removed = [] for row in rows: # for each row: unpack the data field # (format: (category, type, name, category, type, name, ... # ..., 'FEAT', feature1, feature2, ...).join(' ')) # NOTE: if there's a need to do more gzip, put that to a function try: data = GzipFile(fileobj=BytesIO(row.data)).read().decode('utf-8').split('\0') except IOError: # This data is corrupted. It probably contains non-ascii chars to_be_removed.append((row.hash_method, row.hash)) continue i = 0 identities = list() features = list() while i < (len(data) - 3) and data[i] != 'FEAT': category = data[i] type_ = data[i + 1] lang = data[i + 2] name = data[i + 3] identities.append({'category': category, 'type': type_, 'xml:lang': lang, 'name': name}) i += 4 i += 1 while i < len(data): features.append(data[i]) i += 1 # yield the row yield row.hash_method, row.hash, identities, features for hash_method, hash_ in to_be_removed: sql = '''DELETE FROM caps_cache WHERE hash_method = "%s" AND hash = "%s"''' % (hash_method, hash_) self.simple_commit(sql) def add_caps_entry(self, hash_method, hash_, identities, features): data = [] for identity in identities: # there is no FEAT category if identity['category'] == 'FEAT': return data.extend((identity.get('category'), identity.get('type', ''), identity.get('xml:lang', ''), identity.get('name', ''))) data.append('FEAT') data.extend(features) data = '\0'.join(data) # if there's a need to do more gzip, put that to a function string = BytesIO() gzip = GzipFile(fileobj=string, mode='w') gzip.write(data.encode('utf-8')) gzip.close() data = string.getvalue() self._con.execute(''' INSERT INTO caps_cache ( hash_method, hash, data, last_seen ) VALUES (?, ?, ?, ?); ''', (hash_method, hash_, memoryview(data), int(time.time()))) # (1) -- note above self._timeout_commit() def update_caps_time(self, method, hash_): sql = '''UPDATE caps_cache SET last_seen = %d WHERE hash_method = "%s" and hash = "%s"''' % \ (int(time.time()), method, hash_) self.simple_commit(sql) def clean_caps_table(self): """ Remove caps which was not seen for 3 months """ sql = '''DELETE FROM caps_cache WHERE last_seen < %d''' % \ int(time.time() - 3*30*24*3600) self.simple_commit(sql) def replace_roster(self, account_name, roster_version, roster): """ Replace current roster in DB by a new one accout_name is the name of the account to change. roster_version is the version of the new roster. roster is the new version. """ # First we must reset roster_version value to ensure that the server # sends back all the roster at the next connexion if the replacement # didn't work properly. app.config.set_per('accounts', account_name, 'roster_version', '') account_jid = app.get_jid_from_account(account_name) # Execute get_jid_id() because this ensures on new accounts that the # jid_id will be created self.get_jid_id(account_jid, type_=JIDConstant.NORMAL_TYPE) # Delete old roster self.remove_roster(account_jid) # Fill roster tables with the new roster for jid in roster: self.add_or_update_contact(account_jid, jid, roster[jid]['name'], roster[jid]['subscription'], roster[jid]['ask'], roster[jid]['groups'], commit=False) self._timeout_commit() # At this point, we are sure the replacement works properly so we can # set the new roster_version value. app.config.set_per('accounts', account_name, 'roster_version', roster_version) def del_contact(self, account_jid, jid): """ Remove jid from account_jid roster """ try: account_jid_id = self.get_jid_id(account_jid) jid_id = self.get_jid_id(jid) except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) self._con.execute( 'DELETE FROM roster_group WHERE account_jid_id=? AND jid_id=?', (account_jid_id, jid_id)) self._con.execute( 'DELETE FROM roster_entry WHERE account_jid_id=? AND jid_id=?', (account_jid_id, jid_id)) self._timeout_commit() def add_or_update_contact(self, account_jid, jid, name, sub, ask, groups, commit=True): """ Add or update a contact from account_jid roster """ if sub == 'remove': self.del_contact(account_jid, jid) return try: account_jid_id = self.get_jid_id(account_jid) jid_id = self.get_jid_id(jid, type_=JIDConstant.NORMAL_TYPE) except exceptions.PysqliteOperationalError as error: raise exceptions.PysqliteOperationalError(str(error)) # Update groups information # First we delete all previous groups information sql = 'DELETE FROM roster_group WHERE account_jid_id=? AND jid_id=?' self._con.execute(sql, (account_jid_id, jid_id)) # Then we add all new groups information sql = '''INSERT INTO roster_group (account_jid_id, jid_id, group_name) VALUES (?, ?, ?)''' for group in groups: self._con.execute(sql, (account_jid_id, jid_id, group)) if name is None: name = '' sql = '''REPLACE INTO roster_entry (account_jid_id, jid_id, name, subscription, ask) VALUES(?, ?, ?, ?, ?)''' self._con.execute(sql, (account_jid_id, jid_id, name, self.convert_xmpp_sub(sub), bool(ask))) if commit: self._timeout_commit() def get_roster(self, account_jid): """ Return the accound_jid roster in NonBlockingRoster format """ data = {} account_jid_id = self.get_jid_id(account_jid, type_=JIDConstant.NORMAL_TYPE) # First we fill data with roster_entry informations rows = self._con.execute(''' SELECT j.jid, re.jid_id, re.name, re.subscription, re.ask, re.avatar_sha FROM roster_entry re, jids j WHERE re.account_jid_id=? AND j.jid_id=re.jid_id''', (account_jid_id,)) for row in rows: #jid, jid_id, name, subscription, ask jid = row.jid name = row.name data[jid] = {} data[jid]['avatar_sha'] = row.avatar_sha if name: data[jid]['name'] = name else: data[jid]['name'] = None data[jid]['subscription'] = self.convert_db_sub(row.subscription) data[jid]['groups'] = [] data[jid]['resources'] = {} if row.ask: data[jid]['ask'] = 'subscribe' else: data[jid]['ask'] = None data[jid]['id'] = row.jid_id # Then we add group for roster entries for jid in data: rows = self._con.execute(''' SELECT group_name FROM roster_group WHERE account_jid_id=? AND jid_id=?''', (account_jid_id, data[jid]['id'])) for row in rows: group_name = row.group_name data[jid]['groups'].append(group_name) del data[jid]['id'] return data def remove_roster(self, account_jid): """ Remove the roster of an account :param account_jid: The jid of the account """ try: jid_id = self.get_jid_id(account_jid) except ValueError: # This happens if the JID never made it to the Database # because the account was never connected return sql = ''' DELETE FROM roster_entry WHERE account_jid_id = {jid_id}; DELETE FROM roster_group WHERE account_jid_id = {jid_id}; '''.format(jid_id=jid_id) self._con.executescript(sql) self._timeout_commit() def search_for_duplicate(self, account, jid, timestamp, msg): """ Check if a message is already in the `logs` table :param account: The account :param jid: The jid as string :param timestamp: The timestamp in UTC epoch :param msg: The message text """ # Add 10 seconds around the timestamp start_time = timestamp - 30 end_time = timestamp + 30 account_id = self.get_account_id(account) log.debug('start: %s, end: %s, jid: %s, message: %s', start_time, end_time, jid, msg) sql = ''' SELECT * FROM logs NATURAL JOIN jids WHERE jid = ? AND message = ? AND account_id = ? AND time BETWEEN ? AND ? ''' result = self._con.execute( sql, (jid, msg, account_id, start_time, end_time)).fetchone() if result is not None: log.debug('Message already in DB') return True return False def find_stanza_id(self, account, archive_jid, stanza_id, origin_id=None, groupchat=False): """ Checks if a stanza-id is already in the `logs` table :param account: The account :param archive_jid: The jid of the archive the stanza-id belongs to only used if groupchat=True :param stanza_id: The stanza-id :param origin_id: The origin-id :param groupchat: stanza-id is from a groupchat return True if the stanza-id was found """ ids = [] if stanza_id is not None: ids.append(stanza_id) if origin_id is not None: ids.append(origin_id) if not ids: return False type_ = JIDConstant.NORMAL_TYPE if groupchat: type_ = JIDConstant.ROOM_TYPE archive_id = self.get_jid_id(archive_jid, type_=type_) account_id = self.get_account_id(account) if groupchat: # Stanza ID is only unique within a specific archive. # So a Stanza ID could be repeated in different MUCs, so we # filter also for the archive JID which is the bare MUC jid. sql = ''' SELECT stanza_id FROM logs WHERE stanza_id IN ({values}) AND jid_id = ? AND account_id = ? LIMIT 1 '''.format(values=', '.join('?' * len(ids))) result = self._con.execute( sql, tuple(ids) + (archive_id, account_id)).fetchone() else: sql = ''' SELECT stanza_id FROM logs WHERE stanza_id IN ({values}) AND account_id = ? AND kind != ? LIMIT 1 '''.format(values=', '.join('?' * len(ids))) result = self._con.execute( sql, tuple(ids) + (account_id, KindConstant.GC_MSG)).fetchone() if result is not None: log.info('Found duplicated message, stanza-id: %s, origin-id: %s, ' 'archive-jid: %s, account: %s', stanza_id, origin_id, archive_jid, account_id) return True return False def insert_jid(self, jid, kind=None, type_=JIDConstant.NORMAL_TYPE): """ Insert a new jid into the `jids` table. This is an alias of get_jid_id() for better readablility. :param jid: The jid as string :param kind: A KindConstant :param type_: A JIDConstant """ return self.get_jid_id(jid, kind, type_) def insert_into_logs(self, account, jid, time_, kind, unread=True, **kwargs): """ Insert a new message into the `logs` table :param jid: The jid as string :param time_: The timestamp in UTC epoch :param kind: A KindConstant :param unread: If True the message is added to the`unread_messages` table. Only if kind == CHAT_MSG_RECV :param kwargs: Every additional named argument must correspond to a field in the `logs` table """ jid_id = self.get_jid_id(jid, kind=kind) account_id = self.get_account_id(account) if 'additional_data' in kwargs: if not kwargs['additional_data']: del kwargs['additional_data'] else: serialized_dict = json.dumps(kwargs["additional_data"].data) kwargs['additional_data'] = serialized_dict sql = ''' INSERT INTO logs (account_id, jid_id, time, kind, {columns}) VALUES (?, ?, ?, ?, {values}) '''.format(columns=', '.join(kwargs.keys()), values=', '.join('?' * len(kwargs))) lastrowid = self._con.execute( sql, (account_id, jid_id, time_, kind) + tuple(kwargs.values())).lastrowid log.info('Insert into DB: jid: %s, time: %s, kind: %s, stanza_id: %s', jid, time_, kind, kwargs.get('stanza_id', None)) if unread and kind == KindConstant.CHAT_MSG_RECV: sql = '''INSERT INTO unread_messages (message_id, jid_id) VALUES (?, (SELECT jid_id FROM jids WHERE jid = ?))''' self._con.execute(sql, (lastrowid, jid)) self._timeout_commit() return lastrowid def set_avatar_sha(self, account_jid, jid, sha=None): """ Set the avatar sha of a jid on an account :param account_jid: The jid of the account :param jid: The jid that belongs to the avatar :param sha: The sha of the avatar """ account_jid_id = self.get_jid_id(account_jid) jid_id = self.get_jid_id(jid, type_=JIDConstant.NORMAL_TYPE) sql = ''' UPDATE roster_entry SET avatar_sha = ? WHERE account_jid_id = ? AND jid_id = ? ''' self._con.execute(sql, (sha, account_jid_id, jid_id)) self._timeout_commit() def get_archive_infos(self, jid): """ Get the archive infos :param jid: The jid that belongs to the avatar """ jid_id = self.get_jid_id(jid, type_=JIDConstant.ROOM_TYPE) sql = '''SELECT * FROM last_archive_message WHERE jid_id = ?''' return self._con.execute(sql, (jid_id,)).fetchone() def set_archive_infos(self, jid, **kwargs): """ Set archive infos :param jid: The jid that belongs to the avatar :param last_mam_id: The last MAM result id :param oldest_mam_timestamp: The oldest date we requested MAM history for :param last_muc_timestamp: The timestamp of the last message we received in a MUC :param sync_threshold: The max days that we request from a MUC archive """ jid_id = self.get_jid_id(jid) exists = self.get_archive_infos(jid) if not exists: sql = '''INSERT INTO last_archive_message (jid_id, last_mam_id, oldest_mam_timestamp, last_muc_timestamp, sync_threshold) VALUES (?, ?, ?, ?, ?)''' self._con.execute(sql, ( jid_id, kwargs.get('last_mam_id', None), kwargs.get('oldest_mam_timestamp', None), kwargs.get('last_muc_timestamp', None), kwargs.get('sync_threshold', None) )) else: args = ' = ?, '.join(kwargs.keys()) + ' = ?' sql = '''UPDATE last_archive_message SET {} WHERE jid_id = ?'''.format(args) self._con.execute(sql, tuple(kwargs.values()) + (jid_id,)) log.info('Save archive infos: %s', kwargs) self._timeout_commit() gajim-gajim-1.1.3/gajim/common/logging_helpers.py000066400000000000000000000127211345766322700220130ustar00rootroot00000000000000# Copyright (C) 2009 Bruno Tarquini # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging import os import sys from gajim.common.i18n import _ def parseLogLevel(arg): """ Eiter numeric value or level name from logging module """ if arg.isdigit(): return int(arg) if arg.isupper() and hasattr(logging, arg): return getattr(logging, arg) print(_('%s is not a valid loglevel') % repr(arg), file=sys.stderr) return 0 def parseLogTarget(arg): """ [gajim.]c.x.y -> gajim.c.x.y .other_logger -> other_logger -> gajim """ arg = arg.lower() if not arg: return 'gajim' if arg.startswith('.'): return arg[1:] if arg.startswith('gajim'): return arg return 'gajim.' + arg def parseAndSetLogLevels(arg): """ [=]LOGLEVEL -> gajim=LOGLEVEL gajim=LOGLEVEL -> gajim=LOGLEVEL .other=10 -> other=10 .=10 -> c.x.y=c.z=20 -> gajim.c.x.y=20 gajim.c.z=20 gajim=10,c.x=20 -> gajim=10 gajim.c.x=20 """ for directive in arg.split(','): directive = directive.strip() if not directive: continue if '=' not in directive: directive = '=' + directive targets, level = directive.rsplit('=', 1) level = parseLogLevel(level.strip()) for target in targets.split('='): target = parseLogTarget(target.strip()) if target: logging.getLogger(target).setLevel(level) print("Logger %s level set to %d" % (target, level), file=sys.stderr) class colors: # pylint: disable=C0326 NONE = chr(27) + "[0m" BLACk = chr(27) + "[30m" RED = chr(27) + "[31m" GREEN = chr(27) + "[32m" BROWN = chr(27) + "[33m" BLUE = chr(27) + "[34m" MAGENTA = chr(27) + "[35m" CYAN = chr(27) + "[36m" LIGHT_GRAY = chr(27) + "[37m" DARK_GRAY = chr(27) + "[30;1m" BRIGHT_RED = chr(27) + "[31;1m" BRIGHT_GREEN = chr(27) + "[32;1m" YELLOW = chr(27) + "[33;1m" BRIGHT_BLUE = chr(27) + "[34;1m" PURPLE = chr(27) + "[35;1m" BRIGHT_CYAN = chr(27) + "[36;1m" WHITE = chr(27) + "[37;1m" def colorize(text, color): return color + text + colors.NONE class FancyFormatter(logging.Formatter): """ An eye-candy formatter with colors """ colors_mapping = { 'DEBUG': colors.BLUE, 'INFO': colors.GREEN, 'WARNING': colors.BROWN, 'ERROR': colors.RED, 'CRITICAL': colors.BRIGHT_RED, } def __init__(self, fmt, datefmt=None, use_color=False): logging.Formatter.__init__(self, fmt, datefmt) self.use_color = use_color def formatTime(self, record, datefmt=None): f = logging.Formatter.formatTime(self, record, datefmt) if self.use_color: f = colorize(f, colors.DARK_GRAY) return f def format(self, record): level = record.levelname record.levelname = '(%s)' % level[0] if self.use_color: c = FancyFormatter.colors_mapping.get(level, '') record.levelname = colorize(record.levelname, c) record.name = colorize(record.name, colors.CYAN) else: record.name += ':' return logging.Formatter.format(self, record) def init(): """ Iinitialize the logging system """ use_color = False if os.name != 'nt': use_color = sys.stderr.isatty() consoleloghandler = logging.StreamHandler() consoleloghandler.setFormatter( FancyFormatter( '%(asctime)s %(levelname)s %(name)s %(message)s', '%x %H:%M:%S', use_color ) ) # fake the root logger so we have 'gajim' root name instead of 'root' root_log = logging.getLogger('gajim') root_log.setLevel(logging.WARNING) root_log.addHandler(consoleloghandler) root_log.propagate = False # handle nbxmpp logs too root_log = logging.getLogger('nbxmpp') root_log.setLevel(logging.WARNING) root_log.addHandler(consoleloghandler) root_log.propagate = False def set_loglevels(loglevels_string): parseAndSetLogLevels(loglevels_string) def set_verbose(): parseAndSetLogLevels('gajim=DEBUG') parseAndSetLogLevels('.nbxmpp=INFO') def set_quiet(): parseAndSetLogLevels('gajim=CRITICAL') parseAndSetLogLevels('.nbxmpp=CRITICAL') # tests if __name__ == '__main__': init() set_loglevels('gajim.c=DEBUG,INFO') log = logging.getLogger('gajim') log.debug('debug') log.info('info') log.warning('warn') log.error('error') log.critical('critical') log = logging.getLogger('gajim.c.x.dispatcher') log.debug('debug') log.info('info') log.warning('warn') log.error('error') log.critical('critical') gajim-gajim-1.1.3/gajim/common/modules/000077500000000000000000000000001345766322700177365ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/modules/__init__.py000066400000000000000000000071301345766322700220500ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Any from typing import Dict # pylint: disable=unused-import from typing import List from typing import Tuple import logging from importlib import import_module from pathlib import Path from unittest.mock import MagicMock from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m') ZEROCONF_MODULES = ['adhoc_commands', 'receipts', 'discovery', 'chatstates'] _imported_modules = [] # type: List[tuple] _modules = {} # type: Dict[str, Dict[str, Any]] for file in Path(__file__).parent.iterdir(): if file.stem == '__init__': continue _module = import_module('.%s' % file.stem, package='gajim.common.modules') if hasattr(_module, 'get_instance'): log.info('Load module: %s', file.stem) if file.stem == 'pep': # Register the PEP module first, because other modules # depend on it _imported_modules.insert(0, (_module, file.stem)) else: _imported_modules.append((_module, file.stem)) class ModuleMock: def __init__(self, name: str) -> None: self._name = name # HTTPUpload, .. self.available = False # Blocking self.blocked = [] # type: List[Any] # Privacy Lists self.blocked_contacts = [] # type: List[Any] self.blocked_groups = [] # type: List[Any] self.blocked_all = False # Delimiter self.delimiter = '::' # Bookmarks self.bookmarks = {} # type: Dict[Any, Any] # Various Modules self.supported = False def __getattr__(self, key: str) -> MagicMock: return MagicMock() def register(con: ConnectionT, *args: Any, **kwargs: Any) -> None: if con in _modules: return _modules[con.name] = {} for module in _imported_modules: mod, name = module if con.name == 'Local': if name not in ZEROCONF_MODULES: continue instance, name = mod.get_instance(con, *args, **kwargs) _modules[con.name][name] = instance def register_single(con: ConnectionT, instance: Any, name: str) -> None: if con.name not in _modules: raise ValueError('Unknown account name: %s' % con.name) _modules[con.name][name] = instance def unregister(con: ConnectionT) -> None: for instance in _modules[con.name].values(): if hasattr(instance, 'cleanup'): instance.cleanup() del _modules[con.name] def unregister_single(con: ConnectionT, name: str) -> None: if con.name not in _modules: return if name not in _modules[con.name]: return del _modules[con.name][name] def get(account: str, name: str) -> Any: try: return _modules[account][name] except KeyError: return ModuleMock(name) def get_handlers(con: ConnectionT) -> List[Tuple[Any, ...]]: handlers = [] # type: List[Tuple[Any, ...]] for module in _modules[con.name].values(): handlers += module.handlers return handlers gajim-gajim-1.1.3/gajim/common/modules/adhoc_commands.py000066400000000000000000000500211345766322700232450ustar00rootroot00000000000000# Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2006-2007 Tomasz Melcer # Copyright (C) 2007 Jean-Marie Traissard # Copyright (C) 2008 Brendan Taylor # Stephan Erb # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.modules import dataforms from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.commands') class AdHocCommand: commandnode = 'command' commandname = 'The Command' commandfeatures = (nbxmpp.NS_DATA,) @staticmethod def is_visible_for(_samejid): """ This returns True if that command should be visible and invokable for others samejid - True when command is invoked by an entity with the same bare jid. """ return True def __init__(self, conn, jid, sessionid): self.connection = conn self.jid = jid self.sessionid = sessionid def build_response(self, request, status='executing', defaultaction=None, actions=None): assert status in ('executing', 'completed', 'canceled') response = request.buildReply('result') cmd = response.getTag('command', namespace=nbxmpp.NS_COMMANDS) cmd.setAttr('sessionid', self.sessionid) cmd.setAttr('node', self.commandnode) cmd.setAttr('status', status) if defaultaction is not None or actions is not None: if defaultaction is not None: assert defaultaction in ('cancel', 'execute', 'prev', 'next', 'complete') attrs = {'action': defaultaction} else: attrs = {} cmd.addChild('actions', attrs, actions) return response, cmd def bad_request(self, stanza): self.connection.connection.send( nbxmpp.Error(stanza, nbxmpp.NS_STANZAS + ' bad-request')) def cancel(self, request): response = self.build_response(request, status='canceled')[0] self.connection.connection.send(response) return False # finish the session class ChangeStatusCommand(AdHocCommand): commandnode = 'change-status' commandname = _('Change status information') def __init__(self, conn, jid, sessionid): AdHocCommand.__init__(self, conn, jid, sessionid) self._callback = self.first_step @staticmethod def is_visible_for(samejid): """ Change status is visible only if the entity has the same bare jid """ return samejid def execute(self, request): return self._callback(request) def first_step(self, request): # first query... response, cmd = self.build_response(request, defaultaction='execute', actions=['execute']) cmd.addChild( node=dataforms.SimpleDataForm( title=_('Change status'), instructions=_('Set the presence type and description'), fields=[ dataforms.create_field( 'list-single', var='presence-type', label='Type of presence:', options=[ ('chat', _('Free for chat')), ('online', _('Online')), ('away', _('Away')), ('xa', _('Extended away')), ('dnd', _('Do not disturb')), ('offline', _('Offline - disconnect'))], value='online', required=True), dataforms.create_field( 'text-multi', var='presence-desc', label=_('Presence description:')) ] ) ) self.connection.connection.send(response) # for next invocation self._callback = self.second_step return True # keep the session def second_step(self, request): # check if the data is correct try: form = dataforms.SimpleDataForm( extend=request.getTag('command').getTag('x')) except Exception: self.bad_request(request) return False try: presencetype = form['presence-type'].value if presencetype not in ('chat', 'online', 'away', 'xa', 'dnd', 'offline'): self.bad_request(request) return False except Exception: # KeyError if there's no presence-type field in form or # AttributeError if that field is of wrong type self.bad_request(request) return False try: presencedesc = form['presence-desc'].value except Exception: # same exceptions as in last comment presencedesc = '' response, cmd = self.build_response(request, status='completed') cmd.addChild('note', {}, _('The status has been changed.')) # if going offline, we need to push response so it won't go into # queue and disappear self.connection.connection.send(response, now=presencetype == 'offline') # send new status app.interface.roster.send_status( self.connection.name, presencetype, presencedesc) return False # finish the session def find_current_groupchats(account): from gajim import message_control rooms = [] for gc_control in app.interface.msg_win_mgr.get_controls( message_control.TYPE_GC) + \ app.interface.minimized_controls[account].values(): acct = gc_control.account # check if account is the good one if acct != account: continue room_jid = gc_control.room_jid nick = gc_control.nick if (room_jid in app.gc_connected[acct] and app.gc_connected[acct][room_jid]): rooms.append((room_jid, nick,)) return rooms class LeaveGroupchatsCommand(AdHocCommand): commandnode = 'leave-groupchats' commandname = _('Leave Groupchats') def __init__(self, conn, jid, sessionid): AdHocCommand.__init__(self, conn, jid, sessionid) self._callback = self.first_step @staticmethod def is_visible_for(samejid): """ Leave groupchats is visible only if the entity has the same bare jid """ return samejid def execute(self, request): return self._callback(request) def first_step(self, request): # first query... response, cmd = self.build_response(request, defaultaction='execute', actions=['execute']) options = [] account = self.connection.name for gc in find_current_groupchats(account): options.append( ('%s' % gc[0], _('%(nickname)s on %(room_jid)s') % {'nickname': gc[1], 'room_jid': gc[0]})) if not options: response, cmd = self.build_response(request, status='completed') cmd.addChild('note', {}, _('You have not joined a groupchat.')) self.connection.connection.send(response) return False cmd.addChild( node=dataforms.SimpleDataForm( title=_('Leave Groupchats'), instructions=_('Choose the groupchats you want to leave'), fields=[ dataforms.create_field( 'list-multi', var='groupchats', label=_('Groupchats'), options=options, required=True) ] ) ) self.connection.connection.send(response) # for next invocation self._callback = self.second_step return True # keep the session def second_step(self, request): # check if the data is correct try: form = dataforms.SimpleDataForm( extend=request.getTag('command').getTag('x')) except Exception: self.bad_request(request) return False try: gc = form['groupchats'].values except Exception: # KeyError if there's no groupchats in form self.bad_request(request) return False account = self.connection.name try: for room_jid in gc: gc_control = app.interface.msg_win_mgr.get_gc_control( room_jid, account) if not gc_control: minimized_controls = app.interface.minimized_controls gc_control = minimized_controls[account][room_jid] gc_control.shutdown() app.interface.roster.remove_groupchat(room_jid, account) continue gc_control.parent_win.remove_tab(gc_control, None, force=True) except Exception: # KeyError if there's no such room opened self.bad_request(request) return False response, cmd = self.build_response(request, status='completed') note = _('You left the following groupchats:') for room_jid in gc: note += '\n\t' + room_jid cmd.addChild('note', {}, note) self.connection.connection.send(response) return False class AdHocCommands: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('iq', self._execute_command_received, 'set', nbxmpp.NS_COMMANDS) ] # a list of all commands exposed: node -> command class self._commands = {} if app.config.get('remote_commands'): for cmdobj in (ChangeStatusCommand, LeaveGroupchatsCommand): self._commands[cmdobj.commandnode] = cmdobj # a list of sessions; keys are tuples (jid, sessionid, node) self._sessions = {} def get_own_bare_jid(self): return self._con.get_own_jid().getStripped() def is_same_jid(self, jid): """ Test if the bare jid given is the same as our bare jid """ return nbxmpp.JID(jid).getStripped() == self.get_own_bare_jid() def command_list_query(self, stanza): iq = stanza.buildReply('result') jid = helpers.get_full_jid_from_iq(stanza) query = iq.getTag('query') # buildReply don't copy the node attribute. Re-add it query.setAttr('node', nbxmpp.NS_COMMANDS) for node, cmd in self._commands.items(): if cmd.is_visible_for(self.is_same_jid(jid)): query.addChild('item', { # TODO: find the jid 'jid': str(self._con.get_own_jid()), 'node': node, 'name': cmd.commandname}) self._con.connection.send(iq) def command_info_query(self, stanza): """ Send disco#info result for query for command (XEP-0050, example 6.). Return True if the result was sent, False if not """ try: jid = helpers.get_full_jid_from_iq(stanza) except helpers.InvalidFormat: log.warning('Invalid JID: %s, ignoring it', stanza.getFrom()) return node = stanza.getTagAttr('query', 'node') if node not in self._commands: return False cmd = self._commands[node] if cmd.is_visible_for(self.is_same_jid(jid)): iq = stanza.buildReply('result') query = iq.getTag('query') query.addChild('identity', attrs={'type': 'command-node', 'category': 'automation', 'name': cmd.commandname}) query.addChild('feature', attrs={'var': nbxmpp.NS_COMMANDS}) for feature in cmd.commandfeatures: query.addChild('feature', attrs={'var': feature}) self._con.connection.send(iq) return True return False def command_items_query(self, stanza): """ Send disco#items result for query for command. Return True if the result was sent, False if not. """ jid = helpers.get_full_jid_from_iq(stanza) node = stanza.getTagAttr('query', 'node') if node not in self._commands: return False cmd = self._commands[node] if cmd.is_visible_for(self.is_same_jid(jid)): iq = stanza.buildReply('result') self._con.connection.send(iq) return True return False def _execute_command_received(self, _con, stanza): jid = helpers.get_full_jid_from_iq(stanza) cmd = stanza.getTag('command') if cmd is None: log.error('Malformed stanza (no command node) %s', stanza) raise nbxmpp.NodeProcessed node = cmd.getAttr('node') if node is None: log.error('Malformed stanza (no node attr) %s', stanza) raise nbxmpp.NodeProcessed sessionid = cmd.getAttr('sessionid') if sessionid is None: # we start a new command session # only if we are visible for the jid and command exist if node not in self._commands.keys(): self._con.connection.send( nbxmpp.Error( stanza, nbxmpp.NS_STANZAS + ' item-not-found')) log.warning('Comand %s does not exist: %s', node, jid) raise nbxmpp.NodeProcessed newcmd = self._commands[node] if not newcmd.is_visible_for(self.is_same_jid(jid)): log.warning('Command not visible for jid: %s', jid) raise nbxmpp.NodeProcessed # generate new sessionid sessionid = self._con.connection.getAnID() # create new instance and run it obj = newcmd(conn=self, jid=jid, sessionid=sessionid) rc = obj.execute(stanza) if rc: self._sessions[(jid, sessionid, node)] = obj log.info('Comand %s executed: %s', node, jid) raise nbxmpp.NodeProcessed else: # the command is already running, check for it magictuple = (jid, sessionid, node) if magictuple not in self._sessions: # we don't have this session... ha! log.warning('Invalid session %s', magictuple) raise nbxmpp.NodeProcessed action = cmd.getAttr('action') obj = self._sessions[magictuple] try: if action == 'cancel': rc = obj.cancel(stanza) elif action == 'prev': rc = obj.prev(stanza) elif action == 'next': rc = obj.next(stanza) elif action == 'execute' or action is None: rc = obj.execute(stanza) elif action == 'complete': rc = obj.complete(stanza) else: # action is wrong. stop the session, send error raise AttributeError except AttributeError: # the command probably doesn't handle invoked action... # stop the session, return error del self._sessions[magictuple] log.warning('Wrong action %s %s', node, jid) raise nbxmpp.NodeProcessed # delete the session if rc is False if not rc: del self._sessions[magictuple] raise nbxmpp.NodeProcessed def request_command_list(self, jid): """ Request the command list. """ log.info('Request Command List: %s', jid) query = nbxmpp.Iq(typ='get', to=jid, queryNS=nbxmpp.NS_DISCO_ITEMS) query.setQuerynode(nbxmpp.NS_COMMANDS) self._con.connection.SendAndCallForResponse( query, self._command_list_received) def _command_list_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event( AdHocCommandError(None, conn=self._con, error=stanza.getError())) return items = stanza.getQueryPayload() commandlist = [] if items: commandlist = [ (t.getAttr('node'), t.getAttr('name')) for t in items ] log.info('Received: %s', commandlist) app.nec.push_incoming_event( AdHocCommandListReceived( None, conn=self._con, commandlist=commandlist)) def send_command(self, jid, node, session_id, form, action='execute'): """ Send the command with data form. Wait for reply """ log.info('Send Command: %s %s %s %s', jid, node, session_id, action) stanza = nbxmpp.Iq(typ='set', to=jid) cmdnode = stanza.addChild('command', namespace=nbxmpp.NS_COMMANDS, attrs={'node': node, 'action': action}) if session_id: cmdnode.setAttr('sessionid', session_id) if form: cmdnode.addChild(node=form.get_purged()) self._con.connection.SendAndCallForResponse( stanza, self._action_response_received) def _action_response_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event( AdHocCommandError(None, conn=self._con, error=stanza.getError())) return log.info('Received action response') command = stanza.getTag('command') app.nec.push_incoming_event( AdHocCommandActionResponse( None, conn=self._con, command=command)) def send_cancel(self, jid, node, session_id): """ Send the command with action='cancel' """ log.info('Cancel: %s %s %s', jid, node, session_id) stanza = nbxmpp.Iq(typ='set', to=jid) stanza.addChild('command', namespace=nbxmpp.NS_COMMANDS, attrs={ 'node': node, 'sessionid': session_id, 'action': 'cancel' }) self._con.connection.SendAndCallForResponse( stanza, self._cancel_result_received) @staticmethod def _cancel_result_received(stanza): if not nbxmpp.isResultNode(stanza): log.warning('Error: %s', stanza.getError()) else: log.info('Cancel successful') class AdHocCommandError(NetworkIncomingEvent): name = 'adhoc-command-error' class AdHocCommandListReceived(NetworkIncomingEvent): name = 'adhoc-command-list' class AdHocCommandActionResponse(NetworkIncomingEvent): name = 'adhoc-command-action-response' def get_instance(*args, **kwargs): return AdHocCommands(*args, **kwargs), 'AdHocCommands' gajim-gajim-1.1.3/gajim/common/modules/annotations.py000066400000000000000000000067141345766322700226550ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0145: Annotations from typing import Any from typing import Dict # pylint: disable=unused-import from typing import List # pylint: disable=unused-import from typing import Tuple import logging import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m.annotations') class Annotations: def __init__(self, con: ConnectionT) -> None: self._con = con self._account = con.name self._server = self._con.get_own_jid().getDomain() self.handlers = [] # type: List[Tuple[Any, ...]] self.annotations = {} # type: Dict[str, str] def get_annotations(self) -> None: if not app.account_is_connected(self._account): return log.info('Request annotations for %s', self._server) iq = nbxmpp.Iq(typ='get') iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE) iq2.addChild(name='storage', namespace='storage:rosternotes') self._con.connection.SendAndCallForResponse(iq, self._result_received) def _result_received(self, stanza: nbxmpp.Iq) -> None: if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) return log.info('Received annotations from %s', self._server) self.annotations = {} query = stanza.getTag('query') storage_node = query.getTag('storage') if storage_node is None: return notes = storage_node.getTags('note') if notes is None: return for note in notes: try: jid = helpers.parse_jid(note.getAttr('jid')) except helpers.InvalidFormat: log.warning('Invalid JID: %s, ignoring it', note.getAttr('jid')) continue self.annotations[jid] = note.getData() def store_annotations(self) -> None: if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='set') iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE) iq3 = iq2.addChild(name='storage', namespace='storage:rosternotes') for jid in self.annotations: if self.annotations[jid]: iq4 = iq3.addChild(name='note') iq4.setAttr('jid', jid) iq4.setData(self.annotations[jid]) self._con.connection.SendAndCallForResponse( iq, self._store_result_received) @staticmethod def _store_result_received(stanza: nbxmpp.Iq) -> None: if not nbxmpp.isResultNode(stanza): log.warning('Storing rosternotes failed: %s', stanza.getError()) return log.info('Storing rosternotes successful') def get_instance(*args: Any, **kwargs: Any) -> Tuple[Annotations, str]: return Annotations(*args, **kwargs), 'Annotations' gajim-gajim-1.1.3/gajim/common/modules/atom.py000066400000000000000000000150311345766322700212500ustar00rootroot00000000000000# Copyright (C) 2006 Jean-Marie Traissard # Tomasz Melcer # Copyright (C) 2006-2014 Yann Leboulanger # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ Atom (rfc 4287) feed parser, used to read data from atom-over-pubsub transports and services. Very simple. Actually implements only atom:entry. Implement more features if you need """ # XEP-0277: Microblogging over XMPP # Module is disabled for now because Gajim lacks a good UI for that # register the module in connection.py with register_module() to activate again import logging import time import nbxmpp from gajim.common.const import PEPEventType from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData log = logging.getLogger('gajim.c.m.atom') class AtomData(AbstractPEPData): type_ = PEPEventType.ATOM def __init__(self, atom): self.data = atom def get_entry(self): return self.data class Atom(AbstractPEPModule): name = 'atom' namespace = 'urn:xmpp:microblog:0' pep_class = AtomData store_publish = False _log = log def __init__(self, con): AbstractPEPModule.__init__(self, con, con.name) self.handlers = [] def _extract_info(self, item): entry = item.getTag('entry', namespace=nbxmpp.NS_ATOM) if entry is None: StanzaMalformed('no entry node') return OldEntry(node=entry) or None def _build_node(self, data): raise NotImplementedError class PersonConstruct(nbxmpp.Node): """ Not used for now, as we don't need authors/contributors in pubsub.com feeds. They rarely exist there """ def __init__(self, node): ''' Create person construct from node. ''' nbxmpp.Node.__init__(self, node=node) def get_name(self): return self.getTagData('name') name = property( get_name, None, None, '''Conveys a human-readable name for the person. Should not be None, although some badly generated atom feeds don't put anything here (this is non-standard behavior, still pubsub.com sometimes does that.)''') def get_uri(self): return self.getTagData('uri') uri = property( get_uri, None, None, '''Conveys an IRI associated with the person. Might be None when not set.''') def get_email(self): return self.getTagData('email') email = property( get_email, None, None, '''Conveys an e-mail address associated with the person. Might be None when not set.''') class Entry(nbxmpp.Node): def __init__(self, node=None): nbxmpp.Node.__init__(self, 'entry', node=node) def __repr__(self): return '' % self.getAttr('id') class OldEntry(nbxmpp.Node): """ Parser for feeds from pubsub.com. They use old Atom 0.3 format with their extensions """ def __init__(self, node=None): ''' Create new Atom 0.3 entry object. ''' nbxmpp.Node.__init__(self, 'entry', node=node) def __repr__(self): return '' % self.getAttr('id') def get_feed_title(self): """ Return title of feed, where the entry was created. The result is the feed name concatenated with source-feed title """ if self.parent is not None: main_feed = self.parent.getTagData('title') else: main_feed = None if self.getTag('feed') is not None: source_feed = self.getTag('feed').getTagData('title') else: source_feed = None if main_feed is not None and source_feed is not None: return '%s: %s' % (main_feed, source_feed) if main_feed is not None: return main_feed if source_feed is not None: return source_feed return '' feed_title = property( get_feed_title, None, None, ''' Title of feed. It is built from entry''s original feed title and title of feed which delivered this entry. ''') def get_feed_link(self): """ Get source link """ try: link = self.getTag('feed').getTags('link', {'rel': 'alternate'}) return link[1].getData() except Exception: return None feed_link = property( get_feed_link, None, None, ''' Link to main webpage of the feed. ''') def get_title(self): """ Get an entry's title """ return self.getTagData('title') title = property( get_title, None, None, ''' Entry's title. ''') def get_uri(self): """ Get the uri the entry points to (entry's first link element with rel='alternate' or without rel attribute) """ for element in self.getTags('link'): if 'rel' in element.attrs and element.attrs['rel'] != 'alternate': continue try: return element.attrs['href'] except AttributeError: pass return None uri = property( get_uri, None, None, ''' URI that is pointed by the entry. ''') def get_updated(self): """ Get the time the entry was updated last time This should be standarized, but pubsub.com sends it in human-readable format. We won't try to parse it. (Atom 0.3 uses the word «modified» for that). If there's no time given in the entry, we try with and elements. """ for name in ('updated', 'modified', 'published', 'issued'): date = self.getTagData(name) if date is not None: break if date is None: # it is not in the standard format return time.asctime() return date updated = property( get_updated, None, None, ''' Last significant modification time. ''') feed_tagline = '' gajim-gajim-1.1.3/gajim/common/modules/blocking.py000066400000000000000000000126671345766322700221140ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0191: Blocking Command import logging import nbxmpp from gajim.common import app from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.blocking') class Blocking: def __init__(self, con): self._con = con self._account = con.name self.blocked = [] self.handlers = [ ('iq', self._blocking_push_received, 'set', nbxmpp.NS_BLOCKING) ] self.supported = False def pass_disco(self, from_, _identities, features, _data, _node): if nbxmpp.NS_BLOCKING not in features: return self.supported = True log.info('Discovered blocking: %s', from_) def get_blocking_list(self) -> None: if not self.supported: return iq = nbxmpp.Iq('get', nbxmpp.NS_BLOCKING) iq.setQuery('blocklist') log.info('Request list') self._con.connection.SendAndCallForResponse( iq, self._blocking_list_received) def _blocking_list_received(self, stanza: nbxmpp.Iq) -> None: if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) return self.blocked = [] blocklist = stanza.getTag('blocklist', namespace=nbxmpp.NS_BLOCKING) if blocklist is None: log.error('No blocklist node') return for item in blocklist.getTags('item'): self.blocked.append(item.getAttr('jid')) log.info('Received list: %s', self.blocked) app.nec.push_incoming_event( BlockingEvent(None, conn=self._con, changed=self.blocked)) def _blocking_push_received(self, _con, stanza): reply = stanza.buildReply('result') childs = reply.getChildren() for child in childs: reply.delChild(child) self._con.connection.send(reply) changed_list = [] unblock = stanza.getTag('unblock', namespace=nbxmpp.NS_BLOCKING) if unblock is not None: items = unblock.getTags('item') if not items: # Unblock all changed_list = list(self.blocked) self.blocked = [] for jid in self.blocked: self._presence_probe(jid) log.info('Unblock all Push') raise nbxmpp.NodeProcessed for item in items: # Unblock some contacts jid = item.getAttr('jid') changed_list.append(jid) if jid not in self.blocked: continue self.blocked.remove(jid) self._presence_probe(jid) log.info('Unblock Push: %s', jid) block = stanza.getTag('block', namespace=nbxmpp.NS_BLOCKING) if block is not None: for item in block.getTags('item'): jid = item.getAttr('jid') if jid in self.blocked: continue changed_list.append(jid) self.blocked.append(jid) self._set_contact_offline(jid) log.info('Block Push: %s', jid) app.nec.push_incoming_event( BlockingEvent(None, conn=self._con, changed=changed_list)) raise nbxmpp.NodeProcessed def _set_contact_offline(self, jid: str) -> None: contact_list = app.contacts.get_contacts(self._account, jid) for contact in contact_list: contact.show = 'offline' def _presence_probe(self, jid: str) -> None: log.info('Presence probe: %s', jid) # Send a presence Probe to get the current Status probe = nbxmpp.Presence(jid, 'probe', frm=self._con.get_own_jid()) self._con.connection.send(probe) def block(self, contact_list): if not self.supported: return iq = nbxmpp.Iq('set', nbxmpp.NS_BLOCKING) query = iq.setQuery(name='block') for contact in contact_list: query.addChild(name='item', attrs={'jid': contact.jid}) log.info('Block: %s', contact.jid) self._con.connection.SendAndCallForResponse( iq, self._default_result_handler, {}) def unblock(self, contact_list): if not self.supported: return iq = nbxmpp.Iq('set', nbxmpp.NS_BLOCKING) query = iq.setQuery(name='unblock') for contact in contact_list: query.addChild(name='item', attrs={'jid': contact.jid}) log.info('Unblock: %s', contact.jid) self._con.connection.SendAndCallForResponse( iq, self._default_result_handler, {}) @staticmethod def _default_result_handler(_con, stanza): if not nbxmpp.isResultNode(stanza): log.warning('Operation failed: %s', stanza.getError()) class BlockingEvent(NetworkIncomingEvent): name = 'blocking' def get_instance(*args, **kwargs): return Blocking(*args, **kwargs), 'Blocking' gajim-gajim-1.1.3/gajim/common/modules/bookmarks.py000066400000000000000000000311061345766322700223010ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0048: Bookmarks import logging import copy from collections import OrderedDict import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.const import BookmarkStorageType from gajim.common.nec import NetworkIncomingEvent from gajim.common.modules.util import from_xs_boolean from gajim.common.modules.util import to_xs_boolean log = logging.getLogger('gajim.c.m.bookmarks') NS_GAJIM_BM = 'xmpp:gajim.org/bookmarks' class Bookmarks: def __init__(self, con): self._con = con self._account = con.name self.bookmarks = {} self.available = False self.handlers = [] def get_sorted_bookmarks(self, short_name=False): # This returns a sorted by name copy of the bookmarks sorted_bookmarks = {} for jid, bookmarks in self.bookmarks.items(): bookmark_copy = copy.deepcopy(bookmarks) if not bookmark_copy['name']: # No name was given for this bookmark # Use the first part of JID instead name = jid.split("@")[0] bookmark_copy['name'] = name if short_name: name = bookmark_copy['name'] name = (name[:42] + '..') if len(name) > 42 else name bookmark_copy['name'] = name sorted_bookmarks[jid] = bookmark_copy return OrderedDict( sorted(sorted_bookmarks.items(), key=lambda bookmark: bookmark[1]['name'].lower())) def _pubsub_support(self) -> bool: return (self._con.get_module('PEP').supported and self._con.get_module('PubSub').publish_options) def get_bookmarks(self, storage_type=None): if not app.account_is_connected(self._account): return if storage_type in (None, BookmarkStorageType.PUBSUB): if self._pubsub_support(): self._request_pubsub_bookmarks() else: # Fallback, request private storage self._request_private_bookmarks() else: log.info('Request Bookmarks (PrivateStorage)') self._request_private_bookmarks() def _request_pubsub_bookmarks(self) -> None: log.info('Request Bookmarks (PubSub)') self._con.get_module('PubSub').send_pb_retrieve( '', 'storage:bookmarks', cb=self._pubsub_bookmarks_received) def _pubsub_bookmarks_received(self, _con, stanza): if not nbxmpp.isResultNode(stanza): log.info('No pubsub bookmarks: %s', stanza.getError()) # Fallback, request private storage self._request_private_bookmarks() return self.available = True log.info('Received Bookmarks (PubSub)') self._parse_bookmarks(stanza) self._request_private_bookmarks() def _request_private_bookmarks(self) -> None: if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='get') query = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE) query.addChild(name='storage', namespace='storage:bookmarks') log.info('Request Bookmarks (PrivateStorage)') self._con.connection.SendAndCallForResponse( iq, self._private_bookmarks_received) def _private_bookmarks_received(self, stanza: nbxmpp.Iq) -> None: if not nbxmpp.isResultNode(stanza): log.info('No private bookmarks: %s', stanza.getError()) else: self.available = True log.info('Received Bookmarks (PrivateStorage)') merged = self._parse_bookmarks(stanza, check_merge=True) if merged and self._pubsub_support(): log.info('Merge PrivateStorage with PubSub') self.store_bookmarks(BookmarkStorageType.PUBSUB) self.auto_join_bookmarks() app.nec.push_incoming_event(BookmarksReceivedEvent( None, account=self._account)) @staticmethod def _get_storage_node(stanza): node = stanza.getTag('pubsub', namespace=nbxmpp.NS_PUBSUB) if node is None: node = stanza.getTag('event', namespace=nbxmpp.NS_PUBSUB_EVENT) if node is None: # Private Storage query = stanza.getQuery() if query is None: return storage = query.getTag('storage', namespace=nbxmpp.NS_BOOKMARKS) if storage is None: return return storage items_node = node.getTag('items') if items_node is None: return if items_node.getAttr('node') != nbxmpp.NS_BOOKMARKS: return item_node = items_node.getTag('item') if item_node is None: return storage = item_node.getTag('storage', namespace=nbxmpp.NS_BOOKMARKS) if storage is None: return return storage def _parse_bookmarks(self, stanza: nbxmpp.Iq, check_merge: bool = False) -> bool: merged = False storage = self._get_storage_node(stanza) if storage is None: return False confs = storage.getTags('conference') for conf in confs: autojoin_val = conf.getAttr('autojoin') if not autojoin_val: # not there (it's optional) autojoin_val = False minimize_val = conf.getTag('minimize', namespace=NS_GAJIM_BM) if not minimize_val: # not there, try old Gajim behaviour minimize_val = conf.getAttr('minimize') if not minimize_val: # not there (it's optional) minimize_val = False else: minimize_val = minimize_val.getData() print_status = conf.getTag('print_status', namespace=NS_GAJIM_BM) if not print_status: # not there, try old Gajim behaviour print_status = conf.getTagData('print_status') if not print_status: # not there, try old Gajim behaviour print_status = conf.getTagData('show_status') else: print_status = print_status.getData() try: jid = helpers.parse_jid(conf.getAttr('jid')) except helpers.InvalidFormat: log.warning('Invalid JID: %s, ignoring it', conf.getAttr('jid')) continue bookmark = { 'name': conf.getAttr('name'), 'password': conf.getTagData('password'), 'nick': conf.getTagData('nick'), 'print_status': print_status } try: bookmark['autojoin'] = from_xs_boolean(autojoin_val) bookmark['minimize'] = from_xs_boolean(minimize_val) except ValueError as error: log.warning(error) continue if check_merge: if jid in self.bookmarks: continue merged = True log.debug('Found Bookmark: %s', jid) self.bookmarks[jid] = bookmark return merged def _build_storage_node(self) -> nbxmpp.Node: storage_node = nbxmpp.Node( tag='storage', attrs={'xmlns': 'storage:bookmarks'}) for jid, bm in self.bookmarks.items(): conf_node = storage_node.addChild(name="conference") conf_node.setAttr('jid', jid) conf_node.setAttr('autojoin', to_xs_boolean(bm['autojoin'])) conf_node.setAttr('name', bm['name']) conf_node.setTag('minimize', namespace=NS_GAJIM_BM).setData( to_xs_boolean(bm['minimize'])) # Only add optional elements if not empty # Note: need to handle both None and '' as empty # thus shouldn't use "is not None" if bm.get('nick', None): conf_node.setTagData('nick', bm['nick']) if bm.get('password', None): conf_node.setTagData('password', bm['password']) if bm.get('print_status', None): conf_node.setTag( 'print_status', namespace=NS_GAJIM_BM).setData(bm['print_status']) return storage_node @staticmethod def get_bookmark_publish_options() -> nbxmpp.Node: options = nbxmpp.Node(nbxmpp.NS_DATA + ' x', attrs={'type': 'submit'}) field = options.addChild('field', attrs={'var': 'FORM_TYPE', 'type': 'hidden'}) field.setTagData('value', nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS) field = options.addChild('field', attrs={'var': 'pubsub#access_model'}) field.setTagData('value', 'whitelist') return options def store_bookmarks(self, storage_type=None): if not app.account_is_connected(self._account): return storage_node = self._build_storage_node() if storage_type is None: if self._pubsub_support(): self._pubsub_store(storage_node) self._private_store(storage_node) elif storage_type == BookmarkStorageType.PUBSUB: if self._pubsub_support(): self._pubsub_store(storage_node) elif storage_type == BookmarkStorageType.PRIVATE: self._private_store(storage_node) def _pubsub_store(self, storage_node: nbxmpp.Node) -> None: self._con.get_module('PubSub').send_pb_publish( '', 'storage:bookmarks', storage_node, 'current', options=self.get_bookmark_publish_options(), cb=self._pubsub_store_result) log.info('Publish Bookmarks (PubSub)') def _private_store(self, storage_node: nbxmpp.Node) -> None: iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVATE, payload=storage_node) log.info('Publish Bookmarks (PrivateStorage)') self._con.connection.SendAndCallForResponse( iq, self._private_store_result) @staticmethod def _pubsub_store_result(_con, stanza): if not nbxmpp.isResultNode(stanza): log.error('Error: %s', stanza.getError()) return @staticmethod def _private_store_result(stanza: nbxmpp.Iq) -> None: if not nbxmpp.isResultNode(stanza): log.error('Error: %s', stanza.getError()) return def auto_join_bookmarks(self) -> None: if app.is_invisible(self._account): return for jid, bm in self.bookmarks.items(): if bm['autojoin']: # Only join non-opened groupchats. Opened one are already # auto-joined on re-connection if jid not in app.gc_connected[self._account]: # we are not already connected app.interface.join_gc_room( self._account, jid, bm['nick'], bm['password'], minimize=bm['minimize']) def add_bookmark(self, name, jid, autojoin, minimize, password, nick): self.bookmarks[jid] = { 'name': name, 'autojoin': autojoin, 'minimize': minimize, 'password': password, 'nick': nick, 'print_status': None} self.store_bookmarks() app.nec.push_incoming_event(BookmarksReceivedEvent( None, account=self._account)) def get_name_from_bookmark(self, jid: str) -> str: fallback = jid.split('@')[0] try: return self.bookmarks[jid]['name'] or fallback except KeyError: return fallback def purge_pubsub_bookmarks(self) -> None: log.info('Purge/Delete Bookmarks on PubSub, ' 'because publish options are not available') self._con.get_module('PubSub').send_pb_purge('', 'storage:bookmarks') self._con.get_module('PubSub').send_pb_delete('', 'storage:bookmarks') class BookmarksReceivedEvent(NetworkIncomingEvent): name = 'bookmarks-received' def get_instance(*args, **kwargs): return Bookmarks(*args, **kwargs), 'Bookmarks' gajim-gajim-1.1.3/gajim/common/modules/caps.py000066400000000000000000000132361345766322700212430ustar00rootroot00000000000000# Copyright (C) 2009 Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0115: Entity Capabilities import logging import nbxmpp from gajim.common import caps_cache from gajim.common import app from gajim.common.nec import NetworkEvent from gajim.common.modules.presence import parse_show from gajim.common.modules.presence import parse_type log = logging.getLogger('gajim.c.m.caps') class Caps: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('presence', self._presence_received, '', nbxmpp.NS_CAPS) ] self._capscache = caps_cache.capscache self._create_suitable_client_caps = caps_cache.create_suitable_client_caps def _presence_received(self, _con, stanza): if stanza.getType() in ('unavailable', 'error'): return from_ = stanza.getFrom() if from_ is None: # Presence from ourself return full_jid = str(from_) hash_method = node = caps_hash = None caps = stanza.getTag('c', namespace=nbxmpp.NS_CAPS) if caps is not None: hash_method = caps['hash'] node = caps['node'] caps_hash = caps['ver'] show = parse_show(stanza) type_ = parse_type(stanza) log.info('Received from %s, type: %s, method: %s, node: %s, hash: %s', from_, stanza.getType(), hash_method, node, caps_hash) client_caps = self._create_suitable_client_caps( node, caps_hash, hash_method, full_jid) # Type is None means 'available' if stanza.getType() is None and client_caps._hash_method == 'no': self._capscache.forget_caps(client_caps) client_caps = self._create_suitable_client_caps( node, caps_hash, hash_method) else: self._capscache.query_client_of_jid_if_unknown( self._con, full_jid, client_caps) self._update_client_caps_of_contact(from_, client_caps) # Event is only used by ClientIcons Plugin app.nec.push_incoming_event( NetworkEvent('caps-presence-received', conn=self._con, fjid=full_jid, jid=from_.getStripped(), resource=from_.getResource(), hash_method=hash_method, node=node, caps_hash=caps_hash, client_caps=client_caps, show=show, ptype=type_, stanza=stanza)) app.nec.push_incoming_event(NetworkEvent('caps-update', conn=self._con, fjid=full_jid, jid=from_.getStripped())) def _update_client_caps_of_contact(self, from_, client_caps): contact = self._get_contact_or_gc_contact_for_jid(from_) if contact is not None: contact.client_caps = client_caps else: log.info('Received Caps from unknown contact %s', from_) def _get_contact_or_gc_contact_for_jid(self, from_): contact = app.contacts.get_contact_from_full_jid(self._account, str(from_)) if contact is None: room_jid, resource = from_.getStripped(), from_.getResource() contact = app.contacts.get_gc_contact( self._account, room_jid, resource) return contact def contact_info_received(self, from_, identities, features, data, node): """ callback to update our caps cache with queried information after we have retrieved an unknown caps hash via a disco """ bare_jid = from_.getStripped() contact = self._get_contact_or_gc_contact_for_jid(from_) if not contact: log.info('Received Disco from unknown contact %s', from_) return lookup = contact.client_caps.get_cache_lookup_strategy() cache_item = lookup(self._capscache) if cache_item.is_valid(): # we already know that the hash is fine and have already cached # the identities and features return validate = contact.client_caps.get_hash_validation_strategy() hash_is_valid = validate(identities, features, data) if hash_is_valid: cache_item.set_and_store(identities, features) else: node = caps_hash = hash_method = None contact.client_caps = self._create_suitable_client_caps( node, caps_hash, hash_method) log.warning( 'Computed and retrieved caps hash differ. Ignoring ' 'caps of contact %s', contact.get_full_jid()) app.nec.push_incoming_event( NetworkEvent('caps-update', conn=self._con, fjid=str(from_), jid=bare_jid)) def get_instance(*args, **kwargs): return Caps(*args, **kwargs), 'Caps' gajim-gajim-1.1.3/gajim/common/modules/carbons.py000066400000000000000000000066361345766322700217520ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0280: Message Carbons import logging import nbxmpp from gajim.common import app log = logging.getLogger('gajim.c.m.carbons') class Carbons: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] self.supported = False def pass_disco(self, from_, _identities, features, _data, _node): if nbxmpp.NS_CARBONS not in features: return self.supported = True log.info('Discovered carbons: %s', from_) if app.config.get_per('accounts', self._account, 'enable_message_carbons'): iq = nbxmpp.Iq('set') iq.setTag('enable', namespace=nbxmpp.NS_CARBONS) log.info('Activate') self._con.connection.send(iq) else: log.warning('Carbons deactivated (user setting)') def parse_carbon(con, stanza): carbon = stanza.getTag( 'received', namespace=nbxmpp.NS_CARBONS, protocol=True) if carbon is None: carbon = stanza.getTag( 'sent', namespace=nbxmpp.NS_CARBONS, protocol=True) if carbon is None: return stanza, False, False # Carbon must be from our bare jid own_jid = con.get_own_jid() if not stanza.getFrom().bareMatch(own_jid): log.warning('Ignore message because from is invalid %s', stanza.getFrom()) raise nbxmpp.NodeProcessed forwarded = carbon.getTag('forwarded', namespace=nbxmpp.NS_FORWARD, protocol=True) message = forwarded.getTag('message', protocol=True) type_ = carbon.getName() to = message.getTo() frm = message.getFrom() log.info('Received type: %s, from: %s', type_, frm) if type_ == 'received': sent = False if message.getFrom().bareMatch(own_jid): # Drop 'received' Carbons from ourself, we already # got the message with the 'sent' Carbon or via the # message itself log.info('Drop "received"-Carbon from ourself: %s') raise nbxmpp.NodeProcessed if message.getTag('x', namespace=nbxmpp.NS_MUC_USER) is not None: # A MUC broadcasts messages sent to us to all resources # there is no need to process carbons for these messages log.info('Drop MUC-PM "received"-Carbon') raise nbxmpp.NodeProcessed elif type_ == 'sent': if frm is None: frm = own_jid.getStripped() message.setTo(frm) if to is None: to = own_jid.getStripped() message.setFrom(to) sent = True else: log.warning('Ignore invalid carbon: %s', stanza) raise nbxmpp.NodeProcessed return message, sent, True def get_instance(*args, **kwargs): return Carbons(*args, **kwargs), 'Carbons' gajim-gajim-1.1.3/gajim/common/modules/chatstates.py000066400000000000000000000244241345766322700224610ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0085: Chat State Notifications from typing import Any from typing import Dict # pylint: disable=unused-import from typing import Optional from typing import Tuple import time import logging import nbxmpp from gi.repository import GLib from gajim.common import app from gajim.common.nec import NetworkEvent from gajim.common.const import Chatstate as State from gajim.common.modules.misc import parse_delay from gajim.common.connection_handlers_events import MessageOutgoingEvent from gajim.common.connection_handlers_events import GcMessageOutgoingEvent from gajim.common.types import ContactT from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m.chatstates') INACTIVE_AFTER = 60 PAUSED_AFTER = 5 def parse_chatstate(stanza: nbxmpp.Message) -> Optional[str]: if parse_delay(stanza) is not None: return None children = stanza.getChildren() for child in children: if child.getNamespace() == nbxmpp.NS_CHATSTATES: return child.getName() return None class Chatstate: def __init__(self, con: ConnectionT) -> None: self._con = con self._account = con.name self.handlers = [ ('presence', self._presence_received), ] self._chatstates = {} # type: Dict[str, State] self._last_keyboard_activity = {} # type: Dict[str, float] self._last_mouse_activity = {} # type: Dict[str, float] self._timeout_id = GLib.timeout_add_seconds( 2, self._check_last_interaction) def _presence_received(self, _con: ConnectionT, stanza: nbxmpp.Presence) -> None: if stanza.getType() not in ('unavailable', 'error'): return full_jid = stanza.getFrom() if full_jid is None or self._con.get_own_jid().bareMatch(full_jid): # Presence from ourself return contact = app.contacts.get_gc_contact( self._account, full_jid.getStripped(), full_jid.getResource()) if contact is None: contact = app.contacts.get_contact_from_full_jid( self._account, str(full_jid)) if contact is None: return if contact.chatstate is None: return if contact.is_gc_contact: jid = contact.get_full_jid() else: jid = contact.jid contact.chatstate = None self._chatstates.pop(jid, None) self._last_mouse_activity.pop(jid, None) self._last_keyboard_activity.pop(jid, None) log.info('Reset chatstate for %s', jid) app.nec.push_outgoing_event( NetworkEvent('chatstate-received', account=self._account, contact=contact)) def delegate(self, event: Any) -> None: if self._con.get_own_jid().bareMatch(event.jid) or event.sent: # Dont show chatstates from our own resources return if event.mtype == 'groupchat': # Not implemented yet return chatstate = parse_chatstate(event.stanza) if chatstate is None: return if event.muc_pm: contact = app.contacts.get_gc_contact( self._account, event.jid, event.resource) else: contact = app.contacts.get_contact_from_full_jid( self._account, event.fjid) if contact is None: return contact.chatstate = chatstate log.info('Recv: %-10s - %s', chatstate, event.fjid) app.nec.push_outgoing_event( NetworkEvent('chatstate-received', account=self._account, contact=contact)) def _check_last_interaction(self) -> GLib.SOURCE_CONTINUE: setting = app.config.get('outgoing_chat_state_notifications') if setting in ('composing_only', 'disabled'): return GLib.SOURCE_CONTINUE now = time.time() for jid in list(self._last_mouse_activity.keys()): time_ = self._last_mouse_activity[jid] current_state = self._chatstates.get(jid) if current_state is None: self._last_mouse_activity.pop(jid, None) self._last_keyboard_activity.pop(jid, None) continue if current_state in (State.GONE, State.INACTIVE): continue new_chatstate = None if now - time_ > INACTIVE_AFTER: new_chatstate = State.INACTIVE elif current_state == State.COMPOSING: key_time = self._last_keyboard_activity[jid] if now - key_time > PAUSED_AFTER: new_chatstate = State.PAUSED if new_chatstate is not None: if self._chatstates.get(jid) != new_chatstate: contact = app.contacts.get_contact(self._account, jid) if contact is None: room, nick = app.get_room_and_nick_from_fjid(jid) contact = app.contacts.get_gc_contact( self._account, room, nick) if contact is not None: contact = contact.as_contact() else: # Contact not found, maybe we left the group chat # or the contact was removed from the roster log.info( 'Contact %s not found, reset chatstate', jid) self._chatstates.pop(jid, None) self._last_mouse_activity.pop(jid, None) self._last_keyboard_activity.pop(jid, None) continue self.set_chatstate(contact, new_chatstate) return GLib.SOURCE_CONTINUE def set_active(self, jid: str) -> None: self._last_mouse_activity[jid] = time.time() setting = app.config.get('outgoing_chat_state_notifications') if setting == 'disabled': return self._chatstates[jid] = State.ACTIVE def get_active_chatstate(self, contact: ContactT) -> Optional[str]: # determines if we add 'active' on outgoing messages setting = app.config.get('outgoing_chat_state_notifications') if setting == 'disabled': return None if not contact.is_groupchat(): # Dont send chatstates to ourself if self._con.get_own_jid().bareMatch(contact.jid): return None if not contact.supports(nbxmpp.NS_CHATSTATES): return None self.set_active(contact.jid) return 'active' def set_chatstate(self, contact: ContactT, state: State) -> None: current_state = self._chatstates.get(contact.jid) setting = app.config.get('outgoing_chat_state_notifications') if setting == 'disabled': # Send a last 'active' state after user disabled chatstates if current_state is not None: log.info('Send: %-10s - %s', State.ACTIVE, contact.jid) event_attrs = {'account': self._account, 'jid': contact.jid, 'chatstate': str(State.ACTIVE)} if contact.is_groupchat(): app.nec.push_outgoing_event( GcMessageOutgoingEvent(None, **event_attrs)) else: app.nec.push_outgoing_event( MessageOutgoingEvent(None, **event_attrs)) self._chatstates.pop(contact.jid, None) self._last_mouse_activity.pop(contact.jid, None) self._last_keyboard_activity.pop(contact.jid, None) return if not contact.is_groupchat(): # Dont leak presence to contacts # which are not allowed to see our status if not contact.is_pm_contact: if contact and contact.sub in ('to', 'none'): return if contact.show == 'offline': return if not contact.supports(nbxmpp.NS_CHATSTATES): return if state in (State.ACTIVE, State.COMPOSING): self._last_mouse_activity[contact.jid] = time.time() if setting == 'composing_only': if state in (State.INACTIVE, State.GONE, State.PAUSED): state = State.ACTIVE if current_state == state: return # Dont send chatstates to ourself if self._con.get_own_jid().bareMatch(contact.jid): return log.info('Send: %-10s - %s', state, contact.jid) event_attrs = {'account': self._account, 'jid': contact.jid, 'chatstate': str(state)} if contact.is_groupchat(): app.nec.push_outgoing_event( GcMessageOutgoingEvent(None, **event_attrs)) else: app.nec.push_outgoing_event( MessageOutgoingEvent(None, **event_attrs)) self._chatstates[contact.jid] = state def set_mouse_activity(self, contact: ContactT) -> None: self._last_mouse_activity[contact.jid] = time.time() setting = app.config.get('outgoing_chat_state_notifications') if setting == 'disabled': return if self._chatstates.get(contact.jid) == State.INACTIVE: self.set_chatstate(contact, State.ACTIVE) def set_keyboard_activity(self, contact: ContactT) -> None: self._last_keyboard_activity[contact.jid] = time.time() def cleanup(self): GLib.source_remove(self._timeout_id) def get_instance(*args: Any, **kwargs: Any) -> Tuple[Chatstate, str]: return Chatstate(*args, **kwargs), 'Chatstate' gajim-gajim-1.1.3/gajim/common/modules/dataforms.py000066400000000000000000000471121345766322700222750ustar00rootroot00000000000000# Copyright (C) 2006-2007 Tomasz Melcer # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0004: Data Forms import nbxmpp from gajim.common import helpers # exceptions used in this module class Error(Exception): pass # when we get nbxmpp.Node which we do not understand class UnknownDataForm(Error): pass # when we get nbxmpp.Node which contains bad fields class WrongFieldValue(Error): pass # helper class to change class of already existing object class ExtendedNode(nbxmpp.Node): @classmethod def __new__(cls, *args, **kwargs): if 'extend' not in kwargs.keys() or not kwargs['extend']: return object.__new__(cls) extend = kwargs['extend'] assert issubclass(cls, extend.__class__) extend.__class__ = cls return extend # helper to create fields from scratch def create_field(typ, **attrs): ''' Helper function to create a field of given type. ''' field = { 'boolean': BooleanField, 'fixed': StringField, 'hidden': StringField, 'text-private': StringField, 'text-single': StringField, 'jid-multi': JidMultiField, 'jid-single': JidSingleField, 'list-multi': ListMultiField, 'list-single': ListSingleField, 'text-multi': TextMultiField, }[typ](typ=typ, **attrs) return field def extend_field(node): """ Helper function to extend a node to field of appropriate type """ # when validation (XEP-122) will go in, we could have another classes # like DateTimeField - so that dicts in create_field() and # extend_field() will be different... typ = node.getAttr('type') field = { 'boolean': BooleanField, 'fixed': StringField, 'hidden': StringField, 'text-private': StringField, 'text-single': StringField, 'jid-multi': JidMultiField, 'jid-single': JidSingleField, 'list-multi': ListMultiField, 'list-single': ListSingleField, 'text-multi': TextMultiField, } if typ not in field: typ = 'text-single' return field[typ](extend=node) def extend_form(node): """ Helper function to extend a node to form of appropriate type """ if node.getTag('reported') is not None: return MultipleDataForm(extend=node) return SimpleDataForm(extend=node) class DataField(ExtendedNode): """ Keeps data about one field - var, field type, labels, instructions... Base class for different kinds of fields. Use create_field() function to construct one of these """ def __init__(self, typ=None, var=None, value=None, label=None, desc=None, required=False, options=None, extend=None): if extend is None: ExtendedNode.__init__(self, 'field') self.type_ = typ self.var = var if value is not None: self.value = value if label is not None: self.label = label if desc is not None: self.desc = desc self.required = required self.options = options @property def type_(self): """ Type of field. Recognized values are: 'boolean', 'fixed', 'hidden', 'jid-multi', 'jid-single', 'list-multi', 'list-single', 'text-multi', 'text-private', 'text-single'. If you set this to something different, DataField will store given name, but treat all data as text-single """ type_ = self.getAttr('type') if type_ is None: return 'text-single' return type_ @type_.setter def type_(self, value): assert isinstance(value, str) self.setAttr('type', value) @property def var(self): """ Field identifier """ return self.getAttr('var') @var.setter def var(self, value): assert isinstance(value, str) self.setAttr('var', value) @var.deleter def var(self): self.delAttr('var') @property def label(self): """ Human-readable field name """ label_ = self.getAttr('label') if not label_: label_ = self.var return label_ @label.setter def label(self, value): assert isinstance(value, str) self.setAttr('label', value) @label.deleter def label(self): if self.getAttr('label'): self.delAttr('label') @property def description(self): """ Human-readable description of field meaning """ return self.getTagData('desc') or '' @description.setter def description(self, value): assert isinstance(value, str) if value == '': del self.description else: self.setTagData('desc', value) @description.deleter def description(self): desc = self.getTag('desc') if desc is not None: self.delChild(desc) @property def required(self): """ Controls whether this field required to fill. Boolean """ return bool(self.getTag('required')) @required.setter def required(self, value): required = self.getTag('required') if required and not value: self.delChild(required) elif not required and value: self.addChild('required') @property def media(self): """ Media data """ media = self.getTag('media', namespace=nbxmpp.NS_DATA_MEDIA) if media: return Media(media) @media.setter def media(self, value): del self.media self.addChild(node=value) @media.deleter def media(self): media = self.getTag('media') if media is not None: self.delChild(media) @staticmethod def is_valid(): return True class Uri(nbxmpp.Node): def __init__(self, uri_tag): nbxmpp.Node.__init__(self, node=uri_tag) @property def type_(self): """ uri type """ return self.getAttr('type') @type_.setter def type_(self, value): self.setAttr('type', value) @type_.deleter def type_(self): self.delAttr('type') @property def uri_data(self): """ uri data """ return self.getData() @uri_data.setter def uri_data(self, value): self.setData(value) @uri_data.deleter def uri_data(self): self.setData(None) class Media(nbxmpp.Node): def __init__(self, media_tag): nbxmpp.Node.__init__(self, node=media_tag) @property def uris(self): """ URIs of the media element. """ return map(Uri, self.getTags('uri')) @uris.setter def uris(self, value): del self.uris for uri in value: self.addChild(node=uri) @uris.deleter def uris(self): for element in self.getTags('uri'): self.delChild(element) class BooleanField(DataField): @property def value(self): """ Value of field. May contain True, False or None """ value = self.getTagData('value') if value in ('0', 'false'): return False if value in ('1', 'true'): return True if value is None: return False # default value is False raise WrongFieldValue @value.setter def value(self, value): self.setTagData('value', value and '1' or '0') @value.deleter def value(self): value = self.getTag('value') if value is not None: self.delChild(value) class StringField(DataField): """ Covers fields of types: fixed, hidden, text-private, text-single """ @property def value(self): """ Value of field. May be any string """ return self.getTagData('value') or '' @value.setter def value(self, value): assert isinstance(value, str) if value == '' and not self.required: del self.value return self.setTagData('value', value) @value.deleter def value(self): try: self.delChild(self.getTag('value')) except ValueError: # if there already were no value tag pass class ListField(DataField): """ Covers fields of types: jid-multi, jid-single, list-multi, list-single """ @property def options(self): """ Options """ options = [] for element in self.getTags('option'): value = element.getTagData('value') if value is None: raise WrongFieldValue label = element.getAttr('label') if not label: label = value options.append((label, value)) return options @options.setter def options(self, values): del self.options for value, label in values: self.addChild('option', {'label': label}).setTagData('value', value) @options.deleter def options(self): for element in self.getTags('option'): self.delChild(element) def iter_options(self): for element in self.iterTags('option'): value = element.getTagData('value') if value is None: raise WrongFieldValue label = element.getAttr('label') if not label: label = value yield (value, label) class ListSingleField(ListField, StringField): """ Covers list-single field """ def is_valid(self): if not self.required: return True if not self.value: return False return True class JidSingleField(ListSingleField): """ Covers jid-single fields """ def is_valid(self): if self.value: try: helpers.parse_jid(self.value) return True except Exception: return False if self.required: return False return True class ListMultiField(ListField): """ Covers list-multi fields """ @property def values(self): """ Values held in field """ values = [] for element in self.getTags('value'): values.append(element.getData()) return values @values.setter def values(self, values): del self.values for value in values: self.addChild('value').setData(value) @values.deleter def values(self): for element in self.getTags('value'): self.delChild(element) def iter_values(self): for element in self.getTags('value'): yield element.getData() def is_valid(self): if not self.required: return True if not self.values: return False return True class JidMultiField(ListMultiField): """ Covers jid-multi fields """ def is_valid(self): if self.values: for value in self.values: try: helpers.parse_jid(value) except Exception: return False return True if self.required: return False return True class TextMultiField(DataField): @property def value(self): """ Value held in field """ value = '' for element in self.iterTags('value'): value += '\n' + element.getData() return value[1:] @value.setter def value(self, value): del self.value if value == '': return for line in value.split('\n'): self.addChild('value').setData(line) @value.deleter def value(self): for element in self.getTags('value'): self.delChild(element) class DataRecord(ExtendedNode): """ The container for data fields - an xml element which has DataField elements as children """ def __init__(self, fields=None, associated=None, extend=None): self.associated = associated self.vars = {} if extend is None: # we have to build this object from scratch nbxmpp.Node.__init__(self) if fields is not None: self.fields = fields else: # we already have nbxmpp.Node inside - try to convert all # fields into DataField objects if fields is None: for field in self.iterTags('field'): if not isinstance(field, DataField): extend_field(field) self.vars[field.var] = field else: for field in self.getTags('field'): self.delChild(field) self.fields = fields @property def fields(self): """ List of fields in this record """ return self.getTags('field') @fields.setter def fields(self, fields): del self.fields for field in fields: if not isinstance(field, DataField): extend_field(field) self.addChild(node=field) @fields.deleter def fields(self): for element in self.getTags('field'): self.delChild(element) def iter_fields(self): """ Iterate over fields in this record. Do not take associated into account """ for field in self.iterTags('field'): yield field def iter_with_associated(self): """ Iterate over associated, yielding both our field and associated one together """ for field in self.associated.iter_fields(): yield self[field.var], field def __getitem__(self, item): return self.vars[item] def is_valid(self): for field in self.iter_fields(): if not field.is_valid(): return False return True class DataForm(ExtendedNode): def __init__(self, type_=None, title=None, instructions=None, extend=None): if extend is None: # we have to build form from scratch nbxmpp.Node.__init__(self, 'x', attrs={'xmlns': nbxmpp.NS_DATA}) if type_ is not None: self.type_ = type_ if title is not None: self.title = title if instructions is not None: self.instructions = instructions @property def type_(self): """ Type of the form. Must be one of: 'form', 'submit', 'cancel', 'result'. 'form' - this form is to be filled in; you will be able soon to do: filledform = DataForm(replyto=thisform) """ return self.getAttr('type') @type_.setter def type_(self, type_): assert type_ in ('form', 'submit', 'cancel', 'result') self.setAttr('type', type_) @property def title(self): """ Title of the form Human-readable, should not contain any \\r\\n. """ return self.getTagData('title') @title.setter def title(self, title): self.setTagData('title', title) @title.deleter def title(self): try: self.delChild('title') except ValueError: pass @property def instructions(self): """ Instructions for this form Human-readable, may contain \\r\\n. """ # TODO: the same code is in TextMultiField. join them value = '' for valuenode in self.getTags('instructions'): value += '\n' + valuenode.getData() return value[1:] @instructions.setter def instructions(self, value): del self.instructions if value == '': return for line in value.split('\n'): self.addChild('instructions').setData(line) @instructions.deleter def instructions(self): for value in self.getTags('instructions'): self.delChild(value) class SimpleDataForm(DataForm, DataRecord): def __init__(self, type_=None, title=None, instructions=None, fields=None, extend=None): DataForm.__init__(self, type_=type_, title=title, instructions=instructions, extend=extend) DataRecord.__init__(self, fields=fields, extend=self, associated=self) def get_purged(self): simple_form = SimpleDataForm(extend=self) del simple_form.title simple_form.instructions = '' to_be_removed = [] for field in simple_form.iter_fields(): if field.required: # add if there is not if hasattr(field, 'value') and not field.value: field.value = '' # Keep all required fields continue if ((hasattr(field, 'value') and not field.value and field.value != 0) or (hasattr(field, 'values') and not field.values)): to_be_removed.append(field) else: del field.label del field.description del field.media for field in to_be_removed: simple_form.delChild(field) return simple_form class MultipleDataForm(DataForm): def __init__(self, type_=None, title=None, instructions=None, items=None, extend=None): DataForm.__init__(self, type_=type_, title=title, instructions=instructions, extend=extend) # all records, recorded into DataRecords if extend is None: if items is not None: self.items = items else: # we already have nbxmpp.Node inside - try to convert all # fields into DataField objects if items is None: self.items = list(self.iterTags('item')) else: for item in self.getTags('item'): self.delChild(item) self.items = items reported_tag = self.getTag('reported') self.reported = DataRecord(extend=reported_tag) @property def items(self): """ A list of all records """ return list(self.iter_records()) @items.setter def items(self, records): del self.items for record in records: if not isinstance(record, DataRecord): DataRecord(extend=record) self.addChild(node=record) @items.deleter def items(self): for record in self.getTags('item'): self.delChild(record) def iter_records(self): for record in self.getTags('item'): yield record # @property # def reported(self): # """ # DataRecord that contains descriptions of fields in records # """ # return self.getTag('reported') # # @reported.setter # def reported(self, record): # try: # self.delChild('reported') # except Exception: # pass # # record.setName('reported') # self.addChild(node=record) gajim-gajim-1.1.3/gajim/common/modules/date_and_time.py000066400000000000000000000131151345766322700230660ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0082: XMPP Date and Time Profiles import re import time import logging from datetime import datetime from datetime import timedelta from datetime import timezone from datetime import tzinfo log = logging.getLogger('gajim.c.m.date_and_time') PATTERN_DATETIME = re.compile( r'([0-9]{4}-[0-9]{2}-[0-9]{2})' r'T' r'([0-9]{2}:[0-9]{2}:[0-9]{2})' r'(\.[0-9]{0,6})?' r'(?:[0-9]+)?' r'(?:(Z)|(?:([-+][0-9]{2}):([0-9]{2})))$' ) PATTERN_DELAY = re.compile( r'([0-9]{4}-[0-9]{2}-[0-9]{2})' r'T' r'([0-9]{2}:[0-9]{2}:[0-9]{2})' r'(\.[0-9]{0,6})?' r'(?:[0-9]+)?' r'(?:(Z)|(?:([-+][0]{2}):([0]{2})))$' ) ZERO = timedelta(0) HOUR = timedelta(hours=1) SECOND = timedelta(seconds=1) STDOFFSET = timedelta(seconds=-time.timezone) if time.daylight: DSTOFFSET = timedelta(seconds=-time.altzone) else: DSTOFFSET = STDOFFSET DSTDIFF = DSTOFFSET - STDOFFSET class LocalTimezone(tzinfo): ''' A class capturing the platform's idea of local time. May result in wrong values on historical times in timezones where UTC offset and/or the DST rules had changed in the past. ''' def fromutc(self, dt): assert dt.tzinfo is self stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND args = time.localtime(stamp)[:6] dst_diff = DSTDIFF // SECOND # Detect fold fold = (args == time.localtime(stamp - dst_diff)) return datetime(*args, microsecond=dt.microsecond, tzinfo=self, fold=fold) def utcoffset(self, dt): if self._isdst(dt): return DSTOFFSET return STDOFFSET def dst(self, dt): if self._isdst(dt): return DSTDIFF return ZERO def tzname(self, dt): return 'local' @staticmethod def _isdst(dt): tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, 0) stamp = time.mktime(tt) tt = time.localtime(stamp) return tt.tm_isdst > 0 def create_tzinfo(hours=0, minutes=0, tz_string=None): if tz_string is None: return timezone(timedelta(hours=hours, minutes=minutes)) if tz_string.lower() == 'z': return timezone.utc try: hours, minutes = map(int, tz_string.split(':')) except Exception: log.warning('Wrong tz string: %s', tz_string) return if hours not in range(-24, 24): log.warning('Wrong tz string: %s', tz_string) return if minutes not in range(0, 59): log.warning('Wrong tz string: %s', tz_string) return if hours in (24, -24) and minutes != 0: log.warning('Wrong tz string: %s', tz_string) return return timezone(timedelta(hours=hours, minutes=minutes)) def parse_datetime(timestring, check_utc=False, convert='utc', epoch=False): ''' Parse a XEP-0082 DateTime Profile String :param timestring: a XEP-0082 DateTime profile formated string :param check_utc: if True, returns None if timestring is not a timestring expressing UTC :param convert: convert the given timestring to utc or local time :param epoch: if True, returns the time in epoch Examples: '2017-11-05T01:41:20Z' '2017-11-05T01:41:20.123Z' '2017-11-05T01:41:20.123+05:00' return a datetime or epoch ''' if convert not in (None, 'utc', 'local'): raise TypeError('"%s" is not a valid value for convert') if check_utc: match = PATTERN_DELAY.match(timestring) else: match = PATTERN_DATETIME.match(timestring) if match: timestring = ''.join(match.groups('')) strformat = '%Y-%m-%d%H:%M:%S%z' if match.group(3): # Fractional second addendum to Time strformat = '%Y-%m-%d%H:%M:%S.%f%z' if match.group(4): # UTC string denoted by addition of the character 'Z' timestring = timestring[:-1] + '+0000' try: date_time = datetime.strptime(timestring, strformat) except ValueError: pass else: if check_utc: if convert != 'utc': raise ValueError( 'check_utc can only be used with convert="utc"') date_time.replace(tzinfo=timezone.utc) if epoch: return date_time.timestamp() return date_time if convert == 'utc': date_time = date_time.astimezone(timezone.utc) if epoch: return date_time.timestamp() return date_time if epoch: # epoch is always UTC, use convert='utc' or check_utc=True raise ValueError( 'epoch not available while converting to local') if convert == 'local': date_time = date_time.astimezone(LocalTimezone()) return date_time # convert=None return date_time return None gajim-gajim-1.1.3/gajim/common/modules/delimiter.py000066400000000000000000000043221345766322700222670ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0083: Nested Roster Groups import logging import nbxmpp log = logging.getLogger('gajim.c.m.delimiter') class Delimiter: def __init__(self, con): self._con = con self._account = con.name self.available = False self.delimiter = '::' self.handlers = [] def get_roster_delimiter(self): log.info('Request') node = nbxmpp.Node('storage', attrs={'xmlns': 'roster:delimiter'}) iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVATE, payload=node) self._con.connection.SendAndCallForResponse( iq, self._delimiter_received) def _delimiter_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Request error: %s', stanza.getError()) else: delimiter = stanza.getQuery().getTagData('roster') self.available = True log.info('Delimiter received: %s', delimiter) if delimiter: self.delimiter = delimiter else: self.set_roster_delimiter() self._con.connect_machine() def set_roster_delimiter(self): log.info('Set delimiter') iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVATE) roster = iq.getQuery().addChild('roster', namespace='roster:delimiter') roster.setData('::') self._con.connection.SendAndCallForResponse( iq, self._set_delimiter_response) @staticmethod def _set_delimiter_response(stanza): if not nbxmpp.isResultNode(stanza): log.info('Store error: %s', stanza.getError()) def get_instance(*args, **kwargs): return Delimiter(*args, **kwargs), 'Delimiter' gajim-gajim-1.1.3/gajim/common/modules/discovery.py000066400000000000000000000264551345766322700223330ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0030: Service Discovery import logging import weakref import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.caps_cache import muc_caps_cache from gajim.common.nec import NetworkIncomingEvent from gajim.common.connection_handlers_events import InformationEvent log = logging.getLogger('gajim.c.m.discovery') class Discovery: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('iq', self._answer_disco_info, 'get', nbxmpp.NS_DISCO_INFO), ('iq', self._answer_disco_items, 'get', nbxmpp.NS_DISCO_ITEMS), ] def disco_contact(self, jid, node=None): success_cb = self._con.get_module('Caps').contact_info_received self._disco(nbxmpp.NS_DISCO_INFO, jid, node, success_cb, None) def disco_items(self, jid, node=None, success_cb=None, error_cb=None): self._disco(nbxmpp.NS_DISCO_ITEMS, jid, node, success_cb, error_cb) def disco_info(self, jid, node=None, success_cb=None, error_cb=None): self._disco(nbxmpp.NS_DISCO_INFO, jid, node, success_cb, error_cb) def _disco(self, namespace, jid, node, success_cb, error_cb): if success_cb is None: raise ValueError('success_cb is required') if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='get', to=jid, queryNS=namespace) if node: iq.setQuerynode(node) log_str = 'Request info: %s %s' if namespace == nbxmpp.NS_DISCO_ITEMS: log_str = 'Request items: %s %s' log.info(log_str, jid, node or '') # Create weak references so we can pass GUI object methods weak_success_cb = weakref.WeakMethod(success_cb) if error_cb is not None: weak_error_cb = weakref.WeakMethod(error_cb) else: weak_error_cb = None self._con.connection.SendAndCallForResponse( iq, self._disco_response, {'success_cb': weak_success_cb, 'error_cb': weak_error_cb}) def _disco_response(self, _con, stanza, success_cb, error_cb): if not nbxmpp.isResultNode(stanza): if error_cb is not None: error_cb()(stanza.getFrom(), stanza.getError()) else: log.info('Error: %s', stanza.getError()) return from_ = stanza.getFrom() node = stanza.getQuerynode() if stanza.getQueryNS() == nbxmpp.NS_DISCO_INFO: identities, features, data, node = self.parse_info_response(stanza) success_cb()(from_, identities, features, data, node) elif stanza.getQueryNS() == nbxmpp.NS_DISCO_ITEMS: items = self.parse_items_response(stanza) success_cb()(from_, node, items) else: log.warning('Wrong query namespace: %s', stanza) @classmethod def parse_items_response(cls, stanza): payload = stanza.getQueryPayload() items = [] for item in payload: # CDATA payload is not processed, only nodes if not isinstance(item, nbxmpp.simplexml.Node): continue attr = item.getAttrs() if 'jid' not in attr: log.warning('No jid attr in disco items: %s', stanza) continue try: attr['jid'] = helpers.parse_jid(attr['jid']) except helpers.InvalidFormat: log.warning('Invalid jid attr in disco items: %s', stanza) continue items.append(attr) return items @classmethod def parse_info_response(cls, stanza): identities, features, data, node = [], [], [], None query = stanza.getTag('query') node = query.getAttr('node') if not node: node = '' childs = stanza.getQueryChildren() if not childs: childs = [] for i in childs: if i.getName() == 'identity': attr = {} for key in i.getAttrs().keys(): attr[key] = i.getAttr(key) identities.append(attr) elif i.getName() == 'feature': var = i.getAttr('var') if var: features.append(var) elif i.getName() == 'x' and i.getNamespace() == nbxmpp.NS_DATA: data.append(nbxmpp.DataForm(node=i)) return identities, features, data, node def discover_server_items(self): server = self._con.get_own_jid().getDomain() self.disco_items(server, success_cb=self._server_items_received) def _server_items_received(self, _from, _node, items): log.info('Server items received') for item in items: if 'node' in item: # Only disco components continue self.disco_info(item['jid'], success_cb=self._server_items_info_received) def _server_items_info_received(self, from_, *args): from_ = from_.getStripped() log.info('Server item info received: %s', from_) self._parse_transports(from_, *args) try: self._con.get_module('MUC').pass_disco(from_, *args) self._con.get_module('HTTPUpload').pass_disco(from_, *args) self._con.pass_bytestream_disco(from_, *args) except nbxmpp.NodeProcessed: pass app.nec.push_incoming_event( NetworkIncomingEvent('server-disco-received')) def discover_account_info(self): own_jid = self._con.get_own_jid().getStripped() self.disco_info(own_jid, success_cb=self._account_info_received) def _account_info_received(self, from_, *args): from_ = from_.getStripped() log.info('Account info received: %s', from_) self._con.get_module('MAM').pass_disco(from_, *args) self._con.get_module('PEP').pass_disco(from_, *args) self._con.get_module('PubSub').pass_disco(from_, *args) features = args[1] if 'urn:xmpp:pep-vcard-conversion:0' in features: self._con.avatar_conversion = True def discover_server_info(self): # Calling this method starts the connect_maschine() server = self._con.get_own_jid().getDomain() self.disco_info(server, success_cb=self._server_info_received) def _server_info_received(self, from_, *args): log.info('Server info received: %s', from_) self._con.get_module('SecLabels').pass_disco(from_, *args) self._con.get_module('Blocking').pass_disco(from_, *args) self._con.get_module('VCardTemp').pass_disco(from_, *args) self._con.get_module('Carbons').pass_disco(from_, *args) self._con.get_module('PrivacyLists').pass_disco(from_, *args) self._con.get_module('HTTPUpload').pass_disco(from_, *args) features = args[1] if nbxmpp.NS_REGISTER in features: self._con.register_supported = True if nbxmpp.NS_ADDRESS in features: self._con.addressing_supported = True self._con.connect_machine(restart=True) def _parse_transports(self, from_, identities, _features, _data, _node): for identity in identities: category = identity.get('category') if category not in ('gateway', 'headline'): continue transport_type = identity.get('type') log.info('Found transport: %s %s %s', from_, category, transport_type) jid = str(from_) if jid not in app.transport_type: app.transport_type[jid] = transport_type app.logger.save_transport_type(jid, transport_type) if transport_type in self._con.available_transports: self._con.available_transports[transport_type].append(jid) else: self._con.available_transports[transport_type] = [jid] def _answer_disco_items(self, _con, stanza): from_ = stanza.getFrom() log.info('Answer disco items to %s', from_) if self._con.get_module('AdHocCommands').command_items_query(stanza): raise nbxmpp.NodeProcessed node = stanza.getTagAttr('query', 'node') if node is None: result = stanza.buildReply('result') self._con.connection.send(result) raise nbxmpp.NodeProcessed if node == nbxmpp.NS_COMMANDS: self._con.get_module('AdHocCommands').command_list_query(stanza) raise nbxmpp.NodeProcessed def _answer_disco_info(self, _con, stanza): from_ = stanza.getFrom() log.info('Answer disco info %s', from_) if str(from_).startswith('echo.'): # Service that echos all stanzas, ignore it raise nbxmpp.NodeProcessed if self._con.get_module('AdHocCommands').command_info_query(stanza): raise nbxmpp.NodeProcessed node = stanza.getQuerynode() iq = stanza.buildReply('result') query = iq.setQuery() if node: query.setAttr('node', node) query.addChild('identity', attrs=app.gajim_identity) client_version = 'http://gajim.org#' + app.caps_hash[self._account] if node in (None, client_version): for feature in app.gajim_common_features: query.addChild('feature', attrs={'var': feature}) for feature in app.gajim_optional_features[self._account]: query.addChild('feature', attrs={'var': feature}) self._con.connection.send(iq) raise nbxmpp.NodeProcessed def disco_muc(self, jid, callback, update=False): if not app.account_is_connected(self._account): return if muc_caps_cache.is_cached(jid) and not update: callback() return iq = nbxmpp.Iq(typ='get', to=jid, queryNS=nbxmpp.NS_DISCO_INFO) log.info('Request MUC info %s', jid) self._con.connection.SendAndCallForResponse( iq, self._muc_info_response, {'callback': callback}) @staticmethod def _muc_info_response(_con, stanza, callback): if not nbxmpp.isResultNode(stanza): error = stanza.getError() if error == 'item-not-found': # Groupchat does not exist log.info('MUC does not exist: %s', stanza.getFrom()) callback() else: log.info('MUC disco error: %s', error) app.nec.push_incoming_event( InformationEvent( None, dialog_name='unable-join-groupchat', args=error)) return log.info('MUC info received: %s', stanza.getFrom()) muc_caps_cache.append(stanza) callback() def get_instance(*args, **kwargs): return Discovery(*args, **kwargs), 'Discovery' gajim-gajim-1.1.3/gajim/common/modules/entity_time.py000066400000000000000000000101171345766322700226420ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0202: Entity Time import logging import time import nbxmpp from gajim.common import app from gajim.common.nec import NetworkEvent from gajim.common.modules.date_and_time import parse_datetime from gajim.common.modules.date_and_time import create_tzinfo log = logging.getLogger('gajim.c.m.entity_time') class EntityTime: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('iq', self._answer_request, 'get', nbxmpp.NS_TIME_REVISED), ] def request_entity_time(self, jid, resource): if not app.account_is_connected(self._account): return # If we are invisible, do not request if self._con.connected == app.SHOW_LIST.index('invisible'): return if resource: jid += '/' + resource iq = nbxmpp.Iq(to=jid, typ='get') iq.addChild('time', namespace=nbxmpp.NS_TIME_REVISED) log.info('Requested: %s', jid) self._con.connection.SendAndCallForResponse(iq, self._result_received) def _result_received(self, stanza): time_info = None if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) else: time_info = self._extract_info(stanza) log.info('Received: %s %s', stanza.getFrom(), time_info) app.nec.push_incoming_event(NetworkEvent('time-result-received', conn=self._con, jid=stanza.getFrom(), time_info=time_info)) @staticmethod def _extract_info(stanza): time_ = stanza.getTag('time') if not time_: log.warning('No time node: %s', stanza) return tzo = time_.getTag('tzo').getData() if not tzo: log.warning('Wrong tzo node: %s', stanza) return remote_tz = create_tzinfo(tz_string=tzo) if remote_tz is None: log.warning('Wrong tzo node: %s', stanza) return utc_time = time_.getTag('utc').getData() date_time = parse_datetime(utc_time, check_utc=True) if date_time is None: log.warning('Wrong timezone defintion: %s %s', utc_time, stanza.getFrom()) return date_time = date_time.astimezone(remote_tz) return date_time.strftime('%c %Z') def _answer_request(self, _con, stanza): log.info('%s asked for the time', stanza.getFrom()) if app.config.get_per('accounts', self._account, 'send_time_info'): iq = stanza.buildReply('result') time_ = iq.setTag('time', namespace=nbxmpp.NS_TIME_REVISED) formated_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) time_.setTagData('utc', formated_time) isdst = time.localtime().tm_isdst zone = -(time.timezone, time.altzone)[isdst] / 60.0 tzo = (zone / 60, abs(zone % 60)) time_.setTagData('tzo', '%+03d:%02d' % (tzo)) log.info('Answer: %s %s', formated_time, '%+03d:%02d' % (tzo)) else: iq = stanza.buildReply('error') err = nbxmpp.ErrorNode(nbxmpp.ERR_SERVICE_UNAVAILABLE) iq.addChild(node=err) log.info('Send service-unavailable') self._con.connection.send(iq) raise nbxmpp.NodeProcessed def get_instance(*args, **kwargs): return EntityTime(*args, **kwargs), 'EntityTime' gajim-gajim-1.1.3/gajim/common/modules/http_auth.py000066400000000000000000000052411345766322700223120ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0070: Verifying HTTP Requests via XMPP import logging import nbxmpp from gajim.common import app from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.http_auth') class HTTPAuth: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('iq', self.answer_request, 'get', nbxmpp.NS_HTTP_AUTH), ('message', self.answer_request, '', nbxmpp.NS_HTTP_AUTH) ] def answer_request(self, _con, stanza): log.info('Auth request received') auto_answer = app.config.get_per( 'accounts', self._account, 'http_auth') if auto_answer in ('yes', 'no'): self.build_http_auth_answer(stanza, auto_answer) raise nbxmpp.NodeProcessed iq_id = stanza.getTagAttr('confirm', 'id') method = stanza.getTagAttr('confirm', 'method') url = stanza.getTagAttr('confirm', 'url') # In case it's a message with a body msg = stanza.getTagData('body') app.nec.push_incoming_event( HttpAuthReceivedEvent(None, conn=self._con, iq_id=iq_id, method=method, url=url, msg=msg, stanza=stanza)) raise nbxmpp.NodeProcessed def build_http_auth_answer(self, stanza, answer): if answer == 'yes': log.info('Auth request approved') confirm = stanza.getTag('confirm') reply = stanza.buildReply('result') if stanza.getName() == 'message': reply.addChild(node=confirm) self._con.connection.send(reply) elif answer == 'no': log.info('Auth request denied') err = nbxmpp.Error(stanza, nbxmpp.protocol.ERR_NOT_AUTHORIZED) self._con.connection.send(err) class HttpAuthReceivedEvent(NetworkIncomingEvent): name = 'http-auth-received' def get_instance(*args, **kwargs): return HTTPAuth(*args, **kwargs), 'HTTPAuth' gajim-gajim-1.1.3/gajim/common/modules/httpupload.py000066400000000000000000000366041345766322700225050ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0363: HTTP File Upload import os import sys import threading import ssl import urllib from urllib.request import Request, urlopen from urllib.parse import urlparse import io import mimetypes import logging import nbxmpp from nbxmpp import NS_HTTPUPLOAD from gi.repository import GLib from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ from gajim.common.nec import NetworkIncomingEvent from gajim.common.connection_handlers_events import InformationEvent from gajim.common.connection_handlers_events import MessageOutgoingEvent from gajim.common.connection_handlers_events import GcMessageOutgoingEvent if sys.platform in ('win32', 'darwin'): import certifi log = logging.getLogger('gajim.c.m.httpupload') NS_HTTPUPLOAD_0 = NS_HTTPUPLOAD + ':0' class HTTPUpload: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] self.available = False self.component = None self.httpupload_namespace = None self._allowed_headers = ['Authorization', 'Cookie', 'Expires'] self.max_file_size = None # maximum file size in bytes app.ged.register_event_handler('stanza-message-outgoing', ged.OUT_PREGUI, self.handle_outgoing_stanza) app.ged.register_event_handler('gc-stanza-message-outgoing', ged.OUT_PREGUI, self.handle_outgoing_stanza) self.messages = [] def cleanup(self): app.ged.remove_event_handler('stanza-message-outgoing', ged.OUT_PREGUI, self.handle_outgoing_stanza) app.ged.remove_event_handler('gc-stanza-message-outgoing', ged.OUT_PREGUI, self.handle_outgoing_stanza) def pass_disco(self, from_, _identities, features, data, _node): if NS_HTTPUPLOAD_0 in features: self.httpupload_namespace = NS_HTTPUPLOAD_0 elif NS_HTTPUPLOAD in features: self.httpupload_namespace = NS_HTTPUPLOAD else: return self.component = from_ log.info('Discovered component: %s', from_) for form in data: form_dict = form.asDict() if form_dict.get('FORM_TYPE', None) != self.httpupload_namespace: continue size = form_dict.get('max-file-size', None) if size is not None: self.max_file_size = int(size) break if self.max_file_size is None: log.warning('%s does not provide maximum file size', self._account) else: log.info('%s has a maximum file size of: %s MiB', self._account, self.max_file_size / (1024 * 1024)) self.available = True for ctrl in app.interface.msg_win_mgr.get_controls(acct=self._account): ctrl.update_actions() def handle_outgoing_stanza(self, event): if event.conn.name != self._account: return message = event.msg_iq.getTagData('body') if message and message in self.messages: self.messages.remove(message) # Add oob information before sending message to recipient, # to distinguish HTTP File Upload Link from pasted URL oob = event.msg_iq.addChild('x', namespace=nbxmpp.NS_X_OOB) oob.addChild('url').setData(message) event.additional_data.set_value('gajim', 'oob_url', message) def check_file_before_transfer(self, path, encryption, contact, session, groupchat=False): if not path or not os.path.exists(path): return invalid_file = False stat = os.stat(path) if os.path.isfile(path): if stat[6] == 0: invalid_file = True msg = _('File is empty') else: invalid_file = True msg = _('File does not exist') if self.max_file_size is not None and \ stat.st_size > self.max_file_size: invalid_file = True size = GLib.format_size_full(self.max_file_size, GLib.FormatSizeFlags.IEC_UNITS) msg = _('File is too large, ' 'maximum allowed file size is: %s') % size if invalid_file: self.raise_information_event('open-file-error2', msg) return mime = mimetypes.MimeTypes().guess_type(path)[0] if not mime: mime = 'application/octet-stream' # fallback mime type log.info("Detected MIME type of file: %s", mime) try: file = File(path, contact, mime=mime, encryption=encryption, update_progress=self.raise_progress_event, session=session, groupchat=groupchat) app.interface.show_httpupload_progress(file) except Exception as error: log.exception('Error while loading file') self.raise_information_event('open-file-error2', str(error)) return if encryption is not None: app.interface.encrypt_file(file, self._account, self._request_slot) else: self._request_slot(file) @staticmethod def raise_progress_event(status, file, seen=None, total=None): app.nec.push_incoming_event(HTTPUploadProgressEvent( None, status=status, file=file, seen=seen, total=total)) @staticmethod def raise_information_event(dialog_name, args=None): app.nec.push_incoming_event(InformationEvent( None, dialog_name=dialog_name, args=args)) def _request_slot(self, file): GLib.idle_add(self.raise_progress_event, 'request', file) iq = self._build_request(file) log.info("Sending request for slot") self._con.connection.SendAndCallForResponse( iq, self._received_slot, {'file': file}) def _build_request(self, file): iq = nbxmpp.Iq(typ='get', to=self.component) id_ = app.get_an_id() iq.setID(id_) if self.httpupload_namespace == NS_HTTPUPLOAD: # experimental namespace request = iq.setTag(name="request", namespace=self.httpupload_namespace) request.addChild('filename', payload=os.path.basename(file.path)) request.addChild('size', payload=file.size) request.addChild('content-type', payload=file.mime) else: attr = {'filename': os.path.basename(file.path), 'size': file.size, 'content-type': file.mime} iq.setTag(name="request", namespace=self.httpupload_namespace, attrs=attr) return iq @staticmethod def get_slot_error_message(stanza): tmp = stanza.getTag('error').getTag('file-too-large') if tmp is not None: max_file_size = int(tmp.getTag('max-file-size').getData()) return _('File is too large, maximum allowed file size is: %s') % \ GLib.format_size_full(max_file_size, GLib.FormatSizeFlags.IEC_UNITS) return stanza.getErrorMsg() def _received_slot(self, _con, stanza, file): log.info("Received slot") if stanza.getType() == 'error': self.raise_progress_event('close', file) self.raise_information_event('request-upload-slot-error', self.get_slot_error_message(stanza)) log.error(stanza) return try: if self.httpupload_namespace == NS_HTTPUPLOAD: file.put = stanza.getTag('slot').getTag('put').getData() file.get = stanza.getTag('slot').getTag('get').getData() else: slot = stanza.getTag('slot') file.put = slot.getTagAttr('put', 'url') file.get = slot.getTagAttr('get', 'url') for header in slot.getTag('put').getTags('header'): name = header.getAttr('name') if name not in self._allowed_headers: raise ValueError('Not allowed header') data = header.getData() if '\n' in data: raise ValueError('Newline in header data') file.headers[name] = data except Exception: log.error("Got invalid stanza: %s", stanza) log.exception('Error') self.raise_progress_event('close', file) self.raise_information_event('request-upload-slot-error2') return if (urlparse(file.put).scheme != 'https' or urlparse(file.get).scheme != 'https'): self.raise_progress_event('close', file) self.raise_information_event('unsecure-error') return try: file.stream = StreamFileWithProgress(file) except Exception: log.exception('Error') self.raise_progress_event('close', file) self.raise_information_event('open-file-error') return log.info('Uploading file to %s', file.put) log.info('Please download from %s', file.get) thread = threading.Thread(target=self._upload_file, args=(file,)) thread.daemon = True thread.start() def _upload_file(self, file): GLib.idle_add(self.raise_progress_event, 'upload', file) try: file.headers['User-Agent'] = 'Gajim %s' % app.version file.headers['Content-Type'] = file.mime file.headers['Content-Length'] = file.size request = Request( file.put, data=file.stream, headers=file.headers, method='PUT') log.info("Opening Urllib upload request...") if not app.config.get_per( 'accounts', self._account, 'httpupload_verify'): context = ssl.create_default_context() context.check_hostname = False context.verify_mode = ssl.CERT_NONE log.warning('CERT Verification disabled') transfer = urlopen(request, timeout=30, context=context) else: if sys.platform in ('win32', 'darwin'): transfer = urlopen( request, cafile=certifi.where(), timeout=30) else: transfer = urlopen(request, timeout=30) file.stream.close() log.info('Urllib upload request done, response code: %s', transfer.getcode()) GLib.idle_add(self._upload_complete, transfer.getcode(), file) return except UploadAbortedException as exc: log.info(exc) error_msg = exc except urllib.error.URLError as exc: if isinstance(exc.reason, ssl.SSLError): error_msg = exc.reason.reason if error_msg == 'CERTIFICATE_VERIFY_FAILED': log.exception('Certificate verify failed') else: log.exception('URLError') error_msg = exc.reason except Exception as exc: log.exception("Exception during upload") error_msg = exc GLib.idle_add(self.raise_progress_event, 'close', file) GLib.idle_add(self._on_upload_error, file, error_msg) def _upload_complete(self, response_code, file): self.raise_progress_event('close', file) if 200 <= response_code < 300: log.info("Upload completed successfully") message = file.get if file.user_data: message += '#' + file.user_data message = self.convert_to_aegscm(message) else: self.messages.append(message) if file.groupchat: app.nec.push_outgoing_event(GcMessageOutgoingEvent( None, account=self._account, jid=file.contact.jid, message=message, automatic_message=False, session=file.session)) else: app.nec.push_outgoing_event(MessageOutgoingEvent( None, account=self._account, jid=file.contact.jid, message=message, keyID=file.key_id, type_='chat', automatic_message=False, session=file.session)) else: log.error('Got unexpected http upload response code: %s', response_code) self.raise_information_event('httpupload-response-error', response_code) def _on_upload_error(self, file, reason): self.raise_progress_event('close', file) self.raise_information_event('httpupload-error', str(reason)) @staticmethod def convert_to_aegscm(url): return 'aesgcm' + url[5:] class File: def __init__(self, path, contact, **kwargs): for key, val in kwargs.items(): setattr(self, key, val) self.encrypted = False self.contact = contact self.key_id = None if hasattr(contact, 'keyID'): self.key_id = contact.keyID self.stream = None self.path = path self.put = None self.get = None self.data = None self.user_data = None self.size = None self.headers = {} self.event = threading.Event() self.load_data() def load_data(self): with open(self.path, 'rb') as content: self.data = content.read() self.size = len(self.data) def get_data(self, full=False): if full: return io.BytesIO(self.data).getvalue() return io.BytesIO(self.data) class StreamFileWithProgress: def __init__(self, file): self.file = file self.event = file.event self.backing = file.get_data() self.backing.seek(0, os.SEEK_END) self._total = self.backing.tell() self.backing.seek(0) self._callback = file.update_progress self._seen = 0 def __len__(self): return self._total def read(self, size): if self.event.isSet(): raise UploadAbortedException data = self.backing.read(size) self._seen += len(data) if self._callback: GLib.idle_add(self._callback, 'update', self.file, self._seen, self._total) return data def close(self): return self.backing.close() class UploadAbortedException(Exception): def __str__(self): return "Upload Aborted" class HTTPUploadProgressEvent(NetworkIncomingEvent): name = 'httpupload-progress' def get_instance(*args, **kwargs): return HTTPUpload(*args, **kwargs), 'HTTPUpload' gajim-gajim-1.1.3/gajim/common/modules/last_activity.py000066400000000000000000000033161345766322700231720ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0012: Last Activity import logging import nbxmpp from gajim.common import app from gajim.common import idle log = logging.getLogger('gajim.c.m.last_activity') class LastActivity: def __init__(self, con): self._con = con self._account = con.name self.handlers = [('iq', self._answer_request, 'get', nbxmpp.NS_LAST)] def _answer_request(self, _con, stanza): log.info('Request from %s', stanza.getFrom()) if not app.account_is_connected(self._account): return allow_send = app.config.get_per( 'accounts', self._account, 'send_idle_time') if app.is_installed('IDLE') and allow_send: iq = stanza.buildReply('result') query = iq.setQuery() query.attrs['seconds'] = idle.Monitor.get_idle_sec() else: iq = stanza.buildReply('error') err = nbxmpp.ErrorNode(nbxmpp.ERR_SERVICE_UNAVAILABLE) iq.addChild(node=err) self._con.connection.send(iq) raise nbxmpp.NodeProcessed def get_instance(*args, **kwargs): return LastActivity(*args, **kwargs), 'LastActivity' gajim-gajim-1.1.3/gajim/common/modules/mam.py000066400000000000000000000617531345766322700210760ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0313: Message Archive Management import logging import time from datetime import datetime, timedelta import nbxmpp from gajim.common import app from gajim.common.nec import NetworkIncomingEvent from gajim.common.const import ArchiveState from gajim.common.const import KindConstant from gajim.common.const import SyncThreshold from gajim.common.caps_cache import muc_caps_cache from gajim.common.helpers import get_sync_threshold from gajim.common.helpers import AdditionalDataDict from gajim.common.modules.misc import parse_delay from gajim.common.modules.misc import parse_oob from gajim.common.modules.misc import parse_correction from gajim.common.modules.misc import parse_eme from gajim.common.modules.util import is_self_message from gajim.common.modules.util import is_muc_pm log = logging.getLogger('gajim.c.m.archiving') class MAM: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('message', self._mam_message_received, '', nbxmpp.NS_MAM_1), ('message', self._mam_message_received, '', nbxmpp.NS_MAM_2), ] self.available = False self.archiving_namespace = None self._mam_query_ids = {} # Holds archive jids where catch up was successful self._catch_up_finished = [] def pass_disco(self, from_, _identities, features, _data, _node): if nbxmpp.NS_MAM_2 in features: self.archiving_namespace = nbxmpp.NS_MAM_2 elif nbxmpp.NS_MAM_1 in features: self.archiving_namespace = nbxmpp.NS_MAM_1 else: return self.available = True log.info('Discovered MAM %s: %s', self.archiving_namespace, from_) # TODO: Move this GUI code out action = app.app.lookup_action('%s-archive' % self._account) action.set_enabled(True) def _from_valid_archive(self, stanza, message, groupchat): if groupchat: expected_archive = message.getFrom() else: expected_archive = self._con.get_own_jid() archive_jid = stanza.getFrom() if archive_jid is None: if groupchat: return # Message from our own archive return self._con.get_own_jid() if archive_jid.bareMatch(expected_archive): return archive_jid def _get_unique_id(self, result, message, groupchat, self_message, muc_pm): stanza_id = result.getAttr('id') if groupchat: return stanza_id, None origin_id = message.getOriginID() if self_message: return None, origin_id if muc_pm: return stanza_id, origin_id if self._con.get_own_jid().bareMatch(message.getFrom()): # message we sent return stanza_id, origin_id # A message we received return stanza_id, None def _mam_message_received(self, _con, stanza): app.nec.push_incoming_event( NetworkIncomingEvent('raw-mam-message-received', conn=self._con, stanza=stanza)) result = stanza.getTag('result', protocol=True) queryid = result.getAttr('queryid') forwarded = result.getTag('forwarded', namespace=nbxmpp.NS_FORWARD, protocol=True) message = forwarded.getTag('message', protocol=True) groupchat = message.getType() == 'groupchat' archive_jid = self._from_valid_archive(stanza, message, groupchat) if archive_jid is None: log.warning('Message from invalid archive %s', stanza) raise nbxmpp.NodeProcessed log.info('Received message from archive: %s', archive_jid) if not self._is_valid_request(archive_jid, queryid): log.warning('Invalid MAM Message: unknown query id') log.debug(stanza) raise nbxmpp.NodeProcessed # Timestamp parsing # Most servers dont set the 'from' attr, so we cant check for it delay_timestamp = parse_delay(forwarded) if delay_timestamp is None: log.warning('No timestamp on MAM message') log.warning(stanza) raise nbxmpp.NodeProcessed # Fix for self messaging if not groupchat: to = message.getTo() if to is None: # Some servers dont set the 'to' attribute when # we send a message to ourself message.setTo(self._con.get_own_jid()) event_attrs = {} if groupchat: event_attrs.update(self._parse_gc_attrs(message)) else: event_attrs.update(self._parse_chat_attrs(message)) self_message = is_self_message(message, groupchat) muc_pm = is_muc_pm(message, event_attrs['with_'], groupchat) stanza_id, origin_id = self._get_unique_id( result, message, groupchat, self_message, muc_pm) message_id = message.getID() # Check for duplicates namespace = self.archiving_namespace if groupchat: namespace = muc_caps_cache.get_mam_namespace( archive_jid.getStripped()) if namespace == nbxmpp.NS_MAM_2: # Search only with stanza-id for duplicates on mam:2 if app.logger.find_stanza_id(self._account, archive_jid.getStripped(), stanza_id, origin_id, groupchat=groupchat): log.info('Found duplicate with stanza-id') raise nbxmpp.NodeProcessed msgtxt = message.getTagData('body') event_attrs.update( {'conn': self._con, 'additional_data': AdditionalDataDict(), 'encrypted': False, 'timestamp': delay_timestamp, 'self_message': self_message, 'groupchat': groupchat, 'muc_pm': muc_pm, 'stanza_id': stanza_id, 'origin_id': origin_id, 'message_id': message_id, 'correct_id': None, 'archive_jid': archive_jid, 'msgtxt': msgtxt, 'message': message, 'stanza': message, 'namespace': namespace, }) if groupchat: event = MamGcMessageReceivedEvent(None, **event_attrs) else: event = MamMessageReceivedEvent(None, **event_attrs) app.plugin_manager.extension_point( 'decrypt', self._con, event, self._decryption_finished) if not event.encrypted: eme = parse_eme(event.message) if eme is not None: event.msgtxt = eme self._decryption_finished(event) raise nbxmpp.NodeProcessed @staticmethod def _parse_gc_attrs(message): with_ = message.getFrom() nick = message.getFrom().getResource() # Get the real jid if we have it real_jid = None muc_user = message.getTag('x', namespace=nbxmpp.NS_MUC_USER) if muc_user is not None: real_jid = muc_user.getTagAttr('item', 'jid') if real_jid is not None: real_jid = nbxmpp.JID(real_jid) return {'with_': with_, 'nick': nick, 'real_jid': real_jid, 'kind': KindConstant.GC_MSG} def _parse_chat_attrs(self, message): frm = message.getFrom() to = message.getTo() if frm.bareMatch(self._con.get_own_jid()): with_ = to kind = KindConstant.CHAT_MSG_SENT else: with_ = frm kind = KindConstant.CHAT_MSG_RECV return {'with_': with_, 'nick': None, 'kind': kind} def _decryption_finished(self, event): if not event.msgtxt: # For example Chatstates, Receipts, Chatmarkers log.debug(event.message.getProperties()) return user_timestamp = parse_delay(event.stanza) if user_timestamp is not None: # Record it as a user timestamp event.additional_data.set_value( 'gajim', 'user_timestamp', user_timestamp) event.correct_id = parse_correction(event.message) parse_oob(event) with_ = event.with_.getStripped() if event.muc_pm: # we store the message with the full JID with_ = str(event.with_) stanza_id = event.stanza_id if event.self_message: # Self messages can only be deduped with origin-id if event.origin_id is None: log.warning('Self message without origin-id found') return stanza_id = event.origin_id if event.namespace == nbxmpp.NS_MAM_1: if app.logger.search_for_duplicate( self._account, with_, event.timestamp, event.msgtxt): log.info('Found duplicate with fallback for mam:1') return app.logger.insert_into_logs(self._account, with_, event.timestamp, event.kind, unread=False, message=event.msgtxt, contact_name=event.nick, additional_data=event.additional_data, stanza_id=stanza_id) app.nec.push_incoming_event( MamDecryptedMessageReceived(None, **vars(event))) def _is_valid_request(self, jid, query_id): if query_id is None: return False valid_id = self._mam_query_ids.get(jid.getStripped(), None) return valid_id == query_id def _get_query_id(self, jid): query_id = self._con.connection.getAnID() self._mam_query_ids[jid] = query_id return query_id @staticmethod def _parse_iq(stanza): if not nbxmpp.isResultNode(stanza): log.error('Error on MAM query: %s', stanza.getError()) raise InvalidMamIQ fin = stanza.getTag('fin') if fin is None: log.error('Malformed MAM query result received: %s', stanza) raise InvalidMamIQ set_ = fin.getTag('set', namespace=nbxmpp.NS_RSM) if set_ is None: log.error( 'Malformed MAM query result received (no "set" Node): %s', stanza) raise InvalidMamIQ return fin, set_ def _get_from_jid(self, stanza): jid = stanza.getFrom() if jid is None: # No from means, iq from our own archive jid = self._con.get_own_jid().getStripped() else: jid = jid.getStripped() return jid def request_archive_count(self, start_date, end_date): jid = self._con.get_own_jid().getStripped() log.info('Request archive count from: %s', jid) query_id = self._get_query_id(jid) query = self._get_archive_query( query_id, start=start_date, end=end_date, max_=0) self._con.connection.SendAndCallForResponse( query, self._received_count, {'query_id': query_id}) return query_id def _received_count(self, _con, stanza, query_id): try: _, set_ = self._parse_iq(stanza) except InvalidMamIQ: return jid = self._get_from_jid(stanza) self._mam_query_ids.pop(jid) count = set_.getTagData('count') log.info('Received archive count: %s', count) app.nec.push_incoming_event(ArchivingCountReceived( None, query_id=query_id, count=count)) def request_archive_on_signin(self): own_jid = self._con.get_own_jid().getStripped() if own_jid in self._mam_query_ids: log.warning('MAM request for %s already running', own_jid) return archive = app.logger.get_archive_infos(own_jid) # Migration of last_mam_id from config to DB if archive is not None: mam_id = archive.last_mam_id else: mam_id = app.config.get_per( 'accounts', self._account, 'last_mam_id') if mam_id: app.config.del_per('accounts', self._account, 'last_mam_id') start_date = None query_id = self._get_query_id(own_jid) if mam_id: log.info('MAM query after: %s', mam_id) query = self._get_archive_query(query_id, after=mam_id) else: # First Start, we request the last week start_date = datetime.utcnow() - timedelta(days=7) log.info('First start: query archive start: %s', start_date) query = self._get_archive_query(query_id, start=start_date) if own_jid in self._catch_up_finished: self._catch_up_finished.remove(own_jid) self._send_archive_query(query, query_id, start_date) def request_archive_on_muc_join(self, jid): archive = app.logger.get_archive_infos(jid) threshold = get_sync_threshold(jid, archive) log.info('Threshold for %s: %s', jid, threshold) query_id = self._get_query_id(jid) start_date = None if archive is None or archive.last_mam_id is None: # First Start, we dont request history # Depending on what a MUC saves, there could be thousands # of Messages even in just one day. start_date = datetime.utcnow() - timedelta(days=1) log.info('First join: query archive %s from: %s', jid, start_date) query = self._get_archive_query( query_id, jid=jid, start=start_date) elif threshold == SyncThreshold.NO_THRESHOLD: # Not our first join and no threshold set log.info('Request from archive: %s, after mam-id %s', jid, archive.last_mam_id) query = self._get_archive_query( query_id, jid=jid, after=archive.last_mam_id) else: # Not our first join, check how much time elapsed since our # last join and check against threshold last_timestamp = archive.last_muc_timestamp if last_timestamp is None: log.info('No last muc timestamp found ( mam:1? )') last_timestamp = 0 last = datetime.utcfromtimestamp(float(last_timestamp)) if datetime.utcnow() - last > timedelta(days=threshold): # To much time has elapsed since last join, apply threshold start_date = datetime.utcnow() - timedelta(days=threshold) log.info('Too much time elapsed since last join, ' 'request from: %s, threshold: %s', start_date, threshold) query = self._get_archive_query( query_id, jid=jid, start=start_date) else: # Request from last mam-id log.info('Request from archive %s after %s:', jid, archive.last_mam_id) query = self._get_archive_query( query_id, jid=jid, after=archive.last_mam_id) if jid in self._catch_up_finished: self._catch_up_finished.remove(jid) self._send_archive_query(query, query_id, start_date, groupchat=True) def _send_archive_query(self, query, query_id, start_date=None, groupchat=False): self._con.connection.SendAndCallForResponse( query, self._result_finished, {'query_id': query_id, 'start_date': start_date, 'groupchat': groupchat}) def _result_finished(self, _con, stanza, query_id, start_date, groupchat): try: fin, set_ = self._parse_iq(stanza) except InvalidMamIQ: return jid = self._get_from_jid(stanza) last = set_.getTagData('last') if last is None: log.info('End of MAM query, no items retrieved') self._catch_up_finished.append(jid) self._mam_query_ids.pop(jid) return complete = fin.getAttr('complete') if complete != 'true': app.logger.set_archive_infos(jid, last_mam_id=last) self._mam_query_ids.pop(jid) query_id = self._get_query_id(jid) query = self._get_archive_query(query_id, jid=jid, after=last) self._send_archive_query(query, query_id, groupchat=groupchat) else: self._mam_query_ids.pop(jid) app.logger.set_archive_infos( jid, last_mam_id=last, last_muc_timestamp=time.time()) if start_date is not None and not groupchat: # Record the earliest timestamp we request from # the account archive. For the account archive we only # set start_date at the very first request. app.logger.set_archive_infos( jid, oldest_mam_timestamp=start_date.timestamp()) self._catch_up_finished.append(jid) log.info('End of MAM query, last mam id: %s', last) def request_archive_interval(self, start_date, end_date, after=None, query_id=None): jid = self._con.get_own_jid().getStripped() if after is None: log.info('Request intervall from %s to %s from %s', start_date, end_date, jid) else: log.info('Query page after %s from %s', after, jid) if query_id is None: query_id = self._get_query_id(jid) self._mam_query_ids[jid] = query_id query = self._get_archive_query(query_id, start=start_date, end=end_date, after=after, max_=30) self._con.connection.SendAndCallForResponse( query, self._intervall_result, {'query_id': query_id, 'start_date': start_date, 'end_date': end_date}) return query_id def _intervall_result(self, _con, stanza, query_id, start_date, end_date): try: fin, set_ = self._parse_iq(stanza) except InvalidMamIQ: return jid = self._get_from_jid(stanza) self._mam_query_ids.pop(jid) if start_date: timestamp = start_date.timestamp() else: timestamp = ArchiveState.ALL last = set_.getTagData('last') if last is None: app.nec.push_incoming_event(ArchivingIntervalFinished( None, query_id=query_id)) app.logger.set_archive_infos( jid, oldest_mam_timestamp=timestamp) log.info('End of MAM request, no items retrieved') return complete = fin.getAttr('complete') if complete != 'true': self.request_archive_interval(start_date, end_date, last, query_id) else: log.info('Request finished') app.logger.set_archive_infos( jid, oldest_mam_timestamp=timestamp) app.nec.push_incoming_event(ArchivingIntervalFinished( None, query_id=query_id)) def _get_archive_query(self, query_id, jid=None, start=None, end=None, with_=None, after=None, max_=70): # Muc archive query? namespace = muc_caps_cache.get_mam_namespace(jid) if namespace is None: # Query to our own archive namespace = self.archiving_namespace iq = nbxmpp.Iq('set', to=jid) query = iq.addChild('query', namespace=namespace) form = query.addChild(node=nbxmpp.DataForm(typ='submit')) field = nbxmpp.DataField(typ='hidden', name='FORM_TYPE', value=namespace) form.addChild(node=field) if start: field = nbxmpp.DataField( typ='text-single', name='start', value=start.strftime('%Y-%m-%dT%H:%M:%SZ')) form.addChild(node=field) if end: field = nbxmpp.DataField(typ='text-single', name='end', value=end.strftime('%Y-%m-%dT%H:%M:%SZ')) form.addChild(node=field) if with_: field = nbxmpp.DataField(typ='jid-single', name='with', value=with_) form.addChild(node=field) set_ = query.setTag('set', namespace=nbxmpp.NS_RSM) set_.setTagData('max', max_) if after: set_.setTagData('after', after) query.setAttr('queryid', query_id) return iq def save_archive_id(self, jid, stanza_id, timestamp): if jid is None: jid = self._con.get_own_jid().getStripped() if jid not in self._catch_up_finished: return log.info('Save: %s: %s, %s', jid, stanza_id, timestamp) if stanza_id is None: # mam:1 app.logger.set_archive_infos(jid, last_muc_timestamp=timestamp) else: # mam:2 app.logger.set_archive_infos( jid, last_mam_id=stanza_id, last_muc_timestamp=timestamp) def request_mam_preferences(self): log.info('Request MAM preferences') iq = nbxmpp.Iq('get', self.archiving_namespace) iq.setQuery('prefs') self._con.connection.SendAndCallForResponse( iq, self._preferences_received) def _preferences_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event(MAMPreferenceError( None, conn=self._con, error=stanza.getError())) return log.info('Received MAM preferences') prefs = stanza.getTag('prefs', namespace=self.archiving_namespace) if prefs is None: log.error('Malformed stanza (no prefs node): %s', stanza) return rules = [] default = prefs.getAttr('default') for item in prefs.getTag('always').getTags('jid'): rules.append((item.getData(), 'Always')) for item in prefs.getTag('never').getTags('jid'): rules.append((item.getData(), 'Never')) app.nec.push_incoming_event(MAMPreferenceReceived( None, conn=self._con, rules=rules, default=default)) def set_mam_preferences(self, rules, default): iq = nbxmpp.Iq(typ='set') prefs = iq.addChild(name='prefs', namespace=self.archiving_namespace, attrs={'default': default}) always = prefs.addChild(name='always') never = prefs.addChild(name='never') for item in rules: jid, archive = item if archive: always.addChild(name='jid').setData(jid) else: never.addChild(name='jid').setData(jid) self._con.connection.SendAndCallForResponse( iq, self._preferences_saved) def _preferences_saved(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event(MAMPreferenceError( None, conn=self._con, error=stanza.getError())) else: log.info('Preferences saved') app.nec.push_incoming_event( MAMPreferenceSaved(None, conn=self._con)) class MamMessageReceivedEvent(NetworkIncomingEvent): name = 'mam-message-received' class MamGcMessageReceivedEvent(NetworkIncomingEvent): name = 'mam-gc-message-received' class MamDecryptedMessageReceived(NetworkIncomingEvent): name = 'mam-decrypted-message-received' class MAMPreferenceError(NetworkIncomingEvent): name = 'mam-prefs-error' class MAMPreferenceReceived(NetworkIncomingEvent): name = 'mam-prefs-received' class MAMPreferenceSaved(NetworkIncomingEvent): name = 'mam-prefs-saved' class ArchivingCountReceived(NetworkIncomingEvent): name = 'archiving-count-received' class ArchivingIntervalFinished(NetworkIncomingEvent): name = 'archiving-interval-finished' class ArchivingErrorReceived(NetworkIncomingEvent): name = 'archiving-error-received' class InvalidMamIQ(Exception): pass def get_instance(*args, **kwargs): return MAM(*args, **kwargs), 'MAM' gajim-gajim-1.1.3/gajim/common/modules/message.py000066400000000000000000000315551345766322700217450ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # Message handler import time import logging import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.nec import NetworkIncomingEvent from gajim.common.nec import NetworkEvent from gajim.common.helpers import AdditionalDataDict from gajim.common.modules.security_labels import parse_securitylabel from gajim.common.modules.user_nickname import parse_nickname from gajim.common.modules.carbons import parse_carbon from gajim.common.modules.misc import parse_delay from gajim.common.modules.misc import parse_eme from gajim.common.modules.misc import parse_correction from gajim.common.modules.misc import parse_attention from gajim.common.modules.misc import parse_form from gajim.common.modules.misc import parse_oob from gajim.common.modules.misc import parse_xhtml from gajim.common.modules.util import is_self_message from gajim.common.modules.util import is_muc_pm from gajim.common.connection_handlers_events import GcMessageReceivedEvent log = logging.getLogger('gajim.c.m.message') class Message: def __init__(self, con): self._con = con self._account = con.name self.handlers = [('message', self._message_received)] # XEPs for which this message module should not be executed self._message_namespaces = set([nbxmpp.NS_HTTP_AUTH, nbxmpp.NS_PUBSUB_EVENT, nbxmpp.NS_ROSTERX, nbxmpp.NS_MAM_1, nbxmpp.NS_MAM_2, nbxmpp.NS_CONFERENCE, nbxmpp.NS_IBB]) def _message_received(self, _con, stanza): # https://tools.ietf.org/html/rfc6120#section-8.1.1.1 # If the stanza does not include a 'to' address then the client MUST # treat it as if the 'to' address were included with a value of the # client's full JID. # # Implementation Note: However, if the client does # check the 'to' address then it is suggested to check at most the # bare JID portion (not the full JID) own_jid = self._con.get_own_jid().getStripped() to = stanza.getTo() if to is None: stanza.setTo(own_jid) elif not to.bareMatch(own_jid): log.warning('Message addressed to someone else: %s', stanza) raise nbxmpp.NodeProcessed # Check if a child of the message contains any # namespaces that we handle in other modules. # nbxmpp executes less common handlers last if self._message_namespaces & set(stanza.getProperties()): return muc_user = stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER) if muc_user is not None and (stanza.getType() != 'error'): if muc_user.getChildren(): # Not a PM, handled by MUC module return log.info('Received from %s', stanza.getFrom()) app.nec.push_incoming_event(NetworkEvent( 'raw-message-received', conn=self._con, stanza=stanza, account=self._account)) if stanza.getFrom() == self._con.get_own_jid(warn=True): # Drop messages sent from our own full jid # It can happen that when we sent message to our own bare jid # that the server routes that message back to us log.info('Received message from self: %s, message is dropped', stanza.getFrom()) return stanza, sent, forwarded = parse_carbon(self._con, stanza) from_ = stanza.getFrom() type_ = stanza.getType() if type_ is None: type_ = 'normal' self_message = is_self_message(stanza, type_ == 'groupchat') muc_pm = is_muc_pm(stanza, from_, type_ == 'groupchat') id_ = stanza.getID() fjid = None if from_ is not None: try: fjid = helpers.parse_jid(str(from_)) except helpers.InvalidFormat: log.warning('Invalid JID: %s, ignoring it', stanza.getFrom()) return jid, resource = app.get_room_and_nick_from_fjid(fjid) # Check for duplicates stanza_id, origin_id = self._get_unique_id( stanza, forwarded, sent, self_message, muc_pm) # Check groupchat messages for duplicates, # We do this because of MUC History messages if type_ == 'groupchat' or self_message or muc_pm: if type_ == 'groupchat': archive_jid = stanza.getFrom().getStripped() else: archive_jid = own_jid if app.logger.find_stanza_id(self._account, archive_jid, stanza_id, origin_id, type_ == 'groupchat'): return thread_id = stanza.getThread() msgtxt = stanza.getBody() # TODO: remove all control UI stuff gc_control = app.interface.msg_win_mgr.get_gc_control( jid, self._account) if not gc_control: minimized = app.interface.minimized_controls[self._account] gc_control = minimized.get(jid) if gc_control and jid == fjid: if type_ == 'error': if msgtxt: msgtxt = _('error while sending %(message)s ( %(error)s )') % { 'message': msgtxt, 'error': stanza.getErrorMsg()} else: msgtxt = _('error: %s') % stanza.getErrorMsg() # TODO: why is this here? if stanza.getTag('html'): stanza.delChild('html') type_ = 'groupchat' session = None if type_ != 'groupchat': if muc_pm and type_ == 'error': session = self._con.find_session(fjid, thread_id) if not session: session = self._con.get_latest_session(fjid) if not session: session = self._con.make_new_session( fjid, thread_id, type_='pm') else: session = self._con.get_or_create_session(fjid, thread_id) if thread_id and not session.received_thread_id: session.received_thread_id = True session.last_receive = time.time() event_attr = { 'conn': self._con, 'stanza': stanza, 'account': self._account, 'id_': id_, 'encrypted': False, 'additional_data': AdditionalDataDict(), 'forwarded': forwarded, 'sent': sent, 'fjid': fjid, 'jid': jid, 'resource': resource, 'stanza_id': stanza_id, 'unique_id': stanza_id or origin_id, 'mtype': type_, 'msgtxt': msgtxt, 'thread_id': thread_id, 'session': session, 'self_message': self_message, 'muc_pm': muc_pm, 'gc_control': gc_control } app.nec.push_incoming_event(NetworkEvent('update-client-info', account=self._account, jid=jid, resource=resource)) event = MessageReceivedEvent(None, **event_attr) app.nec.push_incoming_event(event) app.plugin_manager.extension_point( 'decrypt', self._con, event, self._on_message_decrypted) if not event.encrypted: eme = parse_eme(event.stanza) if eme is not None: event.msgtxt = eme self._on_message_decrypted(event) def _on_message_decrypted(self, event): try: self._con.get_module('Receipts').delegate(event) self._con.get_module('Chatstate').delegate(event) except nbxmpp.NodeProcessed: return subject = event.stanza.getSubject() groupchat = event.mtype == 'groupchat' # XEP-0045: only a message that contains a but no # element shall be considered a subject change for MUC purposes. muc_subject = subject and groupchat and not event.msgtxt # Determine timestamps if groupchat: delay_entity_jid = event.jid else: delay_entity_jid = self._con.get_own_jid().getDomain() if muc_subject: # MUC Subjects can have a delay timestamp # to indicate when the user has set the subject, # the 'from' attr on these delays is the MUC server # but we treat it as user timestamp timestamp = time.time() user_timestamp = parse_delay(event.stanza, from_=delay_entity_jid) else: timestamp = parse_delay(event.stanza, from_=delay_entity_jid) if timestamp is None: timestamp = time.time() user_timestamp = parse_delay(event.stanza, not_from=[delay_entity_jid]) if user_timestamp is not None: event.additional_data.set_value( 'gajim', 'user_timestamp', user_timestamp) event_attr = { 'popup': False, 'msg_log_id': None, 'subject': subject, 'displaymarking': parse_securitylabel(event.stanza), 'attention': parse_attention(event.stanza), 'correct_id': parse_correction(event.stanza), 'user_nick': '' if event.sent else parse_nickname(event.stanza), 'form_node': parse_form(event.stanza), 'xhtml': parse_xhtml(event.stanza), 'timestamp': timestamp, 'delayed': user_timestamp is not None, } parse_oob(event) for name, value in event_attr.items(): setattr(event, name, value) if event.mtype == 'error': if not event.msgtxt: event.msgtxt = _('message') if event.gc_control: event.gc_control.print_conversation(event.msgtxt) else: self._con.dispatch_error_message( event.stanza, event.msgtxt, event.session, event.fjid, timestamp) return if muc_subject: app.nec.push_incoming_event(NetworkEvent('gc-subject-received', **vars(event))) return if groupchat: app.nec.push_incoming_event(GcMessageReceivedEvent( None, conn=self._con, msg_obj=event, stanza_id=event.stanza_id)) return app.nec.push_incoming_event( DecryptedMessageReceivedEvent( None, **vars(event))) def _get_unique_id(self, stanza, _forwarded, _sent, self_message, _muc_pm): if stanza.getType() == 'groupchat': # TODO: Disco the MUC check if 'urn:xmpp:mam:2' is announced return self._get_stanza_id(stanza), None if stanza.getType() != 'chat': return None, None # Messages we receive live if self._con.get_module('MAM').archiving_namespace != nbxmpp.NS_MAM_2: # Only mam:2 ensures valid stanza-id return None, None if self_message: return self._get_stanza_id(stanza), stanza.getOriginID() return self._get_stanza_id(stanza), None def _get_stanza_id(self, stanza): stanza_id, by = stanza.getStanzaIDAttrs() if by is None: # We can not verify who set this stanza-id, ignore it. return if stanza.getType() == 'groupchat': if stanza.getFrom().bareMatch(by): # by attribute must match the server return stanza_id elif self._con.get_own_jid().bareMatch(by): # by attribute must match the server return stanza_id return class MessageReceivedEvent(NetworkIncomingEvent): name = 'message-received' class DecryptedMessageReceivedEvent(NetworkIncomingEvent): name = 'decrypted-message-received' def get_instance(*args, **kwargs): return Message(*args, **kwargs), 'Message' gajim-gajim-1.1.3/gajim/common/modules/metacontacts.py000066400000000000000000000067351345766322700230100ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0209: Metacontacts import logging import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.nec import NetworkEvent log = logging.getLogger('gajim.c.m.metacontacts') class MetaContacts: def __init__(self, con): self._con = con self._account = con.name self.available = False self.handlers = [] def get_metacontacts(self): log.info('Request') node = nbxmpp.Node('storage', attrs={'xmlns': 'storage:metacontacts'}) iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVATE, payload=node) self._con.connection.SendAndCallForResponse( iq, self._metacontacts_received) def _metacontacts_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Request error: %s', stanza.getError()) else: self.available = True meta_list = self._parse_metacontacts(stanza) log.info('Received: %s', meta_list) app.nec.push_incoming_event(NetworkEvent( 'metacontacts-received', conn=self._con, meta_list=meta_list)) self._con.connect_machine() @staticmethod def _parse_metacontacts(stanza): meta_list = {} query = stanza.getQuery() storage = query.getTag('storage') metas = storage.getTags('meta') for meta in metas: try: jid = helpers.parse_jid(meta.getAttr('jid')) except helpers.InvalidFormat: continue tag = meta.getAttr('tag') data = {'jid': jid} order = meta.getAttr('order') try: order = int(order) except Exception: order = 0 if order is not None: data['order'] = order if tag in meta_list: meta_list[tag].append(data) else: meta_list[tag] = [data] return meta_list def store_metacontacts(self, tags_list): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVATE) meta = iq.getQuery().addChild('storage', namespace='storage:metacontacts') for tag in tags_list: for data in tags_list[tag]: jid = data['jid'] dict_ = {'jid': jid, 'tag': tag} if 'order' in data: dict_['order'] = data['order'] meta.addChild(name='meta', attrs=dict_) log.info('Store: %s', tags_list) self._con.connection.SendAndCallForResponse( iq, self._store_response_received) @staticmethod def _store_response_received(stanza): if not nbxmpp.isResultNode(stanza): log.info('Store error: %s', stanza.getError()) def get_instance(*args, **kwargs): return MetaContacts(*args, **kwargs), 'MetaContacts' gajim-gajim-1.1.3/gajim/common/modules/misc.py000066400000000000000000000120001345766322700212340ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # All XEPs that dont need their own module import logging import nbxmpp from gajim.common import app from gajim.common.i18n import _ from gajim.common.modules.date_and_time import parse_datetime log = logging.getLogger('gajim.c.m.misc') # XEP-0380: Explicit Message Encryption _eme_namespaces = { 'urn:xmpp:otr:0': _('This message was encrypted with OTR ' 'and could not be decrypted.'), 'jabber:x:encrypted': _('This message was encrypted with Legacy ' 'OpenPGP and could not be decrypted. You can install ' 'the PGP plugin to handle those messages.'), 'urn:xmpp:openpgp:0': _('This message was encrypted with ' 'OpenPGP for XMPP and could not be decrypted.'), 'fallback': _('This message was encrypted with %s ' 'and could not be decrypted.') } def parse_eme(stanza): enc_tag = stanza.getTag('encryption', namespace=nbxmpp.NS_EME) if enc_tag is None: return ns = enc_tag.getAttr('namespace') if ns is None: log.warning('No namespace on EME message') return if ns in _eme_namespaces: log.info('Found not decrypted message: %s', ns) return _eme_namespaces.get(ns) enc_name = enc_tag.getAttr('name') log.info('Found not decrypted message: %s', enc_name or ns) return _eme_namespaces.get('fallback') % enc_name or ns # XEP-0203: Delayed Delivery def parse_delay(stanza, epoch=True, convert='utc', from_=None, not_from=None): ''' Returns the first valid delay timestamp that matches :param epoch: Returns the timestamp as epoch :param convert: Converts the timestamp to either utc or local :param from_: Matches only delays that have the according from attr set :param not_from: Matches only delays that have the according from attr not set ''' delays = stanza.getTags('delay', namespace=nbxmpp.NS_DELAY2) for delay in delays: stamp = delay.getAttr('stamp') if stamp is None: log.warning('Invalid timestamp received: %s', stamp) log.warning(stanza) continue delay_from = delay.getAttr('from') if from_ is not None: if delay_from != from_: continue if not_from is not None: if delay_from in not_from: continue timestamp = parse_datetime(stamp, check_utc=True, epoch=epoch, convert=convert) if timestamp is None: log.warning('Invalid timestamp received: %s', stamp) log.warning(stanza) continue return timestamp # XEP-0066: Out of Band Data def parse_oob(event): oob_node = event.stanza.getTag('x', namespace=nbxmpp.NS_X_OOB) if oob_node is None: return url = oob_node.getTagData('url') if url is not None: event.additional_data.set_value('gajim', 'oob_url', url) desc = oob_node.getTagData('desc') if desc is not None: event.additional_data.set_value('gajim', 'oob_desc', desc) # XEP-0308: Last Message Correction def parse_correction(stanza): replace = stanza.getTag('replace', namespace=nbxmpp.NS_CORRECT) if replace is not None: id_ = replace.getAttr('id') if id_ is not None: return id_ log.warning('No id attr found: %s', stanza) # XEP-0224: Attention def parse_attention(stanza): attention = stanza.getTag('attention', namespace=nbxmpp.NS_ATTENTION) if attention is None: return False delayed = stanza.getTag('x', namespace=nbxmpp.NS_DELAY2) if delayed is not None: return False return True # XEP-0004: Data Forms def parse_form(stanza): return stanza.getTag('x', namespace=nbxmpp.NS_DATA) # XEP-0071: XHTML-IM def parse_xhtml(stanza): if app.config.get('ignore_incoming_xhtml'): return None return stanza.getXHTML() # XEP-0319: Last User Interaction in Presence def parse_idle(stanza): idle_tag = stanza.getTag('idle', namespace=nbxmpp.NS_IDLE) if idle_tag is None: return since = idle_tag.getAttr('since') if since is None: log.warning('No since attr in idle node') log.warning(stanza) return timestamp = parse_datetime(since, convert='utc', epoch=True) if timestamp is None: log.warning('Invalid timestamp received: %s', since) log.warning(stanza) return timestamp gajim-gajim-1.1.3/gajim/common/modules/muc.py000066400000000000000000000410461345766322700211010ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0045: Multi-User Chat # XEP-0249: Direct MUC Invitations import time import logging import nbxmpp from gajim.common import i18n from gajim.common.modules import dataforms from gajim.common import app from gajim.common import helpers from gajim.common.caps_cache import muc_caps_cache from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.muc') class MUC: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('message', self._mediated_invite, '', nbxmpp.NS_MUC_USER), ('message', self._direct_invite, '', nbxmpp.NS_CONFERENCE), ] def pass_disco(self, from_, identities, features, _data, _node): for identity in identities: if identity.get('category') != 'conference': continue if identity.get('type') != 'text': continue if nbxmpp.NS_MUC in features: log.info('Discovered MUC: %s', from_) # TODO: make this nicer self._con.muc_jid['jabber'] = from_ raise nbxmpp.NodeProcessed def send_muc_join_presence(self, *args, room_jid=None, password=None, rejoin=False, **kwargs): if not app.account_is_connected(self._account): return presence = self._con.get_module('Presence').get_presence( *args, **kwargs) muc_x = presence.setTag(nbxmpp.NS_MUC + ' x') if room_jid is not None: self._add_history_query(muc_x, room_jid, rejoin) if password is not None: muc_x.setTagData('password', password) log.debug('Send MUC join presence:\n%s', presence) self._con.connection.send(presence) def _add_history_query(self, muc_x, room_jid, rejoin): last_date = app.logger.get_room_last_message_time( self._account, room_jid) if not last_date: last_date = 0 if muc_caps_cache.has_mam(room_jid): # The room is MAM capable dont get MUC History muc_x.setTag('history', {'maxchars': '0'}) else: # Request MUC History (not MAM) tags = {} timeout = app.config.get_per('rooms', room_jid, 'muc_restore_timeout') if timeout is None or timeout == -2: timeout = app.config.get('muc_restore_timeout') if last_date == 0 and timeout >= 0: last_date = time.time() - timeout * 60 elif not rejoin and timeout >= 0: last_date = max(last_date, time.time() - timeout * 60) last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime( last_date)) tags['since'] = last_date nb = app.config.get_per('rooms', room_jid, 'muc_restore_lines') if nb is None or nb == -2: nb = app.config.get('muc_restore_lines') if nb >= 0: tags['maxstanzas'] = nb if tags: muc_x.setTag('history', tags) def set_subject(self, room_jid, subject): if not app.account_is_connected(self._account): return message = nbxmpp.Message(room_jid, typ='groupchat', subject=subject) log.info('Set subject for %s', room_jid) self._con.connection.send(message) def request_config(self, room_jid): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='get', queryNS=nbxmpp.NS_MUC_OWNER, to=room_jid) iq.setAttr('xml:lang', i18n.LANG) log.info('Request config for %s', room_jid) self._con.connection.SendAndCallForResponse( iq, self._config_received) def _config_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) return room_jid = stanza.getFrom().getStripped() payload = stanza.getQueryPayload() for form in payload: if form.getNamespace() == nbxmpp.NS_DATA: dataform = dataforms.extend_form(node=form) log.info('Config form received for %s', room_jid) app.nec.push_incoming_event(MucOwnerReceivedEvent( None, conn=self._con, form_node=form, dataform=dataform, jid=room_jid)) break def cancel_config(self, room_jid): if not app.account_is_connected(self._account): return cancel = nbxmpp.Node(tag='x', attrs={'xmlns': nbxmpp.NS_DATA, 'type': 'cancel'}) iq = nbxmpp.Iq(typ='set', queryNS=nbxmpp.NS_MUC_OWNER, payload=cancel, to=room_jid) log.info('Cancel config for %s', room_jid) self._con.connection.SendAndCallForResponse( iq, self._default_response, {}) def destroy(self, room_jid, reason='', jid=''): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='set', queryNS=nbxmpp.NS_MUC_OWNER, to=room_jid) destroy = iq.setQuery().setTag('destroy') if reason: destroy.setTagData('reason', reason) if jid: destroy.setAttr('jid', jid) log.info('Destroy room: %s, reason: %s, alternate: %s', room_jid, reason, jid) self._con.connection.SendAndCallForResponse( iq, self._default_response, {}) def set_config(self, room_jid, form): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='set', to=room_jid, queryNS=nbxmpp.NS_MUC_OWNER) query = iq.setQuery() form.setAttr('type', 'submit') query.addChild(node=form) log.info('Set config for %s', room_jid) self._con.connection.SendAndCallForResponse( iq, self._default_response, {}) def set_affiliation(self, room_jid, users_dict): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='set', to=room_jid, queryNS=nbxmpp.NS_MUC_ADMIN) item = iq.setQuery() for jid in users_dict: affiliation = users_dict[jid].get('affiliation') reason = users_dict[jid].get('reason') or None item_tag = item.addChild('item', {'jid': jid, 'affiliation': affiliation}) if reason is not None: item_tag.setTagData('reason', reason) log.info('Set affiliation for %s: %s', room_jid, users_dict) self._con.connection.SendAndCallForResponse( iq, self._default_response, {}) def get_affiliation(self, room_jid, affiliation): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='get', to=room_jid, queryNS=nbxmpp.NS_MUC_ADMIN) item = iq.setQuery().setTag('item') item.setAttr('affiliation', affiliation) log.info('Get affiliation %s for %s', affiliation, room_jid) self._con.connection.SendAndCallForResponse( iq, self._affiliation_received) def _affiliation_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) return room_jid = stanza.getFrom().getStripped() query = stanza.getTag('query', namespace=nbxmpp.NS_MUC_ADMIN) items = query.getTags('item') users_dict = {} for item in items: try: jid = helpers.parse_jid(item.getAttr('jid')) except helpers.InvalidFormat: log.warning('Invalid JID: %s, ignoring it', item.getAttr('jid')) continue affiliation = item.getAttr('affiliation') users_dict[jid] = {'affiliation': affiliation} if item.has_attr('nick'): users_dict[jid]['nick'] = item.getAttr('nick') if item.has_attr('role'): users_dict[jid]['role'] = item.getAttr('role') reason = item.getTagData('reason') if reason: users_dict[jid]['reason'] = reason log.info('Affiliations received from %s: %s', room_jid, users_dict) app.nec.push_incoming_event(MucAdminReceivedEvent( None, conn=self._con, room_jid=room_jid, users_dict=users_dict)) def set_role(self, room_jid, nick, role, reason=''): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='set', to=room_jid, queryNS=nbxmpp.NS_MUC_ADMIN) item = iq.setQuery().setTag('item') item.setAttr('nick', nick) item.setAttr('role', role) if reason: item.addChild(name='reason', payload=reason) log.info('Set role for %s: %s %s %s', room_jid, nick, role, reason) self._con.connection.SendAndCallForResponse( iq, self._default_response, {}) def _mediated_invite(self, _con, stanza): muc_user = stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER) if muc_user is None: return if stanza.getType() == 'error': return decline = muc_user.getTag('decline') if decline is not None: room_jid = stanza.getFrom().getStripped() from_ = self._get_from(room_jid, decline) reason = decline.getTagData('reason') log.info('Invite declined: %s, %s', reason, from_) app.nec.push_incoming_event( GcDeclineReceived(None, account=self._account, from_=from_, room_jid=room_jid, reason=reason)) raise nbxmpp.NodeProcessed invite = muc_user.getTag('invite') if invite is not None: room_jid = stanza.getFrom().getStripped() from_ = self._get_from(room_jid, invite) reason = invite.getTagData('reason') password = muc_user.getTagData('password') is_continued = invite.getTag('continue') is not None log.info('Mediated invite: continued: %s, reason: %s, from: %s', is_continued, reason, from_) if room_jid in app.gc_connected[self._account] and \ app.gc_connected[self._account][room_jid]: # We are already in groupchat. Ignore invitation log.info('We are already in this room') raise nbxmpp.NodeProcessed app.nec.push_incoming_event( GcInvitationReceived(None, account=self._account, from_=from_, room_jid=room_jid, reason=reason, password=password, is_continued=is_continued)) raise nbxmpp.NodeProcessed def _get_from(self, room_jid, stanza): try: from_ = nbxmpp.JID(helpers.parse_jid(stanza.getAttr('from'))) except helpers.InvalidFormat: log.warning('Invalid JID on invite: %s, ignoring it', stanza.getAttr('from')) raise nbxmpp.NodeProcessed known_contact = app.contacts.get_contacts(self._account, room_jid) ignore = app.config.get_per( 'accounts', self._account, 'ignore_unknown_contacts') if ignore and not known_contact: log.info('Ignore invite from unknown contact %s', from_) raise nbxmpp.NodeProcessed return from_ def _direct_invite(self, _con, stanza): direct = stanza.getTag('x', namespace=nbxmpp.NS_CONFERENCE) if direct is None: return from_ = stanza.getFrom() try: room_jid = helpers.parse_jid(direct.getAttr('jid')) except helpers.InvalidFormat: log.warning('Invalid JID on invite: %s, ignoring it', direct.getAttr('jid')) raise nbxmpp.NodeProcessed reason = direct.getAttr('reason') password = direct.getAttr('password') is_continued = direct.getAttr('continue') == 'true' log.info('Direct invite: continued: %s, reason: %s, from: %s', is_continued, reason, from_) app.nec.push_incoming_event( GcInvitationReceived(None, account=self._account, from_=from_, room_jid=room_jid, reason=reason, password=password, is_continued=is_continued)) raise nbxmpp.NodeProcessed def invite(self, room, to, reason=None, continue_=False): if not app.account_is_connected(self._account): return contact = app.contacts.get_contact_from_full_jid(self._account, to) if contact and contact.supports(nbxmpp.NS_CONFERENCE): invite = self._build_direct_invite(room, to, reason, continue_) else: invite = self._build_mediated_invite(room, to, reason, continue_) self._con.connection.send(invite) @staticmethod def _build_direct_invite(room, to, reason, continue_): message = nbxmpp.Message(to=to) attrs = {'jid': room} if reason: attrs['reason'] = reason if continue_: attrs['continue'] = 'true' password = app.gc_passwords.get(room, None) if password: attrs['password'] = password message.addChild(name='x', attrs=attrs, namespace=nbxmpp.NS_CONFERENCE) return message @staticmethod def _build_mediated_invite(room, to, reason, continue_): message = nbxmpp.Message(to=room) muc_user = message.addChild('x', namespace=nbxmpp.NS_MUC_USER) invite = muc_user.addChild('invite', attrs={'to': to}) if continue_: invite.addChild(name='continue') if reason: invite.setTagData('reason', reason) password = app.gc_passwords.get(room, None) if password: muc_user.setTagData('password', password) return message def decline(self, room, to, reason=None): if not app.account_is_connected(self._account): return message = nbxmpp.Message(to=room) muc_user = message.addChild('x', namespace=nbxmpp.NS_MUC_USER) decline = muc_user.addChild('decline', attrs={'to': to}) if reason: decline.setTagData('reason', reason) self._con.connection.send(message) def request_voice(self, room): if not app.account_is_connected(self._account): return message = nbxmpp.Message(to=room) xdata = nbxmpp.DataForm(typ='submit') xdata.addChild(node=nbxmpp.DataField(name='FORM_TYPE', value=nbxmpp.NS_MUC + '#request')) xdata.addChild(node=nbxmpp.DataField(name='muc#role', value='participant', typ='text-single')) message.addChild(node=xdata) self._con.connection.send(message) @staticmethod def _default_response(_con, stanza, **kwargs): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) class GcInvitationReceived(NetworkIncomingEvent): name = 'gc-invitation-received' class GcDeclineReceived(NetworkIncomingEvent): name = 'gc-decline-received' class MucAdminReceivedEvent(NetworkIncomingEvent): name = 'muc-admin-received' class MucOwnerReceivedEvent(NetworkIncomingEvent): name = 'muc-owner-received' def get_instance(*args, **kwargs): return MUC(*args, **kwargs), 'MUC' gajim-gajim-1.1.3/gajim/common/modules/pep.py000066400000000000000000000174411345766322700211030ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0163: Personal Eventing Protocol from typing import Any from typing import Dict from typing import List from typing import Tuple import logging import nbxmpp from gajim.common import app from gajim.common.exceptions import StanzaMalformed from gajim.common.nec import NetworkIncomingEvent from gajim.common.const import PEPEventType from gajim.common.types import ConnectionT from gajim.common.types import PEPHandlersDict # pylint: disable=unused-import from gajim.common.types import PEPNotifyCallback log = logging.getLogger('gajim.c.m.pep') class PEP: def __init__(self, con: ConnectionT) -> None: self._con = con self._account = con.name self.handlers = [ ('message', self._pep_event_received, 'headline', nbxmpp.NS_PUBSUB_EVENT) ] self.supported = False self._pep_handlers = {} # type: PEPHandlersDict self._store_publish_modules = [] # type: List[Any] def pass_disco(self, from_: nbxmpp.JID, identities: List[Dict[str, str]], _features: List[str], _data: List[nbxmpp.DataForm], _node: str) -> None: for identity in identities: if identity['category'] == 'pubsub': if identity.get('type') == 'pep': log.info('Discovered PEP support: %s', from_) self.supported = True def register_pep_handler( self, namespace: str, notify_handler: PEPNotifyCallback) -> None: if namespace in self._pep_handlers: self._pep_handlers[namespace].append(notify_handler) else: self._pep_handlers[namespace] = [notify_handler] module_instance = notify_handler.__self__ # type: ignore if module_instance.store_publish: if module_instance not in self._store_publish_modules: self._store_publish_modules.append(module_instance) def _pep_event_received(self, _con: ConnectionT, stanza: nbxmpp.Message) -> None: jid = stanza.getFrom() event = stanza.getTag('event', namespace=nbxmpp.NS_PUBSUB_EVENT) items = event.getTag('items') if items is None: log.warning('Malformed PEP event (no items node): %s', stanza) raise nbxmpp.NodeProcessed namespace = items.getAttr('node') if namespace is None: log.warning('Malformed PEP event (no node attr): %s', stanza) raise nbxmpp.NodeProcessed log.info('PEP notification received: %s %s', jid, namespace) handlers = self._pep_handlers.get(namespace, None) if handlers is None: # Old Fallback from gajim.common.connection_handlers_events import PEPReceivedEvent as OldPEPReceivedEvent app.nec.push_incoming_event( OldPEPReceivedEvent(None, conn=self._con, stanza=stanza)) raise nbxmpp.NodeProcessed else: # Check if this is a retraction retract = items.getTag('retract') if retract is not None: id_ = retract.getAttr('id') log.info('Received retract of id: %s', id_) raise nbxmpp.NodeProcessed # Check if we have items items_ = items.getTags('item') if items_ is None: log.warning('Malformed PEP event received: %s', stanza) raise nbxmpp.NodeProcessed for handler in handlers: handler(jid, items_[0]) raise nbxmpp.NodeProcessed def send_stored_publish(self) -> None: for module in self._store_publish_modules: module.send_stored_publish() def reset_stored_publish(self) -> None: for module in self._store_publish_modules: module.reset_stored_publish() class AbstractPEPData: type_ = PEPEventType.ABSTRACT def __init__(self, data: Any) -> None: self.data = data def as_markup_text(self) -> str: # pylint: disable=no-self-use '''SHOULD be implemented by subclasses''' return '' def __eq__(self, other: Any) -> bool: return other == self.type_ def __bool__(self) -> bool: return self.data is not None def __str__(self) -> str: return str(self.data) class AbstractPEPModule: name = '' namespace = '' pep_class = AbstractPEPData store_publish = True _log = log def __init__(self, con: ConnectionT, account: str) -> None: self._account = account self._con = con self._stored_publish = None self._con.get_module('PEP').register_pep_handler( self.namespace, self._pep_notify_received) def _pep_notify_received(self, jid: nbxmpp.JID, item: nbxmpp.Node) -> None: try: data = self._extract_info(item) except StanzaMalformed as error: log.warning('%s, %s: %s', jid, error, item) return self._log.info('Received: %s %s', jid, data) user_pep = self.pep_class(data) self._notification_received(jid, user_pep) app.nec.push_incoming_event( PEPReceivedEvent(None, conn=self._con, jid=str(jid), pep_type=self.name, user_pep=user_pep)) def _extract_info(self, item: nbxmpp.Node) -> Any: '''To be implemented by subclasses''' raise NotImplementedError def _build_node(self, data: Any) -> nbxmpp.Node: '''To be implemented by subclasses''' raise NotImplementedError def _notification_received(self, jid: nbxmpp.JID, user_pep: Any) -> None: for contact in app.contacts.get_contacts(self._account, str(jid)): if user_pep: contact.pep[self.name] = user_pep else: contact.pep.pop(self.name, None) if jid == self._con.get_own_jid().getStripped(): if user_pep: self._con.pep[self.name] = user_pep else: self._con.pep.pop(self.name, None) def send_stored_publish(self) -> None: if self._stored_publish is not None: self._log.info('Send stored publish') self.send(self._stored_publish) self._stored_publish = None def reset_stored_publish(self) -> None: self._log.info('Reset stored publish') self._stored_publish = None def send(self, data: Any) -> None: if not self._con.get_module('PEP').supported: return if self._con.connected == 1: # We are connecting, save activity and send it later self._stored_publish = data return if data: self._log.info('Send: %s', data) else: self._log.info('Remove') item = self._build_node(data) self._con.get_module('PubSub').send_pb_publish( '', self.namespace, item, 'current') class PEPReceivedEvent(NetworkIncomingEvent): name = 'pep-received' def get_instance(*args: Any, **kwargs: Any) -> Tuple[PEP, str]: return PEP(*args, **kwargs), 'PEP' gajim-gajim-1.1.3/gajim/common/modules/ping.py000066400000000000000000000105231345766322700212460ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0199: XMPP Ping from typing import Any from typing import Tuple import logging import time import nbxmpp from gajim.common import app from gajim.common.nec import NetworkIncomingEvent from gajim.common.types import ConnectionT from gajim.common.types import ContactsT log = logging.getLogger('gajim.c.m.ping') class Ping: def __init__(self, con: ConnectionT) -> None: self._con = con self._account = con.name self._alarm_time = None self.handlers = [ ('iq', self._answer_request, 'get', nbxmpp.NS_PING), ] @staticmethod def _get_ping_iq(to: str) -> nbxmpp.Iq: iq = nbxmpp.Iq('get', to=to) iq.addChild(name='ping', namespace=nbxmpp.NS_PING) return iq def send_keepalive_ping(self) -> None: if not app.account_is_connected(self._account): return to = app.config.get_per('accounts', self._account, 'hostname') self._con.connection.SendAndCallForResponse(self._get_ping_iq(to), self._keepalive_received) log.info('Send keepalive') seconds = app.config.get_per('accounts', self._account, 'time_for_ping_alive_answer') self._alarm_time = app.idlequeue.set_alarm(self._reconnect, seconds) def _keepalive_received(self, _stanza: nbxmpp.Iq) -> None: log.info('Received keepalive') app.idlequeue.remove_alarm(self._reconnect, self._alarm_time) def _reconnect(self) -> None: if not app.config.get_per('accounts', self._account, 'active'): # Account may have been disabled return # We haven't got the pong in time, disco and reconnect log.warning('No reply received for keepalive ping. Reconnecting...') self._con.disconnectedReconnCB() def send_ping(self, contact: ContactsT) -> None: if not app.account_is_connected(self._account): return to = contact.get_full_jid() iq = self._get_ping_iq(to) log.info('Send ping to %s', to) self._con.connection.SendAndCallForResponse( iq, self._pong_received, {'ping_time': time.time(), 'contact': contact}) app.nec.push_incoming_event( PingSentEvent(None, conn=self._con, contact=contact)) def _pong_received(self, _con: ConnectionT, stanza: nbxmpp.Iq, ping_time: int, contact: ContactsT) -> None: if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event( PingErrorEvent(None, conn=self._con, contact=contact)) return diff = round(time.time() - ping_time, 2) log.info('Received pong from %s after %s seconds', stanza.getFrom(), diff) app.nec.push_incoming_event( PingReplyEvent(None, conn=self._con, contact=contact, seconds=diff)) def _answer_request(self, _con: ConnectionT, stanza: nbxmpp.Iq) -> None: iq = stanza.buildReply('result') ping = iq.getTag('ping') if ping is not None: iq.delChild(ping) self._con.connection.send(iq) log.info('Send pong to %s', stanza.getFrom()) raise nbxmpp.NodeProcessed class PingSentEvent(NetworkIncomingEvent): name = 'ping-sent' class PingReplyEvent(NetworkIncomingEvent): name = 'ping-reply' class PingErrorEvent(NetworkIncomingEvent): name = 'ping-error' def get_instance(*args: Any, **kwargs: Any) -> Tuple[Ping, str]: return Ping(*args, **kwargs), 'Ping' gajim-gajim-1.1.3/gajim/common/modules/presence.py000066400000000000000000000204121345766322700221130ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # Presence handler import logging import nbxmpp from gajim.common import app from gajim.common.i18n import _ from gajim.common.nec import NetworkEvent from gajim.common.modules.user_nickname import parse_nickname log = logging.getLogger('gajim.c.m.presence') class Presence: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('presence', self._presence_received), ('presence', self._subscribe_received, 'subscribe'), ('presence', self._subscribed_received, 'subscribed'), ('presence', self._unsubscribe_received, 'unsubscribe'), ('presence', self._unsubscribed_received, 'unsubscribed'), ] # keep the jids we auto added (transports contacts) to not send the # SUBSCRIBED event to GUI self.automatically_added = [] # list of jid to auto-authorize self.jids_for_auto_auth = [] def _presence_received(self, _con, stanza): if stanza.getType() in ('subscribe', 'subscribed', 'unsubscribe', 'unsubscribed'): # Dont handle that here return log.info('Received from %s', stanza.getFrom()) if nbxmpp.isErrorNode(stanza): log.info('Error:\n%s', stanza) app.nec.push_incoming_event( NetworkEvent('raw-pres-received', conn=self._con, stanza=stanza)) def _subscribe_received(self, _con, stanza): from_ = stanza.getFrom() jid = from_.getStripped() fjid = str(from_) status = stanza.getStatus() is_transport = app.jid_is_transport(fjid) auto_auth = app.config.get_per('accounts', self._account, 'autoauth') user_nick = parse_nickname(stanza) log.info('Received Subscribe: %s, transport: %s, auto_auth: %s, ' 'user_nick: %s', from_, is_transport, auto_auth, user_nick) if is_transport and fjid in self._con.agent_registrations: self._con.agent_registrations[fjid]['sub_received'] = True if not self._con.agent_registrations[fjid]['roster_push']: # We'll reply after roster push result raise nbxmpp.NodeProcessed if auto_auth or is_transport or jid in self.jids_for_auto_auth: self.send_presence(fjid, 'subscribed') if not status: status = _('I would like to add you to my roster.') app.nec.push_incoming_event(NetworkEvent( 'subscribe-presence-received', conn=self._con, jid=jid, fjid=fjid, status=status, user_nick=user_nick, is_transport=is_transport)) raise nbxmpp.NodeProcessed def _subscribed_received(self, _con, stanza): from_ = stanza.getFrom() jid = from_.getStripped() resource = from_.getResource() log.info('Received Subscribed: %s', from_) if jid in self.automatically_added: self.automatically_added.remove(jid) raise nbxmpp.NodeProcessed app.nec.push_incoming_event(NetworkEvent( 'subscribed-presence-received', conn=self._con, jid=jid, resource=resource)) raise nbxmpp.NodeProcessed @staticmethod def _unsubscribe_received(_con, stanza): log.info('Received Unsubscribe: %s', stanza.getFrom()) raise nbxmpp.NodeProcessed def _unsubscribed_received(self, _con, stanza): from_ = stanza.getFrom() jid = from_.getStripped() log.info('Received Unsubscribed: %s', from_) app.nec.push_incoming_event(NetworkEvent( 'unsubscribed-presence-received', conn=self._con, jid=jid)) raise nbxmpp.NodeProcessed def subscribed(self, jid): if not app.account_is_connected(self._account): return log.info('Subscribed: %s', jid) self.send_presence(jid, 'subscribed') def unsubscribed(self, jid): if not app.account_is_connected(self._account): return log.info('Unsubscribed: %s', jid) self.send_presence(jid, 'unsubscribed') def unsubscribe(self, jid, remove_auth=True): if not app.account_is_connected(self._account): return if remove_auth: self._con.getRoster().del_item(jid) jid_list = app.config.get_per('contacts') for j in jid_list: if j.startswith(jid): app.config.del_per('contacts', j) else: log.info('Unsubscribe from %s', jid) self._con.getRoster().unsubscribe(jid) self._con.getRoster().set_item(jid) def subscribe(self, jid, msg=None, name='', groups=None, auto_auth=False): if not app.account_is_connected(self._account): return if groups is None: groups = [] log.info('Request Subscription to %s', jid) if auto_auth: self.jids_for_auto_auth.append(jid) infos = {'jid': jid} if name: infos['name'] = name iq = nbxmpp.Iq('set', nbxmpp.NS_ROSTER) query = iq.setQuery() item = query.addChild('item', attrs=infos) for group in groups: item.addChild('group').setData(group) self._con.connection.send(iq) self.send_presence(jid, 'subscribe', status=msg) def get_presence(self, to=None, typ=None, priority=None, show=None, status=None, nick=None, caps=True, sign=None, idle_time=None): if show not in ('chat', 'away', 'xa', 'dnd'): # Gajim sometimes passes invalid show values here # until this is fixed this is a workaround show = None presence = nbxmpp.Presence(to, typ, priority, show, status) if nick is not None: nick_tag = presence.setTag('nick', namespace=nbxmpp.NS_NICK) nick_tag.setData(nick) if sign: presence.setTag(nbxmpp.NS_SIGNED + ' x').setData(sign) if idle_time is not None: idle_node = presence.setTag('idle', namespace=nbxmpp.NS_IDLE) idle_node.setAttr('since', idle_time) if not self._con.avatar_conversion: # XEP-0398 not supported by server so # we add the avatar sha to our presence self._con.get_module('VCardAvatars').add_update_node(presence) if caps: attrs = {'hash': 'sha-1', 'node': 'http://gajim.org', 'ver': app.caps_hash[self._account]} presence.setTag('c', namespace=nbxmpp.NS_CAPS, attrs=attrs) return presence def send_presence(self, *args, **kwargs): if not app.account_is_connected(self._account): return presence = self.get_presence(*args, **kwargs) log.debug('Send presence:\n%s', presence) self._con.connection.send(presence) def parse_show(stanza): show = stanza.getShow() type_ = parse_type(stanza) if show is None and type_ is None: return 'online' if type_ == 'unavailable': return 'offline' if show not in (None, 'chat', 'away', 'xa', 'dnd'): log.warning('Invalid show element: %s', stanza) if type_ is None: return 'online' return 'offline' if show is None: return 'online' return show def parse_type(stanza): type_ = stanza.getType() if type_ not in (None, 'unavailable', 'error', 'subscribe', 'subscribed', 'unsubscribe', 'unsubscribed'): log.warning('Invalid type: %s', stanza) return None return type_ def get_instance(*args, **kwargs): return Presence(*args, **kwargs), 'Presence' gajim-gajim-1.1.3/gajim/common/modules/privacylists.py000066400000000000000000000411061345766322700230460ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0016: Privacy Lists import logging import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.nec import NetworkIncomingEvent from gajim.common.connection_handlers_events import InformationEvent log = logging.getLogger('gajim.c.m.privacylists') class PrivacyLists: def __init__(self, con): self._con = con self._account = con.name self.default_list = None self.active_list = None self.blocked_contacts = [] self.blocked_groups = [] self.blocked_list = [] self.blocked_all = False self.handlers = [ ('iq', self._list_push_received, 'set', nbxmpp.NS_PRIVACY) ] self.supported = False def pass_disco(self, from_, _identities, features, _data, _node): if nbxmpp.NS_PRIVACY not in features: return self.supported = True log.info('Discovered XEP-0016: Privacy Lists: %s', from_) # TODO: Move this GUI code out action = app.app.lookup_action('%s-privacylists' % self._account) action.set_enabled(True) def _list_push_received(self, _con, stanza): result = stanza.buildReply('result') result.delChild(result.getTag('query')) self._con.connection.send(result) for list_ in stanza.getQueryPayload(): if list_.getName() == 'list': name = list_.getAttr('name') log.info('Received Push: %s', name) self.get_privacy_list(name) raise nbxmpp.NodeProcessed def get_privacy_lists(self, callback=None): log.info('Request lists') iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVACY) self._con.connection.SendAndCallForResponse( iq, self._privacy_lists_received, {'callback': callback}) def _privacy_lists_received(self, _con, stanza, callback): lists = [] new_default = None result = nbxmpp.isResultNode(stanza) if not result: log.warning('List not available: %s', stanza.getError()) else: for list_ in stanza.getQueryPayload(): name = list_.getAttr('name') if list_.getName() == 'active': self.active_list = name elif list_.getName() == 'default': new_default = name else: lists.append(name) log.info('Received lists: %s', lists) # Download default list if we dont have it if self.default_list != new_default: self.default_list = new_default if new_default is not None: log.info('Found new default list: %s', new_default) self.get_privacy_list(new_default) if callback: callback(result) else: app.nec.push_incoming_event( PrivacyListsReceivedEvent(None, conn=self._con, active_list=self.active_list, default_list=self.default_list, lists=lists)) def get_privacy_list(self, name): log.info('Request list: %s', name) list_ = nbxmpp.Node('list', {'name': name}) iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVACY, payload=[list_]) self._con.connection.SendAndCallForResponse( iq, self._privacy_list_received) def _privacy_list_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.warning('List not available: %s', stanza.getError()) return rules = [] list_ = stanza.getQueryPayload()[0] name = list_.getAttr('name') for child in list_.getChildren(): item = child.getAttrs() childs = [] for scnd_child in child.getChildren(): childs.append(scnd_child.getName()) item['child'] = childs if len(item) not in (3, 5): log.warning('Wrong count of attrs: %s', stanza) continue rules.append(item) log.info('Received list: %s', name) if name == self.default_list: self._default_list_received(rules) app.nec.push_incoming_event(PrivacyListReceivedEvent( None, conn=self._con, list_name=name, rules=rules)) def del_privacy_list(self, name): log.info('Remove list: %s', name) def _del_privacy_list_result(stanza): if not nbxmpp.isResultNode(stanza): log.warning('List deletion failed: %s', stanza.getError()) app.nec.push_incoming_event(InformationEvent( None, dialog_name='privacy-list-error', args=name)) else: app.nec.push_incoming_event(PrivacyListRemovedEvent( None, conn=self._con, list_name=name)) node = nbxmpp.Node('list', {'name': name}) iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node]) self._con.connection.SendAndCallForResponse( iq, _del_privacy_list_result) def set_privacy_list(self, name, rules): node = nbxmpp.Node('list', {'name': name}) iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node]) for item in rules: childs = item.get('child', []) for child in childs: node.setTag(child) item.pop('child', None) node.setTag('item', item) log.info('Update list: %s %s', name, rules) self._con.connection.SendAndCallForResponse( iq, self._default_result_handler, {}) def _default_list_received(self, rules): roster = app.interface.roster for rule in rules: if rule['action'] == 'allow': if 'type' not in rule: self.blocked_all = False elif rule['type'] == 'jid': if rule['value'] in self.blocked_contacts: self.blocked_contacts.remove(rule['value']) elif rule['type'] == 'group': if rule['value'] in self.blocked_groups: self.blocked_groups.remove(rule['value']) elif rule['action'] == 'deny': if 'type' not in rule: self.blocked_all = True elif rule['type'] == 'jid': if rule['value'] not in self.blocked_contacts: self.blocked_contacts.append(rule['value']) elif rule['type'] == 'group': if rule['value'] not in self.blocked_groups: self.blocked_groups.append(rule['value']) self.blocked_list.append(rule) if 'type' in rule: if rule['type'] == 'jid': roster.draw_contact(rule['value'], self._account) if rule['type'] == 'group': roster.draw_group(rule['value'], self._account) def set_active_list(self, name=None): log.info('Set active list: %s', name) attr = {} if name: attr['name'] = name node = nbxmpp.Node('active', attr) iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node]) self._con.connection.SendAndCallForResponse( iq, self._default_result_handler, {}) def set_default_list(self, name=None): log.info('Set default list: %s', name) attr = {} if name: attr['name'] = name node = nbxmpp.Node('default', attr) iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node]) self._con.connection.SendAndCallForResponse( iq, self._default_result_handler, {}) @staticmethod def _default_result_handler(_con, stanza): if not nbxmpp.isResultNode(stanza): log.warning('Operation failed: %s', stanza.getError()) def _build_invisible_rule(self): node = nbxmpp.Node('list', {'name': 'invisible'}) iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node]) if (self._account in app.interface.status_sent_to_groups and app.interface.status_sent_to_groups[self._account]): for group in app.interface.status_sent_to_groups[self._account]: item = node.setTag('item', {'type': 'group', 'value': group, 'action': 'allow', 'order': '1'}) item.setTag('presence-out') if (self._account in app.interface.status_sent_to_users and app.interface.status_sent_to_users[self._account]): for jid in app.interface.status_sent_to_users[self._account]: item = node.setTag('item', {'type': 'jid', 'value': jid, 'action': 'allow', 'order': '2'}) item.setTag('presence-out') item = node.setTag('item', {'action': 'deny', 'order': '3'}) item.setTag('presence-out') return iq def set_invisible_rule(self, callback=None, **kwargs): log.info('Update invisible list') iq = self._build_invisible_rule() if callback is None: callback = self._default_result_handler self._con.connection.SendAndCallForResponse( iq, callback, kwargs) def _get_max_blocked_list_order(self): max_order = 0 for rule in self.blocked_list: order = int(rule['order']) if order > max_order: max_order = order return max_order def block_gc_contact(self, jid): if jid in self.blocked_contacts: return log.info('Block GC contact: %s', jid) if self.default_list is None: self.default_list = 'block' max_order = self._get_max_blocked_list_order() new_rule = {'order': str(max_order + 1), 'type': 'jid', 'action': 'deny', 'value': jid, 'child': ['message', 'iq', 'presence-out']} self.blocked_list.append(new_rule) self.blocked_contacts.append(jid) self.set_privacy_list(self.default_list, self.blocked_list) if len(self.blocked_list) == 1: self.set_default_list(self.default_list) def block_contacts(self, contact_list, message): if not self.supported: self._con.get_module('Blocking').block(contact_list) return if self.default_list is None: self.default_list = 'block' for contact in contact_list: log.info('Block contacts: %s', contact.jid) contact.show = 'offline' self._con.send_custom_status('offline', message, contact.jid) max_order = self._get_max_blocked_list_order() new_rule = {'order': str(max_order + 1), 'type': 'jid', 'action': 'deny', 'value': contact.jid} self.blocked_list.append(new_rule) self.blocked_contacts.append(contact.jid) self.set_privacy_list(self.default_list, self.blocked_list) if len(self.blocked_list) == 1: self.set_default_list(self.default_list) def unblock_gc_contact(self, jid): new_blocked_list = [] # needed for draw_contact: if jid not in self.blocked_contacts: return self.blocked_contacts.remove(jid) log.info('Unblock GC contact: %s', jid) for rule in self.blocked_list: if (rule['action'] != 'deny' or rule['type'] != 'jid' or rule['value'] != jid): new_blocked_list.append(rule) if not new_blocked_list: self.blocked_list = [] self.blocked_contacts = [] self.blocked_groups = [] self.set_default_list(None) self.del_privacy_list(self.default_list) else: self.set_privacy_list(self.default_list, new_blocked_list) def unblock_contacts(self, contact_list): if not self.supported: self._con.get_module('Blocking').unblock(contact_list) return new_blocked_list = [] to_unblock = [] for contact in contact_list: log.info('Unblock contacts: %s', contact.jid) to_unblock.append(contact.jid) if contact.jid in self.blocked_contacts: self.blocked_contacts.remove(contact.jid) for rule in self.blocked_list: if (rule['action'] != 'deny' or rule['type'] != 'jid' or rule['value'] not in to_unblock): new_blocked_list.append(rule) if not new_blocked_list: self.blocked_list = [] self.blocked_contacts = [] self.blocked_groups = [] self.set_default_list(None) self.del_privacy_list(self.default_list) else: self.set_privacy_list(self.default_list, new_blocked_list) if not app.interface.roster.regroup: show = app.SHOW_LIST[self._con.connected] else: # accounts merged show = helpers.get_global_show() if show == 'invisible': return for contact in contact_list: self._con.send_custom_status(show, self._con.status, contact.jid) self._presence_probe(contact.jid) def block_group(self, group, contact_list, message): if not self.supported: return if group in self.blocked_groups: return self.blocked_groups.append(group) log.info('Block group: %s', group) if self.default_list is None: self.default_list = 'block' for contact in contact_list: self._con.send_custom_status('offline', message, contact.jid) max_order = self._get_max_blocked_list_order() new_rule = {'order': str(max_order + 1), 'type': 'group', 'action': 'deny', 'value': group} self.blocked_list.append(new_rule) self.set_privacy_list(self.default_list, self.blocked_list) if len(self.blocked_list) == 1: self.set_default_list(self.default_list) def unblock_group(self, group, contact_list): if not self.supported: return if group not in self.blocked_groups: return self.blocked_groups.remove(group) log.info('Unblock group: %s', group) new_blocked_list = [] for rule in self.blocked_list: if (rule['action'] != 'deny' or rule['type'] != 'group' or rule['value'] != group): new_blocked_list.append(rule) if not new_blocked_list: self.blocked_list = [] self.blocked_contacts = [] self.blocked_groups = [] self.set_default_list('') self.del_privacy_list(self.default_list) else: self.set_privacy_list(self.default_list, new_blocked_list) if not app.interface.roster.regroup: show = app.SHOW_LIST[self._con.connected] else: # accounts merged show = helpers.get_global_show() if show == 'invisible': return for contact in contact_list: self._con.send_custom_status(show, self._con.status, contact.jid) def _presence_probe(self, jid): log.info('Presence probe: %s', jid) # Send a presence Probe to get the current Status probe = nbxmpp.Presence(jid, 'probe', frm=self._con.get_own_jid()) self._con.connection.send(probe) class PrivacyListsReceivedEvent(NetworkIncomingEvent): name = 'privacy-lists-received' class PrivacyListReceivedEvent(NetworkIncomingEvent): name = 'privacy-list-received' class PrivacyListRemovedEvent(NetworkIncomingEvent): name = 'privacy-list-removed' def get_instance(*args, **kwargs): return PrivacyLists(*args, **kwargs), 'PrivacyLists' gajim-gajim-1.1.3/gajim/common/modules/pubsub.py000066400000000000000000000223241345766322700216130ustar00rootroot00000000000000# Copyright (C) 2006 Tomasz Melcer # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Jean-Marie Traissard # Copyright (C) 2008 Stephan Erb # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0060: Publish-Subscribe import logging import nbxmpp from gajim.common import app from gajim.common.modules import dataforms from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.pubsub') class PubSub: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] self.publish_options = False def pass_disco(self, from_, _identities, features, _data, _node): if nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS not in features: # Remove stored bookmarks accessible to everyone. self._con.get_module('Bookmarks').purge_pubsub_bookmarks() return log.info('Discovered Pubsub publish options: %s', from_) self.publish_options = True def send_pb_subscription_query(self, jid, cb, **kwargs): if not app.account_is_connected(self._account): return query = nbxmpp.Iq('get', to=jid) pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB) pb.addChild('subscriptions') self._con.connection.SendAndCallForResponse(query, cb, kwargs) def send_pb_subscribe(self, jid, node, cb, **kwargs): if not app.account_is_connected(self._account): return our_jid = app.get_jid_from_account(self._account) query = nbxmpp.Iq('set', to=jid) pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB) pb.addChild('subscribe', {'node': node, 'jid': our_jid}) self._con.connection.SendAndCallForResponse(query, cb, kwargs) def send_pb_unsubscribe(self, jid, node, cb, **kwargs): if not app.account_is_connected(self._account): return our_jid = app.get_jid_from_account(self._account) query = nbxmpp.Iq('set', to=jid) pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB) pb.addChild('unsubscribe', {'node': node, 'jid': our_jid}) self._con.connection.SendAndCallForResponse(query, cb, kwargs) def send_pb_publish(self, jid, node, item, id_=None, options=None, cb=None, **kwargs): if not app.account_is_connected(self._account): return if cb is None: cb = self._default_callback query = nbxmpp.Iq('set', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB) publish = pubsub.addChild('publish', {'node': node}) attrs = {} if id_: attrs = {'id': id_} publish.addChild('item', attrs, [item]) if options: publish = pubsub.addChild('publish-options') publish.addChild(node=options) self._con.connection.SendAndCallForResponse(query, cb, kwargs) @staticmethod def get_pb_retrieve_iq(jid, node, item_id=None): """ Get IQ to query items from a node """ query = nbxmpp.Iq('get', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB) items = pubsub.addChild('items', {'node': node}) if item_id is not None: items.addChild('item', {'id': item_id}) return query def send_pb_retrieve(self, jid, node, item_id=None, cb=None, **kwargs): """ Get items from a node """ if not app.account_is_connected(self._account): return if cb is None: cb = self._default_callback query = self.get_pb_retrieve_iq(jid, node, item_id) self._con.connection.SendAndCallForResponse(query, cb, kwargs) def send_pb_retract(self, jid, node, id_, cb=None, **kwargs): """ Delete item from a node """ if not app.account_is_connected(self._account): return if cb is None: cb = self._default_callback query = nbxmpp.Iq('set', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB) retract = pubsub.addChild('retract', {'node': node, 'notify': '1'}) retract.addChild('item', {'id': id_}) self._con.connection.SendAndCallForResponse(query, cb, kwargs) def send_pb_purge(self, jid, node, cb=None, **kwargs): """ Purge node: Remove all items """ if not app.account_is_connected(self._account): return if cb is None: cb = self._default_callback query = nbxmpp.Iq('set', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER) pubsub.addChild('purge', {'node': node}) self._con.connection.SendAndCallForResponse(query, cb, kwargs) def send_pb_delete(self, jid, node, on_ok=None, on_fail=None): """ Delete node """ if not app.account_is_connected(self._account): return query = nbxmpp.Iq('set', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER) pubsub.addChild('delete', {'node': node}) def response(_con, resp, jid, node): if resp.getType() == 'result' and on_ok: on_ok(jid, node) elif on_fail: msg = resp.getErrorMsg() on_fail(jid, node, msg) self._con.connection.SendAndCallForResponse( query, response, {'jid': jid, 'node': node}) def send_pb_create(self, jid, node, cb, configure=False, configure_form=None): """ Create a new node """ if not app.account_is_connected(self._account): return query = nbxmpp.Iq('set', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB) create = pubsub.addChild('create', {'node': node}) if configure: conf = create.addChild('configure') if configure_form is not None: conf.addChild(node=configure_form) self._con.connection.SendAndCallForResponse(query, cb) def send_pb_configure(self, jid, node, form, cb=None, **kwargs): if not app.account_is_connected(self._account): return if cb is None: cb = self._default_callback query = nbxmpp.Iq('set', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER) configure = pubsub.addChild('configure', {'node': node}) configure.addChild(node=form) log.info('Send node config for %s', node) self._con.connection.SendAndCallForResponse(query, cb, kwargs) def request_pb_configuration(self, jid, node): if not app.account_is_connected(self._account): return query = nbxmpp.Iq('get', to=jid) pubsub = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER) pubsub.addChild('configure', {'node': node}) log.info('Request node config for %s', node) self._con.connection.SendAndCallForResponse( query, self._received_pb_configuration, {'node': node}) def _received_pb_configuration(self, _con, stanza, node): if not nbxmpp.isResultNode(stanza): log.warning('Error: %s', stanza.getError()) return pubsub = stanza.getTag('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER) if pubsub is None: log.warning('Malformed PubSub configure ' 'stanza (no pubsub node): %s', stanza) return configure = pubsub.getTag('configure') if configure is None: log.warning('Malformed PubSub configure ' 'stanza (no configure node): %s', stanza) return if configure.getAttr('node') != node: log.warning('Malformed PubSub configure ' 'stanza (wrong node): %s', stanza) return form = configure.getTag('x', namespace=nbxmpp.NS_DATA) if form is None: log.warning('Malformed PubSub configure ' 'stanza (no form): %s', stanza) return app.nec.push_incoming_event(PubSubConfigReceivedEvent( None, conn=self._con, node=node, form=dataforms.extend_form(node=form))) @staticmethod def _default_callback(_con, stanza, *args, **kwargs): if not nbxmpp.isResultNode(stanza): log.warning('Error: %s', stanza.getError()) class PubSubConfigReceivedEvent(NetworkIncomingEvent): name = 'pubsub-config-received' def get_instance(*args, **kwargs): return PubSub(*args, **kwargs), 'PubSub' gajim-gajim-1.1.3/gajim/common/modules/receipts.py000066400000000000000000000067451345766322700221420ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0184: Message Delivery Receipts import logging import nbxmpp from gajim.common import app from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.receipts') class Receipts: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] def delegate(self, event): request = event.stanza.getTag('request', namespace=nbxmpp.NS_RECEIPTS) if request is not None: self._answer_request(event) return received = event.stanza.getTag('received', namespace=nbxmpp.NS_RECEIPTS) if received is not None: self._receipt_received(event, received) raise nbxmpp.NodeProcessed def _answer_request(self, event): if not app.config.get_per('accounts', self._account, 'answer_receipts'): return if event.mtype not in ('chat', 'normal'): return if event.sent: # Never answer messages that we sent from another device return from_ = event.stanza.getFrom() if self._con.get_own_jid().bareMatch(from_): # Dont answer receipts from our other resources return receipt_id = event.stanza.getID() contact = self._get_contact(event) if contact is None: return receipt = self._build_answer_receipt(from_, receipt_id) log.info('Answer %s', receipt_id) self._con.connection.send(receipt) def _get_contact(self, event): if event.muc_pm: return app.contacts.get_gc_contact(self._account, event.jid, event.resource) contact = app.contacts.get_contact(self._account, event.jid) if contact is not None and contact.sub not in ('to', 'none'): return contact @staticmethod def _build_answer_receipt(to, receipt_id): receipt = nbxmpp.Message(to=to, typ='chat') receipt.setTag('received', namespace='urn:xmpp:receipts', attrs={'id': receipt_id}) return receipt def _receipt_received(self, event, received): receipt_id = received.getAttr('id') if receipt_id is None: log.warning('Receipt without ID: %s', event.stanza) return log.info('Received %s', receipt_id) jid = event.jid if event.muc_pm: jid = event.fjid app.nec.push_incoming_event( NetworkIncomingEvent('receipt-received', conn=self._con, receipt_id=receipt_id, jid=jid)) def get_instance(*args, **kwargs): return Receipts(*args, **kwargs), 'Receipts' gajim-gajim-1.1.3/gajim/common/modules/register.py000066400000000000000000000127331345766322700221420ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0077: In-Band Registration import logging import weakref import nbxmpp from gajim.common import app log = logging.getLogger('gajim.c.m.register') class Register: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] self.agent_registrations = {} def change_password(self, password, success_cb, error_cb): if not app.account_is_connected(self._account): return hostname = app.config.get_per('accounts', self._account, 'hostname') username = app.config.get_per('accounts', self._account, 'name') iq = nbxmpp.Iq(typ='set', to=hostname) query = iq.setTag(nbxmpp.NS_REGISTER + ' query') query.setTagData('username', username) query.setTagData('password', password) weak_success_cb = weakref.WeakMethod(success_cb) weak_error_cb = weakref.WeakMethod(error_cb) log.info('Send password change') self._con.connection.SendAndCallForResponse( iq, self._change_password_response, {'success_cb': weak_success_cb, 'error_cb': weak_error_cb}) @staticmethod def _change_password_response(_con, stanza, success_cb, error_cb): if not nbxmpp.isResultNode(stanza): error = stanza.getErrorMsg() log.info('Error: %s', error) if error_cb() is not None: error_cb()(error) else: log.info('Password changed') if success_cb() is not None: success_cb()() def register_agent(self, agent, form, is_form, success_cb, error_cb): if not app.account_is_connected(self._account): return weak_success_cb = weakref.WeakMethod(success_cb) weak_error_cb = weakref.WeakMethod(error_cb) iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent) if is_form: query = iq.setQuery() form.setAttr('type', 'submit') query.addChild(node=form) else: for field in form.keys(): iq.setTag('query').setTagData(field, form[field]) self._con.connection.SendAndCallForResponse( iq, self._register_agent_response, {'agent': agent, 'success_cb': weak_success_cb, 'error_cb': weak_error_cb}) self.agent_registrations[agent] = {'roster_push': False, 'sub_received': False} def _register_agent_response(self, _con, stanza, agent, success_cb, error_cb): if not nbxmpp.isResultNode(stanza): error = stanza.getErrorMsg() log.info('Error: %s', error) if error_cb() is not None: form = is_form = None if stanza.getTagAttr('error', 'type') == 'modify': form, is_form = self._get_register_form(stanza) error_cb()(error, form, is_form) return self._con.get_module('Presence').subscribe(agent, auto_auth=True) self.agent_registrations[agent]['roster_push'] = True if self.agent_registrations[agent]['sub_received']: self._con.get_module('Presence').subscribed(agent) if success_cb() is not None: success_cb()() def get_register_form(self, jid, success_cb, error_cb): if not app.account_is_connected(self._account): return weak_success_cb = weakref.WeakMethod(success_cb) weak_error_cb = weakref.WeakMethod(error_cb) iq = nbxmpp.Iq('get', nbxmpp.NS_REGISTER, to=jid) self._con.connection.SendAndCallForResponse( iq, self._register_info_response, {'success_cb': weak_success_cb, 'error_cb': weak_error_cb}) def _register_info_response(self, _con, stanza, success_cb, error_cb): if not nbxmpp.isResultNode(stanza): error = stanza.getErrorMsg() log.info('Error: %s', error) if error_cb() is not None: error_cb()(error) else: log.info('Register form received') if success_cb() is not None: form, is_form = self._get_register_form(stanza) success_cb()(form, is_form) @staticmethod def _get_register_form(stanza): query = stanza.getTag('query') if not query: return None, False form = query.getTag('x', namespace=nbxmpp.NS_DATA) is_form = form is not None if not is_form: form = {} for field in query.getPayload(): if not isinstance(field, nbxmpp.Node): continue form[field.getName()] = field.getData() return form, is_form def get_instance(*args, **kwargs): return Register(*args, **kwargs), 'Register' gajim-gajim-1.1.3/gajim/common/modules/roster.py000066400000000000000000000263741345766322700216420ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # Roster import logging from collections import namedtuple import nbxmpp from gajim.common import app from gajim.common.nec import NetworkEvent log = logging.getLogger('gajim.c.m.roster') RosterItem = namedtuple('RosterItem', 'jid data') class Roster: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('iq', self._roster_push_received, 'set', nbxmpp.NS_ROSTER), ('presence', self._presence_received) ] self._data = {} self._set = None def load_roster(self): log.info('Load from database') account_jid = self._con.get_own_jid().getStripped() data = app.logger.get_roster(account_jid) if data: self.set_raw(data) for jid, item in self._data.items(): app.nec.push_incoming_event(NetworkEvent( 'roster-info', conn=self._con, jid=jid, nickname=item['name'], sub=item['subscription'], ask=item['ask'], groups=item['groups'], avatar_sha=item['avatar_sha'])) else: log.info('Database empty, reset roster version') app.config.set_per( 'accounts', self._account, 'roster_version', '') app.nec.push_incoming_event(NetworkEvent( 'roster-received', conn=self._con, roster=self._data.copy(), received_from_server=False)) def request_roster(self): version = None features = self._con.connection.Dispatcher.Stream.features if features and features.getTag('ver', namespace=nbxmpp.NS_ROSTER_VER): version = app.config.get_per( 'accounts', self._account, 'roster_version') log.info('Requested from server') iq = nbxmpp.Iq('get', nbxmpp.NS_ROSTER) if version is not None: iq.setTagAttr('query', 'ver', version) log.info('Request version: %s', version) self._con.connection.SendAndCallForResponse( iq, self._roster_received) def _roster_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.warning('Unable to retrive roster: %s', stanza.getError()) else: log.info('Received Roster') received_from_server = False if stanza.getTag('query') is not None: # clear Roster self._data = {} version = self._parse_roster(stanza) log.info('New version: %s', version) app.logger.replace_roster(self._account, version, self._data) received_from_server = True app.nec.push_incoming_event(NetworkEvent( 'roster-received', conn=self._con, roster=self._data.copy(), received_from_server=received_from_server)) self._con.connect_machine() def _roster_push_received(self, _con, stanza): log.info('Push received') sender = stanza.getFrom() if sender is not None: if not self._con.get_own_jid().bareMatch(sender): log.warning('Wrong JID %s', stanza.getFrom()) return push_items, version = self._parse_push(stanza) self._ack_roster_push(stanza) for item in push_items: attrs = item.data app.nec.push_incoming_event(NetworkEvent( 'roster-info', conn=self._con, jid=item.jid, nickname=attrs['name'], sub=attrs['subscription'], ask=attrs['ask'], groups=attrs['groups'], avatar_sha=None)) account_jid = self._con.get_own_jid().getStripped() app.logger.add_or_update_contact( account_jid, item.jid, attrs['name'], attrs['subscription'], attrs['ask'], attrs['groups']) log.info('New version: %s', version) app.config.set_per( 'accounts', self._account, 'roster_version', version) raise nbxmpp.NodeProcessed def _parse_roster(self, stanza): query = stanza.getTag('query') version = query.getAttr('ver') for item in query.getTags('item'): jid = item.getAttr('jid') self._data[jid] = self._get_item_attrs(item, update=False) log.info('Item %s: %s', jid, self._data[jid]) return version @staticmethod def _get_item_attrs(item, update=True): ''' update: True returns only the attrs that are present in the item update: False returns the attrs of the item but fills missing attrs with default values ''' default_attrs = {'name': None, 'ask': None, 'subscription': None, 'groups': [], 'avatar_sha': None} attrs = item.getAttrs() del attrs['jid'] groups = {group.getData() for group in item.getTags('group')} attrs['groups'] = list(groups) if update: return attrs default_attrs.update(attrs) return default_attrs def _parse_push(self, stanza): query = stanza.getTag('query') version = query.getAttr('ver') push_items = [] for item in query.getTags('item'): push_items.append(self._update_roster_item(item)) for item in push_items: log.info('Push: %s', item) return push_items, version def _update_roster_item(self, item): jid = item.getAttr('jid') if item.getAttr('subscription') == 'remove': self._data.pop(jid, None) attrs = self._get_item_attrs(item, update=False) return RosterItem(jid, attrs) if jid not in self._data: self._data[jid] = self._get_item_attrs(item, update=False) else: self._data[jid].update(self._get_item_attrs(item)) return RosterItem(jid, self._data[jid]) def _ack_roster_push(self, stanza): iq = nbxmpp.Iq('result', to=stanza.getFrom(), frm=stanza.getTo(), attrs={'id': stanza.getID()}) self._con.connection.send(iq) def _presence_received(self, _con, pres): ''' Add contacts that request subscription to our internal roster and also to the database. The contact is put into the 'Not in roster' group and because we save it to the database it is also after a restart available. ''' if pres.getType() != 'subscribe': return jid = pres.getFrom().getStripped() if jid in self._data: return log.info('Add Contact from presence %s', jid) self._data[jid] = {'name': None, 'ask': None, 'subscription': 'none', 'groups': ['Not in roster']} account_jid = self._con.get_own_jid().getStripped() app.logger.add_or_update_contact( account_jid, jid, self._data[jid]['name'], self._data[jid]['subscription'], self._data[jid]['ask'], self._data[jid]['groups']) def _get_item_data(self, jid, dataname): """ Return specific jid's representation in internal format. """ jid = jid[:(jid + '/').find('/')] return self._data[jid][dataname] def del_item(self, jid): """ Delete contact 'jid' from roster """ self._con.connection.send( nbxmpp.Iq('set', nbxmpp.NS_ROSTER, payload=[ nbxmpp.Node('item', {'jid': jid, 'subscription': 'remove'})])) def get_groups(self, jid): """ Return groups list that contact 'jid' belongs to """ return self._get_item_data(jid, 'groups') def get_name(self, jid): """ Return name of contact 'jid' """ return self._get_item_data(jid, 'name') def set_item(self, jid, name=None, groups=None): """ Rename contact 'jid' and sets the groups list that it now belongs to """ iq = nbxmpp.Iq('set', nbxmpp.NS_ROSTER) query = iq.getTag('query') attrs = {'jid': jid} if name: attrs['name'] = name item = query.setTag('item', attrs) if groups is not None: for group in groups: item.addChild(node=nbxmpp.Node('group', payload=[group])) self._con.connection.send(iq) def set_item_multi(self, items): """ Rename multiple contacts and sets their group lists """ for i in items: iq = nbxmpp.Iq('set', nbxmpp.NS_ROSTER) query = iq.getTag('query') attrs = {'jid': i['jid']} if i['name']: attrs['name'] = i['name'] item = query.setTag('item', attrs) for group in i['groups']: item.addChild(node=nbxmpp.Node('group', payload=[group])) self._con.connection.send(iq) def get_items(self): """ Return list of all [bare] JIDs that the roster is currently tracks """ return list(self._data.keys()) def keys(self): """ Same as get_items. Provided for the sake of dictionary interface """ return list(self._data.keys()) def __getitem__(self, item): """ Get the contact in the internal format. Raises KeyError if JID 'item' is not in roster """ return self._data[item] def get_item(self, item): """ Get the contact in the internal format (or None if JID 'item' is not in roster) """ if item in self._data: return self._data[item] def unsubscribe(self, jid): """ Ask for removing our subscription for JID 'jid' """ self._con.connection.send(nbxmpp.Presence(jid, 'unsubscribe')) def get_raw(self): """ Return the internal data representation of the roster """ return self._data def set_raw(self, data): """ Set the internal data representation of the roster """ own_jid = self._con.get_own_jid().getStripped() self._data = data self._data[own_jid] = { 'resources': {}, 'name': None, 'ask': None, 'subscription': None, 'groups': None, 'avatar_sha': None } def get_instance(*args, **kwargs): return Roster(*args, **kwargs), 'Roster' gajim-gajim-1.1.3/gajim/common/modules/roster_item_exchange.py000066400000000000000000000110221345766322700245020ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0144: Roster Item Exchange import logging import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.roster_item_exchange') class RosterItemExchange: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('iq', self.received_item, 'set', nbxmpp.NS_ROSTERX), ('message', self.received_item, '', nbxmpp.NS_ROSTERX) ] def received_item(self, _con, stanza): # stanza can be a message or a iq log.info('Received roster items from %s', stanza.getFrom()) exchange_items_list = {} items_list = stanza.getTag( 'x', namespace=nbxmpp.NS_ROSTERX).getChildren() if items_list is None: raise nbxmpp.NodeProcessed action = items_list[0].getAttr('action') if not action: action = 'add' for item in items_list: try: jid = helpers.parse_jid(item.getAttr('jid')) except helpers.InvalidFormat: log.warning('Invalid JID: %s, ignoring it', item.getAttr('jid')) continue name = item.getAttr('name') contact = app.contacts.get_contact(self._account, jid) groups = [] same_groups = True for group in item.getTags('group'): groups.append(group.getData()) # check that all suggested groups are in the groups we have for # this contact if not contact or group not in contact.groups: same_groups = False if contact: # check that all groups we have for this contact are in the # suggested groups for group in contact.groups: if group not in groups: same_groups = False if contact.sub in ('both', 'to') and same_groups: continue exchange_items_list[jid] = [name, groups] if not exchange_items_list: raise nbxmpp.NodeProcessed log.info('Items: %s', exchange_items_list) app.nec.push_incoming_event(RosterItemExchangeEvent( None, conn=self._con, fjid=str(stanza.getFrom()), exchange_items_list=exchange_items_list, action=action)) raise nbxmpp.NodeProcessed def send_contacts(self, contacts, fjid, type_='message'): if not app.account_is_connected(self._account): return if type_ == 'message': if len(contacts) == 1: msg = _('Sent contact: "%(jid)s" (%(name)s)') % { 'jid': contacts[0].get_full_jid(), 'name': contacts[0].get_shown_name()} else: msg = _('Sent contacts:') for contact in contacts: msg += '\n "%s" (%s)' % (contact.get_full_jid(), contact.get_shown_name()) stanza = nbxmpp.Message(to=app.get_jid_without_resource(fjid), body=msg) elif type_ == 'iq': stanza = nbxmpp.Iq(to=fjid, typ='set') xdata = stanza.addChild(name='x', namespace=nbxmpp.NS_ROSTERX) for contact in contacts: name = contact.get_shown_name() xdata.addChild(name='item', attrs={'action': 'add', 'jid': contact.jid, 'name': name}) log.info('Send contact: %s %s', contact.jid, name) self._con.connection.send(stanza) class RosterItemExchangeEvent(NetworkIncomingEvent): name = 'roster-item-exchange-received' def get_instance(*args, **kwargs): return RosterItemExchange(*args, **kwargs), 'RosterItemExchange' gajim-gajim-1.1.3/gajim/common/modules/search.py000066400000000000000000000073661345766322700215710ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0055: Jabber Search import logging import nbxmpp from gajim.common import app from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.search') class Search: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] def request_search_fields(self, jid): log.info('Request search fields from %s', jid) iq = nbxmpp.Iq(typ='get', to=jid, queryNS=nbxmpp.NS_SEARCH) self._con.connection.SendAndCallForResponse(iq, self._fields_received) def _fields_received(self, stanza): data = None is_dataform = False if nbxmpp.isResultNode(stanza): log.info('Received search fields from %s', stanza.getFrom()) tag = stanza.getTag('query', namespace=nbxmpp.NS_SEARCH) if tag is None: log.info('Invalid stanza: %s', stanza) return data = tag.getTag('x', namespace=nbxmpp.NS_DATA) if data is not None: is_dataform = True else: data = {} for i in stanza.getQueryPayload(): data[i.getName()] = i.getData() else: log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event( SearchFormReceivedEvent(None, conn=self._con, is_dataform=is_dataform, data=data)) def send_search_form(self, jid, form, is_form): iq = nbxmpp.Iq(typ='set', to=jid, queryNS=nbxmpp.NS_SEARCH) item = iq.setQuery() if is_form: item.addChild(node=form) else: for i in form.keys(): item.setTagData(i, form[i]) self._con.connection.SendAndCallForResponse(iq, self._received_result) def _received_result(self, stanza): data = None is_dataform = False if nbxmpp.isResultNode(stanza): log.info('Received result from %s', stanza.getFrom()) tag = stanza.getTag('query', namespace=nbxmpp.NS_SEARCH) if tag is None: log.info('Invalid stanza: %s', stanza) return data = tag.getTag('x', namespace=nbxmpp.NS_DATA) if data is not None: is_dataform = True else: data = [] for item in tag.getTags('item'): # We also show attributes. jid is there field = item.attrs for i in item.getPayload(): field[i.getName()] = i.getData() data.append(field) else: log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event( SearchResultReceivedEvent(None, conn=self._con, is_dataform=is_dataform, data=data)) class SearchFormReceivedEvent(NetworkIncomingEvent): name = 'search-form-received' class SearchResultReceivedEvent(NetworkIncomingEvent): name = 'search-result-received' def get_instance(*args, **kwargs): return Search(*args, **kwargs), 'Search' gajim-gajim-1.1.3/gajim/common/modules/security_labels.py000066400000000000000000000056711345766322700235120ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0258: Security Labels in XMPP import logging import nbxmpp from gajim.common import app from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.security_labels') class SecLabels: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] self._catalogs = {} self.supported = False def pass_disco(self, from_, _identities, features, _data, _node): if nbxmpp.NS_SECLABEL not in features: return self.supported = True log.info('Discovered security labels: %s', from_) def request_catalog(self, jid): server = app.get_jid_from_account(self._account).split("@")[1] iq = nbxmpp.Iq(typ='get', to=server) iq.addChild(name='catalog', namespace=nbxmpp.NS_SECLABEL_CATALOG, attrs={'to': jid}) log.info('Request catalog: server: %s, to: %s', server, jid) self._con.connection.SendAndCallForResponse( iq, self._catalog_received) def _catalog_received(self, stanza): if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) return query = stanza.getTag('catalog', namespace=nbxmpp.NS_SECLABEL_CATALOG) to = query.getAttr('to') items = query.getTags('item') labels = {} label_list = [] default = None for item in items: label = item.getAttr('selector') labels[label] = item.getTag('securitylabel') label_list.append(label) if item.getAttr('default') == 'true': default = label catalog = (labels, label_list, default) self._catalogs[to] = catalog log.info('Received catalog: %s', to) log.debug(catalog) app.nec.push_incoming_event(SecLabelCatalog( None, account=self._account, jid=to, catalog=catalog)) def get_catalog(self, jid): return self._catalogs.get(jid) def parse_securitylabel(stanza): seclabel = stanza.getTag('securitylabel', namespace=nbxmpp.NS_SECLABEL) if seclabel is None: return None return seclabel.getTag('displaymarking') class SecLabelCatalog(NetworkIncomingEvent): name = 'sec-catalog-received' def get_instance(*args, **kwargs): return SecLabels(*args, **kwargs), 'SecLabels' gajim-gajim-1.1.3/gajim/common/modules/software_version.py000066400000000000000000000071321345766322700237120ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0092: Software Version import logging import nbxmpp from gajim.common import app from gajim.common.helpers import get_os_info from gajim.common.nec import NetworkIncomingEvent log = logging.getLogger('gajim.c.m.software_version') class SoftwareVersion: def __init__(self, con): self._con = con self._account = con.name self.handlers = [ ('iq', self._answer_request, 'get', nbxmpp.NS_VERSION), ] def request_os_info(self, jid, resource): if not app.account_is_connected(self._account): return # If we are invisible, do not request if self._con.connected == app.SHOW_LIST.index('invisible'): return if resource: jid += '/' + resource iq = nbxmpp.Iq(to=jid, typ='get', queryNS=nbxmpp.NS_VERSION) log.info('Requested: %s', jid) self._con.connection.SendAndCallForResponse(iq, self._result_received) def _result_received(self, stanza): client_info, os_info = None, None if not nbxmpp.isResultNode(stanza): log.info('Error: %s', stanza.getError()) else: try: client_info, os_info = self._extract_info(stanza) except Exception: log.exception('Error') log.error(stanza) log.info('Received: %s %s %s', stanza.getFrom(), client_info, os_info) app.nec.push_incoming_event( VersionResultReceivedEvent(None, conn=self._con, jid=stanza.getFrom(), client_info=client_info, os_info=os_info)) @staticmethod def _extract_info(stanza): query = stanza.getTag('query') name = query.getTag('name').getData() version = query.getTag('version').getData() client_info = '%s %s' % (name, version) os_info = query.getTag('os') if os_info is not None: os_info = os_info.getData() return client_info, os_info def _answer_request(self, _con, stanza): log.info('%s asked for the software version', stanza.getFrom()) if app.config.get_per('accounts', self._account, 'send_os_info'): os_info = get_os_info() iq = stanza.buildReply('result') query = iq.getQuery() query.setTagData('name', 'Gajim') query.setTagData('version', app.version) query.setTagData('os', os_info) log.info('Answer: Gajim %s %s', app.version, os_info) else: iq = stanza.buildReply('error') err = nbxmpp.ErrorNode(nbxmpp.ERR_SERVICE_UNAVAILABLE) iq.addChild(node=err) log.info('Send service-unavailable') self._con.connection.send(iq) raise nbxmpp.NodeProcessed class VersionResultReceivedEvent(NetworkIncomingEvent): name = 'version-result-received' def get_instance(*args, **kwargs): return SoftwareVersion(*args, **kwargs), 'SoftwareVersion' gajim-gajim-1.1.3/gajim/common/modules/user_activity.py000066400000000000000000000064441345766322700232120ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0108: User Activity import logging import nbxmpp from gi.repository import GLib from gajim.common.const import PEPEventType, ACTIVITIES from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData log = logging.getLogger('gajim.c.m.user_activity') class UserActivityData(AbstractPEPData): type_ = PEPEventType.ACTIVITY def __init__(self, activity): self.data = activity def as_markup_text(self): pep = self.data activity = pep['activity'] subactivity = pep['subactivity'] if 'subactivity' in pep else None text = pep['text'] if 'text' in pep else None if activity in ACTIVITIES: # Translate standard activities if subactivity in ACTIVITIES[activity]: subactivity = ACTIVITIES[activity][subactivity] activity = ACTIVITIES[activity]['category'] markuptext = '' + GLib.markup_escape_text(activity) if subactivity: markuptext += ': ' + GLib.markup_escape_text(subactivity) markuptext += '' if text: markuptext += ' (%s)' % GLib.markup_escape_text(text) return markuptext class UserActivity(AbstractPEPModule): name = 'activity' namespace = nbxmpp.NS_ACTIVITY pep_class = UserActivityData store_publish = True _log = log def __init__(self, con): AbstractPEPModule.__init__(self, con, con.name) self.handlers = [] def _extract_info(self, item): activity_dict = {} activity_tag = item.getTag('activity', namespace=self.namespace) if activity_tag is None: raise StanzaMalformed('No activity node') for child in activity_tag.getChildren(): name = child.getName().strip() data = child.getData().strip() if name == 'text': activity_dict['text'] = data else: activity_dict['activity'] = name for subactivity in child.getChildren(): subactivity_name = subactivity.getName().strip() activity_dict['subactivity'] = subactivity_name return activity_dict or None def _build_node(self, data): item = nbxmpp.Node('activity', {'xmlns': self.namespace}) if data is None: return item activity, subactivity, message = data if activity: i = item.addChild(activity) if subactivity: i.addChild(subactivity) if message: i = item.addChild('text') i.addData(message) return item def get_instance(*args, **kwargs): return UserActivity(*args, **kwargs), 'UserActivity' gajim-gajim-1.1.3/gajim/common/modules/user_avatar.py000066400000000000000000000116721345766322700226330ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0084: User Avatar import logging import base64 import binascii import nbxmpp from gajim.common import app from gajim.common.const import PEPEventType from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData log = logging.getLogger('gajim.c.m.user_avatar') class UserAvatarData(AbstractPEPData): type_ = PEPEventType.AVATAR def __init__(self, avatar): self.data = avatar class UserAvatar(AbstractPEPModule): name = 'user-avatar' namespace = 'urn:xmpp:avatar:metadata' pep_class = UserAvatarData store_publish = False _log = log def __init__(self, con): AbstractPEPModule.__init__(self, con, con.name) self.handlers = [] def get_pubsub_avatar(self, jid, item_id): log.info('Request: %s %s', jid, item_id) self._con.get_module('PubSub').send_pb_retrieve( jid, 'urn:xmpp:avatar:data', item_id, self._avatar_received) def _validate_avatar_node(self, stanza): jid = stanza.getFrom() if jid is None: jid = self._con.get_own_jid().getStripped() else: jid = jid.getStripped() if nbxmpp.isErrorNode(stanza): raise StanzaMalformed(stanza.getErrorMsg()) pubsub_node = stanza.getTag('pubsub') if pubsub_node is None: raise StanzaMalformed('No pubsub node', stanza) items_node = pubsub_node.getTag('items') if items_node is None: raise StanzaMalformed('No items node', stanza) if items_node.getAttr('node') != 'urn:xmpp:avatar:data': raise StanzaMalformed('Wrong namespace', stanza) item = items_node.getTag('item') if item is None: raise StanzaMalformed('No item node', stanza) sha = item.getAttr('id') data_tag = item.getTag('data', namespace='urn:xmpp:avatar:data') if sha is None or data_tag is None: raise StanzaMalformed('No id attr or data node found', stanza) data = data_tag.getData() if data is None: raise StanzaMalformed('Data node empty', stanza) data = base64.b64decode(data.encode('utf-8')) return jid, sha, data def _avatar_received(self, _con, stanza): try: jid, sha, data = self._validate_avatar_node(stanza) except (StanzaMalformed, binascii.Error) as error: log.warning('Error: %s %s', stanza.getFrom(), error) return log.info('Received Avatar: %s %s', jid, sha) app.interface.save_avatar(data) if self._con.get_own_jid().bareMatch(jid): app.config.set_per('accounts', self._account, 'avatar_sha', sha) else: own_jid = self._con.get_own_jid().getStripped() app.logger.set_avatar_sha(own_jid, jid, sha) app.contacts.set_avatar(self._account, jid, sha) app.interface.update_avatar(self._account, jid) def _extract_info(self, item): metadata = item.getTag('metadata', namespace=self.namespace) if metadata is None: raise StanzaMalformed('No metadata node') info = metadata.getTags('info', one=True) if not info: return None avatar = info.getAttrs() return avatar or None def _notification_received(self, jid, user_pep): avatar = user_pep.data own_jid = self._con.get_own_jid() if avatar is None: # Remove avatar log.info('Remove: %s', jid) app.contacts.set_avatar(self._account, str(jid), None) app.logger.set_avatar_sha(own_jid.getStripped(), str(jid), None) app.interface.update_avatar(self._account, str(jid)) else: if own_jid.bareMatch(jid): sha = app.config.get_per( 'accounts', self._account, 'avatar_sha') else: sha = app.contacts.get_avatar_sha(self._account, str(jid)) if sha == avatar['id']: log.info('Avatar already known: %s %s', jid, avatar['id']) return self.get_pubsub_avatar(jid, avatar['id']) def _build_node(self, data): raise NotImplementedError def send(self, data): # Not implemented yet return def get_instance(*args, **kwargs): return UserAvatar(*args, **kwargs), 'UserAvatar' gajim-gajim-1.1.3/gajim/common/modules/user_location.py000066400000000000000000000053521345766322700231630ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0080: User Location import logging import nbxmpp from gi.repository import GLib from gajim.common.const import PEPEventType, LOCATION_DATA from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData log = logging.getLogger('gajim.c.m.user_location') class UserLocationData(AbstractPEPData): type_ = PEPEventType.LOCATION def __init__(self, location): # set_location plugin uses self._pep_specific_data self._pep_specific_data = location self.data = location def as_markup_text(self): location = self.data location_string = '' for entry in location.keys(): text = location[entry] text = GLib.markup_escape_text(text) # Translate standard location tag tag = LOCATION_DATA.get(entry, entry) location_string += '\n%(tag)s: %(text)s' % { 'tag': tag.capitalize(), 'text': text} return location_string.strip() class UserLocation(AbstractPEPModule): name = 'geoloc' namespace = nbxmpp.NS_LOCATION pep_class = UserLocationData store_publish = True _log = log def __init__(self, con): AbstractPEPModule.__init__(self, con, con.name) self.handlers = [] def _extract_info(self, item): location_dict = {} location_tag = item.getTag('geoloc', namespace=nbxmpp.NS_LOCATION) if location_tag is None: raise StanzaMalformed('No geoloc node') for child in location_tag.getChildren(): name = child.getName().strip() data = child.getData().strip() if child.getName() in LOCATION_DATA: location_dict[name] = data return location_dict or None def _build_node(self, data): item = nbxmpp.Node('geoloc', {'xmlns': nbxmpp.NS_LOCATION}) if data is None: return item for field in LOCATION_DATA: if data.get(field, False): item.addChild(field, payload=data[field]) return item def get_instance(*args, **kwargs): return UserLocation(*args, **kwargs), 'UserLocation' gajim-gajim-1.1.3/gajim/common/modules/user_mood.py000066400000000000000000000057711345766322700223160ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0107: User Mood from typing import Any from typing import Dict from typing import List # pylint: disable=unused-import from typing import Optional from typing import Tuple import logging import nbxmpp from gi.repository import GLib from gajim.common.const import PEPEventType, MOODS from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m.user_mood') class UserMoodData(AbstractPEPData): type_ = PEPEventType.MOOD def __init__(self, mood: Optional[Dict[str, str]]) -> None: self.data = mood def as_markup_text(self) -> str: if self.data is None: return '' mood = self._translate_mood(self.data['mood']) markuptext = '%s' % GLib.markup_escape_text(mood) if 'text' in self.data: text = self.data['text'] markuptext += ' (%s)' % GLib.markup_escape_text(text) return markuptext @staticmethod def _translate_mood(mood: str) -> str: if mood in MOODS: return MOODS[mood] return mood class UserMood(AbstractPEPModule): name = 'mood' namespace = nbxmpp.NS_MOOD pep_class = UserMoodData store_publish = True _log = log def __init__(self, con: ConnectionT) -> None: AbstractPEPModule.__init__(self, con, con.name) self.handlers = [] # type: List[Tuple[Any, ...]] def _extract_info(self, item: nbxmpp.Node) -> Optional[Dict[str, str]]: mood_dict = {} mood_tag = item.getTag('mood', namespace=nbxmpp.NS_MOOD) if mood_tag is None: raise StanzaMalformed('No mood node') for child in mood_tag.getChildren(): name = child.getName().strip() if name == 'text': mood_dict['text'] = child.getData() else: mood_dict['mood'] = name return mood_dict or None def _build_node(self, data: Optional[Tuple[str, str]]) -> nbxmpp.Node: item = nbxmpp.Node('mood', {'xmlns': nbxmpp.NS_MOOD}) if data is None: return item mood, text = data if mood: item.addChild(mood) if text: item.addChild('text', payload=text) return item def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserMood, str]: return UserMood(*args, **kwargs), 'UserMood' gajim-gajim-1.1.3/gajim/common/modules/user_nickname.py000066400000000000000000000056701345766322700231430ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0172: User Nickname from typing import Any from typing import List # pylint: disable=unused-import from typing import Optional from typing import Tuple import logging import nbxmpp from gajim.common import app from gajim.common.const import PEPEventType from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m.user_nickname') class UserNicknameData(AbstractPEPData): type_ = PEPEventType.NICKNAME def __init__(self, nickname: Optional[str]) -> None: self.data = nickname def get_nick(self) -> str: return self.data or '' class UserNickname(AbstractPEPModule): name = 'nick' namespace = nbxmpp.NS_NICK pep_class = UserNicknameData store_publish = True _log = log def __init__(self, con: ConnectionT) -> None: AbstractPEPModule.__init__(self, con, con.name) self.handlers = [] # type: List[Tuple[Any, ...]] def _extract_info(self, item: nbxmpp.Node) -> Optional[str]: nick = '' child = item.getTag('nick', namespace=nbxmpp.NS_NICK) if child is None: raise StanzaMalformed('No nick node') nick = child.getData() return nick or None def _build_node(self, data: Optional[str]) -> Optional[nbxmpp.Node]: item = nbxmpp.Node('nick', {'xmlns': nbxmpp.NS_NICK}) if data is not None: item.addData(data) return item def _notification_received(self, jid: nbxmpp.JID, user_pep: UserNicknameData) -> None: for contact in app.contacts.get_contacts(self._account, str(jid)): contact.contact_name = user_pep.get_nick() if jid == self._con.get_own_jid().getStripped(): if user_pep: app.nicks[self._account] = user_pep.get_nick() else: app.nicks[self._account] = app.config.get_per( 'accounts', self._account, 'name') def parse_nickname(stanza: nbxmpp.Node) -> str: nick = stanza.getTag('nick', namespace=nbxmpp.NS_NICK) if nick is None: return '' return nick.getData() def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserNickname, str]: return UserNickname(*args, **kwargs), 'UserNickname' gajim-gajim-1.1.3/gajim/common/modules/user_tune.py000066400000000000000000000071301345766322700223220ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0118: User Tune from typing import Any from typing import List # pylint: disable=unused-import from typing import Dict from typing import Optional from typing import Tuple import logging import nbxmpp from gi.repository import GLib from gajim.common.i18n import _ from gajim.common.const import PEPEventType from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData from gajim.common.types import ConnectionT from gajim.common.types import UserTuneDataT log = logging.getLogger('gajim.c.m.user_tune') class UserTuneData(AbstractPEPData): type_ = PEPEventType.TUNE def __init__(self, tune: Optional[Dict[str, str]]) -> None: self.data = tune def as_markup_text(self) -> str: if self.data is None: return '' tune = self.data artist = tune.get('artist', _('Unknown Artist')) artist = GLib.markup_escape_text(artist) title = tune.get('title', _('Unknown Title')) title = GLib.markup_escape_text(title) source = tune.get('source', _('Unknown Source')) source = GLib.markup_escape_text(source) tune_string = _('"%(title)s" by %(artist)s\n' 'from %(source)s') % {'title': title, 'artist': artist, 'source': source} return tune_string class UserTune(AbstractPEPModule): name = 'tune' namespace = nbxmpp.NS_TUNE pep_class = UserTuneData store_publish = True _log = log def __init__(self, con: ConnectionT) -> None: AbstractPEPModule.__init__(self, con, con.name) self.handlers = [] # type: List[Tuple[Any, ...]] def _extract_info(self, item: nbxmpp.Node) -> Optional[Dict[str, str]]: tune_dict = {} tune_tag = item.getTag('tune', namespace=self.namespace) if tune_tag is None: raise StanzaMalformed('No tune node') for child in tune_tag.getChildren(): name = child.getName().strip() data = child.getData().strip() if child.getName() in ['artist', 'title', 'source', 'track', 'length']: tune_dict[name] = data return tune_dict or None def _build_node(self, data: UserTuneDataT) -> nbxmpp.Node: item = nbxmpp.Node('tune', {'xmlns': nbxmpp.NS_TUNE}) if data is None: return item artist, title, source, track, length = data if artist: item.addChild('artist', payload=artist) if title: item.addChild('title', payload=title) if source: item.addChild('source', payload=source) if track: item.addChild('track', payload=track) if length: item.addChild('length', payload=length) return item def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserTune, str]: return UserTune(*args, **kwargs), 'UserTune' gajim-gajim-1.1.3/gajim/common/modules/util.py000066400000000000000000000037661345766322700213010ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # Util module from typing import Union import nbxmpp from gajim.common import app def is_self_message(message: nbxmpp.Node, groupchat: bool = False) -> bool: if groupchat: return False frm = message.getFrom() to = message.getTo() return frm.bareMatch(to) def is_muc_pm(message: nbxmpp.Node, jid: nbxmpp.JID, groupchat: bool = False) -> bool: if groupchat: return False muc_user = message.getTag('x', namespace=nbxmpp.NS_MUC_USER) if muc_user is not None: return muc_user.getChildren() == [] # muc#user namespace was added in MUC 1.28 so we need a fallback # Check if we know the jid if app.logger.jid_is_room_jid(jid.getStripped()): return True return False def from_xs_boolean(value: Union[str, bool]) -> bool: if isinstance(value, bool): return value if value in ('1', 'true', 'True'): return True if value in ('0', 'false', 'False', ''): return False raise ValueError('Cant convert %s to python boolean' % value) def to_xs_boolean(value: Union[bool, None]) -> str: # Convert to xs:boolean ('true', 'false') # from a python boolean (True, False) or None if value is True: return 'true' if value is False: return 'false' if value is None: return 'false' raise ValueError( 'Cant convert %s to xs:boolean' % value) gajim-gajim-1.1.3/gajim/common/modules/vcard_avatars.py000066400000000000000000000213671345766322700231410ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0153: vCard-Based Avatars import os import logging from pathlib import Path import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common import configpaths from gajim.common.const import RequestAvatar log = logging.getLogger('gajim.c.m.vcard.avatars') class VCardAvatars: def __init__(self, con): self._con = con self._account = con.name self._requested_shas = [] self.handlers = [ ('presence', self._presence_received, '', nbxmpp.NS_VCARD_UPDATE), ] self.avatar_advertised = False self._find_own_avatar() def _find_own_avatar(self): sha = app.config.get_per('accounts', self._account, 'avatar_sha') if not sha: return path = Path(configpaths.get('AVATAR')) / sha if not path.exists(): log.info('Missing own avatar, reset sha') app.config.set_per('accounts', self._account, 'avatar_sha', '') def _presence_received(self, _con, stanza): if stanza.getType() in ('unavailable', 'error'): return jid = stanza.getFrom() update = stanza.getTag('x', namespace=nbxmpp.NS_VCARD_UPDATE) if update is None: return avatar_sha = update.getTagData('photo') if avatar_sha is None: log.info('%s is not ready to promote an avatar', jid) # Empty update element, ignore return if self._con.get_own_jid().bareMatch(jid): if self._con.get_own_jid() == jid: # Initial presence reflection if self._con.avatar_conversion: # XEP-0398: Tells us the current avatar sha on the # inital presence reflection self._self_update_received(jid, avatar_sha) else: # Presence from another resource of ours self._self_update_received(jid, avatar_sha) return # Check if presence is from a MUC service contact = app.contacts.get_groupchat_contact(self._account, str(jid)) if contact is not None: self._update_received(jid, avatar_sha, room=True) elif stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER): show = stanza.getShow() type_ = stanza.getType() self._gc_update_received(jid, avatar_sha, show, type_) else: self._update_received(jid, avatar_sha) def _self_update_received(self, jid, avatar_sha): jid = jid.getStripped() full_jid = jid if avatar_sha == '': # Empty tag, means no avatar is advertised log.info('%s has no avatar published', full_jid) app.config.set_per('accounts', self._account, 'avatar_sha', '') app.contacts.set_avatar(self._account, jid, None) app.interface.update_avatar(self._account, jid) return log.info('Update: %s %s', jid, avatar_sha) current_sha = app.config.get_per( 'accounts', self._account, 'avatar_sha') if avatar_sha != current_sha: path = Path(configpaths.get('AVATAR')) / avatar_sha if path.exists(): app.config.set_per( 'accounts', self._account, 'avatar_sha', avatar_sha) app.contacts.set_avatar(self._account, jid, avatar_sha) app.interface.update_avatar(self._account, jid) else: log.info('Request : %s', jid) self._con.get_module('VCardTemp').request_vcard( RequestAvatar.SELF) else: log.info('Avatar already known: %s %s', jid, avatar_sha) def _update_received(self, jid, avatar_sha, room=False): jid = jid.getStripped() full_jid = jid if avatar_sha == '': # Empty tag, means no avatar is advertised log.info('%s has no avatar published', full_jid) # Remove avatar log.debug('Remove: %s', jid) app.contacts.set_avatar(self._account, jid, None) acc_jid = self._con.get_own_jid().getStripped() if not room: app.logger.set_avatar_sha(acc_jid, jid, None) app.interface.update_avatar( self._account, jid, room_avatar=room) else: log.info('Update: %s %s', full_jid, avatar_sha) current_sha = app.contacts.get_avatar_sha(self._account, jid) if avatar_sha == current_sha: log.info('Avatar already known: %s %s', jid, avatar_sha) return if room: # We dont save the room avatar hash in our DB, so check # if we previously downloaded it if app.interface.avatar_exists(avatar_sha): app.contacts.set_avatar(self._account, jid, avatar_sha) app.interface.update_avatar( self._account, jid, room_avatar=room) return if avatar_sha not in self._requested_shas: self._requested_shas.append(avatar_sha) if room: self._con.get_module('VCardTemp').request_vcard( RequestAvatar.ROOM, jid, sha=avatar_sha) else: self._con.get_module('VCardTemp').request_vcard( RequestAvatar.USER, jid, sha=avatar_sha) def _gc_update_received(self, jid, avatar_sha, show, type_): if show == 'offline' or type_ == 'unavailable': return nick = jid.getResource() gc_contact = app.contacts.get_gc_contact( self._account, jid.getStripped(), nick) if gc_contact is None: log.error('no gc contact found: %s', nick) return if avatar_sha == '': # Empty tag, means no avatar is advertised, remove avatar log.info('%s has no avatar published', nick) log.debug('Remove: %s', nick) gc_contact.avatar_sha = None app.interface.update_avatar(contact=gc_contact) else: log.info('Update: %s %s', nick, avatar_sha) path = os.path.join(configpaths.get('AVATAR'), avatar_sha) if not os.path.isfile(path): if avatar_sha not in self._requested_shas: app.log('avatar').info('Request: %s', nick) self._requested_shas.append(avatar_sha) self._con.get_module('VCardTemp').request_vcard( RequestAvatar.USER, str(jid), room=True, sha=avatar_sha) return if gc_contact.avatar_sha != avatar_sha: log.info('%s changed their Avatar: %s', nick, avatar_sha) gc_contact.avatar_sha = avatar_sha app.interface.update_avatar(contact=gc_contact) else: log.info('Avatar already known: %s', nick) def send_avatar_presence(self, force=False, after_publish=False): if self._con.avatar_conversion: if not after_publish: # XEP-0398: We only resend presence after we publish a # new avatar return else: if self.avatar_advertised and not force: log.debug('Avatar already advertised') return show = helpers.get_xmpp_show(app.SHOW_LIST[self._con.connected]) self._con.get_module('Presence').send_presence( priority=self._con.priority, show=show, status=self._con.status) self.avatar_advertised = True def add_update_node(self, node): update = node.setTag('x', namespace=nbxmpp.NS_VCARD_UPDATE) if self._con.get_module('VCardTemp').own_vcard_received: sha = app.config.get_per('accounts', self._account, 'avatar_sha') own_jid = self._con.get_own_jid() log.info('Send avatar presence to: %s %s', node.getTo() or own_jid, sha or 'no sha advertised') update.setTagData('photo', sha) def get_instance(*args, **kwargs): return VCardAvatars(*args, **kwargs), 'VCardAvatars' gajim-gajim-1.1.3/gajim/common/modules/vcard_temp.py000066400000000000000000000274331345766322700224450ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # XEP-0054: vcard-temp import hashlib import binascii import base64 import logging import nbxmpp from gajim.common import app from gajim.common.const import RequestAvatar from gajim.common.nec import NetworkIncomingEvent from gajim.common.connection_handlers_events import InformationEvent log = logging.getLogger('gajim.c.m.vcard') class VCardTemp: def __init__(self, con): self._con = con self._account = con.name self.handlers = [] self._own_vcard = None self.own_vcard_received = False self.room_jids = [] self.supported = False def pass_disco(self, from_, _identities, features, _data, _node): if nbxmpp.NS_VCARD not in features: return self.supported = True log.info('Discovered vcard-temp: %s', from_) # TODO: Move this GUI code out action = app.app.lookup_action('%s-profile' % self._account) action.set_enabled(True) @staticmethod def _node_to_dict(node): dict_ = {} for info in node.getChildren(): name = info.getName() if name in ('ADR', 'TEL', 'EMAIL'): # we can have several dict_.setdefault(name, []) entry = {} for child in info.getChildren(): entry[child.getName()] = child.getData() dict_[name].append(entry) elif info.getChildren() == []: dict_[name] = info.getData() else: dict_[name] = {} for child in info.getChildren(): dict_[name][child.getName()] = child.getData() return dict_ def request_vcard(self, callback=RequestAvatar.SELF, jid=None, room=False, sha=None): if not app.account_is_connected(self._account): return if isinstance(callback, RequestAvatar): if callback == RequestAvatar.SELF: if not self.supported: return callback = self._on_own_avatar_received elif callback == RequestAvatar.ROOM: callback = self._on_room_avatar_received elif callback == RequestAvatar.USER: callback = self._on_avatar_received if room: room_jid = app.get_room_from_fjid(jid) if room_jid not in self.room_jids: self.room_jids.append(room_jid) iq = nbxmpp.Iq(typ='get') if jid: iq.setTo(jid) iq.setQuery('vCard').setNamespace(nbxmpp.NS_VCARD) own_jid = self._con.get_own_jid().getStripped() log.info('Request: %s, expected sha: %s', jid or own_jid, sha) self._con.connection.SendAndCallForResponse( iq, self._parse_vcard, {'callback': callback, 'expected_sha': sha}) def send_vcard(self, vcard, sha): if not app.account_is_connected(self._account): return iq = nbxmpp.Iq(typ='set') iq2 = iq.setTag(nbxmpp.NS_VCARD + ' vCard') for i in vcard: if i == 'jid': continue if isinstance(vcard[i], dict): iq3 = iq2.addChild(i) for j in vcard[i]: iq3.addChild(j).setData(vcard[i][j]) elif isinstance(vcard[i], list): for j in vcard[i]: iq3 = iq2.addChild(i) for k in j: iq3.addChild(k).setData(j[k]) else: iq2.addChild(i).setData(vcard[i]) log.info('Upload avatar: %s %s', self._account, sha) self._con.connection.SendAndCallForResponse( iq, self._avatar_publish_result, {'sha': sha}) def upload_room_avatar(self, room_jid, data): iq = nbxmpp.Iq(typ='set', to=room_jid) vcard = iq.addChild('vCard', namespace=nbxmpp.NS_VCARD) photo = vcard.addChild('PHOTO') photo.addChild('TYPE', payload='image/png') photo.addChild('BINVAL', payload=data) log.info('Upload avatar: %s', room_jid) self._con.connection.SendAndCallForResponse( iq, self._upload_room_avatar_result) @staticmethod def _upload_room_avatar_result(stanza): if not nbxmpp.isResultNode(stanza): reason = stanza.getErrorMsg() or stanza.getError() app.nec.push_incoming_event(InformationEvent( None, dialog_name='avatar-upload-error', args=reason)) def _avatar_publish_result(self, _con, stanza, sha): if stanza.getType() == 'result': current_sha = app.config.get_per( 'accounts', self._account, 'avatar_sha') if (current_sha != sha and not app.is_invisible(self._account)): if not app.account_is_connected(self._account): return app.config.set_per( 'accounts', self._account, 'avatar_sha', sha or '') own_jid = self._con.get_own_jid().getStripped() app.contacts.set_avatar(self._account, own_jid, sha) app.interface.update_avatar( self._account, self._con.get_own_jid().getStripped()) self._con.get_module('VCardAvatars').send_avatar_presence( after_publish=True) log.info('%s: Published: %s', self._account, sha) app.nec.push_incoming_event( VcardPublishedEvent(None, conn=self._con)) elif stanza.getType() == 'error': app.nec.push_incoming_event( VcardNotPublishedEvent(None, conn=self._con)) @staticmethod def _get_vcard_photo(vcard, jid): try: photo = vcard['PHOTO']['BINVAL'] except (KeyError, AttributeError, TypeError): avatar_sha = None photo_decoded = None else: if photo == '': avatar_sha = None photo_decoded = None else: try: photo_decoded = base64.b64decode(photo.encode('utf-8')) except binascii.Error as error: log.warning('Invalid avatar for %s: %s', jid, error) return None, None avatar_sha = hashlib.sha1(photo_decoded).hexdigest() return avatar_sha, photo_decoded def _parse_vcard(self, _con, stanza, callback, expected_sha): frm_jid = stanza.getFrom() room = False if frm_jid is None: frm_jid = self._con.get_own_jid() elif frm_jid.getStripped() in self.room_jids: room = True resource = frm_jid.getResource() jid = frm_jid.getStripped() stanza_error = stanza.getError() if stanza_error in ('service-unavailable', 'item-not-found', 'not-allowed'): log.info('vCard not available: %s %s', frm_jid, stanza_error) callback(jid, resource, room, {}, expected_sha) return vcard_node = stanza.getTag('vCard', namespace=nbxmpp.NS_VCARD) if vcard_node is None: log.info('vCard not available: %s', frm_jid) log.debug(stanza) return vcard = self._node_to_dict(vcard_node) if self._con.get_own_jid().bareMatch(jid): if 'NICKNAME' in vcard: app.nicks[self._account] = vcard['NICKNAME'] elif 'FN' in vcard: app.nicks[self._account] = vcard['FN'] app.nec.push_incoming_event( VcardReceivedEvent(None, conn=self._con, vcard_dict=vcard, jid=jid)) callback(jid, resource, room, vcard, expected_sha) def _on_own_avatar_received(self, jid, _resource, _room, vcard, *args): avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid) log.info('Received own vcard, avatar sha is: %s', avatar_sha) self._own_vcard = vcard self.own_vcard_received = True if avatar_sha is None: # No avatar found in vcard log.info('No avatar found') app.config.set_per('accounts', self._account, 'avatar_sha', '') app.contacts.set_avatar(self._account, jid, avatar_sha) self._con.get_module('VCardAvatars').send_avatar_presence( force=True) return # Avatar found in vcard current_sha = app.config.get_per( 'accounts', self._account, 'avatar_sha') if current_sha == avatar_sha: self._con.get_module('VCardAvatars').send_avatar_presence() else: app.interface.save_avatar(photo_decoded) app.contacts.set_avatar(self._account, jid, avatar_sha) app.config.set_per( 'accounts', self._account, 'avatar_sha', avatar_sha) self._con.get_module('VCardAvatars').send_avatar_presence( force=True) app.interface.update_avatar(self._account, jid) def _on_room_avatar_received(self, jid, _resource, _room, vcard, expected_sha): avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid) if expected_sha != avatar_sha: log.warning('Avatar mismatch: %s %s', jid, avatar_sha) return app.interface.save_avatar(photo_decoded) log.info('Received: %s %s', jid, avatar_sha) app.contacts.set_avatar(self._account, jid, avatar_sha) app.interface.update_avatar(self._account, jid, room_avatar=True) def _on_avatar_received(self, jid, resource, room, vcard, expected_sha): request_jid = jid if room: request_jid = '%s/%s' % (jid, resource) avatar_sha, photo_decoded = self._get_vcard_photo(vcard, request_jid) if expected_sha != avatar_sha: log.warning('Received: avatar mismatch: %s %s', request_jid, avatar_sha) return app.interface.save_avatar(photo_decoded) # Received vCard from a contact if room: log.info('Received: %s %s', resource, avatar_sha) contact = app.contacts.get_gc_contact(self._account, jid, resource) if contact is not None: contact.avatar_sha = avatar_sha app.interface.update_avatar(contact=contact) else: log.info('Received: %s %s', jid, avatar_sha) own_jid = self._con.get_own_jid().getStripped() app.logger.set_avatar_sha(own_jid, jid, avatar_sha) app.contacts.set_avatar(self._account, jid, avatar_sha) app.interface.update_avatar(self._account, jid) def get_vard_name(self): name = '' vcard = self._own_vcard if not vcard: return name if 'N' in vcard: if 'GIVEN' in vcard['N'] and 'FAMILY' in vcard['N']: name = vcard['N']['GIVEN'] + ' ' + vcard['N']['FAMILY'] if not name and 'FN' in vcard: name = vcard['FN'] return name class VcardPublishedEvent(NetworkIncomingEvent): name = 'vcard-published' class VcardNotPublishedEvent(NetworkIncomingEvent): name = 'vcard-not-published' class VcardReceivedEvent(NetworkIncomingEvent): name = 'vcard-received' def get_instance(*args, **kwargs): return VCardTemp(*args, **kwargs), 'VCardTemp' gajim-gajim-1.1.3/gajim/common/multimedia_helpers.py000066400000000000000000000103661345766322700225220ustar00rootroot00000000000000# Copyright (C) 2009 Thibaut GIRKA # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import gi import logging gi.require_version('Gst', '1.0') from gi.repository import Gst from gajim.common.i18n import _ log = logging.getLogger('gajim.c.multimedia_helpers') class DeviceManager: def __init__(self): self.devices = {} def detect(self): self.devices = {} def get_devices(self): if not self.devices: self.detect() return self.devices def detect_element(self, name, text, pipe='%s'): if Gst.ElementFactory.find(name): element = Gst.ElementFactory.make(name, '%spresencetest' % name) if element is None: log.warning('could not create %spresencetest', name) return if hasattr(element.props, 'device'): element.set_state(Gst.State.READY) devices = element.get_properties('device') if devices: self.devices[text % _('Default device')] = pipe % name for device in devices: if device is None: continue element.set_state(Gst.State.NULL) element.set_property('device', device) element.set_state(Gst.State.READY) device_name = element.get_property('device-name') self.devices[text % device_name] = pipe % \ '%s device=%s' % (name, device) element.set_state(Gst.State.NULL) else: self.devices[text] = pipe % name else: log.info('element %s not found', name) class AudioInputManager(DeviceManager): def detect(self): self.devices = {} # Test src self.detect_element('audiotestsrc', _('Audio test'), '%s is-live=true name=gajim_vol') # Auto src self.detect_element('autoaudiosrc', _('Autodetect'), '%s ! volume name=gajim_vol') # Alsa src self.detect_element('alsasrc', _('ALSA: %s'), '%s ! volume name=gajim_vol') # Pulseaudio src self.detect_element('pulsesrc', _('Pulse: %s'), '%s ! volume name=gajim_vol') class AudioOutputManager(DeviceManager): def detect(self): self.devices = {} # Fake sink self.detect_element('fakesink', _('Fake audio output')) # Auto sink self.detect_element('autoaudiosink', _('Autodetect')) # Alsa sink self.detect_element('alsasink', _('ALSA: %s'), '%s sync=false') # Pulseaudio sink self.detect_element('pulsesink', _('Pulse: %s'), '%s sync=true') class VideoInputManager(DeviceManager): def detect(self): self.devices = {} # Test src self.detect_element('videotestsrc', _('Video test'), '%s is-live=true ! video/x-raw,framerate=10/1') # Auto src self.detect_element('autovideosrc', _('Autodetect')) # V4L2 src self.detect_element('v4l2src', _('V4L2: %s')) # Funny things, just to test... # self.devices['GOOM'] = 'audiotestsrc ! goom' self.detect_element('ximagesrc', _('Screen'), '%s ! ffmpegcolorspace') class VideoOutputManager(DeviceManager): def detect(self): self.devices = {} # Fake video output self.detect_element('fakesink', _('Fake video output')) # Auto sink self.detect_element('xvimagesink', _('X Window System (X11/XShm/Xv): %s')) # ximagesink self.detect_element('ximagesink', _('X Window System (without Xv)')) self.detect_element('autovideosink', _('Autodetect')) gajim-gajim-1.1.3/gajim/common/nec.py000066400000000000000000000151321345766322700174070ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' Network Events Controller. :author: Mateusz Biliński :since: 10th August 2008 :copyright: Copyright (2008) Mateusz Biliński :copyright: Copyright (2011) Yann Leboulanger :license: GPL ''' from typing import List # pylint: disable=unused-import from gajim.common import app class NetworkEventsController: def __init__(self): self.incoming_events_generators = {} ''' Keys: names of events Values: list of class objects that are subclasses of `NetworkIncomingEvent` ''' self.outgoing_events_generators = {} ''' Keys: names of events Values: list of class objects that are subclasses of `NetworkOutgoingEvent` ''' def register_incoming_event(self, event_class): for base_event_name in event_class.base_network_events: event_list = self.incoming_events_generators.setdefault( base_event_name, []) if event_class not in event_list: event_list.append(event_class) def unregister_incoming_event(self, event_class): for base_event_name in event_class.base_network_events: if base_event_name in self.incoming_events_generators: self.incoming_events_generators[base_event_name].remove( event_class) def register_outgoing_event(self, event_class): for base_event_name in event_class.base_network_events: event_list = self.outgoing_events_generators.setdefault( base_event_name, []) if event_class not in event_list: event_list.append(event_class) def unregister_outgoing_event(self, event_class): for base_event_name in event_class.base_network_events: if base_event_name in self.outgoing_events_generators: self.outgoing_events_generators[base_event_name].remove( event_class) def push_incoming_event(self, event_object): if event_object.generate(): if not app.ged.raise_event(event_object.name, event_object): self._generate_events_based_on_incoming_event(event_object) def push_outgoing_event(self, event_object): if event_object.generate(): if not app.ged.raise_event(event_object.name, event_object): self._generate_events_based_on_outgoing_event(event_object) def _generate_events_based_on_incoming_event(self, event_object): ''' :return: True if even_object should be dispatched through Global Events Dispatcher, False otherwise. This can be used to replace base events with those that more data computed (easier to use by handlers). :note: replacing mechanism is not implemented currently, but will be based on attribute in new network events object. ''' base_event_name = event_object.name if base_event_name in self.incoming_events_generators: for new_event_class in self.incoming_events_generators[ base_event_name]: new_event_object = new_event_class( None, base_event=event_object) if new_event_object.generate(): if not app.ged.raise_event(new_event_object.name, new_event_object): self._generate_events_based_on_incoming_event( new_event_object) def _generate_events_based_on_outgoing_event(self, event_object): ''' :return: True if even_object should be dispatched through Global Events Dispatcher, False otherwise. This can be used to replace base events with those that more data computed (easier to use by handlers). :note: replacing mechanism is not implemented currently, but will be based on attribute in new network events object. ''' base_event_name = event_object.name if base_event_name in self.outgoing_events_generators: for new_event_class in self.outgoing_events_generators[ base_event_name]: new_event_object = new_event_class( None, base_event=event_object) if new_event_object.generate(): if not app.ged.raise_event(new_event_object.name, new_event_object): self._generate_events_based_on_outgoing_event( new_event_object) class NetworkEvent: name = '' def __init__(self, new_name, **kwargs): if new_name: self.name = new_name self.init() self._set_kwargs_as_attributes(**kwargs) def init(self): pass def generate(self): ''' Generates new event (sets it's attributes) based on event object. Base event object name is one of those in `base_network_events`. Reference to base event object is stored in `self.base_event` attribute. Note that this is a reference, so modifications to that event object are possible before dispatching to Global Events Dispatcher. :return: True if generated event should be dispatched, False otherwise. ''' return True def _set_kwargs_as_attributes(self, **kwargs): for k, v in kwargs.items(): if k not in ('name', 'base_network_events'): setattr(self, k, v) def _set_base_event_vars_as_attributes(self, event): for k, v in vars(event).items(): if k not in ('name', 'base_network_events'): setattr(self, k, v) class NetworkIncomingEvent(NetworkEvent): base_network_events = [] # type: List[str] ''' Names of base network events that new event is going to be generated on. ''' class NetworkOutgoingEvent(NetworkEvent): base_network_events = [] # type: List[str] ''' Names of base network events that new event is going to be generated on. ''' gajim-gajim-1.1.3/gajim/common/optparser.py000066400000000000000000000232151345766322700206620ustar00rootroot00000000000000# Copyright (C) 2003-2005 Vincent Hanquez # Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Dimitur Kirov # Nikos Kouremenos # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 James Newton # Brendan Taylor # Tomasz Melcer # Stephan Erb # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys import re import logging from pathlib import Path from gajim.common import app from gajim.common import caps_cache from gajim.common.i18n import _ log = logging.getLogger('gajim.c.optparser') class OptionsParser: def __init__(self, filename): self.__filename = os.path.realpath(filename) self.old_values = {} # values that are saved in the file and maybe # no longer valid def read(self): try: fd = open(self.__filename, encoding='utf-8') except Exception: if os.path.exists(self.__filename): #we talk about a file print(_('Error: cannot open %s for reading') % self.__filename, file=sys.stderr) return False new_version = app.config.get('version') new_version = new_version.split('+', 1)[0] seen = set() regex = re.compile(r"(?P[^.=]+)(?:(?:\.(?P.+))?\.(?P[^.=]+))?\s=\s(?P.*)") for line in fd: match = regex.match(line) if match is None: log.warning('Invalid configuration line, ignoring it: %s', line) continue optname, key, subname, value = match.groups() if key is None: self.old_values[optname] = value app.config.set(optname, value) else: if (optname, key) not in seen: if optname in self.old_values: self.old_values[optname][key] = {} else: self.old_values[optname] = {key: {}} app.config.add_per(optname, key) seen.add((optname, key)) self.old_values[optname][key][subname] = value app.config.set_per(optname, key, subname, value) old_version = app.config.get('version') if '+' in old_version: old_version = old_version.split('+', 1)[0] elif '-' in old_version: old_version = old_version.split('-', 1)[0] self.update_config(old_version, new_version) self.old_values = {} # clean mem fd.close() return True def write_line(self, fd, opt, parents, value): if value is None: return # convert to utf8 before writing to file if needed value = str(value) s = '' if parents: if len(parents) == 1: return for p in parents: s += p + '.' s += opt fd.write(s + ' = ' + value + '\n') def write(self): config_path = Path(self.__filename) tempfile = 'temp_%s' % config_path.name temp_filepath = config_path.parent / tempfile try: with open(str(temp_filepath), 'w', encoding='utf-8') as file: app.config.foreach(self.write_line, file) except IOError: log.exception('Failed to write config file') return try: temp_filepath.replace(config_path) except Exception: log.exception('Failed to replace config file') else: log.info('Successful saved config file') def update_config(self, old_version, new_version): old_version_list = old_version.split('.') # convert '0.x.y' to (0, x, y) old = [] while old_version_list: old.append(int(old_version_list.pop(0))) new_version_list = new_version.split('.') new = [] while new_version_list: new.append(int(new_version_list.pop(0))) if old < [0, 14, 0, 1] and new >= [0, 14, 0, 1]: self.update_config_to_01401() if old < [0, 14, 90, 0] and new >= [0, 14, 90, 0]: self.update_config_to_014900() if old < [0, 16, 0, 1] and new >= [0, 16, 0, 1]: self.update_config_to_01601() if old < [0, 16, 4, 1] and new >= [0, 16, 4, 1]: self.update_config_to_01641() if old < [0, 16, 10, 1] and new >= [0, 16, 10, 1]: self.update_config_to_016101() if old < [0, 16, 10, 2] and new >= [0, 16, 10, 2]: self.update_config_to_016102() if old < [0, 16, 10, 4] and new >= [0, 16, 10, 4]: self.update_config_to_016104() if old < [0, 16, 10, 5] and new >= [0, 16, 10, 5]: self.update_config_to_016105() if old < [0, 98, 3] and new >= [0, 98, 3]: self.update_config_to_0983() app.config.set('version', new_version) caps_cache.capscache.initialize_from_db() @staticmethod def update_ft_proxies(to_remove=None, to_add=None): if to_remove is None: to_remove = [] if to_add is None: to_add = [] for account in app.config.get_per('accounts'): proxies_str = app.config.get_per('accounts', account, 'file_transfer_proxies') proxies = [p.strip() for p in proxies_str.split(',')] for wrong_proxy in to_remove: if wrong_proxy in proxies: proxies.remove(wrong_proxy) for new_proxy in to_add: if new_proxy not in proxies: proxies.append(new_proxy) proxies_str = ', '.join(proxies) app.config.set_per('accounts', account, 'file_transfer_proxies', proxies_str) def update_config_to_01401(self): if 'autodetect_browser_mailer' not in self.old_values or 'openwith' \ not in self.old_values or \ (self.old_values['autodetect_browser_mailer'] is False and \ self.old_values['openwith'] != 'custom'): app.config.set('autodetect_browser_mailer', True) app.config.set('openwith', app.config.DEFAULT_OPENWITH) app.config.set('version', '0.14.0.1') def update_config_to_014900(self): if 'use_stun_server' in self.old_values and self.old_values[ 'use_stun_server'] and not self.old_values['stun_server']: app.config.set('use_stun_server', False) if os.name == 'nt': app.config.set('autodetect_browser_mailer', True) def update_config_to_01601(self): if 'last_mam_id' in self.old_values: last_mam_id = self.old_values['last_mam_id'] for account in app.config.get_per('accounts'): app.config.set_per('accounts', account, 'last_mam_id', last_mam_id) app.config.set('version', '0.16.0.1') def update_config_to_01641(self): for account in self.old_values['accounts'].keys(): connection_types = self.old_values['accounts'][account][ 'connection_types'].split() if 'plain' in connection_types and len(connection_types) > 1: connection_types.remove('plain') app.config.set_per('accounts', account, 'connection_types', ' '.join(connection_types)) app.config.set('version', '0.16.4.1') def update_config_to_016101(self): if 'video_input_device' in self.old_values: if self.old_values['video_input_device'] == 'autovideosrc ! videoscale ! ffmpegcolorspace': app.config.set('video_input_device', 'autovideosrc') if self.old_values['video_input_device'] == 'videotestsrc is-live=true ! video/x-raw-yuv,framerate=10/1': app.config.set('video_input_device', 'videotestsrc is-live=true ! video/x-raw,framerate=10/1') app.config.set('version', '0.16.10.1') def update_config_to_016102(self): for account in self.old_values['accounts'].keys(): app.config.del_per('accounts', account, 'minimized_gc') app.config.set('version', '0.16.10.2') def update_config_to_016104(self): app.config.set('emoticons_theme', 'noto-emoticons') app.config.set('version', '0.16.10.4') def update_config_to_016105(self): app.config.set('muc_restore_timeout', -1) app.config.set('restore_timeout', -1) app.config.set('version', '0.16.10.5') def update_config_to_0983(self): for account in self.old_values['accounts'].keys(): password = self.old_values['accounts'][account]['password'] if password == "winvault:": app.config.set_per('accounts', account, 'password', 'keyring:') elif password == "libsecret:": app.config.set_per('accounts', account, 'password', '') app.config.set('version', '0.98.3') gajim-gajim-1.1.3/gajim/common/passwords.py000066400000000000000000000123601345766322700206670ustar00rootroot00000000000000# Copyright (C) 2006 Gustavo J. A. M. Carneiro # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Jean-Marie Traissard # Julien Pivotto # Copyright (C) 2008 Stephan Erb # Copyright (c) 2009 Thorsten Glaser # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging from gajim.common import app __all__ = ['get_password', 'save_password'] log = logging.getLogger('gajim.password') try: import keyring from keyring.core import recommended KEYRING_AVAILABLE = True except ImportError: KEYRING_AVAILABLE = False log.debug('python-keyring missing, falling back to plaintext storage') class PasswordStorage: """Interface for password stores""" def get_password(self, account_name): """Return the password for account_name, or None if not found.""" raise NotImplementedError def save_password(self, account_name, password): """Save password for account_name. Return a bool indicating success.""" raise NotImplementedError class SecretPasswordStorage(PasswordStorage): """ Store password using Keyring """ identifier = 'keyring:' def __init__(self): self.keyring = keyring.get_keyring() log.info('Chose %s backend', self.keyring) def save_password(self, account_name, password): try: self.keyring.set_password('gajim', account_name, password) return True except Exception as error: log.warning('Save password failed') log.debug(error) return False def get_password(self, account_name): log.debug('getting password') return self.keyring.get_password('gajim', account_name) class PasswordStorageManager(PasswordStorage): """Access all the implemented password storage backends, knowing which ones are available and which we prefer to use. Also implements storing directly in gajim config.""" def __init__(self): self.preferred_backend = None self.secret = None self.connect_backends() self.set_preferred_backend() def connect_backends(self): """Initialize backend connections, determining which ones are available. """ if not app.config.get('use_keyring') or not KEYRING_AVAILABLE: return backends = keyring.backend.get_all_keyring() for backend in backends: log.info('Found keyring backend: %s', backend) for backend in backends: if recommended(backend): self.secret = SecretPasswordStorage() return log.warning('No recommended keyring backend found, ' 'plain storage is used') def get_password(self, account_name): pw = app.config.get_per('accounts', account_name, 'password') if not pw: return pw if pw.startswith(SecretPasswordStorage.identifier) and self.secret: backend = self.secret else: backend = None if backend: pw = backend.get_password(account_name) if backend != self.preferred_backend: # migrate password to preferred_backend self.save_password(account_name, pw) # TODO: remove from old backend return pw def save_password(self, account_name, password): if self.preferred_backend: if self.preferred_backend.save_password(account_name, password): app.config.set_per('accounts', account_name, 'password', self.preferred_backend.identifier) if account_name in app.connections: app.connections[account_name].password = password return True app.config.set_per('accounts', account_name, 'password', password) if account_name in app.connections: app.connections[account_name].password = password return True def set_preferred_backend(self): if self.secret: self.preferred_backend = self.secret else: self.preferred_backend = None passwordStorageManager = None def get_storage(): global passwordStorageManager if not passwordStorageManager: passwordStorageManager = PasswordStorageManager() return passwordStorageManager def get_password(account_name): return get_storage().get_password(account_name) def save_password(account_name, password): if account_name in app.connections: app.connections[account_name].set_password(password) return get_storage().save_password(account_name, password) gajim-gajim-1.1.3/gajim/common/pep.py000066400000000000000000000052431345766322700174300ustar00rootroot00000000000000# Copyright (C) 2007 Piotr Gaczkowski # Copyright (C) 2007-2014 Yann Leboulanger # Copyright (C) 2008 Brendan Taylor # Jean-Marie Traissard # Jonathan Schleifer # Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Any # pylint: disable=unused-import from typing import List # pylint: disable=unused-import import logging from gajim.common import app log = logging.getLogger('gajim.c.pep') class AbstractPEP: type_ = '' namespace = '' @classmethod def get_tag_as_PEP(cls, jid, account, event_tag): items = event_tag.getTag('items', {'node': cls.namespace}) if items: log.debug('Received PEP "user %s" from %s', cls.type_, jid) return cls(jid, account, items) return None def __init__(self, jid, account, items): self.data, self._retracted = self._extract_info(items) self._update_contacts(jid, account) if jid == app.get_jid_from_account(account): self._update_account(account) self._on_receive(jid, account) def _extract_info(self, items): '''To be implemented by subclasses''' raise NotImplementedError def _update_contacts(self, jid, account): for contact in app.contacts.get_contacts(account, jid): if self._retracted: if self.type_ in contact.pep: del contact.pep[self.type_] else: contact.pep[self.type_] = self def _update_account(self, account): acc = app.connections[account] if self._retracted: if self.type_ in acc.pep: del acc.pep[self.type_] else: acc.pep[self.type_] = self def as_markup_text(self): '''SHOULD be implemented by subclasses''' return '' def _on_receive(self, jid, account): '''SHOULD be implemented by subclasses''' pass SUPPORTED_PERSONAL_USER_EVENTS = [] # type: List[Any] gajim-gajim-1.1.3/gajim/common/protocol/000077500000000000000000000000001345766322700201275ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/protocol/__init__.py000066400000000000000000000000741345766322700222410ustar00rootroot00000000000000""" Implementations of specific XMPP protocols and XEPs """ gajim-gajim-1.1.3/gajim/common/protocol/bytestream.py000066400000000000000000001207751345766322700226740ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # Junglecow J # Copyright (C) 2006-2007 Tomasz Melcer # Travis Shirk # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Julien Pivotto # Copyright (C) 2007-2008 Brendan Taylor # Jean-Marie Traissard # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import socket import base64 from gi.repository import GLib import time import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common import ged from gajim.common import jingle_xtls from gajim.common.file_props import FilesProp from gajim.common.socks5 import Socks5SenderClient import logging log = logging.getLogger('gajim.c.p.bytestream') def is_transfer_paused(file_props): if file_props.stopped: return False if file_props.completed: return False if file_props.disconnect_cb: return False return file_props.paused def is_transfer_active(file_props): if file_props.stopped: return False if file_props.completed: return False if not file_props.started: return False if file_props.paused: return True return not file_props.paused def is_transfer_stopped(file_props): if not file_props: return True if file_props.error: return True if file_props.completed: return True if not file_props.stopped: return False return True class ConnectionBytestream: def __init__(self): app.ged.register_event_handler('file-request-received', ged.GUI1, self._nec_file_request_received) def pass_bytestream_disco(self, from_, identities, features, data, node): if nbxmpp.NS_BYTESTREAM not in features: return if app.config.get_per('accounts', self.name, 'use_ft_proxies'): log.info('Discovered proxy: %s', from_) our_fjid = self.get_own_jid() testit = app.config.get_per( 'accounts', self.name, 'test_ft_proxies_on_startup') app.proxy65_manager.resolve( from_, self.connection, str(our_fjid), default=self.name, testit=testit) raise nbxmpp.NodeProcessed def cleanup(self): app.ged.remove_event_handler('file-request-received', ged.GUI1, self._nec_file_request_received) def _ft_get_our_jid(self): our_jid = app.get_jid_from_account(self.name) resource = self.server_resource return our_jid + '/' + resource def _ft_get_receiver_jid(self, file_props): return file_props.receiver.jid + '/' + file_props.receiver.resource def _ft_get_from(self, iq_obj): return helpers.get_full_jid_from_iq(iq_obj) def _ft_get_streamhost_jid_attr(self, streamhost): return helpers.parse_jid(streamhost.getAttr('jid')) def send_file_request(self, file_props): """ Send iq for new FT request """ if not self.connection or self.connected < 2: return file_props.sender = self._ft_get_our_jid() fjid = self._ft_get_receiver_jid(file_props) iq = nbxmpp.Iq(to=fjid, typ='set') iq.setID(file_props.sid) si = iq.setTag('si', namespace=nbxmpp.NS_SI) si.setAttr('profile', nbxmpp.NS_FILE) si.setAttr('id', file_props.sid) file_tag = si.setTag('file', namespace=nbxmpp.NS_FILE) file_tag.setAttr('name', file_props.name) file_tag.setAttr('size', file_props.size) desc = file_tag.setTag('desc') if file_props.desc: desc.setData(file_props.desc) file_tag.setTag('range') feature = si.setTag('feature', namespace=nbxmpp.NS_FEATURE) _feature = nbxmpp.DataForm(typ='form') feature.addChild(node=_feature) field = _feature.setField('stream-method') field.setAttr('type', 'list-single') field.addOption(nbxmpp.NS_BYTESTREAM) field.addOption(nbxmpp.NS_IBB) self.connection.send(iq) def send_file_approval(self, file_props): """ Send iq, confirming that we want to download the file """ # user response to ConfirmationDialog may come after we've disconneted if not self.connection or self.connected < 2: return # file transfer initiated by a jingle session log.info("send_file_approval: jingle session accept") if file_props.session_type == 'jingle': session = self.get_jingle_session(file_props.sender, file_props.sid) if not session: return content = None for c in session.contents.values(): if c.transport.sid == file_props.transport_sid: content = c break if not content: return if not session.accepted: content = session.get_content('file', content.name) if content.use_security: fingerprint = content.x509_fingerprint if not jingle_xtls.check_cert( app.get_jid_without_resource(file_props.sender), fingerprint): id_ = jingle_xtls.send_cert_request(self, file_props.sender) jingle_xtls.key_exchange_pend(id_, content.on_cert_received, []) return session.approve_session() session.approve_content('file', content.name) return iq = nbxmpp.Iq(to=file_props.sender, typ='result') iq.setAttr('id', file_props.request_id) si = iq.setTag('si', namespace=nbxmpp.NS_SI) if file_props.offset: file_tag = si.setTag('file', namespace=nbxmpp.NS_FILE) range_tag = file_tag.setTag('range') range_tag.setAttr('offset', file_props.offset) feature = si.setTag('feature', namespace=nbxmpp.NS_FEATURE) _feature = nbxmpp.DataForm(typ='submit') feature.addChild(node=_feature) field = _feature.setField('stream-method') field.delAttr('type') if nbxmpp.NS_BYTESTREAM in file_props.stream_methods: field.setValue(nbxmpp.NS_BYTESTREAM) else: file_props.transport_sid = file_props.sid field.setValue(nbxmpp.NS_IBB) self.connection.send(iq) def send_file_rejection(self, file_props, code='403', typ=None): """ Inform sender that we refuse to download the file typ is used when code = '400', in this case typ can be 'stream' for invalid stream or 'profile' for invalid profile """ # user response to ConfirmationDialog may come after we've disconnected if not self.connection or self.connected < 2: return if file_props.session_type == 'jingle': if file_props.sid in self._sessions: jingle = self._sessions[file_props.sid] jingle.cancel_session() return iq = nbxmpp.Iq(to=file_props.sender, typ='error') iq.setAttr('id', file_props.request_id) if code == '400' and typ in ('stream', 'profile'): name = 'bad-request' text = '' else: name = 'forbidden' text = 'Offer Declined' err = nbxmpp.ErrorNode(code=code, typ='cancel', name=name, text=text) if code == '400' and typ in ('stream', 'profile'): if typ == 'stream': err.setTag('no-valid-streams', namespace=nbxmpp.NS_SI) else: err.setTag('bad-profile', namespace=nbxmpp.NS_SI) iq.addChild(node=err) self.connection.send(iq) def _siResultCB(self, con, iq_obj): file_props = FilesProp.getFileProp(self.name, iq_obj.getAttr('id')) if not file_props: return if file_props.request_id: # we have already sent streamhosts info return file_props.receiver = self._ft_get_from(iq_obj) si = iq_obj.getTag('si') file_tag = si.getTag('file') range_tag = None if file_tag: range_tag = file_tag.getTag('range') if range_tag: offset = range_tag.getAttr('offset') if offset: file_props.offset = int(offset) length = range_tag.getAttr('length') if length: file_props.length = int(length) feature = si.setTag('feature') if feature.getNamespace() != nbxmpp.NS_FEATURE: return form_tag = feature.getTag('x') form = nbxmpp.DataForm(node=form_tag) field = form.getField('stream-method') if field.getValue() == nbxmpp.NS_BYTESTREAM: self._send_socks5_info(file_props) raise nbxmpp.NodeProcessed if field.getValue() == nbxmpp.NS_IBB: sid = file_props.sid file_props.transport_sid = sid fp = open(file_props.file_name, 'rb') self.OpenStream(sid, file_props.receiver, fp) raise nbxmpp.NodeProcessed def _siSetCB(self, con, iq_obj): from gajim.common.connection_handlers_events import FileRequestReceivedEvent app.nec.push_incoming_event(FileRequestReceivedEvent(None, conn=self, stanza=iq_obj)) raise nbxmpp.NodeProcessed def _nec_file_request_received(self, obj): pass def _siErrorCB(self, con, iq_obj): si = iq_obj.getTag('si') profile = si.getAttr('profile') if profile != nbxmpp.NS_FILE: return file_props = FilesProp.getFileProp(self.name, iq_obj.getAttr('id')) if not file_props: return jid = self._ft_get_from(iq_obj) file_props.error = -3 from gajim.common.connection_handlers_events import FileRequestErrorEvent app.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, jid=jid, file_props=file_props, error_msg='')) raise nbxmpp.NodeProcessed class ConnectionSocks5Bytestream(ConnectionBytestream): def send_success_connect_reply(self, streamhost): """ Send reply to the initiator of FT that we made a connection """ if not self.connection or self.connected < 2: return if streamhost is None: return None iq = nbxmpp.Iq(to=streamhost['initiator'], typ='result', frm=streamhost['target']) iq.setAttr('id', streamhost['id']) query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM) stream_tag = query.setTag('streamhost-used') stream_tag.setAttr('jid', streamhost['jid']) self.connection.send(iq) def stop_all_active_file_transfers(self, contact): """ Stop all active transfer to or from the given contact """ for file_props in FilesProp.getAllFileProp(): if is_transfer_stopped(file_props): continue receiver_jid = file_props.receiver if contact.get_full_jid() == receiver_jid: file_props.error = -5 self.remove_transfer(file_props) from gajim.common.connection_handlers_events import \ FileRequestErrorEvent app.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, jid=contact.jid, file_props=file_props, error_msg='')) sender_jid = file_props.sender if contact.get_full_jid() == sender_jid: file_props.error = -3 self.remove_transfer(file_props) def remove_all_transfers(self): """ Stop and remove all active connections from the socks5 pool """ for file_props in FilesProp.getAllFileProp(): self.remove_transfer(file_props, remove_from_list=False) def remove_transfer(self, file_props, remove_from_list=True): if file_props is None: return self.disconnect_transfer(file_props) def disconnect_transfer(self, file_props): if file_props is None: return if file_props.hash_: app.socks5queue.remove_sender(file_props.hash_) if file_props.streamhosts: for host in file_props.streamhosts: if 'idx' in host and host['idx'] > 0: app.socks5queue.remove_receiver(host['idx']) app.socks5queue.remove_sender(host['idx']) def _send_socks5_info(self, file_props): """ Send iq for the present streamhosts and proxies """ if not self.connection or self.connected < 2: return receiver = file_props.receiver sender = file_props.sender sha_str = helpers.get_auth_sha(file_props.sid, sender, receiver) file_props.sha_str = sha_str port = app.config.get('file_transfers_port') listener = app.socks5queue.start_listener(port, sha_str, self._result_socks5_sid, file_props) if not listener: file_props.error = -5 from gajim.common.connection_handlers_events import FileRequestErrorEvent app.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, jid=receiver, file_props=file_props, error_msg='')) self._connect_error(file_props.sid, error='not-acceptable', error_type='modify') else: iq = nbxmpp.Iq(to=receiver, typ='set') file_props.request_id = 'id_' + file_props.sid iq.setID(file_props.request_id) query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM) query.setAttr('sid', file_props.sid) self._add_addiditional_streamhosts_to_query(query, file_props) self._add_local_ips_as_streamhosts_to_query(query, file_props) self._add_proxy_streamhosts_to_query(query, file_props) self._add_upnp_igd_as_streamhost_to_query(query, file_props, iq) # Upnp-igd is asynchronous, so it will send the iq itself def _add_streamhosts_to_query(self, query, sender, port, hosts): for host in hosts: streamhost = nbxmpp.Node(tag='streamhost') query.addChild(node=streamhost) streamhost.setAttr('port', str(port)) streamhost.setAttr('host', host) streamhost.setAttr('jid', sender) def _add_local_ips_as_streamhosts_to_query(self, query, file_props): if not app.config.get_per('accounts', self.name, 'ft_send_local_ips'): return try: my_ips = [self.peerhost[0]] # The ip we're connected to server with # all IPs from local DNS for addr in socket.getaddrinfo(socket.gethostname(), None): if not addr[4][0] in my_ips and not addr[4][0].startswith('127') and not addr[4][0] == '::1': my_ips.append(addr[4][0]) sender = file_props.sender port = app.config.get('file_transfers_port') self._add_streamhosts_to_query(query, sender, port, my_ips) except socket.gaierror: from gajim.common.connection_handlers_events import InformationEvent app.nec.push_incoming_event( InformationEvent(None, dialog_name='wrong-host')) def _add_addiditional_streamhosts_to_query(self, query, file_props): sender = file_props.sender port = app.config.get('file_transfers_port') ft_add_hosts_to_send = app.config.get('ft_add_hosts_to_send') additional_hosts = [] if ft_add_hosts_to_send: additional_hosts = [e.strip() for e in ft_add_hosts_to_send.split(',')] else: additional_hosts = [] self._add_streamhosts_to_query(query, sender, port, additional_hosts) def _add_upnp_igd_as_streamhost_to_query(self, query, file_props, iq): if not app.is_installed('UPNP'): self.connection.send(iq) return my_ip = self.peerhost[0] # check if we are connected with an IPv4 address try: socket.inet_aton(my_ip) except socket.error: self.connection.send(iq) return def ip_is_local(ip): if '.' not in ip: # it's an IPv6 return True ip_s = ip.split('.') ip_l = int(ip_s[0])<<24 | int(ip_s[1])<<16 | int(ip_s[2])<<8 | \ int(ip_s[3]) # 10/8 if ip_l & (255<<24) == 10<<24: return True # 172.16/12 if ip_l & (255<<24 | 240<<16) == (172<<24 | 16<<16): return True # 192.168 if ip_l & (255<<24 | 255<<16) == (192<<24 | 168<<16): return True return False if not ip_is_local(my_ip): self.connection.send(iq) return self.no_gupnp_reply_id = 0 def cleanup_gupnp(): if self.no_gupnp_reply_id: GLib.source_remove(self.no_gupnp_reply_id) self.no_gupnp_reply_id = 0 app.gupnp_igd.disconnect(self.ok_id) app.gupnp_igd.disconnect(self.fail_id) def ok(s, proto, ext_ip, re, ext_port, local_ip, local_port, desc): log.debug('Got GUPnP-IGD answer: external: %s:%s, internal: %s:%s', ext_ip, ext_port, local_ip, local_port) if local_port != app.config.get('file_transfers_port'): sender = file_props.sender receiver = file_props.receiver sha_str = helpers.get_auth_sha(file_props.sid, sender, receiver) listener = app.socks5queue.start_listener(local_port, sha_str, self._result_socks5_sid, file_props.sid) if listener: self._add_streamhosts_to_query(query, sender, ext_port, [ext_ip]) else: self._add_streamhosts_to_query(query, file_props.sender, ext_port, [ext_ip]) self.connection.send(iq) cleanup_gupnp() def fail(s, error, proto, ext_ip, local_ip, local_port, desc): log.debug('Got GUPnP-IGD error') self.connection.send(iq) cleanup_gupnp() def no_upnp_reply(): log.debug('Got not GUPnP-IGD answer') # stop trying to use it app.disable_dependency('UPNP') self.no_gupnp_reply_id = 0 self.connection.send(iq) cleanup_gupnp() return False self.ok_id = app.gupnp_igd.connect('mapped-external-port', ok) self.fail_id = app.gupnp_igd.connect('error-mapping-port', fail) port = app.config.get('file_transfers_port') self.no_gupnp_reply_id = GLib.timeout_add_seconds(10, no_upnp_reply) app.gupnp_igd.add_port('TCP', 0, my_ip, port, 3600, 'Gajim file transfer') def _add_proxy_streamhosts_to_query(self, query, file_props): proxyhosts = self._get_file_transfer_proxies_from_config(file_props) if proxyhosts: file_props.proxy_receiver = file_props.receiver file_props.proxy_sender = file_props.sender file_props.proxyhosts = proxyhosts for proxyhost in proxyhosts: self._add_streamhosts_to_query(query, proxyhost['jid'], proxyhost['port'], [proxyhost['host']]) def _get_file_transfer_proxies_from_config(self, file_props): configured_proxies = app.config.get_per('accounts', self.name, 'file_transfer_proxies') shall_use_proxies = app.config.get_per('accounts', self.name, 'use_ft_proxies') if shall_use_proxies: proxyhost_dicts = [] proxies = [] if configured_proxies: proxies = [item.strip() for item in configured_proxies.split(',')] default_proxy = app.proxy65_manager.get_default_for_name(self.name) if default_proxy: # add/move default proxy at top of the others if default_proxy in proxies: proxies.remove(default_proxy) proxies.insert(0, default_proxy) for proxy in proxies: (host, _port, jid) = app.proxy65_manager.get_proxy(proxy, self.name) if not host: continue host_dict = { 'state': 0, 'target': file_props.receiver, 'id': file_props.sid, 'sid': file_props.sid, 'initiator': proxy, 'host': host, 'port': str(_port), 'jid': jid } proxyhost_dicts.append(host_dict) return proxyhost_dicts return [] def _result_socks5_sid(self, sid, hash_id): """ Store the result of SHA message from auth """ file_props = FilesProp.getFilePropBySid(sid) file_props.hash_ = hash_id return def _connect_error(self, sid, error, error_type, msg=None): """ Called when there is an error establishing BS connection, or when connection is rejected """ if not self.connection or self.connected < 2: return file_props = FilesProp.getFileProp(self.name, sid) if file_props is None: log.error('can not send iq error on failed transfer') return if file_props.type_ == 's': to = file_props.receiver else: to = file_props.sender iq = nbxmpp.Iq(to=to, typ='error') iq.setAttr('id', file_props.request_id) err = iq.setTag('error') err.setAttr('type', error_type) err.setTag(error, namespace=nbxmpp.NS_STANZAS) self.connection.send(iq) if msg: self.disconnect_transfer(file_props) file_props.error = -3 from gajim.common.connection_handlers_events import \ FileRequestErrorEvent app.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, jid=to, file_props=file_props, error_msg=msg)) def _proxy_auth_ok(self, proxy): """ Called after authentication to proxy server """ if not self.connection or self.connected < 2: return file_props = FilesProp.getFileProp(self.name, proxy['sid']) iq = nbxmpp.Iq(to=proxy['initiator'], typ='set') auth_id = "au_" + proxy['sid'] iq.setID(auth_id) query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM) query.setAttr('sid', proxy['sid']) activate = query.setTag('activate') activate.setData(file_props.proxy_receiver) iq.setID(auth_id) self.connection.send(iq) # register xmpppy handlers for bytestream and FT stanzas def _bytestreamErrorCB(self, con, iq_obj): id_ = iq_obj.getAttr('id') frm = helpers.get_full_jid_from_iq(iq_obj) query = iq_obj.getTag('query') app.proxy65_manager.error_cb(frm, query) jid = helpers.get_jid_from_iq(iq_obj) id_ = id_[3:] file_props = FilesProp.getFilePropBySid(id_) if not file_props: return file_props.error = -4 from gajim.common.connection_handlers_events import FileRequestErrorEvent app.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self, jid=jid, file_props=file_props, error_msg='')) raise nbxmpp.NodeProcessed def _bytestreamSetCB(self, con, iq_obj): target = iq_obj.getAttr('to') id_ = iq_obj.getAttr('id') query = iq_obj.getTag('query') sid = query.getAttr('sid') file_props = FilesProp.getFileProp(self.name, sid) streamhosts = [] for item in query.getChildren(): if item.getName() == 'streamhost': host_dict = { 'state': 0, 'target': target, 'id': id_, 'sid': sid, 'initiator': self._ft_get_from(iq_obj) } for attr in item.getAttrs(): host_dict[attr] = item.getAttr(attr) if 'host' not in host_dict: continue if 'jid' not in host_dict: continue if 'port' not in host_dict: continue streamhosts.append(host_dict) file_props = FilesProp.getFilePropBySid(sid) if file_props is not None: if file_props.type_ == 's': # FIXME: remove fast xmlns # only psi do this if file_props.streamhosts: file_props.streamhosts.extend(streamhosts) else: file_props.streamhosts = streamhosts app.socks5queue.connect_to_hosts(self.name, sid, self.send_success_connect_reply, None) raise nbxmpp.NodeProcessed else: log.warning('Gajim got streamhosts for unknown transfer. Ignoring it.') raise nbxmpp.NodeProcessed file_props.streamhosts = streamhosts def _connection_error(sid): self._connect_error(sid, 'item-not-found', 'cancel', msg='Could not connect to given hosts') if file_props.type_ == 'r': app.socks5queue.connect_to_hosts(self.name, sid, self.send_success_connect_reply, _connection_error) raise nbxmpp.NodeProcessed def _ResultCB(self, con, iq_obj): # if we want to respect xep-0065 we have to check for proxy # activation result in any result iq real_id = iq_obj.getAttr('id') if real_id is None: log.warning('Invalid IQ without id attribute:\n%s', iq_obj) raise nbxmpp.NodeProcessed if real_id is None or not real_id.startswith('au_'): return frm = self._ft_get_from(iq_obj) id_ = real_id[3:] file_props = FilesProp.getFilePropByTransportSid(self.name, id_) if file_props.streamhost_used: for host in file_props.proxyhosts: if host['initiator'] == frm and 'idx' in host: app.socks5queue.activate_proxy(host['idx']) raise nbxmpp.NodeProcessed def _bytestreamResultCB(self, con, iq_obj): frm = self._ft_get_from(iq_obj) real_id = iq_obj.getAttr('id') query = iq_obj.getTag('query') app.proxy65_manager.resolve_result(frm, query) try: streamhost = query.getTag('streamhost-used') except Exception: # this bytestream result is not what we need pass id_ = real_id[3:] file_props = FilesProp.getFileProp(self.name, id_) if file_props is None: raise nbxmpp.NodeProcessed if streamhost is None: # proxy approves the activate query if real_id.startswith('au_'): if file_props.streamhost_used is False: raise nbxmpp.NodeProcessed if not file_props.proxyhosts: raise nbxmpp.NodeProcessed for host in file_props.proxyhosts: if host['initiator'] == frm and \ query.getAttr('sid') == file_props.sid: app.socks5queue.activate_proxy(host['idx']) break raise nbxmpp.NodeProcessed jid = self._ft_get_streamhost_jid_attr(streamhost) if file_props.streamhost_used is True: raise nbxmpp.NodeProcessed if real_id.startswith('au_'): if file_props.stopped: self.remove_transfer(file_props) else: app.socks5queue.send_file(file_props, self.name, 'server') raise nbxmpp.NodeProcessed proxy = None if file_props.proxyhosts: for proxyhost in file_props.proxyhosts: if proxyhost['jid'] == jid: proxy = proxyhost if file_props.stopped: self.remove_transfer(file_props) raise nbxmpp.NodeProcessed if proxy is not None: file_props.streamhost_used = True file_props.streamhosts.append(proxy) file_props.is_a_proxy = True idx = app.socks5queue.idx sender = Socks5SenderClient(app.idlequeue, idx, app.socks5queue, _sock=None, host=str(proxy['host']), port=int(proxy['port']), fingerprint=None, connected=False, file_props=file_props) sender.streamhost = proxy app.socks5queue.add_sockobj(self.name, sender) proxy['idx'] = sender.queue_idx app.socks5queue.on_success[file_props.sid] = self._proxy_auth_ok raise nbxmpp.NodeProcessed else: if file_props.stopped: self.remove_transfer(file_props) else: app.socks5queue.send_file(file_props, self.name, 'server') raise nbxmpp.NodeProcessed class ConnectionIBBytestream(ConnectionBytestream): def __init__(self): ConnectionBytestream.__init__(self) self._streams = {} def IBBIqHandler(self, conn, stanza): """ Handles streams state change. Used internally. """ typ = stanza.getType() log.debug('IBBIqHandler called typ->%s', typ) if typ == 'set' and stanza.getTag('open'): self.StreamOpenHandler(conn, stanza) elif typ == 'set' and stanza.getTag('close'): self.StreamCloseHandler(conn, stanza) elif typ == 'set' and stanza.getTag('data'): sid = stanza.getTagAttr('data', 'sid') file_props = FilesProp.getFilePropByTransportSid(self.name, sid) if not file_props: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)) elif file_props.connected and self.IBBMessageHandler(conn, stanza): reply = stanza.buildReply('result') reply.delChild('data') conn.send(reply) elif not file_props.connected: log.debug('Received IQ for closed filetransfer, IQ dropped') elif typ == 'error': app.socks5queue.error_cb() else: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_BAD_REQUEST)) raise nbxmpp.NodeProcessed def StreamOpenHandler(self, conn, stanza): """ Handles opening of new incoming stream. Used internally. """ err = None sid = stanza.getTagAttr('open', 'sid') blocksize = stanza.getTagAttr('open', 'block-size') log.debug('StreamOpenHandler called sid->%s blocksize->%s', sid, blocksize) file_props = FilesProp.getFilePropByTransportSid(self.name, sid) try: blocksize = int(blocksize) except Exception: err = nbxmpp.ERR_BAD_REQUEST if not sid or not blocksize: err = nbxmpp.ERR_BAD_REQUEST elif not file_props: err = nbxmpp.ERR_UNEXPECTED_REQUEST if err: rep = nbxmpp.Error(stanza, err) else: log.debug("Opening stream: id %s, block-size %s", sid, blocksize) rep = nbxmpp.Protocol('iq', stanza.getFrom(), 'result', stanza.getTo(), {'id': stanza.getID()}) file_props.block_size = blocksize file_props.direction = '<' file_props.seq = 0 file_props.received_len = 0 file_props.last_time = time.time() file_props.error = 0 file_props.paused = False file_props.connected = True file_props.completed = False file_props.disconnect_cb = None file_props.continue_cb = None file_props.syn_id = stanza.getID() file_props.fp = open(file_props.file_name, 'wb') conn.send(rep) def CloseIBBStream(self, file_props): file_props.connected = False file_props.fp.close() file_props.stopped = True to = file_props.receiver if file_props.direction == '<': to = file_props.sender self.connection.send( nbxmpp.Protocol('iq', to, 'set', payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close', {'sid':file_props.transport_sid})])) if file_props.completed: app.socks5queue.complete_transfer_cb(self.name, file_props) elif file_props.session_type == 'jingle': peerjid = \ file_props.receiver if file_props.type_ == 's' else file_props.sender session = self.get_jingle_session(peerjid, file_props.sid, 'file') # According to the xep, the initiator also cancels the jingle session # if there are no more files to send using IBB if session.weinitiate: session.cancel_session() def OpenStream(self, sid, to, fp, blocksize=4096): """ Start new stream. You should provide stream id 'sid', the endpoint jid 'to', the file object containing info for send 'fp'. Also the desired blocksize can be specified. Take into account that recommended stanza size is 4k and IBB uses base64 encoding that increases size of data by 1/3. """ file_props = FilesProp.getFilePropBySid(sid) file_props.direction = '>' file_props.block_size = blocksize file_props.fp = fp file_props.seq = 0 file_props.error = 0 file_props.paused = False file_props.received_len = 0 file_props.last_time = time.time() file_props.connected = True file_props.completed = False file_props.disconnect_cb = None file_props.continue_cb = None syn = nbxmpp.Protocol('iq', to, 'set', payload=[nbxmpp.Node( nbxmpp.NS_IBB + ' open', {'sid': file_props.transport_sid, 'block-size': blocksize, 'stanza': 'iq'})]) self.connection.send(syn) file_props.syn_id = syn.getID() return file_props def SendHandler(self, file_props): """ Send next portion of data if it is time to do it. Used internally. """ log.debug('SendHandler called') if file_props.completed: self.CloseIBBStream(file_props) if file_props.paused: return if not file_props.connected: #TODO: Reply with out of order error return chunk = file_props.fp.read(file_props.block_size) if chunk: datanode = nbxmpp.Node(nbxmpp.NS_IBB + ' data', { 'sid': file_props.transport_sid, 'seq': file_props.seq}, base64.b64encode(chunk).decode('ascii')) file_props.seq += 1 file_props.started = True if file_props.seq == 65536: file_props.seq = 0 file_props.syn_id = self.connection.send( nbxmpp.Protocol(name='iq', to=file_props.receiver, typ='set', payload=[datanode])) current_time = time.time() file_props.elapsed_time += current_time - file_props.last_time file_props.last_time = current_time file_props.received_len += len(chunk) if file_props.size == file_props.received_len: file_props.completed = True app.socks5queue.progress_transfer_cb(self.name, file_props) else: log.debug('Nothing to read, but file not completed') def IBBMessageHandler(self, conn, stanza): """ Receive next portion of incoming datastream and store it write it to temporary file. Used internally. """ sid = stanza.getTagAttr('data', 'sid') seq = stanza.getTagAttr('data', 'seq') data = stanza.getTagData('data') log.debug('ReceiveHandler called sid->%s seq->%s', sid, seq) try: seq = int(seq) data = base64.b64decode(data.encode('utf-8')) except Exception: seq = '' data = b'' err = None file_props = FilesProp.getFilePropByTransportSid(self.name, sid) if file_props is None: err = nbxmpp.ERR_ITEM_NOT_FOUND else: if not data: err = nbxmpp.ERR_BAD_REQUEST elif seq != file_props.seq: err = nbxmpp.ERR_UNEXPECTED_REQUEST else: log.debug('Successfully received sid->%s %s+%s bytes', sid, file_props.fp.tell(), len(data)) file_props.seq += 1 file_props.started = True file_props.fp.write(data) current_time = time.time() file_props.elapsed_time += current_time - file_props.last_time file_props.last_time = current_time file_props.received_len += len(data) app.socks5queue.progress_transfer_cb(self.name, file_props) if file_props.received_len >= file_props.size: file_props.completed = True if err: log.debug('Error on receive: %s', err) conn.send(nbxmpp.Error(nbxmpp.Iq(to=stanza.getFrom(), frm=stanza.getTo(), payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close')]), err, reply=0)) else: return True def StreamCloseHandler(self, conn, stanza): """ Handle stream closure due to all data transmitted. Raise xmpppy event specifying successful data receive. """ sid = stanza.getTagAttr('close', 'sid') log.debug('StreamCloseHandler called sid->%s', sid) # look in sending files file_props = FilesProp.getFilePropByTransportSid(self.name, sid) if file_props: reply = stanza.buildReply('result') reply.delChild('close') conn.send(reply) # look in receiving files file_props.fp.close() file_props.completed = file_props.received_len >= file_props.size if not file_props.completed: file_props.error = -1 app.socks5queue.complete_transfer_cb(self.name, file_props) else: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)) def IBBAllIqHandler(self, conn, stanza): """ Handle remote side reply about if it agree or not to receive our datastream. Used internally. Raises xmpppy event specifying if the data transfer is agreed upon. """ syn_id = stanza.getID() log.debug('IBBAllIqHandler called syn_id->%s', syn_id) for file_props in FilesProp.getAllFileProp(): if not file_props.direction or not file_props.connected: # It's socks5 bytestream # Or we closed the IBB stream continue if file_props.syn_id == syn_id: if stanza.getType() == 'error': if file_props.direction[0] == '<': conn.Event('IBB', 'ERROR ON RECEIVE', file_props) else: conn.Event('IBB', 'ERROR ON SEND', file_props) elif stanza.getType() == 'result': self.SendHandler(file_props) break class ConnectionSocks5BytestreamZeroconf(ConnectionSocks5Bytestream): def _ft_get_from(self, iq_obj): return iq_obj.getFrom() def _ft_get_our_jid(self): return app.get_jid_from_account(self.name) def _ft_get_receiver_jid(self, file_props): return file_props.receiver.jid def _ft_get_streamhost_jid_attr(self, streamhost): return streamhost.getAttr('jid') gajim-gajim-1.1.3/gajim/common/proxy65_manager.py000066400000000000000000000407341345766322700216760ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # Jean-Marie Traissard # Copyright (C) 2007-2014 Yann Leboulanger # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import socket import struct import errno import logging log = logging.getLogger('gajim.c.proxy65_manager') import nbxmpp from gajim.common import app from gajim.common import helpers from gajim.common.socks5 import Socks5 from nbxmpp.idlequeue import IdleObject from gajim.common.file_props import FilesProp S_INITIAL = 0 S_STARTED = 1 S_RESOLVED = 2 S_ACTIVATED = 3 S_FINISHED = 4 CONNECT_TIMEOUT = 20 class Proxy65Manager: """ Keep records for file transfer proxies. Each time account establishes a connection to its server call proxy65manger.resolve(proxy) for every proxy that is configured within the account. The class takes care to resolve and test each proxy only once """ def __init__(self, idlequeue): # dict {proxy: proxy properties} self.idlequeue = idlequeue self.proxies = {} # dict {account: proxy} default proxy for account self.default_proxies = {} def resolve(self, proxy, connection, sender_jid, default=None, testit=True): """ Start if testit=False, Gajim won't try to resolve it """ if proxy in self.proxies: resolver = self.proxies[proxy] else: # proxy is being resolved for the first time resolver = ProxyResolver(proxy, sender_jid, testit) self.proxies[proxy] = resolver resolver.add_connection(connection) if default: # add this proxy as default for account self.default_proxies[default] = proxy def disconnect(self, connection): for resolver in self.proxies.values(): resolver.disconnect(connection) def resolve_result(self, proxy, query): if proxy not in self.proxies: return jid = None for item in query.getChildren(): if item.getName() == 'streamhost': host = item.getAttr('host') jid = item.getAttr('jid') port = item.getAttr('port') try: port = int(port) except (ValueError, TypeError): port = 1080 if not host or not jid: self.proxies[proxy]._on_connect_failure() self.proxies[proxy].resolve_result(host, port, jid) # we can have only one streamhost raise nbxmpp.NodeProcessed def error_cb(self, proxy, query): sid = query.getAttr('sid') for resolver in self.proxies.values(): if resolver.sid == sid: resolver.keep_conf() break def get_default_for_name(self, account): if account in self.default_proxies: return self.default_proxies[account] def get_proxy(self, proxy, account): if proxy in self.proxies: resolver = self.proxies[proxy] if resolver.state == S_FINISHED: return (resolver.host, resolver.port, resolver.jid) return (None, 0, None) class ProxyResolver: def resolve_result(self, host, port, jid): """ Test if host has a real proxy65 listening on port """ self.host = str(host) self.port = int(port) self.jid = str(jid) if not self.testit: self.state = S_FINISHED return self.state = S_INITIAL log.info('start resolving %s:%s', self.host, self.port) self.receiver_tester = ReceiverTester(self.host, self.port, self.jid, self.sid, self.sender_jid, self._on_receiver_success, self._on_connect_failure) self.receiver_tester.connect() def _on_receiver_success(self): log.debug('Receiver successfully connected %s:%s', self.host, self.port) self.host_tester = HostTester(self.host, self.port, self.jid, self.sid, self.sender_jid, self._on_connect_success, self._on_connect_failure) self.host_tester.connect() def _on_connect_success(self): log.debug('Host successfully connected %s:%s', self.host, self.port) iq = nbxmpp.Protocol(name='iq', to=self.jid, typ='set') query = iq.setTag('query') query.setNamespace(nbxmpp.NS_BYTESTREAM) query.setAttr('sid', self.sid) activate = query.setTag('activate') activate.setData('test@gajim.org/test2') if self.active_connection: log.debug('Activating bytestream on %s:%s', self.host, self.port) self.active_connection.SendAndCallForResponse(iq, self._result_received) self.state = S_ACTIVATED else: self.state = S_INITIAL def _result_received(self, data): self.disconnect(self.active_connection) if data.getType() == 'result': self.keep_conf() else: self._on_connect_failure() def keep_conf(self): log.debug('Bytestream activated %s:%s', self.host, self.port) self.state = S_FINISHED def _on_connect_failure(self): log.debug('Connection failed with %s:%s', self.host, self.port) self.state = S_FINISHED self.host = None self.port = 0 self.jid = None def disconnect(self, connection): if self.host_tester: self.host_tester.disconnect() FilesProp.deleteFileProp(self.host_tester.file_props) self.host_tester = None if self.receiver_tester: self.receiver_tester.disconnect() FilesProp.deleteFileProp(self.receiver_tester.file_props) self.receiver_tester = None try: self.connections.remove(connection) except ValueError: pass if connection == self.active_connection: self.active_connection = None if self.state != S_FINISHED: self.state = S_INITIAL self.try_next_connection() def try_next_connection(self): """ Try to resolve proxy with the next possible connection """ if self.connections: connection = self.connections.pop(0) self.start_resolve(connection) def add_connection(self, connection): """ Add a new connection in case the first fails """ self.connections.append(connection) if self.state == S_INITIAL: self.start_resolve(connection) def start_resolve(self, connection): """ Request network address from proxy """ self.state = S_STARTED self.active_connection = connection iq = nbxmpp.Protocol(name='iq', to=self.proxy, typ='get') query = iq.setTag('query') query.setNamespace(nbxmpp.NS_BYTESTREAM) connection.send(iq) def __init__(self, proxy, sender_jid, testit): """ if testit is False, don't test it, only get IP/port """ self.proxy = proxy self.state = S_INITIAL self.active_connection = None self.connections = [] self.host_tester = None self.receiver_tester = None self.jid = None self.host = None self.port = None self.sid = helpers.get_random_string_16() self.sender_jid = sender_jid self.testit = testit class HostTester(Socks5, IdleObject): """ Fake proxy tester """ def __init__(self, host, port, jid, sid, sender_jid, on_success, on_failure): """ Try to establish and auth to proxy at (host, port) Calls on_success, or on_failure according to the result. """ self.host = host self.port = port self.jid = jid self.on_success = on_success self.on_failure = on_failure self._sock = None self.file_props = FilesProp.getNewFileProp(jid, sid) self.file_props.is_a_proxy = True self.file_props.proxy_sender = sender_jid self.file_props.proxy_receiver = 'test@gajim.org/test2' Socks5.__init__(self, app.idlequeue, host, port, None, None, None) self.sid = sid def connect(self): """ Create the socket and plug it to the idlequeue """ if self.host is None: self.on_failure() return None self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.setblocking(False) self.fd = self._sock.fileno() self.state = 0 # about to be connected app.idlequeue.plug_idle(self, True, False) self.do_connect() self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) return None def read_timeout(self): self.idlequeue.remove_timeout(self.fd) self.pollend() def pollend(self): self.disconnect() self.on_failure() def pollout(self): self.idlequeue.remove_timeout(self.fd) if self.state == 0: self.do_connect() return if self.state == 1: # send initially: version and auth types data = self._get_auth_buff() self.send_raw(data) else: return self.state += 1 # unplug and plug for reading app.idlequeue.plug_idle(self, False, True) app.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) def pollin(self): self.idlequeue.remove_timeout(self.fd) if self.state == 2: self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) # begin negotiation. on success 'address' != 0 buff = self.receive() if buff == b'': # end connection self.pollend() return # read auth response if buff is None or len(buff) != 2: return None version, method = struct.unpack('!BB', buff[:2]) if version != 0x05 or method == 0xff: self.pollend() return data = self._get_request_buff(self._get_sha1_auth()) self.send_raw(data) self.state += 1 log.debug('Host authenticating to %s:%s', self.host, self.port) elif self.state == 3: log.debug('Host authenticated to %s:%s', self.host, self.port) self.on_success() self.disconnect() self.state += 1 else: assert False, 'unexpected state: %d' % self.state def do_connect(self): try: self._sock.connect((self.host, self.port)) self._sock.setblocking(False) log.debug('Host Connecting to %s:%s', self.host, self.port) self._send = self._sock.send self._recv = self._sock.recv except Exception as ee: errnum = ee.errno # 56 is for freebsd if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK): # still trying to connect return # win32 needs this if errnum not in (0, 10056, errno.EISCONN): # connection failed self.on_failure() return # socket is already connected self._sock.setblocking(False) self._send = self._sock.send self._recv = self._sock.recv self.buff = b'' self.state = 1 # connected log.debug('Host connected to %s:%s', self.host, self.port) self.idlequeue.plug_idle(self, True, False) return class ReceiverTester(Socks5, IdleObject): """ Fake proxy tester """ def __init__(self, host, port, jid, sid, sender_jid, on_success, on_failure): """ Try to establish and auth to proxy at (host, port) Call on_success, or on_failure according to the result. """ self.host = host self.port = port self.jid = jid self.on_success = on_success self.on_failure = on_failure self._sock = None self.file_props = FilesProp.getNewFileProp(jid, sid) self.file_props.is_a_proxy = True self.file_props.proxy_sender = sender_jid self.file_props.proxy_receiver = 'test@gajim.org/test2' Socks5.__init__(self, app.idlequeue, host, port, None, None, None) self.sid = sid def connect(self): """ Create the socket and plug it to the idlequeue """ if self.host is None: self.on_failure() return None self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.setblocking(False) self.fd = self._sock.fileno() self.state = 0 # about to be connected app.idlequeue.plug_idle(self, True, False) self.do_connect() self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) return None def read_timeout(self): self.idlequeue.remove_timeout(self.fd) self.pollend() def pollend(self): self.disconnect() self.on_failure() def pollout(self): self.idlequeue.remove_timeout(self.fd) if self.state == 0: self.do_connect() return if self.state == 1: # send initially: version and auth types data = self._get_auth_buff() self.send_raw(data) else: return self.state += 1 # unplug and plug for reading app.idlequeue.plug_idle(self, False, True) app.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) def pollin(self): self.idlequeue.remove_timeout(self.fd) if self.state in (2, 3): self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) # begin negotiation. on success 'address' != 0 buff = self.receive() if buff == b'': # end connection self.pollend() return if self.state == 2: # read auth response if buff is None or len(buff) != 2: return None version, method = struct.unpack('!BB', buff[:2]) if version != 0x05 or method == 0xff: self.pollend() return log.debug('Receiver authenticating to %s:%s', self.host, self.port) data = self._get_request_buff(self._get_sha1_auth()) self.send_raw(data) self.state += 1 elif self.state == 3: # read connect response if buff is None or len(buff) < 2: return None version, reply = struct.unpack('!BB', buff[:2]) if version != 0x05 or reply != 0x00: self.pollend() return log.debug('Receiver authenticated to %s:%s', self.host, self.port) self.on_success() self.disconnect() self.state += 1 else: assert False, 'unexpected state: %d' % self.state def do_connect(self): try: self._sock.setblocking(False) self._sock.connect((self.host, self.port)) log.debug('Receiver Connecting to %s:%s', self.host, self.port) self._send = self._sock.send self._recv = self._sock.recv except Exception as ee: errnum = ee.errno # 56 is for freebsd if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK): # still trying to connect return # win32 needs this if errnum not in (0, 10056, errno.EISCONN): # connection failed self.on_failure() return # socket is already connected self._sock.setblocking(False) self._send = self._sock.send self._recv = self._sock.recv self.buff = '' self.state = 1 # connected log.debug('Receiver connected to %s:%s', self.host, self.port) self.idlequeue.plug_idle(self, True, False) gajim-gajim-1.1.3/gajim/common/resolver.py000066400000000000000000000124021345766322700205000ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging import functools from gi.repository import Gio, GLib log = logging.getLogger('gajim.c.resolver') def get_resolver(): return GioResolver() class CommonResolver(): def __init__(self): # dict {"host+type" : list of records} self.resolved_hosts = {} # dict {"host+type" : list of callbacks} self.handlers = {} def resolve(self, host, on_ready, type_='srv'): host = host.lower() log.debug('resolve %s type=%s', host, type_) assert(type_ in ['srv', 'txt']) if not host: # empty host, return empty list of srv records on_ready([]) return if host + type_ in self.resolved_hosts: # host is already resolved, return cached values log.debug('%s already resolved: %s', host, self.resolved_hosts[host + type_]) on_ready(host, self.resolved_hosts[host + type_]) return if host + type_ in self.handlers: # host is about to be resolved by another connection, # attach our callback log.debug('already resolving %s', host) self.handlers[host + type_].append(on_ready) else: # host has never been resolved, start now log.debug('Starting to resolve %s using %s', host, self) self.handlers[host + type_] = [on_ready] self.start_resolve(host, type_) def _on_ready(self, host, type_, result_list): # practically it is impossible to be the opposite, but who knows :) host = host.lower() log.debug('Resolving result for %s: %s', host, result_list) if host + type_ not in self.resolved_hosts: self.resolved_hosts[host + type_] = result_list if host + type_ in self.handlers: for callback in self.handlers[host + type_]: callback(host, result_list) del self.handlers[host + type_] def start_resolve(self, host, type_): pass class GioResolver(CommonResolver): """ Asynchronous resolver using GIO. process() method has to be called in order to proceed the pending requests. """ def __init__(self): super().__init__() self.gio_resolver = Gio.Resolver.get_default() def start_resolve(self, host, type_): if type_ == 'txt': callback = functools.partial(self._on_ready_txt, host) type_ = Gio.ResolverRecordType.TXT else: callback = functools.partial(self._on_ready_srv, host) type_ = Gio.ResolverRecordType.SRV self.gio_resolver.lookup_records_async(host, type_, None, callback) def _on_ready_srv(self, host, source_object, result): try: variant_results = source_object.lookup_records_finish(result) except GLib.Error as e: if e.domain == 'g-resolver-error-quark': result_list = [] log.info("Could not resolve host: %s", e.message) else: raise else: result_list = [ { 'weight': weight, 'prio': prio, 'port': port, 'host': host, } for prio, weight, port, host in variant_results ] super()._on_ready(host, 'srv', result_list) def _on_ready_txt(self, host, source_object, result): try: variant_results = source_object.lookup_records_finish(result) except GLib.Error as e: if e.domain == 'g-resolver-error-quark': result_list = [] log.warning("Could not resolve host: %s", e.message) else: raise else: result_list = [res[0][0] for res in variant_results] super()._on_ready(host, 'txt', result_list) # below lines is on how to use API and assist in testing if __name__ == '__main__': from gi.repository import Gtk resolver = get_resolver() def clicked(widget): global resolver host = text_view.get_text() def on_result(host, result_array): print('Result:\n' + repr(result_array)) resolver.resolve(host, on_result) win = Gtk.Window() win.set_border_width(6) win.connect('remove', Gtk.main_quit) text_view = Gtk.Entry() text_view.set_text('_xmpp-client._tcp.jabber.org') hbox = Gtk.HBox() hbox.set_spacing(3) but = Gtk.Button(' Lookup SRV ') hbox.pack_start(text_view, 5, True, 0) hbox.pack_start(but, 0, True, 0) but.connect('clicked', clicked) win.add(hbox) win.show_all() Gtk.main() gajim-gajim-1.1.3/gajim/common/rst_xhtml_generator.py000066400000000000000000000146531345766322700227430ustar00rootroot00000000000000# Copyright (C) 2006 Santiago Gala # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Jean-Marie Traissard # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . try: from docutils import io # type: ignore from docutils.core import Publisher from docutils.parsers.rst import roles from docutils import nodes, utils # type: ignore from docutils.parsers.rst.roles import set_classes # type: ignore except ImportError: print("Requires docutils 0.4 for set_classes to be available") def create_xhtml(text): return None else: def pos_int_validator(text): """ Validates that text can be evaluated as a positive integer """ result = int(text) if result < 0: raise ValueError("Error: value '%(text)s' " "must be a positive integer") return result def generate_uri_role(role_name, aliases, anchor_text, base_url, interpret_url, validator): """ Create and register a uri based "interpreted role" Those are similar to the RFC, and PEP ones, and take role_name: name that will be registered aliases: list of alternate names anchor_text: text that will be used, together with the role base_url: base url for the link interpret_url: this, modulo the validated text, will be added to it validator: should return the validated text, or raise ValueError """ def uri_reference_role(role, rawtext, text, lineno, inliner, options=None, content=None): if options is None: options = {} try: valid_text = validator(text) except ValueError as e: msg = inliner.reporter.error(e.message % dict(text=text), line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] ref = base_url + interpret_url % valid_text set_classes(options) node = nodes.reference(rawtext, anchor_text + utils.unescape(text), refuri=ref, **options) return [node], [] uri_reference_role.__doc__ = """Role to make handy references to URIs. Use as :%(role_name)s:`71` (or any of %(aliases)s). It will use %(base_url)s+%(interpret_url)s validator should throw a ValueError, containing optionally a %%(text)s format, if the interpreted text is not valid. """ % locals() roles.register_canonical_role(role_name, uri_reference_role) from docutils.parsers.rst.languages import en en.roles[role_name] = role_name for alias in aliases: en.roles[alias] = role_name generate_uri_role('xep-reference', ('jep', 'xep'), 'XEP #', 'http://www.xmpp.org/extensions/', 'xep-%04d.html', pos_int_validator) generate_uri_role('gajim-ticket-reference', ('ticket', 'gtrack'), 'Gajim Ticket #', 'https://dev.gajim.org/gajim/gajim/issues/', '%d', pos_int_validator) class HTMLGenerator: """ Really simple HTMLGenerator starting from publish_parts It reuses the docutils.core.Publisher class, which means it is *not* threadsafe. """ def __init__(self, settings_spec=None, settings_overrides=None, config_section='general'): if settings_overrides is None: settings_overrides = {'report_level': 5, 'halt_level': 5} self.pub = Publisher(reader=None, parser=None, writer=None, settings=None, source_class=io.StringInput, destination_class=io.StringOutput) self.pub.set_components(reader_name='standalone', parser_name='restructuredtext', writer_name='html') # hack: JEP-0071 does not allow HTML char entities, so we hack our way # out of it. # — == u"\u2014" # a setting to only emit charater entities in the writer would be nice # FIXME: several   are emitted, and they are explicitly forbidden # in the JEP #   == u"\u00a0" self.pub.writer.translator_class.attribution_formats['dash'] = ( '\u2014', '') self.pub.process_programmatic_settings(settings_spec, settings_overrides, config_section) def create_xhtml(self, text, destination=None, destination_path=None, enable_exit_status=None): """ Create xhtml for a fragment of IM dialog. We can use the source_name to store info about the message """ self.pub.set_source(text, None) self.pub.set_destination(destination, destination_path) self.pub.publish(enable_exit_status=enable_exit_status) # kludge until we can get docutils to stop generating (rare)   # entities return '\u00a0'.join(self.pub.writer.parts['fragment'].strip().split( ' ')) Generator = HTMLGenerator() def create_xhtml(text): return Generator.create_xhtml(text) if __name__ == '__main__': print("test 1\n" + Generator.create_xhtml(""" test:: >>> print(1) 1 *I* like it. It is for :JEP:`71` this `` should trigger`` should trigger the   problem. """)) print("test 2\n" + Generator.create_xhtml(""" *test1 test2_ """)) print("test 3\n" + Generator.create_xhtml(""":ticket:`316` implements :xep:`71`""")) gajim-gajim-1.1.3/gajim/common/socks5.py000066400000000000000000001575141345766322700200640ustar00rootroot00000000000000# Copyright (C) 2005-2006 Dimitur Kirov # Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import socket import struct import hashlib import os import time import sys import logging from errno import EWOULDBLOCK from errno import ENOBUFS from errno import EINTR from errno import EISCONN from errno import EINPROGRESS from errno import EAFNOSUPPORT from nbxmpp.idlequeue import IdleObject import OpenSSL from gajim.common.file_props import FilesProp from gajim.common import app from gajim.common import jingle_xtls log = logging.getLogger('gajim.c.socks5') MAX_BUFF_LEN = 65536 # after foo seconds without activity label transfer as 'stalled' STALLED_TIMEOUT = 10 # after foo seconds of waiting to connect, disconnect from # streamhost and try next one CONNECT_TIMEOUT = 30 # nothing received for the last foo seconds - stop transfer # if it is 0, then transfer will wait forever READ_TIMEOUT = 180 # nothing sent for the last foo seconds - stop transfer # if it is 0, then transfer will wait forever SEND_TIMEOUT = 180 class SocksQueue: """ Queue for all file requests objects """ def __init__(self, idlequeue, complete_transfer_cb=None, progress_transfer_cb=None, error_cb=None): self.connected = 0 self.readers = {} self.senders = {} self.idx = 1 self.listener = None self.sha_handlers = {} # handle all io events in the global idle queue, instead of processing # each foo seconds self.idlequeue = idlequeue self.complete_transfer_cb = complete_transfer_cb self.progress_transfer_cb = progress_transfer_cb self.error_cb = error_cb self.on_success = {} # {id: cb} self.on_failure = {} # {id: cb} def start_listener(self, port, sha_str, sha_handler, file_props, fingerprint=None, typ='sender'): """ Start waiting for incoming connections on (host, port) and do a socks5 authentication using sid for generated SHA """ log.debug('Start listening for socks5 connection') sid = file_props.sid self.sha_handlers[sha_str] = (sha_handler, sid) if self.listener is None or self.listener.connections == []: self.listener = Socks5Listener(self.idlequeue, port, file_props, fingerprint=fingerprint) self.listener.queue = self self.listener.bind() else: # There is already a listener, we update the file's information # on the new connection. self.listener.file_props = file_props self.connected += 1 return self.listener def send_success_reply(self, file_props, streamhost): if file_props.streamhost_used is True: for proxy in file_props.proxyhosts: if proxy['host'] == streamhost['host']: self.on_success[file_props.transport_sid](proxy) return 1 return 0 for host in file_props.streamhosts: if host['state'] == 1: # on_success callback already called for another host return 0 # return 0 to disconnect this one streamhost['state'] = 1 self.on_success[file_props.transport_sid](streamhost) return 1 def connect_to_hosts(self, account, transport_sid, on_success=None, on_failure=None, fingerprint=None, receiving=True): self.on_success[transport_sid] = on_success self.on_failure[transport_sid] = on_failure file_props = FilesProp.getFilePropByTransportSid(account, transport_sid) file_props.failure_cb = on_failure streamhosts_to_test = [] # Remove local IPs to not connect to ourself for streamhost in file_props.streamhosts: if streamhost['host'] == '127.0.0.1' or streamhost['host'] == '::1': continue streamhosts_to_test.append(streamhost) if not streamhosts_to_test: on_failure(file_props.transport_sid) # add streamhosts to the queue for streamhost in streamhosts_to_test: if 'type' in streamhost and streamhost['type'] == 'proxy': fp = None else: fp = fingerprint if receiving: if 'candidate_id' in streamhost: log.debug('Trying to connect as receiver to cid %s', streamhost['candidate_id']) else: log.debug('Trying to connect as receiver to jid %s', streamhost['jid']) file_props.type_ = 'r' socks5obj = Socks5ReceiverClient(self.idlequeue, streamhost, transport_sid, file_props, fingerprint=fp) self.add_sockobj(account, socks5obj) else: if 'candidate_id' in streamhost: log.debug('Trying to connect as sender to cid %s', streamhost['candidate_id']) else: log.debug('Trying to connect as sender to jid %s', streamhost['jid']) if file_props.sha_str: idx = file_props.sha_str else: idx = self.idx self.idx = self.idx + 1 file_props.type_ = 's' if 'type' in streamhost and streamhost['type'] == 'proxy': file_props.is_a_proxy = True file_props.proxy_sender = streamhost['target'] file_props.proxy_receiver = streamhost['initiator'] socks5obj = Socks5SenderClient(self.idlequeue, idx, self, _sock=None, host=str(streamhost['host']), port=int(streamhost['port']), fingerprint=fp, connected=False, file_props=file_props, initiator=streamhost['initiator'], target=streamhost['target']) socks5obj.streamhost = streamhost self.add_sockobj(account, socks5obj) streamhost['idx'] = socks5obj.queue_idx def _socket_connected(self, streamhost, file_props): """ Called when there is a host connected to one of the senders's streamhosts. Stop other attempts for connections """ if 'candidate_id' in streamhost: log.debug('Connected to cid %s', streamhost['candidate_id']) else: log.debug('Connected to jid %s', streamhost['jid']) for host in file_props.streamhosts: if host != streamhost and 'idx' in host: if host['state'] == 1: # remove current if file_props.type_ == 's': self.remove_sender(streamhost['idx'], False) else: self.remove_receiver(streamhost['idx']) return # set state -2, meaning that this streamhost is stopped, # but it may be connected later if host['state'] >= 0: if file_props.type_ == 's': self.remove_sender(host['idx'], False) else: self.remove_receiver(host['idx']) host['idx'] = -1 host['state'] = -2 def reconnect_client(self, client, streamhost): """ Check the state of all streamhosts and if all has failed, then emit connection failure cb. If there are some which are still not connected try to establish connection to one of them """ self.idlequeue.remove_timeout(client.fd) self.idlequeue.unplug_idle(client.fd) file_props = client.file_props streamhost['state'] = -1 # boolean, indicates that there are hosts, which are not tested yet unused_hosts = False for host in file_props.streamhosts: if 'idx' in host: if host['state'] >= 0: return if host['state'] == -2: unused_hosts = True if unused_hosts: for host in file_props.streamhosts: if host['state'] == -2: host['state'] = 0 # FIXME: make the sender reconnect also client = Socks5ReceiverClient(self.idlequeue, host, client.sid, file_props) self.add_sockobj(client.account, client) host['idx'] = client.queue_idx # we still have chances to connect return if file_props.received_len == 0: # there are no other streamhosts and transfer hasn't started self._connection_refused(streamhost, file_props, client.queue_idx) else: # transfer stopped, it is most likely stopped from sender client.disconnect() file_props.error = -1 self.process_result(-1, client) def _connection_refused(self, streamhost, file_props, idx): """ Called when we loose connection during transfer """ if 'candidate_id' in streamhost: log.debug('Connection refused to cid %s', streamhost['candidate_id']) else: log.debug('Connection refused to jid %s', streamhost['jid']) if file_props is None: return streamhost['state'] = -1 # FIXME: should only the receiver be remove? what if we are sending? self.remove_receiver(idx, False) for host in file_props.streamhosts: if host['state'] != -1: return self.readers = {} # failure_cb exists - this means that it has never been called if file_props.failure_cb: file_props.failure_cb(file_props.transport_sid) file_props.failure_cb = None def add_sockobj(self, account, sockobj): """ Add new file a sockobj type receiver or sender, and use it to connect to server """ if sockobj.file_props.type_ == 'r': self._add(sockobj, self.readers, sockobj.file_props, self.idx) else: self._add(sockobj, self.senders, sockobj.file_props, self.idx) sockobj.queue_idx = self.idx sockobj.queue = self sockobj.account = account self.idx += 1 result = sockobj.connect() self.connected += 1 if result is not None: result = sockobj.main() self.process_result(result, sockobj) return 1 return None def _add(self, sockobj, sockobjects, file_props, hash_): ''' Adds the sockobj to the current list of sockobjects ''' keys = (file_props.transport_sid, file_props.name, hash_) sockobjects[keys] = sockobj def result_sha(self, sha_str, idx): if sha_str in self.sha_handlers: props = self.sha_handlers[sha_str] props[0](props[1], idx) def activate_proxy(self, idx): if not self.isHashInSockObjs(self.senders, idx): return for key in list(self.senders): if idx in key: sender = self.senders[key] if sender.file_props.type_ != 's': return sender.state = 6 if sender.connected: sender.file_props.error = 0 sender.file_props.disconnect_cb = sender.disconnect sender.file_props.started = True sender.file_props.completed = False sender.file_props.paused = False sender.file_props.stalled = False sender.file_props.elapsed_time = 0 sender.file_props.last_time = time.time() sender.file_props.received_len = 0 sender.pauses = 0 # start sending file to proxy self.idlequeue.set_read_timeout(sender.fd, STALLED_TIMEOUT) self.idlequeue.plug_idle(sender, True, False) result = sender.write_next() self.process_result(result, sender) def send_file(self, file_props, account, mode): for key in list(self.senders.keys()): if file_props.name in key and file_props.transport_sid in key \ and self.senders[key].mode == mode: log.info('socks5: sending file') sender = self.senders[key] file_props.streamhost_used = True sender.account = account sender.file_props = file_props result = sender.send_file() self.process_result(result, sender) def isHashInSockObjs(self, sockobjs, hash_): ''' It tells wether there is a particular hash in sockobjs or not ''' for key in sockobjs: if hash_ in key: return True return False def on_connection_accepted(self, sock, listener): sock_hash = sock.__hash__() if listener.file_props.type_ == 's' and \ not self.isHashInSockObjs(self.senders, sock_hash): sockobj = Socks5SenderServer(self.idlequeue, sock_hash, self, sock[0], sock[1][0], sock[1][1], fingerprint=None, file_props=listener.file_props) self._add(sockobj, self.senders, listener.file_props, sock_hash) # Start waiting for data self.idlequeue.plug_idle(sockobj, False, True) self.connected += 1 if listener.file_props.type_ == 'r' and \ not self.isHashInSockObjs(self.readers, sock_hash): sh = {} sh['host'] = sock[1][0] sh['port'] = sock[1][1] sh['initiator'] = None sh['target'] = None sockobj = Socks5ReceiverServer(idlequeue=self.idlequeue, streamhost=sh, transport_sid=None, file_props=listener.file_props, fingerprint=None) self._add(sockobj, self.readers, listener.file_props, sock_hash) sockobj.set_sock(sock[0]) sockobj.queue = self self.connected += 1 def process_result(self, result, actor): """ Take appropriate actions upon the result: [ 0, - 1 ] complete/end transfer [ > 0 ] send progress message [ None ] do nothing """ if result is None: return if result in (0, -1) and self.complete_transfer_cb is not None: account = actor.account if account is None and actor.file_props.tt_account: account = actor.file_props.tt_account self.complete_transfer_cb(account, actor.file_props) elif self.progress_transfer_cb is not None: self.progress_transfer_cb(actor.account, actor.file_props) def remove_receiver_by_key(self, key, do_disconnect=True): reader = self.readers[key] self.idlequeue.unplug_idle(reader.fd) self.idlequeue.remove_timeout(reader.fd) if do_disconnect: reader.disconnect() else: if reader.streamhost is not None: reader.streamhost['state'] = -1 del self.readers[key] def remove_sender_by_key(self, key, do_disconnect=True): sender = self.senders[key] if do_disconnect: sender.disconnect() self.idlequeue.unplug_idle(sender.fd) self.idlequeue.remove_timeout(sender.fd) del self.senders[key] if self.connected > 0: self.connected -= 1 def remove_receiver(self, idx, do_disconnect=True, remove_all=False): """ Remove receiver from the list and decrease the number of active connections with 1 """ if idx != -1: for key in list(self.readers.keys()): if idx in key: self.remove_receiver_by_key( key, do_disconnect=do_disconnect) if not remove_all: break def remove_sender(self, idx, do_disconnect=True, remove_all=False): """ Remove sender from the list of senders and decrease the number of active connections with 1 """ if idx != -1: for key in list(self.senders.keys()): if idx in key: self.remove_sender_by_key(key, do_disconnect=do_disconnect) if not remove_all: break if not self.senders and self.listener is not None: self.listener.disconnect() self.listener = None self.connected -= 1 def remove_by_mode(self, transport_sid, mode, do_disconnect=True): for (key, sock) in self.senders.copy().items(): if key[0] == transport_sid and sock.mode == mode: self.remove_sender_by_key(key) for (key, sock) in self.readers.copy().items(): if key[0] == transport_sid and sock.mode == mode: self.remove_receiver_by_key(key) def remove_server(self, transport_sid, do_disconnect=True): self.remove_by_mode(transport_sid, 'server') def remove_client(self, transport_sid, do_disconnect=True): self.remove_by_mode(transport_sid, 'client') def remove_other_servers(self, host_to_keep): for (key, sock) in self.senders.copy().items(): if sock.host != host_to_keep and sock.mode == 'server': self.remove_sender_by_key(key) class Socks5: def __init__(self, idlequeue, host, port, initiator, target, sid): if host is not None: try: self.host = host self.ais = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM) except socket.gaierror: self.ais = None self.idlequeue = idlequeue self.fd = -1 self.port = port self.initiator = initiator self.target = target self.sid = sid self._sock = None self.account = None self.state = 0 # not connected self.pauses = 0 self.size = 0 self.remaining_buff = b'' self.file = None self.connected = False self.mode = '' self.ssl_cert = None self.ssl_errnum = 0 def _is_connected(self): if self.state < 5: return False return True def ssl_verify_cb(self, ssl_conn, cert, error_num, depth, return_code): if depth == 0: self.ssl_cert = cert self.ssl_errnum = error_num return True def connect(self): """ Create the socket and plug it to the idlequeue """ if self.ais is None: return None for ai in self.ais: try: self._sock = socket.socket(*ai[:3]) if self.fingerprint is not None: if self.file_props.type_ == 's': remote_jid = app.get_jid_without_resource( self.file_props.receiver) else: remote_jid = app.get_jid_without_resource( self.file_props.sender) self._sock = OpenSSL.SSL.Connection( jingle_xtls.get_context('client', verify_cb=self.ssl_verify_cb, remote_jid=remote_jid), self._sock) # this will not block the GUI self._sock.setblocking(False) self._server = ai[4] break except socket.error as e: if e.errno == EINPROGRESS: break # for all other errors, we try other addresses continue self.fd = self._sock.fileno() self.state = 0 # about to be connected self.idlequeue.plug_idle(self, True, False) self.do_connect() self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) return None def do_connect(self): try: self._sock.connect(self._server) self._send = self._sock.send self._recv = self._sock.recv except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError): pass except Exception as ee: errnum = ee.errno self.connect_timeout += 1 if errnum == 111 or self.connect_timeout > 1000: self.queue._connection_refused(self.streamhost, self.file_props, self.queue_idx) self.connected = False return None # win32 needs this if errnum not in (10056, EISCONN) or self.state != 0: return None # socket is already connected self._sock.setblocking(False) self._send = self._sock.send self._recv = self._sock.recv self.buff = '' self.connected = True self.file_props.connected = True self.file_props.disconnect_cb = self.disconnect self.file_props.paused = False self.state = 1 # connected # stop all others connections to sender's streamhosts self.queue._socket_connected(self.streamhost, self.file_props) self.idlequeue.plug_idle(self, True, False) return 1 # we are connected def read_timeout(self): self.idlequeue.remove_timeout(self.fd) if self.state > 5: # no activity for foo seconds if self.file_props.stalled is False: self.file_props.stalled = True self.queue.process_result(-1, self) if not self.file_props.received_len: self.file_props.received_len = 0 if SEND_TIMEOUT > 0: self.idlequeue.set_read_timeout(self.fd, SEND_TIMEOUT) else: # stop transfer, there is no error code for this self.pollend() else: if self.mode == 'client': self.queue.reconnect_client(self, self.streamhost) def open_file_for_reading(self): if self.file is None: try: self.file = open(self.file_props.file_name, 'rb') if self.file_props.offset: self.size = self.file_props.offset self.file.seek(self.size) self.file_props.received_len = self.size except IOError as e: self.close_file() raise IOError(str(e)) def close_file(self): # Close file we're sending from if self.file: if not self.file.closed: try: self.file.close() except Exception: pass self.file = None # Close file we're receiving into if self.file_props.fd and self.state >= 7: try: self.file_props.fd.close() except Exception: pass def get_fd(self): """ Test if file is already open and return its fd, or just open the file and return the fd """ if self.file_props.fd: fd = self.file_props.fd else: offset = 0 opt = 'wb' if self.file_props.offset: offset = self.file_props.offset opt = 'ab' fd = open(self.file_props.file_name, opt) self.file_props.fd = fd self.file_props.elapsed_time = 0 self.file_props.last_time = time.time() self.file_props.received_len = offset return fd def rem_fd(self, fd): if self.file_props.fd: self.file_props.fd = None try: fd.close() except Exception: pass def receive(self): """ Read small chunks of data. Call owner's disconnected() method if appropriate """ received = b'' try: add = self._recv(64) except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError) as e: log.info('SSL rehandshake request: %s', repr(e)) raise e except Exception: add = b'' received += add if not add: self.disconnect() return add def send_raw(self, raw_data): """ Write raw outgoing data """ try: self._send(raw_data) except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError) as e: log.info('SSL rehandshake request: %s', repr(e)) raise e except Exception: self.disconnect() return len(raw_data) def write_next(self): if self.remaining_buff != b'': buff = self.remaining_buff else: try: self.open_file_for_reading() except IOError: self.state = 8 # end connection self.disconnect() self.file_props.error = -7 # unable to read from file return -1 buff = self.file.read(MAX_BUFF_LEN) if buff: lenn = 0 try: lenn = self._send(buff) except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError) as e: log.info('SSL rehandshake request: %s', repr(e)) raise e except OpenSSL.SSL.SysCallError: return self._on_send_exception() except Exception as e: if e.errno not in (EINTR, ENOBUFS, EWOULDBLOCK): return self._on_send_exception() self.size += lenn current_time = time.time() self.file_props.elapsed_time += current_time - \ self.file_props.last_time self.file_props.last_time = current_time self.file_props.received_len = self.size if self.size >= self.file_props.size: self.state = 8 # end connection self.file_props.error = 0 self.disconnect() return -1 if lenn != len(buff): self.remaining_buff = buff[lenn:] else: self.remaining_buff = b'' self.state = 7 # continue to write in the socket if lenn == 0: return None self.file_props.stalled = False return lenn else: self.state = 8 # end connection self.disconnect() return -1 def _on_send_exception(self): # peer stopped reading self.state = 8 # end connection self.disconnect() self.file_props.error = -1 return -1 def get_file_contents(self, timeout): """ Read file contents from socket and write them to file """ if self.file_props is None or not self.file_props.file_name: self.file_props.error = -2 return None fd = None if self.remaining_buff != b'': try: fd = self.get_fd() except IOError: self.disconnect() self.file_props.error = -6 # file system error return 0 fd.write(self.remaining_buff) lenn = len(self.remaining_buff) current_time = time.time() self.file_props.elapsed_time += current_time - \ self.file_props.last_time self.file_props.last_time = current_time self.file_props.received_len += lenn self.remaining_buff = b'' if self.file_props.received_len == self.file_props.size: self.rem_fd(fd) self.disconnect() self.file_props.error = 0 self.file_props.completed = True return 0 else: try: fd = self.get_fd() except IOError: self.disconnect() self.file_props.error = -6 # file system error return 0 try: buff = self._recv(MAX_BUFF_LEN) except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError) as e: log.info('SSL rehandshake request: %s', repr(e)) raise e except Exception: buff = b'' current_time = time.time() self.file_props.elapsed_time += current_time - \ self.file_props.last_time self.file_props.last_time = current_time self.file_props.received_len += len(buff) if not buff: # Transfer stopped somehow: # reset, paused or network error self.rem_fd(fd) self.disconnect() self.file_props.error = -1 return 0 try: fd.write(buff) except IOError: self.rem_fd(fd) self.disconnect() self.file_props.error = -6 # file system error return 0 if self.file_props.received_len >= self.file_props.size: # transfer completed self.rem_fd(fd) self.disconnect() self.file_props.error = 0 self.file_props.completed = True return 0 # return number of read bytes. It can be used in progressbar if fd is not None: self.file_props.stalled = False if fd is None and self.file_props.stalled is False: return None if self.file_props.received_len: if self.file_props.received_len != 0: return self.file_props.received_len return None def disconnect(self, *args, **kwargs): """ Close open descriptors and remover socket descr. from idleque """ # be sure that we don't leave open file self.close_file() self.idlequeue.remove_timeout(self.fd) self.idlequeue.unplug_idle(self.fd) if self.mode == 'server' and self.queue.listener: try: self.queue.listener.connections.remove(self._sock) except ValueError: pass # Not in list if self.queue.listener.connections == []: self.queue.listener.disconnect() try: if isinstance(self._sock, OpenSSL.SSL.Connection): self._sock.shutdown() else: self._sock.shutdown(socket.SHUT_RDWR) self._sock.close() except Exception: # socket is already closed pass self.connected = False self.fd = -1 self.state = -1 def _get_auth_buff(self): """ Message, that we support 1 one auth mechanism: the 'no auth' mechanism """ return struct.pack('!BBB', 0x05, 0x01, 0x00) def _parse_auth_buff(self, buff): """ Parse the initial message and create a list of auth mechanisms """ if buff[0] != 5: return None num_auth = buff[1] return list(buff[2:2+num_auth]) def _get_auth_response(self): """ Socks version(5), number of extra auth methods (we send 0x00 - no auth) """ return struct.pack('!BB', 0x05, 0x00) def _get_connect_buff(self): """ Connect request by domain name """ buff = struct.pack('!BBBBB%dsBB' % len(self.host), 0x05, 0x01, 0x00, 0x03, len(self.host), self.host.encode('utf-8'), self.port >> 8, self.port & 0xff) return buff def _get_request_buff(self, msg, command=0x01): """ Connect request by domain name, sid sha, instead of domain name (jep 0096) """ if isinstance(msg, str): msg = msg.encode('utf-8') buff = struct.pack('!BBBBB%dsBB' % len(msg), 0x05, command, 0x00, 0x03, len(msg), msg, 0, 0) return buff def _parse_request_buff(self, buff): try: # don't trust on what comes from the outside req_type, host_type, = struct.unpack('!xBxB', buff[:4]) if host_type == 0x01: host_arr = struct.unpack('!iiii', buff[4:8]) host, = '.'.join(str(s) for s in host_arr) host_len = len(host) elif host_type == 0x03: host_len = buff[4] host, = struct.unpack('!%ds' % host_len, buff[5:5 + host_len]) portlen = len(buff[host_len + 5:]) if portlen == 1: port, = struct.unpack('!B', buff[host_len + 5]) elif portlen == 2: port, = struct.unpack('!H', buff[host_len + 5:]) # file data, comes with auth message (Gaim bug) else: port, = struct.unpack('!H', buff[host_len + 5: host_len + 7]) self.remaining_buff = buff[host_len + 7:] except Exception: return (None, None, None) return (req_type, host, port) def read_connect(self): """ Connect response: version, auth method """ try: buff = self._recv().decode('utf-8') except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError) as e: log.info("SSL rehandshake request: %s", repr(e)) raise e try: version, method = struct.unpack('!BB', buff) except Exception: version, method = None, None if version != 0x05 or method == 0xff: self.disconnect() def continue_paused_transfer(self): if self.state < 5: return if self.file_props.type_ == 'r': self.idlequeue.plug_idle(self, False, True) else: self.idlequeue.plug_idle(self, True, False) def _get_sha1_auth(self): """ Get sha of sid + Initiator jid + Target jid """ if self.file_props.is_a_proxy: return hashlib.sha1(('%s%s%s' % (self.sid, self.file_props.proxy_sender, self.file_props.proxy_receiver)).\ encode('utf-8')).hexdigest() return hashlib.sha1(('%s%s%s' % (self.sid, self.initiator, self.target)).encode('utf-8')).hexdigest() class Socks5Sender(IdleObject): """ Class for sending file to socket over socks5 """ def __init__(self, idlequeue, sock_hash, parent, _sock, host=None, port=None, fingerprint=None, connected=True, file_props=None): self.fingerprint = fingerprint self.queue_idx = sock_hash self.queue = parent self.file_props = file_props self.proxy = False self._sock = _sock if _sock is not None: if self.fingerprint is not None and not isinstance(self._sock, OpenSSL.SSL.Connection): self._sock = OpenSSL.SSL.Connection( jingle_xtls.get_context('server'), _sock) else: self._sock.setblocking(False) self.fd = _sock.fileno() self._recv = _sock.recv self._send = _sock.send self.connected = connected self.state = 1 # waiting for first bytes self.connect_timeout = 0 self.file_props.error = 0 self.file_props.disconnect_cb = self.disconnect self.file_props.started = True self.file_props.completed = False self.file_props.paused = False self.file_props.continue_cb = self.continue_paused_transfer self.file_props.stalled = False self.file_props.connected = True self.file_props.elapsed_time = 0 self.file_props.last_time = time.time() self.file_props.received_len = 0 def start_transfer(self): """ Send the file """ return self.write_next() def set_connection_sock(self, _sock): self._sock = _sock if self.fingerprint is not None: self._sock = OpenSSL.SSL.Connection( jingle_xtls.get_context('client'), _sock) else: self._sock.setblocking(False) self.fd = _sock.fileno() self._recv = _sock.recv self._send = _sock.send self.connected = True self.state = 1 # waiting for first bytes self.file_props = None # start waiting for data self.idlequeue.plug_idle(self, False, True) def send_file(self): """ Start sending the file over verified connection """ self.pauses = 0 self.state = 7 # plug for writing self.idlequeue.plug_idle(self, True, False) return self.write_next() # initial for nl byte def disconnect(self, cb=True): """ Close the socket """ # close connection and remove us from the queue Socks5.disconnect(self) if self.file_props is not None: self.file_props.connected = False self.file_props.disconnect_cb = None if self.queue is not None: self.queue.remove_sender(self.queue_idx, False) class Socks5Receiver(IdleObject): def __init__(self, idlequeue, streamhost, sid, file_props=None, fingerprint=None): """ fingerprint: fingerprint of certificates we shall use, set to None if TLS connection not desired """ self.queue_idx = -1 self.streamhost = streamhost self.queue = None self.fingerprint = fingerprint self.connect_timeout = 0 self.connected = False self.pauses = 0 self.sid = sid self.file_props = file_props self.file_props.disconnect_cb = self.disconnect self.file_props.error = 0 self.file_props.started = True self.file_props.completed = False self.file_props.paused = False self.file_props.continue_cb = self.continue_paused_transfer self.file_props.stalled = False self.file_props.received_len = 0 def receive_file(self): """ Start receiving the file over verified connection """ if self.file_props.started: return self.file_props.error = 0 self.file_props.disconnect_cb = self.disconnect self.file_props.started = True self.file_props.completed = False self.file_props.paused = False self.file_props.continue_cb = self.continue_paused_transfer self.file_props.stalled = False self.file_props.connected = True self.file_props.elapsed_time = 0 self.file_props.last_time = time.time() self.file_props.received_len = 0 self.pauses = 0 self.state = 7 # plug for reading self.idlequeue.plug_idle(self, False, True) return self.get_file_contents(0) # initial for nl byte def start_transfer(self): """ Receive the file """ return self.get_file_contents(0) def set_sock(self, _sock): self._sock = _sock self._sock.setblocking(False) self.fd = _sock.fileno() self._recv = _sock.recv self._send = _sock.send self.connected = True self.state = 1 # waiting for first bytes # start waiting for data self.idlequeue.plug_idle(self, False, True) def disconnect(self, cb=True): """ Close the socket. Remove self from queue if cb is True """ # close connection Socks5.disconnect(self) if cb is True: self.file_props.disconnect_cb = None if self.queue is not None: self.queue.remove_receiver(self.queue_idx, False) class Socks5Server(Socks5): def __init__(self, idlequeue, host, port, initiator, target, sid): Socks5.__init__(self, idlequeue, host, port, initiator, target, sid) self.mode = 'server' def main(self): """ Initial requests for verifying the connection """ if self.state == 1: # initial read buff = self.receive() if not self.connected: return -1 mechs = self._parse_auth_buff(buff) if mechs is None: return -1 # invalid auth methods received elif self.state == 3: # get next request buff = self.receive() req_type, self.sha_msg = self._parse_request_buff(buff)[:2] if req_type != 0x01: return -1 # request is not of type 'connect' self.state += 1 # go to the next step # unplug & plug for writing self.idlequeue.plug_idle(self, True, False) return None def pollin(self): self.idlequeue.remove_timeout(self.fd) if self.connected: try: if self.state < 5: result = self.main() if self.state == 4: self.queue.result_sha(self.sha_msg, self.queue_idx) if result == -1: self.disconnect() elif self.state == 5: self.state = 7 if self.file_props.type_ == 's': # We wait for the end of the negotiation to # send the file self.idlequeue.plug_idle(self, False, False) else: # We plug for reading self.idlequeue.plug_idle(self, False, True) return elif self.state == 7: if self.file_props.paused: self.file_props.continue_cb = \ self.continue_paused_transfer self.idlequeue.plug_idle(self, False, False) return self.idlequeue.set_read_timeout(self.fd, STALLED_TIMEOUT) result = self.start_transfer() # send self.queue.process_result(result, self) except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError): log.info('caught SSL exception, ignored') else: self.disconnect() def pollend(self): self.state = 8 # end connection self.disconnect() self.file_props.error = -1 self.queue.process_result(-1, self) def pollout(self): if not self.connected: self.disconnect() return self.idlequeue.remove_timeout(self.fd) try: if self.state == 2: # send reply with desired auth type self.send_raw(self._get_auth_response()) elif self.state == 4: # send positive response to the 'connect' self.send_raw(self._get_request_buff(self.sha_msg, 0x00)) elif self.state == 7: if self.file_props.paused: self.file_props.continue_cb = self.continue_paused_transfer self.idlequeue.plug_idle(self, False, False) return result = self.start_transfer() # send self.queue.process_result(result, self) if result is None or result <= 0: self.disconnect() return self.idlequeue.set_read_timeout(self.fd, STALLED_TIMEOUT) elif self.state == 8: self.disconnect() return else: self.disconnect() except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError): log.info('caught SSL exception, ignored') return if self.state < 5: self.state += 1 # unplug and plug this time for reading self.idlequeue.plug_idle(self, False, True) class Socks5Client(Socks5): def __init__(self, idlequeue, host, port, initiator, target, sid): Socks5.__init__(self, idlequeue, host, port, initiator, target, sid) self.mode = 'client' def main(self, timeout=0): """ Begin negotiation. on success 'address' != 0 """ result = 1 buff = self.receive() if buff == b'': # end connection self.pollend() return if self.state == 2: # read auth response if buff is None or len(buff) != 2: return None version, method = struct.unpack('!BB', buff[:2]) if version != 0x05 or method == 0xff: self.disconnect() elif self.state == 4: # get approve of our request if buff is None: return None sub_buff = buff[:4] if len(sub_buff) < 4: return None version, address_type = struct.unpack('!BxxB', buff[:4]) addrlen = 0 if address_type == 0x03: addrlen = buff[4] # address = struct.unpack('!%ds' % addrlen, buff[5:addrlen + 5]) portlen = len(buff[addrlen + 5:]) # if portlen == 1: # port, = struct.unpack('!B', buff[addrlen + 5]) # elif portlen == 2: # port, = struct.unpack('!H', buff[addrlen + 5:]) # else: # Gaim bug :) # port, = struct.unpack('!H', buff[addrlen + 5:addrlen + 7]) if portlen not in (1, 2): self.remaining_buff = buff[addrlen + 7:] self.state = 5 # for senders: init file_props and send '\n' if self.queue.on_success: result = self.queue.send_success_reply(self.file_props, self.streamhost) if self.file_props.type_ == 's' and self.proxy: self.queue.process_result(self.send_file(), self) return if result == 0: self.state = 8 self.disconnect() # for senders: init file_props if result == 1 and self.state == 5: if self.file_props.type_ == 's': self.file_props.error = 0 self.file_props.disconnect_cb = self.disconnect self.file_props.started = True self.file_props.completed = False self.file_props.paused = False self.file_props.stalled = False self.file_props.elapsed_time = 0 self.file_props.last_time = time.time() self.file_props.received_len = 0 self.pauses = 0 # start sending file contents to socket #self.idlequeue.set_read_timeout(self.fd, STALLED_TIMEOUT) #self.idlequeue.plug_idle(self, True, False) self.idlequeue.plug_idle(self, False, False) else: # receiving file contents from socket self.idlequeue.plug_idle(self, False, True) self.file_props.continue_cb = self.continue_paused_transfer # we have set up the connection, next - retrieve file self.state = 6 if self.state < 5: self.idlequeue.plug_idle(self, True, False) self.state += 1 return None def send_file(self): if self.ssl_errnum > 0: log.error('remote certificate does not match the announced one.' '\nSSL Error: %d\nCancelling file transfer', self.ssl_errnum) self.file_props.error = -12 return -1 return super(Socks5Client, self).send_file() def pollin(self): self.idlequeue.remove_timeout(self.fd) if self.connected: try: if self.file_props.paused: self.idlequeue.plug_idle(self, False, False) return if self.state < 5: self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) result = self.main(0) self.queue.process_result(result, self) elif self.state == 5: # wait for proxy reply pass elif self.file_props.type_ == 'r': self.idlequeue.set_read_timeout(self.fd, STALLED_TIMEOUT) result = self.start_transfer() # receive self.queue.process_result(result, self) except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError): log.info('caught SSL exception, ignored') return else: self.disconnect() def pollout(self): self.idlequeue.remove_timeout(self.fd) try: if self.state == 0: self.do_connect() return if self.state == 1: # send initially: version and auth types self.send_raw(self._get_auth_buff()) elif self.state == 3: # send 'connect' request self.send_raw(self._get_request_buff(self._get_sha1_auth())) elif self.file_props.type_ != 'r': if self.file_props.paused: self.idlequeue.plug_idle(self, False, False) return result = self.start_transfer() # send self.queue.process_result(result, self) return except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError, OpenSSL.SSL.WantX509LookupError): log.info('caught SSL exception, ignored') return self.state += 1 # unplug and plug for reading self.idlequeue.plug_idle(self, False, True) self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) def pollend(self): if self.state >= 5: # error during transfer self.disconnect() self.file_props.error = -1 self.queue.process_result(-1, self) else: self.queue.reconnect_client(self, self.streamhost) class Socks5SenderClient(Socks5Client, Socks5Sender): def __init__(self, idlequeue, sock_hash, parent, _sock, host=None, port=None, fingerprint=None, connected=True, file_props=None, initiator=None, target=None): Socks5Client.__init__(self, idlequeue, host, port, initiator, target, file_props.transport_sid) Socks5Sender.__init__(self, idlequeue, sock_hash, parent, _sock, host, port, fingerprint, connected, file_props) class Socks5SenderServer(Socks5Server, Socks5Sender): def __init__(self, idlequeue, sock_hash, parent, _sock, host=None, port=None, fingerprint=None, connected=True, file_props=None): Socks5Server.__init__(self, idlequeue, host, port, None, None, file_props.transport_sid) Socks5Sender.__init__(self, idlequeue, sock_hash, parent, _sock, host, port, fingerprint, connected, file_props) class Socks5ReceiverClient(Socks5Client, Socks5Receiver): def __init__(self, idlequeue, streamhost, transport_sid, file_props=None, fingerprint=None): Socks5Client.__init__(self, idlequeue, streamhost['host'], int(streamhost['port']), streamhost['initiator'], streamhost['target'], transport_sid) Socks5Receiver.__init__(self, idlequeue, streamhost, transport_sid, file_props, fingerprint) class Socks5ReceiverServer(Socks5Server, Socks5Receiver): def __init__(self, idlequeue, streamhost, transport_sid, file_props=None, fingerprint=None): Socks5Server.__init__(self, idlequeue, streamhost['host'], int(streamhost['port']), streamhost['initiator'], streamhost['target'], transport_sid) Socks5Receiver.__init__(self, idlequeue, streamhost, transport_sid, file_props, fingerprint) class Socks5Listener(IdleObject): def __init__(self, idlequeue, port, fp, fingerprint=None): """ Handle all incomming connections on (0.0.0.0, port) This class implements IdleObject, but we will expect only pollin events though fingerprint: fingerprint of certificates we shall use, set to None if TLS connection not desired """ self.port = port self.ais = socket.getaddrinfo(None, port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.SOL_TCP, socket.AI_PASSIVE) self.ais.sort(reverse=True) # Try IPv6 first self.queue_idx = -1 self.idlequeue = idlequeue self.queue = None self.started = False self._sock = None self.fd = -1 self.fingerprint = fingerprint self.file_props = fp self.connections = [] def bind(self): for ai in self.ais: # try the different possibilities (ipv6, ipv4, etc.) try: self._serv = socket.socket(*ai[:3]) if self.fingerprint is not None: self._serv = OpenSSL.SSL.Connection( jingle_xtls.get_context('server'), self._serv) except socket.error as e: if e.errno == EAFNOSUPPORT: self.ai = None continue raise self._serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._serv.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) self._serv.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # Under windows Vista, we need that to listen on ipv6 AND ipv4 # Doesn't work under windows XP if os.name == 'nt': if sys.getwindowsversion().major >= 6: # Win Vista + # 47 is socket.IPPROTO_IPV6 # 27 is socket.IPV6_V6ONLY under windows, but not defined ... self._serv.setsockopt(41, 27, 0) # will fail when port as busy, or we don't have rights to bind try: self._serv.bind(ai[4]) self.ai = ai break except Exception: self.ai = None continue if not self.ai: log.error('unable to bind to port %s', str(self.port)) return None self._serv.listen(socket.SOMAXCONN) self._serv.setblocking(False) self.fd = self._serv.fileno() self.idlequeue.plug_idle(self, False, True) self.started = True def pollend(self): """ Called when we stop listening on (host, port) """ self.disconnect() def pollin(self): """ Accept a new incomming connection and notify queue """ sock = self.accept_conn() self.queue.on_connection_accepted(sock, self) def disconnect(self): """ Free all resources, we are not listening anymore """ self.idlequeue.remove_timeout(self.fd) self.idlequeue.unplug_idle(self.fd) self.fd = -1 self.state = -1 self.started = False try: self._serv.close() except Exception: pass def accept_conn(self): """ Accept a new incomming connection """ _sock = self._serv.accept() _sock[0].setblocking(False) self.connections.append(_sock[0]) return _sock gajim-gajim-1.1.3/gajim/common/types.py000066400000000000000000000041201345766322700200010ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # Types for typechecking from typing import Callable from typing import Dict from typing import List from typing import Optional from typing import Tuple from typing import Union from typing import TYPE_CHECKING import nbxmpp from gajim.common.const import PathType, PathLocation if TYPE_CHECKING: # pylint: disable=unused-import from gajim.common.connection import Connection from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf from gajim.common.contacts import Contact from gajim.common.contacts import GC_Contact from gajim.common.nec import NetworkEvent from gajim.common.nec import NetworkEventsController from gajim.common.logger import Logger from gajim.gui_interface import Interface NetworkEventsControllerT = Union['NetworkEventsController'] InterfaceT = Union['Interface'] LoggerT = Union['Logger'] ConnectionT = Union['Connection', 'ConnectionZeroconf'] ContactsT = Union['Contact', 'GC_Contact'] ContactT = Union['Contact'] UserTuneDataT = Optional[Tuple[str, str, str, str, str]] # PEP PEPNotifyCallback = Callable[[nbxmpp.JID, nbxmpp.Node], None] PEPHandlersDict = Dict[str, List[PEPNotifyCallback]] # Configpaths PathTuple = Tuple[Optional[PathLocation], str, Optional[PathType]] # Plugins PluginExtensionPoints = Dict[str, Tuple[Optional[Callable[..., None]], Optional[Callable[..., None]]]] EventHandlersDict = Dict[str, Tuple[int, Callable[['NetworkEvent'], Optional[bool]]]] PluginEvents = List['NetworkEvent'] gajim-gajim-1.1.3/gajim/common/zeroconf/000077500000000000000000000000001345766322700201135ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/zeroconf/__init__.py000066400000000000000000000000001345766322700222120ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/common/zeroconf/client_zeroconf.py000066400000000000000000000744451345766322700236660ustar00rootroot00000000000000# Copyright (C) 2006 Stefan Bethge # 2006 Dimitur Kirov # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gajim.common import app import nbxmpp from nbxmpp.idlequeue import IdleObject from nbxmpp import dispatcher_nb, simplexml from nbxmpp.plugin import PlugIn from nbxmpp.plugin import * from nbxmpp.transports_nb import DATA_RECEIVED, DATA_SENT, DATA_ERROR from gajim.common.zeroconf import zeroconf from nbxmpp.protocol import * import socket import ssl import errno import sys import os import string from random import Random import logging log = logging.getLogger('gajim.c.z.client_zeroconf') from gajim.common.zeroconf import roster_zeroconf MAX_BUFF_LEN = 65536 TYPE_SERVER, TYPE_CLIENT = range(2) # wait XX sec to establish a connection CONNECT_TIMEOUT_SECONDS = 10 # after XX sec with no activity, close the stream ACTIVITY_TIMEOUT_SECONDS = 30 class ZeroconfListener(IdleObject): def __init__(self, port, conn_holder): """ Handle all incomming connections on ('0.0.0.0', port) """ self.port = port self.queue_idx = -1 #~ self.queue = None self.started = False self._sock = None self.fd = -1 self.caller = conn_holder.caller self.conn_holder = conn_holder def bind(self): flags = socket.AI_PASSIVE if hasattr(socket, 'AI_ADDRCONFIG'): flags |= socket.AI_ADDRCONFIG ai = socket.getaddrinfo(None, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, flags)[0] self._serv = socket.socket(ai[0], ai[1]) self._serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._serv.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) self._serv.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) if os.name == 'nt': if sys.getwindowsversion().major >= 6: # Win Vista + # 47 is socket.IPPROTO_IPV6 # 27 is socket.IPV6_V6ONLY under windows, but not defined ... self._serv.setsockopt(41, 27, 0) # will fail when port is busy, or we don't have rights to bind try: self._serv.bind((ai[4][0], self.port)) except Exception: # unable to bind, show error dialog return None self._serv.listen(socket.SOMAXCONN) self._serv.setblocking(False) self.fd = self._serv.fileno() app.idlequeue.plug_idle(self, False, True) self.started = True def pollend(self): """ Called when we stop listening on (host, port) """ self.disconnect() def pollin(self): """ Accept a new incomming connection and notify queue """ sock = self.accept_conn() # loop through roster to find who has connected to us from_jid = None ipaddr = sock[1][0] for jid in self.conn_holder.getRoster().keys(): entry = self.conn_holder.getRoster().getItem(jid) for address in entry['addresses']: if address['address'] == ipaddr: from_jid = jid break P2PClient(sock[0], [{'host': ipaddr, 'address': ipaddr, 'port': sock[1][1]}], self.conn_holder, [], from_jid) def disconnect(self, message=''): """ Free all resources, we are not listening anymore """ log.info('Disconnecting ZeroconfListener: %s', message) app.idlequeue.remove_timeout(self.fd) app.idlequeue.unplug_idle(self.fd) self.fd = -1 self.started = False try: self._serv.close() except socket.error: pass self.conn_holder.kill_all_connections() def accept_conn(self): """ Accept a new incoming connection """ _sock = self._serv.accept() _sock[0].setblocking(False) return _sock class P2PClient(IdleObject): def __init__(self, _sock, addresses, conn_holder, stanzaqueue, to=None, on_ok=None, on_not_ok=None): self._owner = self self.Namespace = 'jabber:client' self.protocol_type = 'XMPP' self.defaultNamespace = self.Namespace self._component = 0 self._registered_name = None self._caller = conn_holder.caller self.conn_holder = conn_holder self.stanzaqueue = stanzaqueue self.to = to #self.Server = addresses[0]['host'] self.on_ok = on_ok self.on_not_ok = on_not_ok self.Connection = None self.sock_hash = None if _sock: self.sock_type = TYPE_SERVER else: self.sock_type = TYPE_CLIENT self.fd = -1 conn = P2PConnection('', _sock, addresses, self._caller, self.on_connect, self) self.Server = conn.host # set Server to the last host name / address tried if not self.conn_holder: # An error occured, disconnect() has been called if on_not_ok: on_not_ok('Connection to host could not be established.') return self.sock_hash = conn._sock.__hash__ self.fd = conn.fd self.conn_holder.add_connection(self, self.Server, conn.port, self.to) # count messages in queue for val in self.stanzaqueue: stanza, is_message = val if is_message: if self.fd == -1: if on_not_ok: on_not_ok( 'Connection to host could not be established.') return thread_id = stanza.getThread() id_ = stanza.getID() if not id_: id_ = self.Dispatcher.getAnID() if self.fd in self.conn_holder.ids_of_awaiting_messages: self.conn_holder.ids_of_awaiting_messages[self.fd].append(( id_, thread_id)) else: self.conn_holder.ids_of_awaiting_messages[self.fd] = [(id_, thread_id)] self.on_responses = {} def add_stanza(self, stanza, is_message=False): if self.Connection: if self.Connection.state == -1: return False self.send(stanza, is_message) else: self.stanzaqueue.append((stanza, is_message)) if is_message: thread_id = stanza.getThread() id_ = stanza.getID() if not id_: id_ = self.Dispatcher.getAnID() if self.fd in self.conn_holder.ids_of_awaiting_messages: self.conn_holder.ids_of_awaiting_messages[self.fd].append((id_, thread_id)) else: self.conn_holder.ids_of_awaiting_messages[self.fd] = [(id_, thread_id)] return True def on_message_sent(self, connection_id): id_, _thread_id = \ self.conn_holder.ids_of_awaiting_messages[connection_id].pop(0) if self.on_ok: self.on_ok(id_) # use on_ok only on first message. For others it's called in # ClientZeroconf self.on_ok = None def on_connect(self, conn): self.Connection = conn self.Connection.PlugIn(self) dispatcher_nb.Dispatcher().PlugIn(self) self._register_handlers() def StreamInit(self): """ Send an initial stream header """ self.Dispatcher.Stream = simplexml.NodeBuilder() self.Dispatcher.Stream._dispatch_depth = 2 self.Dispatcher.Stream.dispatch = self.Dispatcher.dispatch self.Dispatcher.Stream.stream_header_received = self._check_stream_start self.Dispatcher.Stream.features = None if self.sock_type == TYPE_CLIENT: self.send_stream_header() def send_stream_header(self): self.Dispatcher._metastream = nbxmpp.Node('stream:stream') self.Dispatcher._metastream.setNamespace(self.Namespace) self.Dispatcher._metastream.setAttr('version', '1.0') self.Dispatcher._metastream.setAttr('xmlns:stream', nbxmpp.NS_STREAMS) self.Dispatcher._metastream.setAttr('from', self.conn_holder.zeroconf.name) if self.to: self.Dispatcher._metastream.setAttr('to', self.to) self.Dispatcher.send("%s>" % str( self.Dispatcher._metastream)[:-2]) def _check_stream_start(self, ns, tag, attrs): if ns != nbxmpp.NS_STREAMS or tag != 'stream': log.error('Incorrect stream start: (%s,%s).Terminating!', tag, ns) self.Connection.disconnect() if self.on_not_ok: self.on_not_ok('Connection to host could not be established: ' 'Incorrect answer from server.') return if self.sock_type == TYPE_SERVER: if 'from' in attrs: self.to = attrs['from'] self.send_stream_header() if 'version' in attrs and attrs['version'] == '1.0': # other part supports stream features features = nbxmpp.Node('stream:features') self.Dispatcher.send(features) while self.stanzaqueue: stanza, is_message = self.stanzaqueue.pop(0) self.send(stanza, is_message) elif self.sock_type == TYPE_CLIENT: while self.stanzaqueue: stanza, is_message = self.stanzaqueue.pop(0) self.send(stanza, is_message) def on_disconnect(self): if self.conn_holder: if self.fd in self.conn_holder.ids_of_awaiting_messages: del self.conn_holder.ids_of_awaiting_messages[self.fd] self.conn_holder.remove_connection(self.sock_hash) if 'Dispatcher' in self.__dict__: self.Dispatcher.PlugOut() if 'P2PConnection' in self.__dict__: self.P2PConnection.PlugOut() self.Connection = None self._caller = None self.conn_holder = None def force_disconnect(self): if self.Connection: self.disconnect() else: self.on_disconnect() def _on_receive_document_attrs(self, data): if data: self.Dispatcher.ProcessNonBlocking(data) if not hasattr(self, 'Dispatcher') or \ self.Dispatcher.Stream._document_attrs is None: return self.onreceive(None) if 'version' in self.Dispatcher.Stream._document_attrs and \ self.Dispatcher.Stream._document_attrs['version'] == '1.0': #~ self.onreceive(self._on_receive_stream_features) #XXX continue with TLS return self.onreceive(None) return True def remove_timeout(self): pass def _register_handlers(self): self._caller.peerhost = self.Connection._sock.getsockname() self.RegisterHandler('message', lambda conn, data: self._caller._messageCB(self.Server, conn, data)) self.RegisterHandler('iq', self._caller._siSetCB, 'set', nbxmpp.NS_SI) self.RegisterHandler('iq', self._caller._siErrorCB, 'error', nbxmpp.NS_SI) self.RegisterHandler('iq', self._caller._siResultCB, 'result', nbxmpp.NS_SI) self.RegisterHandler('iq', self._caller._bytestreamSetCB, 'set', nbxmpp.NS_BYTESTREAM) self.RegisterHandler('iq', self._caller._bytestreamResultCB, 'result', nbxmpp.NS_BYTESTREAM) self.RegisterHandler('iq', self._caller._bytestreamErrorCB, 'error', nbxmpp.NS_BYTESTREAM) self.RegisterHandler('iq', self._caller._JingleCB, 'result') self.RegisterHandler('iq', self._caller._JingleCB, 'error') self.RegisterHandler('iq', self._caller._JingleCB, 'set', nbxmpp.NS_JINGLE) class P2PConnection(IdleObject, PlugIn): def __init__(self, sock_hash, _sock, addresses=None, caller=None, on_connect=None, client=None): IdleObject.__init__(self) self._owner = client PlugIn.__init__(self) self.sendqueue = [] self.sendbuff = None self.buff_is_message = False self._sock = _sock self.sock_hash = None self.addresses = addresses self.on_connect = on_connect self.client = client self.writable = False self.readable = False self._exported_methods = [self.send, self.disconnect, self.onreceive] self.on_receive = None if _sock: self.host = addresses[0]['host'] self.port = addresses[0]['port'] self._sock = _sock self.state = 1 self._sock.setblocking(False) self.fd = self._sock.fileno() self.on_connect(self) else: self.state = 0 self.addresses_ = self.addresses self.get_next_addrinfo() def get_next_addrinfo(self): address = self.addresses_.pop(0) self.host = address['host'] self.port = address['port'] try: self.ais = socket.getaddrinfo(address['host'], address['port'], socket.AF_UNSPEC, socket.SOCK_STREAM) except socket.gaierror as e: log.info('Lookup failure for %s: %s[%s]', self.host, e[1], repr(e[0]), exc_info=True) if self.addresses_: return self.get_next_addrinfo() else: self.connect_to_next_ip() def connect_to_next_ip(self): if not self.ais: log.error('Connection failure to %s', str(self.host), exc_info=True) if self.addresses_: return self.get_next_addrinfo() self.disconnect() return ai = self.ais.pop(0) log.info('Trying to connect to %s through %s:%s', str(self.host), ai[4][0], ai[4][1], exc_info=True) try: self._sock = socket.socket(*ai[:3]) self._sock.setblocking(False) self._server = ai[4] except socket.error: if sys.exc_value[0] != errno.EINPROGRESS: # for all errors, we try other addresses self.connect_to_next_ip() return self.fd = self._sock.fileno() app.idlequeue.plug_idle(self, True, False) self.set_timeout(CONNECT_TIMEOUT_SECONDS) self.do_connect() def set_timeout(self, timeout): app.idlequeue.remove_timeout(self.fd) if self.state >= 0: app.idlequeue.set_read_timeout(self.fd, timeout) def plugin(self, owner): self.onreceive(owner._on_receive_document_attrs) self._plug_idle() return True def plugout(self): """ Disconnect from the remote server and unregister self.disconnected method from the owner's dispatcher """ self.disconnect() self._owner = None def onreceive(self, recv_handler): if not recv_handler: if hasattr(self._owner, 'Dispatcher'): self.on_receive = self._owner.Dispatcher.ProcessNonBlocking else: self.on_receive = None return _tmp = self.on_receive # make sure this cb is not overriden by recursive calls if not recv_handler(None) and _tmp == self.on_receive: self.on_receive = recv_handler def send(self, packet, is_message=False, now=False): """ Append stanza to the queue of messages to be send if now is False, else send it instantly """ if self.state <= 0: return r = str(packet).encode('utf-8') if now: self.sendqueue.insert(0, (r, is_message)) self._do_send() else: self.sendqueue.append((r, is_message)) self._plug_idle() def read_timeout(self): ids = self.client.conn_holder.ids_of_awaiting_messages if self.fd in ids and ids[self.fd]: for (_id, thread_id) in ids[self.fd]: if hasattr(self._owner, 'Dispatcher'): self._owner.Dispatcher.Event('', DATA_ERROR, ( self.client.to, thread_id)) else: self._owner.on_not_ok('connection timeout') ids[self.fd] = [] self.pollend() def do_connect(self): errnum = 0 try: self._sock.connect(self._server[:2]) self._sock.setblocking(False) except Exception as ee: errnum = ee.errno errstr = ee.strerror errors = (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK) if 'WSAEINVAL' in errno.__dict__: errors += (errno.WSAEINVAL,) if errnum in errors: return # win32 needs this if errnum not in (0, 10056, errno.EISCONN) or self.state != 0: log.error('Could not connect to %s: %s [%s]', str(self.host), errnum, errstr) self.connect_to_next_ip() return # socket is already connected self._sock.setblocking(False) self.state = 1 # connected # we are connected self.on_connect(self) def pollout(self): if self.state == 0: self.do_connect() return app.idlequeue.remove_timeout(self.fd) self._do_send() def pollend(self): if self.state == 0: # error in connect()? #self.disconnect() self.connect_to_next_ip() else: self.state = -1 self.disconnect() def pollin(self): """ Reads all pending incoming data. Call owner's disconnected() method if appropriate """ received = '' errnum = 0 try: # get as many bites, as possible, but not more than RECV_BUFSIZE received = self._sock.recv(MAX_BUFF_LEN) except Exception as e: errnum = e.errno # "received" will be empty anyhow if errnum == ssl.SSL_ERROR_WANT_READ: pass elif errnum in [errno.ECONNRESET, errno.ENOTCONN, errno.ESHUTDOWN]: self.pollend() # don't proccess result, cas it will raise error return elif not received: if errnum != ssl.SSL_ERROR_EOF: # 8 EOF occurred in violation of protocol self.pollend() if self.state >= 0: self.disconnect() return if self.state < 0: return received = received.decode('utf-8') if self.on_receive: if self._owner.sock_type == TYPE_CLIENT: self.set_timeout(ACTIVITY_TIMEOUT_SECONDS) if received.strip(): log.debug('received: %s', received) if hasattr(self._owner, 'Dispatcher'): self._owner.Dispatcher.Event('', DATA_RECEIVED, received) self.on_receive(received) else: # This should never happed, so we need the debug log.error('Unhandled data received: %s', received) self.disconnect() return True def disconnect(self, message=''): """ Close the socket """ app.idlequeue.remove_timeout(self.fd) app.idlequeue.unplug_idle(self.fd) try: self._sock.shutdown(socket.SHUT_RDWR) self._sock.close() except socket.error: # socket is already closed pass self.fd = -1 self.state = -1 if self._owner: self._owner.on_disconnect() def _do_send(self): if not self.sendbuff: if not self.sendqueue: return None # nothing to send self.sendbuff, self.buff_is_message = self.sendqueue.pop(0) self.sent_data = self.sendbuff try: send_count = self._sock.send(self.sendbuff) if send_count: self.sendbuff = self.sendbuff[send_count:] if not self.sendbuff and not self.sendqueue: if self.state < 0: app.idlequeue.unplug_idle(self.fd) self._on_send() self.disconnect() return # we are not waiting for write self._plug_idle() self._on_send() except socket.error as e: if e.errno == ssl.SSL_ERROR_WANT_WRITE: return True if self.state < 0: self.disconnect() return self._on_send_failure() return if self._owner.sock_type == TYPE_CLIENT: self.set_timeout(ACTIVITY_TIMEOUT_SECONDS) return True def _plug_idle(self): readable = self.state != 0 writable = self.sendqueue or self.sendbuff if self.writable != writable or self.readable != readable: app.idlequeue.plug_idle(self, writable, readable) def _on_send(self): if self.sent_data and self.sent_data.strip(): log.debug('sent: %s', self.sent_data) if hasattr(self._owner, 'Dispatcher'): self._owner.Dispatcher.Event( '', DATA_SENT, self.sent_data.decode('utf-8')) self.sent_data = None if self.buff_is_message: self._owner.on_message_sent(self.fd) self.buff_is_message = False def _on_send_failure(self): log.error('Socket error while sending data') self._owner.on_disconnect() self.sent_data = None class ClientZeroconf: def __init__(self, caller): self.caller = caller self.zeroconf = None self.roster = None self.last_msg = '' self.connections = {} self.recipient_to_hash = {} self.ip_to_hash = {} self.hash_to_port = {} self.listener = None self.ids_of_awaiting_messages = {} self.disconnect_handlers = [] self.disconnecting = False def connect(self, show, msg): self.port = self.start_listener(self.caller.port) if not self.port: return False self.zeroconf_init(show, msg) if not self.zeroconf.connect(): self.disconnect() return None self.roster = roster_zeroconf.Roster(self.zeroconf) return True def remove_announce(self): if self.zeroconf: return self.zeroconf.remove_announce() def announce(self): if self.zeroconf: return self.zeroconf.announce() def set_show_msg(self, show, msg): if self.zeroconf: self.zeroconf.txt['msg'] = msg self.last_msg = msg return self.zeroconf.update_txt(show) def resolve_all(self): if self.zeroconf: return self.zeroconf.resolve_all() def reannounce(self, txt): self.remove_announce() self.zeroconf.txt = txt self.zeroconf.port = self.port self.zeroconf.username = self.caller.username return self.announce() def zeroconf_init(self, show, msg): self.zeroconf = zeroconf.Zeroconf(self.caller._on_new_service, self.caller._on_remove_service, self.caller._on_name_conflictCB, self.caller._on_disconnected, self.caller._on_error, self.caller.username, self.caller.host, self.port) self.zeroconf.txt['msg'] = msg self.zeroconf.txt['status'] = show self.zeroconf.txt['1st'] = self.caller.first self.zeroconf.txt['last'] = self.caller.last self.zeroconf.txt['jid'] = self.caller.jabber_id self.zeroconf.txt['email'] = self.caller.email self.zeroconf.username = self.caller.username self.zeroconf.host = self.caller.host self.zeroconf.port = self.port self.last_msg = msg def disconnect(self): # to avoid recursive calls if self.disconnecting: return if self.listener: self.listener.disconnect() self.listener = None if self.zeroconf: self.zeroconf.disconnect() self.zeroconf = None if self.roster: self.roster.zeroconf = None self.roster._data = None self.roster = None self.disconnecting = True for i in reversed(self.disconnect_handlers): log.debug('Calling disconnect handler %s', i) i() self.disconnecting = False def start_disconnect(self): self.disconnect() def kill_all_connections(self): for connection in list(self.connections.values()): connection.force_disconnect() def add_connection(self, connection, ip, port, recipient): sock_hash = connection.sock_hash if sock_hash not in self.connections: self.connections[sock_hash] = connection self.ip_to_hash[ip] = sock_hash self.hash_to_port[sock_hash] = port if recipient: self.recipient_to_hash[recipient] = sock_hash def remove_connection(self, sock_hash): if sock_hash in self.connections: del self.connections[sock_hash] for i in self.recipient_to_hash: if self.recipient_to_hash[i] == sock_hash: del self.recipient_to_hash[i] break for i in self.ip_to_hash: if self.ip_to_hash[i] == sock_hash: del self.ip_to_hash[i] break if sock_hash in self.hash_to_port: del self.hash_to_port[sock_hash] def start_listener(self, port): for p in range(port, port + 5): self.listener = ZeroconfListener(p, self) self.listener.bind() if self.listener.started: return p self.listener = None return False def getRoster(self): if self.roster: return self.roster.getRoster() return {} def send(self, stanza, is_message=False, now=False, on_ok=None, on_not_ok=None): to = stanza.getTo() if to is None: # Can’t send undirected stanza over Zeroconf. return -1 to = to.getStripped() stanza.setFrom(self.roster.zeroconf.name) try: item = self.roster[to] except KeyError: # Contact offline return -1 # look for hashed connections if to in self.recipient_to_hash: conn = self.connections[self.recipient_to_hash[to]] id_ = stanza.getID() or '' if conn.add_stanza(stanza, is_message): if on_ok: on_ok(id_) return the_address = None for address in item['addresses']: if address['address'] in self.ip_to_hash: the_address = address if the_address and the_address['address'] in self.ip_to_hash: hash_ = self.ip_to_hash[the_address['address']] if self.hash_to_port[hash_] == the_address['port']: conn = self.connections[hash_] id_ = stanza.getID() or '' if conn.add_stanza(stanza, is_message): if on_ok: on_ok(id_) return # otherwise open new connection if not stanza.getID(): stanza.setID('zero') addresses_ = [] for address in item['addresses']: addresses_ += [{'host': address['address'], 'address': address['address'], 'port': address['port']}] P2PClient(None, addresses_, self, [(stanza, is_message)], to, on_ok=on_ok, on_not_ok=on_not_ok) def getAnID(self): """ Generate a random id """ return ''.join(Random().sample(string.ascii_letters + string.digits, 6)) def RegisterDisconnectHandler(self, handler): """ Register handler that will be called on disconnect """ self.disconnect_handlers.append(handler) def UnregisterDisconnectHandler(self, handler): """ Unregister handler that is called on disconnect """ self.disconnect_handlers.remove(handler) def SendAndWaitForResponse(self, stanza, timeout=None, func=None, args=None): """ Send stanza and wait for recipient's response to it. Will call transports on_timeout callback if response is not retrieved in time Be aware: Only timeout of latest call of SendAndWait is active. """ # if timeout is None: # timeout = DEFAULT_TIMEOUT_SECONDS def on_ok(_waitid): # if timeout: # self._owner.set_timeout(timeout) to = stanza.getTo() to = app.get_jid_without_resource(to) try: item = self.roster[to] except KeyError: # Contact offline item = None conn = None if to in self.recipient_to_hash: conn = self.connections[self.recipient_to_hash[to]] elif item: the_address = None for address in item['addresses']: if address['address'] in self.ip_to_hash: the_address = address if the_address and the_address['address'] in self.ip_to_hash: hash_ = self.ip_to_hash[the_address['address']] if self.hash_to_port[hash_] == the_address['port']: conn = self.connections[hash_] if func: conn.Dispatcher.on_responses[_waitid] = (func, args) conn.onreceive(conn.Dispatcher._WaitForData) conn.Dispatcher._expected[_waitid] = None self.send(stanza, on_ok=on_ok) def SendAndCallForResponse(self, stanza, func=None, args=None): """ Put stanza on the wire and call back when recipient replies. Additional callback arguments can be specified in args. """ self.SendAndWaitForResponse(stanza, 0, func, args) gajim-gajim-1.1.3/gajim/common/zeroconf/connection_handlers_zeroconf.py000066400000000000000000000133101345766322700264070ustar00rootroot00000000000000# Contributors for this file: # - Yann Leboulanger # - Nikos Kouremenos # - Dimitur Kirov # - Travis Shirk # - Stefan Bethge # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import time import logging import nbxmpp from gajim.common import app from gajim.common.protocol.bytestream import ConnectionSocks5BytestreamZeroconf from gajim.common.zeroconf.zeroconf import Constant from gajim.common import connection_handlers from gajim.common.i18n import _ from gajim.common.helpers import AdditionalDataDict from gajim.common.nec import NetworkIncomingEvent, NetworkEvent from gajim.common.modules.user_nickname import parse_nickname from gajim.common.modules.misc import parse_eme from gajim.common.modules.misc import parse_correction from gajim.common.modules.misc import parse_attention from gajim.common.modules.misc import parse_oob from gajim.common.modules.misc import parse_xhtml log = logging.getLogger('gajim.c.z.connection_handlers_zeroconf') STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd', 'invisible'] # kind of events we can wait for an answer AGENT_REMOVED = 'agent_removed' class ZeroconfMessageReceivedEvent(NetworkIncomingEvent): name = 'message-received' class DecryptedMessageReceivedEvent(NetworkIncomingEvent): name = 'decrypted-message-received' class ConnectionVcard: def add_sha(self, p, *args): return p def add_caps(self, p): return p class ConnectionHandlersZeroconf(ConnectionVcard, ConnectionSocks5BytestreamZeroconf, connection_handlers.ConnectionHandlersBase, connection_handlers.ConnectionJingle): def __init__(self): ConnectionVcard.__init__(self) ConnectionSocks5BytestreamZeroconf.__init__(self) connection_handlers.ConnectionJingle.__init__(self) connection_handlers.ConnectionHandlersBase.__init__(self) def _messageCB(self, ip, con, stanza): """ Called when we receive a message """ log.debug('Zeroconf MessageCB') app.nec.push_incoming_event(NetworkEvent( 'raw-message-received', conn=self, stanza=stanza, account=self.name)) type_ = stanza.getType() if type_ is None: type_ = 'normal' id_ = stanza.getID() fjid = str(stanza.getFrom()) if fjid is None: for key in self.connection.zeroconf.contacts: if ip == self.connection.zeroconf.contacts[key][ Constant.ADDRESS]: fjid = key break jid, resource = app.get_room_and_nick_from_fjid(fjid) thread_id = stanza.getThread() msgtxt = stanza.getBody() session = self.get_or_create_session(fjid, thread_id) if thread_id and not session.received_thread_id: session.received_thread_id = True session.last_receive = time.time() event_attr = { 'conn': self, 'stanza': stanza, 'account': self.name, 'id_': id_, 'encrypted': False, 'additional_data': AdditionalDataDict(), 'forwarded': False, 'sent': False, 'timestamp': time.time(), 'fjid': fjid, 'jid': jid, 'resource': resource, 'unique_id': id_, 'mtype': type_, 'msgtxt': msgtxt, 'thread_id': thread_id, 'session': session, 'self_message': False, 'muc_pm': False, 'gc_control': None} event = ZeroconfMessageReceivedEvent(None, **event_attr) app.nec.push_incoming_event(event) app.plugin_manager.extension_point( 'decrypt', self, event, self._on_message_decrypted) if not event.encrypted: eme = parse_eme(event.stanza) if eme is not None: event.msgtxt = eme self._on_message_decrypted(event) def _on_message_decrypted(self, event): try: self.get_module('Receipts').delegate(event) self.get_module('Chatstate').delegate(event) except nbxmpp.NodeProcessed: return event_attr = { 'popup': False, 'msg_log_id': None, 'subject': None, 'displaymarking': None, 'form_node': None, 'attention': parse_attention(event.stanza), 'correct_id': parse_correction(event.stanza), 'user_nick': parse_nickname(event.stanza), 'xhtml': parse_xhtml(event.stanza), 'stanza_id': event.unique_id } parse_oob(event) for name, value in event_attr.items(): setattr(event, name, value) if event.mtype == 'error': if not event.msgtxt: event.msgtxt = _('message') self.dispatch_error_message( event.stanza, event.msgtxt, event.session, event.fjid, event.timestamp) return app.nec.push_incoming_event( DecryptedMessageReceivedEvent(None, **vars(event))) gajim-gajim-1.1.3/gajim/common/zeroconf/connection_zeroconf.py000066400000000000000000000377471345766322700245530ustar00rootroot00000000000000# Contributors for this file: # - Yann Leboulanger # - Nikos Kouremenos # - Dimitur Kirov # - Travis Shirk # - Stefan Bethge # # Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2003-2004 Vincent Hanquez # Copyright (C) 2006 Nikos Kouremenos # Dimitur Kirov # Travis Shirk # Norman Rasmussen # Stefan Bethge # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import socket import random random.seed() import nbxmpp import signal if os.name != 'nt': signal.signal(signal.SIGPIPE, signal.SIG_DFL) import getpass from gi.repository import GLib from gajim.common.connection import CommonConnection from gajim.common import app from gajim.common import ged from gajim.common import modules from gajim.common.i18n import _ from gajim.common.zeroconf import client_zeroconf from gajim.common.zeroconf import zeroconf from gajim.common.zeroconf.connection_handlers_zeroconf import * from gajim.common.connection_handlers_events import * log = logging.getLogger('gajim.c.connection_zeroconf') class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf): def __init__(self, name): ConnectionHandlersZeroconf.__init__(self) # system username self.username = None self.server_resource = '' # zeroconf has no resource, fake an empty one self.call_resolve_timeout = False # we don't need a password, but must be non-empty self.password = 'zeroconf' self.autoconnect = False self.httpupload = False CommonConnection.__init__(self, name) self.is_zeroconf = True # Register all modules modules.register(self) app.ged.register_event_handler('message-outgoing', ged.OUT_CORE, self._nec_message_outgoing) app.ged.register_event_handler('stanza-message-outgoing', ged.OUT_CORE, self._nec_stanza_message_outgoing) def get_config_values_or_default(self): """ Get name, host, port from config, or create zeroconf account with default values """ self.host = socket.gethostname() app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'hostname', self.host) self.port = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'custom_port') self.autoconnect = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'autoconnect') self.sync_with_global_status = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'sync_with_global_status') self.first = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_first_name') self.last = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_last_name') self.jabber_id = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_jabber_id') self.email = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_email') if not self.username: self.username = getpass.getuser() app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'name', self.username) else: self.username = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'name') # END __init__ def check_jid(self, jid): return jid def get_own_jid(self, *args, **kwargs): return nbxmpp.JID(self.username + '@' + self.host) def reconnect(self): # Do not try to reco while we are already trying self.time_to_reconnect = None log.debug('reconnect') self.disconnect() self.change_status(self.old_show, self.status) def disable_account(self): self.disconnect() def _on_resolve_timeout(self): if self.connected: if not self.connection.resolve_all(): self._on_disconnected() return False diffs = self.roster.getDiffs() for key in diffs: self.roster.setItem(key) app.nec.push_incoming_event(NetworkEvent( 'roster-info', conn=self, jid=key, nickname=self.roster.getName(key), sub='both', ask='no', groups=self.roster.getGroups(key), avatar_sha=None)) app.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( None, conn=self, fjid=key, show=self.roster.getStatus(key), status=self.roster.getMessage(key))) #XXX open chat windows don't get refreshed (full name), add that return self.call_resolve_timeout # callbacks called from zeroconf def _on_new_service(self, jid): self.roster.setItem(jid) app.nec.push_incoming_event(NetworkEvent( 'roster-info', conn=self, jid=jid, nickname=self.roster.getName(jid), sub='both', ask='no', groups=self.roster.getGroups(jid), avatar_sha=None)) app.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( None, conn=self, fjid=jid, show=self.roster.getStatus(jid), status=self.roster.getMessage(jid))) def _on_remove_service(self, jid): self.roster.delItem(jid) # 'NOTIFY' (account, (jid, status, status message, resource, priority, # keyID, timestamp, contact_nickname)) app.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( None, conn=self, fjid=jid, show='offline', status='')) def disconnectedReconnCB(self): """ Called when we are disconnected. Comes from network manager for example we don't try to reconnect, network manager will tell us when we can """ if app.account_is_connected(self.name): # we cannot change our status to offline or connecting # after we auth to server self.old_show = STATUS_LIST[self.connected] self.connected = 0 app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) # random number to show we wait network manager to send us a reconenct self.time_to_reconnect = 5 self.on_purpose = False def _on_name_conflictCB(self, alt_name): self.disconnect() app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) app.nec.push_incoming_event(ZeroconfNameConflictEvent(None, conn=self, alt_name=alt_name)) def _on_error(self, message): app.nec.push_incoming_event(InformationEvent( None, dialog_name='avahi-error', args=message)) def connect(self, show='online', msg=''): self.get_config_values_or_default() if not self.connection: self.connection = client_zeroconf.ClientZeroconf(self) if not zeroconf.test_zeroconf(): app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) self.status = 'offline' app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not connect to "%s"') % self.name, msg=_('Please check if Avahi or Bonjour is installed.'))) self.disconnect() return result = self.connection.connect(show, msg) if not result: app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) self.status = 'offline' if result is False: app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not start local service'), msg=_('Unable to bind to port %d.' % self.port))) else: # result is None app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not start local service'), msg=_('Please check if avahi/bonjour-daemon is running.'))) self.disconnect() return else: self.connection.announce() self.roster = self.connection.getRoster() app.nec.push_incoming_event(NetworkEvent('roster-received', conn=self, roster=self.roster.copy(), received_from_server=True)) # display contacts already detected and resolved for jid in self.roster.keys(): app.nec.push_incoming_event(NetworkEvent( 'roster-info', conn=self, jid=jid, nickname=self.roster.getName(jid), sub='both', ask='no', groups=self.roster.getGroups(jid), avatar_sha=None)) app.nec.push_incoming_event(ZeroconfPresenceReceivedEvent( None, conn=self, fjid=jid, show=self.roster.getStatus(jid), status=self.roster.getMessage(jid))) self.connected = STATUS_LIST.index(show) # refresh all contacts data every five seconds self.call_resolve_timeout = True GLib.timeout_add_seconds(5, self._on_resolve_timeout) return True def disconnect(self, on_purpose=False): self.connected = 0 self.time_to_reconnect = None if self.connection: self.connection.disconnect() self.connection = None # stop calling the timeout self.call_resolve_timeout = False def reannounce(self): if self.connected: txt = {} txt['1st'] = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_first_name') txt['last'] = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_last_name') txt['jid'] = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_jabber_id') txt['email'] = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'zeroconf_email') self.connection.reannounce(txt) def update_details(self): if self.connection: port = app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'custom_port') if port != self.port: self.port = port last_msg = self.connection.last_msg self.disconnect() if not self.connect(self.status, last_msg): return if self.status != 'invisible': self.connection.announce() else: self.reannounce() def connect_and_init(self, show, msg, sign_msg): # to check for errors from zeroconf check = True if not self.connect(show, msg): return if show != 'invisible': check = self.connection.announce() else: self.connected = STATUS_LIST.index(show) app.nec.push_incoming_event(SignedInEvent(None, conn=self)) # stay offline when zeroconf does something wrong if check: app.nec.push_incoming_event(OurShowEvent(None, conn=self, show=show)) else: # show notification that avahi or system bus is down self.connected = 0 app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) self.status = 'offline' app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not change status of account "%s"') % self.name, msg=_('Please check if avahi-daemon is running.'))) def _change_to_invisible(self, msg): if self.connection.remove_announce(): app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='invisible')) else: # show notification that avahi or system bus is down app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) self.status = 'offline' app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not change status of account "%s"') % self.name, msg=_('Please check if avahi-daemon is running.'))) def _change_from_invisible(self): self.connection.announce() def _update_status(self, show, msg, idle_time=None): if self.connection.set_show_msg(show, msg): app.nec.push_incoming_event(OurShowEvent(None, conn=self, show=show)) else: # show notification that avahi or system bus is down app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='offline')) self.status = 'offline' app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self, title=_('Could not change status of account "%s"') % self.name, msg=_('Please check if avahi-daemon is running.'))) def _nec_message_outgoing(self, obj): if obj.account != self.name: return self._prepare_message(obj) def _nec_stanza_message_outgoing(self, obj): if obj.conn.name != self.name: return def on_send_ok(stanza_id): app.nec.push_incoming_event(MessageSentEvent(None, **vars(obj))) self.log_message(obj, obj.jid) def on_send_not_ok(reason): reason += ' ' + _('Your message could not be sent.') app.nec.push_incoming_event(MessageErrorEvent( None, conn=self, fjid=obj.jid, error_code=-1, error_msg=reason, msg=None, time_=None, session=obj.session, zeroconf=True)) # Dont propagate event return True obj.timestamp = time.time() ret = self.connection.send( obj.msg_iq, obj.message is not None, on_ok=on_send_ok, on_not_ok=on_send_not_ok) if ret == -1: # Contact Offline error_message = _( 'Contact is offline. Your message could not be sent.') app.nec.push_incoming_event(MessageErrorEvent( None, conn=self, fjid=obj.jid, error_code=-1, error_msg=error_message, msg=None, time_=None, session=obj.session, zeroconf=True)) # Dont propagate event return True def send_stanza(self, stanza): # send a stanza untouched if not self.connection: return if not isinstance(stanza, nbxmpp.Node): stanza = nbxmpp.Protocol(node=stanza) self.connection.send(stanza) def _event_dispatcher(self, realm, event, data): CommonConnection._event_dispatcher(self, realm, event, data) if realm == '': if event == nbxmpp.transports_nb.DATA_ERROR: thread_id = data[1] frm = data[0] session = self.get_or_create_session(frm, thread_id) error_message = _( 'Connection to host could not be established: ' 'Timeout while sending data.') app.nec.push_incoming_event(MessageErrorEvent( None, conn=self, fjid=frm, error_code=-1, error_msg=error_message, msg=None, time_=None, session=session, zeroconf=True)) # END ConnectionZeroconf gajim-gajim-1.1.3/gajim/common/zeroconf/roster_zeroconf.py000066400000000000000000000107771345766322700237240ustar00rootroot00000000000000# Copyright (C) 2006 Stefan Bethge # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gajim.common.zeroconf.zeroconf import Constant, ConstantRI class Roster: def __init__(self, zeroconf): self._data = None self.zeroconf = zeroconf # our zeroconf instance self.version = '' def update_roster(self): for val in self.zeroconf.contacts.values(): self.setItem(val[Constant.NAME]) def getRoster(self): if self._data is None: self._data = {} self.update_roster() return self def getDiffs(self): """ Update the roster with new data and return dict with jid -> new status pairs to do notifications and stuff """ diffs = {} old_data = self._data.copy() self.update_roster() for key in old_data.keys(): if key in self._data: if old_data[key] != self._data[key]: diffs[key] = self._data[key]['status'] return diffs def setItem(self, jid, name='', groups=''): contact = self.zeroconf.get_contact(jid) if not contact: return addresses = [] i = 0 for ri in contact[Constant.RESOLVED_INFO]: addresses += [{}] addresses[i]['host'] = ri[ConstantRI.HOST] addresses[i]['address'] = ri[ConstantRI.ADDRESS] addresses[i]['port'] = ri[ConstantRI.PORT] i += 1 txt = contact[Constant.TXT] self._data[jid] = {} self._data[jid]['ask'] = 'none' self._data[jid]['subscription'] = 'both' self._data[jid]['groups'] = [] self._data[jid]['resources'] = {} self._data[jid]['addresses'] = addresses txt_dict = self.zeroconf.txt_array_to_dict(txt) status = txt_dict.get('status', '') if not status: status = 'avail' nm = txt_dict.get('1st', '') if 'last' in txt_dict: if nm != '': nm += ' ' nm += txt_dict['last'] if nm: self._data[jid]['name'] = nm else: self._data[jid]['name'] = jid if status == 'avail': status = 'online' self._data[jid]['txt_dict'] = txt_dict if 'msg' not in self._data[jid]['txt_dict']: self._data[jid]['txt_dict']['msg'] = '' self._data[jid]['status'] = status self._data[jid]['show'] = status def setItemMulti(self, items): for i in items: self.setItem(jid=i['jid'], name=i['name'], groups=i['groups']) def delItem(self, jid): if jid in self._data: del self._data[jid] def getItem(self, jid): if jid in self._data: return self._data[jid] def __getitem__(self, jid): return self._data[jid] def __setitem__(self, jid, value): self._data[jid] = value def getItems(self): # Return list of all [bare] JIDs that the roster currently tracks. return self._data.keys() def keys(self): return self._data.keys() def getRaw(self): return self._data def getResources(self, jid): return {} def getGroups(self, jid): return self._data[jid]['groups'] def getName(self, jid): if jid in self._data: return self._data[jid]['name'] def getStatus(self, jid): if jid in self._data: return self._data[jid]['status'] def getMessage(self, jid): if jid in self._data: return self._data[jid]['txt_dict']['msg'] def getShow(self, jid): return self.getStatus(jid) def getPriority(self, jid): return 5 def getSubscription(self, jid): return 'both' def Subscribe(self, jid): pass def Unsubscribe(self, jid): pass def Authorize(self, jid): pass def Unauthorize(self, jid): pass def copy(self): return self._data.copy() gajim-gajim-1.1.3/gajim/common/zeroconf/zeroconf.py000066400000000000000000000032011345766322700223060ustar00rootroot00000000000000# Copyright (C) 2006 Stefan Bethge # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Any # pylint: disable=unused-import from enum import IntEnum, unique @unique class Constant(IntEnum): NAME = 0 DOMAIN = 1 RESOLVED_INFO = 2 BARE_NAME = 3 TXT = 4 @unique class ConstantRI(IntEnum): INTERFACE = 0 PROTOCOL = 1 HOST = 2 APROTOCOL = 3 ADDRESS = 4 PORT = 5 def test_avahi(): try: import dbus # pylint: disable=unused-variable except ImportError: return False return True def test_bonjour(): try: import pybonjour # pylint: disable=unused-variable except ImportError: return False except WindowsError: # pylint: disable=undefined-variable return False return True def test_zeroconf(): return test_avahi() or test_bonjour() if test_avahi(): from gajim.common.zeroconf import zeroconf_avahi Zeroconf = zeroconf_avahi.Zeroconf # type: Any elif test_bonjour(): from gajim.common.zeroconf import zeroconf_bonjour Zeroconf = zeroconf_bonjour.Zeroconf gajim-gajim-1.1.3/gajim/common/zeroconf/zeroconf_avahi.py000066400000000000000000000445361345766322700234760ustar00rootroot00000000000000# Copyright (C) 2006 Stefan Bethge # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging log = logging.getLogger('gajim.c.z.zeroconf_avahi') try: import dbus.exceptions except ImportError: pass from gajim.common.i18n import _ from gajim.common.zeroconf.zeroconf import Constant, ConstantRI from gajim.common.zeroconf.zeroconf_avahi_const import * class Zeroconf: def __init__(self, new_serviceCB, remove_serviceCB, name_conflictCB, disconnected_CB, error_CB, name, host, port): self.domain = None # specific domain to browse self.stype = '_presence._tcp' self.port = port # listening port that gets announced self.username = name self.host = host self.txt = {} # service data #XXX these CBs should be set to None when we destroy the object # (go offline), because they create a circular reference self.new_serviceCB = new_serviceCB self.remove_serviceCB = remove_serviceCB self.name_conflictCB = name_conflictCB self.disconnected_CB = disconnected_CB self.error_CB = error_CB self.service_browser = None self.domain_browser = None self.bus = None self.server = None self.contacts = {} # all current local contacts with data self.entrygroup = None self.connected = False self.announced = False self.invalid_self_contact = {} ## handlers for dbus callbacks def entrygroup_commit_error_CB(self, err): # left blank for possible later usage pass def error_callback1(self, err): log.debug('Error while resolving: %s', str(err)) def error_callback(self, err): log.debug(str(err)) # timeouts are non-critical if str(err) != 'Timeout reached': self.disconnect() self.disconnected_CB() def new_service_callback(self, interface, protocol, name, stype, domain, flags): log.debug('Found service %s in domain %s on %i.%i.', name, domain, interface, protocol) if not self.connected: return # synchronous resolving self.server.ResolveService(int(interface), int(protocol), name, stype, domain, Protocol.UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved_callback, error_handler=self.error_callback1) def remove_service_callback(self, interface, protocol, name, stype, domain, flags): log.debug('Service %s in domain %s on %i.%i disappeared.', name, domain, interface, protocol) if not self.connected: return if name != self.name: for key in list(self.contacts.keys()): val = self.contacts[key] if val[Constant.BARE_NAME] == name: # try to reduce instead of delete first resolved_info = val[Constant.RESOLVED_INFO] if len(resolved_info) > 1: for i, _info in enumerate(resolved_info): if resolved_info[i][ConstantRI.INTERFACE] == interface and resolved_info[i][ConstantRI.PROTOCOL] == protocol: del self.contacts[key][Constant.RESOLVED_INFO][i] # if still something left, don't remove if len(self.contacts[key][Constant.RESOLVED_INFO]) > 1: return del self.contacts[key] self.remove_serviceCB(key) return def new_service_type(self, interface, protocol, stype, domain, flags): # Are we already browsing this domain for this type? if self.service_browser: return object_path = self.server.ServiceBrowserNew(interface, protocol, \ stype, domain, dbus.UInt32(0)) self.service_browser = dbus.Interface(self.bus.get_object( DBUS_NAME, object_path), DBUS_INTERFACE_SERVICE_BROWSER) self.service_browser.connect_to_signal('ItemNew', self.new_service_callback) self.service_browser.connect_to_signal('ItemRemove', self.remove_service_callback) self.service_browser.connect_to_signal('Failure', self.error_callback) def new_domain_callback(self, interface, protocol, domain, flags): if domain != 'local': self.browse_domain(interface, protocol, domain) def txt_array_to_dict(self, txt_array): txt_dict = {} for array in txt_array: item = bytes(array) item = item.decode('utf-8') item = item.split('=', 1) if item[0] and (item[0] not in txt_dict): if len(item) == 1: txt_dict[item[0]] = None else: txt_dict[item[0]] = item[1] return txt_dict @staticmethod def string_to_byte_array(s): r = [] for c in s: r.append(dbus.Byte(c)) return r def dict_to_txt_array(self, txt_dict): array = [] for k, v in txt_dict.items(): item = '%s=%s' % (k, v) item = item.encode('utf-8') array.append(self.string_to_byte_array(item)) return array def service_resolved_callback(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags): log.debug('Service data for service %s in domain %s on %i.%i:', name, domain, interface, protocol) log.debug('Host %s (%s), port %i, TXT data: %s', host, address, port, self.txt_array_to_dict(txt)) if not self.connected: return bare_name = name if name.find('@') == -1: name = name + '@' + name # we don't want to see ourselves in the list if name != self.name: resolved_info = [(interface, protocol, host, aprotocol, address, int(port))] if name in self.contacts: # Decide whether to try to merge with existing resolved info: old_name, old_domain, old_resolved_info, old_bare_name, _old_txt = self.contacts[name] if name == old_name and domain == old_domain and bare_name == old_bare_name: # Seems similar enough, try to merge resolved info: for i, _info in enumerate(old_resolved_info): # for now, keep a single record for each (interface, protocol) pair # # Note that, theoretically, we could both get IPv4 and # IPv6 aprotocol responses via the same protocol, # so this probably needs to be revised again. if old_resolved_info[i][0:2] == (interface, protocol): log.debug('Deleting resolved info for interface %s', old_resolved_info[i]) del old_resolved_info[i] break resolved_info = resolved_info + old_resolved_info log.debug('Collected resolved info is now: %s', resolved_info) self.contacts[name] = (name, domain, resolved_info, bare_name, txt) self.new_serviceCB(name) else: # remember data # In case this is not our own record but of another # gajim instance on the same machine, # it will be used when we get a new name. self.invalid_self_contact[name] = (name, domain, (interface, protocol, host, aprotocol, address, int(port)), bare_name, txt) # different handler when resolving all contacts def service_resolved_all_callback(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags): if not self.connected: return if name.find('@') == -1: name = name + '@' + name # update TXT data only, as intended according to resolve_all comment old_contact = self.contacts[name] self.contacts[name] = old_contact[0:Constant.TXT] + (txt,) + old_contact[Constant.TXT+1:] def service_added_callback(self): log.debug('Service successfully added') def service_committed_callback(self): log.debug('Service successfully committed') def service_updated_callback(self): log.debug('Service successfully updated') def service_add_fail_callback(self, err): log.debug('Error while adding service. %s', str(err)) if 'Local name collision' in str(err): alternative_name = self.server.GetAlternativeServiceName(self.username) self.name_conflictCB(alternative_name) return self.error_CB(_('Error while adding service. %s') % str(err)) self.disconnect() def server_state_changed_callback(self, state, error): log.debug('server state changed to %s', state) if state == ServerState.RUNNING: self.create_service() elif state in (ServerState.COLLISION, ServerState.REGISTERING): self.disconnect() self.entrygroup.Reset() def entrygroup_state_changed_callback(self, state, error): # the name is already present, so recreate if state == EntryGroup.COLLISION: log.debug('zeroconf.py: local name collision') self.service_add_fail_callback('Local name collision') elif state == EntryGroup.FAILURE: self.disconnect() self.entrygroup.Reset() log.debug('zeroconf.py: ENTRY_GROUP_FAILURE reached(that' ' should not happen)') # make zeroconf-valid names def replace_show(self, show): if show in ['chat', 'online', '']: return 'avail' if show == 'xa': return 'away' return show def avahi_txt(self): return self.dict_to_txt_array(self.txt) def create_service(self): try: if not self.entrygroup: # create an EntryGroup for publishing self.entrygroup = dbus.Interface(self.bus.get_object( DBUS_NAME, self.server.EntryGroupNew()), DBUS_INTERFACE_ENTRY_GROUP) self.entrygroup.connect_to_signal('StateChanged', self.entrygroup_state_changed_callback) txt = {} # remove empty keys for key, val in self.txt.items(): if val: txt[key] = val txt['port.p2pj'] = self.port txt['version'] = 1 txt['txtvers'] = 1 # replace gajim's show messages with compatible ones if 'status' in self.txt: txt['status'] = self.replace_show(self.txt['status']) else: txt['status'] = 'avail' self.txt = txt log.debug('Publishing service %s of type %s', self.name, self.stype) self.entrygroup.AddService(Interface.UNSPEC, Protocol.UNSPEC, dbus.UInt32(0), self.name, self.stype, '', '', dbus.UInt16(self.port), self.avahi_txt(), reply_handler=self.service_added_callback, error_handler=self.service_add_fail_callback) self.entrygroup.Commit(reply_handler=self.service_committed_callback, error_handler=self.entrygroup_commit_error_CB) return True except dbus.DBusException as e: log.debug(str(e)) return False def announce(self): if not self.connected: return False state = self.server.GetState() if state == ServerState.RUNNING: if self.create_service(): self.announced = True return True return False def remove_announce(self): if self.announced is False: return False try: if self.entrygroup.GetState() != EntryGroup.FAILURE: self.entrygroup.Reset() self.entrygroup.Free() # .Free() has mem leaks self.entrygroup._obj._bus = None self.entrygroup._obj = None self.entrygroup = None self.announced = False return True return False except dbus.DBusException: log.debug("Can't remove service. That should not happen") def browse_domain(self, interface, protocol, domain): self.new_service_type(interface, protocol, self.stype, domain, '') def avahi_dbus_connect_cb(self, a, connect, disconnect): if connect != "": log.debug('Lost connection to avahi-daemon') self.disconnect() if self.disconnected_CB: self.disconnected_CB() else: log.debug('We are connected to avahi-daemon') # connect to dbus def connect_dbus(self): try: import dbus # pylint: disable=redefined-outer-name from dbus.mainloop.glib import DBusGMainLoop main_loop = DBusGMainLoop(set_as_default=True) dbus.set_default_main_loop(main_loop) except ImportError: log.debug('Error: python-dbus needs to be installed. No ' 'zeroconf support.') return False if self.bus: return True try: self.bus = dbus.SystemBus() self.bus.add_signal_receiver(self.avahi_dbus_connect_cb, 'NameOwnerChanged', 'org.freedesktop.DBus', arg0='org.freedesktop.Avahi') except Exception as e: # System bus is not present self.bus = None log.debug(str(e)) return False else: return True # connect to avahi def connect_avahi(self): if not self.connect_dbus(): return False if self.server: return True try: self.server = dbus.Interface(self.bus.get_object(DBUS_NAME, DBUS_PATH_SERVER), DBUS_INTERFACE_SERVER) self.server.connect_to_signal('StateChanged', self.server_state_changed_callback) except Exception as e: # Avahi service is not present self.server = None log.debug(str(e)) return False else: return True def connect(self): self.name = self.username + '@' + self.host # service name if not self.connect_avahi(): return False self.connected = True # start browsing if self.domain is None: # Explicitly browse .local self.browse_domain( Interface.UNSPEC, Protocol.UNSPEC, 'local') # Browse for other browsable domains self.domain_browser = dbus.Interface(self.bus.get_object( DBUS_NAME, self.server.DomainBrowserNew( Interface.UNSPEC, Protocol.UNSPEC, '', DomainBrowser.BROWSE, dbus.UInt32(0))), DBUS_INTERFACE_DOMAIN_BROWSER) self.domain_browser.connect_to_signal('ItemNew', self.new_domain_callback) self.domain_browser.connect_to_signal('Failure', self.error_callback) else: self.browse_domain( Interface.UNSPEC, Protocol.UNSPEC, self.domain) return True def disconnect(self): if self.connected: self.connected = False if self.service_browser: try: self.service_browser.Free() except dbus.DBusException as e: log.debug(str(e)) self.service_browser._obj._bus = None self.service_browser._obj = None if self.domain_browser: try: self.domain_browser.Free() except dbus.DBusException as e: log.debug(str(e)) self.domain_browser._obj._bus = None self.domain_browser._obj = None self.remove_announce() self.server._obj._bus = None self.server._obj = None self.server = None self.service_browser = None self.domain_browser = None # refresh txt data of all contacts manually (no callback available) def resolve_all(self): if not self.connected: return False for val in self.contacts.values(): # get txt data from last recorded resolved info # TODO: Better try to get it from last IPv6 mDNS, then last IPv4? ri = val[Constant.RESOLVED_INFO][0] self.server.ResolveService(int(ri[ConstantRI.INTERFACE]), int(ri[ConstantRI.PROTOCOL]), val[Constant.BARE_NAME], self.stype, val[Constant.DOMAIN], Protocol.UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved_all_callback, error_handler=self.error_callback) return True def get_contacts(self): return self.contacts def get_contact(self, jid): if not jid in self.contacts: return None return self.contacts[jid] def update_txt(self, show=None): if show: self.txt['status'] = self.replace_show(show) txt = self.avahi_txt() if self.connected and self.entrygroup: self.entrygroup.UpdateServiceTxt(Interface.UNSPEC, Protocol.UNSPEC, dbus.UInt32(0), self.name, self.stype, '', txt, reply_handler=self.service_updated_callback, error_handler=self.error_callback) return True return False # END Zeroconf gajim-gajim-1.1.3/gajim/common/zeroconf/zeroconf_avahi_const.py000066400000000000000000000033651345766322700246770ustar00rootroot00000000000000# Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from enum import IntEnum DBUS_NAME = "org.freedesktop.Avahi" DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server" DBUS_PATH_SERVER = "/" DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + ".EntryGroup" DBUS_INTERFACE_DOMAIN_BROWSER = DBUS_NAME + ".DomainBrowser" DBUS_INTERFACE_SERVICE_TYPE_BROWSER = DBUS_NAME + ".ServiceTypeBrowser" DBUS_INTERFACE_SERVICE_BROWSER = DBUS_NAME + ".ServiceBrowser" DBUS_INTERFACE_ADDRESS_RESOLVER = DBUS_NAME + ".AddressResolver" DBUS_INTERFACE_HOST_NAME_RESOLVER = DBUS_NAME + ".HostNameResolver" DBUS_INTERFACE_SERVICE_RESOLVER = DBUS_NAME + ".ServiceResolver" DBUS_INTERFACE_RECORD_BROWSER = DBUS_NAME + ".RecordBrowser" class ServerState(IntEnum): INVALID = 0 REGISTERING = 1 RUNNING = 2 COLLISION = 3 FAILURE = 4 class EntryGroup(IntEnum): UNCOMMITED = 0 REGISTERING = 1 ESTABLISHED = 2 COLLISION = 3 FAILURE = 4 class DomainBrowser(IntEnum): BROWSE = 0 BROWSE_DEFAULT = 1 REGISTER = 2 REGISTER_DEFAULT = 3 BROWSE_LEGACY = 4 class Protocol(IntEnum): UNSPEC = -1 INET = 0 INET6 = 1 class Interface(IntEnum): UNSPEC = -1 gajim-gajim-1.1.3/gajim/common/zeroconf/zeroconf_bonjour.py000066400000000000000000000355311345766322700240570ustar00rootroot00000000000000# Copyright (C) 2006 Stefan Bethge # Copyright (C) 2006 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging import select import re from gajim.common.i18n import _ from gajim.common.zeroconf.zeroconf import Constant log = logging.getLogger('gajim.c.z.zeroconf_bonjour') try: import pybonjour except ImportError: pass resolve_timeout = 1 class Zeroconf: def __init__(self, new_serviceCB, remove_serviceCB, name_conflictCB, disconnected_CB, error_CB, name, host, port): self.stype = '_presence._tcp' self.port = port # listening port that gets announced self.username = name self.host = host self.txt = {} # service data # XXX these CBs should be set to None when we destroy the object # (go offline), because they create a circular reference self.new_serviceCB = new_serviceCB self.remove_serviceCB = remove_serviceCB self.name_conflictCB = name_conflictCB self.disconnected_CB = disconnected_CB self.error_CB = error_CB self.contacts = {} # all current local contacts with data self.connected = False self.announced = False self.invalid_self_contact = {} self.resolved_contacts = {} self.resolved = [] self.queried = [] def browse_callback(self, sdRef, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain): log.debug('Found service %s in domain %s on %i(type: %s).', serviceName, replyDomain, interfaceIndex, regtype) if not self.connected: return if errorCode != pybonjour.kDNSServiceErr_NoError: log.debug('Error in browse_callback: %s', str(errorCode)) return if not flags & pybonjour.kDNSServiceFlagsAdd: self.remove_service_callback(serviceName) return try: # asynchronous resolving resolve_sdRef = None resolve_sdRef = pybonjour.DNSServiceResolve( 0, interfaceIndex, serviceName, regtype, replyDomain, self.service_resolved_callback) while not self.resolved: ready = select.select([resolve_sdRef], [], [], resolve_timeout) if resolve_sdRef not in ready[0]: log.info('Resolve timed out') break pybonjour.DNSServiceProcessResult(resolve_sdRef) else: self.resolved.pop() except pybonjour.BonjourError as error: log.info('Error when resolving DNS: %s', error) finally: if resolve_sdRef: resolve_sdRef.close() def remove_service_callback(self, name): log.info('Service %s disappeared.', name) if not self.connected: return if name != self.name: for key in list(self.contacts.keys()): if self.contacts[key][Constant.NAME] == name: del self.contacts[key] self.remove_serviceCB(key) return def txt_array_to_dict(self, txt): if isinstance(txt, pybonjour.TXTRecord): items = txt._items else: items = pybonjour.TXTRecord.parse(txt)._items return dict((v[0], v[1]) for v in items.values()) @staticmethod def _parse_name(fullname): log.debug('Parse name: %s', fullname) # TODO: do proper decoding... escaping = {r'\.': '.', r'\032': ' ', r'\064': '@', } # Split on '.' but do not split on '\.' result = re.split(r'(? # Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Alex Podaras # Stéphan Kochen # Copyright (C) 2005-2006 Dimitur Kirov # Nikos Kouremenos # Copyright (C) 2006 Junglecow J # Copyright (C) 2006-2007 Travis Shirk # Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 James Newton # Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject from gajim.common import helpers from gajim.common import app from gajim.common.i18n import _ from gajim import gtkgui_helpers from gajim import dialogs from gajim import dataforms_widget from gajim import gui_menu_builder from gajim.gtk.dialogs import ConfirmationDialog from gajim.gtk.dialogs import ConfirmationDialogDoubleRadio from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import InputDialog #---------- ManageProxiesWindow class -------------# class ManageProxiesWindow: def __init__(self, transient_for=None): self.xml = gtkgui_helpers.get_gtk_builder('manage_proxies_window.ui') self.window = self.xml.get_object('manage_proxies_window') self.window.set_transient_for(transient_for) self.proxies_treeview = self.xml.get_object('proxies_treeview') self.proxyname_entry = self.xml.get_object('proxyname_entry') self.proxytype_combobox = self.xml.get_object('proxytype_combobox') self.init_list() self.block_signal = False self.xml.connect_signals(self) self.window.show_all() # hide the BOSH fields by default self.show_bosh_fields() def show_bosh_fields(self, show=True): if show: self.xml.get_object('boshuri_entry').show() self.xml.get_object('boshuri_label').show() self.xml.get_object('boshuseproxy_checkbutton').show() else: cb = self.xml.get_object('boshuseproxy_checkbutton') cb.hide() cb.set_active(True) self.on_boshuseproxy_checkbutton_toggled(cb) self.xml.get_object('boshuri_entry').hide() self.xml.get_object('boshuri_label').hide() def fill_proxies_treeview(self): model = self.proxies_treeview.get_model() model.clear() iter_ = model.append() model.set(iter_, 0, _('None')) for p in app.config.get_per('proxies'): iter_ = model.append() model.set(iter_, 0, p) def init_list(self): self.xml.get_object('remove_proxy_button').set_sensitive(False) self.proxytype_combobox.set_sensitive(False) self.xml.get_object('proxy_table').set_sensitive(False) model = Gtk.ListStore(str) self.proxies_treeview.set_model(model) col = Gtk.TreeViewColumn('Proxies') self.proxies_treeview.append_column(col) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', 0) self.fill_proxies_treeview() self.xml.get_object('proxytype_combobox').set_active(0) def on_manage_proxies_window_destroy(self, widget): window = app.get_app_window('AccountsWindow') if window is not None: window.update_proxy_list() del app.interface.instances['manage_proxies'] def on_add_proxy_button_clicked(self, widget): model = self.proxies_treeview.get_model() proxies = app.config.get_per('proxies') i = 1 while 'proxy' + str(i) in proxies: i += 1 iter_ = model.append() model.set(iter_, 0, 'proxy' + str(i)) app.config.add_per('proxies', 'proxy' + str(i)) self.proxies_treeview.set_cursor(model.get_path(iter_)) def on_remove_proxy_button_clicked(self, widget): sel = self.proxies_treeview.get_selection() if not sel: return (model, iter_) = sel.get_selected() if not iter_: return proxy = model[iter_][0] model.remove(iter_) app.config.del_per('proxies', proxy) self.xml.get_object('remove_proxy_button').set_sensitive(False) self.block_signal = True self.on_proxies_treeview_cursor_changed(self.proxies_treeview) self.block_signal = False def on_close_button_clicked(self, widget): self.window.destroy() def on_useauth_checkbutton_toggled(self, widget): if self.block_signal: return act = widget.get_active() proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'useauth', act) self.xml.get_object('proxyuser_entry').set_sensitive(act) self.xml.get_object('proxypass_entry').set_sensitive(act) def on_boshuseproxy_checkbutton_toggled(self, widget): if self.block_signal: return act = widget.get_active() proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'bosh_useproxy', act) self.xml.get_object('proxyhost_entry').set_sensitive(act) self.xml.get_object('proxyport_entry').set_sensitive(act) def on_proxies_treeview_cursor_changed(self, widget): #FIXME: check if off proxy settings are correct (see # http://trac.gajim.org/changeset/1921#file2 line 1221 proxyhost_entry = self.xml.get_object('proxyhost_entry') proxyport_entry = self.xml.get_object('proxyport_entry') proxyuser_entry = self.xml.get_object('proxyuser_entry') proxypass_entry = self.xml.get_object('proxypass_entry') boshuri_entry = self.xml.get_object('boshuri_entry') useauth_checkbutton = self.xml.get_object('useauth_checkbutton') boshuseproxy_checkbutton = self.xml.get_object('boshuseproxy_checkbutton') self.block_signal = True proxyhost_entry.set_text('') proxyport_entry.set_text('') proxyuser_entry.set_text('') proxypass_entry.set_text('') boshuri_entry.set_text('') #boshuseproxy_checkbutton.set_active(False) #self.on_boshuseproxy_checkbutton_toggled(boshuseproxy_checkbutton) #useauth_checkbutton.set_active(False) #self.on_useauth_checkbutton_toggled(useauth_checkbutton) sel = widget.get_selection() if sel: (model, iter_) = sel.get_selected() else: iter_ = None if not iter_: self.xml.get_object('proxyname_entry').set_text('') self.xml.get_object('proxytype_combobox').set_sensitive(False) self.xml.get_object('proxy_table').set_sensitive(False) self.block_signal = False return proxy = model[iter_][0] self.xml.get_object('proxyname_entry').set_text(proxy) if proxy == _('None'): # special proxy None self.show_bosh_fields(False) self.proxyname_entry.set_editable(False) self.xml.get_object('remove_proxy_button').set_sensitive(False) self.xml.get_object('proxytype_combobox').set_sensitive(False) self.xml.get_object('proxy_table').set_sensitive(False) else: proxytype = app.config.get_per('proxies', proxy, 'type') self.show_bosh_fields(proxytype == 'bosh') self.proxyname_entry.set_editable(True) self.xml.get_object('remove_proxy_button').set_sensitive(True) self.xml.get_object('proxytype_combobox').set_sensitive(True) self.xml.get_object('proxy_table').set_sensitive(True) proxyhost_entry.set_text(app.config.get_per('proxies', proxy, 'host')) proxyport_entry.set_text(str(app.config.get_per('proxies', proxy, 'port'))) proxyuser_entry.set_text(app.config.get_per('proxies', proxy, 'user')) proxypass_entry.set_text(app.config.get_per('proxies', proxy, 'pass')) boshuri_entry.set_text(app.config.get_per('proxies', proxy, 'bosh_uri')) types = ['http', 'socks5', 'bosh'] self.proxytype_combobox.set_active(types.index(proxytype)) boshuseproxy_checkbutton.set_active( app.config.get_per('proxies', proxy, 'bosh_useproxy')) useauth_checkbutton.set_active( app.config.get_per('proxies', proxy, 'useauth')) self.block_signal = False def on_proxies_treeview_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Delete: self.on_remove_proxy_button_clicked(widget) def on_proxyname_entry_changed(self, widget): if self.block_signal: return sel = self.proxies_treeview.get_selection() if not sel: return (model, iter_) = sel.get_selected() if not iter_: return old_name = model.get_value(iter_, 0) new_name = widget.get_text() if new_name == '': return if new_name == old_name: return config = app.config.get_per('proxies', old_name) app.config.del_per('proxies', old_name) app.config.add_per('proxies', new_name) for option in config: app.config.set_per('proxies', new_name, option, config[option]) model.set_value(iter_, 0, new_name) def on_proxytype_combobox_changed(self, widget): if self.block_signal: return types = ['http', 'socks5', 'bosh'] type_ = self.proxytype_combobox.get_active() self.show_bosh_fields(types[type_] == 'bosh') proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'type', types[type_]) def on_proxyhost_entry_changed(self, widget): if self.block_signal: return value = widget.get_text() proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'host', value) def on_proxyport_entry_changed(self, widget): if self.block_signal: return value = widget.get_text() proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'port', value) def on_proxyuser_entry_changed(self, widget): if self.block_signal: return value = widget.get_text() proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'user', value) def on_boshuri_entry_changed(self, widget): if self.block_signal: return value = widget.get_text() proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'bosh_uri', value) def on_proxypass_entry_changed(self, widget): if self.block_signal: return value = widget.get_text() proxy = self.proxyname_entry.get_text() app.config.set_per('proxies', proxy, 'pass', value) class FakeDataForm(Gtk.Table): """ Class for forms that are in XML format value1 infos in a table {entry1: value1} """ def __init__(self, infos, selectable=False): GObject.GObject.__init__(self) self.infos = infos self.selectable = selectable self.entries = {} self._draw_table() def _draw_table(self): """ Draw the table """ nbrow = 0 if 'instructions' in self.infos: nbrow = 1 self.resize(rows=nbrow, columns=2) label = Gtk.Label(label=self.infos['instructions']) if self.selectable: label.set_selectable(True) self.attach(label, 0, 2, 0, 1, 0, 0, 0, 0) for name in self.infos.keys(): if name in ('key', 'instructions', 'x', 'registered'): continue if not name: continue nbrow = nbrow + 1 self.resize(rows=nbrow, columns=2) label = Gtk.Label(label=name.capitalize() + ':') self.attach(label, 0, 1, nbrow - 1, nbrow, 0, 0, 0, 0) entry = Gtk.Entry() entry.set_activates_default(True) if self.infos[name]: entry.set_text(self.infos[name]) if name == 'password': entry.set_visibility(False) self.attach(entry, 1, 2, nbrow - 1, nbrow, 0, 0, 0, 0) self.entries[name] = entry if nbrow == 1: entry.grab_focus() def get_infos(self): for name in self.entries: self.infos[name] = self.entries[name].get_text() return self.infos class GroupchatConfigWindow: def __init__(self, account, room_jid, form=None): self.account = account self.room_jid = room_jid self.form = form self.remove_button = {} self.affiliation_treeview = {} self.start_users_dict = {} # list at the beginning self.affiliation_labels = {'outcast': _('Ban List'), 'member': _('Member List'), 'owner': _('Owner List'), 'admin':_('Administrator List')} self.xml = gtkgui_helpers.get_gtk_builder('data_form_window.ui', 'data_form_window') self.window = self.xml.get_object('data_form_window') self.window.set_transient_for(app.interface.roster.window) if self.form: config_vbox = self.xml.get_object('config_vbox') self.data_form_widget = dataforms_widget.DataFormWidget(self.form) # hide scrollbar of this data_form_widget, we already have in this # widget sw = self.data_form_widget.xml.get_object( 'single_form_scrolledwindow') sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER) if self.form.title: self.xml.get_object('title_label').set_text(self.form.title) else: self.xml.get_object('title_hseparator').set_no_show_all(True) self.xml.get_object('title_hseparator').hide() self.data_form_widget.show() config_vbox.pack_start(self.data_form_widget, True, True, 0) else: self.xml.get_object('title_label').set_no_show_all(True) self.xml.get_object('title_label').hide() self.xml.get_object('title_hseparator').set_no_show_all(True) self.xml.get_object('title_hseparator').hide() self.xml.get_object('config_hseparator').set_no_show_all(True) self.xml.get_object('config_hseparator').hide() # Draw the edit affiliation list things add_on_vbox = self.xml.get_object('add_on_vbox') for affiliation in self.affiliation_labels: self.start_users_dict[affiliation] = {} hbox = Gtk.HBox(spacing=5) add_on_vbox.pack_start(hbox, False, True, 0) label = Gtk.Label(label=self.affiliation_labels[affiliation]) hbox.pack_start(label, False, True, 0) bb = Gtk.HButtonBox() bb.set_layout(Gtk.ButtonBoxStyle.END) bb.set_spacing(5) hbox.pack_start(bb, True, True, 0) add_button = Gtk.Button(stock=Gtk.STOCK_ADD) add_button.connect('clicked', self.on_add_button_clicked, affiliation) bb.pack_start(add_button, True, True, 0) self.remove_button[affiliation] = Gtk.Button(stock=Gtk.STOCK_REMOVE) self.remove_button[affiliation].set_sensitive(False) self.remove_button[affiliation].connect('clicked', self.on_remove_button_clicked, affiliation) bb.pack_start(self.remove_button[affiliation], True, True, 0) # jid, reason, nick, role liststore = Gtk.ListStore(str, str, str, str) self.affiliation_treeview[affiliation] = Gtk.TreeView(liststore) self.affiliation_treeview[affiliation].get_selection().set_mode( Gtk.SelectionMode.MULTIPLE) self.affiliation_treeview[affiliation].connect('cursor-changed', self.on_affiliation_treeview_cursor_changed, affiliation) renderer = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('JID'), renderer) col.add_attribute(renderer, 'text', 0) col.set_resizable(True) col.set_sort_column_id(0) self.affiliation_treeview[affiliation].append_column(col) if affiliation == 'outcast': renderer = Gtk.CellRendererText() renderer.set_property('editable', True) renderer.connect('edited', self.on_cell_edited) col = Gtk.TreeViewColumn(_('Reason'), renderer) col.add_attribute(renderer, 'text', 1) col.set_resizable(True) col.set_sort_column_id(1) self.affiliation_treeview[affiliation].append_column(col) elif affiliation == 'member': renderer = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('Nick'), renderer) col.add_attribute(renderer, 'text', 2) col.set_resizable(True) col.set_sort_column_id(2) self.affiliation_treeview[affiliation].append_column(col) renderer = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('Role'), renderer) col.add_attribute(renderer, 'text', 3) col.set_resizable(True) col.set_sort_column_id(3) self.affiliation_treeview[affiliation].append_column(col) sw = Gtk.ScrolledWindow() sw.add(self.affiliation_treeview[affiliation]) add_on_vbox.pack_start(sw, True, True, 0) con = app.connections[self.account] con.get_module('MUC').get_affiliation(self.room_jid, affiliation) self.xml.connect_signals(self) self.window.connect('delete-event', self.on_cancel_button_clicked) self.window.show_all() def on_cancel_button_clicked(self, *args): if self.form: con = app.connections[self.account] con.get_module('MUC').cancel_config(self.room_jid) self.window.destroy() def on_cell_edited(self, cell, path, new_text): model = self.affiliation_treeview['outcast'].get_model() new_text = new_text iter_ = model.get_iter(path) model[iter_][1] = new_text def on_add_button_clicked(self, widget, affiliation): if affiliation == 'outcast': title = _('Banning…') #You can move '\n' before user@domain if that line is TOO BIG prompt = _('Whom do you want to ban?\n\n') elif affiliation == 'member': title = _('Adding Member…') prompt = _('Whom do you want to make a member?\n\n') elif affiliation == 'owner': title = _('Adding Owner…') prompt = _('Whom do you want to make an owner?\n\n') else: title = _('Adding Administrator…') prompt = _('Whom do you want to make an administrator?\n\n') prompt += _('Can be one of the following:\n' '1. user@domain/resource (only that resource matches).\n' '2. user@domain (any resource matches).\n' '3. domain/resource (only that resource matches).\n' '4. domain (the domain itself matches, as does any user@domain,\n' 'domain/resource, or address containing a subdomain).') def on_ok(jid): if not jid: return model = self.affiliation_treeview[affiliation].get_model() model.append((jid, '', '', '')) InputDialog(title, prompt, ok_handler=on_ok) def on_remove_button_clicked(self, widget, affiliation): selection = self.affiliation_treeview[affiliation].get_selection() model, paths = selection.get_selected_rows() row_refs = [] for path in paths: row_refs.append(Gtk.TreeRowReference.new(model, path)) for row_ref in row_refs: path = row_ref.get_path() iter_ = model.get_iter(path) model.remove(iter_) self.remove_button[affiliation].set_sensitive(False) def on_affiliation_treeview_cursor_changed(self, widget, affiliation): self.remove_button[affiliation].set_sensitive(True) def affiliation_list_received(self, users_dict): """ Fill the affiliation treeview """ for jid in users_dict: affiliation = users_dict[jid]['affiliation'] if affiliation not in self.affiliation_labels.keys(): # Unknown affiliation or 'none' affiliation, do not show it continue self.start_users_dict[affiliation][jid] = users_dict[jid] tv = self.affiliation_treeview[affiliation] model = tv.get_model() reason = users_dict[jid].get('reason', '') nick = users_dict[jid].get('nick', '') role = users_dict[jid].get('role', '') model.append((jid, reason, nick, role)) def on_data_form_window_destroy(self, widget): del app.interface.instances[self.account]['gc_config'][self.room_jid] def on_ok_button_clicked(self, widget): if self.form: form = self.data_form_widget.data_form con = app.connections[self.account] con.get_module('MUC').set_config(self.room_jid, form) for affiliation in self.affiliation_labels: users_dict = {} actual_jid_list = [] model = self.affiliation_treeview[affiliation].get_model() iter_ = model.get_iter_first() # add new jid while iter_: jid = model[iter_][0] actual_jid_list.append(jid) if jid not in self.start_users_dict[affiliation] or \ (affiliation == 'outcast' and 'reason' in self.start_users_dict[ affiliation][jid] and self.start_users_dict[affiliation][jid]\ ['reason'] != model[iter_][1]): users_dict[jid] = {'affiliation': affiliation} if affiliation == 'outcast': users_dict[jid]['reason'] = model[iter_][1] iter_ = model.iter_next(iter_) # remove removed one for jid in self.start_users_dict[affiliation]: if jid not in actual_jid_list: users_dict[jid] = {'affiliation': 'none'} if users_dict: con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, users_dict) self.window.destroy() #---------- RemoveAccountWindow class -------------# class RemoveAccountWindow: """ Ask for removing from gajim only or from gajim and server too and do removing of the account given """ def on_remove_account_window_destroy(self, widget): if self.account in app.interface.instances: del app.interface.instances[self.account]['remove_account'] def on_cancel_button_clicked(self, widget): self.window.destroy() def __init__(self, account): self.account = account xml = gtkgui_helpers.get_gtk_builder('remove_account_window.ui') self.window = xml.get_object('remove_account_window') active_window = app.app.get_active_window() self.window.set_transient_for(active_window) self.remove_and_unregister_radiobutton = xml.get_object( 'remove_and_unregister_radiobutton') self.window.set_title(_('Removing %s account') % self.account) xml.connect_signals(self) self.window.show_all() def on_remove_button_clicked(self, widget): def remove(): if self.account in app.connections and \ app.connections[self.account].connected and \ not self.remove_and_unregister_radiobutton.get_active(): # change status to offline only if we will not remove this JID from # server app.connections[self.account].change_status('offline', 'offline') if self.remove_and_unregister_radiobutton.get_active(): if not self.account in app.connections: ErrorDialog( _('Account is disabled'), _('To unregister from a server, account must be ' 'enabled.'), transient_for=self.window) return if not app.connections[self.account].password: def on_ok(passphrase, checked): if passphrase == -1: # We don't remove account cause we canceled pw window return app.connections[self.account].password = passphrase app.connections[self.account].unregister_account( self._on_remove_success) dialogs.PassphraseDialog( _('Password Required'), _('Enter your password for account %s') % self.account, _('Save password'), ok_handler=on_ok, transient_for=self.window) return app.connections[self.account].unregister_account( self._on_remove_success) else: self._on_remove_success(True) if self.account in app.connections and \ app.connections[self.account].connected: ConfirmationDialog( _('Account "%s" is connected to the server') % self.account, _('If you remove it, the connection will be lost.'), on_response_ok=remove, transient_for=self.window) else: remove() def on_remove_responce_ok(self, is_checked): if is_checked[0]: self._on_remove_success(True) def _on_remove_success(self, res): # action of unregistration has failed, we don't remove the account # Error message is send by connect_and_auth() if not res: ConfirmationDialogDoubleRadio( _('Connection to server %s failed') % self.account, _('What would you like to do?'), _('Remove only from Gajim'), _('Don\'t remove anything. I\'ll try again later'), on_response_ok=self.on_remove_responce_ok, is_modal=False, transient_for=self.window) return # Close all opened windows app.interface.roster.close_all(self.account, force=True) if self.account in app.connections: app.connections[self.account].disconnect(on_purpose=True) app.connections[self.account].cleanup() del app.connections[self.account] app.logger.remove_roster(app.get_jid_from_account(self.account)) app.config.del_per('accounts', self.account) del app.interface.instances[self.account] if self.account in app.nicks: del app.interface.minimized_controls[self.account] del app.nicks[self.account] del app.block_signed_in_notifications[self.account] del app.groups[self.account] app.contacts.remove_account(self.account) del app.gc_connected[self.account] del app.automatic_rooms[self.account] del app.to_be_removed[self.account] del app.newly_added[self.account] del app.sleeper_state[self.account] del app.last_message_time[self.account] del app.status_before_autoaway[self.account] del app.gajim_optional_features[self.account] del app.caps_hash[self.account] if len(app.connections) >= 2: # Do not merge accounts if only one exists app.interface.roster.regroup = app.config.get('mergeaccounts') else: app.interface.roster.regroup = False app.interface.roster.setup_and_draw_roster() app.app.remove_account_actions(self.account) gui_menu_builder.build_accounts_menu() window = app.get_app_window('AccountsWindow') if window is not None: window.remove_account(self.account) self.window.destroy() class ManageSoundsWindow: def __init__(self, transient): self._builder = gtkgui_helpers.get_gtk_builder( 'manage_sounds_window.ui') self.window = self._builder.get_object('manage_sounds_window') self.window.set_transient_for(transient) self.sound_button = self._builder.get_object('filechooser') filter_ = Gtk.FileFilter() filter_.set_name(_('All files')) filter_.add_pattern('*') self.sound_button.add_filter(filter_) filter_ = Gtk.FileFilter() filter_.set_name(_('Wav Sounds')) filter_.add_pattern('*.wav') self.sound_button.add_filter(filter_) self.sound_button.set_filter(filter_) self.sound_tree = self._builder.get_object('sounds_treeview') self._fill_sound_treeview() self._builder.connect_signals(self) self.window.show_all() def _on_row_changed(self, model, path, iter_): sound_event = model[iter_][3] app.config.set_per('soundevents', sound_event, 'enabled', bool(model[path][0])) app.config.set_per('soundevents', sound_event, 'path', model[iter_][2]) def _on_toggle(self, cell, path): if self.sound_button.get_filename() is None: return model = self.sound_tree.get_model() model[path][0] = not model[path][0] def _fill_sound_treeview(self): model = self.sound_tree.get_model() model.clear() # NOTE: sounds_ui_names MUST have all items of # sounds = app.config.get_per('soundevents') as keys sounds_dict = { 'attention_received': _('Attention Message Received'), 'first_message_received': _('First Message Received'), 'next_message_received_focused': _('Next Message Received Focused'), 'next_message_received_unfocused': _('Next Message Received Unfocused'), 'contact_connected': _('Contact Connected'), 'contact_disconnected': _('Contact Disconnected'), 'message_sent': _('Message Sent'), 'muc_message_highlight': _('Group Chat Message Highlight'), 'muc_message_received': _('Group Chat Message Received'), } for config_name, sound_name in sounds_dict.items(): enabled = app.config.get_per('soundevents', config_name, 'enabled') path = app.config.get_per('soundevents', config_name, 'path') model.append((enabled, sound_name, path, config_name)) def _on_cursor_changed(self, treeview): model, iter_ = treeview.get_selection().get_selected() path_to_snd_file = helpers.check_soundfile_path(model[iter_][2]) if path_to_snd_file is None: self.sound_button.unselect_all() else: self.sound_button.set_filename(path_to_snd_file) def _on_file_set(self, button): model, iter_ = self.sound_tree.get_selection().get_selected() filename = button.get_filename() directory = os.path.dirname(filename) app.config.set('last_sounds_dir', directory) path_to_snd_file = helpers.strip_soundfile_path(filename) # set new path to sounds_model model[iter_][2] = path_to_snd_file # set the sound to enabled model[iter_][0] = True def _on_clear(self, *args): self.sound_button.unselect_all() model, iter_ = self.sound_tree.get_selection().get_selected() model[iter_][2] = '' model[iter_][0] = False def _on_play(self, *args): model, iter_ = self.sound_tree.get_selection().get_selected() snd_event_config_name = model[iter_][3] helpers.play_sound(snd_event_config_name) def _on_destroy(self, *args): self.window.destroy() window = app.get_app_window('Preferences') if window is not None: window.sounds_preferences = None gajim-gajim-1.1.3/gajim/conversation_textview.py000066400000000000000000001463461345766322700220370ustar00rootroot00000000000000# Copyright (C) 2005 Norman Rasmussen # Copyright (C) 2005-2006 Alex Mauer # Travis Shirk # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2008 Jonathan Schleifer # Julien Pivotto # Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import time import os import queue import urllib import logging from calendar import timegm from gi.repository import Gtk from gi.repository import Pango from gi.repository import GObject from gi.repository import GLib from gajim.common import app from gajim.common import helpers from gajim.common import i18n from gajim.common.i18n import _ from gajim.common.helpers import AdditionalDataDict from gajim.common.fuzzyclock import FuzzyClock from gajim.common.const import StyleAttr from gajim.htmltextview import HtmlTextView from gajim.gtk import util from gajim.gtk.util import load_icon from gajim.gtk.util import get_cursor from gajim.gtk.emoji_data import emoji_pixbufs from gajim.gtk.emoji_data import is_emoji from gajim.gtk.emoji_data import get_emoji_pixbuf NOT_SHOWN = 0 ALREADY_RECEIVED = 1 SHOWN = 2 log = logging.getLogger('gajim.conversation_textview') def is_selection_modified(mark): name = mark.get_name() return name in ('selection_bound', 'insert') def has_focus(widget): return widget.get_state_flags() & Gtk.StateFlags.FOCUSED == \ Gtk.StateFlags.FOCUSED class TextViewImage(Gtk.Image): def __init__(self, anchor, text): super(TextViewImage, self).__init__() self.anchor = anchor self._selected = False self._disconnect_funcs = [] self.connect('parent-set', self.on_parent_set) self.set_tooltip_markup(text) self.anchor.plaintext = text def _get_selected(self): parent = self.get_parent() if not parent or not self.anchor: return False buffer_ = parent.get_buffer() position = buffer_.get_iter_at_child_anchor(self.anchor) bounds = buffer_.get_selection_bounds() return bounds and position.in_range(*bounds) def get_state(self): parent = self.get_parent() if not parent: return Gtk.StateType.NORMAL if self._selected: if has_focus(parent): return Gtk.StateType.SELECTED return Gtk.StateType.ACTIVE return Gtk.StateType.NORMAL def _update_selected(self): selected = self._get_selected() if self._selected != selected: self._selected = selected self.queue_draw() def _do_connect(self, widget, signal, callback): id_ = widget.connect(signal, callback) def disconnect(): widget.disconnect(id_) self._disconnect_funcs.append(disconnect) def _disconnect_signals(self): for func in self._disconnect_funcs: func() self._disconnect_funcs = [] def on_parent_set(self, widget, old_parent): parent = self.get_parent() if not parent: self._disconnect_signals() return if isinstance(parent, Gtk.EventBox): parent = parent.get_parent() if not parent: self._disconnect_signals() return self._do_connect(parent, 'style-set', self.do_queue_draw) self._do_connect(parent, 'focus-in-event', self.do_queue_draw) self._do_connect(parent, 'focus-out-event', self.do_queue_draw) textbuf = parent.get_buffer() self._do_connect(textbuf, 'mark-set', self.on_mark_set) self._do_connect(textbuf, 'mark-deleted', self.on_mark_deleted) def do_queue_draw(self, *args): self.queue_draw() return False def on_mark_set(self, buf, iterat, mark): self.on_mark_modified(mark) return False def on_mark_deleted(self, buf, mark): self.on_mark_modified(mark) return False def on_mark_modified(self, mark): if is_selection_modified(mark): self._update_selected() class ConversationTextview(GObject.GObject): """ Class for the conversation textview (where user reads already said messages) for chat/groupchat windows """ __gsignals__ = dict(quote=( GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, # return value (str, ) # arguments )) def __init__(self, account, used_in_history_window=False): """ If used_in_history_window is True, then we do not show Clear menuitem in context menu """ GObject.GObject.__init__(self) self.used_in_history_window = used_in_history_window self.line = 0 self.message_list = [] self.corrected_text_list = {} self.fc = FuzzyClock() # no need to inherit TextView, use it as atrribute is safer self.tv = HtmlTextView(account) self.tv.connect_tooltip(self.query_tooltip) # set properties self.tv.set_border_width(1) self.tv.set_accepts_tab(True) self.tv.set_editable(False) self.tv.set_cursor_visible(False) self.tv.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) self.tv.set_left_margin(2) self.tv.set_right_margin(2) self._buffer = self.tv.get_buffer() self.handlers = {} self.image_cache = {} self.xep0184_marks = {} # self.last_sent_message_id = msg_stanza_id self.last_sent_message_id = None # last_received_message_id[name] = (msg_stanza_id, line_start_mark) self.last_received_message_id = {} self.autoscroll = True # connect signals id_ = self.tv.connect('populate_popup', self.on_textview_populate_popup) self.handlers[id_] = self.tv id_ = self.tv.connect('button_press_event', self.on_textview_button_press_event) self.handlers[id_] = self.tv self.account = account self.cursor_changed = False self.last_time_printout = 0 self.encryption_enabled = False style = self.tv.get_style_context() style.add_class('gajim-conversation-font') buffer_ = self.tv.get_buffer() end_iter = buffer_.get_end_iter() buffer_.create_mark('end', end_iter, False) self.tagIn = buffer_.create_tag('incoming') color = app.css_config.get_value( '.gajim-incoming-nickname', StyleAttr.COLOR) self.tagIn.set_property('foreground', color) desc = app.css_config.get_font('.gajim-incoming-nickname') self.tagIn.set_property('font-desc', desc) self.tagOut = buffer_.create_tag('outgoing') color = app.css_config.get_value( '.gajim-outgoing-nickname', StyleAttr.COLOR) self.tagOut.set_property('foreground', color) desc = app.css_config.get_font('.gajim-outgoing-nickname') self.tagOut.set_property('font-desc', desc) self.tagStatus = buffer_.create_tag('status') color = app.css_config.get_value( '.gajim-status-message', StyleAttr.COLOR) self.tagStatus.set_property('foreground', color) desc = app.css_config.get_font('.gajim-status-message') self.tagStatus.set_property('font-desc', desc) self.tagInText = buffer_.create_tag('incomingtxt') color = app.css_config.get_value( '.gajim-incoming-message-text', StyleAttr.COLOR) if color: self.tagInText.set_property('foreground', color) desc = app.css_config.get_font('.gajim-incoming-message-text') self.tagInText.set_property('font-desc', desc) self.tagOutText = buffer_.create_tag('outgoingtxt') color = app.css_config.get_value( '.gajim-outgoing-message-text', StyleAttr.COLOR) if color: self.tagOutText.set_property('foreground', color) desc = app.css_config.get_font('.gajim-outgoing-message-text') self.tagOutText.set_property('font-desc', desc) colors = app.config.get('gc_nicknames_colors') colors = colors.split(':') for i, color in enumerate(colors): tagname = 'gc_nickname_color_' + str(i) tag = buffer_.create_tag(tagname) tag.set_property('foreground', color) self.tagMarked = buffer_.create_tag('marked') color = app.css_config.get_value( '.gajim-highlight-message', StyleAttr.COLOR) self.tagMarked.set_property('foreground', color) self.tagMarked.set_property('weight', Pango.Weight.BOLD) textview_icon = buffer_.create_tag('textview-icon') textview_icon.set_property('rise', Pango.units_from_double(-4.45)) tag = buffer_.create_tag('time_sometimes') tag.set_property('foreground', 'darkgrey') #Pango.SCALE_SMALL tag.set_property('scale', 0.8333333333333) tag.set_property('justification', Gtk.Justification.CENTER) tag = buffer_.create_tag('small') #Pango.SCALE_SMALL tag.set_property('scale', 0.8333333333333) tag = buffer_.create_tag('restored_message') color = app.css_config.get_value('.gajim-restored-message', StyleAttr.COLOR) tag.set_property('foreground', color) self.tv.create_tags() tag = buffer_.create_tag('bold') tag.set_property('weight', Pango.Weight.BOLD) tag = buffer_.create_tag('italic') tag.set_property('style', Pango.Style.ITALIC) tag = buffer_.create_tag('underline') tag.set_property('underline', Pango.Underline.SINGLE) buffer_.create_tag('focus-out-line', justification=Gtk.Justification.CENTER) self.displaymarking_tags = {} tag = buffer_.create_tag('xep0184-received') tag.set_property('foreground', '#73d216') # One mark at the begining then 2 marks between each lines size = app.config.get('max_conversation_lines') size = 2 * size - 1 self.marks_queue = queue.Queue(size) self.allow_focus_out_line = True # holds a mark at the end of --- line self.focus_out_end_mark = None self.just_cleared = False def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): window = widget.get_window(Gtk.TextWindowType.TEXT) x_pos, y_pos = self.tv.window_to_buffer_coords( Gtk.TextWindowType.TEXT, x_pos, y_pos) if Gtk.MINOR_VERSION > 18: iter_ = self.tv.get_iter_at_position(x_pos, y_pos)[1] else: iter_ = self.tv.get_iter_at_position(x_pos, y_pos)[0] for tag in iter_.get_tags(): tag_name = tag.get_property('name') if tag_name == 'focus-out-line': tooltip.set_text(_( 'Text below this line is what has ' 'been said since the\nlast time you paid attention to this ' 'group chat')) return True if getattr(tag, 'is_anchor', False): text = getattr(tag, 'title', False) if text: if len(text) > 50: text = text[:47] + '…' tooltip.set_text(text) window.set_cursor(get_cursor('HAND2')) self.cursor_changed = True return True if tag_name in ('url', 'mail', 'xmpp', 'sth_at_sth'): window.set_cursor(get_cursor('HAND2')) self.cursor_changed = True return False try: text = self.corrected_text_list[tag_name] tooltip.set_markup(text) return True except KeyError: pass if self.cursor_changed: window.set_cursor(get_cursor('XTERM')) self.cursor_changed = False return False def del_handlers(self): for i in self.handlers: if self.handlers[i].handler_is_connected(i): self.handlers[i].disconnect(i) del self.handlers self.tv.destroy() def update_tags(self): self.tagIn.set_property('foreground', app.css_config.get_value('.gajim-incoming-nickname', StyleAttr.COLOR)) self.tagOut.set_property('foreground', app.css_config.get_value('.gajim-outgoing-nickname', StyleAttr.COLOR)) self.tagStatus.set_property('foreground', app.css_config.get_value('.gajim-status-message', StyleAttr.COLOR)) self.tagMarked.set_property('foreground', app.css_config.get_value('.gajim-highlight-message', StyleAttr.COLOR)) color = app.css_config.get_value('.gajim-url', StyleAttr.COLOR) self.tv.tagURL.set_property('foreground', color) self.tv.tagMail.set_property('foreground', color) self.tv.tagXMPP.set_property('foreground', color) self.tv.tagSthAtSth.set_property('foreground', color) def scroll_to_end(self, force=False): if self.autoscroll or force: util.scroll_to_end(self.tv.get_parent()) def correct_message(self, correct_id, kind, name): allowed = True if kind == 'incoming': try: if correct_id in self.last_received_message_id[name]: start_mark = self.last_received_message_id[name][1] else: allowed = False except KeyError: allowed = False elif kind == 'outgoing': if self.last_sent_message_id[0] == correct_id: start_mark = self.last_sent_message_id[1] else: allowed = False else: allowed = False if not allowed: log.debug('Message correction not allowed') return None end_mark, index = self.get_end_mark(correct_id, start_mark) if not index: log.debug('Could not find line to correct') return None buffer_ = self.tv.get_buffer() if not end_mark: end_iter = self.tv.get_buffer().get_end_iter() else: end_iter = buffer_.get_iter_at_mark(end_mark) start_iter = buffer_.get_iter_at_mark(start_mark) old_txt = buffer_.get_text(start_iter, end_iter, True) buffer_.delete(start_iter, end_iter) buffer_.delete_mark(start_mark) return index, end_mark, old_txt def add_xep0184_mark(self, id_): if id_ in self.xep0184_marks: return buffer_ = self.tv.get_buffer() buffer_.begin_user_action() self.xep0184_marks[id_] = buffer_.create_mark( None, buffer_.get_end_iter(), left_gravity=True) buffer_.end_user_action() def show_xep0184_ack(self, id_): if id_ not in self.xep0184_marks: return buffer_ = self.tv.get_buffer() buffer_.begin_user_action() if app.config.get('positive_184_ack'): begin_iter = buffer_.get_iter_at_mark(self.xep0184_marks[id_]) buffer_.insert_with_tags_by_name(begin_iter, ' ✓', 'xep0184-received') buffer_.end_user_action() del self.xep0184_marks[id_] def show_focus_out_line(self): if not self.allow_focus_out_line: # if room did not receive focus-in from the last time we added # --- line then do not readd return print_focus_out_line = False buffer_ = self.tv.get_buffer() if self.focus_out_end_mark is None: # this happens only first time we focus out on this room print_focus_out_line = True else: focus_out_end_iter = buffer_.get_iter_at_mark(self.focus_out_end_mark) focus_out_end_iter_offset = focus_out_end_iter.get_offset() if focus_out_end_iter_offset != buffer_.get_end_iter().get_offset(): # this means after last-focus something was printed # (else end_iter's offset is the same as before) # only then print ---- line (eg. we avoid printing many following # ---- lines) print_focus_out_line = True if print_focus_out_line and buffer_.get_char_count() > 0: buffer_.begin_user_action() # remove previous focus out line if such focus out line exists if self.focus_out_end_mark is not None: end_iter_for_previous_line = buffer_.get_iter_at_mark( self.focus_out_end_mark) begin_iter_for_previous_line = end_iter_for_previous_line.copy() # img_char+1 (the '\n') begin_iter_for_previous_line.backward_chars(21) # remove focus out line buffer_.delete(begin_iter_for_previous_line, end_iter_for_previous_line) buffer_.delete_mark(self.focus_out_end_mark) # add the new focus out line end_iter = buffer_.get_end_iter() buffer_.insert(end_iter, '\n' + '―' * 20) end_iter = buffer_.get_end_iter() before_img_iter = end_iter.copy() # one char back (an image also takes one char) before_img_iter.backward_chars(20) buffer_.apply_tag_by_name('focus-out-line', before_img_iter, end_iter) self.allow_focus_out_line = False # update the iter we hold to make comparison the next time self.focus_out_end_mark = buffer_.create_mark(None, buffer_.get_end_iter(), left_gravity=True) buffer_.end_user_action() self.scroll_to_end() def clear(self, tv=None): """ Clear text in the textview """ buffer_ = self.tv.get_buffer() start, end = buffer_.get_bounds() buffer_.delete(start, end) size = app.config.get('max_conversation_lines') size = 2 * size - 1 self.marks_queue = queue.Queue(size) self.focus_out_end_mark = None self.just_cleared = True def visit_url_from_menuitem(self, widget, link): """ Basically it filters out the widget instance """ helpers.launch_browser_mailer('url', link) def on_textview_populate_popup(self, textview, menu): """ Override the default context menu and we prepend Clear (only if used_in_history_window is False) and if we have sth selected we show a submenu with actions on the phrase (see on_conversation_textview_button_press_event) """ separator_menuitem_was_added = False if not self.used_in_history_window: item = Gtk.SeparatorMenuItem.new() menu.prepend(item) separator_menuitem_was_added = True item = Gtk.MenuItem.new_with_mnemonic(_('_Clear')) menu.prepend(item) id_ = item.connect('activate', self.clear) self.handlers[id_] = item if self.selected_phrase: if not separator_menuitem_was_added: item = Gtk.SeparatorMenuItem.new() menu.prepend(item) if not self.used_in_history_window: item = Gtk.MenuItem.new_with_mnemonic(_('_Quote')) id_ = item.connect('activate', self.on_quote) self.handlers[id_] = item menu.prepend(item) _selected_phrase = helpers.reduce_chars_newlines( self.selected_phrase, 25, 2) item = Gtk.MenuItem.new_with_mnemonic( _('_Actions for "%s"') % _selected_phrase) menu.prepend(item) submenu = Gtk.Menu() item.set_submenu(submenu) phrase_for_url = urllib.parse.quote(self.selected_phrase.encode( 'utf-8')) always_use_en = app.config.get('always_english_wikipedia') if always_use_en: link = 'http://en.wikipedia.org/wiki/Special:Search?search=%s'\ % phrase_for_url else: link = 'http://%s.wikipedia.org/wiki/Special:Search?search=%s'\ % (i18n.LANG, phrase_for_url) item = Gtk.MenuItem.new_with_mnemonic(_('Read _Wikipedia Article')) id_ = item.connect('activate', self.visit_url_from_menuitem, link) self.handlers[id_] = item submenu.append(item) item = Gtk.MenuItem.new_with_mnemonic(_('Look it up in _Dictionary')) dict_link = app.config.get('dictionary_url') if dict_link == 'WIKTIONARY': # special link (yeah undocumented but default) always_use_en = app.config.get('always_english_wiktionary') if always_use_en: link = 'http://en.wiktionary.org/wiki/Special:Search?search=%s'\ % phrase_for_url else: link = 'http://%s.wiktionary.org/wiki/Special:Search?search=%s'\ % (i18n.LANG, phrase_for_url) id_ = item.connect('activate', self.visit_url_from_menuitem, link) self.handlers[id_] = item else: if dict_link.find('%s') == -1: # we must have %s in the url if not WIKTIONARY item = Gtk.MenuItem.new_with_label(_( 'Dictionary URL is missing an "%s" and it is not WIKTIONARY')) item.set_property('sensitive', False) else: link = dict_link % phrase_for_url id_ = item.connect('activate', self.visit_url_from_menuitem, link) self.handlers[id_] = item submenu.append(item) search_link = app.config.get('search_engine') if search_link.find('%s') == -1: # we must have %s in the url item = Gtk.MenuItem.new_with_label( _('Web Search URL is missing an "%s"')) item.set_property('sensitive', False) else: item = Gtk.MenuItem.new_with_mnemonic(_('Web _Search for it')) link = search_link % phrase_for_url id_ = item.connect('activate', self.visit_url_from_menuitem, link) self.handlers[id_] = item submenu.append(item) item = Gtk.MenuItem.new_with_mnemonic(_('Open as _Link')) id_ = item.connect('activate', self.visit_url_from_menuitem, link) self.handlers[id_] = item submenu.append(item) menu.show_all() def on_quote(self, widget): self.emit('quote', self.selected_phrase) def on_textview_button_press_event(self, widget, event): # If we clicked on a tagged text do NOT open the standard popup menu # if normal text check if we have sth selected self.selected_phrase = '' # do not move below event button check! if event.button != 3: # if not right click return False x, y = self.tv.window_to_buffer_coords(Gtk.TextWindowType.TEXT, int(event.x), int(event.y)) iter_ = self.tv.get_iter_at_location(x, y) if isinstance(iter_, tuple): iter_ = iter_[1] tags = iter_.get_tags() if tags: # we clicked on sth special (it can be status message too) for tag in tags: tag_name = tag.get_property('name') if tag_name in ('url', 'mail', 'xmpp', 'sth_at_sth'): return True # we block normal context menu # we check if sth was selected and if it was we assign # selected_phrase variable # so on_conversation_textview_populate_popup can use it buffer_ = self.tv.get_buffer() return_val = buffer_.get_selection_bounds() if return_val: # if sth was selected when we right-clicked # get the selected text start_sel, finish_sel = return_val[0], return_val[1] self.selected_phrase = buffer_.get_text(start_sel, finish_sel, True) elif iter_.get_char() and ord(iter_.get_char()) > 31: # we clicked on a word, do as if it's selected for context menu start_sel = iter_.copy() if not start_sel.starts_word(): start_sel.backward_word_start() finish_sel = iter_.copy() if not finish_sel.ends_word(): finish_sel.forward_word_end() self.selected_phrase = buffer_.get_text(start_sel, finish_sel, True) def detect_and_print_special_text(self, otext, other_tags, graphics=True, iter_=None, additional_data=None): """ Detect special text (emots & links & formatting), print normal text before any special text it founds, then print special text (that happens many times until last special text is printed) and then return the index after *last* special text, so we can print it in print_conversation_line() """ if not otext: return if additional_data is None: additional_data = AdditionalDataDict() buffer_ = self.tv.get_buffer() if other_tags: insert_tags_func = buffer_.insert_with_tags_by_name else: insert_tags_func = buffer_.insert # detect_and_print_special_text() is also used by # HtmlHandler.handle_specials() and there tags is Gtk.TextTag objects, # not strings if other_tags and isinstance(other_tags[0], Gtk.TextTag): insert_tags_func = buffer_.insert_with_tags index = 0 # Too many special elements (emoticons, LaTeX formulas, etc) # may cause Gajim to freeze (see #5129). # We impose an arbitrary limit of 100 specials per message. specials_limit = 100 # add oob text to the end oob_url = additional_data.get_value('gajim', 'oob_url') if oob_url is not None: oob_desc = additional_data.get_value('gajim', 'oob_desc', 'URL:') if oob_url != otext: otext += '\n{} {}'.format(oob_desc, oob_url) # basic: links + mail + formatting is always checked (we like that) if app.config.get('emoticons_theme') and graphics: # search for emoticons & urls iterator = app.interface.emot_and_basic_re.finditer(otext) else: # search for just urls + mail + formatting iterator = app.interface.basic_pattern_re.finditer(otext) if iter_: end_iter = iter_ else: end_iter = buffer_.get_end_iter() for match in iterator: start, end = match.span() special_text = otext[start:end] if start > index: text_before_special_text = otext[index:start] if not iter_: end_iter = buffer_.get_end_iter() # we insert normal text if other_tags: insert_tags_func(end_iter, text_before_special_text, *other_tags) else: buffer_.insert(end_iter, text_before_special_text) index = end # update index # now print it self.print_special_text(special_text, other_tags, graphics=graphics, iter_=end_iter, additional_data=additional_data) specials_limit -= 1 if specials_limit <= 0: break # add the rest of text located in the index and after insert_tags_func(end_iter, otext[index:], *other_tags) return end_iter def print_special_text(self, special_text, other_tags, graphics=True, iter_=None, additional_data=None): """ Is called by detect_and_print_special_text and prints special text (emots, links, formatting) """ if additional_data is None: additional_data = AdditionalDataDict() # PluginSystem: adding GUI extension point for ConversationTextview self.plugin_modified = False app.plugin_manager.extension_point('print_special_text', self, special_text, other_tags, graphics, additional_data, iter_) if self.plugin_modified: return tags = [] use_other_tags = True text_is_valid_uri = False is_xhtml_link = None show_ascii_formatting_chars = \ app.config.get('show_ascii_formatting_chars') buffer_ = self.tv.get_buffer() # Detect XHTML-IM link ttt = buffer_.get_tag_table() tags_ = [(ttt.lookup(t) if isinstance(t, str) else t) for t in other_tags] for t in tags_: is_xhtml_link = getattr(t, 'href', None) if is_xhtml_link: break # Check if we accept this as an uri schemes = app.config.get('uri_schemes').split() for scheme in schemes: if special_text.startswith(scheme): text_is_valid_uri = True if iter_: end_iter = iter_ else: end_iter = buffer_.get_end_iter() theme = app.config.get('emoticons_theme') show_emojis = theme and theme != 'font' if show_emojis and graphics and is_emoji(special_text): # it's an emoticon if emoji_pixbufs.complete: # only search for the pixbuf if we are sure # that loading is completed pixbuf = get_emoji_pixbuf(special_text) if pixbuf is None: buffer_.insert(end_iter, special_text) else: pixbuf = pixbuf.copy() anchor = buffer_.create_child_anchor(end_iter) anchor.plaintext = special_text img = Gtk.Image.new_from_pixbuf(pixbuf) img.show() self.tv.add_child_at_anchor(img, anchor) else: # Set marks and save them so we can replace the emojis # once the loading is complete start_mark = buffer_.create_mark(None, end_iter, True) buffer_.insert(end_iter, special_text) end_mark = buffer_.create_mark(None, end_iter, True) emoji_pixbufs.append_marks( self.tv, start_mark, end_mark, special_text) elif special_text.startswith('www.') or \ special_text.startswith('ftp.') or \ text_is_valid_uri and not is_xhtml_link: tags.append('url') elif special_text.startswith('mailto:') and not is_xhtml_link: tags.append('mail') elif special_text.startswith('xmpp:') and not is_xhtml_link: tags.append('xmpp') elif app.interface.sth_at_sth_dot_sth_re.match(special_text) and\ not is_xhtml_link: # it's a JID or mail tags.append('sth_at_sth') elif special_text.startswith('*'): # it's a bold text tags.append('bold') if special_text[1] == '/' and special_text[-2] == '/' and\ len(special_text) > 4: # it's also italic tags.append('italic') if not show_ascii_formatting_chars: special_text = special_text[2:-2] # remove */ /* elif special_text[1] == '_' and special_text[-2] == '_' and \ len(special_text) > 4: # it's also underlined tags.append('underline') if not show_ascii_formatting_chars: special_text = special_text[2:-2] # remove *_ _* else: if not show_ascii_formatting_chars: special_text = special_text[1:-1] # remove * * elif special_text.startswith('/'): # it's an italic text tags.append('italic') if special_text[1] == '*' and special_text[-2] == '*' and \ len(special_text) > 4: # it's also bold tags.append('bold') if not show_ascii_formatting_chars: special_text = special_text[2:-2] # remove /* */ elif special_text[1] == '_' and special_text[-2] == '_' and \ len(special_text) > 4: # it's also underlined tags.append('underline') if not show_ascii_formatting_chars: special_text = special_text[2:-2] # remove /_ _/ else: if not show_ascii_formatting_chars: special_text = special_text[1:-1] # remove / / elif special_text.startswith('_'): # it's an underlined text tags.append('underline') if special_text[1] == '*' and special_text[-2] == '*' and \ len(special_text) > 4: # it's also bold tags.append('bold') if not show_ascii_formatting_chars: special_text = special_text[2:-2] # remove _* *_ elif special_text[1] == '/' and special_text[-2] == '/' and \ len(special_text) > 4: # it's also italic tags.append('italic') if not show_ascii_formatting_chars: special_text = special_text[2:-2] # remove _/ /_ else: if not show_ascii_formatting_chars: special_text = special_text[1:-1] # remove _ _ else: # It's nothing special if use_other_tags: insert_tags_func = buffer_.insert_with_tags_by_name if other_tags and isinstance(other_tags[0], Gtk.TextTag): insert_tags_func = buffer_.insert_with_tags if other_tags: insert_tags_func(end_iter, special_text, *other_tags) else: buffer_.insert(end_iter, special_text) if tags: all_tags = tags[:] if use_other_tags: all_tags += other_tags # convert all names to TextTag all_tags = [(ttt.lookup(t) if isinstance(t, str) else t) for t in all_tags] buffer_.insert_with_tags(end_iter, special_text, *all_tags) if 'url' in tags: puny_text = helpers.puny_encode_url(special_text) if puny_text != special_text: puny_tags = [] if use_other_tags: puny_tags += other_tags if not puny_text: puny_text = _('Invalid URL') puny_tags = [(ttt.lookup(t) if isinstance(t, str) else t) for t in puny_tags] buffer_.insert_with_tags(end_iter, " (%s)" % puny_text, *puny_tags) def print_empty_line(self, iter_=None): buffer_ = self.tv.get_buffer() if not iter_: iter_ = buffer_.get_end_iter() buffer_.insert_with_tags_by_name(iter_, '\n', 'eol') self.just_cleared = False def get_end_mark(self, msg_stanza_id, start_mark): for index, msg in enumerate(self.message_list): if msg[2] == msg_stanza_id and msg[1] == start_mark: try: end_mark = self.message_list[index + 1][1] end_mark_name = end_mark.get_name() except IndexError: # We are at the last message end_mark = None end_mark_name = None log.debug('start mark: %s, end mark: %s, ' 'replace message-list index: %s', start_mark.get_name(), end_mark_name, index) return end_mark, index log.debug('stanza-id not in message list') return None, None def get_insert_mark(self, timestamp): # message_list = [(timestamp, line_start_mark, msg_stanza_id)] # We check if this is a new Message try: if self.message_list[-1][0] <= timestamp: return None, None except IndexError: # We have no Messages in the TextView return None, None # Not a new Message # Search for insertion point for index, msg in enumerate(self.message_list): if msg[0] > timestamp: return msg[1], index # Should not happen, but who knows return None, None def print_conversation_line(self, text, jid, kind, name, tim, other_tags_for_name=None, other_tags_for_time=None, other_tags_for_text=None, subject=None, old_kind=None, xhtml=None, simple=False, graphics=True, displaymarking=None, msg_stanza_id=None, correct_id=None, additional_data=None, encrypted=None): """ Print 'chat' type messages """ if additional_data is None: additional_data = AdditionalDataDict() buffer_ = self.tv.get_buffer() buffer_.begin_user_action() insert_mark = None insert_mark_name = None if kind == 'incoming_queue': kind = 'incoming' if old_kind == 'incoming_queue': old_kind = 'incoming' if not tim: # For outgoing Messages and Status prints tim = time.time() corrected = False if correct_id: try: index, insert_mark, old_txt = \ self.correct_message(correct_id, kind, name) if correct_id in self.corrected_text_list: self.corrected_text_list[msg_stanza_id] = \ self.corrected_text_list[correct_id] + '\n{}' \ .format(GLib.markup_escape_text(old_txt)) del self.corrected_text_list[correct_id] else: self.corrected_text_list[msg_stanza_id] = \ _('Message corrected. Original message:\n{}') \ .format(GLib.markup_escape_text(old_txt)) corrected = True except TypeError: log.debug('Message was not corrected !') if not corrected: # Get insertion point into TextView insert_mark, index = self.get_insert_mark(tim) if insert_mark: insert_mark_name = insert_mark.get_name() log.debug( 'Printed Line: %s, %s, %s, inserted after: %s' ', stanza-id: %s, correct-id: %s', self.line, text, tim, insert_mark_name, msg_stanza_id, correct_id) if not insert_mark: # Texview is empty or Message is new iter_ = buffer_.get_end_iter() # Insert new Line if Textview is not empty if buffer_.get_char_count() > 0 and not corrected: buffer_.insert_with_tags_by_name(iter_, '\n', 'eol') else: iter_ = buffer_.get_iter_at_mark(insert_mark) # Create a temporary mark at the start of the line # with gravity=Left, so it will not move # even if we insert directly at the mark iter temp_mark = buffer_.create_mark('temp', iter_, left_gravity=True) if text.startswith('/me '): direction_mark = i18n.paragraph_direction_mark(str(text[3:])) else: direction_mark = i18n.paragraph_direction_mark(text) # don't apply direction mark if it's status message if kind == 'status': direction_mark = i18n.direction_mark # print the encryption icon if kind in ('incoming', 'outgoing'): self.print_encryption_status(iter_, additional_data) # print the time stamp self.print_time(text, kind, tim, simple, direction_mark, other_tags_for_time, iter_) # If there's a displaymarking, print it here. if displaymarking: self.print_displaymarking(displaymarking, iter_) # kind = info, we print things as if it was a status: same color, ... if kind in ('error', 'info'): kind = 'status' other_text_tag = self.detect_other_text_tag(text, kind) text_tags = [] if other_tags_for_text: text_tags = other_tags_for_text[:] # create a new list if other_text_tag: text_tags.append(other_text_tag) else: # not status nor /me if app.config.get('chat_merge_consecutive_nickname'): if kind != old_kind or self.just_cleared: self.print_name(name, kind, other_tags_for_name, direction_mark=direction_mark, iter_=iter_) else: self.print_real_text(app.config.get( 'chat_merge_consecutive_nickname_indent'), mark=insert_mark, additional_data=additional_data) else: self.print_name(name, kind, other_tags_for_name, direction_mark=direction_mark, iter_=iter_) if kind == 'incoming': text_tags.append('incomingtxt') elif kind == 'outgoing': text_tags.append('outgoingtxt') self.print_subject(subject, iter_=iter_) iter_ = self.print_real_text(text, text_tags, name, xhtml, graphics=graphics, mark=insert_mark, additional_data=additional_data) if corrected: # Show Correction Icon buffer_.create_tag(tag_name=msg_stanza_id) buffer_.insert(iter_, ' ') icon = load_icon('document-edit-symbolic', self.tv, pixbuf=True) buffer_.insert_pixbuf( iter_, icon) tag_start_iter = iter_.copy() tag_start_iter.backward_chars(2) buffer_.apply_tag_by_name(msg_stanza_id, tag_start_iter, iter_) # If we inserted a Line we add a new line at the end if insert_mark: buffer_.insert_with_tags_by_name(iter_, '\n', 'eol') # We delete the temp mark and replace it with a mark # that has gravity=right temp_iter = buffer_.get_iter_at_mark(temp_mark) buffer_.delete_mark(temp_mark) new_mark = buffer_.create_mark( str(self.line), temp_iter, left_gravity=False) if index is None: # New Message self.message_list.append((tim, new_mark, msg_stanza_id)) elif corrected: # Replace the corrected message self.message_list[index] = (tim, new_mark, msg_stanza_id) else: # We insert the message at index self.message_list.insert(index, (tim, new_mark, msg_stanza_id)) if kind == 'incoming': self.last_received_message_id[name] = (msg_stanza_id, new_mark) elif kind == 'outgoing': self.last_sent_message_id = (msg_stanza_id, new_mark) if not insert_mark: if self.autoscroll or kind == 'outgoing': # we are at the end or we are sending something self.scroll_to_end(force=True) self.just_cleared = False buffer_.end_user_action() self.line += 1 return iter_ def get_time_to_show(self, tim, direction_mark=''): """ Get the time, with the day before if needed and return it. It DOESN'T format a fuzzy time """ format_ = '' # get difference in days since epoch (86400 = 24*3600) # number of days since epoch for current time (in GMT) - # number of days since epoch for message (in GMT) diff_day = int(int(timegm(time.localtime())) / 86400 -\ int(timegm(tim)) / 86400) if diff_day == 0.0: day_str = '' else: #%i is day in year (1-365) day_str = i18n.ngettext('Yesterday', '%(nb_days)i days ago', diff_day, {'nb_days': diff_day}, {'nb_days': diff_day}) if day_str: # strftime Windows bug has problems with Unicode # see: http://bugs.python.org/issue8304 if os.name != 'nt': format_ += i18n.direction_mark + day_str + direction_mark + ' ' else: format_ += day_str + ' ' timestamp_str = app.config.get('time_stamp') timestamp_str = helpers.from_one_line(timestamp_str) format_ += timestamp_str tim_format = time.strftime(format_, tim) return tim_format def detect_other_text_tag(self, text, kind): if kind == 'status': return kind if text.startswith('/me ') or text.startswith('/me\n'): return kind def print_encryption_status(self, iter_, additional_data): details = self._get_encryption_details(additional_data) if details is None: # Message was not encrypted if not self.encryption_enabled: return icon = 'channel-insecure-symbolic' color = 'unencrypted-color' tooltip = _('Not encrypted') else: icon = 'channel-secure-symbolic' color = 'encrypted-color' name, fingerprint = details if fingerprint is None: tooltip = name else: tooltip = '%s %s' % (name, fingerprint) temp_mark = self._buffer.create_mark(None, iter_, True) self._buffer.insert(iter_, ' ') anchor = self._buffer.create_child_anchor(iter_) anchor.plaintext = '' self._buffer.insert(iter_, ' ') # Apply mark to vertically center the icon start = self._buffer.get_iter_at_mark(temp_mark) self._buffer.apply_tag_by_name('textview-icon', start, iter_) image = Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.MENU) image.show() image.set_tooltip_text(tooltip) image.get_style_context().add_class(color) self.tv.add_child_at_anchor(image, anchor) @staticmethod def _get_encryption_details(additional_data): name = additional_data.get_value('encrypted', 'name') if name is None: return fingerprint = additional_data.get_value('encrypted', 'fingerprint') return name, fingerprint def print_time(self, text, kind, tim, simple, direction_mark, other_tags_for_time, iter_): local_tim = time.localtime(tim) buffer_ = self.tv.get_buffer() current_print_time = app.config.get('print_time') if current_print_time == 'always' and not simple: timestamp_str = self.get_time_to_show(local_tim, direction_mark) timestamp = time.strftime(timestamp_str, local_tim) timestamp = direction_mark + timestamp + direction_mark if other_tags_for_time: buffer_.insert_with_tags_by_name(iter_, timestamp, *other_tags_for_time) else: buffer_.insert(iter_, timestamp) elif current_print_time == 'sometimes' and not simple: every_foo_seconds = 60 * app.config.get( 'print_ichat_every_foo_minutes') seconds_passed = tim - self.last_time_printout if seconds_passed > every_foo_seconds: self.last_time_printout = tim if app.config.get('print_time_fuzzy') > 0: tim_format = self.fc.fuzzy_time( app.config.get('print_time_fuzzy'), local_tim) else: tim_format = self.get_time_to_show(local_tim, direction_mark) buffer_.insert_with_tags_by_name(iter_, tim_format + '\n', 'time_sometimes') def print_displaymarking(self, displaymarking, iter_): bgcolor = displaymarking.getAttr('bgcolor') or '#FFF' fgcolor = displaymarking.getAttr('fgcolor') or '#000' text = displaymarking.getData() if text: buffer_ = self.tv.get_buffer() tag = self.displaymarking_tags.setdefault(bgcolor + '/' + fgcolor, buffer_.create_tag(None, background=bgcolor, foreground=fgcolor)) buffer_.insert_with_tags(iter_, '[' + text + ']', tag) buffer_.insert_with_tags(iter_, ' ') def print_name(self, name, kind, other_tags_for_name, direction_mark='', iter_=None): if name: name_tags = [] buffer_ = self.tv.get_buffer() if iter_: end_iter = iter_ else: end_iter = buffer_.get_end_iter() if other_tags_for_name: name_tags = other_tags_for_name[:] # create a new list name_tags.append(kind) before_str = app.config.get('before_nickname') before_str = helpers.from_one_line(before_str) after_str = app.config.get('after_nickname') after_str = helpers.from_one_line(after_str) format_ = before_str + name + direction_mark + after_str + ' ' buffer_.insert_with_tags_by_name(end_iter, format_, *name_tags) def print_subject(self, subject, iter_=None): if subject: # if we have subject, show it too! subject = _('Subject: %s\n') % subject buffer_ = self.tv.get_buffer() if iter_: end_iter = iter_ else: end_iter = buffer_.get_end_iter() buffer_.insert(end_iter, subject) self.print_empty_line(end_iter) def print_real_text(self, text, text_tags=None, name=None, xhtml=None, graphics=True, mark=None, additional_data=None): """ Add normal and special text. call this to add text """ if text_tags is None: text_tags = [] if additional_data is None: additional_data = AdditionalDataDict() buffer_ = self.tv.get_buffer() if not mark: iter_ = buffer_.get_end_iter() else: iter_ = buffer_.get_iter_at_mark(mark) if xhtml: try: if name and (text.startswith('/me ') or text.startswith('/me\n')): xhtml = xhtml.replace('/me', '* %s' % (name,), 1) self.tv.display_html(xhtml, self.tv, self, iter_=iter_) return iter_ except Exception as error: log.debug('Error processing xhtml: %s', error) log.debug('with |%s|', xhtml) # /me is replaced by name if name is given if name and (text.startswith('/me ') or text.startswith('/me\n')): text = '* ' + name + text[3:] text_tags.append('italic') # PluginSystem: adding GUI extension point for ConversationTextview self.plugin_modified = False app.plugin_manager.extension_point('print_real_text', self, text, text_tags, graphics, iter_, additional_data) if self.plugin_modified: if not mark: return buffer_.get_end_iter() return buffer_.get_iter_at_mark(mark) if not mark: iter_ = buffer_.get_end_iter() else: iter_ = buffer_.get_iter_at_mark(mark) # detect urls formatting and if the user has it on emoticons return self.detect_and_print_special_text(text, text_tags, graphics=graphics, iter_=iter_, additional_data=additional_data) gajim-gajim-1.1.3/gajim/data/000077500000000000000000000000001345766322700157075ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/000077500000000000000000000000001345766322700200535ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/000077500000000000000000000000001345766322700214775ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/000077500000000000000000000000001345766322700241425ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/buying_groceries.png000066400000000000000000000016151345766322700302120ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 23 2008 12:31:23 +0300ΜtIME 32h&m pHYs  ~gAMA aIDATx}R]HSa>ssm`䌁n ". эٍ"nnL"'?msnn,l}g=?/I9IqH>Q"E0HfzXwp\Eaᨒp4,2]ft"0`0\ өTjsK$2Hrr S !g{{{Co666F|@' XPX,Vxkk!x^doh4- (kD£Rt/$I)@5TT:,」-?T_qX,<99a3ʮ삑fBxC: ĻVD"W}}}@sdtnnn՚ SSSɊc\.iJAoʐC766Jblnn Tl6@*d H<ʎ1fv.BSV`n8EYE@Q.wvv---%+wĪ/|~~~zddQ.p^}(h4saV#vЏ(L& {p×'R`2XbUU1+ vf{<88؆~?80mlԟVi i^zjGGG?\0q|||ek{y?{:!IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/category.png000066400000000000000000000015261345766322700264710ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 26 2008 20:52:41 +0300tIME .=W pHYsԂbgAMA aIDATxڅOQϼx#V !t nL 6t41muwnZh BTml*1X p~w 6=&s|"?bzzznhhS{{f}<88-Zz{{  B>IzdYVՂKKK?oąrT2vՕj%k???!<:fUb2TNOO9|r9e\\\R\ d~ >/x'x@.vvvT o2lBٙ~x5^0!jdm,r:*`{{'bo"J=5ar[,/fUI`0⁢(*LU!|,P׉vju9v `3y'0%H$AtZ} @a$Q<-[1TDDKU Td2z &%Izff.O4T4@@tuu:왱Gy=Ͻf  {N8,9 hA_ p#:::LmnnSikk㗗AAbͬp+D"!R|E"G! @˷\~+,Ȋ+!q RybYM8H ,,࢘6 n:8-A֏C_aV*bd,$*?%u>KKPmm߿70v>3pqq1\z92@ՂX__? q>{ tttryQ4` @;ƐpHyASW^~b对Lqqq"""*** c/X3qh/CJy_ 3ħƱ(2鳱02?y䖐,0N:*)) [` 0^YaКNpyN ;7._ W\vh͛7?~ ''p.e|3N?xΝ;7PTTT]ҥK@:rHߏen4u'=}j֍oDw~^~}--- {'&~>z7_q Jb2f$;;IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/cooking.png000066400000000000000000000017551345766322700263110ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 6 2006 13:11:59 +0300z~||\y!0 ÌnTVfwtNO{Z\.78ph|u7d.%N_}#s_ߺVZezzz*L!3Y] RG2~))<Lf|S@O?oo OR8 'đɹSKϽrB,;<4Tf#4{Lyx0>w|.""%CG ض *`H 'TAm;{9NcY@͖ U5QWk]>)Ja~RSd˃B]'K R{MOETDT"!hHq@ rfm Qģ'4ĎM~BoxX:.)8VIHy)"?̅56v0x1& :FqDB`Ŧ080lOQh#P7B0Hy&}păg6A ~V[-lvm2._*c,Vo5>=w?lUeQUqﳸ‰]8=ԳpTO,|5⁐H؊ ҩĕM{F}xmoT3dnUw{^1V5v3&g31M^^QUZua|jv؈w?B,IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/doing_maintenance.png000066400000000000000000000016751345766322700303230ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 4 2008 15:29:42 +0300(qtIME :"(i pHYsiTSgAMA aIDATxڍS]HQ?͑tM b5M7hEXSV`A=$AKL!ƆTf:&ۜߙT^;M"4K ozzzW_# EEE񻺺<1[.].h4.++kkhh%333ZX,~‚3N'h4HKK;\RRR{fmh4qmXjj3~+~=X*Tf`w0Vkjj#""lbNׯP(JeȈKI vX,q ggg=EEEMx:1X%`\Q&f,攔ɤEU@=55ullll.5iqsj]p %ol&OD=\7+5e8r*ew+ 9B Āղ> ={dA Šq81n.ɹ@E4P>퇮< "Ba&r .ͷs{sh^gn@m\A^bf "H/6xm]#_Ms)F:511\&4|>+䃰($*87;/7,XXIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/doing_the_dishes.png000066400000000000000000000016241345766322700301520ustar00rootroot00000000000000PNG  IHDRatIME1^P; pHYsiTSgAMA a#IDATxڍYhQ4͞fԦ[iR[lj+Ѻhu QAEE}v{Q|pyPDARj7bS-6iӘ4M2i23 ^8^=pZ1jرy[SER4 N@i)͕۫eF=9FBq<"N!1BeCAfA+;=G;j.Ψ4${튉d֮C|R> }Y 9km}b]໿cQ}n}Uek GR'&\t亽K[6y{緺ߢ ܼq }Ԏ`=gG FFߵg`RrN풫 V7`:'.$ aY׿-T6[]\Wb^ :x:Ti2,dz6 rڵO`1a t$%s 8i) &39J吋IRd4A@c RᙟY3R>b*^|M&(~MMH |o>y\6$qyxǎ8 } Ƞ/"aCϓ^V1oѕYbphZELRo!:ˊ"фP=^/lжp@H+-9V(|H(h:k!'H$(~qKoeE8 hDgǾ z6%bt"61[+׿AO( 8SJUvMIz!i愴tWog0.XfIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/doing_the_laundry.png000066400000000000000000000014501345766322700303460ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 7 2008 12:15:41 +0300)S_tIME +7ɶ pHYsiTSgAMA aIDATxڕMh@3d7V⊈RPJ=bAQAzЋ*Ux,ED(AwziK_:wCdO04pA'ּtqdߢǕrrmW*k&[MWxm.}Mbh;|w/q-v~ceC.jE~}8ZPloeNڃbSVkAH)(M))QÏg4f_LEhLKZjFF#mdpH~ibjy5/Čх!"tE A*HiѢM-F&7(4〢9V^3z>T>ss^>u:8SعzT*]T*5N_r%PV]͸  P\P`J%wX\xq8RTbxI?l#( Kb1ZYYdB4ϗ6n" Fyh4z#)g\͖pݷP: q<;͖/VE(@<yPlnn`DH$2ø0t:lWض\T^/Ad2Y,|>rqr lx<`l-4^ީT*1].G ϘL&j6Kz= ~ĎqjV `^`IbTvfL&7z K,WNCIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/running_an_errand.png000066400000000000000000000017241345766322700303450ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2008 13:47:28 +0300&;htIME  )ӉE pHYs  ~gAMA a-IDATxڍ]l k3v_g9MEGT_pzV "9 7 "B$BԅDpGV#m{֪~t?33xv \x'3[6yz: kzkјOF+g1<vRG֮Bϵ$ pXtv`/1E 0x늒׍[Xnna!ʁݲ t+lFޗ:n v#06+X.\Cen9'޾-4:WpEhO.~sj`"XT`y8{8}d?2x7oE(3XZ_S\N>d iƎm,I|5a_[Q$ak R P[4U]-ajww(P?tcu:8^lV6o58ὰ[XVg "'>G#@a"@o||8*Y*דIJ4Ec"*eH<|],慥hZ +%qk*=f#rCLʞɬ:^tՔHjJy>@|- ?ͿVXa4sHٷ~5f(KƄIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/doing_chores/walking_the_dog.png000066400000000000000000000015731345766322700300030ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2008 14:25:16 +0300itIME !r pHYs  ~gAMA aIDATxڥRMOQ=Lg2mZ H E(DD;… #$n1$&ug4 .P@> vfҖi} (s;硏8xSIy>}Muw 5[Vͭjs@ݼ Z>VCazp۠ |C!2 :ppEGkHL/A(gQ氃at("9lņL&c^ $G;N]+Ecv1lr &ȝbXldp9>ak:N&a4 RY#q86M`brr2ւ=@QeX r9f "89L#jʶ:JJ22>5@ NKM.$EDzJ$()4o(R7<xs,,)z^UMAI)i lj{!,’ouzE ߲1TZjNPbӿV /w<9|i% I'#$ MzlDH]DS/ZRD"Krt ,&џTS*$a2I;GK(%)#_zl($鼗|Kfb`5H2,TR#}v=/ .7d*.v6IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/drinking/000077500000000000000000000000001345766322700233045ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/drinking/category.png000066400000000000000000000013021345766322700256230ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 23 2008 13:18:35 +0300[tIME  1KF pHYs  ~gAMA aIDATxڅMoQg~1 ib acYNm¿PbBHpWII ֘Še!$&Hmf/L :gy̔3i4ˊ`d_q8"iđytZ !^۵W>9bQ]\oRA>NSY؊bf/՚=(VO[-5c\DX;:rY 8G2 x1:^wJE\`͍\.ܦGn}n7!Ǖ)z3ՒLvtEӼͭht KQIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/drinking/having_a_beer.png000066400000000000000000000016121345766322700265630ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 6 2006 10:43:18 +0300itIME 6 $u pHYs'dgAMA aIDATxu]HSaƟs6ù Ӽ".#@Z)DY^TJv>vv{N/8y`mno [՞(W ##.lZs+Ǐs|08U8R[Q05C[Z[𪪡 ̄"t3 *##<ڇ׆al37;nLMO!NO/*)FqY)$!LF$s(z<&Mf|/A BN~Njb[ill|uA%k 01,Mg@nK;777F".Y-tuHhl, +RK@ЉV#u8je66JqRIRN46iI*RqQQAQun;Oz6+hH X,kf-\61r }k𦧧z%M.S9\jBӑe΀iYMjb:::P.ήdVbfG-PdX$Yĸ<;wWֻ/{yiP&YB+ܣao:V?/Y\I IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/drinking/having_coffee.png000066400000000000000000000016261345766322700266020ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 6 2006 11:42:56 +0300HitIME 7 : pHYsiTSgAMA aIDATxڍR]HSa~s|/=<.[[[kRA"N6n)2LFDԕjPv""tuu}.F+C\. ;<888<77 (Q^oZ'Fid4P.qfse,[ZZȍ~l2:K6\AVW7%Kժ $N{ H\u!Tó  ̉C֯S+UX,8w#va\&d(9 hD  O@4€kUIjWVܽ8uf9`9&FR d8 3ғ RJxPMC@ p!^D"OE%%`6ceA*ht=fzv@撈ǁ9<4 6@^t:ݪt9jǨh4WY2KdY|>vPxL&:H`~ >zO r CVȾfe>zG#%`\~ėfl2I4-t}$ Ȏy ;EXM.:{6s}I5 T[yX+Jd߂$m܄T\x96/* jI \JSZaMT]ڗUോ9bD43_it0K |qôoMr]31&~C'kD\2xC>v hd`(jB#NEg tͬ` ~9 g" u\QvɢjC:8V54_Gw0ׅD&ygOU|s9'׆Q`zixZkDVTxoH5Q5oGV!y7N^-S='>MWd۟of{H 0Z|6 &$6j69+ P2qvoϝRF^1 x2Tp< Vc7tt~DF"Z`[32GU9䐝}nq0GIvoA)H7Ҭ|-E"č»Ŭ|\:IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/eating/having_a_snack.png000066400000000000000000000016121345766322700264070ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 11 2008 15:19:45 +0300kctIME 8jE pHYs  ~gAMA aIDATxڍ[H߾ݝsñ97,-e{DODTK^QRfT>AD̖2m7m|[]r^:բ^~>;"{Ŀn:)SCx&r#~\.󌋁Vo緶ի;5_PQxV^kT˘xj'q|RPw=e!y$(Kd(cFhؠ}2 b8 2.UU$b oFk;EUю)UiG=䓅uHfG,~oG %l7h 5  dRV\RUfqd $MT_,'`^\<^Lwul8J&"aG)Epz}#sͻu["ۅAUip󖐵RP( Gelooæ7Sd>*JeZK-EWT!CsNvvR>+xfH -3_:;uFr$y,6XpcQѐL8,'u5R(\'(L'"PB!߻cg۞vr^U]HKUEDc92eL慃n5c&IL~p}Z0XCIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/eating/having_breakfast.png000066400000000000000000000015141345766322700267530ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 11 2008 17:21:36 +0300_/YtIME E6x pHYs  ~gAMA aIDATxڅS]HQ=w:kh EЛA HOA>Tc=DATEPTIA`&ijϝݙ]a?޹sϹ GD|ji^UǎʣRs‡n~{o,/|V&:Ypָd w sa?NBYLLZ H.Ս: A%$JF>zoӅ`݃Gz~_0HvªR&"|x3JiЩM DMx, ,C 'fM BYJ zYsGU Uբ.ԙ+VcʓIwj^R2?@ YA`Eա(* #_/J:! !ɊUD I@eAhmei\\FNKiP688Q8aD$5"~ba*[Г>*|y:0-o3΃[^o⫵m@iv> 2A ֛Yr^0`]c'.PH#44lN*)/7j.@kyٓ;vlo>aZU #EܢzX.冗پBK**BĠǫIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/eating/having_dinner.png000066400000000000000000000017111345766322700262670ustar00rootroot00000000000000PNG  IHDRatEXtCopyrightCopyright 2006LF+tEXtCreation Time 12 2008 11:32:24 +03003縟tIME  !(< pHYs.#.#x?vgAMA aIDATxڥSOq}t:XR6hM:@`D"=g5&^hԛ=F A1"""tu$Ƹ|}OjTUX5$D:/vmNs]ʹP3`mx#2wt_ W@<|RkK_`1PR2)fqn޳^GO<|GmP>0AfAfbD=i4G-)J 68wy"az \Y%CAD0ds8"z޵CV3 $ÏcJ0 @,tp!ihmvCPcL4tv5gIMb&‚3W _O7)P2p$$CF! 0uQ3*0 f39X呈Cc&ŗ7Ø- @D"񏥥Zh"hJDAV"µf H@oNDk TT<'oXTJGf,"NeiLpKZ^I0i#v_]{Zl4SXJY7Z PT׬_ /ݺ̷H>Mv~RNgEf^LVV8+ɒxyއ}^`1 l6f˲Fٝi$}zGxwCs|QQhs]\|FM?$0եs[Qr&>R)EQ^YYbK_xnn_F(ݿuEpo^ {^8x `r* 'J"3*Fe.ҕ[W) Wϼ{ fP% BuL "96,!&s9;UM,dRJMd^O"[puDaE` Hz$ߧݖЮayL!yf}zUUQcHK"8AF:;)j#m0AF%ȏ$"9Z7s ġ*~wBc7r\aMWmu CQ"k8q>M7ZpRMeHd<І2 xˀwJM|M/?tJ "4[m*- ^Cc~+G=R<33+HxBex!:,qَkz[Tڅ A&ADPDEV rnv^^m؟oMNaDyv:%_~>IY/М yT6X-~IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/exercising/000077500000000000000000000000001345766322700236375ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/exercising/category.png000066400000000000000000000016201345766322700261610ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2008 15:31:23 +0300tIME -#Ie pHYs  ~gAMA aIDATxڍRYHQξ8NX.劥ecQb AHAAHSCDKs[ѓED EfFآ89Φ3үQ-t>s1C @.XtP1p;ۨ:+\(CɖNݱS( I[ {l6\< {a6*Q5AXj x476+z>gŧ }TCIzpg֝. #&iOPnފE=gwbB4gtܳQh!e+rLU%C}H}wQcSEUԮTA%d5x.n=KQg7jhV4eW]D-F="RA|Ъ4tl.tVio&ݞf|'= .7O˳1Qn#<Y.H1#f '0\"b 26go,..z|>qvwwt>+&8YxAh"&P*RT\.Z-JـʺK?CvpNMMA @$^Sb1)~1??/ϬyuÙdn566  A,DVWWiٛJ}}vɺ W3XLp\5s$IR T*B.{{{3P(Rtv{>,!<;{Ggff@j&qo,,,t`qfT#9Z[[7"aݎ?Fӓd{uc2|>J4B2BRykIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/exercising/dancing.png000066400000000000000000000016751345766322700257610ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 6 2008 12:00:27 +0300ctIME 9j pHYs  d_gAMA aIDATxڕ[Lg/m- )RF E 1%c… ,cndż/Ƌye[ hF=tH DRK8;48c9]gd5_bMDYlœ#^%+Dk`U/6_kٜf6bWSY$-+H N!_J_Ҩ7:W=Fp{{k=iF#T98RkIl6|z|@}#I7YI I~z^\{)/XJ\ˇ(/b$!t>gՐGF66U)F&Vgoz_cxADXĭ'74>}ͨ*/ #)w9Y ff߾aL -մM ]BZś B @0pqr1x)볲p JHng620nI-$?>~uDo='.".e"^fPbG3l۲,??x\~fx':y;#RxKRSҋ-˿Xپ~2m3cNIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/exercising/jogging.png000066400000000000000000000011611345766322700257700ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 12 2008 15:43:00 +0300͏tIME 5.: pHYs  ~gAMA aIDATxc` 4$HJHݰ~7< !|򞃓<3.gJ!>HkCﲪ ¢b֠cĦʕ+B3L'$,pLæ W $$$XAw֜F@Ojqmsk7o+k6k̝;7aeeii~o6Q ?(DO =_0~>^QQQ#3&Co^]pjtu8'';###ys?;٘z^yΝc +an5np1Nqq=yauVq,p(/KW>i0* y:~Z4wvw ٙ?|>zPFN^bɥײIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/exercising/playing_sports.png000066400000000000000000000015761345766322700274330ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 12 2008 16:06:42 +0300{"DtIME .Ғ pHYs  ~gAMA aIDATxuSKKQf2jIHZ(D]$4K 7;Rt&tP\C`7MA_T#QszΡ-™;3|}*guuu5mllt]R[[k[[[y/=,_:[0u=}}}?!//777WvM}tt S  3})EUru9_ܾQ]+'~qgF|UefWf&.Nm;g^zざiIEt7)>l-;;7"ϼÇ_k(2g{)E @eo;S>J 2}r뺌OBx JJv5ǃ4E %-dX|gaab~UBQs35u#'6_VV=yw=0>˶9s- #"'Nd~i?ןťuIzjއ/_fDV4O ظJvn17瓏]RQ93͙3G{i39ĺreVMǦ%86?6W'# l|Ίp:8i/D>&.j !pL{}ϯkV̎0`bf~☑ov.&/~?)KfQY;/?aQIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/exercising/swimming.png000066400000000000000000000016041345766322700262000ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 14 2008 13:26:11 +0300|tIME 5B<& pHYsiTSgAMA aIDATxڅSmHSQ~wtCY!iίMg.?!F%ba )"H2~a`f"MMS0E\~Pz}9}s('dJUl\S?(Э*ﻟx*fhRf6٩(Rq"/./]Bh*"Pm+Osv%:Ԧ9PQG8D0kteӹ1@h]njӵZV.1 P'^Y`0y`:$=1[ƶ* 8Zpˬ઻zotch3g,v~;=`z4 7ajSZm>DO/"RX'+4XOD86k!I'`}zlM ʆ Hh<H6( b gȨ! ?A 0pȇzR$u#r>ת$ʘT?ZS00uqڼv&F">"KbJ,Hɜ5ŌJ®ng4-Kޓ&T O? CS~ׇ//h_"d*h>Lq{ C2 '!r w)tUXȘi8;|^qkVȨA?6y_&aPECgt̂E1QIY/Aƌ_>KcZֹy{v7mB`$mIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/exercising/working_out.png000066400000000000000000000015161345766322700267170ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 14 2008 13:47:23 +0300ttIME  0: pHYs  ~gAMA aIDATxeSMoRQQhBg,.%&&"M\jbܸ7r]c\.]YM&mP iPڔF<"d޽o̙s$[>N`0VIT[[[?QM9\.Kwgbb#Oggg4772 V/?Z366NS{zzJp.fMd5>c^]]^?nu$ mZ__/rUmZF}4;pZ lll?<T*$]6GX,n`}X&It9A|FkEqjttq"#N @ w70m\!QDi_ Bl4q Ed h4jLO3Z TEL&ʈyb@$R K:v?J}h4Rl|fvH X#TwW|V(0 ZcB p,"2ɉTz\TX,/`ƪ@ d*J]^ ~e撹 K`0O[U\krRL&Su>_G a\8_aETu>iIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/grooming/000077500000000000000000000000001345766322700233205ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/grooming/at_the_spa.png000066400000000000000000000021671345766322700261430ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2006 14:37:42 +0300W tIME  42ڝ pHYs  d_gAMA aIDATxeSmLwzܕzjAeAdN&9q/eٲ,q.ms3?d%.F Q3nAY Nm[--wmc>}_~_ɓpH% 孖?nt`5 MAf8'ZWb׮4hJI""k0$'EzΜ P K,Ԇ"lHOHւwfsR2>(,6}9Uatex~e֔US3ӓZ!'3I):CYL{f:UP}yo?5 X^rNXqAr:`gڎo LދkmKtUDA/\.ɕevq?3^fIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/grooming/brushing_teeth.png000066400000000000000000000012311345766322700270350ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 15 2008 15:13:51 +0300H褷tIME 6Ӈ\ pHYsiTSgAMA aIDATxS=Q=olL4* hcam,4m B!`a( [ʐfE̗_$dfv&盈vxq{Z^{Rv(ۢ($m6jzR<,;⯓Fr95Lb:b0X,a}~[Umv]4Mƛ|>g Xl6^1kZたpvⴓm#"!N)ɠP(Fʱ̲(1@RE6cEQ.Yp]=1gZtـo8%.őBH>~P0Ҵu>O؆ux@9$jԥXDh ͘cX:HAeeXEޘkی(No7G$)DX y+|V}rDڐ!("QGy=0sWo=}(44IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/grooming/category.png000066400000000000000000000017651345766322700256540ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2008 20:08:43 +0300b*tIME * Zn pHYs  ~gAMA aNIDATxڕKhW4W3#YǖRm%RA" V4!&)w R7B.Nl &T!귕رi$4=\Hý9|p.>}<>/gL [/Hݩ Օ#uXCAʡE>46k㉬>:{  zHUTT D?y;W,Vs./if1/v~?@@*^CLl*>KY@f$ՌaG40<O/A$I24wLi667AȲ^oMK0ןMG0[M&B(% }4ST%//HĪ8X]Jfs_j||KيQ/tZqqY"pM8tvvh4hٷ/|Gp/v݆M|<l>y[H711044~b$ ￑z0vѺT`RR|e1066y J{{{WGGnO kx IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/grooming/getting_a_haircut.png000066400000000000000000000013671345766322700275150ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 20 2008 03:40:31 +0300?rtIME6'u pHYs  ~gAMA aOIDATxc`@n a 0#0x 6llvF5z< OlWWׅaz1dX..sonu쬬xqqk;ρ_̄uѱMPPP&73[66`!i \\j:nϟ }Aƍۼyxɲ g1l}ׯqnee厛7o:zL?~23?ly xxNʱ""mq"6 ca d~]o#˳2_mxxi23@g&d?43#oߖ&&<Y1V8IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/grooming/shaving.png000066400000000000000000000012611345766322700254650ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 25 2008 14:32:54 +0300FtIME %: pHYsiTSgAMA a IDATxڍSMRa>p!h_%k#?pV0jMLލ& ?66&AZF$*KJqlz Hve~A T*T(!Ulӽw~Ӟ1@ HP( kڋ}+F LS2J%rl.W**HPłB 9[؇ 00N{te&%l2jnr b1*yOha@>8N7MN%IV\h4X,j x0Jһ@]PV+rL#`1Dp8$;UZOQaxF ߽ҧإ9IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/grooming/taking_a_bath.png000066400000000000000000000020701345766322700266000ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2006 14:37:42 +0300W tIME 9ɱH pHYs  d_gAMA aIDATxmS[Lg~m)@[J R *&+QႨ[ݹ%KeYv41sB\& tn]iCˡh -?vFM|=o-(g)2Jmkl<299w;б %fA̩#BEHw(S&;g ֳϾoZ2oA B g@Z`waDč+_tt~wFڣ+V~׎oP^)X r' d5u ƝH}EͶ#huV_K(yR$qݟquҾqmA7l Rd&RD&. (!o,_Z]_Vx؊  䋉ݩ@g aZ"{'fO+((6~R;םaL#3t-6 ;DyX(41 !w.ݦT$WoTT{Zqrӽ8 oDѮu@ br{- w&܍?bWWbrS{1>B4 .YܱpaAéX]KꥏE_%>z5y?,MD)Nbx)5 -S qo̼/<bl;IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/grooming/taking_a_shower.png000066400000000000000000000014311345766322700271710ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 25 2008 15:21:38 +0300fyLtIME  9G+ pHYsiTSgAMA aqIDATxKSaǟ9.7̦*K؏f!$Xa."*"rD02!"YczBh:hIsgl̝]}o}y^?vIhcn2i"RQ(ycVm"r=<~NFR&j-9 okݻ{"LW1_uyOm?/,/|tiggq"Dn3ׇ^`0HMDQ(L^t-,]{(  le<ǡ?`s>eZ{+og8"\:X I2ăt~[7o RoXeUiN{ZZv9UUAĀ( `J reYi~h T-/D hJRp:U RcO`c!8'^?j1 "R@T.gӁJ4wD)Ҁۢ ĭDnJ NFh4 ODO1ykrVʙzuڿH-+ F&r9R 4*,LZ(bC (PUz,@Cp3(&-xo.ò‘g&pw3P"Ц%xP*fw߻MNJhq)VN`) %_ 6^]ss_Q;] Cfwcą.?~t4f}/T$i֪\tjhzw] |IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/000077500000000000000000000000001345766322700233015ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/inactive/category.png000066400000000000000000000017251345766322700256310ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 11 2008 11:47:57 +0300zywtIME Mq pHYsiTSgAMA a-IDATx}mLUi mE q2l95K&`,FbddH/.٦_ܗ}Zbf b`t:cӸp6`@-Ж_O.%ܗ^0v{2w^sc<4Ù?|Xbr曚F}`w#J>yTe'dDZtV(ÁV,*9e/<\SʤP3 4}^]_Eb+Jcliabʵ6LTWTt͒y9&eśIpKf[^-A!EGkR~7̝0ęUSc^HI rI?G>1ސEm&O/W;dJl$ts~ yRҩIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/day_off.png000066400000000000000000000011151345766322700254140ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 1 2008 12:26:43 +0300etIME  Vj pHYs  ~gAMA aIDATxڭQKKQ>s,ǑR@Jhc&0H~k[@?Ev[آ퀉2hZqgwEPr|34.CZ#9W,%"C;L`_P~Ϊsp[[Wtw&x3R-KΦlGEԧ[ꝛ5{ ɤe *ߐni}t-1GiՑ6'MK)WgݑF;:323S7+ݟ]+ y*aa1ƥ/M.૫nn%Im[Q^MCgf3QcR%t $pGxo@m8uYaʟ?a.{AJ`Izѻ&* VwU"[aSb\ X$KJlwDSNjFe:G-s.]8'5a *(Ԥî}}࣠/S.w}ek5lRVj[ brAˆNyĢ\+A95E­op+L,\gB6O2+b}@ qSEz}Ġ_:1d0=orJ~5w<~|љ ,Xw/#IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/hiding.png000066400000000000000000000013601345766322700252510ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 16 2008 09:23:25 +0300|tIME 0&ޫM pHYs  ~gAMA aHIDATxڕSkQ&nGmP/& ^rГxj[D/МՋśKx xrBI a+.ӏӬ '4@vߺB#oSJ3-2i>jo[iTMr#kAݜlhWT^!clz?:&ڛ ð_=W-]A cv^6v~00bsͼVw=&/pSƯ7}).(.P\N6k>P1Ԛ.lt (focBuJL r(4ǨnD)abT1Eh+v?%c~߫ɚyI(ul1VEhÈ:Иu26 ݁me8udad&)TⰭ_[L&G̒ؑJȆ w;RLBfp?0+@Hh=HOhF^^ S5J w[/ϙ(}c)e B`<IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/on_vacation.png000066400000000000000000000016251345766322700263130ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 23 2008 14:20:35 +0300stIME  !-q% pHYs  ~gAMA aIDATx}]HSaǟsv:m95m*V~䴅 Ԙ%AAEE]D7AwA] M-4 ˏc157snsv>vJA}E)nl3x-ckAyWDfz tr?\ $L" BF9:ۜzkmK1Џ!*OǙ7JQr"89\B`!>)vm2T)eZ(OB*M:*nE_§)fJMw^WBF $c8kzeɦMt<͘L^&AnY }8S ! | )F٫VXbk^b2T 688 (*wga P4R-r<v6Y!Es7.ڭ0y Y.!F7P؇+MZFܩɂt03b jVu bP*a1=o (S+& F޾T^՚ SǸ/>Ĵ% |OA5\mԗSy'  ܗp xVw$qqw=%[f?ģ2+ϱC_jw)m?Edf^kyTM(׷';0ڈ|̷dJJNyG*Ržq?.~*Z;z/&]FDzhIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/praying.png000066400000000000000000000015621345766322700254640ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 31 2008 12:06:41 +0300o1OtIME  P pHYs  d_gAMA aIDATxڅ]Haͦ:3Mԕ2oA# (L~+:: 4H3M3+i ge4mo}ðv'ǡR,. ,PB܆~f1¸9IM*w3e fNV[#\+7R_pd6"E۱$an$gwO]ь%^?;s]P]+E&߸k.~NIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/scheduled_holiday.png000066400000000000000000000012771345766322700274670ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 22 2008 13:34:51 +0300T,tIME  "\M pHYsaa?igAMA aIDATxc`T Ue5eϚZrq)ŻWoxYel_}$l,-. fS,4+(k.TUy͋+.˱q()*թDտ>*+gffn!n_}+3+oZ*9pcsDxxxS9SoX3;|&-8)WO?>HǪ&)[YMKo?;~'-~ O]<"o>|.)a,G>z R0p6OOL^W?# /g@x HwFݟ/n=oRÂmn+?>~x:T4k &8*:.r f$yK(")|1& եʄ H*6Sbݸ#ʢݷ @I²"b\"%?}xߖk\͡=IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/sleeping.png000066400000000000000000000017451345766322700256240ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 22 2007 14:02:43 +0300bptIME  * @ pHYs  ~gAMA a=IDATxMR[LSY]Ŷʣ)lR F!Q3$cbH0j CMf CQ|QQDDh R,g-SқsZ{7d27͛A~#uπ\ \n7lFFAx{և*e6:#KxmmD&|) \طيmY K֙ӧ oJX*sB%DD)Ρլbnmg[\TnV6cnd//gU6#3Zn!8"7.5odtCmmy&GT URP,|yPRޫm),]% W_ł"ke t?yZ&/:\P뽣 sZoyG=+\pmˮ)wIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/inactive/thinking.png000066400000000000000000000017071345766322700256270ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2006 14:27:25 +0300eZtIME  $[ pHYs  d_gAMA a IDATxڅ{HQǿw.mjsԞQYiT[=(ITPYу"{SVR҃b-5[ss?wS|8s/1mkB&8&.Vy\n첷V<&zYep!H68BTg=.1'uY,Ècz d2Eؠ^Vr qr !/Fg[Q)Oh fQQQ2R3`eEp`/A>55 5Oȟ[*Yp$g ֿVdb6[ޭ)rjKT#գk2 bunDWzuAl橒2dmX̲cXQK7s|M n,L mB4lBNTV#;[Ѯ$FBY?#2PmϜ*hQ5Wo*n60&NV . Aq&hDY r ] caV#kj.12)UU!^dDž-5:%x\oG >h^u3xTWDz+<10*-|zΨ$poG6ŀy'Gdzo0*Yx=\Oџ xhFXGb87v{?Lr+IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/000077500000000000000000000000001345766322700233105ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/category.png000066400000000000000000000015071345766322700256360ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 11 2008 12:32:58 +0300StIME !:He pHYs  ~gAMA aIDATxڅR]HQ>lZaE/+RA/==A$R[($`hZϬL>D{r{ ,4" qe'Z(fTWMUg/PDz"0ϋR!\ qo+uUWpN;/\77ʱ1G} dc7[ZFff8+& MTOox,k Ue%-e 4" 4LcSa& 7Ma/԰61Fg6ҧu]vmzG/T8g4YSdvU3ⴋBܵ{WŴci-km}isʊ5I:Kn1?dfJ>S7rNp:eäEXTd֒J/"уFыjP=EešE%6i2̚lnBm_sי`Dց{=s]3$r2\,))񖗗_x5DQG2Ͷwzzaaa!N= -99*Nacҥ6C;2mxoU {:Ά\}{`ހ%m]B#O⛈xV*j'FV˦ EjBAWk'\2ΘjK}+775n,1^?Dp+?R_ ӣx5D@>aHR]]u̩cO+>;Te9 }p~ |E"pu][͛ 8Բ΃7ސ1yyyz}x& HVT*Ur)񢻧ς e?\tL*" b1vC׃bLkd2"HًA8.1HD8;I 6O6tT`nnn#?B!Kގ!++ '(///vKR"GImPL&OE'"### +䊈;I FlJLHI{_ eӁh&Ki0 Ì/p jH8QG(Uұ7c%^@IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/going_out.png000066400000000000000000000014311345766322700260070ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 22 2008 14:00:00 +0300WG[tIME  !V pHYsiTSgAMA aqIDATxڥMOQ߹ѡ40`hDLL [WnvtaaԽ$"he0Rj[3svIINrr{{3~J|UU`sض(~ߴyG(bN4(B7 #0s7+JGYFHScrtV*A0ԅ*NBN:kTPS3حf٤RH؛X1>ԇB(du?fFVN=KӤ1`R(O`ށIhFܺ,WEgX8ܸSr\9MЃ{ H"<` 1H@/Ŝ26T\O䁃_dKgP`]\A B@F,$|v k-# k{潵%|波h/G D,hL }. _瓊h_d.R(!2)/x-p:?|Wu#dZê1$ZNVO,NL&#ﮁTIc d*tEƇ_\ܩJ{zK@?Vwip5^fEIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/partying.png000066400000000000000000000017361345766322700256620ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 6 2008 12:00:27 +0300ctIME   pHYs  d_gAMA a7IDATxukLgoEEeCve]$0"}qY~03YB>m[Ö.RqZAҖЖv*Y6|=9ϫgn;f_KX}_*LH.gĆj#c=ouX[IM~NQGۮg myfRG S;[e1^ eV&MZ}n":ov+G *,Kb1ѿ@Q6 ?.a'{UUurs0c<]OXIV''k;Nuե%[K0crJG"aA,dF3*+Ga:`vNmSءY>_csUnt"2nKXy4Xe-f)%R JvLnrg Wfa '٭4"tŠϑQ*P6I #a3r, U7_̭1GzJd:zF;NPi t,JKV|uR zv_k)VYX¾taك|gW&}ocv{p4j?AX%4ӱ| ֔# !MSj /92x MܬRMeV)\s-s+eW b>8;9gXשp~i8$Sp=<')w,bD?Ψ.{3c_u^:9hOI4H&r-#3u2:fqmøg{hTMbܸQN, 2L ZD)pbrSqV4&@?Ra#@kjh+Dqd'(#;3 !Y`[ӦrQ|!0BeoOw6|3ct Oy"+vnf2 6y~Ϸ$ ,5e.DIA*qqaˎ"&KeJ%bma=hs#^R*?"~<ۋ-ggC\ZZi4}nR6{SUPyY| "P);|Kp~9uه u*6h#;:lB1HH>8EE[%ؕ}ͭh5*>[{CPT;t<6Ұ ۍI$œW*X.~1G-@G9%*$NWmݻy{_x^Y.ݘ)Na0!js57( W`4Y_{e6;5MJQyIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/shopping.png000066400000000000000000000017041345766322700256470ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 6 2008 15:33:02 +0300ɦtIME  XC pHYs  ~gAMA aIDATxڍSMhGvfw][eo⟺Q\ؔІrq!9d0$\J%KN\=!Sn?Ɋfdٍ!9ty{߼yC?􅮮jԶx<>6::X,VOMMMikkk?0g?HhYYY{333Oƴparr2z0 5LK988]^^2v.<}=wqdh.o0ƊBLUHRL&sn4 UZO džLOr>qI:Fa}o߹LX\m^$.Q?ao]tѦnϮAo?@^gdo/"ԁ*"_QZݭ$Wf'x-6QwX;7KL 9 h*9ahjVӧr, yAV*arqN-}͟ nmlIǩ:FeCɀFed )W T\{V˿O%3k_o02tFO4W'5&?;"q~4IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/smoking.png000066400000000000000000000011551345766322700254670ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 6 2006 13:33:33 +0300кftIME -%Ή pHYs'dgAMA aIDATxcf@@ME~ӗ_aeff'{4C^י`6kkkzzz:={Vp?y矑pI .¥/_j^bH?~p֭[Js}'K5G kw=ܺK_tKO8q:&& 6՗Ŝ>jL{ZmBΩlydor=m=n /No^濛N|Qːbxݾzl3H0`ii |ض?CgNnckmdn`V;+eDkfdLK|ֱNcokhygfr!њdU.%i{'0q6LF WpIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/socializing.png000066400000000000000000000016741345766322700263410ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 8 2006 14:27:25 +0300eZtIME $G{ pHYs  d_gAMA aIDATx}RiHTQtlTr\H h!-MGY(G?$dP` TPZf`)iTfڴ4l}jQ]ǹsVl\|FْDt:BgGC!ǟxOچ&OcHǧth~APDdd_ bںaY"< .~2\Y"L<3sH@|$Bry3QYWNwfg٥P'W#2*D-vyY s(YSX0h{GmV/ٙ6K ߔڒ)u`Htx+S#*+:HÅGN,j>ʯ5\ p s:J1K!J<0f*o,s-U@ܼpI0B`5U3q t߰~\ ^L S \$#}W ϊv^}No(l{F`H r`r}g/ZXH=Ckk)6|Ƒ$c[[ 66àLp5ێ .sؕ&u<` <YLmĆW=)'аe-x5pg(,$q W s#%ڈ[.\1'+"pF)G6h~E`:IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/relaxing/sunbathing.png000066400000000000000000000016761345766322700261720ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 11 2008 11:47:57 +0300zywtIME ;'!JHz pHYsiTSgAMA aIDATxuSMh\U=߽{o~2M2Nu*I6.4EDQ]hƮ*BV.t&"R1TGĦMlLg2y7c*r9;经poZPw4'I@?5/*%L.S8}hQut "(BX `;M).T9fX$ aNyfWd)'}'m_Tdy`F0:,i A#[Z mYe᠚9OKc.v;!:mRl" &;2e|pLӄ[7qi<^=J.mmᣗ~۠wWRg̣V4C"\8sSMD YkFEÎ |G'OCe ~%lS=cXZyAo Lm=^@rm#4T&87xhp'Dlo0,s-=g1y~*lI;Ol!n, 7wqf"aGpu>"K]융&BùSɱ;}`[i}0Ƈ -Pw 6ݱa-5*yjmz/['.P֥ΝK.DYAB+Ii6Jf@30WVO|||.c1pԄÎ!1"Әt^F\ڂ%ʽ]cĭnIP:}|e* ,]q?2|Go3 Ir/ OB 0*5i404rr%Цjd I8&;w19T `Aܳ݇r`.YB(tA$Ua Tv Qڶf쫅@h *) x -xRHhҥm2Hj*=Ty,+«? FV3͎=HG9rsԕas3ui5z]xd f`t*Ȅ(>}zcF[өٳ%뜐ד0!PnZs*uyg_< J+~=x(l228}y7uN &kv1B")`/ߜ6}mXҧ a#zf0ZE}Lb^$t VT?x0'q;z6 Ey`LFDV(u$N#߽o05=gϰ;칮3Io. b,I(Q]eڍ..ML]׹o^F>TU^cv3G EHIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/talking/000077500000000000000000000000001345766322700231305ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/talking/category.png000066400000000000000000000015041345766322700254530ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 5 2006 13:18:30 +0300RRtIME7Ć pHYs  d_gAMA aIDATxڵSQHZaK&bQы5D*AИ{Ї(A"el{ a/l2H%833B*3k؁_?w c~}V\__RZ/J%PհYbD"]__@j8vfgg_IRJj%ySSӔJ҉Dcb#8A.s X*dOLL\^^looM (38;;˜kq~~NCgg'd2 qkkkZss]hԤ:2l6}``sssqflFkk+zqqqSң/{{{`LNHDg388t:@ BJ1-ckk CCCH$XXX_̶!Q, @3KC'''rvA$VVVz%1+X,lǸEbyy|,mhL> Y*bʣxK-$囿>{^FZT ?sa O[3P)& G(5n@;Ht1457n.0Ʈ-p=8/K$0}UbDQ=]uÓLg7p-/g "&uDf >H{OIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/talking/on_the_phone.png000066400000000000000000000012131345766322700263000ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 22 2007 13:59:12 +03006MtIME :6* pHYs  ~gAMA aIDATxcdĊ̯ϟ?ѣ, '|pppXX2|Uq7o4Jag333Û N|fp%C\| .`bbb``Ppc_naGQFFF6V6Wl.nnD@60#+i?ok~1x>}tԉ4U_?~|M\̱{߿C Á8~PYY[VV&Wjym``;HǏ +WӉysJJϋ/O> "" £WCta YY٭@g 06???éSnذ[yiii]!W\6!!!P,<]zu7o l ٿ={͍h0O>}6PXǧtvUUSl\H@pIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/talking/on_video_phone.png000066400000000000000000000015411345766322700266320ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 13 2008 16:03:03 +0300(tIME  |N pHYsiTSgAMA aIDATxڍS[K~6wLe82g /+/;ta I*mYyVz^}| ΆVV JD"Qr<===q̔WONN~] FSԟ DG>G7Ӂ; 0\饳{Je:8!O@UnH"?:Kț'---H$JQàZRjXu"ĄMWlfvoo/577Ha6˅*^/C{R* k766ޱt@ nbep8dX kkk.Nd2i%%wͦbZmwwwcgg+++hll䭭2Lt.#nkff E YdcpQ$KKK^2`nx`(eٯPhy{{AgtT3588E$ ӧvHk:b"QAlٞd2=0).?zl|IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/000077500000000000000000000000001345766322700234725ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/traveling/category.png000066400000000000000000000020601345766322700260130ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 21:11:26 +0300礰tIME pHYsiTSgAMA aIDATx]Skh[e~rtݒ&mҙ,:{yY:?ܴ? *TERXQUvNeVfYM699xRp<Y]krksG񐬨nI,gC-iGqt6ߌzb.@TBK'|>l|}~]:qyuTz{>pW~t^Jy Ͳ7%Mc4=6p*X<˙/X|Jkb=˖ ,K30;s6ס5Z<k ^'H*I+Kh;#1xv.`E+f^zGIX0 Qkc#e(ȝNpE#!Ps WO /e{ D } Zv@ҪZ+JPT`Xäk3{E XP)L!/Ǧ `ir`~p5z.X-f fo#TxdQ.n~,xX Cuxz}<0ikjYRuU:ya7L͌!pND:Z$LUѠhρv{uC3-PO>M?Zy^Y٦=«=F{gԆP>ud2 )1Ka2t:::HUNa X09,+­h *Sv8ZeŎWed"K$ (Pw୽6xIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/commuting.png000066400000000000000000000015441345766322700262060ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 5 2006 15:48:06 +0300ztIME  x- pHYs  ~gAMA aIDATxڍSKkAgfI&$` |A$"?Ջx$=Kh#j̋wuwvfvvǚB PttUUw3 {^u]#.(yqܘz5;IۋcA[G/RSë69&.O^Tӏ %33gI#Ih8簥gК%$LfÌPZks킕hLUT&[) ![F0i?@"ORuW}A@s|\Pt0q$ebfa<,:fF.@GaH)}ͿK?DK"T),ҲF-4cX[{RpLgN /98㷒ZjȆ7pj9dž8@iq?~7;J i)à$ m&C:d8;.$iU`RU"R0D=`яY{ܔ`ݷ&jmdvD4EBFYPDq ,̆$’aUQI|(alBG^dIL@ԎJ @`۷Y{Yxv !ɃQհO_ݝ{Xy޻R F{;;յVz+iK?j_V֞n+๱ cwҁp~IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/cycling.png000066400000000000000000000017261345766322700256360ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 13 2008 16:43:40 +0300OtIME  8' # pHYs  ~gAMA a.IDATxڅSkHSa9;9Kw,ל4Dd94bQm#!ן`(1&! 0"/.keksN$|<>o{p߳PvXt >?Lbi|>rffFh2B<fyvD^gNNeT%D:ZYo#+rGjkm;j)U_YSNɫWAw A .[뚝N-*àXeaa! .7#*t+quUrm_CڜPH~D";bؐA/]Rcq iغ w yZCm6Gp8QE#\5L[\^MӴ4(}P> t&ԡYE.h,mRBCE7Z[[B"h .9T* ~?!&dN!͊ ˧MrZV\4f+8:}"%{J\jlV3%N7$a'o|{^8G+-8L3t(⬛|ߞwutp1.IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/driving.png000066400000000000000000000017001345766322700256400ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 15 2008 13:39:26 +0300R1tIME  :D pHYs  ~gAMA aIDATxڅS]La~He(*^Кlh`"Lt lnБSZ]Yd\U15M"LLLBO:.<7sj{{{wB %%Q`08O!q8GݫD"sPϧ---=P{{{)bs]]666f`0js8NR V5tWUUCCC\.UWWy&HJo䵵5y}}f&477 mkko~{``@FP(B@]TT Pf@, z5&wpx LOOOdF!(QVVEIII| ጌ ra}}կ$L&Chyy\.>#E6770E+++rrrB񠽽ݩh蕕v<ᤶeggݎ|wtt\P+Q!okk3F#nBL.g[HNɧlU*xiff&[[[1u|G(^Mt& Î@(VSSo H"R8NAJ$&&crwLp$Pd\n? [߰s*Da+ƉQ=}BcPVyIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/in_a_car.png000066400000000000000000000012701345766322700257330ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 15 2008 14:33:04 +0300tIME  #(fX pHYs  ~gAMA aIDATxSKRQMLp!%h44FѨQ5ap$37>&NBI|\_j E4 a:?7Xjz(2T*xcX bQp80Ll^g2Dh/CP䇧)L& l^mN|1ͮـR),<͊  N.WWjKFs\46 4MVfEV'*xpot:d2 D4rfzs|>XҝNVN X Vޗe~'SQÉ3 7m\n \s\>7)Hd| B2_^nZ^|7J$S67֌b_W* mFiOBIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/on_a_bus.png000066400000000000000000000016011345766322700257630ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 15 2008 17:06:48 +0300l1tIME  8r pHYs  ~gAMA aIDATxeMhTW7G23&fX EK)ŅJtҍJ҅  B$B ]Jjfb>y7yyބ U{{Ϲb2kr,pV ha*t֡N#MXu2a/WNܤX b~dj7%#~fpwƃg3I+XmcKFjCXi5̾f(Ǜ&9u˶[t_Kh3#;uIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/on_a_plane.png000066400000000000000000000014051345766322700262730ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 20 2008 12:20:57 +03001tIME #\ pHYs  ~gAMA a]IDATxc`[X,))'&&ͤ;777fkkkYB_())nmm݆KsyTTQ~߿gA8͛7g 0hkk3kjjzZj/fCCCO###KYYw߿g|g!ƌ ݻ===]~ɰm63g|g<<<9>}ĐhѣG0 `ddxb (((ř⬁ 1W~~ Z_~i`HII u;@2hii11l;mڴ@ ]Νێ=Fyyy]zzz朜 """ 1Cɓ' /^p5[lImvvv222 LLL @g28p້ /|ݻn3g|l ľz >~V#IIIN]]]Fu__;hoh ~ƭGY*fz'Rmll4 uP?~@eI@$$$L| }J% ` ͛7{5 E?m XyvIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/on_a_train.png000066400000000000000000000014711345766322700263140ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 21 2008 13:29:06 +03002tIME  (&h pHYs  ~gAMA aIDATxڍKkQw$d:$5Ժ,v!.ܸVt~ŵԝWA BLڦHL&3w=p8ܙ{ߙB0㺮{M;}ݛ! Øi.ݽd~_^*UՓG J^mdJ"j7(l6自P.'Qx"Y^Bw|}B!N3C-:VcyyQ[tv~`vvBnJ˃NA0Bg+ hhh>=?VXRJp1sΞFcssU`Fn$ .ArAXRIE-S0OYݾfڽK/4EZ]TL%+8N"iX,_ 3t!IE4!1|Ehxy3*0LFko{]K<@@mFd?b `SVi\-XLC.rWB*mcC&89f'B 0eJ.$%u&G[k ζ)Y*uq`hR\|*soL?&":IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/on_a_trip.png000066400000000000000000000017021345766322700261520ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 21 2008 14:40:21 +0300<tIME  8/ pHYs  ~gAMA aIDATxuSYHQ868.Fb"CQb QT/APAeDT/Cm$RYe5N4싧CF{;s  !IQ@?bq;MQFHdhcm|5nc#¹ijy~VF?0j,Qnv)(i #%4pA67/X+G' vړ jL&eU nZְU5$[YO*H3?l:#1ʓ ¡   hLɅ (u(eqi5.;E)+!Dڂ]$=em!dY̫֓qÖ%Wv0Ѣ @ⓐ$`Iu2߮bfeIzca 0xIn6EȌvn`wgF!d44R:_|zgG#`R|Õ},_: @HzH|ܭ#!"O~ +g#~F>Er-Z٠$xYG|XM18'|_"wRq<]ءr(KB":޷R_<DI.y9r{+*tY - QVW.KE1k! cp(7׺aфl⯪.CgdJ0gdRIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/traveling/walking.png000066400000000000000000000014351345766322700256370ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 22 2008 11:51:39 +0300tIME  rm{ pHYs  ~gAMA auIDATxڍR]Ha~SU6?ZHEDQAh?f&/ !^MPҝDI&,/t nN&ۯsSs<yx c=ts Yp\lkPC b--KBOQ[PL6')V^8g +sg3^8?K*M,QUG9cY a;a B~d |D*g'%X~u*U5THx;Nw{_-.Ϲko^GӕڬwC($W`VbbޏtSUCGG\S#[D6Ɓv1wJG]+܃Ȅ79|RkD|i9оmɕb~-,.X 8ŏABN( ˆ}[ooc5oH  Ŵͅm:}i 2 S~CW)grS edFEG^ ù[x~/I i6ܸ:Z}^ %H9[E[V/#0(3roK\,!ZslK)t}zP)jn) }rIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/unknown/000077500000000000000000000000001345766322700231765ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/unknown/category.png000066400000000000000000000005311345766322700255200ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  IDAT8˵1j@?%RˀS4)Bn<*"Le? `f`}Zi4 y4M`8<ڶ$UU%K몺|1𔦩${/Xβ,$-"`9 ?<_˲{cm}1FosiGyUk^H$υ+Ee\ bL 7 mzIENDB`gajim-gajim-1.1.3/gajim/data/activities/default/working/000077500000000000000000000000001345766322700231575ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/activities/default/working/category.png000066400000000000000000000014571345766322700255110ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 4 2006 13:35:39 +0300UtIME'^Ţ pHYs'dgAMA aIDATxm]La?OemYRLLDWiEݸ#W. 3U7 *7u7u^#ʳ}>(dJ"C@4ۏ 7bf3JJfz5(Q^D:׮&t 9#9ݍ\y_I X(NCsV9%4^+Rx^/*jӋzI9Y)\HO`e{2Ccn1,>~bCPӧ/>~0sB q LblC&r5z!D'IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/working/in_a_meeting.png000066400000000000000000000017551345766322700263130ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 13 2007 17:30:18 +0300tIME -~9 pHYs  ~gAMA aEIDATxڅmhSWͽyibcSosZWA[/uuKQt8-~7 c1ql/TDƬZmlES]M֤inr= _vs<&Gx${fCOO˗LMGLVJKi_Bظ½e:s Wԣ!5"8f#7 8eK#Q".@;Q3ݜ,L=[ҴlF5I_+p'7sX܀U)|hK6JfSQ !u $p^EJ?Y5>8BIUVHHG~lo Q^%`2Uʘ!ɐS-NlEeYf[kDdX^^$AW }T-]g.wGВ Ww!炠`G/_7|]_q(],} VTJ`ӊ<1#C'cD^FØ*"_ntu*q2CnJ}؎53)kA7<^FWq,'r*tW f!KL&ήlYYzoi] yl`4ώ ΡnaSpEG=IENDB`gajim-gajim-1.1.3/gajim/data/activities/default/working/studying.png000066400000000000000000000013261345766322700255350ustar00rootroot00000000000000PNG  IHDRatIME / pHYsiTSgAMA aeIDATxڥMhQ'&MZӄ(,``JL4A{&*xE/"y#V`sRj$A&LkJZ$%_4g$"=3x?9Bp\3T*y8`0(VիryX,zk hQ@`l^lZ>ܥF@^2CrѢ 0Ft~(0rXJXyWdY^$)c8& Cd La=y 0V%!A/'dOn^C2^~Bvi'nI$<bXOpDz LKA|=1jRWtbai(Jl>.@Cn| s`̇OPE8 "EꕒɌFa7+kg;j@-(j<vwpnCeNadR"X#~Of2 I4]UJ3  J0  b H*C gzsg2LB}~xLʜs_gZ{^{o9B+qtf3GTφ?sp+9.g<{!I?忆fgϞo u9e;R}-?{ySd^Cͮ$J\':3V+"O!N=%5=Ft) 3E]@Kʺr tl]OUoΒew4"!%};LU|ࠎ?_suR KtG~qh" Ǧfw[_ynn`MĝmuJ_ ߵDx_l .tz] c34$hHC<N5C(W+GnaO!Xk[M~7> :oQ[[/uҍI7.K~؛_]}ܴwdJ5hѰ96su3bXh.'O.խ,AhCHt,oaߣzy{Ǵd\93:?9uo\{lo]徿];t _}NOsۚk_tNhhB%ubzr]=YHl_,CG➮`]񖵝\9[zs?68mt>lj<_bJWK%GJCsܢʋujKqm4nZ=m\/no-R{tCКk}PZ{:_o"5}bzJ} ;Onao7<:'l"H ^NL^m4"QŨU#6֥s+zn+7QjkLjb ֥LJͥzzv\̖6Z! u5>tumqe拸NxqY5ܻkU!!cSG*S c NDh /.Vv98`SLL^u4-rC6ց|貶 Z_x?XwԛvV>=smшx魒dv*M}-81X^rϯXu|:pM@~˚}oE0ֺFk`y鬖/7zbRo'DU jc"+rϭ\ۿqɝWGK/dFXvVLlFc Q@ R)uXZԶWp#9kTb}D9sQ(i +zn]TvBԮ3C E[߿s[ uXc6/Q˚e78!FXA00F#UVv}C:j-a=fBG7P'K~(<_R8{[VU|bU7).}_QXR8]y_Ŭ86tH!@Cw )8!~Ki֯˵_2*:lJWPUQwB*Dc ]K9Lx@hAAMU}ū~fk3>67桃#aa.um{S~_h\ JqDz/64Țw?ې~R>Uv|җ/ H~Vb:kXHbm!q8"/## mTIٌ~7y5Zqd|B#XW׹ykKn_Is標7Ow=&C .ĘZED4!է$H ǖ;*>(ʻezAW0k2N:QP.Y"kt (uBT_r8r+P#g):jU3~ՂQ7醔n x=wKG:9{ճ} ޺45P C+cxƺ=}n֬x58|29UymﯿTƕDS$GIBE(cBqCkX|9mnK;_ͬI׷"(ssBŬymsۛqnZ8R<4#FoAѬ̯̿a4|\7TiG[j1f]'C"8Z! AQ txs}c/6߼}͍n`( jbnHhXY?2^5cZvyv1Nxـpat)=`]! u\o9]o 6GlO` (D#vVbcq F Ccn)>ce rt&t_\ 9v|K|ض0ɿc_5< WQ#;վ ˜o?ϯj jwk{yq1?6T|Ao)u-9fwק1?vXcRdt50@bX3~716GCO͠}o b5WJKɶX(HWW.2c>>BޚZpwtƱi-OĔu +pR.M~; 1%۲K Šu8RPl;M-WWJdEȔb}c͠~_8N?|_dilJhOWMgrJXc9:2-*;g'QSo}`.~N*<\zwuXrnMuAi Gx1^>ybJ2yBA< -rݝe?ԅNl~ctt~H$pb)$gëZ8(:!gceVÑ3[yg.;=wqmc X VvmfNP9$RW Dh1)k!eYn?`37=`ƶ1?r-/!{mcnυ(W~>HK<G/./cӨ=xk$zd猢ڃfӈr^Z Vn{_89js!۴ Bu^s1|1 ؙXi!(H k:;c<)6M~<#5PP,A4E (w?ZS %z'sLB0 ߗ9<~œ7+~bsÂT_%. TgX(,& Hl>KImBaSo 7kQ[+x8CjtvnK"R >/+oY=|u} IF8_s{=[ R,ii66 r蘌uFsQs<#xOG}LBt:hرyzMNj> G~LJ;C?.O/3qi f~5f:'~Xć?cN]=v:8Jhǻu0b+GL\Bmqf(q(,WP` iD?ۖL{&&~OsJN-ɤ°`^\E[fdn0o[[ NFp*\qeZD"߹u\7);/}Zyu̯=/]}ߴ!?"$ߏq`o;ߗ_ /JNIPfҤW_ /,xzAf G7m4lGKѳM-#"r@lꎞz./ /q[:thJ>\"*G ?"PPhkT֬oߨ6_^a8Ͼ U}fKL<XaFucըmϑ%놟s?K2qǑdd)-岥Xq: |yAuX ,GX=1Mlj8)a\1u qFZ$qFZ5$qNOH[R ץ(p{8\"2pj9.@{*m\>Ļ47(ÍW9xxOm 9(t9GEP@K~nu ID$!o*!Ȑ.pۻpiyaOgpyzky;-OQ8 MQԝéIxtNbb2"AeɜkMxt$AOmrg?CkZpw\rm7 9?I &.\"~ț "T¤P뇆 |op֥9usY~[F8E9u.-ju4A~%'w 뫑jܱpEI>}bsՊ->?'1s[V 1ԬEg[L=FF}.k$PILr|DjL<1?&i'3">3 S?NO"+!ya[X&)uc=VIw~d8<> !Z]w98G0Pl)RՅ;P&M"TU01#CX4fqe>~L,Jj2>7w90d nFCCsdhcp녧gɤ-Ds>6}J2!0 ?}jqLeub]q7Xrm7^GDbpYy֬ 9p/o]<Ƶl)'90y^_83TS#<%)f= 0>cj#>@ ;*2Ki  R>8()1uo1e6 PFW(I".LeH\zGݦx.hQ1Qթ!6˒Su;N^:j.|pEigW^yb9Z&Ѽp]OG?~+.2|?ɻ/R zV+B_qĉJ\(v[R ɩj Y' W#%kʉdCK%w ^կgMc+e^z#VmI sQ?q%N]d?Akl#~wa,ْq] mE uS_c(r+m2;:F]GC5fC8 b27. {偯7e)\"?]}P?'1`jcJ Excߦ{]%&w8MM~<]]!'|(Q-(եS߶,3]I&V곜yR Iry:zgGGb|)-j_2k' lx|%[[3>c O<ݮ4FT݀7bMb\_Jv+ccQbTY-OP@&)b/ CLGUih"үw7R{QUd]6?e&di+jKoӴWw2<7+feIQj~vU=W\Y\1۞$^F3G ĚB6MT O$Pftv)"eIdZ::)1}[T:A&+8 BF_4IK狟Q T7;&x45 8OPcܸ`b?M] ajHW¬+`©D=5Z69 ѐ&\M?U8K)'=eZI_F4qsEIyc1.;A@Qo=?mɧ ',x5A%.njC~ۧ]cY"d\!p}w䠃v5jH$j'XIBH|>A_#&SYQ$qʼnjud? >l7k-SE1:ms@{*&E]xLpiooR"%sc҄8=bjn | /YYԎ;s|3)cfhJAD(ç:Qm^\4~x5 S箣n{nGL>E|`cR w?ZCcQʹ_q3N3ekg_ 8>n.~[1b&jMn&QH!Z+MC%H-o]^dX]LnJ\"!"xkE˕x{/!4 o.R$QBY(W$}RIAKTe$\>=gx`m'h8a n;|K9LpÃO<_dIU|N|g_?V5N' 1j1eUl)_ <e c­OC!\Su2d?VcC~uwtOO#ua]\~yGQ}&j+#qqIS B201ĉj-XrVCtPW[k<ф["ת\_?##3oO]<ǹOk{ W}sLSƧ9lAEd;Z[1c* %5v*Xcʁr-v#^[No-Z #2qLڱP3@<|~oܿM0 _D0 Tl|eZ?/Ɵ3 uSXLKl`=p~?\όY}yz|>H7\iϴ:|eToP-XIL7S0ba>CW^{9q|hR@UՂ<Ѿ3o(3qT İvw=QBnh$?ˤ\|8ݻ6{%m T9á{ k @]f Cv1TgAmO0PZf}{-O(ͺe HDjZ]>˘cz!?*lo=NKŰvj`S&*o[Eg`K2CNyXux-{Na`wڼ~?\6&ux>`]vÍ `ޢKXql{Obצ)M%LR5=W ݚE@_?L3N5FUߚv ;je>nҏ o:5!Kt 2`,B`7RH/ UAÊ}HG%9!pO#aߋ3&h-;o/ɻ㱇G皋j0q#|jT |B"~i\ S6f?JJ^Bb[VR-P6ՉR.F@9h:S?ǁ&}}ơmDDEcەe<z{x-|a,-A>׻rp}}\Z%vno-?~]>NR 4*:_t-^-[l3%!dnVޥ4MS7ܱKFhgU40lA\!*ƢNG%ʤV91,FHʹtu.lj[ &Jp1M9\uiX>V8 +^teCRa>G3[lו( 4Yƪ%PS.lhV=VhT7aawR:}p@8ag MۙFbg% Q D40h(xն~z(׉ BA6TՒ+~IIQVlQjqΏv(̕zDRXN>O$)Z[[Fcc#tUKn G{{;V/pQS0W-w( ^J~IiϺUc3qxjǐ"5+1 P8E$RW-w(MM&NL,XȂeچ>~D,X%+kO 0DߥX  nW*}! Ka*8!t@!8aX'*%7F]q'yUMscc-r9ɀ0 e~[eb$:B9eʶ|,ԃU^A00hCqV;g.?c nT{,"~, G5GF8'1JDDTuBMIY `QEElU1bE ,0YPjO4YO D nmrD. Ug(`!R.I&il'^*{Sɨe=*1DU)%*7z:f_ָq3)udahI\S)jY*a A| 1 ,=%:YW7f8o>}we76H$XJT*E_o'=]]ugZݸӧY_r>xfںCWV~n*0Nc\8RP(j*^ ]ޞulg@,{ Iz HQuq6|%Eīx_[nOHPh_f< 8Ł< ޤ[Dk8ޝ{]'{[^񅄞y#H8K{E<^'WZZp\ជ+v uUXVz7[;#p J<',@i11k)8iq9j4w<3W)6 i8}.}y_1A0K/1P<Ww>pf:rh9: 6[Ϣѵakݰ⤛鍾}Uu :e|iG+|rLdjVk-o-^oc#u{qزd}uK/?&T\#}9.pc!N_W(gֺMch>:SDL-F%qI:첍@LXVL&bVeꫳ~Ϊ?HؒΈƪwp-rdI"c~O8֔_鷿X5$ߠ}A 'N~aiG, >pa.3kw2~^T?b6oY۽_ܪS.Oo ,'OƵ0>$TeQ{Vk ԦGs:;T]-߲k`xnK~[X*@.dfQSBsuβf3I+sT€VAs$[ƥG^mQ[Gw{*%XX}oƴ6Xno=ʥhĬO7zVy8z1aҭ\ swt/zw6H'UU=v$|! 2ytf*^Q)H||᷶|HcRK 8j#-n|3 {~3 q+e-v]jv\~6^UVKo* 6`녖}Z|SEc:]] n7a7W(7Yw4'ĭHGo 'DlX BZ;\?1 ei[BL,M *tsׄ.VF8qLmkY`#~T}9+ki[ _;% ec~D鼚rިnRj*QmwƤ[NPLo?_ /ԧi7aTLKUn7_qe'Ao%ye+fxuu̍L!6^"~g==-ՙ<5xo8i($ SϤLyCgk-p\) loqo3g ;ͻ0Pv>[C<>ʍg*#6q s֯s 7fubeʽ+ۯBCv߆;1g1xVswpӷEOWyNsVl&+5S[yYYN phWZn¸n\uS'UU:~Y(ۇWA cT,]ZI 6yq#aB[])O/:.-{7M&U?*(wx_`АuWs?Zvj}7S|ʢQ3U8hGaBP. v׏=޺7VzEg@oĿF \˵w[Ԁ[' R5oO v،u}ʫK3r{iczq=!d}šYw5t@DNo{lئ |C bjFu ɵ1^E-m5kjJt-Ց`ߺ֢d.ce/|U>Ցc'aVCThm'P, >"|`U :V%GXG6JkLOv|H&oTxVɐӲ\11 y*E2`ba.Z~^:'=kO3&p3Ѕh4K>v(U?8PqSt׭ZVnmt3 6U36-@uLmNz|)Y^ŇSwAj: ߅ep4Ǖu_olhZѵ'u:?'7ag嘻o.:ڲL2l # ^v.݃z <MOqCmk#퐕*Ǡ&Iu,1_(=|9n[nJJ'jXAXɿ;>:j}m քVH% (hSJB)zuIM/tUkDKRt4CT?xU1^ u:&fq$Z[=B16pַ0fB)űAm!/rԆZ "7YI4*ש;ۿ÷3_1fJʒu0^xlM[l"t)v^>~3{{6~ӕ?O5*x,_cs8f[VQO9c¢ڽnNW=7C D]! ?C3_);xq12~0FmZ#MJ]q?FJ*CZܗ(bBWq͕I0|ƞ7'\s5ӘAo:#ITB{tb}P|hmЌQ?THYܵlΞeYثb{OVQ4ePccSNZ7>^~ aU7,ꈘ Xϻ[1M*ɿk#m߾UܸU:b]Z,q\AO CBh (U01Knu'1Xlh1N+s)vbBGB7cm{o ;+ ɟIߺQ/X'uƞ-WUQ+xQ"AU/[è ?C1́Jžkʔl T=P SDu&O7z9ߘ)iT@Bq1"6pλwT/^^S_7D kQ"q$*u7=dh<2L~/Q?5V"b{Ń>%@PM7o-hrUt_?F[Jg!ʡEިDd yr}B_y7m <Q7St՜xO7Օ4~(1gT\G.s&;l,r; ]oxf^r9kںիzTw`!&^zxlC qWs#~@:3tt]SdSVeW$EP+bU7a亻r|Kc/6w`ogjפ%M_>s.&:dT苠JD❞?;[uN|ogP|i̹0|Q1`xoIק6ChM(1>^"RXj˹[VV7ՐozŖ_%+bj:%N,q\6M.CY@A\>n/aѦ`q5ZN38RxʋE ?$/BûJEn{!KU ~3cxevjSq(`n~p T3PJ]= ߬K9Z*-&n"KŪ!bZOX~KˏDk^X]/1;[%Ah3!Z +}>/~GmwXҋN*}^g;'vл99`κӽ9SnlhſW|{}9 ̏z N QW2=d%\6|3C@m7o;vX&׹Է%JMsՕLH%OdjU0 ( ??sQkkŤⲧbbnP}V˃ _eن+o&WqU):GYg+9/ޫb=U^"Z isyz~wެu9/5UvoQ֡ьn;8#|4A41#s0ЛZO klPEt`J33$7(f駘%-?/3.AؓU| n-ۅ龵<Nx >y:y.TpY޶8(!_!\1Vy]%.9O׵pۚ96MCt=vۻ6ߒw6{ʑ[SnZW_ӓ\flSFXw\3O+/ӭRYNWqqT2r P/ /fͻ)~jrA%}bzR]-YHFneT,GkQOO^s Wm{o uF}38cS6ygK^:|kpN5ٝ22B6 n?XpEewx*ۮ|+Ӿ^̚/x"MY!?;#ĮeNrBMm>(]/Oya7=t2weٺ߀?j2y[yjOMNmJR(D++eXMu.D|Ʊ1}O?~=l,/97dvlʄ&pb8Z~Cm%$9u(QS-92ǔkόfk/d'&IUZ0&ni$ZnDC.wY춹r1l1h!jh]zz)>wւ#BM.=} fb{s+jc%7:Jo3G ?58E {mrnL}X÷ fX+P)2^.GD3W?.V 4ԁcBTPV ! :{(z&=a5<պ9վleK=_ K sc$؈_Sg?k (c:vۚw RiXVe^ƈIv`q▋ '`?E7/}6fc!kҢXQF)ҳK~3O7$w|쉠p=mZpÇJ%q_z=ⷻx)HUZ3x̕m?}SsТsǛku}]vѨXUsmRS{LhN[t^[?qޗ2h(yZ*Ʉ4JXX_\=vwirf׺kU̚ JDJ6%PYGyiƶn-YW}Wi\;B G\+jhAm%pŴ6.W1k⇎_{~mĽT*u+5 \w! 93 븁-v4w(H< FM M0:?QyWƞ7Y'ԚX&:~XJuW, jlwtӖH?s[GG5ڨa~G㧺͚1j`v 1o>l?~":^8c)-"9u n] 5 ILnk{ ǶRs󾩁8V׉ *~cRwqX1^ϛ|uLj.3tz}$|!z{^o2c,3woJOs-f$[7Q 1In^sNjzXD!@_ٚՋ~Xnx9kp:>8}MC*cϏo1<,@X)qڧD0d칯~T:G`$?">fLM Wv1ߒ|UMLmPkU/f ;kd!ck+Niݓ?+<F^)̫_@+[٘HMr^kKNo,]uQ%Gl%k+M5ķCrj 9ZVAu~,Ƈ w8~W0851Gv InӌM 7VKCsJf͘ƖW3t%4;N`\Oٗ'qOY,D 70=+VpFW"PS?}B%k`Q,>${:wVh2KCkd.3:b :2DfTQYO%$k!8TFE455! yXCHϽTno Vb 1_{Jg 4!:-RӷUܷ0g LvqF{>޾nNÿ+?NGXJ%H,:tvןƩrĵ){hRcaY>\Vca³e=]fILhX?&>?R uJa,lj ?Ǝ# h X?NR^PUOGtlj e.^r~|k9A &ȕ)-'5 M|D!3(-"ȕQUtRY/fwnmtS&lo5[+Y: @< ԏQw̋4|erϽ 1x|#֜i%iJ\$o-Y$_e909d18o* dcb=z̍r^rV\)*0.TrJff[4آ!11 33O%7zV KVmnzVw_f iLlRq#%eT\ḣG5AQ>͡Пm1(ѰrRzɫ7'֨*Jxchk"uq Q:* a}G,9"B[䤍P(qXX"q:H]eѽŋ#·mlbC)Wx-^}9`* fdZfɢ^yow: }%:Ah#')E1މ4\dTiځҒ@?6*=qzb~4L{)-kب=6$i!(C[ D!Nk='*=v$FukGǸ+m Z9jT^vVFqGA{`Us^\:x ^\sZWTAN)k&zYP~%:1eo<[@"rFq?Tx?m\q#ɿ?urՄ [5S'i J%do|;nȓ>IǗ*yr? J(ERZASH1Sq}Hue}iȐk oMqa;+&ۿ+'dZ+'

zaއy~|LJ~eL0ͣ=r?>㥥.:T %MLiٯssjMfS*s"1IaRAޥF!u4_cF]=7 &f(zBSHY}b?WؕdRl:#7%ڞ!iҴw)uL2)nCb%H0VI𝐧g!Z-YPqkZ/8#qn6jTg5&S|#! 6JE<>SݐaMWκ#.w4KwcBs Z ʞ;,s\N9tt+j_~{M?p֥niob {y_^cpU:Q2 ?6vH1sߡq f툆T=ޔ'؟/;b,Vpib~ۘ]-N 'w [ Lb1$&4@0"~mH(ZjIl[ #R;nyE!?Snugmu[汨g" IӯG2^TZ(yb.ZןZ?|RL/, c7O畲MBW2b[KSPg35!~E*Nmb'5&.ZT߄r`4B "呬\"o-iR'F-`˛/-VD7HHtF+nDK.m?8Uf"8#j 8`e)p_:X9tf-Ot;)?P z"N|֢K-vƛ3VGDCp2+Pԡ8!6'bb0kԩ1bhaE!]Q0_Q<?ҵWgw)(R2uxjL,&n]rOƭ2u"TRk)~#b|$zCeM?駃Z.ꗹ=>NjOQYx:  zH 3|k(dRRB @7:TPuj>;#}$aN ;RLj5{H,Oo؇?u-a|o=O6Cm jct0vg}r݊q6׭<1' iW&,SD_DAC;UEĀIhE2&3 4d}:ߡ,ND}śfe`$Cr{~ RuPKra/UMڹ^6Yg!~~{m{+8u-S'}om緗! 8W0_Yqqr%<},R1]F PLP/և1t(Vu*__#gTLq]6c `ھhry71|b}C)Vaa;QWi ,2)r' %)w`MEp/J|9- Y4O7eF$Y7pVE.sY9Zdy!ݎ硧>,Xl9>{QGڿgR,3Lx␷X ǿ)/籃>!ƍWmS.D,&Awp] k噴s !lAYS>?+oc9@Dl4`.x[..20[L4c4=/גi,Pz ޠ~>23rt>^ÒH4tDbd$RAEEu(j~l<E%]/챓ǯ,sQ1e}@~/1Hk a81:_L5$_q"8\0qQO]8qqIWlT|k%Xays`_[`Z@NyـyxGOc',^uu( 6朝g)q5BPPPH sN[|8zCX# (SU?"\g+p.3f8rnd ,O6๖^bfH1N,~E#p4c Ж%NXCygp,T*~cߧ3;;Y63K " T**I(AL0HΙ l U,W?u }?N:uOC I$Amሃ\"W z|6 wV.Z$J= ';~ZIN;/ρGP칛>;89k\E[_ ^؜~{D?CynN?Dʓ#Ayo\Y#G'Sh_ghNSZ|;GK/c.H 2}U*M"N#eWsFXbNǜ=~{cב-CKKcT2|:vHN+N_˸tQ/Q)̙ Z1D=OYxѯyc7h4I*W4#\?췻~x3 [ͫKg%T5(Jug c!Ե>rT_0C >䯏D|͍os 1ƅ_JsډI&M0heKcLj3h MlNfrNC["6u) G'{ [ހ=vMlt| \B:+w=`.#'݋ W dg*"Ձsk,uL.ܐ F@#+L3w+cOTpPy,udh- 3i ㍼;C,]ʘmmph*Iɦu}‘{2+ oYࣇJuF =ٳ}foCA!$TFO6y O(Tٳ=fjOH$D"R4܄nƀ7͔+h5`%8=-)=-ޛ`<y&p>xb-(|O>c&vڮJjzyK~OT߫8T_NEr{@+&YzwߊwXݣ4ez MMUG+S=v͇0 :hu}WPjF3:1.x@ٗ-u;"C }ʮy47[Am#+gzG18#d Ϣ"2b?fh9w -+s{<|[-u 7/*$N ?Su~9v^n+W0`J\&J%_!3SoE#_ K}0o᫟L%hQ.;#uZߒD}}yً3P1qÒǍx+ T9ְkïBrbٻ,hÕB(LRv8l^qN¢EsDbǡC)zZ3NN s mjޱ<'O X㺨J1~,<)e: {K=T2 3tI_V8 lz8X*PIfN3?n&աdfDˎ켉?%$f1>a?4Kd0خ)P·s;`;N>*a}Q Y;rwߘe9J1d)A |%L5~`?dNN9:A}}.׿-jspy0 JRV@<> cKױZRq- 8G?S'.,gs/ވ('X)6`$ZJHIY8MkcHm6b,U*ZK%) [K EDܰL~J(BQij5Dnñ~iG ;`"u㾆SG]=Sx,^ٛ?rYM8[e\:ri4q6R̬P[S`UG/\IxMLYGJ{DJy#[Ո+JƓ<ݨ.dR{ ?Ϙj*!#}f((a΍oQ1;AV~-AClH)/ F $C T#Ơ5; gx RʇFE+JMi"wB^̡ܾ7) LTLMkVaB!>R|_qK^*,W-5Hs#A羔sXtt9:8`#1@BԗCUMxIq[\+''O ʟR mm*QCTTsP^gla_EY`,|cPr+g vv_lfo9~1%@\9T~<]a9 ?Bz-Ys>rFIk JRyx qrHRG3z!>q2X0W+X0@mߕ#I煮+S G;9 R9|䈀0yk/~jI8`B8ߴ,S|4[ů-kh"!ÛFdF(G_s,[+ ® 6LP ī D}lc~5> (8HVWw)B~zi,ޛ\/՗h9Muιn8v﷎ ~NZu!p|Ωa>_j7$(FUBE dp(, QCS}7ǃgV"_&W3gI>Z! /BȗbzUNz]T"ݹ,B ;3*~:@8e wZ@9͒ѧzѵ#}Agqz^i:Lm#=ֺֆ {Ɔy@D[\QpdfgOQ~/UoB[]w%Ǻl:&ᕝ#4f2RuDrS8zFJ/ efL uhm ILi $LK ;р#rŸ\J@;w(D&ԺQ;B"# Ӫ:88E/ FyAVy$}lJGy|I39ޫLL6S}8|o x%D9G Q'2<1yU3 7yOR)XQz⻩\X+;ýO*Pyu] ٟ߬ۧ[3ekx>>>yb3+oL%e$ᇿ,t .^{t K9ŗ,I8:_|x7){?r" }0äqNr ~{شv^[~d~FFꥳSnkx~D 8kH?;(xTV/̸̳`ÌօCs1w8dj-UlɰCnh !TE+qg]7~9^ܩ(naҥ_ vMn5;RGӦa2 \L7KL5Q{אmThfnyapLwax|( A^h-QNoZ׎׊U` ?4pm,7Ϻ^Y|[K!7R_+P~*6젃;6OFGZ7^5dZva\drOG=!/$#Qq޳W#1C!VaySD!!8i~*9>b<覈[4 sI><خxah\ <Ӳ]yMY:/l9"$Ln3fby ʫGYga;/$Q6վÍU#+ԤaYcE<7j[YӽkY !OjA W~~}K.yB%2&Prɖ۱ .nJ+ӡ=O{>?0@֟Y誎k җ?L UH$WoU㜓xGcFX#Qƴo3dz rEDqѥczhE7݇%z|qU*|~&ǴlGx t=ekBw uI(;Mvv?j$i+XOTu8fv` ԓ \IPE;{j)}&n{æ6ya~}n;M!Jғ'C%!C;=x+˺36qt?szEwqgN*X9>,,b/<18Ovj 8R ?+Zql伞]˵[Tz=q-^&ủx'<]$0&\M_GO?E!vRI}g4r &}rJ]@޿pĶWbxTclRs^3 Uʹtħ-mXKB0&t#~6·JΚS޻}EV 16m$?g,_kتnRY}g&gRk;?HC:n+w|MCT*I?3Gӳۤ/kTV%qp mI6_&8oV-hXwkuzI6ף؀4*+XR͆}DA5" B9.Qɞ>j'ުHdibJ$T-Y2g/ 7^i5(Gr1s6yb)ŖiCh|2S(ۂg#H~QgZ-X*=8l9?[vgSsͽ&3: @ߺCa^-v牣\X#bOp6yϾWϸ{%3ZUpΈ'pɭdtxKam2WrΙ kPeJ^AKJ߼Ux\(Zwq[V͚bOj䤹)T)U#4 vj˃Wx<Ņv1Qg}'F$]{8ky~~+饕ɔ>65@MwqȯUIvrG1twRޮ-9im){ Y)gRTpaK2rY}T*h#Ṙ5iNrl˛{41NX ٟ 1dpgE+we=Z}vaO[sYYx楈>"Gm@cRybD] WK^TOú+7>:C08,Q EE8UsŵEcC"wNU=/sc;CBdX/NͲCq%(AC Zk)^nwђ2AMhxa3dUVu֑@1HW~ yBY>\r=5{E9OuI<@\lpS؄W^Ggg rPlγv A|A|F/&Ʃ""BZ:knh*gYkVcz32j غj9?lEy *l8f D)Ey;Aq.Zvk'|?egDȈ-qbKy΄+|so~@%@)ƯKx-r>;9=Ma#zZ \VUOĥgaӛ+{եo~J9AX olyRjX?}u?ܶX7:W~l= 'CXTꃿhi%` *ޮyl6qK -իՖ>l[ݓKx 䆡JZ ~zM-M@i7aNՄ8뫪$k5 ΃LcHkn'׷Du賓RCiUR).i-5W͙ myk7kvrҔ)BI%k\ڵ:6ڰX:_s(d:Wl';eQ( //~|h~xM˪sرi~]&ToHSTֹ7Vzh/fB5FA7E2 Q ϶w<}ȔyaKt\ͩLنˠNjs*("~vrmg Jw^--N?:I/I$ $zg$GJS0l*. ~Ug>hS]qiu**LV**r3F^-GuTmWrjfU2x/ĆY8;_w&3R~( *A9UD?#q4?T8XL;. ىofvhkf\Cf+8R> /[_h//wnx&ߺ;gؐ n667] VT9"f|o3n@ǔjoO >USf~$jR@4,Fq԰{aﵮ/}'o|k2tfhHOnfbI%' $Ϛ> \Y>m ȂrbJ6!w64^zHJ2PcbR:"Bʔ(I[ʂIoNWl鸚# u-Sm\rv$ 60]{?-Xc)08нl oO|6o1~]WnoiCw`g٩eڻj6(tB_/oZl )^0SgQ%|Q%[M[kЌ]Ld3'|/:&";ND%sRZ88gX䬽#&W5i)OV`PFH(|Xʟ1P~nmUʯpI?1 Pܪurm?ګlmN'%oj1"S,+Ϧ_%jxo}߼i''4ب}W {l|KG|_0Ci]XY|פR hl|X)/\ۛd K88Ά (|s9nvSl\ac(oz.v,xƮڽe Hd*lC]-^vKØ2Zʑx!w_x8.a\S/'Kn;H%4C7-e0gvnw!= KZg;Ɨxq~@ֆ"AbiaGdD+LElɧgy&!Q[4厾;=V#X{%Cg/t&Tp=n23G@o&{%wK#—w ˾4w_v/cu1巙 Hm\ ߴ?iaM}E{{o4>1ӻW'|}N}O}=}FRg,_ᕚq\2;.N?\He&^O}s זsXn[\@a3 omU^~k| 55rf|x5ﶃ=r)Ǣ>i, wI {Iқa๨[KvJ',[o9īe,\(vEqir'_: =.&qݢnX}T_bJz3ԏuk.uy}r"[qΨǻ?}/gTy5D0/z#G9\ c?,Wɴ/XUQҾW0]B߈qx"X4ggSMM"(a튺yԭr rn 1#w>{1…v-}4_\*q-WKʖ ayKz &]$8}Mxy 9o9ffSMt--DrwtWM_ nRB.  Zj啓m|FD\Xc|o/vy:om5dgl>"'_Y_%.%[ϲu^D'7ސ> 7ng;L7 uG5j h*0~ߢreݫVrn7[$u^֜Ol8:3nW5wt3<[3c51/| RGפ ut]]m ٨b|j wZ?.yJ L e*lY3@niꨳU+ߧT3L BQ) |._ҾW1&| RǼ@_-?v/v{Nfjj0\rI %`ewrO9!!L)܎ŮX/U.S U ȉs*#7#+o\9 ]-=vZnS4ԃ1Q|[UH\XΧ38y,#1 jS45Hg@էӫsJ_MXtW76o}8ʇ5fzsǟc Mi [N6z̦7/LplY\޶-{slT7k#ι ^| Q|fl+eJ:PEy*CiAU<&7[wkǷ\xb[p᳝1+Ue5vHJNjv*o[z1r ; n6?˱3.?ǮZk./㱘whm?$ CxN\.$0:f/ՄK Z?6w=iv3&Wz]l'1}g*s16TK~%Q±.{F KHM<ڱcQah $z[~گU[oVv -QoA܊Nm wp=:_}KxȋR[*$|oB[Mx}b'sK\!"Ԫ؊Kx'Jd#I3”{6&vR *ccT5)?E'{OX= c;9;"rFdžc@qY5C+u:xQr&/ {fRF2 hxd*5{oV~~mc|wݗNhpƩHWo˷ s^e0E1jJ^oֳP$`Uߡ3jռeP3C$Km<ϭ0Fög|}䬊z/Y]fd0b="r]J ,Qz_Rڣb^8K~L:'3X_7vn)KS6zr>ܒۯ=qnݎ#dwpe$-+q˳Q|pTW|rSWg[ks߹&)&l&5~`+O.֑M:\"+d'ჭ&C:^n憉bf~8zŐN4UW ﺺĻG,^^`[}xp$ږC#]l¦y:jSo \( yjjS_#Mؖ hM,L4{5*&ծbRbL 2)VD4U{u&zۛ!SNopϟEo􎦵QmŊd §"ƸȹL^S!'H`Vߨ^w,ՔA9qfmχ\Ƿy[@*6IVxV&8 4$Z>&5+Ų7}&a!~4;Lf!hyAHS}fP2-Zr) u}l<-HZ '̉LlVW$2z~<;2t  w= W-#?}R3?f}@~гqE~`Nq/!O&E "ӘޞDR\: W!4 } #\(t:Zr?[S'`EjL2%>S=cc=w]_"a#!G^ʕA 3{ob2;.=5?LV %}}Gfg0 Iu{ oyT#6 \'?EM/KJ"4'J֠Qo+AK Z8n ELHNk$EY5FȟK@zu7u\2  2k; G&o\ >XჟɓL{7{㯏Do,O%3EQJxEXzL4^?ul4v!Q1_*o2yUG,PMLאSrm㓈iHoO&#^3}~MԶ3?T{ sutUL a/0=~Lv(t;xWKO- m-’sDfD$&^]̞.q!;S%/zl߄x2^hx"+vȥ8Zk[vk1>2V u gu/LjT a\)?@Мٝay~=7 ]0uj]wFx= =$R yCs͙=PHeKÐRhqjg8fïO לg+#{NRRh't c{`9dIHXP )§σ'N||gTFd'|X߽_X?>Gl[? o!{-لU\_n{J8e/e (;T%DŽ*F;#;K(?M$㑐_S%c7XO '?hULS_f%wf42=QE g啯Ó|%i{\˧8pJ\뻔Hpi)fmzCCPu  ؐ7dx5nۿ5n;\2{dhn5px &Ubp?ymC-p8q{5otaZ*9'8_42lc~kA>>}|f'f~G%9l&.WW:Ų6DN!f Am +5{l )舊4`ꈃg$nbDВ~ (bCHB]Je`PW#T$ٰJe4cWm4"\tf<ސQ ?z R'9'އ7~< _L|7\5{Oc=#lVHe-_-djd?"@X;_?T8 25+*bު?U8TH F1<~"ڠ>ru*7~ |2 cjl=\'ᗏeUs$ U9VWEfDȎ{j5l5W`aj9 /9u[⿵sg:*3ӶfF'_!*[ !Bd'4O(A5")Q_4ͧҿh`=GRIK2m*(Vv0SzC5Co:xx&5;ɏUuV޽sCQ Ks7qHɅIL-BM",Zx %'bM󯱝 xXOVV@ʯF?_%^ =9Kaz+~Urxrxy3t܈fIibY/>>`rey^xղ͈?\KZ wsY'_x?LJ01w"Z`b9hX/5AEUn*q!8jB]խ8VS<ߟ ycqj [M< < .o ="u8Oޛ ~ RI>&SH?EMxm߫@XrɃt8_P9QY}|^c= W\YWy>- DiO|jHښ^#QY#Ӛ*9EPÒvҘ` LݰU 8G'OCMB!,YfHpj6+(9yaY,d)0#_k W%3mq|gNl viA9= H%+T}C[o: Є/gm_o% o27YsJp|c$L |e,y*㠕LzlN\D30cF?f>WN$5z+ \Y?~^<"H'~)'+TT|:}"EC`?Rh¯S>PS'6 :~rBCPH4bbs%Mu(^t@,_:-0FW6*RxV`05BUdՃV` 9* Y6lӆT4JWذY/F>xx;HnrR~R^ ’p!5XeEN?{}܀bgwOJn0uMUuB RO5,A{ǿ14j59'%6ɰ˶>Ƌ`T2/(0Im%|=iuIpN,O,{u+\GaJ#%_d~FS3o~,})͊eKWWeyϻcē/<|ԉ~\toТ^@|<1lQc= }h\a^q5c6VWx&mFNɿlG:my8c Q1.84w 3:y-s;۸(KiGfeW1k?g_:;Ў];yA}5|ihf` U.MZq&6[ UWWSoH` {p!r dS0v]zJ"R~&o/9X“w dy{ҐB/5gPqulɩOho)I~xk/~,Ej g_Gԏ3ءEF}weʅN N5Z)4JTNo|av/[frng$|lD\4Pu[rD9HSÆ(B;ֆQr1Ru(Qeex_zTuF(5Px zC*i*!!rt':ASB( "Б#!~ū 9y_ǒk;d/"wR:3. o?ﰃ>Sʿxަ$^M QWR\yF =sC^oKOIAXfM@A3\w\OY?7R̃MEB Q1R0)# JeIϝ?"`#9#8a"SM /C5́RY*E^`4?J?pE~xK50="?3'%a/d=oj[JXxCRSR|$&Ovآ|$^J+%\fz|`I_xG̛0NfTB:%%77W '#(I4PέeiS?(Q>LUXr_C Ĭ0q!+j6LVb_ JTlQIg Q%#`C ž|/ofjHFZmf.Ȧڑ0o'vLkW: $"J_& ɏE5dT~\êՎ 4\  _;#gOÔ |8~G!_O y'paxؒ9v,|'^0kGT_O ߈!?8`(GL5F~ڧŐ*{taH%SFR(AE,]a!u0Hbo)R {̑k7^sZMB*@&5{ {FCT7F(N0'rA|*֓^tuveD/Q7aԨ:NQxIxՈ]S" -L3̝aˌLh~w.3mg@mC`v?|7<~Mc`S ?[V|5)/UkSN9@hRs5s:\x;|9ϘxzƷو<qw rtI>q#^&W@oڱ"eKjC㔌T*%(DvgLhQ%Am(_|~ؠ?}U3tXBE (b741-"x +UT?#%Wyu?0g?^}U'X2}0>_s 6`i?L©U/&?xf5ʼXs?8L?P)Oh{pS}`6_;=}2^h{5IB^r zGGXx9`U[ *gR~,KDI"$j^\Yr&;8;ożQcBױ[ԣ8g7_M?chLˇP N 0tyFbmKǍ?S/z_}pgμs?^|C6Gi=R d,sm%/cbҳq`Kگ#1 9RaMj3YD$^猳[^Zd9rEI?H9"v=Ҧ>td'=Ѯ!~lyH~ao|NPw$W67U8v&Gێux>5aK>]7 G7%4%6?2\F{M%p~+_@&4+ֆ$0ƣPܷյLA^WD9e7UW ?+;":z4>{YSJnt6!p`m7-mJ%$\kbgL9)DtvmV~$v\ʁ ȓ oéU7(5Tgp>v~<9Y=0{0Uh>hM9\Z!km ;b&՝J8Ú.Gn%QHѠ=`&x\;͐HP2ڹ)ypqupaoabA#jdwc6 %,p#y$v_s>bP6?=ۦ6Meً?$(@mh^D`6&9qA/̘$T*^5m'Whn5pCvFOy 65 v9ıx3[/[(v{~}߾)䎇,4WޢWX=jk#y!6ph>Ũ'XkFfDbUƒEʡX+7T~Pqw2O'Iʪ #&KxqcPm}BM}=ܪ]x0P; Ƙ40?4OԀ>_53U_~֭5uy?x%&IU?9wj]T#1"#Ot6O5R_>10P]H|T){h?:%~/\yz(Wb_Jpa>+ng>:i8/] xRX7WZx4{f8$6O )=[:vLLkX/ Om'7>!ay/8]@UAOދ&|qn0XˠnM)JA?ʕ͘"b9{Q UU YU]_ D;C{:bf8`[ax2>"a=9{Qrӷ] d =| Vfğm>V ߩgɿ-EU#zKN;TN9XiJ>h]7+uE|d_Jw'#XJ]_kq*&/} ]! OHH}9w旹a5Ѻ e|JeG`"N:]onn}!QOF &b k~# џ*?~O 䔣,7] )Wz^XU~%7<•~oR|a;Lףߢվ-4S|DѨH4Z!\^y 7'[FqϮ'1բA3fWo_n YpC;Ln>xfW];IXqVJtu\Ś}ZryEIa*ZG";7?O x)ZCHϮ>l# P?&> ~ 7 +şx0~/wYݒn7󽂵j\245Y#;~^UWV W}vwmV,~3z헹OW?l,|.]>t^Bvܻy=Ś~[8a 4}:"\ز=muxWe ~Ƶ+֩#O?z|VvÓ"nx<;n80,]{MO8m{m$~.<"jPSs W\XeG%Oxlׄ+ vlɞ6;ugBXB*(n^{)ԟ*?nM.3ɶy0NM=2:6u8He"R=0frq.Dq!ccSy&Sk'e nx|KyDdy}ȅgȉ lN\Au'x(3a_0}Bzsڟ!7\!tH`1o{s,'8"׫<PL?9 TZ> yyɍn~o)?(ey>L}84U[@K}>$[[+Gݹ[Cf!fHʢ&g%Q)cXP|' ``pyYE2g,ݝںHaZ2]Ϯ;[in!;&kgK@*]G.scH0wϟ^KmvS2iiWb79c28yΌ;ƛ8?iq1?WRX¯_|駏~cr΍*6e>7"?8GBX4$L!K&䏛vl JץnԷQ[YNxxO*Y"] ;ҩݧцŢٞG&o*׵r=5{E9U/2⼄R5)kK.snցpMY8c¹ܰ%Tk4b $Ca|-0utt>?l7&r ? {ъ8g / H^8xR|RֽƤrX_gd(mXuJ&﵍J C庆,1ܱ7GyFT32Fr`b1ꜗUcJ%e/4gte'@qҹY?mYz^Ɩ ױpɯ@IxfENS.K)B*lY96~0ܾ[[\Xߋ<^XP Lg<@TPUzaB6# ȕz[{qEr$M p9ER:^-YO]Adt~Uz/lʜPS%1e2ÅZ"痊a!_:vܙ!̑@ϚG]S 78H1Qc6xPx fμk'?G|+ ?a'߻3ikr'Mx=.x!1^ q|8@V̆r[޾[|/"NOFd.g_(ՅY3r'/?T:p۟3GZt[銜3ȓ!4RM(KB#3l5W:msK?U:dA]sj3r,Xɬ1Q0]{?-Xc)08нl oO|6o`r՜$mh JKdDb՗z{"Ӳ_?'{;rddM6lCKM^%J&|Qσ(R?vm~\nw3M꼈#*0@ψ6o}z(+4|WgZcuѮ+Gy)ƌ% ?Ԏ\r}uٺ3i~v_ub T'ToyzQ KP43֟omߋu`cwo>qƛof"R 7K23Ӭ~Vpڜ'd|B3>Beʻ=~_~|8F'^t R|9Q\|uID.a_@M˻iY*ٟ]HXwc՗3'|/:&juoX-{ؖUY~8p >s|EJi O"|s9&ucH%6d9zkxUtXK[S7O}&7?@_`LKD%)?yff*ךR %ﴇH{V~5OJYk8_)ݖ+pXʯ.D#?lJӜ28Gzu-ɇH7Ÿє?wڿ6ŸՔi]9Ky}}-NfL*M\_u(ӁR|.EO{J\3\7qxY?38Zd[Ǽs]ճM2n(:̝W}X_gW΄fN=5h/+J˳\LbWsmC٘&JUsoU?{gmU3=pedWtbh&X5Jn*o{o/<}#_7rx2/k=Oiљ%,V7{?g_plG?J' ^7}uѓ3+;kם?qw:cYM%O][!jg"0=!R^fZ7AF=RKAqī5W08fkiQ疈R'pqg79eEcC  $$B4B $$!@h)0jsf?V y|7׵V9s]fʶ?~ϗ_?~&U}'fN@FiA우/Q~_9~~o.{Ct8\K($,G)[zkU' bjkckG٥76jEx.:4mYXӲA+97[|W3YP W~:a|hoSઝW!Z0Վzu/"W>7=Wd o{?%4B71yc[pO=';9 ts ݄Ci$SzԅOZ3}{7c' 75?6~Rd)k7/?,?`|oM'yǽYrs zO=)t}AϗEŎ[?9ij(56745?t|ѾLGd0=G4K@L%K45闾|gmŢS|iWWݧ_r-R?'30OF?"4`miւ% Mr>>-d:h-J<*'W`kWV})z":EY[y/uO5|?B#Yߖō߀D k/q%`|ggqnaOƏ]4;MZ>v Oh|ncFrͿ9ϒM08sj\3|`Ӆ/,]?KMo?3O?Vxfcښ5zK>i'KдgqԾk1!pMOf ϏE?& GY3 O|ZHrq>c h$#x5h2S,o-"hNk77aOL=7֭w~ͼޮ6GViǟg7_/MKX==ƛQa>c'&C}:mizx7`(p4BhQ2zZYpJ~_/ %/PœuqG"PR;ʽa?qy[?/G2\f)@ضkU%SN҆(CitA%{"! V8ܰ4ar0R娝^N_{ϾKA5\2wJF(G0ErjJN|MyַXoZWW7mLOr(g j%SC~?4/ YÅ\@*܃?c6fϤ/ȾZ_ڊK?|釁/{)FqHR<|tew@*Oxo9\lz'xxwkzGfmr':R62ng.~6&8S@4pm h,+b[Bsdb}\`65.>{˧i;(FFa$C:)Tlg(VO=@LXo؝w=兟\IŮ~C/ E1xKqIJQkA!< n|H䑱B17o)d-Bs [NT--{)=ַuS&Imϸ?{}?~F17Ifcs%,)dL|6 !\ASKƏe)u!F1@*pJe2ƒ\giJroԞ;~dSʣ!2Ѧ@ tZ ]P9x g}6i}+!/PǾ6/ 6g hv4nƣ'Covejo })4gHieboWɽ݃6'+觩 t)jOS͊2Vft[: Q6`hk Lظq#iz뾟L&HR/^]>d߼6ު_nl,%@} r/GyS96O~K[]w*_tDTۥE۵.0J%e6 _sWJjgƔUR.v¿RCWXw+X;7o^_ki|(ԅߥ}-!T&S]& w?.I#|6^]ӾL'Pcsx7si8d* e n_Ҡ,˘"⡔62M&ޛHo_]{ļgp^ ]GeD}&iz\NJ!TP0Jb팸o͛o⸘i{ɥ,sF~O-BDKAH3P&8ww&r߮_"wzq|+ Z{6J  R0a9Ox/߳/"VwthD#L_2}[b;Ϝs_?B?QI-x6F@Ap` 0 kp[ Lɕs~&Nk+@[$azpToy d<1{7ӘI_%xQPRȾ-ߒvO~2)ti;Ѡi}{G"9 ڷ*C9/F=LӒ2D"]'x/WtiEѐ(3p1Hh!R]m~[xGus}sF[KBN(Vx(FHe~z;i4iQ+!B큇wW`U` VJ%h!FkIFiۓ¥'u[ LEMiJPO ߮$O{>/:#E0cWdp\GO2%Tnk\:i?f}7OI6=ÒJd}7+u3=K(߆R96]swɟ))yVl{uK… {C9PtJ"m6))) p]W۶#F5kv{gB5|xem )crBmisVShS~…7Sʱ͇jJ)i!-:V Ln'{7==pяUw&@z"oWh!6=R93|ߐ:kR;q֙+nήّ31BQ%IJ# K^VKDн2Oe0?Fun;Ó+˃8[M[UJ>_Lxڊ>vLp$uQG2f$b/V_C_ݟ#2zlóΗ/M򅂡"C)Л:x˧7~3ښ8fv#A\\%C->{7Wj 5 ]X[b}Sq'fZ/k /V #hK7'ݑ"X_Z$ACnjL{P]38 !#ڬ/}+ ?VT6< MJ>\Z= -t3gDcs](-܋.9k sy[Wu9 k!G%δNMCD06 S(iCFB|Ii_GA&ƻ?o>r֢b]Ν''lobVV4l&E n[GEŏ_pԈyp 1m_IiiՔWQdW7!^,CvsNWLJ՚F/t>F?Z)9\QkOx"nGe5nU˫ug~͜\Q|DdR<,3yH<>`b8h+fw㯖ō,{zɣKQ*V > dC窸>#{W` XaȮ_K7ٟQ58,XF{~ѽmh(9\WYuUZJCv0Ѕ=w¶Iv]?Z{^hz{tNg[q}a/1,-XfqSUp '%ס_Gz{wC(RJ H{=/!BvT]gym}*h)*X/O Q,-4s8L/<]>/RMٿNp=i≬kڙؒv,fޚpvT#u:5w@BN̴#lkQ.{uAW(m+(ߝ;t{Vm[,_jtԽIC>f%{pc{kJ͟^a 3Ge8>*ž'd|w#h1T0m4Oi3eȵ%0eŢ~܌D)f4;(K7_&^ssuuu/ 0BJv/ ֥ro ܾ|u _:>☛;WW!\"JihC [%BЁ3M_ũө yo,gW*ƄI#[*e./f _H=O[1uGX~5'N-$!oyws-gYs@eEWz9>H #[qYG޹=/ډpnyUlJ\ɗ/ildpl9m}y'_/FHBsB/uĻwǼW;k~/Q%>S;aw.B$6on8ؚIk}țu%6 ,sf{UR#,2OQt)O8~y[LF *Ԍ֑BB±=>tF;PUP'۩:vWAY(? ܿj1;j\؊L  i?FhY dۨIo!B&L,b BFRD6 X Vv\:tN 9ƿj@ޑlJljj g ~,4ѢBY' = ~7a<e1Lik!Q8 /Gi/?q%GOQ%|BWC6zlX%uak)b /l"uGQ a Fbz_$U>WA?~' C:~+?$qJ% <iY{\}'Y^ŜG8"Zey/J <,oDLV8rfT8ulU*+v8wz|ShV #"3I#mO萣'M@/{.a \Q'ykg an͜l?M%h,SBam _r쭂?(V;p쭂~e V# K #05??|9)OϤi:`Ƕ-R tϼ6&CuyYUFI W.NW6LN}B [<4$wB 9vv(t[< ˵]^?`+uVv2gbWklOehneɽ\zwo 2gb?zV'UGg 1BgV@b8JEc1Kp۸dL)9`Nb0-V!gȿ8>v/"t//;#Y(eg[֗7P~ixriғM dpLk nlH#qoCI xFIB_ gF<Ĥ-04w! 7tpb-PQ~|5'h3¶Mvf&9ZCٙAG rJmEWcUө+HCdo#Ȩ_g1Ft> ׉0aG-<b̙ ȶ#>(_ʌh9°|34~fTxbBVle&B'eWB]`e>JhUm)zQj= |.}~azG[e/q26"1MMQf {gXI*ޠYj^(IXp"'!PUH#{9`Lum4 Ұ]`Ci<%)@c3 $*t,"7:LD>/-=|" j᳆(,gP y2~{(\я8wnSr?>#Cj̫@g$ .a-g3RyH {2~c.-Od1} C7Z (bXxv`t\И]7R*SEw+ }o vƊB` >?$8k&d1ӱZ\͸.^xmUL/YM@7ߐǎ{GoGІ#GcG~FMK>_'Kɍ%eU#Nڎ_v\,Y7O B(]=R0@f Kɔ\ , |qf4L~T{:'oxGq}4D~.&Ŧ&#i#׮2^b3NevBݏ_芃b 9LLy|Y3ye& +^-#d֦(XG>p3Y^RԻDGjyCqr֌a5tGe ϡunQ#k9mٸSPƅR3ϗ' įg FJzK?nY'"pIo Umq{n@1֚>ڱrje40pDX)1Wm֮]ˆ qRz??0Ag' JRNԪ[exl!K6_>, $>jI0} 6'r\xy&=L m+_3 K Ox2bdN'_^~XWY(1_ Q̢嚖Ňi@w׎(13nAK9Ȧ eI][<)5iCJS oz,4V 3.a*)LFc ϐd/E V<(4 Ӳ7K,\f ^/ 1DђkIA4x'bc6 eCZ*/h#;,lK+&?]`s5(xf5|5| xh*[`fmmڒqh`~nExx|isW~4r~ %ܯ,9l+//;::r KEjF<(O?¸~g^;ewmU+rVẞ4U{Z|/:8 㹒oLČhvp[\~qmf dw` `, : -? F49`A/ c3;,zŴQ znt"V)7 # gN/wy`\=Me*iYQ/`y6y|K弶vr~bVi `VOdI\<#B[oǓo>حg۶G| Ds&ڂbE xB*@mk<7-62gI ?2@]KGYKTUJ-{S֟^VtxӨ)₱{| z(ڄ"+>n]Q!t@ŠncagD0L!1mH)U?1/ @U?,` Q#kB2y[F 1>'/Va{5‰%BF)BQf(kiSe . >jFP*du&;)V\z%Fm=ߣӏ()ªu~HJMt4x4{sQp{b[@)E`\dI}׷T/M?i7IԳSs$sKQ_if+/ŴwtȌ&~uc\?/ .9L?ERWq5pɡGNmП  ÀÂ, 77}35\17c >%l,u(EQEqhJTd_Q?Ѐ Bw+o樫6yt"RZ40&R[e[Y5˚啕Q׎fAoo2MS~JqIg^\NYS3}\l<ϯJ?DpI6_:P9 ܗM:1|he [o0j?vM>$ Ű+l^k7B1]{Ձ?LY gB士u"z#N<ѧ=\lfC㩛; ӏeG֔HI$EЮ<8qj5b%4g$vWz:t$vvbl! F7GF@9H F@RIMPS1y`` }yJŎLVi\Wg&Eȶ Z-%jVlTE4 lP!$sh*BbFh2% li"`?|)^w1l|Oot/ٙ_zw.ٝi`e8xu:}mĺQG0 @AEZ088N @9hLfpۭbZF!hJB؄#f6T/zEA {? Z13&mC.`FeR:o?kytF od8> wBT ƱF*iahJ`.).;` "K! qH&SxKb`(+Z x<8$ "eSHv(HD#sı':q%&6߀!%Ѫ,+%FePj !HgVZ LTFlׅ=fUEI_~lC ZZhl[0[U I)OkJAkhsUU=WT\$EyaRK!B F >JU]•0T)\~dg"^?vp͡l(y2VhKÄ4)"Z9њۧ[N^ c]fu2ͷ6l彁4Upu)RTX}W&WEY6FAJmRtPPl *>HK΃;^A*z a;'Θ<𷝾%ӎI3HY:HpBŃysL}"Åʹ2?rQzw^|蟞]6PL2e px k^? ޤ>+fe, MO uָfMi\(Rۦ$-W il!DQV!"U-Ti"2R[(}AS` ӥ[+ p-* /&\qGKCykR=RhoJiQZЃf( ("ʐm-ME+ r>v|Y¥?9?5?6Q3iS$z&Be=ϣwWtwv0 gHȾ_ĒkG_NV_{nE@f7PJc(DFd4%")gʓRc?OY'#gS zˋ,eg/gVڵrpYT  VVK&7r~SYAu@$Yȏv1ZQ,p3K6}C?d (&TLq Q,V b] RMBL)\ U[?ArLp2E?Fs*r +p ZP{`ZY2d_=Zy^T3FAkԦgSSSˬY=0`ZNȑ x x*yiDN:k+J'GI &$M4h%'TsHök`B2]uj۾p~iq~N'/FsJXA HDHpF1_9]krLxx%^0Ϋ'hŒ=7'Lqf5B3X5b`-u5Eˏt 9ζ(8 8AUt}6'3g"uџAgNm_GwJ ̘V Yx } Ԧe.R]ή&_9õr:[kd.7(l#ëY„k,5M_*@UI<Đ֠ŠS-qbyTy'瞠|Ֆ*Tʝd1m RYp*<&Cg9zBG!PZ䳮֊@*ֆCSA t47_ _8Rp̡&VXd8yQ ,l Ta5)9[tTQ+"%&k5u僾 8Zӹ~5N ;Vї3w::ingZ "M,gT!w9SLcY/ /12Q%F Fw)$ yc8I?:NT,'^ukggےơ6 KAk< PBʢH+{(ȴCIh=TN^ *Fi)Z6C2u|  gTW0ZB_AGFKKG~|B [(T؜nuG7$}dڶa"ž !ekˉ6|p)\.Om@: 5뎠b!उ0J (=o3XKq?5|\"vZo/ޙ$v[ sܗ~*?MaxUqH /R_\xrys x9S+]"6q pz9vGfڴR1ng ʴN]οn@jDyy@gWƳ齕7k|Z&yDOB{Id>6T:~=oApPgP g\o;lY<=e&냸Ffhl߉z~{Q5dcOl. Hs ?q.]~,M&QǑ#,Ж)W>p8ҾcKu+Ls*dAiVxt$$D to5q8_\ |sv\?wfʯ~7;XaB>.u( )XbY&e^ۏcl3@.NBl6"7#n^"A`dT NDfcu3u:$ 6aqFh9Xbgf"G9^|'͋X`g4FIE"gT  P)_ZCgun%9tso3 q|Eu֛ }Y@.݌{Wq/bBMB{ZJ hL>Ar9 'pF(z(ܸvsmCQ ..aOJ#m3Au [saUo=6Ϻ 3ft56p\'܍.+ ЯdWU"2@{_aW/Ͻ=Ċ)_8ӗ8Md:kqٮudrn}9oIFy.x(N?RxDZ`jZ|io~/g]|3e:MԊ/ẃ0 ˠJ,ҀNEl嬄7w"IR3UjW Q:)O`]ljWեZ{͛S5-WI*G{&4 8Vgηs;ٱ( A%y.;̙s۶F(B`<+ zyeyZ /*;9D>] y[Ig$5h+R5~LZg<&s 7t&JäaOÒL> {wH@ %DGR/eK&E$H) _OW5Ho* j)e啌0?}x'v F\uOuzt>ҍ|/%3+t0Ϫ;ؚAw-aJ2!8t?X/̢"Jnx‰n"G}Ǥ@Ösc 5'ym|xقpm=7H#9S׊{ٯdoFmbBIGuL:yw9< pyǖRVTЗ\3^,̕u~erJ >cjWߟm2 g#GXش"aޘM:(ݡ^f|_w1[3*ՊF1ۈ,*jY6f0DODƲv6jhxNg+ BB.W ]%Ä*u4"#kMvĉ28kQ 5ȸTC =HeCVȧ2R`<+>ʳf0"W+pqԛyg N6') :ZlvOa%Ja%Rç8K*cjS)!/XL\SVZq=IJ?0Gh `L "PHy,^yUrKK㐙An8c_(C!S/ɚUA(`Eܰ-x2—a!䧫gbYD)npmRJ`Ry9 >=TŒ,PfٔXVJD6YPo5T*EA? X@e)MIߦ^ͮ$]$,FuR!-:]e2^VtLfw'8ݗϺ Jʪv#t+@?<~+o?м*RF#qXAm5Qz&dŐiz|E};Y "CDBJ\/AY^Bx)ܳCh YUdcz ;bx}p_aL͊Ͽ,<iX^i>nȔ/ۓ@)8 }pМ$9 /fs]A]NrP/*7R.icrr((xep\ԑ>rN9>JAiPQO/m?.v9v'/ Y6uٸi?/5װimnb([6&O&y3ݜ2b?f6؊ɦ_y:=b7BU ڠXlp"N\N1 }?}ǨzNaWg@H?c}8hITFz;#kkz O&c_fTj -bA\Z^rMF0mSM:2dǓW#xl7cyw| *QQ Ǎ[)lD@W[b{AcUr:2c'֑A=iS]^, $s@{5Y8ml1 .  _MaPH{ӨR M2m6htƄ9JÌi͘q%63mІ)T[pS}gރtK]jμ&)O\%%Ӱf\{嘹Ɔ'6bP Zk!jZ!J,OGGo)xRyē O|!*Kd홦coݦo"鸐C%BGm)Mɣ()y~orh $Nߧll"4y$4HDL) &wZIm9x|)})iѮy{OY׃^??ImަZl5~>y+N~rf j,XBBmw]>CF֋{7L۾wh-6$'< 2j>cԋƩ+#^L(ϭ;<4kO7pM 9(\'1q'N}a[7xr-CG5';7^~ FU0fOet2klj9h4?}LÔtMOy~#ѿznnu!B=v"N܁d-\)pN^~^ "DdF[sƞV;1 Z0609bl5s*(}B* †ֶ$Lvh:3BXjߝ,5J[mlء/Sl"X\+9-`ψ2ꭊ,cO tS`znuSQ.9>.)ѕIn˺tѥ'u=;κa数]<6v$}lѝ.pYփB!.brӓV_,Lqt_u#;ry՚/%=0;{6_&54pЁrLUEwiѓ'rym:!uۺ)7vGH[ovV{e灾M}[%tōTIEvG66\)w2{<3Rfߦ  яwmi5- b)U/b +ʠg8y|ê4 D>֢wOofGm*Q{ɎE\"5"! %A!IuiZ8['%+۶ /.i}F#-wyW]-S VN'Nu8pF+⧵Ceǁ L1ps+͍Á_㪺tcCrW¯KtVۖpꨇu㙬諧WI]$uF'{氟o=gx'S^Iɿeq1ă[7|-,r÷}같y)JUbM mQYo > Y8RehE8ޥ6^ [Gg;/+$ e/HӲKZ[˨ः䲂ʼ=J6\AuUg` \5KP G>ɎU{Fh)Z*-P`*TT16 %  7k}]W^%y{Y#Wab )y V+ۄ?_;xWJ+-R &k7zDKm ƗV_-4%jpLq3 њ%6f!.P%LR<ĸ%8x#VM빗}p3w$W\|y_9>TҐm'Yn{H=?aɣlEnjKD<|]kg⸞LfM<x7r;HàຬZYg)-Ű,2,3fGſ^quOꊧ?4Y)#xQwI!2WjU6:cUo_IҲTl/[۞#<WJf}Ӭ)Z2YZHeJLWN>lOq7xܜ7SFk%>Ǫ'lplnU/;\<壾VzRܓ~iet`ST$JrGO>£u _,3|'==_߽glr*gDh螏?'ϢGq/_ɜ-ZlO)״ t ?W:v\uݬkcvH?f? ]mL͉XbOwjl伫B Rik8̌"JɛnzL/;ַv{FN7V}o'iwK)Qc )0’w-zT=lz?ߨ`Sp{^>`w֌-8[n{zhll$NSYVu7;{k¸v= _8wú ):jVYbOse!Sl xМ kͣrߡwu[#~mZ#(vkwo=_-6\lg9HSӒ3g/>w>Sv#pq<cy/,٧ot9hCeG5{pO|[xCWEZ6 ) rُ;˵FxJiz2M\|i7?}ųWn zkjQ^j8L\{Q%#kz^g% E%,K'o+9|B7ד K5I|b,:I'9wPCc> ⤑!T|q- @Uǽ\\=ݕ'oe8(hRh'ӟ wW~C 5z>2B@O<,X/N z]raАTu7M)%xռYK0}g/qض~]]tSZJAbi!aMөSoݳ{=ͲK.U3>&=+jPJKTڎH0LRSZa]yx| bo !N j],K*X[-2݌O w ۓ$zW}*E.*뷎IX\_zwʃepR)%0K@<W7lޗ?{7StMEJ LS~Xc7dsUzr~$#R[<+StҪ'ղy5?t': V?wmY?2-R_ `&J!JSp]l+8-I];ݼW\4٧NJfe1j WTyk\m;^ow훛' K,9<+oRFBk6EL¶iU^ΎAkx3[=#Q<7,@E| J[_וmqYGMY\gھ"%E*rrkYϡ2~dՄO M,/ҏo9(O0QW_ڥɲAeEP_$.M[sf!L^ѾЋm:tlj Ն;6,S`[ʨ lڑ/RyKunmRFa|뇫Mnng,^Zm%ZVR@)O)Bj,)-ŲގmXÿq͍WRke;ϐkC~~lBK"*.D G!*G*BLI~X;"`7&x,-<_Mn8{߻OMqv]l_gRhM#Fhvc.lBTy.0cm"arFNPr!o6iZ|UoHՎzu/"W>7=Wd o{wMMMr%~oOWmB|C~oVؐ@u;V+H^'뙛}WNΜl$SQ q~0Xל4K<% Di)>^hx_OϨ*g(5 X*,LF fo9/"~>MZݯ鼞q(GxNTDB֐e|?7].7ER(_xzZLkę \Hɛ:al*ӎxh~~oyЌև(]NB|ﵯ\e>u{ Hc۾kXd85AK/r&fy/kOkz)X`-(@'jXtx}|=e12Z -JS R 7ϼl޽MG˖.sXrw[ "HPb q5q\m thk:;wW4fdO3fF6! WVVa4XRډD"#+*X_^>%pB;7s&'(|-1BaV^8jV~MH#İ0z ` 0ll훌Q>FQD>ٱ3QU?ex‹ Wis&8}855k4K!&ծ\5+=9 MG<6O6;y5l\mY'Ϙvo!Ԅd-B쵾rgQKaYtx K^}_>CL[i=?GzƿC{Uv4khKd k?^!FcM4O}ic\r%Oqsɚ_|hln6Y~| [ gLwL_ {6%0IX_Ebϰ4$ %oOorn; i'E}˓SYDŽ[x۝AB}!eXZޱAA,Lf >k%0llŒ%KĐB:'N|ƍ7u]q(*%{eUu㏽O}ze`:(n(5hѨbbF$m X ^mh0{޿?@|>﻾kp=ϳe-vXMMMr`̙$%ϟ/a ɫ/Rj>{~7brv ìоyc7 |7|cjGY! JFܝE{=?t Т9lKqh筝k'/LjiӦ/Z2N>a>)R ̻BI49W=cpg7mh^+4њ& ; UA6s4`i3f GS\ZgmfGq1f 0{K P^ktV^\ے4n#8(p$v- ߫ҹ*鿫zxz>!MqD-{awS|Ѧ,S ޯ/{dSv@9V{u+?/K8،'AQf) zt_yizY31mQ4bn"daEp~mI/sUw`BIoU,Z MhɴE Yx 0%iâj;a(f6לI#(*J~Myt=ߎ_vGQyQ''5%ߣY]1GTG1J@)՗Ju~52T &Ġ.+>Y1@СCG'{^v~łl4@qaI m}!JmE㶶w1sq Շػ;:?w.0ty->[o=JJJjcH$.׾}>?`mS9@``0Zfӹ\t:}/ZL{?<,99Ffޅ~qr+x?^~o= ͘a;7YhHws2z_l SSccoľ\bSZƷ׌ fșA65Y}߰@.7RTݯ+DkUTV2vvvL2VKU8`Rۛh)JsPwb zOfΔXw*aڙuZý2hЁUUMEErgN{tiD-J&zLtDY(ֿ&)3 Ouwp툛Ī T-tU%ёT Hc[¼$U=d7׊}[.5ŕ\dVO1mWeHEQ>#|*J&vLtDipI|JruokO[|/7_E*RVǎ( KBKmA;уi?KJzCoUWhߞ+\yzoذ {@>^_?RsC=Ofs ʽ? h5;@N>q%'naPUUcǎ=fDсl_B2dŬX6m:+h!fcvZ`rƌnS\`1cx衇R`c.4 .KxL&:t)EEE I4l룵uivւE@ !CH0!WIlX흻mݕn{y#o>/xv;Kū뇾ƾ{ښێ4>蚒߯?rY]G~~\/f %,XuF7rU=cww8g[ӲXW/t\nf<)7U~KR"Li8w8pI{(ꎏ3j;^z뿶_ADC fvc>Z(zM疟<μ;Y5e5F?5yW--[ Q`WY![û PQ Bx*" )4%^_Z'?^1$aef"@}벳KzAv@LJ-۵hmWKA@#. G6H$Dy5Wyo6io2J}l0k(DV%_Kd<|I* ;_Vf5L)54>BI1Hנ VKI ZO6'6dϫJ`Э̧FaJwAR+ήFu$hHNWϯ#3A3Pz??RZ)_˭)_eHJ_rPD x3/΄g\}`^]_0ْj_%r*N3>8Ţhߩ!˻*FŖ|IB?lWUǨH˿^5h3b+`h< CsUg3%Y> Y2A))72k't 2C|8% MC^ 맑0|pCY|y7`?5l~NLFy5#Z"Ba'6Gn[;niСCw}UVVJ)\ו%Жe)!ov^+6S \~}u8&e@2ih%ti&qB`mgWN(p؞r|#j]ׇU1'=#eejp lBr5VG&WסZ 3kE5MY_R[ L7 𳞡Ua (B m}Y.`R#X2.(S!K(WE#:/4ȴi>x30*M937~~,*K\m? ڴX@d㆒zS` QW2rngαސl[AK#6nM8Hv. ݋)7Sw޴0E@mݾ=1/-ߋC3Z`B$R{"vs 6Cy HW7W+Z|tH(>mw1- /rp/#a|W|d7JQW+hDOP,Ы4@erre:vA$ :4~}Dw sXhm)@F u~rGӜs>l}ݵN>}p,sl~N7  dz7uvvN9sb>`)bĈ͛իWxy pwVQQ뒒p9@:{ٳg pw;bĈ ^O$/~n?RIuuu4<ϐRnmVbT\.G4աP_n1鬳rGqೳ4歱cזĢn2PeaR|0Ogo<p  W ri$Ċl=}`~~Fw˚2,AUg 6U}˝@;hsa\8}` afB''|]ws݋k6$eߜ;zygp m]6}+.*بht8"1MJNH%[!%RHLB % ӶQE8C!.9JwгF=L\i rhxVVB$bȪJ0@uK6dn9BaIȖXG[*ǼƏ?!N?{<./6ٝ(H@4m ZE0R&X\?t&_!wQ:`H13~gIHRTUUm-zB/ 90zν~(^|8x@C֖R `!yK& nG~ RpIR[BHW '-9h_H/p9~[ii\ +8Oծf20ܮ~cǎ=<xT ߁JH$;o?lٲ74hШcx⃧N1bVJd2)N4."? &W׏(X]pA{ 8=8q"ƍq(++cҤI1fx Dl9ί:tem4 lĶo `y< C"fжvN77_ou3B#PAc?1v7^ ՅApCsFq>sGGz n UGNޮT*IR(a-vPmϮ /M!h|j˂wbx0rD%--.73ئ:9E2v99ś+mS X[;'"(;k"*+Y#BAꎇimkuSOeRϯD#H !t}rՃ(z/י/7#lOR}E{p6P0ʰ늉>̐Ea|!m]?BUZBXTɭƋwaC;´ SZ;VfX ǗOlk 49eT%tw`u^n/ tVcʺ*횽]b& hO٥PYdPx<~vMEw Fh|({L`慧"wѳ$!< ?zS)#Ͽ%)V춓7G6X|KR,_3i\~7p[f}JZr@`h:8 ߨoO,xXJý(-ō7?П2uOܠWKu}[WIBVzҰч/ά1rh }>W_CNXIurɕ0vQhlypG]!Oi9 '6GH휡]KorijHUiyuކ}ք0#DH;iL4G4-F?7OLOOr ˖-/3tllm3Y%cUWcm7~&![/.tɷHR(|Q>s2pmqY2g2WE,AySE:SҲx8K>@U>x J/_}1c(..>w: ^X^JoNk-W\y.B!;dFԼy3fLɐ!Cx@,\Fri1Lޯn>pTsY4z _iGL9s gҴơV&hAu&*̱bolk{WLfu]G]='pEoP05?6NAC`ssN+IU.gp"&U?$ZD*Iee-69x1+J}HilH47RHAm6z36XLk$Y>wcg|8?JEdDfCoX1c0ZL[Z Ɨ3@`Tq}h2_~K'e3nd/yci'?B TMGiRy<5/4aBOW|ϗ|5!hޜ摧s2(-hW <_0\m'B h%Æ͊3~fGn宛#wdX{4Ǎ2: J0LxjJ5EĪ-a9@1?9BV4tő=,]9p.pwܾ&ve*k;ܑ|vO}ӪkMiZ .c>x"r]=.覴@) zVqfKO3l|Ho w=ĚɃ {r`CJ+EQB!DlHm$71ƜPKY `C,9Cqs9lU+9|Ts=l2| ƏWg沁-@`r(I&dqEw|0w~1mmRVgKZ6hyʰx\řLy8y$'6.Us~Lw7%xԯgh jM~6%דźt4sZW? !TU\\Rd2m{@fE+s x簾*!ĖB&^r=Bʻk>0lqРׯ_{-`Yx衇6lM?O>ܓO>g2Z[[)))7ߤ}ݗD" c=w`ؽnnnnPee[.$ܽ7 Ի,46ȣfڴixeFWAIq  /<ǚUQ =pU3xXu]{lYYUOu8w*qݏcxv$/G'_+Nr>@6 n|\sv /)"Q|_K㲒'rN` C̹&MܥF9'BYVؖ>oi44j v#Ups97˲/-s)`PVn2n؝m"VcS>IZhYьO j*4/!HjZVj0à F}c/5%jE@TRTuG9M-gS#B; wri%ipAy70{4uPTcY^]Zšv*!ՃlH4$5gJvTFJE _~.Aae)vϣ~OmFu}r݃Jpmeli[twu! R\=5e}~ 3o:铺F{ J< K%͈2tǙ\N  6؉&d^Wі՟򛍟 Zsy]Q=}Ǔ2 YbIsżU]+Vw)^1yɃwx%Ӄ?!$ܶ)L #d{2أ39g}峮Ccu5 ^Y9I *XE@q1. (#26WAu|<߹'rB#/ǟ&1bH^rhkNEFQ$od6QT :4NZcKT!]cFNiIn!$[ib|):ilp#*jL2P,S\}a-A`W iJ"><:e {=0R?UBy "GXBEu1? B]g#FDRU, 1hW+v({:&Z%p@_h8V\޸IF)ƎpqhK%cOZ /)+V ::LX*C$lPWk#h`,&Hg2j ڻ</ym:?!0(6-r NZWIDAHjQO:#Q4F|u 7ƗrDU4 2p {{d[̮Y Vכy%z1cIJa&ElJ:WO×:o5R |gi}mmnL=XRQ#%SS+;:9D RR/O/_J%Wa7wlH +VbRg+hp<9`G~spSJ  'ȋ/x<s=w#fI`K2{lzzCП~invm7v7777|S4q%%%$ u-%KpGpI',I۶{y饗0a^x*))i^TĎյfvH$f1qDy^!'R-**>C1zh!vdCCÝX ۶vq^@cw|N:G2f!$_v|"%IWnA#G~4*"M~¬D D{4i\DxcnЍaN:1;(x21m=1.-33,wܘwQ6ݒ'\0*wIy$gDS:IvM~wt2D_~}o@}>bW'j~Q>AI0`!| #>BD$UK/RRZ>M(`_+Vd;AL uC@\r\Eq%F^VT"۪ўOK*ZT2[=Poh,8;9&̒8@ޢlASBB!T^kT/N>Kў": mV෕B2Bc<飤@0_q1 сØ?RUGÒU}'ruR[)5̣X"`SYG=9޴*+O*J|fv62,z.q 0j rA) $pifSIT+e,8Xv:r~:1C,H: ʄF>>X )%CR(A(JC hZ=wY 39瀆:j/0BcSOH$gywx0 yzzzzɓ'rξRP(O<)++f̘1L8!| ӟB,Ys ' |oy/Y0h4jK<#1ҒB40 $$R)VZʼn'N2,򻺺xgώr.)%U5t PZ!`p`|1y<ÇG /yG-Wu~R]3(_:=)C9y!ci\' q k=dJ䓧yRI| Li6e\ƥ+w?k~Q/?eDU 'dWy (:!k[~cX =DܯyX'-Eyc|(MXXE??q܉&LnB@k~z͌;j\*eב%Z+$ (>FhkePHDhH/ffQYhC{wū1b]&/} JQ|97ϢSSN"cK@Cvߘbk`c*bQ82Jӯ|Th.<3ȬDe>Jk =P>nGg:JT3F =d5Ƙh>#T5u #rcꤡy}5]{tQ1QZimoS8{JA!BasNe3)> k~`RvgRZW|Vw=2}1lBGq ؍k_CWoЭk93u6s#3u3M\ " a?=o} x=6wP:ɤ$2?eٸ,.l AJo̗1X |0r,{MxM*8plzccʔZak-xܐ51)`mjmI`y( NP(s1<,alךI6u8yRD"aضM:&J d2R@ a[w\$?<eee\[Y+Qʣ:T§}y5n:CII J),RL&bŊ~_3N㌛~"ָi;0wA>%EEy Ң]w7}}2w O̚$ľmtn&V' Pm S,\c\R,S,<+zuv0ㄟ"e1N~>45ƣ|MǝLb^q~z|_*am":BF4}qM8,V,1pX"lj.=W3CDC7;En`yl|Ivi{T#$2ܺH rp|9"x_!2v:OQzu*ڪ#ѻha,xZ+tꬋ M9G /~fvߩW_bO +>eߟϖQ_WîHr=;rdx D_6BoS&)M&{Bg*?pr/rJ#Y@ k̰WMNOsGfsSZZҞ6<B2 %,5L n{dvDvJM8q.;1,)Hg< ҊX!c2B'.-dؐJR]>;qt?_R@iK6}R-Yyyoa r4Ex?G߇yf0"Tċ7 Ք6  <گx!$?[H0CmJwRQ/=||b:WD9"DWL>0Zj=ۊt7JB&ՉL$((c LJ(w%@奠|t0*+CJ) )E2U6SUi|JV2]+}v-\)Z>Y@/:yk}Ґ|5=dPj ̶,k[ill@z),`y O[oE*BiӦQ舕fb_&#u]O׶mJ8ꨣXx1k׮娣bʔ)~}ѼL2:d2m"g̘d&9믿qD"L:c9zoZ>t;)|Q.%m{d:sG0uT2 d^t+e$蚛>0y)k|ojYmD$A:CbED"Q|'x*g®cv,[V.oI.~đ.S!/ϘJ<-KE@]uC {dg{:|щ_)+wex{*yd h!Z)}B%edrY|6Fjk]d]=cZsp|ZFۮZlT:]}at(fy*,#M %͈7nHkܴ ;ug2<1Dȡ1γё=pf7kx/r( G% T*"娲fMw}+eP|grݬ 㥶dT(Loz ϔj2_|g?7BǑYe5>`\Kל?߿5by&7"2}ʷ(\8m폷*AM'mlym߫ˍfQƳ8~v.$dc*GcMD;jr5 7K6l Ke@l'gcp6aVƈZߟ%؃K)9t՝ڄYTYޏV.8e -l_5tlO/VAǹm\ -J`Gg4-H+{E_GŌca3ao>8ߋ,EodҘ ;;8L~zO@j 2:7 '`csRd"^'NЫ88΍"񤋩 !IEtc^|?# {+8)s/ձ.QJUzJiUQ%k7UԐ3XP_Noق)RAͩ'Q4m*N:Ms:r{OC RxWWۺM i yLdrxR2 }|A@g$b!v5xX#㶥OyYhu=> IXΑ>B2xYkׂ{Wk 8D"~_/aG?bw'Ns5`sa=ફJ)=ЭYΨ-HCku)--kqӊ r~;BsO;OR7vdUX&e*ͻNDRHiY9,tAIWter$nUtg 3#{{66i0#>9bЏ%=iöɔqUi8蜘df_-@B;mфC"UxL@'s G<[ROն"*~:ZNJ6"2ZJe:T*Phv)ElxM{kcYHj2M4ޯ;:w|E"V*‚?|://? mXAuSm3_ (oJP{eǧrz|g Nʷϯ! 蜘Lj_W:1_ 8! Rdܺ.B{WaĂ2AٌT٭];A0mJ@ Ԗ j . ץ4(?Ußi=]}vs/? C1bHF46R_W~2dck+׬aU_T*6SJ/`У棍,q[UVR94y(9A&8bi<r"g,pAev3#b@5? wf*9WrqI2ɞ=ݦ~=rei1 oOsDڋw #ٛ]wϽG/B˺U\urzd^^DBEO#䱡øֶ˪Udf7B0OH"RSCx] $,4,&j-<Pi~``6ut4Ϭ8^ÕGYXc''DH8>xhMT@anZol! RLkM&f酭˄-[G}˗3fw_gkUhhYzB?O̝;wU*fR#>z(B4RJJKK} yk|@W_SvW{汵׽v1º&l 2Jj vGb2.): \rg׆ !n.ON&|x<ՊUJd2TUUmBR "Y;lFc]](ls }h4aq (Zkzzz0 d2F*#nHyyd2LѲMu . hvm8xvNcȼPIw ]'D)mE\pAn~ۂ7nnjjM놖V N[BҮ !FLyT't66Ɲ,gcR;Q)B:i&VPڥ6eYյN븫uٱa\(F * ذWɥ)X}݉Y>*b^uY s壔! +PY* RY1Fib|bn]y|V1se%cm*uXM*D@bhy UeoQRcM^ٵNmO׍<ڻR.ٕUvqԎ"0?C<rt#@ZGiH hKFjL%Bwؤ(d}.?^r$d^fj l@)3ӵaK? oc]k~W.cg;(8 Ei ثa)=֊~I{\#cSٽ+nR4koyzQˍ#G򄒦6x5 0ح#dDM&/zO>mIӑoTYbr'-mjU.n8;VL+<"!Z,Xp+W-ra7O+Ұ)T>Ņ}EG4B}zzy a-7v\jʮTR}xFf2rf, +@Coɫf RI[~kWg}/% 4<`xCe3o$ ]>مTm ن&TG Xb丝6md/9S}Afx;/_vFsLó̚." )%BO{ޯ~ JG CBB`gmWzvMC惫PJs]|Ҡk8aQc1a}#\DI}#Zy()\sm5ɒ|^%V0|}8??d ih$Zp=ݬ_e˗ksNGIhmː: %hqGwݵ)qBH6Mx}M^~89,%U@Z3:1Gh@VDM#uco,Qav =Z0y@en\FiL'l^?RzJ^:ZZW p ^nZ!!qHmvCF־&snB2d-*UBID<`ȼ^[ŷpFսtuD19xMY9ZVR\Sp}$bmx=()|d+~?g{3\W΁y}Uid"8[+1A&t#ަREP>ԦE3gExFh%5y'C47c} Ӯ/LR^CF*ԙn)=%­k&vezcfQp7izehR5t[gcCg+~>suEoƌwmNZJ=ҥɱcn;o) |Q<}^2SO咮|Vʏ:{˹|p[f&{m??mP:U@P~ӓw/X9̂Guk>M/% _Ctkz8L]vX:n #"͚={vv<m9^L&ûAa/I3ƃsU}˱ AwYNu5G5kp6~"ݲ u_{+P\RƏ~v*콿=f2fKǫjjj2 .NvުFz;h]UyQ|/}h6gt{/iPF׺ΚT 4RjooeTYFiY)ޯ>*?be{+UPR@BhF͟1rݘ0zwZx;#o<> /ko,|18-Op<2'A&W*ۍ~缚+Y3f|a'ZV|cwWƬBd> v^[$J|al 5cuya\m7/oL9`0AJPCNʏ[h!o 4Rtveέ=<?vcՆVZqoՙR !UH$ KMȼ"_8k7ffjLC7!eH&hsC,(+uLX[:grf9/o!}IMU9_VPWmgn'\kf-A7eΞ9>Njy(^qytg\sJՐZ'md=o?r37,Ȼ5vO삡Tqky=Yk`;*2xJmίDW 'a(<װ oF/͸8@~/̙33f|ec[)]8fcؗ_'%EFп,y'~Lfuu1_.ڮVpw^L"g[`G/@<]@GJ(A$bdD=i=2dҐul >^3%ү΍ebbCYb'wZY9/NL ]ͅ<3q 7{0TJ3jԨ۶RrhH)8rʕJ)D /_nݺ[bج#GZ\;Soܸ446ƍ6mZEߝwyWYY1e9VrļaÆ=p̒%KeYc*++ SXyuJC>^M 𫪪@ 0p۫ ˮ-*.+S8TmO۵*"јvO%fM7y͕m;מ ]@hb ۺ'C‘ 3dw;y8u-mf͠S/`g[:YBiCٜC"0$T Yh$R)$q9yhvM>f^M\UQiV*,{WEo%CE1 `m*n\ۦ'USܴۛ=, 83d4r#Jm{h%t%*O s!Z`*:ϋL^M]Rkyc`;[8#oWDS^ bB`)$ H̀LK&sk.o[aHIYGGJl},ޭd5CN}tˑWq{<6FLH3!SaI2ڴ@3`6NU4f)fUEa95Hrkn'/^^7_"ho#Q/!ڌ3l\_t?|/nSpi2slxWxGl'] 7JtDw|{T23E}Ysѓ+f?mG%)` > u 籢JKJ\PW[[+\>1kYZagӆ%3;{g<]%\H[)'s9@^~8􄖠qO^H%чWO,#3}~2,ˊ8ZzѨb`eB[:O.y;aܸq^*2 ݫbF=\t鉳fzbGX?,Y_WOΙ3G=rڵ`0( g8㌟l7|<sy&~<6O_y_Ÿ~dE;t#4Ocf5`p˒O<' ڡW滘(ҲN#uF0O1OOch(cڽV.Og< ɦ^lOhq,SE0J8kEh4xss[h+<6V bn=2ie v~G*@HҲN Cp(n](G%d doMhٌPnᙪ V.ʄe {5o{u-'| X'skb~ނiZvVZ7;0|?0JbiĖpDo_.k_wuyH\Rzŏ:G"T9+j䅬 ]wg\O~zˎk@ps_?Ϟrڕ ",WikMC;[i$  4kĉw' iXf RJ믩"W_yygZd2Q@`N&YD̘1H!O-5 ,RԜP(ԘBK,???---S^^ΨQ ʕ+WMMM ض|WO:CwnVfsswLĊ\-! :[GKa 11+!t3M33 ?b%pŠv%MkN_<u3TW:aZwZdXf|#?ljj2U0@@6 >8i&@"h Yuls6[H}')a[y9^ !F`Ҫ<* 3vn$L Y&Zz jVV[Sd ]2!x|gDww@2S5#|$mJLh-a 98%MA5[нJNObM>wu\R.)"ŋ)3l ÔuVk7h^9GRhV 9^uNoַ:-Zmo30f.JK F D rmE׭yVǁ{so\L&CYYX,FOOSZ[[zg<Ϳ,3g]s@f ?~|˨Q-]ydP(СCivZ_~iӦ2htrMMͬqbŊK.mhnnvk5 ~}QSU$vM(RTd{nj@hcPÃ+!՘ʊei>\wEk$cɌ\ x޵Ms9"` * "nShffA9WMT~amt揕̟1s{8uٺwhjB) 'X`ƿϿ,w@j+!Eђ~qzL1f_quegm IەQ?3PN9ي &ſF&xƋ֢m2/*,ϟolomemy߹$wjsM3-^4m^kĜ EU~yZ[b馤\+cq 4:bVّJ⋂0#+n| wk{#wUaSmc6*ZUovaWJvV?^bH9*U (mSǺNHnze#)P4Ž96Vf{e+`#>?t2쩢C=K՗_{m4gVQ7)d٣vͺ+:+7nbާmoV1hЈI4h[\/߼>Z1nmӧ5O R\.=-MfȉuEQSznml{&̅SAE02).[\hknj*x CA$gȅӦEyu#A}ƾaJ]ǽvc[ӦM3-Z$ۅ"vR\Z.kCG۶92LKq]qtw A9gX_ϛfVѐoX`MQ1~-lK'o,40|%ۿog0f.X1 +.'pƐWt!v'[6uחw@k3gsϛ>aHoC!H$8((;K*ݜ8Ol7w|2w۬'p_ NCd)gS:{|sk-Ֆ(H?T<¨k:{\[ćwgJ!~hf1sf~]z?|6yVr"Le3}WkӶI ÄyLhAΏSQ쳥wn;K߭핥32/\VRٟ"`O&]_^) ;%@)%IH&]í䄺eصBҞFAk?L @+X=-* *XJi<ߣ7/z|Sߖ+ے]|KnּO?u3e䜉c4uS֭z/y݂?d7rL*7/񂵥®.kYO\ppt=>Z9v(^7ԥT6t~L{gUkZjթukS9G0 =G Wvv=f -Fs}x3q&@߅.Lk9p;?g~4 Vg#?MPZk~ýwt*ƱQd71ID6l.arga7tX2cKc]>n=f️.إ]jmi59-em[=*0=?={[656~:Hm.,i U!3o(TnIOzy=J=-5FbQ6MCF_TMuu[{^O?.t(dvL\CC_( )˫gvmW7l{?~n}Mhh$l! H?Vu#{ڏ]h7r>mfH:4꣡B!K 3Ak"5&M & rlwdxiLrћ6¦M\.6̜#6dwm}-8Wtн鵜0 p垢Nsc)mlȁ,)o,)'ȼiCaa!4/DЎ C W,ˡ"Z* ۑ) ~ȆD~ ?_?ڸNjM]suMcCpN1Қ yX@VV0դfr80 |,;VizO4B̞uy[~k?8Va0n3TKȬC#=c̀&ߥ6PSdNaerL0pq0bŷ&YdV׃NY]` _(|{ VCkN(K"W 3J?)Ck&&_@P~=ٱt,|oMM<\(y`i Naa+a,7}n ]ExND^iq}i`-u?xv)h2#^p'y_׍n~ȣXV,d^یͿ7`Z>Ϟ?!l,d S[;`?~4PTXCMX}M_CoW2jM1mX K ʟNDd^ .l 0f`XCG_IZw"pI2R8c f3| %AP 2 5ֆ2a$nm wE*nErhsΖ.O~x7_C8ŸU1+" klw2tݭSE* mpXMmy^ ?\X|6bh͘U;&~pݭ5WJID眵֧_?{/܃| [8nn +]SjMoO;>?}w]&I3֚ bw #8nJ\eJE^S6V_$w75G֒tO,g/2aLaOkijk:c~vn AN%x:&hM M @ƢKV5T$W' z Fj`DnK%xe$ 4SɬI0]BmiɀY~ iɀHXمUBp)lhO'3bT'@&gªM!4' 'wn^>y%5dM1Gqo=h:ݘ/`dGCxV$!_x0 4WA@7D% iN[>?Ns"D~̨Hs#_gMU`$P<6!U`e_OGG#-eEsDv $j206?~~+`L 4X–*ok=k;n7g;8ٚ9$ Nȕ%BL*M/c ؎TMW3oάbxPU;/9Xijf;'5Btr ,`XhHuEOv^r5w?.%z5p - HXqO5Ua2o6kh:q_{?*8p:.Tc SWeiqPg?汍ϛ3O[ ?sL,t8|?ƧuN\qE#2cp=MuSp֩g7X-ZAVf&[w}p1|n|*z]{S}oXP\)RZ}7W]G@Dh&0{j]qk nt[;;TW$B+\& eWc^c \caKƤ `V "t2f_,|n|* m V?R)ًt$twat2q)S|`F650"~_o,& ՝vD~ nT!&+l}chop;qHT~N@T454kX.Ot=xu'dHJӭu<Ź9UX&b[4$5#p> O!VP/ _7A 'nO4 D#χxiH*Q7Cv s轴эe8=b `rB,#pO QN@8~9}6iGlB@г)$̓cI((qcSGr ;9s2}=Aw =bUSZcA jD/ HOR eOIR"UorP;q t` yIJi WHC*B,|I(#"BFf#pTڕ+E{ ]4cʔa;nujTADh0;%?wn~0{#n&&iF&?q6 %璲 xs 04{v׿c0QU|n#f&&fcCe>b L㱧M|~ W bDbPtyw#3N#`>6:}am6>6T BX^l #C0"0x T rx.©Xq,i-Y af1VyR>i㼥o^D`޷9Y3I MpLȱmf:f-jnHͩxR@y%0pd֬W.pd%pT !*BscjU'L[?: !l‚8ickA|p L`uj1"hH?އ079dh]uvꎕ0 lS |"MT poo_٩W!1v<*X)8Q| !|ut 0  !+2LK,HuB u; QO )|׭몞-iWٓ*j"Ch#1pfC n3^!0?A%+IWpw>Ϻ6@w1,Zk]8ފ?|$΁&B~[{;}u>"jm@ `w! 0bx~S {vS:XAmd? "$l! MXmVHq? wL&5>]~rن>e CwP-dS)PŝzH㺯 u?gz Ó/h6*ր22\i2Ӈyh=1>=#2n3,Aε"6G~TCB1YmV0{~>:hX>p3%?mLJx%#D ~/L_ƺo8zr~2EM6>"$KdCV7kMTز9[RȻ0 =8Y xN OlӅWi)Vv<$DTLDԤ f %4d4/m*>f!Av/8$ʝO: &Z):y<(-‰$!ZS`/ j0aS`7QB6yM&V'8iΑJdb^LoNɭXAsu XHC9HKzp/bݓ9|Rz X0{>@i2pm4pW*)걯y1i0HО#%1;Elޗy {5@ѰSHA\0 8>Fkf5„ĹqsB54øzK`F$@L}HU60AAQ!!XH;Hx _}Oy,YVU^X  cRÁpPĎvO;D@?,p_~QƂIRe?JE!q0c2^\=EqcA}鄂O {"!BŕC& dl&Q4;k!Vx!: gbI޲p)qۮ9i޴#X^*rsC~w X.8l)?^x۳Xf Zni .ӻw<ߏ{:`[qWU5oajG/+&~e}giК[ċ(?ԍ/u#ߗF$mi9gZrpŅ \ +wczJ [LSǰj ^*?mY,85Cb )LoUPeq? hAyq ,MOS\//3 9l(>ݎJt`grB~&D/i`Oqwx=¡> MwnvwASہyn߱wr4`zcpOH%z=(ʿ&6Zr #x[O y٭ 3(2@l~HE**BBO!TbHD,ŵ%0aj`'bJ.\U`02HRBJ 8^,c  wn/oNel[OmK` ͻz0_F|V %Xv)v҄X:=g>,`2P%dZJX,Cqvzp0B2U62%f_p5[S, $_=TvR(0ee Jj0`fCp]/pW$'뛽x@2wG9 G+uJʏ i "XA1WAVwib?n+S~:`Q3;A?;) (.q (~;l4Њ +S'IK -"8~9M '/-oCј;&ᗿ_G5pnqyJ$pߝuukOl53VT,.X(\*AikNm|GPbU˗iЄJ'Dc=\zy {t)A9Sޒ@4Oޅ V+V) E ;믂읥@|}p.8| .NKw^aZO#eUp܊<#-Ǒr00u~#.oH߷(o8m}RMq<>N$Mۗ#̪+i~wkae-0+ òa;&rn,(~[?]|]P nY«Y¼&S ??XT+.b-k…gh"|KHCwa 9޺ENJy1|Fv%ɰ/O.r 5`X|>p7]– DyaH+}[_~V}?@vNNq`Xt%vjைEHx9 x[ D,wD8_ni طNѭoL?5΁hLC 0\|Y\tYjPc[sZbg7|;͛wr4&"48 hsPB_Ʈ>ŗ^T muu7D|_qܦ`6#M0 zݳg/B0?9h @`QF>G+YRq]@0` RC.,ZE8 וpl v4 ד̄8וJq;w94)'h"E(V~$l PN{둉IpI/,G 5Ý?>oAMBV:Hu7 @??mY8ek`&ç>t),!uPXΟbߡ>|6*~$HQ qip[Ӂ7Eq7wŖ޽ J(G_lx>bƠb"?FʒeL0 [_QpA3%t HY +)/ dH.r`(Ch\zr /3p=r##aE#;&?ZS]C"ޤP~q'݌-C)|Ga:ƴ =_`N<ƯXj癱|ySmMH1P.)$M L}?b럷ВU<\B,,J<_wऔc 7qF+7% $C%z_Bm8XGu!a2KDuuEh̙r) C~b XL={K$qL{r9sPyxjSD 9 ;1gg-|xi/aՇBZl!L'Dٍ>~!MH|K 1]?XОR+\i-9?D~ >ZNs-JOo+=C*5|i*WƓKgx $ 0w? D&- 4Ք_WFX4VR< O Za0>bc0N$__܂Mw`uH~.MeQSCmDmkt67ec![ͭIS{ۭ-:}&j'@Z0tÎc#'yӜ:Yƞ[jԦ44l߾օ/k{wdUO=|5JxᇅwYן^r׺+ݱBMm  ӻjGn*~ell>`^翵=9?sx 3r /4FP2Հ[)aمa^#?>TokSb"?/˶=f<<"XiǏ?v>:uƜ$,֌pQljK#m$1"ڻO_[? Xi0o\ւ{ fd3ALCW^ФB K!9#V. D )04׮a*Z k˝/ɞaj=9Z$ej[0JeALd8H~ȿAb:ÕNn /hID$ċ lh@!Tr/R\Zc!s'5hޡ#Ŝů\p;Guϴ'Wc M q+g 抏 n'PhX=~3nzn72f/2C" sk"X1h [= R|܃_x.GNKD6շJ)-8g(ʸ6K,9sPW_8r0m݊g}>sCК 8L+C#K!h3g <ΞSNZ6?C]LG1;/ Pgn8-jl#ʮ}Ȇoz7OpG\gK_欣; 3NP弹Eo߈6žnuCs2#a zi;Kᇛ" zW.V«x=6swϖ+9-oS򖴔L*ĐE/X))82&?M6&gsޒiJR_R+v]O%{JÀs ǖxHE+GpI8nZD&~t >f eI0᯻bi849޹ʏ1j"[uN@WȄ,܁|EO.—#kvw='vzv Ip` "cB8eg?_~%WyJ+䢿oxd8'YmM$>!(d N"њ0~0=O+Spq{7^p\t2C]Z_d&Eg:DJ{Yi ][H)o0y.ևZ9?_P5غvROKM-.?sFEqh Hf溷=M]v7]ܹD]LkD.#aڊ)lwE׋kOi'΂W1 B{wh겻7M'$X?Sq]ٖm;⩍;3}98iflD1h۲pnzrݯDĬ)f{ HCjDKCmzkM~}iX؎xf C^<\A2z 3hZF48/woSZ fZ*m۟I"Jif CzO}X:4~G,6 /?siGVjZ( 4X´<`8] !$ە;pQ;qVZsp,#E|Fa1>b(nHN֟w=j71&W_߽i)ʖave]-f4{G0kim)#?^5?mNR_U$xcON|iU{XQ)w& 3 paJ1UN(UY>%ђm np&s#8T+/tf,-5߻oC7lT֯_M~VR3?Mip"Wq؈(oDM~sW?li^rSfn ,_MIcG`N/ڌX@*rG+ W쬦*RH)/%jcp#x 2Ąx€{8Wiz O/Ue3ERkF:i0v8d:Z狩Sftš‘nh 'xff5TȉPNv-=!8JK,շl_NwKf`&\؞ջt]qgk"~VwʾG~!3ku\+Gڊ<pisgm B.leڳn5cug|莫0k<撒Vu퇰e!0sg7aF Uk3ھcuwVwt4:;7;> 3?irjĞC``ҘFkC =0wۿ5Js }>xS.U;7aϠ-e5i~1u|ӝU+W46l ߸hg\JQ~a0L͙/?箒uHuUA5b$.7Z<|MgB{\ܑ®BI-wPKjqvIW%S%1^ /D v^l9<|l3j8kN+]I9HZyyÙg9+ή.uV¾J1I<O P`@$B11[З?x} P?~w`<~G;,g_ISC%Ѝ6@z٧؎Nڧ膮.v3{mǒ?N_pHm1>__gԸ[1ILXW?&~8g@kRlVݏǘLئ3FJ1I(q΄:z,5ɩ- I0n# 5sEπN4ʂ1/k>\~ˋ>S&TJ5:c1uVO=6lxdkSt (|1^_q9D7F%dskx8w<|S:TkքN]c3bh_>}]uNul3SӏLzjBR@2qax朱Į{~y\n^]t`#g=\jE$7 1awT*3CE::5N-J)'ÓD``M!z |oh޼lgGj2g2hMCR*g1h-{^Pgu?wqV2kƎX\x=V7LܖYƫu .tovY"ؔIDŽ-ˊLa N K~DB*@j\m|ä='l~JcQ 4J"B+K \ ۳7b=vuxC(bޠEd1 .F/5܌߿~{{_?0#co- P.y>3#ĄP):Kqשܓj.AJf,*!$F(D(Qlp]߻ l T@?YjWm_yJbc:Jap8uR7Mh*P0GYvKk}SH%?憁ԉB{Q;}vl0|p;._ ڼ$D=hRRϿ7WZWrG,iY0 S6"g4fTO]KҢ/#@` 05 jPxj];ĥ]0'cRnE\XA^FBNj O)hjRz>HК"kOxd}PU 0'ss6@T6;?0.r8ږMTm. 8Y36GkQLQ$81O>:!{7[+%.T^XXѨ@؉  -6{o~LN0X+Lď&ڬs$N}7j[.^aXAW_|~m-Ug|+΍EY?y|]W/ CƢ@* uiW y== VXo. ֵ[{1It5wo*bze$hjD~*@_l_YoR U7u\>~5˄D@pӞ{3oGTmÈGoYcۑ˄a/%`U^)wo cyW X'O HSRb>ܺ1ǽ>{ ]fR^H8G.T{?>>a?wѲ5B2R"ϐni)Ϧ׍?=gϝr˄!rm)VR?]*>Ү ?Ե5.fXLITV7axa't%`L?4,AM"֠i>f@`#s?} ?4AR"tB%BP0S?{wZi !>v=Jߔ?Q}5#rI}=_q &e2Ɵ?Z `D)Ba14|w06N~WY)9Pzwp^_TŶ"4…wtpt2}L ]<sW*31]A lůf.74⟷0U1]NBύ<-|usѸ&RŠF*Q;:aWalO>wWR36yMb:F},OcR928wk S'f2&`fRoϴCtun'#hESd"nLrXy55%uZxs3z~k]D`]ۧ%Zk34EÇr{v1' *}H$RH3 _`fa&s݊wRvPʏ=4%+޿0I:Q)LPqzP"0X+վk-lM2tg,FS&yuw\aTg-xD"p4 SPRCPgw_uhN ]`@Ju=y?=} ͙Hp9ϱٖi&,_BT\oGR~$m@PP9J]γlkeZ p=oĭTv凊##?嶿.uwasSƾ*ϳm_~Os]rG>?RA7Ͽt(\\ γMke s#eQ*U*POa窐gZl2%q]wG\~XuWTK6*b;ٶ9>J'G*wG7:Tuwo\ ٖ9˲̄mwyӟ+~SNK2* X,2*E Yye2F*'46f h(&4MS{P]'djrjMɓ< o;A$7TBߐ]}#_{Sk 42!>d4 1 RI 1+PGwU2 MM_o͞lYQhIs >e"55 d˴=ϏĔRCP@TIHk_OT,z{6L97_Z\Ep<82rw\04&m =dT:rl\QϿ bhh<24|#G>`Ln].-}O}:t{S]4e&/b@5˗{˷]_> IT Ȍ{d"6~5#"(P\ʃvxU~77Խ'ޞHS@ŕ( 7r|!ݯ_ԙW'c/&IǶ9|&Foq]}C#偿AZD"_HSI۶!^K#ïC]]TKx+>?gfSH d2OkSաP D<9(՟\\x{nē_okȞd&ظ0 VZX*oxtp ezm-D덍'َ8*HGE >F.}t\{B='%pF$F/# "b= xMvlܿj1^gf}8Fq&!8ZZy冇92<t=޼e7fucmIBq_1{s>sݓ8єi3[oGיQ  Y!8gqO?6˝qߑݓDn L>r @!X,e&y{ w ~͍7Z}am90"TZi<|n[sȑG)ӛofF 0Cp(w =4FT;} 񯭽&R<*~prNA3/ȑ;9rd:ǖ^?%X؂&.gL7𫬉4H+"h"5g:d8A0Sc+q.$4iC MFOPi`d?>I- E# pB9L~C"RJ  vRunKŌHlRGZ)h%E8_.Q|4UG>Ke27B!1Fq.F@>ZR^Z~`dd r7eldrAĸ0. JyJB) <@KsXn?\ڵ]*3[?WI86q9?4#摾&\}೛k>Mo 9#ι/FdV%"Oie m(Q?o2M !HAB0 ÀaGfIibմG|Ju5 DLjM\p;Lt0LE'wQ@P55d2Ԛj(٩ZqendP_O|#ǝVސNXR*p .}c!A"kY,kC?tWS}J}TrC:Wl,Ph"g#yxp'忹h,!H\c7gDDR)9SMT?֤wLEP1vM:z4|}Ck\S7,[ӒMEM)5.X>1&4uTgs&G vM8?BιlTJ)Wf~NNlFDZ'qێgl&-` #{*tK}35C08gba,h F;;;n8ዳ9#Ĺ 0s!ؒL=)6층_yzڵ~UTjy$ɶmJiFD|WZkd29KDwwuupiWzTO轀a&TגeKrvAhk\En2MSJҁ*ڿߨ"iSL21 wu}lSX8teRiReMDG4I/͊% Tokl\nM~T&_ |ƞG95ymG㣫 G"c0|ԑƾ~@PȦhȾcv& djy8=AJLoG793)= )ޑdb?o^u<6nO8~8P ݑ`R ˼ݲl*XQݩT5r=ZIe.h #H{>yUCwcׯ?{xUi_ץE穉U`Oԟ)?]U~lh$xIGaطvU;']G*Z siDg'+RȍezV.[%D, :1SXF۶FMa#8'Z`:|9~&06 gH57`0ʏcs"I/e 9Tg{++Ƕs-"u3岋r=#I祪:7b>/v*OUw?OR@ aږ?ǚRǘ\54wL*l630|LeQ0O#Q`!\e7#%\)HUAKI=~YU0%c3 ^( W\T$T(V*0g@6yZ_OApި5mnΏd\<LMBkPq qTgq`- J)ؖ|`$_pug@k*i`^`pۻ||F=0pLrfN;h=< -7!'U Ǜ(pFq]0p 3a,r.(W<.< ФIF_ 36$!cep4%-T\+G{2Zu)g ů943ถ:,ҀtFœ~F|F-J)sQAl4` < WpћJh?aٲ 0rz߸ȷC'?8\m}|~9=[? q~Uu ]h[BV 1 fmR)K.ۈ6af,ӀbɅҾs~5~A:ghYX(NhO4'(b3eU%LSkM`j&R;`gW#h+Fppު@`KTBTM/g$C8-:!(x+˘;+N٭w^+/^ >񾋑M'Po #@ј9"0$ c J9)$-Z[NŬ! *nCt aCJ`#M05~5qԮ;Db#"܏kx#>sÕ)B*]\)*J+_ҊqTkP3tj7}Q(v1ZNJФ515*{R`M_:ky+b,lKI*z8n^V0 @ Wɣ 'Ʊ57-`n]J*XS(y~QD.I1Ov)dV]3),kCS"BPv] 勘MaQs-*/}־: 82\V$Zt~x. (*A44>NXXA200̰|JJ!`̝\7~ {gQ}grzwջd[䂑lB7F!$Z(IxRY$@J&`[md˲z[m;gO̼V &yyOg-975s5sӣQx6;:om"h׿h5]m!Wf4kz󷔀I.,7[?MOOG4?$:s0d5\?3׾ NV"?Q&5Fk@F7|M18p>KLqŋh;K8Ɔbff_#J$]BH353+>|B>|i8):۳X%l M𾿼RF6 q΅8}T6iu úX0r\'!,C%TˊSLXwp_=ޘJ%b]BSk KȦbOUՖR)jɸ wsmnk7 ?$x^8U~MKT"Sx2 YޜKwƥ++M̒hP%^T90,,J9G̖+5R r qAkMo.͹oQ08gԉ`1xR٫BcfJ #5g0{ RE5[`łic+Ry- QƓ4%VNv0/<R 3V0:1M̱ɷB]!\xBAӜQϐdEBcH$:*e8(]=D39~B0 P4jKpbl*g@w{JC鸃iP{ܴ`ҙvyՀZH=P`-NwơPؖ Zc8TY`<teR&PrA&aA/Rd Ķ,b1R)-kzg]]u57 x1:$m̳g5 hf륬۰\F~e,^?}8xNjؖ$L`Nou@LLs "{wXcJ4%׎4gSt?7s_k̕MLؖƔej섆RmLVk^x˲s8e ſy'ΏW;{%|L׶ Rr$7_gfY5 VKc v}c50AP#hgooaY.J І24p3N66W05[ Z.ۗIp266_oF)ͫ?>>s/w(LBY L&v4]O1O+ 6t/23ȡ#w2]| дaŲ+9v.&g0Iv&ksxE8{ ^X0Fpmeq#1ưlQ/Wh-w?r#E@';;i&"xgF^-= `,錳q8#V[ٹ1/UgpOU0dg3=D L}vP#a3c I{*I#/ai_'.a15,JV'"nAh&eww.vI*yg%*$[]<+6LOt09x$N@Ap4J)T'}}iPqŅx]y,y\K/X[y1L:x.[ءBQr;n5Nr5me ]c'E%F)- DNemȭO ؁RJ->2:6҆Cv!Dt♔?#Ǧ,ɂN^|rEvPJ룶%gb6JΧg9< ,s i7:I &=,)XSqmIU?:0FJc:Ropsb m 9k1ێfBpϞF HW;g-$wcK0Ď(c(Ƭ;w]`.8K9c|FXƫ^ξ}7/ad(w,neff/RJ7Mw0B#n܂(ςYc6-tc%ᇷWDRq䡉9|jSBku/# sP ۊ2BY! iBM?31.Yt0_.Z>C]J ГKl#}R*Ek^IcpΓO9k۟؇6^V0>INꞺzE: :5&$nBa(쭳pJݗL)ml[Qwq&g^K'5XՋH]AHR„|?d^X>Hc\-2mQ.Wشiܵ2 ܩ rLzd2z oFt'  Mq, \jwli~E̵+: i ̜~JO71,+6w<cw:zЛW |`.:{!ri)LOa>D*t,,[X8gW1q7F=O?KOяm;w75_-L}~[ñ ypcIjq d.8+xm$=~$M]ϒnǟ:B*&F6E?,cؖ!P}7z]mɹ,zے87 P=ؖa6Mj9w4sY81QFAGSbKzz !~~4*ÐKim`$H>g"۝@Wn!+ xpJۀl 8o(3.m7@G.Czzs<:CӞ}萬d3%/s%K*ڠE$xH=GbgE+P̔{}(N!|Vz Mż{"wvʞWhm=Tq]OaG.!%zQXR0S*ޣd7O;5HjejѨ:IDa zjJQdQ+5%MtBF5TLL3Q=MHӱlb|%oDW|XI%NڑO?uU (W~*U|u Ug:ҡFD?Mbm_N%H>pJc4~4<8A<[VF)_wMXKM̔Fw),&J6d$ʚxKt_Z pf4[VpOʗB015DD1Y!#gY 4%ƦfLgf}K͚kqgz] kej*J92)O*h4:&gfe>dgm\ޯ0ٟGTkz@!"CBq~OM~6k @6a(ij& OQHs \F@ST@_[7|Y3I:Yzjcnnݡ+V P gɂ^~JȤԫ S!HuV𻯻? 4X:ob#:wuVkeT#P$cdzç<5 BmϒO'yզՄJי+6;MLG[4xv_WcB@+rIҕxRILYBi/4 0m OPwIW0Prgؼz11&s6|Gkv]d1^b!ִgRJH.lm'rۅ+KBU1\R!Yj( - P(T̂u끧=zXw&.ھ=v /äR3e.ڸgTaQO¬Zi=[v;CnYTSoxZt:0}~v}~\l߹3-11W#~rԼk}ֱ[bΝao[қY;+~j&H[bb'^okbmBEoP!Uhf~h:n;gwN,ucʚ#Q^a~.~/YPᢱ u^$wD{tx,>-JfqC]f+L8 @ǂvOpS%^Ǹ.GMtyGt%zmGu߹۶hQ֘ʷf{ho0T tR׉ ״ ־!h\6qUߑ㵗ÖB6A3=^ЕI5JߑRi$YOL9;$wlvJݻmAw܎\\U=EOkXB[4|E [dUz2UOџOXNlwD^{Ap[&?J5L]%$DjcQMĹhtdR4&XDsRlGmۆýnڹ _DW(F׳PABK[4 ԻVw>jg6Mm&Yѻl۶M΂>2{ ;;&2J[K aHy|LwZ,Y|CI՟_i}l۶Mnݾ]ުǾ|"R_mCZ h&&Xc3)F zi96y@ACo^sI7|:RWkV,4S䣅z B̥ &hKe[jaQ<6)'f~P ov=̻^f(9_Zjmu,R:s=Ѷ1%:vb\|4?#bJg %b92`it1J m1E.xa 5;6# hOtǾ||opUa:_~&SGF tt?I931e,3]}'G)vlAkzwa"߀eh`/DԺ~'C6~nxc[|;꾯k:F֠5IƢ5 86xDU~Tq+|⪭[oQ !-roo˯+w\ӿxsflKRN!Fks 1}dDW&uՎ'lٱC `˖-ȫ7]-^ VsI2IG>|̔t֭O g]2ҵĜe%b6ԁ(/EK#%.j;M khVZu@[%Ãurhљ2"M{<>]AѱK#ilO?,Zmu߄Z+۲$?k7mߎ1p$Ҽ?㖲~\G!Nw5oٷ:R } ۖte0T5FZ"wG7-Uh GRЙWwh B0fYT#?:yoYo3BZG lKҕKc2 d>y۲jJ&(m8sE?Jilۢ<[5?{p/N3S=]KWοdyN݊/E-( g Q:z"Gg)U+:<^:R'`>枿+/3٬h~(t2c3ƶ,ʳ=W-| p6싶,%RЄ{/Dɢ٦~2HaxE,[Zo\Gšof_tM7^BsWoCiY+COƒbB/@Nh}]m}-Sm/ھ3_ O0 l۶]mI\t*PaNبN{ݸ;ka;vtw<]ODDPgB.޸Nv߷nٵ__@182xWO_GcYS{Gݔu$y+X04a"nǎuMtշ|6-Q::j,KXGycs{R 30ؓGi>>:uZl>laqɎDL*+l!3J3z mBe˜c3 uOrz֖-p;;RJJi-x5nr(C[Z6Oԛ}NƨmdQ/w.b#W/Ǻ@2]ڞ8 vagSڞ}O7teF/e*ԎNͿpL7-]mr"̛.yB\rQMk?iZ?ak㕛v$FJ5;_~SZ/>|]/켥[ g?Kk& 'w'J`+{_7.#rF|{ɿׇL>c'􉉉Ƨ~ ?1*8qb4)ő}x/ p¾unl5/0=inŐ2Bi}J-1bYJ<yhb-OLewYؕ{Qw{-}SƬ(H; cKCoPhAڕgjɱ|rZ%)=6Ylx}}]/J%ҷS)1m"z:8Fudj:O?kzha JwbRm,)DZՕz:_F,5wۖ^V r:~S)Wn˲"F[L(T{o6W08e̍[O?+_VrsϣɁcS y7qaT;8S{^Nj>xe 7nǟ.]蕕 ,K8O_e*Ԗt,p,[>1{z##WJPiR/8Z?!jaS V=a-/?S-%;nܲ.^ޕ 3L|׻_ce@=y;p%>%,[ZBJHāw B .-#hזC9U |[D>8WFD]:3;ӵ>PZkBے] (TMEI8Iג5?f aKC'|x߱#C&J)m0BpƵ:0RjG JNW뢥ײt`Z*@`Yի<|t#dE3:/EEZ()NL1Y1X؊q*G x$6 0vtgsE2XwdR; mt#P2:U'_Pۚܧ:~?DZ,* c=c,2AT*n;ǏwX)xMZFt_.ۇg*̎ %8P=121_e<[W5o_y]gg{,) –[&ML?ݿx/ogh+)CۥQfbjfd?ڏU_q噸s]:**\AD$tAԂ7l/UƳu^sɪ˳u\!HQV-bfo\~OwW9rcqy KY}2Zk+Gj>_ML7 w߸ki_9wQY܃Bʲ-A:uw>|`:u_!|~l&ěoxՇ2l0Qq]2ZgʥJ|A)e9TZutu>{C_{۴d "Aq솳7,1995c[ZgffJq0re޲{9k5ҎZ G tq OxxLi5c c ieLxq^цR閫6l/r\1y[BBG>wR2Y,DF!}PZR\>-ah:FC R~-P7nrbr4cYLWfN[:m`my!׸euGfϽu] ~L'',*JπP}h6؎>)=z--#5fzҿٶMoga[oߍ޾B vd`k*,:z߶mܾ}ֶW-鹱k}h$AT(mc lpĉ{Fo{o;x*#Ů:@F=5j7}~Kxkg/y_;DGVSAqӣ?ֿo4r}]WYزl@SJ=h4n86u1έehe ;WbK_kOSK87 ];cUҖ-i;`PJ{JÉ?]z>ƹuGp/*mb1@y S?fKh0Y?:=qwO{׷3}]Xu_ym:.*8۱D Pby0_z=CwUO˵Sz ŃX?1;{wGT"<{{?t&Vag۶CbT@^]5ND 鉻;;JĖ=[M~gֵgK񯍩a?UÝNbֽSWu:`0x$bv,{V[5?xXU _J$jٶeE(]Qa@^­_ݝJΧe:PnU";O8OzZtϻu;܄xX8"3~|u|~7ۤ\^w;XHwMC}ձG~zo9ϼkqlÍ(,{mY1JyFF/<F\;wՙ%{_'[ߤkAcK.>c6Z_}'[L? kآMiC/>?9ou`*,T ч?iClhecѝ?Iё?CN?zM{> /gs C'ؿÁaDV~8J>w? }[.B>}x&wş6ЖHg;vZϼù:GQN揿f] 7{kw?~ij[E"|_}3_Y>un\>zX?*;\HI`Q.@[? >4pرcQŃc/AxG=51kCgҢ@+ۙ_=mقOg+Bd>)0mzD*ǿ_^P`h,P.g*Tcs ͜97؞Xt, PAiƫV~{{vvT*w:|h&.IwBeL)~:tXh PƔ|cW*1ֶViqg<\(-*5L4X(јOT?ǿ. Jf7k 6) *]G=8ܐ6RS׏6#=gK;2m![Xm02ЪWяˮ9(BO:2ɡtڌ1҄<[/n?MG<j R SuVzׯϝ{Ki}tȑ7tI YxkOg%\ql `ktk2|!L2xs?CTkxWbqw:ma?&_^by㷪 |g*rs cwchx5}?/žܫNM!渝`kޗ({:_87q0{}a-:o:q:\۲@)0,y^n^9mi8>uu"cmR!ASo4nLO_W׏<-Gipe&-1Zg;vGܵ-x"’=O4>ݸȱDbKuَXV*ynԪ->?~ ^׎m۱"R{<ϿRk\W,7hmehpggt_"jroᆯݻ{^9 ߊL,sNggO۳-RJhJkatTZo01Sztjz<:v߯q0dO,a{6b1,i!0FBiR!z죳}~=:6bq,²,""*lRשT*V_`/\K9++ c#DaDE&Be&K߯5_WiB$b_es8e~)13;r~o9Џe}._L-lV_R!R{3?⃥_[YX(ܔllF2j:'.R,W5 ?T+ttu,$4AS.)W߷_ {/Ȧ2_gV&ZDE=?`T*fk#_5kz ҹsD"e[GFELX}񉉯+2 ߹6狽ɘ HiWh JoʯZgagL&Ŷlfe2g~:S-g=}_c"{;/Hē_L'S+M[ZROV)69~WOS[o{1CCC;7aY1Ơab}=z?}߯q2ߌrs!.p6xcۅT"A2*ҒRH!1t$1FS39p'\HxY3;* iYMˮF)e1m2ʞO*/?m H?;m.qⱄBH۶&A(RJ7+J֨t@lqNUvu\N&cD YV ;Sڹt޽Ȑ< /vJ֮ STBu1cB ]-W;tҽ{߀v6VWG.\v` rF4B郳wJobko7 G7c7:oho1JN i9FBpa"@Hbgiߠ3=3}O>'ٹ .ieo(BbB|EL3vZc8_=p}mmd B\Hgğ)7W96>NVs%mM=mn<Ԅ ’s^0~:hKhDnBUmЉb~o{Y}`;-[NŞ߁rmƓ ?BGkcFsk pɄ~W.tmq}v9,O^h rV1Js^ c /H]9l߾]*w>Б^ Tf,ZOBkmA$qzr~W?Ig.mɿ"\J)+ q\?\իſ쾾\:M0 PK#zH퇡NcI}%2n T.#ƕR isznݡ95ܙI$b&AI]3"~ⱸN w&{v۶˲R3SAS?a:mk۶O-?}4IP[NEկn X0F"LO>NgaBceͳs9c Ðd*Eu?kzbG{ &~h#̈́FQZ)/Z(TH&n>+W?lռ<1h6< @Νԑ ¨Z"tK>j9N>PkmϷ=JR*Ga7Z۷o۶" inbطZN U~%~VW_ F_I|ɖ蛸/(j|WsNh ZT:y z4&<1y_"3#[kP'y( Ơd!i̍f+1z FU`2RJY򁁞S7mwt* F aD$: 6hYR @gɴįټ"|2J-RF韕)RQDNSi p\UZ) QySTV>J+U#9gLʐV8r.,|L+$+I\N$Lkf7s41DY F`N'iI\9s>WqǺ2ZkmtkVr N:^sJ17;3;vݭF`1nspƠQP$ mDsٿh.Xlc3i>)WjHA-'m,c'o6;G~p&nA`YɁ!Z5  >M =߾}n΂??M{anj'?sd"~ou?:;c :s/Xؓ]}ڪ630n*Vi#=Kk.%t:|>o|oOMi4 0р@ΙsBIKs=ApG6͉Qp ~De  "&I) ZM3OAy;P+;;ӎ\hDVnXQjݏHPq׵0'g!&soߴIIڱ r5U/քJt%"mI\Ʀn\yaVVKԒѨ*C\!/0J3Pؖ%76Ei]ضQ0[Y@f7^}f(U`4cGZly8v.q(.UezBZZkPox ӳӳL*(pضs|L`(kqkk"j~ #TͯЋ~*APC+kZ\28F)C }^@?T ¨j#ڈ^ƱOOhcRCkba(j~H αmXDa4f C0[pkȊKM$@ʎ8Ō6VsW ś=J4<˝2:V w;D̘yM' TkuJ~OD̥rnV\q8dⶌcͪ# zAPtv`ْ AcNt.)H8\rri!FݼH)yg柎M?^b~NF0FRy.0JE'qbvisGضǩK^3ԞE% [j˲֭o{:]AZC7H]& CA?~q .R, 6M&ϓd40=|}ln}+P~4sT = AQ"nkW7 kDV"lT fTTJF0 1لF i&+3TJ| fY0@񢍋)d<(MSlґNF'f/VplZض ;wT .' .]N! T-kw'8>c%lRHcD˲19Pk!w985xJ-T8EEXG;7;S3$*-K0 򕗄Sc',ff% #Cfۆdܐj{ժt$ ,K9v?2F/"I(S3e*:A8M:=aP/ ;ng^tj6 Ȯ8v7C6P: !mljra'ѡYm*C/.%:LAǶH  ?`׾18=?;Z&r@#H-H8M#P<~&>_"VhmZ.6fPf,R1?T!v乶eiծ7PRe C^?~s>F݃DB-#3xmkY֜)nnZ# kW,׼.Xͼ󃟧^H&J iY؎G@D3ږ1jq}4:027ЖAHE /=!t0F Kۜ ;9U4 Ȱa ۰o?{0T82ε,i?C ӓq ;XRpŪN~ ¨ ,),+߉zƂsj+H;m+g`~s(:4JwΓv۶Ƙ(4<or';}!cV4CcaG* K˲qתQ9ýs-2Qwh8?'Сb zH'IX݆pHkC^l`a~ C`U*aadh(' ~v14rh=URYt@ \/&Ձ ķ#%ZeH~,-`IɦnY`qꍀCǧ|"~|nuےmK-,mMHCMW&P!%8c R &emT[FgGH+NOSjv(BE>+B N^CS%Kxb k~zL-\X?e)ey76A UmGl(xdC݋bۢcY{{ꩩ2cf'FEDlոmmYHǎSkx߻۶;SSM|c"cP;r~7kĂTTdnxn}XKxbj1,+Q;r~ *[XCV/mXN sVm])Rf|ul@bYsCJZVG#PȊ-k [ӈj37HB"@/Tѣeeue)O/X&Dp2atlBB͛w;r(>,P Dܰ|^ +n5ҰfmGk/d?Bܱô:e_`10[&vB^ !Ө ߼?9>V$Id=;v-ƈaalnV޾4JaB|~_O/c[.%]v͛1C18EO{U{X:܉Xx~CF )o-*" !HbD4ybYRĿ?wR˜@>7

hE64&;)&?B0WhER1XtAF9kH_ӜL$zf}+rbIF=AHeYt:$0НM$fsj ugSs$Xf1hF Z;M|CU.`'0U alkOBF%/8?W1\bJ)!KW?k7}y;zGH Bo1hjA["cWvZ  8 #`דϏuH4$jZ|~hr+휷n.]k_|&Cx =y^Bx?[ (,.u}WogMTDЄ#`[77$;$?s\{شb!Y‚Msm|̥lR¦8 S*ƕRBJrf(jfMBgE.H%cֆQ"w~.q3Bq9y kҸB $dUm iKhFg|hټES-~4é3=9ABPǐOR-j3,EҐ,4J&h<}гNl~c|U\!lov}?xWi؋IwQi6[<f;GҵU-Cc2&wBcַ 5@U}i) N"`UoU_ӑvynnx8?~bBd=&˭}С@mRk~G 2T܅uמ Br.]`iia/?>)L %C>H 7βzy6>i+!Խˑo]ZßA #Pok\t,RȁXޞO$ 6WCXmL1Qu5*}+|}{6 )-mhx{'/fƊsg".]r9JLZ=lyޞufEJTڇ1Ύ5,_2yh] 0p WV;4ΣӳLLY/Z&j}0GưlQ/ۼQl _ &*5FK!k =pʁ$8}Ns |Mrlb޶zo xqNL1,₥Axݶm}ƇoͶ55?Wq] Vt=N!11bg9jrI0%B#JxoͶ5u)w?{di)d(-蔆<:/{K߾6Kk<#uʓP<2($!Fѡxd:˾Z.QxF so߾6)5F:U2ʮDH4@Z0@Oоj2_bƇkל-W#\vn!%FEXr!;wjYbRͦ9̱i:?1RH^0ڰ<IgB @OmrghFLQ%kH*z$I*z(0АaAGBK@o.  (mnOaPM\kYo965Cܱ96NJ3$TL [Jr g1O?> 4DiGJh' 'B{* Q|`Oʼn'BvI%4=JCl͍-WC]dSqn TCQXU@ll*¡.ʕF9 cj TPJ& H0;{ L fg΍Ңِكa L1;{) JV,@ z*2 h7OZNp4qlB&ұ ƫҥBű$I~Be^*áG$赎%)$]|KxA0.e.QĆ3Jr2ll%.:#X ? L#ug>.ܰ hrxZڳ0D6_>m9^}F\K`ْ)ecg]ruH2F6;J-!ZA"\*$Kͮ#[eEwN&ۣe!"k-~4PӞ@0PDkp%WX{hSJ#I~0PS. 0E.K$crn{V+4JV%Yӟwi7 j,aJk]4pW;z;Iܹd8Iai5dh \i&ˍONԪXct!̰GR %amD̥#9@aFJAOرoEg˟fuHI'hAA%aaD2Ag6 H)O_n|jlXM:X 3 3ZwI$bYn,*JHlstc٘υ_n4>59]:ƷҕC!sH4]Ν@h9; "<)NO?U-W_81]KقD2\|2rA+~ X 1EL—O EG>웨oQ z;QfXsZL_Gj!F];4EP[\]%Rsֵ7Il^7#PƄ*\ [Ȉl<ƊJ:r>͐%LW5^4H{:I؜Bi dRG|4ّ|&NqA^y im0Rx;9~NAJt$=ȗ&}q.to̭ގۑbR{xx^t qlknۇc[< r):Yz;1ߙo]\q.9 *%_oRTfu] 㾶sQۺg~C2n 7IV,cL4X|(b C,f٫ߐ ^<݄#;LWm"c~(LM1] 9k Iܑ$v+'yƵ,&\ג}~6Z=lAVgP/%I.Kg#D ,?,!Pbp}?ߒc*Mܝox|!I_=—c>nk:lq-.oo5 1R-̳A C pwk7<rs[.lK+?}Xl(Zݘl?Be!F'_#%󵤤#˭ǏݕG hnjNÏ@( 1ПwyXU˹ FG9Uxh f8:c)Bct~s++уx z Y \ʹ9kn@ufk'ks7q˭w=? FbBn7mL_0)/Λ?!At&1E~Gw~r>D,4۷o7 GG~' ({phvm F) Fwqߏ-?7݄#lyT`YGw6j\//V|dA0Q06UCu(%00,QbT`A[-ai i&!= @|d%dŝ)62 +oN5b;5Q|5*UHH ?X15[B 1Rи&#w7OvubjFH=Gbgזdϑ{ƙ H%w7Ovz$;nzOn7]ܙ53z(>t)Z?nZ)ajĮ飌O΀#E>;yhF:j~|pfڒJ$Sj(Ϳk B 3-#Uam_ZK!DSLTN T=D%`FaC!%^ۗD̖::&>'fHFfR8-90rhe(AӏPL%]LMGjxe.ljͿ!%LLQR0[b1>ti4}` fŎU[ZQ|0jE33T*фJuErNw"Zf5`A1UQ1[m4llRJ*NDC?E(fj!~>c0Cfj!Z@-ͨ hN@3SS5Խɂ:eWZRNE׺9ɏqǵ^C#yvF`M4˜K̅ H_~A=!x}|?_vMpmʏo?ɚ _6m.[T7n6z/_)۝-=%g*x'yj1_Q4Rǚk7EE./4%LT1=FqjNts=[kpܻgEj'f>l۴Cv]r9}>v0-)NT4O74Q`( N L{1SG=ߏcnrݛ%I&\SB i\#RFIS~ȧr1emh9cS,:0;@Ͷbco!A3y PBVrq  |e9&n j6ㅊB*ՋB;l4dͫcL"+ 03Re5C {k_ҤÂ_xhs%͘l݇gFwyjױ.̺cd5'/%NtktA/_;0ưfzĖ0v+a7?D՟- X/!Ҋ{%`@ޠ-fT\25=]>|DQ*}2K?Cw[jg`zR ezy0#Mґr~C Yҙ6YLi<9%ZJ92%Ǣf/0T10Y0,ai5}iðt?0mCCPc0)=ďN`d;UK ~FUK߾ DZY0J݈(L 3AH{[7_})RB~@_OoyeXEG[Q:h'3ɏi0L-נI}B׼h-҅⇡i2,~4TIdWlVБC35߽dU)!!; ?BJspaHcl^m t0TVPQH'xdqP(<]F<0zӇIӆs$THO ٟPy?E~ʕ>OHEΝDn fޜTb͋h˥ͣ.!i/bq6[@޻xIng>Zc6 Q irYjò>-f {m&6nۆ{/ڙvMhc\ @Ѷt2Z: 51[i+Fsi`Z)\f =g\ۍct7mL*͔v&,FGwBspm*Xg-k= L~.gřKK!vܻmRlEm&wN޻Y˖-ڤTy,_FE͹g/R-Z{ڷs̽۶mbkmrb ΑM(E%{o'WU9ګ-;;%a\@qvqtdeA<(Ό2vE0B,tޗꪮ{՝y~yk3ִg a;OV^~.k{@3=% b5[*xPր]l&ޤ6&*݃#~` Xˋ-.8㐤c3 6;x6?Z`p(<51hN_ ϸ€=fup1Bm͞ṻu"W+ǥy`Aj \ UފCZҚlrD7D`6@ яl2ۮ&(]z"06{nV8Ҧ@ Tj*Q lz5Xq6= Rb.i_CpJ`,(b^lԽO6TLe,$SO'&R ڸ DJ-̅1n%O)5aYY8ٻ;SJ`[hS<@,1]BUr\_[Qϵ{lg >߷]2z{wv\1>1_VeW{)`dL48ʮw)!c w{s܄DryF%(Ǖ B `yez]OZ^/ɮ`C/|#X[^J!n0|rɡ\)0ͧcoBb}Uэ([(xX0BA:n0syj(XH׵W 39犩 .qAT* `Y ,^O)JEʄSck&l ,1R}a |*l(5u׶O[mtc8%cBl~l`bk^l;W?mFba d첆/ުBmCe W@=04\ łz 5- 1"d)+T Pc Ѫ<=V[-@D0L N!|>՚r@/MH[FC8ET2|V Bd |[i *8DXF80g"ZLHQ QQ.Q\a;>˄=s>>Aiz3e<~IlETB(S97PՏR{B z@k^hxzpyhEFaYL)k`R0|(&[ ie~p! >@cƷ{]oq@#R~?wd EY ժtS;˛?ryoE>)ϥB+DK8:isMb$Wn[,[{{p_*2M.7} (2a!6f{z{Oluf08cĹ^ \!ePm U9g I4s<_(wxO} kwnْGߔA"׼Zo?Y͋~4sEHn},֮1-shÚ#[RsNiTv'"sCeם|Uq.+ܛ{.\Ck2cK Y&vS._XIk9^? P[JA\KMT*f-3 `m]!;vݤ"$F d7uX7@6m0c&UHgV510|&ݿ҄3`xၭv UH1]/ien_k\}suܔϦCUDZ0 HZ[{8ú W@Ji+o粭kY-7lI?.7=7ݰf-8~Y>~@)\!a`@aѩ9O]#1;y}~SኋA` SYWZM̂lդ!ƒE۷O?hX~ ߼qX>A}>uK߇d&g(M̰7]ؤ&tj`4Lo U3:LS`WxJ#&ڇhNitKımҨg8 jy\90>]فẖ,_O2EW#7taP&4T3pfs6c&IT: `xhg&HE`ИdR=vo/45NޣnPv%A;"L5N!$R~L&XP7_8 Hm;z{{5md:M};c\2R\xrGZдȻ=0:10 cBt:s۩s=k/nkjtn'2V3Hf -R9$&gBsmWk.kW~wߦZm0d:O  TF[v׽}UmնۘImi 0r.IT1h0.6UJ[-K|减=7L?(ք(Ɠ9<ޏk3I\_>%z>sɹZCsO(E$"(Eɹ)cl}cs̃d0&y<<~Ld򨏆gԻ1<7?%l92q]/$A4} e° "풒X>=@ K۽,,DڅaMs(uO4]~s \筜w w_AO(\j18<_z~10@{[u'11>_Q_X{燏?㍢RQB1=LvV,xj!B b$LqoQpMRЊΰ+c4\GbI$gP \_aw~]3C.gI_O!W1h`Q?z9$s{IMyoRbA{&&1>1u^J@0dRIs{@L*@*>z}ң4&c2J.d/#..4Ȥsر+y}f>VjH%GKJSSD UT:Pց"RET^p_vh.Ur`Czf1t =. WlwVCpq78iܓ/& p v k?8gL|g:NVJNj P=J$ YLݓH VXOE+?}\@~gvM PUQd"?2='#T枡фa0QgU*,os02C4Vb> ф%V]#~oTTB0.ŒD˜J-;-[^ï@2SF$FXRq1:JS{ĵ~eWWg$s\Ưv]yrWޝdA#`(;RqE2WJ)OWWkj뫟jj(K 4JTE$'ꟚYP969JLb!GU!4e9 r4TfPK _qt>*s5?U_Sݡ`Lh")}'E9ON^əGS>QW_ϟ ;Pb.L)8 3".O 2I}i/;}R#rPݼg HVK eWeG ^{n z]ks/b1Wvj *Hrsy1>W:@` O6ECG~0ei+Jx Ld`J%騯>/^YdK͖qv{ `dmE}޾Ļ@O38lM;{inƀ84I-WJ5^H!ike鼑lax`P?54?(J_^1 J(fhecbԽq4S_`j/Ymr+/`X>"%ah'W5\gGuW|Z[~jPJK!$X~o߹Hk(Cp)f12:rջoQ]]{Fu_Zj~ Ʀ2ld" hiBS]PsT(`d"yՍ_}?X?eCI rdy%j)"Hg 1sCێef;JHl748cUUGBD2st"=5^vb.hmf/^J3{&ƕ&1)ML~=W(/^8Fɉd&>1ܮ4\kbł>DLi͵fb*=ɮv\Lpi;LDŽVnS+ycKSz}g01qt75[yLhɡ5h Jr 3?{jtx}{51qTW~/xbr||Mhŵ֬&BD Zͱ?Oe'0LfG]JOꇶ5ѷ66S>Y$hVg6&hEEfzh{}R\J* aA%eI Yx q\RMm-eEqx~- PRd7,;乶.QxS *rEUUA h*JO%hlY*Q (;T沞끉 =>J亊C 4uRiz}40!Cp eyP*YS0gL[dDH*(l24Qvi3U&S0 RRYY/INgulRJQoQoR\Ǧtv')ik ` %6 E} rd bK;K_\-Q.{͉&_߭K4\Cהs0 v߬/z:Dܸƛ|9^Q.xl0`0"ֹ^.x%u,#bFvz7M^ǘ|{F%nO]N&cc- qrr40f2f57~3mrklGږXsXf%a;N|mG峣'/-_(7̥>JZ=;}#{N'/Eo +mnr!QWܝ- .g>jbҶj?|{žyB$| g+>&M pE|{gsR|=߼p7XGiT҆vv;v/?ş~ĞyI٧Nߩo>ʄJ٤n\{Of31xx)vUG;g2޳zgvQ 霁m80Bا${퍥8;![pt^T\pT|tO<*v YHΑ޻w`~WWhYvt%CA_+Ff%K(  ~c`힅K7nxDڇ;MoFcm c+mOep`l Cp蓰Mpt!X\@cĂrMvs$KȔLݿ!}eQ6 s&&@}DuiV.6&K.8c t?dƊhጭ'ƛ-ûVHHFzT=㎦alj&C.vWDpZh w%jTKl*uG{oqmf?~pE&ô3& 0@RQ:e;?qDwG/] >cXzyaPk=*Lt|O[>(%Q+;/ 88V)nKD&5.TGyp@W^ƈ}gvm9?t@,] 7}&&ߙ6wBķe\3A~vuA5czJɾC^{m3G#˄G{@燄O2;z}Gָ:33 kK%(NJz/zdo@g@zt*zmhmmqRkH14U UњZyVN{h]:u`YH$_iכ|N{h]%oDb|ړms'{>yY^yb| dILx=4;4

\׾U?;c(I:U*VZ;sq2CCC~_FA[\9 OTV{u~f G{86o6`sv|o^ @bNk7Cىb3 `z'ZVVW3K\)^__]ݳ|yuO]g8r AOsw[n4r⥑ ڷį ~DX'XO]1DrWweǟڷ[Xw?}ZK uH%0ytv@nnYF=(Wg&ro g:G!OtWV37pCMss?]RDbq*˽<55'ݻ*N2}@=ıfN4p`T9h oN4 ^" {z7M)pR1|ߴχC?70MWJەz6_{K}O0264 4pgzgĶ뺥/[(ML77Hϼ6P胖߷в,q/_,mLY-",s˶ڎ/+xpľRx0@+B"٧l;o}-ڧU~. ~8-,b-LP։7i9 km\0-͵m˗ ?o?30&lgZi2dr\.oxvpl&'`o͛wB(&HRexxnNf+@ 2Xᭀ8rv6\ω u>]k.\H4`jB;TL>Zot{ g===Դ|+Մ[.ȥ^[_%bKMXkM4a\W~7o/zuua*/p\\r/hb>aRO1?u`sֳi1_{X/Z/-K^*M/:,Ϗщ| __UMMx)߉ '9>ի~ q'H2MLoK4Muf"%%RSw}fMz{!MLirtj[Nsl3s[/WMj2W/tF&(h%M7􏧜rγ:˗SmrF8u]8C`0(/_r…?Ͽcc%RXz[#6{Q n/^xutׇϿ:t kg? fQOg}>ymGws쫫:Z_yHWwsm7h2hq@gShӶ/?崛Xy姬_Vz3n^[}ݏ{jcs|g߳_oG4l_z󲎖v4_Ѽ~YGէ,iyтzÕ?{25koY?jnl1vu{cl}-"oY?ŵ '@µWG;̿cA [p޼ گX0ΎWGµ8i&w: ^/勮/-TpbI,>/}1_faq%eޏJmR_:;s95ؿׯ6-q]]ׅ뺬WJmZSW_&wx7laW+RѶql8(ێVR;«BosB[sMj.c;R; uHf.lՂsju3ï60Lqep\W4WWo>3oUѪ՜ u]8.a0qฮ\8ձՖy޸*?^+]l`]‘.IdU4.hYP]vv{M7ݲ|0M !, i0 /g'& ۶+Qkdϸ;6lpM=Ez7ZlY OJ:U2[3_W^9~8Z ɸh:98oY)yJ ŠQIY0 }=c]u~inݺc׭['xҳ6-]|eI2""PcL bw|elo&xc]oYneY% V+rED@` 09c{edǞI0sD7kt4K"P?1aq'r ϮWWh|淶d˜w$;0<ۙͦf^_+ښPP0ȌPiBDLVO M\WNjUn܅M4>Y J"RU^xeQ2-SS>oPTWwAmmhT2Wy&Y$=[IfYcj|±'qC_9]O>z*RazWzLlQF Or泝|~CUS`@c>sV5h*{N>uV= $? 1H_/q|h(3s\)*LV MT.|±q3e}`p9Y9^D{Zrƌtf;hn܋1oll{0\qʱlrq/W6KU Wm+ڪ7c9tUaɺ]@/t6wHI1,>^0D:W]/u 5wv.0ڱcTT,'qʩ}W5_nq˗ W/XvגVs!*1Ytʲ޵|5kµjZqQJ ,^иҖkzokCwͫt9Ȫε'R3>ոkjoi^ Hy}~!敚].x1]}}[Mf~smM3F|CpJ9Ri(g͜^-]}}baQ'BV~}fQi9V71s^.V36:i>-KRqX&AׁR֕!ai~0ST exϷ2hύǑ0 OV LO?98Z[ ^X 8 aq1;%#D 'gGk3g>Tv\/!0;IV죴  )>xٮr4  `@go~q3;S uB Rz5 aeX|YXo."M&q x` "٧I 1$Ri:VxF#p8٪*rZP3\)+@xUJx<~>z{{Q̱;_ ]ۯ\xҜʂHl ]/?ΝoԶ\唸fڶfE }؏wirJ\Gj[>qLWznU뮲u=~3gr]VB]u㧮~LO^]uH+gO_)m)^+߷k׏ W+4r֕Xr,Wk Wpٻ6oo/9cW,s> C"]_ƝGK_{fu/u51V(mtpE(5Je )lXP U,˵^kuuC:*߱t]bF\FlT\Aٶ:߶: ]mz|A.e~.3ױ:WNq)ǶQ.r9 ׶(*8/T~/UmCi W)JBi q`eJ'[(0-LG2T/Y9hip +O$ z: fZƙsGk[*eYg:Ryuly+1XX Z\\)eYgemm`eFX, Cp  0bVXfie3dge>X%bѰ `g D~~ǤT2>`0O0k|8SegwUR)0 0FF^ڰS0W)xsC> %WX"$ ?+ᦿ+]e8g} :,t*V7|* νrX?D0th׫YȤ@nXJIUUUD"_߾ҋo>E Vĸ܁7Ӳf33@sS鋗ZV|fT>7/S#5Hs0o gs/W9̐xk}gP=G#a2ZkQIv6֚[Oꈵ.^uͲx$/7vٔҚ8yP7iJ/›w<1,˚XCgٙ}'.8e=/,[:]7ƛK._Ziy9Q涞w7OxݭcLx)bA 0\AY[@J`y`vރ^U26;Ph;c쉹G_lW[XRm_P(%l2t4_7y0PvRJt daЌ`Ap`Sn)\p$A*tC)~A a&8Hi\=O @$)Mٿ0 aЌOwγ΃{ 8ψ 0Xej|[CQ)N! D }F@ĚV&XG?S5-߼־z:L,@,b`G?nE Yc0&`p#\l>.4o<TUך}|ijҷ/guU(؎ x`x"~ `Dsc0&΀˖װEW*ʲIpo -~8x"I q&V v%+g !3 $sEN_` uCk [f5[Vq%4p6n *|_9~Ea}`aUgH°,oQ̤Ѽ-]H,\1UD#3._mذa ;nhk *IQZr e;P ȜC&eyVW'e/7N.okwC[c/m1h*rrjTk<;?} uUjl5D כJ\ǞP80-,LZ _03y~$74TT 3 J%+g'\,Ӏe޷Fk>y`\t{GPUz|՛ ]GB* 0L킵/㣻^+~ŽjjK/R86cRtaVϠF(;_~A^~ŽC;v`~raa݃,R܌َ\ C7 PO~y 'fG,hVCp1k"/}JL( 4u\4Y.j- C`0x i }!Li>)~('qHA̍r 8ih@`C{ BհBUV5\x{2=\6 7=e{UD+0aFkAmp#-'@v|ILO\ɽvT74뛠ß c"%Gq`|Dǂ2K 1salǍ:\c)KވW} 5|8þq_ qʒyxxdug9.3w$]0~n!/pRcDZ @>ml~続Ms[a<3|j)o[)C_(• > s[[g,>Sgf 9/ao|߇QAA2{G 1F!5oEѶTBaMX!0'Ja4_{QXZ ùғ9BwmP ⎴>zR,-\*r(?\g" M&HI0&<Nq`s`AoYI LP'Y(>rӓ2 Ts0`&]]|b0UI _*Bs$jЕ#lST|R)خBEaZ٬NLH$Rph$Z r#s`FƬOF&r)1=9ƢX4Z7>:"UE/+^BT~ +'XtJXP^S%1 lMXT7= E&/(g/zh ߍ\b\|0M޶4%Qp2I( Ar8e4ִ`QSWغ;I#"FkA (0~@%pZf?G)+e1 1F V}ag <8vGQaV=C OO`bnh AzF:6dGF^[|9cV$Bkt: . (KdcoD}LܶwUV.vcWx Iit ' #|3/m}19m~ͥM ݅ZF[0@KDmG--g!mJ/g|X^98m.EwB;"@&TJMٻp t SSILr >sL؇pM ? R ` 4gg{iPi]q0QPf/1]@!0E8L^.ULK \0 o39,F` {eK8; C@yRit_*ByFldFa0=x`٩Q@0T~.WRJ.dtȻPNDdev LH%PNL{\Pt.w_k]2 r H:It\-#?=|")HcҵQ*116 8oE1 qlLOMwAU;ỳ  phpphX԰7=WY2jGjY h33￉*7 ,]PUÕ\Y* ct0κ}NAJ W;c8֌0hiґH&68H8!B.b!T@3ƏU0A%b&@L /CI1 a@ZF^{_k;H&މۈs/.Ju~ïnGi3̺p-(`MȘ.ښKKKhk.!cg-(&P.s s.|"1Q\&',]:P arB>+Q1Ɖ3&~.0^QpJPE8TwTwO6C@ׯAo x0C}} )I(sxURyX671>>>x'u3L ׄ ,_:~2 3e:WTNba,O'%V-^ Gl"恗MM%X!DT:gT}{{{ /L_'vE篃ȍ ]ċ< g_Bf RcL)y&+a:CH ľ9`O-g.Fb ?N{0pE>޹3QsϗIu5g{Gxu0%C[m10o"*Ž h6!&|ixΝai|iтR>tuA{KSE=I0UhgڶK"_,/bN0 $:dFD\N $3BɈ!i41MD e y/Cby.:AZNe5"3LIhSL cz? 9Q(yuZ[ ]{vfX{lVJj? M'a,ƧWbrp]ƲPH3'u^*X;[  8m1`03Jm1Hˋ2:<^=zha$ඣ }q+#!).?: >=yFsl%@3nK aOS0( RsM:%6\X'w2,.j+%8cj]+3h`@J 3LP[dZ Vp]>'p磬W-38ڋԲl%!2 ݫ" H~D5>fwƍa@N$g,hRP~ $ h T|``_l =)1tOІ fvrx*T% Lr\T-UapjdlkɁ"Mbx*2SI"<*TBS& SDW8s)n3d.g N&1)OLN09'W+ [g9Ym- E}5 Lir*TA.ɟLN% +%a@̇J`6 .@P瀢 Qb*yʟ$ 381.P 73 n#;> IiBµajjEvbT%+|cCT#HVyFoo/1|wksڻm+eE+ML{w㱽)g^z M8)6_Tf/?Oz̡j}*-.ςy {"S0bzf6S@7j[ @feAg#<6K6s9O 157vf? />ΐ$4mLC`͙!y{%E~?0^r=?8AVg$w<~ߟ)YX&̃A 7~MÖ:`,bO|wȎ~oa Rv?[cU|جy[8Rbd|♭[,;4>uamĪ·"+|]yAu=gLzvAckAwwMouq]HLqPЏK.^ EΗX)[Fb*\v.8 d_4ַkyyiccBN/xV0ڏdZ 7I 0\w˻7vwwOxݥڃYWj `B6wo798xC/H%_G(&Fc]W{k2>K[~p:p_yCp!0ewbg-Y)Dbt{.lk[Qo"ܗqe[04A1K#$*㣈g1NnHNuD^ٌU2UyVAaDbB[p*; st&ue{nI{ӎL$2鮷7}ߧ/!(Ɖ4i͘i *C(@ \"Ͽ===(@^_+caC>b fQqSq+whA`T(SWMcW<ۯ,C/5! 6} !m7*ի=Ǯt6m'd6[~,zeO2YdE0$w?t篷n܍C1tOOg  |bpS^t7ݻikOxWzݳfOmm1M2o+l[kMJl[@V&i0&OnY8;5k駋vZ+Y(xr~LfK̕]P(`ZR5k̞xWG)5v39eʀ~`ھm_D&!A2v39VSsYkH- L|!aIs,C hZè)K/ۨE0=>B^׽p-[\\3\ ' XֺY9@sM׼#yYՖ as.HX48uI3ﷰq`q/A*K[K68)mZq!L!iMUXs X WbD*uo;b հm6jƙ5W9BCpFJjբ*4B~`ThȇsTvX+5HImp&8 SpƘVZ;Jʦ 1HEqXRiD| 5Pr5jJk a7LS0JiW) &ZH ,m *0#pʼ,bmBcu4W?P) L6@Z}$5iE\iZqME1:0Jښ%gtB H~CiMk]p8nE? ^x8Eo; :`.qIDAT֤#Ck"h㬥,\E`3QZ#`8gy+"b](1M\i&?&GbPs! Nkc1H Mæř p! JjL2XaiK=2A=OB@3m-AQwZ@=s̫MsOC4Ppa18hKO;kO^E'<;GM:mz }NA}u;p⚺k7*Z%1͠?puSss F]C NY6 n&n.^umCKf ࿺C)5VoOsx"/1KtnT'cÖ D]]wvb/,[q`f"[Wr-[.ǾikU>p4`~]5|29KO ~"B+hK1Y\4 ,36=e@5xy MQ@sY`l$&=>91q_rW N,8OĄJkƵR"v^ 0W!5f@O]u&@dЎC~T*OD2Izl3ǶaY8B?glQ|&#%qT&'ON'x DCqWibD%͞~:\?.Հ(C0J0B*'G'Rb*} ~~֚ 2`pxڜS-=q~ʒK)qDD[\_Ŕ8dq]AZfXJ%=1R@ׅ?ӗs+ a咙+(Pvҹ|g(݌ P>'ݝGnzo0`1]x_;5pݑƍu7ЕϿx遪K7bbo@0 aON&.߆7v&ⵋ5`^sMCx2=PH%.t-|m5( 䛦)Z/K'@]b۪hfLfv&ylwwq}ߥJj:BhLgfc:GglK}"B g4eR\p0$u R_Mj|2-.ea|: "*TZt՗ E{ QG, N_$4ra0\ 9 G!,pPpƳtxϬ@# R[LU\%I>VT6a0εaB&}90'{OB.kC&wydžt6|X>05g x>w~=>7iYUHa,(wwlXV&A^2ΙL6sSc|bcKN_0`6rfWJ^\)+׵ C1h@Œ3/s[b0_ H$;//J}5J5Bw]w;J" 4P xdw$ȴ92 Ŋ~sc{#~*.c~׆L7xc3ϭp4*1~bq@,~ ҉c{aoE?OPC?^g)bW @DpzΚ~N\f/_><٫ %|?8s˚֝7ĿŢUui2Y/ėZ/X @DR30Sn?`Vl?H^ #H|gkg?ѱ[{a޵{L ]eXۆ> h';9>kצ{b4$m'=:l[~?̕z"vCUVunsWLk1ΣPv K[/;K+ٍvGh[WZeb{{.bknl4,SbC"5(խb+sWӶkS?zB.w+-# rKxK~Q5a`t ߾4 HۢzGJۮ5Jz{{5?t篷fK[rZ)\L"!XPcR9;0B. \rDTCwz붻Cu*f [ԂR| 2UuըF&oc4E>_R"[([vաVwo*i+eGb$#)i>>K e"MiwozUaYszQJ!/`,Clci\:u[OB?T;g5,euۉSgn }E)D 1e :\?S H?RC;~r'W*v"1 A'0H?un;\?:WH9S\nio멽x(S_UǞ;uct/90=Y{~gjE-~c)/ g8;س1_TBTb^b\OxW X]_->{* ̰h?|-:ڏu^sʪ_!D)bF|]ѻeȯتEg<2y&aGV#?OV<÷|fJO=&n:Y_[Rፏ|KG]w߉B0i?p)]y}ϯ[Nn$C ZZjٜ}bM${%EGC-5ՠTUU4SS##eGG=z|(XUԕҶ  l}ѐwpcx߅;aU>%i- ƍ|OǪZvE; qŭ>6Bb:q>碔˪PMύ'c#p^]]G6n؁XCcîֶTRBgk | \BQkkPbb|bV յlcW߁XSSˮƺd:~xuN"70㔎˶Dblld e6nԇ̎X*+ˎB4? P\Z 7Z(Jʉ\:lglE( v5e9YbX&vXeqlGŢ>H$چ3bMbW.R{~^iD4|l̘ZҀ3bl/nZX[HNxi<ۗQWh~A)W7ܿEIS?]p-[kSSS'OǬ~FR#d;~]͍u3~RŢGg*5^iOGժX_/~SdvYǟHOFZ;7tTtSj#n{l/x:/%Ϩ9'2C|7^ukwwsGq`Tמ<'#xOGU/H7՞6s8>?¯ys7ύ~<1,(ѽjύU?Lsp /NaYGsbSA8=F |2ҺzCGML5ԜQ-PWgKM3CsB|i8}}A&cR;?߹) ]]x~duuL6p8,4iyJK X4UE fPpd(K??:%H_RwBO@jkqr=എI,]0EPBBХuݼB |<>#üS~P1@(J)P\xZ۴ 8PIuߞю @w/nutH,&rE{k5? XЀ5SXQL'eݘ:zл-H0@,Riyڒf4 MQҀE#F.G6Ww36q4_ ^qu~K>7 Iӛ,l4j[>4Ei"7 q%ey]c;S}]+ʟ37. [e}fZ/"s6G?ff(=3/y}$i,JkyVPa#sS#T,j\|/=Dybw]}kɟz!yF%Â(i#a؝:yOn}uu EU[P\N='\f0<<}^hzU*xӦMWlذ87߱|J ,o#[Տ_,*xH$yׁ) L-c j^B>6l(?ĹJĸD}x|cAǯ6}^78;jxU= ϷF#gl?x+cYv .m3{H<ƍU ۱5tfJDĚ#XV-h4cZtƞ\؎wǍ$c^b X*c_c5bp?1 X#Yw.x~(3b矽_YO睽1`('>x~F}]Lި7gCcȥsA.TSsA=@`F.(}.}ltoܨč?xgcSHOgc4V `Ytylr7uuuT q˦XsX`uV7), pʗ>񕟿pB~~{ϒ'2tE?UsS5G?r2ov?9^S.l]Tϥ/.=T?BNN4~.ɡkʹ ~:~Q΍ɡk.'wxc#䦧t+cA= 0S5OZ?kidc!>G?q=:>u͍CO؎-gsVjQsXxW#7lGک\s׶"7<1L̩C\~\&e iPOh"dLT@?&>ߢ.$Je 6O&mAn4ZT(ўQLtuAlnYۊ?4sΚ+4crMv̼X_mf Vl޵(DždQ4h;N4x[=th3h K)ZڏeS;{ˎ c1Lk=٨𥔒X&39)~eZRپ~oX 3xeT#!QMX6;>'nX5͖aVZjq^T?QC)7x6MQ2œ`+h8mvYu/G# :M&rϥR_{m盈աqPD"şFמGsΎF}8ȍ{y.{k*Ry1K I?oK?3_YX/ $%X}+,I" }I:C߯0(cSSԪU+Ʌz:9wOǜƟu.\ ̦:'^sw;,I$ 99/0 6Su@Φ{dk"MD`0UMp~Cu"2Y $dPVj^+t"*M ~+]h,_g< ZSȝ,S_dI$2fSJv& Ν;S'w翻vZU ܪ"i$J/a?yv43~VGģBK">Y,N?6 : dO}Csn MNy24 kii/)"J%9;5 *͏ß|VezaRJrg\*m.Jڎ71 LЪφCƕe, LK㷬ya ^Rq'tyMNn kφ|+}>ke^bqʶ5W(~kd ^xeZ ˲d kOewk-}ktt.'lB8g&y\8XHA)UZcZ^DxQ)9Yw/_n566)Ŗq>Bfx"x8R1RWv\݇X/_n0f..?ss9*'PJAk]VJ}J׈ԋBWv{{{>OgrVr;9M:{UvG3X\FS @HB ɁC'$s(T`L3I.rQGٽGI#&\\{>~B(gɯrUa.f?1K')l JIG)SJi#JWb?/O}u}O?]eأ 5n40B %dOLږE,h<6M 1PjZ)PTPq*kO?p A&ѰTs@k=G &~&@RqP.=\| |޽{eOu*iTa !$* JϞ~[V9l4:zg ?I?gɯsN&DmoU'F !dO~JkwA'k3F o:_sӶm1ƝU?>'C?N8m?}KgVs%ODscq m؈Ү^ԫDk ҰgB-@8N]&gAnǎ;K^} Jqv qRr QL[8tʅ.n5L'`1/؂i]KJ4rvq#(i ;0ys߹0[%SuuQBHSvZ a&  RdH7"LX}ȕ b&.$ @#B+VD (?6_ȫ܇Qzլ.K jg2d.Q]K[=W Shn54Eۛjk)4aU%RZeLG^!jۣX;42&^@8 HR*NÏL@_v-HD,aLԸq+7L$1B;-Dh!|e ۲QJ=֭ҹ7S cѳRI-ԾòlaU ;ĵ9׫4aW)4 '2QZi)|ׄYҲ#)s}jέ+P6O(;:Pk<1 0'^I_*?禶#їR~ۖbR̸u*7{Qe ˊ%'N)]ЫcKkaggb|R $!O"36Iy2~KT֟ħg)%@HJ!h[µwTZH !d!OS{;n_5|M(eN Dt[q DB(h]ꕁ SIYY?8hKD"*%RF  !D4|:pa/V|e(M} =!ɕYU޻}No/PQB2b<2R^RBƥTG S끉uf5X2 TRhU] &BJerCxl} 񫿗?͙~97cZUO!@(@kBies^z7x˟me!QqTQu{z B *bj;m\yJ&nRX,R!Uʙp RRsaMJ?~o?h:W@Owb@kJ(e,CwGxwO@Բ >kOTlgAOhMBiZ*! g  @is]~eË[Qn%n DS)$>Jc4Me~=S<~vR%H)ȹ'87`g_ٺx׭dq,:*$B4(\0(1M8?l1n;N/[dq<}Y*WׇeIJLPʈm,;>ξ~W43>rʗbH)@@i!0f²n5YWy.(>7|ebN!RU'/cslJ˹^Z]a /]pZ$Qs!Lr80 0iⴒ)sW?/YxZ<8BU-$֡眚hy/7EIkB>+M쭫Y/֚iB`C?!iP~o_+Z"D+ٴ愐=Q)Jab45#"9} y O{paFu˿$V$&ӋgbBhDM?G:50&yj@QaeYoЀVJ4T1 P(UpݕKpFƲ0Mkhd8ފ)v 6bV.RS2(A*ى@@/dCj+xMٚ5=}κ@ׯ4ٝB)j 0 %5\/z %L*"Ȟy9|TRZ0NRpUj_bZ 7/Tj-VݔFg=as'ij uظאDc" O(UJKx[6nJ?C<-b:#p: > JhJ៘ä RS&_rr3d֬Yf{{z{ jUhS%3}PJ×Zc (:2 >|r-LicoV*J[klQ) O*x"493X@C!pث ,0ձ#Ufarێ+sbAI,ŋ k';(#aQ]7O,Fٕp\"b\0&]/n|ڥ74'>[f~_S)&Ԏ0qʎK-X:r'vʥۛ/_u[_{{{ق ?9m;V/Pz0kҡ,A>ԅ]Ac*@{f5%+v}^~i[oL}f?h3ŸHe bG L9# h߇M%eANArլ/Y?3$"x"@*~%gƛ/zS-S.òlfZhTDs<?p|x!Vvw|WWZCS Q( 0J9 +C)@@(H4  $: |pВ=A@C) i(8c勠谒VFQ<9'Ꞇ+ph @zaD,~PPA Ťpc *c(JK@}D+HPL*Gl3veY`r)\ׇhj>|Xtאiɠ՝;`phDkSN%,c٦M*z]M}wʕD'g5 7P&L`(*Hr8 4D81hp"1+H1\޽{%9}ZJ)%"(lDi([~zZ}}Y"M$$Pfo-yЄ24AeY4*_T<>EAB>ܼʎDRJhs4Co#{mÆ-imSZ+ׯ1_`_V%%DWǧ7j( Mhi^]QC LF85}_K/Oh__jvץQ3jI$Wp`)@(樍%;pncOnLN+֯_d2? nԶ-K)%ᕙ "a3˻c8)c*p.GzaJ%Xf4anKy<pc)X~sJi|jRk|@PdOQԈ{ 0:)[WE '`!(E)rm\b>@`,]PRR 2P_@ٴ\Owvם8IPرs|&gJ"QhmXHᶞMm \vMF%>+Qtj RSCԹ;(PxHl̘ւ.]q-kp"P(ULƪ|vD4I1 DsS'ZZ!GxHa  JDLP:i?_dDCk LؘVsTn[Oe+"A%mZԥS'pFf1JtH:jl,?T._Fٓ8%6AR)sBdH(Tg1LoE*jCHi q, (3Jhܸ:_iQ(W("F\;,^eӀ^L=h,ʥ :|>x>*2 'DF,b|Kÿߟfkw >`jÜYQB8C. ÆaDqr`+3I4~ @`p҈Xr*XKfẫB-s;b_>LdX#a>l X ?CtV78޿;|u>ecKfv29Zj0 J)8Ւis7a9~g *R}Z ؜1aa^K_b1y xu>jF*jczS=(%? tagҥ (%ʟqHس$Zb#b+Cg%pb3V""W\7͝fzģfLk9k9zbXp͝_kVl)~|>{{1>Fb玁Ph'qbDb&c4ۈE})U&AKCLCk6ZNdÊWZ)K 6ʐ{09E]A2e_(& F?_h4PL@]< $J #~֚$d%+¢Bҡ姀5ahueHcle Y mDl ߲prq y>?L?e@4ų@ K^ظ 1|s08}u>Vx<r$m $|?L}`w'!eh|,35EhX4 @KS fu5Bk 8zbQxpPe gu$E'|f7Fa-I pИF)zW{F1Zĕk 'CiTǟZu KhWc;yxK {`LJc?fb46^1lv?{Q>4?(t{ 0?W1czzo Σp$< <cZ< 9XP|CglO@0<\BT&LsY(UpߛnŽw__~ ^ߏ8ir?| [wk{n_=sh RVP[ӍK1:(d 0x^q飡~[WS 3^ d~'V.K 45$A&WHPX0tW_j`(Q=e]Lw%3|1)˺kп} _Q@H2,V%@0" `^[9䯷pd="k`o!aA#G"S;oaxzOoa,=?U|_W_x!Hk˗uO!bx[y]w^{._:?}bm۶5_Vy-m(Nԩ@(Ekr](G10#>/(5 /@0V+u4@kLm T͵T$wO$t&m\xiJ8vd\:-Tr 4wД4!8ѥ; YOD)4u`ZC- =_Zѐ?V'/*?D+^qGMB3,r#qύb(90?I~f^<0L??w q̛8pd/< 7^|3D= )%hl\=(N0lb͠\E> JI4/Ck2|-MKLgX4W,G1.69ZR` `T7+Mǯ6 eė(eβM/XW|!11%mI-ID-5&8T==˧ౝ({3 \Cc`r!ȕ+85P Z0/>K+Z_L|jF2s<)M5sѐ"(:/qrDMF<*xԂ)<`{ Щg]Klc咃<:[qIx楽8rbMuI$Q 'x)#,G _pfxAr0əhM2Q,1 cZtG4tT"^EiWV}#cX4xnX:SØ`AJLBjOk ӈ!-OnC+!c5ؽ?'t`-c&ԯ(C+kh$c6R(.yhOA@hđN\PJM^=56GM(\ )5Qa0Ah~`hZ}PO h(Rqn  D<$"1e4F64ht9zQh;\kxMĚc )Z]-)X% P*aPy3Z 21oF Q*q.4%ݚZk2_md7 ʦ'b^G" %!bz H6Q7ޢ{.|MHc6gvBs}0$Ԑ B)QpE5=w56]{ @RFR&(&E}CH!Q3,֞2-9Ϛ5GC"``1ڏdԆT5 DL综s罱 ʯr44Z+xPY0#e`wP0 |exOX:;|0wf2N bzW,4,54ZnR$͐R@X#^Ʊq3ԃ J*OQF"f!dPB.GA .j2ⷸ&O KDMPd Fc%_9a|F-,~j68jbTǟ@JĢ'b48CoPpBUF 0 ,10,ֵ[wK̞q><@}W*H JQ T@>dF6_ĭ.Ca\hG"؏qoc 6+|+<%AA džJX=Izl;$/iX/^ybAk 0:4I-1)ZC+ &<$F9sE A@)F7OJ*a$V [㔡5 iߗ+()K0|+& BV4BTvTazuҕУTC+K<i'4ʞBYh(DG 8^\R%bY>h>tHw"ڨMh!e2(;&4U7u :PZEVҧQZ?+;h F /< @Xv1KFW>MJjǟH?b[[d@E5%~P 1 1@4 y`tWͬS36T8Өڦ.位XBCoRiuA3J(gҹ1u!} }}лYZJ mPzB!bP@H JœRЋ[#[ SOpFKcEF8ՔP*Voa=FĤZ6D1\# ?)@hA JЪs.0-aR.7ͫhAZqr?8x' ^/¾.FT0Irϩ0AQԿ0_I]q(=hj|TR*hhH b\kk"6= Cѓ9aS:@@L{'|vSF2?P*LdhA.yonGif6!b*HPPH O+A4%z(,QHnC #p#&cF A鈘~ P&? OR e0\bfp$/iK."ZǗ(k<]aUb۰R1%۱ pp:O_ ׂlK\*5!?zR hhϽ"@BY'AdUd9Z%kO^}4$=_ǿ"p\@>~>( =_]V4s"su%O ﻁ!MN8U:n$'#Ga{j0ON=DnC]M5O7]6BIqjq78c:a!! rn Wܓ3- Rݹ^iJ@T- Fz/g @wuqB^9o:#|BJ%XՆE-j)3@wjO?@邦^8 ~:*9j?'FU)䋀8?=8 B4~ՏkAbuI4>?T#/@*ۄ|IAi@Ɵ "N!작d] U JDǦ&ωG-jW)WO?@TF4mW 팢Ròεω,!}Bىne7A,jy)(p԰M0_k] 7ΟYiq!峻.0Jy|3w#'&qϿ#¥K8DPp 8pkY/NCI$ 0P_ݡN=!q- x *%w |<$k%!R-V㈖hcǁA~ȗ]łPNhP,i+P0,Qþ~zbDeR>$Pᨍpp W 44Qɬ2y!)NMA+X&(tNHv*Y@P$*L'!Rr! ՉPqPZu©Wh0D5eOTWզU\ϣNpI(Hé |BA.AZh(|X1Va>( Hto Cl>X^ח3w 8F : (j?EA քh-X.}{NH^v COT K#Z+%V XᠣJ@ra<}Sߦ?/ս ?Ͽ8;?WmA:W~{T9J *ܼNè0ozgPѣ>x;6_ZzgsJnhV*NB;w=,],ގ)?!? [,X\)IJ(Z+\qr=(SɿUpK>P-qAI'6.;W;0Jn9Q Z0 jmZ0 `DG!A @<~w(Ig&pRugG3d;>h PHHf<>;ZrZk*.EP+UaWB(JS$=ɧǖMaSJCHM'nabA5Ie(9R+BS8GO BQRV Ѐ?RmG&9 5M} (o)"^^ĥ| W: .P-Wp2g_a)|oåsp@Y +@yv .[8X:o 8v! %l7>&$9؟h#E^6!1p絋LoQq<6$qv1<:Rp"}5g5%s1K0x:&4Cy|@2ؾX_Uɬmς|)ҁduӤO#YS a,lk8 A!F2h>3*19F P Qq|lw ш:1],ׁDFbh$K@ 45M mYZ|RX@c`]cqH Ѐ rR`:M4y#b D~`A9&cpR(u؜}[ ?Ǟa,mk&`0>տ }Sް6g7|5˙_j?_Z6aN?q7W>a~]_O~Kͭk ^$1pF1>UWE]]BƉ\;oOmX^' 0͚׷itԯmӚ~ /ö Cf jE]**8FXin]/])Z6m<Yh|epB̤'t|w?yMO_qzzzM/nA=Bi A9i GżFŢFt`罽lݺ_Rqn(;fP/p<,ՄLMC")Gk( n ǫ ^B|,{RE0_ ZjC9|mנ.]bޣ1 !/_7<TRx|OoއT*Kv|R1KyTh!U/OBMa,S hԆؾb0g|8sڐLDPq< d!B`47MRL% 0M_jp);Ү(jc\O` B)_"M9X }?x#FbQg3xB%9oh[ZULZ[vhwDGk["j*U'Ad`n|?4C VLg1%(%}dZkB,MP)tt7_?|̛Պ#>yӚp[<%hD6 \9/5` Weq4igG =z aq{b<#v-֨9qcTS=JpĤxv} )o왏4xӵѐ t5@#&EOfMnk׆s1.%-١ݲAp~ flF}m1<?LJ S/>dXAlB=%$lŲ\zD,;hDAD NaE`ZĶDw 7PHt&92g]BF :0Nd8$ Ir<c"jHXhWJCLm5^_sNf2RA g")0,ɍ˯u`X @5S9MX.7G`S.rl<:GqX `Qr\nkZcX}}rÚ~lo89+jq2y0wV 9 a&$v`2j  ^6S&Szmk=[~<0l ZtbxQ+`#ulϞz/_i\*sSjAG!]H:R &E)5 Αm]o/[i$mӦMLv3 JHYlbhdاš/(Dxt3;eģV((ÊCGPŻaB7L{?Eg8bR<6 (nr6OrlԧϽ2xz!z= "îO~#;cYe1wV bQ#0<2OkʿF__\!wR*:.:kXxe )i9D7V> #D`,Ȯ & xI`zl;ɼO4\~"|*R#Z>LYB\XlӀ%ЀRTLŗY^mOv&Ք,biCZ_f\nl=n};Z'YsDăT R)3Q._4fmk6E& eߪؼ65LA?wy۷򖗶Nɯn~sV>m{VA^,xI*Q-58vtcf]ńǞ?:-/;]/kfU"9+xCGsx2_Oyj]d G{__j3#|.?02:؝Hʀs솹G֒9*ۚAM%AXX%Z#_NfNBL<]m3f%kX1\=wNYpRTDʚc!Vnyv.7ز{k9- pZ# ]0 }Ǡ JYgGF{^=siZs PjkAPE#ZQ'JN:Ӂ<9r!nؽN֏GtH91TFɛ'#^^vusc--!1FP>vؑ7Ϳ[ M^]sӻomj+hӃr֚ҽltt\dv#TN Bzh$֏?^O^~;XX5ODB3KW7};Uw^bd[k"hM*1v-T)BW=W4F9mxOWg |_n7ԖIHXupC<ohon:'Rxmo0#g}V[AJEǟL p!!S^ uMlinZh>=#i=ȗj`dG1meO)h}}p*bzP fe ò {'5T-l;:tZ[mNcPjY[.L!1@id1 ~< QBesfWF-lJM7 L'{惮<|ESJ1ghlus%ڪa]]_KIIk*s , !,zVω_l5)+]UGOnwBqeg͝c&;д2+Y5kիWww֚xt)B~'uhiisw/*#P v}{[qaiZxDOnܜ gA\)3 6! F*z>5T'`vtdگ}7_p3֬YC׮]K׽$Qm|]34.d4J2Xo<-ZvڠIxl: '#Wn_.le'?JF>#~R!h}yƝ;llo{h}=Ħz '_B,Y B0j}Ǒ4=Nx46:c֬7n (?6 DGLBiRŢr/NUA <՗Jx*Ko4^c !s5O>6~rNk dߪ_sIߦ_{Oƣ`7*Z Gr'}~{? DǻV<@(_߰sۗaaF#@R=rlO.O{zz1>&$R>}7 &tOŃM Fxо|ӦMVSSDH/7_֍ I<&@b%%tN۩8uFr*SG yo NM$>|D* fmI O Xd 8%1J%h:`N]^ؼ3~RZJYhKHDB~u1XpqPJ#J- Wն}t4Y} K\>c۷/~^G=~Lm>qKGKS_JE4 e/=0:ҷ-_8Iq?m/3I˸Y0#t Dtwyp|&~wzZOԄW^Ӗ^m$ZG^ԙP',<\i<];o8a@5Y^zqf}(vǮ1yǞF+Ë4`oPzg?Ѿ?8Ic%0Nu0`6Wv> w/t'3vcOny婗v}5)lѼ5-]kB-Mkc6zئ9 'paٶuާ}A>& .fðDk 5+/E-e/77>R\9y7yE+"Gw~m蕆T$ %~^zieE浌@%ױjZ?z\+6lܻwoWXF-a.M4Po ӢIS<7P'i-m6ZmZZ?hQݕ1j_1*_OofḚIB+XMhܥH 8v@_`jpC0i7UׅW۰Ou.Ay0T޴Wb]]khh|iY"yemXUy9ڸxzlGO|?%IW7)]=4ulg˦~ *;$lGhŷ_YCI_ߔjY0_RGn jEME)3*8Qֈ9Ҕ>+nwjAW˿47~YD\V$V%r|#tz=LJ/ʯ]>jFapy0 ]8t]G89ׯ5ܶoX2nnܺ=mqkGуPt)P[{nz >/OwzJ-Lg+;ױ֫b6׮/K٣Vၡt)[o~CCۼ}R.׽f>KXf`Wv'4+N\Hlչ#>˹δgĦ=/XPρMc'{61v_N7_RP_!?uZpOdۼ((f 4QZ?]ܐ8:K{?y 6h]>tc2"vcmxOb[K 0 ޵?)yҹL=zx}uocU}?gg& rwʭ9B>޾ڝNU4cJС>:6`FM$bo5̸%rY7?ㅔ<l{"O?Rjj#V܀~l;a԰3v ?}0CZ*aYѵm;֛forQWɄ/4<t]_ڻw:Χ0 xۃnoHH^3+DO'X4jzE9ۗG{S-TPJ|T*ΐdF?k׮TNx$b(;,%3bY[ M5a5!VT*<Ɍ~_ν0JΗ.cv+S1U?SO؉Pi3QLmoYV=7 0F ,i !Au\؏e0 05<5DGk|_ )u!m~ʬzƌl"gppC%4$ZZyC]?>Mn21CPC;jJ~\7xb9ova`euAPZQBH )뎹P&3HT\'B "a"tp埈߿3'D#XQݭcPV#0F 6A^X=ڞ<P!cE;/5+خ׀>Ҁ?*K¼߄| nrDL^# om ;&oͿ-'S,D*EV4Gb,>.t,!Y!U}/1ሉW2GD#]3 O^M?R8~"J.&=#BJDcQ)G~]C=s/K1BOԿ%@X JW {sG$s$ϳ x8>#Sby!G#jrI|ׅVhtiCIc["VB*2!Fn[|&޼W-OSB_~ܟ2QZK?7_Fd8!#_mކǧ?Czɂ>߹H0P Ç]~!ཟFO$u2АT-nZB~f_<Gߣ fֽmiM\.z:{=wW9[wDwK󹬫 e4RXʘLC@# rgtw_>zZ wu-;cF׭Be0+iM|G~@[HsV,@/K (ʕvwO\yGHy֚nzuDlٶc]Ӯ,r.1iRzYXc@P(Tʮ.*ϟ}H 6\@t "_0l ֥A2 Dyv<1!T$*rE;z WShUXrĀr<5Fi& 2.-t 1q X01Lt@Rضy㨏TOOBW + P=z|~IJk咫;g\!e+|ڷV*eW)e/_o)nWK.UP)&F~r5αϝķm:ѯ~iU˯?}^D3)'/fʯO j?rh?z;MFJ4(k"8f&&`NkhKZ{ɒV R#ʌ*3Ή?7}g|q~ s:&`Ng"(tdqztpP٦)HȡEx?mS| \x}R_~[DS] ۰ yGW-Ӝp9.viʙq{O54! MUT%x]+az[>p뵗Eɼyeie[xOjxCG}r6!:EEc_й-47gSИV2ȕ/H*t5^Kkjb35Z)|wpp0pzuGf0jQBd9#a%hfPjU"Ltg&;2ʛ@*1s`wQhtaHRk>diV5QJ{Mc% "nْA[ '/fG1H+WL,qn3 +I L^Ȓ&e-Tk* O rS|6IXlaY- QT|^WtD]V7S)ˆC G~?q54h ֢4R|h>⳯L-Zk?1^yM!@;E JH拭Ɉ}e&ZrdX#2 MP1U*aI`ĩD$zU2caRm/˕mHdϬ&8,y$3(6P["=-+6a6ٶmZ O7V,~DӞ9]FaXA ?QrN}phh|Sԏ5ۚiYտ?8 nm'^ f>V_s[4bMOQ``<{$҉sO^_ֆ#v B?Z\ woT^'uwu0p& ǸPN& JN.jO:" D Zb8Cſfδ듑OS>1cBJŠzϜOk Cu /RC3S.gxURJzC((J%$]TJ$cz 8Zp3D( X*) \7"QUWoقd PB)!'jjCHt3b4&*8v| 78m/lC4VO) VJH<='1ƛO2_$S"z5BN[SkBi圞Ԛ\ пe̾N"uk3i&!d#?#'P!$R|rIH T%b@%A`G<\y%SBf=x܂SHS-[JPއqlVD)@]^ ܲ0/?r ~&4+MS8};f`T($Syŕ̈FخWPJ"H)ϲPJSJ /?,xӛ`%PR(}X x\V]DZg>$S5H*OτK)5@TṧM_~#a?W~**Ew @\L6TjĶ'5@"L..J&T)g%MjI@CC=EK]r&G/( Ͼ_O?pNJxR!F)<0]jf$HҜ3T_0S\EJ^\7߶qs"5*5KHZ"*$]@D2D=y@d)>[f (&X~©Nى{jS1^0:I~B4Zi-kS CH䆎:O/Oe?X~shm9&F$>RZ)%kjj Էf 5zD~Ÿj=5,~@`4PJjiCJ|^uCb{IX*L͏'ZL S|);c?ZI)S!;o\qC{s;W\cYʑ{j+ieM"aR}랞%7h<xr|b5DKlX ~ k|R̮'v bZ u-yX)d|F(sN6öq߇˃4UP h)?څ NP ZJ5o6v?CtZii D9Ǿ} Y}Uʺr0Idjq#a 3!-E|OQ#e <8o5\A,_)ɡTB=Ý 瓨mi$Gn._3̹NB9@S,28ØZ%~ZkHBQRR >l{ cK6+UT,@HPpe.I4H%"E"XB~&D+&PL 伾SBG"pcޟ#?㜨 ~ ^w`qRJLĉjC5! %!߰mdw ?_ dPQX4eCkCXcLI% J(4Tuq=QO h$Q2JIu Ś@ G hVD[fV$LiMMi)%RBI !P(UҘ)|?RpFu&CcY!=Omk6hFCW8=w| L LsxU?Q; 'JPf AKCm)Ģ&L1"6G}M uL8kįtsAa@I T>E)RR&bՈ qz;,^!ǎ" R^ G@'&xLF,FLVo8[ 1 =U / @x#8ÇM  P()d sf?qba3M1TQ`;Yê:jBPTe $r2".~#IL#(gt*/mhB[ȶ-,J 9,%Itp4 Iiؑm)[)efRXhYJb luОKp-lK`Yױȥ]iϥ ͆1_rr hAڅrRʴ+XOH[}^OY|# %id2M"A[~-]]됖C5X&>뺸&D4Jۇ+CFHXrl0(M2Ӟa.-u,Pq5H\9J2Be#$2MI1BYmDq +yɰ?kKI'H6"p$ NҲhCuHz uYцI-':웘ŵmS/Cäe"j *Z LXR{eA& [Ri 9a_I͈0 qlHEL:!f@*sl\.)Uj7p|.lq|a?l ?B"!e nYe޶0WF좐vNhػ,Fhmjj5PX#"cײzz#G(& !p(U|瘯mi/h^HaM?7 Vݒ)b&~p=1j/YHҕ5hm4PG?Rjh|&g[ԃGwieBPo4x[Z>%4^31uWqR'+A -i>䬳G)%e(XR\kKy^Ajnd]jm[TMѨsu$Ƕ|HؖG"Nm=H&;QIO&l; !FԫP7B`4AڴS,uCti6nI*,)bS:qvqٳ%)t]b`;gZ/U$Tl@fQ5` lKәOA A3.Nyl\dzOxT B0YDK%xW00ưi0KF >YδE32I}iv,f#5x~j2̋P) hHW0*iϤ&\tk لpg]EP?,QK%P$i  kW5P`}yK}6DH5O(рuobxǭ]By#PeQ+1>[hJ_[lT9TFafwYBAչ &R u͞}GȤ {a:Z44$E$D"> k0Ql{ yz;2V w1׆DHKCβyu]9y0 Qohx!EU#0|e =)F:E!9!d;TQT$V!i4qed2#BVK|*aZ_ёOוclbc= X\4-2@oc(Zc8_BEض+RQDo֣+rd%]iBPC={'}tm?a)CgQ:6y$:2g5H)4L7;rteStKVSW[v1:_LlZ]CGlOLfRG[dtD*B'>_k>eK6s,Y4f|bi<]\L!}}QH)l+>` X7õmI?muq?;ljyնZDJt̷؎cr|ZI*ltPi& ,\+ u+C/QIj C<K ۶=Uզ"IVv&zF$lA*i+P׍WJK̦sq1pq_EDĶ-J5Fg ҞpW ABJfR#1?ᗘb斅FZ`0Eщ c-^p态nMawШ$خ B"Ό`c~hwZkz p&ٖeTңZx\|Cًܾl邎(-?ovAđcӌMyv:^6$\%-Z'K`7,줧-O~Lϗq]D&i%FB*M/RLv//:jM4H ,T||Vvyte"e/[БxMC7{R? x2քm\cRg碌aPf\sr\&}/!,PN,Qc9Ckޛ侇7X<$H;A(xJl^Dߨ U6f\,w.XS{!9oFxe1~@;.X#w⋨4R84,Z`Sϯcg81aW#@ôsʄPEZ8j( 02؉1bw"ꍐv^s"֪51I(Q&h8Q xhKEi= 0UxXPiqu|ogBQtFQ@IP*`zz60;Ju IN"E>Ct}{!}'soA\~G-\:2X`Pc|@4 reCpnqTU?æ<{&L7`K_h)C.qd`*(l9*FfM6):Dz'3|55Ch eH%‹VT i"\i(4"6F0Җ*$;'j'#d8%J\t(cRǼ;`#ظv) d! "3XOuTgRZ`^Dok l&>Lgl} C6Z(|6I.|FDWGHіaWLri8 Zgϴ2*RGC{ҢԈGBe8h 2tkTkcdDVX0PUyw pdLM{bTǵ%@+{tbAdlAa3͜`EO,hiG^=B=ijbB0iVbDkEi|CI8,jG&)IoڰZA|CW:IؕgQ~V7QSZk| Igpe A`HɊa19ap%4p!X%’X t2 Ev|Յ$lID úl9:6-zFuȡ#%,d8?ޯ%M_ب ‘4_냌D8 mNc"B~9B5DKcjy/-1JHAg. Ul)1*8]?܉F)URÀ_a^&RY%ؗƑHŇRrGb6aY{`PD!̜! !`l [ Y0q)ᦍ!$JzIdY4IX,MPTBde>x1:rxY<'$xvHGNN0)7"R!K@̏0*i›tdIy6Z0̒J:D~өCFTj REo{-&'BƏUct]kqb8;2?㰰p< RXDJlHaaH2YFX2JQK\Ҫnɫ0b`;l )am[$J~eIlfH@)MzI?&Q&=oUmx6)Rp8ɏ4R@ґpQApeE4M2]dDMrmSkBa[r` VүHJ38@Z< 0M "MVGMAXܰyU?@hC^GhJ +(DM!۴JX"pch({E=Tt%=F?AG!KҴ~tDQBK|uZ_I|q/?ԉ2G8h2UO|GgA-|!w~ܾ6KFt<7"f 5f\<D!0²(9Ѳj?G-HT ˉӕfd_9`|6?~ ɦ"άad$|::jxHMͭ7mD?H! M*e9.Kq_|ضaƯf:_L## "~MѨ0JsrӥqlR"CůUD OMT@J0:GڴeS-MqU3mThQ^6/ǒ)a3O!20М\kF6Eo.Mw5oF|B =X\":kȹm)"l,/OTVUUc[- ˗`T& ~۶h6}E* RJD*BFֺaNJ!Ga[`B-όx(WNZTj] AJxH#$N>G!R!- -dTJ ͱFr\;Sw\u A_b ě.D^K2 vT|\F##mȊʑBcIaPGDoІ%'A Mr(M%KVG*c.q@K0߶3Z!82I0"a[t5tt0F-43ηa:;hf,Ed"!r&c;oA`Ϯn ԙ~.pWk)T6O/湣̚b*#)E@ 3ic9Y9pz]7?'v?ͺ5cPו $; VG^:{rRFdҔ9!X3YKq4_ƓS.I%zBLN+gfjM}\܄K"*R|^HY'yusbw:@OgY)Ʋ%LS60ɄYhP+GeKtFERHiFD- C[չryLYԂ&%d0rJ=k ]j@ɚ0s~7"DmY1DƔGW&ɉ";ӝ˰slci!s|?D泺ޡTʢ1 RRJ#]ӳ X_B."ug0V'm\_Zw:x~2^COG y:^&qZhSڨ16c`#,MM6v,fgpḱ8|lٲsE+ZBTc~|F,Te+tuXFJ6AޣmXҊ_Yi\/z ig+T<@ot_[DWye\Z 9Ӭ;uGTԪ%ҙRǞK>Tr͕Ԫ%i *`7FuZR˒bzH\& }.X7@&Zm25[IJ%FWj:6Dz%.-yyI֋p@+i!S8ޱEm07 _}`i Ȥ#T(R F"k_9٫y{%][ɉik'y;LRQ6d ;?onn k+] ȻBym Y4BE1+ogW>‹y{SOmS?o-9;hE-ل\H+r&FM Yq{'/~^&NLy7[˟zph/CB{*rp`$t/?MS[$L$dX˟|VvϻO=uK.SU/&|+P i~%{ݹ6'޲gyK cLLT hkK14*XfX/032B*P;퍻5oi/;W.[86F8zbPitdoe ƙs U5Fdvv?+kOmblT ogbђ:Ggk&SrH C95>Vip 9]ם`FLS\+B; lT򁟀r-׿a-,^ L}z3u,g*VO!O `x˻Ya3=5Tض@+%4WFcZesN5AjםgŚ~ITTH cZhm'v4ɽ*-tq1\nà%g 0K-_[L%8h4t(lY̋Z8UޮN&gg tu#qjN)xRqcFw"^-zq4A|CX]=Ƶu6?? v 9FS`[Vܾ%#eszǶy;o7l暫/?<'qK7HؖQZ.PZ?d6!'$]YcW3j^JC8MIƒ }.GR84BJ,[$RH6b8 C`>4eKHu۴2UJZi<6RJ, ^ON2ʝ,{fMfſ;=,|7'S6yrkg^]oWL З.)-zeDҮ9㷿v3#}?ҟ[i۵BbҗvqfȑB ڲ,Y+wBG?{K=qAhsr'$aWw\r!޺TCk:VC3 -؋Q) %ߨRF 1 !4~`xWZ!- ˊsTl!ر8zҩgtl Ƕ0EZb1%w!^e) ر,t_dXb$YIeEʆCS8* eaێQ*#r6 { ~?{N+z;zFzݳ|AFH)}mف ^t%?|fwǟ}?ScXUE+ž?{> ` ;-=_?:t[g^!NOu*W9~"I^*s3pc_6rލ|۶mSԺM}fРpz2 it\s>F3;5)`azes `r)_{[<ԟ筡ٯ{HOF", -obapRtDToh!2}Uѿt=2~bu$Vכ3+ =mT}T!ReWRO4EU'0w@g>XDת +݃f!vC_@)!k 3ƏٿmdHW_[ysvu FĊ]?`0i0(|4Հ/<o@ۿOs .YIi9ז>\V_k|a3P7ظ{lFq//LHg6I9?u ~sV.v Uܹyw%Dg ZEWff|ÈJib1W3 _q ߡX歿v7U;H;)i:ߌ)B+|ui ͨJ_b#hT?[ 'ퟰb5}4j^8q0@2_K\tх|?ɡGk7"WK*%KcخKY tmIva7{#>ş ڄYOo1FO:jRvLv7k?/ppxETݳ$:>{fF[lw}w[>\[L.- U|&\vH_zb ě<Nfm>-R]B(OnUmmulGfؼf9/ ="˱~󅝑t:G{Hz֏G{\]v{۶m;~u[g t6#43\f9/d"oK.4yqc ?ܿ(soNg%=&!x݊V ·٣D7ox:tD7m  w!a'%F\U=<#"Jxl~݅,bڻ(Ox7#3Ԍ}[h][m۶-^ɶ}|4e@ [GRE[}!mh5DxE}odxţƶ|ѭ[H}|^I$+ ؼj4cGqSKE];oٔ{>N˩޶O]e{۶%On׵e>H&Dyqo6s9L /{=$Ҕe'y@pwۍrjtmnyoe#LDҸ҈sj?{W]I#T,˥'ǟkƧkw*گhۋ۞ٶ6Y')(DZqQ6MH$pC[nn``FFXY8"b$o$:W06Џŷ% Z)F^KYΟMe9^^HRifM>9hq=VU%GNg^~'ÛXck_%Q i|:q{@UEEH7I"ع[o_RXw"9KE:& ' ;v$s_]r;pMfM:dyN`X)Gm}$~Q3>  H~tWTFAop0_)EziK$I&uGގ#OjJK*Ehp3{u~Fc'Gx0F6}SV=4f Gr?l#HH&ͷscCd*CR%ݳdd"ϑC_=S Gst J넍G>#yK"+?ǟSGgc̛i_-FbAzԺ {9rbROJ]3#%6J2;V.[suƯB4r48bYWD h>ceQ941kB$IML1Wmx+>z-@Ҷpݩ񿽱3X>yEE#hԱW^j/%sl|ٚuy֟x̶fwE$gh M]-u脵(% CV^z ]r TCcS>s۷ a&Z6k^{(=DGB7B=q&#*Qc[@ |K$M3;s}1<,>_JEE< pQJ֭OO&X`D,#U43N"c T#/q.^(CDcT 8D0jz9E+1:֭OPX'2[= Z4dPZGR(,L pVXXB8,h.^6L&aYOTpgD2ɦ>E*d+ %aKNrȷM_8?2L&e+ot3Б%LiY5[LM[%Q^ Sn9x׵_ Z$\|%t5Yk3$R).X>pAtvȫY-)`iWLY;6WvD*<:v179jŖFϝjk|9aS[+; EHg3"eVvLذ0$ d{9r츖Dٔg ¸lR)Ghye3Vi#Lq/:J+ቒv,-TxOyvS9gw̑J&ٸWNSH<*FEIG(5sj';T6/'I3نbI$\bS>|;'fmYQV [hT[zIiоMcYs"}{aFG4E)MH3_:OeH~۟~ ?ظwz4„VO ]蝻5Uc~} ׵Ek@.eYT wSD}o{3{v]Jz4m6uQ)[ 䚫߀1_z12 Fskil3svvx c /21_xQ?}%?W]6O>s5wowג#F /P)?J_Wf3 c=/sWK@z|rfqa&ԕ}`dp\6TԞ#L*lei-),B+iNFY-l~g'# !O=D#p2F[FHO=TʈOs,m4iZ\1[fX>8Q-\(s%FXRZ('y?+53p?W >O9dgY๮e@ iTu]mۆ1F&0tN5B;*FXDaqUl_']~! 8}wi7ERK˲B^ p;PkL)?xS 9.~eƜWF79G<ycx[ߢZaZj۶B^߲k[Iv\Mt^M L,RJWCr/[lawꪫpxF4_c_)hkv&l[ޤf2[,lÁ*1A6Nx.̱q>L2l+ļm!ԫ՛ <Æ=U?CG.MKv]f~AdQlm#&Ok6u7yǫ\4t"?07;Nj⡴4t*MFH\Ζk/)#ə'hϵI'=$;ozL]V.(/m|C/pow;A rX2"hmMhot ܆cUc'G6 [k*fJ 4'G4+& 8VIwMpQ$aǫ\8M.&HLzLN4"/0J% 4B%Ufש+'\OTevvP(ل&ZS]{NnlcU/&HISӼxx %L]’} _}C)e,:"8zhseE8T]@t2ANeXAƏ;r"ߵ0_|nd{Z =zFg*R;^D"Q뮻w߽7FvsUđÇoW g#&Zo9ğa_M'`W߹0 _U2 Çy\Opm.ʴXZ/u3s.VÁa/xm.0RANƣͰs/]r%[2 N/lA^ݮϒI"_yݛf18 c/Oε?"{<}lAu1t5,O=k^K‰*THu߆_f?g/odyg=wr-g}3\bYVeY)Dv4A(QMQT~-7~H_ch1=:eX<!2A*T5 ?_( U}c_d;v%4-kT- d/*կ֛8>k_jv߫}Ea8jG5ҿd|}|{ɖ۶8ū$ Q"ǃX.z߹l#^MY68x9_fr] Dkm֚0 V+axėhW&Co?fGĨaϳq{5(5`' ^Aucefʉ?z_/-Ȼ>%~|N|獩?d52ҕ `"* Y_4 0vWIG_ ݻ_.c!׾vfZdb+Ѡֳ~a?*o8gܘX^'3| 7ƳS'Cj/Fձo~W/e}~mqˮ2F,wA'[IG1N|X9=L|ߦ?>ձ}Nf?3 vwIG_ j*/k?suwޯ],V+$)2.x4M;,M^k~z8 >"u"7( #MP/Y'*)Ac؎sc>G=_OnkX]'ts4Qij)+vN̍[k=>޷vѵ nձWZa ձS>6|zڗEs|':\ɶeg跈UӨȭN@Tv+|M_h%9DPz؎}5r󑯜_lٲŻ[vM_ٌ11F'GkX(u6}aG?Wrϲ WAjEm!_Rڽk|;^_ͫ֌^ @)sut^[eƵ뎞nm7#\8Ji􁷼x}^c|_]fˆT¿ Œ{׽۟?o Cot^g{ߣ]mI^>"ZCFƲc1!$Bė5hm+1z@ &f~CotڿMpjj^+u|Wd몮EgQ'1ֈv_uZ)>^Qךq:6s]O-Qm6Kdsi))Qn%ggv/ӥI+dQ⍣?X ͣ3qosD&zu ͙]&ڤLf}^*ǿNG^Z?M\^Mvl.{N8R O2^:/IqŻ>K&y77_{!T+ !Ũh,γcp,!jq=MiDdW\5",Ǿ_&<}݂?x?u\t퍧N$_3;M"ۣI+{tWO}pikkKؖ}߄ah{aÖ3zR#1uж3Xh6ږ+䟺31[h:rGٞ7}rc[FC(~,Z жeE?oڊńղOhq#˱eX?No4Z<֞3jJٖ-40}{w{lX(ǦqlRJ c R,KbL|to.MSBF8eMϫ wwG}JvOYgE:߹r#T#E,$Q,K"I2XV 0o!K.Lط aOx5ϐmQӁ9RJ!HR-NaWfNc@)8X2&X ng'G? 1{^[{G\ T}̖BJ!-/Aj5[XnjE{ygOn{3KR-LbW?9ix= 9vG>{ )j.RZH%,>E?-2a0|KK,Ld/w߻ϰ!r^2z&jc%-!Ԋs`ptvGk'W["b^oB. C"Jj`BmĶ,d @~`vvvi۲e|-OOG lG{[Zk-Ҩ0KP!n-ˊF㺎=;@n[b?YNh6Z#T⟪߲BmR i4 !.߲%Fӗa>/mT>%}5P vq ⥺RX'0R8ڴVQ6tv~"EJcYBkcO-@)es{+'^Ie/B)-) MdPQل@H p$Jk{LhupP1ų=|-)9j.]C!_oS3?[[Q:R@:'J$PAR.|иD1U-HqgK=gGȴu}ZUjA^^xe\BQ^-ı\l/GMDd=Q=N\T?>Dq'?^50m0@:FHM/cn=Q9vTѬ?/|>8L>_c5,B-u&Ө cX:u20xDц sﶍUũOJY^}tZ}47w )ƅGò*5 !Nsq_XƀR' 9۟{[l'.^8׭~> xgX:RSzibٖq]/ZXXػo}i>w|t!D_/d~˲\v -sO|)N$raa3oևeE#Ӝ,"V-D|T֧'X(w}}] 7mݱ~qK)\"92 L*Eu/yq2Q%kqQ3'~|s t}- ]XiZ4h1(cKL?/4?3iٳm-Oy@ rZ*N:1pn~F:ͷI$2AFJ2PT+s YhqJՑhd~at,h eoZU2?>_-}w=Rv'4h)(%Rŧim A ʱOhtjm͟§6X٨m 30:y5_jk]A2! [?)U7by׉OoKgiTR#[3L' ~hʅ9_-^ow[:nH LUhɩM3=>u/ۯ#Y(!*/_A`酹_}Ñ'ѽ:&N'_rղ93'.?>cjOw]ggI<[ `cCS-fy͇(qJ'5ӿ<6gHH Z(-2K 2YcI+$8e1hhTdQ[j߾ }AP\x_ˊذQ=%lC:mb7Po|5Pe̶}v_i܁KOn ծ,SdS6R/akzy_]ض<{n-|c[-MGWr/<ߘTI& FFȐr}|^R{~ŚDͩ޵ٲ"†#++/0/J:e' 5պ"lzbҜ8?xϮ?=W<=o׏_kZ+I#5Z .Cֶį'v?=D8+n 1~o/nsթ_5]o?]e O,yGW_KX!8X4f%Q!{^qbNwv7qP-]ONZ\Z)mh4oF {}7*~;v;_ CTbiQ !P~I'RB5؎sLrl"5-۲B7x$I`tC)\J2ut:zM7P1F>)|زu^+GGiE+ ֹt\#LWo}Ii;84`[_4n"eۦ#CB[l7ngOO&,f@G4B8"Έ0BPḮeV yS}>Ĥ㺔5tąNBb6BmH%k3Y#= lbMUG§#D.pp\Kt'e2ceCژ( QbfZ(p,WjPڰnս]ϗZeh_$;6w޻'xmO/_6lд^SDZqyfm\Y|y?}#p62EwYް#Re ,B|ӌI$M77bW|o}>kڦ~'/E Z=N9J6c R)ڌ>!oP.}9N/kAmL/O~[I8dm__]-wݵMOv=ȞIް:-FSU!4\Z`r}]_/=tiJ.XهkH!wbtkaˏ,yk ݀ق\g^'?T4 ?upIr'56lF@  |? 5rl 379tMf^;h6]#ēܶ|Kd执5qI븮ax0+'&Tj0287$gw6ig>S_z}?NipgXXl@`y>ɿ>S_Rvmf O.MG wHy.B\rBIћk牽U5] DaaJ_ޫk{ fg8Ν7ONG`hđMWkן{wwUa|s3{Nwkk;sbb[>gHGpϱ}Q|U _љ TaVtpH?%%;&)7C24]mt 7yh߫ߺu+_ܧ>3):o 5*s^R=~W>X7 L)︬*2?B*au!r&6MuX XAN]w^.JJ jg#: 9lޮ3M[ lj"7X7?ȣ?CFPUƨn '@/eZZ(RU-(A+ g>#FEX./bڸh#;0a yi"jkk-)>|t }OUfOIW`lme)J`*#GaӦG][O5hiiC:~WRY.:~ WSD@uP%jE`TG)EZ=ym?vX2w7mC4` P<@e.0 {˟[ZZDuRo)__cwD"wFsa*a#}E$\7X}w---0,}>p/;z;yVx*]]3{?Q~R}H}c*o^, B>*b^ ؁uoaϿUWKK;vV\)S* y%%=w}<R)0RdR{>rWJHsIDAT%% y`A+msT{z4ʑs)lDym{@QW#cֲ(%C vO_/59Rꦦ M!W fKY|0>%Z0}>z:ԑ:Uv`H/J p!!ALVFfc#1lxPQx֠V!4eϩH:2(a.i\EHD-2PoqU1C Bc \ Xa(h%KAR J[LR WV͕zH1NE]BKچ24&t(TplӐ:q0Hu;z|@)F)x(y]~ А-RR@*yv)]iD< 0ՉbaPEPꁠϡl!J%q| Au)@J0 s$. Aa)b$FmAB ? |>z5Qz[D(|P&t 8"\/]DII,a=XI̓]}Sa 5YળSgϞ ƭ?( [Sڋ_ճta3Q@vHV)g7]|ܹ8C'`\rda*L Fp 1P(JNٌcg/HņO\v M46XpGN-i+0 T+UzPQ MQ%ӡNǎì#&_ts{؇x"bQa>'O3+Znm(ePaL_7!qSh9`?-,v0gjUJu}R_[}g ]C.W/@3Mb6ڹ`PtaSZ PI:/5_q=1_jG\BWMA)ð Q\}4 i* jb$]eL[5"F($iY=?S\xD @2 cc,tLXMOMo>t!sWMIsfMc\e"8ɠJ9Z Ve3oG=/΀|Qaݼ ^Q_!\fhB *nsjM{YW0uRzv8w Bfi[`Y:@pq\bu=gjPr-z(K$q5B y^.b|sA((hT9KyWsݤgPDG+c{bZgm^ehh~(NEqչC( np _ԱA A)A%.0u+-׭=?t(.VVک/'N!#t=;1wi63>u)3~ oJ;^o={~7V7w֥i YN]c|nԑZcA4T.wʂ'L9 x{ߛ;W[kTG(T Kf_ $19#/uW_f޼_ysC @V{4![)LD, Y+IJ֌2g)'v!ZDb rL7ryi4]Ae XU/|;Lx땚wVdSl^JYTJ z>PB" z)r B0bfN h5ƃc: . aJP@@=Mn/DDXFtM/"Q7 ySSo~Pz9@ S#PÉ0H$P% ]m;_;ZA9ŋKm#Oh5(昄 s ˠPRݕHNvw:J5I7IygO_ ,u /ߨT!j6\ƯZSJֱ|WĎk557zn_>YǮ{{. Ťzljtc-h?^,Mmܰ|O~#[G򗶴H淯޼y6&nÏwֵxq{1&3}];2T\{2ڧ>c(^stkkk+u]oKRwwcG_ى7ub Uy큯Vδo|KKq_ߒ @*>b"6Jhb κ\+Ru3Fl>=|2b0o7AyĞ ^ߴ.WыUvC)+ ."\;<.2bvSBK[N=D|\eV'|s(}K)mtuPh ?}؈% ~ȫ TPг +7 fMz",Jtbm(v?^巶AHʀ.d 98e- cT58 dUKvw['ֵumC=Eӈ>V-x3y#߼WnqwuUJ:B(K˶eP(0`La_||ìC3<kL Щ @ Aw&WoC5R]x.юL.Q딧7]"͐JNw`p ۢߧu4<:xn$cB/M<?O/Oy*HW+Khݕ^Y 5[qOƟWlďZ;, cT/~ԩSqqS?%K-o~ٮ{OĚ}x5x㭍PJ*]" ڰ{6_<ȭs_LǢ@0eA;4@~چv7]b\˭ݽ0ir ^< s=bQ)7} D|a㝹bJc*%y`Cv[w!J-`Kv¸ 8IOPwݘvP%>y7| |hJ@]7ח/n>}L<;lS y$>b!Buqt(/O[-m2!D V!R)LAgP`kWx2tԥП+.ea]}Ȇ:05)Tf*]=.boWVnmF5OnVm> {w]E9S2,̓\bҥA":_}ݞv 9r1N>f4e*ק.}jJwqE)L|[6mRduU\Ucضm?tP+yo~%:ѫ/w+>@ιg7hEOu;ǔxuEB9*0p/^ӝSTˢEya+2eS)C\!A X{ދ<NjZm^5ν7-k><%>!ͼ<*OE%u!SQ[El9F' F~7r 9~R(N]D e ^SmۼJ)1TU֍00fL%u{hO9$wvs[b9Aw!G(eQteDCm RQ;z"̪Yz==Nϴ1Bl)* ?2 =(Hjx~ϣ}}OeEr4bt, 0DC:!xBBrR^RՋ];|f &Pw ȸڈA5j7P,3'uBA)!ԯKVjz-K*)Y6_ش?*QzBMW[7VmB.Ws&*=W2ȓk|$ҥ_nn$§\@4bb6PcTKdѰx“ɶnhߠcSƣ K42$_!"WQĮ=B: 1"7̇߮K !@~˾uHSh׺~5)CĈ!5 _Ț?M:H`A\py%Q1u$$RP_z;M}e $j Us[qчT:0#wR=T:m6yO" fmdO5{9i< a[!8{sR(ݟ@GMݾW~D G4Mћ[> }:V` (\Vۺמ^w>qw$m\zԗv|u3YWo/-t @"c?ۺ^glڮݑ|UW?jueLA D(=Wf3V3{GvfKBo}~e [S dɒ): P5Ӡ6dCwh}vߧ8sW;IʪW$ծ ]:_@p`(1T']9=-ޮWV} *0ڵG|,ѢEE8yCUKcq틧lGemp #i ŏRð&x @ xkW]|'̀b@9OI# o}_JՆ?4r@I ]<ʾxUƶcN8E^vg5o?== :::idB_JWa@nWv=x̙KUQƶO'+Wޯ͚y%W<&b6 `GgOW0Y7јvi><qㆋ~ׯϻaDnb F$ g[z/bR+#Hd³%>SN9{(CWWo.:iAL($:aD _REO;#j;+nH CwaS >pҿxٳLP/oj*t¸5w$qP 6n*y0(t?{l V@u"h O}yyӦ},nB<&6h@mYIM"bct fQ !%Q N L?/ya6,Z,duq79j#2L2Ŋk/W0# صNtǻ緔/ܶhmڷca*V2,";W\{}q׺-7)%*zџ=q =^:ȋAgw矿ӗїu(C ?b֢E-Wwc,V BzP,O@;bc?kmȊ: a_՟.?7wQR-oh?ұ ۲R§A2Aro|uv>|N#766j_T]t,q>6c²bw>e$v`@hnʓ sF@\Hm c':SU˱x!vua`PA2m_8z!d{755jVcV̸r'&}BͪCʪi[!ǠE.߆Ed* N;G-V!}zsUeu &6ƌDD *pbW{mBTy^'gZ';>|MJ6e\ ЋI6"۔ NȗO.?Jò*vG!RQ@*` B狾[/Ѻ *E*%Kknx|Z|hs\ `1@]Ǝ;n%)fr|vH~717Wu1r>Ux~{doOZUU1G1ء.gWe?31҃ӁА)Zw?S7}Q'b; fŖvuu =wXחKSz߫;w}ӦM;!K%{fsNJܷv9Q̽'7OcoӸ`>TVu3 K-h1?XC?ܛ]mr ϰ:*kT=)o~ֽO4턲]ǂl6h?]t)wRtQ+sM y3w!ڍN /홎LBa D\/OL*B\o;::\ب5o\8q#9H6%[nAyw)?lM?c@] \?>?nRCן?N55}bbm*4)jBkiwoN}f驭o~{ۯ–kv`;SM͞Ī*K+H IzGN*[_XS>̝o~{u`oHW1vf);U9IsC6aL ]B bCY;_.[t[d{H=+(Nk#%JZ`ls~W{Wy_z~kd g_q3ycJW9 [ J ƸSrh AZ=cWpw^}k0f;tUbJ[ \OmmA}_oPvՠ̿ʙ g6T-{lKeSi" }Em0} l?ߍB[7C{=ߜwߘ9+Tܸ3ʙV剅O~,iXΆ"*3](r}k];yC漲w6g7-kԚnʩfč(OAW`&QHS}3.vX:o_޸`}?£k*f9|ej"#-,Gl B+S& \{ɾɔֿ*p1/U6UQK!x0&08V`o7\޻^z~7>{~A46AkmG5VnyDLkxM9X|sx2&F5؅޻k?3&Խԁ['9҈8UȜ/ysf-_c@gyސrԤl߱Lsuc]4nhWN\96]L^jk=EZCØ3O^s Νg91#Fmv&dȪMy$6zXNjNŖ8vquol>{ڏ'sm|ƪ ~z#+ϫ0*UÄS>;IPX$b)\.Ӏ1iaQkBujI7|o}C,}OˣΨIW8*i2bo#4*@hHJuHT07kPO?#XL[Kw7)PBu-$pgF:g -;8tb펑Q~=G|9mnmÓO=uj9_VVKX6UշG=x/0 ]bTݗ6"y[HF /Xuߗ/_N[[[Gmx,\9,ӄECLf٥ZxOs^e)LLmY:%=ϯ!9mZ>f}q=5o1Pb8{Ehm\ 6W"GMDLJ  H)/K/OT\/ 8( plGn 47C^ؑQ3v-)]%=H86uSa)\n&dy;1*sjxb(!?_:7v8XJ bēeL\%52n/.2PU G&GzT=3=F.ҕK2Yw5w`9mƐM9&UT].US|~6.NcդTElAq`  ~)v<ڐ+2᜽5<>!"^MKQWYwHʨ -OJĒgs^ quC]ï*Jp"@dZŰ؊#0qpNr!8sJD"#xsj'2c85> 0UG71ʑV'FP% T E*G"fXwR['DŽv3Q[q|'e#/`S 5 q [(e `x LRLf]Tc>xcF}D0PQ?Brx=9E -nynD->IJkOL=mDjēՉpEIpšO"^cUmEɁ7\>T{C/8&୕L0&Pc[()%.93@~{[2}RlZ5mVm(7,@:k[Բ&ڼں.KtYT\wJ^5/F2EV:u-wݶR.fWVs~j-_񔖖^lY4"zkjZ**ʙs-*ͅq"$o\t ҨB*!6r=ǪRH`3Z~ҺQ[Zj}*>W8Xq@XrT<2H5WaWOxַnjlhY?!BbjTV0>(S'UB+F; '\Z Zm^~YeTA*x{c?z s΅R WݻFy{uB*f9,?J:w4 U~fCE1B1 T]- @Vg|47C~2 Xnn (H黫c 㾐 mH,|A9lJ @G DI޳U@)1 |'?wJhI]Ij۞^i\J}R>wb)!$\ՇXA`R 30<##kvł/0Ú|gH2C]-???%>AK -ve?Igzx !uS殘a[&^@Q0J>r DʒվYE`֦D璇eqΔQ#@jU q0~n& SxQHҵTD,d Cg 12:B+#t5 9.Q>r T!@,A_OITb?xEfRJ'Ps(J!lC"НJ²|Ͽ`HIŝĊ%u"}V|tı ΅Q={_}>5[s05oBɤD0DbM]|^ 4JPeFy:({$V^2D |8h ,PJ $ C}RA~s΅a? uA r J)]ud.,X@FvD,+s= bҕr脁S$!D q BՀAl( `EOi$(5 ih$b Lm#BLjO=.Cs_m$P$%@9`Ac[, 9c @/hXJ,:uB"֐>@j*=+!Ph2k 4c\I((_r?TG(át, 9#Т؏ҝH4z>$W@P @#$rA!Pý|9?1DmPSFtj|Bc_}0t~@'5hplPW/)k* 3B TUS8AR)KPh{D24BeBMA @ jh2[tJn,F0iCR]$p@(]!e@SplJ9gf*Z tAr2 'BChC@~ݶ'r!8(Ɓ|1s@Bu(M"P64(3UVV9>8#研Ӓ 5 \8N4Vj]ק"}٫(N)80h߲_BRS7Rc ,~ݎME CBW\TbLq a ji |8k 8}?%P~[nE?L͛!#PA4Y}8MCy G}ڄb%Y KgMxBqfh"{VzE%|\u3ංM E@:u`I@g j eBp"oW%PIGt+jm(|nJI C@P\JR7孢{bjz*q+JNQ&;+NSr'X-8?hІ@`G9tǠB?<Փ.?}G@J~|?>@JNJL=J*дC}GKSl>XPB !j D٣繈DH!f @0% DAr,fs`ЋI(l@C  DQj=x-PCdY 3fJתx_"܌H{E!_V,ٟˁ&ۏC9m09lDQT#f\G3>8!@]$C(T00t7+TDCDqf[&"ĔA!{s185Ѩ9)-& D1h]>N7*˅0m)@!cEƘF?x| 1uWlۂfP)(5LJ %c@Ȥl6w3Ͽ7^}*3%> eIYHmV_*_mL-`hQWss2A,aV$"0X4rqGGcOI屺DKU*qc`BTD)$:;mÎ.i屸eSN 'R% |M޹geޒ;V_ٱQ5eT}iPP%I Q,INq1go^=pY-f|ȅFߟNĮ:֐CD)Ñ} 6q+ssӅJ<"@y"x$m@"$85][+uDc^@t݈X}{Gk#b7XE̙3u'm#vehhJ!iJQ $S#3O:2eqcX93t:B Q{f0*uDD7&/ p/˨&n9^ACn~C0Tu"u]'vc/<眷e!0e_w…6wi_8{ΎIǥ}BJ:aBHiXe}C˖-.\LmSwʊGBB%Ca; J)N=}ځ| ꊊƊeTJRhR J_ !Wtwd|]*wj*l* Q寔T R0"iƧ;:܅7ݽjE⏸1#TE_-G"QJA2raLc޶{USȾ%SP P†Juۺ k?u$G"KQy4FH)RK)`!W(N;xP &z6]~@*hKRRH<^޴+`P8K7@)a0̹R{߮cv af>><+*`%R)J)#]}ʯ|Nʰ,8ec!@(t2^)Uz82:snۉMEܰ~*L%7M3,U.%/B]>%XQW{Gԉ\4-R(eÑnPPR).RBr!Q,+RŵiS<)PZ,s< 21l1"@"Uww{\9 .]v:B6I[d֗|䣎ZiE07(c+(jFBfP۸#~l\x19ߚ]f\ץajJ)"KJ+m"ajAcL2W$ct]5N&d*ej+?ؗ{oXQ !pCGZoil9XsNk"J +'⑔c_@-ZUǶcRHaHibTo!Ҥ"Hh40ur!JJ JJ-2PJ%BbLlz3(LR2.b B*4$vH"҄,b7P}ÿ17Gq! 5jxCBΩ&XLP>F?0f]KWH&$R ! u!xNԵ?NF]G@pnH%YjEWkx,b_}¸/=Cuh,aRr\BX!G"k+*f4_,v#*YE!7TJN>8wTa^~---|bS#v!ׄLAJڗr=? J)raa&ls޼#? Ra]<"QByIJr⽐\R0qX @6ݶ;BӴs !!aBАs# yiڂCx"Umð,ˎƔD`;DcIJm8ňaZ%SxMmŋ/SN=777sBLUV\Męz4P ;!e;!hX"cz,ԒBҥK@єR?8SL}ߗCby>-PJAVQaE ]hG|˗-~SS}rG2Sb ) / -FBi]Bx) *+iL ]xy9t/Z"94CJ)FԔ1%\?rN A)%݃ԙc֑: pm4t)ȔB BIJ8E:25-GTdiH+z RTKPH!?D JIڟsA4=~ pmnROT RERB/(0Fp +?#Q6((E4vc/IN8T# j#*=4(% :#t`pp_QQV nK:00??~tENHA)VR}8&eYG䲃ce_!8cD+P}<{x"@ȹd{!).=y@/P~,c+ûElX1s&êUO`ZX>u7|(g(%8"(`__N#9L֭[w vJ7[c-"/ƌ=CSsBC+gRf1;v߇9CdJdl$9OSΛ p!{7tԡk ϼVY^X4` kuҤrx\ Bo0Kg(=6OsVWOa-gO iC U6<QCyo){Ԍ:kfΜV@ZMcI@BBE8~c5FhmISDi;e& _p 21i4. "ku I)!BaV2=((%@>i6SUڒ% $pH:*ˆQCA!@*Ick0qt(#RSgWa]MdD+onn&8x!iD @ Jw"iarM`R£ޝc0PBhjVtR B)` qD}Y 0J̛4aKgo>!eMMM0̵KԎaY& r s@hh%<7\v d+(Ŕui؟ϨDl!nŽz. GXeDl"h<()BAtIe^/,J0ᄑRm\HFtY (P{- eJJ)0b7vRC@B ( EB-jDYDM5C 1 `&4C755Ѩ"TA{>`3H>T"“a´ L$ 7^SMMM&WW)E[_y]7Ldryp/yaA eL'h(?^)`;1Ghߣa%K呂|97 :,(E d‹-e--?|XpZ ƶ2n*+RRBU0qRN?{b9" >O% h~|'HC#Dp4HsEeR 'QJ ƍ@&碯?T  9vG<#* 8Pd"ҲT?^UƦ8UqNPZ{Ď>5q=PD_ :%N0/"(9056tAݙ1T'h%n;JQa~?p1c|D8d0=z |#lAh}}O3( G"S'B ^vvcǞ>4}RQocc(UJ )HWLiC0^F54²0>heeGU14ԖCƍDEYB( 7̩#Q;@b? QQB( U1#R640A: %$7΅8 IGB(eGc1$J!nH:&F'P"D)xA\c*SZ P8K!O뜵lpԔADl T}Vn!)UH7r}79+X @RE (}Cd3-#F|1ז&ris"P~z+t3IlR2do9 w %טM9|, @H WtֽY7*`GRqJ VE,_ .wuWG8{$l޺ 2{8uplO-߈p08jTs5>ҲoҶLC*ů~:q\yB>`j,>x1|~[ӮxC}Q0f0 ^Di)MqDmd{`Y1݈ r9E76aG7 -g"+ݎLEey 3*_Kw?؅ށ<1S'qLtuyNɜrCn/ئ/2 F,r@]1  onϡQ0ΆS!꬯4|ԮK=d'PRaŶ]u LYx(ζ=T#S&:t !o4MC_fRrB{XA ]} orp PRaz=} == Oϡu wO' ]ށ|JB4X:u3#k+7흽gNœVXeXB =1Ofxn}Q>&%18 h2T---y7>aX{sغA!@O=9L\Mۻc@=EM?vG}СTiwp%6t0uvw·ʆ1"]l/xwOocI)d2^pL@)A@zsLY}rp[${B>}IZ8y p&W1 bt}'fy<=C~4-;AQO/H$gUߛO;n9sw޹ODO|7<F{W?&1?(q43G?hZ(Se8nG+,~<0@{^TE"S-PQJ"lnzswQwwRں}_ SGǥD]E`5e}t1vb+^]~㮖1v쬸Rj8d|~!6xۛcaJ84Zlîm!jb~K_1k%[mpTNCʓ6Vߎ|){˞ƟyGRzwM/1 wY ]t Q؉w?1iRE"{߽ص]xXzJ) >R w" O=ΟO=0<#!|ԏ.tB$P-Ʊ&Cp܌ATq$!;K3AA)hR{wwAiYd#q̴ؼuFզ@u9tKGҰc1o:kI,3fU_}ņTy+P455O~;?.U%Jc(aVlFݛcHP:HDp%NTILj~s{QKLeq2xpb0J!؝1rd1#/ԕ%š>Mw h&#(st4 D* 7(.1BԈ$y_^[|)3?[;;gI E(!5CcH8jSqxa(33 CcRbluCitv#GWU0P!]&aF @ JP#9đSs MxAw4Eg*Cu]0DM T SUHL趁0 Y:LkX[軼ΏRy\HFiC:^tv%`< ]Qˢ Be b<$`(%"붅 Umu ,mYf?3P3!`T%tCh(,eG-le,`3:LҖ^_߲4!:0UU.4Ja*jl ݙ<ʓMRH/7Ϳv6oZ#ZGRQVnrJI%zG_WT떡{E-K^dK~Y/ӾPogucD{GT #UxV.+A[90at;i&xRD9s=ȱX<-hq 0 cwGII'*].d; ;_oA̍_Wތ|~;351p[28kHQThG&P <;0-!i;q ##O:Ν555ט-E B %Vca"TQ{Ou켥DtI'p|öDW97 e(PZ Bh"5'̝8lav,FHt (rJ[!I,yxJ!BJPOZ^R0!=g#Eͯ o|{$!3!(0ơ1,c3'&<[kSYՃ{3g |Ϫ>s4`jYĝҮ-`h=D _wnh?$u%7\;Qhظ+B1@0TPCP!,OV4574g\nOY&i; n)ddڤXmpl@,̈1#*_oeia䨆/D̙:Vj;+_[2wtssK<)8\HkSw04Dyy7}B0! tww}3Ng|$r H:W;V4݂ԑڸc1bѧî'\G24 A5F ,CÅG 8yR#N9f yX̛7}+,?-(sIұq1Ӡ1|C.m!8gT0FP<r_Xp!4_-kr;8?rD 3fӺ{RtۻXkF֏^~w>rVY^VDz-DXy3 r᱓ {]ç8e<\| }W3JQ?߼3sn@GYU{}gLzHP%4 D bAafXxNJD@:(JBIBz$rLH |5\:^K\/ׇj>Z5߸!+B&N= 046|\Ǚ1}:-?\v{k玧T|i+9P\q6tM _p.|shF4$[G33ۦO珿Cg-Pc]Ɍp֟T(ZXVsmTNq_E!1uɴij>xxϚ] >ڐnLY`)>ˮOFKMH(:"a,ֈZ+O.b[oz U@A0o x);_7pyxY)aq\=Cƺ9_'ذa2lߓP_ 2PD9Wt\v6±0q]p]tC7jΗn~Ķ47&W@52yd$s: g.C7PvD'ӄ0[_J)8x,`)(l8I|}o .L+:Ϯ~o=ycd")DC:O=p5ք8:g(:z[Zs3{GsqA${w~/34taB\WtD8j p3xLgu60i.}ֳ3%} O<{AWO58:q/"-C@(|OLiWn{Kvܦ\syۖ-{H*DWWk4<)g<(-&8 4MKqJ 64W\zbmNcݭ_g-$?)FMwܽ=251]tmnspҭg28vc._|Ԕ@$g.TJy'r'\ֈuNYm3P>t 9F:B9uNr"˧#!˘pDQPEm!} 0 B8ʇ)1\]+XGJVd`euإ`AI H9Tl/%RJ9MneCΗ%#YV NU9#=Bv>)=Ooi󶝹`gܓeTp|IR*@$hR 7\OIh3{ڼ/<<89R U$UCK ]` .َ ]\=:vmoda]?1ݑO?)l+ʕbldWsÏ iR2шSEtpH =O&;yޗ+|~D]=:: pptSJp$̩}9\W:د6~ WLvA8CaA#D)[pv6pMxrV|_ډy s'0 ?CcXz9| C8O][ŻC!SH)ES$R>~8F?`j-]|wO~Y% M`7/EDk6c!La"Ò%gGOHْiw)bWZA/(U|EscgH\+^W[']|a|LJ1}c)ՇO?[r2N[r6qᄐC}gndm[}M\ȥǞiƟ<_?k7W̑$+{^/rem{mL"z[C]xo<5mw%qbԟ~7V7/iPQ\_}o3Pf4ֶLdkq@guwC~bbbB㜁ڴed6COnĚwHT}ncr˶޻ACifc]KXC7>o qkB^sЗ* m(8L{r۹n ,X:}c=Su(4>/9NPіћQxf_ @)%8+9#Fxu|O}! -i{?OYH|H`mƖQ8xqw?NAIl>}_ioo;hQ^ړ* !3{Jb܅"\S?=zO\7UA1.7~m-Uv$Thh<30ÎI w?7w˻՟܏{6®{PvFXϷ9:g#(*#3+U[?;v? $$=Ghddl 37kw"=;* #D(Dݖ}}SY.cPǃb{%M0*c*I¾'|ePe;(>4+ʟwWDx趎q&%"@Cx E6Apσ 3Wgʕ} @g&5kcIrm׽ Ձ b>'`U9MџgwCg,yӒXa/"gͅF 2,5hmEM2!89J @: U1{ C"=I\0w8غ#xK(bpˬ'Eqj m,_?kp%Gw߾]`a~)H_i?qKhiLMpU+ |cX} ю[g_cEy<ۘ00i`nM\(<4?/>/~gV|çMر@>z( cY(D4'![C%'+!h-^r.?{vj? 0^+7U54Ts A WWA1u$z}[AHJ}o0Met-یt[3iK~yZ_ERA."w[5*Ŕ$"L ?xu+;Ko'g47X7/9VFlw􎋟ﯽs~SU~Ӫ;S}+;x_ \XB"EmS 8.&;MrdR`Ѧ2#W/4o;*l^S83=I͕nuwyR}B7)/ֿӳJl_d }qєL>X6e*)Q,]_uR=LJ-GU˗k=G =1[pQT2# 5[0Ob/'n5zd8wS8]n|wez8wėn;'0u7rD>\z|)3\BGVCɥϝJLalrw0\ bo|r7H#ܺxi -M8e~k r*`Kd:}X2aL=m7s?/} Fpa <3L,'!Wr/T%]pHziV>㎧{#(lZX2{Z#t`" Ŏu!فN㦗S_&寧q0r'w^qHtѶ~c, ^;c"c׿)v6U~h|3L?rFpIw٬?U} :eG"׶O?6 U\|Q4Fܱ54K; w`GcR8rJ|d4cX4ٲHqKx)̨0noľ#j(SYby״7󙑼U(2%#v 灥lɱ4I (v:Z kl/tpl$XlY&?;ΕL(Ӄ pS#(ퟟ[+wum_Tǻ5/sJ7kwЉ-N=m>+wˇz'-Ӻig| ] wݵλ*`$??)}Pߒ-3_9,Ȁ8 =WqZd\8eaqշOJA}~KD=K?f\|LH`,gCQ t1NW}]džG?b+Y0=õ  61К,xL,%Q X:ұoT|ho'QIπSX%10Y֞hw]w>z\d;Mҏ#Szȼ16fKb *yJo4\#\}ɮ5U!d81,W4;W#\/b/}A踠[ V\*&|['O;ȼyskgV+ܾ/66`h5o,; /B;vlmtd|u$xjӆ=CE…7|h뼈Mt&۽)c`l/ ɲwP/omVOkm|ja?.xSOL9vh Tgb׈F{ZJlۖ-42ySkOmݽt;}8oxl)9e\Γp_Z.s v !"oƭ;;0^5ry(g+h`S&O9I'ͥm֧5$i w c@EϥlO&oxu5uO Oڻ0ѽB䭏_P.^t}7/mWJpbWf_O?ϼo˖m)%^{;B|_/ϛQ;w3}jFM4:}:sG@-mˮ=Ζݵ W맧 g1wRSG\e}9O;pɇvIM}ͷs2#z/e6~~L㳗%.|>-bO/two[?+kNZZ 3L0鰻Ѽ53+.^綏6=_w[o?m2W/եW+[>joזdUsC/ս DgGz^p˕<{g6_tƩ"?u}5޿{-Hz -uٸ_3seyqߜ'+ۂ6TO$_WnPSˇ=9ּ`p㡑˫؄۞(qIϱ6\ 'zB O\{I\8{v>o%)G!\ԶoanWm|pn䟻m't\vQ8ڴqg? #m8yzK .Yp2~:g]X֌oޜ硤RoTIJP8B&v(Qiyvh{}ϜM%"VuUVWW%0:kA[ e#>eb:sd6f@o_zm55 ^n{ H,Ѝ=wrEL`F `l ^kkF["L\;Y| 3 1ں}-'CuAݮ{`"`Vk Y&i,+ %g$#aĻv|K;-[C9:}hrZϽ[-VRb3}9Yٛ`@<Fk}hepqZc*,\6f]ye~q餽7OЎJ@(j;'%sCHDh`1+>DsnG}c1 %QKd&*],< _oʕ0x,@@ʆ3*X.dĢw~s/YbKGO)jQL9`+VFЊՐYPq #+uIYun릤c3ˆe[}- ^Oڧ֪Q=M4@X0BFlp>FH9S߿|E<_HtU|8ÆڭLc3`X02B! cD1jgsV]/RP`_5вռ>>Imq> `K"bwk@iD.?c~tV5Q'6^Jg\ :<<{o]+D\`/}tabka6QeVu}s*Ѷ%}g wI>ud><[Gj6ې*NcA]#R# *<%ԴwO/w;pZWPM(x% Uy|~yLkfW޿,)ҡ1'Uf{>l4ȭړeb52Qsr5l%i}{J5?}tǪҷsp-imjTc Cv kX63gt)'@w" ̨ZE#غE 6jj^s s o{mSvJ8ywf}{h/'mO_5C13ZCmbe7 WG, hiC[K=Zj(V̱fgFC:f.hȮvww[tn1yɫfM3 ul(U]*|8en@scfԣ& e0JEcׄkAUbO6U7 U}evkͬAÀ7i'RR${rQ ~.7rVĪU:RfY/d:\FqT*; i-jgN^3MaGdr//_@:ω7u 5u!(5՗~<ڻ co^үbeџ9-.r`mu@.#+`h~r3|_&tV`>(3I_vF!grHdn,wuA5 [WGLs9,c~08sA> uQM:MekTao:w)?-OCՆ.'au0dBfd:e" lV"v˗gOَ5ͷv73`8n}S} җgsXn  ղ}XTlKM{9MxiFx㯐LF)n$Ը }Q#u/hZm`V\ `cr_aZgaK&a3׾g _#3i ` &+T);,CT r3yT>T| Py0]`G&!] °B$ Ő>2,~_xU7@dThʁpsXs( B| f ˠ)%$N84"*+:ʅ`.KbC[*uuZe 逕 $)#-IJ>):Fa۰-=).&+Hs"^ :LSb x'1 w 0hILL>sp}|xk> N64UY Y$9<`xш%G'KP8v/ ) Ɣh H=5O^PmD^ds PR; iOcφbͦ~ŭxac߿bYQ>A')| ϮGxOgm 5; !E,ChPbbh=0 Wbl_Ai A2 l!|]@ʃi DB0%>?/ | H=\uify5|E_1( c9 ׃saB:8t3!@ $@cHpp8SҊ4H4.A$EAp/8W`)H෧ O %{5"@CH5&LC0|_XJX~pAq) иC! +rVƃ򅮔D>G_^yws41"M#~CJAJz_cc@Vxn Z8l Ϫus>n0'I~rҿ83258` :|uD hc >Ac]_GϠ@ H@OANHh= 9 ziy ޅx0 G`$ %)J 3*_{%4r6PbzlܗǶmߎ4@/]x2R*Oɐ\r. }?-0!}~r:8N tABr 8C:J^W6 <#Lˀ}ؾHNdWC]]l.u]Wsu|ABP0HvL@1xDt |ř0kt] ˕cwJ }`Z#|`k/!Q.1^L3(c>- o;3ʎ3XanrJyis(hjH;ߓǂu9YoyK]($0PR*Xs^uSO(0KxR*s.@SRc&!==_Çam. !=oXpZP(pcH1)u x%|puߵ\A}"c`6KK)C_Q2=7![ iNk/Rw_-<͔Jr`rXh>cD?6o}ji-u =}}Z ̿kuUUF3QSФx߁lCr+i2 A 1lppB ;:=tݨ8e7 {]*/nhiZqHhw OCœiFRIC҇Sû巿6 [%*& H`Chkm;y_|v} _\RXB~sWC5rbӧ7,?'_zDobˮM 7CQ#Pp( DN Y,Sup<+noXggvGGQ^tC,ҰYaຮNoT7ƟPő- ui,3ێ9כ)8?폛opfhq"U3oG+-p}l͗ni"UjnH"WZ90>g;NoT'=07!Mk!lEԃ Uq +|@-VG> Y7t- }黾?ZRg/~v*D75}6 Üiz1)yިc۫φ'&k&c/LΪ\ W>GD1ߗy#EϺ?M]oȂDѰ4& yceY](?]_'p( - H|J:+tDhpB#b5p|gna:'Zlx"FNhu~{{ZtG‘h{t1ejIf(J&9rѢEDV$Tt{g|eP)bV˛'ί|?,#QojbX[UD-th'T^yfq^Nq EiEϭhh4彳t28$}*@ mT\J ӈ`MÑ^, rkֈȗ7McҦd2hK}22cl*ND˶i;SuS-FkGY! Jih;GR uvu\^{t2MA3-4;;Zu_oHee1HWqo;N!94E5uGB^նih;D'A~S2T'!88 ºTr~Ķ;'&'sֺ9uU'NLߗfkρ9UWWlBS3ej}=͵B|pOS7?i Рi:6 $#j~e|wPGgǸQ?ӦͮIKNL0H#fߗO1㦮o}#LN"Jb&W͞}̿0vMz$}XGG٩'/8V43Y WҐMӘ]f7-ɯ~sŊHw(*;_/Yt꩏cr x9R$ D"Ykλغu+)|XX(8}CJ9I)91ʕ+E{{;}__$b]X xGM#Ah@V.f~z[w b SȇS4&}U5'dT^Ϝ}S9Kp/cAJ M J8taExGa:\ f Oٟqm>uWӾङ5_iHi]}c$X2{fZOҊI$c Nc`lO8$ uK|]kqQD/9(&e_mYf{tN20_O3\bL^ (E 늉l#DI&քR]u|΅ "WzRHJf?{0uk'y3Th".4ԣYVh"fZ E",1 !"!Ҫj>S+W<ο뮻<Ƙ `Bf(P8P8B!GX$ci!^$ƹJ&MWXB.ZuG[( X4"0F",1˲L8E{bO qMYz1n1nF u=Hhꆏ3T{'>>qfɚ'XBPMuu˹` <(U2~<EWWֵKmL{2@CIIẮߐ4.嚥oRGgU }_ \)RR'"*YNH.@ͪ>7^>u">UBTR\JhYuo:>o;7d.'"}C)ŕ2QJ˛N@ RJu"6Wu}i(TĤRS( Gi14(l?_S9'1>HI~)1RJs]OE &}Ѿv:lw=dE)D |*h)0dXT*Sƈ!t=7J1\_“I4k*jYO&}k_@Ke ĖLI %%8BTG !Bp9EU{ߙyk2Ɨ'-_1..bR RQӪ_z xJ~wo~ջ7׃'H?X;&7z{3JA6S8m}k<1+Qק55w(K Rп#$2W%w;x׮_ۿCzz`救A/9 D&J_L <78R[_,*mahB`[AJ i!"#GjS!&2f.H`\DI`!!(b+CNUVKJ%8BF!]>% 9 A"RA0 ddZX_3B#*V BnP{75nȅuuQ0?8#OJM0ARY%l?`ĥ$ ^ZOk\麒x`$ =F<-v`qJFLV)uww˥MMaK#Ji<8&8BEC]/!T2j e/v & lRi  @h%0Yp p)I-!=_W 7z/"\*XXdJJDb144y4445e4457#BIRȊcBDk/-+|)%[2mM-Fxӧ9܌H_jN`zTfRH,ihh4 hT*btHb#_bRH,ЧuhniE}ccTCf%E~I%EԌV7e DTdRqEjՈ@gg)ڊO?hyA>6:YS>hO6447#Tkz"H|Ь6_/L*H4֊4c ?xC۪ Ж>cM>;T- QĢ- >-vT3 mɡ#ҖaK\gӛoZ H&-D(f6sczs|PƑZgg٦`KtX"> :888aQ$0(Sa`KeS][ţkkI"AHD-$X%G״%RYHHX45C☑459ig8gK|_.Xm4& 0"0"h,M6j! I8gOS-So$'ʎet]_5!8ltM#So hˏN5 I0.;]][nOhXv 'MI3޽@8Ύy4B`,q91޻0}P҇T> ,M[p71B4+Eq"Q(.m{z.|I` p]1O.59X'ۅX㢓j8 I0x $JqaD,B8&KPt+p $ʥ |ǡR["@|O`ݐW  n(PH ѪjT%kP,ͤ; 5"V]D4=Їrp,Du55HR,EȲQaN  @(ZXB\K"hml н3yd`H )G96"ݴ'P(e?&!QH, CNArn`D8EA%|:>$D?V٘<`cǫPA!G.{ :KT R}( iHjT!!ICy.`V{(U'ÐNP,'y@8CU2P]2h)&CW"%L 8.]XÚ&J) u]?v\}(,jba8חP"1k̗3;#xc]mhHL3t**\vy%PfÏ.͟021[H+4 4!fkFdPt]GC]|!`hyS+35AJi!b T5j+ 3qQdKB`*W`ۜbM_0o9'BS2)ł@_"^v5~)c#?how8fhۜbɦ/2EcX.S,I=eѺf[栺/f3嗋_65} Eذw7FGQe8 n9O 9: fEm]ϤQ.kd.]-٨o.827zL FHFb>bUwnO]?$b׵~uaMSgcZsT v3kC3#kPUUٌ;bڦ/Ya˯ZFQW߀D<dW@&Cvd10kBﰜV) GvPuEh.˜(@9;0Q 8eLn@i5IS;4&[?V #0l*ַ~|T%kU1?pkw_Iݴdf_lٻC2uD-?%O"*4O'-@MMe2"71vTk۬5MǾBBc<Fus̜mcn̚u6u/;w}zu65bӋ 5q#(Epxtpj?l?T| [`UHBp + c(&!0bC5Puyimݺcۯݪy)i%`.PT~;tK0[٭^8&Vh9EV}@2c SH{0AN} u1#in?UjYZ'5Hp%xD}"R:U{ah/0c).OA wa"&k?1؎SPKkah4 ~ʋ7!.fbAc1]΀IR= >D.ebqǶ+܋&ކ}7]phA z1? ۀm=O@*Ef(RեbL+WOojS]s?/ꩿ l{c||rRBc¶)þ/0^|!JQ8p,/ێƦUOkز#i~ۼ=O(x!(wD+b3ۦQ(/`>LGtՆ1?om ?CaE`/~U3W4~7#djL +/!MaEW̌8>cH3`L8–:SqVsUjDC Œ&T'b46ofMcJ퀜Wbr"]0h@v"ڃF}2 ^!x)} $RϦ1*CA1Tvz렶<>ABh08cV2fΛT)iR}E NJ}fH`P) a^~[~|6m^^7A_sHg{@*~_0g{ʭI v>aDz b b v> XWs}*VY蝴7g0u <'ս9tZe|ٳ=ETE00XWڌfXc`"Xl>q*>>51&6o1<.$Yxqm錎ۆ/;jҖ!boZ7+w]:G&u(fߗ`t0!d M(R`rnLLlZA) c4C'TΜhD&SD|)9C䠯{PqiNA+UYx  &߂#gěfWCiIp7?'GDmm޴ 3cBGoA˴F4DȮMb'~[VmYM/D_]8DNG=>Q6aFCcp+[@C]X]>:X>7X4&3fwK!A\s $ \{S 8Xٚ ??ۍЮ.J+bwR"b\F?C/[dLqc bQc#"afS%CR21Y*cFc=,5ʕ+=uTԅ6u*uQ$$,!duӚˀGG\FV,&!Q9~(vO5&x]2C焓f5Bz.Y9EmK֘T)4rq;K:ŅE4܌gքqkZHAJh-6n3kB[ (,%ݐx2 ' 6PS/|PSR>>pȄe ~K_~n Vm"fjPDHXRBMTC9#s˯wCD1Xd$td$K7C}" A{\Πj6vg^?+HP]6=0aFkP04Rp Zm8iLjQE`f dIt\>I"4K>yE=C,mYS1P c/SFC]$xR! A:2e$cC mV4T|E(8- G[Q(4Du0hA0|Q{; _͟J S8.uʼtRWo˱B gV1UkOlog7|_jCV;JJlɇ/3싎ś_W/}K~R @qqT"pjhW|_r$]}D>^xŢ/tAzT.+ (IpN`\"WplSJ%聾輵ilz ՏWo]8O\S,|]OR {/yv)+՛T/zd"I$}\ r"Mu|t2;o}0[%V!|K1Ωkʥ/ Iq}LfJJfʖz|EʌDH!"<80r-^gL_0o` }G[߀y_Ȥ3p8”/<0 R\4\>P,3ca>:lVs5#QP,|C:8 "!#_,#d59+F6i͞01ƹ8< δJ_i< q SklbdCYߞڹc[ghFqR)hګZ4×Ǖs3ڹcΡf9$f$8㮯 %Ms% 9-iIؔN9`ǀ;&0'|J1pƂY%>g!}ƎwΡ#5ReƙI { () "yUpBSS% bF&{`JG&wJ;P8u$N)B*A*5 A!"3LLN@I= /[iC32&EGtlByHU9z(~*e*a![{_MQ|>ZQƈ mI gC· : gCObNs5?0Rj uW@7LX>Mc$Λm^m۞R- qF 4Qʝz sjMhׄQ<ɏ_c4o pU}"8Ƒ)/وGBPu8rpǴ\D8iZn$x)Tayx)aq\GAӵ<)kq=_ĀW 9i^~!@q<;_rl|}q;ބp,1e=ZqJ+׼&PKM'/oör1{;Xu](zޯO^iطZ`PRf2v_X&}Є@XFTB,$Zk5:A Z2<6PRs22 @)xPx<][2i8MkGN"dU2k/p8dG_0)HUo>ƽڭ"?'(^9gp\\;W UXmNm8E`'%R`:̹mR8DQMbEb#[";AV .C(*mf<;+1rl` #|>|DBؘ Py@)RJ| Iʹb01G#h`{RpRe5?>FI 4!P,PRAM,?m9 aSȨyUOaT""+,` %ۇ"k8-%XðS cxGvttu~8<)g<(}'8 4M@3_*%h*u?҄\&heU!`]=C.J1R)RY!|R& _=;'4Ȏ}h쇅BJJ͗R O0۱J0_J|_Kںc c+ tʇn`,t (󠤂w1MR:~VB J?WЅMT}p\@O*x$r֔1)Rl'_*@=AQ_448<߇84EJA eǁ`"udYL)yT> `܎dWx8 OP>pyDDL +'ӸۑAs*3L&w 1H&GUG79$#bwl 2eg?qd vI8w2+[$eH@8m*ѬT~V$|U Ċh|j. PZ҇C )={xtטFm{G>xn~l; )9&҅@е bdSa ]]سN|3QћUxv G H1lN.ݾ򻺺EyM6J1bXo;GR3L>6Sk[G=23ѱW.# EvS5sb~lC05S8s UT'I3c9ܵ@pˇu{pO=p{^*Q0R~~aӖ}ᗰw=/Y&5DD|It#Ҟ=Eyd$ƂJw㹍ї*Wa ugII p9TI fʕB`Ǩg72v r%&R\8h?*o۶ )OFDZw®@RHDpNƺihg~ 9G{^&''wC&y(;VXS.EOwhbjnA,ÿ●/XKe!QLMﯦ;cROwth#3&'l|o:7||39L6s;:cXu=fuPC0&c^bK{m`&=(\p<wt=fuGrtcrwk. LU{2c똏U{(Ƙ(߭9crة"˵E|RR0+ދ\c2ދRR{ӫ/_(/9Lq.e߰ pm_Z^uGL(惹elKyx49)Mp{0+M eo!5Ůa@LanT֎u('X!P*G^sKۇp_@*c@TD.;c |OOeHg Iٰ{ǰw,_ڃtPu} G QS()%K Va{,|_b$cW^k=t:@BWu k}C)@smBq"nMŎm0#O9ulmCcLxTsL(=h )"/9ލ=xM:.)}1Uc?wUǏO=LL&BIM&^EEp2^ +vDQrA'$@ڤL23>ss&=!X~k5+Ys^9g?~ Ae8(sfzbt4w*QG(ѣҚ(RE3G`v :{ɑ5kwpO7phGWUI`dd3+i2m`O}rC[;:66v(qD(n}US9L&rTWUmpdgP mml}ǩpwyǹo<]Q(4JɜU(ӅI1}uvv68txb*nm,t,j!@OL$':Oϗ01LjK㗏Ae`LL2v +`f_-#PS'&5O;xLa pv  OWr^ "P gڄ M|:}޼ B9u2ddUi\ &72[`dt',or8>9NT`p] c"08DY4ޞA$RpW>Nzͱu )(! )H[.| ~A{,E,.ok[}j7uƚ𭑀e@dԲlOM?P p#rJnOh}GgyzkH#8F?‘P.$Fֽw=n>s~gg'֮ioO !A]ÒC Z,Lfr>`kVfO5y/>vm?ʪ)0ԣއ0 Plخ}^5ajxW\Ey/w'm_z_ͨo>x1 d^G10QRdy$ @&~b*\x\H.@p$&122R h&~>' $X&E֝A U_#CQVPfj*g*xWmmgG57ܖ~^MA |3caGÇẂD7ܖ:nM:*F*iꜼ jc֌rlPF=ۆkX q!F@HVx|4 ~v05_g5aҦgٿO|1B).|*~}doz1&j2V<4He|4WbcA.ka||.) I祛AUOfTaUeށ }3P]FuE.ҎR x-}R)DL kNJ Y\@_AU)֛tYx/ B=GCm۸؄߸mPE]2*!bpȟ^/}}?=p銵Ds2~5+b!TJ)H?ҥreGq}uW^TT<%^m"b|˻RgxC8oNRWHf4.!U _zx㕤]E'ՀR& _P-Jsqfx@J?مv3&,؂j>6Ў ;޾ZOooR9ISf2\ )<*I@!.񳃣֯nM:A>x࿗2h =Khf7`Fu `_$-d0"-+=j{'Oj(n̯~Ax4CSCsT-Ur<|>JJS}zO{@eТnY!⻂>A qd]L, Np q9v/^&A~\;i@H;/uƩ;~_~sBDY UvBs?{a!?~*+ɹ[ۑwxsS p0Ew|o#ޤ(J<˘~WǝoOR] ̬(Xt]m0_jx̟o[Іɝ[[ ]!yf 8K2HH T>9:n}udd;`mmm FWHH+lv*̬A6O ~v ih*Ixu${j~{;hWWYzy3V§̀鏂B.PF&Y^?p*>[6՜ q*#Th$r,zM8 T%)I'suӁc mmx{6ÜO/HsBJ)UFH*gSY1ݭ7_Х/ꅞT%S$]7,Aȳ2?'uV,bYY,1z.k97 DYz_ UdAf8a%4eU8?璬xu|"j}}VdϢ`lVqrT47\k>篨Z=={nTAcg~؝*!H:X/xVzӞe@J#. o8r_}upnb/e03f0U9?1;J{|I=|8PO.d̖󺦔děM6 [(M(39&w6>?ήPt&vU~_%ʯ}!C|X_rZ[.׭\{yFa/ފJSl?,ÛOlzDs\^>kKfRf]a#/B01OH$g-hfYXF(;.]x| ˃+_2kΑjtrQt`)atbM:5_P^?}^,Xpve$n5U5o@+o$)S_6v<菦k,?544Twwwx)cihEW~Ǖ {7 8ǾO=ǩ.q_??n5T¡KǯY`c?7`.|w/xrqc m]w}&\|í_g7 ^w.[n5/u؎SUU]S/n_'M O}˅DvǯTUUUwիWNYcgcgm ݈o<?E&8KMM>R.蓖=$ӻq՟fmڙ ?<dži%>~H$]ecaC]n#m˾zG7Sf.X]O{h]}6lڎgZތJ;̓իW+MwƢ/{L0k.>/ cҘ/[sğyB^쇈Gw>>soDص"GXYOJW˫uޟ`梷$3U?Afm僖YjuS#MSq*蕈wVUs̠ ]Qx?߳H;WW ʸމjaOUwgg$Y}{zjߕcRj&ݱY#!2u7cyĎCpjL \Һ]InE H㢵lk/]$AȇD7=*uXǫ)#8k%X4uz ڏmyU]Pݿ mmx]ۨn3|dǾͰ/eJkz&3#lFOzhhC6/\]s{_{#3 kޏ91GMN@fy+Sٌ?sN?C=sau󽁀/L0撍%w#o[0 Ie}>s{: vC/b,7GRaۻ? +9}_JOm?XmeWaJFy>]/0&XߺmBeJA M/⮇7b|۵m+1YsѭDLS2Y6ʂw7 lAobw#i0X<"`|ڊ//lݺ5uR>PkMߔle yd#.@4!?яˑKi-y -/Ysѧk\KC$i6>AG]jeQHOi:l_󠇱G$jڵ45 Y |4͛iJ;ch^GXoR3VV-=gmeӗ/n۶-yr>J|fl9(bA pw槱:髨S4mW?`9\B!FF|!e#B1d2"']ȳ/(\f̙ŵp בˮn ٍ%'u&^9 qI#g'y42A.\x#S}H$v۱jl~y+`\?חxX-yK˔A;:q:@F"x:fxAb~Čޙ/+s( U8?JT\8]p[jDᩂ,Dn>͘=9-,#Y;>Gd&'EWaٚpv8{^9Kia ;F.8];azD #YxRP7b^␷8U'[8m|ρ _"ޏ[.O?lE(f"f1 rk_??iárԥ"===pyx8{zK!<zqyyyu =ݤp>RoGݳ_?Hzzǧ$th=@tQۜ @qh@ Hz{zH([  &hYk^c3䷷zR~^$ (G{+?ؽs;B0 Qb14^~F) T|D$0v܎/ƢT]v ! FߌUV>pRB dcC c;*ã?eaTU J3͜9<ӃIWWO<?7Em>: %}!DCG1ioܼsh}NMW0k-P/Y';# !*ci+np!$\!R0OU L>6O_ՌM=Q߰D4@&z~CrZ_~&< ɏO<B" I`@M|6$l;^xe>6 D*#pY@ɇ"F' E8WX|:ͷ>P>cxv̖/n5B$|2`j 9z|﹠ϼ^>HU,$\BVFgBrO/v#Mo`-Y7|{I 1R$w_ ~|I-‰Kπ?mȘ)WrKB(*ئ.$$g$̓1)%'S [kxlw`CiϿupa{`Dul-w$/ynSgͥ/ۅ,}K9@]x x{D1$H X ]RyHLN( TUvT C[9*wѱ1z:} XTО$&A\sz~ggi-a\,!Je;p{aqm;v#N( RJI)qLS?sGsksR)eA> Iޏɉ 2ds9Gw C]ut|۹3+n TBbP7rz2=qգP[*   p@kw m}YumY 0LrP]6ə[`KoSs߂ HA3R 0F.9t>3ћ۪<>p#f_[`mϾp# VљRc* Rx%x@晴((ķX ҳ탻j_'<4}:S o x.lk֬Rdy1}Eiev>];4aۅ*:LJE.pϚ5k6_Aw-|Q>=|7w+zO=T)'Pq|tCϞ]8P+O؈Gp]s8EI!Ҷ6mƍ 80+O8GbokkcE-pY. D>gN,BсuB -%dopkgg7m?d~υ"^DZ+:~d+~.q)(\l eM9o=[1+V|* (%\o|%@g)Aŵqllr>xbK"\tփA,Sh0 B.Գ$7OO];{#FJXN և?էM=[=Ol=QA>[Q1@(0es,&6mQL9ڶK)`/XX'3|C.CS?zh5KܗRÉc '30#A UQ!DpLh@L,Lsc]W7BXԹ4qh 01Vփf*膢E$œ#~i,B`fH @7F ww>:P*(^jl,هb?~k' 0\s#Fh ]glv(|oyF5t<3s0?f.4RP?s{hێTWΨ 3suMN SW6~>"p p0Vec 3TxdQ+|VC7f8,“\KWΖ?xk 4U 1Z,n`;3q;c~mE}~{ X\pm{{.?W?рvP*UU7ݩǿ(j6ݯ7LmQ(8]7[Y3a~kM~&/U55ZGvl`M#|uW!0kgAqrm\pɮ!p)Q HM5뚪^vzǓ?o, AxH%1._H p;[-7bbyϱc_ždBԃgrGauy2za-xLe{3mPMm۽̟JX$ oRuY4M3N$^7Ӏu!RCS4UUxYйHW [Bl.u5KM]` 8Ct0JA2`=th{8M:=X?se{bPIP\)%<5zÏA՟ #r)%abbšJ$1<9l>Rw,=ѰqB$ ?{~Ikyo_ ) P)!sO1J>D?V~-1J)Px<c)>J{x3V.Y;IDAT TCuL&T63՟Hs@mExce,|4J PB c4|О׿ p;t4x<X' @>_)S!D(6UE{B;?|>(dQTB|#%hN?ulXX* |? Wp9ѢXMJ@hO?XXopӴӧ3*—#EAq!a E"gu~h4& crN_<>^ 4<YYYpto{i+vMYx2Eaz P )B4Q]+Z1ѱ-gS@Ƞa</+LT)\#((X[}iO)s]ץ\p(%;RH .!ᙦy7ހAKH~H@u* qBQTC #|/L}GPjfBI@oN8Ʊ8YP`97!|fq[8wGvvNV^ttvzԾ- fMgѡN3n5UzS^ @H ̝!С3='gʹÞwi A`˱c!,?tR"a =5FCCJ H=R}bni iB|)t&RCw ڳRJ# `9 ¤We05CIW!瀜Q&0r!uS(>#BxG}ہqqKQ[L %)wP,a9),DZ&a G&, ۑpҏ#P$9` H$ۅy_]|m!ɡ`pR?zpFגƂoĢ7' <ρy6<)GG!+l4`yYn(9xoA(+P]]I <Ea0M1 cp`|@ h[V(`3lP ): 3i~XV.DRy fGmzg=BNa*l/GjuLYSd_ґO&$ET9\.!dO T H\L*ϰnRK:2ꑞLC0, ah, sb[G-,N·3|w\cB¶ xTx[l~I羫C5@)|@<ݑRFfJR(|͕1>!:o&^ !@M:4fs*J d@a;TJ4$׾?_?U6l[Hr$I@g'3~w(mٲelIktPh^͗\x^;.G 4°oy~epm571)?~ `u\^\\z -8\HCPMe5?M<&J+oko'O.2PpJK Û*#0ak y؆]ĉ8!| k`{\.<O((۫]]i0B5" @4^cBK#z/~Wb`VP׷v+dQ|.G %˰h{8"Ha}o=nk~a D ooo8 2JsBµ4_ 2_M #| \~j#Xy8}B2(ˆ3`H)Jہ e0B hlADswi9+11irbA@փ $T"޻!?#?غ9xM\۰gh,Ea ``c|2hܗ@(zAnٰ?Pw0kAJ1} pt?{~pJp 0n6}(F|BqFp o-F==. u3>:fu=x 7k/Qq9Gv`h*ho_>K5J)w0kY#j*cN} DQJ)zGۇfBȗ0W& 3^WlzKQ($f a} R <0%(qh$F)A݄6&rQUҽ Tc_2D40c T4DM4"W0}M 00 Ԅ5T4 S5(5 LLAS"~1p2qT ~jX&0)J\zPptxB{_A5/ak?KP(br̪{xc44*#\}cr̩- Oz k__nF-r?*cZ,pI sl!qrw₫Y8gb -(X|=cGׯ_kע _ɿסd *CmeK6s!$^ܶlPo:wĝx(`)k֯:bwκ Q} F PH tgCQ oν k翖{˵"@44TWD; k׮o|+n;?`:EmD+<@PFP5Gq>7\eKvr7~o_xqnoA4  $KÓ)87{+>s==-uYs׵QU]|??2tz[Ds}l xu⥧6!=2/G fB*px>%;ƚ_I$Sx]R4z݀?Fy ZpiB؎f ?l +*AJq6<c:f-Xt0:d 0x<_1us#Q]%RH2(0H<]PFk'`{wRyOKU=;ezm@$F)lڊʐ F(˸(_u-6?Ӊ{ sRc'Q3O߅=I %f3ÁR"0rg*L'^yu"k2Qo?y($@<@xM'0E#u)rI fxxt@x^S=R;t?o%@ƒ-xf<ߡk n",xyv<",3 ~90${u$sCR'Gp~w5Gxn5C<"@jB8 |n_C /J˜I`j*"~t@.P =߄#@ r,w͚U>xp@0Dp" GGs=Nn k}gnU6w䆟EO"_( #~(0uoƑwS@W )2 .ʰdH1T~>(˟N/^k51yg@s(@49P^`{öGZdKf}a柽Em;J~֔PP2e*">=gh`LEm=ˤѳOJZŘ[U+ӱM_hBJ0)P-0&*:4UEM, 9$~SQr*:Le]P8pa0 R~TP?BJO\]YќUU\AUUBA?B:AO CcP(4bx$T!"[HO->3WL_٤=YP+e{(T=. Z]6 @Iiy.`DjP s0h)C8%?eo=#'GBc2#n+ah4V\M1B05RAy@#P+|%_V#(bkvQx "% J?-\u|uaݳU^ه7<pdᛛ_@,h!ՔC͑7  V >^cVsGYei3S89'@܏p$d7Tmm \2mmPdt~#"jhXAkJ/ChQTsA *<ŇwD6jj"3*Le:o͂'P N3 E|N1eۨ@EP^Q}SўIQĂ5Nsf\hO uVƠʠP[G8`@:T C|qfsO?07,$A*(' !5UFcFcF8!@E8CUhNşEp~.㈗y@^, NTW)TF@k8|m)!9!QH B@Ȣ;tT*oa*u AG|9M|YcoTݐ S(W+eEoshvvSGlsA@hs]NdrUaJ TY>wvvHdO_/`ɟʛ%,ۆ@(]5-dQl RKIq豟c4r;="˦r'ǿ= s FDl*YL @#b*5,? Ws$<\iJO X.kw`1rG<sKsӘLb\u9$$9%Gv1.p= <)(\!+x?G"W墘Cr@ezܬm»G]LPq$Dž lB(`"@8E2XjEWVn*R&VωT<.8j@eL+PVQ$pC&b<! rS=  lRKI)lj̨¡qt!+Pu\HѺzlx.Dpd +qcK@9E@q21 ΋UYPBQX@߄`}ٞ#d|?>B!?tA*rr8n3Uc)h C0_E:x`% sePz0H*|Z(cYHa&O%zcQ!P|AD* h*959f$`~KFїBBX}=P8gyh - P !_(1$MhCҠiŭv$Mh;VF\{ @( sī_@| )\N9`rxF+<_0DZZ*q'XhVΙarG:V0NHE-Mdތz RðGv4bfmTK7?IU-x4רlv`2iUHOs̺Z ;1GYb3 [+ 251JYU|rr>ZeeHK!󹀡XP=[%t!gL"L,igv% 2V͟%M0P?,Zy, kLn9 AGk`0b60eXP?8|a@Rnwk'[Y}*ߒڨ=?9hb kQPP_}C݀x+ga7{_EApr>FB fAEP!A!Q%.sRx2eݨ,2&F>Q'*G -8Bl(1_x|(R =$Y3 k:h^4U0#+IlkEChADu 7mFX9b3YyArf^1e&:N"F~З"(/ouUj:@6A4`d h ?YadS(o- >h,Cng?h5 \ d22x^1ۇ{I(86R_+ƼǩP+IrΑ?^!%8*gnL:N&k*X#$"#7~?綽/L|yRލٻYYg^'0 -Xv @A' PhAJť_}'}'Oo(d{;swf2P+1W ,7~DNZ=O>7NNN unASuʝl dnh0friepd?v_{B0%'oӟ{xduv EשK,n*jr$d{r6id5لpOT[k=bv,k`oee\a*+dX2;-+f9196d W?޿r/9G,IG@M PA0CpT# *)88A O)&:B|-+rBl3P\%`H UHtD))<3Ҟ[+( NJT<' !o'T3 &YfU_ X`T5 aXJQIN>=B{ -f/CUMMqded _$ !X"c>{|@2?ljl9@߮ms T*E(cِ?O=wH\(Mq@/gB3k^ XD\B Vòz/!omA*.gp<0b̜T((. ,d2ʫ PXp"V exZMb|ۛ+н#Wܛ$!H&gr\3Q{1!BD&G%\@C)׃#H.?>?(!\ -$oDyC8 vsLTzo?Su8lƱR뾜롊}B7/<ʰ{ `q#޼fc4;>[qg?)[:5p*g˗_=Hhcw6٭U\a*Mdz/_@c#w5ܚʻWh!`3b_$Md,"~L !ObNSP"r^:)ZޥjN( V$Ͻ*IAi 1!65Y)ASZ{J}Xw"h*P&. & %fMR B(z}0H捅ӜߝHfBCczy^Bʱo\*}@-`d,D;& F29&u#8r#cTT1euU,]D@H:wCN$%1%$zi 8GϡƦEC$2(ѩt=L?8[+ rfs Vg( rdROͧ8 Qp4ƳyN0:8cXK(gqKI0j("ɥ}s‘=ʒ뉓) ]Ȣ_b> B(dqĒ}!d(KM2 ==mRbv>Q "0n8Kn b%?/yYflzh#!y8M1r? ,+4G ;<9=7tJˢRxG2G@(H+b<9Z;Q]OH–9'e)1\fS]PA }otO(󯽞0B^]EL/M F,V2?|r#I?uR{ x̕crZDÿ8-> \){tRUa1b(BE(SW!<&9CG/B d;݅סKPF%v"Ĝ)8)wLJ~ >pLi~O+ W~;: 2wYR%lBSe,j@䈕c:0Jrz~Gx]_t'&ǿיB(f4UH=4ĸ#] d$ho_tt"@5QS@]eT JK3ww vAӽ)7QC1L&TrB24Wo2"S\.$J2xRXؠ>R][\ QJk@OTQ SE]e #]}WxR!$^Ȍ#b00Y$M膁M${ȯN_=MbRLe AU㓐>i Ob"Gj du߀rrQ H)l?9Ϝ9sLzQ/@GAQ*܀ 5Dk_ 1'Ĝ`> hT<pQ ⛻4HZ24fM|h 1S=zFQrD-A^34϶R%cDYWbh1M03Ci00SЬ)%T>O F1Ceyh6}h6c 3Eh8| Tp:B4i: ͦF0Фh` Ah H Ua!hV%DO؂v(!'TJksdC㤩`t"X.ĝwܯ.~oQQ=3pÉ>u:<~ݟV̸F S~ ^ZDZׯ׬67Te:רW~7vhUr >qXΧz_^K$9:3X\;'9,!؎gƍg Ƀ~]=_ĭ!^Õ$9vn_&g0c \!_ Ni#7"L =7I >!k9ˉu8 |pxc(N?ҟTR2`{lه7,%s$6mArk\R"?&$xjtB^Q9ٓ3B8g:rQ8׫AIeCc2yⳓe 81E_8迯]w ϝR9<3϶qpcGq'@`D ^'g{RPJ$\@ g7̤8^c`Gq%#8kf H.ѹ=DT,mQte#ƕSv&)J^CM =Rg=4ҖԽ|v>?`@RoV 懑Y0)IAPaw \Vpv6l;we3HI!Ǔ/0)8Sر ,(su|+$=WYʤ3 d("TAp-'1ɃI\ʐD8Mz; Ŀ;veYxGs{AU5x?A*W @Jir[p;}f^HI  !kkMC]\h+7Er%K65U_ݶv`T{:1ڵ+w:|$<7"2M ߺ4|CeXM81j&QTY#uoi"Unv(W5 boY)Z7HΗWht=Gx+1t$?jlkOOfW7: # ]f͝~_GaΆ?4WU~utphg|+:;%!?kƖܥHu] KƞFzχ@֥an`o%nz1=m"2 N@B-K-ò+Ɍ4ôdCU d-5+߁0@۷zwLML,"c'kĺuq([@`3U3a%Ƒ4Àk٨Z{!L n ɛrhO i*T7@Ӭ99~N _ŕ2ط[϶<{űSQxK/u/_jf&SItRqɯ~ 3fbؿo?ۺ%:|o:7iI9'9G2(~uoCMiBjRR`O* QaQ$Fa.\.($P}睍M l|2+U),9~>:͗Uk.pNlg{YV`18>炐6!Gg ::/:blMRJ%! ~Cq&r2I CK٢TEbj-'Tr^3=rٲe4 464E:a@/05:a|AJ YQU3ZZϚf>䓊]E s0)u {:!b~Mu#Fգ~czr4lFIx~$ _n=v@tbKʚ"?n8?a7`+4M# 42¾3混7ocx,l6EPYoR"De}cuԪz7'"_狙L,eN.5a0x4zO0_DN`(3ZuB4TtiF#LְL~\6y:%I NOrj saZPH8DuMMXcsss;ZX@@AI%a g'qtQ̙7P_0h!S梽rfmVxO]eاA 4J o Ñs/n211i٬Z9 7xy쳺B>f[;8"Gk&ICؑ#ZIXVK/5H7nzUк`1BZ[g@f*A|)|~*@pXrYBt:_u@$pRcfs 2S)XsTo/YM7ؓg};q:6uM/Nm?] }) UPH/ݮ %!DUvE\9D΍-?{|ݺumͩӕR2XPNݱ^jsu{U*zRRBU74\%lӗᴞ=Nww~ w͜q{UM PHorbiݙ{~WdDH$yN$b#H(vڍ>Ud]`t|vF<@4%(D)W;:kmm u+~qlx' Rс5}G7 $"gզ3LUdO飔"}GI,:1EyoMSWX+Ƕ.BP ~xf#=L4?@(9|&|RJ c&4gEuKcнOd/8 ( Jybhaaw G 8P2ÈŢaQkMmU \ZDf̾8ѿϾ⬺ ~B@IG@ !O  aH #ױ&b"B~l޾ |EX1($ms'׬Y54؆|>0J)+ 0)ySENbSQlS 015':TQXLG,+K#PkRz%S@+`c*ضr9"`1V*aX6l)U D[bH,Jؐ&oJP.G';BccckfJ)EcX,t`Bs@jؔ(rJRD4/ Kfrt`0I8\LHBH,Mx٬Ju}-]cpKck8O  xqḻ׹c!灙oZ_oi ,RRƘ*J0L݀H AB@*rB^uD|-I"+|-o_rK02_(-|Lb1l6 !%J-Q'Pi 8 \P* 82L)DD"pSc }پ̬ !% "J)\?h\?r(BRNdWգ//J̆R&>F2VVm9/=g\\  īd>MX@A 9w<]u}zNwKKI $}ʮPpAdzE٘W_v";ygA%%} LJ-2.uV?jt02ڻ3 %BrERPR!!)zLc\djjDOGS@- К\ƲltvElٽJ*D"QőRʮ9(*CuV.WV:aq" Y!@"aY6R J 20;(xCnvoq1(ιiڱGCĶ p PpRnJA ۂF!$I?T*ien0@ĊòlN:!PR,( PFi*YP4"}"aP4-x$ZtT7ï5M;Ʒm´X_m90C^m aR!$#F|۲pd}rL4,CQ'Tˆx%8S.1jDje! CF4@w\L0N`[K0* |@7QyLJ|FrG9ͩb^*滧gx$C-K:|A_S"{tW~{_A UZ'VIOw\Eσ_Q >8mn2n9Z102FO(4t栘ɠ!# " ]Y>Jrt&>pX0?|*!1W~URy-Wk c 0nO+eGgR'?*8e" A^4 |7 ƈ;̞_[rڧ [ mFClW^z g/+c*'+0ZUE[ƿG~=ދMU9^oh4yyȺ^|M$:5@av( `M~ukj 6u*"Kˎ{߳L]PB -ooEjNZP>N FY*;7%\ifñFw(TR"i6*(!Fٿ*kt=ƺ5sgjk#n쾻 @&Eu3tW|x=J'ӆ1Swf2LswM?6LM3nŷWXPݩZ# .3|~ $z_MɨF;5ldJ1x.X"OYtai(ɤ??׭c{zx}Em MD2&Hɏ)F}j&x@^ǿe}^cJ(q9?8888qߙ5Nc':5[2pKt?1{I&; "(z_֭[z*pg6VDoϝՔ4,WT7 J%kZ4[4٭h C9Ð3a?P 1 C_K PJrظj+؎ d@=J)o_imuYkzi"sPu7q @7d>Հfv֚٢뚦pUCo?$=18kOodqѱ.M Grc՟[d[>FѴ.CM C{R\[[OLWiv,65L2uCL7&RBkꌩ"-0 0=?8+yݸ{l,6AWc'?٦5kB9T,|st46IN)-Mضiv0\2¿f[5kNS7fQBp.d.[3GՄh:Ʊw9MuCyOӏ}&&k޿]t1.1tnI"Iʏ]L܁tH{_?1 ִ(:fzAJ)p.0c,}7MyrYPUUfel6l&{ѡ&v47?hEcʼn$DB QC >j[?&b톡gsPD:_c{}VXX&h7M2@UVQe}G:G:_žo}plmMI״NLl<;d";!7'Yd$eU5Bb,ExO[)\[du/S] l29G& }oro__6Ũ+ڤMq/w^o4S;4!DCacjARJ %( !RD"r RDdf: ٚ&BQX5P|pJ(;ƇJI.P/,‹>WˆǗL]iXcxFaQYE(nV(oTJH) ׁ;mVr3qZqS` A)> TBIYl!K0~LԾ>e>CqXȗL)%|ߧQJH%RR(!4 SE̺t?+;8=fR:0 CPJ()+H4l N7Jr)7՝mZf\#&jM+n⿑͞v"{_֯_G{z>ϦFWI)|S:#TȰ%2r"nذݯ;ANs*1J(%!R&9K+` ~ x@{1덩;- B5qLrR*BiPS= ?mcS볼N~'bL 0ԄGRBd"1S~3߀ Q6$c=FIHaJID<!o윲g_oTmmm8TWU5F0 J JH)b! VR3 lz eIqWCܒrF({EGqj}So:vjԺߓEl@HBDMP8jz=6}EcT"D( dJ_7Ƀ{`'XCW6T@)s9R B(1t{Js޾ߜL$KcT% XsPw LcJݸljx @UU͋'VWW)%ÐM<DJ)d@4W-QۺF49+[kL$VPD i:6CkmqQ2տaaX!)|ҿBJJiMu'D'gHOc;hcyHt`(z *¨P 4cmi==8DwF!DH)Qb%hՂ Ӳem=XG?N|>TB 2<L\GYUKAH M_I%|zfÈUCzyТ zx3 =FpCf:cS3rD#&iقXU ]ta! SChT@$z3pz9B $(ҘtM+לbZJ#e:Aa ڀ9͵5 QES Oh{R15=rE23DmGLNr̘y bxtI'` ØkZ UKfSu 񈍈e"QJb8cOcb8}f[VxYE.mFIw9K-Œ&:[ < ^G;ЕpP,{%aW!=Pĉ_ɍ4r&Y|} }(%P16l#9Ͻ[46:[$yN @n*""M"dH; m0OxE(De2<[.n@d|I -t3""miKwl85\< <)SlDYCicƔE!(d[qNn~0̚pӗڏmSBhv @6`ީiRRlR0pj rcͫ . W~q"6af2aPaY&uDHjFY !9jg` ܃0,04yRDYHBU'%D骐ꔡ΍cngdfǘԦ⥸+-PF˴MWNQ.85 CS6KbPj]ڄ;_B aPšO*|B4ʘbʐ( "%#` O,;(ju+:AJDZ%-Mř8 %T*G%V߭0ؔc^M 5Fo +P D$.X9e5FH;dgELI.<+KM1?_))=_>f*AQL] ӲpNj!9\J)#/b0Q$Ftd2t1oz= d[ ''_rb8|MG0/{tFE-CXp:.®}YgK>|@YsS<0T^C? 3DK bYmT/ kA2:j 8QDm͚5L2# -\ 72"꒤&bP:1BF;1(BtWb8'p4bJEZ& ÊjM UN̋(v%rsBSlуr4$crldE#}]6%698"/OE)Bs)2! 7_ص_FOl@MS}q_(Bs-lyeO+ ^ؾ7SBLAP;<v#h|:#0v2 g]Pе7Sj"5FZTaWU1*QdA}㣠xyK;089SNj!QH]bֈց&L6= @>HȰ?._܈w` zH 1h5I/Getp$ [js` #"(Q#%*e)z ^ `N !V/s/P@倕cQIw"bC9 5qHQ]/s/Զz!1Ji* Bc!2Cp0<CqE^e,߽{-bB`8pd_ڃ<.EFD!{TC$}.&P!jBijga>("=r)Ria!@}p ^{^J(f([M1 f6QXdE H.0f PwYEe ̪b$4Зqd܅  bakAE$G ?̀8V,dzR@a<z 3#GB_S<(3I=>Juf>w0gk/O@tf嚆@kc Zk¶=Hgr;B1pA1{4dE>:imu0L4X-" 28n9i`ո6d"j1,D mUB Р7yt*D

HU>u l44"F4Y&h?Qu@(P(V_㲄 Q!2s̈́h.mh "`{1Tr-Տq6)Z):ֲ0atCՠX6FFqvԥhѾ_W+@mjm70H'u!Hgߏ`a4m& zijؿ)6n0-{zhͻw = )@%j8&L/wuث>4Uw#.%4)1?S+:Y*PJ1c2_O6&@!Ha-ը54DlR)'bp J w к$ z/rհ? B mEL!dCO1#?8Fp8#_m:T \ع35).QI@ʓ`#'|lڪ8D3"V-/x`cׁQZz$ $ D0:`9PEw`dv5v%/&(z'_PHT)KvMŨǘV¢l=F3iy_.!Bޘ/&.Dtѧpׂ;m # &=v"Їx$DC}"bhm+R"0gF(.|"!f6tG[ɼmi͕ٓ5kʧΗ1KIF05b^,!sqPښֈT2 [tf+[*h$|W@8` w 6"MB" [:_Z)(Ʊ7al!R p= e'$E9(d1G0`OqLe7j9`J"u$Xz z ,V#Q!r GqAv!` HE* TT37w" q*T3E+PxB=).[8?e}B $"MHFm|vG}6M@,FOcl 01Mh=碥k&ڦˆ!b8z>P(܂/kmϨAElrQR!W4Nӗ{o&9o)[~zAzI-(V=7m&njE921ÀK-HcP(!@NMVOi밎 ;D < #i# $@%7cyLKPxprh0m@:1FSq)S=qj9 z О Edjȱ4`9 0X, _Ȕ')PU^? =:tD*kG0҅Y K>2y Z,K Q@PF若1^^` HH}[~.%S/99|&>%U%`9_fsH$$J^a"GcDmd2n8c_4&Aҙ@:`q"`!s ^0r:@֭c;/;;S U)),b4cj`\wt#$Y֟6_1SUUNT` uKʷҎ%HI! "89Nr 3\a﯒ЊYh_ZU_Cl0=9\̠|ǂ"!QD~{$(ϡ2#fǠT=",C (㰲.M~8~'@P旐Tmb)G/;T=X5fY 8/z hds1v*&S?= ,Y5H6"RU ;cIdpagajQ>5L{_@ksOGCs jkrV/h1#GPEt|0Oä< ~?XM ]$uU6J PR^2O_XvƨGI3c\tRϟ<s'YFŝ;I!#/R\`h u<}@K!zQ ݭnHH)GGU_+) >>(H𮋖$S/)Bjkg~˩+;󳷌@ww7]bU\~4}|~8q٥¦lj|j;ٽ$,}lv!ȺRK Z,hrQ=7upirz'( Վ/|7LC3=8ֱ2 NoCqxY)ǰhZ ,a'RB)j`x002ChOq' T^rA|bgg"q>$>J$# tKbt̥s:̍:r9L\Jئ|CW{R5o{g=M.Z/O=~I'|e"ǮŽ3XUSBL.ʲyΞ6MvvK!3zWqdo۟!'{&U-@<_jnUUHN !5A@ItPZWac"m/8>ehwX"2zTդKTT G-dT=<}'S5[z.zh >'(VTT Jc>l]0" yYv?յfL;+*Jd*s@@PR PyB~w_%$*tC O$>=3>|!AC'2" 8ӣW*SiBʹJ{z49iwxdaoqsI:mq\p \[S`"b*<&3_w$OoPΜ ͳgŪ]تV |U a@(DJ{zO~!G[.߿isz?P@dA+18BcZkbgBG+Br%BBf`$cϱ @ (0zN)0@Q,Ј!c4#X]]7&d[NӐ g0t!BHs5TkR Om_rn!{&-ZE?ØOS ;@x%(H) +hK*g2>qx'{$pE':N6c怆eC b_99"\(\1QTqY6:Ɵhʦ#MpPǟg* !84J (@B2t ===k6  6nzܶFS5SA!a0L64 CPqƍOᅌ숼E)E!͕@oዷ~ruiO Nv vn2-wooܸ߾G_Ն [ׯ;SaH$%BX&, XF)ԩvdxt~k@!kEJy6s'FÉ?1^RP0X 0Vgeaܦ¯ ŎBp_75 $uWlʧ:{1(3,sK_t_J )`PJU ! qjH-~4 46?,C^/+$0nQ&~/ 1 'gBΊvQNdcIL-g2.b T p!r!_Za!-xl\0j Lx2n᧳Ali8~ 2Sgs׬&<~g&2RtoWjXC__(u n?_nSU3%T1+نd2 (FXb&QnDg7Δ鉘q鋙G ,{< uM40Wk.qF)6o?X\?hBԱ-%gGuK4FtCd}`Sw7߄fO9Ӓ&B3 S#/0@ø4F1Co) ;f8oE3V^W`w$& m{ b(Rcqkku+E5fӧj-[l]c/p=]D% C`p…+ulHaҮI>zf0jYd ݲewޙѐ ci)<|?#p`Y#Z0/ePfkj} &əxIG943{G<1X$<^U0 'nrfaڼP(zn\ܻlTiUCh|gòu}X25U^CGǘ1UC_}5:5eZu@$u(JNU,./@ Jvk0P?1Ԁq޳MJ(Wk֬!>(!kkmuum*lnCu!ĶC0tCӰf6ա* } i W,_t1a^+ fshvm2nm;XfY~H\O!Za&#;'U^sLvV_uսI5AIyף[S/ƌF:28e {UW Csϥ]SWW'/o?L X~j!=> ڞOj CGhS@($1L-&-g%C,Decy9kJA}|"P P3sUP21OȢ&z9(t0:c.nhSzL}>R2W~Wa яן04@;q޻c_S%+@w7.ƴ&T!\q>&N5x6FtܥR]͎HbT'Z\8>&2Aą͠w<2篚) :սcum*Ows4f'\/Cغgt5m;z sf 1CSG^x9{uhLf旊x>^H4rc"z!% )Q",S Mӏy]vKFcR&@c/>^>}?5q@S;tI5! zǂ:n1LҗI17ݍλѸd"V%NhI遡q"Ĕ$lC 3|'D7VcRX %Q-KOO-K/8ߎEA@X`0/5! ,5xxlgV Jr9% s;?d2p[筘4 Ń"W5DU< -=[jV X:w!H!`4TW  4r?-??ωǤS!$ihCrSRHPB͑ uOƜ( bp>g}yX\ƒ *%!t0mI dB[RP(h. x4b.%J<uy1H&y9FZRqG(JhI% Hqph i/$ "Eш}:c!/Ǣ Rz#?>gW@jF(:vN]1oܻ2e6YΩDzM]Oƍٙe>QJmdG_97kj6 =lMe Fs_?}?xӧm~7ndd ?WS WjmE&S}HhP]C7_C,r[ RUJ)"qxՔRTDzZqc)ef87祪RDE< ?:2R)<% <KJTH1Pʑ ʘG_yϾxy,f4L,*C}zbO~:|ADZe?,ƲeDlg| , "5,_,a]x*-:z`Dr_[|TBň!!{9gDbNX<280}.hhb]3:1P(gzGF{\lԨh<~pj(ygD"YB`TfvsxǔZ+| D ]Oc\q.D"P 9\0$LtK@]2і>y N^B)/ΥRaȅm5qQN ^HgD|AX Q'?a#jJИAU)\:3/^!T"QP(oi,XTgP= °S1Ix.3/s/6 4%!R~euҁTD_z5?H,g3ط#*,4D1W =X³ECc҆(:"" 1IG"\{vpiU6b#ۯ qx,C:eGc(]#!sW䔟6Kޑ/}1@?M/ @ Do~C7gbOOnsRGT޾'zfFFG)Śj[Lҗr,s`67knY?#|cJMuj&URP M2 rl_f6x#\zrlly05$!\ pByGTcHj r$e}#CF]ڥĤ@C+ !o?r.L'M5m:qwKg@0*'RM>E+|rؿ.*>P{"뮸d8fM\ȒKӌ؉F)~q߭|.R>U0~ $x랭=5Z?޷aSU?`9-w=|oh\ ?QZBl~o~ sP_}vةEyMG2;{hM34ػl\)Η)lL]M@ V?cSt$ K\J;Pwltw ?}/}s>NRUs[ſ; u H?vuI\2|fd>V臜HLc o| 42!eH*x(1^xD4ԜT425U):0|dw_w\7&AƉAu(uǯ?_[0,@TaGdwM5('~y {.V~{ $=@(]aa~26)_)0Be@wϏ6cʞIWTUG|s4.Z]/3#*]*=BYLd :+)Ӏn'׮<=űbFQ(۵_rP\_ECm=OgݪυJrGjn)XK箿\st/nTob1?Gv/cH%6ຌv{!~l-" O?uO\+y7%W .뻽0[^ Vt 7 nޙPr~^>cλ~_z~g+VR ߕ}wt3_mDA]ԑ˹S3gF[ G J ~s#[>SNǾi6Es]})tWQm_/l.y>#_~:Xvm0EÉF.ә'n՚~=Sk- *#Y'~7=募7jBs=ܐNSvRv$r٬wzgy]%ɧ^J*k%>!VzJdKbԡ=* f"'Ցsx2Kb ZH o l H BsXߋ?<0 ̊<1Gpu4Ī: 4h5نȾv 䠵)&-1h(.'bGT~Oa\w!.DK*!`0H#|?{U~H1 0 dF~QH(5>R/F%cTRZ+ImH"]DӋ檣Hbs4_n47k\?ϗFKj*F4mhC! T)5b :c4XsTvU R?$$Aw~5޴}Ӎ=pև7_D_juS O)_r]Ʒ@ՓORG߰fֹSV))T $QP~($q|$8BJn{H ^W|W-YwNnJEOUJ*_HWm?3g/3n>UJΪ9WV1״=}_?T^|wi`@UGjy4krS@}H GYHɻ(x(OW?%?kVʑU[ʟůmF]/BU±LrlFMe2rd3ݳqߙ>D(m%cspo~<1G$_5{ɽ##ÍMտkk[jq:1(`bӝPl!D($r>ӭXS]Si~ .=u5m+!U!AԠLB ]A|& p_?E쐧mFk^rP~Occ֦+',U#ɪI-D8 xt 4%eBHb|z78gȕo5~ݗOUO?Q\/p㝸n!N $⢽}rh#z=#RLF!_k_GW9!`R qϠ|Ρrܯ% ͆+"dyi+LN-d?D̮WDp[ui͌¤c]Ȼ8OCN+shR u6U_<*l=/6BBH&U[_)p! lME: PJpy:09ҘF {7u0 8|x\Ck֬єRPRqGD0HO7~yPB:hC_߆)M@q@ƊtTŅ{,OW =v_wSg #G51((ѲYݎGڨ+Ny5vd[eEfRI]>_,9Vq?B!8+*O59ZC{7aKo/xkE&- 0o7OyRZx("#c~p Yཝy4 vGƶp[Cu z+`dʃ5x_"bh,{t);Kƶ=p[: ,څ4YUQuswzꨩH]R@xb0?AcK<π0 8܍Z:=Bx9ç@PJYD*A=ګB ʃJ{cS05yNӺ{h>zFENqޞ_4d''w2?,!jO+!h`i<2=\XY[vQ⶿U]>/nUe~(C#AG*|;O}ۑi !sdof=,y4eDH!e e{ _}>Q\Ǔ.h314'oy//J̆Rh e9(p!~RVvHp!Ha$+cUK߻a/Kgw )g檥J@M>Q0xHFƳ&u?j<^`_WLVt?'a('1P\б\QTQsqɱuW5yݠYNڹ{!2 r..U 9F0UqbWL9 `ZL*/4ݠY(Ă/Ǔwh)8WUW)r< r.C.g`7&ܿ,{OؖMS<ֿz\f ä؝f 6UuqEDG*~"tl9 2UKQˍ2d9zq,{T>J)Pb?T.5qK|a[]q[a:W *1^~_y un>c]|lu-tCv!CJcJ׉$ : t|[#%) g*I^0v_pg) &_R[tf)|MS_kK-IƈWߟWJL/ux( lq/ۂ^x$DA\ P n {GXq6>ӄzP*m B(=MCU y7=D MF11)!cpWҚFSuS瞜3 @ dGۣ:`sXƀdҀPg:G!_=xo[ԩ4syCSf'8cTh ||G"m3lZtޅKwf5A3D1Fhij64y"NgԗrO+=Z]U[wEwf5,|+DŬ0”2:&>:?QP08]tbu6Nf9nѨ! Q* Yai꭮׿75(HOBKiɒ x뫮c9-@ch./q2XemMt!p&}~QC~!m&T#-˺%l*şI&L#@!\\vYǦ*R63YPKdp8# (eOͲz9Nio_̢>&. (YX6I\:CoZHVdI&u)n|`z 'm&d-˺) E4qQQް_6IZl MU!EIyI2H*/\|۠aƿ ?UMMO5m1.^L pl6CL h3G18eTk! X03MW|gy;Ҽz1{Hs_.*/n1_}0I9:8RN7]*K*0*u&W5/{XY0'i?i- '\@oV޽`!A2Ar{G@J_ʏpBhڴL%& 8>2n]=؎א;Z1tOtT'W yܴ=}:귿eaI@:K=QSlvrIvNɶ+.rCJ\ӱ{|MB1t_T["{+T1zZڄW睂<_7 :#(iLGϜ9On{ & \Wb$; ac$~/ JatOX''0DPajdُf [4I W 1X~F1Ρx,8 F 3ϖm 4RJFo/% <:h f dNH'BsCCd݈f..parB|_a䰩~S42m2 hbJ 6K4q a&}GD#Y\+_KfC1jG4Cmm>3f9h 6koIY@UyUd&~;SD~[ +`.4fRrB;֒]Bxx*Y̗w=Ձ=pp;!:\^>1I?MͼtY>zݤIӔB}9agjo{{W(^Rzr7S ħr{ՁC. T4ǥqw/p>ɿF~*BH2ARxL${L,'V3$\wueDb:W~9Xlo[[!ޚ,JpUW}ߟN­TH=vh#oϡi`ժUIy\qR mmow'd29ȩ$TZG+t Ƣχ-ki:`dlN~_6'XXZP|1.6Mf" uL.l;ߋo8Q]]}n8h}>.1 kRw 欝'˟ ԭEW霓T َcd${yYW^2c0XF眤p]vgO.F77A|ZXY^Jq\]ټ@WUt7ie,Ǡe, Jcp\.ޞxgzMlY(D4QqI%z~q}]hˌޙJ!uUKfSezf(ck(0ijx'qFV H}/T@@h+bƳ:ʣE>cƓ|8_SU^tъ+~$|o$x@FO_ 'K~"|R9Sh+"Ic1a]_X~/vNT5q~]4, 3ƈ@(5pJbDP"}M{{֝r4ˬƺʊ51*.j_R)HYm`t={?Q~uuX$5q"1DN1)RJ(l.˓ʁu8N'?ѹ,1sue߶,/%V(JB)|102}w=J\oM*+b0BCxB !ё^OyŻ_^&uwNfm!RKWJI+H!4M#bo gCkր Os)mO "J JJ*c(ٞ˸p}&V}* CJ)!RPMv!w"7 ~`c'(%BI!}!a۹NOR;|~u ދSdAt$㨯v_vo`0-K-VuqϺT XƗV@/ZqRMo"%$}a*K7oDZG M Zk3!%J B^y,rt o5ؔ@(t<&R*Ȁl0 %DOGM͇P|Pssϋ,qg@sJBS')}()˓m՗bq>Lv%\g\HA% 㒒y0\!t3Yz4} *ui|RjR)Bj|J1 TYU\z}PX5})<|C$d *&]KL~d%aغ!vvA~2‰iZ]!tΟjl,ޕ\4=E錃v3ÑH9x9(W4)睚Ng?@wP[[\re~e(Ĵ_ A\ JrY8]Vlkk;-/p Vm-!53!G-Jgڲc/X5ׇt:- W^yR/71ԵRI庂s9+.?;!5u[vc)ڋiWc"xBHq&C9cje|8,ԀF5VJ)/璃3 .V*U%g5ma]]쁁]8ҥKY{{4,h0`Bhlh*DB g*e(xB1si 3k ] M!O^N`DH2GB8yxfӫZ|)ҲQ^Yz"' ") h#Rb}SSڞ+XA>d'ODE}T7]6cAH4ƤXI Z!ODDFF9CSDX$猤ipp>cVӴ )ΊI!"P2=bD͘1k{uTWW+##8B^zĘ"/PplHpęǾ#lyfBťRc' @}uKΞ8XD(`2qFsϙ,91X)8QmmJ+LgUEe P}R R} !  34 19ODbL7!UQ ]Ї!TT%\GP@0b''u+`SWj?K#5^ B;`F LZ#T.B|(aYŋ~u08T4p)vAˬXmTמQ@p| 9KcKHc|u}!Ps7q\߇' C:Q&?OY=g7 H ,&qLe. M>p-yTğ2(4CҢ 51(oU1`&V-_+/^] <w}瓸Ư{bP բ38#RSR !t=pQU5f 1F8Q `ޑ!BI cZ̚Z BH\ <\wejtG{$"+R!drTL̮ cNmgOFܙ$Ks8?th4JPP  QL(+}sgMBԱw3Ɉ1X=&:pC@F"UJ^R.a arMgR\{4II5B*p\MA(Q !G醩4Cl h1E$Ftq蚆3N7YTϗ=1τl!rK)DpR1!hh4b .#w`|ƴ-C |)ׁPHp4AeBs=dhƍ. $\YׁT U&"TQq酔b+MӏOi&IӦM۲k]SsY[ i)HEp܃@)% lv$-(.Ĵ-]PhN.C, @b潉X28|ϗe#_'|rυ.tB$oKAH@JDIT tp 8jK^6lG_)%\N&EKL RA em,IJc/M!$D"8#H!ʐ+]z(BL\r* H@{=(0[wtB7yckRTh@+02\_7"#d B*$\D-iuLDJEʻ.FSYG0u J/6DX eTǶTc0s(L 顦Ʌ2Hq5qJ5>I)u4>g̜Ξe pYR ɡco׼SIiJMbK2cMOE,;}RH&;M1#V^{m&1*`JC9t]ÌIը,xgΛx4[*ɣspFɈ/*CTnj j: ^iFKtz8>X@ó{|GӇR[jb()PCu,eq;D],c{? }4lȩǟ 8[>bZ$$!= ]P?'Ğ|1;j?uh[8۰K.8[_ih,pB6WF[ZaO&ߞ5mS=3_t;Ʋh+& ZKu5A?zO(< Gʘ$6nL ̬L|A|mmSgpbuYZA Bja{_6qBnöњh5H\!0-xxA9 sL*tjjZK.slCМXPw_3[iMј )!K!41Qb|?)(xvnoҥZ{{&>۷͜<`(804y%x2X&&G1=}LxZٖ--KykkəhLmTZ؂qx2S\ Y F]Eg?q}g1`CezKv|IJ-]5\^i%28AEļ)UؼmN0W3+t)vUOy80:&0BڑYT(r@$̭}?93IOQ*.fn*^A4^>D0:u L;vb`8Hi'#/MőҖvbp4}]0 L`,X 4bρ!23*-S[v0 g@O`E_ٓ3xpiupƤz<:`jFqۢ'P2FQ ?#*..[(n|=֤٩Sh@%TaImiUS N ~*B__ f <Ю2d#1pc>9oDO᠉W,´9Ņ}g'͞sϘ=硇oh>Oj 6U|LM#rK@F@ue«\l9*Z{Ο8^]U>s\,*8)+P[" b۫]( K/ڝ[{X{l7T7VL:#i#R2J#Y:-H ]4U^gX|qcޫMՖE+Y72Fgh\Xq?╡axB"dpԔEћHf2qu2uUˁ_2"PT(2W-w񭟆w2yrex䩗0 ^x:5gv\TTq; qQu]aBBfM8cf5ʦ#nR k|@<@7QΨghZXڪRHgl90gΟ|98!󦗣c 1BC̀}t ΞRA[oj+ 覩,D,Te1C :tV4X"d@q)#D ^;Snla{a C7Ba{u1&/|RhBy2d@HcqOmִŚ{q[đse:AP3B]Y<D4`/tU}G U1񸍵/[U8F=_B`k@=hQ\kң#\H5Q4T؆h#V﹀8)xakb!0x?+)=tFD!=H!lO;x#`)V=m*XseTʷL +dq !UqJOJEߠB&WeG_E<6X1pO*4 C()Z@'X<[XuK1t9L# `$E26 B(2v W sG(*I9lWo c B(\~ )r ;\m(Bi 2yUyf6`LUa#GQUF&0nDUySjc\)uTDPi /U4Si2M&]`YЍ07Qh z(`ji,AǠ Hr$tTUF ]YI h Ua, -*3IDtu+ym48M]Ce4_J0bY&򎇼!h$*aXjg"؀B]DYepl#66f%4 qlh@CC:{Q]E~d 1TWD~*a4CJu\#]lS$L qc92D }PV"8|4ZVJ!" ;icH`ɬDցf{L# 3JNȖ؇xGH|l FF~xޜg4VJEP1lHis|E(:.̛t!@P|V}[tƌyCZ.%8lArFȻ lCPT¦xVuu Ғ^1/ 1RK֜1c]8˸/U~h-Q.DW';!%G+3#&0%'(J)c@BPE\}H 9q88;D }J}VJV[k&`) !ΤgJ>dR2TR@H ϊ3쇴_fΪ>tE}KU Hd%_,et9ۅ*مRs5q,}TE| JV%/$[T16i#p[d̺ {aCUO ś0gGR / (#@A0&/g?/Af|ДHLgy Brq_H!")f&[˶ާ6<PAKcyہp1I"aRHmAh@}MAmƛXo >ŕAcA (`5R( F2#ӧB;fz<-- zMKΘ90t9'_HH`=AM J54;-ZJ @S S{/Mipg ã *σ .R33 () 9d)H) )|>(@ y|xZM"m(P4񥂒@֑8o(#}H.MO|M#:%YUqZWwbh:C6h7_u.4![J5Payvykc_+B/ mFmSJ {ή hC@h>G9aQpBIL{OKL3N~[:cxW-\s6A o?g>c(x+lR܇$Ry)\^i y}tSATz@Cm_MWiDNٶo7 L+B^>/N A)a(BHU4:ld{м.BP:Tj!\`OgΜ (@H%-FPjx4&UZ1 I?&~RTD*S bRƝ((H.@|!<$ ROZ?  H!Nt\>HCPد do"CБI×6i3bi  .wprPR"`93!s+_|!bv2W{̦%+u0{oiia_$ )B(B)] ҆C]X.۞/{J/3 ZZ~d6e%HBc) 0<-<ٗLKKw^^y彃[&{`LNB381N%e1H!]C__/ҌC%=O } yH4% ;@\ߌr?_?~ۿp>&F%21 )\1r(6tIX:+.Cu s 1WoJ> U!yہ(ORo,o<8ef8>Uҗ +_QЙ*ċgxŁ)eݡ"xp?Č&)B޶x*i+F: @9Vi#&.oON$#PL q!Ag@OBy9{d,k݉$"š5T5L_;"8"&CO7"Rw2#5eZX ״5w>L&g3#JJ s@ "HfFk䚖#@P=̵8W8tFcO#Rm7=0zdTK 衁|:k_k>"RR*%e1bRVFKUNgyd卨PW*Lfs(%+}R H) Փ|IfstRIn/=D& Y|0%pTQ|d"(Ҁ)A(8, ItbNE[SPwSc0i >D6;Oؐ%T4"m[U]񮊊XBcTCHv 0qʌZC"- /؋2}#hCڍ~wé5Z[RDD?s'΄ʐS΁j-E/x$/ښ60ݷ~r׆YoPϦ*ǫr8IgQ Ms!TKeȁڿaCq9v *uwPqn0"*Y!aA~۬hiqpLK/wXimڍY?0>t S&sJ^ް QuKR0F$2 EP[[LR K̅H&(r4D/.pnY]a=}< ITAұ`Fᄲ䢆3|p}ГQ6($}P:>LglyOeM7ݤgΜesO|oև)54*!Lq`x0 c~S-4ΐHQ<0'TW-?Z!zh q8-`p)33PUQ\3q98\ڽk7ݣPkT[4Zֺ1w+k[ Iw3\_7O]w!,ѻW}gcG巶--ڲ֍O&9v<Hgps<)#J?c[Zj_l};nzwcwx`z; [8a>3eѠop&2wO>e7![.Z_w@*R lSL k{T 4&wH n;zDZ!]7x2)F5]b!mTZ@y񤆫.8Ht3$ =uX9Le x ?ó?\T6m (qkM4  %TVX!j1 L#>=2?c-]˖9KqW`*EJ@hT&u #:C"<<0*.#5t;| ·piOxLF}FơB<Fy($\CCE< '"(e˖T7[g>?"<9*{r #yg@_~g@4 K;Zp\t\*Z˓;=`1<]x&vq♨. z0ܗLޡZZ˿hMPky=}L͞^q ag=:xZ/Zs|~kkhiYud5U ch4) eejz@Wgk5C[eR`9Ӑzhr8u^,3)1=7 t5somImnի Ww&B5S? ΟsC=z_3wkO |oq :gVfϪ-YOHz;{OO;N@utT+w=P_S6wzSfN,ƃ2I?o'zeꨮV@3;睌K%4D5Ld=c|湬n|Sp?^\@DáM14FL_́5tGG1~K{HRe~(ϟjTЕKqʬIvZb#x4M:.,u]J+ g{;6A UmĤ_sG…S[--`k(|SM*:Bis[4 d8z2,2cNwW!GK\ دuo_XYHJO>sOŪ` z*bAeC]Xk?ӂ:djg~,No,F7 y? g+i2W]4|K'7;;v_S? lC5jhF\q{R˖.]Ѿ-Uȩ9;^-DeyqAst\:05!5h2íl84>&-xT!,8>?8`x<;yn/LSc,Lh:ͼ 3?1V^BxBr*1 ADpd.x~/tI33 ikkMTfpn}"d^,  !awG$gĒ׫9Gعpb%xcys+ D-rIF (9dsFFF/(FD֭vI,dLڢ.B:';1(BgN[ vvuogO9ŖH|D/_?s(mi/yvQ.߷,ȾDY2?}~*ͧ/pB|l+$ ѻ_ݑ8>_t D*;|U2IDATܹ? ~ujwHWvvYHTuR3:֗/EsW =/^ܼW$46x)W^ڵp93''?%yOἺ4Ʋke/3o?%|bΗqJ`}iʬYfd~y{$~k"{F^҅W1Oᖆb-VHn)h]7&}3Ng_@nf8E((nFY]xiKX5[M|XW]rQSU3e%rv|㘗) kui^l|q _,Q@wE>Z(;=Ͽ3Wre˺N?f/e_|ASpmhRw~?K/j**e::wF_В7whp}g޽{Ӈ)oN==_}|=ƔM_ݎ7?hp]~\my%;!S.>c_Nv9&sv,|+O}yre+ f]zŪ) |kvGg~0Q[[៸>.3eUu6u Jx ގ[~:;DE4?oߵC{ձӚ&lZ6 d@}ԟwmC(}Ն!{vm3[M|g}'h??U5?>lh9qӛ_a丘V#/?-JQυs'}e嵦sqށp]^~ܷiY(1a*gܷXOܙ0orw**> O9q;/cw} SO>e c#96y=TʪXk0<7b:grOwc /38P%>$PX@#]֡&%fk8 MD.yfuM?Y$xKYt0Zd0U#e#`.: rٍwg镨|7. Օe`(3ْÏE ́.G/`VQJ Sǟzx TAOpC=X!]bvF>Lv97?m\իO?¡`M0RL`Ǵ `5WM‡ϋbբIa4U>528;8wy˲֘fp8TJ9DwBS4-PqÃpk$א<Yy*dl*O $u0/|M| O T40 ui{`0%4>k2 8gݻS~2;lr_.;spV?jk6::W^y[8GW0kBj|KWļck+ˣ'?>sؾ -_z!w6/4 /-?A}[S dg$F;`oC+)`32Ѓ܈EU \qESnkk.p|~ PT2idמP8NC6MXTyUeSϼXY_lWǼLfh}>XS\buގwދ=} IbqDaѲe˿876nܘ9׊|2gr3YۃIg_SyH㬷_IB@Y\Y¢eS͟7/e[dܷ]ta9Y`{>_x`(+`uâ׈H/& )d6p1cgՈ'PD- * Ch<=RD^Nһ@!mtܰ++(Eu۶U>69 lN@G^H`#ڮ=ߡb1-$<Mc[!ΑEuDz;+Lk FppD]t'"t_SW[H(BB. ?\qfX|ct 6D4.$ j=>?a3kܾ5|}/ Gqa5~fʲ裕C29`0Wb 182c`4WճXQ>)5uG'wpVMNj#Q\ܑ='φg7^SUQx,lۆ^pjQ1 ppw;eq=M ]H6xm$/mcVݘLi%q|qoE9_~R[eX J9J)cbPB]5~66pa9HD.\li)t =[@aπCLʮto񟓰7< P0@LƕR@@$,tG=| q {zp69HgrH+ sD^{G?!Py:n<-'q^^gvb iȔ9N$\er <`-kP ؾ{iL YsKjpbmk^((l߶?mVmz|}ܲ slAJitBum۶aϮ[lEΓiY9- t}( ضmvP}}غe }ReVJ)7'O$e1ۘ8f~_8<)}Rܿe N?f@$MO.T#bkr0ET ܵ, )f><{9s>u]9'Ƌ|e|CT[W4' ҽ+MӒ+8$ 6 g4Y] KGv'ϞihZ]>P0xL~@4&J7-۠a9)〈L9O*ZMsBt%I؅%>Ke(Oܶxrͯ;3B3,lr]4UKS trA,IKb)2Is ,{9Jmz?cg]EnZ1.Zdd|>r<ٶMeaѱ'igN2M4=@3GW\%T*(."yr|\]#;9k( X|yd&YVvIv@BJڹs'iF)cw/ ;BeY^)H &~QC$EOXR6a*r]=@,9~'?F(UIy\qR mmm#Gdžxa4.fW^= o巴h{tX뭷GK)c|xGkXZ^8sgOJ'"w}01VOD@ggO~-\pA1800}{_H|sΙu\ݻzj??ΘO`*ڷzT$&" }-P o#b@zcϏnA'/+H"_E+w8!|n B)>zof 2XGNkYq ɾ^wIe,eh(GO߷tH6k_޵Jzyt<ԕ0t6h;LӸ_w'^kV~IJw9; 4MC>l+ Ofٟ\z[BSeeM@aBrS(y,J+hiiao#4F"yǶ> 4Msn0 麎|>~q֗OٲUiNB!tڶmr=%; #TF7YueY3`w BO.[~reԝqxR%/z? xZEC]""@ nk }@VT.盛)_ 9WBFOt:+V|CCCd2?ڽ{gn&x܄֭X4fuuutB{]/v:^bŊ>mØ*P]]]mR| \.e˖v0G[H5556Y+ڟK_K~p2?c߭.׋lhY7|cŊG,PcJd2w~vD:UU++?>fI9 aW#.C~nRvU{eƗf^;zHD|L_r'P N[^)_/b;J 0-\ 5LƻnC鞞`:{j3~5zVhv^ lȲU?=lKpZP8QA}jjy疟]]]P*@hdP/%?~roXd;sTx~<%w=O^/k\p_.IZ fqpqW!sBavh3C^OTWDtG̲L1Jy;t|p#ć򫫫HDuݏF̴,Q1":yO<񵺺/M3}+eaq"*Lyr,2-bŊO$eiA)Y_?O[(_Hhwq ̟iZ^on붗k8Tyy|C=4Vꐗ뚪8qlsF{K% uSgA1=]cFOO=+WH4M(ۿw/zzL&B0D}CϘ9;1c=ц|!}!9W|'d/f0- M|zOOO륗^8T_W `Fi^uΤQQ߈i3PVS5ޯ_rWG|0MFɱQֵo7 L@J@0L1 ӊzʕ7O|J)Aڻgzz)݇4 3fD]]K/ǫߪ8iFGY=F6 SgAk O'?﩯T30pL +"x!K3{zKn9>mll6>8@vcv0EU$4L:|Nvʕ;iG>`wtJHu0e7*(3.ێ_nU4MA#CC_GH3 fɓccv%|hƳ)ȟ±)biyv$\xBS9,xQ!c7^Il¢G_ƿS⿶"?@=+7ǐf^,T&=&|chb/Eqw搙ǿŃ6%s c+"I=ץ1Iy13:z`ཇ._]}̲OGtEW.b!1vB]l{]>0pՉ﫮~Xho1IB ?'={4W+hߣ~ xr>d}1@bK3 w%C"p ]~: X:{LohTx$Md/ݹj,4Μz\V^ye;%;P=88}!yӋH&ơ򋇴fϙ˯\GO,=ckUյfbe{%we(?xO)RsjB(?kժUs?ÓhGmm^xAڻ%3bzbR@%)ˮRSg㣣>h2͎IӏK O,?";)tA 0-|.ӮVy-%^zsGS\^U;g|/l9|_}pFFqYPMgȑ!N_y{"k ;kk}=xlۦI@p '$psO;_Z͜sՒY_~#aÆRjgcSS=ގDB+'ŘP0Sw gy􁁁K' R\F7VYYؘN׼w~Px~R|/2Zȿ+Cl`Z'+ \aSz@Tw $ʚ*"*KT{w{4:>f1 oJ?k##=Õee+bQ2*:VrQQ{ <McLAM.c[EE!XctWjpם/1uX~ӞOa^"(<7]Ļ]_Y'0  #GccfMAC}5@@꫋kh@Mm㌈sf86lH)>4mڴ6o?GPB= #He/m_2׿dx2 Kܬ߼y-}CqL38 ^x~/?9+++SVE]ĈH-&O >-}"8qH 8؃SO<ںfYk)S7lXgu#Jn L7Hxg_=p}oh$0>40m[|?;F ݂AЭ t+n`{/oٌo~"Ѩ2M6k:B'0L:xGG>!zǐfL+Ӵ`@i!SOᦏ|>5i$MӴ[#)jv]_a؄ *o&??Ri1y+[_"~H$B>_$ĆʉUe~8 b1ƥ;l|X%f0aRrESOnͧY!/G~5,1:33 M#'nKl֏U<&ZȏLt2T0pX7~+%q9 P]nc5~l{E,PWe 0NR"lӴ@i{G/ +dfB1þYyL?`_(\UuiҲmn6om G3: \Q7w`cπ,Y"unF_W؄R̛f#o 9 $JK5{Γy 7Ƌxַo۶rLUx4dr&i؎ "*K6>ډϹ8StR#<~ƍ/muPς'lЈ^Et#OC25瞢u f.][jǯy'M3J" ra,<73`i %R+X}/u%FR6o, _s.ʗBQ]GML+yGiџП77%tM7Lp%n`YYٕunkp' r _CH::hnnV4UŲe|32oy׷BuFb29Xxuk\6H\8apo K<_D~#o<$^!"3L z||k0ij_4 } ly-/~qG?zZlXqol׾K\BeCU M@eϲH0XQA6oBSTE1EA?!?2y)CSqwA?Eӟ&|826!aj$IR0̪nITZ'`Z39ewr|ADjЏ #¬ YJSB`Z3oߑ?P8[ jȀnǐlΫ31"Txkz̄7G:LUs*) _sѠ+ʥ.1bL `$}7K,{v$`1Q"krWLU6iVǃJ%C#âjiBB"Q le޷%U@B .pq=!&Bp5hND>pyEE,~7JreS+PstlIP80syUʖp' ".Ƀ+0 3UTGK丢uˈFÇw=nc ghZfTWOロjkEW`kKK {ixWﱠ`qLDz´]؎-Ө*ktl{(|>(=?xl%30—1^sӾۘ:\QWYep=I8Bؗqtzˎ,JK?Q*W`͛''n۶?tC犢&¬r؞ x#|3 ]Sk}쮻H$R~N[>ߵ{~6V #3H̚"hj*lLe`H yvG󡸸ߋNID/3o1qU@8o$7g ._OIe?gf?b܄ '0dWב66.2b ۨPR<@ 'lZ3_-}Hȴ[t_줈k?)/RO1Mj*Q[UqERłp ¡ 뎟T|~m};aM`$Q_Cmʃ($r">ן[g`_oXg?e˖`Xܿ~dr_ (P$π$ 4 3gTWX1%KKFbn@q$2DE 0 "7J,L+ +;8Xb|{1`0Ę0-Q=f*0%;Pȴ8r[M-..e`kυȤ*S91Dr6rs#Y?H0M+ʄ2 9u IɄ ` =}1(E(9,b:98c,p:@Kd`0p, ZPcLmex! RVVb(uqW t8еW\C6CX*Á"4+ kb1R 7A gQ>W;q3OP4)e<ϳTL(AmqGz`0% `(ömhpѢQ+㎟;u8.8g'ećI' "$ àz瞻zT?_O\>'UUe P:Ԗ7 eM~t T!I8erpwOX3rm0R=14^6]W陧%]X1*~n۶-Ӄđ]c$!ʠO>vBW~ O? /|?c Uee7 Mf e Dې҅p,^P]u0>,_rؼy3V% oċ,YN {sDp\̘8(tUŲAXM7mW^Z_\\\i&%E<1,G_F# `$Mz2 hB <NDshwʔ)esOj ț&,ۏA`:t3 uy,X9ĉz(B{0oq41d5lXa~ R5es玲ŋl9 YhT7*hV. >4X:u=Ons&OTP fOϟVJ}H26N{?ᢼzb :;!6Z9 ӬdF+sydY*'UċӚFK 8vtB f 4 Jc!pObneqF4kʤ@,-Cc_ F5lF,j.5Ұ9aVquE:$0x=uD{cGaЬ ab{9<х L.GmBJ䤍7ڏA$KpIq11 9w GkޓkDcV]u=,*Þ*MBQ}/FÍBA21od%>N8^X¯X,CCv>  2Nd3$HUd,   oU$= ^Nj8 =r N&mCTᅭص(@`A< PW]}+5BYy86e\ܯ!9 dp%*#~uU 7 ;|qURc ͣQ6`i`۾^~Ň/򠬉 b<n&ccex6UW}o먱􆺯# M*G ؒ434G*\rl H{%#ó u_+,靯yXW!9|p(UD5IKlF۽ClS MMo?%SU|d*: {>!Qj($e9 Uh.C$ٗvb޴:pFl3&UXg/;{1ij*K#vt!X$ '{p`ߡz<èJ<5D#qH.R"Ñ*++```á'xmQ"AAX8ЗBYiRJxB$Dö@iq< g~Q bc J| Gԧ SНvQ wA( ipF΅+#t*dh %%%'맮+K"AMXs$s&B,Bڴ@( !+D,8܏۷8 qa^aȓG<#{"A09 !Y$AIIIרc3D4];>l~M,AzJJ#3~Pa:R@#? h$/3YH‡⫽xC`<6sƓϵ'C#  08pe;p8LrXt]î>:ҋ`Qtb(< T7nܨx<]0^K2VwA{"DPā> AcIjO@_QQQJ)U}4聿W&k864]}$E"0kLYݓEpN܁& <`#pJa$8ad ze1&>VRgW8|$14F4Wr:O 2OT#L_ Kl<3@>/rY ټ \`9tTۏ$f7EݍYȹ&kiب@X+|>h`.,P]2@2UU`yӅχ*فAH]N:ki4J j}: +) A]8Ӗ0G"wµ%W?VWy#9'`9.TFnc)a.| .Hǽh嬹Y6}wl٫p)"c4`󗺻aY3q߂OI,;g"B`(SZA#I,O`P+ͯ'.:rL~!EepB^MM CȢe5jkʔ);`rҥo=` 1,S|͙ p, $%\.c/ƇC[> nj}J~6ecjT*댞3Z>yDy)ځ0R0#ҠAs'VaRM A1,\ ΨC!g^_-hjSSS眧-3dZ.*'8>'! p7 {N!H ~ <SQaӟvvwvK&>x5^nė>v%<,i#g @oCø}@x p0-Ua<<ŵW]F΄IRxuuunר~?h~kRHX2w !ʐJB"e亥doSLiÓ^4 ؃&F`uVS\ 4\t( 1kʡ) AY%$lȨc[Zi+@aG }e|1R*R*1m9e or@R/B kZ= Dͥ5{7=:cC 8Y_V@a8 |^p=߾lΜٛ9f8̚}‹c7&1u|%>Y8C +V-Ap͙3d>555)1w֜ϙ*ۻR碡&Oϧfऒu̟!=}Y<>u2=gc 6^ {0wLʑn4H!PUŹSka3(=J < .1e$6gΜ>,Y‰νo9`!S0::; J L,1 SDx//h/*r3F'P1fϝ;/ӦNe%W.&WBW%ѓH@W8&U2;r|8o˩y?ˏ0i}ΛwYY6%)0.EsP|6djV_fMJa9À+H-ٜsO`0wΝyR@.p90BD: wXp&9HҰ,KVWװ6mڤ0h֜1m9,<הa:LV"1mr-fLk N%*0g'cs4y2RJ'$*0 !CUL/CCU\׃irlyeYc?bܹϘra TXr06&_ᘦ)Ofϝ1#ޕ+K'*]S,J\(BW\)"Ű: OB&zV'Bxrq]קXQ( AcƠh@2 #ADP ]\8"w_j*|4*<ǃ>fur]T5)%T0?[ S&M10r#!Rk9Q.{y\" rY`E"<d#` MMUv[x$97$k(2TSz^nʂ'HӲ icW?+ՇY7˲Гwizʕ+_^,sxҶҲbnƆp%RteH8#ٯµ%ma`d&tXrkjjSLypEoժ]ݽ5pD؆C) G| z`&GooYW] ˗_d " u%Kzji:6P9 RrD2G˖/ϯX":Atي߯f] WHM{,d\ǰBx+yv__c &/D0B>0)O-H.DT!fHS`fb^X# ӴG`/ȫHCNtD1*%FOjb1HUʌЁnpy[v'es8<Ѓ mPT+.gT)1˽i КÞ~4L{g K$Q)5"14ll ╃m"k (29( :IJOoA]*GES<Wf`sNEG=0@'Hȷ{Jv%eDx:0tQ$29$29TGa*?F&E ۶=xzd`Ulپv\wb3lذᄆc7\ߘ?x/A~MFJ^׉mou wkxpo\宼/|}6l8 +֮ȇnxb0c⥶$#oRr *GǰtW,e+/A?.^s=4LCI p`.vw ::+t.;z:G|7]xmp-) EqJ1𫇧H*wmSӯ h"Zrm%̘11Ɯm쾇4q|k Èxchyjb*U .ᜫ3Տ`t9mx࡭߯Aa 9$k&/]Ն'16%̊m]t>C*HLlފͯ"*tMرZqZ+?a?V^~ǯi>;}Ҹ e f6C9MQ:d@G\*oo1웻ko7'9 HsecGk'^>ԎT!Za =4w՗_N׬=x67 t*%SCU&PžCaLL4&=&*g*.\: SS#~/z}LSV?]xy!̙fW[B I; q4˵A <@2Cg4!amEMU 1ɐ> e!!}cB8?l$yE>x**;#/Qe;FeYASr탨h046|DL~\~7紑䊃Ar&jzK 5Q9=i!a{0ո 37f XP(e0eA(L!az a$29t $G,#HC,=؜K3ϓN@:ݥ&a>rDG"AT&b(pQY,|]e.L@01{ id,%񔪨ΌE{՗FQ]FuQG:3\apSB555񖖖W֬C~p="%yy3zH`N#E.e|s?LDǯCUY?nYQg2\fX2p _-Yn?;D8#Q{G}n$}e 'cެqDu׭3CCC;E?zAuO!pd̜T  "t s#ݳoPuO|D"LN1SO~򓭆weLcR"B~֗;{pɢ싷rEy"+d={?ԇo1jşt? Īr̨)Ċ‹*m{?E7p3=N?_5>po2b,XtKt81]X/e〝Ѿ֭MMM;{UWu ilΆxT&̷]!455_|q{tMuJ)m}!R hDL c}/[_;Hˮ-'ΤQliite pm6ZVQD;ܡAZj>2;b۶}䦛:b{[ (VWsj+0tCkg+n9ddQcRb_KxİG+ bbbuzF!4kpt?U:-ǰ}FKZ"EDxF`=gΝ0rC%<ы?=P"XYqZFe\KK˿\WYK&N{n l 58|dȤ!MhO~Y_&ΚZZ{X<Ý]&VAr52WǑJ &> ='tebuҜVCʖ5e\UOۺO[4^@q>C*AWzݗC '4>g~ZcF䗣g--5\SQ;BeLS\%F{{E.x.CbC4&*UU<+7>XPcrш}#c}̡+صIc|EGJJBx8 cY`qOzo68oK!clӦM%K?~Ü9ss&}nr}V\1{ q@@ x@yKzeܲeuK,K.ޙų>w}[`E0ћH]mj[7~z,~Vzcޣ=L*pޔr0C}#pWڵW{hLݶmOW\͛7+g?䓷̟?x= ()L8Y8ܗFÚ+Ƶk񢱘}{/_މ_3k֬* W8_ILZu˶N†lHa V $ᣲh`ь߷fuACF_bPZ]6{da*H K̘col|ۣwNϭYsխ~v >:f ٞVJ_v-o8_70fh˖-޸7,0d6/YL]&s_oƶ7  IǶx*|m˖->! c|:::P(x h7`K~p.ZISP/BtX{{;,4N˿<={{|Qx,>ߚ8͛7cҥmK{{k|RwܽОHL]51d9H K)c1ڴizhs{{ԥK`b}8֊D& I*0(.!˱dRZuF%K$czW;::ґH$<<:g gA9p?#XTSY3<^˲ٱc8c1}v 'CGyѣ0 Xw?!$B&LSFfАp]oggg6\t͘;ӊ{Bq .JqSP/m٬m/|3g۹-l:=y@/BeE9L.d&s(|e=nC;D"uKi}0D&"` i50}LYggtgط+B . =} <1T7Y3Ǐrݿ577+drdȽϬ>rŘ,ٖu1 hAmm~e3.,|e_2ag^$  )}%Ђi$ٳXPYOYS,1lx/ߋ:9 ;E20MyVS[57c@}2U/yL9 9 B x;UET~י1t=ߖ ,78xh 8]Z;N|Cة}{eScliy/.)n] :/ <E46Coo***) #7{,˾{uFw;y7tבHZqeY\U kp4Pe+?i/uww;46B!W*vGiӦ ] Vy+ sx*@¶xUUS.{c֭=^iru(0 +BSO~pϙL&-**Zg۶bYW>C/qi1u]p)WnN_|1P( ]סtF2TU%GlvcGG>0=}]B @\rFP +o!CHIa]3 qP #CsNz,N6]a6RpMq 8W 4NeBI~~OŖe11  (OQ|.4 àL&poo+-[8 B,D~? B*W8+yyѨO}n>Sԯbص(B j:$ W!Q[rWWMdcm8sYtqn@kD@TU%X7o-{' ~WGsf(> H}A_UΊjՓ'~9>xT7!psL r=yۻ@"ujjSo}ڇ WhLS%7fMAyL!@pw}~\DzDGt#?l'Jg|j Nwc,d‡?aȁyѕu?[ix}҄/g ә&2>1pԘ0s\'/{2o'D"N E|jC@=1hs§OF0wS|{}hKb{2,` Y744D"%3!p (..FQq W H"lҽj˖-L#=;/MMMMlWM`yqhѷ(PU@d4坝;c |I{1ث}\.u$8dttt\^^sG?پtZq]\(L+0ΏY|qv#qhjjb|ƍOΜ9sY*:\.sGE&Hp$t]p\s5LݗHg `6Ƙ?8(|p@a# $Y -}+6y+c^qYg\*@?eŸ'G't gGD(t~O_qȑ+-cqtw-juRuСqmmm,]MMM GMMMhnn>O}AII8(+wz~0DEE Xong>vAqq(4M===/nggǿo@mll$Ƙ'>СC㎔R= @ee%c,Lڇmkk /BSS g?ٛ:;;甔ضm몪\.}O'8F<^w~k?|رc3N__i1V8n> a,ӟ:::.*++;Zoα'?ȑ#WL&6}qѢE655HE FCBg?mZX`-+T oT?Z|Ž2*R$! m~Upc9?`[;b_7Zˌ6YOz9 U,Y"l"$\烦i8t0̝8t0t]11>/GO` U7,Y" I6pAQ3>4r ݍ\.o477&a`Ad2Cux7m\xeY7B&1 O@N>,H$ws)ݍl6{]w}svcc>~dYCUUxDŽ4Dt\mfFpd2T*e~Q4)4Mpa۶4m1X_ߏ\.gg?|Ga޽4}thht?']cFd2]нO}S **+=aPVEB$5@_$+vAB*90ΖZZlKQ>ʪ(Z1z"_eC#0~I%(\i$ FrvW8SNA5Cߗ8o3+F x" ¯%[:Њ^&_&O;M MQ}6~)` (M#8_~~F~9Ơ*|@a--O;پ69mXAч?4 9ՃNAx_ב?pQq$@FDss38r]ue>B!T(|>D"a͘1G֭ yma8͏D",JeF3ZDCqr]O$DDPUwy߭|>ࠛH$ZFm)彖eȞs !~?EQL&'G2~a۶IJI\-4q8u81WJɈPȲѣ4z!LoY0 0}@Qx'4Ns#}E뺛H);劍y&x<V>;0 9(\(r8!_9?j_]Q~$Bq*H"Q@<§ %x}W>B6%rW$@q$^ #+~ ဥYʟt[DQ&]qgΤwIiM_-G@ilf_L C "ݔl"KFz%|d t_gy 7(o.򸖓sr}{Βw{c8A MFf^rO<6AF̧}/_76nPZZ.T3}o+|pϘl{+3 2WZÙs#e }7a?| v=/§s){t$7%ӟC"=y^+[WxΈ8N@]M ~^\bgfnL?-X.^soSٛY 8i 6:ўWJ\/t_!y)dpWyy?oܠe"oq]?!_`: `I%=hGDe粲ˊI/._R= 8`"#] ۽S򗲊뢚Sb zb~+]4o=߹_єLoN|vo'?PZ~}~y<2 g1=03Z=03 3G& Z5תz$/C}@pk*kt vڇϙOY.Kdt~/Xow7^D!$%W}*SݸkxN-CP &tI~$ؿ8I"OW茐r/mS(x㢑L}f_ⓧHp}f{wgUg\Qp VwE+*aR,zg_b'4p6{s'8 Q/,3\όŋ7)@ t;7sa,rDzH庡Q,(0X`u㚮9p_88, 'ҲNN%x!͜J~<;+9 T;)0fV wx?XYK:n (c;I@P} {V1 ]Y,'v5Ny>Mt4oPO>. |W8)y*V1y'} YqḘxt5|lG` #L<;~]-g KܰhUCX8xm.~0>:rL)VmUo D56(--9t|mU̳ۢ"8~^_N?7_Ue~8 |L*vJ"X\La!q !%WTUTf|-ͅdm/6}Ů@55E6_Ûn8g>]'(Nfׅ .ν0}S7_}Q~̓ .#Lg!áq %b.ZNWgautM8Oo7+OaE E?sAz`A}R,TG*nǂpx9T(5S@9l 3P j7:bAr(EOV;X;gɗb)^qGhH6 QŧvϒC%\mbh'м~( t a@ { eb>hbÁ~bmR'4Z4X;2sV|5T_cq4h;G{wO…Z3#u>*_Q++ v:N24y2 vWB'mP0_@i߁5@+Y7{CPޅ/<">;8tF&8{cz899ҧ<N٣Z#ADjȏ.ܚ,jZ9̜D) B?QbyN8LQNNYskr9PU aH}j ZuxvFG0H ;CMZ_a,wm//$OPa۰r9Y/P1!`aưF`jgCQ]7f!+pQ%#A_״U8ߏt ]B3_/g.8?; im z=7,!/TxB  AWtYHQ9];eakPײA8tUAϏRNekߕET|2<.^q!lY_}.A?ݟTvH%  qd0Vx#ew_EunP<2ۓ #pH`+ `Fdi 㐄d7# )qּ y'S}GvR($ĴdҶx(aAPxA04>L ~ j/o :gc2džt/2傏'G>C_Wa,dTe ΂b}U?1mYy'CCJo0p@S8 nc:2X17 4/ CB $%)q'Ⱦv$j: ׃8r ޔ86c5{O CUn.\ÈVA9Yp/DA.&;u==3vrԨY_0 2L)U0&!;F.4 +5s8z?ZSwV}H,*~!%p229P*)W=ӛ[玏7a=C9m!34lT0{92=0q8xջ:YẸGY"gr Z~]'4ì -V{ufZlF=6YU{ن_ep=B1/zr\>nǻ>筕aV:d::0l!0 0jq`(EywFϾ/^Xݲeh;*UU.oLG_,"L#o/Ӧ(p ;w([a˖#9sJg>ŘW0b%UEj"X2EGx@2uo+LX%vl[_&Ϭ"!29a՟ 5UE`6LBa V)Mo8tnCq 9c}ϛx_|])-pnMQS5` AgpW7τ2;ޕ[ejRUSJ][z:c2 燒&6+ّؕi~w'USե ɼKɬ4cNUBiOk9\ UT`G[[fY[婲qtpW!RYIteEqt eB]~tV.3qr* ̵.tNHuxef(9j~Q ;f1_=uŸlTtvwGp㵗⟿Kl]Q-d,P&QZ2@z>ߏp=Z>ZXOMϨ[HHYy8p s*!p(V8^y\vgoØZW}FeWG^XV =>Y`9_)l2GX`ϛ<ņ0C3xnZ2֨63fW" e$X"h0%P {35a_T;\k,3jЮ躽L?CjP< S0hzkx|[Y3kN^ _:Xt뻽{X6@uO& B@+Hh-473k471LDKCRuQWî Y!jzxcPCIEiV6Sm> UEJYq'VLe!  fۏs&נ8"|AN"hZ^ǞcHHd[^1&ݫfhtuOWB~ 1)Hf$UAp hq?+C@k@<_H)Ss 5UPlh]]W|GI$OJp.򶋀g$J#A4L_P|b *(*cQzPcA׋p8\N!-Y"+7mۈiXvB EW:{1 8uv f:ZQSS?Rϔ8VT6@PC H [$ ,ҝ:ƚ%FW[`WxD$Ɍ,#pRO;/Vm粘AC 3 0ȺN8tՋOT?ezz1,<^Љ͛Ι^ $&R90wv%]uU{_M#t&~ze_C8`yxLRJC`R=$0ΐs\(\׋d7X`?c3k8\jdd)B 7tBJs<2lo~ FNqD%7?v@Yu\؎O?9pM BpI?!IB؎dv5{I`}3Q3Cc` R~Usq`$^) )Ff77z>V-/ yÊٜq0VA?!V_8$ Y |]77in.9`_'qv%,plU,.p@s6:yJ~gq!I.9H3HM3fc8%Bo_[b c(J2.)}&`e1ŸOPUuL¥1[ySiH{W>KKp> [σ9$5.),*8 I׏] g\ *#4Q08sMq|DR ~pUB7Aa8|2g4DP8z.| XBRrQl޼m׮,u=Y)m*,o9p\qy70&$TE)d1OY BtIRSU,a<) v *# cФ:I?.(FF'x3-Zp.ԑ @δcR#Rb {[7[c [zCX@' =0AP d8\9s`hkޅ$'O3his2JcD 4#6  #bȳ3Tbm$֯gZ 1&|63 H#?H!@$AR>H&׮&HS5098I Q>oS\tM{p>ֲ$% PYa$@ sk~#l:s$=J&9v)P %"́d6=J-#DK8 H̰[`ScrXJʥρ$yt""Mg`=8+OU 1fЩ+ #%03OI$N d,A5{A8˴?<OG$-e0mR4ƞC" C|Q3ۂ,@63P$|OC(쇦*܏ LB,3C:@R#!d,dTH c(pEE!؎쀪)0t CG$[K HB**Ԩʄ'F:K]؞PJ¶#9 Hc~]a +Й0+/A24 ux2g"##o9xp/B~к( `&9(!@ cH*`͐ *[tMp)C(+) fQ+bQۅ=v9;:]fITy+h`N@ROϣ`@{>"T\;啕[G{F~ssԤ.mnOk˚<'Ͽap"EOE4t Nz2?}lw߁9g5ĚcN6ow!.Mg,wen9gI&uҀ@ M@PQpm]W}tn] ]UQ$(EEj4@}&~z] )B{3+3w߻\:i^+"Agb{z~c'grmU_W"=^ѓ!Q,x8DȠFQ@Vgj+/.#=Jko5$#i,ބeR 씿kaiFa`O]W6n[HOO;ڻo5#9MIct$ٝ 5cᄀI~WOOq@z{c]FfӛHeJHKi辮ƾt1ϟ{6Fk,L3 Z!UH8 _g{#mT{l~x6Ljƣ1/5k>%GꮮnX<: PݫC8}0(t0FFF8X6z:T8lJvwf]G^laL |c`Bm,Θ}cػo> ½o ӀFM]]{5ˋȸ1x"G߀S ̝Մx jB(d) O1}+ݽm='c]vB?TS8qh\ COxP#.ÿleoC(ΣǠG=" 3gFzx"t2@\An'G6"9*Qdcm~{顤_!Ku jN|# "Pgd<K?p/ WO_~gû  ;>~I 6D4#&@GenP_crqܫ۷ǿhH4/l8!>Ex>c, 'L+@ \zޡ{z@WTg㢱ƘHB$^{Ba MQ (dRQ7)]7h?FY 17U\~}EH%-S'vd܄@f\W|&j47}|}}]>.oI[N,+|ڟ(B`2h-sGj*" 9}k5wzCw.ύV-J~CBJ ^c=ң5"/s8>'KP_H~m/Kn-hxgٷaJ#z]9XBO8j6tjy'ʳIO^v-+wl+97Cab,i9.PK)>p]  0y?Yk===U&SxJD-_EZ/o ș흧֎};Rvp ķ?ؿ>r喙b\xٍ^[m$ 5GPͺiZ%?^Nh Ynm_=ʗ\$?K.h1K#|-q Oj$1xSƂmwo]~tFHP$ƭSZ[+,>W:}ѵ;tEI޷wiX" ]@x_ [%Y綿;x,k

@ |&_1]ਛۓgzsVoIw-$=._yN@F`Y}8SpilcO}zԤ|twz{Ϛ3#i+J~7](浵H8 G)~"7($ o}{/gڻNF 6RJĉ|BǾaJ9Ym;A; Rez$NN$~7Wߧ!^3= eԢC@Rf5ryʬ Մ4jLޫa`(ܙ+]64>ZmюlrZp~~JBޢvv}8Hoo%y[TU"|t> h¹/+\lsK_%i^2 }/v@u E|4̨C7E^(@~kά/-p[ 0$ B%??/-y ܹ~W^SzDzzhQD!+ljN-@"<{&[p8'G3'PD HwdXrR0^|(Z. #X=X˽/R/s6Τ*?Pna.{= eHϺmSy|4*@"muc3 \n6'jN'zG|^EexKPtw·n%†X&^˛@ͽ4cʫ}|Oҏ 6`6!>o~S(jf zLy#DE32‡<2Ў ʇHW =A>AMؐzlm)'pjM}Q'%V)Sj$AFTF)UNthArqI >ci1 @A+?*S4.u%67 4A8 'ZBy B%>5?: PS#>h2ecF&3f@hJFc @wv\7=!OEM>1 D߯w}˫]S 0^s4 \e-(KnL9;[k+]AyvR֐aA7NN p3˗kApޑ7Pz{nA7Vgڣ 63*|<ґa0 JU_X\g=)-_sWM;{Jj(H~tՏ_D'7oPx 6Rp/_q#=S(9ƭw<۳Kͽ Px NR y$k~pLKw2?cz@էbZmpnߦ庇@|e.+݂Y?0Rs]8?| յc1raa LUӀ$v1*QPrseo+˅j/NHjol$ s#~ .0P^qU-bo)?=2U>'.NúsoJS:V|·uB/"Nnj6c:~J ]$b2oG] ! wOߎ` cb a|]mb/NDJ4T(ʔNP)@P(pLAyL`7OlT]Jǂ/~PPj>39.`BI"O缪.0pHmnM/밊H(zOiJoCݬK]wust]R<1QSS# s.8~(:; 4g2:_!c,yO)XLq"M6=7eHy>!Db1H$d8BoYlM~|$f3-QCW_=[ӴRJ5u`0xmO͛7jcƘyD"!a7??+jq]X;RK/4;7o&ݭ<PHp'Xzx \|կ'$ |;K$W4?]SJk~ɽ7KAO2uV9Y??uvCȪURcu]N8K&txxJ%&KoƇ>_y=˗/?O,] )'u]8sL&"miUxww0۴^Gt]kmsl6X*,3!6ʆ)GϚ5kUierqc^p ]:5_)E}Q+ Vu|wdd*~]o:La7Vbk̋D"QQ !4-8?< ---ǍEnz"g;DžS,bVي.O(|7# ͤ e%A3{/NV SND[n9=iu^*"2lۖBHÑx??57|B; CC/N&Gjo~L{TG?ٹ\ajLӘ8J%[yP.HX,៖d}?n '?uutk>%L1MӀ+&/9?=nS(}k0Nh|uuu7'7zT*{ ØԟĿ!~==VbR"8sӛf%Rͪ|O0 |M8`&R$J'|BmٲCPh6ds*uy}{0 7|3N;TX )q}DkJrs(9 eO'P[:=| xmBxsHUʊkg}6L& 6;#.25R≸ ,y< BqH)qsV  ꫧPJu͚5 MRJ]`8稯Srxn5?aȍ7`abW:O>ڲe9&˿aw=Ow|x>*DZu㎯w?cc2(H2y|re-ڞԪPȩLJ Ç?||u833ΨįiBdmwkpKˣO˲,S3h V+F 47dC4i-}hJc /Ɵx40%N@B# Hפ|!-wEEr4 &e m(4.4~d+)mvmFP¡S9 +]7aqWc&FFBDu{ꩧzlRr,nM/ ;CЩL7a4 ] LW_}5;16:@X4*Z[[O;5<5]2L4RB(jLo\ׅxD46t][i )0kBB HK/ .Dž%;sُˏ2\L\[Cӯ01&5t.)矇SO; p X.;::/nfǤRߏ'0`p\꟫сё8 jbQr~OOuuޢ"9/H(3i‡F+. 0<2XHLg}>O|M." Fc &1 RHB@q]A|)u9G2d{ /r7oOO}ϢZ0 U\H]z)͟!.8ƞ{'nN|rX|7_VE0&!0[vXĬō<-h)5ZZ_xWoԚſbL3+,!+锠p5Hxn0O-}έ`>\ SiuP B`@%ȕl M5w|˧ ޶^q֌Nkmgn6vb,$hs &x2DC76T1hh ҋ3px⌺7m=Sv1աuf8ʾBC"_ݨMilj |8͵gY\wei&Z551Ah:i% ~e lx?9 Xq濪}g-%x QDtX,>"dwPˀF`$R-6l>V^V|s=ı#aPNj̊hy\3. {aιoڛoz{!-ݙ]Ou!|\uؽ}+4Âe:=xWϸOv^9[²S5Eiwf;l-s. _ aێ4K/M:U͝9s+M\|2455-{pN̟%*' ($xm6I[?bWTahc5jg` A 3x:aHt^Y߾@=>c0hѺ&UDF%ք6`Yt04849cBe+nG&;q06gԪZ2XPhe6^=[#aHf :֭;瓟1Zi5̝݆3%b1 ssqfo"B%Af:4?yTia~k3)EN]Q\9?eZ !aq[-\eM{Iχ Y_*9 DL,nI`qKa&$ (ni原)MD466FY:3 0$ڍ1\pZy Ap9*H4Z:`͚5t2~͵8y4)0!I|Ko C<Pp5*LYȀ5X2e)>#id9 -q.TB,T$"u] $Wye21>EG4MϘbz1 30¡jk닥b@}}M*|bD3%##DQPHA> /B5B)|a ͘nAS.|l߶ oY|v L* X<8V<him q!7+SXҐąai.8%D\H{ ! C8hI8,RmuMMM+lkIEܐ~:xvj\چ,Ă碥!Xd3Ycw[O}Mp9\d޿M f6Q$C%F,XZ9e=oa1o sMc8}~+Z4-yuftF1BDS01 LD[&_%N,&N | fX: 7> H T@pDإBX,uuu7NR((Ԅ1^Dցa]d. Dt HRT/QKCM!S(A"pAQt%re N U}񤗉R 5! DžsJ!P9JP 'ŸҔޚz{{EW}^} >.@ƅgG.!5P(XY,G 9)8buQ,Պ_?)P٦(A@P҇ hL eGPB*EbaR}IihPpƜ3ۛR`tr{\_Tv(R$4Abm;c{Ɗ֜YPP<.S8|_Ǒ}خB`PNѶ1ϫ俷c;ahgD M%9tƠ)C(v=2׫_Fioy7k֬9r\)% ] V6l`tB #LfP( $L~e|'}(DT(( eV.+5!,d Jx.WʜKKwJPr92"R*H!4dkG|d¯v%` Xi6 [.veǫHaBR!P%.骩S72Ο<V 'Q)8*@M&$T̡Ĺ gP !R k#a,H !)Mj@W2n<)  _3\k>z6>քƘ E'l~0$ IVbdSm .S~yࢳô ؙ4 Nیi͵h#jnkv0)U>]V,|v,?e}5DA@)bPM5 Nr4)Su76 8˶ٕk( ֠5a^[=R) rPJjJү`ӦM6jk5 cXtB:CSRP)y)J_O:<&(B(+̙V3_\%yp.rQcpNGÒe8B/h4?4 84L׮gN3Zj1)s!jqҡʌD0, ^>faѴN^<XRpd~DP۞ܟϞ?VPB"pˇ04^ @[bAG=BABJH~ iZhꛎ<çBcb v NG--D B X8j_); $eZ$J(4R=L \ Wޛ>5(/TW AQ9PJ Q=9Y­佪G[j?{zzA`+ `0Lb+F>!8GH$dɱM'Lrs9$>ep'_,Z)G Sװ?KPfT)pG.+1@oo'_B"nY;eH_fXV w'jij|ێ**BʞcC6C JNogH3|OqO ({JH-tJ!\ a'mQRɑgn_gz _Wf P(gp) @`#2F6|cg %|O(^M\HyR*!*K22^},2ۗK!b!EE+i M) Eۭ`x,CATɃYۚ$0wiA]5J8ƱqcͮPv}] (H"S/d6-eR)ܺ#9#9ܺh)ڔR%E`֔NE; E!.?r1+C~14ï6FeXBrKۜ/߽{_y6>x- YI)^Ǔǣmƒl6#wCP_zW^[?"~7߻ OBo؀7¶qϼog|0 [ ݇;SݳaTrS(![vo}?v ŇWc/~_{` `9fZ'Uuڿs]o;qk2b=;c_YǶENxI'@K ʊ*(m=lڗ ۇ=%;IaA4ys/9H(]^8 r6}m,Ĵ829iJ yMA|b%WI X_XEN7 @`P`zLCcLZia"\TG)ݫq55EXBXBk< S 8Ǯ @PzO]Yz@5s2#.\`ʓXovKGGR/ϗL^<}}HZjR==~˃!]!;N0(e߇'{tґ3oe3O}>!P==_ܶ*)G20$"y]vd]gJuxl}ߝ\zTTww7;gUNHjh h^|ݯP|ܧMOR{=?j\yJU zz@5v$KT[m $Gg#?{߾}fǟq?>|ƁT D=72&pa$勸?܋%=dӫy7(]/|aUJ <}6lںKøviDB}䕗^ջSozd]M+cLm#1Xٳ!qgz8sRo2:>~Fweo ꩇ)(Aۭ߬St Ӛ⨍0b>ZR܌_{?՚]Ͼo힨J),E - ! /vދ>uO&yqzlM7E9l d7 "}W-AΟ 4X\m{x𦁆6G&7v򌺱h(}O2-N+uK-i/t ~mO'hmcUm2y3:\^1$齃cމҥKK/T=+S8 AT h ^ΟfYj"Ϛr݈5T(l3?';!pv5Rw~!r]`e76]{lsjmrv]M|J)B@3ٟ]s4 @ #P#ɨ|p-yvK5MobgR‡s웟 jVfYC3K-y鲹4 jHQ*[k6F?v&؞xyRj~۫oA+쫝VάA@gB@ qܞ|`H@X>5W;}u>2Ǫ}ꩧfsA(f5$Uy  OHoJXcuo^{JU0/_X'>yo8 m~fOf.JIVϮmcW~_h4.x9 3'r,?mVvVuV;@5K@k6|+9ȀіH_r43mHٳZ'SqS~s7:YAH=lڼ w1 d_7EMޟ(,ܛ߯wݽS_sTXf~)F&wWtaQg3L@i7<:X7G?u{geWW~,_;u#]1? "DA lmN!Oâ[ѽg>ٗf//1ql8x3?j{рY6Z$p #J26nߋb"&͗~)'~;Oӗ#A7[*v}?6G4*slO`p^ HM~/9n4*}{ݽhb(W@hnr!vErrO)QT=ts#޷w,YJ޲S9D61bW*-cq1~ѿK|nLDF|-7ontnAWgF:;gKω3$ h `p[`Agg|«'Z>D?ۻ\+Ϛ7$f1Z z؟*CH, ԋR.aڮݻv^ 6+ioyGP%9)Nka+[Gh,d>w7,!6 ٟH!vpMm$V3 D| mњHp_ o3 JX/ЇS2|NoY1tI uNz\ F[049Dmtfj~ [no_&1 bFpvuuG}[?mߍ]l-q|`0fxvg=z_tUzz;՝5sKٺuh 3f|Sєa."x:~z3p-:U{lݽY}yU]G'w{Y}8 |ͮ|3tNj}O$PyӘ*WFPL9Kﮋ5n7/d* ^ؙ ~gl.Rjjg #qS׽Ҽ;F*l`2>% BA)q,^M"ͳ2"q2 j W(@~55ltx0aU$gS[⋛Z[[?r#y[dQ#W5 77-Fwî ҹSl[Cv;ˣY19~S ^8+"^Õ?~ C*`h$ 权߿:?Pgnd׍QS߷wmg㉈]vUehE t&33;~ W9f{۝}3Bb;?q_Ϗutt|& 鵉D R݋94*BMBSL&;UΚ7247MCLصo}滿 ,]4hѢOb랖=.TY"6"܌l8eIg2i]gO&K?]`ot6~nm0z_[ f̘qG0!$Y#\C5ƐycvX٬0 MD>_N?̎(zʹ@j:dw#]ֶ! ``||L3I"ɗ\424cXo?DFENx~hR $34[:-s`.TzD@y#Ü;lx|TT 4!nPBnPf "= 뀂r"KЂMТPQ vÈ=6JSz:묳gΜ̙3gE "# rdNGYkAV$I mmӧ-yt3Ugۺ&Ќ0Ϩ~#9D!"#Үq^G]̀IU[7 8Ӆ20 Sju}pp~.C8$Kk&k "fH*&MEw4T* C`0իm9gΜ:;;O/B&E$"m."4diZC{{ۍV(r*. !W0DZ)a'~t-Xvi={E`xxHz4MF(r&ڦ הWj{ !E" C,;w3f̘k)1[[`Dp(d X5m[d9dQ;2 +`}?>+lGG\(Gh.WD(d"Hk 1m^s%D1k|L?s՝ttLŢlPkbעQ#dFX yz0G}3gS3NdKCP! !ji8d] j J)YP&ZbfJ>*\.3s%~juOV9ky]##4!!Z4xsB:B.3L:evæĨ/hJ,=7.'hꤓNys)%ۖCC4# €kEs[3JH@bP̙7ta >oO!'{N(B1 AUnRyidBd,K ZDw!|s]ģTqIbp9@6'He9 ]g_`s znTO@;.O1s@h)aX? [Cu] e BИs$#^J8&|M9_v;ҥW )k.&D(EB)F5n+~ϱQoCqr^wʇ_*LmO%@m42IBnbƘ5۶x*"J)jY1  X׀s/suTٶ0 u1Ln{8x''J%d2 )%3  sN4bb7`|l ʲ8*۶̑f6b)b*as=ϛuR  . M'ϫb(1=}z& zG[8={T2H$ko_3BPe SFCL,%e/J"i y"qA%˨H((0ʨKԖ/_9\]ĦϽ%5Tk(~pp'S}\BĦ_Y_n+48>Gjv\W PS16{/=c/Mu;дiMX,l3MHuSsE)y(3cKy(U0u]B/řj}t.$!o^q'Ĵz(E"l|.#/iX% ePɞ-(Co>.1*18[OMb8e"V`Ad֒_u4>EΛ!|>ꁬmQ2{ CsϕWT*%_)1` |X,<8NB̆-䌓Dd:ycK>񵵅5y\΢*`Uzd2d2>[P${JTᒯ=X!@4oڍ75'˜Y.uT|o/ cb a| ށu,s+WvkQ 䪫JD)WgD8}b]/`q^}B☎7"'퉧}vP(iiRVnU7jBsa6J4r'lEصk_6S;v*F.?F=σm|)$Qi:P׊ {48V+@2  2t N.HWWP4񏏜Ek720z3^&ڿx3,˂i}e<K%J)4|?σ⾵CLHWwgq+P(mpΡiJ! Ӵ!y:~w7!n\?؂if;|ƀxݲ!DSR*|)偃dT:prp|@~p4jf__rW|>z`>$>>QSdyr#%Pg|\SElJD=?x6={vGIJZ PR 3cǎ~Tuړ?s?şO~8Mlr+OCP4% ÀbVf۶|w@*Sz':SrAgDCV(t35M OUX➷lۿdm۶ \?şO=_࿯ZJ5M SJE,DBB!!s߲.]\|5<<|H[)MROO .YW[~q4 A RPP]cֶ) @VS)rmisua_s04L<0c}(%yiL}oWt9LSWSz'"=k,cZkMM}R? T!kf Oo>o}Ϗ)??_{ǿ[yt:2-pBllBL&ˆmw뭷^pP{@E,kQ0RJ*$RJH)oF5R͵JoRU}zKQrȎRWچ3U.Guߒ5||)%ePeC.B%%TD*eީHSzDS8.#)hrI_Y%@iPJ :I"Xz4JAk Zu!C)K @ ]/xDIPJA 1 \TRRJ(B Ee%F |5TBV !hF*R\Y&R=Ŝ!DUs|>M h`v•+3vLB ho!P;!C8` ho%?.`!BA0BOO) TN~.% R)x>WC#,킮irغqN?bzm C\)ƴR0lڴiO]c;FeXhnꀁ_\1 zU)>҈dA).F}U5l޼Neڥ fNԄ-|+0ǥ$G0)%Q"v_DytC4M?H@z]Gx٢K)ۗrqP馒 C]Sqo^Z$3EU |P˒l6jX x_[_"4PF+L #k{}Y|PZvysPv\26+:-K5 EWi9p^@<'x^xʎ \N%g`ͺG&XsN{Qm[)!%Z}t#f޷]iPo<*ˤSaBpVlRuؼ{T9 秔MaqC^ƶ1[l 3bR)ޱ4tJ ! Z/S6! {% ֭F򼺃PB,Į^Bע%Fc ] sp!dmm66:[ogzkZ55kJkeʬdIA Bz,@  8Sx8`6˵ق{𭌻> L`__jxœa?._KM^gfB*XU: DaWDb,'L,a0 SpQ|PHK. Mqy\r-vyebAc R$@P4@WSJ-gK/XN Z-]ō^G.u]]H<.R6V(5F17 䟮=t}C$ b+z^}}]hDoϏkU6u}K]̈8s埑"2TH#r9_[$ :Q% Y 'Č՝PǒG%`5@LC8iz#w4 eP %0)Y{$wbX ]غm!`At]s۾9ݷ6kJSz'й]?n-F:%А%u rr@Y@7d:%؃[[O-lNZeMaoVqM}262y.S20oTf2IvO<ŋ˟ Y3k64x9(tah,+S ۙ5^=TW3;.?.hh7'}#[(|їip}]WL`OIDATCl^OS`<͎a=0SIxCWn9El{0sS >.?7.~Xr՞paCB Y2AQ04,d@wjXfMOz{a 8ahxHꖦ97Pm7Ò:MʡFF2bZ$'E OeWd>? tQJb@VsL~?BJLY2pT 2r'Hb W2FUv\ L(}MHy+ivRJRawbA ؞dFx!1B/WŽm[9H'k|5 cI}OiJoW=mڰ,Ss/è T"-z{xwfRm:9gz\nħ6tթ/eJۯ<]mZ*Mk{g];rl>`Ysow\%=;Q/^NvOmݰs󝟯ݑcXߎd$>e$gI@m1DOx>٭*Ӭ9yWw7Օ?)68* ]aq|el^w\~SyW<~׬Zuevٲ}&3 a JfxzG_w_tx#o|tОxb}ނjft4 uc0uO؎C~FS5#e=Ү0Y@{'Y_48cZA_zƫo`(W/oemR}'ڪ'l⥻]Tovr;yҘW.ҵm/X蛔_y :wsX8t]R1cϢ٭!˩t `K/t,'6lw4/2X04[p8X&(1}n#y[3 ;4+s,e;P0+(K%t'"Մi-^1m^] Lu=3< ESfoݷMxocYH0ՖrJL䠿9)5BҚ\}0A94(<7_H_g&sI)eW}GS |+a5!90B[kB%yίdI ןH0tnhr(YRi.x#o˖"ls|Wti&-:Kᢹ30=Altmvm"qn^h8- ?ۢ\ MKeyj[۱xY3yӚ6B8T [?/\6cIe1~SV/p=G5ϭC]]i@[kdDc(7uMH|˯AsڎH!%omӚjaYy@K]ah,$gj}ZښJkim(FI*t3M̭ MlKȹ./j,cOuaC OY+Ĕ@wOA12lD0X i *V@Dr\wRM!H-S@ @DpX7@i0N8?R)p%G[7LĹ4HYy6k,cɒ%Ϛ5kE\CCC4! JuFDp(B+3@XY9W8Gb0 ,nFzzUd6(%k'(]o _PgleFII~VfrUiJB!¡T;Ϸ!d儸idk JEa2S;;){0*SuCy$(g[l, l , xa4DI%&$#AGٲdٲ%9Pgdɒ,]GsO:]u+؏l8߸|s_j I,ͬ.jx%|U+*o<6<^uÇƏv1yQJץG7NW.7|^ J?:E dT>B+o\'}6ؒuA8Ig]kמ>f~I (H3`_?:E zS_HDa,~st~{6O]v 3g|0RD"(TUUqes]w R),`jo`t4LCJ={w_kc_,hYtVL)=G(9A uAX[KE T>hK3&uw:v$-|ʫo~U =?5+a2D"ᎎa}4MΚhls`XLy)mU[C[_ r>~+1=sQ߇y =cƿjO;=?%D;L}G'8~~pW|sfΟ7Ly}r_?@[sq@-,]ହ%4u fo`nK;Кȟ-fN۾`F}?fN>}_߻ʸT~ۦSճK|\_}~a6-o&й */}]cTs]؈};}wpjv7Ѕxx.N;uw0 /u<}'g%?1/w6R= x>KpF9>yp,7?{V2'a gy@e.8T=w_~ۗ& N8UG>xSS<7Oهr~4UkԶ?Md~>gG47><߿jA>PmIH]O*$>`7o }F{Xt1 ]e&8\M]p⽼m7u&9T725RPcyej% B5+ >Rw!?_㍆࿯b"L<>]=\pw}qnE3w[(Ƿj0@Bn$h[\?c6a\y"9?.-`SK훪:K. T(_]9x#~fc|X^lX )6lR֙k|A*#vs\&LKZIQQ;$ Ss$jv]m̛KAwTvx_5 u~No׽(=h/E.^~FкGH?H'|1?E1kl]<^tn=uG-ߺM1{gN~ywԿۀF'ېZ#5C=:?2=s:NHRd_ u/P1{aRy8-~<݃_܄TZ3ϫooiN?G׽]at\o]0Z[Sno+C㬣l?Z׼NGЅsu\G?.}uw~Ҿw/W??vIsGi=[_aoqe3·H||0@{@ 7,VfJL!voc|56A|/@ +BW[_607q  c%to[*`WpexxA|@|k,+ DvHL;D]C:Bgh.`t+GnkC>xji]\W?cB 񃥋hxqKH@;'ƏL\<ɟ;9dtdM+@i/hL0)yא'ߒ]Z12JZb0VA*‵VƏ?b;',- Qj_; cZ9ᇣ:TcHcBp߯A$1?v=[_ t)~,R}?M BveRغE+|P~8X&L\|aicL ~Bt 4 ]@𺭁F >™2B/ _s4coGHplc͡Q.bs@kS@"Db,?>Ïpz*(a 1= J+ߊb ޢ5&Q b46l>lC'Kb;5 t74,\q_c׶v[1o$&ϙHJg(Jb&e(VE?MR -k|Q -:̜64SeQ~>4%a}- }~A ܄@ahg 1:bRB Va*E Y"L)|ChAZTVWZe(OQ5 T24c0r/0MEjWR$Gg~~cL@Adca,sJ P ]UzB#p^ @m9,?1N.(}AV= |a*08j )̆F衱wW]($m^  G /0-8VVwȶ?z4H6,p(m|_`+ 2cbBs`p~O1U6kȀ FRSh_ LM<)7$0)KM]? }cO1՘5JUѻ7F> ߵ62mCS}YQG;J]iTcd"$G%1lD+4?@F¡ e5>h#8D4E\]1 u g}Z˦u/ 2 ~s_?w '͚=O7W]s"A I%ap5| "* zs"|܊{gx O%&'% 'p|?W7l1Fz߇h7IOenGWwPS,~'`&W_~x~ 2wz-nGQ}ꣽ4 r>&}u65e}{7S,:TVP}Vtu=I'VVECc#Uji=T d}: ?i_~j~f6*atƧLB)KI?/g{>'&5Bp^6FXrTnsJK5Z L3s2KwM^c҅AN[*߮Qa[~nE' 2Xzf TiZcO33˺rl\6S'MxUԤ|u4NA\/FF޾,m#oINH>pҙgVkJj|EO]D:՛xal;E YҼ3KFxi]+RskN:oe{јxVv]My9UG2QMi–Q|w-KNJI'OiȻћrjDfƧ ŃG_bJb}w u&ilCPY6cVŸh|CEM# {L(Y3HXAu;Z`&\_SSS'4yfvշΈ|sbl[G3onUלAYQPwSnk{M/ ~zמg59/|x~F.lU͜__uF * ygQGsןx <d~]zՎ넣Ojx*Z%w[=}QuV6TVTPYSt=lӠңkl7=ǟ{oTZ:{.c GV;(^uѼ.>9OgưǤ<79OҊї1>9ȰMm̑z xm?_kSdmU 涐NU2{j#[6{jNY0aZ+˯-!aKʬ}AiQfx**"̚Q:h 7WHdI+TP~2̎OVl՚gMIWn+ !ШIRN)}$>&A4BщE}MjM gS'ZkCІC)" B4-La?&1t={Ƭ1:IdwβfWW]SIN:@xI:C -8Q:}hi$Cn9X=BK鬋&ZK.m6He4RgT&ofMx(gvǶĚ䓣~ݤ)blSz!ΗtW@)Jʴ W Wg]*7;YsY=k&UkooDY)e6}&"1JZI2y)՜Ih̊GrVe PؓhOgkRYL BD"#z~]GvlV{䲊JP$H]ū{H i a$9v$S ꪪEۯ+{k/6#OGd4A>X,G$ zpYu)N'O%PݶiBѕjC=W^GEG.ZRj|A1<'W(=kPaڟ/S0s*'fOeҲ H, P:_Tb8-(Z dGJWx"_6U7+l"^ üP ڏ b$]<|-}CEU/j/!TNwٹ@v4a?]0Zնd p=m9ґm&[؆'#JV~4`~ց]㬚* ml6Mb)فR l6O6duYHw*YۄhoM&Ʀ:~X !d{A0X|E!tښ4 4΂CO]<'Pt\8Y7٘{ޣPZ~Wq 8|muDs^65k{Oso=nqSyslR'=3 a.M6+b 2dݔU=uZP!>f9[/y©OLmbWt#!L|,S/3֬]bmusss~NnY~ 2kN 't=4(]ܢK  |Oa_i?=7^YڊbeQZ5d8|qٟjL_wzf|e¡Ɣ|m@?tO̻(PgP٭ҷ܂;E?YWS)LWXA&_ W,R c&RR.^ڹROK/hZ2+w;rӧF4nQb4nNQ̹"VP8;3c[Fz&`JRWݹ_fug_y{ymT&5klpσk3܃i!wESϘ6IlSi8G"%  pw7ze?n.TYg F]NXPӔO'U * hDir"Р@(@W7|$iV^[\̈]GJiHXMǰl% j= !S&l<V(r> T@)i/demY#~muxz5pCH|pA{vObyPtSJկo\vsƆλOfꞝd{^~9[<#m龾0}C@E4bP%]W-w_scC^ӫIw[[CT{!Z+P.@kyJI7~_]_wzoŦg7|K!Q,SRN!|'õMuVfޝۺ_d2#݆| J_PKJa c8] Xg~Ͽի*:ؖdҾo*P"YR\#.84g76^!=)EWxS8QV GObŏ-\(dq%ݵV4#_B>rKO$b>#`] .:.zl$/Ľ0q y{>Rh X/n! Y^KC?!4{wlj*ٷs3!Zi)Mq\|S[ie~V5%j:qB|i߷%Jw-H3:_t}5?~R?hמ}jq Lzwm߿3?_JmmHÔY) (@R S "RZ(_tz ?o^;_'Ʒ6ҩnY׃bb$\fCk]C12!n&?岥7XKmbx2BkAE%By(-^154_6+~57w$Rr̐@kVa&Rah@l&3J\vmm|ht)O8v4Q~Vӽ6œ1,wN,W.3pvWʛHtZQi,(S%j퉝'e@B韭|Z &LPͶOr }|Dpog[?~>hf4UP$VgLHUukw:s'r/z͚%}U{}Nf/FB)+29#CUE>Fpᄑ6/mIʮ{fc@WP? vy9m2LQS2娍̨6!%l/ Xs5j^'p8R<(@Ts}%}6~jh5DfWgB5N?.Oϳ9yسWbo]?ZLlu>4:{G<8s~+-4;vقi6#v~ƵvZ#{hhah6lE@ wX_ Z}hx(?0v+&ط[o3(gzeQ{NS]!{hS@FzH/^f~{;$z~Ry)߹fYUgN)Uן떚PZuHI}9&SmPTA€mm77jG]_'(cQ-z00ԱP!FHeE5@$`3 'RU C?pˮh?k7=}`[ގҫ1RH컞FmSbm.;I?\5֎{3ԃںvWbi_aeM t~CcmK;w/ڱsoooW̥kծN"xz+Kf8ٔ݀h*ëڱs?`BtO#?.vDމ]6m-&a!N^8j{6?out{)#ؠ=EJ<`7wz5~);#ߕQaJwiS>k26'@eZ.7#C Z{ӦkEY4Ȥj_ZxŬHGK7xTU[b7ݣ-)M^s]t &eJ#z2NkGGfKFiNen5>mbM٢u[Rx1S 4{ACh42c/^|tkD2]|TӾgpeP JkQ(D:, ~筎#K|pӅXͯ__+do"F–ɾ8i!ФRi:GRZPb ZC3;oJHx*{gwGo<(|%wKy7 Z]<+!qC= ׁ̡Uקuqu/:4$8Ssډi`IhR幍;󘆅t')K ŋޚH:PbmpNqqNXNydaSpb8]} cZ1up\Wa1F{; %lK xH)=$;G8*h_+9 ~py׼jXd.e^* uW(,͛OϛUzig~35_iR0Y` C_%ټ%/+/qW(Z;msIZ72:w1kKH=8|奦! *M4AϘ,\JL ܝl6>#xذũZ( 42+Zt ^a!Er<'7 hVxk磶ZkMQO ),nWzcF+*9(|]~>d3U#4JQpœ |O`-]ݶ\ *>]Bj&Ex6J|_nkZ+?̐TQQ@/Y-c7gP~X(|[ֻ.\h\@m18{.Y4ai?oMBj_)|'3 S׭_^l2CJ[tɤOWY-üwi?ME ӓ "]kDڧ^hg9,9i(sUϰ# IL]k-5Nߜ4^! CēbR,nq|ʢUk-F5קN˟ۜ̃."qXv+3Ndrc90Qʧk Ͷ]{l! S{[b>ZÀ8ٜitѢ3v̩/9*4yo_J?HLiIe8۴F /H(W,Awe+k?9U7gԸ~x^QcE_*hoh8[ba@_;enkmX9p.|ۧrۻ +w;U0"gvc©߼9}UޯۍPJ7[O YM3\]yoώ_mL}7}Em#LN?: M׺nr$^-M~~/\/G_/ୁsƹ8T|fW6H:?ʏKtyH|nfnYO)UNF5z\&q(_T\sU{VP"^Edn<7^|zf֯'y*7_8" }z?PGY+ ,o{k7N7e婎Gnz^9Z*r`}:U_2,ZjOVsWL cRx_zXdmb⩻miݪ(KX%Ԣ|̗?bTE 3^v y-SH-ް|ݓ~J=tٔBUЫ5iT_Sg]H&6 H%ɪ3\d}{X>{g{hg3Bɴ*Yl8 k>FY-șuybuHf0"2L~~ww_Y0RwnuU1W(jVZ&ٍycޜbۻTnj3-3|^41v<#нR-=+`wPSB&MAK7Dl沈lݬIA8Z/OOOdڡlzyFgV"6͸הeh ܮFVsHX͟6J2]9k/+N2 Sm7x;6H p. LF hb@ {WtZt;~a ׾nm6:IET%TbȉrJE乢'_}?~ݞo[yw&ho?>rrŇЙba[N/m\14 ,NǣL WrFtg eXA IuEҜ{ٻ_;]Prq9mb%5qJFvAkE]3sL>//N?9yywϊU|o+~ּ|]@Rzn?k=_q>#h:gaiM7;̺-eS#O~Ww-S%@}j׏-[ioH?.Q)Y~4P)ӌ=U) ݴvY"C3pï;+Vjō1j! kN bеRK<-ornKU w u1/I=oiYzVm)5mm;7\S(pRrNJ#'nr6O,=#BOs\34Xpv\r‰s+^ӟGW\T XBc AJsHg_YCLa;=Ö̟\79MXF-^o"gFTHA]MϨh aO Ή 3]bƓC/K{P 6dl[7;5|FCsYUvfm 1W3=L&>)b9GOj1x;g2lݳBi8ʫ2Oۼ3sw5v~)G(etAC[#X'AoI;|)2O[vmNUTjj*+^,dUW4/XرGŒx'v'e>է5c0a^sz=H֯3#ȶm-Y&hNCW:ri_Q^fd1+*/R%M֮B[}t7ִURdf%,tIa=13MF̒Ք]Տ̘gZ^SPUhDFRYXqX}*CXO^?9`!ؾslqq; &w֌N]zVמIka21\ɭW93xAѭhsw>^5,if.өk|,w1mqvFX5DU.MMMsqq_65Pصg9Ɋ;9!zڥk7wrjq 'u|eb {Sc"CIU2Iz۷ X3ƿ_mEߧc19+h`{LeT|Blx<`4%f`4dK|;p_:3WLkEK 313IIG1:<_` _Nr~0RN<^eySϱfTVBZ#:-dbF]NXwkrN-#*o`zb<.ohd0Q`ہ{K ޻0RƇ>DHrA,W'yit!w/ULNIӿLLQfaEF7LJ'G11S¥*}cwnNpf j!P^~Vic0^m<"T]0+;]s f[i2v2܂B UtavL?q~;N&ͨ1~2e'H4l߈k_j<?!GU1; 3ƯtUNo.F?GR rUlUzC00y8g'^sPR 3^R6 M߷t#9qԞzz`˨z!$ VᘭzHA{qp5Hf>,cS?B450~z`X)4Ё{%~.x/aOb>?S-P/ ht)v39yA#ÎB6Bz=߱ڽcl@ԃ>"IFO";^4Zf]Y aZ#f1R'};Fz0 h[~Oo/dв|U axF /?Ej/Y#3nZLC!ZdL,ajiB+FǵO xf)f03LaNȆtٮ`BkJFX@k",%҃ǝl]\Ao ,5ќk\WLnxF(D(%ȿewn5V6X!,k yDy܁QTM*ض_B.j+дo`E(cd(h!mh]xz#$k xT-b{/F|]&d0@ҐP5^3P"tqr{b]@ e d~1.N,vpZ=c|w 2%dHf:Ӌwb)hEPi"6QϟiPC Bk -=#|C:pAS 1 eS_C6˩Nw8T`$Dд(3 0Z֞ >? NpZ!nWWpzX$d` W`6_M2P0YlurBYTgpw'fc[6-B/b * 89}r.t,I > iQhZovI'n>"HpPZRnME,P#G|dҌ\ҳԿҋoGbK8w[OV"o"Vyx MS̋OhLOC A$"HwD=X_"-b2KH8,-1Ov4I`ؚ'PbfSeEFF KK|q^"z8ZcĔ0yVso׹4A$"[(q2y~1''S$[d]r<@{G>)x0u1` ҐDcQ"\xN= q,g,Ć@ik>/YPO#e)O '>%RZg.=͎c2<&/HaD(}Y\9+}qR;|]}뻢"P`ZLֻ? f1B6='J?0~Ø> LgbvoL? rGv(́B)<4a"9o9Ag_Π  =St /?cG5U.J @(4%,F*ARSOцF L2V3o%Db )o5V:Hݺ %vAYs:L$kjgj40a[;;\st7aX5Vz4r2w:&I7aLd~!j.g8&;{/[f\lBhZuYlIΛ7r2caj{!|S.PhȺ<m4 Ck[ytB(T1vo}` `o/ZtW6.]z9s/L5Z!KǨ!=6?39]B .p |- ?zvbl5aݾͿ3:χBlaOc(糿i_̟>!U',I+:Bڎ·ܦʉKD>W~[] ~4/N~;z{_|Iʉ+=e:~b?*&$s/&xM\l^W\lj9N-N5ۿ\s0?XIuԦϔ}u_b˔-~$ߝclwV?28qɂgD/*Z>;5$?.O5>2M2?&}Əin?<s'`ߟnQ q8Sq[,>H=߱mxO|"pP[5F.X,4M[a i+;<2}?d;7;̳SS[ᚪ*rEmY&v ¡0Buw'Gn޹sW:߾U:gjW^^V@[%p8Ұo_P| =&@ -YWW552 ضH)՝h+9lN MWZG}elbJee}㒷*w/< W*Qw Z )vW\At&W]R{;D--<gPٌk|*+9*R:zF<ռ}ʯy[5ɘY/&\@Cwױp'q'jD Կx'71aGߞKX&cFh/%~_`g$?=R)=wt' zbmmmrŊv[4#l֝5uO칖ܩf"S2Iz1?uƆ"YL/oQz%}5\^Vl >{xxN㮧D46MǤϢ}C>Tlǖ/3C/)w; h|Gw~\B#7I~{+}x.sý/3B/iz|]B_j⋷>qXaҰULz~<>? p($,J)%0vmH\wcŊbڴӢS*lmtF|$p8$C|_ҀBZk˗/:ԶЫxfBUOJJ¡ 4Ҷ}%4=_ꎝ˒a[λ{Jk#-~(<}֧FW\r%b ZH??|svEoϗg\ ̟S]H>6GVxiїNR҇ynэz'~m[{yW/ߑt̟`;2Lroڐ0CվIԪo)5Lclgp%iNTԛ/|ss&LWuGC[[BlM?]#~JQX^ae5їh~qo!Aʛľv}=2jh ȹgË́'穮D_rOH)V[[)\ĖIщ ۲ ĿfZr%zS-I'v369߯O7GF:J:SZ[O)?i'U~{{S]Uyemu d>_bxxDȈd2ΌiήOSk yܹBch4,k̀ml.?0(FGH|ѹ\֙9c߬XB}>Z&O8P}hy~}xmkېk <3G?XP;(YlN`Ի1-skqqfQ 73^9Od6:F5cqW'%5eS_'o}cTY`괫8[?a5aO!2~'2Uu Gwur&@i=a;DŽ9#̈́H#x"ts/ ؃r2o<#y޾Z nk+/vڴ}[ϘGfE_y'x^rs2Bbap̨vLv/8P}LjIj;,{aE2"C1FU 9ɻ/m;>T@Os [?MZ #F3!ҹ*Qt(ZYL.\Z9(eS(u5r`@ 9" ̆a3˰$PSj js"ݷ^?ʕ+5uklq\pC Eж0M )ǖ ZcHs<ܺeŗ\V\iO"::l4rli96=S-P-K8+2,6ma&4KuM/˛۶<́52`ۢ8".6UK@cuMӏ'ƫNX~围ϒ֧K)meaZ&a m;.o{p&ahX_5ObR.OXYXzAn$r4~gx$"v *^`S$DKڙD"5 \N)g!_w5ص46P$BGg/Lnf۷}qȎ&L򏫽l0σ\z˹:}/0eTJJONi̞ѷ$Tʔ~KgMSEj*jsU^_1eP_%!*yF97 sV\ ql;U.Vh8᝼~Z3s ߯9tڏ*\6i9L{<6V"+4b5pN<1?r/5L]*HB1MNXFdZ[rT)eT=cW8D1kt~K )h uU 0TkhY_w$qlWQbJo 2Ef_|PcնPHP[[+۲E4E'h/Tu]} |_G5hMY,aZ( (]ʡV,m+;dFB"< ^G1-MhEsy냐@`ժUoFE8\ҧ`T+`h!58ϡ<5PHYYs>&`j! tksښ* "⻥aIl&iU`e!ӭv֏-?䗿`cufZ Ωuea Go`X0MT^\?`F ]í!ffQQ빸JreXE8OlKXG1A0 :]*jD. 5|.^QӤ '8Ej|!iI(`aj`:S ( <dBc g2w&6Ӽki4|KO l CL8u8 z FQQ>yB^;u,+ezZ v̘\KE,D)h~%53yd2,L;wd؇M1 v IyȤ: eTGl 3Wpd VI 4i֚2SJ¶EM,*A|pJXs/"aG7k+V|?@Ȓ;Ca/;U/A1@я3z@(MS 7P,&'h("hF)!qܣQ;2Z22 6Hgrx~ /8ZRe`1F84 KB FL30H@ MK%Q4 acZzRk-Xl!WUU%|BC!h iXiPL G k%TQ\#s2$Svcm5!z{,0:P OC]aI:}d;NTnR1gMAuD #"CiMsMSHʵO(eDT-GLHml4X&j]ڧ kyc>l.<#67xRv}R'Bl+z:HE($2C7ƎݽqtF Ҥ,Dutq<H m0lfͼ]4BG+H i0˔4Ԕ:4v2 v|֬pK.<;bpCSjZ][(b} `@FrٔO!d*i{@n]꺮7W3ʺ܋LuiSϽu/wJ\W-y|sE#EL4 g?;t=\"H%_ԩt,¾Q6tvn>iv?fݎEPh_|`7Lgs ,rE>e!]eBZMۃ]´$W_$W8bo4T:ǻv&|ۈBu7lޅ|ldwk7n/`<2)ʗMcÉҙ.R. !pIc|GclD J?,Hrts R͸4!_R "JiL x}Y,Xi8>i(0"֚dt R'X)4y1q;noƖ,Y"T$]<@6[hB0Ce^HoRJe0g.^!_]jst;{7ßy-B!=~u/toyp[%7YPEo` =Da~Lj %,8={%w}Zs'V\inZK.e{=:%P "!E{{zr}|tҥ?=@ >zonUca0)פcs?<k~v<|ʻ>a>{E=_p`M}]9qWQ4 +cx5Օ1IUז ^o+n -CB AؖFL\_ڈI6BTn$AC˕N?*˒h0 *("QU0AFA]ym"Ѳ|U^iUTxr4LC8 ]TLjʱ+ Js,ih~>5GĦj&4W֝ ę3}qEfNm">o-ul4ck `%tY$=<%ez5@(T"Acij |j4UQF>}Yҳܣ^eAʐA2)M]SD-TGLL)Վ?2MA2"JkaRxOM,EB @}vm͚5 s~ݜ-_Y 0eR\zTT1r ݷ|C[K~$3O}_Hf7C}}tp™T7骈7_sɒb/^}1Q]ެyg7ĈD}sFپ O&yIY=q+j*&|叾x~cBC  (>0`XY47VO5VVv pto;Vh )aZcW/[Pk#[|+`Ŋ6hgSgNh5mKK!e0^0$R])4mK:sBdhmm)/gF46RYXϥ84)6'M(o}93:@LlvUր)!,.a)aH!!u[3@aMPqQ!5BFih׬( A0hށZ.Ji>:XiQJɤdhJcB"MN'PDk8WhIe 3d1Қt@*G)|SDk|QJ* 2?'1_5t<+dL4 2"|`lF q,7m+VY鯎Rli6eih"Aң%-S &!V{ ˓KbŊΗYSu6fsē)# QC?4J$`PQ^勪 %CPˏ4!A6W$) /&G:EmLąwRp9>/ R{ /R(X4%E#+bjQ^蒛āᒺ 嘦A9!_kyC@Ye%~&qW>ز5?ZޮWXѽ~"ZJgKLB >4T}ETfc{4u! M၆X|yREWQpJ+79Sch| D1M".vT!) N"}E9m$T!WAbߤ)-5R֏4@K:@߽ P$ӥ N;nB|瓘ﺤj*IRMPZa qT"4 h>oE ySiBe1^KH/8RZp'"L)~ eN))#K|I鱍њϩ$~`? _ZsJ5>2<'K!RBpΜ)B3Hr̛]\ԁvLt[rOOykD-tJ&?}`YO\4G"P:}c<>km95?)天]Zo4?h?I$POwwp@Fysq{JC؞bgTԮŦ;yұ1< Z)t4%o]IXeʈY$T`9_ oi58}މRp=|o;mJiR",mYbEn}?O*]n fތ2c<~6Y8!̂:lJcJm9Ic 0gk +D/%ҙe\aVFJ!)eysP:+ڄ8|mm_ڛHr%S(LckTօ3J.db{x>d"]Z)_K|J) Y1rP2lo2h;b.5542R<1D4p@Hc=Z6FB6S=,[P4 X@hC(Rq)J7J= .h]؆0@Rs]\.{x}ĨB|֠4H!19VNRLfh8>MQ~)HJe TiAriDXA(@+*XQjA *]G=*V~WR]HWY2* =S"8ywxH]}Wͺ y}Vs708|u1%M)QK`XPD"("{ڤ \x6k&8VzŊ6dZ XBchӔh^[au-x\8R b,gI@h!e]!4ZBI$hkCq֯w .@R2R+L~n2}߯޵y|?qA6U[bcsk+V!LhoCY4@*S`fka'ҹҹGގj[lX{VD W+'({coX԰  DlqVWҨw7dS!DK!,in6dI4R&l! !E LT`{dui"ctFOE𧉔wdll[B)=>~(kgLƭ%AX4~QSYM3|c$^޺2FSL l,1%C.;L4B 4rM;`قZr9C7Ei,~&!8 1qx`!l)fg'ia8P@BoL |>NCt]v#*?;'pDBA9frRyq{F:!j(dZP8wBRq( ǁhxИj{N l |)v6׿V^Q{,ۥ?ĢACv.?'̫󘮨ޱ{;bMەQݷPS) zv# @Q(&f!BԁTm[ju{B_ ;}>[bpA]Y[Z-{4EтʛjKHHT[rMQ=c[[ZΞcv)-Ϲe,cQ) !iH>K \TX{,){---J-cJ5ˣ0͡<8%DK$ R ]J\l 2adadCEPfbՓ!lQ<<.teh@cxWC JT#?#G$~j< h RNYqŲ]J*QۣD戄 ,[$ǒX0p1< HQǥp6.('48*%rth.E2m"6P]P )c,gʴt#Y:PKΟAxu G)$8 K9]9J.%U(9_}cI@JDCA4UƑ0 Ho9Ou0v(ϋ\_U=iްUmWsk&PUAM7}EvM|$ӗە޽vU {s<.:sJ AˍEvu|u{J﫷l ꊪkX$PS]HTFd6;J!~(OF&vkjV0:XUQ橊$2[ZΞEٿOtg ꣊LRQS9ǴmV6ոy0HJ5`lbcV,WVߣѹQi׻.Nfw"5r-%*X~eK:e -xl.N !]_˦m[:,fhk'5,!$4WU Ƕ-9";xuw@i= uwq˖-F#1v凗&g-)$c/5+$ɦڴ@֔s #mלA{Yˀb8\'u l&}i ˣ2溶ͤd>J(C'Gj|.d^O_򇖁KFFulmEiy`9 ¶R45ï>'ϭ1ur44J`E>TRUU/:0#Aj1ueNH]i u4708cTU7x0>noŎHjesU㫂U$pOGJ28I#ꊏn?OYq G4^*X]s'eaNb"ҎVbW.{UUe -B( h H&G&Z/OtG9G㷶v%Ъxi+^ь$Sd=_nmm3kZp/QC=/޲((|WڿvWG)W8^ƒ|tP@U5v_S_o&זϥ' Y ux|R|+J~՝ύ n+tY7}W+֦ vve7"j,V-߼q!*7D1V^9UhܦYgc\ 3#:/<5aK~_ -ZDD*o~iI0/ݎ2Q_"2¤%o,udX(%m R a+wAsh_R֫5[R-zD6̡2yY8v!kX7t9{S[>w\}iX&~{`f #Q,oqLgUweɏՄV{X18o>U? t.o{7nA!YlW#q{+z= ;>M *$SK3u?FߡiԷOSB(WnIq|槟PuRYx͹{s/5?:S~>NU5>F(BRʼ9w}Hُ ;9+~FJYQ%^ AR( Xa;%@:QeZ[۞A(Cڳo.l9<^eLb˱ hmmpt!\XJА* E:ʸꗖ2Jkp%jwRIg31]pNʑOЪ TZկزe 'w*0=>)|L:' Q>.?{&' >"7a|!KTt05 ;g ѷs7/Ri<ܱj#&*!}=B ^ʣ?ϖuk;1Zp*G[b/ ]sOXZMad 5./=_Y-:c?x&֯ۄ~3NB/W#d79K'Ow۱v ,Hҥ'_htK1OKgyJ iǽK})UFc⩝Oxukl? XXE٥sJRP~)rc(+{OD\г}),3{v֖8Ot35!TY Ù*1 9E `ӂA1wuEY8 1: c#8gIGrձ^4,Iv1',1%<ο!?8%\(~8>!WWƴmU%;F| (;:E|h`ur0>Z. b8Gh 8Tjt#NHBd֙nT "y6߉w\sדmOş¨hIʪ?ُ韆<'FHȭ} ě]7ވ88(Sp- ջ%m{1H;3>5D~)-Z:J+*@~Kڹ >q+V <;s>5,s7ᄓNo!Q[[ u7b+q3z$ 'Ǽt܎Q[l O~6XΉTR`  xiYH$SÙ\w}yf^dgKfG.C2ޟ~g׎p >\$I}F1m<;߀H%gc *p!7-$\[} 7' !8$̇JG>[_!A&֫Uqj.mlJw|>&SQ*~Te,&U!>AȰ?)QcI *rS$8lb@ V%oa6lpw P%y>+yp%vdZNUr&ʉTFJI!ꪪ{ P<&sI^#[m(Rr J woכg=w>sCԆIވ"jF%|cXv>edW2+H)$@zYN,DC4QBr 9s?r)RK L> NNHJ7H>/7ga.Cdqg;$"~Ҁl9ƌD7glJ$74g Dd1R:"3g|)"EmͣMgB4:4>L egz< U,E-,<)H U䒾{ǠU'0ywwB҆y:Rԝz1N^$*O?nիي'><*2mι" (T&,%9j4|2pDqo&^O)j+d2磦4R{Yvvv?fjlsKnP[]!S9G<0{58ԛtOB'l͚5'>73|嫪ڪJD%D,d@Q]1oNs/-_\Yz5VX?hljjNꊸDΕ P7>M lǹrMWWU %|_T>D0`*BRDB.ʉ G4\EHyxϦPy\ ЦO{P|ϞFy/`efBkHHZkC\ J*4BK )T) zؙEOg}(π Mi_B~"b |Lozq;n STb]Ӑ-c2Pu Qö}\b+ xMUޮWVfTDC:l ψ_L<**|u<'0 pq˄tU!{!<00t8) R@U|i|*}?<Ɛ7[@|ILL1GJ4Fv)QYio^OK)EO8c/;K[[x'ߌ P M1[|yMe뺮BQ,˅](ŒcLrA`-Yih:>{w)orηrMksIROlK|eYSX޲g !Q2`k3'>P}BJ29?{ɪU^#\xc>l=xqvYx׽\xC]/loo?Xk!#>s}}qFǡ|T;\x\x]|.:)%{+\R㎮]U>zC=Izjo]E>f⣽88Zz߅Ɩ,~ۖxۜS'َi#q/"V@Omy۩5o;̚p|#@?qhWwQSUs}4)IaLw=l.y6.=~uәPJӟ768 ^06)>ٜy.U~k uUu 媪3t||#o}ƆG#KcIsyuBu͛ݧ55\ .Rڬ(>9N.=F~}um}OawԖVY~JE~4eʽhF}̱aY?q?>ݼiqVWDXIN &OawݙN;1s8?3ij/. > Vϥz5=gCVN+M79~XUYxyӄ8T` BGnٻ{7O> `T]Uي f&@5( ?޳k7nhNEʏLOPMO|?у$}ONuU?WT+ivl@B*]{޾Or3][q7WVVX^^3oqC: `aoofl|Gkc߿'k?>4V}|gz!Aq֮?O&wo]>x.a:O'rq;ωi S@{w46bpĆf2HCI;@:Ҳe,E( R<Ǔ]_1RJA,YD"!`0@ATU%  @B)%v޽vbt=mmmcS/~/\tYޑJ$ y @s)%Dص{W^y[r'+jjj:7HJA}I>Z9 F ] g5}m IA_tf577=`hBrRPJ{:x`}W_G7Y͞jnn$Jo @c}"ܽ{]jkɁO-)IE}\v5H?{*_td>GSC.(=S—xzbCUT/Hڐ`PB4_W<0uE4q?2ͷϮP}! C.U)H}#?m)xpvvvHxY#n0`Њb:,cphCãd||N$Ąrs++?ZD꺻BDCӬoTWc|| :ʔaP>?2B'h"P&&2Nyg:$^O~萇wvv Z;66CAZ^^NM&ccHAD"OH3wϝRk_:PMZWW%3:ccQ?0cdl|dVU{MZ{eeA*aԲm2zObBw٧7VV~WW;x,0NfSRIIRRqG:RV ޻9o9)|0 4r.H2X c$9P4ʹ Z:mO gϮ,!]\`(' }s}(W<^z@ꥭwu=XaUB "L<誂p0H$H8H$DTU$+jjN]]]dwIQQZRJ)hH]:C4@4*!*jnZ3&I܇kB?3>mkkp(tB TƁA$S) pHpp -'~E}kI `|JeL #D" k " _pnnWc-y| 1У@g(hHBΣ=}E4,+ *x0s:HJ)%4UE4 B 0syWx# ej&45Py89񒒰\")dp`Y>m@R`s8Ι1_ 蚊H8Ծ^$H82-tJł29(R 0E/ۃQk2yVWTT:"YHDJQ΋j:$}2!xJ8p$,5UY|K,!yr~}C.8#cD MSi:$p߲}Rasbr,8zasXy 6* k@9m-Qr__% >&8y٠˗CpQ8m۳G].[[/mπ |-^[o_ *$կߣo^)[8o?QPDdiΧA5 s2l2&@c` o[Lyt>w( x6C؈MU B3*ѿ2 :+loħD \Cm '-RG [ xsMK,ǥJJD(DeH2N0HM+'*" 1l{"G. x]S)D!tӿ`a|D6a*zixP0t2UJ P|ABc5c}L ՙ<!- V>STEFIp)VX SfqrHucI[w8Sc7@hRb(|tp8AHsW)^[WJ:&1E6ڙ@0 x|N4z~|#B4J(H'%"їt`@HsЯ(V3FPŲ%2>P\1&aJAFp_"+T(D`(/azfRzFaRͱaJ %l¡c F/39idI()3 E! <`V,/^|K*Nj~;9?00#8;E3EX5Sk@FE}k3\ܷ?S(/E +CdToY(TawB?Zb+A?c: a@R#gmi!APWtM !E"RVD;XJ@B:! b RU hS.n8&Ǟxr$TP,(!3l5'#\;X (țyDumd܅ 6$ b/@ga) ޼@H!=Qlfj~>\@ڶlx9 ۍp!<sPJ`JXmN?4/X`0H4RZY+`,qEiX♗g'N '7a8"k5f6W`p4ׅ㸴,Q @L l1<&"k5f6;3}GK"A, !'Ց[80E"'!s6}؞Gu1#) @!1+ ˑ+7=K I/E @NC# A {0@Ja"TDk0 y&!kX.z>D&/|,)% Oos*Jk4_J,!hwcC>7/AYo(Ȗ?Q[pؽf3Px?x? `,; l= ThoVsWWP BJq/Dzl\(;/tI 3MDE$}Lǟш$kzz8Aq  }B#='=(}~6PE)sP_^ 3aXo]/xXϕW^z]NQKw dOzo=GA*bXPI/o b5s\߇hقFX|K/78rb~h<}a9ٰc|.%JuuMxfI,\0%r[̠ bd&,OW¦ CH G&D( FLj5T fC&@O?ԩ{H#dߎ5h+y}FjXKY])nK}?-6/02Ƹ-;!#-ƲYclϲr 珌޻md~P\UH d-;ݵ[_ N Ͽ͞=gJKiyࡰɮ8لG޾"hU9;5%@ _"Ud5..EC3!/wZ@ݽOCSl.\ RJw= 밤!XXz@9d ;p C,l|y:ةuAta5b0 L6Wal2] }.!ܐr)Nm4(,0)ؗ>ߗ龃$TFqBC5($ibK0}ZPE#TjlZ 9>Tȇ^d%TCH 2d*!|J߄k]` $P+ʽ z'zC'hEc޴ .>&@Ia By& SA]4PUZ @%Vrfk,5|{=+R H< P@}Y ~zw%=ǾmU:;;W_z뿾@!Ql aXslHC2 .@ g i/\qP,o}u?M 搘 9ƞa,[]q4Ma٢Y qϝ$}t|nx;KOa_F#uxz4 xyseEG'{+b ܽu᷐ܱNԔGa*8**J  !m?"=ݳo>oooQ:;W֯{g7}#1|)0, -tW@&$[ =ly~ CeIW8"CSe߾Y|[:>vЧ׭ۗL\uZ x_D7M<'s(U>v!Jٯ|G»Zt\f ?dGs/U@(R\qls!@D<`Bj=_plv0ӒR1>㐂ԤRJRI tC51-? PBtc,8! ;鬍 |0]2>q!P6%? BR"e <硅 B!w]yuV&0D̃ F)Xq|Z( W:1=_ G}lďnVW7!`lnƏnƶMADCI @kOd H<ř  &( p:,k%D*4f 7R s9>:G+%u4at|#Q>& e_J )~y$\*M?BBdƓP<~J|#oG4aQSn(CmzxTM"_s1\RJ"!\uy\@UdI7Gكὥ0]ڮg.*A4 gЄP@xF5EFJJ5G\TC{bB,ۥ7pѼʴBaHƆA!n L]轧xe{$$oZԏq΂D& !:\h x& H!%Gҹ$: W`52yC~ځB# ~`!:8C@G!!}Z[ }!pmS2@J=  rV)It|E[M,ے׶ B<߁cHU)%, sIU+kesMܨ,!+YBkdRR㡾P teTɜnY]Ш\>7p}^IIpQQI&nb1$'̐\9 p>RHpCB8aLZ5_s9cJ+rAQ8B`o}'r {n5A[Ev")%"1(ܿ`8|qxh+>VL&q?)y'UW ߓH4՟h^ȃ/o[s(gY\/t!# (AHQKDJ[{X}'Mׇ Q؂%A *Aa+ _kp#ZU;O F mgox\^.]- d:-bF,]X/hg}?{#!m.(!S#[[ ݮmnTe9e]u\הAS\<)h-C]u\rK^ֶr7v6Oommmݮe;7UaY@Q8yNކ(GPUCe;7uwGvok9Y., *"@!xp *B ʂRJ7voZX_;\Ӵo4-;+%Ph2d *( B5MFn1[ے;u0AEfA >Bf]s)(oζkST %CN{5?BH ~L#m 9ɥ&4 0V3FN1ϐy/ͷmBcb V^ . 0RJ'"˜HHqއl86 `(li~^fČ.mcČF!K4)x! p.@ a>v ɟ.mT|(Bd'ӫ}*V.pbTIKEKom;>%gwP&a}HM!%3Njii)vd[+(<F*2//][f.<;x߆gڋ{J̧_a-O(e[Ǐ}w< _/;I$ݿK&鱼#yxܗcӈ ջH?Z;L6 |l޽iA-Ox۱2gE*oɚw4>ںj(| SM`|ɧ/]z[cǤ<칭[k0qxb]ϝ])&?2{\&;#kf鿴֮i5g}_&M{4s__U*3YI 8cT3ٿS(dMarF?5 !*_UdL{ 1Up}(m?>&M`?JZvNhUa~miT&ryH<DHW?Lrpĭ42+pד,X6*U@~ o[eϠ.X?@ U5tUncț*h@UyVŰ[tUQ)cs}<*_*lSaLvuwtVK:8PE%LX/n MU@.=~kWk+962iNdQK?`c}חQu"cHӽuS&'R&<αq ^7㠔 J:L&򷶶;E;˽y?isy~-13!Z5=/,FWQKQcZчiŝ{ϣiϝ={q```!?>'~Ĉ؅1R>Zbj01ⅵ=x1oc|\2b>kKHZHgl4חA 9Dj2 8[Vވzfѻg7G `dQH[% Ez6!MnwH$1fP-xTBCYe+Qg -Dm(`9,A}_|?xfUYN!R@8* ?D~^֛OS>G]xOUXVV5k+X֚HVEuԕF&^A dq[?VAVSg- hy7wfkaS`lݳqgvçzFpIVUB>yeOOi*^ԣO]}i _vuwvImnl~jEy57(!ٮmrȎ-9%'efy듔c_:8Ue0jJE{lx {?VUU /̈́_X>I{nծSUFԋvYCo?H ho'9~w,5H ]&YsUQ-9f)%bA&x:;|ɮ16 +3o~W+,*bWyjDX$!I;90?g?钒¿ Է#U7jZ#%{~"C=p0KV"p@%%k{{YX4Ӻo2?om/ 3UY)FdsK6a?MwFYG?0Lq>7ZZB ~VpQ @}%YKmG ;.Z36\`* Ek򱾰{^9}o^r nj9,}|!Y˼p _uʷmX0$ADn;׷ƿE;kWlm3 Z-jK܆ 7ŧHyMPan7 UˑbWszW6SbfyubMD6OiSQ0>35 &`Gr=P璏#as;4m_Ē\Ρ!46 L:PjxS3<≼2U (O!seQlKn@h'lǧ%F(T>mw .(0Io;+@]OJ^~$&t.(]z"eoߺ)jh㟽)X:so={kbFA(Ka]{]RoQ?q9\@za,/%WߋޭL7xKxt4ߟݵc3y|,;ESȊXd*?Xۻ)|=l_oX"9ϵ\-;P$ſt/5].621h͟;,s6X_[f$˟1Bw%UPkv>;s籼umY#W4'pk?VxM5<ֵ1!ө&rr?}s|;[Tӹ6,r" Mr̋'· ɑ Rb~# _!wXҷ,)X"egH_c䎜>c>% Bk^0 !5"}P M͍2T'b8~oHȩVb=10BS | !T:?brp Q0?[?h$/$PJ6|#Zw(D" cCK1/F t(D51sU3䷴@JoU(9^ 4"ay@@ȚŬ~K%ILb!r 5|$m B`"3q58뢕eqp)ϛH&Sr/_޿YDn͐>gc؍%H8 MK_4gfWyB2k63s>h2Ԟ1W텪0CpŬ:?-ܢpI> BSS~^!9=h.qyҙL&-nsX98yx՟.E>FE"a C*gacat R@o\14׀ ӲH$F}{vOM{{;=F?YRmPE*o?ߎmå" 4L`~|(rg\~k,/ >s{,׷6 /^x >߽5%AX,||N +/'ĵm,9TplVBBJHEySQew}A jzsK-7wֻMq2$PZNmjR^VZW]]Lau]<ێCοR/$ebI@r_dfƗ<͒_vj|ۏ}MoEP6"%QgǾ?y`PXkr$C{;d) /uAOB@J 6l`Ip*]~@J8svNJ򓠍p+b@*k*ʞ,5*|ʨ2b!6u97 ;`DAXBa*F>Y)Fx!N`v|^kNO`9>˃ CkT}$ )W3肺c"oQ&93k[8p`Z<e͚5'ivsJ39j ( CUe\ y9q:zMMg9O^ZYz5V Ï=YWٖis)%t+R ^"]&AS\1mnl8qܛ !ꢫWS L)1k֬#?ٳWsG* jk*e* EP|\a̝W;;;uJ4Ǯjjl|c9+~2 ( )^SCbq~Hykyg57m5)(\FJ D:T^sg75:7 !RիW+d삖v3]@'r lN><'4a{0*XE A(>dߣ{4YڀA,K('x|3h-d3{#6B7Ƣ9wSK[dU~PP0jEX0u؅s9%cݘZq?.ߟ hX g5_% jC/$6e MArt| CZy69eTM1 !a:<as~DI!܃)+իW+ź!c[Su]Cm@>Se+4u[{{Θt H~WWaPv \>s94Uy;]|9/6+ CG&m=zq#MJ\ׅx-z[[SLlh miw]I<kvJo棽p|5C{.R@< }G<6[~R rPA ˄->p<ůd>K`P1E9 0<(("j ez쯅AAK^c'Y8φGaYU}mϽ״7nT{`r,KbrnejhsNDj˗ޔG9˼u]!8bq.cskɒ%M'QsMeOisN(Ad$^p_$gE(O 9\S39sn.sT̎<7X ŸMjR0p庰{Vȣ*(M{ R Kb=p/n' )~FHKMWOadts'`al l}gcy0?) ds8 FG|ln]@TVc{w Pt L_urtҁxY4:*Jaqflo'x#A2N{~ǝ uWaDz03ˍ{)ϔ/ QZ 鄵'9_VCiQ?]`d;8}Wθ6=䳅?՗`^_D>ns4URTsQ˴^r ML{@%O4xuJWU 8/]lʼnyۗ~^`'AOU{qi(P@?GW*Ue|.5mŬ=CoIpA#pUR b6mhM++яs4Ub">Zb.mhcp{T%^M ²=z?{7` ?ŗ'Kae_=Vb@QS/Z pD6ןq mABƚ$S%Αf11>ѵۅL[lIΛ}뫣,/ pGmE2&z]|+&P&4-pKZ4ee@@*xk<+##򱨡Ǖ,E0eJ}HgsI${G?<2}& u?>YRREQH@֮9G&X׾i?[׍R usO+*(x|feH>{%s.Z65_/BȱG)^-{wE+@ $(d  Υ,4(T g4_Bt˹3FN."|YCe^_YyuYYهt#z>gd(^ѽD9\Q5խ(_Y_]yn6U7Wϩ~LJ$)4#ŇH)[yfi]]G'ٳ믮+H4}&$r,([_Yyx%;~)%)CD徢*[S_(*IMe2 <_;e{[Y^vZq{&pY}Ż`i>qmHA HAki4_xmCxGuFxK9_?.uN:kEAࠐx&LWV˂)cG $h<#,# ck|p[.)n?c@4ª+Tn9>B$'Dp/ U+j$z$Z}A15/ȃHC6g@=`($}S! CC7D8b,+A!:s&ƕsXuu&+ _@J!9DC8W _uJں< 1У@g(hHHL}E4,+)d{=O0 <5c}W MPJ5CPHz_^x|E'S܎[D0 W:PIbe ⃻d3k  G[IE ;R +tR@@("e$r5(/ OR#z @_x%BӟJT/%O|PA  (Ϥ'Y@8u*NI49_Dɽlw r|B ]߇O@fH߄/8 ,l9|Wp >=YyPQ2JA yaJ%R! C]d9J Yk)/1y/A'JLI|ϗzymrtO67״¡y\boCqH`k½fB$,TF.(\m󤐒xŎ/Ph* ʅP2XZH~MEEK8'\+~*p<\ӇH s" (%Pgk bO rG61r@`~^IXAAH) ^C@rT$)L SAĂg88Q_:ɧ\@Rp_wQA返s@`B16$N/L@ @z膱R7t9˦e10Jp=H. I@f!5M_-zoeKbH+#&=_ .lJ!|p %(Sd@#2 PqF[Zzz]B ṅB{=B^l|TJ]UhEk|!AAp],tbP UZ@|=u] !RH-'MJ@)!RUUMW) O,\Q EaOS 8XlB?9=W hz sp]XHB:? '%@|jO"SSJ(B"B'HU 7!/";]$3VK!AU (k|E<  J@h%gC:iB 54M9$DbHjN/)l{&&>P+Soj\+/D4ľL-x~ar* !e%jB&cG%R* E!3" )$e (:'߷!! )T(|A"HIc᝝@ԓ %DJVA6lۇsbe@U CAIĀرo2v1oyD)'B, PDq.JT6lBaE~OkWdB(RڈRX'KV(B  /vO#e+( D xߍU\ @* k:ޟuTjgsnђgyƨ%0Ȅ!Nc n^&_n0eb V{@[GC3{,Y-%~9V}{^v*!;yv3ضEQctaʥ,?tRIUISjLub+ճ, xcjH8qxa/9`}I/THR`ʂ+P"f(L&iSsW:&;"(LKa@-IgFL@K|{3ր+S%-QbJte J*Fh&k gBr_M+1'6ChW))#꺀r+ف!KL*YS9vX3.[E= SEx(wrA6/jYrr=*`E)8xpjNthYfD>.r90Vp~,jo`,xMWS'3__>(R uDPtp🸃ȺV*VTMTh%05,J m`s况,侇C)/ WZXr^C)'%_x<~sIe.$}txǎu'5+vG# At,בD`N!8f٢.FYlHRJ2Z)bn@FBQ Ih)l@Ff )MsX6VB6tBQja (47ŅwBRВ[ftF&lFϱ6#ѐKc+Gؒ)IܖBGc?'"KfʒF-O8 DA ApxԨrk{H8OJI֯az:G:pEGyf1 W-j4x)V(;o{G̒tB)E,≅^Z^}wN7WVi 43.m:ۛ BMhZ8 Aiˆ'ώ+a_:Z1&?!Бvȏ rα 56mJ!$\& $-$dPiڛ >\ٿi?U_R+Tֆj%5:?T /WC =ORD0һ ( \a-a#}-Vk.9З ,^BB}P%Ǔ ʯii^!Z+6}2O 4w8?%vٚaǃwއm[rk<)ӇC{GK&0 pGgܵ5FIw36!,:ϥ%QS)-g09(tmbzEnC"$O=?+]r#;6wc&h(adDGWB;q}uE)blcn~&hC̲801ͳH{:YؖE5Ƙ,)949 u8n"K~,&31-kx4*<j.z<[ֲ_ o]i%]]JZT>ɤKXA@2>JT’a52q2bpP=ֶ.c"B Ē.1fY1T).jz:4bpr]zrA`Zi`5^h1Z#0?RWB&٩Yj\|@cZk%F ۔(VօRuT^;Yœ%9!}#E~\XIQzc]%Qym'Z0Ϡ4clÇGq,P7upZ*6JhƣLqqql0ۖxuh0>/ztK.ik<s,15݇yzas$$e4Bt}03yKR_+zڨZ՝M]^j)TJLMM15=EZipR)#1:4u~ڨZҖx{B3%&fT~tmfQL2媇B<_wf!2o"lc B*L*^cI[P*f0Y ({ю^l&H\e r*V)~Ժ])3]0]P|X1SP|Ku@Ҷ&FW*b"/ ͽؗRoF-DN,ks;WXuRo^$6 t -iptb+?}/L"Nho^nɱ/RS6ڲm+T;O߾3DPv &&>w{?|P~J+eI)rgW{x4ɱ=1'VTܟ}كH^,1b*OO* o_0P"_wj>DewO|߷a-Tx<*:B@)ey__m_,fO` ʈ-IDAT[woݵJPbg[54yb(_R~rO>]nbս8݂ N ZZEN!dR=G;yVO{LjZ-^J1/|B+tHK -APbIͿ0W-db:O,iTcY< - zJV>{{h3,&{{xoJV!Pq.g)VjNj=_s>[6G[&j&y9ɖ5әm\ "'5hvR+ڒ6o:'˛i&5ل5uYڒ6O(Eҕ$-q?!JE*0$Ji*6_I&'P1!+PL2Φ+ټ~TzT0GF"+b3܋o/ Pn6]Uex$ˆ#4%jd薇+CKvs/|qb2~ClI<{VW4Yn{O<8oi۔Is.bbbё)Y斌jJ{y|ߣoopp(?qN0fn<S-LϔYؕ%㸇Ǧ75~k=88tzАBu(f[nFd,*3ތ-QmЁg?44?|t։\s-ӚfTfP%MuӹG&˷C&1JN6IC-W#(aSSK!aU^$"x&xyQj;V1)+WGFx˫֒IfƱ0NaM͟_V\qMmn 9r3.<D c#t0f-|[\Uё(VkeA%$wh,VA@d &Kzqw\ܕŒ 䧢ܖAJ,D&sĨ.; ; IdxKZ;?\f7%],!8hM/{F ޾ۜxNs5߸׿zmcՀ_c?zfb FO|dXO>\߼p?RZtj}'}↛A߶m ͓Ml{{]9v{s:KZY 56w _mC϶MSw?NPz¶Yl9# *+_4nah~m >^[OܞI$sQsޖ zݚ=\o~ `6No$qmFǵ38ou4Ђx *;HC0/1lʡoŒn<5ltBtr6]":Vڣb J5aЗ`QY] S=ӜF9`? zӵdT wܽ["T7.孯qv=OF-\Zg ˫fMÏYKx,+C/"_؇EII6 ,P?atFcr%pٿtζk6KK&)~F6mjq'+cS%W([ҕ{v[$-޷%zy~¾*TB#Ŋ$%+xߟ$_*[]ugnNݒ}5{nW3Iǒ6LT<r&:'\,)(z~fHߧ K2-y)\GcA}y?o\~Mv~2a`[GcŖm7=״|㝗ۺUl%ݏ.FH_U-ҟgg/~ 91-鏯 Ï`Js?7|iO}}3nZHZٖ[)r /杁}ǿpO|)RVr-_z(,߼s\b#\74K :7)`Kgt/mRU}dH\Z|zBO{n~J2r|x*;`zH=xEcvcI]eNԜRѳHI2y%N?zs=ᒞ- ogoճ|JQF x~^wW.ߺ'<2>cW,b ?ǗߴÿŶa{v<v@,K{x+({߸?_}qu,{hp%76gnimIZhxj(R h?{P!\vm=/~݇N9Mkzn6oiOzpS#ţ=r!ŋiM9<6\ 5.}nxfNHܔfoitJc@ K[3$b5],>zhxW+R$rjc?L"I^#MR7.(ZxQ|OO`ʜxx) {3zK2a`|v1͙wra,SVHQXuQI(3G}LҶVtyP7&meYۇc0fVӅSSc(P}9e֝mNzjƶjW{>ŲKĠw{|U촊N>\q}э~dcd!enJ ZX|3߿e}CC퟽]#/*V}`xϟ&ͤx~ږ}SB01aQ[ײc=_.9m;ܮG5~C[ ;T^ctm M-P.=;0~dan',~$Ӝ]*-iתUGF֢!D"΢ēIҡm[vn߁C>|"q]IK`%oWSSUCI;*?5/C71w) ŇcDGA\(Ou+{h߶yչseYQ5M31_T!1^޿!l YnmHB,Ά7{/wo7::ϡCH&h[w"a[63{CqOA;eiH!b?U\h\Ń8^W0~y]t±IƯI^^j%ݸFs/z}AЗВJߗͤʨ#,xldŒR#䋥jRڸcYI {_s*4F`ie |)%pJTl;Z8}ڿ}CS2s_)ZB+JV+d2mYN\ōs է,hy @-B\R:Xg |RMV4G|ĕ*ZgJ3 _TNq/+^BMjcċ;M|/K)(=!#XoG/oe"DRY0hMTeTSNb 6w= ~ъ)gz|>\=D99?j?[p٨GwzhY)<ˍJ9mKVZjlۖa\n\(\HF?޲e[w+7H,8ұ3ql%tc3^FG Oߺc[X\z X;o)GBH˲Ȧ&J۲BHqf \r͎;uiwtjgR}s\G,I&7TXD8ryT\HQNUo.#-lsdƶm@HNT 4+rfmBC&CVA`*&a00j^%=nm 2El)RǿbpPL\J^!|? vhk1Jϥ?Tku/<֦ aA`t]Ep' ͑ȖU a'LզrheU:}`0H~$N/Խ eBҁ3{w&gL e-`m=0swXԖnJ0TwU[N>ᱩADK鯵 RV2yfW9sq$U9W9Xl̢BpӭF0Kc_||mK%^o߽ۆj=58QdIW*\&:!`c^ ÜO?uaHѨz;g@&.NUcGLP XRcFwʷ_<}Г=k˜ɑKlbmm$߲!lƒ@ikrvV_|$nH.]ҳF8V 䁃#Ϗ6?{g=k0&+#|.9o54/ȼ+rbDޅk%O7N.6#|O4u-yYGFO=(?}0:3-ݚфgŗF,]A/X(~8塌uhM#my|^ԺWbr|; _|+Wwl~kstj.]L >iudcI-T&',O*?ռF}"Xvstڴ97? L5=wlrtD >DzD"'QeW 6%RHjC SϜ x6!a77kT _Tipxs]ZmmV9,8Ouq*g_͟ {+zܔJogb倠^C荔OG|xL+r岞$?hJ$9NAxA0Qy;-?z?%HA"u6u`«v[F%w9vDܥ+ 4* 'UoG_|h3_r[RDJqbMmo Լ`e]ٷ?hJƯt-f;*D)mսwlbkoXe F# $F PA~;wMO)[ @lXMkwy+7X- tҀ@(-g<Ȱz] Dcȯ7˸vq 8&>j!uj߸~wܲeyd;ZdnT@J-Zk6Tu2c37O-[CC϶ܒiŐGZkjb\.b=~[>3yKk&a#m[ J*j:RCy#|K6&sBbYVFS)KL7^>%ݙau/vT(C!gFQFء"#܁ZL볿n/ΐ?;zvޓ4VTGJ)%.1-0Z)ThML޼O3Tg[k;47RJ!D"Zq1RfrV!{󑩩9|aإ]'C!-fi:`[G&7T^v4ӜJRJ˒B6&cPJJ)kP}>;_ٖ'4#%ڦM_(XӅқNϜd*wւGռP(F @E(Pj^h-ht [Nߍo0DP0r,y;`A.ՋW cJ_a?X]ٹyD߱$SЫO=5Fz5+yWS :hc&x&ҫdaL^&в^ cOJJnSB!>]Z5 {%vgeZ4:WT_ uɗW5(U U{A-VNgox D\+ee@mAi,6"TRƈlɤӉikK7h@6%_H$-֖1H._ڈL&cҜ֭d:J+QQ!FQ"P -MdR|֭[UcOSBu2&B7R* >ڈL2n kk>D xBkR2ƈhA]-R6F475Dkmm` ;@{w$/WB+F!TS 0uMNmZ1'&S ~>4bW  ay:&"5yW#LPUQ] W%Dςr@+L:λe/MPayt.KL>OPʳJQ*clS0U?RCʄY[atê:cA_QUTգ9K~ǩ{zS 0Q 3S h9- Oܯcy~tZ^<^ëuh其ZO8V2b ] I 6Y-ΈPu*zGa mQUy2.6/UjHX e9S ST|Vt.Ma}~|̕KWL!1ǢRA#- s攳#ֶڶeBHa2_2FRD|vc=EݏlXpYVB+- ڂ6J FhXJKC1ёLU \+,YZr  Fdvhc͵gIwj׶|"{}?*FcwL 9zt4&77$Ƙ**X;~gv.1F(5iv_+O\o:cBm0"N^tIb`m|MCYXה #"H ƨeDZଈ!2R1K\|,/LvFgafG/EZ SE̒g7@x6Y]l'IBj@$O S XQEJbJ2C]$%uRLfS3qK\,PtL[-B/<bFX3^r)]r-W ]ӈP0P'*mZ//֕F*9K1OTǯ(CePx[9=xm2F+?0P2K?B eȗ hcYҲxfI Ҳ\m} 9v1FJr+TF=ncIiH-B±W`9rX` vR*$qbz wa!X6Zs\ؓ (H>jIXpd/j7Vpę+e@H*6=`sqؤR'J_x$8-_07ntkmȾke A2$QQa,eܸG$`qF n&\(Et51L2-x?%jqmo4ݡ(_`VUD4pD߂oP hhߋڲnЍŅCw`i`<6ݞ;H=~B"mrHTb8̛j]0e2 pw$F:TdvX}G  S"i&qu vo I&87 eE,vBJbk*LHzӛHL2.7 lEUc`Z; ֞|#zA/VD?b*Ub3oS͌w-erŹԚ۱:%kvza;gh 57ξt'{)śptL{ ;΂4˂!K3$L"cۼu*@S;;#m2۲Lt¹k5-5$S%teܣaa|:$y7U7:NN9mcâ145FNH2i 0|&d&cf9$Y $p$ՊYd )!gwc1j [qF襫Ysť`3 %|[l[ڧ:Dz bw4*%ƞ%\L|E_}N NZbZ&r@63}'4g2Lƛɶg hSĊKГy"ˎz}4tAnz2WەXdJp Q/Yʍ WT՚A 3y գfYY)PZOz: >石le4O?{c ?2J !9R;[gdVZ\:$AV2bi!-+سߣa]%O 1YB#hL0Ttg  SEZɏ~8^:kDV6Z\L%Tfc`5Vw&''K?aC+)pG:B~+Er*)j<<$vibQpy;Cc0Րu&uxN#.X0'?y8{ž#aXs`ɝ6uץ ,yZ4#tR_OYgǑ:@:6rDsM,ēLO?OtB (GyɧR\>)>1R[keI&5S%乽c.B8G{3&wxHk{&5cǫ<=Z,MS5FȟYPhɺLCEOWBMKsEuvh$I#!`zRҖ(K!7 2&mRMáRLg#%,hnBPќ#\YDlf7;)6hs`ȩA 5{^?{$sו1A j_Mج-ZafR0=]v>J%O2˻;*{:S3G-K+@CYmzXخZuyfX/\sgQE=r͊nT+.8g1:PϺ50grI'#Ԫ޶a-sg2qdή;d P* CӝI)հ<7j>ZSO5$u4XΏoa 5RG,| h,O#o|p&b:o1]lK&t.o|ݰ6Xq|o_wᦷ:MB.09]eeEf O! hNnzuώs,XYn=w,iZZPYÍZkj2jIf/.v99?Kv_;"TZ>6 $@CS(qG^Ǻay{eo$߽ t,a)ʞ> ˞)Bmp,!_d]-`))E9J]=$TjMqt0ZhS.G#gf}+ kqEuFF0̔chK7qaV3q,e"vBRJBt$.݇Z :J{9Xf<Ƙq΁m+WM;wjHZEXS.noo=(Q:f,MZ;l``0o=wN8==z$ 5|Tw&ؖE2g9Ƕ7} z14qWE+,7`87aFמš;(RU:3QDI`x,1w1&*!6 #hjWN[op:odB¸O0J ,/d62~3hAz[,Iv,^PGymB UB5=_,Ƈ=]#mB7J)%~P+V4k@keKv2)Ӈc'ƟA>Lm-PiJ)AUT_*j!t{sJV?iić{v.Y؜XZ)/?W/OGNugSLgGr( U uO!=!%vc B jD_ԋ0B<_mJ X{CӸP4W a ԩ{BD 7Vѐfϵz@2YhMp #:\A(# 4:DIY"%KG=bP+G3\ ]Ta>&k1DcN"dcD#kjneo30 8Q@KSו˥ǖFZA,p,:@Zvliԑ׽}@G xR*_W,WG@h)AJy9?m^,WG*uw=?iMeu?jxi,+br]7s{?é`gY(וQ b#(*Of U3:;vӜL`aDuM2} hs/o7:_Bz&~UtF0sn^20n|lo|] 18ͽ<}ۻ{=Ehe82HGks?88キ޼ypOo^%8Tق֚ӜMڝm[7{ >|KBJP!ND .$pCanAكCC[_2)QL`({>H:"7=UOCCCY0 $􋵺8Tc {&rhɘa{'r=e2L用IvĘ_CkIdW% "e]M=G{p7]渢rZ̓~;vJ%]-֭[ȑIg8夳iN] }~{1B&\GugLJL,l:wb:74賷7Iꅌ$0,Y^hiaSSKW!S)~3 `' |5Zf"/e{;y{`#S媵4wR_6PuIPe!Hʲ\dK5+01cf9zp䧧hL^U!5ÐV*>{N*s\Y4|os|#hUtj7r\z3/ğ6Z:TkWL6Y̛a4a w1U -O[ЊS(xcJ5ϊ،2kIfRUulX=JSz4/믝ykŃ{HYng[Jን?ʞU$M[%]M5ժ]09c.ɘJ,wC}k;_;4:9s7-L+Qj!5SL|m6jat%l Bl˝(Tk'?/<n$İ*_wIN-h T>N_?IB@멱103ܵ+OUŶ׸$2 LHS[׾bRU@3⋢tsL*[Ebޖhx4~}U fӶ>=kyS\E=B,JnO l=E>PF~w^ʯ;ͭ׼~Z^N [=3q#'[f ?7| G~gk.h5.^4\G*+_4nܼC6{ w|=_5f6պ5Uh4}ίNi٠Z BOp.e*\ΛsJ CA1 Sz`NxFu?~*)]3w}{ulj9`OgGAvͼP)W-_Mcʕ^٘IFg]Z5'ϯE.hApi/MR+3&1xu-QP$.9DW6$*˯H-zDl.j^–W>M=_aR6J#f}iuI\s29|#Gόon=8wn Bm5W5Z}\so7Ҵmqߙ-k֯ZU BpϳFnp#M#.heqwBс ;olgϲ'W4Doy?Ggk1п溱Y`e0B<_>XH8U]-9Ů#C;^^UOrM:DTKw,b Rieuϊ$t.<_}y2hM7YU$ǏNbA}A?t^`" ^r vwlزUs}-皖oښ>s2S^P?_}[·\2 oH{,{_ռ[nǿziu P4[o:koMK3I0Pvq8r?Zn~xس=-2>%ζ[^=on}}3OX9s.9-vW!mR.3C wp|s9c냯k} j:>Y|K69RyzEbJy.{?d^Ύ? ]ɑ`)O1y ϩ棫^pi1[MtrgTGutvEF3U%gT{[?fDD j OG^WV}¥OpBmlwJ*%Vl ʭ99IIε?8ƒ<O*Ŗ:9?bȼG>G#+$~,Iۚhy L?ub(Yy؂Ne`p%[bV9{O.)N}-WoG";Ӷ]qa &]&F]>Ooxw %m{3eZKa` 3俠*?m#(>{XR3|6BPSZ}u-r90A 忞9_XJm_RFkoWwKOͷ:z_S_-IܸqR8LsƘ[Ry]Q8։N)1PKԽh2͠MK ' i`*)\A: jgPgOß5g[ɤI{ Fhy.n?ϲ-N;j#S37794zB䏻+,aūml[ (^_),\o=SK-0ȗJ!]rţlɴJ`Ɨ*D,_0refZHh폐dըgF~%2M-6?EO9eO֡'B xJd_m @9N~ՐnʲY0!_6<#g[VWK0Hu9ۃC֬dks$jώ/3t)j0a%[YڲOхq;looM/6ǹZ #HD-JbAGJHLχ9$d P_>> D=f6 :̃?OgY +h(@ .)F-3i-A 9Sӯ00h|ĕ:'ۭTYB?*} +waOi!}8|ˬ? H>5W7өZG&t.ï-fKi@XX6j@{nEe_F>?1z>Ee2LƟg~S:[c9φHcx(4Hq;(3K3> UA8U9[⼙I$[:0^(hZ=# /a\H6^Q{uiʄJoeFi(P)x6zh|Y7g$k>JLPdM2C囌zɨיP͟϶ ! XsZE$Z ! a`P!hj^%=nm+Pl)] Jzyahh0OtefoBwa2' ͑ȖU~ +SSN4^`L֞ٻMf7=t?6^`L;ọ32/?_fEfEFke^F)?i9 mfn`QT'?;2# YYsԍ/|QH_^~'[:-] ~-1{z#+V#WcٺRXk Bolr!P]s ud-ѯ5N7 ĒjTQ|UC_?|ubE?L/ǎ*m/ ~|۪Z?u1wiwuf=MOO?Ey'?/hu ğSmEe2:W~"²E,?50 "x ~ i1q~.R{_n[g?#o_1̛?s_nS9ET)_-:R%cd\?[T&K6-\^Mi5%ZQ*xgrT2ǶK)یx ÉRis:-R-(|3}6 h~mqF{А<3`|M#MMg7m|͟q>cs5)m׼}?t5?k>>:g )1v}}}}ƍg sf___}Z)emۄa8o~١=A) lk鈹.JiB}OUkտwNlxK[+LܘŲx ۊ X)T-_*^)~}gbcĻRMX6c/+ժ CU+G{y$-[X[nU 'ܘJLS۶0(UP?o}x[OßXJc7&bn66A ڧX~>@ϟ}v_]MčX,^TTX.?<=/h-ZԱmv<1-±hcmjZ)U+F}ȑmaC/oqCOv̙1RԽXǜ_gIc/:L_`@|)0 R}K|y _`#6ɛ~ g49{aSsFƳ*/}w?5i?G/"~rvX_O>fS9|2PoƍkOOo577/KR@\⾱ݶm_MdIx,z{ޟL6ݞNbضmZH!RPQWVK?N`^-D=m- ,ql,!%%!FimAL|;>⮮-p\qB()%׳|#K[GsSM#'/}K6e}uyojRqRrR F D%?>n,tI%b_]Ҽ-ƒRYR04Zkog2_*wx^Yxjgkvc;8Jxt/ko7yjp4vڱ/gu.e)۶R (WʦVcxt_8wH-؍5m2aBzyKe$y_n\ѶK7Q 5FX|/u:$<<޸bs>7mDZ]#c~r]sm^byۇF)D͘W?<ٮ ޸~Ţ̇](]0W*_8;~#0^cEO'񍖴XVtlKuVA?O`EŒMoY(a#A|.֕$k߼`ɥ1;xGw ݺM]ࢋ_T*aE|Gjݏ=}yKz 6^d* 2G*U?>q6Ir}o݂=Kĭ7 "6穻?q뗷8K#H.8g7X Ցjr{o}b241b``@XW^yd2yƿZ}{}yq~q hz)6mi),[XUF6atZ }'aM[td,8RJaI_Rm1ƄAə|m*W-OFLޟuU{;_̓5ؖq;d )@LJ(P@(4LmJjT6-÷@JHHbL3ډQYg{Jgc?},K묳^n_cccJ3ó8|b Tt%^4 ^0kiDR3.,-& yF+*S"ݰ}'>k[[bkS)!9#8U>A RA`M䋕\rZ?D]ccr_s]mJH >{^1H&3JXh3c?ݖRb)-_n !BphNVJ)Q.X-]=<<~U֓>3u?qMjA]Ns]Zx?8gg=sMs]Nӂ4]}v$?qx-oMq?܍,^rWKk[Z@Wg)ۻo~z6Nz~ὯtZ#9RN McOIϼ-kikU5N ƐW CwO:K~ЯZuMGK] uui2FL00:_?gfXZZPpOdgxl̽kmi]ԁ^.9 wT/=ߟ5 /I{{g2OػznŽƟk0e3`hxz`ߡ7z}ϟgsִ5Xg1MF&ogώ_ دYֹ}^O;8fNe`O :tM[=3 Dc?W^y[8Ray1FJhx7\;wlfhAGx|UgZCkMZKWC&GNef~قjkqlKp9ba )~3#1sfywj FA "RZi995g +-;6 D<8?m?eU\뮆TK*Ƹ5ʮQJk9+V?;jIc;1f 1|vfpx,Xd90~2:}6~¶lŅ М lR\)glB$ +[вY% :&5iDMs{W79Q^^zѳW)ci'ܩc/~)6,=g['7 "&0t4Ƈޱ~9^~?\`g[[j/$f0cY򋻇V v:'WS :S^ciV&W)^_ 3ptygŋmilLxAPϑӶeYS8M XꞎoDQ yX!){<=eӭy׍5ˮz:ޱ+|#0T.xfwC[JuF|yEzBc$UgqU2'%00oO/h,O$ ✩xıϞo[vAΩY(dgS>|Ƙ;/}Pۺ4NşaN׬>-)۶CC{͓M?9ӦMbƍo.zh޼VeҲg`ABQ}u' snw8}[NfT Rz}'͌6$R`uU\v?@.Xi q0 @,}==+ )aL`fas5N^s8΢՛0'}ZإAd@ZhϮs&AFT-G/X Wφ+`煒kUy)pC]e-{IyRa( aQ#`ZRs~|#6FN1Jij~DDB*{p8cj#8m 9/P6k}1F$9mKhۢW. d1Vϼ@W)օ1;򷜞E΅ttt&JJ"+4G⌈2U.WyƦcm92/yK[k]qT_ϰnk̫O_-8U_D@ 5X]mczi!Tg} jc-u@π-1?DA  c#Xg}{Ks1F5w. ŀ1U8|1H_=oT+Y w 倌1vX.Xؽbٺ2hKoc ?9Xɫ]Ag[}K_/@ڢlKt<>":cUK Z e?=}ZƆN‰'Tݽv{) P_GG(@[P!Є@k *>Re4~1!uU||T|/|  '?UQvZ K'c4q?P,S4ȗ!W&Fd<+53ֆ/bR~(NWeOd,)/˗0+B)6X,j W~nZ+Y?^Jpmh@^> Xde~_1 Ô֦>IшM+WcCd}&7Zk"ÕBQ(VPa>ZkimL±RH&@2 _䇁fhԲC}:\ʯ % gv(=3&8L| :^0+>'c>~ `/"lSt|6K_vdj2F cW̠*d4#lC G('5ïv52D7mIx2#6R~z}wGwFPI𵡨cGguV 8xHk-9#Z=eZkJcoD\Azx(IhaN(?,k{O?zE^phu*0d?W^'57(P( 9qAT-'#7ic?+hJ:7\qZ~_ỵ9hc8FeU?oʟL$n㤵t!Z).D,4+B@4YH2Sz=0]Еa(w ʝ wAd*a$F5s3Q 8E  t%1/GK"D%^@ 31Do߾]X–B,@Ԥ4 ϭo(S'|"K<\wee(@pcgvw{lWolSJ6tW\w_?_/J8?P0y{]]] suoo-8-JV$w t͍0r,z=W oASJ002$8kGs,@)q$[bA[_ю+/Yk\sü4V/k pM' B,Z7S j18XXgcM{W/Mu8-s*7D$8oﮫ;gVK9!9#8&l¢j4!f07fGRo8_ұ: ̩& 0GG42Lvv,8Ye B|J;AbXGbNSe3 sEVI+꺅{XN$+89qsasZ3ۉ{ g'LJUm 0˲eٛ43fYeqm slپs¹Cݝ,Ck,ɹ-s3%%90Kx¹8u#c /9l) c- 2N"?gp-څm-A`5 l Q+brsVoo/gK]bE6#ڌڈ61ohf|SDb[L #s^e.>zq?'{jwlkI5d%׿aق+cm}uT^p'Z._Î" \Ä?PK[k-^ba̖GYÒkTF~2>cڵk-.͡ich}S@F _u8u#s@-,psjYv5frWcJk,km@m< 4꒱Er8rXPovD48cc90x8.MkgP&[>T /E+WVvk.+bKÙ+7Wף8ref"?݌mA,Lxwo~ ׽x|E#uP @p|#qS:d+, 8Y8ƖsQ(@u ̶,fKs.lb 2B"ieW|^s s1<%:g׮DZk,j4|t7m$rrO1 s@y56޼XXI }h ,oc(S/N1L q+*^H\2q[L` 訯w֦Jij<.b1\7_`aeABydq.]Ts5f^+ƹE f'lWP5υXFi?[]m kV@( Z8{$=+!;<]Qh Xń@TL@O E7^]{'wA۶iT;q %. :khc΀`3x%& %̀3)8qtL(ԘeR?68QAO0fŮZVf̊Ny:p6:<8I[f%kIyhI;ef)fƦf139̈HStfؖ\Bl&(+Tphx TdZ)][؎%9ʊOV¹%",s`XO0FԑO̙ hD:RJ:49%B{} W5&",b;!$#;׾9V/``xjWkD3e$;,`/ qYR 8T5+  4HDl2Mz>ƙm ."İ@p@k`806.r !cqw-+"@aa[ jE]:! A{>ha J{ aewtETG, 1%c8lӁFz*\K'PЄ$@8 4釻*1H9%mP%u6|e4.&P 2U3!1G?|]lxBДNB0ɫ&-%  6As3fG-p+zQ[.g(h.&P@A˨KYhnG{6m>4ټGeV_4$˻76hJX!j4$A|r͛M;Jkcz>Ra|}2x)[ہ覓g[UЄzgղ30AKsQJ [Eu,VA+t tb(ׅ},߄J Ud2Z'[Rp=O٨R> {*$m3 gg1H&4s 4ZJԦb((`CDE3tJB*©쇣Z2AmT3KFkBT:c~\YF2PmuiJ!X$o^Q pG,}~tUP@y tΫ@ Ⱦh5ÙisApT* 4F&AFA@4 O rEHY{½ and#0Fs\1ږ5puT w5kѼTΣ\)3lcPQ*a⥊k"ON5wQZS| BCUG,\O1bCAe7QZaw3::pooujFrhx(z=Ơi\ MĽ@) 3T-8_2z({>l :B>2j= 75gxRB)>>6qbFŠ܌3(vxt #0Y>c#U~I7n6 ; +(s0c4J ,dMgamh2,_r+a3Z3T2S@w5=UaڐQ&S7WVQ !bŊBŅ6ؐAQPڰ@)X8^0ԅ^тOL >'~Me&9/(u`UV1FFJ[Xkm._1NaX$[؎ 1Ì;^QC3;0Cxo (g]XO8C0UA&0ZSviQo84V`#aaɆ|S7"P c,S8 &73CeO +2'R?s(P"z}56dq_;F yc C7]ee$QlruJTJ.X"7\H!0-N?mpRM)P`mkVԀp 4#nQš%n.Q1O ʮ5.^@q(Tka` BO8Q}>mK Kgc>9|r6qO<c "c Je,͒Ko| .< ِƗ>y#ѐRN> c,35XM!}_Af!?{#}TT<CaOKc|*qSܠt1hj7|s_Tah"_t<AXn`njf3s91 PW&"vh?DL= 5<g+?~sʱ.1JaULp 3S}^1mpCÓe2n?tsb6>Ah \xb.|e`@Oy,Q?ʟsfODT}_ԍ@Z܀U$y5p8Aӓ2&w]8J "DS ճaʗS1~"“Ze’9.Z Cθ1ZIЌ~N\gN~,",u͊g$ c2s'm'KʲH463h1]('hq'4`T.KO9p W6^GuM?#<çS.Q0*RpR9ssbgB0؂S{ln4X+2JII79x8R&½S8*y?ZsO>0] Fb3,_v2A |qPh?ީ|<@6eBq/"2hc 8 p[ \7_._?eqM/ 0_rRzbaJw8n"GImɛ 4Q/9k?\j:oo"'iSO426vŌ4ĎkhA -C5,+SOO'Go$pTs0yx4O|#ڿBHm& Ubڏ!Ҍ :禰BӏMBc@TGngH |[BI?d +t(0y4ypNY~ܺuz+njoi1xA`=30DāS2V7& 8gķ~s7\{/ ]+Ϧ㵷)5&ƣ.Dcc8rk/ߏd B/Ie(# *k׊F[:Q;cmuP`br44bx^ܩs,wDqql%^>o碔lTpctKUSYNoIF- &n#SxnC0D(sp& .~{J|Ꮈ>=}[6cfmgO&g bYtmMǠOQӾqhh(w=6dP"tOb . 1Lgl\nR@-}3מ>gJ_n>^H0xx\a ;`4XuPnVߐ1\u.t*}ݻ_{oS{{{Ջ+,deK,&%-kD,R־ïطoSׯ[O_ rόx, ymcx[{}3מ?C^֖{r94jjs:Z(qk}~}?G3ml;GDcuD w~t:U~XٻQhc-퍃mW &;֩zY8/6/п=թ9ԮhiE]m2\>*+T}]B ~C|jP8) 6U[7?gjſO]sNms:;s'K~~I'̲.*d ;nu:qw}]McP;t, "BpNgJD"rb:sp"'U=6@M@1j:b.J>ƞ_`;7f=Vأ֭[sOx&3XBrQFXh&b`Mfrl֯ܺu)72o߾=Je/NܢTEc]kG02farUKLf]V=JE/}dk<۷o ex2P0zwpG&qͫ1JfÓ%GFF8R?n `˓1tdK`|lSy,[܊h$$&'Ё!9UEC^>V۷/W`POU|D-uΖ/T0Hәxz.J)Od˾xl *BhKJL*i(V<:OɊ}?[/7Q{]C|XF):jPђN"D`Ɓi= šiA`P۾ ]/3\eդt^#f0 !pwm߄u lCڶV?{_fjmL.‹{c(Ũ ޷m7_߯}ֵۣd2F12< t s(j1kphk?u}۾~toosV,мLN1-c-546uǾ}}|ZtnU_ֺ7n[ҊHFm)RB{Jl)|[{}_:][kZ>duljIb"WdlKmMLen]:] C ߌL>=PkidKS֓f&w,KA6moLazF/3;:k/ZL璥T\+a7;6 []ڴIсfӦq'35:ycfrJ7ק`z:ݭT˩ wtl[MzΐG|LNdoΖt]:)ڛh:[BPAgk= 95wG2 sr%T tmm IBёmY(n⽣VwSO8 G<|P&ݘt2m)*)^lΝνc3 @|xQm$zYdhE#Pi@||;# %ӱܲ3"#+VB?7$[>RS|xgPgS zvnu6+| tO͊mJЛ7y̛6|lumf6x=̀JxzmS'95^O)V܌5}"" JLOgnw|CVǦу7MKoM''Qn8TbB l.3o+v+w%t඘%-e`eJU ?+k.3<zĊ+Į͛qC9(1`nbr?؇V$zz V@p@" Sn==vy4ظy?묚!ڸZl+wޛ~M=;7<+*oe]cۜh gW|jbWOt[2Rq Pzj8vOY^qeqRRwV] G/(//%uڌ9{t&0ls^=om}T{cDAv#W =-b==͛$nҍ_D>^<x|iŔ(!ᖉT+Oc#ߌ+Xi}$В\ڧ^V'##/}\Yr4m_m2Dפ|(׫Jy ?G>3 qܩ-w%FͶ-EY=%kݱpAFJE  X FgX_K1jKޏyS`j0b3ϑ]KbH_"kUtG{[hИ"<-hO= ط|41@LR]]8w`0|ᅂץ҈ۀAUSZZr`54 πg`Br+-%@I$ L bcg||Y.gp,IJ7=LgK$8l'y|J~5S*,'2C\4U,С_)x!p1T,4g?Q"msp͑Z&MOaz_ap}A !⢸j) Ak30Oݶ8XR|,͇* ZV uN#ݙ].  pw04xXB1fcΪe[1/L D ]xr`8Yj03WH~#^#t@5u  -T^]39Ck˭Vр x c'a 3Ƹvtig.5u ZjlaX }4}J>]}~8R| u=3-:< 6/cm~ᮮWX~W.ȜCOa9g>_2)8+ر`Xv 7`3r.4~:88z{ ]9{>UwSs¯fJs1+.:Z>B_Xb^Lvz(RJh֚ y2#mZ֚)%7J/!az Ŵd(xjV~OC'c|& ʯO );~!*ӏA W|}6~&Y{K+,?e닩F_CF3RpJnM*[#CǼ(U\xC0>ږ<%%`}Bs1ޫL[zř55=(;$_)zm$( ko}mU+tx߃P]NsWq3s}B^Q +7GG_ HiR*JHi>3H\hm*S=;x!G lq`Jj3hE0fɰ gMG'gķʗ*W>p 1p*$m"\(`kX#|-WCp]O&O;': "pb%wi&gkv UO =^O`Ϝ?  ?ON$@?O= 8Ms+@ MIj< `*55~jOߙo2ʆa+(OVߜ=#,zE_52oS%/E~휪)ׯx8MRJ(&VHI?i&o'qWtٶ,뺓<Ⱦ+{ڎ"5.\66j'xįŖZH3;-_nզK 'Rc?s֭p}*ymKm++5K;8}E55Ka|fl"=UbŊDtG@09`޽{Ǿ,@D¶`L3zǾL[,ܮ{sD|4NFnpl+|g/~gKgZ݌xm"q]Rtg~'47#^'?DnBZ {`e~Gc t9syK^ޡ/{zzHkd-KݲD(*04+u_ /?¾]=o{|Vzzď~#ֶ|˲_/hRZ ZR_ַ6W,InYz[vۖc+h.{/Wp|>kӦ-āy-Z藗\rX,6וe<龾>:]?SK;V{VJEQpݟfd ";wV^z?y׻k_>Bck[[5_8afmӥ7l~4D]s]=MMMDpΏcV\Lo~CX<#>X_F57{w/A,<d>mWo@>P{A$b1d"̶A?;~O]:umY`'пMz7~#N=u8NBpp 1m4\TfzM1Gl޼Y7׮\E Z'%p%69:Cpž?~t|v|kas~Z[[E J%622Cqp؟ќkOYk.T45vBF0F+{hc}T#"3?O+9R{`1R@k<wonS}?3w{~WWK.(ιB@p;i5Aܳgڳgy{vlڴltz`sLv+3VU+Y*g߰lO6]+ J"SJ){`d_c\rgo!RZәw8;wZ˒>B~55!c@PJTfC+_y_~UV*L 9P=sR޻9嗿P vS3{70pRqyJ9mWL@+#ς?a eYmD44bJ1Tdh&3\si5M֊ AWY0bZi c0iC';(yTJbg,<vJ1ϭΌ~@_ziM2q-PJ+s­Z)WFL@դ^zYO'KSԵ\epϒC7č6BRk[F2q߯?k/m_ 1\cTs}?~deFIGyiM}TlĬ?垽01> 6@[DITe)`|z[Q9l DXN_@B#E-aVeD\qmK!0w+H)DȎFߎLƉڊ b!c>HX`sz8阤D3#7D\?R@S@lڨ-)j3֏# Mz&8q,(m`@ CFlr!TտoB`A:j(e@d $[ڧ_q8c_xi_Af|ZÒ- Gİv]O< hچ&o\17~R /9_\<ְ, mCi|.\'{!\b9+6nM'o^v/~yiC P.1`/ ?&2g'2d4<σ((fT,_|O~o^1:A&% ~w> 0g-[jlW6)s}5H%4Lh5+\Gkbp Dmk)ٶWukd.YͨK'EEPN`a{36z5:5@Yzl־h1Jt888`[ Se1G5sԏ%(Y*aJDB0DꐊGRY֙ǒr tLQ$b6c 8@樍J, %i374Z5$JAHDQK@k9;)GlЯwyj=җu1x T̊EJO-#e\V|}l۸~=0s|3_әL$ICZ6X`ӟx/>}y7UW}n{zZ{Y)8D|Yho5/®8ax_|=?.Ǝ玀c֮]kq!Z}EB4B EQL#8-eڵc,3fBV-W/#g`8IFK_!Ye[.ֻ 8 8phldi9_r!Go ҵ`(p糵YHRb!}3BҎD浳?~Xl^dYk`x0#q xI ObRpl)e牘- 'b2 My` PSQ hض}| as *_ ۝z0mq|)z2 A)=ۑۿA~2E0?Az-RJx%!͎bPOo;~/x dΊA,S[o0b>4~o5ox03Z"be7/. %jX "'AZNjY5b[rL&\%NkRع/ O )֮}VX2т (CiT-¸,+Bqcp[׮}طNίju떳+>k:[Y}2/P𕆩q`Kǒ*C"M6cG>#DLKfF4df)kPaE>7b(E!1rxl޼?3N$I&ڲlE^=oZ] %\qՅn_}Ŋ8'8߳i12f3 XDsa @'tMM+5@k K Yxi/`(`i^kcUSGgѺu$9UG tB0kMxr^(M8oi;HYnܾ}{0^6wIpwǛH;X1 S[uz~%e;!3`TAc} q{qԫ1&,+˒۷.kL ;Lz !vђTnaXQ< n%"]%|v$ } CDq:[)paXz0"eI?1&fz.-K 혿fLCe CoFc/ Xŝtv/BFv0B3ϷGyr' @$tbf\xC}rmk;C>!~{<F`S 2HL?R- Ps}`ǓOо=X DDO!\g7cu14,آpH FG,Tr,\b|C#,u1p3{.X@d?>1]-jaaQw`.Zډ{Gz.Xn~S׭HH,ֆS}F4VT)h=d h=:Y.#o?2֑ƺjR1m Ԧ91dr%OҘBc]cӅuqcC_iLڨZ?– u1(tIaTKhJH{;Щ忸]jiF5FS:r9rq{|lhgF[V57_1Z!8H%$: xt!<`𙏖/w&)#6TS~oƍz{{ʕ+cLUuJ]o@:\3l3R/!&J__jnnf|c`i56~1=`ak10>a Q}}}?lq;#P*i`AFP2 cdPBx#[Dxov\^Y/j_?}644_?~Q/Dz+S;cAV.:w1~EuŽ]nvNj/ر"&Rmc`a< ?#j6Aeǎ?, e*-u`302Uቧ`304A{K e*9NB+yfoYo=Yٛoqpü_QtECTiH14}ضwc{Ʋl;14AC2CTq/H[wu |Sv^sw#qh9cRc|J#xb{oLH::Jf ShM-W qlw=<ְmãSxdwk؛zokPq}fI:;WoymB~):/TA& x19"c43$t[|sYl/&9XՊu+X "\,_׭`X s|o߮gUrc<(O!k=\ i"~h+}aX[o&pp&4%AP@ANPW@~rafVk.h<o+|jx q!CcBBi S8洍}[a[k`>>28DEguFC* Ɔ0NOt cA㜥90AKK`" >F~=W72.r]G[{'dyLUxNGi,,lԦ;ZH9nOcDCNm5PJAi8phy rQJ@8HK@!!|  Z! F]M 5 (Am".:P)@Ɯ?1%9+@Ǽ :UPhLaOdoIƺ_1B',j|DzXP,phKa~Kigפ,2Dlz4gv hAh?<=E"!ϮI[XGXFSSӊrIӊԔF, ~-kNsQ5e3Q?'5a,D-GsiM>xԖhJ'CIJQQD,14ě e*]%chӰcW"^Q<:|¶qmEX %BH+,?9gRD*ϽL&_ x>oB\¾|2>,LY)4' iY}y}kNw~Rn/WpRm'%`uK(W`\Rn] sמӝa"/(=f1C(=K.gƆ!|0~W_05p܅Xsی(n_yA]*JQGb PE-poƢ@P j ^җ>(n>)şnO.Z1ƹy dDhMړϝzݯZھ@ڒNG\J<_C0Υ-UKz?LgS,<3M-L{.!>j-' w0s 81RqGpZ ^fT׮HkOv8@0dV`tRhe@`=ߧTvW_"]َAeDC $82R l>-q3%ދ)OFkdPnq)Us?gͧ-}OFSMϾ~ C. SadC_;,\sƳc ( Syie$L.|Һh۾#W/x0DP| n ե෮?3"T.#$R1ec`E` HU0auKS` U}$^yE tzBuPφXeqR>Qؖ9&sGsr6߱}a@s2Oe*[DqnXc[| GPSn!sxy"nyjBf0RO;&1s CPLsMS ܄;oIF͛Wr \?̡뺓 Ҧ%ᙘnbxop֤ +Y@kLCK%qڐpmɂ7$x7\R_Ȍ1ʉF$A:K'P"D Mbg LuA/0ӐƗ?u#@AS "DLkt$P*ݯGk )8ʥ\Vs׀ }}ll/g!$Xl @԰ew&e7;zxB63lIA\08%’ \cIA\v^}wg ubyYƘpD ` D\<<5Y߽;f3@{v3l\yް8#`9`s g l`T(U ~&=y2`\.[וʕa9je+K 4;a FBa8_\'z66gB0 Lx0ijZUe˖ᡵhCP^ W 9HC:5U '%y>|2Ds]‘ A: Ue \Rc 4R",B %,!EXBZ+LAF n&8 3ZCA1ی8)KvyFkkNep}PL8)Q`G\0F# @SPLLep!T?+L0F$@ĠaU}Oa9 1FD67}}S^vf'ח CD}S} !Cba";ݝ=l>W\v'F@?WIF;3?Lt"c$ % '2grlX\L 1 0& $0ir2-8# Db11>XCFh? >&DcA$y\qU{2}4F]Uncmb ȹ $!78 WVzn)pIBHBbBXlqMvnjHƹk֒f>z̜Ϝ qzBOQotH*bhp2x<8tL*۲S?r@40 q`^5HGTOk~[bb[T2‡F#݅[َ~%|'C$Sȷ*.6DFNQC>Dmc#!<Oο>w`#tfYhu6:6+z'hNU EoEb'Rx^`O^F& (H4/ж:Ңvk6[[:ӖcR=Ʊs} l F);Ңulii F9-$(霅=0a8]0qpL=Ң$d*8F@{|Jb"fw?^^o_?ۄtFD)L 8̟? 1_Qmi ɤLbh,x^7~HHUΥ7uXhIe-is6<[^IzSK9je3(o&:8{ N`W{!A4Q:{ɤj*>eRh^A'%d8c5ʱc} 8@9BsI:WM}Ih&BYg9αy! ѵ cn,=1()OTO@[lM'_Y qb 3ررg6b X:ajwU=j_[ӑ_Qcݍ_?~KGwc4cġ.tdW5oS۵xW&U8D,ًwo=D2 JTX<OOwx*+F#8 !A q!,m[~[֬-~ 6Jc(Q͇HYPaY[zNnM粿R08霅-h"D[^9t)沿n=YcyJ; e">d" &$S-:z9ñmBp8'^ǟ?Ho4 |w&:[^AmD፾,į>j D,:FL& JHgAwlԫܓuB=ѮtTϑ.x5'.< gP%cFHWOmvx$֭Okw<FqIhn1DpaE~Ɓ?=ޮ%[/;4evDuY#)DbiV`0um7D{Kv-vM𺘘Ql`, h pp7>m--Z)O.Ң mhKc{ܢ4XKB+h]';U[l:GJ+B{ gahX8Ŋq6Jg&eN.'F`Ϟ=o蠏ʥF1aEQU05hFG1R0H.vrܛRSqrծBdl^9MU 2Y0Bl"}L:9%_J9JWѺW Ic04֖" bN}L 'QyU*P&d<t;>T:h(u!g9f{KYX•$LLُb@cF0@P_^D TMUBb"e*!xɉZ+7eЅ峇00hb`IJYCxtadݱqq)l!b2}GFYǹd,8<݃d,<Ljdvb7)֍Bmjc7t:3ݙX'0:3{LJoRX77vtMmml?rxiНڊ&iLD]ӌM)?~ƶoKd5J 6a"1 j0q4JD;cyO[[K4v0uͩ.`,X"P90"xMmmmDφ yr.6`'e% ,oH0+X܀ۥql¹u%@0?{ @]] .Yt\3b#/x^ >c!shbxģR D*xnD# 6@`6SR(~5]_~ڹms `7a,p Ro훮qW,RpRIs聗߂hhf"!?}z{(໼3Kʶp$H/~h=:u]UC?_&oxM̫p|=a;l0~`Z7(BQ]{ktۋ*/Ŝ:cMeP4Ξ/z4z';\.ןJYϛ4r%P.cX8%g`ha8߿(lܸQutt>0rjD0RuU ZW7,rq {"pISөچzqBSC*9 ‹lܑS9糌˕˫GmM3JA 89dAעf Χg9۟uKU.N<;gӘS67%mBp29pgi㬖u3C-M7+ ɂx/`Ȥd#j&`?,w/ӏs&PgGԑa\ĦMdX3轞p5nWH82<u?Kl4H֯|sIb7^7\;sfWLF@9?8r;$m{ @7{2ޒ@}]U J=xX$yuǽdcH|fԾkhA AvQ=wLG16=z穯-8xAB=OW^޽{Oxi1̘^9!4 K`۾b>{pn7T ˆ-hh!1 ! P1 Ӏmzݎ?|ZϮGD)v{(^:ߣC AX'CHE430( ?%hr1:ҍH%3|C1 6n$DzC -%Oz-'%u~?=8Mm m';N_~n%,5͂o%Z??|o۟  ا?i{o:Д~2@A4qҡ9ނȆx~ @AH~T}EжQ4jl el"Dc} ދn(E( BnJ"Te{Zmj]INt&}?+cnzUeY(CCFG(lPLEz /%JikkoF08%s^ -ld0UxFG}n'$R{OߚJxOv02+ұ oxk~%i:hI(r˷~/9mT+;NR7[n˶󏚦˲[v[nZQW?PI9U"CQ(ꛉ>Ҳ%EG~t吙~D#1̚  7CȾe;?qKA]A,;'ق})(+͛crRؐRb_Gf B .K%$GA= v2NJ),0͍DuV*_~p_CLW յFA'Wwu"iqm.`;v)~ :oP]o[|PQIWg/M0;Ho-D׫cSI^ɔCU ]?1x4,'ޒh(CEZ`?Z :u$0CB?ҳѦu_HLsvނn{|V)M>_$Jª)K<̷-Jo4|-Q2)?z1oQ+;f?o0 |K~r1;µ7j.`BzpWU2'Dy@;U-aˆBozHVMF] S_\sgtݲe644\x6MP;5~t[{_xi СN/X> wݟ5wٿ;zZ,PXu ?1;fV:)]dђMM -[^Mp-kص}i?V{8Rr{͈ c0'ci ((HO!;9Xz>2F&T,'=/`J}Nj'(,['}zЅݺh1m{v+57/@~ey)]^Dx ĻabǓ][s 7P 5 b0؀%=F! (B8Y0j_7 p#_HiMG;::5м~s Ut РZ%O"T0>=O)ツ&19- Cw|D0` V?\__rIhblx6f/có00C. H@@:޷)6 B<;X({˾%{?ƸxP/"pT|zjrp%p9jj?~8 Sc[yK.D⪪jj.ett{_7=t/fϼE {cʋ/9~57܀!Ğs?=QS]wމpW_)%Fqo5?aTWWow7p]x5񎷜?܎nW;?(-)BqY 08c6s)bz}Kᯘ{wzC Apd",nW!RIkh.pPJHQm7%ݝ\Ce5+(E%Vzжb2r*_]\A@QS(|a/D$?vjǵ707qx_caAPV0: "^/6r&| Rw̮.;9 I@kM{na +H~Ie˖$C8\9Chl\szgRPJ x )+28Se"4Tщq4669 -ApQ46)9N284DK!8Δ|93Ws4/_tvv!ZQQ .8FQ_?5s qENPnh:lfЗPMs1WR.j<_'5ruƵ]1EM?q( A1"U~`KEkؼa]Bm<9a+Cm#W[J BZQ!~Z5`# _q/k_9ο5+e |2d_g!S9e>qK:s [@pH{ \ݞϏ^=Ϡt)@ӳ~ ѕ2_$[_M1 ]]]1."N攂90w,s9[AJI***iiLFe+oWB)`9jժg0gΜzO3{:UϤ_QgRL 濢Ϛ}αm|.2Pp @윇""`8pR ;=+L~VJ9\þ}wa  1F^i Fr|v;;~.ڋCDBưHau-@Nm Ky'dp|MO ہ__+ uϸN/+ u EpZcV?B S K}RoB%D~skRd2 -?. +V@(ƪk/gEoo/!mI)i*`Z_/_fa V6C>3_Tg#x0~gca\vgq}I\UEum!J [x(0pJ?pwC6zez5,ߒ2SۇM+_ߛĥ75n@@}!-_ٮt C@yOO6~-_K%aF) a<.Rs3e !+Ke|ӟF</|ZWw \.`iF[s9bʂhn![f8xz ~(aXq?-,kMxǒ:X*ehxQpj$~?Ugu~ysj: cnsse9`117^ 5QJ f߲j -*+ &2#~g4EeAk1܁}g8?^{|@OD~^{˂Oq~`_cf P\X7Wө/Ɵz)7*khrV𡶚ysu91^| AOUiP\.DZƟ>i ՙdUx.csg|h-&UMw<kD.W0S9 s=w/a9 }\"y_J3Ls {WsuuXШ]c:@68LStm{׻֏[4W4r)6DZ1pBAKG(Jw]sʹ[4444 K(c5 ӭL]#ʺbwnEe;t~Rr\P8sie mYL;m#mhs]Ey;>~c@rD4o^/wi |E2(i˺=r~"w;n]J)X3f~kǝ~CP很QZ&c;m?]^MsiUT6X4hiP>/\UR*J,Ld<8A`=. /fqsn(d<_s;Ns&ԒpEy!JЫ,Ofr&s'>x- W4 JA!T6l4ѱix]i\UBi9Tßz߭Qv)r4M*vqJP:"` DG?K惱W}tH}%rE&<]#J'JZ3Y~dޟJ~0S2P?.PYSJntaG{ o{S[[&ؤyUEh*(dRi2<4^>ڛ7{{3PU]ףd*Eۋ޾5+eeU Rs$04“{~ ~,lEEE#Ӵ”y$`l| ?S ;+[zvN}i#$c)%m"^ ~ :e%P!pĶm'R_xtiNۯJkB/TuBRL&hs"7Z43WžpQcmG9M,B&BOTO`a]rKud~~hK%$)'"O~~;`2RZZ:Bs%$LLDFѥHdZOWܢưeVP:bVq:c##үA8O]QuR]R4}omΕm;R`,[٥<E%%-P pN%bѥu"m 7MR؎EF&R-ۮ(:l޴s7PmoI+9:ܛ\?COdh~1FxUȂ5>nOed6 JQ6y9))uF{@+g#4MIp/?穮_`%poB?cWFeJb=L0Rt) 2G^_|<#{ju/9n\`(qJ5(iGG+/Y:ηwм{AV1O&Bd4*ЃyV^0NxF7_sڥ,_~7_ZZZXWWK)/ndJ"t7YW^{ijJ~}yyyn薔ʀQJ)0L.Ӽπ7.~ӍjC\0K (PF<.uCKK }}EI0f#"PPKv>XWxqʒ:],W/e7E4o3LƯu](%TBRPʦI3-bq7?ccٔ I(;-Md/;c1Fl&A&v(;H$2-c{ ]7fXSbIj.C)A(aDpd2jWYK||Eح}㚟Y."#D*x2my]a[O=_ s6W :#"Mĭ`]Q7l\ pA2ݦN v_\G,+3[*QrMFt+R?~6olz\D[naBz'-/o Mg>(є]7jO))34S]/ɠbFIn!7^Z]fYO)) %{*Ncp{{;ݸظ1U128va{w7ݩuBl| mtfiM5kvvvƔRonQ*F+wC;rG`[9PÅr8{ּhr{/~iݚw%?j dڒ%KD{j_҆?V?U󸍲LJ͑"T*"Ҫ5;#_r nY.\P@ƪH6{ZKeBXґiY9Dj\ K5vJ1C7&ISu5O/~m9uFeG)(=ᱱ01O6M˸PҲfQ]*jjn a\.BH-d(ŏJ;];گ+/a:W&ObtӼ\*%hX}~_0i7vSq$w& 1 /0|>fe}CGGǔh\J)Z:ko#OՆGʠ4?Iur m``A.iC [ӸjR8#˅se- +k64xd@HA>~nʤj%&JpìkC|FrP(/)qg.( ‘YӧNoLSnb4hs- #= + EezL3XZ⫘,)Ꮄ]S3A 7Dͺgp0fB+.-%P󪜝xS"?viY˥hYӜk[6|41UkjҒ`E;rO[[A O>辽:#C (堶*}{YU37_SjӦ7Ljj(^Ҿo;Oh0t 9G.dЮǽ44.]uUsEׯ_M'q_;rg344s!a:t]!xrl>kSoh[ +/sӇjdLCL]BJET`݆ uNm؊uo>SV}CcY6\$R\b)V]XX0#*g (@JA`L] tuW,xY=#*BU9?q4O'?hA,bҽC8BBB*)Y2Tt(U\R)%@ЦBU#%*Rk۸*kF |]!'pQy#;GFc܌qTP]䝨oP kȃO$Kp  ETqu"Eu MK#[K;'mi~jjܔKIRj֌0,oBiV/k$CQsW-j(ݶS H*yaѤsK`,Kۓn(IOϯq(JQ"?הD2YŤ!{BTpчzo|Y!X"hKdB !(L 6.^|33vnz:;t0)ϲ1VT"9 s=+J% 2g>IƷoL߃ :mS`_G/>\%"f6~*%?T59#[?%ML釾t\X(,yJϧB‰y !(&3i"#cpS&^v׀}u:ĞwEiiz!a %XzGv [q?x;J,:T;%$)=={??Qi͓ Tpd8)U !ྜྷàPG#?/q?r}OΘ1 ~Gُyon()OT B*y5eWUXwK|S~gO+f6֍fEw*WFSST=I}TJQJƔd 5u;zU2,nR?=QPBfr5&# tM#-Ŀt BYY`xj+6ʋcdǾ~()!TB6K ]=qi7zmdȎ$R*J(QD.v S[UNIDATc)rd, !8jJWXs-U'W-%\#%9ȴ%xR+ɟ[٬_XW՜ R[^ '|k@?^ `JLfq=z4B.!: mgX%э4oC`uӌ*zesYh#*̮Hr"!E^ԧB\,.phJ9#)}9>ښxcc@"F(+)¡1ֲ7wv*(}C"?)Y|&x]PPv4 zl# FdES.^ oDOv ^;9 fvH' ; |c,u':q9nSMV#,6d@L# @A"IQTY=21^ gq~&y eE:SXl,<pAw 9 AOw8_M6)Buy<^a&Igr0t E7JpN5JC>,sˡ_xbvR`uv?Vb?] ~Ά:fxڏR1܍k]#$^[B%#='{{.I QxMAf#v5Ν3\*XT>O6u,a)ʘ1F`~7v$pTo:fӜb̛߄yx~ H,L,_SsOd%CM|Pp<[uzJ;L弧)b%f6{D2`ȏQ]%A=|XV؁)g&;M_h>KKʡrz`;8=e6)!J;OmrIcEXf-ۀFp Kz]%\3'{eA9hΑEb7^Sd p8?gUH2M-m]%wM؛ `8{fWFrdž@_邢 `Z_D@r@Hp1 V5֎n( ʋkBbv >XႩ? `:HΫցqζ6,?;T^c Vm" d`(r4upq^b_ ?IL5?g3gK3_3";/e@_ 'HHX~M!D}ÂҒ9RJϫu8gIvVndr6/ZҐe3.* }kj\~hoo?}ÂҲmGH!%#6%8EnY[B)h W/DOespEm_;_~ͅ"_J eŘ]Y,ǁR qH)f &la_T/P˟#sн}BZ T0P¥Xus>}kW}ّ!!eF,c+PBR`rMy@sfϰpYW%8'8{>)@xzYv4D(%p#rwhZm,1h9[i@ BA+-Odښ4d'9Xj: %`L);FxD1ԄlI AWFz FY8) 0DBE.A$BGLVCI[bzZ8ٓÖlg.D.`"b5Qxp`H 0=ͣS% )wƒd΁1&,eT2BkL-S3a #S 3(KL0 7ky$;Ӷ !%rF<(CɜM^p4pnx E(na|pL$ՠnCW.]x.׻ݦw(CJ'iz >7? .MPu&47WyR"HRă 1a+ Kr64d`" RpB .}.(ɮ^~:Q~|]~phqBR X~̓GwcJr. ]>p@jT!?R7 LBQ8u2䇆=|qǑ#0k7Ag $L@g"̢(C=4PDu ~ּ_4UusG:BaNB a$xR*0IJG',@Jep1Q]3Üw*q$%A̫ʿ'R FJTP,h(Tx_yLCV4u:Q9zR1H!.6mb7ܼn-8+4jX8(lX%$qӦ_/6mjc|G7?س0u ` DfYج}bS[:o~z[u&$cKt򳾳SO_nIMhVL8,-QBt*2t Gǿo@":H<=-2OD,]r.qw۞!1('$-Icׁ(Dil1L͟=h"9m.`4ї5@|C~h>?FZG*)pJs) BӓGJB RY+CI3Ar!#!Dc5֭---Z P RnCcIL*K8}Hp?CqF RPt%@[[[k}JUP44hƁT 3]pD^pG%@V4j:'5P/6tC"R E~p.@eyܠ#uqmvv,';=׈L_N ߶6 BW3ݎā;`Y"Né8N$ vudp#"ﴟ:E*k2\{2:yS$ʃ_I~{`b}8sg4p V~67G~%|g81?_׊lfۡi ,2$=o?=r+qN:P O)fš(1"Ts8G/Lc"GSy'hJxqp<I%AU^_1DmFo֖G\^LL_vO*8;r %i?dμ&ӎK6! z8Ʀc dKR1.F@=)X@h/Bft*u\G@ٟR3F+39`nC8/h Sp QS )Dhuq pRRLW=*4ד?|#u $9P[T:X"X"Z|nbsJiW@-_\gT:NO̙vB)NC\~UwrN*a:*X"2Vi;e^r J)d6l[KYA()@Rz0*mG̯k %% #9@W@`OG_}Qs0e۶  R$3ViRI$9|Q!hA-V`h~Yꋚ,vao*$I HQxߪϒ9Xw7 ~i}K]2Q8şld~"@ C?ajD2 Gn0b qq7mˡȂ 6j V%ѷMy[Wcͼ]҆>dˏ~9ig7>eH:Y/}YW4s/L뿃rMZ8zŋߒ|\zN)xW"27gSlq/uLU--9]GY<녿n c C G/D.m{6RkJ񶴴k]Gl~rmؐ_ ߽x% OLSMT{K6/A}k{z'dInul#O@jhf.Ew?==GצoS72àvu|vMZ 9-ԡc'p(KXO80n}] l()gU%KG0f'kh;|`(\.K9(GXbm=+8V, N\z VR^?|c[wbh4H7\{ 9ߋƺr;g>{(}?9͛Wl\JJ4Cf5a"rD/' dՠ<ac0j o57a{6r JϪ >sc*?236293BX2 {1IF]EvPr!p)(,ɰ)5>2H)K"cs,6Ƌ$m=jC&05())]UR&RJn\8P>B" p\9BQd* BiE/.[!p"08B\~ 9/3].pEIi$nY/Ӏ^U@JJt6B\uv(AOWƂի!XԮEoG;8AUQ' ~|WPt}?OO )B!3?~AQʾ DL|P NWBP,kƖR~@/I~|DM3t=Ix:p~vsnyYyQtPkE&&LqDb/8ssuk{¥/Ձ^J22EQ6i)[:{Gܦʮ8`47z]B *; wM#B~U~P(zn[G@]Dq-~~f塞iR:9UMnhg0 I*)ȦI=^>c-wt+c /L=D(l۞?E=Q*K RӐBplΡ~fvG\ljlTW`:%nLDxk:C'30]:Jd,UX8o&2,~F^OH^V=zJ6aiB6ò:6g6&_okkMB&Z *u( 24G6ka0Ϊ@"m94F65ؖJPVms80d:ur!^̧+ $斻ڋx%p "T X\R)_>K3L8 B( ,14nByesLDSm .k'}0 i O"PH26p{p>8^/(H3pTᓼh~YMa- J1 DZC:*nC &J* (ps3q_o).&P ~ x%CBI)!(uǁFS~Yub2y&>Yq !dR)%?|kƠ,"(?vw裳}>7$Z2zJրP1C,}m]HǾޑ%/8I%I(d4u} VP|Wzi{B<○Jo]f}oдRB0g9=^וdz~!?,C[dP;~ @3/2-:G4~aϰe >B]Phi/Dv":R| ¸K 3F]!JEfXK/:=_ZV^:j~3۽am2Jjp )mNpHbArlm m @LR=Ҁ=xh5.EƐ&nd* +穊"}תtkn\OF]wCC7̙4 $Ia'V LӋ;7d~dsLCkLuo {44ǚ@ٜg,¹,Q^tyC~&iLa@Fq`4ti A9Yb*Ik| C<~?t]Cp#1hC<aO_{#xndr4ap$ .nc]w7OC|tFa"iQ ܝQ][g(DG&2p>?&} ]cH0O`w=X%x,T.ӀmD?UkzEDKE1*3R14Em@6NL(r̟s}K9L|3SذubT:J2(MQP f!xL/ AeSο"ب.Bo7}8tku]Õ 01Ixʺa%1 =Pw_6_6vh |YPWH>91A& ݊&;mpF/$ [Dx t:% B*HɑQpAvˬ5 B R(%48J3%эf+8S_s !>7PW8Ps G`2 :X0y Y(˶\!В_sz9wVg-y+\ [J`h篜sjVea͢Ew߈|ZA U'}weeBc8a;90.=/,A"=9$*00;_2?%>W9,RpE4 YR,[T[QQFi\JeJ}m{5  p!:fp1nC69改P%8H/G۰:/ӵZTB7t~4#" 6 Džh,g^Fr`.x $n}SQMR$ 5$-mGchm*Ad04h֣qm48!䍾)**밤¾j  %n,*E<(2M~8xzoPt0:*C:mJ*g&\UO=5u_U锐"a\VJ́[L\QAJ}I8U x4 3!urJ1 "|>6`g!="UUA@3MEƔK+^ޯ B{D~ֳ RY7䠌*)RqҊۀuǪ C BPs)4(ENϷ=x= $thJ1=SQILAB(P %aE*0ٸD_ߴ=)vڊد/yJ3rI"l9)TUer:+;~g.[DMR:rV_//nڊʾܷD|nݺ 4afc%x:ާzq_qg]o_D4NWΫZν3>ٜmn7lK$,nQzz/^9ЇY eXY;_0tbx6v:vKk_cWۼ=풡PS+.DILa8#D2,jD&kрK.[3=ﱛ7Se<˗ͩQȠ'b2ģ<՝DS s]Z 4] VzZ߳n޼jM5ab9@EM7t`d"6o 9!( ^_m]@5nj:;lHh> P1 #Hxp V6F]0Y*H:%мAXC4CpNBx`A 8;::0/t`{(SP_~ ^xB!5̃ճٿ`ь $n3cI]_kKb+E\hX8{qXсqKr[y3FK?&g},s{ҿgUE%q4\qr 3HHOȒf7V}nE]u)wTx1aź_wf7_v2_J) 8oY#4Td,BQÌޱ%!5D2;~o@ bV؅r-:[GeP(RAj?LO(L)p.ME~.7b#B`@fmx|T{D4xLvnPy`@٫CBL#(*A+xM|d: /h$Y se:oPn=G{QR\M&BHg&**028Hu3gu#˽v<:~vce8"̆z};O!ϣm}=sҖ EXlF8aR6!`u:~dgq)u4LJ\M{>FgsvSG-0\%hn$:iªsH04Æt| 0Jr 0S(9;Y/4ӊTRP2Y{?=ݸ{+ |VV0+Sh*ڏ}A J"A -mDih/0r*_#G.$rIߛk. q) n ^mz>C%$%N,i~E%cτ̅Nr}H!\'^}1lV#\9 PϢDXzlma>[$qW?`*0l \ <ؔAAa܎hL z)h& Qppde衇үz݉,:ORb5'Gil,x _821y(s_i+߱=cc?'WnoƜEgTnY9klPBg i; VU1}wgllלC&nbv}ͪ2_0m`.\>{/- RG0"Bf i4ª3[ JP|wϽ|>-_#۷RUAEdйA#x L5;톹_* o=ccc?\:+tRpUQYF\n/>/":2+Van}L~ÚaZs13fm[м3g NadlB1MgaRU?L/clx9=۟oG(pʗ6$f~Uj^[ 1t#ce+ ?~['\'.p%+?K`f]5k`KO3 HŢ,X5g1z nt.e_>poע!Bz0̢"ƣ;P.|o/}3 HD^=LsQ2}E0 N+vli?-@fIɒ>j o!ጕ4#.Ss@Hvé%`[nh8cǩ@:@`%CF]h4c%[Rd,7ܙ(io̔ D[5^bːƇ1|A3a (&M+c䵏],4sp9e3|ॡ2WC"CM.Ż12P4!//sEc~Wٴ@2b9,!br*}f'-G6GgWm =QBӰW+*GCYtZSHJd-=$ȥ`q '@0o!B:chLb"qY lජ8p;L&uuu;{%kxPfXN+PZlܿ!Pto?0AqdǤS.uuu;wƅDQfwA ;G Y_)M KmO;,$ޥbuWٳ4!*ʝwZ,[탡k.Rp.s%d;(5F:ogϞI̜3_h&BI;B(JAHE@+tj$#$ȟ5KS,Z*::-v Y(A؛;: +M!a1;*(9ke_p@ WO <&E5p"/i~gwpB\ C#:/%:޿wP $/!g%qlnp"1II/?ɯby竕SWc=OT mAC,ۇ;>v=Ba} ?kV = Bx鲪d&jzL"dwL'fG y Gƶ>WJUunH 8X|C3<쾯0U|2p$ 5Ћ0fH^8(5 }8xn*ޔzo#!0$C_zc5Ύg? }lzRW+lGfQGI%H,pW ay>wA nt7v̞ pD6+!J U8q9+C9^)(EwUF[2<{^`oBI4]G(upm`ɜj0MmruOˢB:92io}gqw?m0rQ{8?]k,4A)BPS}g#݇μk4fPJ+aM(f=jbƘul:b1;-d-B m[bo<&ա(U#Upj+ TB|AЗOWBxL#\횅J_=.J&Vh aiec10φZ '񏵍 V e3T |430|C0z={AR i?X 4^ -Q-UwM+/ RyLJI8Z,؀ 9P>8a܇y Twt v!! 0@J(!Ξ`P&4O.rrL8-_JJJpA @AA }U 8HoX@.߉* qz0Lpr93,O 7OF^4O)y9,i!i\*3Vas5>p$>jժ{oTLJpa96АMyL"1XʆW;*2v$JBUԇ55h/pT@eEN҉2XN"%NdlH*}jdh _ymPIkè(x4)4䧆H2Gr?B\Бt:sjp uc~EfyQ40rBϠ:U$P:k~~hT\Fj_(ދ,bxB/"AaF6Rԡg\d$R4߻-`ǣs 1Ut_o`ƻ1{ГzdW䦶6Vw'޵%ð (Е Tw~ܴiz}_ߝёF~((\R)rS&;>*iV H­Lt|={*5DiP]Px?7;2;J2A(FLB.: Ųm\g}^ōtf8E+oT:teajbC̻Dv(1bM?D* Dh!1g+Jfr#56%0T-M dnS9߀Y]-pV.N![N˧ CPRᲣJYk$)3M2?ߣhxm;wetcyi`y:MGb[djiB5 U:oU{P!)0p!b 0|IY)}B/ r#/?}_6Z Kjo%mRߔo-ri"ӮU^ATp:c_.;wBdGG?Kopeƞ7ݧ.,^^@ 0:-3KyDy+ՁrOt `#/?2u̚Q! s$5" rŗLͿ/[jmȐ%ե!FA$E ).y7 5_|/_2umpg7݂hE%'U #K4Yܰ㤬a'50Al}fG0ad\wWa\vg$.C5ܔo=PX؂C)冁{#mPSهwORU%oO+_$.PCOڹ |S ݐAB7B0hʄ\\P7ն y_ $u SaB+2;+ Y$u ~RPha?}_@ }5?x+~')@ R(:LʥpB=LNZ[g:rٞ:HC(8*S}'/Qf}Όݧ'cwŘ|(;ب_gfPdtMy;8ǭ]3cyX m&&5&b+6`j?N|}Gpw;(Od1_XP㗾r@y~K)NtBs cY5Ŭ('ѐJB &tA MOYV1>ĊEc_v6VՀ/S:!` |/wxcB`yi^PJ1J0W|mswx3L(?$w ͈__v=Yws?1ky?#Knu\Ek4\po`$(Es͘1k}:ou+4~m^av/+)n\qrC8p笞-̚[5kιl<{ceWlᣟ_3cmHW^xJܲ3s.}jt܁'~`s%嵵e0BFOSx8RA0qY̚Ob" p gB@c 9x-^?\.xPxKi`yF0M(xdrso^.ZdYvzkwtyeƂg`Ŝ%nwj/S{P?ZL~ȡ3?aa(h 8RK#G{SM x&`kX.W0S] u瞪M8܇ܲ}WҪW˲lYewK1B7r(!@ !Ch_B- PDj-c{/r-˶v}oyXdK9gA~4ߝw.In_t@ =|#yl݁r ScL0"m{ Q'ҫY};&* 9Z\`r*9±m<6Kׅ6[OEJd>8!sHK\3BUw㕓JDאԤVy(@gL3 ֩)6ɩMMȇ8o:7R 7Zse!Pd%ClnvhT~/9_>iO"hܾo^ (WU 7ٜ Z`{k&߷5zaXm"1w0e즬a2)i@qρs[Tt>gff%9>*Lv8+ @]`{yI\Р0F\ [M$CLE{}|ܛN 80# 3ud{p{|c7H[ 0_]]N nns $gdu-ZK%>/FW޼]Mm:С]XL5 &srpTl !( E4a7I;^{F:r>8Й&uyVi@HTMOJ'Po QThllB,@}]~/U\^^.?)|vHL?ӣWFs6j8CKN$DC4}АK,iU#$dv%ܩ TkF`-R7xs.d XJiEڻ}:DDz~W t5kp\'~tZmmw vmFZWi$yRZvAa$Ϙ_\IĂB)wz ]X^.}Yb%Kq Z/ ަ>¡~O3fWDIfn$lIg"ARh_?ohWD(OEIF2x$VO<*Vt:p"& \iVN7Mlxjk+n:r %pbP#YSgA fp#"q%{?]rnayM@56}˙. '&+Av; B\sH,za}iɗb[\?c`e P9>GS.Um !ގLH@v ??Llo/2:zv:;4` 22g_.;!>pPr22otW7P=M Sb6tX@ [A%왅ped fvt`meYHOG `mW%*/+mvխ6}3\^>,%7uw'*Dm-$9٫7T YA 6'd(xOxW `VC'H5YC9c˖-ò/tH:'9sxssK.O8?q߇~NxOYnIa:pEAD{B&L,|_8u_|@KT'h04e)Ƀz?bGoa="m !@fx9lrrO* vlވ}к HP 5<㉧?s`Լ Sxuǰ?I2%; 3GUs^`d8]sIw xZ@}" "::J3xm_0[p N93 Zb~AXJf pF8h2|T npfh3y  ,'G!D38׵(a" J T Jf%8?L W! T ` A!(9q_#u 0P*@Wy4ʹ$*</hJ̷??Tւ^~y~Ir0)+HYd0t+ȥu_5hX9,ɧh[t(WA;D|In a%e9iٍfn I?pՄPT%n f`C C~6zcGCM? xj#A,)5ዕ@_S,0y.V !7*Kx$j>;aX *;? FM1dڶbBF:حf4J׊pΝ )G28e /doɀmKokXNR j|-kj8 IsKKu9V-x駣zͯa ˀhq:vo]Qi3۱#5bi Ò|{.v7Ћ.&IĴҡ0c4m/~v eC1ff >)ۓ'i̛Կu\6o‹Gg@}FIXC#>$&&7Zƨ@~tG^$4cs;YQ BT7um&仝h*Kp[-[TW D[΅J"'5 )0<8FSv! 0:_gyF{貗m8tB, LS-HKv*|. !Ar$?0s_ C D %~:={70ME'_ USᠲT`6"g*BCEQIWPbh k oHG0BTd*h[oZRwgՙP}ƣW* B=щ} ] !Y J\wejt$$z)&A "-mq`Q̎DXIa}CSK9 >"m"͂5ٙ GRRI S@W^QYcRzNiRvѽm|݈(Z2LP"!pf"+~#GĞ%Qc2J p(wj3PT8~GU֖Ԅs cf  %%3 >,-55 <ryUE~Iڽzl+LϜ(ͭд ~a@s{;|&(1Çp{?kEڭ +++ZZ]}%#n 'O(:?dd P Z PJ1G1rL Zwn9_zݦ_[{Ć.x1'^JoɖGFM#.cqĸ5뾼$vl > ahm-L^/QZ`Ë-ZaD4{0(VY!UҭE30,/I.n !*Z]] +%Pr V{S@[]<AF$ Ɲ.'߰q^{'UUUW_V+bAφ HBD!fp9{;]\N88ÑD0hD8 &C6[u]1N MEb&3zM; 2M=f;\.aS;\x?]US253(4Q1ܫ`Nw''@D 5 9U"ؾi$Y?V;].>0r.[0?@* nKdjTi6XY@_m}dn/o>d̯dnX{P_]fF+8a3n] wc'p߼ßը_}1YL h@4bWY mX2,~o'\zie%ۼyjװz/"mKE$ )&(@lk 6Q`x ǥlc5#+NL jV:x?~I#3Қ6$55lDAšp䋵/_F0O HMzޮNs|a6$9hC፶Kkjj9O<}M+ݞ<.P"ϒtk S.W˗+|޶%u 8?I+` Q7qp4U?ŠBc @)FdcgK',Hvؠ398vCWQQAYAAl4G /j/ Պv80 l!55 vV,i7%}*:;O##+܌y Sti,33~VvC4Ü.& xgNڌs5Sa̬=~BF0ւן R2pᯯ;5CSu~ʀ!w=f<Hό •@jF&t!m=}{p=bݍq] ;'A`+ Va)L1a(1@8܉.Q:ziջyGg sioSs/C>Y£ϭER sQHI:B[Asi b!{/?`/ aQ>XvpD1,N]M nI +Wڟy^TACX @~ :\vX@XO1B>շ ^4AھE-2+#o jf i qî]K5ny] ZQ89 K aFi 6r~]+**Dۏ'>xJ6 r 6ښNdc-bY}t\0Ҫ*pBTVV 8*QhNJmVl?$3 O0;`{K;DJj5 @Y}օ aZ6 E`hA81jXt^0j88ahA# pTpvSgi45f]SAOCW0fZcʧÕ]U 5AB*cO&4o„3䆪D`h*p)P"!$(1;6ÎMP>s&n(t%zҾ(HMMřgWU+qYg"-- PJ|2…bї¯C3aL(F(DQL(0 !=ZEWrL?~LW|a6Η׿N=88oF}A!; jϺUJ$ӏj}aU8g^ڴiDgV1lx!a 4 7o}muaU8TWUUUu{M_d32Asꈪ: 1=Ӏ( ~}J>|u:\e/lj{PYp%&2\jQgbAYص[ժJAr^ںuI\07UCDP$¶=rU=kϏ'v4b<%35.?{ cVp/jyXϤF~kK$HB~ŠBNDˁ)C"n L78 o\~#@0t{ִ$Ǜc>#&W[GaB{cf19^}ˏMc Q^M0fu͓7i1zMN'g„ĎH 'Sf|?gs>o9אָU'ؕey|Щb+J&u˶lQGkz{~rHVimK&؅1|1_QxAIx-[EOȯl5 ZV9:R]Ϯ($j<̜Tx˶̾uTI&IXg';YB@Tz%5o[6f$}iUݳLڔgU|dBIcM 0ĂaMοmYU|___?Y d3?i{}`h|ޥEiސMwGnQBS`FxB$[VVnݵ@k Y\Ė6YqsOZo۵G!ՕDR"5(n5O\ߺ6w: Kfqogo]lY ]m pcP4bd$?O<NHEmG2:ĩ_ꟷc.>!|7 nݪ񞨚fic?]'|q|q||bIrv9̙)?19{?Ɩ"E[~?lk3x{{_mmm*డsJ2ظl٥=9G=oܸ9&R?nN_[}>#z*!=o]fuyHiPǒgڱo~7^}̼L&#%%kV\DMޅyLj0,'yID7ƁO~BMb>;>z'^WoMJʾQH޻Gt*@op~}K>v_?7dr9$;mT(3~ɨ4{wGG' ]ͯuvviY {/`36ÈmHآ "W!A_sڮC>\q;GGb1lȠB\Ĥ؞``^M ; l\s8h=gOӷ&0ZCVk_m6(-Mjj=gs{?~䛶]#̓h)$1!x07x(7PX2Zٳg_S {\$-~ jiD4:l2I("ɇc]H: ]{lkayq3p#$@%`R'@ۙl( ?2z]qB9j\s-gnU:3htuGGի?=X]] ι@)5~rYw>=pxVaŒ:'EʋN~Ʀ7,[;T1:90 Co!~| FF i=0fT ̒ @LwP fY4!Hc؏'́bWwt4,᾵+`B`'-RXT _s]+/?ܖ_q}N[m|w"" K $vGLmb~:  5P,w0!9!\ js DO_2oڐ~O7oڔR_mξesgA5=֔[~f޲)-{c7/?f_oޞ2ܤCx9j[Kseu̼q-4/RY3~3v+910ޑh{1%9i)cHuoy҉RsS]|NvZ./#MqpeX,Yi WzW$RO+ 7 ynОJFۧ3Ff:i䰦wE2FnҷGfgdBb{H ]X 9ggggZMnOVձ"??//4:-sٞP ogH}ﺳ?| -\'2Y}9_N/<%Y)y`d-&OLS[{'SBOr\r8ʚ5ϵi*7OSqQY y+4Y>vq''vqpeyڵQFf,=Жwm)sկCV2Jz줤ҳgN^`x)[h0=}?_SYI f+pNJY)!Lt__ҷ\jN>,:27y?۲J9&ʱZG:d`fg?-4n4n35?~<=4v"TQfQ nJH@WjS'Ou,tʕ¨1,\0м`G59^1ed3!ҝ ¨AF唫^/,@tnW3m"m9*]ŽB@Dy9NDzbc Y[8*SNhZ@sX>g"uIJ2SXvS[>`1PXv+-IJ,,%j+Ss./wC Iw3Ē͢ʅG9'O<=g>JW4_>T M煓l}+9IzTp)OՍd._~Y<֕4O~qU#f@F^.ea_ b =?xD:RjMNrЩPfY*|)=VIEO/rqT?xUX]rOkЈ[a b`7.H7v55rrΜ69[@]6%3$?ļTzLu5VMu{6kso3.cuZ`nM ~6͞vjjYtBC}RV7 kٽ oz;~Bj^g5(>Ri~3jӻҾ{')uGwX!e_~Xos'Q_6cϏ"֯o* MǷQ}ӫ,*-5: |9jqcՉ֯EQ'3.q*3,D:1~(ͱ|V'2^ޝB>o1;awd}u?A _m޻E6s_َۗ I2Y1}ԓ*VlQjDJ鄩uuO=Б\ro%H$9si.k_B{cH@G}K>}B2L&{~OW{ޝSظr-̓&3G~聎̝ޯ.yIl߱%I5֘ym;21S '_ SrPA@k㟆<ڞ:c9z"sYlr^}ORʕZXtUJ 0^ʣ&aza7gɰz/ 6?u>D [_5QpD;0!z/ k [^ 6=lɞĤO H8.jJuu:| ^9}Hy4#%z&=R"*y W{7>0G/7`P?P#'wR0hO3{ʇtQHv^䤶.|b:_T;pPxzo~9EaCG|~f:'VIɜ>ڰ)ŝ5;y,Z~ K>iɆDO99\Cئ/ӏ'J%*)4CLu1H `8{2sGk N㽔ߖ[,KFzӈnrݗa-_uս){/Mκ~ɺTW ^~{G_)vdX旞x3#\d-qI@H">L@8JHE>Ŕ© [z?1+ݞ<.P"ϒtk S.W˗+|޶%u 8?bHh^n̦IyS {w0˕?XKեÅΫ2xkJRK8@l>5[p&!I#9rR%HG2gNAqy1A+`@MpY W]I[3`ifؼeu Qs&+&J͹aVf%%[QhOՀQ)PxCڹ j-OE̒Jk>s`d;&u&}>̾ŵݭ{Ʒ6ت*OsL^Ø Z@mm/K|g֦[T)C2ScR}G˸Ap܏_捌 .Nг) $ s)#1onE+7@$-L֝k1 U8(lkmxe~2;>̤[7~hT- ۊZzZo5k6z5CZuGm~ax˙[?R7}q?9XIqht { _`KA)fGϭ9orHv'$i4bøY8𾖐3ui˫44;Ĝ)= x~X3ؒ=< gRj*@s~(qҟ ☞/0JZ蛝E{Z ZCWqO X[6soUɁNyaDQx` dn-1 _nXqWUQSi_1`Tqq7} >9]uxAƨvq/zbCþ~ssOq8wpL`]{v~{*eY|.e*!ڵ Ϸ_},35JAvc3P=_² J9i|~2RPNIW(Ɔ{+Kt9.@|okwm<9G䱥c#03&ߵs~N1' THxΝOho^[Ks#uh'TǒYw^TJ F8Ǣ.y9>vm_4aY6 e\fb@Ʌ@}yuJHjE4p.~hW/}tKYLE*?`[q,+y%z皒8,_#v؝qAW2K!XMߔ;%q֙}mˆbcޢl*!Bs]SBuvٛ򿒖,! ה)^INJ,!W\NW )Sl'R?oa w\juN8 M.ͼo?S<6󇎼R#:l2o]IWxK h_-(>sGvm^٨{op·۲4cɑg?ZpYT}~>jń?\sKl蓯57;SFp,Xn'%v747Q +&>ݰ{׈|C464`1a- yN9;Wʔ#^JHɚ-"t# P A t.-[Rˆűx /R2g oEPX 8*L V C*p V#iiik*l,jWn2fŇꢒ9FŨ_bg ]))w_#]Q&]$-1C5](y>"]/MXBY$$ ˆvHu1j4++pP`D@V\7~#]ʗr@))2z'>ϧ23zHW0̠31U#~2A=G/Iy 3izPWe}tUѣ2A:y?9w肤2]joQ˜jb*~x@9àY2U{AV9@9m"&DΉ䆭w~(GaVj?\Q.OlYn^͇瑚=.,'2eM0^k #vgbPdMߵgyWq\Mj:H2)flJ*'h3dDdCޏ'AUYA#Tׂ Rd@6[ MM$Y$id1v-ZzիUV뤐Udꫵ!#o?b_kCebsbljsfO$V΄ Ko:ads\iowdvg"Yp&'eb8zW0H{_!6{>`iT6Yò֭OHKnКWir6yiQcd4MdA8m SBMX]bl ь1`YsdaQf6Rȡ(]%Ɂw>[}r0bfk%{ɯQ.ɒd³o@87Jb-*h䜁{Ĕ(YWvjׯ>5'J;Ҳ l DI$:B:ܞ;pFRV~<\Hee Eu5+PpzV{.w,T%B(%  p@At&Zt-)ss#TVRzؕa e0jS 0DeW3%sIјz#v2NHN}@uU CUBP`O5Y])KJ}E CD+7~bB+7@=]<*%жNa5M6f VswMeԣxI'pCr_S>og@`tBnbvf rwɗ]1-H[\)nM,#Ab[0(j 6?5QGlVܢחC,,Lw_NA웾$3G]}~mv%^a(r:tL!( !>sɘ{G =(zopP`:D!"pB~B̏M pH|*?|g6q W?"7>ء,j̀ʁ9R=sQ)(AJJI$R:&<~sDKÚapQeAFB 6fpds= "GU~zgL_&NM!6dIADD`3™dCZO#[VAcL;x81ؐVi  aPY6Z7-d/xT2x9]f4[m, vFƧ [F3 %Ɔ,nƢ9$T DUi(.>xRXWenꝌ),Յ`F*N(dd- @oav|f,Z!YN#z(S"1*AyIHqI4 –?-~lىaǗ% #<E)C00'6`ϊ " h`n/>[$Va6(Q2:3'l'[?$DD=Xֈ1#/^]WZe JME2!j*pGH)Xο*9YUV_?-J-"AB@3R#,`V+^qoA.uAq?xzji%ngHq;` #jC(FTy`Td%!7E1lUrOH~GڸAsҨ7W3h3D5_W JDZf@DA _"tN@A)6Dt $݀ql_)N@@R gAe(  q;b{"62њ@(!]dKS lG/~~Ey KrOBmiZ!Iɩ 'TO<'P"gS)M pA0 ܁e~H'#bV'>s2"w@)R%vzC KH@s:(/`$4EtsEđ{2ںlDT,L3TT du~! $9ɂ\t.\xB>en\$,`K,QRl3鸾n\g@Nל;sR D!V0$:s \VD0A78LQ z"$ :\ND~@TG(!iOG&.T@g1#v%%I msŕ%`Ht,+l)$sN7@찎Ԃ=]iHcўlQEdO<'NmFg=ϙ L5 "5 *L `0 0]6`%rSo_w/7Il 8ɆeUKM<:d0`˰ &3@i J%~{?O}ſg鮍у=E ݈=6II`%`AEL}?O}?;uc;7|-?2zP~T0@(pIXl:n00N A2ɷxsdta~D@5CgqHA$a0@l:`2va"e$dm =bI:n~o9ըfpʤI תq|d[N>$x9@uh_iXE 4I5 Np`F!1蚷ͮq:;Zӓ*j@@kb|JCrU81x|#b;~-&\ AUub7{0_\)ړjТVځ/܊{g ADCPD@D`d׸ ۩t-ϯ_KWڒ2\UB~?؄]A,Z y "%ABa+??tٕΕH$૦(vv3,FG PD"y6)]gRa'{I<9zShGb2ޤݐ(&uU"O/]w$%/D>MFp>熒i[R"G'~C5y [}p-HMD!;QT~6t%怳Ŋq?QE(MA8GOD4 SR&ξj$|L`>EDĸ=4 *%tIϔmu$ {ܱ ݯsꮇyvSG  i)K2.擂ՆJ8dl܏s2Yhp^5=e | Q)v9m܌S&hE0:gaSH4k潁yVG/#^NC^f*DM H|p۬ B91-.>nDeT pK6xnqs)))ᕕ5aj;DJ,υ*GdBt o]“ az7=}v۞nw<{ϑ%hiWۈhG|N{9<)umG ంdCоo?=^6f\| `o\f`ymş֣"`9)4. 9mmGL6pzolڄc`tR:TOBJ *C/I;€!n!1û1?pB 9IR7WM^Jً LJ$&@ ␬dT@VIMexBpS7 IL՚d҄5"tT@6[EvssոdR[;8/malw{\U*10څMF9?(r8J5{W{+'(9, *n yFoQ5E9_u2q7wȸd?)C0B Yƀ!;tly7nQ=^6{x{L6M0#"^]bſW,BF21޵7O_{IDN42^! oÎo'[fnVVqR^rv 3T\};1dVԡN?AOK67XH&L$ ¥0RWQ#o㖸q<}JB0'l!E&P xJqſ7jA(h@0Swx.hsھg|# ]{/#`Ԋ9\zf"f7"`\?q QЪ2A&1 vɘ:ڞF&:@Q g7"`'.DӧT}jZyڦO'(9lx8bnW=GOI,a]PɊ(*rD +_е şHkDqhAc:|v;KQV ,%X_[jZ#?EI*.weHȷqjfy+lWkPbZd]`ë-CJOrRkȦ/Y.I&!: L %f}ih?b?xN<GV=tSQa7t!)C5(Rڇ0َ4=,aDA f49pty{@ЊQӓ]ۍը\D51xS5Z@qǓqPQ;' \UO/0yۮ jbP al{\Ȳ+X/]҂Vr |z #;tFH Q {xhwK̯*qQ8ilGvb!x@ ~SUOFzA?#z9<OU]Lq]M~i+ `K@PNE/25fZտIhښ;_L7Z$3%e7TGmbC[78p<'MPײW$YN rP56RPLNGĐ|~zz|\F2; ,KVJ+sR._X.mcQ"v[0$?=}xe0z Gl6qj-srr; V7 ֫ZE.k* X9 I Bp: tvÅ2m3m0g /\1 ª2:;{ٻCpѠ7X667x&qI{sۻTU&Ԁˡ]kCqs%FƎ((7K"m [ߩ*/{"`7A]g܏+{&᰸wn.GLc~EG W.Y0+ظC/k=gǖ_ ]gl/ r8$!U}HJ.-+ To:_otmS! z)!@8"PRŤv|Ygh$XNaTz|I´BOcֹPy_5I̹$q֔kcyuCO{y{?ןf}߫ŒGտ~,=dv͝s>yf˷ 9,\EjCGvőph604:-yf{_?9K8Zx)6gMfC6W3j(Mxn9BlwcEIJη$1 oW"Tc8ϟR]}ddo5Y( u5wt%=*dob}IEeHy%Y q4o%1dtw o& ~(:|Yŀt>惐Ue}iFrHqXs-{g40')i#^rdL"t# `" `P(E,u֖-)af #R{LtjO!pE BS5D+ՠ猖t}`< -xO_6sr8^*=*Zs 6bYxm_=``d>YhM; 9̷?LӜc8-`-a۳-fm_9t @ ґ"<"O4m/h8sO}?i\QM3lW[48ۥ#S(vy <uTUQTWޞ%e$0AvX)隿yQUEǢEmN**w&aU2{rIeh̠`0-#7L6'P鸏XCBP^% ڔgSC!`偮 Hg=ҷIgʡ"0𶯕$[asBe 'x;~?&XxC$J 0F(^1K_OwyZajB2k- ud.~?%tӧ=7n$BK&y~=UPtW~.-sG_($m]gY Y4a/RPbV'uNe=zr{,OhMMu;ɔtpKtiB nZb uGdcx|s]!55>mXM!q^)_t y߱7`B-П}͔$@ $? W,:љB]ڰwk)į7|V[- xJ[:~Oi99@ʰZ@#*Ձd&x8U\l??k8򂼙 1Jm*g'{uW{ŭM&rnN?KgqAyI:^r+Gvo|?NV7(vG_2Ld`;M~;O9u !]FXQ̈́L΅oIgt;N Ovh|PH"[nb!pNPJF~5l T$B5uf|`Y^YY#=l5j vbH& ` )0 1nP5٭ԡR@mqkG8C>3A&h;p` 3 þ[w>tO{H*SUU%TWW}.njYjCGzus?Iͮ9%gYtv_' yk읗`.M &(GscYxv/*jv=zobYsD2%#EW[H/0@\ 5a^MLv%Rj?+zwmIïnH!srm/=l q3WZz^Z4Lu59%8|yI棐(s"6ųُ&I;r=/1Cw_=~}yIq_4{ ­V&'HبNY@oim9k.S]퍝77x6l_첤>a+&$vspMHzd@h4#[6ﱣv=sVW'KR͌sp"c/sµp}i_?j+1m-|nSDzxз}꥟Ŗlg:>6r$ ߪ ~:Q?ӗ ׵V퐇Cd*<Ђikm!chk_>p`A`D9YҘhKW4;yyH !2>lQS|ٓvvuS[L#-Y֢3:ap-+v'Bb,{w\?[kHw;>x&Q֔n0J !{w>_KdvׂQ͑}_X|GZ7npJAf& x꩹ftZXeY`;*L08z|A߿w[ ?K>uވ4C6/^481_2{2 i! .!?SoZL77&jo\䲁wçG4=V~ A]ieO[2Χͮt1"a?<EF"E#xi$e`v%d5*++oyXuYO;9fS4VM)fTT p#wݏZh-)irMo'h Vx nGDifMoDԹ-1սYZfHp;Ý:D ҎUo'v~ Wv i?/?A ҁp_ ҍC(w_H Bv:u{cK"(Ʈ@cIL4c>|4,c4-cbW0ET@)lomtc_cv9g;3S1Z d^dr0.bd Guft%+$T]Zc5=>@Ln"˛Tq^umOh'&Lr,lU#:$X]FmfZ7K$/tŧ<;c|Tx2Y22Tu=O?iL[DY==vL*)---T,QId2M4 Iޯ2MƅO}ITW^xExY6 2П ;(TY1-N~^ߗ0KlI{ڟ@qQ7{L +Šҿ=ъ3fm=K ey_qj%#򕆽$K$2Ynn_}7mI+>!]^rpĠ^mœ\8,q68r6]5+d)&cBfB"DQT2]e Ce{C-dYf9s>7ohˉ1nw)ɘlGA7YfLќ( N5+l̒#}qQRV9c& NU` CgF"!$dE(F2__r)+%3۶IsύOO5͑4$D3xT"E9W#Kne9xp 8x La3w iiS  ȶ8*1"M)@0O!=3z%DIBIɷmX}~(Sa{/ &y+@8Bye܊Kw o(87 R@m!7mYc3& : Ͼ{%A rWbp_OڀU Y|kt k饫N0m5R0Cl୫{sVAHx4<14Ȉ d k[?<1+3+VpbKd-}cZƍ@`>_YMF2-_X!ds7?G~V5'C$w,G7P`36}|<14HI*-}X ٖe_'St+%IeڹK($&^_$/l*^+B4PVV/̚q!JO:jÅPXe%; _γu=4\>SsGSé"hh_RƏ'! pu/=3z?'"l -^'꧸XIr8!vsɉR6C7-+SPN?I ] TlsӰ$g'`PNً^HN?])46KW5 tƄP[/=+Mo`d? Y#'d#}k6|kSFPvA8 z0݅Xև5[`H" 1 ,\d" M3O( ()pC& fM7bNOTUHS`ʸ*z.aXolNd:C]NB3up҉C)Κ3 V$–waa3'_4s~{'xI2}ԅ否8sLSv6dwtQ.TFCB`ZppO( ܃ N19x H:cPE=?i.?8^;Z۹dt=QQz]MWK+ $Yb+Qʴnzưm(ldd7>U{cuF.ޤ_;b8oH[CAf76hQC\RdBz q;D1XgSenzɭB,! uuti$/Pشݑp|Iɑ@JĬ ˽5H$TZcԤv`} P~bW#wbϲJ2hK$m1\Yj g%wxn$q$JXPGKlP`Wʲg횦ϕY[.'kլx~-rdb uҲt{T.qcD 1oZI~>b`=hz]iu-ïߺpW}ϜW k{FӷK53xՠa#g1FtͺI77alhsyy!LAȽ irV{u-rUN~y*)T#ۤ"sx7R\O_⸞9=J6]B&LD)>Obj@oF{oƴa\ZݴPohBC{'NTJmw-Mw(E ~s1umch~Sy".,xWc4 Y#Y'ό3kd˕˽O: HrvѷXHEE]r -Jӛ~r9n9\wY8nH TX \vL̾`.>ZՍ~I &r|/I+$ԎD73k2 .A6CSbx:,|Ҥ~R|A OmL% L?t o/߀ËqYb'ؑ+*s5vdP>,mbrue>Y݄*Kś:0Tig޲Z?vR-D~Gj6%|x?bUC+Fσ\NTG6axI_|1fຟI (_1p< 7op"p~b$B·pfY{sv6ub9P B6|цPIê 1Lzp3iTe[_4'0{X ǂD*?W2uѢELAN}䅟IW[MQ hGڀ>g68t5w3{Mi>5k}۞i:9}6{:[WH=(8@'#Q>xYd4WΤ~.D!) Җ % Z6LrP7BR3hu`k˟hq}/[ܿ]ݒXQ* RąBz]8oT2hE*cty1Ξ< NEt Y-%Rs﹠8BH}Z)2\pdWqdΝ g6 .Œkqmm4Hg/d)аcܩ?TWTT8#mi1Gr#qm`9S<1_: FOnd{:1*Ջ"3DqK%E-lջorrYnmOu%$4_!o1T"ۉ.1gF !|b9VrrJ2q@I5Ws&"hO/݈v qݹ1uD128~&Q)д_vdY PU%c4Tĺ qxRxˆ dPCS}\x7*NEUj *)cF{G'vލ68)pZCɠjaQ8tI`}G}@C2Z9H;/^,c_W}W?Z_xg%xQ G@܆?i g9'cZCVQsAG>861z\16-L,םńQu*,}q͔5xwIXL?b\F;&|SxҘ>RN߿,KϻTʋ"& 1P2_@b\WuƜw{tk!^$קeJt-DN*DHA K{+blyE( ȆxܔC0 . ˲ 9 2EqUQI/6û|~zEM¶ﰺV 0fTB;Ұ~y  JB~7&LrǶew&2l}䒖B M~ZZ3TPBeŐ~h@]*.@aA4P U‚0F+{sۂᯜ?훻h1 "8%(;(3 *C!'UR LrֺmStgQIy((.El0^ǟ1 tj>]鶋.[䪂zx>$KD`ɻbէb䘱ؽk'?!s:4igu>L!ꫯŋ1el۶ p?I`i&Z}@P~BWLOBsΫn+fPx<;3ÿ"]#-Rˈ T:K|/Ӵ?va(Ӧh6}M|eMoZ'P޶bf.t|.x˰d:!!᫔fQ (ჽy4! ]zK ðy됋tߓE V,g+Չu\ ½D93P;L?!Bג7E뿃E%SE4^U="=(a5o& VGjab?3H||/Z -vGv*qv4Q,ê뉕4*-uFfmfqS[c[lF 9ٕ ta0!8Zz:TFqw~\&l('+:e_x/{SVHa,X0 ,aI(- 3ٳ8@!'8t۰m&# bջo$1ᄓ @ 3ۄL@oL"f[&mC߷M L<8>Bc=8"6=82tp!0P '.uY Ka6!@rT!(e +,Rvquϒ |a?2PUN{ld:,iP4au~eo!.&׺sX p^`;=MtbƒAe @K70 ZKӨShNkצ-td~(ᅴ% !5HDV)O@ܲi)>0Vx熰#D n;]ReMxE|6/B!e\}^UH:&{^NxdUO۟pK<ҚwcS-}yJΉkFR[>ONEXu&wS= !܃`ɒ% $b(?\?J Z 9$B"PTkn .$-w!A(Ptϓcu)g n_v`z§}Ǖ߸I6c0t/1>?~çO% m# ;$9rt@r!@xB3tٌu|3,N2J8tI|Ņ0 X9;ݾX;.{H)_Dک֚kW7svP8Y  ݀gyg~=Rr;;6&/)E\\*.̚&ҹ\C?wm| qxHr)O^UV\d+- 95d>.]썞a9G?w׈CmRC?oȞ#ʪy|5* S\y^+z;woyݩ.wZ9a-{\sUzՐm"W ;Úbl_\g۝57DW?a{|97=n|96u7M\Sr94k>\nM=@r;Mc;vU/>At+-_JI3̲Vq;WFtG ʊ':,skӮlê=:"eXvwsaxdmmm칏[F^|Ҧ&oǃmB43.T>w[dQpTU:3!̰ SyU:O)o^=-il;5ool~$< <%K{vCZh>;mݝ.;{8Y[+r{H'pY]xG(L8nG6v㍷lVuIvbcKXؐg7n,͈5N]DL}EUUIo 9C  k@"ol d 0 =-n}cc󨅾6e׮%VD"G'z/ l~t||ToODG2c: h?K3rv+%k=+ b>lD7cG^(zw?v|M(̳{?RJ.(/vv?486Eџ_G\\ xC߿|q}}mV~d8:q_yT>|!Ha-Y"yFI_mѯJģ_>U%K$̙,DWn}|ň^M_=1Tr;ϧOgM<Eu!g+ n$ C-JVƙF1?m:^Z33fk+"bo~ ,#=m^u&"17mk]~2 ɭ<8]]d4߮Â:B"8*᧶\GB-L%kɞf.z,`7vs;^>=`\s{C??չ#v Z6'27u @"GQS/4wթer;ݼ]-HVd_cS@re!qt/-^6 `N_t6]eCB߁9#h~s6C޼eHnXcRc?T7:PD;SN-ۚ_,'Xݒ N6uP 97V -|9 Ubq BRa|ӐEC#/AY oP&T<и.B Әtb$>{l Dxɨ? 9ۛ uvwdrHHdRduvv&w/]x%Bq|G(x5Hh(ޢPQ=zFm,fQ: >zBGq0#LYi9Fޯ_XRŞ(r˜1cDmm>η]X Ks;-cRȿ/ {2L1EE"XS_ergRTT$_ԁ/Kj{ٜ?Os0KLqpn,,l6dbRvI|ZJRZ*.*HE2;H$D:nFͅ@o Tq+*J׼`4Ln7{GW7L: O0fWmh-p;L{Բr&gc_Y/>!ᐭhW2 iΘ8z Z[,#\s,9WɧU4p[Z:eܴ=_rٰONYQ68;\)׭Zm]1 &g{?"0h*Cl:VK.I ;NQI\ٲ+otL~N;@6m}J_v'H<lE; 3Z x= \E^q;@r߮ȗf:pmdu N= Wv 64xPdN*,e$EsPTT$]7nFzjFuY?*a6̙6 zHRY%讝:jFy )9r4@ t9v*E8&e ̲hoFT U 8Ab`LP#!(Oix+mN)]Hrr !9y|2  ivx $H$rnyۆikz; 9ezk[gɆH#_m݉; Icu΅M5 ͓GAcl0o<){b%ib}!(!W٦|ltWϝ Y*2YJ3(D& ( @"!5*sI[*s)5u_sȔ 6w83x04d`gd~Z.ƪh65ca'L0t4+8)-eFMd1ijtYtHȢccNؤw鶑~"}v}h}*6;]y֯r߽{{~pnB91}9@9xJ*e==>{t*V"*I$,79zZhi D=ݱd㟞hyyL( >==lcS"s5_OE=*r raU}CBJ$!QK1Fr10nwk @s\5-gG=gASkc[sH)|K×TGA""2%<#ڣ75`=_* E$B4.D[W* G$D$!4b4zoj;4p1,Xnt;TU) LD&wꦶHX097:]6Heo:3-C'{8NGS+FS9KUAi1ô;r:[ܓ_V=NUz}ڍv4YV öeYY\IStTY R$E,;_/Nz>{`"othYeE/6d12;L\[z'Dq1#|n{ݗ:MQ0,Vc2}nkb׽:+oxjmy4-C73s;:Pobyߣ^P!@iOY5d uvYU]E$+reTE+b{\O<ϛ1Ѻ d K|} ].UV4i>1tvf4"k_ޤy]RƲmKh*c˕eM)eNU6TbA?t~_.֔73fkNM6cTC:Mrhӆz^( ED/ ȹzb +J] GpdB0*P5PϴaY6ⱘHk|wH$w˂ EJe 'DpaWZn~{1BSߊöz)+֯xGagHdBA_ (R,B4bu;ڢT=//>١:^zR  e!I[\C?'24 ߮(.ph_~~??9@kgh4shxF*.*.r:>ٵ3=3N/Ȃ h*)V^/ # m[ޜZi5 B4>a <'55>U~%qzg7D^>1ˑ>eJ2,[}\{<1?`}j,М^Ƹe$IB pc& .QQQ`>x`Ȧe[2!/ vEqTЎJ~cES5f2dfOX:>ϯ}lD{*u _!8`JTJ=vCueB :^hJ\ZXX(J-m*ȑ 6"3ϋkдCRjkkmby! WE_|j] N~YL3v=Jw~~\S05N:c|N.)ƺ]KJEW/b{ mI~W ]W"ymݤOqgEO*S"W@2uu@$:{^dܢB) EW(Y@!˶m)gu^G*TemJҥ%^%Jd2(-۶].l >!؏|+ <-!`! ܴ."'2M鯏Fqϩy ۲$*)be^ F~8!3.Uu!&Kvsm[Ҿ20,یn&yH %Ȓ,˒eIB!Am6!TtP E6Ġ3HN, Lu9a}WΌ4/? + O|s$ىdZNdY` ٬N v9m70-@̛7OD"XR͵,˶lRJ I*@ra&BD풠:wOHdc@%s#߽oΘTڑvvOFo-bV&[v{+N\ǖmmi֫}:ME~Bl&vީ.r(~:~c gȱM[w!J%-/=yֵ^]uG:bsot ݟbc'TJٞ-/xT֎ 8dꌌcpн3aJh-q1񫀍8UwtuQcJ>7[o:m 9H|RE0)8L4D"Hg g'(w9㎯*ݾf?Q |4M;g˴DLB2ŬǢq, !pWZP0g qͯ+u?>04-ۜ6a3%r +*>r?鷑k~ݻ>ӇV sʙs.EMH Aa:!2NU>U" [ir8\f*Q 6Gu؉XDJAwhqUIO+**QJds-ULD)8,P ӑ5-BBpJUUNڽ}>f&Xv˩Lcpز]E:_wa?B<lirj.Wfd)yLS C Ś ۑLg}0ezzXNSK-7ѣ4za<2(l'l K*|*Vt;|nUȑHnSYp"+敽2dJ) *Ro驙U7&"kOmmiw p-5OxAڜe" Xc\ rrw{|3<2=v ;]}>4gOu&Ҷ)tⓧ㶅UeZmζ̃f+y${w>슸PݛrZ|;oaYV8c^UƧot_7 CӞʚaF[rO/,-FK7:|'qjs|pP5X7qW|2٠K,C-QȌ &a|߹XU)*U5e59R\s:gi $*3ơ& BAȇ_\}>y \UH kϑ۳){|VCeaSBdQ^:ǡw;n{+oRuV k~ݻ>,r ڌp>q0,I%5YEo}ft)eMTUYa8l.d!AlH%)2ug? %YB&Ȍ1X .`dI#K MmM@"QX,Y&O\zv\b[x-zbKq pJ~lo:,QzuiתWH3+>'o0Hl[x-%*)Y۷_ fقۙ {m?SF]ض㎛c[q=~-=V-}A4Dl/f_SvungΜgv98NO tKM 9ȲH. WzNj{o\d?f/UʣUT!clEɤ.*>$dev/@ Є PZ L^b8ز C7騮`0-J| D\*9Z⦟GUiz29V,NO6 ,a mh pplѩ&@v_ttع]4҆n,(aX̩!95ol.0ÄB)(ibWK7I#M,e[ҼrP lF6 N"l,9u31//WyfbDhDY\ŷI< $`@"ۑ.KJN fvS`њK+][0 DW|:|ä̈3vSe9/ 0pW ٭™qݮ-`2[3ە-oJZpͯ}^јJKd0THRNNܖM:.meQ`8WMK/#`Aߨ&-b3^=+%?eN(LΗ\A BM8/HS/?%+.WW喝#tus[}Rv0o7:_ҲI0_J4>w+󊡸ڟzweثȱ$?C٧raƠJTvhi2S w7dYft?{&_P7 DAЃ*26bź0 ww)&ӃYEQX8=J7CQpAl NpPR<CHqpJ0mL[ *I85!$7Ak{ 6[SIezH0WǸ6g7T( d t,4EuL`B|x{c7(92q(2ǎnG ^$BЛʠ7jʋ14 T: Ss ]x?4ESbZ_aak&0j &V:h IzlrySݯ--8O$et ә!Sd4v> He|Y@|d 0D@i!G0$lO+ &08ʲhc%Yh , p<TQQƆ-; 0P3 X-]<*C%p>rzpVz Y b%SIDATNgo/Džle  @)>";96(* < 8L&vː)%?s# ہn a<.p!` A3?Ũ*3 .] !ۨ,S@elc!0: Ep*Zq 8চ"a*IȄc03M\ pIL=*Kh={WW 22,ĉxg6<`'N]eQ́zD\-MVˎJ"7&((@,dـJ,CP#At7\$VgD"B~ʖ.rύczxA dIHJKB%Ϯo֧6 p! @:g B@"R_ӺTNy:"Ī.IL˂26 `@:G2wj4oM^퇧V KLeTA)@)rʰ,LNBmQ  Uʪ!@DuV_"òmJ$3r:Xt^פ B,n.GORU.ːӄߐD"3D!)GI9GbL>F".\(͟?߈6EL~Ot[PHx 5pBbB&\ėV/,^\'?{Y 5S/0@dM0E-;'B)Mzq!<߱ei_ZSU\2 b@r,.,΀S ܘ'L *$D4&vR1KJq+[()9CQ>q39K w1]H'e&$A Z`lXb2s^ZrzM_PKNmL9gReY2wCg,B6Rq OOz]hE~§e 9/;[lT*'%̭>@}  sê"L}RRBx3pGb[L gR вo~c fܥ82c@<mg9] _g?LദS4ANx;2m8[dH14?zĖh3Y* 9AyiݰWN/Qhˇiy_Rf0(T@Ft ]y/m!#~|ANpn&)QXE 8'P!` NJ^/ֿ=y8PXPX&=a+oE#* #G[$n!N0H1\BPaN}]Y 'љq!@WXbwaYʠ.ۂҦJΡgʂzD[ߛ{zG,"dM\,wQ);Mٝv $`LzB| l>$n?uUTtvTwÖ~d~(5s3lXuDn3w&] WE[w߲^GOB!8YEY$Ɍ8i. ġІlYo#j O?tE,DVX˥9df[6Y?Io޼P!esCI&>k@I>bi)y Pk.?|j1aroUxY~~?hH[8!bنVEnMI@4L sVR6MF1a]ȾٵA¦P(@k7":XAg\d<ܟ6ܼJu9qt倡Rwi#2 ƿyoA\8u+\ Ύ41㩜dö- ,mu9ԯ;㯼>{}n5l_\e;4۴- x6,wG嵣r_9:<߄%脿]6tpg[6#fs،5wnv?Zr<;[G#5#'~@#G{z;1tv{pIy!lOmYc *@d ;ĝwض/,1ў<@6SϱV aٸq3E._^DDO7?[Vx fkPZ<#?B-wnF*DF;_s^SgaC%r1+0 "GlcӶ@39qmyrOcWI0̋QŮy_p`KgkR$Axϟ{z݅[u:BH 90(쇪ߗ14ԓ@sJ[m݇ύ??t0& B՘m}>$EE)`Ht՗;SI6h%y+/ɍ;Q% 8$88$ID&v"p {p]2;Zrh90%tNr?ݓdDl6PasOoCfd p_< x7aG3m\=l}u8P434&l?/=ẐW{6-mD khzCWW >w*Z~P0}}5؋&  rx>!6 Y# f Gitm`2$on%76?(Vm{U?uKH3XZVV1| OwozI~a%+ nyʻ93wz}ceI=+{}߷ۼ$l]w-h+á]ǟYpx Gҿs/X=CMFp f$ ?Οżm*cѪBnJ]==Wɹ@kؽYj.'߭N&֔cŦf{00Ǎ8u̝Q5[ZG \BU\}νݭʹcdla9).*s˚N >\ gMy>NeŘK~ֶGڒ?tρQƸBlrb; ݼ&{eu>ݵ%#T4C)B!2JU%$α۔y $]O뻻\h6D"PYp#\  $s/;i]QWC%NҦj8;9Z>Ě RArΙd+iSU91M/|،t妉vp<3DŽ5 ]l"p\?px,.,橅!%7,=s[U :f^‡~ͳu 5'Uc@yS\$׼ԉ*uȢyG?s_X kln>1.XUMm>dѤfph1Q/wRu۸~;{/(+q+aZK`[W9yIXfgמ apﱍ +W/ v%~x2znh!)5;"DV2- /l~Cb!*R9mh¶1a3NUexcgul)gtl98HPÁi)vbFLagT7}v`c(+lFX=ԡiGa#mPCL)rGQ%UJ)S(p2ǧ D%Q(~֍{O*;Je-+b \0nZR4^)(~ރ:SrU1++˲ڿ6w՟\Re-+ o,({?;xfOOg%ӄѵuuu4%dF͈otϻmutE<RQF,nױۏaq3|.l?jo;LVo˧à:M(}فt:)nRzM@5^Jw  pwEtiQQ9- חMr8|)Bh`L@8zs<4|fYC1)`T%=/aa{khC z\*TɜEVvP)zhZI/ H!p2!m FCmN (5=p @po*K,˂N0(!\ST*lVOp66A()Y·ۺq=<@&xm_ B9K9ta z 7|H^d=gE$땂Pq%,:&+<̙ J/ B;ؒ96~_/B;:/ KۛQJwr(]c6#gϦX}nw-͛Q2CٳKtl63%ND.XRM6.BUK@ss'!P b3fݽ 7gϖ`>hڱ( Hgrhߋ7_s ZΜ^?=X= b+f70r8tREbIC&t;wiݴXG}W97Hrs(hùaH6v !RH* ݆Pe oi36.(CN~6lZƔL6kRBR4?E\7[nAn0!=|WƟa- ~=p?pfeӛZpw'sk,[yۧ'E]%?L춦O}c &m̧,Z#e[{>}iu}g@Kr̮.0f59wc(Qjğhv$$lkWѝQu$ @r:JJJN~{~e Yvu@=Th2|nIm<,= *a{^d_a8دoY3\fL{@͠Am烶Cb TznB$uwV^XE.η\ڽj\5S?( -xPNo G2W/|v^;g~vyiⅯ l 7OW|8yoy|;Y{>;N⽏?zcɒWɲOd?<@pCo򹜗j:DS ˴r՘fwC'2Gf57ݮK6DSE,K׍d6\N_YYzTCTiјճv/t9cGOzdP@Leޞw7~ߐG% 3U7=nbǥ7 3'DOo׻4c‚pL2/ZXXP>(zwc%:ݲm!ק@f>&QD"葿=S0v%FԳ;zÙѻڂ: <=232zwwάr )y/τDUeDwwN}=LxKTEB{wrcvﯨ?$1R)%EÖT֕k ~q - (\3hAIѰ%SJK 꾜p)_]dpiq]yQaMa(zDa(T-(.]RpRO%Ņ%u5@@x<` TWW-)-=, 9&Y2{D@T^-ضr&/G^T0"^ 핾ʙQm,^&:( ^ꪘwF%t%I˜3 ʙRzz1O@ ^,V\Ï/ۿ3ƶryXqFn…"92z*΃vs0J(9:ˡ| EA2ǏVTC7O+ܓ̘CU[7VTZtI8޸YU:q7 —bQvv!!߸\WtKl=1>/$g%'/Afd Qơs9.[;/vi Vg2s+|Arľh3Qq>D?/`jgW#wgltrL#_O#Uk 8c'2٫سx!Sai/3I!rYҪ2CwAW$I/K;8,obAyPL|is~L#;3X"w=FlN_V~݀)0)0>jߪ.r Դ%u=)>Ā5v6gaQ10iV7T@kC*gF"x"* JYTsooI9MFJ~{̾o ]\3Lհlj38gaT7 Ua;ι3qp 9V(y1Bω{ ˝ȯF:g K+頹hhQ*}^>9*ᳵ&{9]U\dc8,GNv7\V!)g3*Y)ɪX"AIk=2AJڜoICˎahFk)qg)ۛz;MMdjB HMI! H آSl,wk%m}+-pxY癝<3vg[<|ٖ) 6F`e>ϽiJ*fSbN۵&:F$]츒"A^|f6Wir }ρMׇ^%䑄t_]л9oz~ϸ*;)YCf v‡3~;>_42 %`6 ӂ€E(3,x4.=B. AEPǨ a90lbrK#[hO~@WE!˶rk(@B´l %>.eA*~ўa p sc)i9I8{]+`+PR}/ kgxJ4a:;c/v!,3 'X,E,` B,]K./{ ;z6˃U )Hr _S?q 6`'X`o%9W(KΟ^v\t]s;k>X۶68ĎYiU%S[!qTmWQd0=TS]7?p7=IJ?~]x)/=~fh^!)}+f C ^5DW^7ii%ŗ[qonaCOfHTm{7eݓ>ލ,zc e Yf+4fwCz-fQݧjcʼ]p/0e9~+̀C8#<ʎ0d`KM`oiAm|9^u T   = ӹQR[b?V/Cc2+ ;=ɭoBz`ʔr% nbQ3AXѠL=_sej*֭[|lbnar_ٸt"e{{ͲFY3WVoO[:ݶ2te~|!d3М9GT=sD-DpߍӏSǑc8z( 3Zaf_WS-CxUd A3Iu!%8b*h?l!+}Enly53jJ1.U,xvBEs3c-R^\V=bj\@k|pd?G%Zʗ.]0ЉBϘډP574]scD{/-6:3g{Kye%ꚹ;^}w~lKuuf/pȪ[J|lUEm;?{@]Z767;w_v̅ʼ4^ Xrܹ jnV:t,*O#68D $&zR4T8=F2ּB Mh[:pD~ʆ8Пu3f­+qC8WEcVS !]/4K @D 3R}RyC?a}Zpc#1:֫ 05`>mo`~P#M䤨ڥş%dSq>TÌyCG̸/6@دd !h5ﲚET2d H{ĴspuS:kwhz_ZnHK ?3 . =v~WM Ywh~Y ʟX_b&{[Q[T7Ҧo)v~SQ,rHN[ZȊٍUd ~)_הi[2a3xqȽPtGIxaHhaשziV_e_I`{d7?-3 6cŋEjͣwGNiJ*+lr5P1wNc t ?5ۖMٻ_yw7Ms39 %UVZU=|uc ALYۤxqX$xۥw,j* a\ r6Aőe%W8 ߴIQெ)Ͽ(znx8c کAְꝗ̙Đ/'NPkUޝĺQ 1( {b}k HT!}dOpX!7n[*8rU|=ΤwwdH ֏sch~yN8Ŏ>Ua>|.ٞx #FV$\6>!5$Gd)VyU5MdSо91b=oEUh;:[`W*Xz*T֩L*E[ \ǷxD}=kꩣzUe,h^Uا }Ux/]VuU-eCꦏj[3o6Е]*T/ϟ?gW_8NZ+l>ikG%W]{++rn%ʼcp\xob |Y_Uҙ+c|\,z8l6܉ɾY.UR] aΙi\`}@~0szm-`㗔TO>qtsI(031 bJ\ɀҊ :Lw6lߚ_2aYw b(\\A,D$KCz"Yt%%gQn`>lC9%#ڕeRY(39IY)J]PX ?GɌPhNIįzeI}Yƴa9ᜩ1$"lu%b|hQ .]UAqċX\ 8z8Ⅲp*łk}}=uu'Tup9*lAث£sp t.͋ /jo猡,g nMG [B[<l4$X: c F5hS ]&L (P*oZqOH{=bZ -b*1F57t,]:& WU}WTD6X丯2X".1FZpN d΄ |`g\z}Hqhc]WK_ե0}>ݝ85HPt=7/}< <1H?v^,z`=:܆l57AUUng|\/ѓSgl&&KܴD>ّ=e+ֱ+֡zJR<3m x65z4қD^??袱%7tJ+[!}=ϠT ۘ3vj\6͕HT/ӯ{AGW,[00uW\wn)xVȩ^lw#-_Z7EΛ:6uˤV?+H9ȮFۥpb 0 Ŗp6mHX__χXTL\^8nؠwC,[Ъo}5_;ruq;T8\l[6츱7}ߐ_ۢ(<# &?#{ݖ}h_߻-6 RX$SHe"לd: |%wXC6wn{r}ַZ9I@ !evKѱ[%WPjcC pB:xpӦ͹D089-. p%uuƲK1A ;wD_e\&h\C$4[bY:i3d~0vI闄DD9W2s΅C$@0,g8P9QhNhjvdƕB!$]zLd^g3 BH**LA{$Z=hVx"~W:c,' ܺ@lGPI)=ڵ-샏jٵ }SM`pПL̛P "@J") 2ְ>`݅pdRb TiN &mmIm[Oo\^:NYx ophԧĶ-W Tie&0B `TmO( v^>MeMŋ`Xcclc~x OI(mگ(dU@4DPIx}BڒmNE˔M% uo;#+]};r U3^Ikf.~ ;< R;OWфuOX*>$<ؽ@钽?\Es!J2tQ&(\TtMן>o9-jWa{#Ҙ[Ltџ̣6râ5yJ2ZZeٹP[0[=ʿhNp;IkjtFƾO>/b8b'G`aPϺ3x+><:AWmv>;Gi~"E},eq LT߳.iRikfio)&dsc{K{7IUuS>G]M{QVV.RFw_>Ћq]2jCO0vכ>zO*SxwݔO.ܴYj Se#Q/?wm45[Fb{pc-EQY=; \w@ o=E'ZŁ ӆǍ$:qD;^},)ʢ7ڪ&^|0mYlB@2@`QHTLFj;k ؖő[.咍Uw$a 4tdzx%@)WЗ V 6e9" ="0[yɾ r$xً, XU5aGZ*A wx빋ǠYSrd-z"0nsHPլ]\| Qm+J=QE4n 1dcHR­vSUWat"ڟ@/s^MGFUm= R߲o~|0#O!DD|G tƐဧ?q94$ OQDЭoVGGέuI"_0y|\MfVK+t)A?cO'ASu.>>ˇmM`0X뚰KA.U8;~xg 88ST!1~,d5( ?% 9wbʊ *^"٦pӉR@h|IQo`tx4F #tǂ)&f$!/&g.IQA?u'N )x >*5@8&_UΚ0BH/aðl*Thx;qI?wٺ</W[_ؘnM^%:xͯ_667:;aߝX1R`5eI*f8m\ڿTLndrxp+v)/kWg䖭L_<_)!D(sιU}gL2+p|&\tuuɗhdظCo.;K^o'T2YX .c?| SzTI‰f<>ZT}R%|j~pqP 3ug X*B$w*lb j_݇jY醗SVJ`42oF7t$L~>U)/07maQ@ :!֧Ճcj~ʲi*S\B,k iJV҅;B@x`/w0Ls7q~T&45E?ɗ*YI]];?cj k OǯS[ZD[>TJ|&>Ԗ>-uu hT|~)GUYhH-KcdX\^z'kyꉣDeA+ΟI\{P_Q_YP>d>#8O3Òs-nDE c7%ܾ`곦^Дtn efXmHM}^QJ!a{2ukĹ'Ԅ\.TflؖD-">z.Z&`/edQ9 ?$G"tܕΩ E hT/mKxG k_^V$5_/!> KumBJ??J,S@z_ I$z3&4+5#+wea0L7\\7iR*-_[6o3Ta?6;&esJW*Vn[L0lb][ 0\h~S;(#V<y砍=x}+QB% L\nrزKש-=}P(kw|N_L~DB]3q9c4kZ'ǠrY !|e-pAUALLckCFo#0\o9 :H0~S1y)3GapIe2̤u QqhН̀g2P2S Yu ?·ݥ :3yeyeѝ͂gL:^%LKsa sW]S>Ek恜+e+@A-}>MVϜLQ?yT>爈 0zd'㛑ͤ* 4 L>Ĩ`t퇘9c3A2+t|>|emmΉͱT6KiӤToΝC+AP%T~tJF)mf)N˲?2?9_  *_~x_A_a S:RnY}]eƖzcP*3 5a#2|jB2b p׫ e TUBWA|?&!Tv!"4|boW M8~ 6G}0s K/]Gĩ^/A\A7MP~0>(=5[]'D3dD}[Y,,}o_)ݺw^m~g}9J |joi )kkPBMD w}VQ^>F}_~1ln_s=k?8JGuԑh#{L:_*h8>#?4]F:*JKywgpgg+݌}/@IEz_m=[_O ;a]*/܇ N!L$n{p/>9X6糏=״ʮkT +3O?se!}a ko3-]TY\3o<W\1rUB}`5#Gom=?7ر{?sa5~1 އڬ<^2mE 33/ gQ_φj,DpSLL?1dYJܹ\sC餇ox≷VWW_> 錝J%[;kwJ؋[kj.c|~&dkgGǟu4D>^9~p'DG>˟{u?`ru4 ?᱗#z"]a?:x~aөO3Oi1`ٲeOڶM㘹\NIeeYd&!m۴lٲ'A~I$0 emYdc) ~a]a8pζLUضϰ1 6{> خ8HH$YU+1a}bQEEŒ)S٬mY&䒈 ! 8mKrbѨ[>_@m۟}:>B8 ]|S5'>#߱mp0~XmC]`1K.Ucwq&M>WJe: 9sٴ.p&M|<|,\x7 7qfσ2@F7?nPfX9Pf3c|lqX$g_lX:-~&WT&CHB:cA84R@L1Ug2X,d _xxqSjL3w dv. r4d-0S3e“My,ɢ mf`fȥbHwj:y~vUbYۚf oE&I$Ekߊ5+Tݵ't?Suն5ooEdd>ok{o;oIK7af:?V8nL>ZcSs1s.<]Wr_[Ν<è|QbwPyǷHRU90ܺnxdk vCeFo',ȅLj_ްf8eD`^N퇙oRLqVE".+ EF@!tWCHƅmbV7Y`'rje3@U^0@IdZ`n% vR3\63з/W^76A#@UU{P9C.ُ_C7az{}HC{Qu`./73I?jaHmmFuakOa /џ~TѕOcn` ,~8nx`] ,+?)+"ST ;_W/ /]yk d9yvߠiU?x37mxaQrO&%sƢm^)l zU ,;1or`8*wkzes?%q?\ ?1Z'6-rJ2X"S]ϯ%D U]wU6r-.=sO=kE.Ui9wNtCuAL״{L:p4psw;[tƟlxa gOr-r\f.7V0HuAtc[` +b ?rU#o0z斿WMb]\6GGv Bthzo[m!LtH%rUN(|fSWb_"][ I455KO<Ң?paGS#ȫ9b+Uװ1F`wDg0cFWS(v ˰v14r_Q\Q1Fhc{SCcQ_&Z5@s5 - Z^ <-P !-x7I SR33vQv|z}g(Om{ m+CkF S :m]gaT0ƨa||WvݴLQy/݁S Vj)$rxX_yF[fM||vۚ?߆?o AJBgV/{ #;?Z cCL9c4ֻf/9\._~[G@`BH Y{Ix/=ckk=yYdH[ζJtwr0YɱD}ҙ9K<:,.l* ֲ;2 . pa@e;Ѳ 4 Ɣ.a{5BP5 x2>mmjAUht;{2R^`;io~_o֮8UIb 5EƦVgv,zRIzgX GxG]IijYG&{X%"VO*ؓNfY8ݜqGx~.'`o>Sb/x&??ƻ*ˏ8,oI%9f#ZXևݏ=6턢P4lډ{Xև8șNw*o=#A8bhkm!cӐt5xl(9,Gt˞t#D(0:mG7y;~UcPUB g:7csW o&Fk )MՠzRo+tf(G:~O?!Ivsѳ[;{xwNu/^hdw?s5x hll5bt{EQ%ed?vq)%9BggFg6͇fX:X1z HeR-=ر]Vܚq`9">ܚ"DTfK?,p=աk!c$W$Ǯ޾}&.$!A,kP81„dG+H afB$t1p'0N (SA* 38 cZ;)^!WT")=EUΞuE!*I@OZ'ko| _ It&L6\Q"3)IBEd_\&UHJd:Tp+HJNtr'ko|E,ɜ!@p ]cʐHHP5K1D(.x%NCT6T6Lr&u *^Qg;;^t 0H0HtYQ`7 g H*fT99mt~fU.ؓ7>N(~&P47 ӄ8`LPbT؎4hn:`mY ʥؓ#p06n GJ ϯf ir#نK&ؓ7>mdh{cz۶aR4(D4A i :z۶퍧`S ߘY,{'m[v`P8g 1(CH vvֺO=b{b(ԽZ4oFv'mtKǎ\.{4ɤ~05H}3);¡Ď;[W  /g˗ .txfMtT%^ b@6  (`4&O~A]vW.ƽ=2_wo;a^0Br $8L(`*Z/^t7=got^W@UTR0/ cN 'zt'zW?|GMbgT7 2FʢzV9Y}5_/8#{ON"pyG˗;*D. \D&zW?x7N17_<ߩH1#`(䫝2)|ENG|k}@Vߵpͬ;g1bs&7$UX$~Pv7/.w60h?XS;r,-9H$`/hNܱcӿ=c_׌P=Ksmۜq#~$ I͛:֞s}7} rv$r…ח/`#\û;=8Wן&g) !prV>txteW0V S<< ctǬ*Ӽ1w(8 !.p <MS8paTC+GGy<+ |BJ6z,kHƊGM$`) :t%p*xdh^?6u̼Qu"ASg2?}Č75-kwZVH@mx 8$(#V 1I*'0\ B.CsglTNcAAҺ'@|>Vh^ضA0J@R{4o3C6b/˴ d-rsI1XM/ .lݓq oU4MRw+ͅ|6MltO>Lto1S}ϡ` =1|3PV^# K+疑ag3\: W-˂OQJg܋kć8u,GHWF&;}Tn8,vn02;᠆XΆgS rC۟12}x #'rI @&=G2 G`ڄ@IĐYCL/>Џ&pGpƐ,e'B>/`cg˅arh?`w@6po{1<gPz\8ND"NS Hh`/ƁZ` n#x"~ #;:KN@yYQ;RcwyC>m,F`L]ؗ4L̬r!ՑMi?\R20cQiE%4>lAliŴ}Hs/DxhОўꃪ߹6ӚA%Ŝg2L嬵Rҥ#Lͻ.PY<N_~zӫG =M8}Q$W*xr6ޓo>uhR`' GpG`[[DQV9򀂣y*1\ou')HG1eb-qE8ba$=p}rH>uE1b^1zy]]x"X<5x}EpѨ2ϻ=58>sF4. u:WߥUG~#gz`˃sǞv;w0 R./CC:d9Dy^2dTL?>F{3' w 2Ȋ0/b)J0l0(*y㰱q(*A 6 M72yt^Vg==7^o6 ~OĦMڀc@h6‡&ًXujęƱ98vh1k*T#sHXd^?X.7 c.ԓ(^z:&CMYZ8$…Ǝb@68;? _Fqd{&:]!fM61,]KtWA4gO.q6wFޢxó9'`جC$۶.g_9X1ۇy!7VgN)vqEY>hcjl'&$0pCql`uA-!+aMI&02A تh{d\!E!H`t(-v6 W; ňH!r>[7n@/D V1s*Y$8@@RD C:.&` .K˽p=,b X#M/ColUc*\^w T_@I.#% 4t'_PX?_|JUxR2S0ҝ3]5 8@/!TMHv8m<9ik1l|k9R1639DC.{J7ѻvx@*f Q?{s.^m8?E'~۹ ] 81F6tgU3%,~4n,^Hw[̝L2k %>pG>#<ڶ"xQ Nt.~dEMˢ?kŊ?umĊ1 ґ> 25Ao6yhu Y1v&b Mg@Ȧ`xmS׳fB,N] 1$b9ڶ\^s D? "CҧAn䇫<a^7]k`RŋD&c!xn|~nmgB 4v>1DG,b1ѱXկŎ 18 FA,2\ʦnGa 2W`*\s} "oP4FỼ$4 0PLafpԐp0s'e`Bl ?E@̄;;|*2dsP4pwoa5PB3Hއ'^%IKnQqsUZS˴b2 `4>pSYL-vT_<$[י{asmtE)4)Y>/lE*&x BQA0+J&iP:Έ*0ۆ=(a__fk?'f76fYKPQ E"T} .kQV2L'T͏p(aݱl~#WWfHQpIpU ɘ !h:YŠp \e G }cӌ,hG?|:A?RwhCW7zG̅P@t@&*E!Y!9Ҷwi+UC(k## @J@ (د p KqߠE'}|*kH\ϗO W5 3098>;vL.Wq]c k~(MC5 #B.u5nEh 0 2y[Q8x 6I!>H*1"ק?#2 ,eB/w&ʡ9q#6tcCcE`T\)a!&|)BQ݀ I"- q&oEcĊ]V[51 C-)HD^ĉ A "a±,#kNO|/YGBԵP]߻~dƨQ_W_ nLJ.@wO00|OxXaXZ* 4@K>޹p7WUSN,׼0_߼W]; w!;IAx<׳0qV  $P'n(=kc{󛛛o3.z Sfɇ?(Y`h?'PϟPςfو< eO0_Y`gݺ^fx`~\ .]>JT',p2YŊvm=:H[WTf9qUčT8g$OPhʔ)vui/|gݵAKg2- 3Ya*-;xN(D_rgLcHәn^Nٞ>5z0Q=Y>>_̧Oɯ\ZW,ntjn|%s?M?v0 .~1էy]T"Z7XUQ*ݦeҝx@?{+JcUEtSH$T*\HDruһ=>rAB\TBRlYgd/b?&_952Ϋ$1)K#*Y}W=y#呁y?n.xH^|u;a9f)VV}wCZ_WIϋN<;ȱ!%I1pELW[-k''?r6i 6:f1n-c}r((KUR(" a9L$ڑaM6{br7 c};7yL(*⨊uU*``pHv) q-bocpgѾ0 Y6/ W x=T` Bd Tg_*U[;đ ˊCBL UUw񍜁D"љL$>C Ư8{oYoFjcA&k?۟w~q$yc* }3TUc N?d/[w!G T}nOV2 $Tm=qhAR +*y=8\.T*՚en9$w=n\͗C>ဿq,%,';m> QS^e{ =&$ ۲LL:dd2y棿\Vn/ {k}^W eو2N4|>0 w7e"DzY__{D"6p-G֏r5xtW B (Blk^OO64bj+ ovN:()L i g]ę$ў6MP\ϾuWw/&0C$1sWK1ƸƮ@drQ vu;AKu*"RaKIm#c 鬉d A 1Wv~z–-f9c30%씀s`?O90id>dp>aA>SkZƫ^ߖҶP!UGHՑRB#TqD0a#FPm硢b$i;8BB UH ێ#D")S~|5Q*vy ӶmQcQVMA/%A=?nFuSS(K?!Pq﵅-G(#U1BmZ#^ ̫>0~Pq0Ȅ#qTG!T[q' .Aau?qyzqqlq*Sxնqlr. ɯcG8(optǴi9?THrFU #w6Qض-QB%)Usv"̈w';.;n:%ALKۏUh?* Dzm֨26Brq]^=567;!BdJ9#:8޹&f5{r8NT~ּuvnܝk_" Ϥ_(>(`&9f,$;M |7}i i30| <Ѭc|2ǹCkr|i\FO 6*il𤰱:Vq% __uȹ+Y$ ccpQge(z|ڗ`Cuh?"s#m3p0d0<@h]̞\fX-HGuR bٶ,|vMsؚ> !d_]DHqaǧ{k(/}#$]ߡ0zK!WQ\ ܺr!p*IB~]}~S۫{.lI.%A e 2#4I^9#Jq|nlfDĥ,[ 0-81&ϕX"nݺ&W{uLa$. )lH@8,+ ؎ ÐG_;v/p_R VGަh"<)v ~޾ Q]uG;*{TiBN%GYǐ-p !мmsh"Hcq OR~\[Y5O # E6|F&2w_ }_).SU=u3qpn1-*cw-$y.@3K/B0\qÀ|ƕ>;>Cs35? }K)ɒT 0o> z\ ܇\7%$|.iP e!dn]#NA5 .E!ô' RJU4OY!LUQ(k9e)nb$AU83Li1R >oQ&4}.@")&%C*v~;901! ^5=GSl* ]Ϳ . 4BGp%5ϾwnX,h̀)ILv,] )_++_qc{>SӴ)9b~ [xLхxY x1zd%><:Gro@l"+ OdhF0 8S(:aF_~k1 ߷ @Uqıl2L# 8\HȋxhS9FO//}ӓٟՊLdӪ|D#aGTryUt&LA{\;p&؎FҠ)Â# 3M4g' >Aӥ$ 1\|Qc%C4Fx]Ae TL/eoqҭUUU dsr׍S/?t<8^h^ps(O/451 #clۆFuQ+Pd`Io0bǩ_>gK7wn@h*@Q฽;ͭ= vI< ̭&ڭa;ۙ٫kJ| WRѺ/=Y(c/bcұzxgdrw#l _/)#wpETp汯ܙ?ui?RP81#v֧H=pɷ'Պv w(ߦ$p-{Ο=u;b0{mwߧ!4a =BGsr?I-8e>|X4D!;Rf%ko5-*L)E2^}CPuu8ѱ_>۵WpH P@vB* # _J"*5sgfE[Bt]v-d6Af?gh KbK1CxT0`; ADqc[4X" ?eN&} Ǥb\z/>* "O gHeek?BXcJDQ8'q(GOs0wQa1w@r?+:]AIai)Xx4L8H _ތq^[?( BJ"bB$2 >_@6i^L|m{=1<`5|S/Bl"v? "R>l>CW|"vğ̤PT>Jb=gay^?F'|_ĪL TOS6'#T2j6r%cR$Q\=z6#Xn^ 9( Ў8qʗZ`/!_F3x%i`}7}I/ɗhyvr@l:.^ێ-© p:<ذȴ|҇3'ePVbf^K̝lpH810mej?Vbk[= #J@Lgv . gz46XKJC$l)y"Qp @l+8QV6~0Ou>QQIqL8bL3c;qlNl&!bS\0Șb[ .~9g*^5-*RjќM"sa tu4!N¶t/  y~|1іr` g+( <\P L;Kb-b(MMbxriTxhI`qۜEuǁ<⎍M,aT i1<<|B` )fC6- >(Q_.x$="3=1Xg8$Ɯ >۠PhiLC! qBb1?B2n²N'"2pZ+(UeyZ h-198`eß~ z/A1UC0aB80a>1>>T(?*^@˩izsĵslɪ"#\JAKCs`" w }EZٺv#ߐ6`L`ȯ046$beXwch% =c|Ǚc8 ܅_|R1B̶P,bhrv{ǚt:>>s8kVMjz`,&wؿߥ_?1S95(W>o_*=R_NHL䊓/;O Cщ,`bj kVtUe'G_ҩJCT*4h# 0:@ all9d"P TGKew`D@F̜(H1>YK{F1- Mugmx`>ҹ9{&} 5h0-9 svԙ*S|lr|;k\s*S88;t;:dTR)c$dImP .>'Dcgbg80,CİkͿƜ|~ϳoL4gxW;q`d  a eL+x=OWscN%!=A"dCR +PZmccϡ!=?Z# $[ij*449y #Iw= g)/ M,>.9foZ{;,oRF|ӈyRFm7"uglj;Zo`ĈS&Կ ag48?Nh|ħM/]!s.a@Mܳl?N&?IbOp2y[;ދSf v'D`gl ⬉y#1g~5wxfEe@t@`\1¹+ ̶'7ߜ[wlCJ(gל?/:9s>;cA+v>+AR"},Z҅Z .pmxiv?J 4olht.~T" c ѐn3l}ldS\$8?c7*nJtdrK9$ 5f- ͌qNsSɛ/`>0szVu$BMh!A*BGچF)9N0 w64$bFkC RkHڐ : Lpg-tvuf4J*m!wq t@ha(g"+kZ6cnk ;v ` %twX((K_  POg18ҁ Ĺ JIMx9%А^c?l$ݑ}p#3; PA! d! U{}{*cߍlX64E,g'>qϫm?1PAIDBѿUB!*>cm?Ճr3Oi 5BB4ܘFǠ;9!@+lC(r<@0vZ?v}'a#oSqQ Ȉ֥+ӌRy~ >h{vC/sw9aG`#?uYhE7OyqLu-q$w)-Ǫ_}1w=C Trϳpv;|.};<|~1/3۹Hu&Gkn>7}iV:-1 ޅퟦ^Z Ji޶?Z Ղ Y{A3@T|'X=&1u1F6 ßΦǮBq-5- ?7С4;<o%xկ鷾ecPJ/U`xDФMs1X=Gx,>g˾JAB $<\r!.Ajc-F|0X@=v]?t Ϻ&~R&5;I\Kش$0+cJg,dМN἞WknFs8!)[7EhSbaT&|m`}mxxCx#a `p40E=8fJDa }|^0a4f|[q{S<_=J0(j΅R5L:7\v.^l0Z k p:x~ש0'\| 4sB50?x3_4Dg}MoۿMA_A][5X|dik+9οK\8;Q4dY6=q=k?E)@1/-K 6Phhoz,VOS]c?Wu}U@`,jlv d#-zi ^\Ο"_kфmjcOl5wy@?6-CY7k7e><9W $WDH (e0 lÕntk7ڰA4\OJXBIv6phB欜[~ukR Y۠ڰW\w|^B*6\0H)!236/ydxʛ6>Q;"Q{}pTײPъDCi\ru/sW~'jӑfGNPJa&Rk-ud3?RH\{]v"ó-X'Ziu}~݀ ZkkR-x;v":i7N2G QH@"nUz 54`Jbj\B:QGPaL+hUXc\H 2ȍ pR>#*,}heV2T(s0F@cGof"|v}w|jhj A W#_GY.r'u׻̩r55rs\?^p5,6 qkjU.^OW_3Ź|J1!ߑWG;RrO r D,փfK`G𵵒9te'Q7{i.-WŖ<̖~nOY?%biE[FM 3FR~JྦྷO Pa%*xG!a2Du@ԝ){#55N~_{` h dqxO~sN@?e9|ߋN`2ϕS{ 04YA&A$l:Ip T,ضoTD'?Rx?$naupMR՚8# [Ǣk|L|`gpmPڸ=[)arÅ*FUL+є*gE#1,!:/sS ܩ@kB~':aHAh?{ֆ!C{,{Jw{U9ԏnΞn;h~^lFqEУcLǎG߶,59ʁKM^693 ÐϕS{ A<2ƎN7졾\R2]E\ˢbgudg d>GͿ9ӻ~@1Qo{e͔ak=4E-NsbV+1@^wǀ>a:evKTYuɏOW%&(R$2fvgI4]ϋ=n t&%_)#`DF׎^C-o{p&\o\ulDuZ4kKf׃guZzW9#6y_ qcI/:`لysJ`~r/oϏ~XxcG>ivebp74&X\q<˻S/oSEŎ͊cA"\Upa۳hU!c_?_2kWL&V 92I$A2/X}otz'oE[{ "z&źL_n>-<݀;}L`Y'+`jҍO Tmc}v~m1i]_Gbw1 2D~6M¯_3F\k<_~ Z3V^r7>V KئM`b 0U+Űd/!L=PK.kvv8g5ˡ,,@NMWl{*?Ra?'v0}M/8nMZ|,_w7{ A (}>Br+]?aL2/$ 7E0y8{<{MAo?g #o*Ɵu:Emt_9"6C_٤ 5M7xa|44އ}rFh~G[$>HTU*%dB/01;9-ζ >N"C;6h Jm q`l42~ ӧğӖ6Zu۶㺽{q׉ZrmTx w}L"">hGxc lgqz:? |Yދփ9hd\bd'~|qُ?96Bc`̱Oʏ1z\%L$9Owz|K`0z_–gς/T>Ϳeu<~K٘Iz?M8c؍5J?:#̛knÝؾ]ǂ3 "^/~!¦ {!YS}^y$_]_,@צm<#p\)u 0ӧ P+WPs{Iԁ\O^%&0j?斍Kj7VpC*$fQQ( :'}7E#i'[w$['Cd5Og(7  @ ??߂?"Z06R':?p;D#z~ 3p+t /qc׽1O^ 2gOPX"/S dpT—,mF[ )%'c\5oZ^Q<;~*Dkm ;쿣>5(!56+c![M#FlzWe k5["$,U՞mDPT0߱@ G@wOoh,ùmc _b ZFkWڍ7cn׃hHR)ƘE |` )lkid)X@°w |xC̓]Q,:> 0LT:e']LS6X(cJ=h} P4# [:(Xb0^v\F8, lhI7 n/Q,fO0Da#'^#ƔrE,[x?_lKyK[桏nu+V~F{ׁ׎_WGuP X`06Gd\C \Egߚjl[>Je>r~WƼ=GÃ:T5(;«% u:KԐ1;SZ9Xqno{-xpMO 3(-ijIX1c7h[>><sY"0Svr存q`J4 /Pϱ|R{:ڢw p9c@p V2QOv//FG8XDY1nF{Z  [qnǧWאB[oӱ4 3H?7܉>o4E8O[1LCD|}~o/q#! 7[|`n7vbɞwŎTVHVEt?Xs} ^Pg`{;D -:1۲H~4h2[[W?F.Zvb:[CtR ?8p">/Q7/a k}x" BȧiHXsQRqlӱWö_r^A%ANZ&V;oػ!)U־R?+L%  V}Tcgkߢx&rq~ ^23t[}@Q2+vtfLO0˟լNC ^>Rj(P?J$6SH <ڭ:Z8,Jc#_p%P#°p8:߀MQ^{r& ?>cF-p:I氬2v{-,"vapxR=*,-H˹~*^ںwv$ƛxeᡷj6 LTp l P.u@XeHߺ9y~c8mMPÕsϗK3)1' @;F'E ~^tas/`v6 zTz5 qK"~}K!05>᷸@YK_k0@}FdR 93`%zI*szbef4r0ݦErADmI20ᯟ"T bpl o?-J st0șVϩRe%GkSLB&zVǣz1reЀ LNZTBϡ~qK)QN$)@mG5A+ [S t WC+oVxChX)-K7o[oMX.&MK9z1 0qo19v| _œg5PT-S460Ď~ yB g?`cďb ryoʦ z7j5Zѫ+ 0HrDȏb;L~ו4!44`4gLf.x~ : S3Xï[^S?slz(JccQbK7m2{D_IO@_lɯOƟ4s:[ n6j/bWx|ym }4_ъ`zx=kRƢn{qӦ{_mlY?ytfK:_J5z0z9ߒ,ҌaGqb+z.9 w3T%p?Hخ..(v?꽧V^~wmyGij0l>14WL9eQYc٢ݐڨBuB!?{OUGا+m!5zJ9>ѯ^:˟u:1ֆ7bѼa bv׋F9b_I#=܎Suv;N4o `wZkЭ+O;ԛpeb^{sCʻunύ~ _+t lC"Yxs:]GݥZ\%? Hd6K\nuHbzWnpWhޛ?渗vnpJP+?9ٹtD}][8C(CJ틛 = L"qS"-r@JPԪՇ' ۑ7lfi-iM|$T'W_Ϝ Mɘfqۖ_@ʑySLhhl|}q/p,k mL)r\Jafq^ ,1SRmOGGs':Y~1qgksN "FDMn\exx eX2llklu9?o_1>6ydjr|J|"~0 nlk_51d"AWad9uGK㚘灳C5çhCd6ߔm\<bhf?bxݝ7k64۶ !b֘dTѝO$LgS婆emǎR) S,J7 ގS}}}|``|#_ޖ1km@mG `,39 ͷOTsa3Z3f˪d,ʵݹ٧l*Lٱ(t fT bQN7>3:E#>I&1`, <J|BjS):iO4W-$_.RzWdX:U>꽍y]u]xb^̋Tc 0DRQAvG˟u:M?䗝WY2g;Cd8cJ)\Jwv8gտe({W{JY0'1t*cG C}QTXP\c$}Y-F@[2m65$mk T~P+E yhˤzҙVv"jlf^~Yb#jki|9ڎ6( RJ9WTJ7gߙi?8!Slݺ|o%yZa0TRJE.$bWH)q29. .v@2Ut=% %{QC2ytD)!qS U-ًNbCh(Ʈ""r1%0h6\)!scWut}}rb3d*Fjmckr 1cJb1V|%OR)ZDc1QR )%Cxy9oF` rmY-͹e1aٰ,B&,$t&nqͭ@|"8|:%p5Z$R̐B)uܱ'$>NRR)1\âiJfP*w]ļ،9YN?a:}ԡB)m),Җ)dli =?zQG~ϱUJ 5}}W(%6έ9x@ϝvq%4RJ!T~R2*ҡ \'jVZc3lD̡j͠Tj>! _A'+@f\g̤Σc<5R՚ a(!UPy9g̤eˢ͋q]g$JVTCKkPh3Jg>kJA LeQ R*BcQl\K@EPҨԈ8}r¢PJDxXPIB %,ac9'sZ " r4V,H5j,mcy8Ӌ\׽6dzB)1:ǚIQ0,"2|.Ӊg.JPa\X p9^ i44̅&XJä8z܁`t-r-q6m,50M UXa(a,9y;}Ӓ^:ڐXJX `@*et4c#Ͳ;{DܶJI0:(P2J2vR:ox•7Bljm{yMT# (Q BADJLu5%S8$}qJ25WJC)5T҆3s[zpbfMlZ*:Z;mF̋TRMa- vU3fҦԖ8Bؼ9- WbAWH=$XՆ^0sgጙ}+*)֐ NBp  p$]p$3:``g>J)IlD:u`uw6"RǶUKy-htq8bW04x ]$]δ!f[I37*4ق5'cY":U-YI1[05㜝~}&=w]s-!|Ap?[>Z{{}!!gd\ہppuXcP,7j| 7 A"sc6l;܉X 0 f[` 0d`tƢ7s`1q$c []܉cucY 3RႳםV}g8cg}>sm""YJR-@pa9 d!6mYs}?-`t- 5?AF</>~=Gtl68}AS%NnP gXcO#rf tu |ӱk%3y cLW $DyBpjCRK,,-74J4Yj1j&bm+[%jGiQO M%G?X ,:;^lC96r˟{@ (4F&ˤo.v݇>"Qȏ3Zz0݋^ǒ6(C)ђey,(۱Xz:>nfs7;dPCsm<#y? f:8޴u4Iԇ: l1\<9vRLɠ0X55%B(5L=g %Z{Ž>s"z`YV%8>C"fծz+1*LL\{ QD,sc JeD =qyYy (U7_;1|d(Vj;>ZK HL1 MCMK`Y.v}JV`[60'G@0#8ф p 8t6ᬥ]h$ ˗tq,VZ u 8 2p-l8VvДpKIxV~u 2pq۸HJ1p4j*m ,jg/Dg[aP,װ}0-2Z[73>4-]e 1-2n 4xqk;ʈ3'͝UsATk -%l!БMcV4%c2IkrE8i{-)-Ү9C_nr0<ǰ ׽֖'z׮ۻ[t>odz܊bтvP8νCbnX:z׮6> ,ws x3D}4C2cRNcM0꠷n]ڲvYrJ{-Id;86$pHUD{kZ*{. O Vѐך{‡-63w20%&t68hI9ɑ '.ڮ.kP5!9Cpl"~\6t阋r겞\PI[h.\[=y-ڠGݱwmoZ? BC .ÙiؖΌŭ1hCQ/ő[Wu1U AMÍ7 ` e ZS\{yמAԳ5{Rg`/d3AY.=\o?o޲-IP#pmU;_6Q50~S D1Y=`\b1|,Y< A\޽Yl{>KBT|^螸O')u7bh8-ůك| Cy=^ d APQ+.]% :خS]ɜ/==RZR Mزs?sp-;]14GK*MTs{N^~a1]25~ {]en܋~9xT}bd|۲t\߄t2/s6ca(~-ykQ-~R>H4gq1`$J(@D`&Q,ԋ hk^c$9:/Κϱ16^h`aǞQXBe #8Ӂ28sNga B\c*|ojX+= yU,45h$}N>5#Ȟ[8gExYg̅! qҹ9BX47p":.ZYa<.$>jm'ӟx|3G: %H%[%cc`0ƜOQw۶/7UCӹm.]و7#?*ٳܢU bB4r 6}\U :J ^ 5 |*=wƘpUȢWd@Ҁq ,fRܗ(*ȗ %aY @Jb*_DPJz : h° T}R AP=:N^~zg|?e6!|_BiG4G"hCPKkZJTҚ"29iF1JĐ̤g$M'If U3k| S0]I eN04-M.F~Cة'q 8U#B&ÁlٔAZɣSjVB {#8pXr+g>'9`Enz00gy*W{8@Tߠ3pQ??ࢳ:-]:߾!QGx&;ZJs]:. s ]c n̘?{82DX:N2ޫ.Ƙ7spʥ)rZt6\ڳ#2+Q60/  ژ4w8h DIaq@ws|=Je̕3u>!&2XדHeL{㹸5u|Vg-@s3qj9(+Wv/ xqhlI qCE >V]|m#͗YMnx<"( ~2lxl _oP0 2;)Z`O0H+ Az6>P֠ N·)8BCgםn xL=>j|C(RGXAs.I#rAc[ٺ)醣fHm M114vV^^O25!rC=яƞIRS COpa6͗P@ƀ3 Rap"1(/c݀YՈ1. 9\#+qpMl*\j"U t&YOpe_A3TfY|0u L0*Z 0 áj5Zgx0uM46q͍wܓ#=窕k gHM2` m`t4 *@jbxZg e |\Z3" $8cYl3U|rM=9q_brZAVT!p!?BBiJGfpֱt13+@KQ=mzY¯1gXaF[,Ia1X2,LUU=&IqQ m_o xY~k#ŀY_ LVKu(]-) 0r!$!O`T.fPʀCȻkCѡ% 7qa2PP| @ASAՐ1}58CJi50pܬfuZ6@'k+)GK#UhswGP#h%?e i bȗ8+YTJJ)ёuўq!R2Y΁w2m?Ioc/LrQR)MIa4c;#_+Sį ]T?YTF:B8jF֦MtooO ~yl*Kp(cqG n HB0gl*+?1^KxzovF@ceC( nna(Fg%b6s8z?'h(]܄z5$!s8epڶlY_ CPOgd4jDGA[AQ܆`xj!CHl$br7&0ziLzBhW8"fa$փ%XRz ` %€Fg9-KV*صqa G` l?"$v T=v 4}S1^I68UE_1gFKd|`VZTsrXFj C2J5K & *OVg5c<w8TFk{D,Ι@6룩]Ю{v8,Sqc,|:S99xMelphobN{.j؁=;'YtqSxO׌InmNt=2:g59^~D.)lΤ%'h$ٶ=2۳\fK#85jdzr$jt9zO#X w/)yPRwLjH*VE>棥9dޖBXq(w.B!_/ )Mrm(m~v7IǑHєI@)ƶd[IWՐ6` O@ CH8H-,(c 9|6__3\o9e.J*`LE xf[ɧ~ɣϲ_f(X+io-0.*R3@0~qP)%v{hk}wqí&~'x2]A``Ɣ@5(_#kWP}g_:*ݬfu<mqz:ɷ׻¤ PdFϞ@PX v:tu4#>yه7vku,_g7 5-tI7.oWWЃ@~u?ԺP;h*yy-(BiͧͿ^1 zƔL~_z>q)zFwe |ˆmp݇].\70Ĥ>Up]_K?[6~7YŘӖ }?ڼ^%l^mw [>eA{me PsI,E"TJU/Ya98ƷZ0IwmɦRimThlZ҉t{iaX6xȶ~ۖLRicyW+HŢfFxn 5} >f.3^|c*Jq$%~ a[Q4C)x_aj%?<}F\{#פc;$^b]K>LvTBڀ;nFy`S)) }4i։ 'l0?O ׊hRKART|jf(zƢ).]ߌDYmw)XsV\;Zaya;+13uڶB!ʊ+RX{k>,M0|^Ⳙl{)ug= N0|^-֑k/|៭Xbe=j4:rݥH2o޿8t(?O᫳?suKIg+:G&bp/nx"@ `K;4峕%Yb7n|ϵXW'6/m eQ"5!q]ϼ|`X'Т^ΘJ+k- ,e߬C&;إjfk,GG&}+WsT%*[M@?;ѐAiZ{q{'{Z`+۽p`B<v*b藷?|94S^`p.8ڻ ? GhT2+kLmûSwz4y͉a5a8[[0R({!kml?:,DŽ%['?#4C4 f8r6gA@Dhs4u q M{~#BX>[:(Xb0u`0@'xrF_0KEK˟u:CM7%pF-HރlC+,f@V׿|v?6Ӓw2a@ J{Q(~/b& y `EnR1ܖ3::x|k?|s!6,;a4Q}qO\ ^ Ű⊟ pɷ\ j3" Cwv^w^T뛁NƏz SYG6Y6`;`R\)#pnۋoNJpy<~sl0.a{o߿ JTWm`Z+.~}S?ųOd4`LeZ9uMXVt Zމ+ 1^}}MƯag 3h()AadmSof_mkn| 0U Xz\}bhǟr SOr26w15YEGeKٕlmxMq7X|7AX>9`v -c[~|b %0a0>WX]P96:֬^}_H2s¹@p (/(<e D=e 1OP}R>*`=n%7_TTnBk .fG# yq3рU:7-[gqsDa\+*|#:p*00>WΏRO(Чd0]eO=ilXf,d30څL[.~rΨV&6U NLWg3jCV ArرAIqΪ%r`Chu|C0C7ؠ*|fu<=go~3XHZ;8rm8ky3-<3?ESsi~;XZ#5GL hAک_֏hp4ٶ_hM"tķa8#8.x}he}=9?*Q-{37*sc~|!nZ`mf<].g:-8\q /hGXHrm\m4XGM3"<΂%\ ].s$|nb qqsy%Y4ti@ch3~D\BƸE ;g`L@Jo^ _0boϵb\3ƥd\c^MY0=~-` ]L!<XHO_9V9V/n,:4`Q+[u%s]yk9`%˯Oϸ?7P~ZtG 5C3Df|IScN؈8v,W=+iBx~L|@O:#'jV4>P6BIlj/u0C-WgO©k5?t#R2R!ܶ\c#۷Sd.?"t^e=dvAK3h:YWG)ٲTp QO/aW)}!~&_j{^HWů%XkZDj^ܴ)W[s:[:vo>RΗR̟}=Rh|zq߾} ~T2ᢝq01xzv{OUGDvvpDp7nл+v=va&v)}y+GgMW[evCs& Йte=m7&OTO>G#e G5n3';׶7yfǵ[00H%r$ |YS8u:TGjkCSu1vm@JYJ {oE~obnGͩD:s'Z P~\޵hVM21ӽ!]:vF|?erpׁA/l:aV!,9#RvTv볣>m@"3X:uǮGJ?vջrBⷵ%<ǺucQD" `7cZ o}vkdҙ1͎wm T:r*/n7+t2fsӱMDn̛oYRJrįV*_(N~[ۖ7573ߵm1#~W?O'}mH7%7{3߶DJR|P\>sLd̫mljCr&^}pyޛ]ǍUA<䇕U5Sζ=^*jvg:gbVl FCJr$k CO:2luGGccc֦5N/CFE]Mn\exx Q]6ydjr|J|"~0 nlk_s2ka*JPJR"͙Wdi~15e|JBJe,;Zdc`QZDd"2JP0Tz͂9K͙td BI,%J"T*NZT.Z7oijZO4663HtJAJEZА2ۛO~,mmwgXV> CAZ-j-P$Ys?sy̆,]!ܝMƚ2>adPJRQ(J]1%}I-M'w76"aH/?!B)I)҉M%=s*8+AY#Y_v#qyKX))ZZkbJ)h!LkmI)5c[ ?fb0k;.ʤW1TpIDATrpB=v= @\0I'Sh rQ: ch78BNf/I^100`#/jot e2p HRi' C\x``}>.$bWH)q2TO6=$.v@2Ut=% %{QC2ygL)">L"c"r8c!%{8̛q*m9lƬm1G8W͝qRȉ9ϤP!M4j UTČ1V(N&bŜ[$28\bO)JDc1сR )R $Sj?ebJ~(V1 %0:dFB+d\}+>S"rtKJJZkH(>qǂgڧn|:O)R6pm ꦁj(m!;U_E+1Fkm)\CJrG&@e21.Λ7\̎g[ <۽.sZ3(UOBB(WhP P$0kQWhZh CR)UXiI/l}1u+B#T p"r__G;`uB a150DhmMg.hT 0ù .^6YDzvUbE5+Ct*1/RI9 ѬYlZu8c&mopgU֯= 索!DC"!X,̛̤qU3fRݮ`cX:N@p  pRp$3:d`g>J)I͛E:q`q 4"RǶUKyotv9\X`1+c~˙6l:}P[a)ecb DzXbtCgc)e_oq]\@Fp0c5`@\㏮ᖏV^aH%vq;)QXl#gTk>&& ǍGq oCgX ێ3wRsH%̺8`8c %}~Dkt[0k- @`&cyB`Nܴ}Ks!AJ5Wl\Tڀ1f\Kqn˵yma,Z B \לӆz*J - pN`_C#ʃK=1"HXiAk:Hox(W99:N `K!1(}$1k-g=-T|HoX!9`ByT__[!h. ^u/A:K!; ׶7BscRCimm=Fȸ+24!٨Gj[Wu9@ilm=NWa38``As-Y10Z(Uc1X լNCbyFhхGadR )! 6 mB"gYB-്. nUym yƍzÆ^'dV-I38=0F#t-D6>ܰ!:o[C}ֆ ~΍uO.qrUesګ%YHH&tQ3Vqqu #n(5$dN޵ *3^JWw=skR,V@ga@BXpqbuАMZ9? 6ַO^[[lߗT_B.4 h"LfKGI~mr9)RgsL?z9 me/<U< ߓTO)IX"hm#h ~72%d9Px~CFkkXTVKپ"*cQd,lt?Y(ocQ(ҥl5zNsaiza0U(2\zk^m{ع7d`x: x.a0Iޱ{a_*LP|^v ug7w ewO<=e^BсipIw^?C(\T-D}i{@kJ1d2v;cďUp.I,ۀKö d10!&E L`O !e|_Ijk1kmm3J 1> Ozv280^qp΁8X>-O8cwt;FxU __;pۋ[Ze" #PZ#/G Pp@K/SRDz%=w ~Hu$*`=ٳ Ocd0oA xIYjxusE-;o{>qڵhOdz}JTU&pqn a♐ Xx&Fưqny%D֮P,{^Q<Yvڢ{~sۮXC}TH#db&~L4gCL#5k;Խ_ՋN?ks@Uq9u{|Xѡfi$2D$lFr)JU'K _-ޑ*  皥է/;98kټ؞/C-+#!A"lrL1V |+]~M+(L69BnZPmW9Mջt̮MfϚ粥sW*E#L4(!Fm*_*R6" -W*E::.Y4ճf8p_BL%Ebj<񌁇4d{/Ͻvt(aD,D,FKUqHE%2Ø0XJD!5"`o]v _<ꎎe C&*Ԅ "TLh x3@&^%^%W2BqH#;*ŎӲų.??/wviH.!)+x>/x.` Ji<A) *0Ҕ`>.Ʉ Y30Etk`&$A`~iKO[9mnӏ7  J3Mt;JКAJ WdAϼ䏾 AV@Q9*)^e5!(L l!CW|ysR_?5赋fɹ |Eq/M"Wre0dku.ߎe35Gua}__eHܸZsy@eoZD$jrE}܌a7;> CQ3՜%Kڿ6L1l PR?ۘR3 ;K.?Ҧn0LKMCG#J `ni0ST %5`!50κ$üDULCI}V7xbU5)}}Ԝmv Xs1GsV|FTY¬WUSWqF&bOQ16sZy}PuGhLV3M(82 ZR"O%X_4骦i7ؖ]LM0$WX ͯz IA9F 2<ӹx7?p^ dNJ g7GYv2,`"a _b?Ɗ-5 9>b 3]s(~qB)n) 'aBH8~}%M[;Ȏ?U)qY֥cxXA]ڄ{\bbv`ѼŌ3=<4?銈8namEfUAڄ#`:Rqfs`9v]noH.(cό&l ݭ, "P2O Cv`9K3~YuM҇r\^'Sr!0/BӶAD`xXCXD9g FfMiJ`C;w߬$\ ^{]̞0.<`fh] ܹ·8PMNEv@{»FKMJU;7%1+fc!Y6]y[E ב8RDC B. ݳ̛5fKMÛl`ɰs82>S/+/\'kBHE۽_Ltu? )mtܦ4r5,f.ǥ )rL!ah%k}dI11; `7~fdZ:|m}0 ޽@CTQ̈(xy.6_ K|u87f_c ӼdFM5g͠?|!~ɴ& #9=gGHTZ:PU߉|Pk C}ѵZd/_ Þpy4KM sY#"4##P8ŋP醑Kc'ˏ|; ʋX7. E9‚G*ѓsA^ۻ =HrVm7j OpeYؿ p/rd#M@io7ӟ4S>~/~V.KQw4l2ž09oad-H5\wFJ5_:&Gm+Ϛ5㦏Xo K" 83Px9x UB4##O7OtvW.N-E3CwO! <܄RE5ƅvvtP+m?bMwy[l F(N۳`Pk`pk s~G+_m>&M+$*nz ߺ³5DCгl!*45ü?>'c? 4j>Z K6:byoF{HWK8A!хO߶nodM7cwXE͇o~ E/PXayɏ{\pJ"$>y] ynɿuemk݇Z9O+6>"@Eӂ-o|I۳PY8i=wuLg u5~GV [섀=T4=mQg4CHT( Ě~/;&>meM:5m0%g H -4o@iv9^x[|={LM+5XwoM ɜE&ӀocY`.D8S %hr|ڻCG_^lgvR+M ͨòlg!8y gѓu Τt3sF'~^b dL|s@< |1M̍U): \2,\tpvʼRX`<7h1H:C|H q da0 jXRXo|V6G"Ia\H i˼Rڎ߼V6>KEʗ C  i?;hǑܭhG$-58X'"LF3x;8bo;p9 GߺV43_)0:6` Gߎ(,{ޱ$i{o2ȊSC.8e"0L hQ!q뫙ߏ^\oVth"vZ "X"#'= f|Ki&Aۯo<:VBGϢE;X0 ξcphۻVȦxR1WyAJb (d rK]rgo [Egg ?;v`աWnJFcaɤ19nV;θwm,垟%lCqBdǵ9f': Oo]ԡclVܶ8{QtR]?KE| "/o`L;/ZC]q~Ydf-z:;+Cb&G1kN>/xgt,8>wEiW7%TϿj/#2+08yY'mL[dz|s{"Pk;om JjQl3:n,算mD#|@ՅOq<ѹXCupNjly/jܬ`r2,/ ѽysSّj;Bb@;mRM[k8E`h F1@vMh5Mcщkp +ZSkmgq. x%(] BO+( @/069x .]vjmg qsT:"wv"hOI--tx 誊#| vlp;ZwxET]|H*c18!:ֵXCVjrIDQ@Hh(H七1 :ԯZֶwxk׵ Puk!ֶ{3̏DG d{]P-Tknhoo֭q-bmZX?;U`~_y2c>;U(Cֶ:;Zl힔LU?N";,ۯ46w{cG'\UB}0?bTɆ.Y\5x?^bG ԯps#Z_?6P[C(o GF>}yov0j =J}' /6P,^H90Ju hb*ƜBΙ|P̿OL/o`戁3Y#qQTeϟQ0a|"~|˛W `r6ʊ)hECԏ~J,(#wBRf/+\[ PSQބxTB)CFMu@cy\PP!W00:v:X_u巭]O`"LΊYlG8LbR3pȻpZ`3 "ЊKy6'./s|Avm)$;8< m0#uW%#%6+O FMiJ[{ ރJ@ia2 +0egLxa"}!_>c aBiՕ0{?TbAC, s cd3'YV3UY1¼a猓8l)dg/3NO S^n2* P# `52 ۀ 0BAf/GBHH@$$Cύ⿲/;W^T" 6,g?xüM[iE=/;ummGf17btLO6;?k?%v9s2Wha"K~1S3~Ƽ[YS"Nfu'm7ճ;CӚZ&3zLv-+Sy>r}_~{'j񓊋y&s)"CcSrM%W[׷?SaXSnb.4mZ=T]ƃCoQ Ǚ|~fƌFswO6nxW?f'jR `vpzѱvky-k*sJ|V $xh d'f~v*[ntM}uu|Bo/r5b xѱ>_X*yku9G^'+A1 $~{*^SL^W=78$ 46' ܿu)o|A{"nqX]ƃ#zcY3j]7x SfQlM>7~׬sѱ'j/VRF%I`8|0;9tבy'_FBkBCuas0?8:pT~XS˖qXI(MWTLE]{KHxŮ 1(29Dx9*@S # Гw -SwVN^s`Ʒ~шL %do W0L*ܯ'Y~x;;vM]|hn-ow=C9A/Yc:LsB ߟy}x;;vK0Y=suMLNtc4 . %Qy-dV,y5zDZuOAA T&Gˬj̛Yޑ _ѐ?ΆT蚃cwP@)BaY ff N?gV R$4V&1߽};=t|ibV䚮m ߼}c1F0_—jRE~,:c۹_ KmmW+gY;-3} r0 A ,(>8U-2SιΆk&ƻ0OZ+FMܿw mzv7\}gsCQlՏ 8')5-%sjpv-z/ԉmWuew֧k d 91Jk 33E =8.H/Κ5Y=ha>gҌ) :OrM%WL`E}5K« ʻ1 `PpLg_mRV-GV%sVu=K_QD2f3*/zdpkhѫ#;:4z}n96`?7uoiYqw{L^0&Iﺺ ZղxrΫMq@?}UOR=2+ KEJ)}3 #^?6щ_آ=طH۫6H3!l*{>}cZ{ۋv]2=?J$BR[mŚ3/|z8;UkU}տ|nT#Qy A%OָF #{&MǾֈ~?vÚUVokeKJ$g=2w>u-l1@?X .U7ڴqzeMv'uuC9t'v~W_ҙ]\˷<#jIvi' }ERJ}Ys3g:GPvRo|Vm[FI6Z_NkYqNK5}ݷ5V?Wۆ2$,K10^>&tKUN]ΞGv&'f8󏅺y?-`g_o5dP9 B !ۄkUXq߾ض(yD3UvXWMaJpn3+ hh_0r˃W{, nD9IpΠ!j$:j:* P,i'g}T!\kāw 81KZdeMt$ pp0R!oXKCWMFfwK3 ,tzS4]I(GOCP򮏯M7:zzC<{\;K6G$$_A*)} /5sљƞy }=!Qhl WEas]9p].>ѿdOӎmj@9BWT'bC u@ ,Ӂ'@5F' 50<n_$a`|1?Y=4̮C EgĊsQ~lP_LLV%_%f xPʇ Rzp,0f@IOw/4~m*yb>Djf>cL— 4|)͗PW)84&uAWjͦ[Y,`g *ÈFפNT:j55}/H}T4Q!#"5t|M% dᷳM\vY,_T#S#ShXLbN*i˙0h0[ cXX.̦ZT&cFBFBH0sU7g8E/G`Ǜa1nsC4ތ*8?%k45ٰ-!`-d,4MpFS&FWN9h#`p`H8UQ 5zH)ţpQ 28Q<0}|2?bXo7 > +:) 8X W/*Vk@ $G7l l=tV0cRXr02)8>xU>k:>C~+8~9xmF =8Yi4֟s_iMgl!N~3 28]"4%lr \yi8Y=@qϜ2 7RaG b f U3xݒ4Ι '!)ӐbZ 8|сV k8{v36 }S:m2<$bkЊDc!|낒pUƛ_|5{bZ}N6Ol؄p] LoDaZ3Y[Q>55 ظӧ Zcdt'y#/,:v>4SA$6aX4NΜD< ";0 dsPݴ'hqR{@lWbNUKX1--ZJ "\ҀTqSsA4di!lwC#!14}i!LfQx7ۭPx 9(ĥ՗ $mt775 lO0Dob2^`2]= `/3`n|}5#ug7w ewO<= 3  ' ໜ[l&\|h[*!X'`I%vxNlV} sFƲ͂`DZ Lg Y sgcqm%4&EQ @!CODbx#Ic`x)A 1 AAS<"y@̍$"Y Avy.Hk Yr nӐ2'@@EbлA&sN0G1 ԩP:j9 9GAk:҃5!(dJW ?yR5 .%Dž&` 1h"|pݠ)_S_ǚ\5$F2 ZCHq+NzH#@knP*grg~N꺪 M8w:>at$Zf|3N$=1XO'I2zfR՜"LYq™!D|82o)1HaD<ܹ7wI]W]"ObECeȈII,`R 4Aöʭ&Ū ;l#`>BV06pH{m$5T@"dq!VVVB)X0Gt<tCW&JTئܳWctڞ$4 96QVx|2kg`" ~R`DR!T+|ևpZWGk؋HR&X`j,^^pCp?4l3{N[ Ӭ04ǶϳBqJg,Z`JD@(Om݃?lAt^Ģ'O>cկǪEYhFїpr2[O @"^L$+"I\66G.ǜE,k{``P+22xIX4&5!&ΠshlhM8 FKr?&"= %@_~8.UPQ@@C@#*/S(de0zpJJI6r@Zg,G$ en/|'4_dyi_Ap9{"{'}2[[{wdaxBgE (9.\y|kȌ$`X?߄&ӗ~ `>P#[W`-ړSP۟+?e'nL}zz$8o -JO<&81?_Sw ;zS/z3Qnoy+urR2.z yW}l>,о|q!o~+ L{ޣ~6w&-pl Bq_k-B~~ oN$1 +aPvs.2ujRjRud 9y@ $/K‹BWfز{?P |ֻn~nNd xv>X1@ƋJ*J}(!+_>G=G={~$r8g()8pOq]*1ͣ=&yWGn0J f *CםIU(Bb Eşvua0S`?BqKʖ0V,Au}WʼCJtmҾJ&#;>~9X}{PLe%"oHD >Lm'ӷž/xR*p6>|LDw|Jy{U]/;{.tc~\j.+">lnzuOEO׾N&";گ})hͮ80wv-"˷Ma?P1W\OD\ټ=c,ðl*06Qxu-7 ?-sTɈrۇrscDSR έsyt[+ΥxO]}Xi dXe>w6km?Jnha@ p 1wH p1<{( ۟ & t!ըxd[~`4(.;{. @.[5dFH?{lFԍ`#Xў >mpKшs0:2ё ̟ShĂ[C[bp swb,;mzMTc\.j㈄-`43.WMsNLv?ö,4' L& I6^֗G>[S7Cuy!?8M Xm"BY3six u'"6=ZMC>UEhta. ` , ΁ի7ߤk)0ř988нgd77/:Emh[YW HΜސƴ`0F'sWcC]xѵ;U>ktн\0*QIӓ&%gfv+qG7ȳ7SöM-XpU|2sO*\Dse|96Of8| Ih-L-iBaт-?~}_4#Czρ%lhrk-{gIhmr!\+|O0sU'+?y _ᓈDs` D|RX5:W .5 1wvͩ n w"BGϮsqG7wì%: 68 K%Ol>m{`=`έgK.@SЀT [zKx߁a90s0lo?08; }93h r"G)0AY 8)_S oAJ\T"ح[}_BoŒT0č8x|LV[BI$ '`v\~<حZ B,]2mBX7Zҽ3֭Bm2؛S' K ú"R9_w^tם{폟2Y~j>-Kt Ӹe9_zw׽(_,7= 5\lSyۄ7R=u_y|TآJEPE0;Ö޲f頼B1|`rH Z iyl>"b /ݎuyo|.kncak1X"v_%ىN p,(D нr32Fb;)`he PYcĸM;{04>3A8e; * O0MaQmPl9:OBx%hNʯt.hqV̅)`*b8HŒB_́.R ܫرS:߂܊eX4}&tUkd]Uj\2 ~3 x-|h*/_MEY5U f7EV_i?cː| X4}a#c܄0_4Ϸ-Hsj_/X487 ߻ayWd _]}jy/־7sI.I׾i?_0s}~0J~[fڴ/Ծk\|vޯBEä0<KoDlmH'ԂU >&GNkpCaP O? Q軷% R,mAԮ v>|0*ҍ!(&&jګ~KGzW}Ra[@pSo&60šÜ<?4B<,zI )tѷShh m7#: 0ňڵ#Jawm(`Wn-Aح2A!ҦqA$l<⟆eIu *!  vnyy ZHHX4V` Hc4.\<ƅcg aQ^%l>'LbGpYü2lgBc.]XT|>Y<5]Y|Nţ+` )]x"dXA,JKP=3Ui3l`%h'sCOe~<\ +D"z ? ٳMŰЬhI0]F:K!ZK~~!&ʀi0S9T`L²m'WlGp&W a/L4BKO4\ !9pp6 9 V*;,A\_Bz52q@Rs ג }5|9dl!h0`8ciS`"uj|A qdI!zR@wAd^k/ϻR)Z ƕ+@M-op=6|y<(.dRS:˔N$ׇe-io1Q/8?@~L~E4:߰z FF3O>Xo`|y<=W(@[x{_fM5!@?_?.f-0#f {JL++c ji9>6K6MƆz@\rF&`.7vNUG6q%3Q( [[ڎo6:cVeōǤSPC_ɞß%c[\^T] I7燻 * !lV̛( *?H4XK Ž  /|rJkP2> Ͷ,b`p}_\@P١&&2xi=YCxp8<4M |ϗ( ?~xIɷ:{zCIz6gmחK?g2/V5 f~2)0c`*(NNޗu'Ծíݫd*uS"gGjZR(/S(q|C4T[J&lT gáIzxx²?Q~2ea Jk#µt )\-UHcLęanH_8>=v`9%>-ODgc83MC+ \A> 䧠r:զiz/K|KBx5Ծ񆆯ToږR{O0 fq*SVޮSaܦWr<.y˂CHJi.?8O)'RjC:uR{O3ד$\'ΙWN-YrbXٺtŕ!|)GܫG!(NK8XD2yi<<xGP,~q8jތ/VnECWJ:O{p=<'OJe_[YqYJS 뿔NoD"RJ)=#|xGRK,˒O矐8~#g~fneB!qu8K%ǣbULKoVqQc֯mm֝$gT [R:#Ok$+*B{Ϩ7IM7U7ǣJIy>\#ȓR CթԽ8);H(|iZK_]!u8.ALi"pde{O)25O7b8J*i4 U%*I--0ągjЭGKNN PZ)Yq D"qa]Uej[{WNIWM`8 D ͤTz1m_yY{;D4tID41uy2 1EeE,|ṧдx4>SJJ&.J @W$K6T>PN\,~W/M5Z3CCk͔VKuC$u@ٴ2 1&]_ 515# %"kΟիWoФjkkWƣs!RhMfJqfD'4ֶ"cxGG}g-J',IוB+e@KdZKLIiKT*yivY\v\yGԹE, 14WJ3]R*ӗʫN%C]YӢ! a(_R)I3WTKƢU׹Cӄ0@J*C)ɥTLJ|i}߳L4I)25OիؖPr `%p=OX&mM0<5Zo8n(9esV(:p=}xbA&[@XBmt4Xji ;֭8'=Ȥt!ʇ )KH(ƛs [fk6z>9<χ'%TR%\Gz>BAguPh(lRQɗ| ^{K<-Cmot.]i[玠Ç1N8Y7ak+ 2 >\9!@X"FcD r}iڴw Z7j ÐJAk] %M5(`~a:8NCQ*`@Z2`X%H߁eF%VR Kwcۿzjv(x RRxʏ& Qr\$c!x R2 6scpW*k  O*\dÓ*Vk۲<~SFX*E*HRB) .J2HQsJ'њ5AabT Օ\桱G2IB BCęK=4IYX` B϶RhdsfOC:C4B4BE25Xsj/e7:)VvaK&aqasC<Lpl9~|4J4hD2BAHDCXD<}!Nò,s `f:TD l2<@Va#5TL!G3f_&3ˆHGC&d%MMMautt9m1ƕ(cd\_g?Zz,`pq4/V}aqV4D:߻#3c9p44oo W^mB_8A+ )Nhn: ]pkn :#~:\_ ?o._g^s:kθ&sci6xR!Wyh= I yg3.68 T,@ `TNPr@ZcA}Ν3ƉsL^w"^| 1XyGM[R Ći=civ!x s|og \!+2@2H1_@.IӱY{8tք3/`&~ -F6;9jsbcd}?"\|Pq% &!lD8dbt"~g@jӱ' GVϫ` b( P* %s$orNe8o{1,bKYs: W*RB Edž]p$B E !/mPSIX.O@>Vg V !PȍP2g@=c #! _t: h]}S,]c,1\0=y r_F5 V4`TTB]Rv- =xV ES`pVt]b>> D #x^ 4"x~av@6!88`V0tl4Lf7ư9TĄ&v  9!fN5<-K"6 ԧSF,dAk¹f}=88:qƙ؏SJFi>maCȬQ`xDc<-%tn== {+g5b&xi`z83ɝXv,_4 skkͱWnDáDi8jj*@9h%g uEk@#Fs:XCV^-Сp"sT(?a2[Јk8Hp2l!id^P/IOzVBSaѸe`t"*\2DJ*Ѡ=Br%CN caes"f'ڂg%PSi@m5Kn@ARcpƇU#68`Xr= 5e44VW f7BJ%%Ms|'᧿z `a/HG8#Kkӌ iFQSx-HK(C)Y!Nchh3ʽ'lٕq҄m)XF˼4$z CJLWCe2#SH Za.A6! OjRC*DQ⼹iTFM<}0A?bH5,@E4 C0̮I:/ˏLFXBKc ay]ħ j*7@.o慥s%vp}|+:=Dey>:~'zg&ϘCXj0b ԾaEK`ӎn|G08r\@v?}Œ+Nw֯o&* kѱ=T֬iW6lzBEE=[89Z0{f1oMz׷g@w,;[ؚu9 !8Mh0<ó“ K&4Vaַ._#`^clf7u_ğ@,n`nU1]98>!(4T`͚u S Mp9 A0:GO8a! GW0F0L3h{FaZ&9ƃm ~x @k"\y? js G e}Y) <V3h{Kct{{PiDg6p`d a˄!8842\X> "'s0-`Μ9Fcc_a>?Szej*\e-%Qa 2И\`r}} 6?7l-wWǍoarR-9`cq`D0 ,˚]!,i ,%kHldő4Ag:V#+l{_^}=ݟ}Tݺ93EM6sK13ɨ\2>ZSٝ猽_L~y?bILk,BSc@Mr$s1"~/O庥4rGMUJU8mcX@]MbG|U+:~p(|{htzH*ƤUlL洍p`̌ 6G dՉ8"(ԦPZ8Hǣ@}&\NvvB&>Ad fL1o!YܰEƅ?8 q Y,? b ?~WÉZ-bt]~)wH10R0P;:w=[FyL DNIJ~l؎7lC䢹8҆뗩7__@P*)HyڪE͈:@1B]mO鵈lB18/2v_b`Pڐj6akӚH@4洍}.fU;p-8D!cK%["ƋXl X` hȦppd jp,|e0V ǿ{no S34cݡD=YR`RК/1D,Mo]3\7Ǚo~2[m2e79bpOwbd[.8QFk0ȈrRq>}밿|S?_Mb* E&[Ʋ3튎|96{cdK0 +ۖ6a %6(}86c$37-55`LUnddUu%8Q,sſ~Ov3*qƕ1R$<,4 3p]s[>bK$e"-gKew<}0]XX1p(``ט(x6˗a0)9tU"2(툜o1n"}uaf++|΁6=oy%3{Y\q X:+oȼlڼTrK?8|)x]>T>TG0XP 3K>t"_(}ӍӗM%Y]z^+IG>ٻ(c11+oU1c ^wu8 ih[X:/}/Zl)u~ A5)D^`؁Q30mWG=dc i ~4-?o%#E#Ŵnxb*B@sua؊zG&Ec4X*~qL/u=DGN"߆袹2,ĢYOyB43@ka'gżV<<߀Wwy=~h*;{Kf,-ƨ38G~d"\U!(!-.AKvsc+,~ @՗_r'n}і͒*` 3h* 9+$ \-uU̟X6|Nh]uۮ[,;bWN(]x|ņG'cZoRj[>804 TFǿ~;U Zp5JC.nV~ux55%ٽh̆[EÆG$>ܢ ' `dE:n(}_6QKFcI)H `|32b zf,j΁X~H[F>81y~GG[{m2#q10)$c0pH3e/ ^ jWʷ;yW8  v|13J:d›`\=6G^sC*nKj֡/+~0`'/AdFҝdb6imc<,HP:L6?5yX;ao"Nj/+hMpE1[‧G |$Lӂ~Orǔ|PPڠ\.SԶ`  b)X|{fxlVj?*^xW)"b0t?$O  (-wCU&CC}ɖ{O?{gH3/ol#&˾; .%O njkn=kӐxgXc7tk vֽo$vyIGS|s x AT6ݳ T\p O"I(G!]MY?i6][G;}ToXPv}Hp07#(!o{7?kkko oLf"dw4`O!}l 46=Zb4!/#G(sexx c&߻X6Aw>\> !#}{o@<*'Kj"bcF7Oـ 1d }t; fjFa^VNDQ$fdTJ&?TeKɱ}w?;psdqưc!ʨ&!xnm.B!m4 }#́?^/̡" ŽA%C+=4e5 SѤ$~9zeF&g2j1ppL}(J5Agg]{tj| D{/\HJcʋU2} 'V?f}ŻV%" pqzh/>c jaS~*l*дss<+U9߶ʯY_Z79l}F{Q@XenH|j]0Nͩ,,khdё >}ǘG5)Wϟ{B*- U/&Jm1~ٚkM2hXtu6N:Vpg5$RHAr. ܹ}Xs+t:m". mlߧyFYՐN!M3FN|+(p:;;5ogx``~̚^KfB 9@Plن 1(dC 3n@i) ӲV4E ApxQ ,RG|HfhJMPFCp2< YpxZluj>svs,.݆ɱDTIi}iŷ@`GW@y ]OVG?}5qM+/w|31_~MҊhl'k/)}~sBe/ w&i;7±_ W}7yD :W>kVpfY  @O<ۇ@c#,bJD `I)쫖{Xv@m݄ȯH+Kix ~ם7a'4WPF]J+>vk?-υ6R>Qo30IeH F wk`GbA(x!Fi|few3c]ۻ&HShY3 e>lۇmf| (Kil<=I,NL``% iUƯ_E@F'0P)BԎAq*040hNJ:53GT gl:Pg_y߹dy@WJ% XX.S鐿O}4w>^c1k|\8+e$>}$ߎֽ9Fc ߳SO;7O?;3){:ݷ1pgc^ 40~rP%}h!O%08}5ug<)zbqxs.ǵid0BMS_ZT Xjqwtɯ628;p޷.Gx+IQE1`R9/,C [M@Jc"xvݯYFDVNЫw1v[D<]X{e᪋l@!o]P D ~amu6VP޷o_=dk y~4jޅyApQgNp f&PgJ$-f{hI~!(Byx:XoaJpTx/ML?L;)냴{+I Hb"km vaX`r@Lw2M5; ~,f%ݎ:pwS\,,疀_{Fzk\T\cZu5J϶Rl(~:ù%!8) wSlLk}j&$pV&{1Ot\2: gRB{Z/F V%f%Sz)|_gH\k36$8xuЩ9,ςJsj8M[3)Xy@I^bxEeeqX0޸?wbU:4ǀ, wc\N{h(c-aa;Hy%ej!,B6~'ڸE\p`w'1s{4Z bS O\y ;1DRiY0ؿ%|oQ_kCcuSPn <fpTv:̥{pbAZ&[BFTR7@@ j@NbcAu" H a8#TJ4%n> @/?__L_d35p=(1$FK@.o9! DSdux? W03M`%؆Y+WYӜV+Y0Q0/:Ԥ7aΌ<Ҋ { =s  \KĢG[^##W o0s|U=V e<5p,Bl& !#թ !߯$K?r<޵BN$@$q|}9>g5f&A6}Şs)C8i0`Ȅp| D'MIrYXd!7t YF6- Wqoq?I>\ `@"O"\MKA/K$!_ C /,IO[&SU4dj/*8 $}I>PD>ʆxGh @DF qG7L/ާ >b7>HWGвxS֩ ŔJ6Q(~=gV!cA !:_|0D5|H5NfFP)es<hJ'?IKuQ#`s; aL$EpR`9ƨzIS%1ǂn<Ũ"6JzFi(*n]5 OC'AQP(B! N5C=jB{ڜfZ03. V<&S8_D*xqhyUX$QK zd؁?e;wcJ'#+;@`^Ɍp$p3kYl wvur jokM$q;q?+d+س,u2N uR|}hء}^idşdT'-)T~s}bhL$Nx^??)??cl#&90 6@t[OM,Za4A060<I'ƎdoL>V9z |=gk=e&wv_B@%+o bQÅ4\hKOgP 9ȯ9̏FTk$YʗF'<% ݛwO>]g$ p&&^IO&O;J]@mmm{gիWVJ vuuv6YX_A)NL-2{3}OԟaYD d@;sعd{?==A-#0dΘ̍iͿv:KI00tbGzA~uyhι)sOۼ87cR )y^7Wrݹ{cKD7"9 ~dž^c,bnY20)y7;N0 Sat-"a 19Q,}量<ñNd-EҺz|'eלFo̬h$h8O&2˶51'OkkRv^!nYV3x '|#RRku+,˺Pr`8#)(l GUN@(ԢhyKԉcޞO9ɜXm;>?Ed"X|KD1d!#qxl9m!"='eo{W|T+M*ޤN> BBOc֥HƣcGI2fĖ:Թ8ĥ&:0c,!N~&[d,`ƘA,ul-XM{ǧ䷷.eDt譂pPHē$=Σߗ5QE`QAZoioT?S K.|c3]]]U]]׬)XN ]]Hy筪{=K/cqZ h20@mY:^x~/ ,o(v`ڧY kfR-6U\eAAR8_pQ66pѪ>ESuUUɐbgSJu.Gs=*1JsKNg[b{*n]oʦ &cPfOVFc^ #83KDb`JMCGʐBJi]|^PhXTSsQ*B4F04(ˀ.xTJ)>G= !L&{Vy7Z9u]4˸=IV(*Ёq\'Ft*^N.tٵu[\(y>M 1F,,WH 0 LƓkk/Dx?.QyʌK1]*Tvu=\QLL0gswv ڎ6iޘIZ8g5npp@A|<>oQA&d L_Y9Ʀ<'Sq;j a|CPI&3DsNcjJ%`Vd.,(}*yJ"󃖖)_HmmmgXBs饗wuOn wom]^vm|?c91 xhrgUR\a ?eQ&I%¦+@Ĕ6LU%ל;PqΡ s)I"A lt{EuTTil.J4x~.*Z>>,g1}E X",eQIFdX`f;g]t{KV'VND?i Y0f&x6Tgzs{|Uvu=VڇyD$Źn=CeژJͤ&L"q̆ 9MgRUNʮABJhJf njoc 3I#J>,)e8sM\qbQxL<^| (ɤ(_h"?Q=E5I A0!G ιZ yD$|E B A*ж$;w&B̯Je'3/aAضJi09c#2\+myJcǽ L"fK&b6(=P@Dp x~ lJkE,?n&/`2Lڲ b$J%= )9d!К!!Zq.dΚ7O@;ގY&j4pnK:x%B6rġϝ[f_}և(lbc򪃬^LQib>e F,Pĉ^hz*QqF 0+lR Xr(9}= [u!眕K㬶j)Ʌ2 ` ZʇV.4Wh|xR,g,Wp[p&]ZW^y+x^mq`UWQs6U“X)AWM+ah/0Pܲ͛6prsb+SbM1 C)]yօ(ƹ KZA1@yQ﻾>0J1BsB,ČԆL"Yq:s*_[[%g cy|/ci¦RfD m ^[ދ:x!XEBʋ/RO3E,#0/16CҁBBi({l/̨+JM6-9"D1vnCCvCCOiAD3Mc7 *dSNju 42ws߈139s*1 l?;#@$4㦯߇,3XdֿB,[:AźWl}6\%g8>c!(d<0d8ػ QcM[lf&Hz,y{7sdIQaX_.DTuR ɓS{JDژ;#OGS]^|4q[( ےfLe%~6QPhމ%<<!;-ΘFc:_N[4A 0[1 Ppc%8<־aK*jԦ,xt(m`KaF)%;;liYF(`ƒB2M 11`*=wV}}fLg>}d˛؃];b2F$j'*Bq\b@t f:<3+˿rO3m)%޴{?FD JiS1Pe㜡ͣ&Ś3880$%Ў}嗝LG3Ĝ8O<cE\01d2,g @p %m'm% ozEqjΓ062%ӛ0^(Q 3ù"jRqd X$2Y =tBy֣fѼx.2Gm l+0 Q``ܠgS+8|?pOEeaY4U|GW63%. c3To|F}8>x {2os`"N EMHiCk\H,{܋  m[;嬽Ոdv놖^~b $67VcZcPv0C}u ^a+Je\L}gzZG[uMnQ UQ̩F=&nE: O'Xc 5T xJ3<qYx|oJA^9)ʻL$*'c+"c$8 ␕,CTzaXԦVv%ߦ 7/j#G߁o=vwf e1n ~qOq [?%ߢ r뫍 -,K +O"®pO6Xp58g|{q^ThnA%3V<;ޞ?Ƞf)>/f {"~iZs3`"nLD/x=0`NfM6RǟF1v4dyjoP4GOiy~ iY[cȞ p@K08|e*G>Mm,γΝ2&8VP<cZu2w~08 y#2(5R۞9h{Mx,}@*f0wv\2cq>å+]|k [Uy^.LFvoO6:|+Om߇T"g%<\7u/rSM7YpOVz v;ԙ(wE_hz!f̸vDamGX-3"V> r;λX0php#Q[ #c75N[8 g6 >5,9HVgK+!v3XXm80ÑI  aŴΜ[OOkAR>%cQmvG$hȤ x]}P`~sᏻR:NZtu%ֆڰFLn8R*Te pfYb%v-ԿlY '6GhD$b  j]y 3(pKؚ~w D80g7¨3F "4 144%[((:]V?Xb$ф8H#ƶYkA&WgUD4F \)c#b4q(i!_PMBgA,EsIhaIUS W`KF!H%l` ak:"I i&amq-:={>ذQB6cIcPAk C@ܱF0PJU:,&&HGL f6d>K`A[E^F;aF$,I80!H;Kr3 3j?0).D9ML`:$LɷM1EjX2Ic<򤅡_h Oቧkmg/FLc +o\y"0+`*@&G_Cԑ&[`Ȧ(aeEHb̓sR<$Vp|lL 4"GmBBK"F < Mgb>X7lxڄ>YJ@i E*`8tj)T͜&8%N!3@``l y^com.-9¥9Sϔ)QH b1E,$#F|z%(b)lh;fܖO@LOS:0 :g $O@?q'}_hD[ \-8BD51zƜ3M4|b iT,FdȻ "9d-hYS1Kp#Q|)B5Dp7QK[ ׇcI1pؒ#P2lŹ'Ơ5c~ a(Rs8#puvF5a> `#P$ڶ`y)wO>ue?_,dAd4X0 Ʊ!hH(=:0`.l:ȎyA;8J &zr8phJ g!a4@r*r8 ; p65_ Zi-*vpRRWHCc3`jtJ\#P^v9Pڠ\ Dc6x 1`(}10 Tp Ԥp, SЕAD`dBc-$ s`ŋ瀅-ap@p*lJ)aͦ =\[9gFpfl):0%Ee1d2fd"w:~,۱_*?8b$H0@0ьcXd@&t9_r}ۏ)'k-ZUX1ewy1 $gr*X1B##ϵSNRC& |WH&=Dl#}h&0c(>3h<xH$R1 VD b`G-#Rڀ@Δbzxa8@Z>TAk K D6,˂# :@<1@8>>BbV B#C@T@ rEԮ)D`0%gf B s J Acǎӄ@d3y an<< U >ڳ"!\; ԮD4 -c16í||xo,4f<1ƀ 9$# ó^pˡ\Î،XGΜ9023X*Ev"nKDm wt<Ѷ6ŝG8JBC@5x;;6 D aV(y.Ƿd0fX*,<ۖ?0Q|2D4;#@'3F B04a;6fNÁx]fIHaBЋcTF_)]D> MGxvA0bm T {GgTeİ幃s0 0a{#ugcї󱭯@r ?{G6aq@P}9s0ާ'`(R*1F*b#bI?8qOq"sO"&n}`2꿹 'g߼7v/k%%d+G qYw7|gtvtho?< vA"P=`BkFFB|{oF+\Kgg-=:eMa{c6l ~v~ #ױs-7_f)XVih7y/́ 6Skĭ83{̇! P )/To[i\kuuk¼9 0@Js9:1n õ 6Ks*-.`Uol.T,(!L?|ln&:O3x0Z7}^LDd* 33; ^PU5^5[tNe};>w@Kؤ^R\u_.@wgS3jV 9dPʥ7t:my@q0sYO@,ąaTX G2|D/eE\r O<`_L|GOG @B)@Ԋ?(կ8^Z>?:{Gz?Ia3''83hc{`>d9 =!(gAvr4Ģ3d,(4R=Tx|{Uk#qI ų 3AJ¢y-7V~_ PxvA<$܂Ѽ:q|Avρ`}#Bcnm s->?Kx@MAs544h^c°dHf`qOcVm3k2^ 9ssɌX)ҟ6+ltf Wk Z>ff=߬ok>}(776_+@AجV&zS{6:M M 8~;??{ws֯Ɔ grNO&zs{m~soP߄?6Bϟ_~j>j a|Cՙ:_>slv.8&&hdhO,=ߺ0]b2yul+={P._\D#cyg?䃷6s})CU|a[_`k*eU,}fDa!'c񻾡Y>wϭ̮snT(hx|~-o?>(ev(ˠ /z:n&<'{!Ȳ PgM(i*>Hb w~[w?6C;S_1nQv JC|)V` ;ջiʻg߽طk+1::};``8w'aKUi|lXۆ/TvcB)Aa ǞƦ`&rEL8;GO[cĭƎ|Dqs."!'=c84i= 7{(1Y67:#YY## e<}p=+78{zc#t(tJ6 tvj|bZT?K+.Ӎѷ yp]D$Mqp*A y' iW`/7cz m⨊C%1|?W 5c}PSȧNkJ)/7Mǃ`^;ϺxcQ>!π߭N{u]2J/?$;t'c7`δ۠1 G߮(8Xj< ߧu }10vx<c.|p'%4s-}&<؇M!$yڊё;cY r/F ܙ_T`CЏL4?^4{Ǟ*Xqw뿾ah ݆a80n5h2 GmUǴ,($c ^F!q k/{+V_t? 1l~j> D)|F~vjkk ^l Xy>Gq+0-|ːoU^)9g==pLmqB)A49řgyZ0񫟴!!][OEG x>ZsLMUߵ,lȣ98Ōg?܀Hp(|JGno:TI 8f,\}  eV:PܶțZ*p4epmU'PQNc" u]PhFInI1kq|Cu^M] .y`,E>e / cj`,eRa* Ż?ߦ N1 S[d j22zOZm( EڂR'W7Y7.;7NLn\`~qې+G7 V jaxNzvZ(lrl]困&|xvw$|Y-s> icsc3/1GO;1&D(z`=72X sЀD <,9X |& Xa_G5@` XΦ.GW^_UB)r+@흝Wl$=_H!1? .tFOp`Pe W.Fwx~eX h (As=`bQcˑiEqԠgHX3_áލޑ|CxF)ܰ L09 dsՙPfDI tgWSX H pπ . r%JBMwx&P(h3 Hr@|F+;ڜ 9r.K"N*vj2|ח#Xj?G kӞ9hAB Ȧ97H7xo-DcVcZ: =R;5#" _+`Ya_"?:R:: c%᷈e\3?," PaR.0q~9>̪dPlÈLqH9?W7Tvr|>r]<7 $È];P {/-]I@~q|[\ dJW4K>Rg,F+Æ%Z[ѻ*1]bkEnJE|Wf F8*L@& (,Y,[ac g& sV9zo"hH4x Y K@@SQ  #;#*sL#[ `L>{S^acb-KUqdsAdG9q7 H+ }qp9DWoƭnS9S:i1|B`yи_f* 0)F3ވo$"?|JXnx~רJs^S h m ݝ>*s b5RJʮhvR1 7''bЧǠJ>uq14[ Ln)raB<=WFcHJӎyƵA៤} Y\~ќdy_? {χ֔?sk=6 !?(n5"G~VFcHM c "cy7GxњWZ43٫0ƾ_!~#0Ґ|c&52ve<θ!(7*Q5^N%hb8hox#D=ˍ 0^RirjLɯщ=KRlR'#6(|էtJ/Yrӝ#%2 l~Y'C ?z'=poy Kn?z=`}B(@S{ѣ8T 6 OZJSR _4E'pr'sZ X xTޢ>b+ >)w! _g8i8l4|-#T.eZ.E=v E IS8[@W#< t&x EĀ⟧ҟJ񄛾m`M.Vɋ#[pZbcX/GP0@,|Rҽ VG>.& WO֭{ğ^zvkkkb#_LG[[[#\rɜ# .9W^y*ʕ֚5k;.lUW]K*\r%񷶶ʩk׮u嗧\~>M⊆# NYkkk˱/Oϑ6q饗6_vm_/r.k<e5F񷶶ʩ饗֯]6~|:83/q4]\&91%eS37iawT}}潻jkNfq˲~kʭ\z?眿kƍpؗ%֭[5F&$ :U5TJwuȞc ɥ|c{&\7oެV^S7nܸkkkڲ ?~k+ )ϕRo3/r+No~7c>|?OD͛MaizcK7ok׮1cwOmO;\-"wOZs/? ߬\)6oY{{[*6[Jkl޼@[[~by}7bkmmu?dyƍիhQџ껧tJΛT$hYfY" )ereߚ/ z`Ux-Hd2TR= k?3^IEoD쥒 w]x~˓?=Gث{*(DɕtWWk!7.w饗^t$5k\x;'b~`;;uoob5* Onݺ?$ZQ@ ͛7/okk񱱱&W?TV'Օf2C@R1tuu *vsZ[[3]w0F-:񷵵51\n׮]{Ɏݺu[[[%ZCEae`_~,ysӚ5kS=PhhhX k+\rɒ5k֤;::̆ m %0Ʒň,omoR֭[/:韧UVfɶm@QJya`6o\V XGGy)_z{&cvCC2An]"w*?x!~p]yki 쫼Ǭ^)ҟ+n f|wf}}笖5U77TWMu/K;sqmmQhlnCccgsKkkkb555ѺK5kڴ;kQInqs7FvtcS}*TNoH7ΟYv}g:G'u -+t[(|^vm|?c91&FD)Zn]1'mE-U&O5k֤ưO^+:71:l;mySc[^-]]].hͥ~dD5Wo|c.'oė5gb{vn/J_YƘˏd_)uWZ)~U͞V[Ye˖b ۶mczx݋NU[x'/7kG@i\?   ґHğPsyMU c<:}H)__WwyپaExG̬H斅3ڂe7e#(˾%H^;3sq8N[n۟z*O&"-kmYqrY.0{Ѣ㬼{o>P`.]#0lgcMKQpZ2 ʆ\xP7@YfͿoD#ѷI!ؖH20JyJ%oy¶mܸ'w5kּWk}gǓ h썶 -KWoleY7n}a|hիW9oؑrJK&Rz?1{h4zѽ$ڵ]w ݑD<޶R,..ɚNz=w>T*n^(-+p%K=uMMk/Y-DT܉qd= h.-~7{M]z2>!uޫ{D,:ǶH)kcJAt\~?Qũww2u]v[(ܷ-_e;K *](6LUFODu`F_kY˲P˿kxOOёs `Μ^7jG]u".gpccL{ 'tzvUmj"8c" ?eMdTn|B \76J+܏si32V cpGY Zk\@togۏi;ՌZ[[EWWrg6yY$ 8N{&[, l6aC'}#gnZJ GS9@~O>zmذӰ)38>0yF(G$@$i sbma4ux:i069x qg a{TsI[ϩsEs>rsB8PAZk=G|?WtTȝ:Jc A261u_v Ӄ?PYy5t롔EcrЎ]SMВ_z]s18NcC<߇]ʼnd)Ձ ? C&'jC##%1gΔW~ٜ8-fZɬ53G#jNxϿ==j}V<[iZ/)=6(%VZKEN[c}ם(׏adiht앻*7&I&h]:YH$q!10.ruG>f6E]Wmk*p%V)4(Hic)30r-Oxssg]W}^(DZv\G͌j) OkCFH%c)j޽oe[oesDZ-QJ!d@;J9}__fCM9sD"2SFJ!eݓYk1'vwvy_# ? 62VK/pmlp~sW8zÆ#zzlwZ {ZRXTJI!3kږ/ z=3YÖbC0B+JJ)Xa| 򧮘~ lڴ);trB)QʱJu(;0J;xƞ8O- B&~ˆ lEFCTg-Mמs]?.n ۜJuuwar("3! C(QQPH67_Դ| bÆ^{MZiQj-A V[q1e&Ͻׯ;*z5Z-9>V M- mv>0:q> 9m A> ڋ]ml绕TQEb.iilnqkIpϵ-:::[)Hah APX|')xΜG=ҲsҺs5fe7 Q ~̜TRX dM6vi&jH:`^;LRƱ396}f3gbQ%I<ו ut8(Щ՗޽ZU^֦[JWwk΄QB{~=gw*­PSR?v>MtHoGODZ 'BșX`A8ʈ}c L9K6|iq :{/dSHJ媙/8hy ̤9Vl\+w9Sʮ6BFBJW @5k1Zgtrw HuOD8ʝԿEVax*[裏F =>ex-we|#bJ2\ʑ/ݻ3bptz`pE Rˋd~s3ﻇL`˞jr++ViWVQ=\HrPʩEf:,ݺu 廯$|kkȈjQÔ8;bUw®n*ll,(fXAl 6ل`aD(?,jknqp$zQ (r_W&ޫ-Xk[zi Vh&KGnc1D;aV-tk"x5B)*9pk2֚T*u\GxurH~_ߦE~ʳo&2q;ʚ1FG237Z#06-yٚM z߯54䒎fZgv2ƘyıGkIx ؞CGA/( L*hT>3h"+ULd}ܢO6ϑkgl\{Y' ㈦LHq OhH'H{ )ű<~N!O5!5 ˒O}ī_\cl^5XO֭;}ꓷ\43#f2c)U Mzi7rk_D; K$΂CORlLx_I0/#FL9i-x!]e k=ź~r{SUX+b6S BU` ;r1!RSjг3;uL|c L}M5)UCr.<5a}HXk6:Q YXk8BᔅsX@]KV(qsQ3]5K"|? tlpT=M ,q͍+BPc08~3UN>v1In^XTp&n]v)Z8"Vhc㠐 ? t6v﹃):16`ų,EYOb_Mb cSLL kNۼG=_bzj5588x%%S*#6ֳ+հ$)Ŗ-@ ӾK]!g& rKĂfՐ к)JMV~wTjͧ螱X~6'RĜbJ=T|G$CS dbsZh+dbM5fpw@c;:: =u WŎRVk:vKω8@K#\1Z|W ؆u 6 !a\av^sټ` wG : YQo,245/yrX`cXh˳l?n`& Vւ|61Kr%ika?ϕBf*rm:R%3V66i%)㱦3ϲ Ri `[pO: ª%Bk5ZH!H[n."J~*EiryN2lUg~;x\_ƒQb٢9X<νC46dh3@ScqrctmޑB}'өF'vRTiju$ MXz ǏTF 4my 31Y!{3Gs8ts¹gvk' r=s.=opyʯڎ9n>j%0h~~WkL'kg 5q Cl{ {ay>ۮy? mjooZ R!57܎4̥}cg׵3=51Q-mCYthjmq]tݹ 2IےH?Kf!n֚ꊅGqՏo;?;A[ͣO{OfyvbU;V#⪗h?19?7=G`|Id&\KgԢC#<J[ ]FIDATyqj|HGm+h]eab!,\tj@DG+"MG[Xɂ&\!֣[w g8='_Z Ӝ94A, "2Rx|ƒ{J4gH5z9fMWG- &a-[yr Nl hܣlPn&O[R)]0-G\OO"]>Ԑ Y]ui*f!֚|&I1m%y$m}s! Ȟ,kMՊIG4g1 ŤC1t%mYXڒ 6ޱ{6|8")<%iI}lH33KC&$MJ7/X.Bdk 5 KcFMļ"6HRA&MKs'<)Tǖ3OX U+(`Ţ#t2n-ld~{$9"XYcHxm"kg4:U* ?%}hn^y7~5X|STT͒ǟBDrO(،VTJoZOSwtt(!-'|5blbNNMKH)JȸM(ĩ yIBލx\v@uޗ*ECGLNm 3s C09UB"YG*~!]s0ٶbQ"d*v !d9m8N=kֳX3UY |nj}0R%gFL<(j[ G@ʁRD!Z8=}봼Jt/N(~޸uClFo2Ӧ~ݨ|ҿ|W'pa5j)䗏m-5+[=E-M~˿xsoLS1=EkMuqU۟Ƅ ZR&Ň/ ’|D}fIۧ>0o}C\أ^uw6.\<vo7\aHTiJpыb«LB_wC}w8}믎?tIU+V/.}ftx+3~Z19ue7VVX?i݂G]~{ǭXf<|o˹Kk #CrW)NJ[W;zϫ߶>ս㳾?j/z1~z=%lN+hc(ӬŠĔ֏{_>on=elه3]c-%N;|k,~eëwύz!?~3LCMXf47~U6w嵿%l~t%[` _.ssbe@b0ã}w!G/[yM&8懿{B\01]"֚|ğṭׂ`ֿ+<3WRV!WS_t f*ctl6JdnB_[;VN֦wV#39?se6Yj%8qB&&aLÜFU8)UomGV\ N֦?]4x}?2ιW>m'UHL$?2:'g~GL,;?'wҁUAG׍(ĘwK @VڤL|l8cdwDB˪o5I?$|cɌG )ǯ=lT[(2+Ow3Nh0s:ޢsU/mw&e,>nG3>Sݑ{ݨEKw'X|_qsdwoۛpq.W Ồ]eTe̯o }_Zj|՚FJtƧ Y[u yހ;*<Qbz F7Lv?}.@v8Ij5LLCx<^ZyL:_elBo>sJ-FJbb k:*eʼn VI ;9GA6hcHJauV@u8-i?Nҩq@%7kֲX.Lǧ=~ 3` QzsvG(h&chg{q: : ժö}[S]l74ec]BH1F9\\z7_Yl ws~=/HE\qmi\7a*njwmcC@ wl!H4/W鸯* 1EUQFvÚ`h 暟/sցBQգDZS(>Cv=y AR5q\";Y*<倭/lqORh/wQgƖۯ~!S!иWq.סБgc9wԅdžW#d:1 e/ǏwRs1N2ߪ)̳R(m_.u1ҐAS &` U?mJ/w0P;x_PK4s[Kڿ |()p :?Ok`|o`7U(Uf1Ez#Ao^JsS30&TڗL]vn#i dw(($R2iK"q p+`)6#-M_z\?\~ܼX& M8A cG1ڽ aB,HІ[xq${F8_*/v1FScï%d"^GƸ\Qa*P̽oeOIXRtHM<9it쵒7qR5S{![>hmpp$Gu!) d9m? QH4[1B>1X ESnԴ_bzu(d:_~ҩ_Tb>}Fy].4Ԃ|@R[EB|qP dP9`BcmT4K/_a`t_ޕa0Q%Gx&|7t4:VB,X8O!U~޽y>bBFHQ:s")ѱB<χ` S}LS_c\\Ąyg 7r5Z#F8blMHJJ l TK@BU(UmnΏC[J=[tT Ickl,l"q*Յx3wJAYhH1V b)Ģ9\$$ZMb%T FHYsh,} A6 K¶໙J;lKrTz{6}ߙq [N:Ĩ"9"2@`g~D 44>}KG Ҥ"Tic2fG]:>mqbKu j{m/AI&z#bN>]6l^A_;AV$VWd4]*wbDV1I ǥn=p vj{qw28C$ x6f2 #)9.L [{hqT6TGX2\8R;4Ox ǭ7MUN*(O߭N,c}f\= ٖz=T'04Ä/N8>9gc,斧E"Isar#loofJrq (y3^?t@}Q ER*ChR4|fn 6o[B"H%J,$'<~sM/ʫB6X{χZ%=#vsmly2M$8av߸Cb+ϋZL%ɧ>D}@JUiidqI9n NБ})ͽA \eYDP`Ū[I50:JT5 #[47Z[ A|+k86!0DFy. *errZhcbnX rM<:Ո{J2F7n@ELmXj7f8T vw_`=*G۫당q ֨$3a66l 2dSst^(s̏Bal 26W1JPX)B_TSȽ A+uz{%o'B>/w؈cl5 `t/Q҆7vdΦNZ~$7]gU=_a;.'m1(:K+vLf^QH0?'LiT=\T[п࿳fZDo7erY+)M )8Tk">G +C.gR +.457 w=݈K#v$jxxGF1RKi;} k6w3}DŽ. !2nR`67.i6\Tlطy;{,G6?Ԇ>Su G\{(!w6Âx{Excxw7t*(A'lzSɩp?*4|b|N`̛?>7\;7U%/x8]l6:<D jKƙ -'uzWne'C)N[yFϟblo%_! LNc:/->6p=UߑSW87u?KV`z21(E~i#ds0յ*ġ*S}Ѿ G+Hy-4+ Y1עl }>TT 2W&BZӍǶUu@uڵ7T }y WK~(?#k؈#y,%400Me+&`rc?M~&O{'dpڱ_ {hSCͤ*!K;O&P&\v!.ho?I/ٽ~q%'hh ,3!(`pN24z]/]uT|vMTB5`(U!W ؗI^iG3vϜ6a(vfC|}]y:{RYzSm9[9jKQٚy?]=@^Qmٓ9mf|x{$K" s#=rM2Y *OBmy+½KL?\￶;NW%nX136ع#G"!ilq){ޟkCotaƮFn&Y]5Ȭf#}]8߽oxؼtBm{ SS i`NE2;JOL>wHqӮ/}\zn4_(.$L5λr=IG(HFka`Dz?G oaS>9#l;AgM͞'Qk}^L$wQ]7PQ9*S@R ;SqYNԷV+ʀa5|7FE#ۂ#>scșiz{cWbkn4Zml4r+e6М󛌵6`'gY`z:{W֝"Z1*mg=| ~gIn6[w^ԐkkjjL35YƏƞi׬rMƔ:QujP>"[j&?}h,fG~ACs16 y64$ ]()vnf9yy(689(dQ7.ΤKuUQ D ,~-;ǁVP]Q0H-'s !bOAT{Ʈۂs^J'*GXGA<\)g>=Cfy+GBkauӓWe؞^}<ʑ]oNR'ys"_: G"Fю( ._566\=rgLW>_\Z|[&J6&іJ>ʃ8% }_(Ll.g`o>z֭Ȝ~JmﻋYktu76m"m̊eޖK/]g2 06]Ƿv>Y6md"K!Ƙ0mӕʏ=rD.| oeR35m J M WEu6]P|{!QRJVmZk*cN^krrbGϤ6vwu/c:q|SojP]{^K?%`Nje\ȟJ(pXc1#㓣Kڱ K œRZ10 d/yNfvK׶ku~ٚ<+{Šp5#=ce}?AIJjjo~ܔϞLH)1#SR?nB:\2yR.lTNU˗l73;3ď3IӠ& CJh\{߾:Ӟѳϐ4԰ {H!0plmwx䚛3u#I4 k~ؙܼgsRehxw=ϟ^vs+="g ac(dˮCmÆ>{pHۼpmGSaeJ3j7>2Vk/l7]ذ2H"e,ZdƑ?>dZM'|?X)RXkBGQ-Olq0%s?L*Yc~"=8Gw ÌGz*@wuιX|!菨7}0u/7:>]{#*E/ks;ۚJ)#aH!6뎎OSؾ#H"ZllhX*;XkZɉx||{x'cAlE߿6q|uA6@IBS5kFk%;^+zGG^noO46om)dZA$+$=bThzONXb^>+4,d2K rvkffgV !J5/UO>0?/ϩBT*TJI)jvVk1nVvڞ=Q|Tb1na-X,X+0mO< "[Zku2V)j5o`(oGX _JbR{(BYQ[c0F[)t$#KW yn ĊBy-"f+coؕ7?}:!Ѹ-ͫTV͔Y~wCrTfYnlGsb;2&u쁑`VĮRҩl3\3g]j3mm nkmdtRBHRZ-pR:ͼ!GSB`̍_՚XUQǞ1z02 c7 ]zyY,H4ҫ"|kzfaXN&.;q~ǒ<7>鎆4d1QǞ5F,G:J\є][N'0ma1A1X1Q\ C"|^L*cmXHkHS4A3}KXHxMx83| =絮8b-8&҆0 88Q㺞ڃ߯Wt0̌Tqh,hQ7]$R2YOdVDZT"ʧuxLJ&KrRSO Fb&:8$EdSS\-ZkRŚWs| g/^LhmBuHXwl;d9>QdD=aIu"C.~ ]sO#jA)i8T?ݙ)s税zFH=ېK֔%\tj:qAF a]9CC϶,?U[D(%()i:ttI cu]y<堠ޑZDS$3/ #ҐeV/KGK6q:햍{BY_&\8 L& ^dH6AK wf 6Wt>ՎΟIRq WKԐexY+֢<eS^iggg|r~l!)*zExr/Z(@(5|OfcBq+ܺSX 8n\2شՍZW,s))bc 7Yv N)#Yё&pHyJ$~ V涶Lq`4|:?XkḮ9)fA1ӫpIGULW][vcs%5 RYQwK:M) !ֆA A,kɣ&J!0oi@Ã;R 1Gm2xglg'Ns~@,/ x;ɲfYE^.7Y-uoo볝N^wc߾LS;Mr.O );]?7l~6)De_F"QW]WGJju)\;}>o߯:$IǑc)RڠGTl/= !D߯ڐt%S./W +12 OuW}}Z3===j/f $ٺsnqX)Pthi08>ȵgShmbaSZ*wH%1rDǚ(%#l**=&՘he34 `q]8FS)MSS|L£\Ntܳ9+J)B k8yfA8k -)MXD K06!14J!D5z,o /&c\clt 'NQAϋVbGx_wD.`XO %AQ8VWX[APe a%@wgٴϒy-Xk\r%^̯o|R%@R--u$Z1psĆGf崶6he14ŽzAT*Te(- `n.wsRjxCNXZ% +4AE)7_TZxv:]r^ϙk G)59$ߐNx?]DRC#I\wM:Մ#`&oV)dž={"@,áCгal/r+R 5JI1sIk ? g(!CC,+P6?OsAcK-XVB I9"mgq%j5 ,m%Jbccf2T5ZêDZ;sT߾o\C|սr]MyȔbHWƐHFxoRXU'/.u~UJqo0iA1y~?zr!Ή^=]v47>i;r6e1`&I3WsӐMUڗ?y|>'SsN$_ ]nalv^8*Xg1&ԏ︎"rI&kadtPZIgst%JҼ!RHo$VZڛ Ljj!|uh,fɤH$<;R|!Ҝu,׈&tq\E.푘?nJ`ߑH> b:IV dS,IS45yZU}rTiz i^+dk5LߙS!V[08PB5=0TOyi^[t -cRrUKڏ]!0k 'n;Sq\1{F-,pu}f>ǭR9{}/]׿e'"#lSwDs5APF^ҺS.+֯.E/q{}7GE-;/g)sCF$D]HֆRJ5$i\Y_.{Kosuﻮ=Bks='nqƄ5`#|@dUS IO7zJ+\SM*q?x&^]ܱ\865[/Ҕu(G\?o"2HUv¶Ly@3{{uVƌ/;ҘK*C*rkc#Yіה]S:KO,iE6N'F(!㠵q]mp)e O,9u(Fׄ(ttjg;nI<5P+AcbQcZʑn8au !ˆm/[653A;ylhM G[T@1B3w?]>ZH }`RG~<Ƨqyp?*Gk ?I6y[/4 ӈOՓtF0tN>ɱ ŢjOύ55cGIXV }܄yq?|uk`Ƨī_z*/>s5& UG8fnq'^`Idcyb|7N}KMGv'Tw'~~7[آ 'cqLԘ1y%˗tǪZջo౫7/^22};~Z띲.dST Yy-1S5^x 4 JJkll΋>x}wdbttSꮆޫ^{Ϛ.$(M 4ņR5&K^}|s|Ů+¿y\2Y 7Ww ۜ+u=nG T}޷,oỎg`FF'V?\[DW1%ەctd<\#p!EO\ԘfZ_2m&kӣ)Gu]>ӥBI8Z#:I6H+L֦Gf=]fSZ53;!VFWk1MƧLW*]:܍TTTNa-J@M AiKhLNМcd| m4ŠgEk[6VEH%]w,C #h$5V,А Eqdl :jeƧRbqcT\ʧRرσϔ06$\,C%ʕ!$H'KLtPc)Xk\GrRHHiZ P zarT:/Ɂ= qLZA^t(Sӓ`blCh@"Qs/lX>=g'&3ɶK-neZsmb zEϹV/c]Ajc! ql-ނ/g=ۻٰn =]1Ѻ|K>_p Q+vyk(6DQ Fc%ҖH1u)kjN߳G_;z׭s$a 3`S}8Q m`0[vq R]+6f Ҿ?q*?n[Y{SۼanTCsƵqS[ a7] S.n{ctc,4>Ⱦ`B$T־}9h-qH!ʤը(>ŎjrC#UBP5J$4<9fAan~KN6| c@n8a턵PV8RQ:L={YIϸ Nwݛrq4I?g#&!;ia"5A?ϾXl^)ǚ('`Y4s[jĻع)W66_ Y[Zs![,v&!bNEkc~z{1cP)fn^+a먑r0nJ`<եSsO-iܾ>ۻm,UH0[XmشwL+YʵVsE.'%7ƍ=0w]vR̿:B 4qC.5G|c>puqIʿ-G`֭[<68Z~kT8I<Ը5υ ࡳN;9i'u9s&옐TEr,e|SW-{JgP]xL*֝{NUtQ+|]ȭ=_`nt=F!f?2Z$ O7<}+u˩lU;ށ;ƊmF0>Yӥalh*5׳[a#G/?btz/*M͘R(k&,4ynGګx=w-DmT-_;&LVZiM:D8][}Aocex˱׆ ksQDV^Xk7f)Dx>q=v&g""n\= WjT\X˴H,6~p]e!kiXʗNj>}MՉ$BH4𿿹O}z5JPi+VpS3tg9{R͓m RH̯֮oܻy ˃n`X<c?}, Z[O(z&q.t3=uЋRU7NXds_Q;sgcי?GT'/:35>2Tyd9Ii- aG"ڀ̑K"{l"u-+try^Ht~g=YmR"0O0|C罼\U EvEυt$0 Vlz=/SmBy`Fw֏LLMvrACƘ{N:M}#$+}4bī&kѠܐ}AzJѱ]-|o6mݷg\}dTUB?;bVfjr_Gf&_:juPv, ~BY`?(cK('&ʱ8*Sv ϧO܎5/X׿fl(:ҍ=(̞Yl#{GGaX)vw_C;q96%-aʉ +D5v#$֚9,9f3^n7:D{ߠb1 Mo7acJ*]T0'{ޭo[P"TLRzDT W1%vMv8: ,yĖ8ӘXC~u"?*Go[_RH[+cw?E7_/-/!KRi(O#o?].u7̯z.}vCy,bg_拣F"i4 #~E3|f RzX[R}g~Y[0Ώu|c]ytBIܰQl'Xpr|:<Ʊ2V2^yUNJG+5OMcN减;~n4>  x:n۝Wt~奯cvZ)WrKxR<v6ƍ_ k_W`߭Fdk5i(qȥ>g @osFݸQZa?CcߊoBHKVd3sWtܧi{Mr3c6Vc!Bx$"#⸱Ѳ6frXw|7E'i;̟S)K"K*k7~ ɹ@-kcvKJ&O}?4tʴ@HMYYcZoN' ͷGt/Lξ4In%Bt!#.Y|bÆC{A|jc!*ʛn~[i2qTvjұo!X<6=GϘ-kw U:==LW>GG?mLvti޾0GX2ƙ0ON偽.J6ױI.9k2  HK((VDE"*c=:DTAj !OL;.{qI!~{u8q笳}w[L > Ծ|}?#7d tr>%bN/—q [[k2 ` `ju!1t{~*+Hㆂ`<UJ0a4S^IXM˪T-QX%VW²Letd؈A_NBڒVP#flinwḥ磏Ů]9L흐`p|k_>[n씌̄VG 7ccntuY}Vd:^kfDr죐]xן fWN9 lP&WKaڐI~o~8sO-Iϸ~$ D['l%6nię[aA A *އ?/  7" kL6#%$c+бi#m@IDTe{kGOme#Dwt9ɏ k2i!&U<7nl0TV| {="lblSʸmND*W>xYƒ$]sƒ0}]oYM)TR6B`Tl:g>V" d~zt^9j$Yw67H;LJ`a}myk# XU 9<3z럝ٮfˊK(P;V /U͡/8<۵SXq)lqQ O+Qg̷J\kr9DG;VK00 CG#T3`%b7~o_nODRc?4;n@QqX.ۯ^71w^>[P{;%Bo/ab!4]V:Tӽ3gXԆ& Fm! AUuga[x9h$<|o񣈻Qr9.|% *n|6L6l}C{{ Xa؟F4_[mL.!d…~|`+K^VT]?ͦ1C%&fB`ß@.׈ayLHÀlfA 섎]G.`KX c IbƋH Ľ`ilCVxt^xt(??ҶM0Ra oY &va1as$r$ 8lhX𜄗be(&AQ=C<0 3&`X&xh&s ѫ ljVYާq 7/^%b4` akЦ̷)!we"9K|/X)~^4w^>|r6]f',FGjU\H'w<@ Zvףٌo]BE6|dVΟL,_LLjo>8%Liz6n[ k(QLi1%<yBk- ۆ5BHPΐw| ;} u.v:UREؓ^DC? |@< /AH}xՕoFO}-b 80 S#JyCX%u`s'%r^h$'{@XYxJ ~؝]+5T'c$^)wl>E/r<{UOeDy7R#x^ K >K˗G\ אbƨ,$RI@A.a'ʯe3!|c!1 KD:!HB( Ԗ?a_}Clz[ى1XLp)"p,$q$k_XX1Rd+`1A̵}G0K$Œ͗H㈹cSX\n18@G̱pq$|IɈUd $wGa, vS&%%'d*ȪXFJyRL5))LҲd?Wct|`pwno; `Bſyϡ}ehƀL=d(!Ge:P| K] U}"H1}Xl= |G7< Tb0L4OPP8!V?أ[Pnڲ}c8@t͞U"W=I9ӒV kMSMbɻk~٦ޗ| *VV'i[VVhm ^*ʏ^?\,e^ק1ӛjbM,[vZh3E`5%)S㗹\˒""t՞߾qNŮ.pڏMٌs.;)WV;:s, @j6~g o >͵P^;Fxq9P*S8dlJJ?+| 'G3/SM\me6qlK 6@k T{ľn^%=sL_&ul.70>8rl=}}>U4֦BJp 0+cyuWt5}?qAx?h\M&WSr,3NWdNyE\L+m@?h+TxcYoLet0d(XPɶ+*~W rk崦-Ui/MUd1;J=ߔ| @!+lm?ݓ-t:nQÐC2d}*}k&S^oZZ/M'S?'0TTL00Tv֖@[[mCm舎ekqt[[ȂEyo=єB"7:CÐ @ʰzMEH!Q?1KgA"NjOOKSQZ 9BaRNi;VZ-Wxe2|~ꫦ5/#f]y>hmԌ)lpmP(iPkwy9qצ|Z/s,K~~rFJj.xJAɱ-D];wGʘ-&jku*w?TƲ-^_s[ Ur,I LmI|vdUmѡR:}GRE;CsyKJ@wC"\ = :G?6:k/ީX_I x5Z0 CGk-֤&c a5+׍8L8L"eDZ1a%&?`bV6&JfTU&@T|>iHlێ|֖F@~R>_$`Gk{{!zXVU((2'Hk6N æjjm>J^{hշc-"!P[ZkaP)PaJxlF]u3֚Dc*mjmic16䅊BhÊd5q? .<%5SiKhBK)%V!AHRd֡m5H>fG7n fiaAFqbY V*F2 36`fbZپ&e' `1{.`hپٳ 2يt‚ѦbJ)L1҉JU q"ٻQLG (m(,L4H&6lT}Cm Muf(]q'{S[ɸ{t"@M1:&Z2dfbcDyE`tRk[/bbGI6VҔ&YJ[ҤJiגe˻dBq7uT<6BڳRJc1Q@kC NlZ´\'6P'Zi׉Q1&TJjR&m ~h0F[ϰf2qOyqGPa @k"r 1BZXvR։]J Th &U @ã-9f[ .]zcX*ui,s0dFhm ad, |hnƎQe8F"~}xsmR%7Cuc?"3:iF|… }K5Iĥ v0dPZBCܕ8.ryQx[OtS175h`7ٸD a)`۲.`-]ڏrIԅAh CJ6Ƕ6 (x>,`ؘ?#ze-k1Q~%0F%FuDHBF'޲hmFIAZb {\>j)m _|"bɇPJAk-O-|$]!|TCX|<׍D53XRhCZ0Zhgڇ IUNT: 'vj%"c=]K TB4.?F*aIsg6sE: ǵ:`hv~|ۡVlf(m^7(Oñd̮۟v) PilPJAiPE˄hHp&a۲`Ѣ \tZ3ƄҀf@`:Q(xṭ7:,j%)Ho{&J$PʖH)BuŔl skqƬv,h&&V_KZ؂YWveIrn v2h q҂7|_A%gj^Ӡ̠߽o$Dܹ :/}u"~~˧wd[rfM""~wtׇI@a6(h/öl-+Y$a@EV7so`FcEt"ؘnP)\U.Xt4ft4ǂc;A*MR[[[{ DUx1@&&k1.Kk)*!*CS[2{{{{8 /!rlA8-i< Ǵ7RFC5 W9UaBLRtw"\[ð6 )5qK]+q 1,cFbVT :c`Kt2cS v%|"GSSiu,'QRpjW)󉈢5Jl\R|93Sf.בS c4ǖhN̓cV"/vS`6u1:AmdryQnI*o11F >p)hf3gQi X V`m H*RO$ATqEyZ~_3s­]wa@ OwzH:nl <@n?.wٽ ƉTGsB Xm'ij$fغ-tјܕ[{@ 5”/[.и!bq/D_x;;W݀gGz2PS&EdI|mC|8qx8=e}x LlH{} \ ApQ[3MM |dfiӦ%cv2M?ZS̾6? c[(|(1SҒW+HǬN㟁gtBDY+ 8'uV"n  _1:jhNv-ah'`íD}}flְDGm%ZmJCd.Nъ60t3ӓe>#:,>(Ljp%{Io{'-촖RIFX$b60D_q)@egm-ԟ~Ot;DT/^ 6?PR_|U?mO|jbdma cB xF3L9 ǘBaIo]%/l,?-|Y'cJ Z*1PZC<2*;{LW+٢?’x$7jHz4%#.o[^fV@S6u 8R Ќ@<Ì㦤0oJl- avF HkPz ] %Q[] d+0)P12棦* _ilXg4|HRka$uEL@#3jR|Sy,j@LkA9:ǦtRb4"l!@i?C+2sY㌓S N9H BXo#Sk~)UΝyeBf&y}̱Q N8*177"WXU&&+LntAww{H㱛`"F^:p4@Y/0.>7P(:XƆ 5%ߓqxFGCXL@Ú sa9W4 {>zzkYk&r\mo: "zn V0J3p= =hG4~_ΛsK{]>SQ:Վhixg 4$1Օ.,+KZ ֞oWoy|~oÉGn_K*N&jݏC)Q m!`b ǖ`OP_߮O7޶3ZOuwg|&XZ 9X #+KI .>ֺ#y'nSmMN9qaK Vle l) [ 8Vt&"K ! =x2/n伢ڎکQ o߆x`d aqiт!! J.wl 6Tҍd ;wÄ!d}"Tg(`aؖZkh _|?04\](DӧK5BeLPfmR0S2C"O?1“fJ/PZ[^NJmFCEJXx脣UD8{V ʅhQ "{`*C9*1,3 Bx6:fI<m#CLx!F~w8͵c]rN -3x7 6lf^_6lZ5&*w43hΠ=s9.߅JV;F&ͺbz딟U$SsG? L/2b57\`VKZBg<NO^BƘF?_{l-¨hih25vkwV&GsJ*`=C8턙B]mi(pj\cݢOo[/dď7ӎ>#RaN F;tb|tS;p߄ UtcG?ˈ6m:E9;o9g^#cE)*Gܵ # &Ƌho;= D0P??ܜ[ жs&;vxkc+$ԾJB4ZcJiJ!6.[#` G 6zџٞhhYkW_5&w6]wg Ŝf sZ0J~]9dq{,dq(HAɼ֏vt4,J̋GtDDGvæ9Q_01[ w.KK3*;v,_Y8GyȰ{o;>^o~uE3RQ|k?GyȦ]@:&& /'?KŜM4 ic4ο>X3ٸw GIƚB(KyyW/B13ZjE2"ڀ%b*޲$]>Xi5RJ.宮(@zA0Z4V8H!0{ՖgGlHؤ–JP:}{Ƌۋ^ɤlI [I囷 [!˛l)v0[qr֏+b@jD7u{aQ^ffmwTa$π4Q(~ z׀]Gh(Mm}-\Zt:Yo 3+ D vƪJ(JMm(f7y&kz=C]tFU|.5뭢(7?7v>1Hp} ټc3)^~m ⌾>sm3e[w> "ؾ d v&`Ƈ+֚H m+xc뵰8O|dΜ91 F&3C%F4:7"͖3>9nG5sE7yGq}g-U_OLoPt="7x' A~<DZ$bPJò$F$MYgLF]vqoB KKUOHgC7U۟zJxqͻ)(zlAm0Rd.?WTo/O.\h-tRڣsV̟q僫DX4k*+bfl5A,B!@[idUel^?QDj3%ڴP ql/ZHbc*gSڛj)׌"+E\)RUq6jw8)ǿ}AϖVSMoqmaƃxd|PcDA5-Bۢw4Lm9xhԅJOڧfi3QH\LK LBQq l]YQw˖&/>cPmsGm|%RP* (ȶT`hadBsϹnǴo;{xqg,\dҒc1~}Ź)$bq(?dK 9v,y kt7<ο}#`6<$ D"{͌:AB:MήƷ)j%7b$:4 x *.ka&6hQy1]dhwX뭇lj#F@_Z o؎yӢ exUFa`4׈lB ,(jT'4$,X23yc{a<^Gu+z~nѹkPH278cdUia)t#" [Z! sit{l=45ud ^=-}=m?+cSj2ڀ `1\. C d4Fr|/{ >ϟ?x唦q"T $li֤aGk#>v 8ww"/. ;t2dA%8:bc[يD4J_,w0DKNX"cADB 10@Jt^䋅w /]ɦ,f"2`L m5 *o;uTUtK?fڄc1%A BԤXTx 63`}V.;M@P5<4HU) `!I !?aOҩ;s .<Ⓣ8Rj+3h_\`@xdFd؄?cB(6 &L-m%0nv5qGb)n iR`q׃M/Ɔ 8FҰm.NƽAI$q)߮Njtwd~ſ5+-$-c V#ٍB2&6j`<( ۑm=?_i0R8rg0Q|-n+aY)н?jJ$*JڂK za9  H nct=VnX{H]w`d K SyS۷#0 b*;@!N$qHUA @n0ͦ+QNՀ-y[@BA@`NUÖ]M0vЎt2!*H'KA >sx0{_q3,ؼ9PV0Z/V~vŁg^›FX4Jb!onO+7[U*0:󮽕KGoyX~WVyexrsy#^pZcxd& 1Z(B3+dXmC?rp<[pv c 6TC XR0ȏ q7.CiTs[.'fnЪ*\{DZyؖ4CZ . 筗"l| / \vMƉZ9lLki܎ /ϿEh.pGߌ3kjNؼz64T.9 3c8_\c6&BÌF\xw6OjU8L4fm }Յk(8 mDƊGѫ+Ap_/@~SĕH?2+ץeLPP[ᮂs!vӜv.mZH9v̵gw[Z+V0C~u$};]hM ޺y˶ 1۲]G uxaf<TJ:%熮9A…[XmY2$q(lB&G̵C)}htl||n]/Ϳ;G [êĦvcyo@_-Qw߽&Xm~sdddK:֑1> fKE526M\ 5BVmSöTV@ )Loš yM&`0ؾ.Ts/,X]I'N6kߊs=,•.tGkG30?Wx X'}} W i ~ph::T֎&¶,_f)cP3u<f??q%VOA},+ Q7f7".- TbpLM3F蜛>DaתMq{;e7a*$vP=#tY; " Hӷ04Kg;ŻR r֜Y[1gVҀ,o fyoŲ~#Pj9]\:۱J55:5qډSms{ò~9YP"wwu-hn7jޝÒdڕ_7<ַ~n`SJ:}d;*3 Sԡ\NdIio5?wSw/ORxGEn$e%)Ro'6uS^IWKJ{hlU)T$5;Jw.]ienه\3I5su7YEtMΒ[0ʧqql{DmSȶ Bׅ'w`wKi=!u'l=;7HyF%gĔ>m{%|ѧ +14ځ.] F'2bJ>o=:o?QlmL^!o h;Q: C&F'' 2xz雑iF 7#(*Ĕʲ@vl}l`lYq BɊ(O~4gٰF׆k@d0^+!b3 9` Tv}6l0(eZa+@b;ūYl@a#?~I==Z`'Q? TX2͸SX)@B_GI{WT];]wMy=DwEĹwҪNM J99+~C~9P30g:[JYEf_Ã(̿cDT0(a7k+⃀SU@iRS+E|ssw7$#fZщd?{ z0Ţ]WU"c>b!W J݁~l8z03Q"ClQX V ? lq<`w= b;X7NWv('1BX V@[76mG< eCH_b;@ |{lN ۻ`~tvbyF5DsycזKPƏ>PF?{o "% [ktBw" |P8Fhr/F,@B\ 28!|, sGtDz{dn?=o;sI\t$aK1&NLu}^G4:ȋy) V 1!M9< :/?~}臇ç)i̟o/8Ɋ9 Ɏ̈́~e :&RDx郍]Spr|¥x#`Py~%",$יx&diO[8'r(VtEn 3>BF%k ß pqB}umw~A6 8`KbFa@G ׏ U9ܺRd3W#;Tf`Yvx=fãwƧYrviiaX 7)g>p :m ,-<xcl!\KvF@?߹$?t(IÒ8xF-!1!fu-T*`<ap+ۇyɤ!bX< G&߇V '4s:,-g>? ~2TB*9d !t y]@nMk;%|J]m">Ls0r7d۲ ;%b.04tJEY^sy0}3n[atL=J7߀蔋PKg0Pò^ ?~q1?3uj EfI~ULk͋aѸu;(qn A@;[ς^w->~ FHыZKVhr  8Ph0 R,Tg'&hzG7X,)A?ux.ӈ%\G"Vct|tkԇ=!TZc"W_xLF NHɃ<,yb>v'㡡PW|շrAxi%{qi<m!p&rRfv {*b! 3R3ż~<im Kڰ-k߇'$I&q0׹zz"ʡ#{˕w/F`[ցۖmY0&)/*͗_JAA ha's/F" *y\q_׽@O\P!\1KW Ҏ 2ہHtLvĞ׹RVXt4r@B_ńoX/d h/@U=)H$ 1$Α\&!FcgORA9#e s)Y@@dmӊ=hz`oO{kí'qh_P~҆ \_O-rf<=kE%l./$Clxxn߃B-Z>?D>?Bl/p4ݓE_DP)gO/yMyYQF}?//\.& ;X†B˗N^q-H60t/apoȟSٕu7P8.Z[LKrJpO>pI'6XM;vo /Zޅ%su56t?L+jw|Gg]*3n,]}9o,xէ~ǹb}nܮ>+ +_p … wL]5لvhSyld]2Ug z`|k^tlF_+޶[?/iU[Ucߴ5Iԥ:-<>1cg6͛6+)޼z?#<ٖ:f 6 ቉U+ɈV ?% !Ձ 4ï%-+:<<8<@ϟ?>ݞe4ZkkV~w߳ΖYBP# a pW~vg],!1bW?얖YD0X9ٿ_g4StvL* &VYݐ{q[kQ]d] 1NƔJcc $+| WjL%XҎ֏ݲg` %d8ԐqiSxs%h_jP?WEU _k1 oWqFڛ_^ץ*ײ II%cuI)31[vzkvݘH yopg<>yak h-T֑7]S?8c=KJ!@h)jVnycuMfm,Nb*{%kGϘD½ĵ.۲26ڟ֪x~pc7gb3m{QndU>v.q\˒2Z*˚Х7[ #:dl/zU܉[r%06*HmVݙ[&F&=&K[ Wbˤ%K)ZT*\W_p*L 5ݑpFo8 -^ g_w˄(Utѯ.[`l*ḗI)KLla__] jmiʒe LD3`(阍MVJ`^zV6XuOmh4C3G [6?[.~gli>+b[vh C~ɻ?W(284 ևÏC'USa}uSۮ,Pij'?28c2U6R gVoL] [ )Ey`3O5JO.}~_t/8h//%cv(CC򛟛wϬęҒ``*$fgH޺|s:– ]޵@X Z¦ۗ4dO-Bg$3Kk=o/Ȳm[ċ>p.),*gvXs8$h?3V3Hʷ.Y11-[w{q\"Ja+W---d33ǁB7FPoh86%`#:W*ke%X`c>eIqQJІ{^YQ_I2Mݹ"jݖ?Tfg[=YnrET等Dnv8|fŽ;U?t4XgÄPDeaIa,}޶>qҹD?w66Ƴ?Tg AǑ"TٟJ4=yë656"^"u%-0۶@jUh:U0wm? c"S-ô%k U>Rg?sP [M5_k^h~g&d+f&+l8TQJKf#a2&ڍ!A(l=STҋ\Ǚ X4{0{ HWTM%hZkEl4H@m,?BрmE=dLG%.BBBkMZkb6RBcyA`6 mK% kV2f3 ƄZKmXjf3#Ԇ1Bcb!mCXbދ;% #~2^1+3(Z*I)EZiAHa 1ِ%-8j`5m҉{$ͬm5N"@ vL*yҭo ?m=1Ү&ѻ5553Ҳ4 Bm=ԉPdr.䗄='& Z1وGğ->?0}BGӌk_A6̶@KE!1lTE]4<tGMzF*Ba`AhpPD|ʦMM53lۺ 46>DD1F9SS:I?"*/!e /0(xL #P ABRkmhQ1=:O Awa&SO )R4Hc G0 ,H%m5 ^pj}RAI(&$BTX$cPUR˯=-M9[v;0yq8R(aL1kYVU _I:Հ²)_G_˲.+WuA{㰭8$YPALTNwo[T~v)ul̝Ռc 50lF._B*0-fOoa8luHKvXB$Ou,1Ơ|[2B!`M0%ETh)l,,B) VJ!_H B4%T48,g+8T$b̹QF*|P1fio\SWVIE?ox)Bys*}x~  APL (y>\e$/'up8]\"!#aL=(p ;6_/}r%q۹8sE4{~Hޕ1ІA4 D \Ktbɸ+Bm 5je0BCPͰa-a_l[PF4@i( PQ2~uN\6Q>fCŒy!43.xfU7$9_J^񗏿33g`Oŷ\ǹ<#Of2#E}MGlxR OpcCroXlO8Lܰf0dt`*~&$Bnq6H|b}ϝ68v4`,ab"\.I].~HQ䃗Qy} ;4*s"*b֌z*th;S-,?/%=hefIE`fg=t18yTOS-$a?1{ 0.J#|Q P™)3%bIq۞nQz/~}-N֌`xabGєIi-3FXc:D#/]r숎q~¬:F]52èdt0N9^aj"l9Gw:O;[r1t:Yh N"G" 2J I)~˲0Ĭ3 q G"Pr0>#43I:lÌcaJU8Rc#f[;628Z*MƄ6LóʱS"/2N;!>Q,`"O02~kǞߝG_%T""!x|/:?UehoX$7mOn gtP'{RkS2ZW" lfθӦ @)Rƶ{^64e^[E}Öggxz3j2I3ohN=i.Tvlv?aWZ|D‹q }uct|-QXV T#"m UUu6m| CTcD?0mh#˞ـ[!"b,Μ)MUPZkZKГPW]N (r׀5OlcH! #E Gj6ѐ5\ii,bL\3vgnxaVlA \H թ8W.6͕8Nܼ kƐrl^0k*&98Hhe%1Oy*:S)7@QSȣe~{02q 9= >㮍ۅMRw9 Q̗A*H)PJilF|l:/|1njXadbARp3q@JFDl+biV<H:[nvm' #'\z`>8DGk-J^?'Au,cF ;Ew~_yzWeC^{TZ@11K ʇ1Q0_ʗo;5;cۛESe(= cIG-_B)Wr1s׬R%kbH FMNsOS;G!-_,oe |ufJ3yoq,}.z8WUB,)P_[Gup򉳡2>['L ?vcΗug”\ 5LFHB8v t=jg#ia!=x;06u涯} Usf+ԝqJ69,<;7q`KxXr7S=$mCHQH?xnJVTf;QT53a胈01R:hx ֮sOQyd칁 |j2MF>6S ! C&ItKȺA~tɄ95ؖ3ht0!ڴƬh]fbf<.]! 4Qon0\C͕L*@[]D9ڌoŖ>GvAѫ!"dbӳ.Z04dc|>͙y[؃@}k;_e b̂%D@ǵ7aVϫlCtUA]!D@M3` ae̠ҥl CccUiIW\T&bزkBU*FWx/ѐt cB|? |:cY|Ҽjg.`4LA',|>~}_1ޟM% O)cH2 YБ2c[ 3OKhjgDE DҒXr=vp5N@~e:R|8DFk젘PWJ@$rm:;ƶmchx$-ޟI%D| ZqƂp5#[oG R`8 ~:p Kahc5 X'@^mA踊{7.Yr\ "zG ț@ IR@BO1"W˖^Vz|ؕ1`c[9:k;s Q^@Gѱ{Z?t& DUcjVDi1.HyI."'~0!I۱zC3E4BXM-nZ\ZPp8A_x=$"F#v|xaMw>V ׏V߅v?@o8kwaflFaAIyoGG';dg}޽,Q(t(٠yf{m;X\وlƪuNӮX.Weef>Wۉx_4!檳z,-Ͱs!F0WDgRMvP/Ɣ YVIp$'*ʏ,5d$*ò,a2 }dr]3LBinj1)ikع!S1 TȒDL ֯7U֧1:uP]BJ24+ R3Hh$Bp?: ℀66[ YP :WîH8rTnY'!Q Ƹ`jT# ! \ c4t?ƕ$#03/O6q4B+Nǟ];Zfva#!8ϔC3TYf`Կ9ǘvjnǬ)cqK؄ٗz ~p){ 5^\BaZ<7OLK?[^ JtӀFI^.8yd p8l'T v3*3aVlvrWKfeGO_.Y_8 D]D;TS˧pa*9[z8 8ǽ|"Q(6 Jd/oy]]&b&hXKS%BÒc+ H$uPBӿl տH\JLS|T |@j34 h{+wRO4}Ȳ5MxFJDMt |T C Ժ  !S6-= Ui1Y uBzKuMԾ;9V܃O4A7-Rr`v4lځn 1zTDB,N  b1X®p9 ;lzfesODvFe"R nH<.$* QPH,Ciw餔 U&s Bhjϩa%uҲ4MN"5NӟÍv.~olvEPJit>Ɂ@$0.&wQ1IӟYiy8"CV<$cB2tC VࡗMzpц Re(!,9}P%%B@7-H&T4t%i2OZ" hV` 8"q] T;AAv;YV 5G떵&Y ]A%@İ"2=H[q:v~4)\US4, 4ME$i"ǹP.;i@ 5I27?I͂,1a 7ޖ 9c pICiI>_"q]裗 Vc}3!_ЦMdnT/@g,À?/3*:23d¥?{ਆ`0HB{لB൵nYAuy{W8q"K@(8aǎ=&SuSzE}`0HB_ joM˘B! $t0s1 @␖nyةSwH+c}_n!c Ӧa`L~.f0-  Һ掗Y AG!jZ"z*qSp~ܜ32 9Apgc5RPYpL΅|~?xf-=ɝ[6'p5e! ,?םbQUEuGir߼{{o^yQS?E7u/ j,>SfeSq 4˗{KM%9)nsk`P*8p8`\Inu=80ޙc]Mհ& R ^(eqT ι8m4cW?oNp:Mq~Tf%)1+9G8 Y>/fqBP: X*~{om 8$@ YϐLMF]7Ɔ奆 n?*r!)gV<pD#aKl^Er~[6g?޷8 M##BvY>(6 ^>0ơ&#;ѷ|5$R{|_j?ްCb0M0:uB$nddaWd4!@csgw}ٲtWn2Xp>9$IepJ%G/3J,o$0aZpxvdz\{P"봃sdR@X3/Y:,UO< -܇  ",NBM84 * \U=8{cݩo ? ip߅zb`!(8mN >)ABpNX2uޤJm`hdL:Ip$@!jIE'HyuX\C B.+%B!@hf#n(p,~aB3Bs.@ C@B*-"}t$iZHR=+ZvNfhшza"ܓ:qyzGi ~y4@87_$B 21nnO(dXl81 Y ##p5+-*- laƯ,fK" ^ ^ pxp˄]D2]7dJ)Xܲ0WM嵤CK8p$Ȅn`YV*{1cPQXM!/WeS &F\=DdsgK'nS~?ی|,qNpf:#ˑدhpء8UQaF*z |z'nnǫoDgg\p蚊H ~e򻒄Ttn/iW;Mt{: P)Z6Yj$u ISIl2#lᣦ$ LП0! ഓ?X(.*QU#DBh;Z$>֌p,ALEf$BglJͻM,+USΦx?ի0,(͸ oU3zzzWA?oMm$QbEq+k՟^Bs{7]Tx=oU8 Ҡ|ooFcwK’X {v{xk5XHEu֪|qk;_d@@LJXbQZukjgV٤J`]ͽ Kw$02.,P)x[[woUnfYLlݍ8:>܄H" X\J$E=o]}U4BsmQ"so4w`Ωx?ش NLPc6` 8^ (vVVM&y/Z4p\vu7F#4uLJoǚxر*`1 *<׹︦"BB<4Idk}=H6 6ٓvs3ZzQ씰vrȈVB ,\xR\8: C`S${w'o܅ ~ twmeՆ<٥wCM.aGظYP8l я=;u; K5J(nmk ō!xa$"B{8=pl2ZzUM"ϨF5$-[şJ$Wa6͜5]tJNdc&mݾ4ի-!:;;O5kֿҥA9޲xˮpI6f6oփ[Zz &h-=VK2>([[l}eOj])dVp}(-΂0*=ۃk5`M}w]Ql,"Canݔ%YDoՏ?~P~!WzꉨmQ"R,"*CWDWS)QԞn>~CCo~'ܿRdJ O$E]1 tn!kkk"{?K}$!C&'Q^ lGypRoWWVZ!`o#\ H[["q/H3I8 P(fNL l;64⑗ibn7=,~"_QAH%xqt_?hpdMDL @{W'(*Ȁe=M%rjZqc<)_QA?lP{a߷~ e@W6E~|}8="5anZ7aXDc˚Әo4p>+KtK፫-bOUaBLIP ;,K M"RK[ӈ0fLlE;61 *0<L ַ-%&Mi |?m+ tT6s!g( (IdJ@{]d:L=SZܭPgBj#cs((!d0L4F/ Jes ?ϝ=Q WՊ5W^UW$^qJS'OPYQ{y׮nzھx!"=BT曯 ōb\^SWi^qL=jv]7]Kŋ}xWZ󉝯QYz '{jyY6JS(Qzzwv]z/(p\Q_[kͧJ^F`jq^2R[3 #]"uo}4@oWVG+>2KPRwR nu2Rwkkk/ 1᧋͜?QW2=ީ/ ^ s%vɺONzA¯絨L;"Yysy~~^pr G_+V*!0$T|֍.n%G=Zi/|k [~ Cן+gߌ;)D{@i!dJdy^0\$ymmsXG s̠0\4BWNM7zY*X9>17j!l9&K$-n>*s $OeEF2١LhUcFa,c߬(TO,KH(^B tUCL SW}1iK`sA6BpeECG[`(;&T +BXLdžmMhjo8WĥxGO^7WT[ ʱodNb`RÁbn{j@0:*:aBl䟰-@ MfdqqNBӎcB&6,fcOģ D ~!@ƭ._x`XT=X%~ODK=L}_v׭!+YBO6{r;/}[%z$g 4ߓasnIs2ƾߟҊޛ>o֭\,TJSZSCOyD孒MFcOVn}=AABB!fa8NrĄLxye,8g)%HlOK;SƲaMq]7^t9zf <{%AeTk@+N)%;O-OtL !U?P-0C%ieO[m %tݵz/+Oոփ%fG9n}XB>nEU=T;Xx `>N9IxS-uR y/#փsY:U"3}}%{{8bN0@oŒ ܁0|y ټ%|>~s*uYM mh qVgfx<1CHfvo-WRe#PCqvٶ Y +|jL]M~St5y1$!>8Xdl \h^wHnzd_ݛn5i=Yl~5<ɩU  ;y2q#'=tk:nH=#?aqkT;j*Kt,îp2U[I FL*Q7+:g9T}+Ӎ!,W wO'$c$,8a.ԭB7 ?+wK: d;E_:\I[y|TNXA~AO+"B[o~.s$q| -NUy'm;+<ƞofP "T k34FPJH] hׯET:Swcϓg{>rG xɫԵqytJX&P(s=}d>!_g^ޘUIfe{*Ʈ6x&L57 ßP0n v3,By'XvC~J-,)v ? P{ݰ+pttET,T{Lrk{?Ge$<}?Q"Yv @lԨvw`%36г trA“Nuh*?u9l^(TmX= `f 74(77ſzu*~Wt,IP 㠙J0@RA(t*_7cHa"#$Q'`@+9mAi^,y8,P]H꽓ըG< 2 R+ZAlҸY`qr2ɟ!# OxB_: 2>uJ-IJfpXLÿ͆۽ NB>&-fa!@43a`ge)E L`XP'C߹2Yiip!@<.īX4"6FfA 2v {x`h԰}lG-`tXar̀ Ŷzu>j`9+I}MȲ , `@Z܇ ͅIJ%_; ΀Xģу]ajG[=jo>/@nRG ]wqB F庺zF AC TH?LAńi[и jINM5BA \"q3yN-FNx2;y5@H@q!'((] =saPXO"ٟ`aj)ъr7F*ٟ*APnӀ{an))62~~FBS76!RS?y)΀L`|? !7f>O\T*I v@<|; ߸IYV8!'!@FO%ư63'HGLG'Y&A4RkQLc~'|&U܇WdOwK5r 7{-26 I27kaj2bn`τ=c=SFOx{{TDb ;׃* ɩaL1B{u3=NHI!B4߲^;z:`Hxe$c2,օ/(ErK/;zoqmTW_Z)NE95ԥ:cRROA=KP5Vؼ\Z A1_X'L_ĥ!Ŧ KP;5cxغ"tM-Ji@uWe2. M3%&ڏOMr%;53'pBXCߊR:_J&TA_Qj" UcM/`X㝒Z4Yٻ T2Q^<ی;@ȵXXOUĕ3^h dO?r)L;3tVT F1S+!1Q GR=ׯ@F(nsRR&l'`tfe>?}G;T~7|hzγ/_d# }nTBr B b3;΁ġ' & NQ}M-b  l7~dlGsoﭭ],B_u78qH3P.Db&[; %5fΆ7"1 ݫ1B"}P0<4},SЯ|O?/"G/f5W4)o [eX.>\.Rگ:|nbw7tM bxў1^qXR{m]@js>ŲTY7.x\ Wj|["a:r |.xBBQUݖHGz| ٨o /SNO>>$_TOIZV;Kέn}l]w'NOjߙ?h9])wEFZE\_l]5|IG1!w^>^6)z\Ƭ.zkF?+"o#MˈuX9@53b;ZY8a=f~؟P_޴}}59P.vъdI~QOcz8lrbeQ34{LCPS9hIS =KǷ 0y&+GFǖ @FŸř9;kX⩕[ (?'y6;TX<Ϧ-7W:u6X2:4lDkX<}:C̘ 9IIUh-ò>t-}C ( AyCHe*&͇q8RI;>}1cNk1t~UU#!介s&e~sDu(.!M_T!y$Iݦ'O.?f{}yʲ,;l6jL{n1Ȋ"mj|_,~]q31eY6YY?3/L1kYm,LEQ<5%{?@ʯ%D ec"%)rݓg@08\ʭNmaʒ$鬼 ~Ljq9~q&qSeO {?!CkkAP,6Za00nu 0n̥, ew444X;Fc4F.A`ZlRQ__:l6K7L0 a=*tbNeVdЀ^VVRKXa0]74]ׅaL$;n[RpGCըF\ ^O&OrAT5x45CΟ@3l %Aat4kӯ>{v4Г"2n1(P8SY .8U$?tw=4 {_.כ:?EN]!R|yIp)@GFB3A C-,_q,LA) eLXR^٥ϒ/:8Tq[0-iksH5G4/35vkwu7&]DcQ&D/N"=mmF iiX>$e:JeDhV iFl٧epoxk펞a7U$ܫ+BD m0Ie5R@ʱKB*8O$uϞiSd~$3+ΟA9/jA۱cԜPm=K4A9:Ks@͒,ͫ0a租~ZGG x^[kƭ3z±?\X.촊ԜaGW,C}3Xb@S b1YIp4kY¼9vO,.[{GB8,RqcrP3g(X*p8AHB7#onXzc8KEǧ~:gI}̜lǙNMOJ`\5 W!0T $;X;.q ~qqLE@TqJ(2}VZJ5DLaeټ[]5i=/i_wQ>E :^ P(4"%>.~:<`՗E,V?ʳޟ~G;}ߟ0i̮ލ``)Dve8i2+OTqyEOqimf֑ ٿiu髗=0.i:VanjSnGL yrń$24pmA`Od5=4d猭ν1>07L{6|ĸk)CWtdinZ Ǐ)PVP fbOGN IMnjPU9;4Ú`5X 7~UL ?uD(!%RŘ,,.H]h')'8\=*&ǜ?:K)%. e9x"Q'v;]aZ&?gWUu#h`3Q dUrW1?IgA*Bˑ?3I~DB;G"eB!{xٕVw\kG:{2}3 md?<@W)\+GAE)kiH-C}t6?o5Yt9=u/tЮYjt=T;'#g>e֮6RnQXH>Bܸʴ95myJTRDŸ(/U=u N8cꉠ{LIŰ, W I+qE857q['j?D?ĉх8c  bzyVfHmmma$N 쥖ҍFΟByt"N"55kjpP> ~5 ~j`WK7 ` -m}F[g?L/,vㅇ*+#2nɞ TM̅x%{>VdYp!wX0)n qc{ J%C0- 4uD`<|&x~2Iv@&>Xlo `Ra(`n߮: 84Q}^4?bَ\9L%LV9g6Es(N H# ̆1D#L;l"73m 5MG*3?|pOW8`f!J$Yb(t6YlhhA"CL2QQF\KjhX6"G d;_LAA_\oՏ )I2D~n z$Kdyp].54jh wu!Ɂ p8<.4vFYJ 9^$_uڢ]s,ig Ψ BX!detLy-}*ʰˇ#sPdq K=8>a1,#v/@@@Sbw:2F]*] $)"c5L}{|NH77zQ1RK % =v/"`|P{NM&bIIbNjmyDx2w>G[:a??jz]!rU&2h.yd 2g/$oN<7ӯ&ЉKHhI abF[FBgXo f쏿 q!4䓋p֬)8h #i9s"j`"iafPJը3_)ycM(E?$G;Q="*A0qLE5'NO݀. nӦX-Gn@³Fu7lEFěyN\?btt0: D϶Te ݮ\{s;QqD'or^OΘj3p01@FEc4Lr@p4?3ϗ.>2Y9qW7.O;(#e+qpyZDۖKC%Z$jB&KPd  qx\eq \ysJ[T_,zm i'\. X,ObnBkV|zniYyT aC@peBۣa Hm\}@EPx].ܿ&fB9w4w F!c6ljFt[3Z@`Y P o3LtjT߁%Dp'p[k!J8lWwL:ȉطWý|9 >=ě˜jѵti*o>|~eu['7"~Sbl7lw w>L}bB`QIclGH֐wH)B&rϤKM`κ?2L b4 lFDR -W~ JK;&6šu;ٽ᭑z&DTT>5)3k3mf7ޏ ŵ7:3f>R|'NYw-곇>ؾM3c뷵x,(P !2|.dex@@ڍ-Me 18\nܿ;=+-]tԄ!`o#\ H[mI|l}[  p 'E~;%\ny'}%9󽳑Zl$mౖpqFAQ3 #}hhx?Q_NV⼯G5W0$NnҶxE oV?wx.zGp)g77?Xј| > (GW2hnX[bξ"GӪ'n#dTX`ϑ3˦h>ٴK$47Oë,;]6O.E6Z'jRqj}x7.;̲CZJNe;Z#. Dxi8~$T/Mhj'`1 n!0$TN;qJʍX[K൨iŝ[c5EeU3xSr'*slpHmI|(h{BdJdy.9o/ ٟdh2f,ʅ 0v! ?HPI-EJZa9Q}S˖-MN7[76uSbA-)H9YB/K&4#YBww7 <2>۩ɝq"K, =Ҿ;ey:Uأ;hOL#D)T@ LSnڥ^"?|tK\%TeB`>*$>U.uAl6BZDF|)dAc?mQMB2ǩJЩQ(d,K0_i݆S" (48A²FT*2\v? ֋ߧvcw6av7@]leVlz!"T@@$ Ώ(Q:ԣ^l_qsOͭnH@TX+wwt#@mTGT *Q5 ?r@-h;gN80ƙzޢVhAOTC[cb( + 륰hh})p dT: !bT@%˱XnY?\zYSi=$CG̚uի꫇_lR$I؞$|?̜9i2%Ȋh4pП#G!+ʛh!EIQD[Pw9׌?$F$ȸz֬9]z98;T !$JH:4IffYs=\ "DD$(H$~3dedX={W?>D(Pl%h1\3{ߌ?RlG"z2α"'#{(S!j օxd,yT#@//G(-/W0DNVHgw PDI2鄉=0ⓐ=Y(T.E~;_V !B8>80 3~r>XBLNLzt |o@`$+ѿEtm~a0K٥w@EV ŪUh:#i> &&߄&T"O\ qBC?Xg&grRK+77W 2{!Yr}MC(Ҥ'j=: 0f@WZPGo|]K|!ܤ~2(8 Rj݂Lſ|]'[MS3{Ç_!jXKowW7J4a#Z?Ri՟}ʷG0<;^u(>Ig>Ē%WKC] tpuw0_ZB[[1drTz?+ze)vTHht͚/΋Gc>߬ *C=4CX*vAjժzzMhgRM>BH%8 h`*e tϷH$h9OT 4HЛ 5k֤ޑ|hYU0 "̲To U$"~0t\ b ' 7-U>^,猃3.H MF L /\'{{n.ɑdϹ0yR8y| Ѕ%GDK"wri?Q}g xb:s 8j׆ k>j ɚk܌Q iAn(\L73g~W׭[8 dS$a9877W VN6Fڵtɜ`D`p{RC!ޭ"jXBZ?m36It3;߸n݊6YO!h3sEt3_ƍ_|8Is dV^+Q g\ںu.݇;k0'""Hm[+p{W̏?@`Z^-zP(ďѹuÆ sX2>0F";1#Q| $k ǟN27/l ҟNo7?T$,KTp6HT%H? Ba'.J975lZ,Bd*6P䳯 )IɎ7mme-%Q` a &S g`|A8 %{dM-mjT#`0Hټ˞>.iRj3 R{~TI>P[XJ`ۑ_?2e'%Zڴ䆻PyxBt9O8擈}`<+?Io3w>߯9o|A"%77tKZ(?!n^x0dEc+lA?U\e@4[#g.'|7|-]lNwQjZbij2[ ^cC!^VknJŵ<=봎1ױhe1k#4VnD,r5R'r{o&34YqfHV?^j*OonF0H7s^>LӸɈ1/R?cq5B~9+@0u,mY|_C<|2D-&Lj k;ӿĆ}}(_dAOH@c}ʟHP|(X %!&h-xg_N |zBVV?K[OI~ş=u71$co\yIs??9Td7lҷ|v(**.,,]<fgUMw\U`~ 0I߉?|cǖ++(NwRiv3&zBՄY[[;-0233+'=dHEz7/.G-Kv99gΜpI͑8Y4{B)S*F*PQqjyqWyG);k1<vDɹY/; x'≷'"x5f|ۍըo`4?g32R4h"RwW[[GZ(^5q~>Jhaj<qk`CB[0ғf$|sGÅ59sf)Y~C1nx΁wu%C!ϙP|Nf ~BhnZ4\ܳ}(>n\Y2UUd2fkZY{Ϝʋ2%*&4Gɕ>SIƣ!":i) O4r_/4[U5H$V9]N4n ^0'BGZ{\Iq2@4I{[>3bHE]f%PUM+}j?_^zF3wrY}T9IUDb% OVCoZƏO M$rYlaH$5W5a1cq1Ns23{ʮgW{77/8JL&N.V$PcʚL,{z\G? AMME;|Mu0@CCh#SH`lX|B CUA..B%If6@Φ!O[kw7WdnwD)pN@lAlNH?|m㲜|/~Dlqiyn7W!Q @lN?~ciI^QjrEV$Ӵ~y$R ,ۺCBR㶟]Laƕ Jd4ݔ'B%ͅx3o֟ab xg"3P첏{]NIɟZWuKDBn%[BࠫϻvSq^u9J Kؼk!`喣wLqm=v~gd.SYM/brJ x86~r('[f$6WdxaKDIpX,~B9mm"ud&WXROERIx#7YP3<0+6Bws\)vva;Mimm݈~P Q!@IN1fcQ;+NXmT! Z~dٲ0|0Bί liwm(. Z;v# Eɸ= |Xx#xUTt ɰk{mw\\A& d2s#qHJozG'ν,}ZeY7`c^VFVBӭhRl۽YG7440 !~yMb̆2Wv| [ Q٭iǭ_ߕ x@sw➒@d7jWvr]onn(RBoHozuWɚ¢Ǹݯln mMxQ; ?%cm()΋5IW?hC׀v̊hoMOvz!{ф:}eU]1q*\aŏԚ*+<پ ٪fwo^%muuu%R k۹V.wtS9$;oc>€yK΄7!kdR7QuyY=U=obyn}ddTA46 5e?<>ȍ+;>p.&A 2q n>j; Lk^_[ \F^%K!r+` _69>eE9'^~t/?(Pɛ 3 ߺmX|. ℙ7eeCaZdEKNY!/jB^;JR\wϯ޾W)-'4-$˖_b?y͚xi #b/?1?  ҅XFC\'O,{ !E~b~z 5<EX㷧<~x H0e54n>kε~`6է;op旃Iveg+Ӕ\'nFT9Uˉ3#+7~Ydߔ;G<`c.k+%A/\טxJ/}ͩ=`xT~Q,Bڅs~RiҭM~Tcğ#{eOmXyw-?[x! jDl>-iM/~ٳƓ +ʴ|hZmmlڱui-=Cc'kVpǼ)'4ui@Ukے޺C߯?H'/0yg֮|M/}=}-}/lhLVIhu?& w8|sPwӞo{ y-<j*sϲl~oXfm|נWӰPB&y;kيFS-o~%!I-+]h?qf0MM@MgMڴpϠ?ln^WQӻ?i|vw֟^λ;[_zR07o{ǘ򎦿4t2lSkO}r`Nwgg_} qi%Cf~͓H~1%shsvxGW$ah++_?i 㦞4!D`ٲCW#JK9})te2=H3s2/'MjVU)X[4ŋKuϾrg]N> Y2+{qpa͡OȢIAr{Z+vP{wߘp-)s_ba͡k7ŋכ|`iIO_Rb 5Aȑ7%v͵WpJGe)WJn*JdBxVw7쫸rtQA% L=y 0OB! :W]޾kg̼$+#cJ8n7;.\w@j'JfA/oKY΅L =8щJ @jO&_S#?|ɼA@r ]V[Y"9u-q?ZXk ¯y&"("az3Sl Nl(}x6?7ѱe^@V?X W}MWR +& os\9MrN6$Irla5apS-@<\K:zW\?p8&?__W~Gpr" G~w1;]{z?΅d,,}KS)"Waz`5:z[st9( FdYMnqWL8?7 ,x~C?=++`YnyqQЂ)U I)DXWUM;~ŅGo uu~KmrWXc{|YkpqB%Ӗni̓wB f p^rط>t1^9o7DB^"2 4֞>uVSw7EYz[B פgϞzzq*22uul5u;\"fwq"wwwr33N 7f]O**_aL>Qd۽V:)U^Q3Cןhğ|ٛk$ 7},"Or۹w"],89wB_,x [7WxYi(D_~B\٥lLBy,ikh\4rs^~!p`~`0l>o;/?("n| _Q49l֖]6na~޳7_|]]=?Hk?um~p3fã|O]_dWZ{vǯp%GgM7_|TBϟxC'~Kr,1QxYSKv꬀撚9gKM((j=\ǻ6O/a aSIAg=a6kϐs{кQ+!Cs;3\WOhtkGR?4 ;zrQWX<5 x-KxP,D?D$evl?qlu=Yӻ>\~#R*)&Z:^ƗNNܺŋ%RՅ/9* 8 33.`<#0ݶ񡌢.6);+XӧU]uϩChZ+eN匸2+O_0Xtmc׫O%Ųp: _UV/?r\ͅ=u|CB0bY571-jO[I2D\RBrvT|5q'+̸K]ȷwJLB. fOq뷞<22T!9z_]qUW|܉cKо|Ċ\p\}0OVԬ Ȗ)s.3Vm97ŗ3mGHr Kƅ33Ů~xrUղMo3!N `kbxyKda2՟e6צiay=SͬnRw賕/M:.(i@œ[N`E==sZЯRB$KIquU {c_1w2@c1Uӷm=mbu|QOݟ}qmtC?!f ~Dom+[{=} HXRGǝ=$螺m|ôhbYEcv;l\'5kbo8k+?)?H"MΟ_1n{r%BĮsw E <54^o :ߺ8nm-?Kr)~SVwe Y& L(E?fڿtNjk37^Gt[N]!E̒lb~H!Tip?E|֟]w Mn=&˱m1bAC\<SU,]$q o - +g>zQ%Bz޿_] eX?ׇ9!?rǯ! )e?cN?&{Uc=L @ 3cXK g7 $ӘuA$Eg~R,%zG3>x7'B\e&/qg=P[ʇѿYͷGeǞLʹnk+Ϛ9l3#|=jWĒ{>{K k؃F-&1qXcbb=o[eX`BG`w,,cvE{yμ3ϙ{wyu[Pe[6YwA읊mCp /Fn: {+~K |uo W.{?5{ܸja?]cZov7A _}QF@ @P  S}5XE3΄+;rw\SqEP ZQQP}T_Uͪ/~!X^vWYعDzD=IM-#sk,^gwKgM`v墝M{xS˗Ǿz$TTU, P]Ϫ/6frOwXwE6n<~Æ @@'PY]*&ԃUWL?fK# bruR02x|ONAuu5+ TF#HNB*f=rͦ>}sՒy[J6e~e56lبw]gGx5yjٮ+m7lYUtNoV7@ @Gٳ%J=^t#517*R6|x^-8$^-QTܝ{װ'J6e}]#mci@dD}+k#K԰[+z_p^[dMhVlUTTHO׋YCǿ=/U]1EBKg5***hUM S_|KNB0UqX~^sބN%Id~mz9^3(I$Q+Z;WTTH'=a?}dG5Z؂»B>^?3^4"fRܜZQQ!nv\r%iO+Π,QY2"Vvzz҉nGǿK<8D&YXX,䤨EJ~=OmmhR"58@BqF:!v]!5!,22ʕΩxqς^r%)e6 J;D)LH0R]=5oي7{0E;^oQuucӤl䚚on/;~=abRpO!y|>_Auuuk '_p%>$) `Ou]v:eյG{1&,`tws0NsHuuoïUAMtMs }o${?ͿzBLrO'mf9NoQuuAbsX~!&)E~͛(9 @i9L,@(&0&H2%+EI!@r2b5oCetumF"^әf6+7o]8%K[b azӻ#)/H˛ l6p8H$87$''0;nfd9 {7hC:mP:bT:Jt:XW`̙dYt:lnףȣ7q.?GSQTjnK/FQW_}=tYV%rg+wX5U=*ɿt*H$յ__URRb9vVٳ4jm6Zbk"GwʳfjZ_6":#RsN@7LR$ uvvo Ϝ9kbw:g83vgWQ~Ίmu9oo =^NT3[NpW{{ܷzksIIr\ y)uyvۦdb#Tw_{ď\_J.%NŴz3fneypbidћ4Xk~%9z^k}z}3wY!.sr rW-tG5Apc74M?hXrnNlޙ6e; UmٽPf}moo?me~f0ӊ2Б۠cE㱰3\Av2@(8=s8e{Ⱦt6BUyqXtKM@4s-s80X]]j/_M$?"#SJ} v̿<-cI_TKE%\ꫯ?1zI(9vjÝP|?_Qp:K$" }__|7B~ą_`;oxz8{@ ?9}y.D"orKMMM"&G$B P̖Ĺv}?@ PQQq>-iݕo>>F.OLVi#0=z玳;~d~h4qOy*OPL-޼!Yu%i_+?\xᅳDwww/z>&'$d\`] 8S&/b>#===˗/ǟ0abJͽ%B3LB71&E1˯Bh$w~kUqBsjE^!wqFV9T]BV,]/ 6 <`w6 !}M6ggL~,sw%O I Ɯwc:+]}$jn_^xb/K֭[*WPC'eS*zm}B5w^~0>Y~K^@EEIr>4}$^D>`O>hbӼnfm:'g}/|~/'ǥ[~ zT_@ELP4\~tf_~p֯_7Z8  -?ڎ@ɟq^ 4׹kZLС[^~WgڵHqQș"9,+]k Om6'_8QlɌٱ( oWgR$y+㕚lX?t:Sۼзto]hehsd hk_wpYnr~-oB_պhEÏ$DYcuM?lRk0Z=!REz6=tS6szS[e˖=z?󻻓lݺaa hѧ_ƍ}@"+JRr:@вeg;A?xk۶M9cuж2O- iH+ ,ߪ?_]]#pxm]{9 }+>$㗙Ȑe*%kʠsƶG)Gc46vﭯo4Q _X,+q:@[˖-_/߱csX=3ίOo~ fq`Ie" ]x`3&n8FF'A4go> ܾ-Uc_=FP0P@ ˟}z /}@YR:✇+;7"}*yː.ŗ6W !HE/o&_Arz_zÔ8]ůC+^/L+d,/XQg=u{;_g=QZHr꯳eg>Q~͋8Ћ^}\ Oi2ß9׿]搁_@FiO;^]7<)ŧf_F7vO__4.wތW~͋ϔHQyzO2ru|)WGɤk5zloF*.dA3?;?ok^ً_ py@/xҟg_Fғ@oclp>D>x&H{15#xK?q}Lk֗aEϜyՋϼ_'-k4}ddp}}ÎSXǨOL'\oJW,%g982܇ mx,}s_veߥߵ?c.㈓Mܘ G߿uca}wO3O,-|ɦuEq',:X"p.bEy_k=ɻr5\hH4]x}SeM(0?S5>xu7ޢi@Dd?ʅJ}iM'~x-@gZYCuiSJ)WLjX6 2!KjJ][_RPkbJoJlAg=>|X.>OR{q+.eR貲uohN{}?'n!@W[^|`o=M[-ȑoOO"_|ynϷTNUs&^8iԊ ǏkF x"O$o1|YG>p1ڿr⢠]$חHeC0vlmYi銢vB'6X! ,]ZQAf`ܕ[Cۚ_M,^Q{iFsdrbo1W"bh\ :n| l-l}f|+0i!JJ'T3zݳ]5~U7E\&"P>'ծ^;K]_ o?uwqfz l$幼vCÝfyݢ\cdO}sqz!$m|ɡ\/dzg0d̦2FgI7_\⶿$mc~q=3PKMP?0X ßHbԄ9WVWyݎoeCOtv޽{PatFVPSxøQvHʫT GYBȉ( UU|^ے#㮔k g-p7)iD܂c519gNk_ݾHrp;0BkADbEYIg9zj ]QY~z\B+NgG4*~"-lD"(yӆ3'ѳӽlXN\ӹi7󇒪*>p9YsT0W[ɣ1{r|Ff0ݢ %?ϛcm-m%G߳olYtџ4:>޺r쵯a}aE+[WFiꘚqihy++*]?|Kw{љ3GmwN}:ZV7?;n5t'#ttYp{S%xUԉ꘳2 OU(uu egMJsRL̪gѤsTPwl@2 dJm!b1eLr\?tɓ`?0~_%TJT)-ɖR\Ӭ=Zop?#FԟV)3HLFd:$|zMN%=^m|ۭR8#n]G>^߃P_1pޟ"6U.. d8JWu9555c>xڳ\+*JiN,iO1Csfiӆ+(xGN{f;+s i=ధl2F2>i/-Yy]şnWfsP")sKI#GWOO8ln~ʄ"cUFZ:sjjjGzwo[O00Rb ʩ1z뷯@k]o~ 1HFt(eI8cixD%?*"~(]k$A<9.LcźxAzб!9:։QA;xݳA"Qޢ{z?J@u ԰C3SQuj"V+m%Hjp?Ŏ')6QfRYɎw ԰?V }*5DŽ%Z$ae?k$E1K̕_>thaSC ]@VH{{D < ?tl2++81?Ԑ &hz#W̜dI^~9 a0A:{BRA)c&9mVYQKsV̮B9I;bqbc1:kX{{{/p-7Yv3y}!@? !ȍg=o\jGGG'JOP.Nina͚CyF B#mmppTOZ^n5k }/O,J;BQO]_;/O>|B̮ .DpG(8s[G/naڵCz _ˏvmhAs\K~-ܰvڡO◗SN5eG^- 'pLbRuu5B.[;\e3fS7%jy > yft*(MN3gziɴ'\}j\ U[ض[ 6gkQ]0 TU%nJx Q?"}h[x^ ZτY7<p!?ja?h790$?#}l8'F 7< !䛚dSoǨ\oظ(~l]/wm@p;]tf~mAh&32=B[4a&ցp!6gyE?2_ʫ/ K0Pt~~W_}v%Ulmp?d@\"TZ;7г4_hyH1Q[iV|䡇e)Eώ͗MGwDgvrW!eDGyrzgsF)|!4vB|*Db(;c@  3cD7{VAj%1th "Ց@O[n)Y{! /.Id`L96M]MPXuGY7ԠNTGV"HU55,x7/&EH}BtDx YȚhBʥHiqdOC"F3/oZhoO_SӇI6ut|$ ]~ۿ]?~r-550x9s_xR [xB{ tG}'ާƏWz+*8mH*X ( ;Т]}jxl !H  =? [讙ҋ%*|q0y^h뛭{\а3>9'Q|]f_"d Tw"5DZ7v4ҙr/rv̜4@>`cnj"̓?0-h hJ:ɧ8}| ;YBRuzI6Y@4s6|`++e;vhܑڏ3ZQ9ϏE,TY jB(N W9y?9Eca lh^WBT*A D X]W=8{ OsG^f֒k5nj}  EacLDSf{>izm}Q-fR+լ#xcmB%u"0p~ Kjj_n`Jń:ğqAfCm7 ZUS\4iE5ed׮y8(ڌvP4+.~|Ԁ]0iԔ9f־  Ԏv6"ljI]ٳ*w_s0 e]&X덧+9m_jKXf:#zȪz  TQBBwr==snezBo?A T_mDrUR"%#3<&+TpAP`ӏkHHwK$N9=$Igv5t{oMX`^w1pl.%3oS&B5%>1>VSr:n1ez^VAo#_ ܟd!Qi4?~"b \Y~fsm֫:ƍgC읷{DP{N!+Wdoۘu5Z~556n=;8$~5556o=wy NSZ93Y#[L)VaW ! RzS#'3EF+BΜGT@oLrǸ@B?ӆO3}RIІggI<ӟŭ?MUغ*M_uܻ ߊP:Q}ex2%ny.I=;ω{QܝA!9:t7v P̩2vms՚utٽU5F VU=4窽?ܕNU55F zkt5iCWG]iߞ_SJIxތr˵4"+Vbh}[Wx^ߖTV^c{PO!Pe fY.>I6Ͽ’ʓ̟cjǷ N~sPy[p ?Hei}̙cp-<=k% }˷?3Y ,u-S{yqnq_煍{SG- o9憾*3_OȄ6KVeKSG(/ZH77O}92 vo~~%oh5uԧ8!*%ÞZ{VEW fUZ:o4tJU$\j_ X3@*^kf򲟊U9{+1ΒO>UL~AYajTUE8dM5xZTɪ~p _@DЋ!摧n~"& *UUaD,dZ7M}G5x(,/~FS".첩`[]dx+ <ggj. FO+ Cf])vYe`dA, =| o*1rjdD1oxѐ?oW.n),B]^wuּup-H\g[ESꮍms],Sj֫3M$.a?9pG*]/Pޒ"d$.4.W֦vjgo^]eq"&E3wEF jPߤ~,t$OHS -p ]&;NQ`'0YR%.]*{:uj?yHOIUXZQ!`VMSzB~d!VTHi:Sf8*QQQ!X=]? ߒOL}BBda J)4M^?$7Q;Sb7*i{nN*_8١mG'˗ ۿ&O?|ƶ~̞}B}K>!*tuw+Dm2I 00 ֦YtLb2BQ"kZV̈3bTy$f78_[ Ia,aHb?vM;Q}mikW𾎪cA H A|\W?v & aWQwd"B0(ojABDͯ.΍^|v0u&;N_$p]5?wӸ&Xp+|Dd 6~rNy#r7LNƇ`?7/Ź/k' #A 6k6Z$bN$l6Gu "0Ǽiڼ;VoID,*Z ~a@y3/d*٣2E9i! jॾ%K@oWUazP' KwxBA@ wPDˤ*W: 89Kҁ3~/:P=Q&:]:?qĀT֮ Q9or\碋 ,~!@$۽{* B |AX*AҥR'K+wɯ8|RN*v'ȢH K'AwTN[H,vc~}X #"CSxB#IgOBtt$ +緼zh"Z$ׯA Hsr"n9L,@y5$8,*Y U> h:?K$qXgL%ƴiDO>?b%$XZBa!8!~G[!ij!٘ZD̜||B #o>p8`X_~!/lx#B*!UTV2RQYYͪK~ww_~BuE*MMq.B!RD롔܉6cG=?:Li"'vuÔGIH,A Dt Ym!DtlĄ'10~noj2/r}dلaU7?>ArmW} od*5pfίΣW30 +hSm,uoWnIaQb>JojP'UJ2&pzx,I<3 P`?x[J/cTcVȮ$CȜ?駍߂?KL|Hx8)cHBM?m'po6B*\ߎ;o>e;1iqH#!nf~uB.Zr+++ߺ\.b2R'`Aպ+p9iFpff.vZ4ofWR9>UʊF]ZPY SP_jP**Wzh 7/4ljxZw$b{#%юCѮ5Ț3KD+/s`N"w:$Jt ߄1 +KKO_wY)#j ߵb)ĉxewnRj.mLEmV NuDl8Í73&RTF!$ЈƪSs`H(0_Xe!$:},IdIJ j|`|4hp\yY_8:gv}K]Cގ UoL?X -^w7~Rl"1W!ym] MktJfwuW^8ꫯNb…EN$9 n8 G=񽬵6!@l ްmx*u窆AfϮ!z깈A3V\)n喇o"No+ wqK.5o7555 \>@i3Jr=Fn{Ĩ񗍢bQo-HOZ7=r(1skWRާ߻qtt䏷ۑb-nBxOc\{/axu_[_F G闟fX|3ںd@:ҞK3+v?|{Ϥȁt ?5],_{?>x1$uҲ$hWߍx޼yx㍱SvM4o$y)=!SL9窫w>vح~>{Ғ&4tĺ@ ` $1ǘi_l[߿ɗ/tqեJ> Z+Ι?#7ˍpYƽ.v$wX]G7Ƹwϡ*ט_ێߔ{j7m#'5jxǍ7wڴig9s|I#f͚uᩧ~_ \~̿cyw]~v ٢^~QϹkc>x_* 8nR83q8h~^1M@2B<92c愡CM.ݒg^xz"&@JKOb?WM _Q"k,dR jќдH8BBJ̒$>)br꡵5e2gjB ?3UVn$TɲSmRL\tYYMg ׯ'im_^L&8W5]oNh&| Ti#wMm_^ U#Y 9j5H=D??~?{D,dBq֬z8's%BLpJ}Vu㿙ؽ򵑲5M^HXBF"e\N:d|kU]&Bf8c1UUFceҬ)z{x/[Ueգ} \TMjVs̟O7j㿝UHYdao'w$j$l2',дhl:ɽ7Se#rKH2~MUeҌ+h}k5 Xn\6OK&OǪyuA±R4u" 2SH8W/I[zp"!/BD%l_ϣy\h+U[ǻ 2\nȞOJ lb`ŝ]"X# bA9oqj7{?Xh@qw B9+6 j\yK5i8h'Z)¼yW ~XpVƮ#oەk]iǎ oUhGA=,/2W'݂ێnޫ2E: .7G !M{tj]Tl%wcb |_=\z .7~8!1ViZq$"_}Ѝ b &d}|E>/SZ$ 6ZKe^H9v,>VV}y ۦz~(>&;>}]r7p-w:9Wѭk~Qy}sqs/]sS^L 8hUM셋쬡wP:DTdJ]?K}sц^t6sbDPucL\.-?t n?Kݕ hoio13"qY")/NMD1159`avT1uH)]_ms9D0MU%0a0bD4 @6l(;~PdbױKtHui-.3Bp … \8dHcS07?޶%b~V7i?3 6]09"ػ#۱jbΨ n@N`0ٽC1ʧ|8Nb~Nwyu]ZtGlv (/8p.(0 jL9{}=mm1 4|5cÊyNGN9BsN!ÍMC i]ڡ+maQΓ1BpSaƴYsk?AT'˖$#I=c^` =$?lz+&p Bf !h㻨ݲ1Ka gUN蝎%qM]hݚ)&5s Gg@aUHr Бc ~r̙e: EI֖L]5SV0t !yr!;HO AO0 Y"Q6vlQң$3HaP pfsPAȒdHVO)VpXw2~6E6qޛ8gGZdX-2RzN(6`b_6TI)2ew?[>b2[ D?æh<J'(//סMO" C1f`@$BEƟ'_@lJKY ND4&HBЍOqfFhɰRnՇEŖ27Vٞ}[*U\H4FTUn`1uPӲ2HMױ)o̪`\F0Cgzd9b̀E3Fi\wWݗJBBUՉ30/vq0ǡrw~.ȳqHϮ^(5 bU7n|%T\n}|oT誅㋟Fo 0iQax|P:Г`P]rv='Sňէ.oQV$XM2&4p.`1+j/[Mk?ɯiCet~elz׭ÊDդO"Ln[AQ/$PܖB78apc -W&@)iF45Tߝ@ZAJ1aA"x<%Lha #oǯR|ghػRѴoWv",dKl+@ ! s0CFiQx(z !Gkj;@ ٩OXAa/DB0 D *RpicqR6oBˁ ]y)v`nM܇s}8r}`{E"I""j8Պ ƥan? T-{XSo\^y$"Au* .bLn:ظq#oM'*$XC]!&cXp$(epz#wjBlkRm =3C.=v=uyBX Ɣ!Ŕ,ԌsȔaİt47mT[c5/fK׶< [S!Kf9J$ج~vmLK~}DQZdp"ShkEKU5~UNu -}UݵyPHD ݥP|e'4:o^P9Msm<\O BqzSўͲ//^^Sg6C$*Q0yCV:B8Z)(?;У2Ydj^um\W$I B^v:FYB"$Iػ /qbNtu)X\ LpXF_#9y'#p:غ+?CӠHAT ~m]* .Dעp:3 p:w3 As8xp .D<.8ARAL|R E[g0qv¦D9i]`Lp"%d9~ <"mb$P ӞDUMQFOaTtuwTQ$T~ 3T-AOS5l;Ђ;Ř,tuu %?>$* D^ZxX!*/NRj6&J ($=Q}Li4?ӋxwzpzKy ^i C[GmY D/A@\G:b6عvz@ǻkؽ]4Z+hGןXBS\DzԬށ 0GO(5;њ~>CQUhKLz˄Pv?ۂ϶Y  ^Vn݉U`Os@.8>߃A]c3tôI7!9 wrPcmÿ7<ᐋ)rE"S^sI=6 ܺaT] &`Gچݻ;pE g%"aZ)11&rAbr;*_6ۅ Av1~ ~v>X]CcvP#VʡE4d O}|a184f<} C:݂.`B E}W# [|/ ,@fY<9తjOMԌ0M@@8O|oCGÔ)㐝a*3) R"!h ‰k>{ +CSǽBBҗ|`V & a@/un2.-_ $F$a|( U nd@>ʌ1x q˕a!@t\ @wTAG٤,s K&N)FFP" tEן ljPMMm[M,g}7 CNSr|(~A3tC 06,b8f@ן)C8}<&݄,.`HK~%I”SJ`WuCQPY$I+iӦʣ=. k7x"U|Y~dJP>B0$PŨ>1 M2E3  -,?2<$#`˽ˏg@; $NSYǡ9OzO=O]tW.m'h:$c^>w*^vy//oEׯ_~\hh)6 ;ߟnEC <2%Nf+JERx)zipXmv';Bx ,RY˿w?ֶNPt`'ç{K![09Мpa=A7!+?ތ^: 0X\ 'G'{8n7]rVA($I!Fn9PVƏPu?NO-(+5j8l#UA)ɪ{Sc r0Cbkx_PPÁԬl8K/"A%H@3VDT N &3.$S=JI/Ha@fiHhvsL,I%^o}m{_R5uxL8~RkYp8,xP)Kӈ7IG~c"o^d̀ՓE: |y "D!,+l>98"S"=^~B23RII bt&EBvNh!DL[".*h?|b2356ӑ/3мS;!` q &z%{!#[Y`+ۡS"+/ )CkBuHR(.&$uJZ>?`e1A%׮ӋNmJ_={/]q<~붲SӳS"U=nj'WC7t~9}KwwFէ[LO*˗r@Q@:zBrpƎK(cdChB.h 9 `G(%)wouDL8Hali>eïй Qptt  {0 H(:B{p 9٩H?5 M+=)B$cFT3Ó> $=c DڡP\CӐCvj9{q;10Ѹ EDvaT)1(H0QJ"cA̩޽m`e7$ՊfF ĭn_JtBqL~LilDO UE׃Nعw/⺁TOhP۝8O$O(¥}1wh8QMe9 )NoԮ0C%㌱AL-2Q6/9{n>iQ|H{"ttpM#!JA;:avg:ӃCA3,䊅aUDM&8J@j5P$Jpl?H޳2 cG#M%AP']-*7.u s8i^G<'K2fDy7B]X(KE, B`xINqZgX"%Υ.VT'[SU鶐SеsB]¬H(ᔡ>L)̅fezRwC.[i<"͝hnnfE^q 2.'䁺SD<~P Jħvv3w1sDIIԳLnYm ~,8Puu`|}()zvFG$sXpͻ_鮣2J@.q^hq8 \ LK& [EYm gL lP*t%vكDZ1+œ` vgX|:R2 UeX AUq0a ;5|; ՖLCO |{JF:};J! baa pk44G ic-.b"qsŽV.jhNBKQn^Yo6' %UHViUʘ-&GY(FԜ9!NFPUwvX:t,)Nami,E"1 1٧e, rADBձ-bXa opn5fFIcZJ38iAtUW@ @;,iK3ܹ3lK2Ρ:Oq.[?$ @s=/i?&Db1ތЈS%šJ u4fӍN叀?4$!PjnPM411ɆJDG6F#"atM2d+WQU͜OP  C7@ v!pK PN`3{bQ7T…hsB8aر9EC[R It-AB% bsDŽI'DUŗ2|DB 1dy&03vDQ8d AtRD)?DT02Æ% +h5>a]` 1#F(ں{9!@qyDgGMÂh Qpcws.>ZAJH a(6[, d~u&xT6ɩ "QS2ITTf,:"d$J a(JnxQmIS4ˠ~ͭlذ C]2H$~׈-CG5CJDeĦ0$B !q3c۞fd Aސ2TH S_8H5SYˏ'm#g5%,6> ̂-1 )ETpuP965$s&nbGRJ@~0Y~F Yh(e됀"ԠN 6M׊S_w;:m?GgOo’m:tS>T~ɧzKKWͮ͸S+pM^C]]Fƿ>?{%L^Q9="n={҈⎎IGzI`R¸bf@AskxrNp;ɗ5}|nĭNUuP#! Eq% P*ilcɉf_j頜|C4ka))60ރP  N9 =<ģqDSp?"X0ZrY[G,܅096ҤR&8҃ -ٓ! J K.ayGe}>08搥<l2Z BFA145mq$UX|i@pTڰi@o3kcRqfp0D"a*:F!@fOZDOyJyD n+\Z5K qYHHe}Ϛ]k6g*{\|T:auO |8{82δ|B="]QEm&*WcNEK8 gCqz^vŌS 4|D="3%o*-$Tācʑ7.p.嚉\<EF$-4UFV;^Tm )gaŇo<;8.18(+FA0tuu q4UcZY8n"T9*PD !9;vt^.Ǘ~^OlBm`KB2{[2S+s+ݙB_.t?_lDT9{,{CJ%Aħ;@U}lwc8 ' "1/% P,)uF#븰 ꑳG1/Op@tD [=ԍS *G $ahScrY&͛Qc_N^Ի-ٖm($-HHb>!DH N(BƀM{oݙX J٧Μٝs/d(жb~+ww"ў+`1 c( MD,-e^yMd5n B"7']]9fahMHPC_w8@n}E "-3g +;IC+–BJӶ"p$~WNR'/dBE~ JBhn- l I-G-,vB[&vkpN.N?d^1%AniK DITe0MRXHGaiLS/<ޜMB 9uHD n_H@S|`0$T=("c>`RY 9kdfY) p HHEcH% 8tHذ]nWYYSGvۛVgژSPFHADKG7,@J0SKRCIۆduGP*++h$m<* ")4mll˄]l(55KRhN>ꍎ>?/*{>J|0W6GLqeG  k{Dˁ][rUPb,e Me#r,_,o)G{}Q^nd"YRa 6D҂c4qIc6_ԥ4I?YR8uČ!ɔ 2aœ(6UUwrEThvV4V8ư<=?p΁iYRpC,-0"v„ܧ_*45΃tY8e"6ѓH j̩3#1_D@Ef39|qiݖ eH4= ̞DBL+S^ly/qޞN5)+14m{}$;AQ@I_ !G{DjH@Ngt*+/xGg.cDZ歯M v8v|_gl]5W$řy:tAŤ0'(+D›~_q<-_ď˔#7۱տ>?+ITHપbػ{7< hJўukrW' f7D r񕬜Cd&4*8h3 \pHb`$pN^TCEݹG!]|p1o?T/Hd.S[ -;au@=RfGZY]5__p*F)JېjEna1kA`py}Ynd-՚owc>/o޺(,!TΐB OS{uun92161G;q "{r>ϫ0F)0 UdqH Tff£{+'? \ORr{lpȄeǩ>Ka'-3n a 0#V 3aTZ2+#ҍo^ۀđ}aSV ef+$a^xTX-mQRqVu0dJ$po.4UE$;bvcFW/$,&GvT rhiB"mٔ]X )%[M;p|.jj(_uNQcyr$ƹ$ɣ?応8n_UyB̥"+ORS";_eH- AUC|M@ڔ0 hp)h{ g'lzz0[Nd"-!%[I]HpE|i(prtw@k{^/ᬾq:ܥ rR^n#iI 0B !I-iRL-EASѺ/89aM' oݧ@w5˙@Is 23TCL  )iLhEհg6zb=l~gUf>EsYk|.DŽ9fe?R@ʴ?UMŎ-[o~ٳś_\ r>pޫqSr3/H=r @0iMW~&kݲF^WOpAW! 2x $M8=" :^q۶U11Kv Pmϑ}!m ohx1=`߲O=p8>ǜ 87 'ٰ%‰,)ѷZP8Q1yn~_is!;wCQ4FbP9 T¬Ya{88@L9?p DZҥ  {[v[ KR/=/B!]BD\Q]BS8WQG)|chw"Fg""Ig'!TAhe:MsJEp)HgWa߮9TٳN+~Բni`3"pEF)lLAQ!Jt J%u9`f%dFG~2ń+ ۄi) ) >ة4:4й:&UG; j>ydKN?FgL!Jea-U"D*Ád*CCٸ1T>z+#͕ZGݼ%XSshF$R9RB9 @@ Jp iS5O-/?-\zQ+=>ˉTɧg2L"J@G8gnzHD X ]c)g|` jXe^*x4M )3D*GB P:Yg(  M¥M )mnOL[ѫw)YeBЭ"8\2`3Bnn.dHD[VAပ]lEKe>5֣'M+ !%4:4 rs+B2 GAs OȬ;La@D)p8]ڂF唙p{~nzXc 8Nj|,Yݗ4M(dJbRBI9WiAZ(uM|>01y,8Ym. I,u`og/8T {/^Wq~钯^U1^"|K. _8ʯ_]Q|cEsܫD1έ, {??q890+~a%*gH#sM q2Yq*I7]nx1wZp/wJi|yߑ( olTaI4\Dbo߿o ?~׊+Hc8FWggrI)Dڭ a[qrtII/+.OD~u?ƁO.uߥEogM xCCà?9~]]Htv52S~Pqk蹦:Ͻ>gvp(iFڲ337qy_?O>=$}5]C/ 盚7̭(^OJ,:?~#=>$zȆ"Qb*suuMڌ _bhH/ suuuhYgbm%)RQ/c31z숑>8|$wgcNodm-#G|Wn)`%B׳xLiȜ@]?ydt 'GvmO=A68#FWN)`-朏\ϙxL!pJT v!4М3][;V93?i?AS2.}*u^n;7ێ秼%殰l56(S xnqf,:?*4y|:XlkN݉l1Oa#6P˭{dc7sۜ.moZ=ǜHKWuܫ/O/EϖFuu5@.rU]I36sb4y\̌9>=9W\]ݽf:mҷ.;fMgFx޿q5 _^3QvV)<ׄA_ܪr:/UI* (7m6q}EE[hvKLg^:>z2ea^5 "<1`.ެV!<4%}2ma~<ϱ ߹[ZjҔltW`F}|رSߎrBq~\ήZlX |E;wkvG^(ʓHw;'.g WlW(&%'x&/gS@`ע3qRjQ;U{>m ةث+ 'F+Ρ! lDNl;w6[@^^ހ?R( ReE1,6y]]-UGh|`:z5+=]v@焥8;2('W<ڻb۰-I۫UhO*G nVwrO4HS8sꚈ̂:G~U_氲H):Jo΃/wk/ǒa;R5mH11O/,HSrW4GK';KUj :ɯŸ^E:0{2y8cTSvlJ<\=+z}}Opۓc1zt*UZVt^o^o}^ۓ_*u-ViiyBٞ_w_+V w4uHgm;@}00ELQ84U%`TW+uMkW}M,uֿ|V܃ Ғ@$3VG$.^u3{k\GGJUP,)2{[ϓ>72l]Ӳz>}1r^ko2%1XG_sq>0<]vt^O)Or YW$壶UW8?s!Cy9#*|ҠF}% Evź'?{cc+#80iv XyKΚ,^S?1CB"44; z'a[R 8ȄO'dӰm9hRD R@ &$8"!,Ġ})ZQU RzN-!?%h"4>te78nE c8"lR3qFM/[Z1{n ^[C,@GCط{׮f\TW{-V|hOĺ}((6²lL?q"zòenO]qY7i ̚8ku#)>T$G7n4&7Cl1¯~wߵ]+L  CWUg&USS{CPϓ['9=n"w{Ͽ| )iNit?YidR9}лA_9VeB$ƦNr'Dn$ϱ;">[w\hGFaK\]8|Tʱ9"Vd8O_ad{ Ӓ 8'+ӳ+) zcX6`_nLHrS -1lscx7|QnC(p9Ļe >+Ԁ۰5]8gϿkw6T  rlb>HRyI_rwbNy70 !% 5`w`Umhz5#rBJΞ%HA׍Aݎ{6oኲ`)$1|m>pymn!GQA<*k<~fpvC~K4ULHqǟnW?l{ȣV@=9uw,yqmhv}K"'{&_1\oǵ? D3;2G"{_Tww`s[yy^iԞ >۹b s0sHd2'| p 0(J:ϓn1k 6x `4ARKf4u/Us,sLmfeoܘ?ny'“m<K [WіsO"^kw+h]f}f<9Dy_{h,4OTn[Q|e]ow/,^nx۴ #}3{M}'v YQv{w9..xdaaUu0>{ ž) b]SwN'VE[W$kI3(}}]TTNZ*O`` .tzU?|oŠw+H_ѫghܝyGoYsS]E`ǿWb=pu-wx?l9\I+6.vjoEr͎"U^v2"g璻f4pkwz4&G0U#Hs\ԔsX' ~d@՘j&FLW(*CM8~)~3KJT5]X׎Z2mss~]Sn:>u&ڹz*<  Re3^td1ߡ=d@g|m] w?Vϔn4s~)?3|RτҜ?lՍyU6raPntSQt{31QO;/7E-f擰{0BEN@PC>,EHlgk1+9Aej _ giN!wF pW] (S_ g*$}9P-?/m\f=eVnK[vm efI>_YI?yh 'Eٶ6$[}݊3iEN]U[tL-i9׭z[ͰBpAVBwSSxtxljF3FT e ?ii߭}q;IһOMBՓJ+ qƗHwOSBZi'ajXA]|H(zujO{s ws(HX[샩pjm 38?𿧮&^&FrT3 ΁p >TƋn]ۑJsB M"kYpe5/xU|p,[L;}k%j'ťk.i5lyWʿ'c3۞8^1uޣJ+,GB Jbbb>{~g_d(]hBJt5ws{"΅lD":%Hh9lDW/\G_,,ʺ l ҏu̯'gْͭ=O!ɿ=ֵ&%ʟp{[Qh"i( Ā=>b tNǮsշ5=W|btٿ:=ߋ\V2t7O~~{쩗ʽwW?3c8 =E#0I+˶-6pS \c g]TMe>Dm92`)w00Z]kXT K,$c$%NTŒ1Fo:} @OXTcβ'I`fL;P|?gI߮޿ev&m)o0yp~ݻl7psa6޲퇪P޽eE*ykPQ@j&pƒO, &Ɩ*Awkࢗ7;5X&lInfCu26ࢗ"H?c{ߐp e4dgز)5Ptc!?cր2S8nr?g8X93Im{UņX$T>1lB?F(ٜ9?fhkosU!lc(I%sG,͞cScBJ(:XP(̹ͷNϷT[O/HcZ4%~9a76*k3?s>9+s̷T[43A 2T"g}Μ9 KZ%c|Rc Z2_c}Vm޲ΎI2sPRS&1>/A*U~:/-ogL˷;ğRĤ$K;C Hm=ouh-%79eFK__/'T}=C?2NDC%.yzsG?} 쟆%~A@toQ? D_1i¿8T@g0f>xpj"ūό߾(J7TG/1N`yۢoU\x,zU1JULw_~(6љ}M>w͌m^(no}j|uKbLj"_@=xxE̖r|>Z(k֮_> ʈ18Ul_e>?禪_ϟ%הVT^Řx*htg\6fպhޮayR@$2&)`Sқ&h﹊qwxa5vL߀kjUP1'ͷQDٓ MϷl>'jj4Km7[k"ay4,mi:aIƟ5f/`ۚG Jgϛ֗ZM46*Rb02i==e_/9b|3qht)`rұYSķ{s}_`S#NO-݃_a/cmP~۸o|~Eekl,-[5{ośw*֏ezo8u>x5c7M5*tEEted'O98bLse|Ǿv[Yq'L?eٷv^~n׳K s6֡4H\?o]pbƍtjlQZ|:ڌV*jiy/76:qdyz6:f3]YNͨuYN/i_fYbKk 3|01UVߓ9r|%)7l%ˈ3Dp?1Z5rv)n-VϯgmmQ({4#2;xZZj'węR@)A_fK)( 5'T+hL⎜V"l$׻B's( qiw<<>iivaaəRL:\9Ԕв|[zM¶3~=B!ptcd8M2fgg$"TL!{$6CØ,17OJz#dPp ^`obTxO8.@x)IDq.dnq5K |ؕ_u~qˉ/#_D p)X$x6{W,ZN&W8u ;$zaPA  8 RĬtֲP1HDij{/z _̈́`\.A*`6H 0| y]lh\[NBg,s({,IG +GƓiJ'tlO!'$YEr` 0Ml޻']_g{ q-%-Tp`~⦉[ V4e;3q;0ї=- BA"ҥ  ɾ}8GP(A(974k 4Usx;nL_緷B޲Ƥо8q pKPVvq[Q&"s{8ܩ]޹լjknoh'`vr;4{9gvV_z8k,Ndvi^j}8g=^Zn*iPW4GY$σB!N$VRfEý+;:;nݳj׶Wmt\BSGN_  q/ UW O{{±ݽч{—wjjn'b4l,11uU,KPhk xʳx  ؊_@)۲v{۶|CO\ȯS\FL:|G)9eٿt;]g0HWkk=/xrJKr`O%S+{n>8 )9|gc^= cn.:/2{Μ 媪z#q3ehr LY\u訮>\u /+x.L[qmr .>/OJ bVOΗ31'*yCC,r9fۆHMa8/h||8n?ͶA)=Kv*idʔѸjey#\ ?v9.]–)m۔-S\Y;(,.۲ɤL%Ytp!UX 06ch|H?+8ܛV$1ҥD#ܺJNU%,A{_DR=d8n`Mu^2W/5"g  _hz)b鱯1I7,2Rp8П_\]p>ac-¬)TV2K8e;?lCI6%@gLȌ>Lw >ߓR Ori Z7Bud}bpDF(1i۴7Jm==o{,&qd|gc8+ a?;,"0&x0k mSdcHZ6Q9 `~mK&6lסp!nAG/Q70h+UU# "d>l 0\Ckk32hL 8^AKWTUž8e9k haoIY.yn=<йԳ<.S5 .@g,AA ʎ7b ƘPn83aICP8ߡP$eC3[h` 2pAq4yB6렀Ĉ"g5<76ւ5/'e=iUdrɣ )߯shllTyFwwN_!X~AS!ɹG N?_=';/kx */]ٶu?Is'Ny3&O@P`ѿyνgӺ'y eҊŷXY>k~=qW\ /ϱd7okg ϼfO>s?_:ɾםE}jkkAe>۾QK4>{OQKT| 1D-[qc8GM̡=Zޝ, 8ֶƇԬ\];Ug_kmd lfFQ? U☢v]-Xh:pz@✑gWa߶ϣizշ:1ab t7}UlǎKTXc{:?55 ү"7U]_]CsYlo[_pq]`޻*'R޺a{uMMMZRo-{>* ֭KSG{bΝ_!; YYsw]ƘQY+T=0]!>l`_8 7qsF.Qit~#H'8j1o1dgVP{R3NMsrd\?T7cWPfMm-<ۋ_Wbcſy w?{tc%MDOm"Z1#|~2;Ol(;;;k?PD2euo '?Pkp1|13x*<#|Lk9X,yK= m@=>~v& dcE@}/r+JR1#8eMW$dWZcOP_pϙ+%09 '+\ApCv3W2ma Yn\e@v* 4[OmrBUXܴ>}tQ֭egwoH);}-'3Kv^ɏSckˆaD~c5l`ƍn\NW5=aoT߸q%,Hfŝ5|N`oWNxvyw)]\{SE߮0iH=uZeIl71wa+'M Ϯ_N_5tYAy'M6`Pۇ֐iEWfr"|X}ľEOgC^vQ[;/;%[ ns 8RlU+F!󳖟YblÉ`LdPHcăe*9s)0YSYoIDATOlpW$xXp<dMn`PsϊͥXdX +Ką JAdv /ț+q @X3}eܹOG޼<(.b1AXLΡâ G"1Axeʇ\O$+8GEi=G2ٯ8mzSC]+֟<:u9ky\Z7PhA!}{c?#aO|߹0}ľڿo!u 2kDO/S+ CvW{.j_ݿA7*,l}⡆Xm3/~ܧnZFӧZeuקfľEwT}z+l}/n4>*gS&N컣^?[om_N]p$wgZy@mu<[2ϞӁ%|  3 P\}c8&IxTN>~*Hd~ŏYzxSNA @`!we;eBh$s4$dA2 Hil>R$M H)H$RA䯖´?  Y$:p_WK!!A`\a}HI[Hh}Q %e|c $I0JIH`Ę8]|ҤinR8Cf[msC+|pzb U0\{- !~{*w}}}uTW3ZM9i^ALPBХpU 6xQ{^{a  ;”哹%ݰU|#D0sP-Gm ^y䑅g֤i( p'GwުWYP_x(?j4Dn0uCW> w UVpBP>޿O4߯='҆"dkCC[g(TNGUGԴm`XR#f}9O5sz{y0#lmhh2s.mhx{ym4yS-mZ+kh UNTrGRrH?>#ڈh2r"S5"mm߿<TcRrGsm-*E'3L`ԸlٍwTXmEDH`DJv#,9-,l "٢`egēxZk|d"UaG\0S# )D΅8f?V%p8@` mt7R]?95/Yn$<]d ` e{%W/R|M83p0 LbWDO}5yDnegnnp%ƬGk0hViU،FBQ^(dgLs+ {-;zp9;kv!@8,c01;E~9ﯼkhĮ8ׇ5q-}.TӋx$wo+7^{ٶg|k?PI|i$:|I7l%+<^=w^,c /,bS4).ç mi?S=pᘶe<?^eD<1Diٴ1;+?_0ynsڦm|9^HrO(^(h8qSC?c[R6*Mu9^HpggLQ!L}sOr5؝'N_.%?~Mߙ=> hFՐՇs]Q=$7bpzCX՝= 1V0oLE|^eoI;^RRpܾ%!VǒHb 0=Mhq3'H L]*Ynjp,,d:??9E2oo{xxV^~ڥ%紵:Km_;&GwCWNm6w_;-1d_~մS/z9m{wmί-H~2e?&@pq/ILaD1a{e]idJ w_7;hu.0T!ġPWIXBT \wMvIQUvWU>9;|l=e|QHkNp/IJϝ4Kf$@ͷy/X,+f9u{D/;YwZ$h@a/A3TtʒdeI$ťg6@Ab[.,٦#ʒ23lir*vӒ+wX %GYѿbYL!+,F>xY-yݿ$H ^3F@?Y@ap[dV aƙhe[oXZ`<>٪^ВhZyXB`A>'=LF#q!x8_%B=0YC2}$Z(pX43;0Mq8bx /ݯ񢼂e>/??E{_䜖=e|Bʘoْ/(pwtbf00s/pɝz"Wqo3"1F1R“ ~l}\+I@[BJ|[wWgs$iP gېc?!$q@I0E5#?6>F"&1骔6?%A2 pU5?~7c lI!҄| s*. :98z+-.tz[x_dmcB`3a}z&R,+gB[-pQ :ţX>8I?rjGz] )}EA,-tB6F<9Ӝ{Nul۰9A}2!e\ʠ5x>۰:A]"$դB%'==rAJ:Lu쫟lVW[˫莆'Wey|Kb6&10Mg4eǣ9'7&:y toU%,16;F%H-M[q9:!//nԢOHC8jABcɶfdq YL1 $Ȉcsro'"& {j\YY,ڶ_jKY@ d9?\fiZE DĚx*s󭓳rV~u8;#9Snk2.qC+xȁvW5viʘjwƕ3F}aCwWx +?]Ji ak5g?y@P"߷w}yf;g'*_hA6Ǚa||>?]7\t:K%OR8 D}HƎ"R̔-.{[:kJ L.1D$Z{[;v 3p_bu*'ȇC2E!?T6)XcOK@#j<3ŽqtZb$u%5uaY 2-rx]c}<umF<#P%eE{6(nxӟ&?h\Ź<|5jsO0^tǧNe3777/0u͞wSyR@$1A!)Gݟ?sܖMU_yOh5%W1"`}ԢEW]}Qj#u?.Fp2b ^JSq3?w[˞\#EOܿj5F)INX=(6љ}M>w͌nZ>|kM|tH'#q*w#7J*?'Z׼tQ:*;/(^{ę-?><^5F{yWV>$8|X[~ѶضďnXYr~ć-*;5}S?xE%3woM<>E^1-u]k7QC79$?KQI=t,7Mỿ1'zMs>§!5hFVkGn-䢋LC4ٞ?>7aϬ?N}͋jǴwbݏyaNfK OSY=𶹯xSUIaԖ;8C#"vuu}9f]J†$Zq?LDbDK5`߷ӡ blJ#aap`][:@}TnN!Bpª=)č>Xlh|VI!Z&&۲tڵe-am Qcr =lL\:7{ZbNmAywGW{b\ mlkq[#Vzw:/ݲގ G3UV5_ݝlI4l]b4/x< &WUV9+`hC)`ՔS]پk}d  0ЍdkW}ˌxlmD;%.56ղ&A,*jܛ#M%;ת.%ˊۀ`^kga״薕` sg;pkK.56ֱ&VR`NTJz~^J[4ǸC",Z~Ze-7-sLqlQ֑)6&VjLTKZں_^#O%e'Q݊ClnPIپ}^0mDlt_p!Bnc;\ڵ(gO}rgۓGutFO ]+Өwphe;bcqp]Kinm[x?y s'$Sr{Ņm'"^__??l4fqGd&3g}P~c $y);K&KS~Fd|k^g}3~y* W@!ă]0l!mq&Hق"fJvDҴ)aҁUI(.Urܔi Xq$n/T?L2yg@2+{c&mN*;ITi+'KsIJb)k.mQGЃfey $b /TX‘ dH.4]Y?7HC)IǰtρkkB!C9R=#ϔRT\&!dp c"B3*Yk%LݡzWHdBG* B\#2wd_Xr$B2夈i˨su83MĔQ(To1;tƢaତw_9G|0H]$cvvvL"v+;($˘.-yILů#MӦH|ٸ'p!e9/mi?mK1f))IYnǗ韄RG)Q KvyHg,qjjjٳ|'.v]rlq c?&VSSÆ^_6c=\W`eJ[Hh ƏlK !$>}2 [޻; U)[d k g.Secr(:I–g$ dƧ/  韶Ov-4MSpEMg^áBLc(ي @fnIc7/;0\C@^g x 9纮0x ))@tKHY[B!p fOt|S6q\.]SlF:Ep L% Rwe1E2޺=u[ 8cRD!`O:Y92LT:)EeTxҁE()5XI74ytwbQ({;^LLP]$Ry%l-LWlK>{p$M/ B[Qt`2q*9uŶ:R Z@סdk T~<|̞-Cp~ӓMI Tl!B"[]_UwkPpsi2?WjO%R D6` > Mǻ|;&Z{aB؊%+zYmU%Zה'‹u=3sMᑅӦi솃 |3ɾt: s`6t 4^r'MSfjVk'3FZ}}p/xڶIWUHQ/@تd/MɓtƵ3Rp0 zAUV>1ɁTv"ҋ.HJ&6uxÛ}1Ql\ Azd_9I~@D,¥p 7"v *]ڵoq'y Uz`+LGNTzdB֗J N醪ôlf7FrrU"_^kq.PU>SUbC qYpI~?RL= A\ueVqƍ^_v5bܤMե<9m޳qM(-aW!%3\ڂG%\R0>}|F&(!e[ؑNak7qH}䗠J0gj]D+~uLlڑmۚ?qa rNsyڒ{%v2WieלZm{Gknk:ՁʪIU{,!;sy88G\U+A2Tk .<0 z}uNM 1/3 7#OKx8چNTu04?KD#,b7YCrKe*IDp/nBX>fb.NLکdsף_n=k='NQrS+m;e҆g? q;'4SXWWgR[[455Uvwu󿖵bhzm9"?fvwu|v  ySFNp‰ݽ{uiP_=8gw=e_%| Bm~NCQs 6{ڈcB=Æz:cD(XC\G F?md%h؀-\k7"bGx>D_(j*//>@#O߿N~!C?Q];7!| @t~~)<ܹsGTUMgggCرAJ< sr̿G677Rz@EUSY'ySuPL\` H% IH۹K'Oy*ejSu 6-H{LE{Z:$|`=]<ϊTO:=}8]o}uW(T q`yՕp_~tin3A}s9cTcZ;ڿ>Tjϛ9jԨ5U)jq&dk.:sqkژ֞o?W7Mtwtt!?޿G|FaG 'u_䉸f@nИt)uɒߴnh?!{sKXHXy睟vtܞJlpZNV֣eeC{?=J٠ Td龺} vLo0"zV:-gS3 )+cLQiZt|'^}NPHmhhWvɯ}{!6 }oEjggւ1v`YO 7 眒Sjvnfaw4a@]^^O_8g|0|5THad\ook}5:R@}q>waʹfœVZģF{KK.|dBBChל_=!?/¢bӶM-f>_jaqYi[G!߼W ixhmi]=+a<v' i4B _4aζ1 σKB2  X?ozo߃mAC|x|MycR{Kq"Is0wcEN+2tOw}&DM!G4N8s=e^ X'~dhՂNm2"bGZU55ю t3d.c bJ+jjb`=XSS-X@ 5u ꍻ*i~UU.4ɪ&ˆ8w&ke9Oo275Q…Ry–ote94p.\hD4:c <)@mh*p6 _`g ]:pevvOP.bSe:aBAfmd3D6A `q' pOԃA?vLMPyZ-[+;ݴ@CȬ)}:6*eqllb5O~"ؠX7n$lo;JwEDdffGvY]ߪ9\+4Uy. Kn:[jkjx Ǚ]eWtK!6и(;dV8[ |I} T\{yI~ٝ2 Qv| o\=zfbEW :zc£9D"yZt|A8-EQ]C55Hor6ܳb]5PYvԀo( 7}# G]ʼnxL#!;G}E xKr7u{a%/%(Ãk&tɯ*|cgD'?e&ӧ@XV'&Rgw/P|:.߬[Rp@?xg=%~{fXj^orfƅأ^זşkl6_NGDZMS?/س|s'/;oUSSSu4Xvȡ *ӟ_=~yRM $;lUSSSx iʣ>8{b[b<%TRNiOxu?n[Bqc㣪?9LO2鍄^B'ґ"]qmUwaVk[XfJ$ H BI!=LϽ `~׏L9ldoO)[*LVaųV]!277G~bB8agien|E0ٞRRba\W  18P2.M":6\?9$ϸ3y435$8EuGqI]'E8E'NtR \i]JRpw!s"_oqhr݅9'l,,\ H3CLfxO~EKV(g٠NJKRϖ,h%^ܨsA= gM]Z)>w1SqN~+ka>#Cӥ&̼&vO_]_srqt/8}|uJмer^ɛ(}y.]׊[0.?F%?ZV+?ir-Y^]״$jRR0JQsWd 'r,6iܒ bC@8)23x_/GHwq܃f#C!I-#;I}?.c.SĮ/|v{^I-gS?HP1o4Mٯ$7BU"02|w A !"hsKJsnC+yQOΤ,]_y$%ZE6}/C< 2\.O7"WƀA'}je.kL1McZf||c$칗%~?[۬x~W;2f.b'?T3ݵUJX&8y;վ+SOP8n\7`iER $vշg$=7\aYAD : R>o9+OPٶܬH)!H42c+ 'e/9.wH`:>>B^i6y_}ZwpM3+yUrB x[jv:ULVڿyO'8MG * &[qك'[A`B`A!ֈewˮc ёIHr8>9nZ1gʙʪ\xN.zRCeMf_pz=DwEɔLi´!4) J: 6z֮~Y_6,nUo|$ yK'v<*GKŹd>B)D70oŨKPN9rt?NYzMAT"W3n@aKhW8 7X aH+E2HoaW&3Lj B@+bke:VתP}NX^|Eg?{+U ?~.x&#tm'yn$?pg&8|:>9U[W&Gd<ĸ5lYAAAA Mn]k^G5=Y:B>4/q3ՉbOտXGИOƃ?RZwOd&Ikܻ:MY|lb$ T1~((PmջQ'cqKttvq9kE3'зG@A;Umklm=/^|^}M9񉦛f Kq꧛5MW-d2!m(Ծmak)!;v1ShgfZ%m'(rmllPǗ~Ь,3ìV;Z=,gPơ[!n\t۷uƞ9B{/$g%>j67oy`6^n6%Ej[quȤ7>5RwS=?M bhccxyýl`3IS~䬓?#ǘ%B$e5N J L)!S'+tc^M i#J[L=8D*@e1av"WUPP W]uc+^_5{c۹U;W]u=g1B||?ڒKSw3{wEo0{x喋/:j-r|.ŰɅdKg9*3g뤋ssO{dgW0w~>.y@8q<w, hN$g!~D/F||Nr|PLLDC#BQ!S6ݹ -z4$pHUerTA H!^$20CKEEE9<;?{ܴCC|$7!sODDNuUdfU^΂9&ckFTS(lVw&d(o#%.̾Q=䏻fX$@|B\E$fөۃ8axfK&(l˦awϲ+oH)םOI:=/7 ?[)DjZc@d5M9=V޳U,-3ʿHJӁ2/qÙ3/M |:`܁NKr逜bUE)mK'l"NkT}A|{N>bf*K|nNWĉ?J&w 3L-Ktm{H@(46|I敷5 m of)H'h0Xjʜ 23~͞=?;XI &ɲBʂr=Ff6nw~~2fذH9D:5zn#Z(tpج(䈮 j,we#6؃0 6j  u}o$ن !A/3MUMȪ;j B(.!2^_y ImBarx/OMN[L"lPDK3o" g9sN;]GgLiGRoTotc/Hݓ`Xxy3=Ŗ΋7COBQ @JN\^4bkkM khX~ZSuߞҧ1䬡DB'>N [$"f's>]h~* >>U7QYGgI(ّWΝ9jf)PX|ÉuAQB{$}<_xBS++"n4D ~eìҌ("|^%+uWy[ =EJR*Y=h0(~#"%) ߮y@(i))zB`Hfbo_১b B`h֩;㧤b!0<{+ `Zұx(o؄hh܅ bs1}5/VK8@umA& JdFA$Y/lg;!('B1qY܅A섴x>x5^MU)OB\nm&[{}T9A$%I Q*VO]mcK~}?P-0UvE3r$QvpMH!=G~E7u{y[GC]_o۹.~-_l)|O_oVҼ{oȷUq%cdyNsD ijBzテmqe!qS{m;X yoLŗ?|X<zנs^?s%.W)V3A>H#a Lˠ=_yc3_t;A`]0ݳ>U|Z~ ϓ /N|榋&Pr%Ys\. r&B4=-A6("k戳iNj?#.0ގu p)~) sSߘ_rk\R~lUUIiRC#FY)feOtݣ]<2-Ҧ>hBmřKDI/_q3{L1S駑2n 0_FA:2b' elh›ucg<鋀9٭c 3-!NRG g!>ndI xhQA%Hϼ:ѲOk^-WMzebh(<CBbKIojD)")] I!HZhg>^r'!%SʄXL ~3!:$3П<+b6x,Z%7Ei `{k3U|>`QQdd6.% kE_;k|r_',=e~$i(%&]>=_ӈߞ e|;ϵ`ZXXo@Y 'ִ?fc=~MܔoTdx??rϹ3(X1cLl9j;  J2b떏 % 0d0ATsA\E\}zG8}cyw=?bRZoQMWK'gx !Ȟ_3Ș? Fb,2. ;ݳ|{ r 6{^mWXؓk)7l| ~k({we_4Ǚ3'?cSzZS.妪`+"#^&±dKRm~!;Avn%Sf!%ǏiOHRӍlv9|XqsZV,o/~f)_ljq&$pEeH1H*MvvlE%7#>%Cmڗ~(IUtzu%m-JKKgw-3 Ӧ~?xzd+LoFJLM嶍$2$geW|D{wx}n|!2꺲?7Co_޼y6[= =_kDJse u>|dyI_0>j ز}'YZ=廠.r8\.N@@~O@d蠏զX BcbRkɑOj=dl׎4郤8\:WbqxxWtL6|ѩ@D# {O 0! D""wS$xӒw\ڮ88)QsH].*۞fM\(2"{Ҕ.g$f^ʈ:Q# 禄.Te Cv i[\Z0 *@T9ڬ6ݤ\dR/ 4d$:>%uTb.6_3UQBHT_;m "A NBE#"1p7|*ɐ%z_c Lm@(>ӵS淵er`5p1S IMdJ-yrAj/i]YBְ@% !Q?ױ'aL5H\ȇƫ GTg8XRot#û҅\A :z+p֧,\iTLA+# "Q":T*\%CvEcsF^ |bͽ3l48D M7Pe;8HZgj#'z}k -o9`ryKZ%ƭ{[vyMNixDs'&Ez[ `=ܸaL!(GR.LF6jIdSmY6o8E &g ^ 5.9qr0Ō1 'mZ-%[@ T =EהkT,^.ƪ{SZDjS;<ǥṒplkoԛN0B=lhX~4.B}fRsHNcQΜ{Ľcv 6?;)'PU&f7F(C!ێ(_yHBᕬ̾"{s$^.MaU _-"!>$HGuլ>@hQ%rE@DGn+>ۗ<9?TۂP^^N"y;Djb[sK+GudC1"~ #G_NS]:~\]hty!x%÷)I{ԯ31JB7(T10{9Rr7gdQ pV2xg {7#v]+&&"D3)R~5;)ypaZw]HԺGɔ)ub7T{u> |+} ݱ)SRv;,@ !=w NՊbq;7xNYֻR0\߃߄OROs& Nu~}b_di3nk+YasP NqD`#'L3/^X`x%]DB?B`4ovg̜+riik'5pH0kG<߹Oqn `a&dD@(0Ms&6h>-jy{j#CM.8;yu^)v[?\15c'LP@0Mlnl+N5I x &8']BRv-×Mٛ@U;y~RbWڏv^o`FH})YiV(p`xTtl`Ի[zܺX9Xs,P\oԙ'`1 GJ7%#Q!c  }qM,9uowvUUѿN5V7Ѫ0b1[͞1L{M9ѸFb\=FPb H~[SY $z5w!5fS561♼5n3Mvc$ʣDz΂&$@ko29omj,%/.*={vfˤVD|B,,9|W+'/4J`CafV@݋ 7|뮻Z((0 LwX\ps'uܷ4D(apIZ,:e>z 7lKz8DB0DL ɏ}hvOY~{j(9ɇfA * 5N6թ`Gy__l҂ʇa?\%EZ׀D0Ə;1*e.9q!hpXhZT: /A kU̝{9qxGّ"~7_l3s.ti)HKa2d7Dqـ.~WO8i'^g:?!`1HhmQ#(T׉E|`mA9VX?G)r8 ps8ڃ &6 jhXC$3g=㭻YRuc@=[9EK]k+9-j9g:/!a5PxDXa$XEZt g8qO(x9Bp% /!~֩DOe?KoqoOX@0~{vCR Ϥ6מ1qk~F(l8w6e_{dʥ# ˟,_!f뚲Zb  I%$UpʸysB&gBSUjR)$x4`K;)! tú\۷H6WNU[ט'TN>(t2[Ğ` 5T"Ӂma`{;;~A}n&m<|s=YFc5% *dUpkn{6gBWUjR%Dql۽'0:xf"&,YL m w9\'0>_qV00 l@d/?v|%8*ga(+Fd4hP|91);F0T`P&}/8burYb|@p.po uPaPIUK} ).|tUHATVv_ymv#rQGBׄokw)K }r5H1H8%R{YIp&D/;gHLb'[+<gDD- H`9su_L Sb Xe@kv͝ f [z`>0 #`ʔ)Gb mDC@J%DQ9CaMp `N;߷`Qohb 85 В| !PsD":6`SI ?Pm~Mt&i I ,[$@/j[^N7`p ֨2Ay[Coh` [@RC=P(B\v;:1-&$Y-C(CWB :ݾs@ᢪy^Z?lJYƣKoݾG&,/9!qnԞcҝ/D_U`Z.^d$T-@%=hjŦ69ƔJBԨ9-i$ݷޙFg=" *xjbsb> DѬ!"=g,W>Z < Ӭf NJ \_MHq1D2ɋKP= Z{2v:?/:g.!AIbV{ûm]f#-ZT}J ġ7uj%`~#~#dXT'PJk fI+WR_* ~^sؒC= pNY,76p^ծ9ل`/(ZT[)MW) b%2*Tqgiy+w{ nG5@\GC JZ'BH mc`nF/( ~1ZfDFx_ ++Iag1 mW0SJyGoq8K&h XTfC|3aGox@19^g"%$;}Є!ۿ_Xh/JŬuR=$څo!}` ` 2j)'}ƝW Mcy=ƛ}`U8Ė׮G'v[QwMn!((ueH H`MP;qF~ pR^ (hw[j#>:+9q?{q!J6{U[])xC_p8h/Sly!),/?G,~ SRf57w69 =m[fПX?Ru;8N+ZrBp"Ăa8:`ޓ$ͧP8K0qM1AmHŻԒt>GVe&Z~w!H W_eCµй0"xTDXrpXJ ӭ"ڰ@ȓ >1W_ Ůʃڪ.=/gߞ6 .ue$%w=o'ID>$E`Dl1 \=)i4ͤF_{T%_Wy2TW~ (cAr1dWU 1@ੱjA?2dlz"ݬ(^ot_\P w6txSc0 NxaBL?0Cc[Y1l0EuYQZOf}yc' *DVu̠@8>hlJ TdEtIQڼ U'_۱&%0 \z iCnkS-elq͏RS#)kD봧`?c( ":"" IĞ>;cCY;]qeїk7 "8]Cf;~›V7rB)2 -l5Naa˲*CAp"c䙂Za zNrX$ܳZX;͐% *&_=^/tÚ/j_Dǝ9C_5!;T$wg[@(2i܅H 2  6@B#⪫߆@LEQ:~d9@J5xTvO$n ).3GQVqw"q&"프#a0Jg 3h8l5 eCSu>r|Ԕp'āC=/(vt: 8T᭾WoޛC-@*zmh1Zغ B U^ i9]~(2e u\<;-^9={k|7m-tN!h͂?>`\\?L)8* J9Ce}-KRu/i$M impվ:8Qle̼D髞BDxeIjq#l0꛾lR-́/BpЫ=Cϛt0g߶g_:~*+_z4AR$N=ߩsR H[JmKSPXo62V--lhB۵2Rim`>JK헺lT}--σ$!=n"7)piM(Pd3Os"@%XVv0\/zGt}?'[%rv8%/ *tE>/R^ePEgi@t.Klq]c%)$_m+ V 8FX^gcě10qA5JD/nf kt21}t T#t=$  c\s^6?Ejc#rXMmgH1$M`RMVR,`$ֹ͢$h1hz 1: `0ILRBRJyGboÓRZɧiow".}"GjNwLpLJ!IZDVc˯9'~#2 žWtHT̂d( TBe")Ce;aNrW}ǂz܅ۏ`C@DہV;f~1Q6#O.+$k"k@o ^ 9c5L@xw>v !$BϟaH{R:LAl'm NP{=GV|̥߯S~>5~.U!@j;)2ec]6!#Z=K`=4쯥V=V6*x}u־ף] As` wavX)W;sD/Dښ?9y۶%Bn+"$+{BLkokl}tʻ'eUuaɯSs7m}^"/Gb*oK*E ".?6>-EUV%i1N|B[2$L /!5 +kAA`;^,lBJf = XzTfI@GZ7݇j2ʁޓaR3:MHSW% CI'=U 9ɛ[bxIFaFnnD2&6%G a&DO/s=ӟءK'HMK|~֖v˸~4_(}g\8r"?wی5~dhSMGNo09تnGYd#f#>;6 @4] *a0⢶Vl5_%Ѧm~O} a C Aި+HgLJ# f̘2hР6lXZZ sH^@ߺu˗{OfwI. 2ZDV)746::f>vXJHP+yB r݃:=2ёX3Dd3Z*[\ad@2%,6*Rs@[8z`M 8jmuruNt{h=/ 5́[nE{{}m3:1wr:A]./MXb6^{CZY1~pݻUh5zYU$A9ve0nF2 GE[m'eO |Aԯzpƻsq/& }'ynSg ;~ni`R5aɼ5Om4(o'&}~_w/mZ77]1ߨP$ǭۯ]%&䃵Ϯb&ٌZ?ߺ|<`c$)Lހ>/7c#2[  AD4/,m?#' ѝ@*(AQDty "9-!)tΩ  ATD5[6%AqTI3Bl kP ţ%lWBx 0s@0@й`Yʐ؝aO6t(e7ׁ}dgM1/=#k\p `@Kc|CRUղsh4* VF:ɷlkfBǼ5+&b @'JzsR =;aӶDP  ]{v<%bԛwZtKp-ԍԖ =@;60' D"G t?g^ )>Q1!SY6T4{5?5 ƈ~ҙpXv,|[_WigpDk;X_\3iIoU{|j)p?fYZoT7ǚtlGy/r=RXl?ն_-hxkQ]P9$Ruh WJAJe3}gǖ &㪗R@?Y+]3=P/WIw|9' {꘷&oX>qN*BHZr%tH5Xefv(Ḏ$X04 |%ú 6Q^׀ yHPYj:"9k[t|A#nDsk 2$-AU6$g6 a W>A"ZQA0MzY=v#pހel@^WCB|ϡHPUtS' pJ414BHI$dz155u!8V׿"01&o۷-ݱ%FT !T"BpH RW7#Z`%UAt='2΍TͶ311\|"-`(tO+l""aˢ#9!#Ypt˄RR>NMr8vBO G"~YTT$/&̝i''.0 bw84#d] \n.#?}ҁr{PV z_{Cj )AIotxXйxV^0t:[ Lp 1`2 GV"t-̀dX@ρ^t@p#BxL= d@t=g_IdoȔ[? F*#¥-`II`܄AP$$8 3jc]CmP84w/NNN s8Itd7}}vɇ{!9wrj>״fL3|ASt8_U״q*c%o^ӪuJ;ߌ}kNp8$,~XE3))՟CGsBWtZOO}||yi1;b!$"7#}o/.#ցBK1d/AH!,'N+uLj*))c Mgٝ{t_A {/ [>W%^CWBasƘ*)1c5W6]'-n$?m/^vskT`D(@F$DN].W߾z ӞYeO\&t'`0 2Vzn! &ߞgݰWo\Ll#qnr`w.uLOjB6@y\.@{zzp >sQA&h~U+/l=)D葊~wM>zB"d Xu0o:Qߋ2FE IS LL-I]n=/pkޝD.KEUӚS+@ACwռ?q9DpYqՠ(m)SS-ś׽vBEh+*3k?e[>ɫ;/\@Ȓtsؼ_"Bw AnԎ~6တnz7ȼZdo B;J!/%㶹3ùGW~=C\;ZFz}wdl  ]\g/sNU 8ZK:O9diq{V|(~!9  E34?m7mhf͎7G]tH-.w^!5y=n !~׸wڷ~~ɗvPh BFQqT[N'(mQ ;4ѣ;g_9!b)5R8LcF 3{MWǩ;4[f\9gPBZ‚#)kt?M /VY|Q}~.X.!HYqTq;m6o܏bSe A ӣہt?wݼKHO>=1'GxEwW*a,ߵ槫js?^pqOO?!!|R$ւDvt?ǜv,.הkxVH_MhTWk?w<ȁb!䩄苪9X|kV{b'fEl7M*5o/scGM}"睶-۞R nZ`lܼmK޵@#6V!,-HtP|vUw,]] W/& OUHk!%%nmKrלα.Wק~̕-=2Swl%^۬8?s/Ko80lpugjyL\]?{E줽-l"3Ej!i*ϨiH+NgES@ \njv!;ؾw)Rox?0~l}56D]^/0B}4EwaRSJK/@T*˫y_CR֕}^3ʟ?,蟪dyhXML ś_e .CO?\ YeG9!H=H-\@斖vwMW.[qYڶ=^|tkFjTD tWZ*\H I0)(w$ܵvT fvpNi#pt832x!Ԥ!vy|In=5%}T8ʯ-x@[ܹ . LvmϷPYhu}ӏ4w8 )F1JbF*cz\V WU;kwp:G|k!4p8$ww 8PXSm'Po{u{2(\Gčj{ޜB[ڪzlؗԐLn|σ~@Ѝl:_t=!n,+{ߝߗL? ޵jTR)NYqg=˭CWRmE=U[kaiŹdS8/p2e݃)m3쒟ofS%JnRvo?9mĐԝd=>3^ [k /ܐ,>_|[a_ӧ_`!N0 Veݾj65mh?gtן~UhOZ[ضh^қwWS0ԞqgD'._68>|w$;M0#S(x\wsDQQTs!˽"->>m33T\.}"!INs"d`J @yD%Xb@wSE9J- "!h!!1b+L93e]-vڎak^>hWPΡBZьU[~E@lbOny;Gʬ$f#Ha֋^+ly+_BJ $Y Ch[*r_b?@RƶNOޗ%H!6ˑpfkہ̆ǖ}R%e#FRaa;Ђ> Z\RD)gIG@9?EVՔ]KwGElϷ`z @HH a˳ȩ`'>A.(|j'eMK$"QE2pAAژD-o៉o3TvA (/{sݗuO?-{|AcQH0'pP`"OP{ Ϲ%+>[ jx#pM❧'Gv ,f$@T#i|W\:הſ3 pWy -wN]I(,dx; BO+HcG6APCԷw>V *a~fѠҾ0Srno+YsNq.+#>sV#(XN65o(dm8?PZZqf0:MκUHD ɔx3W.Uv+>EkSǕ+WVu܄x&YȤa4d#n={PeoժAX!}xowݥҁqs%g6FC:9Tٽ\*j6aCi6!$`4g!fHLyŲo}Iz`7Mo4D"C=`OnZ}_~,AQYwƏm2 ߤHHR#|HD35%rgOQ*^kA>%bD%*YRbܴOxz>FL jy!>zP" PAS;S*[$ILss' 6S_þ?Z׵ӟLdDoD*BM*,~bJc[- t?ª#(PoJ\.=LH,疖O?2;(uZdD}c4 !!zTBtA={ώmYƴ6<+E9;1#5x3rX?!ܸd9?,{~`D|!hŠHKB}AoPAH$YOϾآmVdK#LWL,|NN4 Cŗ#=e(x pɭ?L>FI8-0Vfm~Rf`(BT 6\2.[ݎ_StK:Y#joŬO1<{A{ҥ2)[-Q&3Ku6#bRN44kMR$& jOQM{zu%r/ EZpꥋjEϑ˿8{ߎDGIhKIjDWT {xٲM0ǏZ]͚6kTOVkS C[5M^*?Ngo#)}s2. qr IsZbHҢݛlzM?(eJP!GOy~zR;7ח|lCi W3}3wD7~b6(*D""gcw&l ts@eJv:S0AS3!'s#d@@3Ju3|.O:5*;@+/+7=."Q {rWn6z@[bk9 8!7qDL@gk9tl̘1qq1-}?-[-u{76s8h ov٤I9 8c}w-NG0̀B0vXY~b4!e]݁?L5 AnVPP`U gAH[ZZZ|Aخ|B}CؠDޟ$S9gL\Q|gN0ze=k49H"9 r8}I>9i_O>+ Td>FH]} r:ujIU@ub\Cn;Uzw_rt/$u/iR [)"H]6V6B#[~/.f4åۛǥ 3t[U*sʑfke_px<ˆ (*l7ǙZ T` V2yz^>QȌVνͅ2`ZΘY6Nq;&B"*4Qm]u͝+ .-4@׻lZB:! Ʀꎛnݺ˖ݤregL0p1U=D `]}ҥrMcǎ5~D4bPHoXҥ7/BKƏ?K|q&QU3 GcD#v/]z?( to+_N!FaP#vsݬY /]zc(i_1~_ш\@ķ_jP%$BpZ )((TlٚK\?hxAAbu =;à*LDt*q~Q$\dɥ7n\V{#@xsY A&j\oMSST p{/Yr9t1c*&k9r%"SY:RASa=˗.zcdٲE'toE BTU$.PNo_tEsK8dAwr4ycO@W \x=qgO;hZC̵ּ0GB!=Հc?ykpW,+5UuGUk|3owdk(/lA&pY',Z^CڸgGPĪ D:l0S#QN `٧V.@tM\jcϕJKKX;ظ0..L!Iq0c5.]ǂN1&%9NZZ-| ؘa\י7 !H:d2$ML D@h pN/_lBti A0flٸs2Z|l)z'_o@J]?xόF(DG!J%ʕsvY~~U8j|\CG gJGPnN5"Y[AZ"XfB _Ewg"hV\2x`#Bښ RQf §Ci p $DB P[)F#}`p=tt<+[R5w+ |D ~IX#w\bĈVPnCv$E[&$| m LҹKp| @(uߡ-h2HO^NrѣG[~- zpxsb[,4A޾sѣG}~_tM[\R5O+i2G[׭pbݵv&L~-''A/[Ͽ+2 SR0(xg L"- [00s;˗@~~~J0|OIڙo2AK ^;־ѣB-wI?&>|g$hXF_ PRرc{Z$+|tŸGLDDC2R:kw83лp~ByLu<'m/Pدߐwοx/ViGk_jbwϼ8T]'T.iY3[Zoo,FU_/?n&Jzz+o`N.^#T ء\S|2@C^2E k9fvN:w_1 TU%\ET(YhASϻs1_},SU(V3 T0+=/''^^^ϟGw%)Q0?`:"޷oJ}|G8*UJgdgg'rފDWnqw=`ʒ_:I~ު(@ՠH\h*$Ć eQ튎VWQx.t:2  ]w'--7i*Z/.)g6Sh#R":~ITʩ[,*[,@WrǎBbW$9ltcbm7S`E(LP<|-x)k"V+6Y$jhc_ e CB9δ~I= WJ H!w#$o!+c0oE9&d G`P"_+vN8$IF}6[l>{ҤI[gu)"QJkkoLiihnϞߛ,+[ Xp|IdJ)8~ϷBU 3fY% +l;,r~oϷd4M7M{SreYق'PIkZ`6QwUYقB<UU>b2M)G\QV`Icf?>j X̗8VVvCW$IRwiĉxuiiip;: !m5&y⪦٥u]kۄ>ooѠ1Lc'M:Zե' 97H]Zf)d2L8knwkW8:_E6J9?+dOɱYSKw%Hr D)oق!"2 3 1C-R|YBO&(̒ h2n=2$ƕeQ7'ä$fu~kK؞,q!"mm7 !0 vTJqSVW~sCCǡ]Du]B\ml6?Bb:{|g<͝FN~(X,Da6oQ"V'κ\Cղ+Of3vfqqq(+Opfr}U'ÏD"ͺ !v׫=h4oHH?2ހ`ޥwtڭAp8hX"R$Ӈ[mf8Gyx)@l;A!-p g2&'>sz7i7lX|^;l7$oNc  v?h4c5|0̎) q=ԙ.^TzHq_ gtIBB4Ǹsl7,Iu1Q>1&<~DQ=K6-%x"*[s::MJ 0JĿ'KmaQYmy29q?~ #"#M4mJ$+J|`"OtiH"Q0 '7W~9x@Gh\@XtN)Z̘rPߺuU+V\im?i]ٖkɞEmsbFƸ tpUw46zzZ[?5ZY?(9{CɯѴfe[5?x&TQ9Ɠ74hv! 駻c=  "vȹdՉGI.[Nr=FLL *IS(( %DȔ0) `o@%Ǒe#F֐˗?Ot 2A4F WBaoŇ$F!=\rK] U&K ޼Ó[:'f=w>Є5 ._TZ@x 8._ t58(Hx`05P3A:ع_4a:09eu[NR\"0uS?W.NZMFe1YƿѴpӺ/2{풬Eq MG`EԿn}$xy6th}Mq5=޼fZ{>蜈sa <h!L^__>g٠~q)6: I[N@[8OkP}y̡ӳ h4! @;S?NY6>=(=%ϪO⟈tH[I[_[Vs\F#+\e@2h{>wϗa,8NP%@qbd͆ dF@׷ xD08F` $p|JrUL8Z0⧘ R':tKPMtK{HcT#gT"FZZ 55ok2ػY5~N~#٪0J`*b{9XD$dU5>=}W,>D:穐ƨ$i8'3HT2QF`x\[Rx:f4$S籽WTd.AV\kDӂI2RW@P,ՙWܵ/|Bd1I$3g TܰU?'x m˲E fm2`M[bYO  [>8x$ 7&2K2L>W~}+,z֑eL)~{@,?^K A v:w]=Lyګޭص^M}8c.򿹿'Dqq٣ d.oFV?;_dm_xr~/yPj +)=|@y~>yv"9g-UIeerrrيO;m }kjG;T#@4n+ @YzSbrT*B/Yv/@ wha7gT<Вxr_g>y׷[$Klx2 EbO~9œ?{ѻ8+7{I#ST-{vΊ /݉e{lH)0 -J- Rko\K]:01}nI-qX̏߿`<y@B?[3TO)r`뛟_3//k~USm}Sէ6!,K.t]&S=?PJKsKEfFE8Y&מ|챃@H)N")rȑ#oiUPY<1#Jm.$dѢ=IAf?$mC{j a" DQ|FR%֏fӖL#pH83/wOK;/KVϰX#dIx\G:T)Yd}vPdWn$ = TaR1HC0"+O.:Y;ȁ,6YW 1y$v:i(?H"m%hЪgDF7FV?BegJLsJGnmÆWe/q>JtkWZoL&⏀ub>}ݺu;]ޗfnQ/XcSlEM/jjxƮIX]mΨ 't?A}3ns췵!aB XdzˌGm0~$pǗ ʾ8aLקnx[ހ@`cWKϪc|53~3[ߺ{z 4IuU_g@p$$oxc{%%{n8>U{MYgA0eV?iayKW pWrKrA6ZʒӟNtKgq)8Դ?]~Z 3W>|5[,Pk%C5չ,r#nYl58Ъm{w)9şp*I"|VuSG-},p5Ҩr+3[||_tѳ%?ؗ\~"~%|0QS+3ytݒū:g '/?& ru+-LRbSfuV?uO:qf)Qvk6ٍg,Wrú~ ȬoGJ$PNَW&FiɫjRJgm%QW7g(jr+gܔY.4~ؽOWr 'BJ_AV ˃*%@& tA>6 5wiF A{鏾dKGA<6~?1vl~mT~q=E̦$e =n[_jw|y赽CÌ>zg)"Kq~.t9X_6_浚gvOlKXD?8Eh\'ҟ=T-*R>~Y}'o qA mz\Y@5uSΏu c՜(c2OV_!P[LAMphİ0Д`u*< Qg#sGv{q.ui%Dn5XP t L 3udyּsM阫h^hyK[}<'&#hI2J)%lӔ"bdbJL3gȲ^2#'O 7h+*=SN' ?i)=iуWL7=j%FZPJ)t<9 ]z:n_de OUf|=N}VZo9jٻ)dw2(e.Rfu ߛe Rט\svO%o|qdn%W4*(~E2>{F$8Le)u|}ߍ=̫ݙt */D D _=^#^^{Ïӧ}W6JK>cvPZRPS"O,fB.]ݪn1t?EuVFx͛ Ky҈3!}Z̶L %Ob,fΔYt.#ɇ1Î GF:?dy]9s\4^Ӫ5nM:Oo?=ƭY--KK'^8|?}+xOX*yr6ucLjrvQ>^Pₜct.?(s-n5r6RÍb$ӷ>'OEg\5?%V軮JRr<~V^1h60D;U~fN&+c5Ť04@H2]pW3M7%L=-/oN֛nj|I;cvK!80_]+b$z,1%T"Ĝ'~l b$aȎI0ȑYӮc\OD# 4(z9S|R[rM8Yl Tza;ٹ)jf,ۭLR[z {U "g,xRPN)+Ha yfT LX]`0Kљ z;BT}^Јrr LT}*#{[_\#J B7!T>qIRI b'ϜΚ dnNW,?d)L`R Bι䨁QYNh9+ $wY 7IWT;W^:x3cB!SH rijIw4<kU+禗}H亲1gq};ůOkk [ y:qo o85]?}l"o1{?pr͂Wohn Nϐ63[N?.I9q*co>Eqg8 dR=5Nl|B^7-drSd"~| Sk1~p$RI fab 7sd j!A)bB p "+=L: (K6X"G\Iͫ]?F*cƌIlK]o( G޷eZ.D*FA']݉H#?:ԙGv3_V}:5;"T03gJHVw.d'=aS6S>dJHfI&D ;>a~~馳NG7M.膍ojݙz&ଁW~b/+LV"T0Mgse!)J16cy])F>"UGq3pֹOl}U3{?vagLJ.xzngU_zn٫z|*Q5%c8ꟷc- o+s155oW 5|f9P Ou-\=2o/[SFԧG&V9%0|ⷎ|3[yɪIRO)G~Z޳\du`S'GJiV0E%udde_>k)?̜9R?Jf#ƙB{O?}&M1G/'OϷ1?;.pStB EKO9S̤|K/3)Nr|KIɕ fqμ 8!ؿ96}[_o+*ʲcL0yDvբJ I <Zw(~62kb7YczipGU")2MF$٥i*!))/׮sqc0{5flɉE!7;B"3_.AUUP'Wyr+Һي;ڢɷل6ذJcMnό ,( $Ef BAzR<: 6cλe|")*U䯧&hL3gz3a Z[74u*~Ɋ;?\̜rHb&YNW&#ukHSLJ6ss+/**S#"8)ض>U d OВs%Juƍ_Oκ{CNJ7mdE7f7m;'WW"μg]NJ6mKnz\*(tJjP 4eK&[g|x_S$M>nYUeCyEr]l֒ !o=v{3O!A*rџS-ma;MxlMd3@Z.{CARk70oy#-H-ax=Y)MwSeu%~CE\eѲVO#yDiAN bt8e~Bv1uj~fԨQO'ɳ<\YY)Mm?ԥ.H\T]ͫVSoM磩{43Q<iRKA[$R f\`:>^!P4 Q4%hнxT\kHf0wް #bM-Dv!u!,}Lxy+sӌ=N=3lCi8ws~0/WHuo=׎+5!Ц4ۻيK2jADHN$YuϷk3сH=qnoQSڵBkj& &=nO3WVeq>ș!4,$,sÚ [a| Sw@4zD G-/]y!s-BE]UtJ$RIhe!bg6҂1%hThjCբ009H8(I͠i`% tf33~xjnɵQE\rjuJ4g|dև/]qش9ZHFlcV ~:+~Oj" sl fʍ8o>הDTD(LSHds +_/W(p^ƴX(u݈1AҪ Z"e?g\ sd=/py ^# K3fyzbm"Dw߭g*?_=tAmF*1;uz!2A ^mST Jmid(&c6=whO8AǟrV973 N rjvKi;Obl1a? qіHjM'Hl|vNr,i#asTS D(%$,d񴱙Ov4&NG*L!bY 55hB>qc5zZZZY.3dPY8idJamH3aLlO8?] =p٥VScEU`mZ$N3EH^IFtt\_Y=7>[W o|]x.ֻzLģR(̊a lZ3iG }a_H&?^ flUS)=,q<6lh߈}--~8I:s!OWG%Wx/ V(* HLב#isvgQxQ[O ùԿO{.h>z]OWP^}O5S`%.Ioi~ Vӓ<߮tf/^Ly%9['OFS(;AZ@nڼ1t/DEXo`Xk 6 > ʀAV6Me P1_I~tf:C/Dؒ-.iSԊ ](3'aF tGC;I0cǎPI+R msU.u @ut{p̲R 1F /GU[.8j{q'+R0SNwK S뢚x irmA? K1MCT@uȲ^8X LX@jVN=qtwnAS/`7ߒ;·j=8UX &Jw-j?]f]x9Mpq'o!'Q\uvb̍#ԛp,h'2CAc  \J,2,?=JBT>0g'&7`Bewk"V AR jOVcQPLx`0UU 3ɶ)U*\X.(z1MGTwCuʲ8eX슿U~S\ǘ[zClBL3309FeqB!;ρp  `PPJK)%\h'bu]0yѢEy)ohqtK)AP JΦFp\0]XXh.{ U$icahu/6^}z fc8V7%p}g!0̍H\l㮘{l )/B8OKzxQ5~|i66W/P\%)oArR$qBC^1yaC+uA8e >w"=-߸ֵp!D;C~ey$u}~ϵc qRZֈQgǐ4N݀e:L]cOV=JJ;Z?lws>1LY^;sgLtqvrICX]0dNF;0uykZb8hF3Hy{&?e\z7 %"iňSz'bu  -KaS[ Wv F뀷cBd8#fiQ#F|]WvԩS7t]{K&3$CBwwMiy4x=ކpZ]8 S7 ]pZB :N~UIg̓jFȷGjo¢^P.ԴYTpan0mlJ qYm]h%Lf<='D'5$k?HNĄϵ{ Ռc+0?kN2 ^FfS~] b}0_[c~je 1Ȏ˝Fwip 1PgXn 4ý 0ers/;5(ݵ"6=܆u䛭p[L8†Dފk:q(<-٦Gn]xUIg-EukȣE8ǚ>puZp|X.p㶙!xn} G HkX842~k Ni I o>ޗT gÊ% o$PU.詹Ȳ=ݹ%Q5Mk2 #M)D",.(mY_QƩZvԥ'(]䍷x|ߚswg -а50-,jєpA,3&&>o ޞƧ N;$j2SV.]J7x[.Z9ftK悑Y(Ζq!NS4) !D2 (y-ogeh}.skhkqu_dzB9Y2.aň^fF>x33psoeUm4$1َ/JX(\݊L{QpWδeyo!>5ƪMa|>EGÊFtʩv݄TXZ9oޝ㳺$L}2'Au=K6ggO."#c4{~wԡi@@yV ⨞*T ?o)m꿹C_lʾeۻ}cM*VL_Guܠ, %y&\ӴUs4gc\pPwSuhYifVLk[d%9*i}7nV3،MN|8GrR!PN1wR&pwύŵ1,5P v3&CDԌ>R՗;^v9'n2=3Kk?6! WAѣCqh F -;öWwo}[NvrSd;\,$zg x5S 2ۆ#ΎūPd!=D͈Lh6PdidϚ!Q-dGOq; lQo8PB(D) M\x@2WC0 `rP f4&l|,K!h9`up.8  5*,ҏCCY3R{wd\ Tm^k|Ì~N&ng>5o<K#08Ѧ&՟ jҍD*4N 3qaj֑U(K} -jH Es, $1pl}I 6 vg@t(iCPC(f4g_o'X6,0ovsz 4$%jZo|bȌX8e`nFa8'U6`u|I§sJEب CE$&д|,fR)&Q&XаAجy8TʏaQtSǧe|:;>o8 `TZca.0Jk: f[ ~5g ;cmNgq٤2 _'oE{ğ'd#*rtP: `~!ZPa^ -@cR¢6˰f s VYpA%0tJL6TBPʘ LEphz @̦2E`Qhk9,+h2A١: Aj Гt{By Z9P[{Th}:jH%Y2~8wV?硥}L bBƌX"m鳹Ns1UU TX~ZcZ|- 80Ń+a °Pmj6!Y]LVw9Ԝ@wPMƬ6!)cq8 @l} qv;>s,hHX( b >$J!!caȇO3B}s}"s< %!&aF~tGa-X} 4*$[V|M3j^zEy%4 ~_üPO42Uh4[ usP*Al`o߶9qy9/buxNJT8Ne>K v58wiPTv2%Y1\Ɣ xːk-D:0̘䙧sa!HEMg2+R@j}3вE@E@ C8$\u/g &%k޾BѪvO'g'|̄1X25@\e -/+%m$N n!x-:I102W0xf5+2E@^~ J-8E`GunzloX  Kd;(ﵳFaŬXaKly 0b! ?Ϸq[}W?V{h4n5Kt R6mtW K,}[|j?<'MuSZpybԫ-[rCxŁz L"~`y1<'"_noV^^^jF7;R\`S{׵7\a%%^y@JOO^foVg.|Wlֿk|ٍ KPā.-:]_w+ʟ}QgY9s=Է_{\>67kzPE6q4ߟ)+?Wo{~LAU s!|>_W˚d}ݻlQ})%޹N‚**Do_8iP#N/ܜnn1WnG/YYsWť%4@~{?dy,_?|@xH' u[6'e<7oƸ*/?(1{_sgg{]_u+)}dnonݎ^^:ew}_\8> W$?[UL%3jjq]70 ׹/t8<>e6,d7 cB`nSV2*bXo~'A^]k޽{wUeUɓ%fL_RҿEDee.xE/$+OU%I06~w߿k!^\\즌>%r,IdKN>9uh>%(IT(jrO~:^ӷW}Y?[ɤz$Yj2 ݊JOWy5x݋\?{aBUTSim zʾgCz sg-UEe U%~A/kig?X꽪"$&qjc~:jڧOYd69'?]ڢߠ-쥔#qMDMiIiK %а (U4綉o9T#*w[Qh\$SQG5"| ?wO ߓ ؋Wxtb?ڏ33֐>mh-Ng.<;k/c '4.7I|^+?bP +sc-G|"!|?;嶋F=8R:&BĻ풪Ou(945*d@A] Bɴ=azM OkV!@I ՜K,fBmY2}5) 8bV2=` <ۙ88<i l&Ev$?]BYѴO:ozv&2OPv+VZOGo>'׷o~u2K%2'gZ L~t֬YZ,=;Njc$>Ze&g.Z{[)Ҭ+2FIDRC}/[1X">jJ.}_h}r?^[/@HҊ ( CKMޘx䰁h߾TT秣t aLusNs.mQX~ kUdWm[N)\~OBBZKXj77=뫫 :u܉e-jmy~~? B-RmN%-tl~,Sl*,@Aڒmz`Ac~ԿHkSQ6aDbZ[~^ܻcRd킺ֶ9}uѸXVkM .,ӳqN]s/ @x},kצ[6vj?#6+/C(rjErѯCbi:DukC-M,[W|Xk:q@ϟ6MMUTuqMk[{m]t/V^ViMo^F5o\K~(חt++( BߜB\I 6"Mk6?]Q]ːUUE+`1m\~?3L0~pB"+Bi؈U#kCX+~ZR+?'d/%|1nXxWWW3o!`d߾ 1΢dw=Ϯ]XA.paث}k]|@4rJ}v21-^~_]{@vv؋{y?@I*h酉TZ3// >W]}־`}z_4oH/c+_Ndޟ{ djLGJVNmj޼=26'Bij7_ȑ' NU5x~sv"6ۆxC~5b!)7[E~HEdVcpj/{t(M{~@e@4(1m|eFiihձ/yf Ou ||f7@ͳOFyݐe*NnϮ}zAiE!K$kK B$CqD E5gݧA PBu\ew=g_EIE0)}-͸k?lӟ:KRfdg_.J/=HD YgrbMx!:Mr$5}Ч \$˒Z2}gxkOA4cbOT~ʯ8,z.m'ԅx4G @ccRC,LtыOg;?Dce{huƟ$B[Mp1&<4;0VW%&Yq!&x]s|W403(%qh4Uϼ735T>GYtϱC,V%c'#"D,\|O{ÅELcV.pE߯!|Oki1&%'~1?]nkH6!3̆J^GN+SPg.G1ߒQC N\] J#!H 8K~gq;--OjYpcu-+d&iɕrM%̗B\<C*ynaX6VRߦH'W)U#wW|[>QzF{}/D8 ynۭ)] Yy 'WblAld%'*pLDc)qJ(\sNek7MqêZXqVE'W)%5k;ǩhA~6!ιO CUVZd˥ɕl JX?=SS瘇_c);ĘcM-vӍ4䧷׉槃k2LQ=,\ǾyC{mR3LV;Cq1iksnnNMkxG#>tC[{=nMIV)?jsn:5}2"޸O[>?zn$fߩqrUVh"7[3'w&?O1SK2z,`9R`սK.;̿aoOh°2+Y0{y}hr%nL~_ɧ&'IӉmVI *+,ЉE+]KQ_d@0ˡk^dɀ"3H=@!hbc4 ޹kuZǽ0ɧ Bd<< [U|zJ7{h5mEsg\ ~dȓZJ 36,z{]PyS}~qYyNGlVr`8(#0CpعpXyy?Y&g3Jif4W~-R~kò:_˙֮WϝNȆHlq+^a,nMIآN\s3vfui I-hQKA uz@:S#B%9IDATt{COިzyqiq)g^I>(8ۢ5[JH:M)9ŒG /49E{+p#Oiv=3{XID~kÐM sۯBW>{FlʴͯIe =fݠ_V[LYƗݨki@*E!5PϢEںߑqBcW:oniG\G{|Y [VoJS28!2;d%CYݖqB256za5qme Ȟ^Xr牠선ma߭2#x;˚^԰rѠ !C>Eb)8BQ T7l" UF$eaMjlNUFZC#IqG>FʏNDCccjG Nv;zy/j\X75d$pF@!ōfġM-MH .oՍSCUBO;ЅF 9Ku]OH\Ԉxi5ѶwbxQ˒5?x9b$]Br` `vH٩<ˌ+Ե3-PH71{풍_%PX5_Z;e}} ꗬ* lo_v*F%upޞ~VH.Woݭі-Cs'W4lϪ m0ddcb\#InWZ~Tz=θH;hU5PiGOCMs="[:Ca dƷ74>h[X;1iIPA ? Y]\EUugAB X.[Ml P7)O_lt.RleJ@h!J`\JÒ}mv3B3[Rȏs d gΎibAF)92cJYBOi!6ø) TfLadGM@-3\Y nFiGd`>biFlt+Հٻ 2r]tq~W@&vçL;وЬVI~ E/B&geu~)cƦGӶ^R DyZpY GG]W:K"s︙7I8N2ߑ[.[.R]fjfy!!2@P SU$ #JBaRA/-/6 eeY۷q3U}H F:bap]loh;$Hy s);p~܇ %  0 S nm~! MV0HF/{nc%T"lnHfHE$Qjc΁7gFQHS-5;oіrdc4Cl' 0$0WdvM% LpLJN_lߡ>!MCJ#ofԞuuBA J2? ;-D3/cl hޱzra ͷfs=?  ӫڧ66Cs竣ݭ>u%(!m50 Fe| (6Z@dB4``4NEǬֶӁvg `/iKJW_wR[DpB`Fe;)&Rkxf?NLi;qdH#X5_z;?i&Uў~ܪ>Po/;|K{Nk|T{1x RG}' /)!C.;ڜe'!F<i q37;އ 0 = nA[ ܇v5V]W+怮G0KDkHвK8 o/m `ɖ7jm3;.dܚ=\ avl^2hY%{~nx UdvPKf3a#T"BY@B!p$=`f6|pE iՏ /pC4;_]t#yќ0SVckHyzC޺>;Ch /6/[𭢶_lL}rB5g'Fu%~ \ c,ݿhH=IOwW%p}Ҟ.V]{pT!3TJ5z R. (pnv/lhjՈS;3N| !$ Khj>" -1T\Zo(G;-aV]$Bj-ۚD sxcJ U(&_K"j8SUYK=8 [q]K~d'$/M:@8!Hp)3xIĞgsA7 RuٹbSĸ?_űk!$3Y}5 fF?%$­mk}WT47%}ldt+Ǹ;\㸢̆vә-ߊvݎ,vAojzv'-.%7Wy 9ur6?T/Ol,䇐$peTn`fԇ^Ow{eDuˮd $"D@xG89{)4X 0Q pW|Q;U 4a6mĀ;8!)$L>7CK䁶Ǚ +0z"tL6|u@d4].TZ/,nV#mؠ 0>V $u!u;IMr9!٣r`W冕̃4A & sZ{iXl0;G $o:7a6 َ>s98蒌xڄ\08pA1*tG08*}q!2I uAZiJJ66*}663#a@RLT~b[] ۚ۴p d;M\EFØ 7+K!1˦"i%$ \Eܲd΍p7 '^fCŖFB 74ߚy" M&P4N(4eBJXqC(Rqe]d(PpZUH-Bc(0x\&no @'^xf89p#P¡JmK"AS8mS09DK8.`$nT./iڔҚ#|J] [>T̖rLhB-p B8&fPJJ97,Ttr)x*vZ -RC-"m4Be3!˱=x* n!7QP4ܞEy.LŠsL@3!9.3hJ@׷ՍP"8L$iγ|BT ?77FI" B$Z"Ip#w z?VֆCPB)%)F4A<>l +mA!@O Iڬ%/q (!BDKLC0`3MuL۝kEH`[],yU -\9eSIf* G;AF`t˚ 1`0Mη}~H'.<|kTP&P@)6ouw7`3Eu>m;o \P=ןCQ)R ?]}0>.R]{p S0 &efI`b~p olR&1/:<9| 3d +lE8佪'2vMdO2S\FsB6A82 ȇ@vs9 2pN!YN볯|$qpU*06@pX:[L}RQ bCjϏ.JfviU GOlwx@mE!%ͤi`Hw>@pgr=4I0(g@K0pcO:F8 M{o`/S WnjFfqq; @E:;&&\QOgX9VM!A5J sm9礭3JJa<#n$fW)SȑUF_C}Pc#?#:W3J6jj?OV4@)7n`ӥ?&aY#s2" d\>+?\̲ٽwmwt3ylIVd C!HuAP BZ?=Cӟ8r!ZCK׃Ek2޺B˫p=IUC7B_ֵ: %-'|!JtE> Ck5ݨB AZc Bپ8^N` ƍjG=!h'%L:^(s]EQ00YkZ^ޚLi+`p>]I:uc:n -F8ȴ}Oק n*4 ΅0or5*mI5-#*Dw=Ew)h.0t mn\eF[Bm儐i3sw2 YEn͑D|!}SZ0v$h28 58)#-pr!ݗqlu*t7snluQ˹J#*2m.qյ? <;ɡ,oLll 1b NidHdND\RiT}n}jKsrib j îxFL,uޓ&?뷹}mjͪtr܅..%@rۆ^c'{RJS¢omVeuKS4_Q`MflnMAj}}<p tzYinmk*.L6t7Lxk3++Q퇓ʒSIo-fuu]s[,Y.{aZL&Hi656ɿ<oRµUa}͞T LvXQ+Z囇rVd\ki졨^9R֢;lV Qk[zsUM~~[}s:뛺Tdq&6t X0z͚k>?:l斖h,IMs<7鰙hH"nx⿞F;WC.yEV7{j6YaH:i lj^~[TJN+KJL [m.=": 56OM~е}Ckރ H5@z{lI`PYIT)uMic?'9=!Y諅N ?* f'D|"[F٬H<#oQTWΜ3z[_iAf=̇G?*(&S4CKIW]9EN @NwOx_RǜdECQyuuac֚_[ڽz^p[Η%:Bu翧XNӣpƒmxT"~ȣ$YNllh8is?3D5Xa\>ṫ|6D,izI@aNؚJi̙>z2: [٫B_ #OOxΑU@!cF|#]#nj?-7og6TKNҏЖ\9gNODzVM"Z*!VXqk $rp_-߽n馱isMxd4s sX:^n@+-bvP"Yb$u#\EE%V#~ک< ޖ+ `O/@U/;rFlt'>㬩sΔՇC/?t ū+Wurw {@e sHHg<,9E 󍧟 &~q F߹U(ۿӵ `2Kp!z~Ob^W)vk{Mn(6Oxۙ FwQ)K6Bh c@PQMTTa.M,WV T4A*( "Uz/)픙 wOϳ:9Ͼ3gΙ3 s͖F{c.0"4W12oPS׸Vaƥj5cC^9'~g+%)l2GH,SVE/\Q'3dfjS#ZG[{[ixfSa0IٿDQ+&% +}NhA(%ց;7eLLV]Q F9FE|@gO959<R;:6&)>Ixs /M67Ah#Ӭ_ٜ~95ryKLf~j>iC]`*Q隔s !Α_2Xj56:%&/HLmtt.ϙ?o#Dl:g}Ia>'~NN?$?Ouw6FEkDT#6?,xWNz03 SB`('͞OhKTf-G60׼vQ04b,ssS;#m G[!GaïrxJ9FLHH'dEwr "./x_Xeh(NM4btܣ3D@e`a"t3 Ac>B)$Qmn$k4}y ReFʋz `E WO7Xa!PJ$qjMoF ۚ6!`6PTd?c$qZҁJGA-ס{<,zW9?yw@=gPIiอd҅/v0O[ЄOcZV[(4s;#R8~xʚ-u,Q.g_nVoA蘨/VU`Hr{w͈O91sǓ S7?H[Yg1E&"xʔ,:F| VÏۢ-ڪ$OF>qY5SԨU l%/=1++ܐ8ұv9N;}TfV8r}?E8rZ$:;/_Iףr,և9≠6gr&Vr?Ο$ 6%SCuJT\٪ʉz-/:h*3`H B!f/W)F?=L0ޤuρ>VY8D.Uj!?_zٵ:$7`xIG >>*d0VXOAEw POP#C?ŏ-2.7Cww5"C1={?o&CB++9IgC?Uq2-Š\~wGˆ7z}FQx''&$ݷ0yGX o_Ίh .9',G-"7{}J#!ύ̘ 5n?ٟ:R4=I̸sO^4=zBG o4<늑bbl~)Hb6vy9SSmq鄡Ax/ ?.ix Xbn|y;S_r>;>^/>ը h+:ͲɶreDpJDe^JO䟨2uzqHI47ߵQ|r.0j`o)C]@]DTHPFcgӓ[U'O0dtUU=n^7!r=MZ]K}|@Sԇ>}d̡1uݟ>}`r~b$Jbk([󯍺̗x"4WU5Њ9G\kc 2Ś[ix'PkdPnCٙomMTbjn $# R&:!5:6ޞW rkZߟ\-<KeJ)1GP_!vbN/?(2NE˸n}:G*>_ 8 =. |Z=| ^G"yU)@R^{*lo+ss  0mk\^EQFԕ,2>e$`g*5Z$'GSuUVy|X{xQ ҹ21wbb ȱ= F H\HM{SnM~z!0yPAr"݉481C=ǂbVAMké%"&)B=5㉶ڻZKw o(rQINez:|+T8fq: l $|_ZGǥIw Abv"$' X[xR41/; z[(+"Tx0f㦠g3z9?_ q, EC3kM̠Cc(dUGO4wş9%2δfͺEcn(ZUS"2c"w8S-Kgn_ϧf]Wda4xcu8"7;B+ʛ0~`{^y!?R%C[Cd6#7p p02;O(y)Bd  :N蠅S+Nk?o|_I :t]UكH t@x!Z#i8  5ůUQ?p ߽cOp/ hͶVt}8ĶEgqVB R Z%ʨJtF:$u5s % Lh&)?SFnGC*L>GtF4;1HhAVy+)??LoqQş'^os_шk5]1$K{ۑz1Nd9BUfyiʩbNϽ!IKn5^øZSZGaֲȡ3 "?Tj5Oq@ozWq67⋩0.ЅG?|0>t[V?YO_FW% |]Tf #qWWRy ;\ !h>8Yi6/ez=2$f`<ʽ?fq`}K.jл O3TJATƺ6I Z̀Oǒi[-P_^Z]!`>*Υ LWPj{tN0e( xvq`KoyC5]ƽ%t).}{?k__:S"d>RV6ljiFk\"U#P.pS` 8sL `—&~{-1ገ{7{LC+#Ʉ>ޟš3x]Dj&'p7H\[EŀM ~͸KTg =_ңV r3蘥>DжGr~~]nYB*'=LJ$,ajN6 v锸 3aב4AkuZ+fir?: )]-)$(^^mʐⲨ8,mA-Fy6dh5ޡh N"eDEvhrUbMyG~%Nt\A\&(pQGb N?2칢mꙥ^:?M/V} ԇk:E`ckX/DG7*êq|/e|633QI u>[gvDK(po!%/{RO!γ` ZB0=q9b/`$64F~x>4q;sFu54#~ :fCNxG%7~8pg4t6N3~EiK  /[Ďc mO@ -l[5v' 0]~B1sxڙxfPO}5{sX9."8ٯjW1b$U\, jlNQ@`T' ;2w3/|7BrF\dRh_ֶXzC c ;`Vet s51h? zj碒{)pBSێ]0&ƶpDf7T.{GZK5к8yX@=?ii:{'*x:<sA 9Bew`JˏЕ)k6B،ʶL"ĺ#H}nîAm>pn???,fUfTVx'`"dhcLt` dH*d:@O)e#1W?`A+_ADNc Dau`σ(,Z'8/89-  a D<9mZO3pY#A] [PK|FO@=A*Cو@TD,72Dh9\FHV f_ ("͆cF]T1QFbuD'1D6cn ʍg)W)CLtOP!Ǩ, A!l8Vn:ܤ!Ǖ4wf,;?s!O#.ջCff񅏧f2+7Wi!U'&^qo@\pFa6pwf="LN(+wi,DGsz?OuhhtBpyLX8G{̟}69cGGꉙ9X<`8M=vآU-Y$00`8P``iWOϫA0j!P:p` &)`ANg`05s)N $i|8]9wO ::0J|٨Qc<)D00DXٙ0×Er٠Q+%QIq)?xJ!3cè;,gǕ?gOߢjA*eyRҦرUί0RּN8 I31_TwORF G_!![QLU)%i?rP'?ӔsU놱>EM!'qi)30zq4c'۟;~PpF'.tGJ9ND N]Ҧ0_)o[Z:HQ8 D~9#* B~D@'_QeUW\}8UUs u8ƨ|_`6l. ].OUѡ/2v]Ouy]ݡK͟<>#Wz\#uwyJə@hoI͈j T;/9d2ƶeUUUܟbSbcʟvy 'Fclr||P0X]RQR3SۥZ;ֺ^߼RILe޲K^j~R>91&*TvV_r~||D!JJJ*/ğ˸-뿮ڶPvٲlJr| !z/[j…W6c /Q;ܣ֘H۪#{t7ȏ}zz]%>>Ĕ22^:EG\ӻݶmCz*5s]W -&*rebt;<>懟6u.V'm&0iMOS⢣VFGDlm G+mGlm-"r 2Ω6ح#OǶuGBBҘ؍۶w̷.g ݿg?"i|bov?|B_׳ [i[c]+*v \1UWmu>MʣliqA236IVUEQTC/*&N;b";Ȋ,8=^Vrh(>NFFFSE  "FӯȾ*EU@(hU ɝ _K:G)]23,ֈaRjr=qM7_?XHhQJnACM2gmw >7P:_>mOQVEU!$i1Uǯ{7_gymwG"2UEU$Y lV jwd{w&MΙF"UEQ|> G/<'~Ewk۶풺}-;Z[v[v5ThK/ UU Z.Nqۨ\;}X\Zg*=V58+{vS >) .^zw<7!:3ѵT51)#)!Uyyg6#=%&&HCD|# '_LMJ1F IA(8^{ j%> PH4kwD_e>sA *L@riS{ޟEzW\y7$2ӦC~>I-gʔ~j@crs |a dĔ'ę($(I,(+ZXX^H yM9#P`$LVB$(v͢fkU>,+rCVۀ淨Eg$I6ITUv9/ڶ:58cHӮC:sƀRS7ǖK+glX뛬][%錚kqϕp0JiR0LL |=6nخVN4h7 ޽1;{"ڱNEv?,_H#u/G]FPd9ҖJE!+,+DF!?#4B՚gcVN)vi\5[yċA{2Eg ,DvOy`F"hjhmW`/FRojdk$0d]AimĮC #s 5ϡ~=b"ۢKVumBU:v81}١`Csq|`ݛ9z7ƴB{^R^ b/zgo@jD^^>CI.622:5l&ZZ/YV8gQu=3C}m>#2CT|E91o+i2jn];PhҚyI79YkEGۘťUy7_Vװx 7J}⊊\}-ew qyF918)t9>O[~R yi C4xGt,5au.kuMMUpVV>n0Hڌc-|A`x/2+kAm25*-{<\~RTT_œ@.m2k钵z)kݻ{&MRc6۳gi T wLҦ4~JW)EvpS3!<(h=t.JRl](pRUt3'Z>z.L-U)6?Wee哼`4DVD*_+:k܎nWcVѐB@9zC&<+"5^n$W&!݇M+j5E/BZ0H\٦xj'ƛ\h hyDs^>p("0ZīklF-ٺVTAyH#hswE"P.ͦju`c}i4 8''ӖˊQYlF=厊bS@n&ip={^eJ]l]D)ݮ6j 1噍a^j3\/:wcw`ZX=gys74qH]],,2F$E<5|sׅƏ{xٺ2Ԥ>bQ/ ~i }#!:=QT&op/3_q]{eukL,[J:7ǔlymqw~Fh[uW輾1r n9cjܢѱk̘1G=PBoCuwqYݵ.Dnq+vvmrmy1 w&;<nצMǵgu ^ /7؂0Y89V0AtYL3,x~? >ܿpj0FFrc/^awٝ^tC/Ov+|? {kwđga??4A)[ h_1],{Kf1ͼ2}5e|hRo9͊fu + ukm'όӰ?eQ^1y߽XA:c\+NȮ~6ʍ߱~9@0>ZؑQFpGe?yGFw.0kM6ؕ;`_=ge_0ď3fMN60xبV{Ўچg߿}ky~5ﱎ= d%_~g4;U}ۆ_/ ?ov,b'|57_ +< 1y^뉢 =ߓM !*BMn[Ә'%[iY؅gZtNjns v<Ͽq([I̛duSYWx0T_^߶~ONoe?~ _2dQN'.8G(q!=肂>fw&4I,}ԽB6 Jr@5 Dٱ&ss l rrݙyU;Oiժd`cuW.شF2d$|}# į%M^t{}F.rd:й~bVҿ'.2g𵵵dU?Ggt#(T vYUZQ ?g;ag3;8d\N(&d~sB:\ۧ\YQ(;j0dB~O~SL[}J V4ԭt%)t{DB( EB:VPS0;߳rFCOQo N;w!v$4 F90O8UyuCɳGy8?Q#^`r3_4-[uZjSqFm}bYh`z<UI!Q_&B_fg_.nIP@Ao Em(OޓwYx^4x.uRA'"@?^VUO d]YmI&F= Rݎi/ vzeY jSld%\W +& T4v%^5 ;>m~>IJ`F钓.2ᆏ;QdKL]I~:UΟV4uZV UW9^(+5̦x%ɀeqk?x;D~||ێ/_|:dk/B_A6JM}2lѩ2`}&N, m}[ Za!uޙ)IK/F$ǽsWF3f=~[e#ݢ |=Yik.ӊ^χn 5FTeʀkVVl;RnҙE-*\g͌ecGj6 jP* N; #ïE4Mw|wC:~Ě|̀kwK5=ͯ#D zKғzuxԘQW@OX3]RGj* &"DF&- &)8 w0?k0j6mݼ~rWRaP2sLh[Jxh[ҫV4thʎ~\eȗՕ^ǣK0qƜH]^/qnW E%%u/b_#Y?W9X;uPS˖y0zM1KJ=Tn#).Ƈ$w 0]>;-?nT򢹿=}?X6Ѯn?dx: MzI0;:J2SR2]sC\-m6MO{+"04w7}`¨P^ 3c״;`p`Αi}z+#"_q`oЙ?px@Z^  s k+ 1<0ͳ)vu\~8bb2}\S|F>JoOʒ)Gձs¾Yإ1 -|Śz͗sEw3q#Y']fGꎝQpJA]3\rsҺI3MX]9[jmeu.(8GAI`lNx.5%!sYG(i˜Uq:a''.:xPfcb{?Sn*1alVOqSLztcI/kBZ(kTos1128O`m%{s[RJVSF+mP!l߸#U-L6Ϛ(*/,n͢7{R^8I)7n/u6pf۫n)֚gΚ8QtatvlF"UeVp)??'G&n-Q֚>&@5]2FRsT`8ipG+9:N(G͎'1$'9'c9SML|FTMgXNLsDMM仼6憧k!'[B c:Rm4#&͖iۂ9WZk"&pC [O>?9MMkt 59_5 ?[FuW [*^A~uZNᲈvVl|&yU鹿k"(WY*;y)l;{F~LMc:RY{m Pq%Ffo":O8eWTeB5Qߢ]GYeolU|!R1i3mNn!eg{YM*C@gB3aӴP~W*ځx@txP*Xu@/B\8I@ϱEwu㫚C%宱 6i7_]{_+UY@οw7ůH(7ꙙVzy*׺7t=!*:}CôewdYXu=mJ( :dLBxN2¯Ն *L/&BOJg4֨ò!)8*1١4&fvGvuf3M:QU˄B^!] Uu3Ӣ]J1;8e̞VUpJXzHu5<;Wc0PJ~ K!L AᢍkJy1 U Uzuoidm/؝obYNٹYGrH#fCPe4@kmu.6Ryīu:-YlNJh< ( tF{/_l/،= V"[?Q=O^~a}^ec|tTt}eqm7n/wc~Cb\t;07lnL,XG=ʿfA[/6iXΊ^*bv:FGEt6Ȋh[ڱuUJǎĥ39ZԢ'P p1V1"vL%|нчr#ņ߻,QYS)zE~fF9FqFH cm1* %WbC^?ņ;49ΨxE8"C{CƑq^R8ӧ⓯ Wb]ށOEQ#uJC8$ <ԟ7_bN*u5W*{4JYlIKJGRԱx~CץqV?\~#8y3=1R%Ȍp`TAk-( e(rb:?rwb`}MW%N' FV?{&70R7pp?@ I8.Uc+|oQ :'!ZBfCIAN&pO`l_8#FCӧA ׷M:ޫзpN9e>"CC*U!12[iV[e^#bzoѢx\-HkT.*ޚH:qY! Pޥ.fA6Xh@wk'|_yjgɺ~0{No5QOыi/vc>MN78N^k=GE>tGo?O1FNIɷ[Y7/ {U'_`.Q6ٱs9& oݲ`i=ozG3~;rL'`Ɲs?y {Ai,/#FX,8MߞLv;36aݻw؟?@v ˟v.3yd_Ί>zN?)}9U/a_#;gDuݥnqdg4?>>?Ǎ͝~lgͺ_ϱs79!Nɓc8c{ 3V'9?2c3ƹ ]Q=Yt|LLP1 ZBe%??qN2G]nE}dƗnf[34" 9\a=%rrYr9(U^(R(DaEEvf۹7$?63s'K WA'̄;l.7f|{Ɨ_ۍxs:'p֓ORF(Ϯ%@ғ/ӥKv/]ԝ19s*ӅŸ ^rP"ЍM)?V}ͷEv궾^.? F1閆CkhUn*?5/ӦZvh@QQ)Oj;~{[\#ۼ|N΋oooŴE߰zI,`jߗ.d/ok?U,7uc j́uO;<TmQt`ɟp,oZ@hخ5?>?;&'ٴm[QxiM^Vu%߼}oZ^ۯ(|%lʪ6ޗj0ՆZg'ۃ"g؟97lc_,;ܕ!?`n~/~.Γ6}-Į)1u%FV<},oz3?cw:cَ>s^1U11؞@Y]?wT#U˟B^0]yÿ}7%y(,ph>uSKsr \m^c0YeIwmj 7GpٺL0gus^*~1i4Y?e߹oc;x;1zSx1w/?m5l߹o×.?}nzŶPeO^iYums-OC(ڿዱ.y*~;5sJ߷=̖qwX:GQA_XH~~hDR {/vݾNNjs;UV,{җm/VQ'%n*y@y^h~=UXò'OPp1|PXQ{9QǥPݡ0qyEfۭN(^Cn~?p;J*<.?9Jw2 T y/Q4e r=D|Ыy".y*>̮WUx5-`6pۨʵ ^b>¿/Jש*Zd~ Ӣ]NƳ )kBTE0*+X?8۲Fʁk=21FYb4rWAAy,iSraԨQ=KZg 7Ϛ(6<;D Y#Gf dĉq3>OgM(6=#ԨQmZ[S33S3zӎrFfذa {ρOSlgRsڶC2m)6ݗ8#g!iٺ3ߒ?i_?٧=/j~bb-Hikg{nv̴{v}租~K.UV)^z 4hSnfΝ;͙3֭[FΛ7Ϝݡw>+ u랛aw0|l~~[vqŋ[XXW dh.a\E/,>~YAU G۔? $3NS)_fdq-:z3˻'[9mʟ?>Ab3it4Gt ?gݞ=!SRW Ӟ>6ׯf3%}a~FJޗh8ͦtԉ6g!3S/[2L/:[tԉ{ UZt r|ơo|4  4,գLm;v{>uݓ"Y˒27gQkX#Ɋ7eAMQOrIAG}C=!Y%>o hȈ2@P@6}:#&Wv Fy^  L=(- &3Ʈz^Р">%Kr6h>$gCCgEB8I*$IJRUudjC]Q_s"yJUϓR=J@Sc;!-vԗ kt?(cFDOΟAc-:NdSTUі=j`4>. ((wsmu>=χ$zN#Kjܪp(`Tц*TE;FbrU=/-8K&N#y"UTVO؎nǣz#gș4h5?HVez@a.b:y%:"$In_dY%dt,NUG(,UQU}YYcjffr4>vC!wI{TZt:dGFZ;5!*ktdڜ/\Wh^Qz&zu}ukJ/ BAB!X]Wǰ`c.PԺ.kZp8$7io&s:e `@29#,dEN0k WUUd9\C@@m_9~v 8qK-fi tE%htՃՑWzYr1WGҧj]rw`0x@0?+&z[t$up1K:W|eTFDq5%vYcwx~&>Ç~s{<\nrMi}zjjvbG 7hѡ讽i~x=O<@ 񬭮B)u>rH1v_NsrN3󮨩y@Q|–Y,tqpRt튌UQQU9\@ VSSsԭA~x=nwMP8Ĺ`͂sHGerq@P 77GiGX2SMQrV\q!jD5W{*{wIh8@UTh5=z,eo[ چ33~u:{N=AxYֽ?[5iʁ2i'6;,7ڈoj33>~? 44:ϊ9j#i + B z,EoW;Ϟ?n0lt7Ni%|y6W>R1W9Qo!8Q{g}\7# ))Rz~^pYltLKϕWUE*>\7Dp`0rs=4ԎZz~ϧjQΤ!PFN7;+15~!~AO{//UP?y_Z=;%`O@~ c|Ve ؗU\\Hq'x9T8w>סC2Izʲl%W?)4okӶ;L/ώtHL|fHh>ɢE̙3[B䷂~iee%^9_CW?Т7NKY|(SbRt{IJO#{3g$iEatoʪkkHC]Wj!!YJ?#mebiMٻ9sfqY3gp-SZYub$I(ʫ55& տ+>kVɜ9ˢD5g,G/%JiWHgΜYl0"i7+8I~="## :w|@n$QWWGjk=ͧr`Y3k֬O>DԤdHL,a>8)D\*BO@^1]n,O%^W͏Kbo5d5]R5R-7DϜqq"Rp#uUU(,w3LKN?Ͼ:01ʲ!M^o;d޼y@ I=:&:9)H9sfqJJ&sȟڦMaAhʟ%fwΛm+aqԙ3g'\ijo}=.Dސe5}֬-sC EJ/6 SS:sJp۳Om8f}[T (#o/eeH̯L$3ʲʄ3g[50N  ל2NߚR_Wa՚,1ug~q ;x#X4 #JgΜYa .Z}GCcmI{. SZtbvBvASょ[ ~N݅iU##Djʏxj6{nS;s^nt]H>#^`Ze:"GFLAJ _='IQbcN^|DZ'Ԕ%6azB~K[neYK\ԕ١{Q`o7lޢGM'rI1ý?a07ݦOMup)';xBIV/\P:sMҲiE;t#GXpFxW}rmI7GpxWޡCvm8E#sɑڟf|N/"zAiƒ$ncc_U( ]O>S^^jժUOn91>\NԸ_:>cъ:QN"%dӠG:/O0}3&;BOG6~ˊ\ء׎^;8ț В 2[e~#Ǭ=XRަMMy[EҁE_ f=Cw~s}i߂x$ɏV.z>Mnz{OgǼs3-K}{AeMwݱX쁻t}_t=C;{/3gNfp('npjC~bW\;xne]^O:j@/ӥݿ^wӏ_33t@ | V tB =6A_Y=XMZ7mf_8}sorŶ.4 v{w2w Bg} yk{ϲ_{n?}8U+g߿Tu}ǧi7޿?Vc cc{߲s[XaޝU.0dؤ6{gl_A:QY`_68cHOb3пKC.c}}RGxƁlܕ;ۏ_QxӔp~=}n?G9V(kY>GV|T<}@| (8R燗2N!MJ0͊9*b~iͧAAybo~r{~~b%V6Lcj>9uNYC^.oRa0J_jFD|[b>.2YAOrsiNNWXX|#̟UČoƧ]/.*;"CqOzQz=G~,ݒn]6~٣yaQNoܡ6^j~պ} rsٓO23.KCt?y%mֵOLOaݖ­rrrcSޜ?~>`yYF\~C Ǜ7F#j}B=;;o.ؼgeݻ"aѓ-y)Q>G5\{7 ~ OrqN<ע\soش>͎SGн<)~ 7.[| r#ᶞcm^q55E ._Ǯ ر\!3|.$Zv5TS !T@Tt_}`Ҍ?1_u?q}G1}Cauh7nmsO={LG},goCH`ȿ!{8,So^зgȟS6-j9ꌗwEbE48uWogƚ'x O-;0tr]rˡ<)yMжx~yuun+^-ٵK.gvzA'mZ/ns[Kv?99` 6cB䄄_ז֭Ұ{Aϑf=M\NŖOhyn]dI|Ejѽ- c ή{<ݻG7+bk[ (Cm뚍sp|.wW fڴQgZO v8cT׮TVܩ3,34f )8i*v0qkW@QYms$=BÅ AԂ~%!=^FeeQn_5<%Fl|{6sگ܁RGMB9/8 h"a-!_F#ZeF3弁e0! -E=mՆlQC+&DE!r."'^*A< tSeUP :s sA砀_.o#)oa}:R>\mQW99|_P3isʫՙi;5BT[Yx򤴊[PR[{v@ ϞBx=}=2O+.^01}Suۃ_vu]}yml\F9Mkkm"MQk߁:(NeU’f~ۺ3ϸk*1Y^BL+)O@H0u{NJq |4`i^sM;)_y)H3Cy n-o'&$3>nPhUAR5͆; Fx۷3OU"x|LpBҖŋ WCcD_ix7e2, >^ SɲT dEq W ;c,+K0_?V;KW%0㈇Ba%Urq| SCT&ܔ( ,o\9UR () 編EB^Bc߸t/]#EEdGANIi1f0̻RKޜV9uPYZj#>:;,Lw_Ɵtke ջ+UBeHd7b2/|[ o+J2V498!K7Fj/b$Og7j;ʋ|3cQA"V u̼+hIa.poZt5qp?~?|[ gNg:}z{DCE|=?۞&>r=`Oub =ީrܛ3nۉH3Q:ݺZzza yg8K3]nv]F}:a~bRG_x{:Ϗg{&|v'{m=em~@`?p@g~$|Vwo-(?žl/|;f90;NG{\,Z&ϭ~yi_ð+()8فقLgfF{ ؝~ o~.7ͦ<%xo7OJܒ߰*o*`bKG _98kgѶ_:>!XK}g?~afa 8NՉ\8_,sAٴ7\J`?3EП{? +OM{5ޥ/.˙"Ƴ_VÓBiA[/ЃWCXt own@sU3iz"?E΍bI.Ժ'c<%BM7DFҗ 8ُLgï6MP~ܣ1QeH㗽X :p*P~O ՒA=&DPJTF\/vسM|kjg5cn<5ڨR'4ԙm*RUkպLkHK|asm~ݱeKX<CEEW=f9wbSWAB Ae*N뚹W 19{zN+|:Mv%CȇSSAerApPǫ+Ոs$w|s="ji\(*b:oLJIyJ>5-JvoriU1OUswɔ#σ;G qi&'>r~4YpM9D@99YfNN]~wf:3A)*tjٹYrY(|b 3'^؏=pO`9D!EKEbHITMAv8#?ߖtS ( \Z-M.?*y-(Cd8'/3pPR5.hM=C5 U6}K_B+YBm2ڸU|Pqe~%Ϩ"S̍W:O$re 3+K-UF2y`jGgKQbɤ]IkZFz|'pGϨ4jr.vK+ Vg-ĮLjNU˯ ]u=ssYHX3VvT|pcO,PsI,)v&_Lʈ w+8[1O+>Y&7\קE|E'tKn;-g'?јA5i(vG:ZK!ɡ3G1"RdѸ=ÞLȔqŐ|3-ΖyLk`"h;f%OaIE86^N둦Kp(t0;h{E8p(s XvOMΖT.&NFo4bf/e9.bǖk}̾x'a ǾOֱ⹋T/;Ewk+VLe֖a~uRTTDs&6ffd~[}e{`}gVʬ+\_ "[QšզI%7 {4+'˒TN7 現..X_5E?Rq֥^xd[L-??}Ix`P~B8>Zg=1A8Q}K.n##_m rӆ5PE|$!4gu :طPZK'WYR[U._ѝcЩOV~)77˂׻A4&áymmXX3mAU"75pSl-򊊥gu8NbݾJ3SUo7-Dm{|Z[vdon^Ŝ9]. Z?cfCMᬺfc-&WU_ }~?Ƙsc}eozwƚɚ#.Fa>c6c2% OcPjZvrG>Ǡՠ&\uٛߝa,zVh828;]oˎ W橿D(< Xf6Tli~ζݏ ]ކߗ"| Q47G흄{!f ?RY]d_;Rn,MS%>$x7}tbZj*~>C%y:!,DP64lԞ-:]qAUQPd3K3@XRƾ|o˵#ӳoKj}G \}z5cyt"QސhY=}g~T`P ËYLv;V$᰸ᴕӧG>Ń0l ADeglޖkO}F<',#) /ؠeY=𙽠@IkԇCOaY@..A)F=ѩ4xv;GD(n/(.fWXk6l϶lyQX` }X" /ܖkwgPϷ9VBdWAq1FoR[Ua[ B+~`bRn]w*>o5Xr _,DagAq1FgRzvj%?\Ҿwm0Z$cXX(O mj:t:]!otvzZPBm@)++걟F<B)21D )BH_s Ibi']}._Ä- BP4-CȒl`fKHX@$N:W+w 'cHL Ĉ Nv?O'aXbc)BU8EQh+SуZ((XhA;L86$S1QBPX'"O\PE1) CKZAL(F$eee';^o1BabrCry/wT$)SU;I݇?Y[u-U[.W q:_S6aX1Rz}1"z4;y켿PB$R SUiNR掎 GԮWueWq:KaA.$`Ƭ(| ws%2D1R@Thaާ]Qt% @0L@FI y8hZ%y˟z{/,yY6DJ 0S|QXz9’./ɼګtL^}ţ1dԖRr< %X,8@8,^}\"L1ǻQ{w,PBR|@޷omW| f}@(3@uD.dm>B3k׀R=i?j)9Ec8H?1y4Sl6aIɑ(OqԧR6sEIL򻏌 %Z}1vշ{8I@k[oԹtׅukYKƗ2׾kھ6hա6op(3.j ݾNQk> 4]o]Â=#g^7n õ>W-?,X˪u/)߾1Bm_?hP_u&.?4/k pG"R *gJH rכWm:1ВFB  ;N%^!B0_ @8 v`>RιWo<{vD$ BIZe93q@A VkOA8[?h̚sS?%ye'gz:;6W7n_w>Vs' 4aK[0a3yGw?eLcuF÷,bכqE#]o]Hxه̉WJWt-џ=枚UQs?&J)}!ۏcO/fKJ 15U5Hw+^ʕ;I/Dp)u^qNv=Š7/TZk$ t6?$]"=4 ⡞O$:Y W,ٕ7,m܃`kD1S`Yz^ ~@I(ǻNbQ#/?,m#x[#/=Fo`Ąohȑ%DpK# YpT?gA*oV[<ަ?.ҽyû/=4r+f) "VuT pp޸S XywvkEo^͘P:qpA]t;{"s+Ư,wCZ͘bXNu17FĶ ?Q l4 hz_=}%{/aQ{& w#NGȎ p!(tm3;x֌IΚkp) hÝ0YP>Fv\Oog@uc~䴍Ǎܱ/oY=?+(,v_1f6\0vԎ}?-N>%mÅ>J?J {?vcM%lnr90fԍS7zD|'7ngv;Wjs=}cH`ȿv;S\\̞8TYzTu~篞jCP^}a+@ Eg[wf v8ğ!ڽ⡅2@EeR/Jԓ @ zhHgcm-\D" +$J\bm*8o#`Q 7!֜de  }(-p2աb/QK0_0ݾVH8=l(r_U(fQEPQ)ƅDb:pStAOWq'H %9N)k5ߜKKZW kMw< N,mo/ b!(g1я^3R$EXF1\n- ~C\-D9YJ.̓/ZU9Δa{D* WkRBXQAP/%SJUچCO{|kr" +q|SP%{Rc' |sSSyaaa.Stz52:\װ. ::]ydWPg}{JVfDa-5k kXZtjVDvEC$?_'x@Q{&jjJ )3OFfoLut嫳A/bÆPj'{ hIW[wfk3;e=0(so@OW}?\ 5W@}ӞA[*VP-fɛF¥xROԧ!3LlJ7߷um|tm3$n }Ōuŭ(=`hZ0N|iOK+] zXo XvZrhƬ&%]m(Tͮק%g4 w~EVbLojLc7ǻ>ԍK|oĸ by Y#f;ĭoUMT '_igXa9ZnGU5gLQ<7جSm*ք|>KuYSۦk1;=)u3kkV}{)]՘oOkkC]gCp oDzLYYs%]eRw^_X@@%gpo>%0U}o2̚3/,EI\q=1?#H0g5X< Tz ΉO{2>O tn), ZǷ2Yvۙ4.N*5*E?GS5B==^='tp3I˔WV1%mTzn *@$gul5/ʬ'SWeCTnzuyxÓ|x%%CQ QT"2o, @N0ǟ{?=LMwM즲w'%ǃ**J5QDæ=,9vY=;''CU@f ?w9ǖ[ƶW ]y#ֳe\jH+K RPI9?_P|]~z}PB3 ahe)$5%{(` O`)vqeUν[R\:`+K"rP] ܵ z죫}~Y[9e )? atgiP,a@*>$UU'>gOόp o\1ìF9[}/K(x!g׮ۏNOcO+Z F14Q aE&j|v7eYVҨxPnnbF[ƕ/VAJgjfTV * Րuh̽S+vGY/.~h]JoV4pDBB5Oͯ䫖h̽_[s芋ng,wp]P'wGO?l pMfff~9'7DQ/fUu\NP$ Ϲ{Ki7 ~_K:^7FXC+$b?  ,:ޅf'Q+xIAKsXz# ߼8U `WrR8!$dz7N))qI]ۚ8O@DEβ;D'=7?!w[yU%3ꋨ7ic(sOdͿ𖯧H)Zz_c2tķ:@A |[S/z)奄Ε2|_<obVϟ ~9"&tp3 1]O|Og[1:{7z_z)%+"}^oҟ?˃Cnn*0&"<ڲ6e@!HI Uqs !_x6;7"6+WߐEws3$m|j HaGZ~@PE9As~t߾?P謧̜ewܱ}OqQ1) o>c{>9~xo[ѳTNֹևN#@%= r 0g&&g5^Bh񟡣GϦ|{qwR#"qf_ W"|u4UsQZ=]kxYӸ,Daxt 4y>މ1/ L]s:..PU8W1#-1ݺem-5$y-=4[^|$Ysfƚm.; gh_͇F@AHϺfҾ޶ar6lׂlUdu{P0%f g6onk\5Ozd6:P]jun:F}{{㤣+,,K^{>}qyT͆^EVz;6QiwZh^yއ{˰OܦA` @uԦWY}gA j εi+I/,kY)۸o~Fx58cݫ6\XX(C}R2Ѫ8 4mtSrKr]x3#]~pO)%XpmXGJn?2yK|Kg5A &do@]KW#%٥ܡd,vzIx!bOlDe8Kn&5}̘ⶃla)Oww=6|&ްL}c;&`ԦOpfjRHl˝sf+X?+Mzkrߤ``:EozF>a{/[U 7n bgkHci)7uݏ醻 O'ZBFZ$-Rqـs(/o#IKVn<ĸke4/k3OۛCNnƓ)Q gZzZBcbqy"C:V mu#֙:t9b wЙ)J#u5@Tb74>(G)DQ 叟yhb}J,-Q;-:X 'K'~ؾS*~QFa7 uޣey[qyK5UcoS)ә7LH=8qJw/kٿە9BXfsj5OyB[6ъ6e|ȢtHm#\T\#o#_(rexmCE*^tt/[P,k_5UK Mq=pRn}k\$f)61׊}>׼2jy7 7딀\-LU9eAN ٺ(#_f'"WaՄieA-xėi|M,m6S( >A"'yvǿ[({@vq"4Th[̠J-&ٷ/O;xSXXP oR+ӳDG} w^I1e SN&߿fzGi$tՃթMJJgX%コf%-c.=iXnoD>~`9Eᗉ'V {~>5<ƱpE0Im4 % ʄϏp g@50,C$ї"DbJAF޼VE>Qx} ?ag9r1ꃱDҊCB=1Ȱ4~t7jXFI;Ж4~kH$¤/Mg=,UAKe)n.v qk= T P)f"H@& 4ZZkC#QN byd<4&/E@*$Q,Av1u"`14ܨg m cw ;,nR x4&lQ̩r+e(T@(x u"NJn@*MUcV/5 BCD{'}搳-mWOj2Ofi^E+h9fϨ1@ 9_ZZ16v3 ҷ?sƦ\$|{)[&1Dc,P * B ?_N,E~v{pU`~00Xu~}vTh4l$Yc`9UGBhX &>cajAõ[}^#XA()5ڿyA0]`8G܌=QU 8,N-]8[0T4n؈=nSq%pC7AB#ncP`T|;0l~DѨUL8,\t&_ Ӧ #o7T5cĭi /sikur}([AOӄ8N匐ӹ44 -;g m);wQvK(MMgƎ;ZGiu:M:cqtqޑF_[3KzCI,'`ʟ>KN.m9g޹;oc]cgT$ _V>vO0M3Ż+Bt9aީG藸ki7x;g8c?kBsUδSN۶orgw]ߤ(^cZj}MӇ_7hE5hM:?Gq|bٲR?coGC]/NmpZ__wf'ɤL%J@B 7 Ӑ/ȵ>L X*aȔ@eȬQa[Բ"C|*)\’c`281-9Sui|Ͼ7>^ MBP!1<Uh%Єwg1ߥ\?|>8!l2#ۄ$[b[X:w/?U,SR2 XF5P8 ?4uEBr"`h/AY|؛BA, t!Pd!et0̼x|m722( qV_wF1%eEѩ+EύH>uI`sqPω&ş>܋5H%mkSaxֶ d-s1ƏÜF'Y*aPp};GM㬳gϾX ?QmNyyPfvŘ/6 78s\g ~%) IkG|JH_tϭjE*cl. +"`:2e K/kV<"G|:$*:ƣȅ%4Jl1(m6qd]:|n OSzݗAC_9I»noįId{8kt2מ+dg4;KS~Whg+$}tP=lkRx'K%i cM"So*~5?uj#r~~-ۓUt X=;.u8-ǭ/骯hU [a 5t3V!B^-Sw-*"d"RP[GFb5񃰨$0jc N#u~ b出ġez&hA= 6>~FOk9Qk|<Ҩ˭ ǻO򯛜b7Ɋ5nϣ~P+{IIx0xIJ5umM-q.8[QE/3pPR5.hM=C5  6 $FDbT 5dqe~%Ϩ"S̍W:O~ Q.3hq6[_gS=ƀ-1]ss)'$Q[m\zc?`k>ѵ-LFhGm+W̻f`^ޠqMu :w_ҿʠ]=hh>g_E}Tcӹ|G=\~!u]X[_}Ʀa:~ 'ԯ̳;>_ݕ3PθQ99y%ظ̎zyu[GaӲ5=7*`dyh6Ub隖̄QV.lF7ĔK=oR'h>(8q0>a6)|:A7Vht7i@%w a ijqLpXǠ4ɘsqw) A0BpsD TPY4C!zPQD!ڦ}S Bsp;PIDG_ɈÓsqK =! 10,ׁ]~xR|x.ob(z1xZ\\~??>L<T}IDb0d:Mxzl_Yu G85ID! RF6oI31}fƂјcfn s1A^b DASTTDs&6ffU۷kUY3^keIۯ~RFjZyӗDV;%zܬ׹GT,KRebJ;/p8":cdXVwY%C}*sC`IBz+-eon{ΟzckWYy#nƓMܫ=PyLJ6[b'-?/&oRb+vl9>{I|❡PZo͏_Ql :p@Ez9~oeU_wI#&f!WtVU]r-Vxyέ2=/"0H諣h3A+q ZՊ+𽒇쪃e pKW.n j3_G1Ԩ@R(a0uXG;;}εKbegAq1eRA7cH2+5 ѮxXpI͠k$WuO 1RQ~)>bw";j!#;Wlk5>ժ K[ /;:SęjNx׬]0XĨbU*"_(((RRiXvdҨG::2nEb6~ڰKD?XWtA "GdՏkPЋvrcO2,{$fC9 }osp$+v;5R2_kKCnk6,u"㉰8^eU"'cI]0n_ьq;J\"fngӇLC #eW:Zz#*Ã,Yi}cOT}􃗈5u ۇou8v%SM/7ꮨs_Rhkˏ\$)vliu' Ϛs+.bׯ!ʺN{ROO.).5{ߓS 5.Ya=ooFWdAdZ  -V_34r6^ j=:cBㄫ2f bx&F[ ^$qZ `_|,h l*5Bk`cZO&'\L!Ɖ\Q(G0h~&,?u50yXidʟʯivLxDD#؟Xo4G֡иU OMO!">0L@v맰~#Q 4J"V*n?_{?XD" DjÚ nBIx~VlBFLvzWd$@J "ʀ"wM^;∍>y_`Fݍ`׏/ 3 [?@w߭Wrl57?݁>25d[+ / WE=>T`UR[x:%ge+WnϹ&ݛ}7&KܿmqE.m"{-:>zpX8Ge?a[xz ꯾vC?[1֖/}96 ! /Ju áH.VF"|'q›[M]2Yjn(p7l0[ښ=r%n^xy/0hE zp0Ҵ>C.C,,V ?yM 1g珝uQ^>4oMhon~}ߚcoNM4O 0y:j!X_`[c2ڛk͖))iZz}w1憥S8X CEB*k >BPa`ekHa}hQ0H7!Q@^^N "XX)XZ4  "? @l߇FEc8t2$Tx$9|Է?``Ha/Qb`xJGxB(G;U!&DEJߣ'sq]bιWotHFu-RP 2s%g$6i$ɻU 3?а#G躊`KIֲ)"0z˲|g{ǔ}~uт-w/I<2weITi1g:[iZ>}̙rۖ$$-tlDe)8Fu-Ri;~n?Tݙg٨Vn,WTsltwg]:N)t3-9ζaAeVinTkY? Db;;9޼8{U*L/:nkBvHNBJUm%ĢVnms~zeI1y^ez˲gD5v]X1bc>u%I)t6,k&h[xv>_=21Bk@jea/ʊr'8o?Y_8=}So_6R0vXpE #Ndh0l.KB)GX!H:ר Zeq(O+J͂l2]A 00* AsXA$0>"Ea`cX0eQ -Zdq$ǂGOoQW@vrTY=>‚t*(D0ʤ -F E $/l *B'5:A"V0D"ݣg\s=Z@mN>}-]۩ЮG{eD3,8 FI|;-sGOYpZfbE$icfY(#VMEK1ox.^QȲW'o2g8r$Q^Su}[Wx{|FWzJ)Ĉpv[xU>ò;w(io3[t:íJeB _>^g|Ճ^U$᳖7/]~EI𝛗R7C3u#jF^RE( ={S kK|I B(_r?qշJ8xGk͝kaY&G~Q7 143~m+Z}Lkk{?iHݐYBD ~'YʛOivpi})%UコrOlAz| %t%OV? L^ @>^S/jOÚ߫쏜9?oˆH+?zi/~7?i\RV_Gv74/Էw+8x$I9be adV 1,`yJQC*υK` AJʹUA>Qi 2Xo|%}Y%9?fصk 2DWA>f#ky|׳AwCZ i:'pQS0t;g 53*[;Nkll8̜D)?Сb5erO_wm_ ǂZEAj1%NE"y.%%%>.XK9Nߕ%70VI[b KN^< VY-qj|D?t?q<%VQ$-AW(>/P;B@}a΂a6jOJG~n3v+۹]ng@&{$s@VͶ"7=yA/%J󹂂/۹+'yp[Š^ItV$n78 BR{>W\|l+'nߗ{őg@ՄqOlVKNؾ77Ğ}N<1 of[v{7zA`x3mnJˮkrtMn§v06gj9i]! I`v;1 v 011e&6Vu'Ax?K7uI={G/Lmqߜosv;b/?$;Ρg.'OGRrݟ Vv 7Vq =vN?C N@kG #Ϧ9ΐ&#G(5?l`xw 8:.jȔQ'Kg͠ႹӥSSA{_QtOP"r9s)dZޥnnϳ.kMIwê}߸%s'YW?-\ tc`+Ot4 =/]If&"eDGꂏ[BCZ@A!IMNăMM充uXOF@rI OR->ѳ)_<}-M<.sL̙0ptG\1*?Hv:݌S\@3=A穡)1v|4ZY,½4zіJ}uʞ`DE11 i~oFbSa`Ƿ%" {BW|(!3͇5Rl OdǷ鴺HO󏶿e:C DTذuFmQVXCg *~* %saaaڿF:i_{G0²*IVX/\xހwH4BtM/=K7QuY-1KeyQtY\XFūZsitG?xVmv;\)pиx7{ _v8@M&^6~DB%&iHH(nړ@ZQT˻#5߬?\w\鏷Mwb?VML?eny&a ǘcU\%dj# F/@R4,.}+3R3UT;$.4jau[~-ƕo?̠MO s2#1vP3 hTs4l28R5E=qAYRb{jHz Z?fX-a^h]s ,j͒TQkC5Kx Bx_x[ZMZsUtLJ)H|ڥl)'T:xU$:zh1XFI^7 =k%ytTN :WtJ}]NCRujBሧEѩ P“T-BdOqA[KwO5|hL|_RVem ksƚkJvw/wUI5EQ ˫LiO| ! -.fuoJAJSê 6ٗvIMo;R=Wu<˘67> J^@",ǥg{ٛ/p8vh3p4n5H}ϒͱ ngxb A J`.5=eK^”3>@v}QL{z.~l,wùҶ#?Vosjz]ldk1s wt6=vUs$9Ӽ)y˅*b XlYN{5*yl+hUi!8OJ A$n}+@$$y}a9MjzF/w`u>J$b3i\B)O|mk6bP;RpG/D|̦BC.R݃NvFb,Jm}?4P"~>AF×n%Z~@ҼqE:wp aDF: _CZzHzيk.|msD Z-_{[~hD5Q Jjgٲy "y@UoY[1T!zKG9`C!P0,+jU*ҋn?>hn( ]zl4\Uo>%Ow7IRctW4@>9L"EeS߶] Uvܩ-(h*;5 W8hi)GM;Q߾||n9?6otQuqt"e +E-g6qjyקk臃@By^2,ת/ճN9=^+@|ߘ,8)hd((B5 }޶ ȁbW_%_zF YFXe۪;U6[meqDJJi#Pu""AЮ](Rp0jkixٝ*ʟ~71B# |{އnfmu[-D³;΍(fIDATss6"kgx5ο>A o h]QÞNV<~,C,2h޻!nإalyAQ[wԚtF2@ _b&%BBbiۻЧ6]߬< {wPg(v3:VَweWp7ǩJAJJ OÓZU(ZS/(P amG,\fu=Bcbqz"GvVۢXګ# Je^S6Uǫ .o2i|P(1RH9^-ʟ>8N[dA8s5ڤ\3tfY$3~.YL? 2TBс0~ "%<#=Pl<)oF&Ďj" F]%Z@?/0cnw=" p5twS`Z j?L 9 a|}'p*Н DG->Ts*SOnQ? &7t[[Tpvl[!aat(!eˏpltp!rq(^/aèP9AH9P_[­޸niQLU1g̀"FCgSS᫘ǭuFD7Qz!Aw >}.JY˄eb%`JJ=(*z7N:89 ;ՆhMm*~!i jI nVA'%|#޳~nY 7T6蒴&*ƫu U3A3mC0*4K  g[UbuZ(m*vaFJL;`tė} $Ӿ陯"D+cu ZEnSx̐d\^X{A*=0n|)V3F 28vfXbf?,C >,Ef ;i)Y991aȈHKN` ICFx*U(}8?>Fj5dBQCVQ E$n/Pi P1adF;Rj.q\b1BDsk@rGN/KD$bzc,"0  3rU͛L0"?5U^ l/~_eYр t?_;r$7cXb},1I18h\ Eg(.e桳0h{e"be?&,-tU (Uj(eBǁz ~F5<( ! CRb2p>nfhAX< ߤ D@-rGeCsP葓 K(FP_I02!d̰NKaΣxD"'Z[Mfǩ10\Wj >C%p͋@fH9cT9R!Ek/|W?4 V j<]d/PD_?0vAq_~]2U:X)OȟX.yQخ67K>0ɟ%"f%iђ?w/JbJ;X7n_G| 깣3\xt/>)~eRPYQaqZ!H$C*|>q=fE/ b,VvNEPYѰp&/VngXPJPn[A( 4ჸ{g&ES /F *ThӽZOSX,I*Vuu@ljXg%h rr[246\L*kbL;O _$}X`.af 0;10q*a8A_)%@ | ۉ5c B+cqn@ KJd3M9o@Sዦ’[Gw)J2c E"d$!YXуZK\VWFl'*TzĹyPDFCN5H+"@DJeBT g 0A$$uT Ap`P\WUs`#pZ0~Y!Oa"  OK"2!< .o[A$[q y ;R jx[=&W`ԇ4Dc?i4nz"6;1*'Wuq^GnN ̓1W1}T鏠! m,4@\)b2|*ZHHsE_e07 EAg8pm>Iy{+=29ա7q(fl.6۰j2L&Dĥ"fXo@o?#̮y.곐F- %X󕬳SZw?}{dڱD[ۧ F=pO~b&OO\65뵌C_>{cMv/uO}h6/8׽_oj̗>{,O)fXW>cm{~MZ͗om^Qψ,aEģݐwkV/%LYB+kl1CE>CeH`ԯsˢAѢM2& ~* >H<a9CwELg- 'R H.2>lhZd[߃fJ$Z*<;NOſ%d[4ɳ CwA\{_j-s혿uꃍ.~㳓]y.{枼2SKLڵ1yȳqZ[N>~qF@;} $`܆\FL-d5ot:~I)d=fWQ7ce~YpcAmȋՂh/pСQ{y&-Eg6lϯ(88`SD- yaBdՀA #kU'[xxTy{qn' EcsL0ˈlqJsƏՀѯmX?3l߯9l+F0zk3`*g7rArrUj ֡jQUi{HB $ +:QUwYEw2]7cW%AA L[I iz%&3y9Ͻ$yDC1*cQ?쇟%p>_cT*oDuaQ lbh$Ql  <(ڿ+C< ,ϧ5ɒ ݴ%vA]'c d%P0[gҤ߲irGCSûKbfsg}v}vn p{bȌʉv+,,}@I'rx$aI("([Ja ғD1!Ōf}RnvbKѢ K|?}$(\Pɉ bbcA&t˅-|a )YOKȋVG~60I&=KL;鴱/| ?d}KE͠""MD &0}ŋ~p͛J/ʋ6> s d#cؑ6IFRik`DeCoY"m$ KN1O5X@c2vsRߤ2eP%$H 6@D"qrþu[Hn(;2 wQب"`Ci\$uSuzGyd݌fpp-h& |*%$pLĮ\@Dzl'kFxP?lD24Pg{`iiҫ]o?9 };ՙQc%>7\ 5"Kޚ7kҦ 洴I i =b];O55J?= ݖX "_<Ũaz#8i DE=hCWU ,#5X3%ĖLZЈԠ(*8j*޵ք!I=o_p2FKQ\iZx,6o'%WWbW5)|ё^j17,|'mؼ?]865|5|֖ͨHu}{5!uc+:$UU=T\<9vnelHCrZ3-i8nԮ]͏?4ܯ~E=] piXg34(pՒ矙(rTf`Es8c&=3PןY<Ő`lZ\sR%[]A$3Pc0 !4r9]]MzZ-p:۪많1ل(餣; Hةf0sFBQ' p*rad #a j4izbZP0 8^ 28$ C&b\oTd"7FDp[ U dPg<҅8?"sH2ǎ@"+ qa'DjPA|: %4ԟGIDbG0:0PuH"Hi 2[IӃȱ/i ~#WA /*9: H>ܦ5lޞni1hja4%„qˬdDn {ǻSuvBi vCGxbaQ%㔂͟~G $|h rZQ0@DYĎt~q%7dȐ)&id[[!ЮѤpRiw ŷǛkw=ۍ>eg[o"4D5ƞQCD |ڗf5rpLUU2wKU;>l@SY!taEPTn|n%3? Ԯ=d?TWqQASeJϯ?S9 |%T?3GS-1F aj 0כ* abv x`6ͪ:YѫSY*"'l0/(ʨ$#h)Z4f8$IFD,(Z@+F=Ą6CNfty# d&"#l =""Mz(5Bb e-:FGцZ`6ΙЦ,8?ɤZoEd(~/<@NDmF%$55> *3p$"Wϡ9F*jFFaAfty*T&[j|ќgK."dnK(4-Eo2`NbILRvp`֭hTr22UUӺw /_~yƽxm~K9;l1**h* e'|ygEWy~nSL&])))W_Hd!d} 7r<>-mpԅ),\(oݫ< -]xq3K.`ݲōgR z4Q.]/i$zn1q 6RINfNDdGbF@4&Dp<|:+@9mv5!bb0<8="^ #LR9v^HAH8F)Q ǧF9pvC(4 !(bJ@EvSko H0_櫪F f#I7@o R:%_;]G:QE/t&p4yTU?эiݷcX(wtLTUVcԱ- ;dT0Idj`ܲo_H _ n8q⅔箻< P 7`/*0^5j+? lذuBKݯ~L{C &'tUR#y`eWh}\::Y!A钦FvBps;ֺ^z`ptMS#;wpp2~5`(p0S ;??y #3 Y^;&(Cߊ$@ն!FCdް:w'$$L4-gl$n7 \M]]'Sss E;WqON=u3)nwRG5UţJSO}=+V1 ?E: !$pA!Ju. Ps͌8>6*{k:uTIh}C8p=ۯFs'M HJI"cRi(Fs`I4Ԓ3 ~h )M)Z2'=w<-f4MRT)%vL;:T5%'r%cGG>|:Fd4E`}l}?;5Ywվcu4|R$αc2EF̶wVZ--v1G%\`6k1 ^؀xv, JmiGLYignef7ݙq& lgIKLI5?|ճ;.0`H5x{H7Oo3xb=g6&A`p88ۭ;qD{Io ",ߴ.M:bD͆)GpMGSn⠁M1IJVw:6r#; $&@Ic4פ^o~bNe b247d&&ܙ`ZPP~[w TcZ0$p0`2#qA>[ i+u(k>cQǧ@|ݯuE6Sf aNr]#vv\6 Pitr'p?*aЃiZN'-w:?5uT_6uR#~G#FlC՘ZNPg7[Ѿ:l`,u7T/ FcJX )6Or;:Xn`f4DPT|!Q(1LG.% Ò0PR%&/$.Q FdMR50u u}y~똨#fc:el@͕h%Ld$іdn}*C 91Dy=+>I0Z4ÿO/+[iLaLF2pDz .@\g***]9^1/TTTt;&.h3f@!>Ӎ磢Q:qA;y+_ƁPEwov:y8Rh;A;E/qwPP1"م)G /?n=#`l\MծX"=u2.-3"rFeet6RSt^%s0CrqQ6+iQpFc"|v/>}̰NxG?1sЯ13}hQ?c ) #X*0>bb^"( FL0ކю8S hk(K4ȿˏ$4j~M_Y`%-U6w:i@ .P\:\< gDy =/<+|;Joq~KuVGi1.^4)ۤ/sUV*QQDQ\TV(1 SelkO53U!PqqVQ ߫{yusO9IJVD@|q9F%Fd4s- V靯oh 9Cβ[73 RTѨDf9 \n`No6f _`_ǚ B)ʜ(F年tH;Qk9KwYF|$1MH`I|Z& SGUtR*҆6Ҥ8`IC0Nb 9#pp-{$Tt.ĭ:N7gO>T;L[vO$6kZzj#=i[!jQ̙_{N~l$ Y.B%ݶ8+5gNw2o0Rrv*+I8;hގ=k*Y7g싅QE)>_!q~kX)#qgǨÂnvh."J˔`ſd|2ligc9~YΜu֥ʲh8XFnqƞ1mMn(n-73R/2ץLFv10rq`c|-Dq~kuu|AKD]O\4y\?*5j_F.>nق0ET`FwߣaƝ,cvTԎI6~*E^pÕV+v[^~]CCxeͯcuy4YiWE|\J9@Ơx&]o3.?6ouik͛Z?#G䏳p\ջ@ۯc%D7( q)ڶuu}3q+,IAe'yYD^)R0Mտ&.+ίzkjBf}*`u0Sq%5 7y6*Z?_2YE#].)2zm[2n%0=\8( 'N>Y1oi*8 %w\5՞h8F-Y Xpa1sʸ2_9C~$meJO8"Rjj! i).>tƔϣNkO83}H,!͌[VQ]w@f){{f,NBRlyUY{)~BȞgZh>Umil<@I7/Yg)4cPz)nXƔbgk<ķѾ|ڸ PR%Gyn־-{6lW]ss[>Te9Z^*?Oh٧,J謃-{@HڠTW|㎹+L[·"k z?QMp;ϛE(f{HZc'/>sd9&?ĔTQQQ]E^nE={'98!$Eml5CG\tS2VXXDR[sⲤ,8"tByLUP;;y߈y;o2M 3*n b{K_uX摙S_chͦ9 }r&FQM11Ҁ b9 "Rt⨁!A̘iƑ[=PE_ʝLw]]?v̐L񇐖pf~U iRpPPbOBWszSF1`ݪ,efrM@{Y*Lُ^Q[R{D٨QjiCM=>r7-7" b<^U8m +M\L>|sj5kn/jcpl_ Z=l晌5!o/nMqiL56hO5$%^aSo浻}vq;5/m\[ũheL# k˥zy[׼yGؽj֘-Pm&NgWU%7l52d[f'Á,Con~m_}Lmqf !B}UC[F3s3S.*Y +< #@AM $|t\.^MlYLKZ4aqz!~TD3( -#cet%ێpweZ3/ץR_GHbDŽœs22.mR)$cr)U~ք}"a8&/ȴEitrlF~nfjj5 '!Ȉdp &|sCQx![)K}m[#h(02&'-0$6WF/R9ʩ MEïv3#n3)ԨxC=H!6OJY`"s+ߝZM0m;S)39LO~WRS]*9YHQ4^7夂F*{Wwe@WɆ:3 xgRjN 3Ⱦ`HӔ>z E$ZZ}"Og4)77A9'Ȫ?R$񣖶:Ɩ踨$+PU[&|">:>t)If&ihH<&)_D'˪70jWO-_H|*p֗ȾLmȩB{d\:y߷0|[;ǵq_|ctD cg[hbҟj3I|dž^C匭!PEsRwnJHS̶0b2j3G2~w:)J] `M;DvM4;QoC Ʈee\EU)v_v:bqVhl6iv:ڻ9r=6`v> ڻUoWa҄ٹ Isp|d~Gw0)ZE݈ sa:@o`"/6.s؜<k\KxN;}ɯ4f2T$BM_g.to"y]KNgEK*PO7JpFa˝0LO\# ʀ(k%,&3} %ߛ{rdg~a9ޖt g,E( XȢ5_EP_X3r9e3Tgc i Dr;y_5g?c4[Th*۾Y44\^g :%#1AL#-b7!9xC/y'YpDg YCХKe_y˹vNG0o}W[7wOo=^nEtBy> +jLJ >0w΃7C)oQ>z~$QfuS2:.?&$PMH|QyhW ?v 1 G" ڇIgGxce*%ZpT?D#)/TFu@ D5ՠnS?ȑoSN(ejm9VV4C%_$Dn2|?J;qpǿ= d@2!h ?,wFKU "BU0涁fۣMͪpWH&9qÕ;*s{@=96Ϯ^7Ϲ\.))eK/_w7} Hm0%9CɯW]];lvb UNqIm_:$ -AQ ONq_^C+'{~ȵ`vIo Ұ1pցd6˒/[1kyaXֈAx./`KOFeE}= taasA)0Q~wF>ihD5>uz0 BP %}|Иu@Q9p-jog)86C<)/;Bn~n}>gի2[SfG[?5ESBW|( hg*`TE4VN6K!Qh0^G J(m]c+[eai/Kh{m`T * 7!Zc{MK K 嗗;b9ۆ P(,*0@:1tzZ_3}s,Y' ?+K{oMO|("I ֑È0'F?fWd09+/Z4/TZ~9zuWm֬djYK=?Ϟ`s >f;Zkuv]C7fQVzg?R2%jf_HvG{7rίlS;q}g,Km (D?4r6ˏ;"4|i@V~ω'G  {vyI/~;{ɹ-Gi Ynx˿~NEAxKSz)gHýhs=O9ʗ&?ΉgƇ ;5.RWSOY[ 6LY`3='ntUOMٯ1,.…?"r<¼hFx8 G #6-Q/&(${<U9!"ܾ1YC-xmī;W L>080Sz!nWySNJv PW(ӏ dBx|H(q" oޘn c]t?9H3FػDcHELx )'fg/p;yؗ4MU9+>j%UXzC, ײR'4,\z'-~Ic*{MR%?J ,`*RRrO]lN%| kk4tTDROwE _@ʗIVT*{IaL7) à:-+%_P ^TM Jdh,- C-FN?$kPEǿiL_#Dh^Ksşu^Nyoj IzWCd3}現Hc.ݒK_/b,7î鄬l{dN4>[#LUi#UfmZXmjm~Haz/V p1EaxQ6n`σdƄmKܫ'\!vLym@Piw/{Ft2,Nw UQ<ȄT/qBΌN1NHlMˠ݋l [#om ',M4D(6ab~ K($B,iM#3; ɬ;'<4QG.t<X{T5ϭF4GJ{nw! FEx\TTWVV*ųN54/㤃. tɜ|Yחg`7M郮XL~Mh>p .,. ?_on7d^s_zKeE,\-]EKj_S;5+ NcB]K죹j ߱u n'P՝6 (\YC?{}3cq߿v>wJ 4ykcLBqѥ46~'wƏcR ;9~G9` "t?[e'^3{F: /rظ;lfE# l rz!¥TNrr~ƌ+ٷau_<+:iʩx?4%_qz+ꄷo; ls{2>z_)o⤌< QZս7JbM1 bqhr v+dƬ\ 9Mm"3b MJO^2^*hD K>[!"䦜V<]g$FX(܄vϓ .tGTA zS3Z!+Ldm`>BQhh}O^}ᗺ>bO[4l1#Fq:"\zFcM/>o 'f<(5II_奤6u4SC#xj iP%X1 7HO%.ySDWo(7v#t*Es8c&=ǖ LThe g?"т*1׉^r2CcIjr]]azQxÊ=L8Ai4tS FcݱjT8gX9@ bdJn"ロmpf4}Nk7f ]Wz|ƌe]íR:еo< ^-?q> 5.]/o}jdvF:RKm>+&>hӛ-( WKJ ;D[_!3G_wKgg)`cva3Ӳ k 3obA/Q/d})x #t&%EAT̍c*tzvBiGSYd5-#x5 f:<)N"Z0q.vU 5Xҗ:6Y!t $ pF5ybӎ?+"΢"^U5UVJֈnXs {J}h䈪Ǵa = oٷoc(OG1,Gky]|qPy/N(;R NW(U cڃل#HسT;VOQ:杁o"1h*tƀOS ͉Roe֟ _G!V9X<Hc8=ȴHS!xxB M2q,3i\['ƁX9f3Xe߇ChG I(I&ʒLʙ\[Ʒ 8d,ɤ$pxB}H 7F0^ {ل5i\#oǑd=jU`2pG}^$Oş+59~~c$x0PkexE?[?~ccgI\__OXtFCv l&-Iv HpH[Xd"$= I+>A̬FWAd7v8ILYc'tX?8o&}|;66]0!`GibQ|4TVz=ﻇ 5T5L X(SH[k3&nia#?h|ߑūg 1Nk* `-^ϣz?4p98B3kiڀQ:ӧƏG0X,Y~(JP䂓? 1R1w& s0 (E顿)v~4PsD0Cg sb2~= %̂QqNƂ5۾VX ,r^8N܄4$5?M7vs3sv4#p?6?(5qiT1I}tq?ZgR8^|jzwБ0:f7~~?7"Prsew=:1Ϸ8x?z+~|\|.qVyw?#AXpLHꚜc8AP ֓,Qk|'@\{{WWwdϝ;3g<(P$<Qƹݽ8q;#F;w _pވC߈Iy:ɨ R,ve]B>^|K#јn]=/aGY͉.? >t1I2=p/!;wM셃>M/sK;pE $ {ſXaa -mdKLE1^ph18sv:_ki0ǻ>(gG^LwfO?-qȒF3J_WŇ?ݟ[Zs{ݏ?\v˓4`1oVٍW;lxwGRg'_y8eg ^EC Ԥ1kRߊ ?1'x₲m^ -j#QI`p~tn @Z. _Ll8`A;l;kn0=a{C%.Bhu^o,wmߴNC "V1ME:g*bMڪ7xv5E% <aà{ݲ Зtq܁iwuMvquRևRSS͙t|m;W 'F$}ۅ$})FI5:QhEa8BTjbl5*{$vۯ@X(7oc|++?Ͻ,mVK*7+mǼؿOEkVz',a~$X9kiNZbtrFz Ws/De5 1DZjڽv̿nә?mr/<+1hO:.sP#-/J'f:9+3GEh)VVVơ|";-$俶h-[loXWٱJzw5 5|rfz-eT[?iPr iJr˩i鋭 I7Tq6\۶ο~xONeec[=eZ SHe2≁K6JKLFG$P-{p@ڤx~B'=zGLظ_ТQ0\׍MuFlӗX/𥍍TsDcw>:#Ƥc-[L&a^-_V6Ӛ53`/~~7?0ILHs8l`0 #8կc/Aӥ%(* I٠#7-/ɒ1*LevVrBl2 OHxHJYzGF`0~=X-Ж/,HR$M1)نz 1w32`G[CFYA F>h|twwkZg0',ɠ&AXPRWh'|-"3Ü1]>UM|( )"rO]!`c&>D#eU1=)~:`V/ 1Y$,$~u+JS|9BGbD," J\JH3|GPYk/+LOOӒ1@+#9kkʝC!ccCFy45 CKi#?zGд Ǎ@Ғd bLn¢es^xPB;Ҋ Ifl"0)& bM[t:{wWx~YGM (zM[s<)˗:tưTz3,Lښ6Ft )x}# SGKt]f \k"15Yswa&&~_V6V2%PNOJ2'(1Qy.-]6NԚznN],^X0q߰^-&NV}{>$38i-[eN'Ŭҍy.mk#-Mj͎s 41~v|5 ~H!?|I$ #KJܪqs6nsIJ^cδ%m?M7}r֏*gbAd|dk;w{F) Cբ~U 3oS$DY^Aƚ1do D9ơ+~7WD! .o%i i:pcGRJTĐ[& (mT(IDi;0kկ?J@H('cwtڍ~< w(!KdTU512t:u|b?}Ko4$/Jlk]&sRB\ŜNP>%%)q(5hie<29ֶknicN'%]@A2hB?>ظ糕|9eߢ׻Lmt:`EiV!)'D: mI?۶za| 焝ypIfcʀd!Z~zϽ/nՁVwXweonH_p:;`B;3gTq ۞Ȅn%ۚddN*epA` 8י EMOd;3gTv5mnP_blZ@އ = hu9qVZ`RNؐ~ve%e Cd67/6|q?Oo`k~[q΂\3dqlعO#-bǟ_\cwJץ$XhvEw\ S!23yz;a ھ վ~Fhji䎫-jq)1mgÒLMJ0pǶaݮH}~T~Ϻ' q[edӇ&O;E<Խ? ewХzٔHMK-<5ghi߿9_G}K.:~AUPo#'> qA6S dĭ}~77xI٧?vЌc1iIy걮VuEKӠmF{5/wxC;DZID k{7oǼ ٟ?6(9$ri6k=95oqߗO]>KO_qSnF:Ԑoo&dyӨKWK0v/L,k[q^p*/M4ʢVd6<@3axUԥ Mz+*VbD:aíy45VփߍC#uR7%HH knaCmկV#WWوw> 7,icOH|%Y\wq\{ő^4[VkO)UHHe }鸜 5?[#ZZn)e ֬̓#~|QI;err>4<ϠDt{K{zڐ܋k2(閼)fB4@LO-N#g 2/~E,ƌ8x'뾯nrXu** oX!l`3ﶘ ϛ,foxK0ƸzP5(-5D3S,]mT7F{0C2 =% ,k ʵ-ј#1)"âr(H{oHL&[ԶЖf+D+g1ϢtPť*c7!6 0emL!e -Z[W"}_-=p12R;gЈ Jj9 p{*DU{“# WFS燔DˀĻ36s׼eWH\C{DmWe1ox~޴eL 6K[1;P#WvrXu3Ng3J^U+40M*uW|IQ$?wpA ;Nblغ~NS S`R9Z2s=1{1k&mT 4Ub$&ݽ;h4,kU$HĸV4K?!]NEbʪ fM!deBk 3&2GIOαw⧓[<ʲ-VKbmଌoGRL3z- $pn,ٗz#;9bDuz!S~ov5htBvjxEW{Pvsi {Þ՟O8*9b2w3ٵ3c9ڜJ?cBI.0Yw-|;'ݷP(جɖ!>oAlES}_ҽ!]˾TYursѨ(*6Ւ=@i:P[DAҲuhj‚J%=)~z%9Qiw 3h0s q,)\r7rx EifAs{͊[ ;HQ1837f&5?!2xg/crQ QB (dAjU;y4!ĥǼ&廁[2E# S4`{;|dqGBibPw/`|@ q m{djB\.mPV0Va㎁ۯo!$F@ƨ'xYXqŞugԦu RBQŭ2mm]m=t95Cg׽3cqUnO!̘T)&f7mQ.3vM}L(qUgQQOJ2u #UAx%l*@859'=0Z~g.̳آ@gU$b qFv;_ĭr WeެMEuΌUDx&KCm0d;қ}A(q6vZvx>A޹v&J4U5l] nٳ=<~!LA\Ws)0gl jZjn9?Xs=Ur,y̮mcB<{j`p(~կ!ĥ~W;Д'jO% b40Y&3:$0Tb3sBJTq+/P$=?V\8DTUA-1x̞$%%%x!_>U 8Dcۨd^H>s:II[}()/f[eeb_/X{k?)u:^[PcsŒ ] j:O &`hsg&5 QVƑXMUgm=i ;Fpn{7m|J@sIFBғ,w^3z\Jٮncۿol <& Jr iw^qIΫT=9GkN30}fՍ_6Ϩ;/s[DMԁl++%N_͖J6Ax7&lOHs-Gfzd?RtNoVӄHV~:^N{e $9.η|ft8u׽7U[t lTs5Y #;(pYy3\ +Ef_mkJMKe{rA Bw:ַ}q7v'nSI CGZAx Jaw^qjQ_X8B>]C {u~r]VL6jQ Q[>9IݎXYGK:N&m79O~XRR2Q٨5~2l5f\ܵ'd-++˥~4 @ߏ%%*Ih{$v.

)Ivwp^bMi9)ΏiaU?w턞p}/rG0$J )%nŴ-ZŨ[pѾ ˋ/Эs\, Ff y9&L6hQKF ǁo}x\ZWkQQxQ\DèM{-uIF;i PA@ɋ'_SK.qՒ9|ʯz$E4(DPK^&v'D+CswsDDIX;<U)}4d>k)youĂnTsE3Fm'UL’F2 W.M _.Պ=hF$iH:]de1i#~M_CJ,Y"?q~V,嫟Z4#b4Y@wmə,$tn{C&tΠ<,/\ORl2!ɗ?x܌#t0YdYƅs`7V*r& @A,*mg>'!%57.=ݴs̘cbRQES%Ni2"vb0R-h ޺|4lXJKVUՠqFu0R?{p}hc-H@k"z.%hm1Hj`4(}I#$ ->j#q>=q_ٞ2$6^?GQ tX'_t_NBr%v+~X-E"qϩALݚ֒cMȰEs_q>!tL ˛]ҖcM̱cߏ 3wA `ՠ` aF|2v&[,Sk<B5 BffO@!+wd4B.ցThF5'{otV^ēGŏF~0 Pjm?=YpyNkPhLuVg^@(\oKWa0k#ؾCRN_¥߾yQ6n`σ sծ 5}B4ef^江M&/U@ڍo`[*t¤= ;maaobkrx59m~);t95{ƿ+8 c5 -QHE d$XWb~gj0*|T|u>=;5#HȝNfǯ\1Xi>jҧsߕyp15{7zvn]rf2|zIx*udKJbz8Z`?|=uy >.j59Hӿ9_G_teeU` On)s$T &-|w. 54.6ʿɌb͂9]ݙ9Χ*>p୦欄v-) kkjwG܇FKjjޔkgs'^be+/Iq|IGWWCxx}n7o[n{Y4c^X7jШ)|-Lg$[`0&%5'=yu+ ˴zI:@ K"/oۓ .tGTA z ?kI~+#P?vHMGU1~z皼 ]]pW7~#M'Uo?w!M=W뫍Is.}51BЎi<ݱ7]i}il_MK>8RRnOrdNtۈ[w~i7/; LhSRò.=hii^v3|ғW r,ZyM_sݪxViﭪve&u^vT{jX)" rjDp BW,  T5 HQ@4LTAB8pF@F3c8vdr((czWTP(7_JUOM6AFi//P-EF)4O(!|͆PT%n.G"kywXՅP˓3[nSz[cәAuƒ9?kH<1C yN똂uw 1v)x~x}??yM͌U^gp)ߺqcGݵ@c{[K3$'.S?8dٯU-g\ʲEmxnC @VDQGt<[ט|l%mZʢ"R}a/n/XMSK!a@y9߬TSWywUV* LMYg F:[qG~jO/h=O[ x-˵@ɵ@Ipri1&bL2Exf嘙2*,'3nsJ)2<9'rȰ򠔂8fX)y6 @xgȰgID%V=(s8m26]c }[>e&UidzcklIXf13et22?]BWb UwB43f,}tvӯNՓD!͘2Hػֵ2%۔3UI|Ojjm$s=v^o3\*R]SMՋDQ<0(9wι/KR^UK)S{˟r ۟tK4"6*?qխ4U.cE]*iw׶Ox`·^hhmB^&+,YR |`mo`)eg\)3+u^n喇^=pIyBD"<4-ASJ ^L&Hwm\>myrز7魹 Fɭ1'օ*eG<&ñ>ܸ':7dʼe?vtl+L7ׄ~|"yo'G5_ƴ6Ćzb2eM?]9ZwVM~k7յOoΚv۫8%[1#S:2WWqXuXè5C5  &r(EGwg0)~!@PL%4f<ŘDNTD|2?Зqn~w>ʝYGdUJ &F#k?(I(yN'WQZ &dS7Lzc S/UH~o Ng7zl9%[ .~#(Фh7g %}s\(*Y37M:m1#4$En^+0qn="B%l,FAR@%^)|?o KR"}JCwFڎ_o/#`tGgmil߳FWڙQ؄LlTyߖn<EI)+sg?󏮫wV%v RR4gh_gﱷ>A`lz)939`݁cE]q죵H κ㚌7,Wܞu޵gO׺9qlֽSGto:;@+YY=yz#EEE\qZ1hЎ;s \cB]C-/u뎲2])NSZZ*Q8萷$Ek?ӹͻibZU}jA`/}ca(*Z*x!oɊbw/}GkQQV\L[**I\T2(7`8]q~Z1miƝ8'oP҈(j7oב{Kꤥ:cΔ >xgǧbÞƳ[ߚFGQ\O~ G +++Jď1qٵ7`s-^/s8>DP*>kdg^EE/n}3RAKapNVZsk[ xݑXk t.Q_YY2n̴fMkTUtq~κrd5zbUwG~뿡a&QnB`2 2%VV~@5!ˉi˸_u{gŌJkw©};T~1 Mz O붺U1Ț 6ƒ:?cl~&do{ێ2ZڃH7R'`^Y[n5VU{wHjL, {f]Rd 4,'m;kmdF#16YaQ꧎|h(lmmٴoguPg018 w>?*?QZcf`4`4P>c:`n.qw_ӯ~Z3*Uh{u%O1|?q;4F׾-flpZCⶲA6uwOa>_[^<4?$Guycr4DCnJsOm N%މ9-wFFbB)Ao>C*G0sy-* ~CYS5,&IVaKZi4(e\G#{zIs˿oPF݌ b~iT^0HiPS Y6O4p\кw8>ӨJ(#?vi4 >HlBt_f /__X:xV&M..=yoC `j0u*.n]sFO7%%yqXFjowjj*,fpLT,{fUu>{޻tPAKf%P511Dc4D5ꌚػILoq ~~zÙ9ZDhZҦZ,Ә8qK~2>d>E32Lu0M;}lZ$~TGr.;ߋƂ @:%%Y2错JLEḶ[Z#ݘ5|D߸z9_%3NTʔģ LLZYTD,53fFU敥q $3ܦo1hU _j,f-_;^szښ.8җ<.m5\,6YiM>mڴH/*+[v 6d&3٪}zISwjwey8M(3֌Z)2YzdfkIA0y0|h`H(r~2=*Al֬5\1DKq=cO2Xٙ 6'5Evd1&H0]Ҭ}E9" {yQ1cC_ BbذQUN6=r$#%G#aT"|wuuɑpgeWȑ3mz,EaKFÖ۩>pؘ)ʱx.onzçH7ɴʨf󺤹SgoK~wBWio>lvl}yɒCֽonx:!#rY'gC RY3Smy+3wn8PwC1ͥyi?u_hP^i>?}a h,h,tFgȟ_ ZHKMPB!&j=)ݞ2,ҙ 3,AVn|; XXt@>,0d5 xx,#?/b4@,D<@V1 0O&H$:cDE߉| %FB"3͐/@asAo4bT:DcH$SL3,( 0hd}VW{mU$kqNt;k6-k!67z$t6KnQ-۞16661O1i ]{ qğ~6WeL!-W?xlKxMLUo\ҷƲ"q >9ٰNF3A,Ř1FcϟSY^ݰ1k L[ߜz ƛgv sg}.eDe"vfuZըV#(bxkg{nOy$ixrycjJa滶;~x&۶zanda>jG`$PܭaU`f}c@qs29.Ed1YLJ?i?*nEm)%ξ|gpt0[>*mEh7Vm7] 2-xǣtiS/=,>\R\9mY}~-< B<2:\vkי~S͛S>qW?~,K>I63r'INbgġ>X5J*\|o*5R7n4|0q+ZbI6|cxwN^YcmْkT1gGn\{Vp߳s|_Y5}ަ&égW>=7^ 0? `[+:8@7qY z^wvyZ`dWu04zF%(ܞ3RP_޸K],6#nS % W1Sw׺^ye$)N4^ 1Z{<`,+1{}iZ7'VضvqI#@&[='+\_EO =UK ݯ%+qgQ_;"/`id2~O} 'C%D4,b_`$GL*>x,Jp2*K *2ʋ].hkj%?9yX_Jc?LrQa>@+//`)7b[%J~a8v9M9-Y({ϵ~}+ b;!K$"/-` AwGVJ}6T%s1pIJsDST<Kf@vT[_sABZşr?z=ˑbBBang"Y01Pr}Q0QW[_Iq林>PLVK:#2-9䬁)  ʫ/cSw\Y-kg%40e<@˱|j fK?{ܦXu/3FRQ3LÒCᘒ~qç6h俫cfK\JqH3OT޶0~ބ!G[~atX,LK2s;dF=-Y3[T6U@T ihڍE1>0#>^իY"'|6Oj[I_+>#.ziJҫ+1b@)F]{ï=0E%v^X'v$qO_ZU[^AWljbN/ĞDQKUtك+vVp]Uylw\lnbK[^D1^b{w폞 pPf[:Ą_^A=&Utv l1>2WV$xkaEB5{ͷ#(Γ}kҫ0fh% aΛ` (|Fp{nFߵAZe`YY&@Go;39<%$Iޱj`n˴AXBdIL:-Y21FbJkۇFd4iJ~`f䣊Y}K$y;'jQLgI;,#Y(I;3~Ov840 d CU(ߝ 4u:'ʄ z^Y($3';µvI-bP:c]rYU*gV?j aeZ$?k_ V5uokl{"$.UrmB^d U*P$OVQ>{R|VWsj< i^nze7TguK9l;N>$~AEWKkxW I`„ YNѓOָQRPq@^܀-/a;Q!^㉼zIIgZM96yF+r]`0.ϨD~IgZMAsmُz|<o|?lz涽7,<"o56zH3o}&tqOǿ?sۇf@(C5jjot%EZMEj!`7}ҽΜvmP㍼hY~~E;[" e2C :k3?<>fҤ!r=Dp2֬in;: zcGݏ OBv׻zfS7MOl>+6i~cu5g?'ng=xΌg;XqSͫΫz|̴Gĉf4홋N:^\2gy3f?mjjl\7jkI<| S玵c [A`>t5Íp'Tlw8Y1?\q5CWkHcc׼w_[ܞUMtNQtE_49ʓ˖uYbpEt~넩gSJ TT}^Il}@m5"{bp %gKL!'X'L=aU"i -K;6gb9,/`z?׏"V1ҽmyԂPS? 0L5=mUoR0wkp ](nJ]F[6t_@-t3%8p$nuOA4xmVo|' ku{b.*l]FK+hn C]xx̙Ҭ𷌨ѯ94lx# !SOnY؎R6md=- ]{Qup5uut+eO :sNO(gO\5kꃷ]ӲXcG ˂/ӼdD~I%ްQt'uT]aFv -]1w80bFlV{ɵwd FG O ;6^MJ?|Vw4'_~KD-YBgNoMN>WrD[~ 4ڻ#W>q%`D,+n=ЧR?,/M <a798˧w8wӉ럲Gݡm}Lg'C6?>:Š[KG sq'ՙ1h,%&lJ(@탻~Q;,X]$=fiXg B+ŧ &y30xT<4,QV![tCH)9ocuuB! 'm4n'QO*)TAϷZH!w9?>Gɑ_Ĥn " [g .^6/_ `ih.Z5Õ?T8W9\b]m5:0 ʏ0Cmj!}x\o2R*qp,(\DA-ʶ١Wp|V+Xk,U_[[-})F.:…M%bee^>m,3xÂ| L3\0{_ҿ'֧};!yuUr|~WM(`5uҥZBb\*4'J6뒶Iӌ5D؊~p4- jH_LܱQc飸X7ۍ-/)f0p-^X<{Ԏ%GwC R2&,Kx,N[g2Y2HEL|ȡc` {H,ME$Ӹ?89]Jni"XdtY`1nq4KeGk0j>_Awi,X{Uu}펛Ő죭>c/Y!3w4c!r e""餖"ŦNËT<+|W&N\l bb JmmM;'ZxkW+w5ffeE㧍yE &.^|ꬺ/{ &ԯ߹0aS%%vK"{ĽG5+?uu q;64i9%qA=ԗ<_S;ìQBvQX9~zݑUPd,$3M]c_`Y RTYF4 WߺGbW?į &2Uʆ%2liXe²,AiaW +Məlf[#O/*"8P gֶ{nm@I{5wXΖ/NDAI?a4n{O_05bҥNyF<ͯҶ)prpy$h?~ ,M<%?dKwާʒoޙtP]-`YsZ^I~|$%|oW޲:<9-qK_jzgxsoԳ JJ1uY sBt.\[{^{:>}q[v=6]63d“n{;vں_-6vejo?g/O_w|,/څ'Dck6=sտ{6$s"q#Jf^zo\8h_`9Ͼ鎎H5O^յ>dvƾgW]N1,!Ѭn2 K fЀ[>\Y_XFg8oMFxw'*Rm{'&ɍDuJW}?wZcH|?܉V1旷嫓Ƹ}ݿ.qp^2I:>^E=sv GmHTFۉඋS?qE3<|ɪ<9e ~l+H99 Z+{yӞ5}>\yK5O_[I뷯>|#˟^5Z/]7ZBA5sY?~hO?gyVc=:b_0q7n܈Bw *5F13$>|{~wՎO 0y.c\d$>[*# n8l[q+~HX=~I[ǖ2M%k\U]SkP=וA ysUK~YHOg g6'5UWVZ-x+ֶ9%Fγe=?VKDdL\x;$߳z3+\KkO?UU@j¼_Xɳ?0LiSK]GG`w`˞zO^[]EfƘHu+^Ww=jG TWK b$ ᰁK.ngrp.ILm6!{|Osc,%&Sd`2qL[󞸖AWez*Y9n5?dj 0i+VLP]̯ _d$;/:R'.d X]#$onK~L3>}@55uV0^Nܝ66~ėt>qשrb溶 5:ߣv#c̘FasnT*'(6u`dc-a7-LTg#? ez˭n7sUVَh M)/ aWlo\ @ {mӆ[$ܹasG4|?ߧfzK5~)2db\iidg2y(~AoۻH~? wʘdohoslc^Wa2{vu({SNeuÈ>\`U)[>B^u?I0d !w̬'[A hLqSbFȒ# ĿKwK Ceٳ6䖭 0-]8~S )\%flo5|_?8($.HgkWtؿmА{gMK@"et>{'-9ٹsC LT)cȥidd(8WVKu5u֤=Y=EegAKk;H;C/׸Tzcgg4oAg<gH3m]Ģw4X Hu_I+qq|p9˲N$ Ghw{ghЊQ>>{8c T;vѲ)e}G )a AHÉ?عwe撚L\1 7>sL6&v؁TgEEʌ2@즢 (?Mrd35"wJg3 W(63QzOۛ7/;J fHә=w0z/¨E>_~oetv|öF_9P5`aM8;/zifK^eYk%qۊNq/?P?7ʖ;5htqW$ KJQxp6@$ @aLK<Syf)sfGD=j])Uzrا|.q` qs2^۰`0hB!1}`<=.X 8}.9Ty`ׇx]i,**u q 1r:l cCд}Qwg 2-0Qvnnbڶ ;VXо3xnY߻i3f1FXl=ckw>D~ul;2+T Zrʉ?hcg/ 5 ZAA˪BO/-Wv j:Xߛ+fHX-\yeSʱ0sL @[.:;%"1,GH6|X\о=a mS-X*k e\ϽmhȾC@g'Kfti&acFa;$(wbۇ G[/-`'O'&^fHso/2ɕ#PUίI`m,%W # t8>b*hdvi:s;~, 1}k&$A)씪4Fb^68=BX8#&$IHg ߑ c3! g b:@Ha%,i2>I7M-N\`W=w_%L SMiү_KȆa1#s"Ia?9}!T&I2z'"$$1""&zVL+ %;I0I@kr|F3,L3Yp:BQd,p'WHCKր pUlG WRGƄCUx)p*3f'9 bPBoId Ǖ*,nj% =gH$|D6=2 >$Ӷ8e28eR+6b?K j5p"`Y>FbpԝginҰk.Z!Eߚ2\C>Ò%G 0(vr)ʎOȪ7󡕩PNFŸ́AmumӧL3>ZH,M" KIL:띰YDs7c^)kΣ(}Ӈ0%y 3n )/A\7-H[NEǶx3X67h?0&56E [E3i:Yb,"v;R͐Yyh|9awv=bMH9Я$44[a  i, ,‚а9J, qH|,M߇;ph!KLB8 0qU)rm&Fѭ#L{GO4aYLm&6 N"@ш$"X`@~atlB& LeE)da25 AKUa\wA EŒ & Ý,x&ht`'f%+"%0 3uV7ٳZl?|%(v-T i J(Ą@{r|?`LxxLQ|~ Ieb$bY H/@a ~0 8j$YITPPpP9[I4]3$ TzANļ0,Ago&2î}9NwR11P]ب lM D:ۊ&g5P q3 mOu7OM3:hK|u|Y۽ VjYMg_3t lXd&|!?>( Ěh  `uݳntf|P -m7di\D X0`&LD2%؃}PBӡ"xEV.!`4Mfj0L>jۃ֖}i=׌:s7!L M7YdH4q ^w6S`f'mS(n&Ic2в&i y#NGNٌOAO6au]??᎟G a(~!ncܵ n_du(Mx,N1n*MT{:ROe&~ 2fB)"jBӐIJQ3'>rbа'B9 ŲZ\4uxYzw '+v*l@_F' wx2gPsl0-7`M@7g'aih ز3wlP{$H?3c`ܤfrbh'H3?򤝴y>/I-+6"݈v>?3>/dIʹ@Y&kkFw$r`>cT: ʫ;{]y/cob܎-a C>˖яV{/}Y? b=J0f 3MUh/LU,ԽZb!M*ȡK~}ۥk~cz=i 6@`r$vMǟg,9;G }yKg5s"hxw3g+> !l@&I0,:P2&lDu2? !N d#y;4v,H2dR&ThL1Lo`Ę Of̯ 8lAc=q ̝]@(2,P.2/?H*(ϭ{lQhC/a9x?n4vpx\\/ c6yՎm{%6SB [7saw>2C9İq}5KM "KH$96yp4"*0"3Dcu+سօYxP$ 0 d;}:eydWS*0O?sĚcLGۆSp盀a3>eXW!.wҩ@bJ0}T#i3eRܙX6mM{dH%GEPoRs- i2!ú`S3P)İr:٤@;3 22G6ԟYzv .QjwS$PܭaU`z}h85+)V C*j˞cRԖr^2w JKl3ᮦƝm8` xk\["zooom0'Ӷ,|+NI[a֮&34tF0ip_0h3 uub:x6qɉ<}L\sB `;6\j]h3v&3'`IA):wxkZmٔQ奎˒Vp٭?cw!AfC˯ qiI ?7+! ,!:@b_y.L}$D?/`'X<;itvWAncPݏJME[1xUb8 {:G1*^~ۆ-&ڧsQzr .$qڳx ״?{'U1# ;Q2^>3p : h_8\0gp&Eè0c 2%rP$,!!FUY(.4û~2 0=gkEHe'^҂)xE` JpLw#2xEv54xlou4In',e$qukx0_؂ l+c` gl @m.4)hlRpN~ 3We/edcL1Z$ o'܄T&^7 (zp)mx- e"' a/qI$ckqMhm𣩃c:'fNAdxmN͛Wl-3hࠌQ)6 3I);l䶛ubÉ33NѮj̈́ fYRDV?x[m_6UhLMGޙ6a)D4!`&Ȇy05'$#b^?͇MGIJSZ //! /`A=;eA]bi2b) ^6a`e0L;^H$\X#FuDnz5Hs=&}0[$(cṼ釡yu̪,i86,AeP B%Jwk}+Mo ]Ωaa$Yk3PV+o "1f1C5lWPmQ3_i?ۇ/aXp`ųgv0̘,F 14đ  %Yx> \q ~L+e!խ8=8!t0Rb$, =E` Pd@lD?#a W@mY,/gCK:>՗fp/~', *8kn ̓!17ݢ{39:z>ޫz99qQ>X9qIS(z'CQLȝ0%0o ]^fFa>–uvXBPr^7>ںyؕDy)lNs g"1d`}™(.5e[Wl8:}+oZ?Ki:֯8@hl HX~)'\uۉ6 c4rwFǫu1DD /uǴ7'/8mnà&N$M+-՗>J-0Ǜ8Wjsv)#ڹwwdoSQQjp 6bnHNTV}߉_Ѧ>+Ⓡ@q';ȟb=cMZZ"ԾPR}37 _茹ߝ//Y}f- 6-R__o]D8W~.(T; ꪫyV0)ҴĄYtei ,P<M!3 9(/4 `ۢ"T_VH"c@b~-~;8GS:l.=d*d6 yN'( *-LHgr~@>1Y ?^zAseu\k:@B%}~RT8:E6u3SI:||jOj&"::YxyŶ}V z&9%~]}n`W*+sO%:ԇVJe] 1, 16=\[nX.bt`voɧw#_TG7kM; 68qv][Vzu0` c>KxN=ލmE]kPA`@Z2II'|\er{W]A 21dSo HrK}Ճh ұQȄ Xu|g`ڤ4lvFHv;8~OI oBGNFvh/OBX2a* qFDne!H#g!  C #X,B,A`A2ObMkWmCCVyB&H5Lüc )¥dLp&p=>b.d!hlK200U#G}!Jv` BMC,q{'Kp E2h&zBT{h$XxCK3dQşs$+&^#YKw}$CD)k՞,3@j6?COIEja'2K6|Ж3ϡzdp+y%I h?AղbVHjX=o|lI ;pKمx oC{41}{ƌ'6ȤM^ZakV&mr'ok_G<:sxڱv©+ "&b,\0qj,)֍g?*URiAgUe5i26/sm̿S{dYέ"ܿt/B!qː϶,8!i&\} ٮaP_B Yghlɭb*K]F`*a6a F3ЬFWeƁ,W<P3w/^ ņv[:, 2Y^񵬌i8evVOJaw! 4z0#V'f$Gf{GT_d^lG}_KRM5;M;mC4sR#/kp7cjl{kH9 ~ ;k)t@zN2&sa?-ib40_2LH? RkQf?\vg)th~9Mxh#-0bCڥ وTg\?J^fu讵(ncAQKxy2YKG~9~OWsⷿ\aFgfe~I }'tVeic^sO_Y]Tyw ?xIv4x2&;g\]%.`Ǜ_逤pbPdf<"v Xp;0R) Lɀ0HJp)LJ91tQC51($$DTh `Lim0) ff@\tƾOiL$2|B3!5flL9960)L);UƔq@%@)PpQ8;R0:d .鲤GIQk-R<Z$"Lj-U6' Z LCU5"L@1NYKu_Ц 6bˣ\]μbchYv! I- Y%>,XHП߼~I)+/^C^:aRI$tMjD6sE|ǜ>d#FqeǍ#GA/(nAN%B6U .)yfݑ-7G~|3֟9ze%㼍ԖC$/'@w, MMlx𩌵]" Ƃ33d>(4Lh nmg,)]co~{ьdR1c\'[ 8  cpy3Htf_.[6֣)nON+,kzg$1?kòūW#2w/럝CTY0y_C: ¶ŢO۱gyU+kvwy3x߂$8=́m1, @ss_Q\{OޑjjgmUV_߱5#A8!. LnCw%KA7vu&ɲm cD~0wu^r@ g(|jO=;3q npH1z.kNHx'>.ߪz|ZCHgM8\$/{m'DvDs0Ӟ|sFꪁ`p$$,աʭqn;|(/kKq6|n{ɚ 0fI^~]_*>-0ӕxг0uyc_i=M2,jWR]W;هfIïȯ TO3V$1O㭻_}RE pj׍nND)Ol9t x~ʬ)ٽI +7QegUqDFQ0A&!B`׭nF1ک`g?^Ἢw6#lMFп٥cDVx/\6︟/oi:C]>dl=[:(W lLCן-p:]‚Ș24 @&$!n^kT*K8ɖșpblT]$S@] u] 2{k* `YuL ىSex8sQ ? AD>±w: lu%oRiƲi64^TfsK`ГڙX# 8BARעZA5{Ԡ|.q3I {ڼTZlJw3uUWyLb85⻼`  2I$ xRe`eE1YctؤFQ*}Y @`il0 A\` A62y: P\H" `hk ф}H;$N4 j_$͔ ؗ!`YrMDn{`rsV2]!:{?E, 6SIwgn|eV :B 0aZpGⴹ^[fþ%&4]]父73./PtI'(o` Rkd+i gرU> _CUHbRi_q-]3N/MJ0^!d'h.[r;9\JsK-!^VHCF%k g#O~sUx%ґK/@ V!ai . έq6ÃH8TnX9q;MiN}v}^*ꌁhYG;W̳wgjΕM;M fS$O7jY db ;'dRI=8m鄏kO݈)9}2/sszjrHe'ήv6ËDdىlk?u:cNlR7DMŀyvE81 \`$n~ *RCdĎt&'ϑVtx,Zj?!ߗS~H 0(+ vO#7{iZPb+=N>iJ vy&b&5*/g`-]:AJY>{̞M8yN_K*XDd`Lv%=^X\_,8!;glދ6ALSR=<#;8ir.`~ <81#kA،\%,sQie%0l~Gp90e pȹ3@j3H@X $cE O@c0- 1sSy\r`y g(c>h$g:Q%qt:UD:>"a/;qHf?(nTi/C_hGw,w81$$ "cw:KYXև4UCbubk ^J2s2 B>ԏ+Dkv0X}Z :0/dm/^kp0^%h+K*&pI̅|@bHё~]xaxCuNoFF7g(G~Pw\'A,``sމ/f úMxI\75G6"0Qb'ʼnUwt&R2-_? SOY&/NЉ1ib̤/M)(t*p8 <8oş>RI^b@PfA<wjkOEM+WܲL$YeB1!w Er&۹ ͱgw Okks5'k>ad2'} *-AY%2cYL&a5ZH{mt]G,{t- /9uԀ\a!z0yD*z4Z|TX 95$[1Ď! `X*-?Ec¼Ւ[ʝ~0gUL(B.%$q jqmQ^[L Nd ?쪰h ]ȌCGZϴtB3i} gQ { BO1|PXb8ތ7^[&~Y;',Mb'\C|4M ~0м'w犓:P`Ɲ+u0ˀ'a鄕\{'VXWO6xNgQmmCF_5"hZ'c8QC֦2eq!?[ף5DFt?' ~ cqLP#KfHy,]_5N[oγ:ke}m,f4M9n-,,Js?g2{xglB@$DUUats'p]aƖT*'Q;2|uobADWR@R0@ g:t[6Xss"eE+3z"GZ;A/mTم9,@nq&RI&$% tT VPU]S]!O_kCHClliiĢ6ƍOpdrPF&Hm0RedZ0~ A|z.w8P+ b<ɧ(h:q~Eyx;';= -=>DoG#0a(2mIoU+s0坄K]xZ36FbW{%qn9D2U%K!?Pc^[;M8ƁJKv !],˘^9rW}?wZcH 9E;?0Y VM9B%"l_re_~͌1; ])Eu wX㫦ib]+V>s1f2$]+V*++1l_`$B&0aVLd,\J!b|h$藾#sxeq3!r79 ;0 &g>" V&H0;gb{#eC*dF^+aI>xnRAf7@ٮ `"bWA:`H)vqrM NW.E+0E`:#q0V`>;pt@ׯk xYPK1{QF%vIGgA˚ocgq#סEPOFyF2<(/+xi8}p9?(DD x|Jrr2LkD4RZ{ It:+,a^bEWՌ1;c"r~/0`Q .l"KaOV ~B+3*7d  p|pN,reMBE GbZw?;DxӺ#,Q1ۻWA?,8e-NѾ= "I;YwhG$fS&acz*#Oq/>Z{,=NH%F.Mi 44Id) d +KNwa^|y)w?r.6[bVjz 0e:#,d#M؜\8Wp/ ~"!wY{d2/.)w{iD-!3?0:ұ$Ci XL`0HÐgaij6tb;]pBZKs6,g(!䕛e-+Fk`q7ggN܇o# ѳ@">7L*q7VXdnƭ: o?Sǡu$[҅l{8;j~gLz%! 5 (XU^'bkrUD( R@z4:rԧ~3aR&$~_z?y I~>g]޹z~t;>}q|nxϠ0ZHn;g}e_NXoxI߅:W& \w9^\C[-|p1 UcS F hN֒tW$$ uN apy?2_гgϞ&j_T:mJ-+Wj2ea2%e7ߌ3fΜ@D;ֶ̙mU`˖-Q;4|.!C7m:@`ܹ5kd6ml3f477wМp 7!YfE֯_{G577bf 'Z ?'}<޾o/|M~|{? EK2E8\D`x*> <},??_ m2Ul; -忁~A@$3=W'ܛˁmzSX8fP8s 3@bIHF(G*@B|ia$ !.2r-L_ge< о3y[ y8I?@P 奣V#.J;KQo9}eϞ#I>| XDA 3@lf @v0|#:׃ܿ!hfXGLȰրE$L` Μt"ʪ*r9]]c?a'-< 2 ,\r&\-< Vh f)YX Az]- /蒊i1y,y7m'.$''^19pQ UĞ7wҁ%L)LFp,m.``q}Pz7^ +YeYs/,* L[²۶p>|yC|4l|f.Nl NE7@i< I B88p<&is0&_Bmݞz.2‚38@MX!wkPdA?>>P1L` };c?`ގ%pb!4zqfO>|,,K促~ZW >ΞnL|͸n>Ʒ4붗4/}{` 2|B, i{Pir - -A@ιK AOO"TU@K{+Z3"HuŨ_8'NwPs*#h%1|Ň g -F<-Bޓp_;l_VA6>7౏T6(F x<)f( . ,Pea Z(~$4,4_*IC&T@>":0 UG3"+2%Bi` fs+r0! y]TpP{;~=ݫQt/ޞQ" kڒ.IߔN>&1>b0\'yu-jj6D6)dRk#y0ϻ~ɻ}1uSm˜ zϚε_.|~ѢnFCːw=/ͿJg?󏭻m*5)>o4W >Iv._ a?iR,C]BDT&'ΝÅ{lW"@6 W]LGl iLkd,9h[, 4|`&k+ QĦ:oc= ._qkwCˌӹ dw bųyթSPY~,CAیG!~dqG7ڵ:?JnCD+P8/H4" n"qeZTZx8xNp^SR5"`*6\"5zKWU%W6$u" /Fӛ77X8?JKnB`_¡@u4lv9? GH(6:v3;ԓ0w> 0 ,X$@O_{+6{Z XC[0f8dڰ'Mnboǣ !d.GyeB2FgrugH2LxlYksf6zN\wzy"$Fsfoiغwz 'ł碑G # ZӝZ"]e! !X[t25zzyWW~i<& |P;V@c=V>3]h+/1U񛤔 XWRSp ?{m7,ZXrȁ7p͔" A3ţOHq.ZڋGGCQ4 Z|WoKעE+߹ WCMy\ aƹ 2YUj\sDLc,%-c1Q^-yQYV+ A&V "7W~B`HKKI4[9>X0 I*+/=Z-7zo\ @ӷl.k>'铟o۴MԾK)ꘉ*3[Ì ׿+^l($%1:`iYw"m} )DٿP~}vH~j]OTfLkq"ф.zkŎ/- 78w x-ܠc_10(aF5o Lv TjS'Z+g0{ع]/ODѸnjI>t&3XB4QL5@";kOv5[yQUhc8/iǣnYSMUvեiqi0K4Vߺz7jY/hxBiA҂Sz*,z< AD70޿p[}}}9U}|]_JR)FE$مHȣ,o]2 S0kWF}E! kߍ긃d|߇/:w4wwFZ+N~z2^ }f4]'՛QXT p0kWK0#bb³Q (f{ǯs_yv `->v{DP'NV) ?JkחsB0lsf @%`!4nKu7e*ﴼeBTsU隃Sd:inlzNw2U0Fsxz %||57a:,CסCmw l pϼPUH0-7@IXMj SIS} Y?HU?/;އ\ 3~&M&nHaXh;" ܷ+@uno1\ ̄i#Գ;3--X:6Aw(3 iA,>ش̄ T4sh-P^ ?7o*P/_G@c2>U;#*(o=F~ӱ{!eoWokD-=ZIHiw}Dc1F@Ub$&";w?X!R\O$t ?u~)C So:q݄[lcп? bz(22Թ'D ԼhV;}$%[4jUGl7n))/{=g/<#Mlo௫AeYe{Ōm뷌_K`col>"VQ_]F( ?s 0}^<;Ѱƺ&''ݱzsmbmGs]Iq xAe{+_]{v!MWBR b o'q<He8 $I$Ѩz^H\O` `޽Ѿc>KΨEhӘi404"bq({yRḍ_DhT=P='I$l37v"ɿ}5sO"GKs&^/2p͟>}p#eՖ:o4O#/n~Ϡi ${]A!?zr!+oS A%=؝k|7|-qI/BcQ`n^b֫tiC}ݦP8 3 6_V}ﲟy`o{[=Ag|y3~7ٹl75xϓw[k/t(o|! 3 w6-gW;K[vÛ*9;oYꯐ ɹj%|_gQ#hV+䄹S 3vvXrVI;e{|@gϚL.sE~ރX/ F\ĢQ8?Kxω xrݓo?<2< N壡He*1Jv~zӣO]F vP?`^˾T6lp`*S36O{z|k7ųstYm@Xpl Rltc.+_ +uKl=v&f]OC9c|UyRń_}pG*NOR^Qv{4_G|$$ӊUXZsTB ȚR``πvT0ƬÁR|0Z17@`}vSg:l@4hc8/L 1~}ڬY"Ǒ$MduZWK#tizOPvq T߼ֶQVRRx @•=8l# KЫ\*mҭ ~{ȼ|nMZ6qQ8N"v-.}QQKo^'# 5d͓Of4̙-~/oʓ3M:*q;rMoTY @WdsU+x#F+PԴ_U/ Lh^/l #.'ȿ4u A^[u 2[CLOQWQnKaVX$>L<Sb XzO'C(F/ .~ʊe  '9)'~=2xW]I( VHeH&e K/,֐(RD$h^~K~T_A& ###N9_Ǐ[uG=(MM5?xoxfz"ROVj '>[~u"ѲʪW6 ågoǟf+73Kؑ2 ̺$:uO{{IӟwW2K#+)gO۪ /?g|: A{;3:$"rBwm*Kp C@`|a ~uT{עϏ%? ,~aHYMwz̸/f*qU.oȀ>6%R.{~̥{h0 ?/W})y ,fYP^~RpbAZ&md3/~:F@lЀa<ٱOF據_1GV AFnި,Nj\:5m>/ri%j7"80$6щTT }%p HO\^ݽ$m]6"` ZRsIim=4K+SIq`& {u/5n8lx-/y\pݪ2#E9s{OoqHy.,cSKJRWQ$Ck%|ٝnt폆>;:.t*4e;!%Bwѡ ~QQnd:OUݿFx*h165%eG9G%:dڗ2qI9Ԇet8-. z|A̟oPq$ECJ()+C($H Cyyii>E#TeyH6#h )A '0zQ[<4?-#nVdKt4e_Dh0-(90:DO\!>8)>ROt'!G69S+uywV9H8(-v yƩJAؖOj(u0qQ7,owrAߘ8yv3ID'%bA% C#>pe>] {T]CMCa A` A #aZ @ L0\\4#]!.҃v/5 dV,$3or5ܘƇ`^0=}cTƗg}4E Wtr24?G V֑i9s7qsїEރZt ExXa+64-Y8!VWdQFڶ#Ѕ:co F8 6WcB}`j ؈M] WAvI_p; A lMP/f1(1G8{zbv 7@ޥqxBNQ^aJ-N9Vc,pry{5v' WĖePC{@ *pQ"msB!ڷ"^ōJ@.1d,C kĂY9TV88`Ӷ :|<2-a.eg&ĠS}6XE3A$a]qc$H&]#8I &74ܿYBN'd Jr 4DB6?gns&doCWiag&(PqGy+ qC,Q،HB0X5a9Akb$UpE0{i>Gu}yBw?/H} hljs]|ۿoFP_Rcm/y~VqFyqʼ1$ }zw_\l=]' wk+ - kQvpG4Kc_'πI̜L顺. O beTC\˖ frorib{ErJc~šm\3gwZ U'k o/QhbLšaՎObtQ6~'5dpy CPf5y>jbæ9S 4 ;L4j ` !vZ?_c ~g \nL*(Ӹ}QYlO\C.'98EgRz'bB p?Yv/5l~-3 >\@Cm )B01c1 pݓ11M0^K>g,%ݐBsMYOԃL>G{xcOǎ5}'ma]hξ QMð,nBwZ`NBW'G24'oD-K{P|w8 ٽ C}EAg݃_ϿI>x?`B4"s5fЖ738>A?ϏpT}\;}.|´.x-vwL^aG+qTs+Н8kgcF!]N{0c#Q=~'?x& I8gz{{6L{ĠŋW>zn"?>}X2}bfձNЅkv|$}̑ 3iaɱ}ԟB{+ x'OQt$%lc{qe{pq(|\sN,)P_)oiFTpyS0솗ѱARD>hv*᥃8N tѾVcrysfpxԏ[F~a]ғ!< 1V`B:|| ]҅P?C  (cMndt *CosLt?UԇLe X`QF?`Y٧4.Yl$KdntG%K]Y7s&ʼ 5h|(p9|] jHׂp"b`QwȢlFJgF_=̿9v譜-h|)Ĕ/'h ߻/ش4 ZK1|%!r1f5n P/95}l+$<-Q6,EP(#5 A:Q~ םkCY)F(.?SO#= ;>m,Hb+(IjpS]/h(0-0*HUX|9PoC"x'>~6 *qт$kzSJ <8v!A~wJysoOsTWV\OP>d&w0{VǭϾg<PJ:>6\i E#l8TS70Ξ♩`vӎ>q̞C`0ExAhXmGm܇_մn{9 t`dJh jڱv (L,\p z⽿nB7vEu^^wNCFi˴{{NA! >cKBzc/N%1+҅|߽'،>Hvc>1n@*: =;:B'wbv Z{ȕmذJQ؆2bcv΃P34Z!"5A◷CKQ@2 4b/nn`0w:}Kf'yOwx/ـgׇ.P?D6&1w.#ꧥK54>2 ߹7a$hvjBU,}X?? jZD{?QRkdu/?ˍ\:68ń6bʌMxOWo6*C]l;VexvLڈxd1Pw}~V8J!{?@TtMc/,&ٌ ^z -ۨ ྿^ELY!_n{=o=B93ޏ~BFvf)^4Nv݁.2p[G{e)1ۋ#7>Mx\|Kǰ_l)Pȃe%|@-Y u0r֮܇qԵX4u-_oX> Uȇ.gbV, 띷gzZ>ߪ ,+???)DdZ 0jw&^}5mO, mWWuYpVa|ߨ GTM~y\0edW/=!dw'HNe3_B>?؂' XoAiQ?d+x+pp6L!5T0=33߄YlU^zඳQW0*IV9 8}X4e-\'E* 9~ hd h\|/ԐKg Oe N΃p@>\}t\>eԕӟo>q?+QdD)ڨx}xX8u NY{?ޏ 5ECH;_k۾mF2zH`w恵G ^RV6}<}kKz[Sԟh!_e0{ +R`7M_Ȫ2h.gY{M} t?z҉xa(G_f<\cذ}a&Ǡ?3 @9 χcW869.t'F0#\| G(4;X@ϯ@nǧ/nܓW@'ዟ8;ݽggw38~1?_kva! &&54_x.X"e_g= O>{e8ziX <5Pڱ lޗs]ezq‹Q݂'7ԩ{E ֳ/1c=ˏ`O,Cqs;x>>fǏ_KmHЀa6s+Ute>;=OSPf~D Bbw ٻ d Ȣl\vp\[9 )p Tc CgvJy;`4`W[h/ڏc/@2*-97`̯Ep4I /9/>6{ĸk:~ Pv:< .1(?QG/oFbSףt*Y_\p6~" ڝ)GY茓}V wO=qU@8>REn~ty/Y}J]~m>w|0u ܽ6nw ~*V?Bf~]-r>vW-MMMy}q@>lߺ N 0F".]$?YV-+I_\0G~ g睁2Zs|QdO<}{`Ϲ+KC'Q<`͐4s]?#4< euqx˝K0dDvGO=/  ,`'~'qg,{~m7ЮYcxG_q\N`r+>a="LZ\_G_#w?}t h-`DtS tQ'㖁]N~kk0uQ'Zd ҕ 0ߍ6NG&aҀE$$&`x `f1\,UT ϡJT\'Ȅ"@wY<mG+d~?h H|ʟЇOD75„rtۧK>]tM c!u3 Y!92h,|x`},@43fB: gh D )Ƌ._SLƒN gQZV AۇXb"t_;1#ZO4~m.DR$dTX8e,ˡ缢:s& (>2$`, (|\_00Gp(~Xh9T>O㔳?Ag`ǕAB;{T0`2oDט0k"<G. N(li?"lL|0Fh?ԇUTb헽n̰QqT('͏v))󩬦yWYkq7b|Ctphild+'&R@qg/oj,w*P;T y)̞6! ੧H3Ȳ=ng2ՏaB)7ȍ"cuGFݽop괩=툌[F{bilUtUJ,9$WQjpA q?b CB !!#0BVR#N _ S+~@x@0p aI"j  ٷm}p"tB%]h \T~0P /ż,-XU|d(8yF/nHxGx{  _5>J /3JH8ƒiez0:A@ ࿓Lƅm30!r(R~yB>< Ja%nCڛGCA!7|A iV3/4qS*G&V aH6>BA/^٫iWEFpa{?>~},V W?YD| +  " <߇U0$Yfax 'E`Ff (CCrTɿ `",e߿>_q4B9ܿp l(п)03XP ԕO-s3(=k:vZ+N r|ؖ])z'777'B D#a1b[0t*[}bmf&z*(.mU.PVY9+q]X?jilK[ ^hBMyd֠l=PxQO/9zB?(Z%\۞޼cp 7A`1ĊfXjj WuWpjZd8z\pI^455Ņ7_'}_=Ȭ䳓|e6s>V,*r(¢E0-9\ˆFbŢCEmè=^h>d?7@7vZI(xW8Z^:{!LU03 "gFO(R a`\IoA$X ^)5?-v$X"8} O6"!Kߴ(Z62X&J΁-)X;!K޸(QVP$0 45nb1Vug-H>FÁ? Mt Y>0P,Ig܁s9y}!nmmU/*I|:- %̧7~a N,\,-L,Ҝ If/vbbc&KiҐS4 LR lJL_DC+(_pĨm-R))a˔Bb} OY$C+(I, L2ҘXҐ]Jk&fʹN> `DKZʢPLySM|45֕A\ "sHXY' )ppo+3T9EM]O/!j~[Z$Mzp|'?cs|=6+kU]%|%G[Z2; 9sÓMs ι3UqUW]W/YG[P'8~u}9y+L$KGqUOuC]9V =^ʊ2UU^d KPw.{PXQQ ǀ,1YÐ58Xx?D1SbhSp<iW+8.33Qaߞ5 )Q ?(-[fځSJⱠi5|Z+QY3LaP@rǵ@<^f[)h(h|_A3553k2Lò5Fȸ5Ŀc?YˤfP Oi53AX3`}/X9bF,5pxm[iBfJf֚431XK! (Śh%"T`(C@ÃW=&|>XCF9O0L8!8Sf2)qGP7.q2ac.j x<x6|YLK[U(ݗ,@?~V?`qVU3}9 Qi1U9e~^0q׿a#+ܗbr=θ/6ǚNI:()ڬ0`bt͡oˉ*ft^Kj7MD=ҁVhbh6DT3f͞s cD:/|(PОW=Q&Lno攺sX`*'ףD %<X7k %0%y_zXti&)4v}Ǐ;Ǵm5T:#ץDIұHlۜ| @{{YV ³ !L ia S6ab[?E|d\vm'):SP>k&BRHÐҔ0Ȑ i}H---]vQpV,QPYGyJ~=HHA$@B1gGZnii?zm33HD|=X33K "H!H aH9G7_lmJ) ̠Ϭ\_53$$Af@:$Q={*ϊcA4bҚf$@I! 4O$͚'iJ)!?dJHK¯^<`cBPa0Mo`bb Oq0cwI)_Z#-euW0}=X7 /,+ (˾eKS路^gyjM;E) !9{ٟw| &k >L4YZhPƮWzzNj[k&s>#7_3 vf[ h)ԍpsbjp^sZl?70y}fzCB^frvT 暙wvl4YljX?ۿz7oS)xm^Ww\eDt/|1/wsCe|_;553C&[S7ʛ[$7drtfO|0NSiXmIܺsWel󣠠v3.1A`a`S05`mMݙT/UO5vt*|7Rai! "a0Vi0#|KE>*1?0eR,$  AA`B!j`DBHet&$H0Dfofy;O nPX)&ok1_+ksG[*#b_3= P/]_?<~SPhb5<xmov͒ٓ/hdwQ.| ",P^O!`EWM/[+KagkiSS@c^+㾤)JD.*65O[_o* U3**$f2{vʥ¨0ٌ W^{vbyU*_2mSZFBttS:DĨ,oq'~h1[[gU_,dO%Q {\tDkk>4Q@05 T*EhHD#f>;v_[w6A$tt: Sh&)- L4ð̀&lBD4̀`WTv> ⥴BDIS|" ) H8" R8(NZk|OZv@!JHCKÀmY X"e,lKJR~0M !R,|_I2HAZH %%iÐLlې!4lCHEI ,M0 "-> RHK!`HA%E,M)wz"!`f/-*BJ_ ڐae4 iIÐڟ  iB#?T6Tg jfgZH `krϜtf^V4 w'SsAiBBD_s(OIN{q$QtsY=w$gDEFmx^ }^QAy}$ڀBcFr%} >znY`wC`W}Vr'| A +V'2D˗HwC+@VDϮmBa̴'xvm1g鶇pKb>h=<ʹ@x0<;w%z"ZN-ǏO@%0v۷my$i[v8={OKF"j߽q5 O)(`{[;z홶m9;~X"g76-Upg&:{wvtI\{6(DH:QUrKuYyB1LA݃w?f k;pTHGDKxLcB a+I%`AӀ3KZ۲ic#<"pv1 0V>lCۖBy>|E6 e mL#խw „h}XX& Sp=\2Z^v@oˤO]8B^LD)9|2ZqҪeS62<XK& (!RJ4g4s/km±o4m HI(|_~իYJo\'܈a+p,iM'!@BZU6lo(uvk,]pD* %_ M ~ :zta !Y<,J0 Zk }J'N{=،^GeH aK-ʿO]:ÃoO"AࢵA,vlSu;=I{?G`ʈ¬Jk-bG[3{}ur^ 朞};r8Chf2fR<4ߧ5z}ŝDc{?}BQZڿ{];}==;{w KÆ|@$`4`c[9Xџ[0{:hZ͛ 4;h%Z S?uc<x>|%fy=Y5 soI n 5Qq@OqÇ!y-'.T![9qd|f+ bD / "(I# f_k "dD V@jqe>wU| ^Vi+PU7#.X.2:ʲ yW!yN'88:܅]k~Rv8kٺ~ \Qخ aK`\_(8l338ZV(2CaBCJa/vhx3 6B R};Cg<!M %~B-f×/vXxI~"A6Eۚm`a{Ja JDgaabt A6~k_MA`DEV^+;V춯Ww7H7-ޫ[ h&3R fP8C]{ܪZZ1,NrO…})-3Y^V؈~҃> +Us3( ,m]/|wf@ ݭҕD$\xbj&P `,3 ɎZ*zZ[Uc#p1Җ}.]VX@DppmX) n;൶B5b؈ֽ}466Y ka& Bj~@Boj4b`93&Zfw>V$ QTSn׍f1/@=&>+@aI!PԴȸ}:mf˛ F_>엡5AQnZȨ>zݬV^\8跴Ak4$ ^h1}t[j7;1 (JRkieWl],x$ X9ma ޏ j#"n-J#eEz0#{|:d83Z+dghfX|EFH`l+ ,if&2X#4C$$R0a`x8">ɞPqj&C~I#?YvA)TM5/ +`+4?Xt>< f_X] ޽&.Lı,0I)[P &"v 3|Q`K ^VvעF`RAvKFIx|JK4ݫ ܵ蒩f+,s@ۖI^(lYtHp4f .dew*xC{q[ܲچc ˘$jW/m-۷KGR`` jժaVܲ4^~00I`mF:#jfDB @ V4Q2X0'A%2[y_b'NBfAt:}f4UR$H ~:nbyAR:ID`,$"ӛ,/Ƙ(]k,( f+ٍ{ɘsc@TMo^o3~E:I$,ea\үq"kق0AK v2`\GOMXǏXYVz{$8,*=q?~!4UV,{_E9L}_XՉ}aKq+i(Q:_nj=5z (zF4;YXκ28yM("^V@/0@S (iȠLXy!=w}wX|`1VWJj&;hbhM3gOݷ_MW@GX6 use`M=+6WHW~OF|f6 NB>ۇ1$1-VE7eXMH=b53$V(Xi WO3QH^PxGﯛ/w ^&jPgKOyG{v|t5sĊu͊ VVJi`{%Ӫk+nFbP/䑪MaãXu5~,:,g"Pafz3UFnE#`Ȼ*NO>qɣ]]o,mi](׭+2![j 1N|ʢͶe\,dr}'@W[[W462pH8,u!Q|[[[թk#epƶ #W_hOoW7662A  I`MFPEA(Ĕ& E\Xw AR VpoS?#(F3J)5Uj0㇐ !EFiXF73DoQ5Nxx^6-`h?k R%+Et1&-]Dey&J!|a {;YGUu`9& 3`YjkS߼ɴOXrbi-jz8t <ÎW_:}9BPtt |t=?tƹ\Q.Rbh8")"33th?<4sF׳Ͱk/S;< lǔm[f`3ag/vΝ1gº_F|?R0"to_|re3޻{="b `Tm2LnCҴ<4P 9A++>w/D&"05@`%‘pL%֍G*!A dYX1ofX a3-_A3{~ 0a \.ͽTPU! Ȥ 8/E1w33$B)x~ A6]y#8fe2NC1ZA)@Bs-矲IyA(%㑉YsQ"W <*(d 2"H5iD]Zf|'7T] )jIpF;!H,?v O535ZNm&3C0b";e4+ž8akc V(юΣ/Ŭ)y|pC?fʗL`@NIr(~սv t{ZRmH`́/K741t\/>M,!P*^2ӎ[e7Tyw?">c3v:{ώoϤ)o7zmk?|x>#n^S:Mh/ھխ?l0uM's_l7Bx> RHk0Op,EtW+ȥ{Sqf!`LvAU)yAE>؜Y1qTO6{R RPJ A!{`U'OyMJ "c }A;>(77?xbf!EX$;iȫ&MI)O V0s ɑKs V<6l]_a?mZú%@.~rww|UO J Ǝ\\>EQcGE~?wǧ>u,*ң#FzGOC3 jA%AT}V*.HIZ6L$<|Cn(yZC2TXg0"fbًmR6k MHP&Ëv  /)U$׀4Ԕim2^AF,yQۄWQZH++iČ/GݗU;{cB~~ʷwQuwl[qG49] |'fCpVS 0 , "#^'б-YDd'Bʸ |@B@+AHTY%x ( $@YJ niP/|jِwBV R tZj)XR p iYՔna'_DD"& Jf!((@G,!,B1< ~mJ '4 )Jkhf\ iPA HjXb>lǑ5ILbj1Cߍ4L ?/kXO9ו4&HJ; U)ãa}?q.'07MÀ+Q r7LqQv'9JR@W I9?H .{>ΨT>(UȨQFpҷN17`_4{LM x6(z8v g"ïp)01!Z0 (dXԨgu-L*o6X\.'X':|]Fٿn],Po & +*5*.iȝ,@H)tMéLZ* xav ´Il~4!ĸaz4ZiRΤŠP]ݝmVؖ2 CBk5UA5ƐLa[&]Opc0 @<d%^ VZs8 Pwc)y;&,CT904V!2 ZkHRVZ-a6aWOZ  gv2@X.80A&'x$˅*ї`Ŋ36`|>x;81eXBql,lNJFѝ8&fY,y(ܗWo|[mfYv}xJ{}Dvl ȊbW[V;~6xwѾNoN(XP,Q&"V#'voq(7,Sr~Ea7Pw7tg{Ş'T6ͣ2zR%uOc!Ϝ h( .op2>t/#d>ʗi{ ˣuMOr{J ĥIfe_}~O;sknnw,z[y>@I< B 2!> *XX)`M!ȵ'C6%DM*p#9 3FI@tï2T|2>y}Nj~!1ɶ-444`tt*h@ $Iq " JT'G Wg% I5 ӴPScX,HȏGGX cH4汢g=YvWIg~f%AD H,܀nEf%߉:۔gDcy2Qw ^DmQ~QXڟ3`& wDQ2سn<5&3]r #:udj83V3=zK׶udgs2MgeaϏ" gYxS PÃFn˞u?~UOy춺jjѢMe* u̜ _7%6+UtܖöO f|@t,JтN%&Og4pQ]~48vخI_ԥ)f"<0! rP.iVZ3Ma>_ #v7_;>uuon10 6sę>Lbq< h<8[1P$d4NYF ;nate}kVF_9nw>~2q=u' vä;X/>_G7A<\fYTSU `VJYshZEGD̬ RGmL?H&Sb1 ֌0ZR C)$4`@Ajefb-8'Gqm?H&(@DTZkA523s8 fҚ8׾oy%a,3$25kfh'LlN2sDc^ߕ?K۾c̲q9¯:>Z[g(F$&a~>[?Ƕ CHXCB'#?PN2Ruk!'ʯz|< Fn~jJ(+ [ƉTS$X^r']]] ox/>(>TP'%w#)w؎Qs} 0f45//~ .t<-{+] 2,_ym<Yk&Np86A$ CG2\wVH $纺;{H't8hQ a3`2!% "Ӑ^aF, HF2O cI0&eJ A6@&BS{TVDծ^ J2@tX~'O}a:'I!6)DAIAd!DCY*PJOh" M !O=,?x<P$l"`6HhKCs%rC pE=oX~jǂyp$ Dd0 0 "H ى&%QH/][Rw x[6q`Fmw a^Ajo:mc0\) kQ^y[q ψ%{պ:W/=di%ƫi;-[ٶu]2?C~WUYՇm>mX[[ @`mcwP>?^7Zi%CᲫ~4DK6wL񻺺DooM9-MU[ 4w.Bڴ zM38\ޭDU?FV{0kRk/ 0:4 HQx&P^kgR"M8 6p C"kOC:P0'x#HU7ٖ:2pF:,P#Clȱ@~꘭ HA2$0$l)NuF $h ӠU.㉦aTw|:YN*x' 2lXJC 86ے֔M5\o*nO3 4&MG8§L+BCT6 l (XXQOu]Ss]K@C҉! -I)6g2m*%ĕw=5g纖&QL$s| @KrHT_†331O\}64$q$NB' - '`"d0IC('ذakGe$σ˰q7Rۻ-8)]?tpA;>8 ;R{<}k)ORvGJ?Gd:c١IV6r,@ImA堥X@SZe9<|//////} ;~S.z>w[^}| CSb/<0 %51ZϺJlF[l;=F$A7-*xObu5Wd&vLAe_=?xJlF=מ{t%䱁Lر}?Gz;CZU5C$seΐ?=haE ~ ~F.nRZ&I BO7}z] Vv0C`S)?Wt0MXxbFUr։ rrK۬q|ܴ{6qvOCKˉbe_u  L`ɞٳN,V<͚s,7rG~Nb0eĊ613rGRh$MڤubרnilC bŨ'=Wja  -N=̉x==]`N̩rH鞐vܹ7u);woadކɝ9'AQ:\Nvl ο-\.':6lŏ{j?͏{jTLT¤.,{B5J-2)6p_De]8GOtG1"d UQbU :p idL?`!խtK/xZ(R)FAW 0 I@0]7ڝp2eIłF:ad7OL9*PZG2iZDvt?&S"#PB!<4 03k@C*;vR7(@[6'D7& tw? rPUTlq|_w8[twNq\.G5[^rG}WN~w=P>zU X<4gwo:`>:ūX<4R .ѻ|=Whhq|]_(K/vb}'GKWu{gkj=pt쥶?#L%zƆG N-̹8P4r|qbՋ86i_tß=񻺺DOۋ΅fWX@Ha$IHC.~QH&XfM$h/ ir )wu6a8@!0%$ I ^9d͒^d O~.sŚ%3K- "a\kt$@q>@>k 1 d ºY߆=D8vN6^yD)e D7Qs]~=!7w?xv)-j78xrgx"+⟴t)- nkzW¶P5%rW/@A? FksR)Do"~""~=~ܕuYG\6|G1Wݽמ{|Ys?>{,{+ސsm9-4]>ƧNΝo<]5 [j.o~7w.l;e[o;iSp~gVksz>0 iH|08o#<τ. iy @H3 ۸u's9٣]p6n0̮[D"fkX:"|o`.jNbYuk@ P?^MdM"gxQޱ>~﷿BuÛyeºuzSkWffnn}EC}7Pwf+nx[Ob[Sb67^}{E1odx~twzSy;OO,QRpj֥ƆE; }F }tzSy#/ _k7l:vHɽWxK'F%'$au٬YW[{Hpu}B{嵞^xSy#O, Czz`S'DWjHzzиlbbAN5|Lu&[P.k]q0l0<]%~j\NPw^u-~;SSdL6a}?M|v&|I\NtjRX8t*T2YWBր UdUѝUKeqd,fvf6@k_k|@{X':;J}2Lt֤R`"-pQUAXcm03ac\hO*an 0_1;]O5TR1~$A HЀiĘL](ċH !lH$BڊUEDL 1Ui*JV/DBH"oaB4Pda;E2n8|p+PN`6!>ongϺ0CZCTwD+tٶA Gc;9S>wos5[ڡ+}>KƍZaDfmlÂ%vu՗?>tzm.gv'^=o- !(h`CӺŧu.i~ҵ~>?\-% 餃Y9-5w:sgyN>뜌I}/n|hێ 4:kӹ`ܻ;\~NН&A塷3ϛi6 `hw|pkPx n13Dy/>w)4r5 4f`$Lw卿:o`bw߹2rW}W\̡Gݽ`IGg $*_/CzWv>@\/>ϟgYzy͝ ($DP_߼/衇&ݯw PsgyΪfNKݳӝR=eoٽ'ٹRgg?.n?̂ys>4Ȉmǎ[Ƈ&=ӷ|08 JTV1"2]9 1WV̇*guks9#La ^W~:ڽO9^ȅ1. )-c[BA^@BBJO* !@$T6ۏ x2f T#+]W CjZgg 7PՅ0+] 5@GU `(üz˝#O_1Ok bck^u߶ 3]#\`ˠKN럞Hշ}E;di QܺuM+?O+d^Ck挕+ :@[.M.):uWbMuM_Ij:v -$.:𺺺_Ç?Ko5|Ͱ ]%W߷ Nz.dH%c-m7^I?W5 ʭ4ha-q?*ϬgD&|%m2[RKS1yx:is}}sMu0.i!`uAϽzłOdj_Idct'&3ӊ+hp@JwauÂ|RA(tiTŸ ;k[.A@% =۲C~^k"~>+W.:fJ͆iJ2*Tq@J\ֵNo>>֒yb?Gc%`}.^ks9XV)^䐛SFxV_R*,c[kVl4R6mr֗\5}*O}7>~M7$(V~Qv=Q+˱B;FO:~Vlctx1:; |__p9VjHߜ[X+/p}%*_+ ʵk{g'|~'Xn" Vik VZkT\Wd0k׽f, ᾒ>9iV@`4WTU6+-Tff#%3JͤZظ͹Xbź0"sju*f 0լ0"f 1a & 2v f~y23 ) .0 G;Ӊ0 $!?#Oɟ`m%"]1#>h0 "bA ! Q< PS Y(F ԓ@i1NL5Busp}7 sOΪMX̒P&+b K ayu H9(i&NR5\LA\}_Q京lmD̊P#E ?~ bX+X\jQJ%j0w77^ 鮾*'b3@bid! +r#0ئ$%U&?yF|7Z_oU+1JoEx3n;KHa͜v=E U,n.uu_?o K.ZzDzTZ LN 9NW*.ǶeQfk5|2qnZ`p_ȴ5\DDcP &6d [x(uKϵ)5pu[28l_s5*1G)1Kmƛr CifvFkMrN(?4JW֝Von s-&Qۤ*0$altnaMssy-ǵ-3k>TO;w _՝`ݏڝ?k25  ̐D@PFAvVk]{o-[KU>͐\,߱ù*uuT&7jjKP<T[nX;ak|L9WןU ^___@D0l } cET*.,˪mlnu5ݢ q-t \Bpsɫ6lذK(F#:JAK&iVӬ3o-m936ahsˬEYB~~f%YTMrqwT-#?3oK$GտKK|,-6L#8mCؼMTu:Li$"P2& ӴcS``U@i,iش{ @i뿟raJ1y|;S1B!zCgk'67a54O`r0)lKHxEk9p+feyCuuYY:eAH3:0AR0 _HF3*,R5O}Y)]߶,ohȮ %lB0$D 5:0 NլCymCk.^q-<- !)EX tHA-a ^';+Ip"f_SI\x^ȟ=\6-OŭՁfؑD aH(1BSJj| C&96yºc.|߾uy&Yڶ>4.bDK>pmc}MM:saTQ@J$!S Ope.V h@ωWp:XuUTy}fU J&ڂ+>XG`$-j}OlqU*:my^ AFP+;ZCst9-q_{Y*kiYl{յ!46d̀hc6S \39 X^V{6q^]&XHAbnhM*껌6f)JG| Ì`Jx%}{,y*ppU"?![؉A=몚mк-FkhPJW5!`撶7]g5unÃJ,.m HdFlfT5'^]mv[;Cɗ1,'x&26WS̀\6!{#ڶcɡwƒ?˱3.9A,%gv[3 ԁȆ`gJf2=_n2at"KBI`!T&;,;Y1#~|!=W43$A4_nf2V*4RX$'ȯ@Oh)0,C-׼x`0^rB:n/Sb- %%E~ _3$Bѽj]Vn3@KÀU߂]Gk񘚗J-ޱcU/zQ2M@E)VZ1jNJAX+"YpQ&P@Ah^G9諐 \QP◎\8:*PNoh"!_+(phT ` nkSɅM?6(1Ix k@(T>^At=Y\41sѲ?%8UqJkD+B.-v'ݨ_%K/}ildx2UVBֶ%x<\99 "ݓ[jAY aP`Vv d>ID{ Q^纖Z$ŀ4 ˎab${rIguҥb1`D]AD2>I=3#_-{d aDKK XH 'ǁe;p h(^8ES&ΰcY2I%츀0щJ'[ ϗ+o飃f ΰc@ iSԂ k=CW- g\Wŧoy6H$"ʄY&' 쇞Wx+C]lVpF"42"t`HInQJK/+׽Ӌ@i3t7of)H83K` |֮;UpOg Rd"ػ!?܊Tv5"H+ 삕bJ e/qG=h)eAS&< 6ry _c?nMsMWKWA ILhKO (FbA,c~pX"b~q3+\?P RJˉQ P,VfDTgFbWx+h@3ޞP"^43UZR?ϼ9vK8_{逑@X*A Q<>a:+n/ɦc#R'&(+ A xf0nANjg3J Uc_ge2o&kw:lɡTzN`\N,>qi K>g鿼C:oO)UwL-Ʉ3G3s≘cØZ5o|ˮ?oS;_9 ]Nk>5?ugͯ_9sbc )Pus~o:hgg#xWI0BQ] GC>߃׿ʶ6݀4 Q~}[4~ʻg^hhln,{K!}愶;19^h6zBEi`'OWotB*f7JDDbIxaш^sB1P:l]M{A,s:n@3!K0lE[Owrm{YLx3aN5B)AW[s՞|Zg(t|4Lz(p2u_컓?C40$2$fLܷ_?߃ .B fЊِ=5%}?aeCJdi(ؐԟn* -stpGIjp3 :"3}aE+c2L\(@+}#tPXCTTwzF<|\|Bbdh|k !$Y:Nl'?hMcC#AP5x̑RnPu|ϼLǬzx0g2lnjѱ-d:ìfvFnovOcV &aΤclKHT*J:Pz"pTkS˫L) ?esX[DbfdR5} x晇; ==]ʐA nQ  Odt5,uY(6+ (X̬?wuɆ[9;(cYUlzī0g*϶kᮮ.ti?@v0&enq+a$Oo~ď`=0 {Km3̨}<|5N߇Gx-jH/f~HP*ڜrVT+l`^u5t*%T*GrF Lj?U'=uվ6rG F#N`9֠=iT4q/&*AQD)0E  2c03)'=X)[&;F$0T!mDCI3m/BdkQ|%KN(|oP8 D<_9`WGKӝKD샦)x9& )U:(PJ47f|C9w< cΥI1>(R,lˀ3DM}W&H^ ~Ay%i+ #Ѹ`2&*R,x-η^ܫ p+e*e@atu -klR*ڴj VD<Ҡ~k9ʼn@"r\"]?6c"#\G3  8Lp I^J9%b0SqBh–aGmJN71wJٖt; D*E&[Ϧe7[ 97Aq֤ٴLc])vj$ԴRbcd럚}oڝϐd5 il0}VK,c(L  AоVheXZXcɋHP aő΅4p애2w :p#ma'UM&mV2䯛/(HJ1x sV|/: رd,+nonc bJiW X lfp[-(EWX#VDAІc1Je;GXc@gs&>>q]uk VDi hwlVl[&զ {l@ؘt2vUO Hy DiLaۦd̦!)iLW9r8^믞ו^NTYn,lYiJ2 5744pq=D}~uTi&n]ڡ{ZH{.WmMqvW͐m-9WSz~qtsT)%r .;?FR rN?O?nkOX1Yvc]I$!&'9m[ RzH#'e iDۆɖ_R2"SJB<;%^J6H uFZؔRGyvdABJ?Us{N$l !% ?@Uܾ)A&C!-PW,cÎ[2` Ll%HĉC,4¦1. #+,7xn9YS B๨ɢT.aƗ L!@+̒D_'(Jy%m&ZGl廀Y4/>}}GipwBKi U֏Q}VyW')ҚIk]m!gDL',踼Ow }_#xj}Q*娊D& &XM'% Z.?=chxUp'Tc;vlIݠ@1 Ss3| _?ߗȏ,[_.W(J)u">*O?@A Jsg_>їڅ?ntuAr 5Ɨn*,LZ)V~<" i&I>$Ouu5}}RX/V1 w#IZ,Cg0)\ҍB,Yn3ڲĞ"AL!d@-Ť^h4TTca*\Oĵ%&u>D0$J2ӗ0 І 8:3_~Rk4rLZ&KXQ ҥRI cO/@QaeP". ``D !P(M' i X1!:( `*z&X @H4P~ Z0^8CVFRN5 DwЬ' ]& qgg0#Кeu"vIR3'9'z5 CQ?zL>c&;_h96!.!ڭʈcjA{ّ+oBJŒ 4B浐?{9\Ȝx0~$/Q*ҝ*'&{vPܟ%W"Dv5’B%y};LfJUxKf{Z0"DO$ -Ql|}#CCw&jk&C ߺ?e3%Y]@l0J )Ţ771`eX؝YJ>Rv|5._g SF,O:U*4C?5|^ {Cp2'WmdfA" LJjFUFǓ ?z Dm/fjw\4'J#`.et(ZòL?dwUX[6%?K?_I/i̦$vu<^h-L14/ܲNs '(|5.M;sbSu׻/8) S:~BӠIRZ+]R[ARB3Vhg 2MH&?Ncqf-cxTpq 6B,PQ~!`Q)*_XX?9>ʳ뗆_,FI+P`zP 0;! (A$Ɗ- /ƊD*O ޣgA\i*)FJ&ҮPUN>&XX ʀE Lҁ "3>;A^ xdʖ3;V= hX"q ]mZVkkK!MR@p"JL*S" MW\qgxx'^x̓Hv!*ߔ- CJFTٔfStx^X:9f[_$C/[DD dd CgbŬX4C1CJdݡk\񂯌atm}PJ=9'I)ۅ7ֺaX4k-$@׋l<|XymY_r:'} ¨z̽D$e à-0D VбA02rI*SF<*0VvR~;cC#3@Bt*Uu,(PXH\W-1p .9FLPU} ֌`mwŲ{7+.I%]h %(+.rѱHw΍ڲhX솝xw,G2v-]z*g&bfeNƬmpΐu` T 85?G6q3dw̉;[2T3Z6ƊEhP^BQjJƶ( R iDwŠ(ahI + Ϩ}'TXD==]rAmy(hL BF 2lxATFwr NEDG%fEB 8ĠT RYW3MihZj8q^2rSrImQ h^^qafhfVelp?pۤGY] vǒwΫk6[wIۜ9i%֊N~0ʥbVVec1``=]Kڇwd/՜M3Zif4\,y'X4߿}Яt^~wXv(a4CFI.Hj{񙓖͛]˲ (f. `hXzWG3RwaQf* Crd|Ti% sZ qZjmwĺQ5X&5sUUM S@ 44w5]6T[5 -*Fk&#Vk+ARP~W=q.)w\=]u+ )e˓sVhiXҰ*4~66:so~*^=GP @TS.omYJe# &ToFDg_uOBX'>iyS6:ǐF)( #7 PG|ujjvڌqA5Jq7 0V$J}STX=olT"i5J@)oHadtMgceWk3=h/`h2WD:%/}6 b}f(ae"/A'j0uF3@116PpFgs]Ro|Ҳh!:6tw.mv2Fri͛涶Ʃ%ˣ &.>TK񚖒^ۼcֺV-O<IҌ u0v4j 1 mv;'MX=[ZE,F0}oOPq-\$`,_wɟ<{_.<K/衇5%g-;ٷ'X'^wcEh_Wgh7_?8ƒՙQwǿ; Ox+ 7<*l/5;zEq{G^x['-i_1R.Ky8Ĵo\g6^ɧ!nj=o r?x[ub Om_uaXOho90-h۷`5]C1* S12k]2Έg'Ew =R2\{3#?Z]I(?PNZ3Ͻ7GϞf]H*P`hVq_yW֠|!}D#pЁ{f͍,o'5nܖuY_*Uuurk}wR˹8hH9O9dsf7}άO;b¿M΂ M~`X6`ufq5s[jXۚyMմ7=Z>g~N"v{m|v 5.9u{,;fњ;Q.^q 9Gv!-\rأ «o!?Ux]npdxraK^CvǖkytɼG,l;t~IW\spLbf[7~;!Xkc̣s2}2߹w~ $ճ ;fudL&V<zzY=čdb4"Բs-ճ +t5lcs>L upb@9-Y#.?؋tJ 81ygxAE,@,̦鏅c$0ov}60Ob;Pe-']m΃OĜdkkܔM8}:>JIg: IQ}AaOV䬅Iq4T=5!4cgΚ=;2K:N܃۔g5&kd̲ws2řd6-Zcg6%܍H؉?!2YDzT/i.邬N߭䄝XZje;v8s 3⩐cz|[#dⵍSlgQ[ߌl}3S߂x<~A WtL{O>")s&WL)_uIdIqwHqcqId†mtn8)ԡPLH3Y$@i 2 '0X)M0f\0̨>riO@y3"jo ͓b=0 (4BRQ%P Z3O!$u%|9 Mc9B$}xs$:_{ρ-|?P B>9P "|@[uazlʴ*Pq @Un3e&w_pY3j[z\'x^\]U?{?/u{_shagUK> |Qv=5k/SwZfN憚V/P:PJ*)v^ZT@j^fNvQLQzZTIiƄKR 5/w5{N `&!dgѡe060G 30Մ?qÐ. j|"D;3WW=-v232bЌ|…Hh}1gF<ec xU 'vbи8 3N9YU~Aтz!~O5-U9HM*OP:`>mB҃ɏt[B8,!w $'V2^M+)בFo$h&/ZT\{@FF5;k{jZ0:B~DafM34LOLg|n?2v;&">sF̹}:G>]Lg).: ɏsʏ6m#t}goc) Ͱ0I9KtBS|c!BiT o}>C~ͧdSөA|""{BU,y=USWw~l *tj>XqS?³z-x'`P>]3ʝOt֏o_[>uqTu"ptֿ~~|x'`Dd>Wgu;=Co9qLwvvrzT3tOp%&x?F_6CbCX3G( qL&Vpc ;-lXƹ 1# >g1lCm}υHXMM|4]]{{Cƺd 4O{H6rMmMB;c9L64MkUUr0)OM&5ɛ>{B{*j<&k#LY7}vBwO;p։uQJ|__>˅'եKJ9g0rX9*b>KR5SxYb]gxJEi%Rf;_vH+p̠`] A]3yNis\%, B"iq*b [_ G_5Fg `4VZUCo#qpzz;i̮[RYyDS^mOxQF2/4,D,=O96- Z߅_̚}t¸I@[e@| MK*gc{ 0$|W*38ŀp^2n峅Gz@V g}t<l8\W0mH{ %-9th:+qXj[j^C>[,||ę=? %  1WbpLW`C_s_ ̕H `#^Fx|_*e40s'*OogI}}X*e6X}!]ˣ3HPN~?퇲E3_ ѩRǽ5 )`a@,v 瑦ivTfgL5|^iIÀ?]74"0kēiNk?".dZF4$m"͙+SMJvol+n/&".q؃r3.l^*[YIA*''Vf]~gek=bY6?}?H dᏘRf|p&YgDCۗcGJރĢy۾J%7>lvĂih֬wYl!N3H<[qX=@\SZNȪ I]IZk.J*$5VhQ.͙Y˝Y[V#+&1< RBK irCcÃWMSq)i"=Pgy:8&̺0ljتw=Tmל4->ԉA2Wu `Qb֊ $qMY^Ug䟴4RUav^"f؂0Lkk2k2#UxzGJP=cx퇰=/B\}|r7nƯ޻'m'b;֌P]վq9͛k?0iwWA, h_?6oۼݽ3#sw5f[i@-!ͺ!6͍ޯ{'aمn;EUKk]sQr nIRjQ̵+i!%o^uo 7Qk#`&Rqk'l=g&Oh@!g0Pxf^QT鄗{.;]gc$G[B2]#D2lstWvl2x! !%5vʣ?a;Ϣ:ؒ0\ 昂J'|Ï_xv0>rD'-ni+ 籀!ac wN">,)M!=N횠[5lz~@}ӿvŎYp4`uagVh;+eT-;<:Q{]h߿ⴋY(&N$PAhKk|v"tMֶwxtnls˧μl@κb'Tށd25@*`bq[L:a;NNѭm{їͪO`\ogx? BcP}٦`0bX^cږA!n5iG,lVsmጘ}Ͻx}D"SɄO$4Hzd¶, c']IieP5 RM5?MhL u## I,G@^;m oo8"| yH4ΟWSߞ{>{m: ѷ]Ö.p&m^KKOmˀKT®-1Ud.r} O)(fbԦc2R/'`*ĤTk6ۚ G SEG>3"@N<۶6\ALĮwYxvPW2j+TxPj}!S@!L2 BzO`z85g>s%IR;VR:t֡">3Yڴw5W1+%=%͖hVYiFtE=A@g(cWWaV2ttɮvjUcEC :qj.A4hR @VRoV$$#jרwg/U``X5CH Z`@Hw!+`؃_-dFZ}=s?A0LZ+h! ÇE )RkMR)G&wNK_?~`260R(ņBu*v.?qa[ȏvFrBd?&gsI3?T`&}yiV5sgtH۽MnIQ^թkYⵧjg}Տ󅕄g*O%Uݱޚ~ya/F)M|ӵ4LO%;cLL1rb0bIdL_|1G,w!͍I͛5;&qT1~2mۄXJR-taݻhAi?L7o|>ϟ^ڐƩ$IICmF|4!Pmc;1=3^BV(҆d<;5HX,' O&m,^s|6| /8ǥCLoG //D6q;pWM֧^/] QMc/i2`u{U102eK1 l+/1u~wCH]_+4+Xp}&S48\1h͐Qt#y=OqhVR 0Vz@Hãq NO Ru]+.<%hxxC"%iEh*#w됆JXqNdu:3>A>(*&Fr*~8-jKV 3(k&<AH_hM\i'\Wx RTn#]w0 hcbۆhK8ͦSR;;1R`_ԏvu4LɩqR C&OXGw ie"t:T&b&l~j>IB$<ƈ(RڀqrTݭgZ,XI H`dؼpjx @j8$`0f6caoef4[w߭y#ɚNpq[``ï:0* OժDx`{ l489k6ހKFk_JʲcmعNF"`4[r1#UkRu9ߵ8*JCuWWB@~t X-/+KsBkw[]8RQAD\[l 95CE^U)!WݠJ}E>1w*Ln G~k8K F֪zߴbH:톏}‘[ۭpc}V+_&[@ Y(B+ߚ ZZXFHQ;Ea jc~!oGdV,wDD P)y FcN5 >qCM][G~)ˌsQ}lb!3@,7G]M޵kBv<3sKY:z¼! . wYfwMLwoo}I 8Qe~(dI<\|5<υ 3eem<~𺿽b;zx87F2dۺ:lgʳTy V:W\6+q6V'qVT;DdE]4ޗ<6X##~α2un3 ~g}0!Z1S: hU>"lrs Ҝւ7^/>aqG97-"a$\-lw:8< Ǫ=&!2܇ZG8+ yaauðځռ&w?433#VQY ,lrՐ~gE<b#s-aFtzcILB2iN&Ќ^R;/*|@I+bKXXQ(瀞W:\9cv4D??5YyӢ>ɏflؼwMUcojh"g=5Yvf`Myפa:hh"Hݟ=^oqnD mIo^ZA sͪƸ&@|?ۺek$[)XWuO/?۴5I81t-2`!Z%!xnPSvi^$ D`NyE[[ p, vy)@42aLݽxqP}l U|N1g8oaq`̂mVhƦhå|Á{o}΃ΏB ~g?^P(8癋E.:8kvbo??}sp ^4juH$Ns[vvR_Wn'Ý=_ХoԿ Eeb+?NRCX9NRS,&'!"M[ ʹTҷ~uo"˸ӂ&@-b8K]R<ݾ/;)O, eT,_x%pr$:/7+`|]7K DZv VSάI$Q{{,GN★-!f162eE/u]Z~p_j8 6yO98"q]Mcɑ˭1麡?xQԟ±aL=M.8ODD'჈>oOvfYwa_ߓR9 r +'{o?oGeL܅}H{ELr!4RNw?yE;{u|X?vMXđ11>9_Q|SqrVz"ksIzGxb(PPV` )QG؜uI9 PeN O1N,7H% } }3k:0IJ,qThQJ# ^@Kg)b%6?+˰V>fu1Sc@8"@5ΒeIbQA1y.7#^έ-44.9`m88kWw^u1“G9fX^yoIa8MKbͼB=;/˟b73kevVz_u0ucZp^#`y=ƙ{gB}Gl"= "+tOƹX9T }dAnĩw,ScW7f.85k!Z+y=",0Uj] nm~gAD<>|σyФ>*D6vUYJ\?}нAVVtY{{fw*rpkBox{?p7i VVEZ]ݵkbEEՏ_ߔwZZ0;'':.&k=WON }ߺCoJ&"f9y쮉 jCg[ٛEKWkK0;EfӼql7rY䤛ww7q!« avVSuGx s!tBיbqf}(&ej2]ss!9lV\C\ -sy~u\GdI9r;I9g'|+\8^ }O:] v{lΝ ڽnn陙; ]at놕=udw_M;Yj.Nd-ucS? \yLTV@񥳳swsdcp*Ƈzawрڳ2k !*D@M]:$ >&97$"U3ż,f y]ح ع^ +}u "R]>D#yN@zsћ螳4{"AH9R=B c6${۷癩 ɻ̐ɝskC@ JXqsl5)m9>9$Mw/,3+aQDZu .&L,H^OB;d7W⃳s(fqG1!g->qI'ަGi~Β3 ]q19v7~;X-" 8Ft[AyRc`-{&']1]Oԑw9-B܋=(2ʲ+miOfa>sII81 qۿj eyNqBXvj2s/-BX-\+(NۛعZ !,ޖ-ٗ92F(_DD+ŎJ^`vݭĹ}JcK|@J.:qoϝ޲i,2&tmՏW8I'41*fB?눨X8+TK/p"xc<6>LDZC7}{Ib^ZPp/C#;S9&mlJyIW_{Z-ayvf^@iRLy$@+RyFWտ=9р{8z}kqQ ;1Vle,9R /c,W|w߽?l4߻l tӚǽ;T{8|ٓw:ٵKO~{a*VS/ _X8px:'_vН7 }bzRfL,'lq&&O{C+;HV&4{NSo6'̽'j.VY0{qۿ=N^!D֪$T뛽Ϯ L"WdR9pcW~܏thP8"R ra#k_.DՉh(CY;4)RY:R.=dy/ecl;wqFCircҚh9>){rk~˗h@i?d-;*\gom]Ϟ=(C)H"rV>g*ބ4WDwl}l;Z{It0_"D[&"D["zu]l҃ Oq78,U*cZ_MЧroޏqZ7S?(sq%oN~gLM\ӡ$IT$*w.{aЧp#p@9z0e般~>O;vL:rNg%99r|W|#;ҎI柷Y4 6O&R{>ۑ]+r)3&|&HirȳLigdcw:4ƟID> +Ѿ1>_vv~~DNc?)4EfKGeγ};wVSo; Y1onWdE-sČ_vUT v6e̗yasK:P=<8/ K$=ߩ:?oE%aV{3یxl6:[kn!g:px.ψ%6S t HZ)RJݳ"xZ(X?4 !k֪cgg99G?]R]dPrY$:gTڹs$ ~bkgfaS8cl37>H3)Ϳ&o/դki>A _.wTxJz 8f$~dף,57zg~Q,ʨY?=:hʼn>s(R 2˝}SGӤ;~>@r(kAEf^Xri?uu ln+/z5\+JA+ N E5[a _)5O^qY)X^`"aH#źJ?x57<&~㲋J.0NC8"Oiruy\7[cOKwOoyycC5??G3FS~?w/^{7>|bA>'u}?5x_J_x(o^wםS ߹3:Y ӻvz O9wCZXvp%foy+3??U=Jid+]ruʕjSۭyi4ԩmPKv9a|W\Vcͯ_DŽe#_κ76h`%Ą=LJh`J-|Vw'{;K_3!:`>Guhz/Rn|H[:G ă75%/U=xךW ^UNW_~h݃2={O=xΆlE7rZݐ̓uׯٸi w߉ii(WwΗ=gic<|x~=9ql]4PޘdZɻ>GGK[s Oo^nc /+oL{pz!S߲~-3L~=޳gϼR*1݃}/>UR۵ zYWZP{pZ?4azمk/jg jHe=q;1{=]JNƿ/ֺu2_mM4C]o+a^PU~6niwpo|࿣z .x@+RP?x}ulZb|[= g{ƳFRO]kۿntduG\_E[mӇ|.>jjȣ'j۾&=ʿns;u{=ZE/߷I^wӟ{ZEȇm]wƆ>tpn}>}=tsvuw^)'ݚN=4y.~Q6^PzKG.莵9{*JR]_ `w chh(z)MZnYB2^ Iem/%%ۊh_Oyi9Co=j nig>x9[? mSP| mO^VW/{olAn89x/~ƦӷgnV/!@m'rs{Kpo^qrnڊOO?mr5J6oT _@+.W /}9|Z%jFc: fdpm?:*.*WKO_7ҳ7 y{q |z__nJ2::*kr\YgҳNkdǶW9hVz=zUZډ:Gś*˫mֆֿ\ik#PaOr&?E<:湈6Ο5C*|{·^aom쬁F}ũ5}Щ ޢWxK>?}:W%g W[W$9O:U_S>x xwV>7| }kG!| ^‹~Yl\S7=^>w`pPJQxt\\6h4d K|GqFVy񌋼J\2Io sαsN;k:F7?swrr= ;( Ӂ"9lzttXӀ,l9bRpPw;\7TYo. NLMqsd~MP*EmК͵zv2Ga̷b΍I"ONZ>6#Mci[>Co(XX |i' T o\V Lw80)26gD J& ViX mFqc1om۰yThO,cl?[qc/Zk sY DvLE&д7ٵK~ř<~qdz]7$lxK}{Fʻܰ_p&w/9g |'\tU˟V ۜN|Y[}ƥw+NΟГ&[`<ӮFՏ3_^-s4e<ϽyzГl;^>eCUm Jej)f,wmEg׿7e%'&&G9gnT)?:9Z)$M)Ov.8^QL;h\ jPi^Z`R^[n^jJ,,->pURv]zc'N!q݉ib1TBP–?9w\rɩOoOZsS''cU-jM@3YROݕ?0<'U(W[r!ӂ*?goou)E Ha5[PAngQ)c=BR=ߞ$RJa䑑fnm@ cgL~MwuZ.r+M5p!oũ#U^#]wxj:ċJesg;JN0/ 3sMϵr( ̔NiFY}8Itq1nx!eƩXk3O0u VaJҌ42r 6퀣nz/2cI30hGzI&_Coͦ~?+vpD;}9Df{6 =19a8'm94uyTcn8"lc;v4sʕrFI ,#cnYRʪnǎIwuPDfVg99Y#oR(I ڝiKQp%*p;&'6{PXf3'ϼܗ@{Q)3ijJ#У+bѾpN|[Ty.T/E%Js8?\~]Խ'3]H=vG 1 :l)$g> `t[r4NJ0(PujhxН~.ܩ 2 "PD,̿'-sjA`,Xppj;/W9A`l>2z\-3d *D8ϲ_x p [֯v>rDD<`MvWSHPڻ7ΌEQ8Jl[|(@6w:?[~`-CQX? }Mc]D>,E7Jϭ+~pn@ȍ{4mgl~½yjn6sŨ\{cN ?oڞH(Rsss 1'⛲^in=0jv~qz#<~)Ƹޯv'YfגeVͷց"dY)U;5Yz|f t1<}TudzM1-]z_%޿u&q^\JD*. wb#rPyH0ra`Ъn-|O¯ WxCkv76E:\  mꐇ-` ^h -?{3uq+y 47EA)Xiv@P8N|bVw˵ow.z8cJ)MR\Fȋ\]˄JǾg [yS{^W"Ae-O]LDHRk@("Kر>ߕa-{o$Myj2_~ l( .<q\RxYI $x8>Zi`ZK+yV01QFX+W(Jv fY} znxO[WFxDZoR dm燐Իw7ȿ؆w%V؉c}j@ )qk1 RT(9I `+#wu{x9Qmfinaut"=}M?4484Q)g ?' BIQ*c 妸7-_@>PA K/W. h}:Np LT JpvjM-:s6+Փ~N@Ҁxvؤ%v@C)z:j /l+iAzeHC;0۷7m{fq¬K :(m+%.uG!i4x{igffn\\hYH[XI*N/ mfs]o`=/EK55zvđFj4y37Vzc0Dky_eme5yf޳gkI}Q>Py:.?S )={ދOe6k $NQ Q=[f6[nq`Bl=T8*R:ޣW<1b9Wpgy ` fKebwfj$"qm"(H71V+UkZ{hHƢ;wzL"IRJQP*kq檕h@kv!Kҽz_.Ĺ|?ͬQzT7*r%͌o@!,,/,8]V%$5#qR^*qI"K^ fǶKX ~= "B Zz SY878izO?*HŨTRW^ \rM*l_F C؃%hϻuphw`0S|j<M?r +?\ǖ)ͳu7`iGl2&o[33R}?ZX`LoVlkk33{ haWEc܁~_y|{~Io1;|__pEgkM ʁ~ ?ݱ4$ǽ}t 6;fDU i=BC Mkq+W7% 860XN!m^'o66MkW_pn2Dǭ6qp>Wqǩ<8B]/l6 .x]OŅ6["E~T 'V[nl6WO{™s}?/D{Zn6;)( ĤYr|>qc n7.87'}85mf iIMg ۷l>{/<nusDDQ$q'ylJu6EJj6Oo}qTpz_Ega=cAdM$1lH%`3׭gTq,Z}DQng_gahrNG&mczɨ' pHqjQ-[kk}q~֨knԾ|h H$RT^xe؏_4>uB[&w֥krnaEJe~y: 9Q/`m.JRY)*9IZ+4E&fqk}o 8QYs៾ WTqY!'UE;f C`TsY=}oM[xYߦ5i;+CpYZ JUк$mho^vgus[Ivڕ5dY眔e˗+Dر󼨵87|%眳gkHEj,sp )ECrUI}cbwK6ݶnm6k. }%=rEumg^̵yۂ(Fk Ue乁s,ar]o[v;LJ?.?kRUXX;-`'3UnN}x/)2-p&"^6zo\s~@/gaF:|UUT_"ᒝ+qュ9{˥ N}^_vsQq%kz: trcngvV*~Rn (B9|ln UlE_ں^p<yս}1 q.9be`vi3R?}݄P Tע0H18\]{9z;$[wYk5oIx{"՘x-mZ;@_K2 Bo<X]V"@3?P]M*-.ln@GP!*{A9@L:V 8s`3pZ䚝 /142=3]H Q9zG6j-Efۣ0[_%kW+Ri44<RW;kWn)k7Y3flL844 a,"֘)6L;L)8KlJ#F)CmxU [!:dv BIMHmD$+4( gMf2+L2&SL^ p`MN&ufTkZ~9g8r#XR__ A¾p LnwGl\}akVRu._Lr3L~Oؔ,< ֬D ,K`M/M#kOm>_s|D+" c jf5j5;}¦{??}v{ 17YR$J)2Ɛgl:A`5ȍlކuѫ|BIlAZ##G\q3*U"̀,}}t?vT)>EZ[\xkHDTZbǏcbw!dNCxhufs<xq Cp!xs^Y4{L2CG}Eu!kT.Gc JLP,,MtZۋ(Uj ' RVWfCYn:x'C;qHS8qpNTd XX>ˡ8ah,2:9rfif2cZuP:qt:r$M$ 2L7Kf 2WdF:DY[xrd?=k TԠ}/Xtfg% JD/Fr~,EIYk $6رju־ta~h௽l&3%YMDׯypΡT*ֺTU8kUfnva֑O 9>43dZt޽'hT$`(8KtHVKvthg `Ղ O"MZ[T+ȍ̑y#~ܹǭl'00@CkEZ aC'5,PJ={*x&qc-$ €5GfP!xj ` .k(F՞ZH~ړa;w~}_yyr<_ra!SZ7X*2raMwOڏT7=w|p߳{>-p<;@@ ';F:g G gաᑏ]dOxWZ0_)됳`'|2_ ><{׽=}?zs,tk  Y핲@ͶZ?W-=ZV5u}w=cJK.]-{^r|rpR5jfn.3OOOó{\E=!(; 1HLA$RU#,뿼ZϘ@&8ZT_'qӡju굚QA_H)t:1Xk0蛿 :Dk޾{n 4( Y@¨0B8lP"m|RXiOi$ 8gP8 g3p#p & ر*_+Z sp<ːj}XasP CpYNO^q&vLEjIg0yj׌: Yn`2v튋.ŽɓTZsʥC}"pN kSk"4En (J^z39nj" vEK<X'OӅF_ՒP')(!k`a (q,0$I.|gnsGcl3- /x0<+|2,ݢY3nxDާŢщ`"tn~9Dg=934;П}@v7<":9rsdDJ1(: NWv7Q>S HucQ|qȓYkѡ?}h4=j8;Ա[R;QgYi] l8541{1>q;K3VWp,8p |/y2Ekރ8i!Bs t:J)t} *COe4>sp pyffgw8tV:kVJs옥g>y{w)U-lؘ+"a0V8%SJ+~uMY6kc<^Z)1"jgZ\Q0v#4Ap"˒bgÅ͓((*O9=GB\J066,HYdAbXd"Jц$|(0 ղZ%BXOD kG.<r̂r!&Gpv! zaG}RB4Q pg.逓CtWC3B`u5. ꣨9Au.`i @ݠ-DT\atF` I]i)~SׯVpk֬ՎnWV+%T"T"5#uի0ơ04+A\j[3< ||OZ 0_B #-z9ϋ{Y B T#MUZQ\)atxZ:$]Hp\.^(۽pq6Dʦ7E`K/S Od7<ھ"QHX!0#^XAit+Us37~"m?Q8E0K1:;0;q:R#k6X};2{K?hxۛ=a{혻pp0,#'[l~RnXAxiŲ8ݳ= NkZ9@n9פT;o|1>5WL`sa!HةVsܳ'TO `2AJmdNϡ}h  @ˆ*!GOr`Xn{*B幊ps@'`z7: 9Ya{fhqDA1[1j DaǼ`h6+_),$2D᪐Pa{ If2)YxE]MY焝tWaBk$IF!4 ,zr'{ Ōd_ pH{P~A:H2zg"y[sk?1#V/bNs b`؆M[gj~a1v.Ww1_3N63(MP=D 0֎ bdN:I{,~4sgjm;7KyOJ%"Ɗ1:ɝOK,owfiwkR 0FY%Y'ji['Ot7*bg<5;w._vkz!ڙqg xI]0Xn9fTZWs)IvMK`G`#"PJ4Q|YGʞWbk:Jzs]D?]/ ta7iP~ Q]3DrKyVM(J-d7/MdR/A/2vdgEdm*bG19xٹiUb > cOs@aT5Oik17ϷP=Mb|?@׬@<J)6_d)"Ą/pe?(V1SG1; *aBtm?53s" }d׮ knX;f! D1%KXJ7obN>SZ B%q;CO3s7br[?17ܽ`Qb=E.XDee_$zW  Н@6;$)G)}# s/7x_mDm:d D:~x iYp vb˷^,k3wF,eQA*(J,XrN6Ln 侓ڱۋwLJ.9I [Z\@$o/''GZH{XҜ- v[~uS^@P#[A<>z}~@!X贗b~iV hrrB1Ej8ECϭ|]<929S?8^W~iPSU/x֍(W*ELaw!CY7~xGy~3xКG e@dG`!pNm@e<+׼kjE ~Btu4>!\wG/"$.'2/_y vM;NRԻBt_ td:0y`F`%9`392Gf|ޛwML')Oc®G Y 8']م+qbbB(y>uCGjHV`9&cl$8Wk{O_(ygnx`CО߽6E-"ZnJN" =}}N}"C}qbKuܛ?܉˱E.V귈v-EDAagBh(1絗)'vl6Άk.Lmד{Z)lGs. Iڹ}?:Rё +>F}OLaj?Ϯr;YuaS+W/L-?_u! 쟳^^t aX`B8*{KI: B.L ˨ad. J:0-(b PI:I[{:; ɟmudpI*oFRͭ^UsCT߅/<·֧jjlݙ'D$zoĵg p.ZcPD;qU"|u-ĀR}A[v&հC;y#_\wUyۦWϽ.ګ"AA<{=mں5^ů Ս*?hYbcI6J??|m֭CڟG_H>:*DZ| } zg/⭉F8Ӆ6َFP}oD+|_x;ỗ ҝ]d]5pK'8.؄/@~W,u;?/ 8mr+e7TJr_w?v8·js[SD#c7ٶ6Ո;|Hk?oEklKn۲ɖ0* Ԉ6p&W?n[bk"4ٖcP6/GWoB`5wL 2a9"`  O+^[Tgs]l?)mRb9E+"<_/L"mt"Dr9 ^+6zDTWۑkz26}uKIX˫ވ`ʰ0J=Q)#Xwf^xlM~RQ0+Dx"P{{pB۔l6}ҵKI970Oh(|#϶zhhXo.g?=^Xث#i|t׊cwٗqq}iȷ5`pP1;%.#Dϻ?-Վ?m=9~h.5$Dw}[mAxU;R\(6;>lC4 W_p!X\ӎs>8TJƠpw5`@q+:I@ <<B{ꎻӎ%WĖ1]xcs]׾3j\Xv b+NM>^5@\xzg>RJ$Ƃ\~l*ObXI&"bH+O^Y$49C38+R4* #(EWeO_uZL_iL\4*Q`¯S_z8䕐QkCWf~9zfj'qZJӨI *\?q4l$,Qz1g-Y 8V Xtqpj+fh̠Za k&3aڎoaEG>|>S0oX %7ټ9c_~A55N?y+Tc5Ngȼm+_?V7'6{`ӽ]+֭Zv$/A\rF廱[…4`f⾾*랿*?G,τZڿ̜VW{L_raZ8o]*?Z׮xuOݏ?FPڵvulL{eϏ6Of_6>wokd׽WW.}53x|6OߝhY?d-~CU{kk[>t3w}_-xuw_o ;ﯝN̛6͏tڿ.:;iu:wҪ3?9‚9 SKH]tSpj͛3hK}W:ۆ/}痙*prs&c7ЗS߮~gʿƇBAi/L՗NLwqCgz'9/=&AskmםͿ;}߮\7)c~:V~ڐO}oN:p˯7_Mo_u=9OoɫgwEo8wp3=,M߅#m/ ݯ ?~|{?Ϗ|f9#|c&#f ̷E9.$:v_} Կzx_/D0!o"P(DžIܱ᫪ooI-\ذSWh<4A9"2|Éc6ƢJgvqtOyiњ{SNh2dM](;>+ >ܝhYjc,9!/xl|޲dQ.^ B"Y7u _A٬ɤ- #B;z~`wE.Y$!5w%͎wdAD *qP>pY'>vokc "U>&sFwKK"ym'TޏG'wpttܻIJB|ڎW8Gk-e#/ǃ9bkMXWT`ˇ7iholl>h9sXvl5@C̺Ǝ%o6>t_9shmz+iknlg}nDSGЯumvlNakkmx5MF&ft]܆&sg_y޺wn?wuKrMC`п0[~@:.DZW8&[܀S-膲QWͧrjW ֊_ z7b&G,xaҶ#$q@&7ZV]NORAEbg56]eU@[6ȶNx~L&#˚kc--wt'O}/RV}4jQL\VoҖ%ȶMd bDC~e_Cܟ8݊1HWҧna 8D̹.jJkKBߛaNV⹶#j[J :;xp$H9#H]bi5dY0 "A`]XL&#aXGWt1cjo.|b @q>y􊎕Ͽ2=;Q͡m^u%u3/a"B4)?-ҌV.X tw n<zҥ_ҚH˻^yJk4:rmB Z@aGt<9|Jk2oV:x`NLu[D4YOnT%^gSNI_u#} '[;hqtZׁ[ ?SN;F75gG ,YDI)?TW-i/MF#LX\[g}v4件8D R:Tbܓ&]qLy2qPb$H_־ԎD^<0 bǶZ熀< ܶz4Ոn(%%Ѧh1$0u@ZQK [+-W+~=iGd[oYt TJen*ik+&UxzhvW6uPQ,!#ڱ$8.TiWҍEq.z*-!c.IfWRPGJ#Ю-NVysgfJ6ԧ #1unm%-K^ p]$$FZRK)O?5235IYdaW!3Eao,9Bt6T1e9JU7۬Ƶ3H;RV(u׭lN eC~l'Y *XS X a`axv{FJ2̒l6kB33O<Jm[,BXI+jeMYBWكa6٫XҪ,Z0Y?iee6?0ҨC00Hxڰm"4:ݦ.k\aӆbTY7rQ»R:W"(?;bCe6HYn"*3˙ Jk-l]MK֬ F߯ks󆶼baAk-~ג+V&&' wAsdxoCW]۱w3 }΃Ue/^F0#2ew4Mdžtz,[.u\/0В~{עG;fɃ- /`Yb&̅1*sڮֆȣK;6W%RKเ7jxtSʗԶB}|ѶܗjY(AȆ$$ 1|[: T𬰬#D)d B>sgǣ5vtW&!B*cRa Fd=Z+Ȳ3*Olb}v@'}<=%utU`Ki I5W֚\eRZFZkv]GXsܳOM_Po|}mgyB 6hIF]mGl km ;%f// =52]b``@o.ߗg}H-$ A$aцHYB yضᙧ*eo\8*8peXP0\ێbb ma۲DPW>539}_;oQ[\tֿց "JY$"F2uh K$%/ ٌTy- 2{Y_)JY$LsiN ~v@ooe˯-O{~}/S#Emt@H!SߌVL% Ҳ[J`?0zm{ˏo~~SEcʧԛAdZ(ťD)ϓcƿ׿9/^jC J%A2 %cJgp[o|=tE#@ BD>4XBa.MOԆ{~1qz8.&F` #TI\ xsh7xOWby0IB~ʐ_ {k/\q1ybH0BH7P:6B8.[A;mI&c _tGzzumefBK& (BO64'0ޥ~]̠_$L0j*0HDT{i_U )2K#3B~Bn6ql9?5 2!BlU´;,=-Ju/\ D!5JccaI,ՠucB~|Cĝf,҇%kc$ȞȾ0P9ce~Ű{Gu;[ZΞ.!S/$A0b2(M[:( hv=?{9& E㲺;uv]MPK@U>iY.-hà >?_=>{ϳ1Eo&C=iͭwvkjZSeW ,0^ؕymozLpg],rvUaF/$3[2b@Ø*yeL{~?G΄sC45'lj;fXP!T$,fHŀZcKw>؟N|p"1K/76w2EJ.>u$I$ȉcz`Vίzd,E/oda1sȷd1'Յ(ٶ,`QXB<;uDcotLȗR&Oz톹@ YՂu L5G/sŠYuat34D2"g^В_D4±kNs~q, Z!bނS w~\B5lhs߬9QXJҲ (7 "K> (D=Qx۶B5sG\R&a6U^M?@.Ǯ{xhxw*cÿxPpN4ltQ]f~atJˎyM(ް(iO;ŗm]<0HQ$ "HSXnaa*8UuUb- .B@&whx"ʚW~?z ,Nu켟VpsA 2uc[s٬A_}]'eaYnI /--k\\5 I#!?;٬\]{R7` Klʯ?ȯUX9 ]qN+8;0Yv .j fVW\D#c[V",`^ΓXҲڄU%φfokOO M r $"7L}kJ=ѳYff}-7'Z+*`1HZDˊ~w_Wi!0lAfRzS B[r{bDhL8\د~Uris9sAyyOIQjK>$HBD)kom%\zƉفЧa/?\#bF?eK!0O1Ga/q,KbQKqWݱb[-NjUׂf0 )#n-TOB6V:-lBИjӖ^&vd}l=DLVĎ&[A$ BqW:h0-;t:cʼn0< 0eEDDt"+#W0bkgksr~o@kYY;Od_JYn+WZ"ǖ+]|63?ZDCkcN4̓`@ DhE/H؎ұf׊hv@x4fu%O4̓̀"N+4 JǶ~υ  fw`AXj߹QNfX}I~&FXKd@:"ޜ"9_7mE9?ArXȾW[!?94D3"95{poxWQ<l0…M0?2M}7ǖy"O:s:5Q U(~a!H,zclև~vo>뉥+W=K7<, -,G}|qMw;5?qQO/zX ꤰLU<lB $$8Bw/Ծ'yigmOoxXHщ0.1橂R0,,Bvns#rB_1+|T'^~ԓ矼aIH j^>~Q. a^6zc)@)$O uIce8&q4\'}//sx^]l0j F0F!(F.Sԩ,ov5offDz+|\*uWQ l D\*PM #OR]S\u[WsoZeY~OZ|b!r$ĬR$ 3 P01أ:>}gO-?u?5ګ<6 EuQwi{ݥK\p!WtvK'*ŜQa]f!33PxB QKQ˗=5KI6(N0J ۑdI$j3XXL* -v྾GNP4;Z %6R:-;]}b*".3F X X#`dA$ (*df˲ێ f c^XsjãyghD#1_f,D"~0`KN5-֡܋mVU;7g1Si׶ JaIA$ Zl<ẰmUUN8=/ T  ED2QS̶mۂa]mf 3c(Wrã) <"VSOI _Ch=YƀQ;T"$B7IXjg*9Hpd 7\;#X'b'ĿݬflV0$K""##m9Ѯwos X˥ 1AM&** nmi=cQϼg:5khE1,.VJ{ F @skseKZP(zos 1xzcSZ /"EM@ܘ֔@So|4"XA}` $Hc:(?[뿤6@আs,DTzm?>/JP|wOj/0C1 Epfa@ 8 Y'V 99X-nj(Yx`b wDi9P?D:1 aP> /,03h[>=5s[e5$%>v"F. lV /Հ )3!lV=V;yQP"v4u9JaEZ/, B &4©򃱪Gd#ܖNjg{ˑDr6ƫ "Y~KX JBچJlEGA`YrcmK$K)69SZd 0Tǧe;2 Ar0@XR 81#D y~ƈ҂*v8D.7x0lB2%ea"ẑ3ZcPX_`='36{7F"'(g3y>q"r`#Fa>3V{U f21G_ˇq|dMTz "h&w~|(+ĻZBP lQF9`}iWn4h6F 60xePA<*km*5rך,nB3 Ē b<ʨ=!iOy(b6~4 ]Na@Xab((]/je\1&kSZm0 e\b"6{Zc(l4W1B2Z۶IdB1X|` Z)H0 #!#aI rxH4rw@MXW&v9veR0J'ҏwn/1SMY=ZJ#Pu4'Ne Xpv]"RɘYV@3Cg/zYxiro|OR~@kÝmu-^t`ʕg74yT*b$ F}Qg]zꉏxҶO^u#{ Naˍ@~ N<ڕ CwwV6.jDo>4V5a5-7 6 ҍN4VDsb4٬[C4QÝw]QOD5^>c87E"!-T@S65"U먣!Jίi)&\f4-c/J413TyFѤJhWVYlrpOe6_*ngATJE "WcPeCR9cӒ˕ʕ@@4 Q>Qarz"%_OZäjڝ88ֆK)!ˑqi|N R iBu!WCۧV ؎UU(rxlmmh`j2+1OrQSk=֣NM-?։ĮOILj(2T, -LaMvfan0]E-/ZzjckƺC~R7fxARb`,&35|jgG˱׽~{u\=o+ 1ڰW0U*S3=}y[TwODOKF|O&2#-˄9V?~ŋR{Z[Nmki>uWİI&2X v@)HF` rxwE+D*)TT_L5&7ՁH"h'ވD*C:$;׀$$wom[⊊TQTt=L5Q*@]c[WJ'оx .:V@I撷.‡[@P)3*L)v_ tyvrMN%`塰Y ׾FZmy[apFlV}|db$V{v,F"U0س%*H]Lw9rA|~F0U04C4֒D<A[K= v힠 _Tͅ UVw|ǑXܚdBS}%| בf?hB~u|4בT* 1{yxڥK_OYh@<Fqhr呌r;HѺ@Y͙ɾ- IfFZ_kN,a0ZAeѺ X" 1?:7Jߞ-AhqglPuU( BR, ^u|,G*?bod|bK66aۙ"4K7mEKEX;#ؕ PMDom;͌1R%kXB(jplItuAh>G}S]Dgry*@*R ~,JjѺPeg>ƌV9@: @(@+@:>h2~Ex#P>V{b8*: WV7'C?2V. /X+֤(W 7-+^ k}EdDVSF+*hU 0V=JuѲ{Z;?wK LF,o^4hc&hͤ 11 XuxXJ N+{ LrjLi10i2ahmMb2WsO2=_3ʇ:a*(isRk-10@뽏B|(y{J`lb/WqFsDOXX.I4E`Ō)#㻋j|_[]IlaFތQ>LP1 ` F%і}UgP Sg^^`Xl VձQPAc4 3ET}>+2řȎ/̏}^[pـ?W|c!-H7'7ՎX2Db>Xrl,쇽,t< 'm;( *eh!D$G,D}c RMbzz0fEGjű0ggS] `[ROA)$Ɔ$Ru)1S+R C0ch!Xp xJVDR<;mFT~x,d"z$ Q(Yql?gB'b8a[@ae$*k_ eQP%\΃z0z{ZG p2 ` $:Vs3{c.qʽDY~^^;r񒡡G⎴(n$ J!O}r'{+\p'FؚY%#㏸v "X,E H3eXx-x3oTlt`3lTu`SWKh^6=1=.җ6oXb2 h^{vbيoil/is&ce6 H eTqA؋`ŽMH$¤T 1d}D1466#(1:2FwmȞA(ɤŢ:9806@ bQxv=xe0G( "B"0H\e`@0e`IB<"Q,1<: `*WDXR0ȪӇ1>RD"hlhJ2rF19:5YDDaIeIzZ;|.j3>=>nnf[?qoo;&G𢡊[6؄"I(!:4.g]d-X]Sc&14<|_Ă fM$8HXP&b_>:>Fi fchCkK3ѨR|^ONg;Zz>y3*o\D9G][#@t/+BpԔ7SUX`6JSfFh?ƨ@fơ*13_j  ]{fTcfj,YZ)xŐ_I51~A_ I&wˍHEmPnfmW,XxzpG~zl 6䛅vh6Nxðl #&#/ÄpDBCW*Іٯ|TգOPMPFPF (m0Hs,;`eYD"Fc] ?A> B].M H!ƍNjOnűm-2r|$"Avaf3q|Ϸ gf.)"3Ca|gaj38]Rٿ~y-'XdDϷ g\={n ,HadhweΗ.9ӓ?u%dDC##7D rL"踿ghĚBbe}'O9=L"ۿɟŹw%H@`[JJ51]$(e37"'b`l_O<ϓ`&qL4ظgVJJ}z29sZN#@Us ` /G$‰9_T==Aa_~=,sxQرzر:h'_Esv5Fnzd|Ʒoy|'L䳗S㛑:VքXV0ӹ"8<_Ai0kmO{6D>{Ty ]m&f Pp ǖ e "{T5O޳qZ;ۿm~OKB<\XX CkAӹ[e=֮mۗ?\bbP`#Q >dqxyÐS}l?ˍ"RʭQenz%G;[ÛJmh򦵂1I4AH JHȩGϿ?Eo/4+CM1#Nrk`~YB> ''0:oF*,aR.R/}%fdĕ/k6F3j6R 'QWW+#R/͋^dĦV/33F&0<h$.A`X Aer?(_3c 9 "RT/0 _|!> Pe 3|C34En}J)@H'Denx y>r,l*Wfz]/6{Zއ85L~箛 A1Z$54Zї^k+Oogޜ7eٰ8߿nxxr!avHûvg^z{fs&cQρ d2⣛ёJ|e9{& ?3|#1=_*69;VmtC7 6lXk>2/@]V(s`cx5{ }Wvܴchf˿_v`?'\@k&`3"h8|0@* i\ 8p^M0{f降K0ڇ&XkHё=Nqz kgl̞pWm&tgMl{$  3bM]=`zv dW0 H"12>=8=]3a<ꙿ1Zkn S` +g2a5>ּGk`6=hDSM<5>ش@~1sw׻܁Е X<J[E̟&xLf{S`s )!-7`] 7l}.6陙Q.!- Ax3*"T%o*B@ZFWЅOHEPؘ``х_ :+Fb, - h,L$%"֮-YٻG5+Ҥ !lavl@XB4ڶ^e {x-jLƄRJHABm"֖ f@tì7*?2/#@E"hMCU!~HAI&Ͱ:ލORJա/wA)OL59c-&&+I)pܺ֫wLu\mOs_/͚͙uާؙI-ۉ:--~ilLr_Z!pm]_x|b\nfXMMW3wf/0;mOqSgZOJA@2u+mٟ?@_:-7m g0փϾ™|ae$Tܗv}g_' ȭ[g=Њgfjsl*lsugϦ*iGaYHU |_6z֊MRp OP\'_{hmfv7z㺘LJ|{Ћ-僱ZZM},AkSu@۳ زmm4翡%Tw*JrBuςR "b`.XqPh D~2,)kBMM0j)&iGcqAtOAX_=Re"kl):76n$ 0AcCŝ?@z53u[Jy0nqA `oXUx.|~7A`щQK$%eÉ`.@Z6HcIB@RYߛ PRcbrzTYIH˂㸰mҲ!,DH!Q,Rn|\%eBJH)aY CfZR|3l;{IAPc:sK)`6!r*WI&UCFc SP#),Z}} Y v%_zlzjK Vd]sC2՗dD-մِ w?66>qN)?S[7$@5մlv@mܰ}ljjB>_b@յձ' D-UԆ ks6%tԶۥjڵo_x\xNX*D? ՙs78bz,`{JkN4:Q٪0491~.s7W*2Uެ*RJ(b"Ib,`Y+O=y>wXk" )f_)jUWC x4u(ئ7˞ ϯz|2Z5GH!υ6B/]}jA`4͞}$]RQGq@^~hA1Zm#VAcE]hU+4.߹V̂S5 Qjъ~f: ڂ"+@es&3oD/mR.\RA`tVcVkjKkrrƥ<(L+xM 9X$ H,aiȕOtZG]Crb4Hj!-CeH $IB[7^~N|pO:-'T>`R mYX2Ғ)(bIXoir`P @ RSi!H@|xo\JvLJXnF~}=2쟃H)Wn |}%_z,?=v} ?7n/'?ĪbWߝA}5;:#͚n۴ikqm(K+cmӧf֭[kڿcBCxmffF=a44O!-7*`k˜VP\%Keu}X|-wCO"2:٨ fwZlt&HE!r߲} =יLFk񉧢1VҬJ+(ZDB֋~@l~񩙧KZUh*5kmamXddXlK~Pi|ʵ6,6KH?зfO!fxhX|J0[`zX51JV*[c{d=]fh ^jZp]ף- ZϺrԔ% 2*`}U<67ZA!{ltd[0'ρKwOLN))0Z+5kf-(*Pu`ؘ=4<6ZP-̼vMzu__Z._>==y*OGp Qۈ eoО.0zzu_:-/>::~inzbv-$HM2jsݻ?wp;tZ^~>>5yd-!%l)-*?_O<_.m!%ґ2xSEӀ/|*tf&7dT` %fLem|OO_˧!ajt%7nwC&xSB!uMwOL|>.ˉ).q+77n/GwN|7jÉq"b_mr`ㆵ~''vⱘqݐN*K. R."s-)C>>ݐR4%R+v\QvtQS//r,bQDzdu5J)ȵ-XX.k} /-{z #zcDD! ~\ǒ WK-Ě_(s~s[Cg."&6яqg~V2HfTҖ ڰ̐fHTO79ms,JW.@C }LGs,r !#o{L$ݑk C՚ǽu8gj765^+rDGO $ڭ޶Em yN' `H -WtݻtQ97߹a9,>@-½wQk9#>8$deY6anocVOU*|lzg}C{"OBؠ0S <5nLI')DZ.BtI)m3ORZ=x#ȝxG2O4:f2۵/Fq{f>d2 fj j˒x;sљ[NkG"jŗd2 HYֺ c--G=E,5!Z_{cz- k~MȿI'7> fPUEsT?-\/!g */,zbqZ[ O?x`p օ~?C5kn V^{/6/#޵+}H v6E:5wAw.[n ;/W͟ qζ:@+ A+g =43Ow.n_B f"pި`wvwZqgon4n%yΫ~9mmJ v]?w!mt)$ely{;\vPΟ|c]:@De<2Kۏ}ҋ,'Šf]Z ֮S+~u=^d_[(woD ܎m83hoWjc6Ģn򔗟˶Si6kW17:e ]i`"0O#p~^S_̠}&kcǜDqۦ0_~GGpO=4BaY~^c 4ᄩ~/5yW[N:zj̜jN,]qW[M'LC7}+S]wBuXsB2#3B[:N|_7#.c'hHC>*$-Q6ȵm3m+!t<>2EQM:PDQ:i[NTbnywvK`HH!/l?;.v 4"<P8v8tK t<gwS(#}BXIGVpׯwW$I!WO;v)jDa"Rp( er_ia+}}Y\qxMۯ:ҵhL2SLߔ՟sO<#mͷJ=#vi`SzWQ3NM׷Gzok7}fYz /;`qrsϿZ~Ͳk+Fn;-ܞhJD7֭2~%Wo~צW=xⓃцEG?lZ\nt}vu{w?ʜߴsͭ<|gWg(bŭ76&V^S?v_iZhx. M*{_:~ևRa>nqI[[M[n_zzwot[Gߺ_#˒G75&OD6&o?_@OLZ(mDk/iJEo;O]g A6__)8w rwww5Z ]RldjhO||]wgZ%%i*Q`jX73s> z\o!-47knlo ٫}-bo&Cfd^ؘXؐjkJ}dzϾE7B&VK#q̜jJF>Η-|&EВTrUcc#1dg)d~᳇:{ gDW;2 Q0? 3TuB(6xsȕ]6׾op&âL~ÉEmgʜFyw]]]e`!OJ3lrR68ۮk|oebחI'giywCC]:jrT>7שBV8(6캎U,{oeC~MˤMɳ i}w]*6B?5T+O\H IDz*5lvx%6^HQ쬀4kwXXPFXU_)@J DF*ªwN:dDJ%?%mKe4F NI_x򓧜>\}82\ݖW.jh*ޥ Z !OmyruOoNd[tV] 0Z)ɉd]ݻӀ K2ZֶcT"4PoK0/_X 6Z+A#N%f#4.iz.kc)\ ]jNV>/V؟75zz\9cL猝}olo8Ux,vm$QP@*F"kb: O |4w25 T%Ee0/nlnnz'x#] HU֞b+elY)^¹IOR.| dhlkkz'X!-Q ㅔVFkZ+fke<<9T' (W2ՍQO"}mı;4|T3+73cXÞ9W/z/¶Y>_fUv`@ٮi;֬mKkɢY־;wn9,>;mɶʱEa9]㖴I!!|@gli* Y"-]uuv,yg?<~qb}jNN6-/YQѦ _WBi -g2byGo[\n V'<~qKך_5W_UGCdlVscm㱑ݖdFKZbű+\PGCj>溏MytbDMvK;:L";02x|CTy"+0bۛE':> ԙ\''-"X$Xg^qJ_]tpᵀ-)  K"R~XZR6۶$xjQtĖV5 ,k<[ [JQ3f)Ym(RF$@!kW+YR/anq<.C8cA:+a9BX6EQ*P@&?I\CHj\10fX켶K?Tokw6b).Cc&PgSk_SȌ^Ѯ+G457ѢvcB_? hKa{ˁ2bLzAUk$$J-1|BHBXBX.H$ of=`t 2Rf} !-h BX҂%C!(&G`U ԪQXQZ=̶R`VJA!jժN6Fjk|ł4=& $,Ip0߿%B!/(V|J"P{ Wf4ZuL~O)-4Xێp #?ݿQ6LX.̶'] U,)HBPmH?{xYys֋+OC{,f1hTDC񆐟>llt[=ٟ851򾉑=yFb\ԂBn6K5ݖ@3'q@''ɫ@qucX(ԘD"u[/r/oa˒q,>!f$bE-Lb,"xi׋3S3An: Ec uOFo z]IF\hkmYB,fg2rer?]Xױ %@<18L\k|^X_&rvtt^k2 ArbbB~ |ʕqx|2s妭x$)"+7m YZvܴ5ἓ/l^ 0$2WP򂐿uk sW{Wvn%656\" \-Q+Yͻ/Ar_+ˁS׀XK2e| "PrQDitQ6{ IX o[n}m(Ai: (@%(FGi%B*?Tralڄǖi٨klF[gG1CX@nzb ƆwcdN |6;٣%fT-F@( -B}]m BR1i  LL0<:LLlx4[ vے( 3*~X9PUK9jc/)c*_\ E@i9@13K(K\~vDdOsVK-ZHZb66_Ue2s=`sQ@ FE^"Hhk3gfsz[ߏ7:Ng='Ndd{û~DBNeiDF95x/^#@#s-{K9hPLs3H@]-Qw#8jL322"?"К#kq8ͼs$q0܆8Fj#H\.ߎk߄?Dihk\X4q"nt:ndg~Ꮾ@S7}0ח홶`ѥrŖRk iF}վ'۰a/5ީ0?PR}\v%k@JSFFRInHowOMtkz;/FA:B2:E>$unxϻO3ڧki|d^ge""k-&N U/~s_35MOŌ ("L Wo4AuD#iv+{fHIjehN?<9;Woy΍Ae4!qhЬ6{1ci7c":#Ą () L'_-ξ28"i)Ł֪l1sڠjMNڗ_u%I-"J5Z/űa!VCaߘ-$ʋX?XTŲ۱=_=cc&V-<3>Kobú1VDđ{+S@ T_/pI{!U 6cH|vb ß HY>:@ @tRPt!W8Q7`!0T0!¯n;" "ʚ) Bl:k; E(bryU("mu>)͵jO_(l8Gb[0P.Fic4+nM?~LwY#Eh Y"sZ+bկLE7LMO;QJepkݲ$ ]P/{6~,0H 꺈 `i6LgI"҂)߶m?:2۟Gn~ }k HmYaR$0 |qSY]zYcÛwF:p$ ۩m-m%M({b싻wO:`L]z-[R( 1i7ըSQGwPS+HP~bb싻''Ό?11LM^z ݼa-R,AH+ jb$E\($~𘘀35۵z>:_|K.g$I҉S2@VJt=)}4ܶ~Tۺ뇇RTxNK+hQA(E׏_:ZOS3H~ޛ|W84BH`v6S !*P-nMC[K~)?9- ٔiV~,s??ͻ袾g!e4cw]Ï|Ӯnhǚ7x Ͽޡ ^eK8w_?rH0Zk6rMնg(u,oKFl|`]##UJt$?歯(.ҚPZ+"6|{on/pdZν#"̹\럌j]T(Ё֊/|i{Ի]vő #;<8AbH4( .Za"&[қiwr쥃pD LsJv@,%CG.d@4!4dBDQ$9(@L#эFe+ZCE cTwZr"D1xOVQY8*=LeBRD;!a ̓G{Bӊ|\TywJJFe 3|"(EXX+E|`ED97ÿ}kߒg7;>ݷS\rYWfz-d7xP]-<\O~~õ &½_#/9/<-Q>;_w/?am&| >u;AEL A lF*p;LE:|/)~b.x'[.ؑAD MKqmQ:TwHDݫ&r"K^;7o9[ڶRD QF)! ;-/bi]+2^).ߺa[7 Z"B ż03XSUv6ϔ{9)G X7XHdZXZv Q("r/ݶ򑑡Ol\7Ä@c 8VciyY qXعrY߭m oCp \":մY=H@eGBudLJLn\ ^wA<MGSCW fttq‰o P(xU^2(wO\6_k*ظiS!Rk3|`AhE#7o:u:PCkUfD s_ 5}olVˣ%(l0xs ZˑUve"811f0x.T)ˏ z"j>wu PV"h@9ϒ/ӽ1_mr5R7FG03gPJ< _,"K^C+j/c7v)"`Cjʜ9J'2m ; hD)ѥNټDE0Sb9Q/P&۩!(#[Gfic%*zO?}AF?~ mv4 s Gdr  И]X ;&"u$iM(:UZ+Xv L"@j dꔏKX"|S\TrYU\enhjjmW9[7\k̾׼}{K$^Ys,B> \5{uj m\ Eۮ/u>K#F(P*(RDSzw׍\ff-ۿwpei n5ʍQ ! Z DR$q>PXk vK&WQBDuqH;+\Vhy!OY )80AYA i|,;v #!03ZW+{u;>LMkټơb&- R;F+,+EltR.P^`: uj5#}+H9Pif5 R}1 ̂8u\ H{tDxۯqhp@XD¸ӦYvEᎁ>'`[\(vlvcϢTט 'l54HC vC7_@K_Sڠ9Ė8= ~-9ʑ I_yʕn~а`;?aœtǎdCF2G^ry̓} 6;w - fDȱr1 &Q7WKkJ9ENhgQ$) cb"""rT^cu]/i@k ZW//ԏWn6NqE:P$"c(/MS H-EJ~|vowH*r(dO7k} ,Y@Z!"4[q}isyçeW诠XJ9lX7kahiP&cqe/ݲnZѺ@XtV&&&Na;( ! TpNhXC=}kcNEjw)HZj>IbёaXk6_cR(R.=gKG sN^GLxfjhȭ~pޕgϙlֱ@\ц@z+׎}^),D!ʫȭf%.isXYkI>+4 شaVOz~rɑ'{,J$RJk)=A TWlS Buؠ>rO>}9?zCGZIZ. P P~KLhEW UJ51=9'=s]2|\̹@k"焌V8ێTp@m8ZXXG{gO=d Z.ФE( _5D +MyD\S(ubvծ=7CG$`7_?+MYH\h${>R H+䒖vi[%Ej=B͹G>^~fZZ +s&I*'k b Ejj"cqȓG֬7Avg&3X}9[]94\(IjEDNB>2Mn5UmNgW _ҏm6lHU^e|e6,蓏h" Αc֎YũZjm,\$g)oٰʑa Z>yXթNVju:>;Gs 8v|V:2ӬY$ n[yd< A\%ܛ<@Ep/$?^ Cȍw6)XJDn};ub0"!s>a%t8(R>Y-F5tvۃ=|a& "uQh7 HPrBGdd݈эgg}n\,'ڗm?qń!": ߃V;AOŢ\et*Uw۶<ߧkvp~GC&0Љ-E+4)#}Wr݆r =1u ZXYCf):df=/4:qrՆuCo\7s{?-ŗ5tj ?hjAj1zV;/7OLϱs̠n6[ "PJzN|ۋ"ffgM$h{˙|n'<2ro. {EL2֩ 0Hޝ5_vt"W~޻ ai<{xءOn}_}&'n{dȦ[Uple}d]hLOY`䔓IW{?tʕOln5}^6UbM@Zo34u*~79zB?gko~ ՗ϫ8gY 9'PZo3S߿Mޤv~B>8OX^jv>9u}[?|&˹s*4cQ,vKˇg~BXz?o?r.g%Bab0wZ))HcG{1 Giw ٬xV(#X,%DxohVm&RgȆ)K" 0|H e?%DSe8: R:OAE(*䜕b\.Jwo@2lLJs\|λ+ ҄b^H+ѝ~.)F-c\lo"0PiR$0_Kl>>ƌsֱ@΀=90UZT(Xȗܝa.O<: D QpkBtTm(,A#`ȿ0_S^wpu4N aKe52\c*1h0`T@5p{.[0!ܚD<::UyZ?]ʓ=^u~.8>Zùs۝sv`2BU0F+&@&u,;! MpkB QdN|:"dό1J=|]Y_>؋ź:r| gm}([V痾9Y8NN 2KL y\kjajB4*"jOD8963C߉Kjv~6{MZ\^]<1s|^"](ع4=&MػWt~[Of#BD qF''/^bӃ?wl}_K~xC ޽ZR{cyl=YL*>}S 'R8򞍛^ئ8_ӽ ׭⏏k`a gdwo\7pXN{;ߺhz |ف @ oN<^a *_";n[7\cZ4V ?rZY-C٥O:~] LOcl["l8T* 'o"pVC,S/O7`r` 5s9B ADXuUW'%M4sJR lc\AT6a Ҩn{ bY11;77}B(WP,WL"W(P,TRߠ{ֶm& #5{kHSrR !br)OJ=k`ΉvNȟ1gFis[?XԁZ?*4ijQ.P,1r( (TT܆ʿR/<"A`ȓy T֟V񣷶ˏ/f~֬{t|fV./\߻}|a Lpe-p,uyi鑹33h9X;O|KG]UtZ|П}[ w\^Ç?>7"ƨU|0v쑣n]ZZ~daqycK>>[E@|?qqGW>\QDٕvئ4RԪ/<%{X*MNz5)BcyMafv"FK7?޳̻ ]+%4ԢN_D옥:"=#g"L^R^mZXnZkfhFОg(QU.VKMCM.ݶ%]{-YoΩ4?{VGߌ>YvfvmުvZJ9 8_uTQPJg-VtY}oԉ{ݶ]G׻/@XXcFFY; rhR*c꺑N~utzGx>@qc# rh1_WW 'RGtGZ)|jtR֭i)|.u/zl.=> ZAl+ ^(8V Mlti2F+ wlׁK!NV /R"^9vi/I LG6㜅#dRʼdJ)8v-/z4N= jyyN,=|t|5Ve2 VjM&F"L4#0 &jq%> u  i$h3*;s c4"Uo᳠ezTfu@&̈rdV+X?#Ʉ40 =oXȦ2lH&!mL,mƶ鏳4v,p{;%Ӆu;6MD*uFv Kc?}#@D4˦f/M\}KuSk>01|l,i>ޓilSSg/}ӛ=ޓt[p4/NئʋdBٲddtil_|Tl`KGXЭNBX{(VjM Ak4uZMw=N.t-_[=֚Z|:'z3q$_D:̜:)DV .ME)=~ 驧N"HNV/=kbܜw _T^mVCC9Ɠ_l#4c[hc;iOk 0󍉷D 0k<.FWsv-~/\{[?}3J>]o)JS,| R֦OWwb[q,vӺK?_oO{}o)rH Pι'73?I'l Nk{3{S^|]oɅu, "0,Pd zѡޱO{p [YD 3Im^G @9OhQ 2iDpBL9UjT׎տ8CpB^(gX4=tSee@䊡襣O~q?`8Ԇ@AJeG?4AmL&4D\|oٷ. ?QI^W!ZƑcHR͂za2.B% [o[iهD" JK39҆ ֭Vdb:@rS_{",fG$~}-+ `8o;a _wr$cGF0 |_s|ى(D򧯾S_ߟZ޶'va F/{jZ#B$"N;Fj#qw!>EA>zT7S 4ߎS^ ЎchAƀ#;ĉ3wIDhPFL* xp(K•Z(Z㝕M0æl3 nOVq͹+[ah#)l>~ԟ[_-l}gYojR#l!¢9!o)<#/}Pkژ$Lo>쿻o gٗ*ÃM\ab 65" a8ej 'cr{PmLQ-CvEх/ *#վwxadcbSGI20& $|?VؘBp_&_pXB%+{Sba138XFoI$FLr7eܓVw I9gXJdUN(A\_ !iw0FyDh#~V|AH:r 5C) PDb(ƂmeB>TK*#`a -Q} !=ө?$Nh(azs F &Q,WBzqA3S`Hv!3Ň8*4AeVf 0( "F!iڵ+^;( aEZ֫BQ*2w03,{պm6hZAXR0ʥr^#E$sc # /ݲxG@ߕQ`1[ L!nr2wFLN7t[o?v;Fxe"Q-Ž7;IY?L'?~Fxȕ r[yFIDATGgtru~[}+WR weׯ=x+ bd Qw2GM`::,MJIed) F8r, "\?T{ԩEծ&,d8p7h`Y@J% 4E@kpgS "8k" 7Z%t" VN.:a~dC6Or$ MzXCh0y4MjH߁$!$Vm_g=ʟm{u.z3a+avV^mN g7;w&4Q6=c?;~ r%6U> zn~l//ũ5w1:5k;\$֊򚿈FYG;U = Iwu RfU)E#vGFTZs5_i' 'aAtc%"sN  m?o߶ߙyJ<@E4F? RظpꅱMhX)"_-Ak]QRDؿ-`'Z2Sem HiDum) z H\Ĺ@3 ;j[-p B)݋z mR䢈]qi*> iMNϛsX@C}>EeOȊ)BC,Rv$cu zC P,D貉z Ґ $m.Mt| Bka_#c4RFX52cAkc,Eg)b2^fm,;'\bQvi'8DN魿dZN}s+vbDRSrv`v2%qszFէc˄R}sE4P [YrΦkJjO_f?-~7uhK.J@R'Bް~pdd@9)wNL?dBш?7r!ֱhxbq/`(ԺvBseuN R9G]b;aGqҙg'[ \q;Hc _ 帅(gL-: ^YFgq^{La:%TJ 'uiG!.nQv0Q. m`\@\;“,jl?탙5rQMڴ'`Hi8vmJ嬖Z:Zf0{LV-/gznzz:%,͎=g6;ptBfe4 ZM,40X:=qpV3 =~BMuqj,α)4qbxo`ޑz#Zzla嘹lZkXಗ"_'shۨhhXZY,,.#GjF=x1=!"q<) YDCѪ !"j5D0V"vh-b!an8?A:ΣV3\ϲ!@ljmhH 0Z?-3;RZ)' dY$5ZI35ӏLaV)fΉ8f87ol`4i{M?MK 7`v9α jYװg oC&~JR,`bN'"."bp 45{m{>'ޮ[G NiX [KD--λ4i}LD*g;~YFaӉ9TZ평8}Ä);>_zrK"l-8'Vcy>9J+\sI2LM_~jĩҊDD:QI8Mݵ|c @5 LJC-.Y4$M:3NSJ:  >_1 3M,\6am),$0U* Unk| `"c+HX.ulع\čyANLT CGL(Q?YDh}r@Q$ŽYg9k9+E)KR,W$rR\yU7|Ylv|~>5yiguZC򅒔 HPJIrP5Z>5?=P[_[jw* 2!9iǩ(RE$\ BDQ8] k +$ 9^Asuι4M!|ѐB>/bA0r$|HrQ8Yƿ=U~pmbNjl "'S.:i2uggI: *D*tttRK`PDY;gs{eIO _o=\o6 */NJQ` t<~íNq ):!NDR Vjf}]=6;q:iF9nbFKn f޶M8x6vwKGvqU12/D2])RƸv/0IY=3;|M|~wM$[Z"PhjyimÛ`r?~㓏>qwk* & -S5( 4[jV{÷LNLW'~ьUVlտ[05}`֥8~CǦm'vFҁR&TJ"? DZR(T)F(#*BD5yb KohGVVf8p D" "HyޗRE@?!E[v,3Js)xѺd:;PisQH0aN+:iy|٫kR B++7MN(0Jk :MR]ko-\cӁQVV'O + ⻔60Zw]m ү//͟COQtѽ  d)`6 חh Z;vma~"+|ѣ&NWtnYʙj ve pЯᮽ{jڳ;/+nUw >.nWKLO7~]sG n:dz g,>tSO>?ÿveՏ .RZװiz|λNf|>+y_1H]]24Dq>'^v>R^j䇭N;푻|ߓY׏- /\RXO@?";)"EZC0J6Jmeuf|ӒX}|n!z R뉨6#EJJE\54ADvvceetm} sIy|"*T>n"6Ar(I3Gg>w2xG˻IR*ET?tڑRM(Ј"F_}IIt_sE$[3s&"\dB).?)ǶV *sJ~@J(߉t`QZ)bvv~q_=sOGo`q8@,?Ʊ#C(imv-;s7WK-kK?ÝW7M%=~Ͻ3OL8|k7__QAmAʢMNS]/|{klH:ڢ46 <k qώġ@T`ơk0<Ị8 '(R-8hvt(Wu!'6Ikr. b맾rz|&=kG9蝯|A1|Կ.tfΊIC)S;pי2ӴYA1 ZyVPih$1ؚ )˵( ( T5j2KN9q() ׾3vtA%K5lx`<%~k+/ yoxeeX`~9s퇾L9`^ЗWn [̇H&N}#X7pp⧧ =Y#?= vo?8YY8?>3)=^sE/~iτWºF.Z-4Oױ .Z?~z?mJu;=|օ"r?ׅw/xf`g?K*bsBϭoɕj._?p v xGӎ,ʇGފ޽z||o?)]7U%vlns+#o ضZ+~o}OQ^t?|=s`;>`RMN˦mW.UŹJsFn)6ؤ:v|WοwT+}wc?|o;||\ݹS09)~߮}ťW?U.;2\\*l53|;?տ|G_%wyܱ/>y;wLS?}//OsK-\9ך[w I[Xq79YzĄLNNczs6_Z*^e/6g? ;<KTtZ'+/8BM[n6>Μ'Ok-}I' \SzBy7ӍW @ػWa>0&{qi`{${վv>t*>Hc3;>|'Ye^>=Y,OVt &w]Ijvv$˓UΎЫ7As(x_Lϧ}$"$M )~Kt >~q:]S3uS~ (S2vAWu@Ocb@ƆKW@FA_ʅ X -hzr|,"1ġC>\2+tV1>(ʁ lMۑ-"2'; _<U`#:/:!i_y? vϏncڨP4Kzkn%oD4hc?Gދv]wGִ;\3#o߼ãAlo~#ws{'-/s.b?O]7yG؏kƷl;2TDp?Py7_svl|c! gG?Mqo[qt]ǎ.EʛG*ۅCm5+W0<|dq/ᤆ8 ;;f :k(eG _~7 Ex^xچ]LV4pawUo:Lcо}gt>}~kA5n<7LBL7qf75[~y⋧?w&;q_WҼo|ٻWO>LMM>pGߥTP?~S_pqb9Hח"F7VDAn,cY;3Ciͭ6;{)SSS_{#wEMr>gIJk2MK@&PXf3-#Z c VZw}g~`LM'^{r3)o~ֆqbncROP-GRRkt; cF7[ipp66u|;'N8!@n< r( [?b6Vfe$Ŋ;z>qTBr8?:s>Xٿ[J !GxÿGqN=9Ӹ~uDgFP޹u۶[6n '="yRO]6_UW 8wtaMClZcK|1+JSi|𪋯66.4oDv,2WAR/6O@ + \vLuf7 M2:<s|tnsWn~Lޓx?܅`1* # Tф)A f|όF^< ' ^W˅Q`t8 R}TEAH#E4_5?>t"Sۅ`/.Z#P(PEQާ 57yߴ ;d .݋QfD+=hP<9y"Vo[yg|d L)/1\.DBfDARA@~}Ӥv?G'IyG籽ToǬA!p,5"fIc]1wqB%3(L c@ T%$JiSErEw IQ! B GQ8o÷+o 7V߲^CF*/Z "`@ ("DDNKeoUGC[v||օB(T_p$Ĭ8L AէHN– ?55%6n>G*ʋfgID)sYxE:f;G91ʜ׼뇾~! JE uV aY3ϰ_IL֗([y.`d%-EtR'"aveM 0 9fQXw7Km`7_/Z%uN2F)Hk1+) w ֖;ªUyJCbm#/(R-HWX,@ȏn*˷(Du0b^ ua㯺 _7rs^ *oJ Y; 3E2O8 *VeaٞG^z6Y'sc澳~Y.|u>a?jc XNF7b k-0x߽Sk؞cc9_M |[^* U:IL#}T}9Ax艙=ً&'U'or#* ژm.hJ;5r s*BW͛B.cA!g@B88WG/o{>2֭Q*ruFG_Ru048R)֡A߳k[}l~1 G<%6(cF@z;P ߛ#y}˦`W{c''0|pn/bh_5Eڶ(F{r#k#">/@PDEI)U,1'xZ /4PEaor\at%MGI %\81`L[gm7vb RatObrIJ"L}W7A4ekq)HG]v?ubv-`TrƍIcf6A ,k,OUDR-GD,BiRڪxJ+7Ijcb Lq֟(ED~K"rP:r'sѕ#Eq.Zf59O-!/LI>O#CTe4mY H|Q*_{nmJIP Yޱ8@e"| 8a[[YŻ'`.Y~7<򜋯B" p萲6M@@⋺vlG6m9&ߙzߓDo ws+&#Yik"HD`W0,e:~g}Sڍ x7ajyWYfhAD!a] XB, :&RYG;L}S& 27SZWfIP_>F cHji(+'㞀ϟ.o>kㆫY7:d_~}Ţ/:IXPwMar:̿8_ rv`Ҭ7*;_[BH:8eY&"{b\Wru`Д: +vs" ٿw ßYz%+WW}rJ8w1v̌E}ZaV=KcqLDswʲDS<>tɎg]]Gra\O- G;pC4F& 0[+ LS:i(u_\ʇȷfn<:e0K1Fִ5.-,O(mܹRpuE/. |h"?͊" LU lE;HH־0tWm a.ԧS[4dǠSJ)m AZ1Ft&ˏ$ָpqhJQΗ r*} Aem4 %h@@J /z6 !B|4ŷmPbc;mfC-`&RkŁ@4;/]c0Dݑ E` :q*RB422rOȗ%姬o`E(N,[j%ĥ;H-# o: CzJJRA -`(r,A]9 zŀzzs')+4wCO]Fw>';kHP`97x'8/v(bwO1?SyЦ'N4s{e ,QV% 27)x"r/޴yUΔRzO),BsNY% o{bc't)oJ&U֑k" @|"P9eB!|&)tīU(@B`h@`>&YY>+I7O}[}|zjҳxdp|Zk "dD{Ő1 ,ҁ\>|ne;"g1V}&?Tݎp01,a 0Dg{EZ堢#"9x nLyxv*`:a 8;>G8;70R~gGF %8!8"̉#!a>Cz&% af"mx@3Ã|迢;v#|tK J!_~X!rn{*D [p.@0J6wX3}f1_#_{\wUWb{-‡xP5U"&3ųR.C{D*_уJXweK~UѤy2nF_u#ð֢lVnjaai scǏSQe$mT @pmwpqbc nl, 6IEMdv-#n-l{SK 0\D\m/m ⦸qXuKMr| p.{OΦHN qeO bmgmR333TZ:/K$ Jj''ԑ$9Imkk-3Rjc:E8$ #M{e$C[Xˈ5$Ir=ѭ1uSk!,HE$;18̒$ i?矺\ADVP:QNi]""|1|O\"L@uayd1AzgD@քVy(eYwrR*8q}(HXܡwlO`$M7n)b吲YA&gKd*r6+N@P 48ADNfspΡVcye "s [Xf鴢'CcVIBׅ)4E(.7" ݓ {($ H |~vON1\*XDNt*;Ź8\*o;i~76υ"9O<$c,,5Ѝd167>=irC*(On{8Wҽ Q0 1K@ [ _=S|r>,\T)=O e*~3}xBܪ/N:B+5D4*9 pQFN) O7}J8ςVJ!"r9R3],@|('^cR_ ~̵H-4N0 ˟H>I{ lҔK46"tTP&.hb r>$ўT4[gVs94HBa5BF0Amwgr^C^S{k>I{o}/dvIE=N ѡ*2k }#qԢٌQk6{?xk> K瓤z^ E3?kkآNuLa\=k':amQEFP}jn)fBޗl% ~8@T\߀?8Fe RRpi=,$Zz5 >0]F~{GNA!WY!Hi$YKI6Vqʀ6/!]6Q.UI- ji8*@i PZ« ^wbgxٔvKsoV +c `>Z+X|1!@/߹3ڟLxo9BUk(BJDP.>w)ˀ&zpjzytG!?O---R)ZJh9j5s}lXQ ^s''YEnN)M&ʭZk, "X)>/|XHLZ_G1JҦbX <3_P 6鴑{NFS22|QkaSk\)kQZ+ctT= BA"@db@wߒ1%QdVy%CFi(M, J#O^s(kx/ήUZU8hk>z^B~9`Z8^YJuk#Qc壭QxaZ̽\ s kΒF'oW)*u,Q. J>$&SYGe0 s/~FD=|rHl}z0 ZD$ vy Gwo) v eԎx u]OhHbZA%\BZFg0GZk>1=GcĐ)Zkߍf%ըci~G>KkE(Ν(#RHf+RΟ8e-E@d '$%bC'7c/{1ٵם0UERB"E[jخR ijaiiGf:a$kr"4 YdwQOء6v$IgkY@° EDk5Y9LеzBjtlJ̱c3W|GFњ@0!B lr K*d"(1n9 a;U؂4\)eB/ueB 3K(A.'A5)2AVfNBiN "Y41F⫕F.W\.(4=|cC~vCUU 2a %S.幐$ u_0P`r1D!PkDgu(΅FҊ1h<' c Z)rfqZDuFMAP( Ř&xV8p@p$N<7F L`pJ~XalJ e{w@ v)Bpr"{~(_ |ɦ'zO=PJ)< pR( 07eZ⟜KF@pB/Z%#e»{J [" Z]\jV:YLzd[墐Q@: $",!-D8^Λ5 XF@%AlG=tBD q q~$ٿq=y(b9v;RIvKsXZ Yg-VydwRVƙD3r`h g+ ح le"BNȲs^^ h&bfFVwv0$K!}ብ@?sXWguez#"~}2JYpγFWF*qqR$ ${B4ao;xt }k*eXرDvj,1l)ET.ZkW-8= ,!XDb u(U"thieVGקN Kd5{|gL&8inR2gIwrC]R.Ι6M70V`C@ #0A ͥ!L?l"*}F8!VߏZ'/ݣ+"M/! L/u9FFX?;E\!2u&(0hRĩC+P*0]k ^gF*X(!Dad}}8rtpA9J1=횹;U|Ԇ,BMbݓqhn`t\[Jx>on6KUy(@Og>%Xx Ns``3) 8R֊+ϖ?Wc2`H]D=|i32. %̚7k(/ îC$+E:M;IY3K `'8Mju}L]E:>kSܪCZ㋃K FlATV Qd+[C ` 4efEg'14L|y3m/%^( EF,'i'َ@<;Ѩ BTFj~ 0i@A(D3˝9cKmƠZ)hPzZ=<ϳQ 0K˶ H2 fA;NB%yÇ\әzJ*>Ln@eOlڏB$MQK=#=OX"hE ʟ}I[?ax,r7nV'+YV *D0񱿐&)! K7,B{gO>`#I8z:Peϴ]a QP(C$'ZIA> EɄ=JYA;+4etم&[u1vU|r𖋢|.݇kb 1Z{ mqizY?!ڦ._uޤl!"@\vZm +, eᩆn+ :RuSZ3y=RDP.Z}G@eoXKi)^A/B䅬7 y2̓,C2[t^*  ]lt~HS ̀Or9WMss/UBQpUkϵ~̷~778 3B?|R61BRtL"ШjeC?jK[ykΦH{rbɇp'IB=>kpuѣgѱ#i~s,8nQL+(B89C+v% Qi'Qǎ/>v|GǎO7gQ`|nq/]qF+%"j^iv~Ҍ?}s,0Ҋ ( s>9RB!eUQqHum5xxnaGs ?ho~cs~ sI;dfc+?j[:T0Neds9Ɩ~/1#0 QH>U 3_6wxp]CՐYF'/}7 ZP Hj[2I0[%6'k $b$.tVQ!M:>εg6ؓ.PDnEeB,^8\:pCEEٴvg12l+QI6m$61X;8ki4N<ۉSra6bq"vkFiCk:֏{m[]$u0RwPZk5isF<c&lW:̦i fV:'(=A`N`c0Zcye$4H::,3%,eF&T-*&z({?PEE8{/WQw9Y/ KBX07AYD~>(:"iEFG^h$@’=IvΩs=ׂݺ]]NdY~p[TRTC5 xf6 xGצI Ҳ<8?t$gF_L$:~t+X5u?h c@5,B*7 @L{rR`u I9\TgsTJ 6,퇛T@7 6fI#Bw悺ƨFNJJal)MIaYӿ4l_%uxPy5vknezҁ75#`f96c~v? S o˲016 iYp"Qp>!{OM]o |uLBU-b \?k[9/o6jVd2@# Ϙt]T4T̏[d^B;pBܸCҎ@bH;*&nj֥*߷P(Y `BJHiOy.JD1X-'BCY%ˆg)(tM]|n'FEExc4 (mj\n*BsF#SSD¼"JTLXBމջ3߇ފe@@`N0P"0^#޳e=7V/3SOOWg6:0T&)[JQ"5u)T `k_˙oz+—)Ś}U/B`brC&6:'%{8_[L]d<p>|& _e !G&O*׾2>BLNMu]SŠ:>Dh- ٷ՛V/'{ztp7Q 3'NJQUMX+Dc=TNL5Pрi (V!Eڲw{ ^966FR 3G#9gk;3##{)}qjjC1Wark0+0T^<^; 1AC"LFV"`P.zp#ȹL{'6!|t VҎ̰uBv6d$#Ҡ\8/Tw\ ȐbZJˆeِ˲`$5 M6v"b//Unܘ[v$)x|Vp|E-6 T6Xԁ֬% ewcG971`ƈЯG-,[!`[.@IDl m ިxʍܮ]c0Z0ʺ%|T B]]-8`4zry6| _6OcS4"m,WF߲i]}6!!0(ig/_wo[;QXL)Sl+82 #!jdճچAz/zgܾmk`>fE#"jIi mYD+DXAXV5z<Yنf>GVhˎw/-IҒBHI$“ (USa@+ }gV+\40sx؛/zyGEBZBX=CKN/!Av74x}w OLh)Pni,lSMRq[pNM `>TX8rTEflɽ_` 6ӕ*pq`(@j4Dr+v,sRarr~I5|d_F X 0ʃW[yX|*Sa~\?%D㉓Ét%'r]8XV^,LeI}5o`j"B*u1+sR.KǣjsN&ݴ+ H+/lIIwU_R8CkǖrLd:t )!Njh=%zC)٠XqI75֟!Hhi 5``Z3NFP*70mG)JD#C` k#CmQଣPX{+ALT,, [{>y2@BK ,AX0}-wE%7.e71MraܵX*i \[.v"1A-{ABfd_> MMUօ?%̓h!AHuBdRr_/i~Vn]K$IKJ\ٛdԑE=T98IMMMU.hf-K<EABF,e5<'JcrptG} gE"ROؖuj D"XҝO 58B g2Ҟݧ˥mLw2G\dNV2"056НOg.䪊p<"7\yV:x.LMmoά#R H]eE,0&FG|k?UUxD?HNJ2ߙ)A)Ҳad|;_ޱ3w#kRsK!j< -W@~:V} vEy`%@8ouj/?GF}eG" i;8gKA ZO&7?9W}JM{:Z?2wϟ[ڣi˲V}Dijkf#FGMajW}suopƦMh:u??4ڨ,2\OX X0 l6+\߻ni˗JD-HiThR3>!?.Bq{55(fc$Tbs98l cT,|p@!s"t:x ,ؼ OڍK;$ @ HPyոgi~6+r%3kW/{1)'ɶ두Š$A*5 BH3"dYr%@SYv%}j+L<˲D<E%bHRa~|˩`{7dm;Vv}ϲ"*~T%RDex>E.S,vGͰ$i B(d )AuȆ|@k83,h,)  r|wz߇'suv pDl 01Wޯ SpQ`18ruO8o3ƉF$1>2GG򿚚u% LF _}:QFcddD /=0G/Fx \tW*_ض4l02>Kү& ߽"A/; 2Ʊd0&Kԯk|> O:X(\Ddү[׼iW)|r\܁k?N:ۦN=WGb BƜ=siJiرoW,D`>nL-DSv* - *gŐU,Q}Ec .ݫ=xE -m=YJHHHAAq` Vqtso1ș LϿZ[zZ"> "HW^ŃacXd~o_WXdwoU_TP1`%3Ɗ9 r%522nǮqu(/:t2ړN8fV$ :b =3Z,] E]I%z2t`t*C^Tffchk|bҌML^M~%{q·_jfZx@2u Wė5Cox]{{-ZKR beoYV2JXسY~4 ݽusiFXBҒL*EضspH~o_f4" X*.3|)e2Ò]{ǻc~믫KFo&6zJUKɨmS{?_3GWqKbw=\|)D2.@ p7$r+"l6@wsK~>t<v~6[ɩ<ӿx"T @u ϼU6lpI^[ b[2ԃ\W6loò$֭7u]~aՃ_3nd׭[?HyVT?{6@8$LZ>{/z/pu8WYsN?aW*a_YuMYZ|7^#NHy1%86M[?5GZ4+ }򬚺4+ ׄ%@ĩ2Ib8B~{7||;P·* Ͼ|ðDvV/H2% l;p#-ʕkW6gNq"ui%@F7M}{Hrow~V2b&=EZbp d4URr;+~7J86*UZ&o^uU,{{=swȒ*L=M-b|\q7ۮFo=y.ҖRL2O&Q#-̭T}zҫ"|Rza( Yv´; h4A -^x7({dQĬv'f/cm&un^)hUh G1 ږ G39ufr~|` ?G;HZ_72]ϛo6t]; pኈt!Ec+ qGX~^|i:+,'"tp=a!hY]l[[WHv-r~WDcH;reeFC-=ox=;ǠUdעE?X,˶O,Yo2xbmgKb37wϺcЈBk"u'ů-At) 0*z^~@.9,"jG#-yV /jmXk=~=/LloN_[[{Wka^Ɇa\,yo% üւW̼ւwfK,[g^k%Cu=q1+jGuuxCrI\ԮmUmu0~K I @ {elo0*ϩ3'״vI$ƹ43GUg/lA,!T pU``C%t(3K_44gXI `zV=[KGrRsܖH` $h蕶qK4?4 pš ^ `bAkW֬Z˪Ōy%ŋ7QWX[rX5߃N ˖kśxE8Ebc|llgCxE iS]hMMqQ/#lEbj9ċz{9 Π𺿂=lf˷#R1޴V$pW{$?uD&ݛ{E7{K>u63#^YO5wuɻ^pA_>7}}Kmfе,|׽ꂼzRZs~) TrR%Al w9|3^r,|&+t+ U=$!?3~q?߮׈pu_%2N(y3b/?qfo}g/>&~SX>uoϿ3_Ž- ܴ *ǮX<Ȭɲ?,ȲcXkV¬\cU.Moxìwgx bc3V|g͊w!,a+>Yf?G!+ @¨x c??w@얫c>2?[ZtScΞ{;_kXEW6o34[371o~s92GudfQ݅=$4Lص}Ē¥28XO6f-:'ەlimi"{>D #ݴ_[q'aD`|(H["p`h=j@jp<6P.٬XibޢD#6KI<5 =̓Sn~#oڴbk`a;JfNlbScR̵cޥmWt^l1orn}0xLȇQo9i'xm/{ZoziwGfespѢɂ{|5㋗s]]^ұF gśwLEǵZy??,7>1E ۟_Kjf;śnLXke} 1/Dsm[=/KW>֦&^?ΩI'jʜǀy>tɅӻ _~߾׶ތL>65'dw@z^ԡQt~½S ܿ\9#oacUxnkOW&ڼxm܎%8끆G =oFl:&r_RwȧhTs[3mki_FG=1dk۲uS媫ZjH>Ap}[3Skg-׏jpAgזk̟GvU]:yDkG>63,KD,?];K3Ljpm/_rUؕES_x܂`immamc]͒x*RiH9ݏ9F | J%W˅Ozö!٣6w' D!hfc4q? ґ A&m|8f>X \@i}ovZN"sȔ4 %kFQ,r!6rUz|3DjC? +RE'QMPj/Ӝxb s.x7kg+qd&'-h; k{AZ_ 7Wh_mVs85P|rM ˊm̜i=@.Oa(+/ Tކx̆+Gϟz&zXDmgyVJE;<UJ}*>{@)?ǑFˡ^ X"jWұ Ƃ!1+"4Ć/JDOp5=QDIYNl,̵Sb95wIу*7B/I+#vcT1x"ymGJ'zz$!]o$ZE0[aBH<\;1<pxשrϟ, JrǛ;feⱘi)qڙB&Ǯ822zȩ8bzDDf6.5wv-6җj4'?J\\x^ E;?*#_&" A`X2K?~m<^b6nZ}׾Ń[7OGN{?iD,B]sӻ/k}Ol,cORrd"N6"zyo֭koj z_yu~rc,bo93gV ',;ʆ&=6,b`~^ܬo;n^s{kK-聯]u{{cĖ_u}yysC=Mu;`k{xVS];{}mMtA 5~S__zp +n;靷N`'k#^ܡy/p$`f>BO,'1WXy a&J^FIjd8!:|/?|ud%k/?H33͛Rhln'yq0 =ضȱcciI tLQ|کuz^K[?H;ޔF1׆1P,[e["uJ_()[%e_`.3yǒce2fUƘd ˑ s~S(?Ǖ.=m3@d8$Z3y¬a3E$ 0:1Z225#˞sCCM#N( `caP0&)ъV$|S$90A>ᆋ R%Ys|ʕ7]}S4024 k[(lKa뱯Ɋ5ߋoryXa bT/TXa+¯zM'L^0|mAO5rB(7a58N3Mտ|)RJaf'30anGo{ȶ;wӳ% m$tݣiz\p/;mWi`Bi(~. cCM78Mō yKGwlޔdS\g_]/gqsZ>QЈZ_qk7$bjj䗷ݺc 1)\R_/:pVc)LZÍOK;|q#o՜9rtT1KGY ?c_?Eq?Gw} Ç#灁 H䦚Z;m;vܵ;?wdss3 !_.[/:šT54<׆A|"}ښ1FH|BkB!( 9J{x- ~iaMVNk dhPsp,.ߤKO;DKukYyVܖJ;25Qa؂a-b?kƗl|R3 .)_M~v}} m 3uZ6Xl1`!(\}0H:=ߔ\]MʊLcskW̙å;Gqe'qCQ1'fXY*mRq}CEbilֲbN{~3DZGAd3,[D`̐"Jj}c¤t|E}:Rw]ƿ>[l20˰4JPx4շ47hmj[y :QY"=XXXsCݨ yӇȉ$=$ _𾅵so[t%"Qk1E% D:Z,!TA5K֥b7oıQPA0;l$JGo׶憅^972|0 !%c kGޖ]0m0I|7};&4-GWZ:oo"413־~Tcz ֘Pܼص^i#ni_x~mu w!?T)3z_/9ur}g͍@DqtK;L;_B,-u;455y3qg+Pq8ҥ-]gܖND.3y"bK39]*cJL2bڛ߿yS_d!hRX+N_t[M:y{^E,3ֹovޭ`f}6;Bn}?'I Aq?Fֹ^N6*Gv,T_9+Ge$Ԯl#-ZVDH4?.=]UDD$h?|q"5UOI0 9CKE86DD,,+{>O<]Pj Hny4Y Y34 ȡL2Z W\r}^O{^c+.1f.H-YbWR Dod\EO{UC dŀP+ L"qDoS"D\Bw!ԑl1Pڰ6Hon_zhnbFBlkaQ#4r C Glp1BcpP P/W%֖ḯrHf!8 H|DNDiڲF00C6 A/(76.99<_F#Y{h[FfCAa &fP㢣-f֮ZJ !"0 3pL V|AH mIƱ;D.8hH"='̪dk7䍏quhϷ'w$n]P=/ ` M/==]N2OfNxӲxy; wVFy%{bzRGV~OwbU CvMƌ5O7w'O\rڲy۷046(Nc)'~.FiXBD,D `ZE>3+/>4a8! %9Z\!+caZ 3 ~x-$0At9FV>:D@K Hq幣٧цPgP$ʅ^[oChf`\S"CHf s9Ɂ6(YDcm=o|P$5sA>&"*&m?ӈ2!z; kW1w6. ;{v^ }ϐHrEZ}Űsf֕|Chc묆[_( h,_ -oKeJ7 kjn^kSVݽ^ * wǾmho67f,OX|=D6s﫩O\ؔ5hϭ8WWւ^);'J۴fƣxCp0wMĖ֔ +CDEpYcs?Yra6Whmi6644+MX,̆GRT__ϭM^o H975 k扠ҝ0ҲZ 2Lw7pB'|eZ-U{l.'N%;Qtw꾟GoЪdPg|9ZӾ`vx! ̀baŁ#B>,}wD=Jiv}/>~_e*CtٰXD~f|QAKvDb{aO^ܵ2ӈal-ſݿ^hi(>{ɐt 2sar.9; jk'?FYL&m`_){o;,N- (>c/H;CFRlZP~Dp=O544eh_Yg+E_ο-/\6/DV?;j8]S7?h,W.x֮ gWf>saۖY g[D߾sȪ$`~ DPt:5$Ech֪6j.m+ABܜ{n3ޖMōqyCDV2)}yʊbQ1_̶%*d\A^PNtآB~V{fK 24ϝ/(Jq&FX46FeLP`NY Ԍqi2фoH-x9?ߗlJiRN0ۀj$j*Cnq(B&t2=s Ɵ %ܛn/w`$A^GWJADD"1Y>?L͂շkh9ndt'IUF|m[2;`@ܞD?Ty F !B7lWNܶL7BAr`coLT,B>H$3JRrЦ Q},}#ȣT*(?# Reǥ 6!Z<pc%Jlz.r9#Fj[ϸ|bpό}ZNp'B8qvvЊrP5 0,+\.gH .ܰklZfϓͭ[_0H',A2њsSZZ6QiÉD?ܟDN_>42aqm ZjesS}& p :ZL` 4Ji)%6$, 'Zr >\]>>U007lP?Tуe 7Z0̤aWi-` |\`Ad~ۜG7;nFKsljlvރI8ysǃQamI YDZ>8H s/~O8zDPXhD`% 7kx榒8TW%gAbMsOIJc?u2-qe7TC\@'8$d-46QkdJVBJ|AKf]86e,2sD"dVc""g;-|h51`l 8,0oBk 5H0C̀ th@ZhhW ֶP5%Q 151B|eBh"`Gal"(mP_LM19UG 6:lذ 4TP #w(ʮO$\6FacxNNNAkښ`|WPqߕ1 Qƅ`XK`ǓD28m %jm2I?A "h K'";Q+ ;Q 'BPCŽҪ\WډyZkW X"N$ dx">Ak#֎N(+n/W޲`~x Nzʰ+@<HĂ B2A< B2E*Cp69WF[Zw %ذKDɖ Lшc:b6 I֒WiU]>x>5m\AX,Ǝ!#B!!H-3`P8 y/ONKh:i{ܩUĚZoԞ0n8FFeHSo"s$^Sμ}9)MOo<}|ՄF l,=JOO{zl6.?mw|LL[^,1hnƖY۱n-!^F#]Ot:uϿ7tl/ XrҜLNefF[s-37#c8ISƤRSnйo"  T"X4D4յd̥kXJ}hO6ĮaH!Ԙ "ih7f,3T($LD# w08Zt*Iq̐p(Q z&LI^3^صgubI8aI]Xpvm}Fk4ƜN u`1imd1TxvCn4ֺbu6-M̛ӈ ˜ 6ԖeAi` T+C/ ]ۖޔ+F]:.i+a6Q[E, ĔŸc޼[vv1M 3kV LJܑҲuF)) `6-K%OELp biZ9|}տ%b_%_z> b6<kxE  f6>@a; :sϯ?}N:[OzyO=/~.OyY҂1F !vPHF+"!ݷ>?_o/t| y*ْ" ِ-p=-+G>XX0H'aEhΡِb뫆~ھ峮PW[;;fZ+)LA+B4N-#b6}C}ڵ{6AhI'f'1(m>UF"T8B,֦*`J0W=;K^g=m"$АEfG *XYde0"bCӥm H$`?tACC}?k!!N&03 arj ZDF"0]D`֖{MM!D )@Jc bXO Iꀫ@wLE{kJ~aƩXÝ؋h$'Qor@ rp\/ޟ2T5GeY ۶151"Rcx*Ӂ!ƛ;J|xl $!D!X4m%GJǯDpU _¿+>l[K1R&HXEı-);:?o9q)o0]}fc'l`;HK"?9dg>r*SNI~FۅTm-u 6&lcA "R82azz?ǩ Q|߰ 9h Pr}D+0Q1UoE/MP?_HMu|eA |D*;AlTS U_A6jgdèioV]{k(F 5i*Qg!3t>2NCe#h}4Y|F C|Tz %/]p9|5[gA+ǟk| hjj)&k` 0oN3@hn綞a RgRjgh p$~h5L54Aksg vH̘3kVa5fj=9?tR;J^[ܹY}Wg}4m/LY* Hx%0@@ 6]+bCoyt;OěNriF`P+0H;4R 6o_q${]ͫ?*v& 6PJCYIUC7~Hkk}t&39UJCf{;mYmCK@(6Z![.!?1)jY6>Ul;s,!HYA:z*BJTU^a XkgQ?ZXm ̤1aD#vUdZ@V hN0۴wǮg޻oV$"U cN BTp ж=@Ca|w5Zf/TV.t=(+ÃQX~l|]߰QƇ:o<"(F𡡵>ajS6Ya߰Rup-Em |0|e`1c C+ Egⳕ)M|:LejŸ Ci mF;"Va)UgCKW-&RsmZC?8L&Yq羉5S=}%r왴bB25FsƨZ`8"cl* $11/<-[^zI9,oc! va\| LкriZl $~|omyOߛVGUMh5)Kw?\=ÅX$"ӦjE }hơU0~$ˆGǒ" H)? Jo!qk~jjrٞ}cZS LHun |рG CuP,ڈ  ^<&k?{V ܴ:a! nrp'WA3C1Xa 01 {+`dG^7b-#X Mhff5\.bld0 . m\ <=vZzx~qŎ]-"!,FmmѱIY3H19X 0i~gu/?؊jGW#AU_]3 ̬A}yaE߾F+ ̨ɤQ.RtJO#_@6Q֮-4m&C u pM D}a/|Vn?b6VL0ڰotX.Z8JcDTޡb60 ^c*y"jZC&Q*{p]͡L c!9"|ME)15 7Uz2X, WN=CւAn:e F5=ĉJ&uuΘ'4IQkj<5 K<Ö6z}6GΙOh4/:|Tp 3k0ksk?5U)m}vٻ{$]C52]q``=5wA}S)}Ól ͡0@%}*ua*_3w>N/M2Fb3r%p/2u;G6lN`Rl䪂x'ROe DpRvP5I$ϴ J"hD$݆Xc=@*^0&/&z' ֿGe\2G"W`cf$l9DqH6h,p)0LJbh|7^cmo[sn\Eߨ-)\3̌h<9hnچ&44u-U`Ү iO}'s?-ݟ;Q9Ŝ޹sX2m0Lh=K_fbJFl+H2)/gU[M/tm[Jm ! 3kcZ[c FAhOFR1[z;D֩l6+Vmnܴm!CW&f]m $˱s,{ޠ{֭S,Ī-[KG 9l tpGDP ȈeY%cImxQu֩, K @N?,ri\~֭ۏ/֮]j"ZzpZ{//Σ5*fe_#X໾6=9wšmiVJOoq}DsC~A|ml)/xv;oE,zZxpE()T,W* ]?rsFG *|+XIK"e|?H >ѻɱҨImX'dԌ1dn|f]M۟>whpx`ɁgzބBxCr|`\REw@FDCV] ?g ]Lܻe_o5i٥˥rHh?A 4Xj&bFnݻz yM5Ykf b]*E!kc@Rr1Diē`LlLm _Ou&6{%}< _g?ӍO4!_V0(fV19ݻ}ǜXCX[8϶vk\dY\.{.43 GaŬEݽ%RKZ-)ݹs!?寍y3jҡC(c 75ԉ;v,uHzq^6׻|Ѧ \ȧ?bǓQ2`6J3q"nɼO}̶I:)Ѿ~@ȉMCCyohBsL:L: 1Z\_[#{~,vؖ|9r9.(Ȱ_>Bp(jEj1yz;D)3Ѫc֕s]aZ(Ӧ DlK=ٗwRl5cLV~CypHzO_{|Z6a]zCk 3V`Dz{L=91wus#VB*".ӏu"ZQS[g1$%+|GbUJ@D[\rC_y׏ b䊺Z $^:>@j lBt],]QIYd{>wWlb ^|ڏ]W]grE*愉Z{n_^1A[wˆ]~œJd"a "JEc/<2?̿*<&CC`bGG7 HW'ra@(D\$UcmF[itJ](Je UkDq2Y倿0e+w=Tv ! qwƿ/D0FkYٿ\Ն&eZ,<\ c`"Ұ 45 p=,&gr0JiyAg\.g{x¢S4D3ea01kP @#g|wp-@12@5ɋ9 g_zUev}6S?пoZ="y.BdaW56.y7Z[ `#HDD8{[ tɮ#su*i_l}cYP?S׆-0̐:*30zkҖG {6{iU3Lt̠`X/W7<"ݺu*Ϟ:WfffIpȰ3_=kҖ!?, {#o9ܰ",Ϟ559ج$g)T鍬#!W:8S  `TT;6钯ezụ;[|#˨XI l.mf@!:&p@?zzDeG}J2̲bۮwM6+Smh!eA8f~WnSe-?}5N<]qDM.;[X B_xlgwBZC>Ñ4]]]RO%I-=vvv|>OxGpa3,B b1W)Lc@%IBa``衾;+?lN+nʻx\SSM'YRчo~7GCդcΉEW4)}hpܻ7C!޸`q55R|h׾+7 ×VTZ׵y "TȲ)@5bJad {sfyx=%$T2N'#>\IG% rz9o+*d AD!CD:{vo|ҷrJ:,9&}E5@V ,X_Ⱦz>g;{wV2H@Lbl#6PG$VOU^x~VoT2:US*gAi$R"/VkOU^X~6+(3zejWקJցі`I[#+~oW]]_Wr8T()H@ SSc+?~ϕʾ+ +(x~Iy+3G燻sOwdju&LijT\\=u1PC/ߎƖ6qm#i44\^n܁`X4GRw~l=o-ܲF[}t{_?Z .Ds xg54E/8NRi {[W=>U5֥[H-!l5̷1CX[B&YsK$ܶ16l#|̽<* vL7Yب4A\ t0qH7'`v3d݃M-Ɔe`r, "| >۶m͙wf2  "g-Z?40}ygێ"<ݡ >gZ^٬X -3|-I Z׈ k΀Ľ_%4VmQ)0v(ƪ 1#{,7B&և_RI:Ee0hժ;NzwmV?{(KҎtk30jdQ}o[d镶cwHL6;+ܑ_?0K\ NB-s"Yw_>h*?o=cI<Yiv^`3kXx/jo͜~(s ϿP,¯TLǮ_}=餏++rϼ~jW{<;qqpӮ?xϺ@3=WӞFcſl=vg:!^z~|9bqxܺe`x㜅ڣqm܉+l'c}dqo<6Ų ? h9ƏY臙l'{EOrEbćIZ'E'yF/˥{7ns'X˚mb9t?ڄ|# \0Zb`؃f:V[ϘCpt&q-y- o濂!7 ..?6^i3o|m64&;p}c>40y"k?6[X,z6H+yWm3+o.1#*W ݂ؐ3H^ `fnKvUUZQPo*pu ')56v䕮9:>}a +[? $im|dcoW&K _>:v|[<'{f.8sז).w oOJf_i>[sUli~̙?}s}Mc_tњ蟾@ Nά֖GW{Y؉ޚyw߱ TY TL=]{n9i3c~?f\.7a47Vᣒ~Q 0 %!U~WWz-8ה>wȮ ?ܪN+;NLҜv΍FlH<- 5mu&;(i5|)eS-~V0s"q˒$ִ9>wò[_mHsCx.w\{I*r Mfp!M|ZtN$.w^! 5wLK7f"ݽ^۫c]]?pOxxiC>{_އ|=gЕXnr_mɠʍ̹F[H"fR0͹uO3H138fcgʐD3lÂ请gbFޟYmLf0aM0a kXQ8(p@*9 s(0 (  [Xٗ޻qL$<ՙIﮮkm2 `KɭVDl;_/|Xx: B?4gvޙ%}P˞=ngGs J@6leLOt/qNiϝ#Çkaםʯ?w(KI];G6cC";`bc3~:]]M]Z3Җ 9]zZU:M]ZM -<1yRyݚ';혅sU ןdO?ϲP6ul2XW;8alV!ohOm%cfU/}g>o6vuў`3 _iwNEWW?_F&iSl`̈́,gܬ:E{vX J[ ig9w@=I/e&OMsRg;Q͏_ϟ8MgH/pXd_*:/DAm7֕2VY>Šs1]RJg```32}33tW3׵ļpLN}~!k"ƚ+}՝VE ;[vHp'aŭS/t.5uKw=3sŧf멆Hi]Ym^C]q^w8 mrnt!Xa̩~) dO;ot'0!764 =qmwwSq=0AKHVԸ|~GMl[TL[?=Lon%Z/t]t(l'iG a#*~(IҦ3D6V2i*}V¿<~ܺ_p㏟X8̀XR&dEf\VR?fge_FH:C qIu {Ìq]5m`Wx "1L .BSTZ?,3}pP64@(yӲTv\>u{u7OmB+.afթ,ӈec*ƒ󖡫Fw1M{OϾ~&BD5#0Ou!~fj<>x⦮}^ӹj1Q/CuڻX(~H̚]?34->1D[id%.6KE6nO[/圇ÑȧD_ސ9o#[b\ZV3Psy%ӧ}뢓C"@g9熬 [;[#/mZMů3ӛL|ɦtYJL6+ d/ e2&BqO,r?}672q8~Bn@x=α C˗+ LFFիx{74mneGjO46>#b3^ oz[w >" cm)M] cG|ɪ]+>XooFd7vdLȦ𕒬4]ЏqHǠB jDqlL”aFcRᏢ?7ܬ^_{_4V=G3겾4g_+ ?B~@a% Â5χo'^uBM0" *:E?}4ZojU9d¶~cFBnB4#l :ͭGK.h[?T㏺5:RC͞1&>Y)T>_-1$xil"|Rv65]C9T̯P}RIAL櫪\qD2@8hDsX*ι-qS_?? W*%?4zHsceahhófat|B АB<O8DpZT,j|ۈH[xo_p9FX?f ;  {[Ȏo%մNոz 7_w@/݇}8ܳ]F~0Bn;g!]ԅp9 Ss\n ^]@ذ}j P8|\ n{!00ۮnhվήUey47_U݅z_Uǭg3e8d kzοjewì:vizmH/Z3Bo˽`0_8d娳 Lv\]繫Y&v GtU> ɄuU\ӸG`n0膳닽ٗ}RTRiB̾x岠_,|:iwOw<0?Ԟe!„R)R`l˖oc;1)_AM( M>i@wp4cl:}'<TwaGY>_0<DZ^W{/-O0ƈX/ sV˃:?#w9謇,S#_0,=qޘd^u (~gƹKq\bh=?=͟Y`L?~jwt˲Oc񲌩 VӼ=q$Vty#777zm.qcSs(jv e t<]ƓM@d,l?\;pc5ځlȋ/ 5{vD9\E8I+]@0|Y>y6߼//V~=1;w>˯U/m 54qZAGŲUP( 0MK4𔺍μ˯=/ZyhȫjlT!Xr D8`/iڄR궧o⥯}nٵ㥵<<ەZqXزc 3_Z8A]*xVK$nu{ ''2:OZ-T`P+ԲίJ@1~e>~254+K%Xxb3kzֵ_:ao8O;q[25ZkЯdctn^k&&ƙitRkki3o'UܿO|~ӟ}y~%NJyV ML%]ss1q_32ukiIs7_t 7_t 9 '[bq LmrD)bf.tEk-ONЯ?kou 8?k ֖'"噺5ؕ4DyL0e%"醓qG/ [^~>${$Q&DK0uck' +z .R`J׵Pqug-2|x85_]$@h&?2.fwu*В]>qgۻKLk>x.j05&(~+w`ZhH9zMHƔL MnT_` @w`|3l] |ċp-] V]a.1;\y²7zcіC$5iսbժU즱~@Z1;ϳ%p~)ntU66}yΣbb_9S[KX4UJ̈ASwB $mIi@c(m%rLW 9Z/,1%3s+6B!T"6@e Dg@\3!.4\wvuЏbs*~}v3 X-Tj^Ɛxux1j,H´yScØչRC;ok?jkh3u>K⽜!냥D<s\ţAnD0`&&=+E|8cEM8M#c?jji\wƱKn\LM^Ɛ(A#V=9 %ͩ0LS J6!Wq5frܸ慉m݀%Ec벖H3Lf#&rJ %v"ڏ̆!U,yrppuwm|Gz vBZ dJxң[RX5^ZߓKKC |@ 遠&wLOOiK\7LV&OkL#=.j|i=.Z\K3-ڹ)]ifb|ifZ!ݰX>_X2ui&=Ϫ=&!\OamvI&ݥŒM ժ2M,;)3rx%/4 ìl2 C>Uch\)_Z.Iwuix|BkMSNT玚k]it\ITs(}Mgy>S꥾XR!M渒4M5W:5ǹ{A+' M(CEg/.ٚm)YKc44m 9HƐ*!'Є5.S Vּg+x$X F [h6 {>TNJ sehhiً j5RRXB 1F|7_͸8_bZxrͫ_v*+p|.p=OZ8 3F+q]w_~o>g&{hN||K۷[GB:u#cgA9=G7RSJ%8z0Ƽvjzdӭpمjq>d4p~0>uNJK< \JŊrƭ?{S=F~+d |ѱyiE9%aVo;o\uO y{{:jQpP(zjSHKtr]H'Ffzk/\X]?l~HX%oNo:!e(Nx3G +Byd< (5U=fͦX)N te21^'Z;e-(1fj@<}E$ÍZ<g‰xi^Txf4|LR/KS_E'"BnH66cxxdc FobpT+UJL"Κɿ¨W ~L]ڐ~9 `l*OD chHF08<ϓH%#QBV9t3oki਩{6zF/㭱`˦P +W$a*"D&&sUV.D-#X펚Sܮə,bDHˡ`b S H&yH&P(UUM|ƴƆCe׵s_>U6FfVDIT'eqnAާY$8&\̙Z͑-c2lQDP6Bf$/+/|Ju/J3 H#$Ч{SHXnr&199!̙3Ctwܼ@0/(4Y 2El˶TxAS>s>^BxS;hYT40wp$C! eခ|F 4qޔښZ0%uw` hɆde2ZcW^LxbTΓ~VloJOli,hkihH: 4=PD2Z_,}-TNz͍ '阽L2NcH4"h' 1>XwwUcz7Z<~4pdɿ!1Q Ux5Cd`pD$.ݍG&~HʀS/(.o~|3hu 9?ٱ(`\mmR 0^smY#+w?aSL:X2F145^1)j$bf,0)a$X\a`Z͗(^ȏ]0, 6y.0xj!XY)Ԧ#ka5W08*~=%M *]0 jhnO#lc qS ECSa *+*J:??QZS:3=%Ͳ iPc*C" 1"b`PD4pI4 @풮33֚:/?Qyv1D93=!.4(.tHJĜ@( @tF9P4smBtxCDbP)yt]4]4PqU6D? !lu:i\džnp]8+TJT%Ez:Džkp\RUFsq jkn6%cW9$!48 ]q03Ĝ <Θ)"9< 8)Ǭh'>)CԢu5T3~SS1_ɼ)(R\p!- Ιp]ITq= IWlvbfT``SQޓ ".zu=&AHI%3HI}`x7K'%R\'\x$OJIt!70( 6Y&Q >h3DR"P%e-8ELP`\!ő!G`Mxcvϖ}i#$ x.</4 =GI@i+>c8,=TIVG=[}oq9_H쓑T l-{}JN #9] CWL3jh8V >X-n: o/ӀO&a]ϭxJ\h8f| 6߉Q\BqMG2:Vyg|ZtU6.S|24)Gh8Ý؆ ҁ3Y~oyГtO=ZSOR)rt"߀*ke0Cq]:~d<j=Z^c?Q~.BAm%d\Y&a`FL'nι_;\*pTgvb X;;c̻OMkSVW!8fՉHFu  .H|6+&li>K|OP0R&T<ȧ&F: xH64c.Ah B0Zl*zvYbwv|cVse<RxOLE<DdZC᫏U֚`BŞ(Lw,񔩋J*XZ 5DALLCCH`cmgcwgӧO:pQ4hTc1>ˣ1B4$8Z[!_GTVhe\(KRb-ҶqnjJBIhf/LSS5?:FXAmߕ\*S`.r fexvJn/7bSG&rҊ6ivi\"7Z zg]w0ÚvYϘ,?`\!#08Ço}Ç/4lx,.TmĢQLNd2WK̏ M\s!8*LCq ChЎ[q?glx Θ9RŖ) U'_q]σ&4Iˁp }"uw/>h:q@~lꕛ6+b1HIa_1qR~Y6=|lOb@1#Ӽ|S_&$[<JI e,s00W?-3n?ء'`:I@RT*_oQoڴ .z0Uך9Ngȣ0,4V7q`\8Sܪ,q!p+QM} {fifxLZ+0R\V8Z&I09)UבR,O}@)7boUfY@sՑ,HUV"Y| 1D.&N!x\%<u~Åz,>|Wޞf\s^UXȶ@ Oc^K+,8Zw˧xu΃ɢ0+Vޞw\,M5pK_ǰ0,'$IxS`C?S긛>rpT(Tf{Ykb͎T׊GCp_DkZH \)a2jyܩ~# B߽a 4_h CBEd k9rd#x!HF$&wmX0\McLeAW(B`"5!.bn$PJBur+8!(ρmIҭ6k3LUsNAJBwgקC懄&sS@d11_( b2a)e)<)DP?F"uܼWKm5 [pZhW'% F4YHm^VD ]*AyjvYa84ߩnqñ4N%"L`4ep=`!,]69FniJ1Zs[HqKH)SC((/\iL5M.^}V) yxR\,q=)Y1bh$\R!`r*y4Me#G#(RT*s=Xת-!HWlD9bƬ2.?i&f5F* Tk.$T}c.Zսۀ%g 1zVp=C(Wjl2_AhiC8f0)k$tO5NCIxsâh4j_ ܀?\~/OAYq@c&.tDcK[%t)y]O4CKm!p Ii:3ck`@IGJI +fX1x)yccttt3(hKs羅6 Xq@I(b@ <<) `t"bEiXҩ<gŒšYCף104/` q 0MnY J8gp*c<1$l{089Ʉ/xIJ9`Z: ]H|wUÌ4# 9 NtAJ$ЬHzHZxRbؒqM"H `H6@I \PR 13Ƽ"bb$4RQ( "(P;ڻ 2$ p^b# [kѐ )if-Pu} Q]%`46pθ7#!$̠d2Q_Z/|Se!{&x)|Xi C`Yu )8`2e(Md%#.#;?2O i0CPn Bj{2J)8mW+.X,Χ;VLSaSyK&a:6L3SI+tǶAD4\)xj J%T_#qdhBA&1aǁi)J^q%Hx2#Jx$`V T5W*p\"R&8)B(`q%JUGF,_ӏd2@o4S5PR88g;5L OL CJ sQ,8c(JChHqI\s] q Zrv5n  M l3950f~PD pB*D0tB[z[yt~\?hj" &` V:X^U[Jn@ <$‚E8K\aY(, ~5X-<L`!VUcO.gȊ@yd.1ADWvkNQ)RÿgְYQw40 4MtӓH b_ HR: S 0!'IO*8\yTA ` pH$\.Da;6jeA5ucKS[ǹP ^`'FS:6{PăQMD;2l \+fPko ɳJEQ K dW-u>)d5+"fCҼ +o@%<0ߤ6[/tD FQi1)P8T VK+T[ˬx+'/Y_]iPvM~o"xÑݭ 4x}/zY.{(mgĄ:PTO xUN%0O)=~8ۮY2m9>?8T=dUyYIVtIcR~?mWY/ƚǏrO1YғJI )=_qRRnn쀗G,@8IDATKO)R)5}?V?+GTr7>_GU)Vx3_UE~?𺻡= Qr)ǶKcLU4RSr;lo=l:凝9: @8A(OLSe}0 S,ccg>K ӳ_k~zXЅ 0aS[x㉩m~֭o<6a@b!C]}5?/;'tZ\F&&W,gB㖮ۆG~c#['.6[Gs'LMM,hPo63  ; 3QxRҮy<_* *]Ldj7xӥ2%3AI'ՌncX0 =x}}˖闬f7a!jz'T }ZU͘tlWկe˖7lpu~65,6Y]^u,mry/d)Uy5$x5, 2 Q@eY~xܼOi6TVSZTu 1&5Â˪8W+)_H|""$<Ƙ$)fjO}Jpz Q)9:M9Œ)O6qmy "E37A2c @l6>N 0ZbU O| +,C(t}(%"w4}x R1f<0+#+Xj%MUyTŚ'%IZScSeTuHIn>H1?dCnz{щ`4yqePTj3 ]Tj7ѴKJ2, :/-' l@xZz$qw_ӕežg|{07:ul!?D@H(J%CRKJJy\y`;/-984U;67B0 IRū;y7Ak|`Kŵ?~pp+``5 $u;}zZǖm O*)%So[HI'R> K!| [*WEIUӂ'Iu㿫=~:x~v3{rQ㣃׺K O rCCm}R -~E .JVJKCufܙ{rCG  ^[*^[+nycw4K)Ԣoj*tw]V[ŗ}Geeၾ-/y\V6<݉4wpT]"kdvcϖ\{tdvmu_R)"UԾ[o,ֲN>L\HdO+9sMlzt`n etwkف/;'~\M0]-gA.ң~j44agltP >|wM9&б[UMȳ5m<VGR$iL/9LK@V6>uձ[5 oS AǮ\!`: "mfCC+׿^cv.^?\1m0`9jb$2bq.tQO}^g%^y]::?-ˇ6k/{Iob`;.׃W  \0bzdq]LV>jNm%p ݭ|=$wƙ'T a>Z=m_k[;Wyb֦\7\)Վ9]rƸ1}xt|73v$B_xdjO.[L߰a{9M tTcu >6_[~慳]c637bsOw̫OA_ƉK. xߍs۲暶P8S|}s.r<{_h[8Oloe3.C[P*Usgd+M=͊i?7gfu#O\P{k|p/hRucisMw. /P]{ӻk쀗d;wiuj9%rR"8]R1&ιep쵩9}}P]ob6{7Zv^C$x-bz6[IR&s׊n>@v?00e'$p͑Rj/}˜dDkBkWM;5)bZ.zWsڅ~e#jU<[cت0cr䴓8P.`+)09G'ŒoA])v^4T׸խh-uz,%905-罧睌!_#}pNrlVY㹴U7xK 顀60c>ʜNaƦ8cilq_C^R ;®֜%V ,t0Z]OF]=ň\NJ_*NB: u&#jzV*ZEhZtS3<FeX'~I*Fu wʅrS*8a2h-eXq$#P(J"B an]80s՗hW=@ Vk`0%VmW/B|j?g`6g*tC34&ʥ_5Yt&4op%ݾ8no^g{OQbkiBQn-*\; =ܾtZໟZSU| 4-_*Ry{6I `:5=%ۃ?3 ٞ's*W 1GÏ 6tZd})CJ*+ݗ>pփA2Жg!l}h_0o\oߙחue˳d([>#;:Mq?;wF[;qt6isg ~Ȕ;z]}?N;C~]?6~]8?J1u *c1atbjd'^UAƂx&fi~ȷO-zj>=mX]Iq4vKYߟ!z#OmFZW0!g?^^Ya;1͑Dh.np:[w7{qfûOݯYPqKR+asS MӺXZ'_2wYP QUA:RA|}$}x'8`* #4=y$AFjʭm+o0ݟ]ߩ$LiUP]78Aڿ+K/[֛ɰL3մ* AuW)UnPE7nzVi\ f*T~'y{`=në,8G״"yVuo 5?|ȀwBۋ~E7 _ndXoD|𳠽C3-ߏqݘL&À{ߌ]lӗS? M5s^U*?{y닷f{O[>3\h2`_Mp<(zSm:ΟX˴.5m_MFݓq=]˕oټ _OI̼S9Kqؽu[~pٰ4].p!:ԇW =>~HĀ4vvpx3?ѿ!V~|=P~\lػO{NW9R~N~t6ܒߴ)vՂh VƋP zFx avҩxƷHo7~]pSrUqFog{xzyvǻ +ة*rgΙ씌Ukwwzֽ`VaJJutj_&&|zIvķ/X߷.8'y)? 變Lwݭ_ش|:;x+Oo簐 KO}ho`7؝^6V/חe?+~:-: o:{oW5f[78;? |b޲G޲ys_wܹoywQ켅s?n!oC?‘@mնC^l?o:s?/kg-\s'N<'[O`?r!:r҅_;e?>s9n޼Zx9p{mW;jP˗/?w_ߓ6@{mƛ?{}_| PxשG_)ޘs^y\syoYyWy!`עT?]hh[ˁǿ\;i߳pߋ~[׶|ui9O?‹~'#:fIyao/fk[6)*}3oŷSmfw"=`p}际/Nw{y_;ֽQmilٲtmpΏs;[L>3'*oB~s?G="/|AD.ؚ "rknO}jC_9mlej*w_si7_pں\1_+o5לoV ig?OvM{X]kN[)}i7=ÿMOEuL]=m.PRS8??#|ޯu@ -KX37Sd}uPACfP͡ĜNd3#кЅŀf%jNoWхih5-kZs<@o€[&5Z@NL便5BaXBfM ]Ӛ[bdpMgicյDV~ڛe}"S:Md^qОD}}se+VhڰatR 6x+Vh:c~~hmk%vxVg.cW6wgߵ^𻺺]٘vQ>03 MRprcs!Md!Md}Ӿ8pr]veg};?-cuW.(?j,|"{ \Fv,|[~6~:-O\~cl'D~_gOtPMM^yo{lsS=P>t'!~Fbf%+":Z`ڱ]u~H"a4A߿=7|0ɴndcSLl3hԖI5WӅL&L~'H ι9Ѡ C:?ݾS,D[<!]]e,|߱۴&`ڹ`&$1@uL1{?nݷ@fT8YrhP{Vel @=G>'w y8~Ix˥?wl ;j:+v\| {G #_ڞ7mriӴʥ]eGM69~dz>d=M 0ȧ 8Ҥnes-X@J . pBȾ,~Э#-iB[uiU/y-VD99ֶˆpO/+='o O'׈z9cVR&ћU?)ZZZjlBtZ/{O? H$c446F5?oFWGg2ޛͪ޳>4)~**4'#3XغzNC2o$dA>wPG~uݱK#U(;Z};}ȣ@4`\Vv<'1 Y:;v7N C E"GAVsp8x٩(~Gp"e ZشQG/_ w.3: #0l@]/Ԅѡ9& c:f4n|f@Mrٵ*ckj0 c}=5a1>5oq=yc4|?Z98k}X/=3{^}YFVR3%TTxt%чSWc<96~u8Zu6 ا1Jp>=ah=N+.fB)ܴx] x>Ѽz\ђW0;4~Cm{K%G}o{c5 al1oo9np cK6cz3͵G}7o=L~mn.gar%t'|8_9~O=|kM \r~¢9݋;}>>G- :ߕ 1F-FK*Pɻ-֘b$.N֘bn%3Um$- @smh)aC`Q45gU}59UZPمn-Jֺ k]V"nF҂jrxm_lESsV1hÆ6u+6$51q5Ro=NW칼awVmc mC~i]ۆ(ՔXޖF' nWx{krjoM\uCщޖRMU wfX\՜ Y U7&QK*՘rjPs!+0W:c{fx0*YR**Os.8T\h*n2*Tgբ Ӫe@b0ޱ 1?;?υ>0-(%A tM5Z 0.8 ?suM0`:0.\ӲeA{~G> khym_Pm|:5H{Mni]x^ȳ'^z.}h@=nio):Xt d0<;<ܜZ50=FY@~i ,k 747Eá?Bh2ȍN:`>tZ-%@tvZ{[hyr [j|#e֒nOo:?V;|cOvfkqiXW'ml/f;~{qk[᝙;Wߧß;=>ZmW8n+3_yB/xekOwM;Z<+̈́i9k`  ]]l_xoZiB̲B0 @rBӰriC0>> >W 3&8 /k\F`B0MyEUa хs7I\211pl Kkőy !URnQ[2o#1N7+SMkM )VyX4>kV'7 mv`׹q@綼h֬O&cgYmtlܛ=kcSV|qF_Nyujgq yYh27 ~V.ၧJ6X T46u$~3[,0-PKpu55ه_ RћD}/ٞ2 \}:]]GM:- Kn>" kl1ya|Zk^GƎ|ax-X>@4+iElY(p)&ZiV^ ђ =--S*1_~5^#l}z 2#Hžd NNJZIrcL&GXDfmOb!Iρ񛯟}P(,O-[Q)&ȮI7ecT,L`8b~  .Ϟ\ߎ`c'7n<X$H[& (WlD#U*,cT`РBBAbI Gn{e4Z$Srϒ[TBoys=MBDSC*b.{l6S؎b?{Og~Ÿ3h m#.m Tƌ钛pafFB9y*ef ӕoTe0>܌8T;1tݬʕ*ţKY75ܐ}sM dF/-Wjd:m ]7S-| A$cc +#fݰGQ %`GuC!v[qnItN$3D7z3X7j.Wxs|(D}iF}} T!Gf_U-笽u^n8 [ܔ G9o/WjsKҬ/Кw߮[*Uj36+B9I_6%ak~jMk>s>?f}i'N^4DJ9@I"i\:ɀ퟊䱰_Ym3v7DW y{*Lr C7&qmDsmmw/< sK-=gVD⪚X{c*(?ufijz0t"l@Jp^?rIBI ͙ \xv|q"R2hvNۢa $_JC!!@1ä6h[a{9 Z'3@*?t΢}<%V81R~ih ɇLC8 #+Q:dL[@94= WH"FDBp^3eh$C$C&0k( Ibys͏@紧" OQ= 6鿮q(C_ ^V GOioiy4>1(z烁--F :{mzsBko%&ub{ם>,=1m^)\k2tFNCIi3|E=O #sJ ۤ"#". Є8;,8qi1&R8u3^6K[I!D[ BNbxD؟3qin̫V!بMq?=vuB;zEYPD<BI45=E/ Xs D4vNG"se$S`/gF ^J!*WM^TɸBHT@Q*^ 4fcnQH_ KZ)^"U\=DHϳVuo;- ?q6p~Pv~W1geQꂄq=ֲe-/~OO2gYfԓ; o Cv/4G 5y 00'4Zf-/g2`{d<002HAsެ[^raxē#IB/!Hσ +E Zf220 M\8W:T.*r1u8Rs]z54$'3|p!q'% .tM$ 獎M|È!jLZb7ꗊwQ N& icx)q yXk-Z÷;m}lq`yhI(" C$g>gO}q2 Ϸگ}>~u=\k]U箺'}E1 uV#\769 !# yLMNB>'gZkF;VՙI_ZH!B[(ziX!"8&W aWg@\͘Shn[vٙ8"mYHP;Rİ?^ˆoz-6zJ5RlX8$Yb'8c9} A.-WzDqJyd~#hck8NY>98' "8tW HEN9@ 0α k Pq#?k~Nث[}MV%Yc~ "gpV# -Pb`LTK/PB9~>]qHq$\wG4ztt.Xyug2?`@G3`LEi@HjHҺ9sk{j .C| k4@T%e(Jϟ@̰bc$:>J ~Z2F$Jdzrז޸OZl)fqYfDqVnI,B?mk:(bt_~imz'ٍ pbχ^o+HF!HȎ7t,Hz~nohlt 86:pB ~y=[79}>jƦ/ ~|Cp5ݯ`~9l9eR휅'%R~7lmB(G:k |=[_(]w-; V$Ca1]yx9:F L2Vs<(Vq TL? )**9HC.4̛N)ck J)ٷ`޺q HUFj $pQ\t B12:Nƒ~;WGoKug$ҤI$%\A)!M8'Hau v sb0367rʗq!=_8v 灙$,T 9hv_њ#"MU^=mb$)cz 牴.352T`NikF쒮[>"`\{7H6YxJTY! eAIc$ LGɫ+эݧhuGԉD$҅EgvBAEm%=gGo"=F Drg@x%2LC*^60(P#W:ʍAiX6gx97~GyFu Cק!UiH"u`xePUM1qe`gݰѐA=?( 6 WhEslp:;[iCƦPZ19kg$|OuLi$By ^)AOam|G T[ZB6`$K%A :\.J8! (֎j}hokqMW8n|ZA~,:Z*{jsϔPR9:Rye.,jXCk.I}$3s-EDQ-s\?r/pm(u8 z!n-Th-$&"X0lNW8L֚B)68Ljq=cc-DF& 6{Pbu?Xw3}7c(>: &!8b/XM6xrhqylJR;Vxg"&w~I&t&4Q0;Nr'~Lwk𑚋:=ٗKoZd&m+)桡_|;m#i6pI9꣹s{N'sgQG\^Gr`2~LC;j0rRbf@mݚlxg13Ck 0 !\jȆusD5-1'ѧ`֭߁V[6i8JK*3O9,&r=`P}8]Q9U  ;ጶN^4}6!Be|/3!$(ŕ= !Ρzh R>Lb- cB{cȞJyJ)v$qGQYg C)4VpXk#a-[m79]My T1(Zr6{@L]<:^Tjf4je HpE]'պ/")njzA81jm?t-8IsK $I_B )X3s'&&DV3phtQYl" ƜY8Ǡ^,(@$h@*y@HχIgD(cNG.6gi]~CV:H#+ GteR! D R Eut4n1굺 sF} c!D$B`bDZk(χ0F7^[SuX[B$-[4+(IwDHw80PȄ~jh0$zݎkmk@#?6# "Z $9a {q%XqQLJcmӫRpAk ! +@[ N8>|߇168I,k;f~6;%t[?SpfkR4*呱y%73kϵS~oiG3,KWM80e 7w~3_9sMS~ƽD8f&bf?'[o:L|̓g ݿS?Ϳ3ZB76Rr|k?w;~"lX?*ޓ.̡t*[Mbx" d;:AB4o0%p"nնmLcoo_2ZNb tZRw8RB3``pZ[mL! / A1UƐ+d/9GvR?9~g=?T$cPL=T0v BLB بLձz.CMD2wF-=Gq亖 Ӎ%8m50,:]Xl@6RHD܇b{Džl@c#ɃLl+33;L:`Ю@:Ib֖<JIAG D[Klh2 lp~ZGowƤ$zݷ1kk9 }K6]Uk _3 qbSGAa-kz( BL81/$c̃`Z,_Ia1$ c  Ũ\3H a!.i z$R]PS@쀸cq>Zkv.N\) X0HISSfG'03,LRI=M8FBk97Dč6Q (IRM hc!Ӣa`p$0.=H-4K`ıI\+ĉщXnciS'=P0;QX˨GfN ıj4vIZ46M. y.139~f8IthsŰj')䮎 d;Ha0 ~'o jԲ9qGR~aGkXZ݊ϡx9'XSǩ'#Ƞ{FobFDP-_(\sTa^Xd 31HN50NƼVŸɝ Wy*SAkGh\.QJ0I,ӱimc0%|j}Q:8UomM;#6ưo%Ll.uktEt!u F4.ThxкQ򩑻~k&߉wql)?wT SD,`N@.[̔q~߻`gPk $ Nz(%z-*%{g\bSsBZ-8sN 5i\FDM WARŰ<.~g&z~!DpewEQYx&t;z? #df4թxᶽ ꒇ%tbiV yqZKml"u % h\ kO }k-嬱1W2K]0! e=~'{ agQ-xYByĉ}_ (ipx/@wGFg_]J t!hq:vV%7|Kl3wU~W\Y v"F$j9wd֡ЕX'UR|[]PB v &X!HkLGL0.ØU." f+D10IݝsL8e@NmsG~ + "pt  )^h;jg \uHg͞kL|67g=1m0U޳d`h A3+_ J]\Kށ ;|>5""}m>UTNKB$.Qlލ H7j箺:Ӹ A`d|'c?KbyK!pt{ VKfؚ L-61=)' *}ourXqRUO26GcYTLTi$H=Lu֗z$9W,ON(7:lU$IDH#7+rS(猴h܇˱46:bf?,jrCѩy{5 0qpҥw =A#cSfRP3tyR.Y1LXNCsMaëԓ0?*W?4y?:4{E3KT@B,WL=~W]]s.,2~]RoxKaLTNxՉ9뙪ǞѷE]9E}]{cϵ=9>Rj/[BCw8("/'-Ńեx})LٌˇJNMDR6ӿW׊Y2)Cje5yίUs>AI\'!Tk1w5I2Q..Z`DʽĪwEI@*{^݂=M;MD]kl,e6 a柋Å-qԅ gIhfX fpa7CC i& mk!j4t Oe١q]%b CCCT*&g$ѮZ?361~K3mϞ~K&>R՟I$.MLϻJ:l^q=bv/(v1&!@ B%bzE?:J866a vlMHV\%v6+8gbv&u-P%/쮔=UKBgMgcx;쎭I 8gak N00S)?~Gk~mL' :l$7:&vw`hgej3l-#PCBZWJH$ZaǰLډ䟷쎝s{Ӆ%si#UX'<lGwcM3%659gw`d7kk:g_0Vvע hmL7<ڦ)N@A9⅙#.f1ԁ$U Z̜?$1PaUh6ι hεx<8(sM2F; 6lXP9vZ?tP[8Ii3 S"&G|`[>~c~H(9jDlqk2&yȓ\S%u1zho?68/_vccSHDk$ Dē2 v={HٗGI"fܿscRf Z AiBk/'*(OнQϫE4~"E[Ж5ЏKv6Z Y|cllϺ"&:T_=51C-3g56T·Ρ /Z >tyS94㞌Gs6z όl=War.VU˯>02""p;z߀/S}]k+]t]kb}^ͫˑqUhO:gջ}|F&]G:W:Q&jG',T% h,?j <ɃI&cgGF_}2ndTOfG]8..|6;U4 >dкe8\N 'qeS000[0a(iLR*SAA\:@;q ߔSQ'nq؏c|7:D$!jPfe0e [VJUMhl4zpf&l.ϭ3L qLc]ݤsY4%4K,$"qFPu`"6Dqt3E7 cFʷaJ$,&`s?q (p5&IϑeCAHoVƒo=2$3vs3s1 zܜ`$]e>ԉiTYgQmM]oB'~j.spv&Vq}=4dcfa4&ֳf-6dk>{~C\oy[?Fj$͹}*˓ Ǩ^[pUo{7R#;q7NBs֜6@uwrM Wa7Ɏgs^PpV>NCwO^Wȓy[w~?-;w4r6GYe -1D}إ|Tn/ a6'd3@19_zr "Uo9853cў FFG^*DT*626dG[6PR;vufC;\|R$ѝGePRR{1 {}#?^Rʆ;3Q8^(nY>DR T̆ē^*AJF&&,f@ Ab#hlbľJ ַLVYO9PWd5zrBo/! nEOA.uae|OVQ̷[ʕ'TV#Tt4z{zۦg*O DcC?Uu% D cфok·cAx>a,uxY s)1/G*&( >Ϫ‘iOwz:sddd¼ϪC|V4#%cf*>|/NXc%dHV`e8|hl:2wFf΃#Ӆ@ $@B)rAgŜW $)IxʓPJx"N䝉sdbr:P V~8%)= W*MDzRA)zJJ|3N/ t>@}B/=&(E~%غȱbvU%p\ŝӱs\@8 ȱb@Y5cpKz|[[U꩕4 Ӳ=|$scoz࠼m+?=f sك-9N/,EoW+NpHlj5"EL&iTNo oËkַw7፝<y]vd圦 (x۶m>ϨEޏ6 :|+ `hNVUrG( .Q|:n遬1l-Wq y3luΏqj\|EIR$%Fi->ͷKRg{|b>-w9@݁RdVWv[nq$6oLO_R)imΎ(O;3~cʥ9 i/ݞdáC#['׾eZNl _Իx J41LO[gQtN:?Go^> !dXe̵woAlhǫzӅo+BK4Lݫ)gz\GO|J.[TuW[mB)!?tzEkF"J{ !8HY{&?]e4ꏞ/iW !dCVZvp`2 -ُ ,5R2O8BNbe~T xii^̱Dć ?]9Bca-HoL^oLyL(+KÁ9){]{_kz yOD72lа>H? ˎg2KslDϽ?|p-N4u-?*g{[:0@ m'Jۏo%8jD0>w sͺTsu #wM78F#VDď~ [-nrLc~Jv};JʾU6 =ҵ|n=07Y'3Jȴw.VڴiSܖ8fz|"i\Zܖ$}tMO ŶQ->A|uUCC[h% kS͔B#m-sI.+Ii]-Zl aM7@9Nnklƿ5hEq[LgߊPb,nc3QC1ZcLGo[>;o UvUbv͜{kVx@ځ,қZ|ȠEZ7[q?+(MW/3қֶ;^ГߴeFkLӉӧ7#n!)'b1KsŪk/[MlG~gz>^;1_lh]JTqǑI_ls]_ Kv9wC `3ܛ>?-  $55W7^G` U!/yxrpӣJ%k@G$A؜zIl޼(ܼc7jC5D6gڼy3qrǎYEN83/w:O':^FE_nqH~#qӌ李h  `CfJV|.djKh$?m#8>T[1kep_vu۰/Jbѝ ?>{[S3~ȑoض ̺vθm#:@J/Y蚨vs`#vD&nW-"(d ۴аAjzWq";e:QxWg?_7 rL+Л$9y F_C|1qI4c37gę09olOkq"rB~$^9SH՛$ftM5ij|s)׫8|]:):惗-zg9|%wO?^SϪsvOO=sP8f󳺟vjNv6"]r*>vGF9 }Woo ,1:@ :Ne/A&N, 8,QD m"ޏ";_w>xa[kZ;{FZ &B1 F~kGM5 j ;;:ӽBB c,Kd17l";/[ݝ D#ڱf8kM=00Tdg\|@*fÅS󨨄>{S㧂^jх\[-Bp $ڠzUNv>nz{z[j#2)k0ZÌ po ˍh˼ p M Ok|k"BG~]>5kJ%߾j֓42{xW'jyE}Qo[k:z ;N4Ux jW$GNߍ#/b:^Wo0֘zh !>;ѯj6p&D7BxnH fUnn6%x aW^ոi7?/*{ ۶ٖ?#i&0 rGM`c'_T;n[2=^+LphdJkU\X_Flw ǵ8n խ=[rmZcM&DbוSA;z^z`TȟFK;][zZD`f.L\FBlg=>4vͿ}\ںU՚JC nTa<?2!h߿u?}%?_U[5N'*k˟K<)5o:orBVsᖖb8I=R6L/ 𹣭21=ukodzNk'!Mԥ` j j&O_ fW6l ekH;Ce #k"m$K>-;TmvWK"mLbfivQ6of{bI]#|X:+j[nD X&c]/oig=NbRwCc;<"kZ)/Dbj踮_z!a~ƛ"?ߍ#B֯ mvXr6n˭ u}3snohfK *kVt.ḃqpSC8gR5^ U֭\8MU+7MVt==~SU=7+Vt-_9]DdtKf0ē2J0ZSȩ-ݾM|mh_ֿ)_a-- [kڤ'T/ 4ÔQR:)s-ޓ|mhheX}Bf̙;Sy`tS<-g&ǀ=oq[mDaXeNOgkzD4LAKz$&R{?724V31&J= )Ҋx:J:H2}2`5@42[RLT=$Lϯ6Q$:nkiYPy?J-[ۂV"GDl=yss"ӑrB gxk__}϶t3Ycض fBϿ+I!PeYIKz怒=̞44@ 6 eY}5gɒ\6bq3l{[DztMZd~M/ ̙o\ _ ?̒8c|^ȴ1=]Koq:w1^nltNxҕ(clF誖pYzfX:7|d]N3ڂ3_/J-մ +=7te^._xg,|`^z s©Sw,ԁSd?~c.^B?\8ʉ;d Q;]+&7<~gMv࠼l`L>dghtdYv_6<:{W,jhp_^6|zN[>[+pi l3wWftr`6sß>Чy%C Gmt#ӥXL ~|`6ϿuiU5f-u0Pd?m6'kV^17hqpz÷AB\d$`^>,e/x*lчphY~;su U^: FBʇBnU s|ߺ~׎«-mα}E!T!Rz(H +p&5]oGɄW2leP*l|E=#xP2p\alK [竫r?M[+_/y/,C0P<۳Y[y0 ؁Y)0 !y|<(d@D Be:SSm q_T .,9[7~mϴ) (\ WLkv\pFPy ]3)[OߴfB6e`|.DV"N8Ga =|iY& ÔOXeA>Lils% e=-FYmkGlzVQ|7]uݼg.)v|Ú }-sm)2ԣRGv<\?ﺹu3oƞhh^tk:~9$6c j VonkZzݙR޳Py}Sj ]O)Z,T&B @*DHH c#ܰ9` T6M R P> ؤJI ߩ`|b8Rʃ*-}TRB*L.8HJES'flp Zq=y#VC=κZؤuuLLBlN?t[-[eno_tk7qec;~+)l렱ˉm7k,f{[\劳Ņޖ7w~`e_Mb&gjVhcP95_]vMO{qKo1xųxW[xwoZ7pz4]I48-eK;wˢ޶l}A/o_fyn y"3yÑNv";H<P> ӇHo1|(%$NrB4v͝/;pn$ӝ0A03ST D4Il>PP8Gs'K!L.bVJZ"HH) bpc~;R1e!߰kvv3x\)HS7i,x^C]1Ri5/+g=8ƓJޛG JU ܿ-Y+d} K.`xȻu``d>G-T-!K$!lc>u_cNW0֩b6c %5gIT۲yb;_UPS|7͟;L!oɊ1ekd_oͬ{7^ޙt!bHS{6@@D<#Tp(4#pВ[7|R( t !T(@y>2~}cfI=NxfyɴVv*TR5[wߜ,$19m s;gz((0A.sv/xaUm/˟|--$.$J>'~WλNI#kӮygԮ\Q}~) ȅJx[EZ#)5,}_3 K)[H+% Arx'YK]MT[2t'W.·_~ ٚj@0 T s `\jc!pF'xÈ+$Tj_2ȂMjga`!<,L|B~NJy >#3R"#LM$*XcXkQNʯFq)gV*81A& a`ETONʏ֖_A4պ?-ړc6RS;C$I0S.=9R ;# Byp%c8ԼGCxvRS'?}qA^zd 8@`ޣu >?`eA)#B+? ǀy+ם^pʂTrEfI1u벍ɗ)gPI80y׭%iwt<5og 7omxp3αq3N;㌳N;u6I_.qikgشq̌7yK^ 1*g"Z܎]cW/ĩHZ%uR I]߿녕}WC V|zisAj43-.括 Fg l<ӏ5~}EWq`#%^z{՟ eLM1 =ݻ|Mo3Ϻ:v:Qc|Pݫ`z|1 Fw|/~ʯ\6jK0F[{#e{y:w0XN up녑X6}sZ6 c+% OӫG,߹4v@ 8녽/Ū3paZyI u^Olȉq]֐)!a^^hj&ՁA>'Ik+e86g~ &!@BAx6LIm2v֦d{xxBdd9LO6ǟ$rll܎Op6-{NL=<:] }!HkB|_! Z0`E.˱? x[ʟ(GЗBHbf@S]PVO`mxcd_NW#[)86m Tj8}l6Lb\NA FQ)$6ö{>Tp`:r7؜z5gu ?hO[_j^A#hYM9=kҕXPױhMgcN:`nd;Nt#;gsjts[ :!_ і}̩WlWRxeyqaZ8IȰE*Vr'бs"ȲEl%ZU2`'iE0ǵYe}ܴ:9Kl=;ff2N/hcG{QCFPt*^bfQE|k<CH5p :<޸Mw~w_>k`j0; oǞݿ܂.b˒.d%Jx!#Ԧ1up ƭm '2>s{{ϝu_\bEu QctETeC7NJy#'\&h=~lQEuYV'qhd Z#IsHbΧ{,\I?Rܒ9m_](1lw:B=X5 ɱ7$'+)'%?xhϾß[x.0ZyFPqu\Zo8d_ ]vlCmqa*ZgUkO1[h#8+=:b!=<ڂ rA6M ʆ&>]_}x8`|?[$' B;vh?ӓwA"2:6Bb!G?y)ќ~C"Uvl|3za!<:(I 0=]}y)f~3A$rTcT# ݍ (1A)J5y|S=oJv ;+Rvl|J |A(`lEѣ:&{95t1; $d{gB[hkv3L&f4Yf~Xef2vckv3( s2bw,1s&BK/3hw$(Lw yzYQm~bsBO*ǘN~Xt )_˄sog=o-{P pV'Ⱦkftn??]V쏫u]ZxfONGkYNPh .<\,H0 A"+B!B !RHHbsd 03t,i+e/X`j#ðI>LUspU?}Sa0҂l?=Ak=+.(]W%gP*Ijh{.83eW+׽&_'>f2 -pU8 %K%Q受=, :ޟ'M0TM`5]T_#~ǥЇ^_<aѕ<] l#!L̡/!Y9!ȕJ%qpϳg }l,j2p5r8D*-mQ&n~?u]/<zJw`ZڑCIkQZ Ek_7?1(Ly6K =76YCF"lmQL-NOrD}?PQg_X8NfBhV >0C$`A(A켬J$x/N%cu$"2dp>0TA+KX H"pL.m. ~kC*tr~$3t@ ~6Et T5$JCBOBAO`Z}Kh#/凭e Ǟ߿X_&]:$+s%oߵ9T[U>VVʪolVΡU;\O7#C+▖*psY)?7_#1c~k}Ob36wicvZX{PTmCzm_gwX:tgQw P;qϝD~y_eLqoz6C90j,︻K9Aָ^߾w{eZ$< BqY:U%m~' kYGo45q>k<ΙE> =TVgzG6m:&~Vkp/Ц_z g]lj8ĉ7Bׯ}dhj?v&k[j nxtB ڳֶ<24sj5륈ręm r?#p!89NC`n¡VWo}Eszx;ywG`ΝI3;.3.Yw.,WoRG.{\Fµ/=;ɢnB:$%sg"Q~Q=?19N\sv-F: ADyQ]vZH32|^GG bdgw.K"!=A*9 L4s?+<[lk&qH)0wNMud> 3[>]|߇o'Ñם?%eA$5"tfSv 3NJG?|A=!|3< )%44Joj]OⓌ;Vs+Ǿ]ld@uvf"` }:Etaen%lO|KU^6 L}gVG(E:9`=P*MC]X`F^5}9Wh$M|۶EJ/pzCl?4>%8 +B=T9Z!u|m{4Ip'W'g_b̖՚FX8P\4t?>֯_xv/8`BDqj mLz=kuVjݶQK%"/;-] OkiY' BoT׺3w[.%JJ "^:g\b- VZ"߳Sm6>=gx;Χ~鏿g[tݐ.P!TԪ? r٪E"~ƒC  ] l'ng`ie`06~@;ֹuKRC⋷m͓KC;w&%·_~??sܧ>3OtZȶ@qt g (ᦽ_|JWgSsu%ix\\>`I) ?^gtZﱇ>{nk߳HٓW]w I'="d=h03h$_oxogg٩XtqR "^?00UJjhg}c]x{'B. cG'= lCJA~ћ:{'eKmmHqB""?0ux7Qسj=gm%p/Fr@p =6+rBN9p򩗕]\* $Ƀ^F0i < زݑ"tJ5;T*$NG y5!(Ϸ@v˛[w4K$ n.Jə/plnIkj&n{bhlj?t',2 y'Z T-^pٺR ΥWJH!}1>9Uj 8‚5X3'8H3j2.uA)s6⪎&&N MRG9긥oEx CC m,XT"GqI#IbhasιFܴN$A\L m /E% Dp "ƦI c"c8Jt=h tu/oMP\ݖ "cX!184s H_Nm &?3̱ֆFC뎄Xx [渧36` TP1cH< C .| 3a0TēF<fgaw)DGǐڂGDJDzb+b `tC Vgoy)㣋Mlc=[V|w B8[AZ",I/ 5ԣ[v=?]w6S[ '8wq8VD6C=-{v=t6"aZoZsh-M#*R'woyqգ+VJRDFN}+@jj&{- ?2mB}$%1Sj۞ԩmJv#9H1$B^g$d <'|ٍ\JBB9@ N7DlԀT[kfeP t@([sM,s2M֠~K'I埐|YfkGi̩kM8IDD'$/OI ,9wd+E @CH2t#TS|ϗݾ9H) t~o;SvoQ-M@B/R(!JR !JB c`カU^nݙ9{,7H{^{w9sL%PJ2!v:d6ma#Vg0m.!6窗R)DÜ7l{K#T!׀8op?#\ю6s RW!uo<<aQS룵{߉ Pz'"=:| 1[b`˧+YӗSa6_H q܀Q) HQiX3F,ύ{=cep<ֶg"';<| 0AKΕM_^|⇄4 |khe[2qYG>%8Avh؎ܼ/#8-mm+7w~' 9?IILـI_%A>-+s&ȤFȸJxi3RϩDcCO~ X9Ӷ%6,=`hD fZ#`I>x1'կRbیcRE9@)mɷ46>5gҨǎ/j>-}<͞h9YAr P@rml=58ἼpQ`e&ǹ;~ BaA>2aKmm]O-(phUy 9> <2!=5ЌFJ0DqNdu`,KiO3#|˃1#Tƒ=]͝ Sk'0#2DF Ѯ΁@Tu`> s,hW#`$ֺ5a$]15t.gUqqf6JvD(Kk/hdgq0دoǙSAL;nR]~^ffWz?8tL!D&$)_c4hҞjkdLłK8gҰuC`L8BrɐA#8bz$ ^玼34l뼸? vt `14q`wD4m X2s2nV(H\ŃI73Dqvx>sR"0"eIEsƃzҹW/&`gwƏ. ݧO0[D" p(H[RO|+^4x{.)*)uvXۛݞr$`dlbKPrh҂_:*/i9lن(W$d* Pcco3ǨL^{,+e?DŒA y.!lnoi_=u__RTZ$?Pnf5G׭zlG#`K -<ۿg)=nL^ߘ'-,oYƯd NJ?z0g십0*"W/?Kmu7>XWmMzFJA]]흝'M1EH}:~kNhC}-?l@#p O`]rOa{9}OMmp%qF?W"_z":Tv Z68$pP_W`]O/~DA-'Y3CxHi?qI9#I!W FvVt_r‚yO b1f߲@Z󤓼-)g{WB ǜn,Vwu$"^Q2rb^*VsqA80@i` @INlW9#2,#h倓b9#J:/7F8 D`lIV_y 9')QS0Bk<σy ō ݝJzsw/FR^(>dLލXӯ &< xg4AEooX}w?O/y'/eYͼlu,骀B0.&y51ɸ!bIWقyc^uk>y;ig?[BAvх72ҫ{-Bkֆm-z#zta١_lݮ)-tNUO+gډa}}6NY6h㦮6m#v0௄ h\3z'v>轒&i{4oLQ\$n_百+2}TV`XQ;Hlx`fj0N+,-l=.1wm޺{3qZ)K9ua1W> G0vSf8r3e-c"FU[jz! ?60wDYȈ[0jmB,>ÉgؖqKJWiwr 0􅕛đ-}Կ._чc EHH͛BdN3H `?i|RSQYoZzfQ2S)@PcT^z]ڳ; 11| kaK!Jg.4Ġa1=WYՎ)as;-̩MI*<~ו(,J7 ,ĘYMøKco+7+OFwL $q1}Z%gPoлbc~?߽AzAvT, 9Iǧ>_3"dtB)9n<<#O>lR9hY|j;f/5eDNoޢE{vOVSQ45r"ݝ {ӇΩX2XytE}s+:b@EŌ}29' ^Q!d4gj**`53f{e.)w/|fy*12 |uC Js@kT=|rŻ hMEm-N:Cbch!Nn({ao^:VjO?Zn:2̙_mDPU0gEoqUޓ*o7>y嗫Weɤ?5l)O^?QQQav]tDĪv[f***xgg'+..ٳg_ϥtIӢPٳg{žn;Řwk"/>[D;P}H_?ٌ̞;P n $5M[554>/+=EfdZ2<9 :а<༺2Y^5}R %%2'yks6XO<wRf36`ߖ- \1g֣\6n"Y{+N/#+:a MXxk%v ŇcNgJY}[!;_gz~#ՅJ@̘1clPb&8IOWn|鴲V7cF̐mhC&]3ܺu5ͤ6o7 s[<7g1A17]7KqmYJ-,U .1FW?@5Rs]&>w̘#s'L, }zgںW/ੇ*^8{ޟ/, g_zAؓpOv[n`̬?dvA.ea>״WwjGr1Vx c! a1+>[]<1jbj#z\+gq>šDLf8j"7^|O 6-`&ދx$}8 ~# NɱBd^,kt]wRs9cZ S*Y236f?.m_J{ΑPCq'rVP?>G]2Hr؊ݾi{ <3222UVV;;g^SS3.//ob,=7k***$/Tƈ+Hf"JppS-> pvsҢhGG"3+ 8S}}_x뭱A8.3'Kv M4?ִtm`?E.`h\q{{1~POfL~JT83#zS[A_q{fqdF8+?J'6d3[rzKq=`F{ڌ &լ$rX<^0=ֽ#TpXNMXs+WYٳ3&/fed㏇hE+J A!( W+ c29[}{cc :V-zyԔSܐ:;b]FJb?1 [|NiiVn~sVFxa iM&O:~ok9~b~qm[6Jj_ 2dvZ6IwΥ8;6xQS P,mEߟhntaBB}Z/Gy "g{ Ι7W i{&̃OrꂙKFg0ovө6U_r $բ"ƾ9LXd2֫ԫ6&)*Mb<wCG۶O$Lߵc3~p%뺺sjjXee~[.(2SB$ A1;mgœSL{sS:<C-b:XSS#*׭9Yy*q,q;y8VG4v1o9ʛcJr]2Ui_t^gU~snvs87b8WB`.ikLvJ/555B[sss/6mC0r$aJ)8z{{yf~~ q &A/|>{2m19K $rslDXYr1ON+))#++X˲,qYv.x{'T9 ǫHMI֤?=xU_h =u*ܰy995VlilR0um6l\|л[wCے|OWW[{Hr#6O>,giycȒsΆœqOx@, ! X]{wOrzMGX[[9IeeQ"V63.sYd[( . `3aƌ{wН3"߶'hOR6}qڐue9ڃ,6H9G$w񚕀7r4f~NB`[]_SZ`O*=IvOOdf\183Y"HN%bZ4!(pQĘ4g}!2JPhlEOe\C{\17t^Z[ p> XK׻ 2y r*WIc'}wk۟3.;m笺^5f^FI49WB?nrg]OZwQ ch҆kbe##Ƕ3}ƛ|Wf'Ĕq $$ D{4kU/Z&]P29[]E¶]+qo9k˖_7Lj\iP:0zT s UY93 |^ۥ9S"΀֪E,6aoy =*hay x0nYA4uEeZQS7R @1$xڅau-a rrmw#7oJq 4a 02s0sgC[[WwvO!/X'c/-ZuS {'[kkeèPMŎv{/gO??@!(|JoW&ѣegm( s5`3H!9Tru4Zk~fQd{@i# q69k'}/ Y~MNN5٣Fg& 1mpc~y}y?ac:yYI]&e 4俻}1SS{]"F82y 51M^Bk{}*5e*p!2kdd@ q^y [6eeͼfn_̞}a<T1ce&BDNOΦI',l}E÷wmb1sa(5NG 'bߚgV_.Af4 x0fi*̔ζϪ`K$ iu`|&lH^oSۺm]y%1PivI{6cGb2v n (*oo3'| Z6p}$eŎ/L5\[ZQQ#P8ӎV*{Bi39ݺ}-:d"ggY+V8 J$L(;e8#- RV H01hqaƌww]hee{uuYKxZf-)yF d;҅R2ca'H$ª7.<3trOW gH17R6pA3(cH3`DtFr"}rWjyi_d+z[1Wb0Wkhc&Z/QSS?KJwK#`YQh`@^22` 8MMp5s'Xq~4:ٟ|mȲ:pܲ=>Q&BdK hm{%"))h9~<1 sȞ0Q$XHCJ+{s&r;O#&Ĉ5a@xIbvg3^|6,`1/Ș@TV2OTM*: *Av*^h׆ xy ZoY1f{챫NzlaaL&tti8vQQ7eʔŏ?Oc&L.eܾ͊d &#`s&E105s{%q3 >(af!M&+x[IKK.=hιʲ,B `)k } ~邢k&## B̲,ض )mQSL9zҥ'4yH"f/0yfg1Lü*U@&C)_B1vlAv016DR1EdǵqgCMɋ6ͽpfFи1" H0tRvV0c؂+Ԅ3p 2t1iu^;{a炡߀ Y?w cxy%M=ƄK<3>=ײ`dpniS¡>\Օp:<%=eJ!4\Aؠ,Jםoȧ g@WG?PbX,r~t\Cw"pw%%cJdp>X.#Y[Q %X*v&Կ2z׬B.OG7mGצM1fdbЉӞG dgp &K-R 0䡬 À]6DZZLdȑ#Kp5`o99E8FyMMM򺢢"=-b}IHIÌXk Ƙ(**2 />sBDĤ䐂A BA m8m?7g`>'eEٚ&7/$Oݒsaqq1ƍD˲ZO<9}ӦM {m&Gp8 "1SNN΅^NI1#Xi˲£Fƍ~!஻op8p,%%%19jkk?g}œ%"o+V1% )+&od6 'p\\Wn#d ;f  K&9d\=Uh"1fV&L(ݭȶ팂Bܶ!Յ@v6joGfaPF)Ǵ7:OR cRoG^z:>*eEţ.->+q\o9O$\ҽܵm֤mL)5iC̗RAS J!]-,%VXn3=3"O{dbF0?3; ~C`+K9KHO_| P^x‰vǣ1+c›?TEDې~љd˗_)9g)Ku5ݳhz`%'22=Y+DgRcpݶ9nkxOmے,ϨC|%ct=zsNYWkC[No XJkIc8icœ}ĉ+mkHK xD&$>0Lx6,]/N3ae @`@a8(OLG9>#f41)Duz/;2yRfË, 59S87S߾2ok?`-Gt)X; `#" Aa%GӳB8 !/O-"J=o|>pQ 0&66E(Ey "T Lo/A 91ƐŘBv80TwE#1g QVV4`ٜs tv@DؾaZa%`A@ {dJO?Cc0~xۃdv$DXc6ƯST"p;ڟIO *\2}!OR8's~S}Erhp1cJ)yBJ9H(5 wiL(I&m`\4qL 0P^fc3w7.eF^h-ɬnz#ȉ;$g;#Lz6)…_SNu]S,9 NÈbT]]_Cp[[["x 7ѯ8CQTTqo~uuuHGc xSN^x***QQP`Y JHJ*&VVV,[>PB5+\t`.^Q=0BqD&cǡ 293 "wp|8 !(bȔ}mmSWYeթcx=}ߏOc^2cVzޤ)rȨWUǗW6Ҏo`m L!Q87O CÌH opeߚB2]T]]m} ,! ̙V/( XxuX̩ S=e| )27?t)2CQT|$f]>dQf~ȓjؔi@āEAmVFfQ![S8cѿn|RI!Nw 瞌U2Օ̳s 1`)X:n)mEρicL&"KʙRpܘ-IcbYBd(cȏvcpxe``W"zkLby & u oHE_s`Xc i:ͬ*n"2`BbЀ ND/Ȉ)F8سɱgo3l󖍑{TBk 9K;J J"שS_L@NUt,,̙\bE~@#&o[5MmW*~Bҟ I1F82=oQR68t X ahjx8n4^wY`ҘREň.0ZVD>cefB0@w71eg(0@ۧ+Q Ba*ŠT'MF2&Yd1i`1\9"H)@k6 3 V pahX0P;)''Fk*:F)eR&=}^ho1-0>lN1_8g` qxN0Cxɣ[@Nw߀Htڭ'\sJ{O>'c<ظq#[h0F:F1Ƙ֚Y(##c3<Ö-[ƦLKD۶L6?RUVV&֯_?x1|ᇐRBJ<Xj 7˲i&dfծ0!ƦMp衇t7co ^ q$$oVP##Bh,hcr@Hq.lߔ^37gfI t` B0?}7 "#wR xFtҁx Ҷa\q @,ISf`xE@.SjUS:r'ORHd^yW}z}$! WVޕ[Lpb S .mrc>++ŕWYa+$ .pgxP 0 2̔@Y,Xyy>=8>Ղ%m g+K|)_PCH*낂A<^, +03PSn&%p"@w LZ`i!!0~j| _g#7z`LN8@q},effz˲x,zzz!FbͱXls4]?44~}}}w^wa,ز,BVVV.<2gA P'āN)řB0zcqqCu8`,˂֚c 6l# cZBtuu;D]]ݰxd[زe ;#\c̰Ԅ͛7# a9眃:oܸɳd>GjSi.5L /IqYY βo8,؎N0˃mcܷyRN BZ6@`,O̬/ł!puw|uls'Mnî}_K+- ̒kWiR#%`X¶`$@ TguNFArAvT27<3`,32'VA G~|7M-((9#~[A2i/F2Ʒn}f5LJWPM,=в ./1Fڠeu(55učzᦎ*\Rf(̧?jiٚ~"MZ˷;FJ#Uojv:h `li26cMҳJIخ%^~;eȟ_bZoe#--18镡a9%3N'i]YrǧMC1L:U}2fcWd>ʶFGRQORzHiwmM|[`ؑsl 9s+o=0S1Z0==px,YvmcDDR5v [)geaUp`)0E `p ,h1h2HjjipwަPF t0rO) `BxNtd ] c`0 ۶ciH3+[oܺےvr'N;czi)&N^SS!\sFW;eOwDQh16"=ʼ|YZȈ@+=vnY`A̒;nUό%l%a$Hؖ}g>ffLD1O+@G"dnHё;DӰĜT>r23aykAww7QxƤ~ԢnO`--?N0vL@ܙcIDVvP:i\ҫGGUjOs{Lk1>R݃qabHrFȘlU_(uiR&6d9-CRޠ]V 9[^V&8]1j$3O1au;6dbqee<_J|fn19l[5;7~|ڴZrX:5gCZRk@\kd2i/1`&4)CR MҺXɉjّ|ɧzz7s/M& H90pqSp<&˔vG"b-O4vuHcD֤&xKh$H$±~CmXƐ\?q}L$0Ngsc]9RcPY 5o|E9͌'gd(B2\1y䎵kuuu$+XcLK&ڵk)SlO&˃ p矯 pa<1DIWPΫ[Hjke8c)J HO?- uVVV"#H裏F0N&L&W3ϤI&X,SSOvJKtlD"ܶ[Ȃ=uTѰwo׶mN @ )p1i3L Oian@OoqAQm m\\cX N,- JJ+c%ݮNDnۺq !;0rD;;;4ijoB%0J! !$eòmx8Vdqb|= #-[o8]G'6ckO'Պ1FV3b3XZ` -1>}_ &@3$dafwR55p-!bk9z{da;Z\Qz,0TJiV~7 \?dlʉzqzqٔqO*9alb(*>b_5&j  duzF=wMM_AB-) <6ywNf,!xnq1'N@XS^{շSh OmsɘL4Hh6i,ىv Ǵd _mUڀ5kj`R0>W1 (E$:۶}"Ub{R&; {FH))[[fYQ{#/_Bc-`1&1:I I}6wIN'*ׯw2rK(p=i͌|UsѦ+l&/oJjOM#Og ׆JylkcN]!fVzqYN58 ~L\S/8]&QPAZv{mm-ߢUC &Ci!8pȬL&]ܽI"; N-r]t Cm>;p_P[QQ#zuj_ v|J: R,R _s>MR>ƑAG Xj `1yDĺLyyb%v3)fR11UWWI:ʖZ ;qvx,7,iwTta@!1u8t6 K Y,)Y2Fhww'wr-w~_! {rcqZյ|DpM7aҤIPJL%O~E̙f͚5}~ww/YDdsK,xOO裏bwF/ұ~ӮYg_`^;0Op\s¥ 1,o @G3If`ڍZ^Y]P\,sJJ@f&((@FA9,.Ffa!P@@ 3\(ׅHBJ 1*o]@g[l=[Z)u 'Q{/<~׵^x{Ji ψe}=-[ZN>r 9cLs{,w`H _,NLO-IJwyNxA?h2B2zln3P>vǏ_c30s ߢ':h/=bmiӄ>z-- k̘'JKYaY&C Fpb^=^WVi"ou;21 yf40^5nI?xΦͭ^25LJ@; ֻ}caȿgO0f5.lh#a]egRcPD{Dzy߱jXSD߫njJx(ѥ}ZC QH_t憍W\iS7<1u5cl ƃQOeHHm1&[]q.%U^S2'IN;;LѐN:`_a%B^Pp_Ί_C!PV^P+ѣ}Qd5gvvN{5Zeq4<L+>mi'U2~/=y ii[ƽe>k+C)9]];; hƆ|,.dgI`UFey˷Ӝ5 'J2Q1$4P ДF`($[ݡmۼoҭ+kZ:{ѯ51O'ObvF祁c,k͹6 aH @HtJIDATc-kv;l.U@U%O Yjޡ4Af+ӿ&Ln'Nvzhy瀛66甋.* 2$|n}[g,-&L8Y[Ssn}5b.R>DJI (HtUohxd4 lw$Yy~gֺ` ?O/68~Řh֧vZ}!vaMȃRkC /gy&Zu}Wv]Wig.B}.\x]]kR#R'n;AxӼY!l~0]\R=NZWW=a 1wԗd<`s==1~QĴ~ O⊅Mm I.ezslh&HAlO*=NLxk-ͭݖSJ[U&ՔIguã5 43x3Fc(E` @E~$_ks:ma1_,N䜵%^} 5Vueyv)ڻ)(-lnqA -P %6, [?jo<"|EH0fk< pNJ`۶OkLypr pWe(+4-dK!;v,cnNڊrKokiIuYssHH87#c+~2!:>{ejڄ~gs#€TGV] I8-ZY ]G^Q[QR4&71,UwZ Ƭ&׽"]㎤p7$?4 qΊIJ759K?倧1lQm3&=oM/߅@L<Ŵ1鄦wνRNIc"ꎎ@65"V1^ 7`wn@E_4555nvC[)*FѱKLo~:0!?%ׇ":8{x}WeWW0Bmuo +ń0۳MH`D.,i"yAZA{8`ou]7Ŷx5+0ƈA4Ŷ9ؼysÎ>0\xta1YwMPukcɤӆفN_ {{QCCàeYyu]2B{ڵnٲz"D7o|u>mN1P[{^Uj3劈?\%K\q#Ǐ"??_?^y+'pBkSSMޢ>u".T+TԈ;"c/ݞdoo_-/x-$5$v|a[Ա>FnϮN .kkjl x۶li Iœp8̂YY-hj@w6h7:mW-ށ:G|:?ۼ)8w]ϸGd+3;] MC1xBuF%IР6;DmtjkwBE ֫w D!-Εc!@ X{ۍz۶TԈݕlՊ*jı/ݏ~qm<&Bɘ:Φ95*_BSjcTSDhah#=I{%&sgn|\f,ӫ q8l\Ū]ZqAך⼂ust+D]?Ťk @2hլTTko'gy. 4$s gLek{TTʽ/r:UWyWM=O[0_BLѺ5fpԔ)%c'oM&˘dW' 0FLBCx#[sƤ%E<GkWc!kQY_='~{\f ڊ9fo$E"![ ֌ěRf[]%Uҷ0\U6;_Ω)`h\WЩ1_zr 34cL1_c٘HzncjQ73.ol| @phx_*+u]$"(ϒ‰X ;aZ˦]CC߯ycybK&]. %@Jb/\{8at8%3$B#m[DK_~9 N;vx}{_c>3 ~ Ѳ#w^h\+ٵrp8``SNY}X^3)x?)g3Wfs{J~5oYUKglԗ9!g>^}-ϟyv,:0d#zb>K?ΫjjjDee~fϜ$)tg'[]8ڷdy9S~3yqf\dʶ:Y^^]eI٠#Ě'YVD^JC$Xu5}ron.e_;:- W0I'>n6; `ᬶr/c!}#00b֘̅&iw!w1h!>'~+ Ӵ[n%w_R}6H$zZƻ%ψÌ)ŀfCQ-8rpt8icݩw8#ݴM{s}YWWϙ3ŋ*j9faõ_WfQiFjt m 0d}e3@IɷF[#vλqii|1 ĉ +2=J9J]rAC#@VkE%%S|JD[fd꺺~}^c㟀cs*) (I JcŤֵijZ5b q_X99c-oཪFeg/]|8j.ųF?z:w)$VsJ\z'ъ|w\Z!D_BWXv,VQ[k+k$WT]ZM vӧrgTT+~OMD*3^!P;J|Y]Q Q]Q5حMUTT]TTT]\ Dn)*J- =m_0R rV;A/ϝ;?Ǧ1q6T[>;{S_R2$Нׯ_Z7eԨE @Fԣׯߒj2: fM z>%5#uVk=ØǭmV,0+l^Ϊc=lv|;&*""vQG7|s~ ?}i`}zB1$g=!pl-gП]\8_~uqoQF\8Lǜ}#(!^]Ud-/֌1˗/6_C"],4{])^p751wCtF f~証":m9*x減b_J OGEs2n-vJ «QmvΪ'~ 9VvZqSyip;w()@ Rvn#%?C0qRjڵ>}B2 3f F\G9yݺ/t? ij\߾׏ܣM) DP[˱@Wm-ρ{|(pAز-NǮ qm_ 8si7 tm3Ʀ& Op{،eDWzs{2yI7>+}Ҷ9=#^1g\WĀX ^lBYgoU[bH{b1S2 }ۼ?6}~d[|~npf1S[ӟ[F"~ʕc zu`jڲ /W_}}mF5y oՕo)Y`4`Cy&g81z55b>[ܲGq˚+5 %-P^$=wGkYU&!g{4̸ P>H0Sv'\BO'p~1"⵵0~D-ZvZ{ܹի"xoΜ9cr$E͞)+/pnv^0G^R!UǯUZ}=G厶oeX ! K ;m_9,ɝX}SNA";G8 Aݹo|W=TVBtnلqs {Woug|og\;7Oݔ87/C!~}A7,HᯅlB='/kם?\ɝS,u^̵I a=gT_gxյg4f[r\I4\!L !H'$J(%7)@IBnwɲz9uf1r~jұzu'VZu?J)8D"1` d۷#bf,/L"\Wšw]ƵtyyɤqIa.miS o!=0Ǵi$W\SeĖ>nj0R)Hcbsrr2BJ/ϙ?a*a}4ck9m=-- )~0=+Ǡ!f" p'.[01YyI Ɖs%&7|sdžP}E?}]*+ RPY)>"7BK,Q7UV()tKewv*I^0I%G~VWqʔE(Dk󑻌x>{:&}_ ;v<:4_ 6T*\~x*++\ ;m!q\eØ/o9Oႆ+~ )bX02?:y= ,EF!F ^A-I@_hݱmUw۶K~R``\t-Pryw߮?\s-C]`;B5]P:fTsadiH-U7Eپ(I\bBrgeYΝPnCJ8xo k׮}! :N\|EӦM{q˖-OН=|  [74us6GS++-Ϟ8:ޘ` 0=$yo#oyi>}X#,)Rfp5Zb͛v&O=mז(׎책&70g)C}p?Rpa% T ˡ%6pڧ60y١GaP0-c}N>;xc;zY`Jj "IIؙYtaf*Ү뒔˥bDt-[u5`P/؀2L.WD1+ ƅQ=Gǘ GԚ4s$6%w]a=CjX}]dF~DѤ*`_yyN%s.˧4s҃[3xMcZq8mC  3{ c9'ߛ6m*Zl?圏={҂kڵ~lĉo >\l۶m93Ϛ5ka***z2π?)0 ²|Y aq=׳spbLqƆbh PJu4lG!u>e)Ou 4l%1׈1 cTߎщ SS&Y#$3dkPJPoV"1ƸE1ֆiqe [dnٷ͘Ք"߆EF1\Pڑж$.#HVns+co&rlò`& i2ttucb`CYR#f(""f%6;~#G?++0l0,4Y4MiYav_48*((ǑRJ#18I))/?z Y*2O0ΔiJf/1l %MGtA>#G+R~8bHZrݞ ƍe>)5t.[JL0,W$glk*U=.?4cLR]U 1J!X*QǀNn{0wADdas*5O6T75'L"ə Sg k?؜LLy7הieGPJbS>v7cW~fI']+D4r$x[{ϽkNk̹3 6C^$] _oE^2gN''OW sO)Y&RmQ%*.F85 n'; ՟yeϪ2vdr8Ӗ>0`ZwZ=?yy06'ds 駟Yky0Msƍp;X^D$]'sB87Kމ m}vR137cYo*j^b\=,F ow>?`YxfS3A]W?.aR ' յy}v?Қ0n2mm 2,% Ca,} >qPK:L#K{lbşF)=KFpO'b۶7?|=CŮo?Wmdž ߸tdb@79'N\ZimذaOW- Pf,YpØbP]r<#j9Y Ƙjnn~hZ2||ݺu3曳g~vǎ-m'N%db1xh]]]`e˖>wz-r3n(Ա&gĔҐ1C:Z  -*R0&H5֚+aKθ"rAMv)RJ+0cI` Jȏmy@1bJ`D 41)t]##Y\_ Gk)əf ̀Kr0#?to#>(F$AK ( hͤ&SZg \v "naCf')F 73\rp_iq*3`J S:)fhx]C<v0 eAܺ[~ݜ7T)c&){ƘADҲ|0n3 õ,ضm2W+fJ)3뒑#GFXkk ۂ?* %!Lepp!m/iMFVܬGjkSІIAl!IvN2.4+)šQRm:ch$S`R)/,IWBUUjh8'L">sԏF "#<,߾ Y7}W ab|˖ cC2  M^Ai c,-m|׽rdD$H6l؉tf5q--ʽK10Y=D{wZ)O./8[R (YSy0vNFwB+afp+`9с[њ:HjVjR鿯Xvͫ5=<zi\(PMߏ*YHp /t{7ř6-kA4/L+.\R 3erk7v5า+uuuGԤ,X,0}3&Ly`LqYǶzN'-LıX#s_ S䔉:SzZfsXi.#" Duϗy$5\7g 93, #@$zUO~F?b}t>JKK׏=dRJ5z ;<P(bRJbP(,1ݰXkk\10ɐcLHG4iRj=0,^#E {M&f03@PB M W.\I'W#NJse64q4 @LyYVD@^u9AU WI BȢlLϧ,aq]2cy.9;\r!A‹K*) LR>H)tRIx 8PJ[ JRJhoRk9/m{+cYl?4$C{6SpDPW wY SqU:B Z@汊eÎy?8?ݱ^oyyp D :Sz7Cse+(Iptt"̄~a.)'; C$=/DχnFe n>JL2cǢ~FX[tfc F` 4 1KpJQ,uuhX~ (f" y* A0!dP iel݉蜠Ov:KE5G؎Y\| ImǝY*Kt۷׀*[BSK=V%;cf\&ej 9]ͪ/Z>z}~gof 2R+eGۚX+67gʑcbtk^];c|8ƧT7M~Zn!?J}KJyBoo}}}XUJ ۶1|%A& qA^)+]Q,Czx,$Z8RAWhذ/5Pp ڏmXPWo$ 7g͑I Fȟu 7xv HJ-=vQI%!@aOy≷Zv^^䒒"]g瘜1c':N }>)A<[^>vZ2;1 ?bCË˶EL dtjg&)k0,ͣr.F{7nB ne!ebe!ko*қ^n05⺺ѬpB#LfHrqyҥKo*..~p̘1wۅ:5Z{iq'c󲲲?^z@2!|" FJz\LfH{|#pX"\WC:Tp47X0-djFA{K 7\ELK D#&AZj#ΠY&唠53r,x>C)9* ,(ęA#4 ^ d,b\R3A7IKhH"H"2 s<38C[|fiP7a{;|B%;<f~B˫B%Llg DDw>A:+4>1~X0l7AtWN[۳lD::+;[>WwrBJi<*p}[RFWeg)pL9 Y&RМspWJqՀV(!mHS *" 7e*|Y2`5 u2y,C{64IlƦ&}:'r\gj|b-̘3~P9 y/A|jR`F} ˌQs\G"} 7M&$VuӮdN1?f<~ޒ[\xĴ9>@).IKVmge V^ 1$.~b 5kSTmH$B蜜2Q,;;[l1/"okDZuYdnu0ml& Zg #4vxI3Gr0k 3~5/ol ?[q{GD-c {s4kq0RR%\ HIVu`I0S\2|r([lmuuW̓/|1Kx2L息'wBa 3 |>, ΜcvoܱK&ϔeYp|VK < wQRgo=h|4a kq{t{V*,V4upHiaɄ'+[!i6,&̏K]}kPKx۶mO>d<PHI)9`m&L0A1O> te\+~`$vJ261(0p"0f8Z1E=0i)2ĔR0 ɒ<m2N]K3s2KM&r(L20AA -a fM|A0 D4H `ӟw$Z-Wlea D$B3f粧Ǎ`BP3@97w8Κd?"MMAfh *(aZ G` \)L@JAf/&tAa&6dEa|Ø, p"ͼ GC@XkIk3קx8 "`|x9="CiD?ދ,"XH|BÇcθPDH98 U.hM??E"t=ԉ9OV XY?UGNwp׃s.1c8J g*ў[~v %ssU9dTPp|\ wk~Bs昬YmdV'uj4A( ^R***w< ^900"RaP0J)MD"LqK.첅>&3U3*qZoc#1"a?ւ4 z}' Mb5 wsdehoq)n&-Vô;ZAzm/,lXN1Җ0.!IpW!dImҳ[٩QK>ixwxWW'I͙YL4] o^pd`8@}WW͹.܋Q_PUFcMjl4)nϩm}5`dGzጃ4,( gM4`mOgٿc8z#Ge!tJZ&7,Àaps^AyVZ, Wj8ҖhX;7r\a9uuu}GT~ _*ԩT ׯN8"0dml)y` Z{)ǞGTg kM$LƤ26c@2El ߛi x&GCP빟$g&cE1lN&ddKIDb!830Ҕy G*hW4a%]D쨘r;7!I.}&g@y|oeAyN=WC`Ir7Y (c,Hk2@3f*BR!Rm;(a hg4saW0-(fLi^#L!yIgѩ'?Y$ℽE< sƌ>N]aߞ3ba -|;m{N9ocRUV{bFNK2Cg$8,57'۔ROrƔ 5<3c |i D6iTOgJ)8Ƅ cgA08CR D ˖?IߏT?1!,x7/EV5LGǂh?םJ=bt%X#~}V{D<$]iX#Fx67MˎȀS\_mnP DUZ_c/kjrP`MȺo6o>XpFj[jX}}+N$W`PX%c{zf$"溮*圿~uhѢ=.EΠ>Y6`}TqLv905 O@`9 08^q` ~ٶŠ= "ӜL$,.0;_ZvMcM&|8.?!n%3) $IaJ]9>degλ#7'{h@4 !<tGk9SӦ?l '{Ne vF; j\Y58tZkA@s/1'䍻?7_yww۽`5)аqF\rz7T"d{z! $TḾ;[1Լ$XvfBe XeMVp ΔaKG|vςPSUvwc[[[dذa|""0XGGo}#P/nUe?bD-֊K Z3APscCR]RC)s/nU64y9Lv"H)u\ cO덴o=_ &IG/eS+ MZ rLgJTga}'PhTN X~sha+oqҚHHT,N{= |!8QZjbJ[Y\Q= iqnlM޼d۶:Jgkb}˗#;7)EV޵R"4yXw$m ՇZz` /B?a|-|dwnkOnk~x] #X4bS;5ʁMo]0l[I.<@% bD0˴bJe@k_qZ2Y\shƁ7;;|4=ֶ=!)%,nwwd4{]= S۹.9{RLxU¹`{_ʫ!N68qn2L+sLr*0r]S;|ozzYT*@?wك5&͢ `K1F QDǎ5, \0H 2Op9HGR으_{։mI۱Dgq. o-l@#47v[ʜ1Ί&GZwĐƀBLPD{4[,ݓ!Ĕ:BVMf㙲ir4Etp*֭۞ZemҋzF[𑙓 O6!%*,^}s9\H*t&_Xt?^^~j\c˖3᭷wѢ=F烵c;+Cz:cq2ioLD - eː}wqǂ/!8K0[ |D^sr֩5Co3xv  LC@9'4*%2;Nkg*Uڶڝ~?2Rkq~DžCTWRru}}=1~288Heq0i{,^,˂R B9|>1005_~yptk1)֊@sey%+@4s hpbmtxf9=ANs*\G]&ʅ_zj/L8ww*X^d+ \X$R0 ΕbFv`K0ƘmʚဴJ rG,F8cǛ `d oFwY)ƿ!gO"?x 7 ;Bl6ٓsL-a,09 .>_%^4!4R D0׽2hCC/77ץY)ҖT<op8;dKɥ hEp] QVm߮{_2Lnw$vȼ0mzi[kj)7AP[lJi{=nrc[kjiM/0xb#^܋>{^UЎv\}#3CΟ3alFx}=v6i!fH%Wk8}\m_R&D߱>0[[[_r]w)c~%%ƌ1uݥ/! KRu2+Or\l]HT~O~> UP}11Mzm׎' 'oosT1ն֔PnY41##|>#RR阔2Wz|Ƶ[΀/l1Ǩt,)eEBԿ>p@^>^=Q" Cm8vK2zq3-9x7MDnȐ 3&:iVIr%\卝THJ GXi) =z2\z[F#kxAsDǖN-3K-BP$,QX^ OVVɮkl[sG<Ѻm:Mah>_9\e_K馛%as3vCdhɤhl0y>؉Dl@gϛq7ϥ(Cqnf*)߂YDžK/KC7ȗwuvQ3Vsm[8*F@OVTgqӰ3@)]B+ۏ=g!ln;.r-wg㳡㸐/6xQҼBu9v7]3bzeY7 !Rk@{@I]]]%K̮>[ZZXSIʸnߑ`{Vs? ~GQu]SIi#IݮWOsՄG&i0t;@N6 rwۣAxIZ%QnւVzfԀ0i'? 0}nգ^%3Iw "RJubӝ|- RL+Ip+>: ÎHd!A2 ap.G`x #VV6Qgm4^ o~!̔\q4s6RQ7N1ꘔ*m*$ia9aL:=`U!QJ>?|KxYDt(s·JO~y"j]Tmd3gu^@e}_8RH#w]Hp\"n?QFgx{>/m>J?ãT A9OѼ(_힝[޶D[co6h0}Ojc[TV_3D\꿕t#omNF5\`cc٦V,0M+<`ˀ )VEB C^ClۦT*5wKA`]-%R+ 26pd#8eLI(M( ?. 00gE ʽ˙Qh\ 81&O~#8[3WSrEպge-#!787 ?481`!]59@@*[*rҖkG/GN==Z7aAWݔJTbJh"Tdf8DWF砍|sFWԆՓy~c#cP3H4M` d:·p)ݽ{M6B0"(RJFukqzUSW#"{HƁ+߯a0I"^U5u^ bw6/&5 ˀ<xi HIv͔nP[UWq",mmJC}~Tb n?,7W5#68׿?0nmOt->-(ۗ{䝯?}p]Uuu953"{YvK``Fjǐpb t"kG[6oLjj`d( [)5Dszz4rցht(NbS gHZX7ZCi HaH_A^`R Νr LYi(Z+1+eb|mi4jq` ȕB3 q@2+w\] n$OE@pLfJ)tiֶ8uԓ~{"IŸSAv~3?w||_EϧW{ԟ=჎? 4î[ Ⱦ(f0ާd,CPڃj|PYiP@7tn" 3~!%J'Wʸ3ew绿`HSJ1)e1cWB&r MS8Mۀ0(%_+aS)^NO∹ObUs G^T0bdRH)GplI"34|8avarK疍(kܽGu"sάe*4@G[g+W/e#۶m[70g LJ'.t*Dt7u`ְF:٨DnQJuiXqVϒ#WlYʌD^ć]fnbБNp]>3%% zM+ )ݡI)@D?e϶> !ҮRp//D޼*53 kK'b}18Ninnuxߠ C!E*ӦM>s}}BeҨʇzے0L2ƙ83ZևW>X4*jh4\R@0Ss Dpa0sԣG^Jchz0cu]x0{80[:1`CPzԪJEroq w9fuOaZ*F{{C<381qGױOUW+oq~N tvt/, ~Se pVod](D;mo˲zm J!r; $}GxO{\D{z<80Ķ(6m 70BXtz!a77^o0xN<^7<^ֶ`JY/gS{UT Ϸ0\ҩk6duSdO濗̙cd~G> Z7ߚ;yr滃/"J ^۶JL&8 眧I\ Iie= YщTcDŠTWsxsx藰ssF.dKBJy̶\ H̼Ҁ: -t턭te^QշQ󧆬p+B7ABY+V|gƵǭZꁞ!v&z:|L[cD"L m'/RJ}auZJ)RJ|[hJg.p\mWvR SW H9r%:h_nna6Rfr6ݡL}91wXUV .ܳRm4RmMvvaE pIA_0\a05QOWx>UUMjis '.桜+[ܰ%Y7ʍ7R]@AG⦕7pz .Z?0tnBܘ|&DT ģjXbkpW0w=~M^?;!m 4rB˲.""^kkkiwݺ5byy8VCC>-vui9TzeR˃$ݦNn0b՟ hSLy׮gmR$"CctQ&^.=+U&sӿ6~y63pA? _XWW'L(bsHإv:χ _$ey+` o|!۷7>:zɒ~W;m{vknޱcC8${-`CpDS.> %:>t V }  L ` /`IJ(5G!4Sm:s&+ | #7aMޒvm+pzD C^WT5&/KlwiQ?1L6$d+[?KTMM&L7y0E x*Yk qf,Kĺ'SgYY:ӮϣGyq07I$F:H~[~F,qcCtw<ŷ?kQ.F?k0AL9c4( %,ro$R{TVn=8Ҧnɧw 8E"i$zi[N9?x{"cێ#-`u`6 $}N*46w>.plMH/^:Yr>؂CI8ۿ@,˜yk<.g X=t,[{uS``&|_w-[ܽ{\N쪝Z|?#iGJ4s1Ӂ4{;*"7=ۮoNV1444|4ͭtƌ?L/Df1`qRJtwwT*KKKEaa议N: xp7 g6 ʂC0e;/p8#5w^S|]<9y.uS--_XR ^0}]Ј890&kz]O 3ԡF]UJQ灰<$sp3av;ƥay-jz %{IY9Ҵ,낯a1fڶr[[ۥK@pZ@v˖^;61a9fkfg.C%p7,4)8 _m[WsxG*k?c5UZ)M"9 ɚH. Zy;v\*oxM&W8/(555g2!ᕋ&X<Y]Q ַJㆁ_x+7HyuB5 QcGoF>Q=J`j#ƻnHwp-uoOJ8B&`K8.(q("Hʎ8G7Մ fZ{w8f0]tF!Nv蓻Y0 ]28o|ub#lG^_K=dˇ>;zڬPzk%G|ؖ=MRsߦMٸ"}'*3MM#4|^$-Bp\{ŜyϾꪫB 2UÏ/2K&@uM"1&wi{#ѵE5Ň؊gm)Msǹ[v{ԔI>+THJV9Cu#ەLnNWxu'02"&ZmyQ"[vs/:;;`0hfJp&Nq񧙲ѣ]GjnĠW\K0oG#Zy&8,`x4@AͣpD?[>?P⌥x`γA7:l0@yk.\Mp-+ѭa~W,)S~D*)xbae߆ں%wy)so{a  ?oW.}ׇC fAa~vog &gΎF؟js=u;,zWӬWG}1o% 8³ֆ5X.{ioؘ?p{ㆩ;AQ2$xWN1c;@v]׿f͚>3!<$\dz?t%<&=kKA+3`_2apkڼێlX#_a~1*++k.**"uykkN<ě?+W~I&8 }O>uxWܬ~r)a+r33wX.ieq$=^ɊۇWwQ]ʖg&tNܴ~`p&vۇafFp9w#SRXہx _K 7Qvvt#n0NL PF~cwN8a/&^YVViYk!gİm۱/0Lo-=>fz5Z*23vnr.j͎JHDU8ĽSc^&{1G&@[T 'URսDʁo= TW'ؐ< 5)ơ\(@KGEǮ]@B{zQ"MpV[S, ^δؚرBN5dr%G@|1$:;s|7tw9?#"3gPA gFS]/R bLꤖO#&* LR=z@$^,ø<iNEUes\|Eӳxjʦ&DhT|>#Sn4RPTTt{mmqK1zCN8%|ηQ70`;cH {gG^ _z9?"SBΙ:~UYs&<:<[>ϲg)kAV㆖2=,ӻ҈ծ`IN&v.!ge( ;@Y*U) Я^|WqsL gҚB1sg,twt-۽o4  ,YbΙ3G~3۶7o~kUȪ2{VN6 w W6r8(F1Q7ӴUd!zH7TKhhh0eCC5Fbhooe޼ygnZlڴn_z_iii'F^]]me^gCzUY7eTTR׾g+upwjՊ'TV{0ף-2ԈT?Pꡖ\J`Q8m@eX"J}[(/UEw?TQ:}aLdBxM|>2>[Հo uaܙH\7{h=U^~x6O&ɫ6JaW_e˓;֬!X֛cZ#Ӟw;.K$ı%i X;D|}ٖ-KKƺ􈣋 x}䍻v-enu>I)8y(}qBPGg$MKo9J$uWNǻzBu+ʌEOo^`|0ܷe;qQu\?ƵG>? VŦ@.et[8 E"Ч=VgR* x,R)&\m-_\ph\~vNؙ v\#KZk#->ToKٴi Xm)fcܹ/4^7jԸE``Y¶-~s  (;FaӦM9WmX 2I f<{6[pL9L3㒡;@oߟffs1NZhuu0[`c!:p2/a;쒙_;=;1FOY`_SXCDu5' '6x lG{ɱ7c_@~t5N\r_NCFuusDĠU%i;M#]TZZza/`^f;Kc\`0RYu$7#x4GD\v//3ǜtT>~4чz k̘#-0xw jRq*}M옶p63;8e4~ӬOW=,M;2zxb`` Ө$?B  !???^XXx+h(/+>ׇM]wX:sA. #Cۘ[])\q3xvM p\K gD_2WXϬ1- mllFcǹ P]XAָivҲ#p*iHw'߲K:q|mw/h8ivd;6"ȫKA?ٖh#F@{{̶b؂4{ӓO#)ͫo__[X]]D_w(9ЫI 40_T2fYdwdt7O]IMoM犋gd&.,4888?^+@ #''獜^xᅍje8FOw8zljQZy c.R#O/ƍCQw 0PB=nbac(RjJ 8aͯ[B  7v;gw9`ݾCA a{ǁg]WGb͚F4s19̂p_!"g?cPH {J >]eUߦ?M]⹚{2FZ^t@TZ_=#?QԚPYiT55 蔎>:ztE#._ [vh>3f6\}ؿ t̙ۏӚ[8٧qΌA?5;gрG?yUWMbRwϞ={8sR7_?Lk 04l56;/w޺ژw!|6Yd'WĿ5@ jk""^_}\_WQ_ؾe_w}K_Xˑ*uk˸]Scd ;G|d23\w;7dh ;:;49>Sg'3:BRT)+F>2 HB.4 ᆰF/_z͆:g>D%jM6/:lrp8ȏ9&)~nDe"3y%`(ߝ3Rkj@#(e}ˇgJ3줻ػ0dAO?]RZZ:\)emmjj:זeͲ,˰m;xB SJ ~0?$gVr,).8mEN;w̾; oFTvv)Dg)gX+WJΗVSWI &\c%ɣqZ#[hB-|#őHd1uz([W䔌Cy8:9N*ێ_)6`IMKo^Qgf_ RS{cpZ"`Xg.Nrk9'q~i,`k0!;7Ϛ/~05>* 'j G,¯ּ9wjlD*viT87Wk:̏3R뗱ULyۯp<̼dv$rW15_CeبjU%B-0hJaA50Aəx7h# aKCcELlv׵ @Rc8"?xrv๩kkN%k\P)jAW5|;T/{'w={D%[[VkDJLGaPF8JhG:<9{0o XyyNbϞNV PݧS }}N6uVrw x^\^0bԽ]r[0}h47l7+gy=m'_VވߎqM$¶+?Ҙ&Q.N818E91<-oc.]v-1Yee8.Ŧ/3USӐSIyU (^y$+?Tm _q.}f8-ۋJ%c[ꙝӢd\k+P\e^sѴhwe|ߨfM#ʰ9xUUB_*PBL~kVn i0_nS6Lt K:kkYj=xس7,3` #&}kv'@@ԔMŠrpÙ_a#cyÆ {o30 > G)`۶N!)**RJm5kVs熁v'ԥlW\F=si{:{i4 eeǏWZu5c_< _,[ӧ}vǶm0 %osRӧO?O)1vbm0Pe?mʌs>竾J"UD*{H &P<G8 ~c,Vмƺӎ{Y}rkA}=0 7'1J̑ Cn/𳼢mC=ED%QM :0GL݆3}o@.F52ꦝ1_R,xuיV*U,:p~a84: *8}!Y=G|{Ǟq_~Nv;"s,CdZ>Akk&B;v\qOcwW}|W7CРg'6"96ל˱- v i|PNU{( ;ڍdKae=y_>aHΚؑȂL8N~5}m'8csدc{N8讫66kFV{G]Cvy`33rBޏ6w"J'4>G'N麮9 `BRJi۔3S4q***O?-ys@J >&3kq֬YC .4srrՀ `YCA i4Uaahwp5k%H''njsRZ۶m8}(i(..r̘1455-bhwqL `\8۱%i @ @'y޴yww"D=\ JEvW^llXT!g;ִ`"ncs ;?J3dI g1ZZZؾ's3_ •Z}u/8|Ռ't,Y! $a_ qM+\Xjo*+Uam綊 _2dL"ozY>ZN).wO}WTl}*˦e}ޝ_K-~vi$ YQC}-鈬/d^3hI9ZpCI-5!DPL9ZpQ= _8Y0ҿì=sq^ Ŷ>4/1'C 7H$"o{;JW$ r~v3)8J%;g@ JKr؝;VJD"HWVh0 !',O GC0 s~PJ#?\[7w "ּhs;W1gYk.X'߈UUU*@ p97~?, c>di>9#FUuO?㵵龐H|vO9L6֬  `Ӧճ5kd&/]|Fuu\r入eHX@}Q 7+0 'i #F y;r֬h׳#p]aǎH&QVV`0uGlՎ3%4*WR;ZxGڌ1.N d>? zj \E*XHLmuTs!r CR4Ck0) sd e}CbƟ G=_i2'Fz"W0$L*yh:g{>5-j׍mZEXw!Ĺq˥fib*9sL47QuqX󬠭 G`׎&r+ PZ*Jb`0m46Vy% )@@l X; DZ \u_5=x}b;VuL$X>'07KIʆ+To'#бrh}Rp\%Q`! qpmPQF?ÜE"ݳn Nӣ Q \U4"۟e@ %Tyy{DZ2:Eus9f dJ:6, M`[wuG:J%)F^e+`7lv1k4b&R8;bk``x[naQGn}2//68Һqu>WejjjxEEkllDII UTT Biw}dUUUrLzp7{ˡOspk=2=twUWxʺ4 R&@H|[uSO=5^(2e۶)'';[lFߠWc"++ RJ|spٛ_xGyPI{G| *+(bU&)) L׳NCQe$)wZ@^L`4Q)WO@xJO$} bp5ux?kV* ͹ Gz @5` ~Ǖw heg \^yuf(+2JmVJ< f(zܩ_^کo?.@prsw#Ѭ`Le\yLt06#%"rA 焠5@,*D2 bW 82Pf@`D@^>xo@մ/Gph@|⃜}vWV/-}tiĥ R[ablʲtKKvhbP@6 fk09'#2=wz;>K1r}]bw-Фf&5Yḓ.>_zfxox_go7j|O-1+.k|Zk]x8iLJiK@`taapkjD$Rnf_W 盛_ C@pCS랞H$ӭK7=D욚L)}̪B1MMLA{^̢D9;9aģԚKDAZU${zF ?m2/ q /PnĞxM?I|2kx` 0J` .s](}F#A@77[W*he+)M]>2Iww0,_+N@ KC~VԗKZnho>S)I&rsgC+KIВ&}'d=7 c VI +T {HE؞1UU2'̣ŔQ| [\r]1~`>FWh.[&ޝԪԮ.3},|>zΌ{oX[4eRjp1脍1MȤn[j&Aro>,>2V-w/=%/?0ߜ=YbDˆ|ϗonCՑЄ^8DZyG{Hf^GGouBLT$"zXUe4cJb m^ eS+s],߳jO~9fӂtH'3uiLӂ?"+4ܣ;utYŜ~?\j?Ihxd29{nf.q)eJm W$"v5לb'Z~$0cu݁T*h[ X >D"G@z&&@&@ֺ@6D$nO"xأ~[Tzըq1#0 a08GCjmh"zzqzo[':X >wsvVRC1Nf)B(C`)ǁT yY ?/ 555\LaaYZZ\e>OK)?vd50gpFcĤ (~|>.+--Eaaӓzתt1R g EL e;+VE`'kH* cJ˴VWO?NvHJ1blC0a0;`2 !K8;b't^0]'xX/M%1La,qY{WI}:wO٧j׮ZY:38 ﹰ¡3P߾mCzÊK'J&7Y%ޞ!O%c&];dՆD=0ΙCaABBY5G`c`A$Ծ)3ο/(VfY*4 # Y - Wbq Q`ۣnmm2rtPȑ%Rv74=JB3X3X3PX AQXPp2!8;}xQ a$#sTY e0e x2zz1׾k\IR-CpǏrko 6ٶwјX /mI;|}-ki3`ֈDC +?]}͈XYb%A|cKl-5A?Ӊs[Z8Y*B2([G '/`!m;ki+ōٺKB9>4$7?{泥QT݈r3c&pƓ>4iؗ\pKKQHǽ : == %KoَFreeYp]զ!kU-\ZWC][E[3iK(')Δ׍7Y\k?]z饋HR8Ob~s 3z.zz|{ەMouY3q3PUSxGy)fѹ̌sbʔ)x'׫-Κ5 f“O>Y]%;k{vȄ#O *J,5 pL@\=B>̑(PVV5Ր&cʬ'˯>Ν{z2|  5t F- HR@f}D;:cYf@Ѐ;lY֫===~MM%u[N٧ᒍ Dy+[j:B!f$?dEmFisYRH+f!2gE)-@ 5dY5Y"8vgGKkSN$ O?׋UqMZYpPH5^i_a`Up-h"l xRV'DjpmtR0DHϙk`kH#"_)$2P¾ʓ.ꆵK4 ܮo{Ԇ qY'syWh6j`嵵g4¶j1vmt̥`}6D"!y[OErTgSD(6P` t^AkS`#m=پ 'lYb"BB`8OD aj_A *E6D|m B|ggu7Oh!@;irT4z;Ekj#磊\P4j+NY px'={cV r "Jj=Aڳe!BJ)D#͜=b+L~ٳgRљGjs=c.]:$‘?}E5m<$HM`E+ F-#*OQvW\qŁPM7O4ư 8;?s9l9׿8 548Xb9pIj ԏ۞ώ;͊>qE~Z h-\tE^(ֶׅc /YiۡOfCñMbS|ˀ',BX<^#Ddcܸqp. "F Caa Ox8{n4Cμ n刔Gqc a Bkā |1..XJImYtt%LGNZ CTw}eNI<\(V 5 tDp|e B o\_(׀0\])00Ji?`;G:!2 lD,#ǒJ<v8l[|6 K&L>Ӄ+E'ĪDž =pUBZHxg|w{.>f}zaIw͓Z{o Y"*%(!ܨCHeYȾbx?}m$ż3C_ɕD +;$"I[G}%B1eKx&KmDՖtƶ!<ֈUc Ҩt ; ,@E_=۾oӷo#J-- }Jw!겲%iMb[>a}CAt{6XGx -:3dҴÒ^ʚwi!o7t:etE_4pfҲ(~ꫯQxou8>m} jc@DLJիW]0y_ `5Jc[J$H(iYGR!  ۶,M_joJ @ܱE ˪w}ffB  qB@CCNcMIɔz" )JKKo-Z4zphD4xvM_;7{[;tV{sq.ܾ]h4O0¸w< a83 l5xg/.e#! ’"Q*T:@K![O.s[.\L?LC$ + Ck6~+ί VS7@X4222I`l˖9ȷ*jjܗO:/3{Q_&eөm'M]pS0v"t! dru㨈pEs߾|/" AG92-I@AP av\5?Bd?`cA:au7o5\<t~/.~>ߩaGjD[b:GO> sBWa)v4e!2EשxAaE, @1Hh=/"RjЪ A&s5?"J`q(*p&6xʔr<ЕY]oJ~uk?|u}ecM24ϩdƑyȺ -*+lDÆ^l$8RajBiySj}͂{ҡ6B>ƓeW[Eh%iB l U:ux䅇'sW:jy*`L`v_g$E#c `f`Kڼh ^>|ݫAò;`&6K{|8l ۶ᡡsLqء.߾m1g6yϗR!k!=ϣ^ l@Pƍ/ӣNc۶mG|͆=l2B f( Q;LaB„, (b; J#eiY@~cNO0t*}Km͘3PlXD`KA4S_S[ĩS%Q%I&}0r{z{{2eJWWWI.]TlZ9mڴw6lT]]rqf־.NV6X͕ i߇D Qݐhj֊9sTrwpDQX&iKǂGv^0aGر&h,Dy]݌ҵ@x$ @0^_-(͉alV`  [edho V"b۲--2`$ɸ٬T |6< Qf(h t \p46#5+]*Ț$Lxf6pv c+p+ǂ䡵a6B !%'UV]O# ZzV#UaWBDp0j,d= 'pE9 =3|uO^e&@*YX6 8ℯM$U{\y56RjKվ1F<Ŏ+ŻI 5lޘ' 76JjڇVД 3a'l ѫ}9n87_;-]oilԚܣD:V"XÎ9Pypdv,t[a2,<\3h̥k\A NB2_fg$x:{"TW BwVdThhhJ:ےIBQ[cxxk"A@!6XҪ-Dcchmm̠FQhoxh'qFj 2AVL@x`70zd3:Ěs𳯶]yQr9sB1"|$ , /[Wv"J|.|>\羼FN )]+虥Kvl߶jڵ&^Q BZvBTo-R%*=KTBZZXWTz׮5;o[ҥCiPl] Kҭin w?dY˺ hUC1OlKp.+lؘif(Aee]dY6+/nȖ ڴn˝JR ֦1 ceQ(A6kǟw%URRo}>硡! axx>s3!aY-'w쀔p<,?<+>1B70Iq"MMMi> ?/.103}|gf>rw3 sommͧrʼ\.wy Rӌ15 ΝrB˲94O,߹Pb- 7`Z[[ iΜ9!' AEWx{YԦhtA=|fB24EqG/6{;nw"bfKB.Xu#VRx< 0@ 'F$XI bɒ%bѢEz7Wۻ=.qu\v -SBZGl=.RmoBX-5Ϲ\FEGzpUm] `4(gTFɭx><׆lqG\ %=P؉gSw[GngS:bHf =ƈ,BaybԦTFeȈ&zu-xڂ!hQ{8Okū-3gfOGG2@G~1_!چҀHfëDa xΜKvTaw9H^$440.6a|y`lFXrF^"&iGH9s..⻱[Un- 6d -wi\:ی_N;CA X)xRm XGq7[ Zm8-fQTK ϗE('!==֦,hWͅQiOú؀sJ&] -iHwU>u_=s}uS'NλyN (v&drG֍+^z~?'ȴ`9ݐ"I/ `, X(!)H1*Hq _mfX PtMxWq9lbyLO0!I&p G\c0 #D KA̐W6Apɻ6fϣ   [L0.^800znflH$D!T,?Ϟ8ƌSq-\^{Љ'~̌!lڴwT)d:*.m E"f6EȂ=h"L&ߗpnPG4]\.t: 2pϥ ~7v=!k~ygY "b5֑eS2[We4P]6HLlv0 W\;'(1|t<{@gq5ljcόcD,2@;ACPYtT!|)8ma ftt`Mܰd +E:Ѩ2Jk7s('!wm)  hS=ƫ K l4"8yPz佈99鯉\lϔ?CLX=x'(?etՔP:nD+@M\٥8[d#(u :;ߙ ̠Q%l*s2skGݽ9XIcl;2J(hNv@$&E=##?>Om[d3I Uft0%@Fq*aZ[`>F{yy›\S}!Ŋ &$Dͭ[B=oy'|׾~[.RQ㣯~nJibFC&Y JH~nf?i0tU#Rq  k]rP^)H T85dm1kR=8= 3 I!Ԇ I#>}{!bQqy:Y~B7 a_- |}L&_ksToM&">C>vR,;M.[hѢ9/Bi7#WS1Al+HDJZ䃺mm4tP4ƑԑX\v"fxxxo ZwBqCjY>dJfx}vlOo)+ Z+ma44!'i F( >X)fK;ۓ_*j䗆X6VY`Y5z#OVg?ɒ1%wr"yNIvOP; . 6BX n;: '-dfY/0xK#Jڱ*K7=s-FB) .kߓz)84zKԔE &^7 @8k[[.>hfpIewݵ6Y3X0(M"k ? YIX&Kl35\ް%0lք'"~>000aT.g [t?Bܣ D|ҥopQ8[Θwߺ񑃣4F <=$lBqʥ 6z 'Ɂc;%J)-.I l A&v$/e~ja>$LK#dH˜;< x}W6B뺱ur@O "JLF|4{C\?d+n35|_1 $H IN8X4ʩ"W7 &VI #p=@ך9M*1WfۆV_Wwo=>k~/?b-ߓ/(h#A4F?mx:oXiM-HkdPuf}f(Q $*z G@` &iX /_?UUTTL/ӟT~gnFYYSSC{?=4?F `,?t]r'>@ZV.ft*F?6@{{}cN6/CݡIg_FkgEd>b`i-CtBcB)2$CB Hƭ]7 ;/ F7N?G=r7v]$0 0Io3HZG9jo8lr`Ma^w 7lԺSrfG/Iߏ98Qb^ol{z;z {T綳ܗ~x6˻{^xnCtBaHp^ ɶY~46Vjq/0֨ZC846B~$K@->`F>bڪ}ǭA}IK ~i @V}}{˴},;.={_qjkt:=OXB6wEtjQV {J?1|~Xy@/~>uA/ks{9>d$!q֊e ТDB*s?bhawÕf Ƈ֊!\,U@L0 #$E%N~lbt駟>N_-֋(|>y̿`e$TQᔔ{ۇnA!""^W'Hy9w``>ݏŜtPVČ d0.ݕ( -2Q2kwve8):4go;v?XT0/.>6voo"[#K{T|<ϝfGH$Dc\' W8V !-@i\9?~9T,/TRk,ɞejh^"ۓ;PbdN²fw㻛ЍuuF-+^^V9"*4L e Bd{P.coر;il*:Z}Vܷ{eyWqK{k83DD7<|&e8,`pXJX$d\I 7ßvJ.A(Msz xcI dҌJWFQȽ2p C>9j {/쓌y$ @42fύqiJѝǿF Ϟ}R׾ʕ5D[6pE~t>e&M`tEh`I"s#V`V%Udg;ڿpV$X آb ܼ;X>`d(7}e'{: s;͊9@GG-pCqoSY[vRfQ&-,I)gſZ{>ؚ>>&!mm[]x=dLG8niF #fl6[}`)f,kGO"0)ms S50s&G'–l~xEW]eіwc曳bsvw$sdSZgooK5 `-6XQ|geL\.7Zc5 8_n>ZvVb *0xs!&Ld ӧVҲ?;hcحz{0E},Tb@7gKV~F9s&fNe M^ˡ޲0y柙l߾_R[!Z7뱃f;55s?Ş'}Yzr?Fa._vvҴG-u q~;C:VߺUK?8Uwhc+Y]vب-Cj`z\3/Wxk!i;7x mlιiŦC, ;-Q-3n[oѲͭM3sO/;_j!:7Ɩ<\ET&ڬbK,8hKįPFL% d}$ekӿ,L 9%C}3o OWܯOcQSVl_]V;OƘ-)Z/ ~7jk`Z͇0̸۶m{5y}#Ԍ1PJQO RJ#\qwȲI$^=3ֲLSS 'swF=p'$`5kB%lOLdW/˾1=$*,f:ig,_zq,BsĪ~6ݮ{k?l UU|Bxm9y=|k k/G:h4+'O%5c?\ل9]m-Wݼ7iM . w}U&\m6B}8X㦵>,8 l;<,v o~ݾ墅7z?͚#UwƷg [S,Dd=g <LcRJ[kǣg/ޜ&\pXUei2qN,/e]h!?e p;O\pIeW ۗFWO~MCTE)Njzzzv !11T|^owc k}EDV]]ݲ|@.(HȎ}_~R@"JCaG,ϟˉNI >|=1{1-{`ssO >)7'ӃoCƟdU` aoλ[s5k7T4Ϝy!w)׆N8wÆgtwN<+Jth\_ukcmpFI!%(1l֮lz3Oܧ`&ز^fb$.UW`r$w֢/epvsؒU=* I/~;±/: R$ .oI[Lw7v7־ܐŋ~`Q<_|j?ڤѲollMKg9 I *#la@l̴Cm_xmm:=}OS̬.1d%?_^?w\#[D#5XzjZ5' ď`1gDƩ'5O͠c*Cnv$" p $-rIM7-^ܮZZeYxU}m&ZbєȧoJ&Y⼧MO55 &%\{OZ3KBkð\t=䓡+Vr*/[f5u]y!J(9C^+ZEIH+^I(Fƞ,mYcΓ?'/@kS7mұmlVא!gbVk!a3߿0!!zADP=d2vV?!ԥOq`.|>okH Ēe^ `q{Mq~,c̊n0~b'9R"ykVN`Bjree?S~ArD44W/edߋ*Rޜ:א%$9fa32[㏧jm"qNP\ GrX\+_)!b8^NFApp1cg~oom,~ψ៟8xd]_! KF$P؀2|]^YB}?wX?6k-ښYUE׶u˕|Ώô* ԦNX`UD7 P62w][v0.F􂟼xU=NJ\Z"LS@S/&`ɧ]ZZݷGKM'ᆆkKıWE,@3shleY|!Zw3@uĵ[HsF@ċſkjVu--t3X`82R |3P(sCN/~I ]} cKwyn/G6>Fмu.6` B6骊ӦVފHy6-FeI'?1gN@P!D֚Y03ki;o۶ ""<|߬bf#}CR3u]  G`㚵P(4qB3\z}y?~S*=\'S!x L[D+ۖ\h`h Z[uˌVJZ0{7P /2}@ E6J*>N+׾\̯[jm=M Ņ$+.ҶmK9IM^-=v" <<f:*YŎ@>oQZ4ZXnmW5٪+E*"ت )9B!+v_"A78}*}%%YLeT - +vCu%)> (Elރ)X>Ǿ2%aMmEƫ>}г+Rnmlh<4f:ocNlg%dm="3UUjMRU'+PX(-R㿵,5W" E 44*[1˲ݬr*Ƈ-G(*[*ǣ_tB9ee%22_'ԕE}-S!p~cSgVFw&=[G>g>HG_Ƙ)`6<֭["h4 fFoo f9\ pc߾cTZ\.wI&kSL"<ٷ9%C4Vcnoh쟮k~=3+}T!ކ]>`tvtpw>ɒ5Et`Q;.>նr/}` l}pss3'Icb ^eY0#tz!IZky0B3 )B|>_fIf`<2r,t8iR$M&{I/xv"e%Fip$"!׷ũWAih #js+$f3aGE\dc #)6 feBpė\j+,Knvݹؕ%'CRF@tF]&w+hX`s --{SŏYTn恮t-p2Vj7 ͷH453؝o?s Px $ ٽs0qB6,[> vԿy9G}0wn55_w+񒒐6֊FZlއ-;+0i\,)aZk̇ÌHG=4mr|=FJ=9?d'֨[-Oxf"W-GBd5"8vlZؓgfЖ[O S5:It`@a7:P9X ]A,r˫ iiK̛sxckޢ+N2p8)cLlO@ѻطz&wy۶}tz>!S *FK:,R"0J*ܻ֗z}mWF8H5C~ƥ|8W0}e $iIfmMoDc\dX gߏ;1?p?^96F,ar@&]3 S[g2)O{nܿu2#³X،ɱR~guι7?(.'@T)%tɊ{ho|@=xT0j8bFԶ`Fz}! ~qw,0VgH@κc- ho5?~Kt* A 0C4z-́\=T@Z!F7kyŗSAޤs]<j8y3[ѐ[a}Ɯc+- !X8w蒒uQ^]' Omr'fgfTkϸ1`z6;)9B8X.ŴUP( -Xf CA62VAdGNJ^ǷOP"q=k<2ټ~c*~&&-NoKܘ` xO=qfvq߅dVU|+?hl:Z420DmY &F.x>20Rhb8A ;Er ]!>8w Wi3}Q]诇 iC[q"ʀ1 LB1!B(5khpm\7UW*tAk-A)οRhY"'ulfЋ+Sm j a!0!$`GaILѨeY .ND`@Ÿ18Ni.`<~Ͽ+|(<Cu]D' 5No*#@VG\ƍ0@hl4'((@f20_H1d\qy}eY(DF "B(B8.RTTTXQjooW*v[ZE[H# nO$Dl-Fi&"`Nd4|7qp&+k̋aHc][@d2H5eAA [ Qb[":EKLg,̩Ht\SSt[CvcUG,#c mִMn%dPl\O\9>Q%L]c ~o 鍷3'oPV0A9&;63VL<ݿmYY2KA!;o+`@6Hq;t~B08{c=w}!6 ׈8SDkhÐR j` 9Wa옲Ξ9* G(Q_8e6IP`TJ+Eŵ'l 9 }OGٲc)]G pqMo#geR)8%pvh4`$O6AƘJ)cHJ+zz,Y;s1svkkݻ6߳_z |ĬTYEu\ ` 4fH$/P!Ԅ3smXhʻVzt X+*?=w=U90 5rxCP[bZJv {;2l(i.*jBaK Zrass3777SssYCCC}HJmۢ\ضpBmE}ĭ:,-B[+V~"Y(V96RxtcEM0VD24mLYhe1Ɔ%)eňZ Ұl))eEǤB ր1,fh } ߇F.OgnN/Ξc=cVxCޮ[ٴnϘr!>Z2v3_NFY8sjRZnVwк[l-͇h侺7mذmhxүGS7u'+8iʌL&{?\EВd0e>i/-Q^Gضrabl)Г#k KC+/lEx Ҹx4lZ3911|qypR,Yދy*c >w8ylDr,GCq\7-sr"fs?M!od 2G3 Ax_B aai|lpd/f|g 4^IwdF.=BV:(,}wO7rn Vт%Ggv kIp>2h,$9S}=&}_zd{A.[|d 'ڟ'MCDK# Odq):Ng3ˢ]sمmJ&H$dӿ WcyfDRdƘ"!_xoooٗ S2WXHI4.w\?Kj©c^3FĶT ր۶?"k#TGzԑY ͫ[ bC^|wܔ>%&|'SO,?7r=[AZ;`偵6 Et^g 9kpb1bd2y5y奥g;Fxo "865f̘\tECa–L&0n]{ kqCA锏Hx9-". K!g d9Q'|}{ NeL+UY! ҶIkZ|GГbVzam۱c3l̹rz(tf]ݺk. cBLD_KO(8O @ܲ2`l֓'/`7lYfУ1idQG̠% $&HtՍ0w }ׯ?o^2$3,[hj~qݻy]C霩֌4oIq`¶,b q.gL95ٓRX4Ke,erMQuזR:㋳+a߼LϥB[]w>|qi|םN +u,_j|!L>H$꣦Ǚ`h~.*rǩ wDkk^`}ꩧd2 \#+#Y!squ􀇺B \;xoaBr8UaT:J9Tɟ~ d5#''!J "zW6cǓoZhدn T#Ư f׌xې>9_5zѧ .pL8Ւ0D H!k##02P{Ze~6堣Lcc.]y~rr֓R`YVeY[{Gu0|'BNǾm(=!ZYIS!CT.{*nA{X#} G Ii DClo~al\i<}DDۚ˒eBʨ(Jf2:<՛WVdR_?O^囋 y|DʐEvVoւX Է͘q֦MmIROcjPtoM8+σg LFem 5/Z,;Y⮮_^͋_wu!"r1J/\wu.x5c;}fEܻHf|vf7bZ! ,bt<@ ',лSg#hEeb֔1{r,b =+sl@E(ZhY `KFD,*Xi/[f oJgާhɽ BnDA%krRٛf~CsI IDATԱo:=O# %DaT@o 9B!m |B'ϟ]:1yvL_Wڿ!^|QXCߗWwCl~L&S7_^~?X)S^ϿrdP,8~{e4[W]vı />st?m@1?*T'J*|Qʾ=TWq0)QWW4uuެI3\]L&ݼ , hli+VPܹ<'Ky}穼.^cqklŽ/D3+Bl}b}}WEK8Yo*|6彐Gmiiwu]Ci.;7f)C0T|LdX`僌4.8<#r54uΑMMM9^{D"a%IHI՘T[0gʇ vݷq+w^3D1aĦ fHpbc۸~-KkI'^fƑG|gKFߩ@_= dw:3b,K#P̛7^'8x^$ @f_>_VjkMj{}O x9 {Ur9];XgЕڡ*||ѩRSaQX1 %/a  \ߤJkntv%2ҞeHUA|pF(nA<pzph`e`Sg@=(6iʀ}aX0'\~zbP6ev2~>#u+۶K#IeAk\>A5acw6[y/V:|24`AiiKVtKFzT^q(Q؃z9+stx񕏷Ww4>o ^yr+kzxFv"\niF[UҒ18iGVm9Ox2p߯O|ډPm.v9s%cQwI6mϜ9c;glO :x;;ѫ~e{1P $e;qI42in&p*%/&FEkOT1ϸ@,^Ǣ%"YGO !~c`+3L&ӟL&=y=[9=!2_hq BS\^ӁImU{ z|7} HXfo2/Q@y> ^pGtv%̩`?amTd(ޅGŠgd2  h(,=J H J|ZCQ[0A6m?+E7|70 +( #hSlF@1+ qoxKPBm踊3n-wUj˶ܻ16P$ [z!jHp- ;!` 6[MVvǮdSCsx;3O= mvݯ&ɟ؊#Uף,9HO_P TS 7۷1ygBqѕ)ڲiP\V@Dk׮DO4i ߓK`Xk QP]73Jy$Uʩʵkwt^cEJ0ξsjcmfl䶹AHњ9~:$9=ap8+<Ņ!Oi$`DEzezWxΩκ$CöDi["K}Kvsi8Ȅэ 6l}M݆k@[?GDK!acBt !¦i9 áq>Wy?_u/4a5 v„pS8\YAˁ;.;vv6r{o1|ձ/^8J)m3MO)\ duheۮڕS-_=tzPEevDBS dPXN~[lCcS,˂u]#.P(0c׆JcsZMƑ0t1I]uJ* 8Et߶ݹJK!S aل&0nn|׆OBp'z?Ȝc67,|ST)h· 0_2mX޼]yo7°O;VX*UoTWOMM2u-d Sy/Oکi7X֋=Ho-$%Y m)L~\m]Iy0!AnC6ɡk\;v-UtF( rBPo}}=wz eEDSSOCd%G(DDR{o,͏6sP(A۠TFzﵒ+`#0BpˎNY^ m]ɅeyEoU!U( 2 C|ԶA"t@py*#7<+zM_Rd, D07)sF~L|e4{m'nMfvg cr9.KO֧jL{,k@+dV__oLߨchZlm]JaD(֚-QHim>bz]2M^ 2T!J^E8, RCö X,nP 9xt1%pzA%T`BŅ~BmuNwDz:{$Z!!SB:\TaJt-2gmd2i{]Di0ئ0wBU`򌡡fif: +0klNlEaB=:4ɹr?|oN Gt' ԡ@ULa`)zi2R 8!lPJ!Y#h7)MWr["KS9Sm #RQZ4#aeCryc.ˈCJxn};͝yѹ,N3-ttIHc:>EO1MKj"E|=hQ`h6A#{a ĈLa0 9NEQ=}?yBHc{Xv ZH] O 0YHrJڴlx(q^@Cc#_P]7أ^hpC9(όˎ[PtH6qzmi ‮3(ĉט泷lojC5?ӽ+/=t_il 4]~~ɍʾX3(mVHX@`y494.a>/'|cʂpPWoG'W'8{l1.l@L:bkJNBN5m uu~yp[Zj "w}(gr $*@.!=L#StiX$PF/K?a4ö@_NV큤Ì>Na+eIA6'\@19-2̦i`$ѝ08%JH QooXm6,& , #@2 U1bD%R?ܒS3qyHꄬ(p:d*Nu$=6`5R)¹ $8<>zs`ں]G+>۹{g|ʹX27EKP*˶;7hy[,̀t!@% ねlTs8T[V ˲serb @ JtL'C!sOmq lUgT$ڹ.3|~8mѥK/F:1"ᦦCӄQB­{^)<)s!pȴ/-:κtq[FO~6L;](ADM0+W:ڃA>V=4HI׍+f WKv0k3E͋_Βx0H.x&SC Iۈ&_?v(YvvyH__;EIt ^d0jRJ)!E|>W=s?c7\ st92] h^ hZaB82d?%P]vbic'sa8~ei.+PCfSW|/Qtm|qUUa$ޭϹ)=<rB6]o Z\ L&pOq I!T,0t--J]4<0]=?=7_~虊m;~U{}Jct:gOge{o̼|em@PwYҥT?{K-TlP(D w=9v7 {Ǡc6cFē~G֥FCK*TWHO5(8TX{@ÕPd\V5 գG"/XPdSFl|ͿoT\|$9pO]S#1F)cG190AYN$ !Ǝ[ZO={wV}~ 0 !C9y &pDc ",H{`AJz a_.14O%anjҞn,Y"?|ssDav;~×|l%)J5z*qVb7W@#8C |mu U-ytL?fZq;U%Js]TrP1[][-!}o B`keW0*|9`XbCπ} +'A9 T4Pzi4JMȮTc RKQEQ6;&s=yV ߇ۄ5n! :Pcb<+|S 2|OFnDJߧi bM:}%%,7=+&_.l;\(4M8Ӎ,e]vGG1- ENtzƞ<9ADbD9-[F]ڲyFu{wIܼrݻ^ݽ,HAuݶ귝w hGPײtNpSu\tؽ"btH k>E0gEr#hO)xK Iᢑ9M&Da6mR۶`:AiHZ$FRŹp͝` '\[DB5ӊG^<x*APHY6&aݶآ|yxg~3۶w 4 iZ0 .67vVS^L I>A`J?Bt#mw{MLtˍ.k4cnk[-x=H~}M_~S!e IR!IT_ 1$/X.d5KRB(!sXIdz{Xv4w +P2L({)4c@` Ҍ7}FnHa{G&4NUAJ"/_njkMN;a^y0_Ynl#AyA{^$me6 v{?y~MPa0ӻNk,_pa_,/ɫuF'!aڈ&];z{_:C^ GY ?<¢5rB~ SN{.R8{˟O~\ꉝOoxj`Pã~yZC<ҠGKIC]kl?g ?_P{es\ D7"IyӀ (:<X[sǹ"`Ͽ @P.6DBfvb2G%Q.E(裏uO>#aŠC8gFuﲌC'!o~+%D`Z4:Lgړ:"p87NJHzX>:R6KXDC5o{%u/-g$ieY$ʔk\x4 $\4?&'2\}D SS{[ C1n\L. & 39vwW}7<頾f ,VsbEHZ l=sUiサDݦ$؄ж6^ҡm.[Pr Y}L8R2C% ѕ+Wp|SCݞ* xǾct~m-] g+~cPa kCe}`-0Hn8y. 4==$Y3ت/ߥчd8Emm4'+Np"R)mz2742eP e#L) l~-| Umb!O}{vYsf*.y l6#ɵyu~࿇~ʈv:N"JR?pd(ݎjln4ĊZ =y?4{-dO޺ڞ~cO_8ph.c'Fq?4̣p-bV,$2Ԧo&/Br-aW_?4M:VSS347nK7Xlk/[477*u`h^u;/^*A0lAo﯌82lMjh!˶@, C ͟`%8@-B`ld0nq_ʩ}WݓݣFx%- @[wTTH(b;6uu%;s|:ܚs_P/2 zCcC惣 X N”ByςM aX^m!J9yg[WxՁtd wNeCQ=dϏP" ߐ:~8%(onC?G~5X.w=e' d'Z~=nOO"T[w?o}i쎳;=/w,˓D!m]7#jzCBREEEW=O B!ľH$Vkk}Gpf#cŕU#Em{_lΗ,M?f>ʑU宅k# Xm:_Slr׃=;+B,K EFEYۛ6S(9-P>!6IJԲu'/TQQh;vBTO׶^z?Cya4"lzď{{ِ?$P!uNfK~ĺv)yvuOq?k=AhLuyX^x}o銧<׸Jr.ҁ[_^WaOIH&D<|&,;O֮pHl"*isYq*,C7LO._r@)m߾}Zѫ&:7]BpӚnƍkI4I޳Jyy[?zjC9+B.+//^S?t!g(=]y% ٚC; BZ>hs( /)tJ^C f,X o'Lgnqq eee#nw3$Ȅ "JCJ/E7*.;ڻqm~ Rxr637s!yJgA.&jۯ'DCmY!%j(GRJ 0I(*ٴ2!"ݱ0,Pχ6y9򗿘{D~_ݵfO~>JFĉٽ{ٷ~{!d^I&Ud}}}ё#GѣG'Os:3cT*՝;wKJJn r`ƍÇ/锪,܄~9;cw0V\c< $ Rd-.\␕,[z|OmBB^j`&'K,O֟QT8ȼk@_ 䛃-Y8¢ǜjB7)ǖ JH^I_^Yv/ [z@; voy^ 'GIx, T$>U< onkO]yxI<](Ki!i'!S4BPJ$JPiZ<|v'&TJ /`JGWRA)v$xWOal$tnG)Ym]c;,,$BDj[È鳗ډcݗ_O)2LrNoI†X f,+ռk?͞;)m6-uvX7H8>.Loc[j(/q: fR_\F M6NeUK>'L*~杍iq\~u#G{cf"'t0mHK_=xҴ==24Qo_ΞuN ôXd0I)ty],.dcR+Om=n(v'7rH!4MSB":#TU97kRv)#BkxPPwvA`-`9l]Z5:F`D(N}ȕW/#2!t8 i iؒ.Ev`| xWa䚒7B_o!>#X56mۿpϨ3&o~-e 4ٶS;{ !(IH|WHcܲv]EdY_)vIIWU&zT]@aB,M$˲ѼneieМVΚ7s[N[Mzn{wy|8C:lls-)|֫>+Jw 7%CD/ܿ un}WU~|MJSX8sXt Ycn<}l^ƮE=~6x!`ltnي=9b~YG32=}p}Ձt`~,LR?kx Ǿ{=M!@yP(DO,`ӗ.7?iܪ&*RgoK~_m8Иa*,,|ǎH$uQ.s+++O۰av%&"ܫ=w}7%3 `us2]L7-vkrO_R3TuϿgkwA @-k77r+ˤ&ly}_TkB;Tw4l7*'&p w/U>[oJQxrw1eoۃ螞T8~rS546 U9eiRYB B)G+0Pd 4%l':FApN#n,So\\WGZ(Kg?|OV]Nwɶхqqբ('ENX .qKBY{ meQC"|g*$D7J i8S^?pѴGM+?6G7)^TیAC?1n F,iTv)IЮ=moόq+{쿧k SNyl 9m/upgOXS=?!K:]ٮPFcsz{{㧤&?+pՓ+s& Lg*A5Y7:\)W<ü U ZG{챍]&˲qF6aL8ׯ999v]]'GN7ooxPDw(L_{TR,棖.7YGL,_k-voV H6ʇK^g쇷̻o3N_t~nN%\ʲL<+/3|ޯw{b}BX EB ]!O( {R/w̹#00 Y\"0q,?o;$G/=zpiӤkך@`Q~~TιmYDӵjè~uBXYK:;;oQ3/ H2!L[ކSaĤ+N="|o F$=b]j45zͨBZ L ;`a[k +U  V|zǟ8L.JѾ칯>B$L8&{}}zw^w[lP8.bcDQ0oC!JPH9묳4m;. !!ߏǓQF1I렔~+L<4M( ۱uV#NHHpʌ'My׀>!J,]Akf!7ۃ{c'n~b8eN;KK%oe*+5}'Nlmmm=sJi[o={JNe;nvg: ! MIl떠 \"fϬM)@(եه @6AtrvIeNs`(Y^PE%61Lo+!BCt?, RjLr wK +TB3cbDłŁVӘfRj6"ksh f q4H>J!@X[SpʴׅNS7_|Ip#k`-/__a$, !11*/lSnu~, Oʰ,?v`nm 2 +0q|C ;}@P@ >@ʜh//MوV"g{#%uM3fN Ugl޺'׭~K}#|7njt#V=W =c-1,_DR8Dq*Tnz8:.HHZ5wKהt6Itc lKu6l(BJݬD ́p0wz}] _?"#yyy1; `8pSNEyy9L$Ix\۔_%%%8pF!]亢,o ˭Fbi{=N0n  _uĬ|i`R@!U$QrN;л"uR!՗]p'zs. BxnNwwȚSC|DQp8\?{Ҩ#m[FwIdǿ>m@$ADI~`)"]v zOu\4M9a, m4onlۆ1&<\ay&,M-l.-X?`4 &ǕR%DŽ+q-H&Dl#N Rpl~oW_7D"qJlAD2e͛7" bGqRdzs~ځ!oPJiAAx,߫oNlȲL|>|D0MBBlzE>Yi%||L/Pp,SU@% `@%Kv:,/Ux9!@Wonn 9Oni>?m;cF*(;D,ނƌ5k׎]>5ok~~\նLk{"ӪdCh&Mcu)&<;@  0i"͍){J JeATpU3r]anFB K„յ44=2//>s uD|l̚Ӑ5q fghtuQu*''A֊lەT(Dh sJX~+ǍySdLX"Ev9v>6DV쉓j£1y%DE(N{ ~{q>jg:0\HZ( 8a))ԭ`0xvX!$OCUfWnnQ u! D]ٻ'R} _zT]% \6ACQy L"4ts-%SruUqgډϜtP(.]vi&u]O>}}}vtwwKD=z1GuKg0 8 >v^b_?p}ǎyjMη/;}g]8lJNߕU &=7@<'B8}s_p܉^ !4[?m۪sO?qnii{輕U.UIvłq0RL) 0l'U MGHuYp:tn(ѦC3fp\ݝcY4MYa(tWǬ(CQ|R/МYpo8r)-]К?4/`P-U>]|ϷfbŊyy8ƄP\QUB)-]hQG25r{:ȏFUWܷoo߾sPUUj^TTDnjMӰeD"HrY۶1n88Nh۷RMzE95G"A7CiA l2?:!LBsΩIɺpP(58YQʂɴӨJ< Wݻ" +Leeg-l$v7:(Z>B"\33J P (B)g"̀gy.bokD(w{rsZ=#LyI% bw;#2QP= >̘?M@T+vn,i ,|eY`YbG \T sn!f)t$QK*ݗ䳋}h]((k̍ړAYZ7l(~j{N{v=@f%v搠?cnE/Vmr'Lr,L ־P^O 7aXU}ĪMH<[[#'d`7߆~Vc@[T2,!V%Bw Sd銡[i6%8@ 򑓛mM<677Ou_X# *4v~-9hgV{8&Y>T%m:܊woiGCFE.O}cvEie?NEglfV/d\y&U>3Cg|3hDp=^psx A `YF\#%-(FZakys=ӦMm&-Z ,իn:TVVbժUؽ{7 !D>MEQNlooLkgg{ ]#N<ҒGfHKB\]CiKhywÚBQ7|Ovwu@ e!''? c h^N#x7߿ɓN:P(=nѱp:U3w @4!$bֽ菤,XUmnJ} ?7ffX~~[UPnnnv$A"#0qDtwwc!#Gĉt:Ӄ 6 YD4;;$ollLF%KdYjjlӡӊQF:8 bȊڐ$yJ6$>l'XSk#EQ0u`a=J^Q!؆;{[!o]:-m 8у#//@nn.cED@̽o(MNNsd3app饩0,Yc>">FBq@:}AKٸ` ǿ%uqo9 Gww3!ܦq?ي)',D X6 %@sgֿ񱐩AA;ٙ55!kNUCK1GA*:q6z nE3j^s@p"-4[/,pIǹ_Q«qua…8~˹m`{ BMM`n:~@eZu7]y53No/W޲oqrB(|FHE1|/?/ZqYUUUR O?cժU;w.=X}ٰmeR #Gi/ac)<3tਊm"ms!G}TW$o i6_;+dYի18a`appdFN/,P999tȑ555^{-p)\)er{3^Cz0Ύ;1}&M2 =m[&.{O7{: pҔȹg{^NUU,ˊa@oț{;VF_йiՆi&hvFa>(9ak}N,]7ޏt81zUUiĘRӊ 1nܸߔ5cƌgΜyeˆ_4}yEc{vkAA-[Ƒ8eY9++K*$ s8Nrrrt:9=ɡEEEZP[ڄ#7 o.EڪNooU |l>9s`f+j! VH,Yrf`ܸ tx/^|N8Ddee***{`M3f.Y5n8`Agw˩Ķ@?*KOvpaߟw@7.=]C T˫͑x75,̜ܟ(H,xʆGmPD5Rjkk=@S?R\Gk& F$F=$cJ@yعm_n#T"AHcucJAh*irl>ciG0) '@9§lAI~1 ?ЙBK zu<4Mp6{oSWO!o"犇ֵW>5w0br R\'V֍h G^SQLн[t'zKM9xA@&ARp>zUw+[NqRf͢iv{xU~q0BU_J-ln%͈ڸhWтqjmq)o`yo/. 9ٰ49L)R#Mv0H$1# w;>]O]ڗh־q|e<O:0[3a |Oa[|gM8`(K.fWӍަyW]u͛`0HZZZgϞGΙlC͔Xk4SIDfX1aS˶ʠtFm^'(,J ۈj]{v<ȔeY6(! /χs9˃ӟӃ?BooYXX(jjj.Gy([9;d m@Y3'T68>EŞp19i;`]~m}5'Les = ~+_^^˲IFss3/_#<'p&N8?Squa̘1?~9#1h ޺[[xL [eXs'ڌ%.~8+ n '͒0GkH>,Qy%0 X x.`!x ~$&(Dx!} L8|9bJ#گ\z _(e=FgNwq zVaa!kjjB[[PWWM6ƍ_n%%%غu+9_}}}SGtF1cs:#k:L!骗CHF882%e^x\?PR!裏ۋN^/FOO\.L*+03K.eY2O khc Jm-={P~*HgsN=Į -QWۣ5҉ER뉚Fы(jǸ ڂCGtl}aLu_ xv=^! );AK-'8ufe#G4%lk@}}}뭷Q\RpnYiUXX,uvv`ce"G}bH4z^}}Ki Qj a );uF T9苦SFodҤc^;vb1̱ec/1IǶ/8m}e$ qG r %dF/q$%qY^EQPRRT*1 R _b૏PnC@6\\``XZ]tI7n|Ͼk뤾eysa„ ضm*;/ƓO>۷CUUb& @WgQlYe_Z*mSw2$Bm!bCG Ծ~>hAYs ܪ5k|B)彽kG{)֮p:mE @,eY16i, BustuuM,X5\~R_h?dtυN%;:vKC"8Z,JRN xK*I0U 77~)B2`5k4C)wwwr2f\}PUp\Bsł xuvv ˲b𫯾pHC!YY5< TJ לЉm 0!2( SpF٨v 9#s LpohnQٲ#ph_>vx8]Uk >ؤ b0*JĚۇB(0~g S EQ6O'(O̒1ES K ܊RZZb6 {ٶ`(/?> }DiWTTx"ȭ/V1aQ+F'FT,> X@w3v9=5Qu}rKA/Ȋ7XO[{7ՒQ}o"x #G[ZZގqrc/qEc+q]azCW>ܲeK(CC;= RkX)Þ]ו#MvXCag,4`HzL r8|T}]q%YgX 1:m?z]ݝ[?A61{l"X ۢQ)&YY3 `SĚXxd^,X ȰmqjY2#̞=۹f͚Ԭ.:y`9:|? bgB*" ,Zג Xgއ>]pu8aR':\(`w lG[{8'r|s=,~*H#ѣr%(u@b"%o;.ՌzFW\< |q>Z Plctx3asRIӀs2`5>H*e'L >h{^P!9(0=Ij+i`Jexg^tF TRghm@RL0mp;]mðR$x24f C,&TcՁpP(D?&Lx{9TB0B*** iؑH@Y WB"K$ 'P7a+bQQN;4RSSCz{{1j(Foo/|>qlݺ_~9;8\wux饗ގT*5- Cك>djZ vvv~ %%Lۀ=A!t' !ӆxeC> 8jdJ  J7,NK! d?xt)m #ctq_QMHc͚55jԜnR*ٶT{,P lA BDk:%*SO=UE=;Ȳ|j[[p8T]aY~a٘?>b688۶qma7n,˂iu%dYu W}7?茥tɒĦu1Xv-?YeCp co~IفW鳯0y<{@Z[w~߆ø뮻ɳTUn_zzFl߱1c1Il߹DG?}}=wV,Kk̹7MD5Wp,`D:dzx$TZx8lx@Dpʜ9V1 Dꙷ2el"fj0*?t`Iz<΋DRi@f*SSA0g0aD{zRo/X"8i7*f" C$[Ba¨L憮۶i"//oٳx뭷#BЇ~x{<L&H$lMX 4Jpײ,! bѢEu!Hز,ݻw-IOo=Ǽ7xDljʪJmxwy7>ן9g_ ӝ)هSN9f_q[YMq_1m֌~dUePU9( s1iX@4x<ٵ}ڄq'-[6 }ѭ7VY2,d?Ba>lqTѴY! /PdL&8@r= bKK<[n{ @ iz*IZSoɓvB϶wD  a2һyDhV_q0\ !5m@t 0hA KI9'Ƅ*45@AaCx <Z$mC:[oI ^RbRÂ'RЉE,/: 3 7MI`DˎM[|y߫IG<})Iv[>uOĆ\-!0% @0׏ p(nH#7app:#-s: F8Sj3aZ-BZ: le`LMĉ+f gpɴiy'׾X2*U铎`bSlxDcN |/F~O"IHj~VL`ܘҬ)2 [(ޞ88hʴSĺ#۷ |o.?~5kX&LQ+Q0X~ 1<'>ɀ#ρ  z{{_ܻwokfڵ-]|Jy8q⮻╕kܹso>q?~<{1H2 -3HBht,]88£J|rL3040%>Gf}yO]2MnᦦaV !UVVUoipm@r:OmڤT0ޜbؖص+GBRCK? /![9V fh$lضif+;}S)>}f:a%uFc냮e_|1l_ !~? n7L$0ƴCMK+H[q%*XYqu`}x[oIiZ@i_ˮhdtQ#@XumlG(:RHj "H*H:M%U P*"҇@a^T*1# V7R*sέxd01KmsRJ킂`kk;W\.첾nS]]=۶mOp8!2=end$ BDnn;w+~a7_yH́e.q]doM7߉d G]="9D8ZkS4 Q q8KlgNLNw8UeYg} 2mPJ0 M3$I݄Hd Bwn̚3Xm;٨-_zƻ={t劯ekE={!+.Veդ1%N8dq@0?V#[UWX6%bU/E.Op4P5D{yO砨?>Oxa3қ!At?V.;ȁQM&Xel2Ɩm8bbPaڤρH Xڱ{=YYduŠ@edy?tpyw Le1u" (A*7Q "SÏ w2tZT.J_W SQ}#}zau0UرN"Xġ@D )=ҋ'W :*oo׾CfZZz)%'x sS5_Tuf,x!$*hpv։vaf-  CA/|,o>+GBB"#ip-;߫@p[6*M;&)PM#_ Y(4nܸ)瞓~ q/$i1A6oތ\GM <9*\~#ωSs~x$ !O>A^^?|p`ظq1Þ}پ38#0eK/駟駟n @:7b wy5=&kj%b@ӣK@8 @ Pfx(u6Zw|IBmΎτϛES  }mDMIww1Ud v x(ϪIL)q ,!2 K ao*-+%cǎPnāmxFp.0ydv}?c BeLB!9}ж4C /ѵ fRX|\7tD(vl󭝽^[0ڥ࣍7I⣧skk&,2AU)n.,|{ਸĺNm$;@D_IH]N|5|MA"a/]g Ɇ*si @s_Cˡ%&q9!~\.LQ 8Z'& kB|ԴX/>{*0 k Prz\0f7(P-$$JZvmi 3.ylɲ( l6a@|S۾ITz)EWh%]ݙ%[Wzr Ф@Q2PStwƽzU{ SJںJ L,Fظ?6< ]t%GϿwlePmZ׎f'3j1& B$ib i|Ef,t2^kI`KM`0HpΑm'IfYְmugggM$e]Hx%$Ty.ĜoMӸ#G,kjjؼyp|gx76nܸ^\R\r%w gܹO>$K S* +kmيU,A$II/K ,CbIux2Hf]Y%@apa0`&?}iP3YFYf;s"n03&7ɮ̖'1d[2H/uqdf~y{4;n߾]UOUTCG @$A̍%_MLd]W$5+F@>`a9G4E4Eqq188N 3B$IP'@G{M?V~,FCø;S^)?g 0q [qM5x{+g5_24r,^kE ŒP*bqZ !Dtw4~owJV Rh69*\ 3hQ1g{G\駟flcSSS_ BE h4p8'sKQYI&N\jҎ0(z꩑x$+rE|X(BٳgcΝp:>}:caR J),UO<҂UWtي|_,2MgUAi"yl Jnۉ%0E`qA`WܼS|VkEB#7tٲ,5x0S155x== 9kmÏ8N6CjkkS~9'{i4[novEIC>Afn>l.p}/Zv6cۮ^|x; eb8Hi0D䂲s'6:THYV`񅙦FEK7>zx55&@^mhrJz.E/i52$Q1L.D;_ǫi8y6 no$;E͘t<]u {wʕes̶/<"żAu %Lfa* ݪ_F*&٧(;o\ł&]g$E ԞN朙$JI.^P9, 0k,ŬMG:Q +`g{߼<{^_[GFP[u33pPWҡ_>i)xlsn5:Yͱ0@zmK(I`'}_wni`i,+:Ei]A9bUUef8v,Pv\ _'- "vt̝޷W;J,ä-!P?tDgOO4[nefP$1 Xv7}'wQJ'r4B&9`$ i$",Cʹ"jH%ov8D 뺘/_ݻwv4o޼=i~q׿-Zh͛g~ .w؁{No֯_{ .u3t/^x۔728+Cr1.!@ko?Ud2]oP"_oq)|SPY`2[[Oi2axEiN|=o2fL-iarpc_H%I6 ?"z]q.Ya0B8GF=~DT #l0!rmԜZ4o1MӤ .l6N:$8}1`0+V?LYVYyJ:Z[[%Ψ[)'F獹e@0ƌ*'N-7-,قU޻oO- cF?)foyeSLԚz{[eu蒊0gr`D8,RAގ6~~wUdLJ$غ e$ w1z@h)E ^yF!d B^o)' !#`XUUݻK,Br4cLܾ};=z$''c̘18r޽E"12_* `._\\/+BmjZ6 @’{/R3=]5Cg&e|}b++NX(U_(ϟ-++f[& `7nc\~7nFɧ!H$?ךРyxc~e mp?^5=mۛ0*ىqnLưeȇ X9M jomHְ*&[wj2WsF6]C60M L$4 tC D uM4#Y* G.u,Xxh yiCQttjAn A6&7>< ƀ7 @f\*K 3Q>.1C^nAjt6?`r/mҾV_IH8r!;X+@N~!l^W IV7)7)z}{ `AяXQ⒎ ]U+2aVD4Z;ZCcˉõ]R*Zɀh*Ÿq!>ɭbVo(9͈s܃x+Vu*a ܣPhrRϊKlId ֶN~jX[/{ߏ}͛~_R-;<7>]H+͘M v6Sc`́1b&v~P%ɵn eQ]܊FziGjd-#ݍ.\>My};qonn z꺗_~ҏ?88_<Bxu]Le, ```o`^WW'x3gs=Vr-X`LG?sX֍e]@86"2.+4`ۚ5DuqQ:8cdc. XeD,~KƦ=2++ik`*( &o(tӪ_@kL*3c)vU@t &ZLJ~!bZf慲,glݺ՜?4gߠ~EQĂ Ѐ.K?x}JUuUb}uݝNwyNw D5ΫƩTQp/gk.!3 *_>Vۧ׽ɫ33)Eiʵo|,)ǙBO^˷V)~-m+[}uip£CRbOXF<.'Zw߷;O^x4ߵe˗K<^v5ڵk3f|/LD>p~選Po<#9 8s<*( ZZZiӦAeD"-pP(tϝw޹ZYYi._\:nŷ_e䈪fQ M_57rk/B`jRNLJeIٲy .'_\"&ğCmhh.{ܜrrssrrł;ws!v¨Qߏntuuutwwm۶⋍;"pg;Y}wZsόUřVAۦlp2552 =fPb}s v**Gp /GB[]i){SC`""Xʅaܮ|8NlYx_UU_ۺe'K\#Y_|%=K2)i0c"~ȇ"0v,ZG!gl-8v'ՠqHQzt_gah/fawd'Ɇu,:e5Y ]ѻ݋(|Q 8!M*\o -Fƒ{7Fŝm "(n敜>MM65qx)2|ԹnŇFZ&w(LЬ(P y驧/=#,ƒ>a? m(•9:},sh{}aM,Ҝ'<*Bg/]n`IZ3_|!GD&|U:3*_Ӄa4QLJE;PG }5uDy쟧;@cB*++gnڏB}'hmm9SQi=***xJĵ;X `SO=uk0`<7ߠRD"޽{i}M7=Ăĉy!ʋȒRrBAںL".-<+3 1qʋX>B|NVnp͸q<3nrY9(@ yWر#huuv`(ݣ-}_^=TJ`:y  w O&81ݾڸl>[8My&_g$%ѰS0?ć#>LKDD}?̠(0kO[WoC +?f|JGQj(kDUR.k*%/W8 I5hm-1|(b1u9Ҳ"*G~ki9$kۈe}"7E;=[݃&|h\화%Ypw-,@[ub~e:++ϖ93¾bNC;"7? ۚ}=Y cǝHw~UQtj3bhNJ{һ fBmm.? @(\To FlykB~.n1N68&V?Yϳ+ܼrl1xݝy}]Iɋoyuպ^}̆aޭn|myp#|͛l'"WH`|/|`(==i&'~(mp4p5״h~qun6m?0?'{" 4a)t/WXvҨ4:#B,o8t 13r\RC1.aƄg'#mz4@tIU_7aH6I)nI"2+<4%IsHHTU,2@ꥷ><錓} C3޽{/,,\۷O7nN>4D",a^OKK~˖->b~@D>}̭O )Ϲ+tϭ0^rr @m о 7|Nu߂I-r X 5ZڸcJAF_ӴFrXmmXU@=s)N1p8"I&숰[%=Ev$SVVƫgu{ӶqPD^瑃u$566K/첱 }>SU]7Jeǟ|ϛg-X@J$B),,Į]F?6Mnms2Hu mWVz͸>xjfI$tÑ|9bVsni6`.18ʖصUz<aĉ:Cg$~w0|[נ{U }hsoaҕR&~uQ D5tb ܉9@D1LkF[0$;84Ч (XQX`GiR5Ӈ `ȯ|^y<P?_~0x 4W*]gD]M2? #˾+^[ xu': J&_$gϋQhԃڈ%cF!w狤5)!Щ~\勪I=$v6?yj.C 38Ǩ3+Khk,'\g/\~dOmcnz `j8mM?)}޼W-ZΜzJ!#q+M]uXVƫ~ e=3цe j~u4Y /s8y$S|W78'.yoM Mo/ h?e{o)4!0\"܌j{1yȽa #\ve]v38㈋.uuu O<֬Yc|ӦM` 5w]=e<}F£99 lJ:@}䐌TfBzVAp3  3CbJs[ϊ~s蝑 8qՐ;9V\Ue IaRg6AXápVA2|F I(bBV_~eJrrrj !u= (999ܹseWWpữѱʭ$.5|úw=Wh)%Eܥ@kҕ; _dG?'<M*,55`$ЍDJTMU\p a:Ρy }:"fTcGv`O‡HhvJYE|]nٺ &:2oHxkzm% f|Ąp\nhs'hɽ ;C _g2",H*ŒC#r0V@Arjn1;HFgڪŲ:܋XFpײYxd6ܡUvHm_!1$3B*Mf}SIU;n?z Ị,Dȁ6 $;7*^0#^ %e;5s(?Qk_O554l᫧3r 8#kmݾ$^vLngd:()&aɫRBH"T2%JqɖO#pYЙ1,T!& i7~#kגIIbBB,=ξ䒖_+O ҥnw4ECށՋ9u#=9#9+GkkDL~ۙ/I"C;&J-b$@P4hi;ي9bXpDTVZ|vUx.v ;c@wkw ?8X/CW"a_5tC˄S3ϲ'Q^{u)`Ʒ^{ج(vkzqfe˨;{cE}[=iD`9Y;+7x=:_zRCH)7@$D[}3x ;!]0b3g?הW_}pi#dsAsN Bs"KJJ233A)8?pﰋE=簔4%S^a #3BLk @DƸ;{p`1e?>߽JL/`Ǒ{_C;/1yiIn>&{֥sRpEw>SӒ?=)Wb{q.YD/uCƏ֊us<y,/}׶U3 ^s[NQ$)-]}}} 4V#&L1/hԴl===_1_|ŧ-[oƧ3_zgϻȮU9t P7j Ӯ]nG/\Ng[w^"{7YEWٵs~osmUXU[ץSHO G/\v[̱g:mkQM$ݻO>8~ah5-Vs`з78p(Yk^OToC85rOd*%GݿR0IHUUb]s$,W}8-ZH^t>.;,M̄;Hs-Ϛa*%\6 CDU=}9[XX(m_꫟\2zk͙3vɅNIzksƃx_œ9e@^}Kڶ_r% ,ɾ]/]Hum`o,Y"3Y~`GNJn_Pko !d3\k!]C"'4bk3/5~-##;c6!d.D\\l[[̫~zr/}!l_hzܶvT6࿞XLU6.W |PZZ</MEp |zʤI_Ea 9p|/(!>*s@)h&6 i!`DXe)@^1j9DIRMF[Y0YS}:=`JEb">|ќSd;+B, v4%pԴ~B>痝Sw"@V:vrΗ+wo#o:9.&/Qb 9(** \.~ ~=`oI/_5u,BxY7<黅{ ԍpGl]XZMEF}I2fSLM52onXY[}pHPtiAN\s(H1֋Tٴ>Y}ǧ$Y'oכ'''.]z((-֬]ֽ=,G5&lPAwWkkKzjj7/?z\Zkt$jj0¼nz~^za_gy&tRL8yi|wyUMMMVuin2˟\̒Ң;S3Nζ H\ utD?={o]QY\\pPkw櫵UbUm'^{lҤkKƌ( hԨtMk(,O>9sĉoL2e\J)¿Bn1!^W/_5k_\ Tα~OEq%kO?f̘.M_?wzibe4TB>%Waŋ'\qWݴ祂wwB:&u]3KKKdW4$_1ݶs>$''ҍ7ग़Rj`xfW?Uf 4-+#X߰Ͻ"JSƔq%O,{㑈KlIo74w±Vf\)aW1ϔ(nz{<"/4h2fL$%eǎ\|BDjGv.1m:x4ʸǣ !(J8[zrv883g%5kY6oTT~^p|{{Ш Hm2aIHON'i*Pa-bd?nؑw5'g\.@UݑpZNΎzx/#N^=zӧ>+bTD"gK=G\輍,(-V9DQi.3Il{rGBF#>=zM0UM_xB9̲@B}^oE@]^;gu^^Kܵ&=--L1;0ԥ0W1⡁2ӮʏZ^>VWI5Xkk.}fuJϩ[4)͢ЈYVĬ]~? -wb!W.**Y9ynj3}RRtbD8q< mҶh}z-?PB.Z8'Ɣm6pi)(2|ÈjEZ>Q!z^3''g}v?|oA踉Ơ;w [=44t#U ;- ǫ,P+~+<|1sT[e'!csmc3.ė\:#ud:5U+˖y=kSvJ9t d-\81\]]wdN0ӣ.B_Ivƍ#׾l ! ˗/+++ˎeDNIaG9/ O^w>CGsGWV.M:l~LEũ[n~,^} UUUs?pۂ:6q={9!81>/wN]Y`^璫o}e]4j@zzQSDRW%9g\p`{#Xpܔ윜)5A) ĵCҽ] -%疼qs2angZ1*8Ǟ_]j̯p d@ٙqֱۥ:u& FI(0z{!$%qHE4* GsXLHJ^bOp@1l]\'].,B;xm̩ͦ1evG~[Ԕ57X0>ĆtiHU7ҝ"Q9`#:!?s'O8Ǎ;))cXSRYsr 'nKI$eeeJU>.i9ʔYcGʰ[䅈GuMZ|ƃMnQSJzasy-!5T DE@MB( DVm[-%JLDBhzjӂyÆ5'l N+K6oS^+Lg]YGwH| RXPbvQE.vig @_6yaL!XщϘ~tRS&KQ[z"bi~&H"4q{[Xj78s90RS/L>踙crSQ0#LPUUf$\>G˕2JwM._O򲳯~?SM8ob{ʵM>X^/;k;gNp(lF!Bd'~ eg[z_cPA5{Ed/ C?5L?@UIh$X+86~2 SƸ@@x69 6j|5ə|/G&Z@[*hԨ3\.jZE`P ut@2E?裳ڮK_(++˦;vt\uGgI==:۴I` F?˘=u]χ}@f~MسfXO߻r%KIMdڵY֤4-{լp`@vڨK ؁=!K%!5=䣐$y[*4c鱐(Um4ԴdEUR[NN6j#,\RwwwCՒ;&9kEcmdFlM%)#'}=5>b4 4MM W^2*@XsK3S2sInh4o8z1}OFzFޮ?:ٷ&V9'2d #vQAHM!obBVU>gàÔ2çXJyTm-nl3*H+[۞^4cDjM-w%48216XxNuQ5L~ܑO ͛EHP?\]]oP[[+|>aƁrhooҒH8"Id| OOxa^TT׼S=й;x﷌w&HJS@ (BD) 4 k;wox;\pCC777K1s.ڼŋKUUU !4DւYլz0Da-(@4L_LEð @x^Γ9tBbFJ QƓyA8 A%^Z }h˾3Sr֔K_:a`hp_~#l̟XL] -!ڤi@ D9bIGsP!AiJKkAAuDDLE5h#e~ԉcƎ%岢BpQe4La0~fewnyL 9$TdwpSUɨm (FقȔ}ȓ{eBRt'ֽňڟ^2mۿ%K&4>9\wx_mDi?SFͻyҜcο?I E ]3^˰LK"e&u%4϶.v^QAd@jsFEZrٴ/-X; #.&g4iEiúǮ9_GM*u)[3N:QuSvZ%zaO\qҽuu E k,8匳YEBiZPe +~ٕ:~쬂Y[ﮮ]2㐹ERF{jZ]_Wޘ<ˮ9|`C23{ST5NEFo_?l6+`(O9-SSI%!=2⵪:{v޵c³5{gE?Ám]*ey8GM gS2S,1c]Dƕ+WBvE>bi'$j5%8 M,Оyd 3]iivC*@ (gSLy lLO|dbc @uu]@ xV~c'1)et^.M1,"0(PT 3lw-/$l:gɒFf_ L<48OG4jL"`@RR'M:O-\UzIIIb9)b |>_ !%]Qwc9Ԝ0 5o.\.$Yi$iKn-<*55EAġ XRєL[yԒ+{+֊V/93pYӄ5 8l8s#f 7* !%9hܱkv, 4wmܽwf z<.߯~;+ѹsA@F P>f\ʕ=>x<y^VU[+z]ORGB0ij6MpNYƖbc/JtV՗Cߌ))Hf"6iū#0 r#5ڊ sli\ DBSJ:=}:#MбY5667xu|GSOCy$X~߰Z>0|aѩx`Wuu~ EQ (sǍ{(Teq83)݁̌ }>__zE\.נ-((X`]:D-Z,Ý69vlI` ˯,s(P# 66$Y,;Ee u[|u _~w|2JI w ;:p '@`).΅$傐9.Mhڲe.%^/'lC@i׻uڪ*O,(a~PXdt 嶢w8t7ҝTW.wAU%F _ ۱w 22 #f~ZcQ5w.t]ɜyy_v뤺de|ŕucs΂}z(-*_ˍk֣/18y}%dϘ-$cfKxRu3/'BjkkcΪtuw~T׮,{&O-$)w<BlPd* V7\YndFM.>eaa$dYO;}Q"u,y ( _4׋]߁تkO>|aB#>qml~R&Zy`(-ݴ p*8L3) !`s |~^הzCm [P(ٸqg+^yaBX l_sB)`T۩6F"XT%$$QWn V N@(s,}w_(n`G>}Ѵ7wZZM ;hbqnDD@&ܱ JdÑ ÈE٠T(8[-qGDU~~('V}ٯVTT||uOOϼsS\\4]@("5=R vm"#zbgLXlPp@#CӢ Vq$Y<bs$'0qb9l6 $IҔ)S.$i_xMkmvUU1&+aSMtm' v)04M8aVZ5_500EQ( ͼ+w566LB3L{FySKAh㫯ݍ*+18&<XX|/,_\y1RPhw}%~y]ㅬ,ۧ|C_gӑhGd Rz:>ܰ˷oygsba6XKK'I#7߼}& sR3${x>]X:Hhi6{ ibQ96EQFcpBLTMa&)tFa&$b]p}2p/^r dEQZSNܳ^wRSLIvrxP".AzS~n7-p$0S(e +KRNQ?f2Ou*ZH't1t#6zݮNT6YSK]c,>>@KmUXd 0 aB4ḏe`5DQP`& #V^$(t]0$;VZiʌ0ydWRRΞvWL#lLBH QF7r9Ə{IwW233 3ӸF%L'bækт<i`t$ɨAYz =p>o%\ddئKTU%v4*Dq:V$AFQ6v,_ ۶E/^x|uuuBuu5}O;n\[o֭['$'' .f,usX~=Ybꪫ2.]z&!xIă[?*:o|ŸSBÞ[;p>AMw,*Ea4ؚZWWM=W-?kCK$9mл< @HYY$E$Y5Rݠ<"X%Ee>U_Bݒ[o'{3JKKS#uOlg(9s&v;҈i\4~!AHNNdYwߣ>]d MQ0DP(C%tE|TucΜ9r&J qeeeO'xsb{np IW6 GHbeA5{'4 <ՅvĨt#pz9w7l|N.=H>6+ s GhCC!pM;Myy{{!rW<&BARTdz["HGyV5<00+r78~g5?]}8EˆSk(TU5M4M,?_R3 ˜@"xo@Er6likÌ@Qj;;! [[]S.8(PJDKnk<λZA`̘1E<۽{pGb`˖-عs'JJJ0e\xƩ~74#<2g׺C䔎#moDe*#gDK޽= xmUXWפ+*#*N租zN=/83P4j tbAc3"$!1%θ`&DTS4=-6OմщP#y<YTܲuSI,}۲ V :! D q%ι@)h䜛y/^l?WVVV d]2>#u!NoAAZ(!$q/敕F$wElRe|0""!plFa:((Jl"( S1eA$rlii#||f&._>65A<ގ͛qXN?HjmH4.\GQ<c,_f懷zkSVV{K;jmN*+N.3"MU @4i&@)Ɣm,SUBup"ljmA  vJ EhT0@u0U%6vLiibbsӤHNNй"@̷eOƐ+{x^7o`Z4P0 U"{ !"TX,~xT|F!?+}~C=zj>@qa3јw}e˖^=zc=s@\t.4 rrf΄ e |/ e HV U3g"j&NjM P2SӐ,IptQ(#88h0f1P Bঌ&/n3g~,0޳?by< .;S%O)Q3viӘe&iBJM-PŢiI(!﫞Ai &h H(*&iMӸ()5Q 0Q4" /搀! AE8vԔ;8 c)\O) ^tp `0#7>,MOO/7o^eX}-z+ƿxz10)ƣQ F9D$fdLVU$OKYJܶJxA7YD'D3I3h2 D(DtPŎ/>.Jyǎv}0)E?"R[#^_Q&n0)pDCD7@)&c H;u=B8\i BYgJ.M4x$>37+9sl}鹳IFJvHa*F ytU)*uo^~i#_k.Q+QP5@He՚͓Ǎ:àϏ`p9Hs GT]whp3kO#UUgN_`?gU:Hkk';RRRVÌ'<ij>TJ)ZZZLEQ=Hb<4y$I`ߵ DI=ذe7Ia`HУ-?~̣jƓɹ3gܸeI@$YՊ܌'B`f.HyY L?GSU9 HʆiL_p.t*N"P4Y7?a^N;D$LQF#+qŕWNA@jjj@i}8a"a&IOI#y3pUNpChf8g@~J 8c0# 08}hn`Μy~H͖  @ tBIO/g?b 1sNPWǁ tɒ%ŋ.8ԿrGZ=Iaz|kѸ5W3& 40PURV+&u vCusDŽ/!0 DUU?U?hQ#d"0v6sr5F);:W,41C޸@` $#%Pj"s4qN!)):\DVI~޴m@BQQAP~c`)㽛n$uF"RteBLhQYR" :Ʀ,e${7س(U0RsfUA c8C)7%C1Q&p:Ia>O kjj44㹌1.+5]$BdLi@ mK :o,*J:nwkdp؀á0(9iCPv@G!´#gv_}ŷ1Θb8\u i/8PdpD5 [mkHH=O#3f8RnaaTJ)::: h:% SII39 kG?c)#FAjWeϼDrP2D06dfdê$@ &1 vg")555rN8 b``=nmnb9眳o;NgׁBuuu=.뮲NÁP( ]ۋB%qƿ~-UUUB(Сkf`袳l9c70ev sHp'U3^?B^tE8Dnq d`!-#A9@\* 00)"(Aʳ#/Ơlv$IZUd&4Mk'NbCUUSZQ8=zxMׅ Hv `e#'" "??Gy$OpIʲ3>w` Ja$ e ?pX6y2ʃASRbYɹ(kZ}׻몫O*)@ A( P22Eh{B8xtV~fRa~.6sI;f2W?fr6&iO&H D#^%99Kp(̝ A]rs4ƎŔBlڻ3ƍE1%s=Ѧc [7 f&!0MȲY?4Mcn]hӫ /QAA_KKK&cu!9=݇V=8&1M9kRRR.}uGTWNu5fL 1,J[9!`$f`%5՞{K/߿eػtpT©ED_'Ÿw9"Ƹgi|bb.+8:Eօ4U?cc*T_Jtd(>y8lr͛6&! \0L3ٴdoQ}#{^_@JYdbR:sY&ݽ;cxɿXuh9g jߐ">VT f$zEI)e6;~g_Zlَ3n`$rG!,cqKD(-zd8|~aqo+yb$w(E v߱rJk ۘZ`}K@=J&]=|Zf{UUQ dY9E%V_?N䒹 q :IYY;30r0E> v!OGIINC BiI z_ڴ:9'3gܔ)--uaLeA4(IB!$aXVx1$;;{M7Mz7,Zӆ+:N8\O[lK.!?ֆc̘1BKK Ə/~q̾!t+C7 h &Y٠1\RjOϾte|,^ݥ%&Ac1ǂ+p0"AE2wٲ(Ax?5  Nݸ+6\6n d -5Y|;?Xo/ 0&EҥEJMBҴ4|zۋS'NOf,k;v`رp2TM@@ShԥKW4C߉0Qq@ &1uh$j3)5Zp'F+ TU}*??(4}J#]ٳkj$o]^{T鳩. 6E`Z""QdIUنݠ-g^m`{$qp{ji k^ygQ_Ti0G8jl[?2ªaXȾ˾{JR6.V;gTM }=$CHS^cN|v WsM-Hr" "jp#;N`n{`F}E;ai-#aDve;λJ86.0 D 6MHP].!CH4/ƑPhӝV;c?.V4e*ƌM|XQ`T)u(9- &H: p ٕ O9$I° p:qaM@M- 9nT4֭[QZZ ͆VB!lقѣGb2wں{ _}U%99ϊXf555u`0t]gRB!h4J  4M#@CH$0p8}>|׋7ٳ144D9B/IIIPRR"իWi .-K8V,zM }j1 bPJMÀi,C6fp`Án7Jm6r,i0( f(iћoHȷ2 j[ L]C]0b)Kf߻~/ FW#팬|Åkټ;[3 ZWӳiQ&$03MRp`ooH\4 R"L3g.Pu<~]$Eݎųg@DUeJސ? &xZڴyj(, " ÀaaP0nS0Q,>IIIa]tѺٳb0MM]'P0MИ5M 0 äwoll[n q@< ՄPXeZ;_\3 iQU#ሊ!oW׻{F5]0u3hX9烽݆IbopՋ[~\h3_xKK͐p0@LQ@5gu_/l?Jlh䏨Iv ") l[޵lɢEr|J-n=vMg,Dn۷6dkO[ebB ,N.fD#`7z<TGM5\ǏpFuP!g4[J߽- `.}Wr;-BN #.#7 ʱsO;l_и}veWnk䀦fPu1x^&(bi-})T7LS7)tkFMRMNm[N)3 f"Է LGWW4Uk`y`|kaax0(OUV"bwF @jj*0~'\|8묳?BvaܹVuuu?Wb[XU!a;VX`&N(駟3wyoFquu\~;E4/Ȁ@ZHO `aXӑߏƍۧE=7n4=`eYtu{#PY!^/~Ӕ $n @7'srfrϟ/644vmީ4l[`nyL&V&cq3%908LfPFE]uP]W6p(Ĩib4I %WV5MDTBٸIIB\ 'jPjjj 7{UWqڱ/4aieq#nDl]iRfmx/:@ [[[J;8by4UEJj(TU US NI$I߻O-I.#_'LNI_@vKR)͔XҀ OHh&,.YG۶jM{ƍ>dklFW:zX"GR3`$XLHӑhIUX-j<9$6BH,֥0bP9 /8xCV`O0˓s?lj+?" }zfaTH&'bر6OFGZu'&u}a2 GX1n{"77*!9ѐЌ Dn{]~?~iwQ5sᣪ2MSՊ @AX,FgK[7tX]PR b{_+nQYT ݰx^)iX,?Ȁ2U3 z0tpXZwwO}իŔ)Sί~qǎAHDcСPcƌ9dcD"PR3 *#G}W}98%7|s4cƌ˭[4sN:tgO\`m7tSMSYHܔ0 BH0EE[&I"M-kv>y3N!Dn"DR[;$%ǝhol u)$= ɵi Nu> H'O]&iZ+əgYK1nI}Q(L&7͛7'￶v!H$w;}ٗ3_|}WzT%aC$II^V+H$tuTB vk2a^@ 9d'myyf%{i)m4m6U%d*p!ߏիWszѯw׍#oʞИa兣ݒAK2ZHhiEyHs(DsBMԾಾ7ti>tK)yN<}D71(%# y9@BHZ~6\ )vJ>eLq֣R,X:~fݽibR[[ѓN:YVVr8RjjrڱiO KJǻX,5D=t{vO?桇 83m[8-D8Q8l`_x)REQ ‘pmB2?kR )H[ m~?V$ Lp0iŋ7KX{uu#osA$!i?T\3XҔIxgm<|ቿ844M:UC(a".f,5(rn3k~w}=?,lqN;7{}6d]lE 2/g lxjG('W΋nۙH0 hR󱪪*@46VUW$J(L:7!D|> /tymWU2rhG=oR8V B"fH?cg]u/媪w5)Br99!PJ8M.=\{!T!fjٹuMIPmZJKK=v?p@x=tGܶ~ɓ'>x`ɳf;ڠ\˙ǟz!Nf0t( ƄSJNnmUrI{;#oI#IDAT5FՔrtg_vWH9$D%'%cg,췑CAD۝6j#FHʟ?*RaGdf@'GsNjuЛÑdՆlMm/IOL.dz Iι x")Tƚ/í=˞ztf;4 aV!"bϕ2tYZMӦ{,c.#&5Q~iY^8806dS<Cz$XŇ6cq? E!Bsvر02<K74X,s;wͽ:\ w! @{{;),,iPJe4Eww7:{BJ*TœO^"J?Uu|W$-XD[4Jp$K-:3HV3MLqƘ}iK$j<3 -/]2y{1YGjٟV\U@衶$EJ qfH` !"eT 6{_.i_]{-x\x)!s6:i{zzODb[Z}IWN9uܹSO@˅}գ'Y`rݪ\ſ'1BVB6n|F25[3IHXOLLDp E,U?KHS%`LHqdBo՟_V06’&/Gꪨ/]?<oΥTZD'u睒*.P9t8T(bTuugRlv&SLqytL8nB9m_C$OCFOJ%@:[:"upa)V-w]dB̠EB ?*[h.5@KBq cDpP,:𤪪* HUQ7yX+@DH-x~?>Wzʫٶ'fPנ6y1C Vu/d;'0+*VUfiܐ!Cb7f/7Զe[l/1BUjժpꩧvlٲZz tV3 a X MӞKoy]]ݵk㊢TTT%&i"wXht}6=&G/9'EZK&( = .Z%AssϹ]Vk(JȱL,BHDJI~hAMIq] n@ԤKvY#Aڳ^=*^ 46qX2Hcn-OK^RSS~sϽ6++gw/>@655-mmmkpG};OBWXݎD"3x'~0XޓOG|džJF"XIqCIpjrsF@ڸˠ6mZ#,ޛ{4hod]]yfOQ [)C|TON3}'>OO]MO>Z@ɫ30{ O?cQ?h4%=Hu@]f,]üPY_Jf ߰/V?(>h~Ru>;lNJ)ɗ>xX?2!כ:{N|uu#9/)$w .] &|&3fvܺMR0nj2~" *Q 7}3/j֞%+067,+۰2. m(e(c\c'dơ,Zz ͔f6(߁1rL9`֝Rp]˓RD4f(zw@@_ڼG z[onk1]\6GF_p)o7oyag9\K&ly%~ ğ C}FFhm+2PZ'`nLI/\(R<˙j}AKaXa%EaЌnll$!~{$B0.S,W{=Vc.ͥ$dIDz㩬3p]UkX˪!<*Iߣ[O@em9?iMA@|aBȺ:ra饗*Tf&)K/tOq}e_ .Dmm# eee24#ݺttU4{i&;:zQ݃T2VƤ, wǭEVF,Sk%*zpۼ^fgbRX5>DDN}ܚ.J@M)=2L,At322Fpxu{?1}W9d2)TUivv< >vx3UO2T]ן1TU !bad7ި?s=<:4CJ4 =駟 2+d] + ԝ9N$|SL,-x~  {>YWW/<<' $~/\"#zI'sX$iHI)ɪ ٬T8]ӕ0W@݄yǵ Ym ΅B 22UQ UZL-/k+L>}( $i׿ 'Ol'!D!!͛7d\'(;Ftvpq-[y*808 *a}4o`sz u IS[Lo''MD2{LV_xxpdl446Ϭ'jٹsxGwx\jQ\"-}>k_:ovE$3rkvF~N7)%sgN./)̴o/v䘞oQv]pY;2 <Ы?;(K~64mE봦ت#-J-z!.{D2QfzuӪ/VN-h3=Cwe?($Ͽ\MFOu75(qlEK-xvQJinꫯ>W{}FSNbocz3kY{КUY 9wǎ渢IW\ҥ?҇t^:9/FO ZGN}=.&Y2ih8r 2?S u5)yHm)!-$}}i,|_|:+kRWWGe0(Rc5C>?A׹/7ytg;o77lxe]ln.ҥK6uSFV`s9w644(}.Zqs|]ruf~WΛ5J +V1gΜG2s ^89+[";|/ޞ;}4|姉5`՝L'~\2/~fAs>SDU+yW8޶nݺO>doEEEQii韅H !^۰a##{_!GkH_cVi<~_HG~>DIwWU'^90/"jjf3moHv~gl]FYzOV/zrBUٞ{K**":wh& kt,LV'6J'%M͙۷>31}^jOzԿב3~s,@`~~MvwIAI(*"ܕصMe2_#R!}0}])"޾܃ASHgɋ7Mr_㲱 5$mG o'o7i{^(Ia&{5b!xp8X,LӴ=ʢ뮻.׿򳲲nXU=hZaF"Gϟ̳ӦM{1''R~}m-,,-++zi`_&L(,,C#6lzfW^3\ӭV'?[A/_?0=H#g>@nJUUދgdi^9CJ%ħ[̡C+]Ίu]=]:@ g'NME#{g93ϥ8&_GrVEbLtֿZGugy >).j/DK׿uťZ^Gc._SCXW뭔`n|~u{YNt#5gp%XULj9H:+Yfd {..KX(Ŀ4?z(/:<&DsKXiRuYcF2:̏gm\ *[Geve3֮ة% O[-s,?of[U6%ZV\|,))rŊ@j('O[`Қhw2ran1h[+NJӊ\P4x{fߌ;e:hlNDR`Ă f6_<0kPLtСC£>: uuuG}tq/ :TΠ^uaժUd˖-g֞w0ہ₮08q>СCBj'Ư?JDYƼ6Rq0 sg~--h i,T%ŏH$@>mU4|`h)&[IROʵ$B`)U|2;G0"m(Scb!xRMM烏x&l ؼ׌% 6(Ky i^ QBn+T .{?PJlS]U(Yَ.,]~;TU=n-6:p8ɯښtaMQQ4'`Y__?11=555ydrAAA/))CsN>}LbDH)Enn.pmVV} bኢH$oI-9v!%@ 3=jԠk~Y~?nwj|ԨQp+/̝;wC-ޞzzz>zoz~~O¾}tc#H/];.-..dQ T4 !(*͘Jj_^8L ~! d3ޙF猷y$Ui4>r.3V2M$QHZ^B^5iUw> HF$c|O97[LV@I6aCWXY5z…u^k+>DW6XԩA9v-{iCf O~AyjM2zʆJ\HV+E cL߻woΧ~:g͚GvƔM'8ZMf `'L|2+dr QM99 g-٠ص+ " ޾#@7{6'y5GcO!9|Մ"^wכdW2/=}3Ǿ+u'FK%/8;B.RKުR@,ѥ [ݼsj?'9R%L&+D؜eRZZw_v3uaQCu8҆ʬG.]Piܳ&U^#㶰; .CؔL YvK̉j{pتyR9 оst}@ ÿ{(Eif>pAD>|Tq-u YSKށunUAʤ)ntɪt]J) ›b¥b(uz=ݑث= 4!YYY&L0d'|o>_^~#;;{9X|s/_^7mڴ#FpJ+.>+m݌5/{mi9jҥm_߆@IٌaK_(3L`?}m-W]oPcNefo<ߖunj7j˯2*OL;vju#_}"HvטB+Y3nअuud!l{Ff^y,^QXRwycUVLꏏmu]wM:_9rX0:G&Df1G#1yco|8oCWp$q!"QER*TO!mF!ب|PÆB" @tG@&;U4`h5-_JcQ1xboF@MZV`IBSNڰ|!+ $i:ᓂp@rS`?#"ю@%J̫`?EIñ`d,:0!44(1oJ;"߭Cg{L> Xl(H7]]]`?9\/h2O b0"M]51" En^DrRX3;Cd40“/hU8J16cotw^IM1rb4|FV־>Y[[_Zʯ+2Tv71oހ6AcS{_d'eB;Zw r z;ׄVդ ˵SJS/  R3B)AGXI6ˇ9)i1{5L2 %(ӏq|$d (BR UN"!(؊Vբ22HMc㫩r Mv?PW&'궱ՋƖ"mO;ؓLFT*gR'zic%Ɩ-^ĉ0Mih\2 f9ʨ,qbB86¹$RJ4%9R\FF+DI*27! kѸU[[kB\1F$ RwVnyg,̛^:bӿzY626Wq3֬Ǫ.cy5~3n1~wS Hعu0%gΜ~2F?'|ʸ?z#2󏔒x`fmmmG=s!woS4~Ԝq0"jJn|9hŽ#jXk jk<T́YO5k5u?vtOg[XU Hx޽urD5P }zi6~`Zxwg.L-   n V\4xr;ůhI%Ҭx.t`` tI݌Z-6߬yXB gXdt)=,*O<+&*0V&ez6kլS)AKGYM;.s֭[aZSe%-bX24? Tn \P݅|e?BUŅP+P鮡BNQd+]܀ VpnH wbvCnx#9CVimr˥@VimٜB dz`s˪w~Q__.9-BMe]"?wl۶'Ƀԭ^jkiϐ*c*pmG m4ȟ uf!z A^!DEWücr)^g8&߶չGV脬V7FMTqq x__T45cy''%ֆ-}=ӏ*)uLLw 'gUD~F! Hw.& 5aCt>IC4+zwbޠ\:,wz;w +^<)aurL9zbA־hN'tɒ%7eSF<4oi<9f,=96|g=o/T߯hx?LuYbR> ^֎N N(DD %ss \͜ #йE*uzb\gq؀C9!ΚX7)`a,#0MLBE-ɠ"m:r Emch5 -$Ӻ_rn<0ĘH4LnW\:j4ֳq!q5ive).*Sh"Pc+Jۡ-=Y N+7`)iJsʥqOk ~KL] DUlgeAK ^v)wa@q," B)Rʗ !;&LpcbPw&L`W_}384- y㉑]4_9ϣ%pp?ո =d M3'M4r<3a„X,fRJBcrk׮BdCCY55^mn9]N)MEQ4EQew/ kjzA6g@I!li]\tta JNJ 5Đ=c%%<O~!*a#8ղFAAFsM6%.ELȝ+o2J0qD@X@sVDS̈́yԽҼϫlbXRsf0hc5 ܣac0[DJ0` S Bmn/yru&۲B'tj@Ԯp!kk\=%dIx,\μ?7}mӒ0.RJ8{ѢECnƟV|J,[PcJv7q@ OA JawcE%kM";x$HԦv_~ywp˾^$e= oah#Ix;B4>4ǧT;wo}Y EopBŲF U9|8!Tz39-Eyҟ]O/ :,Y5$w ?,GqFtkT Q(7$+A_૪pj3%Ϸ[-g(*qH?EE1!@w:*$з~%P"lrf4^utj] 4-R1%/,V@@_$R3=c9qzK4V 4bUEgwPEQ6.g<\HB@nkӦ \,=huz osίlJk2.JQ =m|ݞ"Ҵ祐 ![ZP( HBcM5jr˖-lٲehkkCYY~aȐ!?0ۇhmmEII .6i$9jԨ9=$B)%%g9ѻ#dD |Uȿ̟e;u-c P,% cѵ_lkm~YWWXvL&atl} [ر}AdR"777)2_@o-~'v"nB(s:gݳtwEW`PK}ʄ(lXF%^y#9]gO4\Rqs!FP !wLCsLSCH&>o/b}Y~ի:6[I1Blgqƙ---ڵkϘ1cNMWL>d`P*2Κ={vLz &ȷ7łזO@ݱ{@&C]J nЫƳ`xÓrdр=0>=MD|ɵHP8o?p[ @D D(9˃@Sݙn\_xͶݜ1;(eRqC ZH|T]]MjQ˗}cӱN]I)1c$^>XOv۝D"h3LڜHJJb0CIf͚E !G}t} +`(s90uŊ_x;YyynXuoJS~o79LAem 䍙( ǏGeN@c&Dt)M B=v:2:8,>~dzʈ2E +:R: fOwj5JlTKxEa @=7kmYeF1  2j@ ;0x0? (2bwkaQURop0V UuR6`%h nH U1MCBP0Ϳ .=!VJ5AH)1cơ ł.[#0E,Jfb)c֭hnn /2nömrԄuG3fP***eYл@v֌Nmva\,qX98$7%9Yw -t#~{ A]4$qq.`:88xvh4p`X@)#MULb2:SJ cR\BL)Ӌ _h .MѾF2 '\|^f" t.+*ܔexJ8e]{H0iu`+:ePa®$ 3C;pyx]!1^b >̍56*|ĈUPPP{|(++; Hc4([B8NRVVvjKKK1… Sy AgMho唅t"a=?vW6eoe/y ! &` q @ dcɔfbʝ#(ywR7"m^+d)dA*{!b#W gͼQ(񣠎k&]ʧgW{S- p!B}HPA\ R?"CD*"aHjulXƇӚ ,D)h}ô7U͆>qL<Fvl<:wDnb3tiƺ9=#: z%Yxrum=tsms<9ЭVP0ynI$nsp\4_=tQhp)_=x Y*,H߾O?=#,h)@ĚCm!))@/]سК!lIނ=e T4La\k.K) vd@g_t0ri;#G#G"}?Orh?}E\gJmggg ?#z 1* Ӄ.*SWWWH)H)i}}=3(>or=L7@3sJGS,6;#}4`0􄩖\J !)Bp0rŧG?\e _}!s, lpMU]V^9Gu O<f@$ Ղ'm&9 bpYmSUsX6COHscB%aTBvyF >gXk돆سHB:x.啐0LT%  loӢɛz :~M (K (˦5Q4D!{Ok(]0z($9@u5+ RZZ:;RdeeǢEw^|g&a,?3ݻ-ߏ,PJx<%֮_ǣu` v 69- nǓfܞ_ȳ77naD0@^H&irhБ բBCڱx }> s&q!._`:#I$@S@*+sBJ XT)5#&{ o5֧SW@*}'#Mp~0qZ gES#EeGwHA&Z  0[a1| |_=AFL&I4a !x<ΓɤiuCm@2dӮ]K)UYnDc"4Ih*# d(.5!&C|]{$˼sto"c [ q\Nf 12e֣g$-Пq8^@χ)aFٷ^Hķz3)R9-]PŠ)Ğ ijxr YM O$8%^"Wm)@e5-FT۲Xi8ed+$!XUb _:eC@E`ʨW*/b%;F^٣h=od@~#(UR O U&aXD}B,@$a&9Jy=Z. [1bԆsNiT\CZ#@ pZ,b!8C3qh!9/^ oV!8Ox0~΋ah!V,< :]אScHa ifD#4M ),Gq P#)0 rӍ7>wh{Z`kh_n5_…D" !<Q[[~iljWβ.o5MQn[6}ŶZtq};J a )S0tY9Oh="|ؔ~[̤XqMh&'+H(ZwPJ,xjQ]A㚠X NU8|s !v=OUBUU nۃtM\w{ੲ9^ A%*>,*;bQ$!D6 J[nJ024n.km"-EZTv,\tEoN'ERJXSMMM2B|ghjjc VBX-p8Ƿp}_|38pتUA`̘18Sq'w ܽ{7q'SOŘ1cdժU(,,vgdJ|zJw7禀 S@(ޒRxTKsRK KW gqƸ>fq`0ay]`X0{8sP]U4P(X63ߢj'ֹy[g/vpQ)E 4`oqYbxxpQhu)jIoRI]F 1#"$B\ !D eI*qh.H@JQj؆1& !NPUPHH+G,;'rJ){nҥɅ ZDk5g{Wc2֚rn!Fѥ 4qT i;R! 7bf/*͏V)A;d IX$+k#L {{{!z1;j%mHX47to[߿."%3p73bHA@= RP8-y } RK88_/nF5](aAs Bz@z Y@QМ p# |ʁou I (,<PxIDDFJ_glf]#jx֬7ߍa9|RмH$dwwyӑ(!Dn?E6B%LS"8A(Z9`"n[SuCƩK0}sP4BҥKO1c`,Q`t3f\t !b*Dj$Hi&(@kA9GdĈgo޼m۶}{ ~/¨~QHGI~uu=a;?7Z_nZlojϿJgado$M))AbW$ṭ e$TsYUuډJLTzx`lyV/c˫8*gC!&rvⲪj8`mo_0Ko{X~лNj")!pbJn9sy̛aHF [Z`_Bs!irb09$r])4tRPCP&s] QM@49BEÁK/]5k[owߡ ~-֯_[ok֬jjE(mIJ-K֭[A)%Xz5v!s!vގիW:>~$[nYSN-S ;{6S C\JbrCCBH%bxIqw7nI׎ !L.Xp5---pP˖-î0r(pҝ"*11r8vڅe^p:hiiAR{uN|Ŏ@e߷ʬ=Mcnikˆ MvC3wK|uH2 3CHpi$I@T7%`:,l8:\^(#)9Cc^80d kTuظqcB+8FH$h4n[ݵk׮+W.Jo cիͭ7sĘ)aQ$D,BBbB*1¸dJ8+ڃ0-iD^F&R 8`m P!(^o pGA! S+Դ #ԑI4@//9Z'`=!>$$|!~\1'B9m.>bXJ!+i-rz@rA@KI@!Yx0v`MR_v"1KH&!"adnX/b"8uk|:P[kUiTRJ2{gUTU9֯B$EQ*TURJ'|`@ lMndcT|K&N :ˆawcv76A1l&N|KFH&87{ Ps/V/[lF_ם}ɋvA1%`IS=ܹϟK׹$\Lѥ[ȱc+ gX 2 J6Enp#Htj"' fwsB7<6%* Gl? 6mJlس9q_0.KX-Ȋ򊛗}5Yn i%4`_7يA7dyxW6% )`qF@szA} 8 (`2S F BCĞѧXx3z&!vDĤ] %B¶"C?x$8 Mm޳l ]fjlW/gϦO׌uj>p3n M @i*(P0Ƥi(|?wS4 Hj^Zx G$l;-|7vÈ ̻i!^Zx, n@4&Ήl,@ 3'򜜜iRJK?{իA)HBK$A)իq]wG__R;E~]]=s^ؼy`0c , I@)Egg'88q"rPH bرj$1&Lp<"})OUpTœae'f7rKPmVFw|4u'}oEJ\rSHqPJե2(7$I]' $&>x{+}:xﭭ @@r,rI]X& LBcɄ(cLQUP5|ij۾ۆ$י\w6$~U4|јUE1(Ca~߲?L|>F!uu BaK]bp3QoNJ-mO6j?8: 8\fZnrIX]]j~A)ͧB!$N>d7ܹs Fh4P(sOF2\2ƠjfB4Ȓd3DZX Gɓg39&jaĩŅGfJ@l YEE5{T54x=֔'mIC'1-ɣ4)P=‹.0~x6fMgaMQw;bV]bbm6)$6lkݺuhTl68N躎x6_L.` IP!pX(]We+.9~CAwqMRRR!DBH&:Ϙl?D~~>4 Pd2NGGG{8zꩮe˖H$B, bv;?bK.!^z)N?tvmD`ِH$p8䩧Jp#C4R^2՝ I}sД}[(L0)qB1RyB'!$6l?V~A1ʜ9'pW#HCݭ( p饗W^\۝g6}8c,Mw2>gaGiA ݨX#cmt 1.CR%9}9S ȑ#Bil$J nWwѻjժ?/.^oI>OjBpNzt) C@Ub}Q7`GDʮZ0suKwOQ6B'Xx({<@ W4tӮPߌ8Jn _W[.@.ttlVd#nrJ$Dt/i8 `̓?ج57\O d@PC0rD0$ R.ޠ$뮶֋k']FIjGxh8|D! Ω z,*v 1ȱG!©'+W BMuF#2B35d 49}By`Q ED [o}ԩiݭ@Q";;a >g&iii+u2gPYcii!gPGXJR ּ$(c0 4U{,rG& HI~PetK)@&'0JF$\# عnQB(Tl`J)]Z0y]BX]r{ݦs)A$Y,#ƣ j SKfts!?2M^k &0@\Soj.|jjHi%c ?t<@!%RN}뺾z4M l6lڴ xuuuƞ={0a$I`0h꺾nn wwwO>}:3f bzPU-l*㫝;!%pCbcСx t:t:Eww 0&) U`444){W*2T|ֶn٥ cfͭknl$Y2gǎرc~ /38db1*Lya / L4 0 YYYf(R^|E;}ӦM~.Jg2}͓iM+-ٖf:uW7H3OΛ5s|Xn~o $F 1Q-PA"D$]7e0AUy+ k#]/m{/_~q|~H$LBJs׮]ر{kI{' |F)O8ϛ_z!Q m8~bٝ9]'"Y1پb]z`$VmРAJ"RۋP( M~+Rחhoo oVd-GAgo?*+26`+ J,s bR 7DH nvPuPt LtbQ:qBj`p*"mH2)!e@ʽ_yLG4ngQVТ‚JKJ.̶g\YDR J"LdwvvGE.n"7">,B`} 9v5)3G= UlCKJ3!ɹ(D2|i[/.L&BnGCCƌ'bҤIRjZFJI~駷mvcee0 nXX8NN5yM8-F Vmق/݇Zdsٞ={:::NQ?ӛoذoVTTlڵd)xo UUXr%&L =߸qdɒ+WsB~߰@ COtSXpLcrrE%Wԛ"h>6w#}J  &OVbgi/)Tp-!nnum"!LUQưbY^{Vr1OQGvSO<I}w^ɐ!D^{_Y3H$/عY~WͩvtuAtOg$rZ)c,ኢ:?N#WK3+NWŦ7a$LHHw*"flQyuVp/ߠ}\[\!%h$ ("d}wwYb@-)Oxc-/lJ9}wR>T݋7G}/[I.Dpf#eȥy__罽l6A=^x!LkBUU(")jvy~adrI{rɃ+6d|A;z~cO JxIRc7)L܎7m=EƲ>u⧟~) Amm-ꪫ6L0aR,3cJ@_\v^Bt[lx'޻=Loƍ{sΊIww7O$vs$X\.}o'Oܼw^ux<\UA3g\xEM?D8^2Oʏ &+CfRU?EWTT;Jhxsr\rcUwa OO-s4Cj "K] xWp/͟?_Yp>g/)#ц@*Ӟ$¤fB5;'tio>:'*>ؤ11rTG_VUEfx<YIw/)|EGZHYv1o/K.c#O0rYuA$@0$ꏦi &75}ѥϸ{w\ O'&@ cDI{ɧ䊊)ߣK玆 F'J S!S3LcIl{/•m1p38.ekvFڎRd=on+fE[qCVmqOt.WzzCsOIvEQC! !qܹ&QJȄ}iӦ]ΈZ7kꓪD3O@xd0*@& Qa,ͫcjG=}I[`~ywA-&hww7p:l5#)1&Inll43/^{ ?iii)##~XV ==hf+++9s̿y=28;:wncu+I .`ѕ1J@RvO=7w=(Kw8L:y$jCh AqN '0-w@L;9c7n,w>9EZC??d!p휫^=m浒$ae/&ihp y]-KBըƠ̰d˴"^`*JDmsHcTYͪ iw-Zך|ӓ^0LvIz]0͇dYF0D,+kk].}5;;HsBUZ1 Ci>l5rKu_4pĀUYi>c&Cz]%%%?l!(6 .X&n^u#vHXbw?.]zߖ-[k{8o"A!Q"STeYmúM.VV6^tʔ5-Ea}1CG, 5é2W( UuĢVV|g{I WM5Ѭ rYې8ӻF{{yCCo$[ S&864_7'ܵ:Wʶ7>w13pP㺮k0ƈaW;Pr9a߾]w]| J,'YRM(ўz(/wIAArR/!TrK^Y @6:|Ⱦɷw^.!OT-hYR%>ťc/8 <k|_JCFJ)-^|ř 4??9BB)*`X:=^wH%feOvȦ6zj#tkjHdX,= 9fv(f5Ҟ"w-:_~f&蛭ڋe[_[[`޼yxT(:N]v=if>0zyTVVKtLre+K3-gVIj)Ud"T"h]T^3bUatx;%9|oJ $9uh ǣjበy]XRbAH yFӌp ǟ\pI"A<z97-"T.pjO5m^kyɊ9NUUE(EHB랻7{hz!T !7u]Bn !+"ȇW\q#y{;38--ff=r&@oBWo"Phq[[[e]H![n W,8x4XǛo/Wv@x xf2(2unpt#ZKWηW~A{=8999ǍO]>|dɦM6?Qr@DnBʴd/s:=#j0dî[kjz6jԘm9]`Z"Jj~^ qGU%n!h…R R7iWCjv!tJ zh{ȣ>:4??l6HMMV^O?!a6ee .GWS(mP'M]dA`"et:>_Xw]%ɟzaÆ]fXNUe$II0N]wvG jꫯ\9996 UUU^p8T9V7L)ž};wGS df@1(f,2WNMpn΄w#yK;ct<*yd gTܘy; BbNpݍ_ Ya?.cD@ >>*]6ey:&rB4! F!Q` cMu$Q;}嗓EIsuv^1zw$$$h2&BPIJq Bty+|O,[~K{Ww}![ 94_WМ֮κ-۫x{ Y NRkZ,ɺӦWOA"(,,2*yyyYrСCބc UUa2ޏZ.v]<~w*זϞ\ /rbɐe a[瞮cwO?}ѲeRc4Mca.K W|89z%YV~*//=ëkZvtƟ |q,Ѩwwz߱mI[77x"n^$iO_/{,))M_Td墽YSNag+]d }9aNڒKz%ܽ2+믿|bͅjgvUۗ UnwD#InЪ"yZ6·bPX?UlnPAk/A M%D}G獝iYknY?Nf]垊.7~u`FM{F^1XzL)Mfl$u <_3N`HM7|pvLWw4mG<_ݗxLyg~H>^:SeT+`%%rў\.smII<℣\|kSo._:rI}!$ݴWu@%vKzۣܣ`=_UtBȻ'9xg'- ?3ydHz$@#7qJχw'r Az~& r!L.q/]B*q/볟*=--՟y}? M8 R_.(7=_5kVyGyB X yٲ2z{e+o=|u?}w~=~[`kۙޫ¯8S~>{qM%%D>r gO9S~CGpBxW8wqldY))"P2%NgaϞK'UI8jQo+$ (,4=U^r̔G$9{h<?;o:3n;(Lq'>8ι/~b u}$7WK쿝Y'vf)/N鄗O({~qWbBL~R7wm௑˥ntŏmg/o/3mW7* ފҞPU6c/З3Cͽ*=.rH]Gڏ=?)eJ'0.mYS?{qa+᫯TWW_.vݲO-7q&Sb\himE֭D:.1iCҟu6@]wԷy2p A=(DpQ6$$'vw7k682b=uYYW$\u{o;Gг&G#/8W$/u6vX=g)Η6Z BK$۩F>lVΧ>_|Xz<<#?b(KD j{5>[wzy܈<1<nPŤ<].v VuQx ҄Ǝi 6'n?rij|"bwqjr=mƍ.șxd HVAL$DWn_p$̎=w\`E"%15mM_rIr/wsIUEE!Bq޿g$6 #ls?Bm}u ]`=OG_n7-xĴ}-wud_={[n߽7^M`?I|]oݱ`O΂`LdP={fGIB(IΎkO?^MwXD Z8ȰIT/i*oܾӣ%g~%`:!ǭ}VdO?ЩS>z?0c1B+**RoXΥ{OS-7zs-,62c2$Dӧ[V?~]~?JTX|%Y~|zqHNeHkkf}~=v!oon8{XX7(H4''/*%䅞xfWhdHLÆF‘][l IYY;Th$Zl1 ]׎׭}v$\<5+rf%N-ov-$< 35$ ׳7o<Ja7l(*Cx!LZ/Vpa ].xX7fG(6bD$yxBF3z9Ty<>w0)Y@@Q9Io=U n7OzzܿV+1u4$?C{?Гaޛt0Y盧[367Otc~\t*+{~eeeɯG+vF[j"BZT;EB$i0in,ϺK xɯe7!='Ng%IFʷ\nw\T U<$$Qw:f̘/ӧ|;&ISm~yϻ';--3"uv\^S^_-V6_[%|C zmz#&ݐDl ǥ a̯<]!U+;}ϔ)м?-~̚m ?._=Gb[<e{]C8b(VpSy驉 D1tvijz?6f_e %(-eX]| 8.DsLCN_uWꫯNC6$M+N5l^ەe)˷ !DA-_^&uܼŃ 7{iM?*eȋ؆?)zۤ!M sЦPL0cOw!{VWOpг=5yLcB$m\ [3*ViO쾬-6Cd%Kx,I =-VrToWg= Q{6y.y-C7 ٷ'(H9[nAO|<`SdϵEdSM<[Z_{,^ELJ%?xN P3~K2B7ߏ3IݴSI<{xMivx9 g*+d;gMQ0Pe1]"{=^㩫&Mw9w|UI&4_Yyt8Jx降iQvƕ [O7o۹[쓢Mx]._M \z7=cЏO:fjAaxi9 . qĚrSG5q-,`9x%(/~ЈO,Fϳ Hp/럑x~nidfo{흓[OYv֞IMRtWo_|1sܸqGZZZ;?!CmBF,#:i?}e[MQhkG87!:&!G$1jaNBHWO<7/_ /Fw5' N%&m0:O ǀ҅~=vM`kNL[u)g'Yr+7bb:`;HY $1#A24D mQ  vSp)RG|D|>z;i~+'ir7)LV-ӯ k_ !w8 jT;`uͺ7E"nV-mq3&G&JIbjꢷݸQi|]ځ,#wꄋ9Aߓ7ݟ $Apz)O hR=1+طoN1 CJ $|‹R{=߯@ 3O; yPeYb4 )7eGq͖*M|s뎮[eqK1nC98׈̶i8c A=beÅT>ddz#?[n3ON0jNd%"RW<& U⍍l]msTDD0[}֫{3uy9m^_n`O C%mQ| {"DyGZ>^M%12|]wd_d1Fli|FM\xM\+⺛FO@mW7_XL M׻ 2/zu9ϭ3;nH$2Ign 2Beg4Lt^pij%6XRJXLM""l>–6,-1)8„{Rd{38+~q5y  LMR33.ijjrg^A9 BrH"5# u:Ko_"z;z,直ܛx nHĨkU-%݇+cܢG߸ˤ<ĐoKgZGP)`Q\8nqD D0.yݗ ӿ>l{~ie$CQZH,3lX!HEYٯ(+ϴ2!PO$rt]Nq<^в322. "Gznn.~ HHP?## Jwwwj&,*8۳?i8oQ~&JF1`;{#$gv㫮.rzY3KJL>3)CpBw]cmҶf蠾7mIV,!FeI4,K,L)erPRƔ`ٞ kBذHY3,SLf8ggPS"ްB45t qpIy*螽{0mT|W-lV7:# D"Ѱ Sƕ{@ g˥ noz#:T =)NCHBOKtysy1kl c L25j&+ ٰ/MNIg+<24ٛqW wMMFj'RoK!x%Pљ419bV)g}k=$Me ˀρNQ(rtªU=M N/<q\_s^>}naU.$/!wqpFǛ7u\qyدBnAQq,x*g|Y4~$2 tvv#;/%x@䣎m|[D{֍z`8GawvA=nK9'QvUk"`Lٱʙ( :S_k0+p/J ~lX8)SFqb_#"۴AEݷp|ldo]|!,pRF|t{|IiiiV(Rww7233Go!HNNF,`PٳzA-faؔA ITbF$M 䈿C0;lRI"֭E[ kyOjCf;n ):7N>i}B?CnT ޏJKщ)uzχ [!T,D_?<1fh4B8@ (> PJ8&F:uA@ ֿbn-ƖAL( zg77 > C$h!Q $8_&p]eNJwSEv,^|[7ۅ0b) YN$!#|_9$cU$< o٧L8jA HH>s/ ~~OV@zx]0=jŴt TE4%KiC^lvΈg>JX:g !S]f Ly,Gww7Q-f*J%2NKܿ(LL=2~J7}a>#&'WkʳχpđF2  OpScMM"T,{w1HL^{`Ų ޛV,J7-ͤ7|Xr G[3:lOB)!C9YH5,D~SItm4ZͰ6bvuRRÎꦅ_P-M.=Ay:C_www4`^lLl"[7 b昅ŲOҾ-rtfoOCx쵂ϴ6$gz&bG]c3KIa]7AM9/0iLc<@< H~7|}Y?􏓊J~odJc!^Nx1&UN\ZE._ T\1 >(BlJ䊲Hyx'VSP0̢xe4S=7#d|-NyҼM&Dy%!cW`>)i>!qrI M)MM; +h&X\ngz>xg,AJF??=x!=ʷߓkϲ䷲,r"B UJxr UpTh_Y=qcBlȅNeWK}SӑJZzAOj看h4*0(ϗ0P__H$P6饗f@'>:ߌ̴{COm&'PW33z{l(JN3s’kgNx0?gC {PS֧1T-z Ǎ] !>/lj'wذ~ hñ}{k_^}H6gF'_g+8 f`V]!&T8.&D0t 7gt":*c b2-+(cp˟tHD1BfbM!O5{w>'fYU2a{sD%h\Y6qI 6~3N B$)|׿ ۰e%[tJa;' fUdd2j2SȂApî@R茒bmx6%e-Ý{2 Z߮"D"D\==pW9$ooG}ĭ<ܶ)\xxI3+Njfߎ_x霨GG%clIb y ً$8Z2XIQxDϣ:iWC^5mɃZ SMkGK!.f<4zJ=(ϸpiŁXށp ٤!*bfR=Qɡi h@B f\6ww$&̎d9PSҬ ͙ ҳoڹjɷu䍸׋}S6#Ax+.*+RQlϐd*_l94m{bjRl   ''J!qOWOђv N՝y{eYOm>[,1k3k]1үKp2U  GZrtṑ|kʅT߸aȮ =3 T-'XD *t=B%JF< *%8D!sx/`Nx4@ͧ9qd|ɪ\%G_n (܂c?KJJ$W}1W|% Ee9Ģ H0^<|]sNBR'Өjr,2mk[0Rx%q|qxw ay0R[e(~Ynl)MNf Ʉ~ٳb10 3 z" ,555PVV&r6dKLpXhUL#QIM I ՙ`6y\(as$'B5X>x~#ƅ].!ƻwqnkf&S[ꟑF#gns>!꿧W12ͣ]uۂN, 6 'DUJ[9v8X֯D|WrQqcNIOI迩>Ⱥ_~I*)GsKv5@p'YUUH6YzrBƜ[>:Dد+\:%1P %Y# PH"AE@ IB;$j)];kwpX'|.! oCr;rB\eɈ᧴߱z{9yؐ&:@ 胖cyHD H2(py߯QUv/-$RN#wP1#NL0on.rry Ԃ=;$%)'8i j+L* =^ՖH& {m[^v:do)؈{Fd$&,}gd\./x~v ^ͶJYQmN[fAE` I2YXvdIҏݳ^,<<ܱ1xԊ )9[nqjf*~}*ZH~.imNa3&uŶpN+Y Bp G"!4) Bv0*(l sT>Q4,hٵxqǯo]47i@lPAO0˦ĺVh,vhDVmΨY88W& maw$/e,V>+-d"zgo_~ Z_WÒ;wMfwc*6Jusr#.1!H.*{sm1pz01!ClPʉj5k2)97QI#exwzM0(08%JĪPbʰ(gΘWrqqnG֥_*=})錿DLDNtQL p¸  q(KϮyiKޡ&:%éhW 679HBqOfI(J^MAttP1oOܗq.8$f1F)bjR\vp0XIM~"}B1M~f"G?_2J kzdƀA1-쨾a̦w]vMx%^. &766bݺup:(..bA4>MMM3J)k;::n 6;p$0WTY.$ ] h18Tm݌C5׃DC"I :c(E ${:e*78` pY /? t H ]0"Qmݪqß~{Jي.(ή̲)|oGf[N> !ycS3KNO0q7ɒs! (i {|\?9-ո)˟d <Mhs(EDզغv $âJD =\ܷvIAtHj7YH=8D8CEHa~4V@`@X!_Xyb'EEALxGL)/*RëSDgd#Cn:-y2@5.߳ȉ\qܨ~c3r]Hp*ucš"ACZMC\p QعjþB;>BBPKJKKܭ{î`~:%iwtyUnۣN[Vʵe)4!eff=>>ĻZTjȀD$4aWP$8^}?G>d_,(Z`cN:CXq!fm<ԑwR#5}2r/P6yA㳽iR[? +Bh۶?ϼ\Ŀyv7GYeL]:  #!PDI*hKEC0rR!$CT'W2!MbmZ1wIzy%g6q37aX vD)ΝqG.M78MW4na8fZ|:kxowg~4.Fb{^ZY1ʳiw)WᣮškgG$s>Tqr?T6tɄ-dPdKCݤf5CFstOyykqvD50fR%@Dk fxL)]\wطf=5gi($4}M5.Y"X`c% b24!38cLCuU12^D%UּQfvY7᎗ZW~1s!8# #Pa0&i'8utYq "Ik84ځ'6lĉhƺ[ӯw4EVN@ !@%|Aoif[& okݲリF^$Z%ʬumJkyREQ\dgg#FT8ND"Bj"99aHCڲe\p7*$YH4f04豘H͆b6H8p$;ahoEwDheLB(@@)aJ+Hx("1=S9фD8`6+HKaB7 J%o}K]R"{`T,!@w>{ž]Y;{Df%ӜTsjQ~ 8FgS$qŰ]+?r鋄车gQYQ1ơ\vӅ(:n< ~0>qOKBUe@n(C K_U2?>,3MC8ALȶ ).;8}.6A;+DCJ&L.5CEiuj!.(9 cg`n^Bl|@R0G_QpI, 0$$ID(8LI($2 s %I3S奞 Do2%ԣ7.XpA>IoJtkH2 Rd6 J,v#3' ڎ럷jxC{klX"qSDD(R`fiRNdeXUJZIBRbԱRٹCZBge@Vv3ƈ)ɖPk~a>\}ЇҊ1|cQwDH46$ Ia TgrF?Nq{̹PwG3eԥjDJ3,ڱ1$G X̀s.DS^ D% VjGAA3&Аb mag1KdOf h}|cXRb-X1M.)ڿj|AYo r/$I/uz}+䪲 o [w @ ]&6v7Z@F75Y<zp]yP뭐az8m{!Jq,jl<Kl'6dMcAbjjKXH1ttIS`pUR-cL٢O>')%<%IIXcCqJJopɡ~姀bR9*,˵v뫎L[,%4`D3Y0"rҺ棪- xY xaq Ft|~cC۷0fa{zxѹNB8 dBi6qts m:}ԬD݈r!@{0RȔAPf#oM7~Be`t0mXmcz[0 3=ug^;!Z~n ƶmF1#;:B.1vm L? n:qDFSmY@+}]F n+)6V339D1vP݌np*% _8D $h!D%8,%߉fEŬ;ʭE^qQUJ6V:@kKI7O8lq#h 0h LB8Q@AOZ,$U8?&-C^tvQM/D͆vAssۼOk!trXP0?3zaI"kH)t l!U4-cİ97w1~y3MYrs fqUUFhvѦp[fIvڳgeYSp1P=@TdknIױ$/ճO3|'!'#Eᥒmϟ=5; es& &hB7 &qJwg?Jt$NZi5O[QaxT  ߿%Tt J0|$A#! q^u2Ȼ[^a]yy=ʖyl,* 8lY$Ե  .8iS[\Rq> \uX$It:t2N IVBwȂBg ف9(bF\Ǹ9]@`'>[1͙:B:<Ǵs Piɲ-?4*Y";:;PvatAI}{p?Nm?'%XQB? @(1kSZ?a%]N@=.WGJB:aoB z";6|([C6z6!1yoz!iBȻvK/}婧q,X .zMik0.(DŠ:ZCIVBi<qJ4( .(%јf* lRiC1ȒHî}-2 1]סid5CuY8f<l/-.뎾LL!И@ fLXZ'&`Կia@pSWֶIN6"B!BnS8M *߮ "&-q76nzv]6X5ٙ&`"I N hُDUB[[ۍԔN{d'zc߼qoBbPS]6Č3Ϲ[QսCm#1=m&]^!bwS{e&o#Ѩ$FLY4ђD+lV Lf__4d C9Hm_# H7{[ry-`1..)Qa@nafS$QL& XM kIL5$=!#ˉbUZKTjǖk*Lx hԻgm)eQI[-2D'7N<{0dl AE5Q%Q.b0! ^>3Gm;{?ӻv\.ҏ/:"VVخuDt 'ӦnV'HV2AH RNZ#k^%ri(~ցDQAe$"Kb:vkrw\-^XJki&kWqrk&98@4ej.Agk'$D NcFTp#ܿ6|;+)Y\)[Hgg09ܶ| qݹ4#"Lp!dގ_9zRUBbkf XSkKo9|ӅjVj;5$*D5Bk3.` @_nY;)ʉ 3 ݠ{rijSq8;q!IC>mʕ!~0@`瞻-x앆n\J(@WAm@%9.vu"bq9Luö=S<9)?e9 !Ҧ KD4tX 66_jśmfkmSJ Dc kbPPY=sO jǰ5 Sh1L2 '?eaU]֫ʁY휱tƘ aAlp9c 18bP_3+ ^UӉܝ7+Hf"v"3@s~D\A tM4cnsY& k=_2i~yYgLյܛԼ3Fb+pUe*;vf{2 U ᰿h3}(2&Zbx/=&NĘQѿ Mh8 lۂ 7yH(#1lX~(l=7W:)2߱Lr;d&Nl>dat R$pDc@L#8ԥT6KBW#:^v@^=iVj (`KKsȄ ;ي-:2 GE%*w]Xԃl} N}\yA]OR[OT+2 as L"#5l m%(FЃVUagzX~ٲcaJDhAmúMXɂ!yCpƌɤ ҆iZY%V}W/z^?.lOϘ_}JeWZo(/٤\篐|jˆaiRkB躎D$&&BQ#BӴ,EQ:t/38c\8@0 vw*z~+)F0 &(5BqD!nJJ=8PT9(dJn&HvN zS%f_oڒW$t.8:$J8&)B⋈qU"=80!*80 uf[W1|㾄}@oEElglc6Q0$KAqs619cl XX`L)Ư 9 ǠBH̍Ya"AQ Yn%ڍ'-;N%o9riK;oao}rhJ]&I+y'-/LڳTHI$6&_vo.XTOޑv8ÈUe)'KރvޅY5X̠j<5 "ETB@a26Eh:#m~0 ,&Θf';E2DKJRփ LC&4ԉfBb,I1C u `  `rՑ[{hZ} ȑdv_'!H!AfUj) WӒ;rkm{xgs/4-s&&8&ºۈ;c:Usj͗Vt~~E" E H \]>is.IKzG{90>TI/Iv-XB0+!vޚ;KK@ד?03WDLi1͠@uk# @Lb(vjZ#'4AˑFt7p|j! î]эBts^XM&(DO*) I\7tZʧw6dPnb>|!W hxx>9s b"dzqˇqwl2&%qYVC/u3[Dds0Ș1vCd, NbZD)o/,eZBvs-wd~[Z^.tQ3ퟮ]y\fT{hkEQ<ی|`0(c)NjnA=GR Az:qpKN%qw*/7{^cZ`Eyn> 9lww_Uct@@\ɌAG;)2:,x|\Jz֜t19t>隖o0W\1k.H}l]ae#k׮ۆ* !%Es.(n#"]׉aL!Fwɲ'V~nHͤcs&hL}RP8 !uC3)re \Rޥo{锐Mm@89aL*(qSĕT ŮXC𷒻޽'[n7]?M]$=N02&$X|EFxN/&dR:aRUc!C'8% Cv|ɛC?:ecRG4t%@+kZڰZ/rTP.Rۉ+`{PߘjVV<.I RJEB$AQ9)jmm6^=v1H$Y{N)f H HhQe)+3>4 N=ޣc̖z?qxEmS֮hȟ5֩ ߠFB$"#4h[&RO׭{;7 '\0J<0ł=mA2MaS%d `W f`pp=$2:;OmzBzk..ӞpNiLM&K&fhƾN氛%΢UE0A, ?NjmyTV&b<x@P,LӁbڪ+`FLcnbM`Q%zaՃkĝGC"@EozkB,G}Vѽpe+w-Sa\.~6ҧsS`T dցGS%~k O( IP$q]g\V=(MN?'V쉉i! \<` bBdQ=tBQ!av)Ca j&(C+B߁JR*#Xx  bJjn !; I0@%JICtL)Vmi #UgTgXM:q*rC%oF=6xY{r`]Qmg>|0KdbRz좞]ñy8 iC@ *1IYZO8kS2@xz=e ;F]|S3SǙ. m()EFR" l P,`-ݷ:\Cǘc&-֏@p3b⴦l?"EfRTSNq?~t1!%ϛ4 jXst`[^i p 3l:%[Wst AcW%3]۲B1Np74蒮 jp+czYhnCmI1F̣QKN~J}$+M֢m ˼h3kk3&%GILd10fML`>M a 94Ӫ닽M U"-~`)IB M8lT;c2i^xwqCu@K5'U%DF :h fU`K0@4 qX̀aSb}՝Q o]nZsSGoPsA^lnP̏c :}jS4; Zs@ x6QX!Adp V/$P*ϥ>4\1oQRV"Wgo*jݹc&.s vlC[(-ViASo)(]]4#fKdQ/  }q SqEs#i|Jz:)3STZ4Xs*4%/]kG'AJ!g8$0""XiHqX Z42l6!+|j}Kx Yj|KЈCͪw*єw%r.fXFqۮ+ р7$nPOBAgDc֩.cBR:a@bf7 a#&LKsX= u5%ǚ O!{'wEs/,X5Zgdİ[§ VtQ:r&\{yNj`Q]ǢΈC-!0C\(zFh|ΜTxځdS"`29q~RJZ?G=Y\wsCSǞ6`~y[+kZάti{7 ,D8OS{;,'0B`pCCÎ;?~]ge˖3fV,== $[vڠ8)'AEvB\oݾb~a*zt!~z Rr(V;BRBd̵**_a ;w.>~xڙΈfp! !(DHA{()`a% ]`WNy\H}^rs*8黻Uj"fHOM/&$ (h"p?҆Vۯ} í'yLaJeDVU]@0$D&02/7M7Df!"Do% ;Q>AҪӬ㋳Q,=+,B "QɖIxFf9tuJ|d\<2HOh䘲7Wf}9uTi`T}ڦyreى~C섢$Mvݏgz½{]LTN 7M.tLݤGNȪ4W"t 8٠i( QXG P"\.*{XP|ㄿ̏DX3h1]iG+-yˀN3؛fpT{uHAo}L*rʁ~mHa`342Iz4$GU6~t'<9z~W]_}ܠngYhR7TuZ/Ж#)JVN Mʖj/]&8QΜ9{=R5-==e|Gӡ/'A+sxV}p:t?过mo!ά+O & P8Aܫ2Q껃+o8J9MܢK&t(+Ȅ=G[ʲz>H "~7? 9'(qPm~,.gƷ=‡_U* ڑ9~/dm}rAi$2i3. q ـ+?9s{KRrF I]?6U)ܞkh?tቹecBkXmg/[݉o?Ny_XXx #l{M|%;@#Y;n)\I#D KrtIQb&µ$CSF4S-g^:ڧ>HY Wߊs&r|{cټ9픐f0^65!*3Z<7] fv]+7b?M"vvn+)B/srukqdjqfJ\ug1GOQx}Lʥ]>%%P'h-=7wG 9v抍s;q|KLADqP \SJX\!ߺ:X`E4L֖NfBbMLZF,Jg.Fa/oUJ4uRNW!2j֠[fR.X(Хrr=>4g`ZO?#o\67;r([TŅQ< ?lNH zW+FlG5фp&eqNhl)MQACD4:|ՇxQnWN.p3I΄kϙ8 -}a6j/q.v۪ýܳ(: zFk"A}CDhu^[~jZd)8'ťA%\=j*Q76|3„/~yQ癌T'Uܒ>>6J? !W6oO Ŷb+?1b+E5Bس^o?[~}W/y ?=]Oᴰ'lXULdO >VY9!vU=VN3Yx~YB0];<}@®Wu#͕{'LELE-]pMDlttڔ)ʩ&羈< <_g,JK c2-OUWK'ke=BMoC$vnb  |l'G?k`h nw@$Tz?o#/.x[&>}'9&?EDD^RfɈ,=6鳔} ?šbtygS[B± s#`΢.ϞWa- 5 9_fg4kN3gΜrO_uG!2ڵԇB(n!---{C[q"A[]Uks—v^osΫh|b%' N'A98 #Oc;DYY 2ǿ(cg߰БzlUNg@ 2Jh E+**|׆:Rzk} SˬBqi$چQLX 1%3BAu>BN#["ؒ>yk59f# ':(yx+/KqNayomk򦪳>}lL^^c sUUO&('[˯XXASr e.n󩒒zo7&lģGj= N2L;TB1 ً9&ꍘ p PAƋlԔ\"B@ȲWY[[[{N}1F#й3K(J<^O9 ( d$u4l.>t̯]LNEUu'ƍtZŒ/6snIzd}utt!Pݻw !d޽{صkEC [\ gםg"6!`N47cA4@Xs IPbs<6c,QFnڴ鱶̲k.w |k])8֞tߠ e[m۶ ~6s?tP{t/G}?+O eeUȯ+V#/-~Krkp^rPJ ߧb{x@UD2sި "())ԁS5@84dȐEVQQl9BS\%I#[ni'7 JJw2u_ l4=}vt`I<8l?d3 }A(8\{OcSKVfbHH SG s>xh0ioPDgޜ}N#j`{B?]틍=/i/,O;VEvt Ɲw^jߪLMPO!s\m!u/+S.yg9EE¼ t&ݯo<|˯=pnPL[wi<-Q3tqp$478u'X(9anCl#Ih/ !ٙDs$PdFoΎ;Ngþ~ۼuߢ\o销Se#s*~ދ@O`,8$%kW6თ_Yng럸❻vYf( EQ]}#j'bI>6S18:Д@9yHqv߿N6@9.M{y3r{ܢ~ =Ըs'>GVtpB޳Dʕ+ug(J bs_k{mKoc׮'TǬWyڿ7~b\MM݊;hӦM'=gpsf9(JLSS4O"׬gUpIXGKJJTg֭[ :t_EEcK.}s0eeeB2m;'%FiÊ&>I#UujLxqq]vm$EQFS6l؀~M%"!dh(֭80Xe4ix]pfd%{Tp\!qą&uO(zJQYEC/G!EsEMӎv۪mŢnWpf1.`-DEIʑ>4< |ki D-N!}CAvI2ϾuZr{@{9[Cɜ,jlFጉRpUTi얶#b]򻚛޺q`sh&]m=NcBWznJPr+w.igIWVeULeDq%*R5p>I0v<{ҀϿ;Zz Nxݺu;mJ&-ve+:h؃愬M+W|sNJKK2M73h]*1yuue; a㤿aB^:5״X5cBWvd9I: BB <߼ wTK8U|䳁P 68t ,Kѡ~#)_RZZ !sJgGB<ОLc᝕ VK1<^Af2*hڣYYYOر۷ku:f͚t:>Yx|r9//rI~۳gO=NY^ [nn.)//>H^;q Wo| U${ǗZ[[oUs%K=k-Z4w߽[]RRҧÍt&|$^xJ%3.Ғ{ :k$aNf;N/+++EQWXX8|_~9?sOg͚OIIv9sv) V+bɑ^] 4≯Ԁ@x?TB޶4^f=#j_ 28֋<AhŲ&&"r]~# hh'_|ܱ <~zL %%*=n'dF9+4tv9+2vtPg}!xrv/{2Vjd߾ !))ÆAS9 {" `Lv;6O Brs3}gKuG /_M wwi;VB b'_6hT^-zI+*ɢNzWffWt1 W:e ,I|]kmZJʍSSR6i4ߩ4J?6k05Q')F""g&`S½jknLa TɔunD4ƹ9v >`E@ѲmRjNzrEٌ8lݽe!i̘%F2Ӆ\[\,NVV^S4dVD7%TIdbx9);}Zo<)%\Re;/ʬ[=^#Q=]˱fϟ`VUo=2>͟LMSܬK|+n-f@EAM{PGHC/'E[D~JWP6y|+K%8]N*QsZLs\[|7LstfBKK#^wFi IIY'O`!n9~xAb>.Un#'4}OiS|07׳EE:yrLSc/B/_~Oaaa(~wK#/@뮻n fMs9s RK .^81bŊM8áL9sfT|||7>S>|ovrdddً/8!"";mڴc܃NO?… 7gff|o4+++~%KO(BT&4wmJ{No`l ^ |fO 9YYYFDDX |Gz}! V\\ԁN eV0SzsR5u Ӏ`w(y]S*AYeDOJ?mE,X$\ѣSuE/=ʟƍuĢl2Pi@!t7DM$qDuvXP{#b1餒0=qX`6[vߴEgU2-Z2X -* f1r xX>|ݐSZ]}P ܏FFrpΉ(h+P@1֚L|/`^b8F cg|^'\m謭Gi*K">pBE)=gEGWlz]ZR`h)(!)WffvQ*;;'&^=2::7 !ī$I{:$J-t1P<)KF:׭J9rcB^BYp8C5PJg69T‡M(=ɓ'?fϞ}`i($I`ZΝ;w߸qF\~߿Xdɡ#G.|饗[~#oեϷ{uh[#?  OvQ7}s-9q椗$o*g{ϋu+:c,*#BR \E,Qr8'/B ]*B9Ӧ9mӦVt$}ЭyOܟXPQN*J0u EOa(^B82 YK3)]S/ӧwy)BdmJ8ߵ!oI18!"J A@~= ycJyzd跒ϛuVܕ_Wwh#nӉz w.2 39,xX[stŌh[~&NL Oڞ֮(9yBUy2DF#psd…CY_TҍÖ\\,jhDD%gU\,ΞlEߞϿU'QCڻ8Q*1,fHXa?q8꯿fz=H"i;^x݈MrSXOƶ!+ll) s%c'Zj5BL oEYE!NcaӌIf!'Ck:jVEk^[PU@) G}-YoWzAqnɭgtmqEE-IQwߔVR#Nۧ" v:@ ?222vΝϬmJVZf`LIIqnݺpCMt1o7XQ~ (^97ۿ=Vg2t:nK.1hYTdRYrVU zwD;vL3g7xō7  8Z;k;~:m6$ӸÇ߻f͚O1{'yk~G] plڵ뮽گE/Xl}CuuufΜye^^^MZ[cc37w9?vsNgg.O+f1sj}p /'F vk =f#vGDDtv:C!>x!X81~`כֿDMҌuZ;0Pη+ s匥خd7nُ"2rԚ * !z*+rG"X|+`̙ڕ+WzCևeӡ@ۧ3%PPu{pB@!QT=( hs (Ԓ;^SQ {K&B66esYR"{SrX7:;C!TUq,`n_0r .Kۏ}Rjn}w]MZvӮNBzn0B h8|66ԪzΤJ )92@(q8es'E]ҭ*A5"pB޿x9nEy&`ȵHnUQ -8ߝl]ғ})/J[C3A }r5׾tq)/BSw&ލKKI"ѳ)C[3p@_U($`mzxk[rbL5GkpG8!&^'NO#(rs@iQiM8^5q9NoV+{00e'v}CjDRFDLPGڦnӽ?GOg!3ղa[Fdn餇 al=hp GIȘٗx7G]Uh`TYf"B+X͖XSSf[CyIIHNISkkhѢiG~ժU\NO?4;&&d1@8QgwƵ 6fG`89zԌծkuwlMOf2( EFpϾ;wbkyyR\y_ּ!~J:S<(n/0ӕ>j]ON/{UsRO@Ӹ_P@4raDeL:%!Љ K8s8nF]]]]TϪ/B\9+W_ϟoKLLܵu֋ǎ[t7nEmQU[裏ݲeOgk`ǂ[R@NOق, {pt8ώk >Y hGG͘6*=hjZommecc/ۮmm@K \3g_5W]A#5qq ݬ᧟VPڳMmKjd7'F#A'r0WۺnS0L\P,,A86A`oDqa#yz`Vyg^]NwBBwp{6"bjxa0)2(ȳ,硽뻸SZOih헴Q6@7b K\Kk~|qkCS#Qlj~cBCueVq8 en=u2{S<0Rk u2 b68:AwHj 蔱y8q/?=q~cɝ8傫mm;pĬ>\U)`:Qm5c7N|b7^OBXQ怬BVT 'Z1.0Fz'// TLe`Ac'DeiZFطzh~c*8l Z6,j_Mɓ' `1b{ժU%1rb́`0|~mҥKoEQ]=7Cׯ kfGE>c6: DaFaEb° 94#- k 4݀Fp(_f ;!w=P=SQ:8@ֶv'w73lL.\|?BgS*wn '~!P⢌{=ޅ69'HPۿv:7=%O>y s卍Kt%@c9$Tn7|-k:BLC8kto%aUI֮)If6``C@Ύd/$~YE4uU}w}%~!B&e14mu`"wYV>qLt4ӣOJ_cA+3W[,y y~JcM]`2ܤvu9;;TLd,ܲHY SYs1$) !;(3{aAaۙRsiND].TQXtR :~z .,dǎSリ/|Μ9ӦMlٲe{gOvL>}>>sLm_<3h0$IHOZ.("\nՠ:`0,OEF YTt(RJ4 1 *.FW[n.q{7LT- C9k -\F q1QsBHլ\n[ lO{/uYM岰^B)傗2iTo&*o%P4VK\QxAp@ ?{]^כֿBE}8,ˌRNፍy[  pFs ή6mKP 7l߼y&L7a„۷ojɒ%8uԧ$ItTUUmG%E)y'lnމutZ}c]ۄڪJaڣ3í.oɷ;3褐Aҽ x)fѰ%4Yds…555;U8:/7/oSFrw/lɮacҔgrˍAW0~h2 LA CVa  mbnAO:_p: qLDAV$&&qB(RTB!tZ@tB28@Eh34T "*rmv;6v{sw%.]]=vx)<*3˩~F)T0q # I6 (B W 8:.RТ2H{}--NsZ91/} ,ص e ڶoP[K_~eVIyې;Bp`Ҹ}hkDH]\UBPBpZ i48B(P_|.Iq1ĵPIee묤}EZ钱QWN'pvC,Q ! _=7@FFMѤkb =:+Fu"[ ȡ"'1P9j D\"/;6\EEp ?B$M†HU$w<}F1>+*yy 珉rNNl6hw}|o4rTyՇ׭[M3$r0̿O?qC8o.sTiAW_,([FL* 4߾87"&Fy PEB{ϡ B!?( 7ÛB&Ήɠ* I||O(山wlhjS⢨k>CF侸ezqɉ($u[eM ֲ1:28bmG߿b_WS-~ {>ѐz#09-!ɕ!}t1 ȲJOm &8q>ߕ: _w|DPUU2N)%BZgo 4uDe?tG|XgU{mT+$E^wRwSspSY.0O sQB6)7DXKHaPz€s@ ӹ7*=z" g,P ń("{CKI qm0޻j#]_jH đ6=6@TX7Nl<`]]mNgGc;{#0Z.jeF'ix!(D L<8;Us /9O洵a]ظa=ТUUU(O3ԣG.IMMd4] >)۶x_564{?<3GdJh4\$J)$RPo9h'Df]ƒ*TUE0P.vW-Y7JSMMM3Zҿ yp>%m\EjOPeؠI(.+Wl?l@AnUk4wsFwI5Է8[Mte- fvFH˗.vfZ+Vϛ7(((p޽YYY_9r"^&N7]=ѣ_Id_bEj¾':sXD(LUU*rJ)g1v6҉`fg*nlO84:hXNK.8z]P0j oǚ: >t%L~ʐ!C&SJP(H)ݻ{LMP0t!,Ë***j&}`L9ڵR_KHMc?#"|I"9Q[GZJW>DU[ӱqM(q)i\n7wvvt i !hm9QZh!\ Ss"\;q2 OKd}|=kjrt)(h`JWɞ?ơcj | Bvm볳Y!ޚPIsS],lN qN3A~% >+kP$оw_g]{G1åtV1%$ ˊLPD( E>n ң K@N XVWU['' QQ׊H;' gi?esH؉ǂ0wo.ș>_KQ\3O9AixҠ.B,'Dߠ`*S$%D|CB[+xB6@,%`ݪD8ztDYsWQ5 RB@ #T9jDE1B4D!#_4h2Hz8%A$\eg3c9s/"QyRԶelnmI鉂a2Ϲ(//:köɻ'+I`G #O ;6"&V)+:_Q{@k8>IkH0DG4Q$8:3 vxpǜ#677[].0¹.6.׎$ ^TPW6lXr[HJjbDE ilkϱ9d͚5&JBP9ED>C,ɆHJ>̻7޸c_NccEQ>y%6Y)BkS9Α&~pH ɭ)-N6:=*V@_n~brY/ΚPpQi͝}\~V -&}A;(k[#MMmTPV.$^/0zB[?_V/ֶ"55j5ba6J IbdU#FItUf{'eQ%<B_2@% DqT=UU%6PA];ubQ#g;zŕ+C8V:h߫ʒwp7]GEDd%V|X-_6PP/myc̡ܸaEӁs7@L0*,f3Ln-MM}+slAZFر:wyy竪A;!Iz~ Ę()Kޓj0̯xޫjly+fsNCerWj4" ѻ F#4eD< ih`] -Ta>^)Qbbrsg^m mU$I>UaE1Ua8*L.H92o5ݏuwiX S3\~F[FF@?V{ZH_ {rtgW׾^PRB *@Fw3!!z\@m|&f Iy7E}Wp) (];mܱO.G}G?RJ!"ƍ|VO:孛7뢣SX}}ݽs'rDʴ:r>[B~n5B^'kW}W_(@['9(P1$I5 r38 丸t]DO0PQT/jz S*EW1ѓ7m[&Z͸KH$o09mTh11tZF#H-mȆ;Ա/?Y{#5Z{jzn !xlҐ .9JЇ.? &bhjp"qsI`Dd@q1hy9x&v?fő6=4pr.='s޺D/,,G1o6,Bw-Nl- rS |b ' X dܓ~%'!r ߭ma%'@W\8qYtwwZ}muum--Tk.huz 4^WQ5Ww w\(^A[7{ߍ pB&C͢;[AN'E99/Q ͯ7 +%z7CpQ `dz&#LtY@ EuydB/ Ũ7b`TC-&X4w^51eUch,_!dUW]U9{%IbfyW-1,TNCҷB$BhF0O+IIZq. !@@PTUq[$Pv `(z;®O!C@&Q 111f$@QQTQQyaaW]YYy<6䧃ݎÈŤIU( })>43`;bP'8%e̜\}I Jr&]>knj~f/OrndBu:%шA4PU?ϼ1 0FF#gPV}wTTL+<=AzLt:$huDg7@hF/@d"TY!ā:Kă.QyQD6luo|jpIUE!P{3q&cuHCdϙF.#H ngeVP[FDݠk2DZP(ʡ*!rDK1r4]pBZ0B0> {X$%͜sMǝ8Nv@U9=\a*׉Rs@C&3/::p~Mꓟ s`=G4:n<"?/SDRą>nʠSHN\5>Ndlz?R]7LJ76bvz!u@N+B]^ltR]Lt 7To`jW'~?8p:D?Ypa4y*3nO4k#3 ϣ@ף !6N9}$\ D #MvC2]׃hEgIGAT'P@}++c` !%287Տ7cN7bȁqp9#q+>͟vo]/suQ6 ֬1kL{;Q 8`vr"7ܛRʻkIJJ0,ںa(ƚ,I3Zyl\=vZ,BU^VV&\x-V{0|1&tuuW pʟ~Fb'P&-KmU7܏4DEfϞ]|2zN'~ߢv}$ rDS> D eawͻפL>а6??_SYY)CZ` U5u$S9:T-݋hf-@Ih2d%ƠJjvjÖÇdYf4ݒ$ŊHbcchtBa(VkU)<JKK ,/1c >ү:wŊ;.] $ 瞇y .]:+CپZ,[2aGl A$ AYi(r!=htn ͒(9h4)ֆvwLo[C)c2nXn]^Q@A qƐV 57qСu$Z)DZ{[bP7Q1騚_ȸH: y| ci|(!/]x\%hoӺT "*+ r[#Nd9Dqst _zRAxDl kp<CE9O0|j46cP66vdhܘ1Z,/**R5H[Z[Qs;V#Hf7%%%*L>C?p̘1_=Ϻ]]NÍvznN'QC^>ywQMMMçO眄34Fh~q(;By[l~X0ETVVr%2<6w@EtCۻ}h%äH* Jž*;:ŏ<վ'f#|Y$ ^s֬Yp:ƍCBE Y\jl?`v;s:֭[!&&pUUչ^xᫌЛoy93tڴi۶m;eQf曳rss;/䒗+**.߿/{}r޽Y]{zT :r,_ ztiDqW 1$sZ&w#_,ޝ;w&|Ȑ!cqj9:thV^^vY9`RRRwˬ)qu' 9#R}.G+kH&2rb*0@⸺x.TEw8FxIOBs"bV}K-o@QScG4l\^5P򏚭Uq/WUzwr@x}oбޤ=z#޸G{B{heF)؁Wo|h[h", exdEѐ$|>T8nbLhKݷ~qwv~0! O_XseBc2ET3 r`{%oZSU&) ]K ɮcbƱ /D[f7ov _$EɏDЊ-17̝.7$ˠ5!iA;@e tX͎7&?uqlj:ՄX6߳<:o: 0gg0l}iu̸W+=zz{oȑ# >UUիX믿kl6PW9#%-gefeꩧ=ַ6^p{{e47|soye9"SJPCw&Kom>eˤ%K=a>9cy:۷Wɾ;ck fE_9\D$˔*uw{w:@ x~~~%pG+^T~UH_k9*͕G:iuI X9T$F[΃uj# J*>6Ꙛeɼb| XnHEQ=)fdd̝>}:bbb(&L-[ԼOy衇nПn۶s5n;G]SS䥗^:pM7UWxm 6mo,G-K[ny_ggg?~c4;+++O=Plc5=㼀ikShp0_3yבn9t8C,@o=IS†`qοֶ'V nInE# hאEDe&MYEd؊)̊;0gNgAѨ~ 8qpuյo^64|zpNpP8УMYEӣا%%jt&xr)+!)¨E(wCzr$#G {__vqlw~#jK{{sKkۃ<+IDMz 5&2BD 0?Wc;ᑏ4x vR^pL|[Z[o7".nET8CC1Ρ%rtEJbmCkEtt|eD{'NHs|8*S8rhZK@ϖ^ȗcE|SeNW!ڨ&'xt~"3D0=!a}-z}*C=xeKx ކC[3d˖ʼn5LTYUljZ`,dynqA+niP""AK{Mm(B@ ^!Y k! ^Vt$vzL??m9}EIL.!6~mjvGK/U@-& >#1vңL}xePҶ{z4$Kp[)/f=ۚrD/+PntS1hbPTMs$B̆(^N|lO*Tw=޺/X ]jڹ|M+5Mo*..y8$ 狕cǞx^ؽ{wޤɓW;onwop!߼{CUOMM_O~-++V͂TTTzG+[uu -H .I7rHEiK%IԆ8kA0phWeddD6qݘώ.Og;p'[[?,L@<-㓠NT89!ٝ ̠<YQUkWfnjTf e{6_oB\sM/̚5k֊1c`ݸqcKmmmE]t4""b[ouLqB^o=K|7 `c=o7QF-뮻 z%`ZP2wẄ6'%EG_i6,“/,,"vu5N88Tʿ}׻S.$]cizWeO}{j Ps{Ĭ{jCeeVdާ~큿͞Xȳsz+(\U7hDws?(5wCwg.'ܪe fE Gk9YLg?et."b2QzY9YF^.Hu:ο9KRw/Af7k4UAs ʮf:ыWxC6U6`@d$38QτFw}^vvvjp@H t2Zrtt,[#j<ȑX$EwR: Rl?*j;: "ce=I_R4yfN%ʐ8mYӀQѲf (DM#^]HUnը02 "kM`6--~>=OTT{O7);VSW nٔ@D~#srL5˗\VpHfRMzmd+( D@V8ipF,@<ĈKSTnz n8gU7jƴ;MS6ujVpr?Oug 6w:&(.mSdukKh#)mpi.Nqnx ydLgC`a^\8 iDIH1@Gsf+cǎ 2d۷o'Of'j*I^%B ͞=BE{!=.N '뜙j~ϹjqƦ^/Ofw#8޷O@EEE;~wX e/ymѪX(p0 *m}( 'U555ݽe~U/EjZTIbPkkM֙Ŝhf:'5n_W ;껯 ȥ8P(b_ ,P駟~b<^o<#eOQ8pВhѢ՜¿o-_|`bK,͋/x=!$ZVRVV15@e!=?K%\Qт?qԄ)ҭrp:th#rmvg }ى֜wlzoH}Fϗ}ζ8h39~8;ZNr.]=!)(ȑ3SRx?9zޖ{ ֒ڵS; kԚ߭>o̔WrS.+}(=}гHϢ L(++;>Ĉ|;KC{9a %I{ k=:hIϺh040g`l 'YXXx߰a2—  /|ct2J]kCIIʲJgFN>>e6|,gǁJV#Qdهn'd9UUro0X3R#bWvG {9t|n8kg?{Y@L 5.w+\_j456[ժz10cl fFFV 8//_̛7//rNjN@ovK.$rGEE]ں?>>{Ez(8}ʳY>.,@䤑p[~J6n/·1/)cFuz`ڵeSI8dڵڵkngW\qUU??pf'O'OV:͊oEQ|I̓+ՙ?jQ23%*c!~oUUmC 0e׮]_4k'??_h?k 5"_s)sngL=udk#S,tYBqx i OU?C3gɵtYjEog?"#Ko,rg}aѿ !i{EWZ{f'[~pQe6k{_8//Y^~.3ٳ'}%-[^u[/9Ŷojg,f9uis ~9m}‡.lЂ ~8΄{͛gf f̘ax3/B 7s]6*vÀ::1//^,]wuce\ꫯ^+,@f&$O1}WXXh,..֡T5I7ppk''QYYELѿz"۟/ȍ1Os~w3~7|bԸL} 8G*(Hxr q>yO}H{WZN?ۈ8O+_5=؍? =.caߛ eeezW^߸qK} 3Oef"fd=e>F[ kU)/}sE+s N~Vx ͹{l}ֻ~3hmg\k)9zGg2W[h+۾?Oۇs?w}yhkNq[wmeO|z}S3mϙtӓ#AlFO70/ :H2M5*ho}fњDDwfJXgECV[oPAzW׎f[kN0WFkDn, A~8Ż6*p<fwxbhtcXnj%E,9g`p@: | Ⰲ8<)fdV|$79 3pcM ~maNY~h5fȠicQO$fksyi^ u{Yˎ7KʍBu~9sjҶ,]cDITYL'"L~]Nֺֹo@i)!v;ee֮eg;eeJJzTe-gmi2F*Sޱo[϶k֬'DEE 4hQssW\qű?8=??A غuk ۽^[SLYWzV/+fPz+Mz,V 1f؀1[}WZf%ub]L,^3Mh D$*I ?p'Ugnmm`RJtDF+@kgu7}ebRcgclF)uz KzFQ+d*;}ቫ{_Xq\^<%qLewϱ ]6nvbg 8Mmf(+]s~eCimK ^: ˏaQo{O/\JPv rkMhR.yZ]=ds6\̸Y˟WvUM FǛ$sU3}>spAw;** MY}`/q ̱'JA[Ԣ[ˬB ﳧ*DFǾa;&ț|(0Y.7;nXáR= >r\HqxWn۝<( LtwPg_=Oq{ʀi2U Lee=>֫FĪfjjuk~q惮K%R Ijo4wo6Y;l`|nStiBFTVo9!*OBbb"OLL>".//pP~~~bٹs[o5@lcfz vʽ9{;ѱ ub^S={'_ue뼃pum}=d:k\)wc wywx35`>D1=! /cGV4$"ιr@)@d u@7`43eȍ/;|컅50vNԽW<3-iO}e,]Pȝ?T)T8L FUoqpJ:.,'(칏,[A:u$kdˈ^aWDE"Ohx=>[0?\O#IAֱhV ԁ䷷{P¾աGuuOx͢%)ݷ ޴GZM; /]ƲAB$% [ׄ|}^a}uFa @qKI30.ܓXm?I~1uvgUJȑ~[FzdG=F$ݔdve:)O4uߧloJlcG.-6ycd^^B#FLy/))9,K|ty~=0|6cƌ_@E xUaN<#9 ֢,!?GaK {oҹO\FG~:Y/_~{哇]VT{pR)J`ֆ 7 Ѭs^?A;8RJo{m&}<6WeL8oe%g塥<8i(8 U{j[.ʬ\YkmGXD":[J8BI[ŻSG mxKQ.81g}{_FN+%񲧦"WD.UPm6& Ӓt7TǑ#ʍ(HS~b*.'56qX&:?VQk|hޟS15-?y9s&i3G.!tX힭Y‘!Ƥt*r$9P}#C\`x.ؐ-C7#^~%26iV$D^w_|fTH~y'_R}|y;0Ru E<%4$re䇫q^==xT.uv PuZyNqt^wE64/=-VK`,P:b+/a-ͽG ۶oXB vN H4r}u5U*y0ХϗB=m4>eSY7yh]] d9eǘ14# TPRDE$ JGzԣz58PMq` &NǨCę]xs^K4G/nŠU4;\z(Ly yГ]0cNAze!Wz똪[T:/JO6xz^3N$%]`rf^4Z-0-\P捸T@wt`?=xTK* H$*.aƏ8['lbpnE֕U[sn߸Q7@,W}]ۦ>- p< o}B_PUO.íH+ͽPA-U}[$ߏ>-{CS+]ڑ.zNsŏ[xPcM\:88 I8ij4*]?jd-D"-{0P}3^?l'O܄S gu*OSUOPw$ߺ̏ ̙͚Ğ'ׇurW%RW rzp W6rWOř‰I.Z.$?aABʌHP~2RE$A)$IIU5~FBR!qʍÂ0Xi$D$FCzV4&3)[ .#g2D* Q3DbW@C `{f֊|p/' ^Jh10"5}ߣyj'YһOutilvk{7Q5\3D˘+ 99%w@N-ķ4!7ҙ)gǎntZ/Lk&d WV7 = y{b@јpI3g:gu? lZqy8ahK>YG>Wf<b_nch/5;Oxk耪314(\G rؤPth^#Q%vt/S9.s')rpui anLN(4fb~-ν1CB FE8\ YWZAġ1 8%K|:Y"%đ+fN),SY A$@HH0owbeI|￿Oqpɱ~AY_R*K N$4Q"Tm|zę$g#{Y&GPpx7>΂vLʜ9sg͚hGG<@JɈ`$S*{zҋt]#ӧO7wGsqD'[ ʗnh$O`:vڙxּ9쑪i_"?~[s ӴqHq:!X:eTǯ0DͬV1ӎ46g<+!KpEarhwj_m{aHmT}Ņp ˲8VRThS E$Uo NT$ϭb*c-LVpH$O?4)%irD$"huԀF6sN:n떣xYS AkTѫ?BwA"(ĪV"]IP^ՠFv卌mW{7([_BX'BSU=Gt%xQs8: Vt >:V lqvt&_y6i|}񟇻ȥa[{+Ymm9Ow&:KOΈDLW9%d*}?H+d/^gw;E~:ېɹv 4C?>Zr(2Pu||]- 蠊* OJW0%HuVn;01­* [TCۋ|P}H.ngf`Lc+b]Q TIrgJ4JpvLܡkd5õsǥn@6IIĤl b0K}EI* *E޺r߷>AnV>+/P*z/4_/KٖL&Q)5ctk 6ꠥ7K‹p8=c***uxժU۶oʕ+pǑeq"g 2Y:c s~t]?}ܸq&?oeD!2! a18ӆq\mss`Qb-1iBՉx-DkP(TW33EH3c;)T)|"לnJ~_YK XmM}=|H)IWά +acB UXT!!  !%KÝYg=>ՑĺN;rxAb]h_Gr Ug+Zh[ l!xPцKE&eA tyץDEwG.Dݏjm +*@iYŋ,ԃ딍aFoN{PXPP\BFe( [V>&wY Iv1> giDˊ߾Pw_e"F3oM/Ż nF݋M=X%VAU)ql!s(xX|NGwG"L)iT)Ir/3&1-B~, N B4g`&,ԿdMSqcGrȘZjf/ߏ*GLi%.Gu5sny-Bby@ [y K0ɚҲrcj˭FȚsW^KIR.'%Lbna17MqYv1pCI9yw}||BWftuXͬvϾ[YhmQ\X7?(tb+mZ-[o]$ {ma&,XpQFXP4lذ˗/WZAqi.& ˲p]] "}ɓu]'q2)/ݍ7[?ь3#΄#)$AHePI8{賻|n7/($yJHuf=Vsۜko08(0å1vƙm%z3w?tӼd}}HݝI"7:xEU!6%\\@*^ycgfgoS:C}j9W8J iڮrV愰o&g`e LX[s9r~ ʰcCL6 %|(j JBJޠ^M4ohM梹76 ˈ<#$W.dG7_AE!e6+ p>۩4H‘oy4WW(b=-chnj fVi\޹B:tsZv<),0J?T kfu+U{<L"u﬇*ƕ-nyz1!h[3}pHt%ILD&ljS?h  4*mP~X/`jtB #(}O^`wԇK]ݘXc#l].2ǵm[;3 Y,UwDqSHĄ?/XOIe-e n+n?i%:JĄ@GAاW W ߬t2#ƴj@eUP$m==8w85 +.`G@X)X2:_mT #HQݝi{rb go8c!]+ .b30/#3ؒ-o+6u9`F7QweC4eBe!Mp5bX߿NinQ3lࣻʃObzRCey>@āJK3 ۩3o猛([;;&L\wUu=FGSK~?ᠫ__eez_ͬc|0T@ ˲ѣ۷c֭/*A}y N8rDrADϛ7i+:H@&:ws!& d;?Ga!Xbmp-qfZM:~_;k':PQd<Ä (:lǁ9)٪M==xѿ熲wwBet˟<Ѣ*5̌csi%}_Čgjn4Q8e 'u`eGE/e5`s 1-ږ4o;sQ}^cfl˶}}}7nɤ bd-]}]^o-a 3}F.DhIXq/,[ ;20N_Ib$ #L& v Xr/ϸw`]q*iՄy3O̎[/͢η 3lڈ mpmb}! Vh3K<-/2|e¥820Im9H'Os3!RJIs""!EV`l?"+wkj|4͟xEI#+=8mv@(&<M<zN1Q~G}WUkdK[DbH&`Lh*<] # c][0*Fg$~Z< pq:OZ{Vm3W@,[_ȅy*Ç /s4)E@JHAaqR,(3p2(*W[Ռqƫ$uzC`*0'5˷>p4v88#B W =aHbh 261e$ )]$@\GhG@sT!>{ȣ)p)XrjaT\MR'|7fFKOGDP8? R0}p]pDYOOT>B0Г?T. ==wd)-Jgx2Q؊ևcuJ tw3y((5#`3yZm,UpSg- ,å7cɚputhfDUsWtƄa ɀNUY&6H,H~wK?kGф4Md2 `/Q{W lݱ/Z+43En.m{!jTBMdR" %ǁi;)'cǺ_FG#Qkԛ'+lGH0Ơ޴Pt Y0?H TR *pLo;-yfeDʆg\iz@Wag#lA/"M00QXycNI'ҧ|ۢnees3S]=Bom[j&BD )" DΕx*| 4[mݞ[%PV3ڷ>w eKDf2} 2ic?vLr: ?k=&I;0W[ӹ*N+Tו!IeRf10;npA &#yo鉝}x7;i &Pcxt!W>WӊF`ߖł` M8^lpx )T߸3`Jմ5]%ocL3_͔v+Dn=\qn5uokwk]H$Mjw,{cKa )ç 3-"DNσF|ЕXJyoF5:ux'7E5&p*`$g wi*#3{BW $,[ f\^P7Sq5Y>U@OP9`B0Lwv!kϯEog5v!\XTo Ut$bկCSMHw9x8dr\*;)sމS 9v>U07aOc9hb }ƏuX6̍=ԡ*3{\Դ[|z]Tõqrᥭ.W僇ɶvn&KRp 3 `BU7[ FSҶBi; axo!o Aofm jg F $;aqǸ}d!]Ӑ=4 .nECU‹ n#gJRﯛ8qUU!e ")a(h~/B?2k<ފ}PTVF`ʎ;^Yfvs&ytΌnF#9ճC1!q't˲˟$w;u4.r !O9G%v2!݊g@y.Jc?4FoH\ yJ͌mrڶuy_zËG/0p>NmS\3'3ίyøCX۶\ccN~dQ$'kʫMS30z1Gu$sڼH`gH\Z@ӧ il|Fo']UmKGb!ց-R?צ˯`jyG!u'wH~ E$(=a=n=n6gUn봺?6CCs\!!a;̌d<dR?a(Ͼ6>@I"deIY+ ol8+fq ;3os+ֻ~&ںڼdc"#F ^-IisK[1[ږWݜjZΪ5C1G"gZ)Xm )*(yrb_n[.hSPϏזQYdwdAJZUڟU?O D='m[$Z$,mPS<`E-0c `bWV~~ro\&6}H!03621&XЛ5A`>0qd}y ,,t&3ǵvށO](~>2(9=- }iY-7 <@a_&397:ژw5wW9s6@0X7[:@yHw} kЪv}#)0sKJjJe&g5#{S`IMV] —fWi9b1ˣ>O|⎟HaIf KZ@zRpCE47&+: ע"ՓAӞ "8Ai^֔js\ͧS+3AV0HQH=,ݍ~\Tj菊 Շ#M={u?Iq8R0MWD_I&|!fYE6u0f+|;#uK~Z1P8C^ia Y,u_I H%֑Y},v$ m q&g"dLdB0Ɛd @c4i^PQ8ֹ#?ȯd[sZ +$'Ssp8.5}:;y` Dʘ &%!6BUnrM4M-+uL$pƅ#Δί,N *vqIݽ W"v<ל= Yp@ћ_`&y(55X SnGB"%{2=TT ZOW(V<捱_=ב7yNHH&mX#%IR 7O7qȎn+-ti ٌA !A% RJ8I!HPV0t$4#WK)aBdL-f9H3 1 +5 Q:;)mxqUƓ ]8Bja0e$joK/lE( 5T_Dk3+]Ueu!¤b}9JK$әoCE[DZք{}ĔEߴ::bYM~gTo\CfP̀C68cB(BbtwљrأWf?nN{17W/WUh 3Tnp M<dW2WUH.UEUt-MT3^,"P= q,F0kT0)2erD3AiPP|ذgaı[A !ɤc)k6 O(VVW ȂX 'øBJQZQQq… ݸqc[^WWiHzzyeg4<겿M}=gTiqqa!cJy*;ą?1AB oYӚO]@)FtOv;$GHIRr v q-߯R H,z>W>$k '1fH$2dT6`K!SCJRlPpr1 $q>60N,3)֑[zlxB)$ !ԔY7в )HdQwFXfmSKP&ڠ_ ־Y G*$)5i<#Ho2VFIO, IWQM/~y{MFm4e1xʧc|W 8x gN+߳p"6%~B>_^ Gzμoz ˃6J}նڴ2jX¦fskI-ouVoܧ&` S9. !s %S7ǒ"KR09&x./lw%)L~*a LAs)'UWWDO=w 8A$5ƽBJm. z!-7wf,H]?_:pchҝ_Y+W!TsZF!t0 UGN [>SKwV(mlH)w{JTF]-kg+\6wbr}nM\[u}rG̸ꪄL$KM7 'c!6$ (|kF >0M4tMJX.pCk K۔-^0ܯ:._zJIC^$*:R8 ,n('USg;6&_{/湉'6l+`A X0MIS%ơh~p >? JK#F :u깣GHA6'V:] /K||Skzm#Zycla_y-Tgfv8 ^]< /#ۺh5ޝqlK*PtMuTXꡄCJ8\9[n36] )ME_ 1I VgT78& D)ϯQ/>ϒ&g۶m#wu!c!|&"؎}َNڤj o@a m\N5d3&)>ϺLl3ip0xPmݑNe~ɴ5.(*D[kk^O3JYDr$$l)k4z ulMϭSB RC`TLMShV{>lJ`_z呩k׏E GġȌ\11FDȹVܜO Oc#/d ]I8SuIGj?֦/4448Tc Ldz Bf&ޕi;˟`&Bl]S1c0.0#%!$Ľm[LHoE/|Wo:Iq@}”X'2R~wжtPxhH )N\¥s:GvܵoG'-c*|[.P9?\^u۬vuO[#P$X}gBSad0AK༎=9l9,X7]7rmVԇۑ{ֶ~رu[7N& ){]]-`~wVSu%jWMF~ =vPHadh›ODQtZ70q䏰qqp572`dEVa>W45'~݁KbQd`; [/_mnJ[bG` < UwCGyAlĽ.tOT nɲtz3 {}7;vMnfpfu$%F$gP^CO+P; åyܾ+BJ/׸؀wq^iō Ü/|w׾0MHYr/bX0D0 80 [sr`xPgZEWE~J klA.W[mG3;1Cݸmu^2\׊mA\s05;OgĈoM4b*em $E* '=FƢ* \WCVkpT*M'x<&jbK.qsvbHWTO=֧,Lk;w>/r{5'k#c^:DŽ n^쩙۵gtQ4NǀO2@Fk!Q48{T@2מIl5aX)a[L+LHj3 ( 5:Iia&؆pc`Gk+Z;;ח1=[-k^wMqf/fN$1Ydq0FuFe8 +  fdN6_(IHII̱$ J]zn(Ț_Aј(0?OZGxʞH?)7~G1VX zCMi[EM|Ω>/b}}9׎gȂKڷ=%mϢH G:ccpfyvd-.ֻMu;)JI!H1S6u;w_k5^; dO/c]d[B` wJĬbW"d/td\1SG\#d_t$jHJigD) G6@\8,ӱlqHJaUW^@>??GL`qeKoJd''Cj20chT`\۹oI];Wl ^1A.pjV/z$#`F9]wr8 8HrHR^[fܐ-2x].0{6Z+(4z]q߰ r}- {= @RV '3(ѐ#{c?_p怼1z0y`l8frf󾃁r^UaGn](pu3#Q ^ rv6a3-.S{n7%փY} v$%ۖ`RC߶voCABPj%[V>kq|9jb\<ҏdz16s>|ΜP]!w}|)e_K~x/ W"0}v*7<|XaO$Iv2d@3HQq 5c@:( 乁 @>;@Us1Z`E ^h0[H/ߜR]8FƘjxLת.ٲ܏{<>G cC+**&K)8s85M =(g"0i< &?ADOW:;;ri`uMb1eѢE8?1 [-BR3͒L&LuW$"-߮]N8\_6# 潫^uټn].{ "[%:?H&\~tD ט$")l3J;2% HADͩe'͜Es_5-6oYոm-;Z[D"^붒~梏Ϙܡ ?sAaޟ-*lJ1;4؎<ɓ/yikc#Nn7uk!}M]Ol"alMeM Ih%!G(j|Ue5ޟhBq2mcooO\3os7sVwkbe NY9%R EcUB&ԥ$UHR-8pkn~ jZNTD X߸=j\nXNhzؚKOU/%gw@c$bk^[Ru\yU|H3}^. XMqQ'Ɂ ]i^?3@)Hf_(s0(+6 Bʡh/0DǰPtOLt2M`V@S&[dNƢb~Y2Xb v . 0,ʠ-~ j+@% 9k+[ց~ e~q##e ߀7Ixg~{SrK:c~߭nRts-@4, Yͅ#dOxŌ5'nwG"W<9嵼AC6 r؉3^Z{Ǧs/'XۢF+ܭ$lQZgi\|x|Q؋Can愈ku"w6E4y wtv2ԟ5?\ )m Y?)@F"K@Á!ނ cY.WR.դ|06J=#-諝kf #[f\"a1ۭ(7l׋`4Dee%v؁xw߱Ǔ]`Tk|Fe>tGqj_<{˯9ZzTUNCh0s{򓮢Aׅ)ߪ\PVhcj,QI^BB!}>']^KIو-h㌽w5#/ؒWwcl׆sž~7|׽6-KBr)%,ˆ-mTh &'E(E᧮jL,#r ]?cAZfʼ+ѣ_d0jAQp ۳2/6&WJYy<)+\!Jk{;RuWeHܴWo\zNe;ˆFgю&{:*J3RP:$>`R+vx«{O#!!* CYp)6 'y-,}/ jj>|M~>p}ވ1հrPlY6EfoA-޲)vz~)"Z9/]a1o Xڜ8?.пvUS3}=Z:RJ3rZ$0LG8'ն$@9y,2F_wӖϘ$Q<)^֎ \\_]˼`O+W걊7m[e,i^ө?}|C#a8$<ˆ6$T8} %rS8 G@a(h Ce݂8+},ݗti3X褅X{Kv0̾d,كE麙1Fuc `*Nz!6Ê@?~˖zK5C0Pw9{65 40$]!uDZdvk w] ^Pg%%wXr'xJd;.8).ddq/5@^KfӸal`êLJ_7Drww HEV D`)%G?m[͉tMWw,DĪz=lP>l_2zxYrț2( PRO_-3؍_r֟ <,kK㽊EI֦5Te@j좱fkɣh7۟Wh===lѢE3Ƭ@U5IH;Cp뺬F"X߶jժe7nJ)0sEe>*ۻӻv>gSk-'ttnM~[:>Џj^(ZՍtLL@c4F%|<֎yO*٢ƒ/,1PY6 qU=X~yxҬIjDYHG⵫V38q R}#$c:-$\Jњ1gϹ9B^Qksg=-yaoG*h찳?H'2D"b  G}W͵DSLQ-a*eI`dY)IJzjƒ\p!pF;wHxjNJ==S2|o_,nro}w觚_gs\i$J??E9e^U'v1{oS쥏xfIHm[̂ Z}nfhUu54-|LgWAHV8v_@5jC֌^( lKtҎ3 bBј*smϤ\\+ޑI6 94Hxfm>N 0A fܴQM e5$g(nL(>q!dRqרտ^, ~ \c'\Ġ>>u?j_QZw5bѪpov>t܅ ͽ}sZUO@[P#8|Coۼzܙs~ `IL!兏Mx}X/D Q 8PW=h5-K@6=n'߉-\pw}wg~~ae5iڔS'a(Y$DqfZ0 Y]]=/|ر͙3h֬Y,ZԒX*XH!mkŗͧ653K^@hDpڽf" ΞgtW[]24py6g5t~-PHD~:hX⚯-O$-ŮSc+)gtjpVXKo]^/ijn$@ ,bFfܿwC)c\ 12AH$>Mя).K:wK5; w4sLm̹h5}Oe*>0uh *m׎ $L){W]p̃ß$TǭxRK:bD&2j۾vņ}+ءyv²Lڲd׷lGYH0bـb{6_q#)LdQN~FgM|w=Nj 0jީ`mT$}qCJWxţe^Cww$IYe]LUA1RII3Ӓox,.ĐI)vݫ,&ާ.0H{d>T)"2 Ddr lսݮPJ4 k4rϯ9BGow? H$jG ̳ABF#̙#J2'% H$j;l ABH$a7^A]0xdAUykGCG*HdXPʺpЂ=F?d"vmT\W?g?^_Q_KsǶ-َE!X=="%W X쮟] OX2TRzRF֓]P!ջӆo̯j*++׃qjˤ;=;.u9 E`Mv:2ӛ^dIJX?Rys` tދ.T_9/}`vp1KO XYa Jږ5^MΘ1!"t: ׇ@ `;::>?3_믯(..:رC %E"5XpV+ ~˚~WE" w0b xm2μ6F"7PS>5Wgn߉?32@@2B!PѾhl?O[ZR iO@s.1wǽ캈ZeD Y! *.-8$i:y5ŞH]]o>Cmjq{^! K%o!j|MKI )o^ફ mio9sm?}·.b!ti?i˞AdI*rg\8;SՖ=W=sW[E^u=&䮟}MWw˘ wQۖd}PWmٝEOE\< K(k[?ygmy>"b1|sNwNw,&-߹ը5F1z. \DܒnXUQ=q`)ijo׵_^jlz@Zvl5sBu ̼{Z`:;!so݆~sE0bd%,\>MQxr$c߬$ et`}Ta>0lwXb~  =_6w@Fr8KH|˜\jzHc(02s+Z,vfMƢ>Ί\A_3Y5;ٛ^{~BL$Kk¥YG8e^_i$-s )Ãwbůr":D T1N>wv2͡Pv[㞯.o|^M/˟T|1#xSO=E],8eʔVڰuۉg***&]X,VAA6$j¤/8PAX`k?۞a;Z%\SZ&AH8WJ{|ӓko!ϮP(Dڨ8)[zAR-GEMM u^ yop=XL$\΍CH${bf CJ(T H) f!!/~%BRDu<~D"2WZ;^=Ѻ ^[I63Ж9r2]Y{X$Lv̙qH!Dm re2[*@wGFj2Döu[_o~巬޴pku:6Z{ϯ?g+eρ sWG `l1ROM_;oV- ):Xn,,瑈s÷O-9v#C!6_bXYr߯+9Kdktӷor^agԊg3{Շ4 G۹'WGwΎcY3W,^ǚE>`1{٢ŻyU~_\|uucfy.~lΨX,cANhv}0GЯCJQCcE,T!%c=ҼyF|WZK/mKsI'_ ~SLb=9k2p(#VPvbb4*[8`F*>U:2!hQ+g=}djS7}6_vO?>0Ť*t?2w/?>qYg-66yۣs2XMam/_/4̙͚,X 6co/ G7tſ'y8\FoY5ϛK6νo V(G ~ge8 7ϚS815ؓ{$jw'?׹xӞ=X}}=_]\tt!3&yD`0iCU2Ng )~x|ŃяZnZo&\)R%XFiSBաjj6 [zÍ>-mɫ3'1?1LiWttA.X[_^Fp 8 Ʒ?>;mQ.z?/܁m:ݻ<΅F_y}ֽc-۔I޿Lv,޿ U)ѻV%(_zzVa>}:X?w<A7qY/ocE~p,Ǭ*cP!o);&ѿ_=RKͳ&ϵ3^dW_KWa9?\Nkkޜ5Ù=rM 1v/-+9 hOsSC? A*?K3夁EonkmO/AwK B˛Bnoʬ=ftXzPXrzϔ 6cJzu@ P@8;{\a52# >s4y_ un()\mtL/D++Պ߿xUf&}kz巢w>W8`ש /n4wI {[mE8"GOZ277/&1~:ld-??ζNLؿs2p-T5ߩd%e=LY \ x"eԱ|écV^ Y;Co10ϥM٤ m{ N6a[Xc, Mg^|0aw@P4Uԟ)iFv_ڃ;fu+m?q'djVzNyjr NҲw_j _z GqKb/}p:afLsv~ƶ.y9?uoB!FD^IΑ"9?\0p^093~TM npj6߾e b:%8<:ܘ7_OnRQ?#;MrS9 F0ИPoRf%>⪠4?needtR8P&naw|dHu㶹B}(\ ]骑:t|i8\z3g: OtYPv+\*ex>;+/8kKV?-XP 2ܧ ٙċ ܷ`kF΍!ƑO?H5uu2f_apx_y󶥯@OGE`R$P<VD@c V2'@hj+H5_3Ee>]܆]d/P{ mË\UijRw]Ʊ=;F}7`[e0TO|ި >M=i.T\)ؠ ,(;ET )Q }OyG\Is [=ŷOvuHd3l̙*;:#}VN>8n Mt4V2FI3<04*{R@G]-щi` 6sLp~1Wx\: b9 l•C {j&cniv΃w޼,F"36Ay팫|ڵd]溾dS\?1vt7pPկz}mx45>gܸ&~x#몆mӶvǻF%R/+!?$ rRf6Ŭ7$X;2Fi+Bv˶ףž[;_u#\R2\p.47?nJ\xϿM.j[[$+)rL*g*W(88񊁕y߿sN?7g7oQټ |<32P뇥UO}I6B@UcS8uX8ǢxWвs+<ˏwo !^WR@S DPzG,?FY쮄_PSK4uO%ݱDo8 %$k.\uJK8:?s\.X8\$5cq_r;6Խo eޱ {hytM< bAO[Oa WTڇ yTI)ښy=h6\n\qv-WsK~!pMihpy،!%O=w0ԂDF tHK n~l6GϞ[x^x[7mt.bpaeMW W=mjψ=/+ \+5GIOf54(HOCzonޗ.pt%=eIȎ/?7.1T/K:FgV$FwgWQ9-A&ԀM@zS"UJ@:" ܽ RTD@uQA$A:@zr)3y&=^{wϝ9Sμ?jꜗ|gz l]9^N?5;JܿRimˎ!79jCO B B)~s̎KH˛W~j}MϘ#Q[FCm_i;IU^AZ]slhn4`￟ٿɪ&t645vjµ ta7UUPTnFqs]Z?ibGܶOu_ې8ၢCfSc2@1-e_8=h+d;'E5oDZQ)&}OdF򨭯a'DꋾquLY2ų.W;g-وc87+ Q;DN`t,&f"8lWvO=u\}mش,8_Ēʀ]~~zƺХՑ2" B;"űyhSo_{:߼a'9?\l?=5q#dnX1Y>t:|ggGڛjU4Ʃ2MYJҴt@Z0mn=uŖ]LZ3gPGuԼڎqb,(ȂD'G\2;R4?\;ઋ_NtBtT+@D ܪέ>=i/Zs(>IIQpf\6aG,(`0ЂY{C_G~- Yy)w>ʊF]}M-?Qfo.ckj Cam51>G:qY(lxUb PeҬ97V+Xko5] GG@UrMȢ7cEx4tvýî0ֵٝN:vp_㜍isO} >}wqwex56rݰaYS9(mҫr0Ӄk®[ohj#}fl~R 1,%ߞ=i,knUG3k\c#֬~n % Z$;;bjwمlSucj_GLRl[4ϧ rRYͲo3JϞ½~2?_v)sٲy*Nd27>I;Bfdd랈Ukoэz<FDJ!_Qf{~$6bAF49a -C EFU9Ȼy襟%IHmoiOKa).8;qA6  b3fMEPY UL|%3[TRg?{8!"c~S=x{Ё7Cx/[pjeA? &nL!xdm:=P-_rF),H91…UgP8:6W3 }aeHLoW WydB.$뜙`]̮omm:O }՛Ȼ%G3/r>ۜby (iY8R,xnI;|+m~i/۾?RmՕ` \?6fCGHD0 8ތa: 2LBjW%./S&aښx, i M”^2lrC=:;nMƒ.#5u 1ESI7A+*{BS ц(ؐobhixd7,i$h]RM>ҍ|ڜ 9_qҰdjfGPϡ.ڏرMg`24H8UJ-Y 6ir,012T&1v'9X ā AZݜU3FM䲻B}v!LNg Dca¶W`RMtyZ9ARRô *@+\1粐/Rz}G0<䧽K}眣l7mRo6 C* c 4 5cmy7P=ŔR/ol] [*l-wv&ov *2ɍÚk?X )vV&)rbRJ26nxmwL([4Jght~H?wjq60&R)蚆743 =iB Hg ]L[("nѸ r,L |FGdɭTL#S8xD_Qo#UrihjkjN!S!L̴ 0 fr0cap ؀B9ЕHp&O~VSI{ Z7557Wo#PЪ& _{C ,g[+S,kf^?yؓLL:`a2YU7x4#,j*HlJɻ'#.^㌗s_u3#50 ˌ2LJ0_H{;Tܲ=TG.6Ѐ ӨA.rEbkYShME-d'Gt%=42{co.xvno,ܮ\-&gVXb,f93DYH%ڌiHV}a&wc1NU&z9 JC1##7Qmp,$4 &`Ubl.=oMU/tHYB6&,`1cڞ8昽1ilB$B$C!]ʮKL=m.̣9z=RF25jj~RSxr17kioU 5ÊL(xQHYMg=qޒ~Q w[>Oo>+᾽c Kp&J?9LToOd[k>qyuE |9PiA3nRs#_{Ʒm/| 081p:MWkd$D|@qo@=ݳͰ/L\ %Ix5q%DV%ӂO84:|Q /ţ.@TJkRN(YXuM\wd5{! V]jGǘ-w9:5_o@a)„PX3у3AB{a悫qx6yN}a|ڙS<&M˺# `s3Њ@$@ HfP "5pM Rt6QIݜCJnz]dXߩCL^0F|M2{{ǵ"J9sYw5.g MvpBz>pd֋V3oR9+!>o<9wꘖLo42 _r 1Rb 'lځJ'':f#p8t\A@ H+j~f< \U״Ty(4P\Y%}M=QvH)M:|IC4I`r L(0!! GQ( FOT"Au]]馦 媺Ji㌅ xMǑb1&x'Rq/ECJR)ߞ:6z SA[e:LmES@i d C^ ×Eaʐ Wwk'_4O@K@ <1ߋu+0a8Co|hŴ-lHmJ~c3 :2M#)Tf '߄g5a]$\lh1!L_"E|l g"⫔M9Ia6EY5XdfE g4 OLvb_<Ī7.?nc^_' p#5NL@ϝz{z[iE!yĪuLB븃^vrcK/-{^HZIn2 r*@$x~!Rҷ`U Sgwr~_b_P*ɩn͏.w=f3  ?l3u`VfthHe0OI/q"'&)*ئ@F8MDn nx&%MӲ_|~#&f2t,HKNn{Γ &T̩a0<;?s(z8p,?o8N ~~r0Jݜ{(tm0M!~TUD2 mS,&]ZW,Bu.65TbJ3M`p : 0+RA)A#PL6Vs+[ԿL`Wt O-J߷Lot$ ˬ$!cdZpH57-ÅS.Hc&>&9z޸gX*X=(^̷CU3"0<'\ È@J֕D(F I0J3/~w\C / ?AfsST%LWW1R?lSyi01Q[8;_9}9@!F՜6ZHGΉc1KE’bUtz0* Ie,0I0p;J3 ͵!M0;00@i 9~ 7!dJlG\L^zSo_xi<[܄' !lpf# K<9ݪOoaZ⣺mF!"t 5W \1ׇ('nZ>Y{W:1Jj(՚łe?_xK~EK*pכZv;D4ׁaa#gU8j S |#VY2E,b%Lft,>Cx<0jI5 {΢.eVނ`L |ef* N 5ACrUηe]k g0 ,d.[(, #P9"H0p t f5B 14 Jʇ"ǶN842ma}HF+~I30]@G0ɶ#UOwaZ+1>A+%H\c:(Ϧ] eZx$]8 h'AJB0@h@jC*Wc҇^xXݵo/yAЩ%B7֌ M ӲX9w>$}W/:n#Wx[6VU{Z+׽UY|(PFjkkG՜dv 5A,M|n震`L X& gC:Ƭ5`Z=H{5oڳߨ.)lh DV(X9q8КX8T쑁qĜO %I.,/͞1~< }%o1YqVdr̴map!P*Ik[|Đ7 ^nrY<]BCsK -نe2-0 9@y kAi& JԠ`L`g/BM[6 ,pS @ڂ fB0 ha06oOTrz3+l&p%p]US  L sx7МCQ0Ƨ} 'al 3"8p94MJBPd PRqhmH!E)%" <`9{{XM 3} mP$#dY8 pB7 7;Ό fÛm |T~e@G2NvC!FPg ,WkQANA#Lm4y}ic62R"_L;Vnqbڟ`B* bI Db0JևrէLUq_dy]nֱ|WJ5 6pǘؗ;}+~uo?3E9UېJd%UR#yB f—4`}J,?aO.~}rfnmusR*bwyd)Lg L@i/{ @-@ID1t{[?ø G`@&o-8@@L1E3W֍98 D ^ǀ em8Se] *l9cL6܃k9Ԃd3Sh) Z]Ny[1V `GӲ,Hskkj9L` 1ds8ںP|$#2"I .~&~::z7hPN w#r}BO^stgbGj:p* ʴ"*]TL7b`apxҀmm#4cT0=e hzgl[fWWyY@Q)xtҶl'_$_g+9uvJMcmyf,E.V^kMjh}QĶBN=7)9)]W6z@. 0A(^st#;88ulttS+=0\K|S\ j&f.UIoŇǍ_"9Nj-yBI ᘃa abTwjxVc"lY,d o Zu/m&"VkoڿwQnns"\(DUmif `Ѧ"@" Q4!|(πKxA4>U9a0nUaۆ}Hq%fiY$pAҼw5,Yɫ,'4K뿜ՉM=TW$`큔$U $h4;}e5a{27AAET,6*z xIUZyeHˋnOhҀ<"K$Ф@ (P@#^R j"*ם-\s2;5L=-6]ڏ.Iht}-?'WȿGK+7T؋;8#B К8b1%.x@Pr0i @29o\5@if~jv\hw!||{Hja \!#W@!(B Wa¸X5Z @M{CWuczm2iVخA.FmnP%L8GĮe0M0:VtU. lLG"R|i-vͦpL0|D 88 k 7*/a0eVHv(7%}o0L Zi'dE-oJuigD0j'7@6P*XT1hm Io$LW2k>-v,wv&wxw$bI? ma-ѳ=镐>l^S!DMyo崝c_}ïRti)ZKcٳwE!U^&!xuy# 0LDWLgƽ5C 5 Υ`&an =ȗо}J߾2yȝ8/\Cл@7\Y&4湥9l/E @І9sOfǰ7-}A) "W.ФhJ`<]\H8]tҏRfsd2jE#ɤVq^~VIkZP:(3^'%[~*S_F&Z!V> Lj<0-_9%7m\AL{X1kΚRSs_S 4dpP {oY/4ƣÑÿ6ĉ{4MsO` `;/wClP4\;/! (<GH51 N<_YDno٣6ULx0p7_Z  aQ‹߀Om!0ddU Ƙ&P$\֜:2)2HQ*PTAIi9aY,a^CL`ps.0-y|1(Q(8Px? :vBtFkKX4 hTM:bP֣ELKߗhrH@vZ67׋T]^ B$V`^MmIĄu@<.P.r\58~_}M8f+s1H_1 `L+x} rڻS%w @,b:NB:1u`p(g\K-^Dy-14$6 "{`#>jG6 "ڂ >{NV!T#[ԅ`0TP$E"CJB$t|[ۻŀ}QA߮U`Z 4gB[LpYՌzAXxתxH02z}$KV@khKKӺl+KÁdEP%(@fD`6/L.wh*ֲZ,5A%ɷ" 5``"YsN%Q̛ Iw al^uo[1/ H a9c:i(G{ko UdYC`'9s[Fvp7rsWjF YVɈ?_lC % 6nr=\Xwե4eJcm$z{Ss3( 4'+Mv*B^WTS(9ftׁ&\N{(aJ)8!<n i?Uq Ǻ٨~Cļ-o|X2{ Q*-踃T_zY東ӳe}ݞ B1q0,+CXQar]5SNJ㓑^B3V-iT*u9 H3)kv]*>'BZC{B>t@-ڲ$VrT{ۅ4QŸpéZ]a0f |~"]w܄SʠQ C*ǣmT?ebpE_E-ahqmGSc5ٌ>uCHdI R„: P`FuF=ͽ[\Vc'}8\I9,86h.LK!88, nWU!t}}3a/͌>8[V\k/I3~@8yEԶ1~67c@N5" yזaH0s]1{[+S1X_nV0 "i(eb(3 !7)]|Y~]hsSOn~~w4D˥-8?܀a@Fh#bLfJCK~ۚ'is73}6I %|h]0^JER@AY--( &bLjȀJX$(0Ƹ9eVUPmAst^V~o&P|ޤUSc"=oؐZy`-yHD>qpSpl.cQa !KЄ:T=i\l_O.\QrҏCBTGy6/ B mlDǸDku ظyChdG\bb 0KSu D >T!Ppye.=x{L@t%vtz ZyxM;̑A@/2fuPe!" 5meKkѹރEj3Q"%Y54i( rW6 f+.`#׼7\1[ l'kKj"ʇT.,9A~-`IޑJ==ԗ0?+ ᢀen` +0?47<%|izbW_}2 G(VMIJAy>m Dq283v0B!\t:x6p4lF yؔzg9 BsKH9h_{*wzZ'f?;`ӆqȴ׏3qH+LYDZф?CqnAsִoWc/9׊s"hKP U,B$:HȤV@' v-9Cn m0%}:|qP ô$s<xP?  ;,8 hlt~ǮZ$l2P1嘉cЦtѻ)45d:!.ʻe%/T ӄ$')J [/'Ol^ٷbSmԃ|./.0V  ,J-dK7qbH@d ^ʇpm@$B k["5j(7h*Sy!#fѪ4K rڃR zS@+ #fnN"i@ ?Q>y}=Ţ Oz$@Ridy(G &^ 4Sb 3g.n| OYH/ {BxiLc~h jMZ.~?وg2E@؛k_1x _XL.t|4,e4JZp^.-Rm@8hl~w ) IZĒ*Շ(e3fmMET ^ݟ9ehS>2k|Uoxd;M.pj2!.kg^[ʯR7riD&k4 xrvkseZX.8gaٳj exE7e3oC)e}Dc/9% @*P 5RSQ ^7 ~t?rJ q%TOnXXt aE:y9T,F_JcؒQcH q[{׆=1 +E( !dA>(Z`Q]jI=Ӂ<)Zm Jyd~@^VI Q 2@7xޠmme (F`#YdY8B@gR*\.ED`(}+ uKN^Jn"3\YqX8d>aZVe'V>v6UwO@hFD8G#,+~_"2-S:֒_mTWv0ie1#R, _ Fx2m#"bJPGY 4HR™ KE V y[ oi <;҉DBs^_ )iew|MkcOA$z" iDow7n* 2 "q0vz<x'~̕[UzUbGĠje75Dpp!g [g;-I7M2D#HoW]}+"D{ew1Lzkhm}:RZ,\7.r 41H8 !]RM+_i0Ns>זc. eFQ':E{O{ן?KE(Spu@x `a*䨻q5gҜ7RIi'Ҧd׫Wm:`WX́lϓ Hgs_u׾lY 3~1߾+r&~4đ3@d,m ,_T!}c?<7>oAwC`hDJe&Kϴ@c~m٧zj{I`#ͣxŰobSǛ_E~@d`@51A#Y-_>t;&8cۯEMEKzw >B0r&Aشf^|S/쎘̆=fqQKD"KMN&FPSCz?H`F}T3~B,8oX OhJg@ !Xi t.K(2rD7K{{~\{HhnV'6@( a1dUʡF .Y K F~8-Mt&Dj+Y38dIf %r9!^1+TJ%\u >xyq ȻTڴ,f#/q]0&o^+|q4Gva=x Q@Gwc\-򫎟 hc$KBܵݹ>aAP]S+(Rq[JM$֝0H{6/ %P@+R+\@cl-a.f`B-e+K Iia.*aÀLci|U, KBXιw%DgB\ܞ|\#r5 a07(H!Q@BRg͟8nuI{wӃ|7 %H00C@(ЎU! U5e+{ ??x}0,h8޻u06/&,b[%&min nx~xN\QΌ%qHnbq;0/Y>l51}1DiIRU"Wbmwq7{=O{(%lTC+Kޙ34%POFUrJcʼ(J(t*m]KOmjW;b1*qQr!#YBAt_mz(w,c0y[v@u]W(!.`J 5CUU2YӼ6 m@)s]3!nzufB9>MAC!.\rВQu0 A][a wJA')/`|zA20@, 2he1qs۝Om挥RzA[׳=ھ~yrl7hWj|M !\]wdSc_{m<nq:0Ƴ*᧳3YHׅ( p{ztLܾ~B`@, ^UKrc:D&?\F# {Z_͍etAf@q-g UӑM ߅ ă-Σi_J><~2>7߫C!xbB6JFAPz+M-̋2>`8yeG1%iC-Y_;n=_sVMaFW! McZ Wc\U#5X^ Зhxq'jP%vxIv0ar˰07):/{ο3*Q ao*뾼_!)>s`1dO\C}SLx{lx r͇_>Q *q91IlJAQI (@0\ ,ŷfWEsnkmb$"];T ެ1pns޳\#ߏD`78%ٵ 5!}JX&{|w}ܳݿ &=o?Z,ߔY74#6}qi:{m9k>nXIv =#ص^Z+Ժ^hmʕ˺i׳MIqU@ObZr+@I+ciokXtΟAQ@ slQ$adgݾą| Kt-9ug> L1f03uDs257l6Gۯ=I5Kk]sƴD_3iť RT3 R2 p_%8i?K=ӮS&E~ &x9%UUa0ưX|uCx dA[Q l-Svr[+V?e~:R^iیhTZSͼ0irUMsnl0 fIhx֯/yOmwin4練Xc8THP@ߠ^y% i Oc,_F߹/FK۴YK8|ma)<> 3@h(_3D:J<1*kî9x 0*x0pAM6o~l[>*kmm Mfj|_1n!{x᫿a-kh8paRo8"JJR3>J(M/xj2 .F1JWC-#&``Mcg8_d:5=L\@|CǜoJR\~ʖ/ORzȼчL/`R&:uI+}Rd`1뎋m)_7n)a ^\uuxY.)xie&U#j;#_t Udžwz?TralAi`6L86ꯋ0s0GEH&1, Xl`*}J|I|G4$g)S5PpM+3C}{|A)} SgX1MjHiF߃Y _OtBt} d,7[dx(g9Ba2fZ^PM'-^ܽͼ~B)@?f@ |<~[`+=[ f2xJ?x6A{ƍ;Im]MF@S$WZ{^vQ%}3 FqQ{0%-gMW3G@Z*zړ?';?jj h?S됡T!KJz}<ׁ?"&RrD vt*ߝBJE4@\acG~x3y/ֲ̓[>?ΰ'o[>X2dKg.eH x~b&0=g{o͏#9"UZ_OggPL$١)p%PZަ{{`eI;ч=bgXbeP ϬKO;6fS=x+ԬЂ{Z#C< _\, |Y@@"(b}228t1;4_[w/h{`FM jc.s粞7Q>>VU`q`w1s-^LT2Fm^7<ѽya~ep^XWx"UΟ'WrQI 0-- N!)?8{rO>nKZwkExPE i߯Ge?|+/6˚`(5@5)9>~F%)V.||2y&aA$^\msCfކ]Y[15[wD>{GG,l3*DIβ]EduS+K5w=a쪺R % /vP{J~ڏ9׬3g<?slL ɝDB$QO!ly=+#%wT YI`AQ s MRn-dFWv~^Y:I}NT.^k]="7̥}j5bO82oyQ3T6Nu瀏zdGTbR~/?^젻gֆhD}չ|Fe ?^4+$ҥ %smU^`0>Z: @{cՊ;Wn(uЏ-uڽnّv˱gE ?Υ{.2C)Xgs4$x|~#憽">0ίs_:?k:f`] DGmZ  6ջ5mZù;ۻ6Pק3 $0s)gX?F$_8g;xw-DFJt&"O1w}TlL՜hpkڛZp wǞNl?е:wNW*F‡5# <\LdZ% >P7PX,wߗ̗jֻ繁Ohhab鐘U g8?z=p\gIDp 3$}PN=dcM$fjVϮi2`9 w5 [#Yer#XtW/w҉-Z|Y8h6#",Q wGQ 'rJt΁;ols޷w?*{ISk0:i{ys(o)4?:Ry9hsSa>.l7/.n@"b]9ʻJA?va'+kb,ƚ!݅[a{p kiexrHiDow+WzfQggB$zG)T?$ی?͟fG4:|_D7Tqw?rƆPXX=^Q.ec3}9oA2iMo~ͬiޛ2i"zӹ ; :I-RW<'_C}{sȴ!LQ/7?.Y:{ >fٱZB;}1)CKˋ[">~FJ&یTj:R@<8#0o]J?u{C3!{7e3&Ud 49\VJ0`lȯP$-C#jX#s=zwH$畄+Ӟ0i҃=p2P^`^PUu1m JobʗNlU@ !&l`H3D2MˌⴉXbe~_7p%|lObKMu>wJak͠ti{ϼyy<9ٍkxv~/PYGsX>h) /"Iϼ=|"N9>JNx u5q*9Ey۪ ~>>Ϙr+wzpB5N'H *ZmVvcϏ~T2g qa DhyzӨsLccJ 2ӯ|vyF]~a'-U-HYJ*d^+k޻dL}*54̻XWWo>,΂#Vq7sN Xҽb \I|:ovis5u֜뿗߻#0$E)&HQۇ/M8@&B w>]\ X2=*޼qƳ;Ee3'b@ >%,V/'#ԙlSK_]zq;9?R0TND~@`4`MŻϿcՅWLw,c`3<..ڸHj40ywX5{K9l14`FBo\j_%Sd86~L)< k~j NK_Σ3Q|=/O~llC 6cF4GquzCۃ% Jq•F&JrUs P~w/y@!8$|NުzS:anABRL?C>Aʀ+0MA$.K_~҈_]TIJ}mϯ9Tquп{NOZBCcŻx~`=LT5{:uO}|{`ϛg7~ed}kWיiNx8/R3KZ?=`} 6up]t䰰&E>?y돼4ؑZ~k” }.7`4!R6B`Z^ hʹeK߂0l=ϻ7x={}|+e2ίD*G^{va_iůE- hUʆE B ^$Ǧ z tE\%Pf"ٚ׎ڼ9Tͱ~bM5 86uoΟ!O-΄xhN͍76ՏVWūyE}G7v헺#YAcx$cN ʂT)Ru0Ha2~ƺu#0`y=p0y65 #0x8flOfX.N}uSEWЦ%@ ~( Z)2 KƆ r&Q~<9;||jq|񭐒w!`#+OVJq˩/XV1ͅOݙHtAT)Jt\c͕PZq<#\sȦHbcpOx?xFH0q~:u>\G-Xllx$釞Xe ^ ܹd5U{;1R*\ &g`ÀTЁ"Ρ`q#={]}v.S5/m@*C̵zòxps0! Ǫװ呿~=_JÒ` aЖ1#3Zc/Y*(POT䐮.ǯ'kT~׮{}dSuWU$aVAwïOUj#=_d\KƈC8>rx[}Kq`??ѥ:'gy)j:' Gk9LA{ F\iJՋAlxGp3!]<֜(ɡ̗>&LO&6w2H8`[\ W"OM& <MieRX{-W`ȍhoPK(I(D ^QÉr8a;DVX=#2{t̜@;۸jS +E\m\}Z7b)Rg&VBFC#Uf}ߌU0La6 8T ;Ve:8FKh-u|ʙ,+}_ha驁`Bφ!<:1oݑ) /ज़6*ɲzf֚TQ*Ƹ ׃E$Y#g0󿓩ׇۍ@KO˞u DaM_~)qin}9vpToF Al};m`AҘ;7%ٿs1Cߠ 7WJ[ik__pt "bRJR  sRBD4[&(KEۨMmJo:xCJ}g O*U,vVC#Θ ,?+;;ٸ$8eŊh)0;TP"ť-Vd ZVggGn`^7צs=cGϜubĽ"nmI(+kk6 8.sfTMj^O9"6纽bNCJNKۜzf>n/3xTe}sV K6ܻ{?i6a3jt _@P`wLh.J 8`R`U)ai+/5eΖڮQD^~i* g=$?ѽsnˤlH)%O WցzM]aZdB+#e!UW׋ DאO'2P8' Kuꈝnn0)+n|=kJ.C3 QHB#)=e_ i[UB'3D#R00!]ݲ+$tCNESs{J~| ڗ 'j ($ҽkNOp8̦K|y޽ܮKJ>C3DׇHX$aHbT(`4}*k'ӫU\ cB^ft>K??4^3A3[۷E"v>ueiX\2R`B h(/tgVgIР4~kxՓ/ U֌0kFb]#oŮ&H;Q bOy Z}Rv7 (a%2z'eքb d3HZiN-hDÉB_n>ƲUhUQʄ\!IY敟WcP|s\(\IOwWe3Gq]'҅@Q CVڅ\%H+x "X: 0E,&jnABL*l*1 ?ݺ( ^J*(Cfp͜ LQf,'RM#Xo":uӼm?*+FU*g!7F_-fYHw=2.Uf:RkRMZRt l\táà y)҉"v#n/™'7+h4* O==ǰ=RwAQ / )(%~OTβB΍䣷~;t6EzTPzcZ RnBr SX-(8 _y=&VJNɼn6zl0A U+BuV[ڜ|j@j)J%U:D"i,ʖMzϠ0 b~%svտkV9%Dsm\8W!|/<W1m~xܿe.Pb; }T"'Ci]r *8*ƥwfHqZ];Khp]A.|1N?h V 4ÄPgFMӻfT:׆B CcxÔ_ҁƖW5;%宑RW&q Vc3ppJyq'Gm!tF"UG)-❝2(哟]ɒM7YoP.lM,{~c]/٨i &^_)ҙ~ ĩsߞ{*If%K{5/\X((P0IT_gS Op+DDh˷usgE7*hzCmydur(SV|RRHeؘXGo€@TBq;¦9l^4ƿ˜Bھ`' ;S‘S({h{S2@|‡q!%Q`隧]VFpꋃ@œ50X K(8K~sݻ}BOvx? |;#HME2c9GM{JJJ/H&wAb߿?Z9{\>xFO@0I.)mJk_XjQnVV)RjZp*01K"--( ֡tw#\#vMe'yT*gI6v$#ċP4(dȵ )9x"q\s~-GGsO\j[NSdxvaCN!ė0=]Q[,M5*"{B.L'n" ba1*oV*J`=u_ 2_U^ p2i^bJͧa֐W`m*qEn)! 6L#ƍgN6m((ǂA(( -sSʵJa1!J) -*.Sk_E_gg1wAhXxPbU,Iˆap)]Sv.ZK; #s1CN+-薡lG{+lsD~l?`bDic| B8QЭY ^pG.d\A0nɕASV Rp_DnoB|a0D_Af#C[w tpx7[{ax_6~ۈQcIc IEFR Uix{+cg8yJA1PBUW?t{T/+D++wяE"MMP幝kkKo 489i(R N@WQp(hQBXZ]/p}uRXq킥`*) <=+s?CybQ~:F2Fҳ=OW;0'2)kP a${`m(1T68=oxcKH== Vr!߅-])`H:u6DI"z#)V)FŃ3GkpOgdm| !$~Z;Vێfg `d܎K!tT|FuR_e0ug ʔ2JH XY=[:VƘ k?$J`f:["߽$Ʀ>Ե~Nd=XH[x>:n`WCpʤvulظ/qέ9yMsP B4]"+Dc,&>/Q3$F$'SȊdJb!7uƔ8tJ+Y:K JA ZC+{8Jrl 1C`n$/:1Hqd.!@Tu|~U= MW&r^ ZK!X; гl .A]H%h6wMBNX"ΝBZGEuUuҊ'ZhcLgP<M+*G(B 0mAJ )HA |[L@E"D3h:=#/(k@aja i3=/<=-64RH *!JG$%(覉-kW!՞D.k~?yWVB yO,rDNQMgi뢈^p͡V|5ۙR J(aDzUX>MA^b*im'##k c4:)8"J 54 h))$@*_ o^=kdOQI($G*F u8 qfS)}UlpsMr~Rs׫M.X6H)+'4t8fjˤJ xf+(K[#dE9YPJZ$%s]Bs,[m5,cI ^ϥ{qإ`m4jU*"~S^X0& t?ʌ KV]Kw>~ Fw˫B۠QD41թ2\Rf!J3-(GW3*% i38v1ECa"~ JAxAaX˼1ao p>ˁRR 8ea0z ڍ4g_T~Ds8}RLi_S#R8`pdoJ^&mm$37Bm /F"M\ĠBj|1^A* F`"m[`(3ʤP\&*<ɮ>XJi H)a@|dX `zq ? \>.q*(_,&zP'Jh_yE]Os 4B2JR V ɧTc  VPR2B,# 粭sB kټi#* \]%)# { &. H&'xJ6#ГX Tл`n6R]滢2:'4M$rTI c4,8m LAIOMJPw.f I(04 s(E3B%)뵲eo;#/=;[ *f[YK )R R[DPPx}&KPQGԅҀ CIxm;PF9)S#4͠8OK҃uEF.]EŜ`=ĿRARP%OϞuL$ ]R"Njkmů`̋}m;TK,KVʔZ=3?r9jHDG{u.BB`#썄f~ZbyQ#FOiI _PL)^憀U@ >+(% C 2-yPE}{)R'yl4GS'+lxF\G\ +ޅ\zXAH)1#[hEz w:tJF5v Y9AcrYs:9ٔDsFU!RA .+`rKG AÞ aw2%l5U,c1 U7!P b0 BGc]P.n宠n^pxxZ22VD\a0,aE/.A(plpۂѱt pf0bYEG.yE!X+~䜷V-1{a~<BP;CQ<[W$sDCy"!(! k?“;뮝V\(\ppI)r4P^B{D:Ϡ ,*YJUW7q7 h yk8WH4)w8LÀeC1zsp!PB͍}-E`!(3hC"wt.YY`aH.m V*DWy+}9K)OǐgCA@35~^C1`g%Ż)؃0TN6^pv[;pdĞlJTg!rk3''U(T{K*Zbpѫ%LQKqPR[  %wl8Nܶ#TmY!Ly=+C^Lav3}Q<TL׊a XHdӏB6wԃ?s|[DV{ RTt(4Ѻv/a/oEf~ԣHo0f 'ٜkB_{?s`ںw<U s氖h3iϱZCPs>T04 e'2XA]Dh˃?D,hw~!0R"S28mMXo9~elmhkF#͡'++i%.Zt]9/b9ږh?BFnbKJ*XcEzlqCUC(8xJ(Ɗ8oČ]JYˋC6X>௣J/lOIC3 B=ɤ xe?MBO_Ϯ`mG9w=V{H6`BC'*ڒLʮή+҄tC0uƦ%mrH1g2>t!΅60h@B#6J d<뺐L;u02HIB0frʣ-e\R.t8CH5Bq8\ŭI C#PJRp*zh(-x<.ʘ4 Ŝ.AQ ;DtlRB9[\(H!MvJTA}!A689JL&'9#XaoGTv%)|[tWr 7TyU~+MEϷeO}Pg94 GHc.:?Hvm!¡-) 5'Ի[]~]QV !v׾׿ڽ=ֽ43Kj-}29P| vUJ&|SvGɮ%Iۗ_|H̝K*cƍ3ʟވ-hWP")`'4Hvu"30@\@ svR Bx.wSr Hʊ5@uFi12@(shFƾn^r#٬+7T_źU]LC4,b0s4/V ڄ|円[( bu!ggG. @p) 3G**m uhSkת4cͲ)D]Kh% a3 j`-3H5#^8;ՕF1Ų P]CQY*(,3ļKxo7j5F&~J PРbv{Lc{?sU)ET ZxUw?G\HЩ*wcBY! ԑDzB=jʇ[b+ H FhGٗ%#""viI^8;޼U?9#si6p7 3RSVWx6l?&Qn/9ǯX[Ce-m[lߓAKT+لQ>܆W'Ӈ͟bi xwGڠ 9T#!CJ/ ۻM\AE_CP^N).)F_t‘)F,?[`op %h/oO`MRKܬX񗼲5%#eyR(1M p, M%LكI 6y}xؑ4åREPMR˹*leģpɌU!'B'}J;a/]{/qzTҬt{ WVd/o/_ bߩC}¡b4A@_h=vd _ݹ~R"56TWLVTTUׅF#r p ew_R>y&*w=2$-(nC"M1\?`%ZlT^hޅfR jق`YV$5ė/@{3 -ńnضDobX)$Gˎ5Zi4>ڳ#!J]hż.R6%e:B58=͆x $(!?TUJcLdkr0;ڗ:jGGGe L DFy)ׅvB4DŽrd>*n((!Dh LV$Ap"Yױ {0z' +__2c2>eCFԻaDp (U,(C8(";.N>Dh VLCZrXbTV8٬R,aJ諓xVH2_`cákJVT|2i2B]fh3 wMB.ԳIwNY15LMӶ,C=Q2 |R%uI˗ FPr[dשa/0#.l.x%e:?yXCy9qp.q2uXG7/,#+nظ/BS|E $Gs!TEBvK2w y{Rњ4N ~S6P f0dc 4 u_,vKg!tɥ '%^," wďMkna8c0Pn;Z6񾾩*KBO xL&K28r,7|Tv9=O:8T@t^7b[q@񀥔Bss8\@ ?bYb5U`&)$@d. .aBPJQڮq)k7"RrԨcDAd5"݂?i,|Ŝ/D@lTUպ'X OI%\%WV->_Yx*.\S/lE@"'C4UK'>2w0\x:ޫU"FE09ѽC֙U_v0XxJDS-EZ]4z4(V92@7xNoP%|Bۼk0NJ ,ev6Oz,F?"݇|_.Fo[L'&7b )f|tRB˟ Et> W,%h94=BO7K[i]m("Rtb.MD>XL,3G+CgnNLk_U92qD=RCFIܸ^ٲ3l)hѨ'&P E"G`c/v+cլJ0SNډSϦ !8gub1nf7.I9-R@+u+HU,J+>D7(4}}E]{ɽ: ;P| BPP%n.X@Ig .zDIGרџw,}~[L\ayc/${Btaс">C} )ciN|::Tr3ۢ\2lfے)e1^<>0#m|u{k|J]V.iʖLHer4NKOXm{1[NxfnKjKJ "se K$.Y{[?:ODS%{?K{ϡ:`(JA`}G>Xۆ:6q*z9*Ÿ-+HcS#|*1t?t#@uOg $ڿFz RJBԗޱ %!Axy(WMh:q94(%K`0 )r+6koDjA~W?j%eHJ{6- !Ō6&bˊP5dLm!p]C]oAs .de(4IJ$(% KYY%bbs}0nwA+Q;D$st7g[gw~ NM}ϋo )dzu&6U(yVV[ֺ}ALGO]ٓygw>o,HْeE2.ɥݕ^x@x>/GO6mZWD"*4 Av~;L0W3J{@%֠BLQQO)CUrZsS$,BHR_YF5!f|\ %5y5@sUMI C|!GT+%f9HeiCi.So]wGa$[k|em$q;ՏPqqi켷㉟\$*D>|pn/zZ2m)I *5S>n^rqM8}߼?DQ Q G:5ݧShZ8'| kouc8yF?ymRirkv[ mټVqbVnO,y^A TaSjYcԟ;e<=rij\ _yJ) D12 R䁐_սq᭏)p^\kx<XTJXxCmB8!cT~}0kt-*۹]~D?P%5F$P1؎`c?\A%1|GXЙ9$]R!gӬukw= FCynKuObrWT033!>WIɋ살O1x%g;_(ƘT%G|SΫ/UY Hp^\(U,2tC' JoMwƳvwrxC'/8E(t#ݹ _B4Ca2膎4I KaʮՕG!]s,JO>qK @bo14QTbQ1~i@lSHͅp*88*-m@| _9w];Q3Ldr >7e WgUep>lمUDՖ}JV^K2Pd~E_J᡹B%X8%;YۢގDsі(ׯ= |0LJC3%9$ !A}HH8Q\TBOn|T y⸙ҫ66P ccDUyWWy'oxJT(JL"]0E޵&>翅9жSMDIT9}T+9o#.? _eaɆ7X^=島4@l[P)\*djnU.z` afUE01YRj YbJ $Uqx ,qZAFp7}^kIʘA0!LQ ++ݓ#t=b'Who-!.` ]Pqq}˼MM{_s/8mσysU8[I`J1u^d555pgQL?JWi<|STO'4i D[EoZx^Z/z Q1Zl Q~zRMΐ V˺uR@()2!(т/Xl!0Bɤ 4@b~ Rj36Rk} }P D@{{sW>  B5Z!/ҐO =D?~ ic k\ tTb@sCEzɲz }};ma1 /Tl/#%¡aVi\6/<+ Bu85myB04Fess}d`kC cjL((![z@q.$yyomZǶyz{KW߄S*F~L7AN_'n\pr`LVN+FJ{C.?X5L:)+mn(TB2FH8O1K8Mp:B~fs,y٥囿 k;JPѡcguֲe-̥#GsJaTEc I냲yRRgUU!8~|m7<3bĨroDd=<$'Iie@nZMr*A3YeEfՊ'pWfk`FrIG.lYi QK26'7]z:V5*z *Zc QޯYc,&Ϛ?V>wGYES];4`uF,^bᤓI ld҄zzd%w3dGQ;+ UƍR Hɑ$G>^!ujXr!۪?b󬳛s86/ J) ӀYf _.n_3~R 1^ ldo;>y$'CQ̀󕽅d"o(Wvhd\@eS_못tC(M=0a-&jg_*tQc,ޑ{3ۓ;ݴ!ْ03T+*/]de9im.0rBoﰍt\#|!\P)x09y$`^>m{|رcv0 6l}anN-<~lي`:cm 8"6/"4J~)hSS?et:( 샗>q潔jwyc򺌧Bn?mCi$f3o*\r?McտxVQm{9TJ)\jRl)͋~voߖw8~u{1 ml(臮Q)8b( ?y:x6uvҝ> {{nϽ]m)e׎j`;,فuk76,[s{~{TZHWtѡzi6J=]W58 5=b. D.xn3GV46L$e{[1w`$X,&!˙9px@n.3#>zD9$XWZ~%TP)XJP狀TobśLk.g/u+kA\qX7LR~=zoLl1:Ie?*G9vgq*,6o(_9~= :5 *I+WHw/H.xn;HJūVJ>ຎ?3# _<U(SKx2 =n~ O4Ybt8?JJgҭ؜+(Jn|*{z¿IF?d[C_|9}_dnnQe;>\|Og`0V!~z_?<8/=/ bf_CCK*jBW+wf3Wp`A3턻TvQ<4_99 ŅR 0̾*|~{T 8r Uk.Ӎb߮m!/(IhKtld-{N>]p!; ME5ﺖv)x?WWw~~|'.}J@P6SWFr2فM C?ݞm@٨ۺg?D"s4EIPyț!i0m%S+Uc+Po"*@}۫޾́mPw8߲᢫H$sB­?`S@ԑU~H{sm漆=H8lz%{);HX C 6e9Z$qR^>vok}5wW #+K鱎xD( N.*  _Q>j,ݥJR*rE]Xt w`ۆ捨!r0wbcfDOfYs5]~Woȴ[ =Ν IwcC8XLwkj 1PR Mu̾e1ʶV l"4;655ɦh\jc @hdZ?.=T…狷?Vz J~d*:ȶRJ7clr-B/?YnlxrUL%$U$7} 2keC+Y RX\.WO>3ϴ~}) }mxσ Y,vjlOyEtkć< hs.?bl![&<\])/\;l[ȥeegxHE)"kp?&GH$B 9sƏTF?ܰag\i;al;ʶ͋\1*C<#3&a:,|q ;BF*˼Hf퉼:7X1,)RTp* B]Yqzk>f1L30P6`Aa c.a{;/>!@&/Fc TupN.û AǬ/?c0iRxʔ&c7֒H&u`AD7Ua(C"H ^c_0%V047o9X 4=n^ J<-w>{"s4/*ſa "sH NM16^90ߨKzUUŻq˞]f87uDwHBO]suו!_sHz{/z 8O}FB:(p\D"qnvuuXl^s͕[ߢ/@mF38?jQwŨ~,]]3.H:q x _l(~uNfXB/R\yƎxfϞH?<3lsΥpߥW $Ҫ8`J]]@;H$BWXA@w6nzW}}}\.q:t]>VWW'?DCCCaw))Sk$bZueu;4x!%]>wKbMMz8u/}m=Զ@*. ;=:LI=s8(%1l+]4qT5x5xVn$Rsc6iLf8̻װmE#j|QFZorzԑPqDjfHssP9!Pȸvr4jBD 7}]) @>vʪwܥwo`h?sg@dN;JX0P9F irա?]^UH Vz#5z{ fVQJ^5YS!PO:Oim't/_ip pfϊ+kn%%8U:ٓ ߔWr7/DywB\8R56yk $G4c ;B20il~jnfQ,i>Ӹg9\H!WEФѺy*00~ՕPJhCP===4Sϗj|_! o}-:fٌf,}xRB@$VlI~bS6,{k+U*+R{ae\B!ZK{PQ_X^3Y%>F};d J}*A@ ݟBƞuk>[{MOo 7>tq=wt/{- k>0}kzX՟SNLRk_œ}+7s/`10p1O5j䆿PvJ'mų.~y9o޼{zzne9GfEFĴ)u%>b) @&k׮ռ^ovر?s;>~ΨwԔPTcV+ċ6}9>07c{^hn>X+~6“ۏ /gCH)pBy&f w|7ՎuO>j,YcL$FRĀft׏JU/9%n,+YNJ]HB+!}֡̽d}M9}bݚ l;kllp!sp앵 b lK088(RK~}?r#)bdFip&4]cmRJ\&ıX˲a;Nō4ӴkTk@~է+FW˪+Wly7i9 V 2w.rq# @,dܹD2 :p]3[6m*ˆ+W}g]bR)sM4P}A[4[㒷3{(5x#˥7(m ol[piŗ}bx_8Afanć]k4>*HZ}*%RD/Q~_WJ>,(mܕ\NN8|UscGv@N(VQ3KwH7w\ 옳Bb `;g0>=iÑkM{Ȫ_jT)+%$ JH*J0RLO'S-^Âm # #ގwuIJޯԶafdlTs+SQ (y)TS6>+#oTmVW=U됒mpqe&Xb6C5K~R;v$%S"Yo)xސ's9!qt3,vWB6G 9VjP;)kD *G&U#R%R Lӈ6U?N8d8}uc4r8X\. G^)5f̘z[S#k'eUՎz._m~BND"bT*U@ SZ[p(O1\>H=Sp!P9rE˰ ]Ոt?:̉a-іEA.i1oL>9`rƴP--U2`U# lu%/N$5&qư嗟Tor_<2,u 6B \N fnټy*!uGXx?Y6Gʊ Q[[?4}HƞbѢE;4MC.Ů^Jٌ!~Bpj.g-k[wE.=cǎY{ z%Pat.>.[Z~T(ch@K^c=Lcz<'x),X0'wڬ=C0'`Ry7rQBhRߡRs̲K1tuwKDk_>S'm+u宀H%i @ aQm i [Xy97V ‹p^s aj>(ݒza9)]; DU g@U =:Hڂ%$\`n[ [rU3G19 Gn (̥443#s2u/j4kԔC}swӴ~̞Z}%uk4v`OXcNd^駄Ղ7pèQO]lsbP@ @q(! "DJ"9՘PlܼE| GN"_xBGdf}jv0ii?~LîQ0 J)%N?9_W慠YYi5ꃏ 1N&׈Z#M$ay5lcrՊN[oP_$ㄺ97y.XsOPu)`ɴP(\.(Ytu?m{] ȜrjqVK+`wzgt/BC_CGm`&_LCp-t!m3˽_J%8+; !}i]vxM[#u}3x;wY,X@7oo])Ɵ-7Жbݚ ~ajs縱 (4BȷEUwl+rrydsy)rv:#F@qL2s(L^lA,_ @guU.Z+vjkK7ʂ^7u\eTsj/(8D) >a [Br @8)( d׮;0j|fItHe81>U?w^&sglJ@%HX` XD< nAP&S'f@_݃1c| ,UCjLQA8@/7"xW\#k4-pdɁ$9( h}g,MELTGcʼhKT$Bɼy{26UJQ(cR7ʽaxpSLҤxC[i-O]]׽踩S 0 9PIAA Ee&FUI#71ځ=gVJX =}>PBa] FS`夲EVccc8o~%E"Qcs.SC{{-&ǂ5X̢r8 ֎nt=`̄2u]MD[xo?rԲ`H i鐒 5oe(>mدeh4m[nq?#\.z{jX OC+ Pl28݃T*ɤJ$'xۤhTngI@h̻ˆ:`XKK@ aK+0:8.ccA RyrnIÌ&08c]r6- b!8b$.tahC }nn1BDːgpc][o]*+e700"Y$EJ֯_7OrĿyȴ(Ycxkqi/?7t _&\꾉onmrW|Q=J#~A;" _d@bm Ҳ i`!d`!Y5%u@8]o׭36 R+y&4̀ԑԗ… =ܳg3t9.?H`(/+Ey(ۍk`PJAuLU ʠoiG!#*~(}*42NjL8*P}tǷ;][k ǝժvro=pI@ETUC%j% H^D;! P P'\AKpL-X⼡BoH .\ɁR,/@i s. Q:<*к 91Hf$B{!/ه!FN|>_#G߶Tu2ɋ}{yihPd'^Z]5T2_v)LvmnײTԀ׊ ^0l08?+5޷aٔ7c22KN{k'dsܬ/,zފJ @Iѽr=%-HY^c/P[ \'0Hy X׶)bT/8 qp{T5Jsx J;6'\t"_ oC|1XJybOܛ]cp^uVT󄣀r=7flQá[M7`(o})m 7B/X"x졤lX+.S% _0Zz:mG`-#W2 65OWvF}cLսY 4Ծqza&Y;*ɸMmG; G@`P>{paq%lb SG]^rer$Pogt RTjy8}\5#g+^6j(/+Prxfġi|(ip%'xG'@!̾j)PX2¹ƋvuUDPJ4BLFUsڍ @kf+ЌxÄDO.F^ $=~ʔ*m0<Ibz[,߀DM6o߮ǡ8q].]L$\O;C'*1ʋ]ᨽҨ IsۀF7pdm F§80g/@4vטYhn4ޠ=xtLmal؈@'0.W@WRzNjSPuun*[>?{5 Cƻ+xՅgs445%rRnP֕x#&NnܿhN,>y56f ~F=ǛR)M%T#x\'`?FyD/A=LN1gd}3!@sp\\Tvv{U*RZRU#!zE ھTLߎR*@!L \*BdHAB[ߤ..k$nm7򶁂 @"nXpLl' 1FS?J5?q~휌#1F)QͤԙUy!'g9y@ݽrڸ'NyMǼ1C:RH F!FaH; +V'/2,m۽egA牽j) :4C7\~)z?[x@@B_:W}+:ą[i -Agpۀx^[5 P[@8X93A?b?c Q CDAIBBT,NB CcK 'Lb ;`^gA"mh^w^è䚧FAPIb&IxD~PLUcT%U XL {=*ĺ4y /^ՌOecTIny"94Y P @h1[{+RR! 14G$=lB9z=(/$L\P v\ePR2iljkλR,?6?RÏQC,܊+R (I@CMaSqGbTC9.E|WL(eunKM|>CN}+Lʤd2I `SOQ_E^>w媫+i^YǙ%%%G?xz4V,3ЮP)OXiH^vﴫxR#@2^(ETuuee"Iz$Q02o`"@b@tc$H&Z1w1Ç lj;q< z!U-hoo~JRJA cLM5M0"]Y]yvuM8a9%^t sΕR"0 0P2gZ\6.eP3[RPR0K[wZ}:8+vӿH 6Nۑh^$]z~$y,ڲؽEW?J5}CI|p`/.Xfy} |mpD_ }D_afj":[X;_ʎtY0 bg@}!s E((/|  kP~ d DVs`e@nwe/ /;"е1̐vdf3D0$g*Ȕ`e^3G+ /ʽ]|G]<PT$B1$C19m#lͅ|ZW(j+ Nw4*Hs+ͷ!s{B@=>PDҧd){~_2 fV-?  B~[/#ǴdYZ|v< j;:%)P6 VRReVZGۏ]|oZ6449/ٲ~#n. c ZßH"8c./Ւ%K4cu햭9F礰{ncH8Is<8-k"p{@Y)L@s]ztrkPm!mp{Xw 3 ڰpΡkl`!#2Bel`C + Y7;ÏB4iY2 EJ <$zBo1I[݈_*vkU席qQ@|\Ftl)F+kED UMi]a;jݘz'.o1yuk9 E@`̆~+t)qP\ ߸ KqWOn&~6*Tm]?;wGߝ=>9^:"I̎z$ӏcW' 'Mǔ`[M;w{{gţ64Tg]1oaN9) J#q;Ldz}fVڐGԐ eL|%:=19[\/Um--+o:]VI/s4gp`Wk5ڟyG ?'7RO.Q,/d/)aP?/CZJS1WyB'CPJP(!̆xt;1A5Akw!`Pޒc -mS @*657S񤜁އRƣ{?C4*h ?oŦ{1z)WӈkdN9tPQ:ȇOgr(%Sϴ"B{^O{;:;nZ^ :35qOp+K ݿ {5Og !H?U À砎 @ePYƈ;C-/ t ɀr؟{r^)*|twqŭY.B4) "XB/fӡH6$X<="]`Ѹ%=MLzba:'pBӾq9 MO=G'2&{Eůlxaͪ˕U~ u:crw)23ǮrlƵE.`<v,_\۶RPYYIVr$Q Wuz ߆w7@ƭ5Cq4A) ؒv%Uf =h"㬕p.p̶q|$At 4:9߾+{|}=QJ&ƺHdj^I5B<|\> :8#mK{}_Rl_9=Zt0a Qa#' 5 @2ӄwvAEețn8xPՌ46SMZPTH}MCGK*::x* )*3(hgұ66jՃ^-޴pO(ۿ\sA $v'1- BC *;Ӹ3zPJɚFty-U cd6οOj''5hǁ/31daki!_]'"]tk;Bq e*sG_Z0 s(v 5͟[=`pӖX?{ ڸB&,P().XHŅnr&[۴=W/ұK}DQ PJ2zJ9A&ah0LH)af9ggܸqK8555j嗟G/okIBOЅٞy8i8*s*t'x R  t ؖ)IloT^%9`3;xN4K1dJ)C׉i^h$WJ!##DbQ__ܽm߶ a/OT [xalooginjt ֿ{i'13l 6@Hd_ rȆ83r[$< FMM_ȁ(i H.?Q~XpEc9kgy\RʜA/e+ ź}{0ci{: 7OannƿΛwRp4 C[ԍu:YM)xw B co#>p`u 1).PdzOR2n:.Б Ѵz+s vH) -p@ 0x6t\h2vR*GQ`ZZ`*8p$s, Cѓo 3b,kp4"dw4"f3`I'`ln1%ʈtPW#>[GR!aq@9Xѭ5Jc&eP M$'5LpϞ0-GiEØL?\!E2Go6'[ӛȱ^tΆpi o7TVB[=٣[]]m466ڇyѳYG\Ba|'M<2cL v /;Ĵ~X"x஻Mvd]!/s]uhpi?R'&$Z?G|.{O5 >ˣc!Yۻ· VOpF-x'jI?&~9XgRcƖw_:vo`Ȟ3NA(CL8n$Ep lIVVX x$ߓaP m ,@d_c*8 o9X1Kaݒyk_0%V,++m-(FLB Dk+l`ߑLLjl$^(% _0H!&12_UQHﻃ7Ү.)AD*) PA0='/}W[7b5n7(\4\BR*p[¶9lGҔ2\L;=lR۽O&$C0|^y 2X! H2L@i^62'6mW:}OSGHFwg-7L|R*˚_ֽ{o_[w;_ K4e'[SjƔfQ)41f# G!lp*< zazоi7{r-6l+ɑrB:x&#օm%_֧=O@HƨF@ jN OGE_Oٻ D~s ?oaO%zpyp3h d?0+ȡ)IPj"iD`{.  IHΗB g#E{uE؛Toї͜sm֡u?Q{:yn>!SΒ$øGA%y.T5Ys'ٷZ+3?(N_Rʮƻbk4癦Y{~tfu)8*%lͬDR۰+ݱ/'!!@` 뿹Vt}}ծ233ݬn$I0@ kM;O9=$2t lM/`9LI`2˲e3ß=ŝ۲=қ @A1G8VR>.!w/B;7W̌ G8研AJ{8zvv%ϟ<\Yg8~i .h2m@k36IF+1ea9$D["Ș+cΉtƆ')o^yˮZq@yjttw ("r ,aH/s;`Nв *2? L`}u0mˏj^\Ѳ^F14!B a $q O@A9bAt\>״ mc|h#'('sRV5-= :e:QH[X΅B)C";:Ղ!zf@.ہyaΘӕEZ--Zn\?UC+PQ_Y'ln<wu?c3-{;btv2}ci)!FeBM*GntA^F|l͟ su O~?:S@ 'OOu;ց2GcYVa)`8C!qb) G*B/zpQ _-{U~?M0bʘI((EVB)z_ݠxAEϼ?{d§~yyss%fEZpM齕K 6S"!S4A03X0y7==Sf}\!8IզsGVN?ͯC |c:yk!exn@$f/:{Շ\1xshD5|`ƾQE/-())J"4/ 'ODVDY۵/;nz-wMC)_z}}=s뭷1bDcaa`0~vZBu# ";;PrѣKM]w5jkc'ABtUAPT4qP|Ri $KH<홴Ec[8ia0 Q!L1>Zo}gOhmm}$nzxRDcQQtZǦ8I~Y[$ mOc׀ 0~=vLZ0 9K4Yuj9ï=TTjht4/'% jpQ 1!t"zd9LB2 4.ׁq[B)&ahP @P$IG8JsZu9Mk,ʞvgSiZG7o@n4 P(0+F!plLה\۹UIm[]wGc`E_岰0Lߛ'XK9 xsȞdⶒFvxawBoXҀS /4yے1IHp3I ={עxV)NLdxM A?\&f晘9!@F“{x}GqmycF햔LtRRD;,)aKIJ!goi͕k|}G:gA}۶N} ((@v4A ɍ<֖rohK{kZ)ǥ6Mb2129^;g2C)%Ŷ߀oz'555b[jkkORJ,..QZZ333.dffb֭x<1bvڅ,R߽~3Cda7츉FTv87JAphb cS:51to{«szQ@oؔw=uǭvVToRxX$c pC@QrE8W\B *ںv3~q~"aZE圧-먙𖍀GA3tYp3rr$$j4o&~9_w鼲<bFvyN2w>=ҟ1zaEkټkќ~'ꍇšo8 ӆ 'wF'{RZH2D A4ӏBx:,~1Mjlq$mhV;V5 ]edmor(h)%-))$PRN@ECu5r,lV4rrV^|jd*D1'ʐCfKW}]ׅk+] !?)IJ!6E@;:f\|GĒbֽ,V>x*a5+{5{wq9★Աttg Ч4(*ҷYh$C:Sߟ2?\:{0jY1ɂ 3G% bOI“myہ.uy> M ɷ0y} ړ/ MئMݍS"#xHh6NArPJ).ّ!D /ŗ?W8\g8N#?CL d!'P ȓY0t_ﵪSˏݔWN;ϸZZSSDBBқu=_Y 5L;&œ$J2'.IV@ҒjX?l/UJѝ;w$qɨmQ U~j@<)ΙڍQ\2p.l W>ˤO-?~Y Ёþޤ`F1߷wnnFd~΍ u_Muc#m4t}?5}V±bRp%` <%A e0 '`p>jkTjkki<eqƎbpizE<5CA1#&# 'i{G\y_On>B#RL1]8X É%pk:cy4M^:!}DQuLCqsBQ$y@Br @ H⅂;!m'@h*Y &$4/ yߖWE2 }=tLB餘tZUQ@2ݜ|`ls{C80Π߷ t}7B"e[Vz->[uMp/j5;/ZWcN45#Vz6^qOckZv3z(p =t[) E"c %@$5%>C2ߗyKOHiuD5G_0uF-S'Lu%r'<3Hj2QY8xJ07#]~ PϣLK;*%lq<>ș&TLr+PC<гʸV:[;ϳ8hO=3hllP]61kF6^*.<7Z&~c:=E8S^RPP9///Rw^5J% եi81?Ov ] +BG/stnV-> @¡0b@:=h]}ɾ?>`*_ wGf>upims(=[#HJtokk{FjG"ĉ #bgyxB] oxXgUVG?9]<;. 6 lB*oL`gݿc+GeevM.Or@4'(QR% QJoY|g9f[ Fu~+z -K O$QR^)%iN3!Ƙ #vͻuW3~ ~≆qK^3fXuMhNuM'"W\p[9@YVe9~[Ţtw |雪ApìoBK7{/a.3)YB|wdm}OYJ6D% w|~[vK|ZR&]F4440ӛހ?.)! Ap9l2eA |Ϋnge'+n!yd^ ]4ϒ RA2F!$A 4OwEOa`]XWR*$UBl%o:Km._Woh\iMMhj>3dߍ}_xIŵ)n3u錠x4E̛~pK|Wx|)yJE>% .ҶsڥݵVۤ bkpneSfdN RlW|Y[_hOU-<,sD '=; 2ɵ<ϹΪ4!fI!(\r)kg"Z=}b#gLe/ _̐R 9I,@o'tq͏I QߩhPQq<{'tҳeUIÙ?Pݘكlw >S aS5 th%OUp26*sF e_Jǥ>پo(7];\t!H!9R$.*B$H7%C׽[ 9TGQVvgNvFMN06hB:/ _wYI>zEWE{uQjTDĤ3ƺ_\sI#!}`姷~j͙ H ᐃvqJ 1A[z[åG\ٲؓ϶#CGtBQ[iiAa^T>(thIwXLw'vf Ie~>Ff=8$ÖQڸC5 PRR(JSSV -%|DͧNkHj|a  # ).}K?je_5t\24>BŔjKu/g46T|Q 篟_m ;ߙqӑS кt2Q>69iިzn9oAs'j~\nL/ Sz;_ԼlCɢԝW-<*޷՟{i!{v^^ޫY%J)ki>\ԩ։G*#?3'g2p,.Xuu2XCťy?7M rM.)#IC2dhmc?ûy駟~,Jդ Ծq# ~ 2F=h7>6bFaGU3A3? f>cw#) | Wls3(= d "L(ۢRb_"y$\i{>@\BH1AI XDž#ڤcuĿϭ{iݺ!>Nܼ\a3.lN۱?G" Uu$ RB|[|/"/<9i2B=o;W"7Pse߃r<&.9T*sΜ9p /455z\! 㪎s9HO @xS-3ŰѡSe ( @('*TwG-m޸`o߃ϮilltʕŦi4MD"O>9>o(hP[64fbx!\FG#On*])6 j'Svˆc6),rD1HǮ_Uh;G M94zꉾZRXn-?F̪477ٔh`&ސŃ|լi󰋐KS|Df͚*LsIi07]+ZfZUUꚛI]Uj==U}ʟWQM:\R[ 2i Hnw%AUUeuplY0x 7dM~2nԀ8IqjR:g[cccCRbs:@ЌflS5_gHLCC5nC_~r/\71T3l;XKY{?O|!MMM H?.Ls\u|h98oR-tvv?cORR#~ŢQ QSWO2|#ڔܾ[l|:?FÚOk+:66,J?%\TS3Op#H#^ME(c߽̀ \p8PI pMkY-Ц2' qY@ lnu$ۊȿ[/~݄ojj'@<dx{ɲ)(!᜷Û.=þ_mBCH$K Ijuuu7]~ьMs:_H&1 b[AQBim紿뇿SGb 88Mܮ*0RT2iس?F ׃0C.- L{m;T( .!P Xtc>ЊZ0r$f1ilw\{w6dHkYrBu_ǻ7q~{@n: WVU}RRZ:uW JKo*)-=uMs*++9̚5K6֡`܉_DWaD`ԁ4r#=["CҰIc7*^nzfCxWg! ŷjm{n?H S oVh|>KR6rҊ~xED*<<"R"(sKBQ &Wx,'{n_NRG^_*B"'xɱȜـjkA& Ǘ)jk[*H9(QɨCVGRt]o\?'\slp!Bp_{f4=ӕ[?+tK,Pf*:YJ\pb6ԮDoG'>Cze|_.]DgN‘u*ƌ.4/T[SӘ57S'1M99BP\R ?0gϾȞtҤjBjw8%A y"~wZl ys U+gO33qgRR_ "h{6~+8##X;wGAȾbgdgcl풐m~FYO4{Sy41z0b'z#RjbEy;7lXbO?& i}饋L_D*RtчߊΞ}r4flfH}/c}pybck/k Qc~26p-xxwoXqO634B~an_nِ'KsͭPA޾~dM? NZS?T+ݵ3 77W2;o]c*q@ t>vzLߌT@~ ݍ ^BdH4w޺/\4<PHMxvF[3$$P9@J*"@-N?ꈉذ_5Kl8\9 G{:>SIK0,.iUYT-d2'3h.Dӡ8 7@T|฿0y$)tCg\8yJţI<+p*<\غwޥ^‡G|ZDF㋦z'MKrH%eʶ"!@)P ن Q<ֶ46n&5R I]v A& I Jr$bqexĴiy?Ϯy piΞ3\Qxo0(cD))Fb4MúO>j WM N(2n~ J)dgjH$ rPgK7FÑ/NtlHp3GN%t1),ct%64TN?a]X(Bڸfy)m!`$s:LC,BY<Z*+38!7-p7eu4שz*NJ)Sum۶_'OH-"g$ɁSO=uoCCnWNB\z)oa͟?z(ڬ!o{^ji`.c}JrwIy@<_L*wϐ֙.GBe//*..n|ng"yKY6ku6-s"ٺr7?xX3gqx1OHaKxQ21"{=rˡMڷG27}jkk ܘ+R "r%«tEpƂLG׮xq;UplGVM) yF;].[a.]@p+,9>Kv4S)1m^ݱ)tۦkkkٳ‚G+**2!!)@vf@j.FH&y3fϞ}pf4sVx+*&L\1a|q˶uCOI PJ@)4plWPls3EnkRW2fƽ3'̣\i&@#M؜՛Z :*?3(FnيP"si:`l!B5Yn9A|#PBJa;BHIHJI MYIodyi潻vvX/8ν棬]N}=p\Pb$WPR(̲w,sP[Ϋ\9MrJL@tBxB  t3R#};½뿺^˹%Eq. @$j"[b%:֪տˉF#t]'{ۻw/:cpxVWWk'O?䓟>F#o)5e)х3zp{m-Es8cbOק%^Q|>l?{swK ʤG|e&-d_+MovaYYZ>5KB*=^<$#{Xj{-#O>p-vk.xkP[KUU=}ꍮeҎ,ܱs'sK/uJ7)YwuV3iDeۙdbBQ¢^r;!l H&1,0l$VomAc!wr&[d]\zuL*W HE`; }!#ݤ:<FRA$rԸ<5}Xc;/ݹ^4GU< )!<]&Q%,(s$1^/K^Y_SpڰF+;-^;MIl)!e-I08)d dR|WEAg]|!`C[}qeY Dǐ'RR)%NL&)kmm3ljj҆S{X__o[Rʓ~?!'߳z{@ּ}4WNnnξ _fwMMM!WΘ?nyL@ KQ/r o.[L_d{/\\,!raz5G P PLa)>0_ucSNuM]1\U544yƥ5eA )\7$nCrs>ZP^ tmy ~o<,ީ,ٱfG/1AH#Th`K}ݎ?Ww $ʩUK;N',`zEݑ?eD!5ß+@m#ڹҴB:x!K5)D {A0J5.ѕGM}LX ?r9`!%3My0pvtNI{ӘRR=yyJ)E>;}kV{ٗd^LvA<VUJ%|LYq0泟Po-Ph$Ohjfz,ٱ 4B:"yB*F3ܠ%85(B4HME1rDA^{0ڥKT g@,'F!jk[]S0B@7BT.ԥKN( ?՟ #mqI'I͕R†a5de-`2ig], ޲d(J"ə*)tBJ қD (L. Ip-~M.H|JҚ-k/Uw‘L%4+4 \@JIAJ)5E .na7N8 9w" eB#!ϣĪ 뢎 dV k׮}V/~mC{ސyeeejf$ q>V::/83~r6bG-q^s©n?$!9z{2j)T ]@MY%&W _B碱Ņ e2z5$b/>tI TwfIG{^͗~x2Hϕ3aO(&2:mD1z`+?dct dl | pD> ' M@ @M9@X0-㵮,W\ fAlCŠ'q꼩X4=p8W>mŨL@N@~?G :#lXF.`;@\.(pՂ^6QrJ/#J,X7M=VRߞk B&Peg>.[)@;eKHߍ@u[##A\{ `RJe;\Qʉgj=}^Q@fAĀ!)=z#2߽vm ~P͚s'I5(jBJĩ,I*W_OA 426 *J\KB| |ԉ?#5UVjc2׽&uMZ{Ś[}'' sP-]۱ !!PLpU$9rVX10?1ƍw(:Զ6f.O6e9PBfyli?Ca2 VƏ?{G'VU] ࣢i5Ȉd.Tp5pC!`,&@ qw!By C`\ #CDF.)[Bݝ縂^iiPи@ (xwOy 8.Ok?y'N(XH 2T И?vo"KS#GV~@Jyʕ+/$'O?577;T3Zǣ,YQq->_˽+\0Ѵ s0j3a")enZT\T-X_cXV2d0(]ul;M @Ii 5!c~z%m6uk} e@pZTbPB s  M_Hf2hlp7(fg܌|#A,AiA+BdFLhnlj]N-Gg . X `iegn=~ tNCiz9PP% T*Pj`iH8!x x,}ٲN-׻>eY6{I$!)c,}LF"OJQ4U^~n7bC~_z$,bvq0tv=X"#%PJQ˲dn~a'e˖]KQJ)B)U555b՛ ^Ie#]>/Hεܽ onIi d7Ey-[VtUY` !RJBQ@ʕ3~-EEP" i&{rF3,EZ}V(x,b\"XtQvތYn?Uo4F- j|o?]Ks,w7ͫ;tXVFP LEmᄏ*IMH@x+ 2A%}ӎY6qIIM㒐 ʭS$ڃ^7k.!mឮn* 8IH+B5$'Ii9ˍ@)¯뀦Aw(CD7F"R*JOԒeZ嫯q'plGPJ~_Z 47K)uE"i!H!+e;Բ,1v¤IhO˕Rtݻȼj U.y.H# lI(xA>ZRIW:R`07^yԻ0sLeݕ4+; jԌ9+;^`Lg!Ca@$IVnWve86VtarK^LuʇԢ\F[}~فAx3Z{eB@XVTQUpW --[朰iU8焐R^:Vg6! #hJ (&_UËr,g9šmm'{I *.4Bɗ*k~iYsn-e}lгeje6v f9eq9XULe@\w3Y#U֬ * p7-K':R۬,֗1s /Ee' SPLjB_!Qwrn)H#q{3a%RKEtTH.q ty*qUP@4:K& dCf -ڇ@7@>2hM$]G1R;OwXvi :;{2R R(H)`B0p<oǢ,8i?"QQ^O>Aemm-=+۹{.3F:DirA:.]ĚNyM5Tjt#wƏә;KnSR@ KBcCpG@Iw뛚j kBDc"\q-Eܺ i\(XD¢8*|[V4PP(!7Zon[/**|(pb+hT$ϔ|';Rx|C:PfUf^b%A0{%@D pi%CCh뾠b3)nR, $9w1-? p@߳,7zazz(t{Y~!Iw4႖l),h fs@rDbO ŬU[:;Zj}J AVnrrfۉap`6l  `R/d"#&q x/D*!bQagK2d¿G)J2%.sR 1eYL]B` 1xtpzaY62~'i*Ƿ"7_]);4R04 9Ri-X"5vۇ|*lųʕ+C>„BR@i1 RR`90.;I{1bWq;￁ozx|ZdNzIT#Ө$hEh {$lAES,j FN?zbz5t⌣UwFFcc mjQK/, XMQ IE2tDX@ n4I=[1n.ҦuVccO3hf(i%g.x X+w;V5TO4֯ƒ8o5'*q\{o㻍O4oVι2$a=mQeh^-{ò*85qSL+wF߹o>h… _byo1&#m( xe.VEdlDO98Q^;J-;Io?A~h麇L]+)L9(| $[d&3A~GiFtx}]y Nj؃{S葥B=PJP~>Ԡ1(:tiPdp-;[. z0rHҶo?H:r0) ^P P0jcQ>]nT V䜬'B Xz(@I@Mt9o9ɡ؇/d.a#x!֠y8:lI!]-w%b_744j1ud+j5!H=TgێRI%SH&HēR)px)0㼚CAf5N8z󛮮.!`W}bzJ,ZC0dN'Vܲ@% IPb`r@Hj8>H蟏Ÿ9%))=*-⅄I0`h@Г(pkЋ! CPlk low TuC;zĿ77mzIw ǃ .yAq Bq[66 lA՞t{?Ff"h'e_ܣ7j4 2}$RGoOv"\#}zp @(@ 0df.GlNp٬JK#A(ΰ7ODd:m@S$9 1`O MAkpQ(ed2E:{i(EFJ)4 8B8?YOzVиQ#1inlPۃ7pCx֝UyEѣp^{pau.x` H9A.yBꦦ̘9V/nOo+7..5qW)|oQQrW8O9MN9!! P@a3 &H?`0 0d3crBE$(L=oC{ZZu:ugodG fM`lQn'Rqs誰5iЦb;2680E޺ {DŽPXOP ͕WTP HنeY0 C2HҖjZp]$&aFHupϭEf*崪~ `]t7iX B@Q n]2,-h]}[ϐ";mvEAAAar&_VvBǣX3:QDdS7mȽpD4cF^ ΎP0V BG´RbǎNm:?>&}RȸД t d$:83ڻ) qK޴-D\q0Q1jRWMcb0;|n )O>~x/<V0$9mtFdAH՞]ѿ /VUF-0FeM$NOF ආ 2pjaP${[*G>B]#.|n瑆=4 '/_rGR, P~9Nν8v׶/]di iZ*n`Na  JK&5 $쁅so +[z%~8[!ʡ1i?1Uՠj,ys8 T -nBJpɰ"h%uuWqY+kH>7[ܩ#u43(݋O[H'tf{ ;f9;w?wəE~`V]]0eڿGRkT'!r}篥 Ð |8V sFM(؏'PqAΦ;] &8894I@65[O'وo:H9t+ d2@ُYFʶep8 XY<FD+^JEIP瞩p,} 2md2ch6)A55u_ ă2SȨŰR Ag%$R@’HX1K<7CzɎ\hT50{7QKbçǶU3BBU*`RNð\Y G6poٞt5ޕE!cIth EEğ#S4~ l]X@e.`.; @r,dT jdòY4c")@wHqvuJ"igS_/x.UJ4vJp iqsSe4@f`buwK !$oe\Lagkz[iˢ{}~W}M.d}Ozhq[~ژ]Lĥ{P LAڽ$7٤ٺ^3"^[xaQqYVPw _jca-[i*9xu%Ű@2 n:2[Hì KfSوfE䄼` r[ ]JgL9}d{jWz"e_KveB08f-akўpUW=Tw>5nt8}W1m~YgXoȨ;wko{&[|K@D~칣nњ]cN0wf;,mwmg{h$3gl˲!sw7Po@`JLalD"bܹx_ZyAY#Tvik, 75JbkIoJ)q` J;,r4> :XئHS( #0n섔%LjR@4SU=kϿP꫒@Mzݥ# L[-~VlKA'IJ=.돗^W"T=.xS7d F:DG;X/M "b,| !(0 a%pIO"vZp0R`ZwH%@SƲ ?S{8C`Q `);]!P)k7?4k!(J| Ǡ ,CowsY=BOy׌xO@Vח?TX1&*i^_e|yjㆭD}e 1 dS4ϠAHދؒ%d%VYam4-Hi'C&$X7HjLc7Ŭtqg̰GM8|`=>y3lδ 0c` È(J.TݍdZYzM7%/ޮ.p:irؓu} v!E%Mloa/H>@H,Й2ƅ$It)<m%x8)Ta4L=q}E4d cToUxnyròDEV)N02IH W4nJ,'&q]mR} uGy}o,cs!/f[8ߟv6MSnS*Rw4n/,^tnAAp~szAȣjB²4Ms.6B6ϒdIVjB@roǦinBdWKMl ' ΁DOy Hׇt: Q?ԩcRx:p@쥘i69l+$rJMe}.R g~߳ac)۲5F1""$,!` )-Auh|#yU8,Y W$B",r͙;k<^:bms!lEn37f *$9ѵ[;/ogJH2i6K .TiBSL݉Z#mZ0M0Mp:X""($~z[~ZzGR:mߞD*lmp[{[yG0>mRJI iT߀M0Ba^0EȲXΝQ)%xo77]`[ f:(N/(Xksf)%x o͝02V_T4_]_'$ѷ~uoDض߆>d8!{HBe J{Y\ ɣ̟Z~ W$~F_ q u}]tg0dFs_Lu7 te[&B ڊ߳]{zOm[kǎmy;숩PaK^CO^C"T {pNdiJiY#@'5z9'g9jeCMI&L " %8zv MJs{ؕ4Jg:o2Rh*cɸ4_4䙦]6쒌afF*;vnۖ\yKٟk&#GnIɟf\CH? W5&U?Zf_9t`YBJ T"EvMLX!#6悫o}V&|~!geٖm ʥ RY)~ K}/cDIF:;s7R)!!wLDhRHU(JEߒo{zDQGWu:^!ms[QI5 K\^K]Ifo6^-kPIJ$#9w=]qp GZgiRUHSEƺ`7}>V$DHTU*u7V>Ϗ6;t_ɶgeR`) p vOxdžYe%ȝ.Ld$`,F0r-!)e)ts 8&Օm#Y4EOe2ֆiL*{GҠJ!5NԓO@yry ,&ەbm2%bP,F&Ξ(c3xǡnݽޛn<0lײm(s\ R;Tt!{hTt uyhj+.ˮ^3~۔AOMc{ r3fX_pBrJ6p 8]1#FiV4u?>\iuuTO/r"P`Ys)P݀A,GY`ؔ:ښ!e7g/>=xjO_UQX3) @ieRn@Y,3tTNHb(ȯE dmRqTF1|lר:_3Rhjn䮳ݵ}ED+?D<+ܶUSw+Z$Z,+ms$-^ #(Ǝ}' H+F]l3H;ou`aJ ['(a~nE @,6,򗚄]|_gGI`DƸXalSהqcFKakd)R;5<1Zljm5Z}N/qbofV)7ykS"WZחk6S^PX Ȥ c L$@nTn93{r@ O3% $@@]Ym` *N)PqI 6MN<7._K=EZdjԧ"hugԷUpXYR#vO8|(ޛ3DKV}@1,#bwťI1}y cdDٸ~ܳ{umh8}\s6#L R\ CģŠܜªP]]gyFO5g"}L9>'6wx{բG-)jO$nY~;`t{T&2<%zZz Zs>NtbImYC,KGTFdmU>;h]mO,6ׂ$u]fP03٬l3 Nʞjڰyw,klNE"Ϫ g.}xZϠ(Q]O@K EBؾ'?om$ ]Y^RRCC lIRr"lAR6@0s5V~,vn*U~y߮\;ؖ’Pid5EHidZѓ| OA/V"}ꜗz#Wp.ώv{Zcj_XȞ2&?љk2 sD8BB*ɞ>ɔu]$`V)@L]J;E)5q7^x= */RU;IH)iH!/Fm6HEDwQ0n330MfE!kQD"RR^ _g:Hwd(\iY{~R6)H$}|ӯvLzc I4mӝ2 )W?k'aFrΡ;.EOO7tEɁ$i*Lc ,jю0w @DFX#)*y@ppn:c&^SܶUn[LvbRHpnCp 'eQ63k$\H! ӤT:)a8/9hO/Ht8i^@2F*TUU.11c Mz\ semp`0޽{i^/_:O}tщǬs@?tZ3HXTQ4v2Ehx%S:465/|Od(qOĤ$J8AB6l2MLӐszMKۻjᨹ߰⡇ 5jI[đ#!hU8]=̄"v'S$"e)>w~o~sÊ.Iov&](ۺaCH K4 Uo:Zs@N}[{\[e/wT4'Ae#=dLYPI"u3)d3 ϯj P̫ϓвd iM "p4b F3v[ !uu<_ϝ:(&b +5_I;)` d[|>dҽ iXg/o:bD|v틫z*ɤ %%vD*mmiNgՓRJn?]'E"Yկ?h+`Gy5EW"qY9ţ+y}D"b\mr={d烺愴ɖ#% %`%^7xHD̝V%p`=$I[D%x~^ظOuuӵ6f_ޏgB ,e,ι @LgK=\?J{;RCQkQrܲJ=OhrH0@>\pΡd2HR{Dt2/lE22LRJb#H*ҲxAVV^`^ "Vģ] oa4XPy诵 CEy7Cnc#c⓾ow:y~%VF_6U$7 H.Tƭ;}"'Ckc};X K@ i )) M9g7Hb`MQ&upӯ6a̐/Wƍ}@{ 7 y{bTMD"dky1,ә-iDi^B&b:u(QK[AdU*uD'ߞJV"F; |VUsGNY*~vM>V4Ult Pl;#|FRth̑W>S: ΥVòR*@d@"m0/W.^\W]^[[]] nK=-$qpb @2)%ٜ+ܲE׾jC]xE_Ծ%x}> u:0-Kr)enC! dd*6tݡpD[[c^xwEzGo|{/ 3MS*\ኤp8] :sY~M'AUUwܹ;v>rN+(17%2ћcH$S婴--E">~XQ1`iYRUUIĤeQ&!Ƙֶ2s^y'?lP'/ 2{4XD˂ef`8mbQѓLg>I%:Z7/?Ȣ~) wNw#V*[r"iJ[Z[=c/5UWW3=wAtMn֒wu<ֿl~ck7:F1-/]?]}#OfJggNXo JRGўݓT RĦkk?5D:\曛ѓF7ޒQʫ y|z*3$J(AkTGw]{%9vFg---<8%ڛD$mHUCt$gut؍UC?oq*.^9M @KS,+ M?a4)e~-ι\ض֞]n+cdO>We z}/X|hPʹ,rru|„3d<-l~3qWvѢE… /WӴDٹ3aXemjjn;pѢEڂ o)|qw}.k. o\ԙ<Ɠ9B;w.>\Hx?b@@\h-}'|ԒZѴ÷c7ø*ߘt+_q~\vYHi|?{ࡷrΈH,{*JK7M#gᄈ=%S(UR%yd)3BT 1 $MW$SW[k:g׏wyCGYN/^$CS63Έb0 2U&IQ7qma0̝èofu--@YեGqnpgҽYrڪZn2G{GλhߗF;/v`/9>CO4 g@̧_u /Vɡfh-뿯[O9-W{A; #8 "rlaWeLooO%)-s}WHjwPkxs|~0 ]MV~҇=!_r1BԥjGkRBx*eVEg{p6eZC5lAل˞=t47⤺՛e饳 *>VluM:,裰~}yjT8b_(7NXF(j)L״, eZBR^L&Q4z;rşMo^rp?#2-/;2q? @[Of۶LW Hcr! F/vmmXW|x;>|Nf 8矞`)wy:O7sϽ>@0w80 ==E}-[/>ϴ߯lذa`0P{"clCt,Ṕ -bJmo/T}C2dȑ;g*=pL(􉿘eZ;]~/a2[c{Z='|67Xga0D аc7|%W׷Yf.4,hPbDė?yM,"GԉmTB +)_kl\sΩOw 9áɠ ڱn;Vw@nsޣ1~Fxw( !iհ @nj.p6mXV*QR$">tlPw.t]Ow/ZHp7G!kXG jv3E'ou&=,jb޼yAHZZ:΢~Gk!ݎ#yRR|Ғۡ8]+{+-~{u׹f\R6qPT0kŶÂ7_;nCN\m?jkߏ)?t睡`Ź.wDTshjg{T`MUGIA ; ҶE`Aeީ5KT= 쯅 W*++폖.aBQ$78pH)KKy3۷ 5*I-aŧCU#Y5Qkߎ^vX35'ܽ{wSum/.).-ː$8k+OuMB40wtӀty)_dUnI rfoWkx f %gfH}{c< r> pReRJfUʲK{v=@fGqM+'W߽X,ZH;[3TslwW?3R|%%'O]ppX<rM,{29Zyù銴-{eK ;:HRZw뵢=*\܎ί↿͙3Gm?pZֱbWM5zun8,T"EmƏ'b|Ò6 5LBJk_c\)Gu :8Eԥ2XjC彼'^T||kih8~O9sqEEGKtJ_g ]aC*FoF"-tH;a\qܲ.5vڶx[g7lR`W6G-ع'ɜx{`p WO]ꁿDo:૸j.;MEVH2Fp:\Rt]OszuZ )x55?vvSC;HdqˑG[qؗKa91dȐ l\9fdž/6s~s~7݊˞gڔ/j\eڵ~˾/̲푻K~7'Z]]ϐ*(Ba,6H&EogF7T8@Guu5 ĊD"bܸqJuuwyijqH@"~gfLt6w cVʝ6[;雿φKf/q=|ى<{s-GQ(ZwErƱcq#0n ?mʑ;r|oAܲ 1d 揚&j2M=XScꌢ7MUk]]݊\D~×=nḐYBҗဆ:1 KW|HKJ4i|a]mtT詃#ADAx6#OiҀ%}: 82a[ GZppȎ޷>:V]WW[`Tu4ԇБd+ol/\g…߻rݧ;=滽S Lw{/2G( %o+uM zAt򶬥$3#4uͭ`(ed;ԅ#bj`J($P8_ʼRR7hT:3M~>z9s?͹y4`?;7&cҩ c"fHBF$"NUձ{2cQf~79<.1Ȯ>2l'`zlx1n{םPK? 2 ?1ֱ|cf޲G9g]k²aY('s淥Q.gўOr}_+}eV[˗Ig_썣#E8r;%O??6jm3t:ղbpI,V"0ƈAQEQUն֯rbھvmhʕJ)5+>Ƿ6\Yit ;% ,X -6`*+s93Ϋ{;?xyk[[:Hf ?nx_~Qѳi#vĨ* IcU cǎmJuu5mV x6D"cع|v$G;Av%CFW-^X%o ` pU'Nx{Ѯ놌ښ1[&h˿zNE -!GNөߺt7(ox^\G;D4m!%n͌ϘOs=tsU㦌V0截y*ZzUĊ7)'fҲo` ?n[ aBPp{O.{WgT?u7ph]s.1cvŎʭwڸ=.λvݛgߚřeNu/pȗqϺ-g@P!7A^:s੧֔ڕ}߸=ľ ZH#"z`MۭpD,Ƙ[12䰢e!W+) _|YMCmI\(Z[xjÐ(; ژJth^$>gƦG;-y~+HhPHj*9~3gz# 0Ȍ7k՛ S^n2/ FM2ϩK9Nm;2pl`;Mvq(@˖HaCxk%2p)(K;/L8? cV)Dk7v^qv'm#|N5Ŷ"Hf̞NruKZOj X{#;0D^Wr{|c2Ez^'agLGö [TI٘1c.^H􋹋te4ͬ_FɁrRYM,qv4##":+߲ӣ n-M9RH)ُ"`Y@!Y$ Mq?9]OfaÆ̥n(/-gq'\5ѾKZvu|1hIt vZDOCt4 tȽ/zph^t<Mc~ȘU[>8|{۶lEսbC݇Hl~sC_.UV%dTv,Z;W\BIlQ,> T$ t5˽kL`bZE:Cp( 2IЛvPsɈȼtRy鸐*ұ*D~QUUp>,P7dxAA_S3/mg\0̊Bhۅh6wD*$7p;SG1u_Hno`;;{L,ֲwȅA&F|z@HB r4ˢ>}rբEn}4:Kt;F"@ 0Rb Ő7yfMyaGz_Rk˶Eě=luh4`s~ɔA*t)!MjY_WX|KIc{3dw'r; i؛@ty`<{ҏ L9{|N%s*wN{~1̾$1~m)x_:fR^źB-!?=i^{FT8$tTTNG2-#E2IyqmG՗LIs6\^`%A'M: \jϪU}&ծZp8̈?LFH) N>p8AUU7"{Ѿx_0Tz>[R7~~ʟ#*G_7Vǟ _+>3O:P }LJU㹃 .X;+(3ONx=rajO7|h5Sx?\."e 'ɝQx,HT6}j$Mqô~~3g׽틷0/K0 vEPao_Z4FMeЩO0]Ϗ4be]]ݽ'.Qaٶp D|9(fkƘpiAZfNjf²`ɠW\  Q1F[ 6酁Wl(ja7ɉP k&]X*-ECǩL9)2_zبHa[\ƨN_YuC+<U Ҵ`dLL]>/~jjjX$%E**-qt5D_ZT2捞02UID~= &\@0v?X_qs1i̇W_xn&,dmd-6n\6),mp抿Ði+}~?eC-0DrG.~^ *(.ӄ+-Q蠵ԅK5sy}A:ɥK1auX}*#B`UɤBDu !ōpgr0l!4.D e[g H銬^`z.>l_=1#Dq#%ݾO{X~y 9In,8!KlLS&Æ4p95~04 2I@ AR&#Kr@ή&1G5^jd1nYCBW#%oUF cTg|㎑xKL.ڵ2h]G~?0xb%L>  (FuҵFx7߸S',}<, (Gx2IS:@L؀\@F` %aCM4$ IӔu3o>seJ (nFB|ӹLt8%BW(-T;#,뱞Pմi|r<_V:ZhT ˅D:Ύ(]@&s3. B瞫|Uo>W{?O7ߵ'ᦙ#AA-IjkTwٰ@X[x"Yyi v%'0F,`V:|o;A0?{>1}p ߎ^<ќ$"G`L@W{aհ7vl>4<=O$Z6$-{3h2Zv O|j hG\΢n4ue쫐,QF= Z==ݸn ?}tALVVRa珪p]ymV0Mx=hMUs1 rgHuc|^^}⒒F8Gw^M{hs=Ԃkv}}[Fл=kϛ_iy83;z"jD^caXd$Bznu'xp7v3:s4 eViNM3?!4vTyP2 w߮A"96+dUUU^}:ի4!2J6Ҷ-e"!Q?V|=Zv%|ZO[-ҲI,롩UGB*dgL7Mԝ$0b9 NCl;a.o_&R|޾W=ܷ'^eu4g6sfn%S(tL>yx'shN)Y"uc'{(؜ )% @$코s(hٲ[64b p9]p@rؖ np:`0h UVګ_{aSϰ^z{W 2Fѓpv9p8u6Do{\e=qeEϥ :p7nXÚ=U`q+  Z@4 ޳cv+z!aF8/g^u^P :J[@ Wmƛ[?]e}~J3j p;0>>>hk^_\ʆVCܲSd,7sF_h7?sFð'WNOtQ3+ũOW+qbx A!I`lq eX/GMeȑFj'YƈjQW2#_eUM %(rdCvtDۥV߿kJxcTfTMhitaPDX܅n%y}yJ2o>13ϫټD55Lt75u`oF|9I@ȣA#KWU!Qn}x^eeetҩk(~ #)^;|V}f,bhڄ}R*fM;,UJymeeCv?xr{CEN[C~ A`\γMK@uY"x^ .Uцp& .&)%>:; :lyz͟AD`\}G/1}ܡ#&ܴmZr)׽$06 `GLDJ&K)[݆tmLLwH(Z[Udnٕ׿׏9aӴٚS&I,e=])FF3jصo~QUPc\HL-o莩Hpk?`6 ஧=qFcssxǑi~MIb!Sr 9 R]sW0zL@Z0𜴖 ՍWƥR0D i-`~8}uٴDU `/W)8ȩ" h`Nxs {Kl"`~w.$ !0e# k+d&. ;Wc_YXrhQ·\`TW|)9/aZz`[!pO.Kb bm? Gvz#TSs9`GcU#Jڕ#lLBToZ삤l#I )`~lo諾XpK;;/*LI2_C4&Rp+ipW! !JömŰ,/TFW'1k^ڄwaEeyG/bs1lō?V)oM?qZcZY>m]Qe#eѸNYW]DmI2RB86AB=' ;.ȖX||2|SNqߦ۟r%ӉeQ誀~W!% %fO+srzzא|oDRc/TR?IcGjTV*d,Rqѵ8tb 22Q*215[L 9*"d ,֜6mu'n3\ىIU3|N)>x)G/)x?Ukmѫ)J&d&'Ec_":&8L* Ð8yWo\f\^׮pm242 $ڶl,UmBGZ~ ̘m۶7t9OرL:5m,iI)jI)%1\n~l(S}ֻl+bR"mp 4otIGBb.W"p Uu⽛fRfd02HG fXС310U eMQ=}:M㐃}?ZW_3M5m.d=QBv^ 1?jYkem4v؟PU%Yܚ GiM#}{X, ?AEOp۲N/O;!u ,bVEw~xGOۥ BNKn(Z!-|?>\ijCFP? _dA2$ɑOQ#'݃[Nc 7e"mdu;W訜ĉL/ʾwq̪ѶlYW EЕlT^#G׾nL28t_@O JuoO˃e8D%~$RGkP0chhL$5l(#4x"={Q$,2"ri /vT cD%@IJIoe+JF<Θc蕀$giwgM_E  9 tӄ]z/Hؿm_kg6&$7 * [:{m7ae@X!S3 @oBa5# DcP. BXii..pyh,,vR<f| >]E/9d`6ǐ]j:T 8dqX7;2\C=N)=浊Z } UͶNHӂꃴ PSN8F̃*Z3*—g)GiZL 0a`\f#2!.[`w2nHA*hQ'q$ɧ?{ީp kUQX{֡e6wVz(yPڰp(pKzk%DWBlU:4!h7yaU=QcV -)CEft7Ew" )h!ä} d "աu]túcLWt'mHÂ4 Ȥ80V톝tBI3Q/?pH>0 s 4҉gazRذ,ErR)@`DYP]J۝*ov\t>Lh!y^ז Q(ɦTh$`A]{$Ӂք {茚P UT." 5аzҏxFu4~vL˂ B4k>1=0vYLzSsz4aV5.L[L]rڤ5YUVFöh7?_ [ގM{&S_(M_I^JD۶o# BnA.)ek[`ZiAL0ڼ`a'[_q("".]cVYWgM׿ 1&(R ހ +L9MKwמhqy޿Q!hj /.ؼ *Ө($ju"#/H: 6W T!;_&Rjj kuoqj/O1 7M !4-%-ZAOGw„K%Je'}ݛyŮkPA-**LfCa-B@UU)֎.#;ͬ|s _UU.]zMg{(+/gG͚x9-"eB~ʕ+'_d2A]8bO7% :(ݵLQ`VHtO) 4=`σgh+&@פATg`ͻ[u{pN m-x$|`*[1$2~1_dZD ! =Ҁ#8DŅ#8k d2  pmg(XH`e=-YAHW M'DT## }<r0Bf0"&0z>Ůeb+Abhyp2H&ϠME#dt;2߿bգU5To8ә͡F50- }i}tՓ JvB"ۛBF7o;Ϙv8#^i@0T mCp14؁gB޲8@  T)9tf#uYOe:rG r-KF,F+¡| ;|8gh1[9vՌ>uU^SZ[R(e`yh0m.]R{TvEu vt}%+?TˊnPv9gxb<.)$̔ >L /M "AO@p cp"AjHD'wλopG]3 N !%Yֶz&fVh C*P1nLR[-z,#"$6Ѳ\4PtV"QfWR dk$%=-^ vʔđh+Q-p'02gCx d;?m@ H%sELG>X3`F/xO0M}) SrÑY{s U 0> r$_'8K]Lл@I 9QǯoqWn޽YIQ=[o:$Đ\z _!3dĴL6v[TךӟX|IAp:6LBcWk{RH 3 IԸ(xU")ё|;DA^^0eՋ3;N[p-J2mېz ;>xbTG;PAJWV'$h.[(Ѧ[XetNm:=Cg㸒RqW졾V/7p`uj^[U ]wOKt8%<."M%%6VŎ:ҋRЁ˖?|5篖:q cUA08< 8H6rH LK6ab ETt08c㤪qyιN/ XwލjbIH4j,oMhĠIXg!TA`AzަrD@41ݙל{y^jU‰9B+X1b(M:0  JS9 !4{v۟4!*{zOZӲǏO&ߘVwִ#uH<%@ֲt {}귿黭747zS4hks!@4(sy ?ʖ?N@_2L:}Sמ(LaHd`I3ӡ1jF2K\ʯX+ SJ&2Yz%}G&=.:HD~E~z_F{/+%Fe5md[].tHH*~|wX_OU} ;n>9S9@%il1ϵrdl 6nv\@ `mpL$A_vm4,߽Uif@dڥE 4@4GFVB! G@3|?l$=?IwR=¢Bl7w0#!ā p&,p6dZ ή4&SɪRjU| !hG 3DFݭGImxPTW0B}=oޒ:ig#y5MtzD䪗RH \@gԲuIkx,Ro,hbt&Hfӟms-!F T*e;JJO~t׈ik~5wr_}\Ҳa}\ 9aǖM?QG|)RMsV+O}l$+ +V2Ώo "N,._pZ[F^s:]38~#=X_g;§>[7泸2;-'8pvलǞUKn+@Eگ=fR" OC18,@\*PAQVk-66nOv`k(Sp 7 !  ] !g`)FAPs_XX]'[돩补lVB)ڨ pmEU ywXM7 ]U0!$2…YzơR(DJa57;hX,V cYTJRJC6Eww78`LD[[!@II ~}饗Ǎ'T\1֬f&O!tLfx=x*O>'Vl\Zu 8&Cȵ#;:G#34WwB@0pݸK)x"k酧O@O_ +dQqGW;,|}U O&,/)RrC 2V_f=ѣ?ŵdd Y[]S{^۔j?hƗ11JKǶ5 >ē(ރMdf %|a2Ovh=qBWe$M<5-q[Ϸњ'K-Wi$GY!2K)S5qR#3p iT۶G&J 5He:i((@܋ih(/ w;SA"پ нNTJ$;C6zV|Bl r"2| JIP at~Vo{پ&#}) 1*C(uDӁD?a@0M3xeV~X?R6(730Q@;Olr@شLYJ*[2 z< +>k/,N#QjΜ9mlJKeCܽ٬wYb\[`B* Q0bgC>5kVFjjJ,lZ131%GyMKNN߶kY#sr3cMg6o?=|+ukO w,hL? 1U&3m{U;o+X˳L2fNPvHÓ9V9^~!ê+)=ժ'^^D). 8N!(`ˍtVC$^z GMS/Tq{kGU H?Dx eP9XIpO˗3fϵ -c٬R>lH3n,X NRBQ)Á̭))rC޳,!n]X%8s˅^Xp8 ˵8R:4MR B(%\ĞkؚSǝS V/l"4֛JB]|g|RBlr]47vnXa{46@׃gzɿ{],HATJȪaWPyiåKDw6eMM c)eE Z.4ͥc#/Q(k˟mlu]g{M[)]|isME@LqQ#jL/)t%(JB Xg7OfI(JT7ֶM/^WOY%8}pHʈ$JI0*. ^s;P( *Q VV*AnԆϺwVE~SI iF*z. 0mL[}a|^ڻ^K1Íl uB}~n Gغxz w!q0\ ԭ("BR9X6G,kgoZU" ;G PT64FaA, M03w@ ReYy|Xp廟B)lOg=y)_pIs}J%McZl(?~ -7U}kCl.(z矏]ܟL>o%&1 QPB+on63/[feSMVҲ& Ah1dxF/藆umN92;H;8ܳqo=_ʟ@8LU;ox`׳Qt͏߳xwp̸Ҩ'd@ixb?+>aܸ7ƌsmй7ԟ=x4}܋aLEe>#Gb9VnJ~Łjpmwvz㮻+[F 2fd&^T({=JZ:ٵ;~ $n;ǭ,d n0@PS5jӔf̘]\=cʿo댽>$3IYA:.<zПqVul.{߸` :84R)9ҧ/ِfwQe4 Rq$ Xλ94 sx^AXN.q6pf)A%6`ℋ 3ύ1 >.{18 :7mDa((\ `).7vopb<:)x|ݲJ!aȅw{;N9LR!6S7=r|ɛ:u;v:H$B=\ >c:;Y_"rZ|C QJ-=[1ao_4w(u /6'^eҹMXcyyc)u4f%V$!mڶoպ3I>FK&|q:R5BhTMM=~L(z.s?|Fܢ"lٶ-b,\xޱ,/-pß{꫘|-Ӵ:p+5-p$/F/Č3cjk?YcΝ\qTic^epnP<|%8 BH( 3 !Ѡ!C>٤6UPr gpΝϾ7{'~Q锛($6})B.nU[vyRʔPKBg/\E"z(R܌թ 4_~9Ssyڵk(]\^]sO6yA%4X+˥(#BTha׀M\7VdgGihhM-}W&UC s'ؔ\v@4kښ2R][&]7J}~s&A  PaꠊۄH  t*. bjƎ62oVEC| P%nED)¤T8B:Oe+-w71|ъ8K۠Nmw22 "߾E TrdҔ7=\Q"Iw ʑDBroRT1E -Bˡ{?yiUeyx&V[, J@AA\zAXNrݐhnC/4BA)/J .h 8KgUyU7.]]WD54-~ ĵ6<-ӫonH$B=<ٖm5VO4 'y?HtזMؽ$ (@j(:\2]W=ZOwaM쩿;1*ӫE֯3Ξ8 uB5]9d% `p3X6i3K$߯ߢd͞=ɓGW>ifes]*.8B9˭o޳ 7u ̇0mӦ GJI){@)(˲! Xq/{#G>TYYfB"UPP@! 2ҁR:zV81 |>mݩ-[zg_G>IRǻigѪIQؖToض;VP[\ {=6JG_ujK4Q )%*2rߖ7hED"5ڭw>0{eVQQ1yօK$˵P\駷U n eÇ_v+np l.ǝV=4s{Xґy{o#ɓ'# Ύ swJ\19nCi(Dc!8IG&k2{@m .›jG:6 R" #'T9ݜ`ȡ@ w/>U|>CG3OU(/Я 4&!9WT<RB5(>KYO8?ҤR-_p[2PPʼn(M ]՛NM:}K|π?ʹS  s&AEP*.ח>5TӐ &:cS.@R7]av,F$BN7n&y oQR9 FP {ުu#>("Zm-hD$֭#46STzMIQwC9sn$9£޼ azk G+(8&B$e#uu}~@Wq]1n?={ѧ"[>뮻/..F*Q4Rs :YoOvڕx򳶶?i͟~⽓oOnuM R܋QCRJwu̞\5b^|8X}eu.]0sʄc4.$Rx v}fo\ytvmˎ^όvj@Gw_3( K/-JwBo DbA-aQqՕܵk֮]{_q0&[~'Y;75!)s-ب`9f"!d\y uNw0􏒡c{޶4CHQj Er^Q}!RhE׃w^sLΖtTZuݍ(ċB@Y\"LseK>M !sskow{<>YJ׮]9#/|7'G2hjj_YYy;ڥ۷mH&?xSNsA<g/rt1#G)MJdO:oQ104seJPxǴՅ~k %M[ -]_>pZ?Ճ54ziFxF\-2csRwu9xu!ד+RڢEZqž}V. #yV( BXM()'&?&qd5<πK/!%~7f"XP`|EPrew~s֜ەY+ Q4M뇝od9=~o+Qm^޲j\IfB".ʗ?'\s=pK eD*Ev"Tzb׏?eE_Yqh}S~{r0ˈ8KE]oN4)HׇUtA!$uߛ"zk_ʯ7gLր-|sꍪ/c1ZBRb NS5O~$-EϾX~˟"t+|U* !2λ{b^nI=S\b< >)GmA6xO@Y>d'UwvFonmڎ@$h4{Nᢋ{tw)fmg?c_MgΙ3XD nw. os΁h4VrJ)g:xCI(7TMs*Z\]@a>ک#>hsZZġ?jOdm__O~.`+Bz&;;ln !*!$eS|;ؿ%rSnXRC'+2pAܹMVNt"̞}Vw+/..z!^~/xt?!+D^T=aK@'w︣q#;@_ذh^-Y8˙SV4Fƞw&IbKiɷ uԡ  qbO\[841Ta8؝p67a߾9P%KL(++=zt79#* w}Vx gٲeWB i;JJJx*!i:uj _s466VYR.[e2|F]]k9昩7 9L'8ں3(u&H)`3gwY~edK.BQ',QLӊ)>JkpRIK vQJn\pls^mm\f ;~=+,Wll7h---Ov4 ^/?USSþ}r8w/P p 3f,njjjkkҥK*++?ߞ:uTT6dȐ !Bmdc]\*m`ENHw^ Y˯ cI}}=kll]|z)ͱ<)|}xbAF;_h|N8C`њ^RǷ>ëtpzd&ۙ]?^4_lie5켵jժᕕCVœqcFy9s[<4$*o~gw|H`?3g|?1\]Du/9tISz{{#s̺#-lrMmܹٳyݐ)?<\lupb׬Yurn E:}R 3>uWi<bE44I/["X]Mć}аaU? B9~RBI7$J!4Q9ϔsD<]v>}k׮5&Ol_ &|ٲe5wC5k ,iUbwX]acQFT.vm#5 E-~W4~?zʪRQ2f`E)r!XFk*3q}q (y!UQ=[x7bӝ&?w֕8to*hmM٭ ( 9d\b.jO?nu*>6m?f̘7u OV:/<\ן/K ;}՚VgƣHŗ-[\rιm[<m۔BQI:JXlF}}z W_~uM5 ct(Zcǎ%،Rsjd/;%U#4C8Cp[yɔo"h1'fhءq(<7B_֗Ee.q i뺦iFY ^JH+ssM .qwk8',̿,yeat93v kS+ H;u֬o?iڪc~_Wie}cɧ}G^0^|FxhX,c%%%VPJ677fmV\9oCaJiRO|2 N, yދLTKIu]Rt:͕R!O+((xeB~b__[f=!dpO?\XTRrzGgÕ=[=_ nzӧO:ꨣiswRM'UJma\.&؇UB`n{i n7 @(x˗?ASgޙ=YX{]5Ǎ]{o0۳gJP= Kjc2DQe,^l,c=:ḿfxӁC#Uv;hYfJY{3Ag([*B'QnR/\@PhlACn^<A<6(s2m~n=[N??=== a(BHHJ9Q)U\ۭ@-\a8Lz!>$χa3gu^9BlRPׯ>PԶm=B8[|B2'lҥ'pƒ_/C:şޝ$G=6G_ۯ̽~>z[7_L?U*$tVgwݳN=kW9k~қC?IHb}3DG_>EXPR”$ ã=|;.uw]~ ov 9%##ݮ4SR au|گ0 )lS&;{X1HRa UDG|ObWBEχ} R=Z~?(@ X RB\ !$J;(E8 Kz tƲۿ1}t3N6I7^Tu^_xc?}QGueM"iBH k7h.YP(t t ԫ,kiww!sTw;!Js~ŜNd2wTfBp8|o,544:%HI/KKĿ,}iӲ Gg?:E\)ok놡r:DؒԄ͏}wm+ zx@זA 8'ᡏPNR1?AWE|m -]{NԱ/JAR`Diŕ#׋W5\г(kD hZG{g[/'LyYJ8QHf6=؈Eo*[FGEƆEG }r<;6e*ǭ?D;"hǨױ=}5V1 EE&u}A?464]~|N gN֢/.T@fh6 tLyB~EKG=2W56XTG|SaPc BuP*mJu E"%qxp(958Ril &Cgwba./`k1vmq^gUühG4o1(*(D|Sa[7a p8qx؜g_^)yUz?bլ,:7551B_zu}!Sl@؊03L2UŌ_Jy0D",~y_}pJ&e1 LH(N7կ vNv>ׄ#!ųA a.BQ^/L/b9NBԆ J)$7YyV.O25k$SfOЧj:4~$?'4\5/"F&*u ;JMͷ `^'l4aZ+VAd?\Dض_ޯ!dg[ּ: (e‡LU9 JsA36t%˗־IK|wE(Q_'5*/zfĤ7-Hʦ.h}o{\~xZ?clxjV[o=\/;+..8 %VL0C(ʥqx] Oɟ@~:ŪHhTf*YTFYƾ[ Ea0tύƎ?ǑQJi$HڵKkcǎ]0jԨꁁӣL$sBQ>OOii霏?x!zx]qsnOg2E|ۯ}]K8\_Y:9Ȧ JLVG01Y7{,hTfn$X4[YA)a:IBݴcfܦ/mXY)Y%cIEq:{qt6b@טbJI%RA<d݆ށ!h} QƲ0ɳ(VH\Xo_R2V[&匋+wZaٺ+1rdFM(!$T_xOj h+ _AC*(34%@ A?R0Lי\x+V3c-uqC> ){(,+/awԻ/pTտЗGx`Tpn"}x7!'e~?{%>m5|QsETQ/9]~aظ3~|PZf!*ƎBvT>)> `{  =l-z [.E Sg,KbZ^ #D !1$8nkWO2d<ϟ{{{ٹ;akV `^anm;JrX7CuV*ۡ „,E~hp@ܱ@4-2a܆{z.JMW5Mkݟ9Pkwe;2lb䈪&[1Rbp\$qrS@gGk%j?4fW>iMނaho2'6mBu\ W=_FUo;cH)DLF;Ǐ~|֬Ys !f;f۶5۶i&x hei_ !"3gbŊ9isq8!ضH$B7n6-`?}]13No~E7ȣkϢ憓kk_'}%^4Y(?K.w P+6252՟H w@.4~sz6 ^ ͥ7c@"0cȳ"RȠ8fF3t:Ҡ4åtm9n%xVe,uCYVF(Mk>4/ )lp ܊{^jEmlǕ-#ĮcQZiO& * )S1˕1rgBkv"'wkp Jf!% LވQCW퇂7cֳкnL3BI P(/\϶3a;&Q 6r;;̾46}5>j^SN9%%%HP>d섄Z_QR dm啕hsP^*Ps l2Q{|s!saw= k]k)*`P Ł$'D GU),)BZW5.\0&σD"ΜZM']Z 5 ܶ@%RpT qE .{k9PJQen"(]0\2BA 1ʶm',Wi7 uJ)hQF3?ϯ'(w#N{ !2DeYd2T*uPs={ R˲-[D-(--ix\0444H>}MWL&n[sݚinBsgF4ƍS7a}vM\{ ;?ι\y;aBlɒ% ˗_1'J466;~L<~MP :3mA8>ktĚ6 ]@gHY=J \{~Pژq^D!km"9gJqn =fK[w(68/louNîΩ`CRlK#T̸IC}kp,8gR(@0p4zk"qg-Lӏ?xb W ;B@\ґ &`C}0C3lK'kLHBPAJ8 WkJ02Rr g>Q(>f7MmV:)sclӂma;MiʚN.^kpl4cf>Qȹ O-;d0#1l-N8qk Is$6؎:!!ez`;^%⍥wO `WZ($2 o=64@ : cYrggd~FR`ӦG4zH9vZBcb #rb&pu ip̔ !3 ih4ϼO{co"5iE-4"a 6[}{r// kA*)?]h4*U'n7,!Yӆ9 JJX4 821`X&}N;@_2p!N'tH$nݺm]:^^VV0dwOOϩD"n]k[[[?lnnJ lIܔzJ1b(pL!Q"'F455iٶv PNJYEЋ}HY11a&mW]M۶lGPDnW_5 l6e_ 諯\qqYRaLٶ=1\SOSWWX,T*_Fsٙ͞iu^7yQ$Bؘ1c-Z0cƌ#)(;{?ߵ[:{"mq`VbЖ"X(AЛ$cS1]t +Ƃł; P$>ї϶dKͥ?LJk҂Mܫ@IBL3! ( HnR86zՋӯr\F :/AWqܔyK,ZCLoT|]񣐰FC/4́TDI`z_1voؒŐM<kFX(l†=bm@0aBHT?4+(XJ{پS>![((27[ Wҁob[埡$+6փ~ /YTax%\zzF` * `f!%H} n-f]8X6{&~=^mv[Xpañ{szJQ_ 18YL7 CKP\XE"@ /-]ūs2vi Eb 8Ɨj0|>ꒊDT ?-u5Ẍ7hC<2箬.ƈ `tB\^ `l2ݠTRxj믾1IƺF8R*HP x#TM]0 عT ?kK~iUpǖiNR o馎Sq]~0 u!DN 3͛v`Ӡuȸ'AQw`4U޾ay9ړ?hՋc)̸99lPM `b@q5@qHJ ́a[Kuu(d$}Z#Йȕ!(@*h=[|t8<w<3ߵ=zko]5 +W_~k׮mBRJUOA\a &YfmIIɥx<_ th4:y{R[iQMӜxe8BT,c]tf? ?ρ۔RkfD·x衇 T6eYp=!+K=# $:: t ppB2D`G?58 t|Sѩ\弫ex=Rw? .#t6P;u pGr<܀JŠ D EH޳@)@s{ʟA&fN>+-Ĵqol;J躃 =\FJU*ᅛnS;^zE^U\r"ܮ&\mmSjOO߅~q"4 JUT JSJS\(B5 ;=:DXӹ5B &+c0iHQP7 % [pxkK6?mad70bg4x)|,|PzipN_S b|q-lF6f4A#$GL"WŠ 1~Q8:x )&y։?r<1>YbWq%S 0]J]W]M" w Kz\R#۶1NK :3 c7p]у; /IO1[# ˂NRP* ϯ߰q+z1@5!\z2@bCQ)M`L)bR!@^oQC hA1πB24:{0j k͏бC7ĉc1cUV~2HeپkYS/@뮛5jUJի޹ngZ M,>I9oS`"\A*5P䀗$G앦mƊ·r`(n Qֳ̈́p-'FwU$9߼";mA=ȿH)+WXd2Y8wC! O0E|[+򏭭ٶ Mӎ}vSS몫{Æ ?~<ӄ6=R=[oug{G=$JN-R~;ѭwڜ:B*!ܚN%@snUu-:)lG_+D t)y ' =!.A2]}4ߎ KȂ_[*$8Hj{xwz0s )݈+3}@U&׾2Օ#;6!(¿݉q-4`[ ² g7?*e+gC>,ܩ>;S t)_).8e+!տN`$y hˍxoX;HCCcS(!T_R EQ }2k\pGsӤq`AnP(A(F˒O5=na8j,{x Aq5p!Li.0b-ٹk-c۶('SB\ҲV 1di`$RNzU "eזQMmkh,r8sL& o0 mT;L%)@<.o3/QD" NA21 zJ8S_܂RHdUIǁSڶmpΑJFk^ɭ] LQGyQFx˱'ŕcYqBX؄DS[ w=q{u!*Aj.] 3vͪ,cy`pRt⯽8k~$ki*=% %E"@XP 0M+`g IA!ϰA` 0;!_B$xhړ/nL&ͫmYx踟$jh %2X~FQ\~v '5W}WJX8ˡBpY (Fmȼ<@J%%$w<0^ )A(gSX_0W(t#m(ˆːT9v]Y 'V7bĐ`K= G,BWh4lo>X{V␠`Z~D7[ǼSy6! oK\EV6!:@j0Hdפ1bh! °Ebp1z Ǹq˷..^Q[l˂M I6@ m8PP2dR)躎mX37V6KQ\\$ o8 V/m~z笋+jpe\g=!ܶm?ip8 } p{-3T2OIKM7sE"$W. )]rHiMەs%%(ZZZ8m; ]^^ )Al'pPC`6'hsM!m 5`tt~9u.]{UUUOL8q$u_Cmm!Ă;h nd@.֝ϟi3L&?@ PxD"q=L)<w,+())m˨Rq}J)%R[n* L:BvUUշ8444 _=Ecǎr ё*-=zfB! cN kp H"'yV( RSC1b{{R)I&.(e@J7E+sJûcl:E Ɲ@O;IvT{o"V7]ޣ@KpQ TP@pދTd,3AEN7wxa$PF!VPJK# D/&T-êgbT{ܟy AR7P`y  BXJh(!sVYs/G{mӂ<` aِӂp v&7AlW($$|XLTmAhK@_o.<P6#U݃:ȩUMX5@"sjX}jiB.B)RDQJ5ǡJ8l7Tw3vmInSZJ/Nʋs^U ֭;O/B6i<<, 5=훑hS })aSߣTӯw ~OlhAfxŗ 0O´lhbֱ1z"x-lYL:6wKZ~]QN{P sa6)Qö8 @K|Rpwl' .|n#$8\8\%+έ /n pL.<Qg=C]J2MX,v_~%PAc)8 %'A\^\e-|9W>t4IDAT+q{֞{+ͱ[]8s=CPbqe QxK*ph pm/T@#.a6 5 zDvM`MRTY)rIX_X}=kl?}„Aܶ?s?9_M z7S7LJQ?gA&_rkq) @J~g \{<aX43)ܪ|uuN!*G}2dH}0G{'/"lngǎ{#!y~7.dɒzB+9ȨCogAw,aB.nP˕΍RA@Mܘ P1h^U޴\3'yv=v)A)ےXiv~\.o;JA ,6ɳcM˥(IURSA<Bg6) rN=X+b.@庆s(B 9Z|r5fMx]Ɇ3Cvڻg& R().b"?`9 B(:eP3]TнFw? b `.>{/ayKt회?[C{8L#!#q,|!Xt̪ڍK娊v*{KȳСhӯ~'89E4Q. Bj/b\5%]LmyˋJ_Xvv^e9:"VTw<`gqh1 }phH ԛ'nDKu;3MbJ DzX@Lcqa4m~p4 "80+ࢶ|Ԓͫ=J?W110`Qߏt6 ɀ{<>rݝ03iH!X:VcƜT 'NTR #([ːcB ض(P0ɓ'4 I2\%mұNmpF;4^ƄnwJE! BjeP2 tFev(TP;B)ժrz7gXqCC7oRݱXCI?Ctxm07O6T@B9TBApV0dtl/(:\bmɻL˂T#h>l{qWHdzZ:;r _qZ͜sf z5!\p>?gY@n&^W6KzR\ƃh~? x8|8sBsν(4WWWO|խ: cƌ9nj^KxtIoth"ʵ{< *uO0mMr|8 M9@C_7zs347BmW]gr|:|NL \sG o>DcN[ L^mfy{ KJnhqCö DAIKyl̜Єum'nJ'7N6s.9gƲEbv7^;BeNe(t"@7#iUAsng%$RD4dm'rtw7▌'a(H)Mپ<@.e (%AI.CA${иF8SPШ7,aJ=;W[yj}M*"hnqten c( w"Ds1CJN.9rS=П2Kέ,?-ǣDGǞ=()+Gt̅M4,!wA'n|r1.(Iޢn/x_رcG|  U__yرc tC>;L`Y RE"s߹Gw5Rr9;ͱLB_7Mm6~ жZeQ\&6OŌ A(P#`K߉( ' x8Y=[+/<*S-)RL囿R(躍Ow%QQ y[YhZȐ*>kݵe|AnJ&dtwMsqqj Hg3ZHArrʺA ?:7=Gy3[]c!,Ac2X4  I|(NIJI^BbVg}UJ)K RkA)) ݹbLdţ˔:t@MwD",צ{=)+F|@BJ2UG)q9B/5NjjTjJ((ٷ&#n\SCn&^|uwB/J zTyq*,ؔ7K:PJ a\hSAmug;^D@7uHRqƴl J)PJv # Su xB_-% # P v;P 1Ľ)s4 @ wAd7۩s ^w.d"n+Bi MJ-p,x2Q/<9ͅek{NWDvI߀mB9(q}N|8;3 C^ "T'NSL9o:o\HGI&f_/B@)PM!Blz SjJz.<`] LtB/=%޹FyU.B7tdRԕԱ7;;G6e϶T^{5ek1K2V ';l-]`ihqCS-f7!kLTsν.s0%(d5q߯uS ݻ%`[rF okc!z 1U\-D>B.!TLBBJB$p6H\|??}K.^Cc>s|?нPݐ|b9& OK67`0Mǯ\ \2lDž Ukv&4;ї)%YKא~P:gQu/⢮G$aLJ.X/^InYPRgSHp[%MqK~;`'Q 9dZywRRٖe.Y(maC%U>gk:*\u;eK,r/`%BI \BL ɽId%i !DB -T7ܛl:}˔{dLM7sس;gvvv>p$"Sot_~MnXaiJ5;H_C|6bۮ^+ϫ{9f[3'Y#<Lxm#)h=oUBz؀ @UM Ba % k aؽs'&5MƆu1SNE8BP QFhA(`&CAz°MPơ5&HHO2/\ E DGvt[+ [&!Z!T.ʉ:(r2SxN,AG / bpČ_3#7nӈ)Ô:'2(dl .[)oٖ~zRs#Ci N<#fN8UoC]j+BHuYY?w9ff5///J{l2QCz21j (  á›'5}7y??SBΖ`_%L =H2#CToz l㵉}7H5?jj$RCpN*AE".(#69?+6/lc$?coaBW5>6aIJV5F?ٿ7whgRmȪJ s+k#Gp5|M}ͭ Ko|~tQMh-ƒ0 ѧi&_Ax7pvem*;dyEk`qB"Q@`NAq5j'OCC4S×&u\Nޅ7ALᐮtD+(.\p 3fH10 (_Bv{|d uuѶ6Kg :mN,4&`D!B@n/uvvI&х 9&WXVX!Yxq\6AQSPK8d;n%vG\cXp8<]1ζI|&|ioo+VпoON&K$ 㤵Jdԣ~Ck֬91Wu5 <;0o|>?ӟ\pa,^%]fe(14Vڗ# Q,h)/6! XΜK3β)_o 냞k:(׻{;]]kc•tvv1pi! ƒ۷oی11fA|xҥJi9w -[LYXpakVJ _G- ᗗ/_~)S\][[ {TUv7F&u= Oטnonٲ 9t,hd}w^t[ln<^=6Q {棹q~n 8EP w`z鿩Dk'{z˯~`Q!h-A3{Q]>DLt{p0z[m+t ?4uX f#ABBqw~>x[@}Yw㝻M7* ?_TnAu'^pӽK ޸/2i_±jjkY,u@,^.6f Ud5 ##}84܇tZi`VHe,.lޯঋ`c$6!A%@ؑM( NW6K>`cx3\ /ii DqLX ^ƅxHڱAhyAYZRGuua锚Mq0J9ܽwW|fÿHmmm.N5 B˰DJ̽<bԄff2=::{{s y %ik0M3jZ_ryϧy޿kc(eH(yXKd:v,؈vwMgk+ۼy3;11sW>zK>4?ۘkgmnnn͛\pC%[lشiӏfΜyƍ̙0&Fڇ?ǹshMN}ɗ\r߹tNjGFe2b2]5Etttsq#^q˨B*1{A9SDy}Pn}osbWPj.V;"J>s=ұGv?Ů,PVLN}e!dṙ:É+tz!$aQ@ Oi]At_˷տ7ۭ+Onoo۾cRu4@˖b6-2HA.T}yWIoub|t?YB(+Uv~v0V1'$:g\ ;e-eX{'A=0S~3;V?8tAJywi\4Ar?0qB{@ᎎ-9-AA,X?=1dYVY8e2j]N.]J.]*O8^:k眏㜧m])P.;s()3ՈF'2 I1d F>vvꙓWpUW_}]r%,#{<\߳ zS(?cc>s9s3bKK=00l3=w])_|gogR( }Aoe4x2ICJgTd;3]A{]'98y*&HĂa`s H3gs}mn1@ɵG1T@q7WQ8;P\Ƅ+23Dqdfodh#nmظ CdUK {/a6rܜ(30yxڣ۴+֜w#A)5tNZ{o_ېgd&Mu}ncS`^+ co~or:=kjJ ` \9s^o(=|>a1 AعJimIHl}iȤuwt8'w<z՗vZy߱"1$ЉC::GmlCUǖ \Wcbh:䷮}\x%"cxS"4==9mgO~rʖ.ϝ52,dg6nW>췝X|nkicc{3/>]͊cwik֬1FGGضmȠ,cx9'.\>Ecَ)OTh軛~uoiuVQK98$$JSJ6*nf#8K8|' Jd@zOUZ_y:,o>O@`|Qwd; J_!3}-~v L4 ^!m &M}{V-z N0}9ܲtK,1_m;%A-8<Oʪ@/s4G}?*,KX:a,VU%+ KϮSk7޸h4v,c9s~픐vGilLi`|B}e _tfWEGS=)71ڟBozSSз )ZP>Vގw.{z;YWWNaמ;_+ КXA>Hsrv244kkk%'/R2YfHND'X>R=o_q^@WWwSB'HrJ)!PbSAg%+GRV٩ )MSK)oߥwQB [V`G㌎<@19¬|Ѕ^xU"0Yt:}{o-:.p26@nb$Ղ 7k˱t@wOmƮe;EqWXh Fy#l7?.'BqUU~_jѥ|G̈́04]ߟ3' z-ۏծcƌ&~'F(K?vwt]g Dր٫P(,T?2ײPW,jY,NX -ExytߥFZdk'+O;i]٤;jg5W ]0lR˗J[8r?1CE0v9nCe;[b%OhMٓ&1Hdih߫t@y~A)_T-h5EM^:tVF3洗jY(hhiU(hijkK7|h'˺źW!pQs'=cIsr{^>aq,b;\!X0{nN[x MᒘXm>Y7,вut@Vn --3y'˺E[dg;nmmm^[[m[B! d,lc!K[C"'db9aKB! mۢM@%[oql4Rk(Mь1}_3tPyZk-!h s㙶]]]rM{Jj)esuQ]B+ZR +ԾKf =3m񳺺$!D͏e3e0Mm S[6 ym>| ymBw ԖmZ;%ioo$(0#/_Zr'u&LòYieY&LpW_nʕ\|y"K޷S>>^;'X':;'5 ?#HY 2͟C[S=ُ=i6}HrLEXr M%NW DuoqA i,$p~=!vi{Z"@`i}R ^r~ (lq%nAWVVʞ_zj$}&3V_?뙣)bVTBvJ%^dz_5J<(UvqBE97 Üֵfm<W{xsff`Dzu}_-<܁'ةT]"I~vWw;v|X2?wo#pRGnh y?~9cqrJIMRl2<54@%@~hh$PQ8%uv2Ѻ|yH̝vH|.Z]9- #N k5bbY]mh*s/dx;~zOWGG>uQ84BX% H(ZX&(%ɻBwf>ف"p칦*];y'b\ &%I m^|F`P0((E09P OHؔz̙TMkM?!MPpuA*}*i嘉K-H\1`2b$šsg֓ 'VcXWWlom5[,^X ]Qi}PK9aw&qGGSmkN=naWחuIp_cE*`|aR%|x>]m][nIJ_еɿ^fӳxddعs `pA}jScP5)=E>j-E|!ȶmW+++ڗkjӖrEWj d[hpnR(C,U?xe"AI!N%&y>yᢹK&ӡXAI%)#l.0X(iBݚv!E V L)p,^Myrg.yf~d`vFIDO:޼e`z ; H=A<#vc]k1OYGGX|ysϽ:J}.JM+ 핡Pb1 |^iŚ~Wx? 7- 6WIlL|E.gbV.V"Ӈ?:_q xZ?`v6I::ʛ:mʇ )," 6P:Wq"B[,A.Pni%kwdfqCIO6-3xM;@Wzԩ, _?$?/Hf?Չ)PX^U]q$mmE)ڦ%jruqawHe{ cS- D9go+s F];r`Uݯyڻ?ũ\L?L}e3 bd܀Rv b >4pJ()L^!ǡqb9wm C 9c [Qf?MEfRPXD*NR61Fiv%ta>&{6!o^ts V%/hnѨ=K?fƒf3Ԛ5y_+س _=yRzՍg _عߛ0![%!V0 kI0?2 =QqR'>ᘁ_dX7=~v}KmJ@TW5D#D2i 74¼!^d Z߇ǯL$ؽg7CEĢ4`k<|eyG-fE$~:h&.vqxL4T\M>c^d:\ٷ֭GxW!}F mb1n?? O׻U<l)xy <,eh\aL!`.ixAJ(޽ #0ǁaZCS A A<`>@]R $dDRq[ǧPK[[\|yhٲeW/l.ؿ䜓H$(( ́R۶1::u*6~_\ve˗-[vʕ+i+Lxbgހ}c:\u5MTŊjs}xq)3 @Q h{?@PKJP2qp#睦_Un{j@6# `\ޅϟ]%S|=s\ko|nrI}Jo.1s>kkA!М0*q'v ?kioL `g fm_4M(B0o0*+_RV8l~)Z{XpkkWf WG2kW1A—Pq;,͟~g_^NJ ?*4 0Jh&G)cO/T8ֻz~cvN~c)IM?ݑG+bqTPF5$)SF(I]]so6 ?iͼ[{x&WbDQ%d{͸wiv׃Oּq]_ruF, ߋpӣ *((!.#. @\.vG /@2^Oԍ[+I qTa@mßog^⸩Zȟ6wL#knTwuuK?L%Lf]xܜd=9կcCس \1k_x$voߎ}qUWiv8wNRx9|1Ԏ 'P4{r#_ؖ3*#L %z'E0Kj$RZdo id6f{ 3Ir4 2lʺ_PJX4JQtP0_^Xe%PUZ^HUU#;0q9 HPVж-FR+x 5ݻwK5 B ‘n@#/~RJqꩧ.3g-p[~N:_ݎOͩX#Pq76@< o{;Vߟr7MF-(<^Gg/Q7Q|j!EZU?|Cn_p޴n"| ;s^߯R7G 49dq[JOJ),}X hjZ r9--̞8QiC!I&$0h~u{~Dt{;Ytz_pee_Kw;'kNWZ4S8*vҰl1_ x42bI.G=&|l)TWʝ+9~Zᄉ{GijczQ%Μ3dMhf10k~|9MT+Xl ++eu GiC'θ~>zeGǾw ၁UTkfhnNךЭF,,XJfTN0:<̜W+S45ޜ}P3W0=[1<5i37H1 I#TW_S .y3_]?Hcq)}os%˺-gl%@ *ۆpB*f9c).ObLC`|} ^x] q 5"{>=WvƐٴ:8WTZ!/)88XzfTQBSגJ<(". vWl*hPGwGu{LˆyJ@Ӱ,&"SuHUC pB4 htm6 v"J,FJ*B뾁R[T Jih)aps3 3"{RJK8==hqI !l߾}ɔ)S@.###0 9BM#JBXk B*Jfwnٲe7>%U!HդB~j2hATf;jS"B4AQX}ۦac &%__O)d};Kۑ~+B{KƯF {-*?|sܠW#4UZKp15J{hC ɣudC{Y֛)W$Gʮ'>BIbgs&wttl/Ť3tk Y#ay NӹƊ/()!eesGF3,@ A#}EBGO:;:^iox3lcˌZ;y@j?nhr,l}^甇o&Kox 8WtQ):<D9ahs`fJ!0о-DeĮ ur8\m7[hxD\ kOF=۷b6ON#4kޔ~d zٳ"%&6SU)lڲ'x %sf*KQ}PYS J)<Ǟ}OPzz_-.pSN9Z=:O+fp2>EF`ܬpES|Ed13juwMҺ>ںGְٕ+44aZihOhn\ Zm);o&LFμ߬n/;/syFfe |heZ40#"qLLbDP<7䡝Hq׳ o|̉IpXkJ̭GļfamxADQ,= !0b3b;B{>r!"$|AoF&^ʖS }-Y@Tc{߀ThU %tBA;W5.Q` B|>' wJ ەaG@zd- R RikAAgzzqbPbRq5,N3# MpX;NQ*ׅ,8JJԘmtl#_sA`5krƊNOt*+!3!6 R[O.SB(˶m~M(@L8sա3Î !^H?qU~_|C Ii?nx oJZgЎq'onr `<_ !pyxwH#OB#a .X5+Rw pwGNCPkj}@,~i ~)H$K7|:}^b!z%۞f'_ܲɄ_7Ky$ ` oy lԅǡi"qܴ׼0}𥄆4C_?#Z&}p̖fN4 >O=hhQe}1&jX--QZ[Siɟ>i$R ʪbA  cd`v$뒡7Ewtk7m'&$D1myVRC=! `*!ZmbZG[d;69/Y 7^8C,Ύ.6yьɕ`gvE{Ĕhs\'c sL:L: .M'NڟZ]nOBjN Gгu 2CػeƏWٲ ![0eRBW*s@-~n'}_F(13kjasFc^]zCxA!#HUH.S\N%A&`*Gbt0+ )<(D44 `JdӦBү}3h<2PK>@#@3* iܭcP +q#/"Їݤ+}xjFk/:z0 }C(+R,PӀp\@k8CA'Q;FAmK~j!:@by5'\m?@Aq+  Lx,*Rͱ!|$\"LtNb ~0!s3wg>).~E!Pf.J4CVo w@:{PV/ *3NF᩟"1'q;:Vx3;|x矖cYӇzIfd4@ "YY `h,0.BJ*^GYVѺB@Wy_# [ۄeVYoYF)8PJigg's]wRN1^ i۶_vmeq7BF|/@AQ6  @zx(!B$3j|$;E=A4ׇׯ@- FR"iI·l5b$BP$d*C}EC8m,oATWW0G)Ju@[[NK}=rq-+jzyL +43ŗE:kJhJT@ڐh{nOYy}B=(FA PY0PP qWrm죳Mo>q ZaݰR1೓\\^OQ%KrpQGj¶DvD`iBAآb(G)CX@,W@ndl{P&v+RBX(GIs⻌HW7!\!@`h~TU=>S@G)\G&QњpJcg k7>t 1֏G!(r=p(T2u,>+̙3Õ_~y02zddb1TWWc``eeepP|a`ttDB|cUSV0q.Q~yKJ=19S+ʻA'V;Pf<1 a74")}fP1TzqB8y> _f] #ioGwI$ A4@"8koO"DzN!5 mZis&gߺ$lZ4Y( aP/~" 1 i'qIv7G_:P >spGۿ~z8tHLG+V2^6'.umHT{B@> >A࿘I-p>hHa E`˿&΢G2Y3T鎮.yvF =жඍwol؊2lq3`X8o:(yPK6AyRou^;x99Ou0 ~AI>s0c ,L58lH -)RT=wjvOY*m{/DɌ]P]ER%W CQ`X8ʌ&jǭT 1eѨkħ LJmXpqA.=Uԛ x!mĘRDl[Ɖd*)CE8| _}QrK@о/8@)l\Ꮐq啕`"Q:C@@jL}m 8+T <5 ՠ 堏̀;@OAbe[`}TC!POy e'1WbX0k-^!ԓP]Q/9rNq @ߞɲXrDIoᆆ2 J)(<ìYeL2BBc۶mH&hhhR . VZ+V/te!G6DP$ý @jՋx s]8^@GVM#|mXվL k0$ɰ @kQȺp| )5v="QbTdܢ*c+b.:ʚA(#5 Ph, Q`kծh:طb[<(|GXݷ[."@<@{Amw5Gk;#xL?Gc)+$3pww <9<ͣc À,04L0MK'󙎽&XG\OAm|?kXLo/{~#0@ը|A(~.©{#25-wB [`Bmʱd\rgf rucѸhơ  DSx} PD5B<:Bݐ9Q\X,'l&Z0!T `缵V`$ GM$)0q:'^3ƗP+f|^Tz~1ؔca9FHЕa]&i{HĢ8~tbY&$hb 8$;gA+yXjGs L`D _i&Y1Jt/NB Ϛ8sOYּZ<|  {'䎅,;J#4w>SzЊ5- s,#`U{H0&TFb#J"F0a  (:ѺQe#T 8| ģXHʷ@D! XLhgX@"SupLt%"6K.n) PhM *k-䳾. qoӿBX$'!eh+$0iө`QN~PlFQsl:9)?)kμg\DJR{$t]͒nhPĴF,؇C aI]χyΙRA<|;w0}|TFB0KU!l.b1h%Xʄz9abne D<Fj20 />-lO;nQG\JH %#RAUІQ.Te "(\⨉bh bEpWEEG,E ,A2E.C,Bȶ`YT 3zi+$$G!l{IY@'E>. J 5Oe1+u= Pء0g%1xYR 3v0ipbXa|,J|ZCj MԠF4Sݗ,m (IT!@ ◱ Cp<ai(K1BHy  W(b(O&0u}:ƍ}#PJmCt:d2 u{nD"iضT*5_hXG7ć&fZdӊRS8p4Ad8r @3;. w7 v(Ӷa!UU]M'8ٗ}@]1j6BBj*ŵV8h.98 <ԕ'Qa ZJ}.&֏:Eׅe8~Rw~ոd=_۵k, 1h R^444Yl4 FhW䅍iX5"* Z#UFsQWӼ'5W&Wxځ,q͝jZ Vh*X4ܼt= D !y Am!la梼:B:l Ҩ!|8H&b88v.R@P)C(7 NqAp;RH&X UV`zR+!!L7pY掯C.3J@ 0I&5 pT` Qf L0KD &UIT(8(MmzXTǢj5j#13@Rasy!0" F@ E`q" lҘh'9/VTl_qgpz8v!AHH#tY`C478t8x!?\,d/=$Ⱦ]ο']m[QD??GG 3c\nU b➑qF$#(H}9J,$2t/V[Qv=x,NYD }y[+8B œ 4λb$ /%ᾼ} *F/Qg&)Y C%شu;pX?yv=, N9=pO4T㑿=wsXĶ18cs0 LDҟ(#|dĠ% @K!@s]PF9+~bmmmPؘ>e+ƒh6VL @(B6gQ ` ("RP iټ"\(%bǁ%6 BO42i;c`}" [( @PnsԘI M4Qe)@8DW`Ç3Ǟ0r{1) Q*@ zD73KbȻ9@ ł@#[6B`„E>޸rs x4 Q\,bgt +pw#X!r1q"L#uaێ}k:e+tV A  /`gy@̯\@aYڤ M Fu^G6zc9 "d6{5K %R He*mjP, 3P 2޶N,$+R"VrBK Oh0T"'ipNIpP^o U{*0 H Zrp%f,%%auUJA>e(@ (="҅F, %,F!}WVA ̊:eB3@." ""V@&(ܾ])Jq= !cc}@4rʱ5;_?Jq,++KvixO:Y)!yRP-@T I޽{>i'iYqS W~ՋX, -$P8e!Q0M# +TVA(4x80(:R!!0! U L#rFīx^YgDAQsH@8("(Èjm(nX?߆¾ UEÿjgaq .0 #$<\[f@ 0I`jҀ<>6Y"] VBȣX,*C9n8q0, ] >D0Lp娮q| 8j|c)((SGqZCzæx^/ ŜeLލozXfvq%Ӏ B*z{Qqx`ZbB]5$3JuP,BŢ/Bf,=! EEEmݮbai4h.G_ 98 6\ )|iFt@dTKrP#g(PcX܇X,< n&@C`9Y39bp?n,]@Ma=B9 ! (E6_#'+-AA 4YDLDkJ)LΠ%,@"16)S7cVtP3"pk%.((44kS./VG0Ft@Uxւ¤/B *ja *+|:~0XRh11#>2" 8A};J9cVRP2PΟyO; hK:JR^ XWeR B1Jhaeo 3,B*1by|OT}]F HcE"ȅg [(b٘698z|Eńz;"jttT)əL$9G:T =`.{#\C#`dd$P\GO'VVV?Տo(d J㖝ic(2b硡JIٲ ;ؾy"ͦGtP>GRe ĢQ:tB hC>(%P,`dN} +B upA2 .T~З> %dc`Yӓrg-2P$z(fcxPF00Z,cgL%iWYS&m{-B&R@Mxq}rvTObioo'[eƁFA)hJ4W>Pp|R(@ઓˌvڱbt R>$3J |jRpuqg@O*w\Ws*8}K1HيA j' ׀X uĂibp6dwmEB(B+'%26E F50^t)d MgN7fD!G/u<߃K' 3fyҎ;ٌ0/ PB! !(~iH+({xRr,|!{lOZN9 =8Zf$hR#,zp48xf@AznyH h#عPȖCJ EFkA*#T,2Cr | H )"[pP$ 3l ! CF( *閏Y_S )3(颋+u=b>lzEχgHVB&l믽  |\fFrRRPZ#kR5bX@t 佀֨yp9%QR(0>F0Pp(8BHFR/Pqx9@iPt܊PVVf 1\.)%|R Oh߇\cм,VXǞp*kk1:B6]vFGGal/9d(m܈Y>VĢQ"pW>A@Q  ?:Q< f؜%v.b8J\+}| Ac Th5PJ5|e1JsǠ)IJ %a *;8O% qE0p H" %BCH7O;^d0"0JhI ;AZAߣb6pm==^& R ! X9C/uH(>x)LzNE:pC#B\h<Ω sǿ0\dA(Re DPp8Z4ɧp-|RQWYկ0sx87i=p1E3#tzCҥc2q=\1g|C\#ٻ6G'aᴙu׍C^zfâF $x7~}JtHAv^>"F{ vKA8JPt5(:b @X УǁftvvU!P:XUuP@L;X Z6[@wO)(5qQèBE, w(O9sHV> a2!@Zm#ۗM:5[.jnnfٷ*e?@r >'gƌX%1*g߿v󦷷 IR 1PqKe.R]]}450fК]. R>|c( aѶ0HG?b1Ah]QE!C{1aHhh1(:ؖeYG\z1 J21j澅JE:@hw@ JrIw) IR t!] KDMpKT0*vXThtg1WDGE Uc*5K϶!!t}'`N.&v1dH2ąZ"0Eޗ @_քy"$%ވ %66xJCrtMJ,1e-C0!~5V98*ԣ(St)Г \T%C1Zy( ȗt|V$1x4 B?S!"AF#$#bad. :mr^76@uU,G14wz"M%)D]`<w儉D !6a0Y j7߼K_)CCCM&WdS4D)hl6+ҙ2wuu~o{{lmmG9;Z@iY0H-TM5 'mPv2ܱ˗?٢LC>ָSzega)= ~5_k9@0Su[deR Dy*$Q[i-6q#@+)%~HH̛.R#9*igl>Ș#f4 d.piI\Y$RO!oĭ9R>W֟-<9U5kN o,8KLF8l) #2RG]Gt>XumNo]:1A]8puA=k™KUU3h#V^*#2PJ LVq͔*?)B l#,cGIW@tu؂Ĝ3 #ħeYGn s:v`%S<QJQ.pYAhdh:P_/B۲q\ bf߁n;Y7w./ziB9acx&MDN[&pwpkXG+?f2$%UKٝcNS71we۞}Lq{Aȴ4M2;QvZg߾}3fLT*{tZ755ZA J`X  oD"ڱck׮}󲧧GcDXd`` P*?b==y Ka TaX.‰J FHɁ4: a/_0iIVFxPV, G\ߑ(5u~d4PJ)BkU"P4V4š|ELN ={GQP:2**0Z/D"$ #+8#]158IayɋA9&o*Go:J*082NXXđ]0-z]?4c7P:cE@ s#/ FvD ^/_>߶ssR\.`E;|>>|xP*0ZR[nDC_-J5.Sy+5po|ad?= c船De3oU֑kt~չzdP,,Md;B)KFWHR*SMv dJxLTv͎|#PnB$" !e%,Fz08(׍k@)a gS'9((LIfUyth60ZYE~%?f[&L0 , MIH!\ 9= b d3V>[jq:7` qai t?B68h`W詾!lB*FË(YxyU R|X sQK8&Bz'"d1k{`Mxڻ'Z\_W6 G@08znTZ-JsM1hVk*G1)DDF7T[AJ!EU;c&.z~%O'Rkvލ|~xm5h-:{TXx={*s;mߞJpˠ )z(¶*.V;BEUY(O-" ׊a2+F߻0&GK,ۊ~9M#!IUHFN׊/,+l 77|mӉu Á>.,TF;F9jF#|_K T ]A \HcsfFr Z).d`*Vr3ӉXto\;7)RqFmx%cN_%Ȏ+3WZiQ*}}s' Kx._ƌ7}-{\*p K:;soKV%K SBlJ g=plܹsHjI{Ud{K1SnڴItttѯ+WxY\wu/^| .MggXrkE}qgGs~ s:ΕM3V:+b.xs cp&3ɲJPg嗩=xm 룞30Ƽ\uUMLd29Ee,bCk}]w}SȫWN鼱=5![?\ZCr;ܷ㙃~@#\"7^-Kı*\PI+N^sŏ瞧MGZ՝TwνC1^h V)M:1+Ů`9]GU>z2ZKaxĉ/b bFuuu]{WlH ,=鴳6֭M2YiYH;Z0@kE);5w]7F!/n\ p '?i].XfZb5rgccVQQ3|wowwtY#:Z|} 0ﱕ~;*0fSM5ݮT`z:_؛v.{r&m:usV,Yb.2l:! ,΃+nsmێ•+Ջ~75 >5ٿoXp;gx2Tbջ/߅+Wڥ[n8 ';Ѷ˲s)%eQH#d((ZjcZQ* V*A2anuW;P(,* "H$$UMMMy{^熕 .G6Im0S) @!(s]y|WtqbǃIbD5 DڄvV*X4ߴ;oG.+܎K"581ą /y'sQaYBob&]OpW7ahvPPg~/-ˡ:V\b3<~Rm{oKokoL ..h߀e낧䄺>e C#*~#>aPe^XL,PaJTzxΟ:zbŊS<Ǻט6!5-}*})aJ9/'ϘybgZ97ZKQIǕ H~Oix)wK<pF+]!@؋/t [ǎh-F\"3!a(v7zn_XR!X*|vDZ&UeL4O>ĉ/b044q a2 늭[_evǟB*xw"jY,)eB) B>+iɸ#xof$7,w5bPc>wK~csc̓__ɓf||oׁ\e/T"jv7nbbOo-$sC=לԏ{k9JFW^~7 |ra s=я~xСyrbX,aT*Q((۷)%xx<8^"Wg'jkk'?y͵-[fbMЪK[rBcŒpדbֳU {Jvc$C5 2Y¢޲Q+X`XoXaM r-RBnl}bUuX54ϟvcdxkdOe_SNf?-'a\غN_ 3g M6}sTXCbJFxy/;%ԬDdɒB`MMiD"mۜviFkmKv%nThK! /pi"q(n >wW\muFn?tiEXFV5bYh@HwF F!im6STG.AktxsM%o$qR ۷kڮ[Ž;V+2Ii"7ogNT:aiǑ=*3pψngΖ8Y GȮQfS#69}'N" bUB6*_c"0* aݻG 1FZZxq(0=D"މ'^b XL:CXm\.GMMnnnnR4<<|{z{{?x 7c̙3e磏~+ٳfM!BQEg"86-Mf ?~k?>#/ڗ)q(~\1M)}8VNT!!E+S>;6EP6VR}aMbvʎ_t,3]t~p-㫍{CPln+dйdx*egFzB[6UAqҩ!1yof^.Z G>{3lYsw4&bZtϺġSiO?mٟ>_Wpqwޕ :;/_j _s:˖Q֙ӯj<oeAb(e0ܵzm۷3OY(X}+* ]gOLC`>|/Wx%0ˢ]1}bqMXҝ09sLap0ن{qRP76'FBBiGb  tmIBkCh @+12c 엟 L/LmAx˖-s B8x<zBkk˘XSn &*}SCaKaѽkk[nByf4sXOP;ErrC-<@gsb)9Vk-3FO.8m 1u?'* 8c^^x!j₎ t[xɉtps'{WvDZMq_ųvIж} +W"-t.G!J1v'3wiMMM!Endx<. BP EBa A444N;MgF3miS,>o%4*4ڒBJАf(%l$` j)-Rq3I&H{lmx*?@_r{9P< sVbU™R*D`;p8`_qwET%4^ u'ͷ7 7`|:Ai1vp;0+f$R).}54O<GH]ƬwV=sNbK(W15Z=S(zee .L&C+l4t!A F),2SLyy}W*!nk_"zغ7ʩ6a,5b)*ۼgz>k\e?} NokoήM._kQO)V3nJ 7P:6-S-|޸vb~ͧl:"ƲUQE3ce*Y)F QG/wiio:"Ş/v epP( SDDǎ-jnnzgxKlM0aSSXv@Ǜ3ǒe\{CJUA{n;{$ο@Ѽbũ>K|xʔrf`utDv!ySgͯ[4AO{t+oi9B,U1x!rdDN݇4dRq&K:WXnX,c::.[ NR序̰5YK!ֱ5+3~{w^Ӗ}  jWXRQۓ2 2ŁUsWi(m I9n㐿X@sWz#2FkH+ a(PJ*BHrtuh Ҳjkll猟~rSe ڀ+c\g֜[oؙ?@>,Lzz~ +-Ų+s O`1lnD˒ mbBJlRD!l ²|.Qqrah)^rp]짞RVtHTI+˗oll\&YXUX1GRRAD&RvqH$>G… /~YRsϟ /Lطo#Œ0@[m*j4"K/'\s㍳=̎/~񋅅 ګvv,nSWF;Ԥ[2S:V}(ePAtFϵ{=kijR@ī??ݱxq}.e|5~CXĀHZttܸb kKe7:syX>" RvEHXMNQ7g7q,ZM\8_--I,k,Gd 0 y&L|&n-b1A_=Mg=W>ʅ؋W: ̍ b6C-@PE|[hRlB3|YV D8%m 0ar1#efOɀ_`Ѹ [tl^*Yxw57SX'S|>q񌏧n`%CUM\'nk̓Pݻzq/Wy{b7ozw~'>q]m9VN?`ܳ'}F0"X]x޻Wm<$TP.sqS bY=lݽ6 ż[(i㔢rU9{%2Cnȸ0UMq2(18 J).mXMad\ĉ.@䇇i;~hri4k]0wg'5>hW |>OuUmGvTʰE%ΑZr,xU,;5bSNs kuﮐnQhLRA |(A0ڼؼիWZ#dN9abhx 7xÃD \-LKB}jG֜)mŃ^2" ɖG[K>/;'Tgg7s>ߎa͚w.<Ѿ|Frq,/׍76~Q65=!&>X*,mSttm?s1'}>S ɢb}jX7Xʉokuް.dYC'/$oq_w ѹ+%k3V5J do|h`GO;{j~;!]Gk|?x0.ݬya5Gf?fsKOt+ rFe0XFW{ncS`X\i3WbhŲ0ɘلOLMDCHc@c@c@]<Z9ofCאM_bd\ -sDI [%ftR O|ctUd츍 J$|P8K&e[rf(}5=$'|ޑkqܕLÁzX9j9)!!Y5h!L߷hi#a) lN,asM@Y 0+YɯT7yL ҉ +N9LyzmgͷM]k~ٶÅ'Lq I~K_Ϋ:n!sK qSHtޥ!ofypFJP -80-fqXHl4=&4؊%ld@ZFwM9) IZ@[IQ~ywќNqJ!=R1V,yU+Ay@>=֮ k6qsfC-m2dgk%Tҙ5A aa9C+1AwҊmXC6` ()%ˆ%gCspn445O"s.qpNV>G|cʌ8V*!n{3>:;;ҥKiҤBYm2Y˱mdDVvBLtl~vLrj?nöCZTN$bk*h3qfy_ Pw}P.-c@ BMMW8MQTqhZ577]- l4v(~pŷiЫ|FӅ/ƶb=tCmv,tl?\Mvdi:l/ɗāMޝ4鱱#8ݫV,Yb7{mottkcZSm14z߶ljm.0Y}5iL W\6{0{ߟWծ!V9kV2 ۶Mms+d:@3n:k/*BFN~Hjq Ux, aioo_{櫛~v>!m؉gӹw.2S_]G %/s`3'e,aע-wHqy[\{o\ k$RqAZ~!mn[49B7P 44 -H;**I`r;lϢ'Px:*vXY㧱dIW?aDPvV*UoclQumB~1tY_\f|)t:{>ڊ7C3c] L/4:錂D8cBtS5׳sOY}4.Rm2}iE[u߱&N:}*A1djm{tzwwAIz~IᷬgT忼c_S Deˎnqtjv27,Qnê wUTHd-t&Pah1 )˯QȖT *C qFB+mI`WFB*18B@HƄmf!1bL9(>[LU&=U"$_sG/,qwPǮgNĝ4j6ڒbYhY V"fF33z˻Ekas_оI֍wO3E|yZK Ă}:/=v)t c\[^"DŽh#-^ hR(2d 4S%R:Ѐ?6{#+}yڙ[Ci_h?J}v829mk4~;I#OA A&7O~qY-c &t߂ 9N}qQa¸TI1[kPͦ$dInm5ϧXC}OX&٪Hc!✘A!_n9}HKs c#?r'VϼYyE}nk}86#&KJ;ฉ:i2Y)W>~ aϯȝ'OiS&c-=??VWϾΜ=wb'CHImT;L '~gZ۾t|:Y /my8yX$5?Wg^{\&X̶9BpR".~8}b97KMj'VQ02"IU+:;ws_+c@&uإo# H 2Pㅑ~ϡC>TH͈z^]J40uR `DX9r p?{*L ]\D%Fz}ngG>݂;՛K!oSj |Ze a] hi먌RpE)>s\ڱ LBxcNYtme lsЈw=e1.ewWjIز) ;/Cai"6za4Rh0΂ǟԸQ,Oa49cC7ar-BemXj40cWS?g>l#?5ZZW3!o>>nK1Q)o5f~ԿZ8!5 _L4#ƮKh4ǭ3?!Sk#S a)s2fJ B/R =]H%9˨mhdӺٴ?l̜E}<sʹvZlF8{j]2Vk+.jÏ?~/L-DCTW eAL]]=r.رwwu4d?i kOYpک\x!mGĚa8aH._C_( <ӟ4Xd٩1⇿ZL XL*k``h=8ZKNH"`[Rwɹiqp5/œs-Xd!YJ2L96(j%#G^1 ?e֐Wd`}]|ZQ7MX g?ku2Q4+Wl=؛%K$*ir|y}L'q#cB_+c^L{Ù~sdj/_vv_͟+.2"L*eeN;/3N[9qU9U}f*As~\9tL:eSN__͟߸ _,;̈́w^An$'7jr%.`Xv%Fj<h@TdOO/ge3I974}wcJϷ֝E>>oM5GwͷTSZl=x[+͞*DQ,{!09A`)c`U4X;Zr uqBp0!qG3\he@k,hh,HBc UehENM5^`.K Q1rCJŊN% b]#ڿq_=rpKC1w%?c '6o ~99җTlf͇=s}kQPoɆ|$ě) # ]N<*Q.t2܌0YѢ +qWb"sa+EO77BJutt臟2;Lb!HYn?gV?mӯ$ҕ[- O9ڥ74Ŏ%()K^4#,p>$6ƕKva_IU1-EB<#DwiE*6=đFTT_2XZѯcdR/&j| w&jhPΗ](cqx#E!c-X_xLEM*qԹu@CW6IdZh2v(,Y$;Xٳ{VU` TG8>GqG(tIR[XDH@o{mAJg"Xȳo6|# `-{m3ph?nfжq}"hm)ݳKV?u/ gFl0ahF.8\U¡CwZ5. ÞB뮻ƋNu%WN ъ=9cLs֌3w0v1il+G} L77nqǝ~/xb۱?ٹ qWC.8{~7l7a<Å<#@N)`0_{idi.@zq"dw1#:mCҍ{^\n;Axw:#l.y,+61rբEoGdkU:8iS=;bLi&ڞR普Cj])2uwT2\4̌UedǾWOkװ4\w[7&E_cJ׵sUR e=^>87#њ$^,U Xb$oR&so~,cl̗'A9b]D) -:@sy]`➿2i4[x{Gp5F1 b|!PÿW3'|FGMvv3P,3FZÿTs҉Ro#XLp̐BOb /1㞶V8$9):ts #*\atTO&EO%+C(#tLp)3{8]'#jj8"1SCmС2( w0}]wԛ+')$%Τ*R &/]d"EldB,s|8\'~BC3{bj!˟.%odYQ S.yB!3M)LTXwj!_nծՔ}6=L!Q T`!&/mjtJ iko_i_LK-P!r&mB0DQۀ]BFIG`JR-wDPCJl.xW1-z$m5yzs9Rnb]!M>]^Dz$#74`ɧb P>qKmS8qzњ i;sOw_YMkc"2 Lgǵ/:Օrܘ +ܰVTkF(Jk0s<܅(ɞ;8yLlڴ̞:WDǷe7yǵ{AM[ RoOyΏ_[oUϾ^$&_,g\pٙ3fy®񏭤JaѣwhXv\G 7.= a$THtHmZ# T tOfc1])VCC‚+Iǥ(cZ籾WYI"H^㬩/[N~Od f5G1L)ъ,9M!W|kE,+l5,'OV|5/Mg]Ƅ6cc[ΕŇl1xZ`2W-C@0,7ؖ$YrɆPiFRР 7xP+B;:9==`[:j· ʓf7&?J!S#chQ~d^8Lώl(u&!Z^%VL|h!Hi3R&_C Xp!H ʜ hvG&NԖl6hWg a62XBъ׽@_abn9gEUm{6̮W6!`7y*XT2ͧT,Dk@Xeb+]4;DC(Inؐ/% 'Ssw(lX^q;vk'u֤Dְtj&N3g_'Zk!eCpZkRTܥ4m)dUWRҲ̮{fgՃ:\v6B+}=@uR̛ueߣT:::骴0ZiclB\{{o(&tXWܳg^rK_׶ 羰dͺu-[f:::?qrzzKҍ cO:]g2s#ZP}嘛<׫Б~2'cuPe:]3رmo#K٫frpeg/f\z p}9'w$1@Qr Rړ"BRW~%#fo`q4`!q/Hoؿ<*xT{Vt?E5Lpz'RD(#6-H( %OKDC\ t="Hp:@yp0ʤJM ueH'E6Xq*K`[4TTcB& HAj qK0\dT V,-E片99SkS4u"jr] J$Z by9_JFT"Ԛ^ݞ}.Wo&Ǒ\c/UWKGDXD ]?H-FV |g~8m_*!BR@̶0^D]dI-2Jq ?_x!$ML:0׽@QA /`B`mK,8s16g(u1Ɛ,KxB'*0,Ͳeb~`9 i0~ ƥ &JQc)$ uph H9 ޫ9aVR=2_"6` GtaWv !5k{kjJpm9?LnhCQ6;/墍!SUC8_zpsƗ~)VHS]-nZهBҢ;-,* $^kZ u7̦i,N6hlSmiH[0RXR#c.ׂ ec MZ(Ү8Vt+tuU[i+M>$._ X6RAY6r~) {X!*,'NCgס;jAJ7lpr EC=f5$QHJj<36b+Ҩ Zлݶ`OBVfı`QU>E<(/<t9XAɠ,C 1s@ 06Pk mN|TOB e m*j?!" 10qTb4"r~%(سpO&}p?w4Gnxmף&8Ẍ4R q(J<0{Tx K±-Iƻ\U(}R0+jRBW4" .*<0{io]䕥KNWs9RZy8VT 撳NÖҳNñHr)OM2c07dV^ZJ~o`d<΅gg竌SL ױ, K JK1kYeJw!zJBEyZaCng߹Θ,3q^GfY'xMG$ !C)G)M̀;T #˄$7*ێc#q I%( [ #o,VI@ kZn<<\ۻ#fZ&{ŷm[E:t:{9B>c6k@M௽L촻8"&222,C4AGgZs ; ->{5 6/']ັJI!Na:!6MBb00xB#ezw˓z6lBM=(MV057Mp^^̝EmW70 q,!!YdqD"4`6w׉ `FYF xUnFż<4nܸƌ{_{vr&gT1VENܤbjPCx.6YWP0ɰHw?`ejڦ;gI6dyц`bִdjR~t<OGT?6 !ؐ%itm, -_S` 4%1BRh, -c㫅 Lc2J׻K,}En 12 zdk"n ;ΡyL' c-0م,#ZV:bȝB%:lt%fZ9(N }`1֊w dvPܸx hҾ4Q!}s><hcB.jSJ/[8<#֖CJ:`^b,p=Zk!|xP֘r ipu.*d1:F! f H!(KxFQ(%Ѳ*T(cڷx{3g21T.Zb fr;jvxfp.<BQ39p` k[.Cae7&1b0dlAx?T m $0}D*b,VKS:GJ#1 ܗ" u|CųV!Q!9fE.5iJpeXWh%JrXe6b{3R,Ov < .fIB'ے4'$u֐*{gmAE{ C̹;w馦&bœc6~B֕"6? tPyF 0FLB-5H'FJBTSYJ0 0$, q-\p8E8xT DJB 2Lۉ`B&NQH?Lu* #_beL~FK,(cEgxؚB=ʏr0F#h9dZ,Y]5$)(}ZCɈ5K1p;m#@iMS@K≄H@fy7T{EIoTQ4TDS:0*r tEp-B%[Kmi^ c ||u62fm a/wo.\,b6T /?qӏuLu5\%hI$+ $56188H5A%,}>upS57 ϊ ׵) a0sNCrdƄ9QTFe^d O;AO32B/\_&lX*D*y.b1AeG5RքBJ C0Ērڈ0 B7#9Zy/E {RBkCO<}{Љ'2wlIC?tHA266(v-LE=`s5Y6')!&X9P$^Atv6Ir^\邏>Ūի3q:?QRl!K 1iďB\bƌZȿACwttEO\z+_{߿?3#]jݸ bA[B!2'TAmm\R?B|}JuGʹ7\]u7j`7~:c| b.F+­?Wg^4MJ]_Fuq3_ `Yh#އx# %LɏX m-a͝B A\=F(S1~afhh5t5(#BW V& 6AA8eo>Vŕ1FiR͛7z҄q֌3Ė %BHKHNm [ {5Q!1ĄMX|ܳWoݲ%<>@QW`((Cp#,@ī-4$Bly?ٜBt+!2#7d#=Dm&6|/yE{aa1LaꠇDu6pŸ)(0 94?LUf7F[V5_)D ejjrH ߴiS&JbwH7N&"6xxMSPm'`yTDRrH],F&b8O4{|sH*a֢<dz! XčfMKO`9pSPQ5Xb8W2b7|j򢥶( eme?qL51"" eDzXZ_7ɋ-*bߛ<ɱPdjkT!_A~p$UJ͂y."ĐB;CbS*EªaɂRS'sP7Bƍ"msfKWҵhD9b ޽|wS:;QN QvpJRyeMP.d(), R!akMya mЎ0<30BcJ8jiP>~2/006>BgLrY;J QUuSg*٬EcJT*F62 +UĪcYMB0Ԩ"N8:1AlȋΎ0q|b R2w {h}Uh!=(XL*m+Rj 1Te m-(/Čn? Veɥ !FHFW5?wG\MDRP&֚ 䠎p^FɐXk\IBd>tC ~MuҬϥ{sZ|> UU9iQtff[.sʗNXԒU8w(b\j eKu U*R)©oh"ǥ1ђd2J2Vzf'w8Dh cd>~0ӧރ~f;MI9gsٳh̏~/vwÙg(Djd2J2fdhp Lԡa*n6w=j2#٩2_yv&aWWWAms&jzB|>y۶{f%'!Z֍Z:Yٶ-RLR83dֺRV󛚚{#c[JR()-E::@Xű 06[Jl۸%\UMNsŚ5=A!Tj۷U"~p(uI9[dn. }T*eR&T5b@82S҄)%"Z'rJ8ql6KӇL(29OX!X%"P\1(Ʈy%ѥa%t,D`5B>~g8)7T18 R# Cb,e* R Fg8馛n=l1~4V,w*l.P;DM,Ig=E+aoªdHG Ԃ%Ne|301.QȄi38g2R2vdnߊmI  uB 8LrjJPcR )"!t :+6ZydQFz_i(28ƲmA R*0H2RR|KXc4&R4J۶DCRC:-,a!ɱZDQ1H[%;BI $!%R$f;д%hc4UN41US:)!,t磕=jsr 7ߚ9NϦooN\%ZЅc չx7?Iǻq<Ƿ]yhZڈ0Ti)3%W0zKh8&&I2oZ0" V>1c0"Kt1iok3a>xQ`4Fcc8@ME`! ~fg5EBa<|< bH457rl}d|ˢDL)#* Q5qy>X 7ajYg^{mjX"2"͝'M:u{ysv^?*5 '_`Ur%)O'?ɶS*ZV}?UVjA`_,KfYJmKt:mOӞs3gj*MtRsq1ۦyBeH)E&&c*RiRNj_M~W[6C&͒f}$mBC|@__/b\.OK&L(@Tx2hRT}CÌnC@TH+0iWN>2T<ẮH<8RnT&K 5IY&k[KxA8r4AzHDa!#L>EXք"i0*Ptc)!P ܀hHE15 bMhm( ۴a=B{Ƙ7xQ C :lݝxzGmc Q^ge-C=6# H!+F#d.cax; ZS` ÚS ؆|i~\rI8CBq C0b!׊E\;1Z(jWBraKiTJ 8Ba('Dt)ČLOv7&鐕1$* 3N<+Ze),I II8ؖEP[}O^0,[)1gcjUAI&Rjej\O=e09pS'vlJ X`IDATu])$QVqaP" oK%|,I1ɒ!cB }(k:ɘ̚0gm]u-u6w\ 0w5oƾ_MyojW̝{_I.۴a!^HwX,n{baG_/KL-4{5<1X.X``6aNZFjU|@Zl"ux!Zi*Hpl8? *R(%ꃠHBI¶! FHJ¡C{[aPJa,'E1\!RHH>eyuO>^ <2:\6ZEosNX:Շ/W)b"T&c'{(H˂(pR :WkYV8`D#kG7fe- y#Ë=(ˢ20@~>#rIߑJddzr}2Ƙ>1Z}Г5TYPt +ueN)R:tHj>F^o +bWAE`V*$yׇE!m6FRY7EJpZFνX,R},C*C 'PTƲ,Ց9ko lۮj#u‹ ]]]7L#c<_& X)5UGbɒ%GZ*馛vcԻ~_?'C.\LP˗/WK.~_3H3ufcLeY{XՄþo::$yp;@v~׍Ni}N:9XrM[cRd @t*Rb\7= qruFAK. FMza]sۖW KZu) ]Τj1W}{uK>rk&657.rF6HcFQ7o[ouqq̡C6~8Wz|5m_Wh3~km?mQIݼ+/=_|k ڤZXӖm:35\ RJ+ض>0##Œ̓F?3/cC_{@bWE3s2ʓ3E !([mXYad$:S fyq ::D?{-7dy<y߼~ՔAEu2B5!kQc J8x9jΖ/A-:K.gAnjm=Xu`g]Iψ:s߿qژ/]!AP$Jjđ5:BLuBnjj?nܸs~ᗝK萢S#*aUE:cYɸOx͌snt22D?5m'.10rerhk:-٩O|%׮Xa-\|ddym]~Gf]SYc捓L10?ƝK6}}'44{}0$dc 2Խ9cOcXrڲe:u7}\n }%KW#ln!7tSfǎORx[3æ(\n ec?`w[}GgG{d'B<Vyp<'|h.&b־oCð8o!Xy~xݾ9jf؍Dύ1o'#$)K9T$cufbCG[a-L,* &R/Bw`RwF@tv5?#s'nӀX`x% G'gV)ϕBLl457e<&d=B{ bqV cPn'N o1Ge]yz]y@'a}tM]_Ex?ߕ\| m[:}.뿿`sSi"64yŨgwᵳ7}[k_䯿uo9՗9;99& |(!Eb|Zd u%!AZJ c" 0s̜rL. -Z$/^|R(cr)W!u:-ĉ}W4+[{YDϣd]5wya|l\)ph^lY4cw/Q;';?;ҥK>Նo|Ѩ#s'![/_._-Ž3zPɫ`׾h1yr3Xn@ϫ2Tp@3Lϫn[vtX:;1D,Yd2k^wuxG?ѷtvv~\7?UqV/7Mҁ?lzi4v 8cG^ZhhVp-f n_8p&k24Zk%=7f}G; O3Q2JSXP[8k;?&|P,|7b*Pvnk7l`V\<ܡoR%9[ akڱQ&-)ڽC/dpp'"ͱŠ&g"c'c"|i%<h56{BeK„;|ޚiB/#FiS?-?ǯOk^0{z)W {,J7qai9oL޼ SV)2{9Nj?ɜOcOS F!\!͉1sF@peH,Scvng.ó\R g<{=[~+6ܗ]wݕf?5k)is,}lGQE25c}53 []+ޓO9|:W #.[*o.bĿw?XdG[VB9Ic~{[>^oj:拉F˦ gj2symK.yi(zɒ%3z?jp_׫ mn0eO_vvJ/W\ɢE^v# !GSwL0a`͚5 s/-w_E#k?'tڏys7}q?Vk3F2|Jp_&i;WEu\*fW=vEw*we)Lwb&gSkXWËVfB|۔]Gwy*t`PϾXwB~F7ϢmX-1vꋬȹv H6^8#ƖAHRe|M{cM։p{_?ͫ 3<ˮyƍT5-_D 1:ZT 4XrrRL\ꔛo]|zkJP&HCSNMm6cǎVzIs\fRBQD62 T'c\6Y󕟝< '@&#-?4qȵ~hOz,}$}0|Z+sO{jpvo6uo>o;ܴ2L\~u!叻7hNuEo[=Tx/Qٚ9Fͮ[[ܜaOU0BpXs Y3'~NAvڧCsT*/wc]zCk׮I.?7~ }Ϟå2fJ7]}Y`!c%_y##.=Sj:K跎f\0Uxgĉ0{UV?|7f@sH˳=Xe.p3gc=-p)TyӼ04Nܿە>Q#rl0B)Qhl{>7vAƱNl䵏o`hQiE Ѣ{@ʁ-'| vN{@\'72%k)MvGfk.MS!?&Ns+{$C}30}&PGŅnx0,_pE \-!)!@/28`tJEdXq",7_p_5:j~Xh‹ti[u\Zi1J4{P@9$4I' (KXCOs[3,~dhnNҔwn:p>}u/H٤Eh'jߝlKb;*֞PHlZ;Gl!I)k1k f׵18<%sR.|3n\>l ڰn )H3 R+WѺx\'.G(>{65/nfFKL<\?vږ+y'sB!^7n18X5Y9HrUzgEp]Xtq vGY3d}g$w%!/Ϳyw>ol+Qlj]=I=$WN4GYEcôg._`Bx@y?ʕ5ff8X64sDR8-͈7o@xUWY'LКѬ˭d9Q\{{^jծ,Q2?jd W4e!h}#tt7%]]zS/.+r"v-Q 75 + &X=#7-j44qk4pѫ"~5I{d{{y a3h,CCCm{iϙgɄ y1~t)Ѷ΃'n1"U@YܸMKj:y晶[[[! rࠧRIu/+N 8H˥d6. `ܹkn+tXq9X><'J,;oQZZ[z魼?-tZO#g}Qާ8DZo?j^1ر@KSK.}z܄ Bh۶)J7ZȦD >0ubhib !LiIc^aDXB)7V۔5vܶ(8jHrv꠱P1FLKaR7"jzAj7]s[3HK>]smF9čxL0~'C2$)]o؜L> 6&F#׶<4Cr>>uMkZ"Z[ȥj!X0ʥ`i+% Rh݀LK4mbDPWO.oIQ |҇?qld\0 qYSYX(˪˱#oim(XzApaU=VMM(ڤ,%l)\Y7#:0 !d0.\H%Lf c,)PJ:80m(r9Cy YhJ6pl1UDV`aOTgMK|iνM ݱh\ zr6lXfFšs7H|f\xETd805vߒi~ ~ՋG/]߯.u5*{{ vUVO%6I=UH~ze|p^ࡱ3( <ݻ'yPiO}ecH4_$K1>z"s8MdY N>[7گ&:O6t7N QP,D}N]z}'n#4>^؁\Չֱ?R2}'BK"!tv}ʓ?.'^Qg2gӸ8di*5k7k*Ԕ05ڑT) iPeM@YqӲI_%">{I2L={6ozӛ &Z:!-Q<SdFv¼}(HT9 !8jeՊ0`ѢE&Ư|HȂ<,WIڶ=$~jCb[n\PH84<+h$e!?yw?s&s>8vq2eIayg&6{s@ i&f~MPvRjS{h-HɍgmOD."ʨAI57-nv~Ly_BFLl2=X fB ȡg(>}%_Me_+Ut7)`Pä0o TF( P ;vB4 6 +xZt qc%H)-])XMGJ6 uHHƄ6 !6XОќ?*f9ȢuM& JE,hE& <3AB1wbFj_ZX*vH:5`[yC'y~tGۻ-o o?1־0sc{(t6^rUHױ#Q~zi|~gqS\{o:Y!4ZPP/?RH U0II9I%;wx /grۥuBgk96A ˒bUcEe(KDpn/`pX++[/ӑh躯$+VHu.^uv&ᰥK_f\ XLyK_Wjtk.>/Ѿ/sOl|ciK> .x9Yoj9p[3S.a2VzW $fH:d^ Vm'q,rʎy)Wj駌.gW f΂_ "V,\ĪUVE={͉Q꭭SpJ׮0V}G[_xԨҷ^0iӋWGmFc +Qbl'8m:Zdc!QfI :w'٤rj/:-'@&U q|9-z/sX+Σ;h#J\ԶuœM&Q6PDqcT xZwȳza~K.$ UkkRLK6duBE}Uf˗/WkkO9%<_',R݀rdݘS7K<[?&:6fKcs0HǏ-YAFs&ŁAY HPv@&GbKl&b琦}s')rL)ق(\ Qw H$7 JU@ĕ}fٞ* 9voTV #,×^w n恧_7?GѱQO=o/>*xdQ N!#a?x:W֙u+?&y)85,5»"7<56&vs+eȎjjZQw߻|H)$R !@=;UrYǬ[emtݓ}(ڎFA\}2۵Q\s}J/ن\R%cx7,|ڷ=BНUizw ܷ칳^vp5`V.W_4?~o<[?\q`ٲ+( fߙ_1Wl8bU^1R~v3={1ղe yOdWj(0(.]y=N?Vam4^e}SLz5}4-S/o|R,|j?/3ɬ9~ 뛭ūVEߛ>0|aX016f&o3#jy h/}X\$RoCu8y7-^x#Uϯ=)'5":WE*zQwѾh hB!"N HDG i qm?pem| ~Aϧ(GWC[۸6=hpbLrǛx$\˻G5.9Kӧ[Zka{Lc>(zl2& 9sil}8IP.$ㅑF+=ҹidZ %L_d&hT[VJUքwt|{|SZL{JǑ9=j%ن~ I[XϢd¤$Mbxoo8H thH B0I[?q!,[zR4Zw!GV =>QmR=_?qg&W?ANe LA !G6iGȬz.uƻoђ8\g0K?&BMKy I cyRddKYj""=ZI晚,e`)k:F8UȔB:$oӄPE`4'נm6<T"!mA1 :B !b87J<`a5*1"(r)Ծ8 ̈́([ ZY{` NApf3<\膊!Y*9{s;,`SAq!ͅ3J8Osjcg'+H"oYFZ0kQx1uCӱpuzw5>^q@Q9WIM4TH'F/d9 y tc1{rΞ'oGFϿYMX7CvsF8Ѕ1"TάЖ"P.6v #ЧOCZGGXHt\CǒSuւD& i"%P4蠳~e+:qEs{xylM<=ZF H[Ɨ~+D+2(:&+)lJ(yGˍ>r1N-4MZH8B y T Hd,E>mq]w LՄ(j˲Q>|G#8w?P 1.!Ӿwoa 3zaE5 鄪\ENj Ø!h^;BCIpʑdIƈl /"6iG"dL% qf.~Wj!OCޡ6(5>|sMUud)y`4۶)%Gg*H'w"v!ke ŕbCT[?kJAE8D d!@"^j$Kddrj5qu;kzݰ5c;Zh9I0ܵOC'E* `{D08RhH\ϝ6SSr&l@f8Ȗ!8Ź||{&XIeԑ7w0;pMcq 5D8V2){fӌwv2fyn40iuBԖv 4ؕ;~ O}OWrV 4Vɳ4bQ/{pMFgqdtLֻ=Ol5B/ {Qй Q3oƠN]>^٣?~}um'L0u ZRL=iZ RT>ۻ R]K}҄k5L%}c5RX&u3mЄ[y5ckg<Mfa~ԩY3g7,mn6U3J (XQuJmPGX {GqqϿ㌅?0y?} o5ſ ,@зϋ= |;:}0jz|3͘gVz_6K6_z|k\}5碟~Uf͚=MX;=G]t[Q37 /Io45FAah% X/-! !|yfֿ!2YpnHiE~6>4r=$˾9J%&CEzQdSL98%Wǣ9"Ni<?xe'Bmod8BojJ(RB9MXRJuuM#mcL FS%  5r8ʦ>WYלcd46-}]PEZN>t z Mɹ8@D#L^<Ǭ@JېԁɯO+Ʒ'i]"(VLS$ 8f,X}Ƕ XqpUI-({2]w=_35lKJ #MKA͝p9 Bʶ7nt#74~ 3õZ9Vhi)=v~sc-{f|K$eMj@{ a[Jэw0i)o>7` ̚˩w }~/v69u-]*vu_gchCzȩHBiZL<4Dcya„}aB\3@ͳ/hteXLs댉=)BʿiѦ( W6m@"~V;>t;Ჟ.0D,Nef_>8 v^,'Mw?ƌ&U$J׫Ue,uڮR>3%f_d)36D\!OII!3bEJ=|mt!kqˀ`% |VXRak BvD׈X&&C~p G /eȋaF/P+53lg~ƃ}58TM6i2YlfS8װسQ튗eƋ2^N:‹6GXKԳf%dDv$Tg^wc koob1jd2b|`%f}сv'+W mc;y`eteT{a1dC< ,6t2o9Gi|hMk| b 5E vpBHm b|? a6I'UD~ -8~>oS #}$6RH~Qp$qC妈L:oWc0Ԥ]AYcg _FnX֯>cGX v4B g[eCj^?pDg@zE M3FA?GZRʺD*jĀ11%^I9FiT2T<$)lrFr=V=ٞ1,W89A&#p"e)|it:{غOSx{"@9J3D<YO' j0 _;‹\TCC.GE5#@y-)biLɎy}kAGj~/誇eX곗[ϿΞGq2ԏSRvaxbZ`=';N[m|6}ܹμaq{UWzDv=!~ v6 #hš! R۹v|ذ MۨYzV"uQ5PBb.R(+2*Hٯ _qDfj*`jNeȻX %T.PoFKv%c`ȡRVd}'_9?*eo}_[ʕy<>swy}vuo0whk7i,j8Xpa4Ua`x~7/eᷘ7@2da_UyD1o ?˒h__s/cd_ot@ vRA8žblwShO! &Bӳe"6 ZE^oOGE:2Ҽ,#B!F\G4a]E[QLrD3͹DJc+Mw)!Z(J"L` S"N%Eo5,_!W_\P4l>Rhþ f{4*$ a0fcE`=j0S6[IbJmv5[#1G" O0CjY :SRs.S'N) !kT1nzA|\vl<)geYRI^l86QY4dN]>R楦X\/q4X%mV q+Y: !Z#'QaLՖ1L(cm c [|tX|9Np%&XQtWw7ДUP<#úK&TדMʾZAf@B@U?aX.Ɣ |[0eI1XMVHG N[W:5Fy<{(doBZ:|`P|5t]( gLmLO>Wn=RͦMıcVB.? ̧Nhh۴.=_ZԏK5Dیg<`Y! p_hϾ(Z[Xb*2e0>z /|97q ߱uz;-&1ApƯg8?-imu4G619 ҸIM+M[~رaES'N`ϡC jO?aߺ3{ݕrݱvQ|h;=#T? zQNi Hܸ6G\`WѻַE(UйJ7Q_;,l?(6#YJKb4m e`p2y^ 7Je1B[ouɉ'xQ;{%6 YJ~MM `%-%^l) Nm}󕎂C@sg)x OpDcH4lԓ>͙"3T~FERJLxh9hbza3 iPB 7(zMU*mtd:u['rշ!` ? }ѷ651q>U)]}nͷ\* R2)&BXJ @HX{wE)e}UCB-PdK Ē5qڷ ML63LT<5"5w!"G IBQneckoHcKj3X|A4&N{WFkEuȬmHt]`KcXP5O_|;608؋Lj6+%Z dm#EjK?r RFLHiRx4oh+:gsF=OUM.b_}@ZYIޖ$#eCvߛE1"<Ķ "8tc T"UNBjnc99>y63H{d|b4:4neʕҴS^i4“#gTltȺى[U[)!I5vs=pŦb"*rXiC:UdObP$) }C=_WjĤwlcG:ᔅonH_GWpu{î=ۢo#"qRnSim1ӮzK>?ӔB~-ϟ얅=#/7u2A% 55Gwm}@ěw>n}*}{߱_ONg9ᚋv26L"@V}2c9HG!)g*Ζ55PB_gI|??8~)U@ Os{q ع{竎rBUъ([<ۘxTCXG1 d%BIukBP&gk:qAT$2ŤGzZ|[REE'DN(L<۟dP!}_!GQ_ F#Kl1#5f̘v]j$:zTiRl[h׽8n~e kVμ8Ķ8r #}?<6Pk<a׍/-N5!}^B,<6&Fzݔ4xƧ8mB3O1<2k;jlh8T* ylRpR|\rmum4zycP(7>r E.~HTDBǘ8b{( GXֽJ^#"Чĸ!2{`^xl،yU,!0BS*DqgzrgET#Mk(#2Ya1 T@P"lT+u++&K1b^q; I@ =A9# }Eւ#vKhf?M̄fګͣ iNXRQCrل.Q:4VvIy`_ Vt8 ы6[o~ 笫~sθ)9&zYgqwJi h7=Ki^,O9,|O=`/"  D N=/d/jխOeoIs;gwMbT{ Y(^JPc!3 EhyGq (14)@'1TxTAxKyGfٿJVIMI,rR/Oͦ "cYi ~r|ٟ3]3N?ҝK"DYaJK`ĉǙWV HeE˲ >|u1hs$r_~M34B cBmDN-66 8jWt.3Nx]z=םͦ=k @)AF z+}<8C1d,hp h]$6FB!zlV =Gʩ x^+x5GCA6n`ne3ٌKC&(S2Әk!nc)a>7ŢI?Ƭl̼mc BìL̍mfO@CN0!O"nت! qUbj(alkir(jRUR bHU`(L } )8;n}9s9VE~3r<9gWⶁ@?%:;Gx NW3̷:i1lBkᖵ^[Fv=XGlOsHp3XV3RH<n0& }?1mbx9^O2+jw )ɘ%s[]Z.ߒQ6}SWoO0P\?ߛS5V"W-s olSY3ⲭ̶ZFώw T+2wA]5xVg'xJ=B4>p2?f[&h?fF6?Cc-EΒ* M]M~/2a3Xգ?Oq KXe޽ og>~Wgؾ`\0;  2Aߋ,aKG>rket5FpPዘJwсdc 6 `><蝰Ltt=Ж̜6R)D}QĔѣhl, г]u_uU]͝Z'iw5(v f3zLcD9°Ⱥ,5I0U$eҀ0tbzL\T,ٚӔ%!O }f22'ph. ˗'.Zn}iYgTB:8R2?Fu[%UTewmgJ,_X*KԮS׵>PT̝ݬ߼UDDәD!IYؼud3t:u߽6\dz&͝f2 1< ^PLa/"$%v|, vt{ L4u4ʵ/t?2ͪOl,q!K#CPq2P'oG!ÊH3RAF]EYM#F9"badq I,H/?=aҵ[!P2TϣiQfuZHhA MJ m Ilj!/ԃ%7w"T[eP0Y\acܚP`8vBACxKT754|hKq/1݊+3鄛:3<-1 H3zk`c,{6O`q4Ej'%&#DUq )d}B<:6jϻ;&^Q\dϿ 1B0T-di8./,PyxAڸ{=ox skUeߧuocpC۩V{)3cE(3?ZE>L#ogׁO&!F_ײ/W{nyC/\=#&2JƜpeA/OmpvqKbBVP0Zɇ.4Y([^)zӊtW {-mg4;[bbUR7+i>˳w%{ W?ʤf%Wr3((x'US/2gs337>K?Md@V SfWT$rGsgۦ I`wa}Kc'~+Դ>8|%ÒHՒ@9# R) 1vN @Hiʞw*RZmz{Ǚ])W",ͣH漋 4n{w4rҹoie݃`g|S #os9\x2Tu)_RN_ھ}Ǐ\՜>ƌm䛵9NF EZ>☔Q/>QA=X={Z1FlZ/YDo=&Om]엻wfAaǡVNS&NҎ[͇G:!{~)ЄJuRV(\5>v)/I1E?Š=(ar%vBo4zDҖ9<ݏ nF+С"$;؋  NrQLJrASXaazpc#ye|7}jq7G#&6Jem7ԑGj$3BwF,%2>1N-"Ti#mܬlq= (0F`(i16]mҐOd*|Ƙbb`!1 J~Ro¼Fs8p@>0LeW`) Ch z != ! -z3` l0twٖlui){3#ݤɽ߻͜suҚNl矿frČdb# Ez\@)nҙnlh2zSlՙN2B~ix>Շ#\Dž*Ěcg#,C XJ^ 3Is)-W7q?'t fߺ=rw?a3rLYQ~;3\ANDMV2]&~\,ᤙǥM uSs 3KH^HX+٦ڞF,IcXŜSB0MFYѧp2) ?HŇi*ưR*Qb0V`,>\Mm#z<=zw|ȅ1|8V ^BvB& χp +44Vj3|*r-X N"=n Fw 1_555ɺF?NGN?ea&voq]5a#׿MMqRԻ1'ͪ]Hu_$|ݵ$\e7f ig;E : y2Ftvi.p%u\v]Ŷv$, 9@l?k xVeU*_=YfV0)\3-0 tfہQl M҆D- tv_':˹ouOoknrVJ8}cC~u`BD @NEseCWF2MFe ~Q/Pz>?o:m@RG\Ë&nh>u\F=ȓN;w-epm?6}Qѵ Tμ ՛VB$$8@Ek@7oNBpaZ="ɵ4RZR)ng7w` bʯHQpH]S\4,L{1a`@Y((#*ék] %1K%aJ8Tm}lufg( *=cck@&KOD*{YGh y6ӒHObiB s_zU>. GCȤ"gewt9ŖmaGnfK _NFze'lb$=]Guɝ*_l+ t]D"iTTT|RlW<7>h*odgpjg(W(/S0aqMfRag!o%NX7q)$K%#2ҁd qN 8 =p3Π[r?PۯSbm I&,TKP b\QRRY#ðo@QܬA321`[!ixuJآH%VL[7:XmzX hp0t*;?4 oCã/{@޷9*V@} uOp{Ӵ|>ҧk~=W1eYG[ʏ2R>}ɪUs+ (gԘWn]dG@A5Mk{aq^ "u'Rrn{Z`v<2m*QW.e@,m~-b1XțZe !6%^MyKi~i^&-_MAр>;0tWO݉n"u XacY#~'(BqaeL&r-&,7O\`V|ݺudwtΌC x B7@#F@._~… ={v>0M;'S7_&DYw4{qO;p.66 G)tqUI$7 +G޻l P!oY7;1tf0w_c}Ĭ`ԕ\v>_erq@Ak{g%{zt]z!v"Dl{b:)ɔUIE$v7y_< XQ$h;O3}( )$# 0p;;o]v< u=F/H΂J ;kעX $rcOOb^ei{/jH:7>}i [JK z;-v| )W6t~guzmw7ӣ/@GM_cZO6َd-TT0mu$:|˯I%n{ະe"UYQvBIQq|3 r?1f F0R[;==е]ɕ. pa;Jryw&بgo~󛕮NPJ3sW(Zӟtk3;IW}YP>Bĥl^53EN)=0( Mhb11a*-oX;HYW744Psi}s9d2 @uuusGhjjRc/Ν{Rj"3 &u `aq]kjbzssIKBƼy"M+R*vK3<M34MH);:yx?,c@Cⴳ*  qLr|ޑ аL ㏿@J°e-+S~4EɄoliaLYghכ~Vp ǵNnU7d[?555w͵ hF(駿,0+ƿsg޺Ƶ捏z֟S xO٩P[[s)HZ01E I_ -31uz2j!cKvYx}\#cftd陚0/Mn]x<@,āD|vܽ_ݿ$QUNYsqQq[j&)# !®~ =V~468wE";JOD7pw,HGkfjhh o!֕8*Hk6z "AY]Y `xSK ߉يKBeP熠RBĐ''yyœ-578o&\W! ]ohȻhi"4թ}ԾTu.%LMnMtvgۀi&@򞺺:yæ:/hŽK}z-/)ՏqU%浚n\Tˬ{ òkN9LƑsi csztυYЇֿr"I_n}ʶQkg?MEL: iEx{k̆+ :Կr'mR쏗`T[=^4d+$MhһY:w~qʯRCbbow?'!^-,.M߱~_O9֢V_q#fmo_y啿y޼y+9eɾ4\޼"i<?]g]xYհl馧7]/{{_pK9X=d&BJIW/vKex~ *3ݚNJ wfG|)=㏞.{iQAfä>x1}]fDET/2rf>|wZT ,&dsCRyO~ = wv1D P4;^V2Mt`K %-,,<5JhT= 9fqV~ݑ'>h[oMl*u͞X?l 4^_ ,}%{eD! ! aց+mt?}Tow.oTayey@Vw,ș2"!i{&a"LDĿo ϋD"sB0K5MDzjʱT6YkMDԏй2^`gn #tfvSU 1a&Z QUZUU`2"J|zvI:Q7LꚚx>.Aɭ&cy`6 i/!4H RT|eTEM7|˭uuuZZ7"̬+˰E(2NXwRƆЁ(5!:It#ųS%wO.^ |>{l>-[}HDT-W|{T2cXHǸ@zsZzq#7\g=d(˕?X24As @,E/`TDD`H t)V^v Ұ߯)tlP ! %o.+!՞`)T8z(d&+:dfwqyγi誣7~)1QHwp]94t]&պZ LF:m;֕ܧ:sR?v߷sRޞͷ욚zkF\y1]noiQ_i]Wm{uڙ ?7Nmu 8ZA]^TTtLWw N g-U|c#~R>xBH9S|QXpNgoe^xO=nO&5!r)R@b0׏$hBR ѰߍKGS} .4="acͱ}tCZHdMXB>#_6:r:вcb1ϟTTT1ZDGOںXp\O:>0Q^^qÿ5?O_vWWb _?2 }Dy4MR`falR1ҙ,-k0e4e۶p ` o|sdOkq}+¾ Hy @@ .^Ǘhi?QwWKW`@ eM  ˅bFЄ \H4 EVY]ND<.f^wơ+Կ+0hvu=~7ED^E :)51+瞅G?_k߀g=ЄbVg?]73.po)ryc,f=4ng'3&Yl葂bպb䞎[-Qukm?ٷD4gdq܏d67_zk]s$!k[Q@@K c]аo…UVV<5?Mf'|D^yP]{ށ\W߿4cK:ٚLcYrbe'~7;zL$xL!93 GQ/\w$Ԛu]^!Zg>HD ǧ3YWwj퐪Pq\unh$G[4}FkkQt)Qkcl@Jmӵ3I붪?bs)m Dh;V{8qℱ0G-Fr~S&L]çLpN:z?]+HLbA< $H lRpP*`۶@6i8?0|h]hÊ Z09orn_Jǁ:7o+I3  zsΜaQ>O H!49 v>B;P9c8W"RUU0CZ,v.̇ahP(((^rJ Ki`Ҡ4F׺z{sl+mB.J! 4 M%%R7(4)@8E,BO2s=rO)|R[q /XrX)cC[qzeC>e#U$d8 -U+qy4մWBE`B.4qL)k #8'-W-z跲‘e/|>ߧD4*J+)ϕHKB@Yg?㨀_(H)+4mlԯD]y ,2ituY{sWP{O(++M|릮Si M=bjMM^__ϻJ+'( @Bm)AZiYEZA AY755 gީ ȷ}`\v:bFE)I2$M v)KWJ,d%f8YE" ?}{FS >vp섟W F@Hp&\;J @شbޚEh6)d=ƞ0c+7 CR 6>eu`!:iO#45A2&\p.48B}P C[XјLNa ^ a!ÌOz |]3R·. ie<pYA{,_7ek)D. .kP(Ti)dE%\X4?4 ̂sQaM!)sc&` ^4B @6Āw+D PJzIjlH:؜!VZ{я0uIh=\?iؘHce%1H[Mȴmzf5tl*2qb|c^ҶbXJ^ڔ,; DA{}}!_tR UrUZ)J)a`bW[>]@'SG/1:, cB3H`IaԓmT 26|'$'00\=xɕ--?lA>a)[.˼ݨ0g0G+..>0?7CۯoVlȑ}q;ceuMhv9G̐+ ^%#G!a=ܲ2覩"Bҭ~|*8_GIhXפ/ A#%VzH_e3mwhhirmQSҒ%`lzI i0eTv[ GPȝ:;;Tu0=+ 3!Hv40QWU~1qB!hñ~E6ĺA &-iAbkw/S{m%YzlrN~/MlDȤx| ,,a!-ń9jh[eE׭s>CgΜ9 aH('?'v=B@:\wg\A1@(flue>ˆ4PaXfٰ0l#A8RR6`H'axp Pymp[55+ÈvKD*=b$쉓wp"k9<-+E²Rˇ "\% s"3"I$$ 0u9 Fïy\_#P>)=|/S~"}g@#hOc_E;NָX-@4먞~2lܵZ!eFie4.ph_oDpˎtah> Jiu2+k");9;)` RA!N:j e"1Yt iW7 %:% x# bUn\gл|…:[oDٟ+o2,͜6ڶɅKPZTv tZ~pO<1#G _yوD¤ B&kcU=pMmn nr8 .|13(U4QpKX`T 4t 汷R$vY!v W~r#/<yCW;ܻ]GLӥF*1 -IIl%ܽQ`{FcꫯFEeUY ߝ@hNsHqQG-9c;&$y9T1RpV#ed% RQ3fԥrlc7Umښ~./hF_Xpl@'y蚷CVy x s1- ْf֔WMRyT^]f@ y+_͏3@seO5Na!rȻ hȿmwokTו"!3n<VVB| R@"Cmp+@DP@J ,La#OY*00(,l(rI MHY.RH:.\˅#D備a  dȳZ.\ͅ]A"`CH L40߄oBSj'K0."㪡A{wctJ H|+VWwޭ?O_=/IZe璠FE~G Da@ F %!J30>Q2X&L7 `dydvgzm{A @QA mR 0XM7cpzv_>_2S A&!R)B@6 `VWCgF'(ި/tLp49+݀RUYfSc!c&!7o^WSPR4~k9,.3cJt::$ۂ`60M躱]^aK(?b1ABsX[3gN[%"JRʳꀡcbn7^]Y,i6\<k]E99s0q;|mh.~T^~EiwۯE!ci2P o2dKK!ƌ%'1]76~{`ʂc0 >fHK .낥ZPW 쭯Z;_gEi96lʊ-ǭж-F!(^J%k:|omlk52hjjzJC;vղrg@`>ӄi "h6D?W1vl$irxx5:;1sAXT5{T7Z*Pa뷘U8}e5| -۸Q9&ZI2%4}nȱ K:qIA CۆoHH)!]Lڅ p57"yI/@:ӲvZׯZuZú-%o)ִnF_" t-P_:qkg|իm~㍯oYp^[[+̙cX `vĜCDA4]!')p]Y˂eYH@ Ç{0:8iƔ:O<]!zy1zxX 4c.JC %0'=qG/q2} Mٌ#z,s"Bcѱc&a#v\GK%(yYW tmnTͦEҶ>իT ,%|m{fۼi E~h$,03B: w{w@ yɃjJvr 0l0J rgpi14DP.0@qA  iGna8rL!hO=JJ\€b(fu I$م2@Vg *ta MMMW^Qu` Ʈ<y㺐 jlḻXuJaZkџ! f? QEI FYdž/`ɒWTT2L[|RZJ1cTu{XkO?}*E-E |lj#sP=+Da44!5 nY)!^X8,xaSF<` DYnr % d`eGDObO=T`G{`WE͔ K{ Hg=f_:o>mI=?~Ň-7McvTCjNsG$@rԴfi<ilWsTPc>*^DvQ:FV;5U= fIDm? />}Zo"z8( y3y:X* "PZ}R?+&nw5d(Ǵ wܹ֟U7_vΙ>[?{s󸆙y^_U5f\V\:t݀auR u6ʊ 8H9Y .+??o9,zci2t14}v"˘Zzk7z@w,4 I - (+1"e%>t7yGY;]|P{`!|a, !O3d+)hJ u`ڞؚ(둒O1+݇ 6+5HL]R 9R W"OA# ,8T6|? `x% /ahPX~gywG6 \7Æ6zkaJ rv^E:FY]ߏ:<epFlji8NOUUӟi?61 R eiT"Ja U(^cxQ גЬe1OpM˷Wo;X`m4+ ^0(9> $hP"&L9IyW! ȸ ӢLhlm8.aBaRpLi/RQ_R6vdC R.<05@cJ|OyyL-/1-2h~" c# :r][.Əl>ql1>|_ Hh ޽jܸ„LYRg8`x@XVpX*X)HMSэƄn1;Pm{Y#֬2uAFAМ=HD^C9U// 8jzg+"5#nM[ii#f|at&C t#OnK:oc~?P2%mda10ca S<9LSb-Bj03Jjjjkgٚ^S]iܚp_}k;GC&`h#BB0pS~|Wz^2u'-8FrX+WH3h ٛI;ycH@i \Gޤ9v캺y\Ag78o;_>jq++UZ(= R1TBf~ǿwƾ9a'FY?wbH(!Ff3#!0.CǴy@g-L[!d+" ]WW7oʔ)#/=R.T ,ڵ2jC ~bsЁDLpr!}/MS.DCADG73 rMDBS.6mΝ-mhƷGL1#KBJI&#+=ST-#w]«q?\`Dh=!]wg!i DY =@aS\/h ÞS4'`[aWTUUj۶df}" ?YGG}$>q#/9[ѓ 1T.^8Nyn@]bdK"pn!r#ؒWCN3ɂ2 05Cl+Ax U2y!t~ݦ sii-8* 8>v( !>( e2]V"1* GCM4a6&F`mO;,Jr)362}y`D|/8xAklHpwC 1tyEإ/!RijPGCJypB#\<0G{;MP~`/c~z֣KjԿcDqqIA4=6h0`:5LÀ ˜r 5 cDk[;V]+Oܯ^~ޫG[x H [zuV`#LİlǶ9KkGfV׃?\0⨲aB4}DIYGyD%!L0|v\T)LчD0emv)Yqȑ־7{v\~݁3߀ Sb{{~;?Cpq &(IQF EDhEEBRJoL{kKCӷc8@@4' U9ib𥧿GjxljH~E\yUE#@2S{C: ]73uCňWLpY/B{Vjjj,8_nu;P%-7kE#I4; ۜHC=UqoE!H S膪L?+W+@vH%AbȤ26R RI/eN2-Qk$Du<;+!5o͔+!*hׅ[R+= 64PpP=y 5Ec}xV\thvm ȟ'RJ|>RK؅w(!B@JDSAIAT $`e {N[A-ӡDv8g7, D X `2IdBBݻ?w^̸pN m3H\>, fylad[[q=GI vq1<P~; har*^NbdX(E!?0q,;z6 G<>fX>$@3?ԩ"`;rd2>US QRT3dw!kXiG7|=}k;kcWŅ74!m@r x.rɅ-4#UujvmT@Ua 3-a|>[)~ J7,>i>HD})$R#-{·.Hu8[΀ y"8bGM ضAYI:AsPr5HF$$WTCuuwMHgqR\RX~=BƄA)Daq*K3 k[m|LLynlh^p\e#4PU:0zRRseS!K"bj*e-<KPrIkv@h t4i5m*]0 (͆q¬n f9y QQLڀfMZ,tE d G87v᫵#J [  (l4iۣ )%?\ÚJò,~h?Qv _ ]-v\躆5!u,xAw'syn(k\%؄RJf_ ڼ__=d?\X0pB}ѢE-ZTPd׵ F@0r?Ji%Cdooot̘1 zzz׭[77 aq躉'^ׯN0tq\)et :;;WX17ؚd2sB>|.@ :*Ɍ5ڐr^(4!3f÷,J'쓕Bˊ $!{֜G~]RLVOeWŸ;J^Vm9/\,Uy_-3JNj^Ӟd[6OuW]LmvGY1L%>-xRJL;bκJI.;fg,1 R)hJȊ ;` Dx`M=VR)MS,-" NQU*f +DKäN*! HzjX cGA;BӬ~"({{ q@3tbq9b4~L 1\"Q}x8F{\C*1bzl:[ZmCwxÏ<-+/4elO5$)ՑȑQQP>z@G3"%[ֻwbbX4Ɍ-tWE~"~6%I(Dˏ8bLD$@IiRӨ ęt:;::ҙ M;"ix3YC~3}ܣƌ7_ vo\}!$ҺGDe?h/Ӛ.N9pRtВ4>؅ (GX*=G5+r̸dKd74[z+=c\m}XS>5MSV#j._mٸy ʫt"s]W%(˲`[:ۄ4M )/mo+;Ee{NY rK [+k&LF)텯aP1Yl%bat HgRxxo#QR>rK+:(4 aMdYtZyc߷EߘFү8jb>A儱 /ǖo~d!~] ɚY:!leж`*)2ɤDI&PLͺm,RjtblKٶұK|C]&edv@uO XE,+VS5yzWV/z@-b.75555:?X?2TJfņo3Qh-oT.ZSS755o.n7tS`رn붵}fC=ԞBPW\YM78qi4Ms>b]]"g=t^IƆvd3cp0 @i 9D0{jH$rL|t)"7oA%j hL%B3 a%RQ̺ڵm$CL jg)\PaJOwh?s?-H:},͋P}1SN& vȵ }=xM<:>vӸ:#ѓz4?a9,=Z84v^Tsl>mK[q^rͤmRY)W_ oP35bv| К zܬ "ׇ>R3m޼[cFʵyc;tzfh!xpXKn݃kۚ]iêsk[*5Pj#’2mkhmU=1Mio0MZD?ZT,&sc2==+6>FO^ylߢ%=.G2#iֵ3q&@רjm?q?ݺU8[`W[z]q́SpχcYxV*/%𨉓襧 = 'mF477i(T"ADyn d6GrII!߇PWW'c@!:K;kk1}뚆40}:L;PHXG#&L_ݱ@! :۷:K@P҂ )fj_ɎD3gy!~g)=yk !LDb)8 WA)Led{\r@Mh! GhtVEEkf _Zs#voٖ͇9O;r; @ ʶ-7tTVSxV(EzQ"'lT{ o/<Ïdje27W_Meto[4I)ݧOЄK(횠/emHX. 4m$;E4;AeX9 OORvаNA/-aIњu#:@-jl/zxֶuR1ywRJa%*))9{::pΜsc:b<>'> f|sm묭ͽ[7W{B= "T|ӂb(օUswd̢>/HD**ʂX̚9so;J)=Ic_ݳP|V3rB>!ܛ>D]a"!J0|:0ua%gB)B_̩@}DtN xdlUOKS7Gs4uV, MZ?^ V:-v/V4&'jG#QѺn; H$@%~loXhPpa@2E!`@,%m@-- JݷY0&vlѰ2Eu b; >R N24SƁWQwkg߹K.Ŧh[!Z.[i?(.?w`YgK-^wS8MV+1oO~ɫ|7~3лOCUOtZK*8Aé-_PĘwz3́77l/<~t^ bc:Z7 Ea:=8߯Yaގ{,xIWHߧE Y ,=Ly`*YUúJbWܭYq"c9xG~ Ə^R''hPm_GD-U7{[E JE(\:`JGe\kɪu¨{@˫W@ O޳=aU{nΪF9EQ]]V\\|B:ȊhA CtHjooG&a7_Xڨ(-Ƣ7s;+]Džн?Ν,%jhiiы.K !¢<6m>bv H:UUU ^%RoxĈ[ƌc[ٸqc7{3fpx&M=XrO/YfpLIA_1g7J! BO j[/ B?st@oJ*[X9=@'$f kRܼ}LX>WN9尞έoCG-}Q )!O+.+^~gwvIO \p]Ps.=unS6:B|Ao sǘ ˤn{뺫~mɟ67yGMV6+6޸'VSǛ%rwh[6K/h~vnm?_Ӆe{{jw…C_:;SEAqɲ}fbȟ&~߱m޼n͏,ZC!5GVVp%0H)%7ll-hjj8w|~˲ K/tɐk|evBPh~*-t?m_)|>dُub1mԩ\__/sHs.K .;;;H͗\pPG*:H\A~L^TwhCjmjkw-A.ZѼA~F:NMhZ[Ӱ*o^#_yQ^>|XAͷ47.1ꯏj!0*v9Ɂ?|=MCC5440 'lzwX,& ~-jPr~~{߫H$|[w vc%o(C߿ NszEN=hR |kkNqD'^ڕ;OLtM޲82sŢ=p |J5)?? u˧0Bԩk`xXL!Lj(]|jZ\!4?vj cC+/5|Wv!Υ!ŷH fu@Y߫ݾ lKJԟ{]'qL$e>yFkWk!{TS3G[^S}2מqFI(q]vE!↜EMMMqf>`uWWCaY NzwyeÆ-9AaȾD|7kQ ͏Mls)ǎ;__1L&iٲe'9`7=㌒L~ƞ2eVVV{/u{p'!/bo0e9W$Ϝ"jX.4+|Sv,Z$м$uu; ݿԤ?5y |쑮jy#X/y{faM>}~qCׯ$.L>MZazeN,W _2 aDGuA`DS93)" .x8B{_ ]ٞGOP,'G~*Y66GI 4en)s[{R{}j7AqR{S X ߅v1QrѬV-\0 €ӳGN>?ݫG / ?R"Sss#hsUU)>` u L>4 tɋ;KŶ\^l0Dk|a'|x ʼykg=_'FNnȨ'ZAxG$Zn(}'9{A鿵f~=WCM)((U&YC9k;8T< Q͡FRLlHZ.Iv^$iG'YP_ߝDܹsC ,H#0%d0}`0iD'}F.4ٲ.r-ر;S?3}z`HE&IXԯĪwV'>ZXS͋67iN455Iq%͛43ݘp oUgfk F|g: 9 hV+Lj ƺ:I556|AlyPIinjoTQXc4N~!ǡΞ}|2o?m/uj=/,^"߬a!1RIݏ1!nze ?-1a䦖tL- 03 {?# Wva'}g'M>˖-kf'uuuѣG_eJL*z]K׾A@Ī;U=t\&DMs '}'D ﲵ!3g tSƌ;`΄c69MH3AߨZkp; 0vrly.*L) ({]!E55f-9zurY*wx~7e=F'CK y{g#9TSl:H%tOݽp\WOe/sSRkp+^i8uPn8"4;vz_ ӾA,&'5 E9JCyS @UD)L]Nޤ`!D)ʧR)TD˱5ف#s_IЅKZY!ٯ&h Oxo@FtKW  ᕦ$Iʋ_fؕ`K%U6 NwҨkT/kpl׺owBN5d$tCe^ѽBhp%z0?'$8?s >(/;`~TmB ԺK?~>W(E&q_8z4:AM°%4"Q:iuuܗ|CaHӔe3)OZG 8\9_ye~k߿_w~`_$af8{>|գ'Qs ֡,_ l&v;ҩtee!7Xn_[2Um.=_$6m0pK2z 8v? !?=mlJځY7ٓ3Pm^:T5? y!߹~HAO"- ̓rÏpCێ}$) lMࢃn>5s}_޸mۿy揞}O:03~~3ESIەRS^}+.))ꫯv+$ ̦&{o; RJf]OYk^6V"T@teMdwE`0 ZH 4H8r!a@RR;֭^QcO]XL֊ETu BF`ᱚ1jVɁhѮ&ʴӺĴq _P$4>,t,{Fi%z;̀HMU\\+y=!8|tā^X` $H\q)o}|>vaŊ 8Iu N*ǶۆÌa4}J?/[~jժ',Wd&X*'p4 ##!F߁|`RG;ebf3%%QC GX:& $"`p¸Xm]GM$7J*Kf12|Q3SâY5uT6,MiH>i[|b,^u򾢺ƩMH+% Hvta{CQÏ>]?A AuQ+ҕ}_&,+wc4C.1>ʕ @ܮ p22`VЉ028lo蝕K p3Rv. 2%B\)v^;h( OG}_.{ ?X53;dD:5K>C?ŧȐ.}7\={A47pW[eICE+?}Gc1S}xaiqoe@ceW֟NXSL!"8#~CĨnkd 'JtQ_f7/5z]LqȚQ}u%,-ʭ@}&Yzt[^Z/2X,&@KT2e9544`ѢE&uiӱU~xży+tĠآFD.vMD`N4YY9'? ̩H="애cr3ܞ,zҏ#W+g|8xe{F0Ig\aoY59ry0c>կ~kn))!!]5JA0d l<;`FGtD'$K7i*,ͷ/~J)剖k4)ŹcC F ktBvϗ4o[vnXJՋB>,p%F ^JDG1ͯt6a6t@VeGƎ+zw3>^ \s `oT``3sPRCix (/a3s ݸ0P9~^ys|}aKOݱ[2X\z=7q)֭X:7^֙ǯxc"N޻6;1kl2,-Z" ſc$a"0AÔ)&?: zn^ _9|?uknVa%{<.ݠԲ΍IX-Z><^P[[Ԅ:PPC١.{b g7#*齒: h^{6b/rr\EQ^ H&$!3qNb@~9{֬#&by#oi&}{vpy0qFUƘ'446fЀ 칯9EF1wR'l,Ơ(Jc;tQz,)}W&RMo6wV_tRK_*+XjR,6_G%ݰV_HBsUc .>/ki#> 0>si 3}zӀ=pJۅ-ĩ1<4;_^_Cne!Z5[|MpJ ן3!D~CFu _}mcyݤ|Fǰ}01 \ c3F+Ƀޝ5qQg&J)?3X'[yH)b3b38G>~{ϝfUN'upe8r&Y,'sjAynCq9CyI(TdQ01J "˅08C2G] * 8a@$GȠP43Z6@/Oq Xbd$\ y1v/2a16q3].׫ ;TR %8Hk{R ` Ł[P 2z>{q=4)at,JAh*`1E A0b aWUƪi=XOQBP(~+8T:鄨BH 9I5Pv2y|ܛgakbpyYV9:*kˎ]b.,\nQpWD:Fqލ4),J/:#nhA2jvz]+j ~5`EF:!5:tBHJEP2VT⇌ @04< @ c +*db!B}{^/l(Æ#K B # S|qmt%Z%Qfhv m~w)DgN l!wv%3 (*B!:XQq;HbxHQ/?q&WO<ʚ/6*/(^~fӭߔwG>CfxJ3NCTZљټkPM]ݽc@KFD,YY%h !zA{cD )%ۖ/~G96  !S}d|0X2b0X$Ys2!% vXWF妋TՊAIH $6&cdDDJUJ6E.]MH7kk@v:d{q^w0XXuHJI3w4q܄F5FG0F`r)7"*&zI'掸v8t~~1ʅ)Ifm Ø9N8QӤ$Y^^9E.1厥'1iIq h0mKvj1r2FĐ  0ioVd" wl!|GHļ!CLTbh `񉰜|&DJ]4`q8znqU0!$fR_UxZ0Jw J[e{ò60J@C(hJ{ C 19 l BJ0CٟʘȸSqYnFPt % ԬdX%ŮP+~jϔx!rH )ʐÔgΣ郞 M>qTP =w6) fۮ%/B;/mN?(]{arݒd*עWZ嶴ga`k TUqgͪMNٹs>i$aZ)4҈udeU2Tˮ!~X*!s0TgBaȒRIQA &M5S[cY .(bHN#S`8{j&^EIAB8Y, AՐoG0h5c~X- BFԀß3 _3yn'Be͗hA36M3ᬓat` $,yQ:F[n#!?+I)9!买fvop0K}qE\M7^wHy>>ϼrd,%Ay9e2Զ2K2N#RjKt>]YXxxx0yU}|8>{z#xm{ˎڣصU/e`([g7v܈ꔌ줶3XCӃ8LD2Z"5 G6Q9УCg@$3+t%)&k֬}BؤI*tI2Er1hlhۧKj-Y kYqCOYC}3Ҩ4k Y3dM05=\ ;ć;%ںkh|o/l4'I RX_8灕蝞Om[a.ˊ!K@,:-oO(*V ʘb|}# pANavD5t!kS'ʬ?PpyUM+7 )XUEqvSj˥$-8Qvk<+mW|yD=]VVV9Ju)(ROZ5>aB)c*!#T!“PFȀn;܇V  !@ .(P# ")琽=7@@(@H_)SXuBiH`RR(`O#uf 3(eض/_}lXMa/ZN0J@(  ó밣J cUm:DLp6yQ2ĂQq H)))w?LᓁeJJ}0aW {p%%%cW<ICŚCh%ڍ@.@O+Ɉ4* 6 ( \'?4aoQ;iؼNeH|ǞYwvyCt:RY{TԃKtN7dOhp H=f0 H0zLys>,Æ C$ zGtA= З^TC=[ńP@j(g.Umrd(,aRYB~fȈ%)è??12D&(6m7y%{=h̻˄snj"QJwo Ĕ=t+뜚ݛOIA~yM-!mC}g0:9`Q1P"J$h:o@bk~^@`n׬\݋u*$U!}B0K 1ӏ=ʝˋiŷNt2~KWE vLJ W3vjIxh4UEFQe啨GN'@?-k}&.q34 m`{݁x^hš0C $pNj#^؄ND*dجV~X|\{^C+)DRCOpplfq s ;"ZO>86.&Ajxyhx)ٱfO`DJ ֹu\Uh-85g OX:u6-`G^ })75tǃ-3BpWNsL~W~s90O.\TJJJ H%( Kj`F-}M֯ [ajP ufU"0FЀ`\܈ tihh$:.*<0[/ NUU |Ha" h÷+ .X!0 Ih; oր!]2AΈٸZ NtfEK`w\H9' cG_{uƪMvҲ4~ ǫ]ǝƾs\. ^^pGhmm_!aW,eY@^?G9 {FCx4PO^%f]j?m5eo?}7j6IThڱ@ ,e*: XQli`I qBM&PTa)'`o4"$B$~ BV{k7TBfF2U6t- k_M".1SrdS/}͍yA+t})!ȓK tVȓ_VejNH]wyކ Uaʸ(}+"5Laq: mK*ƞ4Yk& oj4 9%`BR!yȰ,S]./((F/ uRQӜN +GRVVbB< $&("$RB2 \v&n޶[1f̦#1I yTg URsJi(/((z澺@qk+)+.f;qh*[ n@Y;k2Hʠ1 ]p!U_yA֗(`#\TemM¡oPB?׏1|!֋1.} LKfttt`ĈQho;xf|+FGGcubm0: *_# >;{hT"GQbՏ𡣰`*0 PP@pH.HBpF#@vX8u@RXPrqnnJUUU[[:bY1n"H8$4]< ߈Nlv{ [[ s{4$#- kORpTe6B: )9 4)$(k; Lku $%މ7,q QQՔVR6À(6MfU@U=1-DB pr 勯9ccƎ;ɪ Ŵэ[>h6{CouB,Oꈏٶi囷>Q޻x䄸4˵tj󇿋FBiɒRrnbc2{Z?X{GT+//UnfhQ< 6ajToc* zH"9(TÜ*oNPR(wV&sw+O+U%u~.Xtִx!}`}Y) 3 Y"(FO77{膛7)cDV fo3Spر Y18L!?TNNf{{$Q`B/V.(?AԬdLG1ż谟‰l njgE'+M xuAT?e5v`SuLp `ѣ1eT47ѽ=r_"ȶ׻Jg̼gvrjS>enS4cWa_XxZWZn|cs4n$ 3tCz<op6**BgGqn.+.fUX(-.9vpb`BQNBp}|/ ,#*tP T8 ! ;1(q(}:::jڑv n,q74 =^'^8$&9f(Ͽ' & 2@12.BaY!P/yY#pX7WxLkX "c*\rƅa'C@@u" 8ù_ !7?> Q}$<凜ƨj BCrE+/ H$edBA( B:[$ D촬d79111t["%\c_4  a0B Ac?<`EU@C;'!V*6481' HHg=N^xԔZ*Su|߽w2IsڌQϺ);>3dm'kk{:NZ}276v?owvJ)ٳT骀CB IҘЍw lOwvv RJRRR?%NIKJH5rb&mkG&\Bٹ'$#vl2(RI( %$$RoAcv'bxJ,'m=Di/&%5Z0V~0x Xtid@~}0ttqbZ2@!sP/1,#ЀP)]bL ҇SPeQݚP HkLSp7=,һb^wd5{t:mL8jji]QfgbϞ=a|>fΜQ]=LIDAT ~Ր,a f٭Vq?6 OǙ9kݝM'||؅ Gly|B.8QgHjNMD+#1ՊDLhzICzgzX\ejQ/~^fj51jpw "2!bȹA>ޫ2#l'N./CJ|<~+AAWP@KBјF8"8e%'psw\(Ft= 9&j 0jL Vb][,\'| 2Sy&v${/ެD? !C݌5HIhjWe5[ O %e! 08Gp? XXaA& fE`' gɍlpHXOB?F`Wq-..ݴiYQCB!Ј8X6HВnwiQfZ\\ܚ_^ۮ(R%˂ sa3D/Kl`SoUqWBXRAVYVY__o3LqFq7--lkK/P.b?WSPĄ Ț5kKTջ5)wbjoIҢ qGkeqe]ErgC`kQ螉q*)~ֽ9xSHtJQ H#tCEԈ\N\xb<ʊaAWT Vob-"#`ER—: !z:sM:!ɖ H C\H]7 -9| fH60'څ̲|{8ϥ5Bu$ܭ+:jwW@$5HBHp)dYs{ 9Ǭ8T&HBtrjv0#*WI3f<4V3 ,lSfCmm-,x0X,D۱"*~;!GPBq\D7ކlC1`]M$@B"'/ۏ -`6[!`Aki}@O,K錐)diiRZSkDZ^^IMI看!2h g/tU7Ca`\H42x4JgpyywMbUQT6 0  ,[V<e+ٹw 9UJdM )EHB2ùҤ/ (n0YY T aEE餕(z|ܨ C"\SA|@-yKM~&=)i=ϛ![-fTy| "d|VrQ\LDsu ĕ'}Zuacj~d]S›{uZ&HIWICa&XWᶐCi51č'(+}۞ʱh1i!#9ZW;X?OQ(D?Xǻ/ z{uyy!NP 0@h8 ߇@Pg X7<\FP ,|#H RBz 7mv g̚ή.dO+.|4 F! 21xcODQQzzz0|pFb2Ũ1˿YRJfW/5CxS3jKBjS$ # WuB挷!f_UDII3-n˘4ںǚڿΖZ[I`! >27*:R>_I Є' ú 2>PІf{yYWz/>qF-OH?fpNI\ۙXm-_d"*R7)6x<\S NY8E6$%jx˂MA#l=hK!].Go1-ՍӪ7LD5Cf$r;QצϿ+ P\r K/d2ADLĔR~̞=n6;cӲd\WX7_ Aݭ/8O>{[B֠lC?Ruhhj gJhv8 >/I;mIwdH F $(^ADPx$$Tow1+מ euz O^sB95iZrK/twvv g5ٳz}m0( )$X!a~xm>S0d5sRSwNze}_H3^Z!zk51.LuHZ}dd]=[{B<^I[&^KwpO~w2FZxͻ,QIu?aP%¯75?M4O17c|$:JpLA/LlkJɶ^:8'(ߍOU(}Q٤>tHGA! Tb @1)*)2oV46;/ ^R{.-DA'{7lZqlRK[nORr3:c$f֮f،49zTJ魯%GhvPSGq,?#Pju8HgG߰qijnrۇ\CFc[P'2X6~1g~8،JIm^C) fm.ӱlYxWUOw+oWdcڸvoL@  ~1$=Mp@HZP<Tm-* /Ț; Y,룮L$@X0 + DDHth^6/l=R~YLL=KHnnU5^QVtM;u]b2N ݁@mnaK87`Rq H+vu-;wym?&5ŦsF:9>H)aީAmePaEPvAfI)MXHa!@ =uIuK `'z˗tS=n! Bxݜ|UWf'|ҚIxBH"~u!8d˝{ͬbbWž);F hR{AoLY])ޠ圯כNl2 I4Gz 4:K'NQ !}wܒ@vn?@HI5TpȐn8==}i}}m'ҒQ_=>Vo[?]_qF("n7BU&L8wȗW|ekm _r{ʭgN;|[aP+W\@Τގu+_)ZZ]?cǽdff_ДXy;Y{(ޛrr~vFBHcbִO6lo[4%H/H*-դB@k~bģ3V#+AnPiHRWD;%ϭMx|KO} ? T %9NJ^xa伳۲vQѡlK D5l{D̠B(Wn! '-]g5DCue~Eݼ@,M7-& I#?1-b 9ɺ0sk)ph3ᮀ ǚ=rg@"??blPUu]6 ۷o|lܸZQp\u&) W0"c{k#/ {Yr$)ʆ%axQH!ij4`Mdvf:`r۫a=;lrG^$dX+R 7@dIB$$1om)( |ܯwu -,ÉYN 鈍AӴ!B:;;wjB r~So[) ;x^04@B&5Mv{¼I߭ ` C5nQI" t2\j1TJ.}T`p%55w:hVv FB`KG8o@a!\ ,Ļ=3b':Gku;Vv'jCi£>y/P5#2u1qey p܃Aԥ"0Md;MDAUt'M8ViOtT#ZizƮ>Q1h39ԺBJx&dLTnJ΂s &?Iy DȐ DȀPY^^_|CME11W̺/_ ڮi$-GDG|qqqqkG[\\] ,?N KŒӣ im{q6I[y/d8H{DjZ?̺2d1y<&|Sӣ"A`|8Z~eO`ֆM+r36?~ 6D 64d@1=oI\}tj,m9~[!4wI%%%wdھijnat(:æMCnlOsBs|32\'WRr#09L($ ]]tѓ}O iSX ـK1n8x<455AӴ}LĄL&477`ܸqظqqu|P-L{\ 'ISY2 MOQUhAC""+= 10uf-FI"",Zr9j3X> ZArz.>q Ht2eeSɇ8(0L`&1(% (B U\zoHHF@ :}U?`J Hd 2,oys̽nㄢvv;"$0_Iz9 0$x H#(x9uuu#N>>RA)řg9񌯬|- LJ xg M__I ҇ HB@5ف}*xn1TkY=۪ po z655Ǿk_2@; !駟3{Ǘ_~{ĉD3@Eaa'^xqB2aJ?|V\\P(ibammms9Cᇣ4_NDkoL,t# w=(d >l6|M@+HACȺ_N< 0hZdٳ}oB^" #fê1܌ W.>۶fɶpSҘOfKXDk`6T?F}8D薡_Qkc|>da'[V^oM^^'[l҉z{{7曇_7N3100xRRү?+,?/fe&*pBw.iRcb^F>P;_}մQݻw60[cbb;;;#}>enL Y#C b" /&xFĽ`@S  PlYIAmo [ D$g&^{{=a{~ៈ`/xC(5 =? 80 _k_#F!_=si9@# p'-K"p.ep6oyV3~ɍ6q5^~;"u:?CͯHG.rN''y[Ha仪|b p.wۓu(.c}D$@* AY~/+cE*..NlhhC yZ8qtUѬYrPR!?XvOHOv>o .aK#/|_^^NX{AM,d rge _AQ^R,OII@7.1ۊ\9OA}8aH=B#$V-|&.&1Z"J)Ji_wݽOg-:H%(*z:%[Gb _/A4r94E: _ݷN#&3R}FII*JKY_dۃ)p3AHAa5n ak2X,¨1~oqj@qUVΚ~Iy]RZ:ܞK.^NϿĴ|0Sޫ/9>9.vaևذ 8>TcS)[n2qɧG}jji{}.}0S.]BibRsԔ斖FٵoYHJ\RJ+t\;rhqq1"E"u1Ts/<2RRNo?CRrGǣ[@CQD%` HU @ޜw?8fRBs !RpiYeğL"}0BXlRS3`LAOgn=sY^Ѯ7eL(0 iԐa7_^R#/1AӔm2)TƑCs{Rq%udtRJ%ء">:Q?מdܢ(*a6BrjЈ/>FGwX3lXdL81uG?_J_`yT.\F=inIo-u {ѢE)}٫`\@$&U=8=idtǸ}ҍL2{C !Ld$6#E|s~D3IE[ :qp2k

a>]y0x{5&^$ :>LB2s\Sh9 o߸@c{'OP"^a*/_hR٘h(*!Uq4meABZ)..yy[HUU,C`O?,BǁPuPemhھrm テ1{ ^}y\Y˯9(7VW_}qƥZ plV}?SL ikՆ_|qƥsZqx@)WsJKK^tNyrFyd5ɢ0E B\.OŚ<~ |Ӣbbg@5e.JucLv[giĬ;˄F5l]-_(nYf2햅}Nǩu뎐a7BAI)HI r*t?`6GJY7C˥PP>g_7. Ã*#B,Q_kǶ{:;wE T)T 6,ٜiƧM&!TST׻{ S_E>GLZxUjFV6{f1/e Zs[ׯ[bLԐ~ER|ejFf mt,/U{%Ux(cO #INk =C!iU9t)zO#vK/u5戚Q]u-vO<`i7O?8;1;ۙۓ*̆(Bp +_k7=@)?l-Gby_G vI9ST .##dbSv;Str]_? 9_>~쨖ب1~!g 4rIHȵ@u-(nܜAD@~\0[@kkHxP1w5nmsfk7GNbZ4i͎XsBb"L& ;]ݹ;w}_LOӉc.SRR 99/暏 f7>C8㓒dy:_hN@PX 7pW]e7LaW>R܉#cMMIb2 {eύXR3g)%Y{9"a4bw_&7=oA۳<3gf7Mn℧W7G1⇄h?G;ljuKoo]ݴ6 rڎ0!3'4 L js/<;pq He]Ĺ~C=TOm(SFDUUӅ- 3`ٲeSSSLq~@]<&:Dfwuzk!RV~]ػvcǦ{>8ӊ Wsqq+//h-urd$M-"}+@p$#/{83巏LSɇDd = $"zWo[kt=ٜYA  @p/Ga[|詻$'ۼw7_{EQpKO7_K|Sq%|hvtmgM+_~3go뢆 رsS?^N7󏳋5fRHJ$-ɪ@ˆtYtj!%}Ocӓ~QnMvwG33M&SבQdNƎC/lVn* !0]`|OܰHJQ\\̆Ϙ tT0ItHf(RU3!$%::=^ʧZchي_wW-2D`̌Vm2|dIP J 1u7`ۖ5AnwF2^퍑_ .TJY@0[Q_?_\J(DnM8,9rw?MMM=!5=rr=Xz%:<~5դv7n;9k3f8nE_zgz @\PȗzVVV>}1=9%*(P("W"=JB 9#4l嗏L۸q5/jdD# =2D'aA!|xW/g.+Д"%]óxnW::{<;>QV 6F\L-<nݳSo7lڰjQ#'}9 eôE ]4u9K?ß=LPB8!Q VVgD/ENiФ*!u]GKK\*_VuS ].߭JBI=y-l]fu7oS]{wDpVT0Wa֊rB43@ad%BfBQUK]thRϡ3͍Dk8c =\^FHx N:w S'X&I H QhcjRPJX,5w7nDWkq-RMMM$( |xjwH#+_/eU,J~ܘdH2s䦵LL,#sY;ZBH/,2bLh9/<]ք܎2#ey1ǔ 6 Ţ !+%vjwl4:B_"wтê˶XfL& L({[gxd8 BB6BKق^%2'-}I,QVTE11C&.MYTJT$$ٜްcGFW8@9p{w{z)d <-!щ,?Dy'tbt=~#pX%%%\釺`׃O?tdUUU2//OTkc(K˻iݻ,Y!Z58FjKmsb0?e=;W}%OٔG hU&sՔEc ?(!8/F'"6:vvvtn߾O>yyYOzWބkGe-\炘tyb{9 Sb 6pk&~0>xأ_cC&]iXUw>8ekշ^,:,iQIGsa.0\ѱVZZz%si^ߜ:gb W%$٤C(::h5y{(eƞӧkbeePsR*2=e1oS_ `n`xP$&T7ng1ﵷ:`QunHԃo&<QD5/0֖zk oSwQvX٘fbhe|֊s[y.nƄ3"<8U`11ιT)!Sci2U19csL L6v Aw'~Ȝ_o3.~f6'1B.ū\.~cZ;8E|HDp{(^g޾T#eI~w`8A8Fܵ Й=VշqMB۬&m\zfF޽-u'Cx/p͝O}SeyęF]%%>hѣ٬[ղGvj "0xtWP_6yd!2_?c}ݦHD@4dH8 GM*^nUoZu[FҚf/:ewܑ:lX#h?wK6]/~aP{">P@ T_Wlftmꖃ=ص)))/6\#(d sxY`A!֭Yֻnwj h8 _.+>زFKVWɼF^ܒ'S+׬ɋ H飔f.[쫾"5 .H]WRM .K,~}e-NuQEuka}~`& 6tX 4L)iC% %GY$ħ?Ԅ@@BOjbކOWGU%%\JIWjL~]׽L-N ; @N:VVB쪒'%%%g @81(B(BituvDڵ&/h}&m۷ 6xo.gcxE.Ӆ<+7 MuuFv<=a(`pANNοeH l9?@h!(|Od1S OX}MN>x5;vn6zhxBwգd:44%eCA( X 9 Y&ӽgXӜ%ymLDC`/2AM\s%0]gfU2p)floJ%! !=$ S^CS"{,t#G^VZZ,--\.Q\VʊSJ?olSӋסC'=nyA\1aN''kA6I g)Ț5ZmL8nuGݦ;BJ@ b#塮Ɔٿ]2 5@+. %ؘ7lsrI(lgN~-8ah0P Bܻߚ78JEi)/)U3= ZC{ҰƯ^ыŜ{ц (ݪItc>__2&*- Ŧ~70s5)RnxZH"8 ʐ9NO~ޚbTTjR*t]WB !@ 嚪說\p(!QxznڴiߗjRiRR JQ0غ vw `a; ơрjRF+synlLlAQ[j튉m|wB_NMSgKR3m6cÎPxY ;JR\&m$;œ7O&0a!:25 sk1` 7H!civ|34Uj{ybZ4T-(ψp†8t(>}Է]yiiiwD'ڲBnYKfLZ#Ԇe &g`HUZEކ=a5s(!DlRZfgR22h&qOKGC}mE'ӑb)ٮIqңv.@AoHEwΕQhK.*tP}C=43))GOrrhX!p8PYQW^^^Z(胆ב+~뮻FXR4BUN=x{[ q|3w QP@H0Gm1e"͡`0l@ Nsįc$@E6Yp|:FD/7i3k"m0ぱ ;|Lz`PRb,4&oTbG}vKOf[o[Iaa! xۗUZfZ͎smҬl87aWbU A[`Wʌb6/tf?0#]%͵/V^;;z!i1_OMF)vݖv#J(,/\ sD2-B ]HXfn1k#č:[(4c)=UUUс>m[][W[6-_]=ywdFG>VRZ)++Ӷl"0onDHUMTEiB,Yr /mۋ=n5OUMc8窮iۻwv]E>4@y9?rԐEQ(%j?yAsAbqs{p:ieLe:ҋ/,e?p3_͌z+2,:P8S.nWpv0TLs(@e)ws6pBA{7qxԛ8=jFjΝxwJ v>b옼;Jb#Xby#/zP",>JR!(!ٺ~!/]4\8C 槱p ( @ 3pB&14s"𵔂bo/&]}&q!/D Y|fk NI4x^3 ر}Ɩ;5rh%3\}~F?%ѓӒsA <+ -9 ^{^V̙4el޼ore;f,}Eɮ#"5D:%b A;#: 5 v)7.;RDzM2v Wv,HSojU'V29"B a戏G|Dc^ٔ@'=bBDYY+9}O9jwhBJs]5쭻 w1rC>dƠ-7!jOswncvɃ߲eKAvjttLKOR7J)cb;4)% klkk{>tRf/\Hbh?緇MDP'([X4V먈U$sY ˓~o㬫JN*C)M>acGjnlYI0B(Rp$%pFAF3TK&oc߻F{Sd(XsުuG c \kФu(k`}7:{NI263ņF-B<77'[o9Z~v:5{xǏ">)ebۧح$iuOie)ia t:!K`|w5a!CN  e)&}q1뙹l ? `@iiޟ^R!{S+O!ˠ)YG7ΞCRF!LS3zB? ƵkBp>s뙙KUq*M;ʋ)ϙk<90]OQ)%RѴJ@ ܠƕ2e,ױK MH9o%ž9t u!y6t]ǡG&cbrBCTe/C.<\CϿ/ !`ux0{ b3@7 fHh RUm0kTE+(,Rв<pvϸho̪B M#m5Q< *<+C <-6B%ee%%xrlqIn.CLY'fHs!0ܽ9[M>Vs5.srTVkW/<;P\vX:PELQui7ֶ8yYgn< %n0R a0Aڍ.H-ܰTڍS bPF:>BVWWϻ+??_Sgj׶\ަ6ňn"c9AAϱ!RU$ŊW`x)=`ݚA7|]nr*eeŬ$ر1Sv8M#C Ie:BĆbDky^˸w,+T:,_T|qIX^_XS;$p~_D/))KJp?#o'ٵ_͜ zZ2i_R*E$uO ݃je.#B;uk#G" :jj4MC0瞇_~ap88˺ Lq:5{na@Fdj"cQIcmc(JtځiVG89H4E{|p I$K6m.ݰ.!VQ ` PɁC!>EC=0 2+Sax}'j?jor ---}^0 K&,bGۣ 1=ފbu8;pp '1K<5/)~+DmوruCn۶iӦ_t:>(.ȑ#HII9;cn۰5MLi)D&]"bgHrpY F!JK(-d^Z[eO۲HTONMPBhKÒ6GQ2dWc᧯`g'\?69}ՙ~ * ƅ"mB_8NRXXH %!|;322f4442@Qo~ 5!}ߜ8 DJg~2,1tT@͂J65؜)n/tHy$I?6 1QQu7l.Fj+,,8dHV[S eR$RG, 8BYH2W䙍F%(:v"vZ:CV''z1%^LUc"[3FܑRv 6cr:,3<- L(ۻ:^l-G!l=4eL|eukY˷;Z4#5M%Rׅ@UmP/Y]33Mv2* /n @5|v{>#"WWq$90=,bl :o[Â2VTD]=4!{ll ]$-k_5vǃ'Mj;<'}Ąio dFjŎA՛w%RJAAt!]$@A0EE\\PT7B?^?F%pcǙ~|}bPܾEd뀟 J$Vly'?*,,H"B쒓شh$UT $ (G5t!H%t hAkWpXnnkg{0KS~g ~&Ly睇pttVeE1m/詧62Y2k 6}ٟ㏎^vS˄zV)synǼw7́DrgD-Z2|// ;괢θ x!!) 4{r֗7L:dR'aE)$F"- 'x}AB.k @U9d$~]J Up) Q3>?kո"ᡑvud7 CWA$aiN0Ý4(R٤j&JN}omnp\I\ PyFPhN )7/MKFoƆ5|)0`?Y%f (@X (`Uff B`* ZI{82}ܵ% !NQq$::vfq EPAMH @Ⱦwz=T۹tfF߼.syN:V[~ab!7 .(mvҐ~kf6h%]ԊynxsT '.WQKKos~%i?P1?{ۉmܣwKFT. Kl}U #Ȭ]; i6!Ĉ0Cy8%` sHp<[[ 8Dp$X?l+,;ܽվtxk~_4L=#Jaci*?bSjFWx'-.*w޽_[z{Yʗ~?\[Xc4e_ß_N%_c%.]_>1ab\:d2xe% /}ۘuH [lK{[ne/[V5-Ö.sRə(-S,[ K.=C 4d~e˖Q{a5+*^]7 ʼ;4{JA*, eh|ghz nLTEpf)pϟgPL`䒺۵l?o]!o2aBSrP:LYJsPR:Eti@olgoDs ?Yih2{WJJ^]xt_s/0("ܿo녂?7Q__߉xy{[*d2޵Pɘg8XJ{Tcurop^&z>FM?\RĽ,-mw.X/+c^tl fmb|NwsvMv{fH ئUe@6:DT&butد_3MO#f@Qs[w/ s ab 0F(2MJK" %(5|bF1!.Ds,ٲ}=@K޾с<>ۍGsO3f{g)~7 s_lCF|_?g$S@I`ӧrsͿ9HC}Mۗ~48Lg:̺0@xڹX^)NNONuǘh(5CEP1'͂-ICKt ؑ0t/O`Ϳ0a@2 ʹsIAhB*ўR{©x_w a"dJYlĊ+1Gn3gq2?jVRBʾ+nAzҽ%Xoz|K;iHzS4&,?0ߑ.?466揧ҙw{w%sx< :߶5Ç\2h2^TrJHsmf,Xp/ߚfWk $;stZ0f-ov:8>Hƨ؃fJژR"*$UC(UzPkSXddqq)-J@BYOسcDkYtm<2QۺX|d*EBD@ʷr;HTm|/7<@HlOwcLuao\g,~?7TuRxzGq kʼ~džB>r>=1 t^r-;s4 iYN$"EC0 PvB,EN 2òTMYfGVgZH 0juԾmbS-#mTv3x pMuu MM`DZtO;yP0]"JyLEtp\$\$L\h)Q`f x`pdPL@s Rq b Rq$<ap#9vtC 𸀧iQP 0 4 o?f^fVŋ-Q`l 8R4J$E!Ōܬ.2'U.:wU p*2R/yȼ iܦz_{c3 L1PIUNJI++wY  A]Y!c`xRQ:g5! rcFpfs+.>ZgϛjDfiUEDc} Y>|eyze7.4tɘ %) ,dՐo^)Y;'zݿo2l'ҹMXo!"Ȧݼ`suݟ655醆ދ5'ͤ삩 =$rdȿ_@K$]0.`B#yy%ó6EO1vqT :RG}xsDZ;p+xRp&`zٽ@Lʳ?ot}Ϊrs(]M~~x:֌ h+]ASfK'g;O>^# < 2+|,Y^M[k KoŏƖ &v$QDR.oh@ y}sKJ\A Ƙ84q9c\Eww:xwޝ:)4VHsZaqw Xwk\@p*@& F|d{eŻ?ge/oc?Z%9yR-}nkt3uuu"g;Y I&I88ؾLJ2g'k3˹ >wag`KB% !RP;fQϣ0-=W2B"TO~3?Ѫ%oyNݷ@ccjgTr%LZm&6`54O\&߻mV}usMo{'^(Y_( X#fOK,0!Z^x]v<!8\ׅeYmJ)dfX( yy{^[ 1yT6|`Zv~.׈ =gL+¨? E4GU+uY2GQi9"%hmw6bƜR8zx_7p1(xF ĄF σR~0\ yPlh.;s= 1$S`VmW b>h?[owŸoVQ` 0N=N39 wTyFhBkڊ O~HνC?dOt¸!lG{d1~?I@˖AЉDW_}5 !؊+҂3f`„ غu+֬YAk˗/GGGfΜqax0l0} /D")]]kh}0d[Wv^bĥak@ ,np:"SKSzuĵvٛV +PoZvu&S},ߛXn?"N\hp`E6tXT)՚>^3S` I%-\w"S+5isn^E#s][ ;ٜ@}}655DbDڴ0@"pGZ0CULYDf+1#C|NE OJ)d:t& 5t!L$4*uo0K*#bat@z C>ߔ._ɎKo ɮbtq[R,'=C>E˗#"bSozM@=;cWUapi2iJ'b;!r=`@0<J:~g9|yRP)Oh[X  Zħ 1SiMSq.FIf5 N!i+@* O9{a~Dp~+`w*eR .To;?QCF . t9d&w{4Y72#]I`& 1 JhGBA":Ew)(?Boz1ϹQXlI|?"46.nj\wm ƎnE}}6s!A>\~>ÇPVVJ8;v4M7J)߿PQQ*dcƏ)%9UWWM=8Ĉ{|SQ7cmmM%[PSG ]wxQeuuurykCr$u@F:0Fi2 !J>)<brv[^ Cz@7w&*6+c^Lʧnغ ?*e+O^YҲжYv#+0cNᙝr ޾b6b@ Yo9ݕ1amu #N8mMT@ർIc K/\=[`V:{^uW AQ޽f6ԅ|4R=\uɜU72 ]G>燤keY|ەm߮YGt4èJ!ߧ趩SEeaL.h7 fNzCI*0;478ɅGk Hqp|-%~f-dv_W`s93r} IŸQM2sXO ={6:t(3 $Ť8p轖|%uM 04zySSU/{,F2TLWlwu S<|U;Fw5~a-ǭ ( &n_ ӣY N7G_sҪ'>͏hGcfU帙`e-,|%U1壗Nвg<G3~Ld]c~6yS/K_-O?d{˂Ϳr`3(E' ERgW[ꯙح%M0Q^p<箎s:0)a/Fy82>!)D4+cz~!fpnR>G`a M837KʅB$w C_FMfq<( G4@X>adУC=TyTq]QH)a6Lӿ%7|DYΞ|I(1oۑ~?}G[?3fDeʓozc{%^rO aVH8\$ZN̏:V._~,I>lC\CC‰`{$wQ|[ŴZoKk[λ/xysf]tQizl+m((ns a̻xe =U_aṕJ\ጓiq4uEß};fMw}]\\|>c}1bĆs1}QOLJ|PaHR?) Zz=[idT 5ضq~oic?{ԉҊI;Vhax`Q8y%`fO&>!'S/ 3g3(7WΟQZbI']rDbȑ#kFrQq(@x%Qkpwً< V>@;xbJ&ㇲtuuݱcDŽŋQ DY"MLNLkf&aXraT33@^HkL2o >k/e)|$h=^F{<ߨ? n2 kiѢ"RJˤӏ$(古蒟X=aBcI.xg} 7\ƇG 7]K 7]K 7\쵵O|%3;/-l٪ͭOe'd֥?I?t'x*Cͭol٪ѿ>NeOrg?? ?/jҏ۟uة'!'n߶O,ZK +t51FKL 溩gG&ްqC>@8Mc?̇'r-,jޜ_6,8mڴm?ܴo߾֯_dyy9l|p36,57Ε~g+.$Rj=1ĠBeA1ѝ*pNWs6ݱu_UxSSԕ# 4q\8b@J1;` ;`#x&_?s+~/]Ԙ;w\*++~2xPJq˲ًKa328Nfjoidm;z1k[^|99.?si`Zg@g+\6QE+ dJ'][[~鼱 ˆֽQ^`̯9Wx7[:ܪϲP + [2r˖xk_ܙWz 7Pk0GܭZ2̽?o%%%~K|}{NJ;2CԵżL=k$eXÈSw|NnO/['*nXRH~g>׏7%Y?.)<L*ME|sX bwMB!-]zɪgΛ&VZu1cG4&I䣄mƚW^̘y1 )8K|w]:k K>@^^ Dŗ\,?Du3ϙ;f;o?(gΟ5vtxEITkJt^*K;4zvQI)J"T^2Ʉ\TKg7$fmZw7o7)KUwgȚ&u뭷^V]]R {mr]`41Z\R ! HԲ#FBW>K|"jl]U5Q͒)>$ʿ7  +%(‘~?ƴIg~i3\ܮqe B$'/겒9k̼r6{=^~Ds/]`\cfkOy~#J8#Z5zЊAՃR;F$mL$t0 b\:g֬ys% d2U9eC?7 C{埿¿iN~;_ȿ-9w?0H'dۇ~l6{yw9I%9v^;sygv=OИvx1lP5 ژ9BՅ-mxs.ΙMy#yל%55 NRloo0M. q 1B]8">ᬳYOW'(++Ƕm[ik];w⻤سgϒN0&72V d%n<R|_%8uI%߀\l#GF:j@IbPL3YqG?~uAE~ʦPV^ngTTU>MSۦk)\ڦMhݺugRp8r؍.SJ#ݳnݺ)O=WHWR /w8ADB KWy`0qyހmE? &?{l3Bap!a=?Z{Z{~o{ۿ1~t', ؕ3.g ˶88 e㬱cp̩(LJ9a䥟xy=m=Zf7y0MS++}+b&L}7s]uaZ)~_`{c#k͌`iG∞5’ö TVVd۠MoB: @+q!bgK7`fQH:RE+jrjk2BKT*'Ϻϻ:P&`(x @S)̼ LlO$8.&u2qĈRA`zBDB)F11a{vSϋvƮ;/|aYVqDӴ݅oװcvv` _牂t+߫srgωbFy#~ `N=<(`[&|uZX CqI f_p.s>0j[/~1]WW'o5^g}C,LTgS"N#k{?>XWoi7x㝅ár׍1vl1NP{[oLu&a8?ZڻqlV`y˖+0M&;`\V RY@9L*I矍s- 키rRd,Q$7e% D1FǚEOr+1D n>|OD0wx _`Æ7 8-|ecBIo`_`:|;ֈFƐf!n3Zkaض!,?wgo45-⍍39q(+-z;@.7u=bMuQq/{3}iuSSXl&CS.]9j8N`B0Vl\x}g:ƥsb}ldYWkkkԔBΌkK\ 62eC+L&JDځLPL&IE3g F2l0YF)X|􄡀)7( [n" $M`o QYQO Ro"9A*aPsX kTjkkeIIUPh\͙wAj 9ct{+"9˭^;oʤC˯Zg-.{l;T4%5Vl88_)/<$U%E-=aX#kFEVhY̜9EEОKWa}8Յ/WE3Nj,A0lC^q(B0SZ+hr[CӴApQ,k<>!q\h\)?|Kk$ be㊫Fg_(FK S' ۶Ko7&_07|CʆiZ#J!? <6|8Írl0>,^X o<$>H>e7ksa9pƩmXD3/J)0 u!r׀\ SA=هj@߾/~\=2t|8E3A9]J)b`lO"iYX|9X7ҬUTT 9@ 0OkMGQF3<>dx 2d(ƌK~LӜ/`FG %'q$\yUH`!b˛X "Qe  u||(_yo~KY39 _?'Ǝ-KfLĄ11"y0"A.Əޭۡ4AsG3UWl|3Oλ(5"0/_55cXl)f^| ԡIFno,:iudD'gVX_<+W,11xP5&3mNO?c/W^ƌs'!{@#0V,[φ< \}u()-A*+!{ { lj9o0EQMg̀ͪ 4 ˆ'=hknlڴ3/TϕL;ob`E*65!ZT<q# 㝷›V8kFL4 T HYEvF)+kIszh(<'ۛyߜk87hη8 %a$V^_֧`J{hkĆoc:sF`f02Yb=+R TV5Gq7y v Rm/ƥ]!;JHp=M?>nLgMPZw:gʅ_kk^50vO.8ms9/~&OAO,> =1}y5V\iMv|E)Һ΁aB*Du_߇ M u-X3.pų|zR M( 9:;pu$IhH$1|h;f QH$ADH$=w"T.\675\Oho{;T8 @;AXe q7]XZ7PvL4+%ϽU" Az@-,N O? Molu=w4&Or'zdY&K=nz:Dlց'U8^SR1qS2d}w#v]݇H1*XuN$  O @+8o%sp=/̆=ߧ`0H4f#^3xf#\c?H`ƬKqsW~`K/bW"bP LE7L D<rl)-29ضg1'.Ӵb[ٜsh`oo<9̙5O[A X o/,ۊ{JM ~l\2uWغ6ҩb5e1\(K,N=xIT3XXO s0aq=߶5@])A(-|?ڄl6P8'"HSI .==$R4BR`( ' <"Uk ڟHvD^p \:d2H>r2`&1pC݇آ?"ITg_.2btɨsF Բ8i !فwv5+3{w>_%0+Be,kpj?)D~naZxo\;y%KP۰T,o+ogCl5mcۑwcG> $  ?͛ ! v`l)<~`}m3㪊3>-R!|ޮ+)∅Ҳ+,,ӀDg"ﻱiȐ!"R9QcNJ)©U[a` !vܱ)|LT:k?Jqf3m~Z2,b8y|ǿfOz4qݢE>#,Zaj6K8Rlڰޯ=i b='Е̂Iw߶cڹTn?^[^^v5uG0Mo[ .f̹ JuֺmVWWד?Gn5i'eSZR$]0.=5JT ݻlSi4&30]+s+^"NxcV__r;"C%LPP } Mſ=> Y' "~m.wϝu\?=? +9ӫ4*)Ļ;Йbgs6m.Bشu;v6#R ֓LCs1b~)MMM񛺻_l:z5+-PQ:۷m^YEO-zDf5iojhhM& fWM'Ad=axg2~s8V_ux|, CV, /]2 RI 亾-⍍Lcn^i(' -o&f LnFro4\>fl 2 Bm&M.=()Έ)zy˖nrmm[&|Ȳ aN3 98RJsGX 3g}&'gôp量EDAn-Dm:E`uuu<ǽ+‘HdUc5Ln_dI ̙?Y|9#/<`(ʼ@r3lgՆ -'GWO/_Y?FLF =_ԧ3g?_D7/^,XT4Nzϟ җdlyۙx+দ&uL{q<30|s*ԁn2qpP>u0`cNko!3&2#~u55!SOR^_0M)S{M2/nM!u

Gm?pSgٲUsJ~4hɑHZk| \˼~d--7Ļ_3g 9Oaj?Oa}2weHk=9 N<(H)5c,!6k|`n0Q8l6Zi*/>eKV1[32_6祥RbGZksqx0 8I-_RlaPĸQ.=ۡCD,_Inټe M#չJ6ͩ /θեLornq/y蝭/4٦w "LmH_|饗yΩiu"ldrC&9i!~0n+ؼ8A?QغT杉WM/&\s5s菊&"5)y< J!mH&_|WO?8c5O(O#ᾸgoKoL^{F?rDUˊMNnӭs7 iR?4zWR1c'۶766w2,K) ``ߙa7NѢ:1wra;ǎ=:@P ͔8ad[8nTaҘ>6ιsroQ z9ϥXH`/l===ʲLD"wϝ;μ9DYgm@0T0M.]5$bаԊ ޷QDpz`FKI01Z&.Q=hP`Eՠ0s }F`o24+VXYWW'ꎏO0tu ^S Zk u)(qT*u\|bV +8?UsEuIK9dY (]D~ KzW9BBaÑm<~^Q {fbF r.'e!s\ep]{׬&:u' #q®]aP38l BvϺuSMNp^NZC s iVU0jr ~oDM5qϠA@~o#AhppC0I6dP)Yw*,&0a@8 3uTd߹$`No"wĆM6:88k*}{b'H]]f mż$7qEg.56ejEqO$2vo,XkqD"4MfYc?}-?nqYz`ys70W?18(asfXf8Qፍ:8bĈJ)3+sBDB)F11بOxrHmò}V?4M!zDw}vX p)ceD"P>7*&qyŕ_EWyE>.D"@2󼉻w1WFWWW'jZ avBA]8JlާFLDycc#N?&ҹjDnR$1-rL+qqDhR$/"R k"٦F'fB"SqP81PQN8{F ƒɔf* M 7'Sɤ_s䂑Zቁ@v1g]?OD1pAys"c ZkAi1=%L>qsVy7' @J̿ /^%+9X,FL_qaB< VBs Cnwd2N ; N_J}CSnjw: 5  )JEtϷ` /wR/K@f q FA7@'<<_gBI Z+(0 "ϭNc<T 8Or'h}hן>H<.@ AՁ!#dmYhaYFWWWolEo3Bqb1H)f8傶N]vj@% M*P$j?w{$j*BL2#&6W$۩'*ŋL˚dB\ah y`1Ӳ-^ >a@::)D}n,Y.zDέ~boމa'E > wtww3w~_2ǗtT(**§,BA*= 'g>/Y<'nFkG B/M9-J1Ƙפ[cȧ!D&aPhZCCC+rsP }NH6 Κ@qDDT61m5e?jv\\FP!zQ`f& in> ŀeiК)bG/hFxJ*f[|ڢ4hbPZ}92R  !96cƌ_,:a|?J4G~/u]  !Ԕhs-K0wyo?y殣>xҐ"Y4&2Cƥ)Cb7qFb<SLW\[0 lٲWFOO<àA0f(SlY oo 5|eߏDRK&Y0lZPc1拎0֤5X9K&Fy)~1<4H9QCo>B09#bdO @0M̲1AXpE3:JDAeYs͞X l۶a&Vo̼|rdm] ك2O`Ǘy\~ŕy%(--S!߮nLp:f;O?84 \ƔpٕW{CpьfqxW.L<,ppf^hvί6 WĖe0 (8p]qDXENQ:p=BOLA u( 4>iBQܒ D">giR=ؔK=6>Uh@1"}h|e{ZAXC॓Lf6dC%*4K9* !)yJ)缂W~~?pudr"@2?G8{<|kOE:Nh*#"F<<̶+'@0OD\eYl۶ ӧO;#m۶wŜ9sﻞw9眃}ahmmŸqY7|R]Ѷ_)i,l#,4z1.,RX9ԲaV+ej$ Җ0E6U4~nhϹo+b;䋟y8vprC+a(-΅˗-̋/A2Bв,l eq\̸"B( ¶ BaX3,] Ji8ĕRK]OA]mx7EquKPqۑ 9pJ3x.xmst: 낒}t|"ʙ}LwJ VsFʟBp|B7kkJi̤!#b(d[CX1&D`*u%V`0| 'V+  7|BfP = /g9*)Jeec%&V6W BbRyL9sqy4Mx"8={6rGKK *++^s = z3&M)m(+ R\=R1xdH<@ev5M&vY h٤#nfG?7-﮻:ݍZsXc!_q\0I OJ00atwE#W\qLӀTnqqI~lpԓO? .2ד:e|}jqqio$ap@o@<Gstm1>u'8L\1!_22 iww >jM:Nf\B:EB|"DQ_DjVo ZAqB߄}oP }ZAN$wQ\ !q)qi8ѵ_ɕRH"B٧rs/ jCLA,c JRӸ+ `Rk.aղq,]*JJKO.@O,O?͂0yꅘvށ 5/ä2t& 9R̸dv 1|'SiLP]a4lIqO?)=q̋mw>ƀx"s'q!~,C=i*LG<}W/s)1֓[k˲x~O9Ri$HvI%eҞV<'toҀtf$@tibrU^:Q陎lzMn?qgi'<4ALrӽP-fW& B!"3YDQ=z=8)))eU*"h"+BpnMB9Zof0 CJYdHkq~/4!"@C"Fe#N ?3Z+DBZ?N:: ZHMD"fB%/gP5:T[)H)8(pi˯T W $=hC 4`KƲ(+ Uܷw0R v=0 ß4ӭI0L c0#l눙(+*L^g5 M7W}Waa,Lv0ƶuIJwmz1h#LTWi(d [ !<[7՜6mK/6)zK%!* 7+7iۈ1Vy<Ax!AUUf͚5***H$+{ʘr4˿IsWRX@is r}9_$T}}_ynt5ʓ "  "H_tΙRD:^.8_!C7} ->j4E6kf?UȥK_:0V>yHӽ~3(*8_q\u?.[GDWk?O;Xuοf;2`Vf Ȧ|RWe*&hEF0>:>9Z8ƅ ,_4avWlZi L!S Cb:\M*E ܲaqOc9렼TZJ&㐙4h>5ƞmlփm+qy6o5ؼv -6H+po?!W ?~Rjݚ5k/K*CV(/ؽޜ1E?w MuMf?$Չ66mros'x aQg!ӉpelROWj Ykƌ\R@)V0lذ^k]]]9[:fls" HSbk,b6x(ϓpXA@s&8JY*z(y'1hN‘^ /g?" $-Ͽ*6՜U=QJ+-2ӆnβ8RqM[0H 0MK!b&cxCc;M'D' V L -0D|`✋D"ql|bBz U&.@M., ö~ohD O!fo=ꛎa̼ĺ2h /iq"B6hQ"0 2M`wyfVWW֯_s/ ;!  C6:p]1lsF9#E$@t@ G>mzoDd.t>XIhυ:| 0Exgkߔز]Ceȴu@fJx'M[zV0H Fy7T*!ݺqhDž׃dld~6m͸8-# ]@9Y2By7^ *,{Eca!,ַ_ޫw2S`#Irqtn| ! TAz$LӤl6{||)Kѱ5(j5&w<|P`2V{޽+lܔZ|x\r7Y6F.;:)J*{:sgv5^m`^l%z H!R^HI5 H$bc"YdwwdƐ|;'s,;3cڶ ƚ5xWG)uq:g)%!UsII ƏSNŤIPZZc?ÛN?t@)ԪaHu[oCM2P?7E9\ђڸ.jǢOv.K7R{?Y 0~[P u.5s3Ύk_<hjjRHo.@0h+;i /eh !@{˖|Yo/|URi88@2D179F?+򊊊;֯_ x|HmP櫌jLRlW%x幹wɤZ@ u&<ąRo` 2Fq 7*(ѵ9u_vK dSкGɤH%#v=U.קLD\KA81:?0 /+wGhiCZQ1o˃ߑgtoNG/V|DwL,+&br]\5b;!ߑ:ЬJAi+jȃY@ Hx*6RԞw0u () B q5B3/ &dݼG|7?>:I ) `hNm۰FF׭qƹkҁ$[) *ie~w9;:y S#]@j i`b(W6X:7=?' ʼQ6̠J`֮:iٰ%Ј[ZaM2aVO3 )el v IS$^߿:UeD v 6#ip룗V\RJpmB&b![?R#c}W\sk!K!D p7臍H$Ξ=t:}[oo/q%RJR) a+R PH/3f0>]:rw[("x1pGضMO&0SlMAZήoI_q9hkaxY}MJ+'3fgf峀ܤv8)0jl B,Iih(~SwC?ٻPVYfP @9Hm&7 +VN  pVu!-Nw[u\MkH{UjW񖭤 tTNI( haxS2^z VZOX`r~) A?2,ʜQ ?ʅt@`& )(ֹM,.5^;V$>vv $ Erw[NNPZk8#gq˴!g#"tz:5e"/\"JՁo|uuH60M.7Y a–7DݵzƲ3Hfy4&pouuT>\$TڦQ(1pxzk6iӛV }HGV*yC 9y9L К!3IL#d"=c?jm%W_ɇ,Ą7r՗]vY۶#Hd3q64!77`S)O޶(~7[|>TFaiMu$) :mׯ~:Um%=ͱKq8$4RF3̀P@('eՒ FԭzwI3*שּׂ]sQyVE  ht:2ذ);8픥ϴi-@`p/g'CD~̩y!5dv((X+r}d, J~Եžby>ƽzocn2臝L)d! vٔ,-?]`Ԇ{u|'f*]}]5{@͘6N;i:ːt0}WO1Ԯnv3Nۏ=Њ'͋;G@?Ϙ1Ø2ei랕L&۶]@d mf7߲-Zļy=)>8MJyVaO]NTbh9i:js)[=OD"pw.ODӅRJR8Am ws2S>(7MCXLgc?0og πqţO Z,ä!>/#qf [=򽫟۳gA,<qןfH:kV9}|i_tlH$f֛y1߿#}2 L[TWhԶ5醤r ְVI؏? "|%7 s~Clp5ٶZHnJ'dix|(0 92Jct:0Z/?JģSolbҭ˗;P3eUe/>gǵO‚Tlp ],f e"[hhym~~uE33r1n^م/H$G y. ΁i~3uȲX8<8h봀8˲t~K/Uڼ#cO͝DSSU jmhlۜFUXvo\ߍ]j=_xpn#Ph@#V `ZT>9 fϫoD^#؋s#Rwc&n]6)4e~-k]E&2 쌆fUn|[^~hDmB9y' !tagg/Ca}m,ud`D6aPQ32g%C47t14~f" h)F'o5C좱nOG^8D{q#*P$_QQhi{]7^ODd@xtwޝTyyo~,gvZ_rmοDԒ|xړ=?YOLR X Ӑ0 i4$ À0gofs%p8L"AC8Rkm4j(f(PXX8vPVV~㠻2T/W N7@$uM+.#}3f#;I x'80En9XxawRt4HܹseCCƂϿ7~)%@?E45CFm@4,ǞV̜=Qsd? E[*S}9fƟ.+ Ɂ =fOf=v%13577SkTUפSipLGX>gA@IyDj`U/^r6!=+nw͟ySYeM3+6[ jn@w\aU.cI~# hU^X<ɬ_qmD䮽zD`<|d?œMu!9}c֒•2߿JϿpjMU#ʋcH-N~Q+|>2+55U"H“G֍z\+ Ez]ϔםB=ex4 |lDZ !V`-+ IRcUJ;B&qfĨ@ ԖaCpFDDIIPZU5[:::e0 paa~a"o(\FeD#8:\ gk˱&KǑ:(1@UbE?9'-,J;`̜ 0Oi]w9\YhlGLetDFL4jV9eȭwN"ggVZC3_ndQ[f~w.//VQi4g)5g  N[b_ cz-m8K_\iXu7MARq,a[W曎!y_PFXߟ1X5TȍhUU%W1D͝9C 2o6QypH I@/X0MF" 8gPU7}1}9+_kik/@Ҿ3Z==4. |s\G6lq^$[6,lR01jrX@x~:O644dB" 5\3MtB˕5'ֈc|״O' /mܹhyyK6zȩ8JV交JKKX%WTIr :Z\p*-3L3I?{IcF\nF$$-EsFPpepZdSrO` ^YYxß2sǣʍbie}w6nuָjV{u+~SO)/z$'lSa挧WY_lnnF8b>\=8kf߶ɭ,ǣG|C! Jy]F[| TPcʅw$P%%wvdm$^hC7^sǝ0뗿a^d0kZx՛ȫG nUK2iJ/f>H["+̙3 q"iC9 @yy9uvvzh(8GYK{ Gtk0 h1'g=e@V@ ;6Im; 3-,RrJ!_|Z# *z^c KMOapf:8ρg0IpR#a9msHnD{t:{4ʆVӶƌι='`Hd ))!1AZ2a k/tO4̻s\HzRu-sF/ S1)h,kIdKZҨw5GGDˠqaֵf{:\BP g඙s|9SNCƛ<߻!p5|q:91FZ"ص->o[WEKelXxkVi'Vpx"q}ZO8"ӯVՍ{)(xX,%+nYfT "_ekiljZ|ȓs>1_V( e0V-=>(|%k̙3UC8vm[ʏe#V\5bdb jTȁh⯗̀ ߋlb^[{:ǠaYWPZ3i@] ax՗mؼaT2< j(:e=QCg.a$7S?o^ V-xyؼ<9O=u%aCV]KMܶM;|7KCޔvKҘ7gbeY<̪lL+{/8֗^X_VYrͨz*3p#/~]"ثT97;r:"YJ/Am4D>C^5ԝ7۽0R ;ZC 8bea U>i(+s&[V}/"͞}/T:0ڱZk ix%QBBD<__=Fώ555ͅR B`֭R+iz٤7ۊyZ -IO:cǓa F5rKD_Gh"7$C3ȟVN&+@̯ lɟ6u` T^N۬ 6PENɒriQ͌AFMʫg<D+?1MzA+I^ 3n ]`|?Ȥ9ŋ[yieVT ,y7 ATUGoOsbrEF9~v{j#+;oDB@^FHdV}eLK+n16;ܙ(Z?]hD#/-4urFyY ,|xʜ-n+Z{,0gh-c44= \ +9M_'U[>h킀r7?Eoa6 c6B;fɪk=:R+ c}kK߾L[W*a [zs<=lfTeM"[)eI1t+F%[uܢ\޴麋Oop`\X}kuu#ÀXk)"gr(vIl72mp8,.-}踀B2 H+<]{\M`v\"yYӧvg$QP-5L\- $alt0Xz:}k}dWvlADŷRY] {c&rW%n>d~QkFSnxWنڌVpN9f18luMl,/D" >SXpOԌMucyţK œ !8 ږ.S4mYjI#萌s/-82 I! Idd@csjW3j 8 bάwaRMr}l q|`N~hT2$ #mڴ2J/ɂo86,[QQ*r1KϩT H$(,,gM:00q`+`VՙVŀ+P^ ^@Bh"rڻd^RAc òIHC2cF7-@P$Opnat&yMT]ӎ\PtޱF<9ǿ #Oh>IBhjr9 jH*# O91PJKA Δvۡ;3 P.tJ!qkdNyY_zJ$H]ۉI~0KmapoC =PH ˗%!0U@;M=5'`JAO0tB]588y,{K4 @ˤ*M)EnowNԲNc\kTQ%f?M[M:uɯ`FUgUa ='C3پocsǖՌ f&GV2 ]R; aȃ`!K=}%'xw\PWTV>lio ¼Z2ApT} _KLGq{EͪF<#Ə:N@ZڊaOr(qdOPJrdݿO^9knY>p'$H˴ahf*<@v'1nEwg7^u@,jl۫Y'?яJy2tAؼ7Nz^"OŜyN\L3&"G˾#-ҩ He`B3ABAi43 ϯ*=Dݺ'?{漹cτ͠9Ͼ=ͺ15c<:3aY9KF@n;nF_&W7[Lj#`6BP}.H!0#3x7b+ !:S:":흧 B+5dijϻo.pQhlH̾$9}Hb Z"nwS6M!)amoк@jԳhγyE`{^g[ZZd*TpCnQbqǑiH~U$l`;yF~qYM&.Lnll9immpX,y{<橊}ڲw'NmPi6Ӷ=H )Krr" (v$;.V~rvYVD#\*d%Nj#"WN0G .)#* X}8'I|-3$5s=nsBԏ0" an%xy(D (A1ƘрE42&3$ 4SL*Lѐ'pT MV[jvh>8mp߻PX`¬K0sj~\E>KLo*sj0_Tʷ" w`eG~ye| ]{\>.;+y1Py Y 8dيԆxv|/|6L0I ;ŦU+ӎvxoc3'5:; l)=7 ~$y?gE@Ibh ;%a`+m MהA?)xuOW/?e|^etJkF20p?/,4.ِa 3pJy@J񪪴h"y1 O]h 9eQ1*S9+*̬qY}{WUնVVZDeEY!u[W+ E/Ԉ''w@oL:8w5[rնHf"5y< Da(j G1N~YUnwϖzzFbKmfl濗鑆J ({et d\յEYS8祗^9۟w|Emu^: DpCYb\g4|qn {Vnԫ:073-Dյ;H0#Ґ2$L3kΈ9"xIpBAߪ葖F+{D<2 hYA ;Y]WZ~#[iI0 ֞ZXIr]5-STr~ڊw_?T},wUW_*h RkL 5WS؎îғP8J\:YN&(((iCllrٿ0 Fի100<~2%z4|]~ѹ?]s[؊4Q8 0I3†˻W 5 V.Xk։v3:l =Yr?6qi(!Lu@s!"/36๏= "\cװՈm==3`l=SeaYb;6!Y[SJ_1 鎧޷|hG0%j6t8{8cܴ~8w#&YFpdZҕ$%Ql])T&\sFߠ"\J+Sթ)qVp b=TZSQoCC Ѐ#Cx&IegF<~igmO3cϥ%UEņՀYÉ=@R۽YiFo+{뿿0Z텥% G ̩kc+ZmOZNlR=G˗踩#j&/Km~MM zKkj^Y)‘9]WgU{ h)XP8=) 䞸K-O:o hxh!0Kx/{u]M5b?\pd!Hɞ͛}?Ų RB)}m9[4`Y֎[{?utvvz9g3?Y/C4ГW7{/Akgc &R>QUzD/ #]~śȢ}YLh ֬@t^}̿&G'R}(&_H(X)"i CHvvB+ŚTgtJ1\/R Ns(E2tB?&GCls/d} u\TNO!;Jj\v␃rmZ ^D(DžN4\yg^4opˌ5?%:Hr_PSC% k_pV= dpҫ?񴺧_ \咱>Kxڸs/+YR鳎L9i7]Qa+*sim KXi6l}ԡ?ZNQWi=U1.XnEbs=G/[]qwE]>јNRowPfgwD±5B%{Iw@xruK' 7M8y_7rj 'G)خ`"?VE/FM)H *ȑj;8iu, Yw7*X0nWk9tn'F2ky0MA}]7\O?Nnk {k-c?aun @>@8(tY$zZCYӮ]ߙ>Ê! )]JtIS"@Q@z볛G_Uonll^2 mCJAJv^/1\H Ω*oپuC*] J<54{˼ 1ˇzL`aH +Z,&. b0t53“>??Pc M־v;577Xo='[1U5d*lւS';8Nbn#8$h7$ֻLx@]QQ(} Q=]}^ a 8W1G)~DDfG?O ʸ/:6@8,=``"UysgE#]N֭{$dž 8gRk*Q394@ 4GC1֞k!hZ pi(캞7 ͸jnMAH"m a 6=]_9@#~wd S9|> +6",眙Rq g7'rG4L(IbgE X!iw: W-"[ ׶4=mj|IO (Nf̊S?v״?aw]#fЂ7cA~S`Z)*M{75x*H7lJ,ygsZ% lr0zD (&N\'PTvk#`ZQI/8&Gv3W6L;kCOVꮚr+͂)5 =8й9W\D]^--ӛ8,iq/%bk `aZ޻&PVhXQnI ]ί9c٢ѶF J&4 3g d@rmSYʲcҟW/,;2yOQlUue'5RNF`򺲪 B XPfDbL³k* ffaXթSg?hc^ܽǑf_7{ӐN%-˷_^AQiH2$HH$Y_P떬YEoRk/CW HDkCᑖi5Վ_g,|#~82eF"vi8)1-eo%֬+((,c۞ʅ,MOSɣ&c̘10MXT &!{^Q?xBT^!4{jiK$ysM aɉFњ7L9ٜ5[?J)JH#ܾ=Y9ef C$r;."<{I  _Q "f'Iډ?|E4YgEtR}/P(0Rt8ֶ[B س+'wh~t:Ihtڎn 3[+rre͝$쁭(WI$!ʑw3di)D>Q\G_iYP枞r# F aj2J.A ɘި}b R`I P&LIH1G,[Z4чLn:m \e]%ET*#Dg$T΀AbJې>g5aCE,Z @"Źx: $-(0i(U6P$ bqs#ڿ }8|Hf3oYp?]2fƬ!AOtS{],JQSo{vL nLҶ/Ge`d'l< 4{RRFI:vWQPVl *[,I;^IɽRw\qG>9$tԎxMOM/WT8  mk][Bj;'dWrYkA+z `eS+$3k"HƑ.C;IDajv(*a]kvH Kpzc,c#7dZܽbql hv:dIe{9>H˿{zq3623]o:Vol.epG4LͭA$43*yeJm) l,S#Mu᜗>{kN?Ϥ+TYW;Ƒ& Gz03""zOT9c;ؼi"u ??a;|s-I8yXQy_+֯#0H$ YێeKϾ0q=%i4d?™gJHYg]|lF,[:  J }\"d=k2+k JK3Ҏ|AWkd )Ǹ8yH?yUq:H_U{!rp]mYr?s ~PrGVZR &co}vaf1y7T͘Q+WjT~s'|ٍ͜$7 9TAX0Zȫ,r *aWA3M+bSDO|pLMޖrnCu:qN%V38>歄U] !`z'cJ>xO7+d:7]ټ==ɐb 9)@6\ׇ[,A1 rq$,ͺe!*D"N( QFW: O3Ν!wt-P|;BpkS V):C_AXGn< t>Gc{[Qc?i(P4,jf&f =wt]xXL-0sSk^|A+Kj+ONDeZ)m w*(#}H e  }ZXTwYјfbmB@ 0aj,g0>Z7>׶ٌ0"D*YnwDt/]4''w1voȝMG` %U\g(v]^^H^nA Ay!GI`lbm\HGbKW!j5h RL#Kl[B B:!/ygƳemyn ~[1AIOeחڇK\vVҨZo =t{?g=Vn񱍭Mgep6^,^9/<_(T&D:џHv v6D4 f%xt}{=ŢpsD"ﮚ/{QQi^AQI<`50hʲcUчafxb(igu;l3#H@]"#M3pl͒哄X"#;, T@.}o_ Ib+摔ɴ4tJ@.%#/3k; !L߉Fn9"$0@֦N7-hi;L>@nOUbwY'-D|snW{?TDt,3#1agKG끓3x"†4,~0|, \jWk+\mG>9)`=V$} SJr:s%Ǝ cVWQ]*qvCj.%0Lngzw#N-{I* [#7`yVo-9-@HmHH9ٟKݩnΝ!fF E~,@234D@dڧ vAcX+P4# ˄'j شf b6MBJڏ8ߵCGw0 r* H)  \v9*g$.5J˭1!|g>g"q'I>z擟l\jts3.߫8 fipGt0<9J<}"|˿'G39Ys&;8x>hxGE0fLS,߻oǟzdtQo ъy. "h1 'MyqIl0ImXs@[[ߜYs]׬zo06X¿Wjm+&WYFVN)>Ƣocz`S꽪Clyl]+))(-.tL*s>~4f @ZRD"60ED#QMWŚ1 ayj4Eyˆ5FNaEgc ?jMdwxDOp e|p ל0OK$I0z}g446Jd_4g9h͜S2nv~"naTņ`]`4*WX[]R7ػqgWÁ[j<`>u?]>Vq/v$őap9'=5mN{Ԉ8)xM|t}4iV*)D.l;MJi '۩'n<yضً;/0M>a ]k;4R8m;pwbWy MT)ԬDY;.+ĕ>T_e -:ʣ:ca֊"TVNI} 2L !]2qѓnbSΖy{Ͼ7rTU;rtE%`"ЋOKX\<^mFD_YV涰7!0T:Iߥls!-@w)IG8T`N0 !m\|l'pvJC4dt'yZ>e%ƺX̽K; GN. n]糾iᖖC+/vk 4 ) DV^He=vч7w?hbuQy'm)93ålxiYC2.rՙl@ O]4e^;?COw{dӅAЮ(z a|tIE]wP}5h~r썧%8Ϭ 9{oZ C^10P҇\FyYwY3O\ /nstYJkFY/ܬ13\$,CJL$]bG@.|BUyw۽=QHQH.Z{mߟ~\|7斄7`zk{`f@eO>򪿇@$<ʛ3Z ٱw}z-OѧNkj"nc*w=RWUŔX\d8̠fxmXx[ɴ^Jv)^Mm3P^ӋRu/8XJg/ ̠f鹋e3EAЮ(tlZr~6j撁fPk.m$q=п몃7o>_cA}O?c;1 rz3#''gmFoo/Đ XD"A什CSEgLDо h4& e& ^[/ŢI8<zMMN6uԻU׼Y9H%+X"߶"aHdZa@ӵiY[]!JK6b!PHkm;gzd2b4*7A#CBz:\.NڅazS^wfhli-82M̿kS3e%ru5e!Bhf ӎHdls}0wnUM柲H^tT7"WNR4mz{Mt]@//,9|jہ2Q~urɒ⤣](/_׷J+G{u efDI+>W)e6v՚Y1Ҁ]j&K:[Z$J6LJY\F_[PɲHlgRqsf -LX۝NmhookqpŒ:Kct;Sm(Noj>} Lc0No73XxR$g>@|NmW'Wz˪??!bUr˪ Ynk mNoy@8MVH/k)N$(([2% یM'Lo OAk( 74D7eD4/+*HKs!}09Hw&e6N-^?ȳWf0-uUe܂TQ}Dk.:-Hd NNlb!vgeY@gg'z{{uDQB( :L^O.<);Vv bNΖ[ ^d{*äre{a۷#bJiH)Hki% ´4`Wҍi͇5{$'D* q/JBmvG,ޔj ĊG)`ű> ئFVb`і]کKM'u#_5+0^uʼ& ?UkWYurz ?8~sΊmCrpS/D܋sUy\ 쑼 fR>a/$aW7L}=+)X0L>Jeb?OvBP.+@;Rԓ.\y[QUUlkkwtm 9+Hau]P =ЧR!58Eqq1,˂@JzxY.++J!aXv-L Mhò4@JW/'᪣'|nk3f74tߍyg/ȟ9;':kzA[E׽MK+gzVIC@pI>wn`Ά ϝpww+@jSѵw29w0j39V s%5dwtSӒhP];g|J @ O4J:8k)(;1f6̻QY\he(S+LE-! S !;ުfzΪ;]gI;O־ӚC9T~j)(gf[;ՆWn/m;/]Z0øoƼ1վZ8?khnsY-=6Y Pov^)(g[3s(c9yv~f8=yll֝y~F"3mo_;RՌ5^+ 1V—[\9K3ށ+? $4g~ລJO^^Ytl0n?CY:s μ҅՚ʛN㙙~W6,?!= @Y 47'G>[m,>糠\4븴C׎2–Ύ|˖ް֗pW3CLV鉅Uf\{}hop4]IRNp]ipبg3veg/ /\yf_m^?)MguQ pSM=zԄSƺ#1l|2- \wE}peM v|N|j\x>E6!ѻpG kdܑG"t_l} ] q eTt@vishE=O;w9sWTٰ*g'Z4xf̚5/{/8kW^! @0KcH ~?DUUURC3N/?'CJ!3cJevu*Yj!FԫafQ nla9i1xpzeH+2FhmRhaiT'*|l̬7Fu:v7sd'rԤ2/ܛ>?{"5 À^'Op9u|w& 9`ѿ: ArM qnM^I@6 :b[ayH;>:DZRYbL JҀQZ LB@XBcSi_Lt9ZZ%O,OjU;vXqXߧ̟! ]ٞzcמeuԍMw-ȵGuTu;fΜ8 Ҥ#`n}/x1fpk+ĔοoiI~{ 6-P5+-_S|?^y&l8FE-MKq?7_irÒw촵9'"`/{:x"{h["up"D۽3s!heN;X Ӧ? o}qYv^ōxGO#'=ٱnh5z'^DJ}k[:@~zoNsś?Һ8hGN~V$ʱҩt{ӟ9(y7MpXH&ri;֧1)~!i"zA_G{K£{3\=pEVvfet,n0WM5d5~IوGj'S3%Ƥfw&_.>bLv L"TtM>sRK V leL'&.$"h|ȗk16jla J` ?iveQs3-g)UO0H(utL-Z[0LM4-խu|!_7k=v_9-'7ڼiu 䆛#-ЩLH\\\UUU_wwm4+2R`HlZٶqŲGƖ1nj3}yS0&HT}[n6 MmlD"n=.}e>ʝi"]M_\vWz,U=?Nw撦u)r5#[ENL=ISxyg'-$m0ao둣Ir%|L>gsڇ){wLN0'- g d%ofQJMMMM{p`,3SSi=xgh|XwK3gB5?g nMƝT}hjmpsx|3g+~z.)m۰(sPHKcK"#Os6ϝ+1shN[;K%D7\X7v/w/4NS "noV{xͥd2I8eTҔ$4ےI}0/B{ul.D -c?pXUsQf oY'u.K0OZo?ow85◞~iBpTTI/|xgA6jHĩ՜_/_S4j!T`i? gO<%"7(=u':M=_YZZ '7}uẆycG4mH[ ɋ! M6tjR@ט7NY|=WOU;Ұ<[ KvѼ;Yԭ6Q_r9ήZ3h9/ kUPXHÊZ))$D*df,mkSpuW#^ðyzᇋ-˚ӦB(_yhֱ|w\ lf2TH33vP @DmbQzOJ9ܚo}_֘dW.3Düc}JMV% eXt;_)ST$/,X_Ցi&TG@˱gfDT_eoj^A!cM}kll6Ǵk#B@umưo#?mvvRӖQ]ׄ. I{<'/WAkww|7=7 f$= 4B4B ENۓLn|U2 Yg^/ORjW5v-YO.fFnLoYҕ@p[H/y+ȴV8ip$->g{S\ Sa` 3$i(Hqׇe3\|Y6,/ȭ9XV| /~둣cůla {pmg!zzjc}|+>hĶ7U{i4Bf޽`2--8HO B/V8z۟jFmۋx… 666/9 dCx<2&yb5R=wm|2KYwwE6 H̤n]qξՁs[b&-~5֦&5'.ΫC +P~ySh_.s{~z^#}`&x73Y[5#|i31dbk{/~իWL&9w@ H=z 7ܰZJGd?_:pX]سzu27ߜ1(]B#1Cݳ 7:xlGqk  cܶH{>Y-i_o?;&p( f$4k#yM9>&fFŘ$[8gXo`*[ZZZ5 Z4z?|,jkqik"ӵg'/0-p`J4ioԅIt \e %bM a+d1ى8iRӦM3<[?PJM#yt)ZCiuѓ4{;D(#@&ŵrMU6F{[?p&+!O~[[o4j8 nxX_A_5iEcz'\0c=p+:gggug ,; M[h&X*$vg0wܲQ7# {B' ׶_U]7<[A@0~4wYoݯ'czQh_BDmD"/5 n8/Ncj Z(fE%^Y,pGDa@ 1BJl׫PK15QD$C\۳*f!M:|B!8kɣkOkXAi€Fb(m$&d dHAp\) <>7B&]__=`!Ai~Iq{ΕΘR #D俤͂nj|ܼ f񱡲\gÂ0<0}1 .Djr27 )8D5h SKF}н s U~d &V)(e(&Ot}i(ck׮=ȑKOh H$666I&o1 WزzwGusl_lٖm`c$ "b't  %ZP B A bYޫluj{dc~{<>sg{u.|]pmu ˙-)(84j5p92ۛsi3m #qnXp$#!:ˋ~ u9ߕ7ltEۑ 3A,%F ӋF<>~__Ss`!H/Rtgv{FF')NTR-e%Էr9<1tHjA" )|xFf{ެ1Sˆ^?J#㵏W4t++׽uņ΢c_~y<++˕_6nz4;,`3z!IW m@xxRBAPc~9;rU*o9}7 khhPGLq 8rЄ)X}!i]DR$4 >*,i,xo͋n!zn6|ӵ [S$q?Ѱ|r39˯%}y5=n 4`#cÙ,Mkf}8bkx'?Yol alI (I e6 r'ggʃg ð Ld`bgpƠ@moն D2MN,t*7^ y>aq5n͆0M(Mx*2ƏSQ :ac%ՓJ sg̯z&}? g1I筑ґD9MfCCjBIJ=SA!|MuvaIg Wf: 56u˼ûBCqac.RR>J2rZUDVҥ^0O*&(&xYVVv~{ۄ *G]Wp5u饗+pzݙ\_!J/S)W;O6&i+nYT5zjQَ\Y( {W7D&LƆeIyqFxK={)XM K'(J%1R=4+7{B-×LlGw<7Ό0؟+~jq4 trZβ9gl]o]PA.z%:5mKZT[сC ޮ<]?J ës,<)l7+wݎ]voY-gr r靦e;I asLdec&t8ᾜ7a98Ӓt1D}͇9dTD$d3*-[=r7zTsgXѪQamh`# g =ה!|*3.c3ڹee dN'n'3;rdcBU>@΁=݈F'\]XNjXLKYرx`TntŒ * P,>LtP%Tul G6{ QR>x*A:Sťq0;Ww6?Dcc ,\_/rFwQ6=bYqKk MP*ץÑ&ھ:4hQ[[I 5r+_U#KD^6].H?Ssp 'PȄrCfׇ!gN_hMw1ܟyMQ!ۙSd̜gmömxu´f z,+-8 N 2ahY7|FWL~fmA҆lx48%_`p$,q n]gH%LtF 'W˯0EI@l> A҇+C؞%l[MbK[ڥp2I=f|r_iuTsуI^(ugg@!?&[)^u㩏_6~_R=u7'Nn*(L-+R) NN>C]}OY*3ͮd$Iīvk1;AfzGawq ݀ xuZ`bR6=`|~r'"O^`#y~߆.kdJYJ&l㒰Gҍ0xf HKq#T2atz6B⤖G+ܹY9ɕq&쉅f̈́P[| B?VQgc}''h8.=]o(,5>(,r )UO~U}څ>説,ܒM-vБu|G޹s]Y1l]1s XRʨZ=羻tYuJw ϣ~f”3|aw0r}sI5ؙoƤ # S7Ȳ, &xu<{ZfXBx8G0Y D[wJ:}l(KछBxgw8+Pfmgp0d+ԃ632t{m8 )Ynnh5[* cdڕ%m-9v$.]Lmxo'+:zO SEdkoo`Ʒ?olhn%-pE`;v9^(4[+ 1Hlg+XI$$Kp?`ɸ9aB4?qznP~g<)_s|Mo78ȫʽԇǟ' B+>uh@{G/uW=m#Sv "9>9 /(EBOBK3{CpfģWj%Ƕ(r=I KA3F ضmx投XӋ /~]nA)pXIC9q?{ H @JN4IFC{R6ӽUгvw lզ¤v`y1Y)uͱ?dhJPgv$“MNհ5v]t]9g4" 9"} =ⶏA]Slg|J!} LRfKja5T}լ *XeqK:Lq&hSҏ*AgJ $lE&Uri8cնAU3;ɉ{m 0mŒ <$oT`Շ3?}EޒD*a3EZ2 TPLA 4e a&>f);W/Ȋiѿ@# #LPH^Gd OlRВm]L$$$)X:f;H%`b <'0DՔH"qε\? ؽ_'\'݆&ee BҊ$Zyukk;y]vn0 ?xy`̒r%x,&WM5XSS9gfq`H^F"N(\x4e*;ϣ VuGxo 2b;t#?|wn a#^CsUV-u+5 DsW5\-=0Tv~!)9/o1{[3ӟ9P͡f9J)+n93WWǁsT?y$.i'Z[~Sgg.]|LÙJie==zpbW$[$!=80BR6] GH;ܨQT__/;K)m@iFqRvAِX_Հۙs^P&Md9J/ N`㘹ZE俺6uYiiF7 #0jwm*x3xH7`3n) ?!Szw;"/>ul5 N&*~0v:'z-fvJ\x"bv4>2U^(A >[m޷v$^YעqcX-tX19&tJ_3+#|<+$@'xI1lA0 O}Z.݀˟h%Cua:l|VKEhhL3< mf6-3nk9&`Ҁ'؞uݩ  ۺQ)0ީELzzBgŠ fi=BB V &dlRJB i[P ),JA'99@{KÁ8]`6,ApY3ʽeʖ$iAB %H(Br%RIHxŠTRI`2yY_ ;kF.R)SYH%I]|U8P,J&',IRBB*%vlrOZe{5ozqnWhݴg\lٟt|mۚʳi$)hp=SclEEzFf g#DB`0G{{/_C7GHJ;ެDz4!~TJ~dKn5s Hqi=yuϟo7^8TUdۺk[P_?\[${WmچIӰr8Wr{/'$^v>`Ў( `r4{2644X/t̋'T'OLJ)DG[={^傣XwG#e zfcRj}f}3f>~߅ښSN[[;WfOOiab۬ߎtkoOw;<[Ѷ۩<g zwWec#[*OŮ Voۅ'|%ؤnpeXhD^Vd"n۴cKGfcccg}} a:}7p?%a8i88- -~\4]e{cTR)d8 G5N.NԶAʆ_g EC;q~ND:-CNTq`&6u=9,$K5YBl7֢+fb(e|e&] ",{h;^InaYF^]ShN qg}oDJmY|+6: b͐ xvEBEMi;uH2_H4pˉ%( UTAYxbl\:| 5{ ssbE=:dX@-H L DJ(ۂL%!$8,ږuw@܏1f[uk7tP9,tt:.b `p8[PS0lz KD'Рe34_ǃ5B/OWֹT](|WhJwvǺbq-w8qۗ$Dr25.k˒2ԐNF\L!Ñ0pO|_OKYL.s[2OKnQ/sal4O^ӗBø|#s-#&S Н%/g5ߙbqt)UEc 4T3;+d86ݙR>; J)OW) t(Kd~q`?`T2eA*d˹ tHißa%'T.Gko"VWGRbC3W=6z׬WyU+-CKʰ @)1%yhmL=wGm^9}׎6z2hR])(%6콁ؐJSa=SrtzTwƅ/M=.ڗ?p;+( H(k7Ot}o'~w|eQ}#5.s91q4B@}.|&C5Нá9A9m[F4?o6qR)!l~'nJSLKp4ENC_?;\qa#C E  Ƙ2e/mzf! 4*eo.7lm>p(S0];eI9хp/IdI0ti_V^ b5, < d28qdׇUََu:6"+,E =)OH h.8cՑĈ F'CXzIJ ,hذՋEPش' (<%Ѐ[`Nx8fH7?mt snw48t7o#ofa`p. *4aq08-&z@ )ܵ|}_/ԣ ǧ6A2@IhPk?{:׷=>=(Z-PhS -J5DӍ^(%N$a)]h!p'&:uNڨb-b)@Yu0GBCfJHehL0qM Z4e\SG}\Pyz89P7*J6v8kipi&2@JȃS> &'ﮈy9|iWA+<4xM[E=|79}oȉ~&ȜtxO=c*kĝ7>ݿ蹩5S'I.#?m/.~{L7k[meg4V9g;kؤSRs4G:,0~1auXnQ )L)@R@2][7-,3o86K-1[0<N!4Hٶx=?m3}ެID)0Ts`v-d ;ógMxdk³x m#o3x3ۃ,(.m{lcߟxgFm9Ms;R8G&oxK8OND移.SLnZ"CcH@*EǏuteTno]{Y@ 1ˉCX}Ybu[JBj>HA6T}肗>g3o^fyJ)$, e+d !\ezw5 y~^0㺛F_ `0AA RyeX zie#o:Ī]qGqvtk]<ӯODyB0 l?ˀ|/ҁ0g5pc?{npP(qti[JS uylIrkBW.Y L!eJDp@#9>ہ& u;ȂW8{j/~{ )t8YН s_GϲvBIgceOM|`{lR C4*w|*$ii0&Is>AI}Q}g`l \^ `oߊ%O`}CrXF (Oꎭ{雦9Fۍ߇:z #lkNWG]_{LݻQwksF/ o?Jd?Ѕ&"ԤBu/:,(ӓP}Wx~fp0ge'zmnȶRy1c:r϶6iK 4(RJJp̟ㆰ8iwzlIwʯjo%y$L]̒ [Lx+'[f*R%Lϖ-e7m&\tI1Ӗ{}sWj; v-gxyﰑns,[XJ

~#ٰ˫.?k7!U7*U[Z"XeJ@Y ."U`1A2_@_o RЕJ٤Q&`˴N HiC,S kQ+qtF0@`pʅRQ'D~ŝ)!M 6gWJl_hV2s%wu4;]Lp\N P3T`pt-J]] L {(R5͡'yюA3GgA4^Cz4hb{e-|$0$ gl,eck Αb8q\7;:,bǪ.~^||ȃOiH* : 31RII3_gs ǮJC@WE%pӳn< x7>YrCւ '.zrSId)@o$IAx(l56k # 54fB!2 #|fl]'X Q5Q}竿iy5u0Mr_SG7;h#YY0q-k'r4iG;uv_S F!CrIT ΀YR) K[" QQDž @d^&Xo1Y.@p=0ZCRq0^|<=FhSi9&iL紷Dt9e>#7%KHA;&wE; A: %Ӈt"a"59yI_޳nãv$Un֭J-{,u{I*{:i¢~NH ߕq :t'9pӹ_'\ H$&(u947{//kM+S6pB\\\s`r3 sȧ?s^svcx eg_P0t+6X21urӎߟfa W=N 8|OZՁDm,dR\|@H&#zd#G3Z02vwaځ{NL\ ЎenqVLiRT(_cdڪl;{W G+`O7w35YD)fַ̮5IBa"f ΄Tx>̒6{v k\S$6FTiB H67v& d8Yhﱱ, N#f™ iKR'v?}UKgʣM1WBgQmx\ MV;H;S0Nko5~x߫B aA^ٳg:믿9c,۶y}_?}k;j}q54U:t[Gei3 ٖ楓\꣫<7uDv_k?vJfy%e O=̗Hmmbmܰ]7c/; !dO%Zwn"pEQ4jU^eoYyRX:-IKaY8c*~O=WoS*'y3]^>Z꯮V5yfT)~yjTǸYΊ6Jn[&k =^özZR׹HRw{m'A&;:wqP5~ Pb AيcD9|X RP`|xR `O=Wj qU+g3R#0o?,`  @RJ/csFh jnyL$I[|ߛ WK_3s+z){G͘E3C^/\xܘ_i6RDHt( kYUii gE@w ߙ.eK4 BZA6U͸ݕc/q,GbAk+bdix&ȊVL:_ ޝo}C]UXށ|%1qMM0 AUi ¸) @14g/Zj@զo0"̲qHHxL)%J5i*=^zۂ6Hۨ J-\8A$vr"ث>PS'C>8͡}@ |~Km3è~WKB4r|.SbGR=+dQcucz\]cL+R4 J+ _9>_O"bf#/}4\`mlďWb;I/DBP&Ϻ-MDR9zMDyWCڻG<\ :bt0~X,FxOd<_')s'awkgERiX3555ibBs2XԹ#e *oWGoŋ tUcֲAL`de ,K/r]ß_.@IXY5O]wjxݵhl 9ez+$6'֤V"pH p"RCJH=ok2 (SXI':SSIq1S)"6Wf.]  Hw -H%#7?ʃ+H$Wq3w1W:D1 |vܡ7nJ8~/XIݘ4}$X%)pџ ݛ㹏v 3d~ 2?Xt?!@6xbkC I 0E*f)JƏ{._/Jyxma0~0`'[<5԰2ǫ?ɵOFx[;OGzlݹ'ʫY#7xRkW7iYWuT\SR+bk0Áqt]aKHh1I.#,.eɵR{=i B25A-T8#Lb-S_?2AYfϞ xwKt]jsxҿK=ǥOFcDLXY?nieXeCNp/pF̘O!pao5؊֬8gkomjPwh>hp@LDohm[w*Ѻۓ)KJ2 K /]艼 ͫn/"ٻ1/s;/UO1zcQR[[5(`cLb%)WN.wE)AxY\r[K?PE;˂NԇkH(&!FAg*p9t.&a#Q? "qH,icy/xM>J29rCW)N+= 5MRP+(_Q2A_}-`Z d1ZbL!sswMh  ,Uq so8%Uyyڅ+N&8.ߔOoeccֆšv@_ SOtJJȉS^VZq{NNIY]A/kN7L%:ru@wWґ#;Zv|iƵG_bھW >.t[viY*dp:2!%?]1eʔt"HL`ZJ+><+ômH~~9+exغG'BwJ;д sWnlRZmP"BIF@:5TqB;&M!3:b)ޓ7G P%fԻ͕W*mK /u2I5$;SWG* :Xv^!j.ΔN^)wQW]3+YCZ30ws .2Ҿ[h4m3P44%Mz n)_:$`x.p HiKbp}UWVMA1?Ks5g|OP0Gc V|xدG,|f/T.g7 cV4)Bٍ\]=Q29aՉbH7zmmw ?S >{@D艙 ppN_u| EbSVN<ҋu;6#űեCp\SǍ? dXDRn ur_vEg62LF钥c$8Sc'k-_~ ?-J<>}M OJx+ß"/9fs.^=@Uy߫))϶ܲˀ x>hs 5U A8:&)RlH1@z)DIKv2 $$)ZzSfT~U]iUl¿O |k)m ,(0Ҳ a%I&ؤ5}}{l,]fJʺ{Л&3: =єԋl^J){7Fy܄n< 8y0`_(ݩ~'#D 6ubxCD !Ræ>g^S8]Dzl8b%EJuJ>%RI8A1Gaӫ}Cgì}b dJAc!$4w>*3 a@/2KQA)M"鶡s׼h#i8R(-_fJYhpy&b kQv הWo-Bq쁅pK_fVNtDI a6l%R:yÎA|טv0ظqCW~0uep>;>",X8oTNC׍ʛ'X0&tg(S*g$!3v9Bj=$-QnפZ;n$n4«'*hO ׆(%CM~쇂hwP㏷R?fc67K$$!恧vˊC KS -e)H[1eA(\`Ld<ɔY_łELeKbҭsC{U~T>E0X}=kNm%;6lon×_֨BwGuϘm߰^0O `)k?}rПDT{]N0 lRJItFzE²9so4KG1|?60 |;$Xsy+].n>/$Nw:nxˡAvPmpPRALWfx D҆ޝ}QBQ1PGx0` >7+Aq>?wҔP@1TV}wgh_x_ㄮv7ޒ6lۉx SF' W?Av/!oh6tb՘ș5??"D"%ukxSčOm#*;M|tSX\gc:LMv+tgB[KeI9Rh+SیaH2"R l a!ʫ`]%=@aqi9裏RlWNjgBmljPЩ> B12]p49t~t&K݆+#XjΌXh JPԈ0Vŷ~k=Y/>vԱ> 跭ib[n AQ?ELm/#b]걱Oa ?)(E]:%0c(Nm)"|.' Ɂ3bPdJIwnq >XXK ?ؘ:CmU&Ӊ icWOsPbKK`C{Ox/4JZӂtf恣Eͱ^WMDof MgP4Twah::MS pK46us.a%ƙx>f/I1 soii=_b@"i"AUY &VI;s NJdClz%\gSmVгPnM*8L߹2)֛6tڭ`0H R+60k/Cy2AGޓ}V{#J8I^Pf9*zҍjGٰM7e45+Y$N_q=EaY=ԩSMV}ss$qοr+7Pl%DDD \6qQ_>lQ_}\٦RJ˲gipM)Dw02sR:k754pz-E~|PXۏ[UCTi|}5hnX#Tmi˲z d|-+J  ?^dJw9E|-{w_{?/Ip*{^~ ' ښY!M|AРs5ޘ]:8g"i64=mp@5aVÆUfeu%~ڵ[?S T9 e* t=Ue݇kLҲ.~F<>育*jE_v~xYŊJIkWm-~$hL# }F?T}ycK\eq|ٿs#}{X &Z3}}\8@yWP~ck =FR*SqĢQ!];v_$vFkkW_K^/~vdch-ltƨ㊟#&l,3g&H)T7԰||um>ft 1}]>9ohw2' ӉX˙&$@@u0w*k5^ڱ`\ղ2ҿ`h _@Kn,’ewmΊ`5  R0S0Fo~79y70iȇ,J-<%â񇍰R+Qa>8-_44wmQTý>gNo'/CdDzAZ31KWy"}cJ@X,KK̸*h?~+VǮkf,P􉔼_W^XO~[WG{uQ*ȈB2 a墻Op8:g.FJ)$-*(oߺutv=K}(e$HIEH9H_݄-o V_z1XJEGmH)cۍ~~f0N s@ՕSWmڶܬr2۲Ʋ>8%Ah1J˜odx_WEgDP^,/\(!moX(JQټO&n^ ;i旍ZJ5-O%`3 ^5$ bցߋ-\ۃCp36z|?.0seLjJGh\Og֟bMɾl.k޽eR#b;0r\<'#3"ĮN3Q24>d4/,k(״>R,FO@t=tpQTpG:yOBR?F֊Wk%vEEfW`}-t etS [zÒ<7Q| %Ljp`o}͏Ȣ TGzH:w0iDFV/vOgR';v\TUu;tB"R TB|(JʣlS}sl+n3DOy]^Tavߠj MCKGKBTܲi|ӸG4AP ؏#-yPEJ֮| (xK$~6OOr=?\4a)eǢk_kfuj:^N;6pA4$n\n\#큢P]#j4kd|cȀ$Je*+4RdI$Sbb(5Db5׷p=`P4zV=fLm{%,2*mon-;#6:y[:kQE?WUϮ8_^}B2m`RN~rɳ_| \yTJ@@4ۻ. d8UO=E& /p+(oSDN4J~_f+OFԸyEpqrW.y8L] +aI;•1pq3*VK=ërsG?_͑Wi̳r+u1b˻Jn"]Tqfg;˥I hr{0'{DϞD4i[m k] $t jk|(0aH$"sNR3z[U8a>z/90 BNQxGh=؏#@ꈥZ/n#8_5b q2|@ F:M!|ht@Q DDWʻٝM$yɮ \|heuW!Q>N̛}AT i &Ʉma;A)%gJYo{:b(4r @A`7 RmK() kH bKQ9}#A]b#zt('A "S(6xO<%RRna y^ç)Y \9 RWܶwP!`֋#rʷM T`V``Ff{K.9}!l;S6CP`40WwUW:3CWnx`A%d5lowŒr_qQr^:~?)vFxfzYiHGG˫ RJ}gj(F4РIG$ԁۋ>;)),!鍔in!Iu/(5ޙ;nE8hEAB9ln0b $,;!C Sj2Ufe՟{|>ǐ/>Do?|&dZյg˲XՉBoج@j}~ %*JCfL+TQR9B 5^)EJwo+QAy= Qeq#wAd1ŸHm^i[yC&{wW1TVX=oOV &|`6]t~{?eVˆx\ַT4ڦ^ړ[sF;RJ "xX/QHl"pxzetU$Z n5vԴFg"a#8;ԺQG|uxڌw[OwԴG8;:ΨN#6Hѵ ؉GR @#65i5MM"\O" -^^P fPH1kKգ\sJ[8uw*{ۖECF7_K$"h * hPo/++y")ryjj-+Uw왔}It,iʇjcԨUcUM™⃝)$8Os'vx3'x{ymN,ZG8rj:g.iNM\J]FeGe3܎,C#J4ΙCc68,.ڥ\'F9Fģi=QkvN)+I L{PЈEbbw*.N+bO JB߫YhnA(6}]N~vȉE19 X2_ް5 ؎^g.}k-oWCy㿣s]qoaȔHH!Kz`m"3-m+܎bh ;$|`}icݽ6m%?<ǛWO?O?`m _z[CA%)z1#u?EPiDd#Rj<$ZU pzssQ -|p;]NScNs\V==YSNàĢqYs -xd<͖WYPA6=j~ѯH{4r3!bM)*^0rܸ\ջUϺc;*C@ڿ9c5c?}M*8|r&??*N妭[z; KKұL⽑C\pȌ0' WK5˗arU 5o22,y׮g*º__Tʙԓnȟ iWqbseUW&*0 ʹL&V <3C4@ |(>[5/4egz尤eM"6s:t,L2D\;  <¿ 7CKrjŠSlEq$|-_Ce +]U-D=Bc95Y:9?%15IHK"btoyK0`H"Xb)G>ǂi+D:U3%EISe ,[´VZYpj_1n&AB5oWGz$P@nS 뢏)aQ[pp9 02N[5MląѾ\Xm*2ÐP* H?7W.TǿTwwb XwP ~B_Jhz|cƝtVRqN?mJ!\b+_{]we (! mӗHIlۆbo5$`?yS^+yuJ`Ҷ m6lJXP–$-5_7ox},q}T$"80%@fP]O<{zY?'BK!!YKZUBQع_=S,沄4 AÊ7_?m(˱||ꩆG=ZB?Jz5-lMBEYA8%6۱qkS类HS/ ⿺OzMUY+4u2˄멧ʀgIlRy6A j.L< *-!VA0X1"_U\g*+eH٬oCZ|_7A穢Po+/m4MH3`Oonch_'_e!c$Dғphzn}xaB!9mG>;{G=^Q=9jl[4/K|ٜgecsm_ D5~x Os4p9eYY~2E>3ҳ;sΝ;9É8啔҆My>ߙLf̆; b``@ qѷ/Us~guߏ>,ږU/?uiq)Om=vn04TX-̚?r3J2@W^H"' %mk􋔫S[a$mg(Rj@IU;qVD>@afB8;[[0'l/?vsTyj3d2 d^*HM8T4D7ӵުI^(vTiUo 64ԋht(4Bu$GJቷWC\<XaW#QL ϲPl @>~+4qشLӨyx oΖ C$WL'R};g4~ϯF5Ff6<²:+cR"{zv, `юRnXI6MZZ 'D\|Ewy:ױ`ݒER@H׃;;$ Z3\J&7mȤkuUߨ(G@+c5 JInR$^Ε_>sgB+r]8FV 8ܜ{)hlH$"N*7=&{ϟqКdO?`&rfRPl*3"9e*{둚 w/8G" zZ)2q]x pt1^ A齾֒Y|nESSZɞsnx)[-Б1)yԗ?:&W7(2]>)v xי,/Ҷ e[0j y++g= jNLz XR6Mc1ü] A?κ{9 mew$ uϤ[V2,KEIk޼rNvZl4ڿ `#7yM{v|!2m:v.pZԣ+/n#gOu6>CI)jדe(@=vGD|P*Twi?YPo/ORЧzTv=pXvPI$L D&z; e`(! B)K\} K A @X))Ws\Dp2\gg5AҤ`:g.1 Do1e$Gk ||HHW <ӀCLL E UpTXc.XPoOm1wu7TOٰ&f?ߐw'\#-ChfC1A n*U<`[ Aqm,w1/{>@bÜc#Qza CBK[+vY}Ix-"b:L U#.\SbjD+yh49A=ᇏabAB_drfpSq8a8TB(\0qWxF=K.y$/Н/M3ނ) L~w9"}hE/ Pm1~[BWByC>Y깉Yz#7Ruk⎎ @APƯN:ؕ3^qmopnjX, KPާb+8obj޸M+,B[FgʗHk~F \_.N|tWicج|[WTu\߳?_\fmxsUOq2$"LYohvTD)o뉆gYAJ ]ߨaq>fCS $ 7ګ$Zb`ld-ErYYs+M Ź" 0n5r Q, 6oK~upI$/ ,09KJ.1,SgS^THghGT޻[7,6FJm6d4Ms4kI,cͿ U]&{h+ǧ=*SBeY^B{*J6|fF>eh63䲇72K:@`cXظȃm*M(OzT)XZWK(T M/L=; T2 Aǝ׿"^K͌mOlpFU`?dA#`rDrH $RK2PbU*b .rXax!)Ql2b y*i0&90C9B:b@2=gjh/w78Y2>6cQZW47eDB2?uж7΢+5RN3^ltzq@Ietݶ B18hOe0e&}7?~>yvE(hY zRi8jGH<%GVi١O|VgVYyWBJieG-`@j,5)2rVJKa|П>0ۜsɖN{- ^oiWiM.JI I MݔQ @%<&G8rE]}MtQ#<>}VFoهwu`Q H. <͟#}txuJS`7xy`Om]f{zt:@TB)HnlFydij2qg0c3[kد`PꬡC xO[."/'ܝMC3/NJmLjm`poe{Vz-'-yP©̞xHJ4mߝtه+zP=D2 >7U`^Y[2JFfdUbSkNDϜNh{^vX:N2scnm} Tr~7ncsYX?ԎV~"z[,df04A"<>O!| e߲ԔC}ʉtǹ}->83K ?Qq]Hnhu "r}ч&MWooNY.&L f/Y>e)=.61䲰S]d?Lc'{|)j[tr a-:CzD;dB:3?!MҦzبz(QA݆a  vo\S$Hk.DY>>H/ě w T0^Fp>*i.2-P{SL$R [3l40iRgJ"J#2);RؒduQeP0hOeu_20&aJBRkdM7Y킳IWv *1m Al33Rɡh~r6ӛPxo?_=bE,&ޯ\/|[6{7o@WKZ9qQϼm#>oJqI=iWf3f,8V/z;s&LZ=`D)11%KLgM"gmF_*C hq H:(E u3GtP+T;0p%˔RLPhmłw:vdRg޿4{iydwmX]Oߩ@r Lv|*5jݓј&JfNS^gT`W9)('\x\ dՄysS}6mˮ˧=v{),.BP_ii¸b57ѝAw ^{͙>cƔ(A)q+3ƍ׍A_[eNIi5Hk<ɓmz_ׯ>7CM+OnP{ 6))­zϭC*9 C[~ !2=7}sڣVA.䶬mO7~ZZZ4<ў\о3S[G;PnR[.0 j i(z3`)fUTFn"NcNGSPppR < ?!EJeI TH`wy 7N|k= [V~{&3}6sc[>+$1l 6^ZTk*JuPq@⍶}L7>84edFd;KMж]SɌQv˺*>88kayu ɡ') 9}=]=3F"8{r :_݀[Z8~l3 m\?6 &; (y0)$ųL=j-ׁ>seAyrYCQ]i*RRUL˻v]BȤQfn;'[j| ȵ (fA g50]1S ?ۻO8= 15PP@ʕ3Y넣>ZĮQ_hT<:;{VܲP$:vDNb@BO{ h8\ xYˬ*&jZ=-҉aq}:; B,j>{:"pdp3 `P:.XR5K-9dYfl&jj 0kW;vS&Ly'DR}]iEYMg(8 VP +ݠP%y5K7?7W 8WBA(/u/b`(#񂣧\4ȹ/L?.Xe8j==iۚԍ潷67B 'ŀP;COz' âCɻ(V;"~[$f^l fO)FE$Xtv3H;H.q~5mZ1̉>X?6aV C[G +?`AC,kXXٽ[&@QE X^2:?>O o}g?X|s^@ f[=/DZ>ǝhm7{1;v Y`!_x'uheZl[+=^An]06r۵0/@cw `7Fu??Kr5e/E*LtMIgoe xI%ofFqFO&V~NIv nzq0*ヰ{ )/m{!} PI(mx妊Ahj)%9Wm# ko!PvnGp KX ݿl!55 e2 d̥`fIYkaARp'+KܛZ[W6 Ih !@_2CH җaiLdmе,}pA<%o{0iUs0gd_]mg0ܞ+vΛ==<c=v(ICBkkd&  iTyLTS :tR_W?{aW3#lT9ォGPϘaAT RJBDzO[tsYdkιvvQ׍o=rĖAذqڝh=G""V3;o}ʘFN%4rA Iieϰjlbp] DQfPu)q` (F$_Z .@uuǏLy(4cQ0s[ (,  ām2b H-7oگ?'|,X06ߏl6 ˲h…Xh5kM2Ed2(++Gy >x$v΋[=ظ-%e .Jch a g v|E `JmbiVUvc~΁[ł'OH%մ4rUd}\}X,>Y5@mRnn 3bD]{3#ᰎD"_սYe;(s^v '"(7/i3 Lo]3jmI)ځ۽%?2z`!NA^~0 ýpE%[3ILv{)=;(p@ \,h8$Pp(pr[nJg >/ Hh C~׽2̕Sf?6'ʕ+W^ta!ԧi;V.$ dw h2!L ND=Rzso/4&gjM~c 7qiwؽqk6 kה27;3{ַRZkH€P11J,j #Dƺ! *5;O=W;SN;oq$C Fw&CJ:n ~%'\6嬺`4D`Ս{md0@lcRi)UzͿA߲g V^9l;Ͽvv` ;= rϸhl|3tQYaEBb 3ҋWpGdlK\XX> YQEH(40\FcI1`斣v[\j>b1VUUEx|Fkk+z){O>.Jܲ2g.b{r`~VTdʅONe kt„WtBal,fn6s7G^lRCor^+(;E\]mՀ'7#EMqdjչxn[wV/3bљ >{0|:w}?C;y$3~AClިnp讝^EK2W.J9Z3Iɡ^?%|fNN{qeOb_k6͆m;Y6$9$ Ö34&I1{bUf0Nql-!l&劢~3;|$:]X7- [10r 6WY7E=wo#ۭ b-%r̽5S3]ns ] XE[ż}h i*؃RGpq_6DMM;ig(նMypX&<&$6DE90+ l!}ǭ@< =[Bg/ 6Hoe+. (zDFSv'Ij*P{V_5ctIMlt>o™C34Uş{hw>Ydy# #QrU^gб[^ T,dg\X(,:xsfaY pnSӴzu9-x=AGmiV)1HHMj! R˓3:zٺk:'U3ɾ#Wte4D4bJp(1JgRjiշL΍_<"p~?HX{(jͱE{ͨd0SHb)LEXFp"?^sOۆDv~2 '-|"fNqi|x+@m W(?q !@O o&MUBD{Åv]@saz%@9V!@z \^^UXwx-OKA$!?aDDKKh0-&.5MA|QN4a(sȻw9Wo8@;G|μGqsX \#T/z%BdUgK'x} ?Ku|@l%w5OamZO0y-v*^,a5qS ~?zI\aP[/>gK_t :أcny'nq,MB1 -@iѶ-vj'˟oX9Q=0my5?d~ $ p}{x·eS?|ˢ'#5(Uĉ?lwwO1~*.f!qsQ̈+7Z ,;@I?> hFW[ / }fagZΈ7fsc3I_RJ+lޑ:dzrJ8#QZZD"eY DmHoPB#n 0!CqgW3 j9+21 2 }mIB"]j :4|'h u'"dso__zvrJ<Y fd zF+زųz8g4&n^g;kisG0G;"|G13l[q>L&3qCp!ਣB2J)&"fx+58zwY rd}.3e.epF3KMv/Gq!68d o6k}ʤzZ٠| "M^5! z(eGcI1w kMj^)„(o.ދqRWM?F 1o"ȁx5%M&Hߩw{ ? DG2rP3^4fզ?&\)3qmWJ"3hO~cݩOrۧ%Faq[rtym},2""&=,RrBw~Lj `Yfwv[kX?ʵ'>?Pah20-lځS0AiMYRb0o?|>° z /ɍ׶Y LQLuw4.mTX IY+C9/W7lpi^%ʕ6yS-i` F';ZM䴧0e)[Ӱ`/8/( 30do;N?P ) ;-`f&ӷ`蹻+ ZۻM7ZB\Pffp\ .)4DԢ3{37[D՚ rF`G-`MTJ-wڽϕQ 3mmܴiQ^^:lڴ RJ|>ha"J-{=ZFDo-[D a|7tc&a \:kMBtͻ3;RE4E׼ 룰e,&@*.-&eṕu>;:!cA4/[|ɝ >7id' &v 3f6?.1sC#=kaF M2K㧇Ұ\GCJ3\h~%Ën7@x{)'9iCK؜ahlr;@Gbn ( HVGHB"HSnnGg{a/ *-iY23C )Зp  Wkf!)BH)… _t, tu|&׌ǘ?6)й;TmȮ] A#@2)mBVcvvv$?𣏾Xk./,\Rq! spiIhM7O,*8xMZʌe;cI^!ԔQtC7VqV.Ȕ_vȹňU Į G\u L^K&PFʕ!0mroIFc ٳg*P̖G2̞^{^3}HP{mqQ BRb > B2|E~Cq8CÃ5ٞuYz{\aF؎zviň^149 F/eq-r^ 4B&9KW/"H[ mݞ}L"o+9gw)ϼ^ݿݖ􀃡-+УnɡF~Y`DwZDyJ8;~Q=o ШΞ3c8x']lT|򝺧|bBM$[<76p/RKM܏f6BjqWf5fNs= n3q7?)]ҫJ |ilX$A\yB-^$]2U`ӵ];۷  vʏ!ƎFq-Kgǘ3ۆ҂fw0tE+mȶv.Юu6VV^)Ĺ-n8Þa@ C"°NjdC@|89"?Ԕ csf !Rr·vJ- m8@Z9~Zt@輠WO&!RtJS:zv\-+Ӑؒz=XFr1ю|G#<{5;4Oʱk+{{cg(wMڊgUiWlȦhѕ2T0N-0<6G)M\4bkҹX3⊦߱8rrx7Im+%43AxŶM;{ή M&Ѝ7.r~r+qc|sZuUR\# ?pO fz2=RP8!8SUb7c/&,sϥIN =%jF#c׽߳%%9qUe%f5*Xg8uڍݾθJ`_QI͇@ . Ag H$J|Ss׼Gf3Iѻ>%J:dګ'4L2WN=2ʶr{s9oJfG,q d0 s#/k{#Aѽ'Dg /Hmm7٬3g~ f&5LDq-0^D"bwF;7"7?V7[1   Jk[#n_9qxO?i*dzPg!ˬv_K6y1(ωDꍕ+8S})VՅT}kw= i3Wߠ%!5j|?X=BK1(z_pyr9FRnrb7r~+8/)fH "B:_u{݃|;==nXhlGw班p =};o4 ]XZ{m8xW :Taxm4vR\Fibqwi( RvbBx[ `[mfb\~>>ٴBCԒ R3K3 ؜ryelm,\乙3oΘF:abESwqٸwJƞ8c bRif4g ƭ﷿lwr H!sJ6g=<>gz(}NY^ޟW@$.7p; w: }W7uwW`>/&]f eL_6ƃG P̨')'%4䚵.b~xL,9 vSz~f>755qSSx/cf|4⑤+""JM"mwW\v \f ߘR!χ HbGj BK(-mqۓ͍?ud`zvjG%3 U=㼯tcg nŀtt7=JmJ=Q+uWu璝\8͍|.'6<\w-?\6|̵7o{k/BDBg-PθKB6oǚ -z X#P`($pw? D|0>MM//eMY: qhJsdE ixEL ̰(; !H)9D3DK yC7؀=Ɇؕ81b]s 4{yUyuضoمD^(^K/LNekibZT74("9 ІbU~\HѨ{\?ПmvY)RLL~1g;+b* Ji^km/MMf1}鍙T# OY\4Rdl# Z{a4X3 P`,xDV`'Ɨ{f#ٙ˾L翲h4׬~+`/D15bչ3w='83C=mZ*X8DFT/[}J3/ <о9Ʈ/G韸pkzO#m҂rGB_9q"ߑM:uA۷ZL--E"^?kƇ_9{]}G KJJjRRJQ{{+?a& EbYcI2

w UKoݥ\:Ӟ窹9,WvSSCnjiu=e<;5~Y7[5#?hq-ݖfi~'rn &"N7c}{5sǷZIDATߥѵ۳4 O7w*_hݩxr %mH#ލCozѢ]E,Uv:@nv%*#$(IQgh L80zo=03ypVgYwxx8d,x0.J P= nͶ4Y~E,Xp/t႖9eBA≄vl裏O|O|uN[rv"˲3 ܲ,IDfZ)ǯ?'<_ljR\zY1~4*kZ8Y$7~<C$B zsBsA]޹Pqѕqx< _G_yٳ͓hJ5w) }'z׷&HX5ٷ5uJ չ>g\LЌb{oo?v7W{nlX ξύ ^j8Y)J!?WЭ(1]jnnk"Ǘ=R}'~G6mڸdS/9nxgϭ4!򄆆7os}y_DyVpessuw ڹﳿeQzCS}EW>}\ WG">{\:4Tpy[[ϾOz|C 9|K _{f&!3,aoצz[Vlax̉Ƭپn]{14+Q)A[q`Yvl'~qzc^ Oc=6>0z{{"9򗔔Hu[w9K>h>W:Pk>o?e`A}/ Q+gW3a'O'kD2e 566␃A<> mmK6os?,ffH~#cYQXx_kZu]`"Lӄaȸ.:3}}so=F]ԉq/>Aj?$|lCZdLCQZ򼚅#1/ ~wڼ1+S`A^uY SIgH%:d[`]nS}'獫sڌ43:::PTTDRwW'-Yͷ]wq٘w~F??mAy^Liul 0cqg?Dﶭ@NJ%xeƵ/|Fow m4O~wIcGRrJib$5@R`s?muq-+/!DD]]Xv33[3Q'|?ԃflhoze]ZYC'y6O>̓o[ז>}`9EN_=ܺh[]&'/1ٟr+{㍋j}r*riv'oݵ+lL p}+$R VmZ;GmY~%Gߺ7;ԉ>~ jcõ`ۆ"Iu5_z1o/G<`Ν; Sۋf.q?EEE())zoꫝ= aF{5,FS!^.3:c=D-s_'GHĈFkéӦa dbfxLShfzfq5@q*J+H! y}[۵gu=vw>i2G d0 RB"ijm>]3f͛r޵`c}1Jf_s=I~2I 4 l:0en74sX6"SlxBhޔ֔?+t)b .,y,CL(xyf`A~D}e8cX***I!ue[N* .*6͒40 V lO6׵$BDŻ뎺'96ϴAx.q>S@JFQL.|u쑓N GP":&2Fsr8,/ފa;:}ֺu|v3S,^3iҤgg̘q<3cj``@#!Z~={liVZd2ٝ]{C{7+V{gRLsOhъ(v `f^\sA]TVӶKAm 6LJ$ExW=VΌCQLpXb1E|~U p,0!f+(+X@4q=b**ƴxu---_hѢ̞2+WXqTJU ?A.*)&0 QXTLij_qp\g[n3 86Ƙ^;?˼nkKy'oa/pc±F堋c񢚃C]"·a95u5yU5})hG6_Fn \l_JpD0@\WWGDmiCulGTV߶e+5-apVrw*U44~aμizօp,&bpvzco_ IXi-oڬ`bM[QU0͝ӻ苿T 2lBT3 k$v'bhllT/t:m !̼<QTT\iI5g2x۶?/inn)~x˔ WJZ4 M˖usqH;<ם+@Z d`ب Zz=ڒbG>=H$Idٜ6J:P]f=K بꩃXTaރavdA$D2/ s24u*|ҭ;z%ǞyrE.xjXe/dR ՟ ޗ>92K` /$,H .ȶA _#<P)tmu0a^hQzgrݒi,qx/3QHj X]bE޸0$¹ygT3垒rKڙ3[ݍcQXXq2Ͳ?r+TZHD4F'Y FqW丮˹ʥ/z´E7ʱtSG;X, X bşyO͞Dghr\B !rqƎѹ#@G`E:׾:`Siw!\(|'l>ǘ:I V VN9ն~c$=7  (qfo(w%OtQ]H$Z,֛N\2zGKq]}]W=#o7`0FoӺF:,TݱL6_~9HwG@An{-}rO$ڊh{i['-ζAGߵƼ؞݉_Eb.j}8vI[f9(FM3A ,۶zO;Q8hTV J!G^;uUJ`<ٕZ06xpؗWPP@)5jԩH 6 TFqX(םd/[[p8~m.hc jꮟLDgC[BLb~O7 =Sb|mC&{1#1X)0TY~УOYn0m% Po_}O>9}ҤI۶h-(++֭[Q\\03`6RmΤI.Obr <+wJZfS]m2_ @B(3L#9oqHKA_Z{l :SpjӠk?E>ϯ# __?:iLUjayxaH/L ? 6!Fփ%Iz{ K˳^#T z}S'ERUr8#X9ذȤvIG7X3L=pWT.RXg60PSt*E۷mɓ@DЮ ǃB̙@6CCh[7adwUWbŊP=o<[9Jnz!`oepBy}Ғ -z~Ϯ3p2R=b*;!03w1434ᬅ@+qACn6zPt0dwBR2CHl?K y ' 9-Cb j<ԕ4DF"2(@B"g^oi/% u9r\KDcM<:-[7w yw?yG8|x㍹WGh2 `A,3e!u;zE:urKۺ̹TH/ׄd}t/SpOi6;\iMR 4Xkdn' ~MY)p _7K0~ "â?~0#c o~^ .C C` ȲEն+;@mOeӐ @) kD3  =(셇=dmNEFXwf BA'Ǐ :N?=,,OhK.W\P^L~VCuww 9W^9me %ƌr݆-0@JAXr>]8  (cd?.vJDu8g9 h^ޯŃ ^ 6!ِ>jˠ+GE3usDp2}ECws'Sլ\OQ1Ņ_` s禇mvЪd쫣hx-*)t*) B2 ,BWg'FR Z0M-;0fl iɆy@Ky2X4~}\h2(|G JBs(LP6#λz n^4Y9ừa `mjdvEY.~0.@+pqڰ,RT9= ̖{Wd5O%xR ;D&hOQe%|Y9H~y$A]ϱ?:7_™V;|7KbŊ<;uKʤص_v!ǯԔ֟*CH_M&x{3Dqo_MSag;$V._OXsX46T._7fuKWoYl kO/?zlsm C5:B$6tY]ȉwAFkK}lfμ9jM:۶}Kp9W|[{1eƥ]gXܪoj)b1Fݣ:ꖎ ГC2\`V.@q:JztƬ?4bxT40OR'zCXBD^I5eS ѯࡳRZN!J9Ю X)@2`?1cԥiΡˍxXm6B dP[[ u=Ni5f̘d"z~~QJ-#^aA?=pʖC/gT3oƮc˒ӧח@b9&Q>Zmލ5YFk2  `oߒRr*gydb$! -[&0M<أXl. ضl&^ L 34@0$p*bRC~%;w 9ujng6 t>0<͐ӦA ^bm/ ˁL Z8m3)@C! Ï̟>+s>B`8S`o=SYc6V}`"\3Xع@^!Ԡ@r3ah.c~j&M,@M$ض )%4oۆuu_,FᄓN8CۍP?x3TC-WH.]Jc.//v.U#]!NrQL}Cm8 oR[)0dr A߸SݡKߍp'ٜ4A ® R ed CIZm}COOq:fT5Fgg',B&R 3f̀eYpBdYH)!d^ BH@۶䕾wpbW0ܑRjӧ~Ѕ+on)w^?8'>옂lR.+WQ%]iР̆9O"Ðsi)rʔ)lb,>ClذH7`g0㨣B:¤T6l ÐsN.) , E0LA2xB! 5Jn>2Lӱr c_xR3#0 c1啙(+/A^pdE.ouH%0@,~cꑵjA#;G)&fH7iWi/30H ʡ&cRe%R)&9  ׆az9Ǣ|ٵD)$Xֆ/-ȏ>㪫c3z{‘GzKN89wD"E+AƯҞZkJu] u@^,yy޲oM?o9Ma"O~*DQD<\ed&G{Uq<AD)h66T$ˣO4!sbm( YdJ.אZ(]*abs^# 6H,**{o_端MbN0>x9 l^ЄHw-~)(62=v­7KA)]7YJsS;|8(L],?$moO|X 돒FQ6oG9crEc#i6U[ٶ%[oqٴ5~_R5Sɔn:c{),3|?x襷F;D"FsOyr!OqZa&6[^}dk__gTί;qiF6//]v9"lF<OMlxW;3\ys:2CTe'ƻ='*Hb֮ciiit`+gVq50PcBiׅvF,K Lhe/PvG[^cr75Y2<[_@[V+,$ݞڰ 록kX*2443;%DQ=Se>o^&!u%VC)!8q"<l΅F*d{ꩧ93-f*w?VFg\Ǻ{׷T$? ܒ'Ge 󄡱]nZt@R,㘟kJQӡ`3/^$ {+aa \x <`۽$EhK ˦4SŒ5ͮo9_Xrik?:ۯ ֦$)P<,]{+`',mD,B$Q@TTW縷rss'egg{mJ)9Gss3RxBp8R(X3g995c }8ƌA)p8q#Rx{7UPL.'C D@(5Ղ- CbFUFXI*ejU6Jw2 GQm;'C喰bDI9nF}Q^{X,Fiip8hjڍN躎۷1Pg]8܌>}bS&'q0q :+Qӛr\psJ  +GcjRĪcꅗuN4nW+J}KB4%՞FnJ $j7`qL:; .W}"i'hs@DhH5O \@m}(4F" EJuf+ǁL^NH]͍\#>]';NDTJ^zJ)\IQ" PJS:cKU%y&㛞:c~a`ӌwFPBض۶ @(°aPTT4A(ƀ#O<3fش N)wd4 eY>2hD*~ҴaHÂ{ 1Ҏs2B?k78<dh:BlHpH!i]ocB(  gKtd76'uQdH("J~ LINFӮ]e`6bss܂;vhxwd$v؁h4 )%2@)EgG22GI R_UJʄK4Koôl7‡O>&B-iڱcaj .OT(.IV e'AF0\NXO ; S$l_wԬgJft0\ٵQds3*)ϦN w[r!rs2勗^ͻۜ": Hv6+%ꗎzgA,9tˑ 8FJB;VhvnQ]B)XZ@@\cә$ZF4BMKú_#!%|9hinB9]nt9'@eMRJ3ܶh_l5jWGg<ܸ/..MG#"km](\y4mUf>N+pPj ڏgL뗣>s;kGoj,JL)-$ym8ly]Y[^R^NW?{5׌ڰcǮ<'7,u8k&ZFiR~ۋO曟oєүm&5Myg(c[@ !571^\e/Nv,lsi+[. 5h3[wVpؼ3P[k$ ׷,I\ RҴ ,VfJIA Muu"2쳎t]#$BB<G}}=QJA>のp:xCk,zyLA|8ľTJ)`YVe]J)ApLv|>|v+uy2a881amڻVPzrpB CAJ! 8n&@/H|fc(14iRv}20r(а.[ 1qPJR=~1yX<=n:Aݪa=ivǭVo>ztS(&, &jZ:FδÂ8u}ЙPmPΘlWBgqK]>ywK:!uM;-;3퉋~J࡯X6#dun-/AA4L4ˊ3ARd۰m[ЉDh JIUm0WK= ,㦛uF"qxthkkR" %oaƩ31p``8J!! -0N8qO>q鵿>?"/}B4ekܲ/3PvgۊՍ'GmzV@5dYs.:*?{;~o~b8mKgN+~VKl/[8Q6!DutuY|DBhlq;bx:2]ZN.>V9|N HU^KoԞȽt[!dTpۉ?[)ӨJqq âRjN\pB( W%qH'f!otЗݷ'tBڶ !4 ֧~:gΜ^&LP%%%$??عs'Fp85k֨˗MӚ ̈́$Y4'tM"JG~Ya{淑#~?;(g.FDG1˿iUFQԎ4fþ_{LS*;^*uбpb7пnݒxjTn߸nun#S{ Ejj|<3W ,Yi[zѣGXIHP2 tuuO-j4\A)]˃t:n(Jy_}k6ZX`99 hiD"---|0Q Ą n/́mAuA2 S@#V])8`$P("Y44ڭkey\ %q+`8b "p8tP6$hnd*HRl}Ok"wQc[㏪zפoӷ/^O5z4 41H!+ 6lX"D[,-tghk&Jrd, n_&=mκoQ8FBl)~Rhd*Sp$Q9vqy\;7j g# (UBcM9u =9QzΠ0_Z"?xSo:q;W/X{tuCu^T_K_?Jls@^/ɋu# T(@DJI ($ j:xCn{T8?QHI֢al۶ EEE( U}H0߫6wou; KSZjh9Ynq3Y)ZUUU%{i*>>۟7n\w_kk&fi742F +%i ru2EE̵Is?FBӎ˼s@J:p JE@>p?}Ė8L_wMMΝڿy"*B8mRQ}PKBU~+U4;㿧΅ mwu r3VmGKSQ44Hl|BuHރس.f٩ȕwn]ַG )eA)H/fՐ!CM63{lp8eYmN0MS2 <4MN)=W)%-ˢ|%i\ޯf2´کcϜ eOp _I5O7q^ҲpbNL} w2r<78D]4@(uI80Gӎ(;׿2ermɯcdiv$Ac>z،QN@)E4łR 7o[o1cN*4X<_`k'JPBhu8Y@!nb ,+ ƍh>hx"B47CBc؏^znxf!cA!!@؞8<t ['@vBp<rAD#e\R#F#M6Z}59cK=ĆU4S6AWRI90#04n&R8\0EVDm;pѓVP`FɨQw>ZݦMؾt  @,G$MhniF>}9Gff&`6 ut>_߮w;q۷_3=ܶ  wcb:h,pŰs} 2|0<,{`@Ѱil.@TWK}"y\2nK4ǀ^ðcn0oNKJo%R 6 O?sAU*_v0wz]۷[R[c^sWU #QWA{gk#iR<D;z A$tK73;xjmmCH ۶܌`'j,)(HqLN"L_OI /F̘Sڶ Jטw[[O9݇B@r^?HgiMs3 |5'uR[Kg<ܸ]?ڕ LBSr տ|wrtkyNlgV>Ri1ZHa^ёfwGEv}pݪT+lUoi "hi!+rzX%1֊k>y˥ˬ0g+t:)#+ _zz=d@4771ѯdgga޼y8sA)!6z!"i 0 y3 ui'AQ h Bșsx=cgqߔ.\=]Vf&W/؛bL9ml~[5*?"\((K AH S-?@5c,'33Sgv]4c%iii8餓C{{;4Mõ^ 0(iFZ[[z}~4Eff&mlĺRNJHW?Y;P'tѤgGNh @FZ, y#MZvw9:iHQe@]>GcGa))'q^O !"(4SJ("+k6r!#B( \@R|ѓN wk_>%,I{d_Էy:;;qeu7oھ}6insdMXuڀ. T;vY<%j6Chsrˎ~UT41"?}̾ˋ&.;v8vA t4J.2T)Y6坦J^\R9mWLisN+^ G'e JQ 9;fᶖs<~~?H >;](9T[&R2+BN9BH8ȿrnhhxL:C-wFEEb۶mBȏdduv;.[yv9;DTlʧce =嵕.cG a-I.P+¹$Hf"E-fA׋]z7RSh~(**J/-͉^z! /VBD{G5lcnDe s,6|8C92@/)!3~~FtIyMEEE,ь!aUknUAY 2P7M,nhĂ`J14h?XD"~Uylwhz3[8!O+W_rN7#T̆RP;EB$XtC"lzŽ (P.jg=BjJj K@>j5۶nfo>_&kjR i )\ mpί!`͝;<ԩ[yzU!8۰姰jxᰩa< *B5Bsؤ_Bqvw3#3)b 1!`msoHjv6/Wͪ*gS9TJ9۝k?񨓆ƿ|msH%OcY-ZUWC$?J//{ێGǐ9Tw"ǰZKTEP9th,wӊS(m--D"hok{nA,ٖ 0,}UUU,~U;>q4| amUh QXYyDS5t)ܣ.xԭR9wG6s gNNӲLPr`zj8zӓq+uEliw6@)a:!>#>ISĹd뷵>/U]]uDQu=9GH>xw{*\QQu/D-Whcomz7ѝ'vT:FflPXV5fP5X"P ~BQ5xhu,UjnR4S4(¹UB*[ 6P~ʕ;6 )|Պ+o~W'jϵKA@Uj%~tZg0~!~0dav& ]Vacm26Nii.~%Kܧip8É D4O)p#i&n9G}=h4j86d8$t!IV2xl+菑XtCZF@e0UqwD:?nvx<[yWtq8 !A!J 2p.P<"qO&#K(m \&{; aJB)Im!Ґ!d7-FMӞ"J#fVBII eb-YjU#77W0ƈRٹX) TUUSN;/Z6y 6Ȭ+޹s nP(ppOgʪq _S[-;*@9 PQq &Lh#:HL-"o:n")7|xr(Ѩp\$j[n$44uWe7܉'}D [jtE( 3w}qWĥ\qǠ;ԥFC1LpcvV熾}ՋU _vmW ǜ]vtב' yRJ)S*iH*@TR 7xݻ/#y_l;$ʀn0`ڦ9~WήX(Ÿi!p:p$x,Ɠ># 1 hL9EXwK̬ICzeǹ759lnk{.R $WF.jKsRdaSnǠPlwg5jxge "J4FwjwLT 6wF]BMmeJm-_:k5"^ӽvݸmvtDFs32FJDy8SOծ[WYק{TUMKϴb%K}4Xo2,ԑV Njc}ޠZxL"ҭ vEit /w>c׺[\u揾?=4r=mu\N5 R A_o7oW~N)_|QK(_ ۶);%j!n]sfӧOvynǡ„A4(N$R۰ek H){ IkR*"eJ)m۶mO0p8K={6CTJIR$D={ di*nY7jjzB.N(+{W_%Y31cꢠ=K+e3O;Ϋ=@`DUXd|z85x^ $R%ʌ(TJ Қ_tIأmUU`忼Aח!'fHa8b1BU"G!r$:5f9Z 7M}urVTT jǖ=ŧ?qQhKKBGpW/gd()4$GasMgV… C^ߴݨ~5}7|ߪYiN@)F "s?@:Wܿ{4CR_LKE $%JQF4jږvڱSD JՓkVVVI)K&>Ƿ~Q>,~g[oKee*))a!CH$hƍ-Run]׷*5 EyB_tTΐ;۔RM4 )$RJJ))W!f~&!B )8)*2o"[w}-G@Ծcp~zmmi D+_\?rW??Zvm1xJٔ3e_pKkK$P&$׈]tm٦JD4ݴȚu2Gl16jUT%(!  lI ЯlozbL X,neP=ѫp\ҙ}LuV}uqתw9Mgȹ2}-@Դido!Ƕ }2߈eƾ o^spm۴u6$iCYzyx-ی+IS݊-^U{1TJ[n=MO6`(@ 4TUU_mV@qA F`F8:QPB zqHv"%%%]oܸB]'e.\P 2N3jm%sܱk׮x͒AH>|&)PP&@՗ү߸J2@,/'gvxsb(TD$Rhz2tk3"??L״4](..F8VzImm-.:|p^es~kSS;YROxaVN3A 0ƠkvBk;::n^Z2~k}sቬ y䀔46ivlĽ7~ {5#!^6,I=v̑jLN!imtHNE-m ~ Cȭ'g佽e ~c32 e"$RX #3N: CG,/殪[#m^댅 uMM DMo߂?z?/Ĺh|/d'>[ySu9Iy]:܁mRJh[b{'b1N]+G(?(P*_ Q^Fߗ?I| +GivRJ[) t/7t]vEcֻX<'$NI5&8o= yrcsR kZEͼ'5&|t|N!筭ϟp*P-kEF 9^e>(wۚC׼8 e5AKP g|pPr $EN}Z`YZ~C$W~?}9g֛\'1t=r19=3Rsun1V7Uv =.fx23G?Ra$'׵@@~u?=\AQ r`sB)ӦH?`Ĉ_uFURR5a¨qn5hFxNaՏ\nɕk9S>k^z@II |yM2dȶs=;w:U"EGl%? {?/BR!I-hX31!Č}+@~z^yE?|.֎Ƙ|GUU+srnhhx 7%=?Yq$r%(q%h6MX,s=W )_rbÉILCFH,9,>3f?tBPO*RhrOy.]8U:F`8itE7~u5T0?GT}z~FZHDsXS[kۊζJ@:}BM J?$+-;܍Gq3τ7+'L^풕=<?7@puHs;-_DdqZ;nEҫ,;fÎN|q喍C?>V)4wq#<3~m{|HuQi)[ pZ+Rm 2dI4"n_VY_{m@,է`}79fLm]ym{?U^OSw5 -k0tW]s/ TR]-y^|o@Fl$" պ=SUUR @_|}WEsrk^^M7b)GIrgے:b$Vi0?J}C2Ҽ7J%bd+9O:i>%4^|1cuXG?"׸I=u}rwB<?$ tq/LSB-߳n3q< .ԦL" l?rTR>t(QMOFCW9[6F=$!|tGvZB__?lcSf)S/ŢEiayaWi"(//giRO`} <~Q~?ŢEtQϦTW}Iʳݦ $@H\8t$ͯ^a84|AHdcNKKkSUuMR/ woI؂a,{>HYY;kTb5_>#Ճ*xKvc{*=쮝;fA#1c )/r̙3;;;k ø諯zT? KO-ZDL][K CH{,l 'Qr҉:%Bt%8be[q]o}`<}-ƭo ༼$V*"Y&7ϳ,k<"PB@I%559 C3f{?CR©5eY9Wc:ӌph , n9jo}q ~ ߓu3BH:ڌ)$(Ew/ or# ZeeeBbeΟ??0zJ 84t^!ZDOk>ײoO>U !DssseEEl >( p܇WTO @dHPI6j٣H;c?R+--RjmA,߻׸n).B`P~*ip?q̡K達^Ox0{*/g$L29p&%Zhio:^&1#~Rp8.wWú*Śk*Iu O>qpxo .N96͵˿[~OJ/w>c]  @$:Y)H2kh3An]ac37~J}e,7,k Hj(0 .b\xP%THϙtf+ I2\E(T'@y<*UJ)h"3gNiff}}9&Ճ4Mlݺ/ ӾW İa&zN*r`[ObV>ŀٸc\Á"@_\Ì^:4>YJZ'7~wg7 }(.R>loop:χo=#! ʆet&%tR.bXUyy" Ϗ<2=;[v \BU&ͫ;J~ py<9.#p0׿ջmq$ gggp|yaͬ)Cf߱RBƍ?2dI:iss+SL(R\A߀3R*$cTTJ BELRf367-,牦z knm2>صA@QJUG[IDJ%>o&-,k N /⇢!% <$TB-\P=rnu]7(-=GzuMqX]]%7DW:={>}---^zaŊbΜ9:SԈ#j}}}wqaQ&NÐ$* $x2T|1XTE)eݾhµ8B52?1&M u+"O C\h@s=R7cq2#*TR#lJ}Ws\+JKYSg_Wr9d19Ms}mzӦO,Ai+ݱx4d󇏜U@%W=~uY:-J pM WꫮJ`m,2?4Ȼp8|Z(c:zTضmh~RLXBl 8\)&xMMMK.=hMKafGnM~?o{Sn;\yDžgoP`O_%QY aoSI;()2ϓhY$D29)\N͞cBTuyK2_ Qg"#o ^M#J~X?ʽqԙWW{J]p3]q:] JNm69~(/؏1QU^ʂA>WL󾔦1BH<'V2 4m\sϙd#ocj wA>H&/|4bu\sC̲(ɺum4Mx /BR2d%RbEt% tX,($+:2r`Y*lB)ݴik=)%X<඼<_4Ud]][v-(#FҬ}G׭[DEE"H3{1)KD),8Ye>h: )SO Y*[[ܜJ:p\kazܖR&(!(\ 1nPi訟߫|o1ec@kk+gi=$۷o>o|vvn@ hJ'dǒw%p[&T1sMǗaE.ن*yRPBTsӧ"UUlHTq2]R5 |UTJ zJJg WR>`;v.cm=yZZZ򪪪'd (Z@A#<~I\^dAGk[_;gf/dc՟S>V߯?c5ӽ_pJ t ˎ+ qX-q,Y-<" I T u,|==9Y؏JnCLx/>Uoزesω vꩧO> 8۷og_~%ᰘ}oߎM6,8T~()H qC~֬Yc kj৺wyJ1` 렀N A( t]q lTxzĘ@y9h HĴ%m5.4ضĖ8ƻiU :t+n7eMq 7S9Գ r鎋/ٿo])e-XBȞ~0 [`Y@4k;nY݊RJT"t A8xsyy!CHEaŨ߼3fF0$[р~`c: O.?p^_\T+W8jԨY2q}|oaGĉqC9xb!ajذa"//ohNNۆaBfVgN@;k"7ㆦ(t,5:C͍wڝ#T T?Rݴ+tQ]Ż 6nӇ[2(hT)S^F $ @ o馣l|׮]h4*4MR4 !auVwx㍧O{*ǍIddTQ*RIL@T4ɀ~Wb8}|uyW2BTWჼ+W \1n>~lr !Du]]msNF=i۶ݯ_n;vHmVYBZ[[+WZ[| J+**(w_b夤_(8v򅷀dIG9@x]]xY&޻t,$AJJ K'pRNjAuu#: 5/9Eq.\m5^wM|v*:cr=@;½|w"u~m<_R+G#G"hs͏R (8do{zfD!D.%M0ܔPQ)R&fhkH`.` i,(!#Q~E  :kkR z/HmV_<0e~׫_8+_>vf޶@ `L YU^ w|3v(I !$#@'6u;sѣnjanwJ!X,} QX4~R!ۧX r2FAGC F[dma1}֬Y8q"^/:|WH&7nn7"H9n7s8%ޕWU7`񶵽h [_:i:cZSK?;od/_!R@C,aYqIX LƮşCul!BJ!2 JvmFo$CWXL644޽{W]wu=bPkaT$ 4Wy/"N\zڔRm|utZ9E..8Wj)1~`-W²hGɋF@"-i0 p8jjjywc, PA S _#SBz1sL 6 `Y46~zJ6K7x]y:8-0ߗ$2 [!d0q`ξ.i&eZEȎUϫz6m=SǪmSa Ѣ&_@}] WQFR[[K~{P($t]?h4*v*,, ^s5兔Rdc ѤDDI v?D5MYu5_PV6)0^4 T<'We k ʶ-\,U:.|'G"[W^=VJ4MӰm&{XiZt֬Y?81Jđ I%ۣ(."\{,#)='==j&Vm>{[íO^^)EV]|%ͫ|uyy皒>N5~IU3RK_儃AG?bҾqFlDL`%Gg}OYiP'`Ĕ!! 涀P$%5ic'M-{ӬٳDDb5Po& 녈?G%~57MǃÅNPȜ0O=Wb^?bO%%斖q".6C@ .lennn?oYh4vubq!tx,ЍǮPN1K-{ TMMlE#?hvǽJs~8/3aH?NHGzz:lF*&tbG[;[!|%%IA醦!$uww1hӧ#''0rHD"!1|>0jyy"XS >Y +qGWN̚/EVTwM.*Xc;0-ݓRD/cjĠ[3y cF ]Tml[Ϊr)qi0W]uUe(b뺮(| !t:|'Ej *%fh$$H E$K~FIu5>Y!84"Up:l.[}1KS+lnnwtt4ͽ&Bczff@ Z UUU$?MszQ__O׿b}yk>3|wS  פ%5un[n8O?~=vk6ڴZȢ v,B j ޷Dnqͤ󈑹+}<%=˦@ B99⯥iReôhL(T 6,0: Qxs8# :숁mCAd(x.ә,|g! 7!xx|Lo MoQMNƎBR"AP["W<1mcL 99GWw7b(&OBqtuw׷V\J)l&eJD"CEnLXKTMTz7M  'JK%GXI(BK&[`QS . ?ϟőߌw {aۡeČcLR)JiyNNNݻw[֭3>la޼y8dZZrZR%% I)lBee]8(& RxzUZnyz%]E+G4L_PCzFF+u$"ѕ&@~0~ zZ: V98O?I ˶a&4Mq˲1cܹ1b ?d0( -4^ pAwU/|3:qwg;G-`Zӓv`ؠ8*j_5|0gfjU0φqkéU2pl;,,}<`0(wܹSB?(Zcc0 «^xa哏sn]IReI]RW KK}nFqҶ"`1^.D9 KKAuuH򪫮:ÿc#1G+)$R e.һwՁ@K Hy]$cqCCFnVu֋vqĉo_O{ۥ~^zF یCXTR2zʇ%3{}0qGt|/.7ZZzdIR2C0 SJEdDR")L4nȑs3#@b`VzΑ~o{CJĘI!~SE1/V_\]} }jva7^G g-mK<>]MRWRR/ @,Ś=Pn7Ψ,/ӝbҒ)~Yl+H8 cqN Lשp ,''RBp!D3! B@ӈoܸq΄m)N;Au ;٧‹kLb v{37 ueq8 PNJ5HiYe[Բm,defAJ6LzΝ ЧOoLz(CVV&( Àe,KH, K %A CBi*@ȕٖ WC^ ?u*TEJ2GDYTn7A^]6ԉMX= nlW!(u8؃ ir0l*0l)GqΕt0 7nԶm!Ry*E c3 X iMqk)[wAȑYRR^ ?+]26,N'U^~([.tUgp j`=<1yyÀsa ]!Y/ }񲞇-J9p8{3mHc666B)؝IC|C7c5_ <^dJKhboeoZ L&T Vc>h{~(UeIKa: B(:#!pdPQfh_yfS>>oHH$rm(rqio\ 8Mp6e$Q+@B)&jXS%qˤxi;RܖfJr\~U_\Ljkkk.)$T$DR]v)UJ ??r~e,ȀB41SBAyYPP@n뷸\Ο~o-vBDȵj\^bh!|.?y8mmW0'w氧'>o 6P !ERvuH(`)C΂e x $3s9A%5e+*D…ZuYF{9/77f5b,/'O{~dy}+3Jk]cq*G_RvWjը +D<צu禑K+U+ NUUk׬1cXTVÉA?mqn7XjwaRD#8 b2(XM>F1F4@)DJP! &9I,ASsa\p&PR^ P$K, D&?2}\PDmiBK6M˄i@ƍs@)ujq :7{Fi4D[,`OsZikiH p@S hDX TH${8?3G;:Sa\@S3br%s4G(:,PyH7jkkg+oax<_}y/m#WS%'%'m%G}2TU>%osD Pa]]]#(ME`GaHB~{ t]뉢w9Z[[.+Z(9s&>|8rss]GѻMMMmڰaÚ!/" pp t\+9"6b:DBFX5b;7,}.P?|Kms≻CTM#@3&:V")_zr=kưNg?z*`ڐQHΪ;]4ԽZE{;=mڻF˕}VaZ,˂mYmmd'I%lBu8yvT1>1BC%hF&hNM`~tD:d$}DR-P H#q&T.H%MӢ2pezxWچq?R8ckH[lmېR!na[!uM " jg{SĕmK4)GRR1-(,)85F"]PEr2~D!J@@ia8胃w (KĚOs0A]^(z]F8f JI0P"3f &L2MM6jqļy0x=Tಛ1f IR |`m]]-nlSM/MB@ "+Z %@RBo٢l{.ϑe[6yo]AF:g޳=k䠙5 C0`((Ll--g `vse̒|ӥ#(S.E@3p&II%o\;}̑#)R)#pO**t M[u1;իNȗ^.d9#B_4BH>O'e^h<ݤV%bdϩ4sxWb*~Yg̨˶oP,K|+הZ8DxٔHdL`K1*RaڳXya@]s~gt$20HnړO=aҾbwZkpž)Ckэ7²,J$FfZ#L!hdH/L (//_븻F<e ,)?T0a't}9s!1b+Ly9XNƆǡ J@q X'-@؀ Cw*(`+"oA8yk}Qߪ͟8g~X{b-Q'!"er.}]NX54\31tIpajКX0 aKLhWIF<̹& W*6&p [Va3`660ZC U |h-V%ߜB8]:ν;X Ol> Aȶ8Cs9q //Ddw]"+pء.rl$w-c {q/Fo}[hkkw8cs-[{AҲE;-CТ{[Zz3mL?C%0 m v,h)sqEH$6i3̛7[x#g| x  DZG!,wD(<AcX2W#Jl4 4"Q~R T$Nu]`˖-B֭H$*WA]I@iX4EJr `a? "Sc!Hfpbi#ߚ;c΃M of3"mmL&Vz罬"޸ee@juڟ|V(BɑG!Ej]R)1c@6@,_>d8|aE؏Zj8*TU]j0ىc`YݞK[e2>W Mn˲FL.Xhl3Di3P`[BTXN&2$rfmdUxkkOI؀fIL9W]79b0 `<"QZbO/~[H 5,b%)/>=ϳ `JwǏaru:@~z " Ml!T)ާ#e4|C=4*dۂ|}}jtuWa+MUiُw2 k`aGd.m:Mm[lٺnƉ06CM6a˦Mt=D_xO!Ǜ_͛6aԘ1ؼy~t ľ֭[hEeAE4w #O>;ضkע]x#f]|'7|󫑯 P+ȧr\t,6]v{7`M pwyhDu87;TUǤB1M@ z5+$7a䌩Da|ﺾd$ȶmo0B)"-EkjkkE"|>ްaRXxlYV↖\Ֆ/>E(Ji{THyiOZl]Z[UD3;!G*tstVV}ĥޑ)iݘdڼy8A FkÇ?uVS V,y=z]RRǦ&e@>זe)_)D1Z)dW^Ə7KKKXP JR]V~t)z-Zyy;>젻gu 9MyYLN~,gCFoeEy 2gCtuq!.}^@hYs:$жزXЏ+`.؜90 }jÍ˹bĤKf%ރOܹ7QwAS82U&1Խ 4˦&zf>..K?ɓ;+ذ-R Vpe R|yׅr}N&}ׯ_KK+M'?;`J:`F"B+'#ca{ȩ@}% "+]w??\|c@ɓ/]df(4I5Be,5\iӦa3֯[O?# nY;#Ȳɓxem"[4Y~@M}Hvk%B¶ g0p=Ƥe?VY>rغHOy\LVD֮IWO1_a [poag= +L@x*)S-r QJIݖ+U<$9h̥fZaJKKi&(TL.v'RS^"zMCl]&ff)h۲F2H:wS]?}/7isƒ|b1lܰ[D}Wї(~=6nތ{텎vlIA30eGU߹Y/~}fDD ",9fks޿s,{nkvЍW'pa|~gggeZ4 @19!O:;; bȑzi@&),r]\BHDc1P} ; >*+P;U55V&֭[yfmތP|7|B 젙ç_lN-&؜9?w}0o]Ey hIϻG->gڹoǯr)ܻ.(6@>(@ ` 獙DzflhavA2ۈ[g[l?=?ZA7B,@ndZ 5,Yo܄  0dem6d7f_~Ckts}p]w'}ﷶwu 6-2 ҥK,B8|aRb^r]~.oۤ5XAt߱󾃧Ɩ; KXlh0|g\_YϫY4l_ҲڅȦfXe d_,1|T v屹+ !$ 5#(SS14 풇 n@twwD"AB7ׇR0ftɝeLƏ&\$4Š`3Z6Jgv-|yW^.]-jwckCt::;3y ?)%:::~+m.\8bX⭫y\a%ƚv.LjZvAK)L&3 # i۶jkk[|Ѣaǡ|ПM {9җ$< )pwDMm?;lBG1iWer79"lxkb1[T`|F&du3ňZlzsTߒY.Z cccX|Ǐ?c h69)--}-#X쟉D"2iҤ˷luaeY4f̘PyyƘfRBu۪mg˥ә>H3g|'{~_3ĪG']P(u>⸓vGWUPKwCU$: #CƧ]{wS~CA355ˆn}?_T-6^BkЕI4η0c-X.%&N2(}x:3ܐJ _r߮|nkZ[dk23C- zĂ}zFJ3CZT yWa>0 ,q!6`hm ĘQT9L]zfҠgY0p!6pDd٬\|9|obId c6&dq{fi9rRlXnuw44co[|jdԾOe [yo>-U8j |%Q|++~q~#ݱ7\ßemm+E΋al= (ykgeԎ{zQ8vE?(ե#Nx)mshKƷ.0&ޛxjɟ}ő/E %dp8tWww:h8+h\k^L&s… 3 ر!H$reY0!<tGݠe٨ep1YH2x{a` 8&;*t;tߦn9# 8`}@_J:`Ar d>:;H(q0uTdY_uƍ׿Ϸ̙iwkg'@V_?նp$A>^7ꅹ/_[^rON~_մ_ܟtr$N:v"mI~A?`*B3s!I$_NvU`Z*|:Z\)pcQ%u+- oZ?c@(3&VcC*X滺Г-[c2Iѭ>{3?ri_Ҵ֦Ԋb^4}n?C57G̱}<|D-Rd1P(4dp 1°`(fyʎέzqo66hj"s-׏TMKk 6o/ TK]˩]M+Zos;D6x̾Ǽe~'q?zb(hcco徙-=/D"~QnjjRm;qVtN5UY!ePƣdžur_/d7=kc7mhss|/_Sd3W{B*XNIywOz+CN(YQjt] .ߣ T__/:::UtABK)G1su-\0NaL6>@P9cW*B^@`'_& c^gϕdEC`6@j]l-Gw4663fPњ]YY4vX3! x-[;ny co5u2Zvp}Ebyg 4_]Y\/OV54|&juO2V o޸ ]455?Ѷ핹\}}}PJaGJ qMTTT սo; 'a!E-^fw}HqO3@O8aɲ|e_u?ٮ` èD([#(l""/<Ѳ;HNF_d-WMnjjO-30~@]}kxcZ(%PsP$* 3HeE n ; b5˖gr$HFoGչ,;XotpɤR=cU\dG =n987tUwNv\${[%#caDz`>H/?MkW% x*o;0>X4aȜx۶'gO,YoӦM,--=/@hl$45}td⬃g4\rk~ o֔ddmGx]0Te}}!"+,2~3SKKh2!F]~lj@RbfV^G[y6 w̔'3Yw5NcO?}D8>}qbRJr98LӋw^PK~h֬1=4gL8age)[}}!đJ)e۶m]"beY1͖ ;a?pUWE9Dd oĿ87lذ)E!ERr8 [ձԾ\VTfŬYǬrbܹc!kjs|sLQwBuՊ#_k{g`˕V,1LHRHIxVJpw6݌Ql(]f,'tw߮1*;oip4K4==gpܩ0~\I,ܺUY7yM[?p_ߔO͇Z1*$,uߦlvUû3k(2ԇG#Ҿ+9x7=`/'-ce5UGgw~:kNSXJCbΜ9 ];p]]AzuQ #ޛڪ?)/6rDeF:Ue754u4 43h:9}]}X>ϟm-0gNޓ8`+?{kbc FQ9s u2RQ;futw1O]wƘdt/# x_tm;fEEEMo}M3gN;0ϛ|w+Als~{kwo8füyTBVB}c" !]5=b ϗգNt37p,{ce-CJp S ukn}EoNXD_eY9{\0rXHiX;n9:-5|e3)/[/n}+_\l;l7n[Y"FblGK)Yr{$1J*`뫷r͹l;ASq-G}Vm]"QaB )2'^_knԗMDٕܹh}Ɂ nYۭs /ujK_5nSTڱ߇2 B[ⁱ&}{Տ~gΔo..~wZ b]1<Gqd2 L9K/]'㭹sgMD[;rc792aWzU<`e%UDdA [F@P7}oמA.?[.ossltx&{`[qW/꽻(?EKvttZ5]/)ׇʰpC3ACL6lM65ɪ2խjEoD:O$e۶6Ơ1?\p41gԤl>x5E}p !O#/pQawvvN$¼y3f"5vp;AB6?{0ijm{xWOT"g! LgQ_Ohi1 :"&rDCh =ƎϨhi{f*2U:l@ON"+Dnuݡ r'05a% {JiC9UU uhs }q ȢٳV!c}1+GOyݒZZoA;?|ܤ(tU,xvo.~ClEMM}lHmXK.3}_EQKl6|EDGxqOMl3 xmY{x-`V|xB&=mq,4q O8 4j0}[րe\=Dۍ/Eh_Leɹ-Fi0iIfcX{ /Ywn|i˄cYlc@ mm\!$W_<+4^\;|Zf٣dxeiSŰ0@$a꧶wWD5=SV*+Ȍ?o^3f00H?~~Xw{ؐo-)l|_/~FjܷH8qPLa@ٳ\ J'mm[,DBK'|ekZcj(_f!?13[@^2@`ؘIYʻli/}`IΑ5c=]V3nܸCCIXP(wMM <:σeY%557194fę?>fΣDKMM0rVC˧5󍉂G$R)Fk,-"Db j2Kg3bDUUQ["Unc,yuaiBlZ D($9E)L߃ N?:۶z{LBk۵_$fYt0k) "8 1…j'n1>#QX)c%!8~z{@YhC+ O!%8hB@( ؕÀR/Zy˅2CM8N?{y쿸Ż|ԨP(i#D+SKL8X}م%/< ) lO:P7>#[iFg:lK:=XkʑoITTl3BК  i12Y౯o;621cLxx G=%ZjSF@jJjC[Z)%r ˎq<~dWWK| B̲_ f.F7gYbfd2A Bg30lXZd!F X >(ԃew,=zjJ)TWW,--{A8;><B6B7,@4LŨu$r~$]"b,\vOAD`A6A"P@V $Y<+2YМaÂfσ80GC@[n3^y=[(c 릠࿭y'hFdjX nﻙ,(,<1 eMlm ƅ - "¢>y8) 3DWLKNLߟ 9^x^&~28-":c4J +@Fr+<35o_ A˽x,}U?ߓKp В28=3BIoFnl}VxHb~s Y a՚4+J)*0|cLN)LO}V3њ6Y‹fͲcBbs9DPV4;u߸ R4|cQ-%^Ũ.&B[4k j-L(J~T=~ah]eI)@0xo!;?ؙӓ4Mr0:zf:ټ˖4?@>FP2t\s>Kkhw07~xQsaP.QF\Db!tP_Pbdl挨ІM>Z~U]D8Y1H@ ,e4&OAdfRJ!ĶH4<y[uue!\zl316Qѳ hm@̨ <_O =&y/+Ċ)IU#(!cY u DhrLTM<.{w?hԘ_JGFk€@JbXt}2SW_ +6lFtlzڻob^s ?4 q:m&9$hv='چm@%00iT!U.3)<~^m\_rooZ̤IH4ҦSr z&ߛ۴B=@՞ƀU7:$@>7+o裏{Od$\_9p=S۠VB|n!r YN[.ЎI.{>Ev$&ه|g7tVxO$J"(χ3y wށ>;w9vǪi 1(̀t &N YH=N5Z 9lT.dH~Kl*έxvw_el'5;;r)-lĄaHEoz9$ %Y: I o甠D(q4F̶޾a#ak5l Ծq+sA^ N8 H=,}=kWltPƴmbmznz9#ھ;$q@YjcDe(LQO4Giծ@8gÏB,DSknj)Z7$\hc@ؖMō <Eu-a;\,"i$[(M/$1HBjf)e i$&HuVlhW/ا<߫,3ěM4@HͻB! o x:Hԉ̥}=d_9c|wFDZR=ukűSJN(x1B<"L ܅ HhDZo;.̓73s4ݿsjCךըZh?p0Ku&^t8j-${vIatf'a͝aWg{OP}L=YOte6yp( p!MZmqmǁ`>Lof[ xck'9b?`QW֡aF֌8$=+/V"7gvR.-r(u#\ òlXMTV IB"T sOHtP]Cō{/E(3)H)XI0_Z0v@'X܃sRvŊ* aZ{Jfk3p )1#bR "QDu9,ة+JҚ>RچA,2#x䕸U ax^RD\2PlPV4L]ZS wO^q=;ޏt1JjSJ@KBf!B_(m(_j{JzA3C`LBJ|U[sۣjBxh:Y+-6 '`a,?RZ4{};kԍZvRqaOؼbaO\ogd *<) wt #? zҢ[mQȼҊ t6fXF)5 i>k@TZVSQlU^Ҵ%cƍM&.8\MP.X Yv(I; 6Lp*!0_6 2z'@23&-  ##b>BY M!|*,ng϶ƍ[Sؔr| Bhx}}({(?{\?]@! $'F3͔( po/="~UpGc@7{a +B x#%|d\"g9NZ?kHap9Bdy{)+wJR|姭ԙۅPQ&dm˻pNh(ͬQ l/DD7`]}MT7Ŗ@^qnp>B.g&," i (oԗ+ǶmV0"c!jYەt:IĆI(6 0 ZZ,˭=1uU+F/% ͠Cqoco6ç(h~6+ B/<¡I&׌,,*; y7U! Q7Ijh`_PZ:>nq]2^4+ZpPOu6k])1RoxY{ش{BƑ]Ɏ>S֞V>֥2!HPvA`;8\jud2ӊ <=kVU 쳑x}Zc6+gYgg„{m",XPm}sH1|Fݥ:GM/(03dկ=Ϛ! XPHFaz .T b(i!K S(ȃ. 1K?@1d @>Ƈ Ij lXv'>Ắ7| <ϻqo}JЮJKFV3ض]-/,#*v)1 ~Rwud(Zh c! '!uʥFE$+1s+f. Rr[! M"q\0̒sR4nHBǑ`6myc!]k7 J+p~X' 9~; #mڭB`AJGc`G_D$*$)l-MqN XŃ.r- ~S@4DTFwkޟm|˕ 4B ˲4`_@`ov O}yC6G.Զ]ȦP>4"n%4Xͥ:i$0.QR'z}=HuWBDVV F)deKng3gc|.HP>[<w\4Wb#r~`q~ |0py+/HVVµf cq?xyqVϖR ڰ OZb}VIdRsiLwQپYr>OBRua%f3/vVT# 洶e_iVjsTqWe\6?.zBk&]Ϛ!gTcmPDஞ|}%BRsײ{˒"F 5(@|j\cd;yנ2Ds!wE@tBTF3Ȼf1 p .j4Y)'JxRTd.2l XiKIN_ ACl4_u>/ }(L.aX@R"~wce+M(LeA$3ekUعmpP;SKFs4 'H?yf<L2Ȧ 6 d7SNhBU%\M/yi};@Hlڊi(5@:Y ,rR J=nxuwfwы;/ݥi Ћ%%q$s9hk 8B uWRi敿~ZUIUpYZJ"OA \f/ٮ}7B>(`_u4dRqqaqNxl4r$)Sjzb6ykU (X`4!}V ehxTx V5L^s>J6-u4\@;p@ kA@=4lBxDIjow+_ }{r1/onjfԊ83`S@ e!-_@;}ZZR|eX(rM{Ya?cVZ W rw9?Z[ ASЊ؆hv# fKZ3*7mvb C@llt1sBId<\Ƣ Pd;X0`4O(hBnsqϾCR9`ɝ[iA&~?[K_%NwU'>Z`_mJRy BRJyC=t;|ghF_dZbY_RR~{^3j"#00[.Ff#6lfH$Fx?r7{6e^_lֻ~㔫oU[qá >CN2) ۃ3E'(AWvĂ$7,eq٢ zH~ dbd*'U06:!H\!C:5>9빈hkwCFcS.+\*9~hC?[w*:h,>,toc^j?'|G;>Č@ Fo#0*gpXPڠ=ŚAmP#Af" mq鮎5h:FdːM0 ӣBbx"jd=Q7.t]~s3v8Āha U4F,.Ŋq6E͜9CwOv?vՄcQ @@VevjJj)^SI殱D51cWHZ!b^$E&T.u #IDATq>X*n*/kj afD.v%!jjɾ~#*c8R)^|p< m$F3p lQP$d Vf}4RoAEcKJܖнs8ϙ C:_]Scާ~qBБeeeUxh]13BRNm[R8<^KbXeakktͻ~Y`VELE0 !ŀwe h"SSY  $ƱS; σ, 0nmHrKQyy'ׁg>A^R2!ΩozGD9R~f^nO2s2P__%@`(ZEht߿u -MS>KLwwiWaƍڶm!@ %%%ҿ=Ngx4zx܊f5|+wQR_`2|O-"j`,.A< Z!fmXvf$^ 85ُ*dLJ))`v$1Ӗzξz#;hwdox&>XJit("D*@9BTu$U +`RU[3-0<"` ӈGw[P6DI ,Ewg@yb?w'6/%[ml?gg-6\c2 &f~GGx!TmK#Qh)(dB3>xѬY'ė䵮2*XRFز`Q`S^lJ%;-m֨Q&{I32jV < ;j84R'w~_r*% LF<֋.ڴiDӕ8o,8냲 $ TyIݕ7 ~49ŔS@3(Pð- trKQuL|{LٚAGϑ(d7OGw A.KK? 0cĘ40|R:~9" blD @}wm.b:3"~Y]~cpV2I)WwBY'LNH[KR ^iOKʐ$YCtӶv]xIZ#X5 [̍>TFVˑYӓ.iiSK 0#]rP|X"@2%ӁeS%8ZFBa|0e9,zS{>_nlB<In""ZmrOY,^XY444tx S!r@WW mm;Tȅ)07T6zFZAS! bh6AnH{rL~7B~7zDN~ގMüJEc6*+l#x&i&M-!ae4θ *]>an&'DYIHWJIȢ+v, ?/5s1ottt8ZO}Y4@ 07|MzIY\:.`h]?HFOn%L&r&[>؃X@ E.TA8He}L>'_8Ѓ|·r,|!V?짅S`Pi41v"X J!9Zc/jq1uȽL6>l,ad}OنĖto/zeqA8<jD!0ta313jHBE>p=]Vk7HA ܿqKѵr'  K y^/gxh/5xn۷sW%_?fGMoaӼ-&M485UMhLͫ7?ɋ>q޼y}=m׶۬n  [!/6r:a-VX}T6Yc^W5<O|RU`)g۫(/H@q0 ~&HS^mڊcLpX&>uZ/D㎔zvҹD.?B1v?|0JV).]AMc&V˦#<4ް3c#&kYW,d!gČf\=uk$wdSwackqcx][X)dSv:6r~6~A973, 伀 ,3~RxM0~ɑ z ;Eoo/ᄏlԩG\z^}5pBOB{BWӋ/8)]z<8ǕVVεN `FI{@ ٩|g_\ t >%fq$Q"N x+,>*B!"Qi$dw `ji3y+| TDJrTNOW7_ST3N/ *0f(fb<ٖe'^xL&?tcLÿ2vZe4 \x kp+GQbM >(4?=$F*Uj7mXlpP ޸q-tsfp].]l6'xŋ/`;z3qps>s̜@z3BXJ>alۖn`)PthE>s ov8rFnw{[qha45:&9>g>y7ݗD \"P'I7W߿+7W&p1 oMo"M,z a tꑅ0 IH&CZȤh۴¢B,.]m-PRBUs.v.x :o;f5_Os*GTJ! 9@ 7=W˛<ޚvӯ}e|V!;{׫7Wu?kB/Tpɺٶn{̠bjp˲>9C\rIcc4cQ@09sh"Z'_ \&?8aX;7nR]jj"1C"eB'{x5bgm_Jx>A3$toY)d=:v%W°;QĽq}l3D*1^`v]{wTN5y*u&gR6AH!ɂf0` /hFMS]2Z՟~\/Z=X/KsXZB$b WܧΒT9&<µ $#%vE-B$LJu/.uVfM|c!R:7m,Z愙qgu4Z/D{daHU7GT9ir1G{ w`jjj2\sMbwEH1Ut?y( L&֬YS>z軮暧RYTNܳ?~/gpӰ?b`-`PbaϨ" x1`H1q9@@3=`G~31ZHW~uf`+PQ_ Eߜ^ԂL2ڎ8D(qHFc@ǭ s vˁ"mށ?&DX4暩dG(1!K} #J'SXʅlD"AL>PK0'͍h"0d7Ys{7c۲!) a&_kfO׶kmh\0?I7:Lm-pl! ̰ ~ yyuyD+Qh1uz/] .RB7򔾾7-)"Ftkcwr]\R"e! b "C I^9!ZS789y;+FBK 0ϛ{ShCfoE(l|bvg(0c^0^}=-},T6"*oHX3UQ'Gf򻕛a(᧻gfrts٘,!9 jt#g%18yf:|̮,ے,s[vgꩧzP U @(q&HNxods"Ӂp<ǵsHy\Obkmn{uawԪN+Nix<.+ꩧ!>쪌.JED!^~k^yCWyi]w|YbuDLOϮ=X%v{Zqwqooç&nTgvQW&د6ԣX7Jttbť2 QAQHp!;7ST#Ib4˩f"s; d@v0BW 1ٖY4CIIɘ󴵵QX*a@P˥]m+].Wu{{JbsTcrmFB/F *$c\ wdA a+!PK^MWZԱ%Vɓ[lY(8,)eN$tm1eVVɓ'DZK)UROşT1pK?8V8ЉTJvAl4NG/灲)Ńt JB)[v !eۊ- )]}RytOXny}w^^GI2$%˿ˀZ>>j)S뻢x{J2([ts l/<1?l8m ?dJ a) sH*ȄiڦSEJ B5usʴ\v201@G+$f2x[꓂ݘRPpxf~txŷۼگJ\#)yM9t_>Ȅ)\A(vm TU  j ڴpُ<2ҧnmkbRkL_^Ghmm&DJyɉijsmZo;E/wEs{&=8o :QKRaٵa)Wz"}}>t]\~gQږIHX]RtP"m@@ADMb^qu 3N -t;v=~^.8r]%\pν/1O=ԧ}w (`:DUTT,9s,ϊmvz RqߖaP>0v=dqHi)DI„)9 (mq}UTON4^Mj›:e!4RD6[UQR*RHIn-j58a/Sm)ds$X MMM9wohh83-]SLPJ9sFѭhg ?mr(uK+~4Ih܈xۅxEbNWi JJ"R J)"EEEpagZNRA)upӉ)-LǵA(MJIB)a0yϩS\*%URر h4)}'N$D)ev=UO!ړ)I($ٯFGAc3< %pcoS_Yy{b<2zaloG,~k:)ӂ҄O/xdaq&o*p(0 q44Dnlݹ} swKP ?AţcWtWjjZQS|_Y[džаic  򄋕4efϿw'|*/~p!([$fBipB=x({1gP @ F־)0 O?fVWWөS_~-4 n_sM. O>a'|r`0mtAwp`D7mh[cNq?S*ލK Xrny O9~渻EY͙3G۲eK<ŅnEH$֖ j (յض.j)C!ae[2w>DʕJXS[X_Ylbvrggby3'Fr@PH 5e^ngBm1Iٷs*?qiJ>mx/(+PJ).ŖV+ҔB).%]I!!Ğ8)mJ%׈͑&:{Əg!4eDlչ}$lJI$3dBʘi^%۶@.˃x ' lV ZE*B!q":/y .JGkLS7ՁB* )Hb@ T~3WŦqg2`M~'4"wj%iXBɢv)zFwkR XntGi>0w/0P4))f4}]fOPZC\|' Aa콿OBWm]20\ &&^h 8SoЊ],r a_F~?|`0SysϱJ/I2IV[I*pvwJkϝ3u2'ׅw틨pNRXܶkkׅ{Cv %c,Ksut bڕLg?PڧHPB>J5R:::.e?tŋۋ/wĜаbxsNZh1m1{ ]^Ykwj_A)..L&s~N!ĦFnwk}}}{NdFOPQJ)߯z[M'Im񏏕dۣ Ev=/UC֚Co]HYmb}!r\$HYdIgqoK[VۮxEzڹj̺}X֔0%Uf& ЊߏydCcArs-*-, R+ԍ 3}<R Abl5/Cށ3NA B XМMeLd =mhuׅq !Seh t-T~w~w(aG oj,}9:s;i}+Tزڇ_Cy=TJ믿Ƙsxv+3J-nyyywqG!Pxq$z9uZ N8bނf"diA?O>xbJ/eU8xbyҝ4EPY͜p57}sɡUX1|KyU 99nܟS| s1nOU?|m%6uQkv=sj-PMͭM']'W\~ai wB'H8C_ KmK)(J)~ <}_%;]T!(sؠG2ÝJ6.& =MhqVWTqƑj5Y_jwVjy.z 8Ҳ9/XvHO(9cKjqjOf̘zi4 1hO}).=gQY5xГ 0]6_-Hݝ~ߚ'jG$zژUpϾ}5Ƙ(f\?ӮlС(..n0{ؘvmPJ=PJ4_gΜ SBtʕVZƍRɸq?^)d9xdyI=+R/g׶6tfRF)RK,md]wKW{,F!g ov%K L2)%x<;G%z0'k$>ߑuF l!!^Cz:_Y ǯ"+W6FtOkmJB3F9>x>xt^)Rjj@.δpue\_ H=fڱq۽k怺[Ʌo^wuGMӄa`!Ha(:tWg9eYp\x<' _/A EFئUo/Fjv`ѥ"~lCœ?5iS_T@,}dgJ'4mn/ж{#9x x DŽ,\Cya.؂'vto}/Hfn}OT?<#rJGeu=^cp >wmkܸq{}@Zt3 5w\/?^r<~Z0K^WZ#bH*]m۶.]tXEEEG_7\|A$D2[6tɧw[*$(jx}C ?ϕgL#ߤlo ;){!lKWV^*zZ!Dgs6MSU>}GBIAv'!~GݯgSL둎C|>gW)>¢K^S҂R()%A EzHeå9hK0Dd+~3@uu56m_b5֭xBbz9 w}MW0#E1_,3D\DWkK?ݗ3SO*+"HQ t߸Cd4UXL\. **4 dR~7);_+  H\vuv(jhh84}#80@BZJz˵,;;{ɵ^I c4ZZZ!䅪R_TWWzԩS{555;pw'XRJ!uq2r"tttIͯ^]PO*}r90 fQY\hDx1+++5*MKhYFҚsV_ /VVJP)ҳ /sޤҪ W"kGv7̏/Z.)D"\|9-{"*is[)Iܴ@D denJ*;UaPmp)HD&6+QRP 4T13&+ ZP:%2{O3uTGyuNjs9G_6nHn7bu?k֬YO#.Bc\ECX=|WzGRʜRJ D͋CX71;:wtCPHgkٟZok?GGeP,(q'ӮYަ*SoEF7Cov,v+|\nۂ67gʧ3S;mN_c$$ aee[|(%>˔^瓙-e\ҔN 7骀B0:P@)B\pΪiů+6kt+KKi=cY'bEۿuƈ_+_BOn+_3Xك*i &mNg(dV`,n6{M4s7 ÓԐO0 9ob6R0ƈmv]۝.CJ@t4/ZbE 3C%M::chjjjۿzJ 5\X,vBKKxx<._P(?IkZ㽘Nm^W3uTJopz$6sLf =[L7w\gNn4B5kz '!%In}FqPm#N$r)׳w*iJMr,˚: 1E ^J9 ,E/ms0E$dqM(%Ņ ZCaz Bn[+n (2xزmfU`swH'O7zȐ61VX4v4gjG?&sQLKڢieܵiט1Ŗ?t߄ $D[=րBoZ_Y7^ikj3o{ϟ5w vA'pwH^vV_?6/U*[ŭ .(V7㫆0=)CjLP]v'YYYRR]qgOgiZ[[GAJIwUDRTJ#<ƍPUv^3eO>A{{;&q$I[ϧC:CX末u;o1 `0*_*u]9`fi]=f5mpx㍹iɲxqJQRR 06gdd uWUU+W-}ڵt/RX }WXI)4c0e)os(2*=@Q?7:[BCݴ@R1û~QŰ3|kͼwVq݂,"sv]q:]o)uw3q,g`;ՉС’xIJsaC%BIVu;mm IJIxh@Fx\ 7ɵ'a)@R7I- kB)_uzEᢋ./~ aԦfhU_& G95<]4&ḓ2c.[ ?|klo_vF/m렗m9, a4(h  ȁXT,a#v>B?T @2Ua64J#>,\tϭsK#?c7κ?3$Y:()uMM?~Ty_@=f N:$nա 369²,|زe `8`/^s~H&hkkË/{baxS|q;&c}32uR3d0nGQ7J(!}[t@A* |*++jjjivyaDw풊чN-][ߺ B @:T@L{J!C |"Ɩ؏Eg>IWq5رcH$:7@ Uuapdv,¨Qp'k\2msAuwkmm=/B<c---0`v׻(ХI[lDkk+222ʲʂӧOb9eu))iRʽꃴBԵ^okk뇱X4=ӛWHu񻯿 !/-4aMӐrwZV{yJWLH g+"ÝC5hS໷@: .L j&w{U"J@ 8$0OuS}L%QRԀvڷi sEw (|ږ ۛj&.)-8[s\.__B!os9_medLPO̽S(|si.I&xq%+?%KPT * qc{gW O`)tD ƏVrǏOV\IR~8X^ܛ}?nz HPJ(!ҶV2G|H@Diĩi+-K*R! 'k131I ,YXQ&(ZEPHP]# *(uլg"[CUb($ JJQjd2پw/wLqݺ,\{*o0j(aڵuRJB0tPL2D=4in7Z[[;[;FBkk+֮][&UUUB|LJH]>gIdqih uܶ @捉া4^UFBH>AFjjjzCjkk୷:G:!"v)ũt)2&`soiM2C9m_Q[$lŦRђ@'. j*iz*,=ݵ, sͪc MbּH$bi+nU;HSr'=Y KbIWWW*EʭDBD+]5͝L]7)b%J!Z ޣ~iv]ptݯ!%hUԞv 6 mzǼ&)$uX\@)IP7/0qp@B `'L'~2(3$˛ˎ_W_kV>ؼysǰapW*ț=Hկخ[{A~hHV @~HQfUYL0E2bf tHk!MGOIhuܤp~ @KHuǽ4CEEϛe1 @6oL0B GTL#P >l@U_]9ᝃ$|njW\\i~~7o|… [ʴSʴsx<09J{"HNeYD"#H@颌FmQTEEӏnדqyKѰ{GV2{5m{cڶI㿬C;<ATdϤoYg58餓ZTT@KKˇUUUJ)A!`UҕՑގE9xJHFQH(6Y0QuXK.TW`\klQg6ny>Ue=i^gv]Q>wto[1y͘OH6ӝKTJH[j~OmnnV1ݶmi7돞p J)3f5!XbŏfϞ;s^9W#sM74.RZB#e !333R`bb54`:`͠BA 9aHaKJv ޾}z~J_wqS7 z5`F ??ϱG_`&rrrDY/?ATK&=Л;}[U w7s%oo)249f4^dZ $r?WG$a;jIoò4GȔ69BT>L..KHX PDML#) -$oiDIąӆ)Kg-Odڂ7y<|iRS4 p))fΜ믿Aokƌ sզUO6%ct.F%H'?p48jT'B>nX,f$IRJJ)-#999C`Y6l؀SN9%-6x`8Kz,+l۶mRjL*$Inn^{)Ce۶_7$7J Z'6nHB ~1pAwƍ I"P,{pV{{ R)%222r~|7|L(IzW"T43"wwu;945xcѭ8c/ Ш M)`TT}_ib0hZ@qKCW˚s⴬h_^:Y@*J.=卦{)`TUvE."D d*w047۰4 .Ba3ؑ6=* ~-aZA4[,0W>O'&68+C6''m_0+|_=1dȐ^z3f SNUhrr17~_*G6* x0PzYL)ls*D\$"naQd!v Tp1G7r KhnFP%~;ϲ5:\uT 6yi팁JFjaӱ!mI?Lj!bB>Q~j_& :wРAƍ*n5⮩D]zc=M`w=p8>+ը:l8yNn~ lXPn}K6zZv7oNpGri!-ϣUf4ri|lׄW=9kp$P9ʙ)$ Eg), EEE'~X8lv&1$8l5Mi-Q%R?fC5@qiUyafΫfyHi,KEQ:4Mx<::: |رC].ܼy3K?Spmm0 -H=kRӧgy淚6~avw+׸N7E 6քeM P@R$@Sseeф!p%W^FC}u]{shٝPBM&*H mŠ Լ^ᄍ>sK)9%X>˶A;Gw(QCZnQ훷@G:3fR•Ɓ/T149>//  g@!%D@aToD@ Bv'N@.!!2 {_ȄqjKsR<4ȋbnlMkNø {@(o0?"̥ф{VyZ MvMӾ?~TW)DkJYoJPNڂJ@<""r~eҲ*PN '#` d$J N} bRPK ,ց4YA|3%8)((J& >5x{=0pgpQ֭;"H$&!2c222joo&00MSߺuTo)gwoEuh` %B9kAuqKD RZXagE}C=rsraY|x\qeKq(LZ'J:]EАآBF[[p$33BBJ U~ ,7@5!cnW\CYT[%2oɪF."~y)œNMmi@(cc1p]wjvA-`]G NM8B؜  ̑$ R8mVGt?WahДa]/KZaK`l QA$wbӽ 7 8I.kS V>xUW;ճMHh 7|3GTUUm;HWvt":l,6:|vv;8;uL S.|4g/s$砄:Qo)Or s$K5=nPVb%UҬNdK~ێkm*7d{c㼵VZ[[]iW2N/] !:-}rTȢ?Mrv o]![0+0.UPfiCW@Av!Uh%!hWn>̈qBJ9 ŗt=0U"nsYr޼r0!Pk^@/Q  &@$ (0 2)@T hO h NLͣ>Zlx4Grss}v( ]׉m$<Gj5kvt B/RJ477۴iK^j@X:!@V.6 {t-1dAæ(P(G9h!5ؖc=hnnvQ;y!`AH䨛peR%o P R<%޵[TԞQЦmLpS%AtC)3IH_"]pAҷIƪ$lࠌXU_ҳm)^)AHr:.RiH&8ٲyz\JB[taANIm֍=Z< Iؑ$@a"pJpqC-@t7T D10E. FAYm%Inr3QX@/1HPz=9VTR<@bNc/; WJ$'i˲&Db` K?O [OIJb [ a@c:HrB6`tQd ӳ~ J'_Ǚm/@f |WS{l  `TSa.>aNiҲ!m-inELUһ?RNbƩAԵB ")1XuaژUzoQ]SKT)5~xdɚmv' 1m%i bZ r.UV],uSC=7-^$>?Dw~n?}5,Y=A2sk~\sDv[cw5*BMʙ0KT7'PegCd kI.lP嶬]Ńe_ur}7ꚦt̿[ÙFF(E)gH KĸB"-aY PLsjK+`/u1 &SpQmk/.> 2QAلޠ%23 QPpItN(lHt% ,,,TlѢEڶ}@kk+ƌ|vE>c z*Əϟ˗_*TӴyUUUGB!4664R? rVUU '~4=ò,,t]%\ꫯ΀C%%"dժUBŽQ4/55!m , 4xJ*f郛[. f;PTT䀠4mMf8@?|j5/_K.| QGFŀ#`& ֢yX%UR*#5f[?JIL6+r7 iu6"1)]-b8 LӠj74Ϟh:q㿡P-d۠As<ƽnP9؜#nv깏G;f 8b{Fn^س||GoW~T)PZ 8FBg AYښOrVnK$( a{y/q(c/-< t7ǴpD%P1)@D8n` ~p@IHE@DtBQYtP%N8+#H`(+݆H?v LukQ4ԍcWM%<PZ d}f:\pTXclŽFoy ܜ!x+BtY5AYUUE***ĸqNJ$444`ر=z4p\Xn-[͛7+J(**:~;2 }t.|)j;4C !BK|^xӦM㻄\LT* vmٶc ǰ  e:dj R8y2PJ 6.A(@bwI會 g444#JDD,҆pۂWo"ݝo[J'қhc;;r$aFߑVERx*hB5jlIq+Bnz O)D9/3nmxBFƕPDkkkL^9U,.A$6i~ym_~~ ֞\Ђhb,F MИJK֠v+(:&B4o4~n(t˵hYs R!H)45rNj?)K*$baiB /ĩ0t2E8JOE/KSB9}q1o:קA*HJP f& ԅ japCD Tr"PEHMq NvF 0.͂G3f>dQ09.讓&HX d/v~彻iϰd3]IP{P^ |MirMR*B Lg?M>+K\$GS!/ayݶĀm!`SPI (pr1ŕ#5i4 @_`yPp0A6Q`w(mkY6ĄGg*C+|,z]>L&inո]l>i՘5K4;.rNFJ Ptd坊79ö19QeS-OiU>LdEO]_7Jl '-@&$.ˀj9Z9gјZXv !-9}IELsiY6!IMGk|6G܊EWRWG&hHH@XQIY%Y~ZU+(J.{ˆ+&Ȣ >qg ʂMI vl''6 ,l[UvSdygq=FpMN&܄ms?=EH( Quc N8hqI@̟<~kPJxBڷھSŮ066a;l4FL&GDĥp^7~˙ܣ } b'AqpdՉAˑJ);AdJ)-L*Mӎ;Ҷy3f̸矯Nnh4ZFeYWVV>0nܸRNB)m)xO>z(ƍhak_¶m|#CAvv6~G|(,,D<r66iCՐQ7L)Q/X^a0b4;0S}@Y6~F|f`W)Vo*J]A|1u MȩOjC1?rڛ6eVG- Q1[6&ؒ3|6q ǞRwL[ؾ5M$e ؒ.`KgJH45eȃPJ=k%cT+ю#%oAjTXAՇ4s46Sv8D)ba}p2Ծt;n2pHIYU3466hkk*349D6설ʻ,pX7 *Yjnᙚ^VV}ᇯvi KMMMu] 4_HIIɋ^{m6 b"˲Ydwsqs2D,Eӻn7>`999ql)%&Mʁ>oqvvƩiKRڹM+x<%KXp!â FPq(`LCsv@Jx}ln䑝qin0VwߔC!U k /Պkvs&QE_=" eWޔmn+.D*a]m?TvM ͎ߋ2)h W\ `s  DR{qP%m;m%mKai/X5umc.}.p7JALC7-kN6gmTR)$ b۽>z`sۆmsē.L&h8Hf[j4(E@`K-r\9("gT0pQ,OBl(pء(.mk#@"+Y:ez|x49  ߶fRHnUM8ܳS|ذax<:t(<O'k4ѿ4558:t(/^aÆuRT%A@j*/? }8S|÷^t~D}f$37m̧Z?Yur)2. smXUoLQ|.>4j%>*1i`IO JfKHۂßz^ln XLm}n2.b'%ȼpp,koǖdOxwnb1p^ʒگF5 ?/퓠z(%!`RSS_}Ug}vJJ5)UuCh"שUUUUTTXE |g2m'IuVL& mŤSB 似oçOõ^{1}=&ms[nhnnF[[.rx^l߾eaƌPJa۶m:t(233gff^ +i 8H+w˲ÑG wn ˅c='`Ą}apyXr)V/O63rp;}MB$yx (b##﶑$J6t(E)-LZM }fJM4<\tJ>`cCyB0@bт  VnNBAT;,xT˦|Ӫ6W6-?,*`>*`۶a%@l!Kl涥iPBw1DKШF%LAw $p8p*&'ܙt$ D +eNBmSnھB`'z=U}az (HD?),4ߓcI~F#u"b1 4:"FwsQ1VS _y U& m-`Mޮ#&色ՑI|-t62*[qtG 2p&DHax=*ӏzRhZxWMBmV=*_h803` )t'ф1H[^fCqM绉cCc]-rrEڊ¢~H&4ڧuTAJz4`"+;۷ ]8ٴi7yc | QJ)F3W\Ӂi%_^^^fmmmbtݢ MӤ]ib充 s=oO5MsS(H&ƠAсLh֙rTTT۽#t(e]9Ҙ4^B)p8hhh@ss3x ]1oTkWA 46å-Ph0m# C;}7aE=IoR ()E|JJAR #`Hu|߷l {8>WoG$+stv@5mR?&OpwewJG8ꎲ4Ɛa!H))go/=X;B:IHۈX<6x~\+~F coJ^x!lۖx|>dee!H ++ p/w} 3f̙3vqUWU3S1aHĢX',=R4EaKVn?:;A}F&T$u~#qJ$(a\(qr˲#|XB"WޞE=)bZ x}" oE7>$@[h#n)MSr S1^Pa@QE}.u ]o#-جrA!16aj^`\Ќi8o;,E i9p #E ,y|N5=QHdž#fqqƝs 9AAעdRd2[Ee]@(Ed>) GDkrx `@s>6YU 4.7g4wBl tf< X@ԽT׀§%;ضpʕjAQ!ںEYg)^6yr<̻_% 8wJi:d%/~_Ca$'?* )ggg$j(!V/ʽ՛UhJ)iuGy$v^^^fϞ`LӤvMӔ)((py 1{ @M.B3h _y~?^/\ L4@ܶ@xuK|iB^w㛚R3I͋c6]4 4= jN"YJN^J5s`ZTcHBLvR]:kfaok t$Lhki~# &M&Ƿ㥀 eړQ`~|0`p RV}b&ӲO Ol:s[W1xu\ƽ1]p3Ua:mJ-@h'ܬ֧*JnKG8w:Ƹuhlxn x*V+\^ l8V,\P54BC8Rd2IZDӵFito"pԒtbi%\/Iॵl|Hak6ϐ7(Hl]]w}IoBVS1v\@R'!;(+Z5&\nyz/^UOmBпݚVJ]x:p^r `DždddhHxu.ԟdZTA*|ޚ`|,42)u[`= 99V \ņa,/u. J)]!33˗/+ a%ѰeCI7 f-m!tmG\x@0t]N?t˶Dް`&B*R`˪r1p$"9mN܈ef">G]hQR&G,`ha" _B*,?Lo,IlMMw_w/}i綇gSoN>W94\ N9].-w2Ѻ333* 'wttw^*8`ix-GHd۳fm@]wq̕1ə3t.]@Rt PoCSZv9 t,ei)`b I%`B,u7a=_SJ1|w(--Ųe9GiiigN0c X /Gy|N.  GѨ۰D=<,'ϚlBF\p7PGΝ /B&E\H}Ա;1Rj5\Ӷ q}0y4MϚo ?χTίPhPn~',dՍeޯ_%wqG4D_I;Lԁiz ӸM3t@MYYYH&;).۶u]+q\Wm$H`ԩ8F;k !PXXuaHccc|ߞxfos%DԹ~y !ٜsZWWOn$cb8t 0v&~疶I@Q^ Te;g 4/9併ߕi_LJ]em=wܑJ5M4M;?+l̅Si?;olN)ks]BRH?^s5$Up{W)*ܚ999w}jJ%sFVO.քo=UATLCF@(J| ܖDQoq\n֓ںK?)cr|CKJJټy@vv?xrXUU${unP( RTWW3un?VQ4|YǏٳgkl}ˆ#I&ܩAvnݺ{:EugL&gB"e[Ck>ժ޸wibJiXJZd}g ^KY z]wpGGMiꀣ|ӕ_R L(сZl޼۷o۝!<3 5A , hD^R*D. Ú5k`c8ꨣCJ9o֬Y'BڕW^_uU>=IӴ"MR0MSԯ]vA$WiiB) .HJ#gh9[N4mP喒پYs+* RWUUTT \zjȃ01] tQZe÷at硇*R7mtR*!;Xw޹JrMϝ7)?`% 1Ѹ/=q⒝"!r T^.wQjJIݹ~iׂ z~l:{!k׮RPP0>+8ׯ_?@YTNn 1p̧^??r!7@\W` Ȍ+㇑XYWDz,i@ضi,GPJ B;hg&@! &%>SI욦a!dVﯺ*cutt\.eB3gqBQp1XoUQQqeY"߿g͚ 8㌿H)_ bk_}UO>lٲ-zOvaH>SZ[[oojjRJ2H4Eaa!N:$L4 +Ų?3̙W1<ُ>pK-ۙi* m$ u9>ddd@uL8yyyD"hll~۶"jժbi:o޼ 0`>izJ>2~z,;_XWWw#!ޔpZ.xy2xb@}Ha)б*M >?9]$ӷg­-֍bÏ)႕tgfxſ*~oZͯ %6!l<Ҏo8*$Hn{mHYND"xWJ>O}YH)1a„᯾K.6T$2:>SC17~:PPId'IAbW?QOrY;gIJU`_skBϋ+_9*0:GEn͛7x^L8cpyY?F>vRJ]?!ĶڵkkOՊi&vı4  4Dꪫ&ڶe2PJ{DEK)ղerwޞsj?4xNj s9)0&PdRRJ1tnf޼y3!Νq;/ȴ+oTd?= 9;RMeǿ4@)"DIB\=.Z3Hʴi)?AMK%AဠCjVǏMor)}unI[0=[_DLɨSeݫzhXKK[mmmv\4E#UGGD"FNN=;c#n(doN8Q1f2|`Biƛgf,t316077oLGXB =cߗ9ї>AJ/Z7tg/oϱ!& q#?dW.-n=nMcn;!r)몀UetZ;`Pso=r)+[VU17PMEܽ4"PP(D/+++Iee宯o>vme@`%>?Ó8\ mtH"" o ɭg>Pxnu[Yl6+S? h:(s% )_xᅑ-[vå^ JqeMu%`@ҋ7!d|II]ɶ$a ![V)e'IԤ"fI[MMMH$ӴmRᙙ <VL>Jz^WWw1P(| )PHmS] R !D^^z駟 lڴ7bC"wR2l{  $`Rei_p%5*g;R BhG8(Zz3RcĂ.V6{\R3Z*$,[[avexa()IFWx[[ۭXgY뺞.Z B!eYv,Bn#\?SӔRnBn™=fP!iړ尉'ӮfOwғnBJX?iZ!}dN Si ײOJvٝcc#eg@#׎g+!>w_2f7xs2h4ָeӄ`Fm w}SOEII F~ .e]gq;<ضmo3gNu<~ƊM_~VBHSO=SOuq*$@.8tp;pmimd+}` -+iD|өqKzӶ-;KདW:Z% x<}N{'%n_JyR[o 7 ۭtàET.dm]B_. ~;Z)E(b8q9sX'8*f*i.2a,[ YYYDJI.U* ZRQQ!~ǣJJJ\J.iDfW˻04fYYYق*VHEHأJǍ!"Qy׻(.ٶ7 \/.e+B v@T2i@ jQ_X  +:'{Bƌ"kܩ2 |ѢE+rL,SJ)f6 anz!Yf۶m{4 @̊n !xt XnJ b(n9"xܮsX$ uR h^8G*x4 8GcY#(HMYz2{w-|@D2񀂒e=/H"dV:O΄RwyV2y,1;&+3o_$7o0ajRM>]}7ߜ1bD_3fl_x .`+s2cƌ^{mmۆCyWݮ{Q o(!Q (HD"&`D ǯ&oڣ`pUMykVzoD)<#E"?ggw%U?Tsg@VӊL(QÐ%M=t9GUݾӓP[߷ך۷NJ{5|E.k2b1"r\uݯ\z饛ǎCo+]շGx'imZUSeDԃ MϬq9Pv_?>MңͲad`~y<2e@*d!L}9{t]oo1}DފH$bdB EaŋD"oPqH6y"NS?|uRd!a,aϟo0+C7 ^h&uND"?`֚Ç@ɉL+bKQqooos[*ˑafWWWX򍺻D.Ӷmsuu5551r _k]ǝ{zziӈ 1 m譒J'MR]]BqSkk?¶kZ455HQ B)b0RB .7oF6.}] Y$IaB@@CցDc;AxjH_67UX?Ecw_gjL' ,wog`1ikNbֈ[/<_%UI))|+**`6D"̍&f&qΝ;۫ ЁkjjNwѧC*R %%aA0MF C(! #n ?MVZi4JI-Z΁4;2flJT*.a#^aU~*^[[t=̿_5i%pk;;\O~}vJ^>QO'Och.쫮:묵TjۓO>^xak_ @z… gMStOO>ƷK--݋R(.^Na'?R$i3"~9 N+12#ה<`߽OSK˟[ "R~ 'OKPF"l޼WSL1yw0 FP M6!ČJL4 k֬67x-rŃ^Ťn;J <8qm>4iVYs'M<.)Je4% |-\׀{^{+ h)[̻{\r%O۶!uUhu<+++_ c׊U$a Tq

_?n{я~UUU*bYV!,D</\b뺘4iN>d,[ htzPHXkq=E_}ӧQJ)"*[ff!RJ!HpIIIrjԩzg񏶴ͺƩSkCt#uPa*VMZL4մgfI(/0龋SiHPdK [LՃ9_0!5ZÈ!wi^ǹ\A>1<<>m6&Olڶ۷sWW*--~yZК1 4%L2 Äaie' FXR+mhPJBzH+?er~ZcEd>toR>M4Ԟ'NR; 2sR@#3>RfUesoxCK9RsV\bx 'Xs>d ekaSNe_t :}=tvu裎3oX7WćO8H+g4sT1(D7v{?3 {94i1XA-zE>Coo/ܰ_k&52=cv׿:!NRJ+<<4Deeem;߯NHAkD"uq4Md2tA|Ex#iyуr[ "=h#r1Ͽbr]8:YzY @+c{e_yg .4|Q!MHib= H$ÊNYp"mW .^҃J|/L"nnn^{m/_+<@^6 *BP$rURJL&9X뺔Jf$"PPJJb3$ >RI454KW^o+x^D&`f%PKf(ڈ|>дRJxG_NL&y 't]w8ZRJc٠D^hiqPwرtQAWl693e1&84\e( è{q衇`ihooǦM0447B9s Cii8(ːp-[`Ŋr3gĔ)S ͛cر8裏E#,e)V^===488|>/h􊊊3ZQ$9/mQ,ufR!d:ױg? tP(+gvꦍR#a(-yV)\&0|98խF{|%[]y`Ӣ,CSԌF Hɚ?j'{<;!ϻ^@sҔR"R?tJ)V~k^ T03PhBg-B .%apBfPWE .O`?eVʳlN~~E(P>] >O5kFp-O?5#މO(}7>?fΚE ' -؉o!>ٳ0ԓڻ ~F\ h%~fZ[n3pL;bs1*,Q D K8@^)#PSDG1%1>0 b~ !߱ "YQɆR0 6nu!mۈbfbe]VxGMӄH$㌿"UT+)<Ѓ[_E>kgs:8tfLy7w1vIiGqƓ‘,.:|!ni AeҎF2"З4@"fS;;96ΰa&o(]U[[k 8ĢEeq"@B[أp !}=t_)ޯMDDwڥMf|[ߢ|>_Xwl)%$fΜ4ECCV^Jx6ŤIсEa8ñn:vaXnϟvcxxBa*}z۶/8w]6 e/\؋\blhbe'8Fi OJ`)2krl6~.CCCC5 aΝO]UYN=:ֲdƵeꅹt3;Z0ٿ*fT?g~d:MVU %}mԧQSy ,7 狀iX0p4yx@0Z <<(=wltқΚSmp6CuBF.0 >a Zep5A 2ǰl,9:w_<ۖsEp kzvQ2iYRb̙8# h4 ۶vZ_*kBE<#Jq=(af|*I@`1EoR5Vo 8H+W"80IPN]HH3җBGcYDjc~:;}VCL3cd vn8]4LkDFoblVZ%eh^z6o|"Q0Ű>P Adyu],:7kmXv1cF" `xx-L&d2B^vB&ip`9S ۶??顓O>y3Th=wŮx)%sMlz衇9蠃>i `X8 fUZcaQ7-`JJJ P#`T*5֭[W\CCCشi,X0gF]2 ]ej( Q6E:EssX`I8fH$E(ps$1D5Y ,, 2S` ! /b`ڕTg۠O ca-p0#t:#1 (LJ `R!@di7xËuuuJe6m2 {  ' I:聮P~-%ðcd5!"1x`rG,?00P  & \R  K+w=AP)&v)`- w7wQnSs6?Oʗ|> /,9˲>v]w]|wlqJ&ٶ)LcڵW$H$AgΜv>ED1˲~eY~?(H*'li1 9kh+j0f H FM[>'| ;)ܺ(ZQrxŔIOĤ\H Ln溺0+24- +645c^ k|>F5 fHO9 n\X0LC8k%HY18R|  ONc eƐqPީ2Mx@*u=}Hhkk1O?ӟo@o~W\q>lΠ4Q 4HIhlmOZ D"Fą^'|˗/G"@YYY?֯_˰b lݺDp5?^xyUN2{$< bkԗ,"oypՌ $Q??rBf2GmkgOyg655"3{ 4G/oll{zz#bP@)E|UUUXpnlֽIZaQ/13cǎl<fqeY-뺮RE ]¬Y ͢C7[WWv؁L& hhhpn݊d2 6 H`PJa͚5Fooo[@744cnM0hPQQ1z9#۶Z+eec,+,fo(ذ]Xltٹ[hAk2ZEE<g 60 ̞=Dk׮qu{{{1eʔnbŧx\.7XYYY)%%%m\UUu<|>["2"ȕgriimay5009\,3ˡ :^j+sl0d%Q}崄w1WdU CHkm`p7 ]Sdԯj K`}'X2`>i o !xTN:(g+~+t7o>$"öm DžE v֞{W}L4=7jYkRBH9 "1w}WRqaԁ z YMp6Wr{tFM96a0H0aVҀ4Q&$4&SZݡ~D,h Ϯyz}*25;|OV@u`!Y5"e024*ZCX3H#C1y PB IB$j# -B^w/R,X0/ ke xc,X֭7yDpMʈCmC=i)LfFm)FLq/Rr_qVCCf tSSjll[ZZܐn"H!˗nL7|˲ ͯdz&tW؎.,.W΃\.2 4MD"˺C Èh9D `˲(Ju|k_X^h 8W֚=ϓ .L&C;wGgy~x!y< =/SBp(sPRcЀ$32(fԤp5@в1)C̎@1C=)3!FgGYa[+ Y/'# UV^jLS=WWCH &f`_NX6!Ӂ)nvTFubKp]B__(>… m6r9ض]vaΝ?]x+msJn\5.5 )P3.2FVypH< ݪQ,}wV3r?Sffiiiы/J5|""[ϛ={6f̘mfTVVbppX "L& KmڴXjyDtsss@fǛGa}k_Kٶ2Ϯlkkc׋`Lffv#v؁˗K<'x"&M!kb1W^)_}gY3;̍{'8zzz @4y6(Rɳnnn6W_h4]888E/1JKK)>K%%%ؼy3~mr)HR,S"VEEEPmk֬())(Ie x<HSmcYMFtZym\QQQ(Q,R߇er>)aoфӂlAK++?H(? hs~Jy@f=yA/*&|K_?qxץ͢-f̈́-6Z<)&> cu˔RhyH pH,dI)D\(K$uDpA@Q:f.X+`%thKOb nў#n\] @Acve _]}0_Xaو6Fe$ !*[鳴Ǻsa` ''GT?4,k^!̨ }`π.vA ,_-,aNT@Nˈ3xC ߕy/ 82\Z~24scrV41UI³6.{HK#\ZZZΜ5kַ̙NL&NL&1<<2dYDQ&@bu# ,eԈ["]SSsӭ;+t;GE%%%)XjSPnu]3H:;;?naΝLRV>7owvvjΝb n]a~dX94Mײ nҥ҂Af_Xك===c#R7ߪ1Tݞ.Dh/0Z~}pG 8qQ$IXUccRJl߾/"h;~֖H$n5k֜\.. FIII-Gi͛7^zY,]O mS"s<[q8Qnx(Fñ3௨!2hic>ǹXd·_omo%$މO0HUG;%c"oyǛuNVY3OkՅWgOc0nqjaHcAyfIPitLEI$=,r|'p׷ Ǔj8# a!A~Vmʷ!#f`+``=V cp$iX@0>0lŀLPʕĻFy._|0Mք=$<}&@M]j>َL_iUOKz{#äCC4Q٠!' Ϸp޻VbhH)êXŲ7S.pOOOaknn;vP Gy'Of^>7HZUUfFMM (///(D"N%q҅ZXߚToRJE>&4Mu矟 ۵kW2YVV?~9̙3̌2k׮T>_w}qccq-~_g*_ث9̊or-ƠxۆEZn _җH$.NRR11RL$?oiilnnޭ\h%vtt%\2JrAL]E.?t:D"QbU엄ێG)6կ~yꩧ{^p RضmJR_hii錯9+=!6G_lDPP!o8R-D7Ր,BKK\ 1]@*R1?d&l &4H5f;>իZfhKfP@Q`r,B2 Yjq䲂V>S}R/~5?{E s3 e HL'a`< Ӵ I&JK )~j3kH I-a 9Oc`0$ ZV J Ibxśd1BiLHegTЫ:2&L~v="V ZJI' D"pGbҤIXPw:>UB;_Ry-by0%?*UEwuZ7o<-L^.I1= ߡŶmm6n{־'-<Ҙ?.K.(566 tCCCgEQbo3eY<44DtcIϟL_ lRJsif$iohhIؐ}xD!7@II 9#~\.h4ZpիCp3ulp[ԤZ[[>̝;6˲rT8+ KMK}}}Ν;8VmGxDgߺw5Mf[=Śăx׋lJ=I5vW+v_#Lk@:_veI&.u~h`RJGVvSW?9eqqJV6 QT19`G"y6MSA5D ~17~+:HHʶil;x"v~.|>lO@<;?9=? ̈bgr?M x^ 0&ں%VdbJt53\ȸRp h6-4 -` R iTNIªM)xv8htLē+_Fj̀Tw{_e:߬[%QE|U5vIό%3DJ/ڒ&-"T b+ eބ\bTAt]> /O>$GE7oկgŎ;`(.{³ T3cz =tbl@aD!}X9G?93\׿~ܦM@WWW? K,cKOӳ,k˾myCf&_̞=f(, :ض 0??aE]{tWs=|g,av@.}ޫzFD1S2Mٿo>w뭷5cƌ+SJ 3 o>,zF[[[W(AݘbfE2^ ~1L$>+~lRqd88:::#`ժUa 33I)M|+0]Y y0, y6|0Ԥ-[ftI?Ә4imAc k?s<ׁa#'45A-[<巿9\kV^fBK-@` 8\F42@O}V]{5/6Ojj+ͯ_8ǚ|/hH#/^达 %UUG,gP΋7E`a$cR.|!uuuo~<=88jZSfZPzwfr.d2iD"'(mC`>_ _D`>_Jy?H|)ՉؑW0GϏ+u[EC}RJHGB0,O#l;Obֆ`w?33oT'E쬇Z 608׶-x񇁲 g #?vp],L?Zɍ0m4|$"~ZFeS)t8/xpG>,n"]vŖɍ0b30WH%\ W^(9tIx۶188XHS;~($bT"*9`ljT׸\AA!J]qy-'?Lk]aÆslF2lOf_x|OOITt~ꩧ PXa* 1h4J777jժ%KaqOQJe:-[f>nBZZZHRWmݺծLQ#a;vm**{BԞ6~ _Bv$1L&/O~ܞ ijx#شiN8|؍}v[xW0<<\_0i: :w\ E?~ L#%3HQqui bI'$ ۟xw2^|Ry1007vugr0nI'- ߾7iȩ'X1Y03"h\g=FPG]e:E?uJۺKK/v& >cHb0j`h\Ox gG~|[Q6aO{#;yXY.ދX5<</oy{XhQhs2rG&h@Y,P|"_ 5:9Va=kyK*:ײ,|cݵ{jmm MMMHss())L)U"3|IJЍBafnÆ }ݻ׻PCMdKinYV61tgcxߝ?kgoO+)K XJ7 n }jN>1!*NQL5`fZ3VBj'5ܼB4 bt(}+! wꞏF708]Lu ;%K/]f>D^kE :aTXiǐמ?ͻDw%)H1^w5ٲ 'NSSSEE%8`Yz5qncq$ tMnnuwwRs?}o(7tam׆n!0 A{zz D"E"(XDyގ뮻nuh^uUSXCǔŴsI+m0ar6Jr+ ?pU<IDwӅ^8}&!? ULX\ $6pջ{ڧX)%%4/W3ߟA]xm8%H/\|_B~-nB+bq -0?o~Bk̴>R3/@XG^>ASwȠP4PR 0#>%SKxKU?@)!{4aF4Q׎/j  ?c!IFu***^MMM.PλVE\7a!F#Fpх g_ǧޯ.x롇%g&SomY@sfγ(=αCE_Wb⢻3|937 "e~{s6УoZ7vO?'x]8LKj ҳ&ƪkĉVVUYn4DqBq0M~uAm4>>kfpzR_gQFx'P5?{W^9C9| >oapsP(& T)Km$xZisT>mVj_?w0,CS<'[r}^Q"aʌK?LѫW]읞> eU9_E0ScD[+4v?ON3qD?>uۗ!T2|_L%9o<yi:l3 ߷tZZ21 `5U܇oڲҩ;v{;BϨwޙa$,^y^ $%؛*J &GkJ&Är\[}Վ['A8wӜY&|$;ð퉆+uV‹vnguAwpoO ׾sNMMՑ}dԎ MfoZf^K #2O/D8|v+ۛԴݨD$h$ fl.p W]W\a]9*ښT$7'JKT?a ~/AD*˫PW_iz . p9W!!cQLMQgZAh߹k~n/<Lmmmf{{{Q/Z-YXhmemN;{ˢd d5]lnnȷfnVz&Ht'2,nsvUx6gM\/TqC@m[2CzN;^Tp7,Y.I=G VN$5ફJn޼iH$ &j9uww_nll---3hZ"Y¼*~;t* =ЩDRqD:͛7p'"w9Uk:*ôUc3}ZS<>g?K1Q6L|~Tx"=i?,pkkADꯏ=2݆\Ooz{KǒSc`!]>uDjXFFK/boiQvG-FpBXjmmm]466R[[nmmMMMsf-ĕjKm a2LׇmuRbrr4Gck빳Nx W:Ϧ˥a[ +Fye/|9|otMnf=Z>gH}kߚ;hd ;I0\MxkV{?/r7815PeEi xy_'Ngz Z P{tc5uذ,VtAT:x]-CIɤ3ӟ=Om0\7bIzI@|`d0LÀi-"Y8;x'%efh)cx2q(.A:+5))hײfO%n?׭[ZSSwu`Hp{׮YW#~m~i̡ ,-!]\-5qPȂk2 վlcŲY)>46L7mێ;PVa[+ N9񃾆pMSm3-Dwnl oʤ5A? -4@ YVRBѺI--L&A% !߉΍H$Zr˥1s15)@AăEh= :7ML=aadɉl\cUd ZzCԳe?7jd, 9(ZWW7n"B޺׿|7(_*KDj4a `_h\3`9ZHfze!ԎZ "eڥ>e"ΘtNPK@b0M| y)k~w6H`&ٯB 52JWkd&aˇGM@.?fܜLgv}>j[N4`VE,Hyif9d ,&M0[Ew~;GUɉ%Md"*XH{Oz$Gãh ˣ'\. O:m; ˎbƕ<"V^W!~arrl_jIֽq6$hYn~<[D H$DȑŒtCzңο`l2t:Y__>z7w+3ömlݺ?>oDkl:F|b0(:οV 0|Np#Ɋ9eD$wu}s9!ydd7ex¢,BĎ, ajkkEDޜ9s>o~~+f{oc[lW!.64Lm~e٘0a۷ \(ZǶmLO>eժUUi 90`/,M @|Tp]H$wwdl\Z~Qk!0M.#&;q.hYdU}(fvq b{2N 3471b[K︣K_1J: "◎Iܝ̢\:~#Bx (*Pb&8)UE0AH8x~+"JiT)Ry)s+_y_TMr#}|*yKmJPAn.J|BB4AJ1KiY, : -QϓDovtv0y3#b[E%s&FXDujVN<w8,70o֬V@eYaoZ-${0hG!]^'#^sOڼv?1qy}WtDy<Wv d Vy`-p2"d^x!ʹS@r:a>l?t r,ձ}2xOa p=XEi \vBo_?vvu#:[bY A hhY mu 4X|xAJ̬rw[X{J 92Q K.:J sf V L~o\0 `W_,.߮-,"oR~7|{ 2vG7d66}KȌA;Cl'[0+` Hs$yrRz"PP)4r\~ |ShTodd"@# T|@局 v<\hXzx@=70azZD ,?kV~av 0^cfOI{hq> PRP1쨣;lێӛgѿwFږFOOھ|y^Ġ K("Q,@LKLÀҌXU==} "A찀G4*=WV}k4/ Rm'i#.¶ZHN$i&vd` D?}/xyU.L}/S>7]-DG=iMm r@jUkOl(Z 60 7\<ƁHk# jz|T%b-! #L8qÍ#)r}===hkiZˆ#0tn/f@;,Dʂ1G]w.ho`;QHDB6-`-45 {U3'D"@,,*=)'E4773}N EgT >1w\̝;ws);j6<,DCC: Dk4-3,߭*2B, Zk`]|-~Nw;PV^>ӹG9;Ӷ|w":X_Lڒ `9Cn^Ё68:2b}uߌ ,bGvnvu@ k$v@jnEiҍ$`>k[cF^JG^.2H Nwu,˪ͤmmmADe)1leDŽeNw Qy0@DV (Yf/hnm}!5SI 5Z Ԉk>xfqĦl Jc >mO?)4O"6q7)+ )_էhQse@ke%хm=#з cZ4`E+XA/֞0;Ά>x*):y_W*21TXJ)\\d՘7o^aB`Æ &XkXC8Ru " $`vΤwcA.RJXA)Xvו:mہV|ދZZ=y{c }Z1ӟ?a˚ކm;T ih18 /UR@YCH(V{K/Gp ]HºK/@i$깳eKcw?y0k%^b ]$5SNԩSvj{}XJ+;b|$Np`Et6q>,+) sJ%k9#bik[)7͚S6`?g£"[1x>%R( xxi@cf#TDTڏ0.Dy`. ߗO"hϳݨl2u]SL瞻ϲ3 k]]=>XOh:`X  ҽqo&뺨(mH)p]W8#"Gȋ[cb1,`uS* 5;Wa`fu 8Ӱy&N@wWzk"^GN^~Uʋ]=?$nw~}/hcA% !{(@j~i"gҥKtRYffgds"WT! 8юf*W ܕ< nV(D"%t:jjDmf2Rj?U ZZѠ|ճn&QATXy/vJk7cgn<dn4/bR0VϷ/<}xzu&c-* {;z 4^uƜӫZkhA =&AAp!VX)psA3CJ ijvmf%4@Ϩ} JL{-(i1JR֭[f!mۨ*\Z#b0Rr 0,vO!6,xT񃰇}i1B2EOЩ``*K?vlA {8dƅ!% 8N YV#s<(a|`%|60x/Ҍ1ϟ3g|5Bx/ u<4L:x-0m4L6myN-[63b_y>}:>NMRC&K u;HR;xxj.x`O<2 gs]8Tfʹ:r7'vl̆Cte\ 2z_Ȥr4wѱeͻ0<"yJ _LL{Va7:̌6Еzn;s7ckI~k9jժ'ߘ3gQ̬ɤ-oO6tlV j{)"q`/<۹u!ܴ`uOg",E$=@[<*OOUoVS9 Z|G2|FT1GEi6@0DA=zDEz3F=k A%U?/ώ; & d&G3xO,u!Ky߬ϝ:sXqmnXfЕ-^]O:uE:b{U )ҧטX=UpBwʕe!lwFDrdY41 2);0C}%m^>pMI>=;:ctoy-mp5%hx9E** ~9P.j́~j-Iz#] @GWr*!T#}A"|haeyy9bب|JuЀ|>_υ.AXJz@UGDp7TFjgd|]z/FÙR9pA9dɫڇm/g[u y 0b`-A"SH5I>kZ?o6LF4O*?x*Ϻ;[|LgqR(--- D\.^x+WD>„\UD3Fey0Td&U ~ۗl+JDvA #-N>HIDATmݒ.Lm~?%#ZzТVآFS T =3ߞZV}[g{);Zt"- 5D3TpvWu=[S)eiX!<B xG}[BU ;uÃɥ:1鼏cZ1l-z3 |z#:μ SV~rJ1ϱ6T?-mt) %mPJW fX@"7tu+uciJ n]nH'S^^v7AncCՍl6UTöm`uJA,h 7_D{{{!.(fϞ üD"ظq#2~xwO4yhڨs~zn ޿ I X.JG*g{[G61.~7*4E29J_1 #vZ,:;;oZRMwC=覗R"NCŢEvmprfW\S0iTL1x`-}P9d2Y'O.I)d Zmm(x CJo\VV>0_M4}7mGvgX\Opcc&in͔\T69GGey 끋bY &&\[«`f-xm<`u8r(0Z#H LJ E)|>[=OAAI&BǶSxrĆb '4M{aŊ㺠dz!c9fT_P0TJ v^` ^IZZHvoiG**䱅Bӫ9庶4K.z_/G>Z09aP"~pöO7m V}U΁II5D_Π[7C|VMmxy mj7(YHIonkٕYw}85p﫜_iE!SBgb =[ ̐~Ӄ– !A.)Ύ +A)kD2g1TWWsRA0NgJ ,ǹa?AHS9}C Z z()pG']9\%S~3 yZ>qB878xp<@#`Aj٬ Nn|`Ÿ) |_h݁9ƢUāGt.yذalR V !.̙y[9|>saX]`vsW7doy2 &L~1܎gŚt: )%G=7:T\}A)"!q\|>qRBGtaFbT?!`D8`$njjRbXVq/6݀keI&%+ed]7hv -;*Z_'uYHMdhص~%n^l-"755~pC;cZ뺣jbEׯeɒ% qȸtihiifu*1xXJ֥0!ZZjgڂ^%ƒ1hf֚L!@Bh4s(|w;xϯCһ)+T( Bm$v~B?pA+BI)z?8iH JcykR$' Ly0m?Fi (KbRU&"nll4kϚR?a^ybKx~8{aL>3gm7ffoBaIy9Jʩ Zc94$E`s&zy-] z?o(՞45 'ocF%I=y+RE:ȽՎ$|Z|GsshY@~)FYdц A<;3!=: @-YVRuvvp*mZAm,J&F$񭵼LFi1$DB$CQVد,H\)@ V\{=XY1`+oτ.t鷵1f~Վuhc{e׍#DDDΤU Q QK? lh = ~H3Su]dYX[(YO:}pNd=\2%5SK) qc͚5+>,1{l̘1cܡH)Ln*5<>ADƃl `Xqo(Vf)d2_ {` +&cf&&>k1$ppqj|yH[[;;7O3.Z*~I1PA" c;1"=;dCr cYR)9t5ԲhQSy [d;Mqf27$ rDTwi8=dNS_ oElQ7㸗ݣyW#cfH&ds9Dy&#jTay[۝tVsŋ zT y ( "M<8׀9ezޱiB$@hjIH(;6 \ ]c qﲺV~|]Y}}={{̙wH*m6M{/9 EW@$ф-Kd ܬRH:фP/H3  @+^\, 1>L,hnܜ L.sw<LFSi9% ۖg-9@AB4@z?+/.P>fB Bt׮]KnƺJUd38FzhT*)$@QQ۷oMӉӎ;!J\6o߆OR7ӎ Bɽn*V87f_z1ӟx{R)tww#//Gu YryЉDb%KR7|4M6Ԧ$s(YW$aYp\BBAooopI07E`D"a:{~p NUEL؜C2¯ ^+ &$cjǶQr*_],a",D(-T-MX{Rȴ`nilj{pIyǴc Ӂ7LD(+G)Mb/ lvp=jmy'^J_(TB8EسYpj׶rmssOjVj sLtcJw~!v,; $]3extcν;D>D0(7C c d}v{vuW?;j3` N^"zD-2#2֚^AO0*p%4SypHwY¾3%h;lWBuZl3}gĕ)]k׎.{尼aD' 4 Znm)cdˮ-2O!:'rx??˳g@$0d, [74KMqwy,hAIArmΎ=ϭ([+ Ba 1Rh d3쳱PMMvn11d6|$v䢚9wbr'!9c'(!}ꪫߛ/m˖j͊@Uv,h@ȅ\@sKsGMMnw_-k7laU56 /--p?[Gdm \Uqk7R_> hɶ?촿/ezV'z֩iB-!Ql[1+=rCWt(ٺm# H"/?\%>,YB:K/b1뇾1x7J/_w p8'B]ti!ƋΩ66Wo;pW}`A֦ng-RR) Li~&C9*КCE♌3zH2稣l*H'S2̠'oA%YoO  H#LRJUUIOOlmV|ی1mݺu |rot@),STF8opšq_8-'e~\{qOO苎OH*{Æ VUu2MjiiِJ@~ h7M{>xA^r 1LuK[ zv(%LB:F*bq|UgT+V $W0v~~p`²P`98,5cYӏ*J ۖ&*p=AF8No5ԍAc0d09P,^>ظ 555ܹs`WI(fMNf) ]vmJ)IM`4 c?^WAˀ.%cD?} |oݾb6C{F>ү}GZbf[wt+?mZřgYk(LDdW"hu޲qK,%J$ֶ}ɒ%c^/)...4MS{zzv\wny~c4ga,kaE@]iKNc|ui.%%% !dÆ _R?iK@l` !D*B_H)I]]݀fԖLm۶HQqI^&eD{{>N@iؾsEf/KMRR0 !*x<.ƍ F/H]]2e ijjp)k"s.>zԎ?n2.{?nYVV6R:m{=@kι,))!.]mP28yO@qZti~s [A wQl0?evuUM" F1~rΜ9$LBQ=r;@![w7nk-蘗H$vr>p s %%%~ ?|rood@)%uB9aYXh\ڜio>sĀR*TaX{))c<㤔c`5`BdQs8ߟ7hvc_>ɪ9Rz@c,,,Ts̙$@԰ōboyf}ïHǨtڟ~ޤs>XM;PZRoaqo;hANÍY'ԇ +BTUtZ%c\45LUU^tttت*sNϲeˆϞ={GNj_heҒrJr*804ʄT]nk]B!fɚKYG?yo6R6W^&/Z lNY?,4032#BJ͟GD:bzsܯs`}=ˍan2׿ZUUU84ݶ=U&i.aNS2hww/u˝10O+'\?[4f]{P^>dBXI|o[)',+֓$F9_@8ۆ%uЃжm_^^;"qA)iFMw76J,0mK>;㿾f&x™j킈uɈ.m[š64Z e|~֣pEBr#M7,C8+!IU_YET7b?Ѡ=~{WBZ_?tc@sqЦ(`89Uƍu oSʕ+W1&&y|UDJt!3{LR/>K$C ~})i[և ^\ZQNNR(bB2D$lsώXyH"o.%c47 ?U$6̖TQL2{Rj`yW_9&BY|X_?;GgtEJI/^L::Z/8qsn۶4M |;}c}V ˲id9ex|kȂWGc7=jjܺF.@V>m:#97],΂O:1^=W7;76(:֔f"OXmxn9w_o:{1wG>2%HF\gg~:iMy>fY0zqɒk%KCUՅ| *jC]] ׅe$rCd9/Wԡa/v׽$+W|_ ]q{F[ Y,疍)w] 5F4"Xd&} bYd:RKIЛJJNm۶9cil@%"N,˴$a{#-xv xl3 d(eZ i dW\?z E: a/(){||΅v/Қ5SzBa?}tw7;ɶ-~g1C<^ϑDpN D_Ge g}Q*xƷ5\9y{(ȼyumݺUTUUQ)%IR4>q{>cyGܛ5) #%d@0,i&a$.CX<9飻 ZtJU .?>O.0Hh. F:±oGN?&`}>gB¢>Ȏ oxzQXRVp8bJX.G"W[",} ='@ "dvOAwqLhA#K2L%F Nj\|'[yڽ{<# 0 SXB ȷH%WdIJFg#Xw IN:Zr}~"ۥ3|E/ ' A_HEALH7@po*RYT)wEؓ}5) 7bI-/m¤.>ᢀHWy)Egu ELa;FtF2d/o{ɒ%O6}cƏ?2NrσzP`=y4FP"Ӯti?G^iY,cW%w繎0 [@ Bž$q+?ؘ¯N?=a &0\[`0Ek٪SQQr): g/ㄲ`v.Jp~)0 W)apla5XdKIU3 TLDWK/\XP ZemmkE5odZA sBaEEtӼڜ-_D(ԾS96-n? ~JbH7{̬w"R8(HJ@uhZ*I%;Xj?5T xCE$"w ~X ۃr]˫if40HlS5S&XW= H2aÆ^ZZZK!4P >---Czk͛7N)%+dr5Fn7=9 ˅x,SZen6'A[Gךr$K>٣y3Em9r 5U_9tٓ'$'Ymurʧ`V5c>4PPK(. 2)9 kzܡ%> Ew,y^(.C!J2 ݯMJtܘ2/^JUSF2ėZ]ɿdmWRo=z֭B|>bٜ2U]߽!zK(G9XUUU+uRIJ O|IJd6p9d\qk۩P\~}Mө'5#ʤe[1 +4 PS\P2;aV/Fܶ[5W'q ؒ>wS"$rlQ72o^4Ӫ C7RS]h-(žBR[% 'Զ X^j@ G4OB!Dv!/j$q)all.q?k7_0Jm$y\BAb)Nu8(B β$V¥x<^yI(Oö Y \bpΑw d=0- iHbnrp Kw|6|AHV i/’&B1GbPkCK "μ.܁:3+82(lې !v~p{?)'xbM7T|w~>a׮f=ltYlEP*r&nkՀs>#׋: BJX #"$}8VGmƈl2y-J K!,{{>P)"7=I ow:0VPHff|R1Vv.2NPy'^YՕO2N)PRɃK=N%ҖaZ3# : RpH+ CJU>7E(x4 /&^9M &,˰dOW0-V!U;?@>u[6XV[Cu#J(>xug+vhr\XnaStD%RQdg@ TBu4`VtnobX\H˲ %a4?~}f w8m:,@4P(qiP@bW{ۺeA kɓ{'£ʵh>|il즚UBJ$ >hn$I%]1Xͼ01Ǽ𵝄Ym^ڜh49MFUUJKK@t]Ñ-++èQm۶>$ٜӘ]4Ǖ́z:.|yhl_OYp<$< s5J(Y#cB$,/6.捱!İ555s"Z$Zw1n(.r !IQ ) Wmmq\"M){Ɣ#*S%=,XHoZ;>[TQk%( `ɿp,V ;7׆ŝf-TrMqR^y" 25H 5hcNӛ??Q.$De6@jͲ1$ fDNX@Z\$J"zSSN~rY^T6CNGr rS2{\O'">!,냌 _&8zx~.xR*~d+\1$1KJ}~#~{. #3T>p4'm2qBZH|V}"hȬ}.Y@p-))(0ԅ ߑD[wQJ]QIeHIE 1mUت7[*|ExC(Fqv=B+LJpb/fH$pV.{Dž@%`}[uC22@ ;t,o }Gm]BDP!P0 ` yM @2p<m ַyr 7$NLu!v] .BKINRFi+̯:ǣd2`0bD ,-wn}[36jU0Z~zy6U:֢ixC `B )myr%m<{E>BnH){V'q^\\~%З-)\'h4Xoxɓ'W^)z뭷.Ơ}dY(bGG ABh3fEV,>~ǒ()$ |q}J޳4Mdz("@d`.BD>ɇF"%@uOpI\RHvA)"́|T񏞟J5Pۏ2Rz#TLh:KbXU#CJ[#)nKsN6Y0sHAQY)*̶ЪV> Z4**s-xt<:CI!ppہmY:c `J$|12<+:Bt85nesKLX0hB@(DwitvBH=LJ74ǫoDPúO{ar (%`1AGci(L2x:,[ΦpݸՉ%g1<M>Ԅn0ћL ^f'mZv Ə `X3E9WB|>N% bvDw{jBr0d &#'ͅaEt̕=%0QNJ!i%;}nYdGPKcg2fjWd1RR}\qصe_qK )xhz^AkO)6 n7}ڏ…3?^aA+[9~UJ!H PtPf U*WsH:H SP0!xr÷+"g 12 >sdgp]M Jn"ɥ<=vB![oҿoݺeR&O?[_|}Ec'#y?zzz)=zI'`mmm`jN=Wp,)(TcNH7(64>sgMm!" miIRQDP\OqTdlKF"C0D}=Zlp9sQSD0&n(@!HQJJq5k\)vu &\Q[4c[v` -1tt& #D!yuo ¯y9 X ! AUm, 7|aqTچW6 !iP*nJU=F#{{)n$-d@U ˶ m;6G"#0aR \=ۅ?`=.) .UeNeshaB5qذ?l!sqUyP}HvO6[sNgGTM@Ǐ8 ~ rFڵ#EmF E X=M0zxTfAr/Lp;eTBu>PJli! nPQQd2ԉxfNotvvR-?ډ# 1cpшsFhI60{[DX҆&վh0>cnQ]IyOF3w~Bp1ō/{~ #IqՉ LD|&DP(D? /Y ~tp#eHY|wWM*ztOVfe>bPG%dȫwFIȱz"V.O#}`2(LCk8sH( L*;uƔmLASO1vOJ|_ (c<^JJkֱlẗ$[jH ],*$w BuB򪫮3fkْ1D# )DјIHJKːd*J"ˏp}u}fY<wq.!ǑH$@AԲN|q/sJml2d$6lq-.{,!auwا+xOgD"?hQpy3o7pUeUAO~ 3\h6>>(R!e6i0EԆ+6,0 x0sZ1i%6||'>v8x >"Zfڿl9 iv>X  iy 2CDUܮb~q]@9\p9 }~yXp؏pﲇ`=4'|s7g6lpp RXG;b\t q.,]=zۭvy ::; qƍ7gw(@: &PɎO04ڶ8г߾-U rx^DQTVVb0 AL1A~~D^FEk^7#a Z0 ;rQ]v+K7jnzik9/zP(D:DbVNnoL')U Ise՟ֵ.rf|k\ǎze gT:.<ӟ4T^gc>d@FH* Z*wc O4 i$N7lv4MPP)ӟ"kj#Np8,kWrY5'*&hZSN(PUX (1^]]=NӴƅ  ~Tae6SFrZcΜ9(.)Faa!]Ǎ'5w CĒ+t2iB Ai`[,Z.ya¸[P Cz0R g>9ηy.2.*Td ! ·WÄW]lrraӗZV9# HLؙ6QsP4A)LK˼dP8d p@:~\)$ -'gMX7  hHNT.*#sTd6PUt': #1p GOrǞ~2g mHƶ6t |VwP=3CENJ %:)t|5JL6x'gW1P9H#2'Ϥcze ;)IIj磠.kG͇`cP]x'OP^QdOMMMPvɰmk׮mL8%%aNCr Ǝ :+g_8wc/[Q>w :,d@g:ZmxxcbЙJUTC̊a@[^ߪ:;Rez,iF_\UEEww;,]_vso켔Hy-bg K'Uu?n: ¾3?!T-X%W=y8ڶ$VW <!DCF4` (#`@A{x+`%vςcm1[n^4/*ɭ'(Iy <(ӣ6eːv_V&$oK؄)B(#p,QȚy&V+041wO.ƫg4_;o_=޼n|~8و2+[i"W y4uA̟?1uJYww7V\iӦ ]7z{{~:)t]7Xtk>1!iJB L0]jKIv 8AUΞ} 4xCڶL"%{{:G1Bx9Uџkl`CB59{7nuQj\Thmqʱ\'g6ݑi g=bvmHՇd]]/ob'aW( Æ$D W3/nÈ 8q85L&qa$cۣsM\K.p|1<7m*XD;jWaB´t*@[FC*?Hpce*=ljEöhj_Q=LB $m#OAU؜'R` <3|#$.  $͑\n'OfLxU|o4*GqȤ%v!2mrg<.JD7PXPNׇ[be f6cϰe}.Ç ÜÏ*" ">λRm;::J0f̘a ޏ׊ᓮOA %,[2R;ђn010}#qrĤCqG\8<9ḽa@- :%LbתƽfWx"Eŏ%*${A6 3[yFYQ*iQMzisOsmA__|}3 88!%1-+tNF( EdӔ@t,9{=⑐= pX퀞\p/?n: `si==fVQg )ӔzWytMVW | @`^!{z͗ ('y~sKwCđW0l;kp?㗇 `K:d?:k :և-5[x6AU$t0RR"eq\xU RL qHAhѢ.r~{3gR/˗/ǴiPYYV|R[NJ)yQQѥfPJ H&عsA9Gyy9i,˂-C/#TZ>I]7YdЁ9_?k'{QMdw=}&vaH%!%\x i1j[[;BC a9;2;V߮>:ś!oQ* D2!=f$ O 9CT PPhd&[ mE ^1VFŋ FIy)w6ݏE3a  ?]F7Vt~ZtLF Y+{O _Ѿ5|mC|v `YB\kHB!b0ʃ>.P= Xܸ>s\PL^.ɲۯ˜sK.XN.iߓ;~PL/P8|U߂;BP8DU !dq/ Jݖ?]/* R_@' Y0$ahR+(f- s=%@o 8&%l@/Xƙ`9z%bf iO[bo4 $FwBvn|e3 vb H[-<9wtu@2. tO߁푠.#*(w4}ik m/Dx}0jrg֜H$?2v5UV)S[laرc;.]'bԩFH&qι(uY+$lۆaشiS_0!eAu\=si94"ߥ|3!=?hgo>kxv쳕J!²BisTSR_M1 0áV\VkCFR%"lnMx3[E^_ ~ mANdgQg`٪NTaYJ5{T)Dv%(9OBRlxЙaM;ɣaC ɥY B%)g c(L[¥dʼnȇxg"a2/u AN )E8H.OHL Il-(ynfPh0::hSlh$arY×v2 nj8e05/ߘD#('zvͅS *,tH +imQ|ٌ1XXwL%~aV7xT76mXޜvI~WVpttթР̝;zaV%dZ"g'$X]$; r&Be?3 5olz gqFQPB(0}QJA œf6o@ ٸb.@WOX 鲟㶩?Q%G`o%w͖w1`*fM ӝ -B`KK$rG~&fEc? kٜZꦿi|j[pKgd~TkjyWs jX6T\V2[3Ø ;"%T '~a (9>{Ga^G;LE`Q=TB @:@q̃(i[R$) H1BJdo +Q> $:9LS"4w$XVvi6=[$v؀,Ź"GYzw1 T7 @(d@o;ٵP2ƄYFR8( "InIA"9$ueïz?L"3Cgf5#?3&_%EEEE9s, +V,Gaa!&L^{ ۷o!~4GXݼyT*gJd& #ϷuC_p-)I~pj66`Zji*]n&I4582RyjoCM;^ pQnobJ!Q䒰3`$;!+װ2vҫRtw癭ʱls)AW8B'QЬGRv:6saCBQO4QLf/hL:sRЈt\9Ύ NW'I8&-6d~ȅ`[Ϊݐِp=K" #,dv-uȤ @$T\z@U :$n:SxW DU`3n& 1^]S,R*Ns P}VWU Cڰ %ЛJqq@ 6-6Npqc>D=+a0A(<ʰTw_7=|nMj|~J$@mB=<z9pnqC D47'[v (($6ض9.]x} ,L:m6nng$bVhhE̊xvk=,i<5Z#a'68(H3䅛>%A~jAԩG{c-7i r!";IJP?Y{-۴ff|Uۀ榇o6*rGd̡H+r3WxJfXؾ7~ .I$h_{CA&=$| l`\TST6xo=!ԀdӤmȞs&NAcIg:gVG'z/ܹsS% {;&moWՠnNsOY@pg=$Fe< pg .CG}:TMͧi!"ti2 B$l{OD"<t7ٯcO6l؀7aH)%MYsB6W'?4ݡђ9).nK.):l>0D$ҏQa/ˣ,` iCp-c~oe}C Tg|{`Bg-r)"+s)5'Q]>Im 2;@3 ʿiېJ 'xRu1\*G=qQbD'S/.X 7h\ ư+4!lO78*f K)Z: Qc0 !8vJҶXRBFst7_#Q IX;EͮVƓLdZ(Ra$p #1RJg@2uX2%  @Myltt îN*O@%d_Ƿ|9uwa;cP<+ HAlȺ]d}}=kjjSL!wM:%!`P00$SU j sTD Pb0ycIIO,!7we%NZߋS=Z1ض'rJj̊cw揻\rĬxa?S ^/%*E̊یB:l1'ȎPTX'wiîͅUTm(âI`}C1-לno߹}F\HmD@zKsg6W{Fi^_zB WeHӒNƿ < LլcEW^B)jntXyYm107` ?m(@$2"n"U.SÒ.O;ۖ~W:r)(qBhvGW9”0] 0y~ۀ~>lpӻD)C|#(9Jʩ;@ s#J:^E9~q*8>0feS>-,,ېL&i*BOOTRJI~~>|>Z[[QRRbe2-孷 `[UUضM遠1d 2C a'9#ۛ#O Ms SH!S6aۛjj[*#m;~2lA9izW_*>H*ʶ.@'K/B 3mij7&ǰidb8W@ K1óouI+6 6G(ИmSG2:QPB)ͥ؂K XfpQ"L$$BRB r/1$IP 05[f& %RLʤcaCRPB_cR:~\ zfP-H)Iuҷ?فӀ5B ԈB?!P]a^ sL4Cͣ^+OƒVKO- Í8B?Mކe_lxn߰29~qu0:s0fn<%sCJ_NJuK'~@"'Ȣ]?,oLɵ:Mv>;6 lij7 e_.D}Vjp,_]*l! !rb}O@E3c'{˟ 3 Hxh/ۤzb\vIA:$P\>Q_;>Y{((4*^Tٺ5Cusׁ_8h) A`nQNw'd}? nvyó>lű !PZOEjKylhn`&^H{{1Ap8lg[]w%<ܼ.ɌnjjRnjc+M0rH[nayu"ضL&tzO!DBj& |]3:4pn(]Q[lo1.qƿ "B"D[?~䤳)ᯖx6LI c;qq1#yBF3~ARʷ"c$jBkF+Q tG㈧n.-z7{TL. =@A~1؜#% 4鋩5dz20S&RDزwmۗK^H*OA2j ;o4Xm 9@uB,G/a&~BT'QNL47GRةq0"IVlh7Fb"! FMb|<;4H#mLQ\qf&Ŧd0a[W-Fr=Uw_9oB_A$LHu͐&8—hC0Ⱦ>2ؓ CvIu@NYNV$(3[4"φ0gӀcynHqBͥ8{\믿UUYSSӛ@[zA)E&AWW׊d2yɫڔKXp]MBf,R}jreYYikkmK. ֜O`{SWRvvp(jA|\>H@3RǍ-ؑon\p_9\ e0lewҲ%T(P)` tu;].08)@kPC0Nq5JփjQZl}q;JVUU(KRy2`bu9ƍòlݺu\IJISF:0\H(HhɜPY. usHiKڳ5_֥kx}^1]-s7/'bd#Lt6As^WRFFʎ5!ك$@Pڽ_5:?ȟd,|S[]@`\Jji+e4l͛:*UUn5 %jA@!lC/wƿu&L7|W_}u93ն3HyJRU꫼?8 R_|T4遖B H d @!"3lC}OU3W$s2YYc;W9[:\y2Fx}}ͮ|Vه>ʀ^2:ѥR1hK'OCU٪YHi `pWH﻽]` Pz=/w_"~2-bnu( шF RSWÍ"| t Po-t'fG]waJ%)i*VoӶQ]\Be;ռoRү %Pfm|S2>h>z͵*FO (G[f=5"@[*gE VXk:R C$pxߖ7H$A$pUBArɛ_$(ٵjO<Ź7}ʹFB,FX4fҴ[2`0ȆDBF" .TƏ/7nu4)QJL/~_a7#\XP7>Mۏ@&0 !asjNs /'U* (zrq|Б;!T wB _j?sCa)SŨRأTe$P܆Jf7.{&R\|=1"tdFlv߬k2#"绔RDj *5B͕\QF M=O8nOIn@LA2syo^v0Kd(DH8,޽_}WepLuMQ3m_QL"GUVV_QQQe_{/$)%TU͛wU ;.ƒ wR0(YdNtMDF"p9DnZ/-9훣}zf$Jdw7zNݷDf1rd^&n7 _<AJϋ𜆻͟~Я( m^V2's7"~ q}dM%;yqxJM$M H&[ihX, Y{b{`4XsX0ds: Y9_%N =)s,Kds74rv@Utr<85y@68 B$+$)\z55=lnco=kpouJ)#q׿}|'.ZY_Cg_hvpEEEnf²Hwpذ^ا/g_Oh*s+ffޢaSi̙+ut[;K,&nt~¨Qv˖H&UqE|#XE(*w~'p|j,)y7qa+Bs~f4"z?ߗ0;'^dR¾I @o}G+ lmCč=*-gQo"ͤ_w))AiٔRڀ*h:bc{6){ѾeGo  Uge%9̫[@!Wq|k5೯Z8VJJJ@~Ot}uc,i;G4,g|B@i8r 2Aj)'eR^&(ͳ(7(~,:N5Ɣ/{c[ *%sʄckS]J }DX1>q o];|0%-!(z&Jёs.K^ !;x[nbD r|%T/Lh=/-Y+kVݩ?}>x #=O/6pyTqAعiՃO/'w} ߲ 3)iXӷhAodMBw{r]m +*5ea,dtғƍFgg'8ɡAٶ Y|^Bo^]v퇱[nU\TxN+ 9+POڪ#mұm:B|tv}hV^7=ֺRӯqHdyDvR$qf{m}g=v@8(>2,!{i&[f{_S33.+Tv!z3S=HXK%Sp;*4_Cc }Slں30A 'rPfDzJH-R[w8h5- 0#noߒ!;mk7}ߢ'> -opsSu{ɹ+i= (PE{<:Gt=rµQd}w) owmW0$$*^g _vR{AބcazAEc_Y'_rD#ڈ#uD&uG6 ,J!mYk&UA(1)z.8Fa8\и--[<#=G)oK^Mc[{X6mKjI=ʥ+-1 JF>G-? ~… ND"n0>*HviWTTy7̙C2Jj ʹ kW\1jWgMrJٓKNP(Dkkk~T+y1y)}]`ܭ蟷;./O— gWܰj阻H٠jwmLׂ"|ϜFc:o|/G.g q#H)ɰa`įPC= TF=゗H]{o"r>s _n/*8V' ϛ2v3f˘FCyM]Ί|8_,{x^%ZO%tx),%$on p@#@AfC+ A.@7z0 pInSF âz<~@c@x׻GV.E)vyen3BҬj+s iI/UQ(0t%9fבbv[_$'R <`gVcr9JRCV{\yE׵ĭðTBͤD4Z6Np(VQ5K<<9>}_9rQWWGZ* ||[0i`sRnDaWF1yޘyd$WsSsC, Mr$O\pumkcRAl ۟+<^~ Z^oC[[[PO7u뭷B5J?.CuA!|&[>k.E;a*ܔ,?_:~GP'c3 n 3!D%Rq&v\iŎn*\i@bԎQ?0@(gv~أ<]$׃E##)],B\&ǎ;`;K@!c}x MT2 }ᤚ9j\;TeaۜJITJwm2^W;긚c 7̖6J*.ngnEy.cRJ)an^p/? ߰bY\G@!AURJ܅Ž({QVt` )%H_1)S''-@^ixuXh0$7C ;xl|pܲr0x=*`Qc"-ͧbGwPЫT)3@lwV&)ׄ:A#)0HRkہI*6vY)~{J\-ri8[RCq1">,^oaڲ!UrYIilJ#)1ՋjT% g.Tthˋs5~ֿyj3)nنIr)LL:Ei&qJ@P6)Nu cCj +*>=ln-FmakWn'?TײMؖ 0\ Ҷkِf [﹀m|THa:l ҟEQ2T/#D |@}}= XLÇJ`ďoᩇ`B2GnF /B8 gBhybG*\hnjô@Ұ*JBwJPZB@J9ǐM3߄f2 J jCEb&%d<_r_:E!uU$v~YgWY WQ+cMit*YB{::ʡFUq#o}dPDȎwfX]7|?͊;,_uv .yL#٢APGcҢ>)@PYxz.Dwڠᑳ RoS8yU%84F$.8̃g(^ uX+yKe\epƕ ?_0[j(ȼ*5d"׽rf f07%ж.6E*&xQT@&A7*'ວoB[ C H6,!heDάWL4QkyacHYٓdYɽ3J3Y?niqC.UCp@,.k.ep)!@jmy:Ȉ+J9*hIҭB36h' c@pL,T -T 9 Xww@LJb `ffUi Fۀ?~2 ^0dc#hz緝S+7Fz:ɑJzlz,#=  _zW,fppx<.,3=9 t^HDķ\]]f%b=jJ:TE&>PFjk9%Oiou8Xm *Sgzo<68f+ +}†e(E$QֵϷ=tҭY/̚:F|#[; %0FasIٚI.ꋿ,www#J Ѐ BAF`I{jq{]8O?gÅXB(![DRBOATTQ 76ۦ$.Brv~Pd9R0Fĭa;FY't-(p}@* )I8n*D!ǓW\vK0PuȰwfؘP/gȮd |%MW][T: , FD)|b;JcN ;"dad8/vW7m8}`jU}=tlH)(ʎ5`)-ߟ~Mr&tDé'몫UT(LShG+wBl[:vAH+pXdZBB%vҫt; ۂ PXhePJV/P5z#FtK.~(\*HX,Rl괥`*-c6v@)aCjpA>1t6iD>U *aV\ 9=I[B%uJ|dCH |dK6>?KA[r ,9Q"WM]rߜ {džTgk6c~| "as8ˑpOs!= : nS J#p> O %p`K!JPs&RX ض$:a G}1Ӆe0v=W"CQq+H 'Fz0D>714l/C7pPPb3ؽKG.\ TP³! DA!H_ @Tf5骧LЄyCG..slPj{@KoD{=wR> !#P'Uֲ}[lTEl̙ڬ+Yp488K%E@'\zN^ZhSg%Fyqy1!]mmm ((2CQ#˻+o/x뀋!K))!v64kLu#C^9&,gORQ?...I/ns]KU2k_ 'ׂ`Rq͗NS55yZ83`_0B5iY9kX{, ع OW-^|_L[llB)u҂ \+/!\`},qQ_~`ԩڴŋnW\aϡ+~x$H"Oeǜz?^~EF$Znt&1 hFXc@"vb&-வp:H"!DKf5Fd1-o$.!%\P-h4探 >iM= <* DaA۫G>x`.6CiV7Wm\Y22#mkܣT/A8:豙q22=%**POC - &hT "5/唍8Y&TWUWò>čԹ},q@w@<>aϽ<(t#$Hshp7^mn_̔bL b5\EqGr+n>Њ6!@v6bg''1{|7FgAA<* (U) *!QB(IThx@Ub:8;zdGD |<ٓ1dߗa,gnSO=/ )M zLUwv:G܅-hFtiӦY555 UU;4}t5;y[lU*-ʓ397߼>[pi}LR2A(:W)Wk 8=ڞK_X2T)|D2D.TUy*F7{\.ʺB\WЇO;uRXMR)a3 zN=/,h !h)@dp:Щ2QU Sܯ+ #uZ4=HOS"5!\Ni6\LTRsdtZ ئ#}^\!Ӥ~aK<Iͽ$.As vbIRa8َ}n Xԗky/"lǁmsRzv"Immt6 F"yZHnE]^@گ P}f= *P4m`K [Hܠ+ݭ /& &ҁ@4br?i׽alt #0f;ǟs&;Gp@N#ŲBn.D\eeHA89AҸE#!N^8# 9Y7~ZRBk L((B!"H"< \hz{%u#ǏGqY1SEfI܍R@#[q@Q~TUEْyЦ^ر`/z 84e6TD~xiSg5G/^͜9S{/:5=eKɖ!f[x-!x\ UU'?S3YMxŋٹ[\ss H%F ɡWK߰zk7PEUEA.Uʕ/waϿ>&]p%𭮫SUUgM)|Qzd6u6ux]H<ԡ>K"!`u@zR"<:cۘK"H ’ T`r6\7@Thay D6utt6 8K)$dsh?C6A-BTUwubz 2~~[ p`[5`+ɡSR$y(tn5Y2Tv`6hR k%Fw}BqP5 4-(ϷBAzH) csnǎjn}1}ã}j H $;WƼכ ҍNR&H{P s5\nmǩ$9 ߁DgL1 S󁤓nŀ禮 [~wlPF]FT/KDH(6EE&gh zW7Ͻ _~+V`=P{oT^xꚚ~3?7/677 RAh~A{ɷrno)dV< /`YFSm]NkJt}}[Xۓ2 TuU^WT]ӧG,^?RBUD$E9<]ds&{K육LRqqq? XBBCD<dQ('ha0=a'A5[p_o;fSC{=fR{)'$p}]1ex"IZ͏6,%@8I8؀%$Ƅ H_ ⮜ D|ݒ{" @}%D/Z^cp7,AGg'66aQw}JݵHP&MζDz}8} aRJ`nzh+IBS Opq( ң$7%{n$&T+鎎3pdž;VP#~[j ?K%dYC&M09)x Es!"҈M nqX&2p(4 FliIns"|I`%Z"}&BUyr#;BL% Rg,ҴYp\wGKT%ԔD\@x$t[qbH>rk³/=3,+Vc k֬ĉU9ʰa>vMMチp%;sjkk{YsJRZZ³{gΜ͟aW2{ӻer˔PTD/3h9ej ,UW+KϢΚ\#w-GU5 4Y1Ͽ|% hlSs5rUCstUEEqP Ai c|;ٹ? Lр%tb?#5BE*h0'<_if+LDC{g7>])BSڑeI_7lil7D`w ZQ;Y 9Iv@b7wSH`צEI!r>S8Zy99s0sCC^^#TVVgŏ뮻T㧟0yd@Ək[_>798sqRp^ti %˘t&$Bm%ԕDCH`z T P MlAcTfW0Lz$oʦ$隂rCnX8~wZ[ s;$֭ns3̜!+K?Ũi;Zv\с;\iH\s䂥z]N%MյI͉\ [qfa֮w[#Q/tWЊ{S)Fu_朹6-̰ݚbAjx1-+.jJ 9dZdpsB[=j *qڒ 0g%x7ᧁmZގ{489D5'SM!0, >Cm@iXTqBHHY@U8BHMӤ  pG/*d֕R$7o~.m]#wBe dߚ3_'J`>zǶ*^V YT Æ ÂuPUDZc9᫯ P+VCU0tPض Exk"4Si:Q3` „$6u"9$71MCqo4MWKiu&͚I cC IFv UCtB! $ 1 wJ)__KFÏPtX ,#4XWF%GO| BD $tOCE DJBeñX v-1Pwa۞Bg;p@BWJ)L*pH&8!\R0碯?(eѳKҀRR~KP(@UReLQ>f*Q:]_ѦFQhQD:O?#F6~x>vX0 |4irrrh2dϘ1#=WsyMM[ ðu]ʒp/{io$BIM ϻ@ 4hXMN;5WC Ù}ԕm~픅tOWKSOosRC UmmDx2_K^vaKdi< 0>JecqQ.[0giH!{ظf *KԀS# 2VxG aD4&EQ*JڒWi]Ș6CJTJ6]wdZ\i 1oa a} k Ҏv-_H;-pmbݺu8æY3B99x9QGL24ĞS JaPT%#V {p^8AcH=#kζNe6G@$!YS߲\P!Xߒ}R08M_0g[8 ( Kv 9gʞ/GB&7V\,RQ?*A(& ~-+BHoO~>V-% 0HxڠBv}D%d" OMVRo툟A \GMT˥SJ,//h۶x2$Ӌt`+@_ I^uRfBr5a Ys%c .6e9 Thooǂ/C~^>zb=ذ~=ʇ % 8i6onCaAaZtցP_ÿ3$$Xp(@^ ק 憧W8l{lN dUSF!r^0jTqՂ* / BCi/aUpZ3W῾QF,XfԦ)a9 Mߏb@!?e4%ԝ?,ZX#=˓|} ^XS!E)%j*՘okd{lIEeYD ye;:&k >PR_ ha}ON{VC }cS595Kw|%@H=#) J5i *D;{optos}W_8%Ck05ctd)MUqH&~1@' &p $Ҵ\7 "Fyn#F0w-;@,概`m㭷BWW~O$9Gnn۲lv p{@Oǰ əKR-zWϠnym.}& #ZHB"od\s<>CS,pƄBU()`SR՝B7:QL9r;߯6͆ަA԰'p_?Dӻs.pJq8蚦6?W ;SJ8 ̹Ų[dwIR=  )Um˯V{>6|kjjx$Q暥^!EQ`&x2}lødeF#rч{]8T_~_(Sꪇ7lpigggrΕ@ @ǎK֬YcBHAAQ+L5j]obhݡ^/VWW+ pꩧ^{mT^^ރLH4vx.lwXz{¯ߑ^U8N;-&$3a0"RRrQLRZ!C{X{+7/X8}:;f2CRJ9(--Eii)PRR3<ÆU;&KB~u@۠nS rsinNH 3(9yssE#+lp$sSI <sۆHg70[@r[Kds$B1 `'!~v\p8LBii)<`E?N:ii0`&Z[[!@wWb8svJSaKPi oK pSPM#4GPMo”ФI֓z.%tyot5Mo߂URmɆu9wz+#bNj-JOҭ&._.A͕ _H"˚=nI14EA9B,8Q(D 'Grse('rse 'g}Hh? [R_sa4cGD3YWLqkU^Xk7?!}MĚiw,v9s vwZ^{c {nڴ!GmlldQ v1Uo{ߟ2n4Qϓi)++ٸqC_pG_QSF"/x 8N(?3C!k> {~T{I?f|g";Ҿ=V\<2iw4 zڄ\vΑ?;roE)JßRiF2@̹+qe,eIB$TPIfʴ?9tU{YRƁt! m@-MkBPp* C8pG0ᐂa IlK(Mpf3i3fLwua8I I~,)7hAA-]H%S g.\) Ç<5zH&S#F+tM#GeҲ2QTT$DBT^'/j2dHG)DeYK]]"@[>ns,z)wjkkF `0H!㻵_G999ZII IR~$:wDK<g2CTQ-Β+LF(! /<j<.ORV_~2ww4<x`̙Zaap8|!䌶|M63dȐyRʺMu ]O믿>^JJ[[W^yjwlbW l D2dOtJsѻE_r]Dw/3KCtUbw3v⦦NO'ŋeM1RʕmmmMpxmۃ XPmۆa~%x΂7y H%= P(qa;UáKYNv>w/ 8gf3f1"D9J=ی(M#oD2ιېt@Lg7<3n>B4lY(wN?*R"<:ISlP`ajUt~Dgyf*Bl9~H?eG'=zi^/YnK/tΜaiJ9 iRH%F"] /MJ]v ~%Idߢx㍇|wKJJ|{w/K.)M$Þ{cRneeE6pH10}=I<;r0˜rvCF`k`֯za<=p{1fs1A-^giJ exrxZpZA/gC#AvHKj %7[HDr!֔HFif" 6.A. Q,%Dߙpx$Ld,_>G;}8g}t)lfusuOoqYKʣm XaOJ|rm=zꩡ^wg_M6?qDnnOrz!|rbŊǎɔ)S̥Ki1dzd8Z9RC/鑅*,s̟8ѹߠz2}b,h;w{0m}9mS2@w4Mѱ݃[ H)eAA7/y9cǎݟ{%IxkD^v_{ۤCjW9s97N2qbQf>s9;lߗ?/Ο??G`MU:SSci,gݛe9 }7DZ:zV=-B}2h~? 6 HIG,,!iѣORRsO9s撡CBJƦ&x9Gss3* (//CUUo=z(Rk}O_4%cB1KAuwyP(ZRTX[ !`RnvLo=@j+Cu,8K3[s4]U Q)$#< q6ث:jyOOyOǫHǒ/㓔;@5]fŅ{6d){;+hGZ5e5z`p8z--eFBpƏ(mdrc{{{K.y~W*V ֘B<;9oڦ~~= Bkm6lj!pJnw29=U;p&R뮿tleD3QW ͛?6*Z*Z ]So\u?kD"F3R͢/lhoo}̙] 3{ha ~ `5A)si5m H &.14( K* NW[O?ofeFwq744664g1bʼq3fxx?3<;::~nݺa,]hz<ї?uϤLNߤ wv-oO;lEΌG7WjI cSw< _s\CgxaBO% 4`ڤLx­F TJ8277*`0t]i"\T|4 IiF2pE<@ 6NgK;>T4DRo(rPt]w,˒]gPH6\>)Nwm;aEQI0%^JH-XbG@5Pm03Qb!G_,D`Ƕqx芥м`D(Q6R'LǙ5{ݺޝ4o$2qvW8p8RɗjUOWٙLz pzƍniiA6lxMyiTVV>7wٳ_ORJR[[mF30wP/̵\~m?:eo|z4rcntd6f0'/r}k|g5Z@N( CȻL?BZN΋0Է.GzO?pE@8C^=z֭{ M/_Z߁!It ҋɅ/ 9?Ђ>t)5ƒF!{yy96lؠVUU)#FeYټLڔ[tDCkk+x :`+`=9~Rwv]TpH9檁^0qjrPIBkG ~͓ 2qճ_<*xg3fl7~!8%%%B*9si;O6lذi!DR B>ӄ@ڻ << z*m EK8s`яb-؉xqhs)ڸ0E> s_nhx<#*** uI'8,Z(|WhGvY^҂'n f#X ⑇w&gxsacNwCw(6aK&Qɋ:$Z s֎TP;“>i5tY8#ɗAMU1f2-P^>8R\ mc s8dٙ 㸹d}q "s؆Wk oh#b 8WF[ -} Anc t?9R$;cm;;"7B![}-U5ZBLa} ,-z,_z z;d@E`HyFM>xRu5E}=VjoC [!zNc3v!'֬kj9Ք=CBmTP I 9C4oZw7Ən8>hʕ7ywe7nǁ@;㕛n}K.$s?m3]"vm}X.>qh ZKѫohUcS)/yyw\q}r͝&LJHիO|ͧtM;q}DՀx}Ҥ~"sڵ㫨ÙO?CԃBHJzʏ!B AFѷ^W8$Ф 7kn_}V]]=`MO: *9ep*ݒ9HH~衇)J˲\vT `Bn4%*"E{HKt 9R۾S[yEI)C2o,ZʏM6cAPByb$'K{^~4Uj4UCnnn`w&Mutuun'ڶF 9liJe3L&L&.uvv@UUz)~ rt>t_d-87gpYdB5p;^paKO!czRp^tiY"amxm[Qaq B,kkSN:?J[dA+@@ݡ9 ӱZ0BK wLoA/0&B:嚶r++;f˖h}=$ࣸDJ)*%nmPE'йO韞1⶚Y2[\\|Њ+n8묳RE)˖-SfϞ}=VTTi uh3_~y<9qUUK.ז/_~gA`رrѢE|U_w8nآNW)g3/y#[yTJIj.{ Ӻ;GD_ܗcy=gi6M-(5u@}=`,^.uۻQdԩiKUm(-_b ۯ:rok^䃵bAtjImD9% Ԅp$ƍ\50>zBpĉw0 $ =m4m]]]/23xyPb:P U]?Kiqm>$77=L0vpY( Wx6i8~zg~8{@c{g6ly~_xk僚3iSʤzϮhSrrrc4FSR ?p Yq* GbZΔ!z-ߎGL|Yu#BH4-9r( I cIJl@0NR*\nHG%g*z3TH%I~24O!ƞ\rp]4fITfX9aP: B%!r`5k֐H$BmƈX.#ٍJ^e"H!A@G('"]hQȔ(++jEEax0!@ii8܊dB* !9 w@Yrr  `qSp<ۈ7|nCH@rWǪ~ \ ;=6)%rrrhu' }/['J)(ՠڠ%QVվj c&0hETxwpWnzOW~xqNX?RaqhTUGav̀hI@H&WW`3oD"sU՟|l `E"qe4:묻|a>he]D"S6nܸ4M9/%Yb9s~svuux!W'NYjA_Bk"%ee 1uB O4y G!2kybeqLc w\}ǽF~-M8M{>ϿyX +{5u2c\sԢM;땭BLtiéS )oLΏ <z[v~jQJf (3Ndct2SO1PMtIrlE{Fs3d2] PRR>?42pz`QaY+PIc+L<ARWIMu+ɤyxU+AZ[=FqLSTXsG/;~Zc.a=j/o7zZOxT@cRq*7LTI4gs Be 8  S;tkNH4ض%8 P}$&s׋tfAu5gK|PGIDlM,EW4MZ:#IՁ9(!`\p6<*J!~4yժU7?2H$VUWWSPPXwqǁRJjxњ~7 ywV_{u}?0^1b~⡜d*zD!W/*PJG5m2l*ϾS'Arm|3nhB))/S~wqދ_ #@Q򠃾R5moEQX .jkUtQ`-% O3рsջҭ@pI06P>z z@xTt}n7*bWK[pNuu5Zy_, ads[7m4(J)a6HLD/k€ϧy Mͱv8|v,n4:msRܝJ1l6%f8Ӻ;ۖtޚA%q)âoϘ8W2]I#h4*f̘q .D4>`c}3,:1@Ś]!j)-1LCcǧ,x($O.ilق+VBT6![Ay}1Q C0TxU* *:Md_ԸGѨ8Kb,PR¶P&.` %+KKKcmʜ,)#̮Iׂi 4 i80I<} 9|4 _3P)BAu s'˟o?&s|%^H À2;6wrKpմm|Ɍ=!pڡ ^0(ǺϞ+P/,c >UEn:8a F2.8q%IiuJ=zd=\0mj1 UU*D(0U=v^qk:M p aHZRWU%[ w<:osϨ{!ݷM8̞=ۺ&S{{tW]|馛z 믿nJie*:4VEp}>'| .?5U)55HBC߼E=tqX cC X֣\1&,{nn՛+axi)Q~w~ml3iH4*"/XYU󫽊6R*J|ډj1Dz|E^梁I! LT9[Hy>P$ (xO?6Y\Vn9PrͦLqtҲCrftM4оm4l|]K2D)@i4E&5CIi6mj )z=qNZlEOb'fFiY)T2 y ]+Uj- la Pd:Wd_lJ w .ZT;m4iEQ~jkkkuMRntϽh RJ̚C_m GbI\bm'v+%}kKG㸝:::W_f`B9kf߭CC$'o4p~AwFA*y^n#heB  0 P8cA^0* !TU\pg۶~01xt8gh* H)]]]PTWt::P{{X׃Zz{{a:6r^ Am`u&1ὖOҳ4-H)c{{{QXXӲL8 eam+1/4BT`ZHBA eLRgqAzʕfWw0!-&Mn&Liwm߇kCQ2YwCw5&|sGFy<&,3l./kC:(ynA &~_PL%ѹD B)UUof64l|@f4y,//aÆo#ˉ'?c|'MDjjjm(D161֦iZx<j8x_u]_cK^ޕ<κ>oNqyEq㰪'e!i,·aZb7bm:j0OLzw^ͳ% u33)Yp)3~8LlUQPM p~uM4zmp`!x;_-^ p+1}ydЫYL2 PwcB>B^ ͛/p]2mm2rHBm4T*up}OmD4J`a Alninzf@0xX[MU;}Uq`PihlCՃ}7-z*UU1AB`<\gιz ABEn:jjj[8=d|R嵵ih"#ϑL!:(˷ LuhB $ HXLB(.be"YP4 Vi8mYiTqc7fӚ~\r[ ?9\B0 $^Bb]' &B:A)%NX !03F("A~\'tRi91h a0vBU P*PU ?,[p8Rx<:z^MӐ{R{{^b EEE.x%!C{{1 iT+Ca;i?|NNt]Gqq1***8I.SBcpPY8$څP7PӋbO%$\Ky=G!vTx@ irHnBz!B{\p!rss1aD( wq(,t{o !!QIL fc+1ɥxoϟWlm(A*5m!@ʀꍎ9N, fvhy}# 755[<{Y3gV Pf_qq+Bn7tS-|ݺupL,0( "˗/wY_>4aܸF e75cn^mCp&6ŔV;;~s]r uTimpnۂϝ]{5vּ_b&=3sqB%(Onn'o%ڒJ]7dBx7dY\D'-v䢔([m+sssϜ7oޝf͊ߗ32ىd2t43OSR qѤ]p?CwWs<0LM1¶dGC[zqF?>N)z[Aآ,P]C0t *ct, [41&pJ)᜻l~\P9,8LQ@>=#ǡ*i;2ym:؎5/rS+L/5ЌI93.yR $My0,6WpX';HrMBTHכ1+K,@_Mi6\{B `6HL{K#g)DB)Ӵ eEº鈘agKɽ(-7O&g u qWдB|8#R>RDmqflhh8 DTg)4ٹ=?zڵg_{Y2d⦦7KJJJmnno$9> p8*,CO,}[|;>`,r!+bz3NzAAv[pN XH*LytC )Ɨo/SQק Ip!aS] ]Uv|w8O i4(1r$N88+녪0-ee8Bح&8+jPc P\RΘ{GҾXuIAR@bkB8. L`0(c&477oW_}˗oT;]v-b==ـEQ!(ٶX ]]]pX BO 0-؝О}*Ju[oOmnjH&D28 twwMXպF,CMA;bPt}d@s4,|ڏ!il9ކm;P)Iaҵٹk,bAaipa)pq 7Ejʕ=Mжq^^8}Zx1KrqKOWxe3LR6 !%lqFƎ%ۈX Nybȹ?S0E6nlpsFn8)(Ja7ԜаpsF+qwf6l|?B3{W\ZTTHWWײT*uܹsIA)={]w y?R޻z궽[?~a_<˲EQ~,_ufgaqA?1eR}mS_' 6~:z( aKg7|%$?裿;ٵw!Z{ig9pMҵ%kc/x52'wȵ7贵'~Ug§RfRh4j$Me/F}L),]׻>oD}ɀrDZEn~ŖظnDܸB66LBjnOmj͖*?ӆLm[W@GR2/@ H %8v$Ipy 2JG#7yPyCCHP :B2Jnp.z/#` paƒe+Wf ~W8ߟ # ]x!=iFOWSh/>E I#U5̱A nD*oKr|;NM\R20qa`#Ja޼qoaCJRBuWtp!:`AHwߌ UDXZ#7MC+PRTSQ4'w*=S>X")!3p^WH^B4^ѱ6  2 \_]ׯ3)!7X1sTl3tE*<䓡wKJJ2F;4; 766{󪫮𑞞6o_~yȐ!D"i !Κ3gɊ_}շ !NQ/KW^Q2l4x<~Q XߝL&x<+<ϝaSJFNΘ/U@=8'Ț::ա8b nPeCpGlU]aPׇx_,_D{EҰw+q!SyIC?t?[Κ6մv-ZT͚wk>bd2O9 4 zĘ!shE?pppNNNvّmңRv$fUwe,dl02wDQnp uW7'ͧ\B,mߒx7=U;=gz4ϨO;d.%{ 811)=I?!ub3TQ)bXLmL4$ap|~;|>3]]]B e;@@ 'P ˶0P7*qg8য়~oM/U p9 %I&$>?)kׯСCaY6/_LkJRcǎv|צ@]LFKjlllxD~!J6 s.bY |-0|3 }R" b[ 0[1"BzCpm3nJXxy`НD EUcPUQ][ UAa7cPUT9犪ޚ%2# z*ﳏ L>g)wp@jׯ_τ U 6k$Abp\+ -h:0mjB F8QD4FbH1ҝI!hTk())W\uo=o޼4?>9?"̙(Ϟ=$JիW]GG,òWpIHȫͣUU&,x]]k%!B'x"0Çꫯ>y)|4!Dkvq6%1C=O\1@uf&H)eZK i81|,_JX---xb Ȗ͛6~VZ0#;*%C64JeSYqN2ymz}u+;&@}x $$e<ͣeW8ƜlNgwW7N>d\z%+䦓8 iR=QFa}AǕpl|j$Ǝ9=]e񁃰2/D{{"@uPTlNWrM*UjMi!jҥNiii5!2o @@UT(*"? [ ?BHWTP#ݯZ57s݇ jtm} XL~?@Jzc c>LDQG M>K3O[Up*DIb8,h4<Wq"&a9އ9w.qB+p7i߭vnwn1~y ѣ1z\xA qzQW],=Q2CBni=i\ѱ&~sZ@ăQG/ҌS֬Y:뮹s*..~9?Csss|3jv☱cAys@i\5t1f?̙s/644X^^{J.4+??m۵Rʧ읹fg-7ÂqMź{*c p-g@rU\!@ׇ>~5?ʥ R}&"G9x_o.Ϛn !D|'TTT ð|>gŊvL2VUU|iWWW9mRL! ۶ q 瘬m64M&^1 e76}q4 ===;T!^sV5UH|msgY΁!0H8&)erH2\f78ݍ/s|`Ϝ o˲0~L0t$G55SLbG̴ PTBGM_ڞ`y{  w{^Ekk s)((x';kv BB;%i<Ǚ}BӶ9b[ܗ&pg4 L2!<*~sTJw#n@XJB{w҈#[y֮]G9ƍ;b;vڬY.:#۟5|13ƐL&:(뺎D"}g:*E" > V /_x?G!䭗-=%9g?ܚ7`;xWCM=1alFրժP&xG$$û٘mr!Հt+q']щA //@qq19b1.e)p0AL851 g||FZsM4nOňbk_#_9 77.lقdb=hG8FggBtuvoԐ3glڴWlLyL^!Dnuu&5-5y({EuHԃ{   x^( ݣ 7'ext0ƲBg91@ 8RX 5-MC.DP=$s BH.!0Uҁ9XHZ $$ 2,!. vl{s+aYR| }"9mkkt!ܼ<7"ŽJTja+[Z7W(_sլ6TGgpjYq.]G-ӳ+h}'/)((zY}wg eB~Rb޼yjjj 771){zo9H4![J~ 7\{W[u>!d_nmmPygLX ±HvܗCI`JxT%"RBS_C&F%^Bg/#镝N{.PRRr01φ J&KE]KƎ[MӜyWkkk NkK! 80AXmp0LRcsss>B$ (f?pc h4e}~؇eI%2SFꕛ~Luuvw=8l|2_AS8PwD{[ 8 d%l@0JUk׮~<b^7@%T W8>?*+)%D(& Bi ]]XzՠNc643Yy8CQ1t(1dHlF8\7ò2 LԳJ;C}8͗ӧxˇفUߣjC_<3΀ 2yTE/b^/|>_ַHzB}2)?kB @@K.9$a#iń\s&h I( ÉT܊-ҵ~%4EMJJ jV t㧍Fa=m@ 4 yH|&' /[>][]z$>H#^Bj۫Ϙ1h@`wR'xbd2---H$gAAbvKs/;xdÝ͛,P+ m[ƈ<7Wib`B|ɹzСou]4 )e})г:뒗_~kئx<~g}W̍3F,:RsF/g[WWW%w?tWYM5w00@ٹ/y>Rلecre)TJk*tM;M9Y׀}FUkT'3EK"wV #o1*J)6o}|UUUK<(is1Ʌ #FUTT>x@qn=ڵk`D). s.h11}KQRJhѢ@oLvѢ_aOW>R2zm}!:y=eaɻpKƌrzkX<;$<~n_dޖT_Myxɨ:wxp O|U҂͛ڊ>;4 arX%;,PfwP 4xa,b~ҔE0ؖ˲ҭ\O?cIAQ V ˲QVV XOlԮ2zORÆ qyW{Lb5Kv| c=ӕSO=ݿ뮻_#G|:H+X[98yhxogw<Θw}dѥ0,%=8hdk Wq!%9deOy$:@" ٸqybUUժpg?s- .<^QGxp޼yb.  !B"D#oeHAcRӴ8_[ k̘1ͮRV~a%4pk)s)0TeQ2u؀ A) Ulǁa?<„|gOрw3s@_}R`ժU0uY TVۘRF]1(--g}ݥ8ۜe qW;LJuRJ3fCGQ뜙wS Ҕ(+] yЇEtذ"OP.6D XhKfsn]r̜s^n [[{8MH 2DA֭lbuׁxKUEAuu];wr}10䦣%IB0L3aubíס᰻  $ӕJ%GD%!dDV-9~ Y0̀$pr'7(IOgspi[.oDױ0SwAR s*T>N!pYe.$8aDsUMKRz Jg^O-@B@8c<ܣ;Аm۶着^ꪫn {7˔Է}]ңG DonHjg,`I(MT˒$r;I:th^ fͺt>޾pnIiiZQQ!boLnsNf̘1],WQJ9)sEMӮyw@T箺?|`Wˢlo Jnvnb1H v6W 3ȊvxAPIAs"RGӋp-:ʋ$IZ1`cc>5!k 6t0Ƭ|_9' ;(Mw]]^lXiN.t/? @8*8\W}JFqn4юǡoXOguzj3dʙ$qƏDho ,`H88;8ҧyj7Kʐc(}ru@2ha26l FsB 9% i fÇGnn.0I!XTp8.2c \..z  HP{(ש+Gi\ߛ6m vء}'( oz߂{f~ހ`NfviUQF4$hbAA~F{? ![y^K\{͊hGJu11>f̘XscRRQfɮ> vEd4_j T%ɀHQG"ZENWk0$llRt\`$d$??I\z .d2BL&~>҄ ;|19֮_nmfFT~L 1p1 9 ^I&~Gb+5 MΞ$@ ښ:t 'H-SN9]v{#a*dY+TVVict=OBѴƴNyBH2N߅]e.!]ffAԘD#u_Tx'49-ӘLv!e!sq*8(t *1h xghU$&lTu?$~!=~ Ph%\ߔqH/h1)˷$I !NҋwٳO|d2M1SnP({&PVVNy!? !eee2x^_|H_|豳6mCI=8/:"tD59v!?'./Ҋ P_v7oNzBs.B>駟ӧKN $Pߏ@ !aJf=pNEQ46nܸ^o 4F@j˲ rR\7:jB1Z$Hv 9M\_^o?~#qQ\ L,`@"o:Ty^@T>$-ATtA18IrxIIQ,㡤KlKDxo\SByfΜ9fF3"T֮,˝^g6[omG[ZZ#810F8IK?/'%^{oӵѣ3EQs{ M[!iڒ~Խɓ'gM [ )Fa0]Sqn c钛h4`Бmmmk&Io0MijhX}ꩧUeRB{ :B PƀD 8`p.h+Ձ8 n/6( Sqŀ VvKW"J{jDP O{~, @ Lc8Ł;@ $]$N8hZOȪU$@ rBKWvܹ)#1VҥKA."| R_83֡W#|S.V1E7~c͛mPhȑ#?KYI]jՙ}6>mڴ3z}oUURPJT`/Z#쓹?}t},XUUHqiF#AgmWkfC& )^ۄ=GR/p v&&kl4;:?zk,[ 6 wiưΓ>裙NiE!$09J AGG<&>sӺ* 0Z EKMWu#{=ٳgX,ݻwoӒ-%CÛ݇\0`0H$_M~?@@lڐɽel.0G#~UUw]|-;A+P@WjITԑn9HEq0IgC !Cf^o?0bIo-Zs̘1c? |" ЋRjMeuuu;ҝ{ᇭ"ןEL":9̵_0rct}/i4CPUؾssNϟ_n/Y^+Жz„  'Mr]Ӌ [,$IpI!Dy7Λ:u{G Gw6EsOxv$ 8j _sIֳ`>~HH7L\B  hs$Q0{<;fRjPUuyKK˫s].m޼yB8إ=N^~"1Pnu~q)k>cVyFBpEQ⚦)IRv~ }/z/O>>*M>]?z\.EFz֬Yw#?g)z~(:Nw1|!D{衇usAcZņHd0<`9hY^(2OvszYu)͍N$#W%!_gdݳ3 | Hz1V*7_NSj^v A8As>}nѢEI祥8+%I]pY>ǿm}zcn1ˍFhMD 3Ls@Gcz&\'o}(ҽj,BǴ`CO= Mg=ؼ]rtN[hIYYYt hٴW^yƻg͚E$Ûouuu_F"O~᛺w YD"---H"pqxrš7vڨ5m5z' h-RZ|eg//=ފ+8PSz;솳Llx r@҃UԵ~ Gԗa#Իc].wUB{eXlJqqq`/N81p?@Q477[ZZΛ2e]=7G#i;l6Olll|`0nt& 6[El6۬[sbg0xZ,c(%WIUβQUUP}uG8rŮ{`roߛZKwt(IO?}vn2644 4xPWW~ .{Mv 3gΌegg_q>7tH?yENBX}}EEEߧ(P} Y`0ҚpΉ y<}g&83y322.tժUW.袧󋚚V̝;,[޲ll)﫫L;򲲲Vth4*oܸ[ou^z6y?x@:`0R;v n[+I>~`)ېvOF&"0TcjNNN_M>|ǾKD"SU[f'JSn:ތ>A=x<b1yӦMr-Dl(cL@pBzueeekq/\A{/ beP?{*C7X*d`nd0xwhtbtY{*ۊ&O@R˸JE>|7u"r89ޙn0(I`%~Ϻu4z=DbJvt~,WGC?PBL͜&pws RLQHPsϬ oG6L:P[!Y} [b#+Q:P#" @L#m?2nCQw7կ>hk4N6 ൢ>u}e{XQ 77PSS쮻瞛G̙3;9^)S\px֭[=z{$yoqq8F ߹s^lX^v\Y/hEQ&TU%:n`8vG5w|>_@8ݭHC"Kp@E"&I[ #!'*r$wQvCnc?>Աrc QwonnǸm۶mS7;::Jw>Q!$?~On ޕyUIIr:FQݩvgm6۳ګx<7m4???v?G_,`رb4E"֩S>Myc=vennn jqqE?Olym6 D|ՍKѰnEظn_$ˮ'ԋ_ |B ;-3ɰh2A4jsf!L'/фp%mtJ1:NFϭ\2 sssTUݚ>~Ŋz)zҙӧOs:+].׀x<5779szm~ JD,>2~ eb0V+,$ oiI(tJlÝ*e(^~4!}0%%%gfffxUUUκ; ~d`0 `5! oZ{~13f$ ߟoۻ{Β%K^6m7|sb9+4~*"ħN* !p8lkk[9'B$b{nˋ/&8B!g{9ru/Nm MKhivnEOoF|D4AI괁 cMr58ajAZy͜++r?D` rM/z̝Bҝ9*]4`0\$cvZ9Fg$ʚ#ܹ2 t̙6Q6GYX]]}돺7)ga|)tjʃ& YVј6;|?QP~(I:uLM_utt,ضm۹}5UeRMӈ(h<L'fg<DE:~=pF3x~yXy3 *wwy6ܓGN[ 62yդ>C Ї'?3?1#r| PE!Q9`+%\=~9[[ӚNgI<'􏰎ӵ&L:l<}{UJ#Gv窘ˊf6< DB $c5B(z=u:fq&fE1i1Ş+++}>_a @6?\RQ$f͚ny睟WWWw_iizy*ဒvϝ;XjEVVldbHn`0ta8F477k&8) 1Q9sl(&tx;w^WWwwܱ\,..f»ᄏ! EM& @&ܜ~:wܟSUU;77[ZZ6m~j RN)mh倫![,N?}8ISDQ!s'Jyy9ᜓ_~Rz4١eQ_<Ӵf@uF "\#UrHpL~2&d)!+"PKv:h"F$ 3$CQgÆ _w~՜9sQJ;,ɲ,h4z<tp8xjׅ2-Z]vb1E `4 pȐIV|(H}kn. S5Gb}>+~_ l̙C YN%jpXwݵ4sceEfUU)BdFrs_6mZ[ Xd-iz|w\C&f<׮_~?UUu1t:]=So2rl6g{{A3pGBYٍNΝ?`sɎ">[wFZ}5Y_-Eϧ]tE!~Lڹc| iomevSwwK-gΧ\@5FHsHָ [6oz㎛~ҮNDwrV!\J 0 D3aŸ=C ~X Wj8pF }}8wTq *3bԨ%.h-U@Wސr FIsDM3n@ hR4TR-m[Pm7_sEEE- m?|=Āa0:܌WUU(2zh4^{#_ymSL3;X,1OH%$ǧEvlTj>͛SM/N~U'Bhq5Yq_YO;{'f[yG<eumѷξy*`m |:3)!?_cs>}v։#?A].͝_bte漢7YG{ə'90.ܺ鱱;眦yr¶ֵ/kaԒE8Qw7mϪ SASFTn+;vg~FBCO;LMxz3 Pԡqa8%$"iT{>@g8:u@ Λ7hSUkF2223ƧZ%I2Dъzj6f̘֕ ˲ @ P(DF#jjjluuu+NzAaag_iڎ&LaA]].kdbn2oa׮]\ŝ*ޣG2x`&"~+#]uH,v7DXs6X=kă `aGv,(&Qw+ߺ~^`՜vڵ W\qţO?tinNt< Xu*i:Y^?Z4z߬Y6~XTT.kduuuߒVd t:gbyW_V~I)i/OJ)IqeH0!`77BZ^5.Xg_ȍj$yha!TΧ#p7'DY=͇D g %(fY;".(IizY}'@Q fb4pUAX5ӟXmmmkѣ꼼 (eynܳgksnvD",˔Tg0rf͢m_pf;J&@ /MF1io :h6}>>3Քz@hcRp8,ԭ]Ѣ:I8  Vm^Z5:Fy2cLtvBH*a0*<Oh4Ej0;Ǫ{fx+1 r22%0M(T3qYVsVFr j٨Qjpܐ:kw~5m;Vܫ.7a)yMK='`+~\MN1sm5&p9!gpxB޵3N:aιd]g$7v`+'&08D%>&#=!S"Hh Z5~ݰoٲEsM*- @}Wӭ[`0p³g̘A,a>sL,5M* <33֭۹ $ }iڇ1.|Ν;9#F Hz(J3gV/XfT·5xpY~=z/*{}H) &tF[I`YKg7H;OxJ=WRι!Ji^II%ׯ$QTT̛7odԴF"[^{챛lmmMD"ݻ4BU^^.@GGG,˄R:hԩ 'pҔ)S槼'q I+_яZ0QmhtBo]̓!\h(Pcm7n{CK8Pe"={dB 0j6I0a PJ&85_~ w,h?V/BxDltTcYɢ *j\1JDʬ¥SNrn;lA\ 333b)W> 2EQ`4i4U[7:mQfTF\bQpza9sf(D(wffxpH>WVVs'{rN0mؽ{Vuv=1 'f *VPͨ<msFbq:C4MSeh{NVU5.2 K$hnn~V7m}K/"0&Iti zIe&"ASE0h8ninn}w{LoiPi\Ez{Iaѓ zjPrLڅ srr7r[ EH'{W9*jӛ[x~dºu 瞯~ n̺sヘRǦN*ƻZ[[kjjE2Q\E+,,MuSO=enn9#G,w8'K推z; S&ulQn:(d/3t0.Cvܽ daɻ|_ 'N2(;6a S46P4DEQ֦BAT @`Jqh҅\X 0tIдiӺy,n9v/Fql&L Y, x|=k;.S).h훞|꩛.3|Z>pPO L6G@@:uI$hx\hmi)ZWsk0f3N23? 4-#ݗ4֩,XF&6r;"n4P5wT_~ӭDpWo޼J @W\1Rf0VSwqs3'g3C2e4Ǚ^hKq^MӴ?cGBr'|X~Mn،&"BҪ FsT5z>jӿrs,N` !BfCc]=/ߝuջ3MǚtTj֑NB>HEw"XO#=!1)lLh-*lU y^Mk:i$]aaa/^\9$555{B4=##][[p΃>sr&A޵_+:d2uPA8;w&9jNN)3x"sʘRJ",&b`Lv2qS#.& RI!3-t鲝,׳g?:$ B(Q,fPEd3Z^ 1RuyVpQfHqFQ/(y, "AC]|į`A~RSS#ƫ333X,֤Iںu6=z\?3AwSUUՊ+S dٲe;/3T @5οz[ee.9iؙVxv@(\s,KUÛ 'M2^~y#f G#lXW;1~O>e gT1iq<TA9 6|v[8BW]uX,v{<oioo_YY=]'N8@(9'F;dT``j%W;w~d'G2F#q˿ث+D 3ܶ7Zjpo'='Gȏ^ocd+R?q׳3<}Ǎ>}o4L\|GC ]խMuW_tY_t JxGU Pѕn@lF8QhWrٞݱ Q4ǥ^+SN|K$@ ."kzpNtIJȯPA#A8琌$TmuWJD  /!' _:Ӌ|j%h> &Mtl~f{5M#mmm\$vDQO5%n@nn.Qd_X,Jv&5ub*+#b1( l6$IDι` !lVg!nv7dwcJH2AS_ ol X?uhr+}o)*Zؾz(Nv,+y/,q}wxss٧7SO<Ā왒$42nܸh}6M$`Ȁ^ $9kkk.}kMUUBTt̘1>Swl(4yI5K,o߾ڵk__5kVaLb4.R1pAu8"Pqu&phj,$% $8y %|n4V-Sr{bI K@˵ ~iJ|%~8E}&:L3s! zUm,Uo9n$Pc !;DE ¦@@2ez>,#[ZZ.2Lk kkk!`4/*vz&PYYVTTBz²e˶]s5cdY˖-9'cǎߩF `E |(F#R&;wʯ8:mVs8ch477_O 6{B耬j[0 h /(^.j;OhW\qiR믿^h'Ow7˥3t\Qh4F6!m^&г jB FdfՌ[u=_TE=T i]նk}ɯN_~ьsWNfuΫ!v@YF \ZZ]p/_+6O?AƝ8_+-;-m}=eSu~ ifPu]nb,ij\z'zq"fƑcFߘ -zHt'H\р8w#?1,"1’Av朼(s6- JWD:xL`ϩxpXUl ;9^W0X,43-gJؼynz+ʲ,C=tnp "XW$׆&O|qvvKRwSS, RiYv|dMrc+9߷KX\\̋:ҕjK 99"b"g TH}ԩRII:g/O3Q%iWt?x)'朓yEWl]G[M+Ӯx ;}>[o 'M [{15{^﹃o4ŋz+''ǡ( bFcj=]$lٲGEQ4BJioUUcDE>hڅ|е4|0x`wqzs.VWr$ZjIa-⿐p`!8O% H\ړ (3u.u6%ֶ6%m%f!"!H`-F$BfJ"2+ $PEwg?-f]]؏NeUz泑?HbSNruMxIE޽{h6L?-X%K4KZf$rߨ[]a?bw5xr[[oL~~QEsϥi8>hJ:0:Qơ:+wY?n;@gvfsMǙ!"3gyN}$DIDׯ֌j<#[w7/kz|R rN@h{+~_T$=;ũ3L$[Г_-YJ*5*z{ Nex dzXm/~\ݻZ0Ç6X|۳_Eaaa7ߜk6;z>H`/n]APQ t+~tqa7AÚL*OMx5yi* r k(@r .^ (גpqq1xBs8(.F^_iu5;'ԍhq"$rPIdzֵ&v7$Vwՙz_:- x-/;;qJH$J)O-;ˊ$'.|2s̷-4٬xXVޫW\s8(1 ֭[hDNN Cz%kSN=DӦMH%BЀX,C4D"|ʍ?bQotPp6%.%K0ѧLsHכsHz=­mW=_T{7P< %!w.{=1gB~y{o>UK<` Ͻ_K{{QEEEO?}vNNλƝ;wVc(jSS^QgϞ:aJ" sӧ#RcO9笸g?xWV:ZBiNa"ߙTBtc5M{ryii@#P.'[ Yf8%&`?,x<S~_/}8i<%/H'9sDZ8xV'ӡ?T_[Gwc2RaB, ? X~$ rW_$Ihnns==uT3`NN/#GM4jf\{DN1 R$4w$g.:]* zfkX$xO1c}Y͂$YKl8c{Ndzc#H\UC}Kύ 5Smt:%)n6 XH|>h?TrTz3{rrr5:EQTIYy[(t%m1د]6b14w\Ad*)[/-\>_ft8x/SpI$u;\{Dso,9̜ԷDk,6dؐ+j / |vZn@"ֱ+VKO' , G,ӿ6===c"<A滚8 Eoy Wyo'‹*t,ˣ999͛7cǎLESUErGcƍ! ޭis۷ooys{õ !%13'DP@ԊӒu(5MFñs[Ú*E(FѬq@ڗ Uι94U1.G&qk}m%]r%%%gdd|aھ{3m%%%455 }_[[o=a

h8 ASJ:~ $(R UW]5v@nlls=%KYPA>?"I[o귶ؙMfUX,&Ǧׯ~mI9('x]7~qA[0UFdQ?f2켲2ۧ߆~-u3PDvaɡ|y9O?w .Hh( x^v9?gCkY-fR8M:8>HCbۼ>8Ogfݭ($vDq+=WK9|N=Xk'; u:j3[Ynڵk޼`KƎrݚ?FdF*qԴU+g|'XxH{zVB+Bt%ۭ!soozYM|=-өtƌyS.Lsp m =L~?=?_|ξCb7%* ` ݦ<.Z۾+z^d2=vmx^S+fMcK]Ɩ?TE6D"Ѹd81}:|zsv;z]"В18졇zWl?-UDN80~_,{~el7T5F]0rS_WV9a#+%SGJA\?eIw3SdݺO_r+KKKr㧮_큈Nms~^ 2=`РAeL}eІu(wv3?!C|J8e WM{J yy>&_>L% )~^ 1l BN#3ud_FB*3Jvy<[V֥^;*tnx</Ooz'fDlo|H)l0y"zG3#$SXaӵ;>S߹~smF,H&dXTD o54XϾ%:ݻ64dyǬ_~>c잿ƈ[1A5呗/bqjCw e^Фcl艕qnĸn'8{,Cmu=1cJןg<=>\/]6ٗW/\PG)Nu^SA0YվvN0ǁ Tv+R㊍ϟKzk=N@d!IV&JѳBffS Ob_3PJsEQe+VR3gN3\ι& )SXAA0a„5MV[nݚ_zމsssYNN%:5k?&|!DVXݻaݬ 9994??_``k֬avݺuuuuZSSޖH$94_diGeX x+֖8͑)(e ΅ƚ{/ j#͑Z)(I%I"xkd9^2XֻU0pO9'a/Z-,V;(4 LLiiؘ%%%ԩS5R*##㌌ Ϯ]B)wrCJ*AK?sW$Q ÿ/^[ކꕖ޽{4`/p ]H~AJ=4g068hIˋ߇.XzύZ({w~;#9vm@MmgxꜺxqiۆf*W4A'1Ew{)7 _|ugNO$){7m/Ҥ|4 _rҨNqE%I6hBiE >=uG 4biiI-f.Ml G#?Qn=;fu;vm a߾8a29ɘ.n6 v|s9'##шX,t:H$xSSe=ic7p;*dd9_XR.v?>?dK4vnlhol l[W? Qg]a}C/hmq+U%?|op뭷 b[Z۱{K,W5ڽ}e,B ꫯ;S^q\% \p Uq\;^^29g^6|~ ʼkW/~{*:UZR=|Y'itKb O̘O3}ac{8< EqԿX^}T}KPU=|_8[{{{ٝwy9999ofdd\ vgҥ #ry'孷zv~~v]i"`yyy$;;l\riW^yiFsjp8JssH$|CEff&k֬zG R0L +^׀#~,,)Um %$MY __1h{wߝvE'j`-'ult;_H8APyokuɩ`0Y J\`=zEe˖qg؏43335k?8dR^ e_Nb6GbbHߧh4tݻF+ycwp;*dEr]Xm=t0]߾ cfqwÎo?kPa^WzB?$pqm3;߾-n2ѱv_,8ΙDa}szK eeeڄs/X,+J_|:.sl6HKao>j$$*gPԁd !ϯO9.7b>uYfN:g|%K 3`,*Q!JQX BD'˱x<5j^OafkS'?_}@.wS'k/@f/6|˦RE)^ 7=Lj`jgPTπ/W^y͖ {< D&7M[ ;qݴt%1Bh8;esx-nmn3zPAh O ,D<(,7P_}kڎr/ζv IbS0tiuuqNsn/ihh|Hf3đ#2n-tD%*~/{in_.rǷqHm]弗~۝GiE>U[%SGJ9v[(WkǛc/uԩ%KK.^ziL*VUWM*/__#O_a0GΕ诺Hۊ#/5g YԤ2f&z:sI L#Dt&[xNU|{uSWYIxxt~ec!+d5T5/3ǭcusrwXl6>EQ4Q擟z?ݥG A~~NQl޼y?8.l)rs6lذwVr`Znڊ#F4رp8Żᄏ}9yǟe?N dn}*LUD"`Aҩ6Jע ,`0x?IJY^+?s@iBAN#70% l ugOvYYY))iijj:$إ="7pNh7mڴ/ɹa˖-}矕4MfC( Ս/**)OB SʛHfJ!ЊݍTy^e8Gst$мz ]Kʧ S^N/Bȃ;sޣtҤIv(:? -Ϥe3.7L1Ed iYvZ߶[-P\~QtnRaN-M}}dho-w9Gzǽ={4Y֏,KA, wtt\s(w_0/Y̹1++|>uvt| f8nugӧ,>z̥u]q%s-39z2[fa4޼y;w_zue߽F"=t$2|Wq.[Mq(nui'y۟z]O R ˈbUWRk95L>]h"{)l24MD<}% wy癪~QzW:{^Hy]œ5M3qΉ(QEQ~kFi$i(Axt>qK<)v 1`4PW}yC[[qݮiYoZzu,'ĆG"ݲ$W$!髢f3UKbsv$i4!Ģ(J{$lllW|M7Yv_D$٬(XNN-;v3y]͛7?ߴK.dlz-^n+n{^a„ &MZqGKOΝiV~Oj O%**Rp@v^}AS@ &w:4OѩsB)McO+s6c%$߷\;v,;~׻inEs6xK4-M'Dbњ 8e0~ ?!zz>ǝ%rE'szv?㾜,]>N_B@a>`ww!"pמpu<=2`ĕdN` \'3sAZp髃,F= rJ2Jco'pܴZŪ/bHL: ŕeGfu.ݵkW޸w/\d>?'@=9E$(htv$J *RUe u^/9pd5Q2*6%8fuR K{v;6l0osRZVF !^z5vRA7$59@ZgئpQ<|رD=OEXݦSl{cm/B:ι$=Z~{lȉGVn9$a͚5>BȚR80/6|hzw;~qV>&aմi:A{*' `RQY<`0vTTs9h~xҦMur='ƒo)~lq|܁@u [~/,$:p19>աIjk J^$ژ$N{sՎ2Pr%4r`|sT 3@dGnAG*V7ʑVF{8TU3葧Ɋ"9N]տ?͓A݇D$&j2阢($T:ґ,--222;WTT xV\\L0=F٨rvslg Sz9BԁN{( !hmkB;QJs=Zoٲ1fə Mv^  SGBZe#2Kp{7o_`? ]c%TQBU9aɝ ~4 \ӠQ BK8syy+1(h'*&*T9YTȺV6(ܙ'yM]yyXQQ+-+'>A=lݘ͕IYr˟0a.ιp6w7|r-K{#gryL|rkǟ6;pvu}Y~kd4u|e^P8O륤LRs<\v+ @ %%%"!Dnwx=LA&0ްZt u }tbxliϔ|zIaaJJt6rH*]vw^zڿrM7^3n;ZBY {I}KKKB|ڟwoASc &3 qPES].I7WxyH%8 Pb2$ӴtM $d-MIax1HSU B1P*JKKeiܥ8&yu̱332α$d%AILlGHj }Qsݖ:BUUtDd,Xa<&o\ѭ[7nxt3SDp?r_$}эw qzY LUM[NPj5J)n&#K0òLΉ4\.Po~??` 3AQ(gA8"蓫f*i޿P4&Jsk1EQ`0l6aÆO=w4Ucg_~9FX_EQ6D_j?_,S֧@1pn\=j~X16=!<5uyfěosWY-pV먆~-'bРA^~KRW_F@%kwLPWd{5}^P j_T2A)r*Hg`cXfT,$I?閗wI,- B(ᜉʹI~n+27l~fk-ϟMr u1UE̤aZ>mٲu_|q@_\!@:]o!O6Inʚ/ (I uhz=^{Ų|\J^(V>sOdv/'}шψJ@X,}~[0/tTUU8]v}EEEJ0#!*L>z~B0 ڶbHHP}x^)HNMT 2پiz9D'" HcUVa%J%@@) ,cGNPME3xZ;W3<?v3nٻvw?F-z> \dtlSǧ4p,y^Wqtur6L D" !6'$y<$v$JBc-\YVgȲ-W[%K>eٳ5^Z8nqǭ[7|a^_7 tYs[7^Z׊yb^RM)|eprs_O]s uGúw":VQjsn}K۶F;m`U%f4wop|I5=bU rF,yw_VDZ]k_W <#G,wo~{10k֬S\sͽO鱌2?; Dꈌ2t&Q]2HӊvgGpx矽gy@`C3@ňdW\zi8^]}.m"Tf;_b%\WcS[6fΊmv4 ` UUW$ /-Vo7Zjkx,v0`gnuaܭ|9\S;]A,F ,ڞJ _0IP Ja(KW61+3k~|ܽ/ H)@J!.RAZ:?&|NsQ ? izgS>Y[pQYY !oOyI&9mȑ'-\M3qfLH pβx<9†([5C/RQ1WZQK*7*@49]cCVss߁tՉZ<0yryY̝;7:{i ͧGε\T'rz4!H!,RJ0é2yfcRJ] *hJ}#AͅU6u኎-DV3} ex?{T#n^CxtvϹRPھ;~ݮ?CEǘ>C7^K$^^sw[_,{g+?EzxrlN5r8ȏ>|R\x!ݝnK[sֱ*]q'~YV@6gRir]/HH:R*.+ d2c<-)} )|߽kܾ]X1V]MBJs]9ٹ39y^xkb0Ngr=d/XndLB ?ɸnnsLg7fRH!v"I#LyuJ)$%_X秫*+ɯ!^7449Ecc#|GJB@J 6,B8b"~϶ dk;.&L.WHX׻&DD-[9zOOI&Q}}8ԺFE)Ff&v it]?:_k`1'|H444P]]WR=y7s 7f: G獯㳂]+?_hG@I)Ü|~8- ĀP (4- 91xTJL) W": _GBIo"/C*;o {iO>yT2qJβ>~w/yQ-VS/zE Bc#⏢jࠟ,g璅6V*IiE?(QOZMS8R@`?g9i<  Wu:hT냞K?_&Mw6y& /=I&r(t]cؚ 3q]z{_Wo`ڴ!+e ?N}=T,$;7&|2۱@$ p'~Ǒ%fSc1gM76Fɿ6 kHF;I]'̀oK$7$^tZ^۝3A^v콲2IGI"By]M7yꙒrsOf쿯yyxgP(ȡt(s F,.L#W|;g^ +G9J)|RǁUyP{Ս$V>hȗ-_X9\bVJR >쫭o08-kAY(7 Xp7U[[+駟~}{瑺k /}M7=nt^!|1|(hµlDv!ܡHS,檯]y+6,١ NN!*Q,YO&Ռ3$I`744Tֽ{/M]㖆E!xoXϪ^E9޻vyĉc{ggt]uyoofd{xXKĦ.^鵵t544Z3<Oo/]JB). PѕSE7 2w/X L5v;^֮e$iH7.[lżӵ{\/^A3"*-Օk+KCTPn +.VJ9Lg&NČCP@*Hy6/|҈!>?\Ysq>yB +W7448G % Bn4NJ 9I)\.qcyFizmtI[]ݕ7⎧˫|yuNβQÇbue$R4xh4"9#s@|_2MD"qσ>nK&*ˡ8dmyXa "RJ)F٭;۳gk4Ոͣ,]~뭷|gN,}uK&#sK=߂h dODz&ŏ1ϣFXkV@'Ķ:%Wkpz{2O9߿z8Pbz gEyiPBd.Se*DjTeI;7GӏQZRX\Ǐ*0yk gNЌpʧY mάV;^뿄x߷mP ߍ}^ CK ɷ;3L:ܓB}Bnw)Ҵ<O^Ov Eǎ=ؘwna]7E`0>6o݊kI B^V^Xr΃+Ƕr?>?QcdD"~1c:p=[&Pp4J#TU=칟w͞xs,iT_K_H>f<ĚvjߚλdN EkStSG=UZ)גXp Ի(U,"&𗛛^2e> FXA!Ȥ%|>/()i0V?>)شj! BpI)n<(̓Re2X5@IElFL~ Aѕ7⎧+|yզRJ=b8|"i췱,R r-R94=Vd7 @2&s !:JJ) cاh=/gD?#|>phl2`q,s.Kn=zC8ĐaH_}lN̲fhҏ.dY9PZ s M >BT}=dy!,> W|mܹ` >tU[Jp7㻏=ا3fG~wnuL-ֽ{o6歝|L Ex|W'UQVG{wιأqF"›3+U\Q83qr;޵+^SGuI8PMpjx5N*1['2'x*;'n-+4%g]{ }Dhɬ9s/꧝67+W5/q*cLlPk=6]]_lnnڵe6in/ en\R|˦M[?Y'2lV$wuqHi<07Wƶr9v~# 7}- 嚿%Ū`|=ZA !@;wUyYĨ4ዱ،g͚ϝ{NGJќfmԩΓM0 roQ?E-B/*;ٞWZ_wMcM9S)_m~-*-pl)M-/+Gy e9`A!da@ Tt@#bmA.F!O92.Ġ </tQxe͊E ൓0 AJ5/0PyEtؗ\))[WAJq?fԠ>]aaСLJ)cN6@mm7@U67i~o(4ռ_ACf6VR1F,;CY)qfr- 'MObjyOϑI,V⍍X+>sϨT[[g{~6ow#!{ެ|H8$6J`Wꄺn߆/\aQ4y"(J%.ب1Au3kF(D= )VJdlȐa-8\d"8ίR@YJ+@3@(Jm-'`id$)6K)҃_`ޕN-^?Vm׊4]N}V{ F@jxsg3L?xt{Tøa!C FG|eZ8oݶ@M"~y:|.dah\'/,ޮ/#}Fꎕh͝MSo^^]=+v8y>Jop(ZbSN^588d8}Oํ񏯬F~_4q;yyG]9vakjRn9Կ\2G|ͦXɓkɫo|+cB Bz7y#,ٖears_h:y9x@HH1wZٳU X~١env̙OC џ*h)AI_4+Fe)8bDIR]WRzFB"R(MJb`wMJ$#agMVѥyJm2DAa5o5ȚEU1r`8RJ?qr9r94-"9C)%HO&rKj޼y*? 1v-(NmV5󷦦>8zFX)ܧBuB=禰, &]bL,SZFFh4g?FS uH7zO~s9T5ρ6u6sU 5M 3j:T  hS 4 O= #8ű :Hq>pH[`>}o|L +D Ta"`܈V ) .a7gUZZ>3zc u9$9MhѨ)x '{?__ pxk\=n&7d*-Q Qexy衷E"E`P)qږ܈b$Xv.Й7!K~UKWi!'߾DtgTEY RG5!6Ϊ8.e74cohP|rڀKk>Xҷ9l/&\_.?Y.Xjj'Ť".Q1jw?5=nPooPstNdvl8> N27Q :bQ4X]-;v)3/P וJAXGWZE}|m@8Z)Eg[#$HwftJn텗tt8c<#/3GTOUsL!g;`\T}ƒ@)eOk?8 IYt91gJ0+yRB u&j74L'Fg^|x~iDz(Ԓ(41P@x A@v"HI#_QVХRJҌ&w޼z"ϸlٲeIyyykQq a;=\(XVNfY R4M߸qc[ooܮj$Nm V@.|N4J{+޼198ٖEqEDW^1F*K+9 !nqPڛp0Tǎ˗_yI\~`oI,s?z{{~pz,KPx416/[ߜZZ 0C&7SRszi,:ISӦ߾ĵ90ԮЇaDbHƖ!N\7p%^ĘO?·#ɡ̌7a-@}H%̋Fiң2RŪ!_2HӐiqvʵ'5Ld1+Z )ՎFDdо}.8diCmKg60!+?n.^p.F1g06)]N|\ !@'F^NN9R);-!VY]vǽ|߷QlAT_%9ɒ$'}iML;c˿\ѨzgnTD5ZY`YLjdmm-'#GϿ:ӷKWÏz|Y#6(K? c1X[a)$]5i+BE;+^1~E D=HsX5=Ѧ64XKSiGծVOQ^&RIET1"'@X/-8{b,6[?5}2M:2o)D=c,!B !D@(sm֭mvnRjhӚfLYVAu⋸Q=V[}Wo޲=j0%b=ɮP__/ o5dPU!3PeTU+_!bE "UYVIG}}ͩdg_=K_Pt7$fn"˲޹b\?#bMX]ןF'Z*Alm$@#p7y-tK[NId^u|x lD5:E֮Gx'P!% h  9g I0VAEE5Wܺk`z2Kev{r#.IP4Sѷܹ1:n?iH y'#E[{nn NVOn]brWp޷r [_YQ>z-akh͌3FFho[i8Ipkǎ:OG8I*㺂I 4\[; jqpfBczmu>#l6Bu]u;T)߅뚢uWa츇zR5)ք~pV5~JM2RA2(--7c&5MH?5Rϝ;;nNDkkkgblmm-/h4wa766~#5Bpmȇ ~E;HYR$/@5#̗|!L"Zooov|>|'KLfN?Ku]'OLwp;~k֏U5k8ob+0ۛmee(E@"GXpUG`IK#G⮪sDǃ"nA WP^#ql'__ԮqsZO Ev|˵I!M|O܇yWGn{)"0NzŒO:wǙZr2Fܾ"pg.mMM{\&5Sޟ~#|k;.W]AagM?iu9*irFOG/ZƎtf6om׶~Iݝ*]7qMt#"±ޞ͌q҈?5Nǟ=;_xכWW֞Z38CNIBֱvNO~1EPd[I ?'(~{D^dAoG3;!eD2,׵lj^{mgL7ƌ3Ҳ,U-x^ e"v9cA'_ V ޮ,7ʸjWֹ(A̼Ӓ-7ү=vtY/oɖC{<[N޺`ѢJϔRBڑ8Dll̶~k3LbGk}P[[{fcccϝ;י5k~{ں89JC<|&S-̓S[G<$48HGuchKp)%uezcP#4/C|r0C'.mL 7*h yW=˜*qLФ6x1ca chmmρTƀN['5pW6%u)y895ІC@Y0Avn{"Izkrv`N TaLBIDJ۰wqGs瞙+//2)e,i* իgP7}փ N Txdv<ϞM1 ~Nxh^nj}OSo3+7's 6Xv&e;[[Q\\ fgoQJA4&NrK34sL s!'~G X̝2ec+ts9466vjDmMʕ+3C(ChdOʫ0 O74`ۯhp9*s{^JXܶa{;NYf@GK9y8GH FVAiC>OR)rF= i0k,w|ƌO>̘1Ý7ofϞ- J= ϔ7g6VR^9J_?g, QyhjEZ&Xٽے=4"[Zn J +K05aĸ#*kCNAOz诮عrhBOL_Ӳ{}b1R3wl{fSOy-[0$hV&hy>}2gjӵQb17f|HTN)Zc +zXhm<ϚϚz)b/ T;Y7nvH9$L3Em0P 1ie(ڹSF[.{FVHqٜ-A8=nQ:]voDh*ˋT"gJZ~0H0#ӵ~+"]VVW^yO?vw۶^V^zt&X~;tbSN;/C JQ"Oށ\>B>/" h_e{.`+ r3LLNUWv8 'i_Ro|̛7RY`JxayMDWxsJN/a 6֡9;%(+`lUMX,n3M+{v8,C5'^e*_ǧҪSAczp$@HXR@JAF ~׿j/b E?8-wX@-B[)G ǁ@T(R:vSrOwMsAE(hժƾfҤ*-8F)juo ųYZ|=^?˕f3JSf77;yFgzD|~S:cfu1{ݺJ"~"\gX| s9(c0g oiaA\1f}~TVA`cRERR1$.HmmWADeAAT~)/_ieƮi߻tQ1*g_tv_FcB]/k@)j&rG~g͘1=i w60Τ}SP5:{zx@pQNE9r2 R4VKɝ2e}KӍw˂I.5M6 y'7Z 89ͮ>7!C-ho)o^?.kpLφK׺RJDxJqo}xߜ1H9ieQJEQ&B:ตaR5558#Wܼpν7ڵMmi$;tGQ: W6-~5Z@ *qZB(2#txqSap|htm.u^> "I@ #Q?mŸu69q'~DcR}$Ƕr<JӯAPXeTPQr ~Vظ3zHyV>wi![M_(KR8 p.ڰV;?qQ#У@iTبʆʑSk2 -,K"rEyyհrٛoFHb[?t c%r”2z{}Df45 WO?3~<J5K)H '"\ɼW((" ("-r##m\IkĠϬIf-vU6N>xa3V8Xj{:tb"-#E0αvNO׎g "9o޼}FēO>94Mu]!\- Sh#ǖ]<~Fȶ!IBE&OTU6_3h4j/4D4Y_%)$F4=(hwPw4iL&r9 V& lttt+_v _puD;`LѸF4Ԃ-<ېًG`x@[JA.<?$h4 R{Q8uZy~uRŒR W LIH…ذ\.MӠi>jԨ3뮻nu]G{Rr\Hľꪫ<;MӜϳFj}[kz:R[.~%G|fP*?F"莜ߥO}QejVI$(-]NRJG)W]&EVٵ~ho8K* M^ h`$ctʳ,ӳ7}:&y׽rD pDz7&k:,!ò|D[3}:1Gs|y/%;| AS t_uﭣ >l˦vtt#Y2m# \ظq̏x4ʪ7JQm#Xcpړ(Ց5g>gpQ#h!k7'8 d{0)``Xc3dGHN[Lx{f%8\ׂx5,7s?[|I Ww&Hn^hAuF7ho7c=,--u"Dt]'f28m^{mz:@5kV+Y裯miZ)%l^ o聫P2 w%GqD;%KB2̂!CSOt10ND"qgS{$w^j( gD_٩_6nLmܸ/w0wQqgN躎3?aK9|\JymyiNA#~&C\*\8K//k'r-?aC{릮JPB^(1᭷!dIOKuFg ϟϔR 2伭[NϝtI_okk%skkkUϏPHC>dS $;ZݪAcߴy݄=|í;kg:}:)4ҚҰtZP r=SZi~t:z}W=3#.//qUw7H f3<)ymۃ˧8qWG ѥiHp@!EH ^w6gb+C-ZFMX *-))%F@&+0׉gF79^w !1ױ'lGDBy|0#: |.?/\hwPqV>>FbWa}1ݨ;.HQ2Yc3yBioGҪD&f?AiǵgQQ E0A@6كW8qlм! 699|920,ЍXW#LᅅDIĄmy5IN:Z=ph8ux<4Mӈ;41uTjKĠEfaYrVN% سe pSZ!HlO* gza{Fk P`K[SEy*7o6cFpti|~9 (md+YF5i_$xGBeC1^ov֬Ygh6?qO,[3е 584[b%lgUk}#`{l$\.!e۶diѨADvpٳN8%zoTDED%Z6+_D >!8r[VBgK6c ̑`IV`m9X50Wbzv&1:;a|>|8&Nqh B#˲h-"A%~2Y4\{ņi0X9pP@*':\z&G @pNIgpA * .?˞v^AL8D3O,㽋O)%G!D<8`+PRS4l@~;ѡ߫bҸ|Zʋ}+N-gpM3_'{M~庄C$hb._b>7 ɤ/O10zg4/<oD9z9\0I^?\'Xe(ۣϑ{)lh;]#l0GI몾<7]'t&kղVgUڅ?wһ1ƨ`l3,8\y\Wv}4HӴ=Rh,3W[FwpU)K_cz $rbF1-x |ZDr0GIi+++PS--F4~س */v3/Uw(#2.Nlnd?NP 4030\rɱ~- |?L*޿/}q1N*;w -\ا'{ƌ-}HH{"R˹CW'rFOQ!¹HH&%$۶/.{rصJgd|tpnBb/Yֺ}/r&rFQwWDtfCmaKEX}1}<481ϜR JU_9zo5m;xdO ??3:ktMMMXGXz5֬Yc9d4ZB@4TT&@<0, Ç^_pI.*KLBp0aQ¸!/R`U k{- Kݞ+iXЄu 0~/& 9X 7~E:^X؅e]T.p J#B :8%!< c X.YȱYmp%c>R9 W0Ϫ?}$]@H 2bPp-8]:R"k{<s+HEq!+qxmSd!(Y{ Cߞ'̗nu\߄k V"|,C P^uw~۔k^{Og\[d,}j~^.(5֯b1;qeY.-Opþ}H^qQ*ˡ8 ˲>Յj^FBj,]{\ӗPJ"mV2iXo!bڙJ3^hbZ͵jq`^UC 7~M&XfǝʊuV\uaཎNW[p_l/?Ceu_TOoJ%{TԜt̺6-}w^$'/P^۽/!,P\mmGW^)@J9[\.6JCm I1\Yqi`Qزޝ8|e۵uj|P9KUқ8^sHI!|Ls Pcںukwww> iSNAgg'0i$$ ض}@}BĻ{ p\l:0qa[цכyu YI/gev!xk!+ѡ p;8lBZp9'aՐ_1o;q8=6nbSvm[3 rԅ~a7ZzKP^Jp򛶃]%n9!cInq |*B8L/YyEE\ ,9) qCAW=? 2. Tk( sTp,U S#IlySû7l4ow 6/`Oy" C3W 9DyҞ8;oZwv- T<ϕK"Rf} =J~_ e+X$ {jS 4Ds㚮)F⺿ A AnA6цԎ veG V4T54400O;n贗oQOi*HGZtSjҀn] 82RjʦA̒8s;nb R%RGβe)Kqݾ_VVz dmjsMD[ŏ*RfFPӐqS0r.u ѹyHY8kOO2"md"H+r9dnܦS%lEtlb ^p7aCN!;;XʕCZpA4? K.$q^b> H )gR)_0m~X}衇7t:-b>_~9t+ 8s9GqI1:s rĿYGa *N dp}ea =Ir|!AfCJ盀0+q6VGqHGqr,^ƻ07h `-X )LK*x=-_ QT?Nk{䷇_D1le!cN)( })<\6'PjtғQ /Q>FO ޡYE \Ұx\t~@&bX$sN(B1ąS$Y#LMg0qLKؑ4?Q2Wx.aAh@Px9 K8޵(_B5~3)'r(+n/f294Iv9(/b(pƱ==-I6 ]z<` HẻǯY~~w;76'vA>HC 5&`J)RvzD׵w}g N$S޺1""ﮗz8R>[.B:i% u,  `\C"hfc \ jCk_#zp.w#y2ˋ(o&I'0x|@`n%IԨbqjW0AiTYqFu$8kXUeT2|̟ѭaFڻ+J#ՓsAD$zPJA lYZ곒 7 $ZneP*m \G3JyǕJA)&q  :$Z?NQ$2;LJ `YR`Vt/c"@" eVIv:<ob `X:n/-LbtepB"G8OD}7ac-ƣ}S᧏&e{JzSi(`N`\û9zq%?!TUj p NBAsRr9j"-)|msSJhkfƑNt;Um9|D[ftF{?((tmmY89~"x}I _< aܛZX`tXkhut~+˾/47dl9q˶V(B4M}CG3#MW_ږJex”T -h 'uuubϞ=6f\#3։8߂'nމ` ,pm{G7 B~Z/:__?s֌3D4eeq皪2B BVoR95 ѺZ6}l،dg+';OcMKΡ/ AvaN8s12lUVR@%5N~e5Ph h͘1mll xO0u|xc'1io*T aH)e}c tU>ف 44^I=b3'0#X5@zKcLCGǛ#_lfÿ_^GmڑD;$>*$?YYRyg QNRiseD_(x1Sj؟awrC¯D. ":+RD)(wfXiycM  %;؏ҫ^-a Ҥo0hґ vsU#aFlD%6phpctԱy a( v+1xs)7[[󛒖7T?AuubrEՠung %tiCƽks}B!-l41{s|cϣq?` tx<~5c,Wk3ċo|Dog^v/uM1BJ!%H3}2TV1go(1(ZR*yr飯ݯR$K\UkCКzk>\6RI!$~!Aue!x Ht{Bm)|3Ual:8>,LZBx-66Žz%[p)7_Єy)O^)Lc@2+q4njJVN?#R)ښÔq߉#g ]%y%!$n{DO8q4[_Tޢq¶l/26sC8urЧ>?<݃K8)!})dV1oQwZ2%v$a껡\νq$;1Qَ38J=?s*K* ^\j$bP 鴅)'jP m4NC} gs0",L^˖,Cq:>ޖ. aa:FWgiӎ.Eg9A:& 㢓],41C=v{q"%p AX!ϏdFb|5G')`-q1ڜM> Ts_p0'K\ 7`Q"ƀޤR _9CmLE[6`|}o~AoK&gU(lNvܘw,h\%0t'en]z06B'1 .&@#@#CV%徊AL+-N4eN*k趭MmYr4d ,0@,Je5l7Qu ?~~hH-V RДk_u붹+I9J1EH@Jb(3\, eݎ2L)c}ϟ%KД)SDR544<)_/`<" wgX5·Ϋǜ]?i %Vwl^+}™w隺'_uJ mз Y [ڎߺu+K3N60 aCdH$d2`)9\ ^ギws'#] M4yk@o8׶!?rg9\὿}576r d}zP)]*$as{>PK,ߘxF/M+q0%B&#$"6V x~AKT+KQٍN*ㄞӋm (^%A ztvqG 7Jc]\;NxZ8 ۍ5m.p~ AL?6*PUR63 3]/]>TcX5b >ӟ~L05`lUNJMlB8V8ylphvpܘ|+` 7/ ΁wˋ0zxME|ΝZ ֖Ž#+K/xy~\y!>llu,NDAyIYi >˱hPZkM6Ɍ-tEu;ϿAUߛp$RXϿR>{4gzkSoWѾs j,ՁbJcQ`k%†T6t-LXV78ۻ ck:FfD(`u]NY  Ce<݃1`vR T46„? s3$3m@`D( 9ZZB3H۷Cm{n/(KA*3ֲFQVZzt_dC6ʀvS#iD >??)$()B#0&Q,:[?Yuuu3b}ϡIY}݃/!'rFъoIQ@jN?O\pŅ2;qRx영mJU5n]׭I b{wo$bP^ D~ Jr(fbK-%_Ջ;Y\\tl[.k.ށ"Da8㕃` Θzi!RR1x-i}YCN /)+5#($`ɔt: 7g* J! 3+ 4wE~eD(ϟ@!]º69ޏwVf|pUDB9L8aW4#̇ü( ֶN(`u[)~hG,藒8}\SLJ0$ ޞsB2;t!y+^πՏ^ ]ۛ3FtVaT!><=o9=I| c*ح7F>ê <^r<ψ`dy [iH]=DbP47֞@kw5a$\paliw{Fic0΁ 7~M7ל3a o,GwdT9 8u#rq0X.8%cG8ӡ򨮓( prR)a7zq1!CE1:*ںl-/V" +pw`bE`m6 yx^tVk!ZQI@f>?|v" Bi;`hap!t#) c^ޯg TE BnJtV`.~] 1AˀAHІn(WJc:m|UN*2 -*FX0C ]$̠ @v Pp3@3J ܆ID8S&w챧~~p $8T >jȺ_u]Ii"p$N ݉JS~5f߻knc7Us^1捁 +rBs)Fno!NHB=VJDJ:;PٽY#pʫN59twn/RAeŎ+=g7ν, :;߃NW Xeb)M VV}Vn'&(ǝ uVy^B 9s++p ǓeH&0M#`I ׶qaZwww+Sw ql$AMŬ#QɽT Z|"JU)7{,XqY,L`Ֆ tJM4`G%1qw>Nܓ>Nӎ n+ Ľ/@NB+`.^^^B0XlKg{~$>l႓#-p2uJDZʺ@!t0iP fx}vw$sK <0]8i VdbM2.t+xӹ;pΙFWC!ouLTG{ S!|&LSG4ÇB3!8rJ@T\L˝`)ti_*9Yh[{ǃ%4n&X*`Q hT1)*bYؖũ8P(N+~tRJjPIKtnẗfH麌 Fv>rikx:Ut)nG([OϢ_9w+b*'r$`L"mPR"#[*j`Η`ʕlpJ>3 cJtRB~aR$6 ~и(wݔIXΙ Г{p];4|@yimdZW<[n( jj$x~5m2ׄ _ꏑIJ]iˉH B Sx" u[~!H HJ"d2?}纱צu]89Ə? ٜVuQر};\W`Xy3Չy]tq`;0$p*XyKBΞ{-lՃ;x5^y'1oLug0licn~ӇWvQŀT 1HA8 gWpAo*CyB*+q%x49qH m]sɼ'Y ~IXoh,vYqp0M?\* xoY{PnЧp"3und~»ӰsFu}ݰi]Coxk0oi+f]RϽ6j~'|a/} {PY^YDŽPhp˽8xϻpd!׈2a{|,@"i&(_`tGBJ(=ӄߗW"qgBEw)+pϿZn  q `/'yiG芷U^^I&c[$jGf`<#L(X4&:! LgX<`ƘGl$,Kfl LقxT%Y#Bq/ee|R#+T(l+tfі%W$,l@D9`RIgg6*-Nr] $Ae 1j>"P4H芷7J$li SJ|]…`0t򞽌g,AŕdR+8:LB Sp+LC47%,vWϵ$iTRg @J,ǡ/@ PdBedVZ?m^3qţtrmi4-GOW7>lHnw˚>#A.Eń1+Q S 4\T:OH)'8b=x笷w;X%ɓ'xA)`]]]().@@k.r94"z^X5k,}ܹ{ę-ʖ.ضl&RI!+¶zY9|aPp{y/P@gRdž.& aXIa'[[/ 44zWyiH 4o^qc*Г2n1M|iseC @H@"DłbE,xCz^AM& H  !]Z?9dfc?29g~{׻ 0JA{&?bJ)e'ʿCBmXZ+,F֕P<vˈauNF[sweKcwh†. GL hNB90LnؖvnQvkI 4 k%7[wtX-Œ0H Zp3Dհd L avD-(x;6%uv[?8[m;Mr^d :hWZ *@-D'Yu7z({a%.w! BpPxۦj^w Cax]*с6R*n(lnDG; _)ZN1@_ |zO2' m]ʊ:Tph[*J1v&8c~jw͛=Te?<Ӳ]dȬk4  uZ)bX-,brұ O9>>T)|աq\ƊՀлڷIFl䛿$uw)>8u5۪ x1|moliag4\aƵ_-/ܵ-hYqjVEPejSgmRb8濱ljwR2µv0-Vlmw50'm-=djSWf¾sɦ͙>8gb\Ktֶy҉dIOVRftm]MͲvukBm?eI ӡn/FJi*Rw(k_Ϝ0aZ)V l+J6Z~z m 5?I͛7OVZS,ϋvIOOJ)Zv'.J2dKmte|)9:A:)vMgޡ1a(.EJU?&Q4 0X5\\MNdqiTRYp!v@s1Vn,p ͠hѮdm֪1sf d9<]OtSJ!T? ʃ?m VnMheFdYi.Y+;zkqbH{?4*\ zWIXxA8(=kIDAT3`¨hirm;8䨘O2$LpXTAdX0Աkw%FCGIm[enWBPUJQ:biҦd|\[enbS&R*ؕV\D1M=wrhBJ;J.ԁaXI8N&5Z%aܹsy%mBi-#~a*c7LF4 pi~|P ][FeK@~7]yr?!xߤoNĜ)(+-c m˥miIr[FTeX:7Ԅg99v^[0zc+YbEC? pd! UP޹jEʾ]o65ѯ}?7gBkѢ={0]o+ǿt%KZh]O8%~rd:;{CSvZy掜h+QRQEJSj0K +ϚH/ZZcZbd!P|x,[ sU7xcsTggBJi RX,ƶٴim ʶ?2+&R1|>Oww7F =z4ooiCr~hzJ,-k x/ I-̖71I]L{y.a&E}KUبJ/X~A4A%rI;5]'s:b!{&z4U'555G7WzƜ}{/Ű V?$2"79܁A@ScZ窱ġ`h/J.cɫ4"TWURm 21 aCg%dk40JmKoˑPɵDtgQW|ƶ%~X-GPٞC&UЊ$t峪9\@:aSUbp뺁oM4TuH|"^㴙龹uC2I1~C>--C[ZVd8uT`"%~B( cmSw;c̆v5zXdު(Q-SՊe!Dhv pby)\|w+>y;yZ7ڹ%QKA&yfBטm1!\߲h7 ŪkBϛ<+.{ח6Ydn\pWW-3#Bݹjt^ّol < #[hhPyZe˖,!mU}0|UO0@㺎*|t_bS͚5)SV /5XӡE2LAǜEszEQe1gEn+:qƘ^!7zGBjW e%zg6bؑWw'%qRFM|Fk웎]kMԲ\.wx}}0LH&imkcA@TvEG-o h}Ӵmop"-mo i:.ٗkqHu-$ ) 5,XUQ%,yY3j9mf-Z`ѳ%<D"aG>[h-B`*@0ϟ;ZK=R˱#9=w#"DQi[B(0o[5-\vS;7^H"fkx7#rFU|!Κ:jQgAG>`djm $\I}O*g|6oo|PDT"?#_AHi|d@%qg-h9sUmٿoR5jԔ-mjb5GaII, أ=~X f>+`!:}'Gi^}hc !?n}W'~zǷn2D\{EgmM.nVUyt5`GS)]UY!6:ž^氃&cF/\!Ap1 |Wz;"E]\._rEPfanɦ;iIz{Ǐ5\<-,-<{]2 [_yQ]8h*N,s峗xՀ[Jꐰ,kΝ;otD!X nIݱsoƔK%RZt2{{{{d7-[km|7e1n8z{{dĉ}&N<7MM!;70,H$r|x< C671Ht?S8v-/ Y!_T۰nK2#ATp„(?a<*NDV/m 51UN|DaFZ|lL/U[k&([ڵ\Nk1G֣( XROʮ$V <וCÁ`HH|8|m'wX҆-:s`}Zۺ -%V/2~$_T} t*ڱ\ Jt)T_!1~#Wql[{qU#c\ngPm #Gj2긒%Y@ Qژ><{p޼y/lhLQK ,ƐH&qmKhQS :z(o̽ם ̱h&B[ ,8ony^=y> ?R7l->ϼRvgLTǢE ݾ=#}fB2_ KzgQa )z^yK:ބ#O-N99{aӅNw}YkiqRJP 0n"!t_>x]kz_鿌N ֭X$c,zQ9}ʶao+# +x GMxcy [{ب%-5qwTxVԍѼi`!{s${B a 1 L5$!2Y,k]n| /VdvGa(UԖr|ɡ@+)yGl^5w_[l! CZZy+d#2cdP:_+ &3/n)m7E7v@%݀DcbRi؅ǹ:x%%P Nm_?_( ^{$t\SRd _^i޶ q*#?W^?j4P$v#v<QG& ,S-ľh);|A-{-K kqԤ!̶ e@9k u=#ý*y~]n/~ha|=vDMƮy??9~!_O}*JK,ie@z>ӵ r֜|eCb6&ȗ¨H) |{k%zW2syyɹ*+O>SSN)]zkMkk} S. 6mT曽gb{c|!~eBƀ}*s.Z  OOΛ3=sΦv }֥;CrkVx2E3m3fsK'o}_,hENLlq].-8gwMnA+֬߰< J~e1Goٛ3g5عSF-%;sؗ2x#%>+<$w,&m0[D6hVK΀vpb޼yϟޓI.JַJғEQܖdƄYմ= yl\no(SݱN61*@J|f t,OW) ! 9?r!0`9",l ߢTKWҒ4 GR@mRMնM(p(AT=O͛'W^-TԧƧS۶ UoA¸+wuf^:^'+?o,o{ǼW2憇go>M²]?;O_o# /ްt|2]?9(xAFHc'|盷_6f89RZI>ۨ(G<R}~o^~_~vkHUߜLN-+ *R,{ /tu;ϿU?6$+Z⺹?zË/PWWwM6_;!~GNonv&ِ%X޹;$;%'{?B*iL,^W._|'/LLy fBFUqHF+,!ٲs˻J3K&`GRwnwm߽G=jrY<˟: 6o)STṉĢEjط~y>?.LK渌NZkuKY륹0K?~+O=l"q~Rʙ1ͱ01:R鞯SO=qίI!VT̮.ҫҞ n|]dI8GWv&4y ӧO/u Xb"5k?LyvS<`|<>))FBD !hr-[}1㎜0ލ7>qN~OMQk̿tU':{TSlѱgpP0l?7>ȿKj*qJ AEb2zFu~':Tnvh|3(}p4)%;ʹujb1ɃwԺu51|3|dU|!*)&ʥ,A19GLXDg%붕Րd&[TɄjxߟ~)9|D''NIҝxpi i,K"tTjeE][sƎKMՑ;.1-W|\!XN`}}O.p>]^iSݴx,{Ǎݐޖ@m\*|1+=qNO rX QZ @yTmbZm퍯pd}nN$nL ZߓJY뒲mau',mc11֋Y"H 'c?.~|2R۶x.}.J1JJĿW}-Fd{kx6_(S'$5b1* tS͹A. _JCWw7*şwBRd x l(˴uved wI cq]RB`I C "JRZO|gY8˟%ntRZo[WW'=?BiZPc"Lܸ)Kn?lRFۖ}9if40/BzeY)l#ҩQ&B̞+T$|}#;[ёQ4͕֏1j+ j bf!2D\;jg*{Jd_a䋌6=2]n_CFny/OO@HBeP"J"Hzse))Erػǎror*|kn]xܰԛ: mdF 쀗^ObK֗n0O1QMK95EϘUqݛlDŽU*8`(0JƀPp8=\޼vD8n@i]c*`Uώr9,nXB9>׀M_wGOȠO(p*܃D@nbcGA0 $y_p$ڮ_"9%ŏOhɷ|gE+H0m*7 ]y330->K( G~ U9'P[=ݐdlS~pj|_SI2 EOucX>"\JSn#Mo QP*ko(z#`agIqSZn5gOyj^+l[ۅ3sLL"҂Oyj{LMU>vH$|F/aQaq@cIWq:؂;dP!j"sیNV[- w%|E6cQ*m3f8Y۾>(lcDMi&҇Qj_{ܕ©eO~"\p8m_:cBp103E5qgs?3MRTJ4vw7?#P_7MRq{oɤZJ%~8L&L:7xX< CgZL_U*Q;e k6ocV:{zfL0GA~Ohoƈ mo燙 W_͕?!o-_'|#GM6Gs3uE;iq==Gs3ΕSFΝ;G?JSSz+ !D:GMv/9djȷՑ3aHLJ% ZѫWO|b!`lٴz,ZFA9 ѯͲ=?t:t]ilr: JL?< Gy$z!2dct鯭F:WuwsDH۵\0$h!(q%DH$_1spu=\u* /'p饗~z<@~pWWŸ+χe?.1UJ[ԤK#xksGdz0:jh/ydI-omNNaw?h]5~;9G]ѿyƧR  1G)ٰŢ٧D fذ٥SCPh,JZkO='wpm "kUHe#[qQB{䅜~P L.m6ST0PM~P+ <<mvQw"SRegCecrFߔ璗[1u#K(Z˟7 !8C'XKa# wufPQȄ#ᱥyGLؤxa :x~|ڪ0"DSQJJ1]EG_`aqQx"(r|1[?G`aMډP#~X5)qbƠJi E2R81cjR\pk8-,&t*k7"{>gjA7VeN}B%]ۨub,ޕZ \cڼS 361&T? 1M͑G8_lVv~+V{ZhM1Ǡ;cj,?8ZlXRךjjXLr@k+Yxӛ˱e.\… I&OhYgd?kjXaYL+DPjT*1bXz-3fѣqy\ىU,bg2]|>ϱ '@oo/.d|xG^R=|\.sιr%y<3rbJ׷ofL}6˼y?HPte_׶-%9^:rץ76bΎYDf: -ˤI]2}y>|9Sƍcp+B*bٲedь9Br_7-ZbN–>^MT [64`K Px&yvY-oi֦& ?àF}CmFј-qןY*'n`5BsM25(md NEaixCkC"3]ΘTOW}e_qƤzn"r:*;n<BjR)m[٢/;:"^Ѿ YrT 3]J-xZڠB'|Ր ɕC>xh=?nJ`1& X!^8P}`c@8Ikqocʄ8m=n(\ xad+i?Ֆe{M-U8q,;M @ A׏q8œT E/$rHp_:Rk+2b5)FXC5fsUGD/\%f׉zuҾȃfSCK)o\ ;'|Aٖ|NDx…X\;60D>7B1g.2H3XO2~ v^t--bV2S c?tLf毦L1ffR5˲\caGZsmp֭ࠃxCb֭y64`Yg'dQĵ5˲ڕ5 hКn!purTUZlĴ'3z#{˷nb8QMmCbZG_{y/񘘉gZyȤŖ4v:R+wyOTγ ͳ˒#{D<&f.zL|%t-!6|\yp(slRWKsF_ۊ+&he,tWc*FU3gLRTDFS|ΘWoHەLj폿0T4@72fW%#c ZJ44=0T:c%PTDCΜTͦ؂S70 6qVMn Wz \d$ m %pe$FEm ,6 Ȅ۝ w;I6ȦlV$kGkEލ!a^PJj]?,%%OwjHܵX,ϴ5nt9}z4Icbgݖ-:=MS}Wۭbp`4(~F)!s9f݄Gz1Z?aQ$pCQWWZ%İg*`1jt 6γRI;v'O$NcXLP*46rѤx}??;v޳Ϧ\.H$Z#+0lc葒͗_N8Ðӥ5YRb'a m3ϱejƭ[GK_> kW`„ ̝;kײ~Ra8dMՍװf+ DoP(GFB0t}Q*a^E6݈"hql77X>2?-nBkAM*7Ӵ$r=-lstM`0 IrSo%Xt.b:↕qRiʏm #%bW+7){!q7*~sCU:ww|i^1χ LʺzO5R aBM˒<ɗom’~IHԆ1|On%/k•<&rt6۬HOX;!cT1Q RgOt;WD{޼^Um䙕<&}S~g*C}It<*+2TZ!,r=|iN1l1$ SHaYĜSɘn~yv`>OjM(+b&Y,J˘ZZvhm<\yq:Z[9cd9I)8r$;iNy8hFࢋ.,m:6S1-ԧ'>A\Ƒ_Jk%Koj Ǘe|q~~tcb7FvhmcCsv ont-XX`Iw+ipĄY&e0 cdcH2fH|6uHO oY6&RF/53..>/11i[aV+4@@N:m$~M>wހ~-#bIBI=sWӤ_X;Zq.>\)$VFQ*eP*_Պ\qT HsʐkK^{nfΗ^&CЯ H61sDҗiq6ܹ+ViMEf vX +5ʣe,"Daଢ଼>w0SYkcK!%C yXsk 2v= !A0iZjh)PG׍g(iA}A+Mt?wQ|Ir3‰ KSdЈhGYAkB2k÷?,>svB3qcXJs e(Dk#|+D)L w;VF0:TvG盙6ѿ[?Yogg>6a(U+N]ɏSƠh:;:_Op]ù x#BR0DTR(!Z%R|Jk!}r<[1b1Qat7}RLEp:e pQ\rSO//3/gҤIۤH۫<a%KǞ'S)nd⋴>dXm|0˖-cٲec1z`x|*a {j&L`ֱrgpB\ރQ$k ɝx&X.FX ٥oӛ՞b!vgFipB=1nN "xfnK:%%\ ޗ' 8",~3>s?Pd`AL WDcDE'*Ñ0h$zl6 w0|)7V~q|Oe6n犗r"cPJ(KVTw ]B>:_ a/?߆s4+3m9nzhR(Y C9e wrڗpب?%/8 JsV:=jl\L1q;*6\O8KFmFGUZ_TVGI Ah"_3 ŋlL3fu@E%X.׈:Qj%JJe197\1ݢŋgώЏW_qWPFw?KS֐+ÉO++$ sN+ӻRl^o?AoЁ6T0ֶ 3x|\\qǑz* Zqd_1QnGZpQ,Һ;P^vuAs躪9pӟav6SNj?<҄+&谫 z{EYJ](N2USÁ&<~|ߠs?{nNO1O~ 7=r-,OIb{{E!=sĽݷ :?4>DN0ӟ4jIҝ{J)"q~mΘzZJ%~3}:OFᇑ_*kr9]˔Cec1j`P|9&/"۶mo?AGsᇳS| ]CWLBHVvC [o%2/ O5kazIVIq!J(\aCꫨUcZ!rdo$`1-.0? /&Խ2W&|媫xykWʧ\:rAmQ3%p´,P@ 0\N0 P6!4 -j3<.^ڱ$r_sN+"L㯴p3f.0V a"VD QPR'&;$|K]-zBs ?jKϕI5,Z$uT_K]\_n|e8ᣇeQ&-_tpj#aHG6r?Z1Lm셜?H Xf<-<ݗsG<>ADI 5_d[Sg6?*G6m1I >ُwW g n̞v8)"7݊[AA*dtA*K -xW} AmO0w#ОȿqzzD!mo~#ҾoBa`6oؾmMMdƍ3=r$3n0/˗ԋ/t]}V7+Gs;IhtM͚ϛ;k329VT"zXkC `ˇjv.upI >2"|]E(JQ!HH+ T:폯A ۍVpAX p9Ԡ$s˛|vI;J 1$Hqk?:(|zʾ,m}<3#RzK 7XUFn"_ рFV`¤5vDP5ގ纶r?rCEpBwOm QJ6JYhяMql V,J3J196\1mL>w.,ƞ>k7/.B 5,|\R YK->uF15'^6^2u7n,_<}N/bsQ_غyKeVZb;;jkAk%=on֭y_&Kw76ݺ=˗#cQuw+tfΝjٚ5\/o? 5^\|G}7w<3ϤH~x%,{ &ܩim?BATe RյW(pmk+ 3RL-_)2mmm,Y|>hb*GtGwwmpJ%<{/7W^?17p_=+Wfڵm2ao--$R_? C2B>O{}b8Rͼ}WUH*E/0\qko;wZ>Яv(C̲1͍!l ؃_Y,KXB)iulolo4kׁDJ!)¥s vDžGʔ \SٳXY³8]D” 'ƇG-5MhW*MuU5PV|{$|ϛK.Z.4 * фJ*M&fSShHũY( 72ӈj=vUTS<З$E lN pɭ{G/G/^{$<_4T\1*0x**ٙXm"+ю(b.}'΍Q5Kt,x}UV[ZSv(kcPՄU. xP^Y8&i]mu$\E)4 wwU!m$5 `]{@s1,>jnmo .Va` |>L1ק8 c|8oV07/|+ ", Kwv 0ywDB=&:}OT+EGpO{S[#!v-/#B%rY\hYW7ߌm?o͛7h"ҵfyQGaz*'܌yz\(.EW υ8WP.TnA@\pL.Ǽ;qq^oȅ(J4-.\H>+X!YRw1cZ[#|=="!,[?1^|Ez!^|E²8g]Tl a4IZ:!ĝNɨD}WDWzq[t҈D+ex2W~bQ/'{2qKΞ_FjCA4ྜ!ڠwkCA;Mk%|WrSH"^+ Ԑ(吸 '!3;֮Y3R4D@Wr5UŷUE`j5((4xm\x^1)STBMRUxߡص|7L'<^|mʕq'vtZ'7~'y% HCAVZ騳|@ZU5tB`I HM4c͟M1sƌGPU>g է5/(%ʨ1#?>ܹn[tbl**6_Cm]UGN2%U,~[C+1(xen&qxƧ@5Ķm%ce0BXouc?ov #VMo_r,^l{X.stG2d9ݸs,KZ_.vJm--ll\umO=W}+>ѣyGYb555O vrwP]Lr%/~+|V kY޾5.ug]̀. yw.7be=Z԰N ˑd*y S( jkɁm83aWcpG-Kz1G 줮.DW^x.Xiw曹qADmSTw[DF7ƍ!hcxgpF?{,Y !m͛7sW}GzBxD?NG;bGbRi sBtO[RąyCͫߴDy I6:l*9p{#*kӆp_LТ_{hrUtՅ R<ϜFDj[&P`O (EüOrﷲ2gcMtbtc8$Es(qtɸ Ԋ+XVG2b"]㲝l`X߉%!0I_g3UfQE! %$P\ɶvs+4}BڶK]ª"ͣ!TAiUo&~v_fryC}S,(i1 ^T;&L&~ww_0DBxm8{ۺ?0PKP:@N=1ur0t}zs- G7`*<~qx` 74 /]+B0?j\fܹf buuQ1 e_gD{9yC"n;iw:K@0:Z66y5slFigd>o6hMAAk{z0ԈF} |ﴵ|޼KamcZPW[m QHX=aU#Ws9.7߈OuAs=!Jkc3?}|#b14<z* ?c|c []H>>\0V477s~?r[]a1CTJO_ddkkc/3c F44Еϳ&=ϜX.?g*Km3Og(cو! e,m0$&-Q!Ɗa4y."0 4c}Q;a0\}[-|OWޚoEUHw k"#ER$,b@ ITI*'4>G[~9ng+ +9(NL!F2fakk[<_nޭ6ܻiC=5Y7u1elw~)` ؖP sb/Hɶ[[C$F>ڪ|C4Ȧ8[I,>tu/%~3C*_WO>8Ȏ2s߃/j"!Hˢ&yHd.=oǟ?X߸:D*P(|7ucooM[ИHTb.ǣ+RbRE{K~f=5MF zn (= 1eЃ

:B0#KFKzWv,E2 v~.a_B.~)e%,o.aYb=;'ɧ*?յ-@ʻyֽA妟Wnc6{ Txmv|wo;DUoz;A}%qvyv `"g___8c^?ˢ+I7K =ʛdr9Ėp4=rOE94X`a)b$Be xK4kUIL5LemN 26lل{[]!Fp`iQ\/w{ոj_qrmHyt*_gŸ U_{]{(ADj͋3V`a˵ lyFxP% ֳEP߹ʬh5 h4A!F\TU?$\8S3ͼ_!3 "=$m`($%ɟן`NqMNgRKN Ipŷ{eM.t}a!"EݑjYỵd lZf -΄?_v7b҂^ hܑJb;#.3pE_+ lOaqqtrvu]guMH8? b_jp>C㯅Ζ~;|+}@05&**KYqIs6|x2 iq0[w;ЫۙB2at |10>.BܹѧM֮)\ 1IU)J*R >1xCkhr"gہԃB֞ J+`v@eBZ\`FAPIĔU\bV þiy ~kBw?-7=DR;|AQ6'h kVZEڰ^-8\k{@h{>X-|Fb`VmɤX)7 `=SaJJq`p br)(S!Jw㏉O^Vc_t.- MR_z)oǬTw,;|Ҹ68*~|wlfYrM$8$|ә{#o5v;gF]SxpBbBF,4׻`w v.5z9c7O^NsHjܽoߏ"~)u8,EQ`@n2ۂ<A· w҂Tщ}$O 3Vd{RĈ/-焭V"k >PHEr weN+ͻmw%6M 8zM+30Vv{eI4{ 'O6#ͻmL"n)@.o2l]eN>H .5<68qh5? \oqt!"6-BnDlcD0)"1[ Hٻ(nzgCO)T$QD lDBp*AK,F1 xA@ %BX"5HBhYٙٙ-yd+gm9)j5:\ ,i}Ŵ_=7_󅻃 ]pII  8_)70)֌͑0ev^ؖ-I^bm 8Ы[<\KC+F6=5m=^,O2b,˘%z[|r>nyƎp"\L4[ r\΅>njX-U׼1d,nBM&cK{D;885?YhZd1AiDzPXg~P Gq⏣cbg!>KEWo-mԝsX3#ŋI;sPFx, /mwv_Y{B뼓.i…wKq\쿞WgKmiTg$|5ݩrq0HXۙg,i3-!<ى6s$#A.(˘evo\Հe` Ψ~4|W3 "$X^|"4T+wyp87nhW딭oj"@@ɕV`*3PvXQT m" _ށXs:x0mĵK!qpZ:=Ay!wj~rg'wl8u_pW4m.w1֣=^B(_^:w{?i<߫bkvWy O/Ge{3>{҇'tύ0} B'Y`g56]3?HLm?EP٬mz#GCeOS1Oݧ|/m#+Aqܸ!C.iٸt!ɗ,zRt5V!Ԣ6 ubkâ)ӑ17 3V`"-%K D׶o\] 86Z ҏ6x= 4fʧ GR@)9 YmvRal[dkzA):M&aG#z@ 9E-[wFnN*0?W4BiبΌ3'c`*?IECnpH˓17@X懟% |Ǥ*AݤKa~(Gp ҡ0n"emX[> qU$9k'G~'.m.{XK7qM MЏ'kloL@okDgM߽p}9Z550:j5Ԇ4M>{Q}OO#̀ p(S N0'wy3^_› u[oi}!>ʐTEA=2vY/N=ٹpȷIHr'_U\~2WUpSUL0Fxuڄ|=\1Kz:}ACrty`:߼~yDra_8|@HCn/M5|$m 'NA0pfzƅ.I^`% &J (˘ȍ7U/+˘h:@s0 XyEHT;,d,!7-]y5#z<ߙPO4n~+W3%$C4-@ş4-@Eg:x:g<]pF޵T*:0(XtkԦ=uDNf[!ü-.Һm qnZ{ p~g<y,^wOFi,7-Q1q=|y秖ǭNY?+ÒBVN(D=o +gzm~.r@- -SGd!p#dmzXSjҹM?~;7LjYEg" =^|E$5)ˁUީ45BJ pzU kX1Sn_FXnf Xe- ދ3!,B  WO^gN)ޖ|Η;PT)LEMy'cƦs=ݫq)7&E{+^C۹€zz /`J4ڟQᕐ/P8cO`+L!!cp7/O8J|wC>ʁlYL JkV5{NZޢRʶ؎DŽe[)'Y_/-#읣[uɠ*2{\ԒßxVhш|aGZB$M $ 䜾-w]P)jkku\M5e˴'Ĝ`1\\%)7b# 0أw?F|Vr?VqT*xqAy!Vq4>DBj~{ESpn,(3vqtB^DZ-|Zi!_Dc9^ ^؀"a?NKf BM<=_ {ԕdvO^UxB$,l|MP󥿻$L,~,.'sI?w}C+@z]?R*e31G kŤ<ʗ@$B0;2dޝ{(-brc9s^n "־@#H­RQ9R}Ԩ 7OroIV\04ںyь9|qь ^nrs IX O&1~PUu&uj\%`QWH{xr:dߨ_H(\v&`M |(1:siQSlkJ^ٖc pEN!~fϿԟ붉 :Mؼu}:ȖpcM;nn0~w*o]A7Md E ֗]H)ѹ I8z]3Dp(uWHEQW[ZK=ڛɶ0e\Ҫ|^VZ{=Q +p \%}t&Ù @CH'^+ 7)bn0}7 MyӟPyׂIk}rPx2 ™ɺuTj0Ś+|e$ļi[be<$C_fvby[1+Fr5_Jsh†% VK_]"-U$-큎8Yyqq9}:FEEGN1Cr7؎Wn1NWzQwfcd8P29kܯ ަʎSM0RUW#L%jč%(/@c7iZs¶BQ![C!TU0ЭEgQ]|wW%CSy+pu `).]>=_'ȉ1;~mqfͱ垯r|YwFQ{@|j|3% gvb򚐰R3U8AG+$_E{4"Ֆ̳Z&!SiVY~{_FPtX_.ͿD?_JmQVJ2_apZ%mAXElWMX9I=`bh[&%chVˏ.5]P|-pm,+KGݙ )%ڜ@u@s2ƫ s΁і7\{(HH5Do^W  ggɁA Lwo y#H0􏦦ߚޥs]Dbaml̵ZlI7uN+PYY|ռ&5yP1ew%T CVՙqb\>qR0H.4aXEԙ'dZŵZGo G/uT$gVq Ǟ~03Z9*|O*FO t{(|_00sMoٖJfc~T__${|XQ89>' I܃ν3[k%ʪqi-,G_7`xo[u3BOF<(; hL-gJI[G c(M 4a ^5F4ik%KZ$yA,hC+2v (cS{E8 ?D1E&iwºdVףcD9}>Vl)@@Y&5~@1K4kr}Uc%2h EZH"3? ܨ%jdiۯruc{P,[C˭ |a MAyjFˑs2M6g'>'󩋁 A:`uO-M)ՙq:)yBfdAmIX| lf@Y1ذT]ڨZX|X+_ ŭ]$C3U{zx6UW |&fKvƒ;mÁj6JՓ"uDZiL Ғ2:|XNVJX|i$l$f8n=_#zvC,Ҡm֩r;[b-L'Zd r _sH^1 kj68rvRy'vg)ŵjPjK4S~68m9o.hpqq]rZO\-˘e` MP cEzE n$ƌcV?]Vh7*yFEOqq+g+bwE_\Dt`r^") _U5u-ܻmZݹW;*o[E s4%G,g?E4)j*:&$8<ņ[9[ҁˁ-J@&/ S32oO [9۠D>8>s󡵡OTaTYPkMܧK yhۥeؐ|<Xyt4Hscl$l+<q1蒦zM^1`!!}k5NV 47ob" ydMx]1^ n.eOHNdbؠ0L:ACg8:8LhRmR_br/[%Ւwʗ"`Z(I) _؝SPEpvrDPOH#%!Dl؂+:&0Zp >f-󺑔oek8 AJ` {q+gXˬ~p k,/u$h0M{|RS:oN[mʊ @B,MXeI&)OwFl/[ C'r⤦JEz0#N\NVx&M 0jr $iZ@Qҙv2aCI-v%d}p8eԩڧ&>M*gtltM| zE){6U`ƌf1Ӡ I>w^+'̸-҈}pgZXBM0p9O]Җn/>rzmM+(?%k%w`Cm#3f,)pSh(0K9*G&FyVtL `(sđjoʢS`e?WLGmJ54h_ԑA%a6v'`BiS۽4aw)d1 oKxxy3hVH }ƴytQ# ԯX1h&KkWE?0^z9rf8JY;| w7W"CrݐZ$H KuN-:xt6!_)=0sT :LK|ΣiOh%]| a4oIR84_?RvʖݸKQ?,(W;`U[*gתhR84_-A-bw01-%Kr#7 \9hQ؜ 4nVDl91+oto쉕% !|-@%v&B>B[DrP[Wr`O@~) I8ĤQ]: O-QS/  "߁lwYrqTk$ ]׃i4@Cc+^ZK^ . xyBj$R;CRfnXm~QaX+ylGDrzoùՉ0 (%dI0^pU4QӚm6ҠP2.|aS7P'iUB4DHXCLΫ<\eEu{$|CP2$'vhWiSX0-](,I^){iJ& NCOkڬZ-Kɗܠuu7)_%cY*Wסt݁5kC£FbईD]#1OK$;I1^CRisb9NȴUr;\V #76bH"1[fq/OLa4Yx aC;MqivlWQ^Q DmQ^\(D~[_kgpfHMs"Ne#, @_\Jz~?[s+;*;yב:jGe:T}45h`;=s(;@O Z>?fw=̰[,Z|GVfṙk8+,-4 : Y'O{<6 )1;>5p\Ixya[Fw74ӝhc ˠ~t)^eUWfLG<{{ \~a=u @hR'FG,TѿdN]og`kq8},6{֠ 'fω4yj2e'/ڨ[97nlMZdqJڣeD 8:Ġ6Pr 1pt֧0H{H,N[9;2UA.Lėi$1A'l+d(rlxrN!a]᧳v'YMeP2N[Z8y}`L=YqHRP^-\|%|jב*\HhcPH ]]3䘤kjOf>xKsܕ,@`P5QX'8Nf(\(XϞ澂FDXւ1<8V'B5)uF86XguN_H#8}_}qmm[;՛]9|:h,S~?yйɔ67r~v}OK`F]>>dO>}6;Б)QaJicnVBd#;nlcZdqbZd1-j+ i@gXOkiDZdq";4>OYOGZ f|~n6K;-5m!Dp &&3VZv09/JQ L4 =H!a @ϓ$#Nф;)b.A;_M[Jǽ&g>1d7Gc^ =>SČfgJ=BsZMl|ޞե3 T^нt3f<#3`Ui 1cu P"7l66|X!k:(7{e ۨM^-Ik%wsSmnChs4ˇ`$"nq0~O\SO3ba AS.'pIov .WOXJbP~Q `q PZ Z+GF0~BXkم:w53llgp:wd߷@^5~ Źb`.,KZbC~2A0NpqTPmt5xl.^̳r-Ÿ.Z|3uv?>Y!Li;F b6*raZh|贔T+3/ iʹ-I^0QYʖP-Z湡tuD:u.r﨩"?яϟ*֮!qRcAc]1< upt,D>xe!bv6J䑨1<:O8MDIHm׬_&W|Az_cTkI&i2cMms-)',%qlYRL'zfs;&M~X~&^SWgG\X4P1д[~+MI5_A>(T^*CKj6"k.2{wxA#b_hDlKoL[] # 9 0%_@ǟ3P9[[Nԓhk*Qs篱uRóSO'jAvDF{Iµ5lDb:&ujv;PC;PSJLCq.Hӣ(g@jߐjCyrPZAxc#9)w"XCŸbBa'CN>nɃ(2fDn,N0Кb rq;z~m"[wY@C9k#Q~9hlhčk%WwW(D:].\ 2ՓHF=I3{LƬCahmηS4N!0 [R3)<#Ith +2C7V~x0mZy3wÐܦib}ZքhsȩƭzН3!ɡW$yA; dXz_>0M$oȯ?ߥK"uw9f59SѡD:,vR;Po>9/j伨ts[*ѷ3)|$/#_d)7,e(`V{ RZ]RX \&dgU}.yּn!]eN۷[?v;wFھ&}T6GEq#_;|'rSJZWqk~-gl֙ wYE0d@on#IW'.rO;&]_.T uyMlm֚yDZX&L6V]B2j# D& Áj]9OnY'!EgVemV'GKKW&VtϝuT>6{"WϊʧI4c~9s(dB3[2@\ w!ܩl`4]1}(E&,My=!L΋PFtK;\1Y}` ~ђpR|W e*fY7YLB 6?\ X`%WTЩp2ȁ^psF~dq09/*vUv%hWG`בtJ0fwr 8,% @s r2;{H2kGtOo>1+s26nH[w*'˨f%K4O΋R5.1rp԰4ch,7f_țxK&ژof@ђd9,wAtB7c2Y('$:lW! Ocn#A+W4W0$N!(| Ix);P[/kYHސwn ȗƧ߯M#_!&~JQI[~0fI[6o,nM+*ב) _Zxs٫8{|SQ@0M,A%sj䗎&g!D/:ݪ?zT%lV^1LȬDaΒ:XS3a2B+\ sC ¨p-yjc8PJ jyܚC^[ 0?xCiǬg-hjT4,8Ν?;wcLL&1=4yiMܾ1pR;Eb`?%yyyb=ӹ{pJ?LRK]W{ T[jXi7q&LV?=_19RK *:&w}?ؾ؞ g* _ホFvTX|i:S }ܠD>T=P%l\}&n&ZB k!\ݫ,jcJgRmT[{?̵G'ZDom`圶1E gqSB}cxrgg*W((*3UPT>jd9rZ@u󢬒O4Eؤɧ2c-EcnjKQ1!dM()B9jK@iEu}c9}u,^4-`!P)lDy;\xAkgOuXY$?o9,MudV yFgGH[9۬l{@þ\T=K>˟0L JV,cjKi-sxm>v_D HR34T=kQ+Q.L auf慡qX>sBk7cUmN0U[KÓ1†8;kJ!G2Yژg5[l}9{Mc:pstqXyBA{_t ' 3tw:?aXLM̗-k=VKUG }Nxm OwShK@iI/&U$JH^ppJjF%37/Ա` >B^8ݿ(.&'bgv|d̸K-u$ K"9<)9iZ[*ӨNT9LmRa=8uU{~74dG1Yr(y<+ ^4Ou!gO{nV.KH;B~xT&R)rҁsJ6'zY@_4rI 0C 5Iۋ͑/ z%l-a&oҴ#5N /zZB z*צ5R@_,N ?k0q) _m.Sve| hDs{GfWbIm"^&Q1i*|xmkk &`|f zNb-%J-e9?n>`Bt(JS|OÝۣDy(R(&,M\H,MVf=r`dҋ摻$#tȱ%8u/fuz!ٙT$H?s#Jq竚2QVg1xzy|h|w52"%eo.钂V|Z\*}f݉L;Y|:"/-bm]@+#UBbI-iZÐ>_'}@%eR57USu )KS:+-p`YDn"o\t M01گ 3acK^9}Ɛ/(e9pvh~0qtrFE)*:&\ۂme^HJnDQ!ƭnJn=*͊X|`aϕ}*84'O#xouV3qj _#weD>8=V}f,@-kʨs[ jH]0qNmcmUpu{mtFPז=MTZ S8J-d&|"}p /v}v<7桍PJQUB"V[OZ6[@+Br},K:rkExw`} D^Qi@о+gͤo r,{2D~A'gRMZssKIX_~%ܹ ^^;o&>Cf9Z 7(͛1ǟg7Ep&{#Zw!S"0pU p:wŴw~(_~ʑ/ ϷGC]2ZQ̹:gidG6GLQ3 V, 7< ^u-vjYx^=kӲa" "Ylmz}wT\A* x'C̄&)|R%4 ͳ>6Q˾ hU)nF3Q]wQ 湸{G8a,x}K|k!Z!CQ^T+yq[4Ԣmi8 5 06vbd b1|oj(>9`v֗!8=/2Wعx9YZ-/}oI[`g+z|ѻxݏvblz=n3v33U\Z|iP_TJaӸ{.~ڑx}gϑrJu_oj7):X)r9 IZB>hP9RVG%PЍP9c9Mr&'"J!{ww1;I{)%p\+H/}"4M޾m9NEsm$:2'sm!ĝ ;}ᡨ- 1/rsq!% =zl@L6`DžqN}bs`EYZҥA;\T2ǴW4dM$8nȉrZTV=l "ُ] VCmgR bGս M(s8 { ]2[|..p$@/N>33&=% b̘}޴}9Bcp s|lU4f9f,yU.7m_eofI11;;5،R[ ~}RW߬zl ;b eCNR 0'˒Էr>ߩT$}lT*BWbmjSHb X R"b^P9O&A/u#ICѽ;!@F81'+[ix}Kd[Cwr2e$% 3WI/U!G.z;@//\6m 0 7g4b\$} MX#8˘o@$o0~ B[_i6v2ZBAv3!3 Сw,ܹ[ҿWkN>[N,U$2=(޲NƚE! [[mTI~W&AUJT$"'sey%:^'ѯud}:@c[N-3 IlsƧJ+gVQk٪.l hW)ৢѲة(Py6l  µqwQV>$cպ.şE^^àLjCkf+`xҵN'T\eO.$o8z,MʖB?;րCAgX^u(b2hs-,Y j=ۛ' hjld.u$~P(3w]P\"$K^!IX.Jik8I\6JҀٰh"斲wY/:M ׯ2{^)}d~t]R2XОjsH#5*7A[ 0$yA5{"zc D/@_̑e+"BȄ!׌ev3C}}Ym줖>sJ/dJEYV;P hZqMԤ,WOY>~ɾ^nԶ]8hFY5mw]HakTլ1ٓ({^/VC|@_ ?\B4RX/&"V?sfٮ#뛚Ĵ܊ ^0Ь0Ol ,nYr5?Ƞ5{O$LRLfŪ{kdn^:lvSR b9NX?&\{xr0l_hFHuf\qqcPT\/DE ŵ_Gxu 5d F!ks0@UH8&Q7Nɪ|׀mc04O[J.囟4JtW{0M?!dfAG1[?GfҊ1ܼ0H-2dYU֬ǖ|5~̬yI.@s=Hd2tP:OGQGC&Ki1@ FH@ D)9l/0{Mc:pstqXyv'`s6njۊ) _zMz!~_w&rȟ='RC] `& 7dw-+(R1߄7AZ~tI/-8!\3 %B(>DZ#tQ&g.4+уՁ !I^ ߐN)Ȓ!&ߢE ?xcGkNUg<ȃ ̟v&P{e$/)ֲٖ{r7V}Z)ޱ?{d 1rӥ]0H(I?h#&a#eetJƷ 0iwvrcU,}M1w?D xw~qР*DP.]Dܸ9/aƧ GGxr2ә1=א?ae o>|&_|S5oSHju 굨9Yu6|"7%zT5T5}fQrd+ -2Ü AFM 5x;3 +߱5ÅЩT8Jrɯ3 <1j.ؙ_rָT5~#<{uՕhĭnVRp 0 ݱCBXFh҄&_vCbh8oR)IYkiJs3̍㑰IRk+چHCDNޱ$jT&1rWkz>ߑ(&p#A~+ G__X|suD߿5mDXX}D8O[GL` \:BVez/d712/={m!s_zpD-\NQt;n+cg_ a+[jqX"Sɞt,#ݚjz͠!"Y%6Y)>wnB^MZXbR{Wۣ3TiŲ? j/UIhS9Sjo(eɗ}zS֞n^Ѣs#*\}҉fZ Y/A|x:^ƠNۦ];Aܤ),VV_|3YXOEuh 1ƚ9])e$aYfo:*-rD]CI5-pJ; &eo?po/hshR2FK niQӁlG+ z\'' |ߕmS/# 8m-C =$<-Si=kCv>82}jڿkN[cC=s,vsm򻷐La]jOt+`$KfMuPHm9nVlHZ!ԇ[P*õP +ty"ZUZ$'S=R-$l(mmo]iHzAjR5~*kp^Y--)qoPt-^6n`!=MErL/)$  !wvWE/C2PZ 5]q(r]0䛵$L$F~ghs׌-VHZqBt_:e" ؤKZ], %ϸ7L-:a4a˿o6H 􀳓]:˴e,11px%I'ݾQ\j4̍`O',6F5k [^Ϸr2?}Q^z Y->i !8d `Uџߢ!{}uO?)nz`72n+ԄHabױqǨq":tC!=`k 'V\M` m_zWeeyovR\3vT|7nPi);wa0fg89?#<[w jx  Es9ٚ,f%t {G'gTn`_0n1Tօxb"Iʫ(ի9T]CU(ї/un^Íkcmz=K=EGtE- V"m,]r ڥuptwd'\-lXh^ЎNpwr#%[CQGAUѪ?!ay%chzo<@jC^z֊ך*vxz,dX%KYΐVȤ#a9%4VnxȳqNJ+͍Ɩ F:ށoLmtXT 9auD E3z @χ&M dk󧯉z[n-{hc %͋ߕE#p.:&h銍[(r&Ɔz0z {`H8@izPX^,r[jO8a[{3/E~Rk5!`]YƬXkd/0^0͚+Jšf9 |3$l /hNCIo ÖmN* VxֽV4~׀G/ܽŷ{?3G |́E©rqTox::~.fr<0UD[lQW߭yO[;KֵfurqCx|yY7:&m'd+|򥰔ZCjؘ)1r̿k l8Ѧ14v>qՕvbCc_VyKVŗ4-~ےd*˘eR1n}b!C^*IF¶BmҴܵ o V O iQǶ%HXP> D>9޺SvlMȡ?E~N(鉜IfH1C X2/?HCߐii/-/?8e 1l:s~O5dlKpr_j!Z 4ߓG"y7-%P45:2Z cĬ onfePUkj}\f8{UuՕpqt*r "uM[@%dT+% bǭh”:DkD0*iZ@˔@JE F 2f|"7Rٕ%l+$5ﳚ.a%v]lNI⃅{Q{#Ƥ9Cp \Gjtu˴ص8~{!m֪6vnTxzU A0ƌodu4*GG9+.ǾHz& Hy'/ݓIE6f JsPV׵7C1{T 1"3WZ$a \f3u#)@lEDŽ\{:Me!glҴMšOC"ܓĥ@39ۛ?t]_ 6H ׌k ҸyHo7#.9C0i]ӭgxE ˌ3{|s³-LyF=!}~qQ'ŵrRkj݌`=>G#Q6cRx&'xuՕik 8t d*PH}%,0 oɓ׀ݜ4-m5~3q-V-lErQ1gFǒsrs (q@%dyH;Tc4X/&T?2z=EJW6a& x{߷U_~-{37Q!I `F{ŵaV6rZ+f0 H549'Q~$Wna!{okKV.I>v]Tb cw吨5b%Ő {ggr^`9j?B ȍVE0|"#  &w?[M䏍RP?DB}:Lb`BLRxE^B߰hSY| % ~f`ǮiE5` 9L ջ7 EL_}R-JCLX6C= x:dj~<[ɝg]C d(/: ǞʼP,$Z)^V y!dI<[ȗ#,:^<)b.z9 O+5%bבk=-9o/֪T*IA2^guDn"; 9, h-EBHx{P=CW Wt{Yc'M<)|m֯wͷVjpoT}ĭkصU@}&TA-AzN`@,% 9dr"0X R3}s__̌K-&ܱ][Sy6J^^-RAa,79r郜ÌY~Y6[5>A ؓKNa^'|G[EaQy?&7/u~t3{⭃{-@@_\@Yg.!;6%#tZlb󤈹jkj_.◼#~ɻRbRUJ7=C9}*`rB}6Hڄ!*{}&@muk?RUhu&7?IYE'f2AW\5:Nǭsj@Z#/={ KHM7若L6!ak,[ זhc0%/·ĭ̄E!y=%orW4msq=y luz/ۺCtJ ,@-Ckhz Sfg5`|`US2$&Q⋏WnF&GLLxfj.*!f^ @ klKwۍnj~{n &f0rro?؏y^mcu8 O>JYd g!q5{_MK=)OEM|;/kϠgɟEgk8^YWn&,ffpHY,14 DqFwk5f,E{+O7'5K}-6MO?+G:VV :Ԩl:f_W|ixlc2? sW0"b(ٓ-S'vͲY*c&y0‰V Kk, ezVh |mz^f:L1$8"EO2(M9 e //GCML oYa}V;A6T`k}"7^$,EBrsZ&R5~yLB}c]OcI 0=h^_ڴlY횆*9LТV DȯJBcf7Nj~=ɟ˯u().DgkS竲YLf払 傿.sǴNj.4 W77& ~z֋2%OzoV[[!q.A9&(1Z@@G j4N}>Y+ǫ/}TQXOQcj05io]"a#X6 ?.I/Cɿ缁<6RuX3|'÷x.ƄY@PX'G 1?Ő\($`!D4}$xSۃ; P^Q;vΘJӆ%`_P/^|#ƐI@.sysL!.\,k;yd ?[~$ ?[#HJ=:>y&:aD`;Lg Ia[E2.׀tU N1[:ྟ 9uZ~A=夰<-8wڷE0+ˆQWWm^ȁ߯'r<)iZo¶P|[qOƭ?dxL_ќ>xGϷKiRr-% Eڪ*F I^8u_`[K=Y)"s*'~ cK:_ROZ/ROZ CeơEn"@??F[.YX̙͌v LMdhbhg/sY!!xər ĥ?9( WpE ם2VaGl=-gwi!`W Am.*q o ꄆз|oױ mT12K6xUVCk(9hF+p{or`''x?/ϚQ/& a3„YWu&()^`yoܸٶJhJІ`+T?=%+TzvjC !En2@B9t8.qy̺_Je߷eeEG$[d-?*׋Oå70iUm/i#PS{3W_iԜ8 ]QL4Wק o/uhB5~b}^ =VE۔B>U`iӳ"',vD,#䓱',lxu -M޽y9fiɘehR%$ǖxb{~)d0+TbD3}zou\3# &,og#Ք ^լq|_5oh|5CۃrL/`j~q4;0Q{rXDķM0hۘ"`@M0GpL6WA@ӿiLǖ]^ c+bgA_2ag  >_x+Ev_c:ag9!9Lv179LK˰ Hl%Ņ{elZ)]p;viHC@hӾ#OŽwP|]!w+ܼA9Bfk$,frY OBU8"aΘqBkZ. L2 P ;'nFѻ;IؿU`:Ike84D/؁ĞÒ)DL`(.1%h}sױ)6al-Db!DBp2OɸW#5Z0+m2bdD7B\羾}Ғ<΂K!FF>ݛz$B:S{e^(M~ϐJ~M:KI,5QLen  :^C呎a M(%Į\ k=^%g"Uy7i&Zj9YY,)+c+X %Ņ2wo@Iq!֦l3Q\Ȗ)/@aL}bnDbbK3Q 9 R$k&o-GѭFt NC|9dDFe ι`qWͯ+}8וP(oX S`UUl6A[I23˓3 *F4 ;{#wj~A9SaqWd(LkCltU޽ZbbC7dKJұ92*g0+ǀ(Tq! `؅S&xpXRĉ,"Xw{A;|>qr|%Hy2Ǫy@@r)_HT]%h=FEMueĺ!҃qkV7PTì*(^6zpvd lWR?rc_W7 Waj~7͗lKrQUBHT: h059}IovRyEot8^q*v9qL`yYnB-;5"w|k.*% څ|+;<Kue2Š?K2aq)-䋩= f:v2Ӈ8:ۑʇuAXRlLC<Dl.ĈO/-Sj,Oi),&?i'2 <$ XCg:*p\xͩ- c}$s![޸\KaL;lY{m["Rմh%cL'WH7G!ג &gsAN̯ Қp3ލr edqkwLXF9Q(3$iˍ=ֆbфI1,'Pr{]A S y !P Qް^0]Ǟ g/& Ȓ+rR31P㗪pmhv?< p!VnVd&`#z,`N{0t@o'z?E'mp*Ž!*&L[3 Q`i2YKmybEP? ߊ-c{;|2W҄[yy>b?~6DM:OudO9 ڗ@$ 'otz(tK#SSlS˟5#k}-'oI6w(#d˧{b?$Oho*0bD"\93Oep<I3}TPTJf,W#5[D΂^?Ê0)bn),+1tבf&EͽMe\ڗN;7oב=6,l5~86ӹTҁ'{|%Qc15<`6 ZM n8vU<ܮC '17({p:=邘_NI=b |kER B<3V0=νr8Wg˒S i7n_!߇?e3XXp@g唋D $ ZQ/8}*@_g:O1,u<RZ%N+7ChR_3NbOZf|35~pk}g<" N` GgW0w0EzZFwB'G|Jx Il֒d _*EAmHz-C1Q@.WU5&*Pڬp@(u+MX&r}l1n*ݧrE/]&83`аG07x3SZKǀ1P*䈭Bjn|b2#'yeK5~_kF Y(9Γaq_nſ?q>)WȖy䐹N/pjr˧4a{3Up(@3&R󜋹!deO+5\p]A=#JR*aFsVkrgm,]jon{0zPyѭфtrϭx7-+( j1j >7w74}ZrR~,ݿg" ~zNXO1e|0ݺaХ,N'Μ>u7σAA{yRXoU"l6C'g<WF#.Y&ɘw܁]Lzz &N&I9"Z{,cktxT]%y&_3UբS@]b0{R$,FJah?Bw @he39CZC_S4 aw)(ĤBѕػc+2$?'3]ӗF1+m"6N#fuō&r R]I^D9^ O)%>[wJVH93iF<5Ҥi?#p?O>>I)XH1 1Q}q9^`0j޹d )Z/{0FZvqw^o"kgx ߘNDcMku"?ӷ;__lH0ߣo>8Fjpmrߘ- 9$,=!>  |?p:-̪Ch:CZ.w2#=_B ]{p~.WrtWE!97ҧDd LsUPNA=0#sm#:&M~}-l\15Dٶfqk8y@(qa|y}]FS*ifN0P6+\B7w+wņܾu!_P?E*ES]CZؐ"h^Ƀ EZ~?߰D 9)4嚝=8Z.},Ԧ_Tڣ,gVE>R r~$se/x82Nu[ ]$imwet?Et Fyh4xz0?C8 jU 4&\EUb DH|M|S5ؐOΞE gKܶiY8tj&}+Aci!}_Ѷ];ܾuKPޣ=zzIZX 2Sg9E !%Tj!уkqJ_Rʊ&|s)1!!r*/@~xJ!I z9&G4 YdqʲV 4Y*("_@%HfRZ0'zq? ;(emKYg. C6f_zӞm?ZU{e('=1zPܺSfǚ@g**dϟgñ)Iϯs?q /o-R(R͚#a9+[f2!!byP"#HRg7M^aHV\Ӛ8(󿛂KWön +nK!=A֙ Pxk JA!e9BwY )8&* R+Nȅ Bݮ/%QzLPCܡ ђ9l+Y )%@EI+Jԍ@iá^>p3dZ52cLWw s\s=m_{/FVo_ ,Tiwfb k [3cZgvızF q~9#vl;k㌃xŒI5_fۢ $yrB yy^P/#Uk?@L,Q*{82X|[l*@@_<2I~%r8gFJzAmg>}q]s*XLQ)*=(h/`6h҅9h#a$Ne7I)IZnZ@.D^@~ zR/+X?Τ(q9F7Xi-W>8,nG9cn݇cIgV1•i]G ؎{ù{.ֈ@Vu)8BKɗ;}֚^S]/Xd_~}1hΨuw3>lrX#jzr>S#a-@ܡ}X* eBFˡ.Q4~?aKm&D>~Izl$_e?ܙ#_ NNN8gHBA ^1jcסy r'xyT\ίY KV}%-C#tA`>"AsNu7iƳCl1#,d3M/?qn"CacsCjz\ 4ɸ6!5ul %aE7LCK$\PxI+ +zrv-!XM{k^9i @}1A Ue)5~TT.,VҜX^*e&dJ*("`65~:{b=]  /*pT֮ؔM8LB*P)zr+ϱS!m,G<><*1cG(E!cr:j;::nhll4j_c}]OLd9K,^wµ @f7XhںzZʔd|HVJrS'Ι:e{{8? &jlBmJ텖Nƙ8,Xl?wViV|Ka1 FB Ͻj>o/Ai6c'/ m4GDV6u*Ղ``r-hn՚/9a V ?bżAU HM/ -^3tP0ł%< :~-`^GjܡGM|ub$/PEBVҒ'´HD8aq^hJ`6u{XX5<H-)CCih( VEJ4 h_bJ_%FxI,^wR|O"]ʞ/吵 oHl>(D46wbǤ (F52,3FghW$9P+/Dʢ@dW:C/ DY`c<Ŵi '(pppp-߾=ʔ#$%Ě'\Z WM+σQ.Ұ/4fcu\|+7,| dA}.7;"P=s`(n(j9)b{j]EpI[J:u &dW2_Z6dœCQKCjlywj%`?jTbȶG3FY-|ADäR L>J6cWRjEu[2M*)_(ԈE!]1HhF꼜eEp#zg؜Bkn1f7d++a?ED)~^`^6isXk^{NE@7]~9Z\h+2[h2ljwv8m7 0Y6c6?9/>I9b}89/*pSÒi5_O$,6r_GzX#Rl0MN!fX8 w+Yis|M?}N Bk[zé8thmnEL FL4;! c98"o'tO`[Dèv8=]B-JdwoKUQ;Y3Y{UtF=p/`|ʐߙѪ{(zbL>2fq>WvH我QHzm1٘ݎhR=e~Ʃj1m $y |.}E>Ad0 mowPaKu$22lf Wpjc+hV(5bRƀ 9̙s9~9y<. %-蹁f!Z(R|qO}[Fr"* )ʳhy񛩤͔`s4HXe+sX]?MXE#@"3 |aY ]ÂSF?vX`(L7X~rX~P:SN]ux’r.CJ<zx:oK<|}NL!a5s!?,{I%؇()M!m{5ƶ:Ѝ%ߨl俟5p<͊|\2qO}#k S ˟ `$8O/ @ʧ%-us-З;Z*dx{er JZ>WKS7!x<'\ PkܖxQr ^u3IݎO??.{3 7A($BĤXsx㥸VeXFJ^W7:}sGxƢhocέQb&L$tW{J*IXLIJ= 6kѯOH\WؼpT/3)y{ AKI7VH>ǥyP 6SfDOLJdv;Iϭ*3G m^~(K%*(>jho/7+. G})(UhǗ0T]{"M-C?e[?=&y| ?hj&Y%hy<|P3H͙CR/ݨH/Wd3m5)v\l=#J IMX+Z$j\C}[dO7S&A'3o@Sq\31pB!A\<\֋7~ jW\_Πb&9vj|,l&Aa](B?n$|:3*7ci3"zϵX,KT?@b$ȗcHNc܍ؿgΜ9}DB*JP^  f:sS p?QrG-rq˿:t~eX$,qEfS̿|N'w1{iHmQ|qO}> $ʾP^0GCho@[rh) j.2ҾGjee6[U5;K6Ce% i?P i/S}TzwBݣbV ;t&oOe} #jHޗ\ ɔBwp ga9ZfCӛq{9ruWe,v(~RhM #߳sL9:_ǣla-\6zRdn~yM1]UJsrM|fgyBUay]&B|cwn%,_q',q$>8.UYr6$G?/?cep xzҝ ySj02$Lj !|idȖigВ{ͻM+ !b7>GA{;ȩ. 50%M:Y E!_%DPn0suzÏc=KR1F, 32%`G_\yCF7Vy&h~ >! nWxYp)~Wh(̰ R̹M·q ]%[M_ቩ,:j<`P`=K#h`2z LR/{A{G.mj`=%)*ME>([Q%=K|XҸ9طMзqޛ/5=ˉ ~M]>A!-G7˔nu>>'9Yx&9UOr' FcW@0~s'dXX!Jvۆyf97GVs3OT9PdBQ>l+o"|gO"uLTS4QTS۸HQUYbrA}+ %oJaF;rޱu.eP1ԈƺvrvP5O_lkz\e]kՕlL,Zҥ"> eܹ&-ȗMynb9m2j ;uޠ 5*JO ,g-g0~8~w7$G vuḅ8EbR,`_W^_Pu ( Mf;dAM`nXYL6H7'wbgrdHWRI8@FE>Ċ2yQѷq= $}cb0>_wK\׃rQw\3$3d 6$Gg4ՂjTQV"$. z3o6dBl0%$)*_ ev|7c0m5  |\]8| u$a}hKw 7w7VfG:?^nv sq>Tu<X}d&ϦLR!>e*.\DԊ&C[pDODw11 AXL)Jk;ƱnJ[AJk7(~bӦ|",4m]]@%a8|\V =.bv:,ʶ )LJ/!kf7;::Qu*Ovz**?W} n7^ﴮH* K)JdPL||Yq73#G9X< pkE|K@K\7@v0D{nR^0իh]akX0իHU7+{Nߟ{Y2oC9|7{ PVȴ#~k W}pKCvKũ ublsb:.4'5=!:eպFԘ,L$pŕkl 󳪭̄\s1Ja 8.\|m?-˪m~w)V0& /A VvcQVb u%a tX뚡&րF_fAuypS_/`ܳLF)Lxw79S>_E51K/KSo6BL?[ N_@W EBpvj7b$ Z0+ @=cO$هgn*a`o`s.BBpՌfZ|oeQЎ@:Vuft~q&39K [m?piNi&GD4'5YƏv|gcp`S?S7F~vsQ0~>(^ ҈QC{T1(OΡkp7 D@zTW ,X%~H5ݍI4 >h+ l/4T#I&dA)\9ro]%/\cH3|g_|N>~gG.x!\O'UlB˵d9yY, +iuT.oiNeg8(jƶ@1Ʋn桴GU4'5)gdKmd2%N0I\9Rx! ̵ V) YJHZّ{~LvC3~Tm8ワ}(g3yżg7VF0 ˴"2˝̍URt>0z|xPuäH.r&,ƥjІtQ0h JC.8C Jڟ/k]t_3Ĉv]a3% +6A烉F` ygy30A@~ 5WŃw _}ϚIx?o"_R$C[*1ctd *]D2sC{s_-mr?&] ֖ 2`87 ^ZPx%$i^fRALu)B)@ !;>Y^F1_ *df4ş6t;&]i6嚝+ Z 23c:^`-)yB>῿Q^u堵Δ{/BH2ArHX,} }/cX`g/lMx~4P$h4 s]L.):8xX| eRd|A:`JD+֫?c GĨ~+x{z*8(>9Wii|ə%_1)d$aY|.V<͊h%_>v:lIJ4,i?:p4N~^@!q X!춗'^{Y#QՂC̊/3We0V70R^)w{\[;77gsy;[.>|$BV1[`ـ;p.X^ #Y|d[]FMᦄ$4'U>llsr,5ecu`:_m3Mm i6E3ZCk ZSi^ HGAfg5K\{^v]occ܄?bO  &;J*U$rG<5 Ckbcx5*/, MSh$\l{ K^16,'Z2 |eQ S&FU4&8d1bήggߵ&R_ eK|NVwZ=g-c&nE >jsY⨯ı"u;#us _^ceQ+j_We3r=12:bQcF"jHD %#8@>os`Lϛ>ORƊǶac0z >$.!!V)1#HmۑZ+s|-Vފġ#Q{& A dQN n S'17>^Oԇ#Ѡ|P N&񌅄hT%%&o~U)h =7춘Lcb4h11Ti4Tn{ CJ6tT&R0|@e%N`o?ZYG|sȢ b:]qNc;[MX¥+fD,{&``aۛ+/vV-NPH J R&%g̓{~ 7p%A.:ŏm(<֎:wFu/xcGMxi/4RH7n3ȝ37i޴tʵe -o 5pRhooc儕v!'OwV&g4!8g,Nn1|T4T,4T TF5q 9$.HÓ$,D%Afr f^ɱ\cG Ҝ԰9SR Q%a=t"D=o#~rL}|I-H$Km ]7;6w Ei;n`>mfIB7ZQcd: 4j#b#ICX==>^Vc"_AOIdssg˸dIkcZJ^KR7on/}UYHcZflt(;m~z%X0'tyufԥmX|>^woNěR6H0ypok]̑;}Cj/ \ϴnd} Z[:Ь| Q*`LϤ 3L:W |ema)#F"AYf6TIhjMm Y /M:KH*T Mg:e商jٵ\ORR$:'rIX 6+ z턝Vwq>=t8lS&FoUj>w|,Rp4|cwڪ f!5_%&-.=و>h.H* }׽V mjf gkhD{+W/uj{x_%N|vMY;#wÞNQ :P{}j4WwBvJ^1O3᠁Pvؿ6[(ԉGax(lgF0 ZXiNm&Lj\ָi1MLK@ɱ?53&s5YVf.C9kײ%4_Haw _Έ&r73ΒÇ4p<w/\7$ H5mvp KMаIJw p}m Z[:pJ=y5Em%97:߷ֶW;#q|_;/;SAa)vR^oa16|C?E=۳%3խt!3#hb,ݑrD( B"I!kV[>=0BGGt،c(rFR ?S⥞<֦0UPa*GNn9Zpp((˜To (m| hh<`!q@A@{y$9]'@B)|Bh2՝eWd{)M ozdc7ٙ4?G œz`wғ>9ϑ˱+VJ+;J \r,bbaHŮ#ww k57Pv䘛Ή$ 3ᮘ|9)?䧃;'Iӣ[g'w!DMz q6y ǍF"_y0vD8+P]fN!L">A΋>h壝c&3Ds^l5+bV=?fJNTw=jIJ xmܟX53`ᤇLГxb HnՂJM\.Cun|Ƀ~ϭP͛vDeA伷b$lp2.]//EZt`Gcs3nc'K.T$LokkL"iS=ez8^V@ ,9ծ|?܀n6Ž$ \RYm+%`!!_)LŸm*Yl8 :Na)| RKuc鉀.yg? ό {Dpo78@V4^ʽ`jDBY$ #\KZ1͚ (GΖҵG%}p;Etjn&e҂,9ZvsHS,Jnf@^q=P]uQ&u L_J?`Ks bLRc4D a X; ~i/p2*֭Ҏn>Ɯ}3kbcTت&r\ Xȝ*Ew d}ٌ1s'ruQfP](/XI7H8!3Oej>0$IF7gkYŐK͌^#$l/4=P(|I"0o~MJO,ԎP mػ8AMz"aIӷWI6z+ӸdYzk|$]DR<x MJ|竑~DX$iL:$-I#_8zMaú@E[WzkjjwvE,s@m@Ft%爐QY ˑ}"]._ V< 6Cɹ"cX%q}"{V[G6z.䐯pIXc`CÇKBCH}] *Q|`\79vDW;*~!{ҜT @G=΀1/)u _JK"T?~B2 B^+4=;vO]١<&( 鰭ai,l2wBzj{G&[ KaPqTfmt)\ :BgUGwBm%FT2ԓR5"L2rg&g ѓ[gvqgGș?QuöM -VnqEXG?4_'$@ƨqxm^ߴdg\O|)ॼth{/%c3^f [q(mT/ϻy]yPy8wD^BԪ3ҡ'!ZM"aC€_਷l3d@~"ŕ0ߋeyp=f4_s#i'Nmdǝa!, 8%fuHm׋Rsd#`v}VΖgx u]LRo5ik<>|gpTh'VH0BP^Dr,ZmG &Rt[(16IHym |C0.l\5 ,PxxU*ػؘЇߘdžE J%N`ԅ H6΀5Mr<@|VS*[֛w| ^<Y#ܵZx uz 1 @sE3J|G:rf"_r-I*_Fqt܂1;fELB !摋06Kvčؗ\лo(z{׎x#lS&D̐b82FG uwG{494Tȷs6X9Eg|?dOpn5_K2uk 5Tfʮt1eݍh)瘣e f׈?p:aEv{ghU%v-Zg.ۓ%aq>o#`Yc"Yg9Iy Y$Y4sSԖ_G1/d5FҺj/{89\{'@J*<^66 |Y^gW叨z:/yM='1iIZR}{g&RH?.kxͅ:N|b[m(#_V*S|ҜtR8%FQi9IDsJZýwڣ@9;::= ߳Kt^C]=W,\Rm.ë=/Im{XVeLm|C*CSSf(JO%V_/zMkf4Ԭ>OCq܂rq9] ,caF. Z, x^ '^ C_r5f$ok>-m~!1X ynY͓e(1e` 3e p uM1g ނ2,:RDﱢsHMr3/$ o*\MzY}KvԴ'%f_~̎xybM?[)~BGXepWL!VX9dR}Yo2h$[Wiz ea!ݴ"ǰ .Z#_J͊p_CH/ew2(Ql,"4|BtOI.ym/h9p!'ʝJd!_f=6+B@ط蜛 i fAz^16kkٗۀP˜d\.Ͷ b1r[w)1MXi"/gs-hIz?p6@ME?VrUlӄ_R (Ye. t\)b4'U3gBJ| /55a.߳6W|GBn"_EאC^nsΚ;>K)9fB?u鱎\Klj|e^\^wk'UYQ|Dko R53{+י_ovu3:-7Һ h"GM6F.=†tW}O\bzE垳pFpL#_jhB24a{PB?QT*`,08fS|}p[|#&?(q2/W7E1(vCEfe]S!NGjŽ{oe71iJj/.S|޲&ޕtjqƌaa>be/u⇿< !o4r^MIhRNj/hBK<1$.hR .cTU-|W _?K)Nw 6*3fѧh5ZsV>->:k]^w:<}"{n)rpp?|T`3΅"GK⽷0w/ȶ[P7_]x+K\ЈA]?*K;0W''MPLt4 &LJWlh+ "a ˕.GLV:$l rw<+ #ɷ]U1.%ɗ^QY$&'͵l*cЍ-ױW#_X`o#)ǍN.;(d*W #Lbnp+SsgY_4]hIIU<\7DDVQ() n{ lkpXx`hdMMX C₌J]= K폮LΊpͰMF+ekLmgfwu'|?t6>%_;%.ȗ /;%xn)=쎡8M'A9d䊞8oei`FDzh35"_NEr:O|h ʹlA.2cw[&B·2Ir9aP/wq_?N+eΏr_1Ip3 K]49[fIVPS- `ːV\PVQaͺ0פ,xL!eϽ$LD Uc,haWNQ͔| H+re+lb4j> ㅳF𑰯+>y4:F0C}.|%PKvXop Wk,E ѣ D t sR$~əI5'~w]v|Il,/L.yQT»z;_-j-kW(JNŸiS2Oq8qӔՊ 8zfʈ0QP"ٞ<^[g|.1rȗ=,m@V|قTKs6^P? ٨r;n QcF"jH|^zk.f uི쩶\.xv9Gj(DV<>rrώ=3of`T/k!Ù"a|^ #C4<˂$aT8Gȷ`F'ᙿɭpjjiB?409'NidEqT4|0`۸pUP* ;EEGF2V{gv{|k/ Y| "aH#fڄtXGrǁn|O YdZ T2f ѣ5 C`$6[gI0GvV RvҜ ;uYNB –[zzz<"[Mk5Șm 1 6L֘`4aUt/./fR{mv/ߊ98;uѰΩt>#:hG?KQ`dRA|"wԄkӃ}uΐotP9 e^'O8n6)?jCR]'C?N Ra >N !~3Y;~N/Ύ$L;yk'D3AԎ"9QpXfʤlVh/!ĺtcTG~>`ّkʨ=0WAks|S큹΍?5ɓ0o DlL=;4Ed҂;v[~Ղv& ڬ+@  c:bG s4nQfJu3?bnr?^uނ^Vv3}mnx3Z:N 5"9oYzt,E.I5: & zSN"\p҂^y;A1fR~qv hTѶ`9QfsV h.N[-zC o03UUں k&ݯh+ՎsXL5WSDME \-W 5ȗROd4`J͛ -SX@::;!:eFC;&L$5v$D>p^NlJƭG0MG{ X,֔-z]aN3fr-D̥9;EJɗ9GgV  Ur$a74Tj0 s!qAI|)sMŘ'Е)Pc/\-V>t}XO$$,ޠ`E^!_> ><ځ=wkUs|I,iq8f ֦s0-PT&R!ps #} )CLw@~qv=cF*S#D0r; @5t 3D}P P9& z 797eŒ˃BZm y= r=Pu`j+9+z>w>|^C'Ko >=!8Ю}ml=Nٵ'S)rr7 |nxeѮja#9eNײ.}zAϐoŕkR69|Q $Dآ6^CA-ͅM$_? V8U& $2Y,7Wѯzk=559}-yU%fRMn)=ʬ E<2@~Ґ/XPQ*3-#+4S3 d=l㴯Yc}%7_ XWLJZ+s`!P~VRgGs$D>yFGM%`!FHtXzvPJn59zTu15rH'9wW #SzxfB!F嘚a9:OYcE\mSHC%/Ŀ`Iu>*X`oP?~pO ͨ|xfx5uv(1ҟƢ"#J?^ $fon`qW \7ېٕf +9)l)V^6M|-jOGEwg 2H"6+I9j_DhثS1s7SrQ~\eE(j?$ 5f$.+9Vs7_{6x"|eߡs5IsĬ+$XmSJC%Hxr&ily mM7 d&K6͘},d6#YsYrrEU&Ӄs2G3AW4҈q|2oa9b+!@|ZwQS<PܓhCQ|BfT/#G2譵2p+/c!+dk섉g|2DɁ^z=aj @ȗ֣׳ 🾆]OrH;aBEPj]2%JCdWto^XY qoHI?1H-e]\?5Cf5}|mt;߻%?9я Gl4SD z6i̔#SjԄ3IRA>]c&&yS\lx/&3G pzB` #t N MWb%g|o4|&zO{WވZƖ|veow#*"}cyh$(doYts|zZ)e+ׂ5_;i_@*VJ54Sv.9;zqvdFN˶fik$,mӄrv s1t)M"bH/`ф?ɁY4fffQ=?V$96nUwZ=+Y RVT[b/6crqao@o_imohdO|FkŐoܮeWя>ڷ?KLBb6B$% |z)w씻庻fS" g/$;.XXRVdK9wg%D>4a.ht "_.039bȣƌҜTy6c;+拚00.qֽjNo :ìy%tj ]ɓ1.q(L/xwZWsK `|v6G{vǻ@mwes]I 跾XS"!oG>p4a#T҄9TzCC&V3!ZW"IB5"ښpfr" ғ2^~ =H3ӛZEss pT;\AL3 /]}Ŷ?^ŜiΌl-;!XFLF\nEǻ @3>\nj 7ʮ(.Ss\oRvh s:_L>1555KaTuͥ |zѩ R'ii"yH T d\HR҄ +( *Y0G# АAh)fLR3ڰ7Ny&]iE1>JpL x@w=ns wSyvEWMaՊ?2WW2!%ts]r8+ f76RN+V߾ƛlͅI KW# J9*L /&2O K

-:gak^=D=+z~ˤfǔ^>96+z>sjZv W:JY8ު);}&$aNAu:MqKY'Մ5` {9"ak$.K 0aKt" 6&k&D/Ξ)e&!'LXC70i%`{3+Tj{kqiDM`%XՂiyZ|p nV8zɱvd/;"Iͻ%Z2Zb}ySK_prKX%/}‰*\6O`!)!#2m~qv# $l4d7$NN(smHHd?,oD}3H˙iiN~M _7 ,FYɱrrު$_Gbg|%egc6߼~|w g0(_+ `+?TY|nl HEAsR2p :!:E&8[? ">ᝊÃl9r* &@ tig:X]b;萄Xr j&фq2װAM,&;C1KsRYwS~qvCǽQT,OXtĘ8FBE{ $ XM a\nF ﶁS:ߵhDp3KE!Z +m"PR'~.h&Ef-5="Æ)i)Kk24o/^pVo`^@t0VS{: !_8~4M;\ݐkikClrJ ɷ¾3DOip|݆JC ;]t03$.hIgN2JY`~:,˜GF:2NJ5s!@N'_$\@TċxRpqZ;G|Rs=;ҁow/K|``(ﯳI839Gi8{8wC՟TK@Gz`uY!µcp~9_A}zµυE97PښwDzŽk,DAB`o|W=SJH֪ܳü5@RtFNH\[ ۂ$!!5PBj, s!5o`*JJxʴ =W 3{$E%a>~vxϸ{@f}Oca~}0h@? @~qWY>21`qǼKEǫPt g(j1[o(jth貂ѽ Nx$BݣH∬h+1ZZGWu@Sy1CqĹ e[c&֟Z]=`]|@5flS.\N^k3`S Zyv}R/Қ֞k=gnj-iqUre/-1 !@{q+"BmiCE gNqs9"d&gB|LXHB)CrwgHe~7;K M?՛ktkA|2rѿK=W@׵=;4ܗ_pPϚ#3.bv9ZP*αVF4XJ&,. uJ|EM{-g. w[_%_@\õW-./F>cV <ǐ/_1ͭBW[N!yż"k͎R[jzb;UF I/Ŀa`UATZQ\,iqevZbʒMB* ե!qJCu):4Di>_+_Neu8@DLG+JքG̀Ԙ1!s}Rk]C<1A "39f$n/^aZ)фȗ1?o9M>}1ך]r/~,H|XO׵)&/Ǖ SXj"fʶ<|A( ~Y&*IĘf#e%P5nd^[Y|pkƿ(A[,}sZr5=YNDԄ%- eNpH,Y j!`Af O/R3L^m%I\I1m{uEh"fS+Qb hR|y__+GC$Xz\ƩRM5;1z@m?Ӷ,x?' __GS{aELKkb8W̚:@|M^(.bvg| 1{ jDhe깆I׿ЙJ[ KwAS5X$ q'8|cڐ7r"9]WD2Ū>g<Xga#^=9FHDy{A15uELfڍ"#Q(WVJpu74ࢹGǀ  O%6-U|"&-bBrR-5dt]iy\ltqsޘ"fEU 7'w#‡݁YtZm BFĿl䜊2_ a% I^:|wƮO#' 芚f'jڞYv# =;6Li<<8cʴG1M? 9MO+헇|x$I(%_uyW5W5‚M‚on]~. -d#X$>x]lE!>j IDRf Wh׮^ gJ5 0cv3#AދDsdiC=3wʶF55VC76=ß?ȂK3|K>vE`6YGQ:D1H,%E;}6YXv]Q 8?l{}\2:|ho"P(CE[߽srS؋iim'\Pwf h˷K\ S)n߬`>] EEM܀9ILttfrCJPqeZeOhĸٲyIP(Ԅx'}}<D3mV=GH~GCݣ _̹QuJ3!$p$ e[5 =r 5*}c;h=+=0H42pfk[NUjc4g[$/nG>2T UR[mKWˀք+s̆3߽slbsdDGۮ͒Mx1i^5K ȗH: ?P4xNSE:bTi٥y24(dQTy2$,FbBݣx4yCʌ] ʶr 1Ql}R Q$DM&߽tPC҈kxlI>S4.U9@He,|MS;|aY\DM0_s'@/v4mGl|{ֵtgOGssV/O7T+,nH_$7OxqdlM{McaF?ջ4C'bb]A7K䴝wniL ɔItpq)9byE 뉃Id\kA0B|_#IlU^8)Qs^:zUAo/CyɆPpަlіG-wS_@HmQpr hgԂ:A']"֛13ȷ :*($aE:*_.QD:(jʴG9)}1#S[ -l)8{wH%9jQz?Ñ)ϱhp[k\{n`I$pLk^vݢYZiBX>UjHBx%ErR$lekCV Ml)Jt$%9+-$\1Aix5ߞgoqW,ZXpblh9k|K\=]Yt.DN/-eq?MvC>; 7|S5[ @XWL-e/IL΢QܚiA4'U&,:3m5E̶ފ4or* 9d d~H}C+$t^ L|Xc593@?J:GLўħ) hؚ=5}.cMd`VBDz34_| 9|Zimf#Vۙ/*Oo,yz'Y:pBrP{~!r I%`Kkl0ǹ'.MINȈ/2\M?@?[xL\fEthͱ=MWa;F.SEZ5mJYn4 |fOX,k3њL=s@AL]QEd=Hq>39m!ߜ ׮# 5d-hr=jfت4/3҆y. I@ C8z 5p3I^+17B\Grﰙ>bը}qOq-vqG_hӏ1>-o&%`BUN5"0!V^@hOEWP$Km@'O*@FZ(K)+6n \4[(bLAW}b4_9`uѨն؊Y$SPVbK"Fb#Ll,pL˝EALWjPH Œ oN->`.lb y=:iERr  0h`GCw;I¦*"_9 e[@| 6dW>`iZ8:F.McSYg,l*zL7syĚ1=F`zpLmi`Q628 e[@,RH:ԘCw2LsZК4H , ZT6izyjP h8* ձtztɘ6i{[?%ڌCX⚾ܳ#EfrV:r3vZT#=kr+z7G?쨟6A]fhW Zmp45bj@N?`!0w\Pl#.$.H9`R>vHcz"/|ҝ`ާ Vu؋j=,Lnbh~OӷԫّJ l=1|gj} |SI?3HNсK @WVZsfr7iҜ52KHDgY7H$Dk7g;aI@rM JC$\SCq|so`e0&-_R|wU]B2.RSBwӚT} Z)"S~Ocӷԧw~U4C57%PhaH^`Q&(9|")LNQ&5c.ՙYƥ9EbuttLy3Tw"!:/JB/v=!_z+EɐoFHJCu:,!RbҜԤAy1իh bK2Y iBOK^1)o4t?Ť;bhDzoѣHcz tPSS)ca?`UR{bE•jqھJC5Ul1ՔI15%_v?:}KjrygKO깐J 4Mh46 -@hDMA"a\ 2K;DHq@gHLN$L/@Z |e3mAmvAM"kDB{gGCSq (o9rJBԄ~wpBt EiiBtJQ~q6_4 j|.@+s"TG=;̂l,8ny#7/EZ ivRyyᒯw `nHL^ 9nyҞŦKM5}D[Jo*>{~ 2x!@[X3]X ≃.]l3.pcXKK bH87@W"7' NzI!0O8|3HCWl~3SfpJ'DŽ5|B Х(6o&}=19=O͢O/HlYu=E|YAH 97B|$IwBpK//ĿA}TʆlBO976JY:{pyIs|t47JI܂wסB.ݧքyȷ~\tOzb62yy҄AALu9g91(?X\ٚP(퐐>}|||M+rF"_?AnL yplu,ޠK^1OO$ߪA ^z8[Y\"sfwja1zݨce hHg%+BQcFBFDz@glu.j̕`|G9$,V 5 ԻO 쮛AE1;,dbH8?ZM&%-Tw$ss5 TA,>T+6mI]*+K b@GG\]%_@KVYJ J_O] 1ձe˝%VvAmzԹr-2,=Βoh~?%^%DF"KcF76mfₘj .y H{v87}! gLҏ;JpGrgu~d|Ist5TuZ]V0@c?ȭ|&bz4$+@1 S咷bs].Lj\~pOu /nMMX0UəkSA/c{T$\~.βJ*\\Ȓ+.*> |z/adC~y ~jP" [ ɝ/D;ʏbfXun.fkڐ/L%W&eUʘ=?PAOZP̾X8c Y&E¦sUTT/6мohQ&_-i+IT:`oq{H/1}zA0]./t8:#s .77Wz{_ k"_v/\{|ݐ::~<wY헄cxdɁ1<ϴ{@bp 8ۂ|RϜ!KpAw wFG5x%νh+y)1{I@zE-2 EJe^wFKe Wyr)@ _vQV`KB;WֹeW>sЫ35HiuwwA. Y"_@vԲ=1;IN@.]Vb,9|fV^XV0GCp t8oP %UWXww܃2b^>-p .7('̗QpS M>.?ߩR.'>!譵M5#_tPkpVH#d߰]\Xs ձ9nljPz=Nf?>OoV۸V` 'c~ ^bĠhKA]1HYG\ z+l456Đw(hZ78@c;󋳍 7hԴ "˨ܬJX?IMXt )J$Ny soH5M$\mm;,naT?zkKy%0! ׹*h~ s Ca4"~窬nbVU>Z<7ଦ@CQ\C  I#V!M T}i ~e\@jyb?CyܹKsR5eP]Bݣdt!^mȗPq|$oY7(]A·V-+  _~1(,ʫ3(,Z9ӏ)5ԱZ[p[{"ym6!C[G3ƲOKj5a(.qT]]-@-PF4b޲>'k T>P߈m}SKJ`E5.!\%) m ZA%\^jϊO};0]zOkWWpw9+|P~ 4ن F!(\i!])<Ҙ\wS>+Z 8+(S5+ jRH0u?HQ*EQ[4ͳEgΉ~gk /,$_.JqU eVInϖ!.p=<ܢH'wJnPP4/_!`Jәژ*%_R q1;dюv[j k776ExedMfƭP"as&JDB>i4/FqR䤹5a1DɚxHf-fT/Y[2JjЙEFYQntzɳH=nN-.p ȬWk6p3q!smހP(fWG5~=n3Sh&r84%Vvj/LU.L$,V,9(עO/P|Xb;`oK^{ @{[Md>.omIyhU3q}04C7ua}yͨJq!X`|]/* +U "Ḉٌ6nv@4:Ӣ1ygeo /OJhIsk@,&1o XqT+_taYT`g."YVHC*5i")l5:?쯵MCZmQjN?Ry&Bj:Ҋ ys)3U$B%Ҝ0 ΂fF9+vLι $ AbK5g˺?/Ks͙q8_0K#U HX9a+d:HLm%q97Ă mnz`Xu`Ry\Ca3C.2pLbO~Z5L+OZP-^'0nZDCj\pSaV|V})yq#gey`\-Beu5_栏WWUi+`W\>ЩEJag^a=cg%-ϵG$^ޛ:|ðgj5AQܥ1NMgr!EJ`,l2|pVybйGe}~X.wus׉X*y>40ۋ m=_P__? OuD`=KsRӥJl Im:Bfid $,yu bAFӾ(p| G4'ur PBfJS0'"_%G$ RxC) ʧь{:@5>TnO 4I͹g Ԛk h%0JSyҜ8۶ms4_O&W}4'՜ ]$DI=b&9e%%a<`!nmʧIMҹGVa `1CV3C.>ʶd\G'1̊H욤o/^_DhZL@J{TS}m%`/2ڠ+\-|}E}VB.VJ9q,~QVÂJQ2hyBۄk5Ki4X`1 H"칆u(N~_10ja=>k{%H/RSvw w]:詇 Y,{1 ;m%"FoRLΪE;5Ђ~׎(c1zĶrMWaQELC x8]>{\9cQ؂9\*x*{j+/Rϩn 54}WS|$mDhi B;WE^:,a\u9~=R]+z3-XʻQT\–\4L J%$Lf˨PΎ.k Q];n"Cr/mn΃MBI(%_[&-tW.՘ݹq!]WSڟu52"{vYܒW=n0k{vGݨoM"?1aqBwlWC7ֿL΢"‡0Cz(EHxGCyrcL^0G gmKDꂵL5||L΢}z1@IܨrB 3uL*D $_<]\]7(pp CX}ZQRp`̀޽ ޽lBIYT<>]_AE$êeu,acV+q cq6"raC8$C }?\;(EtCAJ||? 1!xį-•Š9ja0V f̶k5jTeYjq?O.hxM;žc|,URUC_lk^١Y⺃ kMLp+U#6rώD @,\1cNKY3~>ZVHSK[(E>J= z{z׀~)тI}!ܾj|I@`)5f<{UXRJ uJw#j2-79#ˮvDO|lRx5,cH0F]c[ZP~W6s s2cmc+[7yE7AL.HKwzn=~\,Iu)QԊE]k@JEV>Ns eس}{XǏZ7m ӶK#l&2l''UX)ttZjC>>N;*N[͗NKzb x;;d҇roov[Ӊ`Y{.Ay4'UHA$M֎ȷ5%=2BaN3* |ptOV*"6.TX`B !wV5wF Er$V$Ł*6УW.:,#'ߋKP[y_$*Ͷ, I uJ+O|dr3;zj|-\T况/,w6X:}YӾ**̽Չ,7˟ҴEW YJ@tIY3V1?\zp,A6oSYEϗNę^4"e>5g-n=;򦷴Z--ˇ72{ve~ȌJD.[m֚of _G{U5;>=kifȵB\46ε_S0GcL xh7M~/N.t0M&M%m%Ev]\t(Oµ6vDjk]Z,b[kWx ;3*i?.5A@s\vcX6-'!;|h %>Ʌ,>y͘#xQv{pdlene٭>a} {|{d|ϻ"=FYۇh? 1_"Iַb joj͘RdVG=fX9A(q5noyG``twӧLsUhiiSsgaH`&|8Ufp8mqv||%6ށÖ|u@s+?vvtsǀ`F2 Pk$>[xxxJJ⚘"#J?/g,Đe`I\?qt.1Mxß1*Dd4bء4,'_D {DV_'U%`j/"aכ1R5{[Lo sɗK_MxPCcy̚<ۿ;icMar˿60?"Tܥ+|Ĭ]hH`'ˇtemHM1Mf<0+遨1#.B0&Iuvᢳ ?zUяH.t_W/C1Unn\m ͭ:K\aBN'=ՊKboI )qkڱ@qc[`Bx*iP^O5oP0mg[.V>(\,\͊p`4` ib}O*>^E[Wѷͧ&V!/HjUj1%5>v>#poTc<{IK|$|SdcSapJN֔&LluȈݏ>~dGi\w>/KJCKsR=7_oCעڳ}yt)J@Ka ;CpnQK֋&x2Ooy $.hMz5\lK@t^;vmMM;:tAk]ԘQsw4f˘/Ti/XY F{c; U!'w#k%뻊1Z\Oc!YM˰5=Y:S«F9g>HbhL)Bh+jl-f O,NJM||ʺwx׬xK?i[rT 4orc-3ǡ~_10ǵ+G*)S&e6t1t)P֘ TKU lm/Qҝ`IDATHi*okPuE:"m1-qHňikM0ښ+L7K?qI{{[%3”c]'v=&19aYWʔ<"dLzݟ/aӌfMKJ|%fȗԆ;F;DiDŽ?C{Y" aQ Q$]z97{|1Xee{p"O@-|աe4ט1tXj`yu9m5ȞOo_3/.Iٙe5o1le{/M 沣^Zu҂%ff14-մk%דZ1NUjPk]aƍea}ooWӏN4 cgGWr큣9h=f(zLn!8w,v/_"d^!^ѪvF2ɘ,f_!4Y z⩻vYIsC?<\}@܀ǔp\`5tZ-Ƴ~g)ruq1%,N,$ W]Wtan%`%LkWXiJޞQ5^V@h)\ttvt5## dOa<ҟ0vt,~z Qe~B= ; dCkSwY(7e>!;]s:ĕ|g K _P[-BE X:!+wQdV>6[tUb,re?/.>;xO /`K\XiOOЅ߸r(o~% }W M=!v::;ٱ H?q -5|:pXȷA7]=Ng?uEr:\z^'3X^]WZͥ7JC NrR z6lsɳ@? b*[I<rR2kׯh6=}6|Z.Fԧr_m*,"'׷+j fBxz8=+:{?je[dW⒥yV ~&BnJ2dI)8ܳCUJf&ǟKαfhp{yxܥ`1-X;Rٙ|}sUY$IL鎆z44:Sw/{zW4MP/&\b@{먅M9[_KLa(6Ax˗{v,Ux)AwtJ5}&i5JJP]fG4/;+Řjk&-rSF=+Zup|/<\3N~\b&ITXɣkd/8+P[5^l }5f{;AAݶT5OVSawc~WA||be.pGh\wrSAxʝi,Fw@bue t@(w4~=]Մ{% |0XSApgyIDkWie0~]o2fJ" "gz%f&UQsƚy >V$L%|" rcs9 =W#6%__ho/ƦfE}\gpǞpVX+O$߲pKsR5KsR$g-)}5{nHR g JQVXV9/{.ThCy~~~8/;k|j{ &gEe6C- OA{soÂ{1֓X[ kw]Ldժn\mGC|= Yhz\I= r׀ܳ @p $1K-p)bZK?mAyh~t4#++j d,Sq(ֽ Tfi?X?;g;bܸq|?d]TOg,;`' 2.OR mV(^w ->(盉&1.6vK4m޳eyZjčc{z/ @ hbuL*hF ȱ t)54p69 "͊,S K c)v'wnAح8{ ‡_2%#ٞgwPO ;s8!j;r~.+f݈T]2N7en%Ճ'ٲZh+; a6cBNAv|rDQz /hJsNȽ=ش[~=?TKm~ٞv]Q"2 C4L#JXSPXH\3G0sH\MfHxԚusrdzPQ=dqMuC>_M,m!wEn|_SS%ϩWO"77pGo{Ǎ N)J^1/NK1pg?דPiNM&[}Wl| {vtCwxh/ ),RO5>}>U'zjq+*2s+/s4*R{-s430gov!wѧx4V>=!ĺfQ zݖ[V[V O6aIaQxҮ"JH`͔Zi M"/~3eaѧ}+b4wPs寽t7X ī<ݖ[~w]Q!E¸a:x~ɓI :"S.3@-f7)È-Uez^DHh0sӃvMXW<]b zɖ߉oqf$my[mNuE:(/6k3QM &X _s5ir^}5c_Uǯj];o9$e| |6 枷*kyĶFc}4^EEE 5|"ez係k(̾#]?#OZ-jjj=Xb$$)Yǿ͛6Z_yFQ|fay~?w=ûnG?{ Lؘξuy"XJLJ=43VÑ[Sa7K'q,H0CntpLmiʠ/ڰ󛋲HXmeT$gng=!IGJ哠( aaa(//F"dG+_lj%.%eq74Į;톯WWש^Z-.^3+M!5P1í=[huOm_7aZP+ۆ $ GLx=sXn>OfnJ޼i[Z3ǹ;[DZޫtž84,'qqq#G:~v ^8:kvjPj״_粑yV8XLmSlf\txw{z,S-:`~),Eu"{cXT޴ZїB,E (#HaQq$J&4jy3jxr[RvmRs鳣3@ }%g wt} KWk_p{5k)/px6={Yg*b2ʮ3ʃMJFzR!ԊyFr_ݜ͹4ٗkXr iL2iWؠm Wag=]X x,KlUb\)m!p9sf%%)~-F.][[9s0W}Z\OLLؗ Z+ݪi}wh-mWkc Nܫ^~nVR:YK&4N0Լ}YxO/C_߷cYT eZTV,j5a⫕Y"4[՜^s%a͒c|=}V[ڨmaZ#z8_)?S [oZgq3 cj>2. m_^+K8$ī&A" )t~5"7NR.J­3Ro q]lltV(L@tDžߢvM_tzaaٰc3`1{l'={6/;vIZɚ?,5H#JH+&<٦$3g ]zEX R"LstgĶV1S[] 1= 7"8Ľ2FxO/ͨ.EB_h;Oc_W0"\SZNh%խ#d8KxW79פ;_]܍?S^:"M'1_8v='B;B9/X_ &%%!''痓MQؐcy,bڦZrY  ki?oOMM(٧.zOօ6 ޞ!J0ڤQ+rСkuզq-XN AbY$,؃ش,O zkרaNj;_/UV-(Ѱ/7=}v4GtARjNvdzG 9|da >U'ϸtU6f˭T)N6'ObG4fG3|JJJJq.8n_}%2˺5CnS+dOݎZe fsviu%%,x Y=d& .Y!K݇  }%޶x߆B QnÐX +zbQ3 Zg LNo3gg$o'O S% Nda:iuJϗd{bv',w@O3Cu&x-[}J>[{k}8~T8i -<XY*%bD6XyRդcӲ _WjCCm] mJیx!)[b[#LK@WVR 7@j{ƣVPq 3  D^El_px'Ԕs1-z3%H}m ,`nzӡf@bؖ|r6=l1d 4MQfٜ{I]#aX2qݘ\\7&2@I[,O$fhADDTcPRR"/ĩ%o]NEؐOBJ׾WN"վ\R.Fמm6}5f+YY9ޫ+1}-z ]=E͟$?cȋXZK|˫MӉhrRs!Hjmk`Qj+N ^+ymR)'Lk cʮ^Ξ/?O2hu7ߣU'}l; Ub?)) -j 5'C͔n$%&kxCP0+js9U\șB0\ s]WExm1#G:Rhq9f=!CЉ']_+elA: `+TW F1ۧg,o0ٌwQdeǎX2apyN cX2|f`}t pmm96$EK})kN~OxTC6mMVԁ.ItvoMY}rW9þ% K`x&щk)Iإ+skGZJ$ N;Ɨ4NӲoٯO?RX.IoB-nXlC#r)_̾o p+rȆ^Ғf(ey}~S0K}Φ,mC7`ٷ[}#1!/,0*4>dI0>g+?4>DS\?_yښ}[vZ! %܍`@6&- vƇOxq,_G &7!^ xcn1\YJ/Zt !|b&-!q;ԊӲkxF5YTՂhxDឨ3[TyExi!C\WE`W]5"gKy]qکT H7Ahfg}1L œS/F? 7~T]D&<:NjQ)q٦s- iM# 2mc}uLWϿTjF/=)GU͇ު-Ȕ 5lLP$-4>$_n<81 ==,E5oi{cݻE0 +GU)ʬX柙DFVJ,Eu0ԮV` _,ywآVؤ nj9qOT{fwa\L[!e T7@Mپڗ_@XN7/?n*Iya/GkIQ]y 0an3Te8}LH-kOMWݪ<`ň狜9ϐesn7.=<#ˉY߱si=q\(P,'.3bETu-Y4(PBCn&U[֋=`"D.cŬ\mi{r>#i{㯓Xk+=жoG}'̍_;:YcJqvdͳE 7TUW>Mܸx5q7ĸr~Hx8iYؒ{%â:0g-o=/w-n<{N\O :ԧGx~vֵøw޸mxni{½Jd=ܙ~]T/ЀIX,%Y"ty>ėUhjHJۡ% Mo+Z5 3R͇"5,Br}zRӹJXm<,Rsbi~Ia-bz}}7i$*}4$QK֚(&DBV>`LSÄZуk[n,h('̛!u#Dne=Hڒ{^ٰ3JnΓR)h>HDW-;3?\zВXYlf7fBW@ÕGtt ~k0bĄQL/[i{0F?Ӈ.qҘW L-دQIBjFfZ2DaQ\d$5<)n/ڢuߦ@}NϦ2Kas9McZͅƇsUM~Ih|Dq4۾.X!Cx~Ӗ QRI 99FζXLaC2d&iYCea盔-e$әbK8zg^ U+Z䮝}:AusjП!=)}cH#•7jh %xĝAц߯>EX"7q`L,#4>$^b9! I(@h|jT82!LJ`g2c뫐'u͒d%д8}KKJؒb޸Xt]K M^^Lg Ĝs#YY5,'>h2ZYuw`ap/ B<.,-!P apb`FD ær϶uxAfHŸ]$bVyME2f@KW Gf9PbtyUݜ| 0)sl͒Ě̠Q ں[41 CCElm=ҧL E@OڏNCjHh 9i7|E 02^,[JSM]\f;_{iYX&4ClZ*1T=x\~dK fTTqߵuJCa4T)I^,Vpxdbn}'{pL5q_v628Q김;}ljYuREۧ?AfHd?Gh|H@q Яd3͗*Sd='9%SE@ɐ*p%M!Y0jdlucn硇UM>zXvw}:ǹ:Be!%~_kdRˣ{-n|h|TklΑ 7jsoŁpI2|g\Lrr$lrg%TLI-KMphwk*C|:FD XmϡѬތx~DW#_ҟGkqQX<.I|ɵ +,Ͻ@O#=J$Pz~KV.~׸=9|٭8BCQ@!"M2%٠WP%W) N|iW*m4t{IuIhR $w#iH6;_6W}A}qی9Δp6RF_JL5+6>2-}˾ee?4>&%%Un2u>@g;m/>'q,HG%F%u,3qVl?^\>%&-y*<ľ4E͉q磎=5p,,,:lfBOlFʹ/P]yM4]"wtGK-,,\Fӓ#{xTD{tߏ~._-=j1v#G}g>jCQ`phw_̝\&xcW}nX=oJTNV:ECXǫӇP}l]I|]oÉɹ!uhDjtS m?кxT{ b[R&SJ9j!ն>-c9%.U8"oړ&CK? Hw}!qWH{n?y]/ߚXbE( ~AN>~:ZJMlh9R]y _-=*VB\}Js?VC$c9z~rGh9= نIɵ|u,L}dYycc9%)tV bV.L΅ƺQYCj_'+{xt!b_V#!K]jL*(va2 ȗ$ʉ~OODxӤoWe[{>uFstXzS{R:7tV>RǠh&7zaֳT3%;왺[KN۳& '7|J^7Kל,_?X^,nִc+ou3"E<y}DGEė1()}pnc=x ៮n'n$|w+tzŬ\~^E=OG;hY'ԈaTjJAĄG/ȝ-&zNtMjxз2td 괜e":oz1,q۹$gzIOb'sBcfF{lJ,_SK D؍N"L0j1dBoF,gyِtN@XOlt`@ͺMe]M-_ ;.c9%0[jT~2?kr;S{t*ԍvWoĴgzࠗ56/pt?{y r"5y{F/}uҴ7=߃ܨhOC#oꖩoL;A֩IZv]Z;E3oo1/tHg2Pq{BN,{(&Xc_k=<:)4U(łEv:Z=5$g~(UKYQ{-Ĉg}Vux~aHmט!yR0 qeX E{|YuYjXj!sc HXJfB\B?ZjߡE%>)FKœcs0 v+=*_P4IWJUBv{:-? +741dxษC1%auRW[b; <^'ڢH!n砫y :ݱ%5J'ãXZ{$PҢ%Bˤ Xb]I̢GHߝ"&,G~`bh?m٘b(J21ݶ'Rە>Jd{r~䵖 N_rvk>ɓsF{ōS +VrGH_xQ# _vfdl|(_B0myod|aHB=e9|erɶhZP0#".z4CS{LI.k0!ZX DFf2mLwaIFMIH37*v ) `jWFXFݼmĵ%Ljs~z!R WCQH)X Ӑ۱>gdݟT ب؈4"hzS4#k`@4e N2{Bu4{kh` 3-,\aލA\lCTSD+T˾e߲oٷ[-"k^5}˾e߲oٷcɇ:9f ¢1a7靴cX d[XXXXS0ޡtza5Z!7Rbem¬axOG$g7>-Q^}Քi1RAl;Fږ1|gF|NW>a ol6cSN/ GEێIIm^ wfw1mxkV*K<,DϧЛa?#/ aSnh}N\9׮]"{cְah-G}1+טJ_xa r3Rvh6Fȍ 7V/DN`O/,!5,q7.MFr_7ZxsH4èpo 3=)FA[XZ֩=wsj1XjmJ^ad_)+=m3gK۩O\Voxhr'=|J},ҘOCfzRa^1;}Mz+}g[rϻNo<+d'-'j$rr:;j'#J:iY<'-a;_ꇣGl})#{K2AeW| #=.1fx@:˾߉_7rh1Y6|2L.i>F\?>xpZ>HEa2Т6wsj{NnR# #ׯPv-f / jU},>CJIJf_^}o[_ol+9 Iiz-1ye̼@ VϑNRFuOT{ɧ{cMk8lFRÓĕ庱ķ"EdPud]@.MO."tU\ :J\mj1ZWH>',أ{Yv0fǹ18Z^)ޛ// (ڈm>H>F ٣_࿯&_ GG Cru ghlaRqU5sfƏu3Q]9Yvi KathDXҳ̠p]Yf>_ctDvA)v[(D‚=+D 4+R;ߦ]ra_zVd^E{Qs`U# gKuVk_n_3uLI$,` >l-vLSE:ߘoOmύ(5Hjx߅w`0 u}6v<%!;myokЅ8GYE/t3}`Om/,jWi]p23HWmaco} kV ݜǿ;d%p}CE LG8an_K`Jyjl x:I+t=#D }XXXS*Z)6=B$ǰ5,q[-E3o- EׂܾJe+T}Φfle߲oٷ[-ط MSf6^]fvbL~\\)py#LVb_guHXm9\80 }>e^6|xr)%2 aUŒU0ug] 't^ ]ϾKW^?Sz*聭Meh 2 Ƈa7&#f/k{4o:{0~_M 'Ώt]yNmxQ7ڴ d.~B+Ov `>v·'gao"/^7uZ:\KCCP/D|ފ?ޏU-'6 6Ӽ"\YHnFS?WUCm(<,Smɸ'j850Mu^~Fyn}.8x/Y"@k;dO ("Č6]0%۫,/'iZ*@UBFX'&Pz*)-ׇ!hr%۫FB}QSznк߅TѢ0j]LmLh|HFȐ~$A|]AZlgf&77vZT,Å5<)s6RL^.)kdyj!DVk,G3V|-Q5ňW \٥뇳af̺Lu6'/ײ7G߿9!uj9 %dۇUM%,Ӆ̿0AEi{ <^=/&мDΖ,nK.phIT.ӄTUeKV1l6ȉN s4u HlFjB:oXkYczFbU0C|H7VI|+_61MQ&JA"Q Y!t[$vzFlaIBVΈ-ICl[ }Um=]ԑFSжt!|da'ʮ>}Ed"!z1psaR /yO6nE{F'f5"XM+oWU#'i@O;kcn}DoĖ!sW;xRU/A>p7>dd,x/ 2 %2%=`YȺ^|GTuVwoo-}^&l:nX4ڤ=a+ (%46NvZHo#H2wHSs8=܄9n{ֵėlXsi*MP!NdjIJ gXb96ho^C5ۖhٵ^tZS/۲k'\=qc#n_MѴG '|p~TSS/^-5X{@tl@xM׺ہ[JCИ⑳E{aYZo% j2@|I:aU-^&FIOX.301& YEx9ìk!geOu<;*fce-w; n_V0\;S~/?^'MhhZ|,B.{;E!NۯEISYOG ?oaovO]u靈 Glf=u"t܄=.; :x-/7|wlj/ rf0S| Zl dd{Uԁj]'Ȉ,)5/k%۫Z)@Vj'Xul.[,</t0/bdDJ"L^3ve%Ut\,%= *"#t vFlajBVHcAB_~^n3U""芽f3l]zEᕱ^_{?Wfң$)_;&̍„QrDӗᆈ:"vyU1Z;mN:L9Mj$ k SK`p"yM6b%jD^mE:Ztp gP=NT(zJ Vq^SL' MJ[e}' W9EX8kqZvd*QPNdኖɥ2xٌ}rosfDꭓiyZtL+H!ȶZ8|+c9t0L~@U"߇1mI$9!he>5'0mI'YDu9/ldJr_'l v5ж Wŗa#Lb3/;Rws@AfӃBֳx[;= ɎxY);_Oѷh1Q>H[)3ԅK,BJ2bČ8/P7̲A\_ENVd/_;Nma-hBq6d]k5fs/;_qpZ>:[{>V%fVoK<\=PLl;,_6-cz X[חԊ(JDɏv%r$QKU, )xPგ}p~ܠՎ'LP,GD*maW_^j֏&KV,uj k}-ڵ;^6d?w>/pLrÅ2iqS LOگJ|JAR/8~@-\rcf _rGn\8]1,>7|-7|e*o7vYό$GG05b-ZK -z>SK-5)~"@JtVJ,bB]- !+u"%ZgO F0\h*[Ba} ~m+W\>EQ( l~^_yhĪ6 g8,F >7p#l 8 i%]&x+bWW㕤{8xEuKvsldr*u%, "PQAِK׉QZ-[ ^_x% eA['j8~JV )G33?^+HGs:N.ÊYCHect$BPW"PW,E+ΔXN+(#sW@&(48v?vEhp\crWdDhP2RuF`TR68@tE wWoU!F]X1L>G FC^| "(&cPrBfd&!+2_(jKCS}bo[ԻK;z^m+/*AN. 2 wv$*Vb؉th(i0f(b+/TCB$Y)q!vFa˴?ǦW- Ɏ6#4myo%ϑʯ{7'Tl'WsIeޱpC-(A[9S;Ramr ɭU%K͙cÐ('PWRd&$'ј:3I.^5N-cq&QM$Ja' 2[TZ$R$dFZYȊaFbIM2S 7 q)NUҒÓ"ܘdѦsBR)3b kơuB=?13ۺ -'TVJ Oen5Q+gTMX7?6$1:d6A=Sw ADQC1UXd;l[vs6Mu)=٥I]h5l=B'Tm7j?7 }?n*mCTJ\k׽;=Q⫚聭uqANmw6+56ಢn1=^9lJ ԁ׵UZ1Cz|yl RE mlyDxmd^R"˜Dԉ*?u`iJT; #%Xn< wUhld?2a.hÓ35g!tWZU3p[]_\`p|h|SᦉLc_@mu!"" ėƈ%߯QȯolC~` WhgSo^^TlZU2] p ə:3GֵZnd *)-'vS 5:1?cʚtۺ=)_}kNs$ܱ3QiO{^jʚQW4d$jፉ ts(ߟnMc M,^UWER5t@Afa H~ZFW;SQgF?? s-)kN׊E=eh$9H?!zH 84ħ=iV7&.ąug獉 k_~7BaHzDXkRz hjQtAfa"7[i(MeW9" nj1oKj =E˼r9Qh~SHYs:** +&3ei]^:cBOo2}Z5b-=43XBvܟ\@l3K|Ao 5VTLxRrg~w8ק8T{SSdkSÃSKQ| *EUvZ|u۷h(M>١r!6?kAx3Fmŋ/$3VZ̃SUp.q  pn'whnOPO}!!p\L1e 6%Vs%*䍉 5(Az@OXPZ`ϢֈV,u/~J犙>Ǡ1.ÅHDݍ8c}/_JBY`}AfaRB 8IÃRhD'k璃e! F_(ttOed_'ąطh&8aKkX"_K5f6E¾@)}j.VMfLd.AxgBzp:YWV`C*,c%mj*0K|z! 2 KH߀tIhT4jE /X Qiu Rt]=ԩKrVBO/ᒰ,0DXD J%¬V_r> -9QMqZh~|vb% jdNV&eڿR"LpE| !ÏJg؜7!-Ua `n Wdô6ƇF|TN葜AJz`)X 2 X?yAfajha!"̘b0NX jm g+23ێ'Fo2ߺT<=UR+Tl̆ ~CPj ï Fҕ I1qv0>?D 9hX7M,!HjDmDVk^2A>NXUkKD tfl UjוOjU ʻs7"A@]M76h*(zr!hWV(шZ "iP#K9eTJԔ1ޖNyzrcjf>Ñ,@TLOuw/B@̭)&Tm/Cŀ#&ސnHY"Lא BzEXm!"e'Gf94>N#C$~FfNet.*ґa,J b+;l7I$ai 0N%ۜPTm t37*H=^,wߣhf>`FZuH!7H8akw#iPzt $S{,cmf5 }pF佖brh@ WwƱ|,@SF=u9> Xi֪e<\Xy^Czel?>1K+c>}n6F#=cmԶJ|Şڲ4ѨK bGzϤl%Ό}ꋒ&nߢ$jlaE6,BB1␌NHGIO ;mڏ]ptD$ ÅĬv=\AQ8|"n MLf$k"p6l!%t?oh|[fWBKhE6pCd#2٨|1nX#l҈5>神-VZ;_2вqXJ1uptn܏nȻ՚3 EZlu Esu\H(7۠ȆfP|jq&v~90:wx[^R/x_a챣eUUMTÈwdx gbbԖڦf_=HYs: ԃx3wSկnj(b;@ EfVu7&.,^Y8u%rƆjmgHE~h|*ژ&CU-9 ءVGboD!Ja 0ᄆ nr!Ys$]F?NIT}nHtĞP'M zv;-ũ9>- M`[eldz-,M) SA>g[ξ%͖o4վQ"EQO[ jE˂88B( <8z UI)qFi1Sꊥߝ,*I%˝7|"{K T&g#|HOAFr_C M"zʧHh}#@DtKyv3UyY)}XPGK,L".vv5&"c ra㬔XA|Z儈m>B#5ضh˲Íw#c}EE6FE:mm3מużvcM[˳ J]ش,<XQV J]PaQ!9x8a=Cb76Xr6ycg\{6`zT֌9erTVJ,vIIfa"3!hXT2ƇdaLdES~zvsX769U#7li63מ%++D+[ij$S*f;)۬1N}dZϘՇ<}P8v 'bC {oRk&*O*zAI洙caɷ:-j֪Tt7ad$eM^<. XғberDX`4I#g"mR hjp;C3v2F 0Z} =OJ1鱱t&vycwɘꫪŲbBC=/a/DPA_Z?WyJÖbB1^G=isƄe+ϖV 3GJo(>b8e4Ƈ$,h5YXXX46>sJ #":KzG3מMc91jg (bQd%YZU CzX$} otAXJ17ҳy/X 9V,H pѲ֥ѻEqG@f]k,g1ř RAkѶcXV ='zf939Wg{yX}}#`Ϋ=Gx^n33CCEvt.P F VB%ciI $*7. $!{uRQ$RB .\NB5&ԟ9TꞨ8[Z쟭q,j93!ɇLEGNYu %W k=$h;f$&Jg24TǣfZ*4Lۢg`R هߕuHUbz62b\,-,,VMȠfZ:ve֊NX5CyX Nr+ c`%cyk:'6 Y&#=y@K)J p}2l3olAj'ѳժeMHS^}U|Ym0b#Od9)Ix"6z-)b<|`laa k}Φ1CЌ/j<8ź6cEl,_/ETNR1ne%۫L9ԁmfm}oP}ؿ2_y*&ДȍMSL6l翩_~3<"%O,ٮ=C@Ώ|y)vSAD_3Ϗ̓G#V9:TR"UB\xNyc17Lغ3S}~Ъ-7=9S[IX)zD<8<8e MhXla E4 pެB>vlEUnm^b:"XӖj{twZ)O HxT!p  HyF?GG7t, ?ZtpbHt.(=yZDutz }P;aoI}\0344o'aLHmOzZpxO/VrYgmb2+Kp[]^U,9J[vQ7@C`pzӄedepn;6A_@ň|Ņ?AMzR`Za*F#W-nlxfPӶj'nn{yB©qm!H&q[ӓb[t}J 8 ¤j .1i`հ:-V1SRJY6:JCrZF=txbւ.|r&bww߲/AN^qc"f[^}/;$f,/L1h1V XbC-tU3qS!SSZN rM \lTd@JWRED{oAHȟF>Zmr\/W#bn>N]w[Xz DG "(^9#Y$,ËCiQ\2_WC VσB#μ"EupZ%FCbS qxr}5e''RҾZ[v V‹nץ}P:m#jnL?|\6i>jg!Y,K'yORaeğ*qQJ ʉ *:k`ȏe8 | Mo|{yX3鍰,ܸ4( j?}kWߑeZXnY;'.ɘW7Wu2/C9 x[vt6mg 6>cY}r guawCNB'S;LNORΖV;}DySjێ1CЉiɝݖ} K{wb-G8UJT.E^zB1 } +WSVG?5vw9=mI iolZG ^lZ}۔yxԉoҏa/潃,+^1}8&d)Jh޹ +vߙ|Jҧ3~4kRcscɊj1X,!mg^77$òC/]iq BJ*E7>79!a#'I:LM0arE"|x\CIɌf9;üb~AKvh0!Y,$m>}`ߡmB;$tx&ү/;aU?9rY3Rlɇ+KpO7 7Ln|$9ʹ>`-%' Z({JE0-#E9>?Ŧe!&Osas9<m)sRbNƄ䣆G?a|&v(dB)L Lۤ?$(t15$,$HsKt[/LRDTʻ-T/ B4I89?v²Naih.;Dxp5,/JvUL?0T}>LvR<++熈\Ax偓Su%\޴Q}tj /!wK?v*!#dz'QWڮ1:/UnalZRypJM96뼪9m3a g+ڠm1 A2PR K$fB~xr5DPh7ts(g8Jo[r #[r>Pݥ!bSXUűֻYRF%Wְ<13lK)t /}z B.Z8 >PsܐB&aPEg@>8L[G3Ħea@DA/?_}GْKR;`ѶcX_&|3\?TGY:WCCٗߨ_LEv J1mulT{˫kYsn&ciz$:}B݇ M!㢕@̓_wWo٨ڽg6pvOðf+z{$׉ÑzLoTama% }9_BҠ(U,|Nsj>\!D,:K d?nK)+456(9<8ž3(Qj2ى](d]NXyQtQmh/ ׀5@Eٴ$$ʌlXXXX(ƕXXڴ¢6ui7=m}yf޸}Φ5y lS.c®toFGxmlgL~i5c<0%Q4>z`kSlxrlJtԁ!%۫Li?}n=cS??y#LcoZXV,]ϲCJ?9vp2~Lfx 7yZ}rΛ֛ԓY7ggHM/%Z[bbZ"l ͮxHɪnSz36 > q2j@ f9y؎;Z0jL~wBtkOo}!=hڧMbT P!9[5U4[ Wg@|)6zΆp3zΆ-;vTCZv P}5^G)[fo`R(_ tམ~a'D3􌡖RS~2@"gKSWU:V7D_ =,ڮ7& R},l5u'Fڗ8f _z럶ߺO/eGݲ )ݲ :tJ}}oA^x߶^4 B6a~c"ōc6'@$ƾafOi[~Ζd=BˎNHU,In~ڦm6n2\0#{F^jy똋 S'5Y=,R]R",k='gkz_eCc6LN؊Q%c-)+HJ{J5YY~h|}'"r:' .i۞݇+'ILdc%۫jY Tŕz,9˯o1!s^5cˡܳɲ'g:MZ!w%Љ4>iZ2V}>LPrC<]v73iN#zuWD. /RUM2=b.u)럶/tű^Cy$$,}}NDb/5ͨX8>),k=*2L>#(KXXI+u[<ҹ+,Lh9!z짧|~RS[V nbP9<{@.q$$\-^i!V3h@%۫x4ߏ:,+͘$χ֟-xO\p ?Eo/E S V3%MکVo򞹂epN'o׽,h?odW*unXygݣK2kTVWY׿uO+zxKW >,yO/Cv7+ 0f nDF#oa2}7!uTozrbҏ;18A}#KĚ~7Sz_y4_L/ S0, ƣ4^:,; DUuza ʾ7tGUNs$#u%TߨjQ)fCL3Z$*5Y;6~!.W;GH>sמguO6@XzZV_L<ǐeX?Ʊ|pz>s1ŕbr;͙d{U6PNMs )Ө\kSVyL>ɏ7_7WR/"奺u5u,[Xi[Xvx.y6*2P ? I0>]7i:=U$-6|p~kGߵYw?*8cG_=IPVl[9SZ`– yeomxTu}ABg{^/ >LzaKagٴ>`ձ"6Pۺl ?UPh 1mr0 &N/$n>pQ p6C 4 c>,,,DU%,!eAK`B6Ԑ$nY0kx6+ o֨kVvHV j+ieGѲN[t^"~_9"K2T:su/,δf b\W|il~UEz3OδJMZ4(ZCSz&-^d{U*PۄѶo(OGkKqy\xO/åOσ^eyCq-{> !t݀:]VGRJ>y؎Dr#")ZmK7gQ$,}|8ON'sRɱ^Cвc,y L!n~]EԊڤ:$GRi-L9MGx eZϒe&E @CWY oc2A\5/^N\OkdpbKW2 ݲ -;v@MY932?^L#UR3yVX'W*U Wٷ0]ܲ磰yJoxЍ(tiv+꒱hn U&%t=hmÖlZG|zx?э;p~ҖY9fST\#pߧ45eYۗ8*H⑪4&?Φebu!ՁOQ~"TÅxݍN/eH' !CSR~S:oj~_qޮBuz ˉkRVSfO@ t(Ouֱ~cdb֮ceG1hԁrr&G-ZKW%1$It YCyJ?wTGˠT3Β?gA.LpP{@PJߙV1Sq%[]nr!կbπ$t^L([~#V"N4RV-~6Ii_f3Eę~Yi_ Wd N~I(Yxn-Վmݧ#ʀnRH/Yb+_kj%~摳2pLK( I=fǹjd͉.ɏϿZf!} gᵑu1~S~xMSI!ASIa6$n #~أDs!0}pt-8Wc 'xhuE7۾EaalM攄:sgu|*juA=\d1qhο-:f۷hҞʁB+Ƈjb<ܴ0Flm}:,BL2&aJMovPKxMU0>~ˆlMЋmhp7=#0M_T)-ؕp1qҦZɫ!+`^9~S>=?IiOQY(k?4>P])kb2ߵUorM%ސmiHl=z6EؖUpFbh?臐s1fOaŮ,c(x+zRޮYKh߯V0iM1;DRY2b/Ìn}apt%@лG .,KVkC/bOE:UEVkO\oSZ&SY 8jq x4>`"lD2H| /veΫ1*k10*k6%S> QIiOmۮ P}NGƇ7j (]ؕs=b8q =zE-93oM/,Cl k1q 2 U=P $֔~VN\ٿc؉SX0pg nv>g wq>gC 2!1;jz_1+}Y[ImmWKw$Z,:5kXF| .y / 7idėB s! 2 {œk%۫{œk}ؕ_yJc̑nŬt{coH^1+=zo07f+*ėKU/o(Έu[%d3+)~ZHlD}bQ`6k Vs5X7f3\@<\IbnIcnAi'M2<5%h Gk_޾h"FA'uhMPukSȯ1 ɬM YִM3hf sm{tfEy9&<e| d.0 O'KmpݨMѵU训zG˪8oVa*O3hv%u/o_'܌Zb.|R(86v z=SS0E4+%z./o_', = d=)#_Ͼ>_rȯ@_gqȯbYJISR⫴N\Ҕ咦\ 0].iUlJא43m(KZUi{LK`W+jV#ue鲝1sVJ%\Ԧ>xK`ꃷ@XjX$*݄H4ٶe_~S!@Ox҄IvhAկw/6f!/A /o_I"zE =)lo\ӠGRIoEIyEhdaa {gSu}&̕L4ttFlaXlYbWVT-}zUg. -&|n+ndkv|ؕ3Umh ̞9sR% ~ܤ4ZbVzY6M pBVHjFl`DWqL8bWb_j҆V/XKF4#yH>Z9Fv#GIb#9r;_z<^*6X o,1iC.daa$iC#]\+?9an҆707ID)0 WJPR@3hR0Y7tPJÑHZUM.N>Y*Y:T"^NYvEи hntm;;|t15+ ].ė &N@ 1"bd fhx̰P$=egm6͘iﱩеU5f)u"I| \F}#L 5Q~*(1ha $R}~,j rKtM A$d$e҅4t/bI~+e[s7].f=0'l*GzQ\*|R$=!=; 8?⹀ 4>dCAf!sԁl2ľx.`ؕo sL47,ZFl=`'d XMh͘pОՍ•ŮL WMn4R0Qb]ۜtc+0&nBIcR(ƮGet+mR) ĕv*fFٲP ~2fMi_\ `>5K਌cX -,,,,,!d N¸u3&5a8!+Ofaaaaaa@. k/oA2| [I w !vX+Wo9 @%D]B[{`O_k8vs.¤ó|XwHOy>p~'\3dsMH#VWIO{1D??7i  X }Ŕ?9&;,Z)Io~v/=iSL-pnc)0_o1>~> moOk?هe! Mi{t;|}r~ˏrDm?jR]$iiv9%{=eՒӳW̴6?gƹw܀ڢͭ9 kAo=z\]`X `[˴OpA`KKU7f4:}Zv f^=siΜ$?#f>ch3@J7ж{-9J\<‹aIhյKͅi҇ǢkNk!i Y߯e_КH B޾ɓIG5o?Y$~HpO @ɘ蚻~>#S-=.ا߸<xi7XC7_G^4q$(v[v ?=˽z`. 4f> ~gx :߀6]˪*pUQ+LsO?ذ171!d ?1ә<;Nvc.8ClaFF##[ꮛkS{7HS?1-% /BOJ6`vX9ـ7}}!+g_x}'nվh}mt\8{U}pt|s nqi]8 's< A5'HSrAo| CSXSAm"l;4%BT`af=vCa>qaǨ/Vfkۻv3+؃Y0+hGMY-iF X,pd_v6W})J!U \lZc>]t?_~؊3~G{P= O/?lTZӲpzd =L| a٫{P [oUv+-Ś ÌAE|'^{%>qk |︂NWD|aƋqc˿a[*l+['.E̡ycݽm6Ȝ5 ?ȕ2j%X+!_{WfSބx-cLB@oGĉb8k%|w7>.Xto\\o޷"\[..~^J0rX..ktM(((x{B ?@/C"__-Wl`} .|p۸ 'm5w' ŊUC ּυʼnbdr?mpIXhTӳ3pCOdl\EK3DEPp~a/HONAq޻ѭe"9sz"nIkއŅgDԀw>u}#q7NU&i^t2yzx εr~;JqG+pe|e`oWKhӋ'2E}t+bk=~ֆ'pDi>˂nG@P?0lLmI?rW/M7W!Cޖs8[?'lQ08d[ۣic 畫>~x|#Lns{ nA-Ae;G޽JP^,=J8+<9i<{.ZϞQ[>)߱/J/y(n߯mO}ڤ @绁v {.bCSssS~|y~r/~Z]"4yW+ZzsU+wFkV|⯢D o.{zEe?/S|&$`,˅B-+&4ߚE'ZuGoݽ+S,w)?]&ZWKk,]vx{8< }#fH T{oyKy#ĥÖD9f|#zuœ{%~xYucb9%ة}$!]7>ku=&zs"`[6FT/?#xt7!7'j>mBZQ{؁r3:t` |;y'o;_/lo7fm?8j- {g.KU~]c6luAس q\*8^3W[T_/sz"b.!Mv7^%o"4:8.~H-UU]{-/Gjtn l1~>=MW1Z^r yg}tE|/֍Rꓰ ";ؑ~_9o}kt@dT8mo89aUwn;ߚqE23$K9K#IWS'OĘ _`ɲMm}K*{+>=7n~mT]vK.*+Aj)$ p/DD_ٴJ3O|; s1uX: ?ϫ{DU%myA>|d_Axd,Wy[ 'K)pԍcۿ3히#y[Q{-|I#̋ 8S3^"Y\C-#WKK25P]r`=ڼkh 9Ԫp̐#e=i꣛@p8{O.c|-ƌcF]?F8z!h;rrV?v7ÇGQ}-zf& d&2!h׮~O{ }."|_Pu(ίS"OabI.L~835ؼ< &ywbqm Eޘ1'օK!3X/?IPvCi\+WX0wȔBX`~C]ά#|7  QiUј0'o f=: >L Bܡ>Y@Ax>[;O>EZ4'&\\9Hrr-ݷ?Z X08mf.)}SL_n[MMx '. 9Oy aÓ/Sߋ ]o>'GcVwg?^mhZwc"Q tǦ]t\`E/A N:{ XPu%. s]~馐*?j{ _~̿O.`giN%331:3e2,LPpBt.y13 ,]r-%ȁ9q>9`ެ6{:]W}~ʳ~dV ۤo3;F O\u/O>2 90ȾD-.} ra}+ae& I?ƄƇf?4>$f~f:<БLkmbyi{{|_l g^K9 Oɴb34n{|ߘnKM-piff3b6Va;|'=ݘGG~1M^8=fh浿꘡g'^=v1;ЧkA[XXXXX4Fx&/Q  |v?E` E|7 @: ltl{Q[&ukܛ/vsm8UICwؿlICkI*k?q#߭'$@C`4=δ_W$vSo } m=|*2]ztomv~ӟym XXNrSybUnvؐS"Lh཭M쐛唝km~ ek$@_8^@?~5~n2BX:R?wgw?̰@ewmQ1i٠{{2:tŹsej"܊J@f  9}iV~  96O}ɩT"'h@!0"4{+o'yR`ȹwEnU556O/6v5`s~>ݳw\m"NQh51mn Rl T׭+,rk:.{Me8(8[S;c#`ø9%o Q+*.>?O?wM'[{Vh-\ò uۏ=&E!4{+*~ 7} r`GwrhWYg]A.x2'I'E@Gg?D~T]}Sqac݉]٧/6=۠@ٯ AMt4,i_LXj3 |-ȿfhhyN-JasD޳Ug S N@8t!Ѩ#ؗ,E92Ϛ*=%YX\,GA` Uԯ/7v޺^CD==kΓDnX\eOnʙ돟ADLY?^MaKDGL'gZK~NX_T=Y/e˖acذa[Y.^^}vo?h ?#YSEˋqs6F ? 0!=㮜ҁ>IRTq47my p=nL,"X#wq.㆔]@:8.:, %"nMN|`}C˅54x<Ϳw;/ӂ*Whi3ê?7 …")W5;c*ΰ@pVlAoLCMP\x# Vn s^G`\+s<$~eC 'PQIlCn6;؞ErKMetX@x4~<tܴ5QWKzH5s/Y/ְvE71ɸC~? GOG7"ğ-\seiq|SQ V}Q)lGBh-$E2k>^@˫:0_Bt+P3x7%WϋVtά2s' sV5+c4վbƳwaӖRWmxu꘠>sI9ݑm.]nTS_xXھKI 7?^|0#Anl^g˃5z4h?ƻ $A5IVMmTg7fc1&ŋ1m46{b*~roVL+uӕVUg7Uq)`jZDii)rQs J8DYa軞{,2{Gnyz@q!'|W=bN/~5By=^,_= S~#yyO(lQ1iv1Dž(fdA˂vjD:JYಠ~i0-YಠUѲ}8Ok,K/Ù;rU[$$ ނIX.dA˂;]ʮos|8q%sf˂.q씙90J> o.YFNvک/^ qOkny.~):5ep!-;ND%{Bh׽8= 8"tT}×_~ !6 1 @}ș˂C+]xd#x/I}I|[LmMhUbHZ@ 7Etǟ~##,h=-eYD4ԾDZcEǤسcX mD-I^)vEתZ a>'VPTj<="L ?+A oSź>ߜ=TH6Muxë 6o_$9*瀃3U)b.]or٩O/ } WJGw'!N rG U߽EW7Lç~;` Qn-xb,^ -{|aXC2;~v8~otϻŘEҐg{HhPtNM2 +ˏf@GYG5'֌7Dʹe3sXfal?c 3& #m(ίV6(nۮ sL ^L@QQ+F9|5{BQV^]C\_o #_H,~ b+ IXrrY;w~r$[-αMP빏9։nUpJX*oãc0y;vn_;V)Pq!4R"MVGoph"-XeFsɂ68M_̿\sgV 9T~oNMxחb+A;0~ޯ?cJf:nnU5ݿ| mȝφ t? y+_tS]ȀQ#hXR}/K.xxa.)ZiSo`x]bSZ| - w, W ?aґ`u<.jdۿn]=ڳԵ0\P_χ( ]*DU6PS Y'r %g̽h7Qv~ziU?v~Ghb';*N4OO aJ3gpjYUw6Kc _цﳶO=__+7~+]O|n1b PzBΦuq<#et3¯w4ϜEuY[%=Pm43/gb֫.+ŽoKFgpBe׻VՄ.F5W;h^ J.st봛,T8T՗\_p(ܾTR-EIJ/nv35[_(1xߣ7Xl!χ?k+1u n ^wѲsrm'_v 5~woz! %+qԟnn[P&2oXx[/7EB-{o;S+_E|7͹ՈɎꧥmN"Qxt  )墵H*k~#p^o4tCx4~<rN@iVhrn5X@/nA&' Y_YnIڇ_n`tMK'!O+0R* &^? pukg $^?G wW%ukga]/Cacךg߽67",f`0awČN? |҄H~~. 8v%1C]1LЕy~j=epUG/>ʹ` n5 l)8fkb^^w߽+fmkmbzSbsz-&?7`W)-?!]G𐮣0ô1)]Kbn>}0+blC?F[hnXlaaaaaXlaaaaaXlaaaaaXlaaaaa7?; `I/=idٙPhgl61HВ X5xwQQ}~EE^" MĖRĚbLԘ|֨ch;VWW²\ds8ܝ;aٽ̄辸?Dح*ktՒSIDXh_%].:h\4 <?fҺq55{8m"=jE @ti!CQS&6N~h)sݴ z}/CM,yUOu=Uw "k7aͤ#D)L//Bhj R3bJ]׈aF^y[W& L  ᕅr9 o٪7!l-͗ƨ3Z]&Ok2Z.pvu5,M\`s9Tz;|fzO"^Zc`gm,,R yk+"Iq>I=UlqEt8P%\Hb^&8$Y}x}rq]ݫU6>ѧȺvŨSeyI[]![0{ .i=꾆+6(EoAk:YCz _#hW=MnZ,p^?H$\gl:J&xKQVHP嵝_io&u_<-;;P ,3:/{/AEOu!l}{ F.\\кq|âܸ+#m w%R Z xǝ./=޷&fK,oL޵n{140KIέ$~%Bo]jn&㿡Nw16(UIg [9}@GU.M܇:_E >j,+7s"3ts!s9DhW跋Y,KF_$D& v ([ V|lۿ%ҠF+;ӂuߴ5<:&ig~k!567=@]s̿x"qj,q?Jh ByC "logu1D1\FRxљY36[),U%k VgQKqCJ˱pùVuRzw8sSi?XxmSK I&9[¯}[rNrdHfvXQI]VKIHn)۱ꍂNIRf? x.^x 3}  0vņDN[ZuOTgCAYg-_0/K薦@sPsOn7Bl 'R!t6۟3hA{sq҄M1_[ް; EbrrK2j?3H^nWʖ?zW|=\2HJ3oQlaػi\x|Y:OS *F^ƁA9ƛ 3kAq;;:L sֳ7L ́GWTB|Bq߲DN+# RpWohv2A/9K.7t7+|!^"kMT2@ʣ+M&+w."yU< |Sa^N;quk9-K|^?86^Ĕ.Thڲ !V`>PYן}4~w(G2RvA@Z(ЋW'~n*.W+x>h 0kkX16[]AXfF7j#kӈ h@hFoz"pZZ.ڳ =u.ciqUS/iH]^]*u>Qm>~i5vO`JkB*/ *ՀCxmթ)>򿉫.YFt`х8rcp *ψ|a]917|-Wkh5p9VFUZVXK-Z,2NBp^N#UMh2_mp4iΰZKR+:2L#nt,Rg~4+%EAl\Cw6}Wcدwh풶.JRՎ5R~iHpY#j4``plH+fSF`O@`$T @h* Eo• ?t?n5mv׭YAQ+F2.p,f Zy8g2Z1'U5pgsFO=Wsu,؝\!bXNtz!12< }Ӑ]_f%E gupԪo M#̻F9:[_ID'$mG(TDiH9&V} {7M%T-{/2 }bL,Чj𸶵E׶vpXbg;O#ޞdiK~xosp5gfoDὀAݓD{9Z<"m?)&~Jk&fWӽrpX睢+x_:So'8Q VDXHߟnErpDC~V~KtAۊ+VX VbŊ+VX[bŊ+EqmŊ+Vcm[bŊ+EՀXbŊ"@н@wg6661\c+ߚ<Á.@DkZ_痏ta.!a9͞ni6KDiZ/ G`w5W֟:O Q \·M.W^z=%Pr/!-/"v/%'?Ы 5X"~PG GEosg)o},vQ' &^S9PZ\|&}yj`3¥!o- /y4=ݝ8|g,+hT% ^y>(.#'!-4}y~Գoq--˳%ʪU!D+{NGm\$!sW g/Fî/#EfEHz~>'찾l}襝jq@r^șt.9:dKMgꌟ};䵦.&aF3G&~a[ZЪo78-~>:FOYJȪo~Y?G Zrǁ~os6l)Ö 3X˰?ޮocIBb ǎ!gbq̽.asSnW3BК8;1yGƍk xӺ~'2w yD7V]OΑ4V)dF3GɃfhŊBh*hEݵ0lS8U"-z()^-{~:OZkL M%<>fu:$D5|n=^ qV!.P~;`-rfL)ͷa v N%mDmew7֮Q;W_Q,B:Y|crLXN֘n{wT?cϘXcezX0g7S4C_<Q( ]yrYwаRFf6_|ֿ kYKUw`$?G]⣆2w7ͽuIqjs"oз@b) 5\ ׬Oto뎘3[[Mضt.^+NIj^7jG l+ɹ!cuX^s >Tָ\.܍Gov[ߠ1]\)iR9C)n/TڐV?GWG+x&#Ƽ՘< yO^:QcIYo(b:C2C9AO8eh@E4I4>`vAoLSǔ '#f5[ޜ:nPm6\iٜ ~7}5o2UNF:m0uQH/'mRt;MNݕep}נhn5kɊpJpn< Gv݋T>#-]ے< @96:һ܄jGURv%~Jњ˓I Φ߉7.,JQc l1 -;d綾+<6YQl]Gy~MF%U4Urfk< .';L.8 [U2p!L'r[*aLSLMUH>ƝŹwlIklT^?kč.RQd(;dѻ%9ƀە8Ni*+u&MKl`s>/RH+dF-1`Øѫ'aow{p8^@Kŋ$xs$F,!-}PvI|^ҼC|iwdTh=fs LI?0}q`x NS?-W*,u҄K]=.ditgp2K ~N4o>i$ȫgoKʪYq/`a㚕ɔBoγ4"q8yRm?.m>غa >8\\Gu1@0a*9dEvK]0=hEEo|'ZSֱ)>\1{ۛ=i,L< V_H[d>r([U7Ϊ=1`9,薦@O])`Q"s!Gxiu&is*C,bl @X.}AZwUOe'9 \Ar"¼1ubZty*CS{I׵mMԄзh(n>~q )ӮCMz$ w(ֺE4,=(vV߭]d]}J&k!v _bg!XG_>Kd#}=԰+LJ)<:7``PJ3$jވ!}t%׉H[LQiH\z@eҗ>/璔VA]MicEepӇt<_YkQsun}Mpe298t=:KWp}5r 3wiZO弾00f.v1n:$Q[|DDb wEX︀lck AXzʟYc؍pp]8x40@S{ɕnY/c1Xp|Ykcs㟮x-V5 xgn1Z<Xf^gY$`Dϰ\gfͱϑ5X4pP*~6]+[i5r%,1+p ߗɫɛՇPYRdxmȕuBLM $;~Ữр%ȩO Oxo3!HZi]?e2M1sqf.Ҵ]ʿk;aMz{z]yk2WGgqP|_ GJXPS!ӐQb}ևS5Ԅz(QUO *yǭ Gf+݌v8Nӑ?qꘉ撶̙ͼTʘjfﱕ .椴b|~k|B=nN+3jyw fu!B/y @5Y Gk;prz[}JjdgjG5v͡]u"F㛙jʈI`Ja715 +ӚSnVϏ-yPwwuY3*4MG~Ne-h}-W/="ܭ!{#1e^U,A⏩fp cJSMWO lNA-J 5Ԣ~dI&MM[euƛ=aꑤG<8 (2YiPF8jǿJ2_:u\JfkZ11Xyx[Kt'G0|o֔Rh/n7[%}fj,w&uorbUet 3z&\^Db%W;'y]?aCɬgJ`  1uTOnKbJggBԶ}XJ}8{-5n՝n;d;zi/^仢!l2Fzߪ_͆WS?@",w⯚ Fk/]fg49J$urX1,"0Aሱ!aRо᳹ O6%~CռᶙӐ"p;+E~AL8"M 0gDO6 :"c)@dp |VP}K]C O<.~.I臥yHJE()yiQ?\O y(aͷIVOj73 :p)@[KŸȵh}m"|_ =81ޟRwY bŊ+V,+EZbŊ+V4`5`+VXbXXbŊlŊ+VVbŊ+V;ڭ G0s{GKA4 <;?x 6J_1M"r{5}QtțvҪ?_V}3;T OyQyYCj=A#q#>#LsjwCufi1ᝪ*ץYIuB]V_Z4-3} L_oӫo_tӐz8D"v:j.|#7ӪoaKknEbg)!JZcW)U;//h"Tt9D@aBfPÉ.7H?s e :EպdDIR{3AĈNRɧ[oD#D Bj0`w 0`YO7Y'9_X 5$-XNe85ԲyJ@CkOԉGR'4sʴR PI+X5'%.>QVJ=x/XZo"[4՛oS 1B4ّS ӼFڱ8񼆲%9AͫYO9}x3 0jNy2[̀w.[8q/'t0`/ >ɨUQ{“lN۟>n2O44Q&{x # Tױ>7)L?R_[Mz tN$RKWdK{_jFi@U7 (qEM?-T<"Jc?uy?s9ChliBuxw;CIV=$as1Or;-1fXTX| h62Xކ,GMۊ*1 lN\`syʶGR *=#p|ظRh#Eiquz:0]i*3|e,8v.g,֤ͬ`V.67>Ҙy+|s__,n:V^]tlOQifGNe$=wJΎԷUΧKINY&柡E$(z49z$G(&!jZ xA-/ײw+B}I m}`g咞|-ȚY"1xGh {>x9)>j,wt 7%P{3M:K0#ekPWl5>3ĚOXϚ<%joP&059uno1nT~oɼM ya&&yKt^ktsBfO8Ty9|y~*;{M|k{[!Nn`[FEAO;϶4vV2ѝ$̜6櫉䦤sHi;U]ຍ|l6#wal#zJ։a}Zx _㿈! zA yG6wNb0TS|8u71ՉT'<]3t^Е3T#!j*FtOצ!6k||0ifDkpYwnȮCTjipu)_ǖTZͱj,;?m bi 4тhvn8H.)ZҳN aOҧqկ๴spnؾچm n WlgTED*}?h;2x>?Kbg_b]_abd:uz_u)˜.h5{7}yzbޮfxGU/Wn;Rq_B:Ur F3*'>JOU^:@-ԏ'ܚ>w՛lHLPoA-aVʞ]Aj,߂!-]K+,ϜWUNʁz6˝} eSio&[ 1EZ &]V&6̀-_E7.|&#G%QA,]NaF:Ix8ߟƈT'$oiƑz=e{ϕBfs#ljt% ޴ }5Gӌ/[~Q_|cȟFY =lH9x6Q̟Tti3 RCJx"*Mi?qS qo}Gl'K 7k@㿀խ4!pi%,C(/WaW-!R_s}-GBYuyVy0rNu}}*Yg^cJd GtТHϋ2p1Q;=DTJ1r}Ig u%g_],[ XWΜy>@f-y~w\ï$D}KO7t40kJF,+HL7H/^E簝|L_ElP*ToykZܨ?ݔ?eh嬮tl?ae+(;n3rZ򜶯ᨪq~o͸̻7/@OD՜3g$ dTsaX=zغLZ(:fT p6f*R,ῆ{l<eϨ<`øpՆoqrFR$z$항WFkSiC8~?ۤOQWKJY |VIaӶћ188m3ak֦5iʨ +IV ȸA턫ϙv=-;ֽKQk  #v0|ey 7wGesĻx лdan?HVi)+vU l.TL_S,aa}I wBAMjwnCIL73} ow")ņ^y?:밾l}\ĬوcZ4`7i @S yFf h]KFnC~Z!7%M Uy 4ǃĤ\|||xdžžEjA Z&YܸK nq=aW7m<$ߒpvEl#sj.6WNe\.j$qͬXyɿ?hkHƍ .?I.7݂D(эU?㓶s};$V ԁ_ɺ~H=ùKlm{}*z$N/Qtgwx#] IιR?ER6>F=E|7H0sO|͗RtJΈl^wPysf6җvfRXy"~\c!80~eeZBCqՙ""-`+b_͟gV+[8y5}jI"'nUljj.oxnr͂G݃ĹcO,f͢k$;Q A~m*_YT{DK]b5(Ja5_+EC(WjPc+=VI{8]|=X|z2 BlH%G u!Gz*R_)}f5OM JK't[jXK7`r-JrY?*Z~p9y[>D(}5 PIK^I?yҿméA3e&jQ<*-Tsto6dag ;!.g7!PL[t  *|U[NP!PU+yARENP"o;ݧ/`qbKo7Jx/6H]*QaIѽBAtvepYpӭ#pqK?cL8To׶؈'ڠeWk%w1P?w<;WT/'lhR3YTu})-/n\MOI9'zN;lv Y m7*\LPξw$o&TՀA$\Gy,_*y!>'^9.B1]iXDRӓn4,׿nlۭҩAzxPpFlI[Yy:&̼*Sĵy(e)#="I;쑥e\./HHWy5QcIYoj?9AO8݂B1"h$G=&dJ'[q8M2h7l}ۼSs!lP:g WMFe|TIs UKO@-lAٍ׳^#>x ]n&G%.9^G ?Z(wd[x+ǀ[ \\fp׳>c*( 'oU9=MbZؗkk͊b@oYXQWa\ugۅ[PΧ?ٺ@$C-c';-ݻ =Ϡ=aù*͚b+#6s(f.9nPc{7z8RO7Fjz*Y*#ʛVB>qJ%)>^-4ٮe؟ʩT?v񡚭c~LnT\2/P=/ؕ-Oڞxg>;m}V9˟薦lP3{cRҲ8 _Á˕E5_NX_wH=͡GlzT.@L<)#=m؍d6|"+8ƟjC걽x )roQV {߿yC~!P;2NJ}AiVϏ1 ”as'˭92}39Oryt 3 #wg?AiVG tn pCp] $ .zuN!8oFaeK`^f_L:vܩ@:%U_ l 3RG<_p!XYhd?upAT xQ3xU_rk5=ZBŚ׶v }&Rr RnJڣ?'Sb+mZ0^ωplJivš}іּ~R&tʷq"y-WW.(z-U_-'y"U KӺ~*U0A^7sq!)hCjڰusچFӵU1_V':'B@AX7<xV1 IuצJiH\/+kX˖7@h!gD6X/'s& ˗5ˬ(y Š|={S9pmo>Hqqح<:#l/ % W<%Ĝ3,Eq`6Z[SPe1,ſS1|_?`>4Z!2i]?f.9%‚QciZ׏q]rW߰&d}=Vjp]LB^ꋿX˧4$Prd RwLCڤZlSB|fkxL$9^n,֠*&N2WjJ5Zւ~e Qt+V[µqUK(Mt*LkVO Y=?$Ca3Qgc$-6Ukoai~6C%<|c(-Pqg HyjzQnYʖ7 0Wz9_tPXyy-hY ڵqE>[ C CǖqU.HR(}fRKQ&[hPA{*E*1`^IkHnE?ne)@z臵=-;l(#iiwF#O*Df PJd-+sY4&,]-Ȯ^ "N[ ]49E/[QO:0C㣿ts*&(AnI.aV hAvBΈ_jUW ;؊j 'gBfqѓ2p(SJiʆ3 ywrD՟ߙ"xjiܾna::0ǫ2af0̮8ͳQ8.dQJqQ%8@urigoNe5diAjAe=1r2`GUNѾdžX& '<|?7l9(̇c?^=iLuP\z^.dFU5+7j@nTfϙ= 9sw`+P8$wdݕ"OXqQ6T?1S_7bE9 x5k #2;|Z{do9q;N7H%)6)Yճ&y͌?Seêi,c%ղ':iN5yGF1m[Cҭ8aHzL56wuoS9{ࡥ X7<\\ߚs7<܇Rpc|UERk)lֈn#KMVmbD=\^&W_r%:JJ?#v֥6i'ئdjFbI,рC4R'Nxڼ`Ja]uKgR-o//ag]@}2/"Z0C_/+]/mqtQU0fvAoG*Q1­^嬏]9SúF5[>^cT5һ5W^4һ5c!C!K#6\es;W2f}#ӀS~5 f jP5[;$*w7=%QǞ"E -SSnҶ|j!d E9Sre-$:Ynd}2KW`OU76YDnD~T *&VJUhjq-5Bv J7 Fث;6trN_^sKYW|b56ۃlOY<ݜIR6 Gb濧 s e xp"pVekSRXC' n C#1bŅ݂ʎPT =>~4-pqg;>~fh fQN 6O7Ex[ް%w S9.Gؖå;\wBW1,?Jzץ֮ VϲcpMJ-s $u6~X@|?la{F;qSȺuқ*u4]mkV.Y ܧHe2Wp 6:poؑ6!=2Fp ]t-IGן堫М9zoe_ Q lgv O3P\5Lh6Se{e3@"ʤjnWvCxhl%v&m/Iw/1Ob i M6 HRcUЖMM|]8Ъp7toD#e\,f+~8qő4>%mc2W`ԅK>[*O1|,rHJ3:|J󿯺ڧ2c ;>]cXߺt=pZ$|F;LҶjl^)[ɄY?ήw;n3 oI jB_V%QNIN!qhܯ.Ex | Vlh* ]C׏]S~QAv6IL<8INVi ]6t!~e  <`[5%P1W\ 0O} buAKƏ iuH2HBBwMۘLdJK}Rcv)2G9Oeji n^9k 9J5ZQ}\Udt]-=6J8jٿ`F r.\R´-ّC4Uu})k1-Cl!<T#ϷWZ&!U-3\}(o̯k.݂4kƑ{Gn@t03WVlMB }*GkK='nֻngMAX3F1cdIAXAX{nh LG$Ow!nK__ޏTZް$j\x6 Ir4'{ Rph*2ly^Ok$!Ӑv_%t47^.m_MyXoه4g$Q6nÅ/pJnʏp1XN]ơf 2/^RKW|-CӺ~9s.Ä?֞4%ǙD5u:|57G*OR`IJ-\ŜLn(?MO1Dv}DNWBEZ(W?3!,kJsaUB~}X#*!4RM&\|\OQNe5 Ѵ~MۤbH?Xbd_;r{#5=m2tdY/Ir'z<} y[9+1%+y}{!2KQjV2>>+lIZjEМ}Fc =xnC ̭Hzaڵ3,$%JP\C̅8v娷ye&3`%&.}l6*0(2Mj='qsJIl\m@ΣlpʂxeP82Ou0~V!j2KʴfԺ Ik>bEsQ]hءdi *yZ|[wџ IU 8'ȳYL_WG}d^M4HQ;oGJv kǵ7tIn1-QUg7%2wdZ`cO ջ&ZMB/qW3 հ7鶼H-pUMS;Qg4(1Fouf O};x:;nVϏ t-7B]*~kmX97G+ٖ@s'wWӢn ii]]]vTܰq*+Qr%> Nޫ ׃JrQvDi6sY1I-֛Ot1>aAengLR"KَJ ~}Y^t, Z4.hގ^ƳtѶ#l>bw8wE?$l.͊+VX"`7bŊ+V[bŊ+EՀXbŊ"jVXbJ`5`+VXb+1opL;KVG>EXq)_*Kޟ;řMa0n% ת壅:Enu)Έh7+RG)"oIo{7EDzetHDXH)ߟO#)@}!y HNW桟Ai7:IyG~t1C9)@V}3ˈ9Hkm-5HjRoJ5HH"&trJX,w!1UE"'~UQV+#:G ̙3r>06.~qI7Àd# @fW$OJOPpi3X}\|y# #u#yg)#m k+3oAj9ܘ KTϪV5(߾}ٹs'M6ȑ#  מʲ@a%p.d?WLƺ=XOWaj@bJ&S~R"4]%-smځKԻA0ػc#zKHKSwJ%?q/rɏ*_p_X!jd;ؿ)o X|A׏I) Gnh~OߎUT5S-l*0ʀ-m)fԪU;wpRN 'S2?޵\`Pep\\KO~+ V?w~+Pp|Gsom.'W7-_ַtr!a罦'1#?﹝EDX xN}k)J}]k<+ c~ީ*oq /wѪo~;D:yk7x)_k9 )jRoJ5HH"&trJƘbŊ+V뵤+VX/jVXbJ`5`+VXb+VXRX ؊+VX)@ưjۅMN9w0G͑#ńMj=ovDXhBø67 ̒>Ep_)Eѯ7 2#K~7k HbƮe4kzmWQNoa אuzF|ᛧa1D5].Xt{(C˷D:kKSY[)ޟ9{^{m 4Ge)5O#:wIFm+L#,5Y*AV"w GReGNQS&PkAkDm~`A DuJ9A%9j8r zR~j$%)/j:A0€deKÇY귶UizF5ӀdB!7=&\ށL]*0`ț9`[թWc,xi8Ym m\dJPN}3 @F0uꛉ^ _hZ0{K|TNl\t nTl:ߜQʁ7ev]nr(ُ#G".0$!Gfv}5XՇOX=j=͂;,&W.B)ag%lll"'1# Ҷ<,)*lå|7NM/!-scu귨@xGOZȖՑ/domdj[ hpNÝ pw>.,hұ,2{wʫ]dK@Ώ2:4'7Q  l؏CߪmL..P{s= }󗱑H3F):eL:fu]yI 9(vD ޗQ7UhTns~mpͦ|r"-e-49L]jl XͰOů=J -%LgJ{HPH5Qj wkl=vKT^ҙ7eӾu&Q;қ[௱b|dl W : +:DQAG kr *־u&[?ɉm?[kYxz%+ѴE6 ;aGKFOLtSHy—hDM,$sAsvyn}o0ݜU\? 8TژQd|ܫF0f<.o6BKR1{L}Ժ${ K[)r2=}TZ+81ņ)Ȯ+p GJcu'‡FqWսMչL #GqNO%>([T~_Sjs#oT=oT׬Ir[ɯQ<w#ʠ;J{}cfLilPgӶ cIXeʔ߹qM?bw.϶vWKZ_Ց}| Cx!@TN{F +4Ϥ978>j,Y6؜eR;d1plBtF~R :u+F!u@h W},B-6Wyڷ UVQ[;XOk)_{Ө h/2AiT},ՅdnU1Aw[׹]ܮl*嬙ߞ?]w79nrs/ǚh@a-Gfc0ܙ}h[g.jBc # Te~v'ͣkGfv(b:eF CT rnݜ0%[+ЦXՇ?2 ۬:'~)_G%.9^~) Q{pkM׷=<5W߷Tӻa4`Pq\<)ۮQ:6Kssc kdJ xy3mžChZi'~8_{<73Z0R] Ӌϛ.p=KBi=e̗nQ=[-Ii_&Mk\KX OoɕwrY2\(Z/^JZQfd| k\ls>=_E\w}aKOU%xO# nLtW;d-cJ?JE j=u;r{jʴu:'fƮ݄nۈ{(+q YwzCB[*Vmv?ϬbUD/y_=y}IL0FN f/j2ZQAN/?3n|!z2)ݗ\QXvj*֟AU̧*ZMrSm'y!n*M/2wTs#檏; AA*V5j#Gnce)t^CLJFխ ᚰy͕ܔTe%k&\꾜#B3)x5!U,>c[k9>T§*SqG ~Lٷ)Uf wh/HJc3xq<3yƢ0.o*\++0lo"]oxRv iH12 1@K~3 zsxg%xkDB7k4|rXX7/T/CQyx װA$,.>gwZƙ:֦y} (|dھe87vV]K6_縣?ӿcz{xxɢN/2Ui'޴8 DC+S$_,'0_oZK6H;a|+0Wclm 0*kORʋBDZvl8(#Yov}mI? p,TQFÎy|ZrzBߪĦĽ1K_S׳B&stc6Duno`?X!8dha'? Mp`te{ӃÜENxjNDkKNEӜ΍? D>;~jcI8욳xkMWM a}}.ڊ6+x-VhjۯW}M{+hΠTktڞtp9٢鷟9Zw,+VXbE[>Ȋ+VXb0VbŊ+Vk+V9w!0+e-`+VXb+VXR::Pٸs#M,X 5}mܭhZJI/iyRȓ !Z b;U_~5Z)_U(??<AT]\vQݜ!k:|Do?搰n 3&0RߗGgU/cyNc,+H988EmGO/)o5"Ƶ-m^}9`s+/2IW)s*[Sm?H~]/-^@ιPOmGA&R#Vl4&[F0̑f0V3H4(W8N͔(q;ځ,QBȼV.u\mte_JeCy;Gww5>?zl:*M}Nefn]5!/#G2wd'd[R;X `O!&"U{QKhO\߲hqw)$&+5a2ԩ- )Q:K[uꛉF!n7[[AWtƛ$>uGQZ ^kA xgF>f.k(/lnj#9shAKM|<.QcU2@9ĉƘ/+s.Cy`.L#(w*LJ:r'KY柟?1Wv3|=x(4< PyET8jӅ]&,_[mz2ѷ A6.ȓSpp׳v񤢿{ >Oy&v1wcL-'d<鿞'z 'd*ƔBk7=by$WfF|wXM?>j,(ny#ZjZO͠JM. ' #r|*w o俽h8~ƵLI5Ll՞Z$j9UTZ]&-n=sJlX:?QrX ;_cW:6eː|Q/x#J}&Mz=m$eA|'r;7Ǹ*SYkWrzfڡtkҍ fΰ9*_& \ݝa%y=>{sɏ7 BT}+o#zMNGD\¤-Y&_#9\\wӲp!|]s<_ϭEj*-Cs"qwDZKZ ]H>l]lY\Sczhq$׷Ф,U~mzR0ۏ3E:yjrS#Xʏa͞19\]02UCyξt.]֕"4|n78oVJܺ}z_jUƳ+G8jJZ3QcWk%q$fu36d Yիz lǐT\e^}lDx36Im(lMNWӜ\u#T#y>IB\O˙eºW7zI̙¶Ǐ7>R?X qsI"\˺9HB yZE}x5ʤx 2%iͯ=Շ,uF κ o|ٴڦMrz~*Z:{p׆TGR'wDvv/pSmY2<'T2o>^r*0ˌ+B`*SG%{𝩪 !':}# &U9ߺmӔ5wwpv7LхKz+()MĦA--oz,9i9:f.YTö́4lDHF,[beJƠ+HJ'ʙK2%)*/RFH.iP歷O§cVűOH5 1v vO .ȑ#GQ߬`VN붜 $'U0R<:QNu@LɺLǃͺ̌~bEJeEr]׮`ء}WU^8wkKCkr|Xe7ع'Toy!bEc n@FX|j&};ۧ+1JY|,Ҷ%8y"gDj l<[.=̯̜9 hڒV-PK.4EE.SWu?SII_k34OpT}JVQ0vw,#!!ͩl"6D_ {*4;T<ޗBz<>ǬrU(VQ}?PIStE+i@Sr]i: Z:"%׶̕,mi'&j=_U{hw'onp,֭K~5O 8&1V[T{-h+b"7LP f D6\؆BK:8ꝟʉ̘1CEׯ_g֬Y|ʴLZ ;Pd΅z\9s. rwe+8׾:K@nƓ yآo,d9?hzMC:䳏~op:vҢUKV')[~Qf[&) +Jܜ1L؝Dǽ92i`G jvX&0{;}`ʗfhHo呟  \59KL^`$}_n+xİcx8QEǁW'L*khԩN_ ͋e J ;'1 e#882QY<~NF&MĤI}||hڴ2lYA%`)I%z8&py!i%~Ae`Vl% ZqxT3M7TkoPr%GQHekWٟ$OyM򻢃X|ޘΏYַRt:o|o@*ce(f ɏMF!<p\adʼ_K`bExYV&# d僰.bz?WjK^5)^r<]t|43`dh5*#,p|Gpnjyٲ-3f0i$95p$\1'ţ-KphCƉ3EvCFP 7r[\'.nˇPr໫ J#gy(ӐX"_BҸ% "-/YM }.dl*Ng3o!u7ڐh<`x}qeJ|hMC*HV&:_T. no\--sd=aꆗ5W,%v yHC/AҞdͺ?^d͊|yoJwTϩ7ӿ,scѱwf;8w ieݘ$7_-Qb63*#Aa_VPϖXC .s q(L ?XB^\-dzqͅ W5ka/w\um<=N UoߩsW'5wT5}[S ;lk-Hjf6?7w8 +y-:Qz&ԶK<ޖ:^qem.ޓY Y7}_!_\IxJ˙}i'.rbKlo(7cdڨܭ5[7dK17` D˭L'g '|x2*|}k7mJZgдiS6oެq*>6I2d\V$ׁߴY6un'=Aݗ\jD(ƼY~y"q;waMaT (gʼnZwQVmءj[mmV[\ZG[nqO$Q0=@HY~?Er}b̝9X|3,Glzxd+FG+ B2|צ|JQfO |&8`9.^zɹ:Ejjm熼”pX&_@,1 k!Zqe9;!M Oot㣳zM&}W1i^κuW\j3m_2LAk UP} 6n5Kboo;;߻ʐY%2}2;_8CzOX?,j|QԞ͂! [7W"քkÒ%ˑfgpQ=c|(O|?X%y|-cթ88gd nݪJ+#>FF~6bðeV[G4+oR 9 hm}d b_ouezХҬW-GBOXX; >@*('Z_IpyQm_Aa6p}}4W 4$a nkfi68on{!@jWLZW|#\F}ڹ:6 @zcCaѹTj1m5Q{ި(Oq{u-=V&I9U-w}Lw%/+;{φj 4R.9ԭ6b嫦://BlS3kN_,39kGC -ZWV|?CL; ;ga^s{6CbT|2!to7}7{gZ2BٝD,Y谑:cꄵAFj N0g53TցtdqK`^WnY(uGuCiW6gx?ݛ›gزw a[#P{;;{aϹkl[Zt4vK`xWH^x㏿ 1-Z =S/ $:{PJx_s_G#@p7{Gz uZc ceU^spI8ChbsZ΅'9;aej+r6)MaծSsN–ԭ(-ōU7X:;{aDrOQ{_($/[1Ҩ0޷ƒ u01{Rb$eZhlMO0Pv(O{ 8d}67B_-@bpK'Q(}R͙|!ѮmJf F/e=6 BSaF͇޸'0F3Řb_r!ͽn_kۄ}-&cX CdHp>M,U[yZ|+?6kw͸/O>ۍ|[|?gL^=Di Zʷk} 1祡K&@چn%\|Pp PVyka UaDo4ٜkZ@QJƞMڴn E64 ]%RRR Q Wf r.1ok(. _j $ܷf|׈#׭ ~sn[_ C~1HIn)h Ul V{&MޥX\IZ_7zcyZ|M>&_Hɞ؞d$O&>&+֝Qsz\,nw%3@f_}ɔuC{6]t̝FUJ[0f+b|Zd% a /`qPbBM?)l87SIAKlq jdu=ݾ9`'Ƚ~mWx|VmLFU/j:u -No}且nڐjvIuBJfIvǼη?RqN&ÐL]yaLT&ea&6#+ 4gS3(){9^I&'_^UOrTqB `ZҘNri88=N407|T녰IN)38.K5Gƒy8>TX>&Y^Ϻ>%Z}omQQi1VWQ/g*'u p n(MO`MWɩct04Yi:k 86u !2 |" yZIYg< B'o+uʚnOJT  jϊ-CaIM\jl.N]oE Uu >_A)Dl1 @vVip< ŀrB(1S\b? MΕYA{x^`Z#'ʴOz!`cワ-TmRAÅ<+neM5jhv[| JR((޺7a=#Vg|Dܛ& 7%[b%~ؽR8(ɄqB t%~ǤfKؽHq%"z<=a=jjkDDD X#!B7H _>E0 Fʷo4?",g QHCTR؝:ͤ:D{+s-ߏ߈!'jvK_F#pﰨzS_FFix/X8;ibCBݿêaaqʉLH 31Õª;Ј ."߾*j>҈>,e^?ad/ېwnX$ӗ}<*@Y.~8aŅ߰~Q_2ۇz7"GFڹɵ!m۶EVVγgb7mBuoDϷ)Ty8dN @zZb@Zꗥ3)~5d"ǣآ?~CH:/tE#8bK Iб !=|FKQH9^k|8NO=Cё yo:_^r[V#Coa=7?Q׾P;pv+gkU/&[Yq}m۶EYn5]cVgz\^ҶXa+o`®ps3{U#:*p~1rt%_)䉟 3E~Qpj}힭%ߥu?9 lX G'ӗ4_SXQd*=HsB˧X@LT ֨64Ža[ WW.@u,Oqq{- /~}p"fi.>3=`>R `͍0/a~77[bm~{ vATljUylzAǕ`Hv6ge ;e{&66k\Ņ(|D&h,JV%~P\D!n OJFcBXyI[x 7쐙yW2|7O_fcbHS1uN*Bn 6oO6)nrӎd[Q@@6AZǢh,Qi~ |ĖQߐ%o2\_[KL.Nk^rY5vR j\uRcO]|03WZ|Z|n+&ioU }Tۼ}`"վ5ݍnp}%oR_mH~.]: 0Fz/lCxbZބ.AӍk* B EI8.r38$ oOxvN?(0FVQfi\bVI;WTi1lvbA4,ŗkqn܇Y}%/F~+n?FQk|N ׆Y/n`t|mb`)/y(>++.iazQtkx'PeU_Ϸߛ݁cP?7l+{>@?t{"Nmց.HNܹgЪ9les w5-B+_}o,K8sf4rb{߀Bkh2굂Lw&~WWDIyŔ,:Xl_^GAӈm\JSl3Ϸž8\R #9uui짘#N!n;8`9Õy˺:EͰӹxfsv*+ Μ14p& U(PHJrrzk.2 .qA}zXO(D[_: Ff 2o!!AQ1* 1=n*69WNI\2 P}ezƖ5Ƃ$SLXVp&qkKpDC]!cq| ( ,[K0a X|$ ΝO<j??qM ָ)A7EvZb_Щ@އc?]ѪaKfg8:|M]bWf{P*2ѸtƐS؟j?)2Bmi? +'àrSQel3@|+^[bkTˍ0s} fOFvFX>½碘clE}_,;CiUmU5G7 jcT|yϷ W1[*v3F9 MT|Z>?d:xtԀfLl3H 綩Ωs" VVk@水X+7_] {xl›ÁST*UP7rx_c׍I@.wl iJU| %B\Q^v&3NTUb /CGB"V>7qjnNW=$8FN\] |-u%-n oݵ&T$llq1P073925eS D5<ʆ#NU-n| GiUQS}Eƌ5ѝc-`[V[(>#Jtv’,61 gk5HKĺ TϿrtD$ z聘̙3r( ̞=aaaVu˺Fwd^*-qزWDzV uCY[N.c$|b+2B\G@PX9| $WcA5!/WﯿB=Wt}BQÔ fo Lq߽)& |i5zmC\㊗FȭdʲUI뱴hBb;kfk[M\U5uzɷ&T=ֱ.~~U#JJ0'?_9qmʚ).,e/?5]lt_>w|C7Z/ގV=Nk_,!Y+TmS6?W М @cG6>DVe7@rJ}eM껩u]l4o0cԞ7cs+TM5jb3X4:!JdHC )/,̨)p]%5RC]e~*뛬fV6&|lQ{l`X4 yM`kK:VNRCVvߺ(u5XB*[ub:;cWQ~*,D"AHF s]wrСCUG;bd/>oR7WqU]˼Q"TQ=kZn 0$; j\''teE 5+wé=q8'mvgKc8Yw8lMZLXllFh3V/ mm+_D! Y*Ez t\l~nܿX llXJW׻Qb8fcK/mf[5V%~j"eG|6 @D]mn{/ꈞ;q/pI[?#:m k3'']䋁Xa^lY]1:F*Tkrj0Gb$_*߷Kjo,'_b(=]e])e7rDv#nT%`=T tƯlBLdm":c6C=cqhNbIRD{} 4|_foTBmD+MYE?pa`h8 m14:*J]Ue vV|llFFFw:?ZC_NMh6 Wuzǩ, 0 i,2~ĩ6/G,聡ע޸ z7*^W|{ QH`w$(*<';9&&UkF}2Fmn"Q%cQrV3nD_H ߚR@WIY7bcgPy=>0N_dy^S^h%)7R{{Ukb+\rOmmswZ"4R8ʠzjN J%b?w;H"xe6}Qtٓ_7KIH 8wJ%^^^qB\Ih߀1Ks3$dÐ=n֩QA߫Eu60 QPƏ{+B7jNݩx}$Kwbag17 X ?VPUNfm0-Ld/7bDשptG 8fM\_V_pR~zO b㔏iitQ8=~K(B͘@iW->1!$=0^4[#~;17@Hc\;XT/g c@OgpZ|3YNN|9-uw=cP [FSf[O ba ĩCIV'.>cǫpc@/# ÍMF!AhG-a ;>}t41k|s7~K?NL5 HaU|=ʗf-8Y|\ⱏTX)w@Iy̜nLu7 #p2W -::!Fu[iK mWk mhb_ݏ8Ipx7t{Vw [hfk 7kZ!9;kV'1Ep}}f>_WJ~ȿ.~D3QLZ>;_k*7֭O_ H(0ǧo zZ%ca/Z)RQnA̙dm6="w' ԡ:Zg,:s;n/sTSU|'1G!9Um{fa< ;B:c5y~+`}15R ȑxP=ߜ>@nQXAv r K>.p@t:cYʌG% lr'sW2_]{uk>)o3ocBW_& wev( ܪd%WayiVc,$:m&L"K~׈cJ @<7ύ# =Bm83Ң|l eMQukչU] JpW g9j ќw:#uszcP|v\Gڰcѵa xVk!q5{4x/\D'Lk/[tlxUYBb9ccip#N&꼄W՘Da=t+Gi{&c?/Пp &QjSFP';?x\H7ڣob&N8&5 l/W) ܪ ]BK=Z!'J\SڌIJ>}-f_KsO2Bvפu*X6W=OlK)5&Jen<瓊h~9ʣUjă\ Zyqq6ի> S wpszg7%ckGo]V daP9*]Pa F,\EAIX=T?xٚGw=%$^A/[׷r=%G@QeJx{h"T%O|ߘk{ lX[[#5v{P8vx[b(i#t&c=ocE fh ah  -^7%Q0a凪}BN"n8 (+x p?p1]w+ͦl pVu&* 1<Cn=cplR4;yR=ujk ~-Q5Kӷ=kL`8dJ¦(ܢ3Ruۅ0O $\S%e(.-N~ dgw96ť E%-HJԆ USGtU=ncʤ%]J Eׯ_s){l} YoA.28Z׷ljrWL9va0aH q4h L&C'gQ8htgU;=ն\쐑U7;$"iy~j"?=7ńJx_[ 5n{ 9u⎿#]qh:ax37w„X-dIS15jŠ+ 2dzzjL ~:u 9Lʅ-F,MBnavLi2U'j5ػ3 UP4rN8u:t0jQ5r\ s;&#mcthPH 襁*;YUb AX[{ ?<[ǺRqEhn:{fq4 Cvj{m_2\P&GO['46dLNg'(s`7f>czB#B^gv5X%ECuq35]p7Lh\C 9>HJI{_ zՀ b(mcJ :N>`,K;:VoE /Q 8֚3.c0!4\zͨDYC$WfN !:@vl.-[37υ# Qd1 5&ApoQh*M)%4;hs=oHpo[ I٧qǔNfg 3\72-iK柌0dm(rSӔ99pvrR )rpO\2PVr4_W-.-)p2MЏ#{{{ܹs}} z_B:;w ?R { =N&媆'i#zTuydơor9?;F^'WpW S" jt]b~ /<,|y-HFo|T#[Ž+em UPOU`܁2؃Kvo֒P9*emr4(2*;aG?Itō9A~#?p? @ysqIJSٔ 2g&OZ]Y Lt1lpQ^R דhx P8eG0z .ʦ2twl=]o^=; 9ax&C5g_Xzy$k 2j_'_ոMdP7*΍F |Hmt'4& OHPx1k{z?^nī$)huyNG 9ᅜ}Boc ^0 IMʤpj֦7 CO6DbNA1eck'V`miyv KQCsDu^0$hgM*w0z5YXzD=녺-,Cnaf 4g,=DC2ĩ8H!H+I~$^Yy/#oe-߯2*nmP\(* arGqyX~iry4T%_gW竊6P%߀n̨|r5mnc .'߁_7sEN6}x8; ͗ե8Y$GjMwVaۈmoM0h1iZ;MJeX}wxHaplL89t:&a6Sa8Ѡ`Dzyй<,EwԦ v3c Wyf >I27Us&U8եm`d"iXH.~#\[mد֫0[D K&\cֿT>?5O0 Gk̰#sS&__x'_%2u<={2+ܳo"ΜEvmu,Z1"N#}AD\nhq+~ "o|;PbHZ~} ުE'ߢ2Wo!$gXCËs~w|#錟g4e };ip@/U5H#jLf15PhLJgQS_ao0ȷGIt_4]w\#Z; !ZG v`J:hI//s!-?>0Xu?1S^h%Z)/ u14mn(oTអtgcD؀ЦD4`]ho1TbVWSlt%ߨQ SYts%ߨA(32{`$XJcfnmsTKfzQM#c~9͚֦h=W?rV hG:n GIV\6ZciQܹ罴DcS d=]}/HdG $ԊЊ*+/~UMݬ$ dϚp=쫋ga׮]:u5:c:lI@󥿫mV89m0|XKdæ_A$"Xx >,Z` r=6QNa;oJVm)KI_!NYɡp-|u*O;~ +֛&hm Bj.${c^82ZTHr߮6}p}Z'ZU;DDDB۹8Z6!!;Z4i'ӆ!4mɵ0$qÐ@ T{GaE޸\?%W6F @IzSXcW$ ɘP\)FԨOƄ_(Z&"!Ix.ÿE;jDDT ,?̍ j CIENDB`gajim-gajim-1.1.3/gajim/data/gui/000077500000000000000000000000001345766322700164735ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/gui/account_context_menu.ui000066400000000000000000000066721345766322700232710ustar00rootroot00000000000000 False True False _Status True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Personal Events True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False Join _Group Chat True True False True False _Add Contact... True True False _Discover Services True True False _Execute Command... True True False True False _Modify Account... True gajim-gajim-1.1.3/gajim/data/gui/account_creation_wizard_window.ui000066400000000000000000001347551345766322700253400ustar00rootroot00000000000000 True False gtk-preferences True False gtk-apply None server_liststore 0 server_liststore 0 False 12 Gajim: Account Creation Wizard False dialog True False vertical 6 True False False False True False vertical 12 True False 0 You need to have an account in order to connect to the Jabber network. False False 0 True False 0 none True False 12 6 vertical 6 I already have an account I want to _use True True False True 0 True True False False 0 I want to _register for a new account True True False True 0 True use_existing_account_radiobutton False False 1 True False <b>Please choose one of the options below:</b> True False False 1 True False False True False 6 vertical 12 True False 0 <b>Please fill in the data for your existing account</b> True False False 0 True False 6 6 True False 0 _Jabber ID: True username_entry 0 0 True True 1 0 True False 0 @ 2 0 True False True True True server_entrycompletion 3 0 Anon_ymous authentication True True False True 0 True 1 1 3 True False 0 _Password: True 0 2 True True False True 1 2 Save pass_word True True False If checked, Gajim will remember the password for this account True False 0 True True 2 2 2 False True 1 1 True False 1 False True False 6 vertical 12 True False 0 <b>Please select a server</b> True False False 0 True False 6 True False 0 _Server: True False False 0 True False True True server_entrycompletion1 True True 1 False True 1 Anon_ymous authentication True True False True 0 True False True 2 True True True False 6 6 True False 0 Prox_y: True 0 0 True False liststore1 0 1 0 Manage... True True False start True 2 0 Use custom hostname/port True True False True 0 True 0 1 3 True False False 6 True False 0 _Hostname: True custom_host_entry False False 0 True True True True 1 True False 0 _Port: True custom_port_entry False False 2 True True 6 5222 False True 3 0 2 3 True False _Advanced True True True 3 2 True False 2 False True False vertical True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-dialog-warning 5 False True 0 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True True 1 True False 0 Add this certificate to the list of trusted certificates. SHA1 fingerprint of the certificate: True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 True True False 1 3 True False 3 False True False vertical 4 True False 4 False True False vertical True False <b>Connecting to server</b> Please wait... True center True False 0 True False 0.10000000149 False False 1 5 True False 5 False True False vertical True False 12 True False gtk-missing-image False False 0 True False 0.10000000149011612 True True 100 True True 1 True True 0 Connect when I press Finish True True False True 0 True True False False 1 Set my profile when I connect True True False True 0 True True False False 2 6 True False 6 False True True 0 True False 12 end gtk-cancel True True True False True False False 0 gtk-go-back True False True True False True False False 1 gtk-go-forward True True True True False True False False 2 _Advanced True True False True image2 True False False 3 _Finish True True False True image3 True False False 4 False True 1 gajim-gajim-1.1.3/gajim/data/gui/accounts_window.ui000066400000000000000000000061431345766322700222440ustar00rootroot00000000000000 True False True False start vertical True True start never in 400 True True False OptionsBox1 170 True False start False True False True 1 False True 0 True False start False False True True 1 gajim-gajim-1.1.3/gajim/data/gui/add_new_contact_window.ui000066400000000000000000000454711345766322700235500ustar00rootroot00000000000000 I would like to add you to my contact list. 400 True False 18 18 18 vertical 6 top False True center 18 True center True False False 0 True False 6 12 True False end _Jabber ID True 0 2 True False end _Nickname True 0.5 0 3 True False end _Group True 0 0 4 True True True True user@example.org 1 2 True True True True 1 3 True False True True True True Choose or type new group name 1 4 False True end 12 A_ccount True 0 0 False True end _Protocol True 0 0 1 True False 12 False True protocol 1 5 0 False False 0 False True protocol_jid 0 True True 1 1 1 False True 12 account_liststore 1 0 1 1 0 False True 18 3 A_llow contact to view my status True True False True start True True True False False 4 60 True True True 18 etched-in 5 True True word 6 6 6 6 message_textbuffer True True 4 True False crossfade _Save subscription message True True False start True True False True 5 True False True 6 True False You have to register with this transport to be able to add a contact from this protocol. Click on Register button to proceed. True 0 True True 0 _Register True True True False center center True False False 1 True True 18 7 True False True You must be connected to the transport to be able to add a contact from this protocol. False False 8 True False 18 12 end gtk-cancel True True True False True False False 0 gtk-add True True True False True False False 1 False False 9 gajim-gajim-1.1.3/gajim/data/gui/adhoc_commands_window.ui000066400000000000000000000440631345766322700233670ustar00rootroot00000000000000 True False 6 Ad-hoc Commands - Gajim dialog True False vertical 6 400 400 True False False False True False vertical True False Please wait while retrieving command list... False False 0 True False center center True True 1 True False vertical True False <b>Choose command to execute:</b> True False False 5 0 True True 1 1 in True True False browse True True 5 1 True False Check once more True True False True False False end 0 False True 2 end 2 1 True False vertical True False Please wait while the command is being sent... True False False 0 True False center center True True 1 2 True False vertical True False This jabber entity does not expose any commands. False False 0 True False Check once more True True False True False False end 0 False False end 1 3 True False vertical True False <b>An error has occurred:</b> True False False 0 True False Error description... True False False 1 4 True True 0 True False 12 end gtk-goto-first True True True False True False False 0 gtk-go-back True True True False True False False 1 gtk-go-forward True True True False True False False 2 gtk-execute True True True False True False False 3 F_inish True True True True False False 4 gtk-close True True True False True False False 5 False True 1 gajim-gajim-1.1.3/gajim/data/gui/advanced_configuration_window.ui000066400000000000000000000220401345766322700251130ustar00rootroot00000000000000 True False gtk-dialog-warning False 6 Advanced Configuration Editor ace center-on-parent 650 540 dialog True False vertical 6 True False 12 True False Filter: False True 0 True True True True 1 False True 0 True True never in True True True True True 1 1 True False 3 0 none True False 12 0 True True False <b>Description</b> True False True 2 False False gtk-dialog-warning False True 0 False 0 <b>NOTE:</b> You should restart Gajim for some settings to take effect True True True True 1 False True 3 True False 6 end _Reset to default True False True True image1 True False True 0 gtk-close True True True False True False False 1 False True 4 True False gtk-undo gajim-gajim-1.1.3/gajim/data/gui/application_menu.ui000066400000000000000000000100021345766322700223520ustar00rootroot00000000000000 Accounts View
Show Roster win.show-roster <Primary>R Show Offline Contacts win.show-offline <Primary>O Show Active Contacts win.show-active <Primary>Y Show Transports win.show-transports
File Transfer app.file-transfer <Primary>T History app.history
Help
Contents app.content FAQ app.faq Keyboard Shortcuts app.shortcuts Features app.features About app.about
Accounts app.accounts <Primary><Shift>A Start Chat app.start-chat <Primary>N Bookmarks app.bookmarks <Primary>B History Manager app.history-manager Plugins app.plugins Preferences app.preferences <Primary>P Quit app.quit <Primary>Q
gajim-gajim-1.1.3/gajim/data/gui/atom_entry_window.ui000066400000000000000000000226741345766322700226150ustar00rootroot00000000000000 True False New entry received True False 6 vertical 6 True False You have received new entry: False False 0 True False False True 1 True False 6 6 True False True False True 0 Old stories True 1 0 True False True False True 0 Soliloquy True 1 2 True False 0 Feed name: right 0 0 True False True 0 <small>Romeo and Juliet</small> True 1 1 True False 0 Entry: 0 2 True False 0 Last modified: 0 3 True False True 0 2003-12-13T18:30:02Z 1 3 False True 2 True False False True 3 True False gtk-close True True False True False False 0 Next entry True True False True False False end 2 False True 4 gajim-gajim-1.1.3/gajim/data/gui/blocked_contacts_window.ui000066400000000000000000000061221345766322700237230ustar00rootroot00000000000000 True False gtk-remove True False Blocked Contacts dialog True False 5 vertical 250 300 True True 3 never in True True False True False True 0 _Unblock True True False 3 image1 True False False 1 gajim-gajim-1.1.3/gajim/data/gui/change_activity_dialog.ui000066400000000000000000000375311345766322700235230ustar00rootroot00000000000000 False 6 Set Activity 270 dialog True False vertical 6 True False end gtk-cancel True True True False True False False 0 gtk-ok True True True True False True False False 1 False False end 0 Set an activity True True False 0.5 True False False 2 True False True True False vertical True False gtk-missing-image 1 False True False vertical 1 True False gtk-missing-image 1 1 False True False vertical 2 True False gtk-missing-image 1 2 False True False vertical 3 True False gtk-missing-image 1 3 False True False vertical 4 True False gtk-missing-image 1 4 False True False vertical 5 True False gtk-missing-image 1 5 False True False vertical 6 True False gtk-missing-image 1 6 False True False vertical 7 True False gtk-missing-image 1 7 False True False vertical 8 True False gtk-missing-image 1 8 False True False vertical 9 True False gtk-missing-image 1 9 False True False vertical 10 True False gtk-missing-image 1 10 False False True 3 True False True False <b>Message:</b> True False False 0 True False True False True 1 False False 4 cancel_button ok_button gajim-gajim-1.1.3/gajim/data/gui/change_mood_dialog.ui000066400000000000000000000306611345766322700226220ustar00rootroot00000000000000 False 6 270 dialog True False vertical 6 True False end gtk-cancel True True True False True False False 0 gtk-ok True True True True False True False False 1 False False end 0 True False True 6 6 True False <b>Mood:</b> True 0 1 True False <b>Message:</b> True 0 2 True False 0 None 1 1 True True True 1 2 True False True True True False none 0.5 False True False gtk-cancel 1 0 0 0 0 2 False True 0 cancel_button ok_button gajim-gajim-1.1.3/gajim/data/gui/change_password_dialog.ui000066400000000000000000000040641345766322700235240ustar00rootroot00000000000000 220 True False 12 vertical 6 True True False New Password False True 0 True True False True Confirm New Password False True 1 True False True 0 False True 2 gajim-gajim-1.1.3/gajim/data/gui/change_status_message_dialog.ui000066400000000000000000000415251345766322700247140ustar00rootroot00000000000000 False 18 270 330 dialog True False vertical 12 True False 6 end gtk-cancel True True True False True False True 0 gtk-ok True True True True False True False True 1 False True end 0 True False 0 none True False 6 vertical 6 True False True True in True True word 6 6 6 6 True True 0 True False True True False Save this message as a preset True False gtk-save-as False False 1 True True 0 True False center 6 6 12 True False end Preset _messages True message_combobox 0 0 True False end 6 Ac_tivity True activity_button 0 1 True False end M_ood True mood_button 0 2 200 True False True 1 0 True True True 6 True False 6 True False gtk-missing-image False True 0 True False True 0 True True 1 1 1 True True True True False 6 True False gtk-missing-image False True 0 True False True 0 True True 1 1 2 False True 1 True False _Type your new status message True center message_textview True True 2 cancel_button ok_button gajim-gajim-1.1.3/gajim/data/gui/chat_control.ui000066400000000000000000001367031345766322700215230ustar00rootroot00000000000000 110 1 10 10 110 1 10 10 False False True mouse menu True True False False True False True True True none True False <b>1</b> True 0 0 0 True True True none 0 True False <b>2</b> abc True 1 0 True True True none 0 True False <b>3</b> def True 2 0 True True True none 0 True False <b>4</b> ghi True 0 1 True True True none 0 True False <b>5</b> jkl True 1 1 True True True none 0 True False <b>6</b> mno True 2 1 True True True none True False <b>7</b> pqrs True 0 2 True True True none 0 True False <b>8</b> tuv True 1 2 True True True none 0 True False <b>9</b> wxyz True 2 2 True True True none True False <b>*</b> True 0 3 True True True none True False <b>0</b> True 1 3 True True True none True False <b>#</b> True 2 3 True False bold True False Bold italic True False Italic underline True False Underline strike True False Strike True False True False Color True False Font True False True False Clear formatting True 7 7 5 7 1 True True True False vertical False True 0 True False False True 1 60 True in False True True 2 True False False True 3 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True True True Show a list of emojis (Alt+M) none True False face-smile-symbolic False True 0 True True False True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True none formattings_menu True False format-text-bold-symbolic 1 False True 1 False True True False vertical False True 0 True True False True True none vertical adjustment1 audio-volume-muted audio-volume-high audio-volume-low audio-volume-medium False False False False False True 1 True True False True True none vertical adjustment2 audio-mic-volume-muted audio-mic-volume-high audio-mic-volume-medium audio-mic-volume-low False False False False False True 2 # True True True none True True 3 False True end 2 True False False True 3 True True True none True False open-menu-symbolic False True end 4 True False True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True none True False gtk-dialog-authentication 1 False False end 5 True True True Choose encryption none False True end 6 True True False True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK none True False mail-attachment-symbolic 1 False False end 7 False False 4 False True False True 6 False True 160 120 True False True False False True 0 True False vertical True False 320 240 True False True True 0 True True 1 True True True True 0 gajim-gajim-1.1.3/gajim/data/gui/chat_to_muc_window.ui000066400000000000000000000222641345766322700227140ustar00rootroot00000000000000 True False gtk-jump-to True False 5 Invite Friends! dialog True False vertical 6 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK You are now entering a groupchat. Select the contacts you want to invite center False False 4 0 True True in 300 True True guests_store False column 0 column 1 True True 4 1 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK vertical True False Please select a MUC server. center True False False 4 0 True False False True 1 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK MUC server False True 2 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 6 end gtk-cancel True True False True False False 3 0 In_vite True True False image1 True False False 3 1 False True 3 gajim-gajim-1.1.3/gajim/data/gui/choose_gpg_key_dialog.ui000066400000000000000000000115561345766322700233460ustar00rootroot00000000000000 False 6 550 300 dialog True False vertical 6 True False end gtk-cancel True True True False True False False 0 gtk-ok True True True True False True False False 1 False False end 0 True False 6 vertical 6 True False 0 False False 0 True True in True True True True 1 True True 2 button26 button27 gajim-gajim-1.1.3/gajim/data/gui/contact_context_menu.ui000066400000000000000000000255771345766322700232750ustar00rootroot00000000000000 False True False Start _Chat True True False Send Single _Message... True True False Send _File... True True False In_vite to True True False Invite _Contacts True True False True False Send Cus_tom Status True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False E_xecute Command... True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK M_anage Contact True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False _Rename... True False Edit _Groups... True False Assign Open_PGP Key... True False True Add Special _Notification... True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False _Subscription True False True False _Allow contact to see my status True True False A_sk to see contact status True True False _Forbid contact to see my status True True False _Unblock True True False _Block True False True _Unignore True False True _Ignore True False _Add to Roster... True False Remo_ve True True False False _Information True False _History True gajim-gajim-1.1.3/gajim/data/gui/data_form_window.ui000066400000000000000000000442121345766322700223600ustar00rootroot00000000000000 True False True False 3 vertical 3 True False Fill in the form. False False 0 True False False False True True True True False queue none True True False True True in True True False True 0 True False vertical gtk-add True True True True False False 0 gtk-remove True True True True False False 1 True False False False 3 2 gtk-edit True True True True False False 3 True False False True 3 4 gtk-go-up True True True True False False 5 gtk-go-down True True True True False False 6 True False False True 3 7 gtk-clear True True True True False False 8 False True 1 2 False True 1 False 6 Room Configuration 650 450 dialog True False vertical 6 True True etched-in True False True False vertical True False 5 vertical 5 True False True 0 False False 5 0 True False False True 5 1 False True 0 True False False True 5 1 True False 5 vertical 5 False True 2 True True 0 True False 6 end gtk-cancel True True True False True False False 0 gtk-ok True True True False True False False 1 False True 1 gajim-gajim-1.1.3/gajim/data/gui/dubbleinput_dialog.ui000066400000000000000000000151571345766322700226770ustar00rootroot00000000000000 False 6 dialog True False vertical 6 True False end gtk-cancel False True True True False True False False 0 gtk-ok False True True True True False True False False 1 False True end 0 True False 6 vertical 6 True False 12 True False gtk-dialog-question 6 False True 0 True False True True True 1 False True 0 True True True False False 1 True False False False 2 True True False False 3 False True 1 cancelbutton okbutton gajim-gajim-1.1.3/gajim/data/gui/edit_groups_dialog.ui000066400000000000000000000136641345766322700227070ustar00rootroot00000000000000 False 6 Edit Groups True 290 dialog True False vertical 6 True False end gtk-close False True True True False True False False 0 False True end 0 True False False True 2 True False True False True 3 True False 6 True True True True True 0 gtk-add False True True True True False True False False 1 False False 4 True True in True True False True True 5 close_button gajim-gajim-1.1.3/gajim/data/gui/emoji_chooser.ui000066400000000000000000000117101345766322700216570ustar00rootroot00000000000000 True False vertical True True edit-find-symbolic False False False True 0 True False True False vertical True True in 350 300 True False True False vertical True True 0 list True False vertical True True False end 72 edit-find-symbolic True True 0 True False start 12 No Results Found False True 1 not-found 1 True True 1 gajim-gajim-1.1.3/gajim/data/gui/exception_dialog.ui000066400000000000000000000143461345766322700223570ustar00rootroot00000000000000 False center dialog True False 12 12 12 12 vertical 6 True False 20 20 True False center gtk-dialog-error 6 0 0 True False start center True A programming error has been detected. It probably is not fatal, but should be reported to the developers nonetheless. True 60 3 1 0 150 True True True in True True True True False 4 4 False 0 1 2 True True 0 True False 6 end gtk-close True True True True True True True 0 Report Bug True True True True True 1 False True end 1 gajim-gajim-1.1.3/gajim/data/gui/features_window.ui000066400000000000000000000077271345766322700222540ustar00rootroot00000000000000 300 530 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 18 18 18 18 vertical 6 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>List of possible features in Gajim:</b> True 0 False False 0 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True out True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True True 1 True False 3 0 none True False 12 True True 0 True False <b>Description</b> True False True 2 gajim-gajim-1.1.3/gajim/data/gui/filetransfers.ui000066400000000000000000000275171345766322700217150ustar00rootroot00000000000000 False False _Remove True False True Con_tinue True False _Pause True False _Cancel True True False False _Open Containing Folder True False 12 File Transfers dialog True False vertical 6 460 150 True True in True True False file transfers list A list of active, completed and stopped file transfers True True 0 True False 6 end Clean _up True False True True False Remove completed, cancelled and failed file transfers from the list True Remove file transfer from the list. This action removes single file transfer from the list. If the transfer is active, it is first stopped and then removed False False 0 _Pause True False True True False True False False 1 _Cancel True False True True False Cancel the selected file transfer and remove incomplete files True Cancel file transfer Cancels the selected file transfer False False 2 _Close True True True True False Hide the window True False False 3 False True end 1 _Notify me when a file transfer is complete True True False True True When a file transfer is complete show a popup notification False False 2 File Transfers Shows a list of file transfers between you and others gajim-gajim-1.1.3/gajim/data/gui/gc_control_popup_menu.ui000066400000000000000000000124541345766322700234400ustar00rootroot00000000000000 False False True Change _Nickname... True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK _Manage Room True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True Change _Subject... True False Configure _Room... True True False True False _Destroy Room True True False _Minimize on close True True False Notify on all messages False True True False _Request Voice True False True False True _Bookmark True False True False True _History True False _Disconnect True gajim-gajim-1.1.3/gajim/data/gui/gc_occupants_menu.ui000066400000000000000000000166541345766322700225420ustar00rootroot00000000000000 False True False _Send Private Message True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Send _File True True False Occupant Actions True False True False _Voice True True False Mo_derator True True False True False _Member True True False _Admin True True False _Owner True True False True False _Kick True True False _Ban True True False In_vite to True True False True False _Add to Roster True True False _Execute command True True False _Block True True False _Unblock True True False True False _Information True True False _History True gajim-gajim-1.1.3/gajim/data/gui/groupchat_control.ui000066400000000000000000000540401345766322700225710ustar00rootroot00000000000000 True False bold True False Bold italic True False Italic underline True False Underline strike True False Strike True False True False Color True False Font True False True False Clear formatting True True 7 7 5 7 vertical 5 True True 495 True 0 True False 4 vertical False True 0 True False False True 1 200 60 True True in False True True 2 True False False True 3 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True True True none True False open-menu-symbolic False True end 0 True False True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True none True False gtk-dialog-authentication 1 False False end 1 True True True Choose encryption none False True end 2 True True False True none True False mail-attachment-symbolic False False end 3 True True True Show a list of emojis (Alt+M) none True False face-smile-symbolic False True 4 True True False True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True none formattings_menu True False format-text-bold-symbolic 1 False True 5 True False True False True 7 False False 4 True False 100 True True True 4 5 never in True True 1 False False False True True 1 True True 0 gajim-gajim-1.1.3/gajim/data/gui/groups_post_window.ui000066400000000000000000000136061345766322700230130ustar00rootroot00000000000000 True False Create new post dialog True False 6 vertical 4 True False 6 6 True False 0 From: 0 0 True False 0 Subject: 0 1 True True True 1 0 True True True 1 1 False True 0 True True in True True textbuffer1 False True 1 True False gtk-cancel True True False True False False 0 gtk-go-forward True True False True False False 2 False True 2 gajim-gajim-1.1.3/gajim/data/gui/history_manager.ui000066400000000000000000000300611345766322700222250ustar00rootroot00000000000000 False True False _Export True True False _Delete True True False gtk-find False 6 center 650 500 True False vertical 6 True True 200 True True in True True True False True True False vertical 300 True False 20 20 vertical 10 True False center <big><b>Welcome to Gajim History Logs Manager</b></big> True False True 0 True False start This log manager is not intended for log viewing. If you are looking for such functionality, use the history window instead. Use this program to delete or export logs. You can select logs from the left and/or search database from below. True False True 1 True False start <b>WARNING:</b> If you plan to do massive deletions, please make sure Gajim is not running. Generally avoid deletions with contacts you currently chat with. True True False True 2 False True 0 True True in True True True False True True 1 True True in True True True True True 2 True True True True 0 True False 6 True True True True True 0 _Search Database True True True True False image1 True bottom False False 1 False True 1 gajim-gajim-1.1.3/gajim/data/gui/history_window.ui000066400000000000000000000641771345766322700221410ustar00rootroot00000000000000 False True False 12 12 12 12 vertical 6 Display status changes True True False True False True 0 True False False True 1 True True True app.history-manager History Manager False True 2 main 1 False True False 12 12 12 12 vertical 6 True False start Date False True 0 True False start vertical 270 True True False True 0 True False start True expand True True True True False go-first-symbolic True True 0 True True True True False go-previous-symbolic True True 1 True True True True False go-next-symbolic True True 2 True True True True False go-last-symbolic True True 3 True True 2 False True 1 True False start 12 Mode False True 2 Search complete history True True False start True True False True 3 Search selected day only True True False start True search_complete_history False True 4 False Conversation History center False 600 True False 18 18 18 18 vertical 24 True False 6 12 True False start center Chat 0 0 True True Record history for this chat center 3 0 True False center 6 Record History 2 0 400 True False center True liststore1 Ttitle True 1 1 True True 1 0 False True 0 True False vertical True False True False 300 True True edit-find-symbolic False False False True 0 True True True start search_menu True False 6 True False 3 3 False True 0 True False pan-down-symbolic False True 1 False True 1 False True 2 True False vertical True True True more_menu True False view-more-symbolic False True 0 False True end 1 False True 0 True True True vertical True True in True True True True True True True True etched-in 200 True True True True 1 False True 2 gajim-gajim-1.1.3/gajim/data/gui/httpupload_progress_dialog.ui000066400000000000000000000062331345766322700244650ustar00rootroot00000000000000 300 True False 18 vertical 6 True False document-send-symbolic 6 False True 0 True False 6 <placeholder> False True 1 True False <progress> False True 2 True False 6 0.10000000149 False True 3 Cancel Upload True True True center 6 False True 4 gajim-gajim-1.1.3/gajim/data/gui/input_dialog.ui000066400000000000000000000134521345766322700215150ustar00rootroot00000000000000 False 12 dialog True False vertical 6 True False end gtk-cancel False True True True False True False False 0 gtk-ok False True True True True False True False False 1 False True end 0 True False end vertical 12 True False 12 True False gtk-dialog-question 6 False True 0 True False True True True 1 False True 0 True True True False False 1 False True 1 cancelbutton okbutton gajim-gajim-1.1.3/gajim/data/gui/input_text_dialog.ui000066400000000000000000000142341345766322700225600ustar00rootroot00000000000000 False 6 400 dialog True False vertical 6 True False end gtk-cancel False True True True False True False False 0 gtk-ok False True True True True False True False False 1 False True end 0 True False 6 vertical 6 True False 12 True False gtk-dialog-question 6 False True 0 True False True True True 1 False True 0 True True never in True True word True True 1 False True 1 cancelbutton okbutton gajim-gajim-1.1.3/gajim/data/gui/join_groupchat_window.ui000066400000000000000000000445671345766322700234540ustar00rootroot00000000000000 False True True 6 6 6 6 300 300 True True recently_treeview True False recently_liststorex False False True False True column 3 main 1 400 True False 18 18 18 18 vertical 18 True False 6 12 True True Join group chat every time Gajim is started start center True 1 8 True False end center Auto Join right 0 8 True False True end 12 Account right 0 0 True False end Room right 0 2 True False end Server right 0 1 True False True end Password right 0 3 True True center True 1 5 True False end Nickname right 0 5 6 True False vertical 0 4 6 True False vertical 0 6 True True Bookmark group chat start center True 1 7 True False end center Bookmark right 0 7 True False True 12 account_liststore 0 1 1 0 True True True True password 1 3 True False 12 True True True True False True 0 True True True Recently used group chats recently_popover True False document-open-recent-symbolic False True 1 True True True Search group chats on selected server True False system-search-symbolic False True 2 1 2 True False True True True False 1 1 False True 0 True False 12 end gtk-cancel True True True True True True 0 Join True True True True True True 1 False True 2 gajim-gajim-1.1.3/gajim/data/gui/mam_preferences.ui000066400000000000000000000223271345766322700221730ustar00rootroot00000000000000 Always always Roster roster Never never 400 300 True False 18 18 18 18 5 10 True False start 5 start True True True True False list-add-symbolic False True 0 True True True True True False list-remove-symbolic True True 1 True 0 2 True False start 5 True False Default: 0 0 0 True False start False default_store 0 1 0 1 0 0 0 Save True True True end True 1 2 True False 150 True True True True in True True preferences_store 0 Jabber ID True True True 0 True user@example.org 0 Archive True 0.5 True 1 1 -1 0 1 2 gajim-gajim-1.1.3/gajim/data/gui/manage_bookmarks_window.ui000066400000000000000000000563201345766322700237270ustar00rootroot00000000000000 False Group Chat Bookmarks 550 300 dialog True False 18 18 18 18 18 220 True False vertical True True in True True False True True 0 True False False 1 True False True list-add-symbolic False False True False True list-remove-symbolic False False False True 1 True True 0 True False vertical 18 True False 6 6 12 True False end Name True 0 0 0 230 True False True Bookmark Name True True 1 0 True False end 12 _Server True 0 0 1 True False True 12 True 1 1 True False end 12 _Nickname True 0 0 4 True False True 12 True 1 4 True False end Roo_m True 0 0 2 True False True True 1 2 True False end _Password True 0 0 3 True False True False True 1 3 False True 0 True False none True True True False Join chat when connected center 12 True False start Auto Join False True 0 True True end False True end 1 True True True False center 12 True False start Minimize on Auto Join False True 0 True True end False True end 1 True True True False Status messages displayed in chat window center 18 True False start Status Messages False True 0 True False liststore1 0 False True end 1 False True 1 True False end True 12 end Cancel True True True False False False 0 OK True True True True False False False 1 False True 2 False True 1 gajim-gajim-1.1.3/gajim/data/gui/manage_pep_services_window.ui000066400000000000000000000124611345766322700244240ustar00rootroot00000000000000 True False gtk-preferences False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK PEP Service Configuration 350 150 dialog True False vertical True True in True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True True 0 True False 6 end gtk-delete True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False False 0 _Configure True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK image1 True False False 1 gtk-close True True True False True False False 3 False True 6 1 gajim-gajim-1.1.3/gajim/data/gui/manage_proxies_window.ui000066400000000000000000000564511345766322700234350ustar00rootroot00000000000000 HTTP Connect SOCKS5 BOSH False 12 Manage Proxy Profiles False center-on-parent dialog True False vertical 12 True False 12 True False 6 vertical 6 True True in True True False True True 0 True False 6 center gtk-add True True True False True False False 0 gtk-remove True True True False True False False 1 False True 1 False True 0 True False vertical True False 0 none True False 12 6 6 6 True False start _Name: True 0 0 0 True False _Type: True 0 0 1 True True 1 0 True False liststore1 0 1 1 True False <b>Properties</b> True False True 0 True False 0 none True False 12 6 6 6 True False _BOSH URL: True 0 0 0 True True 1 0 True False Proxy _Host: True 0 0 2 Use HTTP prox_y True True False True 0 True 0 1 2 True False Proxy _Port: True 0 0 3 Use proxy auth_entication True True False True 0 True 0 4 2 True False _Username: True 0 0 5 True False Pass_word: True 0 0 6 True True 1 2 True True 1 3 True True 1 5 True True False 1 6 True False <b>Settings</b> True False True 1 False True 1 False True 0 True False 6 12 end gtk-close True True True False True False False 0 False True 1 gajim-gajim-1.1.3/gajim/data/gui/manage_sounds_window.ui000066400000000000000000000176111345766322700232520ustar00rootroot00000000000000 400 370 False 12 Manage sounds center-on-parent dialog True False vertical 6 True True in True True liststore1 Active True 0 Event 1 True True 0 True False 6 True False False False Choose Sound True True 0 True True True Clear File True False edit-clear-all-symbolic False True 1 True True False True False media-playback-start-symbolic True False False 2 False True 1 True False 6 end gtk-close True True True True False False 0 False True end 2 gajim-gajim-1.1.3/gajim/data/gui/message_window.ui000066400000000000000000000065211345766322700220510ustar00rootroot00000000000000 True False False True False 4 True False gtk-missing-image False False 0 70 True False True end True 0 False False 1 False True True True none True False gtk-close 1 False False 2 MessageWindow False 480 440 False True True True gajim-gajim-1.1.3/gajim/data/gui/passphrase_dialog.ui000066400000000000000000000126121345766322700225240ustar00rootroot00000000000000 False 12 Passphrase dialog True False vertical 6 True False end gtk-cancel True True True False True False False 0 gtk-ok True True True True False True False False 1 False False end 1 True False 6 vertical 6 True False True False False 5 0 True True True False True False False 1 True True False True 0.5 True False False 2 False True 0 cancel_button ok_button gajim-gajim-1.1.3/gajim/data/gui/plugins_window.ui000066400000000000000000000460211345766322700221050ustar00rootroot00000000000000 650 500 False 6 Plugins 650 500 dialog True True True False 18 18 18 18 18 200 True False True vertical True True never out True True True True 0 True False False 1 True False Install Plugin from File Install from File… True document-open-symbolic False True True False Uninstall Plugin True list-remove-symbolic False True False True 1 False True 1 400 True False True vertical 18 True False False 18 True False start <Plugin Name> True False True 0 True True True Plugin Settings True False applications-system-symbolic False False end 1 False True 0 True False True error False 6 end False False 0 False 16 True False True word-char 0 False True 0 False False 0 False True 1 True False start <Description> True word-char True 0 False True 2 True False 6 12 True False end start Version 0 0 True False start <empty> True word-char True 0 1 0 True False end start Authors 0 1 True False start <empty> True word-char True 10 0 1 1 True False end start Homepage 0 2 True False start <empty> True word-char 0 1 2 False True 3 False True 2 True False Installed False Plug-in decription should be displayed here. This text will be erased during PluginsWindow initialization. gajim-gajim-1.1.3/gajim/data/gui/popup_notification_window.ui000066400000000000000000000134021345766322700243320ustar00rootroot00000000000000 312 95 False 1 popup False True True False south-east PopupNotificationEventBox True False True False 4 6 68 86 True False False False 0 True False vertical True False 196 True False Event Type True True False True 0 True False False none True False gtk-close 1 False False 1 False True 0 218 64 True False Event desc True False True 1 False True 1 gajim-gajim-1.1.3/gajim/data/gui/preferences_window.ui000066400000000000000000004005171345766322700227310ustar00rootroot00000000000000 1 1440 20 1 10 1 720 12 1 10 Use default applications Custom All chat states Composing only Disabled All chat states Composing only Disabled Never Only when pending events Always Pop it up Notify me about it Show only in roster Detached roster with detached chats Detached roster with single chat Single window for everything Detached roster with chat grouped by account Detached roster with chat grouped by type Always Never Last state None True True False True False 18 18 18 18 vertical 18 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 6 vertical 6 Display a_vatars of contacts in roster True True False If checked, Gajim will display avatars of contacts in roster window and in group chats start True True False False 0 Display status _messages of contacts in roster True True False If checked, Gajim will display status messages of contacts under the contact name, in roster window and in group chats start True True False False 1 Display e_xtra information of contacts in roster (mood, activity, ...) True True False If checked, Gajim will display the mood of contacts in the roster window start True True False False 2 True False 6 True False Sort contacts by status False True 0 in _roster True True False start True True False True 1 in _group chats True True False start True True True True 2 True True 3 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Roster Appearance</b> True False True 0 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True False 12 6 6 12 Spell _checker True False If checked, Gajim will highlight spelling errors in input fields of chat windows. If no language is explicitly set via right click on the input field, the default language will be used for this contact or group chat. start True True 0 3 2 Show message recei_pts True True False start True True 0 4 2 Show _avatar in chat tabs True True False start True True 0 6 2 True False end _Window behavior True right one_window_type_combobox 0 0 50 True False liststore6 0 1 0 50 True False liststore7 0 1 1 True False end _Show roster on startup True right show_roster_on_startup 0 1 _Ignore rich content in incoming messages True True False Some messages may include rich content (formatting, colors etc). If checked, Gajim will just display the raw message text. start 18 True True 0 2 2 Show subject after joining a group chat True True False True 0 5 2 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Chat Appearance</b> True False True 1 True False General False True False 18 18 18 18 vertical 18 True False 0 none True False 12 6 vertical 6 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end When new event is received right False True 0 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK liststore5 0 False True 1 False True 0 Notify me about contacts that sign _in True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK start True True False False 1 Notify me about contacts that sign _out True True False Gajim will notify you via a popup window in the bottom right of the screen about contacts that just signed out start True True False False 2 Allow popup/notifications when I'm _away/na/busy/invisible True True False start True True False False 3 Allow popup/notifications when a chat window is opened True True False start True True False False 4 True False 12 True False end Show notification area icon right False True 0 True False liststore4 0 False True 1 False True 5 True False <b>Visual Notifications</b> True False True 0 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True False 12 6 vertical 6 True False 12 Play _sounds True True False start True True False True 0 Ma_nage... 120 True True True True False True 1 False True 0 Allow sound when I'm _busy True True False start True True False True 1 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Sounds</b> True False True 1 1 True False True Notifications 1 False True False 18 18 18 18 vertical 12 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 0 none True False 12 6 6 12 True False Gajim can send and receive meta-information related to a conversation you may have with a contact. Here you can specify which chatstates you want to display in chat windows. True False end _Display chat state notifications True right displayed_chat_states_combobox 0 1 True False liststore2 0 1 0 True False liststore3 0 1 1 True False Gajim can send and receive meta-information related to a conversation you may have with a contact. Here you can specify which chatstates you want to send to the other party. True False end _Send chat state notifications True right outgoing_chat_states_combobox 0 0 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Chat state notifications</b> True False True 0 2 False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Personal Events 2 False True False 18 18 18 18 vertical 18 True False True 0 none True False 12 6 6 12 _Away after True True False If checked, Gajim will change status to Away when the computer is unused. start True True 0 0 _Not available after True True False If checked, Gajim will change status to Not Available when the computer has not been used even longer start True True 0 1 True False start minutes 2 0 True False start minutes 2 1 True True The auto away status message. If empty, Gajim will not change the current status message $S will be replaced by previous status message $T will be replaced by auto-away timeout True 3 0 True True The auto not available status message. If empty, Gajim will not change the current status message $S will be replaced by previous status message $T will be replaced by auto-not-available timeout 3 1 50 True True 12 adjustment2 1 12 1 0 50 True True 20 adjustment1 1 20 1 1 True False <b>Auto Status</b> True False False 0 True False 0 none True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 12 6 vertical 6 True False 12 True False end Ask status message when I right False False 0 True False 12 Sign _in True True False start True True False False 0 Sign _out True True False start True True False False 1 False False 1 False False 0 True True If enabled, Gajim will not ask for a status message. The specified default message will be used instead. in True True default_message_liststore Status 1 Default Message True True 2 Enabled 3 True True 1 True False <b>Status Messages</b> True True True 1 True False 0 none True False 12 6 6 12 True True True True in True True status_message_liststore False 0 0 0 True True True never never in 21 True True word 0 1 True False start 12 start gtk-new True True True False True False False 0 gtk-delete True True True False True False False 1 1 0 True False <b>Preset Status Messages</b> True True True 2 3 True False Status 3 False True False 18 18 18 18 vertical 12 True False 6 12 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK start Themes 0 0 2 True False end _Theme True right theme_combobox 1 1 200 True False 2 1 Ma_nage... 120 True True False Configure color and font of the interface True 3 1 True False end _Dark Theme True right dark_theme_combobox 1 2 True False System Enabled Disabled 2 2 True False start Emojis 0 3 2 True False end _Emoji Theme True right emoticons_combobox 1 4 True False 2 4 True False start Icons 0 6 2 True False end _Status iconset True right iconset_combobox 1 7 True False 2 7 Use transports _icons True True False If checked, Gajim will use protocol-specific status icons. (e.g. A contact from ICQ will have the equivalent ICQ icon for status online, away, busy, etc...) start True True 2 8 True False end 1 5 _Convert ASCII Emojis True True False start True True 2 5 False True 0 4 True False Style 4 False True False 18 18 18 18 vertical 18 True False 0 1 none True False 12 6 6 12 True False end Audio input device 0 0 True False end Audio output device 0 1 True False 1 0 True False 1 1 True False <b>Audio</b> True False True 0 True False 0 0 none True False 12 6 6 12 True False end Video input device 0 0 True False end Video output device 0 1 True False end Video framerate 0 2 True False end Video size 0 3 View own video source True True False start True 0 4 2 True False 1 0 True False 1 1 True False 1 2 True False 1 3 True False <b>Video</b> True False True 1 True False 0 0 none True False 12 6 6 12 True False start STUN server right 0 0 True True False start True 1 0 True True STUN server hostname. If none given, Gajim will try to discover one from server. 2 0 True False <i>(example: stun.iptel.org)</i> True 3 0 True False <b>Connection</b> True False True 2 5 False True False Audio/Video 5 False True False 18 18 18 18 vertical 18 True False 0 none True False vertical 12 200 True False start 12 6 liststore1 0 False True 0 False 0 none True False 12 6 6 12 True False end _Mail client True right 0 1 True False end _Browser True right 0 0 True False end _File manager True right 0 2 True True 1 0 True True 1 1 True True 1 2 True False <b>Custom</b> True False True 1 True False <b>Applications</b> True False True 0 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 none True False 12 6 vertical 6 _Ignore events from contacts not in the roster True True False If checked, Gajim will ignore incoming events from unauthorized contacts. Use with caution, because it blocks all messages from any contact that is not in the roster start True True False True 1 Allow client / _OS information to be sent True True False If checked, Gajim will allow others to detect the operation system you are using start True True False True 2 Allow local system time information to be sent True True False If checked, Gajim will allow others to detect the time on your system start True True False True 3 Allow my _idle time to be sent True True False start True True False True 4 True False 12 True False Global proxy right 0.01 False True 0 120 True False liststore8 0 False True 1 _Manage... 120 True True True True False True 2 False True 5 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK <b>Privacy</b> True False True 1 True False 0 none True False 12 6 vertical 6 _Log status changes of contacts True True False start True True False True 0 Enable debug logging True False True start True True False True 1 True False <b>Miscellaneous</b> True False True 2 True False 0 none _Open... 120 True True False start 12 6 True True False <b>Advanced Configuration Editor</b> True False True 3 6 True False Advanced 6 False gajim-gajim-1.1.3/gajim/data/gui/privacy_list_window.ui000066400000000000000000001047541345766322700231440ustar00rootroot00000000000000 100 1 1 10 none both from to True False 6 Privacy List dialog True False vertical True False vertical True True False <i>Privacy List</i> True False False 0 Active for this session True True False True 0.5 True False False 1 Active on each startup True True False True 0.5 True False False 2 False True 0 True False False False 5 1 True False <b>List of rules</b> True False False 5 2 True False liststore3 0 False True 5 3 True False True gtk-add True True False 5 True False False 0 gtk-remove True True False 5 True False False 1 gtk-edit True True False 6 True False False 2 False True 4 False True 5 vertical True False False True 5 0 True False <b>Add / Edit a rule</b> True False False 5 1 True False True False vertical True Allow True True False True 0.5 True False False 0 Deny True True False True 0.5 True edit_allow_radiobutton False False 1 False True 0 True False vertical True True False 5 JabberID True True False True 0.5 True False False 5 0 True True False True 5 1 False True 0 True False 5 all in the group True True False True 0.5 True edit_type_jabberid_radiobutton False False 5 0 True False liststore2 0 False True 5 1 False True 1 True False 5 all by subscription True True False True 0.5 True edit_type_jabberid_radiobutton False False 5 0 True False liststore1 0 False True 5 1 False True 2 True False 10 All True True False True 0.5 True edit_type_jabberid_radiobutton False False 0 False False 3 False True 1 True False vertical True to send me messages True True False True 0.5 True False False 0 to send me queries True True False True 0.5 True False False 1 to view my status True True False True 0.5 True False False 2 to send me status True True False True 0.5 True False False 3 All (including subscription) True True False 0.5 True False True 4 False True 2 False True 2 True False True True False True False Order: False False 5 0 True True adjustment1 1 False True 1 False True 0 gtk-save True True False 5 True False False 1 False True 3 False True 5 True False False True 6 True False 6 end gtk-close True True True False True False False 0 False True 7 gajim-gajim-1.1.3/gajim/data/gui/privacy_lists_window.ui000066400000000000000000000211241345766322700233140ustar00rootroot00000000000000 True False 12 window1 dialog True False vertical 6 True False 12 True False Privacy Lists: 0 False False 0 True False liststore1 0 False True 1 False True 0 True False vertical 6 True False spread gtk-delete True True False 5 True False False 0 gtk-edit True True False 5 True False False 1 False False 0 True False True True False True 0 gtk-new True True False 5 True False False 1 False False 1 False True 1 True False end gtk-close True True False 5 True False False 0 False True 2 gajim-gajim-1.1.3/gajim/data/gui/profile_window.ui000066400000000000000000001761151345766322700220740ustar00rootroot00000000000000 True False vertical True False 6 6 6 6 True True False 18 18 18 18 vertical 18 True False 18 150 True False vertical 6 True True False True False True False gtk-missing-image -1 True True True True Clear Avatar end start 6 6 6 6 True True False window-close False False 0 140 140 True True False True start start True True False center vertical 18 True False 10 avatar-default 6 False True 0 True False Set Avatar… False True 1 False False 1 False True 0 True False 6 12 True False end Full Name True right 0 2 True True True 1 1 True True True 1 2 True False end Nickname True right 0 1 True False end 6 12 Account True right 0 0 True False start 2 6 12 1 0 True True 1 False True 0 True False 6 12 True True True 1 0 3 True True 1 1 3 True False end Phone No. True right 0 3 True True 1 3 True True 3 3 True False Format: YYYY-MM-DD False True False end Birthday True right 2 3 True False end Homepage True right 0 0 True False end E-Mail True right 0 1 True False end Jabber ID True right 0 2 True True 1 2 3 False True 3 True False Main False True False start 18 18 18 18 6 12 True False end Family True right 1 1 True True 2 1 True False end Given True right 3 1 True True 4 1 True False end Middle True 1 2 True False end Prefix True right 1 3 True True 2 2 True True 2 3 True False end Suffix True right 3 3 True True 4 3 True False end Street True right 1 5 True True True 2 5 True False end Extra Address True right 3 5 True True True 4 5 True False end City True right 1 6 True False end State True right 1 7 True True 2 7 True True 2 6 True True 4 6 True False end Postal Code True right 3 6 True True 4 7 True False end Country True right 3 7 True False start 12 <b>Address</b> True 0 4 5 12 True False 0 1 True False start <b>Name Details</b> True 0 0 5 1 True False Personal 1 False True False 18 18 18 18 vertical 18 True False 6 12 True False end Company True right 0 0 True True True 1 0 True False end Department True 2 0 True True True 3 0 True False end Position True right 0 1 True True 1 1 True True 3 1 True False end Role True right 2 1 False True 0 True False start 6 12 True False end E-Mail True right 1 5 True True 2 5 3 True False end Phone No. True right 1 6 True True 2 6 True False end Street True right 1 1 True True 2 1 True False end Extra Address True right 3 1 True True 4 1 True False end City True right 1 2 True True 2 2 True False end Postal Code right 3 2 True True 4 2 True True 2 3 True False end State True right 1 3 True True 4 3 True False end Country True right 3 3 True False start <b>Address</b> True 0 0 5 True False start 12 <b>Contact</b> True 0 4 5 12 True False 0 1 False True 1 2 True False Work 2 False True True 6 6 6 6 in 70 True True word 6 6 6 3 True False About 3 False False True 0 True False 6 6 6 6 12 True False False False 0 True False center 0.10000000149 False False 1 True False end True 12 end gtk-cancel True True True False True False False 0 gtk-ok True True True False True False False 1 False True 2 False True 1 gajim-gajim-1.1.3/gajim/data/gui/progress_dialog.ui000066400000000000000000000060101345766322700222120ustar00rootroot00000000000000 False dialog True False vertical 6 True False end gtk-close True False True True False True False False 0 False False end 0 True False True False False 2 True False 0.10000000149 False False 3 close_button gajim-gajim-1.1.3/gajim/data/gui/remove_account_window.ui000066400000000000000000000172431345766322700234410ustar00rootroot00000000000000 True False gtk-delete False 6 dialog True False 3 vertical 6 True False 6 True False gtk-dialog-question 6 False False 0 True False 0 none True False 12 6 vertical 6 Remove account _only from Gajim True True False True 0 True True False False 0 Remove account from Gajim and from _server True True False True 0 True remove_only_radiobutton False False 1 True False <b>What do you want to do?</b> True False False 1 False False 0 True False 6 12 end gtk-cancel True True True False True False False 0 _Remove True True True False image1 True False False 1 False False 1 gajim-gajim-1.1.3/gajim/data/gui/roster_item_exchange_window.ui000066400000000000000000000155751345766322700246340ustar00rootroot00000000000000 False Roster Item Exchange dialog True False 6 vertical 8 True False <b>someone@somewhere.com</b> would like you to <b>add</b> some contacts in your roster. True center True False True 4 0 True True True True False center False textbuffer1 False True 1 True True True True True False True 2 True False 12 end gtk-cancel True True True True False False 0 True True True True False 3 True False 1 gtk-ok False True 0 True False 0 _OK True False True 1 False False 1 False True 3 gajim-gajim-1.1.3/gajim/data/gui/roster_window.ui000066400000000000000000000216321345766322700217430ustar00rootroot00000000000000 online online online True chat chat chat True away away away True xa xa xa True dnd dnd dnd True invisible invisible invisible True SEPARATOR None None True Change Status Message… gajim-kbd_input status False SEPARATOR None None True offline offline offline True RosterWindow 85 200 False Gajim roster 250 400 True False vertical True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK vertical True True False edit-clear False True 0 True True never True True True False True True True 1 True False status_liststore 3 1 5 end 3 0 False True 2 False True True True 1 gajim-gajim-1.1.3/gajim/data/gui/search_window.ui000066400000000000000000000162661345766322700217010ustar00rootroot00000000000000 True False gtk-add True False gtk-find True False gtk-dialog-info False 12 Search dialog True False vertical 6 True False vertical True False Please wait while retrieving search form... False False 0 True False 0.10000000149 False False 1 False True 0 True False 6 end _Add contact False True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True image1 True False False 0 _Information False True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True image3 True False False 1 _Search True True True False image2 True False False 2 gtk-close True True True False True False False 3 False True 1 gajim-gajim-1.1.3/gajim/data/gui/send_file_dialog.ui000066400000000000000000000105011345766322700222760ustar00rootroot00000000000000 True False 6 6 True True True never in True False True False True none False 0 1 2 True False Description: 0 0 2 2 40 True True True never in True True word-char 0 3 2 Select Files True True True start 0 4 Send True True True end 1 4 True False Files: 0 0 0 2 gajim-gajim-1.1.3/gajim/data/gui/service_discovery_window.ui000066400000000000000000000251331345766322700241540ustar00rootroot00000000000000 True False gtk-jump-to False 6 Service Discovery 550 420 dialog True False vertical 6 False False 0 True False 6 True False _Address: True False True 0 True False center True True True True True 1 G_o True True True True False image1 True False True 2 False True 1 True True etched-in True True False True True 2 True False 12 True False True 0.10000000149 False False 0 True False True True 1 True False 6 gtk-close True True True True False True False False end 0 False True 2 False True 2 3 gajim-gajim-1.1.3/gajim/data/gui/shortcuts_window.ui000066400000000000000000000300731345766322700224620ustar00rootroot00000000000000 1 chat Chat Shortcuts 1 Message composition 1 Return Send the message 1 <shift>Return <ctrl>Return Add new line 1 <alt>m Select an emoji 1 Tab Complete a command or a nick 1 <ctrl>Up Previously sent message 1 <ctrl>Down Next sent messages 1 <ctrl><alt>Up Quote previous message 1 <ctrl><alt>Down Quote next message 1 <ctrl>u Clear message entry 1 Recent history 1 <shift>Page_Up Scroll up 1 <shift>Page_Down Scroll down 1 <ctrl>l Clear 1 Tabs 1 <alt>Left <ctrl>Page_Up Switch to the previous tab 1 <alt>Right <ctrl>Page_Down Switch to the next tab 1 <Alt>1...9 Switch to the first - ninth tab 1 <ctrl><shift>Tab Switch to the previous unread tab 1 <ctrl>Tab Switch to the next unread tab 1 Escape <ctrl>w <ctrl>F4 Close chat 1 roster Roster Shortcuts 1 General 1 <ctrl><shift>a Accounts 1 <ctrl>p Preferences 1 <ctrl>t File transfers 1 <ctrl>n Start a new chat 1 <ctrl>j Join a group chat 1 <ctrl>s Set the status message 1 <ctrl>q Quit Gajim 1 Appearance 1 <ctrl>o Show offline contacts 1 <ctrl>y Show only active contacts 1 <ctrl>k Enable roster filtering 1 Contacts 1 <ctrl>i Contact information 1 F2 Rename contact 1 Delete Delete contact gajim-gajim-1.1.3/gajim/data/gui/single_message_window.ui000066400000000000000000000305451345766322700234150ustar00rootroot00000000000000 True False gtk-ok True False gtk-ok True False gtk-jump-to False 6 550 280 True False vertical 6 True False 3 3 True False True 0 From: 0 0 True False True 0 To: 0 1 True False Subject: 0 2 True True True True 1 0 2 True True True True 1 1 2 True True True 1 2 True False 0 2 2 False True 0 True True True in True True 1 True True True in True True word True True 2 True False 12 end gtk-close True True True False True True False False 0 gtk-cancel True True True False True True False False 1 Sen_d True True True False True Send message image3 True False False 2 _Reply True True True False True Reply to this message image1 True False False 3 _Send & Close True True True False True Send message and close window image2 True False False 4 False True 6 3 gajim-gajim-1.1.3/gajim/data/gui/start_chat_dialog.ui000066400000000000000000000042461345766322700225130ustar00rootroot00000000000000 True False 18 vertical 6 True True True True edit-find-symbolic False False False True 0 True True never in True False StartChatListBox True False browse False True True 1 gajim-gajim-1.1.3/gajim/data/gui/subscription_request_window.ui000066400000000000000000000151771345766322700247300ustar00rootroot00000000000000 True False True False _Start Chat True True False _Information True True False 18 18 18 18 vertical 5 True False False False 0 100 True True 5 in True True False word False True True 1 True False 5 12 end _Close True True True False True False False 0 _Deny True True True False Deny authorization from contact so he or she cannot know when you're connected True False False 1 True True True subscription_request_popup_menu False True False applications-system-symbolic True True 2 Au_thorize True True True False Authorize contact so he or she can know when you're connected True False False 3 False False 2 gajim-gajim-1.1.3/gajim/data/gui/synchronise_select_account_dialog.ui000066400000000000000000000111241345766322700257670ustar00rootroot00000000000000 False 12 Synchronise contacts 350 300 dialog True False vertical 6 True False end gtk-cancel True True True False True False False 0 gtk-ok True True True False True False False 1 False False end 0 True False Select the account with which you want to synchronise False False 2 150 True True in True True True True 3 cancel_button ok_button gajim-gajim-1.1.3/gajim/data/gui/synchronise_select_contacts_dialog.ui000066400000000000000000000110251345766322700261510ustar00rootroot00000000000000 False 12 Synchronise : select contacts 400 300 dialog True False vertical 6 True False end gtk-cancel True True True False True False False 0 gtk-ok True True True False True False False 1 False False end 0 True False Select the contacts you want to synchronise False False 2 150 True True in True True True True 3 cancel_button ok_button gajim-gajim-1.1.3/gajim/data/gui/systray_context_menu.ui000066400000000000000000000076221345766322700233470ustar00rootroot00000000000000 False True False Sta_tus True True False _Start Chat... True True False Join _Group Chat True True False Send Single _Message... True True False True False Show All Pending _Events True True False Mute Sounds True True False True True False _Preferences True True False True False _Quit True gajim-gajim-1.1.3/gajim/data/gui/themes_window.ui000066400000000000000000000177161345766322700217220ustar00rootroot00000000000000 False True True never in 260 False True False True False none True False 6 6 True True never in 150 True True theme_store Themes True 0 0 0 True False True True True True False list-add-symbolic 1 False False 0 True False True True True False list-remove-symbolic 1 False False 1 0 1 True True True never in True False 200 True False True none False 1 0 True False True True True popover1 True False list-add-symbolic 1 False True end 0 1 1 gajim-gajim-1.1.3/gajim/data/gui/tooltip_gc_contact.ui000066400000000000000000000123201345766322700227060ustar00rootroot00000000000000 True False 5 True False start start 0 0 2 True False start start True word-char 40 0 1 2 True False start start Jabber ID: 0 3 True False gtk-missing-image 2 0 7 True False start start Resource: 0 4 True False start start 0 5 2 True False start start 0 2 2 True False start True 0 6 2 True False start True 1 4 True False start True 1 3 gajim-gajim-1.1.3/gajim/data/gui/tooltip_roster_contact.ui000066400000000000000000000270721345766322700236450ustar00rootroot00000000000000 True False start 5 True False start start True 0 0 2 True False start start Jabber ID: 0 4 True False gtk-missing-image 2 0 13 True False start start Resource: 0 5 True False start start 0 1 2 True False start start True 1 5 True False start start True 1 4 True False start start Status: True 40 0 2 True False start start Idle since: 0 12 True False start start True 1 12 True False start start Mood: 0 6 True False start start Activity: 2 0 7 True False start start Tune: 0 8 True False start start Location: 0 9 True False start start True 1 6 True False start True 1 7 True False start start True 1 8 True False start start True 1 9 True False start start OpenPGP: 0 10 True False start start True 1 10 True False start start Subscription: 0 11 True False start start True 1 11 True False start start True True 30 1 2 gajim-gajim-1.1.3/gajim/data/gui/vcard_information_window.ui000066400000000000000000002365771345766322700241510ustar00rootroot00000000000000 False 12 Contact Information False dialog True False vertical 12 True True start True False False 0 True False True False 0.98 start 12 12 8 8 6 6 True False end start Jabber ID True 0 0 True False end start Resource True 0 1 True False end start Status True 0 2 True False end start Client True 0 3 True False end start System True 0 4 True False end start Contact time True 0 5 True False start start 5 True True 1 0 True False True False True False start start 5 True True 1 1 True False start start 5 True True 1 3 True False start start 5 True True True 1 4 True False start start 5 True True 1 5 False True start User avatar True 2 0 False True Configured avatar True 2 0 False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True start start gtk-missing-image 2 1 7 True False end start Ask True 0 7 True False end start Subscription True 0 6 True False start start 5 True word-char True 20 30 1 2 True False start start 5 True 1 6 True False start start 5 True 1 7 True False start False False True start start gtk-missing-image 2 1 7 True False Contact False True False start 12 12 8 8 6 6 6 True False Full Name True start 1 0 0 True False True 5 True 0 1 0 True False Nickname True 1 2 0 True False True 5 True 0 3 0 True True start start True False start 25 12 3 3 6 6 True False Street True 1 0 0 True False City True 1 0 1 True False State True 1 0 2 True False True 5 True 0 1 0 True False True 5 True 0 1 1 True False True 5 True 0 1 2 True False Extra Address True 1 2 0 True False Postal Code True 1 2 1 True False Country True 1 2 2 True False True 5 True 0 3 0 True False True 5 True 0 3 1 True False True 5 True 0 3 2 True False <b>Address</b> True 0 0 0 2 4 True False Homepage True 1 0 3 True False E-Mail True 1 0 4 True False Phone No. True 1 0 5 True False True 5 True 0 1 5 True False True 5 True 0 3 5 True False Format: YYYY-MM-DD False True False Birthday True 1 2 5 True True start start True False start 25 12 3 3 6 6 True False Family True 1 0 0 True False Middle True 1 0 1 True False Prefix True 1 0 2 True False True 5 True 0 1 0 True False True 5 True 0 1 1 3 True False True 5 True 0 1 2 True False Given True 1 2 0 True False Suffix True 1 2 2 True False True 5 True 0 3 0 True False True 5 True 0 3 2 True False <b>Name Details</b> True 0 0 0 1 4 button True True True start none 0 1 3 3 button True True True none 0 1 4 3 1 True False Personal Info 1 False True False start 12 12 8 8 6 6 6 True False Company True 1 0 0 True False start True 5 True end 0 1 0 True False True Department True 1 2 0 True False True 5 True end 0 3 0 True False Position True 1 0 1 True False 5 True end 0 1 1 True False Role True 1 2 1 True False 5 True end 0 3 1 True True start start True False start 21 12 6 6 True False Street True 1 0 0 True False City True 1 0 1 True False State True 1 0 2 True False Extra Address True True 1 2 0 True False Postal Code True 1 2 1 True False Country True 1 2 2 True False start True 5 True 0 1 0 True False True 5 True 0 1 1 True False True 5 True 0 1 2 True False True 5 True 0 3 2 True False True 5 True 0 3 1 True False True 5 True 0 3 0 True False <b>Address</b> True 0 0 0 2 4 True False E-Mail True 1 0 3 True False Phone No. True 1 0 0 4 True False 5 True 0 0 1 4 3 button True True True start none 0 1 3 3 2 True False Work 2 False True True 6 in 70 True True False word False 3 True False About 3 False True True 6 in 70 True True word 4 True False Comments 4 False False True 1 True False True False 0.10000000149 False False 0 True False end gtk-close True True True False True False False 0 False True end 1 False True 2 gajim-gajim-1.1.3/gajim/data/gui/voip_call_received_dialog.ui000066400000000000000000000045501345766322700241730ustar00rootroot00000000000000 False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 5 False center-on-parent dialog True question yes-no <b><big>Incoming call</big></b> True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK vertical 2 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end False False end 0 gajim-gajim-1.1.3/gajim/data/gui/xml_console_window.ui000066400000000000000000000134071345766322700227500ustar00rootroot00000000000000 True False vertical True True True vertical 400 True True in True True False False True False 150 True True in True True False False False True 0 actionbar True False False True end 1 True False XML Console False True True True start center True False start True False none True True True False Message True True True False Presence True True True False Iq True True True Presets popover gajim-gajim-1.1.3/gajim/data/gui/zeroconf_context_menu.ui000066400000000000000000000024011345766322700234440ustar00rootroot00000000000000 False True False _Status True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False _Modify Account... True gajim-gajim-1.1.3/gajim/data/gui/zeroconf_information_window.ui000066400000000000000000000463061345766322700246640ustar00rootroot00000000000000 False 12 Contact Information False dialog True False vertical 12 True True 0 True False False 0 True False True False 6 12 True False 6 6 True False 0 0 Local jid: 0 0 True False 0 0 Resource: 0 1 True False 0 0 Status: 0 2 _Log conversation history True True False True 0 True True 0 3 2 True False True 0 0 5 5 True 1 0 True False False True False True 0 0 5 5 True 1 1 True False True False True 0 0 5 5 True 1 2 False True 0 True False vertical True False False True False 0 False False 0 False True 1 True False 0 0 Contact False True False 6 6 6 True False 0 0 First Name: 0 0 True False 0 0 Last Name: 0 1 True False 0 0 Jabber ID: 0 2 True False 0 0 E-Mail: 0 3 True False True 0 0 5 5 True 1 0 True False True 0 0 5 5 True 1 1 True False True 0 0 5 5 True 1 2 True False True 0 0 5 5 True True 1 3 1 True False Personal 1 False False True 1 True False end gtk-close True True True False True False False 0 False True 2 gajim-gajim-1.1.3/gajim/data/icons/000077500000000000000000000000001345766322700170225ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/000077500000000000000000000000001345766322700204615ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/128x128/000077500000000000000000000000001345766322700214165ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/128x128/apps/000077500000000000000000000000001345766322700223615ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/128x128/apps/org.gajim.Gajim.png000066400000000000000000000255461345766322700260060ustar00rootroot00000000000000PNG  IHDR>asBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATxyW}?Ջ6۲%Yca1 2&rIr2I&ɐ$9$'d90ќĖ$l `l,[^/-jU^zz{oݪWuRxE[xIV^"\^"\Œ=&-&`߯3 rpvD:{v+x5p/v W/8٭ S}n:c&0f?ZkqY ?]ǀ?-]&!_#`=@V^6WDMn( C583cɝ?qtA=՝?[?${CTǩ}B!4FkI&J%CRn kwHy ""Jgw DsT' :߬D>@x^i0:ts=?F3<_3;^i]Lvp>f P9 (eT *q~>/  2tOQJtz#(©|t]9>Rh~AZTv24m_w"WVx}z>H?5#G(EKnEK\ZH!uoaF3בYW(d8/7ix+wVzv.u΄uX{a-g'zeSbdfg V+yu!b{{_@-EW=VB.}$ #d: AKnETABq͏{iavXo7|?òeOρDvDJQµU)H@y!\@C哀Ƈ7U7?!nT  ?òeM=U4 ؅"R 0p&zN4c-~.jh*6Ag+E[ޏR =,;YF詍La @e{@ɛ̫}:v[lVD*Lbѳj&ތ,J-P;0 SyVYTF`lZ qNh59ts$Lϴd9`+7.Nua0|̍ΜB8s·U8F*l \zWmmz$˙^ɬVR( o^CWJ<bLsU$fzE3-'Y@wVݫ"~ 0p)Wi3mz$˞Fb" A@k|\y9p4fkwc򶉋;b$KXMl@.J3||o_!(O[c>b_?LiV3 /PZDp+}w=ND"1Z?HB-Ъ!6D4T@\J7=rkJgs R!n*B *8Su4t[k@kH֬!EKęC,=T盞i9'1ϑ}м.`;D 4N@OoH"E-PwF#齈TxI,@=`!л#⃏qH !4O oLnh;hc T 4sp),_ lrxRx6Y!E`7σ8[Q1YQnP󛏵V 8BYmɽo,N5|$ cG]yLw|pZxhOal1/~9.1vlx6Y` eO<qͣ'xc=k_Ƣ٩ YMC34s=FA\z{e;dy,{!` ?qDja?lh7J6& HqD+=K:Ǝ> P _>pɟ,u/XhQQ?Wov>F\I]T8w#4C]Z\!_>."~>2VpKw6"4_i]$߃qj~/%(C_~xV9< *I"00_Kl$4s 9Uj{X?+٭ǁtgM ɮaw߮Uiޤ`H1J\L+k=VǞ*"xI2CN_Br`dWR/Rڷ]J Ըе(Njklp$ԏ߲\L@fo_ii̮wW8&{-(}:.eM]4pZo[piA(C1xAqԦiYunLP$A3c_ ePj> p?Z.Fv%Wv<26m窾kYٵUh}f_AԦ?`OGBDW!NO|s@l,qrtiʕ&:pKUf#˂#]{92J6|k;{_?p~|`,*J ,|=K!2khvHtu7b0skDb0'=u924ӹx {jbbdI 0+y=/]qf}% Š7Z靯T)&ǘL\m?{cܹl^kSg8:,c' {ѝ/Q[#އ~ x#~m_nn6JZp˭p'KOpT @/WNw^f^iq/Ya.rL8^ث*t'fa ߓ츖ՙͬSK!iS<}r/Sd7lѝʢ`dWeﭚ`$ؾnfVu^SE{'8YXykܲW)=M}(z p]}^ѱ/Q-WkֳzVw\GS{91v \@ѝ:x 7ޏNZJ^uٶNEL^DM=oS 2V8Ge)nڲ9frz~+q] J00t/vGاw z} C/CCC|u>ʁSS[/ |r5'/+Fv%_ |`mܱ^6`Ɖ1=p?a@`mSy?'GZv}!y⺂㺸"=D\ePg$I9$>'nbCO+`5N{)NOC7GwVq&J[*z`c6h<6竇h^U˿s թ-p4X'5Xq- ٮ#8N``: u=28j:8 6vsr9MCS?deZ6B_jk&{'R+ ٕ'FwVO,%%Ȯd~tWzwo{7}-(EO[Hu3S0S_? +~kM)Tm\%epE8W:mt+b=_Ń-Ws na} <{f/Ϟ|u cdW/1z-dٕ\+p{BOS7ۯy;g`5=,ވ6VHݸ6zN20ǼêNa;B75^?dA c\@"^ }#SCl]{'q|4#Y1KB]-;g/ґ#`cv KgtLˈ)v]JeOg3-׺@z0Wp5oڕ7(Vs?ٕѝ_\pȮ6ʑݯ :Y?g?Iߍ {؅~fXs cWᠣ',`@l CS>nko3&َP,Ut4>6@An%scm #[YϾYջ*}sS夼6" L&IRz/+RCk^ ~#9tl C$LLB#ٛbTc2_ 443& l|ׯ_[٘7ـRPMr9ED8{CZ;6rۦ{82'OTEF_]oZ-șZ"yj3_a ]CYnZCwgWvɗjT-b;444rv|O#l|6ozM\\ n>k^uݎti&};gpcnVh?Cc’jcv$Ӳ,׃~|[`QxMɳc∁)6 i^o0+s r4rCy8 fs=3iFCkz#!:+:xUD2 ѝ?)XY0Fv%|qÊocT*_cH G9 m")-#(>m*n3L wݙ"21:t98}u?Oa@6p*[t0:2(U|XE1YFv%ofӃ;/t/ėxDMA$P86eKb=o`p禾+vS!vZǡ'†Y3W/Pn/(}M:dٛE790x+D6\a}˩FwVAY87Smxqu;iU IUlɾ1ʜ?N@5W8Z& W1Sc+z^q gaT~iSK2u#kn$ap*OM^k(S)J4%g=Eٞ&obJەRQSK{u6I&@ٞl[QrEP9/3DwD8H~[ز6h1 T(eٙavkgev 7Յ )&hc[8?/Ĝ`[4Pd,DF^2F #/\8c\oӣ;;.` Ązn׽>=t{LЙґ!\R^o;J:Er(3c!JQa'58S*:}t=dF7Ҽ)o ؖE:MߵZID*G=H9XߵPLo.MO#Y}304q ǥTˑ/OL/OQNQ YOVC.jJ?v-p=fjl~'}8 ':VE>GAG2  ])%E_`tgi.%t 6DnF:_Ӄ-FkBo55= o!l.cv4bm`|tgc>,&gA΁ x u#ǩ|X!f%AH~RӧRNDz,,- gqq =p%%~, N GLm>ku}Rf%jq TE(EDJ49 ;1hIDT")#БȂ&Jy/ x ?>t]:1R̻<0 ˶ڥz,,9& НCD5wTM-XeVđhe[8ͤ9mv~3L@B0$P*dkc҈#H ~\woY@KUAXpi _Dݷ_.8_FBÇf'Ak*Ŕ%'c y! >b$B[%Eu=_Y-a}_ evr)_8 ]G]&0Cs-41>'8"F'PsyV,fJ=?  xg08[Ty71μO~}|C1$R ki,rf Ю Djz K&|BNR5}{h?,C9mxA@XdۉDNnZrK_??S%A P(*$ifX%9q6ydmRŁhJ}%!0xfi̬-V ;Qq-K>GzW/r[1h f b;)ȕ&< `62k<4@yq6Z فY(?"edq)[EѝY~,"Kg~4 0-$ V& z>T~Sb\ERO]qz,,L< cĪ%a#A'HOs8сhAK4HjiL-V&aX}Dk^\Cwn?W.݈( m5ҙhw +D2 59~*f,I3R`)d9 xMBm @; ౠ/:A ~#ȣ %k^𚂶P&:=("Q7@b8Ѧ 8[mzi0Ѫ)ad@R=΃|K.KNm3I\q$u`fQcU|@'[ʏtخTNl؂Ŗ%'/JRMϵ??$QgsU~ZQBVXCB̹ l@! a=j В% |Dvm7bI.oSF%ksu*h2O3x͚bOi4%kdPsb>=KoC-fqDj}BO4$FԒKE݇c߹õw1{oqcl"@ϛ:Oo #Oog([3S@GP F)!itS5pZ&Wd|$"5sRspL&b!DX_:W'fBOId53=ttIIo\޾Բ-5V˭∅Zخ+6cwqm?(+M3ѕh kJGSA '2DL:BV\-P( T5;%j|M Qޮy޳5Uz}$,,],,. _JD079| D\$AsG!6XEVX{׊Tc*6O;5|nY3_,+ .!5ˌڪܠ$Tf` o蚁M{]3të͚.Sv}mXX1DZ۵mǵZ,'2Prlv*ək8\ ., j/KejՍɍJ>@Z/DPDu/8\fc̒7_̇~n'N$ү=A-mW@%A_tgeEHAhہ9vr%4\$K$/E./E.=ǡ~,PIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/000077500000000000000000000000001345766322700212465ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/actions/000077500000000000000000000000001345766322700227065ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/actions/gajim-cam_active.png000066400000000000000000000017341345766322700266010ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYsͿ*tEXtSoftwarewww.inkscape.org<YIDAT8e]lSuƟ9"_cJakѩ+"p$5u@AMv J25}pD6lВTmipf {><%1PxhX[,>4rxZ*˗'gսd/ ~tEFEUPe$ `dsPxH;`4 J!B՞@DE|wJ!s=f/!kX\\σ&agF0?wtucЙV`28BpaNF(41j VVVt:pc'vn$ v\+$ bddҥ4 rYF۽Om:7b- F (CaukdBe )8vx5ElFXQ}Yg2M*B ֆvni=tVa?٬.䙺EQ##3γMMTk8{cc2q4BTIM;T>L]]2<|/`6p녧%VdZ,b6r{.1wfwwDJ)Xq }|JSsz:zC?N;u\.GNHEս': }~rC^bʶ s`x6g#s7o%I Z>IZ.clޯZM&qX__w˯G  kJ!dПLB$BȤTl1PJ'QPIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/actions/gajim-cam_inactive.png000066400000000000000000000017031345766322700271240ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYsͿ*tEXtSoftwarewww.inkscape.org<@IDAT8e_h[uϽKjҬi,VF]P ] RŁͪC٘8\P2IHdor|)|J)WDDZC/I iݎ s?|ͥd2CBZxR|VyΎnho;{/b/'%ciG!x8جwBv&,@)E,?yE(!m6FnGJ)T:Ǐd744ToW)0 C)u>r+q={H)!"zzccc߿3E1YLϾA*x6A{Ze{-#?zq$3g{W,r? NP(xuxk;@9:KKgXZ).:%A#I[1NJlLGG<O9L8OM4k$XkTTp 5NA=a\dJ`yʷ*M9Z#i4RjJYn$q=r>oie[c-1ZC+c'ܤvzGw֝;V]g c1x*&זes9r9vfɾՓ T/`a(|0nnةsRJq~ Jkh Pj?_nP xIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/000077500000000000000000000000001345766322700225715ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/applications-internet.png000066400000000000000000000021041345766322700276100ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< tEXtTitleGajimW )tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'Z:IDAT8mMLu?33 t,/m(V`$\=a5ċxjh^h4$V٤/1 R؅-m]fٝx&4w~~ 8|ɫT0.4:ITWL!?ԻOOZ؄5xY#O"d}'OA6[/}T^!?~б_vmMhKv7C%E"s7j?.RÅt.k:6p㉏13ƞWAbuEݱn sY/;! _9 Y+7߼j EH6 V0q~l]3vy LMMXpS7& 4!!<{h׋@RvT N!a&QN}$(BIMʕu⦍)Ü!)e<^laF_W$YYC9ك':S-ѨÖq,pUoZcMjҠXb᮷<-R3rkEn[OuW nƉmn/ܩӲ͗K?xGGVZ+vm|*s["W{R?^8{պE:n4*2Hsf+ڇW"qitI􈔝7XYc~ƻp]chDJqYyV)'bT?Ӆtnp_%^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/audio-mic-volume-high.png000066400000000000000000000014741345766322700273760ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 7ͫIDAT8ˍKHTpr1$F>*sAEJV֢( f2i+٢SRhBH#Z$-̘l3j^aRǙ))sY? ͉e+iis8/k.88kVeoa (;9vvr N^D" ((×A.fʸp.8*p6B00ƅztttP__O|͔]޸jMO,\/..vedd044ngz_}ffgBoi;՜GCpuvvRUUEZZ===z~T4l2t)*pO0"n7@)--%*/cb=PfA>`7jWWL__?D)uu)l6Orr2 ?Ud SYz%FUeUcDQ$ %b21ID:q4yPW_h`lZ#4Ŋ)ͽ G}+Ȟ6LU횛fD%df u$=蕚ـ7=ԔTGU {tIR]l0O-k?i[5J &hK3 FY.p4^L * \->IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/audio-mic-volume-low.png000066400000000000000000000013021345766322700272460ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 0iIBIDAT8˥OHq?iЙ`&s. cRڨ*m]BJofA/:̵uЄ'8mk[Pv0ECs=?8f h7$ab߯uwt~MLNhjjKKKZsTxݚHRi$͒f@1@Q$axxP(DQQ!:)Ñ;(X/mձNUUFR$IB>{jrnvv򲚛LŸ0D"&HgxM\|t:s{-nA@gN^RV`0B c|G@\/vdll χ,b1:;;x \^뛢p( DD8F# %Μ-CW(FGCĦ]Z QQU\.G4ecs4,ۼ Zb`٨>_*ӟ~p̛.I~gʀG)_Q^Ar97мwuoAtr9yab^u{ʒHIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/audio-mic-volume-medium.png000066400000000000000000000013771345766322700277410ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME  ,IDAT8˥MHq?ތRJ`'Ț3Ii50i;"vQTxS +!H!|; aanWEDO> Ynm\f@8p84֦7PE("} *lv냣555)2*-F!H$B$ajjss46<h5k?]qt퇨¡e?j```~IIѡjHKOಣ;]ɤ{brss ΟEa˯ͭ7ӽYqľ N$^FXY]n6BIH VIB f3P(DAATTTV, ^rBTI Q[[^L__N1!"ɪxLU-L&^/@ n7*-NLtZP]I a j^!2F|1VVkȈCIw>uqM_>]:[ޮ龳~C6 d'TbDLտY/O٭zSN5/ޣ~A&v2.PIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/audio-mic-volume-muted.png000066400000000000000000000013701345766322700275700ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME )}xIDAT8˥OHq?{7}H-%pd;zM0͏_+z>(tֆdv365"BQnq])oߌ#IxM|>*WHb!J$BG xbzfffgbbiv;w?/bN02,D $H Wx%p8XYYh4244DKk R*iYtRrS^N"v;t:m hF4O8SSN|57c0AURX,TWWSv5^/kr[DBUFAnh'[Gǩ,*< ?^YҴ vƊ/s!R)H&I)F0ßuK$jա&zk K4]Go w>IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-away.png000066400000000000000000000016651345766322700256700ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8}oeL;3hRmH :MHh0H" ML\XcHOW0R$6&څ i#ȥ R-3Υ{ SS8$ROq`3(8n;O?VΰriKjch\=ɼ7W<ζm6-#a^Ax 1 t#&Gx+܌} ;Zars%ow\wrQ#c4% }3~18p!4q +Daq6e<- " A+duI}a–ݢAl{2;֮ۛSqlR|O+s?ϏlB?0uhBy[C+W{IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-chat.png000066400000000000000000000017241345766322700256420ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8MlTe޹)2FhiJ)iR&.4ԭ&D n4]")OҤ 5Hh;h 32 ~q@,߼9'<5AG n8y ɵwՙxB'Ư$+M˭+ =5FxpZ-85C{‘exEYm]/qZ+{BIJ@*xv*4ݫՂ(*QEn/9?I:+,~qom̏ ugx=6dnizq_OSj15S}8p-ض֚TjA7>V gwBѷ5ϫ/FCCɓ+O.$Gx@r{^tuEnHc yD]Ꟍd4͙Dwgdgt*~t&ܤjٰʔ.ҺƖ#GzhNSc3/2_9b/;::c Bi&PN>ebrtn^vNLD"Q\yRr0Zu,/8)n,~MSJ.mL.ѾbǕch}.DUR8v]Mz{cFC4!$633_7ƭP}ڣ(\>o<߽(k}}6s.*"a@)2l̿RS^HNIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-closed.png000066400000000000000000000003411345766322700261660ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<^IDAT8c`$BÃ#W\U->W._Ͱrj.`!d38.(Vp^ `x!<2$\.E :DIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-connecting.png000066400000000000000000000020741345766322700270510ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIIDAT8]Mh\U{/&iFm$6?H%-*.ʅ(""" "v)Rܤ5`FI[#M&qf2t̼uguŁOJiWZw`PRR9=ԉK=kDȧ>tV[ -.w _B¼89V70>.{Ez؛"VuB4ϵ7BG*6',ԭMp:&RJV7\kؖ~`ۮ<_oJ7"SDtCY+~R#7<ӮffovZ]RǏ1RX\J l]0 Z +YʒYj]RQk:@%ECHPJ&0栥uОIX\߬$R^:1)o ^{ign !MҠtcgC6SwFAa~I_ t"UfW\>Y: 4n+{gR04RxB;Oܟ?,fCIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-dnd.png000066400000000000000000000017171345766322700254720ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8Ou?}&ec@u# QGds2ㅙQ/]ѿ&&zŹew&[4&fc) *# 6Pm߯*l'97'O ,CSph[7a$Ϫ k*<]{Rgg_'Xiz򍭍`UGj*]}hN#1dD|WDDWt7hOlmAѫ,US3(h'6+4̔drI= ĔVbJT Y鎪lIJs^ DDx!#]Ja-3=F0=qb.]/=r4`X< s$ѓ03xD'1 vS?[32&#o[bnn <"N8c.W=HHn\*)w6XK/|-'8'howL ZcI/E囚ȯxT꫍}yA5*8U}F}\ ؈.Q_sAQ7 g㏼3qCbnZK换1G:1 ^Eao3SU!B-P[K>TUjTn8:-$"Pth#ӴQ1D.84]͎EIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-error.png000066400000000000000000000017071345766322700260550ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8]HQΕB, > Me}.R. &HEmEdYA*F969B\Ap^kp5"[[ʓ-\5|)˘RXT=zȟ<BG<+VTjdԍ_PU>_)K)(@DHN'Pree`YlR ,k13lJ\ޥ&gװTƝ/T|"/,\Ukv^@Y!(pMXggfmu7ƂoA߱Fwee%OSx5)[Ԍ/8{x%<, # ɾ'ieؾ{>B]ɘכ[7aP2x@Ov "7?-JK- f)f(]ӧqP  X< EZ Cv5 h6%xJ5J.```f{L{+,_^tq"O=ggw;b]8v`YuNQ`u/<qz=`zq`p Ή()ʒ~ Ƙsie4k7,UEDPU1 _i43W Dv:YbY6ժOȲUD"R.yx/_ RlJYN(Vx\k|F`*QRXYacôz$I>A[K0 w>V0:n `{(Nc;q>)kIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-invisible.png000066400000000000000000000017511345766322700267070ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8KhSiIrMv*X5^Gq,,2;ѥJ]хWP\("( 5E-hZMӻmiNrYmo}< <̳k2'p9@  ;<W3׷mxwn΍W|{^܄o:/M?zچѿ >rNwz*m6 _Z`¯%vϻ-k 38q驛Ml2,γIx:dSIl+8viͥڴABx:ek%i7w=;;"_3"g2_ju{vDfPe9M-Z>{m=ng0>tYה/MJ]tsݱ'htk@Gjʆs kS>\]$>FGh-7}Γ{#瞔8rbr #ZteJJN 8jw7*yaQ ]vl(lշAV_Q&x_]g B#,zjP~qxҪt{?}'U+1TV&ɞGc3̄>)N990irZ~,C!RqrL9_Z8` 0d~rL DcRu^9`)IA\d\UƘ*Ld@ f5FEOsעz ipTsmu,&~蛛9" ` )B9fžrmIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-muc-active.png000066400000000000000000000011601345766322700267520ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJakub Steiner/IDAT8kSA򾠄`.D\ K,Z"ɢ"";n sHCRZ!`I2s]4$/EA\wΙs #dX,>X{2 b뉈1fjt: @ؓ"bO"JW(k"nR96ǹ3 cy@Eҥ'N1pj뭗<[ȸtD1cjc3Hn͇R&I϶YN ^Eu5sa1~(|^EQ41H/zh4nl73/=3էkׯ,V*M >`L6MrGk8/[ְ401Zkm9tg_ J]-IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-muc-inactive.png000066400000000000000000000010741345766322700273050ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJakub Steiner/IDAT8S11= ڵt:Awb;KA?A,.NE(UԤ߽]^~>:8pOν!?B V]93{ kf"u蜋=33En[v YZk}BIBv:sdRJJ%T*]hHk !\.O BւR'3Hzu#,mH arj E޷⍛̚uǎ#h~ US1<2t:q y:b1hҜhâ 4>vy7 d2wtZ+ٝf!5 ˶@\lKZ$>PUGa"S0B/j &3Ӫ,@h0C eUeehԳ3|`YV`sFBNY}+*))4 `u173\}wř%SI\I'p Cr"DoeR-U)uIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-offline.png000066400000000000000000000017021345766322700263410ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8RKog=7!0j#!X*PȂ-[H,ق`nV @^2M)PPNI 8|Q Hwq9W:ȏBFgbgfhRG?Ԋʼn?v'IEg蕆뇇egaF|w_|R-cXe[r񐩝jeYh4`FZLq|#RJ4z ڋm;_lCOx~ DZpu 3O-[j]rāf)~Ǭ~X n(&yRk[;NLLH6͋tzǖh|h2z ŪSS&`@ӌ޽KRwim޴EZ.yGQ)0J$K  gOSbޝg RC2J۲!"y}1aT*dz&t]Ht*ݿsܫ`f!@=J)D#1U'LfG.@_x5/4MB bMױPhw\*D@0"AevMPL&/PAe:\ fd2MT ,m¶zlzu6gGo'sc7ǿ$╊XMju<8Ivk-CkIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-online.png000066400000000000000000000016661345766322700262140ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8oTu?7:7mB:DT҅%!&ƅqeaG $Ƥ&@ ?tZ-t:N͛y.Or67{s5p+2'OQqs[o]K`R_(Qo|+~Ͷzg >$>,rp̫i>kts3)V!IU~:@QQcM4,  ޣmnĉ/Uc1il4` R~ ^<@$5$7>nfnk[*4D%)wr~r5:zE3-̶FjWy='_mO\).v{wc,Fw8W8L:swRdNhĩK'ogЇ2,xi`o667 &B9qcÖ0"^%{[:v޺=[: xPU5wrF1V`Յ((A3[GZt56o r|\a"G/(_+T(5zw&Q`hӈ5i?'ccOued}"|J"k6=MT{sb+tj{YK2}IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-opened.png000066400000000000000000000002731345766322700261730ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<8IDAT8c`BÃӰzZ=,Z氈 1&|M`0_:IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/dcraven-requested.png000066400000000000000000000017501345766322700267230ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8_he;lE(S7u\ͥY:B`HEQTÛ݄yF$$.Vt]Tٲ)cm3|ݍ&x]78`h7wbnUkлgL/L _& gh3/4xtۮO25B9k>֒O Pښn܆ utOa !W$͢2Zz%_W{Y|ltJ : f ~S_~/I2{vtsaz$l @{'$״(ޏPo}%c }{{R- dnJߙQ:ښq 39J61ԣO^lVjzfWg6FM&c;qeG$]X!5t61vuw^* zɤoK|õ ]1?22s1&~?Ծ}V=|e{5ʷl%ȢE|= :t.P傊oRU(q]H)L֢. m0Г3JVTɎ'~Jk|c#q@ y!ѾR̯``` RZߪV]RWAG#p/6uũUG hbqJG*iqTFhGAtV^q_{LKaa\+{_jP/4PHE4")DZ= AL "CH-= Ơ9CnM8I˨K(NNK8o_Ë;Ac682oF?  K|-/l[s?slFl.}ZO2?OmP߻aC<*\ƍi:-"D|Bʵ$I ^% iWWT,w]UOi&NO>V]="WC4;&ljJSSix09+r`$IN-޽MAj5867PU < x8\J@ "d% ζ.=?yUkPUPEUTlpT**}TQ߇FEgJsLNwuaAZ)륒hUmB%k[U0ƘMEuڶ?XVBIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/facebook-away.png000066400000000000000000000006541345766322700260140ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<)IDAT8NA[Gr@B¥*q X$'  $lE4 n[JNbfv͎9. >gЬBBӎrԁ8ɒjuǛ|NB(J>wD5l#.n^AWb{@ZGފImK:A^`oL+Oz#='DR6( Gā%,X K ^y(cE"āȓNF4l{k*k>7,*^4t8b^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/facebook-chat.png000066400000000000000000000010501345766322700257610ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA; EDCO;ARŁ`B/ *b+b}f?f87{jy0xXD6DaR*JZ|xʪY>Ƥ1Y$V(@QcKO/_ x"i!HcA9N},WϟbtqL25g=w4 ޑi".tx#?\a*G7Ohkt0 u0Y\Ę`u-7R@UVs_IoI0;t޼x|(9/cxE8ZBp~iଽ`wV1b%dFq BQ9XAw_:IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/facebook-dnd.png000066400000000000000000000006541345766322700256200ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<)IDAT8NA[Gr@B¥*q X$'  $lE4 n[JNbfv͎9. >gЬBBӎrԁ8ɒjuǛ|NB(J>wD5l#.n^AWb{@ZGފImK:A^`oL+Oz#='DR6( Gā%,X K ^y(cE"āȓNF4l{k*k>7,*^4t8b^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/facebook-notinroster.png000066400000000000000000000007641345766322700274430ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<qIDAT81NP߳+m-{8 J(p"*H4TH v]}C73OSp $"cYkBJ80Q1@USUEQ0ypĨje)KQ(jLӌ͍M{,..1G/6Qd[_Y h4Z@\àaG߸FD6 x 8}W/vvOg[Ga6 oj:I]ג@UUuN^@Q)[; /{NM EZz{ijDd2,Hbb"KhB D*~6(Kʲ݉#VUct{_UT5Qd Kvi51 *Q`8c;'*u' T.xx'?Z}Ȕ2'Y>0u4, 2ьpxpT8kwZ ;fl>iwZf"2'I\v;^&cxdrT5T$IZ:z?EIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/facebook-online.png000066400000000000000000000010501345766322700263260ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA; EDCO;ARŁ`B/ *b+b}f?f87{jy0xXD6DaR*JZ|xʪY>Ƥ1Y$V(@QcKO/_ x"i!HcA9N},WϟbtqL25g=w4 ޑi".tx#?\a*G7Ohkt0 u0Y\Ę`u-7R@UVs_IoI0;t޼x|(9/cxE8ZBp~iଽ`wV1b%dFq BQ9XAw_:IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/facebook-xa.png000066400000000000000000000006541345766322700254630ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<)IDAT8NA[Gr@B¥*q X$'  $lE4 n[JNbfv͎9. >gЬBBӎrԁ8ɒjuǛ|NB(J>wD5l#.n^AWb{@ZGފImK:A^`oL+Oz#='DR6( Gā%,X K ^y(cE"āȓNF4l{k*k>7,*^4t8b^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gadu-away.png000066400000000000000000000014441345766322700251610ustar00rootroot00000000000000PNG  IHDRabKGDtIME  8IDAT8}_hu?sڶwӑnvTab[reRZX) A5PQAtEAa B:18yv=OŤys|< \~`U6ws|Mqkc>UiQgdv7wszG~' 6zS5-DfR@YuLɄ.?O^ᕻUaG{Ⱦ6F^ B;0ֶU߱2!D1 z"Li]v#9EYa!H[ʥ1{zF%J9|rLgwUdkU ߆"GuzNr %\ʎ+h~*Ȑ_=tKlf=x|8pp Owo_ ^LrK۷&Οol @kY&O}^=9V79AȬ-wLf 61fy1pcgKE} *\rn̵|D~Q\ @m%IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gadu-chat.png000066400000000000000000000015211345766322700251330ustar00rootroot00000000000000PNG  IHDRabKGDtIME  8IDAT8u]hu#`KӮt2dJM7l2UcTPLQ/BG]jڌiQ[uA銙&Yڡ<9Ԩ[2 Ƕ| |"3CCO͋Z#~?lg-aYh) :-WJeQ>fRZ?*,S3T}EgCE.B*}%%T*o|q6w 7_pd۶v龝c3]FkEWG7PݼLWMM~g}ؕcXX 7@0}Meu6<.`ʯ ~;޽wP*iT3  1H_@G8x0~a8+G i$DT 'Lݷ?ذX퉖Opk2 Fղe*q"yεopwﭴ/]%jUdQ y` ~VQ${(ĀPj )?5;(! /s&e"v[9~Vl7T$d "t] я`B8`\rX_ȍf_ߘk_:}@YOZD܀>@ujܣaHIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gadu-dnd.png000066400000000000000000000014411345766322700247620ustar00rootroot00000000000000PNG  IHDRabKGDtIME aDIDAT8uMhW{7$"1`iKk5]YtQu!P b vS(MhRj .lqiI(1~=]H"5]缜s(o=ƹM; ~]^`fkӭ'`ruBkLX*XCD֭J}#3ZTJkGj o>|8;<0@M{Cxg”WB\%jnrDоOqb".r+mfC]1=+YOѨȹ%Xxg9 cN (wa?\HY\1IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gadu-invisible.png000066400000000000000000000014511345766322700262020ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uQhu?_tmr S½J\dEDE"IE>/Qzn5AEJ11kvи9=Bl:3UM$io\fFZE\ > D$~ á|hԹ0"2P(DK>]76xѿ~]wܹ Rg+ssw} w*0o}?n K]L5ܑCOꟈň bKft>dQt. DF.}x띋1q$KyO25$MWA-\䱮\twc2 |`$s^!?0qV۵X!y;$m0q8`)v& p\lѹ^.l|EѡՙɳY&?ZJU'PY5U?^v&L&h wq&\B:R:uƧ3/{2:h^E6yy#K3Gۆ/寧2A0!w߿v6-o>9@ZGO?&ϻSxX'JVEߺU*VvXt.ꈢحjٍp-X0&q|z=N /6؈3+mz4!D>G:]\\j~8Co I$c4[[Z _b6Hd X[?h{CBÒsqvzi3e~A|7~a5j6IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gadu-offline.png000066400000000000000000000014371345766322700256440ustar00rootroot00000000000000PNG  IHDRabKGDtIME  8IDAT8KHTqƿ{;GkNh$n%E#څVF BPM tQeB"ќqL] LC\3w@Yw~ps8B־)qҗ###v:a'@ZZriN Z(0J.V?aX4Z b"j<[10"L7||}?&x^j 1!PZZiYAQ_Fkjj  @ƱB#xӃXD۪$Q,$Ql$%&b ## Y@D$>7ܫvYUUhCCcBcC=,Ihn5NYƻleЉ޾^&=ddf#+dx''b]ݰeNYQb!x)GU99 vƕ,0Y);~K/IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gadu-online.png000066400000000000000000000014421345766322700255020ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKa~_7NaLQ nf (B*ȜEn$AD a**VЕA0BKܿ}[X9<c ʕBaT26fLq.,ל VE"K-pֿ⺔JJy灀T|a8L`~Hy5!Y m+i]:JJ{UGǎԇ[kչ) ƚ_}[^|6kO lm>nj=Ʃy"4 x;j׻U4h|_RzCeH  HbIm|/8q!GW|~w:5tL׮ ƥt.d)Ak0FXUiQgdv7wszG~' 6zS5-DfR@YuLɄ.?O^ᕻUaG{Ⱦ6F^ B;0ֶU߱2!D1 z"Li]v#9EYa!H[ʥ1{zF%J9|rLgwUdkU ߆"GuzNr %\ʎ+h~*Ȑ_=tKlf=x|8pp Owo_ ^LrK۷&Οol @kY&O}^=9V79AȬ-wLf 61fy1pcgKE} *\rn̵|D~Q\ @m%IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gajim-plugins.png000066400000000000000000000010351345766322700260440ustar00rootroot00000000000000PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<IDATxb?%BҸ<E; vP6X>ͽ,/)o zmP`E_ W \@&##Հo?4d ;YGEf3mg7af`dd`x חQ 8v4rX0&521n\;pܶ,?~@8~0|g<;Lˈh1˙珟p/5on߿`myf?X PfIL(-XXyE'>f 0Bezh;\WO߁_yE.H/D@gb(>֟Y͓/H.$iV$#YHav0eذx6IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-away.png000066400000000000000000000010371345766322700253440ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME 7UBIDATxڵ=HawIFbA=IYE**`AXJqpk)-t @(P/E1 YD-X&i*jL.oF3:wz@m"^҄B{0>:l`tz݅(uFC*s#<Mf2nΞMϑΨ|筄Y:S<- ~%.y;0樬pQr;7& %8=O޾~;ٌ2BDRUU3$l6K4BSu‘coc1ގrGG'84/*qwx_;$n[lmoX=gg/:wԡnpY|yiLfo[xQ6JUgwIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-chat.png000066400000000000000000000010541345766322700253210ustar00rootroot00000000000000PNG  IHDRabKGDIDATxՒ?KQVZq' O.M*t.n!a|As!\uf7N%9pxp=}0m~Qmp i%Ik NNWUe\EQ(seY4M$It477:]`$B MSV///5e^WQʲLPOOOr\~=<<,ET*ʲ,--9(I("c}B- B,..{`*1ưFDYv*QaZ;^O-8_[x||lbHbkkkB9F`TmB23Egmm$I>e( 8F{sqpp|0zZ-(GW|N~7&r_GIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-closed.png000066400000000000000000000002541345766322700256540ustar00rootroot00000000000000PNG  IHDR w&bKGD pHYs  tIME)'C_9IDATӭ wQz"JM ]-EP ^Q*1IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-connecting.png000066400000000000000000000020741345766322700265340ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIIDAT8]Mh\U{/&iFm$6?H%-*.ʅ(""" "v)Rܤ5`FI[#M&qf2t̼uguŁOJiWZw`PRR9=ԉK=kDȧ>tV[ -.w _B¼89V70>.{Ez؛"VuB4ϵ7BG*6',ԭMp:&RJV7\kؖ~`ۮ<_oJ7"SDtCY+~R#7<ӮffovZ]RǏ1RX\J l]0 Z +YʒYj]RQk:@%ECHPJ&0栥uОIX\߬$R^:1)o ^{ign !MҠtcgC6SwFAa~I_ t"UfW\>Y: 4n+{gR04RxB;Oܟ?,fCIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-dnd.png000066400000000000000000000007161345766322700251530ustar00rootroot00000000000000PNG  IHDRaIDAT8˵K[Q?U ڱ]D8H.ҡsHK38RUqpDhڡ!R!$;.و~N|{@Π#.L e#`:U4wFI<~{'݊btEGWh"+H+gkQ%J;mN4{o(+ p{<AF\l`Po2.BDDAg/tD>$>e3\BS>_/滎-`Xy=۩Ԛ4&  e$'HϪOtA5*(R|_6?.g$jR)-̳#7 y UK8;h%IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-error.png000066400000000000000000000010241345766322700255300ustar00rootroot00000000000000PNG  IHDRaIDAT8Œ1kq7IXI6KE쮎VQgѥD*J8UKՒJJM6}$6.7wx8z Nb^QDG@  )V (N&t.s _XyEwA +ŶPRWȌߠWH̅P4\Y[x=G#j.nHx]&LJ|.q"$/?g@6K(&?S|&%Rr*bj4+00ߧXa-pbbt6BR%kNO.v2)' r㩯*IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-event.png000066400000000000000000000010201345766322700255140ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDAT8Րjq_v[@, Im&C4^>X< EZ Cv5 h6%xJ5J.```f{L{+,_^tq"O=ggw;b]8v`YuNQ`u/<qz=`zq`p Ή()ʒ~ Ƙsie4k7,UEDPU1 _i43W Dv:YbY6ժOȲUD"R.yx/_ RlJYN(Vx\k|F`*QRXYacôz$I>A[K0 w>V0:n `{(Nc;q>)kIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-invisible.png000066400000000000000000000011641345766322700263700ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME$hOIDAT8˥Ohq?{Mg9e&m-hDD V0J[xE[]:thÐBFFAACCA6 {Y߷ yv{|>90Tzd K!922T(L#΍k3RhuFޠT5h"u2*N4Nɽ;ъZAd4t_8nP7+5SVWb1l ׾/R>ɩiMGA,f#O6\DQx,h7C_DwZ!^kJ_xI_XH1=s`^,vdN'ZQF"1޵-(p,gj63wxn-#}Ď!Jt)D"fPlwy'LtyY*@ Aj*v]eY>o{vA&#2>|> і"&Poiv7nO-IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-muc-active.png000066400000000000000000000011201345766322700264310ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-notinroster.png000066400000000000000000000013671345766322700267770ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME 6eDtEXtCommentMenu-sized icon ========== (c) 2003 Jakub 'jimmac' Steiner, http://jimmac.musichall.cz created with the GIMP, http://www.gimp.orggGIDATxڥkSQwf$ZbېBk+ŕ]\W @t!n]Bp#"FED(U5ƒ4sq__Ru>sΙ3הgOYZ,j5yo =DVmx$K&zky*01 R>{U8xx/W.B ށ *J\¹i&bf64TQu;E:΅&Jƞ}lQ,h[D @^ Fdžqf[ { >mʡ#{!=a0;B,;sJd D= "6*pZV%]^ώa&! 6j?t''xrfwNKpu#`R"c =HIGA?r /Ȥwa?o(VmP3;?٦_?Vd9AIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-offline.png000066400000000000000000000007731345766322700260330ustar00rootroot00000000000000PNG  IHDRabKGDIDATxڥOKA&jŞz P-P "BO`S'HAbKkKac5fK%6k x/<o<otq[Bk '|j{g>T&K&PA| 8:gJqԗ^89eja2T& y\^^Nu^&_a1 鳁j%R+{Eq/R$$ uLn378kMtIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-online.png000066400000000000000000000011221345766322700256620ustar00rootroot00000000000000PNG  IHDRagAMA abKGD pHYs  IDAT8˵kQ̼wjXЅ nBq6Ņ?@UY[]\Y vU+VmREj6jmfB13\![ǹ?JsҶy2ۦ|?@+eؖNNSiiZ־{olK'NPihSOFN)H3ց`V=)lF\:^!IwE231,>U9.]իo9i   fC}6RLO2!`CE dPUa@U7blYYt}DЌ'/9efVp#?H[98ԗᑘ^-pyWn~yx8;nchm(aѰ%d~lU-V-*N91=>GG948DANe㵛4YvoϱS)l.er߻rzϙ^y"! @km(ZfN7ڇKܨ8i9x% RJLdvv &''IRH)Rq8s3ʖZ+jdH$!B>FR" vm(J = J)l& @)n3.G722P2.Xa﫶TĭR&|766k7@V+/ yឮ^wˬ,-wWD U:r>l=UEӺIګIo0= o~Yn{߼t=9 >uӔ6nr5ā`%w|੭J.ߔJ"P?/2#G|IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gnome-xa.png000066400000000000000000000011661345766322700250160ustar00rootroot00000000000000PNG  IHDRa=IDAT8˵OHq?{m4ܬ C"1AJEl$(`jѡ\XRhFAY@?ngWO|[Y @ 0SӧlhMLad:."@Kk:Ib!Ͻ; Y~UP '?Bf>G<Viao7(/3f^c{-X-&:ݶ&䤣@yb80d3W/Wq8Kz{x|pw1oo D*'ErU8(Ƈ %*dag Ye!-MRgЁG%S'bqTEA%;%X]]RL&E*EQD$b~~^1vËd3hYZ|}&sQ FKN fQ*`kUDP(ra; h3 z4McqqI~OWWZ)2θyIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-away.png000066400000000000000000000006461345766322700255300ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<8IDAT8œJA"!je RT:`Jח+@R-`(6Br%&K@"802췬QUH%T6e˅ 9cA3兜cɧ(('`mlFo\ {eN#^ ϴyd2=La^Tz> `|&Glt  df <eg Q܎L?@)M4m} CseIvc{ XQI MiCZUxFg8qLgճ5 v&~Q>(IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-chat.png000066400000000000000000000006271345766322700255050ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<)IDAT8ՓJQ+m@Q_`)i^AQDP-=;xp03̙{052/~CU`qBġ&%1E-7D񀸣A^|< <0 -g1J""*KƬV>^懙~Rj\[LX;_Cg -cCP5|+*'iHA:h5+D;c2ߊEzy Y·J ` Cۓ-Q15XJtOi1T$O67T>0cOGɋPxV^b*٥_٣%XJG?{O1W"+IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-connecting.png000066400000000000000000000010171345766322700267070ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8ՓAH_71H(".@P,ƌ"уd1 s!uR f_sƒ^^9/v{x Id :H@̰^r%X#I}MUVsvG50uĜMfIUy:j?^TU2_~Իkg W59cPtf*N "ΒXv Vc43y5J4]̳t@?KL.7>RC65U#oK>qswC##_5;Q0@`J 7ث R +M 729_M5j9IIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-dnd.png000066400000000000000000000006431345766322700253310ustar00rootroot00000000000000PNG  IHDRabKGDC pHYs  tIMEm}0IDAT8Փ1KAߙȁ  VM> ,,iLo+-$A,-RaM;;3wULy#<P<׋ NXeGv&Eӣ^ʃJe|t䖨‘DϳИU!T!di^2WpS=p 0N~5rܙi݆qP`D KO՚:<}R+cq5^Ù9c w&y"Jka,XWMXJyda; X8̏E%_b:>l4&e "}CN]I4;iwrv#atA)B= Md^9 #> Lv…`!,&j, A"R^+"GZk \vC#m""^-Ֆbp) R/ 'M͟uoM5j'^8Vz?}-- {A =˞cPP}s,w ˩zE=Ν nKg!i3JIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-event.png000066400000000000000000000006541345766322700257070ustar00rootroot00000000000000PNG  IHDRabKGDC pHYs  tIME 5T 9IDAT8ՓJA`iS,0k!>`1XJ !xو\$kH ڤ)1Hc p B }i%,AŌÛ$)"\ehGn:<;%$7Vs蠏)anmZ G_°]$>qFP:Tc^Ne[kG{ay}b~awu CsJUB,c&KWv%-L?ڜIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-invisible.png000066400000000000000000000006031345766322700265440ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8œJ@gAlRRɛXXViaG*`*lٝ\c 9afYuk+a0ݗey&8ZoZk wEQl[kh?\Zk0|y.3f_h'f Ƙi۶>ysu].|;DDT.8b "2_ [D#" "(`+v 0SO4}@$R#?IqeqL [ԭدIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-muc-active.png000066400000000000000000000011201345766322700266100ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-notinroster.png000066400000000000000000000006031345766322700271460ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8œJ@疓X //`y!EH`'()ˮ Yw9e'9Z'ZL}4MeY^ !y 6˲zg ܱ@}, @J4l`Bޣ(-ۂRj3qZ_ѵ`9۶t]̡WWHd(yTUV@D>'JDJP"8Oysk/H ziIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-offline.png000066400000000000000000000007321345766322700262050ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<lIDAT8œKBQƿ/1pBZz('XC:.M7(ݣy=@Ag:ncNYk^6l6mWNy-˺-Jݍ8vz`}5 3姕nws4u9GRjRL"u"K)fL&H$0L@D;z%ObZ-8,$ "ID "!eYDXi ( Bqy_Vu1ǙL"i!0^hxK|s0zx=h{IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-online.png000066400000000000000000000005431345766322700260470ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8ՓJCADϕlml@$?@A{Xigco XHD(؍*6. 5IVrE@%64 [\k[nI,.9O#/1bȀ>z+h:Ԙs 쩮x#Z8j8"cWLh2+G2`><⣦"+ZJHdt8td!pω.4--v vnl"Eot㧗u|=IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-opened.png000066400000000000000000000006241345766322700260350ustar00rootroot00000000000000PNG  IHDR 2ϽbKGD pHYs  tIME/+2!IDAT]+q?/_70YdH~MQJ[ ɤ &(] eȯ^=} *Ll7' =٣vIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-requested.png000066400000000000000000000007571345766322700265730ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8œkZaϋyqHq08P^8IbyuQ\ui{0.8hꠓDRCBH w<)nn$y{D ٦ؼAV;3LEQ~N3j+B^7|~J`&bA<+ SIR@)۶`Y\=Z:Z$H"#`:lu]|@)u^&R˲P(0zpԕ%&"? t;hZFfk ^ݚo"n1kd>j "$H^f eӻy_t?IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/goojim-xa.png000066400000000000000000000006261345766322700251750ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<(IDAT8œ1KA B6وb X-N6֊iYXdGgKwD4ogfaWLi%_x[< 8ta 75+"ˀ^ h- =K}5eL6pUR;4 YQ'v`(\*0v ۝z}vXncf¹I &S'ND#k b_-zrp DN,<'B0Ӵ87@K) ch8xp})\o)@IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-away.png000066400000000000000000000012651345766322700251740ustar00rootroot00000000000000PNG  IHDRatIME'bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8c`@@ -@| +/FF{@B vb6)i)]?)tnC\\jfV n%_9s/9򿪿?C膄spqHcOW?p~Y50C¼#5o>c O[?vK.Nw@x+Pya_};x\( ҉\7꿂<Ȁ:h\nԳ08WdO 97dAsCzws92OEİor*nSrLfB.g$T)_pv7BP@3$r.?WB#%<ی/ٞ3>D5銎Hq\]W̺zZŶ+re3Hl4Mž㾃9\Vr6?j`޹<>l(yVۧ*w-W-yQÄ:r`uI7ḘZUj{ɇc02KyτZ''HuQ)DΚ0MLX,PGGG=r}N ܈̗IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-closed.png000066400000000000000000000003701345766322700255000ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8c?%f+! ļP Ӂx #8W $n > ċx7q/e._H d8jOB- ,$ \ t3lLJjIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-connecting.png000066400000000000000000000020741345766322700263610ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIIDAT8]Mh\U{/&iFm$6?H%-*.ʅ(""" "v)Rܤ5`FI[#M&qf2t̼uguŁOJiWZw`PRR9=ԉK=kDȧ>tV[ -.w _B¼89V70>.{Ez؛"VuB4ϵ7BG*6',ԭMp:&RJV7\kؖ~`ۮ<_oJ7"SDtCY+~R#7<ӮffovZ]RǏ1RX\J l]0 Z +YʒYj]RQk:@%ECHPJ&0栥uОIX\߬$R^:1)o ^{ign !MҠtcgC6SwFAa~I_ t"UfW\>Y: 4n+{gR04RxB;Oܟ?,fCIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-dnd.png000066400000000000000000000011621345766322700247740ustar00rootroot00000000000000PNG  IHDRatIME 5bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8ˍ?Haq- ^*l pJ$" 4AQI"6XP-A E-Q-(:E3z5M= ps"Gq ы Ɉr  _yˊ*rq\|ʾjq&C &<Ҷ4]tbiU?Q\SC*ew!^$PvRqE1J++mj|J~_A<70)rY;NTṈcCr }!χ-χ#t(%tڊdcIUtt[&АZJJ6@Eg1mk^v2YypkZ2^~m@MxGd +[B) [Kx@xCxKxH'b-سY#$ю#6GB^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-error.png000066400000000000000000000007661345766322700253710ustar00rootroot00000000000000PNG  IHDRatIMEg6[bKGD pHYs  tEXtCommentCreated with The GIMPd%nZIDAT8˽JA,!"nȺ""@SQA tSt*:v zC u0 4ßA4;D' 6lgWAjb͘sqдN9^ NK6;'̼CP/`YGT7HdtX>:$7N`8.{(몪nz<0lnFɼb@ BѢ  ($`/V@OI*j|G^4._f\]TdXZ4[S3COeYn'YvPzIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-event.png000066400000000000000000000010201345766322700253410ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDAT8Րjq_v[@, Im&C4^>X< EZ Cv5 h6%xJ5J.```f{L{+,_^tq"O=ggw;b]8v`YuNQ`u/<qz=`zq`p Ή()ʒ~ Ƙsie4k7,UEDPU1 _i43W Dv:YbY6ժOȲUD"R.yx/_ RlJYN(Vx\k|F`*QRXYacôz$I>A[K0 w>V0:n `{(Nc;q>)kIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-invisible.png000066400000000000000000000010201345766322700262040ustar00rootroot00000000000000PNG  IHDRatIME4FbKGD pHYs  tEXtCommentCreated with The GIMPd%ntIDAT8˕?Hq+Ehp< H- -Q--S.!baPAACK` ACCC-Qџ?xhO?ihBnqB/Uii۶'"HR8S]T*%*JbX,:a̒$|nq8ORQ3XR\\V1w!nL!YǤeY:+8EPm: &b0Ni=j8$BG{~%QyvU_=,{5XlJK[ؠo܅?p͚tʘF(V<~abKcTq7Z '\ˋ5yɼS/ !c`Afߨ.?rIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-muc-active.png000066400000000000000000000011201345766322700262560ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-notinroster.png000066400000000000000000000015251345766322700266200ustar00rootroot00000000000000PNG  IHDRatIME EbKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8c`\@@q'{1/@|B@@?^^^ cffb6l󹸸>9;;?~WFF?khhwtt+Pms )55&&@XZZ{RR->>/@~345<:sEVV"VVVfGFFF{YXX~Ĭccc{ 䫁 (}٩ tv? ?klljiiRPP3ͳ/OeҥKYOTPPP* /-Zjkk;жWX~=(@&N(4YL|pppeYrnڴ1<<7LĽ[2TWWG@!rJsssnYYYٳ>AcXgiiybΜ9 jjj?@8,,l*g<cIIf3gr*--G6| `,2A| > Ly'@$'%%O@bbb3aʸ|@i&nL,OWKc3[ Ŝ\odW1#۲W݋)p3 :LMMcutt^-z6,Pw@[>3gK~gFP&P i,IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-offline.png000066400000000000000000000007701345766322700256550ustar00rootroot00000000000000PNG  IHDRatIME ;bKGD pHYs  tEXtCommentCreated with The GIMPd%n\IDAT8˥ӿJP"MtN yqp1lVt⤸5 &T$)";Vrp#?pp ;0+a:$ad6YERDQ$<{ Pa RP^4MnSբ$I}uK ra >FAqSPHe.y >= Ch H4.`0%( 9C p]jfǹML eRU5d^Qs\p8A+5Fs\`o#_etlb:9p~&\B ˠ_:27IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-online.png000066400000000000000000000012671345766322700255210ustar00rootroot00000000000000PNG  IHDRatIME)%7bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8˕MHaFw6eaJ4cE ]?vFvXP"=D\/EDA:dAQTE!T "KBGMI3(HkOwkC<#H%. LeqXEϮu$em'.Jv[Ɂ·a6P;PR6m2&#X!nڽLf$I`|yMb "w#pvQ6E8sÌ8U)4oRK 6A (\r+ ~}1kau\0a/Obob] A*.;U'Zg[;׋U"/#pչ@^'cQtZ貺}Ԋfr2.ェ6K@LqDŖ9 &ಧcfkavߛ7mzY ] `dxݴd9c\4' }ijEW9ʼ#~4SDz≼Sθ=/惻 -Q9mN'ku &>g+IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-opened.png000066400000000000000000000002651345766322700255040ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<GIDAT8c?%a*@ĩ-.,/&2 fx/.X `t0 $e徇IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-requested.png000066400000000000000000000012331345766322700262270ustar00rootroot00000000000000PNG  IHDRatIME׳bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8c`\@lč@ Wq/ ` (((\>xLMM;&&@p f9卍DիW 1[[YYu aaa;/_.Ɉ͆"L~~@nό6Yj8g++ Sķ4]l#1JHH2@&..@W8١P,0r_TT4H rpp8TPP001_BBBa@ 5 ( ` eff~^ @dxh @/GS @w& Dӧ IJJ2{@|!MVWW955O@!L<[JJJ02 f@}@ %6_mmmb}}}>ydI&&$$d( [Laeddn0'ʕ@\ćGP-j }IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/gota-xa.png000066400000000000000000000011261345766322700246370ustar00rootroot00000000000000PNG  IHDRatIMEX(9bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8˕=Has+%.(&A hpj\Z)hhɡ(FuUt-p(8_O4/ s9M$×onP 1O_Mt=.n&UeؘQ}KK<*uvZZ±^XdueVV@TrP69Y7D/f!|D( ,,b7iU^es30?.BANё t^D f ac$ai YљTܥRaq8RKe"Ij$#TKqk ^cy>bohjV #k_#yM K |éK4į[ q 힖aW}[NbK᭝[ͽhCJjf>:aeIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/icq-away.png000066400000000000000000000015671345766322700250230ustar00rootroot00000000000000PNG  IHDRabKGDtIME '8IDAT8}Khe/$3mnh1II5BlDV".\.܈+\EYiV X*B-VPJi&61%\^)gw\6[{{: jݻ.1 bTWo%ZOzcao?rR+tlN9 %Oؼ$Кx$Mw<Bu' GxAxV=ƥ/V%0MZ ΢q }q6n^oL#{.8r85GzUdnkݾ"=^GEp Z]w;?0fIwRMr`R@*9#Dqm׼u^J&~v9<64+|jbu4ZME7{ 5"*a>#tKN 2\]"<8ľ`Axڥ >!N/@DKLwob4NVY.MĨ. >Q׿=#^ynzШv*(^MC{LK7~ Zvݘ!1:ߕkG ӟNbj}p{|ظ&{ u>X,^:@PQ#YB;Rxun~s`cUgѵY'-5ڶSt1٧]*)PMb-$0;?`XO N̰k)rnCwT?6]Ƙ ipkRucb.Bt<4IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/icq-chat.png000066400000000000000000000016551345766322700247770ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-OIDAT8}]le?kKV6ɠl :u3N'ӘFH81CD@4-F:"sA`h߯}=#D;y+O<7Av,릌~L) x`q@Peb&'s^j Vig0Ch^Ua- HN=7 >3pAo[_aa/ŻJm GcYX0yy=ZcgT\ΤJB)Ynt'Rs*ra+n&ԋ54M<3nܜ#CІFM`܆r=L;yZB|tvBxɒ3dZKH$>D\VE\o4f/)dD i3IQ X- TccIrC<w2F*ue3  ZWՀ1!n]'2b1&HaO Q@^B;vcێ70ޭ϶Cs%uUo dHũ5x>H)q _nx<\IgTE+ Ô8wq Vo T ,ba!@`9N.yu;} ]Y-t0Bǃ*jƧԣH{x6rΝR=|`oz>T ڮyQaPts{WV@F#hN*)).cL,x[οP_SBʥTO_m[B>=豭V28)R.7}3wvkAIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/icq-dnd.png000066400000000000000000000016501345766322700246200ustar00rootroot00000000000000PNG  IHDRabKGDtIME '8JIDAT8u]lU9_kYWڭuj')c,lD$ Eb­ VD1$W&HF"C,3΀huk~o7}r`} <`61WOk?b}oٟz+c_މd/0˧0~/N= ?r]4$v6ƒҐ_=;gMf RJ(%)oo[La^O8: x:4M:wxǢE`}m1*†L]<5zҌzDi Rdr)oۏ*j#‡ie`ȕ33+*ğtg3]}^[%EIc7W K8HR+c3?9'(RҴm0#^I['TݨC*YSqWpn `W F6u@.B}~K8 5Λ4O\z@O^dPpr/ )UC#>&e ыh 07 ,O׃o8eCC@3$s BWೇS)XD?f_0՛_8K9TG&$luɹBlp7*30xg[mWC+fq1u)k`5WJ#ڸ3e*o ;JAL]ֈƿfD^5uPlЁ8ۺI#H Y'xOں ٛo^a&}uz2}2cK#2 =s_܏a8<-}M~-xQmlO+l!7/mp]v )"$mX[]+xٵQ̆^ l[ҏ?#sؑ| ZMX:1~kkܝYe6 vJn|ٿ;R$JL^V8~,˒3NfZ3R){Q:ˆĞoZAmR LX LU0{o^S02!m'1o9Ҥ4i2 M@@" EH__/ ]۫DR+42,O\nZg8ctR|8;=9;7B} pIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/icq-offline.png000066400000000000000000000016551345766322700255020ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-OIDAT8}MLU}OXuZU+ZS 1&"Ƥ;jfbF766q;M4p eb ]hM!03u =aE: q0FC$R7|>54VFl3kw tidz5804AV.{4UQ!{~ho|00ѨD<b܅o %Mo]Y0u3Dt$JJ&4T*aHRI<v|Ttez}~B!X^^lw6hnD<Im[ZIMO:wޥP܍<%~BۏiMTff\aiTlol; ߆h({9mms7k-/; ΃@;ً@;,oF zKpuHC)dh^> zEC@?v\iK>׆sO'67ڲz.Ȟ ?n5~~&eYMQS #T*#(W:^3NRum>NZX ""M$srr%""tsʗj:,QfM| Tqjr5 *\.wp`VhLH$&˶t+m,޺%+4̽[6e hlnpc!M5!CIۿ`yΉbq{>oİZ9'㺬Tf[3g>+PQJUttntk_񇭠ȂMeIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/icq-online.png000066400000000000000000000016611345766322700253410ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-SIDAT8}_L[umiGFA+ (6; M"s!hbL=L,Ƹ8/dce 1 Cn0(+3I9O6}!;L$tNƌQHC|j'7܏_^[=Tg6_5+< `P5JO]>l1uvx $y 5G8yQ@r(w|rԊŷ`J4k(hY{v,NefyW@_c#뺸6}Źs#ff,HJ*kCrp  j4(v:AzR wż`1ahX<ڲ7A /@ߕ;zϔX_. ^|Sr8ȬA`ױq__(XoQXka͎NW&V|v{?Y#4$ k\鍞:b!IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/icq-xa.png000066400000000000000000000016001345766322700244560ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-"IDAT8mSMhe}%YMLF6m)&Z0('Aڛ=y,"M)%ReY +RڤtnݤMy;+J7o!y5e蔵q7PZaf03Z"N VEOS>nV]^33(( N{x}{;z"׃4V C]I䀔"ZDy|wz y9]IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/irc-away.png000066400000000000000000000013511345766322700250130ustar00rootroot00000000000000PNG  IHDRabKGDtIME TIDAT8mˋTGT}3F%!5մA"($qֿ^ 0QHBlE1_Y {Nw:uFV{Z|֞g}k {c_X]Z|qq$yn˷sNJBq^ B؞C@7V+K繰c>::b5$Jb =@b17oӉ uRsDQbZwǭ޻CҘ:O+SM|pS^<^pȩ]B|MO#$1/(G5r65 S R̵حCgu$5ʼ/. Τ^ R<-t3O 3ZSb y^]i%VS:RU*A36/3; @040?Ar}Œ'''Ȥ mf ieU\(>.qV2}HdcPڞ]}LWIxpoFM:c!O=IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/irc-chat.png000066400000000000000000000015421345766322700247730ustar00rootroot00000000000000PNG  IHDRabKGDtIME QIDAT8UMlTU;o>N_j)(ta"cA*TXą 2ngTn]e!dI hL4a%-*g:owuA:guO9691c;nx153M ήtSc K,_RMeW';<k-k7\XXk?xIkCkrI=h)љr,.]h :x`\MO37ӣOtn5$gF^[&a+-k-t,ơ3魢s5J\KpmʍDSS+My㵗5@S`cݟ~gjr#ԃ:+++\x?KǀcO:ߛ: /.ƽ\o닗VեëߜKo:84FUͦi*]ru]7]}P(͟/J(4bEW|k3. rk-GK}ZZ!pY?LEFCɽ-}H FU$#oT:V;'Т^P>6sdhwV898n߫1ؓ|qj#tGC"88A>9! tzqW?̑"8Kp&%Gz3z/JyU*y&i6CDT+x7:>wXқ[Xk|32_~#m r\IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/irc-dnd.png000066400000000000000000000015311345766322700246170ustar00rootroot00000000000000PNG  IHDRabKGDtIME |IDAT8UMh\ek2ә4ɄDcChR"V(5dUPvS2k*2 bX4A,4VZskvFͤ?ә;;.bY9/{#GHgu&_}y0.cc ~/dR4[>LM\1| AkzM&3Q&D>a UÇbڴzJ%:!bY^iїOb!g?o5e Fk:k`/!"ٹygvn}/fK5 .]ηPJד^@O!߈EpEY|.{ŀDW)[tB:((fW:rbm!J1 h4B.lhTʄ#^;Ow+?sro''ay@[Ʊ%-QĽ/|6BPwox}Ԍ~8 tı] $ӿQڶ}إ%P|cQūgjػG<3׽ ڢؕ\ZWwaWV0). "k]^tz(A( g*=* !G[TbZCګW)+qqNn$s^>|llvm_08[ Onq'3GN9wD6t= y`mqqhIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/irc-notinroster.png000066400000000000000000000014141345766322700264400ustar00rootroot00000000000000PNG  IHDRabKGDtIME  cIDAT8e_k\En6m4Wb)l[#ՂVAP^X(H9 ji(BJwmƶ"&{v9.ySԍYn] aG<|w c/>k8ge9߯z>ٳeu rTuBP5l>$Ι7Oq3Z {4MF*!xA>[{DѨcBV9GP4FDk 1Fy uo9'~w3$\Y=>Lbҫ^*|<+eQ0hxWs;eYb%7^*53VӊIb|ɲLDu;(0Ɛe1ƇG5yȓպAyrZM()(jVVRK*>iDtQXk)0ag'I^vgY"Qޓ˿t©&[[[,,,L5Qyv wA袳U`ľ6ՈP XEaXߔ]; 2 8{{ 򗱎yrbn{c6G8qA؛p1;k8ZUO4]CVI*5IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/irc-offline.png000066400000000000000000000013331345766322700254740ustar00rootroot00000000000000PNG  IHDRabKGDtIME Q}IDAT8eSMOSA=s;{ RV7ưpabte!qW>$~!.WH˳ODEHڹ.лsϹd芑"wSD+p o[ `an^KKb{{J뗶6~~1rx|`0)Q($Xq6NHB?Fr[-N\zY8F:٨u8өYZz \ɝW@t$AJI$mnm6o=Jஸ4X9"l`mu(MnV/0H8`6 !E!o<*܊W8"" j͜5 36 Znϔw% H0lPhj+|?J9i0̈8{BNkeg-|C92; F(\'̀5 CwԓG;S< ({|dKQߔ͖8̧A*jOѽ@33/TTV:œS4v[UUI[2 ҈*Udځc;h6[Rm е8\갧@ѸZ.՟=e%IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/irc-online.png000066400000000000000000000014161345766322700253400ustar00rootroot00000000000000PNG  IHDRabKGDtIME QIDAT8eSMhTWνw޼&ˀԍ. RCJf,YvY .Eܥ;BiJZ1ƍANZ!?{L|pwww>BT3Vg[FF`Toܹ_7Kq81RjHJi4[wS̔sh,8@}^G܌( s n s9 փi M6 (ahn'gWD4GʬA$P0 3l)0 YA;MW7`yϟ bP1'@h{Y}hRb?=^ nAsddEEew89\D,K@nW@<t`S)V$nn9 v&qCcQt4I9DeQ%0M4ѪB*h4({P} \8FU<5(8=asgȫ/d:>| 30S%?5f*KO.7,!*6@Z`3>ˠN4$_I^./oYoSS,0k@"/.IpeI$EŻvOOKpc0ۻno?*/<4[!IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-away.png000066400000000000000000000017141345766322700263330ustar00rootroot00000000000000PNG  IHDRatIME8$WDbKGD pHYs  ~tEXtCommentCreated with The GIMPd%n0IDAT8˝S]HSas֜ΣN#51`E3 A3]d݄YAe6MBRSlYYj<ٯ55Yj{^x/^xyKR(HԬD:?VDrh@.:8_e K? X/,kvT%LuuTg$ !!\ ; Y,mXu`8) ~`Jw b?2Jެo-2]%Jsӛ4利DscߒRXW[^ҋ,E]Aӏ&=txI<#>,T׍÷/<+U0r>ߊmD_zPRRj&;0-d߿AKI؁QOJ8 f>6}3xFH4V&ZRW(x֙ˌdLލw[=2}ZLRA< 8U={1c @1e9HEDi4r Uz sAR'8`|>!IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-chat.png000066400000000000000000000016361345766322700263140ustar00rootroot00000000000000PNG  IHDRatIME!5WbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8˅_h[u$7˒&]W's ˄"9CcT͇=tS77Q>1/.hS۵-Iek$~'i`sCA;,_RRP(gf/m;thgb:==gds4g8 `NRv{'F'@ضdYnicAUX|s2| 8z K%j뿽YǑe=x\n +[៾8;< ǹ07iEݝ yZP 7*ϥj v,A2^c4aftqhLD]{梯nXo޻YWo##1= 1v|FvjToEdd<;.nkw*L`{ŭ5,\L\GSIu,2JFSSJaY8 rSϒy?!*[\fį/ dٞkmw=p0\_̟dB!4!Va-]ùJW!1طޣ4{BF*߷`oh/z4[z} Q5ky+Z^~e-7`@yUngI.ֺZG^o?o%6bXPw߫E3ٻ T/D ;!qX&0&V"D]F2iSG bIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-closed.png000066400000000000000000000003521345766322700266400ustar00rootroot00000000000000PNG  IHDR obKGD̿ pHYs  ~tIME )5{IDAT-ͱmAW`  ؕ#B9:6p59u`/_G~΃D[BIOZS*r}fLn߯%Lc)!m[iؗD[F"I7\(dIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-connecting.png000066400000000000000000000016241345766322700275210ustar00rootroot00000000000000PNG  IHDRagAMA7KIDAT8moSusshvm)ܧı!.#!1~dWx%\w&^x 71xED ͸Vڍڞ~JC}ܼP]>ƫzvJDPZ+vucӯ>WWo,ۥ!lR7k?˓~Zz)x{*9/6DPB]TXO7 .}]a"[Y [Tks5J_e |^o% p{4Fh6 Ja( [f"GH(V[i*N44Ճi=][QNtщʀ-DB[rdLlrEx!tO]xkrWQeM; XNb_czmCl#}2=򻹲"MAkcşY3{ڽL#|s6B8TEUmD[ +$sI$IŴm\2S+{M7'8vNYH)­Gn.`?,$ >2[Jx(Ca:mU?Vy}V|6~ ^͍*( .ev|,Y|JP}=gN)d(.խ +.`4-8&dsΏ2@˪&Kd*3@ N?apPG0ãzwڵO#})FqEF4`p_OW x2oIϹuޫU23@x {IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-dnd.png000066400000000000000000000015431345766322700261370ustar00rootroot00000000000000PNG  IHDRatIME/LNbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8˝S]HSacss;ss6م-4 4!iXAE,Bic zѾs H7? |_"D-yx~yy?"QRRCqqsZm/(vV}> [yWLrjC6;U(N99llK%H89 ڄ.ЍaF YpKE*=4LBTF3]6]9t Mva^1r8Xq* Ȏee!jmDf\xb]\x ~i  AWnh€^^0!S2;KpkVV+UN$'8pZZtO!$%@@!Ȕ EwcFtVjt\,9p!J)Y^&MwwӭB zE<-z~~MەS*H8DBw#5D^sqr+P TQNI(4TB7a}vI$NGH0HIW%Zm!\c؉m4 .renI&5n6w&lI_ dDR9m4.ȗk)9`]_q sd3 PnIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-error.png000066400000000000000000000012471345766322700265240ustar00rootroot00000000000000PNG  IHDRagAMA7^IDAT8}KH[QFDBBE wmPIWJU @ (]օBAFbU-]ԭPhTѨ_Q|p803"*D><y)wVS니Ott8Ft:OkDWUn`k0`vv8-2Ɂ܄e6$7u؀YMpHC23aj ;Q_[DQP | >Q v; cbP-S*+jjJKAU]$p+9 UrѩV*(,u`?MPݸ7>rի wPg4z4ɂꧩ ;[sXX$$ͯ`rki91: zKGő+IbFF`nVWyj&&`||jKGNgUf.{{aff *-izJJ1_X< EZ Cv5 h6%xJ5J.```f{L{+,_^tq"O=ggw;b]8v`YuNQ`u/<qz=`zq`p Ή()ʒ~ Ƙsie4k7,UEDPU1 _i43W Dv:YbY6ժOȲUD"R.yx/_ RlJYN(Vx\k|F`*QRXYacôz$I>A[K0 w>V0:n `{(Nc;q>)kIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-invisible.png000066400000000000000000000015771345766322700273650ustar00rootroot00000000000000PNG  IHDRatIME$:KzbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8˝S]HQڦs:sNtJ! e .xNڢAL[ *,Jdݨõs[m[|"D-9py>?APC3PQ x<+QXx&sgbYY1& W$ՎH; PYypdQ NÀ+c!}̱юVX&cu_$rsᔪ^Fg.ݍ5yz|o_xFfe'z{yy t5#J҄xj{{b1H$@2 Zm}\v }kh%Z~MB!jBо###U`6A0{脬7,̀+u_,fCv1l6@.%t:l[[p.wjADYV Vk477Rx<,)1@(x3EP/$nB]@iF`o23?R[[[X,;>%b<ھkeJۡ`` EJt)hg D;;G C o*IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-muc-active.png000066400000000000000000000011201345766322700274160ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-notinroster.png000066400000000000000000000015551345766322700277630ustar00rootroot00000000000000PNG  IHDRatIME 5-IbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8c`[X_VRr $삨BB'o(!Qz@Iy9#>pQF 3t;>Ho?}J˾>&\VV8W}AD"Eqq&kX49N`!hh4nDMvlr@A99^@WT|bEd bb)fָlK5 O̵>1ۘ<ϲ2\&- JLwF6`|Gj֞ '&sn3Ⴐ4KnUFƝi`CIJFhlxkUDW`sD'ףKZ8!k>!!aauvro/o;;]wu[.xb\͉~![LTT (XuIFI\\^/?75pscV`ܻCK(BQꯧ^^^'%ǩ@@74 ,:Ԥ2sReeÇ3.JI^n}0)7 &&џ^wzEҧ CZX|> +抦f 0yWecKS| tsMCcekз`%%ŷΪ45=b\ik~^ލ@vBl -LIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-offline.png000066400000000000000000000012241345766322700270100ustar00rootroot00000000000000PNG  IHDRatIME /1pQF 3t;>Ho?}J˾>&\VV8W}AD"Eqq&kX49N`!hh4nDMvlr@A99^@WT|bEd bb)fָlK5 O̵>1ۘ<ϲ2\&sd=/=\rr.kc<0q؟e}78ԜUtIEώ UddXjaoUW7冽?;rg{ Xq @.)*r0&8ওyEgXX1?)_QWW$'7VE)֋ҍ@IY=6Iw0hjwY6d  p]5]34s @'ՇYY7/JJVj |p!pUIѝQIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-opened.png000066400000000000000000000003531345766322700266420ustar00rootroot00000000000000PNG  IHDR dbKGD̿ pHYs  tIME j$|IDAT-@DߊEۂ:c'>$:01Ј"hfowv:8"k/:rQ\N˷>YY7dU>H x.s=nCk$=rj4~`e0ԊIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-requested.png000066400000000000000000000015721345766322700273750ustar00rootroot00000000000000PNG  IHDRatIME 2!޾S/bKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8c`Dݹ%HT:)&.4SJ`dx4qK!,?'Pń~%].1j. ~^yMf YsJT5iG,+;69Na)f!@ ` )hq2SL6 14RޜScbtzI*Cn:^׬F0P 4dX`1n.=ihh`wJȂe%+LbKi.zY0&`7`H)磌|;xwz34}imPncUgϥ-N|Z GYXއ|/_qwgsǗGYd3;Q\+pokk87?_k%%gbz(4UHНSTv8`_WZ? -'5 =- U 4q]@DR>7#@YDj22}Qm}0ic%630tfg71&MWJ?_2'UeJdvAqԌ4 ;88o(-纁ZvE0jƘf0gg*,hߵ@gl;0WSZ-ι+mgIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/jabberbulb-xa.png000066400000000000000000000015771345766322700260110ustar00rootroot00000000000000PNG  IHDRatIME $ sabKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8c`[X_VRr $삨BB'o(!Qz@Iy9#>pQF 3t;>Ho?}J˾>&\VV8W}AD"Eqq&kX49N`!hh4nDMvlr@A99^@W2 .㛁Wщٖ'kk}b1/+de# aM_ԲzVoQ5/7h^|gى b+NL~b8Hm&`7\*h Pe/}˪?rK-91ED_߉N嵀1qC ځ=U}_>k/~__Ewdş,Ws_VA0%s<<;. V]aap_soo{/<?яe|;1Al+0݁h{%EEN}k|[?_ڞ׿`XDϼhpI㼀3,,@$eǯ5xOz\(-$`R.&oNwsgoX|w+-]y-Ԍ!?{w]~W5W>xYA!暁A00-fNn󀼘Yқ56x-0}-Ϸ bdcKl[`YIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/mrim-away.png000066400000000000000000000020321345766322700251770ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME  c)&tEXtCommentCreated with GIMPWuIDAT8EMLe]XvgiQAP4h6$hS5c6Ӧ1jlmC5XAmt(,,,33\Wĸ4f2+RB@&|`!gw7b/xq* BYFc;k"BܢpmtRn- kr=;M 7bh}G`f)r:ǝNJs#HYvK{Wڧʮ=Gv躮jqqqqZr{LKbtZg=Oգ3o0aг-k@W#r4?蝵SC@!5 ~ַUҬK'W+[?w0%4 P@!# 6OH ꤮mVf<U(JhZNH#(*_-Nn )Ud7VR},pieds6k2%rbkBh(PJ :@ Tx<Щ@DbIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/mrim-chat.png000066400000000000000000000016431345766322700251640ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 5#tEXtCommentCreated with GIMPWIDAT8U=lGK --lA Ep +`0?B:Hď`@ jLL  HBKm)w?Yg{]ciHRPT~N}J*`jzQ=&jyZgBy*`6Hufui,TiL޵֪.*8]#iIy 6tQja6-5lȀe~uȄ24xgbZVod}:|c (R$PA$n)+YŒŞToDڽ<[d9N qm\2[\œji7)׼U/ž[VLCѝwO>V  D)7.XQd%EϧWfڒ;=ӃÅqL1 #B56/ֺw46ԕ?{\"#(?w`M#gef8KErRAzsE$RȎ)LN(pKf+sJP9?SkG4pxm5/|I&\5pGo)%t-V#~34^ g[UYRdPodӷF8g{xTbsMYE%4JZƊ3leg`PV+d͓3=^weēuܐIafԢYlt1ߋw<-&^jۮ;n~vh w2KQTV1H>0 z>II%K<1kuYCZM~fwJE Ɣq 4"PP& iycMq))}mWzǞ(?kˋvҘU@$PQVV(|v?r`n7D†'{86=P񇢢zjL cG̔jJ\N<=fSFaw}V)^{ =5jld2q8:b& g\2XN;謏M r|>Z0_MͲfX.&.TTN luDYtq)J\$ 佩N%[\vl̳N.6jg msR3yA>/+ ѕD]|TA~tEY)uj,Ug]l`9d"ܽ y}(L~y|0R_g;_Bui^* $:;;{~sRCӴgcccO?ObvvfffboR1ŀy &1 CjJ/VWW N`aa.gAxFӴj^E ƒH$rl⣣_雕J۟,6M(tZ&FoX]-$LLLL&ojv`0cHo6 RiwC.ld2H$$@XY^^4ccDG\sG~QU建|K?r÷c=qxx*!#mύ AӼ,˪4|CQW@,Ͽqh#i!1G)xJ)1JiZOOOwJ]/*zi(v?*B;Bb ~aYuJ)GD@D1_w4M{uԶ8祔nwX,^B\GĨ}OHFK)c%J)"Jv0w)<ni$ DRJRDL F-YJZZ(0R>vgR:RE,k#bBBR}D[[[\]4mZ) C<I4t]#0yϲ0119G8{fT*}q.Ya=n'Hi3Yu៌FfXLKSSS+gggVnef.s4AtM,cH0:y1cs˲4s, x4!333u(TP(|b{uF0"Rjn>!)LJ)U.w]b[0"VfYVO`04 @DubN9FIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/mrim-online.png000066400000000000000000000014561345766322700255330ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 4;0%tEXtCommentCreated with GIMPWIDAT8MOLAxy0di9c.˲Hٸm١q 'N/a : uZ0au]zTx@rs>슏 PxsqTӮ "ZxLFΤ)%W!Vݴ`̂;Ljdj")1nyZ#V_*IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/mrim-xa.png000066400000000000000000000017511345766322700246550ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 44;8;tEXtCommentCreated with GIMPWDIDAT8MKlTU@ϝ_3v %JvӰ@1*vą!A,J܈ Ĉ0 JuQͼ߽ٜ܇rP;;i//N:hBJmf&d) JpOW3.d. J ˑz'wmg%Ñ<[*,;KeuptB":DGB&<ǗP7F?1-aJlⱱ^>5>ow2/p[%{u&Ϗbjt~-ե5R>(Lr6=e 9aRҴasf{Ɏ $^;T6xmtD i^:3qM&,̬s[ؔ hcqmumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sms-chat.png000066400000000000000000000011411345766322700250130ustar00rootroot00000000000000PNG  IHDRabKGDtIME  :+ gIDAT8KkQɄ̤RbA ҪI _"x(V܉r'Rbd,S$t9.clphX*/z^? 0ȗsU}}L\?bry` zh` h4͆DžGp]@R 4Wh8>mumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sms-dnd.png000066400000000000000000000011751345766322700246500ustar00rootroot00000000000000PNG  IHDRabKGDtIME  IDAT8OkA.1BRI[yBgA R<(?/ T?@TŃ~1lnvfw<u.{w^FJʬ(πe;A;~P4ӥ8 (k䗗aNNioJݘVsG޺FAbhbݘ FT)0/[=uh IR J8,@?ql( J-Oe2h= H)D777h}4EIT%^̹{TBlj]Z+z?s@ZC7xiUrk:AuM!j䄳T %GTb}4 &@$, ZFcЬZLqwVJTB:bgzK".hBաK6Ų,,ƶl,ms[8Nbˆ=OjLۢTXfnt 187/ RsIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sms-offline.png000066400000000000000000000012031345766322700255150ustar00rootroot00000000000000PNG  IHDRabKGDtIME  :+ g%IDAT8QKQj N RYB^B_@KtэPopzl1nw}N6>7{QT*M$)0恵8\v|FG('8urͺqtQDbq=/]շg#bi{]Z'>GS-kfDZkM:)79h`ɀ_ zFovtN͹ӷwޯؐ *㾂+;_܋XmumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sms-xa.png000066400000000000000000000011411345766322700245040ustar00rootroot00000000000000PNG  IHDRabKGDtIME  :+ gIDAT8KkQɄ̤RbA ҪI _"x(V܉r'Rbd,S$t9.clphX*/z^? 0ȗsU}}L\?bry` zh` h4͆DžGp]@R 4Wh8>mumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-away.png000066400000000000000000000015531345766322700250470ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8mRMh]Ef;o6OlLlSfc)*X(? t#PE7Bp#")bq&P*Z\HuEb[H =m{3wq|$gq8i>ADsiq2{w>T*y=tDrν@uˬya4%xVN6Gwmtg;Ѱ?3GyWVk{}&澰iq-c[Gw1//?{Šolu*?)׻^ w@ '叽#psZa~P7үpta ,2w"lr ٳp?, o@t􉷞 g3;BFDN˪}w7!~xO_ x| 1"sH)ADp!TK˺$IsH)cD$`!s0bY ! !Q?BY!$1ZkeB Mӭ3㖁8c眫( Dep΁BPeB1X!.&eY "(P`R {cBXlaa!j)eB`s,an1*cM>551cι17tWsG_[kuuc0TڹVÉKKKOJ)g!RUVkxIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-chat.png000066400000000000000000000016401345766322700250220ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<2IDAT8}]hey4i5bijWN:AE Na/*ɮDKA(ml Y`/Jn:7ݺ6%M7GtFD5秼ddhbhSTDĬq) {һiAxh3mV@OnB6HX闟U#啓vhl0:l rU1#;H`ܒ S Y<!Zls Tu%e?9E/`_s͝WYEQ2cs=(]ZǢC#& fQK2o j--=I,~2- ASW?w57Fa|@ů e`}CsLdo4ʥ$+WLox+ lG˃|\㙷囷sL7ns4,+\Tm8S1 7-dL(5'UN乣';hWo[&:2z 6Z8[`Vɗm!=Z|0v¹z7@.x[YXf>kg-j>={RNr|qp/H׹ƨSwRC"J]0;51F@8BԢV+j( k?Z5 Qo؏(k߭pI*DGWɧoДܰ\%CDU33/%;FIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-closed.png000066400000000000000000000002341345766322700253520ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME/u)IDAT8c`b2Qj.a;H4Q@z=VIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-connecting.png000066400000000000000000000020741345766322700262340ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIIDAT8]Mh\U{/&iFm$6?H%-*.ʅ(""" "v)Rܤ5`FI[#M&qf2t̼uguŁOJiWZw`PRR9=ԉK=kDȧ>tV[ -.w _B¼89V70>.{Ez؛"VuB4ϵ7BG*6',ԭMp:&RJV7\kؖ~`ۮ<_oJ7"SDtCY+~R#7<ӮffovZ]RǏ1RX\J l]0 Z +YʒYj]RQk:@%ECHPJ&0栥uОIX\߬$R^:1)o ^{ign !MҠtcgC6SwFAa~I_ t"UfW\>Y: 4n+{gR04RxB;Oܟ?,fCIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-dnd.png000066400000000000000000000015301345766322700246460ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8R]hUɸ3vԮ!(DB_SD bA)De!ZT}) (Th4PCmu5lwνΌ+䎍y^7fffCRT6-aCxivv muu㩩g,B$ގ}o&xA)0 Q.GQi}rtt4W.i4s!1 @###mAfMqjBN]ADRB)u!c i" CX2Lu7ui }0ƐfAD<4MeYeSRJXq9G.CvRBu@XaYU1jFQB\.؀HD`:8F>GiD ۶'2)p2BI@)0 XݭCF@BsN)fY2.G,kzy)B($2n9Rbދ~T*@DD+"]{ۗHOgw'wAs}Y5%7v/)Ϋko0;h~^ƃD2wO'զv>7LLD <=zn&?ڙ h&M>Vj}0n/GվJ ]."­K#ށ Z8ʼIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-error.png000066400000000000000000000014771345766322700252440ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8SKTQ=Ψ)ei A E~:j>2BD79#jFBTtr,"555%Sqf޻k3`5>=p9 "?mae˿8~UM*sԠ0so&6 Q+[3W$=dYS="@|8.-9i0|>T>Bx<mM*[qLV倸`KdN@DX< EZ Cv5 h6%xJ5J.```f{L{+,_^tq"O=ggw;b]8v`YuNQ`u/<qz=`zq`p Ή()ʒ~ Ƙsie4k7,UEDPU1 _i43W Dv:YbY6ժOȲUD"R.yx/_ RlJYN(Vx\k|F`*QRXYacôz$I>A[K0 w>V0:n `{(Nc;q>)kIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-invisible.png000066400000000000000000000016171345766322700260730ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<!IDAT8]lu>3;n ei]vK)!i6l0bL 7C!h"XBRJxZ 3ӝ˃}&_nrߔnv<9ǘ>:9z^0R9}iOZĨ5o$ɯn&Ȭ+~ml(<ǘLIU%rɫG7[)-O1_ LX>2>STj\}(r慆C=K{v4NV'HݚZmҒU)\ǩ#DwzōLO::$l1E]@{g5'@1W! JI{?_ wν+s.-F5 -Me% ;D 51XdUenF++Dqtvu!>ϑ_&/PJ)JeY9~!&ݾE@VӸ`tU/.1Vm>+':/k,2JKB&5g#eo#cv5gm;55e{}vɮ #"cL (`\sBJAU[!a.7)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-notinroster.png000066400000000000000000000012501345766322700264660ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<%IDAT8kaƟ~ص-E-"do.A"RA\E)5L]Һ8tHl%WҴIyR8s9,gRy ec̓\6=Y foO'L}kk^uEq@enC6={K1楔 ƘK"Q;;z 7j !1 i7B%wM֢1677a.H!Ľ+##n2yN!0@k 5h6dAq*rjC }})$AkADB@E" "''o"`as~8` \ppơDo9~ a/GZbhxaJQ:PB)(((zF(U"s|'Ϳ2~%T]9i?qW]gEG+:?…; ?=r>:)\n RV ^>I\W?.b5o,%/yvw])j/0E5wwًYwwq79* useo1Ɗµ+n*Fh'z!RM 6 ZAaid[߹ϯ+ PF ׫lOɬ<(5j"xA޷ށSqVZ^NMf%pʮ[{6Pҧ.RHgiZ6g +IqTK<=hXmP8N0V;IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/sun-online.png000066400000000000000000000015601345766322700253700ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8[hTgns$N! CZ-)B@Kku[1&Q|V/U1jTTWҘJAQĜdaa"ǶݼyCS7ޝL83|_ip//YtlgƻFO?(Qqy SL)w.\&f;3I, 'VS9\[og[F4,+[Tj٬KC 5o ]"a/x뉻fvuhp*|ϖQh IcNP[b4|{LS'q#"1>,˂(?E}7MA4 @)E, }J@ y?ApR0.<ϫBxt1q&A 28 ÀeY@u88!ATyȕWP$ xq@immeض u[C&eymCCCH$PJ `fP(JHIEض ˲:<&''c1H-MMMAX|"Z%IjEqθ{VY{s0JiۇG)@__}o[zI:jR`H1nZu2׃ǓaI/4!_]ߺH1_!0qKwMw=_RQGj8|ME-D ,<9'''NF!f'Tvc¨F=Wtel3ˏ^* $>@vKr-mmEiS?9lIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/weather-away.png000066400000000000000000000016441345766322700257020ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<!IDAT8m_hu?sl;3*3FR7 Lf `tQxeDuTye. Y03A+uRŜw}ۅ AUU~|p-SUDUװQ M5`F0geYQ?MN%`5>X/(Bx4~PAͬFc%Nw` ݁vmqkN4JM@\?JnǤ4]nCJ&0Xb$ŏ mWt^rӧi/H7yO*;a) wJTsQFiZi3|=Aq$cų&Lx 1jbo[Yl՟D@WDыU-lgN$IⱮr1o5]?>::Y|=[;[f^ 8HVZKr=k8/v=? vou/=R$IȲzNT*&=27_{KE{/xrpΡ^RpQ*k-7uS.H{{lذ4åq)*qS(Ȳ2"yTUT(( kmHc8i4XkDJ1c >4mX_^&{Nt33W'z#c F~rU 4}STw](y>E#-zurm(hHgɃW^+N{IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/weather-chat.png000066400000000000000000000015031345766322700256520ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uQMh\U=w{4i:Z4PE%.QWHݔ."H+J]t.Bnmi h@I:ޛ{q1NHa&#,6N=h[`GehBD㯗GPqk\ 1kF|*%Y>B_5OE  Pn[f~)פu#!&~&g%VzZ--+e}!;p kBM!CDi]嵾#Gz㪣9^0g`~xiK_6IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/weather-dnd.png000066400000000000000000000013621345766322700255030ustar00rootroot00000000000000PNG  IHDRabKGDtIME  9;20IDAT8KqƟw3;Ό֦պ(,*t?ATFvtKA(>dD:K)1W<ޗ!g8dUB!J.xW+ w4zx[k5i<^5Of^̔vk LN,is ĦSX]]:by5eEb+Jtndd!Scz%=ө 86BLDGGV ˠUЇQg>H2JXD>$IȲ ,!"Hb۲H$XC\]1AHkR]8$IB*mm0 zba`hhJO3?66~uR)lmmAtww!ЀJeb1PJI9G~%ȓɩ,#t:Fp\UXEYZuX5P"UMZ0(EN~ dKJϯx8 ^=ۻMfdq}R|j~oς믨Q" [Α/(~QHIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/weather-offline.png000066400000000000000000000007211345766322700263560ustar00rootroot00000000000000PNG  IHDRabKGDtIME  9;20sIDAT8J@ϙ4IxDq p .ŕ/ >kD\]iŊ w "XKC&߅k*;q9%"̚gjVT=NPy3^ Y˕:}X*Xrz8Y_)NW;wk #e[4F +sS>ahiHc3.w"Է-;N- h6)B2F v[a[v[B3֩k2>$TI|*#ŘʝIQ;ERZn@q7 Vxs)l 07*Yb) مJr"?2Aܚ\8')]@2V:ח ^5IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/weather-online.png000066400000000000000000000016341345766322700262240ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8]Khe_f$,IdRN.ԘAE QMADPl1 )ZUΘ;.4 ssPUvʭL{;%ҵj%(`yM4ob.鿴5^Z=wc. ~ ^E^\Bi'O2F!$0[\rsE GgĻA⎁I׮#`7 @I;AT}@0hM̚~!ne*j!6Ӻ]y$x$2`*jw0KeQƙ3ڎ(ʣH$bH[OLZCe|yngY/ ,q4?B-vD*Wsu#nqCJSndqO$j|ÁKw@e{YSmUW?,Jk-3>]7{#o97>ʍs<3y*UVQi6TU$l+_/ןFO^|zb28PU|NOc##y27 oX*BD0 "c JXʈn"yJdWW7qc!"(l"Ӄy++w1މǎǟkS}{|{j;00h jqٙb\}^k|^Tק_{$ Mg3R}ѴCayso@ / g0IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/weather-xa.png000066400000000000000000000011351345766322700253440ustar00rootroot00000000000000PNG  IHDRabKGDtIME  9;20IDAT8͒ORaޮU ƩM:fP"h7#" C22ڶhmU f"fHuL]*"\Ԣ9C3ӭI50G7V&=htB!&>K'ZRy"|7 ߕR?:Z0<_AiLڳ^,T*/ͅFȝ4Pʇ+j5|G:ƛkx:/~6-u$ h!R BL:v6MCID3m<(`bRZC)h4n1Q(1Vu$Lb00 R)X*ǁa>q D NҜifga' }2mp]=8v])8!a0Ӣ&jXA(+ha v+WN]~7ko؉}p)LIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-away.png000066400000000000000000000016411345766322700254060ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKluyl. J ۥADS&4aFoLxb͋񲮛h Ճ1jn"vw6N' !ؽɰ >?P(@HG#=i7`b2;rfW¯٧.Yh5[N\|wog`D!mzv O"p'^FbS&&ýWs08|ί|?5,K m8s7>֕TB >z ?LMKr +m\rs!smk?ǯe˷f4 8tgC-Z,'/_K20ݞdTUG1?-a}PU t^t-ik[:>d#$D3J Gyޠ PkԜl\\uph8 YIܦ\o-r5jZ,jozeIOj& zOҬWKb1B.;jKFC旙5}GMQrr:xj;?*S:V+t3(4UC x*#];wnxR),&uE:||Fв7pYnFzrh$Vܣp轞VybcK- [L]ߣL|g@6 |YNnYևq9k6l6?v}B IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-chat.png000066400000000000000000000016521345766322700253660ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<'IDAT8uAL[uі R]L0K0a3cM9}__n- ^~ _Qd D.<`xc㯖>3#gPGgwDdf/gAԘ 9;]=@Lk6沷P:AM-zvpp;i'ɨJ\ZRBPpmؽKOuj VDX xŝVCPR[66/7yq2=E`cYHNGQ}XVPL\ܯu 3(@ `fqh[دM(j`DuUT_DZ d5̽54T"ј( '&{v BTL:֜=dQ2$l`*"'t4uRF^,_ޖO*&~r[[C!­Ϣwʳ껓iȕO 5IKԜ&, akCL0+)늟z$ab)V~7 0UUm{t=}RRIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-closed.png000066400000000000000000000003221345766322700257110ustar00rootroot00000000000000PNG  IHDR <$sRGB pHYs  tIME ]tEXtCommentCreated with GIMPW?IDATӕ10ډ&&C<e&u{_€D jQJR͈IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-connecting.png000066400000000000000000000020741345766322700265750ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIIDAT8]Mh\U{/&iFm$6?H%-*.ʅ(""" "v)Rܤ5`FI[#M&qf2t̼uguŁOJiWZw`PRR9=ԉK=kDȧ>tV[ -.w _B¼89V70>.{Ez؛"VuB4ϵ7BG*6',ԭMp:&RJV7\kؖ~`ۮ<_oJ7"SDtCY+~R#7<ӮffovZ]RǏ1RX\J l]0 Z +YʒYj]RQk:@%ECHPJ&0栥uОIX\߬$R^:1)o ^{ign !MҠtcgC6SwFAa~I_ t"UfW\>Y: 4n+{gR04RxB;Oܟ?,fCIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-dnd.png000066400000000000000000000016551345766322700252170ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<*IDAT8uMLug;vma8ΌBڇabLȶhEzy27/nQg4&ZjYLeaؒB?ҽo=?Ó' !؝ᑰ-> Ɓe`))H#'k.Kw`fX*~xkH#3]O7ӬNM~#H|~nߌFb _Pk?3qe $ UZ_wEfV/_?WnIЧϿ?16&w蚆dCGWd$j$B}޻_Uh=;tn05?'ߌOp9=JIϐ^DT*܌x0(:7x{Uu^1bY8e@mi#LM&bYޘN@x:iD]pjnfҕl߇SӰ$ZaT*rZg;ĥjTE-*>.(YCTj]-zV INO! !4V+b-Y[P@ebBC0Z'o(%%${sܹi3UѴAJe63`DJ,cD{ #+I0٪8ڏXjpGX17G ~<+薵ߜ={䔧VU^bx;.[1̺K#ڪhv118 z{K."ʂGm~f$v!xvnr04NC"ǿαӮ]Ftj5|nO!,*`O3OX< EZ Cv5 h6%xJ5J.```f{L{+,_^tq"O=ggw;b]8v`YuNQ`u/<qz=`zq`p Ή()ʒ~ Ƙsie4k7,UEDPU1 _i43W Dv:YbY6ժOȲUD"R.yx/_ RlJYN(Vx\k|F`*QRXYacôz$I>A[K0 w>V0:n `{(Nc;q>)kIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-invisible.png000066400000000000000000000016051345766322700264310ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8}kU3gfMM5!UclFVi!⍗ UT²-APDRbm>.JƚΙ3NjA]7?a/ ` 4@׻?qx`~aT*y^=1:h Zͽzo6 w+2`aGLZf{iMlo흦i?hF~zsΗrl\~LT?!MSt-u-+^~b5o.q%I%=8z*"I9#&ZKYٳ>70J+q("lHb`!lEw]V_89`. uW*&V1 Rf$A%9#aﺮ8>r(0xPHuJSS{CF 2㢳>`hؠyDAC1hR#0m24Zwɩc -:yJ>cc !wRw`ލ{>xbqz =Oztz,hZ~-/A@OD3< u$ґXJrAL&ydk2XAva7 t7?}寮%cF}G?f٩ckG$S7oطFNy׵jos}#'Bnjw3lޝO'^>pv5h*qx.JOw7_\bO Z/|ItLdFϝ=C"U԰^USU8Ξa"8k,omc)P H&Rk:󺊛TPDPPcW f fX1@h@, CAD0ƲTջuH)_DDp:uXAXyhZ9ᅰDwPV0fa:~7vJ=^z=| q}XX"Z>ՙi`dY-:cXkD"mKtV:?]ʭ\U,g\y s;ձ>tY^^QU^럎z1!cDc6^4UvR|L /HH3U IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-notinroster.png000066400000000000000000000016341345766322700270350ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKg_|oM4Uc2GA6+vRv2d]C6փsFAHzkcTI7ɰ..6|\> |/a@r0́x0>9zS_N>OJ%P(~Z./fO퍼Dh4iiia}}o^^_1r,No))VԔIMl9i5Ơ6~[]_ 4c߲PJBJJՕʶg3tٙ_pix5Wff@kdP*,fP*23j<./^4 %Щm]dl֜xpΫ՚m.h[V0-v*²4R)JI\>(1jayR) #@tyU_nR9z(uǫV W(=+ϯ| `\ d;!hj>|~M[{pWq6ch p ǹ]WGgh3qw\Tl6=|6d"AM ʲJc 2 w[\/6c_5xRF)mofv%[//柩r4YK{&b8|ѼF4p;H~T__IgGxWB: \iJn2Hg۶/zc>?oIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-offline.png000066400000000000000000000016531345766322700260720ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<(IDAT8uOL[^ǣ Td ǟu2 یC>5zdŃo^ܢh@فddDV6ڎsPվσ8w>morjBt@Z 2095>|t7&|MUUEۆZ0 ><;? M3LNM;}50lÇ022B[㱵K_\|+4/`rj…wqe (┝X5F366F,X|˓pFJĄ޾NzddvV ͠( * .YFu(m3::ڲx@?{D<&F"n7ͪs:ǎ0[I,"ix̹V"#dE@qjGQF:Qn`"KXVMldp.U\4rGQ4lgzj667EJPہ J*82fl8JRܲr $SڎJ$Iwr4uA@{yij_pʃC?_M?, #$A!ݭue3gw?>ZZZ>TӇ㲳`B*ewweYjor&5IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-online.png000066400000000000000000000016511345766322700257320ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<&IDAT8uO[uўsJi)RrcllAN!q -޸n41x&N A8n4!!sL,`Ka~p=yab }.޼$d&&%"cF@\NkәS$`br4MG?1_5[F!`;m~rLvg###SP/,gZ=Z=Gd2م?^^\/HU !o\ݽ;`a͙ٜZ},ZcqGI==~͏a_EV$z'ϗQ749R_btdlSb?i IO0}=D5c3R`kk058m8tVqHj(Z#bNIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-requested.png000066400000000000000000000016411345766322700264460ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKluyl. J ۥADS&4aFoLxb͋񲮛h Ճ1jn"vw6N' !ؽɰ >?P(@HG#=i7`b2;rfW¯٧.Yh5[N\|wog`D!mzv O"p'^FbS&&ýWs08|ί|?5,K m8s7>֕TB >z ?LMKr +m\rs!smk?ǯe˷f4 8tgC-Z,'/_K20ݞdTUG1?-a}PU t^t-ik[:>d#$D3J Gyޠ PkԜl\\uph8 YIܦ\o-r5jZ,jozeIOj& zOҬWKb1B.;jKFC旙5}GMQrr:xj;?*S:V+t3(4UC x*#];wnxR),&uE:||Fв7pYnFzrh$Vܣp轞VybcK- [L]ߣL|g@6 |YNnYևq9k6l6?v}B IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/16x16/status/wroop-xa.png000066400000000000000000000016411345766322700250550ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKluyl. J ۥADS&4aFoLxb͋񲮛h Ճ1jn"vw6N' !ؽɰ >?P(@HG#=i7`b2;rfW¯٧.Yh5[N\|wog`D!mzv O"p'^FbS&&ýWs08|ί|?5,K m8s7>֕TB >z ?LMKr +m\rs!smk?ǯe˷f4 8tgC-Z,'/_K20ݞdTUG1?-a}PU t^t-ik[:>d#$D3J Gyޠ PkԜl\\uph8 YIܦ\o-r5jZ,jozeIOj& zOҬWKb1B.;jKFC旙5}GMQrr:xj;?*S:V+t3(4UC x*#];wnxR),&uE:||Fв7pYnFzrh$Vܣp轞VybcK- [L]ߣL|g@6 |YNnYևq9k6l6?v}B IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/000077500000000000000000000000001345766322700212425ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/000077500000000000000000000000001345766322700233675ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-bytestreams.png000066400000000000000000000032321345766322700306200ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 03a#rd-9rD-F%VwZdu$\O5#FeY۶rI$3\z/}e8>$/^qlt/w* ~k׶7"*zS|nj%؄Cl"?Ÿ_:N>+kadO&ԎfKvB*g|M XmBek6=<@or웙j_Q"Z}-WF74D-6 ĴĔXEkZ38ts{ufsc9)cV{`"unR.* ,>CI4Jkg};ڊ Jk$te޳g 뛍Ϡ_=[n:Ji4HUY--b<τ~/g8f3VTUEXv 55 3 5!Vi4}-̵… K ظq#BL˗w ZE(`Ȓr)/ڌ\rRNG!Jm^wRi"LL+JlWG8Zse*m]+ciܢ,iqshZRi^Ѫ(GNX*bQ:i7/^lFTFP*>>=͕NsYz%,BxR5 '2 '2ē.A{ xr9\-(@5o@ @]]ߵR)R( &Ig]bMl^W>;th}jI,<@Di+5ގѲ6Lg:w.MLl^fS)Ji\O!fd2 `b+I]-iS9?p  0 XXXV*CUUFc,N cy݈vwwwi^񬿿?ǟ @6T@Qˋ twwCUUgGRR)$I$I$ $ hvi8jTUk}}:33띝9ŜMP!А8研B4r9_7co)x4>>i8]X(>4My~~.9XūO< kl0Z+O-o.//#RiTUt}pp-(ZD ZV, B.`[[[|{{JꙕU*02Z+4(, SJO(7MtWvb!ԍcQJB^]T:k'{>hIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-disc.png000066400000000000000000000015521345766322700272030ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 03a IDATXIOSQM1,a2iwą0 LR!B 1ƨ!qc~D!. Py#mo i Ƅ{{pp 'cUU%9βf}P=*8]Q\T ۶Q_א5y"mH&pui!k@<ed3|#RM\k4A)  *;@uQY  ! ikU8a,GJY+W9kBDQق4T xöi"˒nB#mmr@AA(0M1T*<(P(u-ͭVJ|,..(nQ-RU:q z^0 [sV0;7˲u]= 7=}.'Rzkp[EƘjӸWTVV1&n8w/LLL `||eF*R.BՃyz _/5-Vg&C븺՛kT}[ HA Õw/|KL|^zBQ& %+pvO?&Wٹ:1`_rN^{_!Ρ.;S9(FңP2Nm|r@AMڮp8]0j٨)#8<]Gq7ך?AZ3(&ZQ3'DU-Q<{@#N \ajFQoLԉl=RtH;uF3^ٗ?ep+u6#qXވ"Zȕe9]1< jWk N<AF\ Z/Qo6bhyWO==s>`iHADKW:>߃#b˩E%7jZOö/0UEn\:d%} /q{w, xM -)ݷM&m9@qIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-gadu-gadu.png000066400000000000000000000033271345766322700301210ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 03ayIDATX͗mWyc! 벻U!mhشhK M@DcB*&Iɦ&֘ $6~h Ҧ U4ˋe),3;,^!t3'&2!qy--ŽkmƘZzw\UxO}E=6êKڝKR$"&DKݛWC Iypuz h~^LwER&kw0sk[ t-"kr4d2Jf$^P&@C(_$2!t-Z B3‵wCũF|kaUۜF+WAEaY۰uCdP#XUJkPM}\ZֶhA<ADa=B oVf'_qH|7wa8T:ubLo u~xι\-Sդl\ &Bte31SRȵg/DD'ms>Pz|m}SI)aRhxǿ ^#<= s6T&(AbDJgTc=0sx4C͡tM>.ӻr| ؍CG*lq)eF*wQmP ֘=nL)scck:,N?߼ y~JMu@p pf2ruwW/.6&t=pۡ~{H>՝x5xMK0f.R>Gi8<6ʅ}^9nA{0|8If@RvpTAYqayϞňJJj4RF穞rם{~Զ+1FFoݭ]uXJUZ)S3SLIvlҴbtIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-http-ws.png000066400000000000000000000037551345766322700276760ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 03aIDATXY[:kf_2!!A 4@R PBh)"@}  -dҾ>T*( Ah*MĴ LIfxvcksLRP+Ok߫;C|i}ch)Z餐"'~I ԁ{H Ҷ,e,u5XmSJV<&2 χWE WMO]]nMw+|MsF֚y Og~/>Y}V eSu) 2K S.^s6Z!xoke BlL026[X@Ê䰵-)"ВV#ɞ_5@:-"G}M;io @ GL6RļKEi@k@A"br, eMKKShph{&'o=ݛvmk9F)@qz4GWR`H!6X!rliVO__GCgk}OD-,S @+EWJFHJD6GB_!Mg\"_'kK{]3 zF5o0s]t59$bZvϱ LS<-1'\m G8=DWT|E5JS}[RxICn7lCN b!=,CbȪZA(I02S W*]e {6Кƫlfs/2ל W@iUmȱ"gfSR}uh ! h6P*Y9@4bpWO+3+R]P~Y\)g U@sr$֚.,p,&7V$6\ZqRh [gdgY)ػc$yDcѷ)FS2D[]pjd TFJ1\ݜH&ؔ t{xKW`4])B2mAi'Q _fX!2 GG惸cQ6BWײ+b!:[6#~MgfH,h_8}vx%1ϱ\T ,58\Q#^!0.s zxzWrDod٭ErEs2oȹ9 -pjdZlq39w7u^<4pb!\.U4 ʾb:E WU].Nq:P/f4r7ggN]Mqz$KP| -PտAS&l03fGf p?tR@s*\b) kuχ2+,Fg EwGAM$١_8i[;D4= M4dҘUj#PyD|B>0܍֢>#s1u I_K 'd`)GW /Ә=~#r^}gomO^e`Xjx]zn2x@i!2s9N&3 '{>6ǢHɫrvlw7Zh'byeV %2aR]p00oU{#Xi\[ٰcMN!LղV?e/\8xZkTV| &DuYVç B&_78cIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-icq.png000066400000000000000000000043401345766322700270330ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME $lIDATXVilT[fޛy3/،=6bCXCBJJ4Qj(RO%jTiլjV )%8es1[&xxl (R^}|9>wyh[6P{c >ȮSw~(DUO-+7(]HǗ|6д+=+&EK{KR7(J*n ?rd'D,Aܽ, ʂoó[j=n$kP *w*+~:cvFLAÚE[k~򳐒'ƭ0 h|G`yJ,de ϛ#>:D,_vNX@l|E\wO-mqG <^t ztS"NC3N>Xپ K,Fkl$|Z3ihV?ܲ9փ"=me_m'fc@;bL8VR>Sի#=@;HQ [%5]w#<Xqe !–]MT\`"r#u œgmfu[yȓtMC i_cUf%Pr\M&BGET/4,t.߼0mѾm(LРwǶ} )RI ,Xg<fb k3 JFђ4GȰeهaQ-rtI&lAsc<#;E F , a@bwF7 }n.D nj%Gށxp[Yg;V,,rqaǡ1ͽXJqL;"lۂ "A('8<0Y~dd xǚgƅlTc C~KD{ ~R4-֠[FM5'Sb[vſ`70.eCِ6qL8wS Z {x<]DP(lQenѿ*&`X!0Ǵ9&@po;~}"z$̈fčsn:X ?8g2MnƂӸH'̑tg;9hb֖obO\YRQAp{s-Z(%?GJoLf 6:sH抧BN7qd3 /.yVb'`0`p.D+FJQ6r=<\R7ۿuE# >j B|ݢ.dVmۼwgm{tqXd H7mkYj816O"z9_8nOK$ʏšA`~uu{ﶿbOWv ??~bt8V ubzlsbg9ԧPY䇖u>eJ8LwbcDLdcF?d.W4pwù'!gl.iE&wGLG:z[dmNIUyj1eOxVg5A q rhhivDL^َm2^ ;[,yGx,:kþkԸ=1XkǛ"w{!ͯ"7^y:zK:yk]o fgclrw$'2r+xARu hJ`F`X aBGfIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-irc.png000066400000000000000000000030611345766322700270330ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 03aIDATXklUߙ3^\,(ziZ(  &Đ E1`4 RbXi)R5bXjrmKQv/sfenKNs|}=3n2}fxGm)vtEU2UWV133RcJ [>X8sSM|Q_2Oo999Լn'C!! DP8ͬvo 꼝-\rOY9r箞8 &!gq5ygwOUU?`*q@ EpHf&ܽ^}J0Ư,W]\4'Z1!qh< ihjju׸mMIZ!u `1CQfN7)R셪R= D!w8p2>\%py0T'O&A |X0~!!V z>cع67ȎBD9zԫ8nA;'{Ys#GbcbF$`6[aJbނ|EMŞ^`ƌI-]瞓rB$=m6j*( Z%m=t0xnWͯ4sgjiEaNgӜa wo؃^"33}Gׯd[>R=c]ܯͪu|!7͏$ .W6np+~52^{anJ)eŞhN,*Ż-^ocIYw"#$9yKhAZ\Y{7i຅Tr/=:IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-jabber.png000066400000000000000000000026371345766322700275130ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATX]hWw3f7$1*&j\jLkM"H@K@ BR0`D/~`[Z+(XZ($$5ILvݝۇIv7QfgBJI  Pe7oS wPw=k>QT@b X}}dKS;q‡awO  vmڛX@(B@pHdaɫ77wu~U   g:qԬEY5 .xc(dIaYS@O@oݵwmm%a&+ _T /]Z k@~ŀ復VXojt I5+T-g܍-`3NI'NKs4,Zm݀Tl)ہMMU56DT:ϫrԨ`DCC@jMKlfOk~,Hu|`1kYYХ\ Oe{z L:9uB{*ӂ X3} IkIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-jud.png000066400000000000000000000022501345766322700270370ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 0?JIDATXKlTU{/:QP`,XG$cec\2&f6ƅ1 .tM kEۦڦP-eiq9.Zý)t'&I=pKw>{]Jo5ƛR1?>}C>^{2yZ=g,tCǿ*n]q:OeRKP,e,G*I"#H!hZg1R)I*eDWJV8ƺ5砻2:2V ]9 ̕`ߝR&6e t@F\3ƕAۑ*#8oB@ _d߁4?X]mh70.'xZ)$# c8o_ k;9Ȟh'KW/J8ZZt Q=U=Dji\dH:xddȌf|@D=%f'qhmmu<2 s^v~34?o!B΋9`JE qz{Nkڻq%-n$7mm{󹷎5L DRc}H;i8 ߐ pUhO1dNXF7DO&R*}Ee۽h'(PJ~l%T%RJσPo&D>ߞC)Eqfv395a:|1߸Fsc3boflU; v|x ie/B CrvVxes wǏ,+]ea&btt躑esl]ǿ ˲4OQR_`6ޒVF}I7~iY;4Mt\J^Z΂3iu]} ׮be8,;. m+6fgg G”PW[GiI)/' \U̧ "L ySSTT)@)>m;\|rv2==M8QTX[zbgEpa<bY#|B%,& F /#ٶmKd8k,^/ݾ T^+(,,"2ffff!RJ)}bb?S$q>RJ 0>@ "%0Rxͷr,˾  !f<TRʳByԝ_< 0X@,ع8Wn =g `: !4^1O\\)F5Zm-vIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-mrim.png000066400000000000000000000033341345766322700272250ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME'h\IDATXõKl\Wƞ$11 q)JZFU`Z.@ ,X@H`R M B< ̢E<hRiLxC3hNgI@>= 0eUզ&"b|ni-4PB AňvU oXß6qޜمY/'bT6BW$!VН*Q⡕Т)L1TU&%y;*@zPkԧ)*ikq' ޤ7ESˠѕc V?2Z xj)Ȫ`6Ȝ@HHM[Mf$̈́A9`{M/9zczܸB5a`Җ8Kc @#1mc ;zla .aSy/Y5s  º Ֆ,fCܧo~ù1HuO$L0Pbeox>1*oge&OE ߔԒ_ Eي$-)d{%!=慩kzQ(aZЫI=GD#f\ܽkS5ŕF !A,沙4|Qo iJ8?;vzTW Xń(!3d$c1cnD5ܗNnEEupHU6B Hm>=  'T PRW?y8 pgWfh<k Y?+E4IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-msn.png000066400000000000000000000033521345766322700270560ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 0?IDATX͕klWه_Աv: NJm URw!Cy4)@H(| h&B4nCɃq]۱ٙ>x] +{{9s\܄OVPGF+e1!қ=GKMo߾ܧQtMƼw`뺐'"Zݓ8(-&IV=iCk?>ax=B̢0%Bf65R=sտS,V!|·;ӦKHtef6O[{J -@)1C$Y!,btUS;o)tGS}P0Qa qM:hU ĕ =iӂ*}Rq0=[ I\"iH3 B98BRB9dQDv REQ_{uCa)r(C(U\$q0"IDʡH)rJ< ~Ͽ|4mh1qȩIhNJ]7ޡ$myPƁr ~k|2~b0%rQ3:Ūg$bp$%gYtv9C>"<y" epA)C!.E] WR#KVJp&_i* 3M8~qpQY'/z']c]O>"5Дy{(̳~C2t~)ۑ+pt&>@mڋ~oݪ@ڥˊ UBK]9NtUy艃VM Q(|dQԷ>cg(NJ.9G¤g_TT{j-9_SO"r#eRsL)f%93y!xV\yZƲ?Ԡ*}L34@2+"ihԨ3\K=ҩJ0؞+WV!\/# GI4E*ҕ[ u {75մyx\JA)/bM *ذ&(euL[^_ho1zv(a ѱy^3aH$LМK(zgq}΁ohӽ=c-w1WWJ ƙgYD<ļg&nԫsTcS& ͚)3T5~xnY9XŧX[Ʀ U&g0M$XiBQr꿬)$4_ 3'! s4*û>'/ 2pm)Ce}gGsokt]H*?/\%pˊxzofJa$D4f!as*ԣ"P^ NKfr~%W1A)K`$[`/l {/504og=}ڰ^[^"2sTtsoM&n*~p̡kwAm϶jz,;R' Z U޽n.,i͂(9sU 4#Y{v{ Ws`xvqv?BA YdFȈbƲk ˱ܔr$IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-pubsub.png000066400000000000000000000016771345766322700275710ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 0?aIDATXMEU3;.ٰAD0z3 1:~\Ԑ\CB=E{ps!x22x$&!YE4=rffg{k靛>(~U{u3o%Р`QTdv`;;Hp~u(Fjkr'|I@ǛK p{RQAհ`L倩J@)XC`-*JV'jG?uqEMkAc.XҺ3_/ ^Iz^ě}Ը73l[UfMU1`UPgCT@L٭հlh8j%HTڼ;w}k <4Īh }ǴG Z O֯-ڼ6$+5K 6%9""?p@[%ʍQ<DY_RE5kkn:wl&~}2wA3V k53_s&Gz`Z-pU)x;8kGNU?!ۨ2@P > 5/\~(>9pa ҩOho+É?Iw"y*2<G]ihݛaC!ܿނQoF%Y(5?mw 1Xhy$o& votl`Tn؁eL"*@ "ɾ.١T]?IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-rss.png000066400000000000000000000030161345766322700270650ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 0?IDATX_lE3i-JQ@EQ#_`ը5/Ƙ($F1ш#( F14$HUBնTݙݽțܝݙsGY%09o,"F2M.1ػYҲ?}qrDJ>k%ZDZm9Z'L^KC'?W׾4>i3HAD1P'W2uo2#; ܦy#pX5,X;.[(IJFX n dۑߑ {U&^HNizm ,$RP<U<U: \e :y,) δ-]*@ F]q+cDWݏ= m+3x`$؃smSHk#rHU58GWEyswYk[ E{ئm{ pq;UP 2R JUyw~9{b'.lf+ 3_GW&x[ ϣ@8 18Wxp+(b[!WD;Ձ3W~"]'6- x\mEO%@=jlM4T z\ z8 lQ [{<ކ{7A%WLY9m_ eK*xA`Ove]",΄Ÿ#[0M[{Ƞ .ڈ3cz]a^C_EOX0KW!gO棆U@]D_=g[$jBOl:%_)Pŗiډi|P87>7t#, ]lDG}H1dg A,θq>4$,lo:ruK0_8S+焒owg!d`Zv@"AW0v٨oZK;eP.XAdG'y{tR9+:oA00U;}kĽT'Ѵ*C'"\/X5?G Rp4Ii+eS-AMřZXpF`m`ï2C>UD/5Y#Uz]|BKu6bbHvT RwNQJ1"fvGxum.̡QO1>װcO|-Hez6>dR=j9/6/H <,@/X`ĀvAPWN"{h (j;k?$yT`  ajXC GvnWW4Й0I޹n./$H?)ߚ wc߱.wa @'Wǩ{swo6uY@|ُK~yIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-sip.png000066400000000000000000000035511345766322700270550ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 0? IDATXiP[B`#Ibn:صCqILB~HS㤁ĭҦq1!cbcl .ehy}`IF }9h}w W;S]ۮz2ˑYJPg g]Yc5H0geZ!Gy2nz(,7TTJ)EA齥&9J̬%ҿ܌m[ja2`]ed8ZQZ@kEBUUdddB8NVQ`XQp  j.`(bwtƔ@4UUNsIlMMMC)FDJ)B<^zOD/X, r`0*B @%1JCJ%|o^z^;wlYl6`}1Mxk<{ BO"bg}:gyA\J{ I!$ EERJu1=<>}sV :;;~TJ), ~x\FF`|;<hpeqW׼(Jә/^T.,䮒!2 )HOΊ \sqN|źu߃-g-؍6$scOI"xi+**a˱̙چ6It?bƍE/ߐY, ܺ<шI7/ϟj*oFNHTmڴ)%=+s({uy5(/u$  b7N  cx]=gߞ`~Lucu'.kI/`sɶ_1[19dY( xA~rmX,(DB2d9 :A+$t@A00ߑa<N8]GȺUU5ɑ 2  07]vPJ8@0>(D* ;`oDf%조_ 5ng΅ (B>ZKIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-sms.png000066400000000000000000000017451345766322700270670ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 0?IDATX՗nE38qH(nL"JJ ! }^^R cO$Vi>ݝ3\6Mě*̌9ߙE-'WA|yWDF'h@ֱ>@'^-> 4 ;;;gWƊ3׮^-Cra6ֈssXkzNVVVȭbmBGxxQJBkiܚUWr ж~յc~uW>=Dr;GD#O+zp؈u`㔃zL3ת b!OHS}3NyAl}{@lȲwx;Uu1qQ#A{(:SȚg@9p}sFGGQJg{{b355R R\.s''MSk4P..B"BV9ЌJ};yߪTlni1>> 7n|J0>!333JL4n"F+$r8瘘 4eum?XY&?0O-J$ rtcca?d(7B4˜C$A`eiiB@$IsssS9jGaqqLӄar쉊{@{7Iz@>'I'vFAۉ1 Q1c L&$/HK)QSTb/bw8~SlO Rs]k>+xhkbԾ]{&Oz}h]Zm9~Y,in}@8;bJ|IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-tv.png000066400000000000000000000013761345766322700267160ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 0?IDATXKTQ?ͼGH2,Zl.FA@H)BZ*#iQ*pnE &<}ost9Ҍm0s|?r9 hGY@wwۼ{嘆]Zih۶nľ-蛚ͻ]8ܽ;)۶1z<4|18||`y7A 8MMM8}_>[(aqqϙyW!ih{ffxT"֔<=gPrR2Z3LY@[$[uLbp7d@TJPJjBս*y^1ޔXhC ;/4W7I;84v*Eʶl ,1h:@@(}AmcPJ+GXCyb,6b޴L֙,-05Ҵvb9C4}Z  Z4FHR@gG:;7|#x՚..2 BaK3 w'ּyvߟ*d=y*rd$ں[Lrdoܚar_`e뻚UoI-^h,}`*t]l0j((tvW];}FIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-twitter.png000066400000000000000000000025071345766322700277640ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗ]lTEg޻n[jR#DLJ#ѯh@ILb0&B T(ф#/ix 6%J@QBýV8?==f ?ВOxΏ/#h6_}羍@ M5;6vo0V wl?}7_aޮ^p!d8YopYr~35"x]X$s14(*0BhԲ%Yҝ9%P&5c^EugM(b?1T) 5Yk33ŏ9BAcR{ `\ {i0B@HAմ>Qnsjdl33,%8kj8S9pЌw׭v9lVA5iEDB5y^׍3K kGm7 9k U_3@r%2ŰS33kK>v !L`fq !M"+p0)j 1wfe3&4"6шMB04\Bfz_ PjñFHSh݊ 6 nL mveHA@ u52xrywmC3`N"6ͰK Bo=r݇~8{jdǾ &0#RAEmv$߾5Vuw'g 4`aF GǛ҄z ~.L=uC_eعgIEf"א,Ehnϯ,4u|0^}'F/nL )qqzwݞ!Z[(+o!OάшokV7P)1nCʫ9lSV)0+H)n$^0[{Ff`+" %a'E!iVAB'cشes;]߳T,LW[ ڳ*edDaJw=^ڀ/vP9 <;,z]K{9fvOT̑AAp.w@qVB&yM\.-ԺF @`2Q @ /I URjNg@*0@3tS+2# =S\5ʗq8IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/categories/gajim-agent-weather.png000066400000000000000000000032611345766322700277170ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<.IDATXkUk}ι9wf;fLJp1%AMLl:F$VRB !}ljmSci 6/$Nڦy8w}{~~0NXZ,Xl׏s8̸!h'P;V1B[@v&PySMM;ӛВ#\*+-0}=p܆GƂс&Gz="]J'_1Ĭ dO2ܘ\cӃJ<ޛxlpVuLdH,f/ x1v89HAn"^H} \#}ށɑK*ʢU5oW5kuF8}Yɽ 45^!dPřӛNA"K=Ey-fJQq) ½k3aB9>=Aet>+ IeQVA:Y|I1{7 VA,'S>N(F[U7 pjJ,LRp%9BAqeȘ;8LxlN[$\k| @6_dl+OŇ` kḟpĻϭ:>xɝD"Qc0 `&ޣBSBOL 3έS-t`lJ3&W0:4IBPA&fq#%h`nw^|[46n:˝$zq?W^f˚ûyK[!l;*eYvE}M[: QKf>?ra(Bh.+q\D0̶[J R""H)AD`f03RBk c ,3ŋֹۀKMAHsj >{?s{q 0Rj.MS03y`-wKL4Q魙iA!E8FERJA0((]]]H8SRsxhf?V>cO< !$ 8FXDWW8OoV~rϻ?& dIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/000077500000000000000000000000001345766322700225655ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-away.png000066400000000000000000000034431345766322700256600ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗ[UW{;0õP)r+X(@mژJ֢1J >>T/>MZJhJA,w8esc.9sk}>s)LGh&srNo-s2 !҈M({='+6h'RM w|Ώ+R}wt魂~o}um5?_ܸ-eLD{[:j 4|wWo `߫-4Qb|0v pQ?~f-NgrbyW҆h[ 3[>9eL11L0ƯEDKwZPʋV־% ֈ+ĘyԵcI#&H1n&L^ (V]+4H!b'S `+Oelԉs9QFZL8؉i7(WFxqQ6…gQC]!L0Z7gۗO_$pQ'6F]8{ gq.Z})759^pl I<+[vn\ f"&0g ˝x)NcOʧ76&geAMzw~Y|˦ g% `ov6sgC4b۲z~'3 bfC xy_+> Q-˳K$1ތDôܟg030 y4,@X(_bb%) v3 "qVoh<iDR]z0̤D(>!%2xLIL (岄ršl.*ežo@TS܌n"R*ޏP77C8@<83 9[LH>m7q;jFz zmBܻaO1W(fIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-chat.png000066400000000000000000000040651345766322700256370ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs B(xtIMErtIDATX͖ilU3λo7  a_@!,lp(K4QӄV TW!RTRДM K1%2asjlサΜ~q XCG:pu=?^om4w=7.nJ=ݾyON=@U92%ë`D^.^fUutOX|p\]]th^DMe p#U@jn M `V|LylDuj-m޼9Vd9zVb;vX[lrTxcz|劕S*U Fpro?]q Zp)k 7(Z5s`z u1c,ȑkF Ƃg':\ʼnGe4Dѕ8)241P\KH"'3H ᩥE4)H`>}T %[`LLòyuسfc R*x#+q twb^-z_<P \KR&us_ĢOb~"!sYgϞq]޺ikըKy;IWir"J@*)㛐+Mxgg^Y*,{)b""U"f,6{TJȍlɘp<2AJ!-%%OZE~=nذ{ >(g=wLZ @2hibT-{ ?vtt|˖-#+3tzg,C s0P ^™ߤۉHO]R]~`x( )1%РE s#BIϽn4~U*vZVƶ 75%..~ RȋXp=r7m:Eˎ֘=Pg#/4imڏ>;ۿ$҄Y,yf Mp(" oR Z.#++ + ?Z1qRzvDv\ S ʹܾ:{L~K O}svޒu~7pmFB ө?ᙁs55-mN!U@u E6[`ja;q5` ^K7st!u!.;q3~BHs03Th ":rB2 +cE@_X)!Dc޶ʙZEx+'=&5K_8yUmekMAo V-ⵈ;~a „YBh>DԲS댷莴_lMf`Յ6Plz~">}0'k%Z/%:߫$F캲2 oPc}{ a!{=\W=kp`u9҂!P rX@݅A1笹@@ = %3E0L`2#5=fZ`Wdd#)>D  <:.2P$%!n(`^"Gz<#2 ܀eL?2ct7#u9ɻѫMH8qIcvū ~iO–qX^ -=  4?t4.`0LT0ȤH'>mH+xAP3 af $8L'Ie$<Ӎ +n9yz{`@$ϋ\V`ag0 F9hD]t˵4 }}q;fTO26,yc ixo:YjIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-closed.png000066400000000000000000000003611345766322700261640ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<nIDATXc``tHW\KL:ڀ\+FGeBqNH=41C㜐 `8G`QU1`^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-connecting.png000066400000000000000000000041571345766322700270510ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME ;'t߫IDATXŗilU3w}7W؎@b JJ* JT5jZԪjA|C4|ITR"%UJp@%`V`̝3𮍱,U{9̙, ^n `k<%CH;tfsnwo^]Ī#5iLŹ+#ȉo+NE:v~k}y)ސsd=Gm( _(R@_>7@#5q-z򡕦002VFAϕ LzBY@U҅ sxb_hEw~G5ΐ8{=38g 8g α}]@$ @w=6&|*@ö=Q۰tAUquD ѬtTgB*x 2Q]n#106ͱ2gF'[}B4p9qԔ 0uS04]5 \.T89ch"~Gb6hyٶx'43e}tuBYclF*+\G;/e77150BDp#.0" y{]Z֐. b=:59MPg}ֳOORadE@ Fh33LCg',0tѲ[?s/ jY:s>$):) I HDJQ-H)X c}8?s:)w5B>4']]R.Vkc&43c)NiSy q0np @HkZ*׏d~0[6Ƽ{yV 8D8q)=~gF`i`j0fbAjnG@i(,)7z;;pzQ:LаgvC>u@~R4>#Sјҩ1US3y}q_}eRIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-dnd.png000066400000000000000000000037051345766322700254650ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME*rlEIDATX͗m>3,;/X)Uh TmU iR5iimZmMmRZB1YȊ²06s^6bYSL{=>?n~EZ>֢j12@9²mv&z%?)W:"Gݮxsa`f&Rw;T#fo/QE _XxK+"/ZΖQz:61DnGkȍarc9z/=(7 ɣ} G91Ml$-w2aƕJQʏxGNDQ: wS۸TrJsx$ԁGQF)?QZºI@e1 Ԃ!H 2ǸY"{Bg_#֌b4Ma ֌!6Wch,rEiyx%yzth "u/Yq ɏޚJ<}lsjcujV#0VAb&s[7}[6M״S|,leb)~:~Ȟܵ%ud_p?U;Z? _zwy9>Nps݉RyPp2&CPH dy|ufUtoZ>&vu Mر~R\c/l{[nt}' avZbL Kwb6wzh}uxt]<*N ܵp~gg1sh#)ڱJBh& 97H:aѲ~n?"2 Z-}_oWCw?l6z +Beފ`uh_?#.*IgQ߰ԑ!>h8E.vt;8H||'M_[Y{>PEF)1 "ƋHV. Pe PJk"輩p7@9N/^ew-Txa3 X9sqOjZd>(g}ajؑБɔ VcHE771`ȱc&74tZ'j m,h^ :5u _^U 8:i4lK& N@C*u]==O8޾F>.j[k_&/J,eD)1ciW[ҳny@yp ֤nX ЪlTiR'H-ɻnѓw_T'3޽~JFjS윎G50jo"IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-error.png000066400000000000000000000035601345766322700260500ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIMEqIDATX͖klTs޵Ǐ6 i񋖂L@!Bℨ4iUJUdi"Y:D(~(mԤ ȁ@@ih`ގŏ]{9bJ^itݝ;7s?/y?Y&WaCL''ڞlL~y` Mࡃmn8]?(x[CJ)$SzY03L@8\fƞ=X<־77 k~Q8p?dS0 c"6""B!X?N%7V+WH4L&uC4n ˗/(dp—>,Y @zEM|=7 rlˆRJd  ҇e - nRB4tMb35 ^6 M7LM::6ʆa@)$""74166ƺoQO`C*ʥcBA?^*HB:93 ]fŅy9@@:,ܹ~pXtV]EEAQ\!~|Rc\bT+K/m;q2ܰ0m5ZE0ML&N/Om2`i5;j  /NOPΝ\BMsp{D  d2ADO pp __bLe}y_XT bh'8dċC8 HAkk+ٿiGASg0L@J?YVZb4 m#9'G0:1Kͤ (NC _[ܔJ-rө?G^o_ͻ~'O@&iNdΜXg65[n@B)ij午~ܼ2@P]UKS)104v]4,\[HODHoۋ0+*M ՞NgOvyf#eiPȯEetA@`*31/2fF0ˑ@0v]p%B !iю;7n%c+ϟ=Çuy LNNnJ%qn,F14<8 O>ݻR _7ut(r^u|4ziA7zg09)32%9WY[W^ (Uuu>EEiQ/}X5yA&{/aաPk:xt:>J`Y֜y9 (bx:xakE X;>H093&"g |eAfH)Y}]cD ݸb<}&)8xvC}}nhmo 8PJE4K0" 0r{{q[Z؈==p>md"ϑ-=D{qrťիp^$wY^ @K$܁h4j[ˑf<b5/} n ɼhMMP;Cb7m|uK/U^QtDqq1 Äa ]GvhBNX755G"_ ,۾C&B,(zuqQ:@~_bZ)dsj;&.iIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-event.png000066400000000000000000000020611345766322700260330ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATX[OTW}\Q` ѴD}(MۤMcSA" os_?`jADkHƪ(M^fh0w`ƌu ᅕe_RmKolz->O&R*}Ee۽h'(PJ~l%T%RJσPo&D>ߞC)Eqfv395a:|1߸Fsc3boflU; v|x ie/B CrvVxes wǏ,+]ea&btt躑esl]ǿ ˲4OQR_`6ޒVF}I7~iY;4Mt\J^Z΂3iu]} ׮be8,;. m+6fgg G”PW[GiI)/' \U̧ "L ySSTT)@)>m;\|rv2==M8QTX[zbgEpa<bY#|B%,& F /#ٶmKd8k,^/ݾ T^+(,,"2ffff!RJ)}bb?S$q>RJ 0>@ "%0Rxͷr,˾  !f<TRʳByԝ_< 0X@,ع8Wn =g `: !4^1O\\)F5Zm-vIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-invisible.png000066400000000000000000000037271345766322700267100ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<TIDATXWkly쮽k/zY^6 c 4M4BMHT"BZEFQ#j JTT !ccmwkwn6kz33:s~sg!> GwWy9B#1tljGG*SuM}UҰʾ gŌZTk׿8-]X yN#WvN,e=?AV2fX7Nq4rĚ-#pt7)VYdSۯ@U13SDxg ?p`X['-02kLx.S|F4UyvhIV.f*Dnu^tXAKAr#}Z\7Oi37Kʙ~s[}0Μv8J! A)z7{fXV|ӆ{* eAL0+"P;}æ<`3`C*]M S=0?=NU"`F ` ,,ȕ>8vƅY5\ !,E$>̟;SJofo<1=D`^GmRϚ]S] \K}~9~2Zf}W{jъLR7M.K֖wn3` sx=jˡ"}u;7n^?.<.4ޠh~w.D0#Sl1o,f fU6vjw,oMڙ/D,eX"٣bBE?]v;j } V"l8 )fT}vc%Rl,%Bܼ9%wD;>*RFtb+5}@Rw2 ]^]nGRKg5%aidM؊Ol 1n^o@dlt+gy+V;yv"B2>J`
[Z ~+‰PF؃U6|iRƊ'0,ÚQ9?A8tDM٤Ҥ "M&K,Q ˃u \r5S~NJO %JiM"Y(DK!x)年\suSEd.b$3!b&/[.TXT"Q]Tpd`oȐms!FD!yUFܻ3sJVK*Up*nUN!D8OezZO\BOgDv$K#㿶N (`&l?>@) E9;00ۄ %&Ur/J*ˁx:(RL3|N!kKAo?5ܽmj,~GzDd6ZOZ8ao4XA\󆗍# ]vr rF@ \Oӗh:Qzgg yf>>>p"`Y"aZɦr]ZjKl+pzw >;i>z?DW|<3 [EMAbb@FJ$8rͭ;nBs^+5<3c{׊F z{ \G6:2 8IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-muc-inactive.png000066400000000000000000000024121345766322700272760ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsKKE{tEXtSoftwarewww.inkscape.org<tEXtTitleGroup ChatDftEXtAuthorJakub Steiner/KIDATXVOH+GlYS*yyB"h/z(R+4 7)9=CJN OmCxP`f3Ӄl6XY.XXXJӴym  d8777H)=d2lxx q'vwwXX,fi98 %ymc*! B! !F:::5y moosޖ Ϟ=b/1llld2jjj*;xJ->fHI)rd2V⠠T4P(v8D"Fys+RJ:0Ll .l!Yɠڜm9rE?{5 -Ȩ^2 -S5H zSg[o^pm \!䱔U_:."R 9!6Wo2@\89eYVM؟L 6* D(iX__wBB[q[;V1k~?Qc2w Bguk{wwmR+xt]??99yN !pssӒ]"ckYJ \]]!J!"m#`vT*8;@)|۶AA,Bi!BbL&er9=J%4M QJka4 a$ 5R fY_]]mP)XZZ:k!bqql6;500˲ׇMwJgae-qT4 ϲE !WVVVx~"D"T*vV;8>>~U. |t a(@ qh-VUr~XHz;{ia [,E^Ɔu{{: }S,%^mAKɕ1V*B|#=R~WV_W*&(l~ovBy cz{X }չ1x:ls]+ip{ J<.SyUKQ^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-notinroster.png000066400000000000000000000034761345766322700273130ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs B(xtIME,fP՞IDATX͗[lg7qbq7I}ڠTU*ԪH <R QT TUTP.*֎7ub;ٵ^zoݝ~3m:it曇s~9gN82 _$% -*?_ F{:!H$Ȉ$}{btoښyx "TH/lͱ^gȧ4͈/&iӟ߂B<_4:0|? WO?f0 MӠ( }?t䌟ޏ}0Ntt)hlvUU( 8W_@sc#cg/ÇA&A|*˲9c dty:BVuW./]Cbvs!)%D, cLOG^mmEu8EŢ}2qĦf$z0uu(--l8b!CYY0&&xUz*d, %#{Q%<σ(//G{['8,e~6G]$Iéq)샟%ض )% @Sc F/\0eYֵT쥱;h9r恒zղR$f084O60)%$8;zjk! ĕXY^"{r<}6N4{#=,H`^RJ7`1B[k;'  ϣ"Tdr$ ehlh@}}=iphm76:U ~_3-;^o]F6SÌ1!pkk, H%lF:F,G0hc8;U(M}#;7!g 1g@"?lAg "TQ!@Ǒ@of@ёWzsp57 X^YqJ@.G0 c*hjj#G1vq mm)L LzTUUAUTB!-1|.\B:5pG+)1KH42>13 5a )\v "I&|9睂e+Kׯu\?{˷hJ_ Wz_k"lU- w]NHWSV:yY{CU076< o; &32sk L+; 8 r9IL4MQ+<~XtYunU8jl.>fK4MH$A,7@e w=8cSk(1K6o{~ F.@Jyi-AF@7v/4axv} ; =u bBn*X65IrQ$U1((ضOLɯSWD[k+lۆepq\HCthCӡ*TUE @Pח7f-4 V{VoW(=Q^^AS  0 f: =UP-Xqm y[ѧx[]&o=p@ۺV4Ѭ(Z(͜#0VE0$>?Sɢ^K&`gvm)=FV+/XbIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-offline.png000066400000000000000000000034361345766322700263430ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs B(xtIME9U]IDATX͗[l\Gƿ9s޳kǷ㢺&:(ڸ⭨qnN(D$ *U#LAR^TBiS' QЇ@8vk[Mn\vvn<쮽1m#OsV:s<ȧ]pԩ&˦YQJm؈]Y/k/ïQzj׊Ҙ.7|U8򩯴4dϞQ2a1,ĝ8~79wqWW HdW8RIB@)秡 J)cqhm00ZVK~һr9xJ9Xc 20JlƎ;Ԋ[ֻcaPc c 2PJA!{!g]@J )e%>$( k8ׂL0,@$(C,Ӓ[J)(UTZ+haʲ,Bynoߊ1B Uis)%,z!&F%k9 wo})JmF&e `37n~,;L =ܾ=΄О]J1?ϗ.cskNOMLfff k wCu6޽wo8<ߏQPfq1ܹXa!ĵ_C%'}{Dj_<ԡ7vo#@)g{~q dhZvuuafvּwAo:HߗmѣG211w֌\I  H@ՎLƃ1 @2D,#۷ѵm-_2ؿ~SӓH&硍!lRcj( 1zMX_KjѸBi6lA`y2lho~uGb~>6((4\ϭ"vM͸N<աss7̲DX̂m<~}a.w9sF,׏~ĎFSm]F13; 9 ,˂& L& CBX,h cc"JskW %S뒙wtmxb.1xUyA:s?x 2*W6r\q3 cE *sbk6@бݴuY1,hc`1 Fөf% ( (?oԺ9d*B^U$1 "vd|Mc[1H)!JfҿPBzvb&U[7`U}1Y׭au'u`d|~Bdsy!> @7Uw={䑭9uk"6(ڬ!FE N _ZY֗UB/RߌE?V}IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-online.png000066400000000000000000000034351345766322700262040ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs B(xtIME*tIDATX͗[pUWk>I iJ҂0V:0:q-bRdl}C}J[:8>0v@JGh HH${HNrn>rb4oz]exNDT"" <%zqDܵv,Lo®]%/nYx'S/-iz-u@Kw"⣬j YxwSP]F8:&#f f0͙@VDo魍+zӀ]+Qe% ¶ KNZ1ވo}jJWVkE$Jr*:qrQ'} i$F'a&ńgD(倲PJ0a7D-Fh5R9@pcD(]@۴@LߡL8J bL82"Hԓl ]`"> ~p]DGJ1}*4۳So\~/_(A0 02:r/ N|s૿u?kٲI6UWԹk?ϲ08i>l?2/숌ڱٛhDz 'xŢkx%]N;ʻ֣2ƈiASX=-A&?p:2򭽛3Tָ>Ȋo'Vu[;1fx6LqfNWH9#3k_f)ϏnNYA$8^eyryrJO!nS]br~fB8h_;R=d\Gs{kjF=6'Qe'9"*="Li>Ej'ŝw +m06aiy:ש 0n}5S0%\ppTy^}7z%RP~TuH0FE9#rU8vLVMQ< pʧIRNPAI-AVTWRd$>9ǜy [xVjB0 &on:1?m(mh1SH43-LGlc ̴%ٔ MEJi{ ˆ.cm_r,^Njxa`Vq,`iW)x#aQzױ.mMDe'-׍P#frE?/b+db}?’x8'&FgArjtMF+Q %50tEKr7 3i07g+X iL'IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-opened.png000066400000000000000000000003241345766322700261640ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<QIDATXc``Q0#!)`ʵx`pjbZ$"BR7!0qJ*`Q0 n0bIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/dcraven-requested.png000066400000000000000000000040121345766322700267110ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME :$bIDATXŖT?fggfgwaaWtTZ%"**%XukϦ?F[j5MckMZD[돚6HAHe+²̲VX޼ws=?/l; qr* l 9f[s۶'w*b˝R|Fvd=+n]m&+ ;Y?{IqqGQ)KxoFJCw-_4W7ojS/oEGm(=Z/"negy;ɼ7}z"a;fοA^tx* RDMԡt ;Zϼ!PtL$ı2ݲR݇RJ `;A:Ht-JP*-nea儒"/D-b4-ThRxGnDƓVC 46tP*D| 2"LN(es1M[.xso3x7BƏ(drlYtC8{o.y /g#̚&hι3&o"~qy Wӳ{7̣/_n׮]rǽn=EQ}'mޛW,ici/vDvYbK _w o޵ V.}מ5g"2OiO> Z@(eXujj1nRf0Ǚʷۏ #qXN%7]Ym8j(U Zz{v7^qb+op幖SKҘN?W>on{`jд.ƍWՆQL 3Z6HDhL2\eמ d2^}ZFG]D Ώ;/LT¨1FzZE3>53XY(a#'J۟ TKk۴{޿zl=.0ZN-Y4/N&*W YRIR^V{ $ CByGknt- bCc uر1cYmh=4i~Z  )c,[uc,Ze?"cJ-9CRL^ LNNB3#.JQ*bweHk_DM_JJ1󮏢Ϝ:x&7SN`ۑ RCqcn-:x2OR܄< 9v P]$t9!Lvh=&~[a%܉pEȾ@1ן0 ]eis~:^*6 bG`DuOsv8Yl3ldsRG1+W=(:8ri;\߷ADIyv?oC^m|[b;{IğO@iaC~tmҁWEbsYt]:Ex$ 7uuGMU%HbRv[TW64 2oU:Y{`MvzWW_6mޜ˗:'TilFP?O4<R"ZZpV$sl.yry/W&Ro xU;v$Bx߫3i"Llma]K5•l 0ȅn*EՄ7"ĄK M$(gTL&3R*}Db<& 2.L+Lfrc;冀X"A4:Qҗz` :u HP8SkԙZk'xd<Ȉ'4g%Iꤦ:`d=)r>PbZ@F> .HaƓ*3g2855xWc Ib1A*?:u@E< "6x>7dvL9_-9gNk…a2tR%y*DR>O)P, BrBx'҉aI("7bOi14WCs"+bp7FE2|櫦НKг.L Ln-0~A0~Ni)NIIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/facebook-away.png000066400000000000000000000014531345766322700260060ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗjQߙ&IkcEA^@D}/P|ҕk\(nj]؅[*Xm渘I3Mn54zru]DA'hJ9MԂX P %L#?k:/w 7 h^q4x?z"|UA wRo2ħ6[$ t,n(}P!zmaL|EW6r9{Tr<XX ](0EݬYSkIl=>XCm@:]WwW`ISeNWS0R_v׼}k' B1+FXG)phHXc1d#XuNJpp'OV@W]@\$9*b["0d  >'RI܆I85ѬgT62'ۂ@]E(p9%*MH5TBk_S@D8@F+UukR(!0_4'v:=FeNl7JT+QRe_G*^=>|y7-j GU><},-ƁK,Nv1h6(6_^ P4Coʄ<|/IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/facebook-chat.png000066400000000000000000000020361345766322700257620ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗOhU?3; IZ⪱!ִ ɪ衈1'/AAeF*R.BՃyz _/5-Vg&C븺՛kT}[ HA Õw/|KL|^zBQ& %+pvO?&Wٹ:1`_rN^{_!Ρ.;S9(FңP2Nm|r@AMڮp8]0j٨)#8<]Gq7ך?AZ3(&ZQ3'DU-Q<{@#N \ajFQoLԉl=RtH;uF3^ٗ?ep+u6#qXވ"Zȕe9]1< jWk N<AF\ Z/Qo6bhyWO==s>`iHADKW:>߃#b˩E%7jZOö/0UEn\:d%} /q{w, xM -)ݷM&m9@qIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/facebook-dnd.png000066400000000000000000000014531345766322700256120ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗjQߙ&IkcEA^@D}/P|ҕk\(nj]؅[*Xm渘I3Mn54zru]DA'hJ9MԂX P %L#?k:/w 7 h^q4x?z"|UA wRo2ħ6[$ t,n(}P!zmaL|EW6r9{Tr<XX ](0EݬYSkIl=>XCm@:]WwW`ISeNWS0R_v׼}k' B1+FXG)phHXc1d#XuNJpp'OV@W]@\$9*b["0d  >'RI܆I85ѬgT62'ۂ@]E(p9%*MH5TBk_S@D8@F+UukR(!0_4'v:=FeNl7JT+QRe_G*^=>|y7-j GU><},-ƁK,Nv1h6(6_^ P4Coʄ<|/IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/facebook-notinroster.png000066400000000000000000000017211345766322700274310ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<NIDATXŗAoEov:ՑB֑DMH p*QAUik HpS!VR@B%@%H-mic{wvîƉ'd}Yֲ[/NL 6) ~ 4EVfgN0z8xr}"Orݳ ؿoX`hhΜ#o W;̵,,,"G;jɲ Jz8|u]\2;!+!o6-. J( yc ߿j\ AJ1KKKlN); 2V&_^wwhXYYqpUOL+7>byy8%0t Ue˼Yqwl@lv@2ށdt'{i㍽O9Ie>tzn$ԆK{BI*xJ`m2Z  ;㶇$KSvE}°@3( 7^{I>FZ(XV|{ LRRɜJ>X6"fn&L}u Qlun}faq_H}xkY E״B ph`uQFHRH}KH\I?/ {1IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/facebook-offline.png000066400000000000000000000015551345766322700264720ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗn1LfЄ[酊e+T]+V5k^`!DU@%+kh,f2I&!i4r?k-NG<<0LZk~HYzRVg  ɔBD!"HT*% R{$` MX2Ƅ5Xc0P*oSkwcƚB! fp|!\]]jZy^ _}ZyةZ]xyt֠uNiE*v_ @$l7Nū$XHMnMIKȤ3\twfB1bq&$I5t,Mms3Z޵#jl'd66ҁN ܮk-7O8]ҔEѦʯcЁ7diH_f>Wp{F899̡;``bpxhܙ<4 Ng,jc}Uj:N-#*@jOn(Z#B9pŭ⫅ wƯ+I3 $&!ϭCł `akP)tu '?MH׫dյ7߾}8 z;,E` XP@ HG# `Њ@L >X'  n*IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/facebook-online.png000066400000000000000000000020361345766322700263270ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗOhU?3; IZ⪱!ִ ɪ衈1'/AAeF*R.BՃyz _/5-Vg&C븺՛kT}[ HA Õw/|KL|^zBQ& %+pvO?&Wٹ:1`_rN^{_!Ρ.;S9(FңP2Nm|r@AMڮp8]0j٨)#8<]Gq7ך?AZ3(&ZQ3'DU-Q<{@#N \ajFQoLԉl=RtH;uF3^ٗ?ep+u6#qXވ"Zȕe9]1< jWk N<AF\ Z/Qo6bhyWO==s>`iHADKW:>߃#b˩E%7jZOö/0UEn\:d%} /q{w, xM -)ݷM&m9@qIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/facebook-xa.png000066400000000000000000000014531345766322700254550ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗjQߙ&IkcEA^@D}/P|ҕk\(nj]؅[*Xm渘I3Mn54zru]DA'hJ9MԂX P %L#?k:/w 7 h^q4x?z"|UA wRo2ħ6[$ t,n(}P!zmaL|EW6r9{Tr<XX ](0EݬYSkIl=>XCm@:]WwW`ISeNWS0R_v׼}k' B1+FXG)phHXc1d#XuNJpp'OV@W]@\$9*b["0d  >'RI܆I85ѬgT62'ۂ@]E(p9%*MH5TBk_S@D8@F+UukR(!0_4'v:=FeNl7JT+QRe_G*^=>|y7-j GU><},-ƁK,Nv1h6(6_^ P4Coʄ<|/IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-away.png000066400000000000000000000037171345766322700251620ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  >qIDATXkl\3{ v؎cāTPbB *%jLTTA*A|UQi?@"K6>4$$1)GuO;sa81>_w9s۹ڭe}Y|'gGV궆6V_w|֏;ہƷˢ`<دϬ"5ֈᄇM;.fX{ˊ9$[-֪f7^ J@,n<߿}ghKl&V)^Dde*:|1q#p sݯ>2C["UUG/DycH> ֢N~ʩ;RS'/P𑅗_ͩȫ{ZMORwc ߽!ZP?FHVyx0%IqNFR'KTÕW.)%}vȢFN(ES[Ŧ?$[pq#+Q\ gz%ܷGYC&qY|sVH|ۥ9@jFB T9*^~G ]v._^D+x ޿Kw]HU@@ɅD)d^r_ =)#}|r51츃Õ5U.њQ"AlmBBI$6Be5lkZ:jus;rf$ے\q Rgo&yGO6XzdQ g$qÝD*Zܻ`rkLv- Ok%]LI%2V~bXN4{ݺ%!|'\6$p+As GzC4,\ozH'sAe`4XcfQG+ o} oAn J2db;`~ 6s}BWduD`i!Z ǻ>鿬M(5<%VN'ր1 0] Y%q.n )P%`GټUJ3a/BYV=;ypd L N"dSFuöB lNd9W/πx̻8ւx~b׾?9u n}/1T#P в.:[!1bI$-_͡ >GzQ gڴz﷯ZRsSx{p63"H}fxױbb|DVJW]؉btco[ Ԣ6~1 N|Pg2(+t@G+hxtn b }]VMB9vA kdz_C&9Jϑƌqf}nMsC|~ّ{`e̛ۍ_և)O#ASX/$*qҕ &h_VO$$5'fp!D*gdM҉zKq!-y ? ŊK:1`@*NmuY:8zEf|%e܌b@u)5f/rXwZ/Z;֗myK)J^j/37-[5 pd{yC_׬ ň?&Kf6cBN95TZuC(%Rkp܄m2LsUQTl"EDtVun^N,w'e$N#:k3 ~f2lD)l&L2YԱIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-chat.png000066400000000000000000000041561345766322700251360ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  >IDATX{pow&BȒlP T"2tpA@0Zqb"2u*VTjӤzZAAlT4d $Jnr?v7y\s9~*JJZc. ` r%=&m͚5EnTjv</p\'u+Wl8_>硇LUTksCȑ#h,jFkm9r䰽|]ޙj^ַ֩*ݏ=r_Whgh<^?Zzݪ'{C+VIwoef0Baϱ>OBv,ѩ ݳPCɤ)(eEAkpT(y<&~{ZktkwQ/$`!`6v͜9xo|L!R ^JرUv_ HXf|g-_1|WceMDwa4A(Dx#:|Lz @axoh}w!1)qJ~}a>'yP )ƀ AIɦMU# (cfYDž[Ad>ŒՒ5l  ټ`\mmpa,)Z'6/K-x(rqpFF1zdub(Y4pİA'!0qDP-t$Y%`-z.KG"nFx'ÌfL~vj'5|bs xI0+!o iij%'%`St:5kn'w/`0*s"kxe wU/ISPdI~5aDؑľ؃)fo]]wO$r|9{ⱓ'_:tK$gZbڟ+_(/] +1Y]]B\iOBښ!\P8v3p-"g&X`da /z ul̞tg@%SJm0e/7hvF/Eܛױ݂Cmύ1ɾ}= v R6- <ظ@s ,R3\'ݹǎPR.<80j(GF"%B+Ekk+{zm[գG99kWzb=wh=W Qj uTRZFz{b^ U J8NsYY5}:n5qKvJhI^1$*"*)^!x7fH#ynOBJ:KDF|cii }ݻ+ƝoԴ8s ӡdDGCӟlr PNSI (?tyIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-dnd.png000066400000000000000000000041041345766322700247550ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME B~IDATX}l?m/o m]"R 4J"3ز,cddK,sZʖ`*(q** (X}ϽsK_s{=;sI)1fptXS]R~־qm|cSMuks"<4U9AgA c.dR hRqg )uu 0it+5SWup_.DIT\b:H>^}5:SJ-3f/YΞ=92N JO=˩> vkc^Yre8^yuzF)Iʶ]RpW{l^q''rFp<Eh!Q}dfeƑ}l0[#P6o~]QLx4Jf2!|8M/AK2Ň{=Mpd2J%u֑s'O*6x%-HۋƎ5cCA =/XECѼg|Nŕ2D'[77'_ oq!78` `d?"xꇨo|g[j1d8Dx5^ 0HQn͸':+:}-pVVqMŕR@PV,^Qdye?^7IJ ^|{}ez;j,lY+*~? ʃ9xU'm:-tA[10X/4o4mAaG*| x4U Iʓ ed@ *t 6vKji!]%/_RJ6R{bOQ[j!C@'x6Iygx#P ;0@W*?L}D܅g+`-z;63뛐X B5?KaVmIlkAk(kxƬ 1s,(_8w7mBDXt0xwcc3K0"n4ıL#@96~nlۮx~k|̱l{1`]Ĵ*teb8^ߜWf僠w q+r)glIKK1uyt[?XeA>9o{+g=Ʊ ёo.e%| d4,_&MZf|؁jy}oXk)Q*Q'!^1:) YX17_xOGƜ#L RNcrcp|nc@BЉBK˙֕FZ+::V_4SxOzt$QE "_ՅxPI挌 dmU#PRyg8k F<Ԃi٫DZX?Cfw6fMpF hn׽9elZ|y8  ڂWW z2Ā>ƎBIߺUY =wbr:H7B̝5󝝴^DSoUTVVY@<χ{uJKf-@7YR_ɔjƬBčh `m@-TP(CLq4*JkjD6BwEW] Z&'m2w_g$Z/HDHc~fVWۋ|!92jy9;hukXOS\Y\/ "jkӣ==VIk}LHTNp|*)OTAk}O~cݐS^zК0ne̊yNe&IPOBR)wc|B >fuR_F1k1`4?L vԌ$}bw=jO_M'L0YwWXIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-invisible.png000066400000000000000000000040031345766322700261720ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATX[lTxf|al`57* NIT%uP,TVMz!D}j6K#cQѦr5q&~{albL2YhZGwS*/U D\wg۶Ƭ8;}:y;QJeVG)0F)P(/V߿h1 .cJRsJW\?d|ڮ"J[rr efVJo{5ɆkcfmLYnQQxŽ#2ӧȄ]geU۸DyQ/%ߘ7ڕ[T^hw7'sԂJ yW]7RAڲQ =reCuΟ;W9wؓ~ LIT}k.[RAC軘J}J#Qyݜx]yއ;ӔjZ8z7tS>K I4ׁ$@WE(=/Ѳ#.C#N2ƔRnS+ڗ{ !^/D@ IO/WsʀҖGRs WVަwY,^\' 9U(5(51֯76ׅDv8>=Lo?&? ܧ0kCH^V)pFJK%mGg!9uH)0eQ?{CA!#زn"EEX V>l,TZE)#K?CcpIjԽa}TV.p 튺Cɔ:+ b)E({A)3ZQ%"=[C /GiJ?K~d2ܭӟBԼ=<Qyyr<ڻtēQtѓ;"2@2W/b7ig/fCZz.spK} d7&yKVA!ٓ>}$hn̞tvHsK='my{nFQQOmmBEA/-3ں0Z[:מ 'c;SUe[R8\>rnrt`Yl 6B|mQt P(?/Zk~c}u|t옫PeeJ qKza0$ Ky+E]Dgw\nk: Ŗ $ң~[xB p fmLY(77K}BZC4X y\ף \6rMyޙ3RFsR ޲yV";yNzгsPjkL)1o)ھZ)dYVce"(LMb=Toi6EWYc?r?e)M3J!O8wk}N J)7ID`FL\φ1*|5)D$ 6>t4Ň#KIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-notinroster.png000066400000000000000000000040701345766322700266000ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME $<ʬIDATXO\?;c3 ~H&*rQ"Wj7U]zE+5.MU5jUvUUڸmd0c33 03ܹ.Pӝ{4}]GGggc-0Pׇ8(_AX}8)(4Ɂ鱴֦ 0B===Z̞wvhY[岳 ޾w]]o(^FkҊp8Lv5o+Z.?!G#wKhkk[OcW2}+w0ښO|5xx<յ$JtYﶜ; eU,GFF$5_kE,./On\E]sZ<{,Eʎܔ2z49@&G֖*|R)M 5}_ Vbt1C|~.o#d-cnn{_Rhj7sg#ty^y*.dm}%24bϷUpweLU{Ȳ; kOrʊ>Z)(ZqrtX4J㱣 q Wt&s"^@{ڰsoԄñhTkW$IXaܴ!Bq}9BWbڧ tT2@.WH$pt޾TVF+RiF|R !4MMMLLMc6U!Jf%J$ ܸqo19=KG{++LL8-`v~)JJ4g4d B ^V@ѩ3 Rmr LGLtRJRc1ĢuhY[]%W.z+ܙ\zS˜Bh0-9܀$eS},$ N4| Ms$^8KE| (%NoqRF6v"*Foiv BJ BNhM_}e_cZmwgsxTbS4<&/`blb ۶!ԍ Noق Kx@Gc_ǂctΤ +La&iPvҙ,c3xbZКxe%%\r\Xbf.Aram!Rw%%)$u5$RQL%0DGW N Sw_077R @kxBTB>IԯR=WdGgg' mChH.tq#~Zk') TW 8RH-.򥽎ohH'Ϸ4F"308̩MR',.-S*pl6$nP(He0z>S"RWe d2+kH׷ʋW])G!nH  bJl%%eb յ53\q^@ |7\ XBj]gK!跴kM@D+}8R*ƧmJjՋ⽑;?bGS* J)2Bi|8G}}7ׁ nݺ!Ǒ(iY65vU?ʮӛu8lz]jWȭ3 -g/B π]`۱~j`v("X7pB|[~sovMdDW)JXAIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-offline.png000066400000000000000000000041611345766322700256350ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME .IDATXW{PT{^vPeXV|Ԋ 4GeLOL4:hgLG&Z-PҎն؊kA`wQ^˲uN`aȺ&?zf~s=s;;%fs:KxAwDmӱ!(Ojjk, eyY``$ytpәg@c\nnuҶ5",+* NU֘f100CӍm^$If->~Z\VL Tv=oCMy$4QC{zzPUu x׾hNOO(NxՅ%E>$ 1o5=gyԩo?,smtG<^N8 gI KN<^7}|>B!(n՚NW'knn&e奰p\hjj<}vwzJKĘ_{g6R  NĚcryl6;AH׃/o~ Y՞Ue饺ƛ\h}?kοl\f ml&Y M Ec qXh1, ܸqQ1ƈcGAVq=Ax N;*ʷ!%%$)US@MӠ F|ðۓQVVt܇?-`x plٳ3{w1& `2 JØר(bMx232%1!YVT>fϋ֙^ĈF:Ob;QA~[8YuBD bժz.NSjꌌYub Ȳ([ p%L&p?Ml2xHsCՔђ>LAO+=ƨNMR\˧ؒR010Ɛy#Z.\Dަ"$d V[JY yK劺ƛ*?*++uddd!Pׯw7&'Ȁ]e HbeJz`J/^9S]66I0cf)1}: pB "g!`:Qgn!Ior/~.X-<080߼ᄏz!)AGYХɲsR@}}dMlBEQaX!)֭]=_} Lz! eK@)`UӠ;`jmmUn§2ݻwْ%K^ْ2+-F 8s2rP},&̱fAm8xwp8QVZ 3?f׍/Ϸ䋚-;488*'3f"!!P?D̙|36kxdy`@gXq^2::U{{\Q#RQYUAA\FnY Z8tbB8 Y؀ 磯]كյHgLфY䓳z=Ya6B'z=HI?9' DQȟҢ:^JiّьllvJAx=?69hz{z|)ҏ]QK2PWuّ݇:m̖f/%֭!I 5hM9p\dKaRRR~ÏW\IeeI=oݏp_Cag%!y劕t#!MG^xo͎4=%ٶ5q:.jQ ;v1?~Q^o.Z8(euzrssV["iִ֦ Z[[UBF5 Rptl}DMxMp.}? B= c m#IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-online.png000066400000000000000000000037221345766322700255010ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME .tIDATXYpT3FI Z[`SSf11 OER)W<dH"1*Cb+fb3  I$h{0#,İDO>}N_ &I)wBk=o%!V)?bR^nZֹ걆:1 MԶ' Uʤ`PBz q1I Qz" (0 *aVXV77I9z(u[[q* vw.|MWgc#}A0\5jT^ic==4CGS_8 Zuy ??_Na<7+TDuS_[+fΝLZ9eZ{*adڵZ[b/؇*MJr,8mءzkOCx pwDm`.̀m^0httQM|oz `"1}0Z]BY9x/bT!Ͼ;c_ɸz´ŋ GJdL3BL蟠`4m·rjwikMC_-ӺD̕Taa}Bڸ_"kC'w&Lڣ?C?WH_23`Q2xyԩ>'|Y+m&6Ut1kY*wo0keMF1]Õ:YImVeVP67{b޼p8a?6;j]Pwp0]3#rraFd%)/Tpp&v1`bϷHB16k6Sޥ{_gc.0+/yd4\R+{0_TCc: ǎvNr3QYnS?eo*-5sɂ F#y=gWKg.9%1m`:φ| j|IDɳg/.׺Sck^]mQr8 dۈg#pB [[_G3"ԟ?/%#*aRjeaF;WP撒5?^`@w FCGGΜ :d)g?|o&'7WF&etD}>j7̉1's.$RsUf ڱkJ陙yEEE>ߏ !'B+Ekk+t)szeYoM0_GlJT)č?Z D,r+ކu/+S[ڂ#QxJR~!W m?!ĕn D)3HJ('9ƜQsh8J|N̷@ @;ĠagDW 3^үjи߿~2]?լvCuIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gadu-xa.png000066400000000000000000000037171345766322700246310ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  >qIDATXkl\3{ v؎cāTPbB *%jLTTA*A|UQi?@"K6>4$$1)GuO;sa81>_w9s۹ڭe}Y|'gGV궆6V_w|֏;ہƷˢ`<دϬ"5ֈᄇM;.fX{ˊ9$[-֪f7^ J@,n<߿}ghKl&V)^Dde*:|1q#p sݯ>2C["UUG/DycH> ֢N~ʩ;RS'/P𑅗_ͩȫ{ZMORwc ߽!ZP?FHVyx0%IqNFR'KTÕW.)%}vȢFN(ES[Ŧ?$[pq#+Q\ gz%ܷGYC&qY|sVH|ۥ9@jFB T9*^~G ]v._^D+x ޿Kw]HU@@ɅD)d^r_ =)#}|r51츃Õ5U.њQ"AlmBBI$6Be5lkZ:jus;rf$ے\q Rgo&yGO6XzdQ g$qÝD*Zܻ`rkLv- Ok%]LI%2V~bXN4{ݺ%!|'\6$p+As GzC4,\ozH'sAe`4XcfQG+ o} oAn J2db;`~ 6s}BWduD`i!Z ǻ>鿬M(5<%VN'ր1 0] Y%q.n )P%`GټUJ3a/BYV=;ypd L N"dSFuöB lNd9W/πx̻8ւx~b׾?9u n}/1T#P в.:[!1bI$-_͡ >GzQ gڴz﷯ZRsSx{p63"H}fxױbb|DVJW]؉btco[ Ԣ6~1 N|Pg2(+t@G+hxtn b }]VMB9vA kdz_C&9Jϑƌqf}nMsC|~ّ{`e̛ۍ_և)O#ASX/$*qҕ &h_VO$$5'fp!D*gdM҉zKq!-y ? ŊK:1`@*NmuY:8zEf|%e܌b@u)5f/rXwZ/Z;֗myK)J^j/37-[5 pd{yC_׬ ň?&Kf6cBN95TZuC(%Rkp܄m2LsUQTl"EDtVun^N,w'e$N#:k3 ~f2lD)l&L2YԱIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-away.png000066400000000000000000000036571345766322700253520ustar00rootroot00000000000000PNG  IHDR szzvIDATXåm\U9wyiⶕRq4lLBHL$ZBbKDhbP ICWY``+KKK]Z}?In29s޽l8!DJS5<}зuK̙Ӫ^ +KA-mw01ŁRT&mBǑو##ju+n$PF1 <،,XU amdžR X0 ԅJT#ì5ѱNc !QN^zCfGԗh`M!r֫z&&o/%Q[H_-){^ܜhrtܐpes2vEʜmkmHhS{;}LH2a CÃC^ IirsoGȏ>EDp.o aUTWꆮ J)wm߁- ] dh{ӣ "T4p)egϞŏ#_| 3a@2nғzv{ry `ÆntR f*U.V[zpp< 0~g0]0Sq&ytvvk5_ (>L)dPh$P(Jm!t Z (ĩu4׌gr^}s.7/ݰ{}w7ZP>@TPJȿH)zLmmm?8mA(0b`vN)0@ބ=o-3C1w .|zjP˲}}_ d-q^K\/^\+_D#ٳgnrr. ⺮h)4-˒J"'OC)>WT*r⺮A Zkq]WqĶm,KժT*Y^^r,rYJj5V⺮x'KP'N,L0E&[(PJ m} iT-[pq @DH&:uOk}̙3p:9?VED #VܰX,J>%yT{lۖ)kddC]0ZZZ<|޽{8"B,CD"aZkKOOOFp)iR;|b'R?d2}}}|~vHc\.8C^o(A Lfh-XN֭[v3ßmmmtiI}122xo9#@رt 庮(nu]\ɬFD8$I8DU@dIAb_p V:::Zc6ZM6yf re$h˲(F|f'L xQ#mۦ\.~*ttt0::J^kP5eɃj n^D<99n* R 4 T*ž}fwE<}Tݸq EAWn_~[nI$"\.68i6E婩Y#h fo߰aCjF7Dz, NH$XYYɓ' @G*z!355\zu^kGUmm۶/^7lskNL4NԯMlV]&_/KF @Z ]|zF8rٳg3dK\ZWWOMv"Ql:^S(۟]tr֖fk ߸qT__[m+cX,f<}8#RSJ٥Rr+333\2 >>ܯ+Jpȑ;wNZZZǏi599gffVs}Z/c`X -:V"o~e d>W*Sqy7W^j-FXx@=䀹tW£rx|*ckɛ\L"&‹95fԒ/5%IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-connecting.png000066400000000000000000000047231345766322700265330ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDATXkl\>~8N8! iPD#"Z!~ 5U)T(TU[)-** i vįڻ{sN?ݍM)I;>4 b5J|G cX)`80lCGodMq={"e@ bUsX7xhއi9ɷ6`4U9R2/_ީ^0F9Zc7 cs@L>ڛx ϯc04Ơa:y?W1rǥC.l0lIOMjFa"[,G}+; @~^$kבk)҆ьhMW,m%)k 4%Xx)-k@=QگuO?z?I@K DI}  ŀbJc"6Q ~[ZxY˓K>pxHxdhmjhB %HQ55Udp+PiRsH&Y%n[WUGqmB(5~xJaI@A|Eh#ScB Dهmn-մ4 *Gضqk[ڷ?*mݻ h[؜ %1/ f`,X֫p -CԵ* _Tģ6o&0Ip B=|&PM%akPS)0^f-nZPڑ4QGR[r?a (C4(06B]|4U{& L%@[rHUaIX@ǖ8ĶB LiSqMTaKpPhxifn]X)M5URH$b MYq%]h \);P@k|eg(KA h?E;oKM)&! 8aHsy;C |MWx@S 4 ST!Z$#̩.I\[\iY)h 5Ų$MQ,]PMs}#*y: 9DFu-X[gFˍI``2[ؒ]qTsذyuQ<_#q$%e6:T:0d~ec2Mz$3hVtk4ڬaP#5y͵9?c^S=KQ 0Zb8 a$a|M 8;2kbIs '%U ǽT~ɄKĖ!}>-x֣OH@c!%4D^XLYVG{SH>4X#xӲQ9G3LTRfŒ~624'&99Ǻ$+ aiēٷlDuKlٶ`p<7h:n5d MQT/kdz'cXRX$.ڒ6)~ _MTy=*{4zhg22Y`4S QǪLEJ@w-͉:a[?~z x'Pxtb/=m}vB 4Î{nceģ=6:yhZ N@8͚^DzjQE_39169ͩ}tyB#7,۞]z !Px{=ů. ϴgby`LB>{'ntg4'3IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-dnd.png000066400000000000000000000031251345766322700251440ustar00rootroot00000000000000PNG  IHDR szzIDATXí[l]Gͷ:q(4HEιY}sfϚ5sR˙8@ ,.3RclWs@>:T2ɫ5Wbs1Nδb:p>B~ys?z{W⢔>(`ꅗls@Hw"=px<7=9h󩧾 Ƥ;AD7 ?|pޚjx- ]/px,}Uc-|*f !r`̞00'E0$H;?{&'lZiVcDcVlw6նA5s?佞ndlz|br((m;iZMC=GJAp堵<t5|+23W"\][[k yx<2-$›xNMĞDgˆJFDT(V"J_s}@ 'g?gZJ#>-`6Sa} _<{''4>P1"0j"Ģ yu%տP)9 `(UW\v5Em?vLm,>@?/--G;9[WfQ*xuچ fy~5k0*P՗ -fTi}ި"VԨ%^ׄHw#a`f~ώRVq*ƘOI QD{F9 r OpuǺEsEv焦=zFhvۤyk~-kzYyQb{^K7jYyx;μ_}11[ {섥3F.q,p) w+ЮӃ5֘&n/ H6kpNi\옉U_)LSE~;X׳3B`B.WRSO%\JU_KF)yu^Y9 _۟|D0MDPkhjDȢp9N?wug[|Q.^3aWΐD$Io]%4w;݊f+_| '}Zuf$)Etĉ){ʻ3ʭ 'c`d+,,+;%yTwz=ſr}aK \i]x7L7s3qA(g\J'n;>:WS?W\8Mm"Qc(jS-S(,C34+AW4g><9yЖ'I*^Ep=lމ\_6pz9bi@/fGGGO;vL9b:Yə; d@_Fo)1A&;iK._.{(.IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-event.png000066400000000000000000000021511345766322700255160ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<IDATXoU?tJ)RB xI"0gN3??)%33|~ 0[ۘ%ɔmU,F29O8&LR|=; >9g?ennWffD#,,k9@;;;Ct(J&jDGt2,7z{8u$B[yp#v{.dpϏպiH$܎PQQAW<L/fg 4xtc G&S]zXlDJ<`]`]p)vq$ 0>gtlh$cel6T !$^ {Ŋ[I.W%iahxZ(P q<[̱N'@m9>Ϗp!'P?<tz JD|r"QD;^-%{Aլsy ;Bm655uSx JV~ 䱡-U^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-muc-active.png000066400000000000000000000020331345766322700264310ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-muc-inactive.png000066400000000000000000000017761345766322700267750ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# # |(~"i#mjB1i&)%35IS$;s޹ˇϾd4Ǩ0{r}ް16w꿕u{Ml7𞌐(^Oaki{zcnv驫_ ϣz%1c$P%d Y>Ǘ{˓3/qw)Rm#^W.s M!ҽ `tM*%R1`x p Y/cbbòҎiX302\&YAzqwKE21egvqǮa P*Ze|"SsDh^۶B)6np] @`), GNCƮ;W_gD|Ɵq4kT<A DA".B!Ѓc-4,Di_@EQXZ㹣/3?_嗿xG϶;pp?Յ9ˍVBUSE4p/'9~_@B=";wgm,,Γ$Tv .hY"f`Ƃ85 # M @U3caR*fˈ`5 H4/uR$Jyq,')O,Ȼpx[dnVlg]" bUk%M3"qjo=oIR9<@Exwt3sm|&" "?qk3q&;ȅTܯ+ޥ=kɉ0X\!.( U?GL鐕PD= @+ch[KR%bQ Yٿ;nޯri%͆SMI׫ o{3#jU4Mʈ׾Kޕ"g!Sw'qg//xقdÔb`i%MqıУmi?O0fGX{t^˭JQ y-CzvkՠYq}/T}0k+sB0Aύ<0kWR_a妫JXڡii4Ҋ ɦTN٧Gɳn~8WTҊ+!k@^1ͻePKH1'/R[26/zI}Qb(lڨTIrB:/bzzfX5ؾeJ$CZ]zT!Q,[_L?b $ID6RDmdGdrpC[vz,Q"AQs/mIRN/BMM XkO9n7UUU|`u3Jˬ+ߏҔQc.n$iZVtaI$R )Q,¯X˰GXa5> R-3 BEVzrpC P*]ccWR*oK;)´> nܹ񴽶r @ȍ'wj{)^.^ÇMwBss B @g$B[[ nZ[[>iI tϞ=9L"YbR C`lpr#c 覤Nd8a(n e)xk2l{9߿@(zBc@0<<8/t)<y)׾~}IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-online.png000066400000000000000000000031701345766322700256630ustar00rootroot00000000000000PNG  IHDR szz?IDATXíkl\G9gڻ ₠iVVmCEA6*@H !J !DAMmᢴՋҴ-'8^vv;ko;ޘ4:::3EkM E!W= qmAw~&_ .U@9ȓe0]xR^<՜TJ%{h}v%c/} Gl쏜xOK_k,&(E1A^L(:ȉR^sȳޜ]kW]bd3|n ;{ajAx䝃_ɈU1:}nYyAFڞ/{X{(<lr֒/~]M AҪLO8B2~`f⹊MAfV\=sۍp.se+c;'(@"1J9,# t]ޮ/v";P dJ9(%jZW;oSN  )*bGbl]qvҠFqWlRĮSBz`}R ^a1~n\#biH"."=ʈ㮕U( 0z+b @M2([ibiÕM("F0J+6MUb@%  %# Fj@ ARRuh+]П @|_14`A]32,@ɲ'Oa87FA)0fcD0@(bLlf%33@٢B)(tzٹ/uo9U5e ,p=?;eUbY<9uq7؆XjChG)bhQ M0l;Z~Hj&\넒Ύб-#`ru]V?{@ c(նt~?;5/'|AZ@ө GPɹa%s@V5=Ugp'ʉ96`m e Ծ8y'p_OS:OZt!\*>gॣOLLuy߻F\a2D9鳧8I.V] f ݻ_8r S2H:#IK;K bNMIiRYRsn|eבHlbcfUfSfKTN~:H룷;5QNsnzljJ-{w~OCBru IRϫ='@[+Sү&ΑO:-SKr|?uïfm.*`0 :n'9ԧ2~2~h#ŹP ܝH$^߿J4~ |Ԏ 9  ,زBF43jko4$IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-requested.png000066400000000000000000000043671345766322700264110ustar00rootroot00000000000000PNG  IHDR szzbKGDCIDATxo?wfvgwk?$*5MUӨQ*A%^*!RR_iF!)cb^zg̯;]MG:{9GshsK(Z[d>jӆ[l Cez@DhFt u7MM(B@E}=2 bQC80 #ӏٙ" Ck(-a@x> @ra!kUo֪kS q#*z-a|4kld@J<43UVQJ3MNiKH!*LenR-l W(VbnqړGsj3 xӌIf]_*iDO/m-ltd2I$J(/尦>' sԖ\ KV.4~Œm;O v$7oH lkAՏjF,[ )% aDHmmDRΞaR-%ɨA;ۍRjdemRSNO2<<({allfF14JАJ"=BB#eMBok{eddd2ɉ'tڥDJZ3 Mm Cs ]N QUk{Y}saYǏ_=zr+ v8wJC)?D1~@ \!H)%cA)X͛7)9]5v]bʀq__o(&qbF5j!R /c4af@ІI)i44O4`F(bZ!O8!XW`pp۷.ccc|'tttpauZvZvZjΕrc7*L-I%le& Cb###a˗9s BcǎSOm!> l'4u?Pg]9?\8JqC2u_^I3:s92 {g]sgERg(_bR'hZR|;ǂPv]y;eF6 [r (wF ㏔?71SWu'ׁVOw3t.28Xj o>4M05pfj? *`b@Ñ7qznoK Ke;R>:;;WqE;;;e۶m߿x<4M2z/*.3mW xƀPǕOLI;CT5ޙqy&''= C Mc{/1kULNb Pj82JRJi  ۷id2N<Ʌ 9rd<n9 Wk˕pρPlޖ̪⇷"j v"f2Oj5LdttD"AOO<7 h֙y4y-UԢӬ.TRuxoT-hry}%`:tÇc&X ],L[UlzR.Uw=?E8FY%di;unef硳3ZtwwH$HxgGӋ\[.Sؘ7_ܐiV tuyM%ut*Q[w]HRD"t(\Au,ҲZJӹ@m=K @(jpO^N'bl׎D͓M̮ڷD7p2r`1]JiTwiU| ܊Rk /t2z4鎡趮.w)5LLkv)ޯ`\jģ;m$s'۴+;hJSyWKfm,sM[tU_9oKwD4^!TRyUʭ ~SS PJA-[ᗁV~գ6h}װcIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gnome-xa.png000066400000000000000000000044131345766322700250100ustar00rootroot00000000000000PNG  IHDR szzIDATXÝW}lU=9~ޖ*jAt*:eɤs.KY)iMdl3pS)0X^[(sϹ>XJݛ}~=}[Tb*LV:fyr4bZ"u_Ԑ+**/Λ_{Ѣo"t fD)"rlF4}*s֬ԱC<p|(Rlii^53q>HD7ׅ[s#[,Ӵ\~vimw=: 6mj]t) a` @za(08bȗG g"do2,/*!c (nصjgɑ4i/ڷ[V ND;mg]xD+`׆8_,n<Z;ʠ^-<ʌ 4ઘLW_?Џ:("0 BrXg *!N#g PO608KsVSО5֭{;:d=reC.Nq PU9#/W:::68xZa>ZZZ}v$xk>>tΉbh(U2_h01k5`f~eBshd,'X,y{^5?1 qCД xdmy\ƾ}5YCb0M̌;w⮕|ԙ uhhsU^sRJ>ݗ`x:ԟw6^MDϮ]W/\cci>|k֬Accx<ޕH$ ضm[cW_8N,3o޼g2t;L&s&̀Ӯ0fԔaIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-away.png000066400000000000000000000013411345766322700255150ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<sIDATXkQ?oӴ=imhՋ^ -^<ODQ(Bf_KRTФdffw ^20,}oyU09T@jo^c0([}|fcr] Zzm300nr1cT\6wӰPně[e߭^uWyBW[ fڌeLVsmCw:%|}nIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-chat.png000066400000000000000000000012611345766322700254740ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<CIDATX?hArHEID0b!hc)F( VbJMhFbbb!,* D!=ٽg;{in`|{{of$޻r' I?>zy+{"v3uu'Jy"%F8 l]1*2qЮ:-K\qսW9!dA|{,Y.9G4%"  չQr8hUc.{{JJ8ngSՀ}78SUkv]B جV@sF*Nb+ah(F"zZ* S-a3$x=bě#UI0@#\)4&e,ѻy?#pk4xF[.:_i. yoFpYamU)dʷޫ)!ftSDYcRcЌph®rTu9 ;׋H7Dr"1s%vpc[qPOtG'ܸt$1Vp Tr2;W9 Cw`U#TߓB򤐎s&oDЋ9baiXPC-PRRg"C{q]/%߄Пѥk!珥`Dx6:P}~ݮ5%5Hɋ$оdJQ*/n$w IӕZXz++n&QIVSoM hHLOYafmVmCwIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-connecting.png000066400000000000000000000022461345766322700267100ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<8IDATX[lTU3g ,J5(L`DZ#QHxF%*A HRTSI[m-DЂ%R(9shg߇)$6ҕ짽׿eC7<75z@0H A ZiC~F7phO7 ,rps/|ȑG+lZr%DFyhۭn%^4fE-ՙQ}e2[E n^8Oe]e9 ]mܨiStixZK'*% dG c\lQ}}XO/2Y&dR""(ї7$mtJ&_: 7#pyPᰫˤT^G-ZpL[s)S>XQ^-V)9/Iz]2X;nS'WH>9+B֎3IMA3vH>Z<|(N,F0 kl\ Xxl=FMŨ Mɥ!gc X@t1 [e':b@_TrtY}: `,L)q\d"ݖ,Z;|~6",Cz - ҥ~@Kz-&L",3ϤҾwvUVWP4g6yxOVʲ86~VU?ȶ%IuuڹPl-Vx&!.X!+eaUTg!(s֧jj$IjݺkҚ5*_ f#].xrb媬Q/dRzk )B6Lt7ͭ J&-ߛ.fMքJ>|h ֳ*[h T(rC;jڶf3*LRЉo' c; bדɸ6eŽ(˹H$ohJ8˕$!ħΥgd}6zJ1Z*7NNx}٦w^x}?|ee5{Ur6u@`qmbsS$Z˕H6аƘ AD#Ȑ{cV_Xqpac18O{Eywxk8yG"RWF;#?:aԞSj7CQ$O?V,#[w@^A^Z2Ri*@6/^#SriILo1݇ChCmGh}w1mDk3Ҍ9W8!Ҽr?W=?֣F+;OiBhyJȻ䅦?e@`F~(F+R )+p1E3pĻ{Y73C*t#a msӡHOB G&#]PlA!4uUnc*=WY@7U+}yJt\.݅R,N GhUH(Q-4˞T.z͸p_%ƒ.]{f #"JLbPT4Zܖs_o߯⏋ڨ=kl^vOFjm](8RP]iĔH]ڈir|Dp5?||NJo(lW?;td*IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-event.png000066400000000000000000000014571345766322700257050ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATXMhQLTRR "ԥ ] ]Bpۢ;WE""TtSqTݨ!Lw]$iI2MM<9sIiUX#8<-@w3.! h6`ƪg "; G/aNTDjͤ8Loi0%Yy76/E8T nM40W JM<.̤vLjzǑ3Æ1Cn=ਟ} }e R=&09J}ݢ}oxSD ٌom!k ݔÜrD:` Ԅ!K y(J]쭖Jlzy"RHVքKl~ERcabE|PY.n`n: RjVY\7C ȉtL]πY_Z2RjvVvsXC*/DZG"H_}`p^VWVrD]&/!hm 4e*NȕJO(xS96w'*8{VP/JT`b"FG?2;"PY|L^3J} :D>W}$BfL?[} /klR= ; $XZ_k=qXIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-invisible.png000066400000000000000000000012101345766322700265330ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATX1QgoSNOlBI!XIG?JMa4OI,kAh01 "owI$4;̼!"ȳP%Vu~jۧ"y" uc'"ⰱ0cvO`@8t<p 'DZ"O;d2y2);l6`KD^Ѯvf2AAg ض#"k!3xBDZF#>d@V;yލ@"m ṡlOJ)q ?߷ JTJJ)r)F,u+@D ʌ-81 PdW3}PPZhu׳\ռ|IS߂bo4aT*@Dx`5a\3-v(˽m8뺏 C-$em2._yZVAc>lv4˞MQTE#6·%pIIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-message.png000066400000000000000000000021511345766322700262000ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<IDATXoU?tJ)RB xI"0gN3??)%33|~ 0[ۘ%ɔmU,F29O8&LR|=; >9g?ennWffD#,,k9@;;;Ct(J&jDGt2,7z{8u$B[yp#v{.dpϏպiH$܎PQQAW<L/fg 4xtc G&S]zXlDJ<`]`]p)vq$ 0>gtlh$cel6T !$^ {Ŋ[I.W%iahxZ(P q<[̱N'@m9>Ϗp!'P?<tz JD|r"QD;^-%{Aլsy ;Bm655uSx JV~ 䱡-U^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-muc-active.png000066400000000000000000000020331345766322700266100ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-muc-inactive.png000066400000000000000000000017761345766322700271540ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# #v{3HbY` rO&gDdK)IqCMs)1jx<~CDHnH$D$_4K{"r)[FCPVox j˽*6Ƀzc+`YwP-$/t:* "l0>whzƴZW BָR).h0JW#IutNi\x܏D"&c7=-cn;*Eq!|f Z/$- h0J !GHz,chY3>ݤOy,< ,}Uȿ= \:G"3x>-8d2$yjAq}3t.I)?D{Ѩ4d$,"w]; ,4b5/f祍QIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-offline.png000066400000000000000000000016211345766322700261770ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<#IDATXAH\Go*>1}T D`kҠzXBNKXZj $H +Bbʽo $"DQض\.l6&@5xq T*ӃRe$I tuuaddtiSDBb= 31̌P("B:.<477X,z'"{=ƩVdqqg"3}}KKKߝ}+"Z?$Y]Hx1澈c}_^aJd lݮH^)vee4 ְj~+4pimQ)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-online.png000066400000000000000000000011301345766322700260340ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATX1hAwwH((F,[I!F J&$b#gH- enr;w-a D}e7;&aP##@#!v1I`o|"ڬ!ڈLUXǮY x lb py0Pi 4KyႦޑfg<#P+eMk.ـ|3-tJ1߂,=#G]kng*;߃qH9d28rb.&apd@' ~K %B lVai،tyQ%rm] T7@'|LCT(5s8#|AM*cTیv}ݹ%[5<j2@hs8`l&K@2ȽUb|"aHN2^|:0FxiQR&8 3!Ո*"5#ywEٛ+]h^OT;7U1 '4Eϳ 8qΐ k֧eP_r"U(j06amcOj=*ܞ$GφSت堡Xp9=WӱPj'IxN7FM  es IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-requested.png000066400000000000000000000016201345766322700265550ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<"IDATXVAHavUd3S4\ұPŃ%%ȃS !’"K J"y򼂂(тMF3ov:.;afg!"8tL  hmm.0o+ ԛ9MDΔ6055i躞iii4My)`˲ [(&2ף PUU"J=s27rnvh4ڲ,455k4MCVMwwwwc Ԉȵ̝f33E 9QbGߟ*j v|#ǡʕ_$ B3tFGGaF\"^ fˁeAD]8l߄w !mll.ʁ׻ٛ QWH@ 0+;̌J&r. . N3_|*Z øg :fE&ϱnY{9톈 baa!eoy7"" FGDfybvT̂dd2y p8~_RXk_SggQ0~IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/goojim-xa.png000066400000000000000000000012611345766322700251650ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<CIDATX?hA3QQ BM ``!b/J`'(Z؈ZVMl p#|1 '<W"aŷ=6 |`TVT'$<`J6Ř[BGU.rcf\>&u.g"+[GG?QI1Q Oˮa Uu=3aWz/V]9o 搲 CVZ} pJ02KgtSB0VhAlvNPԺlg|$Rڀ#Vց?Qe))քO]u ZO}>oXutIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-away.png000066400000000000000000000030261345766322700251650ustar00rootroot00000000000000PNG  IHDR szztIME)abKGD pHYs  tEXtCommentCreated with The GIMPd%nzIDATXýyPel.,"zqW-YԱ%Œ0%q_P+\3DM/XظnSZ5a۔p9=Pˉxb!]E~"NG:<ĒFW ԃS=G`4@~'?wPI܍ Cg׆h덎AwpoŠq@wW /8QX̯$" M/mݜѹw' 2Xg fE֞Ll&߄o 3,cjB4""PKt'U ނJ~to1FaYl;μWg틸r2.ݺ3N#(8 YOp4rD4&{yl_MOPgy $IQv-g}ۓ^."4>FLN,AR;*7+y,i\btѠTH E`R34![X:QdB XJ=oɺ!i")#Mc;ʷK r)^{{ wCΣؘ];WcU2Zqvl~q訩ܠcY*7YE+3&,߯M)7`n0o{I5^?bD,U7xh?8:i>/O'^XU fDnXYQs&>ñ"];΃KT "h"JABQBmRCڬRߋߣ>%NKrQF7gC *6? eNdue!sE& HID̔hP(, @Xx4J &* rY(e)lˋldV^]#1܁gbƁ]ڴrTN|Hy㬴LtN*^@N {n@~k8q6#8DZL~n2b1rZ> 'R̸xR2~2wn7{?t's |$V'kv1QlGxTQBd̄eʨ!Gc_bѕES-] ,Fa9"ȀRd3#*m^/0UU(]Kx:QƋhj;M)җKE+? ZX'GcJQP#Yoyy^}zV*dR9Aq_Vc>)>KLwL,`/Y3;Z1%4uH}"U|ManzpM;!g |#E>IS8G DPkEoC;bI* )J!+N_J`+doI<~>Kk- ]EB" :jɰBC't)%"F$(ZmBX v~-\Eۋ`-#5qzGprP񇊈NpH~B)ڼyl6!11բ eMEa0Ypt8Z/xFјB$4sI0kiM&)Wʾ4xsaJ3>>I Zd!7t9%U"ͩ矒ҼP0777YnR _QB<1c#UyR)\vv㜓3z˓&M*}-#HX5k222Vыo1݈$mȃn7|a4)\jfmr]4ҏ, ?}tZccc %%e uixZF&!LC2|}}}ip>\"+ Vv!ou:UJmYjbp8?M7n̿~z2a  LC4G$~pѣGر÷~֖`a˖-[488}-:H=MP?GM p<IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-closed.png000066400000000000000000000006371345766322700255020ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<1IDATXֽJ`߈XlTpJRK,FQaKK?* 9cG8H"&+y7̼3 I 5`E4BwySW),^0U{0Mt4j-@ P81]"[p7_$N0тXG%G2~V83ưU>15E@fM@?Ǣv8Ѓ8,ENA(3ojԸZ.$wZD+}Qs'N5xKCk?IIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-connecting.png000066400000000000000000000047231345766322700263600ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDATXkl\>~8N8! iPD#"Z!~ 5U)T(TU[)-** i vįڻ{sN?ݍM)I;>4 b5J|G cX)`80lCGodMq={"e@ bUsX7xhއi9ɷ6`4U9R2/_ީ^0F9Zc7 cs@L>ڛx ϯc04Ơa:y?W1rǥC.l0lIOMjFa"[,G}+; @~^$kבk)҆ьhMW,m%)k 4%Xx)-k@=QگuO?z?I@K DI}  ŀbJc"6Q ~[ZxY˓K>pxHxdhmjhB %HQ55Udp+PiRsH&Y%n[WUGqmB(5~xJaI@A|Eh#ScB Dهmn-մ4 *Gضqk[ڷ?*mݻ h[؜ %1/ f`,X֫p -CԵ* _Tģ6o&0Ip B=|&PM%akPS)0^f-nZPڑ4QGR[r?a (C4(06B]|4U{& L%@[rHUaIX@ǖ8ĶB LiSqMTaKpPhxifn]X)M5URH$b MYq%]h \);P@k|eg(KA h?E;oKM)&! 8aHsy;C |MWx@S 4 ST!Z$#̩.I\[\iY)h 5Ų$MQ,]PMs}#*y: 9DFu-X[gFˍI``2[ؒ]qTsذyuQ<_#q$%e6:T:0d~ec2Mz$3hVtk4ڬaP#5y͵9?c^S=KQ 0Zb8 a$a|M 8;2kbIs '%U ǽT~ɄKĖ!}>-x֣OH@c!%4D^XLYVG{SH>4X#xӲQ9G3LTRfŒ~624'&99Ǻ$+ aiēٷlDuKlٶ`p<7h:n5d MQT/kdz'cXRX$.ڒ6)~ _MTy=*{4zhg22Y`4S QǪLEJ@w-͉:a[?~z x'Pxtb/=m}vB 4Î{nceģ=6:yhZ N@8͚^DzjQE_39169ͩ}tyB#7,۞]z !Px{=ů. ϴgby`LB>{'ntg4'3IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-dnd.png000066400000000000000000000026131345766322700247720ustar00rootroot00000000000000PNG  IHDR szztIME*ӕbKGD pHYs  tEXtCommentCreated with The GIMPd%nIDATXõolgK{rJ-[Cf-l%c|%hbbAb #gsllck mmmp%n}'7w9s=٣F4`1.1lf"cfD8\ dx QW.0w 0&/ DZa >Gs#X[S΢%iMDw3$>hE{v/,cbaSsxl>Ņױ?OzOu؁/s)⁆6Nk+MM,X LMQ.=+9AGG} o74x kn!<+hi!RϚXDr6#;"ܞjN=ye俋Od] LN2>kr(,?zJ d1o@3>Ϸ:FsO<\51AC܅ N6+tBv*{=47s|9Qw&cYjJnJlE[u1ѮUΑZC EHMؖ#kKch'b##9sZ| ms+] ذ]XJx:6m#fu/:dnt:2m'b/B2ǏctU (:;yqBucTO˿ޑ-Y3?/KNEŹt3Cx.%|iUJU03f7_x/!og y0\!#| Y?UAP( ׃vW;W*n1ZG8af"4GǓP鵉hFF5A3eŦ+x8t|oBֱSˤ椐M)oqD(َf7%EY [ěX@g'ǔ׌4=IPGh$4ӳTp_I\z,R/w4"NKV3/i\[IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-error.png000066400000000000000000000015711345766322700253600ustar00rootroot00000000000000PNG  IHDR szztIME05nYbKGD pHYs  tEXtCommentCreated with The GIMPd%nIDATXKhQ$14$V&Ħ 54/!1i`EA7t!P QDtS;7BWvQ J뫴&6>pfiW̙/g{ÌFK6e5aX&c{XX,FP:;;Uǩ ѺN'% $k% Y$)0J^ﶕGY@ XXX) OO \_r`uul6KLF|^_X,jB7պAݚp$IvepA+q0 n+۶Nආ05 cuȊJ*WfVL&r^J|p8 >g^ ʲ\J&d .E$)W-{Xw4@YW@cH8(pSwx&P@ ULf)Ps-O޽ fq.Z%(H>E Ha0A)b׹@yQNU( H` ͷc۱LV1a8E&@Pм ŷ$z"Qeobb)E"FxtJ)RB xI"0gN3??)%33|~ 0[ۘ%ɔmU,F29O8&LR|=; >9g?ennWffD#,,k9@;;;Ct(J&jDGt2,7z{8u$B[yp#v{.dpϏպiH$܎PQQAW<L/fg 4xtc G&S]zXlDJ<`]`]p)vq$ 0>gtlh$cel6T !$^ {Ŋ[I.W%iahxZ(P q<[̱N'@m9>Ϗp!'P?<tz JD|r"QD;^-%{Aլsy ;Bm655uSx JV~ 䱡-U^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-invisible.png000066400000000000000000000021511345766322700262060ustar00rootroot00000000000000PNG  IHDR szztIME- k%bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDATXýiHTQ/dZV-E$*Qjba%e0iDEP_̅ P!ч}Av+,-kfIg ?}s==Oy(` =^9L9w8aL< F_ &: ĂbhWA%卵jr?lu(냃JKK# C\z}}ȝw/[,$oj[ZZM&S*Qp"Χ677'x6{u࡙/ Bp:(ԓ:3d28d4t:]v$n!Ez(Oe۰ 2Pn#dJW\6Xb̀ pQCK=H8qFdl:4ˈ`|Ex B: M F&AdzYF߼#bf1%̶3r? }7XDv"EwomZNB@ deUtCwtA HV?0 ~Iyk1SRdpU( 꽑v|QĒ拇ȉ7F!I=cd@!ۧKV  `i?I&k̪Q6 UjrBNl@ eʎhf2*=~\0-nS(<]xr}@{sy]FPܗ_aٶ2=3-Y'50Ff?9!+p\)\9{,A*ob1,`mc} {S.ϩk (Fl48iD/$0rs?YnO(G/yovmY2Pm fBgSX"g*>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-muc-inactive.png000066400000000000000000000017761345766322700266220ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# #}:˫MQ̱0Cfff߿?oŊp3EDuttz?-G5ц(9?zKz;//2ݻwHEg͚5xBCi["F 6%/¦#WXUUU%0ذqFe0NGSN\D#9O<)s'@¥U.[|y=IIVэIOVVVUǣG~gdd\o"444 B-pi<Ex|g#b y133y%^N7xeJ(C'e 'DgD'2\FG䊝+TA*}OU 7JWE##[XA>5) ӻo}{g MjWJIsH>Q=VT~ڽHÆ B'M&'%}onzp IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-offline.png000066400000000000000000000020041345766322700256410ustar00rootroot00000000000000PNG  IHDR szztIME,XbKGD pHYs  tEXtCommentCreated with The GIMPd%nhIDATX]HSaMjaݤMҴ認ˈ0 B/ ([ix!EQEAQQW}Qely2w9hȃ0Kp^31z@&Ax [ rOZ Q978!028:/GEf3 Rii)NSa8sUb!GMMMC499I455EX(Pmm-QNN2s>\ n8)nt餆166F]]] I+C<]`MOI6M5nddDaNOjsp6.~p*sEww7SۥI(98>" 555F:::R&-ڸ^6,2fjmmMIKKv{-s,\( Q]]ק$ 7P-n'*&xϫzQVYYId0YdCʨ<r\dZ)77wJylAMi |QFL&T! &ܒ Ӟ4HViēVpq+?R}^rrb[d;5s"xMJq9˃fhL<]|#fcpn[4nv:Wb+[D7ߘ=Օ%r|s k{";w/E Qh# ,+@On(?S6Q~gJQp`T_YORv D..4;#;'QS,3c0 C+l4Bfg&t-AvW6v/Fol]ؚnY@5x Ff6p*99yfvvV,JHHHY2pRR[[233?777' 9d;8j Ą.V]]vzuyyy4&ᎧI fff$xc}X"&q222" [92X,^ruud@8|M~6s,;322RB!MMMy]]]M(U t/Sk100b}з'JDrKKK~ @Z rޞO[ Oޢ甧-@EVL|#"E8:!(:!4@~zb xyuZSx B$cJOO庺Sy||\)~C8}PBCCC&ڞcJzzz‚ iԁJfdSSrȈV}&77W'3z]@uHLLhkkӊ^.9 [5 z٢E{(*UPP ?RSShrR,6%%3D@%"<4& ^NNc%($6 V~o IvlXD`+sQQQ---]G0kIII666rN=ZHz8{v|bDg#twwǢ\244ʗX p,ȷ MF.$-l|Y 8f@PhIo0"T%a SLײbjDAq9c 7 2?E [EQKBR >͕݀uUbD[@&b^#hbyH+'Ax|j_ٍyM #a5TɡIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/gota-xa.png000066400000000000000000000024501345766322700246340ustar00rootroot00000000000000PNG  IHDR szztIME)7`bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDATXý]e̼vۭm.KacX4j4И^p Fnx&J!jxA,b]+[.lwv;x v[֓<ɼ9sSra' `w_ğx.YJ؎/L!HUR?i R$<;Ņ&U-Doދ;p0zG6A<(~ _ƽػ]Vs=## 34Do/*44LLHǏ{|v֏Rr,Ə=w-U_Ǒ[>EO5nniINcsh~Wr;Wõ|GU=7́go>T* *Uh89ee<Ӥ`wFƻ 7ko2m{YWq Q"|o3w3=}Mikfg} 4uBFťv%eWrq~؅{F愫TOc)eM Ư3M~ 0=_!ypu+\Zާٳonţ>.md+ {j$U%;{0χS`dvrRaJpf[2R]ը|-/ ](!꽯C|CNːa2Z۸!K+e3+-0fd88x9LLhˏ@Sx t w+x26B⏝(2^Cm=8}UӤv&I*<N/pHϑZo)7; >܍Wn |Geiek|;}P+y'޲v9YOFe@i*^"L5Hf Qȴ(EmF݊bolHCחA'f=!zV3Ѵዱ\~ +'<2sĵuRW{5XNǂ[]54߈͸.2" _IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/icq-away.png000066400000000000000000000041271345766322700250120ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME IDATXilT7o{3x7xaߗ$`AIMB5_Z)_JR*$JDi)%M,6ccccf<{O?6TʇJћw9`_GP|,爷׾hم"oj꥕NVgKKh}FKWn'a>UtnM!z=EGWòAeZynoҀp]IzE:FV-]<Ca'I;&g.~r,.6m u;rԳCS>ꆷg4mH7Ů]D`Z4+g،q@.< ƃ gu>f-,t|86BkuMM!5^xWhܶ۸{%"+A…dIsp !Ov";-^VLY6EEujɢnnV0ŗr' fB)> _"joK&D4'=3ūzIHjV-P܌-v u_96,a1H<&Q˃L^D+| $ojNarn]Bњܿ1˃ܧ'j*N񨡀*:~$bYoԛ+oY-(3r4MD ^[:P H X{W/ǒNݷ ܘ:JAW~1K/0i7CH2.k@,ڡ·D"m";lg9J;_`?Sf=ƿǸ2{tk^)*e4Iz&Dԏ'JVZ(` "gɤ#+oaO8%O7"ȡ;`KRd`~? p_9{*%W~}c%=\Y^-ː JӨϤ qɭBvpyhIkCPuk֕  o/cȄ ZH"3 f.F.ret,4 4e\ B±8 )r)T?c v3L讆2sc7 $Mxskj<Jt xcJvwR +p 0c"ذXX lH^8GQ(0B:y4Oi6+_x$$ATr Ν8sA9Ȳz<{9FUp"d.:0R|rqTU{ 4_:#iY.Px%\W6<^˜gHXRKZƦ-%,ږW6}ss={}\]7x P9M8?KѶoAL`e !ss9j;~a㵗 LGUH>xvX1-\Ut!L_Bwp{p@GVH󳣷F|=c>jJS47נOH d{n W{~Ge+\fT1M(\aZL<IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/icq-chat.png000066400000000000000000000045371345766322700247750ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  IDATX͕klw;޵6xmlc;!g e@ % "*MZEKM)HA!*QH 0`y8q0qb066އ{o?^Vjw=?6 9'5KM$Iw_|ZB6 ` x@6 V1Wh6K+WV3=D$i?)~׮]o[5-vQ}TgI~EFBccVNV#tw/dwCYmoXTVqQOߪپ;97%H:XPJq{\Rxz]C_}R`r(Yk/YMc4k6fVφaEWTM̝3 QZR&2ɟx~RyU8GBYJz"+\3J 8ylXi: Xo{2ӊgچr_c0:H8!;ήlɣE cR JMȲ~DRWL)tCfNq Ot~  󖺾nR"$f5S;iZZ ?]NpJbQ|՟ )g̚EZ:D^DudJ˹z6^*84'"f/fQ^@+F۰X,x(*AR 7g*.\:}S &]OR]Q߂q[sю0e WW^aW;qfu*iZsx@wD(heF[l;>Rah+,{Լ ƀt&O@0R&G* pDM8m^$I­.lm-%ؾ=ә$hx 80`v#7#,Њ 洄pZ=wÎ,ҫ jG}}X: ^4EMER\pmzo;Co?0{7_hS({TժSP s < W.;Gqq> )e@y=}hmː2 ԭ(>+Ԧ8l@88m&O;#ϲ,+'dw_gV+lכ'TaϵۅS|4/?&X8 CgDDvc!) q8uM0F`B&* s_<=6'n%1OZc>|DpMkJ%x;K#^)H $h! *o{`C*is,Vm>#DMb0 ,@Qf!هH{ etp$. U T<|  9sM k% QӺ#Ѝ䧑pV)pܧZ`<—T WcGTaťzܜC0`-)ѝ;^|ɬJ쬙r[,bf:1+ E&0$eW{Hs3#1QԅKPPsQKL\']ـуlZWk>rk*3=#Ca\h﹦) XEDA~%3/YUkm|*:#s/ 7}U8P*L%.A64S$]lo06g;-uoNcWlCr弍tFnL,r䉃SG`nT7R#`m~V#)Ή:褀sD^Ȝ)8w{ z5˭y f92-}-cIg;Y'x#zB rhU;cГT$2FC^KmQ_^N!쯮fY %`  m"ۀ3'ȳΆm u$wܬ ^M(W g7YTg{/V-x|a7!S~lolnu:»`w{.YqD<=bonNU?cVsOV2ƅ= cqc_t #{;IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/icq-dnd.png000066400000000000000000000044471345766322700246230ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME IDATXWilT[fޛ͞cd$ ФtID%JU*ZIUI5$)J\ 4@ Swq߼cEzFG7|{7unھ>SP6i)gYHjc W^;jWY}Je2zR|LtL_x<1SǮG*@ QV\ylE:dLd gmǾyշ7zm}EY3 l/uS"ɡ^#c[\yA2/Wc31OY%yÙv%:]ڢrvπVO_>T{7 -򲲶w>G$(V:WA16QU*l  Y1Vu5Ύԩq~V=uЎOiAnH{Ͽ9v\3]nxs.Pl L8 gFEEA`E(-[әtm!j| ~ l 76nt/^Dlb`*;0\T ms~[YNADH'4ޛPlz΄9<L]*#cROWUz)6Xn6R n W,iFpJ(-OMM?<@VdJgX"(+7cv[YKEb͙[k%&Lmpԛ#t# s؎7=/~o H# 9PM A,LD-ѳ88 [o*9jW(dؓI,NuC^%Z&P:^wfa_x&2jYXt˂>W [nH#(>+0qV* G9ۙ͗L Fĉ##sYĠ$Qm ԟev-7N-(l'tGLDu0#NGs [0!3v\ g;>Gg% k7> c\̈́#+:JZoZg[F0C臝fɆEۦP%B*T$#N>Nva}prYT 2è~/gAHUйՎG81]1al7 2 ,\P~]:.BnA}GD/{[TlɊ.m ËߎAʼnMpnhR?T1eM}btwZv%y *.= P\f= bw _ A 1U+u l;O 8?;quK؝$g0RD?%AYްJjM,!V;:$V> @V>t] };ӧ6 .qn^:5yYAլ;(Ƨ#X];J&Ovp zSSkaMaG㑜@8aZ,2'h6"٨5ۆ|8_xb}=nffs3؞=ir[u-dIX DeD`~;#& L~k"S&VqojPsρcz T& ,KqXEpX3&C,Z|iNu|>^Mr_oIЬƆTZ8 Mc0,+ 8ƗΖ0Q(1GE-(0cE'VL#7x _ˢԴTtx֧ؖuᶉL6~N*+eAFnoO%CE@0Wh:\aq܅I´XyKTܞjFKz|3$qfY,&mI_{_Rzl 7kOFk3etFmIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/icq-notinroster.png000066400000000000000000000042641345766322700264410ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME VIDATXVo\G͜=={eĎVbMR9ȪDX7qAK+UB  $x7(-ITQShKpRv8k{w^};۵SH|37,b>:kߚIg4[??!  +Jgg}CL{Gt^?ѨzFf퉿|Q{ / >F blS~0s/7&IpQW͛7dۥK_g/e6U"u^4:1Onzi_}D4 spQ,Q__/mdr|s<ˠۆыĠ{s(R}>I^P 188J]>?k|ĉjS;1`xd)Y_ qh\o[FÙl*VWrDZ[[ù\sB!,..o[[[_jjjR$s|ࡃ {Ş"o>_cZ&y9~g,j5~ yy455'&n[ x^d2aߋMMʦz[&?6 zdE}__M2D6E&Z -_ߝ-F(c ^ض)c!0L T=J$b1JEj> :ol^%pCG:NT*r4MeEo$bnn}cd* 1n/c ? iTu]$ ?@mf++h3<Y'ُD,N ]g |$˨"_K 巫 lb& %9zz ZMϝ:'ʩ^gn9ڿ#l9(j5J0~ښn\bV`bb^skHQ۱8Vj"1`^'T\U,ȇ{P"X;F#|uTŏOMƅ[;Ap ƿnį#---j8ɲ`.\xqb'!t{~78E<[m43.s/r1PbvԁAO}cY?"%wtvZŅwW=zv`Qrq9ϟ|}bQ>8rHS}$⧂۱:68 8hڠ{Nb\0@)(Jf_[[6q{g}7ZF@ߝxݶ- s uN/}ܻ1L=^ǁa(x<|r/z(J_$3`+\4 * j7u\,|=U60- xZR<#\6w}\H;r P~ oeeFsCJcaYq3GVsX*@xlRadK%Is?V]L,rY'N6 %( ׯ}-H*t]$ *kPj^Y泳3%rHv!ua&/ò,(OdX_fe/j5 Lr`;wWVVRb%|P[㛅sBa/*uMt&-ex&.&bhRF6wKSSS9czF:NlۮiZff]]CA Ir?k>bOQUdX[V*iZgw-+`)[g#Vb[Y6ݤ@L",JcUT"!J!')B[V- B0إ?^ݽ{.~A!*uY=5mUU2&bĂu ݻ7M:k\.f E_m8TU(w랏/\*%_5D#;w|tWZZvv6,W_ 675zw'G{囷c Fq|bmK\۶EǻuL|ƷP/ur!tcт_-+3K@ !&;{߿g[w};wm? `0,;&@i.CUT$@ g`o|kߔ9)}Y9ƈ|vtM Ng /^XZZ[9!3+YO+i˗Hl;nBJdge\?&\^G٬%7J B x^饗Vyv#\0xsqDIIB5<7c FmaP03kwe¥CTRZZC|p'hwYOB$٤LӐ9 lL=3@z{{By2YV#$)l,^Ol#fU@]*ŲASUaTWD~Ǝ71U@D't鲥SLuH)!IAH ׄ?{ދh؉Pq8cp(+׮w=h 櫻*v5.Cc]{ڵ3fsss]iip%D`.8n@ j|/Fh3!}Xgw%,+`Vb'=>Ox[R\휳BM\L"+15#HMNDi>kӌ0H{{x`VV8`9).9sLu/@Ԧ7 S1"D 7DD`!bDPs\O <obtCig8NXV mö-ض ˶`fjksuv-9 )! B؈YTMʕ+R%TE;!=%j"IIa)Pt0}}2!*C!%Ixtt vLJ\6LVc#lF"OYW #`EYSSR@4$| m;:#o7E͛7AVbq~6=]/go{\Ͽn>uу1MM!%,  M}־^ɹ!/Ϟ VII ݆) ]FQņ?>s Mu@p8Rp=1UN(R,IzR_,[!CJ;JN)iijqgD,\PJWt]ObiƌTYf #$E¡,SVok( DPUAu; II70+;U&Vx}~t3'f)B0pv`{k{sCW;@30 M>LQkʜ9s~ӭG=^"h$v#a0iy |9|Chb0|kR'ag]IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/icq-online.png000066400000000000000000000043401345766322700253320ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME $lIDATXVilT[fޛy3/،=6bCXCBJJ4Qj(RO%jTiլjV )%8es1[&xxl (R^}|9>wyh[6P{c >ȮSw~(DUO-+7(]HǗ|6д+=+&EK{KR7(J*n ?rd'D,Aܽ, ʂoó[j=n$kP *w*+~:cvFLAÚE[k~򳐒'ƭ0 h|G`yJ,de ϛ#>:D,_vNX@l|E\wO-mqG <^t ztS"NC3N>Xپ K,Fkl$|Z3ihV?ܲ9փ"=me_m'fc@;bL8VR>Sի#=@;HQ [%5]w#<Xqe !–]MT\`"r#u œgmfu[yȓtMC i_cUf%Pr\M&BGET/4,t.߼0mѾm(LРwǶ} )RI ,Xg<fb k3 JFђ4GȰeهaQ-rtI&lAsc<#;E F , a@bwF7 }n.D nj%Gށxp[Yg;V,,rqaǡ1ͽXJqL;"lۂ "A('8<0Y~dd xǚgƅlTc C~KD{ ~R4-֠[FM5'Sb[vſ`70.eCِ6qL8wS Z {x<]DP(lQenѿ*&`X!0Ǵ9&@po;~}"z$̈fčsn:X ?8g2MnƂӸH'̑tg;9hb֖obO\YRQAp{s-Z(%?GJoLf 6:sH抧BN7qd3 /.yVb'`0`p.D+FJQ6r=<\R7ۿuE# >j B|ݢ.dVmۼwgm{tqXd H7mkYj816O"z9_8nOK$ʏšA`~uu{ﶿbOWv ??~bt8V ubzlsbg9ԧPY䇖u>eJ8LwbcDLdcF?d.W4pwù'!gl.iE&wGLG:z[dmNIUyj1eOxVg5A q rhhivDL^َm2^ ;[,yGx,:kþkԸ=1XkǛ"w{!ͯ"7^y:zK:yk]o fgclrw$'2r+xARu hJ`F`X aBGfIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/icq-xa.png000066400000000000000000000041101345766322700244510ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME $lIDATXV[l93;;ݝ5^_11 16(DDD PR*UFҗH}Z)KK(HP))NqD)1f׬/x;3zݵ VZRk| >اtI!%Wg;NRϔq!LզqPd&W)U={f1]H$1vϟw?-Q@54ǻ]Uxj Cݹo_ig-WWyCoτeyYIhm[@@d@DSl7Sz]Eq?&pv}w4=իu}Ix7(74|yϞ[ TV;O{;|čY^WOz3J@yEQTbgK]ux]]4L89<{wOX, rQ}{ؕ+(a.''!q66._Γ@QGLڵ2D`mn.] "(^-۶Y|`rl 2:8OY` ۆ_יJ 녯q@2 ӠxLӰa˖u%mQ2Uen,~Kiq'pn3[a3[`G&1u1*źM,:W4@m cŃ%_MuĦ?oz0t#2l7LN.3LQ2㜎R꺠TYjDffL$hcg's!i{=b; nR`]@WƂųg3U6y@>Ŀ;(NIyq.;lk z++**,JͶmfƉxpX:-wS"&Ec#.g[oYp`0z#p0, W.t-|\r|jag2sTh}v!*8?T^ "XL&ʉWT :1r.8(ՅKT+E) Aw>4 ŝ1"0ϻ_+%!aLG9Itac8(Fy[-ۆ(;KLUCCoS(TaG" OC6Ca)7= 8 ^_a!~p^n:&K/3m۶ ۆm=6679::x  `%PK|;Q02eW^zPH"[t紒t Ψ1-!P5X}Y,GIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/irc-away.png000066400000000000000000000026211345766322700250100ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_23IDATXŖˏTEz=Lpb\q u{֍Wٹ0хqAQ" ( 3q==i11$>|lfG{[ ̮>OZja9Ȅw֎'!*>xw֎=qRN0iՈϯ@l4r pY4ujۡ@@sP; Ą˪; )" 3׾h,{vZ3]zts nH -̯zR\ÅA9L:V E0n[[D}2震T& ztzw2n}k@B$[ү[(Z7BHbISuj@#ˆـ d*rg":htXa^GZAAe5`cv;vY%h 1t+![`7a_[.H 4˳.@rL6rΫ%ZXk\~!!`-/oycQPlNPn; Wև2qR萄z7vZ8ovSڸvicaM-4멍ONk-5Jm ,^>K|v@UlluAV׀aGqcJh{էU)T;.٥a6n|]:o܃\vk_bozU6?t v~=]h^w#ay~.H/<1MzF.0)6bzݵ1(wY+`=!)Z=ZA`#2PB&^$hUW`E8VZ=Lӛ!Zc4{VƵ˵|d/z3d+m%)i/|bɍo2&IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/irc-chat.png000066400000000000000000000034521345766322700247710ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_2IDATXW[lGfvvc8ķ!6JiI hZ5 * /~P Q6n4Im4EU'CHKe3{g1#voJCCb:g_y}X,49~GK6ڬfzW2v)%}R-Y exʝCÅYw^eч=*d4oD,*Q~\69"<7?ų\8x###W(@vԚh@Ŋmh~}_5{14M0i#{};:4^>TĠH0cAn޸)0_u렔ىS šww::6p~kCn6 /TU:{_Ol 9800 wiH) |'.z,ĕ[esEWS0 qvm8g`5%@)ՑX\ VtR۴݁3WvZl=0 9NJ)(%affg0* 7vy! k>Ք/s^xXA1tNRE ݥ4,S@*M^(bZ>&`CO@uzw0:}Mkq#H)͙~ءhf0: `\?cXVʼn4z3OCZmW`0Bp-b3Yd,g  F<)ش>"MJ硔U\igaN&g @)؁pM[5`(*fɓIgtoPyYpE<ފ?ku01o^pPcHJ> ^BKW>K%^@[ZZ|PK*:7H`prɅ!1S'@m`vjse,|h"ljFK@7X(f*z"l@{vm6 N"83vxƂY1|7|X,jƻMWgoMxaD`||T&̤)?I9@;_9p'[JNgc{F^%FDy" 8bBLC*@])kXoH C))g BG$?jqyRN/7yЎx۴ҭ?F-s')`Tq#zja,& 9y"vF1I彚XWͥ@ Ez^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/irc-dnd.png000066400000000000000000000033361345766322700246200ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 9PeIDATXW[l\W]8дNDN\FUӄʊ@F"P >/ EBQ  _ UjQ81"mM?gVе;?Ui;=pݞ'޷ʴk񓟽PIc?v4a~yN;od]l pm U݈u"ÜP&m#;ef֜"ڱLOspf`Qps$?hc' @fna,"~0FG&O ,,i:2 <9 ,5L`SI?2m bW7=P-`n x쑇~i~\*7Xi6K|r V.- U Ƙ\փ6Aєws 3! *'~'BYs`H0&"5pL@X@["{=]#ж]K˭-ѐx~//3ԙ'<ށE~w݋B,@xczFx!HzěHGZFHDD@u"ڇg|uײsHP> }s'~&ݱB̉Dz LOA9Q"jf.:vBe\Dd^ ('rOƱNTj>m}r,:6nm Z.&,ݎc#L*5?$f>:b9۱ !0{*It mL\M rx,8BB_15XQfb4RZkW)-ЋB6FLSNjA"ZKc3:FcυW;,a_!g:DYr^^4"#(L6/RyCY {h?H/pڵc?zXD~۾R*Z"jA({WC>(Fv `qH ~B/EС\wxgyeDy}y Ju &v?&9 c|ahy։%q7I 1t=8MJ)d,r[;'^bEp6\hi@tĔ=M~9?2yFy"l/kt?Au8R_)lBYjlZΟH݄<5XP`y`'jbG|zfcï#mIT(<=]7ݲ{{9~!?TrJ=Haeby3` E,_b7oΉ1J`pue= wgo -VXHW6bg=(ocp~;` •,^PJs@njd5?puUG8[, ' /{ (Vo5gRtS:)@ SmtNO46vܶj2T>IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/irc-notinroster.png000066400000000000000000000031061345766322700264340ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME %CsIDATXWmo~Ν^Bx)m) `^BB?RHUARժB`xIL^;3;3s0ٗOi{9395hѣGv/mw:5]\s=p!0cy1 x/Uſ 803痹J~E82DaXpjmt՗_sJ)fv?5Le ! @UĒ㵚/0D, "B Rq2p0wV$d5`f@Lza r1̹" $){J\Ϲ'ޫ㸛Rzr/ET7jb;{BgiXɀ0\,]F' r.mnf֋wٶOZ {6{Xz`cc}'x6CxN%ЎV0==]SD#hݟp[s~XET`7׌MM`euV "Da8.^++XY]銙@d}7 %,r1yw+D}_APᣅͧ}^3p$?||-CEĘP/οf{Ǒo=i88?rUF$BM`)4$ W*{Fg fr hpqj Ў*b\hXa$ l_Cg}7;NVǵUz4% G!Ib2q @lms}hk!A!Iŀ$̣e(RG } Rf[ fHu"\zpY;{Q jZ'$ ~`W*3PjWf$q RދEG#B!I n СDBX) P$1PRKv$IUF~[o?rN}y[Պ&''i¹mnnf3aO'K_^>ߓ-cuoϣwZX][?p KXX_OMG;RWEç^]IH5h1HlrmhN4 =wyFߏHi+IDpfy= ]0 "QvJWR>b[ѫkk^g1!ŋE|..,T&w,9{ H kqZR*`_ nłݮ2@h@fev7@R!+"#A雦K^k]K8p@3F%G7oo@nq2Qιs85[yȚ?0:w*ȃIN^$^8:jgIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/irc-offline.png000066400000000000000000000031071345766322700254710ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_2IDATXV;o\ι]T$*Ma `)G,ƐriT8m( %]$\HȊ,Zܽ{3礸w4`pwfsf\M[qb‹`O¯,c7oD<{b Hy=RQN۲3CP#cbg&r|"3O8QK1=6H`ل*1AZ^{:'IQ` *%@==;:}-|m@DÏ|_xUNW|ޟgl%`w{c^'ei ҟ ?MwMh^rZ -D14KgElDk& aN#@(=FĹ҂ ̄8UEGuVE,&"Z L 3&V.08 Wd$IU $x6֝ @&B$Q'D>sBa.soNHI7MHDH$z |XkkY2;>zVEʪ $~kׄn4|民AۭD[o (-q,KZ$u}\rB-z0*ɪZdZTk!úlIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/irc-online.png000066400000000000000000000030751345766322700253370ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_2IDATXWKٝ٧{!m9"\!AL…)("R^8eOL"E(CR"@K$RHhGxXB^zUC?fggT鿾U=y^'N,VNZ_{GI05H<~pq.i6FZ)?vaNTgvl@c17pX ]9ә3 m`XRn8$&<.FrܗKCG$Nam'*@ydYOb<PWO+"ԍxXZZЮ `q}A@"@3/oy }$)?Ѝ,Qw.Ɂ , RK }PB:#kf. 09 Ih"E>2RfVg^Rl#!HV'" n,vBMY|1t9ro\XhXh "| 1o_aXJzE ("-S~/e'7Xc߸"(m^TXkч)Å7މW/8O{wt["lRll}v +$JrnWdGNZDA9^1,r| +'\cEpi=\G! ._bL zQ@L~?u p*@Dp˾i|GW:/މD4 -[oTkSxkȩV}%vS8 xVzWrG`ᵕ3/Eg?adhDUEmWh!uDD0> T3pF6+`jQ 2 5.̀3C&1 m2YrwmqG6v~ XK݁;&鉍chG` pziF ' \Ll9̷Xs"bMY5 ]+H:G,k ZC`A`uԖEk|kNJ/-a??mnKK}ʅ 2X8I l=\* ^yNBQc_oWc܊4[kX?ǰFȴsXMCaݵN&Uk :L&J}P<)6 _-dBSbc P>@*mm4&Tt(yz]IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-away.png000066400000000000000000000042221345766322700263240ustar00rootroot00000000000000PNG  IHDR;0tIME8lѻbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ P.. PybQ1m|j&L'It E4(jElD $$AȧZuU^ ,fy{ĔIZJxg== sԇXU--7c oTŔbży7l0e/bԬ]k^1mo}FFjj_~hOE"}eU{iܵsk@:bWlnS,"p5E&&OSbe^9kVpmPWK%2;;//h2[[kQ'\]}KFL&G4`ggtˑ#MU*<";cz |ظ{ɰRxy=%eX \^bmݬ;lpwy91,z%HEUC]zdFHC}hcxDxI:NWQ*ŀb>g_wP'j5ctjr(r'v>_fԖ`?Fx(+Pݽ3;!<2(sMP>ll6Pfuq\`>Ub&m|ڴώcpm7_?FzĬRjΉ8>֘"<^?g wȼ; r?Vxt˜4xxa([l YYY0 B۠?|72tZjyhyEq-ӹ0t[=<ޓԱXzu=*$Yرc֭[pkk+"""PXXeP1Y ' Y݋=ӫfѣbYRHGy-*YONX&BLEؾ};v9?!!~~~Bwg'_|@ Ԋˠ4WzxRڎ}$:А鎪wglٲGWW:::Pq-i6@5\NV[hO2U.YbKK iU2/NqQ~ T*'I;thkk,z9QE > u$;!9nVo-*"$k U2RSS!jsѕ"sv_Qt^J,R/n`3I[ @#v^V Fܯy&e"#5;ȫM.]5 H 4yu3DK\*rX[:(rPy> n˛3ܱt HHoʦLQ_D紀r=tt=Wǽ5Ҩʃh ͷ6x$5tP%d/3\\&}٤IQfSӕ A f5,C}lcƴemY. ڮ|見4J3uԍHwܸמ<9W_~~ܹ3}}n1Rntw3kGBq]{NYAcIw"nZPf[j ꨑô4樨2kY8˫dӧIDM,5*B>suɚOGxIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-chat.png000066400000000000000000000034531345766322700263070ustar00rootroot00000000000000PNG  IHDR;0tIME" ;DlPbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ PTe.,i@TAsDKGFJI@D"y2 -t&م݅!./"$;F>;sf}wxլ^t9"QRBB'*vwOV{ym( ZX6q+KxUhdj\Tڠ y<,T7dJ utrϿ566L%U|ͅBaeMSn̘ث11~K [N3_݃KG𤏻 NjWWgZ?Eh# vݸqwX;dJ-U<`qisRԂm!!o}ŋ˂ߧUS )rv*à huqqG<<*r޳($y3)6fQ;N`3Vp̏,/wr@`c8>.!ZO c͎,gy=GKB`3UA7D l4l3lolϐ#Kߣ,cσ)s |T/85p.je;"YC!KraI,Id.Q\_'p ̾ XF5d3Kvj` (ۨ |d]}rE},~`t%)ziX:DzyBvh\* (SF֖>74[|%tr }u)ƁVp{,#|>cTy J7aBuT<:k},z!m056Ć3{{K%rz$,+ \HHgx#M,{,䋀@p+L]a 󟓁N7@ʡkKNv4ޛeG:s߸kC1ە7(F&ztq~ky8 ;򳑜a;,Xuj0zCKclDBSMPxu~묇g { GюZQ\u=\D|F ܉GG*Ͻ+M&AZMR7$2suT@C4oa$R?LZP^-nwcDr2tzvTɓ_%ngn[;I (ݮ2ezmqaUI6V9Zcjv~)J*WS95kָ>,q6.Ύ %.xGH`" T9>%+%0씠pU[ ]"*Vh$ک \^;t:)܂ǁ\/P3pIۧ@t+=PLkt?ȇ~ÈP43ix[ Ge8-ϥC?YBSem% ]ԃP/4$HsM9AsznIW&邂F]=zv^@ %[JGp]9sROSi?nA?q۶mn!ÐIKGErn"xG<)/vnIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-dnd.png000066400000000000000000000033731345766322700261360ustar00rootroot00000000000000PNG  IHDR;0tIME.%+ZHbKGD pHYs  ~tEXtCommentCreated with The GIMPd%n_IDATHǽ LSW{*[T@y D\f4@2(,Ǩ#IBL榉*LD&$ĹatQK q(e+2pY9ߖL 7{wl;}hrWSDA/l"$oQ,"ESϒCHn6ҥ^hM J%VUYė: 6=b'4ǙϼDy'9NP1 ؈Sbn䷷;1BFKKgRFkkݱ" 0Z^hQPkMȪȩuñw)""@{oE"Z*tJF-(`tpUQafaOח8jKX9p)2rO]UI *H]Ѥ$Fss변L&P6uwxև̢ƗBcv."Yz?Ph2:cff2j0 Ԥ׳(3* ee}~}ñc UdzKZ љ3ȨeۇVj]`z0 >)P$uEP& cZ<P%8x(tcӐhFs`OEC-_nzfYǧ˫ ~l;w/afM2>LMsŗ`}*љ3{R:spH|J>vF{{??+F044t -6]7;7͚۹ Kpnn yS? t/IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-error.png000066400000000000000000000031561345766322700265210ustar00rootroot00000000000000PNG  IHDR szzgAMA7%IDATXíyLUGhp<1(5`2"D$Irv+W;G&MÒk0}nwy׮L2AqnL['FlA"τ5 HLO9s.__ !A}R<`VUB!!@|<cFv?i63̮ٺI|gg;=(-hvq:2giS7k䆈Wã ;aa@ddN0m к5޶ldG 7[!WE+Æi.]?? 0 6''cH\eFV8x>`4H "w)u72=uuI5ZoDž z'00]s7d 㬮 bB`Zq!̒L,r\\~%F8|HADFV(|aBq>ٹsnDllKW DtO]M36\,_˂2,]WWomV{Yu2(IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-event.png000066400000000000000000000021511345766322700265030ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<IDATXoU?tJ)RB xI"0gN3??)%33|~ 0[ۘ%ɔmU,F29O8&LR|=; >9g?ennWffD#,,k9@;;;Ct(J&jDGt2,7z{8u$B[yp#v{.dpϏպiH$܎PQQAW<L/fg 4xtc G&S]zXlDJ<`]`]p)vq$ 0>gtlh$cel6T !$^ {Ŋ[I.W%iahxZ(P q<[̱N'@m9>Ϗp!'P?<tz JD|r"QD;^-%{Aլsy ;Bm655uSx JV~ 䱡-U^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-invisible.png000066400000000000000000000036361345766322700273570ustar00rootroot00000000000000PNG  IHDR;0tIME$dbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ LTWEAQتQ,2e@H%b( T@ֺJ@ ̀,ʢ ʾZO}ƭ(7?FU3hى 6WoQp0k36bCjAss'٬Ypqn2a*D{ n>zToT)SI,7U8'5FD;L干ɓǨ|a=o4mDcTbn@`/ \O/yH,-cKԆ ~BBDZfk{X;z9$n3ɍ4OY蠿Gn9)%S$aou9CHQw̜9svjݷol۶ 6l+W:u[[[옯䨑~= |V+9MñBQUc_3À(^BBBijjjٳg!..<7nTl2f9fDNحG6r5Θ)!eA'`y!4)O#>}c BSS4440'OH${]IΤ WdhDOGH,*z.W U-'mabp8|>.<88O>:ec椿í}%;oaq5 Jh'<ʬ y/TD"aBTTT@ݻ/ n  B]o>=Q>Z%rGUիV! t^#yI=@TJ>TTXX)HKːI!!M8Tɶ bb>> p}kU… ;.f"8pT9ߟS$aXDc͙c{1Sp yIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-muc-active.png000066400000000000000000000020331345766322700274160ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-muc-inactive.png000066400000000000000000000017761345766322700277620ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# # (8&Z PE*QqT!BKE!XTQ4MQdQ@SA*.gjj]Xl˼y}B8Zbc g*LLꜜ$C8j s A S&ǸuOajZZZf =U;)mlv7z{Onݧ-^,{xǻUA~rGp+X3'Lݎ6ʸqQ^#;@ ? ?C ƆܢZj}V\I۲p#`Y܁jH"&& pA,xx^DU!J݄Pw(-,kQd]e#o4-0F ;Xt ;bXv5w=>N2CaamI?1PdZ(0ylb4.d]*Ӧ? |~+=dC3Jm++Cl\2}(--YX% \YDBJ$dLV!?';t#e :4SfL݇tLP%uRKbG+)!Rї+e>bk8z&ǐ4hiLwRR(LEy:3yB@H@GK3]8+M hkP(ر%HO6w*cViɘXh98RBȖ.ggJ[Y*/ٳ/A;~wĜ]s[PS#ͣ:O7.kk"¢'e)䂻;@~>@a!UpYSSf)}4Syxչz6Ûc{'@ |9 S*< ̠l-ݶkN݄ ׊>?aD;w¼y̚T1/s8F7>h2VKv!,ccAQOťW̟ tZ9f̷x4c}zˠH5#s#0P}uƌiUzz.h- ,s_>ugLgEo|mIUcS@im]- Dh.N4X(+_(,ŋbc󪺪?t{yA@PMEnYiI (ixV2gPнj۶.~[,Y76njg1VǩS; `9z-@]`,#G!&=$֭?;`TO.韯ž,jmqZ^ `vǡq͚N{kg/SSWɤI dDk`GY9.bAK1_㽏m{ͣqڷGر_&%̜ 7s(]138fh[Sg2SD˭UQ Q9{7c#_KM|354B|~q6ʹx-5j}`y!*^cRIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-offline.png000066400000000000000000000025161345766322700270110ustar00rootroot00000000000000PNG  IHDR;0tIME 0.|7,<bKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ}Lu;w&@)B$¡h B4|ej f/?GJܒw{3<,hƳ}>W$|V|2g#bWupT!WTT;Kx&_{tKW$nh|8"gIUڛ3m7}&}\xR!|3LyՄV+cm%aIG"bi-&/i<򺤰逳gǔlU*udq 5^bɰkr,ݞK'fcԬ]1_]liIjLʌZ@s]=X['`?RML,JmTmJyY[V]f`Gh':Jp/G((!v mdR}GL]ӃU5o1qPVy6M" ;-T{]Vo'5**ڏ;Į\6=u}Xkx^K⨈[rA:,X3˜s#qC(]tc!;p~F.#g@RI2_'Cb:Pǭc[CԪADdd_&~b ~K?_0mkG[)X3 $3ʠ7O1 R:9cb}+1G抝ӝ7{y,O ,MD9瘹//"kŀ)[?A|B^kIڽN(1W^$w6G7tQn IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-online.png000066400000000000000000000026071345766322700266540ustar00rootroot00000000000000PNG  IHDR;0tIME iebKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ Lg{-m) ! eLe \1Pl\9F&NYl&[2&oK\)&+7ֶPvήJfHHrhϭTkdVw޾Sh{;^.wH8vlm]7W!?H--zJd^x1^oV ܷys{ Jn(d66!n >? mJ*+M+3{LLtq`K^8~3xt^A@8{NK{-,& r9m"7wHx>'wrjSSk!l M"#G}0s,Feil>e=ɩJL=5LZATEFU RPHh[|( O8v@&3SxqK.;ߟjkʀS9U,J8fz <|߶F CKmlzXZnL5 e2e0*7j-/7MJ̴0cb"$\Fx>;C#Cu-ںQҩ CW*qni[z5}^^x DDrD2B\J61u3P/jm?Ot:k#7~=n"k6e@]^=DCM驀.K=ܾp V쐘ECxEǤx;8CD~s0`mI*(^CG/-(X\WfURRU!!~~UCC `FGap 5w۹7WD8 oo#*>_u=Je5IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-requested.png000066400000000000000000000034461345766322700273730ustar00rootroot00000000000000PNG  IHDR;0tIME 2 f?bKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽyLg-H[KP.K0 CE%NELă( (l x fD3,% NE]W Ø&Oھyz9MçJf} ,_C9#Xx/a3riZD>b,%VM"3HnE=cb E+5qȳ0?6)`9&0Ldjm_ qkb ,[k5ksw5 8LÛ<#)p9~J\uY?MP蹅s7 L!m,ںZ1;*=. nAΡpEoW@biyh;}b.!I_2< ?9.9˹R\{>,oB{8xЬF1"C\ èi8oEq6~&X 0! >s%_(>9|J?tֺL}P6u!ފNPAco{dNnR"{LVr%SpY,\T '0v sXG5*SW쉶wOT>H%wz×)bǏwu p7|g>)@*P`U!}?gx҃W+E-ҽHjAdwkTX=&/Pnn]\6Yp$_ї( WqO+;;bffHvt|՚= ?ǯ9C; I5q:>.>Q\:+<U;,jѬիĦLяa4,"zb0nG$1VފYG@z뉇P MH*b.N"qF܃e1_#}h}Nlfz>-oZ8!G(dA2;cɘۄ5rqipS*J7eFIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/jabberbulb-xa.png000066400000000000000000000036711345766322700260020ustar00rootroot00000000000000PNG  IHDR;0tIME &FvGbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ Ts$r QvT(MyN:=vC7q2tCStډB aBԲ$$($AIp=XYa;~<'s{C)|^&>d_zz#eH1ՂKMܷlْ\qlƮWJr+?|gjUR ڴt ۥ ^^D~p>E 2&ssO@`&&3w7en*$$MdI\Y^#;_jJ>{-&gSΛyԽ:N.ޟa>76Za ocZ01fXm(ړуw^^T&垳g7|~!H*iɄ7I)J*YD̓rr_ )czX}u7G`SP貲s:wd]GQ(Ь%;˦QxzaWw=ʠ4r@Gf-}W(0FȆ0d $2 5d4n)R1!x)^dvɸB"(HU}[E_P.^:O&6vlzK9z4tڡs(5;vv;$mgבө TD>r_CiSR2EYǧO'6^j:QqR tЪuBAv)Y4voH9iL kޔsBp N,o L>ck1jT mwBmt ;Bn|ao8 j&1TcúʔN&aJ?\4JŔꁙ Tת@kjj'$XP&$T< |Qo[q#2ئ@o!fO`4 Ϛ1Zw [h>s{\,fܴ{5k|bBF8&ab 9dX u-|(I$N4tXQNVGFJFmK.G x#U?F=m.p#15p 3kSnYD&Q7[)~VLqv2`_֍"m~Ǭ&ڦ{zj?@v*.(diki.*b,bw x7jHŷH0fv>*P&t)T(*[wjJ7pDABї\k cʦ2BU`x ?6Z+pD?BDGʼn k4re20Px' jOQWZЦnņ(pA: GnPvkU,cGV. smҥ }ZK;}ӹt^ͳF?.i7L]IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/mrim-away.png000066400000000000000000000050461345766322700252030ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME ѸtEXtCommentCreated with GIMPW IDATXŗ{pT?ܻlvM%!8-c Chkә:V-GkN+ZGZy@0%r7}{NĀhG?{WXs_EZޓ%G*cN^2)J ף+y AV B ;uشوәV5%\eߤД{zp2MsŖޓ7q,U *XWcm,Bu#[-;.⑚I SlӐv!>B&N9)<'vR=q'F   pyn3[s{Z`kvi< S~j@D vf_ W&ӣeםw7jQhEF F߉E8dK۬^/[XÆ(ӥ]LaWkŽWedfm%WXV;yET66w\c6+b`ɥǺjτǨ<6 i>;?%? J&M`͚5Y}us rJ)Rz$ &!*%Q߰^ <Uu6/|lj ~Y7rSo[qj/[EKWTUUM1RhBm۶{LZGTA"|_\0)Nv_CvX`E.~-uuubCky@+94)OH$o^剭[& TG |,&S)X9۞8e~sTy*f}/['+++,_|խ(/+-@))VJ1}Zwgmj^LSXyh2J!aZA)JAƅ~z^:X;-S&WT PJ5 9pR",Zr%{{~pvHgTϩ40o^ 27'|04G,;f͚U slO#2 >g{*++ ?IRRH..p=L_K+Ep]W_!,Bzj '>Ϭhe{D|*tzcq']ԺJyR)%T$iǩ+J˪.a띾G&]h{^1~aA]IƅK LJ [#Zs0 -P7˦!{p=FmlLRZo+!JJ! eiؽ t?++]rth$?n/As2C4$t َ)4Fh8CZK\ߘh Nnӳ~/ftQZR@pR`T[080|)7ߞ5R 6ΰP+ĩZ`&zhCn#f1!!`hOglޗ,x퐕X8͙_ZL)oHO:rkYVH+%FA01O)%8~/j"9nmI>1d>r͗rxXcfPJɳ D7l[&e B9~-: :;m:ݬYLH]V!J|&lٕTTNk RJ48Nwy^}l_K+ (s|['cibS$wn̮͆uW{SWQL߄b捩:7+XUgWUM<C8OTdxlJT||jKqq)3g%drmx79RjV7&IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/mrim-chat.png000066400000000000000000000045071345766322700251620ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 52PCOtEXtCommentCreated with GIMPWIDATXÕkl߼360\LpIKMKCIMChj*m*UQWRRmwRU$EMM@@067cga6Jϗ}ΉO ⨈V"1|(EMB}[o56jPW$hʀ~q &P]@~@=6{GV5*ykN(gƨ^s/o'E }`1TzUlo`}3M #&1gBg2XRZm.#.Z OzWe}Vȁ5Ye*Kn%n"p VXSAPsrLˑ(Qυ KЌ|TY!H jVLTr Trac"+~zKo؛YKڇ3/\{Я;:q dEޮXx+Σ7݌#d+n/!H 7ߵcG7ùta M|T6y; w=ozB}UOHKa;s0.+j%dө_pnVU0`چ s>(,OX}5Փ/~}6{_F~%#njt(A7=WZx.`VK&̕jn1B֘rԲVgmZc;>VmKsCa0=}S>~/'}ܺ= b!jf][e*6Lki\] fAJnJAF R8j3k=Gu;Ѩ9}j+#UKI;-3Ufi6쪊59HU¢M-Mܨ*>y;zaaTn3o\w>(K9 GIC7FtGP JJsҬxWu),LJUJI\GJUQ[-5(6CZ4BV+СjTiu|rqL"6fx('i@"S*NAaWtW%Eʼn_?/73ƕbRJd9鬣9c؀Mkj OIIWN oό64bPxw~GTҫOZ UGTQmV q񮟧y0mڅuiùm^{uDWǸ+3ΞuqcnPflz+F 4jWllժFL{kuxR'r[Y7FmڷGO3=sp?n+f5j% 8 `ʘ hQ/6WhY"YۨZPʈs~&FG9}7>5卹iyI-ԕ󸸴juZHL韰p:.6'Hu@#}zp?~ˏ )s4K Gv;5jP%a[l6U,WJ3tO=C7<\hX`6إ&Y+e,b)4 H4S{2)dXl%FZ(˻iȈ!E7sfȗ'EIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/mrim-dnd.png000066400000000000000000000043001345766322700247770ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5/3EtEXtCommentCreated with GIMPWIDATXÍi]}9.s=gkec>6Mn4jLk ̽_C_Q)~Rj=umqvyE6A&e#a>8nz܄|5벴 x(NA0):KqMn)nP$ԮM9Ю`xޠݎ l,OpĐgl=6)e$QW|CLI6r9-cݨA\Bzi|Lk ~yie'ku^[>l>2q_N_.f?aQ}ZB-,pA Ƴwlަ[ٵ}d䞠VovG/ ?sVyi2#Y3UU~qW\|+?mr嚤VԪZ-jݵyq;ϸ]6cCIr& G<.jo]_0Kθ\Qըդ&4Uv]T=kTBTL_6,Ujȯ,V>'ZV?WZMR)Nd-D-DivuZgEH=cQ}Kh,XpjU:=}z>5%Tj5R\3찳,HwǼk-B4i՟*cOac)IKqE4q6OcD2rAkOhK.Qs'#DV=Y윽~af+2)β6њzsɒo~SiJd+s/ܱCR°YCyBtV{];m)aJJUA|^T,;(+DA D1IJUa^p/M"h՟y g}GS¸ƥ,$//!M6'nLA "~/LgyqQ u.O,OH_zO~e-Fn.OX9}ė"5$T AUQSJ:Es&NYz˛vyۮ+7YTĉ qL=dC}.c!Eёr%c ZfmsMzh4OUaf͝s0E?i8-OT]vEK,Erqͽwߚ{ui zŻ瞬׿7&;Īߔڴ5HY%TǞei[}1ROEsDBa3W$+D%qқ*sڮlB[%ANMd"g }??T8^\htXe[uI> RApPh8xq`NF~Bv-Yl1 ̋XF\,PIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/mrim-notinroster.png000066400000000000000000000051111345766322700266210ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5-KtEXtCommentCreated with GIMPW IDATXÝW]lWήwmc;vqB$V >xB! R!HHJ< x DvvYkǻٙ\JH%!)TE4BTZ}{f)8$_">GSԐii Aqs]W:WVW ?_ # 5yoNOO?3885H{}nrR\.ޏ3O8Ǐڌ1qujj8qH)B@0 N$GRC/WՍ V#ONN>;;; c Bpxb޺u\X*PID t:d2GXTUel$P=66:vWOڷo߀DZ&/_p? B`@55MrO=4Mslll1Bw)e18d@;%j:w.gihf[J {?D$jy7~<[ bι}Db$LH)#z9Bpt*Wa PUuib2ƀ644t|fff4Mpl6qܹgΜyU@1Mssw~kTHV|Z&H)q6^vگDMT* UUB ,155l6}Bܞ뺷(L3Gyqbb ˲T)]Y9SjZ4-9_y+eBq0N3LӴ#!q?y1Oq9@7*J@k~R0ƺm> Ovww "AT*3xnԾ/JjZ )H$1p!@SFnS.%"Pt]kV< R*ώaeŭײlBppΫKRJ)r)"@aTιzM98X<7 YVKKt89* dX]FDʇCJIHH);!$P`iIFJV > "\p. !D%أ4Mhg-!C⿒ݪuzjJZaЎyq\;xs8E`D/Cؖe%g/VN|Ȁ8`=z,ÃKKF#@, +j^M?n&N?6<jLJ)]׽VպRԓ""FD^ټl6/xw5X711ҡCe"}T+եZ7[V@nR5 ǢퟗJ;YIr$&#Hw܎?Ni2I!cEIgX2<|:n,eM !lookO cSSS?}&1ou[|oH)el Y>I;8\lX|>(p'@\.Ϲne ۣi435MD"4Mۥ.UUTU`I)sO_U;_.8:%.H !Έs_t]8ǹy<@c2Ms*N?l!]$Y $I ~[.{q˜uN_ct:=adzBQMy vqw{ZgPPɂIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/mrim-offline.png000066400000000000000000000045421345766322700256640ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME $\*tEXtCommentCreated with GIMPWIDATXÕW[$UϭꜪ鞞]fݰ\D@($F O>*hxD#A j J\]`wbzz:?B<\@[PPGq?vЋ4LB0 / p* k-Z,Jlv3q/8t:q|_Eyw 4" k?|1js)<vB@ 0s(ޭEa!B]iOi68ovq|y*^Jb(uB(tt !|5N`Q0`!jE7SJ67h!CnN$w԰( di!˲Ӎ]!ĵ(PAzsUU4M 8x6\K|!D\NYkRTYeyss1ƄUUJM0ZHƏ,{ c}]OjɭzΝaSEQL]z !竪*&F!Z8w5xaҀ^h+vFt}.]{PJzS(Ly&<[7)Y7_;nC;OЎ!@z7l0.5P39ȚGY A`cVU0-X좃 l۟_p4RB_BR<_ @YU)91v %Rwzy>Bheaa8yC`XXZZ|RJ!$ ,˓EQL8K8KEQeى(nqPy!k9s_0 ZKuzʲ<=~ [dVA|* Uf֟R#BHKqc:$kqίMt:}b0<EMZ+c0N l6{])u!+UUlmk-E1fO _8hzcf n)'Z3D!dNpxDk-cK1EL& #8NI89LBoZ-rc  fYc>|>>I3y?KTEQ(b-WMTUB95t7!|>5I?$I^RiǔRnn$I&jc`:]ZZ!axo$ϦiJQ礔)BiB) }_q7y"JpAGrY[Q^^A9)RjZԢZBBhvsQI$8YRt_pn1y^1)J.$T4<۹Y͡,ˎefƘPv6G1J)YfOO&'g)kCe'Ir4Mca^_y*t !LjFk=RSU,ײ,{(sH?JkF$I!a-yw8P)UU 13vbd{: @IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/mrim-online.png000066400000000000000000000036511345766322700255260ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5*C/4tEXtCommentCreated with GIMPWIDATXÝklyimWhPaW@"t (sٌfn/louqdo\2w˲%Menܔ@(r-PNyOSd!7[K>r>ORF:ziW\UQB&dbg~dͰ=# .eMXe"眔 둏x7VHVjTu9q봛5yAoM6D*Qzȋy )* ^J kc]2rrs[ tcqVpֱ~慨\Q@>M/r;.٩Hd!ΡBU^ˣcF=c/w+9TFk⛱IKiФ8FCF blHJXy F V4]Ā~ݺjwY'u؉CN:hVj7_-Bף7x` PwY1Ӕa1|*<AoxG )ԡK:BLb%:v~5rʔYۦiWh 1@Hɘo6,jcpşf3j[UR)IzۀnSThRe*4ZdvSUwR-n2ͦ^x6E&NզkR6J22#u0 LcLJ5rG 灂n5l3$V\#أa;eVL!"Yvx2MGhTz o~%H£S*b X i >Gm:5gL3S(0jX~|@{L ѥVɫ:S4ČOÑKdPJ f[mV3`PA6 xhEjRB  dUHtjue}u֪uKNy*eO}jX}  rUTLp{~{*I ϋ'eUCjJLSZݤ d% HOTQސ ꘝ(V"+( ]!,j6B9e?x3v8(;U톉h 6BVhXfUjLH5^u.'aS>5lǗ7dJQ\:uH #/&圓s#~{IIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/mrim-xa.png000066400000000000000000000046511345766322700246530ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5)&etEXtCommentCreated with GIMPW IDATXÕ{T?;3wv^;s},A+ [4 JEkLh҇iW_M#5IMhZkm5R <ecq=;$wwNX aP{JBH 0?ݡ,#RzGnM?}+ZUm*̉ VF [ǎ#,%0*OF~ɉEs"|sqes4]bLTrPB+D/QUͧY}UP*k2E95I-ZzI @ ທQ׺G3S6 : t_-a[~(31 (HқB!D/ܚdKM[xeA:IT*q<̥yv=lY@_,rb\5T)A7:I)yE0ɮQ40 E C%],9  M6S9h qn4F~d*!6t,! Ďu5<zGK .QIp۪Et Aiefb&65 QAfuM_Eܼ(iBAn qkI&ޟsv© ZdS3l4F-Xfe _,! a)g9)%ӎ.1,6 'LBlpswhD XDPjZM6{G ٠72Áj/ePflfgkʅB'[!30U .V("1h iQMRWyaJz{dJ|P1m Ai!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sms-chat.png000066400000000000000000000026121345766322700250130ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+,IDATXŗOWsfԪ"1ZP6mcFmĤlOЦDO6`/h҅xaAA233j&'l3; sB>i!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sms-dnd.png000066400000000000000000000030371345766322700246430ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME %e6IDATXŗo?m#[6Ʊ ^ j(m" iDKyJ!JQDT)j+ ڄP!P٦Z zۇ7٥HW39{>眙{gl 8. a=A4k,i)bQJ՚IuGLt:}{-;rݻimicqib&H)@xO\bn~ޚǤ;w_[6` h~_XVb֚ ZFP(R ['\>L*~`_ƾ`_nx=ώ ДlrqV"(,ǧlbE#uBFQ,JG٪\ ?kbƲ+-[yJ[[a!ETr= `EK:[d\|`]+/wg@JG#/r5.6fޟl_km\',=֐ 4{w7B 03pjR!"SƦW %]]]ܼy2>>C윳s LjFcBQAT&ҳwouBuX#ӧYG6ݵҝ9oىiЅtsFF.s~"NJa`fHk2s9Le[*E뫯"kaoOx7t,333LOOb>{}immǿJ).^ȅ fh ZW4M9#&''q]P(Oɧf[x㵟2<0o_MUĻb?_`ttq>|j լRhσUo=XS׫@8do.T׷@D.]¶j3WN$ۋaC "ׯ|>W)o+x%|@ Й T @Df)^ fb(C+?#@|a(!-gΰ交DZLs'W)&&--&RJJӿ}gO*y;DD"4 B˭؎C  "wwy$IH&ic)+`%90P\)Fu,d{/%g!qm84B BJDB!p8L4f۶&p֬7)e 1ŕoMMM-@P!7J-  JIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sms-offline.png000066400000000000000000000025721345766322700255230ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+IDATXŗk\E&1&k(MZ)h*~RADPQx#ZJb Ej**/$ ۸4ٴI~b7&mҐ Ùy}73gMܹ3jڎ QJm/G䅔+ c+ʕ(y/X YSP#?,j~HR} . RѣU+/V&gRu<E\y?l)z, Bu+o'gx~qq.sn7^+_}yv]'N|&p!Ri3VGJ.}/JT|J ǷPx$2;;å˗8:L&B`azz=ׇ5붡ve|<˱7an] !ٿ'(ʴěAhPxj?]+\}R<ٿ+cW|=lƶ%Ν3~킕Tt:R 9tT'O? QJ@ZkN:{96R@kףc[oK1|)~:9{imu릠۶ Ðr9gѱqZ1a*_=J[[333LNN`+099ִ69\0Ԡz2nݚgbbTj'0Ơb׮]ضMdY4>۷$-\T*ٹ1R 5\.kY5k-ӳtuepSJ58Cur$0??ϵkR)DcRdhA֫biF<ފ6SS$ej---xGPBkm+˲B`Y_N$ 344D̍MMg)F5x)ql,BZV&dAi)!1˅%}*PRsŚR$GsLHĘv6T Pq-J!W_ZZB@@EQNL-fj-5vP[IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sms-online.png000066400000000000000000000026121345766322700253600ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+,IDATXŗOWsfԪ"1ZP6mcFmĤlOЦDO6`/h҅xaAA233j&'l3; sB>i!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sms-xa.png000066400000000000000000000026121345766322700245040ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+,IDATXŗOWsfԪ"1ZP6mcFmĤlOЦDO6`/h҅xaAA233j&'l3; sB>i!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-away.png000066400000000000000000000041071345766322700250410ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATXUǿ̼yov..]^aYRm6iP~1D-Fb(4 FI$[ E$)6v_k`fAg-]Hf9s}k-.Įk|(cL|?zԴ:hMyl&z}_7H# #gHX8T7ĉ닸n߬o\gO[ƳSjZ;+BJVq3LKn >q܇F:X2V{P# 5V{ÎI7'R7wq߈'Zظ#;ss?Z.w? ΈF*XH.q.C<{7,n8n؟7–%wG@4zӭ􅭪?-_^~n #*am>v=l9y:M#9-@sCn `d3yէ`j`LaMT ZѦ1Dfg}fF}S6.n'OladcFЬ?BGΝ%' ˏRtqίBݫA@mfnϾ1LN0;E0;`3eavqE.][]R B(}^szLa_pp;;Imӯ[iFTcSq$Zvxi s~Xka#Zuo=+aq.[M{`ttt7c쪎JA@k5!@./6k{9sʜPSE1 {ry'}M1:=σyclFp91(93 [JiJ)aaӡ }8Zj!"XkJ%Bt2}/`Lvscju7t]wI3I)58Ngsf4\bKK@)M3NܑR>H10 ""q(`PFB(HI2g+B)cl-oJ)ri6IfqCk 510ƤPڴTY*qTUy^*qBq]w}Bspg8NesqV* `pRBHBR_9()eBFVƘR^hZh6Ks̙IR3L9.؆ 9̀bKD^p~\xPc`!B7Sj g3~y.`;#@@N@kؽ]}8ƿ>XC_\_|Pd6l|P 0OxAP"+l!¤Gt+C4媮8* ʤrbL'g\cf dduTV~8N8! iPD#"Z!~ 5U)T(TU[)-** i vįڻ{sN?ݍM)I;>4 b5J|G cX)`80lCGodMq={"e@ bUsX7xhއi9ɷ6`4U9R2/_ީ^0F9Zc7 cs@L>ڛx ϯc04Ơa:y?W1rǥC.l0lIOMjFa"[,G}+; @~^$kבk)҆ьhMW,m%)k 4%Xx)-k@=QگuO?z?I@K DI}  ŀbJc"6Q ~[ZxY˓K>pxHxdhmjhB %HQ55Udp+PiRsH&Y%n[WUGqmB(5~xJaI@A|Eh#ScB Dهmn-մ4 *Gضqk[ڷ?*mݻ h[؜ %1/ f`,X֫p -CԵ* _Tģ6o&0Ip B=|&PM%akPS)0^f-nZPڑ4QGR[r?a (C4(06B]|4U{& L%@[rHUaIX@ǖ8ĶB LiSqMTaKpPhxifn]X)M5URH$b MYq%]h \);P@k|eg(KA h?E;oKM)&! 8aHsy;C |MWx@S 4 ST!Z$#̩.I\[\iY)h 5Ų$MQ,]PMs}#*y: 9DFu-X[gFˍI``2[ؒ]qTsذyuQ<_#q$%e6:T:0d~ec2Mz$3hVtk4ڬaP#5y͵9?c^S=KQ 0Zb8 a$a|M 8;2kbIs '%U ǽT~ɄKĖ!}>-x֣OH@c!%4D^XLYVG{SH>4X#xӲQ9G3LTRfŒ~624'&99Ǻ$+ aiēٷlDuKlٶ`p<7h:n5d MQT/kdz'cXRX$.ڒ6)~ _MTy=*{4zhg22Y`4S QǪLEJ@w-͉:a[?~z x'Pxtb/=m}vB 4Î{nceģ=6:yhZ N@8͚^DzjQE_39169ͩ}tyB#7,۞]z !Px{=ů. ϴgby`LB>{'ntg4'3IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-dnd.png000066400000000000000000000042341345766322700246460ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<.IDATXV[3^KްId@\PQ(Q"BܸBh /m*UQnJJ ڄ  \ͮ]{x3xityx}?CQer }}R 1::^9RJaxl>M)}T*3DJ۷_],_l*˲ @$8z苞}>O1<<| ch4RT*ge˖E^r%5M!RJ$IJ):>|s'IPJqo AQ̠^?^.8+m۶e2/_t`A4H)l40 Au$I::8Vrk5M Ik6ls `֭-AXD>O09mhZ`!IDQ9BC6a8-9pBQ!E7n4M80 s4M8J)6\ׅi0( E`*e|߇}}}PU5na\{Zց|>˲`t]m۩6<΂1 5VJ)z{{a6!i.'SJ`IH)AA` J)jZZR&$@. 2 TUE&A.KpΧ5 \ntRB 4 R UU*h4Jth48)Ia`ѢEhi^BǁR,YRm!4MK4 i""!p,,c,/Da@Ӵ(p]4(T*UU^0EQ1(*$eYP\.$I i8[QPJ1;;0 AADRA^Oq:RDR$$ز,q 9:jcm;5l6{[˲A0== 077 @) h]Ӊs(9 mu='Ŕ.4>)ݲ/XhN?/St:kߗzȏ`j0ANT~Oar.p/y3z`]bZE鼋~BZ0}5r0/CN̚; DJ@FңR8 [grV؊n;ހ?p~cr# YEa^(xgϥ8MXgڱ^J)%+?(+7_}țԞy Fw~s3NAs bR&;߭aS4дwH9S;]YK)O5ᡱe篼@/`S]9x 3s?wi>K⁁7@(v߭koQ$PWϻ8S%yOv{_|V$^zmF_~S~]%o2\IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-error.png000066400000000000000000000035151345766322700252330ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATXmPe-KA eL$mqJFNIJɀZ-N211:6uLD% "/L@KD>vhs9s#J)" 6 UVwȷWTGGl@y sr&k  SPd-/ 4$LKG R{Eug!VW(:YO J/BGZs]݁ * r"Q@Jj>y 4&<* 'ifBͧ>^ B A΂1b c/AȰ/1>y(#t]@9e5y*Y8N<Þ"3xLX(om$zio ǁv0xxDEE➘+©,Ҡo^ܶ308_h{5#|qu%( vglP?Mީj^uW63aǻb>J6SGq>pYH]Vήnsק뀁[oJ>.sXOo&رCn[_N f(cٵr[мX ZW*eBērϷt3qK~vہlLssg><Xl6@ dz :m>CzęKٸە=#7lbD)_V,IL$x~ԽW*b5 @D1ܮ(d<3ep/o#8h2_Ӏǀ#n;v*-> P|@lT},փr'Opqxx˜Yu;GߠW3>p]oCnc /9pXUiw/+v_d]xݾuY 1 y5.M)R/u[4w{^d9|E#j{5Řn`[ӪUE|Usi7"tRg+R M\3h\>qbc'֝OsYM hy? L]P[@bvӟn4nXևךHNN&66rȀ@ @P}ߘBXSՀΟlxw ^4y5kc8ׯYUJC|΅lbGL S'**S)SK?Q(3|::xm_gjvX> / jZ]5nqX~lIՄ$H@k&S^LRKfۑ_2 Uef/zzsr.9+ߘ lUJ!O`tJ)RB xI"0gN3??)%33|~ 0[ۘ%ɔmU,F29O8&LR|=; >9g?ennWffD#,,k9@;;;Ct(J&jDGt2,7z{8u$B[yp#v{.dpϏպiH$܎PQQAW<L/fg 4xtc G&S]zXlDJ<`]`]p)vq$ 0>gtlh$cel6T !$^ {Ŋ[I.W%iahxZ(P q<[̱N'@m9>Ϗp!'P?<tz JD|r"QD;^-%{Aլsy ;Bm655uSx JV~ 䱡-U^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-invisible.png000066400000000000000000000043561345766322700260720ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATX{pǿc_,yH@#E0H"ԡ>duL[ڱC} > q *MAL0 ynu&a bazf~3w%s\EW;qr@c]&!+0sOe08#C}خRyMX=/)aB惑5ә w~o 0gcr$@H[L]T\؄]/ `[b- @P-XmFzgcvjB+ĈL #m#=4FR/[&9L aCC;3o8c) 7~ku@ }R-z#u9 }n#`p ;g.YF曊[ 2p]&=uDoT> ,ԯ\S6m,ˋnHH&[~q\Iսa`w\nҢe&}rj"+7>iծy c+zu;gTs6̔3fT*\wBreY~R0& q~N(AYY)ƎCՏ9.Ѧ?yJh"[?k,$Zf1EIǦ+y7@iL%o/5BGa4+~V僔k@d! ] 74y>x*uǑS:aDOjD߿>I^٥ϲ]кZjsn媪e7n@l cM@8isM@>Kc* z@$9ä́ҼUV:u*پ}EAP S,!L$ErZtm"P 1c[k֬YEHP>pATX|$3u 1ɥ6zyW$woesPg%zs |4 9\ Q_<=gfdocA* ޷M./}ns;Es!dѾ!qJF9UҲI9rB%Jk$S27͹Df[E#ļ1&L#np=0ięדK(`` EW ߃N2oDQ$a#ʂÈ*0cfpX)Cݷ*"b »Ύ?0(;''#oT^48@79c{M5mԎأZk|Zf WrzcuI< "u? =CJ4@& MP|k V7{Z {=wo%J8(( BB?] ʙ[Ђqto-tM6x,)\z*>z}G7ͬD 2`EJo~ttL"+Y'/ QCEy0$7S'N%|@&24v[ N#I ' :}ZA'D]j|]p78{/JzKɳS"Ѯ"d@gТ ?%toI/ʁU6+)d9qVXhZkA߻}gd0͓_ o_ȁfc^ P&}9w:\vO\۷;ݯ@ 1TS@¬|fW]#ք*J`F3]9nkT-$]JDtLKPQz$# F]f$|]:jA ~ Y9 34pV=5g~J& W_ԴVm2+mذ϶7IgM/gs?mL={m}옮/Ca+okɆێ?K埭\q/Ue IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-muc-active.png000066400000000000000000000020331345766322700261310ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-muc-inactive.png000066400000000000000000000017761345766322700264750ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# #ȓ!˲"1R41 ") ]~u}Vb&{9s= 54Cq/dWoI ~1z@, V`ش);: 5Eg:|#1pbB H2p2κ 㼺};xF5L:;sOdW/4g6o3FhMŋ9s6oDs0s6}}J%?:ǀ3鬮$S@xAtxm\av5JH%Z0999_CL:xM?q6nHVXV (5riVu4M&&&818H0=Uu&־ ]SSöm44c(<<=Fk-+Z٠\ŰZ[iniX,2^czzr9p CyL:;#28@ƍQqib&ieYXisiE6HSt>T.$tˤG}yXU fP331~9(Hw#: ݺu}>a22:z=ݪFv|r9LN8{W.tvl8]Fp>wW?ɞ7`e*&pgHe!v(WXIW:::PR1ruy&{n_„*=%LN=K'. 0f+P_,d<IJ XVIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-offline.png000066400000000000000000000023161345766322700255220ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs::͘tEXtSoftwarewww.inkscape.org<KIDATXkLU߳3יeZQQ!ћPI(bE[6&i"1ioIJlhb1kj",6҅.{vew%|>眜3MpR;j M3zU(*$è$a`jv䕺tҫ5mj$d[}zMnuwX= ?dm9bJV .++_cROQPdeEJDZ1@B]{{1<DA0X<~]45CU9yz{ à X0N%2 PUnவ`1r($Q^VBث5:͵EwC L@Si,4MLq5P6mm^n6IFy a Y! , yg_ͥqlŅ[&qLgL`}.Y:ڨ\$(Bh.t]|^!\Ţ}ε>+EUBj3镘gRbakBDt&TB,Rs :`1cAQHbH7 O-+$ߺFxAu TaDf0?۝~.X @uVX06g XJ8(ڕRۭt1*#)yB؝{fF,!euK @Eu+߹N,OS'KtΩ7׿lTc Cf3qrM$G5uڞ6Db?BlWeoQ]cc#^ze)t/IB`1 ź@3SۯlbpZ<P5U^j)d5YN+ X<4^U1zd g:,7IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-online.png000066400000000000000000000043361345766322700253700ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<pIDATXW{pT}nn6<&4_v'ǽ6 F"ՠoE*4X|kF w&] Ή/iE4 I^o0%U*,=`;GRuH}xvχT֢GET^ϸnK%j~@̘.\#OmNQ"}nCn@V Y{ H&| ׵;벃ǪMmռn OI1W{N><_F紽gL:*l0 Y}/_;C[_껏kgY̸{L\*n.1>z؞uޱvWϣd5£m=e3 jyEM<\崽 u 63'<ވm(+ .{F0` S+ e%" u(VCDu=OAYs%|cYGvm7'Yl<3Wxt{@dd  吮q5ZBwi\y'lOyF8'u4a^]?gȹȑ|N0dO#vHk0MIɚ艾|?gqigc僇LY/gdn|ܨݯ ˉ9SQ"<͸<<֟ke, ~[fU=2d SnށErW> =Kfkv չ,~Ɋ֎4`qDI#)@z_͔इ:qƺ#s{DߪO7?l\qZoud2V =dLNm3OE-I 5 %p3ם!t Ac$Sox=1a)^b?( K#APY)S O#B7F] 0bVmVVG_V[!%5bvf$,4rlx Hg.9 !!A2xי hbS26 j>g"8똛3;וرNU:@RQ Y7DpajRhbm8џom>}_xS\v˚M$yP9RH^ۙFB,)Xxs>{?Y@/\û^W4TW4/?:MLN҉CZqH;AX1H;r 'r3"|YU|vO'Ǿ׸uZ^c!;ӠhEK T<"A$.ȏcqL:s0(@'I ~^\Yݐ+F<负{;U'swMj}J6S޳vs7AEq=Fv0kcgWgF.^^[cuиRD)< ),Q~yZuk}tb{{*߉) ڢkl{}*]u;̆6"?;&Z>S//u.^⛍?Ul7RTu6(gR!,̯M>& 1` W@ ЊK`'._B /EY 1zFп.E3IMIpHk 2G ٸj],Zt_|oX .AyA y!rssZƃM`@kΉ Vs5ZZZ,-l^`dprmVp4o#==p a pΝ=ˮ_@k 7s2PH|ݴ8s˲xikkm bO}O} {/5irf:Dm #ǁWVTew[ 9LduX7@P|`-e0͸>qy x⻝+en+;_[4 ">9W HjF^!Dexwn+x+5|< 5+]͌UF~{`LB%&"LK,*Q9 u151Oc˶d y󩮾7^X>qn 5$щQX ZcN̢R"]gFN8{}FhɒPQ^NNNnwn|qw ۋ}D{Ϗ>Ue$-#^8JIL^^zH$(P@*!  G/!@M s|3Y đ7m BꋬMR1paZ֋Ol3$1V Yp5‹r @¡Y'>iZr0ve|hzπM[CuD @4P $d 5˃7c (`wlKVd;1"I7>v|bpBvWcD Yȶ?4R|uƇG<9(ǜD?sϷvm{mx׃&sNu֍03jnj덊Ԯ:ΪBp:bXQZd}gmForK{xwj-]` eZk׫b)7r(;k35zRZ{TVTdbFǛ8z +k:UUUcRϺVsZ^{.|-~J)ŎQP @k*rrcyPWWe2Ӣ5XZ3q8o+ ˖=BzvRS e&c{p8H{G={bIv\d!LQNC#1~]@|%zJ'QL*;Fp0X }X4l7 9p-yE#Kg47n7v[Ti)fk80N p_m8w=(wko xNn&w@\Bur3/k/TĽ:bIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/sun-xa.png000066400000000000000000000040131345766322700245040ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATXUkpT~sٳM2I@;@- E;U+t,(8 ^i+ae:vu\j-E,J6R;5hB l69g'盍n39{/CcL&#-Ydg2\ B>?5>>MH&ROX,Teu|>r4fW)1 !!pGsۯ|ڸDKKx<EQ IaؔNRMMMVX;E0@)eYe،OLLҡꃭP,C$p_5(ʆ6Ae0.ceY8{,"!"DQPJ|~̙3O- B_4 clff-[p9EQnJ&XhTU <J)A10`F D(ʜ18]ׅiuwtt h4.<σi4;4M8b<0c m<$I,˜9BdY&Ŏf2(ʄmJ)<σm(JB(/ c P$u]^;!(" .+hT*xEQc (0Mau]~ 8@,CE^>v۶9s J}0`0ȩki22ǁeYܡ (<[_ɡS4%.۶a,˂8p]gU*٫!I0of߯,kҬ*۶Y (ːe,#`0I8xJ)DQ$I,3{GllllEQp]# \.ϡݟi}>Ϡm۰m6JM,EdGPc eq@ـlBB/_ iWHӌRzA$J%/ d2V^O?SUU yF|_eHܝP\|GّH$~FoD" A,JB֭[?s8عW6Vd$t:=U~^?{c/Y}o>y-X웢(F B춗F6œ#kӱ|x}9?VcߜʅuҞpɧ`dk5nk`㣚7ڕcly΁@5w *VŝgE^<>М-Y.m;f;{>25 yQ^)CO,s}||DO,B2[:xNﻑ?koQԑ2jlpGZ__plr h~p쮃9?7j[Y5kgqߐWd^+ݐϩ^4+Ib58|M{>T>Rw|V͡E&/-kn^\wCɄeN]9xeʽ d'kw˦%;Z8=Aet>+ IeQVA:Y|I1{7 VA,'S>N(F[U7 pjJ,LRp%9BAqeȘ;8LxlN[$\k| @6_dl+OŇ` kḟpĻϭ:>xɝD"Qc0 `&ޣBSBOL 3έS-t`lJ3&W0:4IBPA&fq#%h`nw^|[46n:˝$zq?W^f˚ûyK[!l;*eYvE}M[: QKf>?ra(Bh.+q\D0̶[J R""H)AD`f03RBk c ,3ŋֹۀKMAHsj >{?s{q 0Rj.MS03y`-wKL4Q魙iA!E8FERJA0((]]]H8SRsxhf?V>cO< !$ 8FXDWW8OoV~rϻ?& dIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/weather-chat.png000066400000000000000000000043641345766322700256560ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<qIDATXW[]Usq}ЂR"IyHDC &&DcÇ?>>MA?iQik˴l{=Zk?m?\?{de1k9$wMy098/$'r"Z>c<صb(˵@lHCV_Ƃ1# X)ϔȩC#,]UYgnq)\iTXUPTpL\z^ Gf;H2s&œ@%O YWrFV\\n1#i X.; t:+-Bv!tz@.[D0',F2]MJAݍ;_8/JbB! .E*evS7R:jubD\[T;16:s`l [S_o-t(KWDn1mBh+~&jjAb GRx\ML a3F4-d^WG %MTcSeQdV 6OQc;L#U狂ǀD#6qlg[w}UkZu@[껥\C (@!`0C|Jhzҳ hPbpK=`s>u˵@}cZMb/ Z2{/P,TaAK] ^kzk]~>m*Rcիj'`5 )1Xpxo[3jes-fEp< Һ f&_M}l~&ZI },{DCSbb&7BI kb9lst/BgkK71o%ƒ`n -tN dZLWHjY淚p灴 *gKq(8k"zfN&_1Y&W J>&j/}Ƈ*`gf~z0t.Ь).ogDSAPQEtE?!D5_&U40hixOyIԊՄMoP>@W A'$ x ! f:0Cl!#OyPZ& VLC X.EWqX Àx ׯЏޢ?:6! 'Hm-ypH`9b~.t$!ӷKA/ĥ4TmH."B)&*%.߀KIkL}N d3`:ԻZ0gcq# =}Af 2<qFT^֡(oܥ-a{RLmC= MoaKRWx!P@2ј}H:ea\UjW(|rQ5<(:4oy@џz7pZg~AaJ)vD%z?ՌzQK7uj> ɃGkyHCVDY=slhA>_Cl߇P=eZT"0(HrNw'3h1zakz?0v)#J_@Ed1r.f'*ZAMWT(!('xDGAduUC .}~gc9HIpesD0eF !.3 !}^2IItk&5C75FUub@P6 #4"Ql `~hLGM! ,O+mӸ|G Js1`S8ȒY^ H~xn_!3ׁVh)Z =T à}Pc &8&1 #$?ON1q$!lFH)(8+`!`&'2UP&f! 8F#.N2??8v6aFM-DC"'w FcJ,jVڳ',ZS0WK0 \]Mڅ.7tth,zB u Aưq9|ֿ lIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/weather-dnd.png000066400000000000000000000024371345766322700255030ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  (IDATXOhUǿ7vgӬmbCAS z]1>>d2hkki<RJtuuH Fu݀TQn}D$߿SC+ÞBH&uF0M"NR !RPJ0 pΡu]n܊[+wѵM80Mmò,pQ.BZ /_FpmP( ӖIB_ZaA4;3[JW HT*Z4MqH$8٠B\[^r9 x8!R RbrrQ!DQ0 a6} cnn¶mtvvX\ _n 0n^riX\\Dd2RH)===:8hooG6EZBȨCuaR2.3__2s޾~?BhA v<>T̈F:?%ik_n4h`WƏ r=@H?pg}9Rk4FGG`ށ]WZ[7kd /c{;NGaTIR <,.i|nw`f>x鿓YBKAwL]~UJyu/D=~Quo#d6?h ~5 "QZٟ[J֚-}"Barܝi %~w`K-y@Dە0#LwwwWK09غ![)Ib#oEEy% {nr/T荖 hW?5HdlO)Ͼ'MkQ*ݝAk 50){# nhLDgJQK"sS@ <$Ie{l,QT)]H!4Au~3=_LIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/weather-online.png000066400000000000000000000032611345766322700262160ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<.IDATXkUk}ι9wf;fLJp1%AMLl:F$VRB !}ljmSci 6/$Nڦy8w}{~~0NXZ,Xl׏s8̸!h'P;V1B[@v&PySMM;ӛВ#\*+-0}=p܆GƂс&Gz="]J'_1Ĭ dO2ܘ\cӃJ<ޛxlpVuLdH,f/ x1v89HAn"^H} \#}ށɑK*ʢU5oW5kuF8}Yɽ 45^!dPřӛNA"K=Ey-fJQq) ½k3aB9>=Aet>+ IeQVA:Y|I1{7 VA,'S>N(F[U7 pjJ,LRp%9BAqeȘ;8LxlN[$\k| @6_dl+OŇ` kḟpĻϭ:>xɝD"Qc0 `&ޣBSBOL 3έS-t`lJ3&W0:4IBPA&fq#%h`nw^|[46n:˝$zq?W^f˚ûyK[!l;*eYvE}M[: QKf>?ra(Bh.+q\D0̶[J R""H)AD`f03RBk c ,3ŋֹۀKMAHsj >{?s{q 0Rj.MS03y`-wKL4Q魙iA!E8FERJA0((]]]H8SRsxhf?V>cO< !$ 8FXDWW8OoV~rϻ?& dIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/weather-xa.png000066400000000000000000000023301345766322700253360ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  (zIDATXoTUǿܹg>f:yuD J,nL& mBBh 7.4>5)UM Bgvޙ2yq}07| <,ΝH _\\ؓdP,yB !IgMjRU)D؎LV%~K@Dž}.)Po?FN>&!D_S#O~P\@^U@O;6z6Cg{Zժ5\ޥg+Z_}LaH:A9Ws"Fh=aJ !?cAK( o)[+kHk/5rϪ4]ùʟWCï7ž 7f}xX4ѸxlQ.M ?bVV6 lz3RcM FO(IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-away.png000066400000000000000000000046051345766322700254050ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATX{\U?1sgtfgmi.X%"&j06M /"(&&7&&>bDO1DԚ@IJiJiy<{;-m!H#79{}~s|Z˵|wlˀN=ӻv\zlFёnMX`x x|"##~\rnqB+Zk<ϟ`*K/8y/v`m+ǥ=?7^z#W?q/ƘY];wضx6ww7'DXCe:W _PȦStwf] R()izC>boO;mR>?4nt#[w4gubu+0ҕvO/v\LoMLش}=_?>5SX!)rl^Ǎk{u \TAR(Vĩ2BH!,]$Wף &&K᫅B8qpHogMbDI", b836v}5k#^g)͖Ҟ%L"ڭ"F{p;_[arĥ,JeSK{{LѱPjJ]ϟj OivGSL) PLϺ8ϬDiq&`P9$ dmwݹ>:H79ߧ)gM hg@K3޵iN@{[W{6{,cםkVZIJ,SӴ+*}?8sԡW;\3WO !ZnYӳtah,9=r@$S8{{txt>1ej%hP+ y%P2c:@ őw^7_TEv}^/hP<#DZ i45LS`1Mi6].}1v45db438ClDAnZo}G!*^=LCbiLCö-z6nsj2z #Cǩj1hTݒ=71yZr[?/vs@~fR{! 1aȚRnNӿs˻VSāO˻Vҿs4IC#g5z.E_ws-|N8ihR04aْ=R!a>qb˖H6הqa(`4uwY ٻIPX4qbqZS-k XRcvt]q>_ۦQP],]֎5QLOTڀ@8RUb![N]!5씍DWH(5 |J$q ;ecH ]k)Ts!4q$,ΎRI%m4`5T)uJUI*QX% |Ij*fb8_4cQ8VQS.M1;Kٛ|L]`,H*qX!$a$kVa$"40uJxsYӟP&DqJ6$qP)PU*q8^C#a[:?CfTH2~yǯxv (ٱAʞGB%qOW =ϋ5'ۤK FTT\öti`H4P(FaҘ!+Kcè4 p&4'~E@^5==5rZRnCFolA|oTsq%&HIoC #wZP)+[ nCNOODl9=sܶ"sf>@2WòXn:{nJ9!m칍ư,⧐aԓOйr3m+( oݼm :W0?u˟Ԑ]qVHW.*(Q,rGxS(%tm 0&Սo÷r\~heSAڎ^w+..)+Jǘ8Gʅa⨈i14qT\f)MenEڎʴl* ry୅7{Fɟ{e cL?\.D1D%K]e7мbWnsze`7^=\]Yǒ-H]h>1MVDjEL,i>E4x`+Sl0xlp²'eKo9Ӷ۱ B..%el>tBeghンL:dKoٲ' Nd b_Rm7l[aVŤj"("C2Y%H'z͓CS oiYԴsL&*A AFBt*2|eP}LՖAZ7n|"օy%4 ;pjUJ|'? +__kkL.ؚ.mksҖ4+Z( U8_fccyEl4RJ:^EQݜ~֞x(P5bIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-connecting.png000066400000000000000000000047231345766322700265740ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDATXkl\>~8N8! iPD#"Z!~ 5U)T(TU[)-** i vįڻ{sN?ݍM)I;>4 b5J|G cX)`80lCGodMq={"e@ bUsX7xhއi9ɷ6`4U9R2/_ީ^0F9Zc7 cs@L>ڛx ϯc04Ơa:y?W1rǥC.l0lIOMjFa"[,G}+; @~^$kבk)҆ьhMW,m%)k 4%Xx)-k@=QگuO?z?I@K DI}  ŀbJc"6Q ~[ZxY˓K>pxHxdhmjhB %HQ55Udp+PiRsH&Y%n[WUGqmB(5~xJaI@A|Eh#ScB Dهmn-մ4 *Gضqk[ڷ?*mݻ h[؜ %1/ f`,X֫p -CԵ* _Tģ6o&0Ip B=|&PM%akPS)0^f-nZPڑ4QGR[r?a (C4(06B]|4U{& L%@[rHUaIX@ǖ8ĶB LiSqMTaKpPhxifn]X)M5URH$b MYq%]h \);P@k|eg(KA h?E;oKM)&! 8aHsy;C |MWx@S 4 ST!Z$#̩.I\[\iY)h 5Ų$MQ,]PMs}#*y: 9DFu-X[gFˍI``2[ؒ]qTsذyuQ<_#q$%e6:T:0d~ec2Mz$3hVtk4ڬaP#5y͵9?c^S=KQ 0Zb8 a$a|M 8;2kbIs '%U ǽT~ɄKĖ!}>-x֣OH@c!%4D^XLYVG{SH>4X#xӲQ9G3LTRfŒ~624'&99Ǻ$+ aiēٷlDuKlٶ`p<7h:n5d MQT/kdz'cXRX$.ڒ6)~ _MTy=*{4zhg22Y`4S QǪLEJ@w-͉:a[?~z x'Pxtb/=m}vB 4Î{nceģ=6:yhZ N@8͚^DzjQE_39169ͩ}tyB#7,۞]z !Px{=ů. ϴgby`LB>{'ntg4'3IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-dnd.png000066400000000000000000000046131345766322700252100ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATXYl\;۽xl vlg8MPTHBD FyaD)URTRԂ!J)$,)RM:s#.\^^;rh_<-l~jW _կ1nxᣟ_3;'nl{um^L:Hkjfy{;x(*RQ(e/a1 g+;On溮2v :E>FJBvGM]= 5B P04gwuv5ǿyӖv\bICBQU"y=uqǶoƍ=rɄ(s!T% URH*PolmjV4H0y~);)yC?$@@l8>>]DRď ;1B]^K߾Xn%HhM‘+֭oMDע B$~DBZ;oEϚ5] ss© >"_\`Pe喵TbaM*FQ*XZm (7 >SPkt-zJ5=\qJ?/ilEUTrlaM*2BhVTEu~if0RR0 N4MR 0%( A0FJ8RnR\)ka X\"AC{;RJiZ,$P]<5 yQAwۯPBX68FkjYTW)Q/C:B2Y0v Wَ92Fr4hj$ S,Sg+IX5ʨN(" $R|2I>5Tv\oMMO\u=! \Ƙ<9VSCP B%;GFǫ!".b3ŘKSc&&S,8uOu\wjz̩@0 ۬բQE-S''y`L P*jDݒ F"^=(R.H#uvK/L!\pp+#^|A}9{)޳`$zdT*Nx;POucSoِǙ$6'<VOA. 8~4nF32K/ /9|Ox H[NM]CK_'E\r%ugGSOիKNM;oI_%~L"ے˺6r^"p5ȼX{Ҹa˺ےt"POؾqӦMJB7Nrg(l4pg'֮ED{Wki6Ο?_^D}}CnnѤP,"M7MC* (w:fK\*ǵ VOM7֭_A:pN0TY6%mwt Ү8^4uGiͯ/1Ymk[47khmH Bey\ּH''' 0r/U *uMFpmv'_K aHەDIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-error.png000066400000000000000000000013431345766322700255710ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<`IDATXOKQc{[+Z"!?8DV":Ď WF@-1wuw#y`yW99@o7tXk{7n:^t,R"]{JҼa0n5ly$+:XTأ,T`L%i0uMa*I3]!RXl {Kei܁0$ jf`Tk@.(`lܮA9xvP;@ &ፘkA)xv`"ѱON{Pss= #-4?<ԃ; ƅ:|%TV4K͡@QvњG&l oZ#7VF>n׀C{JnƵij3'@6֥lH F}]f`khwx9zT`i%JzFq.;ٰfnܲ0wNo{"*JE|.\lX gvӃ)xH}L>dpp?0"]ÂC`S0\tHtny;'snmý)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-event.png000066400000000000000000000021511345766322700255570ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsetEXtSoftwarewww.inkscape.org<IDATXoU?tJ)RB xI"0gN3??)%33|~ 0[ۘ%ɔmU,F29O8&LR|=; >9g?ennWffD#,,k9@;;;Ct(J&jDGt2,7z{8u$B[yp#v{.dpϏպiH$܎PQQAW<L/fg 4xtc G&S]zXlDJ<`]`]p)vq$ 0>gtlh$cel6T !$^ {Ŋ[I.W%iahxZ(P q<[̱N'@m9>Ϗp!'P?<tz JD|r"QD;^-%{Aլsy ;Bm655uSx JV~ 䱡-U^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-invisible.png000066400000000000000000000042321345766322700264240ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATX[o/3s >PRUHZiHRZ>_CJ}?WHI!I j.R 7c>̾a(5#-ff{˖r>rh-sM`'P;}( ~d}03;vHCRGe x {*)%z2O7n\ ~؉9 8*"#?}g|N|?9_D^?z;<7J#+Rh+}9λo}7&SJ.z>{~dYB SuA+nE㜋ƛoo}Pw8πFz(TGOV[v./)]_s.xT8ct pu7ґ]J.ܔ,KJWVF.+.]wsJz5Dj2?-"#Tubb^ qyWL115S:6Q̞ZUb[ؿg!aMsPݣ8ֶ͆FfCrN9|ZkٻCTYUO_1Si lhRt8G{R4=!x ]]݇Zk 6dJ61Tj)f")AEw5I@Pd HHe#Rb 5в׮_2>@(jJI'>R@H0EBТ&Uu P>E 0n]>^D$)Rr\:B -jC5`P m,9 \h3Ͳ,cg:]EĊJ)T,DLn,|;'k2hVRrǕe ҍ[ZUU몰$j˚F?i^h1Q0 4ڒ Z׶-iJmә So$4Fժ&$Ʋy(6'3)+umrS؂"+h y,N\m`f9d&_Wd-mN׵~e||b,tw}kns0Fgye,+hMEosh̛,Ow'Om}UE-ٖ۹Ȏ|l߮5Lk *lW6-yΞxnb>uԅӒ}aS [m[71ޞ\LX=eY?00 Ț>ccRJI!2,--BPes4J)l&+S1UN+;҇)IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-muc-active.png000066400000000000000000000045561345766322700265060ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATXil\-3%;vx/qDj0 R8PPiJ~)Rh((1Hl!!E!@ 8ı3Kd ?@5m@::` .K]P04<4===m8 |&`@cS`╵+KJJzN>7H$၉3m?8:zahin55Ʀ*B[oT}}e3{z$X˲C<{[[{1Ʀ5oJKKv者Ҳ@FOM!p:tˣMG0ܮB1ౖ@cS!nǕ]T4m當O*Jnn. )++   bYerewږe:k|itÆK6ްqy0ԧT#ar9ٰo%T͙ofz:é҅o;NG@,).=usi UUܹB$EDpB ^x^?iq=wY˖,޹`La*ph˖m*OmJ"5fUUW*{^7T뺢8vVBP!Ӆg=ַ9POJmF,JBR!TۧBu*@-Ӵ{i**)DJfBr^r(d !&Ei"**0 T4mۣ ¤iL7NPY(3e!Ez !@rIi0cH$iGF&@%P(.TЉJN{AdE!'0) +e)CQRhgy̷,Ӵ"HSq0X<\jN^V!s;F #+4?~F:*DU>k::;^\cI0l`\ش!fp:|nc<6N ش9swt!vTilj8 x=P(ʜ XWwg@~Y _Weu1"}#ٖֈ];Gjm]t? je|gѿDJIeUqH$M7JodX,4?T]@Su#.ggI;8.M+r8Ot4|[OۙX,~`yheٮbaI% fe F(έAUK|϶3mLs 9v4 ,ۑrQR+Fi/6P@`(D0b2C1- ۶3߄/Mlvcژ>qx<6׵嫮 !khkJxt$ᘊ 8(]P4^Yt@ @Tοb͊b !¦[*'*J~uwۑ:P,Ӓؔ4.^hͶ/*"CICڶ>WήQ!*IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-muc-inactive.png000066400000000000000000000042751345766322700270330ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<:IDATXklWޙ]bc'>4Eu>4NP8n RV >PԂH !}D-y4iҦBi&k{z\>xnIIEtݙs9ιbXOZ40 $=4 t͉ ɩE0{D`?`CCc뎮;hiiYFJb4>>6wKo\xcbfYıǝO {$M{nZ33iACC}ys/]ysc;z|zztkmm7an~W_LMO'_( Uk!є]L<g45:?ߩT* oO"/ݻlYթ3gYrZSSSu0::Hjl6yDc:|s/1?(*P{Ͼݻo|Z{y=>Qͭ V#ȷUC17?\KX\,r͛^]mw˧Ϝ2%0hYc횞>oSc#_?C A $@ic D8rnSC?c|b< YNLb E$qPVxꩧZBݻya&i1V*gRH4MP੧ZԡC[E$A({ښ͵^:cۖ>VR߈ %$Zq}ضe+c<{&ڜh޽ x0ݱX,vg׮ _kG>T^% (tɣ9t4Q>+㑇QYU+_UWGFڵ1@;Np2.J{`7bb>3 (aCłg]Q]U$'o|c=@"H<6vld $_|Æi |ֱB#v< mW@ܶm-"ljoge$<#`tA6} Zk-m+ X]\O&G,ui߰~0MeJ~ C pQs]?Vz<ɒtIjk׀(DM% |ye0c&CADDQ]U44K/) d<c.@rd% BЈ(XA Bk 4Jм\d2K@fRcc"CCr VPZY\ O9himZK57 % {`| *'0¨,Kuajj* ²p2R$X|\:A}:^x mf&P2I}l^H'3{ǎXϛCC;ؼi5q]p]u[q1lݶ)ܡ,AX:;.@ c|A)EĎժRp`]{ܿsG.{i:g%0 όOLD@9 ێR"Zjl;OLN'ݽ;9=aʕ3'[]YQAkU^i~yBa2_NSeMf-z,'~͙/wlܺ+W.e,A\*KX;, j԰~}&\eU[oNotW`u/3<2%W%E ض͹0Jg4b4ba!1hf}<%|u/ܸ+/^8_(s\,/NsDؖX﬩)ixVjaYH-Ħr)XP4۠7Lc7Ύb~͋I9B9 FPZH.RW[t^(| ;8YJoSD8K3~gv=WE IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-notinroster.png000066400000000000000000000044531345766322700270330ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATX[lSG3qb;!$@@"Ji]5 ݮԪ{eJWBڋV E>Mժe(d$rqI>هsH='|1yځzNG{?<D8w \R 0W?8phx /Ķ'6⁹bFΞ=Szl%log{M?s۟/jۧG4~?8_fOuJk)n޼,7of֭tww DJIX(x_N0c1rpxWFΞt:m6DqsF nh4j9bI$ƶmN>ّ{{|>٭T*e1ccc&}'ؘ1D¤R)s98|zr~}-l۶y1“VJT T!%SSS޷wöm,}-}<,7]񒔲ï."J㌞8i% wwJJڤd֌8ǏJ(ïR6ឬ59~7, ͊+W2z$uBBX]ZysCRR''OrUffeY7^s0WxmcoOoKr!)Ӌ=z%)KEկ_Iɓ@1VHR5Ge1Hr!)z{z[6U{{m q)8R*f}% JA2F) %yAkvC`EIf}.x܋E`;4m{;Z DRe:e0OwLA\1Btdds55TUk}(B}X*٬,oc H&H$Jf)wJlu J!Ra((V!S*1S FKA$!m{!]\J6}u}zjCƜ6>Jp+JUK #Q}=AJWJ>lhؘ>}=|uz̽|11q1Yq*Nk{si!٢5ac((EN),."n!B,rJQP1l!$Tq*$o\MϧTjqbrNWGRm<34DD @AJG+u~)J"JmGAJ@D 6\c:z&&'REU^ Ʌt(\GWO))s?7O 7~rB: Ʌ? w1g}pge;c|{,FkOK?~[GBY i=3W}pHzX<@o/MLNvFc\{]CCB!jXU`t#P]CCǺuFcɉɉ%\jqŞ#㞟ߴ_ Nwi.[n3;?O\r"SPU~677%Xwlw2\SzJO; BO?p$\[歊c K%r_UjO9:X^Z_υD:wlL]ZͭܮO|+ +lhh\T]Եԕ+_.z9d, ZZZP(UU=Л9岹wo87?{N6i"Hsd Jl.k&v:S/IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-offline.png000066400000000000000000000047071345766322700260710ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< DIDATX[lsΙLfkʼnرHl(%Q^U jTԋRP5bDx@BAۻxݝa'ҊHrt~|8:߾{3@]p:R:i_ 1F3kl p35)8p|){ ^랭[zRiq޹Oϕ^}핳33g6{O !z'w mZ4>;DEEÇ|;F!w}.l4'O<R}j]n(t@ NF׍kRL> RA3M3ȁGKl==GKmee/D.mɳac %>~SUk}fEL+T^/\dyަWJ) Ҏ^)"tnL;]:RTONau;7nF[, dnn۶a \uA$4Xm4Ֆ9)B"e>^/`rDn+&/ kV&JN!`zzM^cah:ssumgZFp||+õ&/*pJ=]hDE>s (%/W4>seZ4 (" C $ Bv6nX9pڟ^|a x#Ro9q.%;Z ŇLRA9_|#Oct1ދ,𕍍)oQ1!Oߟe˧!PF1m4?;c4Z+ey4ϟ1Q7^>B1'9NpuMΞf8P0B(LA12Rad)(T:= WޤuC><pS/\{mm'!8|(@/^x,un D6z#ej$B4IӘRIZ m,un«F@0̥k\  T }{1ڐzKb4"N#zC`PDˬ$=gQcǏV%"F9L:zx ^ͱ&JiR`}Bbc4"J#c}BC[j-YXXcvt(@#R"u\-@P %6>"u)I"6&u)TR,PZ4HZ V{$.J)a@CZ8k}lC6h#@iibH]Dx$u1]Ҋr4"-X H9k}V7HND{}: F [)R! 1WH_@0!Z؈GXMTDG0YڬLA 2|Fh'+\_ (J+aj[|h([lM([g>\a@jJG>..a^|pXg{Aή_p\R6 O[;6 K2\1 j7Q_m?:yԓW/ھ uDc?S I W$MaM&4bh74yۗW/@.;;'wg=^K7_oFɹyb 1\yꂯr"uow ݉ksKvgԮ]UJQ)Ɣ*K-N00&ʖ ;#ƞ+ +/w/JozTݳ6R |s) MY*}fo4@"WtYk%[^?w;-o Ƿfs{ibĈT6V浚Y?бb\F;]kn 򘿻Y#Z-UkA\J+q. þt;II$f]s* @&~W5ook@iIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/32x32/status/wroop-requested.png000066400000000000000000000046051345766322700264450ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATX{\U?1sgtfgmi.X%"&j06M /"(&&7&&>bDO1DԚ@IJiJiy<{;-m!H#79{}~s|Z˵|wlˀN=ӻv\zlFёnMX`x x|"##~\rnqB+Zk<ϟ`*K/8y/v`m+ǥ=?7^z#W?q/ƘY];wضx6ww7'DXCe:W _PȦStwf] R()izC>boO;mR>?4nt#[w4gubu+0ҕvO/v\LoMLش}=_?>5SX!)rl^Ǎk{u \TAR(Vĩ2BH!,]$Wף &&K᫅B8qpHogMbDI", b836v}5k#^g)͖Ҟ%L"ڭ"F{p;_[arĥ,JeSK{{LѱPjJ]ϟj OivGSL) PLϺ8ϬbDO1DԚ@IJiJiy<{;-m!H#79{}~s|Z˵|wlˀN=ӻv\zlFёnMX`x x|"##~\rnqB+Zk<ϟ`*K/8y/v`m+ǥ=?7^z#W?q/ƘY];wضx6ww7'DXCe:W _PȦStwf] R()izC>boO;mR>?4nt#[w4gubu+0ҕvO/v\LoMLش}=_?>5SX!)rl^Ǎk{u \TAR(Vĩ2BH!,]$Wף &&K᫅B8qpHogMbDI", b836v}5k#^g)͖Ҟ%L"ڭ"F{p;_[arĥ,JeSK{{LѱPjJ]ϟj OivGSL) PLϺ8Ϭ{TcVP ,u/zk[,"*Bg< K/_'AYbtwкێ "$Μ!Dqo3_qojzS&|3[T 5@5MMtuMdsYfC߽gwoy38nJ/ {f~G܏Rt"D$/c8rG Lj~ahXxgm;BJ)DqrT=,bD j$nJ>X/ZX2Y&ݿ3oVp D<#_3qvnI,@}P?Q?v Dc `},RJY!A_ 3x!ۻ)[>o3,wV/[u<"}~Th BիVNdO@Ԫz7Z<^|t ǩ`D1$'jb,ڈp9ea|B!ԽO,=-x w*e}cL7>5&ThK#F0b(J Suޛ X?$a:x<^ONc# zmx(SJljFc8#8q?"\F?XSC,'Lai 2MTpP3.Ϣc![D[۲xllΰqb"48!j&bہ2>0?!Zn~j{så@ 8p Z(>Nmk-[K+j)ԧe'FB@\DDho F&[{ 7 4%Z_vo?sS@gd*E_L`@k/uG M&2E߿v~FV698 ǩ_~ +׃K`׮]v)KR)o,[O/yuНG:'91WJ_D>B```X֋{e{وֺ ժϗ^!?[xdx<}}xlnٳg9rNC$M(Wvٹ֥,iIK(\L񍰦eRlH-d"N to&_3dpZ)wt >ػ~}~O} VLp8bh,FԎH%"(cCsqt|BQb,K8ғiffu]JGT)EOwx3ݳA 9Ccluuzڵ ˪kW''ՐT" b|qz>\<3eǣXp>w$+Xho_b"OT$_ȣ&"FPŊh}opHoYMPXj%8@< u=R)ږS,pM2æu.)%#_R(W2[Vx7ƞhKeTFYDjgc(hooKE˂6ݳ/$ukF#$Ibxi@/XҲl.Uz-Xne;޳V;OTD*˓ez;=~fܲemX®y11DcqV% P܈}gNɺG/]kK,!L{زe+haEffemHM|߯9(L4HR)g&3ں t###LMNf %Uo ۂ#-m|fWp';[!L.Ah[چHCHT-D2=9A&3< $b FSOw^AuGOk)c+(P$8Byl|ʕrv B$RG Y]X, X,LPJ8o:|>pVȿDW_= p/_k|{`` 彯NLLLPq,K uHD#"Aϯ[܆ \ tsdk(,z\w~llfرcUkăpz`ߣR8$q"&oJ(z_T(W!HC]b' 꺔졃޸FXHB#(8npi[ʄWye?-pZʕJC gnLR *t2\QOtD VE:!D)Efz&P1ؖ}]דB"vnܐ B0lB驠m#!TC[UU#:@vULf-0:eZxZ_Ӑi$0k@ }*488x +"PV1Ơu]o~ؿo K|@TR)#Ơ5iiz1%ǩ:U+'r\\,6s$aHچlbrƺRrr12Fp61ys~~eYS*Vs6P°(pr9(Zڦk-.PVV#) ۶Fk;岹zƅ T9 2v.A)E, b#I1NVQdP Sa%Ij˰)uI+w޹D21@ g=D |+c9w,0?l .<6NYֶd2I"$@Mu ߭)J E2i&'I ˽7k[k()AF SY mq- T|Zz%;EûzF[(sZ~v+[E߿gG܅ g6Ԟ2UZ`B.aXY:~С,кZ?ia:4IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/dcraven-online.png000066400000000000000000000070071345766322700262210ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs,K,K=tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'Z IDAThk]u1"<`}FDP/}:O<|뭘pd3޶ 7)ŲKa{v]22C?Vd|tI6mDP|ȷ8bA4"]~C;C OF`$||a/xu`1 &!@ qvcȾW[|/ӳN`Vp7K*R)@!v=OxqUׅJ_IpĈЎj>5Gm!xH q[X  z J( LgDq waӆRgmϿsxA AI8J(/*R!J8;F4$JOWY'b}ٳΤ[1G@EdDTR1'NHb\Ӫ}= V4E 83RF!p3s^{A"y3ql^`P~\J=2`ӐD#$ՙQDjJ%Y Hz.r6 LKTq^@,HHH$#bQWaM1IT?p:.o6Qq REI~m qe".JF%~sWE$V,&FcrW!+lg kԏe?*HD`SR`tߏ*c ?s3b-lq%Ė[HDQA/HLT0>YV'F$&l8^jy7yu*ƫK?噼v|bgD' %x@ _y KG^wOnHq\hХT_x9;)px5r\h "pf0BZﵥ|:.>*?dN)y{>{*82]U76"  \ָ\z]z \{8NW7]؝EDQ cK9jQ6n W"OQ_.n_ k>A6EuPt-9ȓ }ӈP<*Q#Xtb(pΡk=XYrǢԃo% M['AIk.0!&pe,Huiz `]tƋ@DCkKl,6 U~ %͘ف$ۇR"!Dq[#!lj #pۚ _ey})i=[3g[xՇ82ԉdX 3ȱi ׏Sycŷ`&W٠',0J1Y:\׷SݯM[KۮL((*>(*I-?\[o&͢ 0>UX3OTcH[6lf҈cX։OPžiL D? F >)"(}aUzvLTz:ZZjL`P l{|]5<%=ݜi?N/8qBo9Z`Pɋ@c;I:镾ȎLP+6p-)PqM~ zh Lb*[OSSIH2\}ro12=^hhpOS.)}T>|/H4Feih['FyP%ar=}p1dg5Bɮw.Ye9QM#EebSw!%5J͡led{EYP %Z.$b0ڒ/Nsd|Y웗q-W^el來\'T }O%JaLq qLZT)S.*G˗yqR-Q`}B$D=0߇vYaT ,^(S Ti>=qKBQkbsIbsvlXq8(n`sF瓴MO|VI,IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/facebook-offline.png000066400000000000000000000023461345766322700265070ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<cIDATh՚oE~ʼn#;؎% TEUŅS/%zK$"E7$H'$%Nݝᰳ&vH#̼;5 kT`r0!۱V~_n6J mn>X=Liir]K,DD@"*JT_n:Ne 5ZEyT*jwon krP,Zz3 "BTEg^d5 /y5VbdB;NZk\ׅIts{>D %<3^qZ!al67ˏqV X}}沉, udf$G_7?|I(k+`6} `|-<i}`[]Dal6c -zdYrnNt\.ן8~q.7u'W/28m'AE2MmF_/>u˲.ulv;?Pl)S>8N$sUllˉ'ohqmNoK'48I]PJ zJ0y. iW`W`qJ11V`"E s&o 8%>鼲7v +NX{wR˵JqwzJ,ÊNجEĊ8&'#` (@`@$j !j MC}p||4V* 9~q>@h8+q jJrJd`"?NJQٯZ[rV 6V-- y3ٽ3q# )qTۯ}G֦M&}*㗷y4_ Y`(K}yPX/ #Z>\ @]H@X$Q0 rF$hƫ!)) Z2yȼFM>F̭'Wkl@R㌞p5j_n SgE܎4n1:E)}bz~>ЙoN4Ek^q|/to/ ;$IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/facebook-online.png000066400000000000000000000027611345766322700263520ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<nIDAThՙkE?3{r46Ъ RAOA|A|.V?"*H*>YXJ M^bkKs|$ges=|3DtknZ嶑Kh zϝ2 |eO״ m#GwW8R(JX+ƂZb e;>6V5}x; Vc؞9Z108)^p0bu{M no.vcp轢Zlxp%܂j P<$ojj%F);Ԯ Ϻ.z. e߰nVo#])Rp9ۮ56S+ Aؼzx8_5U3iOCRjkV0bsd{ž216QC *d{1`cỲBhb6KM$Ty_6K&ߩ1&>=ˆ^xIMcU?0;k2ȴF> =ZG,uHCUDBPO4Z2 q]JvK J)p㓤h f,6QU!np""!]^/,.4nnRXZw`c0ӿOPo-TFNhbн1VP.@ܩ³Ţ]cG?YѬaXODlB.WN3O EKXO/ȵq $$aM_89n*s[m{b٫gg&FON4N1nn"j?8yG% ` _/M!%s1``Q:a 6nƸ*qD`C"/QrDt Wbl&s@>0Ĝ{B$1^$x0C vIc1B[Uo~ti - F{^t{{Eal q~C13-YXNN}K:=E#;sVEc,\ ێ۱p|a# UAfV >cC)!iE@ XC⁸~o E,N(ӠLeC{ۭ\Rѹ/'ql̄EaɲE15? ֪*-}| ?srMi+]n]|<3MF_F=X4]՛xFr5m8hqa^  5r߾}]xi KZ7gl9'' N9ǎ;sG}7E|IidݝH.c{)W\yŴ#UN-i̙.Q 4Me[ODQ`Y/B(G5ԟ-\2܌tߚO,@+[6+r !c.m wAdZ[o3 +V,Gzz:‘TEE((0L Qϱ$ ^.з~XbeKX2:DAΫu {dAzoO?-Ŕ(%%Sbobi(,((y`4MåKh8uPy!I2x s<AĎǂWWUU[yS|IK٫W\)E@H5231끇eY, 8=ˆi0 q'z Iri!j@ǎʊg7h)qԙCnjbOϼ)+ԅߙ3Eh۾8 ذLyL49O_@y0  Inر;++wV== : Kv,] P(LϽUU]KچXL{Ц l zg}^+CupE,._ MS{ !qZC(0~;zii &ЧN{[+RePe?~\Fnn.qR+=$A׵}}Kl"E<2__]א`i(7fΚ K@AATU0LzF* >H;h+))q4{rsr\n o`31ga ֭_/,,]7n?ϱEq-۶,F;`y7Miӧ˪BUUe7n H|-8~$TU'ͯ; PU 'ko%m5M,*LDqn4fgк! c0MG4m񛦳g nmnia{8 /9Pu &ND(e!}I~(-/]q4BP5 >+P0L3@P<~ׂc YlYGbgO 8>>q4\S]yYylZ*Im^bf@vV&^ڴZ> ۋ{%˲< Dp7{Ίx7B$~3ήIJ.GalS_& n3wy?a(C I7Nahbݲ8tp'Q۲OZ^^bo۶miBiMfhX)%/G>frHzUlz7*Inޒr9@]4 gUuۓ$~ ෩Y|ɟ;;;pI.Ȳ˗0j(hrζ~ݚbbW-FX߈ [EQB`Y_sWu˲^l<7 Ϝ =r+FuxNI}CFSS J\ Mz2,)aԝjWxB4E8 4ű?~~ [ |GXn58KrB0X . ˢ)ڎ0XN7663zͤ2˲`X.\SJ <ގ ^q<,Dvxw@Qy! C›I`9j*Q---Mh$I<A[{;| dfdBd̳,3&,~ލ}NCt(-ys^kA{[;}قayyGS\ܲnuP2բ{/7]n32p[a!~!E(8G ?=9E[Fz& ħ>رc475,`=lݺմ  @e /{w2Md`Eӽ&hFnVbDس{c[7& En- ~y9%߃KRP8l8:::gO !(SQuC3(]h7-'+WǎD,QIsI\Fl qP`EfF6L§ FA*m(L_:TEŹf8qaB7t xnYBfC0؅:KrIvRac&7Gvɹy0 vU+h]4W>i$eI2? 8?jO7e}?D۳{_daa;62`v@\ӧMGAFR@v‘Л*מ9eʲqRR8YY$I믽a&ɹFzJ=bE9 9qVz!!W`4Mi;`YGo*tBS. 'THҺ]ȑ#y۴q`h=--.vkw_\BR콈>ԖأOgDoÏIVֹn@7Hn!vqCi7#){A Tнm`ۄC IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gadu-online.png000066400000000000000000000066761345766322700255320ustar00rootroot00000000000000PNG  IHDR00WbKGDtIME $ IA `IDATh{tՕ?~Hr\!!d-QEqv)-:>c1k::VDL y'q_~7Wcsܳ~>}~0Lmlq[\9\vm ?~NNx3`8lPjJܕ75+*0 [BRȗBUVR`8láT!L, !%[[a3ӯB4 B*n۫9o=p0)N@)l)q~sz 7;LJ|!WʶN_n7=ӿk]qlwߍC_/Qj5೤W+je q|&c[nA6VΜѣjCRZIYp57+;'ԑ}m!*DhaqOލ1~>۹.Mp/tÏaȂWRS9p_3FV>Q7aB#H݌7}VG"JѣFĈPT ._ [D`k|#-P^"JE?Y9~ q+)>yFֈiLgE2_{و)ShK˦%J/ ~IQRv@I9]t,B BAJ^^a )嵁i\TBAȁ={ !:/^!t?SXU;ϼFo ]R$wBDL Vx~݌&uqjm*+ #S]nӖRenu)M~?㡭!DiߵJWeEET.TS=*qẼ˨!l4Y&N$6/nqp UqTsT>UI~mH"B!ze`tnoV:p٬}ק$"2ذ?=15&W%wD+&"hͫ赣n7qˢYF0XlEEru0zM%nz/6#Lޛ\T7(;f֔憸bb:¥?+Dő#uu/ܩSߊ+Ȕ5 qT$J2'+-Dc(Đ lΌ]kա0aBkD57.m+s.w0sRNVVsb† b&CgeF;E"H,g)=$ YqPUU@=n{vN 믗~)ShjqN13ζYLD."r!%|VVf9LӞ?kR$^c1>?zŖ5/^ke>y=j>0G{wPPTtKkTk+K%F T8q&m!L^C\3c0 tpsW.+CU`hUUR:tD$I/Sb0۶(JRQ.IۅO$d"o?8suc3gK'OBS5 IJ9qض ˲ކw9n|8u꤬꫆nl֭@uu`nYV~<|Bq}2q3Ei=DcBmFKKKqɸ/QU>whEEEf$ $!FFŗ_sn(ݹB%gԨkng% R88"3gL(hooϝ=iwb/h+W|gT՜[2ዡBQ`_+9JVFOpE\SS3>o9B&! 8ٶM[d&Ad2A !;SWnڛ_RWdYqnmsrgR 8YIH)8~3-Ӈ/Ekkk7[ B&|Ddi>5ZH{!^l3o7_MdZI{̯Wt=\ /Ew\,_QGt=Iae9'|gC(8YEiaL&)SDs΢`u04@ ˲qbX^P'F_V'O:@ I0 gpNy3,1l߾X![|'BS5ӟl׾:MmyN^N\>x0I@83`]digx7=Xta )SǬ*0X-rN}of$1h7Dséb%w@BUUU) `ze)¶m@g-f/P:;}Mtʜɴ_UU{U/'2aqkزG+d}Kla::&N {OȌ1GQF7ٞ{t޹~æj4 Dq0bh>shi1GGccLFC1ͪktq?GYc1 0|,Ӭ(urW{ٛw!'LrYrns %Imgîu:V}ö,K4nv}͑֓ǹ({M`oB졊WUs_зgn_9rYd(0D7 p6woDӧO5bDi?eyiolUsc0F rkH-*e!oeuJ4jВNIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-connection_lost.png000066400000000000000000000036121345766322700276000ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATh՚]lWIJ++F@P[(224UZJėK&Т6B-QPUQ@TD%҇&RRwٙsxwv;u8H㙹w?sbf\殴˵@y97Weӭ9⁁}_xqwڶΎrrd/Le-(aƴl<< U-GVg;# afa7 S ָNU}`"w~l@ p{B!9ğրԧ19c׮0sBJD@şzPZN $d@WJcy4D̚tf0 3;n&>ksҠxRsM&)"K^*tըf#J=N >qEEOQ8|=tSEիON^$1Ρa\ klxeQ[A@4; ,6"V )jb.gheV_> !P(Y:`jV&>{Yl,O|3ADr43T@\*fFHZ}IMhOj80 _҂"rqj-"Q[,:--BjPK6jblFYlRHҠ6hQݨDTf"$)|Rd-}#Ø);O$tוZSC!ѣ0dc[N3Rj.(P3qLNa QF&oo7@57"YLdQnUD$n/bF\dLD}m`.-}Rxߍ,;c|'PTRyIj .yT'">w40H߿Ńޝ(l?gcS2Vazߜ֦o\-I?P6=]-/X*P :eX۵~3D$TUIp+KeTr[w#"lt{(/Bz9\.߿iѪOisKoC lbbIyb~zFFFr_Ȟ=xcET;DZ }ɪDpȡ\U) QyY&p5eZiPݻ!C>sΜ9ß6r;?CEn)[VMnwF>|061gGGIBFӃsu֭Ehf$IB}rs̟:EM'ywd$Ih{9fg "8疽p-hAX)sQE6lh~hh(WiZe%,Utn_N3WVN37oW_۷LNvӇw=g5Txx̰5kQcv kѿy3=v3wݕ,}ρ^++2%%@O8£J<5̛~nmۨONbf޺O:'Vs}R΋H=<đ.LY1PBIλcc֮%T7ēN"+e_!oDt3tuٳ@UJ,f%8pA%8t5=F^#hIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-ft_done.png000066400000000000000000000026121345766322700260150ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAThY]LSg~sz+RҊ(P`ةȜ.W3C 7[Fh+/hHtd&eK̔j3& `)?񣣴P?r ӳ`“|9/<|R &bź{yԻ;)u>A4v-ܬ6Rꨩ=qētjE-dM+%;KV{/*  16qh:;;E'爄O!BEHjRXPxK4P\\,)NI%R"JEhHK:dЕ˸Rw9jBkT$2jXAA8c^l-"AG4ː/)NI%Y0"u/f"!ߓE@nnnTKY#6,olt @,/x pFQalBa+؟R*#n}}Yoj3c9Sw=.-'.k{ 8h:Mi [ܮ P)¤}Q:$غV꯮{ߎ>{6r6<Aw&}#nLt<18W  x뿝A ͚ai +(~SMy+gkl:p6t,lJӠvJy֩fSӑ/P ,-ئŠuE)@\[5&՞G6lQg{< "4C=Q (p _T}i>ouTY9_1Q#Mw/A":N !á9_hr1\$Aj.!PJ~taG{1bGv s,rLu{($ $QJ0+v˰/lØv __ TqgМa!0ʉ\z#>+π#5 X+# |*8=7'7 KLmDBH"=y.SJYY,ao>uӏ1B ~i#8G|hI ia$cҭ%RM֘UeAc9A[:1V]TBFm>룯羟wamR_S,_0bH` Xx3IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-ft_error.png000066400000000000000000000027201345766322700262210ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<MIDATh]LSg--H1)d Oe4 ]K30݅qYv]iȲ9%1ov# 3v#A.㳜YA/yӞ[@ >8f36U{e z%hlPf]c߲ABGe[m~+NZIcҚW%;%,X֣m#Uuttm=-j|uZdLP(MzZL,UqT`*eGmu+kV/S4ǶmTib 33S,hB/pBȂ xySsaTFϟ<쓭l54YȺf4@ZZJYXZqHII jα-lT`٨@8=W<[ܽ6> fs9w#G0%&LVCCL3Z]MjCCy֥.]UM bcz1Fo`gsA>2ro8ga8JG||}}L=ykEW.㐤=xxz=>zRω_ nvo6š 0څׇ!>>@t϶N͛"($3Fd~>3l!r[Zז\Ǐ ~Qm@$NStKFFFx_!fPn^==t!\.ׂ혒Q&>u\v%$)0J:mm| iLTCeel9u !MMo+e_$"p$I& 2?oZf_I~f~9:-cXhm;88{#"!s^(#wzS_» rn`iؙ?Da2&%aZQ윙| 0xI1OL7 |Fإ? _mh)!`OsoX+*w~'w".yIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-ft_request.png000066400000000000000000000044711345766322700265650ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATh՘yp?ϻnBBB.!$pJPA:*mAǣ8EX*uduŌN۱cmHĖAA9H! ^Odrl9a<3{93+M` 0g\ -|9||g`&۱i۶*>,쳭X͖QBmk|:"sty|l|}DzoV=,-m|Cy,au7̸C1{M[W~9^ Y9g`F$ŽdrO!Kܳl'NwlNDL(eH)HVK<υ.߁|6a!Ā WdӪR:So+5Ogy8Vú1qс 4K(;LZb0CɁѤ jJR8@I@}3J8tR+g|i ?ϴ]~w{YW3o!H dz8ZEy8N2ezbLZ7=Db\zϘ#R 0OSK=ǩn.E8B6Φw9S(ǚ0R2jiq̚Gn޺ksUloSY_ Kӽ!DVӦTnM_+<:p_֌ؚڀI+):Ƹ# &sIO6"6D0-iW\:\lwFA!",3uT'EWXVAqZb xzl0H &b xʃlE2r\k%CJ?b|L)$#NlB9~>k_>pa~CG+PVV6luX^xk_aӝ:2\8B퉎3#?,mRѐkLW_UY(2ɡQ]* u$Mm<0\ukX~:saR͟t7 ` R^g%0&:43=j1"Cm-l0-z p4]n5w5YWˌ^r^^a5uR2PJw+p牢eptf`|s$ y=[kIn{/ټo뚩3PH+_G=GM*^dҟd|̢( =49Ru s/9Ę)P:L̸lmϗrj?{ͣ5< !vpO-eܻh3v,J( X0 4š1?~>S̋f6p~jC~4d==7Di*R%u {N;lAMzJ.4'\C|҃S`R0`5Lǖr1FUiiՑxg2dN; v~C;JZ537O[Ρ*yĭDb y/گs$Obu!myUX30Y#]L<3'Difv։h@ae9pU2Ul 0xANX&z$ʒC!AJߧ!yGRJ(^QSBI}.Fr9 >!1a퀢(H)Q  !4)PBLB1nY?GN XK cąD~w,VB&0)Ӧou]&uSK,2;(W l/'Rz P5.L7 igb)=]wt KckCx{K"\Y:~ ?ɪ脿IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-ft_stopped.png000066400000000000000000000024061345766322700265470ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAThY]HW=.lW]c[h)C hְ4H I}-IBH>)R%K/1E!ƀ]w~g&:?q7\v;|sg D O /g7x| Iء(mv@`Le.iY =]>bTF<}6.tݷhk!I;ey9| bոr v6} }CDNm.x$--a ,~g'<*]ZD$9 cc PaO__j'D Mt/ $xCҦTy-0~끊,c" P6 }oA+j.IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-gc_invitation.png000066400000000000000000000065601345766322700272420ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATh՚ypUUǿoOBYH$nnݴи$Z3v;5.5] 258и(DFBB@X@ws揗bW*^սg~sUc \o7J4Y)6 !Ir+ϑӚnԪ +wx-=4xicR;4-B , 2M0JmfY3MY(D ڗ.]|S׽nDB)q 1`۶8.@ DQӧغXhhfNaaa.pB)_=s ReY  $:{T5 ۶AA\\</864-h(kHO O1SbڵWkHGYYoL 88 !,,vsԴU@Ew,SMK狇8@m/>eXv^ ay~IFf&gc`0T( n&g$ @nn`h Jc! _ULm[8{-=mbulۂe ؒe>81~xV{<(JUԶן P0FA)S׶-( OADm]-ua0 cBR` r -(GUע>֮]˝<}uϿX >++b/*B.{ DyBs'mG@TJ -wrVv-K&[e P.|s'xjǬ3wf?(i*D][P< `ÐQ: p >qMB<Zg.zL[{<ߟ4ι$ 8Ѕ3fOCq7w c1#\P9PmA[\ɯko$no|Sv:H wOH%h5jPe3r1j* @gy;nQ> :ULq R0)#L|:%!}l`.> 5>s W?E2T)H:赻WVt!FP,CM'%M a/Z;QTy6]8R&c15qqyNlBkWobL3(m!~iRT ̩}`Q);l6`}+#&4Q\(h2hרj=Oxi_ٹkݮq^2rd9sf. $Q-MuCIN`)Dm2l<ɲAa((x" փi:i"B\,&f N(:@4Q丶"HٓQ<'g ũ1TED #BYt$ 8::Еc&!yxBXkյBXv7uѫGWM9G{ ؏e{"ZP~W\D^ Rdq)HٔԀF|}hnq ߓF)ZS7 iOv%ӨJܖ"i`^$, Tҷ!4#@z돕Na6KJbE RJnB7,{i*5!F#`h}+cl/V>\N( Qm_Bm:VyO y1y=B(RJ' [S~Wq>'C+PQJ|)}u['a)KH0r4ݴn߸`m%\vԊi ;ob;dɃ?X6B _Gh=ߟ~;Ih~k:gk3h -(RADQ(phHU\͏X4)-FbP b{2JFmR:trz"A(RJ 7Ŷ#8fj"~ȫ>Gü?EMijx p8Ll;cA$ٌ34O}K$as湹+XT'͔dLwBL+i(eeM0j)++ceu&dq>~b!Ki`vj%eC qE'Ӽ VL' TMZo[xS|)%ok+E',+)0,--U՜l9yc ,"0{Xp17݇/o.X! mۂL\:ŋYXC_3 /Ndz"Hoȓ10,'p7jfj  V&7 CㆵT?' 9jNܽ4X^醕Bm|nK}GNrR{6!v YXONv=HVF! y<^*,rNR^RJ1=uuL:)+L %tB pٳr%y/N 4-\.7=eK0 (M$ ˗k%o|YY~dt[nƎv[z2*"|z?tvv:,d?mZkJK&trݔx=>6o~|r?!$shooL23LHt*$p.@zSTTBo00VяLG~큙. //#GPx/0Bi?,`|ǿ~Z:J _!ՠ_|^;ib' A }?3ZGa豈 9Gu0 4`p߼AMf'N_p &F IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-priv_msg_recv.png000066400000000000000000000035701345766322700272500ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATh[ls]w}\4\L1QHMڒ4}!4A iT}R0 -)mL"`HV HIl06^ww>q]{q$#93;"^:Fq8Xk`50kzID|k1Ǎ4M[ .71@JmȱB={F<+e1WY:h.G<-m4 EQyqDBl}\B說J*L3[Ftt݂iʮIU#Ygb^b AD Hbp;vp,\xpءt9yo{YCdgOOz7is}SOnm))C1dV'ki=r a Gt]G4q_ $'%Od 0Pukt]ڈR0 ?5^tbJ #j bu,]jWTUS펜XUZmRUK7o~LX__/Rk'}hܶ ͑Hg㇤y߲n݊#3|֬J9׈By]sgfwҶ~amoǦ(o\= (|sg% ֬GpxB\`HUk52H4b+(vkl.Ӥf'y))\I<0m7XssUWGW]]hoӓLQܸ=ۈRO^o7 }Y6EVP@W]P}=Βn:n_:w.` . x<0q~l omtt#( |tcװ;OnZ2ދ8^=RMӤ)%SL /pzn7xH,.+%$oHFz&!yHBHd*+A!@$AO-[q:]L0EQ+-1PΒzEegWZ<vuttuҿ꿞#˅&1jj*=󑐐՗FqdeBpj >ɓ`FDtR+*h :t_ ӧfBEE캒WSq|>[>n3yTUjbRa!ڳϢ* p ++kЍA}ũ!<ׯ6AԩS5ab͘6B2i>ʱ)HEGP^H);nll61v;EEE I$}KmQUT4M 0/ASuW'! CK ۏ4YGE(b6ը=u-D  m^4}e/=HB`~i>Ddw_ɡSUϷe6!C7)(vQXX8cvAVwȾBœkk<ǑDHnv5uo珄65 H@QPoՙ3+[ZaWpw@R8xbh.~QD!la,''n_d%B89|RN!P;|L06CeER\T>/ RF Jcf1jr;>9!h&P}eVVY t(cqFuIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-single_msg_recv.png000066400000000000000000000032641345766322700275510ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<1IDAThmpT޻wwK(IhJ@%#%ZM_tԶ3/~)BURy3jhKD` JU4۬=1,yL3gν9=sιsRYZRyTk ՚HRH6yJ)UB!i<5CO1PJm;ѳoQTR={F>T?F6_`%ǎx 5w ]BS'"!<<.R}XVðͩӣ2 {GtvE\ukDC@?6Dtδl&}ĞU5M;R%K3z6rrr BcΆt]0 .\::;b?ĕF1 [GvO`^~sp(ڸ7ϟgPVVmawP^Vx^zz{xۜ{&ӹ4:_4d:.ta[EgW'J)nYh-|+_'Q(V˾:6Yd:r7($R*T[=TNXOqsB">u~D{g0ϑVwoǮ柄e':jU!p߶e@kNڊOu'QdT( _qo&~;_:嗁R*\H@x~ng/=V_s2JWG,ֺK~qY`>Vу" m6=f+ȻiWՆO55S+90ue~n0<Q-P\{So-pg=umP Tcu R1~$\̖%\9 bmˎй}n0Q!8ᷓnyTk 8=!IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gajim-subscription_request.png000066400000000000000000000100631345766322700306720ustar00rootroot00000000000000PNG  IHDR00WbKGD pHYs  4tIME IDAThyygfgww>!@ BXx[ 1v\)c9IE#;v H։.:V:W1tt?f+8Roꫩ=o4/6<  sgS<յ:nlx24uO$dR_?8}N!6<7-ok1E.W{o u6<[ܢh$)Sxٵ:lx2ҌƻӮGN>%[XϦ[ٵ:^%QE5:uu-ڂњLP,)9b.h;|[Wu#.>8/4a~(Ai &PbK+k:ݬ9׿8&] 3fˮ5_nx2v , mr :iz@,$&jȊV<Կx ]PB/hun*IdB-rd ?rcK WTRp$R;ڦ>|j"l0bfc̛|PBzC;b0-  ያ[ۦ !2\y{ˁlɤcF}IE.ZEOjFBqx'AX$2]ZdFZ}UծdT dK$W@ȵ%kKa49 UB;mH? @<hQTz DA2ᘲ2:ʍޅwC=}`}+ :BK|ϕ-aDԓpB!!w;wr{0@EsFb흦1`Lr:HXkt Ǐ`b3;\qɑD) ;bR(1 bԺmFԵ:Dqel5H/󅏏yl0KJP$URmES>G~wT @<ߥCɆy7/258i T%7aW(")TTqr={Ngͬ5đi&;ڶbE =C2FSeUUL+E,,lJŜ<7X΂B2?jic[ww2﹟[.&${^'^ؾ>r#&w;]T˚b~H>XU(C(BE$>FTYql[4PC2ߧNk=ćo#{G$ɔM2m#G5YC@K<$!1QYpTYE*?XdY5_S8AД+Nms.M2LeE,^y.]t2@>*ؘK'$P%IȠ} &ǚG?r纺/G~~|e?^-)FX/Mh!1l23b#$A!#Uъ*01Tvy9Ri*яpףYKI"6>矱8{6ɔSVW!ҋc[2?8] dAUg@1' .+68^]\2㗎Nf=ZZᑿ\_=.y鷛X5ZTM5;!&vދ@~TM=ͨ٨2%H{vr܃U 0er⁳knʤoE"Խ.|PG/V(~bsgڒe7F} <7W2 %UR&P3ôfK\4ayGTUW͚]MV1wϓ=<~o v44;7/ c2h:_SQ;Nwf k` ky~TLHS~7_w2ܙ;v<{UǙ~'j2ttEbtdé@U(. ~E>ٺOL h4g7cZ&]vE'^<;@| [YW":9nXp]X*eYl4̬dR]8Eׂv=h @ETSYC##}Dv,o6YBfpt$R׋4MbU6p}(L/NI5^lNf±f N8%ް`}}AH29L\pb|mc5uŚh1 V) fȩ§= s\<3ၕ+ο]EĊ7Ɇ$ 휸t_auͅ׾`6hW߹7t8D>tEXtSoftwarewww.inkscape.org< IDAThyt?KVr! adUQFATTa={DMtFkA֣(ԥS,PM7 99ryyo$!#c`Qv$ca+~$K}923i%kZNyie Edr 3"U-zd .+ˤ!) 5ϪsêɊ+S4~_N=]b7ۏ$u6^?%&LQFOO'! L_`"y嗕_ڿGA* <m>eqS濞jo9M+iĉ"t'qcx>->+c{~UvB)@A؀n$/]nZp/-_l8$iٲe͛7/3.% $ ҆I0&! "˂m:Rs6o޼T3$7ߐ+%7E.s-xoe4ȱ .١FL_*?,o|iW\@2HMɤiXm XP($IpiZ[o R`nl|qv:$H[ˈ ?"E%Khܸq-Z(\__B$v?3 Fu_Ɉr $OJxE , 2 n֪=;;_hEEEt?: 5k䩪aH\2(nw*H9(H>^@/lc2BL'xsK/G$ǡ6\\\>2oM{, 3lRD'r88 [nvfS̙v1¯Ӊ-l[~ scfz׮]f͚m۶g{UTTDEIuttnٲc>J!5rrL̢wr~ScSߡJn[$2{! S~ܻⱖFӮt\4J㊢X@=ZخEP O(˛j]]O6m*%K---nĉ;wl[l{5"{/'͟:C_qѤR(۟2Snj6ʦN`2"%O!nP}+%zHMֶ'?ܲ'5OI}l6cw`VlT^<%`ϙ3g#04bcPUpߛ힒rK#;dB CwRvmlbF"ޯHmkF+z Yt2M\Fja&^mGEc$K\t7*}/$gue܅Z8ej 6W|\+G8S揦#W!Q ڷએ~n+o_K?L{oRA5i'E=YHIv23bg&#? ɒLP$yxaa6~ՇDw2E%~A4Ka^"LIRxY'c!(f9w @v$O&$M?۵rvlN+|ULfz\<.ӧ6@oU}3n DB '5R_X71&0}{T<.x@NT!xS(RC`Is}TEC1?1m%u+G ,H؂`K] Co)SOVX6:xT==^z TuE5Ǩn@Q4<^jdGQs8 y3@_gMI@v0~̸Q,M"i ?#y:CCש)Ul{-P-@H۵4%>Z㸭zA~4?O_7Uhɏnؾ{J&q 't"&}W?cG:nr+uN?N*[ۄ؎j/-ɃN 7;kCLځtaխm@ŹJuB^6+x%0=:0GhSAYglpSidDWjJIYn1kn'˧dng2P2"m=:ɏu5G;+-]"+ډ̵ ` K!ޜiDY"T}5saղ jIqzX Vژ0s)NSZHč̥s #UԱ]/c|iDQ57sN}?PY]_וw&;^IyBb Sr,̗l&s iaa署{a7>,KJ,ɴ9a-h9-J&~K8s~^IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gnome-offline.png000066400000000000000000000014721345766322700260420ustar00rootroot00000000000000PNG  IHDR szzIDATXKOQ3s)Q*X4$Fƍ&ldʕ ~MWBiHMA mR:BMM XkO9n7UUU|`u3Jˬ+ߏҔQc.n$iZVtaI$R )Q,¯X˰GXa5> R-3 BEVzrpC P*]ccWR*oK;)´> nܹ񴽶r @ȍ'wj{)^.^ÇMwBss B @g$B[[ nZ[[>iI tϞ=9L"YbR C`lpr#c 覤Nd8a(n e)xk2l{9߿@(zBc@0<<8/t)<y)׾~}IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/gnome-online.png000066400000000000000000000031701345766322700257010ustar00rootroot00000000000000PNG  IHDR szz?IDATXíkl\G9gڻ ₠iVVmCEA6*@H !J !DAMmᢴՋҴ-'8^vv;ko;ޘ4:::3EkM E!W= qmAw~&_ .U@9ȓe0]xR^<՜TJ%{h}v%c/} Gl쏜xOK_k,&(E1A^L(:ȉR^sȳޜ]kW]bd3|n ;{ajAx䝃_ɈU1:}nYyAFڞ/{X{(<lr֒/~]M AҪLO8B2~`f⹊MAfV\=sۍp.se+c;'(@"1J9,# t]ޮ/v";P dJ9(%jZW;oSN  )*bGbl]qvҠFqWlRĮSBz`}R ^a1~n\#biH"."=ʈ㮕U( 0z+b @M2([ibiÕM("F0J+6MUb@%  %# Fj@ ARRuh+]П @|_14`A]32,@ɲ'Oa87FA)0fcD0@(bLlf%33@٢B)(tzٹ/uo9U5e ,p=?;eUbY<9uq7؆XjChG)bhQ M0l;Z~Hj&\넒Ύб-#`ru]V?{@ c(նt~?;5/'|AZ@ө GPɹa%s@V5=Ugp'ʉ96`m e Ծ8y'p_OS:OZt!\*>gॣOLLuy߻F\a2D9鳧8I.V] f ݻ_8r S2H:#IK;K bNMIiRYRsn|eבHlbcfUfSfKTN~:H룷;5QNsnzljJ-{w~OCBru IRϫ='@[+Sү&ΑO:-SKr|?uïfm.*`0 :n'9ԧ2~2~h#ŹP ܝH$^߿J4~ |Ԏ 9  ,زBF43jko4$IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/goojim-offline.png000066400000000000000000000023571345766322700262240ustar00rootroot00000000000000PNG  IHDR00WsBIT|dtEXtSoftwarewww.inkscape.org<IDAThAH\G)w) o8D+Wt644v`,3gGT󠹹& T !Nǘ~ommLMMt]LhI<ӶwH˲tfaayyyp\p8p80 Ӱ,KiGm .,KSm0;;{<ّ rS+++)RBTR3?SxN塶VNTR?c He,..F~WUURK*\)$H)MfJ]M;;;EEEpFlll`ww7Zʥr}}=rrr+ߏ333":/ _ !r1'|(81t:9030"a 0&\.ZOwU> 2$Nn !J}>ߞ*O*DMDэc@GʮDF#{~xY>wvv3/6Gp\Z#2 mcccOeHV[[[p[Q_D4ЕcRKa=f~ i3U+m,KTؕ^O HRmi3IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/goojim-online.png000066400000000000000000000014411345766322700260570ustar00rootroot00000000000000PNG  IHDR00WsBIT|dtEXtSoftwarewww.inkscape.org<IDAThOHA??CDFuIuH!.JTtH#$IoAt%K d4ȃݷ>.`ofUe=GMFuYGu{,[-&1S)q. "e3P#?0#x;1]l%ėKt4a,zz <]:k8R~NV\iiI@xRZ [ȜPZE|8aJ@e;EbQZ}:E(Vk;O꤭PL&%aE*km (Bi 32!CK5iizJmVc[]KH+5$RZ{c)_.Xi y4;Yv}7; V#l6%[Wc-Jk*+e57|{j(oХ99Vu Him(o+ܙأ=4:c+)nTGJ 3CS,r7f#048w?0r)H#>#v;{L{Bk|F|>A}\ n8)nt餆166F]]] I+C<]`MOI6M5nddDaNOjsp6.~p*sEww7SۥI(98>" 555F:::R&-ڸ^6,2fjmmMIKKv{-s,\( Q]]ק$ 7P-n'*&xϫzQVYYId0YdCʨ<r\dZ)77wJylAMi |QFL&T! &ܒ Ӟ4HViēVpq+?R}^rrb[d;5s"xMJq9˃fhL<]|#fcpn[4nv:Wb+[D7ߘ=Օ%r|s k{";w/E Qh# ,+@On(?S6Q~gJQp`T_YORv D..4;#;'QS,3c0 C+l4Bfg&t-AvW6v/Fol]ؚnY@5x Ff6p*&YwF!0̂ rXAA qtkfݵ@\Մt,ļ_ݤ;H*!VV%9ws}'DuᇼLt]Ƴ?d|XUB.(fEE9|,\0R C$I.;mssssh]qu?E"eYXYYI")**Ⲳ(P__ǏTUK{o޼ I 8zh_\ti@݋0 ?sƕ+WR À,&1##c=0ڸq" `۶mY-aO&_>t4550(--54UUSx< l0iZD"D"4 >}:222Xa!''' oZ!I_~f͢YpHr8Ax:333G(J0 3zzzxbgDQLKHH+,?,uƌo l>s:{:Fu]wBeDEE|>}:Vk$IBE40!ƲIII۷o7'&&R qGY߾ (`f-Mt]NWWW~y٢Gy?*~N8FEBQiUUva*.]j*C__nܸ]۷sw^P?ü 0/v~ׯڴiӣ ;//('ϝ;x^LӇnwϡCbveLLLDWWנP(e1w\oa ! M8W^Y1{֭cZZZ kݘ9s&xOp8UUU#"졂ؒ hooGZZٳgy͚5񝝝믿XV$$$ 0 77d0p8 e[,ttt@UU9>>>g۶m|ww74 $a…,!`ugL?c\kk+'(v̾}P(D+0LHJJt(B<8+&&.Kuݼe$I#rŝD"HJJbYM!e٧px$Ihlliؽ{7ǁ`00uTB ``4a0( }rrrȔ)S-`2%+2̘UUȠ^] O<ӱ~ȲT MӐ666C#/j4Mk֬=М0*( *++#  :cZ!@0DKK 6n܈HOO;w.֦ `F| Yv-5K ::/SNɲ;m/߼ys9stO0 ܏%숞dC}}>| n}ӦMCKK˨L&A3gs@uuuݨAyݻwv;n2nPUw6n 5!q d&d9_Bww*.-V1 (l60 j|G(>TUU1ڼ Mff:^x1]TTF|>aahڸ# L܈;@Uރ{FNFxreLVyffy|>ܸqgΜ ܼyWMOO?s]AH`Yvi,Ybbڠ.;B׽Ί5jp8`X0 G4g0ܢ$2$I뵕mxyyypxGuuuŨAS<ϧ2330 h6p(|&zkx<σ(~:65˲X,ذazj\r'N\\9p-30˗VXA)>477Cqk1%\9u EEE-yeY,kn7l6|AXVѣG?)((\^^?Xrw|b y&DQ<$$$쇪@HҸ7{nߧ`ҤI 躎^"##s1(Zp)2{ٲeF__߄`ҤIK±cM?8!qEx:(^rOB!|> CɠBHzTTTh4rǃ&7+00@QAHn-;( ߯E1)Sz;Yna*hkfĕ+WsN_2kE`#dُf7^}2B8|ׯ_|I6-- ^܉3<ݳg$BȘkEnرcxga0 Yqj9@\WEBBfGLL XŞ={jii)7sLtuuuX,p{;C Fl6߿'O͛ 9hgZQ]] UUٳgS,ۉx{FTUU.]ӄtuu^&&&(//_/// 6xΛfaƌe?:uT}˖-FUM677#11DGG :9Î;8;w@rr2RRRpF&MD""a>ݰap8biphkk ޸qÐBvQC}7n-˸ipY??,IiY֔5kXfΜ Y,nߌAQgԴ2332 {I Vk$  Sn_ /0nB̚5 <_Eq>y$%%aΝ`08r wFyQg''' ,PE:::jEQ_\S(PEEE5ӧsT][Ng(//0L[iiYUQO ,TTT::Ư"DQ?νox6S֖W4mWNU.a1FD3𻪪Ξ=OIIA]݈hV}4Md( nlwaj~~?kךzzz$EAtt4꫐i(e>#--M0o"IMl64nlGmm-EQ$2hH$t! 5&&@nʕ+:M( F" PIII4q`:|>Jn8{lP?PE `4zuMƿ(`2|>> 'NHHBeeBH[GGDŽ*N t:$a~]w`SN␖k׮ABfD"om6۸ 6իG_~饗5kxGYYz뭐$IN.ƠQ 668vɀ$Ik].ݡ~c9d&!..Nu]3CmʊVXAy<B!Płhx<  *ozsq-Mƹ{t6krb^O-̅dX4TFyd}cE4ݸ&l{.71 |h 2c_}RpHd+ez|'t|4a0t!-!E׈3:aZ_7ؔ45 K hsO)A`T^BTujs||LN}4f,z QwR *b3%ڥ9t!Jbzo̥8M(~!M$aq"& ws,.[bnaJӟD74K͔,ZIuX]S&Eu?aUsPHo>wVo$(R >6kJ`6K*N^wB$nt&_H+M#A,o=sNXͥ9CV} VgedܿЧD>:ھ@w;Ykf>bEHׁ\ Xdn q\X Ϝ j*o<14Q[pqO 6AX,siQ%b#f6EYR0f.+Yd$=̥!.,&ŠLDAU1(b KUOd/1f[N I0P595(E6ɲhPǍE`/uCPb#U-$J $A$T-HX2;^(((M}$dN0CC%4m^_uЌ!hŪ$cJzjL ~cRD@備~_"l/%'~'!QѵO7rNq@!)s&%.rs; ᣦȐFX]Y 򃛷_bSn"Vg!≯*̹&GNVc[Gt5FE"i(Di q8k`X-wO弿3_lhR4ߑt>U{u}Ǩ˚m3R-=ZK5>:3͛ ͎YL+H]Sd7xTC4+Q-@hV][)lm,h%̚JfW?ߏKٳ Q"/ϥ{]0dZޑU|V;\~>˾zJ1~!")R.],M3$$l2)z,c좑W=Nk>p/mMק'$#9lVX>}NN#·+7?0 ɤc2b:"b8gAQъ b$^hQ/I R13и{{EWu,犻rW$|V|2g#bWupT!WTT;Kx&_{tKW$nh|8"gIUڛ3m7}&}\xR!|3LyՄV+cm%aIG"bi-&/i<򺤰逳gǔlU*udq 5^bɰkr,ݞK'fcԬ]1_]liIjLʌZ@s]=X['`?RML,JmTmJyY[V]f`Gh':Jp/G((!v mdR}GL]ӃU5o1qPVy6M" ;-T{]Vo'5**ڏ;Į\6=u}Xkx^K⨈[rA:,X3˜s#qC(]tc!;p~F.#g@RI2_'Cb:Pǭc[CԪADdd_&~b ~K?_0mkG[)X3 $3ʠ7O1 R:9cb}+1G抝ӝ7{y,O ,MD9瘹//"kŀ)[?A|B^kIڽN(1W^$w6G7tQn IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/jabberbulb-online.png000066400000000000000000000026071345766322700266720ustar00rootroot00000000000000PNG  IHDR;0tIME iebKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ Lg{-m) ! eLe \1Pl\9F&NYl&[2&oK\)&+7ֶPvήJfHHrhϭTkdVw޾Sh{;^.wH8vlm]7W!?H--zJd^x1^oV ܷys{ Jn(d66!n >? mJ*+M+3{LLtq`K^8~3xt^A@8{NK{-,& r9m"7wHx>'wrjSSk!l M"#G}0s,Feil>e=ɩJL=5LZATEFU RPHh[|( O8v@&3SxqK.;ߟjkʀS9U,J8fz <|߶F CKmlzXZnL5 e2e0*7j-/7MJ̴0cb"$\Fx>;C#Cu-ںQҩ CW*qni[z5}^^x DDrD2B\J61u3P/jm?Ot:k#7~=n"k6e@]^=DCM驀.K=ܾp V쐘ECxEǤx;8CD~s0`mI*(^CG/-(X\WfURRU!!~~UCC `FGap 5w۹7WD8 oo#*>_u=Je5IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/mrim-offline.png000066400000000000000000000075611345766322700257060ustar00rootroot00000000000000PNG  IHDR00WsRGBbKGD pHYs  tIME 948tEXtCommentCreated with GIMPWIDATh޵ZkU^1{̞9sιnvDŽ&!<@-`_-Z@!@!A(>= Z,-g" !IEq$I>Emj"6II u΁y,ICU5{\FAxP7t:=;L?Es+'lͥ_UJ=^EQ|immm[j6ZEQ|s'h0_Y]]ՏJ)L&oN&{g}UU M:zI6ƤƘUU5|>3mSJGB_9?ͳ97bq* uB9G7c>5NO"A(10 oLH6kkվ(LǼ4M&N83OayߍZ(_JB^q[^)Sy7;t硔A?(tPuB 4MKf#<MB?G D1h= VYkRfׅa0 Q7ks?E~) F9kA"~X,NihB|l8Ν;5 -;chsI68Tߨ<7sPJwf1ᵌ- +(?<+(h4:,mG\JykEq˜\q/'D- + RΫz3k x|꺆/2n!mzCJ)+Rzy1p9a_cUUTu0Bۄ?MӓyZ[#o\[[[m+JcL)1֞j`=%c>Q3ƀR6A!1v.DIͯy~9WcoΝ;tY;F PBmBa!Ǵ֭vt9}ާYX,>Mǚl1^UU:WWWKdRڪCEJnJ}s9v-0RJhke,' cTJ(k-hfݮD6rm&F]wqqy!hOh$ue]86|]ǥy@s-KshIH _{t/PT繖$үBH={ն`BU0BCyK:^uc-zYk͂Z1cs!DK_9GGEUU/tApE1F7U_Z";["q mdx.>! qmG |?T56ykBۅ[sUUm`sy]ׯ(G& JZ,T!n^Sa`0|@zy.B2 ~sNEq3:Zrc Xk3luRj ! !'F` F]Q}t0`08e]׳z `%I[GQ'RIt,Q%d9Lqe@քˣy9R/Apx3'V!L\zc7Uq9Ac E_i>-[X/kZM9s>fu]9~<˲I\d!*:M4>ڵnk$;YX5!!vq㣫Z;pޒ'&10ƞeݽ(@ ݕ!Dp9 CWDZTUQZ[cZ<c ߵƵOQ|tz1D87Jj!.i8*McιRk!ztc /ܵu+yxyҾq||\Ɨ0fa!D܋2BhB<_J)5g ca"yfEqZ{QכhJ)bxx>l6{Tkq!m4M(FWVV̙38EQZE]i)#Zrh窪z(Ǫ:GaV!ױTYѪ~\USJ;VJmH)?wU9a?677R\]ߓRpXMfZsj:q8˲G˲|c<y޺bu8yQ|;|j ́Ĉs~̵άkf?2rkkmbx'aYy1fNZ5ueٿ7,nb_B)BZKuzSu]?~ZJ欭G3yWtzz(SJwB !{co/|GK/u1t]gֳ&\ ^N^x//{.\JRoS!޴1R\v՝;L]~%u0IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/mrim-online.png000066400000000000000000000064561345766322700255520ustar00rootroot00000000000000PNG  IHDR00WsRGBbKGD pHYs  tIME 6 ұtEXtCommentCreated with GIMPW IDATh޵Yl\u߽3MH")ѤD-dYvlYՎqܸq i) P ]^EI PHѠM4qiK"/ZIBFNN/p9̽=|s#Rgq,} ˜;y;7F6u׬EVȢ𑂌y&͙G!\+PteڢW~lgNEqY(Y.{Gdy0ʿ]7im=v&ҥKVMbu)L09cqҐzhPb )E~% ȡQvyr}uXr>!|SE')S2ií^uhN ie"'=K91v#YNY4j q]5!hT%X-j]S-'cNܦ_θl*Bz= ;uj sUtѬ͘IʿE"Y:ukZq0as_|)CMfGI7jG`شC9g:S&M"DF:tjeVj+A'Rjb4h7|ʇ}v+s{Kz!Ow>Xj>ZZ7$K;;qkӔ/;' p?3jZryȜ𼔠ᮅ܌F :9(ڨ3 Zu\2 gAGJbs{uT-8Cu5mRVOgLRŸ"F!W֧=jނN8 QV`u: ?ۭ<甯? EB)f+"$Lr4!|W4Mҫ_[ݥJMڜJ x{ܭ\/zcxVlzbY 2Oi7R,"zs&AOn|M`;m΅g)>_}*KVxŘoYo>6ؠWq v~a6ZSvQ%_Ϛ{FOk9A&[ۮD!@  UX?Þ$3bmv.uVP9 z+ &͸Svcn(H6yy,,+k[ݫOcEu}ŸXawMAV6$7/VU j`JR($^ot6]!9mls'Տzz=y?p-U:k*m+.9aIUNZ[e4X^(\i+ 9o`/~<1u(ߙ^)S6ЂL jbİ1mޯGvJ`!/)Wh;ЫkfLJ9UFKUAQFa!aVuc}JS] ։`]6[/SxƳ :\Q{SiU(=⸑̋vbVDrUAfvTR΢ Cw 'AO\@YMu:t,Ȃ|9!k 5B崟t_dE`zTOxγA'U=#x(ݻ/pdق()k]ަ+D8d_N2|9ɥa\[{XyǍ*{2 j,R$[3(VmR;ahI(MU tO)I2=iץ>(TqQd!@\Tՠ-%㚍-DL/[2+3&L×ֱ2%LNJ E+;zظFU8"]g~ 7B\тdID2 (!C޴s,"DԮV{lԻR4kܕXvfCŎ%W.8h>圳UٹANǁWNj|Eh-ߢ-1U<+)E1U ^|Ȫ*Űs3qN]T,vM[2wYLV){װ]hŤX *;~Ś%ֿ`=j9&9ox9jb3Nj7Æ=CD~ƭpb@G("U_[hGܖ)xt]\R`k:UZhmu:h*$!?qԠnUBܨۀXFLr⎊̈a?EK.o͊Py)K ֐+Ɓ& XmAvj>Lh[Vhn=tɘ yaW0ZcdPX$E=}->howk.5z4Vfk>[ `B̒ҹ`톐u[oqofA/U\nQkj5NZpO[W9Jd#zKN95r byYmQV.7YJeXBVp% _)*;-ϒ mny̙5SAҵ,:+4QLӀuIכ%Ne.:kB5m5bIF4h>5Zur"Ō]q Iu֐M%F ;F\`Vmͽൊ]z(`LqÞo~?/;'RMnvj.9 5d2Y1)1Cx1vDRUL"m6d~{կ[f )޴~œ 8;#:uM~JUӖ6ͺ֫M6Ȇw%sJD"EQ1#F]P4r>5_{˗?*QjtT:bԌ,]~a`!^_hxIIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/sun-offline.png000066400000000000000000000036321345766322700255420ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYshtEXtSoftwarewww.inkscape.org<IDAThkUtLh BH@E B"BJ BD)H,@ /0H)? `Q6   b2$q ݙGv߾~[l=}1ǒDA  0!f2!&NN+ŁUk~JM2 "2Qz]9E!qBYT+%PIyP< f޻{Ӫ0]w?(m Y|P V28}%c/`l؊ϔfwFW~ޜw~U`1VbNJIP+hoJ<%OȒ ߌ`&<<2gM FRo9ekL&A):(F 2Ak|\Uk~ݪcG~% /Vݭ0];P-G'X -@I#;Xݝ-&s#ҹ@!vägΘ^RkɈngw˷0@pu!ځBuĭg!_l\ӗl؜UV|l|?!. ndCU;+_*r~经-/I3˵CH)K`솯*'vrm$d Sxs0Oɢ&5F u;j'`uMkbo(x7F-nmaK=O#Hĸ OlϛrE;x&sz:i/X,vj/XwOⴖ-xHqR췾Bˇq/95|~: rD5mw[N2@@P׎:Wr?TM<1Y<6z"_hJ䆑G$SDO!^OoǖW[2X~sJ/:ܻm8O3:!>xN)֪紝?j uPY/@)5 0 Na&1 ]uNәCs~Jz{}}8H/EWU;?/> L>D`OLT6 RcB0[m 2)nc`@IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/sun-online.png000066400000000000000000000076151345766322700254110ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYsEEKWtEXtSoftwarewww.inkscape.org< IDAThZytEշ=yyI^6FnQlpCPGQ;(*Nӭ8?OΙ6ڢF((FA߾}K՝?^^LsON}߭W߭{oխ/0Z-^iԏh0(5n޶L9F@|k-rI[!_<##䮵UNm%I${11#^ɓǞe@:1t-J3lBi? RyUwn-Q[ k$FB̨32+ox]ɞA$v@z_EfdM9DQ% i>G@2IiAeSKlV}j=Ξ dm{z>Zy9-kx i d: iCG=[z>3p2.GU\?Sd<=~!Ր=c! $]3h (JO ~9\ƤWKAkO ,rNψ3Hϑ5t7dlaqvJ뺶&>EҵČsEQE &/Ă ;nOQ'`w~>n]U@ p] ;X3ڟQ$^[㙘.L)~.o_ E{->d[-B6ޫW^\<;+m( ɍWAL.cg2@f2tq2V ]Ҵ+$8g)h - wKkEJL Ld;JgPM L?m^?L]@N`yVJN7aߕ\ eHj@*H6:Vglz(\,䶚Şf^N lgs*taLZGVtS^72^UWeU8i{^UHdA .zD*04H` tw̺^0^\3"w <xD{ހ刄h1x`4Z(شNN ddţC$Q;^D=G x|3죏|{63VT~Y]< <' ;-xO5e74 ٭fKBipa&5x'u Q/z!@?É} S4h.>|`5&U~t>C ul4ɶs9[t3%r5Rw'Lgx~g G"{NdHd Vw?fx;xڄt-/ϛL3igu!@AB :ID{. S-YBצ:Zv-27jpS .Hm;ʷ(Z(&qr!Es-?XF@,lRPmh[6I@),+n̺5;hfcrrNZ7%_yU oPK\πw)WbcgP B:2k6$ߥ  H)C/fΕeU&՛jkY57ڶ1P\Wk!r=J;F\ ѵ揩F0Q(M J {cDi=$A0 f^H\l%[ ZݞZR;d$rꭨ$&g?`8HxdX"An* @,M86D̳v[NH*GOO{AsTv+P|n(>7/LQ@<}**hS{Bq- a: wⳏ7mv*;՝>kMgI]W ,OwWW.W9Wv q"I~ " ?@D[(S : N_&*jL<$KŽgD&N[`wRf,TLx Sw"EAǛ'Oyb$zB ēy+jKŋm,;(iCVdʼnfX,T xvf-'BT[q`9zoN3%KGcCaNQԷ [)9ɮͣ>p\ `{rzrjG{s&Lؕn\Wh=YޘhJlZ#:g$zz=K"A=+%O L<KBh&W+f 7,K,GccEk0PJ6'׼7"]o IH`=p^ÕwSGt h! sp9woudSY P'`W{ ) uo1jR>9FaDU(H /owi1LN̓P1(q=h{XtSY- {/Gm@zGI\WO= ڿU۞'Xp8umL4mUX TL=rH[`|?7?I2<IBtH.UUǻ46M+n,\djr#TU|ʘ Q+<a~` SN 1g!=$MqR[bKb_< 9?ArIܲճx(uWV9J(WnThH)ý`t[x2\Izq,i(9;f׷0 n:"S#d=r)}Jٚ,2'VJc||bPkގ%"ʕ/dvv6&3o1{)شqӘRjp= H& xy[{O:yq,۳xȇ>qZ炑C^ZRi[x@yOZמ;`O۳c g~vSJ:{x.Lp ?suZIBFS"l]?ɶkX31cL@{_yWߎ~Rk_x`rbr:G+nfşɳ_RmB+r3Y?#S;6B ŀSO |ir[?]Z=JR49vx%f+QFaHh6u3xxq" bۆ@!*PB.^8ſ˗Oo!G[;0.y/=_dGZ$yu{X5[ I/peL`0ڠBkQcT H##Q^e*1 {=*SWBJRoﶱ}u>E~OO)ꍘJu|y~v2=(E3"6eP&ךeR57bRG?(4 (Lj- rspeP J-k1Z2ٳڀ2?y{ J% #cJ_}၁h۶{oV±S81LDl3*sbB\`V Y1\&0Ag翙C/ةK8+߬*=۶msoO=^[ f 56 (cr@B!dQ&z[QܕEz3:SW~|V}:wh<ڃx@{<}Gܽf%)ĭB>{KnB;Vߵz`v~QG_=B5sL:+}9:#aAFJhcG+@y5,{QJbvWO#"WRlmy>?cǽQ뜯[YHTgxJk֯$B+k$͚sF!g%tovv4J+?z:뜏q00ch~]Xk…9*54[~F{0&9uDŽr͜p q9& Bs; JQJ=fcw@K΃O%K%C,)N̬uYbW.EQu1g=J zuO^1ZJh zIB+RvnӶOA)F!Q`YMĂM3pse=s3>Fp" QHfcg2=Ҵ 8I?>>^tk节4,T+dY&" B]ZiҲMV iIHS!M%Ą$h)vA ZbV[?:[`g!s""މqg+u3Q( A1:{Yl4G!5LqÉ`mZ[cSV" FA(шwܬXXSo$DaE;k;W6=^"csBWWV*ܨ1wAT`o zֈ2gGc=sduI@2_iXkh:)xWWxmۓ\|kEPJQ,$V(MK#qm\kFhb!ڈuAxAL'ΓZhƎz3aҤTL]YVQ@i AR +B+q}ZH?XkB^4u1ZkHRb}y5Ak%I7]7/Γ 0"" !{OjVIsY$BæCԛ)yD2DwuNBxuKVsj5}Kuډ,孽J:fc ׌h XRnTRϷYHTFh q ׌`!  ~̵X'ZK1 pqNR<&GAI)ҵ*J++HROifShĞF~KhʤZZϚP_?  C8ߙKE濷tN?}mf)3sjZR*-7n:c$G^p-hꌏ6Y7я1}7c,1P_4q4kUt쾽ޱy'~#Fk[ٳg*LtC2gϜݺ+׭}(?;7b,Sض m QnֵCLTh&flD;^=9˙d )QV 9%XYjBrCS8N`r{vl]RoU 8rZb+Fg7Lo9 (L] S&q3د\_lqzCSdgڠՅGw?Ъ;6o z4\p,oWO)dleՙipFj#H^G׎mJC=]]/#ߛKm̷ׅvx6o+o:u>]um RJ%yߟZ xYY%?\VgΧi&zVaǦ Ɔ{:jdJ%QKvlz̷&z4u3筵|Bm-\xbţ߿,"iPA4y-OYb ;6e!k7y/_tFVZ|v~hƻ7 pڍ篘R&.ߤѲ@浢N?- &{aO};OvKHl7O3k\Q-+(e-2BYCes=sO?|U3W^_Bsuց{} cbWk -SV Ƒ;?'/pܦ'U]+J| ]A{Eb@hy4 4`n0,Vꍆ}饣W^nN1-!9Zuցwo,HqLMb$Pyop( hUGB4qgN?~;yȷIJc(['rt.㢦rE.o"&Aešrev I1mDr=00MLU) ;gDZmLM]/,,O;5@Ke],8mQ|1Zzjp=~OrҬLIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-chat.png000066400000000000000000000103151345766322700253740ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<JIDATh՚iluwyI=6Zbɖ9Ė') ZGqE~( (6ݦ(P R+jSE#)l%@JP+)R3w釙H+ :[̹#Ǿ{;Jnط=N`+p"`^=xХ_M`#@e :nΝ?7???-13^8x;&o>cxtχydځy7؉ɉcǎ^9rxxC }fS˗g;_14GJ)މc3Oڭ[j$2{H]#o%`m6_oMBEwxK 2mz&wV9 ~a <t죿2o|jRS, @xEE!Ts780|Cgn?2=BXcp$$_S^x  al C!@I 'x}?-ԗvZZCVqpP*%$-;:G)AiC) O8 w%jOwYf9@Ո{.}ߘ}B)$ hpH\xwxp.9[k#[߰ 0Ffz/şB"?ۘxtK`퓟}w^P. c#wǞC* Tz-QR6{iA36%Xsg-$}7:x7?&tvwOk󡁑FSE^_cZDd' 9qk z#䍫%Z@\{yh˗/9ڕK|" C&JbiccWp@ h% P@ Z-PIK?srOPNg1'RzJ8~6RIJfd3 ߷Az r9 9q?>KVZxdx ;,k7a*1n0+̓W?.kfg&$#O%P ٳ֑AI5k,JJ==]={+%=J&6%$hu8̤l$; PYk|\ؘS.'͔2Yj'^P:( +7\L;kݕ˗f[17 pקuc꽥@+]G_ca<:MYڻD___E:~o,,L_{[/K .: xoZ7^jŬ8tiS)KQ.a2{ws'߾8P/&ۄRlvv|:I|Z)f:Wͭ l[3u⸂Szij JѼt6]cj8S&Xo0r{ܾy66-fp1撳֏^p+xp_<=<:82s^ .=ףp{5 CH&Ek a:/SLe*Bs7i8=N,=dz'_?z . 't_ou l+ol_>LtUDN ob2}AdMݽk_>)k]+.,D/8>IR~J1}/\6͆u CӵlR$TRsE)4lu-[xg{빶Mqo}ΌEB hz뼩hM @= gΜ=3뜃wsĢm0 6燆Vv=<2XX+BEΪ+(6"oʕ ˗٬Zmzju26v<;;ع7B䧾jvf5@V3J٥Qn˗=~zl2(IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-dnd.png000066400000000000000000000102411345766322700252200ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<IDATh՚yl}?rI\!JZiQ]$jn:c-EQ@QmEEz%MIdE=v:v$;-G%GruP%QH+9;̮ԉ<̛ݙ~{{#}{ZrCx/ݷg :-- px~^?3,>lkkk֮Y۶xssssLǀ?xg ݷ,@_k=woNoS ݷgxh}RJc40@Ka:ؘ!:!c怯L`=/@ۓDOҩSwuqN5\Z1c Vִww3aƍX LL+c_?y؝~n1q$9a;VT sBE!xCt\A8^$h4Ih1JGOJyd[,׏|럿q`*V}\>u uqI@ˤ/$da1&8#-hcAZ}{L𗿌Ik@E-[W^ukؾ8\Na䣏~jBTK%JsshO3z$qW )qeLđ2Nǩ_sL<ɳO?VR !xOmc-gQF8䶯:A[G;KVb**P~҂*Rq׆%+{ih7V-kܸ4њr~Vcm1 -]lq0F3vX+RP1ҳ( 5&T0D!Q:a {#Y׏ro[SD( &k:t?7'Ҍ=)Xލ린**UL P B*nABU"\7E8),TK=UnNcHөF̵,fHa##}.!NԒjCğ  4: 1uXmijɒJJc!^zHϣm48RdYRdR=ņAQU JDbǕ3iR^i#LgF@giR^t&y2jMZ*MXkHGWWwcJY(ߧ43q$I&M# iUGq,!گOIR&*!RDZ3yUr-A VEv4yU}?JwVe*Νu.t'Y.|[/^Ϣq(X۳yE.|[l=)4Y܉U oYNwVҋ׈5B{]cw=tm}~a֛CRS'Nԅ:0_HE^I/R86F0Wzpnwmm0ʹvǎ1~ׁ?uo_;/6s/k}A›7)p(~hjz|EZN5B!|&n ܅3/뼛nA)ݽkw}V ZccϝV*w%=lEk<0JRhZ frdxݕH78r7q3;)iAZu`rhj [ G."%E=.@қy]k?qjhK{p`AP\0XնtF] p:1A*hK}XUha-MV)rHMmAEL+wπ-q ^.\s z|5|Pg)\'&|LhpʣQļY8ՑT'{e:w`Iz8no;n3#ԉEiA Ι*o1q6BYx<Y?_9s!hwzkKlDRl^9ZfK"<ߥ.6+w.Yzg|)=/ ~5E$4/~$?%j!-?u'S5L9.y3lٛMePL3Y{OFv}dFJ z( `mdyWވ]GﱚeIx?O.p'Bm>At(nj8^}j Jlq8g7B*<^ ؄Lv.8#= '#qxut\@ZJ'c5ŃLjr`ƬLkޚX Κu>\&dbYj?}ntˬTyjǔ8%'xž. Zǂv%fͮ4``` fͮѨx=g:Ru{?ČÇk?c߁Qac`&!IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-invisible.png000066400000000000000000000074011345766322700264430ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<~IDAThZ[oWrΥ{n EɒVŖE۲ n{-C80~H O q<? !wmyWwJrH΅TUᐒm@8twUSUg8NLO-|zA`~a]vHVXpۧO_41'UUgΝUhe+7W,h~S_‰]^p#sG}l333ӨT*XR(uys+K/m 'O-^F/F/H}wz uD. CfE"F`~nZ^zE)u l( 7kG{p N- /x>x533(-mQJ)p@Q "hÿŹS~i 's>c Zs$ -H@TVV[D$_NyߞZMX<||\x{&F^O;fvԟ{}+w$sZ<ēiVBHlj:xak(1X_VM yꩧj6@p4!V"`5 `q BOi*;uE}Jxx0"ar0ESz#yG/މcGw U[6GB㵴 UD"HT]alcy,@Sكame@{x$1޿@Qo,jf(jUL K,AϙA,ժ/ěg 8`avGc|=tl8Ojq sR i%AbxbxmD2ڄ %`?!o,?dfJYqsI8tЌ0s^@B eBABR`N OIYQNz fVQ.I %$lbR{l?15U!"T81S`af$@!.?c2'T!SE I4AsȋB2BBdjz:$#ImQ,XEB x@(Ty!h%P*XKAa{M#HϢ`Ąm= ^`+A1VX$ι`c mZ)3 41ITZ iD  /sHBCR2Tq H*$V{V+]]]Sl6-11ڱ7"*Tj ` Brȴh6U F'AJOLC@p+fiWWW` !0q(,4 JiDQ>  zD1 x PJCT(15@4x챠ýPFCH,"33pobH|SA h(\Nv %ei?5cih(D+J$  %N(@2@'".Bk1+#"a,ZF=2#'ȉ0*rY 0zXw#FyrW QAVP]%w2AB(dYeғmJK"ż$yդT`dSvJ)ňYFE]B 3KVl=YVhV. " D'8Op`._ V cokoW֝KMb. ?'nvzDn x91 m%`vz  Zh0TN@`vzjcm'u9 {AGW{KokzH8m6jB XXcj4qh4jS& a$hԦphMX8OF;ZQ׮&1[8x‰kk~Q7_1`٢׍$8 W`gjZE=!MR(Q XHc1s u:lmm5pl.׮]>;o~]yh3g^ ` X֨Wj1+IV p|!GHIH<7ڠ;[VLϞ;Fmklr$& EbI  )5\@=zmUʝeҬnΞ; /f~؟( >{l}}xF{iS$lԦa$Ӛ"ڠ:6 E~:] $[Mm$2%:nZ|}1+q@qRn6|mvb$@c-F@/@/R0֢T6Elpy :[YY\Gh@\x?s+_oUdo_I*&y%׶&K3`X_]]}[,^۾rI:N/Ϭ21ρ|kLOttRA5;>{'erxқCt:Nt;ž`?{45(ɒ#&&"ɲs9ֲ mmDnjfffGl64MMvEA^v;h4*w;ԟhU&Vw WH\&O t IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-muc-active.png000066400000000000000000000077571345766322700265320ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<lIDATh՚{p[՝?\I,YbHB  Y[1lGn;AC;ngalw! !љ6C@ @ @! ?%Yu9gW;YZ3}u9wGçAma:cԧ$hh[\ U@8cXwvlyG Vl3͛7ZXp^FGFClVpؽcΞ?,@{G[pK,Y4/F\s?zGMx4ضcOEy@  >7.^rU>Ɓ72<2DTڍpiUXz5h:z=G~7'1@ю;O}l;V7/o.K}q4 cw?KS,FjcJho`Ӧ?faBx |_~0xmW֯曾,1𣏈RH!Bb`Ak6/ME8|j;/}pwl߹[;n[v._j]~ a ,)BZV4_@HR$IN>Mg F --͗nWBH+?mG1YbN<ޱ4>IrL&OZ!_y+W^H4RW& zTjG+RaP2ۏӷ抉Yxͽ@W;nnw_HeXwlX`RL&z@ڀn|3PJ!-d<ԓAIaۀƥKF| 95꼏ݏ>RPQ_ Yg%)ׯ*B!`0lp^Km{²,`pw.buuc\/T. $>doc$AHwc F0HIbo(Bǽ[B&E)m}Qt&m˽f2FviMz5@ ೝ)k3.[ۈ\I0(][Ȟ!H#{D4Owme|J+ X!jv=cΔ7\0o˅,_\m{f3!5y3][84kN!.xpCLq(ڲkP! F|ysLz:JCGYƸ%M7^x!'Os/.@BJ7Pno`v)BП<+=OС]^xa(ۄJCX>T{y3/hYR2?XX4((_xi qE DBP/֜N.F2}`g[}ϲb%eL V/o`M"5 VZVTLzWhh8!jֿbM6Z[=,sHlZnhPcIPjX6b{CEi#E1Rhoȗ} $(̻|V`&1,0H*Jk Kܬ[p7Y ,6*Jk ۧ@0d0y=Axkc=SJP8/f PϲRJgn,⦦bB0{[H雖UiU!+ YMMX 1΢>~_w#A<6(ːrٙ|5 MGa! J xŐu|2aC[#( !@9ڔ@{G[X>"Oim'+S$\h| 0 Ox>*2XS=#ͪf*W3y"DdYNV*t$o>U(ZOf8uzt:j/mP] 3CS䂞y9 ^d%BiRF+]'QD2ik5Z8~6ǻH!,k:" __Qb-_Kx՜2tA ջNJ,iaY> @-N$tTz\*R#pY}:6F"t^1!z]Nl=l Mfƛo+"Jkm&&&od3xDR9J756,߮R??|Z@.6#ײżty7_yp}ɪr99BvW7v9+_ƥwϋ'/H +owg;X2ͬk ÎR;Ϸ#_^T*̝<[,\ﲬ9Tor|ͳ_Vu)7|wgn&&&.FI'JFFSL8wZڳ |ٴYt.Biٝ|[gvnlViJ9&Lvs|d|]>BYԬjʖps壏16jamTŪ&29ޝvlѶ']HZRJjkndڽtѷ8?Bc"U^DS96Oy'v/9BxR)m::Gs̳Wڎm,XPE?gNU^̢ʋ?>m}ePU*LǏmo9qwl9lΞs'I/=]*n톸m7Nk 3@δ'z|*_d:jN~hieym]ZiswGrmgΝ%2rSnYS~wz?pja mr8qd7\6pI#rضM(:D2ɫ^K`Ysmr9b;uc 3fZ**i308@Oo?}70@oo?1P^^N},F}XRF}*yWח}_2b۶9v`W^[/޾~z{Y,ӺjEVdYuщd2a,XV?7ER *KY0`qx 0lVR GYRLII =or`0X4P+eEO aFSPej~eŤ;w:֣##RqY[W_zRB03Ҽc~Eg>V"H X^/)L.SD"7>>d2?>S)Ivt/ͤ?O ?Osn=Gu싇IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-muc-inactive.png000066400000000000000000000073601345766322700270470ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<mIDATh՚{l}?3wH,G$"eSr-ɲbK 4h$HEOZȟ$[K 8ذʖ,|IHqwgT%v~3sAm5DW/byhh p7 u@tk0 g]?sjmMa`'X,fZ*lxkb ɗFYWS@GCߺ=|kqS։N2SŒ),%i\Xbd\WFҚDCw^%4cGc<'7ĒG 'B u;>ҲEMM{ʶmwPJc׾ 0ƷT.˙31==Z)Cm*į:/El_w˃< 06>y⩣eFٷw:DŽ. lOrԫ8RLӇu.ӿyߝ0;%0nME)mI./ $5|{ O`rf1`GxmKCOdyxxmכh>tk@K ysJ9.w!M vKbNaBcs\B#,GCQ*x%k2]1޼9zwVLS"Qz5'_y7GJQ9Q/ B*A,&R,xfikSҟ3ԩW^=Du"4%% e2)daj non))%0a2HV#´T%B#p{s V)dmҲeY!Vkb"lmmEHcRA -*>kQ,R-(ڊ@8zcFkvrC*;oڸs[+eΎrRe)f}|2(vp#}R&QS"-K(tv*/,KaJ"gaJY߄[N%.vc\ٰaz,1 -KD"Ft:ZWbff!ɚ$RZa5k =@/h[&t3_,Tu"YD rڤ(mh[TVZi+8Cmmz0{@k"d*.K} ,yބ "i"׮zEҩT̴,A+R(u.7C0ǚ& Ӧ2 aY%"FИ ̷ T "H]AJl*(Ui$ZW< GH!, )$B Fb>teA h4!%,!$ccT'⠅ֹ| 䟐3=wR#)Ir>>67=wFG'J*i4. B#Ep";R.J[q QX(3}l6 ͍Qқ;cspgvo L6g3 7K$@i<sNPZUhZ )X2[(G`ْ=;v_Q3S.<{8e :+6bG_bE=Ȓ[7bYKͨ|`XN9.ߏPEW1VqƛIq ]nܴuu];oj EQtqxl2dXqſ6pܱVڜɩIk±---_}}go+qҥ,K,c{-[qp]D"qruKu]٫׮?)MW|m:# 03;g{[ ۲7߼5ٴm'^)^-9r:SRع=p:::ڥ8/÷\B=KHعx6H`Uߪs[1gGjృ?J`n`v{?{RFunT*\|%KL&^?OW8&c_w`B1A@Ԉ !%RRJd^kE־K!X,dPX,2==-1 lX۲Yehqy]w(RBW#pR.]Rb5OR6څ )%ǎGT( J%⮻q apuj'XB){ )I !AXup*wBިaR OكR|>/|]&̯]@ܒN5kvcqa~ $P,uz WJuEm4 ABm#$?zI>y c k֬JpKu]߹)T*&V=݋))$ZRjtC.p-$_5QB$l{J>w^UJ)n0߱Wd.]J<…GEYFQ&M9"זܦ5=I GR0*^3 |.]jX|s q,߿?6*C͔$HIh(l!gB@o4I5䔔 v$J!ؿ?35uqZ~C0G`3[rZkS(LJ8} 3R7͸ģ^LF$}]KJ>날^\e֌3xG0)f-F5krKҀJ)g%\RY1Q"$"`I`cUĖ]^?Oq`Բx#\Do988R c]dxLk͕)ĉQψy!^s<ʯ4Xj l^s@CCC=q$)&1SmYRMbabrb.gUBM.lCI qc#ER oc1O$0Yubr_)T`6%E*r@FN.k2VG\꺡3FuvLc8Rp"yd&e IcК8,t&㧩ZJ!fh'꺔e|íV1g͒h룳sI\kmʕPJ1911[>X.Fe-rA@ddqch~8on s( 6&'&PJQtv.GiI@)F YZC59IgC 0"Ҽ`FfjPA:Jە$@>?V18VJєj =[ ]*q1)-B#`JZy|TnܨͦTJ)JRF;fB <.[|_<)m*RRqۦ*=U*a5Գld!A\_yP*X@)Em6F+xB AEJ^hn*2W{~R SzD %ZRw8իW]minmJ)?^FQuYRPOIb~ҾU)QrZ,dͭMZc^6bx+ gaG, B𞔸Q};P{;F joTܓ_ M;#lu#uЈF >mtf+Zk:2ZZ[<2:_HҢ*%)~ m휮)V{^}yhL5K: įO1Kh8tT,V-:6m8/T>mZK _J*%C$,j4$H+J&Cė_ZiJϋH6m$ҋ[e٪X*zMvzMCtb(z{Iu ~$j$x-B it)8ڲx7m('IJAP'N%=EйFs <_~butK{%M:mF7EkuIpkƵrm$N43$7 tɦtK{/x1ZG ڟT*ǏZ+dװ"č4ىs)UzjА.fM).;h#)0IO6{ DFrY]o.]vR}%V]C&ƓXD||cB&^ p"D,^OJ2֮AJMV;xWߟj<@tRJ}?X/WUڰvKRi&s¼;lf5oHǍcӶMUJڗ.e6Ug/WJiٹ =|0pq//hueeCC"7w"j =?+ eˍ!\H]Z0ppk`?us߸ui_OoFcx̱%N]L)sʥD,2shc4ZkRMБ`guvsKY6wH֛f{zLw[`(y|2`RQ$t` b{%kV7_3 P*q@~'dutwOo{m˦TL$6뺪T.h2j,,T_6$%wv>af4pb{ =uF-wf1x/:| @xc1P3K8tza`/й򻖖p`@KOoo#7JΟofx x~k wM~vzcn_~/X <3|B #@f͚ kRw3hr7?'̎3l =u !V{<. xY[{ϝ?7>}*" <5|įLwO-=;-8E#J3[J. @}JFJF9w^<~<|蛿4CП oo)c Ιx.]?~3oafz(*UK{:۸g= }`~(:k뿜 wGx2?%Xn}1&K/lfQ,e5i9z>=*B.WkׯM嗟:3~'H -Op׆5QQDGuQJ!DI4ԽO&7ZKWW?)vڅב::WIw E6>Dag[J+RZ#Bʌ% oSXp%1k-X}Q>O!-'/ۿgOnN^4{>=҂(D~+J*t^+R+"L= Z{9FGGH>g!]ry߯bJ6wa(.!(J͑~##(Z^ %JkiFir@;=2O?Mb(J!ā0ޙ@0|A033- cӧN#D\R@L#BkLTwi_Z! ck-33"1 a' w$m>R(;YgjjJc8uǎ#R J.[M+R2LJ Mww;A(=dn֗Lرc:u c SSS{Ν+ ! ;À|3ORrLiaNJW]/Jgq\˳kh+6tӳ:J27O1::i(4Jyp5m-yg?ɰ cZÉ'DJZ/6RP2rwO?Awl8RY`p&~tt3K#J(`rb'N`a|\F w{PG0r4gJd2ʤ%[m`;BcXJBRI0bZB>6N^Grqca{:35}9?;[9._|fLR!6v=[LbcC\Zl0YW{ݴ^ȚƐy._s wޕYW̴rfLZT"H-[? 5[փXa!I,Il 8!ό1XxAy!Rzrf Ygf35U\.pα0?/;R DsJ(֚]:T"IbƑ$$[b299Kzw"[tspΑ傕QP__{+qZR"Eus446<ĉA)Q8Im(z5ĉɼ`@>9Si"󺳪wxRR륥̲aoooRK$I".da0 08K,&1bbKRGd6}&1b#Pȼ6!I161D {{{Ⴭ,ٕsryITeKX\>'TC#mRR&qTC'H)ϑ pXձ pή\Bf9筵>cJܸqvIYF tb!B.@t2>Rұ@ZJJczzRi\.;5xi``bb. Ca$I`zjFZ ڐR(G #@$x όH!NLy*aOL+R*j!c,a:w >rtx|VY 4Z0q G*...qXTZWZ[[^gmi)"Nby8Kq@kPA@hĤzTtNCزy3e5T* J,AV17ֺEC嫭S 7658c,}HMwT 0$dQ\XXXbnv"ӳS*R!I [\R*xj/%KcSsh%*3o_\tֺZCtbI֫aNJݸZ93HBTD[T9B[+:Z}4Ll,)ݿk 퉳ֽ}rq%*9=akڻy:;hjnHd)k WGϣ{N41i3iިG?[ t@\5!EԎ&:;pγlFNOĬ|K.RZ,MO{ s!%靚yFihS8Sdrj2]tVhJ\I5SSO%GH{Ҿ)Mid.]8LT3+4^xarppך7ơ?;[="!dJ%hb``0۶ĕJLl~|㍟r4^JIss3lYKY/]0++%<^Q4]YP |W"1z/ccc,"h)2xwzmUr ᬥն4(J^I3WA :|𡞽{](͆?x6=SΟ?퇖Y2zε]twemWZ65>-&n]Nt9[28ƃijl_{G7NM#G3WNmܶ}gO_hؾm;Rl'pW +]׳g.=V()Hϵ==l߶k ,5E +'x4J*Yq1}$Ib{:7uU޽kHeyzZ*Zݻ`e]_WsS1Ibq 煪^x{h镓?svL4޵>X1\EBdT4IM~>B]{O{Oشc9^9kWGKgn o lr񼐒bȕ+T*WX]6PӼiN:[rlGP;Ǻ]{%sO}{}w]An)@p-m7/v\xcٓZqrbc71,Y!6A]5i>ǖ{7O\pn'Hk.D1x`ah]J)Yf],\ HefXXZ UpY͠Ӑ2јo<~ͳE~mxh߷z 0Wlvcc~'i1H\Vrq4əZ,.-W_=966vsĴD'd-[rAlѶ{&<Ziii]h)jJۋϜ}l9eoUe0 .kZ;g1."319tbXܿ;?5Zˆ5@EfqieS;]/_m:IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-online.png000066400000000000000000000103431345766322700257420ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<`IDATh՚ۏ]W}?9g̙$n!@*-<*U#RJHUxKi3u-!q%$&\L'N2c9>}g#Hk}]ۿUb[\::ǎ7ދ~ԻA`q}a`nKM` 8dk߿5ť3gS׊Ţ586>^X_^[t:S3׀O/;~ ,.4|{?] FFFʅB!ճn7V~uzg?g_/ }cKG9G\.??pextj[֋/p??5MG&Ȉt5KG3~d}΁B}!!B@4PJEhjuy^r"cǯ /\˿҇FFF *K7 P1 m2Zk@j_~t |5ť xh?gWWV_p)j m1=̡?̮;2K&hms~M|@>_UJ/.=v瑏}lE>1^}gN>IYGUeQ?@@$6T?ʽG+Jau'=~&:Kܒ@_X\j/]z?&U6(1JhQ(zR AA^ŧ?Xy"7o#{> q(5_<1 FgRDil}zsƋjCG@+#-N=?ϬM쿽;[X1`|峏ѝmG=4?7_vl;/G1jqqnmM[֋_A) mbDm 6/Ldw^[z yH\vӶRZť1 x$k-?C{+CsN(x2]x:iM||so{(4./IJK_=vKylpT2G||^I=ϾdyԓEo `d ccLY:?gцέhz佗#G>T*+gɇ?5DZM]W x~9ӰU( a3 [c" w,wrc%678}4I@Phe$fМx~{B)Yw8|SO~;rt> pT Vqgج`,r kX|`2'hXe=ŇNҰ!x٭a4y'l=֌ gr7 ~ۿ(=/#A3έ`l杌fյsNҰ^|c{7D㚱 3_Bir<6(%^JOq>!K}~O{fb[2K:,m4JÙ/q8Ⱦ}#{&ʃ} sa7bb@09>Ed,B;\Hq>yGRR;r9m'Յ_[{ʃ~=/4E(5n u\Y((H$ňƋ‰"h{/)")(˽hɈ(Q45OA^1*"(ͳp,"8t16mk( l +DE(A)@ټp$%(ؘb.Z,D1 >R* kkkttВ>*%Jfg e2z'7q( hIH(h1 T}*%9#@*TֆB@ EA!AaHPl6S. јT*vmm `lE&^/"J\ۺ86 3G&^"4hWBC>;Ґ"r:kZJ w77h'Mb[+ee z=AQ, BT+e*Q(;1&%cI|+DA@Ps H!'Wu)oÀ t]ZkzJ$쫺X U9 |xcqhhԵ>r">hTPą.J:Ad}LMJ86RP hestt]v`@4Jb~ 뿤Ѫ!"VV{OQOdFOBIt.&١j}rW)juˤCdl&/[$2VB6ΑyRTّIxHm@F4 {%M$I"dY@VHPw|Hxm hG*-(ˁx:tBh- 6Tר']i -<KŤ"hw˾f&!EIP:{N\rH /y٠<,*17q/" M$ 4s-D%MPi k#Qy[7PZ139G$w^\T# /n9rSS T zSNuYiڈZfG«R:tp*)EfGڈY e@k@)$dŋ[-^[__j4@ZUj&jkpx^8޽Twcw/QOQKSM`hx  Z-ֻW '(nTklZlx ջ:8^]8IUQpșh M>1-~A$IǷxgs+ɀK>uUگF RJu\xB+xWOZm۩rŶMj#y$\Rj'=Mi" uKz]'x}mwʲGxl:TSn髧_eޑZ\:W+ ZqʜA]?ɥKydʎg1Val.Yk_b{fR'vanQad}gMH^~,c_B?)6/>y-F )CA+iVi[T \[O6ALȤa4cy*.[[dH OH8y4یZwabp:W>1d2i>GԚ\4Mɟ_*!Y)lK._:sW[nCW;w\effv %.6ha#ZrX]PW4q]@\JlR;%K{ʕˍnzݻv懵*xl uafXCL}<A"e5EQ e𠫣vu*)%%=zmeuq%  URh\/.U[#f_&F% |>#Zޘ}S7Nǿz}+Xb#ȧbݥ={#e"0>'7psP]lP;$THܐcp.|\Z#cv]/ ,V$tbR;:vYY]igS2MD޶]*h\T8MIZLvo__ZQld5K$iQV˟=~ /Op2IENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-requested.png000066400000000000000000000103531345766322700264600ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<hIDATh՚{]G}?3sιw^n!S5jU,B" ?JϴTHUZ,"$N 1vkw׻c||bPkގ%"ʕ/dvv6&3o1{)شqӘRjp= H& xy[{O:yq,۳xȇ>qZ炑C^ZRi[x@yOZמ;`O۳c g~vSJ:{x.Lp ?suZIBFS"l]?ɶkX31cL@{_yWߎ~Rk_x`rbr:G+nfşɳ_RmB+r3Y?#S;6B ŀSO |ir[?]Z=JR49vx%f+QFaHh6u3xxq" bۆ@!*PB.^8ſ˗Oo!G[;0.y/=_dGZ$yu{X5[ I/peL`0ڠBkQcT H##Q^e*1 {=*SWBJRoﶱ}u>E~OO)ꍘJu|y~v2=(E3"6eP&ךeR57bRG?(4 (Lj- rspeP J-k1Z2ٳڀ2?y{ J% #cJ_}၁h۶{oV±S81LDl3*sbB\`V Y1\&0Ag翙C/ةK8+߬*=۶msoO=^[ f 56 (cr@B!dQ&z[QܕEz3:SW~|V}:wh<ڃx@{<}Gܽf%)ĭB>{KnB;Vߵz`v~QG_=B5sL:+}9:#aAFJhcG+@y5,{QJbvWO#"WRlmy>?cǽQ뜯[YHTgxJk֯$B+k$͚sF!g%tovv4J+?z:뜏q00ch~]Xk…9*54[~F{0&9uDŽr͜p q9& Bs; JQJ=fcw@K΃O%K%C,)N̬uYbW.EQu1g=J zuO^1ZJh zIB+RvnӶOA)F!Q`YMĂM3pse=s3>Fp" QHfcg2=Ҵ 8I?>>^tk节4,T+dY&" B]ZiҲMV iIHS!M%Ą$h)vA ZbV[?:[`g!s""މqg+u3Q( A1:{Yl4G!5LqÉ`mZ[cSV" FA(шwܬXXSo$DaE;k;W6=^"csBWWV*ܨ1wAT`o zֈ2gGc=sduI@2_iXkh:)xWWxmۓ\|kEPJQ,$V(MK#qm\kFhb!ڈuAxAL'ΓZhƎz3aҤTL]YVQ@i AR +B+q}ZH?XkB^4u1ZkHRb}y5Ak%I7]7/Γ 0"" !{OjVIsY$BæCԛ)yD2DwuNBxuKVsj5}Kuډ,孽J:fc ׌h XRnTRϷYHTFh q ׌`!  ~̵X'ZK1 pqNR<&GAI)ҵ*J++HROifShĞF~KhʤZZϚP_?  C8ߙKE濷tN?}mf)3sjZR*-7n:c$G^p-hꌏ6Y7я1}7c,1P_4q4kUt쾽ޱy'~#Fk[ٳg*LtC2gϜݺ+׭}(?;7b,Sض m QnֵCLTh&flD;^=9˙d )QV 9%XYjBrCS8N`r{vl]RoU 8rZb+Fg7Lo9 (L] S&q3د\_lqzCSdgڠՅGw?Ъ;6o z4\p,oWO)dleՙipFj#H^G׎mJC=]]/#ߛKm̷ׅvx6o+o:u>]um RJ%yߟZ xYY%?\VgΧi&zVaǦ Ɔ{:jdJ%QKvlz̷&z4u3筵|Bm-\xbţ߿,"iPA4y-OYb ;6e!k7y/_tFVZ|v~hƻ7 pڍ篘R&.ߤѲ@浢N?- &{aO};OvKHl7O3k\Q-+(e-2BYCes=sO?|U3W^_Bsuց{} cbWk -SV Ƒ;?'/pܦ'U]+J| ]A{Eb@hy4 4`n0,Vꍆ}饣W^nN1-!9Zuցwo,HqLMb$Pyop( hUGB4qgN?~;yȷIJc(['rt.㢦rE.o"&Aešrev I1mDr=00MLU) ;gDZmLM]/,,O;5@Ke],8mQ|1Zzjp=~OrҬLIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/48x48/status/wroop-xa.png000066400000000000000000000103531345766322700250670ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<hIDATh՚{]G}?3sιw^n!S5jU,B" ?JϴTHUZ,"$N 1vkw׻c||bPkގ%"ʕ/dvv6&3o1{)شqӘRjp= H& xy[{O:yq,۳xȇ>qZ炑C^ZRi[x@yOZמ;`O۳c g~vSJ:{x.Lp ?suZIBFS"l]?ɶkX31cL@{_yWߎ~Rk_x`rbr:G+nfşɳ_RmB+r3Y?#S;6B ŀSO |ir[?]Z=JR49vx%f+QFaHh6u3xxq" bۆ@!*PB.^8ſ˗Oo!G[;0.y/=_dGZ$yu{X5[ I/peL`0ڠBkQcT H##Q^e*1 {=*SWBJRoﶱ}u>E~OO)ꍘJu|y~v2=(E3"6eP&ךeR57bRG?(4 (Lj- rspeP J-k1Z2ٳڀ2?y{ J% #cJ_}၁h۶{oV±S81LDl3*sbB\`V Y1\&0Ag翙C/ةK8+߬*=۶msoO=^[ f 56 (cr@B!dQ&z[QܕEz3:SW~|V}:wh<ڃx@{<}Gܽf%)ĭB>{KnB;Vߵz`v~QG_=B5sL:+}9:#aAFJhcG+@y5,{QJbvWO#"WRlmy>?cǽQ뜯[YHTgxJk֯$B+k$͚sF!g%tovv4J+?z:뜏q00ch~]Xk…9*54[~F{0&9uDŽr͜p q9& Bs; JQJ=fcw@K΃O%K%C,)N̬uYbW.EQu1g=J zuO^1ZJh zIB+RvnӶOA)F!Q`YMĂM3pse=s3>Fp" QHfcg2=Ҵ 8I?>>^tk节4,T+dY&" B]ZiҲMV iIHS!M%Ą$h)vA ZbV[?:[`g!s""މqg+u3Q( A1:{Yl4G!5LqÉ`mZ[cSV" FA(шwܬXXSo$DaE;k;W6=^"csBWWV*ܨ1wAT`o zֈ2gGc=sduI@2_iXkh:)xWWxmۓ\|kEPJQ,$V(MK#qm\kFhb!ڈuAxAL'ΓZhƎz3aҤTL]YVQ@i AR +B+q}ZH?XkB^4u1ZkHRb}y5Ak%I7]7/Γ 0"" !{OjVIsY$BæCԛ)yD2DwuNBxuKVsj5}Kuډ,孽J:fc ׌h XRnTRϷYHTFh q ׌`!  ~̵X'ZK1 pqNR<&GAI)ҵ*J++HROifShĞF~KhʤZZϚP_?  C8ߙKE濷tN?}mf)3sjZR*-7n:c$G^p-hꌏ6Y7я1}7c,1P_4q4kUt쾽ޱy'~#Fk[ٳg*LtC2gϜݺ+׭}(?;7b,Sض m QnֵCLTh&flD;^=9˙d )QV 9%XYjBrCS8N`r{vl]RoU 8rZb+Fg7Lo9 (L] S&q3د\_lqzCSdgڠՅGw?Ъ;6o z4\p,oWO)dleՙipFj#H^G׎mJC=]]/#ߛKm̷ׅvx6o+o:u>]um RJ%yߟZ xYY%?\VgΧi&zVaǦ Ɔ{:jdJ%QKvlz̷&z4u3筵|Bm-\xbţ߿,"iPA4y-OYb ;6e!k7y/_tFVZ|v~hƻ7 pڍ篘R&.ߤѲ@浢N?- &{aO};OvKHl7O3k\Q-+(e-2BYCes=sO?|U3W^_Bsuց{} cbWk -SV Ƒ;?'/pܦ'U]+J| ]A{Eb@hy4 4`n0,Vꍆ}饣W^nN1-!9Zuցwo,HqLMb$Pyop( hUGB4qgN?~;yȷIJc(['rt.㢦rE.o"&Aešrev I1mDr=00MLU) ;gDZmLM]/,,O;5@Ke],8mQ|1Zzjp=~OrҬLIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/64x64/000077500000000000000000000000001345766322700212545ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/64x64/apps/000077500000000000000000000000001345766322700222175ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/64x64/apps/org.gajim.Gajim.png000066400000000000000000000105411345766322700256310ustar00rootroot00000000000000PNG  IHDR@@iqsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATxiyO3=Z$%c.cC1N c|;v qU9 |TXرA8`d :W+jwgw>'gvv4+!iz}WTzx7|ٳߗjەkTHbGȵx!=|EkydR]gW`'N%~C)F^T+oTdv xrc^r܅&_Ta`FE,w X]zkC{ f}dwxQq=nU~KwEe_0jP"Gj= sGh\Skn=OZL쵾:{州ǼdHpbe$ byU M ˚Lr|dyR2jbjXx=_`Ou֧کk x&5p'~X.euaߎK0-2jJ)aL 5E]"Nanx,FͷK߶@ҷ6nrt݂X< I X\DD\*u2zN}JߕŖ$o\NJ3W!bAU*xI"V7A;",nm%Xo֢h@$Sk A#h8 n4`W 0^4dEj,.Jc;1|O~D%وcbFUN ت&˚ u5v:g-NY6om%@Ez+1т=@BD!U=T s0kxم,lm% M-&% j &;šP [@.:R,jFZGP- &@)a0j( &^x_%Eј V6mm%qd_X޳Tn4 0,Jf*(jW524nCP>m36 E^&hF}D0"q4& @{C0IawD݃_:]:7 FJ,ՎΘ"j S@M1?$పɏ0no>gHהV/4RjcLP c2@4`"?l_7V:V:+('L2h%'uCQ^G]:}._eIlna jn/!S߶}.m{+E;][e'T:^M ?)nکIZyP)K->IS~d[\5Ԫ@5T'uw!{_7sWp=b9g*7$a`^j5$7{-J'6BuC(Ef%DWx p=bswۖlk:KeN{=;o읿`պai?a|P&"_^bͲMeWg8Xzb4ƅC6\~Nw,ޫ:Bmou)/Ǜ?zڿי$-ԎZkzpM~zBoUGN:fvn"ݎrEX,[:c-#nvbWi~Tbu*~|&t%_W g`ېNg~t+G72զ8d~f% :΢eK:4phi~\]CbY_k_4ǎSdFkٺ(,˾}.Kg, q (QD0"#vabt#g],TcO3ϭٝ,Ȯf~v͖=>-Zn ˽T\%sVv\fF֓ Ǡ& `]a~s*?%IBaDaXδ0{5ow5O4w'O+)`1kx Q뿓d"~dM|1elc ֯Qp˂ΔuK|S#չGFyb.UJٖwRupK:߿3 J!9D*$Nxe ;q.ww-gM3eRL0'ؚ{>41dum,9'\ӗzЏȇ#uPQEM̧** C,Y˲; K6 cAX aI9]d%,\E<7n,WQl7Uu6qZ7*b:TǢPPXб3ddb((TJHrQϫ6nh>mMS+|7$yE=C,K\̳;䙝?|Vu۔ ' iߊ պ'7&(°_ߛ9瞫z\yqtǴ*Oi317^tI'J'We* @Ȩq7rr(^Nt0TW.Vr 8!U;2(`0 @tx M?IG^]ED2^Hێq Vr{n|MXN"EƵ[~X7PEyG0Q9HJ9 ]Ye"2e So)LR8}o(%{ f;ZOu PD,pU < *2R8@39([:\k-()zN@_Ed* -s7 aa*QϮR䌪 P1Ψ47I`joFR- +Nj<@otb8 XS4!pkkP(GqU& )S G&]U`=]4^N|9ao?9D\yLb!pDЭ|dxXbc[~Xz)X&fPxA7HS &PuDO6xi3_MǓvR%A_:Ocx1W8ܮ!aAO"KdIQe8,(I;]N-1?=#? ੎GR,q'c&@%""T,ڢ"2%Akn#uBJLg$c}XQ A".hGnHa]-$mwU?y=BEFRMCJ'ؒ v3+$Px6ONbiD?mxi~ zNw:UJdhb(y"H"8 bcm$4 'k b%o |y ʗb44P0bk%1i v:Yv_^r ,:=;aHi˶,űl,ƱlIJ1D>QF!AFABiT(r0i?ǯw?j)1`fLVϝ?txݜzrDz[N͊B*q5Ѱ#8[+dfkO76-@đ191MǵF%ἡN{l OM Ӹ10F`G,طڴž~$@N+~:if׭ϋIENDB`gajim-gajim-1.1.3/gajim/data/icons/hicolor/index.theme000066400000000000000000000601431345766322700226200ustar00rootroot00000000000000[Icon Theme] Name=Hicolor Comment=Fallback icon theme Hidden=true Directories=16x16/actions,16x16/animations,16x16/apps,16x16/categories,16x16/devices,16x16/emblems,16x16/emotes,16x16/filesystems,16x16/intl,16x16/mimetypes,16x16/places,16x16/status,16x16/stock/chart,16x16/stock/code,16x16/stock/data,16x16/stock/form,16x16/stock/image,16x16/stock/io,16x16/stock/media,16x16/stock/navigation,16x16/stock/net,16x16/stock/object,16x16/stock/table,16x16/stock/text,22x22/actions,22x22/animations,22x22/apps,22x22/categories,22x22/devices,22x22/emblems,22x22/emotes,22x22/filesystems,22x22/intl,22x22/mimetypes,22x22/places,22x22/status,22x22/stock/chart,22x22/stock/code,22x22/stock/data,22x22/stock/form,22x22/stock/image,22x22/stock/io,22x22/stock/media,22x22/stock/navigation,22x22/stock/net,22x22/stock/object,22x22/stock/table,22x22/stock/text,24x24/actions,24x24/animations,24x24/apps,24x24/categories,24x24/devices,24x24/emblems,24x24/emotes,24x24/filesystems,24x24/intl,24x24/mimetypes,24x24/places,24x24/status,24x24/stock/chart,24x24/stock/code,24x24/stock/data,24x24/stock/form,24x24/stock/image,24x24/stock/io,24x24/stock/media,24x24/stock/navigation,24x24/stock/net,24x24/stock/object,24x24/stock/table,24x24/stock/text,32x32/actions,32x32/animations,32x32/apps,32x32/categories,32x32/devices,32x32/emblems,32x32/emotes,32x32/filesystems,32x32/intl,32x32/mimetypes,32x32/places,32x32/status,32x32/stock/chart,32x32/stock/code,32x32/stock/data,32x32/stock/form,32x32/stock/image,32x32/stock/io,32x32/stock/media,32x32/stock/navigation,32x32/stock/net,32x32/stock/object,32x32/stock/table,32x32/stock/text,36x36/actions,36x36/animations,36x36/apps,36x36/categories,36x36/devices,36x36/emblems,36x36/emotes,36x36/filesystems,36x36/intl,36x36/mimetypes,36x36/places,36x36/status,36x36/stock/chart,36x36/stock/code,36x36/stock/data,36x36/stock/form,36x36/stock/image,36x36/stock/io,36x36/stock/media,36x36/stock/navigation,36x36/stock/net,36x36/stock/object,36x36/stock/table,36x36/stock/text,48x48/actions,48x48/animations,48x48/apps,48x48/categories,48x48/devices,48x48/emblems,48x48/emotes,48x48/filesystems,48x48/intl,48x48/mimetypes,48x48/places,48x48/status,48x48/stock/chart,48x48/stock/code,48x48/stock/data,48x48/stock/form,48x48/stock/image,48x48/stock/io,48x48/stock/media,48x48/stock/navigation,48x48/stock/net,48x48/stock/object,48x48/stock/table,48x48/stock/text,64x64/actions,64x64/animations,64x64/apps,64x64/categories,64x64/devices,64x64/emblems,64x64/emotes,64x64/filesystems,64x64/intl,64x64/mimetypes,64x64/places,64x64/status,64x64/stock/chart,64x64/stock/code,64x64/stock/data,64x64/stock/form,64x64/stock/image,64x64/stock/io,64x64/stock/media,64x64/stock/navigation,64x64/stock/net,64x64/stock/object,64x64/stock/table,64x64/stock/text,72x72/actions,72x72/animations,72x72/apps,72x72/categories,72x72/devices,72x72/emblems,72x72/emotes,72x72/filesystems,72x72/intl,72x72/mimetypes,72x72/places,72x72/status,72x72/stock/chart,72x72/stock/code,72x72/stock/data,72x72/stock/form,72x72/stock/image,72x72/stock/io,72x72/stock/media,72x72/stock/navigation,72x72/stock/net,72x72/stock/object,72x72/stock/table,72x72/stock/text,96x96/actions,96x96/animations,96x96/apps,96x96/categories,96x96/devices,96x96/emblems,96x96/emotes,96x96/filesystems,96x96/intl,96x96/mimetypes,96x96/places,96x96/status,96x96/stock/chart,96x96/stock/code,96x96/stock/data,96x96/stock/form,96x96/stock/image,96x96/stock/io,96x96/stock/media,96x96/stock/navigation,96x96/stock/net,96x96/stock/object,96x96/stock/table,96x96/stock/text,128x128/actions,128x128/animations,128x128/apps,128x128/categories,128x128/devices,128x128/emblems,128x128/emotes,128x128/filesystems,128x128/intl,128x128/mimetypes,128x128/places,128x128/status,128x128/stock/chart,128x128/stock/code,128x128/stock/data,128x128/stock/form,128x128/stock/image,128x128/stock/io,128x128/stock/media,128x128/stock/navigation,128x128/stock/net,128x128/stock/object,128x128/stock/table,128x128/stock/text,192x192/actions,192x192/animations,192x192/apps,192x192/categories,192x192/devices,192x192/emblems,192x192/emotes,192x192/filesystems,192x192/intl,192x192/mimetypes,192x192/places,192x192/status,192x192/stock/chart,192x192/stock/code,192x192/stock/data,192x192/stock/form,192x192/stock/image,192x192/stock/io,192x192/stock/media,192x192/stock/navigation,192x192/stock/net,192x192/stock/object,192x192/stock/table,192x192/stock/text,256x256/actions,256x256/animations,256x256/apps,256x256/categories,256x256/devices,256x256/emblems,256x256/emotes,256x256/filesystems,256x256/intl,256x256/mimetypes,256x256/places,256x256/status,256x256/stock/chart,256x256/stock/code,256x256/stock/data,256x256/stock/form,256x256/stock/image,256x256/stock/io,256x256/stock/media,256x256/stock/navigation,256x256/stock/net,256x256/stock/object,256x256/stock/table,256x256/stock/text,scalable/actions,scalable/animations,scalable/apps,scalable/categories,scalable/devices,scalable/emblems,scalable/emotes,scalable/filesystems,scalable/intl,scalable/mimetypes,scalable/places,scalable/status,scalable/stock/chart,scalable/stock/code,scalable/stock/data,scalable/stock/form,scalable/stock/image,scalable/stock/io,scalable/stock/media,scalable/stock/navigation,scalable/stock/net,scalable/stock/object,scalable/stock/table,scalable/stock/text [16x16/actions] Size=16 Context=Actions Type=Threshold [16x16/animations] Size=16 Context=Animations Type=Threshold [16x16/apps] Size=16 Context=Applications Type=Threshold [16x16/categories] Size=16 Context=Categories Type=Threshold [16x16/devices] Size=16 Context=Devices Type=Threshold [16x16/emblems] Size=16 Context=Emblems Type=Threshold [16x16/emotes] Size=16 Context=Emotes Type=Threshold [16x16/filesystems] Size=16 Context=FileSystems Type=Threshold [16x16/intl] Size=16 Context=International Type=Threshold [16x16/mimetypes] Size=16 Context=MimeTypes Type=Threshold [16x16/places] Size=16 Context=Places Type=Threshold [16x16/status] Size=16 Context=Status Type=Threshold [16x16/stock/chart] Size=16 Context=Stock Type=Threshold [16x16/stock/code] Size=16 Context=Stock Type=Threshold [16x16/stock/data] Size=16 Context=Stock Type=Threshold [16x16/stock/form] Size=16 Context=Stock Type=Threshold [16x16/stock/image] Size=16 Context=Stock Type=Threshold [16x16/stock/io] Size=16 Context=Stock Type=Threshold [16x16/stock/media] Size=16 Context=Stock Type=Threshold [16x16/stock/navigation] Size=16 Context=Stock Type=Threshold [16x16/stock/net] Size=16 Context=Stock Type=Threshold [16x16/stock/object] Size=16 Context=Stock Type=Threshold [16x16/stock/table] Size=16 Context=Stock Type=Threshold [16x16/stock/text] Size=16 Context=Stock Type=Threshold [22x22/actions] Size=22 Context=Actions Type=Threshold [22x22/animations] Size=22 Context=Animations Type=Threshold [22x22/apps] Size=22 Context=Applications Type=Threshold [22x22/categories] Size=22 Context=Categories Type=Threshold [22x22/devices] Size=22 Context=Devices Type=Threshold [22x22/emblems] Size=22 Context=Emblems Type=Threshold [22x22/emotes] Size=22 Context=Emotes Type=Threshold [22x22/filesystems] Size=22 Context=FileSystems Type=Threshold [22x22/intl] Size=22 Context=International Type=Threshold [22x22/mimetypes] Size=22 Context=MimeTypes Type=Threshold [22x22/places] Size=22 Context=Places Type=Threshold [22x22/status] Size=22 Context=Status Type=Threshold [22x22/stock/chart] Size=22 Context=Stock Type=Threshold [22x22/stock/code] Size=22 Context=Stock Type=Threshold [22x22/stock/data] Size=22 Context=Stock Type=Threshold [22x22/stock/form] Size=22 Context=Stock Type=Threshold [22x22/stock/image] Size=22 Context=Stock Type=Threshold [22x22/stock/io] Size=22 Context=Stock Type=Threshold [22x22/stock/media] Size=22 Context=Stock Type=Threshold [22x22/stock/navigation] Size=22 Context=Stock Type=Threshold [22x22/stock/net] Size=22 Context=Stock Type=Threshold [22x22/stock/object] Size=22 Context=Stock Type=Threshold [22x22/stock/table] Size=22 Context=Stock Type=Threshold [22x22/stock/text] Size=22 Context=Stock Type=Threshold [24x24/actions] Size=24 Context=Actions Type=Threshold [24x24/animations] Size=24 Context=Animations Type=Threshold [24x24/apps] Size=24 Context=Applications Type=Threshold [24x24/categories] Size=24 Context=Categories Type=Threshold [24x24/devices] Size=24 Context=Devices Type=Threshold [24x24/emblems] Size=24 Context=Emblems Type=Threshold [24x24/emotes] Size=24 Context=Emotes Type=Threshold [24x24/filesystems] Size=24 Context=FileSystems Type=Threshold [24x24/intl] Size=24 Context=International Type=Threshold [24x24/mimetypes] Size=24 Context=MimeTypes Type=Threshold [24x24/places] Size=24 Context=Places Type=Threshold [24x24/status] Size=24 Context=Status Type=Threshold [24x24/stock/chart] Size=24 Context=Stock Type=Threshold [24x24/stock/code] Size=24 Context=Stock Type=Threshold [24x24/stock/data] Size=24 Context=Stock Type=Threshold [24x24/stock/form] Size=24 Context=Stock Type=Threshold [24x24/stock/image] Size=24 Context=Stock Type=Threshold [24x24/stock/io] Size=24 Context=Stock Type=Threshold [24x24/stock/media] Size=24 Context=Stock Type=Threshold [24x24/stock/navigation] Size=24 Context=Stock Type=Threshold [24x24/stock/net] Size=24 Context=Stock Type=Threshold [24x24/stock/object] Size=24 Context=Stock Type=Threshold [24x24/stock/table] Size=24 Context=Stock Type=Threshold [24x24/stock/text] Size=24 Context=Stock Type=Threshold [32x32/actions] Size=32 Context=Actions Type=Threshold [32x32/animations] Size=32 Context=Animations Type=Threshold [32x32/apps] Size=32 Context=Applications Type=Threshold [32x32/categories] Size=32 Context=Categories Type=Threshold [32x32/devices] Size=32 Context=Devices Type=Threshold [32x32/emblems] Size=32 Context=Emblems Type=Threshold [32x32/emotes] Size=32 Context=Emotes Type=Threshold [32x32/filesystems] Size=32 Context=FileSystems Type=Threshold [32x32/intl] Size=32 Context=International Type=Threshold [32x32/mimetypes] Size=32 Context=MimeTypes Type=Threshold [32x32/places] Size=32 Context=Places Type=Threshold [32x32/status] Size=32 Context=Status Type=Threshold [32x32/stock/chart] Size=32 Context=Stock Type=Threshold [32x32/stock/code] Size=32 Context=Stock Type=Threshold [32x32/stock/data] Size=32 Context=Stock Type=Threshold [32x32/stock/form] Size=32 Context=Stock Type=Threshold [32x32/stock/image] Size=32 Context=Stock Type=Threshold [32x32/stock/io] Size=32 Context=Stock Type=Threshold [32x32/stock/media] Size=32 Context=Stock Type=Threshold [32x32/stock/navigation] Size=32 Context=Stock Type=Threshold [32x32/stock/net] Size=32 Context=Stock Type=Threshold [32x32/stock/object] Size=32 Context=Stock Type=Threshold [32x32/stock/table] Size=32 Context=Stock Type=Threshold [32x32/stock/text] Size=32 Context=Stock Type=Threshold [36x36/actions] Size=36 Context=Actions Type=Threshold [36x36/animations] Size=36 Context=Animations Type=Threshold [36x36/apps] Size=36 Context=Applications Type=Threshold [36x36/categories] Size=36 Context=Categories Type=Threshold [36x36/devices] Size=36 Context=Devices Type=Threshold [36x36/emblems] Size=36 Context=Emblems Type=Threshold [36x36/emotes] Size=36 Context=Emotes Type=Threshold [36x36/filesystems] Size=36 Context=FileSystems Type=Threshold [36x36/intl] Size=36 Context=International Type=Threshold [36x36/mimetypes] Size=36 Context=MimeTypes Type=Threshold [36x36/places] Size=36 Context=Places Type=Threshold [36x36/status] Size=36 Context=Status Type=Threshold [36x36/stock/chart] Size=36 Context=Stock Type=Threshold [36x36/stock/code] Size=36 Context=Stock Type=Threshold [36x36/stock/data] Size=36 Context=Stock Type=Threshold [36x36/stock/form] Size=36 Context=Stock Type=Threshold [36x36/stock/image] Size=36 Context=Stock Type=Threshold [36x36/stock/io] Size=36 Context=Stock Type=Threshold [36x36/stock/media] Size=36 Context=Stock Type=Threshold [36x36/stock/navigation] Size=36 Context=Stock Type=Threshold [36x36/stock/net] Size=36 Context=Stock Type=Threshold [36x36/stock/object] Size=36 Context=Stock Type=Threshold [36x36/stock/table] Size=36 Context=Stock Type=Threshold [36x36/stock/text] Size=36 Context=Stock Type=Threshold [48x48/actions] Size=48 Context=Actions Type=Threshold [48x48/animations] Size=48 Context=Animations Type=Threshold [48x48/apps] Size=48 Context=Applications Type=Threshold [48x48/categories] Size=48 Context=Categories Type=Threshold [48x48/devices] Size=48 Context=Devices Type=Threshold [48x48/emblems] Size=48 Context=Emblems Type=Threshold [48x48/emotes] Size=48 Context=Emotes Type=Threshold [48x48/filesystems] Size=48 Context=FileSystems Type=Threshold [48x48/intl] Size=48 Context=International Type=Threshold [48x48/mimetypes] Size=48 Context=MimeTypes Type=Threshold [48x48/places] Size=48 Context=Places Type=Threshold [48x48/status] Size=48 Context=Status Type=Threshold [48x48/stock/chart] Size=48 Context=Stock Type=Threshold [48x48/stock/code] Size=48 Context=Stock Type=Threshold [48x48/stock/data] Size=48 Context=Stock Type=Threshold [48x48/stock/form] Size=48 Context=Stock Type=Threshold [48x48/stock/image] Size=48 Context=Stock Type=Threshold [48x48/stock/io] Size=48 Context=Stock Type=Threshold [48x48/stock/media] Size=48 Context=Stock Type=Threshold [48x48/stock/navigation] Size=48 Context=Stock Type=Threshold [48x48/stock/net] Size=48 Context=Stock Type=Threshold [48x48/stock/object] Size=48 Context=Stock Type=Threshold [48x48/stock/table] Size=48 Context=Stock Type=Threshold [48x48/stock/text] Size=48 Context=Stock Type=Threshold [64x64/actions] Size=64 Context=Actions Type=Threshold [64x64/animations] Size=64 Context=Animations Type=Threshold [64x64/apps] Size=64 Context=Applications Type=Threshold [64x64/categories] Size=64 Context=Categories Type=Threshold [64x64/devices] Size=64 Context=Devices Type=Threshold [64x64/emblems] Size=64 Context=Emblems Type=Threshold [64x64/emotes] Size=64 Context=Emotes Type=Threshold [64x64/filesystems] Size=64 Context=FileSystems Type=Threshold [64x64/intl] Size=64 Context=International Type=Threshold [64x64/mimetypes] Size=64 Context=MimeTypes Type=Threshold [64x64/places] Size=64 Context=Places Type=Threshold [64x64/status] Size=64 Context=Status Type=Threshold [64x64/stock/chart] Size=64 Context=Stock Type=Threshold [64x64/stock/code] Size=64 Context=Stock Type=Threshold [64x64/stock/data] Size=64 Context=Stock Type=Threshold [64x64/stock/form] Size=64 Context=Stock Type=Threshold [64x64/stock/image] Size=64 Context=Stock Type=Threshold [64x64/stock/io] Size=64 Context=Stock Type=Threshold [64x64/stock/media] Size=64 Context=Stock Type=Threshold [64x64/stock/navigation] Size=64 Context=Stock Type=Threshold [64x64/stock/net] Size=64 Context=Stock Type=Threshold [64x64/stock/object] Size=64 Context=Stock Type=Threshold [64x64/stock/table] Size=64 Context=Stock Type=Threshold [64x64/stock/text] Size=64 Context=Stock Type=Threshold [72x72/actions] Size=72 Context=Actions Type=Threshold [72x72/animations] Size=72 Context=Animations Type=Threshold [72x72/apps] Size=72 Context=Applications Type=Threshold [72x72/categories] Size=72 Context=Categories Type=Threshold [72x72/devices] Size=72 Context=Devices Type=Threshold [72x72/emblems] Size=72 Context=Emblems Type=Threshold [72x72/emotes] Size=72 Context=Emotes Type=Threshold [72x72/filesystems] Size=72 Context=FileSystems Type=Threshold [72x72/intl] Size=72 Context=International Type=Threshold [72x72/mimetypes] Size=72 Context=MimeTypes Type=Threshold [72x72/places] Size=72 Context=Places Type=Threshold [72x72/status] Size=72 Context=Status Type=Threshold [72x72/stock/chart] Size=72 Context=Stock Type=Threshold [72x72/stock/code] Size=72 Context=Stock Type=Threshold [72x72/stock/data] Size=72 Context=Stock Type=Threshold [72x72/stock/form] Size=72 Context=Stock Type=Threshold [72x72/stock/image] Size=72 Context=Stock Type=Threshold [72x72/stock/io] Size=72 Context=Stock Type=Threshold [72x72/stock/media] Size=72 Context=Stock Type=Threshold [72x72/stock/navigation] Size=72 Context=Stock Type=Threshold [72x72/stock/net] Size=72 Context=Stock Type=Threshold [72x72/stock/object] Size=72 Context=Stock Type=Threshold [72x72/stock/table] Size=72 Context=Stock Type=Threshold [72x72/stock/text] Size=72 Context=Stock Type=Threshold [96x96/actions] Size=96 Context=Actions Type=Threshold [96x96/animations] Size=96 Context=Animations Type=Threshold [96x96/apps] Size=96 Context=Applications Type=Threshold [96x96/categories] Size=96 Context=Categories Type=Threshold [96x96/devices] Size=96 Context=Devices Type=Threshold [96x96/emblems] Size=96 Context=Emblems Type=Threshold [96x96/emotes] Size=96 Context=Emotes Type=Threshold [96x96/filesystems] Size=96 Context=FileSystems Type=Threshold [96x96/intl] Size=96 Context=International Type=Threshold [96x96/mimetypes] Size=96 Context=MimeTypes Type=Threshold [96x96/places] Size=96 Context=Places Type=Threshold [96x96/status] Size=96 Context=Status Type=Threshold [96x96/stock/chart] Size=96 Context=Stock Type=Threshold [96x96/stock/code] Size=96 Context=Stock Type=Threshold [96x96/stock/data] Size=96 Context=Stock Type=Threshold [96x96/stock/form] Size=96 Context=Stock Type=Threshold [96x96/stock/image] Size=96 Context=Stock Type=Threshold [96x96/stock/io] Size=96 Context=Stock Type=Threshold [96x96/stock/media] Size=96 Context=Stock Type=Threshold [96x96/stock/navigation] Size=96 Context=Stock Type=Threshold [96x96/stock/net] Size=96 Context=Stock Type=Threshold [96x96/stock/object] Size=96 Context=Stock Type=Threshold [96x96/stock/table] Size=96 Context=Stock Type=Threshold [96x96/stock/text] Size=96 Context=Stock Type=Threshold [128x128/actions] Size=128 Context=Actions Type=Threshold [128x128/animations] Size=128 Context=Animations Type=Threshold [128x128/apps] Size=128 Context=Applications Type=Threshold [128x128/categories] Size=128 Context=Categories Type=Threshold [128x128/devices] Size=128 Context=Devices Type=Threshold [128x128/emblems] Size=128 Context=Emblems Type=Threshold [128x128/emotes] Size=128 Context=Emotes Type=Threshold [128x128/filesystems] Size=128 Context=FileSystems Type=Threshold [128x128/intl] Size=128 Context=International Type=Threshold [128x128/mimetypes] Size=128 Context=MimeTypes Type=Threshold [128x128/places] Size=128 Context=Places Type=Threshold [128x128/status] Size=128 Context=Status Type=Threshold [128x128/stock/chart] Size=128 Context=Stock Type=Threshold [128x128/stock/code] Size=128 Context=Stock Type=Threshold [128x128/stock/data] Size=128 Context=Stock Type=Threshold [128x128/stock/form] Size=128 Context=Stock Type=Threshold [128x128/stock/image] Size=128 Context=Stock Type=Threshold [128x128/stock/io] Size=128 Context=Stock Type=Threshold [128x128/stock/media] Size=128 Context=Stock Type=Threshold [128x128/stock/navigation] Size=128 Context=Stock Type=Threshold [128x128/stock/net] Size=128 Context=Stock Type=Threshold [128x128/stock/object] Size=128 Context=Stock Type=Threshold [128x128/stock/table] Size=128 Context=Stock Type=Threshold [128x128/stock/text] Size=128 Context=Stock Type=Threshold [192x192/actions] Size=192 Context=Actions Type=Threshold [192x192/animations] Size=192 Context=Animations Type=Threshold [192x192/apps] Size=192 Context=Applications Type=Threshold [192x192/categories] Size=192 Context=Categories Type=Threshold [192x192/devices] Size=192 Context=Devices Type=Threshold [192x192/emblems] Size=192 Context=Emblems Type=Threshold [192x192/emotes] Size=192 Context=Emotes Type=Threshold [192x192/filesystems] Size=192 Context=FileSystems Type=Threshold [192x192/intl] Size=192 Context=International Type=Threshold [192x192/mimetypes] Size=192 Context=MimeTypes Type=Threshold [192x192/places] Size=192 Context=Places Type=Threshold [192x192/status] Size=192 Context=Status Type=Threshold [192x192/stock/chart] Size=192 Context=Stock Type=Threshold [192x192/stock/code] Size=192 Context=Stock Type=Threshold [192x192/stock/data] Size=192 Context=Stock Type=Threshold [192x192/stock/form] Size=192 Context=Stock Type=Threshold [192x192/stock/image] Size=192 Context=Stock Type=Threshold [192x192/stock/io] Size=192 Context=Stock Type=Threshold [192x192/stock/media] Size=192 Context=Stock Type=Threshold [192x192/stock/navigation] Size=192 Context=Stock Type=Threshold [192x192/stock/net] Size=192 Context=Stock Type=Threshold [192x192/stock/object] Size=192 Context=Stock Type=Threshold [192x192/stock/table] Size=192 Context=Stock Type=Threshold [192x192/stock/text] Size=192 Context=Stock Type=Threshold [256x256/actions] MinSize=64 Size=256 MaxSize=256 Context=Actions Type=Scalable [256x256/animations] MinSize=64 Size=256 MaxSize=256 Context=Animations Type=Scalable [256x256/apps] MinSize=64 Size=256 MaxSize=256 Context=Applications Type=Scalable [256x256/categories] MinSize=64 Size=256 MaxSize=256 Context=Categories Type=Scalable [256x256/devices] MinSize=64 Size=256 MaxSize=256 Context=Devices Type=Scalable [256x256/emblems] MinSize=64 Size=256 MaxSize=256 Context=Emblems Type=Scalable [256x256/emotes] MinSize=64 Size=256 MaxSize=256 Context=Emotes Type=Scalable [256x256/filesystems] MinSize=64 Size=256 MaxSize=256 Context=FileSystems Type=Scalable [256x256/intl] MinSize=64 Size=256 MaxSize=256 Context=International Type=Scalable [256x256/mimetypes] MinSize=64 Size=256 MaxSize=256 Context=MimeTypes Type=Scalable [256x256/places] MinSize=64 Size=256 MaxSize=256 Context=Places Type=Scalable [256x256/status] MinSize=64 Size=256 MaxSize=256 Context=Status Type=Scalable [256x256/stock/chart] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/code] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/data] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/form] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/image] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/io] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/media] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/navigation] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/net] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/object] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/table] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [256x256/stock/text] MinSize=64 Size=256 MaxSize=256 Context=Stock Type=Scalable [scalable/actions] MinSize=1 Size=128 MaxSize=256 Context=Actions Type=Scalable [scalable/animations] MinSize=1 Size=128 MaxSize=256 Context=Animations Type=Scalable [scalable/apps] MinSize=1 Size=128 MaxSize=256 Context=Applications Type=Scalable [scalable/categories] MinSize=1 Size=128 MaxSize=256 Context=Categories Type=Scalable [scalable/devices] MinSize=1 Size=128 MaxSize=256 Context=Devices Type=Scalable [scalable/emblems] MinSize=1 Size=128 MaxSize=256 Context=Emblems Type=Scalable [scalable/emotes] MinSize=1 Size=128 MaxSize=256 Context=Emotes Type=Scalable [scalable/filesystems] MinSize=1 Size=128 MaxSize=256 Context=FileSystems Type=Scalable [scalable/intl] MinSize=1 Size=128 MaxSize=256 Context=International Type=Scalable [scalable/mimetypes] MinSize=1 Size=128 MaxSize=256 Context=MimeTypes Type=Scalable [scalable/places] MinSize=1 Size=128 MaxSize=256 Context=Places Type=Scalable [scalable/status] MinSize=1 Size=128 MaxSize=256 Context=Status Type=Scalable [scalable/stock/chart] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/code] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/data] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/form] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/image] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/io] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/media] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/navigation] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/net] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/object] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/table] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable [scalable/stock/text] MinSize=1 Size=128 MaxSize=256 Context=Stock Type=Scalable gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/000077500000000000000000000000001345766322700222275ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/apps/000077500000000000000000000000001345766322700231725ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim.svg000066400000000000000000000464771345766322700266400ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/000077500000000000000000000000001345766322700235525ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-away.svg000066400000000000000000000631331345766322700266620ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-chat.svg000066400000000000000000000712641345766322700266440ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-closed.svg000066400000000000000000000077221345766322700271740ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-connecting.svg000066400000000000000000001555461345766322700300620ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-dnd.svg000066400000000000000000000756541345766322700265010ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-error.svg000066400000000000000000000706331345766322700270550ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-invisible.svg000066400000000000000000000656241345766322700277140ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-message.svg000066400000000000000000000355731345766322700273540ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-muc-active.svg000066400000000000000000000255541345766322700277630ustar00rootroot00000000000000 image/svg+xml Group Chat Jakub Steiner group chat IRC internet network gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-muc-inactive.svg000066400000000000000000000267531345766322700303140ustar00rootroot00000000000000 image/svg+xml Group Chat Jakub Steiner group chat IRC internet network gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-notinroster.svg000066400000000000000000000472221345766322700303100ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-offline.svg000066400000000000000000000504431345766322700273430ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-online.svg000066400000000000000000000471111345766322700272030ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-opened.svg000066400000000000000000000071571345766322700271770ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-requested.svg000066400000000000000000000664131345766322700277260ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im ? gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/dcraven-xa.svg000066400000000000000000000631271345766322700263340ustar00rootroot00000000000000 image/svg+xml Gajim 28.10.2006 Josef Vybíral http://cornelius.gimp.cz gajim jabber im gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-bytestreams.svg000066400000000000000000001144351345766322700310260ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-conference.svg000066400000000000000000000255511345766322700305730ustar00rootroot00000000000000 image/svg+xml Group Chat Jakub Steiner group chat IRC internet network gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-disc.svg000066400000000000000000000764721345766322700274160ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-error.svg000066400000000000000000000135271345766322700276150ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-gadu-gadu.svg000066400000000000000000000314461345766322700303220ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-http-ws.svg000066400000000000000000000374701345766322700300750ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-icq.svg000066400000000000000000000307701345766322700272370ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-irc.svg000066400000000000000000000212321345766322700272310ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-jabber.svg000066400000000000000000003544431345766322700277160ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-jud.svg000066400000000000000000000436021345766322700272430ustar00rootroot00000000000000 image/svg+xml @ @ gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-mail.svg000066400000000000000000000355261345766322700274110ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-pubsub.svg000066400000000000000000000461561345766322700277700ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-rss.svg000066400000000000000000000245121345766322700272670ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-sip.svg000066400000000000000000000311301345766322700272450ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-sms.svg000066400000000000000000000650621345766322700272670ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-tv.svg000066400000000000000000000301721345766322700271100ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-agent-weather.svg000066400000000000000000000271061345766322700301210ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-chat_msg_recv.svg000066400000000000000000000610201345766322700301630ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-connection_lost.svg000066400000000000000000001610601345766322700305640ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-ft_done.svg000066400000000000000000001152641345766322700270070ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-ft_error.svg000066400000000000000000000410711345766322700272050ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-ft_request.svg000066400000000000000000000413341345766322700275460ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-ft_stopped.svg000066400000000000000000000451351345766322700275370ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-ft_stopsvg.svg000066400000000000000000000451351345766322700275660ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-gc_invitation.svg000066400000000000000000001337201345766322700302230ustar00rootroot00000000000000 image/svg+xml ? gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-mail.svg000066400000000000000000000355261345766322700263150ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-new_email_recv.svg000066400000000000000000000406021345766322700303410ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-priv_msg_recv.svg000066400000000000000000000523121345766322700302300ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-single_msg_recv.svg000066400000000000000000000414051345766322700305320ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-subscribe.svg000066400000000000000000001320201345766322700273370ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/gajim-unsubscribe.svg000066400000000000000000001223701345766322700277110ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-away.svg000066400000000000000000001713061345766322700260470ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-chat.svg000066400000000000000000001224521345766322700260230ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-dnd.svg000066400000000000000000000751321345766322700256530ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-error.svg000066400000000000000000001717751345766322700262510ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-invisible.svg000066400000000000000000001146341345766322700270730ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-not_in_roster.svg000066400000000000000000001117511345766322700277700ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-offline.svg000066400000000000000000000153531345766322700265270ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-online.svg000066400000000000000000001141311345766322700263630ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-requested.svg000066400000000000000000001215031345766322700271010ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/sun-xa.svg000066400000000000000000001066111345766322700255130ustar00rootroot00000000000000 image/svg+xml gajim-gajim-1.1.3/gajim/data/icons/hicolor/scalable/status/xmpp.svg000066400000000000000000000060611345766322700252620ustar00rootroot00000000000000 gajim-gajim-1.1.3/gajim/data/icons/hicolor/symbolic/000077500000000000000000000000001345766322700223025ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/symbolic/apps/000077500000000000000000000000001345766322700232455ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/icons/hicolor/symbolic/apps/org.gajim.Gajim-symbolic.svg000066400000000000000000000124431345766322700305140ustar00rootroot00000000000000 image/svg+xml Josef Vybíral gajim jabber im gajim-gajim-1.1.3/gajim/data/iconsets/000077500000000000000000000000001345766322700175365ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/000077500000000000000000000000001345766322700211605ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/000077500000000000000000000000001345766322700217455ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/away.png000066400000000000000000000014761345766322700234240ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8ukTgϽw>1HZcblFA$Pꪔ.,B+ƕtםŅta u•J II5|u2Ӆq?QUjo_z\Ve#z2YJm`|Env7}-jJ/T /+Nm̩U)l+Y P˺ƖM 1$>كZ Kbǫ ,P6է .5huʪ? UÕș@#݄L06u×+컣q|FLl鎝;l>7sIݻ %>ǎ^Hvnw>ֲJl ~~֮,}FǦxT<=L5vѺx̣_-ςkc9ѧDkHvz+3܉6wlnJuG[{^ BXkpJ0?JdҳIk cvxOɶt~1` b&͔itN@:SpaZc 4 _A%¢g9r0i_EDFշ-kqAK/{sj$(,h$:!ԫGb՘cJ 霚IհTI I6R,?0Dbˉ76aZoufIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/chat.png000066400000000000000000000015331345766322700233740ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uMHTQsqN꤅ӠST:eR-* f\(h"菰M%Dm40*SS1zsZc}{{ ){\ (A+c]$zµ$ %Kd{JfId/av!xM@vVOÉDʽKb XԓW .7yp-ʧ@ A0zyqce2E BGHeQ04s5@Օ@̺ es^=!SըjpN( TUЀ^__j+ZB_fB%R.ӈ]YH iGp=t&zy9*^ze}ҺC~{nZaK j'NneANjX|hC}cA_W/H̸KͰ =Aӂ-}'Q쿊`?SZSz-pS_Ʀ,pS3HU'st{Eï /jH`_W %G=Z ohbM+,4e6Dh.X80 m&`6q >%9ȑ2`XR./ap4* K=#]c$@ ` . pcM9IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/closed.png000066400000000000000000000002741345766322700237270ustar00rootroot00000000000000PNG  IHDRabKGDtIME  (9m^IDAT8c`( _r-\6\a,،.+Bp^```` e```' {=\%:п-dIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/connecting.png000066400000000000000000000016501345766322700246040ustar00rootroot00000000000000PNG  IHDRabKGDtIME 9+O_0JIDAT8]Kh\UsνsLf2yifRlhJj- Jŕ\IU]ULt Uu!%bHEF)$L1Lgǝ{=n>9sK%+:0%,LjI/N^ӷ*ufvcWRwmڒnU[Gmth۷NfOlFsᄔhD!,ʬmVXK m-"XJR\85-iGuY:4˹2 CCh$uE)c+zw c Kag[SkEDIBc4nDq{.k+v7}1L[$ah [pKJjһYFw[/]8u]4%]Y͗{1[]aO^{[^6#E \)$_̧,]un}IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/dnd.png000066400000000000000000000015101345766322700232150ustar00rootroot00000000000000PNG  IHDRabKGDtIME  0IDAT8_h[ewNN'inKJڴVQ2[ֺ,j Bxo*^PA;zlNjR6d8Y64KzN>/Ɓ/ zP  W66PJwi E*X֍$w@*-IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/error.png000066400000000000000000000014601345766322700236050ustar00rootroot00000000000000PNG  IHDRabKGDtIME /JAIDAT8MhTwd21dGFeD"21*nMdH MwٸB5,%|V0:dtQQ9{慨kƨ>RF˱|\-C^dǩh0F35=inl)0PE;;bW9n&SQ "PJE>#pX\Z  L{ _h"[7T֋- kbm硻fXaC] ropz6:ˡ[ݗQ۾-}??Hu3lnjeFF.isG񫝄*xͪ[nWW>':'ϝJ4~HX`|o"Qyβ~>x2Ɣ0;$:N|.wX]Ϳ.GHF=AW9{c CueK#c?J Wp` UR|& EZlffFE)lC+EM:ֿr5酅`-Z hMP*m<] 6bmn._f%Ο'ӳQ6{48RJf,k Ej7%ܐl1&1?rNL9kGPa+BIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/event.png000066400000000000000000000010351345766322700235730ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8œj`LdfƑ:҈tV"C;F@\.D\JEsfa4V@2;&:J/yrNƉ`޹zqMey=Zq8em}8T狽gH-q89r,ۢ1K0 ( IӔh}ʲdRLQC%zG v?`vF$BKU\ʏ66&ibY6;[%hPUZ$Ix<˰l:!@QJܼqfg\p:UUEQlzZt:D*պO|'Ft_qG[^6ݣn|uޣLu&˲>gy1(%&IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/invisible.png000066400000000000000000000015671345766322700244500ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8KLSA{RKS-"֠  <$(KW$hb;K#+|ą.X1OD hUDȫHm{K_5s\ gy~< V#skX #6sfRwO9PU/H_ins鉂J= nT&x#!A}zQ2wTxCoϓWè|]d yH7=ML#q`ۋȦ rũA=mcnb-7B"J"=LaeULy|T}**Xn3G/j(Qy n4V3'{o!עUpئ>{oycJdrsM7[wf어`Ϩ +!g: yQ4,?=i729Kg8rnY 'klPy)5zeo-q: <竝MY}w&3))o/)|QFE(ƤXQe͇e@)׌! CZ-L1BAmBN, A0]"C@`00,ڄz/ (0QJh)-)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/not_in_roster.png000066400000000000000000000015031345766322700253360ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8}kSQƿs͍**mmB7q>׮|#½ "X *ؤj>BkmM6i619g\H%0 #"Ԗu(ߐD1NJy)d?jY-m:ϜtbT*u`Z߾psy@<,oZ=tFG]`M;;d78X \/!lXӥ; sՌg/$ an9p8z=,IE MMMBGr6́͛g?!_^ŐLnoձ#}j,fLj5[`Y~]{ tgxRJx r2%WRS`옘Ң\MD ;<8tMT)MtX<4liIB2\xKĤ^IK ;ik  "H DkK+2\>9z+R ir $ DUU RmcUMQ)@sښ@lCBfP,kYTt 84 JR2d_B~ تm`STT@>_@BR.W{ѕp{8h#c, JDV{~+e, IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/offline.png000066400000000000000000000014541345766322700241010ustar00rootroot00000000000000PNG  IHDRabKGDtIME 9-< IDAT8KhSAIMҴkbSAmJR)J}Z ۵N\FplO4TQQ5Ucj&MwθK;??|~Hv"ZZ~ i/{zzb93ݻc:uhh(={9DqkuF#QV*q(b$ PV IBBX* X>tww76mV7lhckl1{BٙOt:mq/utx(зӆU'Oe=p;x ;t(=jo岉Gyl^߄YG\oeYCHM;7+vWln4~U[:rDZO`z&7EdbՊ fggkV77p}1f=Ǐ&}L0}Ԁn0Y*becq]dC@ 4M9:zöm[1"<?kgx<B)9~ HJ!$һۓw]odrBER )AD4 z;$0FXRR D $ P*0TD"!"~8 4H$_Tճ䳦Vi@) UAaTE['MLwDT|q!ML[ Lk|IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/online.png000066400000000000000000000015111345766322700237350ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8}oeع`.BP!(MJĂұ $6$*6@[.rC$%1&|{"Hy~z9*3îyL8ecx{2 Zr艳}䫂QDoi`͓-tnG'7h"{{\;p,<#9+5~gs" p\)A +mJ2پ6@zO`CΪ7F}\zhʍqqċ>Iz2:W:ayƾ +֪\Pouy}x7/x}Rj1W_hfPX(3E30S4rGO_2֯*_ Nw|V9{R/OI{RNb0>7"Hze.V/;NIbU)prx4EO8QW,EJO ":Pڪ;Yo傽u GtrƘڔ$' NFp d| iIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/16x16/xa.png000066400000000000000000000014751345766322700230720ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8}Ohe?}vYMƦV^t(L!; de C2x27OE80;Ńd`lnvZFMy~e/n灇*qS `kn6ޮe+ؕ>*:gue|Fl^ovM/D='D9l}De<>?q]ok\3 00x驀l^YknO;S3"CwֵOeNUv[ _O6#2Խ)ߘ^Z=,}-..$p4mv |KcT7{w;k+op*sTmJwJ|| <2:btjFapbbvɓcc۷i_I&94Ofdy;~]uN=%/RӮN-t+WaP=H3"g2͡E8kLNV.W7_?LTB-kAVQUs* ݀{r9pۀss T{OxSuREFFxyXŐA*Xϩ<؎ZJP:KhCX|rqQTxBXV^#X_><b0IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/000077500000000000000000000000001345766322700217415ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/away.png000066400000000000000000000034431345766322700234140ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗ[UW{;0õP)r+X(@mژJ֢1J >>T/>MZJhJA,w8esc.9sk}>s)LGh&srNo-s2 !҈M({='+6h'RM w|Ώ+R}wt魂~o}um5?_ܸ-eLD{[:j 4|wWo `߫-4Qb|0v pQ?~f-NgrbyW҆h[ 3[>9eL11L0ƯEDKwZPʋV־% ֈ+ĘyԵcI#&H1n&L^ (V]+4H!b'S `+Oelԉs9QFZL8؉i7(WFxqQ6…gQC]!L0Z7gۗO_$pQ'6F]8{ gq.Z})759^pl I<+[vn\ f"&0g ˝x)NcOʧ76&geAMzw~Y|˦ g% `ov6sgC4b۲z~'3 bfC xy_+> Q-˳K$1ތDôܟg030 y4,@X(_bb%) v3 "qVoh<iDR]z0̤D(>!%2xLIL (岄ršl.*ežo@TS܌n"R*ޏP77C8@<83 9[LH>m7q;jFz zmBܻaO1W(fIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/chat.png000066400000000000000000000040651345766322700233730ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs B(xtIMErtIDATX͖ilU3λo7  a_@!,lp(K4QӄV TW!RTRДM K1%2asjlサΜ~q XCG:pu=?^om4w=7.nJ=ݾyON=@U92%ë`D^.^fUutOX|p\]]th^DMe p#U@jn M `V|LylDuj-m޼9Vd9zVb;vX[lrTxcz|劕S*U Fpro?]q Zp)k 7(Z5s`z u1c,ȑkF Ƃg':\ʼnGe4Dѕ8)241P\KH"'3H ᩥE4)H`>}T %[`LLòyuسfc R*x#+q twb^-z_<P \KR&us_ĢOb~"!sYgϞq]޺ikըKy;IWir"J@*)㛐+Mxgg^Y*,{)b""U"f,6{TJȍlɘp<2AJ!-%%OZE~=nذ{ >(g=wLZ @2hibT-{ ?vtt|˖-#+3tzg,C s0P ^™ߤۉHO]R]~`x( )1%РE s#BIϽn4~U*vZVƶ 75%..~ RȋXp=r7m:Eˎ֘=Pg#/4imڏ>;ۿ$҄Y,yf Mp(" oR Z.#++ + ?Z1qRzvDv\ S ʹܾ:{L~K O}svޒu~7pmFB ө?ᙁs55-mN!U@u E6[`ja;q5` ^K7st!u!.;q3~BHs03Th ":rB2 +cE@_X)!Dc޶ʙZEx+'=&5K_8yUmekMAo V-ⵈ;~a „YBh>DԲS댷莴_lMf`Յ6Plz~">}0'k%Z/%:߫$F캲2 oPc}{ a!{=\W=kp`u9҂!P rX@݅A1笹@@ = %3E0L`2#5=fZ`Wdd#)>D  <:.2P$%!n(`^"Gz<#2 ܀eL?2ct7#u9ɻѫMH8qIcvū ~iO–qX^ -=  4?t4.`0LT0ȤH'>mH+xAP3 af $8L'Ie$<Ӎ +n9yz{`@$ϋ\V`ag0 F9hD]t˵4 }}q;fTO26,yc ixo:YjIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/closed.png000066400000000000000000000010021345766322700237110ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATX͗N@/+> !Dj荘PJ}Cwhښ:!# ͸rl>m zM~?:s10YD# @V,@I :" \V0 +ܠ ¾.8 h~wBQX- |{!$wP3bXu61=Lsq yzy@Xas&90f WQT:C8Yֲ,Aq 5vthuvͧL^F( $6@HuHmI:e6hBDhPn&38vy82RWgiIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/connecting.png000066400000000000000000000041571345766322700246050ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME ;'t߫IDATXŗilU3w}7W؎@b JJ* JT5jZԪjA|C4|ITR"%UJp@%`V`̝3𮍱,U{9̙, ^n `k<%CH;tfsnwo^]Ī#5iLŹ+#ȉo+NE:v~k}y)ސsd=Gm( _(R@_>7@#5q-z򡕦002VFAϕ LzBY@U҅ sxb_hEw~G5ΐ8{=38g 8g α}]@$ @w=6&|*@ö=Q۰tAUquD ѬtTgB*x 2Q]n#106ͱ2gF'[}B4p9qԔ 0uS04]5 \.T89ch"~Gb6hyٶx'43e}tuBYclF*+\G;/e77150BDp#.0" y{]Z֐. b=:59MPg}ֳOORadE@ Fh33LCg',0tѲ[?s/ jY:s>$):) I HDJQ-H)X c}8?s:)w5B>4']]R.Vkc&43c)NiSy q0np @HkZ*׏d~0[6Ƽ{yV 8D8q)=~gF`i`j0fbAjnG@i(,)7z;;pzQ:LаgvC>u@~R4>#Sјҩ1US3y}q_}eRIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/dnd.png000066400000000000000000000037051345766322700232210ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME*rlEIDATX͗m>3,;/X)Uh TmU iR5iimZmMmRZB1YȊ²06s^6bYSL{=>?n~EZ>֢j12@9²mv&z%?)W:"Gݮxsa`f&Rw;T#fo/QE _XxK+"/ZΖQz:61DnGkȍarc9z/=(7 ɣ} G91Ml$-w2aƕJQʏxGNDQ: wS۸TrJsx$ԁGQF)?QZºI@e1 Ԃ!H 2ǸY"{Bg_#֌b4Ma ֌!6Wch,rEiyx%yzth "u/Yq ɏޚJ<}lsjcujV#0VAb&s[7}[6M״S|,leb)~:~Ȟܵ%ud_p?U;Z? _zwy9>Nps݉RyPp2&CPH dy|ufUtoZ>&vu Mر~R\c/l{[nt}' avZbL Kwb6wzh}uxt]<*N ܵp~gg1sh#)ڱJBh& 97H:aѲ~n?"2 Z-}_oWCw?l6z +Beފ`uh_?#.*IgQ߰ԑ!>h8E.vt;8H||'M_[Y{>PEF)1 "ƋHV. Pe PJk"輩p7@9N/^ew-Txa3 X9sqOjZd>(g}ajؑБɔ VcHE771`ȱc&74tZ'j m,h^ :5u _^U 8:i4lK& N@C*u]==O8޾F>.j[k_&/J,eD)1ciW[ҳny@yp ֤nX ЪlTiR'H-ɻnѓw_T'3޽~JFjS윎G50jo"IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/error.png000066400000000000000000000035601345766322700236040ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIMEqIDATX͖klTs޵Ǐ6 i񋖂L@!Bℨ4iUJUdi"Y:D(~(mԤ ȁ@@ih`ގŏ]{9bJ^itݝ;7s?/y?Y&WaCL''ڞlL~y` Mࡃmn8]?(x[CJ)$SzY03L@8\fƞ=X<־77 k~Q8p?dS0 c"6""B!X?N%7V+WH4L&uC4n ˗/(dp—>,Y @zEM|=7 rlˆRJd  ҇e - nRB4tMb35 ^6 M7LM::6ʆa@)$""74166ƺoQO`C*ʥcBA?^*HB:93 ]fŅy9@@:,ܹ~pXtV]EEAQ\!~|Rc\bT+K/m;q2ܰ0m5ZE0ML&N/Om2`i5;j  /NOPΝ\BMsp{D  d2ADO pp __bLe}y_XT bh'8dċC8 HAkk+ٿiGASg0L@J?YVZb4 m#9'G0:1Kͤ (NC _[ܔJ-rө?G^o_ͻ~'O@&iNdΜXg65[n@B)ij午~ܼ2@P]UKS)104v]4,\[HODHoۋ0+*M ՞NgOvyf#eiPȯEetA@`*31/2fF0ˑ@0v]p%B !iю;7n%c+ϟ=Çuy LNNnJ%qn,F14<8 O>ݻR _7ut(r^u|4ziA7zg09)32%9WY[W^ (Uuu>EEiQ/}X5yA&{/aաPk:xt:>J`Y֜y9 (bx:xakE X;>H093&"g |eAfH)Y}]cD ݸb<}&)8xvC}}nhmo 8PJE4K0" 0r{{q[Z؈==p>md"ϑ-=D{qrťիp^$wY^ @K$܁h4j[ˑf<b5/} n ɼhMMP;Cb7m|uK/U^QtDqq1 Äa ]GvhBNX755G"_ ,۾C&B,(zuqQ:@~_bZ)dsj;&.iIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/event.png000066400000000000000000000020611345766322700235670ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATX[OTW}\Q` ѴD}(MۤMcSA" os_?`jADkHƪ(M^fh0w`ƌu ᅕe_RmKolz->O&R*}Ee۽h'(PJ~l%T%RJσPo&D>ߞC)Eqfv395a:|1߸Fsc3boflU; v|x ie/B CrvVxes wǏ,+]ea&btt躑esl]ǿ ˲4OQR_`6ޒVF}I7~iY;4Mt\J^Z΂3iu]} ׮be8,;. m+6fgg G”PW[GiI)/' \U̧ "L ySSTT)@)>m;\|rv2==M8QTX[zbgEpa<bY#|B%,& F /#ٶmKd8k,^/ݾ T^+(,,"2ffff!RJ)}bb?S$q>RJ 0>@ "%0Rxͷr,˾  !f<TRʳByԝ_< 0X@,ع8Wn =g `: !4^1O\\)F5Zm-vIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/invisible.png000066400000000000000000000037271345766322700244440ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<TIDATXWkly쮽k/zY^6 c 4M4BMHT"BZEFQ#j JTT !ccmwkwn6kz33:s~sg!> GwWy9B#1tljGG*SuM}UҰʾ gŌZTk׿8-]X yN#WvN,e=?AV2fX7Nq4rĚ-#pt7)VYdSۯ@U13SDxg ?p`X['-02kLx.S|F4UyvhIV.f*Dnu^tXAKAr#}Z\7Oi37Kʙ~s[}0Μv8J! A)z7{fXV|ӆ{* eAL0+"P;}æ<`3`C*]M S=0?=NU"`F ` ,,ȕ>8vƅY5\ !,E$>̟;SJofo<1=D`^GmRϚ]S] \K}~9~2Zf}W{jъLR7M.K֖wn3` sx=jˡ"}u;7n^?.<.4ޠh~w.D0#Sl1o,f fU6vjw,oMڙ/D,eX"٣bBE?]v;j } V"l8 )fT}vc%Rl,%Bܼ9%wD;>*RFtb+5}@Rw2 ]^]nGRKg5%aidM؊Ol 1n^o@dlt+gy+V;yv"B2>J`
[Z ~+‰PF؃U6|iRƊ'0,ÚQ9?A8tDM٤Ҥ "M&K,Q ˃u \r5S~NJO %JiM"Y(DK!x)年\suSEd.b$3!b&/[.TXT"Q]Tpd`oȐms!FD!yUFܻ3sJVK*Up*nUN!D8OezZO\BOgDv$K#㿶N ߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/muc_inactive.png000066400000000000000000000017761345766322700251300ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# #13 5a )\v "I&|9睂e+Kׯu\?{˷hJ_ Wz_k"lU- w]NHWSV:yY{CU076< o; &32sk L+; 8 r9IL4MQ+<~XtYunU8jl.>fK4MH$A,7@e w=8cSk(1K6o{~ F.@Jyi-AF@7v/4axv} ; =u bBn*X65IrQ$U1((ضOLɯSWD[k+lۆepq\HCthCӡ*TUE @Pח7f-4 V{VoW(=Q^^AS  0 f: =UP-Xqm y[ѧx[]&o=p@ۺV4Ѭ(Z(͜#0VE0$>?Sɢ^K&`gvm)=FV+/XbIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/offline.png000066400000000000000000000034361345766322700240770ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs B(xtIME9U]IDATX͗[l\Gƿ9s޳kǷ㢺&:(ڸ⭨qnN(D$ *U#LAR^TBiS' QЇ@8vk[Mn\vvn<쮽1m#OsV:s<ȧ]pԩ&˦YQJm؈]Y/k/ïQzj׊Ҙ.7|U8򩯴4dϞQ2a1,ĝ8~79wqWW HdW8RIB@)秡 J)cqhm00ZVK~һr9xJ9Xc 20JlƎ;Ԋ[ֻcaPc c 2PJA!{!g]@J )e%>$( k8ׂL0,@$(C,Ӓ[J)(UTZ+haʲ,Bynoߊ1B Uis)%,z!&F%k9 wo})JmF&e `37n~,;L =ܾ=΄О]J1?ϗ.cskNOMLfff k wCu6޽wo8<ߏQPfq1ܹXa!ĵ_C%'}{Dj_<ԡ7vo#@)g{~q dhZvuuafvּwAo:HߗmѣG211w֌\I  H@ՎLƃ1 @2D,#۷ѵm-_2ؿ~SӓH&硍!lRcj( 1zMX_KjѸBi6lA`y2lho~uGb~>6((4\ϭ"vM͸N<աss7̲DX̂m<~}a.w9sF,׏~ĎFSm]F13; 9 ,˂& L& CBX,h cc"JskW %S뒙wtmxb.1xUyA:s?x 2*W6r\q3 cE *sbk6@бݴuY1,hc`1 Fөf% ( (?oԺ9d*B^U$1 "vd|Mc[1H)!JfҿPBzvb&U[7`U}1Y׭au'u`d|~Bdsy!> @7Uw={䑭9uk"6(ڬ!FE N _ZY֗UB/RߌE?V}IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/online.png000066400000000000000000000034351345766322700237400ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs B(xtIME*tIDATX͗[pUWk>I iJ҂0V:0:q-bRdl}C}J[:8>0v@JGh HH${HNrn>rb4oz]exNDT"" <%zqDܵv,Lo®]%/nYx'S/-iz-u@Kw"⣬j YxwSP]F8:&#f f0͙@VDo魍+zӀ]+Qe% ¶ KNZ1ވo}jJWVkE$Jr*:qrQ'} i$F'a&ńgD(倲PJ0a7D-Fh5R9@pcD(]@۴@LߡL8J bL82"Hԓl ]`"> ~p]DGJ1}*4۳So\~/_(A0 02:r/ N|s૿u?kٲI6UWԹk?ϲ08i>l?2/숌ڱٛhDz 'xŢkx%]N;ʻ֣2ƈiASX=-A&?p:2򭽛3Tָ>Ȋo'Vu[;1fx6LqfNWH9#3k_f)ϏnNYA$8^eyryrJO!nS]br~fB8h_;R=d\Gs{kjF=6'Qe'9"*="Li>Ej'ŝw +m06aiy:ש 0n}5S0%\ppTy^}7z%RP~TuH0FE9#rU8vLVMQ< pʧIRNPAI-AVTWRd$>9ǜy [xVjB0 &on:1?m(mh1SH43-LGlc ̴%ٔ MEJi{ ˆ.cm_r,^Njxa`Vq,`iW)x#aQzױ.mMDe'-׍P#frE?/b+db}?’x8'&FgArjtMF+Q %50tEKr7 3i07g+X iL'IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/opened.png000066400000000000000000000003361345766322700237230ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<[IDAT8A 0 'E|}BYoJ+C6& ]0/SM~Zք$ݳo޾ "GvAg7 %$IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/32x32/requested.png000066400000000000000000000040121345766322700244450ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME :$bIDATXŖT?fggfgwaaWtTZ%"**%XukϦ?F[j5MckMZD[돚6HAHe+²̲VX޼ws=?/l; qr* l 9f[s۶'w*b˝R|Fvd=+n]m&+ ;Y?{IqqGQ)KxoFJCw-_4W7ojS/oEGm(=Z/"negy;ɼ7}z"a;fοA^tx* RDMԡt ;Zϼ!PtL$ı2ݲR݇RJ `;A:Ht-JP*-nea儒"/D-b4-ThRxGnDƓVC 46tP*D| 2"LN(es1M[.xso3x7BƏ(drlYtC8{o.y /g#̚&hι3&o"~qy Wӳ{7̣/_n׮]rǽn=EQ}'mޛW,ici/vDvYbK _w o޵ V.}מ5g"2OiO> Z@(eXujj1nRf0Ǚʷۏ #qXN%7]Ym8j(U Zz{v7^qb+op幖SKҘN?W>on{`jд.ƍWՆQL 3Z6HDhL2\eמ d2^}ZFG]D Ώ;/LT¨1FzZE3>53XY(a#'J۟ TKk۴{޿zl=.0ZN-Y4/N&*W YRIR^V{ $ CByGknt- bCc uر1cYmh=4i~Z  )c,[uc,Ze?"cJ-9CRL^ LNNB3#.JQ*bweHk_DM_JJ1󮏢Ϝ:x&7SN`ۑ RCqcn-:x2OR܄< 9v P]$t9!Lvh=&~[a%܉pEȾ@1ן0 ]eis~:^*6 bG`DuOsv8Yl3ldsRG1+W=(:8ri;\߷ADIyv?oC^m|[b;{IğO@iaC~tmҁWEbsYt]:Ex$ 7uuGMU%HbRv[TW64 2oU:Y{`MvzWW_6mޜ˗:'TilFP?O4<R"ZZpV$sl.yry/W&Ro xU;v$Bx߫3i"Llma]K5•l 0ȅn*EՄ7"ĄK M$(gTL&3R*}Db<& 2.L+Lfrc;冀X"A4:Qҗz` :u HP8SkԙZk'xd<Ȉ'4g%Iꤦ:`d=)r>PbZ@F> .HaƓ*3g2855xWc Ib1A*?:u@E< "6x>7dvL9_-9gNk…a2tR%y*DR>O)P, BrBx'҉aI("7bOi14WCs"+bp7FE2|櫦НKг.L Ln-0~A0~Ni)NIIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/48x48/000077500000000000000000000000001345766322700217575ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/48x48/offline.png000066400000000000000000000052021345766322700241060ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDAThYmh~}$ْ!i̘uiN\%MhkLivc_Y2 ,ll:k% 6]I'iNu[^ɒWǽg?^I3ýsϹ<_km_XnnnRvYW؝Jk ' ZY$! 93MCCZc_~̝Xؿcmᮮ-|!X "C3 ̙!G=Kw ۷Q٥]7EQ<$$P̬9tj=Ck=5m@*5 n(\+u4D[ծ*ܲ[LA#>j38L uuO?w}=m $@0" As09<4jXs9]"@)̟ ]DSS隺}5VOȮp$s$<0/:?p\HZqmU IB:;|':*BxP$I[ Uy@ѕc S!T`YPTej3$)%R@TH!UTe#N1:fOǬ@0* *ɕ 칳+~fvT:5zG!>+&.yDvmB9经ewֿF}}vLbr9MVmiW_}9u]1~$H>IPOfsY(e _$ׇS{duPݳ?{쑟+x:7?3F>V"BG&}Rlǃ(ŷ7{؎ɉJhI"躁h$h#.\>eO<·b%4+zw K#mp2UhbrQ(:p98v=qz]tə$֯K}χ~w}sD"l[x<ʩo=ƾ>erR$gee BK$~"I MXH!uU6\$&J{alåKޑwyI$-y@Ƿm`G'<Ǘp\mmB_gC8s.W2f} AwՎL6]-_&Q؟ǯbÆN50|Onv>dI c*Z\WDs``D4FNף Lsb/8W`:tMtvt_رB1vD^-X3onV HA GUUADp]EBv6uՆFbQWW۱`jzal쒔Rs$q?[!'b]7 q .xMjr"MfQEP /r+ӂEJ$Hn0A 𫧔ρ\|*R];iV<5B e4|7Zs q2 xB^N&-]7@5H$4UE6cZRBxj~$G=] zQU&B%BQM$k@EHfL\H˂/Y  "f5`Q PUP%)W1)XMnƘR"(8?6tzh[OOomv]A !%H ` c@S( #~@dI hԺ"N+KW.(S'DZZZC UӠ**8UDf:+d1|a )~rhQZO%,nxXQ}/buu]F@V9o$ B@I:6PNE\ap:9{@q(M(/i9cU=z`S \_+zMnBܗY5j[JjtOVsf@ _oFIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/dcraven/48x48/online.png000066400000000000000000000053131345766322700237530ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< HIDAThm\yϽwy76a1l0AAE؈R$ R)$ _T|AQHR4BJڤ*iRiZ6xbYkkܹo釙ήFJ9ңsj9sψY-`W~͹7 lGvaR'9Fɶ߱꺇^IM2~Pį~j,Y^= D兵7^_IEa^(h8WblUfֻ[v|ͯ%x GMmOO?7떺KNb3][+;EqX#VMJ&o[g:>'w;:7|%'][XD҈0ib5:3 l_6+n z7<"8uFI^Y6MtjLr!2>$O!Mc$D KѰ*)#XJDL ꦪ(&#X*emSkE<(U@,HPSCV/@ #V Q٥hXReuG5b4&BF?I*P&.UeW{[QI LbI4n@iT0oF %nܻ+|szTT'MW*La6Iʨ ?=p/kp_ɆMPS pC>?^_' ݅vzԿ Q='X#/+NhzT_V̓+O=#xw :Z:]عMۥT9Igm<4OoEy;!"ljѷLOD1;?~<^1svoxq̅Q%Q @8!,cMUG45 ~s}osC(G5,1o?4JDeR<$ZupU3TiRz+g*7YsNqNDHAjHIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/000077500000000000000000000000001345766322700206435ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/000077500000000000000000000000001345766322700214305ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/away.png000066400000000000000000000010371345766322700231000ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME 7UBIDATxڵ=HawIFbA=IYE**`AXJqpk)-t @(P/E1 YD-X&i*jL.oF3:wz@m"^҄B{0>:l`tz݅(uFC*s#<Mf2nΞMϑΨ|筄Y:S<- ~%.y;0樬pQr;7& %8=O޾~;ٌ2BDRUU3$l6K4BSu‘coc1ގrGG'84/*qwx_;$n[lmoX=gg/:wԡnpY|yiLfo[xQ6JUgwIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/chat.png000066400000000000000000000010541345766322700230550ustar00rootroot00000000000000PNG  IHDRabKGDIDATxՒ?KQVZq' O.M*t.n!a|As!\uf7N%9pxp=}0m~Qmp i%Ik NNWUe\EQ(seY4M$It477:]`$B MSV///5e^WQʲLPOOOr\~=<<,ET*ʲ,--9(I("c}B- B,..{`*1ưFDYv*QaZ;^O-8_[x||lbHbkkkB9F`TmB23Egmm$I>e( 8F{sqpp|0zZ-(GW|N~7&r_GIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/closed.png000066400000000000000000000002541345766322700234100ustar00rootroot00000000000000PNG  IHDR w&bKGD pHYs  tIME)'C_9IDATӭ wQz"JM ]-EP ^Q*1IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/connecting.gif000066400000000000000000000017411345766322700242510ustar00rootroot00000000000000GIF89a{   " ;8-hcPYgvrvyo{mu~y~V~_mİiΡúѿ|حԷtuǹٵƺټܽվ߷! NETSCAPE2.0!Created with The GIMP! ,q!0_I%fkZH:- Wkw L<3)QZ+( B>@HLKPD49?AJ".ɵ'*ѵmzb6ׂ uxO 삁! ,{,=dS1,joccT;[ngssgM5X^tqqt^FG]irpv\N#EYeh`U 8CVR/2$&lya7܃ * uxO ! , l!0_I%!fkZH:- Wkw L<3)QZ+( B>@HLKPD49?AJ".'*˃mzb6т uxO ܄! ,{,=dS1,joccT;[ngssgM5X^tqqt^FG]irpv\N#EYeh`U 8CVR/2$&lya7܃ * uxO ;gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/dnd.png000066400000000000000000000007161345766322700227070ustar00rootroot00000000000000PNG  IHDRaIDAT8˵K[Q?U ڱ]D8H.ҡsHK38RUqpDhڡ!R!$;.و~N|{@Π#.L e#`:U4wFI<~{'݊btEGWh"+H+gkQ%J;mN4{o(+ p{<AF\l`Po2.BDDAg/tD>$>e3\BS>_/滎-`Xy=۩Ԛ4&  e$'HϪOtA5*(R|_6?.g$jR)-̳#7 y UK8;h%IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/error.png000066400000000000000000000010241345766322700232640ustar00rootroot00000000000000PNG  IHDRaIDAT8Œ1kq7IXI6KE쮎VQgѥD*J8UKՒJJM6}$6.7wx8z Nb^QDG@  )V (N&t.s _XyEwA +ŶPRWȌߠWH̅P4\Y[x=G#j.nHx]&LJ|.q"$/?g@6K(&?S|&%Rr*bj4+00ߧXa-pbbt6BR%kNO.v2)' r㩯*IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/event.gif000066400000000000000000000052441345766322700232450ustar00rootroot00000000000000GIF89aD 77::nfXrlZ==@@BB~tdxdxfyfGG}h~jkIIlos²ijĴŵВɹɺә¿Ͽ֢ףžĠڪʣΨح۳޲߳! NETSCAPE2.0!Created with The GIMP! ,BB >90Tzd K!922T(L#΍k3RhuFޠT5h"u2*N4Nɽ;ъZAd4t_8nP7+5SVWb1l ׾/R>ɩiMGA,f#O6\DQx,h7C_DwZ!^kJ_xI_XH1=s`^,vdN'ZQF"1޵-(p,gj63wxn-#}Ď!Jt)D"fPlwy'LtyY*@ Aj*v]eY>o{vA&#2>|> і"&Poiv7nO-IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/muc_active.png000066400000000000000000000011201345766322700242470ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/not_in_roster.png000066400000000000000000000013671345766322700250310ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME 6eDtEXtCommentMenu-sized icon ========== (c) 2003 Jakub 'jimmac' Steiner, http://jimmac.musichall.cz created with the GIMP, http://www.gimp.orggGIDATxڥkSQwf$ZbېBk+ŕ]\W @t!n]Bp#"FED(U5ƒ4sq__Ru>sΙ3הgOYZ,j5yo =DVmx$K&zky*01 R>{U8xx/W.B ށ *J\¹i&bf64TQu;E:΅&Jƞ}lQ,h[D @^ Fdžqf[ { >mʡ#{!=a0;B,;sJd D= "6*pZV%]^ώa&! 6j?t''xrfwNKpu#`R"c =HIGA?r /Ȥwa?o(VmP3;?٦_?Vd9AIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/offline.png000066400000000000000000000007731345766322700235670ustar00rootroot00000000000000PNG  IHDRabKGDIDATxڥOKA&jŞz P-P "BO`S'HAbKkKac5fK%6k x/<o<otq[Bk '|j{g>T&K&PA| 8:gJqԗ^89eja2T& y\^^Nu^&_a1 鳁j%R+{Eq/R$$ uLn378kMtIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/online.png000066400000000000000000000011221345766322700234160ustar00rootroot00000000000000PNG  IHDRagAMA abKGD pHYs  IDAT8˵kQ̼wjXЅ nBq6Ņ?@UY[]\Y vU+VmREj6jmfB13\![ǹ?JsҶy2ۦ|?@+eؖNNSiiZ־{olK'NPihSOFN)H3ց`V=)lF\:^!IwE231,>U9.]իo9i   fC}6RLO2!`CE dPUa@U7blYYt}DЌ'/9efVp#?H[98ԗᑘ^-pyWn~yx8;nchm(aѰ%d~lU-V-*N91=>GG948DANe㵛4YvoϱS)l.er߻rzϙ^y"! @km(ZfN7ڇKܨ8i9x% RJLdvv &''IRH)Rq8s3ʖZ+jdH$!B>FR" vm(J = J)l& @)n3.G722P2.Xa﫶TĭR&|766k7@V+/ yឮ^wˬ,-wWD U:r>l=UEӺIګIo0= o~Yn{߼t=9 >uӔ6nr5ā`%w|੭J.ߔJ"P?/2#G|IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/16x16/xa.png000066400000000000000000000011661345766322700225520ustar00rootroot00000000000000PNG  IHDRa=IDAT8˵OHq?{m4ܬ C"1AJEl$(`jѡ\XRhFAY@?ngWO|[Y @ 0SӧlhMLad:."@Kk:Ib!Ͻ; Y~UP '?Bf>G<Viao7(/3f^c{-X-&:ݶ&䤣@yb80d3W/Wq8Kz{x|pw1oo D*'ErU8(Ƈ %*dag Ye!-MRgЁG%S'bqTEA%;%X]]RL&E*EQD$b~~^1vËd3hYZ|}&sQ FKN fQ*`kUDP(ra; h3 z4McqqI~OWWZ)2θyIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/000077500000000000000000000000001345766322700214245ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/away.png000066400000000000000000000036571345766322700231060ustar00rootroot00000000000000PNG  IHDR szzvIDATXåm\U9wyiⶕRq4lLBHL$ZBbKDhbP ICWY``+KKK]Z}?In29s޽l8!DJS5<}зuK̙Ӫ^ +KA-mw01ŁRT&mBǑو##ju+n$PF1 <،,XU amdžR X0 ԅJT#ì5ѱNc !QN^zCfGԗh`M!r֫z&&o/%Q[H_-){^ܜhrtܐpes2vEʜmkmHhS{;}LH2a CÃC^ IirsoGȏ>EDp.o aUTWꆮ J)wm߁- ] dh{ӣ "T4p)egϞŏ#_| 3a@2nғzv{ry `ÆntR f*U.V[zpp< 0~g0]0Sq&ytvvk5_ (>L)dPh$P(Jm!t Z (ĩu4׌gr^}s.7/ݰ{}w7ZP>@TPJȿH)zLmmm?8mA(0b`vN)0@ބ=o-3C1w .|zjP˲}}_ d-q^K\/^\+_D#ٳgnrr. ⺮h)4-˒J"'OC)>WT*r⺮A Zkq]WqĶm,KժT*Y^^r,rYJj5V⺮x'KP'N,L0E&[(PJ m} iT-[pq @DH&:uOk}̙3p:9?VED #VܰX,J>%yT{lۖ)kddC]0ZZZ<|޽{8"B,CD"aZkKOOOFp)iR;|b'R?d2}}}|~vHc\.8C^o(A Lfh-XN֭[v3ßmmmtiI}122xo9#@رt 庮(nu]\ɬFD8$I8DU@dIAb_p V:::Zc6ZM6yf re$h˲(F|f'L xQ#mۦ\.~*ttt0::J^kP5eɃj n^D<99n* R 4 T*ž}fwE<}Tݸq EAWn_~[nI$"\.68i6E婩Y#h fo߰aCjF7Dz, NH$XYYɓ' @G*z!355\zu^kGUmm۶/^7lskNL4NԯMlV]&_/KF @Z ]|zF8rٳg3dK\ZWWOMv"Ql:^S(۟]tr֖fk ߸qT__[m+cX,f<}8#RSJ٥Rr+333\2 >>ܯ+Jpȑ;wNZZZǏi599gffVs}Z/c`X -:V"o~e d>W*Sqy7W^j-FXx@=䀹tW£rx|*ckɛ\L"&‹95fԒ/5%IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/dnd.png000066400000000000000000000031251345766322700227000ustar00rootroot00000000000000PNG  IHDR szzIDATXí[l]Gͷ:q(4HEιY}sfϚ5sR˙8@ ,.3RclWs@>:T2ɫ5Wbs1Nδb:p>B~ys?z{W⢔>(`ꅗls@Hw"=px<7=9h󩧾 Ƥ;AD7 ?|pޚjx- ]/px,}Uc-|*f !r`̞00'E0$H;?{&'lZiVcDcVlw6նA5s?佞ndlz|br((m;iZMC=GJAp堵<t5|+23W"\][[k yx<2-$›xNMĞDgˆJFDT(V"J_s}@ 'g?gZJ#>-`6Sa} _<{''4>P1"0j"Ģ yu%տP)9 `(UW\v5Em?vLm,>@?/--G;9[WfQ*xuچ fy~5k0*P՗ -fTi}ި"VԨ%^ׄHw#a`f~ώRVq*ƘOI QD{F9 r OpuǺEsEv焦=zFhvۤyk~-kzYyQb{^K7jYyx;μ_}11[ {섥3F.q,p) w+ЮӃ5֘&n/ H6kpNi\옉U_)LSE~;X׳3B`B.WRSO%\JU_KF)yu^Y9 _۟|D0MDPkhjDȢp9N?wug[|Q.^3aWΐD$Io]%4w;݊f+_| '}Zuf$)Etĉ){ʻ3ʭ 'c`d+,,+;%yTwz=ſr}aK \i]x7L7s3qA(g\J'n;>:WS?W\8Mm"Qc(jS-S(,C34+AW4g><9yЖ'I*^Ep=lމ\_6pz9bi@/fGGGO;vL9b:Yə; d@_Fo)1A&;iK._.{(.IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/muc_active.png000066400000000000000000000020331345766322700242470ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/muc_inactive.png000066400000000000000000000017761345766322700246130ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# # |(~"i#mjB1i&)%35IS$;s޹ˇϾd4Ǩ0{r}ް16w꿕u{Ml7𞌐(^Oaki{zcnv驫_ ϣz%1c$P%d Y>Ǘ{˓3/qw)Rm#^W.s M!ҽ `tM*%R1`x p Y/cbbòҎiX302\&YAzqwKE21egvqǮa P*Ze|"SsDh^۶B)6np] @`), GNCƮ;W_gD|Ɵq4kT<A DA".B!Ѓc-4,Di_@EQXZ㹣/3?_嗿xG϶;pp?Յ9ˍVBUSE4p/'9~_@B=";wgm,,Γ$Tv .hY"f`Ƃ85 # M @U3caR*fˈ`5 H4/uR$Jyq,')O,Ȼpx[dnVlg]" bUk%M3"qjo=oIR9<@Exwt3sm|&" "?qk3q&;ȅTܯ+ޥ=kɉ0X\!.( U?GL鐕PD= @+ch[KR%bQ Yٿ;nޯri%͆SMI׫ o{3#jU4Mʈ׾Kޕ"g!Sw'qg//xقdÔb`i%MqıУmi?O0fGX{t^˭JQ y-CzvkՠYq}/T}0k+sB0Aύ<0kWR_a妫JXڡii4Ҋ ɦTN٧Gɳn~8WTҊ+!k@^1ͻePKH1'/R[26/zI}Qb(lڨTIrB:/bzzfX5ؾeJ$CZ]zT!Q,[_L?b $ID6RDmdGdrpC[vz,Q"AQs/mIRN/BMM XkO9n7UUU|`u3Jˬ+ߏҔQc.n$iZVtaI$R )Q,¯X˰GXa5> R-3 BEVzrpC P*]ccWR*oK;)´> nܹ񴽶r @ȍ'wj{)^.^ÇMwBss B @g$B[[ nZ[[>iI tϞ=9L"YbR C`lpr#c 覤Nd8a(n e)xk2l{9߿@(zBc@0<<8/t)<y)׾~}IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/online.png000066400000000000000000000031701345766322700234170ustar00rootroot00000000000000PNG  IHDR szz?IDATXíkl\G9gڻ ₠iVVmCEA6*@H !J !DAMmᢴՋҴ-'8^vv;ko;ޘ4:::3EkM E!W= qmAw~&_ .U@9ȓe0]xR^<՜TJ%{h}v%c/} Gl쏜xOK_k,&(E1A^L(:ȉR^sȳޜ]kW]bd3|n ;{ajAx䝃_ɈU1:}nYyAFڞ/{X{(<lr֒/~]M AҪLO8B2~`f⹊MAfV\=sۍp.se+c;'(@"1J9,# t]ޮ/v";P dJ9(%jZW;oSN  )*bGbl]qvҠFqWlRĮSBz`}R ^a1~n\#biH"."=ʈ㮕U( 0z+b @M2([ibiÕM("F0J+6MUb@%  %# Fj@ ARRuh+]П @|_14`A]32,@ɲ'Oa87FA)0fcD0@(bLlf%33@٢B)(tzٹ/uo9U5e ,p=?;eUbY<9uq7؆XjChG)bhQ M0l;Z~Hj&\넒Ύб-#`ru]V?{@ c(նt~?;5/'|AZ@ө GPɹa%s@V5=Ugp'ʉ96`m e Ծ8y'p_OS:OZt!\*>gॣOLLuy߻F\a2D9鳧8I.V] f ݻ_8r S2H:#IK;K bNMIiRYRsn|eבHlbcfUfSfKTN~:H룷;5QNsnzljJ-{w~OCBru IRϫ='@[+Sү&ΑO:-SKr|?uïfm.*`0 :n'9ԧ2~2~h#ŹP ܝH$^߿J4~ |Ԏ 9  ,زBF43jko4$IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/requested.png000066400000000000000000000043671345766322700241450ustar00rootroot00000000000000PNG  IHDR szzbKGDCIDATxo?wfvgwk?$*5MUӨQ*A%^*!RR_iF!)cb^zg̯;]MG:{9GshsK(Z[d>jӆ[l Cez@DhFt u7MM(B@E}=2 bQC80 #ӏٙ" Ck(-a@x> @ra!kUo֪kS q#*z-a|4kld@J<43UVQJ3MNiKH!*LenR-l W(VbnqړGsj3 xӌIf]_*iDO/m-ltd2I$J(/尦>' sԖ\ KV.4~Œm;O v$7oH lkAՏjF,[ )% aDHmmDRΞaR-%ɨA;ۍRjdemRSNO2<<({allfF14JАJ"=BB#eMBok{eddd2ɉ'tڥDJZ3 Mm Cs ]N QUk{Y}saYǏ_=zr+ v8wJC)?D1~@ \!H)%cA)X͛7)9]5v]bʀq__o(&qbF5j!R /c4af@ІI)i44O4`F(bZ!O8!XW`pp۷.ccc|'tttpauZvZvZjΕrc7*L-I%le& Cb###a˗9s BcǎSOm!> l'4u?Pg]9?\8JqC2u_^I3:s92 {g]sgERg(_bR'hZR|;ǂPv]y;eF6 [r (wF ㏔?71SWu'ׁVOw3t.28Xj o>4M05pfj? *`b@Ñ7qznoK Ke;R>:;;WqE;;;e۶m߿x<4M2z/*.3mW xƀPǕOLI;CT5ޙqy&''= C Mc{/1kULNb Pj82JRJi  ۷id2N<Ʌ 9rd<n9 Wk˕pρPlޖ̪⇷"j v"f2Oj5LdttD"AOO<7 h֙y4y-UԢӬ.TRuxoT-hry}%`:tÇc&X ],L[UlzR.Uw=?E8FY%di;unef硳3ZtwwH$HxgGӋ\[.Sؘ7_ܐiV tuyM%ut*Q[w]HRD"t(\Au,ҲZJӹ@m=K @(jpO^N'bl׎D͓M̮ڷD7p2r`1]JiTwiU| ܊Rk /t2z4鎡趮.w)5LLkv)ޯ`\jģ;m$s'۴+;hJSyWKfm,sM[tU_9oKwD4^!TRyUʭ ~SS PJA-[ᗁV~գ6h}װcIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/32x32/xa.png000066400000000000000000000044131345766322700225440ustar00rootroot00000000000000PNG  IHDR szzIDATXÝW}lU=9~ޖ*jAt*:eɤs.KY)iMdl3pS)0X^[(sϹ>XJݛ}~=}[Tb*LV:fyr4bZ"u_Ԑ+**/Λ_{Ѣo"t fD)"rlF4}*s֬ԱC<p|(Rlii^53q>HD7ׅ[s#[,Ӵ\~vimw=: 6mj]t) a` @za(08bȗG g"do2,/*!c (nصjgɑ4i/ڷ[V ND;mg]xD+`׆8_,n<Z;ʠ^-<ʌ 4ઘLW_?Џ:("0 BrXg *!N#g PO608KsVSО5֭{;:d=reC.Nq PU9#/W:::68xZa>ZZZ}v$xk>>tΉbh(U2_h01k5`f~eBshd,'X,y{^5?1 qCД xdmy\ƾ}5YCb0M̌;w⮕|ԙ uhhsU^sRJ>ݗ`x:ԟw6^MDϮ]W/\cci>|k֬Accx<ޕH$ ضm[cW_8N,3o޼g2t;L&s&̀Ӯ0fԔaIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/48x48/000077500000000000000000000000001345766322700214425ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/gnome/48x48/offline.png000066400000000000000000000014721345766322700235760ustar00rootroot00000000000000PNG  IHDR szzIDATXKOQ3s)Q*X4$Fƍ&ldʕ ~MWBiHMA mR:BMM XkO9n7UUU|`u3Jˬ+ߏҔQc.n$iZVtaI$R )Q,¯X˰GXa5> R-3 BEVzrpC P*]ccWR*oK;)´> nܹ񴽶r @ȍ'wj{)^.^ÇMwBss B @g$B[[ nZ[[>iI tϞ=9L"YbR C`lpr#c 覤Nd8a(n e)xk2l{9߿@(zBc@0<<8/t)<y)׾~}IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gnome/48x48/online.png000066400000000000000000000031701345766322700234350ustar00rootroot00000000000000PNG  IHDR szz?IDATXíkl\G9gڻ ₠iVVmCEA6*@H !J !DAMmᢴՋҴ-'8^vv;ko;ޘ4:::3EkM E!W= qmAw~&_ .U@9ȓe0]xR^<՜TJ%{h}v%c/} Gl쏜xOK_k,&(E1A^L(:ȉR^sȳޜ]kW]bd3|n ;{ajAx䝃_ɈU1:}nYyAFڞ/{X{(<lr֒/~]M AҪLO8B2~`f⹊MAfV\=sۍp.se+c;'(@"1J9,# t]ޮ/v";P dJ9(%jZW;oSN  )*bGbl]qvҠFqWlRĮSBz`}R ^a1~n\#biH"."=ʈ㮕U( 0z+b @M2([ibiÕM("F0J+6MUb@%  %# Fj@ ARRuh+]П @|_14`A]32,@ɲ'Oa87FA)0fcD0@(bLlf%33@٢B)(tzٹ/uo9U5e ,p=?;eUbY<9uq7؆XjChG)bhQ M0l;Z~Hj&\넒Ύб-#`ru]V?{@ c(նt~?;5/'|AZ@ө GPɹa%s@V5=Ugp'ʉ96`m e Ծ8y'p_OS:OZt!\*>gॣOLLuy߻F\a2D9鳧8I.V] f ݻ_8r S2H:#IK;K bNMIiRYRsn|eבHlbcfUfSfKTN~:H룷;5QNsnzljJ-{w~OCBru IRϫ='@[+Sү&ΑO:-SKr|?uïfm.*`0 :n'9ԧ2~2~h#ŹP ܝH$^߿J4~ |Ԏ 9  ,زBF43jko4$IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/000077500000000000000000000000001345766322700210225ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/000077500000000000000000000000001345766322700216075ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/away.png000066400000000000000000000006461345766322700232640ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<8IDAT8œJA"!je RT:`Jח+@R-`(6Br%&K@"802췬QUH%T6e˅ 9cA3兜cɧ(('`mlFo\ {eN#^ ϴyd2=La^Tz> `|&Glt  df <eg Q܎L?@)M4m} CseIvc{ XQI MiCZUxFg8qLgճ5 v&~Q>(IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/chat.png000066400000000000000000000006271345766322700232410ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<)IDAT8ՓJQ+m@Q_`)i^AQDP-=;xp03̙{052/~CU`qBġ&%1E-7D񀸣A^|< <0 -g1J""*KƬV>^懙~Rj\[LX;_Cg -cCP5|+*'iHA:h5+D;c2ߊEzy Y·J ` Cۓ-Q15XJtOi1T$O67T>0cOGɋPxV^b*٥_٣%XJG?{O1W"+IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/connecting.png000066400000000000000000000010171345766322700244430ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8ՓAH_71H(".@P,ƌ"уd1 s!uR f_sƒ^^9/v{x Id :H@̰^r%X#I}MUVsvG50uĜMfIUy:j?^TU2_~Իkg W59cPtf*N "ΒXv Vc43y5J4]̳t@?KL.7>RC65U#oK>qswC##_5;Q0@`J 7ث R +M 729_M5j9IIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/dnd.png000066400000000000000000000006431345766322700230650ustar00rootroot00000000000000PNG  IHDRabKGDC pHYs  tIMEm}0IDAT8Փ1KAߙȁ  VM> ,,iLo+-$A,-RaM;;3wULy#<P<׋ NXeGv&Eӣ^ʃJe|t䖨‘DϳИU!T!di^2WpS=p 0N~5rܙi݆qP`D KO՚:<}R+cq5^Ù9c w&y"Jka,XWMXJyda; X8̏E%_b:>l4&e "}CN]I4;iwrv#atA)B= Md^9 #> Lv…`!,&j, A"R^+"GZk \vC#m""^-Ֆbp) R/ 'M͟uoM5j'^8Vz?}-- {A =˞cPP}s,w ˩zE=Ν nKg!i3JIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/event.png000066400000000000000000000006541345766322700234430ustar00rootroot00000000000000PNG  IHDRabKGDC pHYs  tIME 5T 9IDAT8ՓJA`iS,0k!>`1XJ !xو\$kH ڤ)1Hc p B }i%,AŌÛ$)"\ehGn:<;%$7Vs蠏)anmZ G_°]$>qFP:Tc^Ne[kG{ay}b~awu CsJUB,c&KWv%-L?ڜIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/invisible.png000066400000000000000000000006031345766322700243000ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8œJ@gAlRRɛXXViaG*`*lٝ\c 9afYuk+a0ݗey&8ZoZk wEQl[kh?\Zk0|y.3f_h'f Ƙi۶>ysu].|;DDT.8b "2_ [D#" "(`+v 0SO4}@$R#?IqeqL [ԭدIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/muc_active.png000066400000000000000000000011201345766322700244260ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/not_in_roster.png000066400000000000000000000006031345766322700252000ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8œJ@疓X //`y!EH`'()ˮ Yw9e'9Z'ZL}4MeY^ !y 6˲zg ܱ@}, @J4l`Bޣ(-ۂRj3qZ_ѵ`9۶t]̡WWHd(yTUV@D>'JDJP"8Oysk/H ziIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/offline.png000066400000000000000000000007321345766322700237410ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<lIDAT8œKBQƿ/1pBZz('XC:.M7(ݣy=@Ag:ncNYk^6l6mWNy-˺-Jݍ8vz`}5 3姕nws4u9GRjRL"u"K)fL&H$0L@D;z%ObZ-8,$ "ID "!eYDXi ( Bqy_Vu1ǙL"i!0^hxK|s0zx=h{IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/online.png000066400000000000000000000005431345766322700236030ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8ՓJCADϕlml@$?@A{Xigco XHD(؍*6. 5IVrE@%64 [\k[nI,.9O#/1bȀ>z+h:Ԙs 쩮x#Z8j8"cWLh2+G2`><⣦"+ZJHdt8td!pω.4--v vnl"Eot㧗u|=IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/opened.png000066400000000000000000000006241345766322700235710ustar00rootroot00000000000000PNG  IHDR 2ϽbKGD pHYs  tIME/+2!IDAT]+q?/_70YdH~MQJ[ ɤ &(] eȯ^=} *Ll7' =٣vIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/requested.png000066400000000000000000000007571345766322700243270ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8œkZaϋyqHq08P^8IbyuQ\ui{0.8hꠓDRCBH w<)nn$y{D ٦ؼAV;3LEQ~N3j+B^7|~J`&bA<+ SIR@)۶`Y\=Z:Z$H"#`:lu]|@)u^&R˲P(0zpԕ%&"? t;hZFfk ^ݚo"n1kd>j "$H^f eӻy_t?IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/16x16/xa.png000066400000000000000000000006261345766322700227310ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<(IDAT8œ1KA B6وb X-N6֊iYXdGgKwD4ogfaWLi%_x[< 8ta 75+"ˀ^ h- =K}5eL6pUR;4 YQ'v`(\*0v ۝z}vXncf¹I &S'ND#k b_-zrp DN,<'B0Ӵ87@K) ch8xp})\o)@IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/000077500000000000000000000000001345766322700216035ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/away.png000066400000000000000000000013411345766322700232510ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<sIDATXkQ?oӴ=imhՋ^ -^<ODQ(Bf_KRTФdffw ^20,}oyU09T@jo^c0([}|fcr] Zzm300nr1cT\6wӰPně[e߭^uWyBW[ fڌeLVsmCw:%|}nIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/chat.png000066400000000000000000000012611345766322700232300ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<CIDATX?hArHEID0b!hc)F( VbJMhFbbb!,* D!=ٽg;{in`|{{of$޻r' I?>zy+{"v3uu'Jy"%F8 l]1*2qЮ:-K\qսW9!dA|{,Y.9G4%"  չQr8hUc.{{JJ8ngSՀ}78SUkv]B جV@sF*Nb+ah(F"zZ* S-a3$x=bě#UI0@#\)4&e,ѻy?#pk4xF[.:_i. yoFpYamU)dʷޫ)!ftSDYcRcЌph®rTu9 ;׋H7Dr"1s%vpc[qPOtG'ܸt$1Vp Tr2;W9 Cw`U#TߓB򤐎s&oDЋ9baiXPC-PRRg"C{q]/%߄Пѥk!珥`Dx6:P}~ݮ5%5Hɋ$оdJQ*/n$w IӕZXz++n&QIVSoM hHLOYafmVmCwIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/connecting.png000066400000000000000000000022461345766322700244440ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<8IDATX[lTU3g ,J5(L`DZ#QHxF%*A HRTSI[m-DЂ%R(9shg߇)$6ҕ짽׿eC7<75z@0H A ZiC~F7phO7 ,rps/|ȑG+lZr%DFyhۭn%^4fE-ՙQ}e2[E n^8Oe]e9 ]mܨiStixZK'*% dG c\lQ}}XO/2Y&dR""(ї7$mtJ&_: 7#pyPᰫˤT^G-ZpL[s)S>XQ^-V)9/Iz]2X;nS'WH>9+B֎3IMA3vH>Z<|(N,F0 kl\ Xxl=FMŨ Mɥ!gc X@t1 [e':b@_TrtY}: `,L)q\d"ݖ,Z;|~6",Cz - ҥ~@Kz-&L",3ϤҾwvUVWP4g6yxOVʲ86~VU?ȶ%IuuڹPl-Vx&!.X!+eaUTg!(s֧jj$IjݺkҚ5*_ f#].xrb媬Q/dRzk )B6Lt7ͭ J&-ߛ.fMքJ>|h ֳ*[h T(rC;jڶf3*LRЉo' c; bדɸ6eŽ(˹H$ohJ8˕$!ħΥgd}6zJ1Z*7NNx}٦w^x}?|ee5{Ur6u@`qmbsS$Z˕H6аƘ AD#Ȑ{cV_Xqpac18O{Eywxk8yG"RWF;#?:aԞSj7CQ$O?V,#[w@^A^Z2Ri*@6/^#SriILo1݇ChCmGh}w1mDk3Ҍ9W8!Ҽr?W=?֣F+;OiBhyJȻ䅦?e@`F~(F+R )+p1E3pĻ{Y73C*t#a msӡHOB G&#]PlA!4uUnc*=WY@7U+}yJt\.݅R,N GhUH(Q-4˞T.z͸p_%ƒ.]{f #"JLbPT4Zܖs_o߯⏋ڨ=kl^vOFjm](8RP]iĔH]ڈir|Dp5?||NJo(lW?;td*IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/event.png000066400000000000000000000014571345766322700234410ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATXMhQLTRR "ԥ ] ]Bpۢ;WE""TtSqTݨ!Lw]$iI2MM<9sIiUX#8<-@w3.! h6`ƪg "; G/aNTDjͤ8Loi0%Yy76/E8T nM40W JM<.̤vLjzǑ3Æ1Cn=ਟ} }e R=&09J}ݢ}oxSD ٌom!k ݔÜrD:` Ԅ!K y(J]쭖Jlzy"RHVքKl~ERcabE|PY.n`n: RjVY\7C ȉtL]πY_Z2RjvVvsXC*/DZG"H_}`p^VWVrD]&/!hm 4e*NȕJO(xS96w'*8{VP/JT`b"FG?2;"PY|L^3J} :D>W}$BfL?[} /klR= ; $XZ_k=qXIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/invisible.png000066400000000000000000000012101345766322700242670ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATX1QgoSNOlBI!XIG?JMa4OI,kAh01 "owI$4;̼!"ȳP%Vu~jۧ"y" uc'"ⰱ0cvO`@8t<p 'DZ"O;d2y2);l6`KD^Ѯvf2AAg ض#"k!3xBDZF#>d@V;yލ@"m ṡlOJ)q ?߷ JTJJ)r)F,u+@D ʌ-81 PdW3}PPZhu׳\ռ|IS߂bo4aT*@Dx`5a\3-v(˽m8뺏 C-$em2._yZVAc>lv4˞MQTE#6·%pIIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/muc_active.png000066400000000000000000000020331345766322700244260ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/muc_inactive.png000066400000000000000000000017761345766322700247720ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# #v{3HbY` rO&gDdK)IqCMs)1jx<~CDHnH$D$_4K{"r)[FCPVox j˽*6Ƀzc+`YwP-$/t:* "l0>whzƴZW BָR).h0JW#IutNi\x܏D"&c7=-cn;*Eq!|f Z/$- h0J !GHz,chY3>ݤOy,< ,}Uȿ= \:G"3x>-8d2$yjAq}3t.I)?D{Ѩ4d$,"w]; ,4b5/f祍QIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/offline.png000066400000000000000000000016211345766322700237330ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<#IDATXAH\Go*>1}T D`kҠzXBNKXZj $H +Bbʽo $"DQض\.l6&@5xq T*ӃRe$I tuuaddtiSDBb= 31̌P("B:.<477X,z'"{=ƩVdqqg"3}}KKKߝ}+"Z?$Y]Hx1澈c}_^aJd lݮH^)vee4 ְj~+4pimQ)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/online.png000066400000000000000000000011301345766322700235700ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATX1hAwwH((F,[I!F J&$b#gH- enr;w-a D}e7;&aP##@#!v1I`o|"ڬ!ڈLUXǮY x lb py0Pi 4KyႦޑfg<#P+eMk.ـ|3-tJ1߂,=#G]kng*;߃qH9d28rb.&apd@' ~K %B lVai،tyQ%rm] T7@'|LCT(5s8#|AM*cTیv}ݹ%[5<j2@hs8`l&K@2ȽUb|"aHN2^|:0FxiQR&8 3!Ո*"5#ywEٛ+]h^OT;7U1 '4Eϳ 8qΐ k֧eP_r"U(j06amcOj=*ܞ$GφSت堡Xp9=WӱPj'IxN7FM  es IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/requested.png000066400000000000000000000016201345766322700243110ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<"IDATXVAHavUd3S4\ұPŃ%%ȃS !’"K J"y򼂂(тMF3ov:.;afg!"8tL  hmm.0o+ ԛ9MDΔ6055i躞iii4My)`˲ [(&2ף PUU"J=s27rnvh4ڲ,455k4MCVMwwwwc Ԉȵ̝f33E 9QbGߟ*j v|#ǡʕ_$ B3tFGGaF\"^ fˁeAD]8l߄w !mll.ʁ׻ٛ QWH@ 0+;̌J&r. . N3_|*Z øg :fE&ϱnY{9톈 baa!eoy7"" FGDfybvT̂dd2y p8~_RXk_SggQ0~IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/32x32/xa.png000066400000000000000000000012611345766322700227210ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<CIDATX?hA3QQ BM ``!b/J`'(Z؈ZVMl p#|1 '<W"aŷ=6 |`TVT'$<`J6Ř[BGU.rcf\>&u.g"+[GG?QI1Q Oˮa Uu=3aWz/V]9o 搲 CVZ} pJ02KgtSB0VhAlvNPԺlg|$Rڀ#Vց?Qe))քO]u ZO}>oXutIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/48x48/000077500000000000000000000000001345766322700216215ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/goojim/48x48/offline.png000066400000000000000000000023571345766322700237600ustar00rootroot00000000000000PNG  IHDR00WsBIT|dtEXtSoftwarewww.inkscape.org<IDAThAH\G)w) o8D+Wt644v`,3gGT󠹹& T !Nǘ~ommLMMt]LhI<ӶwH˲tfaayyyp\p8p80 Ӱ,KiGm .,KSm0;;{<ّ rS+++)RBTR3?SxN塶VNTR?c He,..F~WUURK*\)$H)MfJ]M;;;EEEpFlll`ww7Zʥr}}=rrr+ߏ333":/ _ !r1'|(81t:9030"a 0&\.ZOwU> 2$Nn !J}>ߞ*O*DMDэc@GʮDF#{~xY>wvv3/6Gp\Z#2 mcccOeHV[[[p[Q_D4ЕcRKa=f~ i3U+m,KTؕ^O HRmi3IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/goojim/48x48/online.png000066400000000000000000000014411345766322700236130ustar00rootroot00000000000000PNG  IHDR00WsBIT|dtEXtSoftwarewww.inkscape.org<IDAThOHA??CDFuIuH!.JTtH#$IoAt%K d4ȃݷ>.`ofUe=GMFuYGu{,[-&1S)q. "e3P#?0#x;1]l%ėKt4a,zz <]:k8R~NV\iiI@xRZ [ȜPZE|8aJ@e;EbQZ}:E(Vk;O꤭PL&%aE*km (Bi 32!CK5iizJmVc[]KH+5$RZ{c)_.Xi y4;Yv}7; V#l6%[Wc-Jk*+e57|{j(oХ99Vu Him(o+ܙأ=4:c+)nTGJ 3CS,r7f#048w?0r)H#>#v;{L{Bk|F|>A}c O[?vK.Nw@x+Pya_};x\( ҉\7꿂<Ȁ:h\nԳ08WdO 97dAsCzws92OEİor*nSrLfB.g$T)_pv7BP@3$r.?WB#%<ی/ٞ3>D5銎Hq\]W̺zZŶ+re3Hl4Mž㾃9\Vr6?j`޹<>l(yVۧ*w-W-yQÄ:r`uI7ḘZUj{ɇc02KyτZ''HuQ)DΚ0MLX,PGGG=r}N ܈̗IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/closed.png000066400000000000000000000003701345766322700232340ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8c?%f+! ļP Ӂx #8W $n > ċx7q/e._H d8jOB- ,$ \ t3lLJjIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/connecting.gif000066400000000000000000000026101345766322700240720ustar00rootroot00000000000000GIF89a        " 4@GJLNOPRY_`!a!"g""h"$i$#l#$l$$n$%r%&s&&t&)t)'x'++,,,,,,//2211448855667799>>??@@@@UUBBEEEEEEJJFFEEFFGGFFGGHH``HHIIJJKKLLPPNNMMNNPPQQRRSSTTUUVVWWYYZZ[[\\]]__``aa``bbcccceeffggiijjqqllmmooppsstttt||{{||}}~~䉌䌌匍卑摒撔甕畘蘙虚蚜霠頟꟡ꡢꢤ뤦릧맨쨩쩪쪭쭮ﷺ! NETSCAPE2.0!, L fM'H LM. 1aEB$T㿂j\g'@aG880Y*Xd"=*R/8}TPH5v%CB=J$ $He;!, o DrƊ (E Z@B$[Q9r"CeAE"0wYlj*h30P @$M2qDSXH+!*R + J?u@!, `` H$Fn$U92`˗ 9yrsf B<C(1\DR$L8iiOfQ^ u,YϢVb¥!, A 2b&͗)H"Ȓ&NQ @(MāHò8 "IbF͛o,b,@XiE&BS$4:$7N`8.{(몪nz<0lnFɼb@ BѢ  ($`/V@OI*j|G^4._f\]TdXZ4[S3COeYn'YvPzIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/event.gif000066400000000000000000000021421345766322700230640ustar00rootroot00000000000000GIF89a  !%&'()*+,-.034578>?@BCEFGHLMNPQ STUWXZ \_bc dfhjk nopruv {}~!!!"""&&&***,,,---...///222333444777:::???@@@EEEFFFIIIOOOQQQYYYZZZiiimmmnnnpppwww~~~! NETSCAPE2.0!Created with The GIMP!<,e AaTSD *,HKYzi(8 ` A֋pu-Qf_$yF  JhТ@=$S*| tU!<,  \H=!C5 aıS$4 , c%JRF@r,Is&%ؠCG@Й`tѣ AJWjU0,O)"1HGv<9Pw`$TdH;gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/invisible.png000066400000000000000000000010201345766322700237400ustar00rootroot00000000000000PNG  IHDRatIME4FbKGD pHYs  tEXtCommentCreated with The GIMPd%ntIDAT8˕?Hq+Ehp< H- -Q--S.!baPAACK` ACCC-Qџ?xhO?ihBnqB/Uii۶'"HR8S]T*%*JbX,:a̒$|nq8ORQ3XR\\V1w!nL!YǤeY:+8EPm: &b0Ni=j8$BG{~%QyvU_=,{5XlJK[ؠo܅?p͚tʘF(V<~abKcTq7Z '\ˋ5yɼS/ !c`Afߨ.?rIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/muc_active.png000066400000000000000000000011201345766322700240740ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/not_in_roster.png000066400000000000000000000015251345766322700246520ustar00rootroot00000000000000PNG  IHDRatIME EbKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8c`\@@q'{1/@|B@@?^^^ cffb6l󹸸>9;;?~WFF?khhwtt+Pms )55&&@XZZ{RR->>/@~345<:sEVV"VVVfGFFF{YXX~Ĭccc{ 䫁 (}٩ tv? ?klljiiRPP3ͳ/OeҥKYOTPPP* /-Zjkk;жWX~=(@&N(4YL|pppeYrnڴ1<<7LĽ[2TWWG@!rJsssnYYYٳ>AcXgiiybΜ9 jjj?@8,,l*g<cIIf3gr*--G6| `,2A| > Ly'@$'%%O@bbb3aʸ|@i&nL,OWKc3[ Ŝ\odW1#۲W݋)p3 :LMMcutt^-z6,Pw@[>3gK~gFP&P i,IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/offline.png000066400000000000000000000007701345766322700234110ustar00rootroot00000000000000PNG  IHDRatIME ;bKGD pHYs  tEXtCommentCreated with The GIMPd%n\IDAT8˥ӿJP"MtN yqp1lVt⤸5 &T$)";Vrp#?pp ;0+a:$ad6YERDQ$<{ Pa RP^4MnSբ$I}uK ra >FAqSPHe.y >= Ch H4.`0%( 9C p]jfǹML eRU5d^Qs\p8A+5Fs\`o#_etlb:9p~&\B ˠ_:27IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/online.png000066400000000000000000000012671345766322700232550ustar00rootroot00000000000000PNG  IHDRatIME)%7bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8˕MHaFw6eaJ4cE ]?vFvXP"=D\/EDA:dAQTE!T "KBGMI3(HkOwkC<#H%. LeqXEϮu$em'.Jv[Ɂ·a6P;PR6m2&#X!nڽLf$I`|yMb "w#pvQ6E8sÌ8U)4oRK 6A (\r+ ~}1kau\0a/Obob] A*.;U'Zg[;׋U"/#pչ@^'cQtZ貺}Ԋfr2.ェ6K@LqDŖ9 &ಧcfkavߛ7mzY ] `dxݴd9c\4' }ijEW9ʼ#~4SDz≼Sθ=/惻 -Q9mN'ku &>g+IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/opened.png000066400000000000000000000002651345766322700232400ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<GIDAT8c?%a*@ĩ-.,/&2 fx/.X `t0 $e徇IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/requested.png000066400000000000000000000012331345766322700237630ustar00rootroot00000000000000PNG  IHDRatIME׳bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8c`\@lč@ Wq/ ` (((\>xLMM;&&@p f9卍DիW 1[[YYu aaa;/_.Ɉ͆"L~~@nό6Yj8g++ Sķ4]l#1JHH2@&..@W8١P,0r_TT4H rpp8TPP001_BBBa@ 5 ( ` eff~^ @dxh @/GS @w& Dӧ IJJ2{@|!MVWW955O@!L<[JJJ02 f@}@ %6_mmmb}}}>ydI&&$$d( [Laeddn0'ʕ@\ćGP-j }IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/16x16/xa.png000066400000000000000000000011261345766322700223730ustar00rootroot00000000000000PNG  IHDRatIMEX(9bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDAT8˕=Has+%.(&A hpj\Z)hhɡ(FuUt-p(8_O4/ s9M$×onP 1O_Mt=.n&UeؘQ}KK<*uvZZ±^XdueVV@TrP69Y7D/f!|D( ,,b7iU^es30?.BANё t^D f ac$ai YљTܥRaq8RKe"Ij$#TKqk ^cy>bohjV #k_#yM K |éK4į[ q 힖aW}[NbK᭝[ͽhCJjf>:aeIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/000077500000000000000000000000001345766322700212515ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/away.png000066400000000000000000000030261345766322700227210ustar00rootroot00000000000000PNG  IHDR szztIME)abKGD pHYs  tEXtCommentCreated with The GIMPd%nzIDATXýyPel.,"zqW-YԱ%Œ0%q_P+\3DM/XظnSZ5a۔p9=Pˉxb!]E~"NG:<ĒFW ԃS=G`4@~'?wPI܍ Cg׆h덎AwpoŠq@wW /8QX̯$" M/mݜѹw' 2Xg fE֞Ll&߄o 3,cjB4""PKt'U ނJ~to1FaYl;μWg틸r2.ݺ3N#(8 YOp4rD4&{yl_MOPgy $IQv-g}ۓ^."4>FLN,AR;*7+y,i\btѠTH E`R34![X:QdB XJ=oɺ!i")#Mc;ʷK r)^{{ wCΣؘ];WcU2Zqvl~q訩ܠcY*7YE+3&,߯M)7`n0o{I5^?bD,U7xh?8:i>/O'^XU fDnXYQs&>ñ"];΃KT "h"JABQBmRCڬRߋߣ>%NKrQF7gC *6? eNdue!sE& HID̔hP(, @Xx4J &* rY(e)lˋldV^]#1܁gbƁ]ڴrTN|Hy㬴LtN*^@N {n@~k8q6#8DZL~n2b1rZ> 'R̸xR2~2wn7{?t's |$V'kv1QlGxTQBd̄eʨ!Gc_bѕES-] ,Fa9"ȀRd3#*m^/0UU(]Kx:QƋhj;M)җKE+? ZX'GcJQP#Yoyy^}zV*dR9Aq_Vc>)>KLwL,`/Y3;Z1%4uH}"U|ManzpM;!g |#E>IS8G DPkEoC;bI* )J!+N_J`+doI<~>Kk- ]EB" :jɰBC't)%"F$(ZmBX v~-\Eۋ`-#5qzGprP񇊈NpH~B)ڼyl6!11բ eMEa0Ypt8Z/xFјB$4sI0kiM&)Wʾ4xsaJ3>>I Zd!7t9%U"ͩ矒ҼP0777YnR _QB<1c#UyR)\vv㜓3z˓&M*}-#HX5k222Vыo1݈$mȃn7|a4)\jfmr]4ҏ, ?}tZccc %%e uixZF&!LC2|}}}ip>\"+ Vv!ou:UJmYjbp8?M7n̿~z2a  LC4G$~pѣGر÷~֖`a˖-[488}-:H=MP?GM p<IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/closed.png000066400000000000000000000006371345766322700232360ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<1IDATXֽJ`߈XlTpJRK,FQaKK?* 9cG8H"&+y7̼3 I 5`E4BwySW),^0U{0Mt4j-@ P81]"[p7_$N0тXG%G2~V83ưU>15E@fM@?Ǣv8Ѓ8,ENA(3ojԸZ.$wZD+}Qs'N5xKCk?IIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/connecting.gif000066400000000000000000000060041345766322700240670ustar00rootroot00000000000000GIF89a              " # # & ) * +, - / 2 20456:;?@C@AEFGHIMORSXUZ[ ]#gm#'j!!o%"p&#q'%r()s""w%*t#+u$%y'(|)%')*++,,$/--..&0,+.,/-2/*330+441-52.3/+35162-4.51793:4<56:7;9<:=;>699;=?CD?@9;@AAB<=CC=>DD??@@CMBA9ECB;FECKIFDDMGFB@?JIGCBAKECBLNKPLMUQMOVPW[WY_]XZ`b^\ae`fadigbejojmrpknsqlotxtyuw}zvx~}~䆃䀁凉䈊剋抉瑍狑摒璔蓚霛ꝣ靡ꤤꞢ쥩ꥪ릫쨨쯹! NETSCAPE2.0!,  HZȰa‡ J41Q#E1XpaA:DRD`gzID8|81$dm9EQ}pсAЃbB;HIɉewKXA ƝveJUx[AaDr: 'ИD*BEX0tw1"X!t}d0B *"$CA!,  H`*\8JX)(@lĄ %"D+$Qf"fbtѕ`"CQxR^"UGPN Fu8E THҡ-&⋆5dPl  et=$QgVq"Y@ {G UYKJh Fd!DhcMXA-h,Ұ;gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/dnd.png000066400000000000000000000026131345766322700225260ustar00rootroot00000000000000PNG  IHDR szztIME*ӕbKGD pHYs  tEXtCommentCreated with The GIMPd%nIDATXõolgK{rJ-[Cf-l%c|%hbbAb #gsllck mmmp%n}'7w9s=٣F4`1.1lf"cfD8\ dx QW.0w 0&/ DZa >Gs#X[S΢%iMDw3$>hE{v/,cbaSsxl>Ņױ?OzOu؁/s)⁆6Nk+MM,X LMQ.=+9AGG} o74x kn!<+hi!RϚXDr6#;"ܞjN=ye俋Od] LN2>kr(,?zJ d1o@3>Ϸ:FsO<\51AC܅ N6+tBv*{=47s|9Qw&cYjJnJlE[u1ѮUΑZC EHMؖ#kKch'b##9sZ| ms+] ذ]XJx:6m#fu/:dnt:2m'b/B2ǏctU (:;yqBucTO˿ޑ-Y3?/KNEŹt3Cx.%|iUJU03f7_x/!og y0\!#| Y?UAP( ׃vW;W*n1ZG8af"4GǓP鵉hFF5A3eŦ+x8t|oBֱSˤ椐M)oqD(َf7%EY [ěX@g'ǔ׌4=IPGh$4ӳTp_I\z,R/w4"NKV3/i\[IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/error.png000066400000000000000000000015711345766322700231140ustar00rootroot00000000000000PNG  IHDR szztIME05nYbKGD pHYs  tEXtCommentCreated with The GIMPd%nIDATXKhQ$14$V&Ħ 54/!1i`EA7t!P QDtS;7BWvQ J뫴&6>pfiW̙/g{ÌFK6e5aX&c{XX,FP:;;Uǩ ѺN'% $k% Y$)0J^ﶕGY@ XXX) OO \_r`uul6KLF|^_X,jB7պAݚp$IvepA+q0 n+۶Nආ05 cuȊJ*WfVL&r^J|p8 >g^ ʲ\J&d .E$)W-{Xw4@YW@cH8(pSwx&P@ ULf)Ps-O޽ fq.Z%(H>E Ha0A)b׹@yQNU( H` ͷc۱LV1a8E&@Pм ŷ$z"Qeobb)E"Fx?@BCEFGHLMNPQ STUWXZ \_bc dfhjk nopruv {}~!!!"""&&&***,,,---...///222333444777:::???@@@EEEFFFIIIOOOQQQYYYZZZiiimmmnnnpppwww~~~! NETSCAPE2.0!<,  HP \p`‡ J"‰F2*U+V@QcB jV,Y2br!bÄ=hRƬϟːrf l CӧOsU(BRiW`5֮hZVWdE.[xX < qrBŪU#jS11V*Ź3gPFVx‹I߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/muc_inactive.png000066400000000000000000000017761345766322700244400ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# #}:˫MQ̱0Cfff߿?oŊp3EDuttz?-G5ц(9?zKz;//2ݻwHEg͚5xBCi["F 6%/¦#WXUUU%0ذqFe0NGSN\D#9O<)s'@¥U.[|y=IIVэIOVVVUǣG~gdd\o"444 B-pi<Ex|g#b y133y%^N7xeJ(C'e 'DgD'2\FG䊝+TA*}OU 7JWE##[XA>5) ӻo}{g MjWJIsH>Q=VT~ڽHÆ B'M&'%}onzp IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/offline.png000066400000000000000000000020041345766322700233750ustar00rootroot00000000000000PNG  IHDR szztIME,XbKGD pHYs  tEXtCommentCreated with The GIMPd%nhIDATX]HSaMjaݤMҴ認ˈ0 B/ ([ix!EQEAQQW}Qely2w9hȃ0Kp^31z@&Ax [ rOZ Q978!028:/GEf3 Rii)NSa8sUb!GMMMC499I455EX(Pmm-QNN2s>\ n8)nt餆166F]]] I+C<]`MOI6M5nddDaNOjsp6.~p*sEww7SۥI(98>" 555F:::R&-ڸ^6,2fjmmMIKKv{-s,\( Q]]ק$ 7P-n'*&xϫzQVYYId0YdCʨ<r\dZ)77wJylAMi |QFL&T! &ܒ Ӟ4HViēVpq+?R}^rrb[d;5s"xMJq9˃fhL<]|#fcpn[4nv:Wb+[D7ߘ=Օ%r|s k{";w/E Qh# ,+@On(?S6Q~gJQp`T_YORv D..4;#;'QS,3c0 C+l4Bfg&t-AvW6v/Fol]ؚnY@5x Ff6p*99yfvvV,JHHHY2pRR[[233?777' 9d;8j Ą.V]]vzuyyy4&ᎧI fff$xc}X"&q222" [92X,^ruud@8|M~6s,;322RB!MMMy]]]M(U t/Sk100b}з'JDrKKK~ @Z rޞO[ Oޢ甧-@EVL|#"E8:!(:!4@~zb xyuZSx B$cJOO庺Sy||\)~C8}PBCCC&ڞcJzzz‚ iԁJfdSSrȈV}&77W'3z]@uHLLhkkӊ^.9 [5 z٢E{(*UPP ?RSShrR,6%%3D@%"<4& ^NNc%($6 V~o IvlXD`+sQQQ---]G0kIII666rN=ZHz8{v|bDg#twwǢ\244ʗX p,ȷ MF.$-l|Y 8f@PhIo0"T%a SLײbjDAq9c 7 2?E [EQKBR >͕݀uUbD[@&b^#hbyH+'Ax|j_ٍyM #a5TɡIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/32x32/xa.png000066400000000000000000000024501345766322700223700ustar00rootroot00000000000000PNG  IHDR szztIME)7`bKGD pHYs  tEXtCommentCreated with The GIMPd%nIDATXý]e̼vۭm.KacX4j4И^p Fnx&J!jxA,b]+[.lwv;x v[֓<ɼ9sSra' `w_ğx.YJ؎/L!HUR?i R$<;Ņ&U-Doދ;p0zG6A<(~ _ƽػ]Vs=## 34Do/*44LLHǏ{|v֏Rr,Ə=w-U_Ǒ[>EO5nniINcsh~Wr;Wõ|GU=7́go>T* *Uh89ee<Ӥ`wFƻ 7ko2m{YWq Q"|o3w3=}Mikfg} 4uBFťv%eWrq~؅{F愫TOc)eM Ư3M~ 0=_!ypu+\Zާٳonţ>.md+ {j$U%;{0χS`dvrRaJpf[2R]ը|-/ ](!꽯C|CNːa2Z۸!K+e3+-0fd88x9LLhˏ@Sx t w+x26B⏝(2^Cm=8}UӤv&I*<N/pHϑZo)7; >܍Wn |Geiek|;}P+y'޲v9YOFe@i*^"L5Hf Qȴ(EmF݊bolHCחA'f=!zV3Ѵዱ\~ +'<2sĵuRW{5XNǂ[]54߈͸.2" _IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/gota/48x48/000077500000000000000000000000001345766322700212675ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/gota/48x48/offline.png000066400000000000000000000020041345766322700234130ustar00rootroot00000000000000PNG  IHDR szztIME,XbKGD pHYs  tEXtCommentCreated with The GIMPd%nhIDATX]HSaMjaݤMҴ認ˈ0 B/ ([ix!EQEAQQW}Qely2w9hȃ0Kp^31z@&Ax [ rOZ Q978!028:/GEf3 Rii)NSa8sUb!GMMMC499I455EX(Pmm-QNN2s>\ n8)nt餆166F]]] I+C<]`MOI6M5nddDaNOjsp6.~p*sEww7SۥI(98>" 555F:::R&-ڸ^6,2fjmmMIKKv{-s,\( Q]]ק$ 7P-n'*&xϫzQVYYId0YdCʨ<r\dZ)77wJylAMi |QFL&T! &ܒ Ӟ4HViēVpq+?R}^rrb[d;5s"xMJq9˃fhL<]|#fcpn[4nv:Wb+[D7ߘ=Օ%r|s k{";w/E Qh# ,+@On(?S6Q~gJQp`T_YORv D..4;#;'QS,3c0 C+l4Bfg&t-AvW6v/Fol]ؚnY@5x Ff6p*,T׍÷/<+U0r>ߊmD_zPRRj&;0-d߿AKI؁QOJ8 f>6}3xFH4V&ZRW(x֙ˌdLލw[=2}ZLRA< 8U={1c @1e9HEDi4r Uz sAR'8`|>!IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/chat.png000066400000000000000000000016361345766322700240500ustar00rootroot00000000000000PNG  IHDRatIME!5WbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8˅_h[u$7˒&]W's ˄"9CcT͇=tS77Q>1/.hS۵-Iek$~'i`sCA;,_RRP(gf/m;thgb:==gds4g8 `NRv{'F'@ضdYnicAUX|s2| 8z K%j뿽YǑe=x\n +[៾8;< ǹ07iEݝ yZP 7*ϥj v,A2^c4aftqhLD]{梯nXo޻YWo##1= 1v|FvjToEdd<;.nkw*L`{ŭ5,\L\GSIu,2JFSSJaY8 rSϒy?!*[\fį/ dٞkmw=p0\_̟dB!4!Va-]ùJW!1طޣ4{BF*߷`oh/z4[z} Q5ky+Z^~e-7`@yUngI.ֺZG^o?o%6bXPw߫E3ٻ T/D ;!qX&0&V"D]F2iSG bIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/closed.png000066400000000000000000000003521345766322700243740ustar00rootroot00000000000000PNG  IHDR obKGD̿ pHYs  ~tIME )5{IDAT-ͱmAW`  ؕ#B9:6p59u`/_G~΃D[BIOZS*r}fLn߯%Lc)!m[iؗD[F"I7\(dIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/connecting.png000066400000000000000000000016241345766322700252550ustar00rootroot00000000000000PNG  IHDRagAMA7KIDAT8moSusshvm)ܧı!.#!1~dWx%\w&^x 71xED ͸Vڍڞ~JC}ܼP]>ƫzvJDPZ+vucӯ>WWo,ۥ!lR7k?˓~Zz)x{*9/6DPB]TXO7 .}]a"[Y [Tks5J_e |^o% p{4Fh6 Ja( [f"GH(V[i*N44Ճi=][QNtщʀ-DB[rdLlrEx!tO]xkrWQeM; XNb_czmCl#}2=򻹲"MAkcşY3{ڽL#|s6B8TEUmD[ +$sI$IŴm\2S+{M7'8vNYH)­Gn.`?,$ >2[Jx(Ca:mU?Vy}V|6~ ^͍*( .ev|,Y|JP}=gN)d(.խ +.`4-8&dsΏ2@˪&Kd*3@ N?apPG0ãzwڵO#})FqEF4`p_OW x2oIϹuޫU23@x {IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/dnd.png000066400000000000000000000015431345766322700236730ustar00rootroot00000000000000PNG  IHDRatIME/LNbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8˝S]HSacss;ss6م-4 4!iXAE,Bic zѾs H7? |_"D-yx~yy?"QRRCqqsZm/(vV}> [yWLrjC6;U(N99llK%H89 ڄ.ЍaF YpKE*=4LBTF3]6]9t Mva^1r8Xq* Ȏee!jmDf\xb]\x ~i  AWnh€^^0!S2;KpkVV+UN$'8pZZtO!$%@@!Ȕ EwcFtVjt\,9p!J)Y^&MwwӭB zE<-z~~MەS*H8DBw#5D^sqr+P TQNI(4TB7a}vI$NGH0HIW%Zm!\c؉m4 .renI&5n6w&lI_ dDR9m4.ȗk)9`]_q sd3 PnIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/error.png000066400000000000000000000012471345766322700242600ustar00rootroot00000000000000PNG  IHDRagAMA7^IDAT8}KH[QFDBBE wmPIWJU @ (]օBAFbU-]ԭPhTѨ_Q|p803"*D><y)wVS니Ott8Ft:OkDWUn`k0`vv8-2Ɂ܄e6$7u؀YMpHC23aj ;Q_[DQP | >Q v; cbP-S*+jjJKAU]$p+9 UrѩV*(,u`?MPݸ7>rի wPg4z4ɂꧩ ;[sXX$$ͯ`rki91: zKGő+IbFF`nVWyj&&`||jKGNgUf.{{aff *-izJJ1_>BDFFFGHJaNNPQPOSScSVZXY\\Z] Y\]mna _a``deag edfek kj{ijokipqv xuw||xw~ }{z݂~~~˖   0   " $ .-%+>'5%1*/&#+.^1+),()&* C98?I)2)(1(IUKNLDE2_[T==VTCFQTLM7! NETSCAPE2.0! , HAMEEWU8C<I`142Lh;| ؀*4@``@! , HI*Ti4D\~5Ơ=Z9/cHq0M\P*QW(S(=2]p$&,x`A3< d(A ! ,| Hz J *+Q`h S̢Z޼2 ep6Q(Eس8A4eFaH&\C rՑ(]C _@0 ! ,^ H*LdG!AY!,][BJߺe֍ڈ|Ga`ǎŪВ.]o$Jr*CH Ȧć2ixa  ! ,8 H*wb!A!Ne[qK# @1NF:)K! ,8 H*wb!A!/E2:WeC1G-@1NF:)K! ,^ H*H!P5K]K Ժeq|KaXǎ.]$qJD7AXC /AK% ! ,{ HF`%P SQ h tᅑR޼ZtN6Y ep)*HԳ814av<8$\qԕQ:9sI H X98 ! , HI*`TΔDcp  6l6{ie9mX̙ϟ>3i)Gy!R$S(jBJiB Ѫ &s=qA! ,{ HF`%P SQ h tᅑR޼ZtN6Y ep)*HԳ814av<8$\qԕQ:9sI H X98 ! ,^ H*H!P5K]K Ժeq|KaXǎ.]$qJD7AXC /AK% ! ,8 H*wb!A!/E2:WeC1G-@1NF:)K! ,8 H*wb!A!Ne[qK# @1NF:)K! ,^ H*LdG!AY!,][BJߺe֍ڈ|Ga`ǎŪВ.]o$Jr*CH Ȧć2ixa  ! ,| Hz J *+Q`h S̢Z޼2 ep6Q(Eس8A4eFaH&\C rՑ(]C _@0 ! , HI*Ti4D\~5Ơ=Z9/cHq0M\P*QW(S(=2]p$&,x`A3< d(A ;gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/invisible.png000066400000000000000000000015771345766322700251210ustar00rootroot00000000000000PNG  IHDRatIME$:KzbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8˝S]HQڦs:sNtJ! e .xNڢAL[ *,Jdݨõs[m[|"D-9py>?APC3PQ x<+QXx&sgbYY1& W$ՎH; PYypdQ NÀ+c!}̱юVX&cu_$rsᔪ^Fg.ݍ5yz|o_xFfe'z{yy t5#J҄xj{{b1H$@2 Zm}\v }kh%Z~MB!jBо###U`6A0{脬7,̀+u_,fCv1l6@.%t:l[[p.wjADYV Vk477Rx<,)1@(x3EP/$nB]@iF`o23?R[[[X,;>%b<ھkeJۡ`` EJt)hg D;;G C o*IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/muc_active.png000066400000000000000000000011201345766322700252340ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA?n6b^ ؓzڛR(7ɮir Z')ƃHK@E$ŐvgymI }0a}ߙQ"I(ˮz@*}Dddz'1fvyaL﷛F[@vX)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/not_in_roster.png000066400000000000000000000015551345766322700260150ustar00rootroot00000000000000PNG  IHDRatIME 5-IbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8c`[X_VRr $삨BB'o(!Qz@Iy9#>pQF 3t;>Ho?}J˾>&\VV8W}AD"Eqq&kX49N`!hh4nDMvlr@A99^@WT|bEd bb)fָlK5 O̵>1ۘ<ϲ2\&- JLwF6`|Gj֞ '&sn3Ⴐ4KnUFƝi`CIJFhlxkUDW`sD'ףKZ8!k>!!aauvro/o;;]wu[.xb\͉~![LTT (XuIFI\\^/?75pscV`ܻCK(BQꯧ^^^'%ǩ@@74 ,:Ԥ2sReeÇ3.JI^n}0)7 &&џ^wzEҧ CZX|> +抦f 0yWecKS| tsMCcekз`%%ŷΪ45=b\ik~^ލ@vBl -LIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/offline.png000066400000000000000000000012241345766322700245440ustar00rootroot00000000000000PNG  IHDRatIME /1pQF 3t;>Ho?}J˾>&\VV8W}AD"Eqq&kX49N`!hh4nDMvlr@A99^@WT|bEd bb)fָlK5 O̵>1ۘ<ϲ2\&sd=/=\rr.kc<0q؟e}78ԜUtIEώ UddXjaoUW7冽?;rg{ Xq @.)*r0&8ওyEgXX1?)_QWW$'7VE)֋ҍ@IY=6Iw0hjwY6d  p]5]34s @'ՇYY7/JJVj |p!pUIѝQIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/opened.png000066400000000000000000000003531345766322700243760ustar00rootroot00000000000000PNG  IHDR dbKGD̿ pHYs  tIME j$|IDAT-@DߊEۂ:c'>$:01Ј"hfowv:8"k/:rQ\N˷>YY7dU>H x.s=nCk$=rj4~`e0ԊIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/requested.png000066400000000000000000000015721345766322700251310ustar00rootroot00000000000000PNG  IHDRatIME 2!޾S/bKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8c`Dݹ%HT:)&.4SJ`dx4qK!,?'Pń~%].1j. ~^yMf YsJT5iG,+;69Na)f!@ ` )hq2SL6 14RޜScbtzI*Cn:^׬F0P 4dX`1n.=ihh`wJȂe%+LbKi.zY0&`7`H)磌|;xwz34}imPncUgϥ-N|Z GYXއ|/_qwgsǗGYd3;Q\+pokk87?_k%%gbz(4UHНSTv8`_WZ? -'5 =- U 4q]@DR>7#@YDj22}Qm}0ic%630tfg71&MWJ?_2'UeJdvAqԌ4 ;88o(-纁ZvE0jƘf0gg*,hߵ@gl;0WSZ-ι+mgIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/16x16/xa.png000066400000000000000000000015771345766322700235450ustar00rootroot00000000000000PNG  IHDRatIME $ sabKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDAT8c`[X_VRr $삨BB'o(!Qz@Iy9#>pQF 3t;>Ho?}J˾>&\VV8W}AD"Eqq&kX49N`!hh4nDMvlr@A99^@W2 .㛁Wщٖ'kk}b1/+de# aM_ԲzVoQ5/7h^|gى b+NL~b8Hm&`7\*h Pe/}˪?rK-91ED_߉N嵀1qC ځ=U}_>k/~__Ewdş,Ws_VA0%s<<;. V]aap_soo{/<?яe|;1Al+0݁h{%EEN}k|[?_ڞ׿`XDϼhpI㼀3,,@$eǯ5xOz\(-$`R.&oNwsgoX|w+-]y-Ԍ!?{w]~W5W>xYA!暁A00-fNn󀼘Yқ56x-0}-Ϸ bdcKl[`YIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/000077500000000000000000000000001345766322700224115ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/away.png000066400000000000000000000042221345766322700240600ustar00rootroot00000000000000PNG  IHDR;0tIME8lѻbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ P.. PybQ1m|j&L'It E4(jElD $$AȧZuU^ ,fy{ĔIZJxg== sԇXU--7c oTŔbży7l0e/bԬ]k^1mo}FFjj_~hOE"}eU{iܵsk@:bWlnS,"p5E&&OSbe^9kVpmPWK%2;;//h2[[kQ'\]}KFL&G4`ggtˑ#MU*<";cz |ظ{ɰRxy=%eX \^bmݬ;lpwy91,z%HEUC]zdFHC}hcxDxI:NWQ*ŀb>g_wP'j5ctjr(r'v>_fԖ`?Fx(+Pݽ3;!<2(sMP>ll6Pfuq\`>Ub&m|ڴώcpm7_?FzĬRjΉ8>֘"<^?g wȼ; r?Vxt˜4xxa([l YYY0 B۠?|72tZjyhyEq-ӹ0t[=<ޓԱXzu=*$Yرc֭[pkk+"""PXXeP1Y ' Y݋=ӫfѣbYRHGy-*YONX&BLEؾ};v9?!!~~~Bwg'_|@ Ԋˠ4WzxRڎ}$:А鎪wglٲGWW:::Pq-i6@5\NV[hO2U.YbKK iU2/NqQ~ T*'I;thkk,z9QE > u$;!9nVo-*"$k U2RSS!jsѕ"sv_Qt^J,R/n`3I[ @#v^V Fܯy&e"#5;ȫM.]5 H 4yu3DK\*rX[:(rPy> n˛3ܱt HHoʦLQ_D紀r=tt=Wǽ5Ҩʃh ͷ6x$5tP%d/3\\&}٤IQfSӕ A f5,C}lcƴemY. ڮ|見4J3uԍHwܸמ<9W_~~ܹ3}}n1Rntw3kGBq]{NYAcIw"nZPf[j ꨑô4樨2kY8˫dӧIDM,5*B>suɚOGxIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/chat.png000066400000000000000000000034531345766322700240430ustar00rootroot00000000000000PNG  IHDR;0tIME" ;DlPbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ PTe.,i@TAsDKGFJI@D"y2 -t&م݅!./"$;F>;sf}wxլ^t9"QRBB'*vwOV{ym( ZX6q+KxUhdj\Tڠ y<,T7dJ utrϿ566L%U|ͅBaeMSn̘ث11~K [N3_݃KG𤏻 NjWWgZ?Eh# vݸqwX;dJ-U<`qisRԂm!!o}ŋ˂ߧUS )rv*à huqqG<<*r޳($y3)6fQ;N`3Vp̏,/wr@`c8>.!ZO c͎,gy=GKB`3UA7D l4l3lolϐ#Kߣ,cσ)s |T/85p.je;"YC!KraI,Id.Q\_'p ̾ XF5d3Kvj` (ۨ |d]}rE},~`t%)ziX:DzyBvh\* (SF֖>74[|%tr }u)ƁVp{,#|>cTy J7aBuT<:k},z!m056Ć3{{K%rz$,+ \HHgx#M,{,䋀@p+L]a 󟓁N7@ʡkKNv4ޛeG:s߸kC1ە7(F&ztq~ky8 ;򳑜a;,Xuj0zCKclDBSMPxu~묇g { GюZQ\u=\D|F ܉GG*Ͻ+M&AZMR7$2suT@C4oa$R?LZP^-nwcDr2tzvTɓ_%ngn[;I (ݮ2ezmqaUI6V9Zcjv~)J*WS95kָ>,q6.Ύ %.xGH`" T9>%+%0씠pU[ ]"*Vh$ک \^;t:)܂ǁ\/P3pIۧ@t+=PLkt?ȇ~ÈP43ix[ Ge8-ϥC?YBSem% ]ԃP/4$HsM9AsznIW&邂F]=zv^@ %[JGp]9sROSi?nA?q۶mn!ÐIKGErn"xG<)/vnIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/dnd.png000066400000000000000000000033731345766322700236720ustar00rootroot00000000000000PNG  IHDR;0tIME.%+ZHbKGD pHYs  ~tEXtCommentCreated with The GIMPd%n_IDATHǽ LSW{*[T@y D\f4@2(,Ǩ#IBL榉*LD&$ĹatQK q(e+2pY9ߖL 7{wl;}hrWSDA/l"$oQ,"ESϒCHn6ҥ^hM J%VUYė: 6=b'4ǙϼDy'9NP1 ؈Sbn䷷;1BFKKgRFkkݱ" 0Z^hQPkMȪȩuñw)""@{oE"Z*tJF-(`tpUQafaOח8jKX9p)2rO]UI *H]Ѥ$Fss변L&P6uwxև̢ƗBcv."Yz?Ph2:cff2j0 Ԥ׳(3* ee}~}ñc UdzKZ љ3ȨeۇVj]`z0 >)P$uEP& cZ<P%8x(tcӐhFs`OEC-_nzfYǧ˫ ~l;w/afM2>LMsŗ`}*љ3{R:spH|J>vF{{??+F044t -6]7;7͚۹ Kpnn yS? t/IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/error.png000066400000000000000000000031561345766322700242550ustar00rootroot00000000000000PNG  IHDR szzgAMA7%IDATXíyLUGhp<1(5`2"D$Irv+W;G&MÒk0}nwy׮L2AqnL['FlA"τ5 HLO9s.__ !A}R<`VUB!!@|<cFv?i63̮ٺI|gg;=(-hvq:2giS7k䆈Wã ;aa@ddN0m к5޶ldG 7[!WE+Æi.]?? 0 6''cH\eFV8x>`4H "w)u72=uuI5ZoDž z'00]s7d 㬮 bB`Zq!̒L,r\\~%F8|HADFV(|aBq>ٹsnDllKW DtO]M36\,_˂2,]WWomV{Yu2(IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/invisible.png000066400000000000000000000036361345766322700251130ustar00rootroot00000000000000PNG  IHDR;0tIME$dbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ LTWEAQتQ,2e@H%b( T@ֺJ@ ̀,ʢ ʾZO}ƭ(7?FU3hى 6WoQp0k36bCjAss'٬Ypqn2a*D{ n>zToT)SI,7U8'5FD;L干ɓǨ|a=o4mDcTbn@`/ \O/yH,-cKԆ ~BBDZfk{X;z9$n3ɍ4OY蠿Gn9)%S$aou9CHQw̜9svjݷol۶ 6l+W:u[[[옯䨑~= |V+9MñBQUc_3À(^BBBijjjٳg!..<7nTl2f9fDNحG6r5Θ)!eA'`y!4)O#>}c BSS4440'OH${]IΤ WdhDOGH,*z.W U-'mabp8|>.<88O>:ec椿í}%;oaq5 Jh'<ʬ y/TD"aBTTT@ݻ/ n  B]o>=Q>Z%rGUիV! t^#yI=@TJ>TTXX)HKːI!!M8Tɶ bb>> p}kU… ;.f"8pT9ߟS$aXDc͙c{1Sp yIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/muc_active.png000066400000000000000000000020331345766322700252340ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/muc_inactive.png000066400000000000000000000017761345766322700256000ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# # (8&Z PE*QqT!BKE!XTQ4MQdQ@SA*.gjj]Xl˼y}B8Zbc g*LLꜜ$C8j s A S&ǸuOajZZZf =U;)mlv7z{Onݧ-^,{xǻUA~rGp+X3'Lݎ6ʸqQ^#;@ ? ?C ƆܢZj}V\I۲p#`Y܁jH"&& pA,xx^DU!J݄Pw(-,kQd]e#o4-0F ;Xt ;bXv5w=>N2CaamI?1PdZ(0ylb4.d]*Ӧ? |~+=dC3Jm++Cl\2}(--YX% \YDBJ$dLV!?';t#e :4SfL݇tLP%uRKbG+)!Rї+e>bk8z&ǐ4hiLwRR(LEy:3yB@H@GK3]8+M hkP(ر%HO6w*cViɘXh98RBȖ.ggJ[Y*/ٳ/A;~wĜ]s[PS#ͣ:O7.kk"¢'e)䂻;@~>@a!UpYSSf)}4Syxչz6Ûc{'@ |9 S*< ̠l-ݶkN݄ ׊>?aD;w¼y̚T1/s8F7>h2VKv!,ccAQOťW̟ tZ9f̷x4c}zˠH5#s#0P}uƌiUzz.h- ,s_>ugLgEo|mIUcS@im]- Dh.N4X(+_(,ŋbc󪺪?t{yA@PMEnYiI (ixV2gPнj۶.~[,Y76njg1VǩS; `9z-@]`,#G!&=$֭?;`TO.韯ž,jmqZ^ `vǡq͚N{kg/SSWɤI dDk`GY9.bAK1_㽏m{ͣqڷGر_&%̜ 7s(]138fh[Sg2SD˭UQ Q9{7c#_KM|354B|~q6ʹx-5j}`y!*^cRIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/offline.png000066400000000000000000000025161345766322700245450ustar00rootroot00000000000000PNG  IHDR;0tIME 0.|7,<bKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ}Lu;w&@)B$¡h B4|ej f/?GJܒw{3<,hƳ}>W$|V|2g#bWupT!WTT;Kx&_{tKW$nh|8"gIUڛ3m7}&}\xR!|3LyՄV+cm%aIG"bi-&/i<򺤰逳gǔlU*udq 5^bɰkr,ݞK'fcԬ]1_]liIjLʌZ@s]=X['`?RML,JmTmJyY[V]f`Gh':Jp/G((!v mdR}GL]ӃU5o1qPVy6M" ;-T{]Vo'5**ڏ;Į\6=u}Xkx^K⨈[rA:,X3˜s#qC(]tc!;p~F.#g@RI2_'Cb:Pǭc[CԪADdd_&~b ~K?_0mkG[)X3 $3ʠ7O1 R:9cb}+1G抝ӝ7{y,O ,MD9瘹//"kŀ)[?A|B^kIڽN(1W^$w6G7tQn IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/online.png000066400000000000000000000026071345766322700244100ustar00rootroot00000000000000PNG  IHDR;0tIME iebKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ Lg{-m) ! eLe \1Pl\9F&NYl&[2&oK\)&+7ֶPvήJfHHrhϭTkdVw޾Sh{;^.wH8vlm]7W!?H--zJd^x1^oV ܷys{ Jn(d66!n >? mJ*+M+3{LLtq`K^8~3xt^A@8{NK{-,& r9m"7wHx>'wrjSSk!l M"#G}0s,Feil>e=ɩJL=5LZATEFU RPHh[|( O8v@&3SxqK.;ߟjkʀS9U,J8fz <|߶F CKmlzXZnL5 e2e0*7j-/7MJ̴0cb"$\Fx>;C#Cu-ںQҩ CW*qni[z5}^^x DDrD2B\J61u3P/jm?Ot:k#7~=n"k6e@]^=DCM驀.K=ܾp V쐘ECxEǤx;8CD~s0`mI*(^CG/-(X\WfURRU!!~~UCC `FGap 5w۹7WD8 oo#*>_u=Je5IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/requested.png000066400000000000000000000034461345766322700251270ustar00rootroot00000000000000PNG  IHDR;0tIME 2 f?bKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽyLg-H[KP.K0 CE%NELă( (l x fD3,% NE]W Ø&Oھyz9MçJf} ,_C9#Xx/a3riZD>b,%VM"3HnE=cb E+5qȳ0?6)`9&0Ldjm_ qkb ,[k5ksw5 8LÛ<#)p9~J\uY?MP蹅s7 L!m,ںZ1;*=. nAΡpEoW@biyh;}b.!I_2< ?9.9˹R\{>,oB{8xЬF1"C\ èi8oEq6~&X 0! >s%_(>9|J?tֺL}P6u!ފNPAco{dNnR"{LVr%SpY,\T '0v sXG5*SW쉶wOT>H%wz×)bǏwu p7|g>)@*P`U!}?gx҃W+E-ҽHjAdwkTX=&/Pnn]\6Yp$_ї( WqO+;;bffHvt|՚= ?ǯ9C; I5q:>.>Q\:+<U;,jѬիĦLяa4,"zb0nG$1VފYG@z뉇P MH*b.N"qF܃e1_#}h}Nlfz>-oZ8!G(dA2;cɘۄ5rqipS*J7eFIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/32x32/xa.png000066400000000000000000000036711345766322700235360ustar00rootroot00000000000000PNG  IHDR;0tIME &FvGbKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ Ts$r QvT(MyN:=vC7q2tCStډB aBԲ$$($AIp=XYa;~<'s{C)|^&>d_zz#eH1ՂKMܷlْ\qlƮWJr+?|gjUR ڴt ۥ ^^D~p>E 2&ssO@`&&3w7en*$$MdI\Y^#;_jJ>{-&gSΛyԽ:N.ޟa>76Za ocZ01fXm(ړуw^^T&垳g7|~!H*iɄ7I)J*YD̓rr_ )czX}u7G`SP貲s:wd]GQ(Ь%;˦QxzaWw=ʠ4r@Gf-}W(0FȆ0d $2 5d4n)R1!x)^dvɸB"(HU}[E_P.^:O&6vlzK9z4tڡs(5;vv;$mgבө TD>r_CiSR2EYǧO'6^j:QqR tЪuBAv)Y4voH9iL kޔsBp N,o L>ck1jT mwBmt ;Bn|ao8 j&1TcúʔN&aJ?\4JŔꁙ Tת@kjj'$XP&$T< |Qo[q#2ئ@o!fO`4 Ϛ1Zw [h>s{\,fܴ{5k|bBF8&ab 9dX u-|(I$N4tXQNVGFJFmK.G x#U?F=m.p#15p 3kSnYD&Q7[)~VLqv2`_֍"m~Ǭ&ڦ{zj?@v*.(diki.*b,bw x7jHŷH0fv>*P&t)T(*[wjJ7pDABї\k cʦ2BU`x ?6Z+pD?BDGʼn k4re20Px' jOQWZЦnņ(pA: GnPvkU,cGV. smҥ }ZK;}ӹt^ͳF?.i7L]IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/48x48/000077500000000000000000000000001345766322700224275ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/48x48/offline.png000066400000000000000000000025161345766322700245630ustar00rootroot00000000000000PNG  IHDR;0tIME 0.|7,<bKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ}Lu;w&@)B$¡h B4|ej f/?GJܒw{3<,hƳ}>W$|V|2g#bWupT!WTT;Kx&_{tKW$nh|8"gIUڛ3m7}&}\xR!|3LyՄV+cm%aIG"bi-&/i<򺤰逳gǔlU*udq 5^bɰkr,ݞK'fcԬ]1_]liIjLʌZ@s]=X['`?RML,JmTmJyY[V]f`Gh':Jp/G((!v mdR}GL]ӃU5o1qPVy6M" ;-T{]Vo'5**ڏ;Į\6=u}Xkx^K⨈[rA:,X3˜s#qC(]tc!;p~F.#g@RI2_'Cb:Pǭc[CԪADdd_&~b ~K?_0mkG[)X3 $3ʠ7O1 R:9cb}+1G抝ӝ7{y,O ,MD9瘹//"kŀ)[?A|B^kIڽN(1W^$w6G7tQn IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/jabberbulb/48x48/online.png000066400000000000000000000026071345766322700244260ustar00rootroot00000000000000PNG  IHDR;0tIME iebKGD pHYs  ~tEXtCommentCreated with The GIMPd%nIDATHǽ Lg{-m) ! eLe \1Pl\9F&NYl&[2&oK\)&+7ֶPvήJfHHrhϭTkdVw޾Sh{;^.wH8vlm]7W!?H--zJd^x1^oV ܷys{ Jn(d66!n >? mJ*+M+3{LLtq`K^8~3xt^A@8{NK{-,& r9m"7wHx>'wrjSSk!l M"#G}0s,Feil>e=ɩJL=5LZATEFU RPHh[|( O8v@&3SxqK.;ߟjkʀS9U,J8fz <|߶F CKmlzXZnL5 e2e0*7j-/7MJ̴0cb"$\Fx>;C#Cu-ںQҩ CW*qni[z5}^^x DDrD2B\J61u3P/jm?Ot:k#7~=n"k6e@]^=DCM驀.K=ܾp V쐘ECxEǤx;8CD~s0`mI*(^CG/-(X\WfURRU!!~~UCC `FGap 5w۹7WD8 oo#*>_u=Je5IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/000077500000000000000000000000001345766322700203435ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/000077500000000000000000000000001345766322700211305ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/away.png000066400000000000000000000015531345766322700226030ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8mRMh]Ef;o6OlLlSfc)*X(? t#PE7Bp#")bq&P*Z\HuEb[H =m{3wq|$gq8i>ADsiq2{w>T*y=tDrν@uˬya4%xVN6Gwmtg;Ѱ?3GyWVk{}&澰iq-c[Gw1//?{Šolu*?)׻^ w@ '叽#psZa~P7үpta ,2w"lr ٳp?, o@t􉷞 g3;BFDN˪}w7!~xO_ x| 1"sH)ADp!TK˺$IsH)cD$`!s0bY ! !Q?BY!$1ZkeB Mӭ3㖁8c眫( Dep΁BPeB1X!.&eY "(P`R {cBXlaa!j)eB`s,an1*cM>551cι17tWsG_[kuuc0TڹVÉKKKOJ)g!RUVkxIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/chat.png000066400000000000000000000016401345766322700225560ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<2IDAT8}]hey4i5bijWN:AE Na/*ɮDKA(ml Y`/Jn:7ݺ6%M7GtFD5秼ddhbhSTDĬq) {һiAxh3mV@OnB6HX闟U#啓vhl0:l rU1#;H`ܒ S Y<!Zls Tu%e?9E/`_s͝WYEQ2cs=(]ZǢC#& fQK2o j--=I,~2- ASW?w57Fa|@ů e`}CsLdo4ʥ$+WLox+ lG˃|\㙷囷sL7ns4,+\Tm8S1 7-dL(5'UN乣';hWo[&:2z 6Z8[`Vɗm!=Z|0v¹z7@.x[YXf>kg-j>={RNr|qp/H׹ƨSwRC"J]0;51F@8BԢV+j( k?Z5 Qo؏(k߭pI*DGWɧoДܰ\%CDU33/%;FIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/closed.png000066400000000000000000000002341345766322700231060ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME/u)IDAT8c`b2Qj.a;H4Q@z=VIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/connecting.gif000066400000000000000000000024341345766322700237510ustar00rootroot00000000000000GIF89a= ! NETSCAPE2.0!Created with The GIMP! ?,pH,Ȥrl:ШtJV!e!! ?,5pH,Ȥrl:ШYY>ay$1!tGiD ۶'2)p2BI@)0 XݭCF@BsN)fY2.G,kzy)B($2n9Rbދ~T*@DD+"]{ۗHOgw'wAs}Y5%7v/)Ϋko0;h~^ƃD2wO'զv>7LLD <=zn&?ڙ h&M>Vj}0n/GվJ ]."­K#ށ Z8ʼIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/error.png000066400000000000000000000014771345766322700230000ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8SKTQ=Ψ)ei A E~:j>2BD79#jFBTtr,"555%Sqf޻k3`5>=p9 "?mae˿8~UM*sԠ0so&6 Q+[3W$=dYS="@|8.-9i0|>T>Bx<mM*[qLV倸`KdN@D;=9-.159!#%)+.2!"%',.ԃ % !  T! ,A;>9;=7*-.159!#%)+.2!"%',.܂ %   !OҽA4uS()! ,=A;>79;=4¸.159#%)+.2!"%',.܃ % 鈂!   7-ӁLf ! ,A;>9;=7.159М+.2',. !"% Ђ!  ! ,{?:<@/368;-0  ;= ¬9̴ϊ.؂ 㾏! ,?:<@/368;=A-047> &)-/1 #$ !"Ç!Է׃ބ! ,?:<@/368;=A-047> &)-/179 #$(, !"&*҃!#%ٸ! Ň(@C(;gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/invisible.png000066400000000000000000000016171345766322700236270ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<!IDAT8]lu>3;n ei]vK)!i6l0bL 7C!h"XBRJxZ 3ӝ˃}&_nrߔnv<9ǘ>:9z^0R9}iOZĨ5o$ɯn&Ȭ+~ml(<ǘLIU%rɫG7[)-O1_ LX>2>STj\}(r慆C=K{v4NV'HݚZmҒU)\ǩ#DwzōLO::$l1E]@{g5'@1W! JI{?_ wν+s.-F5 -Me% ;D 51XdUenF++Dqtvu!>ϑ_&/PJ)JeY9~!&ݾE@VӸ`tU/.1Vm>+':/k,2JKB&5g#eo#cv5gm;55e{}vɮ #"cL (`\sBJAU[!a.7)#B'A6nR?lc!Jc*K.ݛ$.\.s;DSz@gD$׾KEeȵc Q]?ڭVy EnYfFenS.ozÐ ,.eRZyŭ2,˞ΕJ6ŢX,~\J%ۭ ð#c b";Ft:U$yZ8gY|nZfp8TE;i4;j{ދW zNjz7L6)`HD$>t:7|_kWZo=N dg=m1缚mo l)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/not_in_roster.png000066400000000000000000000012501345766322700245200ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<%IDAT8kaƟ~ص-E-"do.A"RA\E)5L]Һ8tHl%WҴIyR8s9,gRy ec̓\6=Y foO'L}kk^uEq@enC6={K1楔 ƘK"Q;;z 7j !1 i7B%wM֢1677a.H!Ľ+##n2yN!0@k 5h6dAq*rjC }})$AkADB@E" "''o"`as~8` \ppơDo9~ a/GZbhxaJQ:PB)(((zF(U"s|'Ϳ2~%T]9i?qW]gEG+:?…; ?=r>:)\n RV ^>I\W?.b5o,%/yvw])j/0E5wwًYwwq79* useo1Ɗµ+n*Fh'z!RM 6 ZAaid[߹ϯ+ PF ׫lOɬ<(5j"xA޷ށSqVZ^NMf%pʮ[{6Pҧ.RHgiZ6g +IqTK<=hXmP8N0V;IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/16x16/online.png000066400000000000000000000015601345766322700231240ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8[hTgns$N! CZ-)B@Kku[1&Q|V/U1jTTWҘJAQĜdaa"ǶݼyCS7ޝL83|_ip//YtlgƻFO?(Qqy SL)w.\&f;3I, 'VS9\[og[F4,+[Tj٬KC 5o ]"a/x뉻fvuhp*|ϖQh IcNP[b4|{LS'q#"1>,˂(?E}7MA4 @)E, }J@ y?ApR0.<ϫBxt1q&A 28 ÀeY@u88!ATyȕWP$ xq@immeض u[C&eymCCCH$PJ `fP(JHIEض ˲:<&''c1H-MMMAX|"Z%IjEqθ{VY{s0JiۇG)@__}o[zI:jR`H1nZu2׃ǓaI/4!_]ߺH1_!0qKwMw=_RQGj8|ME-D ,<9'''NF!f'Tvc¨F=Wtel3ˏ^* $>@vKr-mmEiS?9lIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/000077500000000000000000000000001345766322700211245ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/away.png000066400000000000000000000041071345766322700225750ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATXUǿ̼yov..]^aYRm6iP~1D-Fb(4 FI$[ E$)6v_k`fAg-]Hf9s}k-.Įk|(cL|?zԴ:hMyl&z}_7H# #gHX8T7ĉ닸n߬o\gO[ƳSjZ;+BJVq3LKn >q܇F:X2V{P# 5V{ÎI7'R7wq߈'Zظ#;ss?Z.w? ΈF*XH.q.C<{7,n8n؟7–%wG@4zӭ􅭪?-_^~n #*am>v=l9y:M#9-@sCn `d3yէ`j`LaMT ZѦ1Dfg}fF}S6.n'OladcFЬ?BGΝ%' ˏRtqίBݫA@mfnϾ1LN0;E0;`3eavqE.][]R B(}^szLa_pp;;Imӯ[iFTcSq$Zvxi s~Xka#Zuo=+aq.[M{`ttt7c쪎JA@k5!@./6k{9sʜPSE1 {ry'}M1:=σyclFp91(93 [JiJ)aaӡ }8Zj!"XkJ%Bt2}/`Lvscju7t]wI3I)58Ngsf4\bKK@)M3NܑR>H10 ""q(`PFB(HI2g+B)cl-oJ)ri6IfqCk 510ƤPڴTY*qTUy^*qBq]w}Bspg8NesqV* `pRBHBR_9()eBFVƘR^hZh6Ks̙IR3L9.؆ 9̀bKD^p~\xPc`!B7Sj g3~y.`;#@@N@kؽ]}8ƿ>XC_\_|Pd6l|P 0OxAP"+l!¤Gt+C4媮8* ʤrbL'g\cf dduTVM)}T*3DJ۷_],_l*˲ @$8z苞}>O1<<| ch4RT*ge˖E^r%5M!RJ$IJ):>|s'IPJqo AQ̠^?^.8+m۶e2/_t`A4H)l40 Au$I::8Vrk5M Ik6ls `֭-AXD>O09mhZ`!IDQ9BC6a8-9pBQ!E7n4M80 s4M8J)6\ׅi0( E`*e|߇}}}PU5na\{Zց|>˲`t]m۩6<΂1 5VJ)z{{a6!i.'SJ`IH)AA` J)jZZR&$@. 2 TUE&A.KpΧ5 \ntRB 4 R UU*h4Jth48)Ia`ѢEhi^BǁR,YRm!4MK4 i""!p,,c,/Da@Ӵ(p]4(T*UU^0EQ1(*$eYP\.$I i8[QPJ1;;0 AADRA^Oq:RDR$$ز,q 9:jcm;5l6{[˲A0== 077 @) h]Ӊs(9 mu='Ŕ.4>)ݲ/XhN?/St:kߗzȏ`j0ANT~Oar.p/y3z`]bZE鼋~BZ0}5r0/CN̚; DJ@FңR8 [grV؊n;ހ?p~cr# YEa^(xgϥ8MXgڱ^J)%+?(+7_}țԞy Fw~s3NAs bR&;߭aS4дwH9S;]YK)O5ᡱe篼@/`S]9x 3s?wi>K⁁7@(v߭koQ$PWϻ8S%yOv{_|V$^zmF_~S~]%o2\IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/error.png000066400000000000000000000035151345766322700227670ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATXmPe-KA eL$mqJFNIJɀZ-N211:6uLD% "/L@KD>vhs9s#J)" 6 UVwȷWTGGl@y sr&k  SPd-/ 4$LKG R{Eug!VW(:YO J/BGZs]݁ * r"Q@Jj>y 4&<* 'ifBͧ>^ B A΂1b c/AȰ/1>y(#t]@9e5y*Y8N<Þ"3xLX(om$zio ǁv0xxDEE➘+©,Ҡo^ܶ308_h{5#|qu%( vglP?Mީj^uW63aǻb>J6SGq>pYH]Vήnsק뀁[oJ>.sXOo&رCn[_N f(cٵr[мX ZW*eBērϷt3qK~vہlLssg><Xl6@ dz :m>CzęKٸە=#7lbD)_V,IL$x~ԽW*b5 @D1ܮ(d<3ep/o#8h2_Ӏǀ#n;v*-> P|@lT},փr'Opqxx˜Yu;GߠW3>p]oCnc /9pXUiw/+v_d]xݾuY 1 y5.M)R/u[4w{^d9|E#j{5Řn`[ӪUE|Usi7"tRg+R M\3h\>qbc'֝OsYM hy? L]P[@bvӟn4nXևךHNN&66rȀ@ @P}ߘBXSՀΟlxw ^4y5kc8ׯYUJC|΅lbGL S'**S)SK?Q(3|::xm_gjvX> / jZ]5nqX~lIՄ$H@k&S^LRKfۑ_2 Uef/zzsr.9+ߘ lUJ!O`duL[ڱC} > q *MAL0 ynu&a bazf~3w%s\EW;qr@c]&!+0sOe08#C}خRyMX=/)aB惑5ә w~o 0gcr$@H[L]T\؄]/ `[b- @P-XmFzgcvjB+ĈL #m#=4FR/[&9L aCC;3o8c) 7~ku@ }R-z#u9 }n#`p ;g.YF曊[ 2p]&=uDoT> ,ԯ\S6m,ˋnHH&[~q\Iսa`w\nҢe&}rj"+7>iծy c+zu;gTs6̔3fT*\wBreY~R0& q~N(AYY)ƎCՏ9.Ѧ?yJh"[?k,$Zf1EIǦ+y7@iL%o/5BGa4+~V僔k@d! ] 74y>x*uǑS:aDOjD߿>I^٥ϲ]кZjsn媪e7n@l cM@8isM@>Kc* z@$9ä́ҼUV:u*پ}EAP S,!L$ErZtm"P 1c[k֬YEHP>pATX|$3u 1ɥ6zyW$woesPg%zs |4 9\ Q_<=gfdocA* ޷M./}ns;Es!dѾ!qJF9UҲI9rB%Jk$S27͹Df[E#ļ1&L#np=0ięדK(`` EW ߃N2oDQ$a#ʂÈ*0cfpX)Cݷ*"b »Ύ?0(;''#oT^48@79c{M5mԎأZk|Zf WrzcuI< "u? =CJ4@& MP|k V7{Z {=wo%J8(( BB?] ʙ[Ђqto-tM6x,)\z*>z}G7ͬD 2`EJo~ttL"+Y'/ QCEy0$7S'N%|@&24v[ N#I ' :}ZA'D]j|]p78{/JzKɳS"Ѯ"d@gТ ?%toI/ʁU6+)d9qVXhZkA߻}gd0͓_ o_ȁfc^ P&}9w:\vO\۷;ݯ@ 1TS@¬|fW]#ք*J`F3]9nkT-$]JDtLKPQz$# F]f$|]:jA ~ Y9 34pV=5g~J& W_ԴVm2+mذ϶7IgM/gs?mL={m}옮/Ca+okɆێ?K埭\q/Ue IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/muc_active.png000066400000000000000000000020331345766322700237470ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATX_hSWǿ?ƴ)@AX_XA&:Ht/*%1= BY D02(yrL, ,q611'瞳MڤY sw~oH#FCCC\.5pjsyw8yXoo`0JiSNR}1 ?sֺ `@C@)Ϋ2{Rc _-'ccc<^ ?>߿f4R/: ߾Ahd鱩`VȖ =Kq@s'J fwŭs(,$I'._ϋk:[ȓv)@)[͝uJuz 6Z)شBXR@@jN^J "l:[nT i&A!kpeaffq4MضW%NL "H$ "=u*&uEoyi"NRN||<Lm+$xOX:V}v~~Cz#lթ+E7ݟ8{Z`6L_*Iet?|>_XXC>Eo~^էg=_s\D^hW prp8YTK-Ӡ[|^g^._}m+ BSl۾ s&!ZKԍ֯OR8@RUJW%@rFStvvsss|fFtD0uwa>}9˒2 VXb:pv 8bL_\BѩҒ]zQݽDP"Jٮ @Ad4}SvUu m#X١:v1'˦옗(7,k KлdBBIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/muc_inactive.png000066400000000000000000000017761345766322700243130ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME !sIDATXVAkF4,ohR C_=RC()!R989l{1!%罥? ǰ*b\[iz$&i9`x|Iݤ$A[[[_iְmSclR+I6|>BDspqMD`0QJcl,c^4J)l~ $Ip]w"U loo(Jc8Q Ifff0??GZ_]]5(v]WWW8==0m/)vCUPJj)B88AU4x\HF(LRQ&3q&$Ɩ S|yc < $T JR لI D7#@cTUE. vF*j˔DH8??gggg Ȳ|8X .Wbj^i0IeY!NG Rf|vv!mAv#J19nnndx.$IB6nw$acrpp8 b68瘚c rĒeNZF0 fYVb\ X,~M)m}}=jiqxxط,GuOTտ`gggEQUUzGJHDt:*!@u4A|m3M{q~*Ѧb~scRTg2to<3gBA¼a VeT.K^# #ȓ!˲"1R41 ") ]~u}Vb&{9s= 54Cq/dWoI ~1z@, V`ش);: 5Eg:|#1pbB H2p2κ 㼺};xF5L:;sOdW/4g6o3FhMŋ9s6oDs0s6}}J%?:ǀ3鬮$S@xAtxm\av5JH%Z0999_CL:xM?q6nHVXV (5riVu4M&&&818H0=Uu&־ ]SSöm44c(<<=Fk-+Z٠\ŰZ[iniX,2^czzr9p CyL:;#28@ƍQqib&ieYXisiE6HSt>T.$tˤG}yXU fP331~9(Hw#: ݺu}>a22:z=ݪFv|r9LN8{W.tvl8]Fp>wW?ɞ7`e*&pgHe!v(WXIW:::PR1ruy&{n_„*=%LN=K'. 0f+P_,d<IJ XVIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/offline.png000066400000000000000000000023161345766322700232560ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs::͘tEXtSoftwarewww.inkscape.org<KIDATXkLU߳3יeZQQ!ћPI(bE[6&i"1ioIJlhb1kj",6҅.{vew%|>眜3MpR;j M3zU(*$è$a`jv䕺tҫ5mj$d[}zMnuwX= ?dm9bJV .++_cROQPdeEJDZ1@B]{{1<DA0X<~]45CU9yz{ à X0N%2 PUnவ`1r($Q^VBث5:͵EwC L@Si,4MLq5P6mm^n6IFy a Y! , yg_ͥqlŅ[&qLgL`}.Y:ڨ\$(Bh.t]|^!\Ţ}ε>+EUBj3镘gRbakBDt&TB,Rs :`1cAQHbH7 O-+$ߺFxAu TaDf0?۝~.X @uVX06g XJ8(ڕRۭt1*#)yB؝{fF,!euK @Eu+߹N,OS'KtΩ7׿lTc Cf3qrM$G5uڞ6Db?BlWeoQ]cc#^ze)t/IB`1 ź@3SۯlbpZ<P5U^j)d5YN+ X<4^U1zd g:,7IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/online.png000066400000000000000000000043361345766322700231240ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<pIDATXW{pT}nn6<&4_v'ǽ6 F"ՠoE*4X|kF w&] Ή/iE4 I^o0%U*,=`;GRuH}xvχT֢GET^ϸnK%j~@̘.\#OmNQ"}nCn@V Y{ H&| ׵;벃ǪMmռn OI1W{N><_F紽gL:*l0 Y}/_;C[_껏kgY̸{L\*n.1>z؞uޱvWϣd5£m=e3 jyEM<\崽 u 63'<ވm(+ .{F0` S+ e%" u(VCDu=OAYs%|cYGvm7'Yl<3Wxt{@dd  吮q5ZBwi\y'lOyF8'u4a^]?gȹȑ|N0dO#vHk0MIɚ艾|?gqigc僇LY/gdn|ܨݯ ˉ9SQ"<͸<<֟ke, ~[fU=2d SnށErW> =Kfkv չ,~Ɋ֎4`qDI#)@z_͔इ:qƺ#s{DߪO7?l\qZoud2V =dLNm3OE-I 5 %p3ם!t Ac$Sox=1a)^b?( K#APY)S O#B7F] 0bVmVVG_V[!%5bvf$,4rlx Hg.9 !!A2xי hbS26 j>g"8똛3;וرNU:@RQ Y7DpajRhbm8џom>}_xS\v˚M$yP9RH^ۙFB,)Xxs>{?Y@/\û^W4TW4/?:MLN҉CZqH;AX1H;r 'r3"|YU|vO'Ǿ׸uZ^c!;ӠhEK T<"A$.ȏcqL:s0(@'I ~^\Yݐ+F<负{;U'swMj}J6S޳vs7AEq=Fv0kcgWgF.^^[cuиRD)< ),Q~yZuk}tb{{*߉) ڢkl{}*]u;̆6"?;&Z>S//u.^⛍?Ul7RTu6(gR!,̯M>& 1` W@ ЊK`'._B /EY 1zFп.E3IMIpHk 2G ٸj],Zt_|oX .AyA y!rssZƃM`@kΉ Vs5ZZZ,-l^`dprmVp4o#==p a pΝ=ˮ_@k 7s2PH|ݴ8s˲xikkm bO}O} {/5irf:Dm #ǁWVTew[ 9LduX7@P|`-e0͸>qy x⻝+en+;_[4 ">9W HjF^!Dexwn+x+5|< 5+]͌UF~{`LB%&"LK,*Q9 u151Oc˶d y󩮾7^X>qn 5$щQX ZcN̢R"]gFN8{}FhɒPQ^NNNnwn|qw ۋ}D{Ϗ>Ue$-#^8JIL^^zH$(P@*!  G/!@M s|3Y đ7m BꋬMR1paZ֋Ol3$1V Yp5‹r @¡Y'>iZr0ve|hzπM[CuD @4P $d 5˃7c (`wlKVd;1"I7>v|bpBvWcD Yȶ?4R|uƇG<9(ǜD?sϷvm{mx׃&sNu֍03jnj덊Ԯ:ΪBp:bXQZd}gmForK{xwj-]` eZk׫b)7r(;k35zRZ{TVTdbFǛ8z +k:UUUcRϺVsZ^{.|-~J)ŎQP @k*rrcyPWWe2Ӣ5XZ3q8o+ ˖=BzvRS e&c{p8H{G={bIv\d!LQNC#1~]@|%zJ'QL*;Fp0X }X4l7 9p-yE#Kg47n7v[Ti)fk80N p_m8w=(wko xNn&w@\Bur3/k/TĽ:bIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/32x32/xa.png000066400000000000000000000040131345766322700222400ustar00rootroot00000000000000PNG  IHDR szzsBIT|dtEXtSoftwarewww.inkscape.org<IDATXUkpT~sٳM2I@;@- E;U+t,(8 ^i+ae:vu\j-E,J6R;5hB l69g'盍n39{/CcL&#-Ydg2\ B>?5>>MH&ROX,Teu|>r4fW)1 !!pGsۯ|ڸDKKx<EQ IaؔNRMMMVX;E0@)eYe،OLLҡꃭP,C$p_5(ʆ6Ae0.ceY8{,"!"DQPJ|~̙3O- B_4 clff-[p9EQnJ&XhTU <J)A10`F D(ʜ18]ׅiuwtt h4.<σi4;4M8b<0c m<$I,˜9BdY&Ŏf2(ʄmJ)<σm(JB(/ c P$u]^;!(" .+hT*xEQc (0Mau]~ 8@,CE^>v۶9s J}0`0ȩki22ǁeYܡ (<[_ɡS4%.۶a,˂8p]gU*٫!I0of߯,kҬ*۶Y (ːe,#`0I8xJ)DQ$I,3{GllllEQp]# \.ϡݟi}>Ϡm۰m6JM,EdGPc eq@ـlBB/_ iWHӌRzA$J%/ d2V^O?SUU yF|_eHܝP\|GّH$~FoD" A,JB֭[?s8عW6Vd$t:=U~^?{c/Y}o>y-X웢(F B춗F6œ#kӱ|x}9?VcߜʅuҞpɧ`dk5nk`㣚7ڕcly΁@5w *VŝgE^<>М-Y.m;f;{>25 yQ^)CO,s}||DO,B2[:xNﻑ?koQԑ2jlpGZ__plr h~p쮃9?7j[Y5kgqߐWd^+ݐϩ^4+Ib58|M{>T>Rw|V͡E&/-kn^\wCɄeN]9xeʽ d'kw˦%;Z8@P׎:Wr?TM<1Y<6z"_hJ䆑G$SDO!^OoǖW[2X~sJ/:ܻm8O3:!>xN)֪紝?j uPY/@)5 0 Na&1 ]uNәCs~Jz{}}8H/EWU;?/> L>D`OLT6 RcB0[m 2)nc`@IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/sun/48x48/online.png000066400000000000000000000076151345766322700231450ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYsEEKWtEXtSoftwarewww.inkscape.org< IDAThZytEշ=yyI^6FnQlpCPGQ;(*Nӭ8?OΙ6ڢF((FA߾}K՝?^^LsON}߭W߭{oխ/0Z-^iԏh0(5n޶L9F@|k-rI[!_<##䮵UNm%I${11#^ɓǞe@:1t-J3lBi? RyUwn-Q[ k$FB̨32+ox]ɞA$v@z_EfdM9DQ% i>G@2IiAeSKlV}j=Ξ dm{z>Zy9-kx i d: iCG=[z>3p2.GU\?Sd<=~!Ր=c! $]3h (JO ~9\ƤWKAkO ,rNψ3Hϑ5t7dlaqvJ뺶&>EҵČsEQE &/Ă ;nOQ'`w~>n]U@ p] ;X3ڟQ$^[㙘.L)~.o_ E{->d[-B6ޫW^\<;+m( ɍWAL.cg2@f2tq2V ]Ҵ+$8g)h - wKkEJL Ld;JgPM L?m^?L]@N`yVJN7aߕ\ eHj@*H6:Vglz(\,䶚Şf^N lgs*taLZGVtS^72^UWeU8i{^UHdA .zD*04H` tw̺^0^\3"w <xD{ހ刄h1x`4Z(شNN ddţC$Q;^D=G x|3죏|{63VT~Y]< <' ;-xO5e74 ٭fKBipa&5x'u Q/z!@?É} S4h.>|`5&U~t>C ul4ɶs9[t3%r5Rw'Lgx~g G"{NdHd Vw?fx;xڄt-/ϛL3igu!@AB :ID{. S-YBצ:Zv-27jpS .Hm;ʷ(Z(&qr!Es-?XF@,lRPmh[6I@),+n̺5;hfcrrNZ7%_yU oPK\πw)WbcgP B:2k6$ߥ  H)C/fΕeU&՛jkY57ڶ1P\Wk!r=J;F\ ѵ揩F0Q(M J {cDi=$A0 f^H\l%[ ZݞZR;d$rꭨ$&g?`8HxdX"An* @,M86D̳v[NH*GOO{AsTv+P|n(>7/LQ@<}**hS{Bq- a: wⳏ7mv*;՝>kMgI]W ,OwWW.W9Wv q"I~ " ?@D[(S : N_&*jL<$KŽgD&N[`wRf,TLx Sw"EAǛ'Oyb$zB ēy+jKŋm,;(iCVdʼnfX,T xvf-'BT[q`9zoN3%KGcCaNQԷ [)9ɮͣ>p\ `{rzrjG{s&Lؕn\Wh=YޘhJlZ#:g$zz=K"A=+%O L<KBh&W+f 7,K,GccEk0PJ6'׼7"]o IH`=p^ÕwSGt h! sp9woudSY P'`W{ ) uo1jR>9FaDU(H /owi1LN̓P1(q=h{XtSY- {/Gm@zGI\WO= ڿU۞'Xp8umL4mUX TL=rH[`|?7?I2<IBtH.UUǻ46M+n,\djr#TU|ʘ Q+<a~` SN 1g!=$MqR[bKb_< 9?ArIܲճx(uWV9J(WnThH)ý`t[x2\Izq,i(9;f׷0 n:"S#d=r)}Jٚ,2'VJgЬBBӎrԁ8ɒjuǛ|NB(J>wD5l#.n^AWb{@ZGފImK:A^`oL+Oz#='DR6( Gā%,X K ^y(cE"āȓNF4l{k*k>7,*^4t8b^IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/16x16/chat.png000066400000000000000000000010501345766322700257340ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA; EDCO;ARŁ`B/ *b+b}f?f87{jy0xXD6DaR*JZ|xʪY>Ƥ1Y$V(@QcKO/_ x"i!HcA9N},WϟbtqL25g=w4 ޑi".tx#?\a*G7Ohkt0 u0Y\Ę`u-7R@UVs_IoI0;t޼x|(9/cxE8ZBp~iଽ`wV1b%dFq BQ9XAw_:IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/16x16/dnd.png000066400000000000000000000006541345766322700255730ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<)IDAT8NA[Gr@B¥*q X$'  $lE4 n[JNbfv͎9. >gЬBBӎrԁ8ɒjuǛ|NB(J>wD5l#.n^AWb{@ZGފImK:A^`oL+Oz#='DR6( Gā%,X K ^y(cE"āȓNF4l{k*k>7,*^4t8b^IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/16x16/not_in_roster.png000066400000000000000000000007641345766322700277140ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<qIDAT81NP߳+m-{8 J(p"*H4TH v]}C73OSp $"cYkBJ80Q1@USUEQ0ypĨje)KQ(jLӌ͍M{,..1G/6Qd[_Y h4Z@\àaG߸FD6 x 8}W/vvOg[Ga6 oj:I]ג@UUuN^@Q)[; /{NM EZz{ijDd2,Hbb"KhB D*~6(Kʲ݉#VUct{_UT5Qd Kvi51 *Q`8c;'*u' T.xx'?Z}Ȕ2'Y>0u4, 2ьpxpT8kwZ ;fl>iwZf"2'I\v;^&cxdrT5T$IZ:z?EIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/16x16/online.png000066400000000000000000000010501345766322700263010ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kA; EDCO;ARŁ`B/ *b+b}f?f87{jy0xXD6DaR*JZ|xʪY>Ƥ1Y$V(@QcKO/_ x"i!HcA9N},WϟbtqL25g=w4 ޑi".tx#?\a*G7Ohkt0 u0Y\Ę`u-7R@UVs_IoI0;t޼x|(9/cxE8ZBp~iଽ`wV1b%dFq BQ9XAw_:IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/16x16/xa.png000066400000000000000000000006541345766322700254360ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<)IDAT8NA[Gr@B¥*q X$'  $lE4 n[JNbfv͎9. >gЬBBӎrԁ8ɒjuǛ|NB(J>wD5l#.n^AWb{@ZGފImK:A^`oL+Oz#='DR6( Gā%,X K ^y(cE"āȓNF4l{k*k>7,*^4t8b^IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/000077500000000000000000000000001345766322700243075ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/away.png000066400000000000000000000014531345766322700257610ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗjQߙ&IkcEA^@D}/P|ҕk\(nj]؅[*Xm渘I3Mn54zru]DA'hJ9MԂX P %L#?k:/w 7 h^q4x?z"|UA wRo2ħ6[$ t,n(}P!zmaL|EW6r9{Tr<XX ](0EݬYSkIl=>XCm@:]WwW`ISeNWS0R_v׼}k' B1+FXG)phHXc1d#XuNJpp'OV@W]@\$9*b["0d  >'RI܆I85ѬgT62'ۂ@]E(p9%*MH5TBk_S@D8@F+UukR(!0_4'v:=FeNl7JT+QRe_G*^=>|y7-j GU><},-ƁK,Nv1h6(6_^ P4Coʄ<|/IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/chat.png000066400000000000000000000020361345766322700257350ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗOhU?3; IZ⪱!ִ ɪ衈1'/AAeF*R.BՃyz _/5-Vg&C븺՛kT}[ HA Õw/|KL|^zBQ& %+pvO?&Wٹ:1`_rN^{_!Ρ.;S9(FңP2Nm|r@AMڮp8]0j٨)#8<]Gq7ך?AZ3(&ZQ3'DU-Q<{@#N \ajFQoLԉl=RtH;uF3^ٗ?ep+u6#qXވ"Zȕe9]1< jWk N<AF\ Z/Qo6bhyWO==s>`iHADKW:>߃#b˩E%7jZOö/0UEn\:d%} /q{w, xM -)ݷM&m9@qIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/dnd.png000066400000000000000000000014531345766322700255650ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗjQߙ&IkcEA^@D}/P|ҕk\(nj]؅[*Xm渘I3Mn54zru]DA'hJ9MԂX P %L#?k:/w 7 h^q4x?z"|UA wRo2ħ6[$ t,n(}P!zmaL|EW6r9{Tr<XX ](0EݬYSkIl=>XCm@:]WwW`ISeNWS0R_v׼}k' B1+FXG)phHXc1d#XuNJpp'OV@W]@\$9*b["0d  >'RI܆I85ѬgT62'ۂ@]E(p9%*MH5TBk_S@D8@F+UukR(!0_4'v:=FeNl7JT+QRe_G*^=>|y7-j GU><},-ƁK,Nv1h6(6_^ P4Coʄ<|/IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/not_in_roster.png000066400000000000000000000017211345766322700277020ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<NIDATXŗAoEov:ՑB֑DMH p*QAUik HpS!VR@B%@%H-mic{wvîƉ'd}Yֲ[/NL 6) ~ 4EVfgN0z8xr}"Orݳ ؿoX`hhΜ#o W;̵,,,"G;jɲ Jz8|u]\2;!+!o6-. J( yc ߿j\ AJ1KKKlN); 2V&_^wwhXYYqpUOL+7>byy8%0t Ue˼Yqwl@lv@2ށdt'{i㍽O9Ie>tzn$ԆK{BI*xJ`m2Z  ;㶇$KSvE}°@3( 7^{I>FZ(XV|{ LRRɜJ>X6"fn&L}u Qlun}faq_H}xkY E״B ph`uQFHRH}KH\I?/ {1IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/offline.png000066400000000000000000000015551345766322700264450ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗn1LfЄ[酊e+T]+V5k^`!DU@%+kh,f2I&!i4r?k-NG<<0LZk~HYzRVg  ɔBD!"HT*% R{$` MX2Ƅ5Xc0P*oSkwcƚB! fp|!\]]jZy^ _}ZyةZ]xyt֠uNiE*v_ @$l7Nū$XHMnMIKȤ3\twfB1bq&$I5t,Mms3Z޵#jl'd66ҁN ܮk-7O8]ҔEѦʯcЁ7diH_f>Wp{F899̡;``bpxhܙ<4 Ng,jc}Uj:N-#*@jOn(Z#B9pŭ⫅ wƯ+I3 $&!ϭCł `akP)tu '?MH׫dյ7߾}8 z;,E` XP@ HG# `Њ@L >X'  n*IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/online.png000066400000000000000000000020361345766322700263020ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗOhU?3; IZ⪱!ִ ɪ衈1'/AAeF*R.BՃyz _/5-Vg&C븺՛kT}[ HA Õw/|KL|^zBQ& %+pvO?&Wٹ:1`_rN^{_!Ρ.;S9(FңP2Nm|r@AMڮp8]0j٨)#8<]Gq7ך?AZ3(&ZQ3'DU-Q<{@#N \ajFQoLԉl=RtH;uF3^ٗ?ep+u6#qXވ"Zȕe9]1< jWk N<AF\ Z/Qo6bhyWO==s>`iHADKW:>߃#b˩E%7jZOö/0UEn\:d%} /q{w, xM -)ݷM&m9@qIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/32x32/xa.png000066400000000000000000000014531345766322700254300ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXŗjQߙ&IkcEA^@D}/P|ҕk\(nj]؅[*Xm渘I3Mn54zru]DA'hJ9MԂX P %L#?k:/w 7 h^q4x?z"|UA wRo2ħ6[$ t,n(}P!zmaL|EW6r9{Tr<XX ](0EݬYSkIl=>XCm@:]WwW`ISeNWS0R_v׼}k' B1+FXG)phHXc1d#XuNJpp'OV@W]@\$9*b["0d  >'RI܆I85ѬgT62'ۂ@]E(p9%*MH5TBk_S@D8@F+UukR(!0_4'v:=FeNl7JT+QRe_G*^=>|y7-j GU><},-ƁK,Nv1h6(6_^ P4Coʄ<|/IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/48x48/000077500000000000000000000000001345766322700243255ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/48x48/offline.png000066400000000000000000000023461345766322700264620ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<cIDATh՚oE~ʼn#;؎% TEUŅS/%zK$"E7$H'$%Nݝᰳ&vH#̼;5 kT`r0!۱V~_n6J mn>X=Liir]K,DD@"*JT_n:Ne 5ZEyT*jwon krP,Zz3 "BTEg^d5 /y5VbdB;NZk\ׅIts{>D %<3^qZ!al67ˏqV X}}沉, udf$G_7?|I(k+`6} `|-<i}`[]Dal6c -zdYrnNt\.ן8~q.7u'W/28m'AE2MmF_/>u˲.ulv;?Pl)S>8N$sUllˉ'ohqmNoK'48I]PJ zJ0y. iW`W`qJ11V`"E s&o 8%>鼲7v +NX{wR˵JqwzJ,ÊNجEĊ8&'#` (@`@$j !j MC}p||4V* 9~q>@h8+q jJrJd`"?NJQٯZ[rV 6V-- y3ٽ3q# )qTۯ}G֦M&}*㗷y4_ Y`(K}yPX/ #Z>\ @]H@X$Q0 rF$hƫ!)) Z2yȼFM>F̭'Wkl@R㌞p5j_n SgE܎4n1:E)}bz~>ЙoN4Ek^q|/to/ ;$IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/facebook/48x48/online.png000066400000000000000000000027611345766322700263250ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<nIDAThՙkE?3{r46Ъ RAOA|A|.V?"*H*>YXJ M^bkKs|$ges=|3DtknZ嶑Kh zϝ2 |eO״ m#GwW8R(JX+ƂZb e;>6V5}x; Vc؞9Z108)^p0bu{M no.vcp轢Zlxp%܂j P<$ojj%F);Ԯ Ϻ.z. e߰nVo#])Rp9ۮ56S+ Aؼzx8_5U3iOCRjkV0bsd{ž216QC *d{1`cỲBhb6KM$Ty_6K&ߩ1&>=ˆ^xIMcU?0;k2ȴF> =ZG,uHCUDBPO4Z2 q]JvK J)p㓤h f,6QU!np""!]^/,.4nnRXZw`c0ӿOPo-TFNhbн1VP.@ܩ³Ţ]cG?YѬaXODlB.WN3O EKXO/ȵq $$aM_89n*s[m{b٫gg&FON4N1nn"j?8yG% ` _/M!%s1``Q:a 6nƸ*qD`C"/QrDt Wbl&s@UiQgdv7wszG~' 6zS5-DfR@YuLɄ.?O^ᕻUaG{Ⱦ6F^ B;0ֶU߱2!D1 z"Li]v#9EYa!H[ʥ1{zF%J9|rLgwUdkU ߆"GuzNr %\ʎ+h~*Ȑ_=tKlf=x|8pp Owo_ ^LrK۷&Οol @kY&O}^=9V79AȬ-wLf 61fy1pcgKE} *\rn̵|D~Q\ @m%IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/16x16/chat.png000066400000000000000000000015211345766322700260240ustar00rootroot00000000000000PNG  IHDRabKGDtIME  8IDAT8u]hu#`KӮt2dJM7l2UcTPLQ/BG]jڌiQ[uA銙&Yڡ<9Ԩ[2 Ƕ| |"3CCO͋Z#~?lg-aYh) :-WJeQ>fRZ?*,S3T}EgCE.B*}%%T*o|q6w 7_pd۶v龝c3]FkEWG7PݼLWMM~g}ؕcXX 7@0}Meu6<.`ʯ ~;޽wP*iT3  1H_@G8x0~a8+G i$DT 'Lݷ?ذX퉖Opk2 Fղe*q"yεopwﭴ/]%jUdQ y` ~VQ${(ĀPj )?5;(! /s&e"v[9~Vl7T$d "t] я`B8`\rX_ȍf_ߘk_:}@YOZD܀>@ujܣaHIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/16x16/dnd.png000066400000000000000000000014411345766322700256530ustar00rootroot00000000000000PNG  IHDRabKGDtIME aDIDAT8uMhW{7$"1`iKk5]YtQu!P b vS(MhRj .lqiI(1~=]H"5]缜s(o=ƹM; ~]^`fkӭ'`ruBkLX*XCD֭J}#3ZTJkGj o>|8;<0@M{Cxg”WB\%jnrDоOqb".r+mfC]1=+YOѨȹ%Xxg9 cN (wa?\HY\1IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/16x16/invisible.png000066400000000000000000000014511345766322700270730ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uQhu?_tmr S½J\dEDE"IE>/Qzn5AEJ11kvи9=Bl:3UM$io\fFZE\ > D$~ á|hԹ0"2P(DK>]76xѿ~]wܹ Rg+ssw} w*0o}?n K]L5ܑCOꟈň bKft>dQt. DF.}x띋1q$KyO25$MWA-\䱮\twc2 |`$s^!?0qV۵X!y;$m0q8`)v& p\lѹ^.l|EѡՙɳY&?ZJU'PY5U?^v&L&h wq&\B:R:uƧ3/{2:h^E6yy#K3Gۆ/寧2A0!w߿v6-o>9@ZGO?&ϻSxX'JVEߺU*VvXt.ꈢحjٍp-X0&q|z=N /6؈3+mz4!D>G:]\\j~8Co I$c4[[Z _b6Hd X[?h{CBÒsqvzi3e~A|7~a5j6IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/16x16/offline.png000066400000000000000000000014371345766322700265350ustar00rootroot00000000000000PNG  IHDRabKGDtIME  8IDAT8KHTqƿ{;GkNh$n%E#څVF BPM tQeB"ќqL] LC\3w@Yw~ps8B־)qҗ###v:a'@ZZriN Z(0J.V?aX4Z b"j<[10"L7||}?&x^j 1!PZZiYAQ_Fkjj  @ƱB#xӃXD۪$Q,$Ql$%&b ## Y@D$>7ܫvYUUhCCcBcC=,Ihn5NYƻleЉ޾^&=ddf#+dx''b]ݰeNYQb!x)GU99 vƕ,0Y);~K/IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/16x16/online.png000066400000000000000000000014421345766322700263730ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKa~_7NaLQ nf (B*ȜEn$AD a**VЕA0BKܿ}[X9<c ʕBaT26fLq.,ל VE"K-pֿ⺔JJy灀T|a8L`~Hy5!Y m+i]:JJ{UGǎԇ[kչ) ƚ_}[^|6kO lm>nj=Ʃy"4 x;j׻U4h|_RzCeH  HbIm|/8q!GW|~w:5tL׮ ƥt.d)Ak0FXUiQgdv7wszG~' 6zS5-DfR@YuLɄ.?O^ᕻUaG{Ⱦ6F^ B;0ֶU߱2!D1 z"Li]v#9EYa!H[ʥ1{zF%J9|rLgwUdkU ߆"GuzNr %\ʎ+h~*Ȑ_=tKlf=x|8pp Owo_ ^LrK۷&Οol @kY&O}^=9V79AȬ-wLf 61fy1pcgKE} *\rn̵|D~Q\ @m%IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/000077500000000000000000000000001345766322700243745ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/away.png000066400000000000000000000037171345766322700260530ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  >qIDATXkl\3{ v؎cāTPbB *%jLTTA*A|UQi?@"K6>4$$1)GuO;sa81>_w9s۹ڭe}Y|'gGV궆6V_w|֏;ہƷˢ`<دϬ"5ֈᄇM;.fX{ˊ9$[-֪f7^ J@,n<߿}ghKl&V)^Dde*:|1q#p sݯ>2C["UUG/DycH> ֢N~ʩ;RS'/P𑅗_ͩȫ{ZMORwc ߽!ZP?FHVyx0%IqNFR'KTÕW.)%}vȢFN(ES[Ŧ?$[pq#+Q\ gz%ܷGYC&qY|sVH|ۥ9@jFB T9*^~G ]v._^D+x ޿Kw]HU@@ɅD)d^r_ =)#}|r51츃Õ5U.њQ"AlmBBI$6Be5lkZ:jus;rf$ے\q Rgo&yGO6XzdQ g$qÝD*Zܻ`rkLv- Ok%]LI%2V~bXN4{ݺ%!|'\6$p+As GzC4,\ozH'sAe`4XcfQG+ o} oAn J2db;`~ 6s}BWduD`i!Z ǻ>鿬M(5<%VN'ր1 0] Y%q.n )P%`GټUJ3a/BYV=;ypd L N"dSFuöB lNd9W/πx̻8ւx~b׾?9u n}/1T#P в.:[!1bI$-_͡ >GzQ gڴz﷯ZRsSx{p63"H}fxױbb|DVJW]؉btco[ Ԣ6~1 N|Pg2(+t@G+hxtn b }]VMB9vA kdz_C&9Jϑƌqf}nMsC|~ّ{`e̛ۍ_և)O#ASX/$*qҕ &h_VO$$5'fp!D*gdM҉zKq!-y ? ŊK:1`@*NmuY:8zEf|%e܌b@u)5f/rXwZ/Z;֗myK)J^j/37-[5 pd{yC_׬ ň?&Kf6cBN95TZuC(%Rkp܄m2LsUQTl"EDtVun^N,w'e$N#:k3 ~f2lD)l&L2YԱIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/chat.png000066400000000000000000000041561345766322700260270ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  >IDATX{pow&BȒlP T"2tpA@0Zqb"2u*VTjӤzZAAlT4d $Jnr?v7y\s9~*JJZc. ` r%=&m͚5EnTjv</p\'u+Wl8_>硇LUTksCȑ#h,jFkm9r䰽|]ޙj^ַ֩*ݏ=r_Whgh<^?Zzݪ'{C+VIwoef0Baϱ>OBv,ѩ ݳPCɤ)(eEAkpT(y<&~{ZktkwQ/$`!`6v͜9xo|L!R ^JرUv_ HXf|g-_1|WceMDwa4A(Dx#:|Lz @axoh}w!1)qJ~}a>'yP )ƀ AIɦMU# (cfYDž[Ad>ŒՒ5l  ټ`\mmpa,)Z'6/K-x(rqpFF1zdub(Y4pİA'!0qDP-t$Y%`-z.KG"nFx'ÌfL~vj'5|bs xI0+!o iij%'%`St:5kn'w/`0*s"kxe wU/ISPdI~5aDؑľ؃)fo]]wO$r|9{ⱓ'_:tK$gZbڟ+_(/] +1Y]]B\iOBښ!\P8v3p-"g&X`da /z ul̞tg@%SJm0e/7hvF/Eܛױ݂Cmύ1ɾ}= v R6- <ظ@s ,R3\'ݹǎPR.<80j(GF"%B+Ekk+{zm[գG99kWzb=wh=W Qj uTRZFz{b^ U J8NsYY5}:n5qKvJhI^1$*"*)^!x7fH#ynOBJ:KDF|cii }ݻ+ƝoԴ8s ӡdDGCӟlr PNSI (?tyIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/dnd.png000066400000000000000000000041041345766322700256460ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME B~IDATX}l?m/o m]"R 4J"3ز,cddK,sZʖ`*(q** (X}ϽsK_s{=;sI)1fptXS]R~־qm|cSMuks"<4U9AgA c.dR hRqg )uu 0it+5SWup_.DIT\b:H>^}5:SJ-3f/YΞ=92N JO=˩> vkc^Yre8^yuzF)Iʶ]RpW{l^q''rFp<Eh!Q}dfeƑ}l0[#P6o~]QLx4Jf2!|8M/AK2Ň{=Mpd2J%u֑s'O*6x%-HۋƎ5cCA =/XECѼg|Nŕ2D'[77'_ oq!78` `d?"xꇨo|g[j1d8Dx5^ 0HQn͸':+:}-pVVqMŕR@PV,^Qdye?^7IJ ^|{}ez;j,lY+*~? ʃ9xU'm:-tA[10X/4o4mAaG*| x4U Iʓ ed@ *t 6vKji!]%/_RJ6R{bOQ[j!C@'x6Iygx#P ;0@W*?L}D܅g+`-z;63뛐X B5?KaVmIlkAk(kxƬ 1s,(_8w7mBDXt0xwcc3K0"n4ıL#@96~nlۮx~k|̱l{1`]Ĵ*teb8^ߜWf僠w q+r)glIKK1uyt[?XeA>9o{+g=Ʊ ёo.e%| d4,_&MZf|؁jy}oXk)Q*Q'!^1:) YX17_xOGƜ#L RNcrcp|nc@BЉBK˙֕FZ+::V_4SxOzt$QE "_ՅxPI挌 dmU#PRyg8k F<Ԃi٫DZX?Cfw6fMpF hn׽9elZ|y8  ڂWW z2Ā>ƎBIߺUY =wbr:H7B̝5󝝴^DSoUTVVY@<χ{uJKf-@7YR_ɔjƬBčh `m@-TP(CLq4*JkjD6BwEW] Z&'m2w_g$Z/HDHc~fVWۋ|!92jy9;hukXOS\Y\/ "jkӣ==VIk}LHTNp|*)OTAk}O~cݐS^zК0ne̊yNe&IPOBR)wc|B >fuR_F1k1`4?L vԌ$}bw=jO_M'L0YwWXIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/invisible.png000066400000000000000000000040031345766322700270630ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATX[lTxf|al`57* NIT%uP,TVMz!D}j6K#cQѦr5q&~{albL2YhZGwS*/U D\wg۶Ƭ8;}:y;QJeVG)0F)P(/V߿h1 .cJRsJW\?d|ڮ"J[rr efVJo{5ɆkcfmLYnQQxŽ#2ӧȄ]geU۸DyQ/%ߘ7ڕ[T^hw7'sԂJ yW]7RAڲQ =reCuΟ;W9wؓ~ LIT}k.[RAC軘J}J#Qyݜx]yއ;ӔjZ8z7tS>K I4ׁ$@WE(=/Ѳ#.C#N2ƔRnS+ڗ{ !^/D@ IO/WsʀҖGRs WVަwY,^\' 9U(5(51֯76ׅDv8>=Lo?&? ܧ0kCH^V)pFJK%mGg!9uH)0eQ?{CA!#زn"EEX V>l,TZE)#K?CcpIjԽa}TV.p 튺Cɔ:+ b)E({A)3ZQ%"=[C /GiJ?K~d2ܭӟBԼ=<Qyyr<ڻtēQtѓ;"2@2W/b7ig/fCZz.spK} d7&yKVA!ٓ>}$hn̞tvHsK='my{nFQQOmmBEA/-3ں0Z[:מ 'c;SUe[R8\>rnrt`Yl 6B|mQt P(?/Zk~c}u|t옫PeeJ qKza0$ Ky+E]Dgw\nk: Ŗ $ң~[xB p fmLY(77K}BZC4X y\ף \6rMyޙ3RFsR ޲yV";yNzгsPjkL)1o)ھZ)dYVce"(LMb=Toi6EWYc?r?e)M3J!O8wk}N J)7ID`FL\φ1*|5)D$ 6>t4Ň#KIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/not_in_roster.png000066400000000000000000000040701345766322700277670ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME $<ʬIDATXO\?;c3 ~H&*rQ"Wj7U]zE+5.MU5jUvUUڸmd0c33 03ܹ.Pӝ{4}]GGggc-0Pׇ8(_AX}8)(4Ɂ鱴֦ 0B===Z̞wvhY[岳 ޾w]]o(^FkҊp8Lv5o+Z.?!G#wKhkk[OcW2}+w0ښO|5xx<յ$JtYﶜ; eU,GFF$5_kE,./On\E]sZ<{,Eʎܔ2z49@&G֖*|R)M 5}_ Vbt1C|~.o#d-cnn{_Rhj7sg#ty^y*.dm}%24bϷUpweLU{Ȳ; kOrʊ>Z)(ZqrtX4J㱣 q Wt&s"^@{ڰsoԄñhTkW$IXaܴ!Bq}9BWbڧ tT2@.WH$pt޾TVF+RiF|R !4MMMLLMc6U!Jf%J$ ܸqo19=KG{++LL8-`v~)JJ4g4d B ^V@ѩ3 Rmr LGLtRJRc1ĢuhY[]%W.z+ܙ\zS˜Bh0-9܀$eS},$ N4| Ms$^8KE| (%NoqRF6v"*Foiv BJ BNhM_}e_cZmwgsxTbS4<&/`blb ۶!ԍ Noق Kx@Gc_ǂctΤ +La&iPvҙ,c3xbZКxe%%\r\Xbf.Aram!Rw%%)$u5$RQL%0DGW N Sw_077R @kxBTB>IԯR=WdGgg' mChH.tq#~Zk') TW 8RH-.򥽎ohH'Ϸ4F"308̩MR',.-S*pl6$nP(He0z>S"RWe d2+kH׷ʋW])G!nH  bJl%%eb յ53\q^@ |7\ XBj]gK!跴kM@D+}8R*ƧmJjՋ⽑;?bGS* J)2Bi|8G}}7ׁ nݺ!Ǒ(iY65vU?ʮӛu8lz]jWȭ3 -g/B π]`۱~j`v("X7pB|[~sovMdDW)JXAIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/offline.png000066400000000000000000000041611345766322700265260ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME .IDATXW{PT{^vPeXV|Ԋ 4GeLOL4:hgLG&Z-PҎն؊kA`wQ^˲uN`aȺ&?zf~s=s;;%fs:KxAwDmӱ!(Ojjk, eyY``$ytpәg@c\nnuҶ5",+* NU֘f100CӍm^$If->~Z\VL Tv=oCMy$4QC{zzPUu x׾hNOO(NxՅ%E>$ 1o5=gyԩo?,smtG<^N8 gI KN<^7}|>B!(n՚NW'knn&e奰p\hjj<}vwzJKĘ_{g6R  NĚcryl6;AH׃/o~ Y՞Ue饺ƛ\h}?kοl\f ml&Y M Ec qXh1, ܸqQ1ƈcGAVq=Ax N;*ʷ!%%$)US@MӠ F|ðۓQVVt܇?-`x plٳ3{w1& `2 JØר(bMx232%1!YVT>fϋ֙^ĈF:Ob;QA~[8YuBD bժz.NSjꌌYub Ȳ([ p%L&p?Ml2xHsCՔђ>LAO+=ƨNMR\˧ؒR010Ɛy#Z.\Dަ"$d V[JY yK劺ƛ*?*++uddd!Pׯw7&'Ȁ]e HbeJz`J/^9S]66I0cf)1}: pB "g!`:Qgn!Ior/~.X-<080߼ᄏz!)AGYХɲsR@}}dMlBEQaX!)֭]=_} Lz! eK@)`UӠ;`jmmUn§2ݻwْ%K^ْ2+-F 8s2rP},&̱fAm8xwp8QVZ 3?f׍/Ϸ䋚-;488*'3f"!!P?D̙|36kxdy`@gXq^2::U{{\Q#RQYUAA\FnY Z8tbB8 Y؀ 磯]كյHgLфY䓳z=Ya6B'z=HI?9' DQȟҢ:^JiّьllvJAx=?69hz{z|)ҏ]QK2PWuّ݇:m̖f/%֭!I 5hM9p\dKaRRR~ÏW\IeeI=oݏp_Cag%!y劕t#!MG^xo͎4=%ٶ5q:.jQ ;v1?~Q^o.Z8(euzrssV["iִ֦ Z[[UBF5 Rptl}DMxMp.}? B= c m#IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/online.png000066400000000000000000000037221345766322700263720ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME .tIDATXYpT3FI Z[`SSf11 OER)W<dH"1*Cb+fb3  I$h{0#,İDO>}N_ &I)wBk=o%!V)?bR^nZֹ걆:1 MԶ' Uʤ`PBz q1I Qz" (0 *aVXV77I9z(u[[q* vw.|MWgc#}A0\5jT^ic==4CGS_8 Zuy ??_Na<7+TDuS_[+fΝLZ9eZ{*adڵZ[b/؇*MJr,8mءzkOCx pwDm`.̀m^0httQM|oz `"1}0Z]BY9x/bT!Ͼ;c_ɸz´ŋ GJdL3BL蟠`4m·rjwikMC_-ӺD̕Taa}Bڸ_"kC'w&Lڣ?C?WH_23`Q2xyԩ>'|Y+m&6Ut1kY*wo0keMF1]Õ:YImVeVP67{b޼p8a?6;j]Pwp0]3#rraFd%)/Tpp&v1`bϷHB16k6Sޥ{_gc.0+/yd4\R+{0_TCc: ǎvNr3QYnS?eo*-5sɂ F#y=gWKg.9%1m`:φ| j|IDɳg/.׺Sck^]mQr8 dۈg#pB [[_G3"ԟ?/%#*aRjeaF;WP撒5?^`@w FCGGΜ :d)g?|o&'7WF&etD}>j7̉1's.$RsUf ڱkJ陙yEEE>ߏ !'B+Ekk+t)szeYoM0_GlJT)č?Z D,r+ކu/+S[ڂ#QxJR~!W m?!ĕn D)3HJ('9ƜQsh8J|N̷@ @;ĠagDW 3^үjи߿~2]?լvCuIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/32x32/xa.png000066400000000000000000000037171345766322700255220ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  >qIDATXkl\3{ v؎cāTPbB *%jLTTA*A|UQi?@"K6>4$$1)GuO;sa81>_w9s۹ڭe}Y|'gGV궆6V_w|֏;ہƷˢ`<دϬ"5ֈᄇM;.fX{ˊ9$[-֪f7^ J@,n<߿}ghKl&V)^Dde*:|1q#p sݯ>2C["UUG/DycH> ֢N~ʩ;RS'/P𑅗_ͩȫ{ZMORwc ߽!ZP?FHVyx0%IqNFR'KTÕW.)%}vȢFN(ES[Ŧ?$[pq#+Q\ gz%ܷGYC&qY|sVH|ۥ9@jFB T9*^~G ]v._^D+x ޿Kw]HU@@ɅD)d^r_ =)#}|r51츃Õ5U.њQ"AlmBBI$6Be5lkZ:jus;rf$ے\q Rgo&yGO6XzdQ g$qÝD*Zܻ`rkLv- Ok%]LI%2V~bXN4{ݺ%!|'\6$p+As GzC4,\ozH'sAe`4XcfQG+ o} oAn J2db;`~ 6s}BWduD`i!Z ǻ>鿬M(5<%VN'ր1 0] Y%q.n )P%`GټUJ3a/BYV=;ypd L N"dSFuöB lNd9W/πx̻8ւx~b׾?9u n}/1T#P в.:[!1bI$-_͡ >GzQ gڴz﷯ZRsSx{p63"H}fxױbb|DVJW]؉btco[ Ԣ6~1 N|Pg2(+t@G+hxtn b }]VMB9vA kdz_C&9Jϑƌqf}nMsC|~ّ{`e̛ۍ_և)O#ASX/$*qҕ &h_VO$$5'fp!D*gdM҉zKq!-y ? ŊK:1`@*NmuY:8zEf|%e܌b@u)5f/rXwZ/Z;֗myK)J^j/37-[5 pd{yC_׬ ň?&Kf6cBN95TZuC(%Rkp܄m2LsUQTl"EDtVun^N,w'e$N#:k3 ~f2lD)l&L2YԱIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/48x48/000077500000000000000000000000001345766322700244125ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/48x48/offline.png000066400000000000000000000073321345766322700265470ustar00rootroot00000000000000PNG  IHDR00WbKGDtIME $ IA|IDAThYitוjV# vg>0Ĝ{B$1^$x0C vIc1B[Uo~ti - F{^t{{Eal q~C13-YXNN}K:=E#;sVEc,\ ێ۱p|a# UAfV >cC)!iE@ XC⁸~o E,N(ӠLeC{ۭ\Rѹ/'ql̄EaɲE15? ֪*-}| ?srMi+]n]|<3MF_F=X4]՛xFr5m8hqa^  5r߾}]xi KZ7gl9'' N9ǎ;sG}7E|IidݝH.c{)W\yŴ#UN-i̙.Q 4Me[ODQ`Y/B(G5ԟ-\2܌tߚO,@+[6+r !c.m wAdZ[o3 +V,Gzz:‘TEE((0L Qϱ$ ^.з~XbeKX2:DAΫu {dAzoO?-Ŕ(%%Sbobi(,((y`4MåKh8uPy!I2x s<AĎǂWWUU[yS|IK٫W\)E@H5231끇eY, 8=ˆi0 q'z Iri!j@ǎʊg7h)qԙCnjbOϼ)+ԅߙ3Eh۾8 ذLyL49O_@y0  Inر;++wV== : Kv,] P(LϽUU]KچXL{Ц l zg}^+CupE,._ MS{ !qZC(0~;zii &ЧN{[+RePe?~\Fnn.qR+=$A׵}}Kl"E<2__]א`i(7fΚ K@AATU0LzF* >H;h+))q4{rsr\n o`31ga ֭_/,,]7n?ϱEq-۶,F;`y7Miӧ˪BUUe7n H|-8~$TU'ͯ; PU 'ko%m5M,*LDqn4fgк! c0MG4m񛦳g nmnia{8 /9Pu &ND(e!}I~(-/]q4BP5 >+P0L3@P<~ׂc YlYGbgO 8>>q4\S]yYylZ*Im^bf@vV&^ڴZ> ۋ{%˲< Dp7{Ίx7B$~3ήIJ.GalS_& n3wy?a(C I7Nahbݲ8tp'Q۲OZ^^bo۶miBiMfhX)%/G>frHzUlz7*Inޒr9@]4 gUuۓ$~ ෩Y|ɟ;;;pI.Ȳ˗0j(hrζ~ݚbbW-FX߈ [EQB`Y_sWu˲^l<7 Ϝ =r+FuxNI}CFSS J\ Mz2,)aԝjWxB4E8 4ű?~~ [ |GXn58KrB0X . ˢ)ڎ0XN7663zͤ2˲`X.\SJ <ގ ^q<,Dvxw@Qy! C›I`9j*Q---Mh$I<A[{;| dfdBd̳,3&,~ލ}NCt(-ys^kA{[;}قayyGS\ܲnuP2բ{/7]n32p[a!~!E(8G ?=9E[Fz& ħ>رc475,`=lݺմ  @e /{w2Md`Eӽ&hFnVbDس{c[7& En- ~y9%߃KRP8l8:::gO !(SQuC3(]h7-'+WǎD,QIsI\Fl qP`EfF6L§ FA*m(L_:TEŹf8qaB7t xnYBfC0؅:KrIvRac&7Gvɹy0 vU+h]4W>i$eI2? 8?jO7e}?D۳{_daa;62`v@\ӧMGAFR@v‘Л*מ9eʲqRR8YY$I믽a&ɹFzJ=bE9 9qVz!!W`4Mi;`YGo*tBS. 'THҺ]ȑ#y۴q`h=--.vkw_\BR콈>ԖأOgDoÏIVֹn@7Hn!vqCi7#){A Tнm`ۄC IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/gadu-gadu/48x48/online.png000066400000000000000000000066761345766322700264230ustar00rootroot00000000000000PNG  IHDR00WbKGDtIME $ IA `IDATh{tՕ?~Hr\!!d-QEqv)-:>c1k::VDL y'q_~7Wcsܳ~>}~0Lmlq[\9\vm ?~NNx3`8lPjJܕ75+*0 [BRȗBUVR`8láT!L, !%[[a3ӯB4 B*n۫9o=p0)N@)l)q~sz 7;LJ|!WʶN_n7=ӿk]qlwߍC_/Qj5೤W+je q|&c[nA6VΜѣjCRZIYp57+;'ԑ}m!*DhaqOލ1~>۹.Mp/tÏaȂWRS9p_3FV>Q7aB#H݌7}VG"JѣFĈPT ._ [D`k|#-P^"JE?Y9~ q+)>yFֈiLgE2_{و)ShK˦%J/ ~IQRv@I9]t,B BAJ^^a )嵁i\TBAȁ={ !:/^!t?SXU;ϼFo ]R$wBDL Vx~݌&uqjm*+ #S]nӖRenu)M~?㡭!DiߵJWeEET.TS=*qẼ˨!l4Y&N$6/nqp UqTsT>UI~mH"B!ze`tnoV:p٬}ק$"2ذ?=15&W%wD+&"hͫ赣n7qˢYF0XlEEru0zM%nz/6#Lޛ\T7(;f֔憸bb:¥?+Dő#uu/ܩSߊ+Ȕ5 qT$J2'+-Dc(Đ lΌ]kա0aBkD57.m+s.w0sRNVVsb† b&CgeF;E"H,g)=$ YqPUU@=n{vN 믗~)ShjqN13ζYLD."r!%|VVf9LӞ?kR$^c1>?zŖ5/^ke>y=j>0G{wPPTtKkTk+K%F T8q&m!L^C\3c0 t#tKN 2\]"<8ľ`Axڥ >!N/@DKLwob4NVY.MĨ. >Q׿=#^ynzШv*(^MC{LK7~ Zvݘ!1:ߕkG ӟNbj}p{|ظ&{ u>X,^:@PQ#YB;Rxun~s`cUgѵY'-5ڶSt1٧]*)PMb-$0;?`XO N̰k)rnCwT?6]Ƙ ipkRucb.Bt<4IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/16x16/chat.png000066400000000000000000000016551345766322700247520ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-OIDAT8}]le?kKV6ɠl :u3N'ӘFH81CD@4-F:"sA`h߯}=#D;y+O<7Av,릌~L) x`q@Peb&'s^j Vig0Ch^Ua- HN=7 >3pAo[_aa/ŻJm GcYX0yy=ZcgT\ΤJB)Ynt'Rs*ra+n&ԋ54M<3nܜ#CІFM`܆r=L;yZB|tvBxɒ3dZKH$>D\VE\o4f/)dD i3IQ X- TccIrC<w2F*ue3  ZWՀ1!n]'2b1&HaO Q@^B;vcێ70ޭ϶Cs%uUo dHũ5x>H)q _nx<\IgTE+ Ô8wq Vo T ,ba!@`9N.yu;} ]Y-t0Bǃ*jƧԣH{x6rΝR=|`oz>T ڮyQaPts{WV@F#hN*)).cL,x[οP_SBʥTO_m[B>=豭V28)R.7}3wvkAIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/16x16/dnd.png000066400000000000000000000016501345766322700245730ustar00rootroot00000000000000PNG  IHDRabKGDtIME '8JIDAT8u]lU9_kYWڭuj')c,lD$ Eb­ VD1$W&HF"C,3΀huk~o7}r`} <`61WOk?b}oٟz+c_މd/0˧0~/N= ?r]4$v6ƒҐ_=;gMf RJ(%)oo[La^O8: x:4M:wxǢE`}m1*†L]<5zҌzDi Rdr)oۏ*j#‡ie`ȕ33+*ğtg3]}^[%EIc7W K8HR+c3?9'(RҴm0#^I['TݨC*YSqWpn `W F6u@.B}~K8 5Λ4O\z@O^dPpr/ )UC#>&e ыh 07 ,O׃o8eCC@3$s BWೇS)XD?f_0՛_8K9TG&$luɹBlp7*30xg[mWC+fq1u)k`5WJ#ڸ3e*o ;JAL]ֈƿfD^5uPlЁ8ۺI#H Y'xOں ٛo^a&}uz2}2cK#2 =s_܏a8<-}M~-xQmlO+l!7/mp]v )"$mX[]+xٵQ̆^ l[ҏ?#sؑ| ZMX:1~kkܝYe6 vJn|ٿ;R$JL^V8~,˒3NfZ3R){Q:ˆĞoZAmR LX LU0{o^S02!m'1o9Ҥ4i2 M@@" EH__/ ]۫DR+42,O\nZg8ctR|8;=9;7B} pIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/16x16/offline.png000066400000000000000000000016551345766322700254550ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-OIDAT8}MLU}OXuZU+ZS 1&"Ƥ;jfbF766q;M4p eb ]hM!03u =aE: q0FC$R7|>54VFl3kw tidz5804AV.{4UQ!{~ho|00ѨD<b܅o %Mo]Y0u3Dt$JJ&4T*aHRI<v|Ttez}~B!X^^lw6hnD<Im[ZIMO:wޥP܍<%~BۏiMTff\aiTlol; ߆h({9mms7k-/; ΃@;ً@;,oF zKpuHC)dh^> zEC@?v\iK>׆sO'67ڲz.Ȟ ?n5~~&eYMQS #T*#(W:^3NRum>NZX ""M$srr%""tsʗj:,QfM| Tqjr5 *\.wp`VhLH$&˶t+m,޺%+4̽[6e hlnpc!M5!CIۿ`yΉbq{>oİZ9'㺬Tf[3g>+PQJUttntk_񇭠ȂMeIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/16x16/online.png000066400000000000000000000016611345766322700253140ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-SIDAT8}_L[umiGFA+ (6; M"s!hbL=L,Ƹ8/dce 1 Cn0(+3I9O6}!;L$tNƌQHC|j'7܏_^[=Tg6_5+< `P5JO]>l1uvx $y 5G8yQ@r(w|rԊŷ`J4k(hY{v,NefyW@_c#뺸6}Źs#ff,HJ*kCrp  j4(v:AzR wż`1ahX<ڲ7A /@ߕ;zϔX_. ^|Sr8ȬA`ױq__(XoQXka͎NW&V|v{?Y#4$ k\鍞:b!IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/16x16/xa.png000066400000000000000000000016001345766322700244310ustar00rootroot00000000000000PNG  IHDRabKGDtIME (-"IDAT8mSMhe}%YMLF6m)&Z0('Aڛ=y,"M)%ReY +RڤtnݤMy;+J7o!y5e蔵q7PZaf03Z"N VEOS>nV]^33(( N{x}{;z"׃4V C]I䀔"ZDy|wz y9]IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/32x32/000077500000000000000000000000001345766322700233125ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/32x32/away.png000066400000000000000000000041271345766322700247650ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME IDATXilT7o{3x7xaߗ$`AIMB5_Z)_JR*$JDi)%M,6ccccf<{O?6TʇJћw9`_GP|,爷׾hم"oj꥕NVgKKh}FKWn'a>UtnM!z=EGWòAeZynoҀp]IzE:FV-]<Ca'I;&g.~r,.6m u;rԳCS>ꆷg4mH7Ů]D`Z4+g،q@.< ƃ gu>f-,t|86BkuMM!5^xWhܶ۸{%"+A…dIsp !Ov";-^VLY6EEujɢnnV0ŗr' fB)> _"joK&D4'=3ūzIHjV-P܌-v u_96,a1H<&Q˃L^D+| $ojNarn]Bњܿ1˃ܧ'j*N񨡀*:~$bYoԛ+oY-(3r4MD ^[:P H X{W/ǒNݷ ܘ:JAW~1K/0i7CH2.k@,ڡ·D"m";lg9J;_`?Sf=ƿǸ2{tk^)*e4Iz&Dԏ'JVZ(` "gɤ#+oaO8%O7"ȡ;`KRd`~? p_9{*%W~}c%=\Y^-ː JӨϤ qɭBvpyhIkCPuk֕  o/cȄ ZH"3 f.F.ret,4 4e\ B±8 )r)T?c v3L讆2sc7 $Mxskj<Jt xcJvwR +p 0c"ذXX lH^8GQ(0B:y4Oi6+_x$$ATr Ν8sA9Ȳz<{9FUp"d.:0R|rqTU{ 4_:#iY.Px%\W6<^˜gHXRKZƦ-%,ږW6}ss={}\]7x P9M8?KѶoAL`e !ss9j;~a㵗 LGUH>xvX1-\Ut!L_Bwp{p@GVH󳣷F|=c>jJS47נOH d{n W{~Ge+\fT1M(\aZL<IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/32x32/chat.png000066400000000000000000000045371345766322700247500ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  IDATX͕klw;޵6xmlc;!g e@ % "*MZEKM)HA!*QH 0`y8q0qb066އ{o?^Vjw=?6 9'5KM$Iw_|ZB6 ` x@6 V1Wh6K+WV3=D$i?)~׮]o[5-vQ}TgI~EFBccVNV#tw/dwCYmoXTVqQOߪپ;97%H:XPJq{\Rxz]C_}R`r(Yk/YMc4k6fVφaEWTM̝3 QZR&2ɟx~RyU8GBYJz"+\3J 8ylXi: Xo{2ӊgچr_c0:H8!;ήlɣE cR JMȲ~DRWL)tCfNq Ot~  󖺾nR"$f5S;iZZ ?]NpJbQ|՟ )g̚EZ:D^DudJ˹z6^*84'"f/fQ^@+F۰X,x(*AR 7g*.\:}S &]OR]Q߂q[sю0e WW^aW;qfu*iZsx@wD(heF[l;>Rah+,{Լ ƀt&O@0R&G* pDM8m^$I­.lm-%ؾ=ә$hx 80`v#7#,Њ 洄pZ=wÎ,ҫ jG}}X: ^4EMER\pmzo;Co?0{7_hS({TժSP s < W.;Gqq> )e@y=}hmː2 ԭ(>+Ԧ8l@88m&O;#ϲ,+'dw_gV+lכ'TaϵۅS|4/?&X8 CgDDvc!) q8uM0F`B&* s_<=6'n%1OZc>|DpMkJ%x;K#^)H $h! *o{`C*is,Vm>#DMb0 ,@Qf!هH{ etp$. U T<|  9sM k% QӺ#Ѝ䧑pV)pܧZ`<—T WcGTaťzܜC0`-)ѝ;^|ɬJ쬙r[,bf:1+ E&0$eW{Hs3#1QԅKPPsQKL\']ـуlZWk>rk*3=#Ca\h﹦) XEDA~%3/YUkm|*:#s/ 7}U8P*L%.A64S$]lo06g;-uoNcWlCr弍tFnL,r䉃SG`nT7R#`m~V#)Ή:褀sD^Ȝ)8w{ z5˭y f92-}-cIg;Y'x#zB rhU;cГT$2FC^KmQ_^N!쯮fY %`  m"ۀ3'ȳΆm u$wܬ ^M(W g7YTg{/V-x|a7!S~lolnu:»`w{.YqD<=bonNU?cVsOV2ƅ= cqc_t #{;IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/32x32/dnd.png000066400000000000000000000044471345766322700245760ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME IDATXWilT[fޛ͞cd$ ФtID%JU*ZIUI5$)J\ 4@ Swq߼cEzFG7|{7unھ>SP6i)gYHjc W^;jWY}Je2zR|LtL_x<1SǮG*@ QV\ylE:dLd gmǾyշ7zm}EY3 l/uS"ɡ^#c[\yA2/Wc31OY%yÙv%:]ڢrvπVO_>T{7 -򲲶w>G$(V:WA16QU*l  Y1Vu5Ύԩq~V=uЎOiAnH{Ͽ9v\3]nxs.Pl L8 gFEEA`E(-[әtm!j| ~ l 76nt/^Dlb`*;0\T ms~[YNADH'4ޛPlz΄9<L]*#cROWUz)6Xn6R n W,iFpJ(-OMM?<@VdJgX"(+7cv[YKEb͙[k%&Lmpԛ#t# s؎7=/~o H# 9PM A,LD-ѳ88 [o*9jW(dؓI,NuC^%Z&P:^wfa_x&2jYXt˂>W [nH#(>+0qV* G9ۙ͗L Fĉ##sYĠ$Qm ԟev-7N-(l'tGLDu0#NGs [0!3v\ g;>Gg% k7> c\̈́#+:JZoZg[F0C臝fɆEۦP%B*T$#N>Nva}prYT 2è~/gAHUйՎG81]1al7 2 ,\P~]:.BnA}GD/{[TlɊ.m ËߎAʼnMpnhR?T1eM}btwZv%y *.= P\f= bw _ A 1U+u l;O 8?;quK؝$g0RD?%AYްJjM,!V;:$V> @V>t] };ӧ6 .qn^:5yYAլ;(Ƨ#X];J&Ovp zSSkaMaG㑜@8aZ,2'h6"٨5ۆ|8_xb}=nffs3؞=ir[u-dIX DeD`~;#& L~k"S&VqojPsρcz T& ,KqXEpX3&C,Z|iNu|>^Mr_oIЬƆTZ8 Mc0,+ 8ƗΖ0Q(1GE-(0cE'VL#7x _ˢԴTtx֧ؖuᶉL6~N*+eAFnoO%CE@0Wh:\aq܅I´XyKTܞjFKz|3$qfY,&mI_{_Rzl 7kOFk3etFmIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/32x32/not_in_roster.png000066400000000000000000000042641345766322700267120ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME VIDATXVo\G͜=={eĎVbMR9ȪDX7qAK+UB  $x7(-ITQShKpRv8k{w^};۵SH|37,b>:kߚIg4[??!  +Jgg}CL{Gt^?ѨzFf퉿|Q{ / >F blS~0s/7&IpQW͛7dۥK_g/e6U"u^4:1Onzi_}D4 spQ,Q__/mdr|s<ˠۆыĠ{s(R}>I^P 188J]>?k|ĉjS;1`xd)Y_ qh\o[FÙl*VWrDZ[[ù\sB!,..o[[[_jjjR$s|ࡃ {Ş"o>_cZ&y9~g,j5~ yy455'&n[ x^d2aߋMMʦz[&?6 zdE}__M2D6E&Z -_ߝ-F(c ^ض)c!0L T=J$b1JEj> :ol^%pCG:NT*r4MeEo$bnn}cd* 1n/c ? iTu]$ ?@mf++h3<Y'ُD,N ]g |$˨"_K 巫 lb& %9zz ZMϝ:'ʩ^gn9ڿ#l9(j5J0~ښn\bV`bb^skHQ۱8Vj"1`^'T\U,ȇ{P"X;F#|uTŏOMƅ[;Ap ƿnį#---j8ɲ`.\xqb'!t{~78E<[m43.s/r1PbvԁAO}cY?"%wtvZŅwW=zv`Qrq9ϟ|}bQ>8rHS}$⧂۱:68 8hڠ{Nb\0@)(Jf_[[6q{g}7ZF@ߝxݶ- s uN/}ܻ1L=^ǁa(x<|r/z(J_$3`+\4 * j7u\,|=U60- xZR<#\6w}\H;r P~ oeeFsCJcaYq3GVsX*@xlRadK%Is?V]L,rY'N6 %( ׯ}-H*t]$ *kPj^Y泳3%rHv!ua&/ò,(OdX_fe/j5 Lr`;wWVVRb%|P[㛅sBa/*uMt&-ex&.&bhRF6wKSSS9czF:NlۮiZff]]CA Ir?k>bOQUdX[V*iZgw-+`)[g#Vb[Y6ݤ@L",JcUT"!J!')B[V- B0إ?^ݽ{.~A!*uY=5mUU2&bĂu ݻ7M:k\.f E_m8TU(w랏/\*%_5D#;w|tWZZvv6,W_ 675zw'G{囷c Fq|bmK\۶EǻuL|ƷP/ur!tcт_-+3K@ !&;{߿g[w};wm? `0,;&@i.CUT$@ g`o|kߔ9)}Y9ƈ|vtM Ng /^XZZ[9!3+YO+i˗Hl;nBJdge\?&\^G٬%7J B x^饗Vyv#\0xsqDIIB5<7c FmaP03kwe¥CTRZZC|p'hwYOB$٤LӐ9 lL=3@z{{By2YV#$)l,^Ol#fU@]*ŲASUaTWD~Ǝ71U@D't鲥SLuH)!IAH ׄ?{ދh؉Pq8cp(+׮w=h 櫻*v5.Cc]{ڵ3fsss]iip%D`.8n@ j|/Fh3!}Xgw%,+`Vb'=>Ox[R\휳BM\L"+15#HMNDi>kӌ0H{{x`VV8`9).9sLu/@Ԧ7 S1"D 7DD`!bDPs\O <obtCig8NXV mö-ض ˶`fjksuv-9 )! B؈YTMʕ+R%TE;!=%j"IIa)Pt0}}2!*C!%Ixtt vLJ\6LVc#lF"OYW #`EYSSR@4$| m;:#o7E͛7AVbq~6=]/go{\Ͽn>uу1MM!%,  M}־^ɹ!/Ϟ VII ݆) ]FQņ?>s Mu@p8Rp=1UN(R,IzR_,[!CJ;JN)iijqgD,\PJWt]ObiƌTYf #$E¡,SVok( DPUAu; II70+;U&Vx}~t3'f)B0pv`{k{sCW;@30 M>LQkʜ9s~ӭG=^"h$v#a0iy |9|Chb0|kR'ag]IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/32x32/online.png000066400000000000000000000043401345766322700253050ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME $lIDATXVilT[fޛy3/،=6bCXCBJJ4Qj(RO%jTiլjV )%8es1[&xxl (R^}|9>wyh[6P{c >ȮSw~(DUO-+7(]HǗ|6д+=+&EK{KR7(J*n ?rd'D,Aܽ, ʂoó[j=n$kP *w*+~:cvFLAÚE[k~򳐒'ƭ0 h|G`yJ,de ϛ#>:D,_vNX@l|E\wO-mqG <^t ztS"NC3N>Xپ K,Fkl$|Z3ihV?ܲ9փ"=me_m'fc@;bL8VR>Sի#=@;HQ [%5]w#<Xqe !–]MT\`"r#u œgmfu[yȓtMC i_cUf%Pr\M&BGET/4,t.߼0mѾm(LРwǶ} )RI ,Xg<fb k3 JFђ4GȰeهaQ-rtI&lAsc<#;E F , a@bwF7 }n.D nj%Gށxp[Yg;V,,rqaǡ1ͽXJqL;"lۂ "A('8<0Y~dd xǚgƅlTc C~KD{ ~R4-֠[FM5'Sb[vſ`70.eCِ6qL8wS Z {x<]DP(lQenѿ*&`X!0Ǵ9&@po;~}"z$̈fčsn:X ?8g2MnƂӸH'̑tg;9hb֖obO\YRQAp{s-Z(%?GJoLf 6:sH抧BN7qd3 /.yVb'`0`p.D+FJQ6r=<\R7ۿuE# >j B|ݢ.dVmۼwgm{tqXd H7mkYj816O"z9_8nOK$ʏšA`~uu{ﶿbOWv ??~bt8V ubzlsbg9ԧPY䇖u>eJ8LwbcDLdcF?d.W4pwù'!gl.iE&wGLG:z[dmNIUyj1eOxVg5A q rhhivDL^َm2^ ;[,yGx,:kþkԸ=1XkǛ"w{!ͯ"7^y:zK:yk]o fgclrw$'2r+xARu hJ`F`X aBGfIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/32x32/xa.png000066400000000000000000000041101345766322700244240ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME $lIDATXV[l93;;ݝ5^_11 16(DDD PR*UFҗH}Z)KK(HP))NqD)1f׬/x;3zݵ VZRk| >اtI!%Wg;NRϔq!LզqPd&W)U={f1]H$1vϟw?-Q@54ǻ]Uxj Cݹo_ig-WWyCoτeyYIhm[@@d@DSl7Sz]Eq?&pv}w4=իu}Ix7(74|yϞ[ TV;O{;|čY^WOz3J@yEQTbgK]ux]]4L89<{wOX, rQ}{ؕ+(a.''!q66._Γ@QGLڵ2D`mn.] "(^-۶Y|`rl 2:8OY` ۆ_יJ 녯q@2 ӠxLӰa˖u%mQ2Uen,~Kiq'pn3[a3[`G&1u1*źM,:W4@m cŃ%_MuĦ?oz0t#2l7LN.3LQ2㜎R꺠TYjDffL$hcg's!i{=b; nR`]@WƂųg3U6y@>Ŀ;(NIyq.;lk z++**,JͶmfƉxpX:-wS"&Ec#.g[oYp`0z#p0, W.t-|\r|jag2sTh}v!*8?T^ "XL&ʉWT :1r.8(ՅKT+E) Aw>4 ŝ1"0ϻ_+%!aLG9Itac8(Fy[-ۆ(;KLUCCoS(TaG" OC6Ca)7= 8 ^_a!~p^n:&K/3m۶ ۆm=6679::x  `%PK|;Q02eW^zPH"[t紒t Ψ1-!P5X}Y,GIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/48x48/000077500000000000000000000000001345766322700233305ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/icq/48x48/offline.png000066400000000000000000000103121345766322700254550ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<GIDAThY{pTU{>&YwF!0̂ rXAA qtkfݵ@\Մt,ļ_ݤ;H*!VV%9ws}'DuᇼLt]Ƴ?d|XUB.(fEE9|,\0R C$I.;mssssh]qu?E"eYXYYI")**Ⲳ(P__ǏTUK{o޼ I 8zh_\ti@݋0 ?sƕ+WR À,&1##c=0ڸq" `۶mY-aO&_>t4550(--54UUSx< l0iZD"D"4 >}:222Xa!''' oZ!I_~f͢YpHr8Ax:333G(J0 3zzzxbgDQLKHH+,?,uƌo l>s:{:Fu]wBeDEE|>}:Vk$IBE40!ƲIII۷o7'&&R qGY߾ (`f-Mt]NWWW~y٢Gy?*~N8FEBQiUUva*.]j*C__nܸ]۷sw^P?ü 0/v~ׯڴiӣ ;//('ϝ;x^LӇnwϡCbveLLLDWWנP(e1w\oa ! M8W^Y1{֭cZZZ kݘ9s&xOp8UUU#"졂ؒ hooGZZٳgy͚5񝝝믿XV$$$ 0 77d0p8 e[,ttt@UU9>>>g۶m|ww74 $a…,!`ugL?c\kk+'(v̾}P(D+0LHJJt(B<8+&&.Kuݼe$I#rŝD"HJJbYM!e٧px$Ihlliؽ{7ǁ`00uTB ``4a0( }rrrȔ)S-`2%+2̘UUȠ^] O<ӱ~ȲT MӐ666C#/j4Mk֬=М0*( *++#  :cZ!@0DKK 6n܈HOO;w.֦ `F| Yv-5K ::/SNɲ;m/߼ys9stO0 ܏%숞dC}}>| n}ӦMCKK˨L&A3gs@uuuݨAyݻwv;n2nPUw6n 5!q d&d9_Bww*.-V1 (l60 j|G(>TUU1ڼ Mff:^x1]TTF|>aahڸ# L܈;@Uރ{FNFxreLVyffy|>ܸqgΜ ܼyWMOO?s]AH`Yvi,Ybbڠ.;B׽Ί5jp8`X0 G4g0ܢ$2$I뵕mxyyypxGuuuŨAS<ϧ2330 h6p(|&zkx<σ(~:65˲X,ذazj\r'N\\9p-30˗VXA)>477Cqk1%\9u EEE-yeY,kn7l6|AXVѣG?)((\^^?Xrw|b y&DQ<$$$쇪@HҸ7{nߧ`ҤI 躎^"##s1(Zp)2{ٲeF__߄`ҤIK±cM?8!qEx:(^rOB!|> CɠBHzTTTh4rǃ&7+00@QAHn-;( ߯E1)Sz;Yna*hkfĕ+WsN_2kE`#dُf7^}2B8|ׯ_|I6-- ^܉3<ݳg$BȘkEnرcxga0 Yqj9@\WEBBfGLL XŞ={jii)7sLtuuuX,p{;C Fl6߿'O͛ 9hgZQ]] UUٳgS,ۉx{FTUU.]ӄtuu^&&&(//_/// 6xΛfaƌe?:uT}˖-FUM677#11DGG :9Î;8;w@rr2RRRpF&MD""a>ݰap8biphkk ޸qÐBvQC}7n-˸ipY??,IiY֔5kXfΜ Y,nߌAQgԴ2332 {I Vk$  Sn_ /0nB̚5 <_Eq>y$%%aΝ`08r wFyQg''' ,PE:::jEQ_\S(PEEE5ӧsT][Ng(//0L[iiYUQO ,TTT::Ư"DQ?νox6S֖W4mWNU.a1FD3𻪪Ξ=OIIA]݈hV}4Md( nlwaj~~?kךzzz$EAtt4꫐i(e>#--M0o"IMl64nlGmm-EQ$2hH$t! 5&&@nʕ+:M( F" PIII4q`:|>Jn8{lP?PE `4zuMƿ(`2|>> 'NHHBeeBH[GGDŽ*N t:$a~]w`SN␖k׮ABfD"om6۸ 6իG_~饗5kxGYYz뭐$IN.ƠQ 668vɀ$Ik].ݡ~c9d&!..Nu]3CmʊVXAy<B!Płhx<  *ozsq-Mƹ{t6krb^O-̅dX4TFyd}cE4ݸ&l{.71 |h 2c_}RpHd+ez|'t|4a0t!-!E׈3:aZ_7ؔ45 K hsO)A`T^BTujs||LN}4f,z QwR *b3%ڥ9t!Jbzo̥8M(~!M$aq"& ws,.[bnaJӟD74K͔,ZIuX]S&Eu?aUsPHo>wVo$(R >6kJ`6K*N^wB$nt&_H+M#A,o=sNXͥ9CV} VgedܿЧD>:ھ@w;Ykf>bEHׁ\ Xdn q\X Ϝ j*o<14Q[pqO 6AX,siQ%b#f6EYR0f.+Yd$=̥!.,&ŠLDAU1(b KUOd/1f[N I0P595(E6ɲhPǍE`/uCPb#U-$J $A$T-HX2;^(((M}$dN0CC%4m^_uЌ!hŪ$cJzjL ~cRD@備~_"l/%'~'!QѵO7rNq@!)s&%.rs; ᣦȐFX]Y 򃛷_bSn"Vg!≯*̹&GNVc[Gt5FE"i(Di q8k`X-wO弿3_lhR4ߑt>U{u}Ǩ˚m3R-=ZK5>:3͛ ͎YL+H]Sd7xTC4+Q-@hV][)lm,h%̚JfW?ߏKٳ Q"/ϥ{]0dZޑU|V;\~>˾zJ1~!")R.],M3$$l2)z,c좑W=Nk>p/mMק'$#9lVX>}NN#·+7?0 ɤc2b:"b8gAQъ b$^hQ/I R13и{{EWu,犻r::b5$Jb =@b17oӉ uRsDQbZwǭ޻CҘ:O+SM|pS^<^pȩ]B|MO#$1/(G5r65 S R̵حCgu$5ʼ/. Τ^ R<-t3O 3ZSb y^]i%VS:RU*A36/3; @040?Ar}Œ'''Ȥ mf ieU\(>.qV2}HdcPڞ]}LWIxpoFM:c!O=IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/16x16/chat.png000066400000000000000000000015421345766322700247460ustar00rootroot00000000000000PNG  IHDRabKGDtIME QIDAT8UMlTU;o>N_j)(ta"cA*TXą 2ngTn]e!dI hL4a%-*g:owuA:guO9691c;nx153M ήtSc K,_RMeW';<k-k7\XXk?xIkCkrI=h)љr,.]h :x`\MO37ӣOtn5$gF^[&a+-k-t,ơ3魢s5J\KpmʍDSS+My㵗5@S`cݟ~gjr#ԃ:+++\x?KǀcO:ߛ: /.ƽ\o닗VեëߜKo:84FUͦi*]ru]7]}P(͟/J(4bEW|k3. rk-GK}ZZ!pY?LEFCɽ-}H FU$#oT:V;'Т^P>6sdhwV898n߫1ؓ|qj#tGC"88A>9! tzqW?̑"8Kp&%Gz3z/JyU*y&i6CDT+x7:>wXқ[Xk|32_~#m r\IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/16x16/dnd.png000066400000000000000000000015311345766322700245720ustar00rootroot00000000000000PNG  IHDRabKGDtIME |IDAT8UMh\ek2ә4ɄDcChR"V(5dUPvS2k*2 bX4A,4VZskvFͤ?ә;;.bY9/{#GHgu&_}y0.cc ~/dR4[>LM\1| AkzM&3Q&D>a UÇbڴzJ%:!bY^iїOb!g?o5e Fk:k`/!"ٹygvn}/fK5 .]ηPJד^@O!߈EpEY|.{ŀDW)[tB:((fW:rbm!J1 h4B.lhTʄ#^;Ow+?sro''ay@[Ʊ%-QĽ/|6BPwox}Ԍ~8 tı] $ӿQڶ}إ%P|cQūgjػG<3׽ ڢؕ\ZWwaWV0). "k]^tz(A( g*=* !G[TbZCګW)+qqNn$s^>|llvm_08[ Onq'3GN9wD6t= y`mqqhIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/16x16/not_in_roster.png000066400000000000000000000014141345766322700267110ustar00rootroot00000000000000PNG  IHDRabKGDtIME  cIDAT8e_k\En6m4Wb)l[#ՂVAP^X(H9 ji(BJwmƶ"&{v9.ySԍYn] aG<|w c/>k8ge9߯z>ٳeu rTuBP5l>$Ι7Oq3Z {4MF*!xA>[{DѨcBV9GP4FDk 1Fy uo9'~w3$\Y=>Lbҫ^*|<+eQ0hxWs;eYb%7^*53VӊIb|ɲLDu;(0Ɛe1ƇG5yȓպAyrZM()(jVVRK*>iDtQXk)0ag'I^vgY"Qޓ˿t©&[[[,,,L5Qyv wA袳U`ľ6ՈP XEaXߔ]; 2 8{{ 򗱎yrbn{c6G8qA؛p1;k8ZUO4]CVI*5IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/16x16/offline.png000066400000000000000000000013331345766322700254470ustar00rootroot00000000000000PNG  IHDRabKGDtIME Q}IDAT8eSMOSA=s;{ RV7ưpabte!qW>$~!.WH˳ODEHڹ.лsϹd芑"wSD+p o[ `an^KKb{{J뗶6~~1rx|`0)Q($Xq6NHB?Fr[-N\zY8F:٨u8өYZz \ɝW@t$AJI$mnm6o=Jஸ4X9"l`mu(MnV/0H8`6 !E!o<*܊W8"" j͜5 36 Znϔw% H0lPhj+|?J9i0̈8{BNkeg-|C92; F(\'̀5 CwԓG;S< ({|dKQߔ͖8̧A*jOѽ@33/TTV:œS4v[UUI[2 ҈*Udځc;h6[Rm е8\갧@ѸZ.՟=e%IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/16x16/online.png000066400000000000000000000014161345766322700253130ustar00rootroot00000000000000PNG  IHDRabKGDtIME QIDAT8eSMhTWνw޼&ˀԍ. RCJf,YvY .Eܥ;BiJZ1ƍANZ!?{L|pwww>BT3Vg[FF`Toܹ_7Kq81RjHJi4[wS̔sh,8@}^G܌( s n s9 փi M6 (ahn'gWD4GʬA$P0 3l)0 YA;MW7`yϟ bP1'@h{Y}hRb?=^ nAsddEEew89\D,K@nW@<t`S)V$nn9 v&qCcQt4I9DeQ%0M4ѪB*h4({P} \8FU<5(8=asgȫ/d:>| 30S%?5f*KO.7,!*6@Z`3>ˠN4$_I^./oYoSS,0k@"/.IpeI$EŻvOOKpc0ۻno?*/<4[!IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/32x32/000077500000000000000000000000001345766322700233135ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/32x32/away.png000066400000000000000000000026211345766322700247630ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_23IDATXŖˏTEz=Lpb\q u{֍Wٹ0хqAQ" ( 3q==i11$>|lfG{[ ̮>OZja9Ȅw֎'!*>xw֎=qRN0iՈϯ@l4r pY4ujۡ@@sP; Ą˪; )" 3׾h,{vZ3]zts nH -̯zR\ÅA9L:V E0n[[D}2震T& ztzw2n}k@B$[ү[(Z7BHbISuj@#ˆـ d*rg":htXa^GZAAe5`cv;vY%h 1t+![`7a_[.H 4˳.@rL6rΫ%ZXk\~!!`-/oycQPlNPn; Wև2qR萄z7vZ8ovSڸvicaM-4멍ONk-5Jm ,^>K|v@UlluAV׀aGqcJh{էU)T;.٥a6n|]:o܃\vk_bozU6?t v~=]h^w#ay~.H/<1MzF.0)6bzݵ1(wY+`=!)Z=ZA`#2PB&^$hUW`E8VZ=Lӛ!Zc4{VƵ˵|d/z3d+m%)i/|bɍo2&IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/32x32/chat.png000066400000000000000000000034521345766322700247440ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_2IDATXW[lGfvvc8ķ!6JiI hZ5 * /~P Q6n4Im4EU'CHKe3{g1#voJCCb:g_y}X,49~GK6ڬfzW2v)%}R-Y exʝCÅYw^eч=*d4oD,*Q~\69"<7?ų\8x###W(@vԚh@Ŋmh~}_5{14M0i#{};:4^>TĠH0cAn޸)0_u렔ىS šww::6p~kCn6 /TU:{_Ol 9800 wiH) |'.z,ĕ[esEWS0 qvm8g`5%@)ՑX\ VtR۴݁3WvZl=0 9NJ)(%affg0* 7vy! k>Ք/s^xXA1tNRE ݥ4,S@*M^(bZ>&`CO@uzw0:}Mkq#H)͙~ءhf0: `\?cXVʼn4z3OCZmW`0Bp-b3Yd,g  F<)ش>"MJ硔U\igaN&g @)؁pM[5`(*fɓIgtoPyYpE<ފ?ku01o^pPcHJ> ^BKW>K%^@[ZZ|PK*:7H`prɅ!1S'@m`vjse,|h"ljFK@7X(f*z"l@{vm6 N"83vxƂY1|7|X,jƻMWgoMxaD`||T&̤)?I9@;_9p'[JNgc{F^%FDy" 8bBLC*@])kXoH C))g BG$?jqyRN/7yЎx۴ҭ?F-s')`Tq#zja,& 9y"vF1I彚XWͥ@ Ez^IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/32x32/dnd.png000066400000000000000000000033361345766322700245730ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 9PeIDATXW[l\W]8дNDN\FUӄʊ@F"P >/ EBQ  _ UjQ81"mM?gVе;?Ui;=pݞ'޷ʴk񓟽PIc?v4a~yN;od]l pm U݈u"ÜP&m#;ef֜"ڱLOspf`Qps$?hc' @fna,"~0FG&O ,,i:2 <9 ,5L`SI?2m bW7=P-`n x쑇~i~\*7Xi6K|r V.- U Ƙ\փ6Aєws 3! *'~'BYs`H0&"5pL@X@["{=]#ж]K˭-ѐx~//3ԙ'<ށE~w݋B,@xczFx!HzěHGZFHDD@u"ڇg|uײsHP> }s'~&ݱB̉Dz LOA9Q"jf.:vBe\Dd^ ('rOƱNTj>m}r,:6nm Z.&,ݎc#L*5?$f>:b9۱ !0{*It mL\M rx,8BB_15XQfb4RZkW)-ЋB6FLSNjA"ZKc3:FcυW;,a_!g:DYr^^4"#(L6/RyCY {h?H/pڵc?zXD~۾R*Z"jA({WC>(Fv `qH ~B/EС\wxgyeDy}y Ju &v?&9 c|ahy։%q7I 1t=8MJ)d,r[;'^bEp6\hi@tĔ=M~9?2yFy"l/kt?Au8R_)lBYjlZΟH݄<5XP`y`'jbG|zfcï#mIT(<=]7ݲ{{9~!?TrJ=Haeby3` E,_b7oΉ1J`pue= wgo -VXHW6bg=(ocp~;` •,^PJs@njd5?puUG8[, ' /{ (Vo5gRtS:)@ SmtNO46vܶj2T>IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/32x32/not_in_roster.png000066400000000000000000000031061345766322700267050ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME %CsIDATXWmo~Ν^Bx)m) `^BB?RHUARժB`xIL^;3;3s0ٗOi{9395hѣGv/mw:5]\s=p!0cy1 x/Uſ 803痹J~E82DaXpjmt՗_sJ)fv?5Le ! @UĒ㵚/0D, "B Rq2p0wV$d5`f@Lza r1̹" $){J\Ϲ'ޫ㸛Rzr/ET7jb;{BgiXɀ0\,]F' r.mnf֋wٶOZ {6{Xz`cc}'x6CxN%ЎV0==]SD#hݟp[s~XET`7׌MM`euV "Da8.^++XY]銙@d}7 %,r1yw+D}_APᣅͧ}^3p$?||-CEĘP/οf{Ǒo=i88?rUF$BM`)4$ W*{Fg fr hpqj Ў*b\hXa$ l_Cg}7;NVǵUz4% G!Ib2q @lms}hk!A!Iŀ$̣e(RG } Rf[ fHu"\zpY;{Q jZ'$ ~`W*3PjWf$q RދEG#B!I n СDBX) P$1PRKv$IUF~[o?rN}y[Պ&''i¹mnnf3aO'K_^>ߓ-cuoϣwZX][?p KXX_OMG;RWEç^]IH5h1HlrmhN4 =wyFߏHi+IDpfy= ]0 "QvJWR>b[ѫkk^g1!ŋE|..,T&w,9{ H kqZR*`_ nłݮ2@h@fev7@R!+"#A雦K^k]K8p@3F%G7oo@nq2Qιs85[yȚ?0:w*ȃIN^$^8:jgIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/32x32/offline.png000066400000000000000000000031071345766322700254440ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_2IDATXV;o\ι]T$*Ma `)G,ƐriT8m( %]$\HȊ,Zܽ{3礸w4`pwfsf\M[qb‹`O¯,c7oD<{b Hy=RQN۲3CP#cbg&r|"3O8QK1=6H`ل*1AZ^{:'IQ` *%@==;:}-|m@DÏ|_xUNW|ޟgl%`w{c^'ei ҟ ?MwMh^rZ -D14KgElDk& aN#@(=FĹ҂ ̄8UEGuVE,&"Z L 3&V.08 Wd$IU $x6֝ @&B$Q'D>sBa.soNHI7MHDH$z |XkkY2;>zVEʪ $~kׄn4|民AۭD[o (-q,KZ$u}\rB-z0*ɪZdZTk!úlIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/irc/32x32/online.png000066400000000000000000000030751345766322700253120ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME *_2IDATXWKٝ٧{!m9"\!AL…)("R^8eOL"E(CR"@K$RHhGxXB^zUC?fggT鿾U=y^'N,VNZ_{GI05H<~pq.i6FZ)?vaNTgvl@c17pX ]9ә3 m`XRn8$&<.FrܗKCG$Nam'*@ydYOb<PWO+"ԍxXZZЮ `q}A@"@3/oy }$)?Ѝ,Qw.Ɂ , RK }PB:#kf. 09 Ih"E>2RfVg^Rl#!HV'" n,vBMY|1t9ro\XhXh "| 1o_aXJzE ("-S~/e'7Xc߸"(m^TXkч)Å7މW/8O{wt["lRll}v +$JrnWdGNZDA9^1,r| +'\cEpi=\G! ._bL zQ@L~?u p*@Dp˾i|GW:/މD4 -[oTkSxkȩV}%vS8 xVzWrG`ᵕ3/Eg?adhDUEmWh!uDD0> T3pF6+`jQ 2 5.̀3C&1 m2YrwmqG6v~ XK݁;&鉍chG` pziF ' \Ll9̷Xs"bMY5 ]+H:G,k ZC`A`uԖEk|kNJ/-a??mnKK}ʅ 2X8I l=\* ^yNBQc_oWc܊4[kX?ǰFȴsXMCaݵN&Uk :L&J}P<)6 _-dBSbc P>@*mm4&Tt(yz]IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/000077500000000000000000000000001345766322700227215ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/16x16/000077500000000000000000000000001345766322700235065ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/16x16/away.png000066400000000000000000000020321345766322700251520ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME  c)&tEXtCommentCreated with GIMPWuIDAT8EMLe]XvgiQAP4h6$hS5c6Ӧ1jlmC5XAmt(,,,33\Wĸ4f2+RB@&|`!gw7b/xq* BYFc;k"BܢpmtRn- kr=;M 7bh}G`f)r:ǝNJs#HYvK{Wڧʮ=Gv躮jqqqqZr{LKbtZg=Oգ3o0aг-k@W#r4?蝵SC@!5 ~ַUҬK'W+[?w0%4 P@!# 6OH ꤮mVf<U(JhZNH#(*_-Nn )Ud7VR},pieds6k2%rbkBh(PJ :@ Tx<Щ@DbIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/16x16/chat.png000066400000000000000000000016431345766322700251370ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 5#tEXtCommentCreated with GIMPWIDAT8U=lGK --lA Ep +`0?B:Hď`@ jLL  HBKm)w?Yg{]ciHRPT~N}J*`jzQ=&jyZgBy*`6Hufui,TiL޵֪.*8]#iIy 6tQja6-5lȀe~uȄ24xgbZVod}:|c (R$PA$n)+YŒŞToDڽ<[d9N qm\2[\œji7)׼U/ž[VLCѝwO>V  D)7.XQd%EϧWfڒ;=ӃÅqL1 #B56/ֺw46ԕ?{\"#(?w`M#gef8KErRAzsE$RȎ)LN(pKf+sJP9?SkG4pxm5/|I&\5pGo)%t-V#~34^ g[UYRdPodӷF8g{xTbsMYE%4JZƊ3leg`PV+d͓3=^weēuܐIafԢYlt1ߋw<-&^jۮ;n~vh w2KQTV1H>0 z>II%K<1kuYCZM~fwJE Ɣq 4"PP& iycMq))}mWzǞ(?kˋvҘU@$PQVV(|v?r`n7D†'{86=P񇢢zjL cG̔jJ\N<=fSFaw}V)^{ =5jld2q8:b& g\2XN;謏M r|>Z0_MͲfX.&.TTN luDYtq)J\$ 佩N%[\vl̳N.6jg msR3yA>/+ ѕD]|TA~tEY)uj,Ug]l`9d"ܽ y}(L~y|0R_g;_Bui^* $:;;{~sRCӴgcccO?ObvvfffboR1ŀy &1 CjJ/VWW N`aa.gAxFӴj^E ƒH$rl⣣_雕J۟,6M(tZ&FoX]-$LLLL&ojv`0cHo6 RiwC.ld2H$$@XY^^4ccDG\sG~QU建|K?r÷c=qxx*!#mύ AӼ,˪4|CQW@,Ͽqh#i!1G)xJ)1JiZOOOwJ]/*zi(v?*B;Bb ~aYuJ)GD@D1_w4M{uԶ8祔nwX,^B\GĨ}OHFK)c%J)"Jv0w)<ni$ DRJRDL F-YJZZ(0R>vgR:RE,k#bBBR}D[[[\]4mZ) C<I4t]#0yϲ0119G8{fT*}q.Ya=n'Hi3Yu៌FfXLKSSS+gggVnef.s4AtM,cH0:y1cs˲4s, x4!333u(TP(|b{uF0"Rjn>!)LJ)U.w]b[0"VfYVO`04 @DubN9FIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/16x16/online.png000066400000000000000000000014561345766322700255060ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 4;0%tEXtCommentCreated with GIMPWIDAT8MOLAxy0di9c.˲Hٸm١q 'N/a : uZ0au]zTx@rs>슏 PxsqTӮ "ZxLFΤ)%W!Vݴ`̂;Ljdj")1nyZ#V_*IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/16x16/xa.png000066400000000000000000000017511345766322700246300ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME 44;8;tEXtCommentCreated with GIMPWDIDAT8MKlTU@ϝ_3v %JvӰ@1*vą!A,J܈ Ĉ0 JuQͼ߽ٜ܇rP;;i//N:hBJmf&d) JpOW3.d. J ˑz'wmg%Ñ<[*,;KeuptB":DGB&<ǗP7F?1-aJlⱱ^>5>ow2/p[%{u&Ϗbjt~-ե5R>(Lr6=e 9aRҴasf{Ɏ $^;T6xmtD i^:3qM&,̬s[ؔ hcq7q,U *XWcm,Bu#[-;.⑚I SlӐv!>B&N9)<'vR=q'F   pyn3[s{Z`kvi< S~j@D vf_ W&ӣeםw7jQhEF F߉E8dK۬^/[XÆ(ӥ]LaWkŽWedfm%WXV;yET66w\c6+b`ɥǺjτǨ<6 i>;?%? J&M`͚5Y}us rJ)Rz$ &!*%Q߰^ <Uu6/|lj ~Y7rSo[qj/[EKWTUUM1RhBm۶{LZGTA"|_\0)Nv_CvX`E.~-uuubCky@+94)OH$o^剭[& TG |,&S)X9۞8e~sTy*f}/['+++,_|խ(/+-@))VJ1}Zwgmj^LSXyh2J!aZA)JAƅ~z^:X;-S&WT PJ5 9pR",Zr%{{~pvHgTϩ40o^ 27'|04G,;f͚U slO#2 >g{*++ ?IRRH..p=L_K+Ep]W_!,Bzj '>Ϭhe{D|*tzcq']ԺJyR)%T$iǩ+J˪.a띾G&]h{^1~aA]IƅK LJ [#Zs0 -P7˦!{p=FmlLRZo+!JJ! eiؽ t?++]rth$?n/As2C4$t َ)4Fh8CZK\ߘh Nnӳ~/ftQZR@pR`T[080|)7ߞ5R 6ΰP+ĩZ`&zhCn#f1!!`hOglޗ,x퐕X8͙_ZL)oHO:rkYVH+%FA01O)%8~/j"9nmI>1d>r͗rxXcfPJɳ D7l[&e B9~-: :;m:ݬYLH]V!J|&lٕTTNk RJ48Nwy^}l_K+ (s|['cibS$wn̮͆uW{SWQL߄b捩:7+XUgWUM<C8OTdxlJT||jKqq)3g%drmx79RjV7&IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/32x32/chat.png000066400000000000000000000045071345766322700251350ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 52PCOtEXtCommentCreated with GIMPWIDATXÕkl߼360\LpIKMKCIMChj*m*UQWRRmwRU$EMM@@067cga6Jϗ}ΉO ⨈V"1|(EMB}[o56jPW$hʀ~q &P]@~@=6{GV5*ykN(gƨ^s/o'E }`1TzUlo`}3M #&1gBg2XRZm.#.Z OzWe}Vȁ5Ye*Kn%n"p VXSAPsrLˑ(Qυ KЌ|TY!H jVLTr Trac"+~zKo؛YKڇ3/\{Я;:q dEޮXx+Σ7݌#d+n/!H 7ߵcG7ùta M|T6y; w=ozB}UOHKa;s0.+j%dө_pnVU0`چ s>(,OX}5Փ/~}6{_F~%#njt(A7=WZx.`VK&̕jn1B֘rԲVgmZc;>VmKsCa0=}S>~/'}ܺ= b!jf][e*6Lki\] fAJnJAF R8j3k=Gu;Ѩ9}j+#UKI;-3Ufi6쪊59HU¢M-Mܨ*>y;zaaTn3o\w>(K9 GIC7FtGP JJsҬxWu),LJUJI\GJUQ[-5(6CZ4BV+СjTiu|rqL"6fx('i@"S*NAaWtW%Eʼn_?/73ƕbRJd9鬣9c؀Mkj OIIWN oό64bPxw~GTҫOZ UGTQmV q񮟧y0mڅuiùm^{uDWǸ+3ΞuqcnPflz+F 4jWllժFL{kuxR'r[Y7FmڷGO3=sp?n+f5j% 8 `ʘ hQ/6WhY"YۨZPʈs~&FG9}7>5卹iyI-ԕ󸸴juZHL韰p:.6'Hu@#}zp?~ˏ )s4K Gv;5jP%a[l6U,WJ3tO=C7<\hX`6إ&Y+e,b)4 H4S{2)dXl%FZ(˻iȈ!E7sfȗ'EIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/32x32/dnd.png000066400000000000000000000043001345766322700247520ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5/3EtEXtCommentCreated with GIMPWIDATXÍi]}9.s=gkec>6Mn4jLk ̽_C_Q)~Rj=umqvyE6A&e#a>8nz܄|5벴 x(NA0):KqMn)nP$ԮM9Ю`xޠݎ l,OpĐgl=6)e$QW|CLI6r9-cݨA\Bzi|Lk ~yie'ku^[>l>2q_N_.f?aQ}ZB-,pA Ƴwlަ[ٵ}d䞠VovG/ ?sVyi2#Y3UU~qW\|+?mr嚤VԪZ-jݵyq;ϸ]6cCIr& G<.jo]_0Kθ\Qըդ&4Uv]T=kTBTL_6,Ujȯ,V>'ZV?WZMR)Nd-D-DivuZgEH=cQ}Kh,XpjU:=}z>5%Tj5R\3찳,HwǼk-B4i՟*cOac)IKqE4q6OcD2rAkOhK.Qs'#DV=Y윽~af+2)β6њzsɒo~SiJd+s/ܱCR°YCyBtV{];m)aJJUA|^T,;(+DA D1IJUa^p/M"h՟y g}GS¸ƥ,$//!M6'nLA "~/LgyqQ u.O,OH_zO~e-Fn.OX9}ė"5$T AUQSJ:Es&NYz˛vyۮ+7YTĉ qL=dC}.c!Eёr%c ZfmsMzh4OUaf͝s0E?i8-OT]vEK,Erqͽwߚ{ui zŻ瞬׿7&;Īߔڴ5HY%TǞei[}1ROEsDBa3W$+D%qқ*sڮlB[%ANMd"g }??T8^\htXe[uI> RApPh8xq`NF~Bv-Yl1 ̋XF\,PIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/32x32/not_in_roster.png000066400000000000000000000051111345766322700270720ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5-KtEXtCommentCreated with GIMPW IDATXÝW]lWήwmc;vqB$V >xB! R!HHJ< x DvvYkǻٙ\JH%!)TE4BTZ}{f)8$_">GSԐii Aqs]W:WVW ?_ # 5yoNOO?3885H{}nrR\.ޏ3O8Ǐڌ1qujj8qH)B@0 N$GRC/WՍ V#ONN>;;; c Bpxb޺u\X*PID t:d2GXTUel$P=66:vWOڷo߀DZ&/_p? B`@55MrO=4Mslll1Bw)e18d@;%j:w.gihf[J {?D$jy7~<[ bι}Db$LH)#z9Bpt*Wa PUuib2ƀ644t|fff4Mpl6qܹgΜyU@1Mssw~kTHV|Z&H)q6^vگDMT* UUB ,155l6}Bܞ뺷(L3Gyqbb ˲T)]Y9SjZ4-9_y+eBq0N3LӴ#!q?y1Oq9@7*J@k~R0ƺm> Ovww "AT*3xnԾ/JjZ )H$1p!@SFnS.%"Pt]kV< R*ώaeŭײlBppΫKRJ)r)"@aTιzM98X<7 YVKKt89* dX]FDʇCJIHH);!$P`iIFJV > "\p. !D%أ4Mhg-!C⿒ݪuzjJZaЎyq\;xs8E`D/Cؖe%g/VN|Ȁ8`=z,ÃKKF#@, +j^M?n&N?6<jLJ)]׽VպRԓ""FD^ټl6/xw5X711ҡCe"}T+եZ7[V@nR5 ǢퟗJ;YIr$&#Hw܎?Ni2I!cEIgX2<|:n,eM !lookO cSSS?}&1ou[|oH)el Y>I;8\lX|>(p'@\.Ϲne ۣi435MD"4Mۥ.UUTU`I)sO_U;_.8:%.H !Έs_t]8ǹy<@c2Ms*N?l!]$Y $I ~[.{q˜uN_ct:=adzBQMy vqw{ZgPPɂIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/32x32/offline.png000066400000000000000000000045421345766322700256370ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME $\*tEXtCommentCreated with GIMPWIDATXÕW[$UϭꜪ鞞]fݰ\D@($F O>*hxD#A j J\]`wbzz:?B<\@[PPGq?vЋ4LB0 / p* k-Z,Jlv3q/8t:q|_Eyw 4" k?|1js)<vB@ 0s(ޭEa!B]iOi68ovq|y*^Jb(uB(tt !|5N`Q0`!jE7SJ67h!CnN$w԰( di!˲Ӎ]!ĵ(PAzsUU4M 8x6\K|!D\NYkRTYeyss1ƄUUJM0ZHƏ,{ c}]OjɭzΝaSEQL]z !竪*&F!Z8w5xaҀ^h+vFt}.]{PJzS(Ly&<[7)Y7_;nC;OЎ!@z7l0.5P39ȚGY A`cVU0-X좃 l۟_p4RB_BR<_ @YU)91v %Rwzy>Bheaa8yC`XXZZ|RJ!$ ,˓EQL8K8KEQeى(nqPy!k9s_0 ZKuzʲ<=~ [dVA|* Uf֟R#BHKqc:$kqίMt:}b0<EMZ+c0N l6{])u!+UUlmk-E1fO _8hzcf n)'Z3D!dNpxDk-cK1EL& #8NI89LBoZ-rc  fYc>|>>I3y?KTEQ(b-WMTUB95t7!|>5I?$I^RiǔRnn$I&jc`:]ZZ!axo$ϦiJQ礔)BiB) }_q7y"JpAGrY[Q^^A9)RjZԢZBBhvsQI$8YRt_pn1y^1)J.$T4<۹Y͡,ˎefƘPv6G1J)YfOO&'g)kCe'Ir4Mca^_y*t !LjFk=RSU,ײ,{(sH?JkF$I!a-yw8P)UU 13vbd{: @IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/32x32/online.png000066400000000000000000000036511345766322700255010ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5*C/4tEXtCommentCreated with GIMPWIDATXÝklyimWhPaW@"t (sٌfn/louqdo\2w˲%Menܔ@(r-PNyOSd!7[K>r>ORF:ziW\UQB&dbg~dͰ=# .eMXe"眔 둏x7VHVjTu9q봛5yAoM6D*Qzȋy )* ^J kc]2rrs[ tcqVpֱ~慨\Q@>M/r;.٩Hd!ΡBU^ˣcF=c/w+9TFk⛱IKiФ8FCF blHJXy F V4]Ā~ݺjwY'u؉CN:hVj7_-Bף7x` PwY1Ӕa1|*<AoxG )ԡK:BLb%:v~5rʔYۦiWh 1@Hɘo6,jcpşf3j[UR)IzۀnSThRe*4ZdvSUwR-n2ͦ^x6E&NզkR6J22#u0 LcLJ5rG 灂n5l3$V\#أa;eVL!"Yvx2MGhTz o~%H£S*b X i >Gm:5gL3S(0jX~|@{L ѥVɫ:S4ČOÑKdPJ f[mV3`PA6 xhEjRB  dUHtjue}u֪uKNy*eO}jX}  rUTLp{~{*I ϋ'eUCjJLSZݤ d% HOTQސ ꘝ(V"+( ]!,j6B9e?x3v8(;U톉h 6BVhXfUjLH5^u.'aS>5lǗ7dJQ\:uH #/&圓s#~{IIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/32x32/xa.png000066400000000000000000000046511345766322700246260ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYs  tIME 5)&etEXtCommentCreated with GIMPW IDATXÕ{T?;3wv^;s},A+ [4 JEkLh҇iW_M#5IMhZkm5R <ecq=;$wwNX aP{JBH 0?ݡ,#RzGnM?}+ZUm*̉ VF [ǎ#,%0*OF~ɉEs"|sqes4]bLTrPB+D/QUͧY}UP*k2E95I-ZzI @ ທQ׺G3S6 : t_-a[~(31 (HқB!D/ܚdKM[xeA:IT*q<̥yv=lY@_,rb\5T)A7:I)yE0ɮQ40 E C%],9  M6S9h qn4F~d*!6t,! Ďu5<zGK .QIp۪Et Aiefb&65 QAfuM_Eܼ(iBAn qkI&ޟsv© ZdS3l4F-Xfe _,! a)g9)%ӎ.1,6 'LBlpswhD XDPjZM6{G ٠72Áj/ePflfgkʅB'[!30U .V("1h iQMRWyaJz{dJ|P1m ADŽ&!<@-`_-Z@!@!A(>= Z,-g" !IEq$I>Emj"6II u΁y,ICU5{\FAxP7t:=;L?Es+'lͥ_UJ=^EQ|immm[j6ZEQ|s'h0_Y]]ՏJ)L&oN&{g}UU M:zI6ƤƘUU5|>3mSJGB_9?ͳ97bq* uB9G7c>5NO"A(10 oLH6kkվ(LǼ4M&N83OayߍZ(_JB^q[^)Sy7;t硔A?(tPuB 4MKf#<MB?G D1h= VYkRfׅa0 Q7ks?E~) F9kA"~X,NihB|l8Ν;5 -;chsI68Tߨ<7sPJwf1ᵌ- +(?<+(h4:,mG\JykEq˜\q/'D- + RΫz3k x|꺆/2n!mzCJ)+Rzy1p9a_cUUTu0Bۄ?MӓyZ[#o\[[[m+JcL)1֞j`=%c>Q3ƀR6A!1v.DIͯy~9WcoΝ;tY;F PBmBa!Ǵ֭vt9}ާYX,>Mǚl1^UU:WWWKdRڪCEJnJ}s9v-0RJhke,' cTJ(k-hfݮD6rm&F]wqqy!hOh$ue]86|]ǥy@s-KshIH _{t/PT繖$үBH={ն`BU0BCyK:^uc-zYk͂Z1cs!DK_9GGEUU/tApE1F7U_Z";["q mdx.>! qmG |?T56ykBۅ[sUUm`sy]ׯ(G& JZ,T!n^Sa`0|@zy.B2 ~sNEq3:Zrc Xk3luRj ! !'F` F]Q}t0`08e]׳z `%I[GQ'RIt,Q%d9Lqe@քˣy9R/Apx3'V!L\zc7Uq9Ac E_i>-[X/kZM9s>fu]9~<˲I\d!*:M4>ڵnk$;YX5!!vq㣫Z;pޒ'&10ƞeݽ(@ ݕ!Dp9 CWDZTUQZ[cZ<c ߵƵOQ|tz1D87Jj!.i8*McιRk!ztc /ܵu+yxyҾq||\Ɨ0fa!D܋2BhB<_J)5g ca"yfEqZ{QכhJ)bxx>l6{Tkq!m4M(FWVV̙38EQZE]i)#Zrh窪z(Ǫ:GaV!ױTYѪ~\USJ;VJmH)?wU9a?677R\]ߓRpXMfZsj:q8˲G˲|c<y޺bu8yQ|;|j ́Ĉs~̵άkf?2rkkmbx'aYy1fNZ5ueٿ7,nb_B)BZKuzSu]?~ZJ欭G3yWtzz(SJwB !{co/|GK/u1t]gֳ&\ ^N^x//{.\JRoS!޴1R\v՝;L]~%u0IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/mrim/48x48/online.png000066400000000000000000000064561345766322700255250ustar00rootroot00000000000000PNG  IHDR00WsRGBbKGD pHYs  tIME 6 ұtEXtCommentCreated with GIMPW IDATh޵Yl\u߽3MH")ѤD-dYvlYՎqܸq i) P ]^EI PHѠM4qiK"/ZIBFNN/p9̽=|s#Rgq,} ˜;y;7F6u׬EVȢ𑂌y&͙G!\+PteڢW~lgNEqY(Y.{Gdy0ʿ]7im=v&ҥKVMbu)L09cqҐzhPb )E~% ȡQvyr}uXr>!|SE')S2ií^uhN ie"'=K91v#YNY4j q]5!hT%X-j]S-'cNܦ_θl*Bz= ;uj sUtѬ͘IʿE"Y:ukZq0as_|)CMfGI7jG`شC9g:S&M"DF:tjeVj+A'Rjb4h7|ʇ}v+s{Kz!Ow>Xj>ZZ7$K;;qkӔ/;' p?3jZryȜ𼔠ᮅ܌F :9(ڨ3 Zu\2 gAGJbs{uT-8Cu5mRVOgLRŸ"F!W֧=jނN8 QV`u: ?ۭ<甯? EB)f+"$Lr4!|W4Mҫ_[ݥJMڜJ x{ܭ\/zcxVlzbY 2Oi7R,"zs&AOn|M`;m΅g)>_}*KVxŘoYo>6ؠWq v~a6ZSvQ%_Ϛ{FOk9A&[ۮD!@  UX?Þ$3bmv.uVP9 z+ &͸Svcn(H6yy,,+k[ݫOcEu}ŸXawMAV6$7/VU j`JR($^ot6]!9mls'Տzz=y?p-U:k*m+.9aIUNZ[e4X^(\i+ 9o`/~<1u(ߙ^)S6ЂL jbİ1mޯGvJ`!/)Wh;ЫkfLJ9UFKUAQFa!aVuc}JS] ։`]6[/SxƳ :\Q{SiU(=⸑̋vbVDrUAfvTR΢ Cw 'AO\@YMu:t,Ȃ|9!k 5B崟t_dE`zTOxγA'U=#x(ݻ/pdق()k]ަ+D8d_N2|9ɥa\[{XyǍ*{2 j,R$[3(VmR;ahI(MU tO)I2=iץ>(TqQd!@\Tՠ-%㚍-DL/[2+3&L×ֱ2%LNJ E+;zظFU8"]g~ 7B\тdID2 (!C޴s,"DԮV{lԻR4kܕXvfCŎ%W.8h>圳UٹANǁWNj|Eh-ߢ-1U<+)E1U ^|Ȫ*Űs3qN]T,vM[2wYLV){װ]hŤX *;~Ś%ֿ`=j9&9ox9jb3Nj7Æ=CD~ƭpb@G("U_[hGܖ)xt]\R`k:UZhmu:h*$!?qԠnUBܨۀXFLr⎊̈a?EK.o͊Py)K ֐+Ɓ& XmAvj>Lh[Vhn=tɘ yaW0ZcdPX$E=}->howk.5z4Vfk>[ `B̒ҹ`톐u[oqofA/U\nQkj5NZpO[W9Jd#zKN95r byYmQV.7YJeXBVp% _)*;-ϒ mny̙5SAҵ,:+4QLӀuIכ%Ne.:kB5m5bIF4h>5Zur"Ō]q Iu֐M%F ;F\`Vmͽൊ]z(`LqÞo~?/;'RMnvj.9 5d2Y1)1Cx1vDRUL"m6d~{կ[f )޴~œ 8;#:uM~JUӖ6ͺ֫M6Ȇw%sJD"EQ1#F]P4r>5_{˗?*QjtT:bԌ,]~a`!^_hxIIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/000077500000000000000000000000001345766322700225575ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/16x16/000077500000000000000000000000001345766322700233445ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/16x16/away.png000066400000000000000000000011411345766322700250100ustar00rootroot00000000000000PNG  IHDRabKGDtIME  :+ gIDAT8KkQɄ̤RbA ҪI _"x(V܉r'Rbd,S$t9.clphX*/z^? 0ȗsU}}L\?bry` zh` h4͆DžGp]@R 4Wh8>mumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/16x16/chat.png000066400000000000000000000011411345766322700247660ustar00rootroot00000000000000PNG  IHDRabKGDtIME  :+ gIDAT8KkQɄ̤RbA ҪI _"x(V܉r'Rbd,S$t9.clphX*/z^? 0ȗsU}}L\?bry` zh` h4͆DžGp]@R 4Wh8>mumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/16x16/dnd.png000066400000000000000000000011751345766322700246230ustar00rootroot00000000000000PNG  IHDRabKGDtIME  IDAT8OkA.1BRI[yBgA R<(?/ T?@TŃ~1lnvfw<u.{w^FJʬ(πe;A;~P4ӥ8 (k䗗aNNioJݘVsG޺FAbhbݘ FT)0/[=uh IR J8,@?ql( J-Oe2h= H)D777h}4EIT%^̹{TBlj]Z+z?s@ZC7xiUrk:AuM!j䄳T %GTb}4 &@$, ZFcЬZLqwVJTB:bgzK".hBաK6Ų,,ƶl,ms[8Nbˆ=OjLۢTXfnt 187/ RsIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/16x16/offline.png000066400000000000000000000012031345766322700254700ustar00rootroot00000000000000PNG  IHDRabKGDtIME  :+ g%IDAT8QKQj N RYB^B_@KtэPopzl1nw}N6>7{QT*M$)0恵8\v|FG('8urͺqtQDbq=/]շg#bi{]Z'>GS-kfDZkM:)79h`ɀ_ zFovtN͹ӷwޯؐ *㾂+;_܋XmumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/16x16/xa.png000066400000000000000000000011411345766322700244570ustar00rootroot00000000000000PNG  IHDRabKGDtIME  :+ gIDAT8KkQɄ̤RbA ҪI _"x(V܉r'Rbd,S$t9.clphX*/z^? 0ȗsU}}L\?bry` zh` h4͆DžGp]@R 4Wh8>mumXQٕD7E.UxAMk0>q&fzd}}i Dxe l7nVtT @$:>w\< u;[i(;ݙ+[5Ns3cgsit]0dz!(P SW/P.g_OwCq@ B39@$$ұ2J)66lV) m@4ŁBCP+ $mlg]+ƴtjws6arcLL? yIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/32x32/000077500000000000000000000000001345766322700233405ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/32x32/away.png000066400000000000000000000026121345766322700250100ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+,IDATXŗOWsfԪ"1ZP6mcFmĤlOЦDO6`/h҅xaAA233j&'l3; sB>i!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/32x32/chat.png000066400000000000000000000026121345766322700247660ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+,IDATXŗOWsfԪ"1ZP6mcFmĤlOЦDO6`/h҅xaAA233j&'l3; sB>i!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/32x32/dnd.png000066400000000000000000000030371345766322700246160ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME %e6IDATXŗo?m#[6Ʊ ^ j(m" iDKyJ!JQDT)j+ ڄP!P٦Z zۇ7٥HW39{>眙{gl 8. a=A4k,i)bQJ՚IuGLt:}{-;rݻimicqib&H)@xO\bn~ޚǤ;w_[6` h~_XVb֚ ZFP(R ['\>L*~`_ƾ`_nx=ώ ДlrqV"(,ǧlbE#uBFQ,JG٪\ ?kbƲ+-[yJ[[a!ETr= `EK:[d\|`]+/wg@JG#/r5.6fޟl_km\',=֐ 4{w7B 03pjR!"SƦW %]]]ܼy2>>C윳s LjFcBQAT&ҳwouBuX#ӧYG6ݵҝ9oىiЅtsFF.s~"NJa`fHk2s9Le[*E뫯"kaoOx7t,333LOOb>{}immǿJ).^ȅ fh ZW4M9#&''q]P(Oɧf[x㵟2<0o_MUĻb?_`ttq>|j լRhσUo=XS׫@8do.T׷@D.]¶j3WN$ۋaC "ׯ|>W)o+x%|@ Й T @Df)^ fb(C+?#@|a(!-gΰ交DZLs'W)&&--&RJJӿ}gO*y;DD"4 B˭؎C  "wwy$IH&ic)+`%90P\)Fu,d{/%g!qm84B BJDB!p8L4f۶&p֬7)e 1ŕoMMM-@P!7J-  JIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/32x32/offline.png000066400000000000000000000025721345766322700254760ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+IDATXŗk\E&1&k(MZ)h*~RADPQx#ZJb Ej**/$ ۸4ٴI~b7&mҐ Ùy}73gMܹ3jڎ QJm/G䅔+ c+ʕ(y/X YSP#?,j~HR} . RѣU+/V&gRu<E\y?l)z, Bu+o'gx~qq.sn7^+_}yv]'N|&p!Ri3VGJ.}/JT|J ǷPx$2;;å˗8:L&B`azz=ׇ5붡ve|<˱7an] !ٿ'(ʴěAhPxj?]+\}R<ٿ+cW|=lƶ%Ν3~킕Tt:R 9tT'O? QJ@ZkN:{96R@kףc[oK1|)~:9{imu릠۶ Ðr9gѱqZ1a*_=J[[333LNN`+099ִ69\0Ԡz2nݚgbbTj'0Ơb׮]ضMdY4>۷$-\T*ٹ1R 5\.kY5k-ӳtuepSJ58Cur$0??ϵkR)DcRdhA֫biF<ފ6SS$ej---xGPBkm+˲B`Y_N$ 344D̍MMg)F5x)ql,BZV&dAi)!1˅%}*PRsŚR$GsLHĘv6T Pq-J!W_ZZB@@EQNL-fj-5vP[IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/32x32/online.png000066400000000000000000000026121345766322700253330ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+,IDATXŗOWsfԪ"1ZP6mcFmĤlOЦDO6`/h҅xaAA233j&'l3; sB>i!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/sms/32x32/xa.png000066400000000000000000000026121345766322700244570ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME 3+,IDATXŗOWsfԪ"1ZP6mcFmĤlOЦDO6`/h҅xaAA233j&'l3; sB>i!AXk]F=>OK!#RA*|__߽y,'W-]jG#QB! 41LCJ~@B)|,, Mqrd2iA5BXR  u۞E_}yl{OX9/w89M|m@u ʌΞ1x>9'Oɺy@)04G:=x2ޘs@{ y4tɸ8󌓧'5JɗxUB⏣[Y(^!YULzqy7ϼkx4ch4G0gO~؎\urÇ+ x$;ui}s Vebb繳ΓR"䷖ |cfULrCJ М9L!2w(JYd2~ۛ>tdG>ghhhZrJdnذׯ>ae˖&:g?EK8J)E1]2HT٣RE筛ܹ{*iuuuiz7~8|NJa`fhB0 ֊ڹ4ةߧ,[!G)ťKhkk+Zcc9w h`+ К1kHk|\ώբbӜXV9y7lbժ3|>eYhƙs?qmVTpg8mh> kF#h#,ׯ/f4Mۃ **ʺh>#{w# zHOODbJ>tt:${zzv񨩩ڵ ;:OBI,Fx^>hϣK);dcY&PbѢ*BМ_9{w  cN/>c-F\_U.IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/000077500000000000000000000000001345766322700234145ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/16x16/000077500000000000000000000000001345766322700242015ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/16x16/away.png000066400000000000000000000016441345766322700256550ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<!IDAT8m_hu?sl;3*3FR7 Lf `tQxeDuTye. Y03A+uRŜw}ۅ AUU~|p-SUDUװQ M5`F0geYQ?MN%`5>X/(Bx4~PAͬFc%Nw` ݁vmqkN4JM@\?JnǤ4]nCJ&0Xb$ŏ mWt^rӧi/H7yO*;a) wJTsQFiZi3|=Aq$cų&Lx 1jbo[Yl՟D@WDыU-lgN$IⱮr1o5]?>::Y|=[;[f^ 8HVZKr=k8/v=? vou/=R$IȲzNT*&=27_{KE{/xrpΡ^RpQ*k-7uS.H{{lذ4åq)*qS(Ȳ2"yTUT(( kmHc8i4XkDJ1c >4mX_^&{Nt33W'z#c F~rU 4}STw](y>E#-zurm(hHgɃW^+N{IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/16x16/chat.png000066400000000000000000000015031345766322700256250ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uQMh\U=w{4i:Z4PE%.QWHݔ."H+J]t.Bnmi h@I:ޛ{q1NHa&#,6N=h[`GehBD㯗GPqk\ 1kF|*%Y>B_5OE  Pn[f~)פu#!&~&g%VzZ--+e}!;p kBM!CDi]嵾#Gz㪣9^0g`~xiK_6IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/16x16/dnd.png000066400000000000000000000013621345766322700254560ustar00rootroot00000000000000PNG  IHDRabKGDtIME  9;20IDAT8KqƟw3;Ό֦պ(,*t?ATFvtKA(>dD:K)1W<ޗ!g8dUB!J.xW+ w4zx[k5i<^5Of^̔vk LN,is ĦSX]]:by5eEb+Jtndd!Scz%=ө 86BLDGGV ˠUЇQg>H2JXD>$IȲ ,!"Hb۲H$XC\]1AHkR]8$IB*mm0 zba`hhJO3?66~uR)lmmAtww!ЀJeb1PJI9G~%ȓɩ,#t:Fp\UXEYZuX5P"UMZ0(EN~ dKJϯx8 ^=ۻMfdq}R|j~oς믨Q" [Α/(~QHIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/16x16/offline.png000066400000000000000000000007211345766322700263310ustar00rootroot00000000000000PNG  IHDRabKGDtIME  9;20sIDAT8J@ϙ4IxDq p .ŕ/ >kD\]iŊ w "XKC&߅k*;q9%"̚gjVT=NPy3^ Y˕:}X*Xrz8Y_)NW;wk #e[4F +sS>ahiHc3.w"Է-;N- h6)B2F v[a[v[B3֩k2>$TI|*#ŘʝIQ;ERZn@q7 Vxs)l 07*Yb) مJr"?2Aܚ\8')]@2V:ח ^5IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/16x16/online.png000066400000000000000000000016341345766322700261770ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8]Khe_f$,IdRN.ԘAE QMADPl1 )ZUΘ;.4 ssPUvʭL{;%ҵj%(`yM4ob.鿴5^Z=wc. ~ ^E^\Bi'O2F!$0[\rsE GgĻA⎁I׮#`7 @I;AT}@0hM̚~!ne*j!6Ӻ]y$x$2`*jw0KeQƙ3ڎ(ʣH$bH[OLZCe|yngY/ ,q4?B-vD*Wsu#nqCJSndqO$j|ÁKw@e{YSmUW?,Jk-3>]7{#o97>ʍs<3y*UVQi6TU$l+_/ןFO^|zb28PU|NOc##y27 oX*BD0 "c JXʈn"yJdWW7qc!"(l"Ӄy++w1މǎǟkS}{|{j;00h jqٙb\}^k|^Tק_{$ Mg3R}ѴCayso@ / g0IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/16x16/xa.png000066400000000000000000000011351345766322700253170ustar00rootroot00000000000000PNG  IHDRabKGDtIME  9;20IDAT8͒ORaޮU ƩM:fP"h7#" C22ڶhmU f"fHuL]*"\Ԣ9C3ӭI50G7V&=htB!&>K'ZRy"|7 ߕR?:Z0<_AiLڳ^,T*/ͅFȝ4Pʇ+j5|G:ƛkx:/~6-u$ h!R BL:v6MCID3m<(`bRZC)h4n1Q(1Vu$Lb00 R)X*ǁa>q D NҜifga' }2mp]=8v])8!a0Ӣ&jXA(+ha v+WN]~7ko؉}p)LIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/32x32/000077500000000000000000000000001345766322700241755ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/32x32/away.png000066400000000000000000000032611345766322700256460ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<.IDATXkUk}ι9wf;fLJp1%AMLl:F$VRB !}ljmSci 6/$Nڦy8w}{~~0NXZ,Xl׏s8̸!h'P;V1B[@v&PySMM;ӛВ#\*+-0}=p܆GƂс&Gz="]J'_1Ĭ dO2ܘ\cӃJ<ޛxlpVuLdH,f/ x1v89HAn"^H} \#}ށɑK*ʢU5oW5kuF8}Yɽ 45^!dPřӛNA"K=Ey-fJQq) ½k3aB9>=Aet>+ IeQVA:Y|I1{7 VA,'S>N(F[U7 pjJ,LRp%9BAqeȘ;8LxlN[$\k| @6_dl+OŇ` kḟpĻϭ:>xɝD"Qc0 `&ޣBSBOL 3έS-t`lJ3&W0:4IBPA&fq#%h`nw^|[46n:˝$zq?W^f˚ûyK[!l;*eYvE}M[: QKf>?ra(Bh.+q\D0̶[J R""H)AD`f03RBk c ,3ŋֹۀKMAHsj >{?s{q 0Rj.MS03y`-wKL4Q魙iA!E8FERJA0((]]]H8SRsxhf?V>cO< !$ 8FXDWW8OoV~rϻ?& dIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/32x32/chat.png000066400000000000000000000043641345766322700256310ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<qIDATXW[]Usq}ЂR"IyHDC &&DcÇ?>>MA?iQik˴l{=Zk?m?\?{de1k9$wMy098/$'r"Z>c<صb(˵@lHCV_Ƃ1# X)ϔȩC#,]UYgnq)\iTXUPTpL\z^ Gf;H2s&œ@%O YWrFV\\n1#i X.; t:+-Bv!tz@.[D0',F2]MJAݍ;_8/JbB! .E*evS7R:jubD\[T;16:s`l [S_o-t(KWDn1mBh+~&jjAb GRx\ML a3F4-d^WG %MTcSeQdV 6OQc;L#U狂ǀD#6qlg[w}UkZu@[껥\C (@!`0C|Jhzҳ hPbpK=`s>u˵@}cZMb/ Z2{/P,TaAK] ^kzk]~>m*Rcիj'`5 )1Xpxo[3jes-fEp< Һ f&_M}l~&ZI },{DCSbb&7BI kb9lst/BgkK71o%ƒ`n -tN dZLWHjY淚p灴 *gKq(8k"zfN&_1Y&W J>&j/}Ƈ*`gf~z0t.Ь).ogDSAPQEtE?!D5_&U40hixOyIԊՄMoP>@W A'$ x ! f:0Cl!#OyPZ& VLC X.EWqX Àx ׯЏޢ?:6! 'Hm-ypH`9b~.t$!ӷKA/ĥ4TmH."B)&*%.߀KIkL}N d3`:ԻZ0gcq# =}Af 2<qFT^֡(oܥ-a{RLmC= MoaKRWx!P@2ј}H:ea\UjW(|rQ5<(:4oy@џz7pZg~AaJ)vD%z?ՌzQK7uj> ɃGkyHCVDY=slhA>_Cl߇P=eZT"0(HrNw'3h1zakz?0v)#J_@Ed1r.f'*ZAMWT(!('xDGAduUC .}~gc9HIpesD0eF !.3 !}^2IItk&5C75FUub@P6 #4"Ql `~hLGM! ,O+mӸ|G Js1`S8ȒY^ H~xn_!3ׁVh)Z =T à}Pc &8&1 #$?ON1q$!lFH)(8+`!`&'2UP&f! 8F#.N2??8v6aFM-DC"'w FcJ,jVڳ',ZS0WK0 \]Mڅ.7tth,zB u Aưq9|ֿ lIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/32x32/dnd.png000066400000000000000000000024371345766322700254560ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  (IDATXOhUǿ7vgӬmbCAS z]1>>d2hkki<RJtuuH Fu݀TQn}D$߿SC+ÞBH&uF0M"NR !RPJ0 pΡu]n܊[+wѵM80Mmò,pQ.BZ /_FpmP( ӖIB_ZaA4;3[JW HT*Z4MqH$8٠B\[^r9 x8!R RbrrQ!DQ0 a6} cnn¶mtvvX\ _n 0n^riX\\Dd2RH)===:8hooG6EZBȨCuaR2.3__2s޾~?BhA v<>T̈F:?%ik_n4h`WƏ r=@H?pg}9Rk4FGG`ށ]WZ[7kd /c{;NGaTIR <,.i|nw`f>x鿓YBKAwL]~UJyu/D=~Quo#d6?h ~5 "QZٟ[J֚-}"Barܝi %~w`K-y@Dە0#LwwwWK09غ![)Ib#oEEy% {nr/T荖 hW?5HdlO)Ͼ'MkQ*ݝAk 50){# nhLDgJQK"sS@ <$Ie{l,QT)]H!4Au~3=_LIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/32x32/online.png000066400000000000000000000032611345766322700261710ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<.IDATXkUk}ι9wf;fLJp1%AMLl:F$VRB !}ljmSci 6/$Nڦy8w}{~~0NXZ,Xl׏s8̸!h'P;V1B[@v&PySMM;ӛВ#\*+-0}=p܆GƂс&Gz="]J'_1Ĭ dO2ܘ\cӃJ<ޛxlpVuLdH,f/ x1v89HAn"^H} \#}ށɑK*ʢU5oW5kuF8}Yɽ 45^!dPřӛNA"K=Ey-fJQq) ½k3aB9>=Aet>+ IeQVA:Y|I1{7 VA,'S>N(F[U7 pjJ,LRp%9BAqeȘ;8LxlN[$\k| @6_dl+OŇ` kḟpĻϭ:>xɝD"Qc0 `&ޣBSBOL 3έS-t`lJ3&W0:4IBPA&fq#%h`nw^|[46n:˝$zq?W^f˚ûyK[!l;*eYvE}M[: QKf>?ra(Bh.+q\D0̶[J R""H)AD`f03RBk c ,3ŋֹۀKMAHsj >{?s{q 0Rj.MS03y`-wKL4Q魙iA!E8FERJA0((]]]H8SRsxhf?V>cO< !$ 8FXDWW8OoV~rϻ?& dIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/transports/weather/32x32/xa.png000066400000000000000000000023301345766322700253110ustar00rootroot00000000000000PNG  IHDR szzbKGDtIME  (zIDATXoTUǿܹg>f:yuD J,nL& mBBh 7.4>5)UM Bgvޙ2yq}07| <,ΝH _\\ؓdP,yB !IgMjRU)D؎LV%~K@Dž}.)Po?FN>&!D_S#O~P\@^U@O;6z6Cg{Zժ5\ޥg+Z_}LaH:A9Ws"Fh=aJ !?cAK( o)[+kHk/5rϪ4]ùʟWCï7ž 7f}xX4ѸxlQ.M ?bVV6 lz3RcM FO(IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/000077500000000000000000000000001345766322700207045ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/000077500000000000000000000000001345766322700214715ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/away.png000066400000000000000000000016411345766322700231420ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKluyl. J ۥADS&4aFoLxb͋񲮛h Ճ1jn"vw6N' !ؽɰ >?P(@HG#=i7`b2;rfW¯٧.Yh5[N\|wog`D!mzv O"p'^FbS&&ýWs08|ί|?5,K m8s7>֕TB >z ?LMKr +m\rs!smk?ǯe˷f4 8tgC-Z,'/_K20ݞdTUG1?-a}PU t^t-ik[:>d#$D3J Gyޠ PkԜl\\uph8 YIܦ\o-r5jZ,jozeIOj& zOҬWKb1B.;jKFC旙5}GMQrr:xj;?*S:V+t3(4UC x*#];wnxR),&uE:||Fв7pYnFzrh$Vܣp轞VybcK- [L]ߣL|g@6 |YNnYևq9k6l6?v}B IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/chat.png000066400000000000000000000016521345766322700231220ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<'IDAT8uAL[uі R]L0K0a3cM9}__n- ^~ _Qd D.<`xc㯖>3#gPGgwDdf/gAԘ 9;]=@Lk6沷P:AM-zvpp;i'ɨJ\ZRBPpmؽKOuj VDX xŝVCPR[66/7yq2=E`cYHNGQ}XVPL\ܯu 3(@ `fqh[دM(j`DuUT_DZ d5̽54T"ј( '&{v BTL:֜=dQ2$l`*"'t4uRF^,_ޖO*&~r[[C!­Ϣwʳ껓iȕO 5IKԜ&, akCL0+)늟z$ab)V~7 0UUm{t=}RRIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/closed.png000066400000000000000000000003221345766322700234450ustar00rootroot00000000000000PNG  IHDR <$sRGB pHYs  tIME ]tEXtCommentCreated with GIMPW?IDATӕ10ډ&&C<e&u{_€D jQJR͈IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/connecting.gif000066400000000000000000000004361345766322700243120ustar00rootroot00000000000000GIF89awwwvvvvvvvvv! NETSCAPE2.0!Created with GIMP!,x0F@ ;'d碥LJp,J! , x̺9`b]ێZ\ ! , x'̺9`b]ێZ\ ! , x7̺9`b]ێZ\ ! , xG̺9`b]ێZ\ ;gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/dnd.png000066400000000000000000000016551345766322700227530ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<*IDAT8uMLug;vma8ΌBڇabLȶhEzy27/nQg4&ZjYLeaؒB?ҽo=?Ó' !؝ᑰ-> Ɓe`))H#'k.Kw`fX*~xkH#3]O7ӬNM~#H|~nߌFb _Pk?3qe $ UZ_wEfV/_?WnIЧϿ?16&w蚆dCGWd$j$B}޻_Uh=;tn05?'ߌOp9=JIϐ^DT*܌x0(:7x{Uu^1bY8e@mi#LM&bYޘN@x:iD]pjnfҕl߇SӰ$ZaT*rZg;ĥjTE-*>.(YCTj]-zV INO! !4V+b-Y[P@ebBC0Z'o(%%${sܹi3UѴAJe63`DJ,cD{ #+I0٪8ڏXjpGX17G ~<+薵ߜ={䔧VU^bx;.[1̺K#ڪhv118 z{K."ʂGm~f$v!xvnr04NC"ǿαӮ]Ftj5|nO!,*`O3OI8o@`'da*1};D &,Qc qZr#!,AI8o@`'da*1};D &,Q; P@P,`o!,DI8o@`'da*1};D &D2 0 {Ct (j6v+z8x,!,DI8o@`'da*1};D-p@ePp`2R@ z8x,!,EI8o@`'da*1Tp al@()xF@vn_ fLG!,EI8o@`'da*ƌA#@ɥJ@vn_ fLG!,GI8o@`'da*O pN'`%|&"Z!,GI8o@`'H*Q@]-!Q`pb2)G*ή!,GI8o@`Up g",G+Byn?8`(!(EyԪ:!,DI8o@(A$u p LK6p9;M3 !8x,!,@I8o8( AhөR3p6?G©jo$x!,>I8o`'da*1};A &,Qc Zr#!,AI8o`'da*1};A &,QP@P`o!,DI8o`'da*1};A &솂C2 0 {(j6A˽z8x,!,FI8o`'da*1};Asdaxh:eZ@͆zZg)!,HI8o`'da*1wNpȃl+(D,Plڬ`s!,FI8o`'da*aQ lC(X@Pag)!,HI8o`'da*}B|Opa;qDDH%%lRUZr[`s!,GI8o`'붩?3b 8X<"eӉ)F*H!,HI8o`wgSppJ.r p @D~<qIdP|`s!,GI8o8( AhӇo R7أ sA Jj9o!,CI8o8`ՇgSpJ. 2U#ac#0&c/& aq68!,>I8o@(A!hө"S.p6?jEKqLZFr#;gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/invisible.png000066400000000000000000000016051345766322700241650ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8}kU3gfMM5!UclFVi!⍗ UT²-APDRbm>.JƚΙ3NjA]7?a/ ` 4@׻?qx`~aT*y^=1:h Zͽzo6 w+2`aGLZf{iMlo흦i?hF~zsΗrl\~LT?!MSt-u-+^~b5o.q%I%=8z*"I9#&ZKYٳ>70J+q("lHb`!lEw]V_89`. uW*&V1 Rf$A%9#aﺮ8>r(0xPHuJSS{CF 2㢳>`hؠyDAC1hR#0m24Zwɩc -:yJ>cc !wRw`ލ{>xbqz =Oztz,hZ~-/A@OD3< u$ґXJrAL&ydk2XAva7 t7?}寮%cF}G?f٩ckG$S7oطFNy׵jos}#'Bnjw3lޝO'^>pv5h*qx.JOw7_\bO Z/|ItLdFϝ=C"U԰^USU8Ξa"8k,omc)P H&Rk:󺊛TPDPPcW f fX1@h@, CAD0ƲTջuH)_DDp:uXAXyhZ9ᅰDwPV0fa:~7vJ=^z=| q}XX"Z>ՙi`dY-:cXkD"mKtV:?]ʭ\U,g\y s;ձ>tY^^QU^럎z1!cDc6^4UvR|L /HH3U IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/not_in_roster.png000066400000000000000000000016341345766322700250670ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKg_|oM4Uc2GA6+vRv2d]C6փsFAHzkcTI7ɰ..6|\> |/a@r0́x0>9zS_N>OJ%P(~Z./fO퍼Dh4iiia}}o^^_1r,No))VԔIMl9i5Ơ6~[]_ 4c߲PJBJJՕʶg3tٙ_pix5Wff@kdP*,fP*23j<./^4 %Щm]dl֜xpΫ՚m.h[V0-v*²4R)JI\>(1jayR) #@tyU_nR9z(uǫV W(=+ϯ| `\ d;!hj>|~M[{pWq6ch p ǹ]WGgh3qw\Tl6=|6d"AM ʲJc 2 w[\/6c_5xRF)mofv%[//柩r4YK{&b8|ѼF4p;H~T__IgGxWB: \iJn2Hg۶/zc>?oIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/offline.png000066400000000000000000000016531345766322700236260ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<(IDAT8uOL[^ǣ Td ǟu2 یC>5zdŃo^ܢh@فddDV6ڎsPվσ8w>morjBt@Z 2095>|t7&|MUUEۆZ0 ><;? M3LNM;}50lÇ022B[㱵K_\|+4/`rj…wqe (┝X5F366F,X|˓pFJĄ޾NzddvV ͠( * .YFu(m3::ڲx@?{D<&F"n7ͪs:ǎ0[I,"ix̹V"#dE@qjGQF:Qn`"KXVMldp.U\4rGQ4lgzj667EJPہ J*82fl8JRܲr $SڎJ$Iwr4uA@{yij_pʃC?_M?, #$A!ݭue3gw?>ZZZ>TӇ㲳`B*ewweYjor&5IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/online.png000066400000000000000000000016511345766322700234660ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<&IDAT8uO[uўsJi)RrcllAN!q -޸n41x&N A8n4!!sL,`Ka~p=yab }.޼$d&&%"cF@\NkәS$`br4MG?1_5[F!`;m~rLvg###SP/,gZ=Z=Gd2م?^^\/HU !o\ݽ;`a͙ٜZ},ZcqGI==~͏a_EV$z'ϗQ749R_btdlSb?i IO0}=D5c3R`kk058m8tVqHj(Z#bNIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/requested.png000066400000000000000000000016411345766322700242020ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKluyl. J ۥADS&4aFoLxb͋񲮛h Ճ1jn"vw6N' !ؽɰ >?P(@HG#=i7`b2;rfW¯٧.Yh5[N\|wog`D!mzv O"p'^FbS&&ýWs08|ί|?5,K m8s7>֕TB >z ?LMKr +m\rs!smk?ǯe˷f4 8tgC-Z,'/_K20ݞdTUG1?-a}PU t^t-ik[:>d#$D3J Gyޠ PkԜl\\uph8 YIܦ\o-r5jZ,jozeIOj& zOҬWKb1B.;jKFC旙5}GMQrr:xj;?*S:V+t3(4UC x*#];wnxR),&uE:||Fв7pYnFzrh$Vܣp轞VybcK- [L]ߣL|g@6 |YNnYևq9k6l6?v}B IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/16x16/xa.png000066400000000000000000000016411345766322700226110ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8uKluyl. J ۥADS&4aFoLxb͋񲮛h Ճ1jn"vw6N' !ؽɰ >?P(@HG#=i7`b2;rfW¯٧.Yh5[N\|wog`D!mzv O"p'^FbS&&ýWs08|ί|?5,K m8s7>֕TB >z ?LMKr +m\rs!smk?ǯe˷f4 8tgC-Z,'/_K20ݞdTUG1?-a}PU t^t-ik[:>d#$D3J Gyޠ PkԜl\\uph8 YIܦ\o-r5jZ,jozeIOj& zOҬWKb1B.;jKFC旙5}GMQrr:xj;?*S:V+t3(4UC x*#];wnxR),&uE:||Fв7pYnFzrh$Vܣp轞VybcK- [L]ߣL|g@6 |YNnYևq9k6l6?v}B IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/000077500000000000000000000000001345766322700214655ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/away.png000066400000000000000000000046051345766322700231410ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATX{\U?1sgtfgmi.X%"&j06M /"(&&7&&>bDO1DԚ@IJiJiy<{;-m!H#79{}~s|Z˵|wlˀN=ӻv\zlFёnMX`x x|"##~\rnqB+Zk<ϟ`*K/8y/v`m+ǥ=?7^z#W?q/ƘY];wضx6ww7'DXCe:W _PȦStwf] R()izC>boO;mR>?4nt#[w4gubu+0ҕvO/v\LoMLش}=_?>5SX!)rl^Ǎk{u \TAR(Vĩ2BH!,]$Wף &&K᫅B8qpHogMbDI", b836v}5k#^g)͖Ҟ%L"ڭ"F{p;_[arĥ,JeSK{{LѱPjJ]ϟj OivGSL) PLϺ8ϬDiq&`P9$ dmwݹ>:H79ߧ)gM hg@K3޵iN@{[W{6{,cםkVZIJ,SӴ+*}?8sԡW;\3WO !ZnYӳtah,9=r@$S8{{txt>1ej%hP+ y%P2c:@ őw^7_TEv}^/hP<#DZ i45LS`1Mi6].}1v45db438ClDAnZo}G!*^=LCbiLCö-z6nsj2z #Cǩj1hTݒ=71yZr[?/vs@~fR{! 1aȚRnNӿs˻VSāO˻Vҿs4IC#g5z.E_ws-|N8ihR04aْ=R!a>qb˖H6הqa(`4uwY ٻIPX4qbqZS-k XRcvt]q>_ۦQP],]֎5QLOTڀ@8RUb![N]!5씍DWH(5 |J$q ;ecH ]k)Ts!4q$,ΎRI%m4`5T)uJUI*QX% |Ij*fb8_4cQ8VQS.M1;Kٛ|L]`,H*qX!$a$kVa$"40uJxsYӟP&DqJ6$qP)PU*q8^C#a[:?CfTH2~yǯxv (ٱAʞGB%qOW =ϋ5'ۤK FTT\öti`H4P(FaҘ!+Kcè4 p&4'~E@^5==5rZRnCFolA|oTsq%&HIoC #wZP)+[ nCNOODl9=sܶ"sf>@2WòXn:{nJ9!m칍ư,⧐aԓOйr3m+( oݼm :W0?u˟Ԑ]qVHW.*(Q,rGxS(%tm 0&Սo÷r\~heSAڎ^w+..)+Jǘ8Gʅa⨈i14qT\f)MenEڎʴl* ry୅7{Fɟ{e cL?\.D1D%K]e7мbWnsze`7^=\]Yǒ-H]h>1MVDjEL,i>E4x`+Sl0xlp²'eKo9Ӷ۱ B..%el>tBeghンL:dKoٲ' Nd b_Rm7l[aVŤj"("C2Y%H'z͓CS oiYԴsL&*A AFBt*2|eP}LՖAZ7n|"օy%4 ;pjUJ|'? +__kkL.ؚ.mksҖ4+Z( U8_fccyEl4RJ:^EQݜ~֞x(P5bIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/dnd.png000066400000000000000000000046131345766322700227440ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATXYl\;۽xl vlg8MPTHBD FyaD)URTRԂ!J)$,)RM:s#.\^^;rh_<-l~jW _կ1nxᣟ_3;'nl{um^L:Hkjfy{;x(*RQ(e/a1 g+;On溮2v :E>FJBvGM]= 5B P04gwuv5ǿyӖv\bICBQU"y=uqǶoƍ=rɄ(s!T% URH*PolmjV4H0y~);)yC?$@@l8>>]DRď ;1B]^K߾Xn%HhM‘+֭oMDע B$~DBZ;oEϚ5] ss© >"_\`Pe喵TbaM*FQ*XZm (7 >SPkt-zJ5=\qJ?/ilEUTrlaM*2BhVTEu~if0RR0 N4MR 0%( A0FJ8RnR\)ka X\"AC{;RJiZ,$P]<5 yQAwۯPBX68FkjYTW)Q/C:B2Y0v Wَ92Fr4hj$ S,Sg+IX5ʨN(" $R|2I>5Tv\oMMO\u=! \Ƙ<9VSCP B%;GFǫ!".b3ŘKSc&&S,8uOu\wjz̩@0 ۬բQE-S''y`L P*jDݒ F"^=(R.H#uvK/L!\pp+#^|A}9{)޳`$zdT*Nx;POucSoِǙ$6'<VOA. 8~4nF32K/ /9|Ox H[NM]CK_'E\r%ugGSOիKNM;oI_%~L"ے˺6r^"p5ȼX{Ҹa˺ےt"POؾqӦMJB7Nrg(l4pg'֮ED{Wki6Ο?_^D}}CnnѤP,"M7MC* (w:fK\*ǵ VOM7֭_A:pN0TY6%mwt Ү8^4uGiͯ/1Ymk[47khmH Bey\ּH''' 0r/U *uMFpmv'_K aHەDIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/error.png000066400000000000000000000013431345766322700233250ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<`IDATXOKQc{[+Z"!?8DV":Ď WF@-1wuw#y`yW99@o7tXk{7n:^t,R"]{JҼa0n5ly$+:XTأ,T`L%i0uMa*I3]!RXl {Kei܁0$ jf`Tk@.(`lܮA9xvP;@ &ፘkA)xv`"ѱON{Pss= #-4?<ԃ; ƅ:|%TV4K͡@QvњG&l oZ#7VF>n׀C{JnƵij3'@6֥lH F}]f`khwx9zT`i%JzFq.;ٰfnܲ0wNo{"*JE|.\lX gvӃ)xH}L>dpp?0"]ÂC`S0\tHtny;'snmý)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/invisible.png000066400000000000000000000042321345766322700241600ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATX[o/3s >PRUHZiHRZ>_CJ}?WHI!I j.R 7c>̾a(5#-ff{˖r>rh-sM`'P;}( ~d}03;vHCRGe x {*)%z2O7n\ ~؉9 8*"#?}g|N|?9_D^?z;<7J#+Rh+}9λo}7&SJ.z>{~dYB SuA+nE㜋ƛoo}Pw8πFz(TGOV[v./)]_s.xT8ct pu7ґ]J.ܔ,KJWVF.+.]wsJz5Dj2?-"#Tubb^ qyWL115S:6Q̞ZUb[ؿg!aMsPݣ8ֶ͆FfCrN9|ZkٻCTYUO_1Si lhRt8G{R4=!x ]]݇Zk 6dJ61Tj)f")AEw5I@Pd HHe#Rb 5в׮_2>@(jJI'>R@H0EBТ&Uu P>E 0n]>^D$)Rr\:B -jC5`P m,9 \h3Ͳ,cg:]EĊJ)T,DLn,|;'k2hVRrǕe ҍ[ZUU몰$j˚F?i^h1Q0 4ڒ Z׶-iJmә So$4Fժ&$Ʋy(6'3)+umrS؂"+h y,N\m`f9d&_Wd-mN׵~e||b,tw}kns0Fgye,+hMEosh̛,Ow'Om}UE-ٖ۹Ȏ|l߮5Lk *lW6-yΞxnb>uԅӒ}aS [m[71ޞ\LX=eY?00 Ț>ccRJI!2,--BPes4J)l&+S1UN+;҇)IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/muc_active.png000066400000000000000000000045561345766322700243240ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATXil\-3%;vx/qDj0 R8PPiJ~)Rh((1Hl!!E!@ 8ı3Kd ?@5m@::` .K]P04<4===m8 |&`@cS`╵+KJJzN>7H$၉3m?8:zahin55Ʀ*B[oT}}e3{z$X˲C<{[[{1Ʀ5oJKKv者Ҳ@FOM!p:tˣMG0ܮB1ౖ@cS!nǕ]T4m當O*Jnn. )++   bYerewږe:k|itÆK6ްqy0ԧT#ar9ٰo%T͙ofz:é҅o;NG@,).=usi UUܹB$EDpB ^x^?iq=wY˖,޹`La*ph˖m*OmJ"5fUUW*{^7T뺢8vVBP!Ӆg=ַ9POJmF,JBR!TۧBu*@-Ӵ{i**)DJfBr^r(d !&Ei"**0 T4mۣ ¤iL7NPY(3e!Ez !@rIi0cH$iGF&@%P(.TЉJN{AdE!'0) +e)CQRhgy̷,Ӵ"HSq0X<\jN^V!s;F #+4?~F:*DU>k::;^\cI0l`\ش!fp:|nc<6N ش9swt!vTilj8 x=P(ʜ XWwg@~Y _Weu1"}#ٖֈ];Gjm]t? je|gѿDJIeUqH$M7JodX,4?T]@Su#.ggI;8.M+r8Ot4|[OۙX,~`yheٮbaI% fe F(έAUK|϶3mLs 9v4 ,ۑrQR+Fi/6P@`(D0b2C1- ۶3߄/Mlvcژ>qx<6׵嫮 !khkJxt$ᘊ 8(]P4^Yt@ @Tοb͊b !¦[*'*J~uwۑ:P,Ӓؔ4.^hͶ/*"CICڶ>WήQ!*IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/muc_inactive.png000066400000000000000000000042751345766322700246510ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<:IDATXklWޙ]bc'>4Eu>4NP8n RV >PԂH !}D-y4iҦBi&k{z\>xnIIEtݙs9ιbXOZ40 $=4 t͉ ɩE0{D`?`CCc뎮;hiiYFJb4>>6wKo\xcbfYıǝO {$M{nZ33iACC}ys/]ysc;z|zztkmm7an~W_LMO'_( Uk!є]L<g45:?ߩT* oO"/ݻlYթ3gYrZSSSu0::Hjl6yDc:|s/1?(*P{Ͼݻo|Z{y=>Qͭ V#ȷUC17?\KX\,r͛^]mw˧Ϝ2%0hYc횞>oSc#_?C A $@ic D8rnSC?c|b< YNLb E$qPVxꩧZBݻya&i1V*gRH4MP੧ZԡC[E$A({ښ͵^:cۖ>VR߈ %$Zq}ضe+c<{&ڜh޽ x0ݱX,vg׮ _kG>T^% (tɣ9t4Q>+㑇QYU+_UWGFڵ1@;Np2.J{`7bb>3 (aCłg]Q]U$'o|c=@"H<6vld $_|Æi |ֱB#v< mW@ܶm-"ljoge$<#`tA6} Zk-m+ X]\O&G,ui߰~0MeJ~ C pQs]?Vz<ɒtIjk׀(DM% |ye0c&CADDQ]U44K/) d<c.@rd% BЈ(XA Bk 4Jм\d2K@fRcc"CCr VPZY\ O9himZK57 % {`| *'0¨,Kuajj* ²p2R$X|\:A}:^x mf&P2I}l^H'3{ǎXϛCC;ؼi5q]p]u[q1lݶ)ܡ,AX:;.@ c|A)EĎժRp`]{ܿsG.{i:g%0 όOLD@9 ێR"Zjl;OLN'ݽ;9=aʕ3'[]YQAkU^i~yBa2_NSeMf-z,'~͙/wlܺ+W.e,A\*KX;, j԰~}&\eU[oNotW`u/3<2%W%E ض͹0Jg4b4ba!1hf}<%|u/ܸ+/^8_(s\,/NsDؖX﬩)ixVjaYH-Ħr)XP4۠7Lc7Ύb~͋I9B9 FPZH.RW[t^(| ;8YJoSD8K3~gv=WE IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/not_in_roster.png000066400000000000000000000044531345766322700250650ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org<IDATX[lSG3qb;!$@@"Ji]5 ݮԪ{eJWBڋV E>Mժe(d$rqI>هsH='|1yځzNG{?<D8w \R 0W?8phx /Ķ'6⁹bFΞ=Szl%log{M?s۟/jۧG4~?8_fOuJk)n޼,7of֭tww DJIX(x_N0c1rpxWFΞt:m6DqsF nh4j9bI$ƶmN>ّ{{|>٭T*e1ccc&}'ؘ1D¤R)s98|zr~}-l۶y1“VJT T!%SSS޷wöm,}-}<,7]񒔲ï."J㌞8i% wwJJڤd֌8ǏJ(ïR6ឬ59~7, ͊+W2z$uBBX]ZysCRR''OrUffeY7^s0WxmcoOoKr!)Ӌ=z%)KEկ_Iɓ@1VHR5Ge1Hr!)z{z[6U{{m q)8R*f}% JA2F) %yAkvC`EIf}.x܋E`;4m{;Z DRe:e0OwLA\1Btdds55TUk}(B}X*٬,oc H&H$Jf)wJlu J!Ra((V!S*1S FKA$!m{!]\J6}u}zjCƜ6>Jp+JUK #Q}=AJWJ>lhؘ>}=|uz̽|11q1Yq*Nk{si!٢5ac((EN),."n!B,rJQP1l!$Tq*$o\MϧTjqbrNWGRm<34DD @AJG+u~)J"JmGAJ@D 6\c:z&&'REU^ Ʌt(\GWO))s?7O 7~rB: Ʌ? w1g}pge;c|{,FkOK?~[GBY i=3W}pHzX<@o/MLNvFc\{]CCB!jXU`t#P]CCǺuFcɉɉ%\jqŞ#㞟ߴ_ Nwi.[n3;?O\r"SPU~677%Xwlw2\SzJO; BO?p$\[歊c K%r_UjO9:X^Z_υD:wlL]ZͭܮO|+ +lhh\T]Եԕ+_.z9d, ZZZP(UU=Л9岹wo87?{N6i"Hsd Jl.k&v:S/IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/offline.png000066400000000000000000000047071345766322700236250ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< DIDATX[lsΙLfkʼnرHl(%Q^U jTԋRP5bDx@BAۻxݝa'ҊHrt~|8:߾{3@]p:R:i_ 1F3kl p35)8p|){ ^랭[zRiq޹Oϕ^}핳33g6{O !z'w mZ4>;DEEÇ|;F!w}.l4'O<R}j]n(t@ NF׍kRL> RA3M3ȁGKl==GKmee/D.mɳac %>~SUk}fEL+T^/\dyަWJ) Ҏ^)"tnL;]:RTONau;7nF[, dnn۶a \uA$4Xm4Ֆ9)B"e>^/`rDn+&/ kV&JN!`zzM^cah:ssumgZFp||+õ&/*pJ=]hDE>s (%/W4>seZ4 (" C $ Bv6nX9pڟ^|a x#Ro9q.%;Z ŇLRA9_|#Oct1ދ,𕍍)oQ1!Oߟe˧!PF1m4?;c4Z+ey4ϟ1Q7^>B1'9NpuMΞf8P0B(LA12Rad)(T:= WޤuC><pS/\{mm'!8|(@/^x,un D6z#ej$B4IӘRIZ m,un«F@0̥k\  T }{1ڐzKb4"N#zC`PDˬ$=gQcǏV%"F9L:zx ^ͱ&JiR`}Bbc4"J#c}BC[j-YXXcvt(@#R"u\-@P %6>"u)I"6&u)TR,PZ4HZ V{$.J)a@CZ8k}lC6h#@iibH]Dx$u1]Ҋr4"-X H9k}V7HND{}: F [)R! 1WH_@0!Z؈GXMTDG0YڬLA 2|Fh'+\_ (J+aj[|h([lM([g>\a@jJG>..a^|pXg{Aή_p\R6 O[;6 K2\1 j7Q_m?:yԓW/ھ uDc?S I W$MaM&4bh74yۗW/@.;;'wg=^K7_oFɹyb 1\yꂯr"uow ݉ksKvgԮ]UJQ)Ɣ*K-N00&ʖ ;#ƞ+ +/w/JozTݳ6R |s) MY*}fo4@"WtYk%[^?w;-o Ƿfs{ibĈT6V浚Y?бb\F;]kn 򘿻Y#Z-UkA\J+q. þt;II$f]s* @&~W5ook@iIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/32x32/requested.png000066400000000000000000000046051345766322700242010ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATX{\U?1sgtfgmi.X%"&j06M /"(&&7&&>bDO1DԚ@IJiJiy<{;-m!H#79{}~s|Z˵|wlˀN=ӻv\zlFёnMX`x x|"##~\rnqB+Zk<ϟ`*K/8y/v`m+ǥ=?7^z#W?q/ƘY];wضx6ww7'DXCe:W _PȦStwf] R()izC>boO;mR>?4nt#[w4gubu+0ҕvO/v\LoMLش}=_?>5SX!)rl^Ǎk{u \TAR(Vĩ2BH!,]$Wף &&K᫅B8qpHogMbDI", b836v}5k#^g)͖Ҟ%L"ڭ"F{p;_[arĥ,JeSK{{LѱPjJ]ϟj OivGSL) PLϺ8ϬbDO1DԚ@IJiJiy<{;-m!H#79{}~s|Z˵|wlˀN=ӻv\zlFёnMX`x x|"##~\rnqB+Zk<ϟ`*K/8y/v`m+ǥ=?7^z#W?q/ƘY];wضx6ww7'DXCe:W _PȦStwf] R()izC>boO;mR>?4nt#[w4gubu+0ҕvO/v\LoMLش}=_?>5SX!)rl^Ǎk{u \TAR(Vĩ2BH!,]$Wף &&K᫅B8qpHogMbDI", b836v}5k#^g)͖Ҟ%L"ڭ"F{p;_[arĥ,JeSK{{LѱPjJ]ϟj OivGSL) PLϺ8Ϭc||bPkގ%"ʕ/dvv6&3o1{)شqӘRjp= H& xy[{O:yq,۳xȇ>qZ炑C^ZRi[x@yOZמ;`O۳c g~vSJ:{x.Lp ?suZIBFS"l]?ɶkX31cL@{_yWߎ~Rk_x`rbr:G+nfşɳ_RmB+r3Y?#S;6B ŀSO |ir[?]Z=JR49vx%f+QFaHh6u3xxq" bۆ@!*PB.^8ſ˗Oo!G[;0.y/=_dGZ$yu{X5[ I/peL`0ڠBkQcT H##Q^e*1 {=*SWBJRoﶱ}u>E~OO)ꍘJu|y~v2=(E3"6eP&ךeR57bRG?(4 (Lj- rspeP J-k1Z2ٳڀ2?y{ J% #cJ_}၁h۶{oV±S81LDl3*sbB\`V Y1\&0Ag翙C/ةK8+߬*=۶msoO=^[ f 56 (cr@B!dQ&z[QܕEz3:SW~|V}:wh<ڃx@{<}Gܽf%)ĭB>{KnB;Vߵz`v~QG_=B5sL:+}9:#aAFJhcG+@y5,{QJbvWO#"WRlmy>?cǽQ뜯[YHTgxJk֯$B+k$͚sF!g%tovv4J+?z:뜏q00ch~]Xk…9*54[~F{0&9uDŽr͜p q9& Bs; JQJ=fcw@K΃O%K%C,)N̬uYbW.EQu1g=J zuO^1ZJh zIB+RvnӶOA)F!Q`YMĂM3pse=s3>Fp" QHfcg2=Ҵ 8I?>>^tk节4,T+dY&" B]ZiҲMV iIHS!M%Ą$h)vA ZbV[?:[`g!s""މqg+u3Q( A1:{Yl4G!5LqÉ`mZ[cSV" FA(шwܬXXSo$DaE;k;W6=^"csBWWV*ܨ1wAT`o zֈ2gGc=sduI@2_iXkh:)xWWxmۓ\|kEPJQ,$V(MK#qm\kFhb!ڈuAxAL'ΓZhƎz3aҤTL]YVQ@i AR +B+q}ZH?XkB^4u1ZkHRb}y5Ak%I7]7/Γ 0"" !{OjVIsY$BæCԛ)yD2DwuNBxuKVsj5}Kuډ,孽J:fc ׌h XRnTRϷYHTFh q ׌`!  ~̵X'ZK1 pqNR<&GAI)ҵ*J++HROifShĞF~KhʤZZϚP_?  C8ߙKE濷tN?}mf)3sjZR*-7n:c$G^p-hꌏ6Y7я1}7c,1P_4q4kUt쾽ޱy'~#Fk[ٳg*LtC2gϜݺ+׭}(?;7b,Sض m QnֵCLTh&flD;^=9˙d )QV 9%XYjBrCS8N`r{vl]RoU 8rZb+Fg7Lo9 (L] S&q3د\_lqzCSdgڠՅGw?Ъ;6o z4\p,oWO)dleՙipFj#H^G׎mJC=]]/#ߛKm̷ׅvx6o+o:u>]um RJ%yߟZ xYY%?\VgΧi&zVaǦ Ɔ{:jdJ%QKvlz̷&z4u3筵|Bm-\xbţ߿,"iPA4y-OYb ;6e!k7y/_tFVZ|v~hƻ7 pڍ篘R&.ߤѲ@浢N?- &{aO};OvKHl7O3k\Q-+(e-2BYCes=sO?|U3W^_Bsuց{} cbWk -SV Ƒ;?'/pܦ'U]+J| ]A{Eb@hy4 4`n0,Vꍆ}饣W^nN1-!9Zuցwo,HqLMb$Pyop( hUGB4qgN?~;yȷIJc(['rt.㢦rE.o"&Aešrev I1mDr=00MLU) ;gDZmLM]/,,O;5@Ke],8mQ|1Zzjp=~OrҬLIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/chat.png000066400000000000000000000103151345766322700231300ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<JIDATh՚iluwyI=6Zbɖ9Ė') ZGqE~( (6ݦ(P R+jSE#)l%@JP+)R3w釙H+ :[̹#Ǿ{;Jnط=N`+p"`^=xХ_M`#@e :nΝ?7???-13^8x;&o>cxtχydځy7؉ɉcǎ^9rxxC }fS˗g;_14GJ)މc3Oڭ[j$2{H]#o%`m6_oMBEwxK 2mz&wV9 ~a <t죿2o|jRS, @xEE!Ts780|Cgn?2=BXcp$$_S^x  al C!@I 'x}?-ԗvZZCVqpP*%$-;:G)AiC) O8 w%jOwYf9@Ո{.}ߘ}B)$ hpH\xwxp.9[k#[߰ 0Ffz/şB"?ۘxtK`퓟}w^P. c#wǞC* Tz-QR6{iA36%Xsg-$}7:x7?&tvwOk󡁑FSE^_cZDd' 9qk z#䍫%Z@\{yh˗/9ڕK|" C&JbiccWp@ h% P@ Z-PIK?srOPNg1'RzJ8~6RIJfd3 ߷Az r9 9q?>KVZxdx ;,k7a*1n0+̓W?.kfg&$#O%P ٳ֑AI5k,JJ==]={+%=J&6%$hu8̤l$; PYk|\ؘS.'͔2Yj'^P:( +7\L;kݕ˗f[17 pקuc꽥@+]G_ca<:MYڻD___E:~o,,L_{[/K .: xoZ7^jŬ8tiS)KQ.a2{ws'߾8P/&ۄRlvv|:I|Z)f:Wͭ l[3u⸂Szij JѼt6]cj8S&Xo0r{ܾy66-fp1撳֏^p+xp_<=<:82s^ .=ףp{5 CH&Ek a:/SLe*Bs7i8=N,=dz'_?z . 't_ou l+ol_>LtUDN ob2}AdMݽk_>)k]+.,D/8>IR~J1}/\6͆u CӵlR$TRsE)4lu-[xg{빶Mqo}ΌEB hz뼩hM @= gΜ=3뜃wsĢm0 6燆Vv=<2XX+BEΪ+(6"oʕ ˗٬Zmzju26v<;;ع7B䧾jvf5@V3J٥Qn˗=~zl2(IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/dnd.png000066400000000000000000000102411345766322700227540ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<IDATh՚yl}?rI\!JZiQ]$jn:c-EQ@QmEEz%MIdE=v:v$;-G%GruP%QH+9;̮ԉ<̛ݙ~{{#}{ZrCx/ݷg :-- px~^?3,>lkkk֮Y۶xssssLǀ?xg ݷ,@_k=woNoS ݷgxh}RJc40@Ka:ؘ!:!c怯L`=/@ۓDOҩSwuqN5\Z1c Vִww3aƍX LL+c_?y؝~n1q$9a;VT sBE!xCt\A8^$h4Ih1JGOJyd[,׏|럿q`*V}\>u uqI@ˤ/$da1&8#-hcAZ}{L𗿌Ik@E-[W^ukؾ8\Na䣏~jBTK%JsshO3z$qW )qeLđ2Nǩ_sL<ɳO?VR !xOmc-gQF8䶯:A[G;KVb**P~҂*Rq׆%+{ih7V-kܸ4њr~Vcm1 -]lq0F3vX+RP1ҳ( 5&T0D!Q:a {#Y׏ro[SD( &k:t?7'Ҍ=)Xލ린**UL P B*nABU"\7E8),TK=UnNcHөF̵,fHa##}.!NԒjCğ  4: 1uXmijɒJJc!^zHϣm48RdYRdR=ņAQU JDbǕ3iR^i#LgF@giR^t&y2jMZ*MXkHGWWwcJY(ߧ43q$I&M# iUGq,!گOIR&*!RDZ3yUr-A VEv4yU}?JwVe*Νu.t'Y.|[/^Ϣq(X۳yE.|[l=)4Y܉U oYNwVҋ׈5B{]cw=tm}~a֛CRS'Nԅ:0_HE^I/R86F0Wzpnwmm0ʹvǎ1~ׁ?uo_;/6s/k}A›7)p(~hjz|EZN5B!|&n ܅3/뼛nA)ݽkw}V ZccϝV*w%=lEk<0JRhZ frdxݕH78r7q3;)iAZu`rhj [ G."%E=.@қy]k?qjhK{p`AP\0XնtF] p:1A*hK}XUha-MV)rHMmAEL+wπ-q ^.\s z|5|Pg)\'&|LhpʣQļY8ՑT'{e:w`Iz8no;n3#ԉEiA Ι*o1q6BYx<Y?_9s!hwzkKlDRl^9ZfK"<ߥ.6+w.Yzg|)=/ ~5E$4/~$?%j!-?u'S5L9.y3lٛMePL3Y{OFv}dFJ z( `mdyWވ]GﱚeIx?O.p'Bm>At(nj8^}j Jlq8g7B*<^ ؄Lv.8#= '#qxut\@ZJ'c5ŃLjr`ƬLkޚX Κu>\&dbYj?}ntˬTyjǔ8%'xž. Zǂv%fͮ4``` fͮѨx=g:Ru{?ČÇk?c߁Qac`&!IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/invisible.png000066400000000000000000000074011345766322700241770ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<~IDAThZ[oWrΥ{n EɒVŖE۲ n{-C80~H O q<? !wmyWwJrH΅TUᐒm@8twUSUg8NLO-|zA`~a]vHVXpۧO_41'UUgΝUhe+7W,h~S_‰]^p#sG}l333ӨT*XR(uys+K/m 'O-^F/F/H}wz uD. CfE"F`~nZ^zE)u l( 7kG{p N- /x>x533(-mQJ)p@Q "hÿŹS~i 's>c Zs$ -H@TVV[D$_NyߞZMX<||\x{&F^O;fvԟ{}+w$sZ<ēiVBHlj:xak(1X_VM yꩧj6@p4!V"`5 `q BOi*;uE}Jxx0"ar0ESz#yG/މcGw U[6GB㵴 UD"HT]alcy,@Sكame@{x$1޿@Qo,jf(jUL K,AϙA,ժ/ěg 8`avGc|=tl8Ojq sR i%AbxbxmD2ڄ %`?!o,?dfJYqsI8tЌ0s^@B eBABR`N OIYQNz fVQ.I %$lbR{l?15U!"T81S`af$@!.?c2'T!SE I4AsȋB2BBdjz:$#ImQ,XEB x@(Ty!h%P*XKAa{M#HϢ`Ąm= ^`+A1VX$ι`c mZ)3 41ITZ iD  /sHBCR2Tq H*$V{V+]]]Sl6-11ڱ7"*Tj ` Brȴh6U F'AJOLC@p+fiWWW` !0q(,4 JiDQ>  zD1 x PJCT(15@4x챠ýPFCH,"33pobH|SA h(\Nv %ei?5cih(D+J$  %N(@2@'".Bk1+#"a,ZF=2#'ȉ0*rY 0zXw#FyrW QAVP]%w2AB(dYeғmJK"ż$yդT`dSvJ)ňYFE]B 3KVl=YVhV. " D'8Op`._ V cokoW֝KMb. ?'nvzDn x91 m%`vz  Zh0TN@`vzjcm'u9 {AGW{KokzH8m6jB XXcj4qh4jS& a$hԦphMX8OF;ZQ׮&1[8x‰kk~Q7_1`٢׍$8 W`gjZE=!MR(Q XHc1s u:lmm5pl.׮]>;o~]yh3g^ ` X֨Wj1+IV p|!GHIH<7ڠ;[VLϞ;Fmklr$& EbI  )5\@=zmUʝeҬnΞ; /f~؟( >{l}}xF{iS$lԦa$Ӛ"ڠ:6 E~:] $[Mm$2%:nZ|}1+q@qRn6|mvb$@c-F@/@/R0֢T6Elpy :[YY\Gh@\x?s+_oUdo_I*&y%׶&K3`X_]]}[,^۾rI:N/Ϭ21ρ|kLOttRA5;>{'erxқCt:Nt;ž`?{45(ɒ#&&"ɲs9ֲ mmDnjfffGl64MMvEA^v;h4*w;ԟhU&Vw WH\&O t IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/muc_active.png000066400000000000000000000077571345766322700243500ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<lIDATh՚{p[՝?\I,YbHB  Y[1lGn;AC;ngalw! !љ6C@ @ @! ?%Yu9gW;YZ3}u9wGçAma:cԧ$hh[\ U@8cXwvlyG Vl3͛7ZXp^FGFClVpؽcΞ?,@{G[pK,Y4/F\s?zGMx4ضcOEy@  >7.^rU>Ɓ72<2DTڍpiUXz5h:z=G~7'1@ю;O}l;V7/o.K}q4 cw?KS,FjcJho`Ӧ?faBx |_~0xmW֯曾,1𣏈RH!Bb`Ak6/ME8|j;/}pwl߹[;n[v._j]~ a ,)BZV4_@HR$IN>Mg F --͗nWBH+?mG1YbN<ޱ4>IrL&OZ!_y+W^H4RW& zTjG+RaP2ۏӷ抉Yxͽ@W;nnw_HeXwlX`RL&z@ڀn|3PJ!-d<ԓAIaۀƥKF| 95꼏ݏ>RPQ_ Yg%)ׯ*B!`0lp^Km{²,`pw.buuc\/T. $>doc$AHwc F0HIbo(Bǽ[B&E)m}Qt&m˽f2FviMz5@ ೝ)k3.[ۈ\I0(][Ȟ!H#{D4Owme|J+ X!jv=cΔ7\0o˅,_\m{f3!5y3][84kN!.xpCLq(ڲkP! F|ysLz:JCGYƸ%M7^x!'Os/.@BJ7Pno`v)BП<+=OС]^xa(ۄJCX>T{y3/hYR2?XX4((_xi qE DBP/֜N.F2}`g[}ϲb%eL V/o`M"5 VZVTLzWhh8!jֿbM6Z[=,sHlZnhPcIPjX6b{CEi#E1Rhoȗ} $(̻|V`&1,0H*Jk Kܬ[p7Y ,6*Jk ۧ@0d0y=Axkc=SJP8/f PϲRJgn,⦦bB0{[H雖UiU!+ YMMX 1΢>~_w#A<6(ːrٙ|5 MGa! J xŐu|2aC[#( !@9ڔ@{G[X>"Oim'+S$\h| 0 Ox>*2XS=#ͪf*W3y"DdYNV*t$o>U(ZOf8uzt:j/mP] 3CS䂞y9 ^d%BiRF+]'QD2ik5Z8~6ǻH!,k:" __Qb-_Kx՜2tA ջNJ,iaY> @-N$tTz\*R#pY}:6F"t^1!z]Nl=l Mfƛo+"Jkm&&&od3xDR9J756,߮R??|Z@.6#ײżty7_yp}ɪr99BvW7v9+_ƥwϋ'/H +owg;X2ͬk ÎR;Ϸ#_^T*̝<[,\ﲬ9Tor|ͳ_Vu)7|wgn&&&.FI'JFFSL8wZڳ |ٴYt.Biٝ|[gvnlViJ9&Lvs|d|]>BYԬjʖps壏16jamTŪ&29ޝvlѶ']HZRJjkndڽtѷ8?Bc"U^DS96Oy'v/9BxR)m::Gs̳Wڎm,XPE?gNU^̢ʋ?>m}ePU*LǏmo9qwl9lΞs'I/=]*n톸m7Nk 3@δ'z|*_d:jN~hieym]ZiswGrmgΝ%2rSnYS~wz?pja mr8qd7\6pI#rضM(:D2ɫ^K`Ysmr9b;uc 3fZ**i308@Oo?}70@oo?1P^^N},F}XRF}*yWח}_2b۶9v`W^[/޾~z{Y,ӺjEVdYuщd2a,XV?7ER *KY0`qx 0lVR GYRLII =or`0X4P+eEO aFSPej~eŤ;w:֣##RqY[W_zRB03Ҽc~Eg>V"H X^/)L.SD"7>>d2?>S)Ivt/ͤ?O ?Osn=Gu싇IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/muc_inactive.png000066400000000000000000000073601345766322700246650ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<mIDATh՚{l}?3wH,G$"eSr-ɲbK 4h$HEOZȟ$[K 8ذʖ,|IHqwgT%v~3sAm5DW/byhh p7 u@tk0 g]?sjmMa`'X,fZ*lxkb ɗFYWS@GCߺ=|kqS։N2SŒ),%i\Xbd\WFҚDCw^%4cGc<'7ĒG 'B u;>ҲEMM{ʶmwPJc׾ 0ƷT.˙31==Z)Cm*į:/El_w˃< 06>y⩣eFٷw:DŽ. lOrԫ8RLӇu.ӿyߝ0;%0nME)mI./ $5|{ O`rf1`GxmKCOdyxxmכh>tk@K ysJ9.w!M vKbNaBcs\B#,GCQ*x%k2]1޼9zwVLS"Qz5'_y7GJQ9Q/ B*A,&R,xfikSҟ3ԩW^=Du"4%% e2)daj non))%0a2HV#´T%B#p{s V)dmҲeY!Vkb"lmmEHcRA -*>kQ,R-(ڊ@8zcFkvrC*;oڸs[+eΎrRe)f}|2(vp#}R&QS"-K(tv*/,KaJ"gaJY߄[N%.vc\ٰaz,1 -KD"Ft:ZWbff!ɚ$RZa5k =@/h[&t3_,Tu"YD rڤ(mh[TVZi+8Cmmz0{@k"d*.K} ,yބ "i"׮zEҩT̴,A+R(u.7C0ǚ& Ӧ2 aY%"FИ ̷ T "H]AJl*(Ui$ZW< GH!, )$B Fb>teA h4!%,!$ccT'⠅ֹ| 䟐3=wR#)Ir>>67=wFG'J*i4. B#Ep";R.J[q QX(3}l6 ͍Qқ;cspgvo L6g3 7K$@i<sNPZUhZ )X2[(G`ْ=;v_Q3S.<{8e :+6bG_bE=Ȓ[7bYKͨ|`XN9.ߏPEW1VqƛIq ]nܴuu];oj EQtqxl2dXqſ6pܱVڜɩIk±---_}}go+qҥ,K,c{-[qp]D"qruKu]٫׮?)MW|m:# 03;g{[ ۲7߼5ٴm'^)^-9r:SRع=p:::ڥ8/÷\B=KHعx6H`Uߪs[1gGjృ?J`n`v{?{RFunT*\|%KL&^?OW8&c_w`B1A@Ԉ !%RRJd^kE־K!X,dPX,2==-1 lX۲Yehqy]w(RBW#pR.]Rb5OR6څ )%ǎGT( J%⮻q apuj'XB){ )I !AXup*wBިaR OكR|>/|]&̯]@ܒN5kvcqa~ $P,uz WJuEm4 ABm#$?zI>y c k֬JpKu]߹)T*&V=݋))$ZRjtC.p-$_5QB$l{J>w^UJ)n0߱Wd.]J<…GEYFQ&M9"זܦ5=I GR0*^3 |.]jX|s q,߿?6*C͔$HIh(l!gB@o4I5䔔 v$J!ؿ?35uqZ~C0G`3[rZkS(LJ8} 3R7͸ģ^LF$}]KJ>날^\e֌3xG0)f-F5krKҀJ)g%\RY1Q"$"`I`cUĖ]^?Oq`Բx#\Do988R c]dxLk͕)ĉQψy!^s<ʯ4Xj l^s@CCC=q$)&1SmYRMbabrb.gUBM.lCI qc#ER oc1O$0Yubr_)T`6%E*r@FN.k2VG\꺡3FuvLc8Rp"yd&e IcК8,t&㧩ZJ!fh'꺔e|íV1g͒h룳sI\kmʕPJ1911[>X.Fe-rA@ddqch~8on s( 6&'&PJQtv.GiI@)F YZC59IgC 0"Ҽ`FfjPA:Jە$@>?V18VJєj =[ ]*q1)-B#`JZy|TnܨͦTJ)JRF;fB <.[|_<)m*RRqۦ*=U*a5Գld!A\_yP*X@)Em6F+xB AEJ^hn*2W{~R SzD %ZRw8իW]minmJ)?^FQuYRPOIb~ҾU)QrZ,dͭMZc^6bx+ gaG, B𞔸Q};P{;F joTܓ_ M;#lu#uЈF >mtf+Zk:2ZZ[<2:_HҢ*%)~ m휮)V{^}yhL5K: įO1Kh8tT,V-:6m8/T>mZK _J*%C$,j4$H+J&Cė_ZiJϋH6m$ҋ[e٪X*zMvzMCtb(z{Iu ~$j$x-B it)8ڲx7m('IJAP'N%=EйFs <_~butK{%M:mF7EkuIpkƵrm$N43$7 tɦtK{/x1ZG ڟT*ǏZ+dװ"č4ىs)UzjА.fM).;h#)0IO6{ DFrY]o.]vR}%V]C&ƓXD||cB&^ p"D,^OJ2֮AJMV;xWߟj<@tRJ}?X/WUڰvKRi&s¼;lf5oHǍcӶMUJڗ.e6Ug/WJiٹ =|0pq//hueeCC"7w"j =?+ eˍ!\H]Z0ppk`?us߸ui_OoFcx̱%N]L)sʥD,2shc4ZkRMБ`guvsKY6wH֛f{zLw[`(y|2`RQ$t` b{%kV7_3 P*q@~'dutwOo{m˦TL$6뺪T.h2j,,T_6$%wv>af4pb{ =uF-wf1x/:| @xc1P3K8tza`/й򻖖p`@KOoo#7JΟofx x~k wM~vzcn_~/X <3|B #@f͚ kRw3hr7?'̎3l =u !V{<. xY[{ϝ?7>}*" <5|įLwO-=;-8E#J3[J. @}JFJF9w^<~<|蛿4CП oo)c Ιx.]?~3oafz(*UK{:۸g= }`~(:k뿜 wGx2?%Xn}1&K/lfQ,e5i9z>=*B.WkׯM嗟:3~'H -Op׆5QQDGuQJ!DI4ԽO&7ZKWW?)vڅב::WIw E6>Dag[J+RZ#Bʌ% oSXp%1k-X}Q>O!-'/ۿgOnN^4{>=҂(D~+J*t^+R+"L= Z{9FGGH>g!]ry߯bJ6wa(.!(J͑~##(Z^ %JkiFir@;=2O?Mb(J!ā0ޙ@0|A033- cӧN#D\R@L#BkLTwi_Z! ck-33"1 a' w$m>R(;YgjjJc8uǎ#R J.[M+R2LJ Mww;A(=dn֗Lرc:u c SSS{Ν+ ! ;À|3ORrLiaNJW]/Jgq\˳kh+6tӳ:J27O1::i(4Jyp5m-yg?ɰ cZÉ'DJZ/6RP2rwO?Awl8RY`p&~tt3K#J(`rb'N`a|\F w{PG0r4gJd2ʤ%[m`;BcXJBRI0bZB>6N^Grqca{:35}9?;[9._|fLR!6v=[LbcC\Zl0YW{ݴ^ȚƐy._s wޕYW̴rfLZT"H-[? 5[փXa!I,Il 8!ό1XxAy!Rzrf Ygf35U\.pα0?/;R DsJ(֚]:T"IbƑ$$[b299Kzw"[tspΑ傕QP__{+qZR"Eus446<ĉA)Q8Im(z5ĉɼ`@>9Si"󺳪wxRR륥̲aoooRK$I".da0 08K,&1bbKRGd6}&1b#Pȼ6!I161D {{{Ⴭ,ٕsryITeKX\>'TC#mRR&qTC'H)ϑ pXձ pή\Bf9筵>cJܸqvIYF tb!B.@t2>Rұ@ZJJczzRi\.;5xi``bb. Ca$I`zjFZ ڐR(G #@$x όH!NLy*aOL+R*j!c,a:w >rtx|VY 4Z0q G*...qXTZWZ[[^gmi)"Nby8Kq@kPA@hĤzTtNCزy3e5T* J,AV17ֺEC嫭S 7658c,}HMwT 0$dQ\XXXbnv"ӳS*R!I [\R*xj/%KcSsh%*3o_\tֺZCtbI֫aNJݸZ93HBTD[T9B[+:Z}4Ll,)ݿk 퉳ֽ}rq%*9=akڻy:;hjnHd)k WGϣ{N41i3iިG?[ t@\5!EԎ&:;pγlFNOĬ|K.RZ,MO{ s!%靚yFihS8Sdrj2]tVhJ\I5SSO%GH{Ҿ)Mid.]8LT3+4^xarppך7ơ?;[="!dJ%hb``0۶ĕJLl~|㍟r4^JIss3lYKY/]0++%<^Q4]YP |W"1z/ccc,"h)2xwzmUr ᬥն4(J^I3WA :|𡞽{](͆?x6=SΟ?퇖Y2zε]twemWZ65>-&n]Nt9[28ƃijl_{G7NM#G3WNmܶ}gO_hؾm;Rl'pW +]׳g.=V()Hϵ==l߶k ,5E +'x4J*Yq1}$Ib{:7uU޽kHeyzZ*Zݻ`e]_WsS1Ibq 煪^x{h镓?svL4޵>X1\EBdT4IM~>B]{O{Oشc9^9kWGKgn o lr񼐒bȕ+T*WX]6PӼiN:[rlGP;Ǻ]{%sO}{}w]An)@p-m7/v\xcٓZqrbc71,Y!6A]5i>ǖ{7O\pn'Hk.D1x`ah]J)Yf],\ HefXXZ UpY͠Ӑ2јo<~ͳE~mxh߷z 0Wlvcc~'i1H\Vrq4əZ,.-W_=966vsĴD'd-[rAlѶ{&<Ziii]h)jJۋϜ}l9eoUe0 .kZ;g1."319tbXܿ;?5Zˆ5@EfqieS;]/_m:IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/online.png000066400000000000000000000103431345766322700234760ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<`IDATh՚ۏ]W}?9g̙$n!@*-<*U#RJHUxKi3u-!q%$&\L'N2c9>}g#Hk}]ۿUb[\::ǎ7ދ~ԻA`q}a`nKM` 8dk߿5ť3gS׊Ţ586>^X_^[t:S3׀O/;~ ,.4|{?] FFFʅB!ճn7V~uzg?g_/ }cKG9G\.??pextj[֋/p??5MG&Ȉt5KG3~d}΁B}!!B@4PJEhjuy^r"cǯ /\˿҇FFF *K7 P1 m2Zk@j_~t |5ť xh?gWWV_p)j m1=̡?̮;2K&hms~M|@>_UJ/.=v瑏}lE>1^}gN>IYGUeQ?@@$6T?ʽG+Jau'=~&:Kܒ@_X\j/]z?&U6(1JhQ(zR AA^ŧ?Xy"7o#{> q(5_<1 FgRDil}zsƋjCG@+#-N=?ϬM쿽;[X1`|峏ѝmG=4?7_vl;/G1jqqnmM[֋_A) mbDm 6/Ldw^[z yH\vӶRZť1 x$k-?C{+CsN(x2]x:iM||so{(4./IJK_=vKylpT2G||^I=ϾdyԓEo `d ccLY:?gцέhz佗#G>T*+gɇ?5DZM]W x~9ӰU( a3 [c" w,wrc%678}4I@Phe$fМx~{B)Yw8|SO~;rt> pT Vqgج`,r kX|`2'hXe=ŇNҰ!x٭a4y'l=֌ gr7 ~ۿ(=/#A3έ`l杌fյsNҰ^|c{7D㚱 3_Bir<6(%^JOq>!K}~O{fb[2K:,m4JÙ/q8Ⱦ}#{&ʃ} sa7bb@09>Ed,B;\Hq>yGRR;r9m'Յ_[{ʃ~=/4E(5n u\Y((H$ňƋ‰"h{/)")(˽hɈ(Q45OA^1*"(ͳp,"8t16mk( l +DE(A)@ټp$%(ؘb.Z,D1 >R* kkkttВ>*%Jfg e2z'7q( hIH(h1 T}*%9#@*TֆB@ EA!AaHPl6S. јT*vmm `lE&^/"J\ۺ86 3G&^"4hWBC>;Ґ"r:kZJ w77h'Mb[+ee z=AQ, BT+e*Q(;1&%cI|+DA@Ps H!'Wu)oÀ t]ZkzJ$쫺X U9 |xcqhhԵ>r">hTPą.J:Ad}LMJ86RP hestt]v`@4Jb~ 뿤Ѫ!"VV{OQOdFOBIt.&١j}rW)juˤCdl&/[$2VB6ΑyRTّIxHm@F4 {%M$I"dY@VHPw|Hxm hG*-(ˁx:tBh- 6Tר']i -<KŤ"hw˾f&!EIP:{N\rH /y٠<,*17q/" M$ 4s-D%MPi k#Qy[7PZ139G$w^\T# /n9rSS T zSNuYiڈZfG«R:tp*)EfGڈY e@k@)$dŋ[-^[__j4@ZUj&jkpx^8޽Twcw/QOQKSM`hx  Z-ֻW '(nTklZlx ջ:8^]8IUQpșh M>1-~A$IǷxgs+ɀK>uUگF RJu\xB+xWOZm۩rŶMj#y$\Rj'=Mi" uKz]'x}mwʲGxl:TSn髧_eޑZ\:W+ ZqʜA]?ɥKydʎg1Val.Yk_b{fR'vanQad}gMH^~,c_B?)6/>y-F )CA+iVi[T \[O6ALȤa4cy*.[[dH OH8y4یZwabp:W>1d2i>GԚ\4Mɟ_*!Y)lK._:sW[nCW;w\effv %.6ha#ZrX]PW4q]@\JlR;%K{ʕˍnzݻv懵*xl uafXCL}<A"e5EQ e𠫣vu*)%%=zmeuq%  URh\/.U[#f_&F% |>#Zޘ}S7Nǿz}+Xb#ȧbݥ={#e"0>'7psP]lP;$THܐcp.|\Z#cv]/ ,V$tbR;:vYY]igS2MD޶]*h\T8MIZLvo__ZQld5K$iQV˟=~ /Op2IENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/requested.png000066400000000000000000000103531345766322700242140ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<hIDATh՚{]G}?3sιw^n!S5jU,B" ?JϴTHUZ,"$N 1vkw׻c||bPkގ%"ʕ/dvv6&3o1{)شqӘRjp= H& xy[{O:yq,۳xȇ>qZ炑C^ZRi[x@yOZמ;`O۳c g~vSJ:{x.Lp ?suZIBFS"l]?ɶkX31cL@{_yWߎ~Rk_x`rbr:G+nfşɳ_RmB+r3Y?#S;6B ŀSO |ir[?]Z=JR49vx%f+QFaHh6u3xxq" bۆ@!*PB.^8ſ˗Oo!G[;0.y/=_dGZ$yu{X5[ I/peL`0ڠBkQcT H##Q^e*1 {=*SWBJRoﶱ}u>E~OO)ꍘJu|y~v2=(E3"6eP&ךeR57bRG?(4 (Lj- rspeP J-k1Z2ٳڀ2?y{ J% #cJ_}၁h۶{oV±S81LDl3*sbB\`V Y1\&0Ag翙C/ةK8+߬*=۶msoO=^[ f 56 (cr@B!dQ&z[QܕEz3:SW~|V}:wh<ڃx@{<}Gܽf%)ĭB>{KnB;Vߵz`v~QG_=B5sL:+}9:#aAFJhcG+@y5,{QJbvWO#"WRlmy>?cǽQ뜯[YHTgxJk֯$B+k$͚sF!g%tovv4J+?z:뜏q00ch~]Xk…9*54[~F{0&9uDŽr͜p q9& Bs; JQJ=fcw@K΃O%K%C,)N̬uYbW.EQu1g=J zuO^1ZJh zIB+RvnӶOA)F!Q`YMĂM3pse=s3>Fp" QHfcg2=Ҵ 8I?>>^tk节4,T+dY&" B]ZiҲMV iIHS!M%Ą$h)vA ZbV[?:[`g!s""މqg+u3Q( A1:{Yl4G!5LqÉ`mZ[cSV" FA(шwܬXXSo$DaE;k;W6=^"csBWWV*ܨ1wAT`o zֈ2gGc=sduI@2_iXkh:)xWWxmۓ\|kEPJQ,$V(MK#qm\kFhb!ڈuAxAL'ΓZhƎz3aҤTL]YVQ@i AR +B+q}ZH?XkB^4u1ZkHRb}y5Ak%I7]7/Γ 0"" !{OjVIsY$BæCԛ)yD2DwuNBxuKVsj5}Kuډ,孽J:fc ׌h XRnTRϷYHTFh q ׌`!  ~̵X'ZK1 pqNR<&GAI)ҵ*J++HROifShĞF~KhʤZZϚP_?  C8ߙKE濷tN?}mf)3sjZR*-7n:c$G^p-hꌏ6Y7я1}7c,1P_4q4kUt쾽ޱy'~#Fk[ٳg*LtC2gϜݺ+׭}(?;7b,Sض m QnֵCLTh&flD;^=9˙d )QV 9%XYjBrCS8N`r{vl]RoU 8rZb+Fg7Lo9 (L] S&q3د\_lqzCSdgڠՅGw?Ъ;6o z4\p,oWO)dleՙipFj#H^G׎mJC=]]/#ߛKm̷ׅvx6o+o:u>]um RJ%yߟZ xYY%?\VgΧi&zVaǦ Ɔ{:jdJ%QKvlz̷&z4u3筵|Bm-\xbţ߿,"iPA4y-OYb ;6e!k7y/_tFVZ|v~hƻ7 pڍ篘R&.ߤѲ@浢N?- &{aO};OvKHl7O3k\Q-+(e-2BYCes=sO?|U3W^_Bsuց{} cbWk -SV Ƒ;?'/pܦ'U]+J| ]A{Eb@hy4 4`n0,Vꍆ}饣W^nN1-!9Zuցwo,HqLMb$Pyop( hUGB4qgN?~;yȷIJc(['rt.㢦rE.o"&Aešrev I1mDr=00MLU) ;gDZmLM]/,,O;5@Ke],8mQ|1Zzjp=~OrҬLIENDB`gajim-gajim-1.1.3/gajim/data/iconsets/wroop/48x48/xa.png000066400000000000000000000103531345766322700226230ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs))"ߌtEXtSoftwarewww.inkscape.org<hIDATh՚{]G}?3sιw^n!S5jU,B" ?JϴTHUZ,"$N 1vkw׻c||bPkގ%"ʕ/dvv6&3o1{)شqӘRjp= H& xy[{O:yq,۳xȇ>qZ炑C^ZRi[x@yOZמ;`O۳c g~vSJ:{x.Lp ?suZIBFS"l]?ɶkX31cL@{_yWߎ~Rk_x`rbr:G+nfşɳ_RmB+r3Y?#S;6B ŀSO |ir[?]Z=JR49vx%f+QFaHh6u3xxq" bۆ@!*PB.^8ſ˗Oo!G[;0.y/=_dGZ$yu{X5[ I/peL`0ڠBkQcT H##Q^e*1 {=*SWBJRoﶱ}u>E~OO)ꍘJu|y~v2=(E3"6eP&ךeR57bRG?(4 (Lj- rspeP J-k1Z2ٳڀ2?y{ J% #cJ_}၁h۶{oV±S81LDl3*sbB\`V Y1\&0Ag翙C/ةK8+߬*=۶msoO=^[ f 56 (cr@B!dQ&z[QܕEz3:SW~|V}:wh<ڃx@{<}Gܽf%)ĭB>{KnB;Vߵz`v~QG_=B5sL:+}9:#aAFJhcG+@y5,{QJbvWO#"WRlmy>?cǽQ뜯[YHTgxJk֯$B+k$͚sF!g%tovv4J+?z:뜏q00ch~]Xk…9*54[~F{0&9uDŽr͜p q9& Bs; JQJ=fcw@K΃O%K%C,)N̬uYbW.EQu1g=J zuO^1ZJh zIB+RvnӶOA)F!Q`YMĂM3pse=s3>Fp" QHfcg2=Ҵ 8I?>>^tk节4,T+dY&" B]ZiҲMV iIHS!M%Ą$h)vA ZbV[?:[`g!s""މqg+u3Q( A1:{Yl4G!5LqÉ`mZ[cSV" FA(шwܬXXSo$DaE;k;W6=^"csBWWV*ܨ1wAT`o zֈ2gGc=sduI@2_iXkh:)xWWxmۓ\|kEPJQ,$V(MK#qm\kFhb!ڈuAxAL'ΓZhƎz3aҤTL]YVQ@i AR +B+q}ZH?XkB^4u1ZkHRb}y5Ak%I7]7/Γ 0"" !{OjVIsY$BæCԛ)yD2DwuNBxuKVsj5}Kuډ,孽J:fc ׌h XRnTRϷYHTFh q ׌`!  ~̵X'ZK1 pqNR<&GAI)ҵ*J++HROifShĞF~KhʤZZϚP_?  C8ߙKE濷tN?}mf)3sjZR*-7n:c$G^p-hꌏ6Y7я1}7c,1P_4q4kUt쾽ޱy'~#Fk[ٳg*LtC2gϜݺ+׭}(?;7b,Sض m QnֵCLTh&flD;^=9˙d )QV 9%XYjBrCS8N`r{vl]RoU 8rZb+Fg7Lo9 (L] S&q3د\_lqzCSdgڠՅGw?Ъ;6o z4\p,oWO)dleՙipFj#H^G׎mJC=]]/#ߛKm̷ׅvx6o+o:u>]um RJ%yߟZ xYY%?\VgΧi&zVaǦ Ɔ{:jdJ%QKvlz̷&z4u3筵|Bm-\xbţ߿,"iPA4y-OYb ;6e!k7y/_tFVZ|v~hƻ7 pڍ篘R&.ߤѲ@浢N?- &{aO};OvKHl7O3k\Q-+(e-2BYCes=sO?|U3W^_Bsuց{} cbWk -SV Ƒ;?'/pܦ'U]+J| ]A{Eb@hy4 4`n0,Vꍆ}饣W^nN1-!9Zuցwo,HqLMb$Pyop( hUGB4qgN?~;yȷIJc(['rt.㢦rE.o"&Aešrev I1mDr=00MLU) ;gDZmLM]/,,O;5@Ke],8mQ|1Zzjp=~OrҬLIENDB`gajim-gajim-1.1.3/gajim/data/moods/000077500000000000000000000000001345766322700170305ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/moods/default/000077500000000000000000000000001345766322700204545ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/moods/default/afraid.png000066400000000000000000000017301345766322700224110ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:15:08 +0300J͡tIME  ;2 pHYs  d_gAMA a0IDATx]]LUoik[E&ƸD fX$BMt3[Qcb2 Dfl DGe#58RJ[@?'< oP CؽaGKi`>\sHӴȒkROTWUt/LY?Iz>sa+m^xiedԗ<+?^fsߔ{aIFg矾+BB FмϤ/fu-٥U[Q^± XS v`YRʗ 3c@A ]׾]*-EW|7',lU7Z*|\v_4=E=+ q ^v ?0s#Y/j8rA&,Tos2;-w#BrpACM+te3 cð-&7!WT2tSȯ<#D"|^_SrW||;V'LfI%BhkH&b1 @pȢ3cVy0O$x BPi ӦtB-)AV'g3?=ū{d7to9rB~FWu"3>͏*R1<]&(kgX=lS8U8Z6 h\gG^kwW$H{dW{J 5 k&o,87Nn[EqxJ97u Կxɒ%˩e%#[J_~˃َ]g*%?>늷bokņV[@å)_GgNdNiWhLǀhjz(͌Pi4Zp6/^=¥<~9W=4+D呝NmMV(j9]uXU\:#1S=}ޏC3 p*um.}CB :Su_Oa * @}B1Vy[d%yH#%fg)L33Y}AU|[XBꩱrɍ &U$nX%HJ_ 1^L3 EnJ~lb,6 FɓWxXUv% Ch8>(q!idU6Ȉntmі>?Orr<( CFev+u:imctKI&aCU~}-%;rotW\ ZJ:)R/rzv,qUDe6d{HdHRxɘq^n'/spZ̜Y05sɘM:~6V+4Os'R"+5b0l/>)X"FAL&x%R227XhAw94\%fl6v;} PJW4 Yy=_T#<_']eU×\^KӸ/bM46$wj!㕃y;EY:4j+jh"/T1S֣1L1d\+v in{]M65O0K#‘io'_3̖IBC0v *׺i;1^%2:zx)Tb!AEQ&BCZQQCV`Vd?nYj3;{;#x9s=ֶDQ,Q$CDՎª3lY.ΐe{ c9?]׻t0-DRtŊ4ڎlY$IxݻTvl k"#&N2;W36( с\u<.ƚ,[sjgo/ FQ__׋9qPe)ЛXM FGG1. aHNJB ؈͚dRXvʙ*E@---E/ɮH(h\X1O"X/.K.Q<Ȼ #j!fCݎ 3դ |ua1D&q.**8D  -/r)i;>s|q0V7S\+WZiZ(lup/T$=i;IҺp TWWv#&& 柜N)~ /=f[,On~+?OLLjN+{)=HN9|{WvnSUNg;0ORE9xs:ʦq/P,$IRUuCłYJtpa^shZث(40f-FtC6)|M)IE6AI_ՠy0yCL֞NIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/annoyed.png000066400000000000000000000016341345766322700226230ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  Q pHYs  d_gAMA aIDATxuSmHQ~n-KӚVkjidQhiA}B_}-Zԏ( BEX Jf͚:tnF{9 ܘX)کaX;aԀ}r3V[ķ`TF'yU6ϰo`!D}W)_󿑗aw$^:vk77[=Tu!4[j2F)-|9FP&PP8Q& vg@I x~ZT0rX̦5DH!m^L9u0jer:>p8Ѕ'O]8~v7Z%IR2(ˆ J̕p9tam@O_ ߋ;xvy@9F$7h@i+/f㺡FC99dckp+s%Nby k1"=6+Le,ϳRijiՅO=-_N PB555QѶB[{)ւ+*f.K*v.æR9*۽e o3*EJ%kzPD&"Ww m6)fȾo:q USL)dYQ2~86r!a޿CW-t""ZԽ/ܘePIA;+q%JYqv_5`)!^xF՟:1}S]vIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/anxious.png000066400000000000000000000016651345766322700226600ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  CYV pHYs  d_gAMA a IDATxuLu_B\0: pf[ZD*-6+e_m?pf&4iL~txqsΙl}}~| φݕEuL43Rg`pqw]^^c71rHi!HmF̭ .>^.g.ט4s|"F>,@֯EfFN0MoP9/w%,5ZHG7ϕ^k\ dQ$sKΥjI|WG+qɩPE'Y+Y#n璑 rs%{Z\z#oo\#5G7En.w#2Kj(hYJSXó {g-\i{w"mA~ablh[du+pGuWڌ|~0TOѭ蘝VXW F[:L6iv,mNP͐ UsCc S\x˝p=b38d$)9$i Rca:g?oʹ$$IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/aroused.png000066400000000000000000000016741345766322700226340ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME   az pHYs  d_gAMA aIDATxeklQo*ڍ1Ef6cY# BsYF\'H Â$XHqdVי&5UVksyĬf|LkhA#8eJQ@2ujjewbCns24*ͳ҅6A r LGGXZX? PIJNN -yL. ōhC (t3P5Dꔽdo;=N*.ZCF*ܼ.;PGC"(RYWV_XZ84qX:Aݝt p̩9$ LAa$Ѿ4l"C?[Yi1}duy=EL< YWv ş ,uqa`o >у/6mҠRHJo$I s:WaGQJ@EyYRq '*`'G cKA, \mxR{Ym>!bŝ*8|SU hh`H% ##l͍%]⦹O=/V; `‘<)aJ۔Vx|~' x|Wr@HG.u>3/X5(ʷVFlj]5쪳J5T)sl+V>wR]!Ct&t l%?Nәl<~.]#E4-&DGy,J*LR 9`'hP/Tx&?CX%VgP}Jh\裄 ̔AYK(**si*-ҩxRk(ACMny6MlF#)y+lՂBJYi3Vm)TsLN*=qjfy3hicGӽ[uc[4?;f1虠:m,ZDm˖Tf9n,9dh&jB c:,5yR3R83jd PY}ڸ%8O}VC9RO l\0H֪~7Y 8|Xeb⏜)1O.baS !;0=78*{xFC1dp&1vO(MfuߋM1sRVvn;%H_"S#K?=2ӡ槗1x@vc~*[/Vd@ vEA,7GFp-cD^'zMF&pzGz h (R0/*dc o8}H$ R IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/brave.png000066400000000000000000000016431345766322700222650ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  &g pHYs  d_gAMA aIDATxu}Le?}+z W-1­lҶsM6rp7],ĭez뢷{y3ʳ}w9{~yyI[,9dZ\`#C$ŹT)clUi# +yb/ZSuAhU573k< 2eR1HYNHtfk:XR%BΖe d38rDf6j~ dcYzi]u\7[yxSdFcLNn\C$moYOv lwդ?R JxJeN+u\TÕUWJ)o㇎QVDx8]t'ƿDڻHMI/^ e<ż,.>nJ iB"M.*HrEwre-?۩JwcPS$'NT*Kɰ v&Vk+NZ?(S%/C{j+u_6}z7klHCD~%% tsowgk9?Ħ x3p,.3}I32.K1>+Ԟާ*+E S KQ3!UyNA|&qu,xKe!ISX"Τ]wTyS9\;<$+,,M\]E}={:C<CIzJE)5 Ղ%D+%;b-Foѓ,FrLBscSQ9u!g2  qF'bϮb1"Þgb3ahhǞ((!X.cB{1rq١M "ҩB)ϔɤx0ڍ5k$F Bg;w&T,(qHn˂@:A޺ mJHh5^}_\hZsQ]kVEzĺ\ ! ɦU5j܌XƤU^(+lC"7D7Z|=,Y|I"ל-*cȖ?(,HpW뫍.6 nAs"p.eKxt>Y.N m '079'`jx>}ajZhh0B~O'xXBy<Ÿ>cl]{4w邜 y@*16L;l=YЊ`!g0f##*g&M']."G7n6u|vx·rKMgZKIڿ &}\k+M`_QDQԈ k0 6<42pKy5w+,R[Zgc(>c쌅=Ԭ QrN6TܭȌF`4a2~/^>} E|wr)oo}$iR:k$p´)SW)L&$IۗAJu;+R^Ȩ0jxqE؍s"]Rx/I"v!ZcAΜkTWT-_*[\08_W'rxQƣ'q+H,عRڨg$^8|]s4t|fk2)Q.+`xJRh}vx%f=l9L-pX1Ή\h㓽ד\KTќ߉FݢFxZ7M;gxהy \|`M#yjHn_ oײa=G3~sTA9xF۱FN:ڻֵ'3{1ľIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/confused.png000066400000000000000000000016671345766322700230020ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  7 pHYs  d_gAMA aIDATxuiLW ,Aa@Y[uX\#*mԶaiDuIj%$G?.?$SMl($65iZFZ `0"xzFlNr{,{o[Fb".zpK}r>{rq6]QrDIv:2%diH[`ZHEeyyٝm=fd lL-s(Y8qn\O3_Zyz\u>8pB-<=OQL hwQz2@R*wkXJdP3;=w1yB`P,bS WJ:䑩1}O!O5cYfN㡵өo Cw }CTQ$yR)..1m>%R~Vǒa5,UJf(1p?DtK;qNƒԇl2SA=oHUQ_zL(-3}m/長~mYm5Es  mj0nz')0(/~֦[:y&\ Q˂h^@n2ACmnGEiK[pZ+V!nkF'Gݦ##Ȼ{:QAߙWsw[ɽ9[$fϡ3Ng!7WE>6 |e'[%<<*6"9OF'=ʪ|lN#|fD f#3JuXozx;Rdd/S'CQOӛNlxˤ5p4Us1Xx 46<|ۅmY*$ fj<:XJ4B1AIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/contented.png000066400000000000000000000015661345766322700231550ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  #; pHYs  d_gAMA aIDATxuS]HQ~ R?Mq[ HAYERER!؍AJ]%EPxEId]DENܖNUJS۔~<9s^ұfuUjɚJ ~aؾVAU(䝅h{,WPW F}xCF1kFjFLRA}&DB!IMX'_rYLoEY+kިǙqr\ՙŰV*kAsc$9 :,g1~;*c=$!$|?ĝ>,dC$FsYUJYF=g R TT29)F5"e mے"F#w 8 AP`3X7f"M8!F0YDӥd܈0C5$?Ka4w05ɛC_9,>*b q~6/Ҩ)>+7 >>Ӏxv}cQ3P[[!z$AIjoygD5JliT,^\Бm QiFY !͒ *2ʋr2@<uα#BjܞJgftLdq)]l2Wvӂ(ŽO8`֯u=e8{Ox WyK 2PD4Xݸw 8߹{kCAG* x\$<|VٶmCdFo>V^j3 FrWe調爙"k:[@9mJ޾;KU}&HsE:zO$a~[wڤқ/uOD-cTW٭g"'rbB~fzu{F~sLӲ.'IvȦ21ȡCMrFn%WB˩rZ\#RZʠe>CN`M#B=<[]ېՂݕ@a"MtOI/@9n'wq4xXb b*03`#Bwcn m|kf!"AM~ލҋ` 50I#糭F |u)ق.Ӕ/Q5| `(lu诶+) BZ[;.{GZY06F`s%|t\.^tt]ukcekR7^6x45e^^8ughp+hy&,$e겔e1t|7‰V4&:Jc])ʬV C'A/rMg7h]_@փ;LĹ/9>ZIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/crazy.png000066400000000000000000000017251345766322700223170ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 16 2008 23:27:07 +0300tIME  0gK pHYsiTSgAMA a-IDATxuSKa{_n8&Y8ESdEYt1( )J~0 C@ v3 )e2tWs\ngQy<9R0YǤ00kU'al35mSQNTq@ķe]G yXEJlt`]}2\;POj=[KeD:JvSS|i61Fmutj̬xc'>_xtU"( _*^\>_ >Dl;N]_GЫu_-gX2h\,96 \'N&K!,1]*\ %XSoP(#01Հdz ǝPiqv+а+5Ѣj 3ju4O_)4^ȲYPRb21RaH G?w,: { CAxciƋ7&IӭY赈UЕZbwIcsE0hW# !gl+EK&IqY$/æMY2$"AD9ߍ k7+x fT g`Y pF}ξa\j\W(hD^4!F`R;V<<{:#Α X4L5ۭ<`$#oñ$E1 . ٥NcNײjxGxm Ƀ.v~dJ_`2IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/creative.png000066400000000000000000000016241345766322700227670ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  = pHYs  d_gAMA aIDATxmR[HTQ]g̤6IP)^>  #3裠 ) !룦0PsJ"4L߃5;wibݽ^뜳0L^tẏ`h417"˲]]]v0Xa[BEQ5XNӯe8"22j]e1.ߖ^o$Ia>M%Ay {0cjAZmG< FݛPZ$^u4#1?/ѯ@cU2i"BQe9)S:,x܉ޡ`c`'Z4$)A{#+ /Ascvf:BŅnSmm-uttPUMwJ v 8v$ ]dQ'Fif֜ZM O>h@u :^e RVa+Pdgo4`N<ƦH@e["5hCwCABt$ ~7'>,S(U>`rA4^dJ!yVZ> .-A GwpF4WYg j%h.ñO&\,MR $WkA/'͝+rO9օ XVJZyv@3i.!Du1c]d&Acb"+O6Fu&a 2`37Mzо/\Ě^IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/curious.png000066400000000000000000000016601345766322700226560ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  {* pHYs  d_gAMA aIDATxu{Lg/!ƴ\F s\!8E1s8LTTtWXf"Hb65,s7&F4X!Cd"1mRh{yo{{Ț?pG4fr8Рao,sFnu (5*Fo2Kl~,yBN}V&W-k2^N%_T#qgOK~遲\RR3XB64W Vt+Dp8j+ {:]ܷJ$P5H` "eDdS43y&{.Բi־"j+کXCۨ6ilQ[u8!8߱ȭ ?/d_,ǚ}~Xٲrܼ~Av#rScGf$3Y#xʗ^$b *^SV/۪`/քQя*8\KݧNH#܏"mdȩ !OB]~O1T(̆3{0]Ab~a`b p#6Iî2Hz|2Rr .].N?T;`N^Cd{7@>n?bQyRdIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/dejected.png000066400000000000000000000015661345766322700227410ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  !O pHYs  d_gAMA aIDATxuSkHa~^ty[ٲ1NJ7*Ea?Q? GB7 !$F$2 2 FMkiV^٦mog7E^x~ .^hdmb702Ϣ dPZQ 73?(3~z[\d@sm6"\1;,]Q[(ލ+`6LWjXm^DAA “1xgKAx22"JY7t=p 5bƫ*uY+83NK SJxNͧ}eu)OCsF#GBcr*yK.&eEx:O/^[3YJ(c#ϭ R ``ɀd - 0q*.03$GlKF<8MHO{N^ ˊc`*x;B- @! "OCQ:YJ Z/޴Ȁ%r d hX_7˕,@r~1qk@MJ# DӞ A "(HCзb+-4(+xe gW}Xl# E؟ jvӘK$'Jp6bBKM5r:ItMK??-<ʅNIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/depressed.png000066400000000000000000000017511345766322700231440ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  T pHYs  d_gAMA aAIDATxuLu_KC8ty.ct:I.u.gܜ-V.Z[e5X.~ ? $~HSuRli&ٵUI:518=/ k6pX|%p8Umx g9ƋU87-dZ ʓ6kA,rMGK!kȆ Z& neyB "g/YOWatȜӑLxrc~#t;gPfL/Wa9y0>_[wDKo/< b?b }D!1A0vgh;_'tZ2?;[NeB ͸ jA.Y܍X]u~HSئ+J D_Q2T"$ڙ$ҫ栒.ā|-nNQ[cu :iʓpXgf W#o)6+>Rx5A 'Nsd#Q5= ;S#\oU21 p 3~vtsÜbg"e47y5tOqYKc<TDn2z+Lgw7V?IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/disappointed.png000066400000000000000000000016261345766322700236520ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  2_H+ pHYs  d_gAMA aIDATxu[HTQhey 3sƜ2. T)AFAPD QCPDكt+vdPsjҴ&g:s.8o+egW|yYcI}Nz4Q.߃ol*[N{K#h2㳋J-b?ET9^;/Yɋ5 Pg䞃\5ڧLA>8Xh_VѪkrDKY$L''bM9JId w ̛pxo:!lуP"Z$ዴ?L79'$=h{yov"lq9Bh@PQ/4Zq XȥFcζu櫌cf݊AYܹy/ cv #KT(#I%sV,H蓝Ӆlu.WSLkĉn)r!@(kg8jB[731F%MXAK~U w=S2)9tBatG7;{o`4:)7IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/disgusted.png000066400000000000000000000016741345766322700231650ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  $k pHYs  d_gAMA aIDATxڅ{Hg?v:ܹ)f&DF6R6C.,chmn֨@V1",b]疗<y-=<眓 _>s=2&#x !980)l%wtK~W˝J٣4ZP(L 0h^e]ͫ\ K{s*i:R)/^ b_Od νOzm)u>MԅXh:\pl_'8{<uB e^50\gdz8 w4/1L $Wlab$Q-$h<AfLY^d9"TC۠R"=pt|C,i\>?(EOM~^T쵌Q W*+p㑙; &~‘ R^T|ҠvRO\v8ҨZW,Bd$L|Ӧ!rfFtY>9 QO@!Gs!6<IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/dismayed.png000066400000000000000000000017041345766322700227630ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME :<5j pHYs  d_gAMA aIDATxmQL[em@@A6p F3dDldٴ&CeF%ɂfFͤQ,$cĭeX6FQJwf9i}A:/gS̎]1PX5VbZhC<\[b,EVꈬ3cl-Jow|YH$bRRT0r.w9eT*%6Kmr/Bh&*rρ:fڛ_2UzzzBJy]ijj@ e2yhk9Ѥ/x\^o^.UUU&[ay}VRiP.Vn lŖ[4HW({IוW|nw& 288HaA0RN'dYN?ʛC]<> e./h39,DT"ݯi;:,)S$vOPZڊp95JFEH1GyW?67 ^CÈp>Ʒv]HΡvZU\3u~N= It\Gi|wOdo83HN% L]KZGE~fS~bQa J+s5tU$~/_N0lrn<\T6¦ԯkŽ΍&q$5>R.%x:Jܳ->.Z W;/,,Ms9y'3aFrzIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/distracted.png000066400000000000000000000015471345766322700233170ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  5zKO pHYs  d_gAMA aIDATxuS]HQ~6?30&@H PYvu7&xQWBu!QURFF6oܜԹ';=9sv K^,#h'*0ǏΛF0nzZWp":G.MvD~~0s!p#y*Ux.ɄMP jq!\;X=ƬHcx4xz S;=I,W =͜%4grL{EE:= wl;I V0po"C!#("SR@X:*ǰi#~ ,F/pPUx,V+Z)'恑7~\ ۇ5r571[^NHnYcvч٨bnn0㚠m,Jg5W҄h=}_jch40$T%Vѱ)&uS^6DG^Idb_~3]蝴yE;XrJ\(p>xX)m 9}[GbFY "! J B4'^~iTEidGVS>&G-34uGY6Z{sXBLQl#6r]s(&tvq'p*/5BvZ'K i&'8#5/ @@7LYY;(fl?;TJp+zlyJo rx{IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/envious.png000066400000000000000000000017001345766322700226500ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  0Ytt pHYs  d_gAMA aIDATxmmLgdE!\t&*s1b!1d%_fsK,S#YFهۜ_ns*25Xu)i Ors}9ܕr:(+vNkv u}gD>EG*1yWQ,Ũ#9Yjd#/Tș?Igx/&r}^Q*+=2mCn<[!?4d7lKeZ+v +ަ5ry-]<_ u6p ߠ6ѳ ZsQj%<4/z]1 |߳p^Jp,qlɉpSO3AGh(gX\jb*u_kV Sr<Vz_i~BCk繚ii_Qt@$'#iw^[Q~S4|X.ݯF6Fz~՜7OտH+Tlp|7<WjQn`sԇt' cQ窈.9h :+jk:%M:80iϡ[t)L *9vqP7xgw)Tő GhyaSg IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/excited.png000066400000000000000000000016651345766322700226170ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME   NS pHYs  d_gAMA a IDATxuhu_v릵s]Ѹ+ 0 a ?!L0&i"()ETh *efyƆ~ym’x}y?+pN6ÌM {8Y6? }ވ\S󌑺D6xޚ%g?Tolyx+bxJ(8d2|q &;:tyfs#,ɹ Mޑ竼wR}Bz%[+f2X6kycK+xwi<^?} 4$Ah2Ge)G6M|s*H4(v{9)B͎m ku.:6 xH$YMDܳ2迋 + yV"?_mϮM쭯CYI!Amvm ;9}SvL+V㶥Ip= Gn06-\ˆsDPSG8xH[C|Z"G>%D A"W44o*͝z"Sa-Z&)*_$Ș،"]BV-QLf㮢jG_7ҭ Kt lӢњfF/M̶NU5> W"lN]bDSRwnyLB"' \ s_ogS$~CwҎIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/flirtatious.png000066400000000000000000000016121345766322700235270ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  ,I' pHYs  d_gAMA aIDATxu}hq_߻܎ۃMpbdJ(К(??<+KJ" =rv}};ֻy~~c)!c%NÄ-JؖV-Vh=/ILJZA~<&8汱/[y̍ircܔ2U/Mds$Ѩ,sr7%",C9.d{SS৚9ci,rΧ 8ǢɸݟyISXl$UiˀT$Օ!K!Sp;z]uvP' (~0^6p}J$HB r=bu]tSdD3v(4q#ҭ')/F!G]}1P$v3e02 u~5ZGݒmZ8T)8#J^h‘H%,!Ui?wlaMaX1͢ʲ6E' u gjط3x[(;۷^TpQIf= Z}#5B-510]$c^_gsgqĮ\;()b ~t/E+EW*IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/frustrated.png000066400000000000000000000017171345766322700233530ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  S pHYs  d_gAMA a'IDATxuoLu_]p\9<Ҍ0\ınZ-ls9*Q|b[k=F 9+8!xJ;}?Jg~?x*fsf*zn6M7Pxܩ2j)@&:}B<ܵ0=e gxY3\NTOY8WDȟ#n6Wr_Ԗ7=_>W. 彛a3fHrݺ d "9rGM[Zrk33RLH$JJ Y28c /%4{Ma",b&: guTmC{i>~=iY&\E;T4KhhƆ3D.PfzN6=׮(JSJ+/ '45}x>9B2a??rM_TE5z]iB{u-D/ݲH:;0o s22r7Є#;YR2)8qp=(_=:uۘMsI޷`ݱ? zAېĥH{`dڠ@J7D5rIms g>H-Pڭz"}DvuuvEo_8D6ûO֡Ĵ/ \h.|`9HR|~Ruy vO"QO/I΍1aC^s.=%aIǏr!NM_w2]UG8;ߛùP>vE{n 8E "yhuVcEFݾݟl~_BDH(ögtΧO.G &zzR7e-O/?TZߞ.r[ѱƊ~bR\fKǁ#FQVqUcIEtvTB5nl-=y"]F}l-~bUpz;ybG[3-56Dop}|J[b~IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/grieving.png000066400000000000000000000016401345766322700227750ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  ;Tf pHYs  d_gAMA aIDATxu[LTW=4\f Q1[H"^d1V|0HHxhjHQ[oJJ1>`0}MjRx!.GEQ23̈MZ]9YkVPe3ʒa,KaZ$>û~)M[ t*{;6㯯f[7~L篭jFߑ-F8b\^[_EӁ]~5a>8J+Ph6%6&kЪr!'1֙*jU C8tLx *I0ǹڴV!Z4?i9p%aqLAr݅TI!Nvɏk)(HȖq)(ߙaUl!l#A&fa6"l[(pn'Dh|yѧ !}*fMEw"c +U~(c]4Eblxé݇1"Jϟa>Kz@nC{J;_9M] n.(=zEuu5Nأ{ӉF9;O8KL-7lV鲭ūμYDzTU*w_a-ܻ_nz?'۞sM1-yQ f >gHRv~IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/grumpy.png000066400000000000000000000016011345766322700225030ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  34 pHYs  d_gAMA aIDATxuSkHa~m9/,[5InR1K 0sQ"/!D]~$A7CL4lN\5ξoz||ϹWYo5bq_{w7D~X-aeA7]~ aAX*4N6W-Y ’'@XcAwDD-lnHo/ҝO`%ޮ"bd?H4]N<)%Ղd#jcQ;K4 ZE~j|IzxX]D=iA Cd?Vzሡ}dPmƓ 0P FHEٳ} 7ΡPX5]GoO; Gc~ZD$e j6k gIa|fڐ9< `Z|UCv8~:+: VB3_&C#!nsobDe};gWƀN.L}9*9dp.mb$  2TaGgye^ntƨtTR$FP'|0I6*BaolV'1 QEiĺx-YvْH?$SշP}YBghؔ.Bh,8}u+.zĿs>oBs4N-!qM3kXrF+ 7;VprP:[pKFwYXC_k -"m+D:vKyI^`OM"_c1#XaM!625Ґ oIM pGnbV+`܌>/C\439e7ܨBk_P׊:6K4S@#̌iTu >SMwMv3Lq\qkUM8v%O_Rs 9g] E 9o>O(g;TW 2@\IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/happy.png000066400000000000000000000015601345766322700223050ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 14 2007 11:19:29 +0300)i7tIME  Qw pHYs  ~gAMA aIDATxڭRKHa=|4RQLʂvQavY-U$"Z "(e."*fdc>Jy?638E;7+!|Ih?*`6ԪZa7HØĸ Uߋ9,~ǘbX`L 2 *˅ΣͭHFE#?d`XRIۯT^"W!f@3rnU%x \'OʡT"TM"SŁHN"e&Ď!-4" Z]Py!a} v#TCPj#D&9, xn(y"0 _+ `/_s1D2!flxN†naL3g i`ܭ#,ro #8yL]afG`#?נ Zoi#d5f1DQY2b rCL&͝Hw-f z&R.AfWJNyZ6Nҵ9 Qv& ˷FaQJQx܇)DEۢtP{Ru`\7Q;VO9ypA(4i^b=Ci鉬`h%qo َە8SU*i`oG; ^cOqk>ր_3Jِ e_X P/@e}BeL2R{˭}(>HRԇ ( 6lv7ޒ38g9^Db\zIyb 4Bg,!JJXl#';eRd."<)Bz2l7FW7R(\kWcz`%`;k;py?0>l/VRCBo?هc2lc IN,4Q#N鉝"K.+KZ!VTºbiٝ8J(vOZEQILnƒ_ %L)EUF"8˿tWcB򩜃Q0h-!=14JH.w. >;*2IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/humbled.png000066400000000000000000000016351345766322700226070ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  $Tb pHYs  d_gAMA aIDATxulw_T#ZhSvWƏ4!Ն)[Da#J ,d H&e"#5C*wy|*㓼ycIs9ٝ 7k,)hkT=Nd֯[̣j#rOѤ#.(WO ] )Z+5?τJ m̙ºf} IQ0h3K>&;I$&wњ` n NҿdcY8G} !W/kyf#z(Q=*sd4t~3Fr3Ym'ƏG2ͅ;iYf/0{i,F36?ti% &իf̼ 8 gpyi&&ƊR0JLCK|D.ܡ*xZ%g4OWZTG$RVKr`.pɡڪ8XepL[ thw=Ժ)seEӲQIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/hungry.png000066400000000000000000000015271345766322700225030ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  ,K pHYs  d_gAMA aIDATxڅSmHQ~6udjM7[5t(dAeX%VG?D0" ",,ʲ-d_9u֬i);qy9ys0m(6 n!ФŗL b593H 5㫌hE:ZL rp'# ~c&L*AZjW>z1J%nW!K9)|0 V 34NtJmޗI E8t"8^e/ snde硽 x[p(Q_W o~ښym*Q -MQT)$ڨ@.3JZ )%Ǡ9.zJjwC|AX@Glu۷pb9FRw_9seF( sb<Ӷ1Qi 98ȑS^<Vy 2 ARQj4*){~C*Cz%xPZŹpM1ڵ Qdz(? ΂Ee1'w0zSN51ӣduR"8sQ3\eQR,>XA48t2?8#=F{aô8-'W;^ ]($`wO, &KOIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/hurt.png000066400000000000000000000016721345766322700221520ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME   pHYs  d_gAMA aIDATxڅmLV[C,Qڈ*n%jae&2M$&&q?m?Pg2d`fc:BmiXq4&M=ys=9]v.4rv=ݷ=݋nj%2/}\y-/L%uvvzx󆆆sS9 b1꒵͓OwllQ:[?MZǭK<U>ӉFh4>1P(Spj_)4UgH$…:ܽRdѲz| q/?gb YVL>e6e>Աi^b%Q xjxw<эLOf&_BK 2e`-w : v٫70I )oY i?KRuab)䎫'l*bȞ)gP嘀mOA^`H q7\ 僊0s3Q|UJv'k APx݋hKHV") C[:=oaz/S_-!KtߒFP/K|D-e۱fuT$ЁFdX5T"*N\ܞyGl(-Tw˜+}6YF(dߍN/ ݄`{ mٛl?gq s9eqd 嫧q a"$GIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/impressed.png000066400000000000000000000017141345766322700231600ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  2F pHYs  d_gAMA a$IDATxmmlU}VoLVKFFfd[5Шщ0T!IĠ yI\0isXv Rxu'9qC*X%9[#r :ޮ ֯FG*+Y?G>͋SۭNͲn{3t~&2;&ޯMq/I.ԗS2q51 bL%q*rq%mTCжuN3KkK\UNG]%_~"%%EbXViM1sԖwJvnɍ~99(yyFVf+-RZZr/lo /Txs.B|ATq8TWU25mau=Z,,gSI#[FmK08xM}tG/7GuҸf 27 ARXc6a[T*M-/:N5oj%S*ob]6zYjҴ4`v<:BC|_0=4Fd|ZC ^%̹5Ih]]d7ybI>SJﯕnmN'8R0t}>9-DGy#߸Wҫ{A㊒.%U_cďV34.n"#tLHU]ڧI#\q[ =\D.e|L A^ YޜZRt>=.zo]"_9|Jd M5CWwt<`?`4䈽IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/in_awe.png000066400000000000000000000017231345766322700224270ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME   pHYs  d_gAMA a+IDATxuLd?qwxx"$HN5AdײO3VŤ\616_D4Vis4C6š(/T;.پ=}Qל|Y-庱E0vI40g45nHJ(ٸJ%)U& k5~ûUh3,+KhA5U.Ō d17"nZ RlcNU@%QvJ*ʓQB^(yjC:e›W͵ɥHF:H3ʷEt{UL&Cl HM I{Ddze\L.^fI%S t3Jyb'Ky:唒%5+$,fIzEy1T"2Gԭw+yxP1u M`0 ֻG9tXL;,Mm6)^.S [=HyFiaJf*Gh| L8$i}z8/Ρ95ς98# ~sc|8 \h˹iseIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/in_love.png000066400000000000000000000017231345766322700226200ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  ;cP pHYs  d_gAMA a+IDATxe]lUK߶+m!(L7dj(@tpkzxa⍉ޘ,(ј$ \l :nk=>`O?{qjF8Ն\x|iFDoXն}ٲ_ T <:MC+6:HzByj!,^mc p Bi ش:?z޺^`xVXc[Y])+*} Zl![٦>OjNy"g4G>&+Y= L{C{T=wnk{G!Y'=zo3L֮vsi%dm}a3so#/-4d9.yq 9V2 IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/indignant.png000066400000000000000000000016321345766322700231370ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  txB pHYs  d_gAMA aIDATxuYLWop8 ZE[ԩ\j6DM0D# 4>41!&%.>AԸq#F42'(C kqos=?.*>Lsv&]=!Y9+rG o:tBZM}J2AO|/JGSX=etLxh$3Ҹ>ˠۉF4MҺo7K֒P~e֙-灾&U)][Hc/J(x`7SrKaf.]l}顺z-g.G0,/.HTb%^oyN̈́x%r`-˙;IrN};OR3< \2cqYO]l;/BkIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/interested.png000066400000000000000000000017101345766322700233270ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  t` pHYs  d_gAMA a IDATxuHg_ᏴȞ$u&aQAQ T~lQ 6% @!\L:zN?=_Fy}>),>${ka3!]߇8JBϢ6wGɚsJSY]Q,сTmW9gGt5+L2m['BOQȍٔcB\dheϸ|6PSYlF!*.]~'@/Ho>堫;Ⱦlݲ&S1i#Y*y`Xì*%ttzbxLБdoҏoԵAp:a1as{4j2keHHP0nHhO'{[nw3V4/?R` EU>\C#:k̅e;V//$.^MdMx"mύ~lӍNv8s3@gW)h^Xy .RNm 7ǹ #ɟcgJd_3Q?ǂc&EƸ\i? w |^P̮K9_qm9l[ŊBïiFc B%3W d 9j?;C똛{ކy{{'QϽz8[$416#dž=}}]f18gsl"e򰧄:a$Dj* ]b ;ɓPʭi2W1*#M=D7˘;bW@iIMy;xZh,5 CפWy{vmGYVp5;֎$ǧ0>禒%jNBM}[@C >}ON#PŻ0zȒX\GfH״cXl g^'T*`=,1anU$7VBa@CpY *W烪HMNCE^Hr ;X֒rQhV|V|wkdn,"ua_PecceFʬHDf@AU |':\tRV*; !, Tr<(ʹ0{5:Y4w dYƹggfuYeB>em]9{ G6g͉ˠ= LB:O',G%MzY_w mF0ikWH'S+䪕 y`yn'8-CZ*uEϖW>R%i PAIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/invincible.png000066400000000000000000000017321345766322700233070ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  ` pHYs  d_gAMA a2IDATxumlSUvmחl62`8 jtDA  ~"&"hL$qd1&c1[ %vk7,+/HI~'9w8{0躣[IK0Չ$ohza}|=IU<ӷkZM͚1'iM`ihD6W4Z5OlFS:CDK+;GFArX/$QPghR\DE*BCM-.-Ndrôcn^W^Iicr0 )TJm  87Gq~ʞr QRE&V?!O W}lcs/7/^‰&GNYuSvJ{s g._;K+ulY!KddR#Ar+hu3qS6"lC۷DP *%Qf`K$z=D83]ofXۑcxTOfyYOF t2 9" wy4.X,Ɨ3kVM%Z/"<О+T}INHްўqM  ox)c3mȲTjϨ>ʼnrȝ e ͩl Cz^rs'm̶F)cUpa S]#/>oΕ?w1+ Q? k`{S#?06%/}l4\z !/&@k;𪋆gPiC˶m9)|JPHqF3XpcѰl2j kB/N'E^NiK:I#Jx)V8WOQJ%0R 2 d2zR9#S:3FèDCNT*U"vIUXXH.ɰr$ʤ<-R5 lG}ܬyf)Q@Tb@bNO z~ ,)P 5EP[m{1%rtwDNo8Qp\ooP}14xj}Ps,;C![K4 ,P}#nfHGDxV &'3كN89k>gޡxҲk"[F^ }%[ jTO0IN F hv, hn|k̮8gdJ vsnP ?F "xMXa~hvq ,Val l߁,ok vU1"dS"޷ zPsr%_A,IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/lost.png000066400000000000000000000016541345766322700221510ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME +E pHYs  d_gAMA aIDATxmHw_Pt%_$tJT@00A+jnb+ q2CS:RO;O<~<=b9wBK09̸n)Xu}Q:2v(J^P:vϐhS,&nUoNOi9|R?)ށaon͏_+X Q(F11% aKQ[xmZj_ZZ%] $LV|aJ6)nsv>=k~3迥c'Wb2*;1[1%}Hg7dgg|?h>tʉi>2exu5K(]SnVXX߯kko\Օatꆆ]J޴o'M5*ckf%~?06ÉE|TS毯^Z [@`b LSrŃ{e=q|).lTU{0oCSrJf<(ʂ{FONd%*#7ClN6Y;)3ddB` W CTda,c0ZS,Gp,|)q-eTЁ߭,;*LVj8@ ?ƕ g߶O,5I1[Qq&#0Zqq EYwIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/mean.png000066400000000000000000000015711345766322700221060ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME 8T{ pHYs  d_gAMA aIDATxڅSmHQ~KGnNfKCJȾ")/C2@Ƞ2eQA!#(~UCXM2ff:M/}2i&=N%PDpcK=C-JVF􆣇9ڀRH^kFf ^AT; ,n1,W売BA9ûA"ш:hiGXTrf,ʍ\{H8;$_EEQ1"s\v9^4߀&3MB`sDp7"n~`g-PH9/ўĜ$J, r ^?99˅t' |GAd2dw7qIr>]+O0JVn SPxB.4є3oK6~nߺN3[ ޢǒiw/4~sr˲?Gx2*0tځj%F&=acL,/ϲ&+T} 9  b1-HNZjtFr#Zֱ1j"eJ2hSI^LH)ne/+Eq@5[F5 69kG]}hQu.P.9l%&" 1rQuyWIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/moody.png000066400000000000000000000015741345766322700223200ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME . pHYs  d_gAMA aIDATxuSkHQ~ΜlNwƶR& V2@%Q0??G/,B!!5 Vei:/3/]NmCrp{sP 19n05u#c&7ғt*3n'`C”FDU !b >.iJv00nH΅0)&0pfbo5xq;N'Z Fg$OZ<335_KϦG|z$Fz/ʃru̔oˊxrG㋁A'GUE6$DZvxeX o>/Nb(*bQ=H|$?*v軐 8S`bт ~3UCIbomn'-҂+BnPQ!hUo5M"[k2c K`wb>q,5MM"dN#| D:^` ]yt}_a(e;%X~eEs0;g&~&]Tn/ s+B75I0^+IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/nervous.png000066400000000000000000000017031345766322700226640ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  9 pHYs  d_gAMA aIDATxm[LW33-Т d: #7 mVB5Z)hh)1$/4m$TѤ(c)Q!q(PFp(\3`j's^{׿RHIwea38:6eZ$Bu=yp:kHXo2|ZhhNR)يH1Ixӗ,qhڱԐz#猬ϑ,y_rC޼S],엥o&i^wn&2Y☓D\D6]VLRPVNgWsVua OOw XÂTRl|!HM}>Fq҃sF}8bڪ;l$`K7S*I^ 9ө(^OJ82m%:u {:9uPXP^;Uf;5Ta Křw4j}"[=Tu7>ӟjK2˳ggLkc4V/3XzL%G-!n uRbL7Q"`BItV, UަDէ<#~Ⱥ=^$s^h_ gQtǷ|sgk2v9v?N6IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/neutral.png000066400000000000000000000016071345766322700226400ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME ;KkH pHYs  d_gAMA aIDATxuYHTa:[L[E{=!E/EAFQ=>EDCEEQ-؃ &2i92j,sB{.;%snj$6:{8^S d$~RJ85Y}IiQƲ:/BɝC_{.Y΀>՝9#?W3fJ(tAX0+7DI?ՉӤ<-MqU@]qd-H'<+ڹ|nFD0hl#?ԿszICkS*_512#IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/offended.png000066400000000000000000000016221345766322700227350ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME %D pHYs  d_gAMA aIDATx][Hqǿ?lʜnŗz B)̂.!LCAH)eAkf^leby:\? D% XoZu( = }>EGef$#x 8F" ixXļlYVs-)S@f }`.W g"AQxw>?ֈ u 0K 8J*ٕG˥$2T/ߊAXpm!NUJ'$(%,Jo{#WZTbµŁezq*3FiLr$/4\jN>;0L!e)GC6Ev4ܿ"N(p --`=a{*=4h-)jRٌ3'7 3DkC.QX R6c"1HJ`D$i>5[`&JُptDJ%^v(8n ($Éa˃qN_Z l`(KPyb)LsHӇn >:b3Czv2yأ&1J+A9z?]u9Eehjԓv/9ˇ( j:KNfJ}3'1]ۿf!gG}Ct ?gXIX /?x֘ݿǴh7f\r",kІ" ޱItݸ9W V*+ IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/outraged.png000066400000000000000000000017331345766322700230000ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  &Sp pHYs  d_gAMA a3IDATxemlUݺuk볖]661#U fȢD 2 3%%1|Q]_ʦ$$F"H% FDŽ! (նomxs{99fo,Kɋ!0FxvuvZMƧN5 *"]*Jz=I' ԬJ&h,Z:efSܾidRHS%@-_/8 =\WcYHO/8)]Foq#V8ܦܫ5`8݂}6iyG'dp'>x_a6*غAFn^|HZ+ z?r:#?(ymˠ'6[fRXRI\Rܔ7^~\~tiڃ zC6q}-\ЩN]!_?}(]}m.Wt@n4}gOy餟O*s^fwA5X YHd.Nr‡IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/playful.png000066400000000000000000000016631345766322700226440ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 4 2006 15:22:22 +0300tIME \ pHYs  d_gAMA a IDATxumLW--oRu)eт#ÌN]`b4|0"/FQ5.K~dٌM$l1nZ\B[(r=h|'yrϹGN~NP!u| ikP'I>g+f=ގߔ ZJWET1ݬ*UmmeΑ3H$Bv$+e+r5cƻ*S|ZMo+g Q5u0_P:twF-.'HzY%+c\Ceٝa\nQlޑJ԰imilAѧS 8-\ѝ_էj.V;  &'Bf#HJ,rӮ=kg': TSň5=e_B*ON1Fq w6 Yd~؋)+K!zcB9IEWat暅4@OO?q/z9PL] "/W&K7sV d̤DB>JEP btIoo䎻 Ir6y ˺c<ѭ0HbI/^wAE}AWP} 3ڊƶVMlqoߤ(k}YGrّl=quK gls߭^6[F_Д g\HLu6x9 gACJ/]62{(}b.¡~]$K7hj3c ‘f=iʔOR=ȮbN#AMgiJu(ٺ-=D[D^n+ >'i[64Qe2ٰVtYQ\ -FÝM##b0m!0l[t|'`kVeQ҉3fR2]aA7+ꂐ g(iPNk,^z¯w? Jpp<^ق4UnWnC \y$k{]%̮ܻ/ɘu($E3Zρ TRVW`pNڨذ_In>Dh!f*V,vp"v%E}Su-ξj5 )3lRGnlRX[7TH]‰Bv1y0D^%]H1E>sOݦ*Vo|DF;ɬN!ȿOnpֳgZۉkf|iMmAczT\~w(b{@|cxI^Wύh\fOvV#-دae"wHrJ<+H&\,=YZ/Q;Ok\ւK,ɤ0Fq"iO5lvYn3quϮ03[" \&w |q|$z,R<%K@d#YVgJ?bapMGq3ͩsak%yj41:ݝ (0'7-2H/(ӷ ȡ_ȴ/W8YQgbJ\=2p";Ϗv޲ebKēD/Ė)<& A'IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/relieved.png000066400000000000000000000017111345766322700227610ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME '} pHYs  d_gAMA a!IDATxumHYw^GͱfrgILOL~D}@'+6m%"ؐ(nY؏ǔFmi&SGײ߳gf29}?s(vOHz$ o9{[.?V慿VEWSE7(El(rf4F7).FjDc{m d&iձ<>~זrW %#aWefeYQ"dȱBRۄWx[s-~14mIWMDv?q^TiÒ tۢSưhK1s {vRl>TI$]DZᓗG0_);6-IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/remorseful.png000066400000000000000000000016471345766322700233550ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  _c pHYs  d_gAMA aIDATxuSkHa~mnVV4Yv%R+ 1. jEe7") ! "~T?e!X!t!-)˜0颴Jm35[i\|=yل#j z 9[z?8%؝6 JO%fr*oY;]ܾ+^V Wg",vAmwxP5Q|q10;#w>/ '}映qce4Y"go@6Ajkp(3͌Ul@aA3Ajq 9yyr&9?`- !ܢr-晔 $F<}yV AR֗M#CJ%rEX<s6$BSc}GfCWh47V,gBZ@eҿYD(-)ܨH.1Gضu`çB2 +^wLO= 1T,%5C™n|voB7vར?mH]]4Is6RV;JGp{BZcd~nXx?荄h xW@geq3(YJnb40&1&5mAVw,d%$q3PYE!wMHgMl l""8?Yp@o8QA<{gԎ DЉ} Ն?w7[XZIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/restless.png000066400000000000000000000017061345766322700230320ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME 4wa` pHYs  d_gAMA aIDATxڍSkHQ~6M̼ҲݑR0JAHIYR ??E7 hHʹKtWnsΉso/O=9{ aLa\9G|O>֥$`lό,q&)J)222SiRr4sTy#=x6u 9j19+|(&G>\-(=bԯj$h4 k2z^Zވ‰[bEg^sP)}h~Mӭx-8RĽix3 tYQZ.485UW6V.r'`X!HPSSA~.\t!X- Q#`n h+ąHIDK+$'B((8>h9AX#ٺUؘܼWUqurDΝuf@G=?\ ޶t\%rhCahCZ@;OL` A- j,,G5< }|.d2ԍvnfVPB.ױX4<968%ݗ9$A7m("gB-H~^g))s#޳Z٤%G@\!IFV)=6!xe6!\l0r "q7w;BB۵pX 6h8䥚ۏJ G N='SP]/f]dCyՉSPE O鎨POz-0B}k/!:7~6-IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/sad.png000066400000000000000000000017221345766322700217330ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME ūx pHYs  d_gAMA a*IDATxuLe__"ly-mje+,\럶ɦS.9jk bnݙ" )?λ8ٞ?>~?{Gp.>~X~\F(U}jv{i@FWlx s#WlO zqfe2Jey./u+DtH___ˑ=U4' C☼5vU\rz-}^)]̜Dy$iɝ 'mh"YfRh_$s'onGFMP-q3ODS9͍_eXE+q:ҹ16v{Ǐ!3^ZO^J Xn_,Z M230RF"Q~Z4hE䫜7v7j\>i ɔ(IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/sarcastic.png000066400000000000000000000017031345766322700231370ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME wy pHYs  d_gAMA aIDATxu[LTW="cap@(д5 6AVy1x9k{m-k,RƢݲ6NXH{Li*U_I hG. H0QǢCtJsVEx|_Uv! {ɝ593a]`Bq?nO!*茼˳I\̤XLX $O-ptv3{~/gY|=YCOqtZNp,[< YH 6 z  =sOhny:@uvOrJDW8rf(/rʝnpVzLK]$&(YaU2Ғr˼~]'2OLe}܉zG.{vHax|EYeK ')$0 W:F/1v 0lL-;M\/QF'i+9WTn3AQVゼJ*fIzu*m"Nrn:V#"6P+alYpe+bŎMk$0V5u h`sW/e|4,t(wn&FxXRI#:|QnO1iB]eiII܆A%/߽^}E؝L\'ch7`?m~z9]/\AIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/satisfied.png000066400000000000000000000016431345766322700231410ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 23 2008 18:00:18 +03009tIME 7} pHYs  ~gAMA aIDATxu}HW?{uY9E[@b"7%D YlpVۊ-6H W+8e*m E|NUQp>/#kG>gSx913Orb?{h2l/|HW#ңSbd%9|&.EȾj$<#;9sZhYH%(#OT};IRR*r !k8S/t+bQ,Ad_kdXy"'ugWGNhxbٻHu1mdD#=Ӽ-+oC*!.if]-|'? [vU[~[TÒ+O JյZ ޥь&C}a膅er+AϨjYؒ Ye]P>q }k1WE%bh63ABi>fP,d]oYÄ/@088a.^#_j0|Ռ/**Fe&F&9 [h>/ϙܬ>jD( \k7ĥGNZɾ{uϚ5шK+d=8xVn{CySy+Au!&21G94FIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/serious.png000066400000000000000000000016511345766322700226560ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME $< pHYs  d_gAMA aIDATxumLW}(-/0XA":| H02>a%@b˶Od,df*&b f,hh6@cTVNZxJlz{Ϲo9~[{[ܞQ,[ m~kF7E@1\{yU~}*y:6W% *?O`sf)eN~oDbv ϱco&+;ҁ-%+GEyQ˛HԼ K4DfC RX&rgHB:Ų'c^eRWbvOSy=FN)/ʚU-u"3-EX]LsI䰑2/ؼ\6躔Ν_IqfrhujUL"(̣Z<jbljH=:>̎P65|di\ǖ ?RB`zڼporHrP8rqnB,9">MINxzewFO?%r N0>7d3Ea)/7[7DT=мW 6p]NM72yHIR\+o!%o+W&M2W{ٵ5QtNT}4..ttO0NjO"=0 ‹=ϭx_$a 5|b4QNƘyWKsM<翍~/4 <3O{΋4]_EBu[A&IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/shocked.png000066400000000000000000000017521345766322700226070ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:15:08 +0300J͡tIME G pHYs  d_gAMA aBIDATx]klUo߮ݥͱl-PHD61&/1acRMT ^0DQDX 9al`77qnk]۱J/;<9/9*Ku;#јr Wj+;RlhpSUhv61vKU7|u .L{to$_, Zv`,B]z-@۩>{d3&WᄏuHo>hXʃw_UӪڏP4JT]~?  nrk珧څ?,5|Y"nSD]%xIؿ^Q'P_ib#+-Ŕk$T_^cznY)IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/shy.png000066400000000000000000000017061345766322700217710ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  l pHYs  d_gAMA aIDATxu{hU?7ɚ~,Y.V-];c CTL:&]ccXd!*Z667`ea65}I;y|s*vfcrJlvkJ^l{όt2r7vSXo>4s=FmBT#!d⼑{utymw,IՋL6JZ) #kkjם[0"e(( {dmS~zH$&#OJfX%&a:۟6}̰k'ojNIWg (x S?Y 3 yĘ)Wn\cj3=(dDžj2o())lU W\ ɬVBNU":Y Abdƙ+p^6"Vxt]L =p-%ZE jV׆՗kUrTߙ>^-t…-*89|TT,X,WI(XeAS?d3Th4vg~#ᅆ^ܪmK RƓr*=r Uem[ ֆc.Ɔy70KdjIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/sick.png000066400000000000000000000017771345766322700221270ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME +ґ pHYs  d_gAMA aWIDATxmS_luzw]]OJ9["A .<Q\"$oj(> 1hBIئ th72X׭z5#|}HMu X6Ԝ"y,raeO32*uN>7j < cc5ogof3_mx6_F98˂ilݷME<-~Ah[#qsN6P͆@cL-X 4Y1:J3 a>֐_\CP1X/S; wmRl >Rv3"C@1-y.ioc53<4#=fÈF <ϣ;$DvEI}f? ѱ86ZVm#@2qY3Ip'KĞzeOx# ~y9a8텪T(b+SZNMDլ;_pWҰM0 '04^[u½ UUG ݂,A-k /=A"X(*44(uӴ w57ߋI^Xnz C7`F^F-z~sQ~?~mAqO'k)֗]h ౗èHM+np K>FвRLB-eKpw~JS'=})\bK[PqkTK ܼp=cF*q|8 mَQ(*jF)S|p \Ӭ>IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/sleepy.png000066400000000000000000000016161345766322700224670ustar00rootroot00000000000000PNG  IHDRa*tEXtCreation Time 4 2006 12:19:16 +0300$tIME 7 pHYs  d_gAMA aIDATxu[Ha3HMrDME .Ȯ"! 6 . R霖 fyN6}ԡP/9}އaRPD.YC|vxý#h%gIK2ef= 1L 0nJD?fyC0r> 0YߖF+̻7N!+8U"-O6% z4TSK7(ĥk6 )Ej`Y *t섔vLI<ԝ)ƍ{d s&"(Mb{^jA)cܰSqt6ꠀ|ޛ(v 2aNJ$h qA>#ECt?&UqS@mDt4J0w͇)*ho$I+1 Є.'j+.aFG9̘ JT V묈;]1vD!q F]A=j,j;VXxL5{"o|>Vu9=)b04sykz$l 礪%oڡC#';%EEk'[DFF<9):8 uxDF* H$KЃ#b_9,9(,dpD0F$WpM|'ť% i_ʸv!p_sU϶>iha]n'?67sLfk#Y;xQD'BYV'Q3QhjEVFO`lF`{ߍ  y$`mQQ50}AaB@ D1O_&dpƧ̐a^ $$ EV39 bH1~i8] @'\5veHjs8t!765ǫQpa&'"$XB I ?onBL 07]~$|b)}sZ|1 QmA2ƉBŽ )CLT!4w2z24- JgGWJ8)3Ve4**4078O 8Yŝr;qwG?06ۋHMxMYBlCuK?kk=IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/stressed.png000066400000000000000000000017461345766322700230260ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME /s' pHYs  d_gAMA a>IDATxmLe?{oi\qeĸC Ilɱ@[ʨVFV?Ѧp_8,@j^H  W(p}:G}w9<9Uii^^i s2a3\ q3h-fQYi>;U|Z+=ҭ/-↬H^SM+\t[E0GBj (COoXO? qkLjs'#Qoc'ʶRo.WAS˘nORTnw (/_˹ޡ4Rᯔ^2KG&DP{u}]/+UoQnmjΟ[2tf:{t2r9[LNGȉ.,ȣcxdQYV}WL>Xì^UBg ?)-Yi _Bvz{q͑kdLJoFq ھib<e ؘǒIHpPp`1oU%ߩc խD&dXhYOdž8}9ρIq@Qdqws5*(K*N)%(̤l'=MBVyZHySd]!f._̠ЮﵥBxXRHjk'pAp7C?ˍ*_S7湾raLqAl&}-vP6H8f!ZSL୧\i拉+_}5ev*ʒ~:K䁇3PZJ~:$pJn-| PS lMb  akvʯ(0v\Ik~p%WyG􁫵tݯ=BFwanjsiѐgͼ-U~>$q7nd?"]uk3?3@Ή ~:_$)U"Uu`1xbl} Ryk-Y jP*_#[+hmr>ՉLWN%KrqM%=/-w-:l'uFD$CC ),DB]tXQAExZuH؍ JԚn4q¦[_9R ?RM&pm20\kpnld QSj-'x8` ܐE98l!r3o4Ip2F_7 Q}#B J%1SYh>ْ.S)b T@NHEOͽzT֣, "rSU(mm(>QgP? @؋Yo!,5aQ¡c(y6\`P).w (:y] l;qBmy`HCp+L ^C eq1HP&3*d ж8͉'Rx&UP=2EݲrR6KĒѹ/K\aƍb$S;H׎ 5%_Cϓp9bpUw`Np^AS렄+'VTDf!5c47/dع|u76A >k(DMQZjx['σ{K>Ks*윇.ҡ*Is9Vh9pQVz^蔹,Lq\ 1eGi`+OM:ahJ hKJy0k~O>p5 !SIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/thirsty.png000066400000000000000000000017071345766322700226750ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 16 2008 23:27:07 +0300tIME -5 - pHYsiTSgAMA aIDATxuSiHTQ)93hjbdVfEh- A{dQRQ"致jq!"4Mc*4Sq6e1>*{;gQe2)&!Y ^)Ʉ%3Q{Sr@: p26m㘈QLE"ܧ'P1'bA[VPZmA(p4kTz:ȳ (-D,AT_\|1C}7:啍(\nm _۝ّ`wS ^TG3\[C|`L; ))~pqk+8\ ]/L9Xs) EK! oU/0a8vu=tO*'^]ش;MIh!ydct.m؎ ]>sF z׽7TmnÌSk}5aGC}-\InU?:].diWQ* >?Am3-3Jla$AGl0z=^Bޮᛣn/&P`۟`hr,( QQvE)u \W?+7ojIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/tired.png000066400000000000000000000016771345766322700223040ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 13 2007 14:00:21 +0300tIME  pHYs  d_gAMA aIDATxu]leg`4hQԁ L¦|Th *raL1H/#3E\ 1H.uVZ4d'y7={_7װTX͌Cw$Dְ$[T3|? ;/zRF?w8)!e{? v [z8$_1Jí%h>khݲ ]^6/CDW-h9cͱ%oV׫ ff X9e4-wyV-+I/U 8O'S{[ 5U4SRsOtz{onXפHDq͆S+? I/+W=n.ѣFYhhO75iu; d>Ct=| 1ԧڻE?16Py?#EȼzS$S 7|p>7A[[`r2<Ϭ3DŽۅO &$NFCmkW~5e 0 W+|+/5G :\$<ަrCB@ K8_Bx}k*VoS1+tO&8 #1zwȌ[@X 3[8WqFPx{ٕ8 2QYP {q' \eW>`(dQM IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/undefined.png000066400000000000000000000016031345766322700231230ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME ]0 pHYs  d_gAMA aIDATxuSkHQ~Φ[i$Tt D"" ")(3)a2h.urާswR }(;2+=ܢ!b#ʮ(,%ob7X$Y &b`.";:@JLӾɊ i< !`/ +hEVݵq'׏LBD2zvy&?Y BFV1%K`2pb ӡS ^wlCsED2m ۼsi5׼VRgN/r%M X|ՉBtN4Π81,QE"."u-X}k;QCoAOXzGvDn\{G}(j9Q**)R |b38[>G4IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/unknown.png000066400000000000000000000013201345766322700226550ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  cIDAT8˵OHp?9sn9-IHEúx *եb R MC:THb B2':ͽ%us{}"tʃPsl egXjhJ{x֗C;4 ^Ypp~0]~ Js=A>:vlL&>ۍ"j9S3|yO! YXx6B t*$?c=<ңlBFFFBF  LNNJRrC-&S%ە#;U͢B~_i )db`7- bcA qm꣨(L@ F@ >/I랧 `0H]]3!Z r k@02DﻇZx<i,W] cj&*HKKbϒ_cm؈9^*qʐ? ȕyp+%.NKrP;H^+z.]]:+3eKt)kU S~y{콥Jmفt*mT @[o%P]θujKviR;H|IENDB`gajim-gajim-1.1.3/gajim/data/moods/default/weak.png000066400000000000000000000015231345766322700221120ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME  &.[ pHYs  d_gAMA aIDATxڭ_HQǿw ͜SIK+3BSH +R1 '"D01(Jɤ 5M'Y9 6l0s9OFy0cL?g1=CN=a*ż^pI\9Δ%礊8(g g>pΦV2ǐyIo2$S8XA@2=`uhcbҵvNR45 :%a&'P_C'(?0ucq NP5N}7Pd|(TH!T]YN=+G 340ÊYjh2jYshBRz)*$8c!n;ހB )AAJB.IRz>-2SrUY&hlFU%ayɄІͫ(ʴ]Pur|t㚂RBr-Ȩb ']DkłZC? uy1B/%=f12&imwy)|vz1>Ɩe,̌յٲ+xH߉y#=f*Xt+cS׫G(TP8\@E9XBK _dJ2,hD QvJLjIENDB`gajim-gajim-1.1.3/gajim/data/moods/default/worried.png000066400000000000000000000017401345766322700226370ustar00rootroot00000000000000PNG  IHDRa+tEXtCreation Time 17 2008 23:01:11 +0300YVtIME !'m pHYs  d_gAMA a8IDATxmLe_p*p'v,bi(n#b?Jf[S!f?rXmP tZfvJv8~?N>=Yy}><_br><.qFў&ho _맟4VO^*bU6{,TޫBgV^/Ÿ~w/>N=v{̫E>G;[)UPRWKr_N2+(?3a+cl_7zo`0$A~:4ք6VhidI,3:#_4ƺ*VH*ͳ &= .koMq]Qj݊1vt@ jòuPOxo; ާ9Ϛek#01:EysLԞkqQuYT%piV޾NN8v?1wų Á?=T*NIENDB`gajim-gajim-1.1.3/gajim/data/other/000077500000000000000000000000001345766322700170305ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/other/dh4096.pem000066400000000000000000000017221345766322700204530ustar00rootroot00000000000000-----BEGIN DH PARAMETERS----- MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq 5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O +S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI= -----END DH PARAMETERS----- "4096-bit MODP Group" from RFC3526, Section 5. The prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } RFC3526 specifies a generator of 2. The generation of the group is described in RFC 2412. gajim-gajim-1.1.3/gajim/data/other/servers.json000066400000000000000000000015431345766322700214170ustar00rootroot00000000000000{ "servers":[ "0nl1ne.at", "404.city", "blabber.im", "brauchen.info", "chatme.im", "comm.unicate.me", "creep.im", "deshalbfrei.org", "draugr.de", "im.apinc.org", "jabber-hosting.de", "jabber.at", "jabber.ccc.de", "jabber.cz", "jabber.hot-chilli.net", "jabber.meta.net.nz", "jabber.no", "jabber.sk", "jabber.rueckgr.at", "jabberes.org", "jabbim.com", "jabbim.cz", "jabbim.pl", "jabbim.sk", "jabster.pl", "lightwitch.org", "linuxlovers.at", "njs.netlab.cz", "pandion.im", "richim.org", "suchat.org", "tigase.im", "ubuntu-jabber.de", "ubuntu-jabber.net", "verdammung.org", "xabber.de", "xmpp-hosting.de", "xmpp.jp", "zsim.de" ] } gajim-gajim-1.1.3/gajim/data/sounds/000077500000000000000000000000001345766322700172225ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/sounds/attention.wav000066400000000000000000004363621345766322700217640ustar00rootroot00000000000000RIFF<WAVEfmt DXdata<      $A)kX    ,"j' JD]B\ Wd,4gI6lRT8O;T G4~![6G1H+hj"b]n5(3 AU8S! r8 G x~F)۞P(l o y # ~ cAzx#&$HR#J A s % ; U" " H`"  - g!60AV)cP{ p  % / T !"3"k!@ #  #z])'L&hd&(.!+w4S7- { 1  [ <c+W3 T3 B` 8 d / 2]Z2G]v4si40[!{8E4 J~5 '9 N7$401 Oto 0 5 ` " 3nK4s:0'a'u+@h3*,]M/ i. j-s-l+2{0.+ (  A <'O*[C,&G-#g`- *Pژ3 ;*+sU3 O >5B6"8>z`9?c2 @ f B DKt H3OJ ( FNE%~T`QgU֨Zۄ  U]] ]4WX>_E\ykVMY} xT @ [ FQQeS:gJ N I !Lh{Gpi^3A֜ۿ$N> +2YV:  U]3Vl=2{1G. < = F-3 ,/O 0 5  ~ /y13Kן޶( 4S{7 . M66|6 /(7 W8gU6u@Aa -  H-[(DIH%&  PCe e  ?yF  5a.  k Q _u1ohg  # |% + ז1 b 2g& QjG }  d ut 9 D vxDcl K n  D Y؜8 N  QR$]i~'= K R Q?Ph0 D N _   5d%@ Ҥ+P $#Q  [ n i<- " 0K & #1#0V Y&  z)-`(s-֗կT-H^ N. - R09BB/=@-:Q2A/  , 0 . 1Uc], a  T 1O>S-:)O*ԗըV; )u7)qH ?)~)E(i}Q) T  9 n~('*.q )0_ %E':E'A޺׾) )W&\ 4, Q$@:"w#   K } O5_=  \dRN~Ԉ7Q _ S-qpB  q')y< DQD @  U1l=}3 +iI & - G+_32-q՝ m0 }qm7=\Mt 73:u(>R;;j D   >MC}A 4% ( B eB^@՛@r{1@dTB AKg3EBHCEYDa l <A(h6BQA FN Cm<-rOD0k>ՒْA$@Z  !B#d<`}^<8AD{6  0acaH./ ^ (  A%Kw% :N.ړT6R,< H Nx &P\pa^|ca]Q   \Eue 72 5 )b`x ڄԆ߱c$ $7*'d Ft . IiK-c+*?<:0Xu l13,,:i18 I] 4 @.3#NZ3մlړw@C 41FH7- 1 ( 6C4t,@3=U 4  R 4Q78pmN08 4  JL 1 d2+@11-0jtH (ud( %g}->$#j   Hy0[ #I9 WZډ!ߤ&r s3Q(g V_Z~1`    uzZQs}   [H'/ w*? 'V> |r}w`@5 '   J0\ei  >M ch1FS.F%M "f  2 N  q n YL&[tA} I%'U k QXs?*27lb4nTki w :cF&r- n K _j[U@C&aEV: H}\ui W`iH5LT] \.h   r 8 e8Q{Wp&'p| = mC\ 2} 805~Nou3 X {(G|,,w d/ LYVLoUN%D #l$Bb 3T7  c x  G 7:RC'FeKo0JA3 /!0vi" '*3U w*} _ Q  (=0m }c ,#~ `-n%0,4Hq r<2{ NFfzt}a.<)u7^$#  rdm b[`T(nQ!G!<wO|`Eqh afVIA Azg7Td p0] bN!v{b| U-3Oe&MmU n)A&^ X'6 }D  j 1p c|Oq_F]??`$GU %<) N ckk @6{ Jr+98.a8:#hyRtU>*vX=D.1D3`%%V/Cy9]qNs6C"<~%6,|66oF!+4  L 9K<}:|FM V -~''   K\tJ}(VABFQm`#T5h/<\    8z ,#/%{2  P>R:|5D K W 'w15N *.q>O9e=B3uM=c5 Qw*,kp( !` " >H x a6P8umT J "Ir"*$&K&"Q$ Hy,Z)KLt'\j ;q< -; x6 0y*,!1)t0\@V4 rz ` +>.C8n9YGC+aT MN @%.(y:-nN&GTO0=  A7*z06jH** A # C Mzo LE 0y: L R$sO ,51 F DC0{wc  S c > H[!@ &]T  VH<B2Y s W G qgxYpM 9F  pqum T5߻R- iQ 9 Jqb'3bl   je{ޅ͏;M= Sc 7 r }p}EY$h&    ? 8\Ȍ} ֳ@  Z pA j  eV V - % Ky+m"kFOão*Q +;BW_ 8OUq K5XU U  foL~(ԼË {ha GMh.KM'>)U W  L   '<C 2'ͮ<  "CL}d M 5 6 341}ܶJ#ͥ !W v! 71D{D1    d   ( o .ȍԘ[ Y  2^ 3\W w3H K  G  O  ;Ij<\ R J ;  d<w/1 #Mb=f  j V7ۭ C*5  */8bzP W$- X 1E@  < 1qoϬ"J !  *h+G79TP@<-  oC I 0^tK?ƨH:(vκܖPC K}<1hl19 .|(5S7  XP + 9Lɒʸ#W&l e ,9'U.I ]/4$(j0 $'` z    : Z2%EνaԼX DpA j@n(!\ *6n*} _,*(E\6) ? igM(15G!˵һhp  @cyx gN.EPM) #numg %  5X/?;+^y ,yV L7"w  r ;r+\TTJz D@7 !  U 0 +&_Ľߎ ,y  / 2! A/K *{.~'\3 k YQd'Mq  X69kR@W! nq0 !I!  p= GPjAK P1LW  _ HrCA&6Wսj+( c IRJ2 T  E( LkBR3? ,:BM3[ K 6hoc#F~)~gu q <!u! Ug vg!L|@X p3X5 *B;(Z_eE | !:!. ;6DT=V dA3,e U*jv N\%`޹[̂٫NPN 4H=c )![ 'GA$S RSv pc' 5? Z + v[0`ۻ7}mF*ZX 0H7E V Pbz6 S qBX6$ a$/h ix~c `,L-B'Â,Xg7 +dhu0hJC 1` faIl IT % Ap }^2#ǠֹgV'ݺeaY&v *3' 8 w,9Jc>t2b {vX8\ V3b)BNF  #.v8SAL < 7JY>gph \ 9sg e.#>\!֔ȱN"[m\ ` @Sfu V 6 m,Nb\Y RBT $|T@Xޛs!) {NCrQ]X w6@oep [ `IT H)ɱ6I^L&nME w<S}rQb  tUYn^o PSxg 5 V4 1$SިLec 7QIg,T: j)u0Z0c9fc#/ R *A 6Eͺ2Vd3-( =4C? s J[D-/Zq QnGprJ d ^_ށHXYɪ9'\-x1  f ' ]! +$) lWIQze^aJ{6y e6cr z & EXBφT0I1afEE] (i4H[^]M  6#sYW@v4*d+rO|) Ih% m c@7*Qĺ q8Fl< o QH '&EL,w]g "q y w-ʇWhWO`3] I [b[4 ]lNa8_h; r  ? lQ/ӂwʐFdW^FS i D B0Clv * !poeV%1 W 'uv^=ͷڠL; U A Xe/r  qm;Sy +s9~h-R2 p !  Dzm{~HǗ}JeWN{ ~ C y  {Yh qB.+hz!] ZKO d BY \5Jx)   ? 3 ~k& :_C D  x^OWK6S)N& < b ]UIW/϶ïSPЉޡk`4 iv>uD3| |.Yp!~L6w3 ) t s KOnTpRˑpv y_{w V~mV r X w boCnv Wf_FZ - _MGC\99D=w#&ky  @Jq : } ,(6]f 0?) 79Z | i e_ i}zڄ̛2i[ wmdR#Nzxx \ K L { M i M m/P|~ "Y X7kiK'ԐȈ|{*F f[-PJxN B C , ;%p$Jxyrb ;{E "_3e/ǧw1Qz f ]@aSdW{ y ? . W -N2I + }u* / ZO3&ۆֿ߽BYU= S3gg@Wz ~ \ > w a5Z?`/ Ak@ e5$|    myӴ,KjEz d..zW 8 % v V Ffd  VrQ F f)< < z93^lƤ0ݏ 56  V[38[W @ ) v NLz(YUYTcimU ;$ Sun6g7pa0ħ"ŭ@q1F~v< 0 N T L  H }ex. RJ]eI d`S JugL{{…3q}lm{f $ KZ>[6 T 0   dUOyTpWXk e> "-|o ӊ+=~ӤHt a 0H^Q8 9 8C T9 9S0 -wA5m!N97+`0 Lm? * x A |sckCLbwF g  Ka^0niʎ;mu܇pz!  x#Fm   k [ +_ eI,< ] zcyf*Þ#+ 6k &K0#ya V u i s{ ~5} )q_ |/i 7 gOǞheCUj & 1nEXi i s . MMzJznem;Y x pH.YZz3>W]rnj[  J 9,OBl > l"O8sVJ YW8 g rЄ܌[wR1 ~XIe~` 1 y (tX8{|:Z|mO 7  rExv`]plĆĈʛԉZY0 O irB?i u y - RXcpt5f|W/c -\ R-3݌+CʂY!Q(  V _ _m^ 0   y?Z-'Mz IUu ^+.|̓b93̓z$< p !jjc  k U 0PFy4m\u46 " , w5 bر$" $O6dQC% PA]"!Yd Sjl< l=0 >FoSopv͓kN g #|> Z w 9 ^ ? Q BkI3B2U( @$Z O WӚȺŒxaCz   'o5n3   KEK_5MKb_e]` =`|R` fhR-j+֗\mh; d { e JY; ^ @ +  X+^|K~AKt6[1 lx <&'gsCZÉm[@r 4 k j,! -9*L91H!L4 J EQ-zX[v֬T! ? Q7PDM m  I:{?1[q-l #eo (b@c %r \ %l,6 # zD5BXRUa j@ OGTp9@y˔փG|*   }foy  t78bVkqEY d,T [3IN: Fnx8<ıâPO)x  $ C @*s (80;= LFK oS7ZL{ݠYca"Vr i Y h= E e?\/U3L LE MA9*̹tĊФ74D 2  |\D|A)2  ^/ >  T KH qQ^"p˲^ÊPдۥ;o_g4  F ^ _u_C  R\~V^/AGO2 B C ' 7E-̚'τ{tT X  |O0o$*o-  =oM!`Rc0 v17 ><@kvAƳ ӵݶTHm [ B J dsK 3 Kr*Hc!@k 5A u.Ex}%^ƶ8P6 O fFRdH *ln&ro y&4 *.  ;0(:{ˈԝ;3p 2  B [qKrB: G ;9|.G5 .  )7eޗNdHej o   d $6Ir V* p l~$v2 xT7? b@44G>Ӯ޵OO\}+; S y,EVt ` W~}VCnS4 vG0N . 8 @2G!6Ǐ 4,`tc ! / AAUn: u a/?ZZl  T.Y 967LlCɋbL;WT   S F13U0 B \s[fY#~ S * E W*FaK?J Ay4>{ *  c @u E tct  d4) `g)4|d,Aɝ2jINTG O ,<DT~ R!O) )@N tZ C5 B]lK4EՔߣ*_k  +  t | oQ9 'p< O- 0 %=Qi͍CȁOJ޶DJrD/ K  )M\.  vI)A+5D8[} 0 A$Z!ɺnݦ) B-  F y%R29n C  ~  HS~I,HܲQLcD/{ E R cCBaC  ;y0%0qj#[ i F jmVѷY@c!tE  + -XI6:ig GISOX[p F N ` R oObfWB܊d\Ѻٝ]0$]  -,Sy  uO"Bc@M>8u%F`  ( F %nP ζ]б.2Qt4% %D&~3H {b1 57qd8Y D@ V C A x W GDbx=̯bؾv4?<N2 < T6x*pRR 5 !y+\ UY | ~  HFYd׍B̽,ޠig4\0 >6LF /J{OiZN] @ X  K * w yD[u=(͆m2:k( 0 z 3h'M _  ~D Z9{iw : ' | y`9{< Ψ=יGg K zSPPZ Y4hQMLBB = p Y ^ /."ωNmD(ZSC t ~ ('[ by9 (dE; & M X N # XSѿ^΁}ݥLQcMTxa lk[ ^@X,/LOuw6=q#  0  3 m y!S.G(nTHp0"n { /)@ u|9_AB2JqC ? Q k   WSܙT ۭ,ZsSKQO a/F v9hD/+;FkN [ 7   " | @ %onv. & z 19 @5j}H-dG{ Z I U PqD O?vx-3:9( ~o ek # @ ,jQ:&Շ9ҁڐEGZ K Y[&TO# a (O@K N>Kot<  < B $ 7  X@ pv3ش}((Utp  Z Q M j^" /S F;3O:έ+؞PRH=CS > @Ce! =F 59/3OC +l , J '7ԝ܆[\<ifI Hn" L@1wj9 <@>8  A Q p 1CaIC׸߶*0Dt* [> j:r- ]10mH(a =A  P T-  (aٮӧϥљiGC9u ` )e_5l1 KH7vAFHDI' B 7 FA @x4Bտ܅(<  4 Ooj, .#cP@R1]r6}  f  o @ҁ !$~ y8YL # )2)G O/li/<+<h - e r w(x* .$ԮG(؛I)Ry P tW ZN k2+ = m X !nP =a"HJ&Ж[#*1 /  > Z,O J-Q{E()2. %"S  f u  $;ӆ$S@ rD*h; !b4  g "T31VUAGl  > `  k5ۨZќӹ  s y0X qd }j$M V\  <  sc Ӈ: 9L  3KdFD h g S UWߤպP5!  X F  ^v#uXnr2 M  Y q}/pۚցӈՅTDw#xD '  W&iXW  &1"z  ; ; kC؄\$߃`Y  +gU  .4%!z<  pR *Hډ7t*K  = 1v} Ui?F,gg 5  #FWֆMrFk] q B e ^c Tc +}% ,91 r {e Է-m 7c  Y{# uL`#  (   ; C/|Nbޥ%@ e  %= S u [sM-, W i * UhvՈL NRpj hu9  nN"5$bS   : s Ptڀ%0P!FT)_  "/>J  W@x0huP  7 k  nLdؖ MDxh ?/M`Z O %;7 dP6S<-X t  X v%[>B2 B f( xI(N!i& W   B  QQcP`Y ۛ؜ٸS ZmL p ymn _ OY Q 8~  6  | ] |h _ؽ`;\6^ t %B\A  3zIG^\p"  $ #  : XhD "ۓٱT( Q V tSED   F*4O bUt  E  B)7)waCE iL   V |] | Nc@   8 z "{!p' f  T _ 8`& e 4<k|   W {  (0. SkV$Rp P  P8M ?'\ x(O0~+'2#& $ , 5 <:0PW.{ڿ&GEa& h "4 .ltM7C5 b   I a  [ ya~NAސh ۜS CJs   . k bH/($d  7 ! k xi46 2BOA%*]* J 8Ru ` Z ef"> % =  < l wޭ wE12  5 > 6`k  qICLm ]Ii R   nt<K/ޭDM*.:    < T bJP$nq   P wN_;eܣޢg   # !   !7"Pm"0(FK\d t ,O .9ޙQvWd)D2   UV  c bTK!  t&   lM T ݢiG$A{Y et xsZH% ,  f%jޤQ(8Q     7 adHa9 4$P L  c uB@ޣY D?$   8 t EyrI,p x  p >v I=vR"K   y  ( gx)q T~3KF  , _4ߴY:T   /  (J a I  R e H!CdP"(  b  j z +  ^Fy e' Q:" Q V  Yg+; L- q 4  4\#a9"\<"2   r^(H5M,df ~ > .  | .\ F  'F | (<?-r| <  h  z  xkSS 0w&ZVD5 X ob ;, ' *x  h  r p  f :.` ? Z f  3 %\zS fHb2  v C , uo<c%~ W Ru^ - > [<y E(U y H  b 2 E  {. WEqX   dYA 4A* 2 R v ] 0   bB^;5Q?:B[_Bh  4q8 @S6VG   c   <c8!f&2qg lgV|D$oKYB Z E w g  z W Y\ +}z.@zL.2= P zxoc!2u N ' ? - S y32Q09# T:6  P?' =Ry D   ! ~0&h7kKnV| /QC#"zB79{wyv( k n  s   sG /L:.V$  sjq7=- u F + 5 p<q #o$-$n }&{l`y)VgE 9 4 Q M  kbS m em EW_T2~>ACg[i W    0%I@U&Ph\6do6+Y  P X g q;2 1"q 9^ ChJk~$/Qe3iF^?K D    AW 7DlvES5..Ag!2 u  2 u,t&uGsj -51! Ymd\i rhY9<\"MFU6 O   A O7j(!t=TB ~1- 4; `gdy+   v r  gr|1VgW;/?(`?Dr{h"T  7 7  _(Dw$=~H  R]KSW KPP aO~(VPbEy  t IlF P "4GL0"n=Gf  G S 4 H  l~Z1aeO#+~yQoXI05D#$t i  ~6rDD8Q5;_%hN#@Ma>o  U ')RN`]f1_qE^(1l }z2 }9,= ] O  ,Ux! 8y#Y 1) N y)Bay QbHt  1D/ 8K E ['Lb6J@ WQXRXeo P P 1 7<>~hOzh $=<>EYHm_>XEKuVN]+ Bek  W  c": 3[}aswd 3uI; @TKK\ %AevLD.MTbC>)7/O @> Qmlq6J% &(h)+_) ltvl,( z5jr 1;j 7fbJ :O8q{9LBJ  E|+ 7p+\V#E F]IC4 4Vnz W4y  i0 :vR98GJQH  FV|D&K9y 6J3Tu ;T/ "bmVZz/<4[ =L$_)%[  9 kex5O-9El v {x qG T.\dq ;XFZaxQ9Hhe~crmt 6}'kZ{[sI 94Pd Sq?t(FC29cGQU)H=Zpb'^@64V jIdSa2IK=\DTtLn1|<@}m \|_)$I=v]VG(\ @W@8,=0D*UV 0/=HGaec "Suj}k$%~+R dAf *n .hc%h.LDR }09*  / 'T=`RA`M S Qy9 &fLAlL[7:y-l)"`e $BcPW TZ =<} 9 ,UdB9L<t >y n| F (dG Bsk D V@N!x(?3/T ] G \+\t~!b %O8-?,@Iv6OT\4B'"8(@H0ZC1{n55a}  ^{~ J D RIhB P9<g  ,)5'_ t3r5 R *"+&F7M6=qit<8M0% ?|D|4 *;%n-$~@^}k(`N#Y2iZVY0 Y> %"Y%,g"  `F~Ln5$s36!h$l< |@D3FB1/E! %&j ZCir.s2;(Cw>I`" 8 4IZC;bQ hk?h`Rk*"@K^  KC!0)+"*o@z]c4-, &B=?x:;' O t-B{/o qsi   Kd7 LS!  SBw^ N!dpW=m%G@x([dIsYUzBW^"da   e5 4)U)m[6N0{=5(0 tuZ !+4g3 H dRW 1^8XF^2*4,R<O E^2Z;^I P.   H ` l)Q3l4*, 2#* K  \ a  EpJX)?2p'(i4K=c! I ^ :{"  C  '/d+ T+B6 7 % !-"s5  ?dE[J86  ,r(!  C:w+!`(OHS_A;R "%}H"oEQ/U(|=B*a&;, !), ~/  A~0- 9 +E(^ \.#T]?>;   *"q8 3o"1$ +&~0  ?z VPwHdC'[pAcivu v[ COYTmIIgbLRCdRs[**wBxZt c<y Srًۘ[H 7Q < c Q  PXF0  <-]rk H>DM}p]zG)S4x Q"7w w\7:/ ֱ70v n  O 6-LpUiX{PcR@OFfCON C2Z$B)3/ "4w7=q?ˬߝw ><f8 D  ylB-8C4pYnGujDD+,ixEwjWy%DS cB E '  - p u E`:DPwTWAKM<  6 _W 2a7e+?3UQx(>  k e pu?C0KziC`y 4v& j 0 x | @  =7{E@+?*IS:s \ 6ZטͥƐcȦ޵ _.]< b )^}$Z>Q~*{OIFCu;Tz 4 : s @ / >'bG5,Q$M c $^   TG    H Y  glML- Yf#;1#y`?#r$cO * H D , l+Ef@.u:#:4 H.! m0fӟJ 6( 3Xm 6   JF0_9^4I16)r5Vk0Bk2 K 4 H%5G$i0J~6/4< . b 1 ʤ1hl):0[h`0x .|#n*u8*^%q$1Ozqz0!m 6# r *lOjH OC p< p .AiD x=\E K    2\--j#eVU:rz3UB }  i [3Rjf}e  $ R f!!뽩` ! 5fPA l=Sm{"mM  \B4%Dk9D(Q( a X Q -  W/KqHc6U8:- B o GطRݦhE:YdD T [8fgrx}=| Vaoxy x'rA*`i FTd [ _xY>VS U/ON[ ~ O IfL.LIeIqP{ I lRPY8.J}M`LM3}PHY gS PS3 Zi R  [t^&@aqOYfl< { g 2BGmi!juPpw,1qrH  u z &zj-~:}i'~s H{vQwzmrDo ~ 7mkgY_jNw, e  } RvbYuiebǒݝ~wbaG Taj@ _I%geo$`ia=7la 6LUOjcdwc,+WW_ vi$d^ `<`LdO) b v Hv_-mbña币ɂޡdSb`\ D^_9E#\)VZU~_Q&2[Sj\GZui[gXVT S 8 'JT%ԻNU_lL fMvKp  eF?rT |p > G n =m9 !7&YAZ.B'ma%%$I_K !j}W^P  ^ ^=ZrÄw:DN &- *#{ s2[? R R/M1W!} A=D NI   } Z}Pq^Y\!T3>V4, <zUKxQmc ">3)X"E%m  #b>)J+v}9 M 0  ! y 1 A Q2{4 [4)q7p7?mUѳ8I w4\010K% '/z (4!( I "B5z9 3g  ~ u   ) E ~?^xIafJ;U2$ h ZXg< N w FSBx!w$Kf  1("4 !*&*q G3/_38ٽ{lu6U(5 <3H8 67>;/; 7 ) { 8up54+Ky6q / 1  >6cH ] 81j -,Mem.cy- L,O݁H6+Uҷ9 +R8s([h [ w%JV t& O$C.|1:+ ?Z qB{z{gyg pA^? Lop7S#yy ;h?Q) "  9 e/r4n>'lN j@y)  Gv|ry=mX L!ٜb nDN2 "m`qW }  c va.ci vC 8 R2k} H    G}=`oI`3ܷ('lAO j  m C tSNh aB \a ~WPP"N` < uu"#  e(2 9h _^ܠؙYPm`   ko7_3~b  >  f q  ,`A + 5 4k2 ? gyUuj! 2(;ݐ&g I& uJq ( }&w.quIV4Y P :  99MB( m=h  B L=C : v # C$)`BeL@B>Z*<5~9 W21U-"m - bz~) Pf&h<$ ROb\'dK(k O ?;]q  h 8Z j% g)> ?,{% DL p Y+j(/VXW/[>L)qSY{ G 0  ~ M e C  n6-v@Fu%0vc+2    yNq -(1e{()   4 b!.I.L  H NILoudN!=y "]L!peC&_kKiOqpAe IX:!DOfHO%j|% E _qj<r V+- 8 (bA hsX|[? ck+(2t!0qCzH!"={"0&Hh. I v6 8r tC QO7_U ]O! 1w@ S+mHB :qP@n0  C tV K 6r sP?A]* v2nx>TB 4,2I ?b- 9{%hFB5{H!2, 1).~+=-uP;%4- 0,k;  NR} ]22]+-f!$O3XS] UeQX :'&+  Pn:>H#GbE#`6P;e&Q^!9 Ao   ,=([(  x2w: E3E6 %  (%; O   G  F_ ##1+hWVE&!> 0%@~9<Zb=8cSj  H{gw3BZF~ ] v [ ZuY z~p B g r D L 'z; hx222M  !  tp+Lw9 ?e|  { r  =-eq k rO ] ?   oRu2f)+ > J6 &Y^ :9F:s S\ i y  ` a  _,E5ّԆGn\V Qc'<2  " D[ 1O>oX2 ~d n  ~ 4 B >uh8 ٰH8M e&H#- m'\#j5*8g3A v z 4 + D2Df;NT֊>v!= Hk7:; *nO!rM Wjt yB06H9.P`2e79ӬĄFuϫ{S s g o2s!7v"F|T  ^  z y 8p\gĂϜܻ] NoH,gZ? 22&yY-C2  y h g BM6ս)ÆB c jO\ ylt} "w[ SKP&U ( : DWb-z^CŬ3S^ʌ!M8 5=&6 !T / 5?)/ %*y G@W/j{7~нX OW+j [L ix~J r j$ 9 D 6 }d[M Ĉ9@ / =vU>m/I Re1[ `b$|96 ^ I x A^HT>LϛS̿ɲ&+Lik <uX(% 3 %u bmo < dJ&ptt 4  F9[ƽηZ;؞2d Wj=YoF' i X =`~L ?Ti5@{` (.ta+8Ԯ" c o@}.( )?k9F" o NP Qne  Q_JϞH&ELl,^:n P+zv n3  'O5 o=>yTD= R>f *t淼SˈYdID :p;!w! m~z 2 }rqe;Ec~ NI&0 v  119 ȡw.6 "UO5q+f `kjXX MRhl NXM{ĭlXX="Dii &rvz ' U4[7W` +m {@s\@gHלs2< ;0Vrub2 n S3k3|vpC {,z  gAd#KuWqX(-g(  #rF" >V7 um,_!q ;0,# C  PZC< E};bJPݏΥ}ӿt.PY fF 8 6f32$+--}[ 1 qLz@v w7X)Ĥroݟ&RsX c @ n $G?S fDu  vp4 RIy7#8ku fLh D_( }C9D pnO2Xw  4y7R. +'Rՙʺ(ĿEs?&l fZ  5 .%a_SF- 4 mc 56:Vfݺ48z4 , lr t u;7 BVh   c0 Q?6ź#iVsPz"33q ]wI\EH w = T3w^(^^ /%d .twF+\n̵.X' TjP 9"4% ;_G{I^% >(K l:\EחǔO(ȢX i~cv? ^Bz / lm53rfva H|B_ & m".LO!A@#Fw L'lF < G=J/cb7U> Y' M {:dm.߹Br_Y < bc)7 2^\7Zgi gG (I $dsݺ&Wf   d HG %6x_74l Y ^ 4vlsnrP٫]DB5U xnk50! `(\Nld!0@D5 a :% g # J| ;ݳ=ʠ|U>{< Z  O8qd Tf5(8: {6x[k 9 I53-jP/?q pb Mz8s $MYfC,\jWB7 ] \ =ȷ! VC$B|2  1 "7i_I "j@H;B:%1  Cd  ;moA,͍c;T")  x9AzFh EOLuo'v`g&V ,:] 8 MU_ffʱvy )3" 7}l<C (WQ2m H 8M'I . n {HöZu>ZM5m5  - ; YE0qbE r5yKZ_x4-~w W ^= U b  2 C¿j̳32R.(  M R#!+N]&o  0Cg@T.GS)$ %C3o   d^U9QD/4 '  M&G42}u< ~>qB"[^y0${vTu y  Z @ sG񿹴˰pcΏ: ]F0j C,pM36 L:D L3 F`Q yp j y x M[kC8;}@  5p: '&D> dDTo   Y  pBվ^k7hA0i 8.}i0 Nx7[!F-L5 \ x K } [҃b̥8=  ]29 t< :Zr;5wQx a _ 5 NīGg%>BSY= *m;<8d N<h NjdKr6X }N d B عGQ3SȦy# Z 0 '7t  UYw3 {WytlX.c (r J 2 W\:ڸkѳ` /g$,,5 B ?k+r*0 j!=nu4Mm3O%g G )2 ) n Q RIQ۳hB+KR i  lQ3  ZV{ -uXx^z]  E w \ QOQ/٭ݻ-۵z?e 5./, [ LR]! 4.a*DW ` v # G{nWt:. R#:- Q2 U TP c.JHY"RSwb3z % a u M .,IJuIʸ=DK;j3" 2VG*2 /e; )`VKP` ? '  t [   {P/NiɞR2 S@   Gx/ Wn 2AA{z{u.\ A3 C d )(2JV״"[/ ,y:)_.$ s)1<9I\& } z e t =hܿU:żȐn*9`  B,o10Q1 lR]wnv}~Mw=b k N &  ?˽3̶`dE161gk Q-2U27;  C7F ]8ZW5tX  d { a = 2B۸@9,|LO E;n  UUxo%+h  V q 8 Y`GܒC^tFUA uH0?NTG  1Kg e| ! Zpc ; > 8 Xf!ׂI  ^L X?$5L\:p x#x#tZ!a8[L s Cg9  ? 6 5/ВͷƠ587&9 lD(7ZR7 Die*_R re< _ R { / ) /\A \`cVh*7 &M#VGvk ~X;$k+q"R*AE \ $ Zh 8 2 q 4 η&J2nIBN;*  BGwz^e w  t7~`H @ \e   a % fied?d , ]Ah~ 6x  jT^J.N=   3 :5̼˹t<+3oEs >#Zuo p ,54fa&C~n   Qt 7 3 % xAjL9Bè݋?ZkV% l ! fC^{E L$4im|zr  ] R 2׃ȴ5 ީUg%/<@ HNc r(Jh"A BjC|  !U  "ȹKk/~  da" H z8V7*L78d( , . 0  w"6hΊ~Cl\ h!wMkyH TZ *#Q< / 7  U H \xgy}FȄftU\ =IW_- _7eA!.-]~V t {'  4ž^ILd (my#Z] Gl<OF g <<  5 a?ߓzɃpkcYi3l ;"GT3< cOe 5sT6k'b> , [H` P A+aBӭŔ޹v^Wj[ o  u;p| +m$,J a kO  * f6g~MH 7F &)ur" !R(&'s)k'r@ qRL@j  m ʂ@ aw_zl< &`F+ C'o<vfQz{Yyw ) p6Y :>[55ɹz*Nd}W# _}-Kg OSp_*\Vd QS ,vBoȵɺl$9MBQ79O G@;*R)8NT #w\,|\z4a X N5 ^  qYwa1M q ~9WZfp?5<|z(  U 5^ o (ХoM~׬,q4  yfTI= H SrI8/&z++W*+ R (0 >4mZ\Ľ4E"UZi  vUM Y_6[R:pfJA( - % Q %JȒͻmfw~rmU  Uw D %?~A[I=C" K O6 ajʔѽ|F_vZ3[- %xo7Y& B 6)2 t\"qtC 5ciZSl m>w5P/^TnZRT ;!GLGJ OBP^_U[wXlj <lq aݼQ_V٬/>%y  Em=)-N+ Mwoq2~+7 ;h > NL y x7߮Ƌϼ'ʕ-FA&$Ly m**bPw4 4.C-pVrduQoO+2 7>mb ;HD MG+~d9 )o=3@|@ m`,wutOP4Sb[ dPL  8Ap(¼=V> imG<QeHY  ukJaMk=~H +% /PX0rA2 RStbFx| y '=Z_Qm( Cr I 4=k+ >;yZǿD]"NRW & wMfC,;  o~B&=gN *?#{;m Cuf 8AB辑Yrstx s. u cbY2,J 2$:6>nd/ ,.a D x2` S3?H8ɹNxQԁ`hq <DSj7v ? I]*Cb 3_I MYeʜnM&E.mt ~] Q BSK3.P1)SZ^ g\ hn~:ؠv:Ǚ@vy[W4y?} $Yo~]/  _A|+3߿5Ǎ&O ?Qk9L W.(/So'^`r IB@j j}(g Ƙ+hܽx"Br' {>#|nxD ew f6R7?Xyb4r$Z   1 @1Z˹?~O*#[ ! i0a{w{ %fl e@KKdi Sh&4 o'ˊӽow\6E` '0q|I>~ 01lhu/VT  ]8/Y xW`1q8܈z xU gVg/Qe aafnd~]SnnK Q |  x L޻cȴ* ĭA؟F9'm  {`>  z a" ^>0 jYm sqE *pw:JÒkdXb54 c4SG`f^ 9 >+r\Ek/wx% \ x/G  L0%ĩCѧ 2;^ ( "I5o S?Ty fB[1v_? X Zzz N+iv]NJtڃA:}y9~ P?_m ^ J ] FQR-,  W6 r {˦*-m^3cqJw5 ^+r  ~Z~y9kzw` | mz $ 8vl9Ȗޯb1("O :Hzr:00 Sb /=NEK  " B9E  1oOǛ^ćIٕuyQn>/ z xK]} O  Y:Ruv qD a6- O}:JZ"+6|Dj F`T=<2 L):/Sg)kr gP - t#KqֽÓ"f Mpd yz ah{(dzkX ! I<y6~v6_ajh 3 7 W H< I%jX܏$LO OZ!7'7 kA7R'#bm rbt  yfK }nqhͅzUFHn w`_ ug K;65Z -U$   P B : c; t+P̡Q=bNhQ;F o f rf zxkx=dXz F ! }Ov|۫l*7Ɯbj]O;F ~//x t?%o29v G uJ bb $8sN*ڇZgH  TxFe xs1Jl gq\ xRHn vu$ bBP M4´ſ2Cz1 c _  O }7 ( ?jCQEk $pd{Z Tu6]̡~lՀ@~i]y iiu56  j{"'R^64H)#S 3 kSc>pf ȻѬݩgMtx'=Ze}w 5q o( rIȊ)wء1-_v ajOR  RJvB>sv(U#f w e heI1Čm F]v [unm gvf,|~4^S} 3{/* wEL؀hŹ'Öɘh_Y*nFi mfO3yO  iL[_z{ G &g d =1 QPbږC;&njFR } e K[~ #  |&F pvj>+ \[ HYFc3ȡ0(̍dN  s0 3GP2 dY&y"y {jN e3c¢ Z\ b`^_~mg V lu{|5<g>n LQ 3 H;`'ɊԿrkn{ k ;R|i >nd6 YmyR3 nKl % v#b ]_TǢ]_Ƥbsju Q fzHD -iY~Rbj2446!F5u  _W E'Н(2W4nL{ hvw   FWl"&zyhW2)^ TkB_ Ff0fʓÀārׇUr u W{8 Bx O`''wF fn X 6 <וOĞU ɦߢQ eEcg zNt{w 1N6vLt0 ? Q mqܱ]oƯ|۫]CD!Kg*: -qv &T!h(n8q!W!: m# h @sݥѲǝį@dGaZU A\`|R_ KOe9pZ * w14W [ "<%%Kِ*S R  =K!^: 3= ^YVm=lc} | y &snōü8r3-t _|%yQ *qVA^WRJOVF 0    v0nƲǕelF6]- M*fyO [z-~.@srKj^i$  Kvgs Cj#vLɍº)Mrנ9hq } T^t1 )Fz(j_]  $< ,Bִ˨D^Œhs m !b DW"0VscC\ \e{cU +t qCςžȉ|_Vp4%V9 f,9 Iy'qV5hge)J  E)O iZBwϚaj~z܋9}PE  x{   2T n}t\_s37  cPx N OZ{2}w?؂~"8IE  Jn,vI CEaXK\=o>Q Q} Znu%̏ď~n!Lq y x yI~4x)$ ^ iqB4aIzG` T 1g`  UGЋX?4}1Tb JO`yt st M/gHKyb@oW } _pU %tGBFʌ°q>{qp k -,-Zu) G! -rRfb.  4 e -m̎Fqӿ߮F[}x   V n7~{ n o}>| HtQ 0 ? zy]R oܯb$¼Ƨ0%L n7 `o&!} u3+!uV92 ^J1 \ԈjY؏tL( y t umt p $&Zi>k[[/H7[ $ P}u( < LZ$ϼd'ȅށ nlgR V iM=E)L ?:OP#7X]H g bB (dQ%mgVOΟi]O`R E BF > 00;A7I K(* CzK  4QR̗QFC5`]] e o ~W# : w0 wAsGtG Z ]GyGF 9 ېuC/Mǖ%geULR qx=:{ &? n  1, ca>)TdޠɴL+Ƌ٬C7\^ _ u0WXd h  d"2^0U?V6 HvTOP 7Re"BũI6+c u  J 93 J+2.KIDX_IRB  \mJ f]fϚ}c0hb 23[:q  M}c(:;0%?;  TI, Z̧]bG,:+d^ 6!BM( l N'm>V_5V ZF Qc%۶KȚȹe=_S# 7 >%^| W/  M$^ GJ2CQ;TFDD Hb>K@ . tH?hA6:6aO 0~l "yKqǿʔ2] & e*~% c8/d06 ?I &D'B "J{ނZDškοB H[7 v-P5Y jYz!e  Eo+ ?!M.>+Ƕ8řxk/)Lb! TSXSG  t_~^ 3_zN X`pn9 M.ۧBeGѼ`2*n! "u-Cr a G28*$/f $<Z H$I}T'QĘ/Ϗ٬2VN-2P \ "1Xl) U1L4A3D- f 3~$m '}е4=J(xik RSK$ }S-:vM:=5.@8 HH Nu7!KĚZϴQLjF yf8?%W |4B !u ]\ W0IKű$L` /d/r~7) q]:*A;A\D824>e< ==E $9{/vq0ѧܷ5%? qk  j  TrQ8}C~%  z/f @= =q0D8ȋϱٽLJI [ G pI# G(Z E!'A!8:_G C *d :GdJEVj {V te&, r50:AJJPz /uRH J.X<Zܒ9X Őѭܞ$VU*6M /(4G3x=5 m:"$Wm.i/l5%b Zk:   1;ǒθثL%- b 3`MJ=GO M D_HlJ> I ZCsmjI8<&}K,k OS g {DrZ'r6 "j 43V PKB$˼Jpڸ8PN T MV! @ S.LKH B2 7V,v J +_mj!ϺR˙ @/'"L  jj<x *iW4npAgC I! dFG2iңJƆ`ԲޅeJx G A @4 " 4'uc,&c1Z  bWT  ]ͣ?):({|& ^ 5j@7>a r  IH@Ij3J^E8 ^47y]( ^O M ) #  z_ƙɮ!B ,yb+7 A b*Cek9FJ\0H IA5#  FvWBygֳ\<s+) K -6d"| zQ7<LH4DdO < .+PH8D6Q=:;>Y G~RH5 0 nK\FE~vjB3  ;9r] .!#uu~C ~#]   {2Rk-~6:P ? O Da[1N ƮԷjZKmnc G 4%BW'A q=7vI3||(p J(/.2 pW̿Ƈ ɮC %pW7+5 T<9YV;qtCO W *=^[ /;zS.`*hלZ-lZ4 & ?<$ No6Vj% ~5 D]LOg.߰8WPo `_r\# / `eo3^t`SL P^m OCMߐ7\W*UY(V q~ 9< n /s4NXL'  /G 3-L3ǭjc:k|` 3 $(37n 'g!j!7< 8  X5(9  ̆ljʜњO78$@Z -S6?f ,P?z+C~FAZj1AE ` .6?JM B:l2H5ƨǙրJ(4Gp+ s#Y# ej) -iT<Ot^  e't  p?Q.&Ej7Q%A;r CTBIF d 6.DpA>tnk7 1" &k#z~дkO "  am<8 >D%Hz8w11 \: L =Ip`Cf YA=L?4.-~ #<G  27шʛ'ׇh 8 (>\ f 'cS,5.EH3. 4jE ~ 7iSԣ3ȋ̤^, ) XK" Qi x<  #9o[I ?&6)L/Jl|;u C~P'I) nJ<Iv/H }!wF  w LJ@3A @6 ܓ1 :# A\  ZiP 3 <zzqU8 G% T,bRמ3Xє>5]KCV 2 p;.C t 7+L2B  #I%+ 8~̢ȳiZN , %24 ,"B vE02nF8K5(h7Ba. ] =U@b,?9 o?7e5QY5:-) =8)h%rE} 4 *Wqw(}eV W N  3V } k҂˧'qլqT."  5gB[O4\9 ^3!J51 ^7)TD a@#xn p8RP?sɯSWڱ`-N+ / k8^" !wuR&0%n&7 n-7 31Ҹ+7η$WGP  m g ?   .qov lw i' F1֬S@_h J!_:S Of<y1Q$ T%5TsMeS,  htJymx =C(9)ȁ-T  ~:"|\ >  m1iUyO $;; W?0ߢ֐W.ȕҋ0M0 1Y/T( }./(s ] r s3ђQ R" 6 Y[F"B *Pf/ ,5  + 2(; "[Iy mq :5 q 5 Mu%I 0J{ z< *AUnWRO B   ~Ӧ̻Yw1"#" ^<s^!5 + /d6_IL m9~NI )e, !Ϸ]U<i* bY )`c02 $ G);EYd?fkFn iF ?yH@m|ҍGnΗ~A  6 H/Y  'm!pvfY $JY :!K\9q̔ZݵG*[ 0nW|%3  T_9 67[8 0 'x"̞kɃ2=o 4 <7A'  RQrW@+  0$: {|8"fxՔA(Ӝ(@H. ?_u<mG j9q/>GZ&83 a 0 K FrWeѹ{ Жo<  #heA0W =v8AQ7T)N< q;L` TIEo+?Fymp@ FO_]Ea4 aC1S!;0i8 N>,.P $"PQ 2 qE ^ Y  y9WH  Lm%iQ@- 93I 6ڂ2ɗ'|q0h` ( *Q I %.lgm''_ 8 6  Y .+"+WN5Ԟbqh@~ HE %hL, JTP_ZLcX2 | xVT ? |J#N6A_ˮ$r89.0 7)Jn!n# O * \&j`|>& ] y! z" ծ]-K*SGa" 1a`=73 0>xO&oK  ^ 3e {  q1bˀ ڢ_N !APJ,J 4s c]= 5d2o(.)N ! LNgC^b$S- Y "6[j *nI/N=)[%4+ G7g g530Ϳܛ~v,p haa  OzJu8 iYk I- =.{|~6nF*C94I KuQJW$ oXLg m56"4`(1kը߄ e8 )7|d  Jx$a^D( \7{g _Q:A#Ϩ7?Ӑܿ -?T " @ Ek7<c 4KUne,2% ]` cm1|\ R5T6Qp  Y! i'ra([+ *-# @ (h V*ˤXI!! OK,c jS : 8a#(["  y sx|SbӲ`!C j- /Z/sw1+ -B+C' ~ \"q f fjbOEI<\  )=' -_ud!PEHE(%  o#*& uK4p)4д^D4L: / {}D'; &MmJGt P l V7a Ϙ  lkY S ./Ea@/!i  ٿ5Hڮg { F/4 "Oj.nT/7 86< >H>Ϯ@brAUHe1 :;}s5]+ ++?Q iZ k = P ,@ .TL((! K25@E4  "?.Cw@H MkJ ~VFy> GDwv;B*+wR<|1 #%  :Zr B 5+LL V <{  Q(=`?̦"Y(5h M .P~w-4 60+T81W)>.  UM%SZ H.pܠα\}Q y r zTs  j'o{h)qu7 ) |7;y M-?szB@& ܽC& < bl;nF 3g .HCG0   |F}9 Ԣ/˧У  IJ 39\ (i  2_u`W4ef9;$ b 7=. 2zy2ʴ iCR(z s:U# F  !Ohe. l\'}R L  I>w jl#/)LRٴd:0G  0*w3A 1W //{ph$m yF{g0 <t8 !>,ubk  :Qr.Y &)%e118{d  H;/ @ s?niXB;>?q<g  3 P'I06 ^?u H#;$+f9I>UT7? / K)%  2fvW L;E VkVX p Qy ϰY%mּj+B 4 d7\+_> EakG F$ b BB+ v>{$3ec,?uY! -63 c-   c6sAWR6 K D  L6 XC֐6wא \g^ !F%p% ( (,[k3Kid  ; ># }eҒ͍xT۷2"cSr &)kmnHp0 -7'x9.};  ml: E5,3˻4+#T2 # `jE-l% I  -sr ,"'q'  >t & +uD*z3j>'kHn P Gk;E Gjj?88 ~ '5 -&pr!˙6-iKT5 '. e $Kn7#%R1 8# T::cR_<E# ; 4%Z5 D ,2kiK&mZ R|, g SJL ̡ yؚ gd s  bk+$  24+:vw1G3AE/0  E*sN E)?X+ʣtTV" y ]3mQ7 E~V]#*Y 5 ( ! p 2ي,BNi' K+pY? O ? p F 3 xM 1˸`j-a] He'pFr. E5bpg]:T]A.  fuA1 >܆AB:<<$6%@T. 4 zWO* !$^JUM+ sP 'L < JQ! ϴՔ"9%(q`  [0!4% '=9%FV?I9p_5T5 M 4 ,P["~*sZ 9Fb   2h] V O6y %ler(̹ϟւ."}P #Q*{j%( % /:bNTI 7 y/ Js- CӈEhn9l1* : ]"},' 4*moKD-''/ &*' ;+$˯Y]qA  2  6 ,I)O(J A r1 N#9`-ٍҕD%ԏJ^hO B L LE L&KcpG a =  10~J[$̺JK:8n +r F  0t[ukH! (1 A R7ta ::A[*b@t3S>` ? t@m8:  4j-P44#V O k }ֺ\̸cؓ[b  WXC>  6Fg8 OVD8wػhzI  ^ } v,zOZ#Hh.H 9  w3  =Է·Cн5eE='f: D0A5 s>zwF8i, ,;6w _]]2qߘͷ>{IFO H+; [  9*C|eD"4dLqT  p/R UBT{4}UܩTD-F O KsI  <YQmd2>&  o4 % (!k1yrG62 n NZ!7P -^S(ybY)vcp0% } 2+  >*n! ̫T [l" /\5t {9 r i! )skЊ-̚,ֿA6vg 4V+[M6_: 3 $u1_+4-Q r(\ 5OH#Eт̉ˀԷA   !  bub(~. M WO3 H/N2'50-WM2%m` , ys+" !j;l8GM` ^   1ϟ'L Z  @& (2(F[57(P'~ _&K 4 U21cG۷ΚC|QB  M: K 7>a )fb #  , p`0.x';_Շ4m:>&  :~|J6l 2!i)m+$[ Y4 Q +V .u 7 (9 2an`=6)9qE= ] : 0%?R pBb{3ANˉ) K>Tme8 8 M -: #}Hk  *97/d{ --` Z/J.C6 I &]{  A:(K g }[ W {[ aoE) 't^ueG&./ H <6 j@j_zX@%2۽A-@6 ; o@d#9  Q,3j3v)f &  urL>^ ^  c 8օF| c] " N(p/ ?97RR=J>mfAH( U BW1 q=5A:͹4G3 ,68;*) &7$ <`{M &}oE  Gn-Q {qԗ\c;&?NC  *U;z)x  $-(/b%l&"t *RBt [oRբ( @ X| D3zt1 P @8(:kQ2*5 S8 sV=bֶ"\  G  0' AEv,'J # S g~,|m X fw6.v?]Uڦ[ME@ / JHE  G"Elh;) O 0Vc 7) Mͦ' [ 2X %HilM5 0#DZv'962 z `;# =vOԥC$J?(=< 8 d8n-7 ,k1p$2:h  \5.u sOєK;o 0&1;:* ,chA=.!A1 O, J'] &ΤSb>|I jn  ;Pm=,o0(d ` & af3- bX6)_(>2^p=xt  @=$=  ,8P}]1Oe/, %E S4$̩Pp<k p j$ KRhF sS  's JoX֓6! ~UV   y6 D:` @em0# H`) [~2m.:+e={N <A8-;B h@x  w<|)0Zh)/ {f 6dp4fЬ͈bD75p )xi!B^  3.3Hy\O6 :$  O5=yJ ^<=5ٖ:6>1c~ . b+m'M) S_B !,%e1 B2 S $7 a2Wڳ,+;&)O9 : e   K<}W $'[ l F OQm  #e~Ѣ,7-1[.5` 947H 2;97A[/ )4ZI4 U$g:Qz։Up ^ jI? *sTvWe" h 3%R 5'^ *<'s & M,2  fh/v3:@ C <  N 6$S]ҡΒҞH}Jx$ < %?J%+# A34r30/ l 8- r#+}S>="V9yVD _ H<^ 3  [\\y<v]g J ",Q [B)8J߂VҖ*_ѣF0=< /U6gy1 ,Iy'x ` @ o lGqo'<ջܹo D F K  R&3y%aX o*5 0 >)V C'VU&AyX  3   11Hd B2v w " hڈ8%ѯ֐l&2@8  -SW2Ns  )-.F|^J&.#S[* <O 2  өyϾo$f-w { xt = j $` >sA"1{'- .&( g+i^ۑ*ϡOmFK$ i # t"x3 p6`o]; [ eu k=TG Za(i, _ o2,5 -=$w; :F 8 Rs5W\, .5 }-bވa 8x ( ! a z2XS& ~ 56_` beU&;+ЕԾM/O \ /dP - ^ ,z"k7$*9e$x S\ u dM1 4UЫZߏgFvv  = B * T 4zny;"P#X[ 0 f# k%=ߝ64ТK/X  y   * lL2,BZn_I MJ8@  _k*۟'r10ְ\U2uh  Y5k#6 0<IQ;#!B5 Y ,- ] -,"ϬLTd, ^ o  { 5 { 2VHA ue] l U9n  5j`Ԋre"(  `CuVi tF]' Gw\ B e }-MP#֜ܝz@[= ~ zfJnn!$ 7 ms)L"JB?% h %\v r  meWg#PUD  UjZ*  6jVY  +}?+ *(n| }3 '[ݠױL!Gm?"2 G S !-b # i  j8)p s % d GG[~Їىi - )-%   \v$nzZE&5z, j *+| |'U ZU*Ѥdׁ#Gb  :R3 4e fL kYb 8 V1 d {`2ٮ');/-4L ?+ui1 40 V18p1ck6 Y 3(atB &$D ܆Ҕt҇Qc$E? & "  .|qx?O%b A _*` i2s߹5ҡۜ(4%c v 9LH8I V2K)*z'' H $  G3xl! UrѻOo.c  b\ 3QafH).  - CX&Z #lFy'ҼQ"#v  9+ ( oW0 z%T G{ I! 8$fXٰyAY$T C Y )+[ m ${-Zira*xy+  j 0&v )!qѓy \c3 2 #Xm   6w}0  -U ) ^%r ~)J!NG&HۻG@{, I + 'Td W'?Rpye P  G+&׻ ҁ 6 T M W~sOD#M { ]'7c. 3:. s 3: Q1z.6]=A*;v (   x'd+.&  d$  @0մ|A/ i\G ^ o o80xq ? J ;  ߲ձTz@Qf  qk  # :|I,7tE-!.dVU* f ^) 5".cچl/(ڕ]p4 I * 2f+~ A$P@"dls  A7.Uӹ١f3-w  [JaY$ V 50)cnhT*#+fe2 K 1! 3)F.ԯV/oo#, [ Q\g$m  E]t"O D {13jׂ?- 'K$ : }9  ;0r_8ad 3 S QXh v`] ֠GA$Nf   V[5 A cz3$D? *dcdU<  Os  VbӃյh&!Gx^A  dFrVu b14O - %% C > G V y"k٫՗^GwF?u #]Deg( 6 N ~Q|'IqP(5 &w^   ""stݭӧ8m hzQ   /3z9v`ZJt" { ,{ 3EpqYj8* : G D{7m> >/Ku'g817iy09| J w2;  ]+C"v!6 zH 1 zd+tg0<. 4'H bxߋ٭[ Y*jL  o ;e\9w ;_O^  G ??6FP3a A : P _G  p0_3k    / a>iԎ<j    F5<6Fj^z   D > yV\3,ٓރGd!8v` H # 7@!h >i,N(gQ /A "CR(ڭփ66Z@) jb o# L= craS6 l \ i 15?W3  .ir 54 IKg$;!/    .])Sgy8=. z %%N k Dc&$jk2# % Y ^8 G-o. 7W9 %a  @Z   0yF<1~D$v Y p" ^ x&Mى)o,ݢ'86 ' SD( V#D"7rE&2' u   X?a x֙xT{ F p.t   t1 "m!a=$  :  {݁ևm C  !TE 8OIJ 6  0_Aܶ#؉VkBp  mnt|d GWgrGJhW Z  sP a`;)ٍ׈!߈U+.y }x  g B_8%!=vk&)pM)8 ].  S4l 3ذم+tT2cRp` . $X, -d(S *1a g j s` V   =i/DadT+4p s WG ? b F-J`8DIjM 0 3b  ~Bs6DY.K m W XjP*: &6 n izٖ:NO Fu  bdC ] Z4q.}8^U U g X \ J)XrMْ( ެQ#s _B ] gW  # 7wX3$ic5C  v  T !aEM?P  bk E NgA^o>|  E oL $V R ߃ۅُۊzX[ 8G ` v MAmX  2  O ll8Dipd j ab  ZIY"9-x;+   d >z_n۹ڳT`,l[ *u r  H'  ,) 8M @J p x 3  +BG,Gڟlk&V]  ,A= . m 6b32Ah-*L% E n . 7 6r' xyt%OSW X v  h ARFU~WL   n ]  wv ?߂ܕڵ qAJ^:Wfw  H2  r LmG^oI8 JW    gz "/Pg z  % WR N=)! 5  [nZO%:Z' se  c g$/  9? $uf8 >|A a R  S  ,LlRm߉ܱ4A  j r 1  ; fb[u;5D   D -jF@܈ޡ8(e ; c K y  +t!f Y<G y / C  g @(#߆ܽݡL!(}J "  Xg % [M1"&: cxCG#- $    mX4 Y_'ޮ8 ]   u Vh1g R0 {- $ A H d ")cޑߌK6v G l T ~ ;H^U l '  L |$ ;N,,I(AO@n  I %7S  mF C}?5zM   # 2YX-JoQJnk  - o s xQ 2T~:%M# 4 ` ~  sg3@N f5'' R ( @ 4 po  ' @B|zitZ o   ?:T! 5f   s = P  ]4fxB8!3    c 4 edAzS^K h J %S A  C491;^fv P  SipajsOa,z 4 "  :  , J ? %|^5 5 + RZ8B7H    ~IsRR20n"f F  \ I uMNn 3W ; E . n  >  >G?^noMl  V V 3FpP`+} 1#y a     /t 2> 9a - g["(-T _ 4 5  / \ ~ V  [D .+N & B F 5 V iu 8q C l Q H A  Xi2s!Qu# ,$ fw-]ft }g  w  Re_j< 22}F U b 8 <PL~,7$V= [ i  N ` D  opitk    no >!g[U1AI38  @ ^ L a vNU(p Ff59(64\=ICs9^dp *-  $ 4 ;J3sm".*w[+BIwQkPE : U < | F Q# j6 ' S91" }o a_rui"e6WYYB`OZjEeC jZcpa :pNK))~ a%%dg4i of n]WP"Dz2 "1' /KCF. 1) q0XT F#9n*h y $Vef]ka+iio<" 42v$w9V9 I C0+aPN 'R )Of` i\D :Td( #F AzVbk$w u7J.hg+u d>E 2-e P H}6[CT7]"4j: c }OzcAbr(#B7Y SDk8)oX5 gKl^ IdI Dfc,;- Yo j] /e^` Vdw6K9S<*YH QVNPHvrEQ+e +W r^lE /s ,2%j}Jo]B^11Sfls&cVx-OQR lh@'ICK"jHujhj mlf jTzc c vR ]c /sYiN`64 {-S? t< =8YF-?9$]`"Kw{* >^{hcK \XEV3V\JC9KP#i'FF}d[/UHO~inf  5$~#Kde*bcfljl2fur rmM&S@&_  R#eQ+[y  =N M$j i q} *&/odY&H0:)bs)_MYy0  ^ krkf DP $_=y _W Pn 4l1e 2 f ,YbCX H#$jJFw|~hDA%!EH  k]XHQLVirkzMHH#yvle,8z?0A*q4l`TSl2f OG&Qb/[B'sSCV1w; P&^ }i~p6`0"-d1/YimT#w` aw.6nPg;aTjv  XQ) _3;z -(.nxsqk`2 \Y vr-  0)   cyv; Fok) 61 !Zh#  [O" ofZ Gd1: PeT L E,^ ib%R?   ^J  (6&g$ 52B} \.kV!P_$ ~8dS'U;p~1?)    L ) -+ |/ 'L >h. ,~ X8 *, $4$p2 <  gN&fP2qS   ;*7(o6  ^H ju^;u!3#,(3 0 z7  Z^$*cO/gV  <  O%6%*I8U o$ IT?LJbHR 0"w.!:1jL   $, o=  #,t5A +f'3/  #! 9",#y5*eM  0v;   "+q6 >  (c';'  ,&w2 AOY   %<   KQ1t'(  -x:  %%u7E 5d2- L" A[ :u&    9 3+gS7K-M   %6    A ~B          B  G      (l9E1k/  *p5B3p,  -m5D3m-  .l/H4l+      H  A      @  G       'n9C1m.  4n,D2o/  ;gajim-gajim-1.1.3/gajim/data/sounds/bounce.wav000066400000000000000000010451361345766322700212260ustar00rootroot00000000000000RIFFVJWAVEfmt "VXdataJ            #17LSckq{/Rd)G\bv  v9@rw!$XT92 5+@4iY(yl}iwbq}B2m^%PHyq dcZ[ Y\  -=bs3Sfz.,  ft8Cs{tx"I?z!bT%zwfTD5# dR^KP>M<`Pk^J@yKJ{{cgiq$-  # I W q  - e t Z h    ` k r |  7;FEjh97,(1,  J@1'OCMB(zodZe[OF_W92KD ga,(;9VT|zQQPPz{  n t  ! o u 3;(. k p  "  % u { SXSW>B}33 ]\fdMK20TRecGD@={y75SQ QP-,a`onSS YY | | L L  ZZaa))==22:;mm   FG^^uu55>>))..00<>ssAA__ Q Q wwaaaa??  iiddOO % % BBqq  $$%%55uujjXX??BBssQQffCCdd55gg ^^ nn1188++ww ;;YYBB xx''nnccee,,kkNN  ;;   7 7 n n   Z Z g g W W ??ttAAVV}}66hhkk~~JJmmeeJJrrMM bbYY  ,, 66GGll;;ii~ ~ " " w w a a   & & I I 22''ss>>3366>>..##JJ}}66IIvvww--RRpp {{ nn++99RR22YYV V   ^^WWBBcch h   rr>>6611VV>>""TT)) ~~iiRRPP==~~  !!dd}}vv  [[RR''77 = = xxZZyy??HHhhޟޥݥeeDD--00**// ((UU;;66   55ww33>>++  jjI I r!r!""(#(#1"1"- - AA//**..11kk " " 22XXrrqqSSeekkNN~~55 ((ދߋ%%;;//""gg99 vvOO 88bb55HH !!""##5"5"c c ++  55CC,,kks s   ``gg!!ee99}}iimmZZ//ߵ >>~~nn..AAZZBBtt@@ 33&&r r c!c!!! ! !==77[[99JJ??00>>b b u u    LL}}]]HHޭ^^ 33{{ &&DDDD11@@BB##ffKK11wwii aahh !!^ ^ ZZjjddBByyaa; ; 4 4 EEZZpp++ ߕ߯߯kkPPIILLppVV/.  FEWVdc54 !! dcGEusFCTP-'d^rjE>: 0 l b yn#%g[F:.#`X߽:284omKQOW%9m)@Vq%@.n; ; y{Jb!!5!T"d"""""C!M!DF# g^~rn_( pU[;1   V 4 m.; 2Z+Va: y E޷W3ܼ5& S@ޢ>6 FIy(7,5L6 0V!OPJ~(_.U> 1 &!4B< !I""""&#[# $:$$$e%%%%$$t##%"C" p(2CJliMEyh=' a5Q ! F  s92]Qt-x13|\;ەSCLx>-٦ٳمݠyW[=*MDUQ^_A^^%L=h -7v5o A UDn%5h"";%%o&&&'&%'o''(K((((#)]((3'q'%&&$Z$!!wKq:\IZ)5QQur Y !NyE yBr_؟2փ6Ot*e'ՐվZܮ;hn +1 .z=VE e ] < @#l#&&))W))***\*]**,+^++,w,,,,H,{,+2+))~''$$"" &TO{'x  "El. L  HZ"1%1$ khRK|r+gUӸ<" ҦҷҏҢvFӿԌ<+ܬk*ߐKrGSi<@3,x--}EJ m 3 G  S!p O ##&&)),,,,"-(---V.k.*/F/////P//,.c.f,,;**''b%%a##N!! g  } M /((o`o =F b'hobڌOf SW/ Э~Rc!Cб^ԁԷS1ݾ'ޯ݂Uߌy9@^$GD|4x\hv N e'q"B"%%((++d-c-^.h...}//o00s111;21 2110T1N//)--*%+v((& '$d%#$##";#|"#!" I%" e O Y6o'R_=>I?pZ҄b8 6ͭ͋Ő+̴L~&ϯγ6>ӻFՉڍavSn_Uߨ(x%]#kI ` |(,!-!i$u$(%(++{../#0 1M11/22/34c4>5556Z55X55a553X4k11.k/,-*++)*(Q)'\(j''''&-'$$!8"LL,x O0 i q @E]Mގޯ~ُT֤`ԘKowͤ{lVyYɜrC?ͽ<ϼw~Ӷ=SbWbc٫߽۟޻Z=qjJL h ~ Kk-W1r 1$u$o''*E+./t112^3844w55'778<9;:::R;:V;:4;:,;m99:774.5V22110l0.+/--,-++K**''$$*!H!L < o]3f ޿ ٺX+1Ώ/Y ɧǩƇ"l6´#+ěƀȆ..#<ҟӮ՛״ףڞ'*7Am< OVj |%%(8),N,>//2<35*677889::;;<<=====E=T<<~;;99674522X1t1\0s0 /1/--,,++ **('%x%"|"}d 6 l=~GbOՎW͸d/̊YCźŜxmKýžt``Pvi&}{ψЊнНѥҞԬ!3\p޼c|!'D s#Ai!!%%D(](**D*+,W.m.$18134 66w77!9/9x::;;;;;;;;V;Y;: :384855P3N3x1v100//%.!.x,s,X*T*('%%""' # \Yed~}*)ad.4%BJҧЮw"*_e&,SYƷźšţ(&.)PH̄zΓЈWIkZӥӑL6Զa~^ +~]tE  | U $#&&((+*E---/ /003 3445555555555x5555G5h5b3300...9.-.f...h//.9/,"-**''$% 4! j^*y i 8wXC)ZPtݞۼۂژځׁِՂҾЯβjB̩̽̆ʎʾɖ ˫yφsѧзF2ѿЍH1ٿܬ:'k dj S TdA=.)$!!""$#$%&(0),,00g44|66675T6|55W666#75>6453?4394V33232M31d20x1/l0b..C,,P))%'&"# ;"td $r\۴fy^Ҟ0љ3β͊ }YȹfFQƩwřkƔG2b3ĉ$Ǥfg̻Zu!ch,T&tT"/ 1\}GV! "t$$'{(+@,e/02E355977O9::;<=?;@DAAFBBCD"EEbE FDWECLDBCwBBA8BAAABAVA<<445,,&&8 A '"N:^H  #Lpm@XUٛLћж͢Kƌ'"ȵ i뱇ױ˲"hƱްF=I.ų^ÄsƑʐScЗֵ֥TF:fk:!!'M(.. 449:(??BpCEFcH!IcKLNMO$RRUZVuYZ\\"ZZUdVMQQNNBLL'KyKJKuJJII@GVGCC??:x:54`.+.V''t ! pV a-SRآѤ1z`ѹa;ݫEЬDխR[Vѫ)y[^6bŘ^=֑<)|i[  zcm#0$q+,W33:;.BBF=GGNHCGGF6GHPIKLVOOQRS7TnUUUVT3UCSSQQ P3PMM}JJmFpFAAl>U>;;7h721++%W%w  _ ZZQObajjռ-_t͑ ʅ߽a{ TYfδMaֶŶc\ wԣTٽOUYh:1k 0 f Ngh!)"(t(H--T114y4+667P8k::=b=>$?B@{@ALAfAA@@&??? < yKٝ۵gۃ۾\ف-VIQd  6KS2 y ""R%%((*<+.T.2Y25 68+9J;|;">N>y@@0ASAeAAB(BCDEEFFEEDD@@:s:43,,4& &) T ( PP2}+>;#6Ҙ0̿^ڿlZc)/wz$h_rTͧoC緅sw–}ƅ>qFF`NNTTVqW~X Y[[]^[`a`Waabdqe~f6gefBcc"aa^s_\L]Y8Z-VVRSN_OdI JoCDz=lĮBɇc+ҁ[NGpH H m!f!U%%**b0H04477BD?f:#;7|8,5501-++1%%jv ' PzrS CMK YM؋سΙɮFLyd3 ؿK~0aϽilMÓX3͵Ӛ)o1u#gSc(u_4N _  h$:##"##$V$T&&0(p(''&<&##_ m mnmaP _ =Glr^%4GJT`+߈pRح@X2ϕ΄,̜okĤ+Wm{5ɱɩ{ и֣֮ۥ:> ;;?e@E=FKKDMMNNgOOdPPO2PN{NKHL.IICFFqBB%>i>96:66}5545^2f2,,%%j  {>ް-ٕ դ@?æ%Jհ3?7VdSgӦ ~u 3FׯcͯqRh#OBÖtʏz*G%6i8w] b"(""3**y33%==DEJJNBOR4SQVVXqYZ[T\\\?]G\\k[ \\\\]z]^^,_F__]x^Z[UVfOOIIC(D8==66j//2'W'&=ONYw:w/ݕAԂ%qkF̺bfݰխEyʩ1GH:]_t4;,Ræqhm|ȱͣډڙg&  p$$++1#26B7 >4994<5U//'G(ra@r$L*#&$7(ћUͮ]7÷R>еueެmlIQ{ۭBiƲMKӾ5b/ʂMϾ;%ߪ]dih z1- X&y&,-,1166:+;=l=> ?C@@BBB+CBcCBhC,BB8@@4>><=%<<:$;|67911,D-()$+% !F^jyW ] 4 ^_6aoifGܽ{8؊;|ֹա5><<5::p7K7"43/l/*y*>%$M b  eBJfaOX׸foTƺź$mph8[|'ҧĨۨ -n_νIkkșȗ͖/ z t|f|^co )!Y&&a,-2x3\99M@@G^HO.P VVKZZ\]^^_`aabsc-eeg,hWiiyiigHhree}aa]]SYqYFTVT OOII&CC<}aj, !!((S.c.2296b689KD>{jܿo#p՜9է7Ӟ"*̥IɹȑŅ»š@,oM8sG؅zݺS_Vh& T/ B(/($1%199??C-DF1GXIIKPLOPTPUZZ]H^n^6_]^Z[VWRSNO[JZKDEF=L>56W0[1I+J,%& !_=o D߹'kճ@pκ@>Ż͵S֮멮֟ 5C]~֢G(gAѥX&oh ܻöȭǜ΀͠֐aoLO Pb""s*V*0044H666#7Y::@uAH"IrP,QVW.Z[YZXY0XLYXYZ[]M^v^_]^K[\XZVX/TnUQRRL"NaGH@B9:23T-).m(,)5##h^ @$ -Iߜ+٩ yŏԻ^w"('D)K%EY Ry8z:Ȗ_.! Ǣԡ)I{L0k м[? :>c~<((283;w<6CDIJ_PQQWX^_efklpqustrs#q?r;qSrrs tu0t-usrtpp!llVij"ffalbu[[S7TJKAB9 :A2X2))q5Y kӺn°ͷɰڨ6V֐󏁍-PÉ{:=pͦVx!fe̤,559$W z4 ()).a/4*5 <<DDpKL~QRVxWoZ [g\]^/__2`^h_6]]"[[ZYYyVVSJTWOO}HH@;Ao;;66(1_1,,&&WW ?9 sK?C߼u%>тѽi̥˦`͐A%яJϻ\%ؽش݉e=ynWQQ47 ' 2   @ P 8 I Z k } . =  FRlsii^ZLF!g_}PP ! &  " :Di}LeKh>Z1Q  A7 Z  v  Rsbq3Mn|fmUXi_^BHp&p<`)%\(nERIj=o=F[<AA-;=X 4ePg ;nc&vR "".$$m&&*s*-[.6113'45^67$8r88887U8E889 :92:673 4p221100./L,b,|''!!&!):"x W yG^o-*_o6IВ(x- -šK͠Rtq1LQN?󣵪qUo;ȫ6-ٖ  P*1+4"5:;e@@HI:RR+\\Mddk~lrcs9xx{n|~~~z]{_vv-qqOjjaEbWWLMfAA_66++ TcW [ 4P45帀'={u 3Հd  O'ǔB%ġL7Ʃ,Ʋ彉R}ߊ5 +$=$-.66??H2IHQQXtXk]](bb ff~ijk4lmmnop%q oomnn&ommhi^bb[[T.UOOJJMDD=Y>77/0((![!}7-()+@wD*-e9ô%0dٲAbXIJ"tӴE% o4ɟX̐b ՐOu'jQaU!5!W)4)1h199@?DDIINNSSWW|Z^Z[[[[ZZXWAS+SOOfNTNML=L KJPHCHB~B{8r8 --##d`RR46#PUaf`f򳓬Ħ@E-2eijlXX98|yȲIJc[G?of˾Բ2&(hWw f ('--;1+1+55::\@O@FEJJMMMMKKJJJJBKHK3K>y44**- $  k=8oOچQ͉|9Nͬ5uݨIauTĪ>٪U+ذcWQÀ7X^1ܭkh> t r> `%%)W*T..23q44-44q4 5O779`::r;:;9:6w7223..Z**5&&"j# Vs<vd ,:eGtYxވ%m^[?ڵc9e/dN ?6BU4 kCp4 <H,M]l{BJULw y  h 7 f33c^~ u# VyxX5L{$S"I^nQKIH~qpeu| mNT(oMHUOg+ )% p Er>PH""%%&&'&'2&&%%$m$##":#!!Woa3@  {H3gnfd}t>Ī@û,﹌X(v*t&i`5ΧcI5B*Dz ( )061688>4?DHEJSKMPPUaVl[[_-`a&bbacbdde:ffgsffdd@``Z[SsSKvKDnD==7700((:bA P iԵԀF̪eIJbT±_1H֝]nדR 7P—q(ltTԥޫb,Mp ρϜI}^?r  _[((22;">{9934,9-U%%KQG y(ޠ4ѫh.΢]0ʗ?9ʠ7˞.˵?qipc ؃WُޗyVhgx}w^;z p n n ;H6P5\: l _ C  5 > \ x< 3 c Q   z @/i4 1 B|=kSj    G 1ZF(@z`O!jzgXz;eܩܸܤsj޳ <]2}.>""0E g  =u CC$$*)),:-.//L/J..g--<-i--.....--++;(,(z#c#xV) jjI&؈;`ˍOWƆ+qŽ=núf)ڿE8cE{eօxqu8M; % Q %X3q#1$T)){//[55V::;>>AAD EFG0HHEHHG)HaGGEECC@ A<&&0 0 dd33--\"\"&&1)1)))t)t)g)g)))**))((''$$!!  bbkkUV FFEEtt..ݹܹ''FFϬάΟΟiiWWѴӴrrssՐאظٸggޛzzcc44))?? ##((**J-J-//112222^2^211q1q100//..W,W,(($$o o YYKKll~~ooDDccUU͕ƕƆ†’,,¿¿IIMMӀـޭww$$'',-,-2255664646^5^5u3u3*0*0--,,0*0*|'|'k#k#  ]]--ssCC>>ܞLLookkМϜϫΫ^^""ii==UUmmyyAAnn<<* * ""\\>>2"2"%%q&q&&&%%7'7'J'J'&&$$-"-" y y R#R#%%f&f&$$k"k"** cc11EEaa&&ٔٔ١١**ҨШԚԚZZՎ׎HHLL) ) AA..!!h"h"h!h!  ``vvJJkkFFKK;;UUmm??}}  y y w w X X >>::00XX KK׋ы;;7711pp99麒WW22ii55YY++!!nncc6 6 ##**:3:3::%@%@ D DFFOHOH^L^L$P$PQQ$R$RRRSSwUwUCXCXWW]S]SaLaLDD??<<:6:6--$$iicc7 7 @@qq<>&&vvWWܡ ϕʕ;;ۿۿ^^]]BBʳʳ__55WWxxẤ||LL,,P P uuUUWW%%n.n.55::>>BBvFvFZLZLRRUUWWWWUU]V]VVVTTQRQRUNUN K KYJYJHHDD==A6A6//3*3*$$ }}ۜKKBB̔ŔŎ11//SSββ##))<<;;::hh\ \ m m eekkCC  ""R!R!""$$y%y%&&~'~'''))**++!-!-a,a,****7,7,1,1,9*9*$'$'!!gg]]777 7 a a  bbooPPIIQQWW**??nn__++PPӶֶ֣٣ٰܰߴ,,5 5 yy~ ~ <%<%((m.m.^5^5;; A AODODFFHH J JIIJJLLCLCLJJnHnHDD??==\:\:44,0,0++X&X&P P [[XX hh99ڏkkѿѿ((ÙõƵƓʓʡΡ..UUGGuu00 U U CCGGff !! WWYYSS  FFa a   || MM11AAXXII55ZZ @ @ r r U U )) ## ݢ٢HHט՘ջӻYYYYԂւּټܹrrBB>>II66<<##^^>">"%%((,,..z0z011V2V211////)3)35533//M+M+['[')$)$!!;;e e jjGG;;II}}HHJJ--KK!!}}ZZ~~zz __``11BB;;BB||@@22jjee oo$$__]]ff   v v ))FFAA99NNPP 88NNrrTT33))Ԥ̤̹ƹZZ2222!!oo--ttWWYY;;~~OO DD 22A%A%++22::@@WFWFJJYNYNPPaQaQQQQQPP`N`N L LIIIIJJwFwF??8822M.M.((O"O"PP  77{{ܮCCffddǷɷɕ˕&&uu||tt\\ee^^ݘFF""llT T ""&&''"'"'&&((e-e-g1g133A5A56677t7t75522//--))%%!!vv  ~~""mm(( ~~44pp))۪NN ԚԚԊԊԍԍxxԝ՝֧ק"" AALL(( $$E+E+115588U;U;==@@ECECDD?D?DBB@@>>:: 5 5 . .''""} } BB**} } SSXXvv**aannxxll$$rr''WW--88,,%%LL668833AABB%%ZZZZ, , ??ssLLAA / / ??uu//] ] PPBBHH]]}} __4411BB**y y UUcc99yy))ccl l 4455``%%֣ӣӤФ``wwΉЉЖӖOO۹SSNN tt\\))66 22!!3%3%&&''k(k(((s)s)4)4)''?&?&## 66ookk## ))''kk--BB{{^^}}SS``@@ߋ܋ttBBڹٹxx <<ߓZZII   <<\ \ B#B#$$$$ $ $^#^#!!SSnn))[[%%NNaaa a N N   Z Z   q q d d rrKK\ \ { { \\QQ// HH//ss&&ީީ33tt==΁فٷww""#+#+a4a4!=!=eDeDJJ#P#PSSUUUUeUeUUUTTSRSRUNUN*J*JFFFFAA?>77FFllʳʳRR@@y y XX!! + +55@@JJ R RWWZZ^^bbbb__YYUUPPHH??D5D5**@ @   3300DD[[LL߿WW11IIFFttz z O O ::llQQaaaaŢccLLss""ԬެvvV V  ##//::iBiBKKTTYY[[kZkZYYUUMMEE\=\=U4U4++"">>rrRRVVޑޡءؖՖՕוݰ22KK}}**==$$&&&&%%h$h$ vvyyMMuuww//>>ҫѫ''ϊ̊WW̙̙ ǺǺǍʍdd??dd;;$$))11~~@ @ ] ] bbqq** ##((++ . .002244555544333322R.R.++m'm' ZZ77nn --֘Ϙϡɡ,, iiwwJJ ZZQQ;; ffww uuyy..kkpp00 %%==YYRR##W'W'**--0000w/w/////N+N+%%`` RRUUgg;;ʸʸ##||--ߟ55XX >>))66CCNNZZbbhhjj"i"iifif``WWNN G G==11 & & HHܚΚBB ''ȥȥŢŢ55$$ȶȶYYooQQAAEE99     LLII$$nn33  ;;< < VV  ##n)n)z.z.44"9"9$;$;}:}:262611,,h(h(%%EE   NNyy ΛЛYYѲӲww%%QQrrxxnnll zzhhIIHHpp ''ss--!!%% ( (z+z+....,,%%SS ,,NN]]GGBBQQ $$''u*u*,,..001100&,&, '' @@&&<<ee zz$$ii--PPii55WWttq,q,E:E:HH=U=U]](_(_^^``aa ` `ZZTTNNtFtF==3434))dd JJnnXXuuaa>>ssIIYY   ) ) 6 6 44ٳZZԢϢϢȢȢŢŋɋii~~kkҦئuuRR  oo!!,,55;;9988G>""""!!""{#{###$$S#S#""""" " --VV  bbffzz֮ѮRR͵ɵ''ff99mmýÆɆɪ˪l l @@""')')))''%%%%^'^'%%##ss aa//##''11x x   ##%%|(|(--N0N0 . ._+_+&&D#D#{{` ` ~~TTggNNةԩћћо;;;NNҭ׭99ۺ޺]] !!= = & & ;;  ww}}kkBB::''$$S%S%--r4r4;;@@ F FKKHOHORR=S=SLTLTSSQQNN|J|JDD==55,,""//bbzz۠ۄфjjʅąč))OOұұ99įį==llUU**HH%%WWwwuuDDݥvvPP__   @@""Z&Z&)),,=0=0v3v35537378899o:o:@:@:88h9h98866o2o2C.C.**&&##F F  ||!!  ll۵۵WWששׄׄווט٘ee==ގ//KKRRDD^ ^ ::AATTll,,!!?? G G   VVrr9955bb11ddHH< > $$((++Q-Q-,,****))''##33s s  ~~%%$$[[בԑԼҼKKҹҹՑّ::ݪll>>nnMM$ $ NNaaUU22``&& &&ww??==XX ddRRqq ) ) SSDD''  DDcc% %   O O pp00  PP,,  4 4 i i   IIhh  ff{{^^\\ZZdd11llŔ”†ٽٽ55ppHH 11##ܛccMMkk ##((2.2.3377::{>{> B BDDnGnGIIIIHHHHHHHHEE(C(CTATA==88g5g52200++&&!!**JJcc( ( @@ ܣ jj תת##ããYYWWդդII,,ϴϴ55AA{{DD99  && - -.3.3z7z7::>>@@\@\@==;;g9g9f7f7.5.5=2=2--h'h'P"P"\\++ Q Q gg  BB[[ddee>>;;˦ǦÈ==hhii11Şŭʭ77##xxGG11oo $$aakk  OO&&$$QQ BBXXFFtt f f MM  !! & &6*6*p-p--0-02255G5G522//,,(( # #jj   66јΘ̶ʶʀȀȦŦCC//ǚʚ88Ըٸݲss\\0 0 W W ""BB  77c!c!""####k"k"(!(! [[BBWWޗٗ֐ՐXXӈЈ@@yyffσӃӉ؉ؖޖbb11nnEEK#K#((,,..82824444:2:2//--,,h+h+](](##44  ||::((HHgg))((&&..55bbgg ++nnӸѸ++cc++== eeqq\\ZZ**55@@sJsJzRzR=Z=Zbbvgvg'k'kllllii f faa[[TTLLBB55:&:&8 8 ܨVVfftt99dd<<,,--!!yyЍ֍$$CC XXUU11tt^^xx}}__}}== M M ==xx $$''**i-i-B0B01111#3#322\1\1K/K/,,**m(m(#%#%""!!j!j!==//v v ;;SS..NNAA--AAuuEEߧاسг mmTTxxNN}}&&ww@@gg66ww҈ڈڀ11ZZ <<!!$$%%@'@'&&&&V%V%$$<%<%9$9$K"K"##d$d$$$%%''**..33N7N7::==B@B@OCOCEEDD8D8D$D$DyByB??EK>+E+EKKPPSSUUWWVV U U=P=PjGjGZ=Z=55<,<,!!oo\\ccQQLL((vvSSCCSSSSIIWW  ;;K K RRww==~~::YY@@ VV88  ]]) ) --qq88 //XX~~""11UU&&IIFFffddUU[[D D P P 22JJx!x!($($d&d&,(,(A+A+.... + +/&/&E#E# ))..  55jj  4 4   NNzz33 QQ>>߃׭ЭЁ́ ''ʂɂʱ̱ڡUUI I kk $ $**9/9/2244:4:43333//&&22D D 88 ttڛқ˦Ʀkkɿ̿΋ԋԥܥ''77  z&z&))Q.Q.3366B8B8::Y=Y=>>????3=3=8822;3;3E3E3..''"" @@mm bbݑ~~۱ٱՁӁӰаGGʪΪΔҔJJHHӴӴҭҭСΡ55{{VV##AA ޕ00MMzzX,X,3838CCMMWW``=g=gmm}s}s'y'y||2}2}NyNy*o*oxdxd[[QQ7G7G>>66V-V-1#1#q q tt66``^^ccUUccζ˶DD00޿޿AA3388BBMMZ Z ii$$--55::==AACC??<<7700**&&!!AA   ii((22AA$$EE33pp  SS P P   DD}}$$ ZZddttxxkkȪŪ55ƊȊȴ˴%%ff$$]]<<LLuu&&BBII..FF\\UUCC  3!3!++4499]@]@3H3H1N1NRRUUWW X XUUWNWNEFEF4@4@77//''==XX //oo@@۽ֽ<<~~~~һһCC ѹѹ CCŊźǺʻϻNNssbb. . ''..3377;;??BB>cGcGNNRR&T&TVVUWUW*T*TQQPPFNFNGGh?h?8800%% ؕXXҋ̋EE˼˼GG++,,—WW&&99_ _ ))1!1!''^,^,,,++++,,G*G*##,,[[  1 1 PPiiggMM44KK))22 \\AA""55NNtt  - - m m XXZZ !!m"m"''**))**0+0+n,n,++~*~*))''\"\",,wwRR!!//PP//eeKK11PPssŐŌʌ--ԃڃ޴>>??``11DD# # mmX&X&))))++..11m5m5I8I8::<<>>g>g>q?q?>>88N7N7)8)8{7{744%0%0**##vv  ' ' ;;֪ͪiiQQbb88ff11__΍׍קPP iiF'F',,9494t:t:}>}>AAwDwDEETETE B B==88 0 0'&'&*!*!/ / -- ޭۭ00٦ڦ<<44!!gg+ + UUHH22{{$$||   f f FF}},,rr W W 5 5 8 8 ~~}}66&&==ܼؼ؏Տչѹ̗ȗ \\RRȓ̓wwҿ׿11܌UUwwqq "" ##%%''^'^'w'w'''o(o(''G(G(''''%%""!!2244##rr   } }  33ddddKK 66GGՅօhhssmmKKqqii CCdd!!]&]&'' ' '''((''f&f&D$D$!!__bb55 VV;;سӳϒʒPP>>xx%%@@טޘXX??{{##t*t*_1_1W6W6Z:Z:==???A?A??<<6600))"#"#W W 00LLqq 88QQ>>ެBB>>UUhhLLǖʖ??էڧ[[CC  !!%%**--//-1-1l3l3E6E6e9e9<<~=~=<<;;.;.;0:0:7744~1~1--e'e'NNddEEhh MM== ssȐƐ55kkjjǵʵ##YYXXHHPPff..>>uu|| g&g&+++.+.|.|.--U-U-,,((!#!#wwC C iillccHH]]7722 HHyy &&))++T,T,/*/*''l&l&##uuLL ""//>>00zz{{PP``QQZZ ??``00XXYYM M | | - - " " Y Y  b b GGnnD D \\?"?"''((**L,L,k,k,,,o*o*y%y%uuJJ TT22ە۪ӪDDTT``EEź̺SSWW JJbb""m&m&((((((''V$V$  ??S S ``RRppmm}}<>yyAAii22ff>>aa||8 8   ]]jj//``QQjj mmccSS## ((vvOO>>QQ{{ X X JJ  KKt t ooiiDDgg ((߉ߢߢ߱PP||11xx%%++00 3 33344s3s34455+5+53311//++]%]%gg%%5 5 00hhwwBB**>>AAڄڄ::WWݨaa##44II[[MMnn((11LL<<SSKKNNT T ii))44 ##r(r( - -////..--v.v.--++''"" oo||^^wwڝҝ//;;–ݿݿƙ..88<<7 7 gg  E E M"M"i#i#!!##}}? ? i i EEww JJjjXXFF aa'']]oo   ``88 $$''((((&&##  WW   $$44aavvܱڱtt33ۯܯff((ffAABBoorr!![[ZZqq>>n n SS R R ppee]]pp44//  * *   **SS:: / /  ۭ߭ ||ǔĔµIIȣͣԊ܊ooXX__ %%..558899<<3=3=<<:=:=<<995500++%%$$M M zzOO@@ް$$Ώ̏kk77ͦЦЃԃ99؈܈AAuu ^^!![$[$)%)% & &%%$$!!oo33uu iiwwkk))CC))jj0033 ppII<<   P P  kkMM99GGUUߦܦdd>>JJ``   ""'&'&?)?)**@+@+++m*m*2'2'b$b$-- BBff77xxۗٗ88hhttRRuu " " ;;nn )")" % %((l*l*))8&8&""zzBB"" llOOAAss66ߗؗؐӐUUqqƼż99qq``GG[[..00 ''R.R.3399>>@@??l?l?\>\>9933.. + +''=!=!~~WW%%L L ,,!!߷߷ߝ||^^UUkksswwQQyyPPjjllkk%%AA66oo88>>TT[[RR YY!!))?.?.1166<g>==<>SSAAUU **UU$$ww__HH 66HHJJmm HHψ̈̐͐͒В rr؍ލ``oo((jj+ + """"$$*)*)+.+.11D4D4N3N39090--))%%:#:# hhoo  ۥUUAA%%Ӫժppُ܏ܱ߱^^ii))EENN? ? jj>>o o EE88aaJJww33EE$$``ppmm,,mm88XX * * \ \ J J 3 3     XX{ { XXTT22!!.. '' MMaa!!LL EE1133tt88}}gge e xxYYff ++   kkii44  `` vv%%wwSS{{ i i ((ffccggzzBB~~Լּ..??WW??NNyy *)*);/;/11-2-2a0a000|3|33300,,q'q'!! ``ww^^\\oo..22eemmIIeewwII^^ccff\\kk&&QQ..LLZZ,,JJ >>yy\\OO@@  YY oo99ssSS||55aa5511. . <<[[XXgg**<<++zz77  QQ  E E !!pp22&&mmݕە;; ۣڣڏڏڌڌ>>ڄل''YY<<``MM  }}!!%%((++e/e/H3H3e5e5W4W422E/E/,,H*H*''##__l l ccQQMM 66mmwwxxMMPP9944rr SSKK$$JJcc((@@$$ ]]ss&&ooAA^^``||   O O zzUUZZQQIIggzz@@ aa55RRQQ==33ee rrcc a a   \ \ } } EEqqYY22ppBB^^ %%HH55p p 33((hhPPًڋڃ܃ܟߟ||jj55 gg^^""$$O#O#"""" TTYY..SSVV  QQ^^]]]]??++++zz--ߊߊ22ffggrrff11\\u u SS55##%%(())B*B***,,S-S-++))r&r&""MMzzBBRR QQ<<nn''``ߵ!!޽ݽ݇އ%%qquuRR11((UUgg{{PP55WW ..ee))++cc$ $ + + ??WW ! ! bb}}bb{{gggg__jjvv((~~EE OO@@QQ88vvDDKKdd  LL m m D D hh**NN--AARRoo  %%  HH ``<<ooyyYY;;dd\\''oo  {{rr   ''ff  3322ii==BB  BB,,CC __WW^^ݚLLffרר׃؃9955jj \\ ZZ##  ""5'5'))****N*N*J*J*h*h*D)D) ( (&&## //mm EE ((\\//''{{||ffGGGGTTllxx} }   ff!!X'X's)s)))P)P)K)K)w(w(w&w&$$!!]]gg ff88oo[[33aa@@,,77//YY}}UU$$ggjjHH!!::hhjj66rrxx44  V V - -   t t IIRRvv[[;;mmuu""eeb b 66ttmml l ''KKHH((޾// ҷѷђҒ** cccc =={{55qq  ==@@%%   oossvvs s PPwwqq{{((KKMMf f ::pp}}##||,,00))//ۋ׋սӽ QQII  T T ``..^ ^ $$%%''~)~)++'-'-t-t-,,))[%[%77EE ee]]''22RRxx]]??{{55&&^^JJvvLLdd߽ߊ܊JJ۩ީ NNGGkkIIuu mm 1%1%))--[.[.H+H+V(V('' $ $M M CC11BB..88nn^^uu}}UUHH $$HH00OOTTEEvvffRR4433xx33OOoo pp  TTzz       ,, BBLLXXcc((11G G RR  >> ''**++C*C*\+\+((""JJPP9911JJ ww֏ݏYYbb  yykk""q#q#"" XX;;* * (( ,,**YYzz__]]  Q Q $ $  <<mm}} eeddffffWWچنLLyyBB''\\//''/+/+--1/1/11L6L677x6x6&3&3]1]1 / /((!!bb> > <o>==|<|166::G==.@w@qAAH==\66..o%% F+DaLy٥ϊS4޼i !õvj`Ǫ4P5څ{!n.!!9(("--01_2223E//))"(#6# r>E?wd:PVw Пԓr#ۡfuNwgT[ =E 'o'.//t66H::=9>?g@v@@>2?;h;B77b11)*##\  9 3i1 ۫|&ܻ{R)`i>\n]g ~  # 6 c };_heT=[ߵG^ַ+_P̸`FHqxۀ0`(T o | !)@*1R2s9:AUBHzIELLRNNM1NKxLGnH@bA7H8 -:-O"b" X o(9WO:<ƍeP~LɞUώL  'pQ&&~--.347C88l973855U22-v-%%1 ?޴ݻ;ϯǢ2t3}j¿CįÉ eq1h4} [ M:"B#))/045778K9R773y4I..'(AkOT r {bv`լԇ=+l˿%@z$жIT" D!u"?,,56@5A6KKRSW:XXTY_XXLWW~SSVMMDD::0/s$3$ /Q ]'{¨·)ͳDIձJ˷ν }͓8lzߪvPP:7""$=%5%%D## 27->b R Cmh s2A;}xsKۉcQ 1"##I((.~/56i889}8J9 77<44111,-'(!8" 7xr8rc@lݎ޽ݲPX^l_e J fPq ]!%H&['((-%%t"<#R FU c ~lg||X ibʯ_ġD výbE֪Ղ4< fW%7NM .~t $K%P))**r)%**+*H+n'(!5" %<9n.oxA(j #P**55]?t?5HhHNNzTT{ZZ]G^X]]X2YRcSJXKp?@H22$P%Kk^pӕĆ!ݩxVҒ Њ#H]Z#p!Ɣ>yE-c3&&'2x3<^=ABExFHIHZIFgG?BBM<o=$ 1 QK6""%&,**_,-+,)*:''$$= _BcF\YژiyԕfדLXHk(02{/ ##P$$#$t#'$q")# (%\1 ]EGq78NG dPb ^& #"%%&&h((#++*++&&[ GA<Lto-@œtXC.ȴA$߹::Epˇd܂ }1e > _Wp%%90l0879?e@F GI6J5JJI`J"HHADD=O>D66-'.##,{ElGDZ5+iyŽ ȑ,3e"T?,{l?''W00)::CuCG!H4KK[LLJJFG@3A9900'&T&,F^d7ؘЬυ$ɛ6"k €̅̎_n_&6 Ht%%,,0&1224m4(3u31c1,,'(7#h#Io(B,8pqדͪq8STZ`q&x&++..b1l1W4a4E5M55533c0h0++$$&&  XUYV][$#xx**__# $ $$**1.3.////..\-\-.*.*$$ww [Z̡á11]]ûûBBǑΑΖ֖ߕnnnn""g*g*0066X9X9775511,,Y&Y&00zz::\\00ք҄˧˧̣ΣΝҝeeS"S"..88??EEKKNNOOQNQNKKGGCC}?}?^8^8..!! ٹ ƁٽٽaadzdzMMJJgg''MMaa))j j UU  HHzz' ' QQBB@@ooll ]]]]++''HHbbpp &&RRss66!!  22..## ^ ^ GGQQNNHHoo P P CCTTOOZZ  PPLLܛ֛PPll%%,,۠ܠj j , , `*`*33999>9>IDID0K0KOOPPLNLNHHeEeE5@5@77..##FFxxPPQQ::ˆqqoo--İʰԦަCCXXEEII VV    9%9% ( (&&""GGdd ((##;;ݯܯ܎܎ܜܜiiً܋ܪiiW W VVss""))E-E-//1133I3I322I.I.((##J J \\AA{{UU66!!1188QQXX>>ݺooگׯ44ֱܱYY||aavvgg  55RRTTFFTT88wwrr""%%%%q"q"nn PPooBB::؁ԁPPVV@@LL½½mmĺǺɵεQQՠݠ''kk&&88##H*H*[3[3::l=l=x=x=F">"2#2#d#d#b#b#@"@"//ttRRssܕ֕BBMMiiVVУ֣OOIImmMM((__3 3 !!""$$%%$$""- - = = cc**RRPP00ssWWssQQhh++  wwKK__OOU U >>OO {{UUBB''88    PPOOqqff55}}xxff//~~MMܹoottOOmmBB##1(1(++,,--//00..,,))""}} VVLLOO44yyOO!!}} FF00JJhhmmVV[[ݙݙ݄ބߜߜ߸޸||!!IIssZ Z &&y-y-336688T:T:;;;;M;M;::;;;;55..''ww֛zzbb͞˞??nnvv~~ttRR- - TTNNttllZZTT==j j HHvv}}p!p!%$%$;';'p(p(;(;(''B"B"yyii ((FFyyJJy y 33vvPPTTuu00XXNN<>--nnRRWW1155  hh@@^^ccVVss--::++LL11_ _ 33..oonnpp.. CC!!VVxxhhHH,,~~ёБ--գڣHH00##P&P&R'R'p&p&$$   ``33!!((++,,w-w---++''s#s#66kkbbmm&&PPިkkHH00mmAAAA߻''XX33   5 5 F F ] ] ]]gg33$$vvBBTTee==//-- %%ee''x x 6'6'A-A-K2K25577995500_,_,&&// yyuuعooѴѴэӍIIbbZZaa] ]   XX}}  >>٥ԣѣEEZZ˿ʿffooRRڮ>>$$ NN  ##++A2A2665959g9g988|6|633d/d/))O#O#d d kkzz !!UU]]{{]]hh""[[88WWZZNNSS~~aacc^^ppoo8866 b!b!|'|',,<0<044664400,,I(I(""۴bbRRNN==ʽʽttrr""||='='0/0/L5L588C:C:&;&;;;}7}711I)I)!! ||cceeشҴёԑxxز߲߄44((GG  BB))VV!!oo== XXjjzzFF..??}}< < ffrrDDDDFF [[OOOOߒssbb## {{ll|| llg g Q Q   ޙޔ۔11ۼ $$##%%n(n())(($$++!!**ܭּܼЌӌөةBBހmm11VV''=-=-1144)4)44444`1`1o,o,Z(Z("" >>oo))77TT33ݛۛ>>rrPPdd}}$ $  W W oo %%@@..^^ ^^~~GGyy::(())&&--T3T366O8O88888K5K5#.#.U%U%%% 44׌^^;;ffvvyyՀހ ==}}``YY__33qq SS++UU'' > >   k k LL;;  IIJJss55OOvv**YY>>CCMM33**!!@@llBB  TT66 **&&44||YY;; FFSS##''g*g*1+1+++**''j%j%!! mmnn11ۿ88ױԱWW((;;  cc?"?"I&I&)) + +**p)p)(($$  HH&&&&((ssGG00ZZ tt""%%$$"%"%@%@%## 66 VVZZaaۊي٫۫VVDDWWmm  ' ' &&8$8$''W+W+,,++))%%--||vv55zz``ffaa!!,,""HHuugg??__CCddWWRR** tt z z WW??QQ++ SSBBKKNNSSa a 33 iiFF!!EE۔הՁԁCCxxGGpp ^^!!''++++**,','## HHoo gg~~ooll55]]CCqq$$,,}2}277?9?988>5>500[,[,&&~~{{  !!פԤiiӶҶvvBB33ت۪iiLL>>vv$!$!&&**W,W,$-$---**$$IITT&&XXKK''))44%%llnn||::  }} ))ppooOOmmtt//ooddOOUU VVSS44ss ccRRSS22"" ZZ!!^^FFHH TTHHVV$$hhmm$$ tt/#/#&&**I,I,4-4-,,++g%g%11||11hh<>{{SS~~99aa44DD  bb mmJ J ttXXUU##;;~~""ww9 9 << y!y!   >># # 88 )) GG kk22II))rr<>tt$$++00//,,y%y%&&zzFF==uu J$J$--331414..~"~"ۿۢǢ˹˹((CCmmAA##)/)/66?4?4,, !!ܷٷ{{qqFF5"5"00';'; ? ?;;55**  Һպ՝ݝ??yy,,VVHH 0011RR__ss ""**2277m=m=>>55w*w*ڴڤǤ]]))ﯸ))Ы) ) ""%%3!3!W W VVQQ2#2#N9N9KKSSTTNNAA,,^^sspp]]VVff%%$$,,p0p0..((gg..AA662,2,#5#5::<< : :22L'L'mm 22bbډ44SSւق88ݹzzGG__ާQQǁ""TT44ss** < >66((??Όaaٰٰխխii``55ICIC I I8F8F<<,,77||HHhhppuu/ /   ..::>><<33##gg߱FFII__YY**  ءѡHHбӱ$$  %%++,,~)~)p#p# ppw'w'22v9v9?;?;55v)v)nnDD YY侮ά<<S'S'338866-- MM\\xx o o $$-;-;LL?U?UUULL::## ;;eePPTT44nnCCDD""GG$$88?G?G?Q?QTTSS*J*J;;++QQLL݂ookkjjssFF>>ffRR//ΒגTT99? ? ..;;XAXA>>77 + +ZZyyΙәӈ߈..33))55;; < >::xxa a   hh,,11++!!""""%%ggNN77qq>>ppcc ))    99``uukkffv&v&//'4'4O4O400Y(Y(ccWWuuee<>* *  00Q Q   V V ss..ooHHXX99FF@@**7711ZZ``ZZwwAA==::{{AA  [ [ ##''})})c)c)''##   ߬%%ضԶԹҹ++xx!!zzFF5 5 OO  #$#$A'A'h(h(((((6%6%qqmm33ll??HHddrr++88xxvviimm  e e hh  >>11 QQMMeeWWllII HHYY55ϲϲϸҸ&&ؘߘOOee00BB""T*T*,.,.\1\1}2}22200!,!,''""jjD D vv%%߃gg//AA "" **uupp6644~ ~ ii6 6 ] ] bbQQ44{{88ii55``v v RRll$$11 e e XXPPtt]]gg55]]LLDDkkZZuuqqyyoo%%++z/z/^1^1<0<0++##66**""pptt11,,ʈʈʋ̋``[[aa vv[[c(c(h0h066;;??AA@@==9696 , ,}!}!> > ccii֑֑ mmkkSSuu[[gg , , II x x ) )   W W 4 4 11__uu݄ڿۿ``ޤKKqq@@ YYBBxxii##### # p p %%$$ii!!dd##((,,,,"("(""  NN33ުGGߏXXBB, ,   33XXpp \\33UUFF֫ҫuu֌ی''::--  __..qqQ Q TTnn  44//WWO O !!""zzqqGGRRggiiݮܮmm;;##""++22<6<67777d5d5>1>1**"":: ]]PP||ȞǞNjʋʬϬggvvqqee&&rrxx''a2a2<> zzX X QQ>>SSY Y ((##((CCSS44jj@@8 8 uuss77CC ^^cc} } [[oocc B B g g ; ;   //**RR <>^^!!..HHww AA88%%o-o-11g1g1--((""\\UU{{؇ӇӾҾIIӍՍՏ؏ڛߛ **^^  ##((**q-q-S/S///P+P+!$!$b b ""--))yy**ZZQQ  KKQQOOrrTTVVߊ**$$GGNNL L PP~~UU11  ||!!mmaann; ; <<[[wwyyUUJJFF iiWW/ / e e ``(( iiTT $$/'/'&&%%""GGyyMMcc{{އׇ||cc>>~~ܨ44++~ ~ KK$$,,224433&2&2--"("(JJi i \\ߙי**2288ccҲزrr }}IIAAdd ::b%b%L+L+// 3 311..&&``RRllDDOO((rrEEssdd` ` r"r"~!~!jj""E E ..NN\\UU++kkii  ??LLH H UURRGG L L NN !!5!5!@ @ > > ==  xxYY٨ٴδ\\WW''77vvuuKK!!!! " "FFrrtt ~~ HHdd))66aa## 772 2 >>~~1199!!$$%%""22rroozzkk??ޟݟmmZZhhss--$$^%^%0066>7>766$1$1((zzoo[[;;xxvvDD{{VVnnjj~~> > ,,QQV#V#))A-A-,,&&,,@@QQhh mmSS__zztt]]}}]]qq99RRCC@@JJ? ? T T  SSEECC)) %%OO__ffbbG G zz,,vv cc DD %%D D ++\\ff_ _ ^^G G '&'&((((_&_&  KKyy ZZععoo22tt""bb)#)#))[+[+R'R'!!CC ))oo7!7!  vv::##PPWW**}} ee**;;v v & & llvv7 7 K K  88 LL~~88\\<<EE``ww))ӊӊ--$*$*77>>??99//!!LL++DDYY\\eejj+ + i"i"!$!$ && yyaaQQ;;EEffO O # #6 6 ll  @ @ ^^xx66kk**%%խح;; 44  ^^0 0 yyqqIICCvvYY||  **IIQQ  11 ""bbkkdd΢ܢgg$"$"$$  ))TT  $$@&@&..b3b333//)) kk 99WWLL66}}==ǭĭĞɞ ӭޭFF> > II$$$$%%!!pphhaa P P  ..cc__KKiipp||++..55P P --(7(7A;A;::44!+!+3 3  <<QQOO 0000ll==!!((AAȩѩѭޭbb##6%6% . .e2e200''qq))KKccJJdd RR bb||88 ee8 8   | | GG!!{{A A @@{{ pp|!|!  HHզőmm::ʹvv ]]& & ))''ii 66 XX}} zz``yy&&  RR,,ʡá||bbPP $$((%%**OO||&&%/%/[2[2!0!0''LL5 5 SS||####VV>>ͱɱ((nn'' -"-"%%%%""''W W mm  zzLL< < &&**..!!//gg\\''66>>d=d=55R(R(BBII ;;44cc((??%%II5 5     **""kkFF  ZZ %%&&y!y!77LL@@$$**AA eeޯߣccDDb(b(--**""++FF֯ooѦѦ::SS^^::<<< < ]]00OO>>M M     YYX%X%..445500S$S$ssԓFF77֣BBg g  KK""mm!!    ffLLZZ//OOjjBB(( UU~~F F 00QQvv  ?$?$**00x1x1..Y&Y&RRss``00  [[88==88UUWWppxx%%^.^.G2G2~0~0**!!  ii,,$$\\))HH>>** hhhh--yy!!,,4466`3`38*8*TTAAii  ppAA ddUU߻ \\ ee( ( 99DD [[[[22ll  >>zz99kk sscc##33BBhJhJJJxDxDb6b6!!K K mmߚКЋȋ<<ʍՍG G 3366CCzzjj LLdd  BBYY. .   ==jj@@ tt66nn((FFVV##  ''++R,R,`(`(, ,  ^^<>ݶ  ))2288;;?;?;55''77` ` CCzz77UUuuˋҋ``RRl l F%F%##''= = GG66hh  FFff1#1###r!r!n n SSjj$$RR@@--MM  $ $ [ [   % % <<uu00UU9#9#))--,,))"%"%ee11ܪܥץuuEE ֠ݠ݆ff^^))$6$6>>@@[=[=::11$$} } ..GGWWggxxJJII77ߵ$$==D D F%F%B)B)G*G*****''HHpp((--ddff zz**114444..w%w%mm))BB..\\ CC۴ݴee44bb ii../"/"` ` L L __ UU####``TTgg    kkOO''ss  ##ggWWZZcc**Y:Y:EE L LdMdMXGXG<>NN::ss66ttN N EE  ff~ ~  ""!!ww ==ss߼PPݹ۹``bbttظڸڤߤ[[]]GG&&,,..++*$*$XXww..++AA``rr ++  SS!!O O }}__!!VV|| ~~MM  ww99}}OOww!!vv$$&&Q%Q%LL ZZ""ee\\[[^^R R O O _ _ iiQQ11` ` ww**__PPp p ZZ~~ Q Q **zz//..77ܔԔEEccVVooϖٖqqXX(#(#m'm'|&|&(#(#22ZZm m ..  L L CCXX\\ss,,uuss``uu $$ llOO//nnRRnn@@4433IIPP??}}))@@&&d d $$u-u-11Z4Z400))!!44  >>YYcc ,,HH99))TTnn!!cc$$xx5 5 {{gg] ] --LL((  KKxxmmݢܯޯ   mm 88qqZZ    bb` ` FFeeXX>>լӬnnkk++  >>   @@jjAAl l ddn n OOff**qqDDzz77aaYY{{<<aa ((''ZZi i f f   Y Y   YY [[rrۑ$$eej j zz  nn''>> 77//BByy}}N N N N FFLLoo   //66zzll~~OO""'',,KK``NNaaJJ uuAA88z z   ."."##QQSSߝ__JJ  BBOO.!.![![!00YY==FF^^uueeDDޕ""vvEE  llxx88(( v v N N 7 7 {#{### ##   %%))wwYYsskkpp!!ww ::JJ^^77)#)#K)K)--,,))r"r"33hhڏЏxx^^ׅ..  yyaa iiCC ## rr nnC C ( ( QQIIYYoo Z Z GGMMAA  ""@@cc vvk k UU!!!! 77$$55RRYYHHee44 YY zz{{[[$$ Q Q AARR``DD     77""||++00װѰԒْccBB1 1 d%d%++1155Q9Q9F9F966//H"H" ++CCff00,, qqII^^g g %%ii\\ 66aaOO..&&@@00MMvvKK ~~QQ jjYY  0 0 ddGG ^^\\[[ԤԤԗחff\\j(j(W-W---Q(Q(ZZ((XX تڪ?? !!%%Y(Y())R%R%A A O O ^^44vv44 iioo__rr66GG``DDyyщXX++d:d:CCCC<<11!!DDii dd  WW 99yyTTww E E $$iittee00BB((TT LL))|4|4==5D5D.G.GBB66&&KK"",,11((WWƖϖݜrr" " }}ңғÓťmm %%>>vPvPXXpZpZ#T#T3E3E..__{{aaww{{VV̮׮//SSii  ,,UU KKss oo7#7#++--**\\22|| xx && ; ;HHQQQQ:N:N@@++ JJ,,—֐;;##!!((;;##vvjjCCrr {/{/ < >LL.Q.QOOCC00 77``͠wwll77 ""u u <<<>F/F/{{77xxOOuu00 ) )4D4DmSmS X X&Q&Q?@?@C(C(H H ^^--66؝؈QQ6767RR$g$grr>t>tJmJm-]-]CCC!C!rrߵߵgg0000MMT0T0CC+L+LIIi;i;A"A"jj))zz̈ A AgZgZgggg\\GG**ff##ȨبRRsshh%%9,9,<,<,%%\\55WW ֏ޏ  V*V*33{4{4//$$CCĽĽbbbb$$\K\Kll~~qq#o#odQdQ**ــxxˊ99GG_K_KCC11 ss֬ϟϟvvQQɮ***I*I]]SgSghh``PPI:I:""ގ66yypp""vvc-c-BBNNQQII%9%9 ==Ȏɚ 55uAuAwBwB99c)c)..TTѸѺ˺˯ίۡ n%n%AAWWbbnbnbUU@@$$11||ǷNjK.K.;;y@y@;;L0L0  شؿſkk\\BBVVGG22a4a4LLf^f^.f.fccEUEUX>ssbb ||@@p8p8HHPPNNBBR.R.ґʦʦззЦaaN1N1 J J\\=f=fhhbbtStSu;u;\\OOkkϕɕ55זSS**J/J/,,!! ߉߻λ bbٸٸzz((336622F(F(<<==ppiiУԣԐސ00uu!!++//00((++) ) vv~~GG--CCߺ&&//3333d0d0''JJ ȆƁ66//LLaaoo>ƘјXX((++**3#3#%%##̩©GGNN3)3)<A>A;;,0,0 &&DDSSOO  T T 55 UUOO$$77ddmmpp kkII!!$$+%+%""_!_! KK##tt--ۋDD....ߏSS$$~~,,==IIdPdPOOFF77$$ttgg99h h G G ~~oo::@@rrdd ((0 0   E E ~ ~ ddLLmmKKvvLL$$ 77>>::ll ##l*l*--:+:+{%{%AA;;{{YY kks s ;;hh|| ̔ŔŌŌ&&))W&W&M!M!22\\ ^^xx) )  YY66//ttDD  PPTTvv  >>mmIIeeyy O O f f YYդssHH**zzOOllOO&&117777-2-2)) EEbb,,zzKK..OO BB XX pp99sscc,,MMJ J  A A aa22>>SSBBNN''aa::TT33 v v ++  BBbb mmccDDHHaa22KK!!MMu u PP/ / **::GGff FFTTNN00gg44ii** ,,cckk  NN<<  nnHH; ; yy++xxJJ22YY||ZZjjXX$$^^PP]]99$$D D   KK((66GGii}}ppVViiKKii:: GGv v [[.. **ii77JJkkbbpp\\ $ $ '' + + **]]   OOVV++ll  cc0099LLll DD@@OOttEEyywwYYOO##,(,()),,**$$GGg g ))hhFFgg??~~VVffGG}}LLWWppss,,RR//KKyyUU^^<<vv` ` AAdd&&ccJJ// aaAA{{ YY""&$&$V"V"  [[WW UUAA%% UU   mmUU99WWTT##KK mm" " b b y y uuOOܖnn<> ~~##?+?+55==d?d?i>i>88P,P,߫..88֘ܘNNNN..LL88eeߴ[[<<x x CC//$ $ 99uu66yy[[%%gghhZZޙߙ<<''PPNN##3-3-22l2l2g,g, ԣԻƻ8833s s 22~&~&n-n---r)r)ZZeemm??   ll^"^",, DD%%jjvv 33<<11pphhQQ~~==o o %%$$ ? ? yy<Q>00uu22..EE܅ӅUU'' &%&%,,--((^^%%SSZZGGɃ̓==zzYYk k gg++ff!!$$N2N2>>CC"D"D>>44%%\\GGףʣbb~~řљPP''g1g111**ݮʮYY!!FF--22 F FPPaTaTMMh>eeׯǯJJiiCC9 9 M'M'==MMJUJUUUNNQBQB 0 033ٴ //ǁӁjj``XX22MM33bbɜМooooU(U(;;WIWINNJJ@@00aaaa--  ((|,|,m)m)  xxrrԙǙǁ³ͳ ~"~"d%d%G"G"HHCCܸ߸PPMMEEU$U$G6G6DDjKjKKKDDe5e5e!e!jj Ӏ''^^MM[[,,+?+?*J*JVKVK7B7B11ssuu""[[{{&&_/_///))לKK ϓғҴٴ__55''  K K vvjj33 ((**u3u3e6e633++ BBNN܋22ddAA''22O6O611$$ ȑȤPPRReeҊ}}'&'&i0i0i3i3 0 05'5'zz{ { &&llպ׺;;  ++88@@LELEDD==//PPoo;;kkGG JJ%%))&&QQy y CCcc??ȼȂ؂\\hh%%//4422** XX""~~AAUU }} &&ww99,,qq$$KKP P ee""##""iiYYޭYYooVV!!//889922$$zzCCߐGGyy  ''44";";88008#8#ffHH&&AAS S  $ $((o*o*((i#i#;;??iiMM!!::ۡNN # # kk||## " "DD VV? ? !!?)?)**''..44ڭڔӔtt77ۑa a L L  ]]NNYY||""//::;@;@T@T@~9~9,,GG^^߳ߑёttmm//ffee##,,00 / /%%''zz//XXPP''::77((YY^^zzss11..<<--TT  33ssVVI I &&(($$nnؓ؛ɛ33nnǞLjԈ''$$5$5$!!==  $$99}}UU##EE//::33BBT!T!""^ ^ CCܩ>>dd 6 6 KK``--AAQQ >>9 9 77QQa a <<MM  44ee, , ]]NN CC22ffި&&aaTTӎ֎ss00ddRR i"i" pp##pp  \\ CC    F F a a qq66UUOO%%""kkEE55))VV qq ))SSssm m ''TT ``CCCC!!GG  zz "" 44cc0077==hh^^ߌR R   BB))]]11AAee)) $$ CC^^PPAA, , AAjj FF  ppNN}}<<VV##ssNN!!t t vvkkPPq q ; ; MM \\33xxPPDD[[ff   QQBBJJdd==mm%%{{__   שة 88YYL L W W 7722``~~{{]]  Z Z &&==JJ;;PP&&""aaEELL ==KK66ߴ@@ޡߡkknnNNttcciiHH {{  22QQ]]++ 4 4 e e ||+ + ``;;pp))##RREEBB^^'''3'366U1U1=$=$--LL\\%%hh""t t   2 2 77//;;H H `` <<MM??hh66cc//VV==bb aa5"5"aaBB??QQooIIP P &&((##N N &&hhYY>> 2 2 ,,88 L L    3 3 SS``> > %%((""__ zzMMF F  FFnnaaooFF00[[h h >>8!8!i#i#. . GG  ( ( ; ;    jj//rr gg  R R ' ' pp dd55``..EEL!L!H)H)((tt bbJJccQQ77 ? ?  kk XX ii**NN99 ((B B ll33..QQ55ll4 4 //  ((++X&X&ttז00Ӏـٞaa --!!$$  ee   \\77** --XXyy&&  RRvv  U%U%$$nnZZAAoo0 0 FF<>- - AA_ _ ``uu^^||BBTT??]]66YY::OOE E hh22TT  ::  ~~}}EE7!7!++UU;;׭ѭ==YYDDaa$$ZZSSII 66oo !! !!O O yy>> AATT))[[ XX""mm..jj..yyi i ??    pp gg33 @$@$9.9.m1m1,,x x AAݟ^^OOQQee55``  LLܥܫޫ88::xxhh Q%Q%J#J#sss s AA11!!eevvG G W W ,,//O*O* JJVVpp  44 qqssvv,,EE66RR||  ^^__aaHHff""%%s#s#== 99WWث۫ > > 00^7^722Q#Q# yyيNJǗ TT, ,   ;;^^CCKK.. E$E$##11jj``q q ~~((ۘbbOOtt00;;%%,,dd00--%%g g ""@@NN ooɽŽ̂߂FF""U/U/22--r!r!yyII++++ooOO  o*o*3355.. ww))%%rrۗߗ~~ 009988++,,99PP!!J&J&,&,&!!mm>>''JJrr ddjj<&<&((/#/#DDxx,, XX    nnFF מў ێ  EEH#H#(())I'I'""YYh h ??nnllܤ  ''>>PPTTzMzM<<^#^#++ooXXII 00gg(("" UUhh==WWJJtt  PP^$^$##rr ##ؿ;;ؿBB++77x;x;s7s7**  ݨۨۅ݅ݢ\\] ] X"X"99TTss٢ҢҠҠ==مdd--hh  ݾhh88ԉډiiNN$$66-C-CIIGG<<,,55 77x$x$..22).).77UUς22 ''**((0#0#ss  YYLLaaOO }}xxV"V"##""99  ]]oo%%''I I ww  KKKKAA11HH!*!*668:8:2727,,wwPP66aaɵǵ&&ffXX$$ `(`( 0 011--C$C$OO&&%%FF JJ11}}  ##K(K(((8$8$V V 55л»,,ɵSS ##i5i5q?q?@@::9-9-??AA;; ++!!"" ))44SS==VV$$''&&:#:#11__y y ]]JJ44hhܗMM))##  gg~~݆݊ԊԍҍҤ֤>>!! d5d5BBFFG?G?--AA""&&||11uuޘ  ;!;!'4'4AAQHQHGGM?M?0000܀̀ppaaҵ޵00 o o ^ ^ - - f f %%qq t$t$''%% WW llrr00ddjjT T f3f3BB,H,HDDDD 7 73$3$  ߇,,!!++++vvDD 22ݪݪ݌ii..S S iiAAQQqqMMII22@@IIHIHI ? ?:+:+JJҘћܛii,,p p ++..**  uu::++YY11JJ99JJ%%,,,,6%6%]]rrssMMNN''))11ss""%%1%1% ssooXX ttNN YY>>ֺֺ# # o$o$ 9 9DD[D[D99))FF$$ߩ۩۪ܪ##  zz+ + VVkkDDNNxx ((||AAV V 66wwѪ̪yykkKK  &&j-j-y-y-((FF44TTμԼ&&//""&&%%TT@ @ YYqqjj$ $ XX""f'f'((&&!!KKqqddppww88EE {{5 5 ffww !!݁NNJJDD>>""j*j***##O O GG PPee  >>4'4'0044s2s2))''>>jjxxqq""33PP++UUwwkkGG,,QQD D   < < vvnnxx 33 ''00H5H51313((xxEE))Հ؀ooEE ttqqt t ..^^UU llll!!  SS##++,, ''P,P,&+&+&&AA  }}rr``;;??r r SSjjYY޳ffݟii@ @ 11JJ:://JJSS]]Q Q @@BB88XXvvUU    \\ZZBBSS++00,,_!_!RR44$$ggDDHH UU& &   II<>@@4499AAjj))OO++//DD LLAA,, $$rr((FFߪ44ss^^jjQQBBZ Z JJ""MM&&  YYooc%c%$$l l OOcc:: //EEWWAAooDDl l 4 4 ii@@::,,oo{{XX>>uu AAf f  44}}``  SS66mm>>rr Y Y [[QQXX==SSzz: : YY44; ; ++p p WWww++!!CC{{ii$ $  66##^^BB@@VV~~ iiqqVVSS  II ww  tt[[MM ]] &&)!)!00O O //nnQQ,,xxۂۋۋDDll&&nnMMaa%%||hh UU99 ?#?#&&a!a![[88SSMMww{{~~++hh BB' ' S S ::xx44TT77  ll8800::HHmmBB CCYY NN --ww\\""[[jj  33zzccZZh h - - KKjjZZggOO<<L L 00BB++44AAGGEESS{{XX   {{--..ff``0 0 33vv^^JJ,,ZZS S M M yy##YYBB  33^^@ @ DD==::FF 77))aa]]7799@@ppYYSSwwII2 2 ss   00 ..U U 77C C ::((x x  NNooGGzz jj^ ^ **~~TThhCCHHff YY@@  ==((55 DD!!==ggff]]ppFF>>``::""& & j j !!ff}}]]EE \\ޞJJDDttp p p p ~~ GGII\\]]1 1 L L 9 9 ee88 QQff88UU&& K K 1 1 hh$$&&[[ NNPPMM ~~ ##OOAA``&&) ) K K ))uu2 2 !!""!! {{^^!!FF  WW kk}}jjnn1 1 OO lls s XXݼZZ++) )  //ppaa\\ xxKK88 JJ &&ss\\__}}gg$$X X BBddtt;(;(*.*.++""99ߪުVV__ GG**MMGG~~77--l l ! ! 00ppnn  xxPP  ((FF'' qq  RR'',,''QQ99''))ZZ22,,::66``G G v%v%K"K"NNLL``,,KKEEBB((++ % %!!h h ..==- - &&((!!KK%%((FFBB\\xxRR))BB  SS 3 3 $$uuss@@MM-'-'))""11ggee e)e)3311$$ \\С֡֊__YY;!;!))))55 vv77;;MM9944LL&&&&XX++vvYY-- EEGGYYKK ll !! \\33,,llzzw w T T    EEqqބӄ66YY__uuE E  9$9$((/#/#TT##ܝםffFF!!>>&&--))xx pp~~99L L ,,U1U1Q)Q)ddSS;;@@ MM]$]$)$)$RR>>JJuuQQss||AAXX  x x ,, AA>>KK((M M $$}}uu))(({{ &&00110$0$ 66II{{ؓXX??DDM M z)z))) AAxxee ::eekk99 ##%%YY||dd ttR R &&==KKccYY00zzW W YY/ / SSAAuuP P NN||@@UUKK GG׾۾oo __''**##UUff..YYQQff//DD @@&&bb//٧11`` cc[[  !!55  ccܱww##HH&& " "="="::uuuuhh ii%%  IIww44CC  ::&&00 --zzSS++mm;;**CCKK)),,&&' ' ^^CCxx==))^%^%''!!  3300ߊ..\\ dd__jjYY[[qqG G {{ ((dd!!//~~>>&&PP // & &-$-$--m m ..22CC33 QQ==--)) ޫeeܐ}} m-m-00r(r(~~bbuuQQ))**WW qqddTTgg  77[[KKgg ޓՓyy** KKEE--''00 tt&&3#3#LL//ߘ11   KK+ + ""r r ~~ggddaa  ~ ~ ,, 9966BB"+"+55S3S3/#/#3 3 rr&&EE 00VVJJ 77..GGwwCCl l xx44DDXXhhbb&&[[RR**eeyyFF$$c*c*Y#Y#AA!!޷nnPPFFrr 99   }}#### UU??ww,,MMwwP P ]]77 9933((&&>> **uu%%ssqq??KKD D   OOFFFF^^22""|#|#""**rr}} TT%%{ { ssKKXX{{ 33nnkk-- NNss44H H ..11,(,(uuddXX]]KK]]----ttmmssvva a BBUUKK4 4 BBL L %%aaWW88$$KKffzz~~cc bb q q //**{{ڐאWW&&))     \\ss--ې֐֢ޢXXddYYkkU U EE""RRyy SSll   ~~d"d"L&L&--!!֚ݚvv  WWXX ??  44WWrrݙ݊==I!I!KK LLxx!!ۏۊ؊GG  K K  ;;  zz WWooڏӏddxx''##}}MM44ii((&&  ^^yy##MM<<I+I+x&x&NNII  ۻ~~YY``    ll--..))ؓطط؍EE]]BB^ ^ !!PPUU""##OOӸ(($$bb  xx!!11HH""00$3$3b!b! OOTTͱ߲߱$$00<"<"<<55  CC;;ڦڶݶee//;5;5$$mm;;Z Z 77:: ZZ yy++33##00ppkk~~ooss((0000gg// qqQQ߀33 ""SS""]]""//'',,>>G G ݢݎގުGG>>HH!! 8 8F8F8##]]jj dd))WWvvQQP/P/77x+x+RR WW))~~ ))EEN N \\Ԝʳֳyycc F F ,,,,ҡ١--  44WWJJAAoo**K K JJ!!**++^^ww>>ĚКЫ99BBg3g3TTKK  , , $$x*x*UUQQZZԓMM ii7711 K K &&**//!! OOJJ SS ܀iiBB""**""jj%%VV&&CC $$&&  xx66zzTTQQII??kkkkee77LL""//pp^^NN''22}.}.pphh))ؒ  NN["["6"6"66VVjjccٮܮGGDDmmb b uu WW!! //  dd66K K bbRR6 6 C*C*V*V*BB ,,xx**##׮֮""%%**##33{{GGBBww}}  $$##, , dd{{&&////%%AAccss00&& oo..BBccd!d! ##xxZZiibb: :       22OOxx@@HHdd%%22""k%k%..wwڣۑ$$u#u#l%l%""!!GG$$мɼHHϐݐݐXXXXLLAAMM[[uuff<<11DDSS* * jj~~ZZUUii33!!))))e"e"99@@**uu## ) ) >>$$::PPgg OOTT<>yy N N VVddCCBBq q %%[%[%!!qq""{{iiII..DDrr(!(!^^ff##MMRRRRyyAA{{HH  ii""//QQ ::kkw w ll{ { nn]]uud d YYkkOO%% ' ' ++88@@O O ++||uu00JJWW  hhl l BB** %%..Y.Y.""""ii   AA}}gg66r r !! jjJJ::RR,, __] ] 22TT} } <<ttK K & & 3 3 PP YY YYBB||II@@nnKK##SSPP]]pp !!%%DDkkR R yycct t NN  33RR@@DD MMnncc66,, l*l*b(b(&&OO JJ! ! <<NN``OOaa77mm55@@nn  11a a ""E'E'g)g)&&{ { kk ::aaOOVVSS;;UU7722**vv  DD]]JJ$$zzv"v"``,,  ``UUHH -- * *+#+# ԫ``77xxaaAArrVVee8899فܞGG pp::? ? ::__ިAALL # #])])| | jjrr  ((''ttzz`%`%!!\ \ ,,((kk99mm߶ LL>>NNIICC[[ XXAA11\"\"..U"U"33PPyyi i   AA99 WWWWSS00!!ss  33MMGG99PPGGUUJJw'w'$$YY||^^II٤tt{ { ""))??ؘwwaaYY ]]. . LL''" " f"f",,## ``{{rr''  JJoo00BBrrOO>>uu   $$yyGG11nnss!!??<<:: ! !((..@ @ **   ((''TT""j)j)22s s 66܀//==w w   ;;!!WW܌VVyycc 77 ffCC((ggbbooHH^ ^ YY55aa@@[[<< H H BBll##++''  99NN %%cc}}  &&!!@@XXffTT -$-$  u u  BB""==~~SS ss  ;;qq PPrr{{IIW W BB]]aaYY==''yy\\AA??44 3%3%RRUU99aaRR   zzRR^^)) FFXX --44  pp||  $$"!"!NNVVhh  ? ? c c ++ FFgg mmCC@@TT!!HH((XX9 9 SSnnAAkk;;?? XXkkcc  ll ~~00**QQ# # p p    oo``%%44%% ffPP.. mm\\ޝ""VV&& OO33>> ff99 \\nnllRRVV5 5  KK__ll   dd  LL||&&''11uuBB//-- X X TT++R R @@QQ%%H"H"00 77##rrBB11 pp]]O O eeߴ[[!!  ee==]]NN__jjC"C"''ZZFFKK33؞cc  :: !!" "  ]]]]xx&&ؓٓ55UUXX5 5 {{))KK..j j   11ggee11//$$ !!''bb77%%xxxxhhii` ` AA00 ))ـ AA !!   && llDD ؆44>> c c [[\\{"{"##66\\$$""ii77 TTHHU U 11ppEE``HHNN``EE  ΊʠߠVV::))))JJ HHll? ?  }} 99KK<<҈33eemm$$FFO O ..%%.&.&jjFF @@**&&**B!B!TTL L 44LL00^^~~KKpp_ _ bb22'' VV 99## ttj j !!ߥ99U>U>((ddFFGG  DDPP##GG__VV%%׷(($$C C qq@@jj77 ''##ߺߗܗ܆ //Չ؉ee))--00 ww ' ',,""nnjjcc''<< ??]]k#k#vv::NN''iiHHDDppBBzz%%]&]&NNߕgg(( ff))AA00T1T1$$߶OO(( 33$$`` CCYY'' 8 8 hhټٕӕ!!   ss` ` UU٨ ((ݫbbWW. . ))&%&%uuԩΩ&&BB(())]]WW ' '  ((UU# # {{BBVV  ``>>88##<<|| ))OO**++))XXܷܿϿϼӼ   TT   WWTT<< dd"" '']] EEppDD ! !x%x%!!11ٹIIqq""  XXrroo~ ~ <>OO$$    6 6 nnEE((FF00ߖcc++99 jj**TT##YYff  ccIIBB   LLU U  SSGG ޏbbUUbb__00@@/ / nn{${$ZZFF((ggZZhhCC`` ii//NN! ! ==}} ''ؤ66zzss""e e GG==zzVVuu} } HH''FF GGpp__  4499߂zz88{{$$BBHHJ J GGww? ? p p 0077NNWW xxCCOO}}$$11tt rr- - hh EEppV V %%yy  y y ##VV IIff22--||^^      eeaavv``<<00VV>>llj j yy,,ggKKyy YYPPUU 33== 33FF**c c CC,,RR۸ؤ==@&@&##dd[[qqf f __FFkk99` ` VV    aa  KKyy[[aa ??dd||||==NN 3 3 SS  //tthh| | ~~::oo33;;||zzVVzz   kk) ) HHYY55 ))bb33xxAA CC<>@"@"$"$"yy MM @@TTgg۾پ<>{{X'X'bb``LLhh33YY{{HH @@PP--&&  >>??DDϚ,,,,dd  ) ) 44OOVV   FF KK||YY: : aa ߥ$$..d4d4&&>>88__%"%"  َPPGGq q 33DDYY  88PP ^^ooNNMM6%6%''IIIIZZ**??TTZZee  tt RR99VVXX8$8$11E)E){{ uuWWyyLL@@--//  [[KK  ii'' __//".".vv<<``SSnn 77vvee!!mm ؟LL   RRqqqq   ..FFKKq q ``''//TT  CC^ ^ BBxx..ii {{' ' ggTT ((}},,XX% % pp?? ==  ZZ00rrS S ''??--9 9 ޛ޾ؾddXX88V V 33%%ee2211MM2 2 55""!!pptt\\ ppDD &&dd99DDvvؓ݋YYtto o EETT88  @@!!)) ~ ~ RRaa ''44rr&&@ @ w w ee/ / : : WW__SSvvaaffaatt  v v ``$$!!iir r  (( 88>>IIKKkkdd iiYY6 6  bb >>YY00PP##mmߤ J J yyhh66ttbbO O H H aa     LL zzNNmm   RRqqooUU{{55xxbbii>>WWvv``TTrr< <   b b 9933FF }} P P / / **&&..ww dd{{mm  jj77//== 11bbNN6 6 MMww33__JJ   \\nnTT SS((22@@bb ::dd~~##  ))^ ^ gg77::nn ""NNN N  ..qq``ii77 __jj   pp!!""mmPP  TT >>  <<gg__VV  II??%%EE__DD nnss  }} ``}}xxLL bb ++g-g-++WWeeVV55]] ~"~"&& jjnn ''H#H#"" ~~׾,,<<~~pp  11%%LLPP))II||s s vv22::GG UU##ZZ' ' EE[[BBf,f,5)5)mmQQ&&!!WW&&ff++$$llzz//qq}*}*%% !!--??ss**V!V!44,, !!Ԙݘz z tt**GGm!m!))bbTT  MM||־ݾffRRyy FFaa==%%  ~ ~ ff//\ \ ??UU..\\[[ ..$ $ ..S"S"$$vvvvnnJJ&&A A | | 99ަM M r r ""!.!. ! !((||44!!;;))``Y Y xx6 6 hhږRR4444**r!r!ssjjeej!j!S&S&~~9966JJ``ڋ>>qq00^^11DD RR G$G$M0M0$$bbpp**55VVllGG11GGn n KK``$$ss`` uu ==yy22ssaa&&  ??u u JJz z ''\\CCYY||   EEFF\\!!C.C. ( (22##ZZ**mm!! @@::ooAA  jj[[@@ DD@@`` rr   mm33rrj j $ $ EEccHHcc nn//55##k k !!CCjj%%ooN N vv!!!!##~~77%%t t ^^..uuyy--__y y yy 2 2 x x h h tt"" U U P P UUMM44<<  TTxx&&}}PPk k --mm::AA  zz44MMqqeeLL$$PPff``AAU U ++ddppccddkk    ddK K u u RRnn&&[[EEvvqq((yy<<rrKKRR%% S S j j 5 5 = = 33$$:: pp44##EE//ff99NN&&<<00xx\\((ss  JJHHWW9 9 iiZZ""HHzz{{--11   nnhhTTI I  ooDD**rr;; %% ==uu<<]]$$kkyy//88ssEEZ Z 2266VV"" $ $}}""SS33hh((TT55uu[[Y Y 0 0 -- ''%%$ $  ++4 4 [[<<ݐ N N >>--  o o { { QQll&&ܥ 66ee$$XXO/O/i0i0xx22JJ%%mm99jj__FFaa]]33""hh$$C C BBDD ##$+$+44  pp::߷\\BB..{{ܡgg ii++!!--n n RR55--AA<<RRZZBB``@@ ZZ  t&t& ::vv!! ffҞĞĽҽ҃`$`$#=#=#8#8 YYaa110#0#wwֆ ^^ii  n-n-**[[ %%"" bbkkWW ڋ LLnnݎNNk3k3S9S9e&e& ::ii݁   VV ii BB^ ^ vvnnϬuu!!.."" ccnnll33VVoo$$WW&&<<@@A$A$//++,,@@UU||ܫҫ&& F F ,,ff  -- --ii]]xx@@WWtt33צ  &&,, 11vvHHq q PPnn  55II]]llxxN7N7;;b&b&   xxC C zzRRNNkk ;;++ii!! UUѾ RR( ( XX,,"8"8/)/)``ϭ77rr zzww  GG}}hhփރ,,~~ 4 4--m m T!T!##  ||wwVVKK## [[DDhhޑލ̍ZZpp~+~+--EEMM++x)x)MM 99 &&>> dd``ss''55# # !!k!k!t t YYll{({(::00DDaa}}BB]]ffE E ^^" " !!T T !!ooJJ NN??u u EE+&+&,,ݦ II BB&&OO>>ee$$zz@@AA**I/I/\\ ggH H KKKKxxzz>>00 66>>vvpp ""E(E(GG\ \ ߑڑ\\//BB L L bbss  xx**;;PP nnkk_ _ jj66  jj55 RR>> ccBB   nn""jjo o ,,YYFF  HH QQdd& & a a d d QQ--c c RRJJ]]JJ/"/"R'R'pp kk SSrra a    {{jj  JJ OO00G G S S nn\\WW~~p p ee;;DD::22mmVVoo__::~~''qqccLL aa++( (   NN<> _ _ llJJ //oo FF == --{{qqssRR   == ((^^!!RR- - + + JJ   S S rr xx>> {{ooZZ 88UU((ttDD>>##//5 5 | | ]]3311uu{{[[ &&^^33 x x WW11xx  <<??hhިYY,,nn00 88. . 00}}tt   KKAA--ppaa ~ ~ 22UUt t % % < < 3399 nn܅$$66 ""KKhh((%%__mm~~zz55ވee,,    WWzz99NN qqhhFF88ll``YY== ,, ||bbrr11AAvvhhY Y QQS S v v [[ ee``,,((ggFFڕەeeQ Q nn%%XX22dd  UUjjߗ߼ϼuuyyuuccF(F(!!G G ۨۘߘ}} V V dd ddq q %%&&dd ߮VV--""00Τ]]99YY"">>@@jj  cc==++| | ww ''11,,ooz z SS11++//hh``nn66c#c#++ݦ ttuuWWxxRR''ll9 9 kkޅ΅IINN݃%%vv__,,%%u u FF  AACC ##xx::$$!!HHP%P%55ggz&z& ;;# # WWee>>''  ́ɏݏݡ::m m TT **!!۬NNOO rr __xx""JJDDEE66۩**yyZZ%%qq((jj11YY; ; WWllIIPP__ mm&&<>0099Q Q ZZ==zzhh55ddmmMM,,&&JJ1100YYMMcc 11EE^^''88RR__00::mm//  y y TTdd55  tt  ~~ ::DDOOMMNNOO //YY$$QQKK XXmm00ggRR00V V 99ii ~ ~ nn((LL} } - -  @@__ss--FF// <<``  %%OODDCCII]]H H 11%%**33~~ wwNN22$$ ""77::^^ ? ? dd==PP..>>r r zzqq ffEE~~ZZ\\))hh~~ ((  R#R#!!e e ;;11mmoo**i i ccJ J //ssjj ii99jj99}}**&&@@??77* *  jjBBrrzzڤۤۻ((// llwwJJ}} 3 3 \\00xx  33TT""  LLMM((??qqQQpp __ttyyRR %%UU::rrYY""33]*]*88OONNee ||- - --~~AA``{{DDh#h#~~LLeeEE  pplla a ||  00KK ,,**kkTT::ݙܙ>>  @@""ۼܼtt--V.V.gg{{  BB ;;GGjj SS . .0#0#پ   }}LL%% \ \ ]]%%GGv,v,22  UUCC00 __  $$ee88==HHVVqq  j j ZZ&&QQh"h"qq^^YY- - ww RR&&ll""``   YY44iim m   ##^^llwwII WW!!%%uu  @@XXjjll== ==< < tt}}ݘd d  vv @@zzbb ZZ3 3 XXhh;;aa WW 00;; hh::++bbZZmm 22OOkkCCaa__--^^11^ ^ $ $ }}}}++kk""qq<>NN``LL ,,||aaAAR R wwffpp :: [[oo##''BB> > TT$$ߺ߮ VVYY<<  AA] ] 99//EEW W 88WWVVSS))xxvv&&HH**..xx c c ZZhh77p p }}RR8 8 { { ##iiZZ,,--^ ^ 22"" ttU U 336644]]55[[[ [ ,,vvD D vv ##99eexx99~~NN^ ^ ``;;ZZ <<RRxx]]%%@@ZZKK  ~~JJ::!!QQ NN<> ""@@  jjLLٺ ''OO||CC%%88gg* * %%UUhh **ppggUU  oo  II((GG77%%ii@@w w EEnn mmbb''..ۗqq,,BBڔ{{  &&WWII!!!!++SS..%%ցiiJJuuww$$ QQss11ll^^%%&&YY44ڲ))ii>>++ ++ GGII,,ܨ??K%K%XXYY}}ggoo ss||VV00 @@-- uu  ߦߨߨO O GG$$$$..  55pp(("".. qq==$$RR@@EE,, J J SSiimm}}""JJ3 3 xx  5533++NNjj((L L GG\\//++||//!!PPxxt t KKII OOqq  6 6 {{dd^^  OO  E E !!?? ..q q 44ZZOOSSg g ))qqEE 44UUoo66zz55  ccEEllCC- - $$@@OO++77z z $$??    LLTT==yy||88VVhh AA##-- ll  ssSSHH rr  ``((==<<P P ZZww55,,d d DDE E RR 77EEcc??@@$ $ {{3 3 99&&KKDDff__hh  &&""uu  K K 77KK## 00~~vvUUvvt t ooll _ _ **ee__AA-->>BB-- 77B B ! ! //^ ^  mmEE//ooLLDD8 8     --!! {{CChh''(({{JJ D D }} UU  ZZYY;;wwrrAAss"" ++GG66PPqqtt&&-- n n {{oo \\,,2 2 pp;;99  CC}}SS((||BB00gg YY {{qqAA//B B MMGG[[ss  ;;kk  ,,||K K ))MMyy""yy--``22uuII  dd]]  >)>)ssXXaa%%߀߿00W W ??qq||||yy99qqSS==++55==_ _ XXZZDD55== kk@@"" $$++++ TT8 8 >>ssJJMMAA|| bb CC  _#_#99//wwuuii ??66LL**ssEEBBvvJJ""hhZZ 44YY((ssww{{S S 99AAOOYY  LL$$OO ||kk66??qq55 K K __VV( ( CCUUZZ rr --HHPP88::  11R R ? ? ppPPKK66BB --}}5566//  D D  66 IIt t !!II::%%--==lloo{{ 88zz--EECCff00AA,, OO||SS uu??55{{--(( ....qqOObbgga a y y E E   jjppuuVVYY<<@@  jj88UURR  H H _ _ ߜۃ~~!!$$TT   9911WW  ||- - DDMM%%FFvvwwkk44nn||LLZZcc--66ddyydd%%ooSS __\ \ 44ZZTT!! OOoo8833))))99))WWEE nn,,  L L : : HH""ff TT CC UUy y  RR >>99 {{ hhGGyyIIGG dd.. ##  66ee))aa$$  \\]],,xx@ @  HHRRee __ GGgg<>~~J&J&$$CC**/ / WWKK  L L @@##++99ll|| $$ 77&&oo ))I I 44M M ""``NN ||} } >>6633u u [[77XX++DD||zz2 2 "" ..rrVV33 __SSNNqqYY99ww__TTWW  NN ww88oo88{{``YYSS$$$$!!   ,,bb8 8   ))KK ? ? ]]7799PPZZFFHHRR66////??   $$ooPPRR==22 K K TT;; ;;((OOssHHee oouu[[ ``  uu) )   8 8 99{{\\8 8 BBJJNN;;jj--ޱ""tt dd- - \\[ [ ZZ~~ZZRR;;[[6 6 88GG&&DD TTUU6 6 [[ eeUUQQuuYY   uunn   ww>>   22 Z Z rre e ssGGCChh  00gg% % ((\\hh  ss  JJBB  DD XXEEhh//TTuu** yyrrJJ## .. rr..  vvEE4455XX``77]]55 !!]] HHggTT --SS''zz  ,,hh ||@@  vvbb}}__ \\jj  44 PP hh]]]]  GGllVVd d ]]ddVV..--ggyyppgg~~77GG--  oo \\!! ; ; qq?? >>[[II::$$  ^^\\22t t ++k k 00@@QQ  MMAA  &&<<kkTT rrKK qq **oo^^WW   --9900<< eeFF..  jj2 2 ""  O O ??jjcc` ` 9944||YYLL,,jjEEqqmmVVp p 66__ , , wwOO 22""d d ppG G hhttss<<  '' xx@@| | cc ff::~~ \\11f f ppOO``JJII++8866Y Y rr~~ZZ^^88  88UU\\))WWb b ff((""  MM   ))wwtt)) 66aaBB@@%%>> OO1177ppf f hhWWcc&&m m ;;YY FF<<ee..%%`` n n **//<<  EEXXDD e e (({{)),,  }}  $$aaD D   88mmwwJJvv!!++yyEExxs s == PPLL&&66mmiiii$$==55##[[>>aa?? GGhhIIVV~~22eeccQQ))FF++))FFM M ""__4 4 **uu    ``  bb%%ZZYY/ / ccR R 33||++''yy!!((TT: : ) ) uuSS  1 1 11FF::  ~~**JJ\\0 0 JJ  ggZZAA  ee  QQww|| & & ;;--$$ uu??GG]]ooiigg)),,%% }}xx,,A A  >><<%%R R ]]  7766pp++cc``;;KK @@CCkkyyPPOO++JJ !!-- E E ==EE DD&&ttOOQQaa< < 99%%mmnneehh%%bbqq^^MM``~~GG^^ff  ((QQxx``FF AATT{{}}qq PP::q q GG<>55mmaarr9999 kkAA,,^ ^ \\rr))xx ,,44ZZ ''ppXXxx  | | 2 2 77gg # # ff8800TT{{SS##**xx22 EE {{yyeeAAvv&& GG ssii++ ++kknnuuJJ==ii@@ EEmmEEnnFF   $$UU KKn n WWRR  o o ;; ]]CC))44OO cc&&889911''NNnnMMTTSSzz""**. . xxZZ[[ddzzrr ##}}zz PP IIee//QQqq__;;TT==77dd dd hhaaff   p p 665 5 \\  ''&&EE{ { FFUUVV~~//55 \\33o o CC@@II33RRv v 33||;;55KK$$   ,,(({{n n M M ++CC__? ? ##F F  qq"" LL22i i eegg0000w w ll!!JJffkk@@CC  ?? 33~~  < < QQ''7744t t   //88PPx x 00{{t t uuiiss  { { k k %%]]B B 66 ))==gg,,^^77%%@@,,,, [[22OOss``BB__C C 7 7 QQ&& 8 8 ^^))##&&>>77]]bb^ ^ "" ##  tt LLee77--11@@44XXNNSSZZ\\@@++gg --99eeRRMMIIjj^^  RR??22@@00HH nnuu ""ss oo&&OOyyWW<<@@   hhtt""@@gg11QQ'') ) SS''   uuOO((!! ??nnRR\\!!PPff >>q q ((uux x  $$llttTTCC``TTXXDDff ''##ddI I 00  TTCC]]}}{{z z gg]]||?? M M QQll @@MMDD[[qq. . @@__@@00J J ++! ! ++eeZZrr88{{&&aa--^^**CC==ZZOO(( WW22dd**qq  jj11  HHnn7766,,dd~~A A   ::llbbCC ??**uucc44..hh% % XXCC--||ll  KK__xxs s J J //[[YYQQ??11IImm##--HHbbe e ++dd;; MM\\77OO  ooww ii ppii**BB qq++YY@@33u u R R cc==@@bb//00nnPP ^^44ii AA88//6 6 OOkkTTBB  JJUU //??!!NNjjKKvv<<\\SSDDVV0 0 o o aaPPffBBii44OO ll((yy\\pp66(({{ yyiiww  00ZZqq33qqqq33++ 55>>^^gg ww qq{{--0 0 ##ddWW yyFFCCyy% % v v ||zzcckk::PPqq** e e uuU U 66TT PPnn CCRR-- uu R R ''``## L L || zz!!OOIIllgg&&66**\\qqEE11>>^ ^ //zz  ))rrJJrraaee  DD__TTbb 3388ffQQ  RR  WWrr))~~YYCC$$ee  **dd %% 00nnLL%%OOll  VV99__@@QQ99--EEMMQQ 44++mmPPmmTTNNFF { { lls s JJZZttIIPP X X EE'' q q MM 44))PP,,   ??nn  ss..&&00r r   ??eessmmEEqqbbJJ  l l jjPPii( (  uummGG||jj``ccggYYw w r r OO8 8   ??c c : : 8844 >> JJ88yy }}||< < ""hh ||UUjjllvvVV))qqVV  TT>>uuLL@@DD hhpp,,  WW__..  R R  DD~~\\++uu g g ``==((EEss33''     ==jjCC$$# # 44WW33oo..44__66eeMM""22**VV//''//~~mmoo,, GG& & II~~ii11&&WW __ RRkk ss ##||%%  ?? OOgg~~uulljj   }}uu? ? 5 5 BB))zzPP++aaPP..vv!!<<@@  K K \\- - V V --%%  qqSS[[{{^^  11hhoo   GG;;ddL L 00ttcc  LLSS   **dd 5 5 ""ccJJiiu u ]]ff}} %%BBss 88f f 00==~~DD r r __PPccff66## 55$$Y Y 227755s s jj ``@@GG++ llzzvv  ==77   QQ qqrryygg%%qquus s <<^^uu+ + ^^FF >>cc??  bbffKKAA; ; xxuu11**f f yyee  WW,,77,,FF33{{' ' qqII__ HHEE ]]@@dd LL66pp77   ..TT $$}},,""++ee bbDD>>rrUU  b b ~~//@@''&&cc<<))CC V V ''XX&& SS__ttOO22FF__EEGGjj BBffRRggddMMff,,nn>>88{{;;[[))qq--__aanneenn""GG[[ll==88ggVV##;;!!eeT T __--YY..hh YY//aaddvvdd9955xx``%%//jj HHmmcc  QQ aa;;((    mmgg __ ))VVllssDDFF ZZ llCC --^^ nnkkoo + + x x  ''ll==ooww FF MM&&HH  ;;w w  AA%% 99oo !! TTiiRR vv<< UU((^^ccBB  11 \\//||>>eejj33GG JJPP22 qq55$ $ I I IISS<<qqqqllK K VV))))v v llOO    ccRRoo,,""~~@@PP$ $ >>00 EE__) ) --cc**__@@Y Y 5 5 tt    @@ssGG  33**!!9 9 223377>>  LLyy AA__QQbbVVkkKK JJdd77))!!77 %%;;``uuq q rrnnJJr r 0 0 ^^mmiiWW 11/ / JJMM[[\ \ 33 ++rrff,,AAyy]]GG    __UU cc FF44VVyyc c d d DDpp,,xx^^!!   00@@!!ttjj ZZrr BBzzBB~~ss~~mm''!!? ? & &   77mm   (({{AAWW33DD& &  ?? ff22hhee X X $$//00bbNNw w 5522 xx\\>>EEzzzz xx::11    ]]zz; ; !!cc##s s ` ` dd//}}$$FF44 nn XX&&}}55dd]]wwK K [ [ OOHHcc hhuu--. . ZZRRgg((YYkk00ooGG  VV77SS44LL44mm88AA~~hh88OO]] m m ;;ooSSKK88ii44LL^^FF))CCbb>>KK <<PPRREERR__VV88mm]]uuOO[[ll"",,11vv,,ppYY11GG  BAabKKDCii WW@ A ,,bb11KK++a a   SS//CCee""GG __ 11RRyy__ VVGGxx* * JJ%%HH]]  sstt:: ""{zDDS S Y Y  }} $$45  hh67  BBA @  L L VW o o QP55AA ~o p  77 MM  ``   l l rq  \\UUGGC C (( %%^^,,^]" " U U ;;  ..XX%%  KK// ef  ;;\\--  ' ( ('II.. kjZ[`_ ijLL ; : )(MMFFNNcd"#{{WW ('00LL)( ^]   ZZpp????PQ""vwmm=>&&DC==98<<88[[,,ccKKij vv88CC&&[[SS LL]]! \\}|bbpquvFF&&ZZEFEF22yyAA**[ZnnllPOQQRR..A@ffWVRR>>HGyyVV||@@YYllppIHbb66II??ww''\]  @@YYHH[Zjj& & "#JJGG..vv\\DD%&hh[[xx[[ GG< < xx&&55nnBBAA`` **^^JJ44PP    nnP P G G mmBBttLLll!!    nn0 0 NN@@ R R 66ssRRWW##66##SS66KK HH < < LL \\//WWiiJJ22RR $$RRppp p   KK ''~~qq``~~HH~~ I I 3388 YYHHVV3 3  <<OOll  cc[[88 rrg g hhjj` ` ^^==hh]]kkRRii  MM ((  &&HHww$$KKooII 11zz55[[==;;!!QQN N 99  w w ZZ&&xx==``22UUNN_ _ VV++ 44mm ??ppRR11rr##''ff++BB ww??22 JJ00ddrr**KK::oo   335 5  66mmcc   MM <<vv{{ u u vv^^ q q oo**{{uu<<__uussss**((LL4 4 ::zzYY88{{WW||CC rr>>EE66++mm 44 nn** 66 !!rr::- - >>@@DD**44s s \ \ ;;;;FFOOmm 1 1 BB) ) CCGGiiOO yy55}}9999* * ^^''ff   ##EEWW`_oohh     77i i TTLLyy%%2 2 cce e uu LLcc  E E WW BBccrr--jjiiDE **WV{{  !!UUNNLL}} II O N IIDCooII N N 88ttss884 4 FF$$utz{9955R R JJa`$$llII^^#$  ii56--ss''STJJAAOO~~CCUU,-""++`` -, xx .-LLCCJJmlRQLMXX::23  22`a88[ [ mm!!))=>44,,87RRqr KLJJ;;JKno AA??RRPPDE--  ZZ  \\ijpp||utvwvuLM0033&'bcZZNN"" ##YYkl%%ww+, Z[|||{vvSR|}|}[ Z  ~ OO67KJkj     ##==d d 7 7 WW45no  ?>II PP,,ttZZhh..^_99CCDC hhGGrr!!  | | 11__$$~!!::& & TSab| | llll<;PQ DD~~MN   KLED  bbTT  E E ONTT.-BBLL^]~~bckk T T dd{{ ,,SSVV99,,ZZ>>00ZZzz__~~HHzz'';;`` tt{{  QQ 3 3 oo]]--bbl l XX gg||   QQ2277??CC  \ \ \\bb\\]]cc,,PP--ff22CC00II, , jj77>>KKyyzzBB__XXGG [ [ >>33eeMMmm``//WWkknn  ))CCccZZwwttRR11PP~~HHrr//cc__LLyyYY**## ww]]oo1100''00pp::ZZ00NN0099  }}..CCLL??22qqeennWW""PP{ {   jjmmAA))[[%%ii,-5 4 ( ) ZZGGJJ ll8833::65NN==0 0 \\**kkii^^22 VV{|8876cc-- N N nnpp""BADDyy::%%CBmm``hhAAIJ|}"!)*ii33cckk10oo@@jjll::WWCCK K - - $$yyKKbc}}''RRIIJJ44EEPQ MM`_ff$%vvyySSuv==uu""~,+11UU 44Q R DC  `_JJ]\||66@@}}sr66??##hgyx77 zzZYkk;;` _ dcooXX i h Z[6566=<kj++++77%% MMffkkonZZ @@77<<,+yxaa qq*)hhVXdd44  ii89]]{{}~++EF  }}56 56__?@^_67FG]^     9:mnst{|+, EF,.STvw&(;<  XZuv <> npfhcdbcBC%%e f 46lm*,>?z{"#u w -0z|y|BE46 :<*, LNmo "$"$    ) + NPUWQ T XZ`cpry{AD + - .0*,gjhk SV   \ ^ (*`b24 57kmNQBF5 8 +- [] z } }JM&) ce 36  =@z|  /1oq*,>@NPsu BEik')$&LN#& @B^_ )*YZtuOQ`a?AGGxyHJ[\:;GIgh qrkk]^12 bc++77eeZ[xxuu,,LMOO    AB<<xyMN&&zz]]  @@}}-.   __bb  GG{|TT^^  `_** XXWW&&aaSS99eeVUJJ~''[[ 4 4 -,VW 88KK;;__//IIXW\\[Z** ddab@A}}pp  0 / jj=>%%yy??llDD66--uu  --;:MM[ZxxnnWWBBrr88 xxqqIInn{{NN2244PPNO nn++Z[++66qq66eeccddYYddQQ``eenn??CCQQii55@AwwGG2266mlhh,,rrNM!!$$ggHH@@qqUUqp   nn&&iinnLL{{..jj]^``ll''@@OO))   rr%&XY{{y y Y Y &&~~pp00//NMGGpp9:pp331133_^;;TT==TT RSwwxx; ; 22gg++jj rr aad d z z 44KKTT''+,wwyyp q =>21,,YYCC  22MM  43QQxxh h //87ff\[@@  n n ~~@A}~PPMNkk,,LLyx11ONSRZZ  |{^^@Arqccon{{ 22LL65..>>rrkkii  }}LL   hh{{[[llyz ''[[  YYR R 44ii}}1 1 ggppoo\\$$ZZ55k k AA55nnCCTTST0. feEEM L **{{NN{{uu   4 4 ,,/0( (   UT21``ggQQ::##*)  &'&& j j WW!!66  @ALLCCppXX00]]--r r  ! *** ) I J  zy]]NMpozzMMon  g g ((k k $$JJffRRyy@@TTtt32SSXXvwg h ppE E vvXXRR  =="$}}qqssII77EE OOmmee  }},, ""MMYY||ggdeTTLL--99--<>^^YYBB==TT~~22GG11??NNqq7733}}88yy88JJ??MM&&==aaVVFFffOOXXMM$$HH[[&&JJ'']]NN55UU,,[[JJ[[DDEE))99CC ..[[6699,,KKll55UUll229955JJ FFPPRR MM  jj22MMAAvv>>NN22))bb&&""ii**)) ll00SSaa$$ss----ooYY:: 88yyllaapphheejj((11aa>>==  F F QQLL ``LL44ff # # ,, "" rr<<   ((TT II11ppxxFF&&>>kk@@||O O hh WWJJYYYY..~~,,]]((""RR  i i Q Q KKYY$$KKqq QQ &&**QQ++DD..SS33  ))RR##~~^ ^    %%l l **^^zz  &&k k   pp%%oonn44xxgg~~bb ] ] ??BBQQ]]##qq))----::[ [ 1 1 44))44CC##%%XXssG G //77uuVV00 hh++   !!rrGG||{{==lluuxxcc77* * vv++nn==mm hh{{ aa**PPhhcc //bbYYAAssggyy====ssLL__QQLL 33  //0011 pp99GGii00MMi i a a %% xx--TTEEyy00}}QQAA EE5577  vvDDzzxx\\WWSSCC$$llm m * *  8833__ww KKvvbbXXwwZZ{{++ 88+ + NNuu11~~55::xx**99   77EEIICC__FFNNuuiiuuHH~~11VV{{UU  gg^^IIggJJ ddyySS..WWhhffyy$$kk~~))rr__44""cc 44KK++..{{HHuu^^KKZZbbggeennll~~LLGGxx66GGNN  //OO88iinnXXHHllFF  kkjj99@@``}}FFQQqqkkUUpp88LLJJRR==yyqqRRppqqWWbb:: 33@@YYii))__hh55\\\\99``YY\\``//HH..ggkk%%PPaaIIqqMMFFOOMM::~~++ii llNNxxhh))~~WWTTII &&##~~hhaa____ jj 99OO66{{**22..ppmmyyDD++;;L L CCzz 88OOoo}}AAff **TTKK))(( MMYYF F EE44::VV{{$$FF11 lluu) ) g g HHbbwwF F zz;;$$XX<<PP  PPXX  ~~vv ppbbOOmm}}22RR"",,   ffKKtt**YYNN]]22JJpp 5588 $$DDwwSS   nn==EE^^cc22^^++\\~~ wwllE E uunn  //hh((..++11&&  22  RRpp++/ / ooYYNNii GG jjv v N N  .."" AAppDDww<<SSSS y y II11qq--rr  bb88yyHH**!!99~~33--nn- - ^^  %%<<8 8 dd55HHW W VV%%ZZdd ssbb,,%%OO55&&  OO''ff""7777//~~u u ++>>GGxx??MMVV<<vvnn@@99==DDvvxx//33@@yy QQUU ``ggiiYYhhRRLLRR,,11hhKKOO""{{::``__]]))ll99uu  cc''MMJJ))[[{{''UU<< {{wwBB  <?fgQQFF\[&'11qqii  YY  kkfe>>UVXX  HG--UUEEv u   klNN&&ssmm=>uuXWQQ  GGGG8811@@--[[ 43PPyy::FFMMtt??SSFE C C SRIJ}} ))zz}~ }}bb+++,  [ [ {{RRTT cc32   JJ|||{ ff55""OO! ! UTK K !!<<ww' ' ##XXuu??``PPLKff))KK. . ``66RR~~ggBBSSwxqq MMBA"#  ||ZYJKkk00ddTTXXXX##-,== aa) )  QQBBll$$LMuu pp55''B B _`RRIIxx   eeCCll//XXUU **SSff$$^^hh66xx%%11>>+,MM<<xxWW88;;??hh{{====66OOppjjSS==77HH  0099ggkk !!VV,,RR22--66TTOOppCC&&GG{{!!``11&&DDddqq``--GG__VV~~''bb==dd22<<JJEEll0077kk""SSXXDDRRIIGG994433 >> aa""  {{## HH]]AAFFNN]]  44~~ ii==77!!  ??MM{{ ZZ11hh\\^^RRII..22ww==EEKK||[[::XX[[MMZZYYww??44 AA>>FFYYAA""uu++\\::aaWWGGBB``==uu&&UUuuGGzzEE||''~~}}@@TT[[{{ccSSddXX66WW++""bbggbbEE>>NNaarrrrOO##mm88]]//[[!!""mm))nn??uuDD]] 33''nnyy55__==**22ffWW ~~KKLLww``))}}66mmFF((ww44''""oo ||<<QQKK99dd""DD@@33  ^^ST,,^^[[wwMMuuWWdd**VV,,EEUU11  DCJJ~~01882278&&~}YY**TTkk{{aaTS,,QQfgcchhmmHHUUvv99LLTT22{{wv  ??FFZZ>?  $$pp@A$%12  {{\\NN67OOFGttss!!qqpp0 0 <=[ZjjBB K J && ;;0055<=iiaa++ccWW33RS}}))) ) DD./ tteeddhh{{uuEEII22}}qq{|~~++ghmm44YZ##~}FGts:9[[<< j j FERS{|--HHOOrrMMKL22ww\\RSa`*)yyi i {{GFss77 !"..[[!!ccNNiiQQ}|78"#  ss''22BC==st999:nnxx\]WVee22ZZDDmmJJ++++SS\\BBPP,,SR>>ppjj33AA00^^ VVppKK%%wwnnrr==aaqq!!;;>>77$$XXDDll;;{{4400yy""\\ JJaa**--gg YYTTcc 4400xx''zz!!++ mmhh''AAUU  ##22  \\KK%%!!::::gggg66@@bb>> EE))##ddAA[[^^&&NN||;;ccEEXXeeqqqqLLoott))NN==CCww \\xxvv::__ww33]]__::FF{{**::CCpp''RRzz,,^^//qqHH  nn##77PPbbttMM::QQ&&AAwwNNTT44>>>>66&&[[rr::||++uu4444zzYYNN[[  ii FF55II##$$||OOPP==yyEE??{{==xx55vv,,''1122NNgg??//55hh44]]wwSSWWkkEEddZZhhMMppXXDDkk..~~oo--44QQ((GGCC77hhRR))mmZZ}}33PP $$..IIAA((kkUU qq!!<<YY,,00 TTJJnn;;>>??~~ZZ``##44VV::JJ&&##jj;;uu##__@@ZZIIII\\}}>>IICC66ttUU vv//aa{{]]..}}``33&& "";; **CC>>::aaTThh>>KKnn>> hhqq''55tt..77$$UUddOOOO--@@UU88 ))@@ii   %%eeyyHHUU FF//ll'' //AAqq55SS``00RR--$$ffss((++**ffllww[[HH~~))CCxx__66DDvvyyWWaa11\\GG<<uuqq..kkllIIllSSMMccrr5588##AA>>tt{{,,VV]]55""ZZ||qqKK pp>>;;ttoo<<EEmm66**//wwAAyyDDTToo``IIFF**UUcc++,,FFii ))ggkk**>>RRuu[[44--  JJ==rrvvGG((hh++[[rrVVUU``iiqqgg]]77ll~~WW88}}BBUUuu99SS//cc22DDzz)) ##77__ || ((ooggww@@&&77))MM  77]]bbDDbb%%@@oo**HHkkee\\MM))00VVSS::ff44&&bb $$''TT44__""NNVV ggIIyyooee~~ HHffRRddGGEE ^^**~~  NNnn@@..~~pp^^]]55||FF  eett$$**AA//  lloo~~MM;;yy""yy11RRff&&77 gg__((::RR,,66FFqqNNPP  NN dd  DD--ffTTYYttll))YY<< MMJJFFYY}},,>>SSZZ22  XXRR!!BBTTFFVV]]44ll{{TT  88GG443333DD--xxuu11~~== 44**//99llAAGGnnAApp99GG==55%%MMII||YYZZjjBBss00cc..WW rr''::!!55{{**ii~~ssccdd66$$OO8899;;  zz==rr\\YY<<XX__MMrrpp__QQ||yy==!!cc[[QQii;;;;((BB{{44ppbbYYDD aa@@66xx PPFF]]99>>%%**II++@@yy..]]55}}SS==hhee~~]]%%<<__11MMLLHHJJll''::PP==gg__WW'']]TT  XXff  66qqBB``AA**$$yyqq00yy11AAuu>>EE fe&&OO||xx]]JJSS77~~@@DD}} \\AA   dd@AGGww  !PPUU##ut==TUz{  **KJdd]]xx{{BC-,99""OO@?..((;:PPZZ;;zz--KKtt3345GHYY!!11IIjjAA,,hgNORRvv .- oowxkk AAYY1188BA$#UUqrmn88tt&&@@JKLLji~~@?==01!!WVAAjiXX((``BA66//00TTmm NN,+))WW00]]$$DD>?@A67KLCC||99 1055ppMMRRxxrs,, --bbXX=<uuXX//WW"#yy%%**[[VVrrkk;<AB33 ((\\TT$$''0022&&tuCC++++@@IH''rr77WWtt  zz11 ..$$yyVUee]] BBvvZZ==WWwwbb 66=>..6666  kkwwed  ::}}9:KKvv>>++qq))uuff  vu~}HHee~gg00[[00gg77ttHH;;ww45wv88*+vvjj  {zQRWW('./00UUMMRR11YY*+))QQTT  ttaarr^^[\bc98}}!!JJWWAALKVUbbYYmm,,fgHH}~%%XY??bbMMtt--zyEEPP'(('*+``**>>z{AATT??WWrr``^]oozyHHSSED))VVCC++00fe--iijj;;HHYY uuxxppdc\\GG"#  iiRQ==~}hh::]]'&JJGGghlkQQ||OOqpJJ~}UU<;^^BBmlEF\[22ZZvv**llJJZ[vu HH;;  ++  wwop==EE\\]]ee""EEUUSSbbii[[iiut KKdd,,eeGGjjjjII55xxQQ\\HHss uuZZ??%%""ee22{{YZ@@!!BB  aaPPoo  `` $$;;..rrcc!!eeJJ..yyWWNNll!!AA}}OO @@!!ZZ 66LL^^<<NNYYKK)) bbIIpphh??||KKZZnnhhaa''eeee*)PPssts__FF**98__tt87''^^]]##::__kk__II!!11rr''EDrsttuu^^|}xwggWWII}|xw./@?KK@?<<ttGGrr++vv??WWFF||<<DD$$CBvvjj"!??uugg  HG~ST56||bbmm00OO..55hh{{VV SSLMhhBB** ZZcc44**00eersTS[[FFrrkkMM\[qq MN88--__aa43OOsr((++JJ;<xxOO  zzooTS??98YYuu^^==NN==ttpo\\__JJedLLaa::11 WWllssxx@?@@ IIihccbbPQ{{ooJJSR<<mm..qq22vvRQqqon2100,,hhVVWWppMN32<>77  NNWW__11ZZooccttiiCC99llff""((AAPPCCGG66 ,,bbQQ88??::pp QQ!!aapp""^^NN@@@@SSXXDDaaPP44ppjjYY@@>>,,--**__<<aa;;>>\\II11]]ppBBmm,,ggXXyyuu!!}}[[uuqqDDEE~~SS]]IICCxxUU..UU eehh##$$]]vviiaa88ooooMM&&~~LLTT@@@@nn@@qq%%zz&&~~llNN++^^22((OOYYJJ__iiCCAA}}55**eeKKuuTT''pp""~~88\\~~EE::QQ]]FFDDNNAAlluuSSWWggPPss{{%%pp>>~~))**55  >>ccLLyy^^ss::ccVV88hh88**\\qq!!  II++||88QQ--ll}}""--ggEEMM99PPccnnWW``}}ppkk^^**WW0066[[OOzzss{{--st@@XX##%%bbII^^||DD*+mm00]]mm99&&tt__4433lmijHH44ee''SS&&``~~jj jj770/uu\\4433xxOO<<@?bbdd2243VV!!..11cc((XX77  UU55LLJJ::ggVU[\""hhIHcdss  NN::JK?>aa::ZZ99 HGz{>?ppss))LLiistkkttYYjj-,! ??;:ooXXggtt//IH[[vw::  ==vvstFF)) lm gg``>?01&&nn_^``mm45%%vu::FE&&'&ee 44^^{{MM76xx[[XXwwccVUCClkPPRR))yy@@zzRRmlFF-.GGKJ:;rqyyDD44{|::mm10((EEBBuu55ONzzNNYY>=lkhh|}  ZZvv[Z8789]^::67rqppccTTrrDC  MM88]]"#QQ~~43[[BBEE 00uvcc0000jj,,]]RRxx''21#$ttEEjj{{@@SS66effevv99bbHH55hhff;;rqtt77DD`a&&qqLLZZ''LLOO  87FF''yyAAyy55$$QQ(($$$$FF  [[~~ ))__``..23JIGGcc __]]$$77''  NN99qqghTT==21PP89KKSS&&[[99''""PPSS~ww;;``**}}zz\\>>MLfgpp))iioo``YXSRpp33>> --MM|}^]))^^QR}}{{MM  99VV~~?@?>oo&'66,,>>  ZZ//66==;;))CDggcchg::jikjwwIHUT"" ww))utiiIJ>?==xx..99++hgqq*)ba[[QR-,;;ff<=]],,[[()zzbbQQ__xxQQddMMPQ77}~rsaa  ,,ZZ!!$#nn++56DDee..PO||FGrr@@ssFF??}} 44jj22jjjiAAaaMM|{|{11oopo\\kk,,    ## DEVVGG__++CCNN[[XW//jiAAHHhhVV33__>>ss   33||SSXXii::,,OO~~77  YYmm--++||kkNN@@66hhAAnn77}}ssRR00\\>>``!!ppWWBBVV**IIJJ$$EEZZ\\>>;;GGRRmmJJww"" ttjj;;aa55::44NNSSssQQJJ77++''((>> tt99yy33[[ ##;;++SSDD aa@@00ggZZ((~~::{{AAmmww$$]]77mmnn77YYYY^^<>ZZ,,  mm7766''UU~~gg^^DDhhHHJJeeaaSS99eett$$AAjj44&&uuqqiiaaYY>>jj00..##qq!!''rrTT  88MM44==WW%%$$**MMQQHH%%22``ww FF@@@@eeEEHHXX33RR99MMxx``rraa kk44gg))FFNN[[ooYY3366iiAAMM@@ggff;;44GGTT}}aa  EEPP++''__NN]]rr--22!! xx  zz88YYqq66GG<<\\99YYzzGG    ||xx\\ff``99== ttJJ88  ll22..oo]]EEKKGGJJgg __//tt##@@zz}}ff!!993366RRVVzz||""QQ``''yyGG77YYffyyJJ__//00OOgg\\QQ --VVii PPCCZZAA88TT%%6600rr66 CCVVhh$$mm##00zzIIHH||mmhh33rrAAyy^^""MMQQ22CCyy++%%[[nnii  99$$RRvvBBJJ99WWMM--]]33qqqqii ==88bbmmQQGGllSS~~cc  ff]]  RRTT ZZyyll((__mm<<SS99__&&ggxxtt** KKyy,,!!``\\  ]]88--22QQFF**^^{{__\\qq##~~XX{{mmII@@QQ99##KKMM\\[[,,uu__tt==**ffFF66kkppCC88TTppffxxPP!!RRZZ~~ddRRzzll>>zz$$RRqq  ==RR22FF77WW@@++$$ssff22}}mm||KKHHCCBBUU8822eekk~~<< IIVVxxDD!!llDDddFFii  CCDD;;&&"" VV??(($$LLEE__DDsswwXX66;;eeCCCC__{{mm55uu**((>>II||,,::ooWW==zzWW aaDD==&&JJNNVVYY[[44NNuuRR""SS||!!NN--uu99==""55((}}QQHH  OO &&]][[mm\\ffNN~~uubbyy33~~ww~~00ZZBB6622ggoo ee>>77 aa((MM99ssQQBBAASSZZjj  SSpp  !!ttYY66WW ii""RR&&ww??ZZ&&,,EE++XX))<<XXMMQQ@@44WW22ZZ\\LLFF77''--&&**FF<<::((**HHppyy[[ 3388 HH11..ST<<KKKK|| ''{{..GHnnQPYYpqZZ  ppAB88??bb// pp56 pq<<89-.z{-.hhvu`aUV  ;;YY??GG;;xyMM  XX[[BBaaHHUV&$ll;;::ba77cc -,#"HG~~}ml32ed98BAut1/CB"!|z65EDlkrqLK:9[ZvtOM][ ^\A@  31ihGFedsrCC>=HG\[`_A@><43TS.-86edIHpp00(($#::``us66NNggUU  MM ZZvv>>\\IIFFHH<<YWC@ECFEXVqp>;NM;8{yRPQO&$_] ><@=zxkjsqB@TRkhzxcb;8ba53cbkj$">=?=zy$#ED..76:9a`! |{SR43!!-,EEjj66BBUUjiOOUU::YX.-DE;:yy}}XX!!%%!!XY||MLSR\\**IIqqxx44982121}|ed75IH@?YX@@ooMMhg:9A@'&IHutsr``qq55OOEERR%%edTTnmjk>=00nn  NNww LL``ii./WWABuuqqHHff   44ww``GG==<>NNttXX[[oo::FF__$$rrAA//mmwwCCMMdd[[ss`` %%~~UU .. LLyy XXss--66!!aaSSxx66dd||  @@]]ppVWaa##PP YYww ss  PPYYUUdeccPP++DD'(OO99VV<<OP22  ppeeYY\\66PP""]^[\}~<<RRLL|}MN22qrvvHH rrFFPQ55MMeeyykkYY$$44((EEzz  ZZ&&  ::FFZZBB^])*&&qp]\ee}}*)ff(';<==vu??IIJJ`_nnGF+*xx{z``10ihuuTT_^ihvuSSlk65nm  b`'&DCKJ.-POkj43,+>=XXWW KJvulk*)55cb?>RQNM\[-+ %$  nlQP-,CB)(#"a`MLNNFE+*32dcLK+)ihJHutNL:7<;wuONkj@?hg;:ml_^rq/-BASQ SQ\[MKvt_^CAmk#"TS ED97;9('YXSR98hgdb&%}\\jjIH?>&%=<A@##QPllnmca  yxonssjj~~=<IH:9 }{LLXW&&jj``}}LL$$~~!!??!!,,))  kkhh))YYeeXXff  VVYY44UUXXTTbb @@@@XX)) %%@@ 99XXaa00!!FF!!KK>>AAii\\AA __''GGwwnnAA77 NN,,NN**rr  MMSSJJll;;FFrrMMIIHH{{PP==vvUU``WW..;;ppoo>>{{}}VVXX&&QQ]]{{FF"" 22wwYY&&\\CC((EEvvuu__<<OOnn}} PPggttMM''SSkk##^^SSpp~~++&&89qq--  00--77 hhFF%%^^//JJAAggNN77lk__##FFBBnnxyxx./--!!YZ__--TTuuffss<?FEFF__qq#$qqRR..$%;<``JIaa55eeFFtt[[CCUU<<NN__<;44moll<=#$aaON6755$#10^]QR^]JKyzon{|DCts""ppbb>=xxuvnorsNMfeff?@VU yx89HG||""66BB1177"#BB!ab.-vvLM  UU[[66<<  ]]\\??rq]^wv^^78NN88dd%%JI [[..66bb  99**%%VV66%%&%iicdPQvv10**{zZ[22vv##UUGG&&z{22,,jjnnjk ppNNnnRSjjopDC22::GG BBLL''VV}}))&& %%99aa]]II33yynn33))??NN))EENN ::::gg::''mmYY**kk33RRvv--pp""kk))__II DDjjllyy@@IIyy;;<<yy>>NNBBwwddmm&&{{55ppZZfftt{{AA88ff//XX  qq,,55^^hhjj8877++))ggqq--KKEEffTTmm99SSUU UU  II77OO77ppww}}44gg]]EE {{HH==yy99TT  UU''II<<!![[ll++++wwhhaa99DDII}}pp@@;;~~77 SS``AA  zzEE??SS!!AANNGGtt))**<<HH::{{44;;VVZZ""""//>>44ii  NNEE    ggMMttddrrBBSSCC//99TT]]""xx PP@@//qqzz zzAAMM``IIWWmmUU  cc++--UU gg44yyqq>>PP&&xx//XXrr'',,!!BBWW ^^  ww==22aa}}99ee--rrAA rrPPQQQQ33  ggPP@@AASS77kk__~~XX~~mmxx::wwcc//SS,,``;;))vvzz``VVMMuunnttHHaa$$^^tt>>yy~~FF''pp::iiaa22,,%%__cchhaaUUaaKKWW--iiccLLeepp++..99uu''UU--ccwwyyXX99ll !!==XXHHuuII{{55ZZ DD^^ ssFFyyoo//oo__``00wwnnjitt((::::PPWW<<pp==\\}}ppgg  ccWWzzmleeuu!!poFG??eede"";<:;aasufg[\BBwwppvvLLiiPR34  33mn>?~GHPQ|} wx??77``55dd))BAih~gffgooNNihtsut/. 97QO]\MLutus}|XW  }|!trYXML]\a`((43MK##<<ML;:kjbb[\qp79"!)+$#$$acLL"!cc`b{}vwFF46]_[^"#Z[DENNKJil``ffdg]]qr?>NO  "$$VU^]II34ZZ pnpp+(((OM((MKXV?<**XVLJ mk/.-+nnoldc?=]]SQ`_76  {yHG{ymndf34OO"#jl65UUvxKL[\+,gh^^WWBB8:mn<=##LLDDmmaa@@qpYYHG)+LI+*tt0/wxQQ,, 88{{kknmpqll;<ed<;""bbefwx56GH_`|}GHQR~HItuvwffab /0KLwx^_DELM-.@@bcLMOQ=>~'(MN%'EFRTXYz|$%NPwxdeef}~lmac _`ps=>WX_`df-.NOXYuw~ ^_AB45cdpqMN""DExy~_a()..lmwxTT>?&(>?nogiCD}yzIIvwKKpowxPQ&&ST&&EE ((??HH89#$)*RSrrij./aaWWRRTU!"__wx ]^ee BBSS]^Z[;; nnxy+,pp[[,+)*xyiibbA@yy,,<<ww66$$OO-,yy67^^yz./YYgg SScd@@##__KK))@@wx89.-deAAGGSSWXuv  LIST*INFOIENG IGNRBluesICRD2005gajim-gajim-1.1.3/gajim/data/sounds/connected.wav000066400000000000000000013671641345766322700217250ustar00rootroot00000000000000RIFFlWAVEfmt Ddata %",,96JE^YtoL:R  Ov  (  G ? b fx {iO1 t]D7g ? qA0 !!!vQ"" "0 "H #_ $#p 0#z 5# 5# 2#| )#w &#d #U #> "& " "]""q!&!6! 3p  t)FQr"o+[> 4I#[Mzchq9EOQLE92*Qou K:  [  Ny   ;*  `P p{xJyw(uqvltr~ 4s  s u I (  H  5 _N  4y`)Y|@&dC Cwx5Jg|$W@gz-5{IX,l~@_ {]mX;@f'x&T6/:;q9B5)o"m*u?gG>|4ZBN`c"kOzEhCaH^Tfhp||) tlIGmk b5 KYG'{#aUM'j!n^`nn/m3g:  ) 2 ?m ~ 8j  j   \q f ' # q  )z [ ~fT]6+S}? *4L/ b-?Sn;\M23*"j~ u \ [  6 K  } SX>t#; {p!Yq:J~yX8H0}6yH :Z  t Q h , kc  lD oV>eE' ukipk}2bv,wdMH/0    ?i}JDq$Ee{J Z=+Iei,Od Ag *Mw;a'Ieiv {v;b?VWmF/1r 9s{Dp _ l ,G  * H  z <X+9!3Y  U    : 1 XC '7 c < ?vvEL2mOF,odG!$Sj6jE'|2NO"W \hEb.i!{^.@O]rH 1*Uz!#{e)44-Wns6K&[|8~[g84dT +VP/6a4$LMou5F`8/:zO_A mE.Sog]z\cgiaJT)=5-$@s_@l88? U o \Us$ ~XegucI2vKJ<QCz  k 6 e1   I    .*KqBK* 1xODetq"/:Fq?*O]VX$>~JlWcA;+U k  G L   e i ~I9 1 } D    l 3   t * 5 YH !i & ^<[8zS1oH-]u$9jZB. Hu(=`t8=^#|fOR4(M lLx)+L^ c?9O^]0z-X:L1p h<<j4klP3D qRL,L 3[c fIu{1^/Rf2Q.Axsuqqu8uu?sniyd_)dlzUd/nJ\Q3NI+>'vB+$i Z02Oye] ma 6m v z rY[.N(Z>y0a`[2T%N'?E) ( Y |9   >   v  .k J jme:F`i,m#:#SEjc R\,zekARC:i.D  } J ^  > J   P |  n  dV ' b  k [ u   c # / Ug 0 %f q[PG6$:%ph9s)i7g 3yM F{q_vG+)TyEmC |R- \7z Z7d$v:Qm%W#D}j] :CoW= Nj6*cf5K2o O0qlU 5@r A!:boz*4ZwS ? OY,n5F/LX0J>\8B0 ! a1L5}|KtHF1S c " rKJ$f#oEc3_41/sQ!#@L2GER$& s  / Ck Y p/   }  k  H$"GW )0I=L_gx90<FWxaaZ.F-4-sL!v{^o@k \  ~G M ,  x D  g  R} Q F$  ?  By L H  W  gH  { } )S ) V (kt``G)T H`1FXwaR[H'A>><k9>2 (i+s`GRb=Z:rT/ b8 x?e'{5h-e _P5 ~3eEB<V/Y 4|uaF-X>|PzuxY:5<_Gk#9YX~eg1u|o hheccr`^8YVTDTV ^|m'I^6NXQ ]]u2ku`Rx Q+ 2 3 9cmdvjW@~gL>:6QN5s.bgf>?n8 d  - Cw ^ wJ  $   P   -^a/}7d'@^={K5 ]rwqtQe.YUQ|aJH-C : )  W  -  g  LX . 6  (  !h @ $  -  7h < G [ s} _ F "3  O (nyhV1 fbr R4b w/r< }NzW0E]@8}A tY];=c-[1s0ci*&}cF"PjGj' h PmO01rUmMA/$`7n B/*Hcz#3Y;[~>DI0hlST?.N"D* [xF 41VQ{k45AQc)nPHYVWg`M I a c D B# (?JzD~zX7!eaZTr` xI{&B nDk\.y s 9 R7 h y h   n ~ h H& P s   F   { 3 [/Jfu i6JRNuTG7@ :  5  3p Z -D +    k v V P 3  6   | Y 4     z W 4  $ 4 L cz l ] N < F)  $o~[k8nlo>~mIY@"[,iCW\xbIb.)yqY@8 W^Z4`k5Vb6v$y hw eTP@,5~"hf F*N.h9x2KfYMW 4qO&mTQM5zTP+/ f@t:wm!zI4hRvJ&x+UCLYZE'U # Su C q'(}<KJ~{&Rpvo5I+FRxT3 #;< O ^ kW p p fT W @  3 V q \    [    = 7 S Wk   K     ,  7  5 s 1\ D ,+  (  $     q ` I j 5  R  :   j J '  q  j  hf M k4  v  . M pp X ? 8!  wht`iN@6l1..m...r)!" DT~\6f6ifR-<&q0yiE= e|)aF-t7Fk?DxGjv~elO>/WF3{ kPc7#D~Y-C4_zvg k1E[2wXVJ +a\u&no,Cy[*yHQx5ny= r1Y7[#\1 x\MNb6*\Feq+L=(k3%aD_$o1! P k j n v4XuQi~NfyoOb?bBYI=A#N65Z zGK(,;~JW'^{^Y O] ; #  4 Z sz :    ?   m% "> T o 7   &  [  ~                w f S ~ t 9 h Y G 4   v  \  F  5z h $\ R M H F F F F C A $9 / 1#  C Z x s 9b S mF < : P7 : < D? D F HF A < K0 ! P`jLC1a2xrIY>y=wFRn8]7Y m/eLd.0`6>3,yr cUkH >2V*#9w&*X4AP8ar| kd,jJh4L\ZXJvEQd(|hWcHA@7-&%wq z/C^4x&QGdj5du$*c8K`o Z_  ( X  [z\M'aO.$!xZ/9'o!]TDj#"l9DfT K  4iEWaTfc\8M{7! K p k 2   x 8  4 hM f   *  z   I/ > hG O |O O L G @ ; 4 / ' % x" % o% ' a* * N ' ' 5 "     n  S  9  !| r k c a rc f fh m `r u ^r p bk a gU C u2   . O z  I 1 ~ * - u 5] D ) @ W Fq `N;l':To"EMPp?{ DqeS)8 h#FoVV9[]fVM7#J5x^(>7FW$frlYPS%Emb~:;{nI-*xrB` `d= &hQB2" ,g'Vp%DJFM/h&7TR83 WY  6 assC,QB_/5 Jtks^V;.GF0#Wfz[ 7dJYfFmpp"feR;Itf- v$ 3< U n c   z #  k4 P c ;w  V  h  n  t  o  k  b  V  E 0  h I  )  z u r gr u Qz  >  0  $   | p a *P A 74 ( L  h     K# * / "2 2 h- (  _ b  l u _ |K /7 &  M IlvLG)cR4 iU5#lK?YwCeVH_9%nv"wxW$9tcN3w !2^FWfKu810 H:rV]>-sDH lj= b#q[rG8`*XPC,'1QVtW5n}1#\7m6k!J9j l p !* Wk (.=gp%|y bo:Q zI[NfF67{yG+s[?Kp7r %1;tRftG~|dmW>M|a(.Gsb3~^ r0 N n _   $  C  R  X ( X/ 7 Y< C RM W Ga h 8r z % } [ 9 |  w u u hw z K  0     x  g [ S Q R | \w r lp p u z  * P ~  T u >f U A =-   E T  k } l X GD +  Ob8\ /R P!W!],v:`tE.,T n.w_6C(3'pWB,2wFWaimz]W_ J|q$3sL FEY\&"mqdL)(|qnyaoeR^Y8TT!T^hv NH=li A{u!TCtt  B ~QN P  M A r 8c X?MU;6\bC_3(|E`n']{]Ak\2MJawY)l|c&C\a4+Wwq0^1QthP }& ? U %i } 2  =  =  9  0  &  ( 2 < n C H N M P , U Z  ^ u c k Qr z /     b  H  2    | }    7 U ~  E & n  u of W H y9 **  ? ]  p JN +  c2`3U+yH}Qu$<tDL* t,Md|pasRC/y" qcM5}"j&;eH]D BP|@^'_m+ ]}[:^QI>,~vqogotY~c+|=,l@2d5f(~Y"'[Q$ nF  pe  , .LlZ~K`*8t [j\VFw(;LZ .8{!Df:x7w#G*-(U Cwd5"JVmQ ;m`f 8$ ? Y] x r        ( 7 C P v\ f au  K . | U  3     b, 6 E@ E *J O O Q Q vO O iL L ^L O YQ V W[ c `j o mw | + ~ Qw m ~` T E P6 '  8 3 @ Wz f P {4 0 ` i A k 2bs3K!m6e?K =cC"e~2DwIpf_BUKA592{/-*^-29DCP_'poYF*C8^|/0DxD&dg(hW*jf-Bi:Bc@)yjYL=t4*S"0 *~8Jc#^UL}GK}.8Ct>OYq 3P 2V  MW g)7p(^qBF.o0SH2o^+L/+V]}&f7*Pmds;~ xNiR7Awi 89`QB<gI ,< _ ^     ! ( .> R 6f w :  5  .     c / C @ O ! ` o ~ o  P  3     s  ` L ? 3 - + 0  >  P  i  J   ] r Lc T E R4 "  i  D h C v 6 zx AK  pA`,ObB"M {3oT9O cpnc|L.m K,o R4Jc<|)r'Q}ksI$=2mm*"ek0+q [\+o;qV=*fE"gA'0 *TLq)h. _:\-_jn*pa|[. f D S P <mh)x2pR(w'`_7X fX#&G2b;`oG5V\s%k; NM`8 "Rt=$HIok o0 S x M  w  % &F a ;z  J  P  S  Q  J/ @ : Q c $ t  _  @   ' 1 s8 ? YD I @L L +N Q S X ] }b j qq x k f g o  $ { Gn ` oQ B 5 <'  x  `  Y  ih L /  B vw 6M # z > n ? a-q;]:Ez2PhO9g t u|lphfVfkp8wvM#`;"1zCTj]@=,jz!Rq@:8h6AeYuy5W;,T.yxM "5aDS],bob]S?D.AT*"\C=g7 N+ S z >  w  < 8^  V  h  z  1 E V j ~   x h  P ' = 7 S g {   r  Z  B  -     v  l  c# + a2 : e< ? o< : 5 + ! $  D o  < x  v ]g S ? W)  a  r :L " t 4 u F  F  K k 7g)]8`9P|jV[E1\ U? ].f 74EnYhw@|X6=eyf( _] He|14mf!&_n25#ymB1_0kYoM pcS,G5`}vMb.sh9Gz",ek7.]Fv )0 ]  /  u * R Fz  l   ' C -^ w :  E  J I  , ? G ` 4 x #   j ( R5 ? :I P 'W _ d i p xu  j _ Y T R X c r  ; x ei Z K 4< - q  Y R e ZB  x 3 | O o 1 \ M*  zK I L oLw), CNtOeVHH9*2 vO!T / CYRrQ#,ZD]{6tFZxNWO G^3Aq}7?}ae6 g!kMK4X+mE"zp7qW|+4jKfNv}5znm#ecb 6k ~ + + < C[TNv7+ m/,*{A)U2 hJg gA$1Af.}a;"/9=V@=6&'l7zT6%tPNQ < i t "  w F r X    9 E[ | _  v   ) B ] x     7 u S i b  O  <  &     x i [*7SCMLYaJkpKuuQup^kamWM>2#8c 0 n  z Yd K 0 O Z X x, 3 mr 1@ Ok 2 } Z< -o'eD@' MNG~rj4`VxLE>S611"11U6>JVeJyx=m.G4`{i=wAkZ*F^@ E~J3is2VxMj1=uBM(\"Vu&nd_f]]9]af{nu\@10C;pNd@yy) dRm] OP M . ~T +e x A c"s~M2t7,95?APEm3,{G5fVV%AWFm*rL$lr<T2 HX$8qt6 F x e   z9 #h  q   J@ h t   (  DB ` Y  f n  s 7 U r s h ]  Q#@4E-Tamw pdYPJH KS ^r=era4O<q( [  W} Z 2 a  :V ' t 6 V W #p 2 kl A$ EeWG,ZSB%~yatrt3ttcw|)V~?i'?'XvUN?f%dArF ;=t>!]Px_56v;gh <] f dN:D( }P"`5+~?UgpZY4bhsG 8swc+iI5 6 ~( % q ) $ 2 >73`{Z2r<"yB&zS& zk -mO?}l"D{k+&u(a4>CGFFA&9n-H\X+"`X K  ^  % W /   . C qr   @  k? g    3  EA d S X [  %W C \P uE6(  .;uJVico^{XQRU]j|v j[&O@I1 t A}pgR/ c  pk #?  I { G  E h * c 2 k % } UN 0 emlQ6iZ@|PEq,Rx ,=0QeV}?!Ios;#uTS==o6 B{A5bx RQ6k7$skZ7t3]*e8pExAimn(x^~Jxf={M.<  ^u m [ l  qk 2fTW0q\)j7gJdb #\J>o=0qJ2VPiWRB+x WfF/!wGq= K  Q  < r <   IE t  =  |, V  C  i - U }  / <  >I a O  P  I "B8L9^o-vm)3g:?eDDcGDf?:q3)~ <` qW[@%5~$zyO%% : k : _  b [' o z, F  \  nx K) (3/v]|D!,dBwDn,S v" .:-GSN`on%Fn?f.^O+g;jL9+_<HNv^4@z>.{pDievt`N2=1$c4g7)6kDX=oyDquprRobBK,=} vMX > 6 / ='  Z jC:`Wx\/SJ Iq77fQ,S)V}o) :$5F>U_f=kkk0dZN<i$M{)Qq" F  J  M  K  9 gm   l 5 g R   ## S Q  v  4^ 2  B  J 8 VM q N IC9$80I]$n ~~%>Zsb~Q?)@uS~[6BE^/Z  _ :( yv =8  m f% 4  F iU I (XMj5S?s, Gy<b ".==I^Xg|s (Ge:]:`4 fP'$Y`HGx?WGea@T$qn< _ObB$Q i-Y'RQ&"Bg{ldU^Q>z?&1qm8E}!  _ w  ^e V v D 8 -a q%8DHbE#;J+xxFU~JOv9,NlXp*65-|jvS,V7 w C  W  R  Y  8  8 Bn   4 < sn   =9eh 2 E oB  Q  Z  &] ?Z[qWRK B!5;FU5an.x*&)-zu5nfB\RTF:k+ @o bAB$qV*r fvI*"y${|.eQCF4* m0U",~9HG[te"NQ<-&asRM%Qe$n?  d  y t b 6 I b((^Rsv!u:jf 4[qAFWQ1!`O{)?AVj{av+-q]'B~$"t hd 9  M  a &" e  _ $ ` { )  ~A %x  f T=l%T% D  [ ) Lo l z    0Haz{wpn%,m/1l1/o,(r#} 'AbkP2O&iZ 0]ycGz0p4 b !x 5 m 6`  y m* C  2 + dDv& Y-_vl e`H][i]`els4}Ng~30IJa^x%$MuHk%Q+]G2xsRb cCw/J_goF81|T'1~+AY|urvpm7rwY X19`n$[W;F_A1 ToI ? ( H |  h` 1? b|-@YQ$MXC(.m{IZ#mWEHjV&\'%3BLOVX[lXQ!D8$/6r: J  4   W h   _= }   ;< x  ; /k(gO1\ N x  )  > 5 UM u U [\#>\WmZYTRQOSV^ixy4fOU9~HuP!(g v]Gct;}5Ai + p & { E ? J W - H 7 xXy<! RGl <Vo"4 D#:VUpew(M.pJk 4^$OQU-f81T<QZ]Q7o>meuWk>&w,DZ|@2vPpJ+ L}\,;e}]P (p[Y3  _ ^  = J  } ~ HK`Og" _dOC"; {U\> ArlE>^|d9 o  :  _w3rQD ,  M   MJ   3 g} &  S Q  a^ \[= vBx> d : d   *  9 C cD NTU.EU[lV~WUVY]ckx{l]L*8$H k.rMc(>|P)!{'N6^WJQ i  o ;{ ' | % T -p  U d,K5^!Dg(?Qbq~-D]u*9 *IJk[r@h:`Q#U-f.vRkEx+FS_VCW8-5miC>y,Sj#-uY )Yl ^ F  {" D e  |2 L T c\1b~WbEK4'o 3nkQ<h5q4ORey2yKJr[oC'.   H  m >T   Q l 0 A  j " h98{7:$v`!U/ Z   > j '  >  )P Jj[ci n0q?KtU_xdi}lnnnlgbZP%F:5.Iel>GRh'S ?d`5Rp@1o q.<qoN@J   eU +* a` 6& t<KB&:w`-|K>c16$y+_~o]>dJ5#  /;eEJGMMJC9\,)X   w| R *9   N n 8 S   @Hh.vx#DqC[2# Ya     E@ o Z  n )I g&. 7?#(G((O(&]!gw0OgIr+5gqG@(Y#v!x{:,sJ.}T<kL p  {j L  Q * \ <_ $Jnzpi.aZCUPUNKbKNmSZvan~z -Hc )3C8[UiL{6\F}$^ YAB7~B3v`9W W}@N$.(y|]G"3y""x(7Q"3O{lE{3bK~4mE q`76h(8 7s C `  0y = n CU ^i[M9N)<!c'b |5dtlc#CX_zMC3rO'b k M4 -  c  ' i : D   [MER+isqAc>yE } " V B  j  D l  5 G4\Mdkw{ &0=N`uwaH8-[dK=`V"M|>N`<d>x1:7 S - s  c ;Q  N rYvC -*H_t"*0377%<:Tk>AIQ/L[ok} $Q{>a2d!T4k/xL!q=x67|a!Jn:$q_`=PGB|t?oooJt`J3[x?Dxh)\K"ju>X qfA ( p [ 6 . N p  JW 'T Lpe:`_i^4`r`\S\Y 3ZZ}Y[\(a>R`dr__m&  Ez y4  3 ?;se$==Ct}4G\ ] d %!e!!b"!U#$"C$l",%" &"&#'#u(0#')0#)$#X*#*"C+"+E"+!9,!f, !, , ,v,,6,r,O,:(,+++OZ++**1.*d))%)(r(:(d'_'' & x&B B&r & % % %E%~e%@%%.$o$$F$<$##A#q""g"r"!+~!/! O 4 Pl TLKKtTWfv~5rcU)7zFl.mm"r<!S b j 5p p oQj f]~T;E:+z:}D{T`H0zHnK09Pq߀ނތVݙܱ&{ 08\،9x|qcIZiӫFj+5 ҩ҆`:&zScԒ&)m֨fjٴ$څ}R'AE  V ާ uy~QOHO) j!["{U#U$V%S&I'2(%);)As*7+++;,n, ,,~-3L-v---x-f.^?.X_.Uv.O.E.5 z. g. D. .g - - V-O,,J,+|+R+*:*Q)T)(w^(1'P'&I.&%$P$# "}@"!I  ]YqR= * Z W!!"t"$"G#j7#d#####2 #S #r # # #$#$7$!H$=Y$[f$yk$k$f$U$<$$E#m#}#:#" "7`"b"!o!! =n o S G~ In h=OSMOt5~OphG=.>m oFG` "-a.BLL?f, bc.N5^ 5 {`    A#kBJK=lx>[IUk%z yY5.{*gimEe3J[eggse`nVLB3"dq!t^2BH\!9[   @ /  Wb   UAo?}~iM/}.;+WpA h )  ! d    %r F ab zI*g3a&uSO%w2N E3Z;y(C_ q66XCD;_*Q  ` e  F I ) y ~4__BG"s`ES1'=%%5'*6*'@ R l6MjAgZba`Y<|+CB6v5b]etgM2Rew6jPkM\>CYsK/ E 3nNXS1?! l+ !5 b p 7 w$  d *Y L{ R:d@v x_0GN.x(m`>={a3/G X i d 0 & ig 3  ^ c g,  D }P  %} JK o =b3nyJc8tZ++PvvI>gk8 p@;ei2S   c %g)j)|`YC%s#}p,HG_+KOb!kL2`W#FNivXBI=. Z3oYeGG;,8@Tq S2 z%Rt =6c<<.h%o22 $3@88:B8Ss;7:sy`e!li>o.o0f i  O/   BG    ' ? N S S Q L G B ? ? B D G  I $ G A ? U 3 _  _  P 5 [ " q 6 c    oS ` YWW=TM>^"fFXG;Oy _cJL4B8I.X-E5SLoEt/hc((sW: gg8y 1mc4>NuWV># 9\vgBZSKFBDFFITIIFDi?-:5.}+B) +5BjX6qY!4Aa|ufX N,FW?<< ^`F`8 <Hk|49bv&EvR&FZ&\WDI5O! M ?  3  -% D Z i s nt\:Y5+ qy Cz4}Ti3?`s `@OHA351 4>)SJqa a - B a  ^ ?  V,|F%B0DD6o, Mp4>u])WtO,= y.jhT!;`# #g9q 4}\~:n.Oloܔ5F}-)ڐeBDش!cؑ9hE׹3״A/hJ kحXظ.oo'ڝsYR۠Ji2NZޓ^a)o[2.jD- u c S ? ( |Y;PT"[!OK~R+6@3B f G !O!!v!Z 1"M ~"J "S #_ Z#h#o#n$a/$EH$R$R$H$F2$$###KK##"G"Q" "i!t!!v d    E!!!1"f{"".#u##C7$$%=c%% &*I&v{&&&E&&&&=&ws& g& b& b&Q g& q& &&1&j&&&n&YD&&%~%X'%$p$!$g#U#"F"V""6!e!!A W c}2 ky:^M^D}E8OfA)oL(Qn   e' M p r%R $;RUdvc'|H 'u2i?aLW[PkF}:+ 4ZDSs Waޤ= [۔R+Dي#%|FJֿ=$Py1rԙ.aCa-#Ԛ 8%/ԇ>2Ocԡu]ԩt B=~$֡ւ dJ(1e>۸ۚ^ySj-k޹ߖ ,u V = x& aTU\ellgc3O.cOU,ogdiw@l}k 1!!!"ZI"*~"""#)#~I#od#i }#a #Y #L #7 ####p#FN#&#"Q""@"W!!T! K F }=.>~<?$W h  !2!!l"M"P##X$r$$Y$1%[%Iy%%%2%} % % %Y % % %5 %%%%_%%%E%%w%5C%%$/$7$#1#F#"?"E"!V!/! a L"yqWY&E:H:NBWAuT.Y8m S ' R =} YBg\!v80QrJ*UmcacDmtzVU> BKqw.}P&:3@@en.epV@LrX/zpޭ=/gX2n~)-kMh|%L)@wfTnA!*o &  X( & "  ) I K  ; _ax&)Uw f\t56lb4 ud   Q)  O  w : X s. Ie  $!!8 MavvI m/,>^Rpi{[ 9D'E<>_-.hY & < lL  'd WwA0jJ.fe&6Ip> T h |  1 V t     | ^ >     f 4    X  ~]X,6h;A:z.\<~%x!Dqjm;luo:|/I U;QNYm9fzP<(ez];A)P_t)O >s0`R_(2K[d+xyO%pR7  2W| 6GVco{ 2MhIx/`As=}/^PM8v{BU4T wDV-m>ib50y9@ {d  % 2   S  n F h " 2k k |c 5@h8v?hKpwb&}kP\51{ NgD!-Wz^ A  7  /} ; E HY C 7 %*  X P%i50=BY CIWQI[qgt  !1.>JFk?.%g _ J w <* ?3T9 |89(}sAIg5 K `H@  J JkR7GA P6+;W"f(SFhIݐܽ[ Qۅڹb Dvn1٘~!JU؋\׭b!ׄKװCywIشB$ٛUڕ4ۨ54UGrdފ"N:Ef bzcXXRZ[`p ] W G@ 0 N P \uhg!su%J.a`, Z  | -n |f f"jyq|"lw7]P7Z ZR?X& ~3`9 5 !""tD#6#M$$RE%%)&2&'Sf''e (z(d( )_G){)Q));)) ***T*!*!*x * *, * * )9 ) ))Gl)8)(W(f((o'd'-'&N&L%%'%x$W$G#x##""xy! m\ h+pMX*RT$=gPcs0(bQ  8 ^ T   O+Ie_-{Q#,3 BRbqt`J4*AXofP<-#Bj#-7A,HePUW+Ztachdp|ڋ~١غO2/^0֒E:u{Թd5uҸXH)ҜOѲъxyy8bxr(wiӌ!hhQq֖\%r'ٴv/M۔:SyR߷] f~OEE I Z r x K  3 drv%*QLznwA[\qd I p  } wo d;WTJf;t&| ~wkT9a6x<T ig  oC!!]"Y"i##h$$8[%%CB&&>'s'+' (k(~((Z)E)0h)))c) )- ) ) )V ) ) )x ))=))v)kO) )8(( p(t*('P'?'.&&3&%m%y%$p($#p:#"x;"!*!  4q]6'De9UVU`Ko DoD  G' H i {J/JI`yk7 j9NP6l 2WjQ6Av#b1${%90}158I89p2&+6.6*BcY&2G8 S 4 J 9 3 Z{ U['mc#B\g]$N9hB"0;_zh1WJ<2*v(*q/9H\u?.BvHwN7u5|iWUH#A<<>CkMNW2fryeV QEQr[o$l 7bik/cKfI<"`YX8#+"\g_:xr6j~gx:r*k,1~$ lD x  & _  - F 9\ op    I     . P n m P -   K    g )   `s Z ?  <N~QVWRUn2Xqc.xV+ rQ% ?H X _(o l0D=MjVaE4'5Y7"*1b9BJTN^jwJ W8Vnq8`.m@(7FZnnH#}bG..Li0_;~#]7J cb||68NVvxYB[x}4yY V3V-pbd/mf3{fiI |  6m   =N  a ] c  b A iw    Y =  h : ~n  v  P - D hS _ f Qi i a 0Z vS F : :( u    * H ^e p: |   c " y m ^R J 4 g  lK`GC}TJAw 7Gbh|%Uv"\\7 7t}>"  oe  " u % 0 F1y;!q OW9a9f?iS_:$ 6| V7 peco(L a3LI_>s߇AߘާP޴ݽq9+ 7FPkى٩`1 /Rrؒز@gؑؾ;jSىiAڄrYOܣIBݑ_:ߐ>XLE nd+;umg]P;w"ok pz ~ f V  @L v ?  -5T jvu | :| x s ?mji%fjjt}3qP~gFx#2 * -!(L"!"#H$$%&&i2'?'/(( )qh)3)*]*Y* *!+\W+++?++o,,#,##, ,? , +Q + +[ + d+^ 2+ *b *}*]:*)W)T)M((I>('En'&@& &D%%Lz$#VZ#"i."! Z 7qd s8['|+*lD#]t37iM + X d < $Jn}X5=^}veTB14"Pkm2RP9n 9\s&\XF-#]ߏxddSDM:0)S aQ[w P&8lN,iчѪ`@#%MѶ/'o@ѵcGљ.BlқUDӵӁR[/I:Hu%Y}b-۬Eyb/߯G{uT;M.+13E_,0 4 ] ' g  %2;JgDA ;?s) z;bH   O  Q5IXdkjnLi&_P<$U  r!"Q"_##$M%%'&Z&''D'^(~( )[)6))M*U*Z**c**^+ +W ++ 5+L :+ 5+C 0+ #+4 + *& ***Z*&*))h) )(((( 's''&0B&%Oc%$xp$#n#B"`"~! C! k }qB$RJJ>(oD2nb1K}` ;: b Z"0Ef]5$B_~qT6*Ief>(MksD!&VlS58q< ~rhQ&;'T4$) > i/BVUm ڈ٨JN؂شf&Ma6آ%*rغ# 4]Rطy{)Rt9ڲx.ڭ0+۩%Hܡ ݜqݙUޝY%߰B0n M DKJ{5gwc"|~h} N : / ) ) +} , ,n ) %Mqil:Mz4#Wu R * 8 O ] jYqvv}o+eXyG1]'rNHdhHV .IPv,ME6 ~ W  B }`    c P  | c  !b 6! T!m!e!!!m!!!w!(!!!=j!R!1!Y!  | 7W ! k(]`oYV!P?LcM)A)Mkd5#M`SYM h: /  b I ,nL )~h9kV(qM8 Lb.[a/-xpaF]wsAbSG?5u00s38BN_Cs5DDpq14k\9)q n 2-EamG1UT{ gdWsTMc6qynhU6(eT?-}8F[t(3[0 z  7 k   C ue o x   $ @. 3 X3 1 `)  Q  +   R  m qO , 8   r p JF   {  0 ] +  a  ` ." `   h" 9e   - p P # (^vN)6Yyy[="5Qi|hWH9*lUu=i$\PF<0{&Q% W  `_ =  D ^` 9  k  qd D Ll. Pf {P3 YDD>r r/:g_(QUc/[MwP+Z=qgO_]_gq\4 } b+IM3u$C.D]v{.M< Wers+ 9j\B.{:!;u:h+>m~,5s3:9JpNj3 ]s 4 t4 U r  Q     7 d    % Y    h EC j    S  e$W| 0$.B8=?J=5)R_x+jQ;T' DOhOT4*}faDI!2!s[B)rJ" !-?XP0d zyV3*4,'% %#'>/_9GYo/c'BI~nDI-JO"Q} if Gv"s[i8(|/LO.{9mL8I  : -   o ^ B /  w  |Q  e  LS  #   >#2"9b<<943-]    A ax N !   x 8   c   r w P (n  Xn?1iyB+T9|<:}gO1~i D Eq -1 }R & l 3~T MypAplhvSi3qw}y}cOy>1p%_N C<?Lc} !6FSb~!742:000j0,0---r-M0/027 j Vb D 4 $  Zu H  k  k Y4@W%XR/UpF;buu_Ft* eGl& 8  ^!!="q""J#S##2##g $%$7$ C$H$9K$ H$K C$ 9$[ /$ %$c $ $c # #b ##`#S#Y#"W"["U "![[! f 9 un)6H_Z)]kO/\ge*>?|EA?k:% n @ X . ;woM$,[3euZ>2!a(vZS. !SjL,NVW- PxH*z!yiB-GozO/P;ܸ@ܜۄZmYJ3<2(B#%(|2C> Mauא_׮A& O׃׷2:Rׅ}&*r;ء gvU{A>۸6ܺB dޜW@vI7^b0jfUgk|M48+&i (% . 5 AI M S Z<\YhQD}4"ylM ~  )| ql Z A%Dit;9Z imDi {8;UYU  R;!!"3b""`#i## $R$-$$:%%c%@%%A& $&A B& [&= l& x&9 }& }&7 x& l&: ]&N&=:&$&E&%P%%d%e%~9%%$2$R$a$#i#8#"{V" !!s"!! F 6bt^wkWQ'b)ITO"=pFZiT:  % tR @} yJ?b_-!@\Ux`9aU#qk2;cLjM16^z- Y}XZ7f߻ޯXޣݛ]ݙܖrܖ ܞۨ<۶8DvnEٟOؐjؼg#ىBalT]dz ۡ8oioݚx1` 22v^v&X;`0B"xINl l 2  P ! }Y9Zk_H/,J]}5 $]5 F N S9 P I ?U .Y:{Qa"tsTkYZB$?hV1h? p  ! ds "  | H* y  2  ) Q? qSo% M ?E~`@Rcf--iI})vvBWs=BOV\ON3N  s8N R @ ] a Z s!E~,d6*iK%dg~%3fR/wz7Lx+?xmqEx8 xkY]JAO<7R9AbM\rW_OS.lD`;ClI7,1V'~$ 0_ $52sHMgb:8!KOEv.a Jz4O&"!K (  ;W U 9 uy  $ I } F}P~$N"eDh'J 1=`4RrNB tP9SBfn `E'q-rE`[PEx;B50u*aG u $ H  R h  c g  l N  z - T  9   6. Vv l ~ 2 f    {jAVf= *RE[ o ~a    1  ~ t, e Vp E 1 K C|Yp2 + z QI  y  q <8  l  Y B )c v " F |-`Nt'ICrgB8wUC4:&opdXbN D<`5 0)a! Z DRS,vpgXGX38wMmT;!"cRiUM0q)VqXDZ0}K!tg] XX0XI`djv-aDsT&3m 7^as9A qn4B[+#|'V}(~H,l> lC * b  z} @H{qR!   o*  } j(  =,z&!Kmp 3F>$zfZ7/ Lv:Qq$#a(i2H8^r^z   '  1  t7 Y ;? BJUR_d$qV :pdi 4Bsmek3GDRZ?XOV9  Uc ( 4  j_:1Z]y62;h@;0zU+ peP a Gbdf-eKfon5-`V ;&|J!%/nKD&e,ߠpߔߊޅޅDއޏݞݯvQ3Iuܩ\ܡ= ݒ$GNqݶݐgރ ߊaߢ 0Y]F0C|%[A+|{,=MD{7:{Bj $ R b A "{ - 6xvW4,6l)A w@|W1I   &~ _L   O-9d><4e( W3xI_|[{it?fc=lgd0< | ?  L!@!Tc! !_ ! !e ! !m ! !w ! ! ! !!$!!>!!_|!Y!6! ! T r 9 2s(+.JJOq:+lc%(u>& p?u PvB Cj4L ? \ (  \ PYb" =rW z;0lKIewy-"Mz:B2dL9^u}65z qX3PT"c/ aF/! 7 k*j>ZwܜR%`ۡu\6KۊA>?FۢR dwz[N @Kw^;݅5f߿pt)[VQau|- :Nx x2y+l+V^Wp  W[   _ #7E~IG:}KEg%8}U #Ptz$9I   E   +  \wyP#NLzfo#H2{50*%wuE d   IS   L 0 a H   N 7M]^kty|/\~yKp fT@L*\#uD P[{G@Oc'Dx}=6OKN\E/I xgE wi %  t *  i .J)w`f!`N6Y~%Nu! {N+G\w84(}N,Pb"L8'zq~)*=Xav_(dJ2zao>#$ P2) #8>aPw L5\G+?r; Ly].Kk>.3I+R*M1@B& _  r  C D  k[ I . ><mL]s%=Qeq.~=Dy?l[-G1X2rH w  N i $ :  U j  3 j  e V   K z C % m  n E:  ZvGMoH";fpR0@b{bG.!+5:=:80q)V!;|W4jJ$xPj&4|d:0_~;t q)r L\ c.  V n r l  [C&l WvMjP]QbEU!FZ}v]B)/_=60NOs R0i(Xk0 Qb{0vtv{ )Gd%58iO#lh ;U{W#i%EI 3X 5M 7 Y * y  1 VL b v + s  R 3 ~s b L U1   T | L  . b z C  + _ N  7mGy34`d!:XZx[ 9t_@ }P1&RmsX=" .@Sevyvtrrrtvv yyyyyyvttroomjyhecN^6VLB6%tJ qfN5+]!c3g'h2Wzx<+qB,TVg7y)b7N FJX wd/0c%]:xAV,jWEB9l/'%'9*u/6C9O^ot0,uXeb.ifh ajl"emv=-17PiLwXv_ V < D j  2)   (0 y  oc X@j!_4eBjc@ < U l E   5 G C - l   =u g rX F 3 <  n=vwV8UBc@H* S y6_7 w<d:i: tQx,[ =$ rH_o-`QB6[,&  V%Pe'z^fR>(<`}6bA!UnoD~.6oC(< 1i}7Dx1TCG7Qv;?ca !6C S  `  r    u W) 5Gjd5(UY)kH Zb ]` rQ%/Gdl%$CTWbN e^S S = Y  Pi ;}5f[$|71:K5Z *`x \cPID'p=T7<<1Ir(R]K[gO 5 { * | -K } $lo"|T){4isLL'(mf=GX412|FluL=*MLxUDaCa;]:In6Sn2C v>hLkw`!s(PpeJ1""/My%H ol:8qh" yX  S 4 k  < s C |  H |' b  G vF x  +G4]JqYfkkf^RA/*L r N . d  ? D  6 h m O  ! {,Z*vc_s fO>vi])PPPJG?8c.!MxV=+&)3BV ix3?LZnArvT:Kq%0)^b ~ . @ b + J ~ 5{()q6A64b,<oyX~@xV'J~HQ%\#\ &S  , S  H 6  69    tq   ff   )Sc5},U~9p ?A{gn(LiOY\&ZD;" <zbFk6FKl$#ke/;~ XfH (u aVX80Fo:9jwL%L:nzaF* z dSFAAFSbx!#cCcH8n4BB[ns@,u$'lE Y h6 $7> 6c "  { y 3 O c % =   m3{dK%1ql n-~8@yF"|XO Vq0 Av[S:XYRh9:WO pBk S  |  3 *`X=E{C:x| :yc5 qK L ( ie  ^ 2 +e.*i na/ dkslm;B(Z0ye5-od #dq.>M32sKO0( !:#<{a% TY  (^ Ch8;8_ECcG%s  k|T$r^aN>D"A BDD9$  L a  h!? ! "7L"v""^"""}""H"" "hb"3"!6!]E!y ~\ ~q)`{J.7laB>m\/&KdvD    B u 2H v  U - d   [ ![ , p ~ _@  V Vk F m(  S  l I7 e@eRag !dl6Ty/!zGNq f>g#eh%j9\<681HX}&JOlEh? , x x_+RJGNB=0>LI5RG_ ( `! !w "" &# #p -$$ %Ec%%L%&3&z?&:&'&c&%%"[%[%$c$$.#X.#"E"!@!  v f Y8nrP3![XeBP    \7 s KEZq?1nQ$vC k T  I ' yA \X ?e`oKn Y;G:J0`/"BPU`Z=m3)CcfMXLjjJ^6,**X/69@jL.`~G:~L1>Pj~ RK =.F2JcYPb437#m{Vh   r   [    0 x\ f U < !  A\Ur L~hm Tk 4 [ 9 p 0  d [  h o  I m   <K qvJ 7QNjF(jdM Zl&5h,O l+T* l^Ccv@&)Z_Je;rM"s \R,;nSpt#_?EEQ   ) f X z E ` z o d w K y 3 r  c J ,    vZ I  N 4bkHU \n=Yo=.YZ'%Rc?6)!~M<L9yz&u*SX^?0+3cF-_}>k QbD-y5/+M}h%E}*@RVm%@ 55_}AK YYe0[ |FeUkVWdVub|h~hny9E$  } V 5  sX#my. m ^e `S nI EB=-f'nbz  Oy!""&##zF$*$T%%73&&p&&t'0'82'&''& &4 &W ]&z & % r% % $ A$!#!I# " '" ! K -  niT&;KU`<hpLsyO|A}y&un e ^[ U K E>@9:=nCR8d{a  s A s* U I~34}X$pU0v/wFe 6 g   \ P<    \   s 1K W |o1'N~vJ |$ C3 < < q: 0 ! T woN)c%U} rq$cS6@E/+U=llkB#s3\A0+j0G?,Us 9kJ01dgBN'hjW"`t?D Ri{! h \  ) j'  I D T A 8   BL t    # 2 5 -t ` J 4  n .   BP   z $ :  b=  * "  Ai U1ePkiqg@eiow "R=tFu}(IXgr3jjr'Nq&Fk )LqHr5SkpO(n5 i j >b{kN0)b@@c7|^0C'[',8C^YrX0NRXn40o+e2wI+N%8KnY+bg_@R;v!     .} WZ .  J  M 7  =YHO%sQ_9|EbyNqw]B2)m1j+iEs_ Y  t  % : z N  r^  k g x  ~R18P/l3E m :Z i x3`Yv$w{- fk5RiX',j,M a d0zfvXSN3NNZi96 +V&C2pt@f G.ArDk N7 W j| 3 n/?pT$*X  j >  x   Cw.'~;E;:$s M7_zFirzW_5 qi>+sV 8hVu _   = * X t   >  Kl  37}hnH'D_YD >w-UR08[+C7mJ )@Z$w6T'\ QW{(*p(?L:T4UK(8n #Do# =(QVh6ߠ0R`ޚA}uގx:ޛVc߰9jLVJC@CJTs`>t['f! &DfP DzC k ` SBD-om?nF#2r!""5# >$ ;%c )&8 ' ' (wG)')q*n* W++>+1,]^,y,g,,K,t, R,^%,++_+D+j*)*) )('K'&%{'%]a$6# "!*!^U }9&3Jho ;iAo!J+^r   2 G ] /   E9  d k&@4;N9!Y[*4B(/x3H1s T8\:m84`Wx58QjhzS*ߛz$ݰ,;_aڌS.jqؿ\hׇF ףv L>'t Lٲ١ڗڒ ۙ۰O,gߪ2z<j?A?^j._|jkIn| l O I W ~ ~DisRk#E;3gZ>a#(/4>H,Z>kR|ew')/@6X@lEMT^ht < ]     , G7 ]Z oz x x q b N@ 8o    ' N q ^ 4    <        u  :   < e 1 C r y 6   \  " (g - 06S:BJWe>wPY\+XalP~ ^&CJZwb\.gQ$uSM2 KM*>W:rC),mQXS/ n/^,vt ?j lb +PCj7Rh|~c; <|8^9t  /f&?8GBJ iL0uu&dDg^~zM+XU 1Y)-I b6@tS|y| K*~L1~IPK-%kh@L}=A&D\/pu;{zi8WvA+-kJ~iS=',Oqy.rNrnw;L`DDx  Fz  0aVO3 \  ,   Q~ Uu 0 W  [  v   f]G+ZfU  E;!!! "b""<"+#S#i#Ep#td#I#$#""V")!8!?!B ; 'bcf'*PW}I~ y  O    > ( : QN hW _1^k!B};5jeCA#!{rfZXSV^hw #0UQchEdn[:RM/N9OODN=LB/4߆4.ݛ3P JۈzO!ڞBh 1٧q|`WV5Ybv3C!ACfܚ:RߞEiA96Xha"!VW)j^e=;-C} " cx F#;Ql \W cC b. ] M 4!""q#2P$$|%B%e&}& 'I'"s'''''Z'z'W'40'k&&&:&%% ,%$ C$#0#"!^!K  _D\Qn91r b:6]m~ :+oGMe?L K r  " ? m l  h  9 i  S tq$M 0.ZdILB)ckK>fs&yS#{$*-/03N;CgP]r KRx {qtyۆFڠ0v`glکRڳkd&ܨro8Xu޷ ߞߒ LG{gP+%i`zdgQ.bF_3HYjZz  V  KyX+?S^}vu9 yGvK aOIv{D  9) < K FU ] _ ?_ ] U 3K ? |0   fNe,E"p k  m H "I    O r R 5 7   P  {ob'D)Wz(q{8l[OJ3ZVG+waJf7## }"mk?B qI=#sm9{Ci0oEmM!oi2eWxWQe.3:k~Qyye[D:S430(A}%a3G{')DPp - H  G L  CX~K | C6t8BLbVXSG3lTQ1W cd/ O<2 _u   lg   pt *  s ^  x ) n 7 9 ZvQ3Ok9 x_I5& ~thYE*z>+AUiiz^#~D@ GiIC(r/saL$Cm9j&a(N1>b;#_;l-=ywoZg_OY;! cp&|O {5`%t;= _z 1   : ; pI  ~A  Z%   <[ n  k  J|Z5  %8GiO)QOEE6 ( I  TV  Y : U U 1  ej   "*  aI ]Zmbw}|7 a?&!?c.qr%U]'wY>*vX8O?@~Dby0No7vy1aC*-Ho. ">DYw ,XS }}(fnYO D^4"VBaH=80 / i4 5 K7 /4 RK.r>9;g&  5 z% p   , e    . US v  ]     &   n Q C.   3 vt ; # X p # z $ ! XeI6afLBc@P5'[ 7bV37h0AD3y;EhW 0U)+t{MeN8" :VftTn4qmaSw_JC(HNlxS0G ^߯ ߒtY="n bds޷ަޚߍk߃~%||W=o!bOA>T&8AA4f2:vxR e  @B N{4N< U F ! " # %[ & !' #()c**+j,/--qD..&/!z//*/ 000 0:/// H/<.f.D.-`-,R,++n*c)7)A(u'&I%$$B7#V"hr! |xe=;[w n.  0< V  @  ! c?  5 C}   XU  6U+5"6F'<=W}YJJ<S> d=hHIj1y6ݳp- ڪ.iR)֯q16DӈO3TѮzIh9лДoL1F|o/$l:IV9{8٪Kmdݳ# mf'c [b7*j;ogRK`JZZ M{{5 X h g bTj.  R  ^  mS  10   )^qc&Uz=x 2Piu_H-sdRA2#U)`.{]M:  k 2 { V / L   p 2o 9  N  Z '  > n >3 +G^ Uo9 < b C   l!;\x(wi}X&J>m2 )"L!''2AhXtK63~{* p~k9\;+M5a_>(#~ OS 1!>aNv0 M~f)1vmDipDrHqvx*,d~#tZ. Y^y3]y`B"~MavSG+j%e,g0x:~y[8;u2p2{B 8y`L% 8izrJmkmrB|}Mz /V#9 M=\qchf\_M7/yi`0N`QeqD5oE&1t3BP\{`- H_hpk<wiU>((Z;xl bX#KBV83.R. 5BUvqV?0%U>~   N z mI ^ L 7a   ~  P5   =I  UaK"{."`f%\l0@'$r xQOlAW)GTE + 5 o Y &  gZ 2;x^@y i"6V (\ <'zJC +s!28]M8*R0PLwOWEd2n qG1$M_jrm\Hm6(sy(; Ww!BoElY}!AF l>%~B<u(Av o2B#j< 6bM_NI^yJ6jW+ JoK - L   | J    YF:^O+F*|L+%$=cII=L) E5FWm__\iP?&:Tlc$d~ bWVuPN OT ko$MY!2J n  f ? $ w  K Z   P W2I,kZUxIBGsOS\"k8}!"eHsDq3W .wMnB m1Tz& 6 0 '|B"s b vaQEDt! n & < N< Xz Z Z U* K` : (  , Q n  ` 1   { hg 1L 1   U    xt AY 9   y L P    o5 CQ M@SW!bE!uJ% x m % N  _o !   {z G`,r6.vs.-]VO(?Tdf(xe6C2ZQt;Bo,2ml0r{DN {SQ0,?lS( 'G.gUQU>xek`@SA!- w}}m^%N?O*{3?R>hotv iwRL) P X \ 7 ^ | % Y  | k \ M < *   ^ 1 A  g P Z :  $  S9wN ! : $U s ^   ?   +4 R yr " } . ' L Or  k @  $ . 3 3 1 ) } k Z I : - #^ *   #k 0 ? Rs k B\\/HN\p1~p8Zw.:BVgot~RD{Nqeo[ OGZ@ ;;;U=&BGOQVVVVVYS[`g4q^8$D#lB/3@wbb + -  H4   Ig   : A z  c  26 Cw M O J' <X %  u  5    I   " H b ] 1 q  ~ L   c   A  errd3OY/ 7vG:yV@;g1|CnLS4&()qB3M|uELk2Eqa+Gk7H5lLs.G|P' e 1DRVlX V'?n%kO1eG:FcRYxbfL!$no$9nTqg[B =}3 a| H ,  2 ^  s D )<WH,OL< wE{#  OW!!["D"<#k##rA$$]$$0%/%>%M ;% 1% %6!$r!$!$!\$!$!#!_#!"!"!'"~!!J!>!! < < 03eR~tx-L8RA$`` *@wd6@p n 8  A  g r  N .)T~XJ$D>J Q=5[, 8Aq^0 , EyavYA,  &2I8`zTn2dޯB umڸarx0(רm1B՚uM2 3n ߹(zCftؒߨUBۍ5ݖbHk6,\(/g@X|A!th?V6p{YI<<6|6?P@hD|Cg      `. .> O ` rn 'zxw,gF$U` >T"Q{T0D0SbbgilibXL?+sS+Yw{PcGq* mC Ki?B@|G= G_  ;B  ' {  3  b V >   ! GghJ0 | xn",c7FW[rPNY7puQ+Y}q%_%uL-^xli^q*AxaP/D:5V25<CH K(P>RTRkU~UUUWZ\dkw|kYJ>*2C*Y#o 3Lg~oQ,m1WN( -  $`7u dqRD@2#}XC`>5 P{e@t*zK&v_G.&Pk.6DlePOi(LPDa}>'lP!1R 7 ,   } < \ 71   `S   BP   #cCd =hiH#N tG8TO  i Z  I ]  m Q  x >  b 3 9;i)^?UOP`s`'.Wa/+ i2| I ,TE(n$s,Gw KzRq/ fP:w(_ B$ +u?X[pG>?Q(9yMc\ }ATD~fMx3\;wL   w 3  e I 2&  TQ_2BW<=~m}5nK_>ili*_hP:&5:S8"+y>m,x-AB$LGVWU i :  } o.  + 4  3 / + } 0 " u 3  g6 \-sTGUr h!+3a;:5'zukDg hhrof.QW7N%u"q^"KKQ$m"GM @U^< t V;' >h' ~3LJl>W s U     L%   m e51DNEY2[s]N f1#xV`7+@1Je|j{5UlO6x$I"3Oqq]QI GNLXg4{@!gPD4H66=DD>_. Vj3N&sMU;(~B!Nv?#k*c)11n,G"To@t;U UiOd)y v@ ),xN+$' gB xfOv9% &N$u\oA( }2qn:L)[8T"F I{3*[Jj<d:bYWm;%rg s_kikMuE`*f7#;S"0&%/8Bib h.sYlhr0 < q K (r 5   r EE    6WKx&V|bZ zVy!N-SKFpM   !R!!!!!!u!K!!!!X!M!!o  9 `!2E_J2*c: DULOP Z  j  -~ Q t  .  =  M,_9GvQ^is9P`mq.qHam}dV$>Lw b9p/'UhtD0>E[_*" ߃P{ݸ$ܔ|7ssڀy٣1@؆4^;ؤf2׬נأ4ج^ ?VxٻiWڵHۅOx~$ޓ/T$1$R:+uT+ .  # pT   4d g8SWCv w!d;""#H$H$rr%%v&&P''(O( (((),)8);)3) ))k(M(*z(9(''I']&0&&%4%$S2$)##"!wE!E Bn5ZDFzJ Cq<  U  B hS  6  ' h P u ! 6=>e9&9gr?I^ylDyk&ee _&g `<n".w&kQOG*Wz"eCz^!/B|[E4, *;1tBVyV pNC:,$h2[YqDMCg&Do:9 &uu\J:b0%:_mgNiL#0E@W, N w , { -  K c Cz  Y  _  W  @   j   I r c P > ( * 9 A H K H Cx 9] -D .  }NoQ]6~/~2\>$hp<F p   , U J  f j )x  \s!(v08`@5DcGED5BNCeI| S$cBrj7.xRv!'iWgn@P:(R&-?\}{}O@d0dA,^'.OF qrPZELO];uv@Alp -IM.[kU  7 .  G[  P N R  L P ? #  V < O ^V h k k cP W H 4   - A Rz ^S f( h f \ Oq >= *  e / } N  H { = b + t ,   [P ,  g  r@3HW(UvXK$QvRGd~H?Ze}N+ r1"7)tAOVh:p[wk]1RHaFB8BhWF }L:~}ED vwL^'J <44U&B|*+h??g)y{MF~x+>0{0   X@   i 2 rU   . C :r  *   V  " =' z) $   * F Z f h h _t MT 41     Uf 9  { '  oP ! 5Ng;YW F o J, %  u  I kF!|FxvX:C{Tg0G"uYg-chp<x$]"Jz^N:1L~-OHNNIE~OHPmH(j"`'u2RJ7cE{D0RzM#^ BN6]Y9GBFWyBqxF8KvWA `ip A n  m x ]A5  x +R  | >  K  h. ` o  `  7   A    * Q m  v I  ~ j Qw /9   r W*   n? ?EQ@M32}f$qqhc  n5 w  } .0 jG BgvJI~E%\R G]D` ]\E?ZMN o~;6W gxY.ZLgt/Hi(2x?B t>~ Y4phfku % B@j~eI-7*fUQPYf.Y?p-#"t&)5H`h.7`m-XU j`  [ [   [ 4L<HeTE 9  !"V#$E%%&N'.'3m(6(1^)$)&*{**+?+^k+*+++u+2++|+FU+!+*@*I*) ) )P(-(}''&6%E%R$ #p 7# y" ! ! C K yc    I(r8CM2U[dadd3hhpf e c P^ ] X)WUePOM:KLqL NQ@RWu[ `f=nvj%Fe~ -G#c=Yt<i(NA}{PJ݌I7ܑpDUڷwV; r ةR\>&s8 (>Z|ի LB֏'!{}:M؟ Ezgmx^ݘ/lt `S\HEGVP\oU`Qw) N90cm-l.F&cRN8: d  w 4   $ #l "  ! U    R /H(\kfw~ ~w w mC!a!O!>="-~""" # )# ?# P# U#d X#F P#& D# 2# # " "x "V "3 Q" " ! ! E!~ V 1 F  }  m 1C  C  D } 8S ) _o=" ~/e,'t|>Q{5Z  [  > ps s 9giTLy:{4dY2/dq[KWcg d%GkY`*e!|ilWKFA[C,KWi1`, [L)gz!(c@Q]NW}oC:vG,t00.2z cYAQw5:J]}QA E=x>]u?4J`^3mw|~py>r eWEi15d0nH&h9 }P!d=b3vY=^%7 zR+~rh\`O:C9-  {`G/}Zz5kWD0tO)ipLH0 uI~^@"].{pQ\*H4%cK2 (>Yw (@Hrm)n6wWIaD"p_YGX:m54(3T0&-f, .] . h *   q  j c 7  5 RZtY_x \\'4m`!"<'S'_dbUD+ yHx8HMBv .%' 2  u5  =4  / C $ , r   0 lxqKt!V63Zm [YFeIC[;zH2 qbC#`"m4$MEo q:H8e1Jc2JzMs#S7 lL.-S/wl+3xVy :U@h \b4U;.+/-6B]GvZw +T. T { 7Q2duQqxk,W@& $  |  bO   | v ! !- @" " <#(#r$w$$%;^%Y%q%%&)&5&8&3&$&&%%%[%%$|$ $#U#h"Bq"!o! U R  {  %a s5   = z N   E rc    C ( G cg ~   N   )J@Ul9] t%$>Ws9P4dW}t"!{L&{{"IuiDb n` vk9x+wD߷t?1ݸ@݁M!Y1ܥ܂bD+ ,Wj)+B_߀ߢ=&W4MfM380/54=ICYm^,P[#<`|+5pEG>j 0 z   M  E{:UN_ln8qqnni|bZ`SD:l+ H k   T $   p MP & xW+-~Ed8W XhG1(l]G)pgF\ q [) Gm 3 ' : ~%3FEYo MT"h?iRB;?yeOW6  [A0~m,YE92W+{.kx7nkfddipx W-O%uv5'^#O]R6 Ui  \taeZRqTV)]fr5}/~`. n    P   * > aL 1Y ^ ^ [ AT G 9 L%     1| M $   Kn ) #YQ^ P 3l7\%kU=tQU C=U*`xY#C3!eW'n\-u  j X .U  ;jV_I@8-6n88;*=g@=;6R.' KT.B!Xgq< po* d&,2 Qoz;hWYF7u(9RnJ#q;y@ AfiP<,-V#!#- ??U{sP/oa)[ZsCy%0M)Kt"giZ[>Gq$ 5x  y ^  X 9 ~ '  IB } ] \  5 E S f  u x }  & z s p a N 45 f     V    e   | |% M l  \ ;  cg   E  .k  G  Y kxzgO)/E mxT:.v ~hdpS%GUFKqXBm!yYN>% )rx+N Q|M%4_E?T#c t.G`v# p0 q &TBYn2}l   ;  k 7s^] l >/dASg~Xo 90V|pA8od$:gF]E;dݺ;ݜ܃"hM!43`صMؤדׁur?d WMF<74224('_'t&G`&%J%$$^z#4" ."!  }d_D+#\FlvbQB5+6$U"s"&+ 3 = G S7 ]P ijs{3Lg7-X:{DKMP P3M\IA<5+C#z,mB7gQQ5*e9G*p z޹7ޠ݇lSt8VB63;Gݷ`ݨݜݒ݊$ޅiހރ߃r߅߈JD\8d5,PsmVA@2e%+S{'09E<NaWajnrss/mCeWXhHt4~  ~ I  | p^=M7:jnA}Wl0`h'"XLj 4<?g6EC\_Ud tSB,Z`9'4 < ? > < 7 /1Mm* 8jpWN= Ry"j^IG5+%xY6~S),BvmLKWL vC6y kVF% .d9nAh6e J.@jD F s  >( R rz  X  1 OO o W  o $ ' = GQ ` q h}   x !  j  { < n ] ^ I 3 m  j U o *C   @ r 7  X l ! !35CM,RPpF:&K ~{>IdO1kP f l N I% xR  z L ./M}&i36^Ym7:c}X3Gr ?~vyvtTtv{4uS1r0NXlJH&CaRi%JErFGv}U2.]#W,h +P$}g*?r/m5%v s yF06WU%b](8pd99[{ Zn 7 # z  ' r | C   j ^ : u  5  4YzI\T,2zwCTa*u   U z h M *=   E X  4 o p  J;mcxoW3-LkVf  G h t  _ IR.~G*@DB{?N rkG0mKhW0F9"/(#  #$%*8/7YAKUcpQ4/A%9Jq[1m~V'rZC2&'3?&I4SF]_e|insx%{^}){-fT(X?Unk@C(M{rA '}YR(.gvW9Q Iu W I6    H^&@{c.ngC5[aX7  O4CR^Qh{otwwwrj^Os;I Q_-MSj,Sk(jU] s4)x J9 u s.'`j)=r|EO}P&nQ5[ C@Mo>o':cNed{q R-Fd:G~ C> YupZKA<8ATKo\s E!:Slq=(91Ojm c"dB7b?f :EZk|1@Yl& W B b   .Pm0CWizlM%9  !3"w"aU#H#0M$$%o%%&d8&=e&&&&&L&&&g&a:& &%%U4%$u$$=##"`!j! - :"ek"&c[(P%Fb~S'  r [* J< >K 4[1j/|149>ELT^j"w ? z 5 o,`r96iZ<:gl _UNMIII}N:S]gqs0r4&}M?z G@ wJ [RDb'>w>O"Wg5xxD@`;E Nw eJWJ@>=@xHTh+~i%f=o)l$i+i\Z] NHReL d N  - /k  y ! G uy   t  8 g p  ]  I p 4  ^  v|#*o--L( i  H   k D * @ O V{ V= O > %m   r w 7 Z K'"J9f:{! Y   j   W   )j $`+DLh2;yp:j~ SH >iIf-@T;h|FU ('Eeo] N0@U8{0,+-/G6v=FR [?g vp |  ! Z;rvgR;L0lI U.s  C!h! "t"".###$.9$Bc$S$e$v$$$$$u$M$$q#X#=N#""3"!J!e 9H +aM2=Z0b` W$Ca{Z  l 3  & 8[J*\nqG4qPVn;%"Mz Cz1uLA S.=Q`qdVYk,.o=L]i>x߅ޑޛsޥPޯ2޹ +IkWY) 2 jx6w"V%='+,16=EL'V8^Kh`o{v~ El)Mm e8|~,mYxE/ v.b}=0 Z z q E  fi 9A  zXI VL&jE"r?Tr\IH4#(n8z = ~ 4 P p? F'Oy O,`e BN+#}p" wV&?6hS=UZ0%h$`04__@>ZHwu:iSD:8:DSg:zh.riZ/MAe5(c Z%hL7#}|vjnXgA ]* S G 8 ) wB @gE?"rR#i(M| GL{o".1/e1}&wq*`!VPwK[{~f9AFv< ]S :  a  jpy(?.d8HE]6|]I]Zp5,BuRgeapv5BO~"[rMAa[.V8n0Z$Q D9OeAy wgp'g").m3$6;=\="==;8U6'3.)$yQ) }R"R~j TM > % ]   CrlP-}xW_0tjS3H> Zm|K}w8fP4c?XcL@^nP()b"[j1 0 L a 2c  z  z ]A.)CWl*Ii%)AN]xy<ioI&     n $E3ETbt\$k'< )8?DSIbn4x[=sxn _ S D3$n5Y{Y64IBY(5W!Z}D/Z`% v : 4 H ] Tq|JfA,@UliS=,<bD{2vU.?QVg{sD%5Rs'L9\*~ޡ:'{JBj݊ܨre8^S^nj܇|ܠܹI';Lp^m/~ߍ (hC )08rB^LNVF`FgJqV{f|+Y,dQ ? z   !#G#s#!  $%"n4  !{V"g"Q#8 $$ %%%X&&h&E-' a'''''d'='''p'D'o 'E&&3&%y%w%M$#%$#!#"!ah!? ! vTs b@VrLB:3 .C.g.05=IXi4N g Fp!?^%|W)&cJrXKz[$Pg+Ji h\X6g`#$N`sH:?-CTUf~rfB ||Yp>d'P>-,Ecq,Uq: f/lQ37rzy4cJ4N t]Fx4f%WK<-!t^D}(iXD. a , s *cE0%kd8 Po;QWDqa#bQ 9V)k)@o6di` /QZ7Fby       7\~uEi`@TKdD=Y: e6$47K=wJBY sq6'R]!}_9TJhN#>i2Y}[?I& P    $ ?# ]F f F  \  % e, 6 0; @ C E E rC > y9 4 *   9 b - c c K 9/  n   ; l gF  'tE,  y Ck  4  Z 8   Z K   B  f<O^zh+kkc8WJ9=#  ? @z _ D C( K X S " o " j K | # Dd  1b1Wu[9"*2?rTkfxffkJr|7&s6cT rUI'NyIR.]fK8|b ;m\,]uDDpgQB(5T005?Q1d[ .5ZdC/[ TDFs_<,n4ufw1e:m? vPULa"R<.VV ~ ^   [ .  K g \   L        ]  !   1l P 3  Xj6 RAV$_r,o2rdpthgC` ob/ oB A @ uc5!`V$``0By'_QXm0,lB^T{P_"~Gnk-CWm^[!,=O<^l{'Db4~l\ O G?60 +%     l Y@'{ Z4kMCb fW5b)Yv=1eB~@y7uj:.JIo";  |zU-N  dJxpi?dvb_ b dD kt u  8h H'rY1"eX8:nv7W}eY g"gy+:ih YC001b@_KsO%6@\tKZ)j[ O L LT`q)b-6tbyhtpkhf_a a^j\$\\\k^6acfhmlrKw-|s^L</"  [ ,   |pQaR@/T lCpML(7aQ" TY%Q}{BJ JX +NE]f$UO f>j}FdSA5+J$ ! j ! &% . 7 D7 Ug}EN>Yhn"/VY0 iL&f|7P~1V&l1r 05vLv?R>|U$xY8[:/d-Ru,CYHmy,q d `QRh)dG|e2R;",9pUM(b JU&{2`)RjEx  p  MO   ` G  5 vs 1 ]Ak;fN Ga9  L z D f 2 I  pe I ! c P jQ8=)| aG,pW$8LLb{JU$Dld"M KuI"IQ ~[%3`^4Anb:#O|~]6@c$Bn"QDv7$iDj2f$] B{^+EdIH pER'']&0 b 2  =  I9 \ W|  m    /  ' ; 4 > 3 C G  J } G @ H6 '  h   s  Z U-    b 6& JW^ga\TH>6 A0\t8O{#2[ D *I b@ * ;  |j *k3l-}9op2cZ\+^ yi]G"6$M $yk$l3Dv[q%_Q:]`MAkzP0>j5[:_)Nu% EFc~`b.#EYohVXp.3DZxn!|.\1Gp^>v iF%)D`}jF #  & D _ }hB (t@?\ry'u J.qBTbt~[X ( H a r     p Z y< o e[L]=.T|rWj; >N-ilM5Hx x# `I Do +   AbyhVE4'%LqL|T xOslg-b}]X*SNLDGB ?r=:K:8353.33;00Z000&.0o035u8*:=?iB5GINSX{]gb[gSnQxS[iA}R /j=OG`r<Jq U$5qI-[n}_<(y2q:iAcD`FbIcFiFnAt:{2({p ^ J 3   lN3sJ{rQ*'{n4= 6o;M^@( N'8@@x6G'^r4; ncbH-%tFgs(AYjuU %1 Oz ~ VN5:xf4Nr?.oC.n]"/oU.'imMZQWEtf==brZ8ePdx^%rR4!&(-072Z57799O<<>">sAA#AACRCC4FF)FF5FFTFFCCAZ><<D750C+&bO y+7{bI804$ t OZ ' y  } | Mi  Cz AjsL  MJ,:EWcejmjf@\O;a%B_(r/gp2.N% f  [: . e  ~ c7 J4N `r -?%Q6Mcev)>Qyd)._Y#4mZ =^1`>&kX 4w=EJZf*Dr#DRRE7_0i-mCwEB4^f>'@]!~*@`  . : F BN S xX X X XU P I @< 0 !  Ko ` =*  ;  ? t H2   k|Hj_8!sg'<daWIiFBXG J`'M ( T %S t  p F  ! '}'`G&.!{tojh"hh7hhRjmsorw/y~^:,9U }:{"B) 3=GyQO]%gsz_D+#7K_x29K\i~/=agQL}.0LR3'nz#aprY/JT}3iB zAuY/>W||A  ^ ) ;t L X b j oqqle[dN@&,zYm E;gH Z J[p)#y:4LF^&Ov)c i E b mO ( 2 d &vCxB n1V/R r8r\Hc7(2 yYD 3,*7-HY:kV\4TNtV wD4iX-+Rzq]>Nf?8113,=TI~[sDi-_"WGm=I=bke +sKk%X<9TpBc V6L`tWf, C   } 5 $ )+@.000.+m)$3KH"2{gFTz@),9=9w,Y;w>apA!#o 4lCL.=RtT6e \ > v ] D +NNqF[B.D R1p^!Ot>- z 3^5sfZPD!7-8#Y&q8|EfF( &2DUfz2Ps2R4rrG'OSv!N{>6hvp&#VX 7aX**MruV=% $;O`o{tV7      Y,vjYfG)1F$cF;TLk.?KS"MwV"]+tHtJ RSaC#47'pakWP0IDA>ADF3K~R\iW u % h )j9T+rl2v.QDta&LLnK^;[!{Q(+G}`{tz!N-AP"apmz3{Go e(^-^4a;j@wHOT\a h;mqt|3(H" "DuTPl&YCi wfIT@*o!*ls U 5*  C  Q  XN 0 >Q%:#_d. 6c^.^*Z&[a)>oBH DwR-e p pf U < $L  % \ & VFq1\0ILdU(M3up*NY5)`/9NX T~6'oo1L/W{+gvUZB.H =0 i+DbH]2f ]  ` > Br F % J am * i P  > $ 3' $ +     n  Wc > B  +  \ z(  H z : XqA )   JM   _ " J gm   l   k   i   ly ^ ; r 5P  Q F y7[sT55Ll1TY'} .hHO(n%JiUx?.B ~c ]g>~yzv>ttqtqtDtvy~bB'.AXn$;Vt<^ =n,[U' ]h QIU Mw"Gl$N 9yy&vd5ROBl+#xO U{  < \ [  q B yz  ~ 5 {b  s  a  @( < M e^ k r Sw z z u Pp h ^ R A '/ C V c h e ^ Og ;?  XH$ 8E .Wc U J~ _ ~ 91   nW +  eb"d` "YlD0/}Ok Ob cpIt!1bqS85}ythY5OEg;61J,*'H*,/d6$>EQ~[Qh)wy t$t?y[v;:j\b4K\c6Go'8I_}l@c|4k/"?]xK^3 (:IUlaAkux C    W Qaunf8ZPUD7[+Q-R4rq`N=0.?LQLB3t9{oc`TGZ=4*"67)r?[d ^ I /{zslb[ZPGA:0$,}%|+@b{o.`QEr6'] TT\q Rf9)B[v}3X}A%pO~Y :l:N5ft2fq 'T._&>Kq:T #<PM]xFORe=0]~r Y>'   i N/ xT/ {[ ?,>%Ocysjk0Qsq,2PRu{L E@kR 1V?~Y!'IqpY=Fe9/(( *32]<H\r(Px'Y7 \N2 ,@Lj tP9),BX,l5Mr7h 0[ M~9Wbb n XU B +;     F  t VM6%epJ3%]kDX0gB^4 V]3T  n  ^ 3q  ` \ 2<  p \82`g?=^~`;2V{|a=F-j2f=x'snunnpuu!}~.Hw27RrP;m]3 GKr^M#>m4-*T(*2?9ET4h07,Y;58x)PvJP]\$\G{;' 3 X z         #  $  $   u U ~0  V&  X $H   O H  3 v M  # P =}   g  #E/47k4!* I  t /f :  d ! `  c ' G u >R  A i5R{Q'8[jGy' &D|eaH2Bm:v}s^i_XWNIA_<:5{26225t7;<AFNkU<_iusS8 7Rm;c3N?lq A7zi( fJ"eX+AqC@^])5kMW3)o 5{vx0yn~T|t'XbP  9 $ D  d ` (  7  - 7 h> C F )F _C > 4 *  - H \ k u z | xb pD d$ P :e8s :wy@. 9\ !   gL & o  ^    Hwn#aGB$`k{B0LTk*#nFLs/.e 'p7'_.En[=6/C~mu^7TMHE]E1JOWcrtcYQOOT@[eew ?p.]RFE r L%NZ(*p@4P^7O,:s5LApv5Ctf6w4.d B V e vB   YZ6`szjI{oei[O BT8, 1Yy~jtGh\TJz@99/(P 3YkiS/]xppf Z Pl D 5 &U  .tDlVU?)'nJv[0= (1dDM&~Yl?O158JiwaM.9%om!UX3-@Wm)Oy BgU-+U/[/Y:* ,8d=Z:aZO9Y_w~5 Y,;J;T^bng(jjjNe`VcOB6b '  J     <pOL/L:zP|&;v3Gz-\V%] )[ )a/_/pAFlb8oRyV4;R _ pg Y Ce / ^ S E4#tdVG*>?Uk87<"IGo`| $X5b0i;(Y5[[)nc/G$unP0I f6y? (7HrnH%y\)bQvFC $ 7 [I Z $i s } g F *  u l k_ P Y? . J  :'{[;d; q^48 K\-Cs`D D s Q    * WC %W h u | Z &  | r [f )W C *  [ % X S+ y[B" hf'/ZP}3l0J^Jnc-0NGbyD;Wk,(d&pP2s:e6cA( Uo6skdbU__"_bgDkszU^gi9W uY:*T ~M =Yq)oZB fUE3R*3g5U$ N x ~  J  # v< U 9h w  `  $   ? | p H ^ M 7 ;    [ u K   S    I7YwR9UgwYw4(   A} A  n .} 3 { G>  # LS yyB (k.7,#zP({iS)VC0~j$^VQQOLG@'6*; W{%9JTr22,Q:I[lV wW77\ (C^y A1fQqL 5b0s"TPT8`Z>*7Pf} 5WLW'X B#(i * - / / 2= 2 7K 9 >MEM=T^hrwP|~ ~cytpSkfa^PYYWROH7;H/U\_ZM<(x W5sD iBOc `,K{ N"-g ,- $ ~ H  l uDExBK te4<h3whYhM><-fN@9<>KabM;[{5;0ic &ip:7w1llN6"]  e5,{?Xv<z KRF=j/:DnnO@-?AUHdr^~<t_[ ` _r_TK2C)g v ] B6 & `  z ~T$~ba-/>xI)q&QX^"g+{E Z.a(SzAw%bp.?j`>u  } ^ Ct ( f N 1zpdPZX"Zbp\0v V/^LnW0F{5(!C &O2|ARi8Xv>r `  $ 5) + + &) z$  *  G^Et].E,|jjEZL?|W+0 bi=8 al3tRo N z F  H  ]   ' TG c | = j " R t 7^ C " b  @U # m (} A  d$=q;j"rAH Ue_<rz(5Ov0c -Cd\,am&'bS$0d{V4\Ow\SC*K/wQ5%yn  U 4K(ch"^9eP$ XH79sm7|.X V= A i / + ( K -p   * ~  ' {% 6 $C xO Y ` rj r y c   =    : ~ s o [ C  ' > h a  9 1  G [ h t K y  | y r Ee V C ^,   d  | XP   ; x t: <jdy"n8 YIy{ 7;e_}4 r%=iQ{c.zT9Z+YI {fq g_b] _iq}'\&_u DCw{6[j?)&pc [B)?XsW f+Z,oE.loGny#&ELn~ZC-K>fBUm %92>VHTu^kt.~],]   >  Q  Z  $^.;[GTNbo7{|@= K*Je~t`Jm3O*_fEI%OW/(Wn[$tk QS  1  Sm ! : Y`'!}r3EAkJAYp0Y)sji`K]]5gx)%0&KGph2p4W~l B@yUL&}1g^K3! 8b0<Ifb#*Caa~`S' ;kOe>v"*Gq  E2;Pl! ?a>tSb Q =R $  1  _  mH ##a5`i!.xyU9s*0Tw`<Wne; 9\U }=7;v8~C[,_orr Wn A +e  T A + \>f8EarD,3oPc"~ .-5X7^\.N[Yv#|u6c}DJ!_i=0nEr$@[v5X} : p) 5 ? /F tK P S VS S P NN I D \A < : 5 3 X0 + 5) $    o XA- vrgV[E.AYmO/<CwK1~{ BF    E# R | t -   D / @ IO Y ` =e e c $` Y cO @ / 9  p G a 4 " c p < I =[Mh'z7\{? 5~LY=)c  7[ ~4'=[U y3Xf%Pi -J"Gqzj67O|U-`n#p|U<3$ BJG5R&?VXu D}(UM|%`'M"re:,Gh`y ci y  0& . 5 ?: ? A JF I K TK K F XA : . P  9 GeI,+ ]    w J* K h  r 7   { 8   j "   @m R 4 U   ` p ? ` Z]QOOkUx$lv Jm ZRD_*5 q^{`IR;31N3;GVSbqe~9p0:gNAw`4Q 'u`U7ZYJ+_*Y4R r3] 9h<\}.eS7M#cmy [`)n@T(j~GsB$:Pgf}CU##9MdTwI   a   `   =    5 k   *TazAl:[RuOn* s k 2 e  n L' '9 c - ?n =cjR:UQtc1pw}>uK&,@Un Fs0 HfG/R-]B7o,cyEY bfD#u-;?9)v 5WUx/r-a3o]?nBC9\^'g6HRj1'&-;L`)x16;@B,EE?EEMEBYEB`@@b ; 6^ . $Q  5   u  9~e@O6$inPA} G/9@eC'@9,c F|M]jg!s!;y%4 |u ( ? 2 ` Du c K znb0^M<]8){md]`hu ";Vv;f)]5y>wm}V2d?&}{b'!gT Y\YBvp)2 lN 6 ] c `a > X I9&mUCj=%Lr2fubae mczls4\w')g8 ^B kG:Q^j8 "^r W?n(hS? t6*WGcd-7vPa0Q V+=NubAv X.4fyW]B)V?z2u> N F6Qo T$N@xo*!\Lv6r9^8~_=H[{;=!DfL i+>aOy@DbwC&N xl.   <A a  G   D  * C2 \} r J'T &=Qo_Wl;sxvqgXUD!.x:~Lq)kJ*  _N   lV  o;  r l  . gIm^k7svi,rkVb'VI|U=/2+'%(2@%9WK^ru.`*`;N0:5k` C~h26vzU82x,e8i!Kx (NsCk7r1;Le~&{2^$88K!]q .DaI!(-"5<iC HPXUW\H\ZZ)RKdA5(3 g   %  G  }Z _ B^T8o=  p,^#'qd!3iI`  &<dK W_Va\UCH4-xZr&pj$z+6I+g|>,Jf <\  g j f {] qgNb_>_d(qr <\pG 4>r&Iip- tA`iPM<)3t.y*hK=LA}~Q*-fE{wkc^K\}^fp|+Rz'O4~Y~[B(gsm! "D g K   t4 P em b c o % {9 J Y c m 't w ?y y Yy w qr h ^ O > $*  +  (  Z *  ~  ] I  7  { 1c   >j   (I  b 4"f>R *`G`jqsyye O3"7~RU   D T } H5 iJ & M v B ? "mR`;-(7*2n@ Rh;~m7g;b4 iK@-z~ [d3Sy LZUPiT!XN PR7wF[+qxX:=G<uOQ0PqK}K <i/o@>e&x#)|Qv4X ) !F b z R X ,   i  ?   t  ;   S  _ \:  T`;, |I ;   i M w { &  y  / hC T ` Mj r w 0w t rm c V SG 6 1 r  _f >  [ mS " ^t#8~]>2w5oN_33 M'6kD!SboB~hBDse %  N }s F  VyC@FEj'u-|JKbfpH2x&  .-C6_zG[ *Myr/Z={NI^W%LR InFW%fgQ"=^) 8i/^N})B0[ZyCFhn-$aLvVI)qs \9_RT Hbo~ B,Non7^ $ 7 }K ] <l x  R   b  x _ l ] K C 5   J   y L" Q }   E  ! 5 >F S Z Z_ _ \ bS I 7 \#   I   .] . o  NT  1 A w  S iIl/;fw0<Y~pD-IelSB3,)),H1;iGS`l{JwI5']okHwx+"LQwR)[xH#Ug@Ik06^&Nx !:X;xcM?b4w#TKsS pEp>3s[hjvDn=(dKi&W"P%1>HMIOOu M E ;/ , I  U  RwBR+&dl3%~,;{fD}z(&C+\m{|%swofP4hnd+{.eTw Wd .gQA!h u v o a K 1b7_= 9bh=,cpW`B21x(>$|'1/l>XXy E;~uS[Y-Up}*f +-Op`6)Eb{th`[^`j)wBZs?o0KfS-,1JNe#yq$v3EQ`j8t~d/e@tbQ&;jPwM. dH' I=d  p T r  Og  P 5 (q O=lQ)&dRx *R5rc/k [`mJC#__0&l&{bLJ8)W "K , = Q. j e 2  )] Ks>0i_}% j);Ea N1^S6v 2b_D)`cA3v.?.J@fX!!dd+(fg=$e!_yk^!WaRRT"\`ftX D G} t ( \ D " CL w ' y ') G e 7 Y  N  ^ 6j L ) v B O l  + \  >  3 @3.x|C\)%TY<1Ib`tIyJq0`I}3);wfO%'zFuFqsN=1Vm4K]"o'4@XtSO.F]u\-s/FMkxS. ,E^wmO45SspaU?HdA92/- /J2u7>FR1^em ?{*6eY[5i_N*m O1o%q&bb F^zg 6`nw)'85GQX>]][;SI;')o?   y O4 %k    \* #O r  n +   ^    ;   Z   } 3 j G [  La * Tn ) |LJ\WnRCJT^m~Eo+=Nb5vn+mE!:R8nFm*BC\tuf^"Z3EYT`[jq_vyayvbtldbYfL=c.]P  9  r J # L   fi 2 kNOQ BvGv+1ARa^knpkPdUC0Sr@S!qf.A R Z  D  z~ x z }F i *9tk/_8`3w)Pkxq!*JBhw6.ZI(g_B&5 Rs2Tw)!Q?ybBDlz6~Frl{Ch>yX1NAj9>Ia |  + Gge8BZw`' p +   P  ` ` -  ^ HMB5vSX:=Zu/+8u_[A!^%v?d<@W N ) y v[ t t y ~ 5 N`n0Sxs< ^*+V;O0fX}6&^Ik)e-OMkKX "{;6Qjt9f7: UsbI3/Qt 3]&=7Vdq(\5f)^T,&{U&} 99de=%$He*8Ney-\;G]na-wyDs  c  8J  $ a  S z + a:GL Bdv@<Wrk2|}D|kxWL?"!~Xh$VG;v46,% a k   "] , 9 G; [ rr 7 `0G]2sNe|?Zx0Gb%9M2^rUBu%K3BQ.`oy~"|-F3vL6g~C9[U- Lv{ng2bd_bgn4{k Bv 2ZBs(f0_.yg%Ecr~4lF(xptkW4jgcZ&[Pv5>)l$HZ*\ LlS t " 9 5  > Ot  u 21 V v p 5 [ , ^ >  l N ,  Y ' K  P '>=Tj~c7P.Gj`x9Rn"&-E7AKnU)_isc} c#n2L {L-@TmrK%8[bF.$N}G3q2s4t.I1gl&b#RH| Y 9`X-x'\8ENLVXXDVNEE8'NWyRW'Jf20{IM  JH~;Gop-i )! 3 ? rI 9P S S N dF 3: +   [6b; |tp>cYOHAC<7i2/--3-29;CO^:m|3'vjc f q $ @k(d)~I~rfYJc<;-|dP<+ &7Kd|/HcCm 1$[X A3_ R@9m3$Q<{TA{aIi(K7C/MTWYYgTOHE9** yU  *  _ <`  "   }2 S ) *wrBJ0]_0g(B<"KUZZWP~Ck2YJ>2(#i8 (L2>Opc y u  X  8" V tF _ q$Nyx|x"LqrhZN.L@i5) !5DR\ di*knUcOE<'8=Q6g{8=J\s$3B"P_Hn{xL40'=YDrl)0oS6xpF<i(\n[L?65l.++.I5}?L]qRJ-yZ(Bce)q ]  d  "   Q&rgYEG:`4*.z.<*s$.Qk{d2H"I[h  z N* |  Q`  " p[ >  < d_ ?}   { q g ` [ S} Q_ N< L N Q S [g b3 l x J 7 P VRA  .t \A)mZvQlbXOND:\0 )"s'O C'0?NP`s~L -P|uY9 R,|epf_WUUUUZLamzNP Ch>wGB{q)i3S7nhbiy8bx]*B$[#tLJ" lp&@7U;()txQ )D  - {^ [ = "  ' G ` y } x v v x } r Y ;  R #   %} 6A J ^t;^r!{& ~'w nd [Zt^^E,m:nP`0Oy[Y@ % P!twLk'c\WTRRcTJW1^fr~ ;[y&Lq/Hc9c6bBb$X&C:M_ nQz0#u zypa,P<(B`$b?Kp1V/Ka_5 jeqO,I  U ~ h T/ @^ /   1 G [ j v }  #{ 2s @g TX hD |,  T 1% O l F   37 UxQY 6ML`v8yR( b  9 xYC:y:hVEL1 p*g)}~qLdZPIDhBC? ==?BDL|PiZWdHs<2+&##&( 0=9[F{Rdw"Di6[#Fk.`-:Hxc|9|Q8 + /=SkrM-5 \s#ILdn5+o;= @{L7   c o G , h ~8 ce J 2  ! 2 A N U W W S K A 0   # 7 J a wX ) J  8 V v7 I ?E]}/i3';^Ocv7Xv)Lu2bym^4O=p,ZXhxdP?K+SV,fO9( $8Nd{ (9Mf~9Vv'O{8VvKF-DjWi z[dJkMnZ6D+$ xS. e};wmb`5 I / ` 8|  Q  } k O441{ IKs  4OkW+'GjQ6&Ls< ! S ; Y| t # 3 =&:@N`>lx:1( }vlbX L?3$1 Mn3m UX~{{oy'yy{a#zHxX83G`v7Us)7DOdh~0a> |G+ }(>~ecE2% zYi?D5(Q Lv B q~=sdWO-3 u s RC 5  `  e  N O;^~(?Rk h%G@"Yuk4 ? 1 Ej V g y| ' z i  I"Z+^~v*l`_VLB08,j" I3~(}(8"T, ;J[>oI3qXB{mBHo'$SufWFMuC<74/4\7<CMZ)iQzt  !,8OIwZis}'X5pxnb-SpD0@$sqQf.  a p`E _ x`M& `\b=O6~v[ @N* C|@m3I[lyvjXG1%1=JVy^Re'mrvyi{5~~~N~{voQh^QBE1 x2bvZ=L ?{Y~6BW^<Nx\gA?(rV>%{xx}wurrr u!z:Up4Y~1G`8{^:0`Ss&P}6L c>tpO?};{D\4~yrc TTG9*)n<E;t F u  > ^ |   , @ V o  " B d    z Z -4 P s   S  *Mpe"J,Z@TgXvB Z&Yy!gTT@) W~0^;ra W_- q$b:OZ{#Y6d:gP8{!eQB3)$,8EVg~ .S{ !.0:aGS_i@v~@ZCEHCHE@;`4* PP[ixM0<m@d?V~0V/  xRn)I$g7~`eB)'< > % um m f c3 an a f k r: yd  -4 743/L%e~ u N .! D Z n N  G a   *b 4 =BNGJJ,JGdE@9.1*[  Dl,n]XD.)cD{3gVB43"Fn)j1^1pP2 1EYl=Zx/Lh-Hf "8>Lhbs$X?}>V8&z#qy`N):&5G]oYuE1/ BSZTB b # ^ 1 ^  " 6 J ^, tB V e q {  $ ?} Xs sj [ G 3      0e A9 R a p }f *   i $ GWuWfWFK5! 6y_qS5D*qmL*`WbZD& iBo[wE73"I{N"jM1);J^o !8Ng}4O m/@O[hBto~.bA>yo eNVJ;+,x ^QGs_L@8$?:4$tyqjZc`^2[w[^c>jyoy'[ < _  0 G _ x   ( - 2 2 @/ ^* y    . Gn ]K s& vE h,!#n#+#!Z8W u+}gNG5j"Nt Y;@H vZBf)2qGyl`hVJO,GB@@@BEJQrYf`\jUvMFCAAACFKR$Y=aSkiw%;O,eEy^y3X{$.5:A?kBDDDBM?~:5.&L &] B~~0ml^L=!/_ O;tK>k ,Om ,=Qe{  $?Vn|\;f&57IWfSuQ |2K}]pdWhF5#q y%s2V5FbjG"J MqN)n< eGg,D$rayRoEh9c/`(` choy (/93CSOt\ky 5b#W%6G4Vogy$e&k>`&+0B58:%:r::8[853I.+&9)ybK*rI U  K O ~  . B= U] ix  9 V t  D i e D    A ar >    P  ; Y} w3 B;)!3=]BGJ)JJWGE=6,: `;ckM2#S'pMf+PxLV3^AjL,KTx,bP?.r^J;/##-9J\o G&o.8?I!PSZbiq0xk,rL5-}v1ndZDND5d)( Y&^~g3VB.s HZ+ym\aWOH@< < 9 7K 4 7 9E > C H, Oq Y c p5 ~p <f1Lg*8@GGE:=X3v% *~GWh* U   $ :L N ` qe   h   X 6m5_Ck{i[)I8T&Q*tncO;`' cz/_j}3xvssmsCvx}pU<& 1EVj{#7"M0fBQbn}EjDt D}-k/r{?n`QBd3"H3!s{jc[L;V/ D-yY0s7u"YBj '6E T! c5 oI ~X d n u z } z u n d X F "5 . 8 BIQVXg[@[[XVS`N,G?8.P"ZQ~eJ@1s-`bD$O Lg G) Tu>h O9#xI{V3o[G6% 2E\r,6;OLg^r+"B?X`n 0U}(*T4;ELQBYv^cehDjxmorrQrttr0rgrrooForrt#vYy{)[Dn -Mn$5G[n '/6;(;A;Z9s4* 2H^utU2 d8 "v)B16;@yEHGJLOLZJ+E=6)["r4{p=R4BiMAa+sIX)oEcE'x S+ `rEc'YPF>97444u7h<^ATHMPEY@c>p<<<>@EJOW^*fBp[ww3X}! N}'1;@BrJQY `=eojoq t=tqvvv v;totqo l=gqe`[ V<QpLE@873h.)% ,^Ix-Z%,3;;E\Qy[gt8L`q~5Ld}~tj`/SJBe1 ~$T='Vna+ G! 2APJ\iuw*AN[ nui3ZI7H(_8r1}iXDK0 X.yt]jB`)VOE=6/'" " 6Le ',4;$@IGnOT[c h7oav~ Q'`?z(cTLyohE^QG;D/"?}4p$^vl _DU}LB8!0U&!Jt   3Vv$+ 3! =5 IF SU __ ng {l l l i d _ X P F : +  ' 9GYhve;|Hk0s0[r }+t8`O;E'U`vm]D+7]jOV6k4pDwhYM>2g%I1 #-7CO\hu)B[3tOl)Kn=XqeBF" n?pW>%oL.z~utnjkek`k`n`pexj}r~3L%g9Of|+Px%;QFepy'Y"+VBUi}0iRE={ *49=yGQ[=c}hmrAvy{~E@{)b AwCo$.:G S,`Ilg{  + 5 < ? #< 2: ?3 K) U _ i sz{]@|M|Cz pdW]I!:(j,h%gWN3IEjL/L`}'_D& Rdv:`J6"{[=o^O@4* " *1'96BELTYceqt3$I3b?{LXdnx:Zz%Hm,T{Is"O{.[ ( P%x*16=E9O^Yer";Tg{):L]n +AWnv`J1 rJ #%*--s-D*%  X)h6fMn5= {O"bB~Y4e=sW?Z&3`=pY@-&:Nd}TC^FjCvCA<72+#&8L]n_={Q'&7IhZ4kzPQBv0`Hu0g$}kWjF12 U gnCHJM{OsRiT]WPWBW0WW WWWTR~R[O;JHC>7~/W(-  }M])uaKc51qBiN0`3 tmTH4#lkLR+: # jL.}xrvYvEv/vx{}}xuus(u:uKx_}p4Jc|%4CR3cOrj8Uv"1@O[6jVvvBd:\!+3=D%NHUf]gnx$B^y )8,G;SJ]Yghqvv{{xvng]PD.5B&XnqQ1( :M_pmC_0d0#*/4[7%7974N2-( {JW*sZ\5F-sXBq)V8hJ,gN5':NbqxeYLB81)-%K"i  %'<,Y3y8@JT^g=t^&Ii!3 B,PO_on}3Sv 5Us"',/1/4M6k6666641)1B/[*v'" !0?KUbis{}qdUD3 vV6rE",6=J\Q+[eoy]&Gd+Lr<pAe=oQ{9o ` QB4"xiZL=.';Tj:]5ZHrJv+)8UGSbn}6cGs -'Z4@LVc;ohy@l5Z 0Pp*;M^myyhW@*\7    U$J"$&)^) )))a))&$S"=n +^TZyhsY=J 9*rEwU2q]I3n_PD:2y+g)Y&J&;&.+"05 <FP]ix7Up *%L1m@O^o~$Iq?i+BXnEr) Y 4G[mL}Ev Bv$.8?FG}NSX]H`|bbbbBbqb`][3VbQLGB:93_+$  ,Mh").11.,)"~{{yyvvy~y`{@{ ~_5vBg.CPX`%s:{reYY"L@1"W(uK&s_Lv5V!8 vctOh=[)OE>4/'" ~"u%k*f1a9\@YJYTY^Yh\t^ckpw$:Qg},@Vl+Fa}5Pl2Ru/J cE~g$ I$q:Qg} 1V~ Bi#-7?I(PKWn\dins x-}Jh}'z6uEsQn^igfqay\ZUPMID?:2{-t&g[L= ,~cE( iI&vlbXNxBS80+`@ ~mlYPG54  o{^bOL@53' {eO8" yhWE4 % '.8BOYeo{+:GUbn}*9HWh| / @3OJ^^ot+B+U=iN}bs ,;&J7YIhZtix$.8DNXdn{nZD+ &2?KWdfDs"mG }S) Y.%(-//f2>/-*(#fF&n[G5$p\ F0bG) t,T=4N`vxZ:!<99"m@EJOW^?hbr~(Ii ,(=EOc^o.Jb~ &3? L!X8bNlbvv !#&(&#iP5vO)T%d0[$"~,E6 @LVd`+jvLu> xF&.i3B:?DGLQmSOX4[``bddbb][rVhN^GW?R8M.K&KKM PU\fpz{oc"V;JQ=j4' 3Sq7Z9a'OvGqGr *"1N;{BLT^+eWov-W~"Lt +Kl+AWnytohcz^fVPQ7JE@94/*b%= o B OKq:`*U![)}wvJn#g]ULDf:F0&$n[I8' ~qeYLB6) )8GVev 2I_u .@Qct#V/Y#^` eglqy~ -$<0J=\ImUdq3Og"1BQ+`Ird,Gc~ "+8?I0QGX``vdlqsx{}}}}-{<xIvUqalndx`XNG=3&{jVE1 {gS?+zqsckVdJ\=U3K)D :0& sdSD3%.8BLYcor{[E1}!g3PD:U$i{vcO%;9'J[m~wmc+\:TIMVEd@q>}97444479<@EJ OW!^+f5p?wKU_fpz,8GVcq~     !.8DN XblvsaM:& %{,`6D@&J T^hr~rQ1gG$ $3~?^N=]ixkM2 #x-d7RAAI0R!Z_fknsuuuxuupnid_WPF<2&  #2APaqs]I32{Ec\Lu4 %=YlqXB0 $?Zv{ t=l[gvc^[YYYY8[S^n`ejov~-Id}(> Rf!y.:GUbn{".8ELT[`eggj jgeb^"Y'T*J,B/81.1"11//,,*'%~"f M4 nM0iD"oL*}]= cE' %*16;@wGaLJQ7V#^chmrv{xpkfa\ZWWUUUWZ\_d{ivnrsjzc[TJB9/% %4CTcuxndZSLB,:@3V.j&! $ =Un *E`{$).5=D=LXSsZbls}7Pi/CTfw"*19@GOV^cjrv~p\H4sW<!nN0  oO/"$&){+_.B0&0 333330o0V.@+))&$uh\OC9/%thYJ;* }lZ G5$ (-7>EOYcpqyeVJ@6," %6EVgy !'51L;_GvT`o{ ";Qh):L_ q"8Ndx '6E-Q?`Pmays    sdRA0 l[G3 yeQ;' {l]N?0! ~vogc[VOJE@;~8o3c1Q1B.4,",))'%%%""}"l"X"D"3%' ),.36;@EJtOeTVYJ`;e.l"t{ &5BP_n}  )6BO^"j4yEVev .BS gx$0=GQ[blqx 1@Q`r}vn"g+]5S?IG?Q5[)bis{r`Q@1 }qbXL?5+!xnbVI=0" $+5=G~PjZVdEn1x {gS?+  *4=GQq[`eQm@v1~%  &08BLS]gnx%1;GQ ^gt $0:DNXbnxxiXG5${%e1L;6GT`jvnU:!$5oDVV=d%suaM<#*5DUapzupkiifffiknsu}xfU A-*<M^pv[B&  "6J`veJ/5NniU=! 6Qjq`L;,  $B]{:Rk-E^t .= JVb'o1y=GQ^gq{~tj^Q B3$!)05=BIN|UaZE_*glqx}z\<vS0[9 %/l9LB+L V`jtoQ3w^E/ $.5=GNVu[fbWgKn?s2x(} }xsnib]VNG?8.&  &0<FR_nz{rh^T#J7@J6^,u"6Ql5Sq *Jj &Gd5P}n}}}}}}}}/}C}T}h}y}}}}}  yhWC/ 'p/W9A@(JT[emv~{bI0t[E/q_L:)tg[QEt;e.V'J;,  vdSD3!ylcYQJB;61,)' '%'''3'=)J,V1c3o8{@ELT^gq{ .?N_q)8GUds%6EVet ,6BOYcmv$+38=BDILNNQQQNNLGD?=83 +& "$&+.35:=BGINSXv]mbcgVlLqEv;}1* }{xvsqnnllllllslil[lNn?n0n"nnnnnqqsv~vjxV{B},}gP:&lYG6% ",4=|GuQm[hhcr^{YWTROOOORTWY^chp&u0|:DLV]dnv} '6BQ`o~&8}GvXlibxXLB5&"4EVhyo^L;*"3DSdsvbPB0+5AK~Uq_gi[pQzG@6.'  }skaUK? 2&"',3;BJQq[]cLl8v$mYB/$3?LXgvsdUD5&  1@O^o~~ytlje`^[Y$V3VDTSTbQsQQQQQTTTVVYY[^&^0`:cDeMgWg_jflnouqztvy{~}zupidZRI?2( $n0[:IG5P"_lxycO9" '9J^rxdN:& 0DVi{o`QB3' -:FPZdksz~|yywwzwswkwayW|K~A2&xbN8" )6BjQQ^;l%{ s]I&5:!Nbv~q1eGY^LvB81' . D[q-?Rdu   %,18@EL#V*^/e4l9v>~@CEEEC@>;7/(   +5?LUblxnZF2}dL"3/;JVcr~eL1gN&83= IV`lvo[G6"|pcYOE<4*# vl`VI=0"  #(/9@JR\ftrh|YL@1% ,@Qcvxng] S!L8BN:g0})! *E^y0Id} #:Pf}~{yvvt#q/q>oJoWoaokoto|oqtvy{~~tkaWJ>2%+8GUdszfR<(,=O`txbL3.=yLc[Lg6v  q]G3 ygVG6'}qbVG8|)rh ^WME>72*%r `O=, xi]#S(G-=43<)CJT^hu~ 1BVg{ 3G ]q$).5:?*G@LTPhU{]bglqx}$3BN]iv ',4;@GOV^hov{slb[QIB):038+B$IQX]diqv{~vohc[{TsLnEg=`6X/N'D"=0& tcTB1"{vsxnglUgDd3b$__]]ZZZZZ]]]v_jb^bQgGi;l1q'sx}   '/9@GOV[cjot{~ )3=GQ^jv{ vo.jBcS[dTxJB91' 1G^tx+lB_XSnG:0$ -AUizytl gc[(Y/T4O;L@JCGHEHEJEJBJBHEEE@E;G7J2L*O QT Y^cgltyzfR?+x` I0!.8DP]ixoV@'x bN*:6)ETcrtg[OB$83,D"Sbq!0<IWdnz}pa RA 2,!8ETcqs`I3!5I_vv`G/,E[tnX?)3LbxvcO8%#7IZizwhYM>2%    }n\M<+n[D 0-< HWhwvcO;'  6Lc{n]N+=D._{;Vt~tg^$T?L]Bx;3)"- F_x#4ETcr~ %,3=GQ[eq{whYJ$;3*DS dvkWA+"4ETevqX?) $0j:QG;Q%[ dls}s]I5 veTE3%{sng]VND:3y)pf\ TJC<4-(  y ocYOE ; 1 '  (/7>EOYcp|}vqib%]8UJN^IqB:5.&! !:Pg %=Tm 3G[l!-7AKRZainsx}+8GU}gxvskd\UMF<2(*=Q ey+x=iQ[bLs=. !+t5c<TFEK6R'W\_adddda_ZU{PlK_DS<D58++!  vdSB.yq jc[TOGB=m8Y3E11,) '%" x g"U%D'5)$,16;@GLT[elvvoe^TLE@83.)$%3 DSds  *;L^o"').38=EJ+O8VB^NcXjbql{v+8GSbq}/v@nQg``rXNG=3)"$3BQ`l{vmcYLE;1 ' !#(+--000--+(&!}vn g_XPG?80)! vi]NB5& {m^O@1"sgXI=.&3?yLlZcgVvL@6,"%6ETct)3=DNV]dlqv{)8GVgy}{vql+gB`XXnQIB:0&/ Jc{)BX{nocVJ=1% &7IWfuvlbZPIB:3+$ sfZK<- xdQ=&o[G4  !){0i8X?IG8P)Zb nxyoc YO'E6;B1Q'` r )5DSbn}!&+-02555520- +&!)6B O^l{v)g=VPGd5x$'={ThjT@, 5Lb{vgS?+!2AP_{nl}^L=1"|umfaYTOJE@><97442x2k2_4R4D757&9<@CHMRW^f{miuV~B.yeO";3%EYj~iUB).?Xq ~'lB[^Jy8'=Xsypf2\MRfJ@94-(# 2CWhy %*/7>HOY c p| .BVj~~m\J39I%b{u_6FL-cyx] B&0 BVdvjO4}d L3#&+-00q0[0E0.0-+(#!y fTC2 z}nsdiZ`RSIIA?:52+-"&# !#+y0m7c?YIOPE\;f1s'-@WmxnbXN B;8Y+t! &Db =^{yqjc[V0ONJiEB=;86 3#3<3R3k3668=@EJQV%^4e@oMvWakt|!3DUgxyrkaY"O6CG9[/o# "0BpQ_]Ml<x+n[G3 {hT@,xdS?+xl`SD8) {l[L=. ~o^L=, ~xyguXrIr8p)pp pruw|ylcYLB8.%% 3ETev.BUi{ 1 BTc%t.;EQ^jy " &..3?8S=g?{DGIIILL I I6GJD`Bt?:53.&".? Sgx!-7DMvUo_hf`nVuO}G@9/'  zunf_WPF?5+ {vqnid_]XS}PnL`ISDDB5=&:530.)&$$!{j[J;* !!$&).0s5d8S=BD3I!PU_gnx{j[J;, %4BQ`o~wk^TJ@92 (#&8DSb q }   *7CTfy "8!L!c!v! $:Pg}*=sTdjV~D5$.DXnt`O;'(:IWfsq_N=+ tg[OB6,  zn_PA2!{dQ=)yhYG6'}n ]L"=..=JYgv vl0cGYZQqLE@83,%,E^ t 8 Qi 2%F)Z1k6=GOV^goy#-4;@EJMOO OO&O5MGJUEg@x;4/% "1BQ`o~}kZF5!  {&d.N88B"I Q[biqx}jT;%vbL8$ygVE3%{qugk]aQWDM:E+<4-%  tcQ@/  #v*d2S4-#&0:nD\NKX7b&lvs]I3 o[E/s_L8$veTBv1i [N?0$uh^{RhHT>@4,*# {gUB.  ~o^ O(@21<%HTam|)@Tj $=Un ".;4GLVce{t.D Xl.}?Pbs +5/<@FQMcRtZ_dfiknnnnki+f:dGaS\`WlRxKD?7-& sgXL?3$ ~ocVJ=1%vlbVL?3& vlbXND:~0m)[J9'sbN=+~o`QE6) ~$y0w=uLuXugws| ,=L^m~,;J[jy $.:DNX `i+q?xS}dx%9J[mxqib[QG&=83I)[l} tc(T5BA4M"ZfpzsdUG8)voe^TLG}@p8d3W.K)<%-      q[D.  mT;" %,16=EJlQS[:c!j t{{eQ;'.=N_n|pf\TME>92'-=%Q h{ (/)7?>SEiOW^fmw~&:M_s"3EVev  *4;CJOT&Y:^La_aqccaa^YTOH@9%/6%ETcr~s_K5 ! "+5?IS]gdNn5veL1}dL3v`J3  ucTC4% xlbVI=0"xsnkfda_o_^\J\9_'_adfkpuzvdSB0(9J\yplc[TLE= 6".;%Vo 3Pn 'G h%),3;B$LBVb`lv-Id+(8;GOUcdtv,9 GVet  "+8BN|XkbYlHv7#u_F-gN3hL4v_G0sgXI=+vcO=, mYE1uh\RE~J~W~f|r||||~ 6J`t 0,I;bJ{Yj{,E^v +=N_q5I`v 1B Tc(r7DP\fpz&5BN[dq}zsi_UI? 2&! &-27<AFIMRsUbWQ\?_.aa ddddda_\ZoW^RLM;K*F? :2+#xiZL=0!{iXD3 yto^eE^/TLE=6.'"nU=& lYB. ~ r%f,\3R=JECO2(iS:$o^L=. *7CO\ky)@Tj%~1@L[gv !:Sl& 89GQXmgx8Qg,9GVco-~?Rdu$.8B#I(S-[/d2l4v4}442/-(% zk\K<+n]I5"o}[qGb4V G8&n]No=Y.E1nXB{+qg[QG@6.%q`O= , |wrmkhfca^^^^achmu'|18BOYco{,;J[&j8{IXi{$5GX%i6{GVhy /@Qc t".8BLV]gnv&{5DSds #-x7sAlKdU]_VfNpDx:0&reYL@1%zp f\RF:-!xqg]xSdLND::$3+$ jT;" {dL5 yeTE3% $)08?DLU]dlv  ',48@EOQ[`hlv{+)85GBSN`]li{x' 1=JT`!m#v&&((&&#!  +5?IS]gq{qbSB0vcO;'nZG3~o^sOg@X1I":)  vcO;%|ywurpnpZpGp5p!ruwy|tg[OB8.%  '3@O[jv  '18)B=JNTb[seoy"6J`t$3?N]lx.BVi{"1!@0LAYPh_tn}$.8B L V ` g q x sdUD2!q]G0{eO9s"g [NB3$q]G3 vcO;%veVE6' lXD.~l|[wJp8k)fa ^YWTTRRRRRRTWY\a~c|h|m|r|y~~~ '6EV ev ,8ET`o~+?Sg}.=N]'l=}Tj .1B@XQl`r!0 ?M&Z5fDsSbq&2<IR_is}}pfWK<-lXD0siZMt?`2J!6  v`nIZ3I8&mT9 ~qeYLiBN85,% t^J6"ymcYOHC>94/*(#  #%- 2'91@;HEOOYYaekor{|!0"B1PBbQs`o'9J!^3rDSdv&:I [l*}9JYhy!+5?F.M=UI\Xadfqk}psuxxzzxxusnkf_!Z(R0K7A<:D0I&MRWZ\_aaaa__\vWdUSPBK0F?70(! {hVB1 vdSB0 n]N=.o[G4 tj`nVZOIE8=&3,'  ylcYQJB;61,'"  ") 1"8'@)J.Q1[6e;o@yELT[cjt{+:LZi{&3?LX d1q@}Qct"$/0=?JNY[egts+8DQ]isxl`SG:+xric[VLG=9.* yeQ=*xlbXND:3)v!bN: )yl`TG=3)  %.6=EOV^!g&q.{5=DNU]gnx !+8DP]iv ",9EQ[ht*6BO[er~$.5?GNV]d)i3q?vI{S}`is}}xslg`X Q I?5+"  teVG6'xi[vLg=X+I: +yeQ=*~tlc[TL{Eg@U;B601, )'%"  t g"[%O'B)8..3%6;@GLTY`gov ! .:GU%b,q3};BJT^gq~/=L[m{+8GS bn)}8GVds /;JYet(2<FPW_fnuz $0:GS`lv}xpiaWMD:0#  {iVD0 t`J{4n`QB3$qZD0vcQ@,o^L;) vdSB0!|rkc\TOJyEo@g>^UQnjWJ2b@ !YQ/ I _*x74m[d|OT dPb2e B]h_Bq~9jWc`8E#(084*3Gk$\ w v  68  L n UIP57- q0+; M l \  iC sx_C :&F/{2d*kQrZCb)8 z~([[Ao3p/j=^[D!\  `TQzDJPydQ#IFB`BpVrcm Ifn W{rCW*0xudPr59 uvZOL$Qsxejn ߎ*sOt8&06ߩK{oWB/ #n X^W F (jnJdlkp@9t@} "   >'cVD&]d SH ( \  -) } 9  *L   v0C7KAc u x mT5X0z W3q.AK U M 8X    AO  p { u2  c T D   Q  D3wqM&Bm?  t- :X   J~iM,&^F4hY o1$dP7nlaL!3Q6.J&#9&/c:?`>}:RCFUX{޲(ZݻQv!< ܸܩݟ)ݔH݊h}ob\^Xkފ2 zpG'm  zp3<zW. +w#DZ!6BPg@y_5 =  {g /J 7 'F   K :   \: x   dP #  ~XF     u S .  x T l 3 H     dh 1  N  _E  O  (J   ` O / dT-;kL/)sK M % q  b .W A|(itR7Pp!-fR/ r>;{6LSWCtQ# H8Ldf]>k`-~ i-SS\$nn'ߎQsdd߹lߪߝߕߏ߆|'qQgccqclX7|5b@%JKZEx,W.I Hp3BP!oW@$ o  - k5>5 n   ae   Y ? u K  / Dp  }  {C _ ,o gs k V =     x ah LB 3!     ]m ?  u  g 3,  6 v &:  Zd#L|0D r8fF)J L   gM 6  U i=couyYp2]KA>$pGT6@TU;'mnF0Y7GVl+?` 5pD^6k"g7tL+ ,Px)h"] _x=^O|IbXJaS!go HY )lG)7a*edpQ9e8`OhvJ>ZMCut S*>FC<0)&u+7]G[Nm}D  By h CN .@ (NMu F p .    ? Ym   }  )0 pC I G 8 #      ] }9 S )    `j #D  JT/Xkr3j >g; z a @a " C    brO7)wLiK2 Nlax3%yU$y"pv:mV^HQ]J ^Z ] \b?m4=~5YW<XC_t1g gt7k#n1?JV!=QM >Em63CTh*!uW='   j A dx9<=kF : A_   n  $ mN t  O    ! : D Dz 8Z #7     X (h F % FtV#&o J; Yho6~`8!a 5     ~ p [d G2E"kqKD&Ut{]B4"@s<BA]'K  N  H |:iV$C.yY6tP /xGm$fI%,'v|D sq?e Zk3SB]{6Wg= 3O< ZI 9aY+dw8g`gw%f|zFwwzT:[!byFB"mb< #ho ^nWXMdvHJA!U~d H-X +  r cE .;ON= I:d9^ ! /@ da      9 N ] e e ]h JF /# r6sQ.s 2ce5}'ds+FPq$iBB^ x   b 8 2  ?  oD N2?1pgOH$*d/hQ:J% RMd6Bm5:'xm;qbx'6o0pVp-NYh)wu[= Dn@uW>+%b =C6\K PfB ,ox+Gh@kWN=}@liF!2  f l -= K2[nJ s#IHkP <6 bQ j }     n W :  f8fE#I=i=dyqB _d.2^g;< _  Y} 6  %  9 i AF KF6p]H1rN"nOU0t'~$hwF!ikX8Ir?< 9yDOg.ozg;rK.v&o= d2_9!W-~{w.wwy[T<'a.kuK)4lj9&p`L0B2MLAj+ )H[.  m  4 ] . R tb"WbeAR|' .FMi9{  )! @8 OF [O `Q bJ ]> W+ M <% dA^$e mFKg`)lMU.zHa# wL S -p     q; G Q \_iPW;)E+ wNlI'CU{fOT8G4d6lt F]VY )k5`*~LCl6=q}EK#iN7'@y Y e) -Rr7 7yr:Juz[K'; f-FF^r#{zmUU1h"k8 ?   `Q   r] q>dF&3kB@0Kb{X      qmMI$&NvR-@`Mrwq?^i5>u} U= - j   ! w RA * [ o_z>yoY<y`E%Qw}1_F-6-|{fX0Nz7L'|j/>V/\*_4+^`W/f>^92^~t$nxie,a_]M]_/gvA[.=w8uzKPwP 7V)-8jOg=y   1<(y ]\"YU1x*AZ,q\oT6yX4_-a=<crBz)o28,ax-^ j >5  f   |% X 2L  l nDs`rO>P+$S}[k:qhuW\?;kR&Xy[O'|SX=,9KpBseY/nG'wZ= $7'e0_O>[WoZGE0+w W~V-:.[6? vy`T,]l]019b@`@'0sMbwTIC@=;7M442{22a4;uGZwV3-hyJH|KkYTZnj~$I}YW(SEL   T\   [ KP90SyDFe-:[uL~0E Zi&y"}onVF=yMr!N*z9l]@n{Gz*k57: h 6.  p   VE . t   / nHM et\w8r^?wnW<<LM{^C@,)u StR0/z ijDu;sR. !TvN([w^WD8628IdNXp!V -8 h DqxD =ooYP)RtYgwv0yb:@+ym4i ~ A k  s j%tR)*m1Gn!^;a-[ . ? KV\^ZOi=@(sGkH$~?llB0T?zLDQ p >H   -  Rd &  (  O _7m uM%yZr_-M:'U ebbC#S9at]D=& !tySy/ ;otP0}6k1J(uI% uYB-BuDV'$f6SwmQ39nz2Q`-8{ g m hrO=3 Z  ( | \ !pl  P45`oUW?Ja~| .I`kmd&T.=460&iDmJb()g rM!9Gg4P]U&I Q 1  j  Z ,2  Z  ~{ W //l4E,hiM39_mkkK, Y;r__N;&;o`s<3ugkPn4$inPS7#wh+^bUOM@MOS`UWBY[B^dfj yv? ;kqQ/. ZK~~]TDrP'#l_ H&   4t 3  #pSH+9 I 26l N;Y,rZ~ g I(i;m L* W{9U+P{\I\xBQ 6j 6s   @ m =h     Y6 /ITfU>I5}Y~6Nr*wb-K0lNeN(9p&L0'fH)= ygglP8! ] {>| cL5!YBo`pK &]J7r*VoS9"1bV :#l>vG  W o 3 ;  o!"js9x).iDD3wz6k/H_t sR.ivJ;* y2`P8abf2\a-BU N  z  T $0  N  ed 9 u|fy>mR{0S/ i0yGbM:M&@&nmP5I%oSyJdK1[#v{udR=(Td#xeuRm@o-z D7~ } ."/y=/PimO5& R {!MyuidfRks}#oHpZ<S X a#   =v 4`L&eIW _M{;w '7BJS][m]~YQD4! V|$eJ/t1YnHu#&+~PycT:l}G .  S u Cq    ~ N% .-nE! |}WU/*U{^oC* tiPtV;.w S7tf(U}D4. U0 {g'P=E*z @zvmgiYoJ~;1( Ya$+A17<@FNNT{_n~~? ?i~jWA)8`T`6{@e:  D o 5  ` w-<!D@;,b96d"b96RKgWz`bb[Q@/VmRa5Dn\H !e oUA5rl;0 `X ) }   P(  =  O PVV^K26[1Z )kQG# ei~ e[N5D(tpU^>'SWvFs\,E0$6^J~}rIeYLB5+ G}n ?2(39@HXTev7vN .4`8btX>(P V-t>^- B   Q X  4<{!F;72i9<n^;Yv/>FMMKB4# m6~;mN/j 9}S)>'o;c1c+\   I 5  Q g 0g  y Y$yU%dJl'>c0h?T feHg- \KnQ9100q@`P?m.H6;Szg&YJ|;7/"jK4%!!)F ~   Na   'p<@160m} @7rM(~Np%2: >:#4,%48:82(K YeGF"el]/Wm.6_Y A  na 4 }   I  + i01-!W! ~^Y)9 ssE>_pHo$pilO1`\ y_\A(o1iMCr]NJ5n"Ki/{njly LT2" &-B8Wpk]6Gw  ?vk2> i H  !  Q?  V  Xh qcr'jsZ8B!Ogw8Cd~$N4f::99dE&>N ckD$6 |jmyj[MO>/!Z|W9" &@e%4gDW'l|w 5T?vZ%R|1`j@ ?v^@!&b8jfF9 PN   p ^  l1v?C^c-P`lJ=vt2.OIi`}uoV6Nu\bA#R mnDl`R-'PU   _ ":  X d %q   e & g )un0_@{>\V'NPdWn'tw!Pw,+=eD\"&klRWBM2!Z~] ~A xg][_nII'@[w +8Nt;*bsQ1Q9Wr-\-n{aR@d(J^! ^  M % h T  7~: iM  Byg% w9e9n.Oo&AXisyyqbM2W p2qT2e1pF)m U@ow; .  S B q   @  ! |9&$v5s|2br?3{?S~](>RW#`\l."8iH&Y!}a^V$yoyg/\RIsAA;400.29?IVb s?y b&/On#DdkQ2 m)jhB$asOO-fQvV@1`Y   )y l'  v 7|UMKm!Jnv)Y?b.CP Z \ X! M' ;) "+ + ) %  Y & {<sb*?Bv<H YM gE * l  k +  , d !< CVA:H*<kv3Hq2Xz ?Ab+[pT!)Fc9k3bq@O:5e@K9`& ;SsM,? k2I#`p|$iD]jg+/[~4.mW/ 4ym?B~8y|\@J%4'vd7V 9 ' j D  3 x2nG'K-s*[!l",TQw* ;' E8 KF KQ CY 6_ "a a a _ [ kS ;J > /  Y KwTc,bRG"OE m  ` !#  ? _ T  a O k~k9dgX"HQ0 >^q3,ii*1wW<uZ5!V~LJpK%eO|CZ;H[k|vOrnligseZgIlCpCzK^w>2$TwR:<;hV.FxJ $gvL6#} PT*X'ppS9 "^UR? L ^  U ( k C;8F73ze%nA)f] / 2J Ca Mt R P E 6      g 7 } p a OO 8   ;JuK!B"g5U[ !=  ] g &w   ]  ! B#"m$Lps)X7Qy2T"aRYy=d*bz(@ Ul$>hLsP:, 2;UlP9$'v(`)ug`bm /D['tdFEooY_'WXPn,Ke':rPpE#h@lR+9'zcm, K_   l a  ^0u5>QL7&m4,X};r - M .l A P V X T G 6      g 7    I } d wH *)  3m%Ac/NZ ~ l / +  qC . T  __ d>c]`TD50Sph%DCeU!KSEKNQd-(wi?_STaaB"Vcysnjn8nnsw}@r/P7vAP#MM2(eP.wwK`"J|R('qQlP@4@=T' pP   F_   UZ*'jB;(cw%0p^7n < [ } ( ; G M M G = *      ] +   { :   c n Q n-  b`?2pg01 R  n D    =  % g*(>#Z  r$m:U6Ob[z/-kM>y 4vIn-p^4=#RrL'/]hMM6#k(]: +8#I@^bu1x9eyO.DeT vD}O5v^RwIB7tGmU{W7KPfR3@{ 3   gF   ;C O.'Ri0bl; v+ O p   0 C P V V/ P? CN 2V ] _ _ ] V iP 5J A 5 ( B   e   j _ : Z 0^a, T;  S  df # t  V} |1{Ks^gWnC{-)3`=;HWY -s*nBR DdGG1 !l; !2pRO.'w&Rskc`cbgFm2u%!'4D]'GBh$NQF2Qop'hA1GzgT%f{eP$Z{MW2KYi >b  []   B 5   b6v6 }%D k2i#y PD h    0 I \( iC o] qq k ` R = $     W   z ^k Z H z3 (  z   dr J ! 5a`, 1  JD  S  K]  a w.baJ[[R Fi6n" p}apCo"mmHn!w(iE@ fqXRF:U9@QV'zSuX=T$ ~D u`SQS]l0G`~V4.dW BHOAj 2O},/~e(01|Q=&?zQ>+I_]6 qqr6   _f   ?x ]b1r ,^fw+ U W}     6( PF bc o~ u u q i Z G .     _ &   d   | (i P x3   ^  } ,Q # UwV !  - r 38  ? l 'B AK=a8.l"qpv`hF]* O`DB:!8tU@9W w0zcu"zl66|gT. O^racU3L HHJS[j| 1_;`dUo Pm} e8@z&3U?W\/k{uN#'<iD[ wm+6 &z v2   \E  :+RVb[X;[- [  B |   ; &Z Az T b i k i ` T C! ** . 0 . * ]# $   `   u "  p c C O    { DM  d z  G    V    Fgx$}'wyg"Up@b+Mn4Vz=d# T~hLRQ@4e,+>2pC2]T!$_WjL1w6kH-  35PTlxT2eS$Oe CC}2$9H Tl;y 7~MO hw'P*Rw]-2 5?   (a u  XY 5|41E- G_   / n 3 V v  ; R ` k o! o8 kK ^Z Mf 6o u w w u ko 3f ^ S jI : * ~ *  v   S| V 1   @  ZO  m  z u :    =  j~w6m=cU8E,5t#\r<[{GV34 ul]^OPIPE_HS}6im0O_358iy.bO@6~.e'N'?.581E1W7oD[t 5&af_2q* >n,banh"/p^;+xVG{@f< pBzRu'8S H   C:   42jc8{ z1 j @   -( nP v   $ A X i4 uO {f ~} y o ^ E *    | D   { 0 } m 7Z E ,   Z   g = >  U  e J  n  s f *q  n e icBYTMBT6K&7x}kU[-Hd8+5l A{|s`nlPqN}`=;j|CD5fOE % ^2 0S{Aw3Mjc(m=)M(@>jE db/Y oBNxCV)xM$Y1e0|E J  < P  C H "5Lb\a! I]   j 1 ] F     &4 ?Q Tm b k o k b R = "    x @   w +   2  zy ` E S(     1i ; E R r Y <  Z  V M Q K?A`8,k gY|n=a|TQF:!.Q$Hy F ^(N@O^`UD:b?2j-mXoCM50*$"$*7EZv8^4b@ 3J`gD;YGan Z Q~+>wWS (LhBc;pNf!5J ?  \ S  ] CRx :'- M    >5 g   _  0 S s , C T ` d d Z# K1 9> F L O L vJ =F > 5 w) +   2  x   Oy X |6   '  :g 7 C  F d E + ?  q8 00_${+ .y|k"]hQGF:1O)!?g%Mx @+u:PRl@%?VU1 y#E 7xNt*< sXA0$!!(4Id"Lv!_QHheBV3:^[~

' + self.make_clickable_urls(text) + '

' return None def replace_emojis(self): theme = app.config.get('emoticons_theme') if not theme or theme == 'font': return def replace(anchor): if anchor is None: return image = anchor.get_widgets()[0] if hasattr(image, 'codepoint'): # found emoji self.replace_char_at_iter(iter_, image.codepoint) image.destroy() iter_ = self.get_buffer().get_start_iter() replace(iter_.get_child_anchor()) while iter_.forward_char(): replace(iter_.get_child_anchor()) def replace_char_at_iter(self, iter_, new_char): buffer_ = self.get_buffer() iter_2 = iter_.copy() iter_2.forward_char() buffer_.delete(iter_, iter_2) buffer_.insert(iter_, new_char) def insert_emoji(self, codepoint, pixbuf): self.remove_placeholder() buffer_ = self.get_buffer() if buffer_.get_char_count(): # buffer contains text buffer_.insert_at_cursor(' ') insert_mark = buffer_.get_insert() insert_iter = buffer_.get_iter_at_mark(insert_mark) if pixbuf is None: buffer_.insert(insert_iter, codepoint) else: anchor = buffer_.create_child_anchor(insert_iter) image = Gtk.Image.new_from_pixbuf(pixbuf) image.codepoint = codepoint image.show() self.add_child_at_anchor(image, anchor) buffer_.insert_at_cursor(' ') def clear(self, widget=None): """ Clear text in the textview """ _buffer = self.get_buffer() start, end = _buffer.get_bounds() _buffer.delete(start, end) def save_undo(self, text): self.undo_list.append(text) if len(self.undo_list) > self.UNDO_LIMIT: del self.undo_list[0] self.undo_pressed = False def undo(self, widget=None): """ Undo text in the textview """ _buffer = self.get_buffer() if self.undo_list: _buffer.set_text(self.undo_list.pop()) self.undo_pressed = True def get_sensitive(self): # get sensitive is not in GTK < 2.18 try: return super(MessageTextView, self).get_sensitive() except AttributeError: return self.get_property('sensitive') gajim-gajim-1.1.3/gajim/message_window.py000066400000000000000000001435771345766322700204040ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2008 Travis Shirk # Nikos Kouremenos # Copyright (C) 2006 Geobert Quach # Dimitur Kirov # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Julien Pivotto # Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import time from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject from gi.repository import GLib from gajim import common from gajim.common import app from gajim.common.i18n import Q_ from gajim.common.i18n import _ from gajim import gtkgui_helpers from gajim import message_control from gajim.chat_control_base import ChatControlBase from gajim.chat_control import ChatControl from gajim.gtk.dialogs import YesNoDialog #################### class MessageWindow: """ Class for windows which contain message like things; chats, groupchats, etc """ # DND_TARGETS is the targets needed by drag_source_set and drag_dest_set DND_TARGETS = [('GAJIM_TAB', 0, 81)] hid = 0 # drag_data_received handler id ( CLOSE_TAB_MIDDLE_CLICK, CLOSE_ESC, CLOSE_CLOSE_BUTTON, CLOSE_COMMAND, CLOSE_CTRL_KEY ) = range(5) def __init__(self, acct, type_, parent_window=None, parent_paned=None): # A dictionary of dictionaries # where _contacts[account][jid] == A MessageControl self._controls = {} # If None, the window is not tied to any specific account self.account = acct # If None, the window is not tied to any specific type self.type_ = type_ # dict { handler id: widget}. Keeps callbacks, which # lead to circular references self.handlers = {} # Don't show warning dialogs when we want to delete the window self.dont_warn_on_delete = False self.widget_name = 'message_window' self.xml = gtkgui_helpers.get_gtk_builder('%s.ui' % self.widget_name) self.window = self.xml.get_object(self.widget_name) self.window.set_application(app.app) self.notebook = self.xml.get_object('notebook') self.parent_paned = None if parent_window: orig_window = self.window self.window = parent_window self.parent_paned = parent_paned old_parent = self.notebook.get_parent() old_parent.remove(self.notebook) if app.config.get('roster_on_the_right'): child1 = self.parent_paned.get_child1() self.parent_paned.remove(child1) self.parent_paned.pack1(self.notebook, resize=False) self.parent_paned.pack2(child1) else: self.parent_paned.pack2(self.notebook) self.window.lookup_action('show-roster').set_enabled(True) orig_window.destroy() del orig_window # NOTE: we use 'connect_after' here because in # MessageWindowMgr._new_window we register handler that saves window # state when closing it, and it should be called before # MessageWindow._on_window_delete, which manually destroys window # through win.destroy() - this means no additional handlers for # 'delete-event' are called. id_ = self.window.connect_after('delete-event', self._on_window_delete) self.handlers[id_] = self.window id_ = self.window.connect('destroy', self._on_window_destroy) self.handlers[id_] = self.window id_ = self.window.connect('focus-in-event', self._on_window_focus) self.handlers[id_] = self.window keys = ['f', 'g', 'h', 'i', 'l', 'L', 'n', 'u', 'b', 'F4', 'w', 'Page_Up', 'Page_Down', 'Right', 'Left', 'd', 'c', 'm', 't', 'Escape'] + \ [''+str(i) for i in range(10)] accel_group = Gtk.AccelGroup() for key in keys: keyval, mod = Gtk.accelerator_parse(key) accel_group.connect(keyval, mod, Gtk.AccelFlags.VISIBLE, self.accel_group_func) self.window.add_accel_group(accel_group) # gtk+ doesn't make use of the motion notify on gtkwindow by default # so this line adds that self.window.add_events(Gdk.EventMask.POINTER_MOTION_MASK) id_ = self.notebook.connect('switch-page', self._on_notebook_switch_page) self.handlers[id_] = self.notebook id_ = self.notebook.connect('key-press-event', self._on_notebook_key_press) self.handlers[id_] = self.notebook # Tab customizations pref_pos = app.config.get('tabs_position') if pref_pos == 'bottom': nb_pos = Gtk.PositionType.BOTTOM elif pref_pos == 'left': nb_pos = Gtk.PositionType.LEFT elif pref_pos == 'right': nb_pos = Gtk.PositionType.RIGHT else: nb_pos = Gtk.PositionType.TOP self.notebook.set_tab_pos(nb_pos) window_mode = app.interface.msg_win_mgr.mode if app.config.get('tabs_always_visible') or \ window_mode == MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: self.notebook.set_show_tabs(True) else: self.notebook.set_show_tabs(False) self.notebook.set_show_border(app.config.get('tabs_border')) self.show_icon() def change_account_name(self, old_name, new_name): if old_name in self._controls: self._controls[new_name] = self._controls[old_name] del self._controls[old_name] for ctrl in self.controls(): if ctrl.account == old_name: ctrl.account = new_name if self.account == old_name: self.account = new_name def change_jid(self, account, old_jid, new_jid): """ Called when the full jid of the control is changed """ if account not in self._controls: return if old_jid not in self._controls[account]: return if old_jid == new_jid: return self._controls[account][new_jid] = self._controls[account][old_jid] del self._controls[account][old_jid] def get_num_controls(self): return sum(len(d) for d in self._controls.values()) def resize(self, width, height): gtkgui_helpers.resize_window(self.window, width, height) def _on_window_focus(self, widget, event): # on destroy() the window that was last focused gets the focus # again. if destroy() is called from the StartChat Dialog, this # Window is not yet focused, because present() seems to be asynchron # at least on KDE, and takes time. if 'start_chat' in app.interface.instances: if app.interface.instances['start_chat'].ready_to_destroy: app.interface.instances['start_chat'].destroy() # window received focus, so if we had urgency REMOVE IT # NOTE: we do not have to read the message (it maybe in a bg tab) # to remove urgency hint so this functions does that gtkgui_helpers.set_unset_urgency_hint(self.window, False) ctrl = self.get_active_control() if ctrl: ctrl.set_control_active(True) # Undo "unread" state display, etc. if ctrl.type_id == message_control.TYPE_GC: self.redraw_tab(ctrl, 'active') else: # NOTE: we do not send any chatstate to preserve # inactive, gone, etc. self.redraw_tab(ctrl) def _on_window_delete(self, win, event): if self.dont_warn_on_delete: # Destroy the window return False # Number of controls that will be closed and for which we'll loose data: # chat, pm, gc that won't go in roster number_of_closed_control = 0 for ctrl in self.controls(): if not ctrl.safe_shutdown(): number_of_closed_control += 1 if number_of_closed_control > 1: def on_yes1(checked): if checked: app.config.set('confirm_close_multiple_tabs', False) self.dont_warn_on_delete = True for ctrl in self.controls(): if ctrl.minimizable(): ctrl.minimize() win.destroy() if not app.config.get('confirm_close_multiple_tabs'): for ctrl in self.controls(): if ctrl.minimizable(): ctrl.minimize() # destroy window return False YesNoDialog( _('You are going to close several tabs'), _('Do you really want to close them all?'), checktext=_('_Do not ask me again'), on_response_yes=on_yes1, transient_for=self.window) return True def on_yes(ctrl): if self.on_delete_ok == 1: self.dont_warn_on_delete = True win.destroy() self.on_delete_ok -= 1 def on_no(ctrl): return def on_minimize(ctrl): ctrl.minimize() if self.on_delete_ok == 1: self.dont_warn_on_delete = True win.destroy() self.on_delete_ok -= 1 # Make sure all controls are okay with being deleted self.on_delete_ok = self.get_nb_controls() for ctrl in self.controls(): ctrl.allow_shutdown(self.CLOSE_CLOSE_BUTTON, on_yes, on_no, on_minimize) return True # halt the delete for the moment def _on_window_destroy(self, win): for ctrl in self.controls(): ctrl.shutdown() self._controls.clear() # Clean up handlers connected to the parent window, this is important since # self.window may be the RosterWindow for i in list(self.handlers.keys()): if self.handlers[i].handler_is_connected(i): self.handlers[i].disconnect(i) del self.handlers[i] del self.handlers def new_tab(self, control): fjid = control.get_full_jid() if control.account not in self._controls: self._controls[control.account] = {} self._controls[control.account][fjid] = control if self.get_num_controls() == 2: first_widget = self.notebook.get_nth_page(0) ctrl = self._widget_to_control(first_widget) self.notebook.set_show_tabs(True) ctrl.scroll_to_end() # Add notebook page and connect up to the tab's close button xml = gtkgui_helpers.get_gtk_builder('message_window.ui', 'chat_tab_ebox') tab_label_box = xml.get_object('chat_tab_ebox') widget = xml.get_object('tab_close_button') # this reduces the size of the button # style = Gtk.RcStyle() # style.xthickness = 0 # style.ythickness = 0 # widget.modify_style(style) id_ = widget.connect('clicked', self._on_close_button_clicked, control) control.handlers[id_] = widget id_ = tab_label_box.connect('button-press-event', self.on_tab_eventbox_button_press_event, control.widget) control.handlers[id_] = tab_label_box self.notebook.append_page(control.widget, tab_label_box) self.notebook.set_tab_reorderable(control.widget, True) self.redraw_tab(control) if self.parent_paned: self.notebook.show_all() else: self.window.show_all() # NOTE: we do not call set_control_active(True) since we don't know # whether the tab is the active one. self.show_title() if self.get_num_controls() == 1: GLib.timeout_add(500, control.msg_textview.grab_focus) def on_tab_eventbox_button_press_event(self, widget, event, child): if event.button == 3: # right click n = self.notebook.page_num(child) self.notebook.set_current_page(n) self.popup_menu(event) elif event.button == 2: # middle click ctrl = self._widget_to_control(child) self.remove_tab(ctrl, self.CLOSE_TAB_MIDDLE_CLICK) else: ctrl = self._widget_to_control(child) GLib.idle_add(ctrl.msg_textview.grab_focus) def accel_group_func(self, accel_group, acceleratable, keyval, modifier): st = '1234567890' # alt+1 means the first tab (tab 0) control = self.get_active_control() if not control: # No more control in this window return # CTRL mask if modifier & Gdk.ModifierType.CONTROL_MASK: if keyval == Gdk.KEY_h: # CTRL + h if Gtk.Settings.get_default().get_property( 'gtk-key-theme-name') != 'Emacs': arg = GLib.Variant('s', 'none') self.window.lookup_action( 'browse-history-%s' % control.control_id).activate(arg) return True elif control.type_id == message_control.TYPE_CHAT and \ keyval == Gdk.KEY_f: # CTRL + f # CTRL + f moves cursor one char forward when user uses Emacs # theme if not Gtk.Settings.get_default().get_property( 'gtk-key-theme-name') == 'Emacs': if app.interface.msg_win_mgr.mode == \ app.interface.msg_win_mgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: app.interface.roster.tree.grab_focus() return False self.window.lookup_action( 'send-file-%s' % control.control_id).activate() return True elif control.type_id == message_control.TYPE_CHAT and \ keyval == Gdk.KEY_g: # CTRL + g control._on_convert_to_gc_menuitem_activate(None) return True elif control.type_id in (message_control.TYPE_CHAT, message_control.TYPE_PM) and keyval == Gdk.KEY_i: # CTRL + i self.window.lookup_action( 'information-%s' % control.control_id).activate() return True elif keyval in (Gdk.KEY_l, Gdk.KEY_L): # CTRL + l|L control.conv_textview.clear() return True elif keyval == Gdk.KEY_u: # CTRL + u: emacs style clear line control.clear(control.msg_textview) return True elif control.type_id == message_control.TYPE_GC and \ keyval == Gdk.KEY_b: # CTRL + b # CTRL + b moves cursor one char backward when user uses Emacs # theme if not Gtk.Settings.get_default().get_property( 'gtk-key-theme-name') == 'Emacs': self.window.lookup_action( 'bookmark-%s' % control.control_id).activate() return True # Tab switch bindings elif keyval == Gdk.KEY_F4: # CTRL + F4 self.remove_tab(control, self.CLOSE_CTRL_KEY) return True elif keyval == Gdk.KEY_w: # CTRL + w # CTRL + w removes latest word before cursor when User uses emacs # theme if not Gtk.Settings.get_default().get_property( 'gtk-key-theme-name') == 'Emacs': self.remove_tab(control, self.CLOSE_CTRL_KEY) return True elif keyval in (Gdk.KEY_Page_Up, Gdk.KEY_Page_Down): # CTRL + PageUp | PageDown # Create event and send it to notebook event = Gdk.Event.new(Gdk.EventType.KEY_PRESS) event.window = self.window.get_window() event.time = int(time.time()) event.state = Gdk.ModifierType.CONTROL_MASK event.keyval = int(keyval) self.notebook.event(event) return True if modifier & Gdk.ModifierType.SHIFT_MASK: # CTRL + SHIFT if control.type_id == message_control.TYPE_GC and \ keyval == Gdk.KEY_n: # CTRL + SHIFT + n self.window.lookup_action( 'change-nick-%s' % control.control_id).activate() return True # MOD1 (ALT) mask elif modifier & Gdk.ModifierType.MOD1_MASK: # Tab switch bindings if keyval == Gdk.KEY_Right: # ALT + RIGHT new = self.notebook.get_current_page() + 1 if new >= self.notebook.get_n_pages(): new = 0 self.notebook.set_current_page(new) return True if keyval == Gdk.KEY_Left: # ALT + LEFT new = self.notebook.get_current_page() - 1 if new < 0: new = self.notebook.get_n_pages() - 1 self.notebook.set_current_page(new) return True if chr(keyval) in st: # ALT + 1,2,3.. self.notebook.set_current_page(st.index(chr(keyval))) return True if keyval == Gdk.KEY_m: # ALT + M show emoticons menu control.emoticons_button.get_popover().show() return True if (control.type_id == message_control.TYPE_GC and keyval == Gdk.KEY_t): # ALT + t self.window.lookup_action( 'change-subject-%s' % control.control_id).activate() return True # Close tab bindings elif keyval == Gdk.KEY_Escape and \ app.config.get('escape_key_closes'): # Escape self.remove_tab(control, self.CLOSE_ESC) return True def _on_close_button_clicked(self, button, control): """ When close button is pressed: close a tab """ self.remove_tab(control, self.CLOSE_CLOSE_BUTTON) def show_icon(self): window_mode = app.interface.msg_win_mgr.mode icon = 'org.gajim.Gajim' if window_mode in (MessageWindowMgr.ONE_MSG_WINDOW_PERTYPE, MessageWindowMgr.ONE_MSG_WINDOW_NEVER): if self.type_ == 'gc': icon = gtkgui_helpers.get_iconset_name_for('muc-active') self.window.set_icon_name(icon) def show_title(self, urgent=True, control=None): """ Redraw the window's title """ if not control: control = self.get_active_control() if not control: # No more control in this window return unread = 0 for ctrl in self.controls(): if ctrl.type_id == message_control.TYPE_GC and not \ app.config.get('notify_on_all_muc_messages') and not \ app.config.get_per('rooms', ctrl.room_jid, 'notify_on_all_messages') and not ctrl.attention_flag: # count only pm messages unread += ctrl.get_nb_unread_pm() continue unread += ctrl.get_nb_unread() unread_str = '' if unread > 1: unread_str = '[' + str(unread) + '] ' elif unread == 1: unread_str = '* ' else: urgent = False if control.type_id == message_control.TYPE_GC: name = control.room_jid.split('@')[0] urgent = control.attention_flag or \ app.config.get('notify_on_all_muc_messages') or \ app.config.get_per('rooms', control.room_jid, 'notify_on_all_messages') else: name = control.contact.get_shown_name() if control.resource: name += '/' + control.resource window_mode = app.interface.msg_win_mgr.mode if window_mode == MessageWindowMgr.ONE_MSG_WINDOW_PERTYPE: # Show the plural form since number of tabs > 1 if self.type_ == 'chat': label = Q_('?Noun:Chats') elif self.type_ == 'gc': label = _('Groupchats') else: label = _('Private Chats') elif window_mode == MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: label = None elif self.get_num_controls() == 1: label = name else: label = _('Messages') title = 'Gajim' if label: title = '%s - %s' % (label, title) if window_mode == MessageWindowMgr.ONE_MSG_WINDOW_PERACCT: title = title + ": " + control.account self.window.set_title(unread_str + title) if urgent: gtkgui_helpers.set_unset_urgency_hint(self.window, unread) else: gtkgui_helpers.set_unset_urgency_hint(self.window, False) def set_active_tab(self, ctrl): ctrl_page = self.notebook.page_num(ctrl.widget) self.notebook.set_current_page(ctrl_page) self.window.present() GLib.idle_add(ctrl.msg_textview.grab_focus) def remove_tab(self, ctrl, method, reason=None, force=False): """ Reason is only for gc (offline status message) if force is True, do not ask any confirmation """ def close(ctrl): if reason is not None: # We are leaving gc with a status message ctrl.shutdown(reason) else: # We are leaving gc without status message or it's a chat ctrl.shutdown() # Update external state app.events.remove_events( ctrl.account, ctrl.get_full_jid, types=['printed_msg', 'chat', 'gc_msg']) fjid = ctrl.get_full_jid() jid = app.get_jid_without_resource(fjid) fctrl = self.get_control(fjid, ctrl.account) bctrl = self.get_control(jid, ctrl.account) # keep last_message_time around unless this was our last control with # that jid if not fctrl and not bctrl and \ fjid in app.last_message_time[ctrl.account]: del app.last_message_time[ctrl.account][fjid] self.notebook.remove_page(self.notebook.page_num(ctrl.widget)) del self._controls[ctrl.account][fjid] if not self._controls[ctrl.account]: del self._controls[ctrl.account] self.check_tabs() self.show_title() def on_yes(ctrl): close(ctrl) def on_no(ctrl): return def on_minimize(ctrl): if method != self.CLOSE_COMMAND: ctrl.minimize() self.check_tabs() return close(ctrl) # Shutdown the MessageControl if force: close(ctrl) else: ctrl.allow_shutdown(method, on_yes, on_no, on_minimize) def check_tabs(self): if self.parent_paned: # Do nothing in single window mode pass elif self.get_num_controls() == 0: # These are not called when the window is destroyed like this, fake it app.interface.msg_win_mgr._on_window_delete(self.window, None) app.interface.msg_win_mgr._on_window_destroy(self.window) # dnd clean up self.notebook.drag_dest_unset() if self.parent_paned: # Don't close parent window, just remove the child child = self.parent_paned.get_child2() self.parent_paned.remove(child) self.window.lookup_action('show-roster').set_enabled(False) else: self.window.destroy() return # don't show_title, we are dead elif self.get_num_controls() == 1: # we are going from two tabs to one window_mode = app.interface.msg_win_mgr.mode show_tabs_if_one_tab = app.config.get('tabs_always_visible') or \ window_mode == MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER self.notebook.set_show_tabs(show_tabs_if_one_tab) def redraw_tab(self, ctrl, chatstate=None): tab = self.notebook.get_tab_label(ctrl.widget) if not tab: return hbox = tab.get_children()[0] status_img = hbox.get_children()[0] nick_label = hbox.get_children()[1] # Optionally hide close button close_button = hbox.get_children()[2] if app.config.get('tabs_close_button'): close_button.show() else: close_button.hide() # Update nick nick_label.set_max_width_chars(10) if isinstance(ctrl, ChatControl): tab_label_str = ctrl.get_tab_label() # Set Label Color gtkgui_helpers.add_css_class(nick_label, chatstate, 'gajim-state-') else: tab_label_str, color = ctrl.get_tab_label(chatstate) # Set Label Color if color == 'active': gtkgui_helpers.add_css_class(nick_label, None, 'gajim-state-') elif color is not None: gtkgui_helpers.add_css_class(nick_label, color, 'gajim-state-') nick_label.set_markup(tab_label_str) tab_img = ctrl.get_tab_image() if tab_img: if isinstance(tab_img, Gtk.Image): if tab_img.get_storage_type() == Gtk.ImageType.ANIMATION: status_img.set_from_animation(tab_img.get_animation()) else: status_img.set_from_pixbuf(tab_img.get_pixbuf()) elif isinstance(tab_img, str): status_img.set_from_icon_name(tab_img, Gtk.IconSize.MENU) else: status_img.set_from_surface(tab_img) self.show_icon() def repaint_themed_widgets(self): """ Repaint controls in the window with theme color """ # iterate through controls and repaint for ctrl in self.controls(): ctrl.repaint_themed_widgets() def _widget_to_control(self, widget): for ctrl in self.controls(): if ctrl.widget == widget: return ctrl return None def get_active_control(self): notebook = self.notebook active_widget = notebook.get_nth_page(notebook.get_current_page()) return self._widget_to_control(active_widget) def get_active_contact(self): ctrl = self.get_active_control() if ctrl: return ctrl.contact return None def get_active_jid(self): contact = self.get_active_contact() if contact: return contact.jid return None def is_active(self): return self.window.is_active() def get_origin(self): return self.window.get_window().get_origin() def get_control(self, key, acct): """ Return the MessageControl for jid or n, where n is a notebook page index. When key is an int index acct may be None """ if isinstance(key, str): jid = key try: return self._controls[acct][jid] except Exception: return None else: page_num = key notebook = self.notebook if page_num is None: page_num = notebook.get_current_page() nth_child = notebook.get_nth_page(page_num) return self._widget_to_control(nth_child) def has_control(self, jid, acct): return acct in self._controls and jid in self._controls[acct] def change_key(self, old_jid, new_jid, acct): """ Change the JID key of a control """ try: # Check if controls exists ctrl = self._controls[acct][old_jid] except KeyError: return if new_jid in self._controls[acct]: self.remove_tab(self._controls[acct][new_jid], self.CLOSE_CLOSE_BUTTON, force=True) self._controls[acct][new_jid] = ctrl del self._controls[acct][old_jid] if old_jid in app.last_message_time[acct]: app.last_message_time[acct][new_jid] = \ app.last_message_time[acct][old_jid] del app.last_message_time[acct][old_jid] def controls(self): for jid_dict in list(self._controls.values()): for ctrl in list(jid_dict.values()): yield ctrl def get_nb_controls(self): return sum(len(jid_dict) for jid_dict in self._controls.values()) def move_to_next_unread_tab(self, forward): ind = self.notebook.get_current_page() current = ind found = False first_composing_ind = -1 # id of first composing ctrl to switch to # if no others controls have awaiting events # loop until finding an unread tab or having done a complete cycle while True: if forward is True: # look for the first unread tab on the right ind = ind + 1 if ind >= self.notebook.get_n_pages(): ind = 0 else: # look for the first unread tab on the right ind = ind - 1 if ind < 0: ind = self.notebook.get_n_pages() - 1 ctrl = self.get_control(ind, None) if ctrl.get_nb_unread() > 0: found = True break # found elif app.config.get('ctrl_tab_go_to_next_composing'): # Search for a composing contact contact = ctrl.contact if first_composing_ind == -1 and contact.chatstate == 'composing': # If no composing contact found yet, check if this one is composing first_composing_ind = ind if ind == current: break # a complete cycle without finding an unread tab if found: self.notebook.set_current_page(ind) elif first_composing_ind != -1: self.notebook.set_current_page(first_composing_ind) else: # not found and nobody composing if forward: # CTRL + TAB if current < (self.notebook.get_n_pages() - 1): self.notebook.next_page() else: # traverse for ever (eg. don't stop at last tab) self.notebook.set_current_page(0) else: # CTRL + SHIFT + TAB if current > 0: self.notebook.prev_page() else: # traverse for ever (eg. don't stop at first tab) self.notebook.set_current_page( self.notebook.get_n_pages() - 1) def popup_menu(self, event): menu = self.get_active_control().prepare_context_menu() if menu is None: return # show the menu menu.attach_to_widget(app.interface.roster.window, None) menu.show_all() menu.popup(None, None, None, None, event.button, event.time) def _on_notebook_switch_page(self, notebook, page, page_num): old_no = notebook.get_current_page() if old_no >= 0: old_ctrl = self._widget_to_control(notebook.get_nth_page(old_no)) old_ctrl.set_control_active(False) new_ctrl = self._widget_to_control(notebook.get_nth_page(page_num)) new_ctrl.set_control_active(True) self.show_title(control=new_ctrl) control = self.get_active_control() if isinstance(control, ChatControlBase): control.msg_textview.grab_focus() def _on_notebook_key_press(self, widget, event): # when tab itself is selected, # make sure <- and -> are allowed for navigating between tabs if event.keyval in (Gdk.KEY_Left, Gdk.KEY_Right): return False control = self.get_active_control() if event.get_state() & Gdk.ModifierType.SHIFT_MASK: # CTRL + SHIFT + TAB if event.get_state() & Gdk.ModifierType.CONTROL_MASK and \ event.keyval == Gdk.KEY_ISO_Left_Tab: self.move_to_next_unread_tab(False) return True # SHIFT + PAGE_[UP|DOWN]: send to conv_textview if event.keyval in (Gdk.KEY_Page_Down, Gdk.KEY_Page_Up): control.conv_textview.tv.event(event) return True elif event.get_state() & Gdk.ModifierType.CONTROL_MASK: if event.keyval == Gdk.KEY_Tab: # CTRL + TAB self.move_to_next_unread_tab(True) return True # Ctrl+PageUP / DOWN has to be handled by notebook if event.keyval == Gdk.KEY_Page_Down: self.move_to_next_unread_tab(True) return True if event.keyval == Gdk.KEY_Page_Up: self.move_to_next_unread_tab(False) return True if event.keyval in (Gdk.KEY_Shift_L, Gdk.KEY_Shift_R, Gdk.KEY_Control_L, Gdk.KEY_Control_R, Gdk.KEY_Caps_Lock, Gdk.KEY_Shift_Lock, Gdk.KEY_Meta_L, Gdk.KEY_Meta_R, Gdk.KEY_Alt_L, Gdk.KEY_Alt_R, Gdk.KEY_Super_L, Gdk.KEY_Super_R, Gdk.KEY_Hyper_L, Gdk.KEY_Hyper_R): return True if isinstance(control, ChatControlBase): # we forwarded it to message textview control.msg_textview.remove_placeholder() control.msg_textview.event(event) control.msg_textview.grab_focus() def get_tab_at_xy(self, x, y): """ Return the tab under xy and if its nearer from left or right side of the tab """ page_num = -1 to_right = False horiz = self.notebook.get_tab_pos() == Gtk.PositionType.TOP or \ self.notebook.get_tab_pos() == Gtk.PositionType.BOTTOM for i in range(self.notebook.get_n_pages()): page = self.notebook.get_nth_page(i) tab = self.notebook.get_tab_label(page) tab_alloc = tab.get_allocation() if horiz: if (x >= tab_alloc.x) and \ (x <= (tab_alloc.x + tab_alloc.width)): page_num = i if x >= tab_alloc.x + (tab_alloc.width / 2.0): to_right = True break else: if (y >= tab_alloc.y) and \ (y <= (tab_alloc.y + tab_alloc.height)): page_num = i if y > tab_alloc.y + (tab_alloc.height / 2.0): to_right = True break return (page_num, to_right) def find_page_num_according_to_tab_label(self, tab_label): """ Find the page num of the tab label """ page_num = -1 for i in range(self.notebook.get_n_pages()): page = self.notebook.get_nth_page(i) tab = self.notebook.get_tab_label(page) if tab == tab_label: page_num = i break return page_num ################################################################################ class MessageWindowMgr(GObject.GObject): """ A manager and factory for MessageWindow objects """ __gsignals__ = { 'window-delete': (GObject.SignalFlags.RUN_LAST, None, (object,)), } # These constants map to common.config.opt_one_window_types indices ( ONE_MSG_WINDOW_NEVER, ONE_MSG_WINDOW_ALWAYS, ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER, ONE_MSG_WINDOW_PERACCT, ONE_MSG_WINDOW_PERTYPE, ) = range(5) # A key constant for the main window in ONE_MSG_WINDOW_ALWAYS mode MAIN_WIN = 'main' # A key constant for the main window in ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER mode ROSTER_MAIN_WIN = 'roster' def __init__(self, parent_window, parent_paned): """ A dictionary of windows; the key depends on the config: ONE_MSG_WINDOW_NEVER: The key is the contact JID ONE_MSG_WINDOW_ALWAYS: The key is MessageWindowMgr.MAIN_WIN ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: The key is MessageWindowMgr.MAIN_WIN ONE_MSG_WINDOW_PERACCT: The key is the account name ONE_MSG_WINDOW_PERTYPE: The key is a message type constant """ GObject.GObject.__init__(self) self._windows = {} # Map the mode to a int constant for frequent compares mode = app.config.get('one_message_window') self.mode = common.config.opt_one_window_types.index(mode) self.parent_win = parent_window self.parent_paned = parent_paned def change_account_name(self, old_name, new_name): for win in self.windows(): win.change_account_name(old_name, new_name) def _new_window(self, acct, type_): parent_win = None parent_paned = None if self.mode == self.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: parent_win = self.parent_win parent_paned = self.parent_paned win = MessageWindow(acct, type_, parent_win, parent_paned) # we track the lifetime of this window win.window.connect('delete-event', self._on_window_delete) win.window.connect('destroy', self._on_window_destroy) return win def _gtk_win_to_msg_win(self, gtk_win): for w in self.windows(): if w.window == gtk_win: return w return None def get_window(self, jid, acct): for win in self.windows(): if win.has_control(jid, acct): return win return None def has_window(self, jid, acct): return self.get_window(jid, acct) is not None def one_window_opened(self, contact=None, acct=None, type_=None): try: return \ self._windows[self._mode_to_key(contact, acct, type_)] is not None except KeyError: return False def _resize_window(self, win, acct, type_): """ Resizes window according to config settings """ hpaned = app.config.get('roster_hpaned_position') if self.mode in (self.ONE_MSG_WINDOW_ALWAYS, self.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER): size = (app.config.get('msgwin-width'), app.config.get('msgwin-height')) if self.mode == self.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: # Need to add the size of the now visible paned handle, otherwise # the saved width of the message window decreases by this amount handle_size = win.parent_paned.style_get_property('handle-size') size = (hpaned + size[0] + handle_size, size[1]) elif self.mode == self.ONE_MSG_WINDOW_PERACCT: size = (app.config.get_per('accounts', acct, 'msgwin-width'), app.config.get_per('accounts', acct, 'msgwin-height')) elif self.mode in (self.ONE_MSG_WINDOW_NEVER, self.ONE_MSG_WINDOW_PERTYPE): opt_width = type_ + '-msgwin-width' opt_height = type_ + '-msgwin-height' size = (app.config.get(opt_width), app.config.get(opt_height)) else: return win.resize(size[0], size[1]) if win.parent_paned: win.parent_paned.set_position(hpaned) def _position_window(self, win, acct, type_): """ Moves window according to config settings """ if (self.mode in [self.ONE_MSG_WINDOW_NEVER, self.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER]): return if self.mode == self.ONE_MSG_WINDOW_ALWAYS: pos = (app.config.get('msgwin-x-position'), app.config.get('msgwin-y-position')) elif self.mode == self.ONE_MSG_WINDOW_PERACCT: pos = (app.config.get_per('accounts', acct, 'msgwin-x-position'), app.config.get_per('accounts', acct, 'msgwin-y-position')) elif self.mode == self.ONE_MSG_WINDOW_PERTYPE: pos = (app.config.get(type_ + '-msgwin-x-position'), app.config.get(type_ + '-msgwin-y-position')) else: return gtkgui_helpers.move_window(win.window, pos[0], pos[1]) def _mode_to_key(self, contact, acct, type_, resource=None): if self.mode == self.ONE_MSG_WINDOW_NEVER: key = acct + contact.jid if resource: key += '/' + resource return key if self.mode == self.ONE_MSG_WINDOW_ALWAYS: return self.MAIN_WIN if self.mode == self.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: return self.ROSTER_MAIN_WIN if self.mode == self.ONE_MSG_WINDOW_PERACCT: return acct if self.mode == self.ONE_MSG_WINDOW_PERTYPE: return type_ def create_window(self, contact, acct, type_, resource=None): win_acct = None win_type = None win_role = None # X11 window role win_key = self._mode_to_key(contact, acct, type_, resource) if self.mode == self.ONE_MSG_WINDOW_PERACCT: win_acct = acct win_role = acct elif self.mode == self.ONE_MSG_WINDOW_PERTYPE: win_type = type_ win_role = type_ elif self.mode == self.ONE_MSG_WINDOW_NEVER: win_type = type_ win_role = contact.jid elif self.mode == self.ONE_MSG_WINDOW_ALWAYS: win_role = 'messages' win = None try: win = self._windows[win_key] except KeyError: win = self._new_window(win_acct, win_type) if win_role: win.window.set_role(win_role) # Position and size window based on saved state and window mode if not self.one_window_opened(contact, acct, type_): if app.config.get('msgwin-max-state'): win.window.maximize() else: self._resize_window(win, acct, type_) self._position_window(win, acct, type_) self._windows[win_key] = win return win def change_key(self, old_jid, new_jid, acct): win = self.get_window(old_jid, acct) if self.mode == self.ONE_MSG_WINDOW_NEVER: old_key = acct + old_jid if old_jid not in self._windows: return new_key = acct + new_jid self._windows[new_key] = self._windows[old_key] del self._windows[old_key] win.change_key(old_jid, new_jid, acct) def _on_window_delete(self, win, event): self.save_state(self._gtk_win_to_msg_win(win)) app.interface.save_config() return False def _on_window_destroy(self, win): for k in list(self._windows.keys()): if self._windows[k].window == win: self.emit('window-delete', self._windows[k]) del self._windows[k] return def get_control(self, jid, acct): """ Amongst all windows, return the MessageControl for jid """ win = self.get_window(jid, acct) if win: return win.get_control(jid, acct) return None def search_control(self, jid, account, resource=None): """ Search windows with this policy: 1. try to find already opened tab for resource 2. find the tab for this jid with ctrl.resource not set 3. there is none """ fjid = jid if resource: fjid += '/' + resource ctrl = self.get_control(fjid, account) if ctrl: return ctrl win = self.get_window(jid, account) if win: ctrl = win.get_control(jid, account) if not ctrl.resource and ctrl.type_id != message_control.TYPE_GC: return ctrl return None def get_gc_control(self, jid, acct): """ Same as get_control. Was briefly required, is not any more. May be useful some day in the future? """ ctrl = self.get_control(jid, acct) if ctrl and ctrl.type_id == message_control.TYPE_GC: return ctrl return None def get_controls(self, type_=None, acct=None): ctrls = [] for c in self.controls(): if acct and c.account != acct: continue if not type_ or c.type_id == type_: ctrls.append(c) return ctrls def windows(self): for w in list(self._windows.values()): yield w def controls(self): for w in self._windows.values(): for c in w.controls(): yield c def shutdown(self, width_adjust=0): for w in self.windows(): self.save_state(w, width_adjust) if not w.parent_paned: w.window.hide() w.window.destroy() app.interface.save_config() def save_state(self, msg_win, width_adjust=0): # Save window size and position max_win_key = 'msgwin-max-state' pos_x_key = 'msgwin-x-position' pos_y_key = 'msgwin-y-position' size_width_key = 'msgwin-width' size_height_key = 'msgwin-height' acct = None x, y = msg_win.window.get_position() width, height = msg_win.window.get_size() # If any of these values seem bogus don't update. if x < 0 or y < 0 or width < 0 or height < 0: return if self.mode == self.ONE_MSG_WINDOW_PERACCT: acct = msg_win.account elif self.mode == self.ONE_MSG_WINDOW_PERTYPE: type_ = msg_win.type_ pos_x_key = type_ + '-msgwin-x-position' pos_y_key = type_ + '-msgwin-y-position' size_width_key = type_ + '-msgwin-width' size_height_key = type_ + '-msgwin-height' elif self.mode == self.ONE_MSG_WINDOW_NEVER: type_ = msg_win.type_ size_width_key = type_ + '-msgwin-width' size_height_key = type_ + '-msgwin-height' elif self.mode == self.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: # Ignore any hpaned width width = msg_win.notebook.get_allocation().width if acct: app.config.set_per('accounts', acct, size_width_key, width) app.config.set_per('accounts', acct, size_height_key, height) if self.mode != self.ONE_MSG_WINDOW_NEVER: app.config.set_per('accounts', acct, pos_x_key, x) app.config.set_per('accounts', acct, pos_y_key, y) else: win_maximized = msg_win.window.get_window().get_state() == \ Gdk.WindowState.MAXIMIZED app.config.set(max_win_key, win_maximized) width += width_adjust app.config.set(size_width_key, width) app.config.set(size_height_key, height) if self.mode != self.ONE_MSG_WINDOW_NEVER: app.config.set(pos_x_key, x) app.config.set(pos_y_key, y) def reconfig(self): for w in self.windows(): self.save_state(w) mode = app.config.get('one_message_window') if self.mode == common.config.opt_one_window_types.index(mode): # No change return self.mode = common.config.opt_one_window_types.index(mode) controls = [] for w in self.windows(): # Note, we are taking care not to hide/delete the roster window when the # MessageWindow is embedded. if not w.parent_paned: w.window.hide() else: # Stash current size so it can be restored if the MessageWindow # is not longer embedded roster_width = w.parent_paned.get_position() app.config.set('roster_width', roster_width) while w.notebook.get_n_pages(): page = w.notebook.get_nth_page(0) ctrl = w._widget_to_control(page) w.notebook.remove_page(0) page.unparent() controls.append(ctrl) # Must clear _controls to prevent MessageControl.shutdown calls w._controls = {} if not w.parent_paned: w.window.destroy() else: # Don't close parent window, just remove the child child = w.parent_paned.get_child2() w.parent_paned.remove(child) self.parent_win.lookup_action('show-roster').set_enabled(False) gtkgui_helpers.resize_window(w.window, app.config.get('roster_width'), app.config.get('roster_height')) self._windows = {} for ctrl in controls: mw = self.get_window(ctrl.contact.jid, ctrl.account) if not mw: mw = self.create_window(ctrl.contact, ctrl.account, ctrl.type_id) ctrl.parent_win = mw ctrl.add_actions() ctrl.update_actions() mw.new_tab(ctrl) def save_opened_controls(self): if not app.config.get('remember_opened_chat_controls'): return chat_controls = {} for acct in app.connections: chat_controls[acct] = [] for ctrl in self.get_controls(type_=message_control.TYPE_CHAT): acct = ctrl.account if ctrl.contact.jid not in chat_controls[acct]: chat_controls[acct].append(ctrl.contact.jid) for acct in app.connections: app.config.set_per('accounts', acct, 'opened_chat_controls', ','.join(chat_controls[acct])) gajim-gajim-1.1.3/gajim/notify.py000066400000000000000000000346101345766322700166640ustar00rootroot00000000000000# Copyright (C) 2005 Sebastian Estienne # Copyright (C) 2005-2006 Andrew Sayman # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006 Travis Shirk # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Julien Pivotto # Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging import sys from gi.repository import GLib from gi.repository import Gio from gi.repository import Gdk from gi.repository import Gtk from gajim import gtkgui_helpers from gajim.common import app from gajim.common import helpers from gajim.common import ged from gajim.common.i18n import _ log = logging.getLogger('gajim.notify') def get_show_in_roster(event, account, jid, session=None): """ Return True if this event must be shown in roster, else False """ if event == 'gc_message_received': return True if event == 'message_received': if app.config.get('autopopup_chat_opened'): return True if session and session.control: return False return True def get_show_in_systray(event, account, jid, type_=None): """ Return True if this event must be shown in systray, else False """ notify = app.config.get('notify_on_all_muc_messages') notify_for_jid = app.config.get_per( 'rooms', jid, 'notify_on_all_messages') if type_ == 'printed_gc_msg' and not notify and not notify_for_jid: # it's not an highlighted message, don't show in systray return False return app.config.get('trayicon_notification_on_events') class Notification: """ Handle notifications """ def __init__(self): self._dbus_available = False self.daemon_capabilities = ['actions'] self._detect_dbus_caps() app.ged.register_event_handler( 'notification', ged.GUI2, self._nec_notification) app.ged.register_event_handler( 'our-show', ged.GUI2, self._nec_our_status) app.events.event_removed_subscribe(self._on_event_removed) def _detect_dbus_caps(self): if sys.platform in ('win32', 'darwin'): return def on_proxy_ready(_source, res, _data=None): try: proxy = Gio.DBusProxy.new_finish(res) self.daemon_capabilities = proxy.GetCapabilities() except GLib.Error: log.exception('Notifications D-Bus connection failed') else: self._dbus_available = True log.info('Notifications D-Bus connected') log.info('Connecting to Notifications D-Bus') Gio.DBusProxy.new_for_bus(Gio.BusType.SESSION, Gio.DBusProxyFlags.DO_NOT_CONNECT_SIGNALS, None, 'org.freedesktop.Notifications', '/org/freedesktop/Notifications', 'org.freedesktop.Notifications', None, on_proxy_ready) def _nec_notification(self, obj): if obj.do_popup: icon_name = self._get_icon_name(obj) self.popup(obj.popup_event_type, obj.jid, obj.conn.name, obj.popup_msg_type, icon_name=icon_name, title=obj.popup_title, text=obj.popup_text, timeout=obj.popup_timeout) if obj.do_sound: if obj.sound_file: helpers.play_sound_file(obj.sound_file) elif obj.sound_event: helpers.play_sound(obj.sound_event) if obj.do_command: try: helpers.exec_command(obj.command, use_shell=True) except Exception: pass def _on_event_removed(self, event_list): for event in event_list: if event.type_ == 'gc-invitation': self.withdraw('gc-invitation', event.account, event.room_jid) if event.type_ in ('normal', 'printed_chat', 'chat', 'printed_pm', 'pm'): self.withdraw('new-message', event.account, event.jid) def _nec_our_status(self, obj): if app.account_is_connected(obj.conn.name): self.withdraw('connection-failed', obj.conn.name) def _get_icon_name(self, obj): if obj.notif_type == 'msg': if obj.base_event.mtype == 'pm': return 'gajim-priv_msg_recv' if obj.base_event.mtype == 'normal': return 'gajim-single_msg_recv' elif obj.notif_type == 'pres': if obj.transport_name is not None: return '%s-%s' % (obj.transport_name, obj.show) return gtkgui_helpers.get_iconset_name_for(obj.show) def popup(self, event_type, jid, account, type_='', icon_name=None, title=None, text=None, timeout=-1, room_jid=None): """ Notify a user of an event using GNotification and GApplication under Linux, Use PopupNotificationWindow under Windows """ if icon_name is None: icon_name = 'gajim-chat_msg_recv' if timeout < 0: timeout = app.config.get('notification_timeout') if sys.platform == 'win32': instance = PopupNotificationWindow(event_type, jid, account, type_, icon_name, title, text, timeout) app.interface.roster.popup_notification_windows.append(instance) return if not self._dbus_available: return scale = gtkgui_helpers.get_monitor_scale_factor() icon_pixbuf = gtkgui_helpers.gtk_icon_theme.load_icon_for_scale( icon_name, 48, scale, 0) notification = Gio.Notification() if title is not None: notification.set_title(title) if text is not None: notification.set_body(text) notif_id = None if event_type in (_('Contact Signed In'), _('Contact Signed Out'), _('New Message'), _('New Single Message'), _('New Private Message'), _('Contact Changed Status'), _('File Transfer Request'), _('File Transfer Error'), _('File Transfer Completed'), _('File Transfer Stopped'), _('Groupchat Invitation'), _('Connection Failed'), _('Subscription request'), _('Unsubscribed')): if 'actions' in self.daemon_capabilities: # Create Variant Dict dict_ = {'account': GLib.Variant('s', account), 'jid': GLib.Variant('s', jid), 'type_': GLib.Variant('s', type_)} variant_dict = GLib.Variant('a{sv}', dict_) action = 'app.{}-open-event'.format(account) #Button in notification notification.add_button_with_target(_('Open'), action, variant_dict) notification.set_default_action_and_target(action, variant_dict) # Only one notification per JID if event_type in (_('Contact Signed In'), _('Contact Signed Out'), _('Contact Changed Status')): notif_id = self._id('contact-status-changed', account, jid) elif event_type == _('Groupchat Invitation'): notif_id = self._id('gc-invitation', account, room_jid) elif event_type == _('Connection Failed'): notif_id = self._id('connection-failed', account) elif event_type in (_('New Message'), _('New Single Message'), _('New Private Message')): avatar = app.contacts.get_avatar(account, jid) if avatar: icon_pixbuf = avatar notif_id = self._id('new-message', account, jid) notification.set_icon(icon_pixbuf) notification.set_priority(Gio.NotificationPriority.NORMAL) app.app.send_notification(notif_id, notification) def withdraw(self, *args): if not self._dbus_available: return app.app.withdraw_notification(self._id(*args)) def _id(self, *args): return ','.join(args) class PopupNotificationWindow: def __init__(self, event_type, jid, account, msg_type='', icon_name=None, title=None, text=None, timeout=-1): self.account = account self.jid = jid self.msg_type = msg_type self.index = len(app.interface.roster.popup_notification_windows) xml = gtkgui_helpers.get_gtk_builder('popup_notification_window.ui') self.window = xml.get_object('popup_notification_window') self.window.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) self.window.set_name('NotificationPopup') close_button = xml.get_object('close_button') event_type_label = xml.get_object('event_type_label') event_description_label = xml.get_object('event_description_label') eventbox = xml.get_object('eventbox') image = xml.get_object('notification_image') if not text: text = app.get_name_from_jid(account, jid) # default value of text if not title: title = '' event_type_label.set_markup( '%s' % GLib.markup_escape_text(title)) css = '#NotificationPopup {background-color: black }' gtkgui_helpers.add_css_to_widget(self.window, css) if event_type == _('Contact Signed In'): bg_color = app.config.get('notif_signin_color') elif event_type == _('Contact Signed Out'): bg_color = app.config.get('notif_signout_color') elif event_type in (_('New Message'), _('New Single Message'), _('New Private Message'), _('New E-mail')): bg_color = app.config.get('notif_message_color') elif event_type == _('File Transfer Request'): bg_color = app.config.get('notif_ftrequest_color') elif event_type == _('File Transfer Error'): bg_color = app.config.get('notif_fterror_color') elif event_type in (_('File Transfer Completed'), _('File Transfer Stopped')): bg_color = app.config.get('notif_ftcomplete_color') elif event_type == _('Groupchat Invitation'): bg_color = app.config.get('notif_invite_color') elif event_type == _('Contact Changed Status'): bg_color = app.config.get('notif_status_color') else: # Unknown event! Shouldn't happen but deal with it bg_color = app.config.get('notif_other_color') background_class = ''' .popup-style { border-image: none; background-image: none; background-color: %s }''' % bg_color gtkgui_helpers.add_css_to_widget(eventbox, background_class) eventbox.get_style_context().add_class('popup-style') gtkgui_helpers.add_css_to_widget(close_button, background_class) eventbox.get_style_context().add_class('popup-style') event_description_label.set_markup('%s' % GLib.markup_escape_text(text)) # set the image image.set_from_icon_name(icon_name, Gtk.IconSize.DIALOG) # position the window to bottom-right of screen window_width, self.window_height = self.window.get_size() app.interface.roster.popups_notification_height += self.window_height pos_x = app.config.get('notification_position_x') screen_w, screen_h = gtkgui_helpers.get_total_screen_geometry() if pos_x < 0: pos_x = screen_w - window_width + pos_x + 1 pos_y = app.config.get('notification_position_y') if pos_y < 0: pos_y = screen_h - \ app.interface.roster.popups_notification_height + pos_y + 1 self.window.move(pos_x, pos_y) xml.connect_signals(self) self.window.show_all() if timeout > 0: GLib.timeout_add_seconds(timeout, self.on_timeout) def on_close_button_clicked(self, widget): self.adjust_height_and_move_popup_notification_windows() def on_timeout(self): self.adjust_height_and_move_popup_notification_windows() def adjust_height_and_move_popup_notification_windows(self): #remove app.interface.roster.popups_notification_height -= self.window_height self.window.destroy() if len(app.interface.roster.popup_notification_windows) > self.index: # we want to remove the destroyed window from the list app.interface.roster.popup_notification_windows.pop(self.index) # move the rest of popup windows app.interface.roster.popups_notification_height = 0 current_index = 0 for window_instance in app.interface.roster.popup_notification_windows: window_instance.index = current_index current_index += 1 window_width, window_height = window_instance.window.get_size() app.interface.roster.popups_notification_height += window_height screen_w, screen_h = gtkgui_helpers.get_total_screen_geometry() window_instance.window.move(screen_w - window_width, screen_h - \ app.interface.roster.popups_notification_height) def on_popup_notification_window_button_press_event(self, widget, event): if event.button != 1: self.window.destroy() return app.interface.handle_event(self.account, self.jid, self.msg_type) self.adjust_height_and_move_popup_notification_windows() gajim-gajim-1.1.3/gajim/options_dialog.py000066400000000000000000000467251345766322700204000ustar00rootroot00000000000000from gi.repository import Gtk, GLib, Gdk, GObject from gajim.common import app from gajim.common import passwords from gajim.common.i18n import _ from gajim import gtkgui_helpers from gajim.common.const import OptionKind, OptionType from gajim.common.exceptions import GajimGeneralException from gajim import dialogs from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import ChangePasswordDialog class OptionsDialog(Gtk.ApplicationWindow): def __init__(self, parent, title, flags, options, account, extend=None): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_show_menubar(False) self.set_title(title) self.set_transient_for(parent) self.set_resizable(False) self.set_default_size(250, -1) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.account = account if flags == Gtk.DialogFlags.MODAL: self.set_modal(True) elif flags == Gtk.DialogFlags.DESTROY_WITH_PARENT: self.set_destroy_with_parent(True) self.listbox = OptionsBox(account, extend) self.listbox.set_hexpand(True) self.listbox.set_selection_mode(Gtk.SelectionMode.NONE) for option in options: self.listbox.add_option(option) self.listbox.update_states() self.add(self.listbox) self.show_all() self.listbox.connect('row-activated', self.on_row_activated) self.connect('key-press-event', self.on_key_press) def on_key_press(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() @staticmethod def on_row_activated(listbox, row): row.get_child().on_row_activated() def get_option(self, name): return self.listbox.get_option(name) class OptionsBox(Gtk.ListBox): def __init__(self, account, extend=None): Gtk.ListBox.__init__(self) self.set_name('OptionsBox') self.account = account self.named_options = {} self.map = { OptionKind.SWITCH: SwitchOption, OptionKind.SPIN: SpinOption, OptionKind.DIALOG: DialogOption, OptionKind.ENTRY: EntryOption, OptionKind.ACTION: ActionOption, OptionKind.LOGIN: LoginOption, OptionKind.FILECHOOSER: FileChooserOption, OptionKind.CALLBACK: CallbackOption, OptionKind.PROXY: ProxyComboOption, OptionKind.PRIORITY: PriorityOption, OptionKind.HOSTNAME: CutstomHostnameOption, OptionKind.CHANGEPASSWORD: ChangePasswordOption, OptionKind.GPG: GPGOption, } if extend is not None: for option, callback in extend: self.map[option] = callback def add_option(self, option): if option.props is not None: listitem = self.map[option.kind]( self.account, *option[1:-1], **option.props) else: listitem = self.map[option.kind](self.account, *option[1:-1]) listitem.connect('notify::option-value', self.on_option_changed) if option.name is not None: self.named_options[option.name] = listitem self.add(listitem) def get_option(self, name): return self.named_options[name] def update_states(self): values = [] values.append((None, None)) for row in self.get_children(): name = row.get_child().name if name is None: continue value = row.get_child().get_property('option-value') values.append((name, value)) for name, value in values: for row in self.get_children(): row.get_child().set_activatable(name, value) def on_option_changed(self, widget, *args): value = widget.get_property('option-value') for row in self.get_children(): row.get_child().set_activatable(widget.name, value) class GenericOption(Gtk.Grid): def __init__(self, account, label, type_, value, name, callback, data, desc, enabledif): Gtk.Grid.__init__(self) self.set_column_spacing(12) self.set_size_request(-1, 25) self.callback = callback self.type_ = type_ self.value = value self.data = data self.label = label self.account = account self.name = name self.enabledif = enabledif self.option_value = self.get_value() description_box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=0) description_box.set_valign(Gtk.Align.CENTER) optiontext = Gtk.Label(label=label) optiontext.set_hexpand(True) optiontext.set_halign(Gtk.Align.START) optiontext.set_valign(Gtk.Align.CENTER) optiontext.set_vexpand(True) description_box.add(optiontext) if desc is not None: description = Gtk.Label(label=desc) description.set_name('SubDescription') description.set_hexpand(True) description.set_halign(Gtk.Align.START) description.set_valign(Gtk.Align.CENTER) description_box.add(description) self.add(description_box) self.option_box = Gtk.Box(spacing=6) self.option_box.set_size_request(200, -1) self.option_box.set_valign(Gtk.Align.CENTER) self.option_box.set_name('GenericOptionBox') self.add(self.option_box) def do_get_property(self, prop): if prop.name == 'option-value': return self.option_value raise AttributeError('unknown property %s' % prop.name) def do_set_property(self, prop, value): if prop.name == 'option-value': self.option_value = value else: raise AttributeError('unknown property %s' % prop.name) def get_value(self): return self.__get_value(self.type_, self.value, self.account) @staticmethod def __get_value(type_, value, account): if value is None: return if type_ == OptionType.VALUE: return value if type_ == OptionType.CONFIG: return app.config.get(value) if type_ == OptionType.ACCOUNT_CONFIG: if value == 'password': return passwords.get_password(account) if value == 'no_log_for': no_log = app.config.get_per( 'accounts', account, 'no_log_for').split() return account not in no_log return app.config.get_per('accounts', account, value) if type_ == OptionType.ACTION: if value.startswith('-'): return account + value return value raise ValueError('Wrong OptionType?') def set_value(self, state): if self.type_ == OptionType.CONFIG: app.config.set(self.value, state) if self.type_ == OptionType.ACCOUNT_CONFIG: if self.value == 'password': passwords.save_password(self.account, state) if self.value == 'no_log_for': self.set_no_log_for(self.account, state) else: app.config.set_per('accounts', self.account, self.value, state) if self.callback is not None: self.callback(state, self.data) self.set_property('option-value', state) @staticmethod def set_no_log_for(account, state): no_log = app.config.get_per('accounts', account, 'no_log_for').split() if state and account in no_log: no_log.remove(account) elif not state and account not in no_log: no_log.append(account) app.config.set_per('accounts', account, 'no_log_for', ' '.join(no_log)) def on_row_activated(self): raise NotImplementedError def set_activatable(self, name, value): if self.enabledif is None or self.enabledif[0] != name: return activatable = (name, value) == self.enabledif self.get_parent().set_activatable(activatable) self.set_sensitive(activatable) class SwitchOption(GenericOption): __gproperties__ = { "option-value": (bool, 'Switch Value', '', False, GObject.ParamFlags.READWRITE),} def __init__(self, *args): GenericOption.__init__(self, *args) self.switch = Gtk.Switch() if self.type_ == OptionType.ACTION: self.switch.set_action_name('app.%s' % self.option_value) state = app.app.get_action_state(self.option_value) self.switch.set_active(state.get_boolean()) else: self.switch.set_active(self.option_value) self.switch.connect('notify::active', self.on_switch) self.switch.set_hexpand(True) self.switch.set_halign(Gtk.Align.END) self.switch.set_valign(Gtk.Align.CENTER) self.option_box.add(self.switch) self.show_all() def on_row_activated(self): state = self.switch.get_active() self.switch.set_active(not state) def on_switch(self, switch, *args): value = switch.get_active() self.set_value(value) class EntryOption(GenericOption): __gproperties__ = { "option-value": (str, 'Entry Value', '', '', GObject.ParamFlags.READWRITE),} def __init__(self, *args): GenericOption.__init__(self, *args) self.entry = Gtk.Entry() self.entry.set_text(str(self.option_value)) self.entry.connect('notify::text', self.on_text_change) self.entry.set_valign(Gtk.Align.CENTER) self.entry.set_alignment(1) if self.value == 'password': self.entry.set_invisible_char('*') self.entry.set_visibility(False) self.option_box.pack_end(self.entry, True, True, 0) self.show_all() def on_text_change(self, *args): text = self.entry.get_text() self.set_value(text) def on_row_activated(self): self.entry.grab_focus() class DialogOption(GenericOption): __gproperties__ = { "option-value": (str, 'Dummy', '', '', GObject.ParamFlags.READWRITE),} def __init__(self, *args, dialog): GenericOption.__init__(self, *args) self.dialog = dialog self.option_value = Gtk.Label() self.option_value.set_text(self.get_option_value()) self.option_value.set_halign(Gtk.Align.END) self.option_box.pack_start(self.option_value, True, True, 0) self.show_all() def show_dialog(self, parent): if self.dialog: dialog = self.dialog(self.account, parent) dialog.connect('destroy', self.on_destroy) def on_destroy(self, *args): self.option_value.set_text(self.get_option_value()) def get_option_value(self): self.option_value.hide() return '' def on_row_activated(self): self.show_dialog(self.get_toplevel()) class SpinOption(GenericOption): __gproperties__ = { "option-value": (int, 'Priority', '', -128, 127, 0, GObject.ParamFlags.READWRITE),} def __init__(self, *args, range_): GenericOption.__init__(self, *args) lower, upper = range_ adjustment = Gtk.Adjustment(0, lower, upper, 1, 10, 0) self.spin = Gtk.SpinButton() self.spin.set_adjustment(adjustment) self.spin.set_numeric(True) self.spin.set_update_policy(Gtk.SpinButtonUpdatePolicy.IF_VALID) self.spin.set_value(self.option_value) self.spin.set_halign(Gtk.Align.END) self.spin.set_valign(Gtk.Align.CENTER) self.spin.connect('notify::value', self.on_value_change) self.option_box.pack_start(self.spin, True, True, 0) self.show_all() def on_row_activated(self): self.spin.grab_focus() def on_value_change(self, spin, *args): value = spin.get_value_as_int() self.set_value(value) class FileChooserOption(GenericOption): __gproperties__ = { "option-value": (str, 'Certificate Path', '', '', GObject.ParamFlags.READWRITE),} def __init__(self, *args, filefilter): GenericOption.__init__(self, *args) button = Gtk.FileChooserButton(self.label, Gtk.FileChooserAction.OPEN) button.set_halign(Gtk.Align.END) # GTK Bug: The FileChooserButton expands without limit # get the label and use set_max_wide_chars() label = button.get_children()[0].get_children()[0].get_children()[1] label.set_max_width_chars(20) if filefilter: name, pattern = filefilter filter_ = Gtk.FileFilter() filter_.set_name(name) filter_.add_pattern(pattern) button.add_filter(filter_) button.set_filter(filter_) filter_ = Gtk.FileFilter() filter_.set_name(_('All files')) filter_.add_pattern('*') button.add_filter(filter_) if self.option_value: button.set_filename(self.option_value) button.connect('selection-changed', self.on_select) clear_button = gtkgui_helpers.get_image_button( 'edit-clear-all-symbolic', _('Clear File')) clear_button.connect('clicked', lambda *args: button.unselect_all()) self.option_box.pack_start(button, True, True, 0) self.option_box.pack_start(clear_button, False, False, 0) self.show_all() def on_select(self, filechooser): self.set_value(filechooser.get_filename() or '') def on_row_activated(self): pass class CallbackOption(GenericOption): __gproperties__ = { "option-value": (str, 'Dummy', '', '', GObject.ParamFlags.READWRITE),} def __init__(self, *args, callback): GenericOption.__init__(self, *args) self.callback = callback self.show_all() def on_row_activated(self): self.callback() class ActionOption(GenericOption): __gproperties__ = { "option-value": (str, 'Dummy', '', '', GObject.ParamFlags.READWRITE),} def __init__(self, *args, action_args): GenericOption.__init__(self, *args) self.action = gtkgui_helpers.get_action(self.option_value) self.variant = GLib.Variant.new_string(action_args) self.on_enable() self.show_all() self.action.connect('notify::enabled', self.on_enable) def on_enable(self, *args): self.set_sensitive(self.action.get_enabled()) def on_row_activated(self): self.action.activate(self.variant) class LoginOption(DialogOption): def __init__(self, *args, **kwargs): DialogOption.__init__(self, *args, **kwargs) self.option_value.set_selectable(True) def get_option_value(self): jid = app.get_jid_from_account(self.account) return jid def set_activatable(self, name, value): DialogOption.set_activatable(self, name, value) anonym = app.config.get_per('accounts', self.account, 'anonymous_auth') self.get_parent().set_activatable(not anonym) class ProxyComboOption(GenericOption): __gproperties__ = { "option-value": (str, 'Proxy', '', '', GObject.ParamFlags.READWRITE),} def __init__(self, *args): GenericOption.__init__(self, *args) self.combo = Gtk.ComboBoxText() self.update_values() self.combo.connect('changed', self.on_value_change) self.combo.set_valign(Gtk.Align.CENTER) button = gtkgui_helpers.get_image_button( 'preferences-system-symbolic', _('Manage Proxies')) button.set_action_name('app.manage-proxies') button.set_valign(Gtk.Align.CENTER) self.option_box.pack_start(self.combo, True, True, 0) self.option_box.pack_start(button, False, True, 0) self.show_all() def update_values(self): proxies = app.config.get_per('proxies') proxies.insert(0, _('None')) self.combo.remove_all() for index, value in enumerate(proxies): self.combo.insert_text(-1, value) if value == self.option_value or index == 0: self.combo.set_active(index) def on_value_change(self, combo): self.set_value(combo.get_active_text()) def on_row_activated(self): pass class PriorityOption(DialogOption): def __init__(self, *args, **kwargs): DialogOption.__init__(self, *args, **kwargs) def get_option_value(self): adjust = app.config.get_per( 'accounts', self.account, 'adjust_priority_with_status') if adjust: return _('Adjust to Status') priority = app.config.get_per('accounts', self.account, 'priority') return str(priority) class CutstomHostnameOption(DialogOption): def __init__(self, *args, **kwargs): DialogOption.__init__(self, *args, **kwargs) def get_option_value(self): custom = app.config.get_per('accounts', self.account, 'use_custom_host') return _('On') if custom else _('Off') class ChangePasswordOption(DialogOption): def __init__(self, *args, **kwargs): DialogOption.__init__(self, *args, **kwargs) def show_dialog(self, parent): try: self.change_dialog = ChangePasswordDialog( self.account, self.on_changed, parent) except GajimGeneralException: return self.change_dialog.set_modal(True) def on_changed(self, new_password): self.set_value(new_password) def set_activatable(self, name, value): activatable = False if self.account in app.connections: con = app.connections[self.account] activatable = con.connected >= 2 and con.register_supported self.get_parent().set_activatable(activatable) class GPGOption(DialogOption): def __init__(self, *args, **kwargs): DialogOption.__init__(self, *args, **kwargs) def show_dialog(self, parent): secret_keys = app.connections[self.account].ask_gpg_secrete_keys() secret_keys[_('None')] = _('None') if not secret_keys: ErrorDialog( _('Failed to get secret keys'), _('There is no OpenPGP secret key available.'), transient_for=parent) return dialog = dialogs.ChooseGPGKeyDialog( _('OpenPGP Key Selection'), _('Choose your OpenPGP key'), secret_keys, self.on_key_selected, transient_for=parent) dialog.window.connect('destroy', self.on_destroy) def on_key_selected(self, keyID): if keyID is None: return keyid_new, keyname_new = keyID keyid = app.config.get_per('accounts', self.account, 'keyid') if keyid_new == _('None'): if keyid == '': return app.config.set_per('accounts', self.account, 'keyname', '') app.config.set_per('accounts', self.account, 'keyid', '') else: if keyid == keyid_new: return app.config.set_per( 'accounts', self.account, 'keyname', keyname_new) app.config.set_per( 'accounts', self.account, 'keyid', keyid_new) def get_option_value(self): keyid = app.config.get_per('accounts', self.account, 'keyid') keyname = app.config.get_per('accounts', self.account, 'keyname') if keyid is not None: return '\n'.join((keyid, keyname)) return '' def set_activatable(self, name, value): active = self.account in app.connections self.get_parent().set_activatable(app.is_installed('GPG') and active) gajim-gajim-1.1.3/gajim/plugins/000077500000000000000000000000001345766322700164575ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/plugins/__init__.py000066400000000000000000000016371345766322700205770ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' Main file of plugins package. :author: Mateusz Biliński :since: 05/30/2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' from gajim.plugins.pluginmanager import PluginManager from gajim.plugins.gajimplugin import GajimPlugin __all__ = ['PluginManager', 'GajimPlugin'] gajim-gajim-1.1.3/gajim/plugins/gajimplugin.py000066400000000000000000000214211345766322700213370ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' Base class for implementing plugin. :author: Mateusz Biliński :since: 1st June 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' from typing import List # pylint: disable=W0611 from typing import Tuple # pylint: disable=W0611 from typing import Dict # pylint: disable=W0611 from typing import Any # pylint: disable=W0611 import os import locale import logging import pickle from gajim.common import configpaths from gajim.common.types import PluginExtensionPoints # pylint: disable=W0611 from gajim.common.types import EventHandlersDict # pylint: disable=W0611 from gajim.common.types import PluginEvents # pylint: disable=W0611 from gajim.plugins.helpers import log_calls, log from gajim.plugins.gui import GajimPluginConfigDialog log = logging.getLogger('gajim.p.plugin') class GajimPlugin: ''' Base class for implementing Gajim plugins. ''' name = '' ''' Name of plugin. Will be shown in plugins management GUI. :type: str ''' short_name = '' ''' Short name of plugin. Used for quick identification of plugin. :type: str :todo: decide whether we really need this one, because class name (with module name) can act as such short name ''' encryption_name = '' ''' Name of the encryption scheme. The name that Gajim displays in the encryption menu. Leave empty if the plugin is not an encryption plugin. :type: str ''' version = '' ''' Version of plugin. :type: str :todo: decide how to compare version between each other (which one is higher). Also rethink: do we really need to compare versions of plugins between each other? This would be only useful if we detect same plugin class but with different version and we want only the newest one to be active - is such policy good? ''' description = '' ''' Plugin description. :type: str :todo: should be allow rich text here (like HTML or reStructuredText)? ''' authors = [] # type: List[str] ''' Plugin authors. :type: [] of str :todo: should we decide on any particular format of author strings? Especially: should we force format of giving author's e-mail? ''' homepage = '' ''' URL to plug-in's homepage. :type: str :todo: should we check whether provided string is valid URI? (Maybe using 'property') ''' gui_extension_points = {} # type: PluginExtensionPoints ''' Extension points that plugin wants to connect with and handlers to be used. Keys of this string should be strings with name of GUI extension point to handles. Values should be 2-element tuples with references to handling functions. First function will be used to connect plugin with extpoint, the second one to successfully disconnect from it. Connecting takes places when plugin is activated and extpoint already exists, or when plugin is already activated but extpoint is being created (eg. chat window opens). Disconnecting takes place when plugin is deactivated and extpoint exists or when extpoint is destroyed and plugin is activate (eg. chat window closed). ''' config_default_values = {} # type: Dict[str, Tuple[Any, str]] ''' Default values for keys that should be stored in plug-in config. This dict is used when when someone calls for config option but it has not been set yet. Values are tuples: (default_value, option_description). The first one can be anything (this is the advantage of using shelve/pickle instead of custom-made config I/O handling); the second one should be str (gettext can be used if need and/or translation is planned). :type: {} of 2-element tuples ''' events_handlers = {} # type: EventHandlersDict ''' Dictionary with events handlers. Keys are event names. Values should be 2-element tuples with handler priority as first element and reference to handler function as second element. Priority is integer. See `ged` module for predefined priorities like `ged.PRECORE`, `ged.CORE` or `ged.POSTCORE`. :type: {} with 2-element tuples ''' events = [] # type: PluginEvents ''' New network event classes to be registered in Network Events Controller. :type: [] of `nec.NetworkIncomingEvent` or `nec.NetworkOutgoingEvent` subclasses. ''' @log_calls('GajimPlugin') def __init__(self) -> None: self.config = GajimPluginConfig(self) ''' Plug-in configuration dictionary. Automatically saved and loaded and plug-in (un)load. :type: `plugins.plugin.GajimPluginConfig` ''' self.activatable = True self.available_text = '' self.load_config() self.config_dialog = GajimPluginConfigDialog(self) self.init() @log_calls('GajimPlugin') def save_config(self) -> None: self.config.save() @log_calls('GajimPlugin') def load_config(self) -> None: self.config.load() def __eq__(self, plugin): if self.short_name == plugin.short_name: return True return False def __ne__(self, plugin): if self.short_name != plugin.short_name: return True return False @log_calls('GajimPlugin') def local_file_path(self, file_name): return os.path.join(self.__path__, file_name) @log_calls('GajimPlugin') def init(self): pass @log_calls('GajimPlugin') def activate(self): pass @log_calls('GajimPlugin') def deactivate(self): pass class GajimPluginConfig(): @log_calls('GajimPluginConfig') def __init__(self, plugin): self.plugin = plugin self.FILE_PATH = os.path.join( configpaths.get('PLUGINS_CONFIG_DIR'), self.plugin.short_name) self.data = {} @log_calls('GajimPluginConfig') def __getitem__(self, key): if not key in self.data: self.data[key] = self.plugin.config_default_values[key][0] self.save() return self.data[key] @log_calls('GajimPluginConfig') def __setitem__(self, key, value): self.data[key] = value self.save() @log_calls('GajimPluginConfig') def __delitem__(self, key): del self.data[key] self.save() @log_calls('GajimPluginConfig') def __contains__(self, key): return key in self.data def __iter__(self): for k in self.data.keys(): yield k def keys(self): return self.data.keys() def items(self): return self.data.items() @log_calls('GajimPluginConfig') def save(self): fd = open(self.FILE_PATH, 'wb') pickle.dump(self.data, fd) fd.close() @log_calls('GajimPluginConfig') def load(self): if os.path.isfile(self.FILE_PATH): fd = open(self.FILE_PATH, 'rb') try: self.data = pickle.load(fd) fd.close() except Exception: fd.close() try: import shelve s = shelve.open(self.FILE_PATH) for (k, v) in s.items(): self.data[k] = v if not isinstance(self.data, dict): raise GajimPluginException s.close() self.save() except Exception: enc = locale.getpreferredencoding() filename = self.FILE_PATH.decode(enc) + '.bak' log.warning( '%s plugin config file not readable. Saving it as ' '%s and creating a new one', self.plugin.short_name, filename) if os.path.exists(self.FILE_PATH + '.bak'): os.remove(self.FILE_PATH + '.bak') os.rename(self.FILE_PATH, self.FILE_PATH + '.bak') self.data = {} self.save() else: self.data = {} self.save() class GajimPluginException(Exception): pass class GajimPluginInitError(GajimPluginException): pass gajim-gajim-1.1.3/gajim/plugins/gui.py000066400000000000000000000305631345766322700176240ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' GUI classes related to plug-in management. :author: Mateusz Biliński :since: 6th June 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' __all__ = ['PluginsWindow'] from gi.repository import Gtk from gi.repository import GdkPixbuf from gi.repository import Gdk import os from enum import IntEnum, unique from gajim import gtkgui_helpers from gajim.gtk.dialogs import WarningDialog from gajim.gtk.dialogs import YesNoDialog from gajim.gtk.filechoosers import ArchiveChooserDialog from gajim.common import app from gajim.common import configpaths from gajim.common.exceptions import PluginsystemError from gajim.common.helpers import launch_browser_mailer from gajim.plugins.helpers import log_calls from gajim.plugins.helpers import GajimPluginActivateException from gajim.plugins.plugins_i18n import _ @unique class Column(IntEnum): PLUGIN = 0 NAME = 1 ACTIVE = 2 ACTIVATABLE = 3 ICON = 4 class PluginsWindow: '''Class for Plugins window''' @log_calls('PluginsWindow') def __init__(self): '''Initialize Plugins window''' builder = gtkgui_helpers.get_gtk_builder('plugins_window.ui') self.window = builder.get_object('plugins_window') self.window.set_transient_for(app.interface.roster.window) widgets_to_extract = ('plugins_notebook', 'plugin_name_label', 'plugin_version_label', 'plugin_authors_label', 'plugin_homepage_linkbutton', 'install_plugin_button', 'uninstall_plugin_button', 'configure_plugin_button', 'installed_plugins_treeview', 'available_text', 'available_text_label') for widget_name in widgets_to_extract: setattr(self, widget_name, builder.get_object(widget_name)) self.plugin_description_textview = builder.get_object('description') # Disable 'Install from ZIP' for Flatpak installs if app.is_flatpak(): self.install_plugin_button.set_tooltip_text( _('Click to view Gajim\'s wiki page on how to install plugins in Flatpak.')) self.installed_plugins_model = Gtk.ListStore(object, str, bool, bool, GdkPixbuf.Pixbuf) self.installed_plugins_treeview.set_model(self.installed_plugins_model) renderer = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('Plugin'))#, renderer, text=Column.NAME) cell = Gtk.CellRendererPixbuf() col.pack_start(cell, False) col.add_attribute(cell, 'pixbuf', Column.ICON) col.pack_start(renderer, True) col.add_attribute(renderer, 'text', Column.NAME) col.set_property('expand', True) self.installed_plugins_treeview.append_column(col) renderer = Gtk.CellRendererToggle() renderer.connect('toggled', self.installed_plugins_toggled_cb) col = Gtk.TreeViewColumn(_('Active'), renderer, active=Column.ACTIVE, activatable=Column.ACTIVATABLE) self.installed_plugins_treeview.append_column(col) self.def_icon = gtkgui_helpers.get_icon_pixmap('preferences-desktop') # connect signal for selection change selection = self.installed_plugins_treeview.get_selection() selection.connect('changed', self.installed_plugins_treeview_selection_changed) selection.set_mode(Gtk.SelectionMode.SINGLE) self._clear_installed_plugin_info() self.fill_installed_plugins_model() root_iter = self.installed_plugins_model.get_iter_first() if root_iter: selection.select_iter(root_iter) builder.connect_signals(self) self.plugins_notebook.set_current_page(0) # Adding GUI extension point for Plugins that want to hook the Plugin Window app.plugin_manager.gui_extension_point('plugin_window', self) self.window.show_all() def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() @log_calls('PluginsWindow') def installed_plugins_treeview_selection_changed(self, treeview_selection): model, iter_ = treeview_selection.get_selected() if iter_: plugin = model.get_value(iter_, Column.PLUGIN) self._display_installed_plugin_info(plugin) else: self._clear_installed_plugin_info() def _display_installed_plugin_info(self, plugin): self.plugin_name_label.set_text(plugin.name) self.plugin_version_label.set_text(plugin.version) self.plugin_authors_label.set_text(plugin.authors) markup = '%s' % (plugin.homepage, plugin.homepage) self.plugin_homepage_linkbutton.set_markup(markup) if plugin.available_text: text = _('Warning: %s') % plugin.available_text self.available_text_label.set_text(text) self.available_text.show() # Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=710888 self.available_text.queue_resize() else: self.available_text.hide() self.plugin_description_textview.set_text(plugin.description) self.uninstall_plugin_button.set_property( 'sensitive', configpaths.get('PLUGINS_USER') in plugin.__path__) self.configure_plugin_button.set_property( 'sensitive', plugin.config_dialog is not None) def _clear_installed_plugin_info(self): self.plugin_name_label.set_text('') self.plugin_version_label.set_text('') self.plugin_authors_label.set_text('') self.plugin_homepage_linkbutton.set_markup('') self.plugin_description_textview.set_text('') self.uninstall_plugin_button.set_property('sensitive', False) self.configure_plugin_button.set_property('sensitive', False) @log_calls('PluginsWindow') def fill_installed_plugins_model(self): pm = app.plugin_manager self.installed_plugins_model.clear() self.installed_plugins_model.set_sort_column_id(1, Gtk.SortType.ASCENDING) for plugin in pm.plugins: icon = self.get_plugin_icon(plugin) self.installed_plugins_model.append([plugin, plugin.name, plugin.active and plugin.activatable, plugin.activatable, icon]) def get_plugin_icon(self, plugin): icon_file = os.path.join(plugin.__path__, os.path.split( plugin.__path__)[1]) + '.png' icon = self.def_icon if os.path.isfile(icon_file): icon = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_file, 16, 16) return icon @log_calls('PluginsWindow') def installed_plugins_toggled_cb(self, cell, path): is_active = self.installed_plugins_model[path][Column.ACTIVE] plugin = self.installed_plugins_model[path][Column.PLUGIN] if is_active: app.plugin_manager.deactivate_plugin(plugin) else: try: app.plugin_manager.activate_plugin(plugin) except GajimPluginActivateException as e: WarningDialog(_('Plugin failed'), str(e), transient_for=self.window) return self.installed_plugins_model[path][Column.ACTIVE] = not is_active @log_calls('PluginsWindow') def on_plugins_window_destroy(self, widget): '''Close window''' app.plugin_manager.remove_gui_extension_point('plugin_window', self) del app.interface.instances['plugins'] @log_calls('PluginsWindow') def on_configure_plugin_button_clicked(self, widget): selection = self.installed_plugins_treeview.get_selection() model, iter_ = selection.get_selected() if iter_: plugin = model.get_value(iter_, Column.PLUGIN) if isinstance(plugin.config_dialog, GajimPluginConfigDialog): plugin.config_dialog.run(self.window) else: plugin.config_dialog(self.window) else: # No plugin selected. this should never be reached. As configure # plugin button should only be clickable when plugin is selected. # XXX: maybe throw exception here? pass @log_calls('PluginsWindow') def on_uninstall_plugin_button_clicked(self, widget): selection = self.installed_plugins_treeview.get_selection() model, iter_ = selection.get_selected() if iter_: plugin = model.get_value(iter_, Column.PLUGIN) try: app.plugin_manager.uninstall_plugin(plugin) except PluginsystemError as e: WarningDialog(_('Unable to properly remove the plugin'), str(e), self.window) return model.remove(iter_) @log_calls('PluginsWindow') def on_install_plugin_button_clicked(self, widget): if app.is_flatpak(): launch_browser_mailer('url', 'https://dev.gajim.org/gajim/gajim/wikis/help/flathub') return def show_warn_dialog(): text = _('Archive is malformed') dialog = WarningDialog(text, '', transient_for=self.window) dialog.set_modal(False) dialog.popup() def _on_plugin_exists(zip_filename): def on_yes(is_checked): plugin = app.plugin_manager.install_from_zip(zip_filename, True) if not plugin: show_warn_dialog() return model = self.installed_plugins_model for _index, row in enumerate(model): if plugin == row[Column.PLUGIN]: model.remove(row.iter) break iter_ = model.append([plugin, plugin.name, False, plugin.activatable, self.get_plugin_icon(plugin)]) sel = self.installed_plugins_treeview.get_selection() sel.select_iter(iter_) YesNoDialog(_('Plugin already exists'), sectext=_('Overwrite?'), on_response_yes=on_yes, transient_for=self.window) def _try_install(zip_filename): try: plugin = app.plugin_manager.install_from_zip(zip_filename) except PluginsystemError as er_type: error_text = str(er_type) if error_text == _('Plugin already exists'): _on_plugin_exists(zip_filename) return WarningDialog(error_text, '"%s"' % zip_filename, self.window) return if not plugin: show_warn_dialog() return model = self.installed_plugins_model iter_ = model.append([plugin, plugin.name, False, plugin.activatable, self.get_plugin_icon(plugin)]) sel = self.installed_plugins_treeview.get_selection() sel.select_iter(iter_) ArchiveChooserDialog(_try_install, transient_for=self.window) class GajimPluginConfigDialog(Gtk.Dialog): @log_calls('GajimPluginConfigDialog') def __init__(self, plugin, **kwargs): Gtk.Dialog.__init__(self, title='%s %s'%(plugin.name, _('Configuration')), **kwargs) self.plugin = plugin button = self.add_button('gtk-close', Gtk.ResponseType.CLOSE) button.connect('clicked', self.on_close_button_clicked) self.get_child().set_spacing(3) self.init() def on_close_dialog(self, widget, data): self.hide() return True def on_close_button_clicked(self, widget): self.hide() @log_calls('GajimPluginConfigDialog') def run(self, parent=None): self.set_transient_for(parent) self.on_run() self.show_all() self.connect('delete-event', self.on_close_dialog) result = super(GajimPluginConfigDialog, self) return result def init(self): pass def on_run(self): pass gajim-gajim-1.1.3/gajim/plugins/helpers.py000066400000000000000000000102001345766322700204640ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' Helper code related to plug-ins management system. :author: Mateusz Biliński :since: 30th May 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' __all__ = ['log', 'log_calls', 'Singleton'] from typing import List import logging import functools from gajim.plugins import plugins_i18n from gajim.gtk.util import Builder log = logging.getLogger('gajim.plugin_system') ''' Logger for code related to plug-in system. :type: logging.Logger ''' class GajimPluginActivateException(Exception): ''' Raised when activation failed ''' pass class log_calls: ''' Decorator class for functions to easily log when they are entered and left. ''' filter_out_classes = ['GajimPluginConfig', 'PluginManager', 'GajimPluginConfigDialog', 'PluginsWindow'] ''' List of classes from which no logs should be emited when methods are called, even though `log_calls` decorator is used. ''' def __init__(self, classname=''): ''' :Keywords: classname : str Name of class to prefix function name (if function is a method). log : logging.Logger Logger to use when outputting debug information on when function has been entered and when left. By default: `plugins.helpers.log` is used. ''' self.full_func_name = '' ''' Full name of function, with class name (as prefix) if given to decorator. Otherwise, it's only function name retrieved from function object for which decorator was called. :type: str ''' self.log_this_class = True ''' Determines whether wrapper of given function should log calls of this function or not. :type: bool ''' if classname: self.full_func_name = classname+'.' if classname in self.filter_out_classes: self.log_this_class = False def __call__(self, f): ''' :param f: function to be wrapped with logging statements :return: given function wrapped by *log.debug* statements :rtype: function ''' self.full_func_name += f.__name__ if self.log_this_class: @functools.wraps(f) def wrapper(*args, **kwargs): log.debug('%s() ', self.full_func_name) result = f(*args, **kwargs) log.debug('%s() ', self.full_func_name) return result else: @functools.wraps(f) def wrapper(*args, **kwargs): result = f(*args, **kwargs) return result return wrapper class Singleton(type): ''' Singleton metaclass. ''' def __init__(cls, name, bases, dic): super(Singleton, cls).__init__(name, bases, dic) cls.instance = None def __call__(cls, *args, **kwargs): if cls.instance is None: cls.instance = super(Singleton, cls).__call__(*args, **kwargs) #log.debug('%(classname)s - new instance created'%{ #'classname' : cls.__name__}) else: pass #log.debug('%(classname)s - returning already existing instance'%{ #'classname' : cls.__name__}) return cls.instance def get_builder(file_name: str, widgets: List[str] = None) -> Builder: return Builder(file_name, widgets, domain=plugins_i18n.DOMAIN, gettext_=plugins_i18n._) gajim-gajim-1.1.3/gajim/plugins/pluginmanager.py000066400000000000000000000770421345766322700216740ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' Plug-in management related classes. :author: Mateusz Biliński :since: 30th May 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' __all__ = ['PluginManager'] import os import sys import fnmatch import zipfile from shutil import rmtree, move import configparser from pkg_resources import parse_version import gajim from gajim.common import app from gajim.common import nec from gajim.common import configpaths from gajim.common import modules from gajim.common.i18n import _ from gajim.common.exceptions import PluginsystemError from gajim.plugins import plugins_i18n from gajim.plugins.helpers import log, log_calls, Singleton from gajim.plugins.helpers import GajimPluginActivateException from gajim.plugins.gajimplugin import GajimPlugin, GajimPluginException class PluginManager(metaclass=Singleton): ''' Main plug-in management class. Currently: - scans for plugins - activates them - handles GUI extension points, when called by GUI objects after plugin is activated (by dispatching info about call to handlers in plugins) :todo: add more info about how GUI extension points work :todo: add list of available GUI extension points :todo: implement mechanism to dynamically load plugins where GUI extension points have been already called (i.e. when plugin is activated after GUI object creation). [DONE?] :todo: implement mechanism to dynamically deactivate plugins (call plugin's deactivation handler) [DONE?] :todo: when plug-in is deactivated all GUI extension points are removed from `PluginManager.gui_extension_points_handlers`. But when object that invoked GUI extension point is abandoned by Gajim, eg. closed ChatControl object, the reference to called GUI extension points is still in `PluginManager.gui_extension_points` These should be removed, so that object can be destroyed by Python. Possible solution: add call to clean up method in classes 'destructors' (classes that register GUI extension points) ''' __metaclass__ = Singleton #@log_calls('PluginManager') def __init__(self): self.plugins = [] ''' Detected plugin classes. Each class object in list is `GajimPlugin` subclass. :type: [] of class objects ''' self.active_plugins = [] ''' Instance objects of active plugins. These are object instances of classes held `plugins`, but only those that were activated. :type: [] of `GajimPlugin` based objects ''' self.gui_extension_points = {} ''' Registered GUI extension points. ''' self.gui_extension_points_handlers = {} ''' Registered handlers of GUI extension points. ''' self.encryption_plugins = {} ''' Registered names with instances of encryption Plugins. ''' self.update_plugins() for path in reversed(configpaths.get_plugin_dirs()): pc = self.scan_dir_for_plugins(path) self.add_plugins(pc) @log_calls('PluginManager') def _plugin_has_entry_in_global_config(self, plugin): if app.config.get_per('plugins', plugin.short_name) is None: return False return True @log_calls('PluginManager') def _create_plugin_entry_in_global_config(self, plugin): app.config.add_per('plugins', plugin.short_name) def _remove_plugin_entry_in_global_config(self, plugin): app.config.del_per('plugins', plugin.short_name) @log_calls('PluginManager') def update_plugins(self, replace=True, activate=False, plugin_name=None): ''' Move plugins from the downloaded folder to the user plugin folder :param replace: replace plugin files if they already exist. :type replace: boolean :param activate: load and activate the plugin :type activate: boolean :param plugin_name: if provided, update only this plugin :type plugin_name: str :return: list of updated plugins (files have been installed) :rtype: [] of str ''' updated_plugins = [] user_dir = configpaths.get('PLUGINS_USER') dl_dir = configpaths.get('PLUGINS_DOWNLOAD') to_update = [plugin_name] if plugin_name else next(os.walk(dl_dir))[1] for directory in to_update: src_dir = os.path.join(dl_dir, directory) dst_dir = os.path.join(user_dir, directory) try: if os.path.exists(dst_dir): if not replace: continue self.delete_plugin_files(dst_dir) move(src_dir, dst_dir) except Exception: log.exception('Upgrade of plugin %s failed. Impossible to move ' 'files from "%s" to "%s"', directory, src_dir, dst_dir) continue updated_plugins.append(directory) if activate: pc = self.scan_dir_for_plugins(dst_dir, scan_dirs=True, package=True) if not pc: continue self.add_plugin(pc[0]) plugin = self.plugins[-1] self.activate_plugin(plugin) return updated_plugins @log_calls('PluginManager') def init_plugins(self): self._activate_all_plugins_from_global_config() @log_calls('PluginManager') def add_plugin(self, plugin_class): ''' :todo: what about adding plug-ins that are already added? Module reload and adding class from reloaded module or ignoring adding plug-in? ''' try: plugin = plugin_class() except Exception: log.exception('Error while loading a plugin') return if plugin not in self.plugins: if not self._plugin_has_entry_in_global_config(plugin): self._create_plugin_entry_in_global_config(plugin) self.plugins.append(plugin) plugin.active = False else: log.info('Not loading plugin %s v%s from module %s ' '(identified by short name: %s). Plugin already loaded.', plugin.name, plugin.version, plugin.__module__, plugin.short_name) @log_calls('PluginManager') def remove_plugin(self, plugin): ''' removes the plugin from the plugin list and deletes all loaded modules from sys. This way we will have a fresh start when the plugin gets added again. ''' if plugin.active: self.deactivate_plugin(plugin) self.plugins.remove(plugin) # remove modules from cache base_package = plugin.__module__.split('.')[0] # get the subpackages/-modules of the base_package. Add a dot to the # name to avoid name problems (removing module_abc if base_package is # module_ab) modules_to_remove = [module for module in sys.modules if module.startswith('{}.'.format(base_package))] # remove the base_package itself if base_package in sys.modules: modules_to_remove.append(base_package) for module_to_remove in modules_to_remove: del sys.modules[module_to_remove] @log_calls('PluginManager') def add_plugins(self, plugin_classes): for plugin_class in plugin_classes: self.add_plugin(plugin_class) @log_calls('PluginManager') def get_active_plugin(self, plugin_name): for plugin in self.active_plugins: if plugin.short_name == plugin_name: return plugin return None @log_calls('PluginManager') def extension_point(self, gui_extpoint_name, *args): ''' Invokes all handlers (from plugins) for a particular extension point, but doesn't add it to collection for further processing. For example if you pass a message for encryption via extension point to a plugin, its undesired that the call is stored and replayed on activating the plugin. For example after an update. :param gui_extpoint_name: name of GUI extension point. :type gui_extpoint_name: str :param args: parameters to be passed to extension point handlers (typically and object that invokes `gui_extension_point`; however, this can be practically anything) :type args: tuple ''' self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name, *args) @log_calls('PluginManager') def gui_extension_point(self, gui_extpoint_name, *args): ''' Invokes all handlers (from plugins) for particular GUI extension point and adds it to collection for further processing (eg. by plugins not active yet). :param gui_extpoint_name: name of GUI extension point. :type gui_extpoint_name: str :param args: parameters to be passed to extension point handlers (typically and object that invokes `gui_extension_point`; however, this can be practically anything) :type args: tuple :todo: GUI extension points must be documented well - names with parameters that will be passed to handlers (in plugins). Such documentation must be obeyed both in core and in plugins. This is a loosely coupled approach and is pretty natural in Python. :bug: what if only some handlers are successfully connected? we should revert all those connections that where successfully made. Maybe call 'self._deactivate_plugin()' or sth similar. Looking closer - we only rewrite tuples here. Real check should be made in method that invokes gui_extpoints handlers. ''' self._add_gui_extension_point_call_to_list(gui_extpoint_name, *args) self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name, *args) @log_calls('PluginManager') def remove_gui_extension_point(self, gui_extpoint_name, *args): ''' Removes GUI extension point from collection held by `PluginManager`. From this point this particular extension point won't be visible to plugins (eg. it won't invoke any handlers when plugin is activated). GUI extension point is removed completely (there is no way to recover it from inside `PluginManager`). Removal is needed when instance object that given extension point was connect with is destroyed (eg. ChatControl is closed or context menu is hidden). Each `PluginManager.gui_extension_point` call should have a call of `PluginManager.remove_gui_extension_point` related to it. :note: in current implementation different arguments mean different extension points. The same arguments and the same name mean the same extension point. :todo: instead of using argument to identify which extpoint should be removed, maybe add additional 'id' argument - this would work similar hash in Python objects. 'id' would be calculated based on arguments passed or on anything else (even could be constant) This would give core developers (that add new extpoints) more freedom, but is this necessary? :param gui_extpoint_name: name of GUI extension point. :type gui_extpoint_name: str :param args: arguments that `PluginManager.gui_extension_point` was called with for this extension point. This is used (along with extension point name) to identify element to be removed. :type args: tuple ''' if gui_extpoint_name in self.gui_extension_points: extension_points = list(self.gui_extension_points[gui_extpoint_name]) for ext_point in extension_points: if args[0] in ext_point: self.gui_extension_points[gui_extpoint_name].remove( ext_point) @log_calls('PluginManager') def _add_gui_extension_point_call_to_list(self, gui_extpoint_name, *args): ''' Adds GUI extension point call to list of calls. This is done only if such call hasn't been added already (same extension point name and same arguments). :note: This is assumption that GUI extension points are different only if they have different name or different arguments. :param gui_extpoint_name: GUI extension point name used to identify it by plugins. :type gui_extpoint_name: str :param args: parameters to be passed to extension point handlers (typically and object that invokes `gui_extension_point`; however, this can be practically anything) :type args: tuple ''' if ((gui_extpoint_name not in self.gui_extension_points) or (args not in self.gui_extension_points[gui_extpoint_name])): self.gui_extension_points.setdefault(gui_extpoint_name, []).append( args) @log_calls('PluginManager') def _execute_all_handlers_of_gui_extension_point(self, gui_extpoint_name, *args): if gui_extpoint_name in self.gui_extension_points_handlers: for handlers in self.gui_extension_points_handlers[ gui_extpoint_name]: try: handlers[0](*args) except Exception: log.warning('Error executing %s', handlers[0], exc_info=True) def _register_events_handlers_in_ged(self, plugin): for event_name, handler in plugin.events_handlers.items(): priority = handler[0] handler_function = handler[1] app.ged.register_event_handler(event_name, priority, handler_function) def _remove_events_handler_from_ged(self, plugin): for event_name, handler in plugin.events_handlers.items(): priority = handler[0] handler_function = handler[1] app.ged.remove_event_handler(event_name, priority, handler_function) def _register_network_events_in_nec(self, plugin): for event_class in plugin.events: setattr(event_class, 'plugin', plugin) if issubclass(event_class, nec.NetworkIncomingEvent): app.nec.register_incoming_event(event_class) elif issubclass(event_class, nec.NetworkOutgoingEvent): app.nec.register_outgoing_event(event_class) def _remove_network_events_from_nec(self, plugin): for event_class in plugin.events: if issubclass(event_class, nec.NetworkIncomingEvent): app.nec.unregister_incoming_event(event_class) elif issubclass(event_class, nec.NetworkOutgoingEvent): app.nec.unregister_outgoing_event(event_class) def _remove_name_from_encryption_plugins(self, plugin): if plugin.encryption_name: del self.encryption_plugins[plugin.encryption_name] def _register_modules_with_handlers(self, plugin): if not hasattr(plugin, 'modules'): return for con in app.connections.values(): for module in plugin.modules: if not module.zeroconf and con.name == 'Local': continue instance, name = module.get_instance(con) modules.register_single(con, instance, name) # If handlers have been registered, register the # plugin handlers. Otherwise this will be done # automatically on connecting # in connection_handlers._register_handlers() if con.handlers_registered: for handler in instance.handlers: con.connection.RegisterHandler(*handler) def _unregister_modules_with_handlers(self, plugin): if not hasattr(plugin, 'modules'): return for con in app.connections.values(): for module in plugin.modules: instance = con.get_module(module.name) modules.unregister_single(con, module.name) # Account is still connected and handlers are registered # So just unregister the plugin handlers if con.handlers_registered: for handler in instance.handlers: con.connection.UnregisterHandler(*handler) @log_calls('PluginManager') def activate_plugin(self, plugin): ''' :param plugin: plugin to be activated :type plugin: class object of `GajimPlugin` subclass ''' if not plugin.active and plugin.activatable: self._add_gui_extension_points_handlers_from_plugin(plugin) self._add_encryption_name_from_plugin(plugin) self._handle_all_gui_extension_points_with_plugin(plugin) self._register_events_handlers_in_ged(plugin) self._register_network_events_in_nec(plugin) self._register_modules_with_handlers(plugin) self.active_plugins.append(plugin) try: plugin.activate() except GajimPluginException as e: self.deactivate_plugin(plugin) raise GajimPluginActivateException(str(e)) self._set_plugin_active_in_global_config(plugin) plugin.active = True def deactivate_plugin(self, plugin): # remove GUI extension points handlers (provided by plug-in) from # handlers list for gui_extpoint_name, gui_extpoint_handlers in \ plugin.gui_extension_points.items(): self.gui_extension_points_handlers[gui_extpoint_name].remove( gui_extpoint_handlers) # detaching plug-in from handler GUI extension points (calling # cleaning up method that must be provided by plug-in developer # for each handled GUI extension point) for gui_extpoint_name, gui_extpoint_handlers in \ plugin.gui_extension_points.items(): if gui_extpoint_name in self.gui_extension_points: for gui_extension_point_args in self.gui_extension_points[ gui_extpoint_name]: handler = gui_extpoint_handlers[1] if handler: try: handler(*gui_extension_point_args) except Exception: log.warning('Error executing %s', handler, exc_info=True) self._remove_events_handler_from_ged(plugin) self._remove_network_events_from_nec(plugin) self._remove_name_from_encryption_plugins(plugin) self._unregister_modules_with_handlers(plugin) # removing plug-in from active plug-ins list plugin.deactivate() self.active_plugins.remove(plugin) self._set_plugin_active_in_global_config(plugin, False) plugin.active = False def _deactivate_all_plugins(self): for plugin_object in self.active_plugins: self.deactivate_plugin(plugin_object) @log_calls('PluginManager') def _add_gui_extension_points_handlers_from_plugin(self, plugin): for gui_extpoint_name, gui_extpoint_handlers in \ plugin.gui_extension_points.items(): self.gui_extension_points_handlers.setdefault(gui_extpoint_name, []).append(gui_extpoint_handlers) def _add_encryption_name_from_plugin(self, plugin): if plugin.encryption_name: self.encryption_plugins[plugin.encryption_name] = plugin @log_calls('PluginManager') def _handle_all_gui_extension_points_with_plugin(self, plugin): for gui_extpoint_name, gui_extpoint_handlers in \ plugin.gui_extension_points.items(): if gui_extpoint_name in self.gui_extension_points: for gui_extension_point_args in self.gui_extension_points[ gui_extpoint_name]: handler = gui_extpoint_handlers[0] if handler: try: handler(*gui_extension_point_args) except Exception: log.warning('Error executing %s', handler, exc_info=True) @log_calls('PluginManager') def _activate_all_plugins(self): ''' Activates all plugins in `plugins`. Activated plugins are appended to `active_plugins` list. ''' for plugin in self.plugins: try: self.activate_plugin(plugin) except GajimPluginActivateException: pass def _activate_all_plugins_from_global_config(self): for plugin in self.plugins: if self._plugin_is_active_in_global_config(plugin) and \ plugin.activatable: try: self.activate_plugin(plugin) except GajimPluginActivateException: pass def register_modules_for_account(self, con): ''' A new account has been added, register modules of all active plugins ''' for plugin in self.plugins: if not plugin.active: return if not hasattr(plugin, 'modules'): return for module in plugin.modules: if not module.zeroconf and con.name == 'Local': continue instance, name = module.get_instance(con) modules.register_single(con, instance, name) def _plugin_is_active_in_global_config(self, plugin): return app.config.get_per('plugins', plugin.short_name, 'active') def _set_plugin_active_in_global_config(self, plugin, active=True): app.config.set_per('plugins', plugin.short_name, 'active', active) @log_calls('PluginManager') def scan_dir_for_plugins(self, path, scan_dirs=True, package=False): r''' Scans given directory for plugin classes. :param path: directory to scan for plugins :type path: str :param scan_dirs: folders inside path are processed as modules :type scan_dirs: boolean :param package: if path points to a single package folder :type package: boolean :return: list of found plugin classes (subclasses of `GajimPlugin` :rtype: [] of class objects :note: currently it only searches for plugin classes in '\*.py' files present in given directory `path` (no recursion here) :todo: add scanning zipped modules ''' plugins_found = [] conf = configparser.ConfigParser() fields = ('name', 'short_name', 'version', 'description', 'authors', 'homepage') if not os.path.isdir(path): return plugins_found if package: path, package_name = os.path.split(path) dir_list = [package_name] else: dir_list = os.listdir(path) sys.path.insert(0, path) for elem_name in dir_list: file_path = os.path.join(path, elem_name) if os.path.isfile(file_path) and fnmatch.fnmatch(file_path, '*.py'): module_name = os.path.splitext(elem_name)[0] elif os.path.isdir(file_path) and scan_dirs: module_name = elem_name file_path += os.path.sep else: continue manifest_path = os.path.join(os.path.dirname(file_path), 'manifest.ini') if scan_dirs and (not os.path.isfile(manifest_path)): continue # read metadata from manifest.ini conf.remove_section('info') with open(manifest_path, encoding='utf-8') as conf_file: try: conf.read_file(conf_file) except configparser.Error: log.warning('Plugin %s not loaded, error loading manifest', elem_name, exc_info=True) continue short_name = conf.get('info', 'short_name', fallback=None) if short_name is None: log.error('No short_name defined for %s', elem_name) # Check if the plugin is already loaded try: for plugin in self.plugins: if plugin.short_name == short_name: raise PluginAlreadyLoaded( 'Skip Plugin %s because its ' 'already loaded' % elem_name) except PluginAlreadyLoaded as error: log.warning(error) continue min_v = conf.get('info', 'min_gajim_version', fallback=None) max_v = conf.get('info', 'max_gajim_version', fallback=None) if min_v is None or max_v is None: log.warning('Plugin without min/max version: %s', elem_name) continue gajim_v = gajim.__version__.split('+', 1)[0] gajim_v_cmp = parse_version(gajim_v) if min_v and gajim_v_cmp < parse_version(min_v): log.warning('Plugin %s not loaded, newer version of' 'gajim required: %s < %s', elem_name, gajim_v, min_v) continue if max_v and gajim_v_cmp > parse_version(max_v): log.warning('Plugin %s not loaded, plugin incompatible ' 'with current version of gajim: ' '%s > %s', elem_name, gajim_v, max_v) continue module = None try: log.info('Loading %s', module_name) module = __import__(module_name) except Exception: log.warning( 'While trying to load %s, exception occurred', elem_name, exc_info=True) continue if module is None: continue log.debug('Attributes processing started') for module_attr_name in [attr_name for attr_name in dir(module) if not (attr_name.startswith('__') or attr_name.endswith('__'))]: module_attr = getattr(module, module_attr_name) log.debug('%s: %s', module_attr_name, module_attr) try: if not issubclass(module_attr, GajimPlugin) or \ module_attr is GajimPlugin: continue log.debug('is subclass of GajimPlugin') module_attr.__path__ = os.path.abspath( os.path.dirname(file_path)) for option in fields: if conf.get('info', option) == '': raise configparser.NoOptionError(option, 'info') if option == 'description': setattr(module_attr, option, plugins_i18n._(conf.get('info', option))) continue setattr(module_attr, option, conf.get('info', option)) plugins_found.append(module_attr) except TypeError: # set plugin localization try: module_attr._ = plugins_i18n._ except AttributeError: pass except configparser.NoOptionError: # all fields are required log.debug( '%s: wrong manifest file. all fields are required!', module_attr_name) except configparser.NoSectionError: # info section are required log.debug( '%s: wrong manifest file. info section are required!', module_attr_name) except configparser.MissingSectionHeaderError: # info section are required log.debug('%s: wrong manifest file. section are required!', module_attr_name) sys.path.remove(path) return plugins_found def install_from_zip(self, zip_filename, owerwrite=None): ''' Install plugin from zip and return plugin ''' try: zip_file = zipfile.ZipFile(zip_filename) except zipfile.BadZipfile: # it is not zip file raise PluginsystemError(_('Archive corrupted')) except IOError: raise PluginsystemError(_('Archive empty')) if zip_file.testzip(): # CRC error raise PluginsystemError(_('Archive corrupted')) dirs = [] manifest = None for filename in zip_file.namelist(): if filename.startswith('.') or filename.startswith('/') or \ ('/' not in filename): # members not safe raise PluginsystemError(_('Archive is malformed')) if filename.endswith('/') and filename.find('/', 0, -1) < 0: dirs.append(filename.strip('/')) if 'manifest.ini' in filename.split('/')[1]: manifest = True if not manifest: return if len(dirs) > 1: raise PluginsystemError(_('Archive is malformed')) user_dir = configpaths.get('PLUGINS_USER') plugin_dir = os.path.join(user_dir, dirs[0]) if os.path.isdir(plugin_dir): # Plugin dir already exists if not owerwrite: raise PluginsystemError(_('Plugin already exists')) self.uninstall_plugin(self.get_plugin_by_path(plugin_dir)) zip_file.extractall(user_dir) zip_file.close() plugins = self.scan_dir_for_plugins(plugin_dir, package=True) if not plugins: return self.add_plugin(plugins[0]) plugin = self.plugins[-1] return plugin def delete_plugin_files(self, plugin_path): def on_error(func, path, error): if func == os.path.islink: # if symlink os.unlink(path) return # access is denied or other raise PluginsystemError(error[1][1]) rmtree(plugin_path, False, on_error) def uninstall_plugin(self, plugin): ''' Deactivate and remove plugin from `plugins` list ''' if plugin: self.remove_plugin(plugin) self.delete_plugin_files(plugin.__path__) if self._plugin_has_entry_in_global_config(plugin): self._remove_plugin_entry_in_global_config(plugin) def get_plugin_by_path(self, plugin_dir): for plugin in self.plugins: if plugin.__path__ in plugin_dir: return plugin class PluginAlreadyLoaded(Exception): pass gajim-gajim-1.1.3/gajim/plugins/plugins_i18n.py000066400000000000000000000021461345766322700213540ustar00rootroot00000000000000# Copyright (C) 2010-2011 Denis Fomin # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import locale import gettext from gajim.common import configpaths DOMAIN = 'gajim_plugins' plugin_user_dir = configpaths.get('PLUGINS_USER') plugins_locale_dir = os.path.join(plugin_user_dir, 'locale') try: t = gettext.translation(DOMAIN, plugins_locale_dir) _ = t.gettext except OSError: _ = gettext.gettext if hasattr(locale, 'bindtextdomain'): locale.bindtextdomain(DOMAIN, plugins_locale_dir) # type: ignore gajim-gajim-1.1.3/gajim/remote_control.py000066400000000000000000001124731345766322700204130ustar00rootroot00000000000000# Copyright (C) 2005-2006 Andrew Sayman # Dimitur Kirov # Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006-2007 Travis Shirk # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # Julien Pivotto # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import base64 import mimetypes from gi.repository import GLib from gi.repository import Gio from gajim.common import app from gajim.common import helpers from gajim.gtk.add_contact import AddNewContactWindow from gajim.common import ged from gajim.common.connection_handlers_events import MessageOutgoingEvent from gajim.common.connection_handlers_events import GcMessageOutgoingEvent def get_dbus_struct(obj): """ Recursively go through all the items and replace them with their casted dbus equivalents """ if obj is None: return None if isinstance(obj, str): return GLib.Variant('s', obj) if isinstance(obj, int): return GLib.Variant('i', obj) if isinstance(obj, float): return GLib.Variant('d', obj) if isinstance(obj, bool): return GLib.Variant('b', obj) if isinstance(obj, (list, tuple)): lst = [get_dbus_struct(i) for i in obj if i is not None] result = GLib.Variant('av', lst) return result if isinstance(obj, dict): result = GLib.VariantDict() for key, value in obj.items(): result.insert_value(key, get_dbus_struct(value)) return result.end() # unknown type return GLib.Variant('s', str(obj)) class Server: def __init__(self, con, path): method_outargs = {} method_inargs = {} for interface in Gio.DBusNodeInfo.new_for_xml(self.__doc__).interfaces: for method in interface.methods: method_outargs[method.name] = '(' + ''.join( [arg.signature for arg in method.out_args]) + ')' method_inargs[method.name] = tuple( arg.signature for arg in method.in_args) con.register_object( object_path=path, interface_info=interface, method_call_closure=self.on_method_call) self.method_inargs = method_inargs self.method_outargs = method_outargs def on_method_call(self, connection, sender, object_path, interface_name, method_name, parameters, invocation): args = list(parameters.unpack()) for i, sig in enumerate(self.method_inargs[method_name]): if sig == 'h': msg = invocation.get_message() fd_list = msg.get_unix_fd_list() args[i] = fd_list.get(args[i]) result = getattr(self, method_name)(*args) # out_args is atleast (signature1). We therefore always wrap the result # as a tuple. Refer to https://bugzilla.gnome.org/show_bug.cgi?id=765603 result = (result, ) out_args = self.method_outargs[method_name] if out_args != '()': variant = GLib.Variant(out_args, result) invocation.return_value(variant) else: invocation.return_value(None) class GajimRemote(Server): ''' ''' def __init__(self): self.con = Gio.bus_get_sync(Gio.BusType.SESSION, None) Gio.bus_own_name_on_connection(self.con, 'org.gajim.Gajim', Gio.BusNameOwnerFlags.NONE, None, None) super().__init__(self.con, '/org/gajim/dbus/RemoteObject') self.first_show = True app.ged.register_event_handler('version-result-received', ged.POSTGUI, self.on_os_info) app.ged.register_event_handler('time-result-received', ged.POSTGUI, self.on_time) app.ged.register_event_handler('roster-info', ged.POSTGUI, self.on_roster_info) app.ged.register_event_handler('presence-received', ged.POSTGUI, self.on_presence_received) app.ged.register_event_handler('subscribe-presence-received', ged.POSTGUI, self.on_subscribe_presence_received) app.ged.register_event_handler('subscribed-presence-received', ged.POSTGUI, self.on_subscribed_presence_received) app.ged.register_event_handler('unsubscribed-presence-received', ged.POSTGUI, self.on_unsubscribed_presence_received) app.ged.register_event_handler('gc-message-received', ged.POSTGUI, self.on_gc_message_received) app.ged.register_event_handler('decrypted-message-received', ged.POSTGUI, self._nec_decrypted_message_received) app.ged.register_event_handler('our-show', ged.POSTGUI, self.on_our_status) app.ged.register_event_handler('account-created', ged.POSTGUI, self.on_account_created) app.ged.register_event_handler('vcard-received', ged.POSTGUI, self.on_vcard_received) app.ged.register_event_handler('chatstate-received', ged.POSTGUI, self.on_chatstate_received) app.ged.register_event_handler('message-sent', ged.POSTGUI, self.on_message_sent) def on_chatstate_received(self, obj): if obj.contact.is_gc_contact: jid = obj.contact.get_full_jid() chatstate = obj.contact.chatstate else: jid = obj.contact.jid chatstate = app.contacts.get_combined_chatstate( obj.account, obj.contact.jid) self.raise_signal('ChatState', (obj.account, [jid, chatstate])) def on_message_sent(self, obj): try: chatstate = obj.chatstate except AttributeError: chatstate = '' self.raise_signal('MessageSent', (obj.conn.name, [ obj.jid, obj.message, obj.keyID, chatstate])) def on_os_info(self, obj): self.raise_signal('OsInfo', (obj.conn.name, [obj.jid.getStripped(), obj.jid.getResource(), obj.client_info, obj.os_info])) def on_time(self, obj): self.raise_signal('EntityTime', (obj.conn.name, [obj.jid.getStripped(), obj.jid.getResource(), obj.time_info])) def on_roster_info(self, obj): self.raise_signal('RosterInfo', (obj.conn.name, [obj.jid, obj.nickname, obj.sub, obj.ask, obj.groups])) def on_presence_received(self, obj): if obj.old_show < 2 and obj.new_show > 1: event = 'ContactPresence' elif obj.old_show > 1 and obj.new_show < 2: event = 'ContactAbsence' elif obj.new_show > 1: event = 'ContactStatus' else: return self.raise_signal(event, (obj.conn.name, [obj.jid, obj.show, obj.status, obj.resource, obj.prio, obj.keyID, obj.timestamp, obj.contact_nickname])) def on_subscribe_presence_received(self, obj): self.raise_signal('Subscribe', (obj.conn.name, [obj.jid, obj.status, obj.user_nick])) def on_subscribed_presence_received(self, obj): self.raise_signal('Subscribed', (obj.conn.name, [obj.jid, obj.resource])) def on_unsubscribed_presence_received(self, obj): self.raise_signal('Unsubscribed', (obj.conn.name, obj.jid)) def on_gc_message_received(self, obj): if not hasattr(obj, 'needs_highlight'): # event has not been handled at GUI level return self.raise_signal('GCMessage', (obj.conn.name, [obj.fjid, obj.msgtxt, obj.timestamp, obj.delayed, obj.xhtml_msgtxt, obj.status_code, obj.displaymarking, obj.captcha_form, obj.needs_highlight])) def _nec_decrypted_message_received(self, obj): self.raise_signal('NewMessage', ( obj.conn.name, [obj.fjid, obj.msgtxt, obj.timestamp, obj.encrypted, obj.mtype, obj.subject, obj.msg_log_id, obj.user_nick, obj.xhtml, obj.form_node])) def on_our_status(self, obj): self.raise_signal('AccountPresence', (obj.show, obj.conn.name)) def on_account_created(self, obj): self.raise_signal('NewAccount', (obj.conn.name, obj.account_info)) def on_vcard_received(self, obj): self.raise_signal('VcardInfo', (obj.conn.name, obj.vcard_dict)) def raise_signal(self, event_name, data): self.con.emit_signal(None, '/org/gajim/dbus/RemoteObject', 'org.gajim.dbus.RemoteInterface', event_name, GLib.Variant.new_tuple(get_dbus_struct(data))) def get_status(self, account): """ Return status (show to be exact) which is the global one unless account is given """ if not account: # If user did not ask for account, returns the global status return helpers.get_global_show() # return show for the given account index = app.connections[account].connected return app.SHOW_LIST[index] def get_status_message(self, account): """ Return status which is the global one unless account is given """ if not account: # If user did not ask for account, returns the global status return str(helpers.get_global_status()) # return show for the given account status = app.connections[account].status return status def _get_account_and_contact(self, account, jid): """ Get the account (if not given) and contact instance from jid """ connected_account = None contact = None accounts = app.contacts.get_accounts() # if there is only one account in roster, take it as default # if user did not ask for account if not account and len(accounts) == 1: account = accounts[0] if account: if app.connections[account].connected > 1: # account is connected connected_account = account contact = app.contacts.get_contact_with_highest_priority( account, jid) else: for account_ in accounts: contact = app.contacts.get_contact_with_highest_priority( account, jid) if contact and app.connections[account_].connected > 1: # account is connected connected_account = account_ break if not contact: contact = jid return connected_account, contact def _get_account_for_groupchat(self, account, room_jid): """ Get the account which is connected to groupchat (if not given) or check if the given account is connected to the groupchat """ connected_account = None accounts = app.contacts.get_accounts() # if there is only one account in roster, take it as default # if user did not ask for account if not account and len(accounts) == 1: account = accounts[0] if account: if app.connections[account].connected > 1 and \ room_jid in app.gc_connected[account] and \ app.gc_connected[account][room_jid]: # account and groupchat are connected connected_account = account else: for account_ in accounts: if app.connections[account_].connected > 1 and \ room_jid in app.gc_connected[account_] and \ app.gc_connected[account_][room_jid]: # account and groupchat are connected connected_account = account_ break return connected_account def send_file(self, file_path, jid, account): """ Send file, located at 'file_path' to 'jid', using account (optional) 'account' """ jid = self._get_real_jid(jid, account) connected_account, contact = self._get_account_and_contact( account, jid) if connected_account: if file_path.startswith('file://'): file_path = file_path[7:] if os.path.isfile(file_path): # is it file? app.interface.instances['file_transfers'].send_file( connected_account, contact, file_path) return True return False def _send_message(self, jid, message, keyID, account, type_='chat', subject=None): """ Can be called from send_chat_message (default when send_message) or send_single_message """ if not jid or not message: return False if not keyID: keyID = '' connected_account = self._get_account_and_contact(account, jid)[0] if connected_account: connection = app.connections[connected_account] sessions = connection.get_sessions(jid) if not sessions: connection.make_new_session(jid) ctrl = app.interface.msg_win_mgr.search_control( jid, connected_account) if ctrl: ctrl.send_message(message) else: app.nec.push_outgoing_event( MessageOutgoingEvent( None, account=connected_account, jid=jid, message=message, keyID=keyID, type_=type_, control=ctrl)) return True return False def send_chat_message(self, jid, message, keyID, account): """ Send chat 'message' to 'jid', using account (optional) 'account'. If keyID is specified, encrypt the message with the pgp key """ jid = self._get_real_jid(jid, account) return self._send_message(jid, message, keyID, account) def send_single_message(self, jid, subject, message, keyID, account): """ Send single 'message' to 'jid', using account (optional) 'account'. If keyID is specified, encrypt the message with the pgp key """ jid = self._get_real_jid(jid, account) return self._send_message(jid, message, keyID, account, 'normal', subject) def send_groupchat_message(self, room_jid, message, account): """ Send 'message' to groupchat 'room_jid', using account (optional) 'account' """ if not room_jid or not message: return False connected_account = self._get_account_for_groupchat(account, room_jid) if connected_account: app.nec.push_outgoing_event( GcMessageOutgoingEvent( None, account=connected_account, jid=room_jid, message=message)) return True return False def open_chat(self, jid, account, message): """ Shows the tabbed window for new message to 'jid', using account (optional) 'account' """ if not jid: raise ValueError('jid is missing') jid = self._get_real_jid(jid, account) try: jid = helpers.parse_jid(jid) except Exception: # Jid is not conform, ignore it return False minimized_control = None if account: accounts = [account] else: accounts = app.connections.keys() if len(accounts) == 1: account = accounts[0] connected_account = None first_connected_acct = None for acct in accounts: if app.connections[acct].connected > 1: # account is online contact = app.contacts.get_first_contact_from_jid(acct, jid) if app.interface.msg_win_mgr.has_window(jid, acct): connected_account = acct break # jid is in roster elif contact: minimized_control = \ jid in app.interface.minimized_controls[acct] connected_account = acct break # we send the message to jid not in roster, because account is # specified, or there is only one account elif account: connected_account = acct elif first_connected_acct is None: first_connected_acct = acct # if jid is not a contact, open-chat with first connected account if connected_account is None and first_connected_acct: connected_account = first_connected_acct if minimized_control: app.interface.roster.on_groupchat_maximized( None, jid, connected_account) if connected_account: app.interface.new_chat_from_jid(connected_account, jid, message) # preserve the 'steal focus preservation' win = app.interface.msg_win_mgr.get_window( jid, connected_account).window if win.get_property('visible'): win.window.present() return True return False def change_status(self, status, message, account): """ change_status(status, message, account). Account is optional - if not specified status is changed for all accounts """ if status not in ('offline', 'online', 'chat', 'away', 'xa', 'dnd', 'invisible'): status = '' if account: if not status: if account not in app.connections: return False status = app.SHOW_LIST[app.connections[account].connected] GLib.idle_add(app.interface.roster.send_status, account, status, message) else: # account not specified, so change the status of all accounts for acc in app.contacts.get_accounts(): if not app.config.get_per('accounts', acc, 'sync_with_global_status'): continue if status: status_ = status else: if acc not in app.connections: continue status_ = app.SHOW_LIST[app.connections[acc].connected] GLib.idle_add(app.interface.roster.send_status, acc, status_, message) return False def set_priority(self, prio, account): """ set_priority(prio, account). Account is optional - if not specified priority is changed for all accounts. That are synced with global status """ if account: app.config.set_per('accounts', account, 'priority', prio) show = app.SHOW_LIST[app.connections[account].connected] status = app.connections[account].status GLib.idle_add(app.connections[account].change_status, show, status) else: # account not specified, so change prio of all accounts for acc in app.contacts.get_accounts(): if not app.account_is_connected(acc): continue if not app.config.get_per('accounts', acc, 'sync_with_global_status'): continue app.config.set_per('accounts', acc, 'priority', prio) show = app.SHOW_LIST[app.connections[acc].connected] status = app.connections[acc].status GLib.idle_add(app.connections[acc].change_status, show, status) def show_next_pending_event(self): """ Show the window(s) with next pending event in tabbed/group chats """ if app.events.get_nb_events(): account, jid, event = app.events.get_first_systray_event() if not event: return app.interface.handle_event(account, jid, event.type_) def list_accounts(self): """ List register accounts """ result = app.contacts.get_accounts() result_array = [] if result: for account in result: result_array.append(account) return result_array def account_info(self, account): """ Show info on account: resource, jid, nick, prio, message """ result = {} if account in app.connections: # account is valid con = app.connections[account] index = con.connected result['status'] = app.SHOW_LIST[index] result['name'] = con.name result['jid'] = app.get_jid_from_account(con.name) result['message'] = con.status result['priority'] = str(con.priority) result['resource'] = app.config.get_per('accounts', con.name, 'resource') return result def list_contacts(self, account): """ List all contacts in the roster. If the first argument is specified, then return the contacts for the specified account """ result = [] accounts = app.contacts.get_accounts() if not accounts: return result if account: accounts_to_search = [account] else: accounts_to_search = accounts for acct in accounts_to_search: if acct in accounts: for jid in app.contacts.get_jid_list(acct): item = self._contacts_as_dbus_structure( app.contacts.get_contacts(acct, jid)) if item: result.append(item) return result def prefs_list(self): prefs_dict = {} def get_prefs(data, name, path, value): if value is None: return key = '' if path is not None: for node in path: key += node + '#' key += name prefs_dict[key] = str(value) app.config.foreach(get_prefs) return prefs_dict def prefs_store(self): try: app.interface.save_config() except Exception: return False return True def prefs_del(self, key): if not key: return False key_path = key.split('#', 2) if len(key_path) != 3: return False if key_path[2] == '*': app.config.del_per(key_path[0], key_path[1]) else: app.config.del_per(key_path[0], key_path[1], key_path[2]) return True def prefs_put(self, key): if not key: return False key_path = key.split('#', 2) if len(key_path) < 3: subname, value = key.split('=', 1) app.config.set(subname, value) return True subname, value = key_path[2].split('=', 1) app.config.set_per(key_path[0], key_path[1], subname, value) return True def add_contact(self, jid, account): if account: if account in app.connections and \ app.connections[account].connected > 1: # if given account is active, use it AddNewContactWindow(account=account, jid=jid) else: # wrong account return False else: # if account is not given, show account combobox AddNewContactWindow(account=None, jid=jid) return True def remove_contact(self, jid, account): jid = self._get_real_jid(jid, account) accounts = app.contacts.get_accounts() # if there is only one account in roster, take it as default if account: accounts = [account] contact_exists = False for account_ in accounts: contacts = app.contacts.get_contacts(account_, jid) if contacts: app.connections[account_].get_module('Presence').unsubscribe(jid) for contact in contacts: app.interface.roster.remove_contact(contact, account_) app.contacts.remove_jid(account_, jid) contact_exists = True return contact_exists def _is_first(self): if self.first_show: self.first_show = False return True return False def _get_real_jid(self, jid, account=None): """ Get the real jid from the given one: removes xmpp: or get jid from nick if account is specified, search only in this account """ if account: accounts = [account] else: accounts = app.connections.keys() if jid.startswith('xmpp:'): return jid[5:] # len('xmpp:') = 5 nick_in_roster = None # Is jid a nick ? for account_ in accounts: # Does jid exists in roster of one account ? if app.contacts.get_contacts(account_, jid): return jid if not nick_in_roster: # look in all contact if one has jid as nick for jid_ in app.contacts.get_jid_list(account_): c = app.contacts.get_contacts(account_, jid_) if c[0].name == jid: nick_in_roster = jid_ break if nick_in_roster: # We have not found jid in roster, but we found is as a nick return nick_in_roster # We have not found it as jid nor as nick, probably a not in roster jid return jid def _contacts_as_dbus_structure(self, contacts): """ Get info from list of Contact objects and create dbus dict """ if not contacts: return None prim_contact = None # primary contact for contact in contacts: if prim_contact is None or contact.priority > prim_contact.priority: prim_contact = contact contact_dict = {} name = prim_contact.name if prim_contact.name is not None else '' contact_dict['name'] = GLib.Variant('s', name) contact_dict['show'] = GLib.Variant('s', prim_contact.show) contact_dict['jid'] = GLib.Variant('s', prim_contact.jid) if prim_contact.keyID: keyID = None if len(prim_contact.keyID) == 8: keyID = prim_contact.keyID elif len(prim_contact.keyID) == 16: keyID = prim_contact.keyID[8:] if keyID: contact_dict['openpgp'] = GLib.Variant('s', keyID) resources = GLib.VariantBuilder(GLib.VariantType('a(sis)')) for contact in contacts: resource_props = (contact.resource, int(contact.priority), contact.status) resources.add_value(GLib.Variant('(sis)', resource_props)) contact_dict['resources'] = resources.end() groups = GLib.VariantBuilder(GLib.VariantType('as')) for group in prim_contact.groups: groups.add_value(GLib.Variant('s', group)) contact_dict['groups'] = groups.end() return contact_dict def get_unread_msgs_number(self): unread = app.events.get_nb_events() for event in app.events.get_all_events(['printed_gc_msg']): if not app.config.notify_for_muc(event.jid): unread -= 1 return str(unread) def start_chat(self, account): if not account: # error is shown in gajim-remote check_arguments(..) return False app.app.activate_action('start-chat') return True def send_xml(self, xml, account): if account: app.connections[account].send_stanza(str(xml)) else: for acc in app.contacts.get_accounts(): app.connections[acc].send_stanza(str(xml)) def change_avatar(self, picture, account): filesize = os.path.getsize(picture) invalid_file = False if os.path.isfile(picture): stat = os.stat(picture) if stat[6] == 0: invalid_file = True else: invalid_file = True if not invalid_file and filesize < 16384: sha = app.interface.save_avatar(picture, publish=True) if sha is None: return app.config.set_per('accounts', self.name, 'avatar_sha', sha) data = app.interface.get_avatar(sha, publish=True) avatar = base64.b64encode(data).decode('utf-8') avatar_mime_type = mimetypes.guess_type(picture)[0] vcard = {} vcard['PHOTO'] = {'BINVAL': avatar} if avatar_mime_type: vcard['PHOTO']['TYPE'] = avatar_mime_type if account: app.connections[account].get_module('VCardTemp').send_vcard( vcard, sha) else: for acc in app.connections: app.connections[acc].get_module('VCardTemp').send_vcard( vcard, sha) def join_room(self, room_jid, nick, password, account): if not account: # get the first connected account accounts = app.connections.keys() for acct in accounts: if app.account_is_connected(acct): if not app.connections[acct].is_zeroconf: account = acct break if not account: return if app.connections[account].is_zeroconf: # zeroconf not support groupchats return if not nick: app.interface.join_gc_minimal(account, room_jid) else: app.interface.join_gc_room(account, room_jid, nick, password) def Introspect(self): return self.__doc__ gajim-gajim-1.1.3/gajim/roster_window.py000066400000000000000000007446361345766322700203010ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Alex Mauer # Stéphan Kochen # Copyright (C) 2005-2006 Dimitur Kirov # Copyright (C) 2005-2007 Travis Shirk # Nikos Kouremenos # Copyright (C) 2006 Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # James Newton # Tomasz Melcer # Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys import time import locale import logging from enum import IntEnum, unique from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import Pango from gi.repository import GObject from gi.repository import GLib from gi.repository import Gio from nbxmpp.protocol import NS_FILE, NS_ROSTERX, NS_CONFERENCE from gajim import dialogs from gajim import vcard from gajim import disco from gajim import gtkgui_helpers from gajim import gui_menu_builder from gajim import cell_renderer_image from gajim import tooltips from gajim import message_control from gajim import adhoc_commands from gajim.common import app from gajim.common import helpers from gajim.common import idle from gajim.common.exceptions import GajimGeneralException from gajim.common import i18n from gajim.common.helpers import save_roster_position from gajim.common.i18n import _ from gajim.common.const import PEPEventType, AvatarSize, StyleAttr from gajim.common.dbus import location from gajim.common import ged from gajim.message_window import MessageWindowMgr from gajim.gtk.dialogs import ConfirmationDialogCheck from gajim.gtk.dialogs import ConfirmationDialog from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import InputDialog from gajim.gtk.dialogs import WarningDialog from gajim.gtk.dialogs import InformationDialog from gajim.gtk.dialogs import NonModalConfirmationDialog from gajim.gtk.join_groupchat import JoinGroupchatWindow from gajim.gtk.single_message import SingleMessageWindow from gajim.gtk.add_contact import AddNewContactWindow from gajim.gtk.pep_config import ManagePEPServicesWindow from gajim.gtk.bookmarks import ManageBookmarksWindow from gajim.gtk.account_wizard import AccountCreationWizard from gajim.gtk.service_registration import ServiceRegistration from gajim.gtk.history import HistoryWindow from gajim.gtk.accounts import AccountsWindow from gajim.gtk.util import restore_roster_position log = logging.getLogger('gajim.roster') @unique class Column(IntEnum): IMG = 0 # image to show state (online, new message etc) NAME = 1 # cellrenderer text that holds contact nickame TYPE = 2 # account, group or contact? JID = 3 # the jid of the row ACCOUNT = 4 # cellrenderer text that holds account name MOOD_PIXBUF = 5 ACTIVITY_PIXBUF = 6 TUNE_PIXBUF = 7 LOCATION_PIXBUF = 8 AVATAR_IMG = 9 # avatar_sha PADLOCK_PIXBUF = 10 # use for account row only VISIBLE = 11 empty_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 1, 1) empty_pixbuf.fill(0xffffff00) class RosterWindow: """ Class for main window of the GTK+ interface """ def _get_account_iter(self, name, model=None): """ Return the Gtk.TreeIter of the given account or None if not found Keyword arguments: name -- the account name model -- the data model (default TreeFilterModel) """ if model is None: model = self.modelfilter if model is None: return if self.regroup: name = 'MERGED' if name not in self._iters: return None it = self._iters[name]['account'] if model == self.model or it is None: return it try: (ok, it) = self.modelfilter.convert_child_iter_to_iter(it) if ok: return it return None except RuntimeError: return None def _get_group_iter(self, name, account, model=None): """ Return the Gtk.TreeIter of the given group or None if not found Keyword arguments: name -- the group name account -- the account name model -- the data model (default TreeFilterModel) """ if model is None: model = self.modelfilter if model is None: return if self.regroup: account = 'MERGED' if account not in self._iters: return None if name not in self._iters[account]['groups']: return None it = self._iters[account]['groups'][name] if model == self.model or it is None: return it try: (ok, it) = self.modelfilter.convert_child_iter_to_iter(it) if ok: return it return None except RuntimeError: return None def _get_self_contact_iter(self, account, model=None): """ Return the Gtk.TreeIter of SelfContact or None if not found Keyword arguments: account -- the account of SelfContact model -- the data model (default TreeFilterModel) """ jid = app.get_jid_from_account(account) its = self._get_contact_iter(jid, account, model=model) if its: return its[0] return None def _get_contact_iter(self, jid, account, contact=None, model=None): """ Return a list of Gtk.TreeIter of the given contact Keyword arguments: jid -- the jid without resource account -- the account contact -- the contact (default None) model -- the data model (default TreeFilterModel) """ if model is None: model = self.modelfilter # when closing Gajim model can be none (async pbs?) if model is None: return [] if not contact: contact = app.contacts.get_first_contact_from_jid(account, jid) if not contact: # We don't know this contact return [] if account not in self._iters: return [] if jid not in self._iters[account]['contacts']: return [] its = self._iters[account]['contacts'][jid] if not its: return [] if model == self.model: return its its2 = [] for it in its: try: (ok, it) = self.modelfilter.convert_child_iter_to_iter(it) if ok: its2.append(it) except RuntimeError: pass return its2 @staticmethod def _iter_is_separator(model, titer): """ Return True if the given iter is a separator Keyword arguments: model -- the data model iter -- the Gtk.TreeIter to test """ if model[titer][0] == 'SEPARATOR': return True return False @staticmethod def _status_cell_data_func(cell_layout, cell, tree_model, iter_): if isinstance(cell, Gtk.CellRendererPixbuf): icon_name = tree_model[iter_][1] if icon_name is None: return if tree_model[iter_][2] == 'status': cell.set_property('icon_name', icon_name) else: iconset_name = gtkgui_helpers.get_iconset_name_for(icon_name) cell.set_property('icon_name', iconset_name) else: show = tree_model[iter_][0] id_ = tree_model[iter_][2] if id_ not in ('status', 'desync'): show = helpers.get_uf_show(show) cell.set_property('text', show) ############################################################################# ### Methods for adding and removing roster window items ############################################################################# def add_account(self, account): """ Add account to roster and draw it. Do nothing if it is already in """ if self._get_account_iter(account): # Will happen on reconnect or for merged accounts return if self.regroup: # Merged accounts view show = helpers.get_global_show() it = self.model.append(None, [ app.interface.jabber_state_images['16'][show], _('Merged accounts'), 'account', '', 'all', None, None, None, None, None, None, True] + [None] * self.nb_ext_renderers) self._iters['MERGED']['account'] = it else: show = app.SHOW_LIST[app.connections[account].connected] our_jid = app.get_jid_from_account(account) tls_pixbuf = None if app.account_is_securely_connected(account): tls_pixbuf = 'changes-prevent' it = self.model.append(None, [ app.interface.jabber_state_images['16'][show], GLib.markup_escape_text(account), 'account', our_jid, account, None, None, None, None, None, tls_pixbuf, True] + [None] * self.nb_ext_renderers) self._iters[account]['account'] = it self.draw_account(account) def add_account_contacts(self, account, improve_speed=True, draw_contacts=True): """ Add all contacts and groups of the given account to roster, draw them and account """ if improve_speed: self._before_fill() jids = app.contacts.get_jid_list(account) for jid in jids: self.add_contact(jid, account) if draw_contacts: # Do not freeze the GUI when drawing the contacts if jids: # Overhead is big, only invoke when needed self._idle_draw_jids_of_account(jids, account) # Draw all known groups for group in app.groups[account]: self.draw_group(group, account) self.draw_account(account) if improve_speed: self._after_fill() def _add_group_iter(self, account, group): """ Add a group iter in roster and return the newly created iter """ if self.regroup: account_group = 'MERGED' else: account_group = account delimiter = app.connections[account].get_module('Delimiter').delimiter group_splited = group.split(delimiter) parent_group = delimiter.join(group_splited[:-1]) if len(group_splited) > 1 and parent_group in self._iters[account_group]['groups']: iter_parent = self._iters[account_group]['groups'][parent_group] elif parent_group: iter_parent = self._add_group_iter(account, parent_group) if parent_group not in app.groups[account]: if account + parent_group in self.collapsed_rows: is_expanded = False else: is_expanded = True app.groups[account][parent_group] = {'expand': is_expanded} else: iter_parent = self._get_account_iter(account, self.model) iter_group = self.model.append(iter_parent, [app.interface.jabber_state_images['16']['closed'], GLib.markup_escape_text(group), 'group', group, account, None, None, None, None, None, None, False] + [None] * self.nb_ext_renderers) self.draw_group(group, account) self._iters[account_group]['groups'][group] = iter_group return iter_group def _add_entity(self, contact, account, groups=None, big_brother_contact=None, big_brother_account=None): """ Add the given contact to roster data model Contact is added regardless if he is already in roster or not. Return list of newly added iters. Keyword arguments: contact -- the contact to add account -- the contacts account groups -- list of groups to add the contact to. (default groups in contact.get_shown_groups()). Parameter ignored when big_brother_contact is specified. big_brother_contact -- if specified contact is added as child big_brother_contact. (default None) """ added_iters = [] visible = self.contact_is_visible(contact, account) if big_brother_contact: # Add contact under big brother parent_iters = self._get_contact_iter( big_brother_contact.jid, big_brother_account, big_brother_contact, self.model) assert parent_iters, 'Big brother is not yet in roster!' # Do not confuse get_contact_iter: Sync groups of family members contact.groups = big_brother_contact.groups[:] image = self._get_avatar_image(account, contact.jid) for child_iter in parent_iters: it = self.model.append(child_iter, [None, contact.get_shown_name(), 'contact', contact.jid, account, None, None, None, None, image, None, visible] + \ [None] * self.nb_ext_renderers) added_iters.append(it) if contact.jid in self._iters[account]['contacts']: self._iters[account]['contacts'][contact.jid].append(it) else: self._iters[account]['contacts'][contact.jid] = [it] else: # We are a normal contact. Add us to our groups. if not groups: groups = contact.get_shown_groups() for group in groups: child_iterG = self._get_group_iter(group, account, model=self.model) if not child_iterG: # Group is not yet in roster, add it! child_iterG = self._add_group_iter(account, group) if contact.is_transport(): typestr = 'agent' elif contact.is_groupchat(): typestr = 'groupchat' else: typestr = 'contact' image = self._get_avatar_image(account, contact.jid) # we add some values here. see draw_contact # for more i_ = self.model.append(child_iterG, [None, contact.get_shown_name(), typestr, contact.jid, account, None, None, None, None, image, None, visible] + \ [None] * self.nb_ext_renderers) added_iters.append(i_) if contact.jid in self._iters[account]['contacts']: self._iters[account]['contacts'][contact.jid].append(i_) else: self._iters[account]['contacts'][contact.jid] = [i_] # Restore the group expand state if account + group in self.collapsed_rows: is_expanded = False else: is_expanded = True if group not in app.groups[account]: app.groups[account][group] = {'expand': is_expanded} assert added_iters, '%s has not been added to roster!' % contact.jid return added_iters def _remove_entity(self, contact, account, groups=None): """ Remove the given contact from roster data model Empty groups after contact removal are removed too. Return False if contact still has children and deletion was not performed. Return True on success. Keyword arguments: contact -- the contact to add account -- the contacts account groups -- list of groups to remove the contact from. """ iters = self._get_contact_iter(contact.jid, account, contact, self.model) assert iters, '%s shall be removed but is not in roster' % contact.jid parent_iter = self.model.iter_parent(iters[0]) parent_type = self.model[parent_iter][Column.TYPE] if groups: # Only remove from specified groups all_iters = iters[:] group_iters = [self._get_group_iter(group, account) for group in groups] iters = [titer for titer in all_iters if self.model.iter_parent(titer) in group_iters] iter_children = self.model.iter_children(iters[0]) if iter_children: # We have children. We cannot be removed! return False # Remove us and empty groups from the model for i in iters: assert self.model[i][Column.JID] == contact.jid and \ self.model[i][Column.ACCOUNT] == account, \ "Invalidated iters of %s" % contact.jid parent_i = self.model.iter_parent(i) parent_type = self.model[parent_i][Column.TYPE] to_be_removed = i while parent_type == 'group' and \ self.model.iter_n_children(parent_i) == 1: if self.regroup: account_group = 'MERGED' else: account_group = account group = self.model[parent_i][Column.JID] if group in app.groups[account]: del app.groups[account][group] to_be_removed = parent_i del self._iters[account_group]['groups'][group] parent_i = self.model.iter_parent(parent_i) parent_type = self.model[parent_i][Column.TYPE] self.model.remove(to_be_removed) del self._iters[account]['contacts'][contact.jid] return True def _add_metacontact_family(self, family, account): """ Add the give Metacontact family to roster data model Add Big Brother to his groups and all others under him. Return list of all added (contact, account) tuples with Big Brother as first element. Keyword arguments: family -- the family, see Contacts.get_metacontacts_family() """ nearby_family, big_brother_jid, big_brother_account = \ self._get_nearby_family_and_big_brother(family, account) if not big_brother_jid: return [] big_brother_contact = app.contacts.get_first_contact_from_jid( big_brother_account, big_brother_jid) assert not self._get_contact_iter(big_brother_jid, big_brother_account, big_brother_contact, self.model), \ 'Big brother %s already in roster\n Family: %s' \ % (big_brother_jid, family) self._add_entity(big_brother_contact, big_brother_account) brothers = [] # Filter family members for data in nearby_family: _account = data['account'] _jid = data['jid'] _contact = app.contacts.get_first_contact_from_jid( _account, _jid) if not _contact or _contact == big_brother_contact: # Corresponding account is not connected # or brother already added continue assert not self._get_contact_iter(_jid, _account, _contact, self.model), \ "%s already in roster.\n Family: %s" % (_jid, nearby_family) self._add_entity(_contact, _account, big_brother_contact=big_brother_contact, big_brother_account=big_brother_account) brothers.append((_contact, _account)) brothers.insert(0, (big_brother_contact, big_brother_account)) return brothers def _remove_metacontact_family(self, family, account): """ Remove the given Metacontact family from roster data model See Contacts.get_metacontacts_family() and RosterWindow._remove_entity() """ nearby_family = self._get_nearby_family_and_big_brother( family, account)[0] # Family might has changed (actual big brother not on top). # Remove children first then big brother family_in_roster = False for data in nearby_family: _account = data['account'] _jid = data['jid'] _contact = app.contacts.get_first_contact_from_jid(_account, _jid) iters = self._get_contact_iter(_jid, _account, _contact, self.model) if not iters or not _contact: # Family might not be up to date. # Only try to remove what is actually in the roster continue assert iters, '%s shall be removed but is not in roster \ \n Family: %s' % (_jid, family) family_in_roster = True parent_iter = self.model.iter_parent(iters[0]) parent_type = self.model[parent_iter][Column.TYPE] if parent_type != 'contact': # The contact on top old_big_account = _account old_big_contact = _contact old_big_jid = _jid continue ok = self._remove_entity(_contact, _account) assert ok, '%s was not removed' % _jid assert not self._get_contact_iter(_jid, _account, _contact, self.model), '%s is removed but still in roster' % _jid if not family_in_roster: return False assert old_big_jid, 'No Big Brother in nearby family %s (Family: %s)' %\ (nearby_family, family) iters = self._get_contact_iter(old_big_jid, old_big_account, old_big_contact, self.model) assert iters, 'Old Big Brother %s is not in roster anymore' % \ old_big_jid assert not self.model.iter_children(iters[0]), \ 'Old Big Brother %s still has children' % old_big_jid ok = self._remove_entity(old_big_contact, old_big_account) assert ok, "Old Big Brother %s not removed" % old_big_jid assert not self._get_contact_iter(old_big_jid, old_big_account, old_big_contact, self.model), \ 'Old Big Brother %s is removed but still in roster' % old_big_jid return True def _recalibrate_metacontact_family(self, family, account): """ Regroup metacontact family if necessary """ brothers = [] nearby_family, big_brother_jid, big_brother_account = \ self._get_nearby_family_and_big_brother(family, account) big_brother_contact = app.contacts.get_contact(big_brother_account, big_brother_jid) child_iters = self._get_contact_iter(big_brother_jid, big_brother_account, model=self.model) if child_iters: parent_iter = self.model.iter_parent(child_iters[0]) parent_type = self.model[parent_iter][Column.TYPE] # Check if the current BigBrother has even been before. if parent_type == 'contact': for data in nearby_family: # recalibrate after remove to keep highlight if data['jid'] in app.to_be_removed[data['account']]: return self._remove_metacontact_family(family, account) brothers = self._add_metacontact_family(family, account) for c, acc in brothers: self.draw_completely(c.jid, acc) # Check is small brothers are under the big brother for child in nearby_family: _jid = child['jid'] _account = child['account'] if _account == big_brother_account and _jid == big_brother_jid: continue child_iters = self._get_contact_iter(_jid, _account, model=self.model) if not child_iters: continue parent_iter = self.model.iter_parent(child_iters[0]) parent_type = self.model[parent_iter][Column.TYPE] if parent_type != 'contact': _contact = app.contacts.get_contact(_account, _jid) self._remove_entity(_contact, _account) self._add_entity(_contact, _account, groups=None, big_brother_contact=big_brother_contact, big_brother_account=big_brother_account) def _get_nearby_family_and_big_brother(self, family, account): return app.contacts.get_nearby_family_and_big_brother(family, account) def _add_self_contact(self, account): """ Add account's SelfContact to roster and draw it and the account Return the SelfContact contact instance """ jid = app.get_jid_from_account(account) contact = app.contacts.get_first_contact_from_jid(account, jid) assert not self._get_contact_iter(jid, account, contact, self.model), 'Self contact %s already in roster' % jid child_iterA = self._get_account_iter(account, self.model) self._iters[account]['contacts'][jid] = [self.model.append(child_iterA, [None, app.nicks[account], 'self_contact', jid, account, None, None, None, None, None, None, True] + [None] * self.nb_ext_renderers)] self.draw_completely(jid, account) self.draw_account(account) return contact def redraw_metacontacts(self, account): for family in app.contacts.iter_metacontacts_families(account): self._recalibrate_metacontact_family(family, account) def add_contact(self, jid, account): """ Add contact to roster and draw him Add contact to all its group and redraw the groups, the contact and the account. If it's a Metacontact, add and draw the whole family. Do nothing if the contact is already in roster. Return the added contact instance. If it is a Metacontact return Big Brother. Keyword arguments: jid -- the contact's jid or SelfJid to add SelfContact account -- the corresponding account. """ contact = app.contacts.get_contact_with_highest_priority(account, jid) if self._get_contact_iter(jid, account, contact, self.model): # If contact already in roster, do nothing return if jid == app.get_jid_from_account(account): show_self_contact = app.config.get('show_self_contact') if show_self_contact == 'never': return if (contact.resource != app.connections[account].server_resource \ and show_self_contact == 'when_other_resource') or \ show_self_contact == 'always': return self._add_self_contact(account) return is_observer = contact.is_observer() if is_observer: # if he has a tag, remove it app.contacts.remove_metacontact(account, jid) # Add contact to roster family = app.contacts.get_metacontacts_family(account, jid) contacts = [] if family: # We have a family. So we are a metacontact. # Add all family members that we shall be grouped with if self.regroup: # remove existing family members to regroup them self._remove_metacontact_family(family, account) contacts = self._add_metacontact_family(family, account) else: # We are a normal contact contacts = [(contact, account), ] self._add_entity(contact, account) # Draw the contact and its groups contact if not self.starting: for c, acc in contacts: self.draw_completely(c.jid, acc) for group in contact.get_shown_groups(): self.draw_group(group, account) self._adjust_group_expand_collapse_state(group, account) self.draw_account(account) return contacts[0][0] # it's contact/big brother with highest priority def remove_contact(self, jid, account, force=False, backend=False, maximize=False): """ Remove contact from roster Remove contact from all its group. Remove empty groups or redraw otherwise. Draw the account. If it's a Metacontact, remove the whole family. Do nothing if the contact is not in roster. Keyword arguments: jid -- the contact's jid or SelfJid to remove SelfContact account -- the corresponding account. force -- remove contact even it has pending evens (Default False) backend -- also remove contact instance (Default False) """ contact = app.contacts.get_contact_with_highest_priority(account, jid) if not contact: return if not force and self.contact_has_pending_roster_events(contact, account): return False iters = self._get_contact_iter(jid, account, contact, self.model) if iters: # no more pending events # Remove contact from roster directly family = app.contacts.get_metacontacts_family(account, jid) if family: # We have a family. So we are a metacontact. self._remove_metacontact_family(family, account) else: self._remove_entity(contact, account) old_grps = [] if backend: if not app.interface.msg_win_mgr.get_control(jid, account) or \ force: # If a window is still opened: don't remove contact instance # Remove contact before redrawing, otherwise the old # numbers will still be show if not maximize: # Don't remove contact when we maximize a room app.contacts.remove_jid(account, jid, remove_meta=True) if iters: rest_of_family = [data for data in family if account != data['account'] or jid != data['jid']] if rest_of_family: # reshow the rest of the family brothers = self._add_metacontact_family(rest_of_family, account) for c, acc in brothers: self.draw_completely(c.jid, acc) else: for c in app.contacts.get_contacts(account, jid): c.sub = 'none' c.show = 'not in roster' c.status = '' old_grps = c.get_shown_groups() c.groups = [_('Not in Roster')] self._add_entity(c, account) self.draw_contact(jid, account) if iters: # Draw all groups of the contact for group in contact.get_shown_groups() + old_grps: self.draw_group(group, account) self.draw_account(account) return True def rename_self_contact(self, old_jid, new_jid, account): """ Rename the self_contact jid Keyword arguments: old_jid -- our old jid new_jid -- our new jid account -- the corresponding account. """ app.contacts.change_contact_jid(old_jid, new_jid, account) self_iter = self._get_self_contact_iter(account, model=self.model) if not self_iter: return self.model[self_iter][Column.JID] = new_jid self.draw_contact(new_jid, account) def minimize_groupchat(self, account, jid, status=''): gc_control = app.interface.msg_win_mgr.get_gc_control(jid, account) app.interface.minimized_controls[account][jid] = gc_control self.add_groupchat(jid, account) def add_groupchat(self, jid, account): """ Add groupchat to roster and draw it. Return the added contact instance """ contact = app.contacts.get_groupchat_contact(account, jid) show = 'offline' if app.account_is_connected(account): show = 'online' contact.show = show self.add_contact(jid, account) return contact def remove_groupchat(self, jid, account, maximize=False): """ Remove groupchat from roster and redraw account and group """ contact = app.contacts.get_contact_with_highest_priority(account, jid) if contact.is_groupchat(): if jid in app.interface.minimized_controls[account]: del app.interface.minimized_controls[account][jid] self.remove_contact(jid, account, force=True, backend=True, maximize=maximize) return True return False # FIXME: This function is yet unused! Port to new API def add_transport(self, jid, account): """ Add transport to roster and draw it. Return the added contact instance """ contact = app.contacts.get_contact_with_highest_priority(account, jid) if contact is None: contact = app.contacts.create_contact(jid=jid, account=account, name=jid, groups=[_('Transports')], show='offline', status='offline', sub='from') app.contacts.add_contact(account, contact) self.add_contact(jid, account) return contact def remove_transport(self, jid, account): """ Remove transport from roster and redraw account and group """ self.remove_contact(jid, account, force=True, backend=True) return True def rename_group(self, old_name, new_name, account): """ Rename a roster group """ if old_name == new_name: return # Groups may not change name from or to a special groups for g in helpers.special_groups: if g in (new_name, old_name): return # update all contacts in the given group if self.regroup: accounts = app.connections.keys() else: accounts = [account, ] for acc in accounts: changed_contacts = [] for jid in app.contacts.get_jid_list(acc): contact = app.contacts.get_first_contact_from_jid(acc, jid) if old_name not in contact.groups: continue self.remove_contact(jid, acc, force=True) contact.groups.remove(old_name) if new_name not in contact.groups: contact.groups.append(new_name) changed_contacts.append({'jid': jid, 'name': contact.name, 'groups':contact.groups}) app.connections[acc].update_contacts(changed_contacts) for c in changed_contacts: self.add_contact(c['jid'], acc) self._adjust_group_expand_collapse_state(new_name, acc) self.draw_group(old_name, acc) self.draw_group(new_name, acc) def add_contact_to_groups(self, jid, account, groups, update=True): """ Add contact to given groups and redraw them Contact on server is updated too. When the contact has a family, the action will be performed for all members. Keyword Arguments: jid -- the jid account -- the corresponding account groups -- list of Groups to add the contact to. update -- update contact on the server """ self.remove_contact(jid, account, force=True) for contact in app.contacts.get_contacts(account, jid): for group in groups: if group not in contact.groups: # we might be dropped from meta to group contact.groups.append(group) if update: app.connections[account].update_contact(jid, contact.name, contact.groups) self.add_contact(jid, account) for group in groups: self._adjust_group_expand_collapse_state(group, account) def remove_contact_from_groups(self, jid, account, groups, update=True): """ Remove contact from given groups and redraw them Contact on server is updated too. When the contact has a family, the action will be performed for all members. Keyword Arguments: jid -- the jid account -- the corresponding account groups -- list of Groups to remove the contact from update -- update contact on the server """ self.remove_contact(jid, account, force=True) for contact in app.contacts.get_contacts(account, jid): for group in groups: if group in contact.groups: # Needed when we remove from "General" or "Observers" contact.groups.remove(group) if update: app.connections[account].update_contact(jid, contact.name, contact.groups) self.add_contact(jid, account) # Also redraw old groups for group in groups: self.draw_group(group, account) # FIXME: maybe move to app.py def remove_newly_added(self, jid, account): if account not in app.newly_added: # Account has been deleted during the timeout that called us return if jid in app.newly_added[account]: app.newly_added[account].remove(jid) self.draw_contact(jid, account) # FIXME: maybe move to app.py def remove_to_be_removed(self, jid, account): if account not in app.interface.instances: # Account has been deleted during the timeout that called us return if jid in app.newly_added[account]: return if jid in app.to_be_removed[account]: app.to_be_removed[account].remove(jid) family = app.contacts.get_metacontacts_family(account, jid) if family: # Perform delayed recalibration self._recalibrate_metacontact_family(family, account) self.draw_contact(jid, account) # Hide Group if all children are hidden contact = app.contacts.get_contact(account, jid) if not contact: return for group in contact.get_shown_groups(): self.draw_group(group, account) # FIXME: integrate into add_contact() def add_to_not_in_the_roster(self, account, jid, nick='', resource=''): keyID = '' attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] contact = app.contacts.create_not_in_roster_contact(jid=jid, account=account, resource=resource, name=nick, keyID=keyID) app.contacts.add_contact(account, contact) self.add_contact(contact.jid, account) return contact ################################################################################ ### Methods for adding and removing roster window items ################################################################################ def _really_draw_account(self, account): child_iter = self._get_account_iter(account, self.model) if not child_iter: assert False, 'Account iter of %s could not be found.' % account return num_of_accounts = app.get_number_of_connected_accounts() num_of_secured = app.get_number_of_securely_connected_accounts() tls_pixbuf = None if app.account_is_securely_connected(account) and not self.regroup or\ self.regroup and num_of_secured and num_of_secured == num_of_accounts: tls_pixbuf = 'changes-prevent' self.model[child_iter][Column.PADLOCK_PIXBUF] = tls_pixbuf if self.regroup: account_name = _('Merged accounts') accounts = [] else: account_name = app.get_account_label(account) accounts = [account] if account in self.collapsed_rows and \ self.model.iter_has_child(child_iter): account_name = '[%s]' % account_name if (app.account_is_connected(account) or (self.regroup and \ app.get_number_of_connected_accounts())) and app.config.get( 'show_contacts_number'): nbr_on, nbr_total = app.contacts.get_nb_online_total_contacts( accounts=accounts) account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) self.model[child_iter][Column.NAME] = GLib.markup_escape_text(account_name) pep_dict = app.connections[account].pep if app.config.get('show_mood_in_roster') and 'mood' in pep_dict: self.model[child_iter][Column.MOOD_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['mood']) else: self.model[child_iter][Column.MOOD_PIXBUF] = empty_pixbuf if app.config.get('show_activity_in_roster') and 'activity' in \ pep_dict: self.model[child_iter][Column.ACTIVITY_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['activity']) else: self.model[child_iter][Column.ACTIVITY_PIXBUF] = empty_pixbuf if app.config.get('show_tunes_in_roster') and 'tune' in pep_dict: self.model[child_iter][Column.TUNE_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['tune']) else: self.model[child_iter][Column.TUNE_PIXBUF] = empty_pixbuf if app.config.get('show_location_in_roster') and 'geoloc' in \ pep_dict: self.model[child_iter][Column.LOCATION_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['geoloc']) else: self.model[child_iter][Column.LOCATION_PIXBUF] = empty_pixbuf def _really_draw_accounts(self): for acct in self.accounts_to_draw: self._really_draw_account(acct) self.accounts_to_draw = [] return False def draw_account(self, account): if account in self.accounts_to_draw: return self.accounts_to_draw.append(account) if len(self.accounts_to_draw) == 1: GLib.timeout_add(200, self._really_draw_accounts) def _really_draw_group(self, group, account): child_iter = self._get_group_iter(group, account, model=self.model) if not child_iter: # Eg. We redraw groups after we removed a entity # and its empty groups return if self.regroup: accounts = [] else: accounts = [account] text = GLib.markup_escape_text(group) if helpers.group_is_blocked(account, group): text = '%s' % text if app.config.get('show_contacts_number'): nbr_on, nbr_total = app.contacts.get_nb_online_total_contacts( accounts=accounts, groups=[group]) text += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) self.model[child_iter][Column.NAME] = text # Hide group if no more contacts iterG = self._get_group_iter(group, account, model=self.modelfilter) to_hide = [] while iterG: parent = self.modelfilter.iter_parent(iterG) if (not self.modelfilter.iter_has_child(iterG)) or (to_hide \ and self.modelfilter.iter_n_children(iterG) == 1): to_hide.append(iterG) if not parent or self.modelfilter[parent][Column.TYPE] != \ 'group': iterG = None else: iterG = parent else: iterG = None for iter_ in to_hide: self.modelfilter[iter_][Column.VISIBLE] = False def _really_draw_groups(self): for ag in self.groups_to_draw.values(): acct = ag['account'] grp = ag['group'] self._really_draw_group(grp, acct) self.groups_to_draw = {} return False def draw_group(self, group, account): ag = account + group if ag in self.groups_to_draw: return self.groups_to_draw[ag] = {'group': group, 'account': account} if len(self.groups_to_draw) == 1: GLib.timeout_add(200, self._really_draw_groups) def draw_parent_contact(self, jid, account): child_iters = self._get_contact_iter(jid, account, model=self.model) if not child_iters: return False parent_iter = self.model.iter_parent(child_iters[0]) if self.model[parent_iter][Column.TYPE] != 'contact': # parent is not a contact return parent_jid = self.model[parent_iter][Column.JID] parent_account = self.model[parent_iter][Column.ACCOUNT] self.draw_contact(parent_jid, parent_account) return False def draw_contact(self, jid, account, selected=False, focus=False, contact_instances=None, contact=None): """ Draw the correct state image, name BUT not avatar """ # focus is about if the roster window has toplevel-focus or not # FIXME: We really need a custom cell_renderer if not contact_instances: contact_instances = app.contacts.get_contacts(account, jid) if not contact: contact = app.contacts.get_highest_prio_contact_from_contacts( contact_instances) if not contact: return False child_iters = self._get_contact_iter(jid, account, contact, self.model) if not child_iters: return False name = GLib.markup_escape_text(contact.get_shown_name()) # gets number of unread gc marked messages if jid in app.interface.minimized_controls[account] and \ app.interface.minimized_controls[account][jid]: nb_unread = len(app.events.get_events(account, jid, ['printed_marked_gc_msg'])) nb_unread += app.interface.minimized_controls \ [account][jid].get_nb_unread_pm() if nb_unread == 1: name = '%s *' % name elif nb_unread > 1: name = '%s [%s]' % (name, str(nb_unread)) # Strike name if blocked strike = False if helpers.jid_is_blocked(account, jid): strike = True else: for group in contact.get_shown_groups(): if helpers.group_is_blocked(account, group): strike = True break if strike: name = '%s' % name # Show resource counter nb_connected_contact = 0 for c in contact_instances: if c.show not in ('error', 'offline'): nb_connected_contact += 1 if nb_connected_contact > 1: # switch back to default writing direction name += i18n.paragraph_direction_mark(name) name += ' (%d)' % nb_connected_contact # add status msg, if not empty, under contact name in # the treeview if contact.status and app.config.get('show_status_msgs_in_roster'): status = contact.status.strip() if status != '': status = helpers.reduce_chars_newlines(status, max_lines=1) # escape markup entities and make them small # italic name += ('\n{}'.format( GLib.markup_escape_text(status))) icon_name = helpers.get_icon_name_to_show(contact, account) # look if another resource has awaiting events for c in contact_instances: c_icon_name = helpers.get_icon_name_to_show(c, account) if c_icon_name in ('event', 'muc_active', 'muc_inactive'): icon_name = c_icon_name break # Check for events of collapsed (hidden) brothers family = app.contacts.get_metacontacts_family(account, jid) is_big_brother = False have_visible_children = False if family: bb_jid, bb_account = \ self._get_nearby_family_and_big_brother(family, account)[1:] is_big_brother = (jid, account) == (bb_jid, bb_account) iters = self._get_contact_iter(jid, account) have_visible_children = iters and \ self.modelfilter.iter_has_child(iters[0]) if have_visible_children: # We are the big brother and have a visible family for child_iter in child_iters: child_path = self.model.get_path(child_iter) path = self.modelfilter.convert_child_path_to_path(child_path) if not path: continue if not self.tree.row_expanded(path) and icon_name != 'event': iterC = self.model.iter_children(child_iter) while iterC: # a child has awaiting messages? jidC = self.model[iterC][Column.JID] accountC = self.model[iterC][Column.ACCOUNT] if app.events.get_events(accountC, jidC): icon_name = 'event' break iterC = self.model.iter_next(iterC) if self.tree.row_expanded(path): state_images = self.get_appropriate_state_images( jid, size='opened', icon_name=icon_name) else: state_images = self.get_appropriate_state_images( jid, size='closed', icon_name=icon_name) # Expand/collapse icon might differ per iter # (group) img = state_images[icon_name] self.model[child_iter][Column.IMG] = img self.model[child_iter][Column.NAME] = name #TODO: compute visible visible = True self.model[child_iter][Column.VISIBLE] = visible else: # A normal contact or little brother state_images = self.get_appropriate_state_images(jid, icon_name=icon_name) visible = self.contact_is_visible(contact, account) # All iters have the same icon (no expand/collapse) img = state_images[icon_name] for child_iter in child_iters: self.model[child_iter][Column.IMG] = img self.model[child_iter][Column.NAME] = name self.model[child_iter][Column.VISIBLE] = visible if visible: parent_iter = self.model.iter_parent(child_iter) self.model[parent_iter][Column.VISIBLE] = True # We are a little brother if family and not is_big_brother and not self.starting: self.draw_parent_contact(jid, account) if visible: delimiter = app.connections[account].get_module('Delimiter').delimiter for group in contact.get_shown_groups(): group_splited = group.split(delimiter) i = 1 while i < len(group_splited) + 1: g = delimiter.join(group_splited[:i]) iterG = self._get_group_iter(g, account, model=self.model) if iterG: # it's not self contact self.model[iterG][Column.VISIBLE] = True i += 1 app.plugin_manager.gui_extension_point('roster_draw_contact', self, jid, account, contact) return False def _is_pep_shown_in_roster(self, pep_type): if pep_type == 'mood': return app.config.get('show_mood_in_roster') if pep_type == 'activity': return app.config.get('show_activity_in_roster') if pep_type == 'tune': return app.config.get('show_tunes_in_roster') if pep_type == 'geoloc': return app.config.get('show_location_in_roster') return False def draw_all_pep_types(self, jid, account, contact=None): for pep_type in self._pep_type_to_model_column: self.draw_pep(jid, account, pep_type, contact=contact) def draw_pep(self, jid, account, pep_type, contact=None): if pep_type not in self._pep_type_to_model_column: return if not self._is_pep_shown_in_roster(pep_type): return model_column = self._pep_type_to_model_column[pep_type] iters = self._get_contact_iter(jid, account, model=self.model) if not iters: return if not contact: contact = app.contacts.get_contact(account, jid) if pep_type in contact.pep: pixbuf = gtkgui_helpers.get_pep_as_pixbuf(contact.pep[pep_type]) else: pixbuf = empty_pixbuf for child_iter in iters: self.model[child_iter][model_column] = pixbuf def _get_avatar_image(self, account, jid): if not app.config.get('show_avatars_in_roster'): return None scale = self.window.get_scale_factor() surface = app.contacts.get_avatar( account, jid, AvatarSize.ROSTER, scale) return Gtk.Image.new_from_surface(surface) def draw_avatar(self, jid, account): iters = self._get_contact_iter(jid, account, model=self.model) if not iters or not app.config.get('show_avatars_in_roster'): return jid = self.model[iters[0]][Column.JID] image = self._get_avatar_image(account, jid) for child_iter in iters: self.model[child_iter][Column.AVATAR_IMG] = image return False def draw_completely(self, jid, account): contact_instances = app.contacts.get_contacts(account, jid) contact = app.contacts.get_highest_prio_contact_from_contacts( contact_instances) self.draw_contact( jid, account, contact_instances=contact_instances, contact=contact) def adjust_and_draw_contact_context(self, jid, account): """ Draw contact, account and groups of given jid Show contact if it has pending events """ contact = app.contacts.get_first_contact_from_jid(account, jid) if not contact: # idle draw or just removed SelfContact return family = app.contacts.get_metacontacts_family(account, jid) if family: # There might be a new big brother self._recalibrate_metacontact_family(family, account) self.draw_contact(jid, account) self.draw_account(account) for group in contact.get_shown_groups(): self.draw_group(group, account) self._adjust_group_expand_collapse_state(group, account) def _idle_draw_jids_of_account(self, jids, account): """ Draw given contacts and their avatars in a lazy fashion Keyword arguments: jids -- a list of jids to draw account -- the corresponding account """ def _draw_all_contacts(jids, account): for jid in jids: family = app.contacts.get_metacontacts_family(account, jid) if family: # For metacontacts over several accounts: # When we connect a new account existing brothers # must be redrawn (got removed and readded) for data in family: self.draw_completely(data['jid'], data['account']) else: self.draw_completely(jid, account) yield True self.refilter_shown_roster_items() yield False task = _draw_all_contacts(jids, account) GLib.idle_add(next, task) def _before_fill(self): self.tree.freeze_child_notify() self.tree.set_model(None) # disable sorting self.model.set_sort_column_id(-2, Gtk.SortType.ASCENDING) self.starting = True self.starting_filtering = True def _after_fill(self): self.starting = False accounts_list = app.contacts.get_accounts() for account in app.connections: if account not in accounts_list: continue jids = app.contacts.get_jid_list(account) for jid in jids: self.draw_completely(jid, account) # Draw all known groups for group in app.groups[account]: self.draw_group(group, account) self.draw_account(account) self.model.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.tree.set_model(self.modelfilter) self.tree.thaw_child_notify() self.starting_filtering = False self.refilter_shown_roster_items() def setup_and_draw_roster(self): """ Create new empty model and draw roster """ self.modelfilter = None self.model = Gtk.TreeStore(*self.columns) self.model.set_sort_func(1, self._compareIters) self.model.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.modelfilter = self.model.filter_new() self.modelfilter.set_visible_func(self._visible_func) self.modelfilter.connect('row-has-child-toggled', self.on_modelfilter_row_has_child_toggled) self.tree.set_model(self.modelfilter) self._iters = {} # for merged mode self._iters['MERGED'] = {'account': None, 'groups': {}} for acct in app.contacts.get_accounts(): self._iters[acct] = {'account': None, 'groups': {}, 'contacts': {}} for acct in app.contacts.get_accounts(): self.add_account(acct) self.add_account_contacts(acct, improve_speed=True, draw_contacts=False) # Recalculate column width for ellipsizing self.tree.columns_autosize() def select_contact(self, jid, account): """ Select contact in roster. If contact is hidden but has events, show him """ # Refiltering SHOULD NOT be needed: # When a contact gets a new event he will be redrawn and his # icon changes, so _visible_func WILL be called on him anyway iters = self._get_contact_iter(jid, account) if not iters: # Not visible in roster return path = self.modelfilter.get_path(iters[0]) if self.dragging or not app.config.get( 'scroll_roster_to_last_message'): # do not change selection while DND'ing return # Expand his parent, so this path is visible, don't expand it. path.up() self.tree.expand_to_path(path) self.tree.scroll_to_cell(path) self.tree.set_cursor(path) def _readjust_expand_collapse_state(self): def func(model, path, iter_, param): type_ = model[iter_][Column.TYPE] acct = model[iter_][Column.ACCOUNT] jid = model[iter_][Column.JID] key = None if type_ == 'account': key = acct elif type_ == 'group': key = acct + jid elif type_ == 'contact': parent_iter = model.iter_parent(iter_) ptype = model[parent_iter][Column.TYPE] if ptype == 'group': grp = model[parent_iter][Column.JID] key = acct + grp + jid if key: if key in self.collapsed_rows: self.tree.collapse_row(path) else: self.tree.expand_row(path, False) self.modelfilter.foreach(func, None) def _adjust_account_expand_collapse_state(self, account): """ Expand/collapse account row based on self.collapsed_rows """ if not self.tree.get_model(): return iterA = self._get_account_iter(account) if not iterA: # thank you modelfilter return path = self.modelfilter.get_path(iterA) if account in self.collapsed_rows: self.tree.collapse_row(path) else: self.tree.expand_row(path, False) return False def _adjust_group_expand_collapse_state(self, group, account): """ Expand/collapse group row based on self.collapsed_rows """ if not self.tree.get_model(): return if account not in app.connections: return delimiter = app.connections[account].get_module('Delimiter').delimiter group_splited = group.split(delimiter) i = 1 while i < len(group_splited) + 1: g = delimiter.join(group_splited[:i]) iterG = self._get_group_iter(g, account) if not iterG: # Group not visible return path = self.modelfilter.get_path(iterG) if account + g in self.collapsed_rows: self.tree.collapse_row(path) else: self.tree.expand_row(path, False) i += 1 ############################################################################## ### Roster and Modelfilter handling ############################################################################## def refilter_shown_roster_items(self): if self.filtering: return self.filtering = True for account in app.connections: for jid in app.contacts.get_jid_list(account): self.adjust_and_draw_contact_context(jid, account) self.filtering = False def contact_has_pending_roster_events(self, contact, account): """ Return True if the contact or one if it resources has pending events """ # jid has pending events if app.events.get_nb_roster_events(account, contact.jid) > 0: return True # check events of all resources for contact_ in app.contacts.get_contacts(account, contact.jid): if contact_.resource and app.events.get_nb_roster_events(account, contact_.get_full_jid()) > 0: return True return False def contact_is_visible(self, contact, account): if self.rfilter_enabled: return self.rfilter_string in contact.get_shown_name().lower() if self.contact_has_pending_roster_events(contact, account): return True if app.config.get('showoffline'): return True if contact.show in ('offline', 'error'): if contact.jid in app.to_be_removed[account]: return True return False if app.config.get('show_only_chat_and_online') and contact.show in ( 'away', 'xa', 'busy'): return False if _('Transports') in contact.get_shown_groups(): return app.config.get('show_transports_group') return True def _visible_func(self, model, titer, dummy): """ Determine whether iter should be visible in the treeview """ if self.starting_filtering: return False visible = model[titer][Column.VISIBLE] type_ = model[titer][Column.TYPE] if not type_: return False if type_ == 'account': # Always show account return True account = model[titer][Column.ACCOUNT] if not account: return False jid = model[titer][Column.JID] if not jid: return False if not self.rfilter_enabled: return visible if type_ == 'group': group = jid if group == _('Transports'): if self.regroup: accounts = app.contacts.get_accounts() else: accounts = [account] for _acc in accounts: for contact in app.contacts.iter_contacts(_acc): if group in contact.get_shown_groups(): if self.rfilter_string in \ contact.get_shown_name().lower(): return True elif self.contact_has_pending_roster_events(contact, _acc): return True # No transport has been found return False if type_ == 'contact': if model.iter_has_child(titer): iter_c = model.iter_children(titer) while iter_c: if self.rfilter_string in model[iter_c][Column.NAME].lower(): return True iter_c = model.iter_next(iter_c) return self.rfilter_string in model[titer][Column.NAME].lower() if type_ == 'agent': return self.rfilter_string in model[titer][Column.NAME].lower() if type_ == 'groupchat': return self.rfilter_string in model[titer][Column.NAME].lower() return visible def _compareIters(self, model, iter1, iter2, data=None): """ Compare two iters to sort them """ name1 = model[iter1][Column.NAME] name2 = model[iter2][Column.NAME] if not name1 or not name2: return 0 type1 = model[iter1][Column.TYPE] type2 = model[iter2][Column.TYPE] if type1 == 'self_contact': return -1 if type2 == 'self_contact': return 1 if type1 == 'group': name1 = model[iter1][Column.JID] name2 = model[iter2][Column.JID] if name1 == _('Transports'): return 1 if name2 == _('Transports'): return -1 if name1 == _('Not in Roster'): return 1 if name2 == _('Not in Roster'): return -1 if name1 == _('Groupchats'): return 1 if name2 == _('Groupchats'): return -1 account1 = model[iter1][Column.ACCOUNT] account2 = model[iter2][Column.ACCOUNT] if not account1 or not account2: return 0 if type1 == 'account': return locale.strcoll(account1, account2) jid1 = model[iter1][Column.JID] jid2 = model[iter2][Column.JID] if type1 == 'contact': lcontact1 = app.contacts.get_contacts(account1, jid1) contact1 = app.contacts.get_first_contact_from_jid(account1, jid1) if not contact1: return 0 name1 = contact1.get_shown_name() if type2 == 'contact': lcontact2 = app.contacts.get_contacts(account2, jid2) contact2 = app.contacts.get_first_contact_from_jid(account2, jid2) if not contact2: return 0 name2 = contact2.get_shown_name() # We first compare by show if sort_by_show_in_roster is True or if it's # a child contact if type1 == 'contact' and type2 == 'contact' and \ app.config.get('sort_by_show_in_roster'): cshow = {'chat':0, 'online': 1, 'away': 2, 'xa': 3, 'dnd': 4, 'invisible': 5, 'offline': 6, 'not in roster': 7, 'error': 8} s = self.get_show(lcontact1) show1 = cshow.get(s, 9) s = self.get_show(lcontact2) show2 = cshow.get(s, 9) removing1 = False removing2 = False if show1 == 6 and jid1 in app.to_be_removed[account1]: removing1 = True if show2 == 6 and jid2 in app.to_be_removed[account2]: removing2 = True if removing1 and not removing2: return 1 if removing2 and not removing1: return -1 sub1 = contact1.sub sub2 = contact2.sub # none and from goes after if sub1 not in ['none', 'from'] and sub2 in ['none', 'from']: return -1 if sub1 in ['none', 'from'] and sub2 not in ['none', 'from']: return 1 if show1 < show2: return -1 if show1 > show2: return 1 # We compare names cmp_result = locale.strcoll(name1.lower(), name2.lower()) if cmp_result < 0: return -1 if cmp_result > 0: return 1 if type1 == 'contact' and type2 == 'contact': # We compare account names cmp_result = locale.strcoll(account1.lower(), account2.lower()) if cmp_result < 0: return -1 if cmp_result > 0: return 1 # We compare jids cmp_result = locale.strcoll(jid1.lower(), jid2.lower()) if cmp_result < 0: return -1 if cmp_result > 0: return 1 return 0 ################################################################################ ### FIXME: Methods that don't belong to roster window... ### ... at least not in there current form ################################################################################ def fire_up_unread_messages_events(self, account): """ Read from db the unread messages, and fire them up, and if we find very old unread messages, delete them from unread table """ results = app.logger.get_unread_msgs() for result, shown in results: jid = result.jid additional_data = result.additional_data if app.contacts.get_first_contact_from_jid(account, jid) and not \ shown: # We have this jid in our contacts list # XXX unread messages should probably have their session saved # with them session = app.connections[account].make_new_session(jid) tim = float(result.time) session.roster_message(jid, result.message, tim, msg_type='chat', msg_log_id=result.log_line_id, additional_data=additional_data) app.logger.set_shown_unread_msgs(result.log_line_id) elif (time.time() - result.time) > 2592000: # ok, here we see that we have a message in unread messages # table that is older than a month. It is probably from someone # not in our roster for accounts we usually launch, so we will # delete this id from unread message tables. app.logger.set_read_messages([result.log_line_id]) def fill_contacts_and_groups_dicts(self, array, account): """ Fill app.contacts and app.groups """ # FIXME: This function needs to be split # Most of the logic SHOULD NOT be done at GUI level if account not in app.contacts.get_accounts(): app.contacts.add_account(account) if not account in self._iters: self._iters[account] = {'account': None, 'groups': {}, 'contacts': {}} if account not in app.groups: app.groups[account] = {} if app.config.get('show_self_contact') == 'always': self_jid = app.get_jid_from_account(account) if app.connections[account].server_resource: self_jid += '/' + app.connections[account].server_resource array[self_jid] = {'name': app.nicks[account], 'groups': ['self_contact'], 'subscription': 'both', 'ask': 'none'} # .keys() is needed for jid in list(array.keys()): # Remove the contact in roster. It might has changed self.remove_contact(jid, account, force=True) # Remove old Contact instances app.contacts.remove_jid(account, jid, remove_meta=False) jids = jid.split('/') # get jid ji = jids[0] # get resource resource = '' if len(jids) > 1: resource = '/'.join(jids[1:]) # get name name = array[jid]['name'] or '' show = 'offline' # show is offline by default status = '' # no status message by default keyID = '' attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] if app.jid_is_transport(jid): array[jid]['groups'] = [_('Transports')] #TRANSP - potential contact1 = app.contacts.create_contact(jid=ji, account=account, name=name, groups=array[jid]['groups'], show=show, status=status, sub=array[jid]['subscription'], ask=array[jid]['ask'], resource=resource, keyID=keyID) app.contacts.add_contact(account, contact1) # If we already have chat windows opened, update them with new # contact instance chat_control = app.interface.msg_win_mgr.get_control(ji, account) if chat_control: chat_control.contact = contact1 def connected_rooms(self, account): if account in list(app.gc_connected[account].values()): return True return False def on_event_removed(self, event_list): """ Remove contacts on last events removed Only performed if removal was requested before but the contact still had pending events """ msg_log_ids = [] for ev in event_list: if ev.type_ != 'printed_chat': continue if ev.msg_log_id: # There is a msg_log_id msg_log_ids.append(ev.msg_log_id) if msg_log_ids: app.logger.set_read_messages(msg_log_ids) contact_list = ((event.jid.split('/')[0], event.account) for event in \ event_list) for jid, account in contact_list: self.draw_contact(jid, account) # Remove contacts in roster if removal was requested key = (jid, account) if key in list(self.contacts_to_be_removed.keys()): backend = self.contacts_to_be_removed[key]['backend'] del self.contacts_to_be_removed[key] # Remove contact will delay removal if there are more events # pending self.remove_contact(jid, account, backend=backend) self.show_title() def open_event(self, account, jid, event): """ If an event was handled, return True, else return False """ ft = app.interface.instances['file_transfers'] event = app.events.get_first_event(account, jid, event.type_) if event.type_ == 'normal': SingleMessageWindow(account, jid, action='receive', from_whom=jid, subject=event.subject, message=event.message, resource=event.resource, session=event.session, form_node=event.form_node) app.events.remove_events(account, jid, event) return True if event.type_ == 'file-request': contact = app.contacts.get_contact_with_highest_priority(account, jid) ft.show_file_request(account, contact, event.file_props) app.events.remove_events(account, jid, event) return True if event.type_ in ('file-request-error', 'file-send-error'): ft.show_send_error(event.file_props) app.events.remove_events(account, jid, event) return True if event.type_ in ('file-error', 'file-stopped'): msg_err = '' if event.file_props.error == -1: msg_err = _('Remote contact stopped transfer') elif event.file_props.error == -6: msg_err = _('Error opening file') ft.show_stopped(jid, event.file_props, error_msg=msg_err) app.events.remove_events(account, jid, event) return True if event.type_ == 'file-hash-error': ft.show_hash_error(jid, event.file_props, account) app.events.remove_events(account, jid, event) return True if event.type_ == 'file-completed': ft.show_completed(jid, event.file_props) app.events.remove_events(account, jid, event) return True if event.type_ == 'gc-invitation': dialogs.InvitationReceivedDialog(account, event.room_jid, event.jid_from, event.password, event.reason, is_continued=event.is_continued) app.events.remove_events(account, jid, event) return True if event.type_ == 'subscription_request': dialogs.SubscriptionRequestWindow(jid, event.text, account, event.nick) app.events.remove_events(account, jid, event) return True if event.type_ == 'unsubscribed': app.interface.show_unsubscribed_dialog(account, event.contact) app.events.remove_events(account, jid, event) return True if event.type_ == 'jingle-incoming': dialogs.VoIPCallReceivedDialog(account, event.peerjid, event.sid, event.content_types) app.events.remove_events(account, jid, event) return True return False ################################################################################ ### This and that... random. ################################################################################ def show_roster_vbox(self, active): vb = self.xml.get_object('roster_vbox2') if active: vb.set_no_show_all(False) vb.show() else: vb.hide() vb.set_no_show_all(True) def authorize(self, widget, jid, account): """ Authorize a contact (by re-sending auth menuitem) """ app.connections[account].get_module('Presence').subscribed(jid) InformationDialog(_('Authorization sent'), _('"%s" will now see your status.') %jid) def req_sub(self, widget, jid, txt, account, groups=None, nickname=None, auto_auth=False): """ Request subscription to a contact """ groups_list = groups or [] app.connections[account].get_module('Presence').subscribe( jid, txt, nickname, groups_list, auto_auth) contact = app.contacts.get_contact_with_highest_priority(account, jid) if not contact: keyID = '' attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] contact = app.contacts.create_contact(jid=jid, account=account, name=nickname, groups=groups_list, show='requested', status='', ask='none', sub='subscribe', keyID=keyID) app.contacts.add_contact(account, contact) else: if not _('Not in Roster') in contact.get_shown_groups(): InformationDialog(_('Subscription request has been ' 'sent'), _('If "%s" accepts this request you will know his ' 'or her status.') % jid) return self.remove_contact(contact.jid, account, force=True) contact.groups = groups_list if nickname: contact.name = nickname self.add_contact(jid, account) def revoke_auth(self, widget, jid, account): """ Revoke a contact's authorization """ app.connections[account].get_module('Presence').unsubscribed(jid) InformationDialog(_('Authorization removed'), _('Now "%s" will always see you as offline.') %jid) def set_state(self, account, state): child_iterA = self._get_account_iter(account, self.model) if child_iterA: self.model[child_iterA][0] = \ app.interface.jabber_state_images['16'][state] if app.interface.systray_enabled: app.interface.systray.change_status(state) def set_connecting_state(self, account): self.set_state(account, 'connecting') def send_status(self, account, status, txt, auto=False, to=None): if status != 'offline': if to is None: app.config.set_per('accounts', account, 'last_status', status) app.config.set_per('accounts', account, 'last_status_msg', helpers.to_one_line(txt)) if app.connections[account].connected < 2: self.set_connecting_state(account) keyid = app.config.get_per('accounts', account, 'keyid') if keyid and not app.connections[account].gpg: WarningDialog(_('OpenPGP is not usable'), _('Gajim needs python-gnupg >= 0.3.8\n' 'Beware there is an incompatible Python package called gnupg.\n' 'You will be connected to %s without OpenPGP.') % account) self.send_status_continue(account, status, txt, auto, to) def send_pep(self, account, pep_dict): connection = app.connections[account] if 'activity' in pep_dict: activity = pep_dict['activity'] subactivity = pep_dict.get('subactivity', None) activity_text = pep_dict.get('activity_text', None) connection.get_module('UserActivity').send( (activity, subactivity, activity_text)) else: connection.get_module('UserActivity').send(None) if 'mood' in pep_dict: mood = pep_dict['mood'] mood_text = pep_dict.get('mood_text', None) connection.get_module('UserMood').send((mood, mood_text)) else: connection.get_module('UserMood').send(None) def delete_pep(self, jid, account): if jid == app.get_jid_from_account(account): app.connections[account].pep = {} self.draw_account(account) for contact in app.contacts.get_contacts(account, jid): contact.pep = {} self.draw_all_pep_types(jid, account) ctrl = app.interface.msg_win_mgr.get_control(jid, account) if ctrl: ctrl.update_all_pep_types() def send_status_continue(self, account, status, txt, auto, to): if app.account_is_connected(account) and not to: if status == 'online' and not idle.Monitor.is_unknown(): app.sleeper_state[account] = 'online' elif app.sleeper_state[account] not in ('autoaway', 'autoxa') or \ status == 'offline': app.sleeper_state[account] = 'off' if to: app.connections[account].send_custom_status(status, txt, to) else: if status in ('invisible', 'offline'): self.delete_pep(app.get_jid_from_account(account), account) was_invisible = app.connections[account].connected == \ app.SHOW_LIST.index('invisible') app.connections[account].change_status(status, txt, auto) if account in app.interface.status_sent_to_users: app.interface.status_sent_to_users[account] = {} if account in app.interface.status_sent_to_groups: app.interface.status_sent_to_groups[account] = {} for gc_control in app.interface.msg_win_mgr.get_controls( message_control.TYPE_GC) + \ list(app.interface.minimized_controls[account].values()): if gc_control.account == account: if app.gc_connected[account][gc_control.room_jid]: app.connections[account].send_gc_status( gc_control.nick, gc_control.room_jid, status, txt, auto=auto) if was_invisible and status != 'offline': # We come back from invisible, join bookmarks con = app.connections[account] con.get_module('Bookmarks').auto_join_bookmarks() def chg_contact_status(self, contact, show, status, account): """ When a contact changes their status """ contact_instances = app.contacts.get_contacts(account, contact.jid) contact.show = show contact.status = status # name is to show in conversation window name = contact.get_shown_name() fjid = contact.get_full_jid() # The contact has several resources if len(contact_instances) > 1: if contact.resource != '': name += '/' + contact.resource # Remove resource when going offline if show in ('offline', 'error') and \ not self.contact_has_pending_roster_events(contact, account): ctrl = app.interface.msg_win_mgr.get_control(fjid, account) if ctrl: ctrl.update_ui() ctrl.parent_win.redraw_tab(ctrl) # keep the contact around, since it's # already attached to the control else: app.contacts.remove_contact(account, contact) elif contact.jid == app.get_jid_from_account(account) and \ show in ('offline', 'error'): if app.config.get('show_self_contact') != 'never': # SelfContact went offline. Remove him when last pending # message was read self.remove_contact(contact.jid, account, backend=True) uf_show = helpers.get_uf_show(show) # print status in chat window and update status/GPG image ctrl = app.interface.msg_win_mgr.get_control(contact.jid, account) if ctrl and ctrl.type_id != message_control.TYPE_GC: ctrl.contact = app.contacts.get_contact_with_highest_priority( account, contact.jid) ctrl.update_status_display(name, uf_show, status) if contact.resource: ctrl = app.interface.msg_win_mgr.get_control(fjid, account) if ctrl: ctrl.update_status_display(name, uf_show, status) # Delete pep if needed keep_pep = any(c.show not in ('error', 'offline') for c in contact_instances) if not keep_pep and contact.jid != app.get_jid_from_account(account) \ and not contact.is_groupchat(): self.delete_pep(contact.jid, account) # Redraw everything and select the sender self.adjust_and_draw_contact_context(contact.jid, account) def on_status_changed(self, account, show): """ The core tells us that our status has changed """ if account not in app.contacts.get_accounts(): return child_iterA = self._get_account_iter(account, self.model) if app.config.get('show_self_contact') == 'always': self_resource = app.connections[account].server_resource self_contact = app.contacts.get_contact(account, app.get_jid_from_account(account), resource=self_resource) if self_contact: status = app.connections[account].status self.chg_contact_status(self_contact, show, status, account) self.set_account_status_icon(account) if show == 'offline': if self.quit_on_next_offline > -1: # we want to quit, we are waiting for all accounts to be offline self.quit_on_next_offline -= 1 if self.quit_on_next_offline < 1: # all accounts offline, quit self.quit_gtkgui_interface() else: # No need to redraw contacts if we're quitting if child_iterA: self.model[child_iterA][Column.AVATAR_IMG] = None if account in app.con_types: app.con_types[account] = None for jid in list(app.contacts.get_jid_list(account)): lcontact = app.contacts.get_contacts(account, jid) ctrl = app.interface.msg_win_mgr.get_gc_control(jid, account) for contact in [c for c in lcontact if ( (c.show != 'offline' or c.is_transport()) and not ctrl)]: self.chg_contact_status(contact, 'offline', '', account) self.update_status_combobox() def get_status_message(self, show, on_response, show_pep=True, always_ask=False): """ Get the status message by: 1/ looking in default status message 2/ asking to user if needed depending on ask_on(ff)line_status and always_ask show_pep can be False to hide pep things from status message or True """ empty_pep = {'activity': '', 'subactivity': '', 'activity_text': '', 'mood': '', 'mood_text': ''} if show in app.config.get_per('defaultstatusmsg'): if app.config.get_per('defaultstatusmsg', show, 'enabled'): msg = app.config.get_per('defaultstatusmsg', show, 'message') msg = helpers.from_one_line(msg) on_response(msg, empty_pep) return if not always_ask and ((show == 'online' and not app.config.get( 'ask_online_status')) or (show in ('offline', 'invisible') and not \ app.config.get('ask_offline_status'))): on_response('', empty_pep) return dlg = dialogs.ChangeStatusMessageDialog(on_response, show, show_pep) dlg.dialog.present() # show it on current workspace def change_status(self, widget, account, status): def change(account, status): def on_response(message, pep_dict): if message is None: # user pressed Cancel to change status message dialog return self.send_status(account, status, message) self.send_pep(account, pep_dict) self.get_status_message(status, on_response) if status == 'invisible' and self.connected_rooms(account): ConfirmationDialog( _('You are participating in one or more group chats'), _('Changing your status to invisible will result in ' 'disconnection from those group chats. Are you sure you want ' 'to go invisible?'), on_response_ok=(change, account, status)) else: change(account, status) def update_status_combobox(self): # table to change index in connection.connected to index in combobox table = {'offline':9, 'connecting':9, 'online':0, 'chat':1, 'away':2, 'xa':3, 'dnd':4, 'invisible':5} liststore = self.status_combobox.get_model() # we check if there are more options in the combobox that it should # if yes, we remove the first ones while len(liststore) > len(table)+2: titer = liststore.get_iter_first() liststore.remove(titer) show = helpers.get_global_show() # temporarily block signal in order not to send status that we show # in the combobox self.combobox_callback_active = False if helpers.statuses_unified(): self.status_combobox.set_active(table[show]) else: uf_show = helpers.get_uf_show(show) liststore.prepend(['SEPARATOR', None, '', True]) status_combobox_text = uf_show + ' (' + _("desynced") + ')' liststore.prepend( [status_combobox_text, show, 'desync', False]) self.status_combobox.set_active(0) self.combobox_callback_active = True if app.interface.systray_enabled: app.interface.systray.change_status(show) def get_show(self, lcontact): prio = lcontact[0].priority show = lcontact[0].show for u in lcontact: if u.priority > prio: prio = u.priority show = u.show return show def on_message_window_delete(self, win_mgr, msg_win): if app.config.get('one_message_window') == 'always_with_roster': self.show_roster_vbox(True) gtkgui_helpers.resize_window(self.window, app.config.get('roster_width'), app.config.get('roster_height')) def close_all_from_dict(self, dic): """ Close all the windows in the given dictionary """ for w in list(dic.values()): if isinstance(w, dict): self.close_all_from_dict(w) else: try: w.window.destroy() except (AttributeError, RuntimeError): w.destroy() def close_all(self, account, force=False): """ Close all the windows from an account. If force is True, do not ask confirmation before closing chat/gc windows """ if account in app.interface.instances: self.close_all_from_dict(app.interface.instances[account]) for ctrl in app.interface.msg_win_mgr.get_controls(acct=account): ctrl.parent_win.remove_tab(ctrl, ctrl.parent_win.CLOSE_CLOSE_BUTTON, force=force) def on_roster_window_delete_event(self, widget, event): """ Main window X button was clicked """ if not app.config.get('quit_on_roster_x_button') and ( (app.interface.systray_enabled and app.config.get('trayicon') != \ 'on_event') or app.config.get('allow_hide_roster')): save_roster_position(self.window) if os.name == 'nt' or app.config.get('hide_on_roster_x_button'): self.window.hide() else: self.window.iconify() elif app.config.get('quit_on_roster_x_button'): self.on_quit_request() else: def on_ok(checked): if checked: app.config.set('quit_on_roster_x_button', True) self.on_quit_request() ConfirmationDialogCheck(_('Really quit Gajim?'), _('Are you sure you want to quit Gajim?'), _('Always close Gajim'), on_response_ok=on_ok) return True # do NOT destroy the window def prepare_quit(self): if self.save_done: return msgwin_width_adjust = 0 # in case show_roster_on_start is False and roster is never shown # window.window is None if self.window.get_window() is not None: save_roster_position(self.window) width, height = self.window.get_size() app.config.set('roster_width', width) app.config.set('roster_height', height) if not self.xml.get_object('roster_vbox2').get_property('visible'): # The roster vbox is hidden, so the message window is larger # then we want to save (i.e. the window will grow every startup) # so adjust. msgwin_width_adjust = -1 * width app.config.set('last_roster_visible', self.window.get_property('visible')) app.interface.msg_win_mgr.save_opened_controls() app.interface.msg_win_mgr.shutdown(msgwin_width_adjust) app.config.set('collapsed_rows', '\t'.join(self.collapsed_rows)) app.interface.save_config() for account in app.connections: app.connections[account].quit(True) self.close_all(account) if app.interface.systray_enabled: app.interface.hide_systray() self.save_done = True def quit_gtkgui_interface(self): """ When we quit the gtk interface - exit gtk """ self.prepare_quit() self.application.quit() def on_quit_request(self, widget=None): """ User wants to quit. Check if he should be warned about messages pending. Terminate all sessions and send offline to all connected account. We do NOT really quit gajim here """ accounts = list(app.connections.keys()) get_msg = False for acct in accounts: if app.connections[acct].connected: get_msg = True break def on_continue3(message, pep_dict): self.quit_on_next_offline = 0 accounts_to_disconnect = [] for acct in accounts: if app.connections[acct].connected > 1: self.quit_on_next_offline += 1 accounts_to_disconnect.append(acct) if not self.quit_on_next_offline: # all accounts offline, quit self.quit_gtkgui_interface() return for acct in accounts_to_disconnect: self.send_status(acct, 'offline', message) self.send_pep(acct, pep_dict) def on_continue2(message, pep_dict): if 'file_transfers' not in app.interface.instances: on_continue3(message, pep_dict) return # check if there is an active file transfer from gajim.common.protocol.bytestream import is_transfer_active files_props = app.interface.instances['file_transfers'].\ files_props transfer_active = False for x in files_props: for y in files_props[x]: if is_transfer_active(files_props[x][y]): transfer_active = True break if transfer_active: ConfirmationDialog(_('You have running file transfers'), _('If you quit now, the file(s) being transferred will ' 'be stopped. Do you still want to quit?'), on_response_ok=(on_continue3, message, pep_dict)) return on_continue3(message, pep_dict) def on_continue(message, pep_dict): if message is None: # user pressed Cancel to change status message dialog return # check if we have unread messages unread = app.events.get_nb_events() if not app.config.get('notify_on_all_muc_messages'): unread_not_to_notify = app.events.get_nb_events( ['printed_gc_msg']) unread -= unread_not_to_notify # check if we have recent messages recent = False for win in app.interface.msg_win_mgr.windows(): for ctrl in win.controls(): fjid = ctrl.get_full_jid() if fjid in app.last_message_time[ctrl.account]: if time.time() - app.last_message_time[ctrl.account][ fjid] < 2: recent = True break if recent: break if unread or recent: ConfirmationDialog(_('You have unread messages'), _('Messages will only be available for reading them later ' 'if you have history enabled and contact is in your ' 'roster.'), on_response_ok=(on_continue2, message, pep_dict)) return on_continue2(message, pep_dict) if get_msg: self.get_status_message('offline', on_continue, show_pep=False) else: on_continue('', None) def _nec_presence_received(self, obj): account = obj.conn.name jid = obj.jid if obj.need_add_in_roster: self.add_contact(jid, account) jid_list = app.contacts.get_jid_list(account) if jid in jid_list or jid == app.get_jid_from_account(account): if not app.jid_is_transport(jid) and len(obj.contact_list) == 1: if obj.old_show == 0 and obj.new_show > 1: GLib.timeout_add_seconds(5, self.remove_newly_added, jid, account) elif obj.old_show > 1 and obj.new_show == 0 and \ obj.conn.connected > 1: GLib.timeout_add_seconds(5, self.remove_to_be_removed, jid, account) if obj.need_redraw: self.draw_contact(jid, account) if app.jid_is_transport(jid) and jid in jid_list: # It must be an agent # Update existing iter and group counting self.draw_contact(jid, account) self.draw_group(_('Transports'), account) if obj.contact and obj.need_redraw: self.chg_contact_status(obj.contact, obj.show, obj.status, account) if obj.popup: ctrl = app.interface.msg_win_mgr.search_control(jid, account) if ctrl: GLib.idle_add(ctrl.parent_win.set_active_tab, ctrl) else: ctrl = app.interface.new_chat(obj.contact, account) if app.events.get_events(account, obj.jid): ctrl.read_queue() def _nec_gc_presence_received(self, obj): account = obj.conn.name if obj.room_jid in app.interface.minimized_controls[account]: gc_ctrl = app.interface.minimized_controls[account][obj.room_jid] else: return if obj.nick == gc_ctrl.nick: contact = app.contacts.get_contact_with_highest_priority( account, obj.room_jid) if contact: contact.show = obj.show self.draw_contact(obj.room_jid, account) self.draw_group(_('Groupchats'), account) def _nec_roster_received(self, obj): if obj.received_from_server: self.fill_contacts_and_groups_dicts(obj.roster, obj.conn.name) self.add_account_contacts(obj.conn.name) self.fire_up_unread_messages_events(obj.conn.name) else: # add self contact if app.config.get('show_self_contact') == 'always': account = obj.conn.name self_jid = app.get_jid_from_account(account) if self_jid not in app.contacts.get_jid_list(account): resource = '' if app.connections[account].server_resource: resource = app.connections[account].server_resource sha = app.config.get_per('accounts', account, 'avatar_sha') contact = app.contacts.create_contact( jid=self_jid, account=account, name=app.nicks[account], groups=['self_contact'], show='offline', sub='both', ask='none', resource=resource, avatar_sha=sha) app.contacts.add_contact(account, contact) self.add_contact(self_jid, account) if app.config.get('remember_opened_chat_controls'): account = obj.conn.name controls = app.config.get_per( 'accounts', account, 'opened_chat_controls') if controls: for jid in controls.split(','): contact = \ app.contacts.get_contact_with_highest_priority( account, jid) if not contact: contact = self.add_to_not_in_the_roster( account, jid) app.interface.on_open_chat_window( None, contact, account) app.config.set_per( 'accounts', account, 'opened_chat_controls', '') GLib.idle_add(self.refilter_shown_roster_items) def _nec_anonymous_auth(self, obj): """ This event is raised when our JID changed (most probably because we use anonymous account. We update contact and roster entry in this case """ self.rename_self_contact(obj.old_jid, obj.new_jid, obj.conn.name) def _nec_our_show(self, obj): model = self.status_combobox.get_model() iter_ = model.get_iter_from_string('7') if obj.show == 'offline': # sensitivity for this menuitem if app.get_number_of_connected_accounts() == 0: model[iter_][3] = False self.application.set_account_actions_state(obj.conn.name) else: # sensitivity for this menuitem model[iter_][3] = True self.on_status_changed(obj.conn.name, obj.show) def _nec_connection_type(self, obj): self.draw_account(obj.conn.name) def _nec_agent_removed(self, obj): for jid in obj.jid_list: self.remove_contact(jid, obj.conn.name, backend=True) def _nec_pep_received(self, obj): if obj.user_pep.type_ not in (PEPEventType.ACTIVITY, PEPEventType.TUNE, PEPEventType.MOOD, PEPEventType.LOCATION, PEPEventType.NICKNAME): return if obj.jid == app.get_jid_from_account(obj.conn.name): self.draw_account(obj.conn.name) if obj.pep_type == 'nick': self.draw_contact(obj.jid, obj.conn.name) else: self.draw_pep(obj.jid, obj.conn.name, obj.pep_type) def _nec_update_avatar(self, obj): app.log('avatar').debug('Draw roster avatar: %s', obj.jid) self.draw_avatar(obj.jid, obj.account) def _nec_gc_subject_received(self, obj): contact = app.contacts.get_contact_with_highest_priority( obj.account, obj.jid) if contact: contact.status = obj.subject self.draw_contact(obj.jid, obj.account) def _nec_metacontacts_received(self, obj): self.redraw_metacontacts(obj.conn.name) def _nec_signed_in(self, obj): self.application.set_account_actions_state(obj.conn.name, True) self.draw_account(obj.conn.name) def _nec_decrypted_message_received(self, obj): if not obj.msgtxt: return True if obj.mtype not in ('normal', 'chat'): return if obj.mtype == 'normal' and obj.popup: # it's single message to be autopopuped SingleMessageWindow(obj.conn.name, obj.jid, action='receive', from_whom=obj.jid, subject=obj.subject, message=obj.msgtxt, resource=obj.resource, session=obj.session, form_node=obj.form_node) return if obj.popup and obj.mtype == 'chat' and not obj.session.control: contact = app.contacts.get_contact(obj.conn.name, obj.jid) obj.session.control = app.interface.new_chat(contact, obj.conn.name, session=obj.session) if app.events.get_events(obj.conn.name, obj.fjid): obj.session.control.read_queue() if obj.show_in_roster: self.draw_contact(obj.jid, obj.conn.name) self.show_title() # we show the * or [n] # Select the big brother contact in roster, it's visible because it # has events. family = app.contacts.get_metacontacts_family(obj.conn.name, obj.jid) if family: _nearby_family, bb_jid, bb_account = \ app.contacts.get_nearby_family_and_big_brother(family, obj.conn.name) else: bb_jid, bb_account = obj.jid, obj.conn.name self.select_contact(bb_jid, bb_account) ################################################################################ ### Menu and GUI callbacks ### FIXME: order callbacks in itself... ################################################################################ def on_bookmark_menuitem_activate(self, widget, account, jid, bookmark): app.interface.join_gc_room( account, jid, bookmark['nick'], bookmark['password']) def on_info(self, widget, contact, account): """ Call vcard_information_window class to display contact's information """ if app.connections[account].is_zeroconf: self.on_info_zeroconf(widget, contact, account) return info = app.interface.instances[account]['infos'] if contact.jid in info: info[contact.jid].window.present() else: info[contact.jid] = vcard.VcardWindow(contact, account) def on_info_zeroconf(self, widget, contact, account): info = app.interface.instances[account]['infos'] if contact.jid in info: info[contact.jid].window.present() else: contact = app.contacts.get_first_contact_from_jid(account, contact.jid) if contact.show in ('offline', 'error'): # don't show info on offline contacts return info[contact.jid] = vcard.ZeroconfVcardWindow(contact, account) def on_agent_logging(self, widget, jid, state, account): """ When an agent is requested to log in or off """ app.connections[account].send_agent_status(jid, state) def on_edit_agent(self, widget, contact, account): """ When we want to modify the agent registration """ ServiceRegistration(account, contact.jid) def on_remove_agent(self, widget, list_): """ When an agent is requested to be removed. list_ is a list of (contact, account) tuple """ for (contact, account) in list_: if app.config.get_per('accounts', account, 'hostname') == \ contact.jid: # We remove the server contact # remove it from treeview app.connections[account].get_module('Presence').unsubscribe(contact.jid) self.remove_contact(contact.jid, account, backend=True) return def remove(list_): for (contact, account) in list_: full_jid = contact.get_full_jid() app.connections[account].unsubscribe_agent(full_jid) # remove transport from treeview self.remove_contact(contact.jid, account, backend=True) # Check if there are unread events from some contacts has_unread_events = False for (contact, account) in list_: for jid in app.events.get_events(account): if jid.endswith(contact.jid): has_unread_events = True break if has_unread_events: ErrorDialog(_('You have unread messages'), _('You must read them before removing this transport.')) return if len(list_) == 1: pritext = _('Transport "%s" will be removed') % list_[0][0].jid sectext = _('You will no longer be able to send and receive ' 'messages from contacts using this transport.') else: pritext = _('Transports will be removed') jids = '' for (contact, account) in list_: jids += '\n ' + contact.get_shown_name() + ',' jids = jids[:-1] + '.' sectext = _('You will no longer be able to send and receive ' 'messages to contacts from these transports: %s') % jids ConfirmationDialog(pritext, sectext, on_response_ok=(remove, list_), transient_for=self.window) def _nec_blocking(self, obj): for jid in obj.changed: self.draw_contact(jid, obj.conn.name) def on_block(self, widget, list_, group=None): """ When clicked on the 'block' button in context menu. list_ is a list of (contact, account) """ def on_continue(msg, pep_dict): if msg is None: # user pressed Cancel to change status message dialog return accounts = [] for _, account in list_: con = app.connections[account] if con.get_module('PrivacyLists').supported or ( group is None and con.get_module('Blocking').supported): accounts.append(account) if group is None: for acct in accounts: l_ = [i[0] for i in list_ if i[1] == acct] con = app.connections[acct] con.get_module('PrivacyLists').block_contacts(l_, msg) for contact in l_: self.draw_contact(contact.jid, acct) else: for acct in accounts: l_ = [i[0] for i in list_ if i[1] == acct] con = app.connections[acct] con.get_module('PrivacyLists').block_group(group, l_, msg) self.draw_group(group, acct) for contact in l_: self.draw_contact(contact.jid, acct) def _block_it(is_checked=None): if is_checked is not None: # dialog has been shown if is_checked: # user does not want to be asked again app.config.set('confirm_block', 'no') else: app.config.set('confirm_block', 'yes') self.get_status_message('offline', on_continue, show_pep=False) confirm_block = app.config.get('confirm_block') if confirm_block == 'no': _block_it() return pritext = _('You are about to block a contact. Are you sure you want' ' to continue?') sectext = _('This contact will see you offline and you will not ' 'receive messages it sends you.') ConfirmationDialogCheck(pritext, sectext, _('_Do not ask me again'), on_response_ok=_block_it) def on_unblock(self, widget, list_, group=None): """ When clicked on the 'unblock' button in context menu. """ accounts = [] for _, account in list_: con = app.connections[account] if con.get_module('PrivacyLists').supported or ( group is None and con.get_module('Blocking').supported): accounts.append(account) if group is None: for acct in accounts: l_ = [i[0] for i in list_ if i[1] == acct] con = app.connections[acct] con.get_module('PrivacyLists').unblock_contacts(l_) for contact in l_: self.draw_contact(contact.jid, acct) else: for acct in accounts: l_ = [i[0] for i in list_ if i[1] == acct] con = app.connections[acct] con.get_module('PrivacyLists').unblock_group(group, l_) self.draw_group(group, acct) for contact in l_: self.draw_contact(contact.jid, acct) for acct in accounts: if 'privacy_list_block' in app.interface.instances[acct]: del app.interface.instances[acct]['privacy_list_block'] def on_rename(self, widget, row_type, jid, account): # this function is called either by F2 or by Rename menuitem if 'rename' in app.interface.instances: app.interface.instances['rename'].dialog.present() return # account is offline, don't allow to rename if app.connections[account].connected < 2: return if row_type in ('contact', 'agent'): # it's jid title = _('Rename Contact') message = _('Enter a new nickname for contact %s') % jid old_text = app.contacts.get_contact_with_highest_priority(account, jid).name elif row_type == 'group': if jid in helpers.special_groups + (_('General'),): return old_text = jid title = _('Rename Group') message = _('Enter a new name for group %s') % \ GLib.markup_escape_text(jid) def on_renamed(new_text, account, row_type, jid, old_text): if 'rename' in app.interface.instances: del app.interface.instances['rename'] if row_type in ('contact', 'agent'): if old_text == new_text: return contacts = app.contacts.get_contacts(account, jid) for contact in contacts: contact.name = new_text app.connections[account].update_contact(jid, new_text, \ contacts[0].groups) self.draw_contact(jid, account) # Update opened chats for ctrl in app.interface.msg_win_mgr.get_controls(jid, account): ctrl.update_ui() win = app.interface.msg_win_mgr.get_window(jid, account) win.redraw_tab(ctrl) win.show_title() elif row_type == 'group': # in Column.JID column, we hold the group name (which is not escaped) self.rename_group(old_text, new_text, account) def on_canceled(): if 'rename' in app.interface.instances: del app.interface.instances['rename'] app.interface.instances['rename'] = InputDialog(title, message, old_text, False, (on_renamed, account, row_type, jid, old_text), on_canceled, transient_for=self.window) def on_remove_group_item_activated(self, widget, group, account): def on_ok(checked): for contact in app.contacts.get_contacts_from_group(account, group): if not checked: self.remove_contact_from_groups(contact.jid, account, [group]) else: app.connections[account].get_module('Presence').unsubscribe(contact.jid) self.remove_contact(contact.jid, account, backend=True) ConfirmationDialogCheck(_('Remove Group'), _('Do you want to remove group %s from the roster?') % group, _('Also remove all contacts in this group from your roster'), on_response_ok=on_ok) def on_assign_pgp_key(self, widget, contact, account): attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() keys = {} keyID = _('None') for i in range(len(attached_keys) // 2): keys[attached_keys[2*i]] = attached_keys[2*i+1] if attached_keys[2*i] == contact.jid: keyID = attached_keys[2*i+1] public_keys = app.connections[account].ask_gpg_keys() public_keys[_('None')] = _('None') def on_key_selected(keyID): if keyID is None: return if keyID[0] == _('None'): if contact.jid in keys: del keys[contact.jid] keyID = '' else: keyID = keyID[0] keys[contact.jid] = keyID ctrl = app.interface.msg_win_mgr.get_control(contact.jid, account) if ctrl: ctrl.update_ui() keys_str = '' for jid in keys: keys_str += jid + ' ' + keys[jid] + ' ' app.config.set_per('accounts', account, 'attached_gpg_keys', keys_str) for u in app.contacts.get_contacts(account, contact.jid): u.keyID = helpers.prepare_and_validate_gpg_keyID(account, contact.jid, keyID) dialogs.ChooseGPGKeyDialog(_('Assign OpenPGP Key'), _('Select a key to apply to the contact'), public_keys, on_key_selected, selected=keyID, transient_for=self.window) def on_edit_groups(self, widget, list_): dialogs.EditGroupsDialog(list_) def on_history(self, widget, contact, account): """ When history menuitem is activated: call log window """ if 'logs' in app.interface.instances: app.interface.instances['logs'].window.present() app.interface.instances['logs'].open_history(contact.jid, account) else: app.interface.instances['logs'] = HistoryWindow(contact.jid, account) def on_disconnect(self, widget, jid, account): """ When disconnect menuitem is activated: disconnect from room """ if jid in app.interface.minimized_controls[account]: ctrl = app.interface.minimized_controls[account][jid] ctrl.shutdown() ctrl.got_disconnected() self.remove_groupchat(jid, account) def on_reconnect(self, widget, jid, account): """ When reconnect menuitem is activated: join the room """ if jid in app.interface.minimized_controls[account]: ctrl = app.interface.minimized_controls[account][jid] app.interface.join_gc_room(account, jid, ctrl.nick, app.gc_passwords.get(jid, '')) def on_send_single_message_menuitem_activate(self, widget, account, contact=None): if contact is None: SingleMessageWindow(account, action='send') elif isinstance(contact, list): SingleMessageWindow(account, contact, 'send') else: jid = contact.jid if contact.jid == app.get_jid_from_account(account): jid += '/' + contact.resource SingleMessageWindow(account, jid, 'send') def on_send_file_menuitem_activate(self, widget, contact, account, resource=None): app.interface.instances['file_transfers'].show_file_send_request( account, contact) def on_invite_to_new_room(self, widget, list_, resource=None): """ Resource parameter MUST NOT be used if more than one contact in list """ account_list = [] jid_list = [] for (contact, account) in list_: if contact.jid not in jid_list: if resource: # we MUST have one contact only in list_ fjid = contact.jid + '/' + resource jid_list.append(fjid) else: jid_list.append(contact.jid) if account not in account_list: account_list.append(account) # transform None in 'jabber' type_ = app.get_transport_name_from_jid(jid_list[0]) or 'jabber' for account in account_list: if app.connections[account].muc_jid[type_]: # create the room on this muc server if 'join_gc' in app.interface.instances[account]: app.interface.instances[account]['join_gc'].destroy() else: app.interface.instances[account]['join_gc'] = \ JoinGroupchatWindow( account, None, automatic={'invities': jid_list}) break def on_invite_to_room(self, widget, list_, room_jid, room_account, resource=None): """ Resource parameter MUST NOT be used if more than one contact in list """ for e in list_: contact = e[0] contact_jid = contact.jid if resource: # we MUST have one contact only in list_ contact_jid += '/' + resource con = app.connections[room_account] con.get_module('MUC').invite(room_jid, contact_jid) gc_control = app.interface.msg_win_mgr.get_gc_control(room_jid, room_account) if gc_control: gc_control.print_conversation( _('%(jid)s has been invited in this room') % { 'jid': contact_jid}, graphics=False) def on_all_groupchat_maximized(self, widget, group_list): for (contact, account) in group_list: self.on_groupchat_maximized(widget, contact.jid, account) def on_groupchat_maximized(self, widget, jid, account): """ When a groupchat is maximized """ if not jid in app.interface.minimized_controls[account]: # Already opened? gc_control = app.interface.msg_win_mgr.get_gc_control(jid, account) if gc_control: mw = app.interface.msg_win_mgr.get_window(jid, account) mw.set_active_tab(gc_control) return ctrl = app.interface.minimized_controls[account][jid] mw = app.interface.msg_win_mgr.get_window(jid, account) if not mw: mw = app.interface.msg_win_mgr.create_window(ctrl.contact, ctrl.account, ctrl.type_id) id_ = mw.window.connect('motion-notify-event', ctrl._on_window_motion_notify) ctrl.handlers[id_] = mw.window ctrl.parent_win = mw ctrl.on_groupchat_maximize() mw.new_tab(ctrl) mw.set_active_tab(ctrl) self.remove_groupchat(jid, account, maximize=True) def on_edit_account(self, widget, account): window = app.get_app_window(AccountsWindow) if window is None: window = AccountsWindow() else: window.present() window.select_account(account) def on_change_status_message_activate(self, widget, account): show = app.SHOW_LIST[app.connections[account].connected] def on_response(message, pep_dict): if message is None: # None is if user pressed Cancel return self.send_status(account, show, message) self.send_pep(account, pep_dict) dialogs.ChangeStatusMessageDialog(on_response, show) def on_add_to_roster(self, widget, contact, account): AddNewContactWindow(account, contact.jid, contact.name) def on_roster_treeview_key_press_event(self, widget, event): """ When a key is pressed in the treeviews """ if event.keyval == Gdk.KEY_Escape: if self.rfilter_enabled: self.disable_rfilter() else: self.tree.get_selection().unselect_all() elif event.keyval == Gdk.KEY_F2: treeselection = self.tree.get_selection() model, list_of_paths = treeselection.get_selected_rows() if len(list_of_paths) != 1: return path = list_of_paths[0] type_ = model[path][Column.TYPE] if type_ in ('contact', 'group', 'agent'): jid = model[path][Column.JID] account = model[path][Column.ACCOUNT] self.on_rename(widget, type_, jid, account) elif event.keyval == Gdk.KEY_Delete: treeselection = self.tree.get_selection() model, list_of_paths = treeselection.get_selected_rows() if not list_of_paths: return type_ = model[list_of_paths[0]][Column.TYPE] account = model[list_of_paths[0]][Column.ACCOUNT] if type_ in ('account', 'group', 'self_contact') or \ account == app.ZEROCONF_ACC_NAME: return list_ = [] for path in list_of_paths: if model[path][Column.TYPE] != type_: return jid = model[path][Column.JID] account = model[path][Column.ACCOUNT] if not app.account_is_connected(account): continue contact = app.contacts.get_contact_with_highest_priority( account, jid) list_.append((contact, account)) if not list_: return if type_ == 'contact': self.on_req_usub(widget, list_) elif type_ == 'agent': self.on_remove_agent(widget, list_) elif not (event.get_state() & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)): num = Gdk.keyval_to_unicode(event.keyval) if num and num > 31: # if we got unicode symbol without ctrl / alt self.enable_rfilter(chr(num)) elif event.get_state() & Gdk.ModifierType.CONTROL_MASK and \ event.get_state() & Gdk.ModifierType.SHIFT_MASK and \ event.keyval == Gdk.KEY_U: self.enable_rfilter('') self.rfilter_entry.event(event) elif event.keyval == Gdk.KEY_Left: treeselection = self.tree.get_selection() model, list_of_paths = treeselection.get_selected_rows() if len(list_of_paths) != 1: return path = list_of_paths[0] iter_ = model.get_iter(path) if model.iter_has_child(iter_) and self.tree.row_expanded(path): self.tree.collapse_row(path) return True if path.get_depth() > 1: self.tree.set_cursor(path[:-1]) return True elif event.keyval == Gdk.KEY_Right: treeselection = self.tree.get_selection() model, list_of_paths = treeselection.get_selected_rows() if len(list_of_paths) != 1: return path = list_of_paths[0] iter_ = model.get_iter(path) if model.iter_has_child(iter_): self.tree.expand_row(path, False) return True def on_roster_treeview_button_release_event(self, widget, event): try: path = self.tree.get_path_at_pos(int(event.x), int(event.y))[0] except TypeError: return False if event.button == 1: # Left click if app.single_click and not event.get_state() & Gdk.ModifierType.SHIFT_MASK and \ not event.get_state() & Gdk.ModifierType.CONTROL_MASK: # Check if button has been pressed on the same row if self.clicked_path == path: self.on_row_activated(widget, path) self.clicked_path = None def accel_group_func(self, accel_group, acceleratable, keyval, modifier): # CTRL mask if modifier & Gdk.ModifierType.CONTROL_MASK: if keyval == Gdk.KEY_s: # CTRL + s model = self.status_combobox.get_model() accounts = list(app.connections.keys()) status = model[self.previous_status_combobox_active][2] def on_response(message, pep_dict): if message is not None: # None if user pressed Cancel for account in accounts: if not app.config.get_per('accounts', account, 'sync_with_global_status'): continue current_show = app.SHOW_LIST[ app.connections[account].connected] self.send_status(account, current_show, message) self.send_pep(account, pep_dict) dialogs.ChangeStatusMessageDialog(on_response, status) return True if keyval == Gdk.KEY_k: # CTRL + k self.enable_rfilter('') def on_roster_treeview_button_press_event(self, widget, event): try: pos = self.tree.get_path_at_pos(int(event.x), int(event.y)) path, x = pos[0], pos[2] except TypeError: self.tree.get_selection().unselect_all() return False if event.button == 3: # Right click try: model, list_of_paths = self.tree.get_selection().\ get_selected_rows() except TypeError: list_of_paths = [] if path not in list_of_paths: self.tree.get_selection().unselect_all() self.tree.get_selection().select_path(path) return self.show_treeview_menu(event) if event.button == 2: # Middle click try: model, list_of_paths = self.tree.get_selection().\ get_selected_rows() except TypeError: list_of_paths = [] if list_of_paths != [path]: self.tree.get_selection().unselect_all() self.tree.get_selection().select_path(path) type_ = model[path][Column.TYPE] if type_ in ('agent', 'contact', 'self_contact', 'groupchat'): self.on_row_activated(widget, path) elif type_ == 'account': account = model[path][Column.ACCOUNT] if account != 'all': show = app.connections[account].connected if show > 1: # We are connected self.on_change_status_message_activate(widget, account) return True show = helpers.get_global_show() if show == 'offline': return True def on_response(message, pep_dict): if message is None: return True for acct in app.connections: if not app.config.get_per('accounts', acct, 'sync_with_global_status'): continue current_show = app.SHOW_LIST[app.connections[acct].\ connected] self.send_status(acct, current_show, message) self.send_pep(acct, pep_dict) dialogs.ChangeStatusMessageDialog(on_response, show) return True if event.button == 1: # Left click model = self.modelfilter type_ = model[path][Column.TYPE] # x_min is the x start position of status icon column if app.config.get('avatar_position_in_roster') == 'left': x_min = AvatarSize.ROSTER else: x_min = 0 if (app.single_click and not event.get_state() & Gdk.ModifierType.SHIFT_MASK and not event.get_state() & Gdk.ModifierType.CONTROL_MASK): # Don't handle double click if we press icon of a metacontact titer = model.get_iter(path) if x > x_min and x < x_min + 27 and type_ == 'contact' and \ model.iter_has_child(titer): if self.tree.row_expanded(path): self.tree.collapse_row(path) else: self.tree.expand_row(path, False) return # We just save on which row we press button, and open chat # window on button release to be able to do DND without opening # chat window self.clicked_path = path return if type_ == 'group' and x < 27: # first cell in 1st column (the arrow SINGLE clicked) if self.tree.row_expanded(path): self.tree.collapse_row(path) else: self.expand_group_row(path) elif type_ == 'contact' and x > x_min and x < x_min + 27: if self.tree.row_expanded(path): self.tree.collapse_row(path) else: self.tree.expand_row(path, False) def expand_group_row(self, path): self.tree.expand_row(path, False) iter_ = self.modelfilter.get_iter(path) child_iter = self.modelfilter.iter_children(iter_) while child_iter: type_ = self.modelfilter[child_iter][Column.TYPE] account = self.modelfilter[child_iter][Column.ACCOUNT] group = self.modelfilter[child_iter][Column.JID] if type_ == 'group' and account + group not in self.collapsed_rows: self.expand_group_row(self.modelfilter.get_path(child_iter)) child_iter = self.modelfilter.iter_next(child_iter) def on_req_usub(self, widget, list_): """ Remove a contact. list_ is a list of (contact, account) tuples """ def on_ok(is_checked, list_): remove_auth = True if len(list_) == 1: contact = list_[0][0] if contact.sub != 'to' and is_checked: remove_auth = False for (contact, account) in list_: if _('Not in Roster') not in contact.get_shown_groups(): app.connections[account].get_module('Presence').unsubscribe(contact.jid, remove_auth) self.remove_contact(contact.jid, account, backend=True) if not remove_auth and contact.sub == 'both': contact.name = '' contact.groups = [] contact.sub = 'from' # we can't see him, but have to set it manually in contact contact.show = 'offline' app.contacts.add_contact(account, contact) self.add_contact(contact.jid, account) def on_ok2(list_): on_ok(False, list_) if len(list_) == 1: contact = list_[0][0] pritext = _('Contact "%s" will be removed from your roster') % \ contact.get_shown_name() sectext = _('You are about to remove "%(name)s" (%(jid)s) from ' 'your roster.\n') % {'name': contact.get_shown_name(), 'jid': contact.jid} if contact.sub == 'to': ConfirmationDialog(pritext, sectext + \ _('By removing this contact you also remove authorization ' 'resulting in them always seeing you as offline.'), on_response_ok=(on_ok2, list_)) elif _('Not in Roster') in contact.get_shown_groups(): # Contact is not in roster ConfirmationDialog(pritext, sectext + \ _('Do you want to continue?'), on_response_ok=(on_ok2, list_)) else: ConfirmationDialogCheck(pritext, sectext + \ _('By removing this contact you also by default remove ' 'authorization resulting in them always seeing you as' ' offline.'), _('I want this contact to know my status after removal'), on_response_ok=(on_ok, list_)) else: # several contact to remove at the same time pritext = _('Contacts will be removed from your roster') jids = '' for contact, _account in list_: jids += '\n ' + contact.get_shown_name() + ' (%s)' % \ contact.jid + ',' sectext = _('By removing these contacts:%s\nyou also remove ' 'authorization resulting in them always seeing you as ' 'offline.') % jids ConfirmationDialog(pritext, sectext, on_response_ok=(on_ok2, list_)) def on_send_custom_status(self, widget, contact_list, show, group=None): """ Send custom status """ # contact_list has only one element except if group != None def on_response(message, pep_dict): if message is None: # None if user pressed Cancel return account_list = [] for (contact, account) in contact_list: if account not in account_list: account_list.append(account) # 1. update status_sent_to_[groups|users] list if group: for account in account_list: if account not in app.interface.status_sent_to_groups: app.interface.status_sent_to_groups[account] = {} app.interface.status_sent_to_groups[account][group] = show else: for (contact, account) in contact_list: if account not in app.interface.status_sent_to_users: app.interface.status_sent_to_users[account] = {} app.interface.status_sent_to_users[account][contact.jid] \ = show # 2. update privacy lists if main status is invisible for account in account_list: if app.SHOW_LIST[app.connections[account].connected] == \ 'invisible': con = app.connections[account] con.get_module('PrivacyLists').set_invisible_rule() # 3. send directed presence for (contact, account) in contact_list: our_jid = app.get_jid_from_account(account) jid = contact.jid if jid == our_jid: jid += '/' + contact.resource self.send_status(account, show, message, to=jid) def send_it(is_checked=None): if is_checked is not None: # dialog has been shown if is_checked: # user does not want to be asked again app.config.set('confirm_custom_status', 'no') else: app.config.set('confirm_custom_status', 'yes') self.get_status_message(show, on_response, show_pep=False, always_ask=True) confirm_custom_status = app.config.get('confirm_custom_status') if confirm_custom_status == 'no': send_it() return pritext = _('You are about to send a custom status. Are you sure you ' 'want to continue?') sectext = _('This contact will temporarily see you as %(status)s, ' 'but only until you change your status. Then they will see ' 'your global status.') % {'status': show} ConfirmationDialogCheck(pritext, sectext, _('_Do not ask me again'), on_response_ok=send_it) def on_status_combobox_changed(self, widget): """ When we change our status via the combobox """ model = self.status_combobox.get_model() active = self.status_combobox.get_active() if active == -1: # no active item return if not self.combobox_callback_active: self.previous_status_combobox_active = active return accounts = list(app.connections.keys()) if not accounts: ErrorDialog(_('No account available'), _('You must create an account before you can chat with other ' 'contacts.')) self.update_status_combobox() return status = model[active][2] # status "desync'ed" or not statuses_unified = helpers.statuses_unified() if (active == 7 and statuses_unified) or (active == 9 and \ not statuses_unified): # 'Change status message' selected: # do not change show, just show change status dialog status = model[self.previous_status_combobox_active][2] def on_response(message, pep_dict): if message is not None: # None if user pressed Cancel for account in accounts: if not app.config.get_per('accounts', account, 'sync_with_global_status'): continue current_show = app.SHOW_LIST[ app.connections[account].connected] self.send_status(account, current_show, message) self.send_pep(account, pep_dict) self.combobox_callback_active = False self.status_combobox.set_active( self.previous_status_combobox_active) self.combobox_callback_active = True dialogs.ChangeStatusMessageDialog(on_response, status) return # we are about to change show, so save this new show so in case # after user chooses "Change status message" menuitem # we can return to this show self.previous_status_combobox_active = active connected_accounts = app.get_number_of_connected_accounts() def on_continue(message, pep_dict): if message is None: # user pressed Cancel to change status message dialog self.update_status_combobox() return global_sync_accounts = [] for acct in accounts: if app.config.get_per('accounts', acct, 'sync_with_global_status'): global_sync_accounts.append(acct) global_sync_connected_accounts = \ app.get_number_of_connected_accounts(global_sync_accounts) for account in accounts: if not app.config.get_per('accounts', account, 'sync_with_global_status'): continue # we are connected (so we wanna change show and status) # or no account is connected and we want to connect with new # show and status if not global_sync_connected_accounts > 0 or \ app.connections[account].connected > 0: self.send_status(account, status, message) self.send_pep(account, pep_dict) self.update_status_combobox() if status == 'invisible': bug_user = False for account in accounts: if connected_accounts < 1 or app.account_is_connected( account): if not app.config.get_per('accounts', account, 'sync_with_global_status'): continue # We're going to change our status to invisible if self.connected_rooms(account): bug_user = True break if bug_user: def on_ok(): self.get_status_message(status, on_continue, show_pep=False) def on_cancel(): self.update_status_combobox() ConfirmationDialog( _('You are participating in one or more group chats'), _('Changing your status to invisible will result in ' 'disconnection from those group chats. Are you sure you ' 'want to go invisible?'), on_response_ok=on_ok, on_response_cancel=on_cancel) return self.get_status_message(status, on_continue) def on_publish_tune_toggled(self, widget, account): active = widget.get_active() app.config.set_per('accounts', account, 'publish_tune', active) if active: app.interface.enable_music_listener() else: app.connections[account].get_module('UserTune').send(None) # disable music listener only if no other account uses it for acc in app.connections: if app.config.get_per('accounts', acc, 'publish_tune'): break else: app.interface.disable_music_listener() helpers.update_optional_features(account) def on_publish_location_toggled(self, widget, account): active = widget.get_active() app.config.set_per('accounts', account, 'publish_location', active) if active: location.enable() else: app.connections[account].get_module('UserLocation').send(None) helpers.update_optional_features(account) def on_pep_services_menuitem_activate(self, widget, account): if 'pep_services' in app.interface.instances[account]: app.interface.instances[account]['pep_services'].window.present() else: app.interface.instances[account]['pep_services'] = \ ManagePEPServicesWindow(account) def on_add_new_contact(self, widget, account): AddNewContactWindow(account) def on_join_gc_activate(self, widget, account): """ When the join gc menuitem is clicked, show the join gc window """ app.app.activate_action('%s-join-groupchat' % account, GLib.Variant('as', [account, ''])) def on_show_transports_action(self, action, param): app.config.set('show_transports_group', param.get_boolean()) action.set_state(param) self.refilter_shown_roster_items() def on_manage_bookmarks_menuitem_activate(self, widget): ManageBookmarksWindow() def on_execute_command(self, widget, contact, account, resource=None): """ Execute command. Full JID needed; if it is other contact, resource is necessary. Widget is unnecessary, only to be able to make this a callback """ jid = contact.jid if resource is not None: jid = jid + '/' + resource adhoc_commands.CommandWindow(account, jid) def on_roster_window_focus_in_event(self, widget, event): # roster received focus, so if we had urgency REMOVE IT # NOTE: we do not have to read the message to remove urgency # so this functions does that gtkgui_helpers.set_unset_urgency_hint(widget, False) # if a contact row is selected, update colors (eg. for status msg) # because gtk engines may differ in bg when window is selected # or not if self._last_selected_contact: for (jid, account) in self._last_selected_contact: self.draw_contact(jid, account, selected=True, focus=True) def on_roster_window_focus_out_event(self, widget, event): # if a contact row is selected, update colors (eg. for status msg) # because gtk engines may differ in bg when window is selected # or not if self._last_selected_contact: for (jid, account) in self._last_selected_contact: self.draw_contact(jid, account, selected=True, focus=False) def on_roster_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: if self.rfilter_enabled: self.disable_rfilter() return True if app.interface.msg_win_mgr.mode == \ MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER and \ app.interface.msg_win_mgr.one_window_opened(): # let message window close the tab return list_of_paths = self.tree.get_selection().get_selected_rows()[1] if not list_of_paths and not app.config.get( 'quit_on_roster_x_button') and ((app.interface.systray_enabled and\ app.config.get('trayicon') == 'always') or app.config.get( 'allow_hide_roster')): if os.name == 'nt' or app.config.get('hide_on_roster_x_button'): self.window.hide() else: self.window.iconify() elif event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == \ Gdk.KEY_i: treeselection = self.tree.get_selection() model, list_of_paths = treeselection.get_selected_rows() for path in list_of_paths: type_ = model[path][Column.TYPE] if type_ in ('contact', 'agent'): jid = model[path][Column.JID] account = model[path][Column.ACCOUNT] contact = app.contacts.get_first_contact_from_jid(account, jid) self.on_info(widget, contact, account) elif event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == \ Gdk.KEY_h: treeselection = self.tree.get_selection() model, list_of_paths = treeselection.get_selected_rows() if len(list_of_paths) != 1: return path = list_of_paths[0] type_ = model[path][Column.TYPE] if type_ in ('contact', 'agent'): jid = model[path][Column.JID] account = model[path][Column.ACCOUNT] contact = app.contacts.get_first_contact_from_jid(account, jid) self.on_history(widget, contact, account) def on_roster_window_popup_menu(self, widget): event = Gdk.Event.new(Gdk.EventType.KEY_PRESS) self.show_treeview_menu(event) def on_row_activated(self, widget, path): """ When an iter is activated (double-click or single click if gnome is set this way) """ model = self.modelfilter account = model[path][Column.ACCOUNT] type_ = model[path][Column.TYPE] if type_ in ('group', 'account'): if self.tree.row_expanded(path): self.tree.collapse_row(path) else: self.tree.expand_row(path, False) return if self.rfilter_enabled: GObject.idle_add(self.disable_rfilter) jid = model[path][Column.JID] resource = None contact = app.contacts.get_contact_with_highest_priority(account, jid) titer = model.get_iter(path) if contact.is_groupchat(): first_ev = app.events.get_first_event(account, jid) if first_ev and self.open_event(account, jid, first_ev): # We are invited to a GC # open event cares about connecting to it self.remove_groupchat(jid, account) else: self.on_groupchat_maximized(None, jid, account) return # else first_ev = app.events.get_first_event(account, jid) if not first_ev: # look in other resources for c in app.contacts.get_contacts(account, jid): fjid = c.get_full_jid() first_ev = app.events.get_first_event(account, fjid) if first_ev: resource = c.resource break if not first_ev and model.iter_has_child(titer): child_iter = model.iter_children(titer) while not first_ev and child_iter: child_jid = model[child_iter][Column.JID] first_ev = app.events.get_first_event(account, child_jid) if first_ev: jid = child_jid else: child_iter = model.iter_next(child_iter) session = None if first_ev: if first_ev.type_ in ('chat', 'normal'): session = first_ev.session fjid = jid if resource: fjid += '/' + resource if self.open_event(account, fjid, first_ev): return # else contact = app.contacts.get_contact(account, jid, resource) if not contact or isinstance(contact, list): contact = app.contacts.get_contact_with_highest_priority(account, jid) if jid == app.get_jid_from_account(account): resource = None app.interface.on_open_chat_window(None, contact, account, \ resource=resource, session=session) def on_roster_treeview_row_activated(self, widget, path, col=0): """ When an iter is double clicked: open the first event window """ if not app.single_click: self.on_row_activated(widget, path) def on_roster_treeview_row_expanded(self, widget, titer, path): """ When a row is expanded change the icon of the arrow """ self._toggeling_row = True model = widget.get_model() child_model = model.get_model() child_iter = model.convert_iter_to_child_iter(titer) if self.regroup: # merged accounts accounts = list(app.connections.keys()) else: accounts = [model[titer][Column.ACCOUNT]] type_ = model[titer][Column.TYPE] if type_ == 'group': group = model[titer][Column.JID] child_model[child_iter][Column.IMG] = \ app.interface.jabber_state_images['16']['opened'] if self.rfilter_enabled: return for account in accounts: if group in app.groups[account]: # This account has this group app.groups[account][group]['expand'] = True if account + group in self.collapsed_rows: self.collapsed_rows.remove(account + group) for contact in app.contacts.iter_contacts(account): jid = contact.jid if group in contact.groups and \ app.contacts.is_big_brother(account, jid, accounts) and \ account + group + jid not in self.collapsed_rows: titers = self._get_contact_iter(jid, account) for titer_ in titers: path = model.get_path(titer_) self.tree.expand_row(path, False) elif type_ == 'account': account = list(accounts)[0] # There is only one cause we don't use merge if account in self.collapsed_rows: self.collapsed_rows.remove(account) self.draw_account(account) # When we expand, groups are collapsed. Restore expand state for group in app.groups[account]: if app.groups[account][group]['expand']: titer = self._get_group_iter(group, account) if titer: path = model.get_path(titer) self.tree.expand_row(path, False) elif type_ == 'contact': # Metacontact got toggled, update icon jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] contact = app.contacts.get_contact(account, jid) for group in contact.groups: if account + group + jid in self.collapsed_rows: self.collapsed_rows.remove(account + group + jid) family = app.contacts.get_metacontacts_family(account, jid) nearby_family = \ self._get_nearby_family_and_big_brother(family, account)[0] # Redraw all brothers to show pending events for data in nearby_family: self.draw_contact(data['jid'], data['account']) self._toggeling_row = False def on_roster_treeview_row_collapsed(self, widget, titer, path): """ When a row is collapsed change the icon of the arrow """ self._toggeling_row = True model = widget.get_model() child_model = model.get_model() child_iter = model.convert_iter_to_child_iter(titer) if self.regroup: # merged accounts accounts = list(app.connections.keys()) else: accounts = [model[titer][Column.ACCOUNT]] type_ = model[titer][Column.TYPE] if type_ == 'group': child_model[child_iter][Column.IMG] = app.interface.\ jabber_state_images['16']['closed'] if self.rfilter_enabled: return group = model[titer][Column.JID] for account in accounts: if group in app.groups[account]: # This account has this group app.groups[account][group]['expand'] = False if account + group not in self.collapsed_rows: self.collapsed_rows.append(account + group) elif type_ == 'account': account = accounts[0] # There is only one cause we don't use merge if account not in self.collapsed_rows: self.collapsed_rows.append(account) self.draw_account(account) elif type_ == 'contact': # Metacontact got toggled, update icon jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] contact = app.contacts.get_contact(account, jid) groups = contact.groups if not groups: groups = [_('General')] for group in groups: if account + group + jid not in self.collapsed_rows: self.collapsed_rows.append(account + group + jid) family = app.contacts.get_metacontacts_family(account, jid) nearby_family = \ self._get_nearby_family_and_big_brother(family, account)[0] # Redraw all brothers to show pending events for data in nearby_family: self.draw_contact(data['jid'], data['account']) self._toggeling_row = False def on_modelfilter_row_has_child_toggled(self, model, path, titer): """ Called when a row has gotten the first or lost its last child row Expand Parent if necessary. """ if self._toggeling_row: # Signal is emitted when we write to our model return type_ = model[titer][Column.TYPE] account = model[titer][Column.ACCOUNT] if not account: return if type_ == 'contact': child_iter = model.convert_iter_to_child_iter(titer) if self.model.iter_has_child(child_iter): # we are a bigbrother metacontact # redraw us to show/hide expand icon if self.filtering: # Prevent endless loops jid = model[titer][Column.JID] GLib.idle_add(self.draw_contact, jid, account) elif type_ == 'group': group = model[titer][Column.JID] GLib.idle_add(self._adjust_group_expand_collapse_state, group, account) elif type_ == 'account': GLib.idle_add(self._adjust_account_expand_collapse_state, account) # Selection can change when the model is filtered # Only write to the model when filtering is finished! # # FIXME: When we are filtering our custom colors are somehow lost # # def on_treeview_selection_changed(self, selection): # '''Called when selection in TreeView has changed. # # Redraw unselected rows to make status message readable # on all possible backgrounds. # ''' # model, list_of_paths = selection.get_selected_rows() # if len(self._last_selected_contact): # # update unselected rows # for (jid, account) in self._last_selected_contact: # GLib.idle_add(self.draw_contact, jid, # account) # self._last_selected_contact = [] # if len(list_of_paths) == 0: # return # for path in list_of_paths: # row = model[path] # if row[Column.TYPE] != 'contact': # self._last_selected_contact = [] # return # jid = row[Column.JID] # account = row[Column.ACCOUNT] # self._last_selected_contact.append((jid, account)) # GLib.idle_add(self.draw_contact, jid, account, True) def on_service_disco_menuitem_activate(self, widget, account): server_jid = app.config.get_per('accounts', account, 'hostname') if server_jid in app.interface.instances[account]['disco']: app.interface.instances[account]['disco'][server_jid].\ window.present() else: try: # Object will add itself to the window dict disco.ServiceDiscoveryWindow(account, address_entry=True) except GajimGeneralException: pass def on_show_offline_contacts_action(self, action, param): """ When show offline option is changed: redraw the treeview """ action.set_state(param) app.config.set('showoffline', param.get_boolean()) self.refilter_shown_roster_items() self.window.lookup_action('show-active').set_enabled( not param.get_boolean()) def on_show_active_contacts_action(self, action, param): """ When show only active contact option is changed: redraw the treeview """ action.set_state(param) app.config.set('show_only_chat_and_online', param.get_boolean()) self.refilter_shown_roster_items() self.window.lookup_action('show-offline').set_enabled( not param.get_boolean()) def on_show_roster_action(self, action, param): # when num controls is 0 this menuitem is hidden, but still need to # disable keybinding action.set_state(param) if self.hpaned.get_child2() is not None: self.show_roster_vbox(param.get_boolean()) def on_rfilter_entry_changed(self, widget): """ When we update the content of the filter """ self.rfilter_string = widget.get_text().lower() if self.rfilter_string == '': self.disable_rfilter() self.refilter_shown_roster_items() # select first row self.tree.get_selection().unselect_all() def _func(model, path, iter_, param): if model[iter_][Column.TYPE] == 'contact' and self.rfilter_string in \ model[iter_][Column.NAME].lower(): col = self.tree.get_column(0) self.tree.set_cursor_on_cell(path, col, None, False) return True self.modelfilter.foreach(_func, None) def on_rfilter_entry_icon_press(self, widget, icon, event): """ Disable the roster filtering by clicking the icon in the textEntry """ self.disable_rfilter() def on_rfilter_entry_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.disable_rfilter() elif event.keyval == Gdk.KEY_Return: self.tree.grab_focus() self.tree.event(event) self.disable_rfilter() elif event.keyval in (Gdk.KEY_Up, Gdk.KEY_Down): self.tree.grab_focus() self.tree.event(event) elif event.keyval == Gdk.KEY_BackSpace: if widget.get_text() == '': self.disable_rfilter() def enable_rfilter(self, search_string): self.rfilter_entry.set_visible(True) self.rfilter_entry.set_editable(True) self.rfilter_entry.grab_focus() if self.rfilter_enabled: self.rfilter_entry.set_text(self.rfilter_entry.get_text() + \ search_string) else: self.rfilter_enabled = True self.rfilter_entry.set_text(search_string) self.tree.expand_all() self.rfilter_entry.set_position(-1) # If roster is hidden, let's temporarily show it. This can happen if user # enables rfilter via keyboard shortcut. self.show_roster_vbox(True) def disable_rfilter(self): self.rfilter_enabled = False self.rfilter_entry.set_text('') self.rfilter_entry.set_visible(False) self.rfilter_entry.set_editable(False) self.refilter_shown_roster_items() self.tree.grab_focus() self._readjust_expand_collapse_state() # If roster was hidden before enable_rfilter was called, hide it back. state = self.window.lookup_action('show-roster').get_state().get_boolean() if state is False and self.hpaned.get_child2() is not None: self.show_roster_vbox(False) def on_roster_hpaned_notify(self, pane, gparamspec): """ Keep changing the width of the roster (when a Gtk.Paned widget handle is dragged) """ if gparamspec and gparamspec.name == 'position': roster_width = pane.get_child1().get_allocation().width app.config.set('roster_width', roster_width) app.config.set('roster_hpaned_position', pane.get_position()) ################################################################################ ### Drag and Drop handling ################################################################################ def drag_data_get_data(self, treeview, context, selection, target_id, etime): model, list_of_paths = self.tree.get_selection().get_selected_rows() if len(list_of_paths) != 1: return path = list_of_paths[0] data = '' if path.get_depth() >= 2: data = model[path][Column.JID] selection.set_text(data, -1) def drag_begin(self, treeview, context): self.dragging = True def drag_end(self, treeview, context): self.dragging = False def on_drop_rosterx(self, widget, account_source, c_source, account_dest, c_dest, was_big_brother, context, etime): type_ = 'message' if (c_dest.show not in ('offline', 'error') and c_dest.supports(NS_ROSTERX)): type_ = 'iq' con = app.connections[account_dest] con.get_module('RosterItemExchange').send_contacts( [c_source], c_dest.get_full_jid(), type_=type_) def on_drop_in_contact(self, widget, account_source, c_source, account_dest, c_dest, was_big_brother, context, etime): con_source = app.connections[account_source] con_dest = app.connections[account_dest] if (not con_source.get_module('MetaContacts').available or not con_dest.get_module('MetaContacts').available): WarningDialog(_('Metacontacts storage not supported by ' 'your server'), _('Your server does not support storing metacontacts ' 'information. So this information will not be saved on next ' 'reconnection.')) def merge_contacts(is_checked=None): contacts = 0 if is_checked is not None: # dialog has been shown if is_checked: # user does not want to be asked again app.config.set('confirm_metacontacts', 'no') else: app.config.set('confirm_metacontacts', 'yes') # We might have dropped on a metacontact. # Remove it and readd later with updated family info dest_family = app.contacts.get_metacontacts_family(account_dest, c_dest.jid) if dest_family: self._remove_metacontact_family(dest_family, account_dest) source_family = app.contacts.get_metacontacts_family( account_source, c_source.jid) if dest_family == source_family: n = contacts = len(dest_family) for tag in source_family: if tag['jid'] == c_source.jid: tag['order'] = contacts continue if 'order' in tag: n -= 1 tag['order'] = n else: self._remove_entity(c_dest, account_dest) old_family = app.contacts.get_metacontacts_family(account_source, c_source.jid) old_groups = c_source.groups # Remove old source contact(s) if was_big_brother: # We have got little brothers. Readd them all self._remove_metacontact_family(old_family, account_source) else: # We are only a little brother. Simply remove us from our big # brother if self._get_contact_iter(c_source.jid, account_source): # When we have been in the group before. # Do not try to remove us again self._remove_entity(c_source, account_source) own_data = {} own_data['jid'] = c_source.jid own_data['account'] = account_source # Don't touch the rest of the family old_family = [own_data] # Apply new tag and update contact for data in old_family: if account_source != data['account'] and not self.regroup: continue _account = data['account'] _jid = data['jid'] _contact = app.contacts.get_first_contact_from_jid(_account, _jid) if not _contact: # One of the metacontacts may be not connected. continue _contact.groups = c_dest.groups[:] app.contacts.add_metacontact(account_dest, c_dest.jid, _account, _contact.jid, contacts) app.connections[account_source].update_contact(_contact.jid, _contact.name, _contact.groups) # Re-add all and update GUI new_family = app.contacts.get_metacontacts_family(account_source, c_source.jid) brothers = self._add_metacontact_family(new_family, account_source) for c, acc in brothers: self.draw_completely(c.jid, acc) old_groups.extend(c_dest.groups) for g in old_groups: self.draw_group(g, account_source) self.draw_account(account_source) context.finish(True, True, etime) dest_family = app.contacts.get_metacontacts_family(account_dest, c_dest.jid) source_family = app.contacts.get_metacontacts_family(account_source, c_source.jid) confirm_metacontacts = app.config.get('confirm_metacontacts') if confirm_metacontacts == 'no' or dest_family == source_family: merge_contacts() return pritext = _('You are about to create a metacontact. Are you sure you ' 'want to continue?') sectext = _('Metacontacts are a way to regroup several contacts in one ' 'line. Generally it is used when the same person has several ' 'XMPP- or transport -accounts.') dlg = ConfirmationDialogCheck(pritext, sectext, _('_Do not ask me again'), on_response_ok=merge_contacts) if not confirm_metacontacts: # First time we see this window dlg.checkbutton.set_active(True) def on_drop_in_group(self, widget, account, c_source, grp_dest, is_big_brother, context, etime, grp_source=None): if is_big_brother: # add whole metacontact to new group self.add_contact_to_groups(c_source.jid, account, [grp_dest, ]) # remove afterwards so the contact is not moved to General in the # meantime if grp_dest != grp_source: self.remove_contact_from_groups(c_source.jid, account, [grp_source]) else: # Normal contact or little brother family = app.contacts.get_metacontacts_family(account, c_source.jid) if family: # Little brother # Remove whole family. Remove us from the family. # Then re-add other family members. self._remove_metacontact_family(family, account) app.contacts.remove_metacontact(account, c_source.jid) for data in family: if account != data['account'] and not self.regroup: continue if data['jid'] == c_source.jid and\ data['account'] == account: continue self.add_contact(data['jid'], data['account']) break self.add_contact_to_groups(c_source.jid, account, [grp_dest, ]) else: # Normal contact self.add_contact_to_groups(c_source.jid, account, [grp_dest, ]) # remove afterwards so the contact is not moved to General in # the meantime if grp_dest != grp_source: self.remove_contact_from_groups(c_source.jid, account, [grp_source]) if context.get_actions() in (Gdk.DragAction.MOVE, Gdk.DragAction.COPY): context.finish(True, True, etime) def drag_drop(self, treeview, context, x, y, timestamp): treeview.stop_emission_by_name('drag-drop') target_list = treeview.drag_dest_get_target_list() target = treeview.drag_dest_find_target(context, target_list) treeview.drag_get_data(context, target, timestamp) return True def move_group(self, old_name, new_name, account): for group in list(app.groups[account].keys()): if group.startswith(old_name): self.rename_group(group, group.replace(old_name, new_name), account) def drag_data_received_data(self, treeview, context, x, y, selection, info, etime): treeview.stop_emission_by_name('drag-data-received') drop_info = treeview.get_dest_row_at_pos(x, y) if not drop_info: return data = selection.get_data().decode() if not data: return # prevents tb when several entries are dragged model = treeview.get_model() path_dest, position = drop_info if position == Gtk.TreeViewDropPosition.BEFORE and len(path_dest) == 2 \ and path_dest[1] == 0: # dropped before the first group return if position == Gtk.TreeViewDropPosition.BEFORE and len(path_dest) == 2: # dropped before a group: we drop it in the previous group every # time path_dest = (path_dest[0], path_dest[1]-1) # destination: the row something got dropped on iter_dest = model.get_iter(path_dest) type_dest = model[iter_dest][Column.TYPE] jid_dest = model[iter_dest][Column.JID] account_dest = model[iter_dest][Column.ACCOUNT] # drop on account row in merged mode, we cannot know the desired account if account_dest == 'all': return # nothing can be done, if destination account is offline if app.connections[account_dest].connected < 2: return # A file got dropped on the roster if info == self.TARGET_TYPE_URI_LIST: if len(path_dest) < 3: return if type_dest != 'contact': return c_dest = app.contacts.get_contact_with_highest_priority( account_dest, jid_dest) if not c_dest.supports(NS_FILE): return uri = data.strip() uri_splitted = uri.split() # we may have more than one file dropped try: # This is always the last element in windows uri_splitted.remove('\0') except ValueError: pass nb_uri = len(uri_splitted) # Check the URIs bad_uris = [] for a_uri in uri_splitted: path = helpers.get_file_path_from_dnd_dropped_uri(a_uri) if not os.path.isfile(path): bad_uris.append(a_uri) if bad_uris: ErrorDialog(_('Invalid file URI:'), '\n'.join(bad_uris)) return def _on_send_files(account, jid, uris): c = app.contacts.get_contact_with_highest_priority(account, jid) for uri in uris: path = helpers.get_file_path_from_dnd_dropped_uri(uri) if os.path.isfile(path): # is it file? app.interface.instances['file_transfers'].send_file( account, c, path) # Popup dialog to confirm sending prim_text = _('Send file?') sec_text = i18n.ngettext('Do you want to send this file to %s:', 'Do you want to send these files to %s:', nb_uri) %\ c_dest.get_shown_name() for uri in uri_splitted: path = helpers.get_file_path_from_dnd_dropped_uri(uri) sec_text += '\n' + os.path.basename(path) dialog = NonModalConfirmationDialog(prim_text, sec_text, on_response_ok=(_on_send_files, account_dest, jid_dest, uri_splitted)) dialog.popup() return # a roster entry was dragged and dropped somewhere in the roster # source: the row that was dragged path_source = treeview.get_selection().get_selected_rows()[1][0] iter_source = model.get_iter(path_source) type_source = model[iter_source][Column.TYPE] account_source = model[iter_source][Column.ACCOUNT] if app.config.get_per('accounts', account_source, 'is_zeroconf'): return if type_dest == 'self_contact': # drop on self contact row return if type_dest == 'groupchat': # drop on a minimized groupchat # TODO: Invite to groupchat if type_dest = contact return if type_source == 'group': if account_source != account_dest: # drop on another account return grp_source = model[iter_source][Column.JID] delimiter = app.connections[account_source].get_module('Delimiter').delimiter grp_source_list = grp_source.split(delimiter) new_grp = None if type_dest == 'account': new_grp = grp_source_list[-1] elif type_dest == 'group': grp_dest = model[iter_dest][Column.JID] grp_dest_list = grp_dest.split(delimiter) # Do not allow to drop on a subgroup of source group if grp_source_list[0] != grp_dest_list[0]: new_grp = model[iter_dest][Column.JID] + delimiter + \ grp_source_list[-1] if new_grp: self.move_group(grp_source, new_grp, account_source) # Only normal contacts and group can be dragged if type_source != 'contact': return # A contact was dropped if app.config.get_per('accounts', account_dest, 'is_zeroconf'): # drop on zeroconf account, adding not possible return if type_dest == 'account' and account_source == account_dest: # drop on the account it was dragged from return # Get valid source group, jid and contact it = iter_source while model[it][Column.TYPE] == 'contact': it = model.iter_parent(it) grp_source = model[it][Column.JID] if grp_source in helpers.special_groups and \ grp_source not in ('Not in Roster', 'Observers'): # a transport or a minimized groupchat was dragged # we can add it to other accounts but not move it to another group, # see below return jid_source = data c_source = app.contacts.get_contact_with_highest_priority( account_source, jid_source) # Get destination group grp_dest = None if type_dest == 'group': grp_dest = model[iter_dest][Column.JID] elif type_dest in ('contact', 'agent'): it = iter_dest while model[it][Column.TYPE] != 'group': it = model.iter_parent(it) grp_dest = model[it][Column.JID] if grp_dest in helpers.special_groups: return if jid_source == jid_dest: if grp_source == grp_dest and account_source == account_dest: # Drop on self return # contact drop somewhere in or on a foreign account if (type_dest == 'account' or not self.regroup) and \ account_source != account_dest: # add to account in specified group AddNewContactWindow(account=account_dest, jid=jid_source, user_nick=c_source.name, group=grp_dest) return # we may not add contacts from special_groups if grp_source in helpers.special_groups: return # Is the contact we drag a meta contact? accounts = (self.regroup and app.contacts.get_accounts()) or \ account_source is_big_brother = app.contacts.is_big_brother(account_source, jid_source, accounts) drop_in_middle_of_meta = False if type_dest == 'contact': if position == Gtk.TreeViewDropPosition.BEFORE and len(path_dest) == 4: drop_in_middle_of_meta = True if position == Gtk.TreeViewDropPosition.AFTER and (len(path_dest) == 4 or\ self.modelfilter.iter_has_child(iter_dest)): drop_in_middle_of_meta = True # Contact drop on group row or between two contacts that are # not metacontacts if (type_dest == 'group' or position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.AFTER)) and not drop_in_middle_of_meta: self.on_drop_in_group(None, account_source, c_source, grp_dest, is_big_brother, context, etime, grp_source) return # Contact drop on another contact, make meta contacts if position == Gtk.TreeViewDropPosition.INTO_OR_AFTER or \ position == Gtk.TreeViewDropPosition.INTO_OR_BEFORE or drop_in_middle_of_meta: c_dest = app.contacts.get_contact_with_highest_priority( account_dest, jid_dest) if not c_dest: # c_dest is None if jid_dest doesn't belong to account return menu = Gtk.Menu() #from and to are the names of contacts item = Gtk.MenuItem.new_with_label(_('Send %(from)s to %(to)s') % { 'from': c_source.get_shown_name(), 'to': c_dest.get_shown_name()}) item.set_use_underline(False) item.connect('activate', self.on_drop_rosterx, account_source, c_source, account_dest, c_dest, is_big_brother, context, etime) menu.append(item) dest_family = app.contacts.get_metacontacts_family(account_dest, c_dest.jid) source_family = app.contacts.get_metacontacts_family( account_source, c_source.jid) if dest_family == source_family and dest_family: item = Gtk.MenuItem.new_with_label( _('Make %s first contact') % ( c_source.get_shown_name())) item.set_use_underline(False) else: item = Gtk.MenuItem.new_with_label( _('Make %(contact1)s and %(contact2)s metacontacts') % { 'contact1': c_source.get_shown_name(), 'contact2': c_dest.get_shown_name()}) item.set_use_underline(False) item.connect('activate', self.on_drop_in_contact, account_source, c_source, account_dest, c_dest, is_big_brother, context, etime) menu.append(item) menu.attach_to_widget(self.tree, None) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() menu.popup_at_pointer(None) ################################################################################ ### Everything about images and icons.... ### Cleanup assigned to Jim++ :-) ################################################################################ def get_appropriate_state_images(self, jid, size='16', icon_name='online'): """ Check jid and return the appropriate state images dict for the demanded size. icon_name is taken into account when jid is from transport: transport iconset doesn't contain all icons, so we fall back to jabber one """ transport = app.get_transport_name_from_jid(jid) if transport and size in self.transports_state_images: if transport not in self.transports_state_images[size]: # we don't have iconset for this transport loaded yet. Let's do # it self.make_transport_state_images(transport) if transport in self.transports_state_images[size] and \ icon_name in self.transports_state_images[size][transport]: return self.transports_state_images[size][transport] return app.interface.jabber_state_images[size] def make_transport_state_images(self, transport): """ Initialize opened and closed 'transport' iconset dict """ if not app.config.get('use_transports_iconsets'): return folder = os.path.join(helpers.get_transport_path(transport), '32x32') self.transports_state_images['32'][transport] = \ gtkgui_helpers.load_iconset(folder, transport=True) folder = os.path.join(helpers.get_transport_path(transport), '16x16') self.transports_state_images['16'][transport] = \ gtkgui_helpers.load_iconset(folder, transport=True) pixo, pixc = gtkgui_helpers.load_icons_meta() self.transports_state_images['opened'][transport] = \ gtkgui_helpers.load_iconset(folder, pixo, transport=True) self.transports_state_images['closed'][transport] = \ gtkgui_helpers.load_iconset(folder, pixc, transport=True) def update_jabber_state_images(self): # Update the roster self.setup_and_draw_roster() # Update the status combobox self.status_combobox.queue_draw() # Update the systray if app.interface.systray_enabled: app.interface.systray.set_img() for win in app.interface.msg_win_mgr.windows(): for ctrl in win.controls(): ctrl.update_ui() win.redraw_tab(ctrl) self.update_status_combobox() def set_account_status_icon(self, account): status = app.connections[account].connected child_iterA = self._get_account_iter(account, self.model) if not child_iterA: return if not self.regroup: show = app.SHOW_LIST[status] else: # accounts merged show = helpers.get_global_show() self.model[child_iterA][Column.IMG] = app.interface.jabber_state_images[ '16'][show] ################################################################################ ### Style and theme related methods ################################################################################ def show_title(self): change_title_allowed = app.config.get('change_roster_title') if not change_title_allowed: return nb_unread = 0 for account in app.connections: # Count events in roster title only if we don't auto open them if not helpers.allow_popup_window(account): nb_unread += app.events.get_nb_events(['chat', 'normal', 'file-request', 'file-error', 'file-completed', 'file-request-error', 'file-send-error', 'file-stopped', 'printed_chat'], account) if app.config.get('one_message_window') == 'always_with_roster': # always_with_roster mode defers to the MessageWindow if not app.interface.msg_win_mgr.one_window_opened(): # No MessageWindow to defer to self.window.set_title('Gajim') gtkgui_helpers.set_unset_urgency_hint(self.window, nb_unread) return start = '' if nb_unread > 1: start = '[' + str(nb_unread) + '] ' elif nb_unread == 1: start = '* ' self.window.set_title(start + 'Gajim') gtkgui_helpers.set_unset_urgency_hint(self.window, nb_unread) def _style_changed(self, *args): self.change_roster_style(None) def _change_style(self, model, path, titer, option): if option is None or model[titer][Column.TYPE] == option: # We changed style for this type of row model[titer][Column.NAME] = model[titer][Column.NAME] def change_roster_style(self, option): self.model.foreach(self._change_style, option) for win in app.interface.msg_win_mgr.windows(): win.repaint_themed_widgets() def repaint_themed_widgets(self): """ Notify windows that contain themed widgets to repaint them """ for win in app.interface.msg_win_mgr.windows(): win.repaint_themed_widgets() for account in app.connections: for ctrl in list(app.interface.minimized_controls[account].values()): ctrl.repaint_themed_widgets() def _iconCellDataFunc(self, column, renderer, model, titer, data=None): """ When a row is added, set properties for icon renderer """ try: type_ = model[titer][Column.TYPE] except TypeError: return if type_ == 'account': self._set_account_row_background_color(renderer) renderer.set_property('xalign', 0) elif type_ == 'group': self._set_group_row_background_color(renderer) parent_iter = model.iter_parent(titer) if model[parent_iter][Column.TYPE] == 'group': renderer.set_property('xalign', 0.4) else: renderer.set_property('xalign', 0.2) elif type_: # prevent type_ = None, see http://trac.gajim.org/ticket/2534 if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append when at the moment we add the row return jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] self._set_contact_row_background_color(renderer, jid, account) parent_iter = model.iter_parent(titer) if model[parent_iter][Column.TYPE] == 'contact': renderer.set_property('xalign', 1) else: renderer.set_property('xalign', 0.6) renderer.set_property('width', 26) def _nameCellDataFunc(self, column, renderer, model, titer, data=None): """ When a row is added, set properties for name renderer """ try: type_ = model[titer][Column.TYPE] except TypeError: return if type_ == 'account': color = app.css_config.get_value('.gajim-account-row', StyleAttr.COLOR) renderer.set_property('foreground', color) desc = app.css_config.get_font('.gajim-account-row') renderer.set_property('font-desc', desc) renderer.set_property('xpad', 0) renderer.set_property('width', 3) self._set_account_row_background_color(renderer) elif type_ == 'group': color = app.css_config.get_value('.gajim-group-row', StyleAttr.COLOR) renderer.set_property('foreground', color) desc = app.css_config.get_font('.gajim-group-row') renderer.set_property('font-desc', desc) parent_iter = model.iter_parent(titer) if model[parent_iter][Column.TYPE] == 'group': renderer.set_property('xpad', 8) else: renderer.set_property('xpad', 4) self._set_group_row_background_color(renderer) elif type_: # prevent type_ = None, see http://trac.gajim.org/ticket/2534 if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append when at the moment we add the row return jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] color = None if type_ == 'groupchat': ctrl = app.interface.minimized_controls[account].get(jid, None) if ctrl and ctrl.attention_flag: color = app.css_config.get_value( '.state_muc_directed_msg_color', StyleAttr.COLOR) renderer.set_property('foreground', color) if not color: color = app.css_config.get_value('.gajim-contact-row', StyleAttr.COLOR) renderer.set_property('foreground', color) self._set_contact_row_background_color(renderer, jid, account) desc = app.css_config.get_font('.gajim-contact-row') renderer.set_property('font-desc', desc) parent_iter = model.iter_parent(titer) if model[parent_iter][Column.TYPE] == 'contact': renderer.set_property('xpad', 16) else: renderer.set_property('xpad', 12) def _fill_pep_pixbuf_renderer(self, column, renderer, model, titer, data=None): """ When a row is added, draw the respective pep icon """ try: type_ = model[titer][Column.TYPE] except TypeError: return # allocate space for the icon only if needed if not model[titer][data] or model[titer][data] == empty_pixbuf: renderer.set_property('visible', False) else: renderer.set_property('visible', True) if type_ == 'account': self._set_account_row_background_color(renderer) renderer.set_property('xalign', 1) elif type_: if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append at the moment we add the row return jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] self._set_contact_row_background_color(renderer, jid, account) def _fill_avatar_pixbuf_renderer(self, column, renderer, model, titer, data=None): """ When a row is added, set properties for avatar renderer """ try: type_ = model[titer][Column.TYPE] except TypeError: return if type_ in ('group', 'account'): renderer.set_property('visible', False) return image = model[titer][Column.AVATAR_IMG] if image is not None: surface = image.get_property('surface') renderer.set_property('surface', surface) # allocate space for the icon only if needed if model[titer][Column.AVATAR_IMG] or \ app.config.get('avatar_position_in_roster') == 'left': renderer.set_property('visible', True) if type_: # prevent type_ = None, see http://trac.gajim.org/ticket/2534 if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append at the moment we add the row return jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] self._set_contact_row_background_color(renderer, jid, account) else: renderer.set_property('visible', False) if model[titer][Column.AVATAR_IMG] is None and \ app.config.get('avatar_position_in_roster') != 'left': renderer.set_property('visible', False) renderer.set_property('width', AvatarSize.ROSTER) renderer.set_property('xalign', 0.5) def _fill_padlock_pixbuf_renderer(self, column, renderer, model, titer, data=None): """ When a row is added, set properties for padlock renderer """ try: type_ = model[titer][Column.TYPE] except TypeError: return # allocate space for the icon only if needed if type_ == 'account' and model[titer][Column.PADLOCK_PIXBUF]: renderer.set_property('visible', True) self._set_account_row_background_color(renderer) renderer.set_property('xalign', 1) # align pixbuf to the right else: renderer.set_property('visible', False) def _set_account_row_background_color(self, renderer): color = app.css_config.get_value('.gajim-account-row', StyleAttr.BACKGROUND) renderer.set_property('cell-background', color) def _set_contact_row_background_color(self, renderer, jid, account): if jid in app.newly_added[account]: renderer.set_property('cell-background', app.css_config.get_value( '.gajim-roster-connected', StyleAttr.BACKGROUND)) elif jid in app.to_be_removed[account]: renderer.set_property('cell-background', app.css_config.get_value( '.gajim-roster-disconnected', StyleAttr.BACKGROUND)) else: color = app.css_config.get_value('.gajim-contact-row', StyleAttr.BACKGROUND) renderer.set_property('cell-background', color) def _set_group_row_background_color(self, renderer): color = app.css_config.get_value('.gajim-group-row', 'background') renderer.set_property('cell-background', color) ################################################################################ ### Everything about building menus ### FIXME: We really need to make it simpler! 1465 lines are a few to much.... ################################################################################ def build_account_menu(self, account): # we have to create our own set of icons for the menu # using self.jabber_status_images is poopoo if not app.config.get_per('accounts', account, 'is_zeroconf'): xml = gtkgui_helpers.get_gtk_builder('account_context_menu.ui') account_context_menu = xml.get_object('account_context_menu') status_menuitem = xml.get_object('status_menuitem') join_group_chat_menuitem = xml.get_object( 'join_group_chat_menuitem') add_contact_menuitem = xml.get_object('add_contact_menuitem') service_discovery_menuitem = xml.get_object( 'service_discovery_menuitem') execute_command_menuitem = xml.get_object( 'execute_command_menuitem') edit_account_menuitem = xml.get_object('edit_account_menuitem') sub_menu = Gtk.Menu() status_menuitem.set_submenu(sub_menu) for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) con = app.connections[account] if show == 'invisible' and con.connected > 1 and \ not con.get_module('PrivacyLists').supported: item.set_sensitive(False) else: item.connect('activate', self.change_status, account, show) item = Gtk.SeparatorMenuItem.new() sub_menu.append(item) item = Gtk.MenuItem.new_with_mnemonic(_('_Change Status Message')) sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate, account) if app.connections[account].connected < 2: item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() sub_menu.append(item) uf_show = helpers.get_uf_show('offline', use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) item.connect('activate', self.change_status, account, 'offline') pep_menuitem = xml.get_object('pep_menuitem') if app.connections[account].get_module('PEP').supported: pep_submenu = Gtk.Menu() pep_menuitem.set_submenu(pep_submenu) item = Gtk.CheckMenuItem(_('Publish Tune')) pep_submenu.append(item) if sys.platform in ('win32', 'darwin'): item.set_sensitive(False) else: activ = app.config.get_per('accounts', account, 'publish_tune') item.set_active(activ) item.connect('toggled', self.on_publish_tune_toggled, account) item = Gtk.CheckMenuItem(_('Publish Location')) pep_submenu.append(item) if not app.is_installed('GEOCLUE'): item.set_sensitive(False) else: activ = app.config.get_per('accounts', account, 'publish_location') item.set_active(activ) item.connect('toggled', self.on_publish_location_toggled, account) pep_config = Gtk.MenuItem.new_with_label( _('Configure Services…')) item = Gtk.SeparatorMenuItem.new() pep_submenu.append(item) pep_config.set_sensitive(True) pep_submenu.append(pep_config) pep_config.connect('activate', self.on_pep_services_menuitem_activate, account) else: pep_menuitem.set_sensitive(False) edit_account_menuitem.connect('activate', self.on_edit_account, account) if app.connections[account].roster_supported: add_contact_menuitem.connect('activate', self.on_add_new_contact, account) else: add_contact_menuitem.set_sensitive(False) service_discovery_menuitem.connect('activate', self.on_service_disco_menuitem_activate, account) hostname = app.config.get_per('accounts', account, 'hostname') contact = app.contacts.create_contact(jid=hostname, account=account) # Fake contact execute_command_menuitem.connect('activate', self.on_execute_command, contact, account) gc_sub_menu = Gtk.Menu() # gc is always a submenu join_group_chat_menuitem.set_submenu(gc_sub_menu) self.add_bookmarks_list(gc_sub_menu, account) # make some items insensitive if account is offline if app.connections[account].connected < 2: for widget in (add_contact_menuitem, service_discovery_menuitem, join_group_chat_menuitem, execute_command_menuitem, pep_menuitem): widget.set_sensitive(False) else: xml = gtkgui_helpers.get_gtk_builder('zeroconf_context_menu.ui') account_context_menu = xml.get_object('zeroconf_context_menu') status_menuitem = xml.get_object('status_menuitem') zeroconf_properties_menuitem = xml.get_object( 'zeroconf_properties_menuitem') sub_menu = Gtk.Menu() status_menuitem.set_submenu(sub_menu) for show in ('online', 'away', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) item.connect('activate', self.change_status, account, show) item = Gtk.SeparatorMenuItem.new() sub_menu.append(item) item = Gtk.MenuItem.new_with_mnemonic(_('_Change Status Message')) sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate, account) if app.connections[account].connected < 2: item.set_sensitive(False) uf_show = helpers.get_uf_show('offline', use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) item.connect('activate', self.change_status, account, 'offline') zeroconf_properties_menuitem.connect('activate', self.on_edit_account, account) return account_context_menu def make_account_menu(self, event, titer): """ Make account's popup menu """ model = self.modelfilter account = model[titer][Column.ACCOUNT] if account != 'all': # not in merged mode menu = self.build_account_menu(account) else: menu = Gtk.Menu() accounts = [] # Put accounts in a list to sort them for account in app.connections: accounts.append(account) accounts.sort() for account in accounts: label = app.get_account_label(account) item = Gtk.MenuItem.new_with_label(label) account_menu = self.build_account_menu(account) item.set_submenu(account_menu) menu.append(item) event_button = gtkgui_helpers.get_possible_button_event(event) menu.attach_to_widget(self.tree, None) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() menu.popup(None, None, None, None, event_button, event.time) def make_group_menu(self, event, titer): """ Make group's popup menu """ model = self.modelfilter group = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] list_ = [] # list of (contact, account) tuples list_online = [] # list of (contact, account) tuples show_bookmarked = True group = model[titer][Column.JID] for jid in app.contacts.get_jid_list(account): contact = app.contacts.get_contact_with_highest_priority(account, jid) if group in contact.get_shown_groups(): if contact.show not in ('offline', 'error'): list_online.append((contact, account)) # Check that all contacts support direct NUC invite if not contact.supports(NS_CONFERENCE): show_bookmarked = False list_.append((contact, account)) menu = Gtk.Menu() # Make special context menu if group is Groupchats if group == _('Groupchats'): maximize_menuitem = Gtk.MenuItem.new_with_mnemonic(_( '_Maximize All')) maximize_menuitem.connect('activate', self.on_all_groupchat_maximized, list_) menu.append(maximize_menuitem) else: # Send Group Message send_group_message_item = Gtk.MenuItem.new_with_mnemonic( _('Send Group M_essage')) send_group_message_submenu = Gtk.Menu() send_group_message_item.set_submenu(send_group_message_submenu) menu.append(send_group_message_item) group_message_to_all_item = Gtk.MenuItem.new_with_label(_( 'To all users')) send_group_message_submenu.append(group_message_to_all_item) group_message_to_all_online_item = Gtk.MenuItem.new_with_label( _('To all online users')) send_group_message_submenu.append(group_message_to_all_online_item) group_message_to_all_online_item.connect('activate', self.on_send_single_message_menuitem_activate, account, list_online) group_message_to_all_item.connect('activate', self.on_send_single_message_menuitem_activate, account, list_) # Invite to if group != _('Transports'): invite_menuitem = Gtk.MenuItem.new_with_mnemonic( _('In_vite to')) gui_menu_builder.build_invite_submenu(invite_menuitem, list_online, show_bookmarked=show_bookmarked) menu.append(invite_menuitem) # Send Custom Status send_custom_status_menuitem = Gtk.MenuItem.new_with_mnemonic( _('Send Cus_tom Status')) if helpers.group_is_blocked(account, group): send_custom_status_menuitem.set_sensitive(False) status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): status_menuitem = Gtk.MenuItem.new_with_label( helpers.get_uf_show(s)) status_menuitem.connect('activate', self.on_send_custom_status, list_, s, group) status_menuitems.append(status_menuitem) menu.append(send_custom_status_menuitem) # there is no singlemessage and custom status for zeroconf if app.config.get_per('accounts', account, 'is_zeroconf'): send_custom_status_menuitem.set_sensitive(False) send_group_message_item.set_sensitive(False) if app.connections[account].connected < 2: send_group_message_item.set_sensitive(False) invite_menuitem.set_sensitive(False) send_custom_status_menuitem.set_sensitive(False) if not group in helpers.special_groups: item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Rename rename_item = Gtk.MenuItem.new_with_mnemonic(_('_Rename…')) menu.append(rename_item) rename_item.connect('activate', self.on_rename, 'group', group, account) # Block group is_blocked = False if self.regroup: for g_account in app.connections: if helpers.group_is_blocked(g_account, group): is_blocked = True else: if helpers.group_is_blocked(account, group): is_blocked = True if is_blocked and app.connections[account].get_module('PrivacyLists').supported: unblock_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Unblock')) unblock_menuitem.connect('activate', self.on_unblock, list_, group) menu.append(unblock_menuitem) else: block_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Block')) block_menuitem.connect('activate', self.on_block, list_, group) menu.append(block_menuitem) if not app.connections[account].get_module('PrivacyLists').supported: block_menuitem.set_sensitive(False) # Remove group remove_item = Gtk.MenuItem.new_with_mnemonic(_('Remo_ve')) menu.append(remove_item) remove_item.connect('activate', self.on_remove_group_item_activated, group, account) # unsensitive if account is not connected if app.connections[account].connected < 2: rename_item.set_sensitive(False) # General group cannot be changed if group == _('General'): rename_item.set_sensitive(False) remove_item.set_sensitive(False) event_button = gtkgui_helpers.get_possible_button_event(event) menu.attach_to_widget(self.tree, None) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() menu.popup(None, None, None, None, event_button, event.time) def make_contact_menu(self, event, titer): """ Make contact's popup menu """ model = self.modelfilter jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] contact = app.contacts.get_contact_with_highest_priority(account, jid) menu = gui_menu_builder.get_contact_menu(contact, account) event_button = gtkgui_helpers.get_possible_button_event(event) menu.attach_to_widget(self.tree, None) menu.popup(None, None, None, None, event_button, event.time) def make_multiple_contact_menu(self, event, iters): """ Make group's popup menu """ model = self.modelfilter list_ = [] # list of (jid, account) tuples one_account_offline = False is_blocked = True privacy_rules_supported = True for titer in iters: jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] if app.connections[account].connected < 2: one_account_offline = True if not app.connections[account].get_module('PrivacyLists').supported: privacy_rules_supported = False contact = app.contacts.get_contact_with_highest_priority(account, jid) if not helpers.jid_is_blocked(account, jid): is_blocked = False list_.append((contact, account)) menu = Gtk.Menu() account = None for (contact, current_account) in list_: # check that we use the same account for every sender if account is not None and account != current_account: account = None break account = current_account show_bookmarked = True for (contact, current_account) in list_: # Check that all contacts support direct NUC invite if not contact.supports(NS_CONFERENCE): show_bookmarked = False break if account is not None: send_group_message_item = Gtk.MenuItem.new_with_mnemonic( _('Send Group M_essage')) menu.append(send_group_message_item) send_group_message_item.connect('activate', self.on_send_single_message_menuitem_activate, account, list_) # Invite to Groupchat invite_item = Gtk.MenuItem.new_with_mnemonic(_('In_vite to')) gui_menu_builder.build_invite_submenu(invite_item, list_, show_bookmarked=show_bookmarked) menu.append(invite_item) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Manage Transport submenu item = Gtk.MenuItem.new_with_mnemonic(_('_Manage Contacts')) manage_contacts_submenu = Gtk.Menu() item.set_submenu(manage_contacts_submenu) menu.append(item) # Edit Groups edit_groups_item = Gtk.MenuItem.new_with_mnemonic(_('Edit _Groups…')) manage_contacts_submenu.append(edit_groups_item) edit_groups_item.connect('activate', self.on_edit_groups, list_) item = Gtk.SeparatorMenuItem.new() # separator manage_contacts_submenu.append(item) # Block if is_blocked and privacy_rules_supported: unblock_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Unblock')) unblock_menuitem.connect('activate', self.on_unblock, list_) manage_contacts_submenu.append(unblock_menuitem) else: block_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Block')) block_menuitem.connect('activate', self.on_block, list_) manage_contacts_submenu.append(block_menuitem) if not privacy_rules_supported: block_menuitem.set_sensitive(False) # Remove remove_item = Gtk.MenuItem.new_with_mnemonic(_('_Remove')) manage_contacts_submenu.append(remove_item) remove_item.connect('activate', self.on_req_usub, list_) # unsensitive remove if one account is not connected if one_account_offline: remove_item.set_sensitive(False) event_button = gtkgui_helpers.get_possible_button_event(event) menu.attach_to_widget(self.tree, None) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() menu.popup(None, None, None, None, event_button, event.time) def make_transport_menu(self, event, titer): """ Make transport's popup menu """ model = self.modelfilter jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] contact = app.contacts.get_contact_with_highest_priority(account, jid) menu = gui_menu_builder.get_transport_menu(contact, account) event_button = gtkgui_helpers.get_possible_button_event(event) menu.attach_to_widget(self.tree, None) menu.popup(None, None, None, None, event_button, event.time) def make_groupchat_menu(self, event, titer): model = self.modelfilter jid = model[titer][Column.JID] account = model[titer][Column.ACCOUNT] contact = app.contacts.get_contact_with_highest_priority(account, jid) menu = Gtk.Menu() if jid in app.interface.minimized_controls[account]: maximize_menuitem = Gtk.MenuItem.new_with_mnemonic(_( '_Maximize')) maximize_menuitem.connect('activate', self.on_groupchat_maximized, \ jid, account) menu.append(maximize_menuitem) if not app.gc_connected[account].get(jid, False): connect_menuitem = Gtk.MenuItem.new_with_mnemonic(_( '_Reconnect')) connect_menuitem.connect('activate', self.on_reconnect, jid, account) menu.append(connect_menuitem) disconnect_menuitem = Gtk.MenuItem.new_with_mnemonic(_( '_Disconnect')) disconnect_menuitem.connect('activate', self.on_disconnect, jid, account) menu.append(disconnect_menuitem) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) adhoc_menuitem = Gtk.MenuItem.new_with_mnemonic(_('Execute command')) adhoc_menuitem.connect('activate', self.on_execute_command, contact, account) menu.append(adhoc_menuitem) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) history_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_History')) history_menuitem.connect('activate', self.on_history, contact, account) menu.append(history_menuitem) event_button = gtkgui_helpers.get_possible_button_event(event) menu.attach_to_widget(self.tree, None) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() menu.popup(None, None, None, None, event_button, event.time) def get_and_connect_advanced_menuitem_menu(self, account): """ Add FOR ACCOUNT options """ xml = gtkgui_helpers.get_gtk_builder('advanced_menuitem_menu.ui') advanced_menuitem_menu = xml.get_object('advanced_menuitem_menu') xml_console_menuitem = xml.get_object('xml_console_menuitem') archiving_preferences_menuitem = xml.get_object( 'archiving_preferences_menuitem') privacy_lists_menuitem = xml.get_object('privacy_lists_menuitem') administrator_menuitem = xml.get_object('administrator_menuitem') send_server_message_menuitem = xml.get_object( 'send_server_message_menuitem') set_motd_menuitem = xml.get_object('set_motd_menuitem') update_motd_menuitem = xml.get_object('update_motd_menuitem') delete_motd_menuitem = xml.get_object('delete_motd_menuitem') xml_console_menuitem.connect('activate', self.on_xml_console_menuitem_activate, account) if app.connections[account]: if app.connections[account].get_module('PrivacyLists').supported: privacy_lists_menuitem.connect('activate', self.on_privacy_lists_menuitem_activate, account) else: privacy_lists_menuitem.set_sensitive(False) if app.connections[account].get_module('MAM').available: archiving_preferences_menuitem.connect( 'activate', self.on_archiving_preferences_menuitem_activate, account) else: archiving_preferences_menuitem.set_sensitive(False) if app.connections[account].is_zeroconf: administrator_menuitem.set_sensitive(False) send_server_message_menuitem.set_sensitive(False) set_motd_menuitem.set_sensitive(False) update_motd_menuitem.set_sensitive(False) delete_motd_menuitem.set_sensitive(False) else: send_server_message_menuitem.connect('activate', self.on_send_server_message_menuitem_activate, account) set_motd_menuitem.connect('activate', self.on_set_motd_menuitem_activate, account) update_motd_menuitem.connect('activate', self.on_update_motd_menuitem_activate, account) delete_motd_menuitem.connect('activate', self.on_delete_motd_menuitem_activate, account) advanced_menuitem_menu.show_all() return advanced_menuitem_menu def add_history_manager_menuitem(self, menu): """ Add a separator and History Manager menuitem BELOW for account menuitems """ item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # History manager item = Gtk.MenuItem.new_with_mnemonic(_('History Manager')) menu.append(item) item.connect('activate', self.on_history_manager_menuitem_activate) def add_bookmarks_list(self, gc_sub_menu, account): """ Show join new group chat item and bookmarks list for an account """ item = Gtk.MenuItem.new_with_mnemonic(_('_Join New Group Chat')) item.connect('activate', self.on_join_gc_activate, account) gc_sub_menu.append(item) # User has at least one bookmark. con = app.connections[account] if con.get_module('Bookmarks').bookmarks: item = Gtk.SeparatorMenuItem.new() gc_sub_menu.append(item) bookmarks = con.get_module('Bookmarks').get_sorted_bookmarks( short_name=True) for jid, bookmark in bookmarks.items(): name = bookmark['name'] # Do not use underline. item = Gtk.MenuItem.new_with_label(name) item.set_use_underline(False) item.connect( 'activate', self.on_bookmark_menuitem_activate, account, jid, bookmark) gc_sub_menu.append(item) def show_appropriate_context_menu(self, event, iters): # iters must be all of the same type model = self.modelfilter type_ = model[iters[0]][Column.TYPE] for titer in iters[1:]: if model[titer][Column.TYPE] != type_: return if type_ == 'group' and len(iters) == 1: self.make_group_menu(event, iters[0]) if type_ == 'groupchat' and len(iters) == 1: self.make_groupchat_menu(event, iters[0]) elif type_ == 'agent' and len(iters) == 1: self.make_transport_menu(event, iters[0]) elif type_ in ('contact', 'self_contact') and len(iters) == 1: self.make_contact_menu(event, iters[0]) elif type_ == 'contact': self.make_multiple_contact_menu(event, iters) elif type_ == 'account' and len(iters) == 1: self.make_account_menu(event, iters[0]) def show_treeview_menu(self, event): try: model, list_of_paths = self.tree.get_selection().get_selected_rows() except TypeError: self.tree.get_selection().unselect_all() return if not list_of_paths: # no row is selected return if len(list_of_paths) > 1: iters = [] for path in list_of_paths: iters.append(model.get_iter(path)) else: path = list_of_paths[0] iters = [model.get_iter(path)] self.show_appropriate_context_menu(event, iters) return True def on_ctrl_j(self, accel_group, acceleratable, keyval, modifier): """ Bring up the conference join dialog, when CTRL+J accelerator is being activated """ # find a connected account: for account in app.connections: if account == 'Local': continue if app.account_is_connected(account): self.on_join_gc_activate(None, account) return True def fill_column(self, col): for rend in self.renderers_list: col.pack_start(rend[1], rend[2]) if rend[0] != 'avatar': col.add_attribute(rend[1], rend[3], rend[4]) col.set_cell_data_func(rend[1], rend[5], rend[6]) # set renderers properties for renderer in self.renderers_propertys: renderer.set_property(self.renderers_propertys[renderer][0], self.renderers_propertys[renderer][1]) def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): try: row = widget.get_path_at_pos(x_pos, y_pos)[0] except TypeError: return False if not row: return False iter_ = None try: model = widget.get_model() iter_ = model.get_iter(row) except Exception: return False typ = model[iter_][Column.TYPE] account = model[iter_][Column.ACCOUNT] jid = model[iter_][Column.JID] connected_contacts = [] if typ in ('contact', 'self_contact'): contacts = app.contacts.get_contacts(account, jid) for c in contacts: if c.show not in ('offline', 'error'): connected_contacts.append(c) if not connected_contacts: # no connected contacts, show the offline one connected_contacts = contacts elif typ == 'groupchat': connected_contacts = app.contacts.get_contacts(account, jid) elif typ != 'account': return False if self.current_tooltip != row: # If the row changes we hide the current tooltip self.current_tooltip = row return False tooltip = widget.get_tooltip_window() if tooltip.row == row: # We already populated the window with the row data return True tooltip.row = row tooltip.populate(connected_contacts, account, typ) return True def add_actions(self): action = Gio.SimpleAction.new_stateful( "show-roster", None, GLib.Variant.new_boolean( not self.xml.get_object('roster_vbox2').get_no_show_all())) action.connect("change-state", self.on_show_roster_action) self.window.add_action(action) action = Gio.SimpleAction.new_stateful( "show-offline", None, GLib.Variant.new_boolean(app.config.get('showoffline'))) action.connect("change-state", self.on_show_offline_contacts_action) self.window.add_action(action) action = Gio.SimpleAction.new_stateful( "show-active", None, GLib.Variant.new_boolean( app.config.get('show_only_chat_and_online'))) action.connect("change-state", self.on_show_active_contacts_action) self.window.add_action(action) action = Gio.SimpleAction.new_stateful( "show-transports", None, GLib.Variant.new_boolean(app.config.get('show_transports_group'))) action.connect("change-state", self.on_show_transports_action) self.window.add_action(action) ################################################################################ ### ################################################################################ def __init__(self, application): self.application = application self.filtering = False self.starting = False self.starting_filtering = False # Number of renderers plugins added self.nb_ext_renderers = 0 # When we quit, rememver if we already saved config once self.save_done = False # [icon, name, type, jid, account, editable, mood_pixbuf, # activity_pixbuf, tune_pixbuf, location_pixbuf, avatar_img, # padlock_pixbuf, visible] self.columns = [Gtk.Image, str, str, str, str, GdkPixbuf.Pixbuf, GdkPixbuf.Pixbuf, GdkPixbuf.Pixbuf, GdkPixbuf.Pixbuf, Gtk.Image, str, bool] self.xml = gtkgui_helpers.get_gtk_builder('roster_window.ui') self.window = self.xml.get_object('roster_window') application.add_window(self.window) self.add_actions() self.hpaned = self.xml.get_object('roster_hpaned') app.interface.msg_win_mgr = MessageWindowMgr(self.window, self.hpaned) app.interface.msg_win_mgr.connect('window-delete', self.on_message_window_delete) self.advanced_menus = [] # We keep them to destroy them if app.config.get('roster_window_skip_taskbar'): self.window.set_property('skip-taskbar-hint', True) self.tree = self.xml.get_object('roster_treeview') sel = self.tree.get_selection() sel.set_mode(Gtk.SelectionMode.MULTIPLE) # sel.connect('changed', # self.on_treeview_selection_changed) self._iters = {} # for merged mode self._iters['MERGED'] = {'account': None, 'groups': {}} # holds a list of (jid, account) tuples self._last_selected_contact = [] self.transports_state_images = {'16': {}, '32': {}, 'opened': {}, 'closed': {}} self.last_save_dir = None self.editing_path = None # path of row with cell in edit mode self.add_new_contact_handler_id = False self.service_disco_handler_id = False self.new_chat_menuitem_handler_id = False self.single_message_menuitem_handler_id = False self.profile_avatar_menuitem_handler_id = False #FIXME: When list_accel_closures will be wrapped in pygtk # no need of this variable self.have_new_chat_accel = False # Is the "Ctrl+N" shown ? self.regroup = app.config.get('mergeaccounts') self.clicked_path = None # Used remember on which row we clicked if len(app.connections) < 2: # Do not merge accounts if only one exists self.regroup = False gtkgui_helpers.resize_window(self.window, app.config.get('roster_width'), app.config.get('roster_height')) restore_roster_position(self.window) self.popups_notification_height = 0 self.popup_notification_windows = [] # Remove contact from roster when last event opened # { (contact, account): { backend: boolean } self.contacts_to_be_removed = {} app.events.event_removed_subscribe(self.on_event_removed) # when this value become 0 we quit main application. If it's more than 0 # it means we are waiting for this number of accounts to disconnect # before quitting self.quit_on_next_offline = -1 # groups to draw next time we draw groups. self.groups_to_draw = {} # accounts to draw next time we draw accounts. self.accounts_to_draw = [] # StatusComboBox self.status_combobox = self.xml.get_object('status_combobox') pixbuf_renderer, text_renderer = self.status_combobox.get_cells() self.status_combobox.set_cell_data_func( pixbuf_renderer, self._status_cell_data_func) self.status_combobox.set_cell_data_func( text_renderer, self._status_cell_data_func) self.status_combobox.set_row_separator_func(self._iter_is_separator) self.status_combobox.set_active(9) # holds index to previously selected item so if # "change status message..." is selected we can fallback to previously # selected item and not stay with that item selected self.previous_status_combobox_active = 9 # Enable/Disable checkboxes at start if app.config.get('showoffline'): self.window.lookup_action('show-active').set_enabled(False) if app.config.get('show_only_chat_and_online'): self.window.lookup_action('show-offline').set_enabled(False) if self.hpaned.get_child2() is None: self.window.lookup_action('show-roster').set_enabled(False) # columns col = Gtk.TreeViewColumn() # list of renderers with attributes / properties in the form: # (name, renderer_object, expand?, attribute_name, attribute_value, # cell_data_func, func_arg) self.renderers_list = [] self.renderers_propertys = {} self._pep_type_to_model_column = {'mood': Column.MOOD_PIXBUF, 'activity': Column.ACTIVITY_PIXBUF, 'tune': Column.TUNE_PIXBUF, 'geoloc': Column.LOCATION_PIXBUF} renderer_text = Gtk.CellRendererText() self.renderers_propertys[renderer_text] = ('ellipsize', Pango.EllipsizeMode.END) def add_avatar_renderer(): self.renderers_list.append(('avatar', Gtk.CellRendererPixbuf(), False, None, Column.AVATAR_IMG, self._fill_avatar_pixbuf_renderer, None)) if app.config.get('avatar_position_in_roster') == 'left': add_avatar_renderer() self.renderers_list += ( ('icon', cell_renderer_image.CellRendererImage(0, 0), False, 'image', Column.IMG, self._iconCellDataFunc, None), ('name', renderer_text, True, 'markup', Column.NAME, self._nameCellDataFunc, None), ('mood', Gtk.CellRendererPixbuf(), False, 'pixbuf', Column.MOOD_PIXBUF, self._fill_pep_pixbuf_renderer, Column.MOOD_PIXBUF), ('activity', Gtk.CellRendererPixbuf(), False, 'pixbuf', Column.ACTIVITY_PIXBUF, self._fill_pep_pixbuf_renderer, Column.ACTIVITY_PIXBUF), ('tune', Gtk.CellRendererPixbuf(), False, 'pixbuf', Column.TUNE_PIXBUF, self._fill_pep_pixbuf_renderer, Column.TUNE_PIXBUF), ('geoloc', Gtk.CellRendererPixbuf(), False, 'pixbuf', Column.LOCATION_PIXBUF, self._fill_pep_pixbuf_renderer, Column.LOCATION_PIXBUF)) if app.config.get('avatar_position_in_roster') == 'right': add_avatar_renderer() self.renderers_list.append(('padlock', Gtk.CellRendererPixbuf(), False, 'icon_name', Column.PADLOCK_PIXBUF, self._fill_padlock_pixbuf_renderer, None)) # fill and append column self.fill_column(col) self.tree.append_column(col) # do not show gtk arrows workaround col = Gtk.TreeViewColumn() render_pixbuf = Gtk.CellRendererPixbuf() col.pack_start(render_pixbuf, False) self.tree.append_column(col) col.set_visible(False) self.tree.set_expander_column(col) # signals self.TARGET_TYPE_URI_LIST = 80 self.tree.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE | \ Gdk.DragAction.COPY) self.tree.drag_source_add_text_targets() self.tree.enable_model_drag_dest([], Gdk.DragAction.DEFAULT) dst_targets = Gtk.TargetList.new([]) dst_targets.add_text_targets(0) dst_targets.add_uri_targets(self.TARGET_TYPE_URI_LIST) self.tree.drag_dest_set_target_list(dst_targets) self.tree.connect('drag-begin', self.drag_begin) self.tree.connect('drag-end', self.drag_end) self.tree.connect('drag-drop', self.drag_drop) self.tree.connect('drag-data-get', self.drag_data_get_data) self.tree.connect('drag-data-received', self.drag_data_received_data) self.dragging = False self.xml.connect_signals(self) self.combobox_callback_active = True self.collapsed_rows = app.config.get('collapsed_rows').split('\t') self.tree.set_has_tooltip(True) self.tree.set_tooltip_window(tooltips.RosterTooltip(self.window)) self.current_tooltip = None self.tree.connect('query-tooltip', self.query_tooltip) # Workaround: For strange reasons signal is behaving like row-changed self._toggeling_row = False self.setup_and_draw_roster() if app.config.get('show_roster_on_startup') == 'always': self.window.show_all() elif app.config.get('show_roster_on_startup') == 'never': if app.config.get('trayicon') != 'always': # Without trayicon, user should see the roster! self.window.show_all() app.config.set('last_roster_visible', True) else: if app.config.get('last_roster_visible') or \ app.config.get('trayicon') != 'always': self.window.show_all() self.scale_factor = self.window.get_scale_factor() if not app.config.get_per('accounts') or \ app.config.get_per('accounts') == ['Local'] and not \ app.config.get_per('accounts', 'Local', 'active'): # if we have no account configured or only Local account but not enabled def _open_wizard(): app.interface.instances['account_creation_wizard'] = \ AccountCreationWizard() # Open wizard only after roster is created, so we can make it # transient for the roster window GLib.idle_add(_open_wizard) # Setting CTRL+J to be the shortcut for bringing up the dialog to join a # conference. accel_group = Gtk.accel_groups_from_object(self.window)[0] accel_group.connect(Gdk.KEY_j, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.MASK, self.on_ctrl_j) # Setting CTRL+S to be the shortcut to change status message accel_group = Gtk.AccelGroup() keyval, mod = Gtk.accelerator_parse('s') accel_group.connect(keyval, mod, Gtk.AccelFlags.VISIBLE, self.accel_group_func) # Setting CTRL+k to focus rfilter_entry keyval, mod = Gtk.accelerator_parse('k') accel_group.connect(keyval, mod, Gtk.AccelFlags.VISIBLE, self.accel_group_func) self.window.add_accel_group(accel_group) # Setting the search stuff self.rfilter_entry = self.xml.get_object('rfilter_entry') self.rfilter_string = '' self.rfilter_enabled = False self.rfilter_entry.connect('key-press-event', self.on_rfilter_entry_key_press_event) app.ged.register_event_handler('presence-received', ged.GUI1, self._nec_presence_received) # presence has to be fully handled so that contact is added to occupant # list before roster can be correctly updated app.ged.register_event_handler('gc-presence-received', ged.GUI2, self._nec_gc_presence_received) app.ged.register_event_handler('roster-received', ged.GUI1, self._nec_roster_received) app.ged.register_event_handler('anonymous-auth', ged.GUI1, self._nec_anonymous_auth) app.ged.register_event_handler('our-show', ged.GUI2, self._nec_our_show) app.ged.register_event_handler('connection-type', ged.GUI1, self._nec_connection_type) app.ged.register_event_handler('agent-removed', ged.GUI1, self._nec_agent_removed) app.ged.register_event_handler('pep-received', ged.GUI1, self._nec_pep_received) app.ged.register_event_handler('update-roster-avatar', ged.GUI1, self._nec_update_avatar) app.ged.register_event_handler('update-room-avatar', ged.GUI1, self._nec_update_avatar) app.ged.register_event_handler('gc-subject-received', ged.GUI1, self._nec_gc_subject_received) app.ged.register_event_handler('metacontacts-received', ged.GUI2, self._nec_metacontacts_received) app.ged.register_event_handler('signed-in', ged.GUI1, self._nec_signed_in) app.ged.register_event_handler('decrypted-message-received', ged.GUI2, self._nec_decrypted_message_received) app.ged.register_event_handler('blocking', ged.GUI1, self._nec_blocking) app.ged.register_event_handler('style-changed', ged.GUI1, self._style_changed) gajim-gajim-1.1.3/gajim/search_window.py000066400000000000000000000222121345766322700202030ustar00rootroot00000000000000# Copyright (C) 2007 Stephan Erb # Copyright (C) 2007-2014 Yann Leboulanger # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import GLib from gi.repository import Gtk from gi.repository import Gdk from gajim.common import app from gajim.common import ged from gajim.common.modules import dataforms from gajim.common.i18n import _ from gajim import gtkgui_helpers from gajim import vcard from gajim import config from gajim import dataforms_widget from gajim.gtk.add_contact import AddNewContactWindow class SearchWindow: def __init__(self, account, jid): """ Create new window """ # an account object self.account = account self.jid = jid # retrieving widgets from xml self.xml = gtkgui_helpers.get_gtk_builder('search_window.ui') self.window = self.xml.get_object('search_window') for name in ('label', 'progressbar', 'search_vbox', 'search_button', 'add_contact_button', 'information_button'): self.__dict__[name] = self.xml.get_object(name) self.search_button.set_sensitive(False) # displaying the window self.xml.connect_signals(self) self.window.show_all() self.request_form() self.pulse_id = GLib.timeout_add(80, self.pulse_callback) self.is_form = None # Is there a jid column in results ? if -1: no, else column number self.jid_column = -1 app.ged.register_event_handler('search-form-received', ged.GUI1, self._nec_search_form_received) app.ged.register_event_handler('search-result-received', ged.GUI1, self._nec_search_result_received) def request_form(self): con = app.connections[self.account] con.get_module('Search').request_search_fields(self.jid) def pulse_callback(self): self.progressbar.pulse() return True def on_search_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def on_search_window_destroy(self, widget): if self.pulse_id: GLib.source_remove(self.pulse_id) del app.interface.instances[self.account]['search'][self.jid] app.ged.remove_event_handler('search-form-received', ged.GUI1, self._nec_search_form_received) app.ged.remove_event_handler('search-result-received', ged.GUI1, self._nec_search_result_received) def on_close_button_clicked(self, button): self.window.destroy() def on_search_button_clicked(self, button): con = app.connections[self.account] if self.is_form: self.data_form_widget.data_form.type_ = 'submit' con.get_module('Search').send_search_form( self.jid, self.data_form_widget.data_form.get_purged(), True) else: infos = self.data_form_widget.get_infos() if 'instructions' in infos: del infos['instructions'] con.get_module('Search').send_search_form(self.jid, infos, False) self.search_vbox.remove(self.data_form_widget) self.progressbar.show() self.label.set_text(_('Waiting for results')) self.label.show() self.pulse_id = GLib.timeout_add(80, self.pulse_callback) self.search_button.hide() def on_add_contact_button_clicked(self, widget): (model, iter_) = self.result_treeview.get_selection().get_selected() if not iter_: return jid = model[iter_][self.jid_column] AddNewContactWindow(self.account, jid) def on_information_button_clicked(self, widget): (model, iter_) = self.result_treeview.get_selection().get_selected() if not iter_: return jid = model[iter_][self.jid_column] if jid in app.interface.instances[self.account]['infos']: app.interface.instances[self.account]['infos'][jid].window.present() else: contact = app.contacts.create_contact(jid=jid, account=self.account) app.interface.instances[self.account]['infos'][jid] = \ vcard.VcardWindow(contact, self.account) def _nec_search_form_received(self, obj): if self.pulse_id: GLib.source_remove(self.pulse_id) self.progressbar.hide() self.label.hide() if obj.is_dataform: self.is_form = True self.data_form_widget = dataforms_widget.DataFormWidget() self.dataform = dataforms.extend_form(node=obj.data) self.data_form_widget.set_sensitive(True) try: self.data_form_widget.data_form = self.dataform except dataforms.Error: self.label.set_text(_('Error in received dataform')) self.label.show() return if self.data_form_widget.title: self.window.set_title('%s - Search - Gajim' % \ self.data_form_widget.title) else: self.is_form = False self.data_form_widget = config.FakeDataForm(obj.data) self.data_form_widget.show_all() self.search_vbox.pack_start(self.data_form_widget, True, True, 0) self.search_button.set_sensitive(True) def on_result_treeview_cursor_changed(self, treeview): if self.jid_column == -1: return (model, iter_) = treeview.get_selection().get_selected() if not iter_: return if model[iter_][self.jid_column]: self.add_contact_button.set_sensitive(True) self.information_button.set_sensitive(True) else: self.add_contact_button.set_sensitive(False) self.information_button.set_sensitive(False) def _nec_search_result_received(self, obj): if self.pulse_id: GLib.source_remove(self.pulse_id) self.progressbar.hide() self.label.hide() if not obj.is_dataform: if not obj.data: self.label.set_text(_('No result')) self.label.show() return # We suppose all items have the same fields sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.result_treeview = Gtk.TreeView() self.result_treeview.connect('cursor-changed', self.on_result_treeview_cursor_changed) sw.add(self.result_treeview) # Create model fieldtypes = [str]*len(obj.data[0]) model = Gtk.ListStore(*fieldtypes) # Copy data to model for item in obj.data: model.append(item.values()) # Create columns counter = 0 for field in obj.data[0].keys(): self.result_treeview.append_column(Gtk.TreeViewColumn(field, Gtk.CellRendererText(), text=counter)) if field == 'jid': self.jid_column = counter counter += 1 self.result_treeview.set_model(model) sw.show_all() self.search_vbox.pack_start(sw, True, True, 0) if self.jid_column > -1: self.add_contact_button.show() self.information_button.show() return self.dataform = dataforms.extend_form(node=obj.data) if not self.dataform.items: # No result self.label.set_text(_('No result')) self.label.show() return self.data_form_widget.set_sensitive(True) try: self.data_form_widget.data_form = self.dataform except dataforms.Error: self.label.set_text(_('Error in received dataform')) self.label.show() return self.result_treeview = self.data_form_widget.records_treeview selection = self.result_treeview.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) self.result_treeview.connect('cursor-changed', self.on_result_treeview_cursor_changed) counter = 0 for field in self.dataform.reported.iter_fields(): if field.var == 'jid': self.jid_column = counter break counter += 1 self.search_vbox.pack_start(self.data_form_widget, True, True, 0) self.data_form_widget.show() if self.jid_column > -1: self.add_contact_button.show() self.information_button.show() if self.data_form_widget.title: self.window.set_title('%s - Search - Gajim' % \ self.data_form_widget.title) gajim-gajim-1.1.3/gajim/session.py000066400000000000000000000341721345766322700170420ustar00rootroot00000000000000# Copyright (C) 2008-2014 Yann Leboulanger # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import string import random import itertools from gajim import notify from gajim.common import helpers from gajim.common import events from gajim.common import app from gajim.common import contacts from gajim.common import ged from gajim.common.helpers import AdditionalDataDict from gajim.common.const import KindConstant from gajim.gtk.single_message import SingleMessageWindow class ChatControlSession: def __init__(self, conn, jid, thread_id, type_='chat'): self.conn = conn self.jid = jid self.type_ = type_ self.resource = jid.getResource() self.control = None if thread_id: self.received_thread_id = True self.thread_id = thread_id else: self.received_thread_id = False if type_ == 'normal': self.thread_id = None else: self.thread_id = self.generate_thread_id() self.loggable = True self.last_send = 0 self.last_receive = 0 app.ged.register_event_handler('decrypted-message-received', ged.PREGUI, self._nec_decrypted_message_received) def generate_thread_id(self): return ''.join( [f(string.ascii_letters) for f in itertools.repeat( random.choice, 32)] ) def is_loggable(self): return app.config.should_log(self.conn.name, self.jid.getStripped()) def get_to(self): to = str(self.jid) return app.get_jid_without_resource(to) + '/' + self.resource def _nec_decrypted_message_received(self, obj): """ Dispatch a received stanza """ if obj.session != self: return if obj.muc_pm: contact = app.contacts.get_gc_contact( self.conn.name, obj.jid, obj.resource) else: contact = app.contacts.get_contact( self.conn.name, obj.jid, obj.resource) if self.resource != obj.resource: self.resource = obj.resource if self.control: if isinstance(contact, contacts.GC_Contact): self.control.gc_contact = contact self.control.contact = contact.as_contact() else: self.control.contact = contact if self.control.resource: self.control.change_resource(self.resource) if obj.mtype == 'chat': if not obj.msgtxt: return log_type = KindConstant.CHAT_MSG_RECV if obj.forwarded and obj.sent: log_type = KindConstant.CHAT_MSG_SENT else: log_type = KindConstant.SINGLE_MSG_RECV if obj.forwarded and obj.sent: log_type = KindConstant.SINGLE_MSG_SENT treat_as = app.config.get('treat_incoming_messages') if treat_as: obj.mtype = treat_as pm = False if obj.muc_pm or (obj.gc_control and obj.resource): # It's a Private message pm = True obj.mtype = 'pm' if self.is_loggable() and obj.msgtxt: if obj.xhtml and app.config.get('log_xhtml_messages'): msg_to_log = obj.xhtml else: msg_to_log = obj.msgtxt jid = obj.fjid if not pm: jid = obj.jid obj.msg_log_id = app.logger.insert_into_logs( self.conn.name, jid, obj.timestamp, log_type, message=msg_to_log, subject=obj.subject, additional_data=obj.additional_data, stanza_id=obj.unique_id) self.conn.get_module('MAM').save_archive_id( None, obj.stanza_id, obj.timestamp) if obj.muc_pm and not obj.gc_control: # This is a carbon of a PM from a MUC we are not currently # joined. We log it silently without notification. return True if not obj.msgtxt: # empty message text return True if app.config.get_per('accounts', self.conn.name, 'ignore_unknown_contacts') and not app.contacts.get_contacts( self.conn.name, obj.jid) and not pm: return True if not self.control: ctrl = app.interface.msg_win_mgr.search_control(obj.jid, obj.conn.name, obj.resource) if ctrl: self.control = ctrl self.control.set_session(self) if isinstance(contact, contacts.GC_Contact): self.control.gc_contact = contact self.control.contact = contact.as_contact() else: self.control.contact = contact if not pm: self.roster_message2(obj) def roster_message2(self, obj): """ Display the message or show notification in the roster """ contact = None jid = obj.jid resource = obj.resource fjid = jid # Try to catch the contact with correct resource if resource: fjid = jid + '/' + resource contact = app.contacts.get_contact(obj.conn.name, jid, resource) highest_contact = app.contacts.get_contact_with_highest_priority( obj.conn.name, jid) if not contact: # If there is another resource, it may be a message from an # invisible resource lcontact = app.contacts.get_contacts(obj.conn.name, jid) if (len(lcontact) > 1 or (lcontact and lcontact[0].resource and \ lcontact[0].show != 'offline')) and jid.find('@') > 0: contact = app.contacts.copy_contact(highest_contact) contact.resource = resource contact.priority = 0 contact.show = 'offline' contact.status = '' app.contacts.add_contact(obj.conn.name, contact) else: # Default to highest prio fjid = jid contact = highest_contact if not contact: # contact is not in roster contact = app.interface.roster.add_to_not_in_the_roster( obj.conn.name, jid, obj.user_nick) if not self.control: ctrl = app.interface.msg_win_mgr.search_control(obj.jid, obj.conn.name, obj.resource) if ctrl: self.control = ctrl self.control.set_session(self) else: fjid = jid obj.popup = helpers.allow_popup_window(self.conn.name) event_t = events.ChatEvent event_type = 'message_received' if obj.mtype == 'normal': event_t = events.NormalEvent event_type = 'single_message_received' if self.control and obj.mtype != 'normal': # We have a ChatControl open obj.show_in_roster = False obj.show_in_systray = False do_event = False elif obj.forwarded and obj.sent: # Its a Carbon Copied Message we sent obj.show_in_roster = False obj.show_in_systray = False unread_events = app.events.get_events( self.conn.name, fjid, types=['chat']) read_ids = [] for msg in unread_events: read_ids.append(msg.msg_log_id) app.logger.set_read_messages(read_ids) app.events.remove_events(self.conn.name, fjid, types=['chat']) do_event = False else: # Everything else obj.show_in_roster = notify.get_show_in_roster(event_type, self.conn.name, contact.jid, self) obj.show_in_systray = notify.get_show_in_systray(event_type, self.conn.name, contact.jid) if obj.mtype == 'normal' and obj.popup: do_event = False else: do_event = True if do_event: event = event_t(obj.msgtxt, obj.subject, obj.mtype, obj.timestamp, obj.encrypted, obj.resource, obj.msg_log_id, correct_id=(obj.id_, obj.correct_id), xhtml=obj.xhtml, session=self, form_node=obj.form_node, displaymarking=obj.displaymarking, sent_forwarded=obj.forwarded and obj.sent, show_in_roster=obj.show_in_roster, show_in_systray=obj.show_in_systray, additional_data=obj.additional_data) app.events.add_event(self.conn.name, fjid, event) def roster_message(self, jid, msg, tim, encrypted=False, msg_type='', subject=None, resource='', msg_log_id=None, user_nick='', xhtml=None, form_node=None, displaymarking=None, additional_data=None): """ Display the message or show notification in the roster """ contact = None fjid = jid if additional_data is None: additional_data = AdditionalDataDict() # Try to catch the contact with correct resource if resource: fjid = jid + '/' + resource contact = app.contacts.get_contact(self.conn.name, jid, resource) highest_contact = app.contacts.get_contact_with_highest_priority( self.conn.name, jid) if not contact: # If there is another resource, it may be a message from an invisible # resource lcontact = app.contacts.get_contacts(self.conn.name, jid) if (len(lcontact) > 1 or (lcontact and lcontact[0].resource and \ lcontact[0].show != 'offline')) and jid.find('@') > 0: contact = app.contacts.copy_contact(highest_contact) contact.resource = resource if resource: fjid = jid + '/' + resource contact.priority = 0 contact.show = 'offline' contact.status = '' app.contacts.add_contact(self.conn.name, contact) else: # Default to highest prio fjid = jid contact = highest_contact if not contact: # contact is not in roster contact = app.interface.roster.add_to_not_in_the_roster( self.conn.name, jid, user_nick) if not self.control: ctrl = app.interface.msg_win_mgr.get_control(fjid, self.conn.name) if ctrl: self.control = ctrl self.control.set_session(self) else: fjid = jid # Do we have a queue? no_queue = len(app.events.get_events(self.conn.name, fjid)) == 0 popup = helpers.allow_popup_window(self.conn.name) if msg_type == 'normal' and popup: # it's single message to be autopopuped SingleMessageWindow(self.conn.name, contact.jid, action='receive', from_whom=jid, subject=subject, message=msg, resource=resource, session=self, form_node=form_node) return # We print if window is opened and it's not a single message if self.control and msg_type != 'normal': typ = '' if msg_type == 'error': typ = 'error' self.control.print_conversation(msg, typ, tim=tim, encrypted=encrypted, subject=subject, xhtml=xhtml, displaymarking=displaymarking, additional_data=additional_data) if msg_log_id: app.logger.set_read_messages([msg_log_id]) return # We save it in a queue event_t = events.ChatEvent event_type = 'message_received' if msg_type == 'normal': event_t = events.NormalEvent event_type = 'single_message_received' show_in_roster = notify.get_show_in_roster(event_type, self.conn.name, contact.jid, self) show_in_systray = notify.get_show_in_systray(event_type, self.conn.name, contact.jid) event = event_t(msg, subject, msg_type, tim, encrypted, resource, msg_log_id, xhtml=xhtml, session=self, form_node=form_node, displaymarking=displaymarking, sent_forwarded=False, show_in_roster=show_in_roster, show_in_systray=show_in_systray, additional_data=additional_data) app.events.add_event(self.conn.name, fjid, event) if popup: if not self.control: self.control = app.interface.new_chat(contact, self.conn.name, session=self) if app.events.get_events(self.conn.name, fjid): self.control.read_queue() else: if no_queue: # We didn't have a queue: we change icons app.interface.roster.draw_contact(jid, self.conn.name) app.interface.roster.show_title() # we show the * or [n] # Select the big brother contact in roster, it's visible because it has # events. family = app.contacts.get_metacontacts_family(self.conn.name, jid) if family: _nearby_family, bb_jid, bb_account = \ app.contacts.get_nearby_family_and_big_brother(family, self.conn.name) else: bb_jid, bb_account = jid, self.conn.name app.interface.roster.select_contact(bb_jid, bb_account) gajim-gajim-1.1.3/gajim/statusicon.py000066400000000000000000000440261345766322700175520ustar00rootroot00000000000000# Copyright (C) 2006 Nikos Kouremenos # Copyright (C) 2006-2007 Jean-Marie Traissard # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Lukas Petrovicky # Julien Pivotto # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os from gi.repository import Gtk from gi.repository import Gdk from gajim import dialogs from gajim import tooltips from gajim import gtkgui_helpers from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.helpers import save_roster_position from gajim.gtk.util import restore_roster_position from gajim.gtk.single_message import SingleMessageWindow class StatusIcon: """ Class for the notification area icon """ def __init__(self): self.single_message_handler_id = None self.show_roster_handler_id = None self.new_chat_handler_id = None # click somewhere else does not popdown menu. workaround this. self.added_hide_menuitem = False self.status = 'offline' self.xml = gtkgui_helpers.get_gtk_builder('systray_context_menu.ui') self.systray_context_menu = self.xml.get_object('systray_context_menu') self.xml.connect_signals(self) self.popup_menus = [] self.status_icon = None self.tooltip = tooltips.NotificationAreaTooltip() def subscribe_events(self): """ Register listeners to the events class """ app.events.event_added_subscribe(self.on_event_added) app.events.event_removed_subscribe(self.on_event_removed) def unsubscribe_events(self): """ Unregister listeners to the events class """ app.events.event_added_unsubscribe(self.on_event_added) app.events.event_removed_unsubscribe(self.on_event_removed) def on_event_added(self, event): """ Called when an event is added to the event list """ if event.show_in_systray: self.set_img() def on_event_removed(self, event_list): """ Called when one or more events are removed from the event list """ self.set_img() def show_icon(self): if not self.status_icon: self.status_icon = Gtk.StatusIcon() self.status_icon.set_property('has-tooltip', True) self.status_icon.connect('activate', self.on_status_icon_left_clicked) self.status_icon.connect('popup-menu', self.on_status_icon_right_clicked) self.status_icon.connect('query-tooltip', self.on_status_icon_query_tooltip) self.status_icon.connect('size-changed', self.set_img) self.set_img() self.subscribe_events() def on_status_icon_right_clicked(self, widget, event_button, event_time): self.make_menu(event_button, event_time) def on_status_icon_query_tooltip(self, widget, x, y, keyboard_mode, tooltip): tooltip.set_custom(self.tooltip.get_tooltip()) return True def hide_icon(self): self.status_icon.set_visible(False) self.unsubscribe_events() def on_status_icon_left_clicked(self, widget): self.on_left_click() def on_status_icon_size_changed(self, statusicon, size): if size > 31: self.statusicon_size = '32' elif size > 23: self.statusicon_size = '24' else: self.statusicon_size = '16' if os.environ.get('KDE_FULL_SESSION') == 'true': # detect KDE session. see #5476 self.statusicon_size = '32' self.set_img() def set_img(self, *args): """ Apart from image, we also update tooltip text here """ if not app.interface.systray_enabled: return if app.config.get('trayicon') == 'always': self.status_icon.set_visible(True) if app.events.get_nb_systray_events(): self.status_icon.set_visible(True) icon_name = gtkgui_helpers.get_iconset_name_for('event') self.status_icon.set_from_icon_name(icon_name) return if app.config.get('trayicon') == 'on_event': self.status_icon.set_visible(False) icon_name = gtkgui_helpers.get_iconset_name_for(self.status) self.status_icon.set_from_icon_name(icon_name) def change_status(self, global_status): """ Set tray image to 'global_status' """ # change image and status, only if it is different if global_status is not None and self.status != global_status: self.status = global_status self.set_img() def start_chat(self, widget, account, jid): contact = app.contacts.get_first_contact_from_jid(account, jid) if app.interface.msg_win_mgr.has_window(jid, account): app.interface.msg_win_mgr.get_window(jid, account).set_active_tab( jid, account) elif contact: app.interface.new_chat(contact, account) app.interface.msg_win_mgr.get_window(jid, account).set_active_tab( jid, account) def on_single_message_menuitem_activate(self, widget, account): SingleMessageWindow(account, action='send') def on_new_chat(self, widget, account): app.app.activate_action('start-chat') def make_menu(self, event_button, event_time): """ Create chat with and new message (sub) menus/menuitems """ for m in self.popup_menus: m.destroy() chat_with_menuitem = self.xml.get_object('chat_with_menuitem') single_message_menuitem = self.xml.get_object( 'single_message_menuitem') status_menuitem = self.xml.get_object('status_menu') join_gc_menuitem = self.xml.get_object('join_gc_menuitem') sounds_mute_menuitem = self.xml.get_object('sounds_mute_menuitem') show_roster_menuitem = self.xml.get_object('show_roster_menuitem') if self.single_message_handler_id: single_message_menuitem.handler_disconnect( self.single_message_handler_id) self.single_message_handler_id = None if self.new_chat_handler_id: chat_with_menuitem.disconnect(self.new_chat_handler_id) self.new_chat_handler_id = None sub_menu = Gtk.Menu() self.popup_menus.append(sub_menu) status_menuitem.set_submenu(sub_menu) gc_sub_menu = Gtk.Menu() # gc is always a submenu join_gc_menuitem.set_submenu(gc_sub_menu) for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, show) item = Gtk.SeparatorMenuItem.new() sub_menu.append(item) item = Gtk.MenuItem.new_with_mnemonic(_('_Change Status Message…')) sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate) connected_accounts = app.get_number_of_connected_accounts() if connected_accounts < 1: item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() sub_menu.append(item) uf_show = helpers.get_uf_show('offline', use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, 'offline') iskey = connected_accounts > 0 and not (connected_accounts == 1 and app.zeroconf_is_connected()) chat_with_menuitem.set_sensitive(iskey) single_message_menuitem.set_sensitive(iskey) join_gc_menuitem.set_sensitive(iskey) accounts_list = sorted(app.contacts.get_accounts()) # items that get shown whether an account is zeroconf or not if connected_accounts > 1: # 2 or more connections? make submenus account_menu_for_chat_with = Gtk.Menu() chat_with_menuitem.set_submenu(account_menu_for_chat_with) self.popup_menus.append(account_menu_for_chat_with) for account in accounts_list: account_label = app.get_account_label(account) if app.account_is_connected(account): # for chat_with item = Gtk.MenuItem.new_with_label( _('using account %s') % account_label) account_menu_for_chat_with.append(item) item.connect('activate', self.on_new_chat, account) elif connected_accounts == 1: # one account # one account connected, no need to show 'as jid' for account in app.connections: if app.connections[account].connected > 1: # for start chat self.new_chat_handler_id = chat_with_menuitem.connect( 'activate', self.on_new_chat, account) break # No other connected account # menu items that don't apply to zeroconf connections if connected_accounts == 1 or (connected_accounts == 2 and \ app.zeroconf_is_connected()): # only one 'real' (non-zeroconf) account is connected, don't need # submenus for account in app.connections: if app.account_is_connected(account) and \ not app.config.get_per('accounts', account, 'is_zeroconf'): # for single message single_message_menuitem.set_submenu(None) self.single_message_handler_id = single_message_menuitem.\ connect('activate', self.on_single_message_menuitem_activate, account) # join gc app.interface.roster.add_bookmarks_list(gc_sub_menu, account) break # No other account connected else: # 2 or more 'real' accounts are connected, make submenus account_menu_for_single_message = Gtk.Menu() single_message_menuitem.set_submenu( account_menu_for_single_message) self.popup_menus.append(account_menu_for_single_message) for account in accounts_list: account_label = app.get_account_label(account) if app.connections[account].is_zeroconf or \ not app.account_is_connected(account): continue # for single message item = Gtk.MenuItem.new_with_label( _('using account %s') % account_label) item.connect('activate', self.on_single_message_menuitem_activate, account) account_menu_for_single_message.append(item) # join gc gc_item = Gtk.MenuItem.new_with_label( _('using account %s') % account_label) gc_sub_menu.append(gc_item) gc_menuitem_menu = Gtk.Menu() app.interface.roster.add_bookmarks_list(gc_menuitem_menu, account) gc_item.set_submenu(gc_menuitem_menu) gc_sub_menu.show_all() newitem = Gtk.SeparatorMenuItem.new() # separator gc_sub_menu.append(newitem) newitem = Gtk.MenuItem.new_with_mnemonic(_('_Manage Bookmarks…')) newitem.connect('activate', app.interface.roster.on_manage_bookmarks_menuitem_activate) newitem.set_sensitive(False) gc_sub_menu.append(newitem) for account in accounts_list: if app.account_supports_private_storage(account): newitem.set_sensitive(True) break sounds_mute_menuitem.set_active(not app.config.get('sounds_on')) win = app.interface.roster.window if self.show_roster_handler_id: show_roster_menuitem.handler_disconnect(self.show_roster_handler_id) if win.get_property('has-toplevel-focus'): show_roster_menuitem.get_children()[0].set_label(_('Hide _Roster')) self.show_roster_handler_id = show_roster_menuitem.connect( 'activate', self.on_hide_roster_menuitem_activate) else: show_roster_menuitem.get_children()[0].set_label(_('Show _Roster')) self.show_roster_handler_id = show_roster_menuitem.connect( 'activate', self.on_show_roster_menuitem_activate) if os.name == 'nt': if self.added_hide_menuitem is False: self.systray_context_menu.prepend(Gtk.SeparatorMenuItem.new()) item = Gtk.MenuItem.new_with_label( _('Hide this menu')) self.systray_context_menu.prepend(item) self.added_hide_menuitem = True self.systray_context_menu.show_all() self.systray_context_menu.popup(None, None, None, None, 0, event_time) def on_show_all_events_menuitem_activate(self, widget): events = app.events.get_systray_events() for account in events: for jid in events[account]: for event in events[account][jid]: app.interface.handle_event(account, jid, event.type_) def on_sounds_mute_menuitem_activate(self, widget): app.config.set('sounds_on', not widget.get_active()) def on_show_roster_menuitem_activate(self, widget): win = app.interface.roster.window win.present() def on_hide_roster_menuitem_activate(self, widget): win = app.interface.roster.window win.hide() def on_preferences_menuitem_activate(self, widget): from gajim.gtk.preferences import Preferences window = app.get_app_window(Preferences) if window is None: Preferences() else: window.present() def on_quit_menuitem_activate(self, widget): app.interface.roster.on_quit_request() def on_left_click(self): win = app.interface.roster.window if not app.events.get_systray_events(): # No pending events, so toggle visible/hidden for roster window if win.get_property('visible'): if win.get_property('has-toplevel-focus') or os.name == 'nt': save_roster_position(win) win.hide() # else we hide it from VD that was visible in else: win.show_all() restore_roster_position(win) if not app.config.get('roster_window_skip_taskbar'): win.set_property('skip-taskbar-hint', False) win.present_with_time(Gtk.get_current_event_time()) else: self.handle_first_event() def handle_first_event(self): account, jid, event = app.events.get_first_systray_event() if not event: return win = app.interface.roster.window if not win.get_property('visible'): # Needed if we are in one window mode restore_roster_position(win) app.interface.handle_event(account, jid, event.type_) def on_middle_click(self): """ Middle click raises window to have complete focus (fe. get kbd events) but if already raised, it hides it """ win = app.interface.roster.window if win.is_active(): # is it fully raised? (eg does it receive kbd events?) win.hide() else: win.present() def on_clicked(self, widget, event): self.on_tray_leave_notify_event(widget, None) if event.type_ != Gdk.EventType.BUTTON_PRESS: return if event.button == 1: # Left click self.on_left_click() elif event.button == 2: # middle click self.on_middle_click() elif event.button == 3: # right click self.make_menu(event.button, event.time) def on_show_menuitem_activate(self, widget, show): # we all add some fake (we cannot select those nor have them as show) # but this helps to align with roster's status_combobox index positions l = ['online', 'chat', 'away', 'xa', 'dnd', 'invisible', 'SEPARATOR', 'CHANGE_STATUS_MSG_MENUITEM', 'SEPARATOR', 'offline'] index = l.index(show) if not helpers.statuses_unified(): app.interface.roster.status_combobox.set_active(index + 2) return current = app.interface.roster.status_combobox.get_active() if index != current: app.interface.roster.status_combobox.set_active(index) def on_change_status_message_activate(self, widget): model = app.interface.roster.status_combobox.get_model() active = app.interface.roster.status_combobox.get_active() status = model[active][2] def on_response(message, pep_dict): if message is None: # None if user press Cancel return accounts = app.connections.keys() for acct in accounts: if not app.config.get_per('accounts', acct, 'sync_with_global_status'): continue show = app.SHOW_LIST[app.connections[acct].connected] app.interface.roster.send_status(acct, show, message) app.interface.roster.send_pep(acct, pep_dict) dlg = dialogs.ChangeStatusMessageDialog(on_response, status) dlg.dialog.present() gajim-gajim-1.1.3/gajim/tooltips.py000066400000000000000000000646621345766322700172430ustar00rootroot00000000000000# Copyright (C) 2005 Alex Mauer # Stéphan Kochen # Copyright (C) 2005-2006 Dimitur Kirov # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006 Travis Shirk # Stefan Bethge # Copyright (C) 2006-2007 Jean-Marie Traissard # Copyright (C) 2007 Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import time import logging from datetime import datetime from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gi.repository import Pango from gajim import gtkgui_helpers from gajim.common.const import AvatarSize from gajim.common import app from gajim.common import helpers from gajim.common.i18n import Q_ from gajim.common.i18n import _ log = logging.getLogger('gajim.tooltips') class StatusTable: """ Contains methods for creating status table. This is used in Roster and NotificationArea tooltips """ def __init__(self): self.current_row = 0 self.table = None self.text_label = None self.spacer_label = ' ' def create_table(self): self.table = Gtk.Grid() self.table.insert_column(0) self.table.set_property('column-spacing', 2) def add_text_row(self, text, col_inc=0): self.table.insert_row(self.current_row) self.text_label = Gtk.Label() self.text_label.set_line_wrap(True) self.text_label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) self.text_label.set_max_width_chars(35) self.text_label.set_halign(Gtk.Align.START) self.text_label.set_valign(Gtk.Align.START) self.text_label.set_selectable(False) self.text_label.set_markup(text) self.table.attach(self.text_label, 1 + col_inc, self.current_row, 3 - col_inc, 1) self.current_row += 1 def get_status_info(self, resource, priority, show, status): str_status = resource + ' (' + str(priority) + ')' if status: status = status.strip() if status != '': # reduce to 100 chars, 1 line status = helpers.reduce_chars_newlines(status, 100, 1) str_status = GLib.markup_escape_text(str_status) status = GLib.markup_escape_text(status) str_status += ' - ' + status + '' return str_status def add_status_row(self, file_path, show, str_status, show_lock=False, indent=True): """ Append a new row with status icon to the table """ self.table.insert_row(self.current_row) state_file = show.replace(' ', '_') files = [] files.append(os.path.join(file_path, state_file + '.png')) files.append(os.path.join(file_path, state_file + '.gif')) image = Gtk.Image() image.set_from_pixbuf(None) for f in files: if os.path.exists(f): image.set_from_file(f) break spacer = Gtk.Label(label=self.spacer_label) image.set_halign(Gtk.Align.START) image.set_valign(Gtk.Align.CENTER) if indent: self.table.attach(spacer, 1, self.current_row, 1, 1) self.table.attach(image, 2, self.current_row, 1, 1) status_label = Gtk.Label() status_label.set_markup(str_status) status_label.set_halign(Gtk.Align.START) status_label.set_valign(Gtk.Align.START) status_label.set_line_wrap(True) self.table.attach(status_label, 3, self.current_row, 1, 1) if show_lock: lock_image = Gtk.Image() lock_image.set_from_icon_name("dialog-password", Gtk.IconSize.MENU) self.table.attach(lock_image, 4, self.current_row, 1, 1) self.current_row += 1 class NotificationAreaTooltip(StatusTable): """ Tooltip that is shown in the notification area """ def __init__(self): StatusTable.__init__(self) def fill_table_with_accounts(self, accounts): iconset = app.config.get('iconset') if not iconset: iconset = 'dcraven' file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16') for acct in accounts: message = acct['message'] message = helpers.reduce_chars_newlines(message, 100, 1) message = GLib.markup_escape_text(message) con_type = app.con_types.get(acct['name']) show_lock = con_type in ('tls', 'ssl') if message: self.add_status_row(file_path, acct['show'], GLib.markup_escape_text(acct['account_label']) + ' - ' + \ message, show_lock=show_lock, indent=False) else: self.add_status_row(file_path, acct['show'], GLib.markup_escape_text(acct['account_label']), show_lock=show_lock, indent=False) for line in acct['event_lines']: self.add_text_row(' ' + line, 1) def get_tooltip(self): self.create_table() accounts = helpers.get_notification_icon_tooltip_dict() self.fill_table_with_accounts(accounts) self.hbox = Gtk.HBox() self.table.set_property('column-spacing', 1) self.hbox.add(self.table) self.hbox.show_all() return self.hbox class GCTooltip(): # pylint: disable=E1101 def __init__(self): self.contact = None self.xml = gtkgui_helpers.get_gtk_builder('tooltip_gc_contact.ui') for name in ('nick', 'status', 'jid', 'user_show', 'fillelement', 'resource', 'affiliation', 'avatar', 'resource_label', 'jid_label', 'tooltip_grid'): setattr(self, name, self.xml.get_object(name)) def clear_tooltip(self): self.contact = None def get_tooltip(self, contact): if self.contact == contact: return True, self.tooltip_grid self._populate_grid(contact) self.contact = contact return False, self.tooltip_grid def _hide_grid_childs(self): """ Hide all Elements of the Tooltip Grid """ for child in self.tooltip_grid.get_children(): child.hide() def _populate_grid(self, contact): """ Populate the Tooltip Grid with data of from the contact """ self._hide_grid_childs() self.nick.set_text(contact.get_shown_name()) self.nick.show() # Status Message if contact.status: status = contact.status.strip() if status != '': self.status.set_text(status) self.status.show() # Status show = helpers.get_uf_show(contact.show) self.user_show.set_markup(colorize_status(show)) self.user_show.show() # JID if contact.jid.strip(): self.jid.set_text(contact.jid) self.jid.show() self.jid_label.show() # Resource if hasattr(contact, 'resource') and contact.resource.strip(): self.resource.set_text(contact.resource) self.resource.show() self.resource_label.show() # Affiliation if contact.affiliation != 'none': uf_affiliation = helpers.get_uf_affiliation(contact.affiliation) uf_affiliation = \ _('%(owner_or_admin_or_member)s of this group chat') \ % {'owner_or_admin_or_member': uf_affiliation} uf_affiliation = self.colorize_affiliation(uf_affiliation) self.affiliation.set_markup(uf_affiliation) self.affiliation.show() # Avatar if contact.avatar_sha is not None: app.log('avatar').debug( 'Load GCTooltip: %s %s', contact.name, contact.avatar_sha) scale = self.tooltip_grid.get_scale_factor() surface = app.interface.get_avatar( contact.avatar_sha, AvatarSize.TOOLTIP, scale) if surface is not None: self.avatar.set_from_surface(surface) self.avatar.show() self.fillelement.show() app.plugin_manager.gui_extension_point( 'gc_tooltip_populate', self, contact, self.tooltip_grid) @staticmethod def colorize_affiliation(affiliation): """ Color the affiliation of a MUC participant inside the tooltip by it's semantics. Color palette is the Tango. """ formatted = "%s" color = None if affiliation.startswith(Q_("?Group Chat Contact Affiliation:None")): color = app.config.get('tooltip_affiliation_none_color') elif affiliation.startswith(_("Member")): color = app.config.get('tooltip_affiliation_member_color') elif affiliation.startswith(_("Administrator")): color = app.config.get('tooltip_affiliation_administrator_color') elif affiliation.startswith(_("Owner")): color = app.config.get('tooltip_affiliation_owner_color') if color: affiliation = formatted % (color, affiliation) return affiliation class RosterTooltip(Gtk.Window, StatusTable): # pylint: disable=E1101 def __init__(self, parent): Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP, transient_for=parent) StatusTable.__init__(self) self.create_table() self.row = None self.contact_jid = None self.last_widget = None self.num_resources = 0 self.set_title('tooltip') self.set_border_width(3) self.set_resizable(False) self.set_name('gtk-tooltips') self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) self.xml = gtkgui_helpers.get_gtk_builder('tooltip_roster_contact.ui') for name in ('name', 'status', 'jid', 'user_show', 'fillelement', 'resource', 'avatar', 'resource_label', 'pgp', 'pgp_label', 'jid_label', 'tooltip_grid', 'idle_since', 'idle_since_label', 'mood', 'tune', 'activity', 'location', 'tune_label', 'location_label', 'activity_label', 'mood_label', 'sub_label', 'sub', 'status_label'): setattr(self, name, self.xml.get_object(name)) self.add(self.tooltip_grid) self.tooltip_grid.show() def clear_tooltip(self): """ Hide all Elements of the Tooltip Grid """ for child in self.tooltip_grid.get_children(): child.hide() status_table = self.tooltip_grid.get_child_at(0, 3) if status_table: status_table.destroy() self.create_table() def fill_table_with_accounts(self, accounts): iconset = app.config.get('iconset') if not iconset: iconset = 'dcraven' file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16') for acct in accounts: message = acct['message'] message = helpers.reduce_chars_newlines(message, 100, 1) message = GLib.markup_escape_text(message) con_type = app.con_types.get(acct['name']) show_lock = con_type in ('tls', 'ssl') if message: self.add_status_row(file_path, acct['show'], GLib.markup_escape_text(acct['account_label']) + ' - ' + \ message, show_lock=show_lock, indent=False) else: self.add_status_row(file_path, acct['show'], GLib.markup_escape_text(acct['account_label']), show_lock=show_lock, indent=False) for line in acct['event_lines']: self.add_text_row(' ' + line, 1) def populate(self, contacts, account, typ): """ Populate the Tooltip Grid with data of from the contact """ self.current_row = 0 self.account = account if self.last_widget: self.last_widget.set_vexpand(False) self.clear_tooltip() if account == 'all': # Tooltip for merged accounts row accounts = helpers.get_notification_icon_tooltip_dict() self.spacer_label = '' self.fill_table_with_accounts(accounts) self.tooltip_grid.attach(self.table, 0, 3, 2, 1) self.table.show_all() return if typ == 'account': jid = app.get_jid_from_account(account) contacts = [] connection = app.connections[account] # get our current contact info nbr_on, nbr_total = app.\ contacts.get_nb_online_total_contacts( accounts=[account]) account_name = app.get_account_label(account) if app.account_is_connected(account): account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) contact = app.contacts.create_self_contact(jid=jid, account=account, name=account_name, show=connection.get_status(), status=connection.status, resource=connection.server_resource, priority=connection.priority) if app.connections[account].gpg: contact.keyID = app.config.get_per('accounts', connection.name, 'keyid') contacts.append(contact) # Username/Account/Groupchat self.prim_contact = app.contacts.get_highest_prio_contact_from_contacts( contacts) if self.prim_contact is None: log.error('No contact for Roster tooltip found') log.error('contacts: %s, typ: %s, account: %s', contacts, typ, account) return self.contact_jid = self.prim_contact.jid name = GLib.markup_escape_text(self.prim_contact.get_shown_name()) name_markup = '{}'.format(name) if app.config.get('mergeaccounts'): color = app.config.get('tooltip_account_name_color') account_name = GLib.markup_escape_text(self.prim_contact.account.name) name_markup += " ({})".format( color, account_name) if account and helpers.jid_is_blocked(account, self.prim_contact.jid): name_markup += _(' [blocked]') try: if self.prim_contact.jid in app.interface.minimized_controls[account]: name_markup += _(' [minimized]') except KeyError: pass self.name.set_markup(name_markup) self.name.show() self.num_resources = 0 # put contacts in dict, where key is priority contacts_dict = {} for contact in contacts: if contact.resource: self.num_resources += 1 priority = int(contact.priority) if priority in contacts_dict: contacts_dict[priority].append(contact) else: contacts_dict[priority] = [contact] if self.num_resources > 1: self.status_label.show() transport = app.get_transport_name_from_jid(self.prim_contact.jid) if transport: file_path = os.path.join(helpers.get_transport_path(transport), '16x16') else: iconset = app.config.get('iconset') if not iconset: iconset = 'dcraven' file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16') contact_keys = sorted(contacts_dict.keys()) contact_keys.reverse() for priority in contact_keys: for acontact in contacts_dict[priority]: icon_name = self._get_icon_name_for_tooltip(acontact) if acontact.status and len(acontact.status) > 25: status = '' add_text = True else: status = acontact.status add_text = False status_line = self.get_status_info(acontact.resource, acontact.priority, acontact.show, status) self.add_status_row(file_path, icon_name, status_line) if add_text: self.add_text_row(acontact.status, 2) self.tooltip_grid.attach(self.table, 0, 3, 2, 1) self.table.show_all() else: # only one resource if contact.show and contact.status: status = contact.status.strip() if status: self.status.set_text(status) self.status.show() self.status_label.show() # PEP Info self._append_pep_info(contact) # JID self.jid.set_text(self.prim_contact.jid) self.jid.show() self.jid_label.show() # contact has only one resource if self.num_resources == 1 and contact.resource: res = GLib.markup_escape_text(contact.resource) prio = str(contact.priority) self.resource.set_text("{} ({})".format(res, prio)) self.resource.show() self.resource_label.show() if self.prim_contact.jid not in app.gc_connected[account]: if (account and self.prim_contact.sub and self.prim_contact.sub != 'both'): # ('both' is the normal sub so we don't show it) self.sub.set_text(helpers.get_uf_sub(self.prim_contact.sub)) self.sub.show() self.sub_label.show() if self.prim_contact.keyID: keyID = None if len(self.prim_contact.keyID) == 8: keyID = self.prim_contact.keyID elif len(self.prim_contact.keyID) == 16: keyID = self.prim_contact.keyID[8:] if keyID: self.pgp.set_text(keyID) self.pgp.show() self.pgp_label.show() self._set_idle_time(contact) # Avatar scale = self.get_scale_factor() surface = app.contacts.get_avatar( account, self.prim_contact.jid, AvatarSize.TOOLTIP, scale) if surface is None: return self.avatar.set_from_surface(surface) self.avatar.show() app.plugin_manager.gui_extension_point( 'roster_tooltip_populate', self, contacts, self.tooltip_grid) # Sets the Widget that is at the bottom to expand. # This is needed in case the Picture takes more Space then the Labels i = 1 while i < 15: if self.tooltip_grid.get_child_at(0, i): if self.tooltip_grid.get_child_at(0, i).get_visible(): self.last_widget = self.tooltip_grid.get_child_at(0, i) i += 1 self.last_widget.set_vexpand(True) def _append_pep_info(self, contact): """ Append Tune, Mood, Activity, Location information of the specified contact to the given property list. """ if 'mood' in contact.pep: mood = contact.pep['mood'].as_markup_text() self.mood.set_markup(mood) self.mood.show() self.mood_label.show() if 'activity' in contact.pep: activity = contact.pep['activity'].as_markup_text() self.activity.set_markup(activity) self.activity.show() self.activity_label.show() if 'tune' in contact.pep: tune = contact.pep['tune'].as_markup_text() self.tune.set_markup(tune) self.tune.show() self.tune_label.show() if 'geoloc' in contact.pep: location = contact.pep['geoloc'].as_markup_text() self.location.set_markup(location) self.location.show() self.location_label.show() def _set_idle_time(self, contact): if contact.idle_time: idle_color = app.config.get('tooltip_idle_color') idle_time = contact.idle_time idle_time = time.localtime(contact.idle_time) idle_time = datetime(*(idle_time[:6])) current = datetime.now() if idle_time.date() == current.date(): formatted = idle_time.strftime("%X") else: formatted = idle_time.strftime("%c") idle_markup = "{}".format(idle_color, formatted) self.idle_since.set_markup(idle_markup) self.idle_since.show() self.idle_since_label.show() if contact.show and self.num_resources < 2: show = helpers.get_uf_show(contact.show) # Contact is Groupchat if (self.account and self.prim_contact.jid in app.gc_connected[self.account]): if app.gc_connected[self.account][self.prim_contact.jid]: show = _('Connected') else: show = _('Disconnected') self.user_show.set_markup(colorize_status(show)) self.user_show.show() def _get_icon_name_for_tooltip(self, contact): """ Helper function used for tooltip contacts/accounts Tooltip on account has fake contact with sub == '', in this case we show real status of the account """ if contact.ask == 'subscribe': return 'requested' if contact.sub in ('both', 'to', ''): return contact.show return 'not in roster' class FileTransfersTooltip(): def __init__(self): self.sid = None self.widget = None def clear_tooltip(self): self.sid = None self.widget = None def get_tooltip(self, file_props, sid): if self.sid == sid: return True, self.widget self.widget = self._create_tooltip(file_props, sid) self.sid = sid return False, self.widget def _create_tooltip(self, file_props, _sid): ft_table = Gtk.Table(2, 1) ft_table.set_property('column-spacing', 2) current_row = 1 properties = [] name = file_props.name if file_props.type_ == 'r': file_name = os.path.split(file_props.file_name)[1] else: file_name = file_props.name properties.append((_('Name: '), GLib.markup_escape_text(file_name))) if file_props.type_ == 'r': type_ = Q_('?Noun:Download') actor = _('Sender: ') sender = file_props.sender.split('/')[0] name = app.contacts.get_first_contact_from_jid( file_props.tt_account, sender).get_shown_name() else: type_ = Q_('?Noun:Upload') actor = _('Recipient: ') receiver = file_props.receiver if hasattr(receiver, 'name'): name = receiver.get_shown_name() else: name = receiver.split('/')[0] properties.append((_('Type: '), type_)) properties.append((actor, GLib.markup_escape_text(name))) transfered_len = file_props.received_len if not transfered_len: transfered_len = 0 properties.append((_('Transferred: '), helpers.convert_bytes(transfered_len))) status = self._get_current_status(file_props) properties.append((_('Status: '), status)) file_desc = file_props.desc or '' properties.append((_('Description: '), GLib.markup_escape_text( file_desc))) while properties: property_ = properties.pop(0) current_row += 1 label = Gtk.Label() label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) label.set_markup(property_[0]) ft_table.attach(label, 1, 2, current_row, current_row + 1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL, 0, 0) label = Gtk.Label() label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) label.set_line_wrap(True) label.set_markup(property_[1]) ft_table.attach(label, 2, 3, current_row, current_row + 1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL, 0, 0) ft_table.show_all() return ft_table @staticmethod def _get_current_status(file_props): if file_props.stopped: return _('Aborted') if file_props.completed: return _('Completed') if file_props.paused: return Q_('?transfer status:Paused') if file_props.stalled: # stalled is not paused. it is like 'frozen' it stopped alone return _('Stalled') if file_props.connected: if file_props.started: return _('Transferring') return _('Not started') return _('Not started') def colorize_status(status): """ Colorize the status message inside the tooltip by it's semantics. Color palette is the Tango. """ formatted = "%s" color = None if status.startswith(Q_("?user status:Available")): color = app.config.get('tooltip_status_online_color') elif status.startswith(_("Free for Chat")): color = app.config.get('tooltip_status_free_for_chat_color') elif status.startswith(_("Away")): color = app.config.get('tooltip_status_away_color') elif status.startswith(_("Busy")): color = app.config.get('tooltip_status_busy_color') elif status.startswith(_("Not Available")): color = app.config.get('tooltip_status_na_color') elif status.startswith(_("Offline")): color = app.config.get('tooltip_status_offline_color') if color: status = formatted % (color, status) return status gajim-gajim-1.1.3/gajim/vcard.py000066400000000000000000000617451345766322700164640ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Vincent Hanquez # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2006 Junglecow J # Dimitur Kirov # Travis Shirk # Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import base64 import binascii from gi.repository import Gtk from gi.repository import GLib from gi.repository import Gdk from gajim import gtkgui_helpers from gajim.common import helpers from gajim.common import app from gajim.common import ged from gajim.common import configpaths from gajim.common.i18n import Q_ from gajim.common.i18n import _ from gajim.common.const import AvatarSize # log = logging.getLogger('gajim.vcard') class VcardWindow: """ Class for contact's information window """ def __init__(self, contact, account, gc_contact=None): # the contact variable is the jid if vcard is true self.xml = gtkgui_helpers.get_gtk_builder('vcard_information_window.ui') self.window = self.xml.get_object('vcard_information_window') self.progressbar = self.xml.get_object('progressbar') self.contact = contact self.account = account self.gc_contact = gc_contact self.avatar = None # Get real jid if gc_contact: # Don't use real jid if room is (semi-)anonymous gc_control = app.interface.msg_win_mgr.get_gc_control( gc_contact.room_jid, account) if gc_contact.jid and not gc_control.is_anonymous: self.real_jid = gc_contact.jid self.real_jid_for_vcard = gc_contact.jid if gc_contact.resource: self.real_jid += '/' + gc_contact.resource else: self.real_jid = gc_contact.get_full_jid() self.real_jid_for_vcard = self.real_jid self.real_resource = gc_contact.name else: self.real_jid = contact.get_full_jid() self.real_resource = contact.resource puny_jid = helpers.sanitize_filename(contact.jid) local_avatar_basepath = os.path.join(configpaths.get('AVATAR'), puny_jid) + \ '_local' for extension in ('.png', '.jpeg'): local_avatar_path = local_avatar_basepath + extension if os.path.isfile(local_avatar_path): image = self.xml.get_object('custom_avatar_image') image.set_from_file(local_avatar_path) image.show() self.xml.get_object('custom_avatar_label').show() break self.vcard_arrived = False self.os_info_arrived = False self.entity_time_arrived = False self.time = 0 self.update_intervall = 100 # Milliseconds self.update_progressbar_timeout_id = GLib.timeout_add(self.update_intervall, self.update_progressbar) app.ged.register_event_handler('version-result-received', ged.GUI1, self.set_os_info) app.ged.register_event_handler('time-result-received', ged.GUI1, self.set_entity_time) self.fill_jabber_page() con = app.connections[self.account] annotations = con.get_module('Annotations').annotations if self.contact.jid in annotations: buffer_ = self.xml.get_object('textview_annotation').get_buffer() buffer_.set_text(annotations[self.contact.jid]) for widget_name in ('URL_label', 'EMAIL_WORK_USERID_label', 'EMAIL_HOME_USERID_label'): widget = self.xml.get_object(widget_name) widget.hide() self.xml.connect_signals(self) self.xml.get_object('close_button').grab_focus() self.window.show_all() def update_progressbar(self): self.progressbar.pulse() self.time += self.update_intervall # Timeout in Milliseconds if (self.vcard_arrived and self.os_info_arrived and self.entity_time_arrived) or self.time == 10000: self.progressbar.hide() self.update_progressbar_timeout_id = None return False return True def on_vcard_information_window_destroy(self, widget): if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) del app.interface.instances[self.account]['infos'][self.contact.jid] buffer_ = self.xml.get_object('textview_annotation').get_buffer() new_annotation = buffer_.get_text(buffer_.get_start_iter(), buffer_.get_end_iter(), True) con = app.connections[self.account] annotations = con.get_module('Annotations').annotations if new_annotation != annotations.get(self.contact.jid, ''): annotations[self.contact.jid] = new_annotation con.get_module('Annotations').store_annotations() app.ged.remove_event_handler('version-result-received', ged.GUI1, self.set_os_info) app.ged.remove_event_handler('time-result-received', ged.GUI1, self.set_entity_time) def on_vcard_information_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def on_information_notebook_switch_page(self, widget, page, page_num): GLib.idle_add(self.xml.get_object('close_button').grab_focus) def on_PHOTO_eventbox_button_press_event(self, widget, event): """ If right-clicked, show popup """ if event.button == 3: # right click menu = Gtk.Menu() menuitem = Gtk.MenuItem.new_with_mnemonic(_('Save _As')) if self.gc_contact: sha = self.gc_contact.avatar_sha name = self.gc_contact.get_shown_name() else: sha = app.contacts.get_avatar_sha( self.account, self.contact.jid) name = self.contact.get_shown_name() if sha is None: sha = self.avatar menuitem.connect('activate', gtkgui_helpers.on_avatar_save_as_menuitem_activate, sha, name) menu.append(menuitem) menu.connect('selection-done', lambda w: w.destroy()) # show the menu menu.show_all() menu.attach_to_widget(widget, None) menu.popup(None, None, None, None, event.button, event.time) def set_value(self, entry_name, value): try: widget = self.xml.get_object(entry_name) if entry_name in ('URL_label', 'EMAIL_WORK_USERID_label', 'EMAIL_HOME_USERID_label'): if entry_name == 'URL_label': widget.set_uri(value) else: widget.set_uri('mailto:' + value) widget.set_label(value) self.xml.get_object(entry_name).show() else: val = widget.get_text() if val: value = val + ' / ' + value widget.set_text(value) except AttributeError: pass def _set_values(self, vcard, jid): for i in vcard.keys(): if i == 'PHOTO' and self.xml.get_object('information_notebook').\ get_n_pages() > 4: if 'BINVAL' not in vcard[i]: continue photo_encoded = vcard[i]['BINVAL'] if photo_encoded == '': continue try: photo_decoded = base64.b64decode( photo_encoded.encode('utf-8')) except binascii.Error as error: app.log('avatar').warning('Invalid avatar for %s: %s', jid, error) continue pixbuf = gtkgui_helpers.get_pixbuf_from_data(photo_decoded) if pixbuf is None: continue self.avatar = pixbuf pixbuf = gtkgui_helpers.scale_pixbuf(pixbuf, AvatarSize.VCARD) surface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, self.window.get_scale_factor()) image = self.xml.get_object('PHOTO_image') image.set_from_surface(surface) image.show() self.xml.get_object('user_avatar_label').show() continue if i in ('ADR', 'TEL', 'EMAIL'): for entry in vcard[i]: add_on = '_HOME' if 'WORK' in entry: add_on = '_WORK' for j in entry.keys(): self.set_value(i + add_on + '_' + j + '_label', entry[j]) if isinstance(vcard[i], dict): for j in vcard[i].keys(): self.set_value(i + '_' + j + '_label', vcard[i][j]) else: if i == 'DESC': self.xml.get_object('DESC_textview').get_buffer().set_text( vcard[i], len(vcard[i].encode('utf-8'))) elif i != 'jid': # Do not override jid_label self.set_value(i + '_label', vcard[i]) self.vcard_arrived = True def clear_values(self): for l in ('FN', 'NICKNAME', 'N_FAMILY', 'N_GIVEN', 'N_MIDDLE', 'N_PREFIX', 'N_SUFFIX', 'EMAIL_HOME_USERID', 'TEL_HOME_NUMBER', 'BDAY', 'ORG_ORGNAME', 'ORG_ORGUNIT', 'TITLE', 'ROLE', 'EMAIL_WORK_USERID', 'TEL_WORK_NUMBER', 'URL'): widget = self.xml.get_object(l + '_label') if l in ('EMAIL_HOME_USERID', 'EMAIL_WORK_USERID', 'URL'): widget.hide() else: widget.set_text('') for pref in ('ADR_HOME', 'ADR_WORK'): for l in ('STREET', 'EXTADR', 'LOCALITY', 'PCODE', 'REGION', 'CTRY'): widget = self.xml.get_object(pref + '_' + l + '_label') widget.set_text('') self.xml.get_object('DESC_textview').get_buffer().set_text('') def _nec_vcard_received(self, jid, resource, room, vcard, *args): self.clear_values() self._set_values(vcard, jid) def set_os_info(self, obj): if obj.conn.name != self.account: return if self.xml.get_object('information_notebook').get_n_pages() < 5: return if self.gc_contact: if obj.jid != self.contact.jid: return elif obj.jid.getStripped() != self.contact.jid: return i = 0 client = '' os_info = '' while i in self.os_info: if self.os_info[i]['resource'] == obj.jid.getResource(): if obj.client_info: self.os_info[i]['client'] = obj.client_info else: self.os_info[i]['client'] = Q_('?Client:Unknown') if obj.os_info: self.os_info[i]['os'] = obj.os_info else: self.os_info[i]['os'] = Q_('?OS:Unknown') else: if not self.os_info[i]['client']: self.os_info[i]['client'] = Q_('?Client:Unknown') if not self.os_info[i]['os']: self.os_info[i]['os'] = Q_('?OS:Unknown') if i > 0: client += '\n' os_info += '\n' client += self.os_info[i]['client'] os_info += self.os_info[i]['os'] i += 1 self.xml.get_object('client_name_version_label').set_text(client) self.xml.get_object('os_label').set_text(os_info) self.os_info_arrived = True def set_entity_time(self, obj): if obj.conn.name != self.account: return if self.xml.get_object('information_notebook').get_n_pages() < 5: return if self.gc_contact: if obj.jid != self.contact.jid: return elif obj.jid.getStripped() != self.contact.jid: return i = 0 time_s = '' while i in self.time_info: if self.time_info[i]['resource'] == obj.jid.getResource(): if obj.time_info: self.time_info[i]['time'] = obj.time_info else: self.time_info[i]['time'] = Q_('?Time:Unknown') else: if not self.time_info[i]['time']: self.time_info[i]['time'] = Q_('?Time:Unknown') if i > 0: time_s += '\n' time_s += self.time_info[i]['time'] i += 1 self.xml.get_object('time_label').set_text(time_s) self.entity_time_arrived = True def fill_status_label(self): if self.xml.get_object('information_notebook').get_n_pages() < 5: return contact_list = app.contacts.get_contacts(self.account, self.contact.jid) connected_contact_list = [] for c in contact_list: if c.show not in ('offline', 'error'): connected_contact_list.append(c) if not connected_contact_list: # no connected contact, get the offline one connected_contact_list = contact_list # stats holds show and status message stats = '' if connected_contact_list: # Start with self.contact, as with resources stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status for c in connected_contact_list: if c.resource != self.contact.resource: stats += '\n' stats += helpers.get_uf_show(c.show) if c.status: stats += ': ' + c.status else: # Maybe gc_vcard ? stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status status_label = self.xml.get_object('status_label') status_label.set_text(stats) status_label.set_tooltip_text(stats) def fill_jabber_page(self): self.xml.get_object('nickname_label').set_markup( '' + self.contact.get_shown_name() + '') self.xml.get_object('jid_label').set_text(self.contact.jid) subscription_label = self.xml.get_object('subscription_label') ask_label = self.xml.get_object('ask_label') if self.gc_contact: self.xml.get_object('subscription_title_label').set_markup(Q_("?Role in Group Chat:Role:")) uf_role = helpers.get_uf_role(self.gc_contact.role) subscription_label.set_text(uf_role) self.xml.get_object('ask_title_label').set_markup(_("Affiliation:")) uf_affiliation = helpers.get_uf_affiliation(self.gc_contact.affiliation) ask_label.set_text(uf_affiliation) else: uf_sub = helpers.get_uf_sub(self.contact.sub) subscription_label.set_text(uf_sub) if self.contact.sub == 'from': tt_text = _("This contact is interested in your presence information, but you are not interested in their presence") elif self.contact.sub == 'to': tt_text = _("You are interested in the contact's presence information, but it is not mutual") elif self.contact.sub == 'both': tt_text = _("The contact and you want to exchange presence information") else: # None tt_text = _("You and the contact have a mutual disinterest in each-others presence information") subscription_label.set_tooltip_text(tt_text) uf_ask = helpers.get_uf_ask(self.contact.ask) ask_label.set_text(uf_ask) if self.contact.ask == 'subscribe': tt_text = _("You are waiting contact's answer about your subscription request") else: tt_text = _("There is no pending subscription request.") ask_label.set_tooltip_text(tt_text) resources = '%s (%s)' % (self.contact.resource, str( self.contact.priority)) uf_resources = self.contact.resource + _(' resource with priority ')\ + str(self.contact.priority) if not self.contact.status: self.contact.status = '' con = app.connections[self.account] # do not wait for os_info if contact is not connected or has error # additional check for observer is needed, as show is offline for him if self.contact.show in ('offline', 'error')\ and not self.contact.is_observer(): self.os_info_arrived = True else: # Request os info if contact is connected if self.gc_contact: j, r = app.get_room_and_nick_from_fjid(self.real_jid) GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, j, r) else: GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, self.contact.jid, self.contact.resource) # do not wait for entity_time if contact is not connected or has error # additional check for observer is needed, as show is offline for him if self.contact.show in ('offline', 'error')\ and not self.contact.is_observer(): self.entity_time_arrived = True else: # Request entity time if contact is connected if self.gc_contact: j, r = app.get_room_and_nick_from_fjid(self.real_jid) GLib.idle_add(con.get_module('EntityTime').request_entity_time, j, r) else: GLib.idle_add(con.get_module('EntityTime').request_entity_time, self.contact.jid, self.contact.resource) self.os_info = {0: {'resource': self.real_resource, 'client': '', 'os': ''}} self.time_info = {0: {'resource': self.real_resource, 'time': ''}} i = 1 contact_list = app.contacts.get_contacts(self.account, self.contact.jid) if contact_list: for c in contact_list: if c.resource != self.contact.resource: resources += '\n%s (%s)' % (c.resource, str(c.priority)) uf_resources += '\n' + c.resource + \ _(' resource with priority ') + str(c.priority) if c.show not in ('offline', 'error'): GLib.idle_add(con.get_module('SoftwareVersion').request_os_info, c.jid, c.resource) GLib.idle_add(con.get_module('EntityTime').request_entity_time, c.jid, c.resource) self.os_info[i] = {'resource': c.resource, 'client': '', 'os': ''} self.time_info[i] = {'resource': c.resource, 'time': ''} i += 1 self.xml.get_object('resource_prio_label').set_text(resources) resource_prio_label_eventbox = self.xml.get_object( 'resource_prio_label_eventbox') resource_prio_label_eventbox.set_tooltip_text(uf_resources) self.fill_status_label() if self.gc_contact: con.get_module('VCardTemp').request_vcard( self._nec_vcard_received, self.gc_contact.get_full_jid(), room=True) else: con.get_module('VCardTemp').request_vcard( self._nec_vcard_received, self.contact.jid) def on_close_button_clicked(self, widget): self.window.destroy() class ZeroconfVcardWindow: def __init__(self, contact, account, is_fake=False): # the contact variable is the jid if vcard is true self.xml = gtkgui_helpers.get_gtk_builder('zeroconf_information_window.ui') self.window = self.xml.get_object('zeroconf_information_window') self.contact = contact self.account = account self.is_fake = is_fake self.fill_contact_page() self.fill_personal_page() self.xml.connect_signals(self) self.window.show_all() def on_zeroconf_information_window_destroy(self, widget): del app.interface.instances[self.account]['infos'][self.contact.jid] def on_zeroconf_information_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def on_PHOTO_eventbox_button_press_event(self, widget, event): """ If right-clicked, show popup """ if event.button == 3: # right click menu = Gtk.Menu() menuitem = Gtk.MenuItem.new_with_mnemonic(_('Save _As')) menuitem.connect('activate', gtkgui_helpers.on_avatar_save_as_menuitem_activate, self.contact.avatar_sha, self.contact.get_shown_name()) menu.append(menuitem) menu.connect('selection-done', lambda w: w.destroy()) # show the menu menu.show_all() menu.attach_to_widget(widget, None) menu.popup(None, None, None, None, event.button, event.time) def set_value(self, entry_name, value): try: if value and entry_name == 'URL_label': widget = Gtk.LinkButton(uri=value, label=value) widget.set_alignment(0, 0) table = self.xml.get_object('personal_info_table') table.attach(widget, 1, 3, 2, 1) else: self.xml.get_object(entry_name).set_text(value) except AttributeError: pass def fill_status_label(self): if self.xml.get_object('information_notebook').get_n_pages() < 2: return contact_list = app.contacts.get_contacts(self.account, self.contact.jid) # stats holds show and status message stats = '' one = True # Are we adding the first line ? if contact_list: for c in contact_list: if not one: stats += '\n' stats += helpers.get_uf_show(c.show) if c.status: stats += ': ' + c.status one = False else: # Maybe gc_vcard ? stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status status_label = self.xml.get_object('status_label') status_label.set_text(stats) status_label.set_tooltip_text(stats) def fill_contact_page(self): self.xml.get_object('nickname_label').set_markup( '' + self.contact.get_shown_name() + '') self.xml.get_object('local_jid_label').set_text(self.contact.jid) resources = '%s (%s)' % (self.contact.resource, str( self.contact.priority)) uf_resources = self.contact.resource + _(' resource with priority ')\ + str(self.contact.priority) if not self.contact.status: self.contact.status = '' self.xml.get_object('resource_prio_label').set_text(resources) resource_prio_label_eventbox = self.xml.get_object( 'resource_prio_label_eventbox') resource_prio_label_eventbox.set_tooltip_text(uf_resources) self.fill_status_label() def fill_personal_page(self): contact = app.connections[app.ZEROCONF_ACC_NAME].roster.getItem(self.contact.jid) for key in ('1st', 'last', 'jid', 'email'): if key not in contact['txt_dict']: contact['txt_dict'][key] = '' self.xml.get_object('first_name_label').set_text(contact['txt_dict']['1st']) self.xml.get_object('last_name_label').set_text(contact['txt_dict']['last']) self.xml.get_object('jabber_id_label').set_text(contact['txt_dict']['jid']) self.xml.get_object('email_label').set_text(contact['txt_dict']['email']) def on_close_button_clicked(self, widget): self.window.destroy() gajim-gajim-1.1.3/launch-history-manager.py000066400000000000000000000001211345766322700206340ustar00rootroot00000000000000#!/usr/bin/env python3 from gajim import history_manager history_manager.main() gajim-gajim-1.1.3/launch.py000077500000000000000000000000751345766322700155400ustar00rootroot00000000000000#!/usr/bin/env python3 from gajim import gajim gajim.main() gajim-gajim-1.1.3/mac/000077500000000000000000000000001345766322700144475ustar00rootroot00000000000000gajim-gajim-1.1.3/mac/Gajim.icns000066400000000000000000004035531345766322700163660ustar00rootroot00000000000000icnskinfo bplist00X$versionX$objectsY$archiverT$topU$null WNS.keysZNS.objectsV$class TnameTiconZ$classnameX$classes\NSDictionaryXNSObject_NSKeyedArchiverTroot#-27=CJR]dfhjlnsx}ic09JPNG  IHDRxsRGB@IDATx dYU&#9gUes1S(cA "(EZ'{>[کy>q C@ՂJDyS{'"N{f7O|e7v~pJ?ܼe)7xs8' 7^6B?<3W 0#3y؀܄M$|~yׅ뜇sU"Ufz p;3!<{Waj| oĶ'!|>vO[7b#۽9AJx1 'oVȷ GV[9kOUL<2^wcb;?|uP\I_'GdA''7y>֭+XW8 okQl|> /EkuF#ظ8pi^oӎ{~lwٯ=9WvN>|p}gI.4 :/6OCMѺ.qc@':^x=n{!}y>~4<0$u#3>8f݁#PE >X6W>>p33qSں#A'cq#0 C$榱]KݹM;3증av~'BuB7z3 僡[aia_X:7=t?kִC n%gZcwa|0siQ~?egya멏 .F?Л?T^>2"=Xay.L  o n ~3Kaȡl~a_~w~#9=|N} >gF'%ܵag6j8g-;szBk%ݨzOȓ_<񒁕EL~5wSwϧÞ>b>@x|eXYxx!W+|{'uZ>=aiW-Ng6lst`]4,GeM:tG >w܄#k^^ys=V^텷6Z1e[81/ypʊ-CXU ?efkhkz>e|)bcÑ=7w]Gq`({q6[c`2FG1 |8 g\Ca)/.\H(ڙj䓟3t8GlG0Y8ca ~\`ddz_s';8}ua}TUvK~#7#`~n:ǀ̈́}G.mJ^@-T/Jaw7(hm=Y]Q ѷqxc߇{P~D Cp @(rn.l^9~A6o \p#~] V龤-\k,U gv_&.RÕ=wQA^p~ 'E7G`"x^'  ?Ilں%\ ;/;s>\P򍶞f]ȅtKDЭH1igt!O$RQqK-~/EoU_˗^׆$>xH~RE׆0_v];(iZK~XL^l{3%~A7Ƨt' ?3Asmx|&ǀuׅ޹rL/zp+_+jY5EYiM{n r`5Wxh#35-qŽ̜gAF2~KOS+uK: /|ý_{ ZX938~噷O [/Ǵ{xAkPE [ֱ:3.|dv5wV謧 TD:>J../ݬ 8_ gbHKa&OE\٦b#qD/CfOSrѕ$W3RɁF:ˇ?ү{osTHմ}3^cqNv|p O[mٱ-<"l9{ʪTe_б ʑq/0J+쬀o짛X,nG*#OTIw٭f6Y%>".hu4[}.V*?w uMUڻ#p"W'F=Wu7uѣ…O/afsF*YL#kЍd[aG|v~+n(xf x]&$('C8 r\'0avpI J!':*/h_ vŴ[}MdK}Ws!5JE ֦ԛ4?N͸pW[+RF1+8|ۅBM QKq Tyi5ܣ1x <9"Ia&: <ʲ܎iX3w߄ 1M i)7Sf@)-C~آ:a!ø( AN0N9GӸ&_-6Ir\y_[U; /Is_<=6<5#6ug\pA)5l}~4g>ZTPe[_\^jU& ^XD>D@K1T&L"_#/D Ah÷ Wc6-p3_,p]uM9oCۂ=a?yhwsn7\|P'׊&OÅ}KgH(-&Rb4z#AO:]| $vUc_:y7舜{JWFz)^3=<Ȳ^Œ pԡ./xl+:r>9qe|*m$ںbڰtw ~=MA|]6TaR{jFF|ֿayCB*[jyM1S'>i,5xQW/;v68pnpDp),ؒ f}<8hm?naqu W^pG!Ob_"i1߲9<ׄg_(@v`9_JX{L4ʘ^H)P,F).裺:kt<9IN "r>zx~׿Ó/+OYl /c08·>pČ?s 3W>I$yz@kbmuF{ZE-۷=ֳ~1}RBƞ|?!w)5-ڭ@.lcQ"VrVk.5ZJA%-ƉLDU6^aG,Ƈo>cdQ_ETQȑ7*”TeXYzDxru+.\2<cG3¯G,N)l{Nضp2^0e{ @N֓s&!w@귽yV!l>a:j^lņY_|] g2ReURR~21}Is#꤂i6Q/꫟R7뉯^1XЏ$_QY>ԟdU# `,>CwS?MS๐Y>NE/Ktj^&Ĵׅ0;';d_aǯ is97ZsϿXh6"tӅtE$RQ*B-44BcymWYӗbZCbM :8"mp_DM|qD^!lvaL?{NԸ\:f%w!& xhɏ@}t򯑯+lڗ4j]_/)d0,0ajm{6V{Z$ٯOb#?(uIcdؘ1ďʸ$a5o'eAl0[7\3̹]Jpu6|ӟ%< )xs6:ɛ#p#~+1UBǷMˉYc5(ӆŸ.u8YM`,'o|%Vb_KU0{Z'55nX $>Y ڏk>W(гF[yw^tٹgOt]Nյ)zvx>ymx)vy޿uca{ԓv=mx ]`->7,FѥR|Sy6.z!X\m2C=jͅ>Q祱S;OKg?B靊6z?>enQn|_۾zp'>u/-Ɉ@}s20Fws+ i`ٗ? Ѭ(RFWpoaLG+2H G*8BmbF煮~*Wy`$ tQY'C)n DSw7K.y6֊I?k,Lk !M,'\py81?oI@OUϼpc~>+ֳb =Vg>GC9zr;TyAM7ܳ]\[Ⱦӡ"bJd)yZ^6ru7NcLɃ=[#i<&YG#"nx|w,ߩ3|O7;G/3gOq#:IOhB׆Wc&(޶SO }y*,l"(>Ϲ*|׉}8Ѭ&Ow.XYX\m?< }; DG}C\qڣM|rJ+y/1V垼ڧ }ԑuQWs8A{ O-GxK?M8? ]]Xm<=G .^}zn~,l;-|<W0P^f.>l1[Zjv矈T\8}EqVuX91kDB> OP:}_$ jk\'8of7LfÖ~͍Δ@z?7?M&{g;Ყ6νsNw1N=ч3(o_Y/;E|f+쫼aS6(zxۡa)<3)2lyi3vR =$C&K52ud19@}z|F`>&IY#yYlQX:@vC-6f\wTD Kua9%-YK7GC`#N56O=9+FĂ`$nS|rL`苯Z]fc}he5y FGRbm5$ӏ=eIcn>_a[e.ߌ~ĉ3Z`g XkqC=mG{O92-򥂠e 7Gj˂'RnKEG ϸ<̊Td \=gwzgpRLRҺ(\{N)A^+Dm}?[K^!,Njp^?aGrBPzf^μiaϬog~k:'X=zK?tKuԑN'OdDe1 ҃wj}K Tl_*-6}wNmg=I]0f^~ًS8؍l9(2.9 hGnYEZ|W9k8i1ߊ}eO7p%J*9 gSq#Q›#~I;sÎs{-<v+ai?"*E-';Nj1o1GeYH3!ayOśxt'0uR_:JR6M:59-ȏ<\IC#!?ʧ3szq+N֬Xl{(ɆjO#3rFkT%l .~ ^{qxF= Vù{*T\ y֠TP8ϘYb2`RZ:ĵbb*_q=f?@AlbARXyäwvɾtw 6bAxXZqB' Hwsر#pW7jg?{_ua[ E2TYRC1 |f6㜿\(XբcLV*ɟ4[S~F P˕6>/OM:bhYo -~䱩j_%\|C/ Z؃;>w"~V gu?bG!n@C?a|F;o_|ٮCbY+<{oó}+>1@^ű^o!l~s5G}^YG˳-cFXLl,Kjc:W}%F#b~%:]`G~]=9̶ "E''> O)#C3./)GmʹTX@Ppj,G? v}CE:M,D]u+˅oοiX_)Xܧ1GC;r"3)B|Q-ٙMS_>ɖʞ,ձD xL`/RikRv<:? - ]X{|{U s g\=C6 W=C.D?K x=-h)VH"/ŵ&뛼쩋!K,B PS  SuN,G / 6)'t'jOSΜudQJ(ĹȎX?UtU{e7[ElaqWv;aԁ,#8']瞕2RñuËj8!'"ʉQaǮ]a)GsC=a_Cy{W)zo3ϰ/EVD^򚔛8*>/K;ETVyrT,xI06S}8RoCrUR20 $a{JE9t \Tgi< f;a[OVAV#>XG=d>a;/g ÿ*<<LŠ腥c)(8ݹq`w)wQ݋^z'9͚2NsnDIXؘUΧ4TAF"~4KtyEZm̓iko܆^Xu~F|S140=p]C/k9냀Og`2;?v9oŢ С+ptO:`~.{?TT_kЕ#If'f@inߏ^ }Z續p>A8hkFE=6Kx~ΐ?FK3.pJ$V|Ͱ.iÝb)p)xZ՛#`vuauzcmO;2\Ӵ(WumT/A9sCOKEf ͮ>ͦMX@T/S3k1r8ded|aЬ[-2l΢?lbPTimvR_twf߅[q7- |[#`vxHx6['4](7 sl7 5+HIou6?'u#FRCMz&7_aO scVE<p%7G`c =x@;/l )gr7 NG? V#^4}8_)Ъ'6~LO^C_Hòh8!xcZ8FrUf}䤢j|E 3O_ꊆcRocz0/e1#.18 .S 4=μ9뎀Or8 ۾h?¼GiXavI"\(¿ -*UZ#c핗q-~azn6ӔL~xJiX1i>a"JQF }!X)vi!52}}<)}2 <)vvj? ֬$xr @*[w𤴳qcw{:V$F[,p}Q|.lM=xg&Ps7=2 :ƫ\Ј'Z L\4=y/+#+L>7wT)} (mR9!6fضϾKwb[r]m3toI)G!g{rT84K ź=V,Q>7zb-?}?|o{V0|z$AQ(M>h1]SdE1̪,SJNMV-.z!4*D+G>-C6gݒrEغ=kN:u@r ٣L@OJkQqxcGK-fEl/DERPxϿ4tVOc\y#U+9kp4^#Y,K=2ѽ銸c{JkH7=1#uWwe)>M'f#`-Pu# W5:+Qo޼q{(w?e35z{c`hq17/{SfIN5=?X-:07׈}Z}•z3JMKK¾n}Z_Cgw4vȨ;O&뀀Od1) zӟza~ǓhlCNY)[J6e3 q Z0@G6elE_gx@! Q}Q d}G̷U7$O L3:BW؈Ÿ;\CZ+G?D{j9<8P|pBD`pԢm۹#*(ϕlӓݲ\ľ{g\aPst<ԩښ&I} fDltO3?5Kzq,7lI'kۊk>E̕_a}A$-?DŽ߹EN:wHtVdlt ]U8bf[~땛ԘQ/iʰE*bS  bPĘl1ʽ c'ϴPȶ4zB.d16)s:[da+_ gZW5{Qغόhv>X;lsKĖxUZa{KDgxJ]<S%{&t9)J(ojG}͎1ؖ:'澱*]m)}OmoeU,|=C 3 dk9kO[) @Q$St$D¿Ng!hkKSqLM2[J> .>M<"?MhPB&ZaSOvQ5lEt,~#bZ~GUz^?ҺPZ!BG`.m< g6X\kKKjiJ?.7drmW"6; yc_o4$oIٕ|)ǵ |zOiӒnnK_c-,p08 I|\nJ~g,LZoR;p}9":cw *.9JYY+]οJ8@7tDbo0rb0Od Ct'bw4NMlgw6\Z5@'klm7oQek(˸]N62).Vr!ioQ}MzԡX]8 c4&m2im!& H,My'I_i?mѵht~]h^;߶ &%I=nXX7slqv3=cqY`7u1tG8)}r&&֨~cS2~P"ňmw`I)o~3#ݺoKWt#XZ 0)}R3 0_;>No+7EAN$vbdBF{AdpQǸ=e(=#VlQ nыJ = azeГuG'㑰 ?mèc~kLOU?(sϯ6,=%}Fv=u r-R"%W=P'^@ .毴И.Ʃ 5hk~[b{DL<$9X͵zG!Ulԛ ]\'M@tpEig pNTdQ+Eqr MhkS>rr_GLyH?񴿕[A3 N>GYdJRWsS`֐ck?MSrn+ҝ9Sj1SkE1!cύl>wNj|Pb=npBLC)mRXSoSoq P%M`/r*bwGx7΋z]Fm<(vaczܦ.)ܙ)j4X- /W ErV/r*<ɨhx}.h&7ܯ7cҚ~K݌7;g?0-b\p_6G{([z3Yzn/yIb_c<"PJ"Lɣe-}Qȩ(cǤ,Kʤ 7h $~C&7L77e~2z|f<7T|/|pt?EFpf&y#l\ l|ڴ..i|hb>t8 YY$*|c2! [IS/A?VhS1.<:t'|LY+k"!qțD 6ydzh ka2H O@ O6Hn׳Ml"K6\l<7Υn9y[tx?ӆ ,icG@J0^>,& 1 JS5t?LLo7SN"J^iuJT'ĺͤqNi?n{6qPSr0qT|(۔b/EI?r\@]7Kjx7G!GVZMDVsapjGm`!ƽ xEOEq1AH-&_stƲA~Y䓶1X؍/3}-fSwXiXk QUݘ52I(ϣJhTZO0|p D#MeΠblREH2)7O0=z ciNvELൾ29!ttT4{,24#ㄠf'Si(kShF|*Wiߘ;}jJcȡ-)=藼1+u#`v@)l_]mQ6@̋dewe]l[q tH`:$@>Mlizҫ_ ?M^=O>3[e[NED^3?gLWg^TIwk y6͔3G(e'lkF#2qzw|0g>X'=HZMp*NL@GZd :=j<ޏ>eo^ [dQxl ƃKpyaעytD^ҫ`lĮ.udZHJ6&u[5Q~@{[@UPگoJ栙^Y `g8.sUuW^9h&V,##۔힆#< }q 9{:!oynE:X ٧x#|dN )eXDEq&@mXc42|(}VZ>G2bܪ.GoşJgt܅,ƢTg˱Tno7B"v pQ7G!Gt^0=7ҒE5nܓa*dbo҇(1 g· o Vܫ~ :"| +Կ2>)ϡfF Z0O>T'Ky|%62vL0\K*bOEQK84c-#YpI^&fm=Mͱr\ oC''{ Z^x *npdp;襋$pBǃ>N.݂S# =) Iد}`zEn&ӈ9ifIjO! :r۟Z"D}OD wKmafBh^3dqUNHj}I/-/Ň0Yhha ;','ƪHDCqG$8鸀ydI qt|, 82⳩/xdirEoN^F0op(A膟D_=86|pl1";yM[<|oشj.f,Lsy@$hNP`8I: ҟhR&$~LjO-Qo|SKcz,m,n>&%YO}6;[F[6"LЋ 8L#b4ƣyt@+b -:[jR:v0 n5tz8  Vܛ#pxk^$pԬȰ7(V:s}yȫ!Ůӗ^ ҅xSƷX.eoov#k"6 C|ˁ߄'rd*En ]C$dQҡnEf?ԛ||ߙ9 q̥g¡}e9N9대Op׈5摽B}dV0З;s64lSR\ `>Ɛr+ qʁ1wƐbKo1꼈MccҵucM߶XmEimEZM /}ʕ,)#'u]~Jڬclė*X| {|e.nՍnu t,iO5<ɤpWI@Î2IG-剈a_mآפO=c\STr*P$];ǗOv"mE^HGZygAD75^Kk^؏~L^iO=_TKyWNSNSnq]j(\ߌexH_.y)+" T"}%"S=Y'E|BHçb>->R~i+8kO`w?I?M _u|.7,~#! P X:1l㩌{D,[/sRH yG5G,˅֌bcjInIFC537"&Iة?{qK`g> IF24^c5&Qًcj(Bx=~낿 y;) 7pج^iQnqc`Н 9,sҙMefWRx(O"QGde=K/kM4CCrӉ2Oįiy? :j|}T'1MmR<6,)E]B];jDm(u.[=e/UY>aq;낀mE%qF!mj;Vƍ{*S>E\  MnYs!k比x|f7,jnv5tt*=gEINRu]IC"3)Gy?](G/-vL?9] >X\,(3bk*6Ȳ׍so FݴF:–hˢzz/~c/i+'yK91,Vҥ3^w 2y Z01e)N)7IRqi+V*';蔟5ǨS Y/׾Y)HF?lo}LO-+Ş7ڸ>}Ҹ{ aEP.ig+ m_=`G'=yB`,|sgHѩWceN>D.z'9DFῈ%vimԖ..0&| rk7} Rm?{Dr4[sK pdX| ͣD''}]E`>Xe4<鰼&^cl3`/XTRaO[P@QP,_o2M3NrYSN¯G)~X AZ績8D!Ib,1kqu,/tK3à]MWcFݔӵA5efNK9.?_]X| {v`6 Á>U8g7'?ᧂmq*N ?Hy,ɟ嚽:/!1LUxfܧLGl:fzRX &c%mD0N˸ǘe?T#KNIZ`?]v14brq 9]&>X;l5| &ާn 2i@k4p|-7K:V4XH9n@s`L\!&BĊ>6Ÿu4WZ?a W,Fk:?]˱5fl5h'‡8T^bh|aLћQ4<3ͫ%9۲nrG` z!q&"p+6#dr\-~;بŭZ T+ ؊.ʿ$6ukh!?.)hz#U/h/%U"J&V~rϙM uqfzé&7L'>7l|!OFiM>z@Ux@Q|@+ck1Ŵ@\{>SҤ'+eLXo%/Qo?,|Ԙqc|f]iΪWLy`xęюYU('&>+lxj/iϝn8W{-,,rGwAA{CzE2):u =,gG(75*\qc^Jse|$Q}Ÿi+^UIsXsVi|  ; 䚽f_QfÇ(#^`8x8 6۰pxTEB B M3[2fӅRZE$ 3hxWi52JR>Ο)8"0yKbķwOS>3JG.茮J izdiΦtYel̀{\z֫žʮ>X=T]m +G>}+~,5 +GQaN":P*LB K/*L{)GY~ԗꕺuYØ؄"'Ot/{[TSŘ[5Wk~ DɣZMVbW ~,BPM†Zo3.}H/ I]XG|`{v>ϕ:6/6ڕ",)xк :^l^yIZѕG,\o~ğĜXbnWQ K3x! Zr#x}_i{˩-:l|a OҰt n8 [)"@B&x-p7X+VbL}mqR!BF?18wuӤ#Ӻ>cI_1ױĦBp ɣ_WdCBڔ25^nד 6wh= x)l|Q ϣ^4 K覅ZBo xVsT }-\UE|e8?RlʂO:(/I5-_}-("^憘sddX{g(SN{πQ'jGq=聛-sZA'Grxk7q{Oɀ_juC豑Om^^0avVlЋlk= I1Ʈ[cB.j' -HW ?rjXw{g1,GF~r/xcj'5yuA2fu|L?}|d_a& QNvկ x{7G`!xF@vA/n-,hPnU>%QdbMJ:x/G&Sʤ K|i?C C;E^[Q_|x+j:Ɣ؅ɓzpSugǘ{jiHXᩳvG 1C m` >.dm^JOO69%:ڈ({unي"EAƇn"B RY"rq,Ȣ y*'RڍY,NMr\~QŦ:\TŖ2,Iċ9롾h_qt2ִeCc ]DZi_h*kaZhg?Ѣ^ -'-#` @u^7 h/y.@*V({>"R. m6MBd[cR -\ lC[i[.졫K!1^cbGyW>#y)vS٘-}1̘kx֛<}XNFkHw>G]8!_&؎vcg Mll{Iٲhа~= ==cƢt-r3o]SKbYyΟr+d}j|эDGĥcz&o1N [ͯGf=VfiB}S}'/.[ĭ8l/SSp -~]UP-nyCo| `1(*־ZH25<Tlr|2=gi"*_*|m,MŹOSJ:"!5numv *˃Lġ#{pOG`"xf+3r`v pH]ިܣp1sTGlf,O%mqJ~#t&}Wg2Mkd41)fբ[zRh i/ӤMf}VC y'oMO WPžFܥE<`%EZ=MnGk\8A cn\U[G7,fh,,R~ x$h-vI&(L\tQ֤P/%Ocj>hb:yG}^2-G&˓G;=WMS٘9W~Ƈn'AҘqE^>6˦43_rG`# -xXEm/zH B'EMn!\["gvգD8^Ѧ㤂Nlw=jb {B*B8cxp8߀o_Ǧ,3w­ly虭N/ă /0@ТfEˊz\ʛhxI'I٘_Nu:%Qhᇝ>I~D:"Я6=%|;XT|zUeݙ3aIl$hɁ\dp>I8BzU3IFA'Kq㮥$QSanTp`ފHcצ7?_)\V]- ME7?WYG*:#~W\e|e; Y7L)9?r8,bc99=3[-,6UU[1BIz*&ډVȥpO5?];=S.@~Nr_^!҅xgMq?$ۊ MzsyV>/푍>Şbxޏ=>/zU;IFC'|Z!Ŗ6O]) B. 6d;~w<3{MJp8ZqEGs^}1NyK&"X'Y/=1)(Z.cay|~̥.cif4lީanࢿY?fQ ݌ZE?Njl<|ϨĭVؔO {jB ЍE+_GY_?;BIA91j2UelO:<s,2_|/b7WK!#hf\q1~u@ˆs s=Xɣп2'vUOu G`!өO\[FVmnWZؼԨV ➷.6- t]f~:orʱ,pҧ-K^!2 K}Uz'Qk<)W.t> ~ }C(ⳁ_i>;]8=NfWWC؃GK=x6nFR$>tN.}y# ?JF=p߭ }NEj`<ceb?pهİXM},{-%_?{(Q7l+ihQD9`l6os%1K%$J iVڜwoqsܝNS'VWWש(b#uKjZ-Ll0Jv=ô NKAeڸ)aű 領s}FggaD[`TsOj5(O|Cg~ `V\h]VW%^ r(.`@7 oB!+lUsuLsBJqz)Яx¥g:_Ww]ᕺSY2̺.r 8gi(_a2q_Uj9 j݉퐨 :4Qӕ;t0&8~pb-Y.oTl-Oխc&IA3mӭϲ[tH!LrB)Rp&^нB)'$H%a;!VOn*y٠40}o [,.t(<]Nr`t5 =4Lɣ1T7J2k/௲VssF$jx Bb0x-_dZOw/aIÊ͟v{4@#9 >? d'HaxP0-LZVWJݮǿI9U>5yNg3xҠ:yj"0}/*'߂2w K.i:㟔xB)z"P(<kξp{߬A+eK5NDt:W5M n'*Ͽѷ :sZNvD`ƶE\}E!ӯBfYLmt3&ts!"%6q~+fʈGzt:oexMgAX(P|>9SsG8J鑬j*9́n  oBFWlsrVl|05FOhX':`Ǖya^L%3&/dp6;~_kN8-9 OC(OPVsYI7m8F`"N<(V '4#9p瀟}D5gg ]u=%WvX,'X@DE#pQxr1B mk:6EMw-C*h6I4I%{-lҟNEuQS`U7Ӧ<'W]{bH 05Ṕ/\O[lȁZL|:ZKTVc#94&:m $ac^:J3ucB7 t@M2^.\`D o;L\ĥs<hcNy ¼[y$RV4?bRp?|Eϧ74` H.xOfR9prs8]f/ _o-H^gT,`#xY!NBm@M}w;HU9y!ک:T4+.˷Z:xʴ(x [E>wK'f :KbtG-dGpOJO!t{*6ls`6G5Ts䀟$jA ;P dDbоVk>j# ;_HNǓwphw/>U=q<6׫8s{(B-¹!-Iq yXP}LF{]Bוb_>qʣPܛɤM=jpb'tBʁ_b>z=[iT[z)AuRo Ò789~&9*cR0 s&#dի)M$#4ӌ(NOk8~<(#a> cL;8i3c_Rn`AA9 #?cXI?H â9P6* \ vw"ޏX3}kBCC{|kvIc~yAτw \eCpY/pM!^~@4Z  f8!>l^Di8/UqcB4Lt F+niHǞa;-Lwၽo.c> +.wPr> xپoc`hO60B1n=etHɸyʁj`2v!}]%bX>T3Oԇ_k nS:ï k2/[LBٿ3?]96v1H @;66zY]+$8r'n'\I_x@]/o&c@AIp9>[ 9~Bװ~ș;V(hQi1ۛ$qD:?=Ghy(6r .-\>Wg# qLt ~}jDwe Ц:X\{t%\t+wnЩ_rqX{o+jSl\s3]p >ɦ{b&j.qRpe 3 'I@EnU pQ:aN+Bs RwVi4DbWA<m0nv$m3 gFKܺfg'Ɉ,P tqSpGvX +M@RGrr-zwJ(>2vq}ZzǾ𱫽!k']-b;d宑cd_BO QvoG7kGƮ@C}sQj6TVU#BAH Gȼax'ŕT.f?FJ=?K4&a:Q;MY}띱1 @n-[FAm 8%l*3Fv=pe7"85|P=}jPz&倨Τ4WzrA!Oם$(~MӺ{r 8&/ʼnclv׊\:;ϨA-s_e70K*8X:ܲ> 1Ҕ3hvى!7ɭm^i82*q%LUq`P/ md$9Elg9P >ɧf(ִCO[ .\OR< G1#G#]or;)8f5Zʁj+g0;#R9Fl'-.{I$:d,M\Kp<=v܊u;In$t48BWNB@ג7LsZj"puO`Źlx5<īg9ܮ6=UGӹM:5KNO,K1.q9oyߓm_,qO:^=/,8L57ޏ'^7>M^Tv C׿r9xrf?y䚮Z;s@B{:\=~ٜ iBο5V$/5Yc08NxVۙHLY!?s:n17)UӁ$u!xq偶ǡJNS8\U1MSjC8qabP+l1vZ_RN̚g? %tٵ|Ukya[.eȫy&=16vd?Lꮃ9/k?EPcXBsW50ΘGg_a_k`y"XN&l"YNޫ2vޛKOnO@/CahMEyU(tҾ?y@@JP RxzODk: ~)dDkюeۍ!f[|D N;`0:NZ(iC?ifN6NGrr&#\JSh#KFK~_BH]bEiUZLNHe{a(}oq[|dY?vHҬdr{$4Xq(oƸ%v6#R5WT@2ֿK1mk*} E˗W-}|?æg!G7aomeC4TM.huASZQyyQRF/'bㆧz`؋L(o'_3x7bܹrUˁj zDzܰ' }4[{f:`UaU!̋ P-Ϯ$B+0B_j/XW7kd,"o_]*32)–K!0-ʡ5}QvPnF"טNy$jhqk朾o]z? C>ME0𝀺hk 4'AKl ^d,?Οi, { ә %s*^~iXODURK&"-j\SZh(ԵdXtm՚UfsE HP l?:=u27h@T+eHŹ k D_B:=J1@4\/^5EC'ه` '.a~~J3=$:katq<00gh%%Ģl } 'v@x-d{fۥj.&2AR}$JH췱*S98_mQ/–뭭׻tb3 [eVSIMנ'Lյ0(` \д 7nv*/]3Mn 5!CmʰuXcM B=ד_uLF犯K.l{{U_&OcÌogW0( Q25ڒ+YÀz 8$8Z]F|(r` ᡝQ"9ccpv9'hg.; Gm7׭A6ON?3iյګp=+ATPja8=ί/ҹ1862~3:Ӓ{S /Ғ<_ǖS0^0 ם?G  ?WpzB0^| |]=\ y&5'Aty_) 'K>Jb`%,J 7eMs@F4t&+I.߭ɦ*şD&ϛm-c 1XYw},E꒷%*, db pM~qI)Eͅ@ naCp߯F1w?SZ7k8:2/.T )4d-fhA=cc=X{kK[М?)g$EVt{oqPހ}v܅pО&}j{oyQU{r@OɪJ; >'9Q@eD~Oh'l]4yK,feEqeOh>9}z5MZ[~-+ ogtD~<F82D3Qo\Y;x0ůbj M9DH@hF "gft&A<\+˨->w0XUVIep9ደ701_ `|™oI( T,ޝ)*`'ecͧ5lB"l>981*H`t܉:|1˾Lo/Wp/~C%ci^,'E ײFm+#t2Ň֙Výqߔf?d'd4I@y UIR*P:j5bxcP9yU(J>M'Pὰxr^W58ͥwVwD\&?V_XPX,Y4G7 7uPEdYiZɢ8q,93;p=1 Y*1$l3qBʩ Z_]SߖFk|{m4Q{4qe#OɝD*U9DH@^"L@`2]X\s4'{+m;DuD1.dgq|3|#X'|oc=}cp&Q I^irW@mׄ#f=߈Wui *ԸTC\q,ҟS3/qn2H`d&eG,+"8?[f=y[A ^|9R*`>W OwJ5hU=%c HDJ:ђ*s!ŵb CcS}gl%ʒrlǞyqy(R?3 9Tkv=sAP霠 {p _C{ 0Ntmx+p""hI(QJd1 E܍_q| bI&cE$d\YI @<:_gO="Z;1=o}Gǟ73vqŢTY""*)GOSC0ɨRLTNMB`9dLOZ47ߤ$֙@]na Wণ׏~Xg #-tnO^q*  H DKz9 X Nk~\;}~7ADfYNBusZjL>FSjKv4 .8vS=0%uH$,<䜺'] /1FΟn+ll΍\ŕȁH$58{J2yoR+5!Ƥ@*{G=z穀< !4q%]-68R}qbj,;3-6>Fzd{NIx3o{w NρKHezsxN=5X ~qTbF?9"8TdY;i(1jMe%!]=7݌`ECiTr;S$g1%Hl4{I i_zLƟ?]w†XLN2A9 8- Co sEy0PUt:AEN^0N@GVX"ВX 60zy ǭg@T0bq!~&5;Æs0RXCPWO]U.5 ;Hv wbτcGO'm}W^mX9G,󙍯[F+ǝhsqK”%J QIedH 0)QB}*[c H+zsV{`/#Ͻ w_m/]y $1{p?O)88tv4%{ad͖5`CUvQ"*bu/ <i'ENy$B2i DK].dHJ0 ik7ױ%jA&ŀTS/B:=/LbK))F>᱇pJsT{Jا_> 89E16Os-l_nT* ʷgWoWyЎU\JDI@`V%+1E"%,T)[tmmA d;-q_ 3yiQKv^Gosql*'%p/+S4Ab0GZxǢ G`$8[jϻϡ#\lhX@6)tOdyhS@N XB^e (" hU8HJ6 ˱!@C1\U(S3,k} @ _z*]j*ȁRɰ`mt{lm0wJeے׸?|VVhsQe"j"n҃qK"8 6 MeNXx$Rb:Jl4\oRɿI¾Tn+#>*㥀5s.fk6]۾)4.h +SbC8 #>."֜c:m8axA * ɬG\'U=! )&I†zVt,U1 `%k?-`cBF H DK@GڊȐQ*84~34Sc⹩hT –qitg 7_ð}*PO>;܈U WÍwDc?ǗF|0q0"ܼ VUי/b\? ;qEK ~ :;@);EޟHſc1>Vc|=S\;+qCLj>4nÌV>W䬅+`;uK+ >~N @L䶐,fsyPMkiWc}h v^Ʊ9Ckp|5\8?vMEP>O⎠筸un=OT!pE1۷| $ sTty/q+KeW:N>=xbK_2.ȼ -{[l,s0-Kn %EuͿ{xE9 oDm[RSAAv^ۤ|֖9ެ% a# qsm 3 +"iHڶ=Pz~7;5<N VE9.0; ^D<5t(Yr޸Y'XzV !<V$BFg^Fo-~pb_.xjI( bxS 04ušoYWxkdfXaU =Cq<"\Ŭ.&HT+ȨB,S0_Ÿu2;G&_RQ'!@.7{N:5-+ҧӸI=?KPs ۆ\~ʼns ?:ǀZ֭+O>~%!ڀ4 }Oc~CfЕvhM.:W=Cu_hJ>kM{ѰKfu7o==0{x8|/k"ͫu\3 5؈O-wExC}TˁjbYƻCR5K~D74æ`c[zY|5.B(ަ%|W~ cFdPY-UH5`Zi%ĚۧI{d%H Ą%it&}k1";R]Y)BR0^#Vᄅ&$%/WcP1MOp5Q$5e{ISIC8!eK<\džyԹ%̝q>4 \:I'`~{̝süM֍80ǩ?&(ŸGov;|:7ͅ"_s1|`#yȭb>ץ'z4ۗ7E7~'ů~v>BT F_.I@HWd$ |DH ɘ|BH',/$r輌aa8:w?ڧSS֎&QӖ«V,$؉S'-!!+G$}3'n1 gMeyHgESg+k,tb  IhQ& Ƌ?Yµ>>cS{^$[ 8V)K{TqeA4_b` boI 6o@pñ:$4g'`}%?u~E /+*ZZҬY*`IË@_j/Vί2aWQ-idDU#آhFualY]3altɁ[ QTW/*Sy f"î&LqQvx839{!?LO_\専K!ѩ X݅3q8=d0E˽85LΟ' :xkh(')LC=ͅ4Bx~%ayFHaxK=u+·`͙'Ϳ^ʶ+Ng1+Xw8,iY ~&^CkZ]_V3):>;3Xuj^ӫF1ԩd"IRh&QJ$+s,N `#}Y*G1\7p|&$cD$yWJY"s 4T_d58;'\À?ϮVSs8G#Ӹ F֌;@iP>uypx%ˠ&ˇ#/tY"kY)[tmMk۱L]jg<_ĺݚ~ԓJ(; ]A+S(ǭ9/.I7zTQj8|5] G3{wIwgSR~ 4?PmYG mqUw'fDJ eYx #a%Oqg 2Gdơ%yb!9:V#9I6/$ <"={$I%a䘏2‰:X|F剑eI2#K⎏5/) Mq?@=֚ 8ք6*PnZB8m,o:Qu4mi ]8a)*KzTɫtݚ+xw{gҪR]keD,m"jU ݙ$Vj񨬴J4h1!bf.:T}|Za4n"QwghJzVt>%jLA(+j4 p{*a2&g"x^20vFp-qi_) q`@l>g ,=0CnCei5ZG|_ʒYN;2=:jº˱!ФS'H糩CZ5w`Gϯ '4!qgӣqG} !gHpo߆b`щ{auFrGZ~V*/'q:kdvTh2-oVAm^4ÒCN-Y pΉzXqWEs0Хg4-'),%WZ j\cL7H$u~ CK4Ɯ;ka+ x7mgA[r$QzMjA "XϽrVؓQW F8/*U:(:V'\0U96)#ȭ8X(e(XaX a]_$}Ƨ&yҪԍ^l_.?K6/mKpIsƥE\5.`8ܒ I3sI`)m"% IA60CL rв51wDNxY6y5 >A%̯VtZ)6GI w9 =MN&Vkz=õu+Nsd%)á9"~er(Et|Aq<Ψ^Z_ZhgY|?u~o pğKNI{.`i2Mؘp춢r!#υDM _]x FXzv*!*Z0  +lK9,;b: 6c6|e9]܋:[>ı+µ?c/N-b'N>G=㿰IdoE5~Eҭ()+>SB ph\?} rFY.,&Kk;00p F,.D4l~J'(q8dAإ+AW 1x 8opެҧj䋩 r,[|hġpnXtD Bx 3-)Bw Nܼ:_ /N o9ߓ~LOof@9<2ˑSyiflKW^z+\r |i/G 00#yM@$~<"+F"X TQb2ԘE׀K59HmýuCAœX>s+@~#8QqBپBTL;n)S?H|bx"4Q:8&0 <7rnh3$T`WgY~V6] [ĕkyYsr!G" t,q'Ց\-wnr$pϕy!#o=|9{09%Cfx߁ _bն =w^}ҕN! "Y$3_Aѭ5OBM_W5a81<\;Ey[ 0!xyCGpX )H*VnPɒEf7oqRo]< G#"_lDqacV ύe6|e>C!8< Æ^!, r5Zp<'=KV ԄpARxs@h nĶ;"7>p[ qIf5̒4? D}kp՟?!/^#zylhZ- ABXtb5j-brĸtMۮj>1Ey^c3Q=fYc8DRl|{t7丰Kz YQPzܲx&l"saѝ0t?a#_&'׵3C ~Wu2vL,OXKLqxwǀcV&/}}PoE5 ٷV2 (?z{ZA"(@ X\r^?=lY/r0d*Tf/+OԂ"H4 =<̓MJ$B75/1Or#PFҘTzirfGZoW Mc]o- &TH| ?4E']m6N@&] /Jkp'b`d)q[='Oxd}nֶ";ɚȰK};kK MUP3<)l6MO2o`"39a6+QTSq4%OUq,ÎV>(~-}`Y g~ ҝ2 [ 4FlKX||A)q<=OYPZDp(W;`EF"B<]JRݍ) &#nmA* pY PD98vj 'p=u'U?1y՜NKM燱A@ sGzE9+7P@ SP[g_ĉc!F"OMкi7UxPHG6'H9p|5תdGSnDg 4!-)*6@NX#ҥ% wCy)UE0wlF,UlQg$inpyX7"Պj@aSXϗ` UȦ )AZDJڀEX#4fӶ^>ddu3'c|J]C{:Tbf ^Opv0lYFLġٺRf.Ζ\Ǜ2F}9$~'b$f3UUO*f:xegz&`|t#~/oMO*{ h_tΟ)7Έ*HsaYymoĆ *,YIF?~mpwc?.<Š_rgЭٯ ;+ρjQ8_?u[]:?:0 6,YoU<;]tʖlŋ.D Eldx6]bpf̮9o &SCB=mLea*g %Oq6 Pƀ9ũ,$4 LAv QLcɯA qVDj;iryHdU0IInn=?6cCx_Sg4OBN{%~|_v5c382JZ7Vgw[ٍrxRks WZ]Fωh.U83 @*; )+mW:p-sFTgw!l/-(\Hx hgpLcӯOϼn+Ń)BY K_Yxm"b?K7'hYZƁtCYe0?,2ڞgb/OE8a!:fȔt [RID6gM_%-;OjkW9| @|ܓ߄xZ&=X* Ah R4oFŤpBπcTٽe-Ǵ' @2u+6a`ߕ/];"G<8<SY$o@yX-weΙBq`:}yxmh48:{TYڽp /1YWY%\k:^ fozxi{Y={ {܃3aV`HJbزaK781n< *vb5YU7,#x;2m)|5X)\ӱ|~П:`PSPڶER5E"| dӍT(| s@~WRK3\u1aKCg{.@g N@<eI!O8+=¡3Y6|˾Iؕ3G:p8=6&3T%¦=e:5np:?2ܗ?̔,h(<6GS04}Ոb,}&V hDoR}'1Ȟ m.l|`ד]|XA,*~_aAlj!.pJm5 t<_&,.h*CMd,>~)ak.#" -%I{>@}" _2eM +A+~NItc0> C7?dWFW>}SN9A#Syg`A6߭ݼ~o)n}_r(;-3}#O=TO"OY%MuOf' F VYu-e0d1@Ӟpq(!D {n%zr [u/v~+9nȽ :k]i'oJ,AL,Q䰗P#.@=>&8H;VMoGyy󞵔XS|o.^rpV>^mڨe ቾo1eN4Q[2ذ ElQWHYm.bo㡣>#WDpPa >c$tj᥻`1BSf7>> QiDøpЇVX?'Jq:2#`|GFV87 b/Ƙ4U"$SpwAj%ԱL.EU*fp(pHYdo3 9dCSaswA7@kb)h)G5+5Q49:aP?K:r=itׅ~ `[~ùQ6EȲ+әTҊ0_byK6͆,"^J"WH堂p8H"j*F}Df6!&j' EGaYN(tDIO(wņoLp^6`&D<,9t8p&&:o|:GzF!:ZhCsһ`|QY3awnx'&5`:;6̚h))z~C[1"#*̹^gp(1l5&,0Wd#.ƕU[ 6^q[nn~Նm?,{)UX7.F3ǝ5QJLep F"N5A`>Y_(]9lBaȉhKRRʰɮBԯ5,wCn 'J{r*#l46ih?qt6Ο@ȗG8N2Ѝcb2=s4Cv8{ IHI|S@I@$w܀;R6i'} S{-ug󜲊Blwr.n}dz-‰iK鑾C-`׷Yx:'5+Gr _~H9Y(*  ]\"BA 6Cj%lepPA9.;$ksCdHCF#d} WY'6CFX;uhj'i Pg $p aN N{ sL~ k?7@B]Rwjz}TcwEŮbZ0f!hC o/.G_v'4^]7e2%12͚qF*[:RHÁSnqR!E*ki5oũĬ33yx#>u;xcIJ=夷3r*jS9}OV^pvנkw)˝ï_}NT%3܃(pKE/n%0@԰ HMD#'uG2 oJ32F~$T# ȿp&d>s15 xw±eq-އ{R6hAօΠ;UA"C?l 0Nj[Ddk" Y-E}0(-El} ]-!CVjU֟k[p_|a''C:g!aUdY.!\ev|F״]'#(%ϢBq:G߭G%51d%i݀uQ6TRFyydrEjK6:ڼLl @ ){L HXZy:T:\n\a"DϤ];p;_?\nymaIF '"qF,zJrxgUB͖~H[K.x>~_CmQqnK8 ]~JdAZDIy<!gh 솮X%L+.g\*3˼ .JXO ݺi#@h?'n ׈z$A4"#6df%vXz_plxbvjCSx|^ g~A4n2C!Zi~{>[.4,kݠНE{gR&7f=ܦQCk%]dQvp p5 0EhR#K1Pn! (ˬAU+W~Ъg=8 #K񌈸xuqrw ~}0R$ ʽ+ nmoΚuiҟ`<0,eD38J ΅C>Xf˽{7i38 P! ڄS Wݒ{%xD`ѿGse5iw)XAi%nM!t˙H#"!}$;CL)҈jɚ ^PPtXR$qkҶ Iu)MTpcwf(yZ01 rvp0 -y ]u< 94ύO%8F֤ d]j3"=e@ kL;4hg4dۯs3#̞$81*rx`O g]9q з|}' +=mVan_$/<3cTIdiB!Z1&WW@A<ɡJcqG1@,5t8dvX?tFSPPuSЎf&P9'W GnelxǜG{B@IDAThدaSymϣ'z>KthӤSWf9Oïza| (TAZD7!+.}1IBʾ*yT(haqвXc-yc^e$+6 :!4SCF[}p &W3^Ir\Y]|ndG6B}>(f8M"$DAx׸whz?bn]+p ss*ryfe7Z܌^O=kzv\F'iKbbYxn9+z YKp&V{Z[vCs7LvM|FfgKv~"N\t)~٭UptuKˁ1`O 2XQLi9ޘ9!4 ,d-*o>6)>xJkrHOBf̷DEuG>D"]jQ }yO CH*Gص^e 5ĺ8ڣ;J0KcIx?$wq. &N6C~3jbyA$: OA8ۺRIfVŬbHMXJpYְ vPElS&m!@]&w0^`G\)AD)C V^>K0T/}6厜65± dmGZ#m] @Ē\1k%]7}ΜEu|;5<䑋ZF$Ճjz0hh-bڐ` f+-+;*D,أ$\ؼ 5FC FFA6mgtOJ%"(tԙ= RoƤ[!bQJy].b_`U4O=M>NVp)2-0fVlQ\v7CCΟ^됲t{(3 jQ-W'e9 D".ކj!D}}x4|Њ>giQ3&%+_Οw?TXDQq k#?$%!Ԛ<ڃjs{0hh-b1XL`lRP2!>0SD#@eȏqǣ[4!,GxRfhMW*?fA!`_K {p{Nki3+64_UK%OΟfGE72+*#ZՁq2Fhɔ-I,'f]I#p"4,f |qlgpߧh@}t铼 \]z ?; Dv٢Δiq ~xH̃OCSL꿊S• DXMO _9 ׹kB qi 0"W^p!,{ 5vOm[H\.T:H QǸ ߞR;yr8  %st)zvKZ^w!w%\_"R5&O8bA,e>|(sO#N)_賶OPS0"=Ο"W?S ka0`p2 DIOof@ɤuV1P@e '%}4oW3 eD="@+V^kV*mE_ƾמFq oj?OL2T@_ɗd2ˌ*hY xV{ঊM#WӤzA;Zd@$R"TҿX[؂fDmJK#4 cR& ;C'7[]ăб>NYܫ:HY87Y©M[Mރރk<>F.y/bI#iQF &%l"J G`0Thu X^+WXъ"/P}a8uZ= Risv]IIJ6I-B-lcs|1}TEp@.:4yN (V])Rl@r&BrF5!Y:hB"-AԢZDjJmb 5t*`sMU /pL! o"<}{˳)03~B1\'񄷳,=@"UNJecYI!xr+ NV-nU&ф-FAC !lLdT>+j{HIY$˵LJT-s%s-9Z9Zhi`偗JmBGƆf`r%쏌r0Nh agPxF:J2 [t:ODlN,&tuQ,Kg3Cti aՏc'O G (A/A³2xuތnefKK(-Aɡ58آ6Wo+IV .|c~ q3/ \)C]~zV6ZJfo2;`%)/ E$qJ`8`'%s"m2 3 'L1#n?:~4ۣ7 ]jIY\Eܻ%D:cXaBS/35JJa6Alg Dž\xf+xJ]:(fYB&%&9k#-xmʺ Kx0 VʁnUY>G'_q%HTvE@-Vv*J)Osۙ!w;Xow$g_mh3+K7˓[銣1!C34 b+N3P>Afp+fdu C2"˝E5ljQMZ{&#f`0MGY@:ż"lbzM(${HC W624J5hdG*H:Ԑ]vLP^8-;,`TVrL nFԝkU q?J1[A{F%{\"e$0C%?Yr~QG{&[-{RnT}Nص_4Mәs̽GqG Bc;R[as {?{osKr݇-o7 g2Mh BN$Ec) "qYP%+A$p1`%[%3HeX)Y&E-}̼ymw9U]U:]}{޻_9w6|F#Nv1 =p8? w +8 ̲n(3' 2H : 8ظUz Ա{xϙW |U @0-IcGԧ\R$B >>&M~.>\WZ B*MIO䷌@ 27q:voC;Uvi׈](]<K_!>MԊFvU1esSu!_?Y|}?8gCVɋ$H"ĠE-{X=&Yu300qA>"D~:bJF)YC_g>Z?[AtvtDhl"@ĨͰoT+=yrY : 6Y*F M+7ɴ"MقGQ*>ӼwN|amQ<,G,zmM״<ħ7/2P$WBǭ Q_._ kD^~BEGU82gUƨp*NU=pCA6`}S/|x/eT,[ a BM D_|o^SAs `+4W#VG G8MEX4o|xCUE3tObiv J_|tvl|7ռU.1S*͞cg.qqqe[._ oV<sP_P{?e z" 6W֋7]xV:,s/@hdS-u9RK%b|P&b Am% "UjG^Ue2RuF6s0]=%b;Ux4PSzsW-F(i☫}#t+P\oi'MW9atNHT =;3&p=޾A@n'dH?pN# +~?H?}hohCg()MYGk s$ i41Sf, a<&!$i#~d!bЬҶ$[k;Ҳ v$ƿc!xyn}>Ei7ĵQF@.BuC1sb'UY MvŞ|4#5P aGZ?ݯN R^n׺0z x ggcg$SR,ʖOH͇g ?Lyx,t+Wb,@˖*x۩g rs) ) @.P+9 'm-g}ѻAa^3DN^RyZ2'T)@ wDxu 4aǏݐRx.BΛ F\aŰ ?/._˦\DL>>Vpr2_Krj"6w:tXu``~2ҫW ~؆%c݀ 6WO;8`>P( f 8"{+v/5mj$pl":š}٨&KgDN!/3rGDЈT[NBW5amGZf]Nx˩sRJ 0q6dNEX YB ޅ5ܻf^ތ3A#&F-^:羴?7GHxcR:|;_pKnYve!jg |)Nʺ"8~j8Le}2mmW3k7HDR5)rqDMUQAFl MX[;^xO@%I8ñmۼ\w-wrƾI"8(r+tTMC;~I8ao?v˸؁eaKuG\-:?p)W=fʏ++gv[>f'Ow~[O_dvi0YPgZ%[J;i@87wl>l_86)GT*3(Ո-PxrZO:/9إ9.lP9gNryDЈT tҎ/Dd-(bp`;v;B`e3Z,;X } N}0ϼj-`vew{UT&_Q< 3g?~[>FI>Fų/u=^)>#.Y{?oY{C}o0sasdڡ{Ixu"4@o$d95Y ~h [-vy~йRүwݛ04,5`'4|،D(x < r4¥*TI XUį 2Ǝ?TRib3p9bdK 'f+A#S>#mm>Vvޑ`UP.Ym?m >^+Xt򱬾߀? LKpRs'G;?Tܳ>_=fjl>OoU/W:]$Y$7B3Vp7 =Q4 #X;)޽_܇Om5>5epFT!3FQ@'[&HšS/ϦHa+dDdCcB߇Ф$?ަoT xE}2e<^•>tZ!c>x ^x8g\|q5#x ?cǵ$5 ]~xpC"~f{xL!ϱ '1Qkb4ƫL $YH/YO^lKM Q'6W}k xu:tmG@e,)Ό"\$⁨>$3vf81;82A6uCoP3iKcӡCŰ`X,g؇wKб0:m gu8IXsRVc+'Ywy:+;?c XLH[V>U<67ɛA4`d'.}xXl&lB3j꙾V!B;,JR3qrxyp? LAy!esy]ѻdօ%Dl̙ #BP:hmrc:QaSſp+oIyp1˄IN¹݃\P\yw~o{Y*Ţ3uh~~*ɞ*|p:wAA(B~ ~ɍ/O>w L V=u5ƪa^ EWpmÓ 9dQgIi),': 93A庝-:|{ > `+UvpGBCG3UO5KA#OM12h-e!P_IЁJ%-IK}tq{p}\*kDYa =ŷw~-ן+Ƹb捗Ç >ܹg%rQ*'>Q=oQ=ZtF0նw K4 ř' )J;O-&*X]_ 4mn獍ӍbǏɻ>ʶxJ;uMHi+,'Z 1qrCx$k5*sLԩK?*3}q4cRB y޽a{ d/1wOwƸ8y(9DC8Ao-|3qS_&i6ʟ bY9~ т +5ZE ~IC`8YRt\آ@^3휙BM;"}nYc\Hp sNahü/煴gՉ rsML_⹋O{ETsSk=OZPͳh:qҏjqv)F“VԽp8L@mR 32ʎׇݳ^+5\ImTB2"׬P$ZQXx- ,k4<ƾYIqH߈k02ISԟ^}h)yx}rZA$$L8 ثsoep"LBluOs:_92ǫ7`P L7y}Tkk/ۋL-lhW5#](Vxp~xF5<{@ᄪ4hxHPE_ti0HM= TfAŠfLKL-?8ןeCSye>VT,Qahţ{b}s 蟀_ƫ7 ][?l\@K1ܣ&*.UL6Savl" dUj;gܧB' ~&˷=u84ލݫf`1L^?@YWqќ ثv Ǿmj |̄=ޏ4~&~ .8 ǽ6IN,3w;aǍPi'KT#Aa9"i\c3pp*&Փ`@2p*%ř m Ce2O^6b>8bc&a9WN.w{[ nó`?xkOK-J .(]r|-)<>x 8? Lh)g629Ʊ Z JuiZD+!*&Փ`@2pde©`=v" 26qꔄ\Q EAc@uOPf%0G|y]o=Dؼq{ς xT;31rM]Y$s{>uȆk(ݶ8k;g2`lg l]xd˰O#*&UERU A *5-0>uMqݽHW"7~ T+Zh  /p+uH|` ?r:~XV~z^qe%nɁkU={ΟHy6öda#F>9&׹ "N^Mpu.:R;nq9ܖGa!a!|RD -dnjͮ>PhwY\͚B; `[O9CvJ"Jt|n+Ďtbf% 3 o &UiF^%Vb쑐T?aGXSrAV^XmB]ps} oxmQ˝;$dmQ @Cur_]_ÆqaKIˁ;8rk{Dqڈ)%a΄'`1nB1j / 2 # ,+mrL`T3W th(ĉx{ T3 _pEp7otP\*Szڈ~˟h󵿦3^gvM+jc"9~u,V“aQ}*ף=©$#k L e`X6 4aKI" ;@bchPdp>/Bn3Lr7#!0$X*(ȱb 㿏f!Y{B oU3.ၦy)>6'|7B(lеe< r>/̠,X^Vf*g`q8 o:"dȀ\=Ʊ41xwn-<㩅-Ῡw5w |S'0?s_`wa~Nf*_y+ q=i~:87acZ˵qPt>jx,Pd ƒF1Xb{L/ gu9\qXL|iUM".ŨFDn[\@;6Y|yEЬX3ؽkD6.F̆]4(h7AߏsmyP0O+B93  8mޑL e`X{ZRdOU3}xGg3LbL PHK{P_`@Ž4_ ` e-h ݱZ>a?&+;,]W'M V&+IPEZe,s, mT#J)G,dLy-3A9 (KǛ9{X3ͿEWaļ] ;7@!dv_Y%M޿Qz p\n`At۵ߴB: |3gVOL`Z4HN1bH$KN, Fl@2pΤ3x8xV&ay#>]# d< i'\cօ7b>1o8T6m \郅F"k 7:ZgZ!l~%^6L2_eɒʓ Y8b2S^5VkAhfU( X\oaK֚.:faGꊻ0*HǤwb\݁7: !xj<} ߅ gxqe c5&]b%d[H@0PLlޥLif7^2ʭ6ˁWEpdIgDUaLF8<ִ5kx+xn^B'-ly 4=7`چXk ys Cm0 'N6?/g˛e 4 2XHֱ@2pԬӺQ+, -Xe :aCΔy9&TvrwR rmCwk3.4~a28 q#sR!LpUi]Ƙ\P$a zQogE WK&&W'F~(m>.ѬmCV:/5pTb sJu|@wk&03М%d?FB4 M}f4 o#;X9e"Yǒ[IhGUL.&)謫*:u- (\_+F/3ij[Xfc? DuwjR@"O& ^FlᑖظLm udBd4[gL3- XũLYAV/lҙ q(4z}Usc^/uNT,V ڟɺIؐύ60x>{ļORPXrZ F[3q-Ӊ<;ZPW2MTrb`²J$- 1 -NeY9aC& q~#D6>wҋx~;.=|=8`-hnjͮa@W o޴ݵbc-N"bEug*| [.z'r^dL9[9R"~UKBScګ@KՄBk硭Lzg3{=8Tv[h_MO+`5]C^ÖQ^e ;\=ekd\ cd=e5P:)E `F ;+x^I\tQp(AvQd#$dw3i`)yъ5vRp ,mnq[Fm]%Ur2Xl(HJ9+(HEG}!- Rӈx_ 81`< 3x^.:mBV>?5)Pi} lOt@@D@VW.hq30$E6V$N"M}1LE_aK֨DQRɅ֘?k-4 =/{Q2+g0|j4WǸDzAoxFx3X}lluWX0.\eAJ8 " Qu u~,pHʕebbo#|(~ =]ҟrBEf#$Xf- 6(-W7;Ra5ʏcE󂔙?w5n*[~](4&նA` N;݅;eT'q8Rue򉔼 켜dN9I),q|tD`i*ә¬_(ϷgseA*WD#1Ȍk Ŗ55|N~3?h[󉀦>Qz¾ QL~rB8l6++|Dd'j.[ gꩄy"NәX)F%w;kL#cbA:کH6>/ j.ksR`NvԬÄABWl\˟mpp};y,o~+͚+@jSJE%$LڛpL=C]bsCB-"i' d 2g$iq+14?<*;^9 Ҙ70@<9jMpvd6[|m#6ʙx%+U@%GQb49++:ɛnOʼn+H(r[.@2cG 2 2g$iq+QZGCj@5y0v9isds+2&;`-ۡvSkHvw DŽ4, ,S :*@$;㠌im&c6l]=h^3Q8FQXYV蔃(' HۻpI=B `GkUmpWn.~).MDW+~0"[{>3~AVy7mAgWU+bܭ{F*%?_:~Tq.,X='x-$5P/I=,]1?;|gf?,F6Ч͇03vfB5~B_g#L:I@2q)P)Ru i>G汗(v׊0+/c>%긠Xd ō3ޠцhsd]wK 9PIGj֜JTB 3y@Bf8W_6Q+6ymS$ٗKӡ1Vco;- |W$>S@VaW "0:Zϗ4BQK1T\pj5&_ls=fy*Awg0 07Awr+kq`wjn5GI(_=4 <𫡊Tae1:~B/!1!#CgbbJa)1HSVM : FaΔhFP^Ղ Mz1(P F/wXL-05>X]9YAF++ٍ h`vMl@J1E*C)4*\D"lD Ti !XR*3xԺ_Ŧ3 FaZ@j'6*}nwu`n{ y߃S[k`fէa л9$i`o[lx,9_GSRM%*J\c٩E+. `VF'lC5ݺ㔫LypR(b vN-x^pyιbu3ӍgB [hO')QֳaT܄W1a^Er<#?Т t^-u9L)]U"KeY\cnmx p=ċΓYsiD)NV_xEM;#8p?a~^mWLF䙎XoEMk|#AFޚ|M5Ic4fgaFHJ)Axu(xeuQt=N0 S2K YF|9k NvYW kw3˶ d.P\+zýi6t;Jǭ`E hWYٯS!rY68!e=TXV7)p ;>q-`,e*DB y3b^"n]^ӯ)6S* tw2C ;">բ+~Rto"V: @EοԴ؇QvEjPY!l˱+KWí[F* LF@&au{Sjd>̤11ԫS! p0"c$0l5%ml-Qp ֧sS5u`"VP"\;}vv\GFLriym嫁v|%MOim& y(8 k&ΠrNT9}[ |\<Dc 𔍖5>X8u)U\#Ñ([:9 jȵ~8lMDrز#PH& sW-m_S]eCU &BN(ȋT*&cY5_Wm$8X(ïSvunbƥx> t@|4E~ p7~plH)LYn)b5ۉ^"3_K'\ [M <m?0M5QX!(]F),jiF۪Xxnd-b+爹65xӢ=_T~4;00W !<]'ϱ؈cUNb* rX|R HPu`ω^"3%NH9& 2vA:aQk]hiM6f58vR߇y8x<}Xmfyk,WJ&.tOZ& .m) ?% #F*;~`!ĩ\Ƣ2cƿgW()"/3Hҟ6M8>|0+oY`1D_߻_^ XMb#L TcV8!;~t'Re ^@󍑌<;J$W()"EF,(F$?0a_ĭEsrS>&[@G>ǜtsy`muy kdl5@l)eև+RCU"3n M1sB)t!iMU ɢ|F҈EټYi?WSKj,n+$ ٷGM^We{̱{_&sT% U1%X 7T"5Up|;^`h$!%őªսO<]ڲ TVL))`(J Twn\5M8Π$cR^IdB5JXa~Wx$(VJ%OmRۆemP @8~,} ?B|'!\/N:7U?jҫS뷇Ví©Ui˒HeSO *`0tIq()becnb U], ȱp@<Ԟ]fwrDb6559ykw=M&(1#Tф?#EbBP+D7X1,L[55/zkUCe3&jX)U@rs+#;{@cyvZ,X o,8xO&W%7 Y 9m @Uh4Ꮻb7iVPcVĠ4'3L 0&yuWPW - Hayc?N)pF9-NA pמcJx k~ju߲|8x7`_4k %vÿ-jM7^$1D eger-PRmwWY`w*2CQHCe25oZJ eNv  kPbhp)DrYhKEo$eBe&Aa!;Gd:9G N\: D8R6* `Àӄs/F)!V*3r[ +V5y4na F >RŬvuR (=~X6[ͭa82;HeY j!(ɦ)4撂Ȅa9[lDzHŞR͌{ Aw 8YjY\#e/d ܭu|]PWWw6:2gQޱQ KP * T&"xRD& dž5I.UncH'"$YWXv_9@]p s w&:-+EھZeaՒ0h5v_-!es"T, z=<&6ס^$\&L9.RJ>QR*q N9XRTXLZ[plb\P~̴~( ֮\;~5_( @R<@!4`p5 _0dI7DQg3c̄4 Wj*b()`e(' *[ez!j(3* ntCۅ@Evkૢ͸-@{u'[\ |ǝ?6`e#3б-6u?cB9"'eQh̊5TzM1IQRV$*X)u [ ÿ\_bR§~ v䩵I (;Gq7u72V; xUF*=W*e)P!celENJkST 5FU&#-6y9AXNmUn'l(S߉U8r&H(ԝWⱢʀXTg V0HoجQo!`@>_9˳&=w1臉 49BvVzE3U2;22D,T+̌'x* Hez<j8,5#E<tcuv䡾?g@<^"HTL.@{5d_4K7xnF af"kTǃ9uSz(8>o`dolE pO}%m)3LDQkX< TLMƠ, X&\9mC]ƭaYvZM–$ġ]&Ue^$YfO'l,\w{-e:]cؑ+ZrIj$;zbB}`T. \8䫀uAVwhhjlֈ,&qUN)T *3iUR"@28|ǏAmBT,s 03Gpw'bkً]`T 3,=| iC96DIH(=8EGaR t:()нu,m25ox`9`ssMa;ȭ%ĵp/B;(7RN&1d8X-qY-hSfe&n+%!}i%?/?g"cY0Gb*T!oEK^`/Ta  M~wtw-Z?}KpM-[_?qͳb3kMCp/3cP 0_7I<ǏpSD%T鶼威vyRf}I ۤ1. ǵ\ 9* 9~a 0T}v1dCbfQ V@+DIF%`ҞR3WE*SjZ\(w46Zf؜GX %3"5^D-kIj yKR඘j`Y}c&AqwL%Z0P7zኀL t1Z*mfó}G1 @⤀-E ,ElIHp?Y4 6l7`  /]^.Y %M^tƙ9 'A#5(V:^5`/7Zy 75јJ#p{&IA:NmdUU2fI6>ctN;G' "QP]EK/m'.!P]{A(+#\w^ ɮZF.Ѵ&@L0xsX4ˈm(Qh`:<$)N JR4^&u,ܪU&Xs>I38C?Dv(v>^-P Ejc4LZ3 kw 6NZq,Hc @\&mr]W'A -GDU,ib LcfyiMh&VAn[P;qGx R\)L:y-/:nx͆3` BZ݄o;_Esm{?)>4Zٍd#f}aA|$6 P5\C 8q* Ja Miq)!IV(J xJM;)Vȝ `o`)7"IG<n'ҧD U@X 0nĠA[!Qۙw*S)c ըT+McRdMǟHҎ`@F6@]ۂ\ǚ -3ӁsMm @;VlV'e4=R (nЁ8qkynnUTRJ˪HeJMB>[r.R8$u灦o  3&4D05vPU;੃Q76p5ll\eg~[fj,G7,n0#JHb2[@$EI`inu,w#̍UxP8y ?TlvT{kK˵5sS?]\{_m2¦K oJ+ιP5j/ߒ@jFd$Q[P8@3=SItR&u,UETNKlqe'Ō'Hņ(']U\4}vصѷ[Wqd:yr ¬+ 8ÉKn2ǣ]'f`6M`e\لr\;&Hq%ZhS@V I $g0\S@İAc  'k0f-I dGC1RmT̀ zE%ucxQu:7v2U+a( OU]HrėʴrvpL! G ڒZʞH4#񪑖yk3ItħųڄNp-!,YxldذQߊLcJwSZ TWNlRO8$E'EI&yg0 #tBY pl Pͷ3<έOlr`g! OIJkǰ1) BNr&}Ϯe 6VQX[] LՕ0H@݉Ӝ5KNq4Q Ttp$HNMop1qʳ=y3chAdXSmyGY(koxEBR؈??[L LyQ9u9A@LZʗ.bZ4kiV &G[!J/IQR -t1p B&TevERs?e6Ρ5ԳZہsUot#\[Y$[Y$ԘWdԸP W@Scx~ !aEe?V([n[YɴAM1'`U)weS"IVEmĘGl#I<]Y _1!Ư=S60\_m1vptqE|/ ]^&ldд;~Y 9BSY^G#@ūf(f#)N 4+8V!,n{Vsһ}vTt^0Kٔ|M Ok@;aeSB,y®9p&-X]s^p;= 7bÓkf{EJ6&Z̔@ RzW Fj $ lK͵?<NoO"b:ʎ2E*96s0 "VԴ@K HɓVs9ז 0]ӱr}d&xv ZېcK'u'MqJ]1Jڿ@;ڼ= S$8ɓ _^lhAo>az\= gr]FQ`#COR#F*P@RR\)Jt1F8$a>Ou`靲̀+WBOR hag'mK+B6%jdZH^S7:+=9GŹ{O? oq&muE38_19CθDJ!zR3R jJ5V8SOE3oa\s`8ǽkW)_|IP_8"`rjese^ şE-myɫstn)&}?N~qi T6vxr2prӿjp59zOXd>A R\ jJMʔd@x+gMսX}~ }zv MԟV"eF)9t*tA,{^G 8'i C$MH+yt,ujvӃ9xSGI&u.0 KY7RԆ4A3OWklwfL{ᕽu;8(8X8 s: R j'2,R$ l͕q cGU u3WZֲ;jޅ+y+Z];ŒWGOl.a؜q)=8e!eo5ạO;8;(VW|)h 'o_fګs~}p=8[ w >jI4Zf@ 3;yomGri|*-v\F7!]ٹXrixD5"T?p%jZMi δ)c:-ΕNE7iDEANGş?Dqڍⱻ? FOa.UMoF6(l&d[`*q]/a݂->R=[0\eT2J{Rj uD:#x[~q=cGnq&\H&M f/iǕ a?k/nwe޿2e,~@$)Ju49̭"f픅.dY8YVI#LYpq}[2wo_qfVס9)fP@j]kL =` N5Ѝ =MJx|36;A;WU>ޑ9/n'.?[șjߖ&i[sJ6s^5|YƖ4u}|ϯ| '6N<28 S[g[k0(pwفPk@ MH#zj5:‹4K \Pjyc)q[bn\W⺆R@+t]О+o~ CxU`·A6~.elsٯz_0|ay̺>9d?ʼn—ki^E3GO[ .nϝqMS0_0H;~| ?({:$\cW6FTGĀ+?}wgzoli^An})!qQeZW]?Խ?PnqWǏ¹[5fvU'jw N/'5b:QJtȞA8i R)*z>\[(QpA J]DqMHk8/>FǗpU?g>p>v=EH4Sdp."! Ҽr>9d0EQCki^MV?vo|wy)|`>kakd~=Qtu: `2osNJvfVR?wo@=".4伦R6A6Oq^*큀R:y^{o\LcW$(ŧ_}b~W/}5&îm)qQ24Cٵw_^|^8^>y|(|}>S0H؆A|[5 ۘ+n#:=ۊɶLw x 0\)T1*.㶼+@9>7>vʊE;yȎ^:OM_>?/.}Ut9%9/,cKjsa'?|A¬r t{80W͚__ۀ|5t1mx):6/Õ\ٯZ[vޘ8/paL=!,\+!pۇءSfye ^VWM/n_/ o>YvKZM#8眒',gK:@oOV]^, A@-6eַ:d @` f)^\ E*ko.M NttK=wBg܁;w9~[Yx ގxo͸`exK^}O~mT#B44H %JCUҨ)yFEUt>Wzηo,}u~})=>tӦ`l41џO(+_/ jNLkQl2"f@Zy%X[,|NbC<[`6: p jC&LYCΟ<?\:## iEu>f-bFB&ّ,d!BrjCG}X:}Q|/v(z?L?<:7~@kṀz߀ wx[|_$e'"ɓttfWhJOR?M}1NZŠɲ7\S1ɱ;)8`}=rCoG ܅FրLkx:VWjov!);wI|BGڐtN=I,|OCZ+u0%- IDATk]đs%|{睛gw(  xv^$ta7o|kg?3xyu= M˱uI|BGڐV3->&Ɏii . *AQ٘oΤYiR8sVݾn!p LDxnO= ;~o3/Y]vx)wz9%FZH'9*R%-UӅ!iԔ$6K'MO0Mx2p`\G6t޺5~u #Ⱦ.sWxup0~a7~~ __y޿@FTP܄?-Vӗ,ldRiSvηw}d[y{fznX讕 t]r7d-M%OS#_H!xPl6 8G#ivgg{XnI=/f@<\ \ZOx?Q,~vx߿9N^?vhzYcL5Cy.95}h8V@6 eZ>)V%pymqsxK+?|ν$$ni[ Ͻ?;wg2|yE,Ev}1p:{_ǟm_&3MJ+]#ai_MKӷSJR߿o闻'~\y~|qgᝄon=<:Z? a80 8~i x?]0Ux\]p}y z5 ߙ]Cfx}quqfxuraxpp>ju.mK\wp q!@8]IQt]u? hXz-)^k ۶NC+Zv9(CH+Xc}Zm8Ϊiɜ5\<\MRzAזlfjXz-cLZXO/Og-[?jHxx9y>6fdL8UpV0k;5B8% }P윢eb յCnxb ѣekڧ1pKaOG@4!-f^DkZէx'*Ր:-XVKA5kjи&BkZ6ͫvX/$ԍ0k1T'D(iq{9hrT>"pfܶ^Sn=m55Kxh\p5=H}PvsIx,nO$\ԳỨIrhl*_Nd{Qmc=DqzY~|\/CyXF!ZhEdb5_wQ+)u99n_Q^TxQ|R^F_AշYp 5Yf}P!o& ^iLX5ZakFjrԌcܼpjQ#67ھ<:)suemh c& x7 /iT#‘nSOZ\[ ^=Gx%NK=js­eqFKhl]wV|E+G/ "c\pz?j<)sG93K`bZp{ ,ZIQ ?=ry%_['t=Ex%NK=Y/ n@{p&bn X5 NQ+ƈr}{85MԎ[d.cϭw5> yy {6=ͭ)jH(iO鍌%pA9NGr^RikkY[x<⧗[?5 -x"WZ1_;{xszx'Q[C#t7}S.ֺL<;>&5e-ϣCidH 7OFJy9 ~+K;A[ƊQzX!NK^p{qðӫΓL[t FLHHcxp:9>zGu29'ns+! 91&`L 0&`L 0&`L 0&`L 0&`L 0&`L 0&`L 0&`L 0&`L 0&`L 0&`L H,?WINIENDB`ic05 ARGB~{؅~{Շԑևӑvs܅.ݥ-:9zx프%Ky͍[-54ݍϋύUU $"  ,hӨg+   ɶ ƒ Ց ɑ ̑ ֑ ֑ ϑȑ ՏNTdбdPOOWAbdd`:wXQIStrqXOdcas}SUf[oopqplexmWhdba`^qV@R|lmnop_^n~dba_^\f}OSumldcb`reOLNPSbikkjimlfedb^XUPNOMijjiihgfedcb`_sNUxxh ggfedcba_igUfggffeedcba`^q\Ve ddcbaa`_]xTQc bba`_^]\yPQbba`__^]\[tNKf``_^]]\[]mK+_xtonppttqY& )BKRZ]__[XQJ@*İ ⮡ 讪 ۦ 孑 ޺ ݻ ᰑ ֦ ݮɩnhμ}vɻʺӔȻàЬǻԀɼ˳¿Ā ɽʀ ŸNþK QMMKtl fqH9'/ snI5$l mT=% h InW>&>, IuzqcO9" 6- #NYZQA.K HAB;/ U 3*% TI:t a4C!OrBHB.QeG PKGΏG*WD ~QGTƤQG *Uq.;Q.qr-P7 C 4YruF:ikji7*IJG! mM Y!9?5()'G 2V ; X  ;R  6F - HGA4.)&*+131   ic08PNG  IHDR\rfsRGB@IDATxeGu&|^ܓF3&(H$1do{]w&'cl`X%$Gh49OwO}­^fnͼU9UNխ[Hr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @nr -[ @n,P!iZ/IwmL7 t) ސp6u7qo[!OJI6wKpY wYKuy-@Zg6ސJU~x寪ØEx1>Ke9[y;|9~YR=BClKrӅc86KZ5>&;W1Lڔd KC.|P@*/ %r;Vɛv1ZQ9JW1ZǼZrX~+[ЯiW$Z^:殕r[)X*z2: vq@`vvHI.tT,;b{HoJK,Z >"""'(=aߤC26 OCl_F4n >r rTrk]{Oۿ, c 05ji#+N_yT:ϓBb Mָ1^7T4ԇer`wdN𳕂Knr G6Z0 rbD(/,]s,Yi:n.Ђvt9O|:%B갎!_8F}@*/jܜX w/Ӆ^Yo6.{,?RxX-hUALh2<Oe8ꤜq1>6zsۍ0YoGzf1䴣k V.'_SJu pQ3K+_-Rn;ײ9`ۦjxb78PG^#vۥP^co!9ND{:\.'Zv=!3++4X'sѳ@3Kr!p]d.dk2Y{ٟI7!Kf@E> F0~c>ILab)Tij)#AZrm~SG :Mt_I/Lp>as +7)ՀבiT(JȂSJsq>]jCHm) ' ڋ+7<8F'p[_.W.AH:i( YiG~$u3028/r]/3'fb5i/goe5.8&^~Pn/@G hhOq<#P0fJ zouh l/d+uŲ.K*''q 8]>/ 9/,;BYuǥX9 X &!#2e>k)I#9PO;'@XwJJl#ʇg~_nݮ|pIG8RmN30;wʢI9K01~hX@CqswN@{~ l'PK9n3Jյ25uG@<;ہ7EB4wGȮ;?'ҩ{~ݥ &@4ҍ;u眡wG1#o\9 ثN]FL x~8АJ2Czrn.=S38W" 'V9AㆪdWY{ hѧe8\L7e#XGwaOOg92)$# P^ & &sD5}n:aOa\.tVNm LԒfVp,igw,尀{ E28>5@g哎SAL;`ҠF `-T~@]סpSg[+[-.-s$ZދBW担XG@∞ıo:=UOx%y0|q\j? `ar`cq8oH&4 z0ҚO"i'Lp 6)] rB: Z/ҳk {}r[Howef_sQ-pYHl}y3?iVy{Y'уVԉKz9ޞq6{W'=(M:* K'[3*aҶQ_ P?ʶuĝOGsB%bR۩0kh֌fY꫌ V_Yrr@Ͻ9 H^ >=~e:,= p-x(0u_xA>L;?z9 ."j[1kt 'sZ;;+?О,f(MH{Kr絺\HP22^rgcE&uVu&Z4 J]iUQXPУ[Ө"ǰ^`9xdt/X%wX&*2V 81wlPk43g_X@f2yq|3z󔠂{ˤy? _bЊbT5B\@P@~UaZmp@=Pnwg/?urg%Bb a-W{wA+b9Hlҁgk#A ?biT P:ۅ|BWIPa24 u2JMmdi3GLl9S6>x|2Μ nkV#/~xL,[;u082ˀk?Tq*IW=rR`17Km=K+h,_tKu2'E}߀#N9dɚߔv8/X>$SlXW-hTrSx@>@oL0"x ZÆ D=/ {cڦ/p V * mojUqJ:Dڌp zpófy4p~LpFYdB- W2!5M2)^<̢/sÒؕw,h`<9`s(,=81o9 CT1?;&Lsa i:_KIn P!<Gd>W8:)[o:[z*(m)jN8, Ja,<ݱP, :<9ֆs,V!{8ifdןq ئov b`O:6*A:cO6ްL{j8-OrpKE|G$}Ik,zfkO?^ LieXH/~1Y'44#^vrhn֓߂^)#>ELQ?ֹȼ|2r(W'y0,ٲ@C~- XqdN. '@6 g{t&#|ytyQ~3 xcO@GO<?i<881uzqjpרVe# y0-;4 ?[}0oriFK#80U]w"Kp^j @(p<^_G5fˣ:f3:{WdNv1?hF^O\O'yr,X`*֤e.'`$0AfɋxX$ !Lhvkq=u64򟑱qZB=UϋdQhA< F_ Xqdĝ@ע˥1J:TǧnLVM9߭q| W4 #8 [.Dl -88wlS@F^c|ӳza ),m(QkQ(x;;sL"|i\GDt\t:U8 0 Wk? &}D"s$<v6C >V|<b_֩F܀6 L_yמ 8P_O xN{{-  VZ0 @C7 Mf,90*Gtyr 4.oH[)c^Ch#ON؟ ~'t 1'@i1Z(Q w`ve?bcN!8 t9I8^[y蓁Y|Zojzw,ƜhnTv@kHY0;:fߑx,~T:"܂@;&__lU!YzTy3ӹOERX̌gNhj453h-gY%C J+˞?pڴkQCmdG/΄((qLlM3lA~ *uPt\[:q^§d~r03ERp'ځcEr.ƽJxԥwwßC((k џ]x4cmtc|pn)g<rpSFYqQ`L0˝ "6EWcuM?`-pN<1Gƛ 1>dy~Bvf;ü8LbII8i\Ӡ9f27A~I;G ЉC: 8Fm'pul{ klG)LV3޽8UCLs´,"pHtf6@ȝ3P:A\|~[jG X ~<'k\=hZnVjx;tSvb1ЕG'@&5$ b[ZACsO..W) 89Z 1ĭ: uqr .OD(icR=j2&״12JIr F8 YT#,mF%.$C "h!@A : 8B89-΂?#"q b׻/]2.Pm4iFQy:zK,4{-"&~Ã(+ήzq`G |Ϟ3? xR7!0mo i_FHK]ёKGu$E+IT*?'LbLb)d^|/n'%0#Np 7i~_=?G⫎}TFecͤ]'cgYOy[v#7+?ebA("ah4j0="s"N?٢ݧq:n8fXgu ٻ!$FgZ'F "@qWo?@&Lzt}#!s2ƅa8ڥTpSNZ/߃?L%<U~u$etAg121 L#6:\:8*nUqG $֏QSM%'L20g|i Tf@ZD{~ʻX^ cU 4V&RaY~ P]c&Χ  8gahƭS0t;,toJN<ѡ/p,;ñdѤwaq7ݟ3 GqN)#D :~8}I6)hY!Y9rTO'r1szy̢AZud%u(sOuym HdzL^)npk8xȭgg=x4 .3b: @D'yϭx$QA p0x+?gkF$3G I9SA Ue3mH;lTlLTٌhOab0*3ۋq >=[6Ae X)O RB? -X89P|0|cq0⮞Xt Ϗu`?dF2`'<9M `KOZ<Бa 917aN> x&II@"@qt s@&q#m GC9*8Y)L4W^_ P(q Tm!C|I(rLRW0,Шc'*|׆`w mbt@=G@Iڐ)L4E Ӷ@m@&a VCO!]Ry@S`QYy&riU-_kT2<*-1|מu H3e x*?H-;,%_ ޕطG lz]<+-ӀU 0 4 V7"Bx \oeX1!< hr'r;ey%L^GN+Oy=PڹGgbjY2 F˭2KXMcv=e :4GvVӓG4%rSZN^qC2 HɐʭTO_CFҷ/5'Pf`hY"qg26Wzw Xcz&:w;*-S|S't Ym)gsA79|L;'G5KƟ.VP3IZ]mX w30ZȥXtk2oƯKmzK5<OGe{oOsyG7p#Kld @Ysfq1$ce@IbxW_+d =bm& D0".!8N )2F(6͞o H'ׁnz#Pй?z]C`^zCr MyFE[>Gy:9yY:fBjg2Wݩ*4_>rL,;Xm|ۓ,{_n{9VI[@nv-Dz2{ +x#G==eMHzcU:A*१p:4de|[|1NSkz ) pf,0X" hOK> 4F|.o[V[}6أsI:s_c?u5=?Cҷ#mVNNr0c5lՉIm9b;gr bу|c|V:= @ʳNhNgӴ;6٬H*|j`Cn[%_@feR݅1Ln`gg~?GhzM !UlY'S+́VAgAiA: cʧoon)Xaʏn )mIMsӖwbc7Ήiɺ^_cf)3@fb)\> Ϭd{A?y~H~Ѓ;u 6W:,ԇ_weVSqTZ˙Siis aoHmA%F;,S& &MH:9:jIy+~>vc؏Mpes/;ny!_J=GGIh%c#DFS 6l[|ܿa;{aۣKG+!s;Gi,vkAo90NBi.moM?l{3ၒtFNm ]ld^c9H>sٲҏJZ D{j[d.K&^i6O39gZny>=tO꫅z,!g6ٻk(O/*WWyHY#r[+ZUm 7J΅Ț~G*-Ud4xm^;m PY^1YCrz17NȰ*jL&Fy !}>s~Ow;w",ׯo؀w{|IeM/n+|{A[`3R,7Pő3tbAZ;KdRYL9i:YܶFVKmc2|ߟ[yrIߔymȂΗ. 0`$4SA0DGzG3:4?pр*i:<}SOW\+X~?5s@!枦0!VlݷQ،w& rFgwHfx@-0~}UvuR9mfrsee92bz 쐑{LꇶHU[jrނ{'S֮@Vfl.pm1K2 =& [z dw*ʗ~8({boTdan )KX.cnz"U{0*JXmDvzY8gdw6ToшjK9ބۧևG7[ -bFA4+M)ZcNrY%?^"8ȥ2$ײB] $84O <]Iv =wƟI_7bﹲtGrUS=b ~29_]t3@ noПW׾tl3dɺb^Q:gPnWNY9NǶZV+]oZi|%ş.n<}$LՊTp4`AJYzo;IJs[N`SDn_6yv׃Gdx!c[uGoNY%xB8>&9+*zΞk(˼mrIȚ˪ q87: OGgl? Ae~J>췮x2btW9 re)=ifY!7c>m[Wɶ? ]غK>etr7<֔6(`~.F OEm"5U\sJVNn_ {#G _n?vBt;>ZqT={y9%5Wv-5Pѯ#㭯)"& [.g|}k7ɰQiSmA#~|äՁa¥oWJa]knמ} 5a(A`rwʅw۷rc{>^J ,ZSnNy=L`$S{0 ?diՈI9{mHGeu_-mnPF+M.tlǶ݃J@_?ALCuK=-s?F':UZXVIVw^s a$i?wȾM5`hEm\>۪1QaxOXNj3w[=,?6.~kR=cJپc )#GjeK˶dpp$VВweyVV9Wm@crK\fÛE#&5xuUYAQ((3nGx 6sIn7G4GӇRurx|e[E%Q`*cx_DlĤºLq^#[.Vq^Vw[hQslT9gDkpyLzc˶ CC,7~Ǭ7̴wfdݚV/bap0RO`pv/Ѭ9u\hsw?=Vop/&a"]ڷNucwe d}?O td78;]xi@`*L;XD>u:"O Yr}jϰgfzsk%;G,떾GeK2u23mjo8RIN[o G^ O|zld/Ž ^r-(_Q.~ lD-W^!tz>_&tMuZvpA^9ٺ|\~]Y=MҌ]O<\T6p˦ pLDzZHeGµXz  We>YHYƵW.(\.'ȷ1?Ȣ|w$6w7l}\uaռOL0uPg)m-r雞{afe4?P~Ǽx˧׍K3:)VcϗW|.u uIgދel|H?n5P'9D%jBcQ1c!6~b>)ioKOH|\Dx]'򑧍ܬ*=:FN,-,!bo|Ľj'-m_DCXهǭS-jW:ahiYq FȜ`œFP2^$Wvٲiypˏdq'Buoyn%,ip'0XaƆ8i\sQɟ%s1;[-f*W rنU+ ߳Fm-" Y"U M]l18rhyb4&J5Ĩx08 gdP̲_ڪ%Y1Mv1wˀь(c%\"̩0;Iݚ eGxCf_?Zُ Vu+ͻXkYX|)#"#\?Б]l19J+holf ȵ(t_hYТ|,ߒ'0fێ=H9JFEeIR-L,H| RAUh8AF|^污;::sڍN@ʌV#*{X7ҙ2ljU%'IOsz<r i]4Fq檥da comYeW =cQ"Ϫ@{?T2Ϟ +?kD.ΆɋG{nCc^G:m/bnF2\ӱL5=${DIsݵGHzzs@e^Gp(zc/Rs[ 1Ҙo/iThRW.ep:"YM? p%wm #T:ۑA;1V, QOd=qc#RǨ͙Y5V^rwb=iɞcГÝ+?S 05gb>O,>R0qtȓ;g3sV-1& г/*:, 8 AO<84&JY{}ӛ"@od8y&tenG%;{οA@[r}QuM߫K%5I&2G[2A\;xJקۜ/lo;t<DŽWĝڬJ/Hnis/4WNs$?Q/u(7 ABA3s ya$e@mNq '@&k.`>cY"> 뷣'޴u ϰ oq)M?4vj4H{aMd$w:sJ\=-w&@Dمۥ,3C鬢\~3?)4ڂ{u&^ב#: {Nho$->c;Nl=\=N3OM 8o<юр)ȵɶ6YԱZz!=щ7'+XJ\7pWfe^!o;L3sFޯ{ H G}$b3rYiBFhym9艁R7FdfGNؐKC[Ŧ|}9;̻ރ*[:0s$p/Y}Hf¡֛)s_.8ޑ]fZu)Zy;[m} yo iii%]C۱.# ZtԾMNQ`û3}_^vMg}DF'[2{\vk3F/>Ö}GXZ `h(;yk2 %m `k;6tiuH )Za ȖjEnKz{1'x0YX~Yr'd5=8-m |pb6 [M(4 M-sKw wKIgY>}4kI[Sp ( !>#Di/^N ||Dtyz|+='?1QQܽpC=gi\OBLq^#4u^+H::^æL:ex\ԫX>Qc4G|Vȋ˵z~yu n~Jw Χo/A?ɣgqfW|yg^gɰo ك/(0} F%c '0 G8]Lt^[G׻uc >%?6sNUFuXOh!=ehqY9oE6@FV|[?c+}?7e1p:N14)g"Lnzy( +骺9F:˖}Ovp_v[-5J1Qw_[6ڪ_Gd>M93kpGVcJ4Hk4H!Gd,%AôZ2 Lp_}-PbepK]rhd~?mr_֋&shdzqN-h]Yxϯ @ O!qN/AZ2 MD-"2oT~l>2u ^;0H@+=VQ0zʵ^@47`sXq~g#?6A% h4H{Rdff3Mo%1 rQڮ+:^ѝ,OljA,'[DxYw+侀 //*>.%$~Jzz꼜݀]}lc鍔;^ty 2u^W/u`#% O$Sh0vɊ-R\.bPd#ˍ`}p;"08;zT?Khk=Yچܳ ~T9ffUjBd`28ѷlɦ 22w == NU xa8sS\&Sr)%BW,>k4(K:NevZrI"d9坎mjD$#tתد*#c:&h2v:x_JHg ×e΢VG}NhVPѭ 48~@j$zFtǃt}3Qq얀C*˱ 18]gkĤZsެ;v':y|f`Bu<2urFA4RJ8=?˵}nQQ4Y? 㝗~[FaA*(8 hɡ,>b8g–Y|$FCxahډJ܂`p͎UF}jH56鮜?Oڎ(xv\!KsuJ@{A A8/ޱ]pTYU)n H7|kY}0"82lF8nq³[F0fP^ڱVMwx&Nw{t[Bm8qBC8)Dc,Fj]]]I$5N!83+LOBI$Wj\n5XzRWx.b %$N\q暻B,?c]ᣰGߦey""*4vk3ƈ#">bI6]lcWֺj݌jv7v0#VYK"G'Rat.rduL! ht,9E"Zs͍.~*toz (O'DJ$b^X"`-c&y,k?/*ԭ9tBN`2ٔ.$![ľ};$'zJI'Q1)L7%BwW9_^L14>yf _ɼKmάuIzzpo*T`\Y5wL/W[Ƞf׌,k5gy#[dc ~GzRLM6^eZNuW+BXbę;8_"iNL³ t6\ׯ F+?꫾@˷eR<6;k=5VURUA>eeç, Z`tj(ZP)sBd[{ꗟG2GT8<7ęUMx= 6V}v,9 ZK{uΌwf$Gl>1yIq,_5_aЬM{rDU),\-ai6>b ?6GŽy$_> ^2Ʋ E;R=eYǰk||Lcu Shoj3:),1$,m}L妓Þ `ks9'Susp' 2 ڏw}{lR iڍWF&b23Bn)mTdfli>GLF"\kv /fIw҈Oo+tq{ #iОE 26a<?p>%8~]IpI,j|Tf/Ά uZWK?;;jubrsddQ)(.;rbg≶\o-jYDV[e:[X"#\~7nK?hnƲc$MJMVW&a@.O#K&.ZVW^=UqS=xs :AKoe:BGFCOԆgnz"}zf(J cS3#nFXV߅D'ƚNpB<~;O,ɬ[`v}| Zz*; p.|+)^f"5>1|lXdpOH& N (jNЦ=GLm9+*ĵg,7`^3\ y(e?6ڋa>}]׿gajv$@7q;k3dMHx_DŘ:vwDTZJuk?. Ju ,F5>bUKWAX#&yP֦6#~%4/Wd"{1q| 92b"НSLF5y6ߊO7:I]T (2`Qq'`ꬅHo='?|Poa|W}h4w ~6:[+t/jdܑ}[͟}L,k_2&c؈P/zayXXQh4g]y1~Szq=lBK*-~v;A aƦ"|&޹" G6#~2䔔Ag0 '|)LdT0LgUd+X9:N8jӋa 9bY.#$l]JkkDoa/J /J 06 O|7I?1,+Fx Eq6 +R?^,EXzxg;'澾Ҿ=|(Q<`t^G0n jS[ pxvPdx䰦,шOYpzn_#A4G`ՎD [q_Vcڝ9Ł:״AU B{҅(yGQچ[>,QH tGi0}UD_-Wk0p|.۪E^u{ "Mv\l]aKyHQR]fx 9ȋI7J9X&4w2(Bpџ`Ρ҆G!Ksk[ڸ@oA=Fn= G 6xvg $:VǍ^kJ͸ȯu2|i?FݐN+(#ӭwɣbdLPɎFRA~DngھJj2As@ȈE U4UH0%c< #RKA]dt` 5d`WR:Keb㏪c߸KbR3aW 7 [MXBm+e~5f4(udL_&6sC,atp@7[D&1ա|,$432:kL6Pxb(9T58me<6\ԃT zX7jtHTFŌ=}=(\屁Uu4EDsb;LM.&AY_ʆ2e tlq3˔qDG$n6Ɉ\GEЭBNz{s L8mCؚ<:FdԍD3Bwl@G.Y0,=YE;Ab44SxٞGȒH2ს@2_71?n#tB:^S4gM0ӉI_^t-(qfyMɂǟ AO~WD/IǞdS %G !Kr7'elZm2b ? gS|q'm!s|RNXéy͉I|kmԌ?6TkNH(3iyqzmYQE D}*( 4{DɔkǐiM{pi6x7Q gj A,zDȘJp XՕv(^loݭ\iia&ۣe(.HM٬`Q6bQKdʧdH"vU)k!0Xܷ9qf3><>ߦಎ p7..la12 A'9C_C(pf &'C c-!WudɃcDD\Ğ,!J[#KË5G|h4BM3/:?6-&QfBL6߸S5EPd &ԑŮ4AQ ˍa giOPxXOV.L0ǁ @l ZG%M^փCfw= p_Mr23 zbƈ&Y)E,tRI#ǜ'*_<r9G8 ؂_m.dFJB{dў#/dO nz~FhS*ܭMFleq'<9ΤM;]:lTfłMe.v<1ArYz(ʠk5DDI$Zqha%VӆGay xŸG󙮀Q܏?wOp:{SC}鋍?!6"Z7WLq/;qʲȰ1پIPg*bx1jXDp!˱1MDDTc$m,H/H9K@nٶ%`xr dt|ROlW=}3Af 4&`%i>#lTT!Rgcnr_ɠ2 $R+9}k2 ,Vf=qFL&^`?Oq<@ÇqQ>N`{MCG2͂Ӌ(jc!&T'bb>a3m~ yNG#MG=%P`hF&P::C  mAC㇄;&%;QN4vOFz1zwڃtm,-B^wNh+Ǿh#ٶ;|2lnf?D6O3NAKlF#-/I?CBrSE#gH>#u7e mT2i(^*2y̿ .#~LF @ [ pST~Cjp,!d 0;PMr2+6eGpX*N4YfYX\cTu":,s㆙S4[~t0q"h XY[󟟠5o}7l\F?W?uppmD˂[{D3k$*2GQ͚ 5 ZQyܖX;%G>1ej0mr2+R>&T#7F&?U&ZJ9` =vlI(Gl>xՀ7N2"ˊ%6 'd3,Ӧkт4?װ{"#u,}wh,@5|Qod/6w1{?۴MVDX@(hțQé2)їˏ%H<\;hb|h W1#xS2kb: '1ZU]6 ;'k#l~F6hRo R犍JhKDxg*A 6PbR8?d  YPO;,㙆nNP{TƬq"QsG&z*C7k U6ل 9[-s*2O5j=G8)Dzc c$6K#m5DI$hS/p2pP_TX4]pC 2MvrHar[U7'fw7RAܽ$kL"P{HMaR|1A޵Xvs%;c;2"`,@d !) V [6AfI@2I&==qwOWu{t꾷Ws<9CsEvajN Z}H&< c=^ c.6n&6b O_t0JQROMx:6&"$iBceIN%*$Rnͻmf,&M5^`̛ܛS,N0`3`S F^ (N69RqG$M&e7 $HI`X9@+ ty*f T4~y! V@@`cKN x=tLN.?$O+8)ܟɑEqW5]cbMu w2) {1T/* . nB1d~rN Lr يyT9VPB(qM6Pz@1)fV ,[H.8P^s9p'`0#˭6v5/!ٲgS#4;$jLTAS(HFrZ5br1P#J1Ь=`F+A3l iofb ,M 5jw$0ǠC=URmA-8 %I*bD}xn6&HTn5s<[&ciDtT<j&7Y^6"@Q?+ $("f?@D X"&_(0OJ1#(3V# Cə ɾ8JFƣp` .pn&7xgk,`k' d%@,99-ν~1@ lWyH-z*pIawq6hHv171W%XtB@*QL8V JZ%*E&m TE⯶7ƟCP4\U\(p#nn$klE(Qm]gsɩ  'NLJ'r$U(r[t 96HwBaehq? t]̫Հrl;;WL1Hl>Kq8))۵ 1  B{ iKr^hֆМPXY?i,܉2hq_G3}=[q#`8%&ڱ8cY_(eډ,N4A-6)i_'@:ļ.WQ4+2QML70ыE yav'C1 l]+k%i-lyr vepQQ$Z(8y =M; +4S@si7F7~=1O((u7DDlZuI՝|9닂QQ #wQ ')0DjWxoJ@=پ{\tD$|~II&$*h&o7I?ILq8+v~À'Y X*Z(ʓB)bhD+E1R0Fv*Fj%ݲoub u 0LaP]JYoG e%L~LJDFA*z B9bh>HϣYWU,[% yoGe5h&Oy0dZx]=:Kr^2'c>X P$0!zdmA$tD0 klB@* } )E >2t"%6`35*U)8E=M'( @ZjRk>b+(:*& .E=RLX"R ŭ)S4@]Г,O@*?c< 8Z\ 8ެIrP?K,cȐJ;g @fut 2?q6Jk8KdJm=&$ =s2?rxp01weO𹗙]T]Jf>U'!tbz(M8|"MW~>/NLRowyvTFo+4"5k{o󵿅[ D ӈԤ:2e⣌Oz1UR'ӝrB.*͊|._W< nx/<+9Mc,iޝwDT7_/ulͬm=藳rZ`%H ^b1V/ױ<};&vw؝+<36Z붙Ɨ$i>{OV߰qI7^ ɶɶ.n\vI['A@bPxڞДQ?"'50 ̕|yA)Nwz^pY g1 8 ѱ&=3?~-јi6_'4JC|D>8|`Lxa ;Mnf:5'C<i\Կ'+_dw{ pz]vY3\0N3~FO<-DG[PČ'r쾵Hޘ@N,x=7дglY/Q|nI!Q6XIvpWb#'%=/uK,N$>d=}#DnӷTIu kp9\m]6Vp-l"QIĔqg%yRӝiUJ{S.%M Qh*O.&%]L7=Þ9zD!{~G}Q4>]1wxp8v^}=׿mnՑ:ouz*IxfodjZgu "ԮDn{36gѐH']ۓzhI HI~hH"m eQs VK'm}W?|z2#T}uI# |Vknqm?_FV^D}^8\+C 赌@1HT8K8'UQmb#)_._j7.cXSx˄2!_ǯ g;Db,aClqETFΤ e5xuب#[%hXZ<3o}ae+{fz S[x[;j2D7N-\~otdS&2)yI]GfYщ:(sE'J[jutdf5MfM#}ϵZ?ֺ^m=/BGKiNhGN;%CRt>$JeQeSi4?*g<ëۓ+++CK\w{.jm0c]6[-LR@owFTnZs0//I7|pdw2n.ǣA7?h1?ֆs#.^5~p^:U2'zp.k4gՕOiQX!-.ob^L.%f4=KmX8xe@ƃhUjANMp\#"g1 '2:bMh5>/3TJ㚾gMyXg Lt]iq:Iɤuh5h .eV}Qs;48 Xb_O' MK2~ӎ׶4|s:VIIDAT]䛦JdhUi'v#2GgI*2^i>v4聓@8ѵ:2Z: Y&SF?66hz遦hz遦hz遦hz遦hz遦hz2N,AIENDB`ic04_ARGBߡ߁ۇ݇ IHIGck!҃΅ cbՇڇօ W{U xzqyqrcfxj PtnzcdrqO OR|jjigd`kSM Uxggfdb`h@xddca_]hvb``^]\gKmigfcaIê·̇׽ ˧ϤίĹ Ff[4G8B,oK>dda?58P4" FLjURb>= :Q&W˿Q6* LB6NL4,0 =- :): &7 %/)&#!! ic071-PNG  IHDR>asRGB0IDATx}u}ӓ04h`@J kPd=Zzcl#sei-$,K+$Ba.^B($wzM 4{C,r'e8ݓ^|@] E|2F 8^)f_cwK ?5;!@hec+3P.I~ ł?@fR ߓo!r` doB/ Am. H!Nu`vh|20n%\o05!^I es+=mRD?)w:d'X~ښd抿CmڞO%5inռ|0>@覍v@"n|D>t s?W~kӔ2*RڿW^Һ sЫaS0*5|e>:m4A@4}@bCL,;&[{ "5&n2xhҘWh$} x` 0TO= Ƈ1Cǎ;4 b DG¢mHCOt}Eh[g2o7Ԁȿ['HhIU؞|Z^zWȬJ2=7CѯP%@gCL@8N@X/X UMmZ#QF4 7@!4p< ):'r br笷Cy𢥆/ZZlH%?0v {MNFµˆ7?P 1Z}!&ATk)I`&M z {ẳE=mG(oU:n 9\w9XZOodfw*n2tv,)`C ڌR~e VS_ȇg"ۓBP?F"Ai'p].@a?<p21s8pS ӕ~N{$}a"iw%B &>j\=9@BkM{6z闋=p6@B-u5w~R@>ItU48M.T8)~QgLG m<8l~6ɃҾ]TYssֳs8Ǯa U[kLd2 (r19j8IyuOXk q9շ'hKM89pv8-`f& *4=cLVCT!kZuâp9&m+I3:bglY0#(`iaxJ)x*zgxL@DhIuMkB܀5̈́f) h)maGSݗ%0;bxT ''$1xNW@ NbǓ4{Bݴ`(shٴʙ>2=ḳ5n]UjN`_Ƭ,I0 |a1D` 7C]J3 ?&oizd %0W~ 9ppۗpa~)F T3`k|N3W 1ew hOஎY:pdp=0z 1û2`ISg1B`Sh#@Pl84,5$%cIDń6Fre }`\ <Țuh\Y`H;  S)&M#h V\*@VcQ8lvWf0pf2T\O̊^Y5;3fFk  ͷT Z>I,=>%Q'0,gEK'm GW䏫݆N ! wBO+h@տc~EB =ll5bPpjOx1$;BYP<[Y-Cj=`dSFѕf"V| ςRX ݥ癨m=s2͚/͆[\j?¹k CJPl(Iȹ-!=|`TuJhgW~ {l&`J_h hpx8M1y&=)D? b_ 0۾*)}7Z`Xo jJ lP  V"u"(ɾ-ˈo2;ͤR?|t.b S]-^FYF !,+4Ntiq돨 JuRI#CjfpxΚ% -\c*5ܧ |BQN8M@ܴ]3`m6{Z_^dy¿:0FH ,\{T9pG>LQC2 ?ë4L4Np{0 = wuɁm<ӑc<2h Bx۰΀(Oc|X* :v._LNܸ^>v|W-_*0Op13ܾv'ICTLs-iCd~'>}Y t{V)x&8.pbd28Wa0LSgxE;B8|-VT2$(~|)xQ LS"n^TxFW`@vPIe~`8!~g44>mD5jY@ZϚo3Ꮱb"OBɵC@zOwLD{B {]7T,](q5YγrK ˚bO g ̓h4n 7CغGvoyZZ¸g9?n'gEB'7{+AUQnѯ@ZܹeVX]XZ*Kg+ snsuՎwJ"/l%g=tjdJi#(e:fwB' 7xF[>Ure/}+IpKqY)$o$oD PT̐4~aD>Eym w?.75iٌe^Ù㺻#/j1Jr;K~^bgs.ʎ~܁(q5M?ACgbM\{ޯz)%pG8Stn@vw&"m4aia'ÿ#mߔN= 'pe6 /U/gK+m$-pgw!\x0U$oZ9)M8UIDgɷ~=O}7C^\$ӥ56WKKlBcV|1+{t nҭlي7f~냟2),߂/PkyzEoeI41/!{/r 5 c~Fk^b+)FbHK}QX-7O#R%Nlu1a\wnٜ|Yvh@,C#E2=Xf%J"&IvEy}{4?>Xp2L=| 6q }L1*kV^.co Ir)KWnL]d phLZagGY'\tFY<$U%[Zp7fʜ ݰB3P,ˁ]gdסeSLq  d/I ?C}}"iMvrΌwHCxa+K$o= pЄE Ll)˲a>ywhX"l6~֠1B$Q.c /Y'kkNd_rlF"dA#ni<}ۇxVlv}uӲcCu_R1Lzߘ {H'M.Ssba1-rWɹ3 bԃqD^= e?ߤ,JEmX ȇ`jpϗ5/6mË6`!^5@i^){q!7-_!by^,`5CIi3fokO,EB04ƽOU Ba_rϵ:{QN+|"si]ug|1P!B&]*`Rjmeɗ2yjoPuVxEs Dcaɢ?z$͡\1. { g 5_V&S0܀)r4,8yK!T3pH6(oΒn/H~v9܎!k,n9G7$aGrYkdO_CoƮz]|pZqM7/YzɆ,N y+0fj;Uvt+I噖i /}p'e:!tֲY|t(lQylޤ;WLqx=siN1BG"inq\Ŵzh}ANoD%pu==W_+3[sRiP\^}kn_XH8[?+,VB< v#_}`'c4K`*sg<h,PUٝKٷuw꓎x.hݍ1[: Z_;N^2K%f|s|tgjU]v4ta@Z?2Jm'1Z}]Ԯ#UɎ=>?ks.0 pL&ZS%'ǞtA^"92DBgePH: kxL BS|:CymIo$~VȆl~uq {q'ٶO$iOM{IzGJ9̭_%RD2^6M|2 k1݄A3(;tigCB9+oT7ru֌+=ڠ)8 `x-k`#cpvb`9zv9<ߐ$[`ǦKKʗ☝["r5}JPE[-1^ u0?Le*\nt ,)šxMa%LxE>!V6+|-jk/DxP92vyu,hZ؞DPoUW-k5*|&VWБ>We)y{%& 8 r 5B!~˳e5ޯ0acIeh-!|T A \܌\7 {n)3?-,jMT|7Xq=S`wzVK.}{$S7)8e6 G5x7Zo{/ISdL-T(z,h8g%sR-D60~/~L,9 +>G @7^<̋> l]C(Ё`;?Gmua n(GfRXTr3xGra+\)Kn2E[&+*Qjzs/w'lE6/0A8B5K6|fJx) @҄qHO=prG}O X4ٟ,z~al+@M/I`3 ףkFٛѱmh Ѝ5 &; I[o~q瓘PY;᪗Pk<#.倂=eS.BK8}gSgbm{ .Yp>M;Ec:me`Au; 5CRA,^SMn7*y$ )?4]}LūH|+| %҂_lCMX׆!S8qҨ,ǸX\o 8| dF70Glˈbpԁ6َ6?!%߂, g2 *.<SKo.a> f`cCpL\=( (6ӕHv,v9mlkY4ud6]hd%X.cKQ^46 r(C:RЙDVjiI,J=\j9T<^*. zL?X}=z3wܻ1w9q"br·WCz`= Vl m/ #h/:X%2~h3pdɺ7#(Hr+92[!q5̡NOn\R*.?şM%ƈA%R ~*%%9R`.jӬr 0 gAHg3 q/ӄ毛d])1UnCm0_\xs8ӟHa&CFͧpQ,c˲I'=KǾy'N݇>4`{Q]@y',7?p#~ ?A=z?-4JwK(9~ﯿC5`ݬ+s] "8bQ+Il]4g!qu(a/c\.E=eKb{~=]80g+ pfq:}H1[믾-r+q ;^ݩ7m)jFXiT15>R8mц3>?ycWpT9mwPp, m ez)(߅}n|G-F;5,u[!&s"9h[2H^,\q{0^¹ytNkf;ɦfN=n2 E5x0q Ӕ9h⯀=Ioc010n";/lvfTlRX﷦;T:{|b`3A@&H%<^0~#(/2c/c8>7W1, xZmݰ]lQ]j"229̂Prk\4яv':ùwĭX9t&m:2T0pV$ I$ ~h-K* ,^^׃HF`?Ƚ[#Y2>qƱ^*cU}i`=R b1&0㙀x4`1!4W#"pϠ{wad$ŧxU6oB0Ъ:{a{oy5}|oR5[&µ2FRCcemKYTh6.43p|'t!O- p_r6|N'HH8G(I8Y$: EdxkR˄j |/A:o`fNqS1pn}"}K Wjȍ"h_DQc,ӧnLP U{Ȍkr88$ W4{$h̸ lU6$\UX Ag(@aid4Rbb :#Ѹ0Vq[MpL"S-PUHA=kx-dPpz @@0>> WPiTk1Pv]P$/lFbUn9"=[|Z}2L*auΡiy`w(t0??@'%1bXdr\ߋ?QISc8.?]pdL7aa`?|eMTv; 2DAo!Rmǥ*Ǣ+ U {86T&/ FQdٌY ȴ wwo't$;;K].rdDӋ>0n S&_: D+ٙk91F}[Oֵ/}f->~\LsRqJmr?1Ha9i-5zlਵ♢8/ ǼՋ;jiTcƽg1&$11%LbQ9VK~oEC x_w~\x6bPQqBeOQo(ؗRb#m~:2bdQ\ M*h$<|: 狆MO4P T٤2> ! Ot)EI4=cTL"#9,@iN[^K+EU3ԡ6 j6Ax@z+lSo bls8hG] Yu)lD1۟E>^%]ͿOM0"nm&xI )2{ˤ5H`%д首W4443NGN @?<;{]bOЂ۝1%9_bc@8UqsCOD2R֩K-`W&'DŽ\“<^3TiG2~ƒ|GQI0bYϋln $B?*QI2Q͚0=H fLa>ڎ>DGcXT_x5 CD ĥ)ی╉NxМL1\xjc5^@ 9?>In}R;*:35^0lA^0Q=k=H^!xYB0l3C8O9l~sӦ dڍ7re>ݞ2c09"@>gj"8CHjg2G&\n&\d]o(ptjnm$4afHO>zLK_ @x. 4'yFFP^F j|~7iݤ0&>b{ɜvt!dZ!3:< Y#.=4xx,Q=?[S]k^;qlmᏢQ01 Heaj'q!Ø <Oq{禎jE@ ?4[+಩4O=w5~yD1䆛TU9١UQo <p‘ ygHL9г M9'@`m66 6Û?V G]ҙ~`7Α- 656!)kspo.v2.ɣ)OsrQ^b+ă7Kx"z6x8SKAcUNv=^00t8&=FsTf¯5|]-x+SEz©iz)u#.N]++,CL1,]DCNlR2 gxxIƉ!J+yMQ8,pB.КO"8a+eF,'!kōRoЫգhG"8a\Lw1"ڋTtO`rwwu̕ڎ'41$w~Fv;Xl?4.;w5~>ۏ[v/18^c#Fs0?euZÎv~-SvD9e;BFr]+9<;­))(0E) LQ`"PLv[a0IENDB`gajim-gajim-1.1.3/mac/Info.plist.template000066400000000000000000000021561345766322700202350ustar00rootroot00000000000000 CFBundleExecutable launch.sh CFBundleIdentifier org.gajim.mac CFBundleInfoDictionaryVersion 6.0 CFBundleName Gajim CFBundlePackageType APPL CFBundleShortVersionString ${short_version_string} CFBundleSignature DASH CFBundleVersion ${version} CFBundleIconFile Gajim CFBundleURLTypes CFBundleTypeRole Viewer CFBundleURLName XMPP CFBundleURLSchemes xmpp gajim-gajim-1.1.3/mac/launch.sh.template000066400000000000000000000000271345766322700200660ustar00rootroot00000000000000#!/bin/sh ${bin_path} gajim-gajim-1.1.3/mac/makebundle.py000077500000000000000000000034411345766322700171350ustar00rootroot00000000000000#!/usr/bin/env python3 import os import shutil import sys from string import Template from os.path import join import argparse EXEC_TEMPLATE = 'mac/launch.sh.template' PLIST_TEMPLATE = 'mac/Info.plist.template' ICNS_FILE = 'mac/Gajim.icns' def fill_template(in_path, out_path, vars): with open(in_path, 'r') as f: templ = Template(f.read()) filled_templ = templ.substitute(vars) with open(out_path, 'w') as f: f.write(filled_templ) def create_executable(exec_path, bin_path): fill_template(EXEC_TEMPLATE, exec_path, { 'bin_path': bin_path }) os.chmod(exec_path, 0o755) def create_plist(plist_path, version): fill_template(PLIST_TEMPLATE, plist_path, { 'version': version, 'short_version_string': version }) if __name__ == '__main__': if not os.path.isdir('mac'): sys.exit("can't find the 'mac' directory. make sure you run " "this script from the project root") parser = argparse.ArgumentParser(description='Create a macOS .app bundle.') parser.add_argument('bundle', help='bundle output location') parser.add_argument('--version', default='0.0.1', help='version number of the .app bundle') parser.add_argument('--bin-path', default='/usr/local/bin/gajim', help='location of the actual executable') args = parser.parse_args() bundle = args.bundle os.mkdir(bundle) os.mkdir(join(bundle, 'Contents')) os.mkdir(join(bundle, 'Contents/MacOS')) os.mkdir(join(bundle, 'Contents/Resources')) create_executable(join(bundle, 'Contents/MacOS/launch.sh'), bin_path=args.bin_path) create_plist(join(bundle, 'Contents/Info.plist'), version=args.version) shutil.copy(ICNS_FILE, join(bundle, 'Contents/Resources/Gajim.icns')) gajim-gajim-1.1.3/mac/makeicns.py000077500000000000000000000022101345766322700166110ustar00rootroot00000000000000#!/usr/bin/env python3 import os import shutil from argparse import ArgumentParser from subprocess import run ICON_SVG = 'gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim.svg' def create_icns(icon_path): tmpdir = 'Gajim.iconset' if os.path.isdir(tmpdir): shutil.rmtree(tmpdir) os.mkdir(tmpdir) for size_pt in [16, 32, 128, 256, 512]: for scale in [1, 2]: size_px = scale * size_pt scale_txt = '@{}'.format(scale) if scale != 1 else '' png_fn = 'icon_{}x{}{}.png'.format(size_pt, size_pt, scale_txt) png_path = os.path.join(tmpdir, png_fn) run(['inkscape', '-z', '-e', png_path, '-w', str(size_px), '-h', str(size_px), '-y', '0', ICON_SVG]) run(['iconutil', '-c', 'icns', '-o', icon_path, tmpdir]) shutil.rmtree(tmpdir) if __name__ == '__main__': parser = ArgumentParser(description='Create a macOS .icns icon. ' 'Requires Inkscape and iconutil (macOS).') parser.add_argument('output', help='bundle output location') args = parser.parse_args() create_icns(args.output) gajim-gajim-1.1.3/mypy.ini000066400000000000000000000023351345766322700154110ustar00rootroot00000000000000[mypy] python_version = 3.5 warn_unused_configs = True disallow_incomplete_defs = True [mypy-nbxmpp.*] ignore_missing_imports = True [mypy-gi.*] ignore_missing_imports = True [mypy-dbus.*] ignore_missing_imports = True [mypy-win32file.*] ignore_missing_imports = True [mypy-win32con.*] ignore_missing_imports = True [mypy-pywintypes.*] ignore_missing_imports = True [mypy-OpenSSL.*] ignore_missing_imports = True [mypy-pybonjour.*] ignore_missing_imports = True [mypy-gnupg.*] ignore_missing_imports = True [mypy-encodings.*] ignore_missing_imports = True [mypy-precis_i18n.*] ignore_missing_imports = True [mypy-winsound.*] ignore_missing_imports = True [mypy-PIL.*] ignore_missing_imports = True [mypy-pycurl.*] ignore_missing_imports = True [mypy-netifaces.*] ignore_missing_imports = True [mypy-keyring.*] ignore_missing_imports = True [mypy-ossaudiodev.*] ignore_missing_imports = True [mypy-cssutils.*] ignore_missing_imports = True [mypy-distro.*] ignore_missing_imports = True [mypy-docutils.*] ignore_missing_imports = True [mypy-IPython.*] ignore_missing_imports = True [mypy-traitlets.*] ignore_missing_imports = True [mypy-pygments.*] ignore_missing_imports = True [mypy-cairo.*] ignore_missing_imports = Truegajim-gajim-1.1.3/plugins/000077500000000000000000000000001345766322700153705ustar00rootroot00000000000000gajim-gajim-1.1.3/plugins/dbus_plugin/000077500000000000000000000000001345766322700177035ustar00rootroot00000000000000gajim-gajim-1.1.3/plugins/dbus_plugin/__init__.py000066400000000000000000000000371345766322700220140ustar00rootroot00000000000000from .plugin import DBusPlugin gajim-gajim-1.1.3/plugins/dbus_plugin/dbus_plugin.png000066400000000000000000000041421345766322700227250ustar00rootroot00000000000000PNG  IHDR##$)IDATHǽWݏV?ڱıtgw2a?["$x$ <O}+< PVB!!Bv3Lݙٙl+qlljc;=<8Y*@(>>{{A"Xx|GB8&?*dqO󓫏ɟ(< TSCy۽K3Eu44jhc1x0k1Ȳ< DQ1 .B5Da)?ԏf [g7FEno]9H4M3ɤW3V3Wzlwm$$$L8ro~aAI=Jg>|lj Y,7;J/{7/))%qQiX %%]Yْ֔m[ˋg0 @Qq<RNo9zQĩu} $ bZq%qb))QѶJr$i8*"ʲ*+HK[淟'L!;C? 88)7BaamVe 0n{z$/ږFF hT32v@hT-Fgy!8w̯]zpc cN'"N4w—/J1FDKKH) #M0d1M4-ˉN1 ,"ڶCMiZ>WUUc89Qqc(&ڏs'{G;l_pCO,\IENDB`gajim-gajim-1.1.3/plugins/dbus_plugin/manifest.ini000066400000000000000000000004031345766322700222070ustar00rootroot00000000000000[info] name: D-Bus Support short_name: dbus version: 0.1.1 description: D-Bus support. Based on remote_control module from Gajim core but uses new events handling system. authors = Mateusz Biliński homepage = http://blog.bilinski.it gajim-gajim-1.1.3/plugins/dbus_plugin/plugin.py000066400000000000000000000774021345766322700215650ustar00rootroot00000000000000# -*- coding: utf-8 -*- ## Copyright (C) 2005-2006 Yann Leboulanger ## Copyright (C) 2005-2006 Nikos Kouremenos ## Copyright (C) 2005-2006 Dimitur Kirov ## Copyright (C) 2005-2006 Andrew Sayman ## Copyright (C) 2007 Lukas Petrovicky ## Copyright (C) 2007 Julien Pivotto ## Copyright (C) 2007 Travis Shirk ## Copyright (C) 2008 Mateusz Biliński ## ## This file is part of Gajim. ## ## Gajim is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published ## by the Free Software Foundation; version 3 only. ## ## Gajim is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Gajim. If not, see . ## ''' D-BUS Support plugin. Based on gajim/remote_control.py :author: Mateusz Biliński :since: 8th August 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' import os # import new # depricated in python3; use types instead import types import gobject from gajim.common import dbus_support if dbus_support.supported: import dbus if dbus_support: INTERFACE = 'org.gajim.dbusplugin.RemoteInterface' OBJ_PATH = '/org/gajim/dbusplugin/RemoteObject' SERVICE = 'org.gajim.dbusplugin' import dbus.service # type mapping # in most cases it is a utf-8 string DBUS_STRING = dbus.String # general type (for use in dicts, where all values should have the same type) DBUS_BOOLEAN = dbus.Boolean DBUS_DOUBLE = dbus.Double DBUS_INT32 = dbus.Int32 # dictionary with string key and binary value DBUS_DICT_SV = lambda : dbus.Dictionary({}, signature="sv") # dictionary with string key and value DBUS_DICT_SS = lambda : dbus.Dictionary({}, signature="ss") # empty type (there is no equivalent of None on D-Bus, but historically gajim # used 0 instead) DBUS_NONE = lambda : dbus.Int32(0) def get_dbus_struct(obj): ''' recursively go through all the items and replace them with their casted dbus equivalents ''' if obj is None: return DBUS_NONE() if isinstance(obj, (unicode, str)): return DBUS_STRING(obj) if isinstance(obj, int): return DBUS_INT32(obj) if isinstance(obj, float): return DBUS_DOUBLE(obj) if isinstance(obj, bool): return DBUS_BOOLEAN(obj) if isinstance(obj, (list, tuple)): result = dbus.Array([get_dbus_struct(i) for i in obj], signature='v') if result == []: return DBUS_NONE() return result if isinstance(obj, dict): result = DBUS_DICT_SV() for key, value in obj.items(): result[DBUS_STRING(key)] = get_dbus_struct(value) if result == {}: return DBUS_NONE() return result # unknown type return DBUS_NONE() class SignalObject(dbus.service.Object): ''' Local object definition for /org/gajim/dbus/RemoteObject. (This docstring is not be visible, because the clients can access only the remote object.)''' def __init__(self, bus_name): self.first_show = True self.vcard_account = None # register our dbus API dbus.service.Object.__init__(self, bus_name, OBJ_PATH) @dbus.service.signal(INTERFACE, signature='av') def Roster(self, account_and_data): pass @dbus.service.signal(INTERFACE, signature='av') def AccountPresence(self, status_and_account): pass @dbus.service.signal(INTERFACE, signature='av') def ContactPresence(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def ContactAbsence(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def ContactStatus(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def NewMessage(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def Subscribe(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def Subscribed(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def Unsubscribed(self, account_and_jid): pass @dbus.service.signal(INTERFACE, signature='av') def NewAccount(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def VcardInfo(self, account_and_vcard): pass @dbus.service.signal(INTERFACE, signature='av') def LastStatusTime(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def OsInfo(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def GCPresence(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def GCMessage(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def RosterInfo(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def NewGmail(self, account_and_array): pass @dbus.service.signal(INTERFACE, signature='av') def EntityTime(self, account_and_array): pass def raise_signal(self, signal, arg): '''raise a signal, with a single argument of unspecified type Instead of obj.raise_signal("Foo", bar), use obj.Foo(bar).''' getattr(self, signal)(arg) @dbus.service.method(INTERFACE, in_signature='s', out_signature='s') def get_status(self, account): '''Returns status (show to be exact) which is the global one unless account is given''' if not account: # If user did not ask for account, returns the global status return DBUS_STRING(helpers.get_global_show()) # return show for the given account index = gajim.connections[account].connected return DBUS_STRING(gajim.SHOW_LIST[index]) @dbus.service.method(INTERFACE, in_signature='s', out_signature='s') def get_status_message(self, account): '''Returns status which is the global one unless account is given''' if not account: # If user did not ask for account, returns the global status return DBUS_STRING(str(helpers.get_global_status())) # return show for the given account status = gajim.connections[account].status return DBUS_STRING(status) def _get_account_and_contact(self, account, jid): '''get the account (if not given) and contact instance from jid''' connected_account = None contact = None accounts = gajim.contacts.get_accounts() # if there is only one account in roster, take it as default # if user did not ask for account if not account and len(accounts) == 1: account = accounts[0] if account: if gajim.connections[account].connected > 1: # account is connected connected_account = account contact = gajim.contacts.get_contact_with_highest_priority(account, jid) else: for account in accounts: contact = gajim.contacts.get_contact_with_highest_priority(account, jid) if contact and gajim.connections[account].connected > 1: # account is connected connected_account = account break if not contact: contact = jid return connected_account, contact def _get_account_for_groupchat(self, account, room_jid): '''get the account which is connected to groupchat (if not given) or check if the given account is connected to the groupchat''' connected_account = None accounts = gajim.contacts.get_accounts() # if there is only one account in roster, take it as default # if user did not ask for account if not account and len(accounts) == 1: account = accounts[0] if account: if gajim.connections[account].connected > 1 and \ room_jid in gajim.gc_connected[account] and \ gajim.gc_connected[account][room_jid]: # account and groupchat are connected connected_account = account else: for account in accounts: if gajim.connections[account].connected > 1 and \ room_jid in gajim.gc_connected[account] and \ gajim.gc_connected[account][room_jid]: # account and groupchat are connected connected_account = account break return connected_account @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') def send_file(self, file_path, jid, account): '''send file, located at 'file_path' to 'jid', using account (optional) 'account' ''' jid = self._get_real_jid(jid, account) connected_account, contact = self._get_account_and_contact(account, jid) if connected_account: if file_path[:7] == 'file://': file_path=file_path[7:] if os.path.isfile(file_path): # is it file? gajim.interface.instances['file_transfers'].send_file( connected_account, contact, file_path) return DBUS_BOOLEAN(True) return DBUS_BOOLEAN(False) def _send_message(self, jid, message, keyID, account, type = 'chat', subject = None): '''can be called from send_chat_message (default when send_message) or send_single_message''' if not jid or not message: return DBUS_BOOLEAN(False) if not keyID: keyID = '' connected_account, contact = self._get_account_and_contact(account, jid) if connected_account: connection = gajim.connections[connected_account] connection.send_message(jid, message, keyID, type, subject) return DBUS_BOOLEAN(True) return DBUS_BOOLEAN(False) @dbus.service.method(INTERFACE, in_signature='ssss', out_signature='b') def send_chat_message(self, jid, message, keyID, account): '''Send chat 'message' to 'jid', using account (optional) 'account'. if keyID is specified, encrypt the message with the PGP key ''' jid = self._get_real_jid(jid, account) return self._send_message(jid, message, keyID, account) @dbus.service.method(INTERFACE, in_signature='sssss', out_signature='b') def send_single_message(self, jid, subject, message, keyID, account): '''Send single 'message' to 'jid', using account (optional) 'account'. if keyID is specified, encrypt the message with the PGP key ''' jid = self._get_real_jid(jid, account) return self._send_message(jid, message, keyID, account, type, subject) @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') def send_groupchat_message(self, room_jid, message, account): '''Send 'message' to groupchat 'room_jid', using account (optional) 'account'.''' if not room_jid or not message: return DBUS_BOOLEAN(False) connected_account = self._get_account_for_groupchat(account, room_jid) if connected_account: connection = gajim.connections[connected_account] connection.send_gc_message(room_jid, message) return DBUS_BOOLEAN(True) return DBUS_BOOLEAN(False) @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') def open_chat(self, jid, account): '''Shows the tabbed window for new message to 'jid', using account (optional) 'account' ''' if not jid: raise MissingArgument return DBUS_BOOLEAN(False) jid = self._get_real_jid(jid, account) try: jid = helpers.parse_jid(jid) except Exception: # Jid is not conform, ignore it return DBUS_BOOLEAN(False) if account: accounts = [account] else: accounts = gajim.connections.keys() if len(accounts) == 1: account = accounts[0] connected_account = None first_connected_acct = None for acct in accounts: if gajim.connections[acct].connected > 1: # account is online contact = gajim.contacts.get_first_contact_from_jid(acct, jid) if gajim.interface.msg_win_mgr.has_window(jid, acct): connected_account = acct break # jid is in roster elif contact: connected_account = acct break # we send the message to jid not in roster, because account is # specified, or there is only one account elif account: connected_account = acct elif first_connected_acct is None: first_connected_acct = acct # if jid is not a conntact, open-chat with first connected account if connected_account is None and first_connected_acct: connected_account = first_connected_acct if connected_account: gajim.interface.new_chat_from_jid(connected_account, jid) # preserve the 'steal focus preservation' win = gajim.interface.msg_win_mgr.get_window(jid, connected_account).window if win.get_property('visible'): win.window.present() return DBUS_BOOLEAN(True) return DBUS_BOOLEAN(False) @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') def change_status(self, status, message, account): ''' change_status(status, message, account). account is optional - if not specified status is changed for all accounts. ''' if status not in ('offline', 'online', 'chat', 'away', 'xa', 'dnd', 'invisible'): return DBUS_BOOLEAN(False) if account: gobject.idle_add(gajim.interface.roster.send_status, account, status, message) else: # account not specified, so change the status of all accounts for acc in gajim.contacts.get_accounts(): if not gajim.config.get_per('accounts', acc, 'sync_with_global_status'): continue gobject.idle_add(gajim.interface.roster.send_status, acc, status, message) return DBUS_BOOLEAN(False) @dbus.service.method(INTERFACE, in_signature='', out_signature='') def show_next_pending_event(self): '''Show the window(s) with next pending event in tabbed/group chats.''' if gajim.events.get_nb_events(): gajim.interface.systray.handle_first_event() @dbus.service.method(INTERFACE, in_signature='', out_signature='as') def list_accounts(self): '''list register accounts''' result = gajim.contacts.get_accounts() result_array = dbus.Array([], signature='s') if result and len(result) > 0: for account in result: result_array.append(DBUS_STRING(account)) return result_array @dbus.service.method(INTERFACE, in_signature='s', out_signature='a{ss}') def account_info(self, account): '''show info on account: resource, jid, nick, prio, message''' result = DBUS_DICT_SS() if account in gajim.connections: # account is valid con = gajim.connections[account] index = con.connected result['status'] = DBUS_STRING(gajim.SHOW_LIST[index]) result['name'] = DBUS_STRING(con.name) result['jid'] = DBUS_STRING(gajim.get_jid_from_account(con.name)) result['message'] = DBUS_STRING(con.status) result['priority'] = DBUS_STRING(unicode(con.priority)) result['resource'] = DBUS_STRING(unicode(gajim.config.get_per( 'accounts', con.name, 'resource'))) return result @dbus.service.method(INTERFACE, in_signature='s', out_signature='aa{sv}') def list_contacts(self, account): '''list all contacts in the roster. If the first argument is specified, then return the contacts for the specified account''' result = dbus.Array([], signature='aa{sv}') accounts = gajim.contacts.get_accounts() if len(accounts) == 0: return result if account: accounts_to_search = [account] else: accounts_to_search = accounts for acct in accounts_to_search: if acct in accounts: for jid in gajim.contacts.get_jid_list(acct): item = self._contacts_as_dbus_structure( gajim.contacts.get_contacts(acct, jid)) if item: result.append(item) return result @dbus.service.method(INTERFACE, in_signature='', out_signature='') def toggle_roster_appearance(self): ''' shows/hides the roster window ''' win = gajim.interface.roster.window if win.get_property('visible'): gobject.idle_add(win.hide) else: win.present() # preserve the 'steal focus preservation' if self._is_first(): win.window.present() else: win.window.present_with_time(long(time())) @dbus.service.method(INTERFACE, in_signature='', out_signature='') def toggle_ipython(self): ''' shows/hides the ipython window ''' win = gajim.ipython_window if win: if win.window.is_visible(): gobject.idle_add(win.hide) else: win.show_all() win.present() else: gajim.interface.create_ipython_window() @dbus.service.method(INTERFACE, in_signature='', out_signature='a{ss}') def prefs_list(self): prefs_dict = DBUS_DICT_SS() def get_prefs(data, name, path, value): if value is None: return key = '' if path is not None: for node in path: key += node + '#' key += name prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value) gajim.config.foreach(get_prefs) return prefs_dict @dbus.service.method(INTERFACE, in_signature='', out_signature='b') def prefs_store(self): try: gajim.interface.save_config() except Exception: return DBUS_BOOLEAN(False) return DBUS_BOOLEAN(True) @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') def prefs_del(self, key): if not key: return DBUS_BOOLEAN(False) key_path = key.split('#', 2) if len(key_path) != 3: return DBUS_BOOLEAN(False) if key_path[2] == '*': gajim.config.del_per(key_path[0], key_path[1]) else: gajim.config.del_per(key_path[0], key_path[1], key_path[2]) return DBUS_BOOLEAN(True) @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') def prefs_put(self, key): if not key: return DBUS_BOOLEAN(False) key_path = key.split('#', 2) if len(key_path) < 3: subname, value = key.split('=', 1) gajim.config.set(subname, value) return DBUS_BOOLEAN(True) subname, value = key_path[2].split('=', 1) gajim.config.set_per(key_path[0], key_path[1], subname, value) return DBUS_BOOLEAN(True) @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') def add_contact(self, jid, account): if account: if account in gajim.connections and \ gajim.connections[account].connected > 1: # if given account is active, use it AddNewContactWindow(account = account, jid = jid) else: # wrong account return DBUS_BOOLEAN(False) else: # if account is not given, show account combobox AddNewContactWindow(account = None, jid = jid) return DBUS_BOOLEAN(True) @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') def remove_contact(self, jid, account): jid = self._get_real_jid(jid, account) accounts = gajim.contacts.get_accounts() # if there is only one account in roster, take it as default if account: accounts = [account] contact_exists = False for account in accounts: contacts = gajim.contacts.get_contacts(account, jid) if contacts: gajim.connections[account].unsubscribe(jid) for contact in contacts: gajim.interface.roster.remove_contact(contact, account) gajim.contacts.remove_jid(account, jid) contact_exists = True return DBUS_BOOLEAN(contact_exists) def _is_first(self): if self.first_show: self.first_show = False return True return False def _get_real_jid(self, jid, account = None): '''get the real jid from the given one: removes xmpp: or get jid from nick if account is specified, search only in this account ''' if account: accounts = [account] else: accounts = gajim.connections.keys() if jid.startswith('xmpp:'): return jid[5:] # len('xmpp:') = 5 nick_in_roster = None # Is jid a nick ? for account in accounts: # Does jid exists in roster of one account ? if gajim.contacts.get_contacts(account, jid): return jid if not nick_in_roster: # look in all contact if one has jid as nick for jid_ in gajim.contacts.get_jid_list(account): c = gajim.contacts.get_contacts(account, jid_) if c[0].name == jid: nick_in_roster = jid_ break if nick_in_roster: # We have not found jid in roster, but we found is as a nick return nick_in_roster # We have not found it as jid nor as nick, probably a not in roster jid return jid def _contacts_as_dbus_structure(self, contacts): ''' get info from list of Contact objects and create dbus dict ''' if not contacts: return None prim_contact = None # primary contact for contact in contacts: if prim_contact is None or contact.priority > prim_contact.priority: prim_contact = contact contact_dict = DBUS_DICT_SV() contact_dict['name'] = DBUS_STRING(prim_contact.name) contact_dict['show'] = DBUS_STRING(prim_contact.show) contact_dict['jid'] = DBUS_STRING(prim_contact.jid) if prim_contact.keyID: keyID = None if len(prim_contact.keyID) == 8: keyID = prim_contact.keyID elif len(prim_contact.keyID) == 16: keyID = prim_contact.keyID[8:] if keyID: contact_dict['openPGP'] = keyID contact_dict['resources'] = dbus.Array([], signature='(sis)') for contact in contacts: resource_props = dbus.Struct((DBUS_STRING(contact.resource), dbus.Int32(contact.priority), DBUS_STRING(contact.status))) contact_dict['resources'].append(resource_props) contact_dict['groups'] = dbus.Array([], signature='(s)') for group in prim_contact.groups: contact_dict['groups'].append((DBUS_STRING(group),)) return contact_dict @dbus.service.method(INTERFACE, in_signature='', out_signature='s') def get_unread_msgs_number(self): return DBUS_STRING(str(gajim.events.get_nb_events())) @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') def start_chat(self, account): if not account: # error is shown in gajim-remote check_arguments(..) return DBUS_BOOLEAN(False) app.app.activate_action('start-chat') return DBUS_BOOLEAN(True) @dbus.service.method(INTERFACE, in_signature='ss', out_signature='') def send_xml(self, xml, account): if account: gajim.connections[account].send_stanza(xml) else: for acc in gajim.contacts.get_accounts(): gajim.connections[acc].send_stanza(xml) @dbus.service.method(INTERFACE, in_signature='ssss', out_signature='') def join_room(self, room_jid, nick, password, account): if not account: # get the first connected account accounts = gajim.connections.keys() for acct in accounts: if gajim.account_is_connected(acct): account = acct break if not account: return if not nick: gajim.interface.join_gc_minimal(account, room_jid) else: gajim.interface.join_gc_room(account, room_jid, nick, password) from gajim.common import app from gajim.common import helpers from time import time from gajim.dialogs import AddNewContactWindow, JoinGroupchatWindow from gajim.plugins import GajimPlugin from gajim.plugins.helpers import log_calls, log from gajim.common import ged class DBusPlugin(GajimPlugin): @log_calls('DBusPlugin') def init(self): self.description = _('D-Bus support.' ' Based on remote_control module from' '\nGajim core but uses new events handling system.') self.config_dialog = None #self.gui_extension_points = {} #self.config_default_values = {} self.events_names = ['Roster', 'AccountPresence', 'ContactPresence', 'ContactAbsence', 'ContactStatus', 'NewMessage', 'Subscribe', 'Subscribed', 'Unsubscribed', 'NewAccount', 'VcardInfo', 'LastStatusTime', 'OsInfo', 'GCPresence', 'GCMessage', 'RosterInfo', 'NewGmail', 'EntityTime'] self.signal_object = None self.events_handlers = {} self._set_handling_methods() @log_calls('DBusPlugin') def activate(self): session_bus = dbus_support.session_bus.SessionBus() bus_name = dbus.service.BusName(SERVICE, bus=session_bus) self.signal_object = SignalObject(bus_name) @log_calls('DBusPlugin') def deactivate(self): self.signal_object.remove_from_connection() self.signal_object = None @log_calls('DBusPlugin') def _set_handling_methods(self): for event_name in self.events_names: setattr(self, event_name, types.MethodType( self._generate_handling_method(event_name), self)) self.events_handlers[event_name] = (ged.POSTCORE, getattr(self, event_name)) def _generate_handling_method(self, event_name): def handler(self, arg): #print "Handler of event %s called"%(event_name) if self.signal_object: getattr(self.signal_object, event_name)(get_dbus_struct(arg)) return handler gajim-gajim-1.1.3/plugins/events_dump/000077500000000000000000000000001345766322700177215ustar00rootroot00000000000000gajim-gajim-1.1.3/plugins/events_dump/__init__.py000066400000000000000000000000451345766322700220310ustar00rootroot00000000000000from .plugin import EventsDumpPlugin gajim-gajim-1.1.3/plugins/events_dump/manifest.ini000066400000000000000000000003161345766322700222300ustar00rootroot00000000000000[info] name: Events Dump short_name: events_dump version: 0.1 description: Dumps info about selected events to console. authors = Mateusz Biliński homepage = http://blog.bilinski.it gajim-gajim-1.1.3/plugins/events_dump/plugin.py000066400000000000000000000116731345766322700216010ustar00rootroot00000000000000# -*- coding: utf-8 -*- ## ## This file is part of Gajim. ## ## Gajim is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published ## by the Free Software Foundation; version 3 only. ## ## Gajim is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Gajim. If not, see . ## ''' Events Dump plugin. Dumps info about selected events to console. :author: Mateusz Biliński :since: 10th August 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' import types from pprint import pformat from gajim.plugins import GajimPlugin from gajim.plugins.helpers import log_calls, log from gajim.common import ged class EventsDumpPlugin(GajimPlugin): @log_calls('EventsDumpPlugin') def init(self): self.description = _('Dumps info about selected events to console.') self.config_dialog = None #self.gui_extension_points = {} #self.config_default_values = {} events_from_old_dbus_support = [ 'Roster', 'AccountPresence', 'ContactPresence', 'ContactAbsence', 'ContactStatus', 'NewMessage', 'Subscribe', 'Subscribed', 'Unsubscribed', 'NewAccount', 'VcardInfo', 'LastStatusTime', 'OsInfo', 'GCPresence', 'GCMessage', 'RosterInfo', 'NewGmail'] events_from_src_gajim = [ 'ROSTER', 'WARNING', 'ERROR', 'INFORMATION', 'ERROR_ANSWER', 'STATUS', 'NOTIFY', 'MSGERROR', 'MSGSENT', 'MSGNOTSENT', 'SUBSCRIBED', 'UNSUBSCRIBED', 'SUBSCRIBE', 'AGENT_ERROR_INFO', 'AGENT_ERROR_ITEMS', 'AGENT_REMOVED', 'REGISTER_AGENT_INFO', 'AGENT_INFO_ITEMS', 'AGENT_INFO_INFO', 'QUIT', 'NEW_ACC_CONNECTED', 'NEW_ACC_NOT_CONNECTED', 'ACC_OK', 'ACC_NOT_OK', 'MYVCARD', 'VCARD', 'LAST_STATUS_TIME', 'OS_INFO', 'GC_NOTIFY', 'GC_MSG', 'GC_SUBJECT', 'GC_CONFIG', 'GC_CONFIG_CHANGE', 'GC_INVITATION', 'GC_AFFILIATION', 'GC_PASSWORD_REQUIRED', 'BAD_PASSPHRASE', 'ROSTER_INFO', 'BOOKMARKS', 'CON_TYPE', 'CONNECTION_LOST', 'FILE_REQUEST', 'FILE_REQUEST_ERROR', 'FILE_SEND_ERROR', 'STANZA_ARRIVED', 'STANZA_SENT', 'HTTP_AUTH', 'VCARD_PUBLISHED', 'VCARD_NOT_PUBLISHED', 'ASK_NEW_NICK', 'SIGNED_IN', 'METACONTACTS', 'ATOM_ENTRY', 'FAILED_DECRYPT', 'PRIVACY_LISTS_RECEIVED', 'PRIVACY_LIST_RECEIVED', 'PRIVACY_LISTS_ACTIVE_DEFAULT', 'PRIVACY_LIST_REMOVED', 'ZC_NAME_CONFLICT', 'PING_SENT', 'PING_REPLY', 'PING_ERROR', 'SEARCH_FORM', 'SEARCH_RESULT', 'RESOURCE_CONFLICT', 'PEP_CONFIG', 'UNIQUE_ROOM_ID_UNSUPPORTED', 'UNIQUE_ROOM_ID_SUPPORTED', 'SESSION_NEG', 'GPG_PASSWORD_REQUIRED', 'SSL_ERROR', 'FINGERPRINT_ERROR', 'PLAIN_CONNECTION', 'PUBSUB_NODE_REMOVED', 'PUBSUB_NODE_NOT_REMOVED'] network_events_from_core = ['raw-message-received', 'raw-iq-received', 'raw-pres-received'] network_events_generated_in_nec = [ 'customized-message-received', 'more-customized-message-received', 'modify-only-message-received', 'enriched-chat-message-received'] self.events_names = [] self.events_names += network_events_from_core self.events_names += network_events_generated_in_nec self.events_handlers = {} self._set_handling_methods() @log_calls('EventsDumpPlugin') def activate(self): pass @log_calls('EventsDumpPlugin') def deactivate(self): pass @log_calls('EventsDumpPlugin') def _set_handling_methods(self): for event_name in self.events_names: setattr(self, event_name, types.MethodType( self._generate_handling_method(event_name), self)) self.events_handlers[event_name] = (ged.POSTCORE, getattr(self, event_name)) def _generate_handling_method(self, event_name): def handler(self, *args): print ("Event '%s' occured. Arguments: %s\n\n===\n" % (event_name, pformat(args))) return handler gajim-gajim-1.1.3/plugins/new_events_example/000077500000000000000000000000001345766322700212605ustar00rootroot00000000000000gajim-gajim-1.1.3/plugins/new_events_example/__init__.py000066400000000000000000000000531345766322700233670ustar00rootroot00000000000000from .plugin import NewEventsExamplePlugin gajim-gajim-1.1.3/plugins/new_events_example/manifest.ini000066400000000000000000000004221345766322700235650ustar00rootroot00000000000000[info] name: New Events Example short_name: new_events_example version: 0.1 description: Shows how to generate new network events based on existing one using Network Events Controller. authors = Mateusz Biliński homepage = http://blog.bilinski.it gajim-gajim-1.1.3/plugins/new_events_example/plugin.py000066400000000000000000000112711345766322700231320ustar00rootroot00000000000000# -*- coding: utf-8 -*- ## ## This file is part of Gajim. ## ## Gajim is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published ## by the Free Software Foundation; version 3 only. ## ## Gajim is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Gajim. If not, see . ## ''' New Events Example plugin. Demonstrates how to use Network Events Controller to generate new events based on existing one. :author: Mateusz Biliński :since: 15th August 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' #import new # Depricated in python3 for types module from pprint import pformat from gajim.common import helpers from gajim.common import app from gajim.plugins import GajimPlugin from gajim.plugins.helpers import log_calls, log from gajim.common import ged from gajim.common import nec class NewEventsExamplePlugin(GajimPlugin): @log_calls('NewEventsExamplePlugin') def init(self): self.description = _('Shows how to generate new network events based ' 'on existing one using Network Events Controller.') self.config_dialog = None #self.gui_extension_points = {} #self.config_default_values = {} self.events_handlers = {'raw-message-received' : (ged.POSTCORE, self.raw_message_received), 'customized-message-received' : (ged.POSTCORE, self.customized_message_received), 'enriched-chat-message-received' : (ged.POSTCORE, self.enriched_chat_message_received)} self.events = [CustomizedMessageReceivedEvent, MoreCustomizedMessageReceivedEvent, ModifyOnlyMessageReceivedEvent, EnrichedChatMessageReceivedEvent] def enriched_chat_message_received(self, event_object): pass # print "Event '%s' occured. Event object: %s\n\n===\n" % \ # (event_object.name, event_object) def raw_message_received(self, event_object): pass # print "Event '%s' occured. Event object: %s\n\n===\n" % \ # (event_object.name,event_object) def customized_message_received(self, event_object): pass # print "Event '%s' occured. Event object: %s\n\n===\n" % \ # (event_object.name, event_object @log_calls('NewEventsExamplePlugin') def activate(self): pass @log_calls('NewEventsExamplePlugin') def deactivate(self): pass class CustomizedMessageReceivedEvent(nec.NetworkIncomingEvent): name = 'customized-message-received' base_network_events = ['raw-message-received'] def generate(self): return True class MoreCustomizedMessageReceivedEvent(nec.NetworkIncomingEvent): ''' Shows chain of custom created events. This one is based on custom 'customized-messsage-received'. ''' name = 'more-customized-message-received' base_network_events = ['customized-message-received'] def generate(self): return True class ModifyOnlyMessageReceivedEvent(nec.NetworkIncomingEvent): name = 'modify-only-message-received' base_network_events = ['raw-message-received'] def generate(self): msg_type = self.base_event.stanza.attrs.get('type', None) if msg_type == u'chat': msg_text = ''.join(self.base_event.stanza.kids[0].data) self.base_event.stanza.kids[0].setData( u'%s [MODIFIED BY CUSTOM NETWORK EVENT]' % (msg_text)) return False class EnrichedChatMessageReceivedEvent(nec.NetworkIncomingEvent): ''' Generates more friendly (in use by handlers) network event for received chat message. ''' name = 'enriched-chat-message-received' base_network_events = ['raw-message-received'] def generate(self): msg_type = self.base_event.stanza.attrs.get('type', None) if msg_type == u'chat': self.stanza = self.base_event.stanza self.conn = self.base_event.conn self.from_jid = helpers.get_full_jid_from_iq(self.stanza) self.from_jid_without_resource = app.get_jid_without_resource( self.from_jid) self.account = self.conn.name self.from_nickname = app.get_contact_name_from_jid( self.account, self.from_jid_without_resource) self.msg_text = ''.join(self.stanza.kids[0].data) return True return False gajim-gajim-1.1.3/plugins/roster_buttons/000077500000000000000000000000001345766322700204645ustar00rootroot00000000000000gajim-gajim-1.1.3/plugins/roster_buttons/__init__.py000066400000000000000000000001141345766322700225710ustar00rootroot00000000000000 __all__ = ['RosterButtonsPlugin'] from .plugin import RosterButtonsPlugin gajim-gajim-1.1.3/plugins/roster_buttons/manifest.ini000066400000000000000000000003251345766322700227730ustar00rootroot00000000000000[info] name: Roster Buttons short_name: roster_buttons version: 0.1 description: Adds quick action buttons to roster window. authors = Mateusz Biliński homepage = http://blog.bilinski.it gajim-gajim-1.1.3/plugins/roster_buttons/plugin.py000066400000000000000000000052131345766322700223350ustar00rootroot00000000000000# -*- coding: utf-8 -*- ## This file is part of Gajim. ## ## Gajim is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published ## by the Free Software Foundation; version 3 only. ## ## Gajim is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Gajim. If not, see . ## ''' Roster buttons plug-in. :author: Mateusz Biliński :since: 14th June 2008 :copyright: Copyright (2008) Mateusz Biliński :license: GPL ''' import sys import gtk from gajim.common import app from gajim.plugins import GajimPlugin from gajim.plugins.helpers import log, log_calls class RosterButtonsPlugin(GajimPlugin): @log_calls('RosterButtonsPlugin') def init(self): self.description = _('Adds quick action buttons to roster window.') self.GTK_BUILDER_FILE_PATH = self.local_file_path('roster_buttons.ui') self.config_dialog = None @log_calls('RosterButtonsPlugin') def activate(self): self.roster_vbox = app.interface.roster.xml.get_object('roster_vbox2') self.show_offline_contacts_menuitem = app.interface.roster.xml.get_object('show_offline_contacts_menuitem') self.xml = gtk.Builder() self.xml.set_translation_domain('gajim_plugins') self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, ['roster_buttons_buttonbox']) self.buttonbox = self.xml.get_object('roster_buttons_buttonbox') self.roster_vbox.pack_start(self.buttonbox, expand=False) self.roster_vbox.reorder_child(self.buttonbox, 0) self.xml.connect_signals(self) @log_calls('RosterButtonsPlugin') def deactivate(self): self.roster_vbox.remove(self.buttonbox) self.buttonbox = None self.xml = None @log_calls('RosterButtonsPlugin') def on_roster_button_1_clicked(self, button): #gajim.interface.roster.on_show_offline_contacts_menuitem_activate(None) self.show_offline_contacts_menuitem.set_active(not self.show_offline_contacts_menuitem.get_active()) @log_calls('RosterButtonsPlugin') def on_roster_button_2_clicked(self, button): pass @log_calls('RosterButtonsPlugin') def on_roster_button_3_clicked(self, button): pass @log_calls('RosterButtonsPlugin') def on_roster_button_4_clicked(self, button): pass gajim-gajim-1.1.3/plugins/roster_buttons/roster_buttons.ui000066400000000000000000000054521345766322700241250ustar00rootroot00000000000000 True True spread 1 True True True False False 0 2 True True True False False 1 3 True True True False False 2 4 True True True False False 3 gajim-gajim-1.1.3/po/000077500000000000000000000000001345766322700143255ustar00rootroot00000000000000gajim-gajim-1.1.3/po/LINGUAS000066400000000000000000000002311345766322700153460ustar00rootroot00000000000000# available languages fr pt el pl es ru bg de nb_NO cs nl pt_BR sv it eu sk zh_CN br eo hr en_GB be be@latin sr sr@Latn gl lt da uk ja kk he zh_TW hu tr gajim-gajim-1.1.3/po/be.po000066400000000000000000013451631345766322700152700ustar00rootroot00000000000000# Беларускі пераклад Gajim # Copyright (C) 2006 Free Software Foundation, Inc. # This file is distributed under the same license as Gajim. # # Ihar Hrachyshka , 2006, 2009. msgid "" msgstr "" "Project-Id-Version: 0.10.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2009-08-19 23:42+0200\n" "Last-Translator: Ihar Hrachyshka \n" "Language-Team: Belarusian \n" "Language: be\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "" #: gajim/chat_control_base.py:1103 #, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "" #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Файл" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Час" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Ступень выкананасці" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Файл: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Памер: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "Вы" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Адпраўнік: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Атрымальнік: " #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Захаваць у: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Перадача файла скончаная" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 #, fuzzy msgid "Open _Containing Folder" msgstr "_Адкрыць дырэкторыю з файлам" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "Перадача файла скасаваная" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "Немагчыма ўсталяваць злучэнне з атрымальнікам." #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "Атрымальнік: %s" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "Памылка: %s" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 #, fuzzy msgid "File transfer stopped" msgstr "Перадача файла спыненая" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" #: gajim/filetransfers_window.py:341 #, fuzzy msgid "Gajim can not read this file" msgstr "Gajim не можа даступіцца да гэтага файла" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "" #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "Немагчыма перапісаць наяўны файл \"%s\"" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "Файл з такой назвай ужо існуе, а Вы не маеце правоў на яго перазапіс." #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Такі файл ужо ёсць" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "Што Вы хочаце зрабіць?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "Немагчыма запісваць файлы ў дырэкторыю \"%s\"" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "Вы не маеце права ствараць файлы ў гэтай дырэкторыі." #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Файл: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Тып: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Апісанне: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "%s хоча адправіць Вам файл:" #: gajim/filetransfers_window.py:487 #, fuzzy msgid "Checking file…" msgstr "Адпраўленне профіля..." #: gajim/filetransfers_window.py:501 #, fuzzy msgid "File error" msgstr "Памылка перадачы файла" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/с)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Няправільны файл" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Файл: " #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "Немагчыма адправіць пусты файл" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Назва:" #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Адпраўнік:" #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Прыпыніць" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "_Працягнуць" #: gajim/filetransfers_window.py:1019 #, fuzzy msgid "Choose a File to Send…" msgstr "Выберыце файл..." #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "Пашырэнне не падтрымліваецца" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" "Немагчыма захаваць малюнак у фармаце %(type)s. Захаваць як %(new_filename)s?" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 #, fuzzy msgid "Save _As" msgstr "Мае " #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "?Праграма:Невядомая" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "?Сістэма:Невядомая" #: gajim/vcard.py:326 gajim/vcard.py:329 #, fuzzy msgid "?Time:Unknown" msgstr "?Праграма:Невядомая" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "" #: gajim/vcard.py:384 #, fuzzy msgid "Affiliation:" msgstr "Праграмы" #: gajim/vcard.py:391 #, fuzzy msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "Вы не цікавіцеся гэтым чалавекам, але ён цікавіцца Вамі" #: gajim/vcard.py:393 #, fuzzy msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "Вы цікавіцеся чалавекам, але ён не цікавіцца Вамі" #: gajim/vcard.py:395 #, fuzzy msgid "The contact and you want to exchange presence information" msgstr "Вы і гэты чалавек абодва цікавіцеся адзін адным" #: gajim/vcard.py:397 #, fuzzy msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "Вы і гэты чалавек абодва цікавіцеся адзін адным" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "Вы чакаеце адказу на Ваш запыт" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "" #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr " рэсурс з прыярытэтам " #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "Усе файлы" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 #, fuzzy msgid "Clear File" msgstr "Вечар" #: gajim/options_dialog.py:484 #, fuzzy msgid "Manage Proxies" msgstr "Кіраванне профілямі проксі" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Ніякі" #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "_Адпаведна стану" #: gajim/options_dialog.py:528 msgid "On" msgstr "" #: gajim/options_dialog.py:528 #, fuzzy msgid "Off" msgstr "Адключаны" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Немагчыма атрымаць сакрэтныя ключы" #: gajim/options_dialog.py:565 #, fuzzy msgid "There is no OpenPGP secret key available." msgstr "Памылка пошуку Вашых сакрэтных ключоў OpenPGP." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "Выбар ключоў OpenPGP" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Выберыце Ваш ключ OpenPGP" #: gajim/gui_menu_builder.py:95 #, fuzzy msgid "_New Group Chat" msgstr "Новая групавая размова" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Няма ў спісе" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "Я хачу дадаць Вас у мой кантактны ліст" #: gajim/gui_menu_builder.py:502 #, fuzzy msgid "Send Single _Message…" msgstr "Адправіць _асобнае паведамленне" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 #, fuzzy msgid "Send Cus_tom Status" msgstr "Адправіць асаблівы XML" #: gajim/gui_menu_builder.py:535 #, fuzzy msgid "E_xecute Command…" msgstr "_Выканаць загад..." #: gajim/gui_menu_builder.py:543 #, fuzzy msgid "_Manage Transport" msgstr "Транспарты" #: gajim/gui_menu_builder.py:549 #, fuzzy msgid "_Modify Transport" msgstr "Паказаць _транспарты" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 #, fuzzy msgid "_Rename…" msgstr "Змяніць _імя" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 #, fuzzy msgid "Remo_ve" msgstr "Вы_даліць" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 #, fuzzy msgid "_Information" msgstr "Асабістыя звесткі" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 #, fuzzy msgid "Send File…" msgstr "Адправіць _файл" #: gajim/gui_menu_builder.py:602 #, fuzzy msgid "Upload File…" msgstr "Захаваць файл як..." #: gajim/gui_menu_builder.py:603 #, fuzzy msgid "Send File Directly…" msgstr "Захаваць файл як..." #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Людзі" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "_Дадаць у кантактны ліст" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "Асабістыя звесткі" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 #, fuzzy msgid "History" msgstr "_Журнал" #: gajim/gui_menu_builder.py:634 #, fuzzy msgid "Manage Room" msgstr "Кіраванне закладкамі" #: gajim/gui_menu_builder.py:635 #, fuzzy msgid "Change Subject" msgstr "Змяніць _тэму" #: gajim/gui_menu_builder.py:636 #, fuzzy msgid "Configure Room" msgstr "Настаўленні _пакоя" #: gajim/gui_menu_builder.py:637 #, fuzzy msgid "Upload Avatar…" msgstr "Выберыце малюнак" #: gajim/gui_menu_builder.py:638 #, fuzzy msgid "Destroy Room" msgstr "Апісанне: %s" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "" #: gajim/gui_menu_builder.py:641 #, fuzzy msgid "Change Nick" msgstr "Змяніць м_янушку" #: gajim/gui_menu_builder.py:642 #, fuzzy msgid "Bookmark Room" msgstr "_Змясціць у закладках" #: gajim/gui_menu_builder.py:643 #, fuzzy msgid "Request Voice" msgstr "_Голас" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 #, fuzzy msgid "Notify on all messages" msgstr "Стандартныя паведамленні:" #: gajim/gui_menu_builder.py:645 msgid "Minimize on close" msgstr "" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 #, fuzzy msgid "Execute command" msgstr "_Выканаць загад..." #: gajim/gui_menu_builder.py:648 #, fuzzy msgid "Disconnect" msgstr "Чалавек адлучыўся" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "" #: gajim/gui_menu_builder.py:680 #, fuzzy, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "%i дзён таму" msgstr[1] "%i дзён таму" msgstr[2] "%i дзён таму" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Удзельнічаць у групавой размове" #: gajim/gui_menu_builder.py:734 #, fuzzy msgid "Add Contact…" msgstr "_Дадаць чалавека..." #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 #, fuzzy msgid "Profile" msgstr "файл" #: gajim/gui_menu_builder.py:737 #, fuzzy msgid "Discover Services" msgstr "_Пошук сервісаў" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Адправіць _асобнае паведамленне" #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Адмысловы" #: gajim/gui_menu_builder.py:740 #, fuzzy msgid "Archiving Preferences" msgstr "_Настаўленні" #: gajim/gui_menu_builder.py:741 #, fuzzy msgid "Synchronise History" msgstr "Паказаць _адлучаных людзей" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "Спісы прыватнасці" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 #, fuzzy msgid "Server Info" msgstr "Сервер" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "Кансоль XML" #: gajim/gui_menu_builder.py:746 #, fuzzy msgid "Admin" msgstr "_Адміністратар" #: gajim/gui_menu_builder.py:747 #, fuzzy msgid "Send Server Message…" msgstr "Ад_правіць паведамленне серверу" #: gajim/gui_menu_builder.py:748 #, fuzzy msgid "Set MOTD…" msgstr "Вызначыць MOTD" #: gajim/gui_menu_builder.py:749 #, fuzzy msgid "Update MOTD…" msgstr "Абнавіць MOTD" #: gajim/gui_menu_builder.py:750 #, fuzzy msgid "Delete MOTD…" msgstr "Выдаліць MOTD" #: gajim/gui_menu_builder.py:799 #, fuzzy msgid "No Accounts available" msgstr "Рахункаў няма" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Рахункі" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 #, fuzzy msgid "Copy JID" msgstr "Пакой:" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Удзельнічаць у групавой размове" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Пачаць размову" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 #, fuzzy msgid "Add to Roster…" msgstr "_Дадаць у кантактны ліст" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "_Скапіяваць адрас спасылкі" #: gajim/gui_menu_builder.py:881 #, fuzzy msgid "Open Link in Browser" msgstr "_Адкрыць у праглядальніку" #: gajim/gui_menu_builder.py:886 #, fuzzy msgid "Copy Email Address" msgstr "_Скапіяваць JID / паштовы адрас" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Напісаць ліст" #: gajim/gui_menu_builder.py:892 #, fuzzy msgid "Copy JID/Email" msgstr "_Скапіяваць JID / паштовы адрас" #: gajim/history_manager.py:71 #, fuzzy msgid "Usage:" msgstr "паведамленне" #: gajim/history_manager.py:73 #, fuzzy msgid "Options:" msgstr "Сымболікі:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "Немагчыма адшукаць базу дадзеных" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Дата" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Мянушка" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Паведамленне" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Тэма" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" "Вы сапраўды хочаце ачысціць базу дадзеных? (Увага: закрыйце Gajim перад " "працягам)" #: gajim/history_manager.py:257 #, fuzzy msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" "Звычайна памер базы дадзеных не змяншаецца, але вызваленае месца можа быць " "скарыстаным для пазнейшых размоў. Калі Вы хочаце зменшыць памер базы " "дадзеных, пстрыкніце Так, інакш Не.\n" "\n" "Калі Вы выбралі Так, пачакайце..." #: gajim/history_manager.py:262 msgid "Database Cleanup" msgstr "" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(who)s а %(time)s сказаў: %(message)s\n" #: gajim/history_manager.py:577 #, fuzzy, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Вы сапраўды хочаце выдаліць выбранае паведамленне?" #: gajim/history_manager.py:581 #, fuzzy msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "Вы сапраўды хочаце выдаліць журнал размоў з выбранай асобай?" #: gajim/history_manager.py:583 #, fuzzy msgid "This can not be undone." msgstr "Немагчыма знайсці сервіс" #: gajim/history_manager.py:585 gajim/history_manager.py:624 #, fuzzy msgid "Deletion Confirmation" msgstr "Асабістыя звесткі" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Вы сапраўды хочаце выдаліць выбранае паведамленне?" msgstr[1] "Вы сапраўды хочаце выдаліць выбраныя паведамленні?" msgstr[2] "Вы сапраўды хочаце выдаліць выбраныя паведамленні?" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "Гэтае дзеянне не аднаўляецца." #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "Імя чалавека: %s" #: gajim/dialogs.py:84 #, fuzzy, python-format msgid "JID: %s" msgstr "Jabber ID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "Агульная" #: gajim/dialogs.py:200 msgid "Group" msgstr "Група" #: gajim/dialogs.py:207 msgid "In the group" msgstr "У групе" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "KeyID" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Імя чалавека" #: gajim/dialogs.py:483 #, fuzzy msgid "Set Mood" msgstr "Вызначыць MOTD" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "Паведамленне аб змене стану %s" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Паведамленне аб змене стану" #: gajim/dialogs.py:807 #, fuzzy msgid "Overwrite Status Message?" msgstr "Паведамленне аб змене стану" #: gajim/dialogs.py:808 #, fuzzy msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "Гэтая назва ўжо скарыстаная для іншага рахунка. Выберыце іншую назву." #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Захаваць гэтае паведамленне аб змене стану" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Вызначце назву гэтага паведамлення аб змене стану" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Запыт падпіскі" #: gajim/dialogs.py:857 #, fuzzy, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Запыт увагі на рахунак %s ад %s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Запыт увагі ад %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "Вы не злучаны з серверам" #: gajim/dialogs.py:928 #, fuzzy msgid "Without a connection, you can not synchronise your contacts." msgstr "Вы не можаце змяніць пароль, не злучыўшыся з серверам." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Назва" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Сервер" #: gajim/dialogs.py:978 #, fuzzy msgid "This account is not connected to the server" msgstr "Рахунак \"%s\" злучаны з серверам" #: gajim/dialogs.py:979 #, fuzzy msgid "You cannot synchronize with an account unless it is connected." msgstr "" "Вы не можаце ўдзельнічаць у групавой размове, не злучыўшыся з серверам." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "" #: gajim/dialogs.py:1065 #, fuzzy msgid "add" msgstr "Марнаванне часу" #: gajim/dialogs.py:1065 #, fuzzy msgid "modify" msgstr "_Змяніць" #: gajim/dialogs.py:1066 #, fuzzy msgid "remove" msgstr "Вы_даліць" #: gajim/dialogs.py:1095 #, fuzzy, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "Я хачу дадаць Вас у свой кантактны ліст." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 #, fuzzy msgid "Add" msgstr "Адрас" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 #, fuzzy msgid "Modify" msgstr "_Змяніць" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Выдаліць" #: gajim/dialogs.py:1125 #, fuzzy msgid "Groups" msgstr "Група" #: gajim/dialogs.py:1233 #, fuzzy, python-format msgid "%s suggested me to add you in my roster." msgstr "Я хачу дадаць Вас у мой кантактны ліст." #: gajim/dialogs.py:1247 #, fuzzy, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "Дадаць _чалавека" msgstr[1] "Дадаць _чалавека" msgstr[2] "Дадаць _чалавека" #: gajim/dialogs.py:1285 #, fuzzy, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "Выдаліць чалавека з спіса" msgstr[1] "Выдаліць чалавека з спіса" msgstr[2] "Выдаліць чалавека з спіса" #: gajim/dialogs.py:1305 #, fuzzy msgid "You are invited to a groupchat" msgstr "Вы не ўвайшлі ў пакой групавой размовы." #: gajim/dialogs.py:1308 #, fuzzy msgid "$Contact has invited you to join a discussion" msgstr "$Contact запрасіў Вас у групавую размову %(room_jid)s" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "$Contact запрасіў Вас у групавую размову %(room_jid)s" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Каментарый: %s" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Запрашэнне ў групавую размову" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "" #: gajim/dialogs.py:1628 msgid "a video" msgstr "" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 #, fuzzy msgid "File Transfer" msgstr "Перадача файлаў" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "" #: gajim/dialogs.py:1764 #, fuzzy msgid "Encrypting file…" msgstr "Шыфраванне адключанае" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, fuzzy, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%s змяніў мянушку на %s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s цяпер %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Памылка адпраўкі прыватнага паведамлення" #: gajim/groupchat_control.py:253 #, fuzzy, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "Вы выйшлі з пакоя \"%s\", альбо \"%s\" сышоў." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 #, fuzzy msgid "No File Transfer available" msgstr "Перадача файлаў" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Змяненне тэмы" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Вызначце новую тэму:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Змена мянушкі" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Вызначце сваю новую мянушку:" #: gajim/groupchat_control.py:711 #, fuzzy msgid "Invalid group chat JID" msgstr "Няправільны Jabber ID групавой размовы" #: gajim/groupchat_control.py:712 #, fuzzy msgid "The group chat JID has not allowed characters." msgstr "Jabber ID групавой размовы ўтрымлівае няправільныя знакі." #: gajim/groupchat_control.py:724 #, fuzzy, python-format msgid "Destroying %s" msgstr "Апісанне: %s" #: gajim/groupchat_control.py:725 msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "Немагчыма загрузіць малюнак" #: gajim/groupchat_control.py:934 msgid "Insert Nickname" msgstr "Уставіць мянушку" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 #, fuzzy msgid "and authenticated" msgstr "Аўтарызацыя" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 #, fuzzy msgid "and NOT authenticated" msgstr "Аўтарызацыя" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" #: gajim/groupchat_control.py:1157 #, fuzzy msgid "Conversation with " msgstr "Журнал размоў" #: gajim/groupchat_control.py:1159 #, fuzzy msgid "Continued conversation" msgstr "Злучэнне" #: gajim/groupchat_control.py:1525 #, fuzzy, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(nick)s пакараны: %(reason)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "" #: gajim/groupchat_control.py:1556 msgid "Room now shows unavailable members" msgstr "" #: gajim/groupchat_control.py:1558 msgid "Room now does not show unavailable members" msgstr "" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "" #: gajim/groupchat_control.py:1576 msgid "Room is now fully anonymous" msgstr "" #: gajim/groupchat_control.py:1615 #, python-format msgid "Ping? (%s)" msgstr "" #: gajim/groupchat_control.py:1618 #, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 #, fuzzy msgid "Error." msgstr "Памылка Avahi" #: gajim/groupchat_control.py:1845 #, fuzzy, python-format msgid "You (%s) joined the room" msgstr "%s далучыўся да групавой размовы" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, fuzzy, python-format msgid "%(jid)s has been invited in this room" msgstr "%(who)s пакараў %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "" #: gajim/groupchat_control.py:1879 #, fuzzy msgid "A new room has been created" msgstr "Новы рахунак паспяхова створаны" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s пакараны: %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(who)s пакараў %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "Для %(nick)s забаронена казанне: %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(who)s забараніў казанне для %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "Вашая мянушка змененая на %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, fuzzy, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(who)s пакараў %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1950 #, fuzzy msgid "affiliation changed" msgstr "Адносіны: " #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "" #: gajim/groupchat_control.py:2034 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "%(who)s пакараў %(nick)s: %(reason)s" #: gajim/groupchat_control.py:2038 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "%(nick)s пакараны: %(reason)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "%s сышоў" #: gajim/groupchat_control.py:2067 #, python-format msgid "%s has joined the group chat" msgstr "%s далучыўся да групавой размовы" #: gajim/groupchat_control.py:2374 #, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Вы сапраўды хочаце сысці з групавой размовы \"%s\"?" #: gajim/groupchat_control.py:2376 msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "Калі Вы закрыеце гэтае вакно, Вы выйдзеце з гэтай групавой размовы." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 #, fuzzy msgid "_Do not ask me again" msgstr "_Больш не пытацца" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Пакаранне %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Вы можаце вызначыць прычыну:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Забарона казання для %s" #: gajim/chat_control.py:389 #, fuzzy msgid "Show a list of formattings" msgstr "Пстрыкніце, каб уставіць сымболік (Alt+M)" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 #, fuzzy msgid "This contact does not support HTML" msgstr "Спіс актыўных, скончаных і спыненых перадачаў файлаў" #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "" #: gajim/chat_control.py:660 #, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s з групавой размовы %(room_name)s" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "Вам адправіў паведамленне \"%s\"" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Калі Вы закрыеце гэтую картку з адключаным вядзеннем журналаў, гэтае " "паведамленне згубіцца." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "" #: gajim/chat_control.py:1205 #, python-format msgid "Pong! (%s seconds)" msgstr "" #: gajim/chat_control.py:1313 #, fuzzy, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Тэма: %s\n" "%s" #: gajim/chat_control.py:1416 #, fuzzy, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(nick)s цяпер %(status)s" #: gajim/chat_control.py:1471 #, fuzzy msgid "File transfer" msgstr "Перадача файлаў" #: gajim/chat_control.py:1474 #, fuzzy msgid "Size" msgstr "Памер: %s" #: gajim/chat_control.py:1476 #, fuzzy msgid "Accept" msgstr "Прыняць" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Далучыцца" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 #, fuzzy msgid "Remote contact stopped transfer" msgstr "Выдаліць чалавека з спіса" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 #, fuzzy msgid "Error opening file" msgstr "Памылка чытання файла:" #: gajim/application.py:68 #, fuzzy msgid "Show the application's version" msgstr "_Значка панэлі паведамленняў" #: gajim/application.py:75 #, fuzzy msgid "Show only critical errors" msgstr "Паказваць толькі ў _галоўным вакне" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 #, fuzzy msgid "Use defined profile in configuration directory" msgstr "Адмысловы рэдактар настаўленняў" #: gajim/application.py:105 #, fuzzy msgid "Set configuration directory" msgstr "Настаўленні пакоя" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 #, fuzzy msgid "Show all warnings" msgstr "Паказаць нягледжаныя _падзеі" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 msgid "Pops up a window with the next pending event" msgstr "Паказаць выплыўнае вакно з наступнай нягледжанай падзеяй" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 #, fuzzy msgid "Start a new chat" msgstr "Пачаць размову" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Аб'яднаныя рахункі" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Транспарты" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 msgid "Groupchats" msgstr "Групавыя размовы" #: gajim/roster_window.py:2056 #, fuzzy msgid "Authorization sent" msgstr "Адпраўленая аўтарызацыя" #: gajim/roster_window.py:2057 #, fuzzy, python-format msgid "\"%s\" will now see your status." msgstr "Цяпер \"%s\" можа бачыць Ваш стан." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Адпраўлены запыт на падпіску" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "Калі \"%s\" задаволіць гэты запыт, Вы зможаце бачыць яго стан." #: gajim/roster_window.py:2095 #, fuzzy msgid "Authorization removed" msgstr "Аўтарызацыя забраная" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "Цяпер \"%s\" будзе заўсёды бачыць Вас адлучаным." #: gajim/roster_window.py:2120 #, fuzzy msgid "OpenPGP is not usable" msgstr "Немагчыма ўжыць OpenPGP на гэтым кампутары" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Вы ўдзельнічаеце ў некалькіх групавых размовах" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Змяніўшы свой стан на нябачны, Вы такім чынам выйдзеце з гэтых групавых " "размоў. Вы сапраўды хочаце стаць нябачным?" #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "Адмысловы" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "" #: gajim/roster_window.py:2426 #, fuzzy msgid "Are you sure you want to quit Gajim?" msgstr "Вы сапраўды хочаце сысці з групавой размовы \"%s\"?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "" #: gajim/roster_window.py:2514 #, fuzzy msgid "You have running file transfers" msgstr "Скасаваць перадачу файла" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Ёсць нечытаныя паведамленні" #: gajim/roster_window.py:2547 #, fuzzy msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "Вы зможаце прачытаць нечытаныя паведамленні толькі з уключаным вядзеннем " "журналаў размоў." #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "Вы павінны прачытаць іх перад выдаленнем гэтага транспарта." #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Транспарт \"%s\" будзе выдалены" #: gajim/roster_window.py:2829 msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "Вы больш не зможаце мець зносіны з людзьмі праз гэты транспарт." #: gajim/roster_window.py:2832 msgid "Transports will be removed" msgstr "Транспарты будуць выдаленыя" #: gajim/roster_window.py:2837 #, fuzzy, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "Вы больш не зможаце мець зносіны з людзьмі праз гэтыя транспарты: %s" #: gajim/roster_window.py:2891 #, fuzzy msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "Вы ствараеце мета-кантакт. Вы сапраўды хочаце працягнуць?" #: gajim/roster_window.py:2893 msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" #: gajim/roster_window.py:2939 msgid "Rename Contact" msgstr "Змяніць імя чалавека" #: gajim/roster_window.py:2940 #, python-format msgid "Enter a new nickname for contact %s" msgstr "Вызначце новую мянушку для чалавека %s." #: gajim/roster_window.py:2947 msgid "Rename Group" msgstr "Змяніць назву групы" #: gajim/roster_window.py:2948 #, python-format msgid "Enter a new name for group %s" msgstr "Вызначце новую назву групы %s" #: gajim/roster_window.py:2993 msgid "Remove Group" msgstr "Выдаліць групу" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "Хочаце выдаліць групу %s з кантактнага ліста?" #: gajim/roster_window.py:2995 #, fuzzy msgid "Also remove all contacts in this group from your roster" msgstr "Таксама выдаліць усіх людзей з гэтай групы" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Прызначыць ключ OpenPGP" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "Выберыце ключ для гэтага чалавека" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "\"%s\" будзе выдалены з Вашага кантактнага ліста" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "" #: gajim/roster_window.py:3448 #, fuzzy msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "Выдаліўшы гэтых людзей:%s\n" "з Вашага кантактнага ліста, Вы такім чынам таксама прыбярэце ў іх " "аўтарызацыю, і яны заўсёды будуць бачыць Вас адлучаным." #: gajim/roster_window.py:3454 #, fuzzy msgid "Do you want to continue?" msgstr "Што Вы хочаце зрабіць?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "Выдаліўшы гэтага чалавека з Вашага кантактнага ліста, Вы звычайна такім " "чынам таксама прыбярэце ў яго аўтарызацыю, і ён заўсёды будзе бачыць Вас " "адлучаным." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Я хачу, каб гэты чалавек мог бачыць мой стан пасля выдалення" #: gajim/roster_window.py:3465 msgid "Contacts will be removed from your roster" msgstr "Людзі будуць выдаленыя з Вашага кантактнага ліста" #: gajim/roster_window.py:3470 #, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "Выдаліўшы гэтых людзей:%s\n" "з Вашага кантактнага ліста, Вы такім чынам таксама прыбярэце ў іх " "аўтарызацыю, і яны заўсёды будуць бачыць Вас адлучаным." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "Вы ствараеце мета-кантакт. Вы сапраўды хочаце працягнуць?" #: gajim/roster_window.py:3531 #, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Рахункаў няма" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "Вы павінны стварыць рахунак, каб размаўляць з іншымі людзьмі." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "Сервер не падтрымлівае сховішча мета-кантактаў" #: gajim/roster_window.py:4180 #, fuzzy msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" "Сервер не падтрымлівае мета-кантакты. Гэтае настаўленне не захаваецца для " "наступных сеансаў." #: gajim/roster_window.py:4276 msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "Вы ствараеце мета-кантакт. Вы сапраўды хочаце працягнуць?" #: gajim/roster_window.py:4278 #, fuzzy msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" "Мета-кантакты дазваляюць згрупаваць некалькі кантактаў у адным элеменце " "кантактнага ліста. Звычайна ўжываецца, калі ў чалавека некалькі рахункаў " "Jabber альбо некалькі транспартных рахункаў." #: gajim/roster_window.py:4400 #, fuzzy msgid "Invalid file URI:" msgstr "Няправільны файл" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Адправіць _файл" #: gajim/roster_window.py:4412 #, fuzzy, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "%s хоча адправіць Вам файл:" msgstr[1] "%s хоча адправіць Вам файл:" msgstr[2] "%s хоча адправіць Вам файл:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Адправіць %s" #: gajim/roster_window.py:4565 #, fuzzy, python-format msgid "Make %s first contact" msgstr "Зрабіць %s і %s мета-кантактамі" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Зрабіць %s і %s мета-кантактамі" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "З_мяніць паведамленне аб стане" #: gajim/roster_window.py:4965 #, fuzzy msgid "Publish Tune" msgstr "_Абнавіць" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "_Абнавіць" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "_Праглядзець сервісы..." #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 msgid "Send Group M_essage" msgstr "Ад_правіць групавое паведамленне" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "Усім карыстальнікам" #: gajim/roster_window.py:5135 msgid "To all online users" msgstr "Усім актыўным карыстальнікам" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "За_прасіць" #: gajim/roster_window.py:5299 #, fuzzy msgid "_Manage Contacts" msgstr "Змяніць імя чалавека" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Змяніць _групы" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "Вы_даліць" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "" #: gajim/roster_window.py:5370 #, fuzzy msgid "_Reconnect" msgstr "Чалавек адлучыўся" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 #, fuzzy msgid "_Disconnect" msgstr "Чалавек адлучыўся" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Журнал" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Кіраўнік журналаў" #: gajim/roster_window.py:5475 msgid "_Join New Group Chat" msgstr "_Удзельнічаць у групавой размове" #: gajim/config.py:359 msgid "Ban List" msgstr "Чорны спіс" #: gajim/config.py:360 msgid "Member List" msgstr "Спіс удзельнікаў" #: gajim/config.py:360 msgid "Owner List" msgstr "Спіс уладальнікаў" #: gajim/config.py:361 msgid "Administrator List" msgstr "Спіс адміністратараў" #: gajim/config.py:435 msgid "Reason" msgstr "Прычына" #: gajim/config.py:442 msgid "Nick" msgstr "Мянушка" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "Роля" #: gajim/config.py:478 #, fuzzy msgid "Banning…" msgstr "Забараніць казанне..." #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Каму Вы хочаце забараніць казанне?\n" "\n" #: gajim/config.py:482 #, fuzzy msgid "Adding Member…" msgstr "Дадаць ўдзельніка..." #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" "Каго Вы хочаце зрабіць удзельнікам?\n" "\n" #: gajim/config.py:485 #, fuzzy msgid "Adding Owner…" msgstr "Дадаць уладальніка..." #: gajim/config.py:486 msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "" "Каго Вы хочаце зрабіць уладальнікам?\n" "\n" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "Дадаць адміністратара..." #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" "Каго Вы хочаце зрабіць адміністратарам?\n" "\n" #: gajim/config.py:490 #, fuzzy msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" "Мажлівыя варыянты:\n" "1. user@domain/resource (толькі гэты рэсурс).\n" "2. user@domain (любы рэсурс).\n" "3. domain/resource (толькі гэты рэсурс).\n" "4. domain (гэты домэн user@domain,\n" "domain/resource ці адрас паддамена)." #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Выдаленне рахунка %s" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Шыфраванне адключанае" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Патрабуецца пароль" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Увядзіце пароль для рахунка %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Захаваць пароль" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Рахунак \"%s\" злучаны з серверам" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Калі Вы выдаліце яго, згубіцца злучэнне." #: gajim/config.py:652 #, fuzzy, python-format msgid "Connection to server %s failed" msgstr "Памылка злучэння" #: gajim/config.py:653 #, fuzzy msgid "What would you like to do?" msgstr "Што Вы хочаце зрабіць?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Выдаліць рахунак _толькі для Gajim" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Файлы Wav" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "Атрыманае першае паведамленне" #: gajim/config.py:746 msgid "First Message Received" msgstr "Атрыманае першае паведамленне" #: gajim/config.py:747 #, fuzzy msgid "Next Message Received Focused" msgstr "Атрыманае наступнае паведамленне" #: gajim/config.py:748 #, fuzzy msgid "Next Message Received Unfocused" msgstr "Атрыманае наступнае паведамленне" #: gajim/config.py:749 msgid "Contact Connected" msgstr "Чалавек далучыўся" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "Чалавек адлучыўся" #: gajim/config.py:751 msgid "Message Sent" msgstr "Паведамленне адпраўленае" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "Фарбаванае паведамленне ў групавой размове" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "Новае паведамленне ў групавой размове" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "%(owner_or_admin_or_member)s гэтай групавой размовы" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 msgid "?Group Chat Contact Affiliation:None" msgstr "?Адносіны ўдзельніка групавой размовы:Няма" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 msgid "Member" msgstr "Удзельнік" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 msgid "Administrator" msgstr "Адміністратар" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 msgid "Owner" msgstr "Уладальнік" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr "" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr "" #: gajim/tooltips.py:574 #, fuzzy msgid "Connected" msgstr "Злучэнне" #: gajim/tooltips.py:576 #, fuzzy msgid "Disconnected" msgstr "Чалавек адлучыўся" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Сцягнуць" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Загрузіць" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Тып: " #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Перададзена: " #: gajim/tooltips.py:645 msgid "Status: " msgstr "Стан: " #: gajim/tooltips.py:647 #, fuzzy msgid "Description: " msgstr "Апісанне: %s" #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Скончаная" #: gajim/tooltips.py:676 msgid "?transfer status:Paused" msgstr "?transfer status:Прыпыненая" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "Марнаванне часу" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "Перадача" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "Не пачатая" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "?transfer status:Прыпыненая" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Магу размаўляць" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Сышоў" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Заняты" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Мяне няма" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Адключаны" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "З_мяніць паведамленне аб стане" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "выкарыстоўвае рахунак %s" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Кіраванне закладкамі" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "Няма ў спісе" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "Паказаць _галоўнае вакно" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Схаваць гэтае меню" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Немагчыма загрузіць модуль idle" #: gajim/dataforms_widget.py:586 #, fuzzy, python-format msgid "Media type not supported: %s" msgstr "Пашырэнне не падтрымліваецца" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "Гэты сервіс яшчэ не адказаў на запыт падрабязных звестак" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "Гэты сервіс не дае падрабязных звестак.\n" "Хутчэй за ўсё, гэты сервіс састарэлы ці зламаны" #: gajim/disco.py:121 msgid "Others" msgstr "Іншыя" #: gajim/disco.py:125 msgid "Conference" msgstr "Канферэнцыі" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "" "Вы не можаце праглядзець спіс даступных сервісаў, не злучыўшыся з серверам." #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "Пошук сервісаў для рахунка %s" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Пошук сервісаў" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "Немагчыма знайсці сервіс" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "Па вызначаным адрасе няма сервісаў, альбо яны не адказваюць на запыты. " "Праверце адрас і паспрабуйце зноў." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "Немагчыма праглядзець сервіс" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "Гэты сервіс не ўтрымлівае ў сабе элементаў." #: gajim/disco.py:726 gajim/disco.py:736 #, fuzzy msgid "Invalid Server Name" msgstr "Няправільнае імя карыстальніка" #: gajim/disco.py:794 #, fuzzy, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "Прагляд %s для рахунка %s" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Праглядзець" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "Гэты сервіс не ўтрымлівае ў сабе элементаў, якія можна праглядзець." #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "_Выканаць загад..." #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "Зарэ_гістравацца" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "_Далучыцца" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "Пошук" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Змяніць" #: gajim/disco.py:1450 #, fuzzy, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "Пошук у %d / %d.." #: gajim/disco.py:1649 msgid "Users" msgstr "Карыстальнікі" #: gajim/disco.py:1657 msgid "Description" msgstr "Апісанне" #: gajim/disco.py:1665 msgid "Id" msgstr "Id" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 #, fuzzy msgid "_Bookmark" msgstr "_Змясціць у закладках" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Закладка ўжо ўсталяваная" #: gajim/disco.py:1722 #, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "Групавая размова \"%s\" ужо знаходзіцца ў Вашых закладках." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Закладка паспяхова дададзеная" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "" "Вы можаце рэдагаваць спіс Вашых закладак праз меню \"Дзеянні\" галоўнага " "вакна." #: gajim/disco.py:1929 msgid "Subscribed" msgstr "Падпісаны" #: gajim/disco.py:1938 #, fuzzy msgid "Node" msgstr "Ніякі" #: gajim/disco.py:2005 msgid "New post" msgstr "Новы допіс" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "Падп_ісацца" #: gajim/disco.py:2017 msgid "_Unsubscribe" msgstr "_Адпісацца" #: gajim/conversation_textview.py:320 #, fuzzy msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "Тэкст пад гэтай рысаю ёсць тэкстам, які Вы яшчэ не бачылі" #: gajim/conversation_textview.py:541 #, fuzzy msgid "_Quote" msgstr "_Выйсці" #: gajim/conversation_textview.py:549 #, python-format msgid "_Actions for \"%s\"" msgstr "_Дзеянні для \"%s\"" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Прачытаць артыкул у _Вікіпедыі" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Шукаць у _слоўніку" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "У адрасе слоўніка не хапае \"%s\", і гэта не Вікі-слоўнік" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "У адрасе пошуку ў Сеціве не хапае \"%s\"" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "_Шукаць у Сеціве" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "Адкрыць _спасылку" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "Няправільны JID" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, fuzzy, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "Учора" msgstr[1] "Учора" msgstr[2] "Учора" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Не пачатая" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Тэма: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Новае прыватнае паведамленне" #: gajim/message_window.py:243 #, fuzzy msgid "You are going to close several tabs" msgstr "Вы не злучаны з серверам" #: gajim/message_window.py:244 #, fuzzy msgid "Do you really want to close them all?" msgstr "Вы сапраўды хочаце выдаліць выбранае паведамленне?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Групавыя размовы" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "Прыватныя размовы" #: gajim/message_window.py:530 msgid "Messages" msgstr "Паведамленні" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 msgid "Unable to join group chat" msgstr "Немагчыма ўвайсці ў групавую размову" #: gajim/gui_interface.py:170 #, fuzzy, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "Гэтая мянушка ўжо ўжытая альбо зарэгістраваная іншым чалавекам.\n" "Выберыце іншую мянушку:" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Хочаце задаволіць гэты запыт?" #: gajim/gui_interface.py:194 #, fuzzy, python-format msgid "Do you accept this request on account %s?" msgstr "Хочаце задаволіць гэты запыт?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "HTTP (%s) аўтарызацыя для %s (id: %s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 msgid "Connection Failed" msgstr "Памылка злучэння" #: gajim/gui_interface.py:327 #, fuzzy, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "Каб удзельнічаць у гэтай групавой размове, трэба ведаць пароль." #: gajim/gui_interface.py:342 #, fuzzy, python-format msgid "%s is full" msgstr "Гукі" #: gajim/gui_interface.py:351 #, fuzzy, python-format msgid "You are banned from group chat %s." msgstr "Вам забаронена казанне ў гэтай групавой размове." #: gajim/gui_interface.py:358 #, fuzzy, python-format msgid "Remote server %s does not exist." msgstr "Такой групавой размовы няма." #: gajim/gui_interface.py:362 #, fuzzy, python-format msgid "Group chat %s does not exist." msgstr "Такой групавой размовы няма." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "Стварэнне групавых размоў абмежаванае." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Немагчыма ўвайсці ў групавую размову" #: gajim/gui_interface.py:368 #, fuzzy, python-format msgid "You must use your registered nickname in %s." msgstr "Вы павінны карыстацца зарэгістраванай для Вас мянушкай." #: gajim/gui_interface.py:373 #, fuzzy, python-format msgid "You are not in the members list in groupchat %s." msgstr "Вас няма ў спісе ўдзельнікаў." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, fuzzy, python-format msgid "Error %(code)s: %(msg)s" msgstr "%(nickname)s: %(message)s" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, fuzzy, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "памылка адпраўкі %s ( %s )" #: gajim/gui_interface.py:503 gajim/notify.py:194 #, fuzzy msgid "Subscription request" msgstr "Запыт падпіскі" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "Назіральнікі" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Паспяховая аўтарызацыя" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "Чалавек \"%s\" дазволіў Вам бачыць змены яго стану." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Чалавек \"%s\" забраў у Вас аўтарызацыю" #: gajim/gui_interface.py:539 msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" #: gajim/gui_interface.py:560 gajim/notify.py:194 #, fuzzy msgid "Unsubscribed" msgstr "_Адпісацца" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, fuzzy, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Вы не ўвайшлі ў пакой групавой размовы." #: gajim/gui_interface.py:658 msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "Вы злучаны без выкарыстання ключа OpenPGP." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Няправільны пароль" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Няправільны пароль" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "Патрэбны пароль" #: gajim/gui_interface.py:683 #, fuzzy, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Вызначце пароль GPG для рахунка %s." #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Выберыце Ваш ключ OpenPGP" #: gajim/gui_interface.py:706 msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Памылка перадачы файла" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "%s хоча адправіць Вам файл." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Запыт на перадачу файла" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Перадача файла скончаная" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Перадача файла спыненая" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Перадача файлаў" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Перадача файла %(filename)s ад %(name)s спыненая." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Перадача файла %(filename)s ад %(name)s спыненая." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Перадача файла %(filename)s ад %(name)s спыненая." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Вы паспяхова адправілі файл %(filename)s для %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Перадача файла %(filename)s для %(name)s спыненая." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Перадача файла %(filename)s для %(name)s спыненая." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "Канфлікт імёнаў карыстальнікаў" #: gajim/gui_interface.py:1178 msgid "Please type a new username for your local account" msgstr "Вызначце імя карыстальніка для мясцовага рахунка" #: gajim/gui_interface.py:1201 #, fuzzy msgid "Resource Conflict" msgstr "Канфлікт імёнаў карыстальнікаў" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "" #: gajim/gui_interface.py:1259 #, fuzzy, python-format msgid "%s wants to start a voice chat." msgstr "%s хоча адправіць Вам файл." #: gajim/gui_interface.py:1261 #, fuzzy msgid "Voice Chat Request" msgstr "Запыт на перадачу файла" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 #, fuzzy msgid "Certificate Already in File" msgstr "Чалавек ужо ёсць у кантактным лісце" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" #: gajim/gui_interface.py:1351 #, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "" #: gajim/gui_interface.py:1354 #, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "" #: gajim/gui_interface.py:1362 #, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "" #: gajim/gui_interface.py:1380 #, fuzzy, python-format msgid "SSL Certificate Verification for %s" msgstr "Дадаць асабістае нагадванне для %s" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 #, fuzzy msgid "Insecure connection" msgstr "Злучэнне" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "Вы ствараеце мета-кантакт. Вы сапраўды хочаце працягнуць?" #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "" "Вы не можаце ўдзельнічаць у групавой размове, не злучыўшыся з серверам." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Гэта не групавая размова" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "Гэта не групавая размова" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 msgid "You cannot join a group chat while you are invisible" msgstr "Вы не можаце ўдзельнічаць у групавой размове нябачным" #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Немагчыма захаваць настаўленні" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Патрэбны пароль" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "Вызначце пароль GPG для рахунка %s." #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "Выбар ключоў OpenPGP" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "Вы злучыцеся з %s без падтрымкі OpenPGP." #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "Няправільны пароль" #: gajim/gui_interface.py:2853 #, fuzzy msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "Паўтарыце ўвод пароля GPG альбо пстрыкніце Скасаваць." #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "Піша" #: gajim/atom_window.py:123 #, fuzzy, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "Вы атрымалі новае паведамленне:" msgstr[1] "Вы атрымалі новае паведамленне:" msgstr[2] "Вы атрымалі новае паведамленне:" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "Вы атрымалі новае паведамленне:" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "Свае загады - Gajim" #: gajim/adhoc_commands.py:326 #, fuzzy msgid "Cancel confirmation" msgstr "Асабістыя звесткі" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "" #: gajim/adhoc_commands.py:422 #, fuzzy, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "Свае загады - Gajim" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Чалавек прыйшоў" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Чалавек сышоў" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Новае паведамленне" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Новае асобнае паведамленне" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Новае прыватнае паведамленне" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 msgid "Contact Changed Status" msgstr "Чалавек змяніў стан" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenPGP: " #: gajim/notify.py:270 msgid "New E-mail" msgstr "Новы ліст" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "" "Вы не можаце ўдзельнічаць у групавой размове, не злучыўшыся з серверам." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 msgid "Invalid JID" msgstr "Няправільны JID" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, fuzzy, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "Немагчыма адправіць пусты файл" #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "Нягледжаныя падзеі" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "Прагледзьце нягледжаныя падзеі перад выдаленнем гэтага рахунка." #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "Вы злучаны з серверам" #: gajim/dialog_messages.py:53 #, fuzzy msgid "To disable the account, you must be disconnected." msgstr "Каб змяніць назву рахунка, трэба папярэдне адлучыцца." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Няправільны элемент" #: gajim/dialog_messages.py:58 #, fuzzy msgid "The form is not filled correctly." msgstr "Jabber ID групавой размовы ўтрымлівае няправільныя знакі." #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Нябачны" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "Няма злучэння" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "Вы не можаце адпраўляць паведамленні без злучэння." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "Jabber-праграма" #: gajim/dialog_messages.py:73 msgid "The JID you entered is already in the list. Choose another one." msgstr "" #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "Няправільны адказ" #: gajim/dialog_messages.py:78 #, fuzzy, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "Транспарт %s некарэктна адказаў, каб зарэгістраваць запыт: %s" #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Адмысловы вузел / порт" #: gajim/dialog_messages.py:84 #, fuzzy, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Адмысловы вузел / порт" #: gajim/dialog_messages.py:88 msgid "Error while removing privacy list" msgstr "Памылка ў часе выдалення спіса прыватнасці" #: gajim/dialog_messages.py:89 #, fuzzy, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" "Спіс прыватнасці %s не выдалены. Магчыма, ён ужываецца ў адным з Вашых " "злучаных рэсурсаў. Дэактывізуйце іх і паўтарыце свае дзеянні." #: gajim/dialog_messages.py:95 #, fuzzy msgid "Invisibility not supported" msgstr "Пашырэнне не падтрымліваецца" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "" #: gajim/dialog_messages.py:100 #, fuzzy msgid "Unregister failed" msgstr "Памылка злучэння" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "" #: gajim/dialog_messages.py:105 #, fuzzy msgid "Registration succeeded" msgstr "Зарэгістравацца на %s" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 #, fuzzy msgid "Registration failed" msgstr "Памылка злучэння" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Немагчыма ўвайсці ў групавую размову" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, fuzzy, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "Памылка: %s" #: gajim/dialog_messages.py:126 msgid "Wrong host" msgstr "Няправільны вузел" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "Памылка Avahi" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" "%s\n" "Мясцовыя паведамленні могуць не працаваць." #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 #, fuzzy msgid "Could not request upload slot" msgstr "Немагчыма стартаваць мясцовы сервіс" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 #, fuzzy msgid "Could not open file" msgstr "Немагчыма загрузіць малюнак" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 msgid "Server returned unsecure transport (HTTP)" msgstr "" #: gajim/dialog_messages.py:161 #, fuzzy msgid "Could not upload file" msgstr "Немагчыма загрузіць малюнак" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 #, fuzzy msgid "Encryption Error" msgstr "Шыфраванне дзейнічае" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "Няма злучэння" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "Памылка абнаўлення vCard" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "D-Bus няма на гэтым кампутары, альбо няма адпаведнага модуля python" #: gajim/gajim_remote.py:77 msgid "Shows a help on specific command" msgstr "Паказвае даведку па вызначаным загадзе" #: gajim/gajim_remote.py:80 msgid "command" msgstr "загад" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "паказаць даведку па загадзе" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "Паказаць спіс усіх людзей у кантактным лісце. Звесткі пра кожнага чалавека " "друкуюцца на асобным радку" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "рахунак" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "паказаць людзей з пэўнага рахунка" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "Паказаць спіс зарэгістраваных рахункаў" #: gajim/gajim_remote.py:97 #, fuzzy msgid "Changes the status of account(s)" msgstr "Змяніць стан рахунка(ў)" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "стан" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "адзін з: offline, online, chat, away, xa, dnd, invisible " #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "паведамленне" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "паведамленне стану" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "змяніць стан рахунка \"account\". Калі не вызначана, змяняецца стан усіх " "рахункаў, якія \"сінхранізуюцца з глабальным станам\"" #: gajim/gajim_remote.py:108 #, fuzzy msgid "Changes the priority of account(s)" msgstr "Змяніць стан рахунка(ў)" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "Прыяры_тэт:" #: gajim/gajim_remote.py:110 #, fuzzy msgid "priority you want to give to the account" msgstr "_Зарэгістраваць новы рахунак" #: gajim/gajim_remote.py:112 #, fuzzy msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "змяніць стан рахунка \"account\". Калі не вызначана, змяняецца стан усіх " "рахункаў, якія \"сінхранізуюцца з глабальным станам\"" #: gajim/gajim_remote.py:118 msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Адпраўляе новае паведамленне чалавеку з спіса. Выстаўленне ключа OpenPGP і " "рахунка не абавязковае. Калі Вы хочаце вызначыць толькі 'account', без " "'ключа OpenPGP', проста выставіце 'ключ OpenPGP' у ''." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID чалавека, які атрымае паведамленне" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "змест паведамлення" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "Калі вызначана, паведамленне будзе зашыфраванае адкрытым ключом" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "Калі вызначана, паведамленне будзе адпраўленае праз гэты рахунак" #: gajim/gajim_remote.py:131 #, fuzzy msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Адпраўляе новае паведамленне чалавеку з спіса. Выстаўленне ключа OpenPGP і " "рахунка не абавязковае. Калі Вы хочаце вызначыць толькі 'account', без " "'ключа OpenPGP', проста выставіце 'ключ OpenPGP' у ''." #: gajim/gajim_remote.py:136 msgid "subject" msgstr "тэма" #: gajim/gajim_remote.py:136 msgid "message subject" msgstr "тэма паведамлення" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "" #: gajim/gajim_remote.py:147 #, fuzzy msgid "JID of the room that will receive the message" msgstr "JID чалавека, які атрымае паведамленне" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Атрымаць падрабязныя звесткі пра чалавека" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "JID чалавека" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "Атрымаць падрабязныя звесткі аб рахунку" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "Назва рахунка" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Адправіць файл чалавеку" #: gajim/gajim_remote.py:168 msgid "file" msgstr "файл" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Месца файла" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "Калі вызначана, файл будзе адпраўлены праз гэты рахунак" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Паказаць спіс усіх настаўленняў і іх значэнні" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "Выстаўляе значэнне 'ключа' ў 'значэнне'" #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "ключ=значэнне" #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "'ключ' ёсць назваю настаўлення, 'значэнне' ёсць выстаўляемым значэннем" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "Выдаляе ўласцівасць" #: gajim/gajim_remote.py:188 msgid "key" msgstr "ключ" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "назва выдаляемай уласцівасці" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "Запісвае бягучыя настаўленні Gajim у файл .config" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Выдаліць чалавека з спіса" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "Калі вызначана, то імя чалавека выбіраецца з спіса гэтага рахунка" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "Вяртае бягучы стан (глабальны, калі не вызначаны рахунак)" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" "Вяртае бягучае паведамленне аб стане (глабальнае, калі не вызначаны рахунак)" #: gajim/gajim_remote.py:221 msgid "Returns number of unread messages" msgstr "Вяртае колькасць нечытаных паведамленняў" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "Адправіць асаблівы XML" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "Адправіць XML" #: gajim/gajim_remote.py:229 #, fuzzy msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" "Рахунак, на які будзе адпраўлены xml; калі не вызначаны, xml будзе " "адпраўлены на ўсе рахункі" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Змяніць стан" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "Мянушка не знойдзеная: %s" #: gajim/gajim_remote.py:238 #, fuzzy msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" "Рахунак, на які будзе адпраўлены xml; калі не вызначаны, xml будзе " "адпраўлены на ўсе рахункі" #: gajim/gajim_remote.py:245 #, fuzzy msgid "Check if Gajim is running" msgstr "Праверце, ці працуе avahi-daemon." #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "Не хапае аргумента \"contact_jid\"" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "'%s' няма ў Вашым спісе.\n" "Калі ласка, вызначце рахунак для адпраўкі паведамлення." #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "У Вас няма актыўнага рахунка" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "" #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Аргументы:" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "%s не знойдзены" #: gajim/gajim_remote.py:383 #, fuzzy, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Карыстанне: %s загад [аргументы]\n" "Загад ёсць адным з:\n" #: gajim/gajim_remote.py:453 #, fuzzy, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Надта шмат аргументаў. \n" "Увядзіце \"%s help %s\" для падрабязнейшых звестак" #: gajim/gajim_remote.py:458 #, fuzzy, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Аргумент \"%s\" не вызначаны. \n" "Увядзіце \"%s help %s\" для падрабязных звестак" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "дванаццаць" #: gajim/common/fuzzyclock.py:36 msgid "one" msgstr "адзін" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "два" #: gajim/common/fuzzyclock.py:36 msgid "three" msgstr "тры" #: gajim/common/fuzzyclock.py:36 msgid "four" msgstr "чатыры" #: gajim/common/fuzzyclock.py:37 msgid "five" msgstr "пяць" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "шэсць" #: gajim/common/fuzzyclock.py:37 msgid "seven" msgstr "сем" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "восем" #: gajim/common/fuzzyclock.py:37 msgid "nine" msgstr "дзевяць" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "дзесяць" #: gajim/common/fuzzyclock.py:38 msgid "eleven" msgstr "адзінаццаць" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "%(0)s гадзінаў" #: gajim/common/fuzzyclock.py:46 #, python-format msgid "five past %(0)s" msgstr "пяць хвілінаў на %(0)s" #: gajim/common/fuzzyclock.py:47 #, python-format msgid "ten past %(0)s" msgstr "дзесяць хвілінаў на %(0)s" #: gajim/common/fuzzyclock.py:48 #, python-format msgid "quarter past %(0)s" msgstr "чвэрць на %(0)s" #: gajim/common/fuzzyclock.py:49 #, python-format msgid "twenty past %(0)s" msgstr "дваццаць хвілінаў на %(0)s" #: gajim/common/fuzzyclock.py:50 #, python-format msgid "twenty five past %(0)s" msgstr "дваццаць пяць хвілінаў на %(0)s" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "палова на %(0)s" #: gajim/common/fuzzyclock.py:52 #, python-format msgid "twenty five to %(1)s" msgstr "без дваццаці пяці хвілінаў %(1)s" #: gajim/common/fuzzyclock.py:53 #, python-format msgid "twenty to %(1)s" msgstr "без дваццаці хвілінаў %(1)s" #: gajim/common/fuzzyclock.py:54 #, python-format msgid "quarter to %(1)s" msgstr "без чвэрці %(1)s" #: gajim/common/fuzzyclock.py:55 #, fuzzy, python-format msgid "ten to %(1)s" msgstr "дзесяць хвілінаў на $s" #: gajim/common/fuzzyclock.py:56 #, python-format msgid "five to %(1)s" msgstr "без пяці хвілінаў %(1)s" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "%(1)s гадзінаў" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "Ноч" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "Світанак" #: gajim/common/fuzzyclock.py:63 msgid "Morning" msgstr "Раніца" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "Амаль дзень" #: gajim/common/fuzzyclock.py:65 msgid "Noon" msgstr "Полудзень" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "Абед" #: gajim/common/fuzzyclock.py:67 msgid "Evening" msgstr "Вечар" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "Позні вечар" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "Пачатак тыдня" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "Сярэдзіна тыдня" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "Канец тыдня" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "Выходныя!" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, python-format msgid "%s is a directory but should be a file" msgstr "%s з'яўляецца дырэкторыяй, але павінны быць файл" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Апісанне: %s" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 #, fuzzy msgid "Room has been destroyed" msgstr "Аўтарызацыя забраная" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "" #: gajim/common/connection_handlers_events.py:598 #, python-format msgid "Unknown SSL error: %d" msgstr "" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Новае паведамленне ад %(nickname)s" msgstr[1] "Новае паведамленне ад %(nickname)s" msgstr[2] "Новае паведамленне ад %(nickname)s" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s змяніў стан" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s прыйшоў" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "%(nickname)s сышоў" #: gajim/common/contacts.py:427 msgid "Not in roster" msgstr "Няма ў спісе" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "" #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "Праз колькі хвілінаў змяняць стан на сышоўшы." #: gajim/common/config.py:87 #, fuzzy msgid "$S (Away as a result of being idle more than $T min)" msgstr "Сышоў як вынік марнавання часу" #: gajim/common/config.py:87 msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "Праз колькі хвілінаў змяняць стан на недаступны." #: gajim/common/config.py:90 #, fuzzy msgid "$S (Not available as a result of being idle more than $T min)" msgstr "Недаступны ў выніку марнавання часу" #: gajim/common/config.py:90 msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" #: gajim/common/config.py:93 msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "_Паказваць падзею ў галоўным вакне" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "_Паказваць падзею ў галоўным вакне" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "_Паказваць падзею ў галоўным вакне" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Запыт на перадачу файла" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Перадача файла скасаваная" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "Паказаць нагадванне па сканчэнні перадачы файла" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "Запрашэнне ў групавую размову" #: gajim/common/config.py:106 #, fuzzy msgid "Background color of status changed notification" msgstr "Фонавы колер для толькі ўвайшоўшых людзей." #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "Спіс падзеленых прагаламі згорнутых рахункаў і групаў." #: gajim/common/config.py:109 #, fuzzy msgid "default" msgstr "Прадвызначана" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "Мова правапісу" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" "'always' - паказваць час кожнага паведамлення.\n" "'sometimes' - паказваць час кожныя print_ichat_every_foo_minutes хвілінаў.\n" "'never' - не паказваць час." #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" "Паказваць час у вокнах размовы прыблізна. Значэнне прыблізнасці ад 1 да 4, " "альбо 0, каб адключыць прыблізнасць. 1 паказвае самы дакладны час, 4 " "паказвае самы прыблізны. Працуе, калі опцыя print_time мае значэнне " "'sometimes'." #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "Лічыць спалучэнні * / _ мажлівымі знакамі фарматавання." #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "Калі true, не выдаляць */_ . Такім чынам, *abc* будзе тлустым, але * * не " "выдаляецца." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" "Ужыць рэструктураваную мову тэкставай разметкі для адпраўлення HTML, а " "таксама фарматаванне ASCII, калі ўключаная адпаведная опцыя. Глядзіце " "сінтаксіс на http://docutils.sourceforge.net/docs/ref/rst/restructuredtext." "html (калі Вы хочаце ўжыць гэтую магчымасць, усталюйце docutils)" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "Знак пасля дапоўненай мянушкі ў групавой размове." #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "Знак пасля вызначанай мянушкі, калі яе згадваюць у групавой размове." #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" "З дапамогай гэтай опцыі Вы можаце змяніць фармат часавых мецінаў, якія " "паказваюцца ў вокнах размовы. Напр., \"[%H:%M] \" азначае, што трэба " "паказваць \"[гадзінаў:хвілінаў] \". Глядзіце падрабязную інфармацыю ў " "дакументацыі для python на функцыю strftime: http://docs.python.org/lib/" "module-time.html" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "Знакі, якія друкуюцца ў вокнах размовы перад мянушкай" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "Знакі, якія друкуюцца ў вокнах размовы пасля мянушкі" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Дадаць * і [n] у назву галоўнага вакна?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Колькі радкоў помніць з апошняй размовы, калі размова наноў адкрываецца." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" #: gajim/common/config.py:177 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" "Адпраўляць паведамленне праз Ctrl+Enter, а Enter стварае новы радок " "(стандартныя паводзіны Mirabilis ICQ)." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Колькі радкоў захоўваць для Ctrl+KeyUP." #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Альбо адмысловы адрас з %s, дзе %s ёсць словам/выразам, альбо 'WIKTIONARY', " "што значыць выкарыстанне Вікі-Слоўніка." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "" "Калі гэтая опцыя ўключаная, Gajim можа кантралявацца з дапамогай gajim-" "remote." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" "Адпраўляць паведамленні аб стане размовы. Адно з наступных значэнняў: all, " "composing_only, disabled." #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" "Паказваць паведамленні аб стане размовы. Адно з наступных значэнняў: all, " "composing_only, disabled." #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" "Калі трэба паказваць час не для кожнага паведамлення " "(print_time==sometimes), паказваць яго кожныя x хвілінаў." #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Пытацца пацверджання закрыцця групавой размовы." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" "Заўсёды пытацца пацверджання закрыцця групавых размоў з гэтага спіса " "падзеленых прагаламі назваў групавых размоў." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" "Ніколі не пытацца пацверджання закрыцця групавых размоў з гэтага спіса " "падзеленых прагаламі назваў групавых размоў." #: gajim/common/config.py:196 msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" #: gajim/common/config.py:199 #, fuzzy msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" "Вызначае вузел, якому мы адпраўляем файлы, у выпадку трансляцыі адрасоў / " "перанакіравання портаў." #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "У стандарце IEC вызначана, што КіБ = 1024 байтаў, КБ = 1000 байтаў." #: gajim/common/config.py:202 #, fuzzy msgid "Notify of events in the notification area." msgstr "Нагадваць аб падзеях праз значку прасторы паведамленняў." #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Паказваць картку, калі актыўная толькі адна размова?" #: gajim/common/config.py:210 msgid "Show tabbed notebook border in chat windows?" msgstr "Паказваць межы картак у вокнах размовы?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Паказваць кнопку закрыцця на картцы?" #: gajim/common/config.py:224 msgid "Preview new messages in notification popup?" msgstr "" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" "Спіс падзеленых кропкай з коскай слоў, якія трэба фарбаваць у групавых " "размовах." #: gajim/common/config.py:228 #, fuzzy msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" "Калі true, Gajim сканчвае работу па націску кнопкі X вакна. Гэтае " "настаўленне ўлічваецца толькі разам з значкай прасторы паведамленняў." #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 #, fuzzy msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" "Калі true, Gajim паказвае значку на кожнай картцы з нечытанымі " "паведамленнямі. У залежнасці ад тэмы, гэтая значка можа быць і анімаванай." #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "Калі true, Gajim паказвае стан у галоўным вакне для кожнага чалавека" #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "" #: gajim/common/config.py:238 #, fuzzy msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "Калі false, не паказваць паведамленні аб змене стану суразмоўцы." #: gajim/common/config.py:239 #, fuzzy msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" "магчымыя значэнні: \"none\", \"all\" альбо \"in_and_out\". Калі опцыя " "выстаўленая ў \"none\", Gajim не будзе паказваць паведамленні аб змене стану " "суразмоўцаў у вакне размовы. Калі опцыя выстаўленая ў \"all\", Gajim будзе " "паказваць усе такія паведамленні. Калі опцыя выстаўленая ў \"in_and_out\", " "Gajim будзе паказваць толькі паведамленні аб сыходзе / ўваходзе суразмоўцы." #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 #, fuzzy msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" "Калі true, адноўленыя з папярэдняга сеанса паведамленні будуць мець меншы " "памер шрыфта." #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "Не паказваць аватар для транспарта." #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "Не паказваць галоўнае вакно на панэлі заданняў." #: gajim/common/config.py:245 #, fuzzy msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" "Калі true і калі ўсталяваныя GTK+ і PyGTK версіі, вышэйшай за 2.8, міргаць " "вакном (звычайныя паводзіны ў бальшыні кіраўнікоў вокнаў) пры наяўнасці " "нягледжаных падзей." #: gajim/common/config.py:249 #, fuzzy msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" "Вызначае вакно для новых паведамленняў.\n" "'always' - Усе паведамленні адпраўляюцца ў адзінае вакно.\n" "'never' - Усе паведамленні адпраўляюцца ў асобныя вокны.\n" "'peracct' - Паведамленні ад кожнага рахунка адпраўляюцца ў асобнае вакно.\n" "'pertype' - Паведамленні аднаго тыпу (напр., прыватныя і групавыя) " "адпраўляюцца ў асобныя вокны. Зважайце, што гэтыя змены будуць ужытыя толькі " "пасля перазапуску праграмы." #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "Калі false, не паказваць аватары ў вакне размовы." #: gajim/common/config.py:252 #, fuzzy msgid "If true, pressing the escape key closes a tab/window." msgstr "Калі true, клавіша Escape закрывае картку / вакно." #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "Хавае банер у групавой размове" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "Хавае банер у прыватнай размове" #: gajim/common/config.py:255 msgid "Hides the group chat occupants list in group chat window." msgstr "Схаваць спіс удзельнікаў групавой размовы." #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" "У групавой размове не паказваць мянушку, калі папярэдняе паведамленне " "напісаў той самы чалавек." #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "Водступ пры шматмэтавым прызначэнні паведамлення." #: gajim/common/config.py:258 #, fuzzy msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "Спіс колераў для фарбавання мянушак у групавой размове." #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "" "Ctrl-Tab пераходзіць у наступную картку, калі няма нечытаных паведамленняў." #: gajim/common/config.py:260 #, fuzzy msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" "Ці трэба паказваць вакно пацверджання пры стварэнні мета-кантакта? Пусты " "радок адключае гэтае вакно." #: gajim/common/config.py:261 #, fuzzy msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" "Ці трэба паказваць вакно пацверджання пры стварэнні мета-кантакта? Пусты " "радок адключае гэтае вакно." #: gajim/common/config.py:262 #, fuzzy msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" "Ці трэба паказваць вакно пацверджання пры стварэнні мета-кантакта? Пусты " "радок адключае гэтае вакно." #: gajim/common/config.py:263 #, fuzzy msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" "Калі true, Вы зможаце выставіць для рахунка адмоўны прыярытэт. Увага: калі " "Вы ўвайшлі з адмоўным прыярытэтам, Вы не будзеце атрымліваць паведамленняў " "ад Вашага сервера." #: gajim/common/config.py:264 #, fuzzy msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" "Калі true, Gajim будзе паказваць у кантактным лісце колькасць падлучаных " "людзей і агульную колькасць у радках групаў і рахункаў." #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" "Можа мець значэнні 'chat', 'normal' альбо быць пустым. Калі не пустое, то " "лічыць усе ўваходныя паведамленні гэтага тыпу" #: gajim/common/config.py:266 msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" #: gajim/common/config.py:269 msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "" #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" #: gajim/common/config.py:272 msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 #, fuzzy msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" "Калі true, Gajim будзе захоўваць паролі ад рахункаў з дапамогай кіраўніка " "пароляў Gnome Keyring (калі ўсталяваны)." #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" "Аўтаматычна змяняць прыярытэт згодна з станам. Прыярытэты выстаўленыя ў " "опцыях autopriority_*." #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "" #: gajim/common/config.py:325 msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" #: gajim/common/config.py:326 #, fuzzy msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "Калі false, не паказваць аватары ў вакне размовы." #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "" #: gajim/common/config.py:337 msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "" #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "" #: gajim/common/config.py:354 msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "Выпраўленне хібы Jabberd2" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" "Калі выстаўленая гэтая опцыя, Gajim будзе ўжываць для перадачы файлаў " "выстаўленыя IP-адрас і проксі-серверы з параметра file_transfer_proxies." #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "" "Калі гэтая опцыя ўключаная, Gajim далучыцца да гэтай групавой размовы пры " "запуску" #: gajim/common/config.py:386 #, fuzzy msgid "Allow Gajim to send your local time." msgstr "%s хоча адправіць Вам файл." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Запоўніце палі звесткамі, каб дадаць чалавека ў спіс" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Аўтарызацыя" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Аўтарызацыя" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Аўтарызацыя" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 #, fuzzy msgid "Language for which misspelled words will be checked" msgstr "Мова праверкі правапісу" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" #: gajim/common/config.py:442 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "Сон" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Хутка буду" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Хутка буду." #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "Ежа" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "Ямо, пакіньце мне паведамленне." #: gajim/common/config.py:454 msgid "Movie" msgstr "Фільм" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "Гляджу фільм." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "Працую" #: gajim/common/config.py:455 msgid "I'm working." msgstr "Працую." #: gajim/common/config.py:456 msgid "Phone" msgstr "Тэлефон" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Я на тэлефоне." #: gajim/common/config.py:457 msgid "Out" msgstr "Сышоў" #: gajim/common/config.py:457 msgid "I'm out enjoying life." msgstr "Я цешуся з жыцця." #: gajim/common/config.py:468 msgid "I'm available." msgstr "Я даступны." #: gajim/common/config.py:469 msgid "I'm free for chat." msgstr "Я магу размаўляць." #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "Хутка прыйду." #: gajim/common/config.py:471 msgid "I'm not available." msgstr "Мяне няма." #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "Не турбаваць." #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "Бывай!" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" "Прайграць гэты гук, калі прыходзіць групавое паведамленне з адным з слоў, " "вызначаных у параметры muc_highlight_words, ці калі гэтае паведамленне " "ўтрымлівае Вашую мянушку." #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "Прайграць гук пры атрыманні паведамлення MUC." #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "Да" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Памылка: немагчыма прачытаць %s" #: gajim/common/const.py:205 #, fuzzy msgid "Doing Chores" msgstr "Няправільны вузел" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "" #: gajim/common/const.py:207 #, fuzzy msgid "Cleaning" msgstr "Вечар" #: gajim/common/const.py:208 #, fuzzy msgid "Cooking" msgstr "Піша" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "" #: gajim/common/const.py:212 #, fuzzy msgid "Gardening" msgstr "Раніца" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "" #: gajim/common/const.py:214 #, fuzzy msgid "Walking the Dog" msgstr "усе з групы" #: gajim/common/const.py:216 #, fuzzy msgid "Drinking" msgstr "Працую" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "" #: gajim/common/const.py:227 msgid "Exercising" msgstr "" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "" #: gajim/common/const.py:229 #, fuzzy msgid "Dancing" msgstr "Вечар" #: gajim/common/const.py:230 #, fuzzy msgid "Hiking" msgstr "Пакаранне %s" #: gajim/common/const.py:231 #, fuzzy msgid "Jogging" msgstr "_Далучыцца" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "" #: gajim/common/const.py:233 msgid "Running" msgstr "" #: gajim/common/const.py:234 #, fuzzy msgid "Skiing" msgstr "Працую" #: gajim/common/const.py:235 msgid "Swimming" msgstr "" #: gajim/common/const.py:236 #, fuzzy msgid "Working out" msgstr "Працую" #: gajim/common/const.py:238 #, fuzzy msgid "Grooming" msgstr "пакой" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "" #: gajim/common/const.py:242 #, fuzzy msgid "Shaving" msgstr "Ежа" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Неактыўны" #: gajim/common/const.py:249 msgid "Day Off" msgstr "" #: gajim/common/const.py:250 #, fuzzy msgid "Hanging out" msgstr "Змяненне тэмы" #: gajim/common/const.py:251 #, fuzzy msgid "Hiding" msgstr "Пакаранне %s" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "" #: gajim/common/const.py:253 #, fuzzy msgid "Praying" msgstr "Ежа" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "" #: gajim/common/const.py:256 #, fuzzy msgid "Thinking" msgstr "Працую" #: gajim/common/const.py:258 msgid "Relaxing" msgstr "" #: gajim/common/const.py:259 #, fuzzy msgid "Fishing" msgstr "Пакаранне %s" #: gajim/common/const.py:260 #, fuzzy msgid "Gaming" msgstr "Ежа" #: gajim/common/const.py:261 #, fuzzy msgid "Going out" msgstr "З_ысці" #: gajim/common/const.py:262 #, fuzzy msgid "Partying" msgstr "Ежа" #: gajim/common/const.py:263 #, fuzzy msgid "Reading" msgstr "Прычына" #: gajim/common/const.py:264 #, fuzzy msgid "Rehearsing" msgstr "Прычына" #: gajim/common/const.py:265 #, fuzzy msgid "Shopping" msgstr "Сон" #: gajim/common/const.py:266 #, fuzzy msgid "Smoking" msgstr "Працую" #: gajim/common/const.py:267 msgid "Socializing" msgstr "" #: gajim/common/const.py:268 #, fuzzy msgid "Sunbathing" msgstr "Ежа" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "" #: gajim/common/const.py:270 #, fuzzy msgid "Watching a Movie" msgstr "Гляджу фільм." #: gajim/common/const.py:272 #, fuzzy msgid "Talking" msgstr "Ежа" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "" #: gajim/common/const.py:274 #, fuzzy msgid "On the Phone" msgstr "Я на тэлефоне." #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "" #: gajim/common/const.py:277 #, fuzzy msgid "Traveling" msgstr "Перадача" #: gajim/common/const.py:278 #, fuzzy msgid "Commuting" msgstr "Піша" #: gajim/common/const.py:280 msgid "Driving" msgstr "" #: gajim/common/const.py:281 msgid "In a Car" msgstr "" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "" #: gajim/common/const.py:283 #, fuzzy msgid "On a Plane" msgstr "У сетцы" #: gajim/common/const.py:284 #, fuzzy msgid "On a Train" msgstr "Адкрыць _спасылку" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "" #: gajim/common/const.py:286 #, fuzzy msgid "Walking" msgstr "Працую" #: gajim/common/const.py:289 #, fuzzy msgid "Coding" msgstr "Піша" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "" #: gajim/common/const.py:291 msgid "Studying" msgstr "" #: gajim/common/const.py:292 #, fuzzy msgid "Writing" msgstr "Працую" #: gajim/common/const.py:295 msgid "Afraid" msgstr "" #: gajim/common/const.py:296 msgid "Amazed" msgstr "" #: gajim/common/const.py:297 msgid "Amorous" msgstr "" #: gajim/common/const.py:298 msgid "Angry" msgstr "" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "" #: gajim/common/const.py:300 msgid "Anxious" msgstr "" #: gajim/common/const.py:301 #, fuzzy msgid "Aroused" msgstr "Прыпынена" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "" #: gajim/common/const.py:303 #, fuzzy msgid "Bored" msgstr "Тлусты" #: gajim/common/const.py:304 #, fuzzy msgid "Brave" msgstr "Мае " #: gajim/common/const.py:305 msgid "Calm" msgstr "" #: gajim/common/const.py:306 #, fuzzy msgid "Cautious" msgstr "Размовы" #: gajim/common/const.py:307 #, fuzzy msgid "Cold" msgstr "Тлусты" #: gajim/common/const.py:308 #, fuzzy msgid "Confident" msgstr "_Змест" #: gajim/common/const.py:309 msgid "Confused" msgstr "" #: gajim/common/const.py:310 #, fuzzy msgid "Contemplative" msgstr "Скончаная" #: gajim/common/const.py:311 #, fuzzy msgid "Contented" msgstr "_Змест" #: gajim/common/const.py:312 msgid "Cranky" msgstr "" #: gajim/common/const.py:313 msgid "Crazy" msgstr "" #: gajim/common/const.py:314 #, fuzzy msgid "Creative" msgstr "Неактывізаваны" #: gajim/common/const.py:315 #, fuzzy msgid "Curious" msgstr "спасылка" #: gajim/common/const.py:316 #, fuzzy msgid "Dejected" msgstr "Выдаліць" #: gajim/common/const.py:317 msgid "Depressed" msgstr "" #: gajim/common/const.py:318 #, fuzzy msgid "Disappointed" msgstr "Адключана" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "" #: gajim/common/const.py:320 #, fuzzy msgid "Dismayed" msgstr "Адключана" #: gajim/common/const.py:321 #, fuzzy msgid "Distracted" msgstr "Адключана" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "" #: gajim/common/const.py:323 msgid "Envious" msgstr "" #: gajim/common/const.py:324 #, fuzzy msgid "Excited" msgstr "Актывізаваны" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "" #: gajim/common/const.py:327 msgid "Grateful" msgstr "" #: gajim/common/const.py:328 msgid "Grieving" msgstr "" #: gajim/common/const.py:329 #, fuzzy msgid "Grumpy" msgstr "Група" #: gajim/common/const.py:330 msgid "Guilty" msgstr "" #: gajim/common/const.py:331 msgid "Happy" msgstr "" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "" #: gajim/common/const.py:333 #, fuzzy msgid "Hot" msgstr "_Вузел:" #: gajim/common/const.py:334 msgid "Humbled" msgstr "" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "" #: gajim/common/const.py:336 msgid "Hungry" msgstr "" #: gajim/common/const.py:337 msgid "Hurt" msgstr "" #: gajim/common/const.py:338 #, fuzzy msgid "Impressed" msgstr "паведамленне" #: gajim/common/const.py:339 msgid "In Awe" msgstr "" #: gajim/common/const.py:340 msgid "In Love" msgstr "" #: gajim/common/const.py:341 msgid "Indignant" msgstr "" #: gajim/common/const.py:342 msgid "Interested" msgstr "" #: gajim/common/const.py:343 #, fuzzy msgid "Intoxicated" msgstr "Актывізаваны" #: gajim/common/const.py:344 #, fuzzy msgid "Invincible" msgstr "Нябачны" #: gajim/common/const.py:345 msgid "Jealous" msgstr "" #: gajim/common/const.py:346 #, fuzzy msgid "Lonely" msgstr "адзін" #: gajim/common/const.py:347 #, fuzzy msgid "Lost" msgstr "_Вузел:" #: gajim/common/const.py:348 msgid "Lucky" msgstr "" #: gajim/common/const.py:349 #, fuzzy msgid "Mean" msgstr "Нямецкая" #: gajim/common/const.py:350 #, fuzzy msgid "Moody" msgstr "_Змяніць" #: gajim/common/const.py:351 msgid "Nervous" msgstr "" #: gajim/common/const.py:352 msgid "Neutral" msgstr "" #: gajim/common/const.py:353 #, fuzzy msgid "Offended" msgstr "Адключаны" #: gajim/common/const.py:354 msgid "Outraged" msgstr "" #: gajim/common/const.py:355 msgid "Playful" msgstr "" #: gajim/common/const.py:356 #, fuzzy msgid "Proud" msgstr "Група" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "" #: gajim/common/const.py:358 #, fuzzy msgid "Relieved" msgstr "адзінаццаць" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "" #: gajim/common/const.py:360 msgid "Restless" msgstr "" #: gajim/common/const.py:361 #, fuzzy msgid "Sad" msgstr "Марнаванне часу" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "" #: gajim/common/const.py:363 #, fuzzy msgid "Satisfied" msgstr "Апошняя змена:" #: gajim/common/const.py:364 msgid "Serious" msgstr "" #: gajim/common/const.py:365 msgid "Shocked" msgstr "" #: gajim/common/const.py:366 msgid "Shy" msgstr "" #: gajim/common/const.py:367 #, fuzzy msgid "Sick" msgstr "Мянушка" #: gajim/common/const.py:368 #, fuzzy msgid "Sleepy" msgstr "Сон" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "" #: gajim/common/const.py:370 #, fuzzy msgid "Stressed" msgstr "Вуліца:" #: gajim/common/const.py:371 msgid "Strong" msgstr "" #: gajim/common/const.py:372 #, fuzzy msgid "Surprised" msgstr "Падпісаны" #: gajim/common/const.py:373 msgid "Thankful" msgstr "" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "" #: gajim/common/const.py:375 #, fuzzy msgid "Tired" msgstr "Час" #: gajim/common/const.py:376 #, fuzzy msgid "Undefined" msgstr "дзевяць" #: gajim/common/const.py:377 msgid "Weak" msgstr "" #: gajim/common/const.py:378 msgid "Worried" msgstr "" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "Прадвызначана" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "мора" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Пакаранне %s" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "Краіна:" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Рахунак" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Апісанне" #: gajim/common/const.py:391 #, fuzzy msgid "error" msgstr "Памылка Avahi" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "адзін" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 msgid "room" msgstr "пакой" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "" #: gajim/common/const.py:412 #, fuzzy msgid "Unable to decode issuer public key" msgstr "Немагчыма загрузіць модуль idle" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "" #: gajim/common/const.py:430 #, fuzzy msgid "Invalid CA certificate" msgstr "Няправільнае імя карыстальніка" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Злучэнне для рахунка \"%s\" згубленае" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "Перадалучыцеся самастойна." #: gajim/common/connection.py:740 #, fuzzy, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "Транспарт %s некарэктна адказаў, каб зарэгістраваць запыт: %s" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "" #: gajim/common/connection.py:1090 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Немагчыма злучыцца з \"%s\"" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Немагчыма злучыцца з \"%s\"" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Праверце злучэнне, альбо паспрабуйце пазней." #: gajim/common/connection.py:1100 #, fuzzy, python-format msgid "Server replied: %s" msgstr "Захаваць у: %s" #: gajim/common/connection.py:1115 #, fuzzy msgid "Connection to proxy failed" msgstr "Памылка злучэння" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, fuzzy, python-format msgid "Could not connect to account %s" msgstr "Немагчыма злучыцца з \"%s\"" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, fuzzy, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "Злучэнне для рахунка \"%s\" згубленае" #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Немагчыма злучыцца з \"%s\"" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "Памылка аўтарызацыі з \"%s\"" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Праверце звесткі аўтарызацыі." #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "Файлы падтрымкі python для D-Bus адсутнічаюць на гэтым кампутары" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "Немагчыма скарыстаць D-Bus для Gajim" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "D-Bus няма на гэтым кампутары, альбо няма адпаведнага модуля python" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "D-Bus няма на гэтым кампутары, альбо няма адпаведнага модуля python" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Стандартныя паведамленні стану" #: gajim/common/multimedia_helpers.py:70 msgid "Audio test" msgstr "" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Памер: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Файл: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "зялёны" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, fuzzy, python-format msgid "%s configuration error" msgstr "Настаўленні пакоя" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Няправільны знак у назве вузла." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Патрэбны адрас сервера." #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Няправільны знак у імені карыстальніка." #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "Няправільны знак у назве рэсурса." #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "_Заняты" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "М_яне няма" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "_Магу размаўляць" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "?transfer status:Прыпыненая" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "Злучэнне" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "Н_е тут" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "_Адключаны" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "_Нябачны" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "?чалавек у стане:Невядомы" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "?чалавек у стане:Ёсць памылкі" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "?Ужо ёсць падпіскі:Няма" #: gajim/common/helpers.py:315 msgid "To" msgstr "Да" #: gajim/common/helpers.py:317 msgid "From" msgstr "Ад" #: gajim/common/helpers.py:319 msgid "Both" msgstr "Абодва" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "?Сістэма:Невядомая" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "?Запыт (на падпіску):Няма" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Падпісацца" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "?Роля чалавека:Няма" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Мадэратары" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Мадэратар" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Удзельнікі" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Удзельнік" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Наведвальнікі" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Наведвальнік" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "сочыць за размовай" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "заняты чымсьці іншым" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "піша паведамленне..." #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "перастаў пісаць" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "закрыў вакно / картку размовы" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s ГіБ" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s ГБ" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s МіБ" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s МБ" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s кiБ" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s кБ" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s Б" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, fuzzy, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "Адправіць паведамленне" msgstr[1] "Адправіць паведамленне" msgstr[2] "Адправіць паведамленне" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr "Я %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, python-format msgid "from user %s" msgstr "" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr "Ад" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Я хачу дадаць Вас у свой кантактны ліст." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 #, fuzzy msgid "Timeout loading image" msgstr "Немагчыма загрузіць малюнак" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "" #: gajim/common/helpers.py:1383 msgid "PyCURL is not installed" msgstr "" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Немагчыма загрузіць малюнак" #: gajim/common/configpaths.py:85 #, python-format msgid "%s is a file but it should be a directory" msgstr "%s з'яўляецца файлам, але павінна быць дырэкторыя" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Gajim сканчвае работу" #: gajim/common/exceptions.py:45 #, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" "Сервіс недаступны: Gajim не працуе, альбо remote_control мае значэнне False" #: gajim/common/exceptions.py:81 #, fuzzy, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "" "Шына сеанса недаступная.\n" "Чытайце http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/exceptions.py:93 #, fuzzy, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" "Шына сеанса недаступная.\n" "Чытайце http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 #, fuzzy msgid "Please check if Avahi or Bonjour is installed." msgstr "Праверце, ці ўсталяваны Avahi." #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "Немагчыма стартаваць мясцовы сервіс" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, python-format msgid "Unable to bind to port %d." msgstr "Немагчыма злучыцца праз порт %d." #: gajim/common/zeroconf/connection_zeroconf.py:217 #, fuzzy msgid "Please check if avahi/bonjour-daemon is running." msgstr "Праверце, ці працуе avahi-daemon." #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, python-format msgid "Could not change status of account \"%s\"" msgstr "Немагчыма змяніць стан рахунка \"%s\"" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "Праверце, ці працуе avahi-daemon." #: gajim/common/zeroconf/connection_zeroconf.py:349 #, fuzzy msgid "Your message could not be sent." msgstr "Чалавека пакуль няма. Вы не можаце адправіць паведамленне." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "Чалавека пакуль няма. Вы не можаце адправіць паведамленне." #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "Немагчыма злучыцца з вузлом: скончыўся тэрмін чакання." #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, python-format msgid "Error while adding service. %s" msgstr "Памылка дадання сервіса. %s" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "паведамленне" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "Я хачу дадаць Вас у мой кантактны ліст." #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Памылка: %s" #: gajim/common/modules/httpupload.py:134 #, fuzzy msgid "File is empty" msgstr "Месца файла" #: gajim/common/modules/httpupload.py:137 #, fuzzy msgid "File does not exist" msgstr "Такой групавой размовы няма." #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 msgid "Change status information" msgstr "Змяніць звесткі аб стане" #: gajim/common/modules/adhoc_commands.py:113 msgid "Change status" msgstr "Змяніць стан" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "Выставіць тып прысутнасці і апісанне" #: gajim/common/modules/adhoc_commands.py:121 msgid "Free for chat" msgstr "Вольны для размовы" #: gajim/common/modules/adhoc_commands.py:122 msgid "Online" msgstr "У сетцы" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "Пашыраны рэжым адсутнасці" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "Не турбаваць" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "Адлучаны - па-за сеткай" #: gajim/common/modules/adhoc_commands.py:132 msgid "Presence description:" msgstr "Апісанне прысутнасці:" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "Стан змяніўся." #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 msgid "Leave Groupchats" msgstr "Сысці з групавых размоў" #: gajim/common/modules/adhoc_commands.py:231 #, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s на %(room_jid)s" #: gajim/common/modules/adhoc_commands.py:235 msgid "You have not joined a groupchat." msgstr "Вы не ўвайшлі ў пакой групавой размовы." #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "Выберыце групавыя размовы, з якіх Вы хочаце сысці" #: gajim/common/modules/adhoc_commands.py:292 #, fuzzy msgid "You left the following groupchats:" msgstr "Вы сышлі з наступных групавых размоў:" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" #: gajim/common/modules/roster_item_exchange.py:100 #, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "" #: gajim/common/modules/roster_item_exchange.py:104 #, fuzzy msgid "Sent contacts:" msgstr "Людзі" #: gajim/data/gui/blocked_contacts_window.ui:13 #, fuzzy msgid "Blocked Contacts" msgstr "Людзі" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Адмысловы рэдактар настаўленняў" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Фільтар:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Апісанне" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "Увага: Каб ужыць некаторыя змены, трэба перазапусціць Gajim" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "_Вярнуць звычайныя колеры" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Аўтаматычна далучацца" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Рахунак" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Пакой:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Пароль:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "_Змясціць у закладках" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "_Змясціць у закладках" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "Удзельнічаць у _групавой размове" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 #, fuzzy msgid "HTTP Connect" msgstr "Злучэнне HTTP" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Кіраванне профілямі проксі" #: gajim/data/gui/manage_proxies_window.ui:148 msgid "_Name:" msgstr "_Імя:" #: gajim/data/gui/manage_proxies_window.ui:161 #, fuzzy msgid "_Type:" msgstr "Тып:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Уласцівасці" #: gajim/data/gui/manage_proxies_window.ui:234 #, fuzzy msgid "_BOSH URL:" msgstr "_Спасылка:" #: gajim/data/gui/manage_proxies_window.ui:258 #, fuzzy msgid "Proxy _Host:" msgstr "Проксі:" #: gajim/data/gui/manage_proxies_window.ui:269 #, fuzzy msgid "Use HTTP prox_y" msgstr "С_карыстаць проксі" #: gajim/data/gui/manage_proxies_window.ui:288 #, fuzzy msgid "Proxy _Port:" msgstr "_Порт:" #: gajim/data/gui/manage_proxies_window.ui:299 #, fuzzy msgid "Use proxy auth_entication" msgstr "Аўтарызацыя" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "_Імя карыстальніка:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "Па_роль:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Настаўленні" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Захаваць пароль" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Змяніць пароль" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Асабістыя звесткі" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "Мясцовы jid:" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "Рэсурс:" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Стан:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Весці журнал размоў" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 msgid "Contact" msgstr "Чалавек" #: gajim/data/gui/zeroconf_information_window.ui:234 msgid "First Name:" msgstr "Імя:" #: gajim/data/gui/zeroconf_information_window.ui:247 msgid "Last Name:" msgstr "Прозвішча:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "Jabber ID:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "E-mail:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 msgid "Personal" msgstr "Асабістае" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "Ад_правіць прыватнае паведамленне" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Адправіць _файл" #: gajim/data/gui/gc_occupants_menu.ui:29 #, fuzzy msgid "Occupant Actions" msgstr "_Дзеянні ўдзельнікаў" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Голас" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Ма_дэратар" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Удзельнік" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Адміністратар" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "_Уладальнік" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "_Выкінуць" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Забараніць казанне" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "_Дадаць у кантактны ліст" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "_Выканаць загад..." #: gajim/data/gui/tooltip_roster_contact.ui:125 #, fuzzy msgid "Idle since:" msgstr " ад %s" #: gajim/data/gui/tooltip_roster_contact.ui:151 #, fuzzy msgid "Mood:" msgstr "Пакой:" #: gajim/data/gui/tooltip_roster_contact.ui:164 #, fuzzy msgid "Activity:" msgstr "Актывізаваны" #: gajim/data/gui/tooltip_roster_contact.ui:178 #, fuzzy msgid "Tune:" msgstr "Тып:" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Змяненне рахунка" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP: " #: gajim/data/gui/tooltip_roster_contact.ui:281 msgid "Subscription:" msgstr "Падпіска:" #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "_Стан" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Змяніць рахунак..." #: gajim/data/gui/atom_entry_window.ui:8 msgid "New entry received" msgstr "Атрыманае новае паведамленне" #: gajim/data/gui/atom_entry_window.ui:92 msgid "Feed name:" msgstr "Назва крыніцы:" #: gajim/data/gui/atom_entry_window.ui:119 msgid "Entry:" msgstr "Уваход:" #: gajim/data/gui/atom_entry_window.ui:131 msgid "Last modified:" msgstr "Апошняя змена:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 #, fuzzy msgid "Change _Nickname..." msgstr "Змяніць м_янушку" #: gajim/data/gui/gc_control_popup_menu.ui:20 #, fuzzy msgid "_Manage Room" msgstr "Кіраванне закладкамі" #: gajim/data/gui/gc_control_popup_menu.ui:31 #, fuzzy msgid "Change _Subject..." msgstr "Змяніць _тэму" #: gajim/data/gui/gc_control_popup_menu.ui:38 #, fuzzy msgid "Configure _Room..." msgstr "Настаўленні _пакоя" #: gajim/data/gui/gc_control_popup_menu.ui:52 #, fuzzy msgid "_Destroy Room" msgstr "Апісанне: %s" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:85 #, fuzzy msgid "_Request Voice" msgstr "_Голас" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "Аватар:" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Выберыце малюнак" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 #, fuzzy msgid "Full Name" msgstr "Адмысловы" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Тэлефон" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Фармат: ГГГГ-ММ-ДД" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 #, fuzzy msgid "Birthday" msgstr "Народзіны:" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "У Сеціве:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "E-mail:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 #, fuzzy msgid "Jabber ID" msgstr "Jabber ID:" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 #, fuzzy msgid "Family" msgstr "Прозвішча:" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 #, fuzzy msgid "Given" msgstr "Дадзенае імя:" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Сярэдняе:" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Прэфікс:" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Суфікс:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Вуліца:" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "Дадатковы адрас:" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 #, fuzzy msgid "City" msgstr "Горад:" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Штат:" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 #, fuzzy msgid "Postal Code" msgstr "Паштовы індэкс:" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "Краіна:" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 #, fuzzy msgid "Address" msgstr "Дадаць правіла" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Адмысловы" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Кампанія:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 #, fuzzy msgid "Department" msgstr "Аддзел:" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Пазіцыя:" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Настаўленні" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Праца" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Пра мяне" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "_Працягнуць" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Прыпыніць" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Скасаваць" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Адкрыць дырэкторыю з файлам" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Перадача файлаў" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "спіс файлаў у чарзе на перадачу" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "Спіс актыўных, скончаных і спыненых перадачаў файлаў" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "Па_чысціць" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "Выдаліць скончаныя, скасаваныя і хібныя запісы перадачы файлаў з спіса" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Выдаліць перадачу файла з спіса." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "Выдаліць адзін файл з чаргі перадачы. Калі яшчэ адбываецца перадача, яна " "спыняецца, а потым выдаляецца" #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "Скасаваць выбраную перадачу файла і выдаліць няскончаны файл" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Скасаваць перадачу файла" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Скасаваць выбраную перадачу файла" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "Ад_правіць і закрыць" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Схаваць вакно" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Паведамляць мне аб сканчэнні перадачы файлаў" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "Паказаць нагадванне па сканчэнні перадачы файла" #: gajim/data/gui/filetransfers.ui:229 msgid "Shows a list of file transfers between you and others" msgstr "Паказаць спіс перадаваных і атрыманых файлаў" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Тлусты" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Нахілены" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 #, fuzzy msgid "Underline" msgstr "дзевяць" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 #, fuzzy msgid "Strike" msgstr "Мянушка" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "Колер" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 #, fuzzy msgid "Font" msgstr "_Шрыфт:" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Асабістыя звесткі" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Выберыце файл..." #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Пстрыкніце, каб уставіць сымболік (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Падзея" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Падзеі" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Гукі" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "№" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Сышоў" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "Паказаць _галоўнае вакно" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "_Ніколі" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "Прадвызначана" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "Месца файла" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Рэсурс:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Стан" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Праграма:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 #, fuzzy msgid "System" msgstr "Адмысловы" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Імя чалавека" #: gajim/data/gui/vcard_information_window.ui:240 #, fuzzy msgid "User avatar" msgstr "Аватар:" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Настаўленні _пакоя" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 #, fuzzy msgid "Ask" msgstr "Запыт:" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Падпіска:" #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 msgid "Personal Info" msgstr "Асабістыя звесткі" #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "Каментарыі" #: gajim/data/gui/preferences_window.ui:38 msgid "Use default applications" msgstr "" #: gajim/data/gui/preferences_window.ui:41 #, fuzzy msgid "Custom" msgstr "Адмысловы" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Усе станы" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 #, fuzzy msgid "Composing only" msgstr "Піша" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Адключана" #: gajim/data/gui/preferences_window.ui:89 msgid "Only when pending events" msgstr "" #: gajim/data/gui/preferences_window.ui:103 #, fuzzy msgid "Pop it up" msgstr "_Вынырваць" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "_Паведамляць мне пра гэта" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "Паказваць толькі ў _галоўным вакне" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 #, fuzzy msgid "Last state" msgstr "Апошняе паведамленне: %s" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "Паказваць _малюнкі ў галоўным вакне" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Калі гэтая опцыя ўключаная, Gajim паказвае аватары ў галоўным вакне і ў " "групавых размовах" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "Паказваць _стан у галоўным вакне" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Калі гэтая опцыя ўключаная, Gajim паказвае паведамленні аб зменах стану для " "кожнага чалавека ў галоўным вакне і ў групавых размовах" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Паказваць _малюнкі ў галоўным вакне" #: gajim/data/gui/preferences_window.ui:254 #, fuzzy msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "" "Калі гэтая опцыя ўключаная, Gajim паказвае аватары ў галоўным вакне і ў " "групавых размовах" #: gajim/data/gui/preferences_window.ui:275 #, fuzzy msgid "Sort contacts by status" msgstr "_Упарадкаваць людзей па стане" #: gajim/data/gui/preferences_window.ui:285 #, fuzzy msgid "in _roster" msgstr "Няма ў спісе" #: gajim/data/gui/preferences_window.ui:302 #, fuzzy msgid "in _group chats" msgstr "Удзельнічаць у _групавой размове" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "" #: gajim/data/gui/preferences_window.ui:359 msgid "Spell _checker" msgstr "" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "змест паведамлення" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 msgid "_Window behavior" msgstr "" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "Паказаць _галоўнае вакно" #: gajim/data/gui/preferences_window.ui:484 #, fuzzy msgid "_Ignore rich content in incoming messages" msgstr "Ігнараваць афармленне ўваходных паведамленняў" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" "Некаторыя паведамленні ўключаюць афармленне (фармат, колеры і г.д.). Калі " "гэтая опцыя ўключаная, Gajim будзе паказваць нефарматаваны тэкст." #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Немагчыма ўвайсці ў групавую размову" #: gajim/data/gui/preferences_window.ui:523 #, fuzzy msgid "Chat Appearance" msgstr "Змяніць правіла" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "Па атрыманні новай падзеі" #: gajim/data/gui/preferences_window.ui:623 #, fuzzy msgid "Notify me about contacts that sign _in" msgstr "Паведамляць мне аб людзях, якія: " #: gajim/data/gui/preferences_window.ui:641 #, fuzzy msgid "Notify me about contacts that sign _out" msgstr "Паведамляць мне аб людзях, якія: " #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Gajim будзе паведамляць Вам аб сышоўшых людзях у выплыўным вакне ў правым " "верхнім куце экрана" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" "Дазволіць паказ паведамленняў і нагадванні, калі я _сышоў/заняты/нябачны" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "" "Дазволіць паказ паведамленняў і нагадванні, калі я _сышоў/заняты/нябачны" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "_Значка панэлі паведамленняў" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Візуальныя нагадванні" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "Граць _гук" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "Кі_раванне..." #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Гукі" #: gajim/data/gui/preferences_window.ui:861 #, fuzzy msgid "Notifications" msgstr "Змяненне рахунка" #: gajim/data/gui/preferences_window.ui:898 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "Gajim можа адпраўляць і атрымліваць метазвесткі размоў з пэўным чалавекам. " "Вызначце, аб якіх зменах стану Вы хочаце ведаць." #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "_Паказваць нагадванні стану размовы:" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim можа адпраўляць і атрымліваць метазвесткі размоў з пэўным чалавекам. " "Вызначце, аб якіх зменах стану Вы хочаце паведамляць суразмоўцу." #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "_Паказваць нагадванні стану размовы:" #: gajim/data/gui/preferences_window.ui:987 #, fuzzy msgid "Chat state notifications" msgstr "Візуальныя нагадванні" #: gajim/data/gui/preferences_window.ui:1009 #, fuzzy msgid "Personal Events" msgstr "Асабістыя звесткі" #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "Аўтаматычна змяняць стан на \"_сышоў\" праз:" #: gajim/data/gui/preferences_window.ui:1047 msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "Аўтаматычна змяняць стан на \"_недаступны\" праз:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "хвіліны" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1166 #, fuzzy msgid "Auto Status" msgstr "Дзеянні" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Запытацца аб паведамленні змены стану, калі я:" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "_Злучыцца" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "З_ысці" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" #: gajim/data/gui/preferences_window.ui:1291 #, fuzzy msgid "Default Message" msgstr "Стандартныя паведамленні стану" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 #, fuzzy msgid "Enabled" msgstr "Уключыць" #: gajim/data/gui/preferences_window.ui:1332 #, fuzzy msgid "Status Messages" msgstr "Паведамленні аб змене стану" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Паведамленні аб змене стану" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Тэма" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Тэма" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "Настаўленні колераў і шрыфтаў" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "Прадвызначаны набор _значак стану:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Ужыць _значкі транспартаў" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Калі гэтая опцыя ўключаная, Gajim будзе паказваць значкі для асобных " "пратаколаў. (напр., чалавек з MSN будзе мець адпаведныя значкі злучанасці, " "адсутнасці, занятасці і г.д. для MSN-карыстальнікаў)" #: gajim/data/gui/preferences_window.ui:1724 msgid "_Convert ASCII Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1808 #, fuzzy msgid "Style" msgstr "Марнаванне часу" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Дзеянні" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Дадаць правіла" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Сервер:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Умовы" #: gajim/data/gui/preferences_window.ui:2159 msgid "Audio/Video" msgstr "" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "_Паштовая праграма:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "_Гартач:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "_Кіраўнік файлаў:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Адмысловы" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Праграмы" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "_Ігнараваць падзеі ад людзей, якіх няма ў кантактным лісце" #: gajim/data/gui/preferences_window.ui:2363 #, fuzzy msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Скарыстайце гэтую опцыю, калі Вам надакучвае ці закідвае непатрэбнымі " "паведамленнямі нейкі чалавек, якога няма ў Вашым кантактным лісце. Але " "зважайце, што ў такім разе ніхто з людзей, якіх няма ў Вашым спісе, не зможа " "адправіць Вам паведамленне" #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Дазволіць адпраўку звестак аб _сістэме" #: gajim/data/gui/preferences_window.ui:2381 #, fuzzy msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "" "Калі гэтая опцыя ўключаная, Gajim далучыцца да гэтай групавой размовы пры " "запуску" #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Дазволіць адпраўку звестак аб _сістэме" #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "" "Калі гэтая опцыя ўключаная, Gajim далучыцца да гэтай групавой размовы пры " "запуску" #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Дазволіць адпраўку звестак аб _сістэме" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 #, fuzzy msgid "_Manage..." msgstr "Кіраванне..." #: gajim/data/gui/preferences_window.ui:2500 #, fuzzy msgid "Privacy" msgstr "Спіс прыватнасці" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "_Пісаць у журнал паведамленні аб змене стану чалавека" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Рознае" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "_Адкрыць..." #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Адмысловы рэдактар настаўленняў" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Пачаць _размову" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Адправіць _асобнае паведамленне..." #: gajim/data/gui/contact_context_menu.ui:28 #, fuzzy msgid "Send _File..." msgstr "Адправіць _файл" #: gajim/data/gui/contact_context_menu.ui:44 #, fuzzy msgid "Invite _Contacts" msgstr "Людзі" #: gajim/data/gui/contact_context_menu.ui:73 #, fuzzy msgid "E_xecute Command..." msgstr "Выканаць загад..." #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "Змяніць імя чалавека" #: gajim/data/gui/contact_context_menu.ui:92 #, fuzzy msgid "_Rename..." msgstr "Змяніць _імя" #: gajim/data/gui/contact_context_menu.ui:99 #, fuzzy msgid "Edit _Groups..." msgstr "Змяніць _групы" #: gajim/data/gui/contact_context_menu.ui:106 #, fuzzy msgid "Assign Open_PGP Key..." msgstr "Прызначыць ключ Open_PGP" #: gajim/data/gui/contact_context_menu.ui:115 #, fuzzy msgid "Add Special _Notification..." msgstr "Дадаць спецыяльнае _нагадванне" #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "П_адпіска" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "_Дазволіць чалавеку бачыць змены майго стану" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "Спытацца _дазволу праглядаць змены стану" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "_Забараніць праглядаць змены майго стану" #: gajim/data/gui/contact_context_menu.ui:182 #, fuzzy msgid "_Unignore" msgstr "дзевяць" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "" #: gajim/data/gui/contact_context_menu.ui:197 #, fuzzy msgid "_Add to Roster..." msgstr "_Дадаць у кантактны ліст" #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim: Стварэнне рахунка" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Трэба зарэгістраваць рахунак, каб далучыцца да\n" "сеткі Jabber." #: gajim/data/gui/account_creation_wizard_window.ui:95 #, fuzzy msgid "I already have an account I want to _use" msgstr "Я ўжо маю патрэбны рахунак" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "_Зарэгістраваць новы рахунак" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Выберыце адну з наступных опцый:" #: gajim/data/gui/account_creation_wizard_window.ui:167 #, fuzzy msgid "Please fill in the data for your existing account" msgstr "Запоўніце звесткі Вашага рахунка" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "_Jabber ID:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 #, fuzzy msgid "Anon_ymous authentication" msgstr "Аўтарызацыя" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Пароль:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Захоўваць па_роль" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Калі гэтая опцыя ўключаная, Gajim запомніць пароль для гэтага рахунка" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Сервер:" #: gajim/data/gui/account_creation_wizard_window.ui:423 #, fuzzy msgid "Prox_y:" msgstr "Проксі:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Кіраванне..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Адмысловы вузел / порт" #: gajim/data/gui/account_creation_wizard_window.ui:491 #, fuzzy msgid "_Hostname:" msgstr "Назва вузла: " #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Порт:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "_Адмысловыя" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:687 #, fuzzy msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Стварэнне рахунка\n" "\n" "Калі ласка, пачакайце..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Злучыцца па націску кнопкі \"Скончыць\"" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Абнавіць профіль па злучэнні" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Скончыць" #: gajim/data/gui/privacy_lists_window.ui:34 msgid "Privacy Lists:" msgstr "Спісы прыватнасці:" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Адрас:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "_Ісці" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 #, fuzzy msgid "Select the contacts you want to synchronise" msgstr "JID чалавека, з якім Вы хочаце паразмаўляць" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Змяніць групы" #: gajim/data/gui/search_window.ui:42 #, fuzzy msgid "Please wait while retrieving search form..." msgstr "Калі ласка, пачакайце канца атрымання спіса загадаў..." #: gajim/data/gui/search_window.ui:80 #, fuzzy msgid "_Add contact" msgstr "Дадаць _чалавека" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "П_ошук" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Стандартныя паведамленні:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Актыўны" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Увядзіце тэкст новага паведамлення аб змене стану" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 #, fuzzy msgid "Synchronise contacts" msgstr "Паказаць _адлучаных людзей" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "_Jabber ID:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "_Мянушка:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "_Група:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "Р_ахунак:" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "_Пратакол:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "_Дазволіць чалавеку бачыць змены майго стану" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "П_адпіска" #: gajim/data/gui/add_new_contact_window.ui:367 #, fuzzy msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" "Вы павінны зарэгістравацца для гэтага\n" "транспарта, каб дадаць чалавека з\n" "гэтага пратакола. Пстрыкніце па кнопцы\n" "рэгістрацыі." #: gajim/data/gui/add_new_contact_window.ui:382 msgid "_Register" msgstr "_Рэгістрацыя" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" "Вы павінны злучыцца з транспартам, каб\n" "дадаць людзей з гэтага пратакола." #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "З_мяніць паведамленне аб стане" #: gajim/data/gui/change_mood_dialog.ui:73 #, fuzzy msgid "Mood:" msgstr "Гукі" #: gajim/data/gui/change_mood_dialog.ui:85 #, fuzzy msgid "Message:" msgstr "Паведамленні аб змене стану" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Марнаванне часу" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Памылка злучэння" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Памылка злучэння" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Апісанне" #: gajim/data/gui/plugins_window.ui:258 #, fuzzy msgid "Version" msgstr "Версія GTK+:" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "А_ўтарызаваць" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 #, fuzzy msgid "Installed" msgstr "Марнаванне часу" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "адзін" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "Абодва" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "Ад" #: gajim/data/gui/privacy_list_window.ui:27 #, fuzzy msgid "to" msgstr "два" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "Спіс прыватнасці" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "Спіс прыватнасці" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "Актыўны для гэтага сеанса" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "Актываваць пры запуску" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "Спіс правілаў" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "Дадаць / Змяніць правіла" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "Дазволіць" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Адмовіць" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "JabberID" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "усе з групы" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "усе па падпісцы" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "Усе" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "адпраўляць мне паведамленні" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "адпраўляць мне запыты" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "бачыць мой стан" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "адпраўляць мне паведамленні аб змене стану" #: gajim/data/gui/privacy_list_window.ui:557 #, fuzzy msgid "All (including subscription)" msgstr "усе па падпісцы" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "Парадак:" #: gajim/data/gui/manage_sounds_window.ui:23 #, fuzzy msgid "Manage sounds" msgstr "Кіраванне рахункамі" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Актыўны" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Падзея" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Выберыце гукавы файл" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Выдаліць рахунак _толькі для Gajim" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Выдаліць рахунак для Gajim і на _серверы" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "Што Вы хочаце зрабіць?" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Калі ласка, пачакайце канца атрымання спіса загадаў..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Выберыце загад для выканання:" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Праверыць яшчэ" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Калі ласка, пачакайце канца адпраўлення загаду..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Гэты рахунак не мае адпаведных загадаў." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Адбылася памылка:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Скончыць" #: gajim/data/gui/account_context_menu.ui:20 #, fuzzy msgid "_Personal Events" msgstr "Асабістыя звесткі" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "Удзельнічаць у _групавой размове" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Дадаць чалавека..." #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Пошук сервісаў" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "_Выканаць загад..." #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Выгляд" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Паказаць _галоўнае вакно" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Паказаць _адлучаных людзей" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Паказаць _адлучаных людзей" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Паказаць _транспарты" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Даведка" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Змест" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_Частыя пытанні" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 #, fuzzy msgid "Features" msgstr "Здольнасці сервера" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "_Змясціць у закладках" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Уласцівасці" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Выйсці" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Скасаваць" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "Групавая размова" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "_Змясціць у закладках" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Сервер:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Пароль:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Чалавек адлучыўся" #: gajim/data/gui/manage_bookmarks_window.ui:342 msgid "Minimize on Auto Join" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Адправіць паведамленне і закрыць вакно" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Паведамленне аб змене стану" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Апісанне: %s" #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Вечар" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 #, fuzzy msgid "Send" msgstr "Ад_правіць" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Файл: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" "Магчыма, гэтая памылка не крытычная, але пра яе варта паведаміць " "распрацоўнікам." #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Паведаміць пра памылку" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Пачаць размову" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "_Адмовіць" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "Забраць аўтарызацыю ў чалавека, каб ён не мог бачыць, калі Вы далучаны" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "А_ўтарызаваць" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "Аўтарызаваць чалавека, каб ён мог бачыць, калі Вы далучаны" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "_Прысутнасць" #: gajim/data/gui/emoji_chooser.ui:98 msgid "No Results Found" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "JID чалавека, з якім Вы хочаце паразмаўляць" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:141 #, fuzzy msgid "MUC server" msgstr "Назіральнікі" #: gajim/data/gui/chat_to_muc_window.ui:176 #, fuzzy msgid "In_vite" msgstr "За_прасіць" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Экспартаваць" #: gajim/data/gui/history_manager.ui:93 #, fuzzy msgid "Welcome to Gajim History Logs Manager" msgstr "Gajim - Кіраўнік журналаў размоў" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" #: gajim/data/gui/history_manager.ui:123 #, fuzzy msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "Gajim - Кіраўнік журналаў размоў\n" "\n" "Вы можаце выбраць адзін з журналаў на левай панэлі альбо адшукаць у базе " "дадзеных.\n" "\n" "Увага:\n" "Калі Вы хочаце здзейсніць масавую чыстку журналаў, закрыйце Gajim. Не " "выдаляйце журналы размоў з людзьмі, з якімі Вы зараз размаўляеце." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Пошук у базе дадзеных" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "змест паведамлення" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Адправіць паведамленне" #: gajim/data/gui/shortcuts_window.ui:24 #, fuzzy msgid "Add new line" msgstr "Стварыць новы допіс" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Стандартныя паведамленні:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Стандартныя паведамленні:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "паведамленне стану" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Адправіць паведамленне" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Паведамленне адпраўленае" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Нядаўна:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Вечар" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Перадача файлаў" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "Удзельнічаць у _групавой размове" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "паведамленне стану" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 #, fuzzy msgid "Appearance" msgstr "Змяніць правіла" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Паказаць _адлучаных людзей" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Паказаць _адлучаных людзей" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Людзі" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Асабістыя звесткі" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Змяніць імя чалавека" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Людзі" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Пароль" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "_Пісаць у журнал паведамленні аб змене стану чалавека" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Мадэратар" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Нядаўна:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Журнал размоў" #: gajim/data/gui/history_window.ui:315 msgid "Chat" msgstr "Размова" #: gajim/data/gui/history_window.ui:329 msgid "Record history for this chat" msgstr "" #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Нядаўна:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Загаловак:" #: gajim/data/gui/manage_pep_services_window.ui:13 #, fuzzy msgid "PEP Service Configuration" msgstr "Настаўленні пакоя" #: gajim/data/gui/manage_pep_services_window.ui:69 #, fuzzy msgid "_Configure" msgstr "_Працягнуць" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Стварыць новы допіс" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "Ад:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Тэма:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Запоўніце форму." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Настаўленні пакоя" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_Добра" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "Ст_ан" #: gajim/data/gui/systray_context_menu.ui:20 #, fuzzy msgid "_Start Chat..." msgstr "_Пачаць размову" #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Паказаць нягледжаныя _падзеі" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "Адключыць гукі" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Уласцівасці" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Выйсці" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Каму:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "Ад_правіць" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Адправіць паведамленне" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Адказаць" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Адказаць на гэтае паведамленне" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "Ад_правіць і закрыць" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Адправіць паведамленне і закрыць вакно" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:337 #, fuzzy msgid "Message: " msgstr "Паведамленні аб змене стану" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Не хапае аргумента \"contact_jid\"" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Не хапае аргумента \"contact_jid\"" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 #, fuzzy msgid "Send a message to the contact" msgstr "Карыстанне: /%s, хавае кнопкі размовы." #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "%s не знойдзены" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "_Тут" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 #, fuzzy msgid "Clear the text window" msgstr "Карыстанне: /%s, прыбірае тэкст у вакне." #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Адправіць файл чалавеку" #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 msgid "Command is not supported for zeroconf accounts" msgstr "" #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 #, fuzzy msgid "No open audio sessions with the contact" msgstr "Пстрыкніце, каб праглядзець былыя размовы з гэтым чалавекам" #: gajim/command_system/implementation/standard.py:191 #, python-format msgid "%s is not a valid tone" msgstr "" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "Няма злучэння" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "Няма злучэння" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Карыстанне: /%s, хавае кнопкі размовы." #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Змяніць м_янушку" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 #, fuzzy msgid "Invalid nickname" msgstr "Няправільнае імя карыстальніка" #: gajim/command_system/implementation/standard.py:267 #, fuzzy msgid "Open a private chat window with a specified occupant" msgstr "" "Карыстанне: /%s <мянушка>, адкрывае вакно прыватнай размовы з чалавекам." #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 #, fuzzy msgid "Nickname not found" msgstr "Мянушка не знойдзеная: %s" #: gajim/command_system/implementation/standard.py:276 #, fuzzy msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" "Карыстанне: /%s <мянушка>, адкрывае вакно прыватнай размовы з чалавекам." #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Пытацца пацверджання закрыцця групавой размовы." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "%(contact_jid)s запрошаныя ў %(room_jid)s." #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "Удзельнічаць у _групавой размове" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Вы не ўвайшлі ў пакой групавой размовы." #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Няправільнае імя карыстальніка" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "Адносіны: " #: gajim/command_system/implementation/standard.py:365 #, fuzzy msgid "Display names of all group chat occupants" msgstr "Карыстанне: /%s, хавае кнопкі групавой размовы." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Злучэнне" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Новая групавая размова" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Дадаць новага чалавека" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "Асобнае паведамленне для рахунка %s" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "Асобнае паведамленне для рахунка %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Асобнае паведамленне" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Адправіць %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Атрымана %s" #: gajim/gtk/single_message.py:238 #, fuzzy, python-format msgid "Form %s" msgstr "Я %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "Няма злучэння" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Праверце злучэнне з \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "RE: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s сказаў:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "" #: gajim/gtk/pep_config.py:133 #, fuzzy, python-format msgid "Configure %s" msgstr "_Працягнуць" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "_Рэгістрацыя" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Зарэгістравацца на %s" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "Слоўніка для мовы %s няма" #: gajim/gtk/dialogs.py:83 #, fuzzy, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" "Вы павінны ўсталяваць слоўнік %s, каб спраўджваць правапіс, альбо выбраць " "іншую мову праз опцыю speller_language." #: gajim/gtk/dialogs.py:440 #, fuzzy, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "Вы ствараеце мета-кантакт. Вы сапраўды хочаце працягнуць?" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "Jabber ID групавой размовы ўтрымлівае няправільныя знакі." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "для рахунка %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Змяніць пароль" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Вы павінны ўвесці пароль." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Паролі розняцца" #: gajim/gtk/add_contact.py:30 #, fuzzy msgid "GG Number" msgstr "Нумар GG:" #: gajim/gtk/add_contact.py:31 #, fuzzy msgid "ICQ Number" msgstr "Нумар ICQ:" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Дадаць чалавека..." #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s МіБ" #: gajim/gtk/add_contact.py:235 #, fuzzy, python-format msgid "You must supply the %s of the new contact." msgstr "Вы павінны ўвесці пароль для новага рахунка." #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "Няправільны ID карыстальніка" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "ID карыстальніка не павінны вызначаць рэсурс." #: gajim/gtk/add_contact.py:274 #, fuzzy msgid "You cannot add yourself to your roster." msgstr "Я хачу дадаць Вас у мой кантактны ліст." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Адключаны" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Чалавек ужо ёсць у кантактным лісце" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Гэты чалавек ужо ёсць у у кантактным лісце." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "ID карыстальніка:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "Памылка дадання сервіса. %s" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "Піша" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Неактыўны" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Змяніць стан" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "Накіраваны MUC\n" "Паведамленні" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Новае паведамленне" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Рахунак" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Група" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "_Паказваць падзею ў галоўным вакне" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Журнал размоў" #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Змена мянушкі" #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "_Уваходнае паведамленне:" #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "_Уваходнае паведамленне:" #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "_Выходнае паведамленне:" #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "_Выходнае паведамленне:" #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Паведамленне аб змене стану" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Паведамленне аб змене стану" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Колер" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "_Фарбаваць няправільна напісаныя словы" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Паведамленні" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "_Вярнуць звычайныя колеры" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Чалавек адлучыўся" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Чалавек далучыўся" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "Gajim - %s" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Такая мянушка не дазволеная: %s" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Актыўны" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s цяпер %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, fuzzy, python-format msgid "Error: %s" msgstr "Памылка: %s" #: gajim/gtk/history.py:590 msgid "Error" msgstr "" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Цяперашні стан: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Цяперашні стан: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "Што Вы хочаце зрабіць?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Злучэнне" #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Перадача файла %(filename)s ад %(name)s спыненая." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "%d нечытанае паведамленне" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "Jabber-праграма для GTK+" #: gajim/gtk/about.py:48 #, fuzzy, python-format msgid "GTK+ Version: %s" msgstr "Версія GTK+:" #: gajim/gtk/about.py:49 #, fuzzy, python-format msgid "PyGObject Version: %s" msgstr "Версія PyGTK:" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Актыўныя распрацоўнікі:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Былыя распрацоўнікі:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 #, fuzzy msgid "we would like to thank all the package maintainers." msgstr "" "Таксама хочам выказаць падзяку ўсім людзям, што збіраюць пакункі з праграмай " "для розных сістэмаў." #: gajim/gtk/about.py:61 msgid "Thanks" msgstr "" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "Ihar Hrachyshka " #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Выберыце файл..." #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Выберыце малюнак" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Усе файлы" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Усе файлы" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Адправіць _файл" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Малюнкі" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Выберыце малюнак" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Усе файлы" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Захаваць файл як..." #: gajim/gtk/profile.py:72 #, fuzzy msgid "Retrieving profile…" msgstr "Чытанне профіля..." #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Асабістыя звесткі" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Фармат: ГГГГ-ММ-ДД" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "Атрыманыя звесткі" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "" "Вы не можаце абнавіць Вашыя асабістыя звесткі, не злучыўшыся з серверам." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Адпраўленне профіля..." #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "Звесткі НЕ абноўленыя" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "Памылка абнаўлення vCard" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "У часе абнаўлення Вашых асабістых звестак адбылася памылка, паспрабуйце " "абнавіць пазней." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Няправільны элемент" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 #, fuzzy msgid "Invalid Nickname" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/join_groupchat.py:223 #, fuzzy msgid "Please choose a nickname" msgstr "Стварыць новы допіс" #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Няправільная спасылка" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "Гэта не групавая размова" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Настаўленні" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Вы не злучаны з серверам" #: gajim/gtk/mam_preferences.py:102 #, fuzzy msgid "Error received: {}" msgstr "Вы атрымалі новае паведамленне:" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Памылка Avahi" #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "Актывізаваны" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "Неактывізаваны" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "Лагічнае" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "Цэлы лік" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Тэкставае" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Назва ўласцівасці" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Значэнне" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Тып" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Няма)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Схаваны" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "Назва вузла: " #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Здольнасці сервера" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Захаваць у: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "" #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 #, fuzzy msgid "Command line" msgstr "Загады: %s" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "" #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "" #: gajim/gtk/features.py:61 #, fuzzy msgid "OpenPGP message encryption" msgstr "Шыфраванне OpenPGP" #: gajim/gtk/features.py:63 #, fuzzy msgid "Ability to encrypting chat messages with OpenPGP." msgstr "_Уваходнае паведамленне:" #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "" #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 #, fuzzy msgid "Password encryption" msgstr "Паролі розняцца" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "" #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "" #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 msgid "Requires Gspell" msgstr "" #: gajim/gtk/features.py:76 #, fuzzy msgid "Automatic status" msgstr "_Адпаведна стану" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "" #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "" #: gajim/gtk/features.py:81 #, fuzzy msgid "RST Generator" msgstr "Агульная" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "" #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "" #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 msgid "Requires gir1.2-gupnpigd-1.0." msgstr "" #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "Тут" #: gajim/gtk/features.py:109 #, fuzzy msgid "Feature" msgstr "Здольнасці сервера" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "Спіс прыватнасці %s" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "Спіс прыватнасці для %s" #: gajim/gtk/privacy_list.py:147 #, fuzzy, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "Парадак: %s, дзеянне: %s, тып: %s, значэнне: %s" #: gajim/gtk/privacy_list.py:152 #, fuzzy, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Парадак: %s, дзеянне: %s" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "Змяніць правіла" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "Дадаць правіла" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "Спісы прыватнасці для %s" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "Няправільная назва спіса" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "Вы павінны вызначыць назву для новага спіса прыватнасці." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Рахунак паспяхова дададзены" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 #, fuzzy msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Вы можаце зараз змяніць адмысловыя настаўленні, націснуўшы кнопку " "\"Адмысловыя\", альбо пазней, выбраўшы элемент \"Рахункі\" ў меню \"Змяніць" "\" галоўнага вакна." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Новы рахунак паспяхова створаны" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "" "Вы павінны пазначыць імя карыстальніка, каб змяніць настаўленні гэтага " "рахунка." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 #, fuzzy msgid "Invalid server" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/account_wizard.py:255 #, fuzzy msgid "Please provide a server on which you want to register." msgstr "Вызначце сваю новую мянушку:" #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Няправільны элемент" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "Адмысловы порт павінны быць нумарам порта." #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "Адбылася памылка ў часе стварэння рахунка" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Назва рахунка ўжо скарыстаная" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Вы ўжо маеце рахунак з такой назваю." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Фільтар:" #: gajim/gtk/xml_console.py:79 #, fuzzy msgid "XML Input" msgstr "Увод XML" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Няправільны файл" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "Прадвызначана" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "загаловак паведамлення аб змене стану" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "тэкст паведамлення аб змене стану" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Перадалучыцца?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "Калі Вы хочаце ўжыць усе зробленыя змены, перадалучыцеся." #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "Вы пачалі размову ў рахунку %s" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "Усе размоўныя вокны закрыюцца. Хочаце працягнуць?" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Дадаць чалавека..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "Вы_даліць" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Аб'яднаныя рахункі" #: gajim/gtk/accounts.py:549 msgid "Use PGP Agent" msgstr "" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Злучэнне" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Людзі" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Прызначыць ключ OpenPGP" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "_Злучацца па старце Gajim" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Аўтаматычна перадалучацца, калі знікае злучэнне" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Захоўваць _журналы размоў з усімі людзьмі" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "Ад_правіць паведамленне серверу" #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Усе станы" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Змяніць стан рахунка(ў)" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Паведамленні" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Ужыць проксі для перадачы файлаў" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "Няма злучэння" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Проксі:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "Злучэнне" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Адпраўляць праверачныя пакункі серверу" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "Прыяры_тэт:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Змяніць стан рахунка(ў)" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Імя:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Прозвішча:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Новы ліст" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "_Адпаведна стану" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Уключыць" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Порт:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Злучэнне" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Няправільнае імя карыстальніка" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Захаваць пароль" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "Сымболікі:" #: gajim/gtk/bookmarks.py:72 msgid "?print_status:All" msgstr "?print_status:Усе" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "Увайсці і выйсці" #: gajim/gtk/bookmarks.py:74 msgid "?print_status:None" msgstr "?print_status:Няма" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "Новая групавая размова" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Гэтая закладка мае няправільныя звесткі" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "Запоўніце палі сервера і пакоя альбо выдаліце гэтую закладку." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 #, fuzzy msgid "Character not allowed" msgstr "Такая мянушка не дазволеная: %s" #: gajim/gtk/bookmarks.py:367 #, fuzzy msgid "Invalid room" msgstr "Няправільны элемент" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Месца файла" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 msgid "Archive is malformed" msgstr "" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Такі файл ужо ёсць" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Забарона казання для %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Памылка злучэння" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Настаўленні пакоя" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Jabber-праграма" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "Jabber-праграма для GTK+" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Паказаць нягледжаныя _падзеі" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Здольнасці сервера" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 msgid "Automatic spell-checking for your messages" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Пошук сервісаў для рахунка %s" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "_Пісаць у журнал паведамленні аб змене стану чалавека" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Групавыя размовы" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Нядаўна:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Памылка злучэння" #~ msgid "Stopped" #~ msgstr "Спыненая" #~ msgid "Error reading file:" #~ msgstr "Памылка чытання файла:" #~ msgid "Error parsing file:" #~ msgstr "Памылка разбору файла:" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Памылка перадачы файла" #, fuzzy #~ msgid "XML console interface" #~ msgstr "Кансоль XML" #, fuzzy #~ msgid "(ESession info)" #~ msgstr "Апісанне" #~ msgid "Save as Preset..." #~ msgstr "Захаваць тлумачэнне..." #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "Jabberd1.4 не любіць звесткі sha, калі чалавек заходзіць у абароненую " #~ "паролем групавую размову. Змяніце значэнне гэтай опцыі на False, каб " #~ "перастаць адпраўляць звесткі sha у групавыя размовы" #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim заменіць ascii-сымболікі (напр., ':)' ) " #~ "адпаведнай значкай" #, fuzzy #~ msgid "_Emoticons" #~ msgstr "Сымболікі:" #~ msgid "_Highlight misspelled words" #~ msgstr "_Фарбаваць няправільна напісаныя словы" #, fuzzy #~ msgid "Notify by icon when your messages are received" #~ msgstr "Прайграць гук пры атрыманні паведамлення MUC." #, fuzzy #~ msgid "T_heme" #~ msgstr "Т_эма:" #, fuzzy #~ msgid "Themes" #~ msgstr "Уласцівасці" #, fuzzy #~ msgid "Presence" #~ msgstr "_Прысутнасць" #, fuzzy #~ msgid "Emoticons disabled" #~ msgstr "Шыфраванне адключанае" #, fuzzy #~ msgid "You cannot make changes to the default theme" #~ msgstr "Вы не можаце выдаліць актыўную тэму" #, fuzzy #~ msgid "Please create a new clean theme." #~ msgstr "Стварыць новы допіс" #~ msgid "theme name" #~ msgstr "назва тэмы" #~ msgid "You cannot delete your current theme" #~ msgstr "Вы не можаце выдаліць актыўную тэму" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Новае асобнае паведамленне ад %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Новае прыватнае паведамленне ў групавой размове %s" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s: %(message)s" #, fuzzy #~ msgid "Messaged by %(nickname)s" #~ msgstr "Новае паведамленне ад %(nickname)s" #, fuzzy #~ msgid "Status message text color." #~ msgstr "тэкст паведамлення аб змене стану" #, fuzzy #~ msgid "Incoming nickname font." #~ msgstr "Няправільнае імя карыстальніка" #, fuzzy #~ msgid "Status message text font." #~ msgstr "тэкст паведамлення аб змене стану" #~ msgid "Background color of contacts when they just signed in." #~ msgstr "Фонавы колер для толькі ўвайшоўшых людзей." #~ msgid "Background color of contacts when they just signed out." #~ msgstr "Фонавы колер для толькі сышоўшых людзей." #~ msgid "green" #~ msgstr "зялёны" #~ msgid "grocery" #~ msgstr "садавіна" #~ msgid "human" #~ msgstr "чалавек" #~ msgid "marine" #~ msgstr "мора" #, fuzzy #~ msgid "Contact row" #~ msgstr "Чалавек" #~ msgid "Gajim Themes Customization" #~ msgstr "Настаўленне тэмы Gajim" #~ msgid "Text _color:" #~ msgstr "Колер _тэксту:" #~ msgid "_Background:" #~ msgstr "_Фон:" #~ msgid "Text _font:" #~ msgstr "_Шрыфт:" #~ msgid "Font style:" #~ msgstr "Шрыфт:" #~ msgid "Paused" #~ msgstr "Прыпынена" #~ msgid "Gone" #~ msgstr "Знік" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "MUC\n" #~ "Паведамленні" #~ msgid "Chatstate Tab Colors" #~ msgstr "Колер картак" #, fuzzy #~ msgid "Chat message" #~ msgstr "П_аведамленне стану:" #~ msgid "Use system _default" #~ msgstr "Ужыць _сістэмны" #, fuzzy #~ msgid "Font" #~ msgstr "Гукі" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Імя чалавека" #, fuzzy #~ msgid "Contact's message" #~ msgstr "П_аведамленне стану:" #, fuzzy #~ msgid "_Status message" #~ msgstr "П_аведамленне стану:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Фарбаванае паведамленне ў групавой размове" #, fuzzy #~ msgid "Your nickname" #~ msgstr "П_ерад мянушкай:" #, fuzzy #~ msgid "Your message" #~ msgstr "Памылка: %s" #, fuzzy #~ msgid "Chat Line Colors" #~ msgstr "Колер картак" #, fuzzy #~ msgid "Jabber ID:" #~ msgstr "Jabber ID:" #, fuzzy #~ msgid "Resource:" #~ msgstr "Рэсурс:" #, fuzzy #~ msgid "Status:" #~ msgstr "Настаўленні" #, fuzzy #~ msgid "Client:" #~ msgstr "Адмысловы" #, fuzzy #~ msgid "Contact time:" #~ msgstr "Настаўленні" #, fuzzy #~ msgid "Ask:" #~ msgstr "Дзеянні" #, fuzzy #~ msgid "Subscription:" #~ msgstr "Апісанне" #, fuzzy #~ msgid "Name:" #~ msgstr "Адмысловы" #, fuzzy #~ msgid "Nickname:" #~ msgstr "Мянушка:" #, fuzzy #~ msgid "Street:" #~ msgstr "Настаўленні" #, fuzzy #~ msgid "City:" #~ msgstr "Адмысловы" #, fuzzy #~ msgid "State:" #~ msgstr "Настаўленні" #, fuzzy #~ msgid "Extra Address:" #~ msgstr "Дадатковы адрас:" #, fuzzy #~ msgid "Postal Code:" #~ msgstr "Паштовы індэкс:" #, fuzzy #~ msgid "Country:" #~ msgstr "Гукі" #, fuzzy #~ msgid "Homepage:" #~ msgstr "У Сеціве:" #, fuzzy #~ msgid "E-Mail:" #~ msgstr "E-mail:" #, fuzzy #~ msgid "Phone No.:" #~ msgstr "Тэлефонны нумар:" #, fuzzy #~ msgid "Birthday:" #~ msgstr "Народзіны:" #, fuzzy #~ msgid "Family:" #~ msgstr "Прозвішча:" #, fuzzy #~ msgid "Middle:" #~ msgstr "Дадаць правіла" #, fuzzy #~ msgid "Prefix:" #~ msgstr "Уласцівасці" #, fuzzy #~ msgid "Given:" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "Suffix:" #~ msgstr "Гукі" #, fuzzy #~ msgid "Full Name" #~ msgstr "Адмысловы" #, fuzzy #~ msgid "Company:" #~ msgstr "Адмысловы" #, fuzzy #~ msgid "Department:" #~ msgstr "Аддзел:" #, fuzzy #~ msgid "Position:" #~ msgstr "Умовы" #, fuzzy #~ msgid "Role:" #~ msgstr "Гукі" #~ msgid "Edit %s" #~ msgstr "Змяніць %s" #~ msgid "Register to %s" #~ msgstr "Зарэгістравацца на %s" #~ msgid "Conversation History with %s" #~ msgstr "Журнал размоў %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Немагчыма злучыцца з \"%s\"" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "Звесткі рэгістрацыі для транспарта %s не прыйшлі ў час" #~ msgid "Register to" #~ msgstr "Зарэгістравацца" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Імя чалавека" #, fuzzy #~ msgid "Search:" #~ msgstr "Пошук" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Вы не можаце змяніць пароль, не злучыўшыся з серверам." #~ msgid "Invalid password" #~ msgstr "Няправільны пароль" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "Паролі ў абодвух палях павінны быць аднолькавымі." #~ msgid "Enter new password:" #~ msgstr "Увядзіце новы пароль:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Увядзіце для пацверджання:" #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "JID %s не адпавядае стандарту RFC. Ён не будзе дададзены ў кантактны " #~ "ліст. Выдаліце яго з дапамогай адмысловай праграмы, напр., http://jru." #~ "jabberstudio.org/" #~ msgid "unsubscribe request from %s" #~ msgstr "запыт адпіскі ад %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Аўтаматычна далучацца" #, fuzzy #~ msgid "Homepage:" #~ msgstr "У Сеціве:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Працягнуць" #~ msgid "Manage Bookmarks" #~ msgstr "Кіраванне закладкамі" #~ msgid "_Nickname:" #~ msgstr "_Мянушка:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim далучыцца да гэтай групавой размовы пры " #~ "запуску" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Стан друку:" #, fuzzy #~ msgid "Add JID" #~ msgstr "Jabber ID:" #, fuzzy #~ msgid "Preference:" #~ msgstr "Уласцівасці" #, fuzzy #~ msgid "Preference" #~ msgstr "Уласцівасці" #, fuzzy #~ msgid "JID:" #~ msgstr "Ваш JID:" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "" #~ "Запоўніце палі звесткамі пра чалавека, якога Вы хочаце дадаць у спіс " #~ "рахунка %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Запоўніце палі звесткамі, каб дадаць чалавека ў спіс" #, fuzzy #~ msgid "Recently" #~ msgstr "Нядаўна:" #~ msgid "Add New Contact" #~ msgstr "Дадаць новага чалавека" #~ msgid "_User ID:" #~ msgstr "_ID карыстальніка:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "ID карыстальніка:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Мянушка" #~ msgid "Personal Information" #~ msgstr "Асабістыя звесткі" #, fuzzy #~ msgid "Avatar:" #~ msgstr "Аватар:" #~ msgid "Click to set your avatar" #~ msgstr "Пстрыкніце, каб вызначыць свой аватар" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "Выдаліць групу" #~ msgid "Not fetched because of invisible status" #~ msgstr "Не атрымана з-за нябачнага стану" #~ msgid "Please wait..." #~ msgstr "Калі ласка, пачакайце..." #~ msgid "Yahoo! Address:" #~ msgstr "Адрас Yahoo!:" #, fuzzy #~ msgid "Forward unread messages" #~ msgstr "%d нечытанае паведамленне" #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "%d нечытанае паведамленне" #~ msgid "AIM Address:" #~ msgstr "Адрас AIM:" #~ msgid "MSN Address:" #~ msgstr "Адрас MSN:" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "Ці ўжыты OpenPGP ў размове з гэтым чалавекам?" #, fuzzy #~ msgid "End to End message encryption" #~ msgstr "Шыфраванне OpenPGP" #, fuzzy #~ msgid "Encrypting chat messages." #~ msgstr "_Уваходнае паведамленне:" #, fuzzy #~ msgid "This session is encrypted" #~ msgstr "[Гэтае паведамленне зашыфраванае]" #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "Шыфраванне адключанае" #, fuzzy #~ msgid "Unable to decrypt message" #~ msgstr "Для кожнага _паведамлення" #~ msgid "_Send" #~ msgstr "Ад_правіць" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Захаваць малюнак як..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Экспартаванне журналаў..." #~ msgid "Choose Image" #~ msgstr "Выберыце малюнак" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Выберыце файл..." #~ msgid "When %s becomes:" #~ msgstr "Калі %s становіцца:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Дадаць асабістае нагадванне для %s" #~ msgid "Unable to load idle module" #~ msgstr "Немагчыма загрузіць модуль idle" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s з'яўляецца дырэкторыяй, але павінны быць файл" #~ msgid "creating logs database" #~ msgstr "стварэнне базы журналаў" #, fuzzy #~ msgid "creating cache database" #~ msgstr "стварэнне базы журналаў" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Адправіць %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Gajim - Кіраўнік журналаў размоў" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Кіраванне рахункамі" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Адправіць _асобнае паведамленне..." #, fuzzy #~ msgid "E2E encryption disabled" #~ msgstr "Шыфраванне адключанае" #~ msgid "uri" #~ msgstr "спасылка" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Марнаванне часу" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Марнаванне часу" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Памылка злучэння" #~ msgid "cyan" #~ msgstr "cyan" #~ msgid "migrating logs database to indices" #~ msgstr "перанос базы журналаў у індэкс" #, fuzzy #~ msgid "Send File..." #~ msgstr "Адправіць _файл" #, fuzzy #~ msgid "HTTP File Upload not supported by your server" #~ msgstr "Сервер не падтрымлівае сховішча мета-кантактаў" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Перадача файлаў" #~ msgid "Shows or hides the roster window" #~ msgstr "Паказаць / схаваць галоўнае вакно" #, fuzzy #~ msgid "Shows or hides the ipython window" #~ msgstr "Паказаць / схаваць галоўнае вакно" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "рахунка %s" #, fuzzy #~ msgid "Exception" #~ msgstr "Апісанне" #, fuzzy #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "Я хачу дадаць Вас у свой кантактны ліст." #~ msgid "_Actions" #~ msgstr "_Дзеянні" #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Пачаць размову" #~ msgid "You are already in group chat %s" #~ msgstr "Вы ўжо ўдзельнічаеце ў групавой размове %s" #~ msgid "Join Group Chat with account %s" #~ msgstr "Удзельнічаць у групавой размове праз рахунак %s" #, fuzzy #~ msgid "Invalid Account" #~ msgstr "Няправільная назва рахунка" #, fuzzy #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "Вы павінны стварыць рахунак, каб размаўляць з іншымі людзьмі." #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "Jabber ID групавой размовы ўтрымлівае няправільныя знакі." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "Jabber ID групавой размовы ўтрымлівае няправільныя знакі." #~ msgid "Start Chat with account %s" #~ msgstr "Пачаць размову з рахунка %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Вызначце мянушку для Jabber ID чалавека, якому Вы\n" #~ "хочаце адправіць паведамленне:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Паўторны Jabber ID" #~ msgid "Unable to parse \"%s\"." #~ msgstr "Немагчыма разабраць \"%s\"." #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "" #~ "Паказвае вакно, з якога Вы можаце адправіць паведамленне пэўнаму чалавеку" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID чалавека, з якім Вы хочаце паразмаўляць" #~ msgid "Adds contact to roster" #~ msgstr "Дадаць чалавека ў спіс" #~ msgid "jid" #~ msgstr "jid" #~ msgid "Adds new contact to this account" #~ msgstr "Дадаць новага чалавека для гэтага рахунка" #~ msgid "Opens 'Start Chat' dialog" #~ msgstr "Адкрыць вакно 'Пачаць размову'" #~ msgid "Starts chat, using this account" #~ msgstr "Пачаць размову для рахунка" #, fuzzy #~ msgid "Handle a xmpp:/ URI" #~ msgstr "Апрацоўваць спасылкі xmpp:/" #, fuzzy #~ msgid "Message content" #~ msgstr "змест паведамлення" #~ msgid "Join a MUC room" #~ msgstr "Увайсці ў размоўны пакой" #, fuzzy #~ msgid "Nickname to use" #~ msgstr "Мянушка не знойдзеная: %s" #, fuzzy #~ msgid "Password to enter the room" #~ msgstr "Паролі розняцца" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Няправільная спасылка" #~ msgid "Nickname:" #~ msgstr "Мянушка:" #~ msgid "Server:" #~ msgstr "Сервер:" #~ msgid "Password:" #~ msgstr "Пароль:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Увайсці ў гэты пакой па злучэнні" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Праглядзець" #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "Кіраўнік журналаў" #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Кіраўнік журналаў" #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "Паведамленне аб аўтаматычнай недаступнасці" #, fuzzy #~ msgid "This contact does not support file transfer." #~ msgstr "Спіс актыўных, скончаных і спыненых перадачаў файлаў" #~ msgid "" #~ "You have to install %s dictionary to use spellchecking, or choose another " #~ "language by setting the speller_language option." #~ msgstr "" #~ "Вы павінны ўсталяваць слоўнік %s, каб спраўджваць правапіс, альбо выбраць " #~ "іншую мову праз опцыю speller_language." #, fuzzy #~ msgid "Hides the buttons in chat windows." #~ msgstr "Схаваць кнопкі групавой размовы." #, fuzzy #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Змяніць м_янушку" #, fuzzy #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "_Змясціць у закладках" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Пстрыкніце, каб уставіць сымболік (Alt+M)" #, fuzzy #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Дадаць чалавека ў спіс" #, fuzzy #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "сочыць за размовай" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Дадаць чалавека ў спіс" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Дадаць чалавека ў спіс" #, fuzzy #~ msgid "Ma_ke message windows compact" #~ msgstr "_Вакно для аднаго паведамлення:" #, fuzzy #~ msgid "Hide all buttons in chat windows" #~ msgstr "Схаваць кнопкі групавой размовы." #, fuzzy #~ msgid "Hide the chat buttons" #~ msgstr "Карыстанне: /%s, хавае кнопкі размовы." #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "Калі true, Gajim будзе адпраўляць запыт на атрыманне аватара кожнаму " #~ "чалавеку, хто не меў усталяванага аватара ў апошні сеанс, ці чый аватар " #~ "надта стары." #, fuzzy #~ msgid "?CLI:room" #~ msgstr "пакой" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "мянушка" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "пароль" #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "Паказваць нагадванні праз DBus і Notification-Daemon" #, fuzzy #~ msgid "Notification" #~ msgstr "Змяненне рахунка" #, fuzzy #~ msgid "Ignore" #~ msgstr "дзевяць" #~ msgid "_Open Gmail Inbox" #~ msgstr "_Адкрыць уваходную пошту Gmail" #~ msgid "Notify on new _GMail email" #~ msgstr "Паведамляць аб новай пошце на _Gmail" #, fuzzy #~ msgid "" #~ "If checked, Gajim will show a notification when a new e-mail is received " #~ "via GMail" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim таксама дадасць звесткі аб адпраўніку " #~ "новых лістоў" #~ msgid "Display _extra email details" #~ msgstr "Паказаць _падрабязнасці пошты" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim таксама дадасць звесткі аб адпраўніку " #~ "новых лістоў" #~ msgid "GMail Options" #~ msgstr "Настаўленні GMail" #, fuzzy #~ msgid "20" #~ msgstr "0" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Адправіць %s" #~ msgid "GMail Email Received" #~ msgstr "Новы ліст GMail" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Новая пошта на %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "%d новы ліст" #~ msgstr[1] "%d новыя лісты" #~ msgstr[2] "%d новых лістоў" #~ msgid "Re_name" #~ msgstr "_Змяніць імя" #~ msgid "Resour_ce:" #~ msgstr "Рэ_сурс:" #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "Назва рэсурса перадаецца серверу, каб той мог адрозніваць некалькі " #~ "праграмаў, злучаных праз адзін рахунак. Такім чынам, Вы можаце злучыцца " #~ "праз адзін рахунак і з рэсурса 'Дома', і з рэсурса 'Праца'. Падзеі будуць " #~ "накіроўвацца на рэсурс з найвышэйшым прыярытэтам. (гл. ніжэй)" #, fuzzy #~ msgid "A_djust to status" #~ msgstr "_Адпаведна стану" #~ msgid "Priority will change automatically according to your status." #~ msgstr "Прыярытэт будзе змяняцца згодна з станам." #, fuzzy #~ msgid "Anonymous authentication" #~ msgstr "Аўтарызацыя" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "Прыярытэт вызначае, куды накіроўваць падзеі, калі некалькі праграмаў " #~ "злучаныя з серверам праз адзін рахунак. Праграма з найвышэйшым " #~ "прыярытэтам атрымлівае гэтыя падзеі" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Паказаць _адлучаных людзей" #~ msgid "Chan_ge Password" #~ msgstr "З_мяніць пароль" #~ msgid "Click to change account's password" #~ msgstr "Пстрыкніце, каб змяніць пароль рахунка" #, fuzzy #~ msgid "Administration operations" #~ msgstr "Спіс адміністратараў" #, fuzzy #~ msgid "Browse..." #~ msgstr "_Праглядзець" #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "[Гэтае паведамленне зашыфраванае]" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim будзе аўтаматычна злучацца з дапамогай " #~ "гэтага рахунка" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Паказаць _адлучаных людзей" #~ msgid "Synch_ronize account status with global status" #~ msgstr "С_інхранізаваць стан рахунка з глабальным станам" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, любыя глабальныя змены стану (праз адмысловы " #~ "спіс унізе галоўнага вакна) будуць змяняць стан рахунка адпаведным чынам" #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim зойме некаторыя іншыя адрасы IP, і " #~ "шанец правільнай перадачы файлаў падвысіцца." #, fuzzy #~ msgid "Proxy" #~ msgstr "Уласцівасці" #, fuzzy #~ msgid "Send _keep-alive packets" #~ msgstr "Адпраўляць праверачныя пакункі серверу" #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim адпраўляе адмысловыя інфармацыйныя " #~ "пакункі для запэўнівання сервера ў Вашым існаванні" #, fuzzy #~ msgid "Use cust_om hostname/port" #~ msgstr "Адмысловы вузел / порт" #, fuzzy #~ msgid "_Hostname: " #~ msgstr "Назва вузла: " #, fuzzy #~ msgid "_Port: " #~ msgstr "_Порт:" #~ msgid "No key selected" #~ msgstr "Ключ не выбраны" #~ msgid "Choose _Key..." #~ msgstr "Выберыце _ключ..." #, fuzzy #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim запомніць пароль для гэтага рахунка" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "_Edit Personal Information..." #~ msgstr "Змяніць асабістыя звесткі..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Звесткі аб Вас, якія захоўваюцца на серверы" #~ msgid "Personal Information" #~ msgstr "Асабістыя звесткі" #, fuzzy #~ msgid "Co_nnect on Gajim startup" #~ msgstr "_Злучацца па старце Gajim" #, fuzzy #~ msgid "Synchroni_ze account status with global status" #~ msgstr "С_інхранізаваць стан рахунка з глабальным станам" #, fuzzy #~ msgid "Use cust_om port:" #~ msgstr "Адмысловы порт:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Калі порт адпраўкі паведамленняў не прыдатны для Вас, выберыце іншы.\n" #~ "Вам можа спатрэбіцца таксама змяніць настаўленні фаервола." #~ msgid "Mer_ge accounts" #~ msgstr "_Аб'яднаць рахункі" #, fuzzy #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "Немагчыма ўжыць OpenPGP на гэтым кампутары" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Каб змяніць назву рахунка, трэба папярэдне адлучыцца." #~ msgid "To change the account name, you must read all pending events." #~ msgstr "" #~ "Каб змяніць назву рахунка, Вы павінны праглядзець усе нягледжаныя падзеі." #~ msgid "Account Name Already Used" #~ msgstr "Назва рахунка ўжо скарыстаная" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "" #~ "Гэтая назва ўжо скарыстаная для іншага рахунка. Выберыце іншую назву." #~ msgid "Invalid account name" #~ msgstr "Няправільная назва рахунка" #~ msgid "Account name cannot be empty." #~ msgstr "Назва рахунка не павінна быць пустой." #~ msgid "Account name cannot contain spaces." #~ msgstr "Назва рахунка не павінна ўтрымліваць прагалаў." #, fuzzy #~ msgid "Enter a new name for account %s" #~ msgstr "Вызначце новую назву групы %s" #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "Jabber ID павінны мець форму \"user@servername\"." #~ msgid "No such account available" #~ msgstr "Такога рахунка няма" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "Вы павінны стварыць рахунак да рэдагавання асабістых звестак." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "Немагчыма рэдагаваць асабістыя звесткі ў адлучаным рэжыме." #, fuzzy #~ msgid "Your server does not have vCard support" #~ msgstr "Ваш сервер не падтрымлівае Vcard" #~ msgid "Your server can't save your personal information." #~ msgstr "Сервер не можа захаваць Вашыя асабістыя звесткі." #~ msgid "Account Local already exists." #~ msgstr "Мясцовы рахунак Local ужо існуе." #~ msgid "Please rename or remove it before enabling link-local messaging." #~ msgstr "" #~ "Змяніце назву альбо выдаліце яго, каб скарыстаць мясцовыя паведамленні." #~ msgid "THANKS:" #~ msgstr "Падзякі:" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "Немагчыма запісаць у %s. Сеансы не працуюць" #~ msgid "Jabber Traffic" #~ msgstr "Трафік Jabber" #, fuzzy #~ msgid "_Enable" #~ msgstr "Уключыць" #, fuzzy #~ msgid "Filter" #~ msgstr "Гукі" #~ msgid "_IQ" #~ msgstr "_IQ" #~ msgid "Info/Query" #~ msgstr "Звесткі/Запыт" #~ msgid "_Message" #~ msgstr "_Паведамленне" #~ msgid "XML Input" #~ msgstr "Увод XML" #~ msgid "XML Console for %s" #~ msgstr "Кансоль XML для %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "Кансоль XML для %s" #~ msgid "Last status: %s" #~ msgstr "Апошняе паведамленне: %s" #~ msgid " since %s" #~ msgstr " ад %s" #~ msgid "since %s" #~ msgstr "ад %s" #, fuzzy #~ msgid "No" #~ msgstr "Ніякі" #, fuzzy #~ msgid "Prefer" #~ msgstr "Уласцівасці" #, fuzzy #~ msgid "Auto" #~ msgstr "Аўтаматычна далучацца" #, fuzzy #~ msgid "otr" #~ msgstr "_Вузел:" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Няправільнае імя карыстальніка" #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "Колькі хвілінаў апошняй размовы паказваць у новых размовах." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Вы злучыцеся з %s без падтрымкі OpenPGP." #, fuzzy #~ msgid "The following message was NOT encrypted" #~ msgstr "[Гэтае паведамленне зашыфраванае]" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Ці ўжыты OpenPGP ў размове з гэтым чалавекам?" #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Пераключыць шыфраванне Open_PGP" #, fuzzy #~ msgid "Toggle End to End Encryption" #~ msgstr "Пераключыць шыфраванне Open_PGP" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "Шыфраванне дзейнічае" #, fuzzy #~ msgid "The following message was encrypted" #~ msgstr "[Гэтае паведамленне зашыфраванае]" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Пераключыць шыфраванне Open_PGP" #, fuzzy #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Гэтае паведамленне *зашыфраванае* (Гл.:JEP:`27`]" #~ msgid "" #~ "If True, listen to D-Bus signals from NetworkManager and change the " #~ "status of accounts (provided they do not have listen_to_network_manager " #~ "set to False and they sync with global status) based upon the status of " #~ "the network connection." #~ msgstr "" #~ "Калі true, чакаць сігналаў D-Bus ад NetworkManager і змяняць стан " #~ "рахункаў (для якіх опцыя listen_to_network_manager не выстаўленая ў False " #~ "і якія сінхранізуюцца з глабальным станам) згодна з станам сеткавага " #~ "злучэння." #, fuzzy #~ msgid "Database cannot be read." #~ msgstr "Назва рахунка не павінна быць пустой." #, fuzzy #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Адправіць паведамленне і закрыць вакно" #~ msgid "Show _XML Console" #~ msgstr "Паказаць _кансоль XML" #, fuzzy #~ msgid "Edit _Privacy Lists..." #~ msgstr "_Спісы прыватнасці" #~ msgid "_Administrator" #~ msgstr "_Адміністратар" #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "Адправіць паведамленне ўсім далучаным людзям з гэтага сервера" #~ msgid "Sets Message of the Day" #~ msgstr "Вызначыць паведамленне дня" #~ msgid "Updates Message of the Day" #~ msgstr "Абнавіць паведамленне дня" #~ msgid "Deletes Message of the Day" #~ msgstr "Выдаліць паведамленне дня" #, fuzzy #~ msgid "Add _Contact..." #~ msgstr "_Дадаць чалавека..." #, fuzzy #~ msgid "_Accounts" #~ msgstr "Рахункі" #~ msgid "Profile, A_vatar" #~ msgstr "Профіль, а_ватар" #~ msgid "File _Transfers" #~ msgstr "Перадача _файлаў" #~ msgid "Help online" #~ msgstr "Дапамога ў Сеціве" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Частыя пытанні (у Сеціве)" #, fuzzy #~ msgid "Fea_tures" #~ msgstr "Здольнасці сервера" #~ msgid "to %s account" #~ msgstr "рахунку %s" #~ msgid "using %s account" #~ msgstr "выкарыстоўвае рахунак %s" #~ msgid "of account %s" #~ msgstr "рахунка %s" #~ msgid "for account %s" #~ msgstr "для рахунка %s" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Выдаліўшы гэтага чалавека з Вашага кантактнага ліста, Вы такім чынам " #~ "таксама прыбярэце ў яго аўтарызацыю, і ён заўсёды будзе бачыць Вас " #~ "адлучаным." #~ msgid "Invalid Jabber ID" #~ msgstr "Няправільны Jabber ID" #~ msgid "This file is being used by another process." #~ msgstr "Гэтым файлам карыстаецца іншы працэс." #~ msgid "pgp key" #~ msgstr "ключ pgp" #~ msgid "" #~ "Sends new single message to a contact in the roster. Both OpenPGP key and " #~ "account are optional. If you want to set only 'account', without 'OpenPGP " #~ "key', just set 'OpenPGP key' to ''." #~ msgstr "" #~ "Адпраўляе новае асобнае паведамленне чалавеку з спіса. Выстаўленне ключа " #~ "OpenPGP і рахунка не абавязковае. Калі Вы хочаце вызначыць толькі " #~ "'account', без 'ключа OpenPGP', проста выставіце 'ключ OpenPGP' у ''." #, fuzzy #~ msgid "Please first choose another theme as your current theme." #~ msgstr "Спачатку актывізуйце іншую тэму." #~ msgid "Your passphrase is incorrect" #~ msgstr "Пароль няправільны" #, fuzzy #~ msgid "OpenPGP Passphrase Incorrect" #~ msgstr "Пароль няправільны" #~ msgid "You successfully received %(filename)s from %(name)s." #~ msgstr "Файл %(filename)s паспяхова атрыманы ад %(name)s." #, fuzzy #~ msgid "Set logs directory" #~ msgstr "стварэнне дырэкторыі %s" #~ msgid "Chats" #~ msgstr "Размовы" #~ msgid "_Manage Bookmarks..." #~ msgstr "_Кіраванне закладкамі..." #~ msgid "Change Status Message..." #~ msgstr "Змяніць паведамленне стану..." #~ msgid "_Change Status Message..." #~ msgstr "_Змяніць паведамленне стану..." #~ msgid "" #~ "You are not interested in the contact's presence, and neither he/she is " #~ "interested in yours" #~ msgstr "Вы не цікавіцеся чалавекам, і ён не цікавіцца Вамі" #~ msgid "Error description..." #~ msgstr "Апісанне памылкі..." #, fuzzy #~ msgid "View contact information (Ctrl+I)" #~ msgstr "сочыць за размовай" #, fuzzy #~ msgid "Groupchat Histories" #~ msgstr "Групавыя размовы" #, fuzzy #~ msgid "All Chat Histories" #~ msgstr "Старыя казкі" #~ msgid "More" #~ msgstr "Яшчэ" #~ msgid "creating %s directory" #~ msgstr "стварэнне дырэкторыі %s" #, fuzzy #~ msgid "" #~ "If True, Gajim will use KDE Wallet (if kwalletcli is available) to store " #~ "account passwords." #~ msgstr "" #~ "Калі true, Gajim будзе захоўваць паролі ад рахункаў з дапамогай кіраўніка " #~ "пароляў Gnome Keyring (калі ўсталяваны)." #~ msgid "%s is not the name of a group chat." #~ msgstr "%s не з'яўляецца сапраўднай назвай групавой размовы." #, fuzzy #~ msgid "Session Management" #~ msgstr "Паведамленне адпраўленае" #~ msgid "Gajim needs X server to run. Quiting..." #~ msgstr "Gajim патрабуе запуску сервера X. Выхад..." #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above" #~ msgstr "Gajim патрабуе PyGTK 2.6 альбо вышэйшай версіі" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above to run. Quiting..." #~ msgstr "" #~ "Gajim патрабуе PyGTK 2.6 альбо вышэйшай версіі для запуску. Выхад..." #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above" #~ msgstr "Gajim патрабуе GTK 2.6 альбо вышэйшай версіі" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above to run. Quiting..." #~ msgstr "Gajim патрабуе GTK 2.6 альбо вышэйшай версіі для запуску. Выхад..." #~ msgid "Gajim needs pywin32 to run" #~ msgstr "Gajim патрабуе pywin32 для запуску" #~ msgid "" #~ "Please make sure that Pywin32 is installed on your system. You can get it " #~ "at %s" #~ msgstr "Праверце, ці ўсталяваны Pywin32. Вы можаце сцягнуць яго з %s" #~ msgid "Gajim is already running" #~ msgstr "Gajim ужо працуе" #~ msgid "" #~ "Another instance of Gajim seems to be running\n" #~ "Run anyway?" #~ msgstr "" #~ "Gajim ужо працуе\n" #~ "Усё роўна запусціць наноў?" #~ msgid "A programming error has been detected" #~ msgstr "Знойдзеная памылка праграмнага коду" #~ msgid "Details" #~ msgstr "Падрабязнасці" #, fuzzy #~ msgid "" #~ "Gnome Keyring is installed but not correctly started (environment " #~ "variable probably not correctly set)" #~ msgstr "" #~ "Кіраўнік пароляў Gnomekeyring усталяваны, але няправільна выконваецца " #~ "(магчыма, зменная асяроддзя выстаўленая няправільна)" #~ msgid "Jabber ID: " #~ msgstr "Jabber ID:" #~ msgid "Resource: " #~ msgstr "Рэсурс: " #~ msgid "Subscription: " #~ msgstr "Падпіска: " #, fuzzy #~ msgid "Mood: " #~ msgstr "Пакой:" #, fuzzy #~ msgid "Activity: " #~ msgstr "Актывізаваны" #, fuzzy #~ msgid "Join _Group Chat..." #~ msgstr "Удзельнічаць у _групавой размове" #, fuzzy #~ msgid "_Modify Account" #~ msgstr "Змяніць рахунак" #, fuzzy #~ msgid "Check on startup if Gajim is the _default Jabber client" #~ msgstr "" #~ "Заўсёды пры запуску спраўджваць, ці з'яўляецца Gajim _прадвызначанай " #~ "Jabber-праграмай" #~ msgid "_Group Chat" #~ msgstr "_Групавая размова" #~ msgid "" #~ "If True, Gajim will check if it's the default jabber client on each " #~ "startup." #~ msgstr "" #~ "Калі true, Gajim будзе пры запуску спраўджваць, ці з'яўляецца ён " #~ "прадвызначанай Jabber-праграмай." #~ msgid "Gajim is not the default Jabber client" #~ msgstr "Gajim не з'яўляецца прадвызначанай Jabber-праграмай" #~ msgid "Would you like to make Gajim the default Jabber client?" #~ msgstr "Ці Вы хочаце зрабіць Gajim прадвызначанай Jabber-праграмай?" #~ msgid "Always check to see if Gajim is the default Jabber client on startup" #~ msgstr "" #~ "Заўсёды пры запуску спраўджваць, ці з'яўляецца Gajim прадвызначанай " #~ "Jabber-праграмай" #, fuzzy #~ msgid "Send Single Message" #~ msgstr "Ад_правіць асобнае паведамленне" #~ msgid "Execute Command..." #~ msgstr "Выканаць загад..." #~ msgid " a window/tab opened with that contact " #~ msgstr " вакно / картка размовы з гэтым чалавекам адкрыта " #~ msgid "Actions" #~ msgstr "Дзеянні" #~ msgid "Conditions" #~ msgstr "Умовы" #~ msgid "Advanced Actions" #~ msgstr "Адмысловыя дзеянні" #~ msgid "Advanced Notifications Control" #~ msgstr "Адмысловыя настаўленні нагадванняў" #~ msgid "Busy " #~ msgstr "Заняты" #, fuzzy #~ msgid "Contact Change Status " #~ msgstr "Чалавек змяніў стан" #~ msgid "Don't have " #~ msgstr "Няма " #, fuzzy #~ msgid "File Transfer Started " #~ msgstr "Перадача файла спыненая" #, fuzzy #~ msgid "Group Chat Message Highlight " #~ msgstr "Фарбаванае паведамленне ў групавой размове" #, fuzzy #~ msgid "Group Chat Message Received " #~ msgstr "Новае паведамленне ў групавой размове" #~ msgid "Launch a command" #~ msgstr "Выканаць загад" #~ msgid "One or more special statuses..." #~ msgstr "Некалькі спецыяльных станаў..." #~ msgid "Online / Free For Chat" #~ msgstr "У сетцы / Вольны для размовы" #~ msgid "Play a sound" #~ msgstr "Граць гук" #~ msgid "When " #~ msgstr "Калі " #~ msgid "" #~ "_Activate window manager's UrgencyHint to make chat window in taskbar " #~ "flash" #~ msgstr "" #~ "_Скарыстаць здольнасць UrgencyHint, каб вакно размовы міргала на панэлі " #~ "заданняў" #~ msgid "_Disable auto opening chat window" #~ msgstr "_Не адкрываць аўтаматычна вокны размовы" #~ msgid "_Disable existing popup window" #~ msgstr "_Адключыць выплыўнае вакно" #~ msgid "_Disable existing sound for this event" #~ msgstr "_Адключыць гук для гэтай падзеі" #, fuzzy #~ msgid "_Disable showing event in notification area" #~ msgstr "_Не паказваць падзею ў галоўным вакне" #~ msgid "_Disable showing event in roster" #~ msgstr "_Не паказваць падзею ў галоўным вакне" #~ msgid "_Inform me with a popup window" #~ msgstr "_Паведаміць у выплыўным вакне" #~ msgid "_Open chat window with user" #~ msgstr "_Адкрыць вакно размовы з карыстальнікам" #~ msgid "_Show event in roster" #~ msgstr "_Паказваць падзею ў галоўным вакне" #~ msgid "and I " #~ msgstr "і я " #, fuzzy #~ msgid "contact(s)" #~ msgstr "Людзі" #~ msgid "for " #~ msgstr "для " #, fuzzy #~ msgid "group(s)" #~ msgstr "Група" #~ msgid "when I'm in" #~ msgstr "калі я ў" #~ msgid "_Allow him/her to see my status" #~ msgstr "Дазволіць чалавеку _бачыць змены майго стану" #, fuzzy #~ msgid "Descrition:" #~ msgstr "Апісанне: %s" #, fuzzy #~ msgid "Advanced..." #~ msgstr "Адмысловы" #, fuzzy #~ msgid "Display _activity of contacts in roster" #~ msgstr "Паказваць _малюнкі ў галоўным вакне" #, fuzzy #~ msgid "Display _tunes of contacts in roster" #~ msgstr "Паказваць _малюнкі ў галоўным вакне" #, fuzzy #~ msgid "Display m_ood of contacts in roster" #~ msgstr "Паказваць _малюнкі ў галоўным вакне" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the activity of contacts in the roster " #~ "window" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim паказвае аватары ў галоўным вакне і ў " #~ "групавых размовах" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the location of contacts in the roster " #~ "window" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim паказвае аватары ў галоўным вакне і ў " #~ "групавых размовах" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the tunes of contacts in the roster window" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim паказвае аватары ў галоўным вакне і ў " #~ "групавых размовах" #~ msgid "Gajim Instant Messenger" #~ msgstr "Імгненны паведамляльнік Gajim" #~ msgid "English" #~ msgstr "Ангельская" #~ msgid "Belarusian" #~ msgstr "Беларуская" #~ msgid "Bulgarian" #~ msgstr "Балгарская" #, fuzzy #~ msgid "Breton" #~ msgstr "Брытонская" #~ msgid "Czech" #~ msgstr "Чэшская" #~ msgid "German" #~ msgstr "Нямецкая" #~ msgid "Greek" #~ msgstr "Грэцкая" #~ msgid "British" #~ msgstr "Брытанская" #~ msgid "Esperanto" #~ msgstr "Эсперанта" #~ msgid "Spanish" #~ msgstr "Іспанская" #, fuzzy #~ msgid "Basque" #~ msgstr "Басцкая" #~ msgid "French" #~ msgstr "Французская" #~ msgid "Croatian" #~ msgstr "Харвацкая" #~ msgid "Italian" #~ msgstr "Італійская" #~ msgid "Norwegian (b)" #~ msgstr "Нарвежская (бокмал)" #~ msgid "Dutch" #~ msgstr "Галандская" #~ msgid "Norwegian" #~ msgstr "Нарвежская" #~ msgid "Polish" #~ msgstr "Польская" #~ msgid "Portuguese" #~ msgstr "Партугальская" #~ msgid "Brazilian Portuguese" #~ msgstr "Бразільская партугальская" #~ msgid "Russian" #~ msgstr "Расейская" #, fuzzy #~ msgid "Serbian" #~ msgstr "Нямецкая" #~ msgid "Slovak" #~ msgstr "Славацкая" #~ msgid "Swedish" #~ msgstr "Шведская" #~ msgid "Chinese (Ch)" #~ msgstr "Кітайская (Ch)" #~ msgid "Spelling language" #~ msgstr "Мова правапісу" #~ msgid "all or space separated status" #~ msgstr "усе ці падзеленыя прагаламі станы" #~ msgid "'yes', 'no', or 'both'" #~ msgstr "'yes', 'no' ці 'both'" #~ msgid "'yes', 'no' or ''" #~ msgstr "'yes', 'no' ці ''" #~ msgid "Check your connection or try again later" #~ msgstr "Праверце злучэнне альбо паспрабуйце пазней" #~ msgid "error: cannot open %s for reading" #~ msgstr "памылка: немагчыма прачытаць %s" #~ msgid "Unable to bind to port %s." #~ msgstr "Немагчыма адкрыць порт %s." #~ msgid "" #~ "Maybe you have another running instance of Gajim. File Transfer will be " #~ "cancelled." #~ msgstr "Магчыма, Gajim ужо працуе. Перадача файлаў скасаваная." #~ msgid "A GTK+ jabber client" #~ msgstr "Jabber-праграма для GTK+" #~ msgid "Condition" #~ msgstr "Умова" #~ msgid "when I am " #~ msgstr "калі я " #, fuzzy #~ msgid "one of: offline, online, chat, away, xa, dnd, invisible " #~ msgstr "адзін з: offline, online, chat, away, xa, dnd, invisible " #, fuzzy #~ msgid "" #~ "Returns current status message(the global one unless account is specified)" #~ msgstr "" #~ "Вяртае бягучае паведамленне аб стане (глабальнае, калі не вызначаны " #~ "рахунак)" #~ msgid "" #~ "Usage: %s %s %s \n" #~ "\t %s" #~ msgstr "" #~ "Карыстанне: %s %s %s \n" #~ "\t %s" #, fuzzy #~ msgid "" #~ "Too many arguments. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Надта шмат аргументаў. \n" #~ "Увядзіце \"%s help %s\" для падрабязнейшых звестак" #, fuzzy #~ msgid "" #~ "Argument \"%s\" is not specified. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Аргумент \"%s\" не вызначаны. \n" #~ "Увядзіце \"%s help %s\" для падрабязных звестак" #~ msgid "Subject: %s" #~ msgstr "Тэма: %s" #, fuzzy #~ msgid "Mood: %s" #~ msgstr "Пакой:" #, fuzzy #~ msgid "Activity: %s" #~ msgstr "Актывізаваны" #~ msgid "_Disable showing event in systray" #~ msgstr "_Не паказваць падзею ў прасторы паведамленняў" #~ msgid "_Show event in systray" #~ msgstr "_Паказваць падзею ў прасторы паведамленняў" #, fuzzy #~ msgid "Autodetect on every Gajim startup" #~ msgstr "_Злучацца па старце Gajim" #, fuzzy #~ msgid "Show systray:" #~ msgstr "_Паказваць падзею ў прасторы паведамленняў" #~ msgid "Nickname not allowed: %s" #~ msgstr "Такая мянушка не дазволеная: %s" #~ msgid "we are now subscribed to %s" #~ msgstr "цяпер падпісаны на %s" #~ msgid "we are now unsubscribed from %s" #~ msgstr "цяпер адпісаны ад %s" #~ msgid "Account Modification" #~ msgstr "Змяненне рахунка" #~ msgid "" #~ "Check this so Gajim will connect in port 5223 where legacy servers are " #~ "expected to have SSL capabilities. Note that Gajim uses TLS encryption by " #~ "default if broadcasted by the server, and with this option enabled TLS " #~ "will be disabled" #~ msgstr "" #~ "Скарыстайце гэтую опцыю, калі хочаце, каб Gajim злучаўся з серверам праз " #~ "порт 5223, праз які старыя серверы даюць мажлівасць выкарыстання SSL. " #~ "Зважайце, што Gajim звычайна выкарыстоўвае шыфраванне TLS, калі " #~ "звяртаецца да сервера, а гэтая опцыя адключыць выкарыстанне TLS" #~ msgid "Edit Personal Information..." #~ msgstr "Змяніць асабістыя звесткі..." #~ msgid "Hostname: " #~ msgstr "Назва вузла: " #~ msgid "" #~ "If checked, Gajim will store the password in ~/.gajim/config with 'read' " #~ "permission only for you" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim будзе захоўваць пароль у файле ~/.gajim/" #~ "config з правамі чытання толькі для Вас" #~ msgid "Port: " #~ msgstr "Порт: " #~ msgid "Save _passphrase (insecure)" #~ msgstr "Захоўваць _пароль (небяспечна)" #~ msgid "Use _SSL (legacy)" #~ msgstr "Ужыць _SSL (састарэлая опцыя)" #~ msgid "" #~ "Receive a Message\n" #~ "Contact Disconnected \n" #~ "Contact Change Status \n" #~ "Group Chat Message Highlight \n" #~ "Group Chat Message Received \n" #~ "File Transfer Request \n" #~ "File Transfer Started \n" #~ "File Transfer Finished" #~ msgstr "" #~ "Атрыманае паведамленне\n" #~ "Чалавек адлучыўся \n" #~ "Чалавек змяніў стан \n" #~ "Фарбаванае паведамленне групавой размовы \n" #~ "Атрыманае групавое паведамленне \n" #~ "Запыт на перадачу файла \n" #~ "Перадача файла пачалася \n" #~ "Перадача файла скончаная" #~ msgid "" #~ "contact(s)\n" #~ "group(s)\n" #~ "everybody" #~ msgstr "" #~ "людзі\n" #~ "групы\n" #~ "усе" #~ msgid "" #~ "Account row\n" #~ "Group row\n" #~ "Contact row\n" #~ "Chat Banner" #~ msgstr "" #~ "Шэраг рахункаў\n" #~ "Шэраг групаў\n" #~ "Шэраг людзей\n" #~ "Банер размовы" #, fuzzy #~ msgid "gtk-delete" #~ msgstr "Выдаліць" #~ msgid "" #~ "All chat states\n" #~ "Composing only\n" #~ "Disabled" #~ msgstr "" #~ "Усе станы\n" #~ "Толькі пісанне\n" #~ "Адключана" #, fuzzy #~ msgid "" #~ "Autodetect on every Gajim startup\n" #~ "Always use GNOME default applications\n" #~ "Always use KDE default applications\n" #~ "Always use Xfce default applications\n" #~ "Custom" #~ msgstr "" #~ "Аўтаматычна вызначаць пры кожным запуску Gajim\n" #~ "Заўсёды карыстацца праграмамі, прызначанымі ў GNOME\n" #~ "Заўсёды карыстацца праграмамі, прызначанымі ў KDE\n" #~ "Адмысловы" #~ msgid "" #~ "none\n" #~ "both\n" #~ "from\n" #~ "to" #~ msgstr "" #~ "ніводны\n" #~ "абодва\n" #~ "ад\n" #~ "каму" #, fuzzy #~ msgid "gtk-cancel" #~ msgstr "Выдаліць" #~ msgid "pysqlite2 (aka python-pysqlite2) dependency is missing. Exiting..." #~ msgstr "" #~ "Залежнасць ад pysqlite2 (aka python-pysqlite2) не выкананая. Выхад..." #~ msgid "GTK+ runtime is missing libglade support" #~ msgstr "GTK+ не падтрымлівае libglade" #~ msgid "" #~ "Please remove your current GTK+ runtime and install the latest stable " #~ "version from %s" #~ msgstr "" #~ "Выдаліце бібліятэку GTK+ і ўсталюйце найноўшую стабільную версію з %s" #~ msgid "" #~ "Please make sure that GTK+ and PyGTK have libglade support in your system." #~ msgstr "" #~ "Праверце, ці падтрымліваюць бібліятэкі GTK+ і PyGTK сродкі libglade." #~ msgid "Gajim needs PySQLite2 to run" #~ msgstr "Gajim патрабуе PySQLite2 для запуску" #, fuzzy #~ msgid "gtk-ok" #~ msgstr "gtk+" #, fuzzy #~ msgid "" #~ "The host %s you configured as the ft_add_hosts_to_send advanced option is " #~ "not valid, so ignored." #~ msgstr "" #~ "Вузел, вызначаны опцыяй ft_override_host_to_send, некарэктны, таму " #~ "ігнаруецца." #~ msgid "OpenPGP passphrase was not given" #~ msgstr "Пароль OpenPGP не вызначаны" #~ msgid "" #~ "To continue sending and receiving messages, you will need to reconnect." #~ msgstr "" #~ "Каб працягваць адпраўку і атрыманне паведамленняў, трэба перадалучыцца." #~ msgid "" #~ "You are not connected or not visible to others. Your message could not be " #~ "sent." #~ msgstr "" #~ "Вы не злучаны альбо не бачны для іншых. Вы не можаце адправіць " #~ "паведамленне." #~ msgid "Add Special _Notification" #~ msgstr "Дадаць спецыяльнае _нагадванне" #~ msgid "Assign Open_PGP Key" #~ msgstr "Прызначыць ключ Open_PGP" #~ msgid "Commands: %s" #~ msgstr "Загады: %s" #, fuzzy #~ msgid "" #~ "Usage: /%(command)s , sends action to the current group chat. Use " #~ "third person. (e.g. /%(command)s explodes.)" #~ msgstr "" #~ "Карыстанне: /%s <дзеянне>, выконвае дзеянне ў групавой размове (ад трэцяй " #~ "асобы). (напр., /%s рагоча як конь.)" #~ msgid "No help info for /%s" #~ msgstr "Даведка па /%s адсутнічае" #~ msgid "Enable link-local/zeroconf messaging" #~ msgstr "Дазволіць мясцовыя паведамленні" #~ msgid "Nickname not found: %s" #~ msgstr "Мянушка не знойдзеная: %s" #~ msgid "This group chat has no subject" #~ msgstr "Для гэтай групавой размовы не вызначаная тэма размовы" #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], bans the JID from the group chat. The " #~ "nickname of an occupant may be substituted, but not if it contains \"@\". " #~ "If the JID is currently in the group chat, he/she/it will also be kicked." #~ msgstr "" #~ "Карыстанне: /%s <мянушка|JID> [прычына], забараняе JID-у казанне для " #~ "гэтай групавой размовы. Мянушку парушальніка можна змясціць тут, калі яна " #~ "не ўтрымлівае знака \"@\". Калі JID яшчэ ўдзельнічае ў групавой размове, " #~ "ён таксама будзе выкінуты адтуль. Прагалы ў мянушках не падтрымліваюцца." #~ msgid "" #~ "Usage: /%s [reason], closes the current window or tab, displaying reason " #~ "if specified." #~ msgstr "" #~ "Карыстанне: /%s [прычына], закрывае вакно / картку, паказаўшы вызначаную " #~ "прычыну." #~ msgid "" #~ "Usage: /%s [reason], invites JID to the current group chat, " #~ "optionally providing a reason." #~ msgstr "" #~ "Карыстанне: /%s [прычына], запрашае JID паўдзельнічаць у гэтай " #~ "групавой размове, з пазначанай прычынай запрашэння." #~ msgid "" #~ "Usage: /%s @[/nickname], offers to join room@server " #~ "optionally using specified nickname." #~ msgstr "" #~ "Карыстанне: /%s <пакой>@<сервер>[/мянушка], увайсці ў пакой room@server з " #~ "вызначанай мянушкай." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], removes the occupant specified by " #~ "nickname from the group chat and optionally displays a reason." #~ msgstr "" #~ "Карыстанне: /%s <мянушка> [прычына], выкідае парушальніка з вызначанай " #~ "мянушкай з групавой размовы з паказанай прычынай. Прагалы ў мянушках не " #~ "падтрымліваюцца." #~ msgid "" #~ "Usage: /%s [message], opens a private message window and sends " #~ "message to the occupant specified by nickname." #~ msgstr "" #~ "Карыстанне: /%s <мянушка> [паведамленне], адкрывае вакно прыватнай " #~ "размовы і адпраўляе паведамленне чалавеку." #~ msgid "Usage: /%s , changes your nickname in current group chat." #~ msgstr "" #~ "Карыстанне: /%s <мянушка>, змяняе Вашую мянушку ў гэтай групавой размове." #~ msgid "" #~ "Usage: /%s [topic], displays or updates the current group chat topic." #~ msgstr "Карыстанне: /%s [тэма], паказвае ці змяняе тэму групавой размовы." #~ msgid "" #~ "Usage: /%s , sends a message without looking for other commands." #~ msgstr "" #~ "Карыстанне: /%s <паведамленне>, адпраўляе паведамленне, не шукаючы іншых " #~ "загадаў." #, fuzzy #~ msgid "" #~ "Usage: /%s , allow to send you messages and private " #~ "messages." #~ msgstr "" #~ "Карыстанне: /%s <мянушка>, змяняе Вашую мянушку ў гэтай групавой размове." #~ msgid "Click to see features (like MSN, ICQ transports) of jabber servers" #~ msgstr "" #~ "Пстрыкніце, каб праглядзець спіс здольнасцяў jabber-сервераў (напр., " #~ "транспарты MSN, ICQ)" #~ msgid "Name:" #~ msgstr "Імя:" #~ msgid "_Host:" #~ msgstr "_Вузел:" #~ msgid "Modify Account" #~ msgstr "Змяніць рахунак" #, fuzzy #~ msgid "" #~ "%(title)s by %(artist)s\n" #~ "from %(source)s" #~ msgstr "\"%(title)s\" выконвае %(artist)s" #~ msgid "Gajim account %s" #~ msgstr "Рахунак Gajim %s" #~ msgid "This account is already configured in Gajim." #~ msgstr "Гэты рахунак ужо выкарыстоўваецца ў Gajim." #, fuzzy #~ msgid "Idle" #~ msgstr "Id" #~ msgid "File transfer stopped by the contact at the other end" #~ msgstr "Перадача файла спыненая чалавекам" #, fuzzy #~ msgid "Generic" #~ msgstr "Агульная" #~ msgid "%s has not broadcast an OpenPGP key, nor has one been assigned" #~ msgstr "%s не распаўсюджвае ключ OpenPGP і не мае прызначанага ключа" #~ msgid "No such command: /%s (if you want to send this, prefix it with /say)" #~ msgstr "" #~ "Такога загаду няма: /%s (калі Вы хочаце адправіць яго, устаўце перад " #~ "тэкстам \"/say\")" #~ msgid "" #~ "Usage: /%s , sends action to the current group chat. Use third " #~ "person. (e.g. /%s explodes.)" #~ msgstr "" #~ "Карыстанне: /%s <дзеянне>, выконвае дзеянне ў групавой размове (ад трэцяй " #~ "асобы). (напр., /%s рагоча як конь.)" #~ msgid "_Retype Password:" #~ msgstr "Паўта_рыце пароль:" #~ msgid "" #~ "If checked, all local contacts that use a Bonjour compatible chat client " #~ "(like iChat, Trillian or Gaim) will be shown in roster. You don't need to " #~ "be connected to a jabber server for it to work.\n" #~ "This is only available if python-avahi is installed and avahi-daemon is " #~ "running." #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, усе мясцовыя кантакты з Bonjour-кліентам " #~ "(напр., iChat, Trillian, Gaim) будуць паказвацца ў галоўным вакне. Для " #~ "гэтага Вам не патрэбнае злучэнне.\n" #~ "Гэтая мажлівасць будзе працаваць, калі ўсталяваны python-avahi і працуе " #~ "сервіс avahi-daemon." #~ msgid "" #~ "If you have 2 or more accounts and this is checked, Gajim will list all " #~ "contacts as if you had one account" #~ msgstr "" #~ "Калі ў Вас некалькі рахункаў, гэтая опцыя прымушае Gajim паказваць усіх " #~ "людзей з розных рахункаў у адзіным спісе" #~ msgid "_Enable link-local messaging" #~ msgstr "_Уключыць мясцовыя паведамленні" #~ msgid "2003-12-13T18:30:02Z" #~ msgstr "2003-12-13T18:30:02Z" #~ msgid "Romeo and Juliet" #~ msgstr "Рамэа і Джульета" #~ msgid "Soliloquy" #~ msgstr "Маналог" #~ msgid "_Compact View Alt+C" #~ msgstr "_Кампактны выгляд Alt+К" #~ msgid "Click to see past conversation in this room" #~ msgstr "Пстрыкніце, каб праглядзець былую размову ў гэтым пакоі" #~ msgid "Build custom query" #~ msgstr "Стварыць адмысловы запыт" #~ msgid "Query Builder..." #~ msgstr "Стварэнне запыту..." #~ msgid "Invitation Received" #~ msgstr "Атрыманае запрашэнне" #~ msgid "Format of a line" #~ msgstr "Фармат радка" #~ msgid "Interface Customization" #~ msgstr "Інтэрфэйс" #~ msgid "Also known as iChat style" #~ msgstr "Таксама вядома як \"стыль iChat\"" #~ msgid "" #~ "An example: If you have enabled status message for away, Gajim won't ask " #~ "you anymore for a status message when you change your status to away; it " #~ "will use the default one set here" #~ msgstr "" #~ "Напрыклад, калі Вы ўключылі паведамленне стану для сышоўшага стану, Gajim " #~ "больш не будзе ў Вас пытацца пацверджання гэтага паведамлення" #~ msgid "" #~ "Determined by sender\n" #~ "Chat message\n" #~ "Single message" #~ msgstr "" #~ "Вызначае адпраўнік\n" #~ "Размоўнае паведамленне\n" #~ "Асобнае паведамленне" #~ msgid "E_very 5 minutes" #~ msgstr "_Кожныя 5 хвілінаў" #~ msgid "" #~ "Gajim will automatically show new events by popping up the relative window" #~ msgstr "Gajim аўтаматычна пакажа новыя падзеі ў адпаведным выплыўным вакне" #~ msgid "" #~ "Gajim will notify you for new events via a popup in the bottom right of " #~ "the screen" #~ msgstr "" #~ "Gajim будзе паведамляць Вам аб новых падзеях у выплыўным вакне ў правым " #~ "верхнім куце экрана" #~ msgid "" #~ "Gajim will notify you via a popup window in the bottom right of the " #~ "screen about contacts that just signed in" #~ msgstr "" #~ "Gajim будзе паведамляць Вам аб увайшоўшых людзях у выплыўным вакне ў " #~ "правым верхнім куце экрана" #~ msgid "" #~ "Gajim will only change the icon of the contact that triggered the new " #~ "event" #~ msgstr "" #~ "Gajim толькі зменіць значку чалавека, які стаў прычынай новай падзеі" #~ msgid "" #~ "If checked, Gajim will remember the roster and chat window positions in " #~ "the screen and the sizes of them next time you run it" #~ msgstr "" #~ "Калі гэтая опцыя ўключаная, Gajim запомніць пазіцыю галоўнага і іншых " #~ "вокнаў і іх памеры" #~ msgid "" #~ "Never\n" #~ "Always\n" #~ "Per account\n" #~ "Per type" #~ msgstr "" #~ "Ніколі\n" #~ "Заўсёды\n" #~ "Па рахунках\n" #~ "Па тыпе" #~ msgid "Outgoing Chat state noti_fications:" #~ msgstr "Адпраўляць _нагадванні стану размовы:" #~ msgid "Print time:" #~ msgstr "Паказваць час:" #~ msgid "Save _position and size for roster and chat windows" #~ msgstr "Захоўваць _пазіцыю і памеры галоўнага і размоўных вокнаў" #~ msgid "Set status message to reflect currently playing _music track" #~ msgstr "Выстаўляць паведамленне стану з улікам _гранай музыкі" #~ msgid "The auto away status message" #~ msgstr "Паведамленне аб аўтаматычным сыходзе" #~ msgid "Treat all incoming messages as:" #~ msgstr "Лічыць усе ўваходныя паведамленні:" #~ msgid "" #~ "When a new event (message, file transfer request etc..) is received, the " #~ "following methods may be used to inform you about it. Please note that " #~ "events about new messages only occur if it is a new message from a " #~ "contact you are not already chatting with" #~ msgstr "" #~ "Магчымыя наступныя варыянты нагадвання аб здзяйсненні новых падзей " #~ "(паведамленне, запыт на перадачу файла і г.д.). Зважайце, што атрыманне " #~ "новага паведамлення фіксуецца толькі тады, калі Вы атрымліваеце " #~ "паведамленне ад чалавека, з якім на той момант яшчэ не вялася размова" #~ msgid "" #~ "Works for Rhythmbox and Muine players. For more players, please visit " #~ "http://trac.gajim.org/wiki/GajimAndMusicPlayer" #~ msgstr "" #~ "Працуе з Rhythmbox і Muine. Для іншых праграмаў глядзіце старонку http://" #~ "trac.gajim.org/wiki/GajimAndMusicPlayer" #~ msgid "_Advanced Notifications Control..." #~ msgstr "_Адмысловыя настаўленні нагадванняў..." #~ msgid "_Player:" #~ msgstr "_Прайгравальнік:" #~ msgid "Role:" #~ msgstr "Роля:" #~ msgid "_Remove from Roster" #~ msgstr "Вы_даліць з кантактнага ліста" #~ msgid "A_ccounts" #~ msgstr "Р_ахункі" #~ msgid "_Filter:" #~ msgstr "_Фільтар:" #~ msgid "OS:" #~ msgstr "Аперацыйная сістэма:" #~ msgid "" #~ "If that is not your language for which you want to highlight misspelled " #~ "words, then please set your $LANG as appropriate. Eg. for French do " #~ "export LANG=fr_FR or export LANG=fr_FR.UTF-8 in ~/.bash_profile or to " #~ "make it global in /etc/profile.\n" #~ "\n" #~ "Highlighting misspelled words feature will not be used" #~ msgstr "" #~ "Калі гэта не мова, для якой трэба паказваць няправільна напісаныя словы, " #~ "тады вызначце зменную $LANG адпаведным чынам. Напр., для беларускай мовы " #~ "змясціце загад export LANG=be_BY.UTF-8 у файле ~/.bash_profile, альбо " #~ "глабальна ў /etc/profile.\n" #~ "\n" #~ "Фарбаванне няправільна напісаных слоў не працуе" #~ msgid "Every %s _minutes" #~ msgstr "Кожныя %s _хвілінаў" #~ msgid "You will always see him or her as offline." #~ msgstr "Вы заўсёды будзеце бачыць гэтага чалавека адключаным." #~ msgid "%s is now %s (%s)" #~ msgstr "%s цяпер %s (%s)" #~ msgid "%s is now %s" #~ msgstr "%s цяпер %s" #~ msgid "" #~ "\n" #~ "From: %(from_address)s" #~ msgstr "" #~ "\n" #~ "Ад: %(from_address)s" #~ msgid "Network Manager support not available" #~ msgstr "Падтрымка Network Manager адсутнічае" #~ msgid "Session Management support not available (missing gnome.ui module)" #~ msgstr "Падтрымка працоўных сеансаў адсутнічае (няма модуля gnome.ui)" #~ msgid "Private Chat" #~ msgstr "Прыватная размова" #~ msgid "%s does not appear to be a valid JID" #~ msgstr "%s не з'яўляецца карэктным JID" #~ msgid "%s - Gajim" #~ msgstr "%s - Gajim" #~ msgid "_New group chat" #~ msgstr "_Новая групавая размова" #~ msgid "_Log on" #~ msgstr "_Увайсці" #~ msgid "Log _off" #~ msgstr "_Сысці" #~ msgid "Save passphrase" #~ msgstr "Захоўваць пароль" #~ msgid "Drop %s in group %s" #~ msgstr "Перанесці %s у групу %s" #~ msgid "Hides the buttons in two persons chat window." #~ msgstr "Схаваць кнопкі прыватнай размовы." #~ msgid "Connected to server %s:%s with %s" #~ msgstr "Злучаны з серверам %s:%s з %s" #~ msgid "invisible" #~ msgstr "нябачны" #~ msgid "offline" #~ msgstr "адключаны" #~ msgid " %d unread single message" #~ msgid_plural " %d unread single messages" #~ msgstr[0] "%d нечытанае асобнае паведамленне" #~ msgstr[1] "%d нечытаныя асобныя паведамленні" #~ msgstr[2] "%d нечытаных асобных паведамленняў" #~ msgid " %d unread group chat message" #~ msgid_plural " %d unread group chat messages" #~ msgstr[0] "%d нечытанае групавое паведамленне" #~ msgstr[1] "%d нечытаныя групавыя паведамленні" #~ msgstr[2] "%d нечытаных групавых паведамленняў" #~ msgid " %d unread private message" #~ msgid_plural " %d unread private messages" #~ msgstr[0] "%d нечытанае прыватнае паведамленне" #~ msgstr[1] "%d нечытаныя прыватныя паведамленні" #~ msgstr[2] "%d нечытаных прыватных паведамленняў" #~ msgid "" #~ "Connection to host could not be established: Incorrect answer from server." #~ msgstr "Немагчыма злучыцца з вузлом: некарэктны адказ сервера." #~ msgid "Connection to host could not be established" #~ msgstr "Немагчыма ўсталяваць злучэнне з вузлом" #~ msgid "A_fter nickname:" #~ msgstr "_Пасля мянушкі:" #~ msgid "_After time:" #~ msgstr "_Праз пэўны час:" #~ msgid "_Before time:" #~ msgstr "_За пэўны час да:" #~ msgid "_Retrieve" #~ msgstr "_Атрымаць" #~ msgid "Information published" #~ msgstr "Звесткі абноўлены" #~ msgid "Without a connection, you can not get your contact information." #~ msgstr "Вы не можаце атрымаць звесткі аб сабе, не злучыўшыся з сэрвэрам." gajim-gajim-1.1.3/po/be@latin.po000066400000000000000000012201371345766322700164110ustar00rootroot00000000000000# Biełarusji pierakład Gajim # Copyright (C) 2006-2007 Free Software Foundation, Inc. # This file is distributed under the same license as Gajim. # Based on cyrillic version. # # Ihar Hrachyshka , 2006-2007, 2009. msgid "" msgstr "" "Project-Id-Version: 0.11.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2009-08-19 23:41+0200\n" "Last-Translator: Ihar Hrachyshka \n" "Language-Team: Belarusian Latin \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "" #: gajim/chat_control_base.py:1103 #, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "" #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Fajł" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Čas" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Prahres" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Nazva fajłu: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Pamier: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "Ty" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Dasłaŭ: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Atrymaŭ: " #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Zapisany ŭ: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Pieradača fajłu skončana" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 #, fuzzy msgid "Open _Containing Folder" msgstr "_Adčyni kataloh z fajłam" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "Pieradača fajłu anulavana" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "NIemahčyma złučycca ź inšym bokam." #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "Atrymoŭca: %s" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "Tekst pamyłki: %s" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 #, fuzzy msgid "File transfer stopped" msgstr "Pieradača fajłu spyniena" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" #: gajim/filetransfers_window.py:341 #, fuzzy msgid "Gajim can not read this file" msgstr "Gajim nia moža dastupicca da hetaha fajłu" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "" #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "Niemahčyma nadpisać fajł \"%s\"" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "" "Fajł z takoj nazvaj užo isnuje, i nie staje pravoŭ dla nadpisańnia hetaha " "fajłu." #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Hety fajł užo isnuje" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "Što chočaš zrabić?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "Niemahčyma zapisać u kataloh \"%s\"" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "Nie staje pravoŭ dla stvareńnia fajłaŭ u hetym katalohu." #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Fajł: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Typ: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Apisańnie: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "%s choča dasłać tabie fajł:" #: gajim/filetransfers_window.py:487 #, fuzzy msgid "Checking file…" msgstr "Dasyłańnie profilu..." #: gajim/filetransfers_window.py:501 #, fuzzy msgid "File error" msgstr "Pamyłka pieradačy fajłu" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/s)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Niapravilny fajł" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Fajł: " #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "Niemahčyma dasyłać pustyja fajły" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Nazva:" #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Adpraŭnik:" #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Prypyni" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "_Praciahni" #: gajim/filetransfers_window.py:1019 #, fuzzy msgid "Choose a File to Send…" msgstr "Abiary fajł dla adsyłańnia..." #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "Pašyreńnie nie padtrymvajecca" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" "Niemahčyma zapisać vyjavu ŭ farmacie %(type)s. Zapisać jak %(new_filename)s?" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 #, fuzzy msgid "Save _As" msgstr "Nie razmaŭlaju " #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "?Klijent:Nieviadomy" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "?AS:Nieviadomaja" #: gajim/vcard.py:326 gajim/vcard.py:329 #, fuzzy msgid "?Time:Unknown" msgstr "?Klijent:Nieviadomy" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "" #: gajim/vcard.py:384 #, fuzzy msgid "Affiliation:" msgstr "Aplikacyi" #: gajim/vcard.py:391 #, fuzzy msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "" "Hety kantakt cikavicca tvajim statusam, ale ciabie jahony status nie cikavić" #: gajim/vcard.py:393 #, fuzzy msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "" "Ty cikaviśsia statusam hetaha kantaktu, ale jaho nie cikavić tvoj status" #: gajim/vcard.py:395 #, fuzzy msgid "The contact and you want to exchange presence information" msgstr "Ty i hety kantakt uzajemna cikaviciesia statusam adno adnaho" #: gajim/vcard.py:397 #, fuzzy msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "Ty i hety kantakt uzajemna cikaviciesia statusam adno adnaho" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "Ty čakaješ adkazu kantaktu na zapyt aŭtaryzacyi" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "" #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr " krynica z pryjarytetam " #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "Usie fajły" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 #, fuzzy msgid "Clear File" msgstr "Viečar" #: gajim/options_dialog.py:484 #, fuzzy msgid "Manage Proxies" msgstr "Kiruj profilami proxy" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Nijaki" #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "_Dastasuj da statusu" #: gajim/options_dialog.py:528 msgid "On" msgstr "" #: gajim/options_dialog.py:528 #, fuzzy msgid "Off" msgstr "Adłučany" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Niemahčyma atrymać sakretnyja klučy" #: gajim/options_dialog.py:565 #, fuzzy msgid "There is no OpenPGP secret key available." msgstr "Adbyłasia pamyłka ŭ časie atrymańnia sakretnych klučoŭ OpenPGP." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "Vybar kluča OpenPGP" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Abiary svoj kluč OpenPGP" #: gajim/gui_menu_builder.py:95 #, fuzzy msgid "_New Group Chat" msgstr "Novaja hrupavaja razmova" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Niama ŭ śpisie" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "Ja chaču dadać ciabie da svajho śpisu kantaktaŭ" #: gajim/gui_menu_builder.py:502 #, fuzzy msgid "Send Single _Message…" msgstr "Vyšli _asobnaje paviedamleńnie" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 #, fuzzy msgid "Send Cus_tom Status" msgstr "Dasyłaje svoj XML" #: gajim/gui_menu_builder.py:535 #, fuzzy msgid "E_xecute Command…" msgstr "_Vykanaj zahad..." #: gajim/gui_menu_builder.py:543 #, fuzzy msgid "_Manage Transport" msgstr "Transparty" #: gajim/gui_menu_builder.py:549 #, fuzzy msgid "_Modify Transport" msgstr "Pakažy _transparty" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 #, fuzzy msgid "_Rename…" msgstr "Źmiani _nazvu" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 #, fuzzy msgid "Remo_ve" msgstr "_Vydal" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 #, fuzzy msgid "_Information" msgstr "Źviestki ab kantakcie" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 #, fuzzy msgid "Send File…" msgstr "Vyšli _fajł" #: gajim/gui_menu_builder.py:602 #, fuzzy msgid "Upload File…" msgstr "Zapišy fajł jak..." #: gajim/gui_menu_builder.py:603 #, fuzzy msgid "Send File Directly…" msgstr "Zapišy fajł jak..." #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Kantakty" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "_Dadaj u śpis kantaktaŭ" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "Źviestki ab kantakcie" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 #, fuzzy msgid "History" msgstr "_Žurnał razmoŭ" #: gajim/gui_menu_builder.py:634 #, fuzzy msgid "Manage Room" msgstr "Kiruj zakładkami" #: gajim/gui_menu_builder.py:635 #, fuzzy msgid "Change Subject" msgstr "Źmiani _temu" #: gajim/gui_menu_builder.py:636 #, fuzzy msgid "Configure Room" msgstr "Kanfihuruj _pakoj" #: gajim/gui_menu_builder.py:637 #, fuzzy msgid "Upload Avatar…" msgstr "Abiary vyjavu" #: gajim/gui_menu_builder.py:638 #, fuzzy msgid "Destroy Room" msgstr "Apisańnie: %s" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "" #: gajim/gui_menu_builder.py:641 #, fuzzy msgid "Change Nick" msgstr "Źmiani _mianušku" #: gajim/gui_menu_builder.py:642 #, fuzzy msgid "Bookmark Room" msgstr "_Stvary zakładku dla hetaja pakoju" #: gajim/gui_menu_builder.py:643 #, fuzzy msgid "Request Voice" msgstr "_Daj hołas" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 #, fuzzy msgid "Notify on all messages" msgstr "Šablony paviedamleńniaŭ statusu:" #: gajim/gui_menu_builder.py:645 msgid "Minimize on close" msgstr "" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 #, fuzzy msgid "Execute command" msgstr "_Vykanaj zahad..." #: gajim/gui_menu_builder.py:648 #, fuzzy msgid "Disconnect" msgstr "Kantakt adłučyŭsia" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "" #: gajim/gui_menu_builder.py:680 #, fuzzy, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "%i dzion tamu" msgstr[1] "%i dzion tamu" msgstr[2] "%i dzion tamu" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Dałučysia da pakoju" #: gajim/gui_menu_builder.py:734 #, fuzzy msgid "Add Contact…" msgstr "_Dadaj kantakt..." #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 #, fuzzy msgid "Profile" msgstr "fajł" #: gajim/gui_menu_builder.py:737 #, fuzzy msgid "Discover Services" msgstr "_Šukaj servisy" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Vyšli _asobnaje paviedamleńnie" #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Pašyranyja" #: gajim/gui_menu_builder.py:740 #, fuzzy msgid "Archiving Preferences" msgstr "_Nałady" #: gajim/gui_menu_builder.py:741 #, fuzzy msgid "Synchronise History" msgstr "Pakažy _adłučanyja kantakty" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "Śpisy pryvatnaści" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 #, fuzzy msgid "Server Info" msgstr "Server" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "Kansol XML" #: gajim/gui_menu_builder.py:746 #, fuzzy msgid "Admin" msgstr "_Administratar" #: gajim/gui_menu_builder.py:747 #, fuzzy msgid "Send Server Message…" msgstr "_Dašli paviedamleńnie servera" #: gajim/gui_menu_builder.py:748 #, fuzzy msgid "Set MOTD…" msgstr "Vyznač MOTD" #: gajim/gui_menu_builder.py:749 #, fuzzy msgid "Update MOTD…" msgstr "Aktualizuj MOTD" #: gajim/gui_menu_builder.py:750 #, fuzzy msgid "Delete MOTD…" msgstr "Vydal MOTD" #: gajim/gui_menu_builder.py:799 #, fuzzy msgid "No Accounts available" msgstr "Konty niedastupnyja" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Konty" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 #, fuzzy msgid "Copy JID" msgstr "Pakoj:" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Dałučysia da pakoju" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Pačni razmovu" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 #, fuzzy msgid "Add to Roster…" msgstr "_Dadaj u śpis kantaktaŭ" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "S_kapijuj adras spasyłki" #: gajim/gui_menu_builder.py:881 #, fuzzy msgid "Open Link in Browser" msgstr "_Adčyni spasyłku ŭ hartačy" #: gajim/gui_menu_builder.py:886 #, fuzzy msgid "Copy Email Address" msgstr "S_kapijuj JID/Email" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Adčyni paštovuju prahramu" #: gajim/gui_menu_builder.py:892 #, fuzzy msgid "Copy JID/Email" msgstr "S_kapijuj JID/Email" #: gajim/history_manager.py:71 #, fuzzy msgid "Usage:" msgstr "paviedamleńnie" #: gajim/history_manager.py:73 #, fuzzy msgid "Options:" msgstr "Smajliki:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "Niemahčyma znajści bazu žurnałaŭ razmoŭ" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Data" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Mianuška" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Paviedamleńnie" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Tema" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" "Chočaš ačyścić bazu źviestak? (NIE REKAMENDUJECCA RABIĆ Z AKTYŬNYM GAJIMAM)" #: gajim/history_manager.py:257 #, fuzzy msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" "Zvyčajna zaniataja bazaj źviestak prastora nie vyzvalajecca, ale " "rezervujecca dla paźniejšych patrebaŭ prahramy. Kali ty sapraŭdy chočaš " "źmienšyć pamier bazy źviestak, klikni \"Tak\", inakš \"Nie\".\n" "\n" "Kali ty abraŭ \"Tak\", pačakaj..." #: gajim/history_manager.py:262 msgid "Database Cleanup" msgstr "" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(who)s a %(time)s napisaŭ: %(message)s\n" #: gajim/history_manager.py:577 #, fuzzy, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Sapraŭdy chočaš vydalić zaznačanaje paviedamleńnie?" #: gajim/history_manager.py:581 #, fuzzy msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "Sapraŭdy chočaš vydalić žurnał razmoŭ z abranym kantaktam?" #: gajim/history_manager.py:583 #, fuzzy msgid "This can not be undone." msgstr "Niemahčyma znajści servis" #: gajim/history_manager.py:585 gajim/history_manager.py:624 #, fuzzy msgid "Deletion Confirmation" msgstr "Źviestki ab kantakcie" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Sapraŭdy chočaš vydalić zaznačanaje paviedamleńnie?" msgstr[1] "Sapraŭdy chočaš vydalić zaznačanyja paviedamleńni?" msgstr[2] "Sapraŭdy chočaš vydalić zaznačanyja paviedamleńni?" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "Vynikaŭ hetaj aperacyi niemahčyma anulavać." #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "Nazva kantaktu: %s" #: gajim/dialogs.py:84 #, fuzzy, python-format msgid "JID: %s" msgstr "JID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "Ahulnaja" #: gajim/dialogs.py:200 msgid "Group" msgstr "Hrupa" #: gajim/dialogs.py:207 msgid "In the group" msgstr "U hrupie" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "ID kluča" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Nazva kantaktu" #: gajim/dialogs.py:483 #, fuzzy msgid "Set Mood" msgstr "Vyznač MOTD" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "Paviedamleńnie statusu %s" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Paviedamleńnie statusu" #: gajim/dialogs.py:807 #, fuzzy msgid "Overwrite Status Message?" msgstr "Paviedamleńnie statusu" #: gajim/dialogs.py:808 #, fuzzy msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "Kont z takoj nazvaj užo zaniaty. Kali łaska, abiary inšuju nazvu." #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Zapišy jak šablon paviedamleńnia statusu" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Kali łaska, uviadzi nazvu dla hetaha paviedamleńnia statusu" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Zapyt aŭtaryzacyi" #: gajim/dialogs.py:857 #, fuzzy, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Zapyt aŭtaryzacyi dla kontu %s ad %s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Zapyt aŭtaryzacyi ad %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "Niama złučeńnia z serveram" #: gajim/dialogs.py:928 #, fuzzy msgid "Without a connection, you can not synchronise your contacts." msgstr "Niemahčyma źmianić parol, nie dałučyŭšysia da servera." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Nazva" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Server" #: gajim/dialogs.py:978 #, fuzzy msgid "This account is not connected to the server" msgstr "Kont \"%s\" dałučany da servera" #: gajim/dialogs.py:979 #, fuzzy msgid "You cannot synchronize with an account unless it is connected." msgstr "" "Niemahčyma ŭdzielničać u hrupavoj razmovie, nie dałučyŭšysia da servera." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "" #: gajim/dialogs.py:1065 #, fuzzy msgid "add" msgstr "Zatrymana" #: gajim/dialogs.py:1065 #, fuzzy msgid "modify" msgstr "_Madyfikuj" #: gajim/dialogs.py:1066 #, fuzzy msgid "remove" msgstr "_Vydal" #: gajim/dialogs.py:1095 #, fuzzy, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "Ja chaču dadać Vas u svoj śpis kantaktaŭ." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 #, fuzzy msgid "Add" msgstr "Adras" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 #, fuzzy msgid "Modify" msgstr "_Madyfikuj" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Vydal" #: gajim/dialogs.py:1125 #, fuzzy msgid "Groups" msgstr "Hrupa" #: gajim/dialogs.py:1233 #, fuzzy, python-format msgid "%s suggested me to add you in my roster." msgstr "Ja chaču dadać ciabie ŭ svoj śpis kantaktaŭ." #: gajim/dialogs.py:1247 #, fuzzy, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "_Dadaj kantakt" msgstr[1] "_Dadaj kantakt" msgstr[2] "_Dadaj kantakt" #: gajim/dialogs.py:1285 #, fuzzy, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "Vydalaje kantakt sa śpisu" msgstr[1] "Vydalaje kantakt sa śpisu" msgstr[2] "Vydalaje kantakt sa śpisu" #: gajim/dialogs.py:1305 #, fuzzy msgid "You are invited to a groupchat" msgstr "Ty nie dałučyŭsia da pakoju." #: gajim/dialogs.py:1308 #, fuzzy msgid "$Contact has invited you to join a discussion" msgstr "$Contact zaprasiŭ ciabie ŭ pakoj %(room_jid)s" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "$Contact zaprasiŭ ciabie ŭ pakoj %(room_jid)s" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Kamentar: %s" #: gajim/dialogs.py:1321 #, fuzzy msgid "Do you want to accept the invitation?" msgstr "%s choča dasłać tabie fajł:" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Zaprašeńnie ŭ pakoj" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "" #: gajim/dialogs.py:1628 msgid "a video" msgstr "" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 #, fuzzy msgid "File Transfer" msgstr "Pieradačy fajłaŭ" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "" #: gajim/dialogs.py:1764 #, fuzzy msgid "Encrypting file…" msgstr "Šyfravańnie adklučanaje" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, fuzzy, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%s ciapier viadomy jak %s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s maje ciapier status %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Pamyłka dasyłańnia pryvatnaha paviedamleńnia" #: gajim/groupchat_control.py:253 #, fuzzy, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "Ciabie niama ŭ pakoji \"%s\", albo \"%s\" pakinuŭ jaho." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 #, fuzzy msgid "No File Transfer available" msgstr "Pieradačy fajłaŭ" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Źmianiajecca tema" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Kali łaska, vyznač novuju temu:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Źmianiajecca mianuška" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Kali łaska, vyznač dla siabie novuju mianušku:" #: gajim/groupchat_control.py:711 #, fuzzy msgid "Invalid group chat JID" msgstr "Niapravilny JID pakoju" #: gajim/groupchat_control.py:712 #, fuzzy msgid "The group chat JID has not allowed characters." msgstr "JID pakoju ŭtrymlivaje niedazvolenyja znaki." #: gajim/groupchat_control.py:724 #, fuzzy, python-format msgid "Destroying %s" msgstr "Apisańnie: %s" #: gajim/groupchat_control.py:725 msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "Niemahčyma adčytać vyjavu" #: gajim/groupchat_control.py:934 msgid "Insert Nickname" msgstr "Ustaŭ mianušku" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 #, fuzzy msgid "and authenticated" msgstr "Užyvaj aŭtaryzacyju" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 #, fuzzy msgid "and NOT authenticated" msgstr "Užyvaj aŭtaryzacyju" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" #: gajim/groupchat_control.py:1157 #, fuzzy msgid "Conversation with " msgstr "Žurnał razmoŭ" #: gajim/groupchat_control.py:1159 #, fuzzy msgid "Continued conversation" msgstr "Złučeńnie" #: gajim/groupchat_control.py:1525 #, fuzzy, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(nick)s vypchnuty z pakoju: %(reason)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "" #: gajim/groupchat_control.py:1556 msgid "Room now shows unavailable members" msgstr "" #: gajim/groupchat_control.py:1558 msgid "Room now does not show unavailable members" msgstr "" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "" #: gajim/groupchat_control.py:1576 msgid "Room is now fully anonymous" msgstr "" #: gajim/groupchat_control.py:1615 #, python-format msgid "Ping? (%s)" msgstr "" #: gajim/groupchat_control.py:1618 #, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 #, fuzzy msgid "Error." msgstr "Pamyłka Avahi" #: gajim/groupchat_control.py:1845 #, fuzzy, python-format msgid "You (%s) joined the room" msgstr "%s dałučyŭsia da pakoju" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, fuzzy, python-format msgid "%(jid)s has been invited in this room" msgstr "%(who)s vypchnuŭ %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "" #: gajim/groupchat_control.py:1879 #, fuzzy msgid "A new room has been created" msgstr "Aŭtaryzacyja anulavanaja" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s vypchnuty z pakoju: %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(who)s vypchnuŭ %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "%(nick)s zablakavany: %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(who)s zablakavaŭ %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "Ciabie ciapier viedajuć jak %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, fuzzy, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(who)s vypchnuŭ %(nick)s: %(reason)s" #: gajim/groupchat_control.py:1950 #, fuzzy msgid "affiliation changed" msgstr "Suviaź: " #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "" #: gajim/groupchat_control.py:2034 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "%(who)s vypchnuŭ %(nick)s: %(reason)s" #: gajim/groupchat_control.py:2038 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "%(nick)s vypchnuty z pakoju: %(reason)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "%s vyjšaŭ" #: gajim/groupchat_control.py:2067 #, python-format msgid "%s has joined the group chat" msgstr "%s dałučyŭsia da pakoju" #: gajim/groupchat_control.py:2374 #, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Ty sapraŭdy chočaš pakinuć pakoj \"%s\"?" #: gajim/groupchat_control.py:2376 msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "Kali začyniš hetaje akno, adłučyśsia ad pakoju." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 #, fuzzy msgid "_Do not ask me again" msgstr "_Bolš nie pytajsia" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Vypichvajecca %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Možaš akreślić pryčynu nižej:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Blakavańnie %s" #: gajim/chat_control.py:389 #, fuzzy msgid "Show a list of formattings" msgstr "Klikni, kab ustavić smajlik (Alt+M)" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 #, fuzzy msgid "This contact does not support HTML" msgstr "Śpis dziejnych, skončanych i spynienych pieradačaŭ fajłaŭ" #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "" #: gajim/chat_control.py:660 #, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s z pakoju %(room_name)s" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "Tolki što atrymanaje paviedamleńnie ad \"%s\"" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Kali ty začyniš hetuju kartku i kali žurnały nie vieducca, to hetaje " "paviedamleńnie źniknie nazaŭždy." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "" #: gajim/chat_control.py:1205 #, python-format msgid "Pong! (%s seconds)" msgstr "" #: gajim/chat_control.py:1313 #, fuzzy, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Tema: %s\n" "%s" #: gajim/chat_control.py:1416 #, fuzzy, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(nick)s maje ciapier status %(status)s" #: gajim/chat_control.py:1471 #, fuzzy msgid "File transfer" msgstr "Pieradačy fajłaŭ" #: gajim/chat_control.py:1474 #, fuzzy msgid "Size" msgstr "Pamier: %s" #: gajim/chat_control.py:1476 #, fuzzy msgid "Accept" msgstr "Dazvol" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Dałučysia" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 #, fuzzy msgid "Remote contact stopped transfer" msgstr "Vydalaje kantakt sa śpisu" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 #, fuzzy msgid "Error opening file" msgstr "Pamyłka adčytańnia fajłu:" #: gajim/application.py:68 #, fuzzy msgid "Show the application's version" msgstr "Pakazvaj _ikonu ŭ poli nahadvańnia" #: gajim/application.py:75 #, fuzzy msgid "Show only critical errors" msgstr "Pakazvaj tolki ŭ śpisie _kantaktaŭ" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 #, fuzzy msgid "Use defined profile in configuration directory" msgstr "Redaktar dadatkovych naładaŭ" #: gajim/application.py:105 #, fuzzy msgid "Set configuration directory" msgstr "Kanfihuracyja pakoju" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 #, fuzzy msgid "Show all warnings" msgstr "Pakažy ŭsie niahledžanyja _padzieji" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 msgid "Pops up a window with the next pending event" msgstr "Adčyniaje akno z nastupnym niečytanym paviedamleńniem" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 #, fuzzy msgid "Start a new chat" msgstr "Pačni razmovu" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Abjadnanyja konty" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Transparty" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 msgid "Groupchats" msgstr "Pakoji" #: gajim/roster_window.py:2056 #, fuzzy msgid "Authorization sent" msgstr "Aŭtaryzacyja dasłanaja" #: gajim/roster_window.py:2057 #, fuzzy, python-format msgid "\"%s\" will now see your status." msgstr "Ciapier \"%s\" budzie viedać tvoj status." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Zapyt aŭtaryzacyi dasłany" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "Kali \"%s\" zadavolić tvoj zapyt, ty zmožaš bačyć jahony status." #: gajim/roster_window.py:2095 #, fuzzy msgid "Authorization removed" msgstr "Aŭtaryzacyja anulavanaja" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "Ciapier \"%s\" budzie zaŭsiody bačyć ciabie jak adłučanaha." #: gajim/roster_window.py:2120 #, fuzzy msgid "OpenPGP is not usable" msgstr "Nielha vykarystać OpenPGP na hetym kamputary" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Ty znachodziśsia ŭ adnym ci niekalkich pakojach" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Źmianiŭšy status na niabačny, ty adłučyśsia ad hetych pakojaŭ. Ty sapraŭdy " "chočaš stać niabačnym?" #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "Pašyranyja" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "" #: gajim/roster_window.py:2426 #, fuzzy msgid "Are you sure you want to quit Gajim?" msgstr "Ty sapraŭdy chočaš pakinuć pakoj \"%s\"?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "" #: gajim/roster_window.py:2514 #, fuzzy msgid "You have running file transfers" msgstr "Anuluj pieradaču fajła" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Jość niečytanyja paviedamleńni" #: gajim/roster_window.py:2547 #, fuzzy msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "Paviedamleńni možna budzie pračytać paźniej, kali ŭklučana viadzieńnie " "žurnałaŭ razmoŭ." #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "Musiš pračytać ich pierad vydaleńniem hetaha transpartu." #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Transpart \"%s\" budzie vydaleny" #: gajim/roster_window.py:2829 msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" "Ty bolš nia zmožaš kamunikavać z kantaktami, jakija karystajucca hetym " "transpartam." #: gajim/roster_window.py:2832 msgid "Transports will be removed" msgstr "Transparty buduć vydalenyja" #: gajim/roster_window.py:2837 #, fuzzy, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" "Ty bolš nia zmožaš kamunikavać z kantaktami, jakija karystajucca hetymi " "transpartami:%s" #: gajim/roster_window.py:2891 #, fuzzy msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "Stvarajecca metakantakt. Ty sapraŭdy chočaš praciahnuć?" #: gajim/roster_window.py:2893 msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" #: gajim/roster_window.py:2939 msgid "Rename Contact" msgstr "Źmiani nazvu kantaktu" #: gajim/roster_window.py:2940 #, python-format msgid "Enter a new nickname for contact %s" msgstr "Vyznač novuju mianušku dla kantaktu %s." #: gajim/roster_window.py:2947 msgid "Rename Group" msgstr "Źmiani nazvu hrupy" #: gajim/roster_window.py:2948 #, python-format msgid "Enter a new name for group %s" msgstr "Vyznač novuju nazvu dla hrupy %s" #: gajim/roster_window.py:2993 msgid "Remove Group" msgstr "Vydal hrupu" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "Chočaš vydalić hrupu %s sa śpisu kantaktaŭ?" #: gajim/roster_window.py:2995 #, fuzzy msgid "Also remove all contacts in this group from your roster" msgstr "Vydal taksama ŭsie kantakty z hetaj hrupy sa śpisu kantaktaŭ" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Pryznač kluč OpenPGP" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "Abiary kluč dla hetaha kantaktu" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "Kantakt \"%s\" budzie vydaleny z tvajho śpisu kantaktaŭ" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "" #: gajim/roster_window.py:3448 #, fuzzy msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "Vydaliŭšy hetyja kantakty:%s,\n" "ty taksama anuluješ ichnyja aŭtaryzacyi. U vyniku jany zaŭsiody buduć bačyć " "ciabie adłučanym." #: gajim/roster_window.py:3454 #, fuzzy msgid "Do you want to continue?" msgstr "Što chočaš zrabić?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "Vydaliŭšy hety kantakt, ty zmoŭčana taksama anuluješ jahonuju aŭtaryzacyju. " "U vyniku jon zaŭsiody budzie bačyć ciabie adłučanym." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Ja chaču, kab hety kantakt moh bačyć moj status paśla vydaleńnia" #: gajim/roster_window.py:3465 msgid "Contacts will be removed from your roster" msgstr "Kantakty buduć vydalenyja z tvajho śpisu kantaktaŭ" #: gajim/roster_window.py:3470 #, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "Vydaliŭšy hetyja kantakty:%s,\n" "ty taksama anuluješ ichnyja aŭtaryzacyi. U vyniku jany zaŭsiody buduć bačyć " "ciabie adłučanym." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "Stvarajecca metakantakt. Ty sapraŭdy chočaš praciahnuć?" #: gajim/roster_window.py:3531 #, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Konty niedastupnyja" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "Treba stvaryć kont, kab razmaŭlać ź inšymi kantaktami." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "Tvoj server nie padtrymvaje zachoŭvańnia metakantaktaŭ" #: gajim/roster_window.py:4180 #, fuzzy msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" "Tvoj server nie padtrymvaje zachoŭvańnia metakantaktaŭ. Tamu hetyja źviestki " "nia buduć dastupnyja pry nastupnym złučeńni." #: gajim/roster_window.py:4276 msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "Stvarajecca metakantakt. Ty sapraŭdy chočaš praciahnuć?" #: gajim/roster_window.py:4278 #, fuzzy msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" "Metakantakty jość sposabam hrupavańnia niekalkich kantaktaŭ u adnum radku. " "Zvyčajna hetaja mažlivaść vykarystoŭvajecca, kali adzin čałaviek " "karystajecca niekalkimi kontami Jabber albo niekalkimi kontami z transpartaŭ." #: gajim/roster_window.py:4400 #, fuzzy msgid "Invalid file URI:" msgstr "Niapravilny fajł" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Vyšli _fajł" #: gajim/roster_window.py:4412 #, fuzzy, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "%s choča dasłać tabie fajł:" msgstr[1] "%s choča dasłać tabie fajł:" msgstr[2] "%s choča dasłać tabie fajł:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Dašli %s" #: gajim/roster_window.py:4565 #, fuzzy, python-format msgid "Make %s first contact" msgstr "Zrabi z %s i %s metakantakt" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Zrabi z %s i %s metakantakt" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "Ź_miani paviedamleńnie statusu" #: gajim/roster_window.py:4965 #, fuzzy msgid "Publish Tune" msgstr "_Абнавіць" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "_Абнавіць" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "_Šukaj servisy..." #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 msgid "Send Group M_essage" msgstr "_Dašli hrupavoje paviedamleńnie" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "Usim karystalnikam" #: gajim/roster_window.py:5135 msgid "To all online users" msgstr "Usim dałučanym karystalnikam" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "_Zaprasi" #: gajim/roster_window.py:5299 #, fuzzy msgid "_Manage Contacts" msgstr "Źmiani nazvu kantaktu" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Źmiani _hrupy" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "_Vydal" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "" #: gajim/roster_window.py:5370 #, fuzzy msgid "_Reconnect" msgstr "Kantakt adłučyŭsia" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 #, fuzzy msgid "_Disconnect" msgstr "Kantakt adłučyŭsia" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Žurnał razmoŭ" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Kiraŭnik žurnałaŭ" #: gajim/roster_window.py:5475 msgid "_Join New Group Chat" msgstr "_Dałučysia da pakoju" #: gajim/config.py:359 msgid "Ban List" msgstr "Śpis zablakavanych kantaktaŭ" #: gajim/config.py:360 msgid "Member List" msgstr "Śpis udzielnikaŭ" #: gajim/config.py:360 msgid "Owner List" msgstr "Śpis ułaśnikaŭ" #: gajim/config.py:361 msgid "Administrator List" msgstr "Śpis administrataraŭ" #: gajim/config.py:435 msgid "Reason" msgstr "Pryčyna" #: gajim/config.py:442 msgid "Nick" msgstr "Mianuška" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "Funkcyja" #: gajim/config.py:478 #, fuzzy msgid "Banning…" msgstr "Blakavańnie..." #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Kaho chočaš zablakavać?\n" "\n" #: gajim/config.py:482 #, fuzzy msgid "Adding Member…" msgstr "Dadajecca ŭdzielnik..." #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" "Kaho chočaš zrabić udzielnikam?\n" "\n" #: gajim/config.py:485 #, fuzzy msgid "Adding Owner…" msgstr "Dadajecca ŭłaśnik..." #: gajim/config.py:486 msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "" "Kaho chočaš zrabić ułaśnikam?\n" "\n" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "Dadajecca administratar..." #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" "Kaho chočaš zrabić administrataram?\n" "\n" #: gajim/config.py:490 #, fuzzy msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" "Mahčymyja varyjanty:\n" "1. karystalnik@damen/krynica (tolki hetaja krynica).\n" "2. karystalnik@damen (usiakaja krynica).\n" "3. damen/krynica (tolki hetaja krynica).\n" "4. damen (adpaviadaje damen, jak karystalnik@damen,\n" "damen/krynica ci paddamen)." #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Vydalajecca kont %s" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Šyfravańnie adklučanaje" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Vymahaje parolu" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Uviadzi parol dla kontu %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Zachavaj parol" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Kont \"%s\" dałučany da servera" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Kali ty vydališ jaho, złučeńnie razarviecca." #: gajim/config.py:652 #, fuzzy, python-format msgid "Connection to server %s failed" msgstr "Niemahvyma dałučycca" #: gajim/config.py:653 #, fuzzy msgid "What would you like to do?" msgstr "Što chočaš zrabić?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Vydal kont _tolki dla Gajim" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Fajły ŭ Wav" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "Atrymanaje pieršaje paviedamleńnie" #: gajim/config.py:746 msgid "First Message Received" msgstr "Atrymanaje pieršaje paviedamleńnie" #: gajim/config.py:747 #, fuzzy msgid "Next Message Received Focused" msgstr "Atrymanaje novaje paviedamleńnie" #: gajim/config.py:748 #, fuzzy msgid "Next Message Received Unfocused" msgstr "Atrymanaje novaje paviedamleńnie" #: gajim/config.py:749 msgid "Contact Connected" msgstr "Kantakt dałučyŭsia" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "Kantakt adłučyŭsia" #: gajim/config.py:751 msgid "Message Sent" msgstr "Paviedamleńnie dasłanaje" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "Padśviatleńnie paviedamleńnia ŭ pakoji" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "Novaje paviedamleńnie ŭ pakoji" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "%(owner_or_admin_or_member)s hetaha pakoju" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 msgid "?Group Chat Contact Affiliation:None" msgstr "?Suviaź udzielnikaŭ pakoju:Niama" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 msgid "Member" msgstr "Udzielnik" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 msgid "Administrator" msgstr "Administratar" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 msgid "Owner" msgstr "Ułaśnik" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr "" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr "" #: gajim/tooltips.py:574 #, fuzzy msgid "Connected" msgstr "Złučeńnie" #: gajim/tooltips.py:576 #, fuzzy msgid "Disconnected" msgstr "Kantakt adłučyŭsia" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Ściahni" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Zaciahni na server" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Typ: " #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Pierasłany: " #: gajim/tooltips.py:645 msgid "Status: " msgstr "Status: " #: gajim/tooltips.py:647 #, fuzzy msgid "Description: " msgstr "Apisańnie: %s" #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Zavieršana" #: gajim/tooltips.py:676 msgid "?transfer status:Paused" msgstr "?status pieradačy:Prypyniena" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "Zatrymana" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "Pieradajecca" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "Nie pačata" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "?status pieradačy:Prypyniena" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Achvotna parazmaŭlaju" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Adyjšoŭ" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Zaniaty" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Niedastupny" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Adłučany" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "Ź_miani paviedamleńnie statusu" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "praz kont %s" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Kiruj zakładkami" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "Niama ŭ śpisie kantaktaŭ" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "Pakažy _śpis kantaktaŭ" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Schavaj hetaje menu" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Niemahčyma adčytać modulu idle" #: gajim/dataforms_widget.py:586 #, fuzzy, python-format msgid "Media type not supported: %s" msgstr "Pašyreńnie nie padtrymvajecca" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "Hety servis dahetul nie adkazaŭ na zapyt padrabiaznych źviestak" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "Hety servis nia zmoh adkazać na zapyt padrabiaznych źviestak.\n" "Servis sastareły albo złamany" #: gajim/disco.py:121 msgid "Others" msgstr "Inšyja" #: gajim/disco.py:125 msgid "Conference" msgstr "Kanferencyja" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "Nia možaš prahladać najaŭnyja servisy, nie dałučyŭšysia da servera" #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "Prahlad servisaŭ dla kontu %s" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Prahlad servisaŭ" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "Niemahčyma znajści servis" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "Niama servisu z akreślenym adrasam, albo jon nie adkazvaje. Pravier adras i " "pasprabuj znoŭ." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "Niemahčyma ahladać hety servis" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "Taki servis nia ŭtrymlivaje elementaŭ dla ahladańnia." #: gajim/disco.py:726 gajim/disco.py:736 #, fuzzy msgid "Invalid Server Name" msgstr "Niapravilnaje imia karystalnika" #: gajim/disco.py:794 #, fuzzy, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "Prahlad %s dla kontu %s" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Prahladaj" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "Hety servis nia ŭtrymlivaje elementaŭ dla prahladu." #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "_Vykanaj zahad..." #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "_Zarehistrujsia" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "_Dałučysia" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "Šukaj" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Źmianić" #: gajim/disco.py:1450 #, fuzzy, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "Skanavańnie %d / %d.." #: gajim/disco.py:1649 msgid "Users" msgstr "Karystalniki" #: gajim/disco.py:1657 msgid "Description" msgstr "Apisańnie" #: gajim/disco.py:1665 msgid "Id" msgstr "Identyfikatar" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 #, fuzzy msgid "_Bookmark" msgstr "_Stvary zakładku dla hetaja pakoju" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Zakładka ŭžo dadana" #: gajim/disco.py:1722 #, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "Pakoj \"%s\" užo jość u tvajich zakładkach." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Zakładka paśpiachova dadanaja" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "" "Možaš kiravać svajimi zakładkami praz menu \"Dziejańni\" śpisu kantaktaŭ." #: gajim/disco.py:1929 msgid "Subscribed" msgstr "Aŭtaryzavany" #: gajim/disco.py:1938 #, fuzzy msgid "Node" msgstr "Nijaki" #: gajim/disco.py:2005 msgid "New post" msgstr "Novy zapis" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "_Aŭtaryzuj" #: gajim/disco.py:2017 msgid "_Unsubscribe" msgstr "_Anuluj aŭtaryzacyju" #: gajim/conversation_textview.py:320 #, fuzzy msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" "Tekst pad hetaj rysaj addzialaje toj tekst, jaki ty jašče nia bačyŭ/nia " "bačyła" #: gajim/conversation_textview.py:541 #, fuzzy msgid "_Quote" msgstr "_Skonč pracu" #: gajim/conversation_textview.py:549 #, python-format msgid "_Actions for \"%s\"" msgstr "_Dziejańni dla \"%s\"" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Pračytać artykuł u _Wikipedii" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Šukaj u _słoŭniku" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "U adrasie słoŭnika nie staje \"%s\", i heta nia Wiktionary" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "U adrasie dla web-pošuku nie staje \"%s\"" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "_Šukaj u Web" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "Adčyni jak _spasyłku" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "Niapravilny JID" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, fuzzy, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "Učora" msgstr[1] "Učora" msgstr[2] "Učora" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Nie pačata" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Tema: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Novaje pryvatnaje paviedamleńnie" #: gajim/message_window.py:243 #, fuzzy msgid "You are going to close several tabs" msgstr "Niama złučeńnia z serveram" #: gajim/message_window.py:244 #, fuzzy msgid "Do you really want to close them all?" msgstr "Sapraŭdy chočaš vydalić zaznačanaje paviedamleńnie?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Pakoji" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "Pryvatnyja razmovy" #: gajim/message_window.py:530 msgid "Messages" msgstr "Paviedamleńni" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 msgid "Unable to join group chat" msgstr "Niemahčyma dałučycca da pakoju" #: gajim/gui_interface.py:170 #, fuzzy, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "Hetaja mianuška vykarystoŭvajecca ci zarehistravanaja na inšuju asobu.\n" "Kali łaska, vyznač inšuju mianušku nižej:" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Prymaješ hety zapyt?" #: gajim/gui_interface.py:194 #, fuzzy, python-format msgid "Do you accept this request on account %s?" msgstr "Prymaješ hety zapyt?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "Aŭtaryzacyja HTTP (%s) dla %s (id: %s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 msgid "Connection Failed" msgstr "Niemahvyma dałučycca" #: gajim/gui_interface.py:327 #, fuzzy, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "Treba ŭvieści parol, kab dałučycca da pakoju." #: gajim/gui_interface.py:342 #, fuzzy, python-format msgid "%s is full" msgstr "Huki" #: gajim/gui_interface.py:351 #, fuzzy, python-format msgid "You are banned from group chat %s." msgstr "Ty zablakavany ŭ hetym pakoji." #: gajim/gui_interface.py:358 #, fuzzy, python-format msgid "Remote server %s does not exist." msgstr "Takoha pakoju niama." #: gajim/gui_interface.py:362 #, fuzzy, python-format msgid "Group chat %s does not exist." msgstr "Takoha pakoju niama." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "Stvareńnie pakojaŭ abmiežavanaje." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Niemahčyma dałučycca da pakoju" #: gajim/gui_interface.py:368 #, fuzzy, python-format msgid "You must use your registered nickname in %s." msgstr "Treba karystacca zarehistravanaj na siabie mianuškaj." #: gajim/gui_interface.py:373 #, fuzzy, python-format msgid "You are not in the members list in groupchat %s." msgstr "Ciabie niama ŭ śpisie ŭdzielnikaŭ." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, fuzzy, python-format msgid "Error %(code)s: %(msg)s" msgstr "%(nickname)s: %(message)s" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, fuzzy, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "pamyłka dasyłańnia %s ( %s )" #: gajim/gui_interface.py:503 gajim/notify.py:194 #, fuzzy msgid "Subscription request" msgstr "Zapyt aŭtaryzacyi" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "Naziralniki" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Aŭtaryzacyja pryniataja" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "" "Kantakt \"%s\" aŭtaryzavaŭ ciabie, i ciapier ty možaš bačyć jaho status." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Kantakt \"%s\" anulavaŭ tvaju aŭtaryzacyju" #: gajim/gui_interface.py:539 msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" #: gajim/gui_interface.py:560 gajim/notify.py:194 #, fuzzy msgid "Unsubscribed" msgstr "_Anuluj aŭtaryzacyju" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, fuzzy, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Ty nie dałučyŭsia da pakoju." #: gajim/gui_interface.py:658 msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "Dałučany biez kluča OpenPGP." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Niapravilny parol" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Niapravilny parol" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "Musiš vyznačyć parol" #: gajim/gui_interface.py:683 #, fuzzy, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Vyznač parol GPG dla kontu %s." #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Abiary svoj kluč OpenPGP" #: gajim/gui_interface.py:706 msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Pamyłka pieradačy fajłu" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "%s choča dasłać tabie fajł." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Zapyt na pieradaču fajłu" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Pieradača fajłu skončana" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Pieradača fajłu spyniena" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Pieradačy fajłaŭ" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Pieradača fajłu %(filename)s ad %(name)s spyniena." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Pieradača fajłu %(filename)s ad %(name)s spyniena." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Pieradača fajłu %(filename)s ad %(name)s spyniena." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Fajł %(filename)s paśpiachova dasłany da %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Pieradača fajłu %(filename)s da %(name)s spynienaja." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Pieradača fajłu %(filename)s da %(name)s spynienaja." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "Kanflikt imionaŭ karystalnikaŭ" #: gajim/gui_interface.py:1178 msgid "Please type a new username for your local account" msgstr "Kali łaska, akreśli novaje imia karystalnika dla lakalnaha kontu" #: gajim/gui_interface.py:1201 #, fuzzy msgid "Resource Conflict" msgstr "Kanflikt imionaŭ karystalnikaŭ" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "" #: gajim/gui_interface.py:1259 #, fuzzy, python-format msgid "%s wants to start a voice chat." msgstr "%s choča dasłać tabie fajł." #: gajim/gui_interface.py:1261 #, fuzzy msgid "Voice Chat Request" msgstr "Zapyt na pieradaču fajłu" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 #, fuzzy msgid "Certificate Already in File" msgstr "Kantakt užo jość u śpisie kantaktaŭ" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" #: gajim/gui_interface.py:1351 #, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "" #: gajim/gui_interface.py:1354 #, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "" #: gajim/gui_interface.py:1362 #, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "" #: gajim/gui_interface.py:1380 #, fuzzy, python-format msgid "SSL Certificate Verification for %s" msgstr "Dadajecca admysłovaje nahadvańnie dla %s" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 #, fuzzy msgid "Insecure connection" msgstr "Złučeńnie" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "Stvarajecca metakantakt. Ty sapraŭdy chočaš praciahnuć?" #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "" "Niemahčyma ŭdzielničać u hrupavoj razmovie, nie dałučyŭšysia da servera." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Heta nie pakoj" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "Heta nie pakoj" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 msgid "You cannot join a group chat while you are invisible" msgstr "Niemahčyma dałučycca da pakoju, kali ty niabačny" #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Niemahčyma zapisać tvaje nałady i opcyi" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Musiš vyznačyć parol" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "Vyznač parol GPG dla kontu %s." #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "Vybar kluča OpenPGP" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "Ty dałučyśsia da %s biaz OpenPGP." #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "Niapravilny parol" #: gajim/gui_interface.py:2853 #, fuzzy msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "Kali łaska, vyznač parol GPG znoŭ albo naciśni knopku \"Anuluj\"." #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "Uvod paviedamleńnia" #: gajim/atom_window.py:123 #, fuzzy, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "Atrymaŭ novy zapis:" msgstr[1] "Atrymaŭ novy zapis:" msgstr[2] "Atrymaŭ novy zapis:" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "Atrymaŭ novy zapis:" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "Zahady ad-hoc - Gajim" #: gajim/adhoc_commands.py:326 #, fuzzy msgid "Cancel confirmation" msgstr "Źviestki ab kantakcie" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "" #: gajim/adhoc_commands.py:422 #, fuzzy, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "Zahady ad-hoc - Gajim" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Kantakt dałučyŭsia" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Kantakt adłučyŭsia" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Novaje paviedamleńnie" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Novaje asobnaje paviedamleńnie" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Novaje pryvatnaje paviedamleńnie" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 msgid "Contact Changed Status" msgstr "Kantakt źmianiŭ status" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenPGP: " #: gajim/notify.py:270 msgid "New E-mail" msgstr "Novy list" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "" "Niemahčyma ŭdzielničać u hrupavoj razmovie, nie dałučyŭšysia da servera." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 msgid "Invalid JID" msgstr "Niapravilny JID" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, fuzzy, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "Niemahčyma dasyłać pustyja fajły" #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "Niepračytanyja paviedamleńni" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "Pračytaj usie novyja paviedamleńni pierad vydaleńniem kontu." #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "Prahrama dałučanaja da servera" #: gajim/dialog_messages.py:53 #, fuzzy msgid "To disable the account, you must be disconnected." msgstr "Kab źmianić nazvu kontu, treba pieradałučycca." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Niapravilny zapis" #: gajim/dialog_messages.py:58 #, fuzzy msgid "The form is not filled correctly." msgstr "JID pakoju ŭtrymlivaje niedazvolenyja znaki." #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Niabačny" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "Złučeńnie niemahčymaje" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "Ty nia možaš dasłać paviedamleńnie, pakul nia złučyśsia z serveram." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "Klijent kamunikacyi dla Jabber" #: gajim/dialog_messages.py:73 msgid "The JID you entered is already in the list. Choose another one." msgstr "" #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "Niapravilny adkaz" #: gajim/dialog_messages.py:78 #, fuzzy, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "Transpart %s niapravilna adkazaŭ na zapyt rehistracyi: %s" #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Skarystaj admysłovy host/port" #: gajim/dialog_messages.py:84 #, fuzzy, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Skarystaj admysłovy host/port" #: gajim/dialog_messages.py:88 msgid "Error while removing privacy list" msgstr "Pamyłka vydaleńnia śpisu pryvatnaści" #: gajim/dialog_messages.py:89 #, fuzzy, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" "Śpis pryvatnaści %s nia vydaleny. Jon vykarystoŭvajecca adnoj z dałučanych " "krynic. Adklučy jaje i paŭtary znoŭ." #: gajim/dialog_messages.py:95 #, fuzzy msgid "Invisibility not supported" msgstr "Pašyreńnie nie padtrymvajecca" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "" #: gajim/dialog_messages.py:100 #, fuzzy msgid "Unregister failed" msgstr "Niemahvyma dałučycca" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "" #: gajim/dialog_messages.py:105 #, fuzzy msgid "Registration succeeded" msgstr "Zarehistrujsia na %s" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 #, fuzzy msgid "Registration failed" msgstr "Niemahvyma dałučycca" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Niemahčyma dałučycca da pakoju" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, fuzzy, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "Tekst pamyłki: %s" #: gajim/dialog_messages.py:126 msgid "Wrong host" msgstr "Niapravilny host" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "Pamyłka Avahi" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" "%s\n" "Lakalnyja paviedamleńni mohuć pracavać pamyłkova." #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 #, fuzzy msgid "Could not request upload slot" msgstr "Niemahčyma ŭruchomić lakalny servis" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 #, fuzzy msgid "Could not open file" msgstr "Niemahčyma adčytać vyjavu" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 msgid "Server returned unsecure transport (HTTP)" msgstr "" #: gajim/dialog_messages.py:161 #, fuzzy msgid "Could not upload file" msgstr "Niemahčyma adčytać vyjavu" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 #, fuzzy msgid "Encryption Error" msgstr "Šyfravańnie ŭklučanaje" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "Złučeńnie niemahčymaje" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "Pamyłka publikacyi vCard" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "D-Busu niama na hetym kamputary, albo nie staje modula Python" #: gajim/gajim_remote.py:77 msgid "Shows a help on specific command" msgstr "Pakazvaje daviedku pa akreślenym zahadzie" #: gajim/gajim_remote.py:80 msgid "command" msgstr "zahad" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "pakažy daviedku pa zahadzie" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "Pakazvaje śpis usich kantaktaŭ sa śpisu kantaktaŭ. Źviestki ab kožnym " "kantakcie źjaŭlajucca na novym radku" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "kont" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "pakažy kantakty akreślenaha kontu" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "Pakazvaje śpis zarehistravanych kontaŭ" #: gajim/gajim_remote.py:97 #, fuzzy msgid "Changes the status of account(s)" msgstr "Źmianiaje status kontu albo kontaŭ" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "status" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "adno z: offline, online, chat, away, xa, dnd, invisible " #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "paviedamleńnie" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "paviedamlennie statusu" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "źmiani status kontu \"kont\". Kali nie akreślena, pasprabuj źmianić statusy " "dla ŭsich kontaŭ, dla jakich vystaŭlenaja opcyja \"Synchranizuj z hlabalnym " "statusam\"" #: gajim/gajim_remote.py:108 #, fuzzy msgid "Changes the priority of account(s)" msgstr "Źmianiaje status kontu albo kontaŭ" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "Pryjary_tet:" #: gajim/gajim_remote.py:110 #, fuzzy msgid "priority you want to give to the account" msgstr "Ja chaču za_rehistravać novy kont" #: gajim/gajim_remote.py:112 #, fuzzy msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "źmiani status kontu \"kont\". Kali nie akreślena, pasprabuj źmianić statusy " "dla ŭsich kontaŭ, dla jakich vystaŭlenaja opcyja \"Synchranizuj z hlabalnym " "statusam\"" #: gajim/gajim_remote.py:118 msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Dasyłaje novaje paviedamleńnie kantaktu sa śpisu kantaktaŭ. Kluč OpenPGP i " "kont nie abaviazkovyja dla akreśleńnia. Kali chočaš akreślić tolki 'kont', " "biez 'kluča OpenPGP', tady prosta akreśli 'kluč OpenPGP' jak ''." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID kantaktu, jaki atrymaje paviedamleńnie" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "źmiest paviedamleńnia" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "" "Kali akreślena, paviedamleńnie budzie zašyfravana hetym publičnym klučom" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "Kali akreślena, paviedamleńnie budzie dasłanaje z hetaha kontu" #: gajim/gajim_remote.py:131 #, fuzzy msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Dasyłaje novaje paviedamleńnie kantaktu sa śpisu kantaktaŭ. Kluč OpenPGP i " "kont nie abaviazkovyja dla akreśleńnia. Kali chočaš akreślić tolki 'kont', " "biez 'kluča OpenPGP', tady prosta akreśli 'kluč OpenPGP' jak ''." #: gajim/gajim_remote.py:136 msgid "subject" msgstr "tema" #: gajim/gajim_remote.py:136 msgid "message subject" msgstr "tema paviedamleńnia" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "" #: gajim/gajim_remote.py:147 #, fuzzy msgid "JID of the room that will receive the message" msgstr "JID kantaktu, jaki atrymaje paviedamleńnie" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Atrymvaje padrabiaznyja źviestki ab kantakcie" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "JID kantaktu" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "Atrymvaje padrabiaznyja źviestki ab kantakcie" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "Nazva kontu" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Dasyłaje kantaktu fajł" #: gajim/gajim_remote.py:168 msgid "file" msgstr "fajł" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Ściežka da fajłu" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "Kali akreślena, fajł budzie dasłany z hetaha kontu" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Pakazvaje ŭsie nałady i ichnyja vartaści" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "Akreślivaje dla 'kluča' 'vartaść'" #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "kluč=vartaść" #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "'kluč' jość nazvaj nałady, 'vartaść' jość vartaściu hetaj nałady" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "Vydalaje naładu" #: gajim/gajim_remote.py:188 msgid "key" msgstr "kluč" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "nazva vydalenaj nałady" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "Zapisvaje dziejnyja nałady Gajima ŭ fajł .config" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Vydalaje kantakt sa śpisu" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "Kali akreślena, kantakt biarecca sa śpisu kantaktaŭ hetaha kontu" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "Viartaje dziejny status (hlabalny, kali nie akreśleny kont)" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" "Viartaje dziejnaje paviedamleńnie statusu (hlabalnaha, kali nie akreśleny " "kont)" #: gajim/gajim_remote.py:221 msgid "Returns number of unread messages" msgstr "Viartaje kolkaść niečytanych paviedamleńniaŭ" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "Dasyłaje svoj XML" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "XML dla dasyłańnia" #: gajim/gajim_remote.py:229 #, fuzzy msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" "Kont, na jaki budzie dasłany XML; kali kont nie akreśleny, XML budzie " "dasłany na ŭsie konty" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Źmiani status" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "Mianuška nia znojdziena: %s" #: gajim/gajim_remote.py:238 #, fuzzy msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" "Kont, na jaki budzie dasłany XML; kali kont nie akreśleny, XML budzie " "dasłany na ŭsie konty" #: gajim/gajim_remote.py:245 #, fuzzy msgid "Check if Gajim is running" msgstr "Kali łaska, pravier, ci pracuje avahi-daemon." #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "Nie staje arhumenta \"contact_jid\"" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "'%s' niama ŭ tvajim śpisie kantaktaŭ.\n" "Kali łaska, akreśli kont dla dasyłańnia paviedamleńnia." #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "Nivodny kont nia dziejny" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "" #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Arhumenty:" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "%s nia znojdzieny" #: gajim/gajim_remote.py:383 #, fuzzy, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Užyvańnie: %s zahad [arhumenty]\n" "Zahadam moža być adzin z nastupnych vyrazaŭ:\n" #: gajim/gajim_remote.py:453 #, fuzzy, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Nadta šmat arhumentaŭ. \n" "Vykanaj \"%s help %s\" dla padrabiaźniejšych źviestak" #: gajim/gajim_remote.py:458 #, fuzzy, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Arhument \"%s\" nie akreśleny. \n" "Vykanaj \"%s help %s\" dla padrabiaźniejšych źviestak" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "dvanaccataja" #: gajim/common/fuzzyclock.py:36 msgid "one" msgstr "pieršaja" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "druhaja" #: gajim/common/fuzzyclock.py:36 msgid "three" msgstr "treciaja" #: gajim/common/fuzzyclock.py:36 msgid "four" msgstr "čaćviortaja" #: gajim/common/fuzzyclock.py:37 msgid "five" msgstr "piataja" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "šostaja" #: gajim/common/fuzzyclock.py:37 msgid "seven" msgstr "siomaja" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "vośmaja" #: gajim/common/fuzzyclock.py:37 msgid "nine" msgstr "dziaviataja" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "dziasiataja" #: gajim/common/fuzzyclock.py:38 msgid "eleven" msgstr "adzinaccataja" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "%(0)s hadzinaŭ" #: gajim/common/fuzzyclock.py:46 #, python-format msgid "five past %(0)s" msgstr "piać chvilinaŭ na %(0)s" #: gajim/common/fuzzyclock.py:47 #, python-format msgid "ten past %(0)s" msgstr "dziesiać chvilinaŭ na %(0)s" #: gajim/common/fuzzyclock.py:48 #, python-format msgid "quarter past %(0)s" msgstr "čverć na %(0)s" #: gajim/common/fuzzyclock.py:49 #, python-format msgid "twenty past %(0)s" msgstr "dvaccać chvilinaŭ na %(0)s" #: gajim/common/fuzzyclock.py:50 #, python-format msgid "twenty five past %(0)s" msgstr "dvaccać piać chvilinaŭ na %(0)s" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "pałova na %(0)s" #: gajim/common/fuzzyclock.py:52 #, python-format msgid "twenty five to %(1)s" msgstr "biez dvaccaci piaci chvilinaŭ %(1)s" #: gajim/common/fuzzyclock.py:53 #, python-format msgid "twenty to %(1)s" msgstr "biez dvaccaci chvilinaŭ %(1)s" #: gajim/common/fuzzyclock.py:54 #, python-format msgid "quarter to %(1)s" msgstr "biaz čverći %(1)s" #: gajim/common/fuzzyclock.py:55 #, fuzzy, python-format msgid "ten to %(1)s" msgstr "bieź dziesiaci chvilinaŭ $s" #: gajim/common/fuzzyclock.py:56 #, python-format msgid "five to %(1)s" msgstr "bieź piaci chvilinaŭ %(1)s" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "%(1)s hadzinaŭ" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "Noč" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "Śvitanak" #: gajim/common/fuzzyclock.py:63 msgid "Morning" msgstr "Ranica" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "Amal poŭdzień" #: gajim/common/fuzzyclock.py:65 msgid "Noon" msgstr "Poŭdzień" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "Papoŭdni" #: gajim/common/fuzzyclock.py:67 msgid "Evening" msgstr "Viečar" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "Poźni viečar" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "Pačatak tydnia" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "Siaredzina tydnia" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "Kaniec tydnia" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "Vychodny!" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, python-format msgid "%s is a directory but should be a file" msgstr "%s jość kataloham, ale musiŭ być fajł" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Apisańnie: %s" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 #, fuzzy msgid "Room has been destroyed" msgstr "Aŭtaryzacyja anulavanaja" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "" #: gajim/common/connection_handlers_events.py:598 #, python-format msgid "Unknown SSL error: %d" msgstr "" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Novaje paviedamleńnie ad %(nickname)s" msgstr[1] "Novaje paviedamleńnie ad %(nickname)s" msgstr[2] "Novaje paviedamleńnie ad %(nickname)s" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s źmianiŭ status" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s dałučyŭsia" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "%(nickname)s adłučyŭsia" #: gajim/common/contacts.py:427 msgid "Not in roster" msgstr "Niama ŭ śpisie kantaktaŭ" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "" #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "Čas u chvilinach, paśla katoraha tvoj status źmienicca na \"Adyjšoŭ\"." #: gajim/common/config.py:87 #, fuzzy msgid "$S (Away as a result of being idle more than $T min)" msgstr "Status \"Adyjšoŭ\" jak vynik biaździejnaści prahramy" #: gajim/common/config.py:87 msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "" "Čas u chvilinach, paśla katoraha tvoj status źmienicca na \"Niedastupny\"." #: gajim/common/config.py:90 #, fuzzy msgid "$S (Not available as a result of being idle more than $T min)" msgstr "Status \"Niedastupny\" jak vynik biaździejnaści prahramy" #: gajim/common/config.py:90 msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" #: gajim/common/config.py:93 msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "_Pakazvaj padzieju ŭ śpisie kantaktaŭ" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "_Pakazvaj padzieju ŭ śpisie kantaktaŭ" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "_Pakazvaj padzieju ŭ śpisie kantaktaŭ" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Zapyt na pieradaču fajłu" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Pieradača fajłu anulavana" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "Pakažy nahadvańnie ŭ vypłyŭnym aknie pa zakančeńni pieradačy fajła" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "Zaprašeńnie ŭ pakoj" #: gajim/common/config.py:106 #, fuzzy msgid "Background color of status changed notification" msgstr "Fonavy koler kantaktaŭ, kali jany tolki dałučylisia." #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "Śpis (padzielenych prabiełami) zhornutych radkoŭ (kontaŭ i hrupaŭ)." #: gajim/common/config.py:109 #, fuzzy msgid "default" msgstr "Zmoŭčany" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "Mova pravierki pravapisu" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" "'always' - pakazvaj čas dla kožnaha paviedamleńnia.\n" "'sometimes' - pakazvaj čas praz kolkaść chvilinaŭ, akreślenuju ŭ opcyi " "print_ichat_every_foo_minutes.\n" "'never' - nie pakazvaj času." #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" "Pakazvaj niedakładny čas. Vartaść niedakładnaści ad 1 da 4 albo 0, kab " "adklučyć niedakładnaść. 1 akreślivaje samy dakładny čas, 4 akreślivaje samy " "niedakładny. Zadziejničana, kali opcyja print_time maje vartaść 'sometimes'." #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "Traktuj pary znakaŭ * / _ jak znaki farmatavańnia." #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "Kali maje vartaść True, nie vydalaj */_ . Takim čynam *abc* budzie tłustym, " "ale i znaki * * nia vydalacca." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" "Užyvaje restrukturavanuju movu tekstavaj raźmietki dla dasyłańnia HTML, a " "taksama farmatavańnie ASCII, kali zadziejničana adpaviednaja opcyja. Hladzi " "syntaksyčnyja praviły pa adrasie: http://docutils.sourceforge.net/docs/ref/" "rst/restructuredtext.html (Kali chočaš karystacca hetaj mahčymaściu, " "zainstaluj docutils)" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" "Znak, jaki dadajecca paśla mianuški pry dapaŭnieńni (klavišaj TAB) u pakoji." #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" "Znak, jaki dadajecca paśla mianuški, kali akreślenaja mianuška ŭžyvajecca ŭ " "movie inšaha ŭdzielnika pakoju." #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" "Hetaja opcyja dazvalaje tabie akreślić farmat miecin času ŭ razmovie. " "Naprykład, \"[%H:%M] \" akreślaje, što treba pakazvać \"[hadziny:chviliny] " "\". Hladzi padrabiaznyja źviestki ŭ dakumentacyi dla Pythonu pa funkcyi " "strftime: http://docs.python.org/lib/module-time.html" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "Znaki, što pakazvajucca ŭ razmovie pierad mianuškaj" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "Znaki, što pakazvajucca ŭ razmovie paśla mianuški" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Dadać * i [n] u zahałovak śpisu kantaktaŭ?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Kolki radkoŭ z apošniaj razmovy zapaminać i pakazvać u znoŭ adčynienym aknie." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" #: gajim/common/config.py:177 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" "Dasyłaj paviedamleńnie praz Ctrl+Enter, a Enteram stvaraj novy radok " "(zmoŭčanyja pavodziny Mirabilis ICQ)." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Kolki radkoŭ zachoŭvać dla Ctrl+KeyUP." #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Albo specyjalny adrasm jaki ŭtrymlivaje %s, dzie %s jość słovam/vyrazam, " "albo radok 'WIKTIONARY', što aznačaje vykarystańnie Wiktionary." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "" "Kali hetaja opcyja ŭklučanaja, Gajimam možna kiravać praz gajim-remote." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" "Dasyłaj nahadvańni ab stanie razmovy. Musić być adnoj z nastupnych " "vartaściaŭ: all, composing_only, disabled." #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" "Pakazanyja nahadvańni stanu razmovy ŭ voknach. Musić być adnoj z nastupnych " "vartaściaŭ: all, composing_only, disabled." #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" "Kali čas pakazvajecca nie dla kožnaha paviedamleńnia " "(print_time==sometimes), pakazvaj jaho kožnyja x chvilinaŭ." #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Pytajsia paćvierdžańnia pierad začynieńniem kartki/akna razmovy." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" "Zaŭsiody pytajsia paćvierdžańnia pierad začynieńniem kartki/akna razmovy z " "hetaha śpisu padzielenych prabiełami nazvaŭ pakojaŭ." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" "Nikoli nie pytajsia paćvierdžańnia pierad začynieńniem kartki/akna razmovy z " "hetaha śpisu padzielenych prabiełami nazvaŭ pakojaŭ." #: gajim/common/config.py:196 msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" #: gajim/common/config.py:199 #, fuzzy msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" "Nadpisvaje host, jaki vysyłajecca dla Pieradačy fajłaŭ, u vypadku tranślacyi " "adrasoŭ/pieranakiravańnia partoŭ." #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "Standart IEC vyznačaje, što KiB = 1024 bajtaŭ, KB = 1000 bajtaŭ." #: gajim/common/config.py:202 #, fuzzy msgid "Notify of events in the notification area." msgstr "Nahadvaj ab padziejach ikonaj pola nahadvańnia." #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Pakazvać kartku, kali dziejnaja tolki adna razmova?" #: gajim/common/config.py:210 msgid "Show tabbed notebook border in chat windows?" msgstr "Pakazvać padzieł kartak u voknach razmovy?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Pakazvać knopki začynieńnia na kartkach?" #: gajim/common/config.py:224 msgid "Preview new messages in notification popup?" msgstr "" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" "Śpis padzielenych kropkaj z koskaj słovaŭ, jakija treba padśviatlać u " "pakojach." #: gajim/common/config.py:228 #, fuzzy msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" "Kali opcyja maje vartaść True, Gajim zaviaršaje vykanańnie pa nacisku knopki " "X Kiraŭnika voknaŭ. Hetaja nałada dziejničaje tolki ź dziejnaj ikonaj pola " "nahadvańnia." #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 #, fuzzy msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" "Kali opcyja maje vartaść True, Gajim pakazvaje ikonu na kožnaj kartcy ź " "niečytanymi paviedamleńniami. U zaležnaści ad matyvu, hetaja ikona moža być " "animavanaj." #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" "Kali opcyja maje vartaść True, Gajim pakazvaje status kožnaha kantaktu, kali " "jon nie pusty, dla kožnaha elementu śpisu kantaktaŭ." #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "" #: gajim/common/config.py:238 #, fuzzy msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" "Kali opcyja maje vartaść False, Gajim nie budzie pakazvać radki stanu, kali " "surazmoŭca źmianiaje status i/ci paviedamleńnie statusu." #: gajim/common/config.py:239 #, fuzzy msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" "moža mieć vartaść: \"none\", \"all\" albo \"in_and_out\". Kali opcyja maje " "vartaść \"none\", Gajim nia budzie pakazvać paviedamleńni statusu ŭ " "pakojach, kali surazmoŭca źmianiaje status. Kali opcyja maje vartaść \"all" "\", Gajim budzie pakazvać usie takija paviedamleńni. Kali opcyja maje " "vartaść \"in_and_out\", Gajim budzie pakazvać tolki paviedamleńni ab " "dałučeńni/adłučeńni surazmoŭcaŭ." #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 #, fuzzy msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" "Kali opcyja maje vartaść True, adnoŭlenyja paviedamleńni buduć pakazvacca " "mienšym za zmoŭčany šryftam." #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "Nie pakazvaj avatara dla transpartu." #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "Nie pakazvaj śpis kantaktaŭ na paneli zadańniaŭ." #: gajim/common/config.py:245 #, fuzzy msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" "Kali opcyja maje vartaść True i kali instalavanyja GTK+ i PyGTK versii 2.8 " "albo paźniejšaj, mirhaj aknom (zmoŭčanyja pavodziny akna ŭ bolšaści " "Kiraŭnikoŭ voknaŭ) pry najaŭnaści niečytanych paviedamleńniaŭ." #: gajim/common/config.py:249 #, fuzzy msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" "Kiruje aknom, u jakim pakazvajucca novyja paviedamleńni.\n" "'always' - Usie paviedamleńni pakazvajucca ŭ adnym aknie.\n" "'never' - Usie paviedamleńni pakazvajucca ŭ asobnych voknach.\n" "'peracct' - Paviedamleńnia z adnaho kontu pakazvajucca ŭ adnym aknie.\n" "'pertype' - Paviedamleńni adnaho typu (naprykład, pryvatnyja albo hrupavyja) " "pakazvajucca ŭ asobnych voknach. Zvažaj, što kab ubačyć źmieny, treba " "ŭruchomić Gajima nanoŭ." #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "" "Kali opcyja maje vartaść False, ty bolš nia ŭbačyš avatara ŭ aknie razmovy." #: gajim/common/config.py:252 #, fuzzy msgid "If true, pressing the escape key closes a tab/window." msgstr "" "Kali opcyja maje vartaść True, nacisk klavišy Escape začyniaje kartku/akno." #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "Chavaje baner u aknie pakoju" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "Chavaje baner u aknie pryvatnaj razmovy" #: gajim/common/config.py:255 msgid "Hides the group chat occupants list in group chat window." msgstr "Chavaje śpis naviednikaŭ pakoju." #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" "U pakoji pakazvaj mianušku pierad paviedamleńniem, tolki kali jaho napisała " "nia taja asoba, što napisała papiaredniaje paviedamleńnie." #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "Vodstup pry šmatmetavym pryznačeńni paviedamleńnia." #: gajim/common/config.py:258 #, fuzzy msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "Śpis koleraŭ dla farbavańnia mianušak u pakojach." #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "" "Ctrl-Tab pierachodzić na nastupnuju kartku, kali na dziejnaj niama " "niečytanych paviedamleńniaŭ." #: gajim/common/config.py:260 #, fuzzy msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" "Ci treba pakazvać akno paćvierdžańnia pry stvareńni metakantaktu? Pusty " "radok aznačaje, što hetaje akno nikoli nia budzie pakazvacca." #: gajim/common/config.py:261 #, fuzzy msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" "Ci treba pakazvać akno paćvierdžańnia pry stvareńni metakantaktu? Pusty " "radok aznačaje, što hetaje akno nikoli nia budzie pakazvacca." #: gajim/common/config.py:262 #, fuzzy msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" "Ci treba pakazvać akno paćvierdžańnia pry stvareńni metakantaktu? Pusty " "radok aznačaje, što hetaje akno nikoli nia budzie pakazvacca." #: gajim/common/config.py:263 #, fuzzy msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" "Kali opcyja maje vartaść True, ty zmožaš akreślić admoŭny pryjarytet ŭ aknie " "madyfikacyi kontu. UHAVA: kali ty dałučajeśsia z admoŭnym pryjarytetam, to " "nia budzieš atrymvać paviedamleńniaŭ z servera." #: gajim/common/config.py:264 #, fuzzy msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" "Kali opcyja maje vartaść True, Gajim budzie pakazvać kolkaść dałučanych " "kantaktaŭ i ahulnuju kolkaść kantaktaŭ u radkach kontaŭ i hrupaŭ." #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" "Moža być pustym albo mieć vartaść 'chat' ci 'normal'. Kali vartaść nie " "pustaja, traktuj usie ŭvachodnyja paviedamleńni jak paviedamleńni hetaha typu" #: gajim/common/config.py:266 msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" #: gajim/common/config.py:269 msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "" #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" #: gajim/common/config.py:272 msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 #, fuzzy msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" "Kali opcyja maje vartaść True, Gajim budzie zachoŭvać paroli z dapamohaj " "Kiraŭnika parolaŭ GNOME (kali jość mahčymaść)." #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" "Pryjarytet budzie aŭtamatyčna źmianiacca zhodna tvajmu statusu. Pryjarytety " "akreślivajucca ŭ opcyjach autopriority_*." #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "" #: gajim/common/config.py:325 msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" #: gajim/common/config.py:326 #, fuzzy msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "" "Kali opcyja maje vartaść False, ty bolš nia ŭbačyš avatara ŭ aknie razmovy." #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "" #: gajim/common/config.py:337 msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "" #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "" #: gajim/common/config.py:354 msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "Abychod dla Jabberd2" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" "Kali hetaja opcyja ŭklučanaja, Gajim budzie pieradavać fajły z akreślenym " "adrasam IP i proxy-serveram z opcyi file_transfer_proxies." #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "" "Kali ŭklučanaja hetaja opcyja, Gajim budzie dałučacca da hetaha pakoju pry " "starcie" #: gajim/common/config.py:386 #, fuzzy msgid "Allow Gajim to send your local time." msgstr "%s choča dasłać tabie fajł." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Kali łaska, zapoŭni źviestki ab kantakcie, jaki chočaš dadać" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Užyvaj aŭtaryzacyju" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Užyvaj aŭtaryzacyju" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Užyvaj aŭtaryzacyju" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 #, fuzzy msgid "Language for which misspelled words will be checked" msgstr "Mova, dla jakoj treba praviarać pravapis" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" #: gajim/common/config.py:442 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "Splu" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Chutka viarnusia" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Viarnusia praz paru chvilinaŭ." #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "Jem" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "Ja jem, možaš pakinuć mnie paviedamleńnie." #: gajim/common/config.py:454 msgid "Movie" msgstr "Film" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "Hladžu film." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "Pracuju" #: gajim/common/config.py:455 msgid "I'm working." msgstr "Ja pracuju." #: gajim/common/config.py:456 msgid "Phone" msgstr "Telefon" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Ja razmaŭlaju pa telefonie." #: gajim/common/config.py:457 msgid "Out" msgstr "Vyjšaŭ" #: gajim/common/config.py:457 msgid "I'm out enjoying life." msgstr "Vyjšaŭ ciešycca z žyćcia." #: gajim/common/config.py:468 msgid "I'm available." msgstr "Dastupny." #: gajim/common/config.py:469 msgid "I'm free for chat." msgstr "Achvotna parazmaŭlaju." #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "Chutka viarnusia." #: gajim/common/config.py:471 msgid "I'm not available." msgstr "Niedastupny." #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "Nie turbavać." #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "Byvaj!" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" "Hukm jaki treba hrać, kali paviedamleńnie ŭ pakoji ŭtrymlivaje adno sa " "słovaŭ, akreślenych u opcyi muc_highlight_words, albo tvaju mianušku." #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "Huk, jaki treba hrać pry atrymańni novaha hrupavoha paviedamleńnia." #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "Da" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Pamyłka: niemahčyma adčytać %s" #: gajim/common/const.py:205 #, fuzzy msgid "Doing Chores" msgstr "Niapravilny host" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "" #: gajim/common/const.py:207 #, fuzzy msgid "Cleaning" msgstr "Viečar" #: gajim/common/const.py:208 #, fuzzy msgid "Cooking" msgstr "Uvod paviedamleńnia" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "" #: gajim/common/const.py:212 #, fuzzy msgid "Gardening" msgstr "Ranica" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "" #: gajim/common/const.py:214 #, fuzzy msgid "Walking the Dog" msgstr "pavodle hrupy" #: gajim/common/const.py:216 #, fuzzy msgid "Drinking" msgstr "Pracuju" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "" #: gajim/common/const.py:227 msgid "Exercising" msgstr "" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "" #: gajim/common/const.py:229 #, fuzzy msgid "Dancing" msgstr "Viečar" #: gajim/common/const.py:230 #, fuzzy msgid "Hiking" msgstr "Vypichvajecca %s" #: gajim/common/const.py:231 #, fuzzy msgid "Jogging" msgstr "_Dałučysia" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "" #: gajim/common/const.py:233 msgid "Running" msgstr "" #: gajim/common/const.py:234 #, fuzzy msgid "Skiing" msgstr "Pracuju" #: gajim/common/const.py:235 msgid "Swimming" msgstr "" #: gajim/common/const.py:236 #, fuzzy msgid "Working out" msgstr "Pracuju" #: gajim/common/const.py:238 #, fuzzy msgid "Grooming" msgstr "pakoj" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "" #: gajim/common/const.py:242 #, fuzzy msgid "Shaving" msgstr "Jem" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Pasiŭny" #: gajim/common/const.py:249 msgid "Day Off" msgstr "" #: gajim/common/const.py:250 #, fuzzy msgid "Hanging out" msgstr "Źmianiajecca tema" #: gajim/common/const.py:251 #, fuzzy msgid "Hiding" msgstr "Vypichvajecca %s" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "" #: gajim/common/const.py:253 #, fuzzy msgid "Praying" msgstr "Jem" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "" #: gajim/common/const.py:256 #, fuzzy msgid "Thinking" msgstr "Pracuju" #: gajim/common/const.py:258 msgid "Relaxing" msgstr "" #: gajim/common/const.py:259 #, fuzzy msgid "Fishing" msgstr "Vypichvajecca %s" #: gajim/common/const.py:260 #, fuzzy msgid "Gaming" msgstr "Jem" #: gajim/common/const.py:261 #, fuzzy msgid "Going out" msgstr "_Adłučajusia" #: gajim/common/const.py:262 #, fuzzy msgid "Partying" msgstr "Jem" #: gajim/common/const.py:263 #, fuzzy msgid "Reading" msgstr "Pryčyna" #: gajim/common/const.py:264 #, fuzzy msgid "Rehearsing" msgstr "Pryčyna" #: gajim/common/const.py:265 #, fuzzy msgid "Shopping" msgstr "Splu" #: gajim/common/const.py:266 #, fuzzy msgid "Smoking" msgstr "Pracuju" #: gajim/common/const.py:267 msgid "Socializing" msgstr "" #: gajim/common/const.py:268 #, fuzzy msgid "Sunbathing" msgstr "Jem" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "" #: gajim/common/const.py:270 #, fuzzy msgid "Watching a Movie" msgstr "Hladžu film." #: gajim/common/const.py:272 #, fuzzy msgid "Talking" msgstr "Jem" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "" #: gajim/common/const.py:274 #, fuzzy msgid "On the Phone" msgstr "Ja razmaŭlaju pa telefonie." #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "" #: gajim/common/const.py:277 #, fuzzy msgid "Traveling" msgstr "Pieradajecca" #: gajim/common/const.py:278 #, fuzzy msgid "Commuting" msgstr "Uvod paviedamleńnia" #: gajim/common/const.py:280 msgid "Driving" msgstr "" #: gajim/common/const.py:281 msgid "In a Car" msgstr "" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "" #: gajim/common/const.py:283 #, fuzzy msgid "On a Plane" msgstr "Dałučany" #: gajim/common/const.py:284 #, fuzzy msgid "On a Train" msgstr "Adčyni jak _spasyłku" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "" #: gajim/common/const.py:286 #, fuzzy msgid "Walking" msgstr "Pracuju" #: gajim/common/const.py:289 #, fuzzy msgid "Coding" msgstr "Uvod paviedamleńnia" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "" #: gajim/common/const.py:291 msgid "Studying" msgstr "" #: gajim/common/const.py:292 #, fuzzy msgid "Writing" msgstr "Pracuju" #: gajim/common/const.py:295 msgid "Afraid" msgstr "" #: gajim/common/const.py:296 msgid "Amazed" msgstr "" #: gajim/common/const.py:297 msgid "Amorous" msgstr "" #: gajim/common/const.py:298 msgid "Angry" msgstr "" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "" #: gajim/common/const.py:300 msgid "Anxious" msgstr "" #: gajim/common/const.py:301 #, fuzzy msgid "Aroused" msgstr "Prypynienaja" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "" #: gajim/common/const.py:303 #, fuzzy msgid "Bored" msgstr "Tłusty" #: gajim/common/const.py:304 #, fuzzy msgid "Brave" msgstr "Nie razmaŭlaju " #: gajim/common/const.py:305 msgid "Calm" msgstr "" #: gajim/common/const.py:306 #, fuzzy msgid "Cautious" msgstr "Razmovy" #: gajim/common/const.py:307 #, fuzzy msgid "Cold" msgstr "Tłusty" #: gajim/common/const.py:308 #, fuzzy msgid "Confident" msgstr "_Źmiest" #: gajim/common/const.py:309 msgid "Confused" msgstr "" #: gajim/common/const.py:310 #, fuzzy msgid "Contemplative" msgstr "Zavieršana" #: gajim/common/const.py:311 #, fuzzy msgid "Contented" msgstr "_Źmiest" #: gajim/common/const.py:312 msgid "Cranky" msgstr "" #: gajim/common/const.py:313 msgid "Crazy" msgstr "" #: gajim/common/const.py:314 #, fuzzy msgid "Creative" msgstr "Niadziejny" #: gajim/common/const.py:315 #, fuzzy msgid "Curious" msgstr "uri" #: gajim/common/const.py:316 #, fuzzy msgid "Dejected" msgstr "Vydal" #: gajim/common/const.py:317 msgid "Depressed" msgstr "" #: gajim/common/const.py:318 #, fuzzy msgid "Disappointed" msgstr "Adklučana" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "" #: gajim/common/const.py:320 #, fuzzy msgid "Dismayed" msgstr "Adklučana" #: gajim/common/const.py:321 #, fuzzy msgid "Distracted" msgstr "Adklučana" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "" #: gajim/common/const.py:323 msgid "Envious" msgstr "" #: gajim/common/const.py:324 #, fuzzy msgid "Excited" msgstr "Dziejny" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "" #: gajim/common/const.py:327 msgid "Grateful" msgstr "" #: gajim/common/const.py:328 msgid "Grieving" msgstr "" #: gajim/common/const.py:329 #, fuzzy msgid "Grumpy" msgstr "Hrupa" #: gajim/common/const.py:330 msgid "Guilty" msgstr "" #: gajim/common/const.py:331 msgid "Happy" msgstr "" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "" #: gajim/common/const.py:333 #, fuzzy msgid "Hot" msgstr "_Host:" #: gajim/common/const.py:334 msgid "Humbled" msgstr "" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "" #: gajim/common/const.py:336 msgid "Hungry" msgstr "" #: gajim/common/const.py:337 msgid "Hurt" msgstr "" #: gajim/common/const.py:338 #, fuzzy msgid "Impressed" msgstr "paviedamleńnie" #: gajim/common/const.py:339 msgid "In Awe" msgstr "" #: gajim/common/const.py:340 msgid "In Love" msgstr "" #: gajim/common/const.py:341 msgid "Indignant" msgstr "" #: gajim/common/const.py:342 msgid "Interested" msgstr "" #: gajim/common/const.py:343 #, fuzzy msgid "Intoxicated" msgstr "Dziejny" #: gajim/common/const.py:344 #, fuzzy msgid "Invincible" msgstr "Niabačny" #: gajim/common/const.py:345 msgid "Jealous" msgstr "" #: gajim/common/const.py:346 #, fuzzy msgid "Lonely" msgstr "pieršaja" #: gajim/common/const.py:347 #, fuzzy msgid "Lost" msgstr "_Host:" #: gajim/common/const.py:348 msgid "Lucky" msgstr "" #: gajim/common/const.py:349 #, fuzzy msgid "Mean" msgstr "Niamieckaja" #: gajim/common/const.py:350 #, fuzzy msgid "Moody" msgstr "_Madyfikuj" #: gajim/common/const.py:351 msgid "Nervous" msgstr "" #: gajim/common/const.py:352 msgid "Neutral" msgstr "" #: gajim/common/const.py:353 #, fuzzy msgid "Offended" msgstr "Adłučany" #: gajim/common/const.py:354 msgid "Outraged" msgstr "" #: gajim/common/const.py:355 msgid "Playful" msgstr "" #: gajim/common/const.py:356 #, fuzzy msgid "Proud" msgstr "Hrupa" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "" #: gajim/common/const.py:358 #, fuzzy msgid "Relieved" msgstr "adzinaccataja" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "" #: gajim/common/const.py:360 msgid "Restless" msgstr "" #: gajim/common/const.py:361 #, fuzzy msgid "Sad" msgstr "Zatrymana" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "" #: gajim/common/const.py:363 #, fuzzy msgid "Satisfied" msgstr "Apošniaja źmiena:" #: gajim/common/const.py:364 msgid "Serious" msgstr "" #: gajim/common/const.py:365 msgid "Shocked" msgstr "" #: gajim/common/const.py:366 msgid "Shy" msgstr "" #: gajim/common/const.py:367 #, fuzzy msgid "Sick" msgstr "Mianuška" #: gajim/common/const.py:368 #, fuzzy msgid "Sleepy" msgstr "Splu" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "" #: gajim/common/const.py:370 #, fuzzy msgid "Stressed" msgstr "Vulica:" #: gajim/common/const.py:371 msgid "Strong" msgstr "" #: gajim/common/const.py:372 #, fuzzy msgid "Surprised" msgstr "Aŭtaryzavany" #: gajim/common/const.py:373 msgid "Thankful" msgstr "" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "" #: gajim/common/const.py:375 #, fuzzy msgid "Tired" msgstr "Čas" #: gajim/common/const.py:376 #, fuzzy msgid "Undefined" msgstr "dziaviataja" #: gajim/common/const.py:377 msgid "Weak" msgstr "" #: gajim/common/const.py:378 msgid "Worried" msgstr "" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "Zmoŭčany" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "marski" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Vypichvajecca %s" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "Krajina:" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Kont" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Apisańnie" #: gajim/common/const.py:391 #, fuzzy msgid "error" msgstr "Pamyłka Avahi" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "pieršaja" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 msgid "room" msgstr "pakoj" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "" #: gajim/common/const.py:412 #, fuzzy msgid "Unable to decode issuer public key" msgstr "Niemahčyma adčytać modulu idle" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "" #: gajim/common/const.py:430 #, fuzzy msgid "Invalid CA certificate" msgstr "Niapravilnaje imia karystalnika" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Złučeńnie dla kontu \"%s\" zhubiłasia" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "Pieradałučysia samastojna." #: gajim/common/connection.py:740 #, fuzzy, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "Transpart %s niapravilna adkazaŭ na zapyt rehistracyi: %s" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "" #: gajim/common/connection.py:1090 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Niemahčyma złučycca z \"%s\"" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Niemahčyma złučycca z \"%s\"" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Pravier złučeńnie albo pasprabuj paźniej." #: gajim/common/connection.py:1100 #, fuzzy, python-format msgid "Server replied: %s" msgstr "Zapisany ŭ: %s" #: gajim/common/connection.py:1115 #, fuzzy msgid "Connection to proxy failed" msgstr "Niemahvyma dałučycca" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, fuzzy, python-format msgid "Could not connect to account %s" msgstr "Niemahčyma złučycca z \"%s\"" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, fuzzy, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "Złučeńnie dla kontu \"%s\" zhubiłasia" #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Niemahčyma złučycca z \"%s\"" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "Pamyłka aŭtaryzacyi z \"%s\"" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Kali łaska, pravier pravilnaść loginu i parolu." #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "Nie staje fajłaŭ padtrymki Python dla D-Bus na hetym kamputary" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "Niemahčyma vykarystać mahčymaści D-Bus dla Gajima" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "D-Busu niama na hetym kamputary, albo nie staje modula Python" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "D-Busu niama na hetym kamputary, albo nie staje modula Python" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Standartnyja šablony paviedamleńniaŭ statusu" #: gajim/common/multimedia_helpers.py:70 msgid "Audio test" msgstr "" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Pamier: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Fajł: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "zialony" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, fuzzy, python-format msgid "%s configuration error" msgstr "Kanfihuracyja pakoju" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Niapravilny znak u naźvie hostu." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Patrabujecca adras servera." #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Niapravilny znak u imiani karystalnika." #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "Niapravilny znak u naźvie krynicy." #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "_Zaniaty" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "_Niedastupny" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "_Achvotna parazmaŭlaju" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "?status pieradačy:Prypyniena" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "Dałučajusia" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "_Adyjšoŭ" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "Adł_učany" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "N_iabačny" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "?kantakt maje status:Nieviadomy" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "?kantakt maje status:Jość pamyłki" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "?Najaŭnaja aŭtaryzacyja:Niama" #: gajim/common/helpers.py:315 msgid "To" msgstr "Da" #: gajim/common/helpers.py:317 msgid "From" msgstr "Ad" #: gajim/common/helpers.py:319 msgid "Both" msgstr "Dvuchbakovaja" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "?AS:Nieviadomaja" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "?Zapyt (aŭtaryzacyi):Niama" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Aŭtaryzuj" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "?Funkcyja kantaktu ŭ pakoji:Niama" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Maderatary" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Maderatar" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Udzielniki" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Udzielnik" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Naviedniki" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Naviednik" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "sočyć za razmovaj" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "robić štości inšaje" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "piša paviedamleńnie..." #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "pierastaŭ pisać" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "začyniŭ akno/kartku razmovy" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s GiB" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s GB" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s MiB" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s MB" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s KiB" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s KB" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s B" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, fuzzy, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "Dašli paviedamleńnie" msgstr[1] "Dašli paviedamleńnie" msgstr[2] "Dašli paviedamleńnie" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr "Я %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, python-format msgid "from user %s" msgstr "" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr "Ad" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Ja chaču dadać Vas u svoj śpis kantaktaŭ." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 #, fuzzy msgid "Timeout loading image" msgstr "Niemahčyma adčytać vyjavu" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "" #: gajim/common/helpers.py:1383 msgid "PyCURL is not installed" msgstr "" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Niemahčyma adčytać vyjavu" #: gajim/common/configpaths.py:85 #, python-format msgid "%s is a file but it should be a directory" msgstr "%s jość fajłam, ale musiŭ być kataloh" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Gajim zaviaršaje vykanańnie" #: gajim/common/exceptions.py:45 #, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" "Servis niedastupny: Gajim nie vykonvajecca, albo opcyja remote_control maje " "vartaść False" #: gajim/common/exceptions.py:81 #, fuzzy, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "" "Interfejs sesijaŭ niedastupny.\n" "Pasprabuj pračytać: http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/exceptions.py:93 #, fuzzy, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" "Interfejs sesijaŭ niedastupny.\n" "Pasprabuj pračytać: http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 #, fuzzy msgid "Please check if Avahi or Bonjour is installed." msgstr "Kali łaska, pravier instalacyju Avahi." #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "Niemahčyma ŭruchomić lakalny servis" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, python-format msgid "Unable to bind to port %d." msgstr "Niemahčyma dałučycca da portu %d." #: gajim/common/zeroconf/connection_zeroconf.py:217 #, fuzzy msgid "Please check if avahi/bonjour-daemon is running." msgstr "Kali łaska, pravier, ci pracuje avahi-daemon." #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, python-format msgid "Could not change status of account \"%s\"" msgstr "Niemahčyma źmianić status kontu \"%s\"" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "Kali łaska, pravier, ci pracuje avahi-daemon." #: gajim/common/zeroconf/connection_zeroconf.py:349 #, fuzzy msgid "Your message could not be sent." msgstr "Kantakt adłučany. Niemahčyma dasłać paviedamleńnie." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "Kantakt adłučany. Niemahčyma dasłać paviedamleńnie." #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "" "Niemahčyma złučycca z hostam: pieravyšany termin čakańnia padčas adsyłańnia " "źviestak." #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, python-format msgid "Error while adding service. %s" msgstr "Pamyłka dadańnia servisu. %s" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "paviedamleńnie" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "Ja chaču dadać ciabie ŭ svoj śpis kantaktaŭ." #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Tekst pamyłki: %s" #: gajim/common/modules/httpupload.py:134 #, fuzzy msgid "File is empty" msgstr "Ściežka da fajłu" #: gajim/common/modules/httpupload.py:137 #, fuzzy msgid "File does not exist" msgstr "Takoha pakoju niama." #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 msgid "Change status information" msgstr "Źmiani infarmacyju statusu" #: gajim/common/modules/adhoc_commands.py:113 msgid "Change status" msgstr "Źmiani status" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "Akreśli typ bačnaści i apisańnie" #: gajim/common/modules/adhoc_commands.py:121 msgid "Free for chat" msgstr "Achvotna parazmaŭlaju" #: gajim/common/modules/adhoc_commands.py:122 msgid "Online" msgstr "Dałučany" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "Adyjšoŭ" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "Nie turbavać" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "Niabačny - adłučany" #: gajim/common/modules/adhoc_commands.py:132 msgid "Presence description:" msgstr "Apisańnie statusu:" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "Status źmianiŭsia." #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 msgid "Leave Groupchats" msgstr "Pakiń pakoji" #: gajim/common/modules/adhoc_commands.py:231 #, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s z pakoju %(room_jid)s" #: gajim/common/modules/adhoc_commands.py:235 msgid "You have not joined a groupchat." msgstr "Ty nie dałučyŭsia da pakoju." #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "Zaznač pakoji, jakija chočaš pakinuć" #: gajim/common/modules/adhoc_commands.py:292 #, fuzzy msgid "You left the following groupchats:" msgstr "Ty pakinuŭ nastupnyja pakoji:" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" #: gajim/common/modules/roster_item_exchange.py:100 #, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "" #: gajim/common/modules/roster_item_exchange.py:104 #, fuzzy msgid "Sent contacts:" msgstr "Kantakty" #: gajim/data/gui/blocked_contacts_window.ui:13 #, fuzzy msgid "Blocked Contacts" msgstr "Kantakty" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Redaktar dadatkovych naładaŭ" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Filter:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Apisańnie" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "UVAHA: Kab ubačyć niekatoryja źmieny, uruchom Gajim" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "_Viarni zvyčajnyja kolery" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Aŭtamatyčna dałučajsia" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Kont" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Pakoj:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Parol:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "_Stvary zakładku dla hetaja pakoju" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "_Stvary zakładku dla hetaja pakoju" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "Dałučysia da _pakoju" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 #, fuzzy msgid "HTTP Connect" msgstr "Złučeńnie HTTP" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Kiruj profilami proxy" #: gajim/data/gui/manage_proxies_window.ui:148 msgid "_Name:" msgstr "_Imia:" #: gajim/data/gui/manage_proxies_window.ui:161 #, fuzzy msgid "_Type:" msgstr "Typ:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Ułaścivaści" #: gajim/data/gui/manage_proxies_window.ui:234 #, fuzzy msgid "_BOSH URL:" msgstr "_URL:" #: gajim/data/gui/manage_proxies_window.ui:258 #, fuzzy msgid "Proxy _Host:" msgstr "Proxy:" #: gajim/data/gui/manage_proxies_window.ui:269 #, fuzzy msgid "Use HTTP prox_y" msgstr "S_karystaj proxy" #: gajim/data/gui/manage_proxies_window.ui:288 #, fuzzy msgid "Proxy _Port:" msgstr "_Port:" #: gajim/data/gui/manage_proxies_window.ui:299 #, fuzzy msgid "Use proxy auth_entication" msgstr "Užyvaj aŭtaryzacyju" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "_Imia karystalnika:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "_Parol:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Nałady" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Zachavaj parol" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Źmiani parol" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Źviestki ab kantakcie" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "Lakalny JID:" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "Krynica:" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Status:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Zachoŭvaj žurnał razmoŭ" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 msgid "Contact" msgstr "Kantakt" #: gajim/data/gui/zeroconf_information_window.ui:234 msgid "First Name:" msgstr "Imia:" #: gajim/data/gui/zeroconf_information_window.ui:247 msgid "Last Name:" msgstr "Proźvišča:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "JID:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "E-mail:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 msgid "Personal" msgstr "Asabistyja źviestki" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "_Dasłać pryvatnaje paviedamleńnie" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Vyšli _fajł" #: gajim/data/gui/gc_occupants_menu.ui:29 #, fuzzy msgid "Occupant Actions" msgstr "_Dziejańni haspadara" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Daj hołas" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Ma_deratar" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Udzielnik" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Administratar" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "_Uładalnik" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "_Vypchni" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "Za_blakuj" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "_Dadaj u śpis kantaktaŭ" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "_Vykanaj zahad..." #: gajim/data/gui/tooltip_roster_contact.ui:125 #, fuzzy msgid "Idle since:" msgstr " ad %s" #: gajim/data/gui/tooltip_roster_contact.ui:151 #, fuzzy msgid "Mood:" msgstr "Pakoj:" #: gajim/data/gui/tooltip_roster_contact.ui:164 #, fuzzy msgid "Activity:" msgstr "Dziejny" #: gajim/data/gui/tooltip_roster_contact.ui:178 #, fuzzy msgid "Tune:" msgstr "Typ:" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Madyfikacyja kontu" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP: " #: gajim/data/gui/tooltip_roster_contact.ui:281 msgid "Subscription:" msgstr "Aŭtaryzacyja:" #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "_Status" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Madyfikuj kont..." #: gajim/data/gui/atom_entry_window.ui:8 msgid "New entry received" msgstr "Atrymaŭ novy zapis" #: gajim/data/gui/atom_entry_window.ui:92 msgid "Feed name:" msgstr "Nazva kanału:" #: gajim/data/gui/atom_entry_window.ui:119 msgid "Entry:" msgstr "Zapis:" #: gajim/data/gui/atom_entry_window.ui:131 msgid "Last modified:" msgstr "Apošniaja źmiena:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 #, fuzzy msgid "Change _Nickname..." msgstr "Źmiani _mianušku" #: gajim/data/gui/gc_control_popup_menu.ui:20 #, fuzzy msgid "_Manage Room" msgstr "Kiruj zakładkami" #: gajim/data/gui/gc_control_popup_menu.ui:31 #, fuzzy msgid "Change _Subject..." msgstr "Źmiani _temu" #: gajim/data/gui/gc_control_popup_menu.ui:38 #, fuzzy msgid "Configure _Room..." msgstr "Kanfihuruj _pakoj" #: gajim/data/gui/gc_control_popup_menu.ui:52 #, fuzzy msgid "_Destroy Room" msgstr "Apisańnie: %s" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:85 #, fuzzy msgid "_Request Voice" msgstr "_Daj hołas" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "Avatar:" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Abiary vyjavu" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 #, fuzzy msgid "Full Name" msgstr "Asablivy" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Telefon" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Farmat: HHHH-MM-DD" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 #, fuzzy msgid "Birthday" msgstr "Narodziny:" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Chatniaja staronka:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "E-mail:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 #, fuzzy msgid "Jabber ID" msgstr "JID:" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 #, fuzzy msgid "Family" msgstr "Proźvišča:" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 #, fuzzy msgid "Given" msgstr "Imia:" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Druhoje imia:" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Prefiks:" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Sufiks:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Vulica:" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "Dadatkovy adras:" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 #, fuzzy msgid "City" msgstr "Horad:" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Štat:" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 #, fuzzy msgid "Postal Code" msgstr "Paštovy indeks:" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "Krajina:" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 #, fuzzy msgid "Address" msgstr "Dadaj praviła" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Asablivy" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Firma:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 #, fuzzy msgid "Department" msgstr "Addzieł:" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Stanovišča:" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Nałady" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Praca" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Pra siabie" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "_Praciahni" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Prypyni" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Anuluj" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Adčyni kataloh z fajłam" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Pieradačy fajłaŭ" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "śpis pieradačaŭ fajłaŭ" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "Śpis dziejnych, skončanych i spynienych pieradačaŭ fajłaŭ" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "Pry_biarysia" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "Vydal skončanyja, anulavanyja i chibnyja pieradačy fajłaŭ ź śpisa" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Vydal pieradaču fajła ź śpisu." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "Hetaje dziejańnie anuluje pieradaču fajła i vydalić jaje ź śpisu." #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "Anuluj abranuju pieradaču fajła i vydal niedaciahnuty fajł" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Anuluj pieradaču fajła" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Anuluj abranuju pieradaču fajła" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "_Dašli i začyni" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Schavaj akno" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Nahadaj mnie ab zakančeńni pieradačy fajła" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "Pakažy nahadvańnie ŭ vypłyŭnym aknie pa zakančeńni pieradačy fajła" #: gajim/data/gui/filetransfers.ui:229 msgid "Shows a list of file transfers between you and others" msgstr "Pakažy śpis pieradačaŭ fajłaŭ" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Tłusty" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Nachileny" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 #, fuzzy msgid "Underline" msgstr "dziaviataja" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 #, fuzzy msgid "Strike" msgstr "Mianuška" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "Koler" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 #, fuzzy msgid "Font" msgstr "_Šryft:" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Źviestki ab kantakcie" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Abiary fajł dla adsyłańnia..." #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Klikni, kab ustavić smajlik (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Padzieja" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Padzieji" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Huki" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Huki" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Huki" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Huki" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Huki" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Huki" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Huki" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Huki" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Huki" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Huki" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "№" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Adyjšoŭ" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "Pakažy _śpis kantaktaŭ" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "_Nikoli" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "Zmoŭčany" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "Ściežka da fajłu" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Krynica:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Status" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Prahrama:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 #, fuzzy msgid "System" msgstr "Asablivy" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Nazva kantaktu" #: gajim/data/gui/vcard_information_window.ui:240 #, fuzzy msgid "User avatar" msgstr "Avatar:" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Kanfihuruj _pakoj" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 #, fuzzy msgid "Ask" msgstr "Pytaj:" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Aŭtaryzacyja:" #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 msgid "Personal Info" msgstr "Asabistyja źviestki" #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "Kamentary" #: gajim/data/gui/preferences_window.ui:38 msgid "Use default applications" msgstr "" #: gajim/data/gui/preferences_window.ui:41 #, fuzzy msgid "Custom" msgstr "Asablivy" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Usie statusy" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 #, fuzzy msgid "Composing only" msgstr "Uvod paviedamleńnia" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Adklučana" #: gajim/data/gui/preferences_window.ui:89 msgid "Only when pending events" msgstr "" #: gajim/data/gui/preferences_window.ui:103 #, fuzzy msgid "Pop it up" msgstr "_Vynyrni" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "_Paviedam mnie pra heta" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "Pakazvaj tolki ŭ śpisie _kantaktaŭ" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 #, fuzzy msgid "Last state" msgstr "Apošni status: %s" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "Pakazvaj a_vatary kantaktaŭ u śpisie kantaktaŭ" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać avatary kantaktaŭ u " "śpisie kantaktaŭ i ŭ pakojach" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "Pakazvaj paviedamleńni _statusu kantaktaŭ u śpisie kantaktaŭ" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać paviedamleńni statusu " "kantaktaŭ u śpisie kantaktaŭ i ŭ pakojach" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Pakazvaj a_vatary kantaktaŭ u śpisie kantaktaŭ" #: gajim/data/gui/preferences_window.ui:254 #, fuzzy msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "" "Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać avatary kantaktaŭ u " "śpisie kantaktaŭ i ŭ pakojach" #: gajim/data/gui/preferences_window.ui:275 #, fuzzy msgid "Sort contacts by status" msgstr "_Paradkuj kantakty pa statusie" #: gajim/data/gui/preferences_window.ui:285 #, fuzzy msgid "in _roster" msgstr "Niama ŭ śpisie kantaktaŭ" #: gajim/data/gui/preferences_window.ui:302 #, fuzzy msgid "in _group chats" msgstr "Dałučysia da _pakoju" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "" #: gajim/data/gui/preferences_window.ui:359 msgid "Spell _checker" msgstr "" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "źmiest paviedamleńnia" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 msgid "_Window behavior" msgstr "" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "Pakažy _śpis kantaktaŭ" #: gajim/data/gui/preferences_window.ui:484 #, fuzzy msgid "_Ignore rich content in incoming messages" msgstr "Ihnaruj afarmleńnie ŭvachodnych paviedamleńniaŭ" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" "Niekatoryja paviedamleńni źmiaščajuć afarmleńnie tekstu (farmatavańnie, " "kolery i h.d.). Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać tekst " "biez afarmleńnia." #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Niemahčyma dałučycca da pakoju" #: gajim/data/gui/preferences_window.ui:523 #, fuzzy msgid "Chat Appearance" msgstr "Redahuj praviła" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "Kali ŭčyniajecca novaja padzieja" #: gajim/data/gui/preferences_window.ui:623 #, fuzzy msgid "Notify me about contacts that sign _in" msgstr "Paviedamlaj mnie ab kantaktach, jakija źmianiajuć status na: " #: gajim/data/gui/preferences_window.ui:641 #, fuzzy msgid "Notify me about contacts that sign _out" msgstr "Paviedamlaj mnie ab kantaktach, jakija źmianiajuć status na: " #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Gajim budzie paviedamlać ab adłučeńni kantaktaŭ ad servera ŭ pravym nižnim " "kucie ekranu" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" "Pakazvaj vypłyŭnyja vokny i nahadvańni, kali ja ŭ stanie _Adyjšoŭ/" "Niedastupny/Zaniaty/Niabačny" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "" "Pakazvaj vypłyŭnyja vokny i nahadvańni, kali ja ŭ stanie _Adyjšoŭ/" "Niedastupny/Zaniaty/Niabačny" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "Pakazvaj _ikonu ŭ poli nahadvańnia" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Vizualnyja nahadvańni" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "_Ahučvaj" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "_Kiruj..." #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Huki" #: gajim/data/gui/preferences_window.ui:861 #, fuzzy msgid "Notifications" msgstr "Madyfikacyja kontu" #: gajim/data/gui/preferences_window.ui:898 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "Gajim umieje vysyłać i atrymvać metaźviestki, źviazanyja z razmovaj z peŭnym " "kantaktam. Tut ty možaš vyznačyć, jakija paviedamleńni statusu treba " "pakazvać u voknach razmoŭ." #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "Pakazanyja nahadvańni statusu ŭ časie razmovy:" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim umieje vysyłać i atrymvać metaźviestki, źviazanyja z razmovaj z peŭnym " "kantaktam. Tut ty možaš vyznačyć, jakija paviedamleńni statusu treba dasyłać " "surazmoŭcam." #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "Pakazanyja nahadvańni statusu ŭ časie razmovy:" #: gajim/data/gui/preferences_window.ui:987 #, fuzzy msgid "Chat state notifications" msgstr "Vizualnyja nahadvańni" #: gajim/data/gui/preferences_window.ui:1009 #, fuzzy msgid "Personal Events" msgstr "Asabistyja źviestki" #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "Aŭtamatyčna źmianiać stan na \"_Adyjšoŭ\" praz:" #: gajim/data/gui/preferences_window.ui:1047 msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "Aŭtamatyčna źmianiać stan na \"_Niedastupny\" praz:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "chvilinaŭ" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1166 #, fuzzy msgid "Auto Status" msgstr "Dziejańni" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Spytaj paviedamleńnia statusu, kali ja:" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "_Dałučajusia" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "_Adłučajusia" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" #: gajim/data/gui/preferences_window.ui:1291 #, fuzzy msgid "Default Message" msgstr "Standartnyja šablony paviedamleńniaŭ statusu" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 #, fuzzy msgid "Enabled" msgstr "Ukluč" #: gajim/data/gui/preferences_window.ui:1332 #, fuzzy msgid "Status Messages" msgstr "Šablony paviedamleńniaŭ statusu" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Šablony paviedamleńniaŭ statusu" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "Kanfihuruj koler i šryft interfejsu" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "Standartny zbor _ikon statusu:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Užyvaj _ikony transpartaŭ" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać admysłovyja ikony dla " "kožnaha pratakołu (naprykład, kantaktu z MSN buduć adpaviadać ikony statusu " "MSN)" #: gajim/data/gui/preferences_window.ui:1724 msgid "_Convert ASCII Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1808 #, fuzzy msgid "Style" msgstr "Zatrymana" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Dziejańni" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Dadaj praviła" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Server:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Umovy" #: gajim/data/gui/preferences_window.ui:2159 msgid "Audio/Video" msgstr "" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "_Paštovaja prahrama:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "_Hartač:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "_Kiraŭnik fajłaŭ:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Asablivy" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Aplikacyi" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "_Ihnaruj padzieji ad kantaktaŭ, jakich niama ŭ śpisie kantaktaŭ" #: gajim/data/gui/preferences_window.ui:2363 #, fuzzy msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Uklučy hetuju opcyju, kali tabie nadakučvaje ci zakidvaje niepatrebnymi " "paviedamleńniami chtości, kaho navat niama ŭ śpisie kantaktaŭ. Ale zvažaj, " "što ŭ takim razie nichto, akramia kantaktaŭ z tvajho śpisu, nia zmoža dasłać " "tabie paviedamleńnie" #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Raskryj źviestki pra _aperacyjnuju systemu" #: gajim/data/gui/preferences_window.ui:2381 #, fuzzy msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "" "Kali ŭklučanaja hetaja opcyja, Gajim budzie dałučacca da hetaha pakoju pry " "starcie" #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Raskryj źviestki pra _aperacyjnuju systemu" #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "" "Kali ŭklučanaja hetaja opcyja, Gajim budzie dałučacca da hetaha pakoju pry " "starcie" #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Raskryj źviestki pra _aperacyjnuju systemu" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 #, fuzzy msgid "_Manage..." msgstr "Kiruj..." #: gajim/data/gui/preferences_window.ui:2500 #, fuzzy msgid "Privacy" msgstr "Śpis pryvatnaści" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "_Zachoŭvać u žurnale źmieny statusu kantaktaŭ" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Roznaje" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "_Adčyni..." #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Redaktar dadatkovych naładaŭ" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Pačni _razmovu" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Dašli _asobnaje aviedamleńnie..." #: gajim/data/gui/contact_context_menu.ui:28 #, fuzzy msgid "Send _File..." msgstr "Vyšli _fajł" #: gajim/data/gui/contact_context_menu.ui:44 #, fuzzy msgid "Invite _Contacts" msgstr "Kantakty" #: gajim/data/gui/contact_context_menu.ui:73 #, fuzzy msgid "E_xecute Command..." msgstr "Vykanaj zahad..." #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "Źmiani nazvu kantaktu" #: gajim/data/gui/contact_context_menu.ui:92 #, fuzzy msgid "_Rename..." msgstr "Źmiani _nazvu" #: gajim/data/gui/contact_context_menu.ui:99 #, fuzzy msgid "Edit _Groups..." msgstr "Źmiani _hrupy" #: gajim/data/gui/contact_context_menu.ui:106 #, fuzzy msgid "Assign Open_PGP Key..." msgstr "Pryznač kluč Open_PGP" #: gajim/data/gui/contact_context_menu.ui:115 #, fuzzy msgid "Add Special _Notification..." msgstr "Dadaj admysłovaje _nahadvańnie" #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Aŭtaryzacyja" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "_Dazvol hetamu kantaktu bačyć moj status" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "Spytaj _dazvołu bačyć jahony/jejny status" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "Za_barani jamu/joj bačyć moj status" #: gajim/data/gui/contact_context_menu.ui:182 #, fuzzy msgid "_Unignore" msgstr "dziaviataja" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "" #: gajim/data/gui/contact_context_menu.ui:197 #, fuzzy msgid "_Add to Roster..." msgstr "_Dadaj u śpis kantaktaŭ" #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim: Stvareńnie kontu" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Ty musiš mieć kont, kab dałučycca da sietki\n" "Jabber." #: gajim/data/gui/account_creation_wizard_window.ui:95 #, fuzzy msgid "I already have an account I want to _use" msgstr "Ja ŭžo maju patrebny kont" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "Ja chaču za_rehistravać novy kont" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Kali łaska, abiary adnu z nastupnych opcyjaŭ:" #: gajim/data/gui/account_creation_wizard_window.ui:167 #, fuzzy msgid "Please fill in the data for your existing account" msgstr "Kali łaska, zapoŭni kartku źviestak dla novaha kontu" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "_Jabber ID:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 #, fuzzy msgid "Anon_ymous authentication" msgstr "Užyvaj aŭtaryzacyju" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Parol:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Zachavaj _parol" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Kali ŭklučanaja hetaja opcyja, Gajim zapomnić parol dla hetaha kontu" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Server:" #: gajim/data/gui/account_creation_wizard_window.ui:423 #, fuzzy msgid "Prox_y:" msgstr "Proxy:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Kiruj..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Skarystaj admysłovy host/port" #: gajim/data/gui/account_creation_wizard_window.ui:491 #, fuzzy msgid "_Hostname:" msgstr "Nazva hosta: " #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Port:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "_Dadatkovyja" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:687 #, fuzzy msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Stvarajecca kont\n" "\n" "Kali łaska, pačakaj..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Dałučysia pa nacisku knopki \"Skonč\"" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Nastaŭ profil paśla złučeńnia" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Skonč" #: gajim/data/gui/privacy_lists_window.ui:34 msgid "Privacy Lists:" msgstr "Śpisy pryvatnaści:" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Adras:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "_Pierajdzi" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 #, fuzzy msgid "Select the contacts you want to synchronise" msgstr "JID kantaktu, ź jakim chočaš parazmaŭlać" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Źmiani hrupy" #: gajim/data/gui/search_window.ui:42 #, fuzzy msgid "Please wait while retrieving search form..." msgstr "Kali łaska, pačakaj kanca atrymańnia śpisu zahadaŭ..." #: gajim/data/gui/search_window.ui:80 #, fuzzy msgid "_Add contact" msgstr "_Dadaj kantakt" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "Š_ukaj" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Šablony paviedamleńniaŭ statusu:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Dziejny" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Uviadzi novaje paviedamleńnie statusu" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 #, fuzzy msgid "Synchronise contacts" msgstr "Pakažy _adłučanyja kantakty" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "_Jabber ID:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "_Mianuška:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "_Hrupa:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "_Kont:" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "_Pratakoł:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "_Dazvol hetamu kantaktu bačyć moj status" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "_Aŭtaryzacyja" #: gajim/data/gui/add_new_contact_window.ui:367 #, fuzzy msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" "Treba zarehistravacca na hetym šluzie,\n" "kab dadać kantakt z hetaha pratakołu.\n" "Klikni pa knopcy rehistracyi\n" "dla praciahu." #: gajim/data/gui/add_new_contact_window.ui:382 msgid "_Register" msgstr "_Rehistruj" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" "Treba złučycca z šluzam, kab mahčy dadavać kantakty\n" "z hetaha pratakołu." #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "Ź_miani paviedamleńnie statusu" #: gajim/data/gui/change_mood_dialog.ui:73 #, fuzzy msgid "Mood:" msgstr "Huki" #: gajim/data/gui/change_mood_dialog.ui:85 #, fuzzy msgid "Message:" msgstr "Šablony paviedamleńniaŭ statusu" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Zatrymana" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Niemahvyma dałučycca" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Niemahvyma dałučycca" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Apisańnie" #: gajim/data/gui/plugins_window.ui:258 #, fuzzy msgid "Version" msgstr "Versija GTK+:" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "_Aŭtaryzuj" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 #, fuzzy msgid "Installed" msgstr "Zatrymana" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "pieršaja" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "Dvuchbakovaja" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "Ad" #: gajim/data/gui/privacy_list_window.ui:27 #, fuzzy msgid "to" msgstr "druhaja" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "Śpis pryvatnaści" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "Śpis pryvatnaści" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "Dziejny dla hetaj sesii" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "Dziejny pry kožnym starcie" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "Śpis praviłaŭ" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "Dadaj / Źmiani praviła" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "Dazvol" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Admoŭ" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "JID" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "pavodle hrupy" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "pavodle aŭtaryzacyi" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "usim" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "dasyłać mnie paviedamleńni" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "dasyłać mnie apytańni" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "bačyć moj status" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "dasyłać mnie paviedamleńni statusu" #: gajim/data/gui/privacy_list_window.ui:557 #, fuzzy msgid "All (including subscription)" msgstr "pavodle aŭtaryzacyi" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "Paradak:" #: gajim/data/gui/manage_sounds_window.ui:23 #, fuzzy msgid "Manage sounds" msgstr "Kiruj kontami" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Dziejny" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Padzieja" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Abiary hukavy fajł" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Vydal kont _tolki dla Gajim" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Vydal kont i dla Gajim, i na _servery" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "Što chočaš zrabić?" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Kali łaska, pačakaj kanca atrymańnia śpisu zahadaŭ..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Abiary zahad dla vykanańnia:" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Spraŭdź nanoŭ" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Kali łaska, pačakaj kanca dasyłańnia zahadu..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Hety abjekt Jabber nia maje dastupnych zahadaŭ." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Adbyłasia pamyłka:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Skonč" #: gajim/data/gui/account_context_menu.ui:20 #, fuzzy msgid "_Personal Events" msgstr "Asabistyja źviestki" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "Dałučysia da _pakoju" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Dadaj kantakt..." #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Šukaj servisy" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "_Vykanaj zahad..." #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Vyhlad" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Pakažy _śpis kantaktaŭ" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Pakažy _adłučanyja kantakty" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Pakažy _adłučanyja kantakty" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Pakažy _transparty" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Dapamoha" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Źmiest" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_Častyja pytańni" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 #, fuzzy msgid "Features" msgstr "Zdolnaści serveraŭ" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "_Stvary zakładku dla hetaja pakoju" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Nałady" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Skonč pracu" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Anuluj" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "Групавая размова" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "_Stvary zakładku dla hetaja pakoju" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Server:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Parol:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Kantakt adłučyŭsia" #: gajim/data/gui/manage_bookmarks_window.ui:342 msgid "Minimize on Auto Join" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Dašli paviedamleńnie i začyni akno" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Paviedamleńnie statusu" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Apisańnie: %s" #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Viečar" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 #, fuzzy msgid "Send" msgstr "_Vyšli" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Fajł: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" "Heta nie fatalna, ale ŭsio roŭna varta paviedamić pra takuju sytuacyju " "raspracoŭnikam." #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Paviedam pra pamyłku" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Pačni razmovu" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "_Admoŭ" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" "Admoŭ na zapyt aŭtaryzacyi kantaktu, kab jon/jana nie mahli bačyć, kali ja " "dałučany" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "_Aŭtaryzuj" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "" "Aŭtaryzuj kantakt, kab jon/jana mahli bačyć, kali ja dałučany da servera" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "P_rysutnaść" #: gajim/data/gui/emoji_chooser.ui:98 msgid "No Results Found" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "JID kantaktu, ź jakim chočaš parazmaŭlać" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:141 #, fuzzy msgid "MUC server" msgstr "Naziralniki" #: gajim/data/gui/chat_to_muc_window.ui:176 #, fuzzy msgid "In_vite" msgstr "_Zaprasi" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Ekspartuj" #: gajim/data/gui/history_manager.ui:93 #, fuzzy msgid "Welcome to Gajim History Logs Manager" msgstr "Kiraŭnik žurnałaŭ razmoŭ Gajim" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" #: gajim/data/gui/history_manager.ui:123 #, fuzzy msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "Vas vitaje Kiraŭnik žurnałaŭ razmoŭ Gajim\n" "\n" "Možaš vybrać adzin z žurnałaŭ u levaj paneli albo pasprabavać znajści " "patrebny tekst u bazie žurnałaŭ.\n" "\n" "UVAHA:\n" "Kali chočaš ździejśnić masavuju čystku žurnałaŭ, to začyni Gajim. Nie " "vydalaj žurnały razmoŭ ź ludźmi, ź jakimi ŭ hety čas razmaŭlaješ." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Šukaj u bazie žurnałaŭ" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "źmiest paviedamleńnia" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Dašli paviedamleńnie" #: gajim/data/gui/shortcuts_window.ui:24 #, fuzzy msgid "Add new line" msgstr "Stvary novy zapis" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Šablony paviedamleńniaŭ statusu:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Šablony paviedamleńniaŭ statusu:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "paviedamlennie statusu" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Dašli paviedamleńnie" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Paviedamleńnie dasłanaje" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Niadaŭna:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Viečar" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Pieradačy fajłaŭ" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "Dałučysia da _pakoju" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "paviedamlennie statusu" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 #, fuzzy msgid "Appearance" msgstr "Redahuj praviła" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Pakažy _adłučanyja kantakty" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Pakažy _adłučanyja kantakty" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Kantakty" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Źviestki ab kantakcie" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Źmiani nazvu kantaktu" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Kantakty" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Parol" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "_Zachoŭvać u žurnale źmieny statusu kantaktaŭ" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Maderatar" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Niadaŭna:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Žurnał razmoŭ" #: gajim/data/gui/history_window.ui:315 msgid "Chat" msgstr "Razmova" #: gajim/data/gui/history_window.ui:329 msgid "Record history for this chat" msgstr "" #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Niadaŭna:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Zahałovak:" #: gajim/data/gui/manage_pep_services_window.ui:13 #, fuzzy msgid "PEP Service Configuration" msgstr "Kanfihuracyja pakoju" #: gajim/data/gui/manage_pep_services_window.ui:69 #, fuzzy msgid "_Configure" msgstr "_Praciahni" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Stvary novy zapis" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "Ad:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Tema:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Zapoŭni formu." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Kanfihuracyja pakoju" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_Tak" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "Sta_tus" #: gajim/data/gui/systray_context_menu.ui:20 #, fuzzy msgid "_Start Chat..." msgstr "_Pačni razmovu" #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Pakažy ŭsie niahledžanyja _padzieji" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "Ściš huki" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Nałady" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Skonč pracu" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Da:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "_Dašli" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Dašli paviedamleńnie" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Adkažy" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Adkažy na hetaje paviedamleńnie" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "_Dašli i začyni" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Dašli paviedamleńnie i začyni akno" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:337 #, fuzzy msgid "Message: " msgstr "Šablony paviedamleńniaŭ statusu" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Nie staje arhumenta \"contact_jid\"" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Nie staje arhumenta \"contact_jid\"" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 #, fuzzy msgid "Send a message to the contact" msgstr "Užyvańnie: /%s, chavaje knopki razmovy." #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "%s nia znojdzieny" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "_Dastupny" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 #, fuzzy msgid "Clear the text window" msgstr "Užyvańnie: /%s, ačyščaje akno ad tekstu." #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Dasyłaje kantaktu fajł" #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 msgid "Command is not supported for zeroconf accounts" msgstr "" #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 #, fuzzy msgid "No open audio sessions with the contact" msgstr "Klikni, kab pahladzieć tekt papiarednich razmoŭ z hetym kantaktam" #: gajim/command_system/implementation/standard.py:191 #, python-format msgid "%s is not a valid tone" msgstr "" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "Złučeńnie niemahčymaje" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "Złučeńnia niama" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Užyvańnie: /%s, chavaje knopki razmovy." #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Źmiani _mianušku" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 #, fuzzy msgid "Invalid nickname" msgstr "Niapravilnaje imia karystalnika" #: gajim/command_system/implementation/standard.py:267 #, fuzzy msgid "Open a private chat window with a specified occupant" msgstr "" "Užyvańnie: /%s , adčyniaje akno pryvatnaj razmovy z akreślenaj " "asobaj." #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 #, fuzzy msgid "Nickname not found" msgstr "Mianuška nia znojdziena: %s" #: gajim/command_system/implementation/standard.py:276 #, fuzzy msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" "Užyvańnie: /%s , adčyniaje akno pryvatnaj razmovy z akreślenaj " "asobaj." #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Pytajsia paćvierdžańnia pierad začynieńniem kartki/akna razmovy." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "%(contact_jid)s zaprošany ŭ %(room_jid)s." #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "Dałučysia da _pakoju" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Ty nie dałučyŭsia da pakoju." #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Niapravilnaje imia karystalnika" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "Suviaź: " #: gajim/command_system/implementation/standard.py:365 #, fuzzy msgid "Display names of all group chat occupants" msgstr "Užyvańnie: /%s, pakazvaje imiony naviednikaŭ pakoju." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Złučeńnie" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Novaja hrupavaja razmova" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Dadaj novy kantakt" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "Asobnaje paviedamleńnie z kontu %s" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "Asobnaje paviedamleńnie z kontu %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Asobnaje paviedamleńnie" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Dašli %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Atrymana %s" #: gajim/gtk/single_message.py:238 #, fuzzy, python-format msgid "Form %s" msgstr "Я %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "Złučeńnia niama" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Kali łaska, pravier, ci jość złučeńnie z \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "RE: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s napisaŭ:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "" #: gajim/gtk/pep_config.py:133 #, fuzzy, python-format msgid "Configure %s" msgstr "_Praciahni" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "_Rehistruj" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Zarehistrujsia na %s" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "Słoŭnik dla movy %s niedastupny" #: gajim/gtk/dialogs.py:83 #, fuzzy, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" "Treba zainstalavać słoŭnik %s, kab praviarać pravapis, albo abrać inšuju " "movu ŭ opcyi speller_language." #: gajim/gtk/dialogs.py:440 #, fuzzy, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "Stvarajecca metakantakt. Ty sapraŭdy chočaš praciahnuć?" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "JID pakoju ŭtrymlivaje niedazvolenyja znaki." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "dla kontu %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Źmiani parol" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Treba ŭvieści parol." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Paroli roźniacca" #: gajim/gtk/add_contact.py:30 #, fuzzy msgid "GG Number" msgstr "Numer GG:" #: gajim/gtk/add_contact.py:31 #, fuzzy msgid "ICQ Number" msgstr "Numer ICQ:" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Dadaj kantakt..." #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s MiB" #: gajim/gtk/add_contact.py:235 #, fuzzy, python-format msgid "You must supply the %s of the new contact." msgstr "Treba ŭvieści parol dla novaha kontu." #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "Niapravilny identyfikatar karystalnika" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "Identyfikatar karystalnika nia moža ŭtrymlivać krynicy." #: gajim/gtk/add_contact.py:274 #, fuzzy msgid "You cannot add yourself to your roster." msgstr "Ja chaču dadać ciabie ŭ svoj śpis kantaktaŭ." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Adłučany" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Kantakt užo jość u śpisie kantaktaŭ" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Hety kantakt užo jość u tvajim śpisie kantaktaŭ." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "Identyfikatar karystalnika:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "Pamyłka dadańnia servisu. %s" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "Uvod paviedamleńnia" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Pasiŭny" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Źmiani status" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "Razmova\n" "Paviedamleńni" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Novaje paviedamleńnie" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Kont" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Hrupa" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "_Pakazvaj padzieju ŭ śpisie kantaktaŭ" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Žurnał razmoŭ" #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Źmianiajecca mianuška" #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "_Uvachodnaje paviedamleńnie:" #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "_Uvachodnaje paviedamleńnie:" #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "_Zychodnaje paviedamleńnie:" #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "_Zychodnaje paviedamleńnie:" #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Paviedamleńnie statusu" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Paviedamleńnie statusu" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Koler" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "_Padśviatlaj słovy z pamyłkami" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Paviedamleńni" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "_Viarni zvyčajnyja kolery" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Kantakt adłučyŭsia" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Kantakt dałučyŭsia" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "Gajim - %s" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Mianuška nie dazvolenaja: %s" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Dziejny" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s maje ciapier status %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, fuzzy, python-format msgid "Error: %s" msgstr "Tekst pamyłki: %s" #: gajim/gtk/history.py:590 msgid "Error" msgstr "" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Dziejny status: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Dziejny status: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "Što chočaš zrabić?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Dałučajusia" #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Pieradača fajłu %(filename)s ad %(name)s spyniena." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "%d niečytanaje paviedamleńnie" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "Klijent Jabber dla GTK+" #: gajim/gtk/about.py:48 #, fuzzy, python-format msgid "GTK+ Version: %s" msgstr "Versija GTK+:" #: gajim/gtk/about.py:49 #, fuzzy, python-format msgid "PyGObject Version: %s" msgstr "Versija PyGTK:" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Dziejnyja raspracoŭniki:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Byłyja raspracoŭniki:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 #, fuzzy msgid "we would like to thank all the package maintainers." msgstr "I ŭrešcie, chočacca padziakavać usim apiekunam pakietaŭ." #: gajim/gtk/about.py:61 msgid "Thanks" msgstr "" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "Ihar Hrachyshka " #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Abiary fajł dla adsyłańnia..." #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Abiary vyjavu" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Usie fajły" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Usie fajły" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Vyšli _fajł" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Vyjavy" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Abiary vyjavu" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Usie fajły" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Zapišy fajł jak..." #: gajim/gtk/profile.py:72 #, fuzzy msgid "Retrieving profile…" msgstr "Atrymańnie profilu..." #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Źviestki ab kantakcie" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Farmat: HHHH-MM-DD" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "Źviestki atrymanyja" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "" "Niemahčyma apublikavać asabistyja źviestki, nie dałučyŭšysia da servera." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Dasyłańnie profilu..." #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "Źviestki NIE apublikavanyja" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "Pamyłka publikacyi vCard" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "Adbyłasia pamyłka padčas publikacyi asabistych źviestak, pasprabuj paźniej." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Niapravilny zapis" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 #, fuzzy msgid "Invalid Nickname" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/join_groupchat.py:223 #, fuzzy msgid "Please choose a nickname" msgstr "Stvary novy zapis" #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Niapravilnaja spasyłka" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "Heta nie pakoj" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Nałady" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Niama złučeńnia z serveram" #: gajim/gtk/mam_preferences.py:102 #, fuzzy msgid "Error received: {}" msgstr "Atrymaŭ novy zapis:" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Pamyłka Avahi" #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "Dziejny" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "Niadziejny" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "Lahičnaja źmiennaja" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "Cely lik" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Tekst" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Nazva nałady" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Vartaść" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Typ" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Niama)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Schavany" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "Nazva hosta: " #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Zdolnaści serveraŭ" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Zapisany ŭ: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "" #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 #, fuzzy msgid "Command line" msgstr "Zahady: %s" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "" #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "" #: gajim/gtk/features.py:61 #, fuzzy msgid "OpenPGP message encryption" msgstr "Šyfravańnie OpenPGP" #: gajim/gtk/features.py:63 #, fuzzy msgid "Ability to encrypting chat messages with OpenPGP." msgstr "_Uvachodnaje paviedamleńnie:" #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "" #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 #, fuzzy msgid "Password encryption" msgstr "Paroli roźniacca" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "" #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "" #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 msgid "Requires Gspell" msgstr "" #: gajim/gtk/features.py:76 #, fuzzy msgid "Automatic status" msgstr "_Dastasuj da statusu" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "" #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "" #: gajim/gtk/features.py:81 #, fuzzy msgid "RST Generator" msgstr "Ahulnaja" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "" #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "" #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 msgid "Requires gir1.2-gupnpigd-1.0." msgstr "" #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "Dastupny" #: gajim/gtk/features.py:109 #, fuzzy msgid "Feature" msgstr "Zdolnaści serveraŭ" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "Śpis pryvatnaści %s" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "Śpis pryvatnaści dla %s" #: gajim/gtk/privacy_list.py:147 #, fuzzy, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "Paradak: %s, dziejańnie: %s, typ: %s, vartaść: %s" #: gajim/gtk/privacy_list.py:152 #, fuzzy, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Paradak: %s, dziejańnie: %s" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "Redahuj praviła" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "Dadaj praviła" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "Śpisy pryvatnaści dla %s" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "Niapravilnaja nazva śpisu" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "Treba akreślić nazvu dla novaha śpisu pryvatnaści." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Kont paśpiachova dadany" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 #, fuzzy msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Možaš źmianić dadatkovyja nałady kontu, nacisnuŭšy zaraz knopku \"Dadatkovyja" "\", albo paźniej, abraŭšy \"Źmianić\"->\"Konty\" ŭ menu hałoŭnaha akna." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Novy kont paśpiachova stvorany" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Treba vyznačyć imia karystalnika, kab skanfihuravać hety kont." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 #, fuzzy msgid "Invalid server" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/account_wizard.py:255 #, fuzzy msgid "Please provide a server on which you want to register." msgstr "Kali łaska, vyznač dla siabie novuju mianušku:" #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Niapravilny zapis" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "Abrany port musić być numeram portu." #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "Adbyłasia pamyłka padčas stvareńnia kontu" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Nazva kontu ŭžo vykarystoŭvajecca" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Kont z takoj nazvaj užo isnuje." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Filter:" #: gajim/gtk/xml_console.py:79 #, fuzzy msgid "XML Input" msgstr "Uvod XML" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Niapravilny fajł" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "Zmoŭčany" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "zahałovak statusu" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "tekst paviedamleńnia statusu" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Pieradałučycca?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "Kali chočaš zadziejničać źmieny, treba pieradałučycca." #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "Akno razmovy adčynienaje dla kontu %s" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "Usie adčynienyja vokny razmovy buduć začynienyja. Praciahnuć?" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Dadaj kantakt..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "_Vydal" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Abjadnanyja konty" #: gajim/gtk/accounts.py:549 msgid "Use PGP Agent" msgstr "" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Złučeńnie" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Kantakty" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Pryznač kluč OpenPGP" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "_Zlučajsia pry starcie Gajim" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Aŭtamatyčna pieradałučajsia pry abryvie złučeńnia" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Zachoŭvaj _žurnały razmoŭ dla ŭsich kantaktaŭ" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "_Dašli paviedamleńnie servera" #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Usie statusy" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Źmianiaje status kontu albo kontaŭ" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Paviedamleńni" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Skarystaj proxy dla pieradačy fajłaŭ" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "Złučeńnia niama" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Proxy:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "Złučeńnie" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Dasyłaj pravieračnyja infarmacyjnyja pakiety" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "Pryjary_tet:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Źmianiaje status kontu albo kontaŭ" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Imia:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Proźvišča:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Novy list" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "_Dastasuj da statusu" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Ukluč" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Port:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Złučeńnie" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Niapravilnaje imia karystalnika" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Zachavaj parol" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "Smajliki:" #: gajim/gtk/bookmarks.py:72 msgid "?print_status:All" msgstr "?print_status:Usie" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "Tolki ŭvachod i vychad" #: gajim/gtk/bookmarks.py:74 msgid "?print_status:None" msgstr "?print_status:Niama" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "Novaja hrupavaja razmova" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Hetaja zakładka źmiaščaje niapravilnyja źviestki" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "" "Kali łaska, pravier, ci vyznačanyja pali servera i pakoju, albo vydal hetuju " "zakładku." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 #, fuzzy msgid "Character not allowed" msgstr "Mianuška nie dazvolenaja: %s" #: gajim/gtk/bookmarks.py:367 #, fuzzy msgid "Invalid room" msgstr "Niapravilny zapis" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Ściežka da fajłu" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 msgid "Archive is malformed" msgstr "" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Hety fajł užo isnuje" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Blakavańnie %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Niemahvyma dałučycca" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Kanfihuracyja pakoju" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Klijent kamunikacyi dla Jabber" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "Klijent Jabber dla GTK+" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Pakažy ŭsie niahledžanyja _padzieji" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Zdolnaści serveraŭ" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 msgid "Automatic spell-checking for your messages" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Prahlad servisaŭ dla kontu %s" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "_Zachoŭvać u žurnale źmieny statusu kantaktaŭ" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Pakoji" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Niadaŭna:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Niemahvyma dałučycca" #~ msgid "Stopped" #~ msgstr "Spyniena" #~ msgid "Error reading file:" #~ msgstr "Pamyłka adčytańnia fajłu:" #~ msgid "Error parsing file:" #~ msgstr "Pamyłka razboru fajłu:" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Pamyłka pieradačy fajłu" #, fuzzy #~ msgid "XML console interface" #~ msgstr "Kansol XML" #, fuzzy #~ msgid "(ESession info)" #~ msgstr "Apisańnie" #~ msgid "Save as Preset..." #~ msgstr "Zachavaj jak šablon..." #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "Jabberd1.4 nia lubić danych SHA pry sprobie dałučeńnia da pakoju, " #~ "abaronienaha parolem. Źmiani vartaść hetaj opcyi na False, kab pierastać " #~ "słać takija danyja SHA." #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie zamianiać ascii-smajliki " #~ "(naprykład, ':)' ) na adpaviednyja hrafičnyja smajliki" #, fuzzy #~ msgid "_Emoticons" #~ msgstr "Smajliki:" #~ msgid "_Highlight misspelled words" #~ msgstr "_Padśviatlaj słovy z pamyłkami" #, fuzzy #~ msgid "Notify by icon when your messages are received" #~ msgstr "Huk, jaki treba hrać pry atrymańni novaha hrupavoha paviedamleńnia." #, fuzzy #~ msgid "T_heme" #~ msgstr "T_ema:" #, fuzzy #~ msgid "Themes" #~ msgstr "Ułaścivaści" #, fuzzy #~ msgid "Presence" #~ msgstr "P_rysutnaść" #, fuzzy #~ msgid "Emoticons disabled" #~ msgstr "Šyfravańnie adklučanaje" #, fuzzy #~ msgid "You cannot make changes to the default theme" #~ msgstr "Niemahčyma vydalić dziejnuju temu" #, fuzzy #~ msgid "Please create a new clean theme." #~ msgstr "Stvary novy zapis" #~ msgid "theme name" #~ msgstr "nazva temy" #~ msgid "You cannot delete your current theme" #~ msgstr "Niemahčyma vydalić dziejnuju temu" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Novaje asobnaje paviedamleńnie ad %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Novaje pryvatnaje paviedamleńnie ŭ pakoji %s" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s: %(message)s" #, fuzzy #~ msgid "Messaged by %(nickname)s" #~ msgstr "Novaje paviedamleńnie ad %(nickname)s" #, fuzzy #~ msgid "Status message text color." #~ msgstr "tekst paviedamleńnia statusu" #, fuzzy #~ msgid "Incoming nickname font." #~ msgstr "Niapravilnaje imia karystalnika" #, fuzzy #~ msgid "Status message text font." #~ msgstr "tekst paviedamleńnia statusu" #~ msgid "Background color of contacts when they just signed in." #~ msgstr "Fonavy koler kantaktaŭ, kali jany tolki dałučylisia." #~ msgid "Background color of contacts when they just signed out." #~ msgstr "Fonavy koler kantaktaŭ, kali jany tolki adłučylisia." #~ msgid "green" #~ msgstr "zialony" #~ msgid "grocery" #~ msgstr "bakaleja" #~ msgid "human" #~ msgstr "čałaviek" #~ msgid "marine" #~ msgstr "marski" #, fuzzy #~ msgid "Contact row" #~ msgstr "Kantakt" #~ msgid "Gajim Themes Customization" #~ msgstr "Kanfihuracyja temy Gajim" #~ msgid "Text _color:" #~ msgstr "Koler _tekstu:" #~ msgid "_Background:" #~ msgstr "_Fon:" #~ msgid "Text _font:" #~ msgstr "_Šryft:" #~ msgid "Font style:" #~ msgstr "Styl šryftu:" #~ msgid "Paused" #~ msgstr "Prypynienaja" #~ msgid "Gone" #~ msgstr "Vyjšaŭ" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "MUC\n" #~ "Paviedamleńni" #~ msgid "Chatstate Tab Colors" #~ msgstr "Kolery kartak u aknie razmoŭ" #, fuzzy #~ msgid "Chat message" #~ msgstr "Pa_viedamleńnie statusu:" #~ msgid "Use system _default" #~ msgstr "Užyvaj _zmoŭčany dla systemy" #, fuzzy #~ msgid "Font" #~ msgstr "Huki" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Nazva kantaktu" #, fuzzy #~ msgid "Contact's message" #~ msgstr "Pa_viedamleńnie statusu:" #, fuzzy #~ msgid "_Status message" #~ msgstr "Pa_viedamleńnie statusu:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Padśviatleńnie paviedamleńnia ŭ pakoji" #, fuzzy #~ msgid "Your nickname" #~ msgstr "П_ерад мянушкай:" #, fuzzy #~ msgid "Your message" #~ msgstr "Tekst pamyłki: %s" #, fuzzy #~ msgid "Chat Line Colors" #~ msgstr "Kolery kartak u aknie razmoŭ" #, fuzzy #~ msgid "Jabber ID:" #~ msgstr "JID:" #, fuzzy #~ msgid "Resource:" #~ msgstr "Krynica:" #, fuzzy #~ msgid "Status:" #~ msgstr "Nałady" #, fuzzy #~ msgid "Client:" #~ msgstr "Asablivy" #, fuzzy #~ msgid "Contact time:" #~ msgstr "Nałady" #, fuzzy #~ msgid "Ask:" #~ msgstr "Dziejańni" #, fuzzy #~ msgid "Subscription:" #~ msgstr "Apisańnie" #, fuzzy #~ msgid "Name:" #~ msgstr "Asablivy" #, fuzzy #~ msgid "Nickname:" #~ msgstr "Mianuška:" #, fuzzy #~ msgid "Street:" #~ msgstr "Nałady" #, fuzzy #~ msgid "City:" #~ msgstr "Asablivy" #, fuzzy #~ msgid "State:" #~ msgstr "Nałady" #, fuzzy #~ msgid "Extra Address:" #~ msgstr "Dadatkovy adras:" #, fuzzy #~ msgid "Postal Code:" #~ msgstr "Paštovy indeks:" #, fuzzy #~ msgid "Country:" #~ msgstr "Huki" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Chatniaja staronka:" #, fuzzy #~ msgid "E-Mail:" #~ msgstr "E-mail:" #, fuzzy #~ msgid "Phone No.:" #~ msgstr "Telefon:" #, fuzzy #~ msgid "Birthday:" #~ msgstr "Narodziny:" #, fuzzy #~ msgid "Family:" #~ msgstr "Proźvišča:" #, fuzzy #~ msgid "Middle:" #~ msgstr "Dadaj praviła" #, fuzzy #~ msgid "Prefix:" #~ msgstr "Ułaścivaści" #, fuzzy #~ msgid "Given:" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "Suffix:" #~ msgstr "Huki" #, fuzzy #~ msgid "Full Name" #~ msgstr "Asablivy" #, fuzzy #~ msgid "Company:" #~ msgstr "Asablivy" #, fuzzy #~ msgid "Department:" #~ msgstr "Addzieł:" #, fuzzy #~ msgid "Position:" #~ msgstr "Umovy" #, fuzzy #~ msgid "Role:" #~ msgstr "Huki" #~ msgid "Edit %s" #~ msgstr "Źmiani %s" #~ msgid "Register to %s" #~ msgstr "Zarehistrujsia na %s" #~ msgid "Conversation History with %s" #~ msgstr "Žurnał razmoŭ z %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Niemahčyma złučycca z \"%s\"" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "Źviestki rehistracyi dla transpartu %s nie pryjšli ŭ čas" #~ msgid "Register to" #~ msgstr "Zarehistrujsia na" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Nazva kantaktu" #, fuzzy #~ msgid "Search:" #~ msgstr "Šukaj" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Niemahčyma źmianić parol, nie dałučyŭšysia da servera." #~ msgid "Invalid password" #~ msgstr "Niapravilny parol" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "Parolu ŭ abodvuch palach nie pavinny roźnicca." #~ msgid "Enter new password:" #~ msgstr "Uviadzi novy parol:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Paŭtary parol dla paćvierdžańnia:" #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "JID %s nie adpaviadaje standartu RFC. Jon nia budzie dadany da tvajho " #~ "śpisu kantaktaŭ. Vydal jaho z dapamohaj pryłady kiravańnia śpisam " #~ "kantaktaŭ, naprykład, http://jru.jabberstudio.org/" #~ msgid "unsubscribe request from %s" #~ msgstr "zapyt adpiski ad %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Aŭtamatyčna dałučajsia" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Chatniaja staronka:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Praciahni" #~ msgid "Manage Bookmarks" #~ msgstr "Kiruj zakładkami" #~ msgid "_Nickname:" #~ msgstr "_Mianuška:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie dałučacca da hetaha pakoju " #~ "pry starcie" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Pakazvaj status:" #, fuzzy #~ msgid "Add JID" #~ msgstr "JID:" #, fuzzy #~ msgid "Preference:" #~ msgstr "Nałady" #, fuzzy #~ msgid "Preference" #~ msgstr "Nałady" #, fuzzy #~ msgid "JID:" #~ msgstr "Vaš JID:" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "" #~ "Kali łaska, zapoŭni źviestki ab kantakcie, kali chočaš dadać kantakt %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Kali łaska, zapoŭni źviestki ab kantakcie, jaki chočaš dadać" #, fuzzy #~ msgid "Recently" #~ msgstr "Niadaŭna:" #~ msgid "Add New Contact" #~ msgstr "Dadaj novy kantakt" #~ msgid "_User ID:" #~ msgstr "_ID karystalnika:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "Identyfikatar karystalnika:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Mianuška" #~ msgid "Personal Information" #~ msgstr "Asabistyja źviestki" #, fuzzy #~ msgid "Avatar:" #~ msgstr "Avatar:" #~ msgid "Click to set your avatar" #~ msgstr "Klikni, kab vystavić svoj avatar" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "Vydal hrupu" #~ msgid "Not fetched because of invisible status" #~ msgstr "Nia ściahnuta z-za niabačnaha statusu" #~ msgid "Please wait..." #~ msgstr "Kali łaska, pačakaj..." #~ msgid "Yahoo! Address:" #~ msgstr "Adras Yahoo!:" #, fuzzy #~ msgid "Forward unread messages" #~ msgstr "%d niečytanaje paviedamleńnie" #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "%d niečytanaje paviedamleńnie" #~ msgid "AIM Address:" #~ msgstr "Adras AIM:" #~ msgid "MSN Address:" #~ msgstr "Adras MSN:" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "Ci vykarystoŭvajecca šyfravańnie OpenPGP dla hetaha kantaktu?" #, fuzzy #~ msgid "End to End message encryption" #~ msgstr "Šyfravańnie OpenPGP" #, fuzzy #~ msgid "Encrypting chat messages." #~ msgstr "_Uvachodnaje paviedamleńnie:" #, fuzzy #~ msgid "This session is encrypted" #~ msgstr "[Hetaje paviedamleńnie zašyfravanaje]" #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "Šyfravańnie adklučanaje" #, fuzzy #~ msgid "Unable to decrypt message" #~ msgstr "Dla kožnaha _paviedamleńnia" #~ msgid "_Send" #~ msgstr "_Vyšli" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Zapišy vyjavu jak..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Ekspartavańnie žurnałaŭ..." #~ msgid "Choose Image" #~ msgstr "Abiary vyjavu" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Abiary fajł dla adsyłańnia..." #~ msgid "When %s becomes:" #~ msgstr "Kali %s maje status:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Dadajecca admysłovaje nahadvańnie dla %s" #~ msgid "Unable to load idle module" #~ msgstr "Niemahčyma adčytać modulu idle" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s jość kataloham, ale musiŭ być fajł" #~ msgid "creating logs database" #~ msgstr "stvarajecca baza žurnałaŭ" #, fuzzy #~ msgid "creating cache database" #~ msgstr "stvarajecca baza žurnałaŭ" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Dašli %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Kiraŭnik žurnałaŭ razmoŭ Gajim" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Kiruj kontami" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Dašli _asobnaje aviedamleńnie..." #, fuzzy #~ msgid "E2E encryption disabled" #~ msgstr "Šyfravańnie adklučanaje" #~ msgid "uri" #~ msgstr "uri" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Zatrymana" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Zatrymana" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Niemahvyma dałučycca" #, fuzzy #~ msgid "Security error during download" #~ msgstr "Niemahčyma złučycca z \"%s\"" #, fuzzy #~ msgid "Error in download" #~ msgstr "Niemahčyma złučycca z \"%s\"" #~ msgid "cyan" #~ msgstr "cyan" #~ msgid "migrating logs database to indices" #~ msgstr "indeksavańnie bazy razmoŭ" #, fuzzy #~ msgid "Send File..." #~ msgstr "Vyšli _fajł" #, fuzzy #~ msgid "HTTP File Upload not supported by your server" #~ msgstr "Tvoj server nie padtrymvaje zachoŭvańnia metakantaktaŭ" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Pieradačy fajłaŭ" #~ msgid "Shows or hides the roster window" #~ msgstr "Pakazvaje / chavaje śpis kantaktaŭ" #, fuzzy #~ msgid "Shows or hides the ipython window" #~ msgstr "Pakazvaje / chavaje śpis kantaktaŭ" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "kontu %s" #, fuzzy #~ msgid "Exception" #~ msgstr "Apisańnie" #, fuzzy #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "Ja chaču dadać Vas u svoj śpis kantaktaŭ." #~ msgid "_Actions" #~ msgstr "_Dziejańni" #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Pačni razmovu" #~ msgid "You are already in group chat %s" #~ msgstr "Užo ŭdzielničaješ u razmovie ŭ pakoji %s" #~ msgid "Join Group Chat with account %s" #~ msgstr "Dałučysia da pakoju dla kontu %s" #, fuzzy #~ msgid "Invalid Account" #~ msgstr "Niapravilnaja nazva kontu" #, fuzzy #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "Treba stvaryć kont, kab razmaŭlać ź inšymi kantaktami." #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "JID pakoju ŭtrymlivaje niedazvolenyja znaki." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "JID pakoju ŭtrymlivaje niedazvolenyja znaki." #~ msgid "Start Chat with account %s" #~ msgstr "Pačni razmovu dla kontu %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Vyznač mianušku albo JID kantakta, jakomu chočaš dasłać\n" #~ "paviedamleńnie:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Taki JID užo vykarystoŭvajecca" #~ msgid "Unable to parse \"%s\"." #~ msgstr "Niemahčyma razabrać \"%s\"." #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "Pakazvaje akno razmovy, kab dasyłać paviedamleńni kantaktu" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID kantaktu, ź jakim chočaš parazmaŭlać" #~ msgid "Adds contact to roster" #~ msgstr "Dadaje kantakt u śpis kantaktaŭ" #~ msgid "jid" #~ msgstr "jid" #~ msgid "Adds new contact to this account" #~ msgstr "Dadaje novy kantakt dla hetaha kontu" #~ msgid "Opens 'Start Chat' dialog" #~ msgstr "Adčyniaje akno 'Pačni razmovu'" #~ msgid "Starts chat, using this account" #~ msgstr "Pačynaje razmovu dla hetaha kontu" #, fuzzy #~ msgid "Handle a xmpp:/ URI" #~ msgstr "Absłuhoŭvaj spasyłki xmpp:/" #, fuzzy #~ msgid "Message content" #~ msgstr "źmiest paviedamleńnia" #~ msgid "Join a MUC room" #~ msgstr "Dałučysia da pakoju" #, fuzzy #~ msgid "Nickname to use" #~ msgstr "Mianuška nia znojdziena: %s" #, fuzzy #~ msgid "Password to enter the room" #~ msgstr "Paroli roźniacca" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Niapravilnaja spasyłka" #~ msgid "Nickname:" #~ msgstr "Mianuška:" #~ msgid "Server:" #~ msgstr "Server:" #~ msgid "Password:" #~ msgstr "Parol:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Dałučajsia da hetaha pakoju aŭtamatyčna pry kožnym złučeńni" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Prahladaj" #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "Kiraŭnik žurnałaŭ" #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Kiraŭnik žurnałaŭ" #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "Aŭtamatyčnaje paviedamleńnie statusu \"Niedastupny\"" #, fuzzy #~ msgid "This contact does not support file transfer." #~ msgstr "Śpis dziejnych, skončanych i spynienych pieradačaŭ fajłaŭ" #~ msgid "" #~ "You have to install %s dictionary to use spellchecking, or choose another " #~ "language by setting the speller_language option." #~ msgstr "" #~ "Treba zainstalavać słoŭnik %s, kab praviarać pravapis, albo abrać inšuju " #~ "movu ŭ opcyi speller_language." #, fuzzy #~ msgid "Hides the buttons in chat windows." #~ msgstr "Chavaje knopki ŭ aknie pakoju." #, fuzzy #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Źmiani _mianušku" #, fuzzy #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "_Stvary zakładku dla hetaja pakoju" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Klikni, kab ustavić smajlik (Alt+M)" #, fuzzy #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Dadaje kantakt u śpis kantaktaŭ" #, fuzzy #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "sočyć za razmovaj" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Dadaje kantakt u śpis kantaktaŭ" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Dadaje kantakt u śpis kantaktaŭ" #, fuzzy #~ msgid "Ma_ke message windows compact" #~ msgstr "_Hrupuj vokny:" #, fuzzy #~ msgid "Hide all buttons in chat windows" #~ msgstr "Chavaje knopki ŭ aknie pakoju." #, fuzzy #~ msgid "Hide the chat buttons" #~ msgstr "Užyvańnie: /%s, chavaje knopki razmovy." #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "Kali opcyja maje vartaść True, Gajim budzie pytać avatary ŭ kožnaha " #~ "kantaktu, jaki nia mieŭ avatara byłym razam, albo kali buferavany avatar " #~ "sastareje." #, fuzzy #~ msgid "?CLI:room" #~ msgstr "pakoj" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "mianuška" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "parol" #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "Pakazvaj nahadvańni z dapamohaj DBus i Notification-Daemon" #, fuzzy #~ msgid "Notification" #~ msgstr "Madyfikacyja kontu" #, fuzzy #~ msgid "Ignore" #~ msgstr "dziaviataja" #~ msgid "_Open Gmail Inbox" #~ msgstr "_Adčyni poštu Gmail" #~ msgid "Notify on new _GMail email" #~ msgstr "Paviedamlaj mnie ab novych listach u skryni _Gmail" #, fuzzy #~ msgid "" #~ "If checked, Gajim will show a notification when a new e-mail is received " #~ "via GMail" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim taksama budzie paviedamlać " #~ "dadatkovyja źviestki pra aŭtaraŭ novych listoŭ" #~ msgid "Display _extra email details" #~ msgstr "Pakazvaj dadatkovyja _padrabiaznaści ab emaiłu" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim taksama budzie paviedamlać " #~ "dadatkovyja źviestki pra aŭtaraŭ novych listoŭ" #~ msgid "GMail Options" #~ msgstr "Opcyi GMail" #, fuzzy #~ msgid "20" #~ msgstr "0" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Dašli %s" #~ msgid "GMail Email Received" #~ msgstr "Novy list na skryncy GMail" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Novaja pošta ŭ skryncy %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "%d novy list" #~ msgstr[1] "%d novyja listy" #~ msgstr[2] "%d novych listoŭ" #~ msgid "Re_name" #~ msgstr "_Źmiani nazvu" #~ msgid "Resour_ce:" #~ msgstr "_Krynica:" #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "Nazva krynicy paviedamlajecca serveru, kab toj moh adroźnić niekalki " #~ "prahram, dałučanych da adnaho kontu. Tak ty možaš dałučycca da adnaho " #~ "kontu i z domu, i z pracy. Paviedamleńni buduć skiroŭvacca na krynicu z " #~ "najvyšejšym pryjarytetam. (hladzi nižej)" #, fuzzy #~ msgid "A_djust to status" #~ msgstr "_Dastasuj da statusu" #~ msgid "Priority will change automatically according to your status." #~ msgstr "Źmianiaj pryjarytet aŭtamatyčna zhodna z statusam." #, fuzzy #~ msgid "Anonymous authentication" #~ msgstr "Užyvaj aŭtaryzacyju" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "Pryjarytet vyznačaje, jakaja prahrama atrymvaje paviedamleńni z servera, " #~ "kali niekalki prahram dałučanyja praz adzin kont. Prahrama z najvyšejšym " #~ "pryjarytetam budzie atrymvać paviedamleńni" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Pakažy _adłučanyja kantakty" #~ msgid "Chan_ge Password" #~ msgstr "Ź_miani parol" #~ msgid "Click to change account's password" #~ msgstr "Klikni, kab źmianić parol dla kontu" #, fuzzy #~ msgid "Administration operations" #~ msgstr "Śpis administrataraŭ" #, fuzzy #~ msgid "Browse..." #~ msgstr "_Prahladaj" #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "[Hetaje paviedamleńnie zašyfravanaje]" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie aŭtamatyčna dałučacca da " #~ "servera praz hety kont" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Pakažy _adłučanyja kantakty" #~ msgid "Synch_ronize account status with global status" #~ msgstr "_Synchranizuj status kontu z glabalnym statusam" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, to źmieny glabalnaha statusu (z menu " #~ "ŭnizie śpisu kantaktaŭ) buduć upłyvać na status hetaha kontu" #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim zojmie dadatkovyja adrasy IP, kab " #~ "pieradača fajłaŭ było šparčejšym." #, fuzzy #~ msgid "Proxy" #~ msgstr "Ułaścivaści" #, fuzzy #~ msgid "Send _keep-alive packets" #~ msgstr "Dasyłaj pravieračnyja infarmacyjnyja pakiety" #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie dasyłać infarmacyjnyja " #~ "pakiety dziela zapeŭnivańnia servera ŭ tym, što złučeńnie " #~ "vykarystoŭvajecca" #, fuzzy #~ msgid "Use cust_om hostname/port" #~ msgstr "Skarystaj admysłovy host/port" #, fuzzy #~ msgid "_Hostname: " #~ msgstr "Nazva hosta: " #, fuzzy #~ msgid "_Port: " #~ msgstr "_Port:" #~ msgid "No key selected" #~ msgstr "Kluč nie abrany" #~ msgid "Choose _Key..." #~ msgstr "Abiary _kluč..." #, fuzzy #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim zapomnić parol dla hetaha kontu" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "_Edit Personal Information..." #~ msgstr "Źmiani asabistyja źviestki..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Źviestki pra ciabie, jakija zachoŭvajucca na servery" #~ msgid "Personal Information" #~ msgstr "Asabistyja źviestki" #, fuzzy #~ msgid "Co_nnect on Gajim startup" #~ msgstr "_Zlučajsia pry starcie Gajim" #, fuzzy #~ msgid "Synchroni_ze account status with global status" #~ msgstr "_Synchranizuj status kontu z glabalnym statusam" #, fuzzy #~ msgid "Use cust_om port:" #~ msgstr "Užyvaj admysłovy port:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Kali zvyčajny port dla ŭvachodnych paviedamleńniaŭ nie pasuje, možaš " #~ "vybrać inšy.\n" #~ "Taksama moža spatrebicca źmianić nałady firewalla." #~ msgid "Mer_ge accounts" #~ msgstr "_Źlej konty ŭ adno" #, fuzzy #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "Nielha vykarystać OpenPGP na hetym kamputary" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Kab źmianić nazvu kontu, treba pieradałučycca." #~ msgid "To change the account name, you must read all pending events." #~ msgstr "Kab źmianić nazvu kontu, treba pračytać usie novyja paviedamleńni." #~ msgid "Account Name Already Used" #~ msgstr "Taki kont užo zaniaty" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "Kont z takoj nazvaj užo zaniaty. Kali łaska, abiary inšuju nazvu." #~ msgid "Invalid account name" #~ msgstr "Niapravilnaja nazva kontu" #~ msgid "Account name cannot be empty." #~ msgstr "Nazva kontu nia moža być pustoj." #~ msgid "Account name cannot contain spaces." #~ msgstr "Nazva kontu nia moža ŭtrymlivać prabiełaŭ." #, fuzzy #~ msgid "Enter a new name for account %s" #~ msgstr "Vyznač novuju nazvu dla hrupy %s" #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "JID musić mieć formu \"user@servername\"." #~ msgid "No such account available" #~ msgstr "Takoha kontu niama" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "Treba stvaryć kont, kab redahavać asabistyja źviestki." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "" #~ "Nie złučyŭšysia z serveram, niemahčyma źmianiać asabistyja źviestki." #, fuzzy #~ msgid "Your server does not have vCard support" #~ msgstr "Server nie padtrymvaje Vcard" #~ msgid "Your server can't save your personal information." #~ msgstr "Server nia moža zachoŭvać asabistyja źviestki." #~ msgid "Account Local already exists." #~ msgstr "Kont Local užo isnuje." #~ msgid "Please rename or remove it before enabling link-local messaging." #~ msgstr "" #~ "Kali łaska, źmiani nazvu albo vydal jaho pierad uklučeńniem miascovych " #~ "paviedamleńniaŭ." #~ msgid "THANKS:" #~ msgstr "PADZIAKI:" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "Niemahčyma zapisać u %s. Kiravańnie sesijami nia budzie dziejničać" #~ msgid "Jabber Traffic" #~ msgstr "Trafik Jabber" #, fuzzy #~ msgid "_Enable" #~ msgstr "Ukluč" #, fuzzy #~ msgid "Filter" #~ msgstr "Huki" #~ msgid "_IQ" #~ msgstr "_IQ" #~ msgid "Info/Query" #~ msgstr "Źviestki/Apytańnie (Info/Query)" #~ msgid "_Message" #~ msgstr "_Paviedamleńnie" #~ msgid "XML Input" #~ msgstr "Uvod XML" #~ msgid "XML Console for %s" #~ msgstr "Kansol XML dla %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "Kansol XML dla %s" #~ msgid "Last status: %s" #~ msgstr "Apošni status: %s" #~ msgid " since %s" #~ msgstr " ad %s" #~ msgid "since %s" #~ msgstr "ad %s" #, fuzzy #~ msgid "No" #~ msgstr "Nijaki" #, fuzzy #~ msgid "Prefer" #~ msgstr "Nałady" #, fuzzy #~ msgid "Auto" #~ msgstr "Aŭtamatyčna dałučajsia" #, fuzzy #~ msgid "otr" #~ msgstr "_Host:" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Niapravilnaje imia karystalnika" #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "" #~ "Kolki chvilinaŭ z apošniaj razmovy zapaminać i pakazvać u znoŭ adčynienym " #~ "aknie." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Ty dałučyśsia da %s biaz OpenPGP." #, fuzzy #~ msgid "The following message was NOT encrypted" #~ msgstr "[Hetaje paviedamleńnie zašyfravanaje]" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Ci vykarystoŭvajecca šyfravańnie OpenPGP dla hetaha kantaktu?" #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Uklučy/Adklučy šyfravańnie Open_PGP" #, fuzzy #~ msgid "Toggle End to End Encryption" #~ msgstr "Uklučy/Adklučy šyfravańnie Open_PGP" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "Šyfravańnie ŭklučanaje" #, fuzzy #~ msgid "The following message was encrypted" #~ msgstr "[Hetaje paviedamleńnie zašyfravanaje]" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Uklučy/Adklučy šyfravańnie Open_PGP" #, fuzzy #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Hetaje paviedamleńnie *zašyfravanaje* (Hladzi :JEP:`27`]" #~ msgid "" #~ "If True, listen to D-Bus signals from NetworkManager and change the " #~ "status of accounts (provided they do not have listen_to_network_manager " #~ "set to False and they sync with global status) based upon the status of " #~ "the network connection." #~ msgstr "" #~ "Kali hetaja opcyja maje vartaść True, čakaj syhnałaŭ D-Bus ad " #~ "NetworkManager i źmianiaj status kontaŭ (dla jakich opcyja " #~ "listen_to_network_manager nia maje vartaści False i jakija " #~ "synchranizujucca z hlabalnym stanam) zhodna statusu sietkavaha złučeńnia." #, fuzzy #~ msgid "Database cannot be read." #~ msgstr "Nazva kontu nia moža być pustoj." #, fuzzy #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Dašli paviedamleńnie i začyni akno" #~ msgid "Show _XML Console" #~ msgstr "Pakažy _kansol XML" #, fuzzy #~ msgid "Edit _Privacy Lists..." #~ msgstr "_Śpisy pryvatnaści" #~ msgid "_Administrator" #~ msgstr "_Administratar" #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "Dašli paviedamleńnie karystalnikam, dałučanym da servera" #~ msgid "Sets Message of the Day" #~ msgstr "Vyznač paviedamleńnie dniu" #~ msgid "Updates Message of the Day" #~ msgstr "Aktualizuj paviedamleńnie dniu" #~ msgid "Deletes Message of the Day" #~ msgstr "Vydal paviedamleńnie dniu" #, fuzzy #~ msgid "Add _Contact..." #~ msgstr "_Dadaj kantakt..." #, fuzzy #~ msgid "_Accounts" #~ msgstr "Konty" #~ msgid "Profile, A_vatar" #~ msgstr "Profil, a_vatar" #~ msgid "File _Transfers" #~ msgstr "Pieradačy _fajłaŭ" #~ msgid "Help online" #~ msgstr "Dapamoha online" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Častyja pytańni (online)" #, fuzzy #~ msgid "Fea_tures" #~ msgstr "Zdolnaści serveraŭ" #~ msgid "to %s account" #~ msgstr "da kontu %s" #~ msgid "using %s account" #~ msgstr "praz kont %s" #~ msgid "of account %s" #~ msgstr "kontu %s" #~ msgid "for account %s" #~ msgstr "dla kontu %s" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Vydaliŭšy hety kantakt, ty taksama anuluješ jahonuju aŭtaryzacyju. U " #~ "vyniku jon zaŭsiody budzie bačyć ciabie adłučanym." #~ msgid "Invalid Jabber ID" #~ msgstr "Niapravilny JID" #~ msgid "This file is being used by another process." #~ msgstr "Hety fajł vykarystoŭvajecca inšym pracesam." #~ msgid "pgp key" #~ msgstr "kluč pgp" #~ msgid "" #~ "Sends new single message to a contact in the roster. Both OpenPGP key and " #~ "account are optional. If you want to set only 'account', without 'OpenPGP " #~ "key', just set 'OpenPGP key' to ''." #~ msgstr "" #~ "Dasyłaje novaje asobnaje paviedamleńnie kantaktu sa śpisu kantaktaŭ. Kluč " #~ "OpenPGP i kont nie abaviazkovyja dla akreśleńnia. Kali chočaš akreślić " #~ "tolki 'kont', biez 'kluča OpenPGP', tady prosta akreśli 'kluč OpenPGP' " #~ "jak ''." #, fuzzy #~ msgid "Please first choose another theme as your current theme." #~ msgstr "Kali łaska, zadziejničaj spačatku inšuju temu." #~ msgid "Your passphrase is incorrect" #~ msgstr "Parol niapravilny" #, fuzzy #~ msgid "OpenPGP Passphrase Incorrect" #~ msgstr "Parol niapravilny" #~ msgid "You successfully received %(filename)s from %(name)s." #~ msgstr "Atrymany fajł %(filename)s ad %(name)s." #, fuzzy #~ msgid "Set logs directory" #~ msgstr "stvarajecca kataloh %s" #~ msgid "Chats" #~ msgstr "Razmovy" #~ msgid "_Manage Bookmarks..." #~ msgstr "_Kiruj zakładkami..." #~ msgid "Change Status Message..." #~ msgstr "Źmiani paviedamleńnie statusu..." #~ msgid "_Change Status Message..." #~ msgstr "Ź_miani paviedamleńnie statusu..." #~ msgid "" #~ "You are not interested in the contact's presence, and neither he/she is " #~ "interested in yours" #~ msgstr "Ty i hety kantakt nie cikaviciesia statusam adno adnaho" #~ msgid "Error description..." #~ msgstr "Apisańnie pamyłki..." #, fuzzy #~ msgid "View contact information (Ctrl+I)" #~ msgstr "sočyć za razmovaj" #, fuzzy #~ msgid "Groupchat Histories" #~ msgstr "Pakoji" #, fuzzy #~ msgid "All Chat Histories" #~ msgstr "Старыя казкі" #~ msgid "More" #~ msgstr "Bolš" #~ msgid "creating %s directory" #~ msgstr "stvarajecca kataloh %s" #, fuzzy #~ msgid "" #~ "If True, Gajim will use KDE Wallet (if kwalletcli is available) to store " #~ "account passwords." #~ msgstr "" #~ "Kali opcyja maje vartaść True, Gajim budzie zachoŭvać paroli z dapamohaj " #~ "Kiraŭnika parolaŭ GNOME (kali jość mahčymaść)." #~ msgid "%s is not the name of a group chat." #~ msgstr "Naźvie %s nie adpaviadaje nivodny pakoj." #, fuzzy #~ msgid "Session Management" #~ msgstr "Paviedamleńnie dasłanaje" #~ msgid "Gajim needs X server to run. Quiting..." #~ msgstr "Gajimu patrebny X-server. Vychad..." #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above" #~ msgstr "Gajimu treba PyGTK 2.6 albo paźniejšaj versii" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above to run. Quiting..." #~ msgstr "Gajimu treba PyGTK 2.6 albo paźniejšaj versii. Vychad..." #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above" #~ msgstr "Gajimu treba GTK 2.6 albo paźniejšaj versii" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above to run. Quiting..." #~ msgstr "Gajimu treba GTK 2.6 albo paźniejšaj versii. Vychad..." #~ msgid "Gajim needs pywin32 to run" #~ msgstr "Gajimu treba pywin32" #~ msgid "" #~ "Please make sure that Pywin32 is installed on your system. You can get it " #~ "at %s" #~ msgstr "" #~ "kali łaska, pravier, ci instalavanaja biblijateka Pywin32. Jaje možna " #~ "ściahnuć z %s" #~ msgid "Gajim is already running" #~ msgstr "Gajim užo vykonvajecca" #~ msgid "" #~ "Another instance of Gajim seems to be running\n" #~ "Run anyway?" #~ msgstr "" #~ "Gajim užo vykonvajecca\n" #~ "Usio adno ŭruchomić?" #~ msgid "A programming error has been detected" #~ msgstr "Znojdziena pamyłka prahramistaŭ" #~ msgid "Details" #~ msgstr "Padrabiaznaści" #, fuzzy #~ msgid "" #~ "Gnome Keyring is installed but not correctly started (environment " #~ "variable probably not correctly set)" #~ msgstr "" #~ "Kiraŭnik parolaŭ GNOME instalavany, ale niapravilna vykonvajecca " #~ "(mahčyma, źmiennaja asiarodździa niapravilna akreślenaja)" #~ msgid "Jabber ID: " #~ msgstr "JID:" #~ msgid "Resource: " #~ msgstr "Krynica: " #~ msgid "Subscription: " #~ msgstr "Aŭtaryzacyja: " #, fuzzy #~ msgid "Mood: " #~ msgstr "Pakoj:" #, fuzzy #~ msgid "Activity: " #~ msgstr "Dziejny" #, fuzzy #~ msgid "Join _Group Chat..." #~ msgstr "Dałučysia da _pakoju" #, fuzzy #~ msgid "_Modify Account" #~ msgstr "Madyfikuj kont" #, fuzzy #~ msgid "Check on startup if Gajim is the _default Jabber client" #~ msgstr "" #~ "Zaŭsiody pry starcie praviaraj, ci pryznačany Gajim _zmoŭčanym klijentam " #~ "Jabber" #~ msgid "_Group Chat" #~ msgstr "_Pakoj" #~ msgid "" #~ "If True, Gajim will check if it's the default jabber client on each " #~ "startup." #~ msgstr "" #~ "Kali opcyja maje vartaść True, Gajim budzie praviarać, ci akreśleny jon " #~ "jak zmoŭčany klijent Jabber." #~ msgid "Gajim is not the default Jabber client" #~ msgstr "Gajim nie akreśleny jak zmoŭčany klijent Jabber" #~ msgid "Would you like to make Gajim the default Jabber client?" #~ msgstr "Chočaš zrabić Gajim zmoŭčanym klijentam Jabber?" #~ msgid "Always check to see if Gajim is the default Jabber client on startup" #~ msgstr "Zaŭsiody praviaraj, ci akreśleny Gajim jak zmoŭčany klijent Jabber" #, fuzzy #~ msgid "Send Single Message" #~ msgstr "_Dašli asobnaje paviedamleńnie" #~ msgid "Execute Command..." #~ msgstr "Vykanaj zahad..." #~ msgid " a window/tab opened with that contact " #~ msgstr " akno/kartka razmovy z hetym kantaktam adčynienaja " #~ msgid "Actions" #~ msgstr "Dziejańni" #~ msgid "Conditions" #~ msgstr "Umovy" #~ msgid "Advanced Actions" #~ msgstr "Admysłovyja dziejańni" #~ msgid "Advanced Notifications Control" #~ msgstr "Pašyranyja nałady nahadvańnia" #~ msgid "Busy " #~ msgstr "Zaniaty" #, fuzzy #~ msgid "Contact Change Status " #~ msgstr "Kantakt źmianiŭ status" #~ msgid "Don't have " #~ msgstr "Razmaŭlaju " #, fuzzy #~ msgid "File Transfer Started " #~ msgstr "Pieradača fajłu spyniena" #, fuzzy #~ msgid "Group Chat Message Highlight " #~ msgstr "Padśviatleńnie paviedamleńnia ŭ pakoji" #, fuzzy #~ msgid "Group Chat Message Received " #~ msgstr "Novaje paviedamleńnie ŭ pakoji" #~ msgid "Launch a command" #~ msgstr "Vykanaj zahad" #~ msgid "One or more special statuses..." #~ msgstr "Adzin ci niekalki admysłovych statusaŭ..." #~ msgid "Online / Free For Chat" #~ msgstr "Dałučany / Achvotna parazmaŭlaju" #~ msgid "Play a sound" #~ msgstr "Ahuč" #~ msgid "When " #~ msgstr "Kali " #~ msgid "" #~ "_Activate window manager's UrgencyHint to make chat window in taskbar " #~ "flash" #~ msgstr "_Mirgaj vyjavaj na paneli zadańniaŭ" #~ msgid "_Disable auto opening chat window" #~ msgstr "_Nie adčyniaj aŭtamatyčna voknaŭ razmovy" #~ msgid "_Disable existing popup window" #~ msgstr "_Nie pakazvaj vypłyŭnych voknaŭ" #~ msgid "_Disable existing sound for this event" #~ msgstr "_Nie ahučvaj hetaj padzieji" #, fuzzy #~ msgid "_Disable showing event in notification area" #~ msgstr "_Nie pakazvać paviedamleńniaŭ u śpisie kantaktaŭ" #~ msgid "_Disable showing event in roster" #~ msgstr "_Nie pakazvać paviedamleńniaŭ u śpisie kantaktaŭ" #~ msgid "_Inform me with a popup window" #~ msgstr "_Paviedam mnie ŭ vypłyŭnym aknie" #~ msgid "_Open chat window with user" #~ msgstr "_Adčyni akno razmovy z karystalnikam" #~ msgid "_Show event in roster" #~ msgstr "_Pakazvaj padzieju ŭ śpisie kantaktaŭ" #~ msgid "and I " #~ msgstr "u časie, kali " #, fuzzy #~ msgid "contact(s)" #~ msgstr "Kantakty" #~ msgid "for " #~ msgstr "dla " #, fuzzy #~ msgid "group(s)" #~ msgstr "Hrupa" #~ msgid "when I'm in" #~ msgstr "kali maju " #~ msgid "_Allow him/her to see my status" #~ msgstr "Dazvol jamu/joj _bačyć moj status" #, fuzzy #~ msgid "Descrition:" #~ msgstr "Apisańnie: %s" #, fuzzy #~ msgid "Advanced..." #~ msgstr "Pašyranyja" #, fuzzy #~ msgid "Display _activity of contacts in roster" #~ msgstr "Pakazvaj a_vatary kantaktaŭ u śpisie kantaktaŭ" #, fuzzy #~ msgid "Display _tunes of contacts in roster" #~ msgstr "Pakazvaj a_vatary kantaktaŭ u śpisie kantaktaŭ" #, fuzzy #~ msgid "Display m_ood of contacts in roster" #~ msgstr "Pakazvaj a_vatary kantaktaŭ u śpisie kantaktaŭ" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the activity of contacts in the roster " #~ "window" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać avatary kantaktaŭ u " #~ "śpisie kantaktaŭ i ŭ pakojach" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the location of contacts in the roster " #~ "window" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać avatary kantaktaŭ u " #~ "śpisie kantaktaŭ i ŭ pakojach" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the tunes of contacts in the roster window" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie pakazvać avatary kantaktaŭ u " #~ "śpisie kantaktaŭ i ŭ pakojach" #~ msgid "Gajim Instant Messenger" #~ msgstr "Kamunikatar Gajim" #~ msgid "English" #~ msgstr "Anhielskaja" #~ msgid "Belarusian" #~ msgstr "Biełaruskaja" #~ msgid "Bulgarian" #~ msgstr "Baŭharskaja" #, fuzzy #~ msgid "Breton" #~ msgstr "Brytonskaja" #~ msgid "Czech" #~ msgstr "Českaja" #~ msgid "German" #~ msgstr "Niamieckaja" #~ msgid "Greek" #~ msgstr "Hreckaja" #~ msgid "British" #~ msgstr "Brytanskaja" #~ msgid "Esperanto" #~ msgstr "Esperanto" #~ msgid "Spanish" #~ msgstr "Hišpanskaja" #~ msgid "French" #~ msgstr "Francuzkaja" #~ msgid "Croatian" #~ msgstr "Charvackaja" #~ msgid "Italian" #~ msgstr "Italijskaja" #~ msgid "Norwegian (b)" #~ msgstr "Narveskaja (b)" #~ msgid "Dutch" #~ msgstr "Halandzkaja" #~ msgid "Norwegian" #~ msgstr "Narveskaja" #~ msgid "Polish" #~ msgstr "Polskaja" #~ msgid "Portuguese" #~ msgstr "Partuhalskaja" #~ msgid "Brazilian Portuguese" #~ msgstr "Brazilskaja partuhalskaja" #~ msgid "Russian" #~ msgstr "Rasiejskaja" #~ msgid "Serbian" #~ msgstr "Serbskaja" #~ msgid "Slovak" #~ msgstr "Słavackaja" #~ msgid "Swedish" #~ msgstr "Švedzkaja" #~ msgid "Chinese (Ch)" #~ msgstr "Kitajskaja (Ch)" #~ msgid "Spelling language" #~ msgstr "Mova spraŭdžvańnia pravapisu" #~ msgid "all or space separated status" #~ msgstr "\"all\" albo statusy, padzielenyja prabiełami" #~ msgid "'yes', 'no', or 'both'" #~ msgstr "'yes', 'no' albo 'both'" #~ msgid "'yes', 'no' or ''" #~ msgstr "'yes', 'no' albo ''" #~ msgid "Check your connection or try again later" #~ msgstr "Pravier złučeńnie albo paŭtary paźniej" #~ msgid "error: cannot open %s for reading" #~ msgstr "pamyłka: niemahčyma adčynić %s, kab adčytać" #~ msgid "Unable to bind to port %s." #~ msgstr "Niemahčyma dałučycca da portu %s." #~ msgid "" #~ "Maybe you have another running instance of Gajim. File Transfer will be " #~ "cancelled." #~ msgstr "" #~ "Mahčyma, inšaja kopija Gajim užo vykonvajecca. Pieradača fajłaŭ " #~ "anulavanaja." #~ msgid "A GTK+ jabber client" #~ msgstr "Jabber-klijent dla GTK+" #~ msgid "Condition" #~ msgstr "Umova" #~ msgid "when I am " #~ msgstr "kali maju " #, fuzzy #~ msgid "one of: offline, online, chat, away, xa, dnd, invisible " #~ msgstr "adno z: offline, online, chat, away, xa, dnd, invisible " #, fuzzy #~ msgid "" #~ "Returns current status message(the global one unless account is specified)" #~ msgstr "" #~ "Viartaje dziejnaje paviedamleńnie statusu (hlabalnaha, kali nie akreśleny " #~ "kont)" #~ msgid "" #~ "Usage: %s %s %s \n" #~ "\t %s" #~ msgstr "" #~ "Užyvańnie: %s %s %s \n" #~ "\t %s" #, fuzzy #~ msgid "" #~ "Too many arguments. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Nadta šmat arhumentaŭ. \n" #~ "Vykanaj \"%s help %s\" dla padrabiaźniejšych źviestak" #, fuzzy #~ msgid "" #~ "Argument \"%s\" is not specified. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Arhument \"%s\" nie akreśleny. \n" #~ "Vykanaj \"%s help %s\" dla padrabiaźniejšych źviestak" #~ msgid "Subject: %s" #~ msgstr "Tema: %s" #, fuzzy #~ msgid "Mood: %s" #~ msgstr "Pakoj:" #, fuzzy #~ msgid "Activity: %s" #~ msgstr "Dziejny" #~ msgid "_Disable showing event in systray" #~ msgstr "_Nie pakazvać padziejaŭ u poli nahadvańnia" #~ msgid "_Show event in systray" #~ msgstr "_Pakazvaj padzieju ŭ poli nahadvańnia" #, fuzzy #~ msgid "Autodetect on every Gajim startup" #~ msgstr "_Zlučajsia pry starcie Gajim" #, fuzzy #~ msgid "Show systray:" #~ msgstr "_Pakazvaj padzieju ŭ poli nahadvańnia" #~ msgid "Nickname not allowed: %s" #~ msgstr "Mianuška nie dazvolenaja: %s" #~ msgid "we are now subscribed to %s" #~ msgstr "padpisany na %s" #~ msgid "we are now unsubscribed from %s" #~ msgstr "ciapier adpisany ad %s" #~ msgid "Account Modification" #~ msgstr "Madyfikacyja kontu" #~ msgid "" #~ "Check this so Gajim will connect in port 5223 where legacy servers are " #~ "expected to have SSL capabilities. Note that Gajim uses TLS encryption by " #~ "default if broadcasted by the server, and with this option enabled TLS " #~ "will be disabled" #~ msgstr "" #~ "Paznač hetuju opcyju, kali chočaš, kab Gajim złučaŭsia z serveram praz " #~ "port 5223, praź jaki staryja servery dajuć mažlivaść vykarystańnia SSL. " #~ "Zvažaj: Gajim zvyčajna vykarystoŭvaje šyfravańnie TLS, kali źviartajecca " #~ "da servera, a hetaja opcyja adklučaje vykarystańnie TLS" #~ msgid "Edit Personal Information..." #~ msgstr "Źmiani asabistyja źviestki..." #~ msgid "Hostname: " #~ msgstr "Nazva hosta: " #~ msgid "" #~ "If checked, Gajim will store the password in ~/.gajim/config with 'read' " #~ "permission only for you" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie zachoŭvać parol u fajle ~/." #~ "gajim/config z pravami na čytańnie tolki dla ciabie" #~ msgid "Port: " #~ msgstr "Port: " #~ msgid "Save _passphrase (insecure)" #~ msgstr "Zachavaj _parol (niebiaśpiečna)" #~ msgid "Use _SSL (legacy)" #~ msgstr "Skarystaj _SSL (zastarełaja opcyja)" #~ msgid "" #~ "Receive a Message\n" #~ "Contact Disconnected \n" #~ "Contact Change Status \n" #~ "Group Chat Message Highlight \n" #~ "Group Chat Message Received \n" #~ "File Transfer Request \n" #~ "File Transfer Started \n" #~ "File Transfer Finished" #~ msgstr "" #~ "Atrymaŭ paviedamleńnie\n" #~ "Kantakt adłučyŭsia \n" #~ "Kantakt źmianiŭ status \n" #~ "Padśvietlenaje paviedamleńnie ŭ hrupavoj razmovie \n" #~ "Atrymaŭ hrupavoje paviedamleńnie \n" #~ "Zapyt na pieradaču fajłu \n" #~ "Pieradača fajłu pačałosia \n" #~ "Pieradača fajłu skončyłasia" #~ msgid "" #~ "contact(s)\n" #~ "group(s)\n" #~ "everybody" #~ msgstr "" #~ "kantakt(y)\n" #~ "hrupa(y)\n" #~ "kožny" #~ msgid "" #~ "Account row\n" #~ "Group row\n" #~ "Contact row\n" #~ "Chat Banner" #~ msgstr "" #~ "Kont\n" #~ "Hrupa\n" #~ "Kantakt\n" #~ "Baner" #, fuzzy #~ msgid "gtk-delete" #~ msgstr "Vydal" #~ msgid "" #~ "All chat states\n" #~ "Composing only\n" #~ "Disabled" #~ msgstr "" #~ "Usie stany razmovy\n" #~ "Tolki datyčnyja pisańnia\n" #~ "Adklučana" #, fuzzy #~ msgid "" #~ "Autodetect on every Gajim startup\n" #~ "Always use GNOME default applications\n" #~ "Always use KDE default applications\n" #~ "Always use Xfce default applications\n" #~ "Custom" #~ msgstr "" #~ "Aŭtamatyčna vyznačać pry kožnym starcie Gajim\n" #~ "Zaŭsiody karystacca prahramami, pryznačanymi dla GNOME\n" #~ "Zaŭsiody karystacca prahramami, pryznačanymi dla KDE\n" #~ "Inšyja" #~ msgid "" #~ "none\n" #~ "both\n" #~ "from\n" #~ "to" #~ msgstr "" #~ "niama\n" #~ "abiedźvie\n" #~ "ad\n" #~ "da" #, fuzzy #~ msgid "gtk-cancel" #~ msgstr "Vydal" #~ msgid "pysqlite2 (aka python-pysqlite2) dependency is missing. Exiting..." #~ msgstr "Nie staje pysqlite2 (python-pysqlite2) dla vykananaja. Vychad..." #~ msgid "GTK+ runtime is missing libglade support" #~ msgstr "Biblijateka GTK+ nie padtrymvaje libglade" #~ msgid "" #~ "Please remove your current GTK+ runtime and install the latest stable " #~ "version from %s" #~ msgstr "" #~ "Kali łaska, vydal biblijateku GTK+ i zainstaluj najnoŭšuju stabilnuju " #~ "versiju z %s" #~ msgid "" #~ "Please make sure that GTK+ and PyGTK have libglade support in your system." #~ msgstr "" #~ "Kali łaska, pravier, ci padtrymvajuć srodki libpango biblijateki GTK+ i " #~ "PyGTK." #~ msgid "Gajim needs PySQLite2 to run" #~ msgstr "Gajimu treba PySQLite2" #, fuzzy #~ msgid "gtk-ok" #~ msgstr "gtk+" #, fuzzy #~ msgid "" #~ "The host %s you configured as the ft_add_hosts_to_send advanced option is " #~ "not valid, so ignored." #~ msgstr "" #~ "Host, akreśleny ŭ opcyi ft_override_host_to_send, niapravilny, tamu " #~ "ihnarujecca." #~ msgid "OpenPGP passphrase was not given" #~ msgstr "Parol OpenPGP nia vyznačany" #~ msgid "" #~ "To continue sending and receiving messages, you will need to reconnect." #~ msgstr "Kab paciahnuć kamunikacyju, treba ŭruchomić Gajim nanoŭ." #~ msgid "" #~ "You are not connected or not visible to others. Your message could not be " #~ "sent." #~ msgstr "Ty nie dałučany albo niebačny. Ty nia možaš dasyłać paviedamleńni." #~ msgid "Add Special _Notification" #~ msgstr "Dadaj admysłovaje _nahadvańnie" #~ msgid "Assign Open_PGP Key" #~ msgstr "Pryznač kluč Open_PGP" #~ msgid "Commands: %s" #~ msgstr "Zahady: %s" #, fuzzy #~ msgid "" #~ "Usage: /%(command)s , sends action to the current group chat. Use " #~ "third person. (e.g. /%(command)s explodes.)" #~ msgstr "" #~ "Užyvańnie: /%s , dasyłaje dziejańnie ŭ dziejny pakoj (ad " #~ "treciaj asoby). (naprykład, /%s rahoča, jak koń.)" #~ msgid "No help info for /%s" #~ msgstr "Niama daviedki pa /%s" #~ msgid "Enable link-local/zeroconf messaging" #~ msgstr "Uklučy lakalnyja paviedamleńni praz Zeroconf" #~ msgid "Nickname not found: %s" #~ msgstr "Mianuška nia znojdziena: %s" #~ msgid "This group chat has no subject" #~ msgstr "Dla hetaha pakoju nie akreślena tema" #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], bans the JID from the group chat. The " #~ "nickname of an occupant may be substituted, but not if it contains \"@\". " #~ "If the JID is currently in the group chat, he/she/it will also be kicked." #~ msgstr "" #~ "Užyvańnie: /%s [pryčyna], blakuje JID dla pakoju. Mianušku " #~ "možna źmianić, kali jana nia ŭtrymlivaje znaka \"@\". Kali JID jašče " #~ "znachodzicca ŭ pakoji, jon budzie vypchnuty preč. Prabieły ŭ mianuškach " #~ "nie padtrymvajucca." #~ msgid "" #~ "Usage: /%s [reason], closes the current window or tab, displaying reason " #~ "if specified." #~ msgstr "" #~ "Užyvańnie: /%s [pryčyna], začyniaje dziejnaje akno albo kartku, pakazaŭšy " #~ "akreślenuju pryčynu." #~ msgid "" #~ "Usage: /%s [reason], invites JID to the current group chat, " #~ "optionally providing a reason." #~ msgstr "" #~ "Užyvańnie: /%s [pryčyna], zaprašaje JID u dziejny pakoj, z " #~ "akreślenym tłumačeńniem." #~ msgid "" #~ "Usage: /%s @[/nickname], offers to join room@server " #~ "optionally using specified nickname." #~ msgstr "" #~ "Užyvańnie: /%s @[/mianuška], dałučajecca da pakoju " #~ "pakoj@server z akreślenaj mianuškaj." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], removes the occupant specified by " #~ "nickname from the group chat and optionally displays a reason." #~ msgstr "" #~ "Užyvańnie: /%s [pryčyna], vypichvaje asobu z takoj mianuškaj z " #~ "pakoju z akreślenaj pryčynaj. Prabieły ŭ mianuškach nie padtrymvajucca." #~ msgid "" #~ "Usage: /%s [message], opens a private message window and sends " #~ "message to the occupant specified by nickname." #~ msgstr "" #~ "Užyvańnie: /%s [paviedamleńnie], adčyniaje akno pryvatnaj " #~ "razmovy i dasyłaje paviedamleńnie asobie z akreślenaj mianuškaj." #~ msgid "Usage: /%s , changes your nickname in current group chat." #~ msgstr "" #~ "Užyvańnie: /%s , źmianiaje tvaju mianušku dla dziejnaja pakoju." #~ msgid "" #~ "Usage: /%s [topic], displays or updates the current group chat topic." #~ msgstr "" #~ "Užyvańnie: /%s [tema], pakazvaje albo aktualizuje dziejnuju temu pakoju." #~ msgid "" #~ "Usage: /%s , sends a message without looking for other commands." #~ msgstr "" #~ "Užyvańnie: /%s , dasyłaje paviedamleńnie, nie šukajučy " #~ "inšych zahadaŭ." #, fuzzy #~ msgid "" #~ "Usage: /%s , allow to send you messages and private " #~ "messages." #~ msgstr "" #~ "Užyvańnie: /%s , źmianiaje tvaju mianušku dla dziejnaja pakoju." #~ msgid "Click to see features (like MSN, ICQ transports) of jabber servers" #~ msgstr "" #~ "Pstykni, kab pahladzieć zdolnaści serveraŭ Jabber (naprykład, šluzy MSN, " #~ "ICQ)" #~ msgid "Name:" #~ msgstr "Nazva:" #~ msgid "_Host:" #~ msgstr "_Host:" #~ msgid "Modify Account" #~ msgstr "Madyfikuj kont" #, fuzzy #~ msgid "" #~ "%(title)s by %(artist)s\n" #~ "from %(source)s" #~ msgstr "\"%(title)s\" ŭ vykanańni %(artist)s" #~ msgid "Gajim account %s" #~ msgstr "Kont Gajim %s" #~ msgid "This account is already configured in Gajim." #~ msgstr "Hety kont užo naładžany dla Gajim." #, fuzzy #~ msgid "Idle" #~ msgstr "Identyfikatar" #~ msgid "File transfer stopped by the contact at the other end" #~ msgstr "Pieradača fajłu spyniena inšym bokam" #, fuzzy #~ msgid "Generic" #~ msgstr "Ahulnaja" #~ msgid "%s has not broadcast an OpenPGP key, nor has one been assigned" #~ msgstr "" #~ "%s nie dasłaŭ svajho kluča OpenPGP, a ty taksama nie pryznačyŭ na jaho " #~ "kluča" #~ msgid "No such command: /%s (if you want to send this, prefix it with /say)" #~ msgstr "" #~ "Takoha zahadu niama: /%s (kali chočaš dasłać hety tekst jak " #~ "paviedamleńnie, ustaŭ pierad im \"/say\")" #~ msgid "" #~ "Usage: /%s , sends action to the current group chat. Use third " #~ "person. (e.g. /%s explodes.)" #~ msgstr "" #~ "Užyvańnie: /%s , dasyłaje dziejańnie ŭ dziejny pakoj (ad " #~ "treciaj asoby). (naprykład, /%s rahoča, jak koń.)" #~ msgid "_Retype Password:" #~ msgstr "Paŭta_ry parol:" #~ msgid "" #~ "If checked, all local contacts that use a Bonjour compatible chat client " #~ "(like iChat, Trillian or Gaim) will be shown in roster. You don't need to " #~ "be connected to a jabber server for it to work.\n" #~ "This is only available if python-avahi is installed and avahi-daemon is " #~ "running." #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, usie lakalnyja kantakty, jakija " #~ "karystajucca prahramaj z zdolnaściami pratakołu Bonjour (naprykład, " #~ "iChat, Trillian, Gaim), buduć pakazanyja ŭ śpisie kantaktaŭ. Dla hetaha " #~ "tabie nia treba navat złučacca z serveram Jabber.\n" #~ "Hetaja zdolnaść budzie pracavać tolki z ustalavanym python-avahi i " #~ "servisam avahi-daemon." #~ msgid "" #~ "If you have 2 or more accounts and this is checked, Gajim will list all " #~ "contacts as if you had one account" #~ msgstr "" #~ "Kali ŭ ciabie niekalki kontaŭ, Gajim budzie pakazvać usie kantakty ŭ " #~ "adzinym śpisie" #~ msgid "_Enable link-local messaging" #~ msgstr "_Uklučy miascovyja paviedamleńni" #~ msgid "_Compact View Alt+C" #~ msgstr "_Kampaktny vyhlad Alt+K" #~ msgid "Click to see past conversation in this room" #~ msgstr "Klikni, kab pahladzieć tekst minułych razmoŭ u hetym pakoji" #~ msgid "Build custom query" #~ msgstr "Stvary admysłovy zapyt" #~ msgid "Query Builder..." #~ msgstr "Stvaralnik zapytaŭ..." #~ msgid "Invitation Received" #~ msgstr "Atrymanaje zaprašeńnie" #~ msgid "Format of a line" #~ msgstr "Farmat radka" #~ msgid "Interface Customization" #~ msgstr "Asabistaja kanfihuracyja interfejsu" #~ msgid "Also known as iChat style" #~ msgstr "Taksama viadomy jak styl iChat" #~ msgid "" #~ "An example: If you have enabled status message for away, Gajim won't ask " #~ "you anymore for a status message when you change your status to away; it " #~ "will use the default one set here" #~ msgstr "" #~ "Naprykład, kali ty ŭžo ŭklučyŭ paviedamleńnie statusu dla stany Adyjšoŭ, " #~ "tady Gajim bolš nia budzie pytacca paćvierdžańnia hetaha tekstu" #~ msgid "" #~ "Determined by sender\n" #~ "Chat message\n" #~ "Single message" #~ msgstr "" #~ "Vyznačaje adpraŭnik\n" #~ "Razmova\n" #~ "Asobnaje paviedamleńnie" #~ msgid "E_very 5 minutes" #~ msgstr "_Kožnyja 5 chvilinaŭ" #, fuzzy #~ msgid "" #~ "Gajim will automatically show new events by popping up the relevant window" #~ msgstr "" #~ "Gajim budzie aŭtamatyčna pakazvać novyja paviedamleńni ŭ adpaviednym aknie" #~ msgid "" #~ "Gajim will notify you for new events via a popup in the bottom right of " #~ "the screen" #~ msgstr "" #~ "Gajim budzie nahadvać ab novych padziejach u vypłyŭnym aknie ŭ pravym " #~ "nižnim kucie ekranu" #~ msgid "" #~ "Gajim will notify you via a popup window in the bottom right of the " #~ "screen about contacts that just signed in" #~ msgstr "" #~ "Gajim budzie paviedamlać ab dałučeńni kantaktaŭ da servera ŭ pravym " #~ "nižnim kucie ekranu" #~ msgid "" #~ "Gajim will only change the icon of the contact that triggered the new " #~ "event" #~ msgstr "Gajim tolki źmienić ikonu kantakta, jaki ŭčyniŭ novuju padzieju" #~ msgid "" #~ "If checked, Gajim will remember the roster and chat window positions in " #~ "the screen and the sizes of them next time you run it" #~ msgstr "" #~ "Kali ŭklučanaja hetaja opcyja, Gajim budzie zapaminać pazycyju i pamiery " #~ "śpisu kantaktaŭ i voknaŭ razmoŭ i adnaŭlać ich pry nastupnym starcie" #~ msgid "" #~ "Never\n" #~ "Always\n" #~ "Per account\n" #~ "Per type" #~ msgstr "" #~ "Nikoli\n" #~ "Zaŭsiody\n" #~ "Dla kožnaha konta\n" #~ "Dla kožnaha typu" #~ msgid "Outgoing Chat state noti_fications:" #~ msgstr "Vysyłańnie paviedamleńnia ab stanie _razmovy:" #~ msgid "Print time:" #~ msgstr "Pakazvaj čas:" #~ msgid "Save _position and size for roster and chat windows" #~ msgstr "Zachoŭvaj _pazycyju i pamiery śpisu kantaktaŭ i voknaŭ razmovy" #~ msgid "Set status message to reflect currently playing _music track" #~ msgstr "" #~ "Vystaŭlaj paviedamleńnie statusu jak nazvu hranaj _muzyčnaj kampazycyi" #~ msgid "The auto away status message" #~ msgstr "Aŭtamatyčnaje paviedamleńnie statusu \"Adyjšoŭ\"" #~ msgid "Treat all incoming messages as:" #~ msgstr "Traktuj usie ŭvachodnyja paviedamleńni jak:" #~ msgid "" #~ "When a new event (message, file transfer request etc..) is received, the " #~ "following methods may be used to inform you about it. Please note that " #~ "events about new messages only occur if it is a new message from a " #~ "contact you are not already chatting with" #~ msgstr "" #~ "Mahčymyja nastupnyja varyjanty nahadvańnia ab ździajśnieńni novych " #~ "padziejaŭ (ab paviedamleńniach, zapytach na pieradaču fajłaŭ i h.d.). " #~ "Zvažaj, što atrymańnie novaha paviedamleńnia adbyvajecca tolki tady, kali " #~ "ty atrymvaješ paviedamleńnie ad kantakta, ź jakim jašče na toj momant nia " #~ "vioŭ razmovy" #~ msgid "" #~ "Works for Rhythmbox and Muine players. For more players, please visit " #~ "http://trac.gajim.org/wiki/GajimAndMusicPlayer" #~ msgstr "" #~ "Pracuje dla Rhythmbox i Muine. Dla inšych prahram hladzicie staronku " #~ "http://trac.gajim.org/wiki/GajimAndMusicPlayer" #~ msgid "_Advanced Notifications Control..." #~ msgstr "_Pašyranaje kiravańnie nahadvańniami..." #~ msgid "_Player:" #~ msgstr "_Player:" #~ msgid "Role:" #~ msgstr "Funkcyja:" #~ msgid "_Remove from Roster" #~ msgstr "_Vydal ź śpisu kantaktaŭ" #~ msgid "A_ccounts" #~ msgstr "_Konty" #~ msgid "_Filter:" #~ msgstr "_Filter:" #~ msgid "OS:" #~ msgstr "Aperacyjnaja systema:" #~ msgid "" #~ "If that is not your language for which you want to highlight misspelled " #~ "words, then please set your $LANG as appropriate. Eg. for French do " #~ "export LANG=fr_FR or export LANG=fr_FR.UTF-8 in ~/.bash_profile or to " #~ "make it global in /etc/profile.\n" #~ "\n" #~ "Highlighting misspelled words feature will not be used" #~ msgstr "" #~ "Kali heta nia taja mova, dla jakoj treba padśviatlać słovy z pamyłkami, " #~ "vystaŭcie źmiennuju $LANG adpaviedna patrebam. naprykład, dla biełaruskaj " #~ "movy źmiaścicie zahad export LANG=be_BY.UTF-8 u fajle ~/.bash_profile, " #~ "albo hlabalna ŭ /etc/profile.\n" #~ "\n" #~ "Słovy z pamyłkami nie padśviatlajucca" #~ msgid "Every %s _minutes" #~ msgstr "Praz kožnyja %s _chvilinaŭ" #~ msgid "You will always see him or her as offline." #~ msgstr "" #~ "Ciapier ty zaŭsiody budzieš bačyć status hetaha kantaktu jak adłučany." #~ msgid "%s is now %s (%s)" #~ msgstr "%s maje ciapier status %s (%s)" #~ msgid "%s is now %s" #~ msgstr "%s maje ciapier status %s" #~ msgid "" #~ "\n" #~ "From: %(from_address)s" #~ msgstr "" #~ "\n" #~ "Ad: %(from_address)s" #~ msgid "Network Manager support not available" #~ msgstr "Nie staje padtrymki Network Manager" #~ msgid "Session Management support not available (missing gnome.ui module)" #~ msgstr "Nie staje padtrymki kiravańnia sesijami (nie staje modulu gnome.ui)" #~ msgid "%s does not appear to be a valid JID" #~ msgstr "%s nia jość pravilnym JIDam" #~ msgid "%s - Gajim" #~ msgstr "%s - Gajim" #~ msgid "_New group chat" #~ msgstr "_Novy pakoj" #~ msgid "_Log on" #~ msgstr "_Dałučysia" #~ msgid "Log _off" #~ msgstr "_Adłučysia" #~ msgid "Save passphrase" #~ msgstr "Zachavaj parol" #~ msgid "Drop %s in group %s" #~ msgstr "Pieraniasi %s u hrupu %s" #~ msgid "Hides the buttons in two persons chat window." #~ msgstr "Chavaje knopki ŭ aknie pryvatnaj razmovy." #~ msgid "Connected to server %s:%s with %s" #~ msgstr "Dałučany da servera %s:%s z %s" #~ msgid " %d unread single message" #~ msgid_plural " %d unread single messages" #~ msgstr[0] "%d niečytanaje asobnaje paviedamleńnie" #~ msgstr[1] "%d niečytanyja asobnyja paviedamleńni" #~ msgstr[2] "%d niečytanych asobnych paviedamleńniaŭ" #~ msgid " %d unread group chat message" #~ msgid_plural " %d unread group chat messages" #~ msgstr[0] "%d niečytanaje hrupavoje paviedamleńnie" #~ msgstr[1] "%d niečytanyja hrupavyja paviedamleńni" #~ msgstr[2] "%d niečytanych hrupavych paviedamleńniaŭ" #~ msgid " %d unread private message" #~ msgid_plural " %d unread private messages" #~ msgstr[0] "%d niečytanaje pryvatnaje paviedamleńnie" #~ msgstr[1] "%d niečytanyja pryvatnyja paviedamleńni" #~ msgstr[2] "%d niečytanych pryvatnych paviedamleńniaŭ" #~ msgid "" #~ "Connection to host could not be established: Incorrect answer from server." #~ msgstr "Niemahčyma złučycca z hostam: Niapravilny adkaz servera." #~ msgid "Connection to host could not be established" #~ msgstr "Niemahčyma złučycca z hostam" #~ msgid "Basc" #~ msgstr "Basckaja" #~ msgid "Private Chat" #~ msgstr "Прыватная размова" #~ msgid "invisible" #~ msgstr "нябачны" #~ msgid "offline" #~ msgstr "адключаны" #~ msgid "2003-12-13T18:30:02Z" #~ msgstr "2003-12-13T18:30:02Z" #~ msgid "Romeo and Juliet" #~ msgstr "Рамэа і Джульета" #~ msgid "Soliloquy" #~ msgstr "Маналог" #~ msgid "A_fter nickname:" #~ msgstr "_Пасля мянушкі:" #~ msgid "_After time:" #~ msgstr "_Праз пэўны час:" #~ msgid "_Before time:" #~ msgstr "_За пэўны час да:" #~ msgid "_Retrieve" #~ msgstr "_Атрымаць" #~ msgid "Information published" #~ msgstr "Звесткі абноўлены" #~ msgid "Without a connection, you can not get your contact information." #~ msgstr "Вы не можаце атрымаць звесткі аб сабе, не злучыўшыся з сэрвэрам." gajim-gajim-1.1.3/po/bg.po000066400000000000000000014572311345766322700152720ustar00rootroot00000000000000# Bulgarian translation of Gajim. # Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This file is distributed under the same license as the Gajim package. # # # Yavor Doganov , 2005, 2006, 2007, 2008, 2009. msgid "" msgstr "" "Project-Id-Version: Gajim 0.12\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2009-08-19 23:43+0200\n" "Last-Translator: Yavor Doganov \n" "Language-Team: Bulgarian \n" "Language: bg\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "Наистина ли да се изпрати файла?" #: gajim/chat_control_base.py:1103 #, fuzzy, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "Ако изпратите файл на %s, той/тя ще разбере истинския ви Jabber ID." #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Файл:" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Време" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Напредък" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Име на файл: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Размер: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "Вие" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Изпращач: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Получател: " #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Запазен в: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Файловият трансфер завърши" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 #, fuzzy msgid "Open _Containing Folder" msgstr "_Отваряне на папката" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "Файловият трансфер е прекъснат" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "Не може да бъде установен контакт с отсрещната машина." #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "Получател: %s" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "Грешка: %s" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 #, fuzzy msgid "File transfer stopped" msgstr "Файловият трансфер е преустановен" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" #: gajim/filetransfers_window.py:341 #, fuzzy msgid "Gajim can not read this file" msgstr "Неуспех при достъпа до този файл" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "" #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "Неуспех при презаписването на съществуващия файл „%s“" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "Вече съществува файл с това име и нямате права да го презапишете." #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Този файл вече съществува" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "Какво искате да направите?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "Папката „%s“ не е разрешена за запис" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "Нямата права да създавате файлове в тази папка." #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Файл: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Тип: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Описание: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "%s иска да ви изпрати файл:" #: gajim/filetransfers_window.py:487 #, fuzzy msgid "Checking file…" msgstr "Изпращане на профила…" #: gajim/filetransfers_window.py:501 #, fuzzy msgid "File error" msgstr "Грешка при файловия трансфер" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/сек)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Невалиден файл" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Файл: " #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "Не е възможно да бъдат изпращани празни файлове" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Име: " #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Изпращач: " #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Пауза" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "П_родължаване" #: gajim/filetransfers_window.py:1019 #, fuzzy msgid "Choose a File to Send…" msgstr "Избор на файл за изпращане…" #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "Разширението не се поддържа" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" "Изображението не може да бъде запазено във формат %(type)s. Запазване като " "%(new_filename)s?" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 #, fuzzy msgid "Save _As" msgstr "имам " #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "Неизвестен" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "Неизвестна" #: gajim/vcard.py:326 gajim/vcard.py:329 #, fuzzy msgid "?Time:Unknown" msgstr "Неизвестен" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "" #: gajim/vcard.py:384 msgid "Affiliation:" msgstr "Ранг:" #: gajim/vcard.py:391 #, fuzzy msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "" "Този контакт се интересува от информацията за вашето състояние, но вие не се " "интересувате от неговото" #: gajim/vcard.py:393 #, fuzzy msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "" "Вие с интересувате от информацията за състоянието на този контакт, но той не " "се интересува от вашето" #: gajim/vcard.py:395 #, fuzzy msgid "The contact and you want to exchange presence information" msgstr "" "Вие и контакта се интересувате взаимно от информацията за състоянията си" #: gajim/vcard.py:397 #, fuzzy msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "" "Вие и контакта се интересувате взаимно от информацията за състоянията си" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "Чакате отговора на контакта относно запитването ви за записване" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "Няма чакащо запитване за записване." #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr " ресурс с приоритет " #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "Всички файлове" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 #, fuzzy msgid "Clear File" msgstr "Чистя" #: gajim/options_dialog.py:484 #, fuzzy msgid "Manage Proxies" msgstr "Настройки на сървъра-посредник" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Няма" #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "_Съгласуване спрямо състоянието" #: gajim/options_dialog.py:528 msgid "On" msgstr "" #: gajim/options_dialog.py:528 #, fuzzy msgid "Off" msgstr "Изключен" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Неуспех при извличането на частните ключове" #: gajim/options_dialog.py:565 #, fuzzy msgid "There is no OpenPGP secret key available." msgstr "Възникна проблем при извличането на частните ви OpenPGP ключове." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "Избор на ключ на OpenPGP" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Изберете вашия ключ на OpenPGP" #: gajim/gui_menu_builder.py:95 msgid "_New Group Chat" msgstr "_Нова стая" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Не е в списъка" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "" "Бих искал(а) да Ви добавя към списъка си. I would like to add you to my " "roster." #: gajim/gui_menu_builder.py:502 #, fuzzy msgid "Send Single _Message…" msgstr "Изпращане на _еднократно съобщение" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 msgid "Send Cus_tom Status" msgstr "Изпращане на _специфично състояние" #: gajim/gui_menu_builder.py:535 #, fuzzy msgid "E_xecute Command…" msgstr "_Изпълнение на команда" #: gajim/gui_menu_builder.py:543 msgid "_Manage Transport" msgstr "Управление на _транспорт" #: gajim/gui_menu_builder.py:549 msgid "_Modify Transport" msgstr "Промяна на т_ранспорт" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 #, fuzzy msgid "_Rename…" msgstr "_Преименуване" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "_Деблокиране" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "_Блокиране" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 msgid "Remo_ve" msgstr "П_ремахване" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 msgid "_Information" msgstr "_Информация" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 #, fuzzy msgid "Send File…" msgstr "Изпращане на _файл" #: gajim/gui_menu_builder.py:602 #, fuzzy msgid "Upload File…" msgstr "Запазване на файла като…" #: gajim/gui_menu_builder.py:603 #, fuzzy msgid "Send File Directly…" msgstr "Запазване на файла като…" #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Покана на _контакти" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "Добавяне към _списъка…" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "_Информация" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 #, fuzzy msgid "History" msgstr "Ист_ория" #: gajim/gui_menu_builder.py:634 #, fuzzy msgid "Manage Room" msgstr "_Управление на стаята" #: gajim/gui_menu_builder.py:635 #, fuzzy msgid "Change Subject" msgstr "Промяна на _темата…" #: gajim/gui_menu_builder.py:636 #, fuzzy msgid "Configure Room" msgstr "Настройки на _стаята…" #: gajim/gui_menu_builder.py:637 #, fuzzy msgid "Upload Avatar…" msgstr "Избор на изображение" #: gajim/gui_menu_builder.py:638 #, fuzzy msgid "Destroy Room" msgstr "_Унищожаване на стаята" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "" #: gajim/gui_menu_builder.py:641 #, fuzzy msgid "Change Nick" msgstr "Смяна на псе_вдоним…" #: gajim/gui_menu_builder.py:642 #, fuzzy msgid "Bookmark Room" msgstr "_Добавяне на стаята към отметките (Ctrl+B)" #: gajim/gui_menu_builder.py:643 #, fuzzy msgid "Request Voice" msgstr "_Глас" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 #, fuzzy msgid "Notify on all messages" msgstr "Настроени съобщения:" #: gajim/gui_menu_builder.py:645 #, fuzzy msgid "Minimize on close" msgstr "_Минимизиране при затваряне" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 #, fuzzy msgid "Execute command" msgstr "_Изпълнение на команда" #: gajim/gui_menu_builder.py:648 #, fuzzy msgid "Disconnect" msgstr "_Изключване" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "" #: gajim/gui_menu_builder.py:680 #, fuzzy, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "Преди %i дни" msgstr[1] "Преди %i дни" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Влизане в стая" #: gajim/gui_menu_builder.py:734 #, fuzzy msgid "Add Contact…" msgstr "_Добавяне на контакт…" #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 #, fuzzy msgid "Profile" msgstr "файл" #: gajim/gui_menu_builder.py:737 #, fuzzy msgid "Discover Services" msgstr "_Откриване на услуги" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Изпращане на _еднократно съобщение" #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Напреднали" #: gajim/gui_menu_builder.py:740 #, fuzzy msgid "Archiving Preferences" msgstr "_Настройки" #: gajim/gui_menu_builder.py:741 #, fuzzy msgid "Synchronise History" msgstr "Синхронизиране" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "Филтри за уединение" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 #, fuzzy msgid "Server Info" msgstr "Сървър" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "XML конзола" #: gajim/gui_menu_builder.py:746 #, fuzzy msgid "Admin" msgstr "_Администратор" #: gajim/gui_menu_builder.py:747 #, fuzzy msgid "Send Server Message…" msgstr "_Изпращане на съобщение от сървъра…" #: gajim/gui_menu_builder.py:748 #, fuzzy msgid "Set MOTD…" msgstr "Настройване на MOTD…" #: gajim/gui_menu_builder.py:749 #, fuzzy msgid "Update MOTD…" msgstr "Актуализиране на MOTD…" #: gajim/gui_menu_builder.py:750 #, fuzzy msgid "Delete MOTD…" msgstr "Изтриване на MOTD" #: gajim/gui_menu_builder.py:799 #, fuzzy msgid "No Accounts available" msgstr "Няма наличен акаунт" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Акаунти" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 #, fuzzy msgid "Copy JID" msgstr "JID на стая" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Влизане в стая" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Започване на разговор" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 #, fuzzy msgid "Add to Roster…" msgstr "Добавяне към _списъка…" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "_Копиране на адреса на връзката" #: gajim/gui_menu_builder.py:881 #, fuzzy msgid "Open Link in Browser" msgstr "_Отваряне на връзката в браузър" #: gajim/gui_menu_builder.py:886 #, fuzzy msgid "Copy Email Address" msgstr "Копиране на _JID/Е-поща" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Отваряне на пощенската програма" #: gajim/gui_menu_builder.py:892 #, fuzzy msgid "Copy JID/Email" msgstr "Копиране на _JID/Е-поща" #: gajim/history_manager.py:71 #, fuzzy msgid "Usage:" msgstr "съобщение" #: gajim/history_manager.py:73 #, fuzzy msgid "Options:" msgstr "_Емотикони:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "Неуспех при откриването на базата от данни за разговорите" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Дата" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Псевдоним" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Съобщение" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Тема" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" "Искате ли да изчистите базата от данни? (ИЗОБЩО НЕ СЕ ПРЕПОРЪЧВА АКО GAJIM Е " "СТАРТИРАН)" #: gajim/history_manager.py:257 #, fuzzy msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" "Разпределеното пространство на базата от данни няма да бъде освободено, а ще " "стане наново използваемо. Ако наистина искате да намалите файловия размер на " "базата от данни, изберете „Да“; в противен случай изберете „Не“.\n" "\n" "В случай, че изберете „Да“, изчакайте…" #: gajim/history_manager.py:262 #, fuzzy msgid "Database Cleanup" msgstr "Грешка в базата от данни" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(who)s каза в %(time)s: %(message)s\n" #: gajim/history_manager.py:577 #, fuzzy, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Наистина ли искате да изтриете избраното съобщение?" #: gajim/history_manager.py:581 #, fuzzy msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "Наистина ли искате да изтриете дневниците на избрания контакт?" #: gajim/history_manager.py:583 #, fuzzy msgid "This can not be undone." msgstr "Услугата не може да бъде намерена" #: gajim/history_manager.py:585 gajim/history_manager.py:624 #, fuzzy msgid "Deletion Confirmation" msgstr "Отмяна на потвърждението" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Наистина ли искате да изтриете избраното съобщение?" msgstr[1] "Наистина ли искате да изтриете избраните съобщения?" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "Това е необратима операция." #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "Име на контакта: %s" #: gajim/dialogs.py:84 #, fuzzy, python-format msgid "JID: %s" msgstr "Jabber ID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "Общи" #: gajim/dialogs.py:200 msgid "Group" msgstr "Група" #: gajim/dialogs.py:207 msgid "In the group" msgstr "В групата" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "Идентификатор на ключ" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Име на контакта" #: gajim/dialogs.py:483 msgid "Set Mood" msgstr "Задаване на настроение" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "Съобщение за състояние „%s“" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Съобщение за състояние" #: gajim/dialogs.py:807 msgid "Overwrite Status Message?" msgstr "Презаписване на съобщението за състояние?" #: gajim/dialogs.py:808 msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "" "Това име вече се използва. Искате ли да презапишете това съобщение за " "състояние?" #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Запазване като настроено съобщение за състояние" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Напишете име за това съобщение за състояние" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Искане за записване" #: gajim/dialogs.py:857 #, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Искане за записване за акаунт „%(account)s“ от %(jid)s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Искане за записване от %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "Не сте свързани към сървъра." #: gajim/dialogs.py:928 msgid "Without a connection, you can not synchronise your contacts." msgstr "Трябва да сте свързани, за да синхронизирате контактите си." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Име" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Сървър" #: gajim/dialogs.py:978 msgid "This account is not connected to the server" msgstr "Този акаунт не е свързан към сървъра" #: gajim/dialogs.py:979 msgid "You cannot synchronize with an account unless it is connected." msgstr "Не може да се синхронизирате с акаунт, ако не е свързан." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "Синхронизиране" #: gajim/dialogs.py:1065 #, fuzzy msgid "add" msgstr "Тъжен" #: gajim/dialogs.py:1065 #, fuzzy msgid "modify" msgstr "Унил" #: gajim/dialogs.py:1066 #, fuzzy msgid "remove" msgstr "П_ремахване" #: gajim/dialogs.py:1095 #, fuzzy, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "Бих искал(а) да ви добавя към списъка си." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 msgid "Add" msgstr "" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 #, fuzzy msgid "Modify" msgstr "Унил" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Изтриване" #: gajim/dialogs.py:1125 #, fuzzy msgid "Groups" msgstr "Група" #: gajim/dialogs.py:1233 #, fuzzy, python-format msgid "%s suggested me to add you in my roster." msgstr "" "Бих искал(а) да ви добавя към списъка си. I would like to add you to my " "roster." #: gajim/dialogs.py:1247 #, fuzzy, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "Добавяне на _контакт" msgstr[1] "Добавяне на _контакт" #: gajim/dialogs.py:1285 #, fuzzy, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "Премахване на контакт от списъка" msgstr[1] "Премахване на контакт от списъка" #: gajim/dialogs.py:1305 msgid "You are invited to a groupchat" msgstr "Поканени сте в стая." #: gajim/dialogs.py:1308 msgid "$Contact has invited you to join a discussion" msgstr "$Contact ви покани да се присъедините към дискусия" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "$Contact ви покани в стая %(room_jid)s." #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Коментар: %s" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "Искате ли да приемете поканата?" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Покана за разговор в стая" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "" #: gajim/dialogs.py:1628 msgid "a video" msgstr "" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 #, fuzzy msgid "File Transfer" msgstr "Файлови трансфери" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "" #: gajim/dialogs.py:1764 #, fuzzy msgid "Encrypting file…" msgstr "Шифрирането чрез E2E е изключено" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%(nick)s вече е познат като %(new_nick)s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s вече е %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Неуспех при изпращането на лично съобщение" #: gajim/groupchat_control.py:253 #, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "Вече не сте в стая „%(room)s“ или „%(nick)s“ е напуснал(а)." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 #, fuzzy msgid "No File Transfer available" msgstr "Файлови трансфери" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Промяна на темата" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Въведете новата тема:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Промяна на псевдонима" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Въведете новия псевдоним, който искате да използвате:" #: gajim/groupchat_control.py:711 #, fuzzy msgid "Invalid group chat JID" msgstr "Невалиден Jabber ID на стая" #: gajim/groupchat_control.py:712 #, fuzzy msgid "The group chat JID has not allowed characters." msgstr "Jabber ID на стаята съдържа непозволени знаци." #: gajim/groupchat_control.py:724 #, python-format msgid "Destroying %s" msgstr "Унищожаване на %s" #: gajim/groupchat_control.py:725 #, fuzzy msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" "Определено сте на път да унищожите тази стая.\n" "Може да укажете причина по-долу:" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "Може да въведете и друго място за срещи:" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "Неуспех при зареждането на изображението" #: gajim/groupchat_control.py:934 msgid "Insert Nickname" msgstr "Въведете псевдоним" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 msgid "and authenticated" msgstr "и удостоверяването е успешно" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 msgid "and NOT authenticated" msgstr "и удостоверяването НЕ Е успешно" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, fuzzy, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" "Шифрирането чрез %(type)s %(status)s включено %(authenticated)s.\n" "%(logged)s се запазва дневник за сесията." #: gajim/groupchat_control.py:1157 msgid "Conversation with " msgstr "Разговор с " #: gajim/groupchat_control.py:1159 msgid "Continued conversation" msgstr "Продължен разговор" #: gajim/groupchat_control.py:1525 #, fuzzy, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(jid)s зададе темата на %(subject)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "На всеки участник е позволено да вижда вашия JID" #: gajim/groupchat_control.py:1556 #, fuzzy msgid "Room now shows unavailable members" msgstr "Стаята показва отсъстващ член" #: gajim/groupchat_control.py:1558 #, fuzzy msgid "Room now does not show unavailable members" msgstr "Стаята не показва отсъстващи членове" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "Воденето на дневник на стаята е включено" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "Воденето на дневник на стаята е изключено" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "Стаята не е анонимна" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "Стаята е полу-анонимна" #: gajim/groupchat_control.py:1576 #, fuzzy msgid "Room is now fully anonymous" msgstr "Стаята е напълно анонимна" #: gajim/groupchat_control.py:1615 #, fuzzy, python-format msgid "Ping? (%s)" msgstr "Понг! (%s сек)" #: gajim/groupchat_control.py:1618 #, fuzzy, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "Понг! (%s сек)" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 msgid "Error." msgstr "Грешка." #: gajim/groupchat_control.py:1845 #, fuzzy, python-format msgid "You (%s) joined the room" msgstr "%s влезе в стаята" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, fuzzy, python-format msgid "%(jid)s has been invited in this room" msgstr "%(nick)s беше изритан от стаята (%(reason)s)" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "Воденето на дневник на стаята е включено" #: gajim/groupchat_control.py:1879 msgid "A new room has been created" msgstr "Беше създадена нова стая" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "Сървърът назначи или промени псевдонима ви в стаята" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s беше изритан: %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(nick)s беше изритан от %(who)s: %(reason)s" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "%(nick)s беше отлъчен: %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(nick)s беше отлъчен от %(who)s: %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "Вече сте познати като %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(nick)s беше изритан от стаята (%(reason)s)" #: gajim/groupchat_control.py:1950 msgid "affiliation changed" msgstr "рангът е променен" #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "Конфигурацията на стаята бе променена на „само за членове“" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "Изключване на системата" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "** Рангът на %(nick)s бе зададен на %(affiliation)s от %(actor)s" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "** Рангът на %(nick)s бе зададен на %(affiliation)s" #: gajim/groupchat_control.py:2034 #, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "** Ролята на %(nick)s бе зададена на %(role)s от %(actor)s" #: gajim/groupchat_control.py:2038 #, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "** Ролята на %(nick)s бе зададена на %(role)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "%s напусна" #: gajim/groupchat_control.py:2067 #, python-format msgid "%s has joined the group chat" msgstr "%s влезе в стаята" #: gajim/groupchat_control.py:2374 #, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Сигурни ли сте, че искате да напуснете стаята „%s“?" #: gajim/groupchat_control.py:2376 msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "Ако затворите този прозорец, връзката със стаята ще бъде прекъсната." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 #, fuzzy msgid "_Do not ask me again" msgstr "Да _не се задава този въпрос отново" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Изритване на %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Може да уточните причина по-долу:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Отлъчване на %s" #: gajim/chat_control.py:389 #, fuzzy msgid "Show a list of formattings" msgstr "Списък с емотикони (Alt+M)" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 #, fuzzy msgid "This contact does not support HTML" msgstr "Списък с активни, завършили и прекъснати файлови трансфери" #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "" #: gajim/chat_control.py:660 #, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s от стая %(room_name)s" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "Току-що получихте ново съобщение от „%s“" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Ако затворите този прозорец и нямате включена опция за запазване на " "историята, съобщението ще бъде загубено." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "Пинг?" #: gajim/chat_control.py:1205 #, fuzzy, python-format msgid "Pong! (%s seconds)" msgstr "Понг! (%s сек)" #: gajim/chat_control.py:1313 #, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Тема: %(subject)s\n" "%(message)s" #: gajim/chat_control.py:1416 #, fuzzy, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(name)s вече е %(status)s" #: gajim/chat_control.py:1471 #, fuzzy msgid "File transfer" msgstr "Файлови трансфери" #: gajim/chat_control.py:1474 #, fuzzy msgid "Size" msgstr "Размер: %s" #: gajim/chat_control.py:1476 #, fuzzy msgid "Accept" msgstr "_Акаунти" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Влизане" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 #, fuzzy msgid "Remote contact stopped transfer" msgstr "Премахване на контакт от списъка" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 #, fuzzy msgid "Error opening file" msgstr "Грешка при четене на файл:" #: gajim/application.py:68 #, fuzzy msgid "Show the application's version" msgstr "Демон за уведомления" #: gajim/application.py:75 #, fuzzy msgid "Show only critical errors" msgstr "Показване на събитието в спис_ъка" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 #, fuzzy msgid "Use defined profile in configuration directory" msgstr "Редактор на настройки за напреднали" #: gajim/application.py:105 #, fuzzy msgid "Set configuration directory" msgstr "Настройки на стаята" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 #, fuzzy msgid "Show all warnings" msgstr "Показване на всички _чакащи събития" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 msgid "Pops up a window with the next pending event" msgstr "Показва следващото чакащо събитие в изскачащ прозорец" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 #, fuzzy msgid "Start a new chat" msgstr "Започване на разговор" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "Грешка в базата от данни" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Смесени акаунти" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Транспорти" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 msgid "Groupchats" msgstr "Стаи" #: gajim/roster_window.py:2056 #, fuzzy msgid "Authorization sent" msgstr "Упълномощаването беше изпратено" #: gajim/roster_window.py:2057 #, fuzzy, python-format msgid "\"%s\" will now see your status." msgstr "„%s“ вече ще знае състоянието ви." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Искането за записване беше изпратено" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "Ако „%s“ приеме това запитване, ще знаете за състоянието му." #: gajim/roster_window.py:2095 #, fuzzy msgid "Authorization removed" msgstr "Упълномощаването беше прекратено" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "„%s“ винаги ще ви вижда като изключен." #: gajim/roster_window.py:2120 #, fuzzy msgid "OpenPGP is not usable" msgstr "GPG не е използваем" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Участвате в една или повече стаи" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Промяната на състоянието до „Невидим“ ще ви изключи от тези стаи. Сигурни ли " "сте, че искате да станете „Невидим“?" #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "без синхронизация" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "" #: gajim/roster_window.py:2426 #, fuzzy msgid "Are you sure you want to quit Gajim?" msgstr "Сигурни ли сте, че искате да напуснете стаята „%s“?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "" #: gajim/roster_window.py:2514 #, fuzzy msgid "You have running file transfers" msgstr "Отменя файловия трансфер" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Имате непрочетени съобщения" #: gajim/roster_window.py:2547 msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "Може да преглеждате съобщенията по-късно само ако е активирана опцията за " "историята и контактът е в списъка." #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "Трябва да ги прочетете преди да премахнете този транспорт." #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Транспортът „%s“ ще бъде премахнат" #: gajim/roster_window.py:2829 msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" "Вече няма да можете да получавате и изпращате съобщения до контакти чрез " "този транспорт." #: gajim/roster_window.py:2832 msgid "Transports will be removed" msgstr "Ще бъдат премахнати транспорти" #: gajim/roster_window.py:2837 #, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" "Вече няма да можете да получавате и изпращате съобщения до контакти чрез " "тези транспорти: %s" #: gajim/roster_window.py:2891 #, fuzzy msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "" "На път сте да създадете мета-контакт. Сигурни ли сте, че искате да " "продължите?" #: gajim/roster_window.py:2893 msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" #: gajim/roster_window.py:2939 msgid "Rename Contact" msgstr "Преименуване на контакт" #: gajim/roster_window.py:2940 #, python-format msgid "Enter a new nickname for contact %s" msgstr "Въведете нов псевдоним за контакт „%s“" #: gajim/roster_window.py:2947 msgid "Rename Group" msgstr "Преименуване на група" #: gajim/roster_window.py:2948 #, python-format msgid "Enter a new name for group %s" msgstr "Въведете ново име за група „%s“" #: gajim/roster_window.py:2993 msgid "Remove Group" msgstr "Премахване на група" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "Искате ли да премахнете групата „%s“ от списъка?" #: gajim/roster_window.py:2995 msgid "Also remove all contacts in this group from your roster" msgstr "Премахване от списъка и на всички контакти в тази група" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Задаване на OpenPGP ключ" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "Изберете ключ за този контакт" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "Контактът „%s“ ще бъде премахнат от списъка ви" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "" #: gajim/roster_window.py:3448 #, fuzzy msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "Премахвайки тези контакти: %s\n" "прекратявате и упълномощаването, така че винаги ще ви виждат изключен(а)." #: gajim/roster_window.py:3454 msgid "Do you want to continue?" msgstr "Искате ли да продължите?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "Премахвайки този контакт, прекратявате и упълномощаването. Контактът винаги " "ще ви вижда изключен." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Искам този контакт да вижда състоянието ми след премахването" #: gajim/roster_window.py:3465 msgid "Contacts will be removed from your roster" msgstr "Ще бъдат премахнати контакти от списъка" #: gajim/roster_window.py:3470 #, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "Премахвайки тези контакти: %s\n" "прекратявате и упълномощаването, така че винаги ще ви виждат изключен(а)." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "" "На път сте да създадете мета-контакт. Сигурни ли сте, че искате да " "продължите?" #: gajim/roster_window.py:3531 #, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Няма наличен акаунт" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "" "За да разговаряте с други контакти, първо трябва да създадете Джабър акаунт." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "Сървърът ви няма поддръжка за мета-контакти" #: gajim/roster_window.py:4180 #, fuzzy msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" "Вашият сървър не поддържа съхраняването на информация за мета-контакти, така " "че тази информация няма да се запази при следващото свързване." #: gajim/roster_window.py:4276 msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "" "На път сте да създадете мета-контакт. Сигурни ли сте, че искате да " "продължите?" #: gajim/roster_window.py:4278 #, fuzzy msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" "Мета-контактите са начин за прегрупиране на няколко контакта на един ред. " "Основно се използва, когато един и същ потребител има няколко акаунта за " "Джабър или акаунти за транспорти." #: gajim/roster_window.py:4400 msgid "Invalid file URI:" msgstr "Невалиден адрес на файл:" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Изпращане на _файл" #: gajim/roster_window.py:4412 #, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "Искате ли да изпратите този файл на %s:" msgstr[1] "Искате ли да изпратите тези файлове на %s:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Изпращане на %s" #: gajim/roster_window.py:4565 #, fuzzy, python-format msgid "Make %s first contact" msgstr "Изпращане на файл до контакт" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Изпращане на файл до контакт" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "Пром_яна на съобщението за състояние" #: gajim/roster_window.py:4965 msgid "Publish Tune" msgstr "Публикуване на мелодия" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "Публикуване на мелодия" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "Настройване на услуги…" #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "_Максимизиране на всички" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 msgid "Send Group M_essage" msgstr "_Изпращане на групово съобщение" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "До всички потребители" #: gajim/roster_window.py:5135 msgid "To all online users" msgstr "До всички включени потребители" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "По_кана в" #: gajim/roster_window.py:5299 msgid "_Manage Contacts" msgstr "_Управление на контакти" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Редактиране на _групи" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "_Премахване" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "_Максимизиране" #: gajim/roster_window.py:5370 #, fuzzy msgid "_Reconnect" msgstr "_Изключване" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 msgid "_Disconnect" msgstr "_Изключване" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "Ист_ория" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Мениджър на историята" #: gajim/roster_window.py:5475 msgid "_Join New Group Chat" msgstr "_Влизане в нова стая" #: gajim/config.py:359 msgid "Ban List" msgstr "Списък с отлъчени" #: gajim/config.py:360 msgid "Member List" msgstr "Списък с членове" #: gajim/config.py:360 msgid "Owner List" msgstr "Списък със собственици" #: gajim/config.py:361 msgid "Administrator List" msgstr "Списък с администратори" #: gajim/config.py:435 msgid "Reason" msgstr "Причина" #: gajim/config.py:442 msgid "Nick" msgstr "Псевдоним" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "Роля" #: gajim/config.py:478 #, fuzzy msgid "Banning…" msgstr "Отлъчване…" #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Кого искате да отлъчите?\n" "\n" #: gajim/config.py:482 #, fuzzy msgid "Adding Member…" msgstr "Добавяне на член…" #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" "Кого искате да направите член?\n" "\n" #: gajim/config.py:485 #, fuzzy msgid "Adding Owner…" msgstr "Добавяне на собственик…" #: gajim/config.py:486 msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "" "Кого искате да направите собственик?\n" "\n" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "Добавяне на администратор…" #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" "Кого искате да направите администратор?\n" "\n" #: gajim/config.py:490 #, fuzzy msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" "Може да бъде едно от следните:\n" "1. потребител@домейн/ресурс (само този ресурс съвпада).\n" "2. потребител@домейн (всеки ресурс съвпада).\n" "3. домейн/ресурс (само този ресурс съвпада).\n" "4. домейн (домейна съвпада, както и всеки потребител@домейн,\n" "домейн/ресурс или адрес, съдържащ под-домейн." #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Премахване на акаунт „%s“" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Емотиконите са изключени" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Необходима е парола" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Въведете парола за акаунт „%s“" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Запазване на паролата" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Акаунт „%s“ е свързан към сървъра" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Ако го премахнете, връзката ще се разпадне." #: gajim/config.py:652 #, fuzzy, python-format msgid "Connection to server %s failed" msgstr "Неуспех при свързването със сървъра-посредник" #: gajim/config.py:653 #, fuzzy msgid "What would you like to do?" msgstr "Какво искате да направите?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Премахване на акаунт _само от Gajim" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Формат WAV" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "Първо получено съобщение" #: gajim/config.py:746 msgid "First Message Received" msgstr "Първо получено съобщение" #: gajim/config.py:747 msgid "Next Message Received Focused" msgstr "Следващо получено съобщение в прозорец на фокус" #: gajim/config.py:748 msgid "Next Message Received Unfocused" msgstr "Следващо получено съобщение в прозорец без фокус" #: gajim/config.py:749 msgid "Contact Connected" msgstr "Включване на контакт" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "Изключване на контакт" #: gajim/config.py:751 msgid "Message Sent" msgstr "Изпратено съобщение" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "Осветено съобщение в стая" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "Получено съобщение в стая" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "%(owner_or_admin_or_member)s на тази стая" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 msgid "?Group Chat Contact Affiliation:None" msgstr "Няма" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 msgid "Member" msgstr "Член" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 msgid "Administrator" msgstr "Администратор" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 msgid "Owner" msgstr "Собственик" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr " [блокиран]" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr " [минимизиран]" #: gajim/tooltips.py:574 msgid "Connected" msgstr "Свързан" #: gajim/tooltips.py:576 msgid "Disconnected" msgstr "Изключен" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Изтегляне" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Качване" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Тип: " #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Прехвърлени: " #: gajim/tooltips.py:645 msgid "Status: " msgstr "Състояние: " #: gajim/tooltips.py:647 msgid "Description: " msgstr "Описание: " #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Завършил" #: gajim/tooltips.py:676 msgid "?transfer status:Paused" msgstr "Временно прекъснат" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "Блокирал" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "Прехвърляне" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "Не е започнал" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "Временно прекъснат" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Свободен за разговор" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Отсъствам" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Зает" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Не съм на разположение" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Изключен" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "Пром_яна на съобщението за състояние" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "от акаунт „%s“" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Управление на отметките" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "в с_писъка" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "П_оказване на списъка" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Скриване на това меню" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Неуспех при зареждането на модула „idle“" #: gajim/dataforms_widget.py:586 #, fuzzy, python-format msgid "Media type not supported: %s" msgstr "Състоянието „Невидим“ не се поддържа." #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "new@jabber.id" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "new%d@jabber.id" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "Тази услуга все още не е отговорила с подробна информация" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "Тази услуга не можа да отговори с подробна информация.\n" "Най-вероятно е извън употреба или повредена" #: gajim/disco.py:121 msgid "Others" msgstr "Други" #: gajim/disco.py:125 msgid "Conference" msgstr "Стаи за разговор" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "Трябва да сте свързани, за да разглеждате наличните услуги" #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "Откриване на налични услуги за акаунт „%s“" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Откриване на услуги" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "Услугата не може да бъде намерена" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "Няма услуга на въведения адрес или не отговаря. Проверете адреса и опитайте " "отново." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "Услугата не е достъпна" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "Този вид услуга не съдържа обекти за показване." #: gajim/disco.py:726 gajim/disco.py:736 msgid "Invalid Server Name" msgstr "Невалидно име на сървър" #: gajim/disco.py:794 #, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "Търсене в %(address)s от акаунт „%(account)s“" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Търсене" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "Тази услуга не съдържа обекти за показване." #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "_Изпълнение на команда" #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "_Регистриране" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "_Влизане" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "Търсене" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Редактиране" #: gajim/disco.py:1450 #, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "Сканиране на %(current)d / %(total)d…" #: gajim/disco.py:1649 msgid "Users" msgstr "Потребители" #: gajim/disco.py:1657 msgid "Description" msgstr "Описание" #: gajim/disco.py:1665 msgid "Id" msgstr "Идентификатор" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 msgid "_Bookmark" msgstr "_Добавяне на стаята към отметките" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Отметката вече е установена" #: gajim/disco.py:1722 #, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "Стаята „%s“ вече присъства в отметките." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Отметката беше добавена успешно" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "Може да организирате отметките чрез менюто „Действия“." #: gajim/disco.py:1929 msgid "Subscribed" msgstr "Записан" #: gajim/disco.py:1938 msgid "Node" msgstr "Възел" #: gajim/disco.py:2005 msgid "New post" msgstr "Ново съобщение" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "_Записване" #: gajim/disco.py:2017 msgid "_Unsubscribe" msgstr "_Отписване" #: gajim/conversation_textview.py:320 msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" "Текстът под този ред е последното, което е казано откакто\n" "за последен път сте обърнали внимание на тази стая" #: gajim/conversation_textview.py:541 #, fuzzy msgid "_Quote" msgstr "_Изход" #: gajim/conversation_textview.py:549 #, python-format msgid "_Actions for \"%s\"" msgstr "_Действия за „%s“" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Четене на статия от _Уикипедия" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Проверка в _речника" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "Липсва „%s“ в адреса на речника и не е WIKTIONARY" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "Липсва „%s“ в адреса за търсене" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "_Търсене в уеб" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "Отваряне като _връзка" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "Невалиден JID" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, fuzzy, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "Вчера" msgstr[1] "Вчера" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Не е започнал" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Тема: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Ново лично съобщение" #: gajim/message_window.py:243 #, fuzzy msgid "You are going to close several tabs" msgstr "Не сте свързани към сървъра." #: gajim/message_window.py:244 #, fuzzy msgid "Do you really want to close them all?" msgstr "Наистина ли искате да изтриете избраното съобщение?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Стаи" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "Лични разговори" #: gajim/message_window.py:530 msgid "Messages" msgstr "Съобщения" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 msgid "Unable to join group chat" msgstr "Неуспех при влизането в стаята" #: gajim/gui_interface.py:170 #, fuzzy, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "Желаният от вас псевдоним за стая %s се използва или е регистриран от друг " "участник.\n" "Укажете друг псевдоним по-долу:" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Приемате ли това запитване?" #: gajim/gui_interface.py:194 #, python-format msgid "Do you accept this request on account %s?" msgstr "Приемате ли това запитване за акаунт %s?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "Упълномощаване по HTTP (%(method)s) за „%(url)s“ (id: %(id)s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 msgid "Connection Failed" msgstr "Неуспех при свързването" #: gajim/gui_interface.py:327 #, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "Необходима е парола за влизане в стаята „%s“. Въведете я." #: gajim/gui_interface.py:342 #, fuzzy, python-format msgid "%s is full" msgstr "Шрифт" #: gajim/gui_interface.py:351 #, fuzzy, python-format msgid "You are banned from group chat %s." msgstr "Вие сте отлъчени от стаята %s." #: gajim/gui_interface.py:358 #, fuzzy, python-format msgid "Remote server %s does not exist." msgstr "Стаята %s не съществува." #: gajim/gui_interface.py:362 #, fuzzy, python-format msgid "Group chat %s does not exist." msgstr "Стаята %s не съществува." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "Създаването на стаи е ограничено." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Неуспех при влизането в стаята" #: gajim/gui_interface.py:368 #, fuzzy, python-format msgid "You must use your registered nickname in %s." msgstr "Трябва да се използва регистрирания ви псевдоним в стаята %s." #: gajim/gui_interface.py:373 #, python-format msgid "You are not in the members list in groupchat %s." msgstr "Не сте в списъка с членове на стаята %s." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, python-format msgid "Error %(code)s: %(msg)s" msgstr "Грешка %(code)s: %(msg)s" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "грешка при изпращане на %(message)s ( %(error)s )" #: gajim/gui_interface.py:503 gajim/notify.py:194 #, fuzzy msgid "Subscription request" msgstr "Искане за записване" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "Наблюдатели" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Упълномощаването е прието" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "Контактът „%s“ ви упълномощи да виждате състоянието му." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Контактът „%s“ премахна записването за вас" #: gajim/gui_interface.py:539 #, fuzzy msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" "Винаги ще го виждате като изключен.\n" "Искате ли да го премахнете от списъка с контакти?" #: gajim/gui_interface.py:560 gajim/notify.py:194 #, fuzzy msgid "Unsubscribed" msgstr "_Отписване" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, fuzzy, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Поканени сте в стая." #: gajim/gui_interface.py:658 #, fuzzy msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" "Конфигурирали сте Gajim да използва агент на GPG, но такъв не е стартиран " "или е предоставил грешна парола.\n" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "В момента сте свързани без OpenPGP ключ." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Грешна парола" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Грешна парола" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "Валидността на сертификата е изтекла" #: gajim/gui_interface.py:683 #, fuzzy, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Въведете парола за ключ на GPG %(keyid)s (акаунт „%(account)s“)." #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Изберете вашия ключ на OpenPGP" #: gajim/gui_interface.py:706 #, fuzzy msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" "Няма зададен ключ на GPG за този контакт, така че не може да шифрирате " "съобщения." #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Грешка при файловия трансфер" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "%s иска да ви изпрати файл." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Запитване за файлов трансфер" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "Грешка в сертификата на SSL" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Файловият трансфер е приключен" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Файловият трансфер е преустановен" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Файлови трансфери" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Файловият трансфер на %(filename)s от %(name)s прекъсна." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Файловият трансфер на %(filename)s от %(name)s прекъсна." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Файловият трансфер на %(filename)s от %(name)s прекъсна." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Успешно изпратихте %(filename)s на %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Файловият трансфер на %(filename)s до %(name)s прекъсна." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Файловият трансфер на %(filename)s до %(name)s прекъсна." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "Конфликт с имената на потребители" #: gajim/gui_interface.py:1178 msgid "Please type a new username for your local account" msgstr "Укажете ново потребителско име за локалния ви акаунт" #: gajim/gui_interface.py:1201 msgid "Resource Conflict" msgstr "Конфликт на ресурсите" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "Вече сте свързани към този акаунт със същия ресурс. Въведете нов." #: gajim/gui_interface.py:1259 #, fuzzy, python-format msgid "%s wants to start a voice chat." msgstr "%s иска да ви изпрати файл." #: gajim/gui_interface.py:1261 #, fuzzy msgid "Voice Chat Request" msgstr "Запитване за файлов трансфер" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 msgid "Certificate Already in File" msgstr "Сертификатът вече е във файла" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" "Този сертификат вече е във файла „%s“, така че няма да бъде добавен наново." #: gajim/gui_interface.py:1351 #, fuzzy, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "Автентичността на сертификата на %s може да е под въпрос." #: gajim/gui_interface.py:1354 #, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "" "\n" "Неизвестна грешка на SSL: %d" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" "\n" "Грешка на SSL: %s" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "Грешка при проверка на сертификата на SSL" #: gajim/gui_interface.py:1362 #, fuzzy, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" "Възникна грешка при проверката на сертификата за вашия сървър на Джабър: " "%(error)s\n" "Все още ли искате да се свържете със сървъра?" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, fuzzy, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" "Добавяне на този сертификат към списъка с доверени сертификати.\n" "Отпечатък тип SHA1 на сертификата:\n" "%s" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "Пренебрегване на грешката за този сертификат." #: gajim/gui_interface.py:1380 #, fuzzy, python-format msgid "SSL Certificate Verification for %s" msgstr "Грешка в сертификата на SSL" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 msgid "Insecure connection" msgstr "Несигурна връзка" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" "На път сте да изпратите паролата си чрез несигурна връзка. Трябва да " "инсталирате PyOpenSSL, за да предотвратите това. Сигурни ли сте, че искате " "да го направите?" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "Да, наистина искам да се свържа по несигурен начин" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "" "На път сте да изпратите паролата си чрез нешифрирана връзка. Сигурни ли сте, " "че искате да го направите?" #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "Трябва да сте свързани, за да влезете в стая." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Това не е стая" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "Това не е стая" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 msgid "You cannot join a group chat while you are invisible" msgstr "Не може да влезете в стая, докато сте невидими." #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Неуспех при запазването на настройките" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Необходима е парола" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "Въведете парола за ключ на GPG %(keyid)s (акаунт „%(account)s“)." #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "Няма зададен ключ на GPG" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "Ще бъдете свързани към „%s“ без OpenPGP." #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "Грешна парола" #: gajim/gui_interface.py:2853 #, fuzzy msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "Въведете паролата за GPG ключа наново или натиснете „Отказване“." #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "Изчакване на резултатите" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "Грешка в получените данни" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "Няма резултати" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "Програмирам" #: gajim/atom_window.py:123 #, fuzzy, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "Получихте нов запис:" msgstr[1] "Получихте нов запис:" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "Получихте нов запис:" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "Специални команди - Gajim" #: gajim/adhoc_commands.py:326 msgid "Cancel confirmation" msgstr "Отмяна на потвърждението" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "На път сте да изпълните команда. Наистина ли искате да я отмените?" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "Услугата изпрати лошо форматирани данни" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "Услугата промени идентификатора на сесията." #: gajim/adhoc_commands.py:422 #, fuzzy, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "Специални команди - Gajim" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "Услугата върна грешка." #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Включи се контакт" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Изключи се контакт" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Ново съобщение" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Ново еднократно съобщение" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Ново лично съобщение" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 msgid "Contact Changed Status" msgstr "Контактът промени състоянието си" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenGPG" #: gajim/notify.py:270 msgid "New E-mail" msgstr "Нова е-поща" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "Трябва да сте свързани, за да влезете в стая." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 msgid "Invalid JID" msgstr "Невалиден JID" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, fuzzy, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "Не е възможно да бъдат изпращани празни файлове" #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "Непрочетени събития" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "Преди да премахнете този акаунт, прочетете всички чакащи събития." #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "В момента сте свързани със сървъра" #: gajim/dialog_messages.py:53 #, fuzzy msgid "To disable the account, you must be disconnected." msgstr "Трябва да сте изключени, за да смените името на акаунта." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Невалиден формат" #: gajim/dialog_messages.py:58 #, fuzzy msgid "The form is not filled correctly." msgstr "Псевдонимът съдържа непозволени знаци." #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Невидим" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "В момента няма връзка" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "Съобщението не може да бъде изпратено, докато не се свържете." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "В списъка вече има такъв Jabber ID" #: gajim/dialog_messages.py:73 #, fuzzy msgid "The JID you entered is already in the list. Choose another one." msgstr "Въведеният Jabber ID вече съществува в списъка. Изберете друг." #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "Невалиден отговор" #: gajim/dialog_messages.py:78 #, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "" "Транспортът „%(name)s“ отговори погрешно на запитването за регистрация: " "%(error)s" #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Използване на нестандартен хост/порт" #: gajim/dialog_messages.py:84 #, fuzzy, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Използване на нестандартен хост/порт" #: gajim/dialog_messages.py:88 msgid "Error while removing privacy list" msgstr "Грешка при премахването на списъка за уединение" #: gajim/dialog_messages.py:89 #, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" "Списъкът за уединение „%s“ не беше премахнат. Навярно е активен в някой от " "свързаните ви ресурси. Изключете го и опитайте отново." #: gajim/dialog_messages.py:95 msgid "Invisibility not supported" msgstr "Състоянието „Невидим“ не се поддържа." #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "Акаунтът „%s“ не поддържа невидимост." #: gajim/dialog_messages.py:100 #, fuzzy msgid "Unregister failed" msgstr "Неуспех при свързването" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "" #: gajim/dialog_messages.py:105 #, fuzzy msgid "Registration succeeded" msgstr "Регистриране в %s" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 #, fuzzy msgid "Registration failed" msgstr "Неуспех при свързването" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Неуспех при влизането в стаята" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, fuzzy, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "Грешка: %s" #: gajim/dialog_messages.py:126 msgid "Wrong host" msgstr "Грешен хост" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "Невалиден локален адрес? :-O" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "Грешка на Avahi" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" "%s\n" "Изпращането и получаването на съобщения тип „link-local“ може и да не " "функционира правилно." #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 #, fuzzy msgid "Could not request upload slot" msgstr "Неуспех при стартирането на локална услуга" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 #, fuzzy msgid "Could not open file" msgstr "Неуспех при зареждането на изображението" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 #, fuzzy msgid "Server returned unsecure transport (HTTP)" msgstr "Услугата върна грешка." #: gajim/dialog_messages.py:161 #, fuzzy msgid "Could not upload file" msgstr "Неуспех при зареждането на изображението" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 msgid "Encryption Error" msgstr "" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "В момента няма връзка" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "Неуспех при публикуването на визитката" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "На тази машина няма инсталиран D-Bus или липсва модула за Питон" #: gajim/gajim_remote.py:77 msgid "Shows a help on specific command" msgstr "Показва помощ за специфична команда" #: gajim/gajim_remote.py:80 msgid "command" msgstr "команда" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "показване на помощ за команда" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "Показване на списък с всички контакти. Всеки контакт се появява на отделен " "ред" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "акаунт" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "показва само контактите на дадения акаунт" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "Показване на списък с регистрираните акаунти" #: gajim/gajim_remote.py:97 #, fuzzy msgid "Changes the status of account(s)" msgstr "Промяна на състоянието на акаунта или акаунтите" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "състояние" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "" "едно от: offline (изключен), online (на линия), chat (свободен за разговор), " "away (отсъствам), xa (не съм на разположение), dnd (зает), invisible " "(невидим)" #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "съобщение" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "съобщение за състояние" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "променя състоянието на акаунта. Ако не е указано се прави опит за смяна на " "състоянието на всички акаунти, които имат настроена опция „синхронизиране с " "общото състояние“" #: gajim/gajim_remote.py:108 #, fuzzy msgid "Changes the priority of account(s)" msgstr "Промяна на състоянието на акаунта или акаунтите" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "Приори_тет:" #: gajim/gajim_remote.py:110 #, fuzzy msgid "priority you want to give to the account" msgstr "_Искам да регистрирам нов акаунт" #: gajim/gajim_remote.py:112 #, fuzzy msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "променя състоянието на акаунта. Ако не е указано се прави опит за смяна на " "състоянието на всички акаунти, които имат настроена опция „синхронизиране с " "общото състояние“" #: gajim/gajim_remote.py:118 msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Изпращане на ново съобщение до контакт от списъка. Опциите „account“ и " "„OpenPGP key“ са по избор. Ако искате да настроите само „account“ без " "“OpenPGP key“, настройте „OpenPGP key“ на „“." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID на контакта, който ще получи съобщението" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "текст на съобщението" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "" "ако е указано, съобщението ще се шифрира, използвайки този публичен ключ" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "ако е указано, съобщението ще бъде изпратено от този акаунт" #: gajim/gajim_remote.py:131 #, fuzzy msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Изпращане на ново съобщение до контакт от списъка. Опциите „account“ и " "„OpenPGP key“ са по избор. Ако искате да настроите само „account“ без " "“OpenPGP key“, настройте „OpenPGP key“ на „“." #: gajim/gajim_remote.py:136 msgid "subject" msgstr "тема" #: gajim/gajim_remote.py:136 msgid "message subject" msgstr "тема на съобщението" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "Изпраща ново съобщение до стаята, в която сте влезли." #: gajim/gajim_remote.py:147 msgid "JID of the room that will receive the message" msgstr "JID на стаята, която ще получи съобщението" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Получаване на подробна информация за контакта" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "JID на контакта" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "Получаване на подробна информация за акаунта" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "Име на акаунта" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Изпращане на файл до контакт" #: gajim/gajim_remote.py:168 msgid "file" msgstr "файл" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Път до файл" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "ако е указано, файлът бъде изпратен от този акаунт" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Показва всички настройки и техните стойности" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "Настройва стойността на „ключ“ на „стойност“." #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "ключ=стойност" #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "" "„ключ“ е името на настройката, „стойност“ е стойността, която се задава" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "Изтрива обект от настройките" #: gajim/gajim_remote.py:188 msgid "key" msgstr "ключ" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "име на настройката за изтриване" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "Запазва текущото състояние на настройките във файла .config" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Премахване на контакт от списъка" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "ако е указано, контактът се взима от списъка с контакти на този акаунт" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "Връща текущото състояние (общото, в случай, че не е указан акаунт)" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" "Връща текущото съобщение за състояние (общото, в случай, че не е указан " "акаунт)" #: gajim/gajim_remote.py:221 msgid "Returns number of unread messages" msgstr "Връща броя непрочетени съобщения" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "Изпраща указан XML" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "XML за изпращане" #: gajim/gajim_remote.py:229 #, fuzzy msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" "Акаунт, до който да се изпраща XML; ако не е указан, ще се изпрати до всички " "акаунти" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Промяна на състоянието" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "Псевдоним" #: gajim/gajim_remote.py:238 #, fuzzy msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" "Акаунт, до който да се изпраща XML; ако не е указан, ще се изпрати до всички " "акаунти" #: gajim/gajim_remote.py:245 msgid "Check if Gajim is running" msgstr "Проверка дали Gajim е стартиран" #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "Липсващ аргумент „contact_jid“" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "„%s“ не е в списъка ви.\n" "Укажете акаунт за изпращането на това съобщение." #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "Нямате активен акаунт" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "" "Изглежда Gajim не е стартиран, така че не може да ползвате gajim-remote." #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" "Употреба: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Аргументи:" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "%s не е намерен" #: gajim/gajim_remote.py:383 #, fuzzy, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Употреба: %s команда [аргументи]\n" "Командата е една от:\n" #: gajim/gajim_remote.py:453 #, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Твърде много аргументи. \n" "Напишете „%(basename)s help %(command)s“ за повече информация" #: gajim/gajim_remote.py:458 #, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Не е указан аргумент „%(arg)s“.\n" "Напишете „%(basename)s help %(command)s“ за повече информация" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "дванадесет" #: gajim/common/fuzzyclock.py:36 msgid "one" msgstr "един" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "два" #: gajim/common/fuzzyclock.py:36 msgid "three" msgstr "три" #: gajim/common/fuzzyclock.py:36 msgid "four" msgstr "четири" #: gajim/common/fuzzyclock.py:37 msgid "five" msgstr "пет" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "шест" #: gajim/common/fuzzyclock.py:37 msgid "seven" msgstr "седем" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "осем" #: gajim/common/fuzzyclock.py:37 msgid "nine" msgstr "девет" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "десет" #: gajim/common/fuzzyclock.py:38 msgid "eleven" msgstr "единадесет" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "%(0)s часа" #: gajim/common/fuzzyclock.py:46 #, python-format msgid "five past %(0)s" msgstr "%(0)s и пет" #: gajim/common/fuzzyclock.py:47 #, python-format msgid "ten past %(0)s" msgstr "%(0)s и десет" #: gajim/common/fuzzyclock.py:48 #, python-format msgid "quarter past %(0)s" msgstr "%(0)s и петнадесет" #: gajim/common/fuzzyclock.py:49 #, python-format msgid "twenty past %(0)s" msgstr "%(0)s и двадесет" #: gajim/common/fuzzyclock.py:50 #, python-format msgid "twenty five past %(0)s" msgstr "%(0)s и двадесет и пет" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "%(0)s и половина" #: gajim/common/fuzzyclock.py:52 #, python-format msgid "twenty five to %(1)s" msgstr "%(1)s без двадесет и пет" #: gajim/common/fuzzyclock.py:53 #, python-format msgid "twenty to %(1)s" msgstr "%(1)s без двадесет" #: gajim/common/fuzzyclock.py:54 #, python-format msgid "quarter to %(1)s" msgstr "%(1)s без петнадесет" #: gajim/common/fuzzyclock.py:55 #, python-format msgid "ten to %(1)s" msgstr "%(1)s без десет" #: gajim/common/fuzzyclock.py:56 #, python-format msgid "five to %(1)s" msgstr "%(1)s без пет" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "%(1)s часа" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "Нощ" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "Рано сутрин" #: gajim/common/fuzzyclock.py:63 msgid "Morning" msgstr "Сутрин" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "Почти обед" #: gajim/common/fuzzyclock.py:65 msgid "Noon" msgstr "Обед" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "Следобед" #: gajim/common/fuzzyclock.py:67 msgid "Evening" msgstr "Вечер" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "Късно вечер" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "Началото на седмицата" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "Средата на седмицата" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "Края на седмицата" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "Събота и неделя!" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, python-format msgid "%s is a directory but should be a file" msgstr "%s e папка, а би трябвало да е файл" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Унищожаване на %s" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 msgid "Room has been destroyed" msgstr "Стаята е била унищожена" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "Вместо това може да влезете в тази стая: %s" #: gajim/common/connection_handlers_events.py:598 #, python-format msgid "Unknown SSL error: %d" msgstr "Неизвестна грешка на SSL: %d" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Ново съобщение от %(nickname)s" msgstr[1] "Ново съобщение от %(nickname)s" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s промени състоянието си" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s се включи" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "%(nickname)s се изключи" #: gajim/common/contacts.py:427 msgid "Not in roster" msgstr "Не е в списъка" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "" #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "Време в минути, след което състоянието да се променя на „Отсъствам“." #: gajim/common/config.py:87 msgid "$S (Away as a result of being idle more than $T min)" msgstr "$S (Отсъствам поради липса на активност над $T мин)" #: gajim/common/config.py:87 #, fuzzy msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" "$S ще бъде заменено от текущото съобщение за състояние, а $T от времето на " "отсъствие." #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "" "Време в минути, след което състоянието да се променя на „Не съм на " "разположение“." #: gajim/common/config.py:90 msgid "$S (Not available as a result of being idle more than $T min)" msgstr "$S (Не съм на разположение поради липса на активност над $T мин)" #: gajim/common/config.py:90 #, fuzzy msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" "$S ще бъде заменено от текущото съобщение за състояние, а $T от времето на " "отсъствие." #: gajim/common/config.py:93 msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "Показване на събитието в спис_ъка" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "Показване на събитието в спис_ъка" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "Показване на нови съобщения в изскачащ прозорец?" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Запитване за файлов трансфер" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Файловият трансфер е прекъснат" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "Уведомяване чрез изскачащ прозорец при завършване на файловия трансфер" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "Покана за разговор в стая" #: gajim/common/config.py:106 #, fuzzy msgid "Background color of status changed notification" msgstr "Цвят на фона на контактите, които се включват." #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "" "Списък (разделен с интервали) на редове (акаунти и групи), които да се " "свиват автоматично." #: gajim/common/config.py:109 msgid "default" msgstr "по подразбиране" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "Език, който да се използва за проверката на правописа" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" "„always“ - изписване на часа при всяко съобщение.\n" "„sometimes“ - изписване на часа през интервал, указан в " "„print_ichat_every_foo_minutes“.\n" "„never“ - никога да не се изписва часа." #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" "Изписване на часа при разговорите чрез „Относителен часовник“. Стойността на " "относителността е от 1 до 4, или 0 за премахването на относителния часовник. " "1 е най-прецизния часовник, 4 е най-относителния. Това е в сила само ако " "опцията „print_time“ е настроена на „sometimes“." #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "Тълкуване на двойки от „* / _“ като възможни символи за форматиране." #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "Ако е активирана, не се премахват */_. Така *абв* ще е в получер стил, но " "със символите * *." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" "Ако е избрана, използва реструктуриран текст за изпращане на HTML и " "форматиране в ASCII, ако е указано. За синтаксиса, вижте http://docutils." "sourceforge.net/docs/ref/rst/restructuredtext.html (Ако искате да използвате " "това, инсталирайте docutils)" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" "Знак за добавяне след името на псевдонима при използване на автоматично " "допълване (TAB) в стая." #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" "Знак, който да се предложи да бъде добавен след желания псевдоним, когато " "той вече е използван от някой в стаята." #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" "Чрез тази опция може да персонализирате начина на изписване на времето в " "разговор. Например „[%H:%M] “ ще показва „час:минути] “. Вижте " "документацията на Питон относно „strftime“ за повече информация: http://docs." "python.org/lib/module-time.html" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "Знаци, които се изобразяват в разговори преди псевдонима" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "Знаци, които се изобразяват в разговори след псевдонима" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Добавяне на * и [n] към заглавието на списъка?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Колко реда от предишния разговор да за запомнят при повторното отваряне на " "подпрозорец/прозорец." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" #: gajim/common/config.py:177 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "Изпращане на съобщение при Ctrl+Enter и нов ред с „Enter“." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Колко реда да се запазват за Ctrl+горна стрелка." #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Или определен адрес, съдържащ %s, където %s е думата/фразата, или " "„WIKTIONARY“, което означава използване на wiktionary." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "" "Ако тази опция е избрана, Gajim може да се контролира отдалечено чрез gajim-" "remote." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" "Изпращане на уведомления за състоянието на разговор. Може да бъде „all“, " "„composing_only“, „disabled“." #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" "Показвани уведомления за състоянието на разговора в прозорците за разговор. " "Може да бъде „all“, „composing_only“, „disabled“." #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" "Когато не се изписва часа на всяко съобщение („print_time“ е настроено на " "„sometimes“), да се показва на всеки x минути." #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Питане преди затваряне на подпрозорец/прозорец на стая." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" "Винаги да се пита преди затваряне на подпрозорец/прозорец на стая от този " "списък с адреси на стаи." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" "Никога да не се пита преди затваряне на подпрозорец/прозорец на стая от този " "списък с адреси на стаи." #: gajim/common/config.py:196 msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" #: gajim/common/config.py:199 #, fuzzy msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" "Списък от хостове, разделен със запетаи, които се изпращат като допълнение " "към локалните интерфейси за файлов трансфер в случай, че се ползва NAT/" "пренасочване на портове." #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "Според стандарта на IEC KiB = 1024 байта, KB = 1000 байта." #: gajim/common/config.py:202 #, fuzzy msgid "Notify of events in the notification area." msgstr "Уведомяване за събития в областта за уведомяване." #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Показване на подпрозорец при един разговор?" #: gajim/common/config.py:210 msgid "Show tabbed notebook border in chat windows?" msgstr "Показване на границата на подпрозореца в прозорците за разговор?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Показване на бутона за затваряне на подпрозореца?" #: gajim/common/config.py:224 msgid "Preview new messages in notification popup?" msgstr "Показване на нови съобщения в изскачащ прозорец?" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" "Списък с думи, отделени с точка и запетая, които ще се осветяват при " "разговор в стая." #: gajim/common/config.py:228 #, fuzzy msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" "Ако е активирана, се спира програмата при натискане на бутона „X“ на " "администратора на прозорци. Тази настройка е валидна само ако се използва " "иконата в областта за уведомяване." #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 #, fuzzy msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" "Ако е активирана, ще се изобразява икона във всеки подпрозорец, съдържащ " "непрочетени съобщения. В зависимост от темата иконата може да бъде анимирана." #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" "Ако е активирана, ще се показва съобщението за състояние, ако има такова, на " "всеки контакт под името му списъка." #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "" "Позиция на аватара в списъка. Може да е ляво (left) или дясно (right)." #: gajim/common/config.py:238 #, fuzzy msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" "Ако е изключена, вече няма да виждате реда за състоянието при разговорите, " "когато контактът променя състоянието си." #: gajim/common/config.py:239 #, fuzzy msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" "Може да бъде „none“, „all“ или „in_and_out“. Ако е „none“, няма да се " "изписват състоянията в стаите, когато някой член сменя съобщението си за " "състояние или влиза/излиза в стаята. Ако е „all“, ще се изписват всички " "съобщения за състояние. Ако е „in_and_out“, ще се изписва само „Сульо влезе " "в стаята“ или „Сульо напусна“." #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 #, fuzzy msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" "Ако е активирана, ще се използва по-малък шрифт от стандартния за " "възстановените съобщения." #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "Да не се показва аватара на транспорта." #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "Да не се показва списъка в панела." #: gajim/common/config.py:245 #, fuzzy msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" "Ако е активирана и инсталираните версии на GTK+ и PyGTK са поне 2.8, " "прозорецът ще мига (стандартното поведение при повечето мениджъри на " "прозорци) при задържане на чакащи събития." #: gajim/common/config.py:249 #, fuzzy msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" "Контролира прозореца, където се отварят нови съобщения.\n" "„always“ — Всички съобщения се отварят в един прозорец.\n" "„always_with_roster“ — Като „always“, но съобщенията са в общ прозорец със " "списъка.\n" "„never“ — Всички съобщения се отварят в собствен прозорец.\n" "„peracct“ — Съобщенията за всеки акаунт се отварят в специфичен прозорец.\n" "„pertype“ — Всеки тип съобщение (т.е. разговор и от стая) се отварят в " "специфичен прозорец." #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "" "Ако е изключена, повече няма да виждате аватар в прозореца за разговор." #: gajim/common/config.py:252 #, fuzzy msgid "If true, pressing the escape key closes a tab/window." msgstr "" "Ако е активирана, натискането на клавиша „Escape“ затваря прозореца/" "подпрозореца." #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "Скрива лентата в прозореца на стаята" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "Скрива лентата в прозорец за разговор с два контакта" #: gajim/common/config.py:255 msgid "Hides the group chat occupants list in group chat window." msgstr "Скрива списъка на участниците в прозореца на стаята." #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" "В разговор, показва псевдонима в началото на реда само ако не е същия човек, " "който е написал предното съобщение." #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "Отстъп, когато се използва смесване на последователен псевдоним." #: gajim/common/config.py:258 msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "" "Списък с цветове, разделени с „:“, които да се използват за оцветяване на " "псевдонимите в стаите." #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "Ctrl-TAB отива на следващия подпрозорец, когато всички са прочетени." #: gajim/common/config.py:260 #, fuzzy msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" "Да се показва ли диалогов прозорец за потвърждение при създаване на мета-" "контакти? Празен низ означава никога да не се показва диалогов прозорец." #: gajim/common/config.py:261 #, fuzzy msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" "Да се показва ли диалогов прозорец за потвърждение при създаване на мета-" "контакти? Празен низ означава никога да не се показва диалогов прозорец." #: gajim/common/config.py:262 #, fuzzy msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" "Да се показва ли диалогов прозорец за потвърждение при създаване на мета-" "контакти? Празен низ означава никога да не се показва диалогов прозорец." #: gajim/common/config.py:263 #, fuzzy msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" "Ако е активирана, ще може да настроите отрицателен приоритет за акаунта в " "прозореца за промяна на акаунти. ВНИМАВАЙТЕ, понеже когато сте свързани с " "отрицателен приоритет, НЯМА да получите нито едно съобщение от сървъра." #: gajim/common/config.py:264 #, fuzzy msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" "Ако е активирана, Gajim ще показва броя на включените контакти и общия брой " "в редовете за акаунти и групи." #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" "Може да е празно, „chat“ или „normal“. Ако не е празно, всички входящи " "съобщения се третират като от указания тип." #: gajim/common/config.py:266 #, fuzzy msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" "Ако е активирана, Gajim ще прелиства списъка избирайки контакта, който ви е " "изпратил последното съобщение, в случай, че прозорецът за разговор не е вече " "отворен." #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" "Необходимо време без активност преди прозорецът за промяна на състоянието да " "се затвори." #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" "Максимален брой редове, които да се показват в разговорите. Най-старите " "редове се изчистват." #: gajim/common/config.py:269 #, fuzzy msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" "Ако активирана, прозорците за уведомления от „notification-daemon“ ще бъдат " "прикрепени към иконата в областта за уведомяване." #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "Интервал между две проверки за липса на активност." #: gajim/common/config.py:271 #, fuzzy msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" "Валидни схеми на адреси. Само схемите в този списък ще бъдат достъпни като " "„истински“ адреси." #: gajim/common/config.py:272 msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 #, fuzzy msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" "Ако тази опция е избрана, няма да се пита за съобщение за състояние — ще се " "използва стандартно зададеното." #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 #, fuzzy msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" "Ако е активирана, Gajim ще използва набора на ключове на GNOME (gnome-" "keyring), ако е достъпен, за да запазва информация за паролите на акаунтите." #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" "Приоритетът ще се променя автоматично в съответствие със състоянието ви. " "Приоритетите се настройват в опциите „autopriority_*“." #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" "Състояние при автоматично включване. Може да е „online“, „chat“, „away“, " "„xa“, „dnd“ или „invisible“. ЗАБЕЛЕЖКА: Тази опция се използва само ако " "„restore_last_status“ е изключена." #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "Ако е активирана, възстановява се последното използвано състояние." #: gajim/common/config.py:325 msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" #: gajim/common/config.py:326 #, fuzzy msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "" "Ако е изключена, повече няма да виждате аватар в прозореца за разговор." #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" "Ако е изключена, не се се подписват съобщенията за състояние с ключ на GPG, " "дори и да е конфигуриран." #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 #, fuzzy msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" "Показване на предупреждение преди изпращане на паролата при нешифрирана " "връзка." #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "" "Показване на предупреждение преди използване на стандартната библиотека на " "SSL." #: gajim/common/config.py:337 #, fuzzy msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" "Показване на предупреждение преди изпращане на паролата при нешифрирана " "връзка." #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "Списък (разделен с шпации) от грешки на SSL, които да се пренебрегват." #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "" #: gajim/common/config.py:354 #, fuzzy msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" "Колко секунди да се чака за отговор на изпратен пакет за поддържане на " "връзката, преди да да се опита свързване наново." #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "Заобикалка заради Jabberd2" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" "Ако тази опция е избрана, ще се използва вашия IP адрес и сървърите-" "посредници, указани в опцията file_transfer_proxies, за файлови трансфери." #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "Отговор на заявки" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "Изпратени заявки" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "" "Ако тази опция е избрана, контактите ще могат да откриват операционната " "система, която използвате." #: gajim/common/config.py:386 #, fuzzy msgid "Allow Gajim to send your local time." msgstr "%s иска да ви изпрати файл." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Попълнете данните за контакта, който искате да добавите" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Използване на удостоверяване" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Използване на удостоверяване" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Използване на удостоверяване" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 #, fuzzy msgid "Language for which misspelled words will be checked" msgstr "Език, за който желаете да се проверяват сгрешените думи." #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" #: gajim/common/config.py:442 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "Спя" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Връщам се скоро" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Ще се върна след малко." #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "Хапвам" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "Хапвам, така че ми оставете съобщение." #: gajim/common/config.py:454 msgid "Movie" msgstr "Филм" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "Гледам филм." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "Работя" #: gajim/common/config.py:455 msgid "I'm working." msgstr "Работя." #: gajim/common/config.py:456 msgid "Phone" msgstr "Телефон" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Говоря по телефона." #: gajim/common/config.py:457 msgid "Out" msgstr "Навън" #: gajim/common/config.py:457 msgid "I'm out enjoying life." msgstr "Наслаждавам се на живота навън." #: gajim/common/config.py:468 msgid "I'm available." msgstr "На линия съм." #: gajim/common/config.py:469 msgid "I'm free for chat." msgstr "Свободен за разговор." #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "Сега се връщам." #: gajim/common/config.py:471 msgid "I'm not available." msgstr "Не съм на разположение." #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "Не ме притеснявайте." #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "Довиждане!" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" "Звукът, който да се възпроизвежда, когато в стаята се изпише дума от " "„muc_higlighted_words“ или когато съобщение съдържа псевдонима ви." #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "Звук за изпълнение при получаване на каквото и да е съобщение в стая." #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "За" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Грешка: %s не може да бъде отворен за четене" #: gajim/common/const.py:205 msgid "Doing Chores" msgstr "Домакинствам" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "Купувам хранителни продукти" #: gajim/common/const.py:207 msgid "Cleaning" msgstr "Чистя" #: gajim/common/const.py:208 msgid "Cooking" msgstr "Готвя" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "Ремонтирам" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "Мия чиниите" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "Пера" #: gajim/common/const.py:212 msgid "Gardening" msgstr "Работя в градината" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "Изпълнявам поръчка" #: gajim/common/const.py:214 msgid "Walking the Dog" msgstr "Разхождам кучето" #: gajim/common/const.py:216 msgid "Drinking" msgstr "Пия" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "Пия бира" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "Пия кафе" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "Пия чай" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "Похапвам" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "Закусвам" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "Вечерям" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "Обядвам" #: gajim/common/const.py:227 msgid "Exercising" msgstr "Правя упражнения" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "Карам велосипед" #: gajim/common/const.py:229 msgid "Dancing" msgstr "Танцувам" #: gajim/common/const.py:230 msgid "Hiking" msgstr "На поход съм" #: gajim/common/const.py:231 msgid "Jogging" msgstr "Тичам за здраве" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "Спортувам" #: gajim/common/const.py:233 msgid "Running" msgstr "Бягам" #: gajim/common/const.py:234 msgid "Skiing" msgstr "Карам ски" #: gajim/common/const.py:235 msgid "Swimming" msgstr "Плувам" #: gajim/common/const.py:236 msgid "Working out" msgstr "Тренирам" #: gajim/common/const.py:238 msgid "Grooming" msgstr "Поддържам се" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "В Спа-центъра" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "Мия си зъбите" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "Подстригвам се" #: gajim/common/const.py:242 msgid "Shaving" msgstr "Бръсна се" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "Във ваната" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "Взимам си душ" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "На среща" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Бездеен" #: gajim/common/const.py:249 msgid "Day Off" msgstr "Почивен ден" #: gajim/common/const.py:250 msgid "Hanging out" msgstr "Вися си" #: gajim/common/const.py:251 msgid "Hiding" msgstr "Крия се" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "В отпуск" #: gajim/common/const.py:253 msgid "Praying" msgstr "Моля се" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "Планиран отдих" #: gajim/common/const.py:256 msgid "Thinking" msgstr "Мисля" #: gajim/common/const.py:258 msgid "Relaxing" msgstr "Почивам" #: gajim/common/const.py:259 msgid "Fishing" msgstr "Ловя риба" #: gajim/common/const.py:260 msgid "Gaming" msgstr "Играя" #: gajim/common/const.py:261 msgid "Going out" msgstr "Навън съм" #: gajim/common/const.py:262 msgid "Partying" msgstr "На купон съм" #: gajim/common/const.py:263 msgid "Reading" msgstr "Чета" #: gajim/common/const.py:264 msgid "Rehearsing" msgstr "Репетирам" #: gajim/common/const.py:265 msgid "Shopping" msgstr "На пазар съм" #: gajim/common/const.py:266 msgid "Smoking" msgstr "Пуша" #: gajim/common/const.py:267 msgid "Socializing" msgstr "Общувам" #: gajim/common/const.py:268 msgid "Sunbathing" msgstr "На плаж съм" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "Гледам телевизия" #: gajim/common/const.py:270 msgid "Watching a Movie" msgstr "Гледам филм" #: gajim/common/const.py:272 msgid "Talking" msgstr "Разговарям" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "На четири очи" #: gajim/common/const.py:274 msgid "On the Phone" msgstr "Говоря по телефона" #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "Говоря по видеотелефона" #: gajim/common/const.py:277 msgid "Traveling" msgstr "Пътувам" #: gajim/common/const.py:278 msgid "Commuting" msgstr "Пътувам от/до работа" #: gajim/common/const.py:280 msgid "Driving" msgstr "Карам велосипед" #: gajim/common/const.py:281 msgid "In a Car" msgstr "В колата" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "В автобуса" #: gajim/common/const.py:283 msgid "On a Plane" msgstr "В самолета" #: gajim/common/const.py:284 msgid "On a Train" msgstr "Във влака" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "На екскурзия" #: gajim/common/const.py:286 msgid "Walking" msgstr "Разхождам се" #: gajim/common/const.py:289 msgid "Coding" msgstr "Програмирам" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "На съвещание" #: gajim/common/const.py:291 msgid "Studying" msgstr "Уча" #: gajim/common/const.py:292 msgid "Writing" msgstr "Пиша" #: gajim/common/const.py:295 msgid "Afraid" msgstr "Уплашен" #: gajim/common/const.py:296 msgid "Amazed" msgstr "Изумен" #: gajim/common/const.py:297 msgid "Amorous" msgstr "Страстен" #: gajim/common/const.py:298 msgid "Angry" msgstr "Ядосан" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "Раздразнен" #: gajim/common/const.py:300 msgid "Anxious" msgstr "Обезпокоен" #: gajim/common/const.py:301 msgid "Aroused" msgstr "Възбуден" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "Засрамен" #: gajim/common/const.py:303 msgid "Bored" msgstr "Отегчен" #: gajim/common/const.py:304 msgid "Brave" msgstr "Смел" #: gajim/common/const.py:305 msgid "Calm" msgstr "Спокоен" #: gajim/common/const.py:306 msgid "Cautious" msgstr "Предпазлив" #: gajim/common/const.py:307 msgid "Cold" msgstr "Бездушен" #: gajim/common/const.py:308 msgid "Confident" msgstr "Уверен" #: gajim/common/const.py:309 msgid "Confused" msgstr "Объркан" #: gajim/common/const.py:310 msgid "Contemplative" msgstr "Замислен" #: gajim/common/const.py:311 msgid "Contented" msgstr "Спорещ" #: gajim/common/const.py:312 msgid "Cranky" msgstr "Раздразнителен" #: gajim/common/const.py:313 msgid "Crazy" msgstr "Луд" #: gajim/common/const.py:314 msgid "Creative" msgstr "Съзидателен" #: gajim/common/const.py:315 msgid "Curious" msgstr "Любопитен" #: gajim/common/const.py:316 msgid "Dejected" msgstr "Обезсърчен" #: gajim/common/const.py:317 msgid "Depressed" msgstr "Депресиран" #: gajim/common/const.py:318 msgid "Disappointed" msgstr "Разочарован" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "Отвратен" #: gajim/common/const.py:320 msgid "Dismayed" msgstr "Уплашен" #: gajim/common/const.py:321 msgid "Distracted" msgstr "Шашнат" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "Смутен" #: gajim/common/const.py:323 msgid "Envious" msgstr "Завистлив" #: gajim/common/const.py:324 msgid "Excited" msgstr "Развълнуван" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "Склонен към флиртуване" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "Разочарован" #: gajim/common/const.py:327 msgid "Grateful" msgstr "Признателен" #: gajim/common/const.py:328 msgid "Grieving" msgstr "Опечален" #: gajim/common/const.py:329 msgid "Grumpy" msgstr "Кисел" #: gajim/common/const.py:330 msgid "Guilty" msgstr "Виновен" #: gajim/common/const.py:331 msgid "Happy" msgstr "Щастлив" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "С надежда" #: gajim/common/const.py:333 msgid "Hot" msgstr "Сгорещен" #: gajim/common/const.py:334 msgid "Humbled" msgstr "Скромен" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "Унизен" #: gajim/common/const.py:336 msgid "Hungry" msgstr "Гладен" #: gajim/common/const.py:337 msgid "Hurt" msgstr "Ранен" #: gajim/common/const.py:338 msgid "Impressed" msgstr "Впечатлен" #: gajim/common/const.py:339 msgid "In Awe" msgstr "Със страхопочитание" #: gajim/common/const.py:340 msgid "In Love" msgstr "Влюбен" #: gajim/common/const.py:341 msgid "Indignant" msgstr "Възмутен" #: gajim/common/const.py:342 msgid "Interested" msgstr "Заинтересуван" #: gajim/common/const.py:343 msgid "Intoxicated" msgstr "Пиян" #: gajim/common/const.py:344 msgid "Invincible" msgstr "Непобедим" #: gajim/common/const.py:345 msgid "Jealous" msgstr "Ревнив" #: gajim/common/const.py:346 msgid "Lonely" msgstr "Самотен" #: gajim/common/const.py:347 msgid "Lost" msgstr "Безпомощен" #: gajim/common/const.py:348 msgid "Lucky" msgstr "Късметлия" #: gajim/common/const.py:349 msgid "Mean" msgstr "Подъл" #: gajim/common/const.py:350 msgid "Moody" msgstr "Унил" #: gajim/common/const.py:351 msgid "Nervous" msgstr "Нервен" #: gajim/common/const.py:352 msgid "Neutral" msgstr "Безразличен" #: gajim/common/const.py:353 msgid "Offended" msgstr "Обиден" #: gajim/common/const.py:354 msgid "Outraged" msgstr "Оскърбен" #: gajim/common/const.py:355 msgid "Playful" msgstr "Игрив" #: gajim/common/const.py:356 msgid "Proud" msgstr "Горд" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "Отпуснат" #: gajim/common/const.py:358 msgid "Relieved" msgstr "Облекчен" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "Разкайващ се" #: gajim/common/const.py:360 msgid "Restless" msgstr "Неспокоен" #: gajim/common/const.py:361 msgid "Sad" msgstr "Тъжен" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "Саркастичен" #: gajim/common/const.py:363 msgid "Satisfied" msgstr "Удовлетворен" #: gajim/common/const.py:364 msgid "Serious" msgstr "Сериозен" #: gajim/common/const.py:365 msgid "Shocked" msgstr "Шокиран" #: gajim/common/const.py:366 msgid "Shy" msgstr "Срамежлив" #: gajim/common/const.py:367 msgid "Sick" msgstr "Болен" #: gajim/common/const.py:368 msgid "Sleepy" msgstr "Сънен" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "Спонтанен" #: gajim/common/const.py:370 msgid "Stressed" msgstr "Стресиран" #: gajim/common/const.py:371 msgid "Strong" msgstr "Твърд" #: gajim/common/const.py:372 msgid "Surprised" msgstr "Изненадан" #: gajim/common/const.py:373 msgid "Thankful" msgstr "Благодарен" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "Жаден" #: gajim/common/const.py:375 msgid "Tired" msgstr "Уморен" #: gajim/common/const.py:376 msgid "Undefined" msgstr "Неопределен" #: gajim/common/const.py:377 msgid "Weak" msgstr "Слаб" #: gajim/common/const.py:378 msgid "Worried" msgstr "Обезпокоен" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "по подразбиране" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "морска" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Крия се" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "Акаунт" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Акаунт" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Описание" #: gajim/common/const.py:391 #, fuzzy msgid "error" msgstr "Грешка." #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "един" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 msgid "room" msgstr "стая" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "Неуспех при получаването на сертификата на издателя" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "Неуспех при получаването на списъка с отменени сертификати" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "Неуспех при дешифрирането на подписа на сертификата" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "Неуспех при дешифрирането на подписа на списъка с отменени сертификати" #: gajim/common/const.py:412 msgid "Unable to decode issuer public key" msgstr "Неуспех при декодирането на публичния ключ на издателя" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "Грешка при проверката на подписа на сертификата" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "Грешка при проверката на подписа на списъка с отменени сертификати" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "Сертификатът все още не е валиден" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "Валидността на сертификата е изтекла" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "Списъкът с отменени сертификати все още не е валиден" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "Валидността на списъка с отменени сертификати е изтекла" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "Грешка при форматирането на полето „notBefore“ на сертификата" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "Грешка при форматирането на полето „notAfter“ на сертификата" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "" "Грешка при форматирането на полето „lastUpdate“ на списъка с отменени " "сертификати" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "" "Грешка при форматирането на полето „nextUpdate“ на списъка с отменени " "сертификати" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "Изчерпана памет" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "Само-подписан сертификат" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "Само-подписан сертификат в удостоверителската верига" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "Неуспех при получаването на сертификата на издателя" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "Неуспех при проверката на първия сертификат" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "Удостоверителската верига е твърде дълга" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "Сертификатът е отменен" #: gajim/common/const.py:430 msgid "Invalid CA certificate" msgstr "Невалиден сертификат на удостоверителя" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "Максималната дължина на пътя е надвишена" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "Неподдържана цел на сертификата" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "Сертификатът не е доверен" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "Сертификатът е отхвърлен" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "Несъответствие на издателя на сертификата" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "Несъответствие на идентификатора и сертифициращия орган" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "Несъответствие на серийния номер на издателя и сертифициращия орган" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "Основната употреба не включва подписване на сертификати" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "Грешка на приложението за проверка" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "%s не е валидно ниво за дневник" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Връзката на акаунт „%s“ се разпадна" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "Свържете се наново." #: gajim/common/connection.py:740 #, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "" "Сървърът „%(name)s“ отговори погрешно на запитването за регистрация: " "%(error)s" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "Сървърът „%s“ предостави различна форма за регистрация" #: gajim/common/connection.py:1090 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Неуспех при свързване с „%s“" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Неуспех при свързване с „%s“" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Проверете връзката или опитайте отново по-късно." #: gajim/common/connection.py:1100 #, fuzzy, python-format msgid "Server replied: %s" msgstr "Запазен в: %s" #: gajim/common/connection.py:1115 msgid "Connection to proxy failed" msgstr "Неуспех при свързването със сървъра-посредник" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, python-format msgid "Could not connect to account %s" msgstr "Неуспех при свързване с акаунт „%s“" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "Връзката на акаунт „%s“ се разпадна. Опит за повторно свързване." #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Неуспех при свързване с „%s“" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "Неуспех при удостоверяването с „%s“" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Проверете дали името и паролата са правилни." #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "На този компютър няма инсталиран модул на Питон за D-Bus" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "Възможностите за D-Bus не могат да бъдат използвани" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "На тази машина няма инсталиран D-Bus или липсва модула за Питон" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "На тази машина няма инсталиран D-Bus или липсва модула за Питон" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Стандартно съобщение" #: gajim/common/multimedia_helpers.py:70 msgid "Audio test" msgstr "" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Размер: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Файл: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "зелена" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, fuzzy, python-format msgid "%s configuration error" msgstr "Настройки на стаята" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Невалиден символ в името на хоста." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Необходим е адрес на сървъра." #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Невалиден символ в потребителското име." #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "Невалиден символ в ресурса." #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "_Зает" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "_Не съм на разположение" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "_Свободен за разговор" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "Временно прекъснат" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "Свързване" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "_Отсъствам" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "_Изключен" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "Не_видим" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "Неизвестно" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "Има грешки" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "Няма" #: gajim/common/helpers.py:315 msgid "To" msgstr "За" #: gajim/common/helpers.py:317 msgid "From" msgstr "От" #: gajim/common/helpers.py:319 msgid "Both" msgstr "Двустранно" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "Неизвестна" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "Няма" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Записване" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "Не е установен" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Председатели" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Председател" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Участници" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Участник" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Посетители" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Посетител" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "обръща внимание на разговора" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "прави нещо друго" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "пише съобщение…" #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "спря да пише съобщение" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "затвори прозореца или подпрозореца" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s GiB" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s GB" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s MiB" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s MB" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s KB" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s KB" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s B" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "%d непрочетено съобщение" msgstr[1] "%d непрочетени съобщения" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr " от стая %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, fuzzy, python-format msgid "from user %s" msgstr " от потребител %s" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr " от %s" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "%d чакащо събитие" msgstr[1] "%d чакащи събития" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Бих искал(а) да ви добавя към списъка си." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 msgid "Timeout loading image" msgstr "Изтече времето за зареждане на изображението" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "Изображението е твърде голямо" #: gajim/common/helpers.py:1383 #, fuzzy msgid "PyCURL is not installed" msgstr "Списъкът с отменени сертификати все още не е валиден" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Изтече времето за зареждане на изображението" #: gajim/common/configpaths.py:85 #, python-format msgid "%s is a file but it should be a directory" msgstr "%s e файл, а би трябвало да е папка" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Спиране на програмата" #: gajim/common/exceptions.py:45 #, fuzzy, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" "Файлът „%s“ от базата от данни не може да бъде прочетен. Опитайте се да го " "поправите (вижте http://trac.gajim.org/wiki/DatabaseBackup) или изтриете " "(цялата история ще бъде загубена)." #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" "Услугата не е налична: Gajim не е стартиран или „remote_control“ е " "„Изключена“" #: gajim/common/exceptions.py:81 #, fuzzy, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "" "Липсва „session bus“.\n" "Опитайте се да прочетете http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/exceptions.py:93 #, fuzzy, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" "Липсва „session bus“.\n" "Опитайте се да прочетете http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 msgid "Please check if Avahi or Bonjour is installed." msgstr "Проверете дали Avahi или Bonjour е инсталиран." #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "Неуспех при стартирането на локална услуга" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, python-format msgid "Unable to bind to port %d." msgstr "Неуспех при свързването с порт %d." #: gajim/common/zeroconf/connection_zeroconf.py:217 #, fuzzy msgid "Please check if avahi/bonjour-daemon is running." msgstr "Проверете дали е стартиран avahi-daemon." #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, python-format msgid "Could not change status of account \"%s\"" msgstr "Неуспех при промяната на състоянието на акаунт „%s“" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "Проверете дали е стартиран avahi-daemon." #: gajim/common/zeroconf/connection_zeroconf.py:349 msgid "Your message could not be sent." msgstr "Съобщението ви не можа да бъде изпратено." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "Контактът е изключен. Съобщението ви не можа да бъде изпратено." #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "" "Неуспех при установяването на връзка с хоста: Изтичане на допустимото време " "при изпращането на данните." #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, python-format msgid "Error while adding service. %s" msgstr "Грешка при добавянето на услугата. %s" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "съобщение" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "" "Бих искал(а) да ви добавя към списъка си. I would like to add you to my " "roster." #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Грешка: %s" #: gajim/common/modules/httpupload.py:134 msgid "File is empty" msgstr "Файлът не съдържа нищо" #: gajim/common/modules/httpupload.py:137 msgid "File does not exist" msgstr "Файлът не съществува" #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 msgid "Change status information" msgstr "Промяна на информацията за състоянието" #: gajim/common/modules/adhoc_commands.py:113 msgid "Change status" msgstr "Промяна на състоянието" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "Настройване на съобщението за състояние и описанието му" #: gajim/common/modules/adhoc_commands.py:121 msgid "Free for chat" msgstr "Свободен за разговор" #: gajim/common/modules/adhoc_commands.py:122 msgid "Online" msgstr "На линия" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "Не съм на разположение" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "Не ме притеснявайте" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "Изключен - изключване" #: gajim/common/modules/adhoc_commands.py:132 msgid "Presence description:" msgstr "Описание на състоянието:" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "Състоянието беше променено." #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 msgid "Leave Groupchats" msgstr "Излизане от стаите" #: gajim/common/modules/adhoc_commands.py:231 #, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s от стая %(room_jid)s" #: gajim/common/modules/adhoc_commands.py:235 msgid "You have not joined a groupchat." msgstr "Не сте влезли в стая." #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "Изберете стаите, които искате да напуснете" #: gajim/common/modules/adhoc_commands.py:292 msgid "You left the following groupchats:" msgstr "Напуснахте следните стаи:" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "Неизвестен изпълнител" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "Неизвестно заглавие" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "Неизвестен източник" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" "\"%(title)s\" на %(artist)s\n" "от %(source)s" #: gajim/common/modules/roster_item_exchange.py:100 #, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "" #: gajim/common/modules/roster_item_exchange.py:104 #, fuzzy msgid "Sent contacts:" msgstr "Покана на _контакти" #: gajim/data/gui/blocked_contacts_window.ui:13 msgid "Blocked Contacts" msgstr "Блокирани контакти" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Редактор на настройки за напреднали" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Филтър:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Описание" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "" "ЗАБЕЛЕЖКА: Трябва да рестартирате Gajim, за да влязат в сила някои от " "настройките" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "Възстановяване на стандартните _цветове" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Автоматично влизане" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Акаунт" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Стая:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Парола:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "_Добавяне на стаята към отметките (Ctrl+B)" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "_Добавяне на стаята към отметките" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "в _стаи" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 #, fuzzy msgid "HTTP Connect" msgstr "" "Свързване по HTTP\n" "SOCKS5" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Настройки на сървъра-посредник" #: gajim/data/gui/manage_proxies_window.ui:148 msgid "_Name:" msgstr "_Име:" #: gajim/data/gui/manage_proxies_window.ui:161 #, fuzzy msgid "_Type:" msgstr "Тип:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Настройки" #: gajim/data/gui/manage_proxies_window.ui:234 msgid "_BOSH URL:" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:258 #, fuzzy msgid "Proxy _Host:" msgstr "Сървър-посредник:" #: gajim/data/gui/manage_proxies_window.ui:269 msgid "Use HTTP prox_y" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:288 #, fuzzy msgid "Proxy _Port:" msgstr "По_рт:" #: gajim/data/gui/manage_proxies_window.ui:299 #, fuzzy msgid "Use proxy auth_entication" msgstr "Използване на удостоверяване" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "И_ме на потребител:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "Паро_ла:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Настройки" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Запазване на паролата" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Промяна на парола" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Информация за контакта" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "Локален JID:" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "Ресурс:" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Състояние:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Запазване на разговорите" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 msgid "Contact" msgstr "Контакт" #: gajim/data/gui/zeroconf_information_window.ui:234 msgid "First Name:" msgstr "Собствено име:" #: gajim/data/gui/zeroconf_information_window.ui:247 msgid "Last Name:" msgstr "Фамилия:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "Jabber ID:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "Е-поща:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 msgid "Personal" msgstr "Лични данни" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "_Изпращане на лично съобщение" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Изпращане на _файл" #: gajim/data/gui/gc_occupants_menu.ui:29 msgid "Occupant Actions" msgstr "_Действия на участника" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Глас" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "_Председател" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Член" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Администратор" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "Со_бственик" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "_Изритване" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Забраняване на достъпа" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "Добавяне към _списъка…" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "_Изпълнение на команда" #: gajim/data/gui/tooltip_roster_contact.ui:125 #, fuzzy msgid "Idle since:" msgstr " от %s" #: gajim/data/gui/tooltip_roster_contact.ui:151 msgid "Mood:" msgstr "Настроение:" #: gajim/data/gui/tooltip_roster_contact.ui:164 msgid "Activity:" msgstr "Дейност:" #: gajim/data/gui/tooltip_roster_contact.ui:178 #, fuzzy msgid "Tune:" msgstr "Песен:" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Уведомления" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP: " #: gajim/data/gui/tooltip_roster_contact.ui:281 #, fuzzy msgid "Subscription:" msgstr "Записване: " #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "_Състояние" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Промяна на акаунт…" #: gajim/data/gui/atom_entry_window.ui:8 msgid "New entry received" msgstr "Получен е нов запис" #: gajim/data/gui/atom_entry_window.ui:92 msgid "Feed name:" msgstr "Име на емисията:" #: gajim/data/gui/atom_entry_window.ui:119 msgid "Entry:" msgstr "Запис:" #: gajim/data/gui/atom_entry_window.ui:131 msgid "Last modified:" msgstr "Последно променена:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 msgid "Change _Nickname..." msgstr "Смяна на псе_вдоним…" #: gajim/data/gui/gc_control_popup_menu.ui:20 msgid "_Manage Room" msgstr "_Управление на стаята" #: gajim/data/gui/gc_control_popup_menu.ui:31 msgid "Change _Subject..." msgstr "Промяна на _темата…" #: gajim/data/gui/gc_control_popup_menu.ui:38 msgid "Configure _Room..." msgstr "Настройки на _стаята…" #: gajim/data/gui/gc_control_popup_menu.ui:52 msgid "_Destroy Room" msgstr "_Унищожаване на стаята" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "_Минимизиране при затваряне" #: gajim/data/gui/gc_control_popup_menu.ui:85 #, fuzzy msgid "_Request Voice" msgstr "_Глас" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "Аватар:" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Избор на изображение" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 #, fuzzy msgid "Full Name" msgstr "Име" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Телефон" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Формат: гггг-мм-дд" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 #, fuzzy msgid "Birthday" msgstr "Рожден ден:" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Страница в Интернет:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "Е-поща:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 #, fuzzy msgid "Jabber ID" msgstr "Jabber ID:" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 #, fuzzy msgid "Family" msgstr "Фамилия:" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 msgid "Given" msgstr "" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Средата на седмицата" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Настройки" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Наставка:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Стресиран" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "Допълнителен адрес:" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 msgid "City" msgstr "" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Състояние" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 #, fuzzy msgid "Postal Code" msgstr "Пощенски код:" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "Акаунт" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 msgid "Address" msgstr "Адрес" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Име:" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Фирма:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 #, fuzzy msgid "Department" msgstr "Отдел:" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Условие" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Област/Щат:" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Работа" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Относно" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "П_родължаване" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "П_ауза" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Отказ" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Отваряне на папката" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Файлови трансфери" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "списък с файлови трансфери" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "Списък с активни, завършили и прекъснати файлови трансфери" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "Из_чистване" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "" "Премахва завършилите, прекъснатите или провалени файлови трансфери от списъка" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Премахване на файловия трансфер от списъка." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "Това действие премахва файлов трансфер от списъка. Ако трансферът е активен, " "първо се прекъсва и след това се премахва." #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "Отменя избрания файлов трансфер и изтрива непълния файл" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Отменя файловия трансфер" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Отменя избрания файлов трансфер" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "Изпра_щане и затваряне" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Скрива прозореца" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Уведомяване при завършване на файловия трансфер" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "Уведомяване чрез изскачащ прозорец при завършване на файловия трансфер" #: gajim/data/gui/filetransfers.ui:229 msgid "Shows a list of file transfers between you and others" msgstr "Показва списък с файловите трансфери между вас и останалите" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Получер" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Курсив" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 #, fuzzy msgid "Underline" msgstr "Неопределен" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 #, fuzzy msgid "Strike" msgstr "Болен" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "Цвят" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 msgid "Font" msgstr "" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Информация за контакта" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Избор на файл за изпращане…" #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Списък с емотикони (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Събитие" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Събитие" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Шрифт" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "№" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Отсъствам" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "П_оказване на списъка" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "Сървър" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "По подразбиране" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "Файлът не съдържа нищо" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Ресурс:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Състояние" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Клиент:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 #, fuzzy msgid "System" msgstr "Система:" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Име на контакта" #: gajim/data/gui/vcard_information_window.ui:240 #, fuzzy msgid "User avatar" msgstr "Аватар:" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Настроен аватар:" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 msgid "Ask" msgstr "" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Записване: " #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 msgid "Personal Info" msgstr "Лични данни" #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "Коментари" #: gajim/data/gui/preferences_window.ui:38 msgid "Use default applications" msgstr "" #: gajim/data/gui/preferences_window.ui:41 msgid "Custom" msgstr "Персонални" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Всички състояния" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 #, fuzzy msgid "Composing only" msgstr "Пише" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Изключени" #: gajim/data/gui/preferences_window.ui:89 msgid "Only when pending events" msgstr "" #: gajim/data/gui/preferences_window.ui:103 msgid "Pop it up" msgstr "" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "Уведомяване за _изключващи се контакти" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "Показване на събитието в спис_ъка" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 #, fuzzy msgid "Last state" msgstr "Последно състояние: %s" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "Показване на _аватари на контактите в списъка" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Ако тази опция е избрана, Gajim ще изобразява аватари на контакти в списъка " "и стаите" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "Показване на _съобщенията за състояние на контактите в списъка" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Ако тази опция е избрана, съобщенията за състояние на контактите ще се " "показват под имената им в списъка и в стаите" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Показване на _настроенията на контактите в списъка" #: gajim/data/gui/preferences_window.ui:254 msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "" "Ако тази опция е избрана, Gajim ще изобразява настроението на контактите в " "списъка." #: gajim/data/gui/preferences_window.ui:275 msgid "Sort contacts by status" msgstr "Подреждане на контактите по състояние" #: gajim/data/gui/preferences_window.ui:285 msgid "in _roster" msgstr "в с_писъка" #: gajim/data/gui/preferences_window.ui:302 msgid "in _group chats" msgstr "в _стаи" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "Изглед на списъка" #: gajim/data/gui/preferences_window.ui:359 #, fuzzy msgid "Spell _checker" msgstr "Проверка на правописа" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" "Ако тази опция е избрана, ще се осветяват правописни грешки в полетата за " "въвеждане на текст в прозорците за разговор. Ако не е избран език чрез " "натискане с десния бутон на мишката в полето за въвеждане, ще се използва " "езикът по подразбиране." #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "текст на съобщението" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 #, fuzzy msgid "_Window behavior" msgstr "_Поведение на прозорците:" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "П_оказване на списъка" #: gajim/data/gui/preferences_window.ui:484 msgid "_Ignore rich content in incoming messages" msgstr "_Пренебрегване на излишно форматиране на входящите съобщения" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" "Някои съобщения могат да включват „rich content“ (форматиране, цветове и т." "н.). Ако тази опция е избрана, Gajim ще изобразява само обикновения текст." #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Неуспех при влизането в стаята" #: gajim/data/gui/preferences_window.ui:523 msgid "Chat Appearance" msgstr "Изглед на разговорите" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "При получаване на ново събитие:" #: gajim/data/gui/preferences_window.ui:623 msgid "Notify me about contacts that sign _in" msgstr "Уведомяване за _включващи се контакти" #: gajim/data/gui/preferences_window.ui:641 msgid "Notify me about contacts that sign _out" msgstr "Уведомяване за _изключващи се контакти" #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Ще се появява съобщение за уведомяване в долния десен ъгъл на екрана при " "изключване на контакти" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" "Позволяване на прозорци/уведомления при _Отсъствам/Не съм на разположение/" "Зает/Невидим" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "" "Позволяване на прозорци/уведомления при _Отсъствам/Не съм на разположение/" "Зает/Невидим" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "Демон за уведомления" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Зрителни уведомления" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "Изпълнение на з_вуци" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "_Управление…" #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Звуци" #: gajim/data/gui/preferences_window.ui:861 msgid "Notifications" msgstr "Уведомления" #: gajim/data/gui/preferences_window.ui:898 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "Gajim може да изпраща и получава мета-информация, свързана с разговора с " "даден контакт. Тук може да укажете кои състояния бихте искали да се показват " "в прозорците за разговор." #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "Показване на уведомления при _разговор:" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim може да изпраща и получава мета-информация, свързана с разговора с " "даден контакт. Тук може да укажете кои състояния бихте искали да изпращате." #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "Изпращане на уведомления при _разговор:" #: gajim/data/gui/preferences_window.ui:987 msgid "Chat state notifications" msgstr "Уведомления за състояния на разговора" #: gajim/data/gui/preferences_window.ui:1009 msgid "Personal Events" msgstr "Лични събития" #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "„_Отсъствам“ след:" #: gajim/data/gui/preferences_window.ui:1047 msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" "Ако тази опция е избрана, Gajim ще променя състоянието на „Отсъствам“ когато " "компютърът не се използва." #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "„Не съм на _разположение“ след:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" "Ако тази опция е избрана, Gajim ще променя състоянието на „Не съм на " "разположение“ когато компютърът не се използва по-дълго време." #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "минути" #: gajim/data/gui/preferences_window.ui:1103 #, fuzzy msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" "Съобщение за автоматично състояние „Отсъствам“. Ако е празно, няма да се " "сменя текущото съобщение." #: gajim/data/gui/preferences_window.ui:1118 #, fuzzy msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" "Съобщение за автоматично състояние „Не съм на разположение“. Ако е празно, " "няма да се сменя текущото съобщение." #: gajim/data/gui/preferences_window.ui:1166 msgid "Auto Status" msgstr "Автоматично състояние" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Питане за съобщение за състояние при преминаване в режим:" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "_Включване" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "Изкл_ючване" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" "Ако тази опция е избрана, няма да се пита за съобщение за състояние — ще се " "използва стандартно зададеното." #: gajim/data/gui/preferences_window.ui:1291 msgid "Default Message" msgstr "Стандартно съобщение" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 msgid "Enabled" msgstr "Включено" #: gajim/data/gui/preferences_window.ui:1332 msgid "Status Messages" msgstr "Съобщения за състояние" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Настроени съобщения за състояние" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Тема" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Тема" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "Настройване на цвят и шрифт на интерфейса" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "gajim-remote" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "gajim-remote" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "_Набор икони за състояние:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Използване на и_кони за транспортите" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Ако тази опция е избрана, ще се използват специфични за протокола икони за " "състояние (т.е. контакт от MSN ще има еквивалентната за MSN икона за " "състоянията „На линия“, „Отсъствам“, „Зает“ и т.н.)." #: gajim/data/gui/preferences_window.ui:1724 msgid "_Convert ASCII Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1808 msgid "Style" msgstr "Стил" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Действия" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Презиме:" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Сървър:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Условия" #: gajim/data/gui/preferences_window.ui:2159 msgid "Audio/Video" msgstr "" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "_Програма за е-поща:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "Интернет _браузър:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "_Файлов мениджър:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Персонални" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Програми" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "Прене_брегване на събития от контакти, които не са в списъка" #: gajim/data/gui/preferences_window.ui:2363 msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Ако тази опция е избрана, Gajim ще игнорира входящи събития от " "неупълномощени контакти. Използвайте я внимателно, тъй като блокира всички " "съобщения от всеки контакт, който не е в списъка." #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Позволяване изпращането на _информация за ОС" #: gajim/data/gui/preferences_window.ui:2381 msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "" "Ако тази опция е избрана, контактите ще могат да откриват операционната " "система, която използвате." #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Позволяване изпращането на _информация за ОС" #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "" "Ако тази опция е избрана, контактите ще могат да откриват операционната " "система, която използвате." #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Позволяване изпращането на _информация за ОС" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 #, fuzzy msgid "_Manage..." msgstr "Управление на…" #: gajim/data/gui/preferences_window.ui:2500 msgid "Privacy" msgstr "Уединение" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "Запазване на промените на _състоянията на контактите" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Разни" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "_Отваряне…" #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Редактор на настройките за напреднали" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Започване на _разговор" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Изпращане на _еднократно съобщение…" #: gajim/data/gui/contact_context_menu.ui:28 msgid "Send _File..." msgstr "Изпращане на _файл…" #: gajim/data/gui/contact_context_menu.ui:44 msgid "Invite _Contacts" msgstr "Покана на _контакти" #: gajim/data/gui/contact_context_menu.ui:73 #, fuzzy msgid "E_xecute Command..." msgstr "Изпълнение на команда…" #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "_Управление на контакт" #: gajim/data/gui/contact_context_menu.ui:92 msgid "_Rename..." msgstr "_Преименуване…" #: gajim/data/gui/contact_context_menu.ui:99 msgid "Edit _Groups..." msgstr "Редактиране на _групи…" #: gajim/data/gui/contact_context_menu.ui:106 msgid "Assign Open_PGP Key..." msgstr "Задаване на ключ Open_PGP…" #: gajim/data/gui/contact_context_menu.ui:115 msgid "Add Special _Notification..." msgstr "Добавяне на специално _уведомление…" #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Записване" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "_Позволяване на този контакт да вижда състоянието ми" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "_Запитване за виждане на състоянието на контакта" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "За_брана за виждане на състоянието ми" #: gajim/data/gui/contact_context_menu.ui:182 msgid "_Unignore" msgstr "_Премахване на игнорирането" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "_Игнориране" #: gajim/data/gui/contact_context_menu.ui:197 msgid "_Add to Roster..." msgstr "Добавяне към _списъка…" #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim: Помощник за създаване на акаунт" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Трябва да имате акаунт, за да се свържете с\n" "мрежата на Джабър." #: gajim/data/gui/account_creation_wizard_window.ui:95 msgid "I already have an account I want to _use" msgstr "_Вече имам регистриран акаунт, който искам да използвам" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "_Искам да регистрирам нов акаунт" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Изберете една от опциите по-долу:" #: gajim/data/gui/account_creation_wizard_window.ui:167 msgid "Please fill in the data for your existing account" msgstr "Попълнете данните за съществуващия ви акаунт" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "_Jabber ID:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 #, fuzzy msgid "Anon_ymous authentication" msgstr "Използване на удостоверяване" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Парола:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Запазване на паро_ла" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Ако тази опция е избрана, ще се запомни паролата за този акаунт." #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "Изберете сървър" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "С_ървър:" #: gajim/data/gui/account_creation_wizard_window.ui:423 msgid "Prox_y:" msgstr "_Сървър-посредник:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Управление на…" #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Използване на нестандартен хост/порт" #: gajim/data/gui/account_creation_wizard_window.ui:491 msgid "_Hostname:" msgstr "_Хост:" #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "По_рт:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "На_преднали" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" "Добавяне на този сертификат към списъка с доверени сертификати.\n" "Отпечатък тип SHA1 на сертификата:\n" #: gajim/data/gui/account_creation_wizard_window.ui:687 msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Свързване със сървъра\n" "\n" "Изчакайте…" #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Свързване при натискане на бутона „Приключване“" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Настройване на профила при свързване" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Приключване" #: gajim/data/gui/privacy_lists_window.ui:34 msgid "Privacy Lists:" msgstr "Филтри за уединение:" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Адрес:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "_Отиване" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "Синхронизиране: избор на контакти" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 msgid "Select the contacts you want to synchronise" msgstr "Изберете контактите, които искате да синхронизирате" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Редактиране на групи" #: gajim/data/gui/search_window.ui:42 msgid "Please wait while retrieving search form..." msgstr "Изчакайте, докато се извлече формуляра за търсене…" #: gajim/data/gui/search_window.ui:80 msgid "_Add contact" msgstr "Добавяне на _контакт" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "_Търсене" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Настроени съобщения:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Дейност" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Напишете новото съобщение за състояние" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 msgid "Synchronise contacts" msgstr "Синхронизиране на контакти" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "Изберете акаунт, с който искате да синхронизирате" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "_Jabber ID:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "Псе_вдоним:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "_Група:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "_Акаунт:" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "П_ротокол:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "_Позволяване на този контакт да вижда състоянието ми" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "_Записване" #: gajim/data/gui/add_new_contact_window.ui:367 #, fuzzy msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" "Трябва да регистрирате този транспорт,\n" "за да може да добавите контакт от този\n" "протокол. Натиснете бутона „Регистриране“,\n" "за да продължите." #: gajim/data/gui/add_new_contact_window.ui:382 msgid "_Register" msgstr "_Регистриране" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" "Трябва да сте свързани към транспорта, за да може\n" "да добавите контакт от този протокол." #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "Пром_яна на съобщението за състояние" #: gajim/data/gui/change_mood_dialog.ui:73 msgid "Mood:" msgstr "Настроение:" #: gajim/data/gui/change_mood_dialog.ui:85 msgid "Message:" msgstr "Съобщение:" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Блокирал" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Неуспех при свързването" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Неуспех при свързването" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Описание" #: gajim/data/gui/plugins_window.ui:258 #, fuzzy msgid "Version" msgstr "Версия на GTK+:" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "_Упълномощаване" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 #, fuzzy msgid "Installed" msgstr "Блокирал" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "един" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "Двустранно" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "От" #: gajim/data/gui/privacy_list_window.ui:27 #, fuzzy msgid "to" msgstr "два" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "Филтър за уединение" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "Филтър за уединение" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "Активен за тази сесия" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "Активен при всяко стартиране" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "Списък с правила" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "Добавяне / Редактиране на правило" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "Позволяване на" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Отказване" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "Jabber ID" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "всички в групата" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "всички със записване" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "Всички" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "да ми изпраща съобщения" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "да ми изпращат лични съобщения" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "да виждат състоянието ми" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "да ми изпращат състоянието си" #: gajim/data/gui/privacy_list_window.ui:557 #, fuzzy msgid "All (including subscription)" msgstr "всички със записване" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "Ред:" #: gajim/data/gui/manage_sounds_window.ui:23 #, fuzzy msgid "Manage sounds" msgstr "Управление на акаунти" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Активен" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Събитие" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Избор на звук" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Премахване на акаунт _само от Gajim" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Премахване на акаунт от Gajim и от с_ървъра" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "Какво искате да направите?" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Изчакайте, докато се извлече списъка с команди…" #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Изберете команда за изпълнение:" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Проверка наново" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Изчакайте, докато командата се изпраща…" #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Този Джабър контакт не предлага никакви команди." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Възникна грешка:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Приключване" #: gajim/data/gui/account_context_menu.ui:20 msgid "_Personal Events" msgstr "_Лични събития" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "_Влизане в стая" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Добавяне на контакт…" #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Откриване на услуги" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "_Изпълнение на команда…" #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Изглед" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "П_оказване на списъка" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Показване на изкл_ючените контакти" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Показване на изкл_ючените контакти" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Показване на т_ранспорти" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "Помо_щ" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Ръководства" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_ЧЗВ" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 msgid "Features" msgstr "Възможности" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "_Добавяне на стаята към отметките" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Настройки" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Изход" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Отказ" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "Списък с възможни функционалности на Gajim:" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "С_тая" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "_Добавяне на стаята към отметките (Ctrl+B)" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "С_ървър:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Парола:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Изключване на контакт" #: gajim/data/gui/manage_bookmarks_window.ui:342 #, fuzzy msgid "Minimize on Auto Join" msgstr "Минимизиране при автоматично влизане" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Изпращане на съобщението и затваряне на прозореца" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Съобщение за състояние" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Описание: " #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Чистя" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 #, fuzzy msgid "Send" msgstr "_Изпращане" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Файл: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" "Вероятно не е фатална, но би трябвало да се докладва на разработчиците." #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Докладване на грешка" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Започване на разговор" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "_Отказване" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" "Отказване на упълномощаване на контакт, така че да не знае кога сте свързани" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "_Упълномощаване" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "Упълномощаване на контакта, така че да знае кога сте свързани" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "С_ъстояние" #: gajim/data/gui/emoji_chooser.ui:98 #, fuzzy msgid "No Results Found" msgstr "Няма резултати" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "Поканете приятели!" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "" "На път сте да започнете разговор в стая.\n" "Изберете контактите, които искате да поканите." #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "Изберете сървър за стаи." #: gajim/data/gui/chat_to_muc_window.ui:141 msgid "MUC server" msgstr "Сървър за стаи" #: gajim/data/gui/chat_to_muc_window.ui:176 msgid "In_vite" msgstr "По_кана" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Изнасяне" #: gajim/data/gui/history_manager.ui:93 msgid "Welcome to Gajim History Logs Manager" msgstr "Добре дошли в мениджъра на историята на разговорите" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" "Този мениджър не е предназначен за преглед на историята на разговорите. Ако " "търсите такава функционалност, използвайте прозореца за история.\n" "\n" "Използвайте тази програма за изтриване или изнасяне на дневници. Може да ги " "избирате от списъка вляво и/или да търсите в базата от данни по-долу." #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "ПРЕДУПРЕЖДЕНИЕ:\n" "Ако планирате да изтривате масово, уверете се, че Gajim не е стартиран. По " "принцип избягвайте да изтривате история за контакти, с които разговаряте в " "момента." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Търсене в базата от данни" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "текст на съобщението" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Изпращане на съобщение" #: gajim/data/gui/shortcuts_window.ui:24 #, fuzzy msgid "Add new line" msgstr "Създаване на ново съобщение" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Настроени съобщения:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Настроени съобщения:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "съобщение за състояние" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Изпращане на съобщение" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Изпратено съобщение" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Скоро посетени:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Чистя" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Файлови трансфери" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "в _стаи" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "съобщение за състояние" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 #, fuzzy msgid "Appearance" msgstr "Изглед на разговорите" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Показване на изкл_ючените контакти" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Показване на изкл_ючените контакти" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Контакти" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Информация за контакта" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Преименуване на контакт" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Покана на _контакти" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Парола" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "Запазване на промените на _състоянията на контактите" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Председател" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Скоро посетени:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "История на разговорите" #: gajim/data/gui/history_window.ui:315 #, fuzzy msgid "Chat" msgstr "Разговори" #: gajim/data/gui/history_window.ui:329 #, fuzzy msgid "Record history for this chat" msgstr "Пренебрегване на грешката за този сертификат." #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Скоро посетени:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Заглавие:" #: gajim/data/gui/manage_pep_services_window.ui:13 msgid "PEP Service Configuration" msgstr "Настройки на услугата PEP" #: gajim/data/gui/manage_pep_services_window.ui:69 msgid "_Configure" msgstr "_Настройване" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Създаване на ново съобщение" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "От:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Тема:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Попълнете формуляра." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Настройки на стаята" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_Да" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "С_ъстояние" #: gajim/data/gui/systray_context_menu.ui:20 msgid "_Start Chat..." msgstr "_Започване на разговор…" #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Показване на всички _чакащи събития" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "Изключване на звука" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Настройки" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Изход" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "До:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "_Изпращане" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Изпращане на съобщение" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Отговор" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Отговор на това съобщение" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "Изпра_щане и затваряне" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Изпращане на съобщението и затваряне на прозореца" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "Задаване на дейност" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "Задаване на дейност" #: gajim/data/gui/change_activity_dialog.ui:337 msgid "Message: " msgstr "Съобщение:" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Липсващ аргумент „contact_jid“" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Липсващ аргумент „contact_jid“" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 #, fuzzy msgid "Send a message to the contact" msgstr "Употреба: /%s, изпраща съобщение до контакта." #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "%s не е намерен" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "На _линия" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 #, fuzzy msgid "Clear the text window" msgstr "Употреба: /%s, изчиства текстовия прозорец." #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Употреба: /%s, изпраща „ping“ до контакта." #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 #, fuzzy msgid "Command is not supported for zeroconf accounts" msgstr "Командата не се поддържа за акаунт тип „zeroconf“." #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 msgid "No open audio sessions with the contact" msgstr "" #: gajim/command_system/implementation/standard.py:191 #, fuzzy, python-format msgid "%s is not a valid tone" msgstr "%s не е валидно ниво за дневник" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "В момента няма връзка" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "В момента няма връзка" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Употреба: /%s, изпраща съобщение до контакта." #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Смяна на псевдоним (Ctrl+N)" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 msgid "Invalid nickname" msgstr "Невалиден псевдоним" #: gajim/command_system/implementation/standard.py:267 #, fuzzy msgid "Open a private chat window with a specified occupant" msgstr "" "Употреба: /%s <псевдоним>, отваря прозорец за лично съобщение със съответния " "участник." #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 #, fuzzy msgid "Nickname not found" msgstr "Псевдонимът не е намерен: %s" #: gajim/command_system/implementation/standard.py:276 #, fuzzy msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" "Употреба: /%s <псевдоним>, отваря прозорец за лично съобщение със съответния " "участник." #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Питане преди затваряне на подпрозорец/прозорец на стая." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "%(contact_jid)s е поканен в %(room_jid)s." #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "в _стаи" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Поканени сте в стая." #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Невалиден сървър" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "рангът е променен" #: gajim/command_system/implementation/standard.py:365 #, fuzzy msgid "Display names of all group chat occupants" msgstr "Употреба: /%s, показва имената на участниците в стаята." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Продължен разговор" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Нова стая" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Добавяне на нов контакт" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "Еднократно съобщение с акаунт „%s“" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "Еднократно съобщение за акаунт „%s“" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Еднократно съобщение" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Изпращане на %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Получено %s" #: gajim/gtk/single_message.py:238 #, python-format msgid "Form %s" msgstr "От %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "В момента няма връзка" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Уверете се, че сте свързани към „%s“." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "Относно: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s написа:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "Възелът на PEP не беше премахнат" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "Възелът на PEP %(node)s не беше премахнат: %(message)s" #: gajim/gtk/pep_config.py:133 #, fuzzy, python-format msgid "Configure %s" msgstr "_Настройване" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "_Регистриране" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Регистриране в %s" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "Няма наличен речник за %s език" #: gajim/gtk/dialogs.py:83 #, fuzzy, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" "За да използвате проверката за правопис, трябва да инсталирате речник за %s " "или да изберете друг език чрез настройването на опцията „speller_language“.\n" "\n" "Функционалността за осветяване на сгрешени думи ще е изключена" #: gajim/gtk/dialogs.py:440 #, fuzzy, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "" "На път сте да изпратите паролата си чрез несигурна връзка. Трябва да " "инсталирате PyOpenSSL, за да предотвратите това. Сигурни ли сте, че искате " "да го направите?" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "Псевдонимът съдържа непозволени знаци." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "за акаунт „%s“" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Само-подписан сертификат" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Промяна на парола" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Трябва да въведете парола." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Паролите не съвпадат" #: gajim/gtk/add_contact.py:30 #, fuzzy msgid "GG Number" msgstr "Номер на GG:" #: gajim/gtk/add_contact.py:31 #, fuzzy msgid "ICQ Number" msgstr "Номер на ICQ:" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Добавяне на контакт…" #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s MiB" #: gajim/gtk/add_contact.py:235 #, python-format msgid "You must supply the %s of the new contact." msgstr "" #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "Невалиден идентификатор" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "Потребителският идентификатор не трябва да съдържа ресурс." #: gajim/gtk/add_contact.py:274 msgid "You cannot add yourself to your roster." msgstr "Не може да добавите себе си към списъка." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Изключен" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Контактът вече е в списъка" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Контактът вече съществува в списъка." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "Идентификатор на потребител:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "Грешка при добавянето на услугата. %s" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "Пише" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Бездеен" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Промяна на състоянието" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "Съобщения\n" "за стая" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Ново съобщение" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Акаунт" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Група" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "Показване на събитието в спис_ъка" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Разговор с " #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Невалиден псевдоним" #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Промяна на псевдонима" #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "В_ходящо съобщение:" #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "В_ходящо съобщение:" #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "_Изходящо съобщение:" #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "_Изходящо съобщение:" #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Съобщение за състояние" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Съобщение за състояние" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Цвят" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "_Осветяване на неправилно изписаните думи" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Съобщения" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "Възстановяване на стандартните _цветове" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Изключване на контакт" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Включване на контакт" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "gajim-remote" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Невалиден псевдоним" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Псевдонимът не е позволен: %s" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Активен" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "Грешка при запис/четене от диска" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s вече е %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, fuzzy, python-format msgid "Error: %s" msgstr "Грешка: %s" #: gajim/gtk/history.py:590 #, fuzzy msgid "Error" msgstr "Грешка." #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Сегашното състояние е: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Сегашното състояние е: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "Какво искате да направите?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Свързване" #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Файловият трансфер на %(filename)s от %(name)s прекъсна." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "Препращане на непрочетени съобщения" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "Джабър клиент за GTK+" #: gajim/gtk/about.py:48 #, fuzzy, python-format msgid "GTK+ Version: %s" msgstr "Версия на GTK+:" #: gajim/gtk/about.py:49 #, fuzzy, python-format msgid "PyGObject Version: %s" msgstr "Версия на PyGTK:" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Текущи разработчици:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Бивши разработчици:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 #, fuzzy msgid "we would like to thank all the package maintainers." msgstr "" "И не на последно място, бихме искали да благодарим на всички, които " "поддържат пакетите." #: gajim/gtk/about.py:61 #, fuzzy msgid "Thanks" msgstr "Благодарен" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "" "Явор Доганов \n" "\n" "Проектът за превод на GNOME има нужда от подкрепа.\n" "Научете повече за нас на http://gnome.cult.bg\n" "Докладвайте за грешки на http://gnome.cult.bg/bugs" #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Избор на файл за изпращане…" #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Избор на изображение" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Всички файлове" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Всички файлове" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Изпращане на _файл" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Изображения" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Избор на изображение" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Всички файлове" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Запазване на файла като…" #: gajim/gtk/profile.py:72 #, fuzzy msgid "Retrieving profile…" msgstr "Извличане на профила…" #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Информация за контакта" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Формат: гггг-мм-дд" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "Получена информация" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "Трябва да сте свързани, за да публикувате визитката." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Изпращане на профила…" #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "Информацията НЕ Е публикувана" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "Неуспех при публикуването на визитката" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "Възникна грешка при публикуване на личните данни, опитайте отново по-късно." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Невалиден формат" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 msgid "Invalid Nickname" msgstr "Невалиден псевдоним" #: gajim/gtk/join_groupchat.py:223 #, fuzzy msgid "Please choose a nickname" msgstr "Създайте нова тема с желаното име." #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Грешен адрес" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "Това не е стая" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Настройки" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Не сте свързани към сървъра." #: gajim/gtk/mam_preferences.py:102 #, fuzzy msgid "Error received: {}" msgstr "Грешка в получените данни" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Грешка." #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "Активирана" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "Изключена" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "Булев израз" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "Число" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Текст" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Име на опцията" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Стойност" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Тип" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Няма)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Скрита" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "_Хост:" #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Функционалности на сървърите" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Запазен в: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "Bonjour / Zeroconf" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" "Разговори с автоматично открити контакти в локалната мрежа (без сървър)." #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "Изисква python-dbus." #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 #, fuzzy msgid "Command line" msgstr "Команди: %s" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "Скрипт за управление на Gajim от командния ред." #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "" #: gajim/gtk/features.py:61 #, fuzzy msgid "OpenPGP message encryption" msgstr "Избор на ключ на OpenPGP" #: gajim/gtk/features.py:63 #, fuzzy msgid "Ability to encrypting chat messages with OpenPGP." msgstr "Шифриране на съобщения с ключове на GPG." #: gajim/gtk/features.py:64 #, fuzzy, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "Изисква gpg и python-GnuPGInterface." #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 #, fuzzy msgid "Password encryption" msgstr "Парола за влизане в стаята" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "" "Паролите могат да се съхраняват по сигурен начин, вместо в обикновен текст." #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "Проверка на правописа" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "Проверка на изходящите съобщения за правописни грешки." #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 #, fuzzy msgid "Requires Gspell" msgstr "Изисква python-sexy." #: gajim/gtk/features.py:76 #, fuzzy msgid "Automatic status" msgstr "_Съгласуване спрямо състоянието" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" "Възможност за измерване на времето на бездействие, с цел да се установи " "автоматично съобщение за състояние." #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "" #: gajim/gtk/features.py:80 #, fuzzy msgid "Requires python2.5." msgstr "Изисква python-gnome2." #: gajim/gtk/features.py:81 msgid "RST Generator" msgstr "Генератор на RST" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" "Генериране на изход в XHTML от RST (вижте http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "Изисква python-docutils." #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "" #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 #, fuzzy msgid "Requires gir1.2-gupnpigd-1.0." msgstr "Изисква python-gnome2." #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "На линия" #: gajim/gtk/features.py:109 msgid "Feature" msgstr "Функционалност" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "Филтър за уединение %s" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "Филтър за уединение за %s" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "" "Ред: %(order)s, действие: %(action)s, вид: %(type)s, стойност: %(value)s" #: gajim/gtk/privacy_list.py:152 #, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Ред: %(order)s, действие: %(action)s" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "Редактиране на правило" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "Добавяне на правило" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "Филтри за уединение за %s" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "Невалидно име на филтър" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "Трябва да въведете име, за да се създаде филтър за уединение." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Акаунтът беше добавен успешно" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 #, fuzzy msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Може да настроите допълнителните опции, като натиснете бутона „Напреднали“ " "или по-късно от менюто „Редактиране“->„Акаунти“ в основния прозорец." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Новият акаунт беше създаден успешно" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Невалидно потребителско име" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Трябва да въведете име на потребител за новия акаунт." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 msgid "Invalid server" msgstr "Невалиден сървър" #: gajim/gtk/account_wizard.py:255 msgid "Please provide a server on which you want to register." msgstr "Задайте сървър, където искате да се регистрирате." #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Невалиден формат" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "Портът по избор трябва все пак да е номер на порт." #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" "Предупреждение за сигурността\n" "\n" "Автентичността на сертификата на %(hostname)s е под въпрос.\n" "Грешка на SSL: %(error)s\n" "Все още ли искате да се свържете с този сървър?" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "Възникна грешка при създаването на акаунта" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Името на акаунта се използва" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Вече има регистриран акаунт с това име." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Филтър:" #: gajim/gtk/xml_console.py:79 #, fuzzy msgid "XML Input" msgstr "Вход в XML формат" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Невалиден файл" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "По подразбиране" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "заглавие на съобщението за състояние" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "текст на съобщението за състояние" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Свързване наново?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "" "Ако искате всички промени да влязат в сила веднага, трябва да се свържете " "наново." #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "Имате активни разговори за акаунт „%s“" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "" "Всички прозорци за разговори и стаи ще бъдат затворени. Искате ли да " "продължите?" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Добавяне на контакт…" #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "_Премахване" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Смесени акаунти" #: gajim/gtk/accounts.py:549 #, fuzzy msgid "Use PGP Agent" msgstr "Използване на агент на _GPG" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Свързване" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Покана на _контакти" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Само-подписан сертификат" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Задаване на OpenPGP ключ" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "С_вързване при стартиране" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Автоматично свързване при разпадане на връзката" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Запазване на история на _разговорите за всички контакти" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "_Изпращане на съобщение от сървъра…" #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Всички състояния" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Промяна на състоянието на акаунта или акаунтите" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Съобщения" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Използване на сървъри-посредници за файлови трансфери" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "Използване на променливата на обкръжението „HTTP_PROXY“" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Сървър-посредник:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "Предупре_ждаване преди използване на несигурна връзка" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Изпращане на пакети за поддържане на връзката" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "Приори_тет:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Промяна на състоянието на акаунта или акаунтите" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Собствено име:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Фамилия:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Нова е-поща" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "_Съгласуване спрямо състоянието" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Активиране" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "По_рт:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Свързване" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Само-подписан сертификат" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Само-подписан сертификат" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Запазване на паролата" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "_Емотикони:" #: gajim/gtk/bookmarks.py:72 msgid "?print_status:All" msgstr "Всички" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "Само влизащи и излизащи" #: gajim/gtk/bookmarks.py:74 msgid "?print_status:None" msgstr "Без" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "Нова стая" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Тази отметка съдържа невалидни данни" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "Попълнете полетата за сървър и стая или изтрийте тази отметка." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 #, fuzzy msgid "Character not allowed" msgstr "Псевдонимът не е позволен: %s" #: gajim/gtk/bookmarks.py:367 #, fuzzy msgid "Invalid room" msgstr "Невалиден формат" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Файлът не съдържа нищо" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 #, fuzzy msgid "Archive is malformed" msgstr "Услугата изпрати лошо форматирани данни" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Този файл вече съществува" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Отлъчване на %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Неуспех при свързването" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Настройки на стаята" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Джабър клиент за бързи съобщения" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "Джабър клиент за GTK+" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Показване на всички _чакащи събития" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Възможности" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 #, fuzzy msgid "Automatic spell-checking for your messages" msgstr "Проверка на изходящите съобщения за правописни грешки." #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Откриване на налични услуги за акаунт „%s“" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "Запазване на промените на _състоянията на контактите" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Стаи" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Скоро посетени:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Неуспех при свързването" #~ msgid "Stopped" #~ msgstr "Преустановен" #~ msgid "Error reading file:" #~ msgstr "Грешка при четене на файл:" #~ msgid "Error parsing file:" #~ msgstr "Грешка при анализиране на файл:" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Грешка при файловия трансфер" #, fuzzy #~ msgid "XML console interface" #~ msgstr "XML конзола" #~ msgid "" #~ "A list of modp groups to use in a Diffie-Hellman, highest preference " #~ "first, separated by commas. Valid groups are 1, 2, 5, 14, 15, 16, 17 and " #~ "18. Higher numbers are more secure, but take longer to calculate when you " #~ "start a session." #~ msgstr "" #~ "Списък от групи „modp“ за употреба чрез алгоритъма „Дифи-Хелман“, " #~ "разделени чрез запетаи, най-предпочитаните в началото. Валидни групи са " #~ "1, 2, 5, 14, 15, 16, 17 и 18. По-големите числа са по-сигурни, но " #~ "изчисленията отнемат повече време в началото на сесията." #~ msgid "_Verify" #~ msgstr "_Проверка" #~ msgid "(ESession info)" #~ msgstr "(Информация за Е-сесия)" #~ msgid "Save as Preset..." #~ msgstr "Запазване като настроено…" #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "Jabberd1.4 не харесва информация от тип SHA при включване в стая, " #~ "защитена с пароли. Настройте тази опция на „Изключена“, за да спрете да " #~ "изпращате информация от тип SHA при присъствие в стаи." #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Ако тази опция е избрана, усмивките в ASCII като „:)“ ще се изобразяват " #~ "със съответните анимирани или статични емотикони." #, fuzzy #~ msgid "_Emoticons" #~ msgstr "_Емотикони:" #~ msgid "_Highlight misspelled words" #~ msgstr "_Осветяване на неправилно изписаните думи" #, fuzzy #~ msgid "Notify by icon when your messages are received" #~ msgstr "" #~ "Звук за изпълнение при получаване на каквото и да е съобщение в стая." #, fuzzy #~ msgid "T_heme" #~ msgstr "_Тема:" #~ msgid "Themes" #~ msgstr "Теми" #, fuzzy #~ msgid "Presence" #~ msgstr "С_ъстояние" #~ msgid "Emoticons disabled" #~ msgstr "Емотиконите са изключени" #, fuzzy #~ msgid "" #~ "Your configured emoticons theme could not be loaded. See the log for more " #~ "details." #~ msgstr "Темата с емотикони не беше намерена, така че са изключени." #~ msgid "You cannot make changes to the default theme" #~ msgstr "Не може да правите промени по стандартната тема" #, fuzzy #~ msgid "Please create a new clean theme." #~ msgstr "Създайте нова тема с желаното име." #~ msgid "theme name" #~ msgstr "име на тема" #~ msgid "You cannot delete your current theme" #~ msgstr "Не може да изтриете текущата тема" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Ново еднократно съобщение от %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Ново лично съобщение от стая „%s“" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s: %(message)s" #~ msgid "Messaged by %(nickname)s" #~ msgstr "Съобщение от %(nickname)s" #, fuzzy #~ msgid "Status message text color." #~ msgstr "текст на съобщението за състояние" #, fuzzy #~ msgid "Incoming nickname font." #~ msgstr "Невалиден псевдоним" #, fuzzy #~ msgid "Status message text font." #~ msgstr "текст на съобщението за състояние" #~ msgid "Background color of contacts when they just signed in." #~ msgstr "Цвят на фона на контактите, които се включват." #~ msgid "Background color of contacts when they just signed out." #~ msgstr "Цвят на фона на контактите, които се изключват." #~ msgid "green" #~ msgstr "зелена" #~ msgid "grocery" #~ msgstr "колониална" #~ msgid "human" #~ msgstr "хуманна" #~ msgid "marine" #~ msgstr "морска" #, fuzzy #~ msgid "Contact row" #~ msgstr "Контакт" #~ msgid "Gajim Themes Customization" #~ msgstr "Персонализиране на темите на Gajim" #~ msgid "Text _color:" #~ msgstr "_Цвят на текста:" #~ msgid "_Background:" #~ msgstr "_Фон:" #~ msgid "Text _font:" #~ msgstr "_Шрифт на текста:" #~ msgid "Font style:" #~ msgstr "Стил на шрифта:" #~ msgid "Paused" #~ msgstr "Временно преустановен" #~ msgid "Gone" #~ msgstr "Отсъства" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "Съобщения\n" #~ "в стая" #~ msgid "Chatstate Tab Colors" #~ msgstr "Цветове на подпрозорците" #, fuzzy #~ msgid "Chat message" #~ msgstr "Съобщение от разговор:" #~ msgid "Use system _default" #~ msgstr "Използване на стан_дартните за системата" #~ msgid "Font" #~ msgstr "Шрифт" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Име на контакта" #, fuzzy #~ msgid "Contact's message" #~ msgstr "Съобщение от разговор:" #, fuzzy #~ msgid "_Status message" #~ msgstr "С_ъобщение за състояние:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Осветено съобщение в стая" #, fuzzy #~ msgid "Your nickname" #~ msgstr "Псевдоним:" #, fuzzy #~ msgid "Your message" #~ msgstr "Грешка: %s" #, fuzzy #~ msgid "_URL highlight" #~ msgstr "_Адреси:" #~ msgid "Chat Line Colors" #~ msgstr "Цветове за разговорите" #~ msgid "Jabber ID:" #~ msgstr "Jabber ID:" #~ msgid "Resource:" #~ msgstr "Ресурс:" #~ msgid "Status:" #~ msgstr "Състояние:" #, fuzzy #~ msgid "Contact time:" #~ msgstr "Област/Щат:" #~ msgid "Ask:" #~ msgstr "Запитване:" #~ msgid "Subscription:" #~ msgstr "Записване:" #~ msgid "Name:" #~ msgstr "Име:" #~ msgid "Nickname:" #~ msgstr "Псевдоним:" #~ msgid "Street:" #~ msgstr "Улица:" #~ msgid "City:" #~ msgstr "Град:" #~ msgid "State:" #~ msgstr "Област/Щат:" #~ msgid "Extra Address:" #~ msgstr "Допълнителен адрес:" #~ msgid "Postal Code:" #~ msgstr "Пощенски код:" #~ msgid "Country:" #~ msgstr "Държава:" #~ msgid "Homepage:" #~ msgstr "Страница в Интернет:" #~ msgid "E-Mail:" #~ msgstr "Е-поща:" #~ msgid "Phone No.:" #~ msgstr "Телефон:" #~ msgid "Birthday:" #~ msgstr "Рожден ден:" #~ msgid "Family:" #~ msgstr "Фамилия:" #~ msgid "Middle:" #~ msgstr "Презиме:" #~ msgid "Prefix:" #~ msgstr "Представка:" #~ msgid "Given:" #~ msgstr "Собствено:" #~ msgid "Suffix:" #~ msgstr "Наставка:" #~ msgid "Full Name" #~ msgstr "Име" #~ msgid "Company:" #~ msgstr "Фирма:" #~ msgid "Department:" #~ msgstr "Отдел:" #~ msgid "Position:" #~ msgstr "Дейност:" #~ msgid "Role:" #~ msgstr "Роля:" #~ msgid "- messages will be logged" #~ msgstr "— ще бъде воден дневник за съобщенията" #~ msgid "- messages will not be logged" #~ msgstr "— няма да бъде воден дневник за съобщенията" #~ msgid "Edit %s" #~ msgstr "Редактиране на %s" #~ msgid "Register to %s" #~ msgstr "Регистриране в %s" #~ msgid "Conversation History with %s" #~ msgstr "История на разговорите с %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Неуспех при установяването на контакт с „%s“" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "Информацията за регистрация за транспорт %s не пристигна навреме" #~ msgid "Register to" #~ msgstr "Регистриране към" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Име на контакта" #~ msgid "Search:" #~ msgstr "Търсене:" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Трябва да сте свързани, за да променяте паролата." #~ msgid "Invalid password" #~ msgstr "Невалидна парола" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "Паролите, написани в двете полета, трябва да са едни и същи." #~ msgid "Enter new password:" #~ msgstr "Въведете нова парола:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Въведете я отново за потвърждение:" #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "JID %s не е съгласно стандарта по RFC. Няма да бъде добавен към списъка. " #~ "Използвайте инструменти за управление на списък като http://jru." #~ "jabberstudio.org/, за да го премахнете." #~ msgid "unsubscribe request from %s" #~ msgstr "искане за отписване от %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Автоматично влизане" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Страница в Интернет:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Настройване" #~ msgid "Manage Bookmarks" #~ msgstr "Управление на отметките" #~ msgid "_Nickname:" #~ msgstr "Псе_вдоним:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "Ако тази опция е избрана, ще влизате в тази стая при стартиране." #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Изписване на състоянията:" #, fuzzy #~ msgid "Add JID" #~ msgstr "Jabber ID:" #, fuzzy #~ msgid "Preference:" #~ msgstr "Настройки" #, fuzzy #~ msgid "Preference" #~ msgstr "Настройки" #, fuzzy #~ msgid "JID:" #~ msgstr "Вашия JID:" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "" #~ "Попълнете данните за контакта, който искате да добавите към акаунт „%s“" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Попълнете данните за контакта, който искате да добавите" #, fuzzy #~ msgid "Recently" #~ msgstr "Скоро посетени:" #~ msgid "Add New Contact" #~ msgstr "Добавяне на нов контакт" #~ msgid "_User ID:" #~ msgstr "_Идентификатор на потребител:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "Идентификатор на потребител:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Псевдоним" #~ msgid "Personal Information" #~ msgstr "Лични данни" #~ msgid "Avatar:" #~ msgstr "Аватар:" #~ msgid "Click to set your avatar" #~ msgstr "Натиснете, за да настроите аватара си" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "Премахване на група" #~ msgid "Not fetched because of invisible status" #~ msgstr "Не е изтеглен, понеже е в състояние „Невидим“" #~ msgid "Please wait..." #~ msgstr "Изчакайте…" #~ msgid "" #~ "When negotiating an encrypted session, should Gajim assume you want your " #~ "messages to be logged?" #~ msgstr "" #~ "Когато се договаря шифрирана сесия, да се приема ли, че искате " #~ "собствените съобщения да се запазват в дневник?" #~ msgid "Log _encrypted chat session" #~ msgstr "Запазване на дневник на _шифрираната сесия" #, fuzzy #~ msgid "" #~ "If checked, Gajim will keep logs for encrypted messages. Please note that " #~ "when using end-to-end encryption the remote party has to agree on " #~ "logging, else the messages will not be logged." #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще запазва дневници за шифрираните " #~ "съобщение. Забележете, че при шифриране тип „E2E“ другата страна трябва " #~ "да се съгласи, иначе съобщенията няма да бъдат запазвани." #~ msgid "Yahoo! Address:" #~ msgstr "Адрес на Yahoo!:" #~ msgid "Forward unread messages" #~ msgstr "Препращане на непрочетени съобщения" #~ msgid "All unread messages have been forwarded." #~ msgstr "Всички непрочетени съобщения бяха препратени." #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "Препращане на непрочетени съобщения" #~ msgid "AIM Address:" #~ msgstr "Адрес на AIM:" #~ msgid "MSN Address:" #~ msgstr "Адрес на MSN:" #~ msgid "Confirm these session options" #~ msgstr "Потвърждение на тези настройки на сесията" #, fuzzy #~ msgid "" #~ "The remote client wants to negotiate a session with these features:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Are these options acceptable?" #~ msgstr "" #~ "Отдалеченият клиент иска да договори сесия с тези параметри:\n" #~ "\n" #~ "\t%s\n" #~ "\n" #~ "\tДопустими ли са тези настройки?" #~ msgid "" #~ "The remote client selected these options:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Continue with the session?" #~ msgstr "" #~ "Отдалеченият клиент избра тези настройки:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Продължаване с тази сесия?" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "Активиран ли е OpenPGP за този контакт?" #, fuzzy #~ msgid "End to End message encryption" #~ msgstr "Шифриране тип „End to End“" #, fuzzy #~ msgid "Encrypting chat messages." #~ msgstr "Шифриране на разговорите." #~ msgid "Requires python-crypto." #~ msgstr "Изисква python-crypto." #~ msgid "Session negotiation cancelled" #~ msgstr "Договорката за сесията отменена" #, fuzzy #~ msgid "This session WILL NOT be archived on server" #~ msgstr "НЯМА да се запазва дневник за сесията" #~ msgid "This session is encrypted" #~ msgstr "Тази сесия е шифрирана" #~ msgid " and WILL be logged" #~ msgstr " и ЩЕ СЕ запазва дневник" #~ msgid " and WILL NOT be logged" #~ msgstr " и НЯМА да се запазва дневник" #~ msgid "" #~ "Remote contact's identity not verified. Click the shield button for more " #~ "details." #~ msgstr "" #~ "Идентичността на отсрещния контакт не е потвърдена. Натиснете бутона със " #~ "щита за повече информация." #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "Шифрирането чрез GPG е изключено" #~ msgid "" #~ "Unable to decrypt message from %s\n" #~ "It may have been tampered with." #~ msgstr "" #~ "Неуспех при дешифрирането на съобщение от %s\n" #~ "Възможно е да е било фалшифицирано." #~ msgid "Unable to decrypt message" #~ msgstr "Неуспех при дешифриране на съобщението" #~ msgid "Enable ESessions encryption for this account." #~ msgstr "Активира шифриране тип „ESessions“ за този акаунт." #~ msgid "Should Gajim automatically start an encrypted session when possible?" #~ msgstr "Дали Gajim да започва шифрирана сесия автоматично, ако е възможно?" #~ msgid "" #~ "[This is part of an encrypted session. If you see this message, something " #~ "went wrong.]" #~ msgstr "" #~ "[Това е част от шифрирана сесия. Ако виждате това съобщение, нещо не е " #~ "както трябва.]" #~ msgid "Requires python-avahi." #~ msgstr "Изисква python-avahi." #~ msgid "_Send" #~ msgstr "_Изпращане" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Запазване на изображението като…" #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Изнасяне на записите на разговорите…" #~ msgid "Choose Image" #~ msgstr "Избор на изображение" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Избор на файл за изпращане…" #~ msgid "When %s becomes:" #~ msgstr "Когато %s стане:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Добавяне на специално уведомление за %s" #, fuzzy #~ msgid "" #~ "It seems the SSL certificate of account %(account)s has changed and is " #~ "not valid or your connection is being compromised.\n" #~ "\n" #~ "Old SHA-1 fingerprint: %(old_sha1)s\n" #~ "Old SHA-256 fingerprint: %(old_sha256)s\n" #~ "\n" #~ "New SHA-1 fingerprint: %(new_sha1)s\n" #~ "New SHA-256 fingerprint: %(new_sha256)s\n" #~ "\n" #~ "Do you still want to connect and update the fingerprint of the " #~ "certificate?" #~ msgstr "" #~ "Изглежда сертификатът на SSL е бил променен или връзката е взломена.\n" #~ "Стар отпечатък: %(old)s\n" #~ "Нов отпечатък: %(new)s\n" #~ "\n" #~ "Все още ли искате да се свържете и да обновите отпечатъка на сертификата?" #, fuzzy #~ msgid "" #~ "The authenticity of the %s certificate could be invalid.\n" #~ "The certificate does not cover this domain." #~ msgstr "Автентичността на сертификата на %s може да е под въпрос." #~ msgid "Unable to load idle module" #~ msgstr "Неуспех при зареждането на модула „idle“" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s e папка, а би трябвало да е файл" #~ msgid "creating logs database" #~ msgstr "създаване на база от данни за разговорите" #, fuzzy #~ msgid "creating cache database" #~ msgstr "създаване на база от данни за разговорите" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Изпращане на %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Мениджър на историята на разговорите" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Преименуване на акаунт" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Изпращане на _еднократно съобщение…" #, fuzzy #~ msgid "We received an error: {}" #~ msgstr "Услугата върна грешка." #~ msgid "E2E encryption disabled" #~ msgstr "Шифрирането чрез E2E е изключено" #, fuzzy #~ msgid "" #~ "Add this certificate to the list of trusted certificates.\n" #~ "SHA-1 fingerprint of the certificate:\n" #~ "%(sha1)s\n" #~ "SHA256 fingerprint of the certificate:\n" #~ "%(sha256)s" #~ msgstr "" #~ "Добавяне на този сертификат към списъка с доверени сертификати.\n" #~ "Отпечатък тип SHA1 на сертификата:\n" #~ "%s" #~ msgid "uri" #~ msgstr "адрес" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Блокирал" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Блокирал" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Неуспех при свързването" #~ msgid "cyan" #~ msgstr "синьозелена" #~ msgid "migrating logs database to indices" #~ msgstr "мигриране на базата от данни с дневници към индекси" #, fuzzy #~ msgid "Send File..." #~ msgstr "Изпращане на _файл…" #, fuzzy #~ msgid "HTTP File Upload not supported by your server" #~ msgstr "Сървърът ви няма поддръжка за мета-контакти" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Файлови трансфери" #~ msgid "" #~ "Your configured emoticons theme has not been found, so emoticons have " #~ "been disabled." #~ msgstr "Темата с емотикони не беше намерена, така че са изключени." #~ msgid "Shows or hides the roster window" #~ msgstr "Показва или скрива списъка" #~ msgid "Shows or hides the ipython window" #~ msgstr "Показва или скрива прозореца на IPython" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "за акаунт „%s“" #, fuzzy #~ msgid "Exception" #~ msgstr "Описание" #, fuzzy #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "Бих искал(а) да ви добавя към списъка си." #~ msgid "" #~ "Ordered list (space separated) of connection type to try. Can contain " #~ "tls, ssl or plain" #~ msgstr "" #~ "Списък (разделен с шпации) на видове свързвания. Може да съдържа „tls“, " #~ "„ssl“ или „plain“." #~ msgid "_Actions" #~ msgstr "_Действия" #, fuzzy #~ msgid "Requires upower and python-dbus." #~ msgstr "Изисква python-dbus." #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Започване на разговор…" #~ msgid "You are already in group chat %s" #~ msgstr "Вече сте в стая „%s“" #~ msgid "Join Group Chat with account %s" #~ msgstr "Влизане в стая с акаунт „%s“" #, fuzzy #~ msgid "Invalid Account" #~ msgstr "Невалидно име на акаунт" #, fuzzy #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "Акаунт, от който искате да влезете в стаята" #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "Jabber ID на стаята съдържа непозволени знаци." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "Jabber ID на стаята съдържа непозволени знаци." #~ msgid "Start Chat with account %s" #~ msgstr "Започване на разговор с акаунт „%s“" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Въведете JID или псевдоним на контакта, до който\n" #~ "искате да изпратите съобщение:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Дублиран Jabber ID" #~ msgid "Unable to parse \"%s\"." #~ msgstr "Неуспех при анализирането на „%s“." #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "" #~ "Показване на диалогов прозорец за разговор, за да може да се изпрати " #~ "съобщение до контакта" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID на контакта, с който искате да разговаряте" #~ msgid "Adds contact to roster" #~ msgstr "Добавяне на контакт към списъка" #~ msgid "jid" #~ msgstr "JID" #~ msgid "Adds new contact to this account" #~ msgstr "Добавяне на нов контакт към този акаунт" #~ msgid "Opens 'Start Chat' dialog" #~ msgstr "Отваря прозореца „Започване на разговор“" #~ msgid "Starts chat, using this account" #~ msgstr "Започване на разговор, като се използва този акаунт" #, fuzzy #~ msgid "Handle a xmpp:/ URI" #~ msgstr "Обработка на адрес тип xmpp://" #~ msgid "URI to handle" #~ msgstr "Адрес за обработка" #~ msgid "Account in which you want to handle it" #~ msgstr "Акаунт, за който искате да го обработите" #, fuzzy #~ msgid "Message content" #~ msgstr "текст на съобщението" #~ msgid "Join a MUC room" #~ msgstr "Влизане в стая" #~ msgid "Nickname to use" #~ msgstr "Псевдоним" #~ msgid "Password to enter the room" #~ msgstr "Парола за влизане в стаята" #~ msgid "Account from which you want to enter the room" #~ msgstr "Акаунт, от който искате да влезете в стаята" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Грешен адрес" #~ msgid "Nickname:" #~ msgstr "Псевдоним:" #~ msgid "Server:" #~ msgstr "Сървър:" #~ msgid "Password:" #~ msgstr "Парола:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Влизане в тази стая автоматично при свързване" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Търсене" #, fuzzy #~ msgid "Requires libgtkspell and libenchant." #~ msgstr "Изисква python-sexy." #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "network-manager" #~ msgid "Autodetection of network status." #~ msgstr "Автоматично засичане на състоянието на мрежата." #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Изисква gnome-network-manager и python-dbus." #, fuzzy #~ msgid "This contact does not support file transfer." #~ msgstr "Списък с активни, завършили и прекъснати файлови трансфери" #~ msgid "" #~ "You have to install %s dictionary to use spellchecking, or choose another " #~ "language by setting the speller_language option." #~ msgstr "" #~ "За да използвате проверката за правопис, трябва да инсталирате %s речник " #~ "или да изберете друг език чрез настройването на опцията " #~ "„speller_language“." #~ msgid "Hides the buttons in chat windows." #~ msgstr "Скрива бутоните в прозорците за разговор." #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Смяна на псевдоним (Ctrl+N)" #~ msgid "Change the room's subject (Alt+T)" #~ msgstr "Смяна на темата на стаята (Alt+T)" #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "_Добавяне на стаята към отметките (Ctrl+B)" #~ msgid "Browse the chat history (Ctrl+H)" #~ msgstr "Разглеждане на историята на разговорите (Ctrl+H)" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Меню с функции за напреднали (Ctrl+A)" #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Добавяне на контакт към списъка (Ctrl+D)" #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "Покана на контакти в разговора (Ctrl+G)" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Показване на профила на контакта (Ctrl+I)" #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Показване на профила на контакта (Ctrl+I)" #~ msgid "Ma_ke message windows compact" #~ msgstr "_Компактни прозорци за разговор" #~ msgid "Hide all buttons in chat windows" #~ msgstr "Скриване на всички бутони в прозорците за разговор." #, fuzzy #~ msgid "Hide the chat buttons" #~ msgstr "Употреба: /%s, скрива бутоните за разговор." #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "Ако е активирана, ще се изпраща запитване за аватар до всеки контакт, " #~ "който е нямал такъв последния път или пък има остарял кеширан аватар." #~ msgid "Disk Write Error" #~ msgstr "Грешка при запис" #~ msgid "Set Custom _Avatar..." #~ msgstr "Задаване на друг _аватар…" #, fuzzy #~ msgid "SSL certificate validation" #~ msgstr "Грешка в сертификата на SSL" #~ msgid "" #~ "A library used to validate server certificates to ensure a secure " #~ "connection." #~ msgstr "" #~ "Библиотека за проверка на валидността на сертификатите на сървърите. " #~ "Използва се за установяване на сигурна връзка." #, fuzzy #~ msgid "Requires python-pyopenssl > 0.12 and pyasn1." #~ msgstr "Изисква python-pyopenssl." #, fuzzy #~ msgid "?CLI:room" #~ msgstr "стая" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "псевдоним" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "парола" #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "" #~ "Използване на DBus и Notification-Daemon за показване на уведомленията" #, fuzzy #~ msgid "Notification" #~ msgstr "Уведомления" #~ msgid "Passive popups notifying for new events." #~ msgstr "Изскачащи прозорци с уведомления за нови събития." #~ msgid "" #~ "Requires python-notify or instead python-dbus in conjunction with " #~ "notification-daemon." #~ msgstr "Изисква python-notify или python-dbus заедно с notification-daemon." #, fuzzy #~ msgid "Ignore" #~ msgstr "_Игнориране" #~ msgid "_Open Gmail Inbox" #~ msgstr "_Отваряне на пощенската кутия на Gmail" #~ msgid "Notify on new _GMail email" #~ msgstr "Уведомяване при нова поща от _GMail" #~ msgid "" #~ "If checked, Gajim will show a notification when a new e-mail is received " #~ "via GMail" #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще показва уведомление при получаването " #~ "на ново писмо чрез GMail." #~ msgid "Display _extra email details" #~ msgstr "Показване на _допълнителни данни за е-поща" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще включва информация за подателя на " #~ "новите писма." #~ msgid "GMail Options" #~ msgstr "Настройки за GMail" #, fuzzy #~ msgid "20" #~ msgstr "0" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Изпращане на %s" #~ msgid "GMail Email Received" #~ msgstr "Получена поща от Gmail" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Ново писмо за %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "Имате %d ново писмо" #~ msgstr[1] "Имате %d нови писма" #~ msgid "" #~ "\n" #~ "\n" #~ "From: %(from_address)s\n" #~ "Subject: %(subject)s\n" #~ "%(snippet)s" #~ msgstr "" #~ "\n" #~ "\n" #~ "От: %(from_address)s\n" #~ "Тема: %(subject)s\n" #~ "%(snippet)s" #~ msgid "Re_name" #~ msgstr "Пре_именуване" #~ msgid "Resour_ce:" #~ msgstr "_Ресурс:" #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "Ресурсът се изпраща до Джабър сървъра, за да „раздели“ един и същи JID на " #~ "две или повече части в зависимост от броя на клиентите, свързани с един " #~ "сървър и един и същ акаунт. Така може да сте свързани със същия акаунт и " #~ "ресурси „Вкъщи“ и „На работа“ по едно и също време. Ресурсът с най-голям " #~ "приоритет ще получава събитията. (вижте по-долу)" #, fuzzy #~ msgid "A_djust to status" #~ msgstr "_Съгласуване спрямо състоянието" #~ msgid "Priority will change automatically according to your status." #~ msgstr "Приоритетът ще се сменя автоматично в зависимост от състоянието ви." #, fuzzy #~ msgid "Anonymous authentication" #~ msgstr "Използване на удостоверяване" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "Приоритетът в Джабър се използва, за да се определи кой да получава " #~ "събитията от Джабър сървър, когато два или повече клиента са свързани с " #~ "един и същ акаунт. Клиентът с най-голям приоритет ще получава събитията." #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Синхронизиране на контакти" #~ msgid "Click to request authorization to all contacts of another account" #~ msgstr "" #~ "Натиснете, за да изискате упълномощаване от всички контакти на друг акаунт" #~ msgid "Chan_ge Password" #~ msgstr "Пром_яна на парола" #~ msgid "Click to change account's password" #~ msgstr "Натиснете, за да смените паролата на акаунта" #~ msgid "Administration operations" #~ msgstr "Административни операции" #, fuzzy #~ msgid "Browse..." #~ msgstr "_Търсене" #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "Сертификатът е отхвърлен" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Ако тази опция е избрана, при стартиране Gajim ще се свързва автоматично, " #~ "използвайки този акаунт." #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Синхронизиране на контакти" #~ msgid "Synch_ronize account status with global status" #~ msgstr "Син_хронизиране на състоянието на акаунта с общото състояние" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Ако тази опция е избрана, всяка промяна на общото състояние (от списъка в " #~ "долната част на главния прозорец) ще променя и състоянието на този акаунт." #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще излъчва повече IP адреси освен вашия " #~ "собствен, така че файловият трансфер има повече шансове да работи добре." #~ msgid "Proxy" #~ msgstr "Сървър-посредник" #~ msgid "" #~ "Check this so Gajim will ask you before sending your password over an " #~ "insecure connection." #~ msgstr "" #~ "Ако тази опция е избрана, ще се изисква потвърждение преди изпращането на " #~ "паролата ви чрез несигурна връзка." #, fuzzy #~ msgid "Send _keep-alive packets" #~ msgstr "Изпращане на пакети за поддържане на връзката" #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще изпраща пакети за поддържане на " #~ "връзката с цел избягване на разпадането ѝ." #, fuzzy #~ msgid "Use cust_om hostname/port" #~ msgstr "Използване на нестандартен хост/порт" #, fuzzy #~ msgid "_Hostname: " #~ msgstr "_Хост:" #, fuzzy #~ msgid "_Port: " #~ msgstr "По_рт:" #~ msgid "No key selected" #~ msgstr "Няма избран ключ" #~ msgid "Choose _Key..." #~ msgstr "Избор на _ключ…" #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "" #~ "Ако тази опция е избрана, паролата ще се взима от агент на GPG като " #~ "Seahorse." #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "_Edit Personal Information..." #~ msgstr "Редактиране на личните данни…" #~ msgid "Information about you, as stored in the server" #~ msgstr "Вашите лични данни, както са запазени на сървъра" #~ msgid "Personal Information" #~ msgstr "Лични данни" #, fuzzy #~ msgid "Co_nnect on Gajim startup" #~ msgstr "С_вързване при стартиране" #, fuzzy #~ msgid "Synchroni_ze account status with global status" #~ msgstr "Син_хронизиране на състоянието на акаунта с общото състояние" #, fuzzy #~ msgid "Use cust_om port:" #~ msgstr "Използване на нестандартен порт:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Ако стандартния порт за входящи съобщения е неудобен за настройките ви, " #~ "може да изберете друг тук.\n" #~ "Може да помислите и да промените настройките на огнената стена, " #~ "евентуално." #~ msgid "Mer_ge accounts" #~ msgstr "_Смесване на акаунти" #, fuzzy #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "OpenPGP не може да бъде използван на този компютър" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Трябва да сте изключени, за да смените името на акаунта." #~ msgid "To change the account name, you must read all pending events." #~ msgstr "" #~ "За да смените името на акаунта, трябва да прочетете всички чакащи събития." #~ msgid "Account Name Already Used" #~ msgstr "Името на акаунта вече се използва" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "Това име вече се използва от друг акаунт. Изберете друго име." #~ msgid "Invalid account name" #~ msgstr "Невалидно име на акаунт" #~ msgid "Account name cannot be empty." #~ msgstr "Трябва да посочите някакво име на акаунта." #~ msgid "Account name cannot contain spaces." #~ msgstr "Името на акаунта не може да съдържа интервали." #~ msgid "Enter a new name for account %s" #~ msgstr "Въведете ново име за акаунт „%s“" #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "Jabber ID трябва да бъде във формат „user@server“." #~ msgid "No such account available" #~ msgstr "Няма такъв наличен акаунт" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "" #~ "Трябва първо да създадете акаунт и след това да редактирате личните данни." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "Трябва да сте свързани, за да редактирате личните данни." #, fuzzy #~ msgid "Your server does not have vCard support" #~ msgstr "Сървърът ви не поддържа визитки" #~ msgid "Your server can't save your personal information." #~ msgstr "Сървърът ви не може да запази личната ви информация." #~ msgid "Account Local already exists." #~ msgstr "Името на акаунта вече се използва." #~ msgid "Please rename or remove it before enabling link-local messaging." #~ msgstr "" #~ "Преименувайте го или го премахнете преди да активирате съобщения от/за " #~ "локални контакти." #~ msgid "THANKS:" #~ msgstr "БЛАГОДАРНОСТИ:" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "" #~ "Неуспех при запис на %s. Поддръжката за управление на сесиите няма да " #~ "работи" #~ msgid "Jabber Traffic" #~ msgstr "Джабър трафик" #, fuzzy #~ msgid "_Enable" #~ msgstr "Активиране" #, fuzzy #~ msgid "Filter" #~ msgstr "Шрифт" #~ msgid "_IQ" #~ msgstr "I_Q" #~ msgid "Info/Query" #~ msgstr "Информация/запитване (Info/Query)" #~ msgid "_Message" #~ msgstr "_Съобщение" #~ msgid "XML Input" #~ msgstr "Вход в XML формат" #~ msgid "XML Console for %s" #~ msgstr "XML конзола за %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "XML конзола за %s" #~ msgid "Last status: %s" #~ msgstr "Последно състояние: %s" #~ msgid " since %s" #~ msgstr " от %s" #~ msgid "since %s" #~ msgstr "от %s" #, fuzzy #~ msgid "No" #~ msgstr "Няма" #, fuzzy #~ msgid "Auto" #~ msgstr "Автоматично влизане" #, fuzzy #~ msgid "otr" #~ msgstr "Сгорещен" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Невалидно име на сървър" #, fuzzy #~ msgid "There is an error" #~ msgstr "Услугата върна грешка." #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "Колко минути да отделят последните редове от предишния разговор." #~ msgid "" #~ "Your configured emoticons theme cannot been loaded. You maybe need to " #~ "update the format of emoticons.py file. See http://trac.gajim.org/wiki/" #~ "Emoticons for more details." #~ msgstr "" #~ "Темата с емотикони не можа да бъде заредена. Навярно трябва да обновите " #~ "формата на файла emoticons.py. Вижте http://trac.gajim.org/wiki/Emoticons " #~ "за повече подробности." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Ще бъдете свързани към „%s“ без OpenPGP." #~ msgid "The following message was NOT encrypted" #~ msgstr "Следното съобщение НЕ БЕШЕ шифрирано" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Активира шифриране тип „ESessions“ за този акаунт." #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Превключване на шифриране тип „Open_PGP“" #~ msgid "Toggle End to End Encryption" #~ msgstr "Превключване на шифриране тип „End to End“" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "Шифрирането чрез GPG е включено" #, fuzzy #~ msgid "No OpenPGP key assigned" #~ msgstr "Няма зададен ключ на GPG" #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages with OpenPGP." #~ msgstr "" #~ "Няма зададен ключ на GPG за този контакт, така че не може да шифрирате " #~ "съобщенията с GPG." #~ msgid "Session WILL be logged" #~ msgstr "ЩЕ СЕ запазва дневник за сесията" #~ msgid "Session WILL NOT be logged" #~ msgstr "НЯМА да се запазва дневник за сесията" #~ msgid "is" #~ msgstr "е" #~ msgid "is NOT" #~ msgstr "НЕ е" #~ msgid "will" #~ msgstr "Ще" #~ msgid "will NOT" #~ msgstr "НЯМА да" #~ msgid "The following message was encrypted" #~ msgstr "Следното съобщение беше шифрирано" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Превключване на шифриране тип „Open_PGP“" #~ msgid "Is OpenPGP enabled for this contact?" #~ msgstr "Активиран ли е OpenPGP за този контакт?" #~ msgid "" #~ "Should Gajim automatically start an encrypted session with this contact " #~ "when possible?" #~ msgstr "Да се започва ли шифрирана сесия с този контакт, когато е възможно?" #~ msgid "Neither the remote presence is signed, nor a key was assigned." #~ msgstr "Нито отдалеченото присъствие е подписано, нито има зададен ключ." #~ msgid "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "Ключът на контакта (%s) не съвпада със зададения в Gajim." #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Това съобщение е *шифрирано* (вижте XEP:„27“)]" #~ msgid "" #~ "Your chat session with %(jid)s is encrypted.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Сесията ви с %(jid)s е шифрирана.\n" #~ "\n" #~ "Краткият удостоверителен низ (SAS) на сесията е %(sas)s." #~ msgid "You have already verified this contact's identity." #~ msgstr "Вече се проверили идентичността на този контакт." #~ msgid "Contact's identity verified" #~ msgstr "Идентичността на контакта проверена" #, fuzzy #~ msgid "Verify again…" #~ msgstr "Проверка наново…" #~ msgid "" #~ "To be certain that only the expected person can read your messages " #~ "or send you messages, you need to verify their identity by clicking the " #~ "button below." #~ msgstr "" #~ "За да се сигурни, че само очакваният човек може да чете ваши " #~ "съобщения или да ви изпраща такива, е необходимо да проверите " #~ "идентичността му като натиснете бутона по-долу." #~ msgid "Contact's identity NOT verified" #~ msgstr "Идентичността на контакта НЕ Е проверена" #, fuzzy #~ msgid "Verify…" #~ msgstr "_Проверка" #~ msgid "Have you verified the contact's identity?" #~ msgstr "Проверихте ли идентичността на контакта?" #~ msgid "" #~ "To prevent talking to an unknown person, you should speak to %(jid)s directly (in person or on the phone) and verify that they see the same " #~ "Short Authentication String (SAS) as you.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "За да избегнете разговор с непознат човек, трябва да говорите с " #~ "%(jid)s директно (лично или по телефона) и да проверите дали вижда " #~ "същия Кратък удостоверителен низ (SAS) като вас.\n" #~ "\n" #~ "Краткият удостоверителен низ на тази сесия е %(sas)s." #~ msgid "Did you talk to the remote contact and verify the SAS?" #~ msgstr "Говорихте ли с отдалечение контакт за проверка на SAS?" #~ msgid "" #~ "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "Ключът на контакта (%s) не съвпада с този, зададен в Gajim." #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages." #~ msgstr "" #~ "Няма зададен ключ на GPG за този контакт, така че не може да шифрирате " #~ "съобщения." #, fuzzy #~ msgid "" #~ "OpenPGP key is assigned to this contact, but you do not trust their " #~ "key, so message cannot be encrypted. Use your OpenPGP client " #~ "to trust their key." #~ msgstr "" #~ "Има зададен ключ на GPG за този контакт, но вие не му се доверявате, така че съобщенията не могат да се шифрират. За да се доверите " #~ "на този ключ, използвайте клиент на GPG." #, fuzzy #~ msgid "" #~ "OpenPGP Key is assigned to this contact, and you trust their key, so " #~ "messages will be encrypted." #~ msgstr "" #~ "Има зададен ключ на GPG за този контакт и вие му се доверявате, така че " #~ "съобщенията ще бъдат шифрирани." #~ msgid "" #~ "This icon indicates that this message has not yet\n" #~ "been received by the remote end. If this icon stays\n" #~ "for a long time, it's likely the message got lost." #~ msgstr "" #~ "Тази икона показва, че съобщението все още не е\n" #~ "получено от отсрещния контакт. Ако иконата остане\n" #~ "дълго време, най-вероятно съобщението е било изгубено." #~ msgid "" #~ "If True, listen to D-Bus signals from NetworkManager and change the " #~ "status of accounts (provided they do not have listen_to_network_manager " #~ "set to False and they sync with global status) based upon the status of " #~ "the network connection." #~ msgstr "" #~ "Ако е активирана, слуша за сигнали по DBus от NetworkManager и променя " #~ "състоянието на акаунтите (при положение, че нямат изключена " #~ "„listen_to_network_manager“ и се синхронизират с общото състояние) в " #~ "зависимост от състоянието на мрежовата връзка." #~ msgid "" #~ "The database file (%s) cannot be read. Try to repair it or remove it (all " #~ "history will be lost)." #~ msgstr "" #~ "Файлът „%s“ от базата от данни не може да бъде прочетен. Опитайте се да " #~ "го поправите или изтриете (цялата история ще бъде загубена)." #~ msgid "Database cannot be read." #~ msgstr "Неуспех при четенето на базата от данни." #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Плавно прелистване на съобщение в прозореца за разговор" #~ msgid "Show _XML Console" #~ msgstr "Показване на _XML конзола" #~ msgid "Edit _Privacy Lists..." #~ msgstr "_Филтри за уединение…" #~ msgid "_Administrator" #~ msgstr "_Администратор" #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "" #~ "Изпраща съобщение на всички потребители, свързани със сървъра в момента" #~ msgid "Sets Message of the Day" #~ msgstr "Настройване на съобщение за деня" #~ msgid "Updates Message of the Day" #~ msgstr "Актуализиране на съобщението за деня" #~ msgid "Deletes Message of the Day" #~ msgstr "Изтрива съобщението за деня" #~ msgid "Add _Contact..." #~ msgstr "_Добавяне на контакт…" #~ msgid "_Accounts" #~ msgstr "_Акаунти" #~ msgid "Profile, A_vatar" #~ msgstr "_Профил, аватар" #~ msgid "File _Transfers" #~ msgstr "_Файлови трансфери" #~ msgid "Help online" #~ msgstr "Помощ в Интернет" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Често задавани въпроси (в Интернет)" #~ msgid "Fea_tures" #~ msgstr "_Възможности" #~ msgid "to %s account" #~ msgstr "към акаунт „%s“" #~ msgid "using %s account" #~ msgstr "за акаунт „%s“" #~ msgid "of account %s" #~ msgstr "за акаунт „%s“" #~ msgid "for account %s" #~ msgstr "за акаунт „%s“" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Премахвайки този контакт, прекратявате и упълномощаването. Контактът " #~ "винаги ще ви вижда изключен." #~ msgid "Invalid Jabber ID" #~ msgstr "Невалиден Jabber ID" #~ msgid "Verify..." #~ msgstr "Проверка…" #~ msgid "This file is being used by another process." #~ msgstr "Този файл се използва от друг процес." #~ msgid "pgp key" #~ msgstr "ключ на OpenPGP" #~ msgid "" #~ "Sends new single message to a contact in the roster. Both OpenPGP key and " #~ "account are optional. If you want to set only 'account', without 'OpenPGP " #~ "key', just set 'OpenPGP key' to ''." #~ msgstr "" #~ "Изпращане на ново съобщение до контакт от списъка. Опциите „account“ и " #~ "„OpenPGP key“ са по избор. Ако искате да настроите само „account“ без " #~ "“OpenPGP key“, настройте „OpenPGP key“ на „“." #, fuzzy #~ msgid "Please first choose another theme as your current theme." #~ msgstr "Първо изберете друга като текуща тема." #~ msgid "A non-privacy-related room configuration change has occurred" #~ msgstr "" #~ "Възникна промяна в конфигурацията на стаята (не е свързана с настройки за " #~ "уединение)" #~ msgid "Your passphrase is incorrect" #~ msgstr "Паролата е грешна" #, fuzzy #~ msgid "OpenPGP Passphrase Incorrect" #~ msgstr "Паролата е грешна" #, fuzzy #~ msgid "OpenPGP key not trusted" #~ msgstr "GPG не е използваем" #~ msgid "You successfully received %(filename)s from %(name)s." #~ msgstr "Успешно получихте %(filename)s от %(name)s." #, fuzzy #~ msgid "Set logs directory" #~ msgstr "създаване на папка %s" #~ msgid "_Manage Bookmarks..." #~ msgstr "_Управление на отметките…" #~ msgid "Change Status Message..." #~ msgstr "Промяна на съобщението за състояние…" #~ msgid "_Change Status Message..." #~ msgstr "_Промяна на съобщението за състояние…" #~ msgid "" #~ "You are not interested in the contact's presence, and neither he/she is " #~ "interested in yours" #~ msgstr "" #~ "Вие не се интересувате от информацията за състоянието на контакта, както " #~ "и той от вашата" #~ msgid "Error description..." #~ msgstr "Описание на грешката…" #, fuzzy #~ msgid "View contact information (Ctrl+I)" #~ msgstr "Покана на контакти в разговора (Ctrl+G)" #, fuzzy #~ msgid "Groupchat Histories" #~ msgstr "Стаи" #, fuzzy #~ msgid "All Chat Histories" #~ msgstr "Всички състояния" #~ msgid "More" #~ msgstr "Още" #~ msgid "creating %s directory" #~ msgstr "създаване на папка %s" #, fuzzy #~ msgid "" #~ "If True, Gajim will use KDE Wallet (if kwalletcli is available) to store " #~ "account passwords." #~ msgstr "" #~ "Ако е активирана, Gajim ще използва набора на ключове на GNOME (gnome-" #~ "keyring), ако е достъпен, за да запазва информация за паролите на " #~ "акаунтите." #~ msgid "%s is not the name of a group chat." #~ msgstr "%s не е име на стая." #~ msgid "Session Management" #~ msgstr "Управление на сесии" #~ msgid "Gajim session is stored on logout and restored on login." #~ msgstr "Запазва сесията на Gajim при излизане и я възстановява при влизане." #~ msgid "Requires python-gnome2." #~ msgstr "Изисква python-gnome2." #, fuzzy #~ msgid "Requires gnome-keyring and python-gnome2-desktop, or kwalletcli." #~ msgstr "Изисква gnome-keyring и python-gnome2-desktop." #~ msgid "SRV" #~ msgstr "SRV" #~ msgid "Ability to connect to servers which are using SRV records." #~ msgstr "Възможност за свързване към сървъри, които използват записи SRV." #~ msgid "Requires dnsutils." #~ msgstr "Изисква dnsutils." #~ msgid "Gajim needs X server to run. Quiting..." #~ msgstr "Необходим е X сървър. Спиране на програмата…" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above" #~ msgstr "Gajim изисква PyGTK 2.8 или по-нова версия" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above to run. Quiting..." #~ msgstr "Gajim изисква PyGTK 2.8 или по-нова версия. Спиране на програмата…" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above" #~ msgstr "Gajim изисква GTK 2.8 или по-нова версия" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above to run. Quiting..." #~ msgstr "Gajim изисква GTK 2.8 или по-нова версия. Спиране на програмата…" #~ msgid "Gajim needs pywin32 to run" #~ msgstr "Gajim изисква pywin32" #~ msgid "" #~ "Please make sure that Pywin32 is installed on your system. You can get it " #~ "at %s" #~ msgstr "" #~ "Уверете се, че Pywin32 е инсталиран на системата. Може да го изтеглите от " #~ "%s" #~ msgid "Gajim is already running" #~ msgstr "Gajim вече е стартиран" #~ msgid "" #~ "Another instance of Gajim seems to be running\n" #~ "Run anyway?" #~ msgstr "" #~ "Изглежда вече е стартирана друга инстанция на Gajim\n" #~ "Продължаване въпреки това?" #~ msgid "A programming error has been detected" #~ msgstr "Беше открита програмна грешка" #~ msgid "Details" #~ msgstr "Подробности" #, fuzzy #~ msgid "" #~ "Gnome Keyring is installed but not correctly started (environment " #~ "variable probably not correctly set)" #~ msgstr "" #~ "Наборът с ключове на GNOME е инсталиран, но не е стартиран правилно " #~ "(навярно променливата на обкръжението не е настроена)" #~ msgid "Jabber ID: " #~ msgstr "Jabber ID: " #~ msgid "Resource: " #~ msgstr "Ресурс: " #, fuzzy #~ msgid "Mood: " #~ msgstr "Настроение:" #, fuzzy #~ msgid "Activity: " #~ msgstr "Дейност:" #~ msgid "Join _Group Chat..." #~ msgstr "_Влизане в стая…" #~ msgid "_Modify Account" #~ msgstr "_Промяна на акаунт" #~ msgid "Check on startup if Gajim is the _default Jabber client" #~ msgstr "" #~ "_Да се проверява дали Gajim е стандартния Джабър клиент при стартиране" #~ msgid "" #~ "If True, Gajim will check if it's the default jabber client on each " #~ "startup." #~ msgstr "" #~ "Ако е активирана, Gajim ще проверява дали е стандартния Джабър клиент при " #~ "всяко стартиране." #~ msgid "Gajim is not the default Jabber client" #~ msgstr "Gajim не е стандартния Джабър клиент" #~ msgid "Would you like to make Gajim the default Jabber client?" #~ msgstr "Искате ли Gajim да бъде стандартния Джабър клиент?" #~ msgid "Always check to see if Gajim is the default Jabber client on startup" #~ msgstr "" #~ "Винаги да се проверява дали Gajim е стандартния Джабър клиент при всяко " #~ "стартиране" #~ msgid "Send Single Message" #~ msgstr "Изпращане на еднократно съобщение" #~ msgid "Execute Command..." #~ msgstr "Изпълнение на команда…" #~ msgid " a window/tab opened with that contact " #~ msgstr " отворен прозорец/подпрозорец с този контакт " #~ msgid "Actions" #~ msgstr "Действия" #~ msgid "Conditions" #~ msgstr "Условия" #~ msgid "Advanced Actions" #~ msgstr "Действия за напреднали" #~ msgid "Advanced Notifications Control" #~ msgstr "Контрол на уведомления за напреднали" #~ msgid "Busy " #~ msgstr "Зает " #, fuzzy #~ msgid "Contact Change Status " #~ msgstr "Контактът промени състоянието си" #~ msgid "Don't have " #~ msgstr "нямам " #, fuzzy #~ msgid "File Transfer Started " #~ msgstr "Файловият трансфер е преустановен" #, fuzzy #~ msgid "Group Chat Message Highlight " #~ msgstr "Осветено съобщение в стая" #, fuzzy #~ msgid "Group Chat Message Received " #~ msgstr "Получено съобщение в стая" #~ msgid "Launch a command" #~ msgstr "Изпълнение на команда" #~ msgid "One or more special statuses..." #~ msgstr "Едно или повече определени състояния…" #~ msgid "Online / Free For Chat" #~ msgstr "На линия / Свободен за разговор" #~ msgid "Play a sound" #~ msgstr "Изпълнение на звук" #~ msgid "When " #~ msgstr "Когато " #~ msgid "" #~ "_Activate window manager's UrgencyHint to make chat window in taskbar " #~ "flash" #~ msgstr "" #~ "_Активиране на подсказката за спешност на мениджъра на прозорци, за да " #~ "мига прозореца в панела" #~ msgid "_Disable auto opening chat window" #~ msgstr "_Изключване на автоматичното появяване на прозорец за разговор" #~ msgid "_Disable existing popup window" #~ msgstr "_Изключване на съществуващ изскачащ прозорец" #~ msgid "_Disable existing sound for this event" #~ msgstr "_Изключване на съществуващ звук за това събитие" #, fuzzy #~ msgid "_Disable showing event in notification area" #~ msgstr "_Изключване на показване на събитието в списъка" #~ msgid "_Disable showing event in roster" #~ msgstr "_Изключване на показване на събитието в списъка" #~ msgid "_Inform me with a popup window" #~ msgstr "_Информиране с изскачащ прозорец" #~ msgid "_Open chat window with user" #~ msgstr "_Отваряне на прозорец за разговор с потребителя" #~ msgid "_Show event in roster" #~ msgstr "Показване на събитието в спис_ъка" #~ msgid "and I " #~ msgstr "и аз " #, fuzzy #~ msgid "contact(s)" #~ msgstr "Контакти" #~ msgid "for " #~ msgstr "за " #, fuzzy #~ msgid "group(s)" #~ msgstr "Група" #~ msgid "when I'm in" #~ msgstr "когато съм" #~ msgid "_Allow him/her to see my status" #~ msgstr "_Позволение за виждане на състоянието ми" #, fuzzy #~ msgid "Descrition:" #~ msgstr "Описание: " #~ msgid "Advanced..." #~ msgstr "Напреднали…" #~ msgid "Display _activity of contacts in roster" #~ msgstr "Показване на _дейност на контактите в списъка" #~ msgid "Display _tunes of contacts in roster" #~ msgstr "Показване на _слушаната от контактите музика в списъка" #~ msgid "Display m_ood of contacts in roster" #~ msgstr "Показване на _настроенията на контактите в списъка" #~ msgid "" #~ "If checked, Gajim will display the activity of contacts in the roster " #~ "window" #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще изобразява дейността на контактите в " #~ "списъка." #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the location of contacts in the roster " #~ "window" #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще изобразява настроението на контактите " #~ "в списъка." #~ msgid "" #~ "If checked, Gajim will display the tunes of contacts in the roster window" #~ msgstr "" #~ "Ако тази опция е избрана, Gajim ще изобразява слушаната от контактите " #~ "музика в списъка." #~ msgid "Gajim Instant Messenger" #~ msgstr "Моментни съобщения (Gajim)" #~ msgid "English" #~ msgstr "английски" #~ msgid "Belarusian" #~ msgstr "белоруски" #~ msgid "Bulgarian" #~ msgstr "български" #~ msgid "Breton" #~ msgstr "бретонски" #~ msgid "Czech" #~ msgstr "чешки" #~ msgid "German" #~ msgstr "немски" #~ msgid "Greek" #~ msgstr "гръцки" #~ msgid "British" #~ msgstr "британски английски" #~ msgid "Esperanto" #~ msgstr "есперанто" #~ msgid "Spanish" #~ msgstr "испански" #~ msgid "Basque" #~ msgstr "баски" #~ msgid "French" #~ msgstr "френски" #~ msgid "Croatian" #~ msgstr "хърватски" #~ msgid "Italian" #~ msgstr "италиански" #~ msgid "Norwegian (b)" #~ msgstr "норвежки (Bokmål)" #~ msgid "Dutch" #~ msgstr "холандски" #~ msgid "Norwegian" #~ msgstr "норвежки (Nynorsk)" #~ msgid "Polish" #~ msgstr "полски" #~ msgid "Portuguese" #~ msgstr "португалски" #~ msgid "Brazilian Portuguese" #~ msgstr "бразилски португалски" #~ msgid "Russian" #~ msgstr "руски" #~ msgid "Serbian" #~ msgstr "сръбски" #~ msgid "Slovak" #~ msgstr "словашки" #~ msgid "Swedish" #~ msgstr "шведски" #~ msgid "Chinese (Ch)" #~ msgstr "китайски" #~ msgid "Spelling language" #~ msgstr "Език за проверка на правописа" #~ msgid "" #~ "If True, Gajim will convert string between $$ and $$ to an image using " #~ "dvips and convert before insterting it in chat window." #~ msgstr "" #~ "Ако е активирана, Gajim ще преобразува чрез „dvips“ низа между $$ и $$ в " #~ "изображение преди да го вмъкне в прозореца за разговор." #~ msgid "" #~ "Change the value to change the size of latex formulas displayed. The " #~ "higher is larger." #~ msgstr "" #~ "Променете стойността за увеличаване или намаляване размера на " #~ "изобразените формули на LaTeX. По-голяма стойност означава по-голям " #~ "размер." #~ msgid "all or space separated status" #~ msgstr "„all“ или състояния, разделени с интервал" #~ msgid "'yes', 'no', or 'both'" #~ msgstr "„yes“, „no“ или „both“" #~ msgid "'yes', 'no' or ''" #~ msgstr "„yes“, „no“ или „“" #~ msgid "Check your connection or try again later" #~ msgstr "Проверете връзката или опитайте отново по-късно" #~ msgid "Error executing \"%(command)s\": %(error)s" #~ msgstr "Грешка при изпълнение на „%(command)s“: %(error)s" #~ msgid "error: cannot open %s for reading" #~ msgstr "грешка: %s не може да бъде отворен за четене" #~ msgid "Unable to bind to port %s." #~ msgstr "Неуспех при свързването с порт %s." #~ msgid "" #~ "Maybe you have another running instance of Gajim. File Transfer will be " #~ "cancelled." #~ msgstr "" #~ "Навярно имате стартирана друга инстанция на Gajim. Файловият трансфер ще " #~ "бъде отменен." #~ msgid "A GTK+ jabber client" #~ msgstr "Джабър клиент за GTK+" #~ msgid "when I am " #~ msgstr "когато съм " #~ msgid "LaTeX" #~ msgstr "LaTeX" #~ msgid "Transform LaTeX expressions between $$ $$." #~ msgstr "Трансформира изрази на LaTex, разграничени с $$ $$." #, fuzzy #~ msgid "" #~ "Requires texlive-latex-base and (dvipng or ImageMagick). You have to set " #~ "'use_latex' to True in the Advanced Configuration Editor." #~ msgstr "" #~ "Изисква texlive-latex-base и dvipng. Трябва да активирате опцията " #~ "„use_latex“ в редактора на настройки за напреднали." #, fuzzy #~ msgid "" #~ "Requires texlive-latex-base and (dvipng or ImageMagick) (All is in " #~ "MikTeX). You have to set 'use_latex' to True in the Advanced " #~ "Configuration Editor." #~ msgstr "" #~ "Изисква texlive-latex-base и dvipng. Трябва да активирате опцията " #~ "„use_latex“ в редактора на настройки за напреднали." #, fuzzy #~ msgid "Requires python-farsight." #~ msgstr "Изисква python-avahi." #, fuzzy #~ msgid "one of: offline, online, chat, away, xa, dnd, invisible " #~ msgstr "" #~ "едно от: offline (изключен), online (на линия), chat (свободен за " #~ "разговор), away (отсъствам), xa (не съм на разположение), dnd (зает), " #~ "invisible (невидим)" #, fuzzy #~ msgid "" #~ "Returns current status message(the global one unless account is specified)" #~ msgstr "" #~ "Връща текущото съобщение за състояние (общото, в случай, че не е указан " #~ "акаунт)" #, fuzzy #~ msgid "" #~ "Too many arguments. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Твърде много аргументи. \n" #~ "Напишете „%(basename)s help %(command)s“ за повече информация" #, fuzzy #~ msgid "" #~ "Argument \"%s\" is not specified. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Не е указан аргумент „%(arg)s“.\n" #~ "Напишете „%(basename)s help %(command)s“ за повече информация" #~ msgid "Disk WriteError" #~ msgstr "Грешка при запис на диска" #~ msgid "Subject: %s" #~ msgstr "Тема: %s" #, fuzzy #~ msgid "Mood: %s" #~ msgstr "Настроение:" #, fuzzy #~ msgid "Activity: %s" #~ msgstr "Дейност:" #~ msgid "_Disable showing event in systray" #~ msgstr "_Изключване на показване на събитието в областта за уведомяване" #~ msgid "_Show event in systray" #~ msgstr "Показване на събитието в областта за _уведомяване" #, fuzzy #~ msgid "Autodetect on every Gajim startup" #~ msgstr "С_вързване при стартиране" #, fuzzy #~ msgid "Show systray:" #~ msgstr "Показване на събитието в областта за _уведомяване" #~ msgid "Nickname not allowed: %s" #~ msgstr "Псевдонимът не е позволен: %s" #~ msgid "we are now subscribed to %s" #~ msgstr "вече сме записани за %s" #~ msgid "we are now unsubscribed from %s" #~ msgstr "вече сме отписани от %s" #~ msgid "Account Modification" #~ msgstr "Промяна на акаунт" #~ msgid "" #~ "Check this so Gajim will connect in port 5223 where legacy servers are " #~ "expected to have SSL capabilities. Note that Gajim uses TLS encryption by " #~ "default if broadcasted by the server, and with this option enabled TLS " #~ "will be disabled" #~ msgstr "" #~ "Изберете тази опция, за да може Gajim да се свързва по порт 5223, където " #~ "се очаква сървърите да предоставят възможности по SSL. Забележете, че " #~ "Gajim използва шифриране тип TLS по подразбиране и избирайки тази опция, " #~ "изключвате TLS." #~ msgid "Edit Personal Information..." #~ msgstr "Редактиране на личните данни…" #~ msgid "Hostname: " #~ msgstr "Хост: " #~ msgid "" #~ "If checked, Gajim will store the password in ~/.gajim/config with 'read' " #~ "permission only for you" #~ msgstr "" #~ "Ако тази опция е избрана, паролата ще се запази в ~/.gajim/config с права " #~ "за четене само за потребителя." #~ msgid "Port: " #~ msgstr "Порт: " #~ msgid "Save _passphrase (insecure)" #~ msgstr "Запазване на _паролата (рисковано за сигурността)" #~ msgid "Use _SSL (legacy)" #~ msgstr "Използване на _SSL (извън употреба)" #~ msgid "gtk-add" #~ msgstr "gtk-add" #~ msgid "gtk-close" #~ msgstr "gtk-close" #~ msgid "gtk-remove" #~ msgstr "gtk-remove" #~ msgid "" #~ "Receive a Message\n" #~ "Contact Disconnected \n" #~ "Contact Change Status \n" #~ "Group Chat Message Highlight \n" #~ "Group Chat Message Received \n" #~ "File Transfer Request \n" #~ "File Transfer Started \n" #~ "File Transfer Finished" #~ msgstr "" #~ "се получава съобщение\n" #~ "контактът се изключва \n" #~ "контактът сменя състоянието си \n" #~ "се осветява съобщение в стая \n" #~ "се получава съобщение в стая \n" #~ "се получава запитване за файлов трансфер \n" #~ "започва файлов трансфер \n" #~ "завършва файлов трансфер" #~ msgid "" #~ "contact(s)\n" #~ "group(s)\n" #~ "everybody" #~ msgstr "" #~ "контакт(и)\n" #~ "група/и\n" #~ "всички" #~ msgid "" #~ "Account row\n" #~ "Group row\n" #~ "Contact row\n" #~ "Chat Banner" #~ msgstr "" #~ "Ред за акаунт\n" #~ "Ред за група\n" #~ "Ред за контакт\n" #~ "Лента за разговор" #~ msgid "" #~ "Enter JID or Contact name\n" #~ "Groupchat Histories\n" #~ "All Chat Histories" #~ msgstr "" #~ "Въведете JID или име на контакт\n" #~ "История на разговори в стаи\n" #~ "История на всички разговори" #~ msgid "gtk-delete" #~ msgstr "gtk-delete" #~ msgid "Send a file (Ctrl+F)" #~ msgstr "Изпращане на файл (Ctrl+F)" #~ msgid "" #~ "All chat states\n" #~ "Composing only\n" #~ "Disabled" #~ msgstr "" #~ "Всички състояния\n" #~ "Само при писане\n" #~ "Изключено" #~ msgid "" #~ "Autodetect on every Gajim startup\n" #~ "Always use GNOME default applications\n" #~ "Always use KDE default applications\n" #~ "Always use Xfce default applications\n" #~ "Custom" #~ msgstr "" #~ "Автоматично определяне при всяко стартиране на Gajim\n" #~ "Винаги да се използват стандартните програми на GNOME\n" #~ "Винаги да се използват стандартните програми на KDE\n" #~ "Винаги да се използват стандартните програми на Xfce\n" #~ "Персонални" #~ msgid "" #~ "Detached roster with detached chats\n" #~ "Detached roster with single chat\n" #~ "Single window for everything\n" #~ "Detached roster with chat grouped by account\n" #~ "Detached roster with chat grouped by type" #~ msgstr "" #~ "Отделен списък и прозорци за разговори\n" #~ "Отделен списък и един прозорец за разговори\n" #~ "Един прозорец за всичко\n" #~ "Отделен списък и разговори, групирани по акаунт\n" #~ "Отделен списък и разговори, групирани по вид" #~ msgid "" #~ "Pop it up\n" #~ "Notify me about it\n" #~ "Show only in roster" #~ msgstr "" #~ "Показване в изскачащ прозорец\n" #~ "Уведомяване\n" #~ "Показване само в списъка" #~ msgid "" #~ "none\n" #~ "both\n" #~ "from\n" #~ "to" #~ msgstr "" #~ "без\n" #~ "двустранно\n" #~ "от\n" #~ "за" #, fuzzy #~ msgid "gtk-cancel" #~ msgstr "gtk-close" #~ msgid "pysqlite2 (aka python-pysqlite2) dependency is missing. Exiting..." #~ msgstr "" #~ "Липсва зависимостта pysqlite2 (също познато и като python-pysqlite2). " #~ "Спиране на програмата…" #~ msgid "Ability to have clickable URLs in chat and groupchat window banners." #~ msgstr "" #~ "Възможност за натискане с мишката върху адреси в заглавните части на " #~ "прозорците." #~ msgid "Requires python-sexy." #~ msgstr "Изисква python-sexy." #~ msgid "GTK+ runtime is missing libglade support" #~ msgstr "Липсва поддръжка на libglade за библиотеката GTK+" #~ msgid "" #~ "Please remove your current GTK+ runtime and install the latest stable " #~ "version from %s" #~ msgstr "" #~ "Премахнете текущата версия на библиотеката GTK+ и инсталирайте последната " #~ "стабилна от %s" #~ msgid "" #~ "Please make sure that GTK+ and PyGTK have libglade support in your system." #~ msgstr "" #~ "Уверете се, че версиите на GTK+ и PyGTK на системата ви имат поддръжка за " #~ "libglade." #~ msgid "Gajim needs PySQLite2 to run" #~ msgstr "Gajim изисква PySQLite2" #, fuzzy #~ msgid "gtk-ok" #~ msgstr "gtk-close" #~ msgid "" #~ "The host %s you configured as the ft_add_hosts_to_send advanced option is " #~ "not valid, so ignored." #~ msgstr "" #~ "Хостът „%s“, който сте конфигурирали в опцията „ft_add_hosts_to_send“, не " #~ "е валиден, така че се пренебрегва." #~ msgid "OpenPGP passphrase was not given" #~ msgstr "Не беше зададена парола за OpenPGP" #~ msgid "" #~ "To continue sending and receiving messages, you will need to reconnect." #~ msgstr "" #~ "За да продължите да изпращате и получавате съобщения, трябва да се " #~ "свържете наново." #~ msgid "" #~ "You are not connected or not visible to others. Your message could not be " #~ "sent." #~ msgstr "" #~ "Не сте свързани и не сте видими за другите. Съобщението ви не можа да " #~ "бъде изпратено." #~ msgid "[This message is encrypted]" #~ msgstr "[Това съобщение е шифрирано]" #~ msgid "Trayicon" #~ msgstr "Икона в областта за уведомяване" #~ msgid "A icon in systemtray reflecting the current presence." #~ msgstr "Икона в областта за уведомяване, отразяваща текущото състояние." #~ msgid "" #~ "Requires python-gnome2-extras or compiled trayicon module from Gajim " #~ "sources." #~ msgstr "" #~ "Изисква python-gnome2-extras или компилиран модул „trayicon“ от изходния " #~ "код на Gajim." #~ msgid "Add Special _Notification" #~ msgstr "Добавяне на специално _уведомление" #~ msgid "Assign Open_PGP Key" #~ msgstr "Задаване на ключ на Open_PGP" #~ msgid "Commands: %s" #~ msgstr "Команди: %s" #~ msgid "" #~ "Usage: /%(command)s , sends action to the current group chat. Use " #~ "third person. (e.g. /%(command)s explodes.)" #~ msgstr "" #~ "Употреба: /%(command)s <действие>, изпраща действие до текущата стая. " #~ "Използва се трето лице (напр. „/%(command)s експлодира“)." #~ msgid "No help info for /%s" #~ msgstr "Няма помощна информация за /%s" #~ msgid "Enable link-local/zeroconf messaging" #~ msgstr "" #~ "Активиране на съобщения от/за локални потребители (link-local/zeroconf)" #~ msgid "Nickname not found: %s" #~ msgstr "Псевдонимът не е намерен: %s" #~ msgid "This group chat has no subject" #~ msgstr "Тази стая няма тема" #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], bans the JID from the group chat. The " #~ "nickname of an occupant may be substituted, but not if it contains \"@\". " #~ "If the JID is currently in the group chat, he/she/it will also be kicked." #~ msgstr "" #~ "Употреба: /%s <псевдоним|JID> [причина], отлъчва контакта от стаята. " #~ "Псевдонимът може да се замества, но не и ако съдържа „@“. Ако контактът е " #~ "в стаята, той също ще бъде изритан. Не се поддържат интервали в " #~ "псевдонима." #~ msgid "" #~ "Usage: /%s [reason], closes the current window or tab, displaying reason " #~ "if specified." #~ msgstr "" #~ "Употреба: /%s [причина], затваря текущия прозорец или подпрозорец и " #~ "показва причина, ако е указана." #~ msgid "" #~ "Usage: /%s [reason], invites JID to the current group chat, " #~ "optionally providing a reason." #~ msgstr "" #~ "Употреба: /%s [причина], кани JID в текущата стая, причината е по " #~ "избор." #~ msgid "" #~ "Usage: /%s @[/nickname], offers to join room@server " #~ "optionally using specified nickname." #~ msgstr "" #~ "Употреба: /%s <стая>@<сървър>[/псевдоним], предлага влизане в " #~ "стая@сървър, използването на указания псевдоним е по избор." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], removes the occupant specified by " #~ "nickname from the group chat and optionally displays a reason." #~ msgstr "" #~ "Употреба: /%s <псевдоним> [причина], премахва указания с псевдоним " #~ "участник от стаята и евентуално показва причина. Не се поддържат " #~ "интервали в псевдонима." #~ msgid "" #~ "Usage: /%s [message], opens a private message window and sends " #~ "message to the occupant specified by nickname." #~ msgstr "" #~ "Употреба: /%s <псевдоним> [съобщение], отваря прозорец за лично съобщение " #~ "и изпраща съобщение до участника, указан с псевдонима." #~ msgid "Usage: /%s , changes your nickname in current group chat." #~ msgstr "Употреба: /%s <псевдоним>, сменя псевдонима ви в текущата стая." #~ msgid "" #~ "Usage: /%s [topic], displays or updates the current group chat topic." #~ msgstr "" #~ "Употреба: /%s [тема], показва или актуализира текущата тема на стаята." #~ msgid "" #~ "Usage: /%s , sends a message without looking for other commands." #~ msgstr "" #~ "Употреба: /%s <съобщение>, изпраща съобщение без да се имат предвид други " #~ "команди." #, fuzzy #~ msgid "" #~ "Usage: /%s , allow to send you messages and private " #~ "messages." #~ msgstr "Употреба: /%s <псевдоним>, сменя псевдонима ви в текущата стая." #~ msgid "Click to see features (like MSN, ICQ transports) of jabber servers" #~ msgstr "" #~ "Натиснете, за да видите функционалностите (като MSN, ICQ транспорти) на " #~ "Джабър сървърите" #~ msgid "Name:" #~ msgstr "Име:" #~ msgid "_Host:" #~ msgstr "_Хост:" #, fuzzy #~ msgid "Select the account with which to synchronise" #~ msgstr "Изберете акаунт, с който искате да синхронизирате" #~ msgid "Modify Account" #~ msgstr "Промяна на акаунт" #~ msgid "" #~ "%(title)s by %(artist)s\n" #~ "from %(source)s" #~ msgstr "" #~ "%(title)s на %(artist)s\n" #~ "от %(source)s" #~ msgid "Gajim account %s" #~ msgstr "Акаунт „%s“" #~ msgid "This account is already configured in Gajim." #~ msgstr "Този акаунт вече е конфигуриран в Gajim." #~ msgid "PyOpenSSL" #~ msgstr "PyOpenSSL" #~ msgid "gnome-keyring" #~ msgstr "gnome-keyring" #~ msgid "" #~ "Requires python-gnome2-extras or compilation of gtkspell module from " #~ "Gajim sources." #~ msgstr "" #~ "Изисква python-gnome2-extras и компилация на модула „gtkspell“ от " #~ "изходния код на Gajim." #~ msgid "Idle" #~ msgstr "Време на бездействие" #~ msgid "Requires compilation of the idle module from Gajim sources." #~ msgstr "Изисква компилация на модула „idle“ от изходния код на Gajim." #~ msgid "libsexy" #~ msgstr "libsexy" #~ msgid "File transfer stopped by the contact at the other end" #~ msgstr "Файловият трансфер е преустановен от отсрещната страна" #~ msgid "Mood" #~ msgstr "Настроение" gajim-gajim-1.1.3/po/br.po000066400000000000000000011427501345766322700153020ustar00rootroot00000000000000# translation of gajim.po to # French translations for gajim package # Traduction anglaise du package gajim. # Copyright (C) 2004 THE gajim'S COPYRIGHT HOLDER # This file is distributed under the same license as the gajim package. # Automatically generated, 2004. # , 2005. # # msgid "" msgstr "" "Project-Id-Version: gajim 0.10\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2006-06-05 19:14+0100\n" "Last-Translator: Giulia Fraboulet \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Poedit-Language: French\n" "X-Poedit-Country: FRANCE\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "" #: gajim/chat_control_base.py:1103 #, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "" #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Restr" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Mare" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Araokadur" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Anv ar restr: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Ment: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "C'hwi" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Kaser: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Resever:" #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Enrollet e-barzh: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Echu eo an treuzkas" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 #, fuzzy msgid "Open _Containing Folder" msgstr "_Digeriñ ar renkell pal" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 #, fuzzy msgid "File transfer cancelled" msgstr "Nullet eo bet an treuzkas" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "N'eus ket tu seveniñ al lugadenn gant an darempred." #: gajim/filetransfers_window.py:288 #, fuzzy, python-format msgid "Recipient: %s" msgstr "Resever:" #: gajim/filetransfers_window.py:290 #, fuzzy, python-format msgid "Error message: %s" msgstr "Fazi en ur lenn ar restr:" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 #, fuzzy msgid "File transfer stopped" msgstr "Sac'het an treuzkas" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" #: gajim/filetransfers_window.py:341 #, fuzzy msgid "Gajim can not read this file" msgstr "N'hell ket Gajim tizhout ar restr-mañ" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "" #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Bez ez eus eus ar restr-mañ dija" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "Petra a fell deoc'h ober?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "" #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Restr: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Doare: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Taolennadur: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "Fellout a ra da %s kas deoc'h ur restr:" #: gajim/filetransfers_window.py:487 #, fuzzy msgid "Checking file…" msgstr "Kas ur _restr" #: gajim/filetransfers_window.py:501 #, fuzzy msgid "File error" msgstr "Fazi treuzkas" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/s)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Restr direizh" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Restr:" #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "N'eus ket tu da gas restroù goullo" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Anv:" #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Kaser:" #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Ehan" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "_Kenderc'hel" #: gajim/filetransfers_window.py:1019 #, fuzzy msgid "Choose a File to Send…" msgstr "Dibabit ur restr da gas..." #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 #, fuzzy msgid "Save _As" msgstr "Enrollet e-barzh: %s" #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "Dianav" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "Dianav" #: gajim/vcard.py:326 gajim/vcard.py:329 #, fuzzy msgid "?Time:Unknown" msgstr "Dianav" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "" #: gajim/vcard.py:384 #, fuzzy msgid "Affiliation:" msgstr "Poelladoù" #: gajim/vcard.py:391 #, fuzzy msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "" "Dedennet eo an darempred-mañ gant ho pezañs, met n'oc'h ket gant he/e hini" #: gajim/vcard.py:393 #, fuzzy msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "" "Dedennet oc'h gant bezañs an darempred-mañ, met hennezh/hounnez n'eo ket " "gant ho hini" #: gajim/vcard.py:395 #, fuzzy msgid "The contact and you want to exchange presence information" msgstr "Dedennet hoc'h an eil gant bezañs egile/eben" #: gajim/vcard.py:397 #, fuzzy msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "Dedennet hoc'h an eil gant bezañs egile/eben" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "Emaoc'h o c'hortoz respont an darempred d'ho koulenn koumanantiñ" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "" #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr "" #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "An holl restroù" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 #, fuzzy msgid "Clear File" msgstr "Darvoud" #: gajim/options_dialog.py:484 #, fuzzy msgid "Manage Proxies" msgstr "Merañ an aeladoù proksi" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Hini ebet" #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "Goulenn evit gwelet e/he stad" #: gajim/options_dialog.py:528 msgid "On" msgstr "" #: gajim/options_dialog.py:528 #, fuzzy msgid "Off" msgstr "Ezlinenn" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Fazi en ur dapout an alc'hwezhioù kuzh" #: gajim/options_dialog.py:565 #, fuzzy msgid "There is no OpenPGP secret key available." msgstr "Bez ez eus bet ur gudenn en ur gargañ hoc'h alc'hwezhioù-kuzh OpenPGP." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "Dibab un alc'hwezh OpenPGP" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Dibabit hoc'h alc'hwezh OpenPGP" #: gajim/gui_menu_builder.py:95 #, fuzzy msgid "_New Group Chat" msgstr "Flap a-stroll" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Ket er roll" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "Laouen 'vefen d'az ouzhpennañ em roll-darempredoù" #: gajim/gui_menu_builder.py:502 #, fuzzy msgid "Send Single _Message…" msgstr "Kas ur gemennadenn _simpl" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 #, fuzzy msgid "Send Cus_tom Status" msgstr "Goulenn evit gwelet e/he stad" #: gajim/gui_menu_builder.py:535 #, fuzzy msgid "E_xecute Command…" msgstr "urzhiad" #: gajim/gui_menu_builder.py:543 #, fuzzy msgid "_Manage Transport" msgstr "Dorioù" #: gajim/gui_menu_builder.py:549 #, fuzzy msgid "_Modify Transport" msgstr "Dorioù" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 #, fuzzy msgid "_Rename…" msgstr "_Adenvel" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 #, fuzzy msgid "Remo_ve" msgstr "_Dilemel" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 #, fuzzy msgid "_Information" msgstr "Titouroù" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 #, fuzzy msgid "Send File…" msgstr "Kas ur _restr" #: gajim/gui_menu_builder.py:602 #, fuzzy msgid "Upload File…" msgstr "Enrollañ ar restr dindan..." #: gajim/gui_menu_builder.py:603 #, fuzzy msgid "Send File Directly…" msgstr "Enrollañ ar restr dindan..." #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Darempredoù" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "_Ouzhpennañ er roll" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "Titouroù" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 #, fuzzy msgid "History" msgstr "_Istoradur" #: gajim/gui_menu_builder.py:634 #, fuzzy msgid "Manage Room" msgstr "Merañ ar sinedoù" #: gajim/gui_menu_builder.py:635 #, fuzzy msgid "Change Subject" msgstr "Kemmañ ar _sujed" #: gajim/gui_menu_builder.py:636 #, fuzzy msgid "Configure Room" msgstr "Ke_fluniañ ar flap" #: gajim/gui_menu_builder.py:637 #, fuzzy msgid "Upload Avatar…" msgstr "Dibabit ur skeudenn" #: gajim/gui_menu_builder.py:638 #, fuzzy msgid "Destroy Room" msgstr "Taolennadur: %s" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "" #: gajim/gui_menu_builder.py:641 #, fuzzy msgid "Change Nick" msgstr "Cheñch _lesanv" #: gajim/gui_menu_builder.py:642 #, fuzzy msgid "Bookmark Room" msgstr "_Ouzhpennañ ar webgaoz d'ar sinedoù" #: gajim/gui_menu_builder.py:643 msgid "Request Voice" msgstr "" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 #, fuzzy msgid "Notify on all messages" msgstr "Kemennadennoù raklakaet:" #: gajim/gui_menu_builder.py:645 msgid "Minimize on close" msgstr "" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 #, fuzzy msgid "Execute command" msgstr "urzhiad" #: gajim/gui_menu_builder.py:648 #, fuzzy msgid "Disconnect" msgstr "Darempred diluget" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "" #: gajim/gui_menu_builder.py:680 #, fuzzy, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "%i devezh 'zo" msgstr[1] "%i devezh 'zo" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Ebarzhiñ ur sal-flapiñ" #: gajim/gui_menu_builder.py:734 #, fuzzy msgid "Add Contact…" msgstr "_Ouzhpennañ un darempred..." #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 #, fuzzy msgid "Profile" msgstr "restr" #: gajim/gui_menu_builder.py:737 #, fuzzy msgid "Discover Services" msgstr "_Dizoleiñ ar servijoù" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Kas ur gemennadenn _simpl" #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Dre ar munut" #: gajim/gui_menu_builder.py:740 #, fuzzy msgid "Archiving Preferences" msgstr "_Penndibaboù" #: gajim/gui_menu_builder.py:741 #, fuzzy msgid "Synchronise History" msgstr "Diskouez an darempredoù _ezlinenn" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 #, fuzzy msgid "Privacy Lists" msgstr "Flapoù prevez" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 #, fuzzy msgid "Server Info" msgstr "Servijer" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "" #: gajim/gui_menu_builder.py:746 #, fuzzy msgid "Admin" msgstr "_Merour-ez" #: gajim/gui_menu_builder.py:747 #, fuzzy msgid "Send Server Message…" msgstr "_Kas ur gemennadenn d'ar servijer" #: gajim/gui_menu_builder.py:748 #, fuzzy msgid "Set MOTD…" msgstr "Lakaat MOTD" #: gajim/gui_menu_builder.py:749 #, fuzzy msgid "Update MOTD…" msgstr "Hizivaat MOTD" #: gajim/gui_menu_builder.py:750 #, fuzzy msgid "Delete MOTD…" msgstr "Dilemel MOTD" #: gajim/gui_menu_builder.py:799 #, fuzzy msgid "No Accounts available" msgstr "Kont ebet hegerz" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Kontoù" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 #, fuzzy msgid "Copy JID" msgstr "Webgaoz:" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Ebarzhiñ ur sal-flapiñ" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Kregiñ da flapiñ" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 #, fuzzy msgid "Add to Roster…" msgstr "_Ouzhpennañ er roll" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "_Kopiañ chomlec'h an ere" #: gajim/gui_menu_builder.py:881 #, fuzzy msgid "Open Link in Browser" msgstr "_Digerién an ere er furcher web" #: gajim/gui_menu_builder.py:886 #, fuzzy msgid "Copy Email Address" msgstr "_Kopiañ ar JID/Chomlec'h postel" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Digeriñ ar bostelerez" #: gajim/gui_menu_builder.py:892 #, fuzzy msgid "Copy JID/Email" msgstr "_Kopiañ ar JID/Chomlec'h postel" #: gajim/history_manager.py:71 #, fuzzy msgid "Usage:" msgstr "kemennadenn" #: gajim/history_manager.py:73 #, fuzzy msgid "Options:" msgstr "Boulomelloù:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "Dibosupl eo kavout titourva an istoradur" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Deiziad" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Lesanv" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Kemennadenn" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Titl" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" "Ha fellout a ra deoc'h naetaat an titourva? (DIALIET GROÑS M'EMAÑ GAJIM O " "VONT EN-DRO)" #: gajim/history_manager.py:257 msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" #: gajim/history_manager.py:262 msgid "Database Cleanup" msgstr "" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(time)s e lâras %(who)s: %(message)s\n" #: gajim/history_manager.py:577 #, fuzzy, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Ha fellout a ra deoc'h da vat diverkañ ar gemennadenn ziuzet?" #: gajim/history_manager.py:581 #, fuzzy msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "Ha sur oc'h e fell deoc'h diverkañ istoradur an darempred-mañ?" #: gajim/history_manager.py:583 #, fuzzy msgid "This can not be undone." msgstr "N'eo ket bet kavet ar servij" #: gajim/history_manager.py:585 gajim/history_manager.py:624 #, fuzzy msgid "Deletion Confirmation" msgstr "Titouroù" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Ha fellout a ra deoc'h da vat diverkañ ar gemennadenn ziuzet?" msgstr[1] "Ha fellout a ra deoc'h da vat diverkañ ar c'hemennadennoù diuzet?" #: gajim/history_manager.py:622 #, fuzzy msgid "This is an irreversible operation." msgstr "Setu un ober n'eus ket tu da vont war e giz." #: gajim/dialogs.py:82 #, fuzzy, python-format msgid "Contact name: %s" msgstr "Anv an darempred: %s" #: gajim/dialogs.py:84 #, fuzzy, python-format msgid "JID: %s" msgstr "JID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "Hollek" #: gajim/dialogs.py:200 msgid "Group" msgstr "Strollad" #: gajim/dialogs.py:207 msgid "In the group" msgstr "Er strollad" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "KeyID" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Anv an darempred" #: gajim/dialogs.py:483 #, fuzzy msgid "Set Mood" msgstr "Lakaat MOTD" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "Titour-stad %s" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Titour-stad" #: gajim/dialogs.py:807 #, fuzzy msgid "Overwrite Status Message?" msgstr "Titour-stad" #: gajim/dialogs.py:808 #, fuzzy msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "" "Implijet e vez an anv-mañ gant unan eus ho kontoù dija. Dibabit un anv all " "marplij." #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Enrollañ evel titour-stad rakenrollet" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Roit un anv d'an titour-stad-mañ" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Goulenn koumanantiñ" #: gajim/dialogs.py:857 #, fuzzy, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Goulenn enskrivañ evit ar gont %s digant %s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Goulenn enskrivañ digant %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "N'oc'h ket luget d'ar servijer" #: gajim/dialogs.py:928 #, fuzzy msgid "Without a connection, you can not synchronise your contacts." msgstr "Rankout a rit bezañ luget evit cheñch ger-kuzh." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Anv" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Servijer" #: gajim/dialogs.py:978 #, fuzzy msgid "This account is not connected to the server" msgstr "Luget eo ar gont \"%s\" d'ar servijer" #: gajim/dialogs.py:979 #, fuzzy msgid "You cannot synchronize with an account unless it is connected." msgstr "N'hellit ket ebarzhiñ ur sal-flapiñ keit ha ma n'oc'h ket luget." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "" #: gajim/dialogs.py:1065 #, fuzzy msgid "add" msgstr "Chomlec'h" #: gajim/dialogs.py:1065 #, fuzzy msgid "modify" msgstr "_Kemmañ" #: gajim/dialogs.py:1066 #, fuzzy msgid "remove" msgstr "_Dilemel" #: gajim/dialogs.py:1095 #, fuzzy, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "Me blijfe din ouzhpennañ ac'hanoc'h em roll-darempredoù." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 #, fuzzy msgid "Add" msgstr "Chomlec'h" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 #, fuzzy msgid "Modify" msgstr "_Kemmañ" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Dilemel" #: gajim/dialogs.py:1125 #, fuzzy msgid "Groups" msgstr "Strollad" #: gajim/dialogs.py:1233 #, fuzzy, python-format msgid "%s suggested me to add you in my roster." msgstr "Laouen 'vefen d'ho ouzhpennañ em roll-darempredoù." #: gajim/dialogs.py:1247 #, fuzzy, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "Ouzhpennañ un _darempred" msgstr[1] "Ouzhpennañ un _darempred" #: gajim/dialogs.py:1285 #, fuzzy, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "Dilemel an darempred diouzh ar roll" msgstr[1] "Dilemel an darempred diouzh ar roll" #: gajim/dialogs.py:1305 #, fuzzy msgid "You are invited to a groupchat" msgstr "Vous êtes banni de ce salon." #: gajim/dialogs.py:1308 #, fuzzy msgid "$Contact has invited you to join a discussion" msgstr "Pedet oc'h bet gant %(contact_jid)s er sal-flapiñ %(room_jid)s" #: gajim/dialogs.py:1310 #, fuzzy, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "Pedet oc'h bet gant %(contact_jid)s er sal-flapiñ %(room_jid)s" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Evezhiadenn: %s" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Pedadenn evit ur sal-flapiñ" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "" #: gajim/dialogs.py:1628 msgid "a video" msgstr "" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 #, fuzzy msgid "File Transfer" msgstr "Treuzkasoù" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "" #: gajim/dialogs.py:1764 #, fuzzy msgid "Encrypting file…" msgstr "Lazhet eo ar sifrañ" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, fuzzy, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%s a zo bremañ %s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s a zo bremañ %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Kas ar gemennadenn brevez c'hwitet" #: gajim/groupchat_control.py:253 #, fuzzy, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "N'emaoc'h ket er webgaoz \"%s\" ken, pe neuze eo aet kuit \"%s\"." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 #, fuzzy msgid "No File Transfer available" msgstr "Treuzkasoù" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Cheñch ar sujed" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Skrivit ar sujed nevez:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Cheñch lesanv" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Skrivit al lesanv nevez a fell deoc'h implij:" #: gajim/groupchat_control.py:711 #, fuzzy msgid "Invalid group chat JID" msgstr "ID jabber direizh" #: gajim/groupchat_control.py:712 #, fuzzy msgid "The group chat JID has not allowed characters." msgstr "Bez ez eus arouezioù difennet en anv ar sal pe hini ar servijer." #: gajim/groupchat_control.py:724 #, fuzzy, python-format msgid "Destroying %s" msgstr "Taolennadur: %s" #: gajim/groupchat_control.py:725 msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "Dibosupl eo kargañ ar skeudenn" #: gajim/groupchat_control.py:934 #, fuzzy msgid "Insert Nickname" msgstr "Cheñch _lesanv" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 #, fuzzy msgid "and authenticated" msgstr "Implij an diskleriañ" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 #, fuzzy msgid "and NOT authenticated" msgstr "Implij an diskleriañ" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" #: gajim/groupchat_control.py:1157 #, fuzzy msgid "Conversation with " msgstr "Istoradur ar gaoz" #: gajim/groupchat_control.py:1159 #, fuzzy msgid "Continued conversation" msgstr "Kevreadenn" #: gajim/groupchat_control.py:1525 #, fuzzy, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(nick)s a zo bet skarzhet : %(reason)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "" #: gajim/groupchat_control.py:1556 msgid "Room now shows unavailable members" msgstr "" #: gajim/groupchat_control.py:1558 msgid "Room now does not show unavailable members" msgstr "" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "" #: gajim/groupchat_control.py:1576 msgid "Room is now fully anonymous" msgstr "" #: gajim/groupchat_control.py:1615 #, python-format msgid "Ping? (%s)" msgstr "" #: gajim/groupchat_control.py:1618 #, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 #, fuzzy msgid "Error." msgstr "Fazi en ur lenn ar restr:" #: gajim/groupchat_control.py:1845 #, fuzzy, python-format msgid "You (%s) joined the room" msgstr "Er strollad" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, fuzzy, python-format msgid "%(jid)s has been invited in this room" msgstr "%(nick)s a zo bet skarzhet gant %(who)s : %(reason)s" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "" #: gajim/groupchat_control.py:1879 #, fuzzy msgid "A new room has been created" msgstr "Gant berzh eo bet krouet ho kont nevez!" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s a zo bet skarzhet : %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(nick)s a zo bet skarzhet gant %(who)s : %(reason)s" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "%(nick)s a zo argaset : %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(nick)s a zo argaset gant %(who)s : %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "Anavezet oc'h bremañ gant an anv %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, fuzzy, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(nick)s a zo bet skarzhet gant %(who)s : %(reason)s" #: gajim/groupchat_control.py:1950 msgid "affiliation changed" msgstr "" #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "" #: gajim/groupchat_control.py:2034 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "%(nick)s a zo bet skarzhet gant %(who)s : %(reason)s" #: gajim/groupchat_control.py:2038 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "%(nick)s a zo bet skarzhet : %(reason)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "Aet eo kuit %s" #: gajim/groupchat_control.py:2067 #, fuzzy, python-format msgid "%s has joined the group chat" msgstr "Er strollad" #: gajim/groupchat_control.py:2374 #, fuzzy, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Ha sur oc'h e fell deoc'h kuitaat ar flap \"%s\"?" #: gajim/groupchat_control.py:2376 #, fuzzy msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "Ma serrit ar prenestr-mañ, e tigevreoc'h diouzh ar flap-mañ." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 #, fuzzy msgid "_Do not ask me again" msgstr "_Chom hep goulenn ket" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Skarzhañ %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Bez e c'hellit reiñ un abeg amañ dindan:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Argas %s" #: gajim/chat_control.py:389 #, fuzzy msgid "Show a list of formattings" msgstr "Klikit evit enlakaat ur boulomell (Alt+M)" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 #, fuzzy msgid "This contact does not support HTML" msgstr "Ur roll eus an treuzkasoù oberiant, echu pe arsavet" #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "" #: gajim/chat_control.py:660 #, fuzzy, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s : %(message)s" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "O paouez resev ur gemennadenn nevez digant \"%s\" emaoc'h" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Ma serrit ar prenestr-mañ ha n'eo ket enaouet an istoradur, e vo kollet ar " "gemennadenn." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "" #: gajim/chat_control.py:1205 #, python-format msgid "Pong! (%s seconds)" msgstr "" #: gajim/chat_control.py:1313 #, fuzzy, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Titl : %s\n" "%s" #: gajim/chat_control.py:1416 #, fuzzy, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(nick)s a zo bremañ %(status)s" #: gajim/chat_control.py:1471 #, fuzzy msgid "File transfer" msgstr "Treuzkasoù" #: gajim/chat_control.py:1474 #, fuzzy msgid "Size" msgstr "Taille : " #: gajim/chat_control.py:1476 #, fuzzy msgid "Accept" msgstr "Asantiñ" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "E_barzhiñ" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 #, fuzzy msgid "Remote contact stopped transfer" msgstr "Dilemel an darempred diouzh ar roll" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 #, fuzzy msgid "Error opening file" msgstr "Fazi en ur lenn ar restr:" #: gajim/application.py:68 #, fuzzy msgid "Show the application's version" msgstr "_Implij an arlun-gelaouiñ (trayicon)" #: gajim/application.py:75 #, fuzzy msgid "Show only critical errors" msgstr "Diskouez er _roll hepken" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 #, fuzzy msgid "Use defined profile in configuration directory" msgstr "Aozer kefluniañ dre ar munut" #: gajim/application.py:105 #, fuzzy msgid "Set configuration directory" msgstr "Kefluniañ ar webgaoz" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 #, fuzzy msgid "Show all warnings" msgstr "Diskouez an holl _zarvoudoù o c'hortoz" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 #, fuzzy msgid "Pops up a window with the next pending event" msgstr "A zifoup ur prenestr gant ar gemennadenn dilenn da-heul" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 #, fuzzy msgid "Start a new chat" msgstr "Kregiñ da flapiñ" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Kontoù strollet" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Dorioù" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 #, fuzzy msgid "Groupchats" msgstr "Flapoù a-stroll" #: gajim/roster_window.py:2056 #, fuzzy msgid "Authorization sent" msgstr "Kaset eo bet an aotre" #: gajim/roster_window.py:2057 #, fuzzy, python-format msgid "\"%s\" will now see your status." msgstr "Anavezout a raio \"%s\" ho stad adalek bremañ." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Kaset eo bet ar goulenn goumanantiñ" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "Ma asant \"%s\" ar c'houmanant e weloc'h he/e stad." #: gajim/roster_window.py:2095 #, fuzzy msgid "Authorization removed" msgstr "Dilamet eo bet an aotre" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "Adalek bremañ e welo ac'hanoc'h \"%s\" atav evel pa vefec'h ezlinenn." #: gajim/roster_window.py:2120 #, fuzzy msgid "OpenPGP is not usable" msgstr "N'eus ket tu da implij OpenPGP war an urzhiataer-mañ" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Kemer a rit perzh e unan pe meur a webgaoz" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Tremen d'ar stad diwelus a lakao ac'hanoc'h da zilugañ diouzh ar webkaozioù-" "se. Ha sur oc'h e fell deoc'h bezañ diwelus?" #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "Dre ar munut" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "" #: gajim/roster_window.py:2426 #, fuzzy msgid "Are you sure you want to quit Gajim?" msgstr "Êtes-vous sûr de vouloir quitter les salons \"%s\" ?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "" #: gajim/roster_window.py:2514 #, fuzzy msgid "You have running file transfers" msgstr "Nullañ an treuzkas" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Kemennadennoù nevez ho peus" #: gajim/roster_window.py:2547 #, fuzzy msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "Posubl e vo lenn ar gemennadennoù diwezhatoc'h m'emañ an istoradur war enaou." #: gajim/roster_window.py:2825 #, fuzzy msgid "You must read them before removing this transport." msgstr "Lennit an holl zarvoudoù a-raok lemel ar gont-mañ." #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Dilamet e vo an nor \"%s\"" #: gajim/roster_window.py:2829 #, fuzzy msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" "N'helloc'h ket mui kas pe resev kemennadennoù d'an darempredoù liammet gant " "an nor-mañ." #: gajim/roster_window.py:2832 #, fuzzy msgid "Transports will be removed" msgstr "Dilamet e vo an nor \"%s\"" #: gajim/roster_window.py:2837 #, fuzzy, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" "N'helloc'h ket mui kas pe resev kemennadennoù d'an darempredoù liammet gant " "an nor-mañ." #: gajim/roster_window.py:2891 #, fuzzy msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "Rankout a rit krouiñ ur gont a-raok gellout flapiñ gant tud all." #: gajim/roster_window.py:2893 msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" #: gajim/roster_window.py:2939 #, fuzzy msgid "Rename Contact" msgstr "Darempredoù" #: gajim/roster_window.py:2940 #, fuzzy, python-format msgid "Enter a new nickname for contact %s" msgstr "Roit ho ker-kuzh GPG evit ar gont %s." #: gajim/roster_window.py:2947 #, fuzzy msgid "Rename Group" msgstr "_Adenvel" #: gajim/roster_window.py:2948 #, fuzzy, python-format msgid "Enter a new name for group %s" msgstr "Roit ho ker-kuzh GPG evit ar gont %s." #: gajim/roster_window.py:2993 #, fuzzy msgid "Remove Group" msgstr "_Dilemel" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "" #: gajim/roster_window.py:2995 #, fuzzy msgid "Also remove all contacts in this group from your roster" msgstr "Dilemel an darempred diouzh ar roll" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Assigner une clé OpenPGP" #: gajim/roster_window.py:3035 #, fuzzy msgid "Select a key to apply to the contact" msgstr "Dibabit un alc'hwezh da" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "Dilamet e vo an darempred \"%s\" diouzh ar roll" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "" #: gajim/roster_window.py:3448 #, fuzzy msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "En ur zilemel an darempred-mañ, e tilamit ivez e/he aotre. Atav e welo " "ac'hanoc'h evel pa vefec'h ezlinenn." #: gajim/roster_window.py:3454 #, fuzzy msgid "Do you want to continue?" msgstr "Petra a fell deoc'h ober?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "En ur zilemel an darempred-mañ, e tilamit dre-ziouer he/e aotre. Atav e welo " "ac'hanoc'h evel pa vefec'h ezlinenn." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Aotreañ an darempred-mañ da welout ma stad war-lerc'h e zilam" #: gajim/roster_window.py:3465 #, fuzzy msgid "Contacts will be removed from your roster" msgstr "Dilamet e vo an darempred \"%s\" diouzh ar roll" #: gajim/roster_window.py:3470 #, fuzzy, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "En ur zilemel an darempred-mañ, e tilamit ivez e/he aotre. Atav e welo " "ac'hanoc'h evel pa vefec'h ezlinenn." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "Rankout a rit krouiñ ur gont a-raok gellout flapiñ gant tud all." #: gajim/roster_window.py:3531 #, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Kont ebet hegerz" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "Rankout a rit krouiñ ur gont a-raok gellout flapiñ gant tud all." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "" #: gajim/roster_window.py:4180 msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" #: gajim/roster_window.py:4276 #, fuzzy msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "Rankout a rit krouiñ ur gont a-raok gellout flapiñ gant tud all." #: gajim/roster_window.py:4278 msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" #: gajim/roster_window.py:4400 #, fuzzy msgid "Invalid file URI:" msgstr "Restr direizh" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Kas ur _restr" #: gajim/roster_window.py:4412 #, fuzzy, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "Fellout a ra da %s kas deoc'h ur restr:" msgstr[1] "Fellout a ra da %s kas deoc'h ur restr:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Kas %s" #: gajim/roster_window.py:4565 #, fuzzy, python-format msgid "Make %s first contact" msgstr "Strollañ %s ha %s" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Strollañ %s ha %s" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "_Kemmañ an titour-stad" #: gajim/roster_window.py:4965 #, fuzzy msgid "Publish Tune" msgstr "_Embann" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "_Embann" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "_Dizoleiñ ar servijoù..." #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 #, fuzzy msgid "Send Group M_essage" msgstr "_Kas ur gemennadenn d'ar servijer" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "" #: gajim/roster_window.py:5135 #, fuzzy msgid "To all online users" msgstr "Utilisateurs En _Ligne" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "" #: gajim/roster_window.py:5299 #, fuzzy msgid "_Manage Contacts" msgstr "Darempredoù" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Kemmañ ar _strolladoù" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "_Dilemel" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "" #: gajim/roster_window.py:5370 #, fuzzy msgid "_Reconnect" msgstr "Darempred diluget" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 #, fuzzy msgid "_Disconnect" msgstr "Darempred diluget" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Istoradur" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Merour an istoradur" #: gajim/roster_window.py:5475 #, fuzzy msgid "_Join New Group Chat" msgstr "Ebarzhiñ ur sal-flapiñ" #: gajim/config.py:359 msgid "Ban List" msgstr "Roll argas" #: gajim/config.py:360 msgid "Member List" msgstr "Roll an izili" #: gajim/config.py:360 msgid "Owner List" msgstr "Roll ar perc'hennerien" #: gajim/config.py:361 msgid "Administrator List" msgstr "Roll ar verourien" #: gajim/config.py:435 msgid "Reason" msgstr "Abeg" #: gajim/config.py:442 msgid "Nick" msgstr "Lesanv" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "Perzh" #: gajim/config.py:478 #, fuzzy msgid "Banning…" msgstr "Oc'h argas..." #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Piv a fell deoc'h argas ?\n" "\n" #: gajim/config.py:482 #, fuzzy msgid "Adding Member…" msgstr "Oc'h ouzhpennañ un ezel..." #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" "Piv a fell deoc'h lakaat da ezel ?\n" "\n" #: gajim/config.py:485 #, fuzzy msgid "Adding Owner…" msgstr "Oc'h ouzhpennañ ur perc'henn..." #: gajim/config.py:486 #, fuzzy msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "" "Piv a fell deoc'h lakaat da berc'henn ?\n" "\n" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "Oc'h ouzhpennañ ur v-merour-ez..." #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" "Piv a fell deoc'h lakaat da verour-ez ?\n" "\n" #: gajim/config.py:490 #, fuzzy msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" "A c'hell bezañ unan eus ar stummoù da heul :\n" "1. lesanv@domani/resource(seulement cette ressource correspond).\n" "2. pseudo@domaine (toutes les ressources correspondent).\n" "3. domaine/ressources (seulement cette ressource correspond).\n" "4. domaine (le domaine complet correspond, incluant tous les " "pseudo@domaine,\n" "domaine/ressource, ou les adresses comprenant un sous-domaine)." #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Lemel ar gont %s" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Lazhet eo ar sifrañ" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Ger-kuzh ret" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Roit ho ker-kuzh evit ar gont %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Enrollañ ar ger-kuzh" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Luget eo ar gont \"%s\" d'ar servijer" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Ma tilamit anezhañ, e voc'h diluget." #: gajim/config.py:652 #, fuzzy, python-format msgid "Connection to server %s failed" msgstr "Kevreadenn" #: gajim/config.py:653 #, fuzzy msgid "What would you like to do?" msgstr "Petra a fell deoc'h ober?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Dilemel ar gont diwar Gajim _hepken" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Sonioù wav" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "Kemennadenn gentañ" #: gajim/config.py:746 msgid "First Message Received" msgstr "Kemennadenn gentañ" #: gajim/config.py:747 #, fuzzy msgid "Next Message Received Focused" msgstr "Kemennadenn da-heul" #: gajim/config.py:748 #, fuzzy msgid "Next Message Received Unfocused" msgstr "Kemennadenn da-heul" #: gajim/config.py:749 msgid "Contact Connected" msgstr "Darempred luget" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "Darempred diluget" #: gajim/config.py:751 msgid "Message Sent" msgstr "Kemennadenn gaset" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "Message d'un Salon mis en Sur-brillance" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "Kemennadenn digant ur sal-flapiñ" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 #, fuzzy msgid "?Group Chat Contact Affiliation:None" msgstr "Hini ebet" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 #, fuzzy msgid "Member" msgstr "_Ezel" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 #, fuzzy msgid "Administrator" msgstr "_Merour-ez" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 #, fuzzy msgid "Owner" msgstr "_Perc'hener-ez" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr "" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr "" #: gajim/tooltips.py:574 #, fuzzy msgid "Connected" msgstr "Kevreadenn" #: gajim/tooltips.py:576 #, fuzzy msgid "Disconnected" msgstr "Darempred diluget" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Pellgargañ" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Kas" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Doare:" #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Treuzkaset:" #: gajim/tooltips.py:645 msgid "Status: " msgstr "Stad:" #: gajim/tooltips.py:647 #, fuzzy msgid "Description: " msgstr "Taolennadur: %s" #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Echu" #: gajim/tooltips.py:676 #, fuzzy msgid "?transfer status:Paused" msgstr "Diskouez an eur:" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "O treuzkas" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "N'eo ket kroget" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "Diskouez an eur:" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Prest da flapiñ" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Ezvezant" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Dihegerz" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Ezlinenn" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "_Kemmañ an titour-stad" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "en ur implij ar gont %s" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Merañ ar sinedoù" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "Ket er roll" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "Diskouez ar _roll-darempredoù" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Kuzhat ar meuziad-mañ" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Impossible de rejoindre le salon" #: gajim/dataforms_widget.py:586 #, python-format msgid "Media type not supported: %s" msgstr "" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "N'eus ket bet kaset titouroù munut gant ar servij-mañ c'hoazh" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "N'eus ket bet kaset titouroù munut gant ar servij-mañ.\n" "Sur 'walc'h eo torr pe kamm" #: gajim/disco.py:121 msgid "Others" msgstr "Traoù all" #: gajim/disco.py:125 msgid "Conference" msgstr "Kendiviz" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "Rankout a rit bezañ luget evit gellout furchal er servijoù hegerz" #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "Merañ servijoù ar gont %s" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Merañ ar servijoù" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "N'eo ket bet kavet ar servij" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "N'eus servij ebet er chomlec'h roet, pe ne respont ket. Gwiriekait ar " "chomlec'h ha klaskit en-dro." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "N'eus ket tu furchal er servij" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "N'eus elfenn ebet da furchal e seurt servijoù." #: gajim/disco.py:726 gajim/disco.py:736 #, fuzzy msgid "Invalid Server Name" msgstr "Anv-arveriad-ez direizh" #: gajim/disco.py:794 #, fuzzy, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "O furchal e-barzh %s oc'h implij ar gont %s" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Furchal" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "N'eus elfenn ebet da furchal er servij-mañ." #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "urzhiad" #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "_Emezelañ" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "E_barzhiñ" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "Klask" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Aozañ" #: gajim/disco.py:1450 #, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "" #: gajim/disco.py:1649 msgid "Users" msgstr "Arveridi" #: gajim/disco.py:1657 msgid "Description" msgstr "Taolennadur" #: gajim/disco.py:1665 msgid "Id" msgstr "" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 #, fuzzy msgid "_Bookmark" msgstr "_Ouzhpennañ ar webgaoz d'ar sinedoù" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Sined lakaet dija" #: gajim/disco.py:1722 #, fuzzy, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "Emañ ar flap \"%s\" en ho sinedoù dija." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Gant berzh eo bet ouzhpennet ar sined" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "" "Bez e c'hellit merañ ho sinedoù dre ar meuziad Oberoù er roll-darempredoù." #: gajim/disco.py:1929 #, fuzzy msgid "Subscribed" msgstr "Emezelañ" #: gajim/disco.py:1938 #, fuzzy msgid "Node" msgstr "Hini ebet" #: gajim/disco.py:2005 msgid "New post" msgstr "" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "_Koumanantiñ" #: gajim/disco.py:2017 #, fuzzy msgid "_Unsubscribe" msgstr "_Koumanantiñ" #: gajim/conversation_textview.py:320 #, fuzzy msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" "Dindan al linenn e welit ar pezh a zo bet lâret er sal-flapiñ dibaoe ar wech " "diwezhañ ho peus taolet ur sell ennañ." #: gajim/conversation_textview.py:541 #, fuzzy msgid "_Quote" msgstr "_Kuitaat" #: gajim/conversation_textview.py:549 #, fuzzy, python-format msgid "_Actions for \"%s\"" msgstr "Oberoù evit \"%s\"" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Lenn pennad _Wikipedia" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Klask er _geriadur" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "" "Mankout a ra un \"%s\" e-barzh URL ar geriaoueg, ha n'eo ket WIKTIONARY" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "Mankout a ra un \"%s\" e-barzh URL ar webklask" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "Web_klask" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "ID jabber direizh" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, fuzzy, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "Dec'h" msgstr[1] "Dec'h" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "N'eo ket kroget" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Sujed: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Kemennadenn hiniennel nevez" #: gajim/message_window.py:243 #, fuzzy msgid "You are going to close several tabs" msgstr "N'oc'h ket luget d'ar servijer" #: gajim/message_window.py:244 #, fuzzy msgid "Do you really want to close them all?" msgstr "Ha fellout a ra deoc'h da vat diverkañ ar gemennadenn ziuzet?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Flapoù a-stroll" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "Flapoù prevez" #: gajim/message_window.py:530 msgid "Messages" msgstr "Kemennadennoù" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 #, fuzzy msgid "Unable to join group chat" msgstr "Impossible de rejoindre le salon" #: gajim/gui_interface.py:170 #, fuzzy, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "Le surnom que vous vouliez utiliser est actuellement utilisé ou enregistré " "par un autre occupant.\n" "Veuillez entrer un autre surnom ci-dessous :" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Degemer a rit ar goulenn-mañ?" #: gajim/gui_interface.py:194 #, fuzzy, python-format msgid "Do you accept this request on account %s?" msgstr "Degemer a rit ar goulenn-mañ?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "Aotre HTTP (%s) evit %s (id : %s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 #, fuzzy msgid "Connection Failed" msgstr "Kevreadenn" #: gajim/gui_interface.py:327 #, fuzzy, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "Un mot de passe est requis pour rejoindre ce salon." #: gajim/gui_interface.py:342 #, fuzzy, python-format msgid "%s is full" msgstr "Sonioù" #: gajim/gui_interface.py:351 #, fuzzy, python-format msgid "You are banned from group chat %s." msgstr "Vous êtes banni de ce salon." #: gajim/gui_interface.py:358 #, fuzzy, python-format msgid "Remote server %s does not exist." msgstr "Ce salon n'existe pas." #: gajim/gui_interface.py:362 #, fuzzy, python-format msgid "Group chat %s does not exist." msgstr "Ce salon n'existe pas." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "La création de salon est réservée aux administrateurs." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Impossible de rejoindre le salon" #: gajim/gui_interface.py:368 #, fuzzy, python-format msgid "You must use your registered nickname in %s." msgstr "Vous devez utiliser le surnom donné lors de l'enregistrement." #: gajim/gui_interface.py:373 #, fuzzy, python-format msgid "You are not in the members list in groupchat %s." msgstr "Vous n'êtes pas dans la liste des membres." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, fuzzy, python-format msgid "Error %(code)s: %(msg)s" msgstr "%(nickname)s : %(message)s" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, fuzzy, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "fazi en ur gas %s ( %s )" #: gajim/gui_interface.py:503 gajim/notify.py:194 #, fuzzy msgid "Subscription request" msgstr "Goulenn koumanantiñ" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "Sellerien" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Aotre degmeret" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "Aotreet oc'h bet gant \"%s\" da welet e stad." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Dilamet eo bet ho aotre digant \"%s\"" #: gajim/gui_interface.py:539 msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" #: gajim/gui_interface.py:560 gajim/notify.py:194 #, fuzzy msgid "Unsubscribed" msgstr "_Koumanantiñ" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, fuzzy, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Vous êtes banni de ce salon." #: gajim/gui_interface.py:658 msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "Luget oc'h hep hoc'h alc'hwezh OpenPGP." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Ger-kuzh faos" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Ger-kuzh faos" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "Ger-kuzh ret" #: gajim/gui_interface.py:683 #, fuzzy, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Roit ho ker-kuzh GPG evit ar gont %s." #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Dibabit hoc'h alc'hwezh OpenPGP" #: gajim/gui_interface.py:706 msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Fazi treuzkas" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "Fellout a ra da %s kas deoc'h ur restr." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Goulenn treuzkas" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Echu an treuzkasadenn" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Sac'het an treuzkas" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Treuzkasoù" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Arsavet eo an treuskas eus %(filename)s digant %(name)s." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Arsavet eo an treuskas eus %(filename)s digant %(name)s." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Arsavet eo an treuskas eus %(filename)s digant %(name)s." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Gant berzh ho peus kaset %(filename)s da %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Arsavet eo an treuzkas eus %(filename)s da %(name)s." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Arsavet eo an treuzkas eus %(filename)s da %(name)s." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "" #: gajim/gui_interface.py:1178 #, fuzzy msgid "Please type a new username for your local account" msgstr "Leuniit an titouroù evit ho kont nevez" #: gajim/gui_interface.py:1201 msgid "Resource Conflict" msgstr "" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "" #: gajim/gui_interface.py:1259 #, fuzzy, python-format msgid "%s wants to start a voice chat." msgstr "Fellout a ra da %s kas deoc'h ur restr." #: gajim/gui_interface.py:1261 #, fuzzy msgid "Voice Chat Request" msgstr "Goulenn treuzkas" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 #, fuzzy msgid "Certificate Already in File" msgstr "Darempred er roll dija" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" #: gajim/gui_interface.py:1351 #, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "" #: gajim/gui_interface.py:1354 #, fuzzy, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "Aozadur D-Bus dianav: %s" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "" #: gajim/gui_interface.py:1362 #, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "" #: gajim/gui_interface.py:1380 #, fuzzy, python-format msgid "SSL Certificate Verification for %s" msgstr "Oc'h ouzhpennañ ur gelaouenn nevez evit %s" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 #, fuzzy msgid "Insecure connection" msgstr "Kevreadenn" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "Rankout a rit krouiñ ur gont a-raok gellout flapiñ gant tud all." #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "N'hellit ket ebarzhiñ ur sal-flapiñ keit ha ma n'oc'h ket luget." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "A guzha an nozelennoù er prenestr flapiñ" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 #, fuzzy msgid "You cannot join a group chat while you are invisible" msgstr "N'hellit ket ebarzhiñ ur webgaoz keit ha m'emaoc'h diwelus." #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Dibosupl eo enrollañ ho tibarzhioù ha dibaboù" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Ger-kuzh ret" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "Roit ho ker-kuzh GPG evit ar gont %s." #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "Dibab un alc'hwezh OpenPGP" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "Luget e voc'h da %s hep OpenPGP." #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "Ger-kuzh faos" #: gajim/gui_interface.py:2853 #, fuzzy msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "Adroit ho ker-kuzh GPG pe pouezit war Nullañ." #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "O skrivañ" #: gajim/atom_window.py:123 #, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "" msgstr[1] "" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "" #: gajim/adhoc_commands.py:326 #, fuzzy msgid "Cancel confirmation" msgstr "Titouroù" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "" #: gajim/adhoc_commands.py:422 #, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Darempred luget" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Darempred diluget" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Kemennadenn nevez" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Kemennadenn simpl nevez" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Kemennadenn hiniennel nevez" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 #, fuzzy msgid "Contact Changed Status" msgstr "Darempred diluget" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenPGP : " #: gajim/notify.py:270 msgid "New E-mail" msgstr "Postel nevez" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "N'hellit ket ebarzhiñ ur sal-flapiñ keit ha ma n'oc'h ket luget." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 #, fuzzy msgid "Invalid JID" msgstr "ID jabber direizh" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, fuzzy, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "N'eus ket tu da gas restroù goullo" #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "Darvoudoù chomet dilenn" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "Lennit an holl zarvoudoù a-raok lemel ar gont-mañ." #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "Luget oc'h d'ar servijer" #: gajim/dialog_messages.py:53 #, fuzzy msgid "To disable the account, you must be disconnected." msgstr "Rankout a rit bezañ diluget evit cheñch anv ar gont." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Road direizh" #: gajim/dialog_messages.py:58 #, fuzzy msgid "The form is not filled correctly." msgstr "Bez ez eus arouezioù difennet en anv ar sal pe hini ar servijer." #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Diwelus" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "N'eus ket tu da gevreañ" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "N'eus ket tu da gas ho kemennadenn keit ha ma n'oc'h ket luget." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "Flaperez Jabber" #: gajim/dialog_messages.py:73 msgid "The JID you entered is already in the list. Choose another one." msgstr "" #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "Respont direizh" #: gajim/dialog_messages.py:78 #, fuzzy, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "Respontet fall he deus an nor %s d'ar goulenn emezelañ." #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Implij un anv ostiz/porzh personelaet" #: gajim/dialog_messages.py:84 #, fuzzy, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Implij un anv ostiz/porzh personelaet" #: gajim/dialog_messages.py:88 #, fuzzy msgid "Error while removing privacy list" msgstr "fazi en ur gas %s ( %s )" #: gajim/dialog_messages.py:89 #, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" #: gajim/dialog_messages.py:95 msgid "Invisibility not supported" msgstr "" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "" #: gajim/dialog_messages.py:100 #, fuzzy msgid "Unregister failed" msgstr "échec lors de la publication de votre vCard" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "" #: gajim/dialog_messages.py:105 #, fuzzy msgid "Registration succeeded" msgstr "Gant berzh eo bet embannet ar vCard" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 #, fuzzy msgid "Registration failed" msgstr "échec lors de la publication de votre vCard" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Impossible de rejoindre le salon" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, fuzzy, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "Fazi en ur lenn ar restr:" #: gajim/dialog_messages.py:126 #, fuzzy msgid "Wrong host" msgstr "Ger-kuzh faos" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 #, fuzzy msgid "Could not request upload slot" msgstr "Dibosupl eo kargañ ar skeudenn" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 #, fuzzy msgid "Could not open file" msgstr "Dibosupl eo kargañ ar skeudenn" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 msgid "Server returned unsecure transport (HTTP)" msgstr "" #: gajim/dialog_messages.py:161 #, fuzzy msgid "Could not upload file" msgstr "Dibosupl eo kargañ ar skeudenn" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 #, fuzzy msgid "Encryption Error" msgstr "War enaou emañ ar sifrañ" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "N'eus ket tu da gevreañ" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "C'hwitet eo embannadur ar vCard" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "" "N'eus ket eus D-Bus war an urzhiataer-mañ, pe mankout a ra ur mollad python" #: gajim/gajim_remote.py:77 #, fuzzy msgid "Shows a help on specific command" msgstr "diskouez ar skoazell evit un urzhiad resis" #: gajim/gajim_remote.py:80 msgid "command" msgstr "urzhiad" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "diskouez ar skoazell evit an urzhiad" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "A ziskouez ur roll eus an holl zarempredoù, pep darempred war ul linenn." #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "kont" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "diskouez darempredoù ar gont roet hepken" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "A ziskouez roll ar c'hontoù enrollet" #: gajim/gajim_remote.py:97 #, fuzzy msgid "Changes the status of account(s)" msgstr "A cheñch stad ar gont pe ar c'hontoù" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "stad" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "unan eus: offline, online, chat, away, xa, dnd, invisible " #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "kemennadenn" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "titour stad" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "A cheñch stad ar gont \"kont\". Ma n'eus hini ebet roet, klaskit cheñch stad " "an holl gontoù o deus an dibab \"sync with global status\" enaouet" #: gajim/gajim_remote.py:108 #, fuzzy msgid "Changes the priority of account(s)" msgstr "A cheñch stad ar gont pe ar c'hontoù" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "Digant" #: gajim/gajim_remote.py:110 #, fuzzy msgid "priority you want to give to the account" msgstr "Fellout a ra din emezelañ evit krouiñ ur gont" #: gajim/gajim_remote.py:112 #, fuzzy msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "A cheñch stad ar gont \"kont\". Ma n'eus hini ebet roet, klaskit cheñch stad " "an holl gontoù o deus an dibab \"sync with global status\" enaouet" #: gajim/gajim_remote.py:118 #, fuzzy msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Envoyer un nouveau message à un contact dans la liste. La clé OpenPGP et le " "compte sont facultatifs. Si vous voulez renseigner seulement le paramètre " "'compte' sans 'clé pgp', mettez simple la valeur '' pour 'clé pgp'." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID an darempred hag a resevo ar gemennadenn" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "korf ar gemennadenn" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "Ma vez resisaet, e vo kaset ar gemennadenn en ur implij ar gont-mañ" #: gajim/gajim_remote.py:131 #, fuzzy msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Envoyer un nouveau message à un contact dans la liste. La clé OpenPGP et le " "compte sont facultatifs. Si vous voulez renseigner seulement le paramètre " "'compte' sans 'clé pgp', mettez simple la valeur '' pour 'clé pgp'." #: gajim/gajim_remote.py:136 #, fuzzy msgid "subject" msgstr "Titl" #: gajim/gajim_remote.py:136 #, fuzzy msgid "message subject" msgstr "Kemennadenn gaset" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "" #: gajim/gajim_remote.py:147 #, fuzzy msgid "JID of the room that will receive the message" msgstr "JID an darempred hag a resevo ar gemennadenn" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Evit kargañ titouroù-munut un darempred" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "JID an darempred" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "Evit kargañ titouroù-munut ur gont" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "Anv ar gont" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Kas ur restr d'un darempred" #: gajim/gajim_remote.py:168 msgid "file" msgstr "restr" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Treug ar restr" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "m'eo resisaet, e vo kaset ar rest en ur implij ar gont-mañ" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Roll an holl zibaboù hag o zalvoudoù" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "A laka talvoud an 'alc'hwezh' da 'dalvoud'." #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "alc'hwezh=talvoud" #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "'alc'hwezh' eo anv an dibab, 'talvoud' eo an talvoud da lakaat dezhañ" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "A zilam un elfenn dibab" #: gajim/gajim_remote.py:188 msgid "key" msgstr "touchenn" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "anv an dibab da zilemel" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "A skriv stad red dibaboù Gajim er restr .config" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Dilemel an darempred diouzh ar roll" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "Si spécifié, le contact est pris dans la liste de contact de ce compte" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "" "A ro ar stad red (an hini hollek, nemet ez eus bet resisaet ur gont bennak)" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" "A gas an titour-stad red (an hini hollek, nemet ez eus bet resisaet ur gont " "bennak)" #: gajim/gajim_remote.py:221 #, fuzzy msgid "Returns number of unread messages" msgstr "A ro an niver a gemennadennoù chomet dilenn" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "" #: gajim/gajim_remote.py:229 msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Darempred diluget" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "N'eus ket bet kavet al lesanv : %s" #: gajim/gajim_remote.py:238 msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" #: gajim/gajim_remote.py:245 msgid "Check if Gajim is running" msgstr "" #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "N'emañ ket '%s' en hor roll darempredoù.\n" "Resisait ar gont evit kas ur gemennadenn." #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "N'ho peus kont bev ebet" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "" #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Arguments :" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "N'eo ket bet kavet %s" #: gajim/gajim_remote.py:383 #, fuzzy, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Implij: %s urzhiad [arguments]\n" "urzhiad eo unan eus :\n" #: gajim/gajim_remote.py:453 #, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" #: gajim/gajim_remote.py:458 #, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "" #: gajim/common/fuzzyclock.py:36 #, fuzzy msgid "one" msgstr "Hini ebet" #: gajim/common/fuzzyclock.py:36 #, fuzzy msgid "two" msgstr "piv" #: gajim/common/fuzzyclock.py:36 #, fuzzy msgid "three" msgstr "Straed:" #: gajim/common/fuzzyclock.py:36 #, fuzzy msgid "four" msgstr "Porzh:" #: gajim/common/fuzzyclock.py:37 #, fuzzy msgid "five" msgstr "restr" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "" #: gajim/common/fuzzyclock.py:37 #, fuzzy msgid "seven" msgstr "Darvoud" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "" #: gajim/common/fuzzyclock.py:37 #, fuzzy msgid "nine" msgstr "_Kenderc'hel" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "" #: gajim/common/fuzzyclock.py:38 #, fuzzy msgid "eleven" msgstr "Dilemel" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "" #: gajim/common/fuzzyclock.py:46 #, fuzzy, python-format msgid "five past %(0)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:47 #, fuzzy, python-format msgid "ten past %(0)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:48 #, fuzzy, python-format msgid "quarter past %(0)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:49 #, fuzzy, python-format msgid "twenty past %(0)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:50 #, fuzzy, python-format msgid "twenty five past %(0)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:52 #, fuzzy, python-format msgid "twenty five to %(1)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:53 #, fuzzy, python-format msgid "twenty to %(1)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:54 #, fuzzy, python-format msgid "quarter to %(1)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:55 #, fuzzy, python-format msgid "ten to %(1)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:56 #, fuzzy, python-format msgid "five to %(1)s" msgstr "Emezelañ war %s" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "" #: gajim/common/fuzzyclock.py:63 #, fuzzy msgid "Morning" msgstr "O labourat" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "" #: gajim/common/fuzzyclock.py:65 #, fuzzy msgid "Noon" msgstr "Hini ebet" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "" #: gajim/common/fuzzyclock.py:67 #, fuzzy msgid "Evening" msgstr "Darvoud" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, fuzzy, python-format msgid "%s is a directory but should be a file" msgstr "ur renkell eo %s met rankout a rafe bezañ ur restr" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Taolennadur: %s" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 #, fuzzy msgid "Room has been destroyed" msgstr "Dilamet eo bet an aotre" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "" #: gajim/common/connection_handlers_events.py:598 #, fuzzy, python-format msgid "Unknown SSL error: %d" msgstr "Aozadur D-Bus dianav: %s" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Kemennadenn nevez digant %(nickname)s" msgstr[1] "Kemennadenn nevez digant %(nickname)s" #: gajim/common/connection_handlers_events.py:1118 #, fuzzy, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s a zo bremañ %(status)s" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "Emañ %(nickname)s o paouez lugañ" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "Emañ %(nickname)s o paouez dilugañ" #: gajim/common/contacts.py:427 #, fuzzy msgid "Not in roster" msgstr "Ket er roll" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "" #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "War-lerc'h pet munutenn e vo lakaet ho stad evel ezvezant." #: gajim/common/config.py:87 #, fuzzy msgid "$S (Away as a result of being idle more than $T min)" msgstr "Ezvezant rak dizoberiant" #: gajim/common/config.py:87 msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "War-lerc'h pet munutenn e vo lakaet ho stad evel dihegerz." #: gajim/common/config.py:90 #, fuzzy msgid "$S (Not available as a result of being idle more than $T min)" msgstr "Dihegerz rak dizoberiant." #: gajim/common/config.py:90 msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" #: gajim/common/config.py:93 msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "Diskouez er _roll hepken" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "Diskouez er _roll hepken" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "Noti_fications d'état de discussion" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Goulenn treuzkas" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Nullet eo bet an treuzkas" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "P'eo echu un treuzkas, diskouez ur gemennadenn gelaouiñ difoupus" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "Pedadenn evit ur sal-flapiñ" #: gajim/common/config.py:106 msgid "Background color of status changed notification" msgstr "" #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "" #: gajim/common/config.py:109 #, fuzzy msgid "default" msgstr "Dilemel" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "Implij ur re */_ evel arouezioù neuziañ an destenn." #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "M'eo gwir, ne vo ket dilamet */_. Neuze e vo *abc* tev ma ne vez ket dilamet " "* *." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Ouzhpennañ * hag [n] da ditl ar roll darempredoù?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Niver a linennoù da vemoriñ diouzh ar gaozeadenn gent pa vez addigoret un " "ivinell pe ur prenestr." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" #: gajim/common/config.py:177 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" "Kas ar gemennadenn gant Ctrl+Kas ha mont d'al linenn gant Kas (emzalc'h dre-" "ziouer ar poellad ICQ Mirabilis)." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Niver a linennoù da zerc'hel soñj evit Ctrl+BirLaez" #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Pe un url personelaet gant %s ennañ, %s o vezañ ar ger-kuzh pe 'WIKTIONARY' " "hag a dalvez implij wiktionary." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "" "M'eo diuzet, e vo tu da sturiañ Gajim a-bell en ur implij gajim-remote." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Goulenn a-raok serriñ un ivinell pe ur prenestr." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" "Goulenn atav a-raok serriñ ar webgaozioù dispartiet gant un esaouenn ar roll-" "mañ." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" "Chom hep goulenn morse a-raok serriñ ar webgaozioù dispartiet gant un " "esaouenn er roll-mañ." #: gajim/common/config.py:196 msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" #: gajim/common/config.py:199 msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "Hervez ar standard IEC, KiB = 1024 byte, KB = 1000 byte." #: gajim/common/config.py:202 msgid "Notify of events in the notification area." msgstr "" #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Diskouez an ivinell pa 'z eus ur gaoz hepken?" #: gajim/common/config.py:210 #, fuzzy msgid "Show tabbed notebook border in chat windows?" msgstr "Diskouez an ivinell pa 'z eus ur gaoz hepken?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Diskouez an nozelenn-serriñ war an ivinell?" #: gajim/common/config.py:224 #, fuzzy msgid "Preview new messages in notification popup?" msgstr "Noti_fications d'état de discussion" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" #: gajim/common/config.py:228 msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" "Si cette case est cochée, Gajim affichera le message d'état, sous le nom de " "chaque contact dans la fenêtre principale et les salons" #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "" #: gajim/common/config.py:238 msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" #: gajim/common/config.py:239 msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "" #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "" #: gajim/common/config.py:245 msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" #: gajim/common/config.py:249 #, fuzzy msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" "A reolia ar prenestr a vez lakaet ar c'hemennadennoù nevez enni.\n" "'always' - An holl gaozioù en hevelep prenestr.\n" "'never' - An holl gaozioù e prenestroù disheñvel.\n" "'peracct' - An holl gaozioù en ur prenestr hervez ar gont.\n" "'pertype' - Bep a brenestr gant ur stumm flapiñ (webgaoz/flap)." #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 #, fuzzy msgid "If False, you will no longer see the avatar in the chat window." msgstr "M'eo faos, ne weloc'h ket an avatar er prenestr-flapiñ ken" #: gajim/common/config.py:252 #, fuzzy msgid "If true, pressing the escape key closes a tab/window." msgstr "" "M'eo gwir, klikit war an douchenn Echap evit serriñ un ivinell/prenestr" #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "A guzha an nozelennoù er prenestr flapiñ" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "" #: gajim/common/config.py:255 #, fuzzy msgid "Hides the group chat occupants list in group chat window." msgstr "A guzha roll ar berzhidi en ur prenestr webgaoz" #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "" #: gajim/common/config.py:258 msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "" #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "" #: gajim/common/config.py:260 msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" #: gajim/common/config.py:261 msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" #: gajim/common/config.py:262 msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" #: gajim/common/config.py:263 msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" #: gajim/common/config.py:264 msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" #: gajim/common/config.py:266 msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" #: gajim/common/config.py:269 msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "" #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" #: gajim/common/config.py:272 msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "" #: gajim/common/config.py:325 msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" #: gajim/common/config.py:326 #, fuzzy msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "M'eo faos, ne weloc'h ket an avatar er prenestr-flapiñ ken" #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "" #: gajim/common/config.py:337 msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "" #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "" #: gajim/common/config.py:354 msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "Si cette case est cochée, Gajim se connectera à ce salon au démarrage" #: gajim/common/config.py:386 #, fuzzy msgid "Allow Gajim to send your local time." msgstr "Fellout a ra da %s kas deoc'h ur restr." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Leuniit an titouroù diwar-benn an darempred da ouzhpennañ" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Implij an diskleriañ" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Implij an diskleriañ" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Implij an diskleriañ" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 msgid "Language for which misspelled words will be checked" msgstr "" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" #: gajim/common/config.py:442 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "O kousket" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Distro 'benn nebeut" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Distro 'vin a-benn un nebeut munutennoù.." #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "O tebriñ" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "O tebriñ 'maon, neuze laoskit ur gemennadenn." #: gajim/common/config.py:454 msgid "Movie" msgstr "Film" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "O sellout ouzh ur film 'maon." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "O labourat" #: gajim/common/config.py:455 msgid "I'm working." msgstr "O labourat 'maon." #: gajim/common/config.py:456 msgid "Phone" msgstr "Pellgomz" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Ouzh ar pellgomz emaon." #: gajim/common/config.py:457 msgid "Out" msgstr "Er-maez" #: gajim/common/config.py:457 #, fuzzy msgid "I'm out enjoying life." msgstr "Er-maez emaon o profitañ eus ar vuhez" #: gajim/common/config.py:468 #, fuzzy msgid "I'm available." msgstr "Hegerz" #: gajim/common/config.py:469 #, fuzzy msgid "I'm free for chat." msgstr "Prest da flapiñ" #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "Distro a-benn nebeut." #: gajim/common/config.py:471 #, fuzzy msgid "I'm not available." msgstr "Dihegerz" #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "" #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "" #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "Da" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Fazi: dibosupl eo digeriñ %s evit e lenn" #: gajim/common/const.py:205 #, fuzzy msgid "Doing Chores" msgstr "Ger-kuzh faos" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "" #: gajim/common/const.py:207 #, fuzzy msgid "Cleaning" msgstr "Darvoud" #: gajim/common/const.py:208 #, fuzzy msgid "Cooking" msgstr "O skrivañ" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "" #: gajim/common/const.py:212 #, fuzzy msgid "Gardening" msgstr "O labourat" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "" #: gajim/common/const.py:214 #, fuzzy msgid "Walking the Dog" msgstr "Er strollad" #: gajim/common/const.py:216 #, fuzzy msgid "Drinking" msgstr "O labourat" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "" #: gajim/common/const.py:227 msgid "Exercising" msgstr "" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "" #: gajim/common/const.py:229 #, fuzzy msgid "Dancing" msgstr "Darvoud" #: gajim/common/const.py:230 #, fuzzy msgid "Hiking" msgstr "Skarzhañ %s" #: gajim/common/const.py:231 #, fuzzy msgid "Jogging" msgstr "E_barzhiñ" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "" #: gajim/common/const.py:233 msgid "Running" msgstr "" #: gajim/common/const.py:234 #, fuzzy msgid "Skiing" msgstr "O labourat" #: gajim/common/const.py:235 msgid "Swimming" msgstr "" #: gajim/common/const.py:236 #, fuzzy msgid "Working out" msgstr "O labourat" #: gajim/common/const.py:238 msgid "Grooming" msgstr "" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "" #: gajim/common/const.py:242 #, fuzzy msgid "Shaving" msgstr "O tebriñ" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Dizoberiant" #: gajim/common/const.py:249 msgid "Day Off" msgstr "" #: gajim/common/const.py:250 #, fuzzy msgid "Hanging out" msgstr "Cheñch ar sujed" #: gajim/common/const.py:251 #, fuzzy msgid "Hiding" msgstr "Skarzhañ %s" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "" #: gajim/common/const.py:253 #, fuzzy msgid "Praying" msgstr "O tebriñ" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "" #: gajim/common/const.py:256 #, fuzzy msgid "Thinking" msgstr "O labourat" #: gajim/common/const.py:258 #, fuzzy msgid "Relaxing" msgstr "Standard" #: gajim/common/const.py:259 #, fuzzy msgid "Fishing" msgstr "Skarzhañ %s" #: gajim/common/const.py:260 #, fuzzy msgid "Gaming" msgstr "O tebriñ" #: gajim/common/const.py:261 #, fuzzy msgid "Going out" msgstr "_Dilugañ" #: gajim/common/const.py:262 #, fuzzy msgid "Partying" msgstr "O tebriñ" #: gajim/common/const.py:263 #, fuzzy msgid "Reading" msgstr "Abeg" #: gajim/common/const.py:264 #, fuzzy msgid "Rehearsing" msgstr "Abeg" #: gajim/common/const.py:265 #, fuzzy msgid "Shopping" msgstr "O kousket" #: gajim/common/const.py:266 #, fuzzy msgid "Smoking" msgstr "O labourat" #: gajim/common/const.py:267 msgid "Socializing" msgstr "" #: gajim/common/const.py:268 #, fuzzy msgid "Sunbathing" msgstr "O tebriñ" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "" #: gajim/common/const.py:270 #, fuzzy msgid "Watching a Movie" msgstr "O sellout ouzh ur film 'maon." #: gajim/common/const.py:272 #, fuzzy msgid "Talking" msgstr "O tebriñ" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "" #: gajim/common/const.py:274 #, fuzzy msgid "On the Phone" msgstr "Ouzh ar pellgomz emaon." #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "" #: gajim/common/const.py:277 #, fuzzy msgid "Traveling" msgstr "O treuzkas" #: gajim/common/const.py:278 #, fuzzy msgid "Commuting" msgstr "O skrivañ" #: gajim/common/const.py:280 msgid "Driving" msgstr "" #: gajim/common/const.py:281 msgid "In a Car" msgstr "" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "" #: gajim/common/const.py:283 msgid "On a Plane" msgstr "" #: gajim/common/const.py:284 msgid "On a Train" msgstr "" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "" #: gajim/common/const.py:286 #, fuzzy msgid "Walking" msgstr "O labourat" #: gajim/common/const.py:289 #, fuzzy msgid "Coding" msgstr "O skrivañ" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "" #: gajim/common/const.py:291 msgid "Studying" msgstr "" #: gajim/common/const.py:292 #, fuzzy msgid "Writing" msgstr "O labourat" #: gajim/common/const.py:295 msgid "Afraid" msgstr "" #: gajim/common/const.py:296 msgid "Amazed" msgstr "" #: gajim/common/const.py:297 msgid "Amorous" msgstr "" #: gajim/common/const.py:298 msgid "Angry" msgstr "" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "" #: gajim/common/const.py:300 msgid "Anxious" msgstr "" #: gajim/common/const.py:301 #, fuzzy msgid "Aroused" msgstr "Ehan" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "" #: gajim/common/const.py:303 #, fuzzy msgid "Bored" msgstr "Tev" #: gajim/common/const.py:304 msgid "Brave" msgstr "" #: gajim/common/const.py:305 msgid "Calm" msgstr "" #: gajim/common/const.py:306 #, fuzzy msgid "Cautious" msgstr "Flapoù" #: gajim/common/const.py:307 #, fuzzy msgid "Cold" msgstr "Tev" #: gajim/common/const.py:308 #, fuzzy msgid "Confident" msgstr "_Endalc'hadoù" #: gajim/common/const.py:309 msgid "Confused" msgstr "" #: gajim/common/const.py:310 #, fuzzy msgid "Contemplative" msgstr "Echu" #: gajim/common/const.py:311 #, fuzzy msgid "Contented" msgstr "_Endalc'hadoù" #: gajim/common/const.py:312 msgid "Cranky" msgstr "" #: gajim/common/const.py:313 msgid "Crazy" msgstr "" #: gajim/common/const.py:314 #, fuzzy msgid "Creative" msgstr "Dizoberiant" #: gajim/common/const.py:315 msgid "Curious" msgstr "" #: gajim/common/const.py:316 #, fuzzy msgid "Dejected" msgstr "Dilemel" #: gajim/common/const.py:317 msgid "Depressed" msgstr "" #: gajim/common/const.py:318 #, fuzzy msgid "Disappointed" msgstr "Dizoberiant" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "" #: gajim/common/const.py:320 #, fuzzy msgid "Dismayed" msgstr "Dizoberiant" #: gajim/common/const.py:321 #, fuzzy msgid "Distracted" msgstr "Dizoberiant" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "" #: gajim/common/const.py:323 msgid "Envious" msgstr "" #: gajim/common/const.py:324 msgid "Excited" msgstr "" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "" #: gajim/common/const.py:327 msgid "Grateful" msgstr "" #: gajim/common/const.py:328 msgid "Grieving" msgstr "" #: gajim/common/const.py:329 #, fuzzy msgid "Grumpy" msgstr "Strollad" #: gajim/common/const.py:330 msgid "Guilty" msgstr "" #: gajim/common/const.py:331 msgid "Happy" msgstr "" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "" #: gajim/common/const.py:333 #, fuzzy msgid "Hot" msgstr "_Ostiz:" #: gajim/common/const.py:334 msgid "Humbled" msgstr "" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "" #: gajim/common/const.py:336 msgid "Hungry" msgstr "" #: gajim/common/const.py:337 msgid "Hurt" msgstr "" #: gajim/common/const.py:338 #, fuzzy msgid "Impressed" msgstr "kemennadenn" #: gajim/common/const.py:339 msgid "In Awe" msgstr "" #: gajim/common/const.py:340 msgid "In Love" msgstr "" #: gajim/common/const.py:341 msgid "Indignant" msgstr "" #: gajim/common/const.py:342 msgid "Interested" msgstr "" #: gajim/common/const.py:343 msgid "Intoxicated" msgstr "" #: gajim/common/const.py:344 #, fuzzy msgid "Invincible" msgstr "Diwelus" #: gajim/common/const.py:345 msgid "Jealous" msgstr "" #: gajim/common/const.py:346 #, fuzzy msgid "Lonely" msgstr "Hini ebet" #: gajim/common/const.py:347 #, fuzzy msgid "Lost" msgstr "_Ostiz:" #: gajim/common/const.py:348 msgid "Lucky" msgstr "" #: gajim/common/const.py:349 #, fuzzy msgid "Mean" msgstr "Hollek" #: gajim/common/const.py:350 #, fuzzy msgid "Moody" msgstr "_Kemmañ" #: gajim/common/const.py:351 msgid "Nervous" msgstr "" #: gajim/common/const.py:352 msgid "Neutral" msgstr "" #: gajim/common/const.py:353 #, fuzzy msgid "Offended" msgstr "Ezlinenn" #: gajim/common/const.py:354 msgid "Outraged" msgstr "" #: gajim/common/const.py:355 msgid "Playful" msgstr "" #: gajim/common/const.py:356 #, fuzzy msgid "Proud" msgstr "Strollad" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "" #: gajim/common/const.py:358 #, fuzzy msgid "Relieved" msgstr "Dilemel" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "" #: gajim/common/const.py:360 msgid "Restless" msgstr "" #: gajim/common/const.py:361 msgid "Sad" msgstr "" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "" #: gajim/common/const.py:363 #, fuzzy msgid "Satisfied" msgstr "Anv:" #: gajim/common/const.py:364 msgid "Serious" msgstr "" #: gajim/common/const.py:365 msgid "Shocked" msgstr "" #: gajim/common/const.py:366 msgid "Shy" msgstr "" #: gajim/common/const.py:367 #, fuzzy msgid "Sick" msgstr "Lesanv" #: gajim/common/const.py:368 #, fuzzy msgid "Sleepy" msgstr "O kousket" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "" #: gajim/common/const.py:370 #, fuzzy msgid "Stressed" msgstr "Straed:" #: gajim/common/const.py:371 msgid "Strong" msgstr "" #: gajim/common/const.py:372 #, fuzzy msgid "Surprised" msgstr "Emezelañ" #: gajim/common/const.py:373 msgid "Thankful" msgstr "" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "" #: gajim/common/const.py:375 #, fuzzy msgid "Tired" msgstr "Mare" #: gajim/common/const.py:376 #, fuzzy msgid "Undefined" msgstr "Islinennañ" #: gajim/common/const.py:377 msgid "Weak" msgstr "" #: gajim/common/const.py:378 msgid "Worried" msgstr "" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "Dilemel" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "Glas-mor" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Skarzhañ %s" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "Bro:" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Kont" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Taolennadur" #: gajim/common/const.py:391 msgid "error" msgstr "" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "Hini ebet" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 #, fuzzy msgid "room" msgstr "Digant" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "" #: gajim/common/const.py:412 #, fuzzy msgid "Unable to decode issuer public key" msgstr "Impossible de rejoindre le salon" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "" #: gajim/common/const.py:430 #, fuzzy msgid "Invalid CA certificate" msgstr "Anv-arveriad-ez direizh" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Kollet eo bet al lugadenn gant ar gont \"%s\"" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "" #: gajim/common/connection.py:740 #, fuzzy, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "Respontet fall he deus an nor %s d'ar goulenn emezelañ." #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "" #: gajim/common/connection.py:1090 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Dibosupl eo en em lugañ da \"%s\"" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Dibosupl eo en em lugañ da \"%s\"" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Gwiriekait ho lugadenn pe klaskit diwezhatoc'h." #: gajim/common/connection.py:1100 #, fuzzy, python-format msgid "Server replied: %s" msgstr "Enrollet e-barzh: %s" #: gajim/common/connection.py:1115 #, fuzzy msgid "Connection to proxy failed" msgstr "Kevreadenn" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, fuzzy, python-format msgid "Could not connect to account %s" msgstr "Dibosupl eo en em lugañ da \"%s\"" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, fuzzy, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "Kollet eo bet al lugadenn gant ar gont \"%s\"" #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Dibosupl eo en em lugañ da \"%s\"" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "C'hwitet an diskleriadenn gant \"%s\"" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Gwiriekait ho ker-kuzh hag anv-lugañ." # Traduction moins mauvaise mais pas terrible: binding=lier, attacher #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "" "N'eus ket eus D-Bus war an urzhiataer-mañ, pe mankout a ra ur mollad python" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "" "N'eus ket eus D-Bus war an urzhiataer-mañ, pe mankout a ra ur mollad python" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Titour-stad" #: gajim/common/multimedia_helpers.py:70 msgid "Audio test" msgstr "" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Ment: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Restr: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "Glas" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, fuzzy, python-format msgid "%s configuration error" msgstr "Kefluniañ ar webgaoz" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Arouezenn zireizh en anv-ostiz." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Chomlec'h ar servijer dre ret" #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Arouezenn ziereizh en anv-arveriad-ez" #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "" #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "D_ihegerz" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "_Prest da flapiñ" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "_Hegerz" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "O lugañ" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "E_zvezant" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "_Ezlinenn" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "_Diwelus" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "Dianav" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "fazi" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "Hini ebet" #: gajim/common/helpers.py:315 msgid "To" msgstr "Da" #: gajim/common/helpers.py:317 msgid "From" msgstr "Digant" #: gajim/common/helpers.py:319 msgid "Both" msgstr "An daou" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "Dianav" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "Hini ebet" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Emezelañ" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "Hini ebet" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Kasourien" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Kasour-ez" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Perzhidi" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Perzhiad-ez" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Gweladennerien" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Gweladenner-ez" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "a zo aketus d'ar gaozeadenn" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "a ra un dra bennak all" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "a skriv ur gemennadenn..." #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "a zo paouezet da skrivañ ar gemennadenn" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "he/en deus serret ar prenestr-flapiñ pe an ivinell" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s Go" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s Go" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s Mo" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s Mo" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s Ko" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s Ko" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s o" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, fuzzy, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "Kas ur gemennadenn" msgstr[1] "Kas ur gemennadenn" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr "De %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, fuzzy, python-format msgid "from user %s" msgstr "De %s" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr "De %s" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "" msgstr[1] "" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Me blijfe din ouzhpennañ ac'hanoc'h em roll-darempredoù." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 #, fuzzy msgid "Timeout loading image" msgstr "Dibosupl eo kargañ ar skeudenn" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "L'image est trop grande" #: gajim/common/helpers.py:1383 msgid "PyCURL is not installed" msgstr "" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Dibosupl eo kargañ ar skeudenn" #: gajim/common/configpaths.py:85 #, fuzzy, python-format msgid "%s is a file but it should be a directory" msgstr "ur restr eo %s met rankout a rafe bezañ ur renkell" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Emañ Gajim o vont da guitaat diouzhtu" #: gajim/common/exceptions.py:45 #, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" "Servij dihegerz: n'eo ket loc'het Gajim, pe lakaet eo bet remote_control war " "False" #: gajim/common/exceptions.py:81 #, fuzzy, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "Le bus de session n'est pas disponible" #: gajim/common/exceptions.py:93 #, fuzzy, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" "Dihegerz eo bus an estez.\n" "Klaskit o lenn http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 msgid "Please check if Avahi or Bonjour is installed." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 #, fuzzy msgid "Could not start local service" msgstr "Dibosupl eo kargañ ar skeudenn" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, fuzzy, python-format msgid "Unable to bind to port %d." msgstr "Impossible de rejoindre le salon" #: gajim/common/zeroconf/connection_zeroconf.py:217 msgid "Please check if avahi/bonjour-daemon is running." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, fuzzy, python-format msgid "Could not change status of account \"%s\"" msgstr "Dibosupl eo en em lugañ da \"%s\"" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:349 #, fuzzy msgid "Your message could not be sent." msgstr "N'eus ket tu da gas ho kemennadenn keit ha ma n'oc'h ket luget." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "" #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, fuzzy, python-format msgid "Error while adding service. %s" msgstr "fazi en ur gas %s ( %s )" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "kemennadenn" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "Laouen 'vefen d'ho ouzhpennañ em roll-darempredoù." #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Fazi en ur lenn ar restr:" #: gajim/common/modules/httpupload.py:134 #, fuzzy msgid "File is empty" msgstr "Treug ar restr" #: gajim/common/modules/httpupload.py:137 #, fuzzy msgid "File does not exist" msgstr "Ce salon n'existe pas." #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 #, fuzzy msgid "Change status information" msgstr "Titouroù" #: gajim/common/modules/adhoc_commands.py:113 #, fuzzy msgid "Change status" msgstr "Darempred diluget" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "" #: gajim/common/modules/adhoc_commands.py:121 #, fuzzy msgid "Free for chat" msgstr "Prest da flapiñ" #: gajim/common/modules/adhoc_commands.py:122 #, fuzzy msgid "Online" msgstr "_Kenderc'hel" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "" #: gajim/common/modules/adhoc_commands.py:132 #, fuzzy msgid "Presence description:" msgstr "Taolennadur" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "" #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 #, fuzzy msgid "Leave Groupchats" msgstr "Flap a-stroll" #: gajim/common/modules/adhoc_commands.py:231 #, fuzzy, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s : %(message)s" #: gajim/common/modules/adhoc_commands.py:235 #, fuzzy msgid "You have not joined a groupchat." msgstr "Er strollad" #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "" #: gajim/common/modules/adhoc_commands.py:292 #, fuzzy msgid "You left the following groupchats:" msgstr "Emaoc'h er webgaoz %s dija" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" #: gajim/common/modules/roster_item_exchange.py:100 #, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "" #: gajim/common/modules/roster_item_exchange.py:104 #, fuzzy msgid "Sent contacts:" msgstr "Darempredoù" #: gajim/data/gui/blocked_contacts_window.ui:13 #, fuzzy msgid "Blocked Contacts" msgstr "Darempredoù" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Aozer kefluniañ dre ar munut" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Sil:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Taolennadur" #: gajim/data/gui/advanced_configuration_window.ui:136 #, fuzzy msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "" "NOTENN : Dav eo deoc'h adloc'hañ Gajim evit ma vo efedus kemmoù 'zo" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "_Distreiñ gant al livioù dre-ziouer" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "E_barzhiñ" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Kont" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Webgaoz:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Ger-kuzh:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "_Ouzhpennañ ar webgaoz d'ar sinedoù" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "_Ouzhpennañ ar webgaoz d'ar sinedoù" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "Ebarzhiñ ur _webgaoz" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 #, fuzzy msgid "HTTP Connect" msgstr "Kevreadenn HTTP" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Merañ an aeladoù proksi" #: gajim/data/gui/manage_proxies_window.ui:148 #, fuzzy msgid "_Name:" msgstr "_Anv:" #: gajim/data/gui/manage_proxies_window.ui:161 #, fuzzy msgid "_Type:" msgstr "Doare:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Perzhioù" #: gajim/data/gui/manage_proxies_window.ui:234 #, fuzzy msgid "_BOSH URL:" msgstr "_URL :" #: gajim/data/gui/manage_proxies_window.ui:258 #, fuzzy msgid "Proxy _Host:" msgstr "Proksi:" #: gajim/data/gui/manage_proxies_window.ui:269 #, fuzzy msgid "Use HTTP prox_y" msgstr "_Implij ur proxy" #: gajim/data/gui/manage_proxies_window.ui:288 #, fuzzy msgid "Proxy _Port:" msgstr "_Porzh:" #: gajim/data/gui/manage_proxies_window.ui:299 #, fuzzy msgid "Use proxy auth_entication" msgstr "Implij an diskleriañ" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "_Anv:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "_Ger-kuzh:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Dibarzhioù" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Enrollañ ar ger-kuzh" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Cheñch ar ger-kuzh" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Titouroù" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Stad:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Istoradur flapiñ" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 #, fuzzy msgid "Contact" msgstr "Darempredoù" #: gajim/data/gui/zeroconf_information_window.ui:234 #, fuzzy msgid "First Name:" msgstr "Anv:" #: gajim/data/gui/zeroconf_information_window.ui:247 #, fuzzy msgid "Last Name:" msgstr "Anv:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "ID Jabber:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "Postel:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 #, fuzzy msgid "Personal" msgstr "Titouroù hiniennel" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "_Kas ur gemennadenn brevez" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Kas ur _restr" #: gajim/data/gui/gc_occupants_menu.ui:29 #, fuzzy msgid "Occupant Actions" msgstr "_Galloudoù an darempred" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Ka_sour-ez" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Ezel" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Merour-ez" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "_Perc'hener-ez" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "_Ermaeziañ" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Argas" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "_Ouzhpennañ er roll" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "urzhiad" #: gajim/data/gui/tooltip_roster_contact.ui:125 #, fuzzy msgid "Idle since:" msgstr "dibaoe %s" #: gajim/data/gui/tooltip_roster_contact.ui:151 #, fuzzy msgid "Mood:" msgstr "Webgaoz:" #: gajim/data/gui/tooltip_roster_contact.ui:164 #, fuzzy msgid "Activity:" msgstr "Oberiant" #: gajim/data/gui/tooltip_roster_contact.ui:178 #, fuzzy msgid "Tune:" msgstr "Doare:" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Kemmañ ar gont" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP : " #: gajim/data/gui/tooltip_roster_contact.ui:281 msgid "Subscription:" msgstr "Koumanant:" #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "_Stad" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Kemmañ ar gont..." #: gajim/data/gui/atom_entry_window.ui:8 #, fuzzy msgid "New entry received" msgstr "Pa resever un darvoud nevez" #: gajim/data/gui/atom_entry_window.ui:92 #, fuzzy msgid "Feed name:" msgstr "anv ar gwiskadur" #: gajim/data/gui/atom_entry_window.ui:119 #, fuzzy msgid "Entry:" msgstr "Bro:" #: gajim/data/gui/atom_entry_window.ui:131 #, fuzzy msgid "Last modified:" msgstr "Anv:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 #, fuzzy msgid "Change _Nickname..." msgstr "Cheñch _lesanv" #: gajim/data/gui/gc_control_popup_menu.ui:20 #, fuzzy msgid "_Manage Room" msgstr "Merañ ar sinedoù" #: gajim/data/gui/gc_control_popup_menu.ui:31 #, fuzzy msgid "Change _Subject..." msgstr "Kemmañ ar _sujed" #: gajim/data/gui/gc_control_popup_menu.ui:38 #, fuzzy msgid "Configure _Room..." msgstr "Ke_fluniañ ar flap" #: gajim/data/gui/gc_control_popup_menu.ui:52 #, fuzzy msgid "_Destroy Room" msgstr "Taolennadur: %s" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:85 msgid "_Request Voice" msgstr "" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "Choisissez un Avatar" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Dibabit ur skeudenn" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 #, fuzzy msgid "Full Name" msgstr "Personelaet" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Pellgomz" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Stumm : BBBB-MM-DD" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 #, fuzzy msgid "Birthday" msgstr "Deiz-ha-bloaz:" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Lec'hienn hiniennel:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "Postel:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 #, fuzzy msgid "Jabber ID" msgstr "ID Jabber:" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 #, fuzzy msgid "Family" msgstr "Familh:" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 #, fuzzy msgid "Given" msgstr "Anv bihan:" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Eil anv bihan:" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Rakger:" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Lostger:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Straed:" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "Chomlec'h 2:" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 #, fuzzy msgid "City" msgstr "Kêr:" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Stad:" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 #, fuzzy msgid "Postal Code" msgstr "Kod postel:" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "Bro:" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 #, fuzzy msgid "Address" msgstr "Furmad ul linenn" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Personelaet" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Embregerezh:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 #, fuzzy msgid "Department" msgstr "Departamant:" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Plas:" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Dibarzhioù" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Labour" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Diwar-benn" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "_Kenderc'hel" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Ehan" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Nullañ" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Digeriñ ar renkell pal" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Treuzkasoù" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "roll an treuzkasadoù" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "Ur roll eus an treuzkasoù oberiant, echu pe arsavet" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "_Naetaat" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "Diverkañ an treuzkasadoù echu, nullaet pe sac'het" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Dilemel an treuzkas restroù diwar ar roll" #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "An ober-mañ a zilam an treuzkasoù diouzh ar roll. Ma 'z eus un treuzkas " "oberiant, e vo arsavet anezhañ ha dilamet da c'houde" #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "A nulla an treuzkas dibabet hag a zilam ar restr diglok" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Nullañ an treuzkas" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "A nulla an treuzkas dibabet" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "_Kas & Serriñ" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "A guzha ar prenestr" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Kelaouiñ ac'hanon p'eo echu un treuzkas" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "P'eo echu un treuzkas, diskouez ur gemennadenn gelaouiñ difoupus" #: gajim/data/gui/filetransfers.ui:229 #, fuzzy msgid "Shows a list of file transfers between you and others" msgstr "A ziskouez ur roll eus an dreuzkasoù etrezoc'h hag ar re all" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Tev" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Stouet" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 #, fuzzy msgid "Underline" msgstr "Islinennañ" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 #, fuzzy msgid "Strike" msgstr "Lesanv" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 #, fuzzy msgid "Font" msgstr "_Nodrezh:" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Titouroù" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Dibabit ur restr da gas..." #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Klikit evit enlakaat ur boulomell (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Darvoud" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Darvoudoù" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Sonioù" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Ezvezant" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "Diskouez ar _roll-darempredoù" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "_Morse" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "Dilemel" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "Treug ar restr" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Une erreur de protocole s'est produite :" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Stad" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Poellad:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 #, fuzzy msgid "System" msgstr "Personelaet" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Anv an darempred" #: gajim/data/gui/vcard_information_window.ui:240 #, fuzzy msgid "User avatar" msgstr "Dibab ur _skeudenn" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Ke_fluniañ ar flap" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 #, fuzzy msgid "Ask" msgstr "Goulenn:" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Koumanant:" #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 #, fuzzy msgid "Personal Info" msgstr "Titouroù hiniennel" #: gajim/data/gui/vcard_information_window.ui:1515 #, fuzzy msgid "Comments" msgstr "Evezhiadenn: %s" #: gajim/data/gui/preferences_window.ui:38 msgid "Use default applications" msgstr "" #: gajim/data/gui/preferences_window.ui:41 #, fuzzy msgid "Custom" msgstr "Personelaet" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Stad:" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 #, fuzzy msgid "Composing only" msgstr "O skrivañ" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Dizoberiant" #: gajim/data/gui/preferences_window.ui:89 msgid "Only when pending events" msgstr "" #: gajim/data/gui/preferences_window.ui:103 #, fuzzy msgid "Pop it up" msgstr "Di_foupañ" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "_Kelaouiñ ac'hanon" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "Diskouez er _roll hepken" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 #, fuzzy msgid "Last state" msgstr "Stad diwezhañ: %s" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "Diskouez _skeudennigoù an darempredoù er roll" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Si cette case est cochée, Gajim affichera l'avatar de chaque contact dans la " "fenêtre principale et les salons" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "Diskouez titouroù-stad an darempredoù e-barzh ar roll" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Si cette case est cochée, Gajim affichera le message d'état, sous le nom de " "chaque contact dans la fenêtre principale et les salons" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Diskouez _skeudennigoù an darempredoù er roll" #: gajim/data/gui/preferences_window.ui:254 #, fuzzy msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "" "Si cette case est cochée, Gajim affichera l'avatar de chaque contact dans la " "fenêtre principale et les salons" #: gajim/data/gui/preferences_window.ui:275 #, fuzzy msgid "Sort contacts by status" msgstr "_Urzhiañ an darempredoù hervez o stad" #: gajim/data/gui/preferences_window.ui:285 #, fuzzy msgid "in _roster" msgstr "Ket er roll" #: gajim/data/gui/preferences_window.ui:302 #, fuzzy msgid "in _group chats" msgstr "Ebarzhiñ ur _webgaoz" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "" #: gajim/data/gui/preferences_window.ui:359 msgid "Spell _checker" msgstr "" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "korf ar gemennadenn" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 msgid "_Window behavior" msgstr "" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "Diskouez ar _roll-darempredoù" #: gajim/data/gui/preferences_window.ui:484 msgid "_Ignore rich content in incoming messages" msgstr "" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Impossible de rejoindre le salon" #: gajim/data/gui/preferences_window.ui:523 #, fuzzy msgid "Chat Appearance" msgstr "Furmad ul linenn" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "Pa resever un darvoud nevez" #: gajim/data/gui/preferences_window.ui:623 #, fuzzy msgid "Notify me about contacts that sign _in" msgstr "Ma c'helaouiñ pa c'hoarvez gant un darempred:" #: gajim/data/gui/preferences_window.ui:641 #, fuzzy msgid "Notify me about contacts that sign _out" msgstr "Ma c'helaouiñ pa c'hoarvez gant un darempred:" #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Gajim vous signalera par une fenêtre de notification en bas à droite de " "l'écran qu'un contact s'est déconnecté" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "Aotren ar c'helaouennoù p'emaon _ezvezant/dihegerz/busy/diwelus" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "Aotren ar c'helaouennoù p'emaon _ezvezant/dihegerz/busy/diwelus" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "_Implij an arlun-gelaouiñ (trayicon)" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Kelaouennoù dre welet" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "_Seniñ" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "Me_rañ..." #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Sonioù" #: gajim/data/gui/preferences_window.ui:861 #, fuzzy msgid "Notifications" msgstr "Kemmañ ar gont" #: gajim/data/gui/preferences_window.ui:898 #, fuzzy msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "Gajim peut envoyer et recevoir des meta-informations concernant les " "conversations que vous pouvez avoir avec un contact. Vous pouvez ici " "spécifier quel état de conversation vous voulez envoyer à vos contacts" #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "Titou_roù-stad ar flap:" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim peut envoyer et recevoir des meta-informations concernant les " "conversations que vous pouvez avoir avec un contact. Vous pouvez ici " "spécifier quel état de conversation vous voulez envoyer à vos contacts" #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "Titou_roù-stad ar flap:" #: gajim/data/gui/preferences_window.ui:987 #, fuzzy msgid "Chat state notifications" msgstr "Kelaouennoù dre welet" #: gajim/data/gui/preferences_window.ui:1009 #, fuzzy msgid "Personal Events" msgstr "Titouroù hiniennel" #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "Bezañ lakaet da _ezvezant war-lerc'h:" #: gajim/data/gui/preferences_window.ui:1047 #, fuzzy msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" "Si cette case est cochée, Gajim placera une icône dans la zone de " "notification" #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "Bezañ lakaet evel _dihegerz war-lerc'h:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "munutenn" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1166 #, fuzzy msgid "Auto Status" msgstr "Poelladoù" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Goulenn an titour-stad pa:" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "_Lugañ" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "_Dilugañ" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" #: gajim/data/gui/preferences_window.ui:1291 #, fuzzy msgid "Default Message" msgstr "Titour-stad" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 #, fuzzy msgid "Enabled" msgstr "Enaouiñ" #: gajim/data/gui/preferences_window.ui:1332 #, fuzzy msgid "Status Messages" msgstr "Titouroù-stad raklakaet" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Titouroù-stad raklakaet" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Gwiskadur" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Gwiskadur" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "_Arlunioù-stad dre-ziouer:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Implij arlunioù an _dorioù" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Si cette case est cochée, Gajim utilisera des icônes d'état spécifiques aux " "protocoles. (Par ex. un contact MSN aura les icônes de MSN pour les états " "disponible, absent, occupé, etc)" #: gajim/data/gui/preferences_window.ui:1724 #, fuzzy msgid "_Convert ASCII Emojis" msgstr "Gérer les frimousses" #: gajim/data/gui/preferences_window.ui:1808 msgid "Style" msgstr "" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Poelladoù" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Furmad ul linenn" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Servijer:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Sonioù" #: gajim/data/gui/preferences_window.ui:2159 msgid "Audio/Video" msgstr "" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "_Meziant posteliñ:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "_Furcher web:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "Merour _restroù:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Personelaet" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Poelladoù" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "_Chom hep teurel pled eus ar c'hemennadennoù kaset gant tud dianav" #: gajim/data/gui/preferences_window.ui:2363 #, fuzzy msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Cochez cette option seulement si quelqu'un n'appartenant pas à votre liste " "vous spamme/ennuie. Utilisez la avec précaution, car elle bloque tous les " "messages des contacts qui ne sont pas dans votre liste" #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Aotren e vefe kaset titouroù diwar-benn an _OS" #: gajim/data/gui/preferences_window.ui:2381 #, fuzzy msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "Si cette case est cochée, Gajim se connectera à ce salon au démarrage" #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Aotren e vefe kaset titouroù diwar-benn an _OS" #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "Si cette case est cochée, Gajim se connectera à ce salon au démarrage" #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Aotren e vefe kaset titouroù diwar-benn an _OS" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 #, fuzzy msgid "_Manage..." msgstr "Kemmañ..." #: gajim/data/gui/preferences_window.ui:2500 #, fuzzy msgid "Privacy" msgstr "Perzhioù" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "_Menegiñ kemmoù stad an darempredoù e-barzh an istoradur" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "A bep seurt" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "_Digeriñ..." #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Aozer kefluniañ munut" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Kregiñ da _flapiñ" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Kas ur gemennadenn _simpl..." #: gajim/data/gui/contact_context_menu.ui:28 #, fuzzy msgid "Send _File..." msgstr "Kas ur _restr" #: gajim/data/gui/contact_context_menu.ui:44 #, fuzzy msgid "Invite _Contacts" msgstr "Darempredoù" #: gajim/data/gui/contact_context_menu.ui:73 #, fuzzy msgid "E_xecute Command..." msgstr "urzhiad" #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "Darempredoù" #: gajim/data/gui/contact_context_menu.ui:92 #, fuzzy msgid "_Rename..." msgstr "_Adenvel" #: gajim/data/gui/contact_context_menu.ui:99 #, fuzzy msgid "Edit _Groups..." msgstr "Kemmañ ar _strolladoù" #: gajim/data/gui/contact_context_menu.ui:106 #, fuzzy msgid "Assign Open_PGP Key..." msgstr "Assigner une clé OpenPGP" #: gajim/data/gui/contact_context_menu.ui:115 #, fuzzy msgid "Add Special _Notification..." msgstr "Ouzhpennañ ur gelaouenn _ispisial" #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Koumanant" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "He/E aotren da welet ma stad" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "Goulenn evit gwelet e/he stad" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "Difenn dezhañ/dezhi gwelet ma stad" #: gajim/data/gui/contact_context_menu.ui:182 #, fuzzy msgid "_Unignore" msgstr "_Kenderc'hel" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "" #: gajim/data/gui/contact_context_menu.ui:197 #, fuzzy msgid "_Add to Roster..." msgstr "_Ouzhpennañ er roll" #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim : Assistant de création de compte" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Rankout a rit kaout ur gont evit en em lugañ\n" "d'ar rouedad Jabber." #: gajim/data/gui/account_creation_wizard_window.ui:95 #, fuzzy msgid "I already have an account I want to _use" msgstr "Bez em eus ur gont a fell din implij" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "Fellout a ra din emezelañ evit krouiñ ur gont" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Diuzit unan eus an dibaboù dindan :" #: gajim/data/gui/account_creation_wizard_window.ui:167 #, fuzzy msgid "Please fill in the data for your existing account" msgstr "Leuniit an titouroù evit ho kont nevez" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "ID _Jabber:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 #, fuzzy msgid "Anon_ymous authentication" msgstr "Implij an diskleriañ" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Ger-kuzh:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Enrollañ ar _ger-kuzh" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "" "Si cette case est cochée, Gajim va retenir le mot de passe pour ce compte" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Servijer:" #: gajim/data/gui/account_creation_wizard_window.ui:423 #, fuzzy msgid "Prox_y:" msgstr "Proksi:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Kemmañ..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Implij un anv ostiz/porzh personelaet" #: gajim/data/gui/account_creation_wizard_window.ui:491 #, fuzzy msgid "_Hostname:" msgstr "Servijer:" #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Porzh:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "_Mont pelloc'h" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:687 #, fuzzy msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "O krouiñ ar gont\n" "\n" "Gortozit marplij..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Kevreañ pa bouezan war Echuiñ" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Aozañ ma aelad pa lugan" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Echuiñ" #: gajim/data/gui/privacy_lists_window.ui:34 #, fuzzy msgid "Privacy Lists:" msgstr "Flapoù prevez" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Chomlec'h:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "_Mont" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 #, fuzzy msgid "Select the contacts you want to synchronise" msgstr "JID an darempred ho peus c'hoant flapiñ gantañ" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Kemmañ ar strolladoù" #: gajim/data/gui/search_window.ui:42 #, fuzzy msgid "Please wait while retrieving search form..." msgstr "Gortozit marplij e keit ma vez dilec'hiet an istoradur..." #: gajim/data/gui/search_window.ui:80 #, fuzzy msgid "_Add contact" msgstr "Ouzhpennañ un _darempred" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "_Klask" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Kemennadennoù raklakaet:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Oberiant" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Roit un titour-stad nevez" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 #, fuzzy msgid "Synchronise contacts" msgstr "Diskouez an darempredoù _ezlinenn" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "ID _Jabber:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "Lesanv:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "Strollad:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "Kont" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "Protokol:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "He/E aotren da welet ma stad" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "_Koumanant" #: gajim/data/gui/add_new_contact_window.ui:367 msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" #: gajim/data/gui/add_new_contact_window.ui:382 #, fuzzy msgid "_Register" msgstr "_Emezelañ" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "_Kemmañ an titour-stad" #: gajim/data/gui/change_mood_dialog.ui:73 #, fuzzy msgid "Mood:" msgstr "Sonioù" #: gajim/data/gui/change_mood_dialog.ui:85 #, fuzzy msgid "Message:" msgstr "Titouroù-stad raklakaet" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 msgid "Uninstall Plugin" msgstr "" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "échec lors de la publication de votre vCard" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "échec lors de la publication de votre vCard" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Taolennadur" #: gajim/data/gui/plugins_window.ui:258 msgid "Version" msgstr "" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "_Aotren" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 msgid "Installed" msgstr "" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "Hini ebet" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "An daou" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "Digant" #: gajim/data/gui/privacy_list_window.ui:27 #, fuzzy msgid "to" msgstr "piv" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 #, fuzzy msgid "Privacy List" msgstr "Roll argas" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "" #: gajim/data/gui/privacy_list_window.ui:94 #, fuzzy msgid "Active on each startup" msgstr "K_evreañ en ur loc'hañ Gajim" #: gajim/data/gui/privacy_list_window.ui:132 #, fuzzy msgid "List of rules" msgstr "Furmad ul linenn" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Nac'hañ" #: gajim/data/gui/privacy_list_window.ui:317 #, fuzzy msgid "JabberID" msgstr "ID Jabber:" #: gajim/data/gui/privacy_list_window.ui:358 #, fuzzy msgid "all in the group" msgstr "Er strollad" #: gajim/data/gui/privacy_list_window.ui:407 #, fuzzy msgid "all by subscription" msgstr "_Koumanant" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "" #: gajim/data/gui/privacy_list_window.ui:493 #, fuzzy msgid "to send me messages" msgstr "Kas ur gemennadenn" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "" #: gajim/data/gui/privacy_list_window.ui:525 #, fuzzy msgid "to view my status" msgstr "He/E aotren da welet ma stad" #: gajim/data/gui/privacy_list_window.ui:541 #, fuzzy msgid "to send me status" msgstr "Goulenn evit gwelet e/he stad" #: gajim/data/gui/privacy_list_window.ui:557 #, fuzzy msgid "All (including subscription)" msgstr "_Koumanant" #: gajim/data/gui/privacy_list_window.ui:598 #, fuzzy msgid "Order:" msgstr "Servijer:" #: gajim/data/gui/manage_sounds_window.ui:23 #, fuzzy msgid "Manage sounds" msgstr "Merañ ar c'hontoù" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Oberiant" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Darvoud" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Dibabit ur son" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Dilemel ar gont diwar Gajim _hepken" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Dilemel ar gont diwar Gajim ha diwar ar _servijer" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "Petra 'fell deoc'h ober ?" #: gajim/data/gui/adhoc_commands_window.ui:35 #, fuzzy msgid "Please wait while retrieving command list..." msgstr "Gortozit marplij e keit ma vez dilec'hiet an istoradur..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Gortozit marplij e keit ma vez dilec'hiet an istoradur..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "" #: gajim/data/gui/adhoc_commands_window.ui:233 #, fuzzy msgid "An error has occurred:" msgstr "Une erreur de protocole s'est produite :" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Echuiñ" #: gajim/data/gui/account_context_menu.ui:20 #, fuzzy msgid "_Personal Events" msgstr "Titouroù hiniennel" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "Ebarzhiñ ur _webgaoz" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Ouzhpennañ un darempred..." #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Dizoleiñ ar servijoù" #: gajim/data/gui/account_context_menu.ui:65 #, fuzzy msgid "_Execute Command..." msgstr "urzhiad" #: gajim/data/gui/application_menu.ui:8 msgid "View" msgstr "" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Diskouez ar _roll-darempredoù" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Diskouez an darempredoù _ezlinenn" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Diskouez an darempredoù _ezlinenn" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Dorioù" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Skoazell" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Endalc'hadoù" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_FAQ" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 #, fuzzy msgid "Features" msgstr "Perzhioù ar servijerien" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "_Ouzhpennañ ar webgaoz d'ar sinedoù" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Penndibaboù" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Kuitaat" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Nullañ" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "Flap a-stroll" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "_Ouzhpennañ ar webgaoz d'ar sinedoù" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Servijer:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Ger-kuzh:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Darempred diluget" #: gajim/data/gui/manage_bookmarks_window.ui:342 msgid "Minimize on Auto Join" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Kas ar gemennadenn ha serriñ ar prenestr" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Titour-stad" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Taolennadur: %s" #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Darvoud" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 msgid "Send" msgstr "Envoyer" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Restr:" #: gajim/data/gui/exception_dialog.ui:45 msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Diskleriañ ar Bug" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Kregiñ da flapiñ" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "_Nac'hañ" #: gajim/data/gui/subscription_request_window.ui:100 #, fuzzy msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" "Nac'hañ aotre an darempred evit ma ne welo ket hag eñ oc'h kevreet pe get" #: gajim/data/gui/subscription_request_window.ui:133 #, fuzzy msgid "Au_thorize" msgstr "_Aotren" #: gajim/data/gui/subscription_request_window.ui:138 #, fuzzy msgid "Authorize contact so he or she can know when you're connected" msgstr "Aotren an darempred da welet hag emaon kevreet pe get" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "_Bezañs" #: gajim/data/gui/emoji_chooser.ui:98 msgid "No Results Found" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "JID an darempred ho peus c'hoant flapiñ gantañ" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:141 #, fuzzy msgid "MUC server" msgstr "Sellerien" #: gajim/data/gui/chat_to_muc_window.ui:176 #, fuzzy msgid "In_vite" msgstr "Diwelus" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Ezporzhiañ" #: gajim/data/gui/history_manager.ui:93 #, fuzzy msgid "Welcome to Gajim History Logs Manager" msgstr "Merour istoradur Gajim" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Klask en titourva" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "korf ar gemennadenn" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Kas ur gemennadenn" #: gajim/data/gui/shortcuts_window.ui:24 msgid "Add new line" msgstr "" #: gajim/data/gui/shortcuts_window.ui:31 #, fuzzy msgid "Select an emoji" msgstr "Utiliser les _frimousses" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Kemennadennoù raklakaet:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Kemennadennoù raklakaet:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "Ou choisissez votre message :" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Kas ur gemennadenn" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Kemennadenn gaset" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Nevez 'zo:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Darvoud" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Treuzkasoù" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "Ebarzhiñ ur _webgaoz" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "titour stad" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 #, fuzzy msgid "Appearance" msgstr "Furmad ul linenn" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Diskouez an darempredoù _ezlinenn" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Diskouez an darempredoù _ezlinenn" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Darempredoù" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Titouroù" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Darempredoù" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Darempredoù" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Ger-kuzh" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "_Menegiñ kemmoù stad an darempredoù e-barzh an istoradur" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Kasour-ez" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Nevez 'zo:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Istoradur ar gaoz" #: gajim/data/gui/history_window.ui:315 msgid "Chat" msgstr "Flap" #: gajim/data/gui/history_window.ui:329 msgid "Record history for this chat" msgstr "" #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Nevez 'zo:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Titl:" #: gajim/data/gui/manage_pep_services_window.ui:13 #, fuzzy msgid "PEP Service Configuration" msgstr "Kefluniañ ar webgaoz" #: gajim/data/gui/manage_pep_services_window.ui:69 #, fuzzy msgid "_Configure" msgstr "_Kenderc'hel" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "Digant:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Titl:" #: gajim/data/gui/data_form_window.ui:19 #, fuzzy msgid "Fill in the form." msgstr "Er strollad" #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Kefluniañ ar webgaoz" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_Mat eo" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "S_tad" #: gajim/data/gui/systray_context_menu.ui:20 #, fuzzy msgid "_Start Chat..." msgstr "_Kregiñ da flapiñ" #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Diskouez an holl _zarvoudoù o c'hortoz" #: gajim/data/gui/systray_context_menu.ui:59 #, fuzzy msgid "Mute Sounds" msgstr "Sonioù wav" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Penndibaboù" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Kuitaat" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Da:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "_Kas" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Kas ur gemennadenn" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Respont" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Respont d'ar gemennadenn-mañ" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "_Kas & Serriñ" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Kas ar gemennadenn ha serriñ ar prenestr" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:337 #, fuzzy msgid "Message: " msgstr "Titouroù-stad raklakaet" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Kemennadenn gaset" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Kemennadenn gaset" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 #, fuzzy msgid "Send a message to the contact" msgstr "Usage: /%s, cache les boutons de discussion." #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "N'eo ket bet kavet %s" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "Dihegerz" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 #, fuzzy msgid "Clear the text window" msgstr "Usage : /%s, nettoie la fenêtre." #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Usage : /%s, passe la fenêtre de salon de discussion en vue compacte." #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 msgid "Command is not supported for zeroconf accounts" msgstr "" #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 #, fuzzy msgid "No open audio sessions with the contact" msgstr "Klikit amañ evit gwelout kaozioù kent gant an darempred-mañ" #: gajim/command_system/implementation/standard.py:191 #, python-format msgid "%s is not a valid tone" msgstr "" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "N'eus ket tu da gevreañ" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "N'eus ket tu en em lugañ" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Usage: /%s, cache les boutons de discussion." #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Cheñch _lesanv" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 #, fuzzy msgid "Invalid nickname" msgstr "Anv-arveriad-ez direizh" #: gajim/command_system/implementation/standard.py:267 #, fuzzy msgid "Open a private chat window with a specified occupant" msgstr "" "Usage : /%s , ouvre une fenêtre de discussion privée avec l'occupant " "spécifié." #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 #, fuzzy msgid "Nickname not found" msgstr "N'eus ket bet kavet al lesanv : %s" #: gajim/command_system/implementation/standard.py:276 #, fuzzy msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" "Usage : /%s , ouvre une fenêtre de discussion privée avec l'occupant " "spécifié." #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Goulenn a-raok serriñ un ivinell pe ur prenestr." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "Darempred %(contact_jid)s bet pedet e-barzh %(room_jid)s." #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "Ebarzhiñ ur _webgaoz" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Vous êtes banni de ce salon." #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Anv-arveriad-ez direizh" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 msgid "Invalid affiliation given" msgstr "" #: gajim/command_system/implementation/standard.py:365 #, fuzzy msgid "Display names of all group chat occupants" msgstr "Usage : /%s [sujet], affiche ou met à jour le sujet actuel du salon." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Kevreadenn" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Flap a-stroll" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Ouzhpennañ un darempred nevez" #: gajim/gtk/single_message.py:185 #, fuzzy, python-format msgid "Single Message using account %s" msgstr "Kemennadenn simpl gant ar gont %s" #: gajim/gtk/single_message.py:187 #, fuzzy, python-format msgid "Single Message in account %s" msgstr "Kemennadenn simpl gant ar gont %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Kemennadenn simpl" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Kas %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "%s resevet" #: gajim/gtk/single_message.py:238 #, fuzzy, python-format msgid "Form %s" msgstr "De %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "N'eus ket tu en em lugañ" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Gwiriekait oc'h luget gant \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "RE: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s a skrivas:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "" #: gajim/gtk/pep_config.py:133 #, fuzzy, python-format msgid "Configure %s" msgstr "_Kenderc'hel" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "_Emezelañ" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Gant berzh eo bet embannet ar vCard" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "N'eus ket tu da gevreañ" #: gajim/gtk/dialogs.py:83 #, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" #: gajim/gtk/dialogs.py:440 #, fuzzy, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "Rankout a rit krouiñ ur gont a-raok gellout flapiñ gant tud all." #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "Bez ez eus arouezioù difennet en anv ar sal pe hini ar servijer." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "evit ar gont %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Cheñch ar ger-kuzh" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Rankout a rit reiñ ur ger-kuzh." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Ne glot ket ar gerioù-kuzh" #: gajim/gtk/add_contact.py:30 msgid "GG Number" msgstr "" #: gajim/gtk/add_contact.py:31 msgid "ICQ Number" msgstr "" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Ouzhpennañ un darempred..." #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s Mo" #: gajim/gtk/add_contact.py:235 #, fuzzy, python-format msgid "You must supply the %s of the new contact." msgstr "Rankout a rit reiñ ur ger-kuzh evit enrollañ ar gont nevez." #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "ID-arveriad-ez direizh" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "" #: gajim/gtk/add_contact.py:274 #, fuzzy msgid "You cannot add yourself to your roster." msgstr "Laouen 'vefen d'ho ouzhpennañ em roll-darempredoù." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Ezlinenn" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Darempred er roll dija" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Emañ an darempred en ho roll-darempredoù dija." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 #, fuzzy msgid "User ID:" msgstr "ID arveriad-ez:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "fazi en ur gas %s ( %s )" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "O skrivañ" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Dizoberiant" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Darempred diluget" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "Kemennadennoù\n" "kaset davet\n" "webkaozioù" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Kemennadenn nevez" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Kont" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Strollad" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "Diskouez er _roll hepken" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Istoradur ar gaoz" #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Cheñch lesanv" #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "Kemennadenn o _tegouezhout:" #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "Kemennadenn o _tegouezhout:" #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "Kemennadenn o _vont 'maez:" #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "Kemennadenn o _vont 'maez:" #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Titour-stad" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Titour-stad" #: gajim/gtk/themes.py:145 msgid "URL Color" msgstr "" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "_Islinennañ ar fazioù reizhskrivañ" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Kemennadennoù" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "_Distreiñ gant al livioù dre-ziouer" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Darempred diluget" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Darempred luget" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "Gajim - %s" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "N'eus ket bet kavet al lesanv : %s" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Oberiant" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s a zo bremañ %(status)s : %(status_msg)s" #: gajim/gtk/history.py:588 #, fuzzy, python-format msgid "Error: %s" msgstr "Fazi en ur lenn ar restr:" #: gajim/gtk/history.py:590 msgid "Error" msgstr "" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Ar stad a zo bremañ: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Ar stad a zo bremañ: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "Petra a fell deoc'h ober?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "O lugañ" #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Arsavet eo an treuskas eus %(filename)s digant %(name)s." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "Gajim - %d gemennadenn nevez" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "Ur flaperez Jabber e GTK+" #: gajim/gtk/about.py:48 #, python-format msgid "GTK+ Version: %s" msgstr "" #: gajim/gtk/about.py:49 #, python-format msgid "PyGObject Version: %s" msgstr "" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Diorroerien kent:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Diorroerien kent:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 #, fuzzy msgid "we would like to thank all the package maintainers." msgstr "Evit echuiñ, e fell deomp trugarekaat holl gempennerien ar pakad." #: gajim/gtk/about.py:61 msgid "Thanks" msgstr "" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "" "Troet e brezhoneg gant\n" "Giulia Fraboulet " #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Dibabit ur restr da gas..." #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Dibabit ur skeudenn" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "An holl restroù" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "An holl restroù" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Kas ur restr" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Skeudennoù" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Dibabit ur skeudenn" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "An holl restroù" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Enrollañ ar restr dindan..." #: gajim/gtk/profile.py:72 msgid "Retrieving profile…" msgstr "" #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Titouroù" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Stumm : BBBB-MM-DD" #: gajim/gtk/profile.py:257 #, fuzzy msgid "Information received" msgstr "Resevet ar bedadenn" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "Rankout a rit bezaén luget evit embann ho titouroù hiniennel." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Kas ur restr" #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "C'hwitet eo embannadur ar vCard" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "Bez ez eus bet ur fazi en ur embann ho titouroù hiniennel, klaskit en-dro " "diwezhatoc'h." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Road direizh" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 #, fuzzy msgid "Invalid Nickname" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/join_groupchat.py:223 msgid "Please choose a nickname" msgstr "" #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Ger-kuzh faos" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "A guzha an nozelennoù er prenestr flapiñ" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Penndibaboù" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "N'oc'h ket luget d'ar servijer" #: gajim/gtk/mam_preferences.py:102 msgid "Error received: {}" msgstr "" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Fazi en ur lenn ar restr:" #: gajim/gtk/advanced_config.py:86 #, fuzzy msgid "Activated" msgstr "Oberiant" #: gajim/gtk/advanced_config.py:86 #, fuzzy msgid "Deactivated" msgstr "Dizoberiant" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "" #: gajim/gtk/advanced_config.py:89 #, fuzzy msgid "Integer" msgstr "Er strollad" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Texte" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Dibab" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Talvoud" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Doare" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Hini ebet)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Elfennoù kuzh" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "Servijer:" #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Perzhioù ar servijerien" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Enrollet e-barzh: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "" #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 #, fuzzy msgid "Command line" msgstr "Urzhioù: %s" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "" #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "" #: gajim/gtk/features.py:61 #, fuzzy msgid "OpenPGP message encryption" msgstr "Encryption OpenPGP" #: gajim/gtk/features.py:63 #, fuzzy msgid "Ability to encrypting chat messages with OpenPGP." msgstr "Kemennadenn o _tegouezhout:" #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "" #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 #, fuzzy msgid "Password encryption" msgstr "Ne glot ket ar gerioù-kuzh" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "" #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "" #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 msgid "Requires Gspell" msgstr "" #: gajim/gtk/features.py:76 #, fuzzy msgid "Automatic status" msgstr "Goulenn evit gwelet e/he stad" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "" #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "" #: gajim/gtk/features.py:81 #, fuzzy msgid "RST Generator" msgstr "Hollek" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "" #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "" #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 msgid "Requires gir1.2-gupnpigd-1.0." msgstr "" #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "Hegerz" #: gajim/gtk/features.py:109 #, fuzzy msgid "Feature" msgstr "Perzhioù ar servijerien" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "" #: gajim/gtk/privacy_list.py:152 #, fuzzy, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Taolennadur: %s" #: gajim/gtk/privacy_list.py:208 #, fuzzy msgid "Edit a rule" msgstr "Furmad ul linenn" #: gajim/gtk/privacy_list.py:321 #, fuzzy msgid "Add a rule" msgstr "Furmad ul linenn" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "" #: gajim/gtk/privacy_list.py:526 #, fuzzy msgid "Invalid List Name" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/privacy_list.py:527 #, fuzzy msgid "You must enter a name to create a privacy list." msgstr "Rankout a rit reiñ ur ger-kuzh evit enrollañ ar gont nevez." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Gant berzh eo bet ouzhpennet ar gont!" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 #, fuzzy msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Bez e c'hellit aozañ dibaboù araoket ar gont en ur pouezañ war an nozelenn " "Araoket, pe hen ober diwezhatoc'h en ur glikañ war Kontoù er meuziad Aozañ " "eus ar prenestr pennañ." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Gant berzh eo bet krouet ho kont nevez!" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Rankout a rit reiñ un anv-arveriad-ez evit kefluniañ ar gont-mañ." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 #, fuzzy msgid "Invalid server" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/account_wizard.py:255 #, fuzzy msgid "Please provide a server on which you want to register." msgstr "Skrivit al lesanv nevez a fell deoc'h implij:" #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Road direizh" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "Ar porzh personelaet a rank bezañ un niverenn borzh" #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 #, fuzzy msgid "An error occurred during account creation" msgstr "Bez ez eus bet ur fazi en ur grouiñ ar gont" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Implijet eo an anv-kont dija" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Bez ho peus ur gont gant an anv-se dija." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Sil:" #: gajim/gtk/xml_console.py:79 msgid "XML Input" msgstr "" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Restr direizh" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 #, fuzzy msgid "Default" msgstr "Dilemel" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "titl ar gemennadenn stad" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "korf ar gemennadenn stad" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Adlugañ bremañ?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "Ret eo deoc'h adlugañ evit ma vo sevenet an holl gemmoù diouzhtu." #: gajim/gtk/accounts.py:224 #, fuzzy, python-format msgid "You have opened chat in account %s" msgstr "N'ho peus kont bev ebet" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Ouzhpennañ un darempred..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "_Dilemel" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Kontoù strollet" #: gajim/gtk/accounts.py:549 msgid "Use PGP Agent" msgstr "" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Kevreadenn" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Darempredoù" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Assigner une clé OpenPGP" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "K_evreañ en ur loc'hañ Gajim" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Adkevreañ war-eeun pa vez kollet ar gevreadenn" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Enrollaén an _istoradur-flapiñ evit an holl zarempredoù" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "_Kas ur gemennadenn d'ar servijer" #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Stad:" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "A cheñch stad ar gont pe ar c'hontoù" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Kemennadennoù" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Implij ar proksioù evit treuzkas restroù" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "N'eus ket tu en em lugañ" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Proksi:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "Kevreadenn" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Kas ar pakadoù derc'hel al lugadenn vev" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 msgid "Priority" msgstr "" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "A cheñch stad ar gont pe ar c'hontoù" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Anv:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Anv:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Postel nevez" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "Goulenn evit gwelet e/he stad" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Enaouiñ" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Porzh:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Kevreadenn" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Anv-arveriad-ez direizh" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Enrollañ ar ger-kuzh" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "Boulomelloù:" #: gajim/gtk/bookmarks.py:72 #, fuzzy msgid "?print_status:All" msgstr "Diskouez an eur:" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "" #: gajim/gtk/bookmarks.py:74 #, fuzzy msgid "?print_status:None" msgstr "Diskouez an eur:" #: gajim/gtk/bookmarks.py:143 #, fuzzy msgid "New Group Chat" msgstr "Flap a-stroll" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Bez ez eus titouroù direizh er sined-mañ" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "" "Gwiriekait ho peus leuniet an takadoù servijer ha sal-flapiñ pe lamit ar " "sined-mañ." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 #, fuzzy msgid "Character not allowed" msgstr "N'eus ket bet kavet al lesanv : %s" #: gajim/gtk/bookmarks.py:367 #, fuzzy msgid "Invalid room" msgstr "Road direizh" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Treug ar restr" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 msgid "Archive is malformed" msgstr "" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Bez ez eus eus ar restr-mañ dija" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Argas %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "échec lors de la publication de votre vCard" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Kefluniañ ar webgaoz" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Flaperez Jabber" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "Ur flaperez Jabber e GTK+" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Diskouez an holl _zarvoudoù o c'hortoz" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Perzhioù ar servijerien" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 msgid "Automatic spell-checking for your messages" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Merañ servijoù ar gont %s" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "_Menegiñ kemmoù stad an darempredoù e-barzh an istoradur" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Flapoù a-stroll" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Nevez 'zo:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "échec lors de la publication de votre vCard" #~ msgid "Stopped" #~ msgstr "Arsavet" #~ msgid "Error reading file:" #~ msgstr "Fazi en ur lenn ar restr:" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Fazi treuzkas" #, fuzzy #~ msgid "XML console interface" #~ msgstr "Console _XML..." #, fuzzy #~ msgid "(ESession info)" #~ msgstr "Taolennadur" #, fuzzy #~ msgid "Save as Preset..." #~ msgstr "Enrollañ evel raklakaet..." #, fuzzy #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "Jabberd1.4 n'aime pas l'information sha quand on rejoint un salon protégé " #~ "par un mot de passe. Passer cette option a Faux pour ne plus envoyer " #~ "l'information sha dans les présences des salons" #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "M'eo lazhet, ne vo ket erlec'hiet ar voulomelloù ascii doare ':)' gant " #~ "boulomelloù grafikel fiñv pe difiñv" #, fuzzy #~ msgid "_Emoticons" #~ msgstr "Boulomelloù:" #~ msgid "_Highlight misspelled words" #~ msgstr "_Islinennañ ar fazioù reizhskrivañ" #, fuzzy #~ msgid "T_heme" #~ msgstr "_Gwiskadur:" #, fuzzy #~ msgid "Themes" #~ msgstr "Perzhioù" #, fuzzy #~ msgid "Presence" #~ msgstr "_Bezañs" #, fuzzy #~ msgid "Emoticons disabled" #~ msgstr "Lazhet eo ar sifrañ" #, fuzzy #~ msgid "You cannot make changes to the default theme" #~ msgstr "N'hellit ket dilemel ar gwiskadur red" #~ msgid "theme name" #~ msgstr "anv ar gwiskadur" #~ msgid "You cannot delete your current theme" #~ msgstr "N'hellit ket dilemel ar gwiskadur red" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Kemennadenn simpl nevez digant %(nickname)s" #, fuzzy #~ msgid "New Private Message from group chat %s" #~ msgstr "Kemennadenn hiniennel nevez digant ar sal %s" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s : %(message)s" #, fuzzy #~ msgid "Messaged by %(nickname)s" #~ msgstr "Kemennadenn nevez digant %(nickname)s" #, fuzzy #~ msgid "Status message text color." #~ msgstr "korf ar gemennadenn stad" #, fuzzy #~ msgid "Incoming nickname font." #~ msgstr "Anv-arveriad-ez direizh" #, fuzzy #~ msgid "Status message text font." #~ msgstr "korf ar gemennadenn stad" #~ msgid "green" #~ msgstr "Glas" #~ msgid "human" #~ msgstr "Mab-den" #~ msgid "marine" #~ msgstr "Glas-mor" #, fuzzy #~ msgid "Contact row" #~ msgstr "Darempredoù" #~ msgid "Gajim Themes Customization" #~ msgstr "Personelaat gwiskadurioù Gajim" #~ msgid "Text _color:" #~ msgstr "_Liv ar skrid:" #~ msgid "_Background:" #~ msgstr "_Drekleur:" #~ msgid "Text _font:" #~ msgstr "_Nodrezh ar skrid:" #~ msgid "Font style:" #~ msgstr "Neuz an nodrezh:" #~ msgid "Paused" #~ msgstr "Ehan" #~ msgid "Gone" #~ msgstr "Aet kuit" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "Kemennadennoù\n" #~ "webgaoz" #~ msgid "Chatstate Tab Colors" #~ msgstr "Liv-stad an ivinelloù" #, fuzzy #~ msgid "Chat message" #~ msgstr "_Titour-stad:" #, fuzzy #~ msgid "Font" #~ msgstr "Sonioù" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Anv an darempred" #, fuzzy #~ msgid "Contact's message" #~ msgstr "_Titour-stad:" #, fuzzy #~ msgid "_Status message" #~ msgstr "_Titour-stad:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Message d'un Salon mis en Sur-brillance" #, fuzzy #~ msgid "Your nickname" #~ msgstr "_A-raok al lesanv:" #, fuzzy #~ msgid "Your message" #~ msgstr "Fazi en ur lenn ar restr:" #, fuzzy #~ msgid "Chat Line Colors" #~ msgstr "Liv-stad an ivinelloù" #, fuzzy #~ msgid "Jabber ID:" #~ msgstr "ID Jabber:" #, fuzzy #~ msgid "Resource:" #~ msgstr "Une erreur de protocole s'est produite :" #, fuzzy #~ msgid "Status:" #~ msgstr "Dibarzhioù" #, fuzzy #~ msgid "Client:" #~ msgstr "Personelaet" #, fuzzy #~ msgid "Contact time:" #~ msgstr "Dibarzhioù" #, fuzzy #~ msgid "Ask:" #~ msgstr "Poelladoù" #, fuzzy #~ msgid "Subscription:" #~ msgstr "Taolennadur" #, fuzzy #~ msgid "Name:" #~ msgstr "Personelaet" #, fuzzy #~ msgid "Nickname:" #~ msgstr "Lesanv:" #, fuzzy #~ msgid "Street:" #~ msgstr "Dibarzhioù" #, fuzzy #~ msgid "City:" #~ msgstr "Personelaet" #, fuzzy #~ msgid "State:" #~ msgstr "Dibarzhioù" #, fuzzy #~ msgid "Extra Address:" #~ msgstr "Chomlec'h 2:" #, fuzzy #~ msgid "Postal Code:" #~ msgstr "Kod postel:" #, fuzzy #~ msgid "Country:" #~ msgstr "Sonioù" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Lec'hienn hiniennel:" #, fuzzy #~ msgid "E-Mail:" #~ msgstr "Postel:" #, fuzzy #~ msgid "Phone No.:" #~ msgstr "Pellgomz:" #, fuzzy #~ msgid "Birthday:" #~ msgstr "Deiz-ha-bloaz:" #, fuzzy #~ msgid "Family:" #~ msgstr "Familh:" #, fuzzy #~ msgid "Middle:" #~ msgstr "Furmad ul linenn" #, fuzzy #~ msgid "Prefix:" #~ msgstr "Perzhioù" #, fuzzy #~ msgid "Given:" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "Suffix:" #~ msgstr "Sonioù" #, fuzzy #~ msgid "Full Name" #~ msgstr "Personelaet" #, fuzzy #~ msgid "Company:" #~ msgstr "Personelaet" #, fuzzy #~ msgid "Department:" #~ msgstr "Departamant:" #, fuzzy #~ msgid "Position:" #~ msgstr "Sonioù" #, fuzzy #~ msgid "Role:" #~ msgstr "Sonioù" #~ msgid "Edit %s" #~ msgstr "Kemmañ %s" #~ msgid "Register to %s" #~ msgstr "Emezelañ war %s" #~ msgid "Conversation History with %s" #~ msgstr "Istoradur flapiñ gant %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "N'eus ket tu da dizhout \"%s\"" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "" #~ "L'information d'enregistrement pour la passerelle %s n'est pas arrivée à " #~ "temps" #~ msgid "Register to" #~ msgstr "En em enrollañ war" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Anv an darempred" #, fuzzy #~ msgid "Search:" #~ msgstr "Klask" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Rankout a rit bezañ luget evit cheñch ger-kuzh." #~ msgid "Invalid password" #~ msgstr "Ger-kuzh direizh" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "Rankout a ra an daou c'her-kuzh bezañ heñvel en daou dakad." #~ msgid "Enter new password:" #~ msgstr "Roit ur ger-kuzh nevez:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Roit anezhañ en-dro evit kadarnaat:" #, fuzzy #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "je Jid %s ne respecte pas la norma RFC. Il ne sera pas ajouté a votre " #~ "liste de contact. Utiliser un outil de gestion de liste de contact tel " #~ "que http://jru.jabberstudio.org/ pour le supprimer" #~ msgid "unsubscribe request from %s" #~ msgstr "Requête de désinscription de la part de %s" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Lec'hienn hiniennel:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Kenderc'hel" #~ msgid "Manage Bookmarks" #~ msgstr "Merañ ar sinedoù" #, fuzzy #~ msgid "_Nickname:" #~ msgstr "Lesanv:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "" #~ "Si cette case est cochée, Gajim se connectera à ce salon au démarrage" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Diskouez an eur:" #, fuzzy #~ msgid "Add JID" #~ msgstr "ID Jabber:" #, fuzzy #~ msgid "Preference:" #~ msgstr "Penndibaboù" #, fuzzy #~ msgid "Preference" #~ msgstr "Penndibaboù" #, fuzzy #~ msgid "JID:" #~ msgstr "Ho JID:" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "Leuniit titouroù an darempred a zo da vezañ ouzhpennet er gont %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Leuniit an titouroù diwar-benn an darempred da ouzhpennañ" #, fuzzy #~ msgid "Recently" #~ msgstr "Nevez 'zo:" #~ msgid "Add New Contact" #~ msgstr "Ouzhpennañ un darempred nevez" #, fuzzy #~ msgid "_User ID:" #~ msgstr "ID arveriad-ez:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "ID arveriad-ez:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Lesanv" #~ msgid "Personal Information" #~ msgstr "Titouroù hiniennel" #, fuzzy #~ msgid "Avatar:" #~ msgstr "Dibab ur _skeudenn" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "_Dilemel" #, fuzzy #~ msgid "Yahoo! Address:" #~ msgstr "Chomlec'h 2:" #, fuzzy #~ msgid "Forward unread messages" #~ msgstr "Gajim - %d gemennadenn nevez" #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "Gajim - %d gemennadenn nevez" #, fuzzy #~ msgid "AIM Address:" #~ msgstr "_Chomlec'h:" #, fuzzy #~ msgid "MSN Address:" #~ msgstr "_Chomlec'h:" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "N'eus ket tu da implij OpenPGP war an urzhiataer-mañ" #, fuzzy #~ msgid "End to End message encryption" #~ msgstr "Encryption OpenPGP" #, fuzzy #~ msgid "Encrypting chat messages." #~ msgstr "Kemennadenn o _tegouezhout:" #, fuzzy #~ msgid "This session is encrypted" #~ msgstr "[Sifret eo ar gemennadenn-mañ]" #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "Lazhet eo ar sifrañ" #, fuzzy #~ msgid "Unable to decrypt message" #~ msgstr "Da _bep kemennadenn:" #~ msgid "_Send" #~ msgstr "_Kas" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Enrollañ ar restr dindan..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Oc'h ezporzhiañ an istoradur..." #~ msgid "Choose Image" #~ msgstr "Dibabit ur skeudenn" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Dibabit ur restr da gas..." #~ msgid "When %s becomes:" #~ msgstr "Pa teu %s da vezañ:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Oc'h ouzhpennañ ur gelaouenn nevez evit %s" #, fuzzy #~ msgid "Unable to load idle module" #~ msgstr "Impossible de rejoindre le salon" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "ur renkell eo %s met rankout a rafe bezañ ur restr" #~ msgid "creating logs database" #~ msgstr "o krouiñ titourva an istoradur" #, fuzzy #~ msgid "creating cache database" #~ msgstr "o krouiñ titourva an istoradur" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Kas %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Merour istoradur Gajim" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Merañ ar c'hontoù" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Kas ur gemennadenn _simpl..." #, fuzzy #~ msgid "E2E encryption disabled" #~ msgstr "Lazhet eo ar sifrañ" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "échec lors de la publication de votre vCard" #~ msgid "cyan" #~ msgstr "Cyan" #, fuzzy #~ msgid "migrating logs database to indices" #~ msgstr "o krouiñ titourva an istoradur" #, fuzzy #~ msgid "Send File..." #~ msgstr "Kas ur _restr" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Treuzkasoù" #~ msgid "Shows or hides the roster window" #~ msgstr "Diskouez pe kuzhat ar prenestr pennañ" #, fuzzy #~ msgid "Shows or hides the ipython window" #~ msgstr "Diskouez pe kuzhat ar prenestr pennañ" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "eus ar gont %s" #, fuzzy #~ msgid "Exception" #~ msgstr "Taolennadur" #, fuzzy #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "Me blijfe din ouzhpennañ ac'hanoc'h em roll-darempredoù." #~ msgid "_Actions" #~ msgstr "_Oberoù" #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Kregiñ da flapiñ" #, fuzzy #~ msgid "You are already in group chat %s" #~ msgstr "Emaoc'h er webgaoz %s dija" #~ msgid "Join Group Chat with account %s" #~ msgstr "Ebarzhiñ ur sal-flapiñ gant ar gont %s" #, fuzzy #~ msgid "Invalid Account" #~ msgstr "Anv-kont direizh" #, fuzzy #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "Rankout a rit krouiñ ur gont a-raok gellout flapiñ gant tud all." #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "Bez ez eus arouezioù difennet en anv ar sal pe hini ar servijer." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "Bez ez eus arouezioù difennet en anv ar sal pe hini ar servijer." #~ msgid "Start Chat with account %s" #~ msgstr "Kregiñ da flapiñ gant ar gont %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Roit ID an darempred a fell deoc'h kas ur gemennadenn\n" #~ "dezhañ:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Eilañ an ID Jabber" #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "" #~ "A ziskouez ar prenestr flapiñ evit ma c'hellfec'h kas ur gemennadenn d'un " #~ "darempred" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID an darempred ho peus c'hoant flapiñ gantañ" #~ msgid "Adds contact to roster" #~ msgstr "Ouzhennañ an darempred d'ar roll" #, fuzzy #~ msgid "Adds new contact to this account" #~ msgstr "Ouzhpennañ un darempred nevez d'ar gont-mañ." #, fuzzy #~ msgid "Starts chat, using this account" #~ msgstr "Kregiñ da flapiñ gant ar gont %s" #, fuzzy #~ msgid "Message content" #~ msgstr "korf ar gemennadenn" #, fuzzy #~ msgid "Join a MUC room" #~ msgstr "_Ebarzhiñ ur webgaoz nevez" #, fuzzy #~ msgid "Nickname to use" #~ msgstr "N'eus ket bet kavet al lesanv : %s" #, fuzzy #~ msgid "Password to enter the room" #~ msgstr "Ne glot ket ar gerioù-kuzh" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Ger-kuzh faos" #~ msgid "Nickname:" #~ msgstr "Lesanv:" #~ msgid "Server:" #~ msgstr "Servijer:" #~ msgid "Password:" #~ msgstr "Ger-kuzh:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Aozañ ma aelad pa lugan" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Furchal" #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "Merour an istoradur" #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Merour an istoradur" #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "An emc'hemennadenn evit ar stad \"Dihegerz\"" #, fuzzy #~ msgid "This contact does not support file transfer." #~ msgstr "Ur roll eus an treuzkasoù oberiant, echu pe arsavet" #, fuzzy #~ msgid "Hides the buttons in chat windows." #~ msgstr "A guzha an nozelennoù er prenestroù webgaoz" #, fuzzy #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Cheñch _lesanv" #, fuzzy #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "_Ouzhpennañ ar webgaoz d'ar sinedoù" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Klikit evit enlakaat ur boulomell (Alt+M)" #, fuzzy #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Ouzhennañ an darempred d'ar roll" #, fuzzy #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "a zo aketus d'ar gaozeadenn" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Ouzhennañ an darempred d'ar roll" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Ouzhennañ an darempred d'ar roll" #, fuzzy #~ msgid "Ma_ke message windows compact" #~ msgstr "Ur prenestr-flapiñ:" #, fuzzy #~ msgid "Hide all buttons in chat windows" #~ msgstr "A guzha an nozelennoù er prenestroù webgaoz" #, fuzzy #~ msgid "Hide the chat buttons" #~ msgstr "Usage: /%s, cache les boutons de discussion." #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "Lesanv" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "Ger-kuzh:" #, fuzzy #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "" #~ "Implij DBus ha Notification-Daemon evit diskouez ar c'hemennadennoù-" #~ "kelaouiñ" #, fuzzy #~ msgid "Notification" #~ msgstr "Kemmañ ar gont" #, fuzzy #~ msgid "Ignore" #~ msgstr "_Kenderc'hel" #, fuzzy #~ msgid "_Open Gmail Inbox" #~ msgstr "_Digeriñ ar bostelerez" #, fuzzy #~ msgid "Notify on new _GMail email" #~ msgstr "Ma c'helaouiñ evit ar c'hemennadennoù _Gmail nevez" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Si cette case est cochée, Gajim affichera l'avatar de chaque contact dans " #~ "la fenêtre principale et les salons" #, fuzzy #~ msgid "GMail Options" #~ msgstr "Poelladoù" #, fuzzy #~ msgid "20" #~ msgstr "0" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Kas %s" #, fuzzy #~ msgid "GMail Email Received" #~ msgstr "Resevet ar bedadenn" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Postel nevez war %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "Bez ho peus %d postel nevez" #~ msgstr[1] "Bez ho peus %d postel nevez" #~ msgid "Re_name" #~ msgstr "_Adenvel" #, fuzzy #~ msgid "Anonymous authentication" #~ msgstr "Implij an diskleriañ" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Diskouez an darempredoù _ezlinenn" #~ msgid "Chan_ge Password" #~ msgstr "C_heñch ar ger-kuzh" #~ msgid "Click to change account's password" #~ msgstr "Klikit evit cheñch ger-kuzh ar gont" #, fuzzy #~ msgid "Administration operations" #~ msgstr "Roll ar verourien" #, fuzzy #~ msgid "Browse..." #~ msgstr "_Furchal" #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "[Sifret eo ar gemennadenn-mañ]" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "M'eo diuzet, ec'h emlugo Gajim da jabber en ur implij ar gont-mañ en ur " #~ "loc'hañ" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Diskouez an darempredoù _ezlinenn" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "M'eo enaouet, kement cheñchamant graet war ar stad hollek (meret gant ar " #~ "voestig e traoñ ar roll-darempredoù) a gemmo stad ar gont-mañ ivez" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Si cette case est cochée, Gajim va diffuser des adresses IP en plus de la " #~ "votre, les transferts de fichiers ont ainsi plus de chance de fonctionner." #, fuzzy #~ msgid "Proxy" #~ msgstr "Perzhioù" #, fuzzy #~ msgid "Send _keep-alive packets" #~ msgstr "Kas ar pakadoù derc'hel al lugadenn vev" #, fuzzy #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Si cette case est cochée, Gajim enverra des paquets de maintien de " #~ "connexion pour prévenir des temps de latence pouvant entraîner des " #~ "déconnexions" #, fuzzy #~ msgid "Use cust_om hostname/port" #~ msgstr "Implij un anv ostiz/porzh personelaet" #, fuzzy #~ msgid "_Hostname: " #~ msgstr "Servijer:" #, fuzzy #~ msgid "_Port: " #~ msgstr "_Porzh:" #~ msgid "No key selected" #~ msgstr "Alc'hwez ebet diuzet" #~ msgid "Choose _Key..." #~ msgstr "Dibabit un _alc'hwezh..." #, fuzzy #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "" #~ "Si cette case est cochée, Gajim va retenir le mot de passe pour ce compte" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "_Edit Personal Information..." #~ msgstr "Kemmañ an titouroù hiniennel..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Titouroù diwar ho penn, miret war ar servijer" #~ msgid "Personal Information" #~ msgstr "Titouroù hiniennel" #, fuzzy #~ msgid "Co_nnect on Gajim startup" #~ msgstr "K_evreañ en ur loc'hañ Gajim" #, fuzzy #~ msgid "Use cust_om port:" #~ msgstr "Implij un anv ostiz/porzh personelaet" #, fuzzy #~ msgid "Mer_ge accounts" #~ msgstr "_Strollañ ar c'hontoù" #, fuzzy #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "N'eus ket tu da implij OpenPGP war an urzhiataer-mañ" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Rankout a rit bezañ diluget evit cheñch anv ar gont." #~ msgid "To change the account name, you must read all pending events." #~ msgstr "" #~ "Rankout a rit lenn an holl zarvoudoù-mañ evit gellout cheñch anv ar gont." #~ msgid "Account Name Already Used" #~ msgstr "Anv-kont implijet dija" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "" #~ "Implijet e vez an anv-mañ gant unan eus ho kontoù dija. Dibabit un anv " #~ "all marplij." #~ msgid "Invalid account name" #~ msgstr "Anv-kont direizh" #~ msgid "Account name cannot be empty." #~ msgstr "N'hell ket anv ar gont chom goullo." #~ msgid "Account name cannot contain spaces." #~ msgstr "N'hell ket anv ar gont kaout esaouennoù." #, fuzzy #~ msgid "Enter a new name for account %s" #~ msgstr "Roit ho ker-kuzh GPG evit ar gont %s." #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "Un ID Jabber a rank bezañ er stumm \"anv@anvservijer\"." #~ msgid "No such account available" #~ msgstr "Kont dihegerz" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "Rankout a rit krouiñ ho kont a-raok kemmañ an titouroù hiniennel." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "Rankout a rit bezañ luget evit kemmañ ho titouroù hiniennel." #, fuzzy #~ msgid "Your server can't save your personal information." #~ msgstr "Rankout a rit krouiñ ho kont a-raok kemmañ an titouroù hiniennel." #, fuzzy #~ msgid "Account Local already exists." #~ msgstr "Anv-kont implijet dija" #~ msgid "THANKS:" #~ msgstr "TRUGAREZ DA:" #, fuzzy #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "N'eus ket bet tu skrivañ e-barzh %s." #, fuzzy #~ msgid "_Enable" #~ msgstr "Enaouiñ" #, fuzzy #~ msgid "Filter" #~ msgstr "Sonioù" #~ msgid "_IQ" #~ msgstr "_IQ" #~ msgid "Info/Query" #~ msgstr "Titour/Goulenn" #~ msgid "_Message" #~ msgstr "_Kemennadenn" #, fuzzy #~ msgid "Last status: %s" #~ msgstr "Stad diwezhañ: %s" #, fuzzy #~ msgid " since %s" #~ msgstr "dibaoe %s" #~ msgid "since %s" #~ msgstr "dibaoe %s" #, fuzzy #~ msgid "No" #~ msgstr "Hini ebet" #, fuzzy #~ msgid "Prefer" #~ msgstr "Penndibaboù" #, fuzzy #~ msgid "otr" #~ msgstr "_Ostiz:" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Anv-arveriad-ez direizh" #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "" #~ "E-pad pet munutenn e rank linennoù diwezhañ ar gaozeadenn kent bezañ " #~ "gwarezet." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Luget e voc'h da %s hep OpenPGP." #, fuzzy #~ msgid "The following message was NOT encrypted" #~ msgstr "[Sifret eo ar gemennadenn-mañ]" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "N'eus ket tu da implij OpenPGP war an urzhiataer-mañ" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "War enaou emañ ar sifrañ" #, fuzzy #~ msgid "The following message was encrypted" #~ msgstr "[Sifret eo ar gemennadenn-mañ]" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Encryption OpenPGP" #, fuzzy #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Sifret eo ar gemennadenn-mañ]" #, fuzzy #~ msgid "Database cannot be read." #~ msgstr "N'hell ket anv ar gont chom goullo." #, fuzzy #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Kas ar gemennadenn ha serriñ ar prenestr" #, fuzzy #~ msgid "Show _XML Console" #~ msgstr "Diskouez ar gonsol _XML" #, fuzzy #~ msgid "Edit _Privacy Lists..." #~ msgstr "Flapoù prevez" #~ msgid "_Administrator" #~ msgstr "_Merour-ez" #, fuzzy #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "A gas ur gemennadenn d'an arveridi luget war ar servijer-mañ" #~ msgid "Sets Message of the Day" #~ msgstr "A laka kemennadenn an devezh" #~ msgid "Updates Message of the Day" #~ msgstr "A hiziva kemennadenn an devez" #~ msgid "Deletes Message of the Day" #~ msgstr "A zilam kemennadenn an devezh" #, fuzzy #~ msgid "Add _Contact..." #~ msgstr "_Ouzhpennañ un darempred..." #, fuzzy #~ msgid "_Accounts" #~ msgstr "Kontoù" #, fuzzy #~ msgid "Profile, A_vatar" #~ msgstr "Aelad, Avatar" #~ msgid "File _Transfers" #~ msgstr "_Treuzkasoù" #~ msgid "Help online" #~ msgstr "Skoazell enlinenn" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Marc'had Ar Goulennoù (FAQ enlinenn)" #, fuzzy #~ msgid "Fea_tures" #~ msgstr "Perzhioù ar servijerien" #~ msgid "to %s account" #~ msgstr "d'ar gont %s" #~ msgid "using %s account" #~ msgstr "en ur implij ar gont %s" #~ msgid "of account %s" #~ msgstr "eus ar gont %s" #~ msgid "for account %s" #~ msgstr "evit ar gont %s" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "En ur zilemel an darempred-mañ, e tilamit ivez e/he aotre. Atav e welo " #~ "ac'hanoc'h evel pa vefec'h ezlinenn." #~ msgid "Invalid Jabber ID" #~ msgstr "ID jabber direizh" #~ msgid "This file is being used by another process." #~ msgstr "Implijet eo ar restr-mañ gant ur poellad all." #~ msgid "pgp key" #~ msgstr "alc'hwezh pgp" #, fuzzy #~ msgid "" #~ "Sends new single message to a contact in the roster. Both OpenPGP key and " #~ "account are optional. If you want to set only 'account', without 'OpenPGP " #~ "key', just set 'OpenPGP key' to ''." #~ msgstr "" #~ "Envoyer un nouveau message à un contact dans la liste. La clé OpenPGP et " #~ "le compte sont facultatifs. Si vous voulez renseigner seulement le " #~ "paramètre 'compte' sans 'clé pgp', mettez simple la valeur '' pour 'clé " #~ "pgp'." #, fuzzy #~ msgid "Please first choose another theme as your current theme." #~ msgstr "Dibabit ur gwiskadur all da gentañ." #~ msgid "Your passphrase is incorrect" #~ msgstr "Direizh eo ho ker-kuzh" #, fuzzy #~ msgid "OpenPGP Passphrase Incorrect" #~ msgstr "Direizh eo ho ker-kuzh" #~ msgid "You successfully received %(filename)s from %(name)s." #~ msgstr "Gant berzh ho peus resevet %(filename)s digant %(name)s." #, fuzzy #~ msgid "Set logs directory" #~ msgstr "a grou ar renkell %s" #~ msgid "Chats" #~ msgstr "Flapoù" #, fuzzy #~ msgid "_Manage Bookmarks..." #~ msgstr "Merañ ar sinedoù..." #~ msgid "Change Status Message..." #~ msgstr "Kemmañ an titour-stad..." #~ msgid "_Change Status Message..." #~ msgstr "_Kemmañ an titour-stad..." #~ msgid "" #~ "You are not interested in the contact's presence, and neither he/she is " #~ "interested in yours" #~ msgstr "" #~ "N'oc'h ket dedennet gant bezañs an darempred-mañ, nag eñ/hi gant ho hini" #, fuzzy #~ msgid "Error description..." #~ msgstr "Taolennadur" #, fuzzy #~ msgid "View contact information (Ctrl+I)" #~ msgstr "a zo aketus d'ar gaozeadenn" #, fuzzy #~ msgid "Groupchat Histories" #~ msgstr "Flapoù a-stroll" #, fuzzy #~ msgid "All Chat Histories" #~ msgstr "Stad:" #~ msgid "More" #~ msgstr "Muioc'h" #~ msgid "creating %s directory" #~ msgstr "a grou ar renkell %s" #, fuzzy #~ msgid "%s is not the name of a group chat." #~ msgstr "A guzha an nozelennoù er prenestr flapiñ" #, fuzzy #~ msgid "Session Management" #~ msgstr "Kemennadenn gaset" #, fuzzy #~ msgid "Gajim needs X server to run. Quiting..." #~ msgstr "Ezhomm en deus Gajim eus ur servijer X evit labourat. O kuitaat..." #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above" #~ msgstr "Ezhomm en deus Gajim eus PyGTK 2.6 pe uheloc'h" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above to run. Quiting..." #~ msgstr "" #~ "Ezhomm en deus Gajim eus PyGTK 2.6 pe uheloc'h evit labourat. O kuitaat..." #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above" #~ msgstr "Ezhomm en deus Gajim eus GTK 2.6 pe uheloc'h" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above to run. Quiting..." #~ msgstr "" #~ "Ezhomm en deus Gajim eus GTK 2.6 pe uheloc'h evit labourat. O kuitaat..." #, fuzzy #~ msgid "Gajim needs pywin32 to run" #~ msgstr "Ezhomm en deus Gajim eus PySQLite evit labourat" #~ msgid "A programming error has been detected" #~ msgstr "Ur fazi gouleviñ (programmiñ) ez eus bet kavet" #~ msgid "Details" #~ msgstr "Munudoù" #, fuzzy #~ msgid "Jabber ID: " #~ msgstr "ID Jabber:" #~ msgid "Subscription: " #~ msgstr "Koumanant:" #, fuzzy #~ msgid "Mood: " #~ msgstr "Webgaoz:" #, fuzzy #~ msgid "Activity: " #~ msgstr "Oberiant" #, fuzzy #~ msgid "Join _Group Chat..." #~ msgstr "Ebarzhiñ ur _webgaoz" #, fuzzy #~ msgid "_Modify Account" #~ msgstr "_Kemmañ ar gont..." #~ msgid "_Group Chat" #~ msgstr "_Webkaozioù" #, fuzzy #~ msgid "Would you like to make Gajim the default Jabber client?" #~ msgstr "Voulez-vous l'écraser ?" #, fuzzy #~ msgid "Send Single Message" #~ msgstr "_Kas ur gemennadenn simpl" #, fuzzy #~ msgid "Actions" #~ msgstr "Poelladoù" #, fuzzy #~ msgid "Conditions" #~ msgstr "Sonioù" #, fuzzy #~ msgid "Advanced Actions" #~ msgstr "Actions a_vancées" #, fuzzy #~ msgid "Advanced Notifications Control" #~ msgstr "Aozer kefluniañ dre ar munut" #, fuzzy #~ msgid "Contact Change Status " #~ msgstr "Darempred diluget" #, fuzzy #~ msgid "File Transfer Started " #~ msgstr "Sac'het an treuzkas" #, fuzzy #~ msgid "Group Chat Message Highlight " #~ msgstr "Message d'un Salon mis en Sur-brillance" #, fuzzy #~ msgid "Group Chat Message Received " #~ msgstr "Kemennadenn digant ur sal-flapiñ" #, fuzzy #~ msgid "Launch a command" #~ msgstr "urzhiad" #, fuzzy #~ msgid "Online / Free For Chat" #~ msgstr "Prest da flapiñ" #, fuzzy #~ msgid "Play a sound" #~ msgstr "_Seniñ" #, fuzzy #~ msgid "_Disable auto opening chat window" #~ msgstr "A guzha an nozelennoù er prenestroù webgaoz" #, fuzzy #~ msgid "_Open chat window with user" #~ msgstr "Utiliser une seule fenê_tre de discussion avec des onglets" #, fuzzy #~ msgid "_Show event in roster" #~ msgstr "Diskouez er _roll hepken" #, fuzzy #~ msgid "contact(s)" #~ msgstr "Darempredoù" #, fuzzy #~ msgid "for " #~ msgstr "Porzh:" #, fuzzy #~ msgid "group(s)" #~ msgstr "Strollad" #, fuzzy #~ msgid "_Allow him/her to see my status" #~ msgstr "He/E aotren da welet ma stad" #, fuzzy #~ msgid "Descrition:" #~ msgstr "Taolennadur: %s" #, fuzzy #~ msgid "Advanced..." #~ msgstr "Dre ar munut" #, fuzzy #~ msgid "Display _activity of contacts in roster" #~ msgstr "Diskouez _skeudennigoù an darempredoù er roll" #, fuzzy #~ msgid "Display _tunes of contacts in roster" #~ msgstr "Diskouez _skeudennigoù an darempredoù er roll" #, fuzzy #~ msgid "Display m_ood of contacts in roster" #~ msgstr "Diskouez _skeudennigoù an darempredoù er roll" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the activity of contacts in the roster " #~ "window" #~ msgstr "" #~ "Si cette case est cochée, Gajim affichera l'avatar de chaque contact dans " #~ "la fenêtre principale et les salons" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the tunes of contacts in the roster window" #~ msgstr "" #~ "Si cette case est cochée, Gajim affichera l'avatar de chaque contact dans " #~ "la fenêtre principale et les salons" #~ msgid "Gajim Instant Messenger" #~ msgstr "Flaperez Gajim" #, fuzzy #~ msgid "German" #~ msgstr "Hollek" #, fuzzy #~ msgid "Greek" #~ msgstr "Glas" #, fuzzy #~ msgid "Croatian" #~ msgstr "Chomlec'h" #, fuzzy #~ msgid "Italian" #~ msgstr "Stouet" #, fuzzy #~ msgid "Polish" #~ msgstr "_Embann" #, fuzzy #~ msgid "Serbian" #~ msgstr "Hollek" #~ msgid "Check your connection or try again later" #~ msgstr "Gwiriekait ho lugadenn pe klaskit en-dro diwezhatoc'h" #~ msgid "error: cannot open %s for reading" #~ msgstr "fazi: dibosupl eo digeriñ %s evit lenn" #, fuzzy #~ msgid "Unable to bind to port %s." #~ msgstr "Impossible de rejoindre le salon" #~ msgid "A GTK+ jabber client" #~ msgstr "Ur flaperez jabber e GTK+" #, fuzzy #~ msgid "Condition" #~ msgstr "Kevreadenn" #, fuzzy #~ msgid "one of: offline, online, chat, away, xa, dnd, invisible " #~ msgstr "unan eus: offline, online, chat, away, xa, dnd, invisible " #, fuzzy #~ msgid "" #~ "Returns current status message(the global one unless account is specified)" #~ msgstr "" #~ "A gas an titour-stad red (an hini hollek, nemet ez eus bet resisaet ur " #~ "gont bennak)" #~ msgid "" #~ "Usage: %s %s %s \n" #~ "\t %s" #~ msgstr "" #~ "Implij: %s %s %s \n" #~ "\t %s" #, fuzzy #~ msgid "Subject: %s" #~ msgstr "Sujed: %s\n" #, fuzzy #~ msgid "Mood: %s" #~ msgstr "Webgaoz:" #, fuzzy #~ msgid "Activity: %s" #~ msgstr "Oberiant" #, fuzzy #~ msgid "_Show event in systray" #~ msgstr "Diskouez er _roll hepken" #, fuzzy #~ msgid "Autodetect on every Gajim startup" #~ msgstr "K_evreañ en ur loc'hañ Gajim" #, fuzzy #~ msgid "Show systray:" #~ msgstr "Diskouez er _roll hepken" #, fuzzy #~ msgid "Nickname not allowed: %s" #~ msgstr "N'eus ket bet kavet al lesanv : %s" #~ msgid "we are now subscribed to %s" #~ msgstr "nous sommes maintenant inscrits chez %s" #~ msgid "we are now unsubscribed from %s" #~ msgstr "nous ne sommes plus dans la liste de %s" #~ msgid "Account Modification" #~ msgstr "Kemmañ ar gont" #~ msgid "" #~ "Check this so Gajim will connect in port 5223 where legacy servers are " #~ "expected to have SSL capabilities. Note that Gajim uses TLS encryption by " #~ "default if broadcasted by the server, and with this option enabled TLS " #~ "will be disabled" #~ msgstr "" #~ "Si vous cochez cette case, Gajim se connectera sur le port 5223, sur " #~ "lequel les serveurs sont supposés gérer le SSL. Notez que Gajim utilise " #~ "le cryptage TLS par défaut si le serveur annonce qu'il le supporte, et " #~ "avec cette option vous désactivez le TLS" #~ msgid "Edit Personal Information..." #~ msgstr "Kemmañ an titouroù hiniennel..." #~ msgid "Hostname: " #~ msgstr "Servijer:" #~ msgid "" #~ "If checked, Gajim will store the password in ~/.gajim/config with 'read' " #~ "permission only for you" #~ msgstr "" #~ "Si cette case est cochée, Gajim va sauvegarder le mot de passe dans ~/." #~ "gajim/config avec accès en lecture pour vous uniquement" #~ msgid "Port: " #~ msgstr "Porzh:" #~ msgid "Save _passphrase (insecure)" #~ msgstr "_Enrollañ ar ger-kuzh (diasur)" #~ msgid "Use _SSL (legacy)" #~ msgstr "Implij _SSL" #, fuzzy #~ msgid "" #~ "Account row\n" #~ "Group row\n" #~ "Contact row\n" #~ "Chat Banner" #~ msgstr "" #~ "Kont\n" #~ "Strollad\n" #~ "Darempred\n" #~ "Titl" #, fuzzy #~ msgid "gtk-delete" #~ msgstr "Dilemel" #~ msgid "" #~ "All chat states\n" #~ "Composing only\n" #~ "Disabled" #~ msgstr "" #~ "An holl stadoù\n" #~ "O skrivañ hepken\n" #~ "Lazhet" #, fuzzy #~ msgid "" #~ "Autodetect on every Gajim startup\n" #~ "Always use GNOME default applications\n" #~ "Always use KDE default applications\n" #~ "Always use Xfce default applications\n" #~ "Custom" #~ msgstr "" #~ "Détection automatique à chaque démarrage\n" #~ "Toujours utiliser les applications par défaut de GNOME\n" #~ "Toujours utiliser les applications par défaut de KDE\n" #~ "Personnalisé" #, fuzzy #~ msgid "gtk-cancel" #~ msgstr "Dilemel" #~ msgid "pysqlite2 (aka python-pysqlite2) dependency is missing. Exiting..." #~ msgstr "pysqlite2 (ou python-pysqlite2) n'eo ket staliet. O kuitaat..." #~ msgid "" #~ "Please remove your current GTK+ runtime and install the latest stable " #~ "version from %s" #~ msgstr "" #~ "Dilamit al levraoueg red eus GTK+runtime ha staliit an aozadur stabil " #~ "diwezhañ diwar %s" #~ msgid "Gajim needs PySQLite2 to run" #~ msgstr "Ezhomm en deus Gajim eus PySQLite evit labourat" #, fuzzy #~ msgid "gtk-ok" #~ msgstr "gtk+" #~ msgid "OpenPGP passphrase was not given" #~ msgstr "N'eo ket bet roet ar ger-kuzh OpenPGP" #~ msgid "" #~ "To continue sending and receiving messages, you will need to reconnect." #~ msgstr "" #~ "Evit kenderc'hel da gas ha da resev kemennadennoù, e rankit lugañ en-dro." #~ msgid "Add Special _Notification" #~ msgstr "Ouzhpennañ ur gelaouenn _ispisial" #~ msgid "Commands: %s" #~ msgstr "Urzhioù: %s" #, fuzzy #~ msgid "" #~ "Usage: /%(command)s , sends action to the current group chat. Use " #~ "third person. (e.g. /%(command)s explodes.)" #~ msgstr "" #~ "Usage : /%s , envoie l'action au salon actuel. Utilise la " #~ "troisième personne. (ex : /%s explose.)" #~ msgid "No help info for /%s" #~ msgstr "N'eus skoazell hegerz ebet evit /%s" #~ msgid "Nickname not found: %s" #~ msgstr "N'eus ket bet kavet al lesanv : %s" #, fuzzy #~ msgid "This group chat has no subject" #~ msgstr "N'eus sujed ebet gant ar webgaoz-mañ" #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], bans the JID from the group chat. The " #~ "nickname of an occupant may be substituted, but not if it contains \"@\". " #~ "If the JID is currently in the group chat, he/she/it will also be kicked." #~ msgstr "" #~ "Usage : /%s [raison], bannit le JID du salon. Le surnom de " #~ "l'occupant peut être utilisé s'il ne contient pas de \"@\". Si le JID est " #~ "actuellement dans le salon il sera également éjecté. Ne supporte pas les " #~ "espaces dans le surnom." #~ msgid "" #~ "Usage: /%s [reason], closes the current window or tab, displaying reason " #~ "if specified." #~ msgstr "" #~ "Usage : /%s [raison], ferme la fenêtre ou l'onglet courrant en affichant " #~ "la raison si spécifiée." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], invites JID to the current group chat, " #~ "optionally providing a reason." #~ msgstr "" #~ "Usage : /%s [raison], invite le JID dans le salon actuel, la raison " #~ "est optionnelle." #~ msgid "" #~ "Usage: /%s @[/nickname], offers to join room@server " #~ "optionally using specified nickname." #~ msgstr "" #~ "Usage : /%s @[/surnom], propose de rejoindre " #~ "salon@serveur en option on peut spécifier le surnom utilisé." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], removes the occupant specified by " #~ "nickname from the group chat and optionally displays a reason." #~ msgstr "" #~ "Usage : /%s [raison], supprime l'occupant portant le surnom " #~ "spécifié du salon et affiche en option la raison. Le surnom ne doit pas " #~ "contenir d'espaces !" #, fuzzy #~ msgid "" #~ "Usage: /%s [message], opens a private message window and sends " #~ "message to the occupant specified by nickname." #~ msgstr "" #~ "Usage : /%s [message], ouvre une fenêtre de discussion privée et " #~ "envoie le message à l'occupant(e) spécifié(e) par le surnom." #, fuzzy #~ msgid "Usage: /%s , changes your nickname in current group chat." #~ msgstr "Usage : /%s , change votre surnom dans ce salon." #, fuzzy #~ msgid "" #~ "Usage: /%s [topic], displays or updates the current group chat topic." #~ msgstr "" #~ "Usage : /%s [sujet], affiche ou met à jour le sujet actuel du salon." #~ msgid "" #~ "Usage: /%s , sends a message without looking for other commands." #~ msgstr "" #~ "Usage : /%s , envoie un message sans chercher d'autres commandes." #, fuzzy #~ msgid "" #~ "Usage: /%s , allow to send you messages and private " #~ "messages." #~ msgstr "Usage : /%s , change votre surnom dans ce salon." #~ msgid "Name:" #~ msgstr "Anv:" #~ msgid "_Host:" #~ msgstr "_Ostiz:" #, fuzzy #~ msgid "Modify Account" #~ msgstr "_Kemmañ ar gont..." #, fuzzy #~ msgid "Gajim account %s" #~ msgstr "eus ar gont %s" #~ msgid "This account is already configured in Gajim." #~ msgstr "Kefluniet eo bet ar gont-mañ e-barzh Gajim dija." #, fuzzy #~ msgid "File transfer stopped by the contact at the other end" #~ msgstr "Arsavet eo bet an treuzkas gant ho tarempred" #, fuzzy #~ msgid "Generic" #~ msgstr "Hollek" #~ msgid "%s has not broadcast an OpenPGP key, nor has one been assigned" #~ msgstr "" #~ "N'eus bet kaset alc'hwezh OpenPGP ebet gant %s, ha n'o peus roet hini " #~ "ebet dezhañ" #~ msgid "No such command: /%s (if you want to send this, prefix it with /say)" #~ msgstr "" #~ "N'eus ket eus an urzhiad: /%s (lakait /say araozañ ma fell deoc'h e gas)" #, fuzzy #~ msgid "" #~ "Usage: /%s , sends action to the current group chat. Use third " #~ "person. (e.g. /%s explodes.)" #~ msgstr "" #~ "Usage : /%s , envoie l'action au salon actuel. Utilise la " #~ "troisième personne. (ex : /%s explose.)" #~ msgid "_Retype Password:" #~ msgstr "_Adroit ho ker-kuzh" #~ msgid "" #~ "If you have 2 or more accounts and it is checked, Gajim will list all " #~ "contacts as if you had one account" #~ msgstr "" #~ "M'ho peus daou gont pe ouzhpenn hag eo diuzet, e vo strollet an holl " #~ "zarempredoù evel pa vefe ur gont hepken" #~ msgid "Click to see past conversation in this room" #~ msgstr "Klikit amañ evit gwelout kaozioù kent ar flap-mañ" #~ msgid "Build custom query" #~ msgstr "Krouiñ ur goulenn personelaet" #~ msgid "Query Builder..." #~ msgstr "Krouiñ ur goulenn..." #~ msgid "Invitation Received" #~ msgstr "Resevet ar bedadenn" #~ msgid "Format of a line" #~ msgstr "Furmad ul linenn" #~ msgid "Interface Customization" #~ msgstr "Personelaat an etrefas" #~ msgid "A_fter nickname:" #~ msgstr "Da _heul al lesanv:" #~ msgid "Also known as iChat style" #~ msgstr "Anvet ivez stil iChat" #~ msgid "E_very 5 minutes" #~ msgstr "_Bep 5 munutenn" #~ msgid "" #~ "Gajim will automatically show new events by poping up the relative window" #~ msgstr "" #~ "Gajim montrera automatiquement les nouveaux évènements reçus en montrant " #~ "la fenêtre correspondante" #~ msgid "" #~ "Gajim will notify you for new events via a popup in the bottom right of " #~ "the screen" #~ msgstr "" #~ "Gajim vous signalera les nouveaux évènements dans une fenêtre en bas à " #~ "droite de l'écran" #~ msgid "" #~ "Gajim will notify you via a popup window in the bottom right of the " #~ "screen about contacts that just signed in" #~ msgstr "" #~ "Gajim vous signalera par une fenêtre de notification en bas à droite de " #~ "l'écran qu'un contact s'est connecté" #~ msgid "" #~ "Gajim will only change the icon of the contact that triggered the new " #~ "event" #~ msgstr "" #~ "Gajim ne fera que changer l'icône du contact qui a envoyé le nouvel " #~ "évènement" #~ msgid "" #~ "If checked, Gajim will remember the roster and chat window positions in " #~ "the screen and the sizes of them next time you run it" #~ msgstr "" #~ "Si cette case est cochée, Gajim va retenir la position de votre liste " #~ "decontacts et des fenêtres de discussion pour vos prochaines utilisations" #~ msgid "" #~ "Never\n" #~ "Always\n" #~ "Per account\n" #~ "Per type" #~ msgstr "" #~ "Morse\n" #~ "Atav\n" #~ "Dre gont\n" #~ "Dre zoare" #, fuzzy #~ msgid "Outgoing Chat state noti_fications:" #~ msgstr "Titou_roù-stad ar flap:" #~ msgid "Print time:" #~ msgstr "Diskouez an eur:" #~ msgid "Save _position and size for roster and chat windows" #~ msgstr "_Mirout lec'hiadur ha ment ar roll hag ar prenistri-flapiñ" #~ msgid "The auto away status message" #~ msgstr "An emc'hemennadenn evit ar stad \"Ezvezant\"" #~ msgid "" #~ "When a new event (message, file transfer request etc..) is received, the " #~ "following methods may be used to inform you about it. Please note that " #~ "events about new messages only occur if it is a new message from a " #~ "contact you are not already chatting with" #~ msgstr "" #~ "Pa resevit un darvoud nevez (kemennadenn, goulenn treuzkas h.a.), ez eus " #~ "tu implij an doareoù da heul evit kelaouién ac'hanoc'h. Deoc'h da " #~ "c'houzout, ec'h erru darvoudoù evit kemennadennoù nevez m'int bet kaset " #~ "gant un darempred n'emaoc'h ket o flapién gant-añ/-i." #, fuzzy #~ msgid "_Advanced Notifications Control..." #~ msgstr "Aozer kefluniañ dre ar munut" #~ msgid "_After time:" #~ msgstr "_War-lerc'h an eur:" #~ msgid "_Before time:" #~ msgstr "_A-raok an eur:" #~ msgid "_Player:" #~ msgstr "_Soner:" #~ msgid "Address" #~ msgstr "Chomlec'h" #~ msgid "Role:" #~ msgstr "Perzh:" #~ msgid "_Retrieve" #~ msgstr "_Kargañ" #~ msgid "_Remove from Roster" #~ msgstr "_Dilemel diouzh ar roll" #~ msgid "A_ccounts" #~ msgstr "_Kontoù" #~ msgid "_Filter:" #~ msgstr "_Sil:" #~ msgid "OS:" #~ msgstr "OS:" #~ msgid "Every %s _minutes" #~ msgstr "Bep %s _munutenn" #~ msgid "You will always see him or her as offline." #~ msgstr "Atav e weloc'h anezhañ ezlinenn." #~ msgid "%s is now %s (%s)" #~ msgstr "%s a zo bremañ %s (%s)" #, fuzzy #~ msgid "Network Manager support not available" #~ msgstr "N'eus ket tu da gevreañ" #~ msgid "Session Management support not available (missing gnome.ui module)" #~ msgstr "" #~ "Support du gestionnaire de sessions indisponible (module gnome.ui " #~ "manquant)" #~ msgid "Private Chat" #~ msgstr "Flap prevez" #~ msgid "%s is now %s" #~ msgstr "%s a zo bremañ %s" #~ msgid "%s does not appear to be a valid JID" #~ msgstr "%s ne seblant ket bezañ ur JID a-feson" #~ msgid "%s - Gajim" #~ msgstr "%s - Gajim" #~ msgid "Without a connection, you can not get your contact information." #~ msgstr "Rankout a rit bezañ luget evit kaout titouroù an darempred." #, fuzzy #~ msgid "_New group chat" #~ msgstr "Flap a-stroll" #~ msgid "_Log on" #~ msgstr "_Lugañ" #~ msgid "Log _off" #~ msgstr "_Dilugañ" #~ msgid "Save passphrase" #~ msgstr "Enrollañ ar ger-kuzh" #~ msgid "Drop %s in group %s" #~ msgstr "Kas %s er strollad %s" #, fuzzy #~ msgid "Hides the buttons in two persons chat window." #~ msgstr "A guzha an nozelennoù er prenestroù-flapiñ" #~ msgid "Connected to server %s:%s with %s" #~ msgstr "Luget d'ar servijer %s:%s gant %s" #~ msgid "invisible" #~ msgstr "Diwelus" #~ msgid "offline" #~ msgstr "Ezlinenn" #~ msgid "I'm %s" #~ msgstr "%s on" #, fuzzy #~ msgid " %d unread single message" #~ msgid_plural " %d unread single messages" #~ msgstr[0] "Gajim - %d gemennadenn simpl nevez" #~ msgstr[1] "Gajim - kemennadennoù simpl nevez: %d" #, fuzzy #~ msgid " %d unread group chat message" #~ msgid_plural " %d unread group chat messages" #~ msgstr[0] "Gajim - %d gemennadenn webgaoz nevez" #~ msgstr[1] "Gajim - kemennadennoù webgaoz nevez: %d" #, fuzzy #~ msgid " %d unread private message" #~ msgid_plural " %d unread private messages" #~ msgstr[0] "Gajim - %d gemennadenn brevez nevez" #~ msgstr[1] "Gajim - kemennadennoù prevez nevez: %d" #, fuzzy #~ msgid "Connection to host could not be established" #~ msgstr "N'eus ket tu seveniñ al lugadenn gant an darempred." #, fuzzy #~ msgid "_New room" #~ msgstr "Sal-flapiñ nevez" #~ msgid "Role: " #~ msgstr "Perzh:" #, fuzzy #~ msgid "Away " #~ msgstr "Ezvezant" #, fuzzy #~ msgid "Down" #~ msgstr "Pellgargañ" #, fuzzy #~ msgid "List of special notifications settings" #~ msgstr "Oc'h ouzhpennañ ur gelaouenn nevez evit %s" #, fuzzy #~ msgid "Not Available " #~ msgstr "Dihegerz" #~ msgid "Contact _Info" #~ msgstr "_Titouroù" #~ msgid "Jabber" #~ msgstr "Jabber" #~ msgid "Invalid room or server name" #~ msgstr "Anv sal pe servijer direizh" #~ msgid "Your personal information has been published successfully." #~ msgstr "Gant berzh eo bet embannet ho titouroù hiniennel." #~ msgid "Migrating Logs..." #~ msgstr "O tilec'hiañ an istoradur..." #~ msgid "Gajim - %d unread message" #~ msgid_plural "Gajim - %d unread messages" #~ msgstr[0] "Gajim - %d gemennadenn nevez" #~ msgstr[1] "Gajim - kemennadennoù nevez: %d" #~ msgid "Since %s" #~ msgstr "Dibaoe %s" #~ msgid "Automatically authorize contact" #~ msgstr "Aotren war-eeun an darempred" #~ msgid "_Join New Room..." #~ msgstr "Re_joindre un nouveau salon..." #, fuzzy #~ msgid "Please modify your special notification below" #~ msgstr "Choisissez une des options suivantes :" #~ msgid "Delete Message of the Day" #~ msgstr "Supprimer le message du jour" #, fuzzy #~ msgid "I want to listen to:" #~ msgstr "%s souhaite vous envoyer un fichier :" #~ msgid "Send _New Message..." #~ msgstr "Envoyer un _nouveau message..." #~ msgid "Set Message of the Day" #~ msgstr "Définir un message du jour" #~ msgid "Update Message of the Day" #~ msgstr "Mettre à jour le message du jour" #~ msgid "Use compact view when you open a chat window" #~ msgstr "" #~ "Utiliser la vue compacte quand vous ouvrez une fenêtre de discussion" #~ msgid "Use compact view when you open a group chat window" #~ msgstr "Utiliser la vue compacte quand vous ouvrez une fenêtre de salon" #~ msgid "%(nickname)s in room %(room_name)s has sent you a new message." #~ msgstr "" #~ "%(nickname)s du salon %(room_name)s vous a envoyé un nouveau message." #~ msgid "%s has sent you a new message." #~ msgstr "%s vous a envoyé un nouveau message." #~ msgid "Logs have been successfully migrated to the database." #~ msgstr "L'historique a été corectement récupéré." #, fuzzy #~ msgid "Start Chat with Contact" #~ msgstr "Commencer une discussion avec le compte %s" #~ msgid "All contacts in this group are offline or have errors" #~ msgstr "Tous les contacts de ce groupe sont déconnectés ou ont des erreurs" #~ msgid "Sound" #~ msgstr "Son" #~ msgid "Image" #~ msgstr "Image" #~ msgid "To %s" #~ msgstr "À %s" #~ msgid "You have been invited to the %(room_jid)s room by %(contact_jid)s" #~ msgstr "Vous avez été invité dans le salon %(room_jid)s par %(contact_jid)s" #~ msgid "_Set Image..." #~ msgstr "_Choisir une image..." #~ msgid "Switch to %s" #~ msgstr "Basculer vers %s" #~ msgid "using account " #~ msgstr "en utilisant le compte " #~ msgid "The filesize of image \"%s\" is too large" #~ msgstr "Le taille du fichier de l'image \"%s\" est trop importante" #~ msgid "The file must not be more than 32 kilobytes." #~ msgstr "Le fichier ne doit pas excéder les 32 kilobytes." #~ msgid "Timeout" #~ msgstr "Dépassement de temps" #~ msgid "account: " #~ msgstr "compte : " #~ msgid "If you close this window, you will be disconnected from these rooms." #~ msgstr "Si vous fermer cette fenêtre, vous serez déconnecté de ces salons." #~ msgid "Activate/Disable notification for when a file transfer is complete" #~ msgstr "Active/Désactive la notification de fin de transfert" #~ msgid "Removing selected file transfer" #~ msgstr "Supprime le transfert du fichier sélectionné" #~ msgid "Stoping selected file transfer" #~ msgstr "Arrête le transfert de fichier sélectionné" #~ msgid "" #~ "If you close this tab and you have history disabled, the message will be " #~ "lost." #~ msgstr "" #~ "Si vous fermez cet onglet et que l'historique n'est pas activé, le " #~ "message sera perdu." #~ msgid "Cannot remove last group" #~ msgstr "Impossible d'enlever le dernier groupe" #~ msgid "At least one contact group must be present." #~ msgstr "Au moins un groupe de contacts doit exister." #~ msgid "" #~ "pysqlite2 (aka python-pysqlite2) dependency is missing. After you install " #~ "pysqlite3, if you want to migrate your logs to the new database, please " #~ "read: http://trac.gajim.org/wiki/MigrateLogToDot9DB Exiting..." #~ msgstr "" #~ "pysqlite2 (ou python-pysqlite2) n'est pas installé. Aprés avoir installé " #~ "pysqlite2, si vous voulez migrer votre historique dans la nouvelle base " #~ "de donnée, lisez http://trac.gajim.org/wiki/MigrateLogToDot9DB. Quitte..." #~ msgid "" #~ "Image for emoticon has to be less than or equal to 24 pixels in width and " #~ "24 in height." #~ msgstr "" #~ "L'image pour l'émoticône doit être inférieure ou égale à 24 points en " #~ "largeur et 24 points en hauteur." gajim-gajim-1.1.3/po/ca.po000066400000000000000000007145551345766322700152710ustar00rootroot00000000000000# 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. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2017-08-01 14:04+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.8.11\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "" #: gajim/chat_control_base.py:1103 #, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "" #: gajim/filetransfers_window.py:97 msgid "File" msgstr "" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "" #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 msgid "Open _Containing Folder" msgstr "" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "" #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 msgid "File transfer stopped" msgstr "" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" #: gajim/filetransfers_window.py:341 msgid "Gajim can not read this file" msgstr "" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "" #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "" #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "" #: gajim/filetransfers_window.py:487 msgid "Checking file…" msgstr "" #: gajim/filetransfers_window.py:501 msgid "File error" msgstr "" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "" #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "" #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "" #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "" #: gajim/filetransfers_window.py:1019 msgid "Choose a File to Send…" msgstr "" #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 msgid "Save _As" msgstr "" #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "" #: gajim/vcard.py:326 gajim/vcard.py:329 msgid "?Time:Unknown" msgstr "" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "" #: gajim/vcard.py:384 msgid "Affiliation:" msgstr "" #: gajim/vcard.py:391 msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "" #: gajim/vcard.py:393 msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "" #: gajim/vcard.py:395 msgid "The contact and you want to exchange presence information" msgstr "" #: gajim/vcard.py:397 msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "" #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr "" #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 #, fuzzy msgid "Clear File" msgstr "Fitxer de Certificat de Client:" #: gajim/options_dialog.py:484 #, fuzzy msgid "Manage Proxies" msgstr "Gestió de perfils de proxy" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Cap" #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "Ajustar a estat" #: gajim/options_dialog.py:528 msgid "On" msgstr "" #: gajim/options_dialog.py:528 #, fuzzy msgid "Off" msgstr "Desconnectat" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "" #: gajim/options_dialog.py:565 msgid "There is no OpenPGP secret key available." msgstr "" #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "" #: gajim/gui_menu_builder.py:95 msgid "_New Group Chat" msgstr "" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "" #: gajim/gui_menu_builder.py:502 msgid "Send Single _Message…" msgstr "" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 msgid "Send Cus_tom Status" msgstr "Envia Estat" #: gajim/gui_menu_builder.py:535 msgid "E_xecute Command…" msgstr "" #: gajim/gui_menu_builder.py:543 msgid "_Manage Transport" msgstr "" #: gajim/gui_menu_builder.py:549 msgid "_Modify Transport" msgstr "" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 msgid "_Rename…" msgstr "" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "_Desbloquejar" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "_Bloca" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 msgid "Remo_ve" msgstr "Esborra" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 msgid "_Information" msgstr "" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 #, fuzzy msgid "Send File…" msgstr "Envia _Fitxer" #: gajim/gui_menu_builder.py:602 msgid "Upload File…" msgstr "" #: gajim/gui_menu_builder.py:603 msgid "Send File Directly…" msgstr "" #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Convida _Contactes" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "_Afegeix a llista de contactes" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "Informació personal" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 msgid "History" msgstr "Historial" #: gajim/gui_menu_builder.py:634 #, fuzzy msgid "Manage Room" msgstr "Gestiona Sala" #: gajim/gui_menu_builder.py:635 #, fuzzy msgid "Change Subject" msgstr "Canvia Tema..." #: gajim/gui_menu_builder.py:636 #, fuzzy msgid "Configure Room" msgstr "Configura Sala..." #: gajim/gui_menu_builder.py:637 msgid "Upload Avatar…" msgstr "" #: gajim/gui_menu_builder.py:638 #, fuzzy msgid "Destroy Room" msgstr "_Destrueix Sala" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "" #: gajim/gui_menu_builder.py:641 #, fuzzy msgid "Change Nick" msgstr "Canvia _Nick..." #: gajim/gui_menu_builder.py:642 #, fuzzy msgid "Bookmark Room" msgstr "Afegeix aquesta sala a les adreces d'interès" #: gajim/gui_menu_builder.py:643 #, fuzzy msgid "Request Voice" msgstr "Sol.licita Veu" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 msgid "Notify on all messages" msgstr "" #: gajim/gui_menu_builder.py:645 #, fuzzy msgid "Minimize on close" msgstr "_Minimitza en tancar" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 #, fuzzy msgid "Execute command" msgstr "_Executa Comanda...." #: gajim/gui_menu_builder.py:648 #, fuzzy msgid "Disconnect" msgstr "_Desconnecta" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "" #: gajim/gui_menu_builder.py:680 #, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "" msgstr[1] "" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Uneix-te al xat en grup" #: gajim/gui_menu_builder.py:734 #, fuzzy msgid "Add Contact…" msgstr "_Afegeix Contacte..." #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 msgid "Profile" msgstr "Perfil" #: gajim/gui_menu_builder.py:737 msgid "Discover Services" msgstr "" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Envia un _Missatge únic..." #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Avançat" #: gajim/gui_menu_builder.py:740 msgid "Archiving Preferences" msgstr "" #: gajim/gui_menu_builder.py:741 #, fuzzy msgid "Synchronise History" msgstr "Sincronitza els contactes" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 #, fuzzy msgid "Server Info" msgstr "Servidor:" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "" #: gajim/gui_menu_builder.py:746 #, fuzzy msgid "Admin" msgstr "_Administra" #: gajim/gui_menu_builder.py:747 #, fuzzy msgid "Send Server Message…" msgstr "Envia Missatge Privat" #: gajim/gui_menu_builder.py:748 msgid "Set MOTD…" msgstr "" #: gajim/gui_menu_builder.py:749 msgid "Update MOTD…" msgstr "" #: gajim/gui_menu_builder.py:750 #, fuzzy msgid "Delete MOTD…" msgstr "Suprimeix" #: gajim/gui_menu_builder.py:799 msgid "No Accounts available" msgstr "" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Comptes" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 msgid "Copy JID" msgstr "" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Uneix-te al xat en grup" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 #, fuzzy msgid "Add to Roster…" msgstr "_Afegeix a llista de contactes" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "_Copia la ubicació de l'enllaç" #: gajim/gui_menu_builder.py:881 #, fuzzy msgid "Open Link in Browser" msgstr "_Obri l'enllaç al navegador" #: gajim/gui_menu_builder.py:886 #, fuzzy msgid "Copy Email Address" msgstr "_Copia adreça JID/Email" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Obre Editor de Correu" #: gajim/gui_menu_builder.py:892 #, fuzzy msgid "Copy JID/Email" msgstr "_Copia adreça JID/Email" #: gajim/history_manager.py:71 msgid "Usage:" msgstr "" #: gajim/history_manager.py:73 msgid "Options:" msgstr "" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" #: gajim/history_manager.py:257 msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" #: gajim/history_manager.py:262 msgid "Database Cleanup" msgstr "" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "" #: gajim/history_manager.py:577 #, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "" #: gajim/history_manager.py:581 msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "" #: gajim/history_manager.py:583 msgid "This can not be undone." msgstr "" #: gajim/history_manager.py:585 gajim/history_manager.py:624 msgid "Deletion Confirmation" msgstr "" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "" msgstr[1] "" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "" #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "" #: gajim/dialogs.py:84 #, python-format msgid "JID: %s" msgstr "" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "General" #: gajim/dialogs.py:200 msgid "Group" msgstr "" #: gajim/dialogs.py:207 msgid "In the group" msgstr "" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "" #: gajim/dialogs.py:483 msgid "Set Mood" msgstr "" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "" #: gajim/dialogs.py:807 msgid "Overwrite Status Message?" msgstr "" #: gajim/dialogs.py:808 msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "" #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "" #: gajim/dialogs.py:857 #, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "" #: gajim/dialogs.py:928 msgid "Without a connection, you can not synchronise your contacts." msgstr "" #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "" #: gajim/dialogs.py:978 msgid "This account is not connected to the server" msgstr "" #: gajim/dialogs.py:979 msgid "You cannot synchronize with an account unless it is connected." msgstr "" #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "" #: gajim/dialogs.py:1065 msgid "add" msgstr "" #: gajim/dialogs.py:1065 msgid "modify" msgstr "" #: gajim/dialogs.py:1066 msgid "remove" msgstr "" #: gajim/dialogs.py:1095 #, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "" #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 msgid "Add" msgstr "Afegeix" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 msgid "Modify" msgstr "" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Suprimeix" #: gajim/dialogs.py:1125 msgid "Groups" msgstr "" #: gajim/dialogs.py:1233 #, python-format msgid "%s suggested me to add you in my roster." msgstr "" #: gajim/dialogs.py:1247 #, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "" msgstr[1] "" #: gajim/dialogs.py:1285 #, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "" msgstr[1] "" #: gajim/dialogs.py:1305 msgid "You are invited to a groupchat" msgstr "" #: gajim/dialogs.py:1308 msgid "$Contact has invited you to join a discussion" msgstr "" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "" #: gajim/dialogs.py:1628 msgid "a video" msgstr "" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 msgid "File Transfer" msgstr "Transferència de Fitxers" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "" #: gajim/dialogs.py:1764 msgid "Encrypting file…" msgstr "" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "" #: gajim/groupchat_control.py:253 #, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "" #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 #, fuzzy msgid "No File Transfer available" msgstr "Transferència de Fitxers" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "" #: gajim/groupchat_control.py:711 msgid "Invalid group chat JID" msgstr "" #: gajim/groupchat_control.py:712 msgid "The group chat JID has not allowed characters." msgstr "" #: gajim/groupchat_control.py:724 #, python-format msgid "Destroying %s" msgstr "" #: gajim/groupchat_control.py:725 msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "" #: gajim/groupchat_control.py:934 msgid "Insert Nickname" msgstr "" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 msgid "and authenticated" msgstr "" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 msgid "and NOT authenticated" msgstr "" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" #: gajim/groupchat_control.py:1157 msgid "Conversation with " msgstr "" #: gajim/groupchat_control.py:1159 msgid "Continued conversation" msgstr "" #: gajim/groupchat_control.py:1525 #, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "Qualsevol membre pot veure el teu JID" #: gajim/groupchat_control.py:1556 msgid "Room now shows unavailable members" msgstr "" #: gajim/groupchat_control.py:1558 msgid "Room now does not show unavailable members" msgstr "" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "" #: gajim/groupchat_control.py:1576 msgid "Room is now fully anonymous" msgstr "" #: gajim/groupchat_control.py:1615 #, python-format msgid "Ping? (%s)" msgstr "" #: gajim/groupchat_control.py:1618 #, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 msgid "Error." msgstr "" #: gajim/groupchat_control.py:1845 #, python-format msgid "You (%s) joined the room" msgstr "" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, python-format msgid "%(jid)s has been invited in this room" msgstr "" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "" #: gajim/groupchat_control.py:1879 msgid "A new room has been created" msgstr "" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "" #: gajim/groupchat_control.py:1950 msgid "affiliation changed" msgstr "" #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "" #: gajim/groupchat_control.py:2034 #, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "" #: gajim/groupchat_control.py:2038 #, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "" #: gajim/groupchat_control.py:2067 #, python-format msgid "%s has joined the group chat" msgstr "" #: gajim/groupchat_control.py:2374 #, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "" #: gajim/groupchat_control.py:2376 msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "" #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 msgid "_Do not ask me again" msgstr "" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "" #: gajim/chat_control.py:389 msgid "Show a list of formattings" msgstr "Mostra una llista de formats" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 msgid "This contact does not support HTML" msgstr "" #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "" #: gajim/chat_control.py:660 #, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "" #: gajim/chat_control.py:1205 #, python-format msgid "Pong! (%s seconds)" msgstr "" #: gajim/chat_control.py:1313 #, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" #: gajim/chat_control.py:1416 #, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "" #: gajim/chat_control.py:1471 msgid "File transfer" msgstr "" #: gajim/chat_control.py:1474 msgid "Size" msgstr "" #: gajim/chat_control.py:1476 msgid "Accept" msgstr "" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Entra-hi" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 msgid "Remote contact stopped transfer" msgstr "" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 msgid "Error opening file" msgstr "" #: gajim/application.py:68 msgid "Show the application's version" msgstr "" #: gajim/application.py:75 msgid "Show only critical errors" msgstr "" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 msgid "Use defined profile in configuration directory" msgstr "" #: gajim/application.py:105 msgid "Set configuration directory" msgstr "" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 msgid "Show all warnings" msgstr "" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 msgid "Pops up a window with the next pending event" msgstr "" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 msgid "Start a new chat" msgstr "" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 msgid "Groupchats" msgstr "Grups de xat" #: gajim/roster_window.py:2056 msgid "Authorization sent" msgstr "" #: gajim/roster_window.py:2057 #, python-format msgid "\"%s\" will now see your status." msgstr "" #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "" #: gajim/roster_window.py:2095 msgid "Authorization removed" msgstr "" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "" #: gajim/roster_window.py:2120 msgid "OpenPGP is not usable" msgstr "" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "Avançat" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "" #: gajim/roster_window.py:2426 msgid "Are you sure you want to quit Gajim?" msgstr "" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "" #: gajim/roster_window.py:2514 msgid "You have running file transfers" msgstr "" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "" #: gajim/roster_window.py:2547 msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "" #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "" #: gajim/roster_window.py:2829 msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" #: gajim/roster_window.py:2832 msgid "Transports will be removed" msgstr "" #: gajim/roster_window.py:2837 #, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" #: gajim/roster_window.py:2891 msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "" #: gajim/roster_window.py:2893 msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" #: gajim/roster_window.py:2939 msgid "Rename Contact" msgstr "" #: gajim/roster_window.py:2940 #, python-format msgid "Enter a new nickname for contact %s" msgstr "" #: gajim/roster_window.py:2947 msgid "Rename Group" msgstr "" #: gajim/roster_window.py:2948 #, python-format msgid "Enter a new name for group %s" msgstr "" #: gajim/roster_window.py:2993 msgid "Remove Group" msgstr "" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "" #: gajim/roster_window.py:2995 msgid "Also remove all contacts in this group from your roster" msgstr "" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "" #: gajim/roster_window.py:3448 msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" #: gajim/roster_window.py:3454 msgid "Do you want to continue?" msgstr "" #: gajim/roster_window.py:3458 msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "" #: gajim/roster_window.py:3465 msgid "Contacts will be removed from your roster" msgstr "" #: gajim/roster_window.py:3470 #, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" #: gajim/roster_window.py:3529 msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "" #: gajim/roster_window.py:3531 #, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" #: gajim/roster_window.py:3550 msgid "No account available" msgstr "" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "" #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "" #: gajim/roster_window.py:4180 msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" #: gajim/roster_window.py:4276 msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "" #: gajim/roster_window.py:4278 msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" #: gajim/roster_window.py:4400 msgid "Invalid file URI:" msgstr "" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Envia _Fitxer" #: gajim/roster_window.py:4412 #, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "" msgstr[1] "" #: gajim/roster_window.py:4552 #, python-format msgid "Send %(from)s to %(to)s" msgstr "" #: gajim/roster_window.py:4565 #, python-format msgid "Make %s first contact" msgstr "" #: gajim/roster_window.py:4570 #, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "_Canvia Missatge d'Estat" #: gajim/roster_window.py:4965 msgid "Publish Tune" msgstr "" #: gajim/roster_window.py:4976 msgid "Publish Location" msgstr "" #: gajim/roster_window.py:4988 msgid "Configure Services…" msgstr "" #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 msgid "Send Group M_essage" msgstr "" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "" #: gajim/roster_window.py:5135 msgid "To all online users" msgstr "" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "Con_vida a" #: gajim/roster_window.py:5299 msgid "_Manage Contacts" msgstr "" #: gajim/roster_window.py:5305 msgid "Edit _Groups…" msgstr "" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "" #: gajim/roster_window.py:5370 msgid "_Reconnect" msgstr "" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 msgid "_Disconnect" msgstr "_Desconnecta" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Historial" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Gestor d'Històric" #: gajim/roster_window.py:5475 msgid "_Join New Group Chat" msgstr "" #: gajim/config.py:359 msgid "Ban List" msgstr "" #: gajim/config.py:360 msgid "Member List" msgstr "" #: gajim/config.py:360 msgid "Owner List" msgstr "" #: gajim/config.py:361 msgid "Administrator List" msgstr "" #: gajim/config.py:435 msgid "Reason" msgstr "" #: gajim/config.py:442 msgid "Nick" msgstr "" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "" #: gajim/config.py:478 msgid "Banning…" msgstr "" #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" #: gajim/config.py:482 msgid "Adding Member…" msgstr "" #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" #: gajim/config.py:485 msgid "Adding Owner…" msgstr "" #: gajim/config.py:486 msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "" #: gajim/config.py:488 msgid "Adding Administrator…" msgstr "" #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" #: gajim/config.py:490 msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "" #: gajim/config.py:608 msgid "Account is disabled" msgstr "" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Escriu la teva contrasenya per al compte %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Desa la contrasenya" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "" #: gajim/config.py:652 #, python-format msgid "Connection to server %s failed" msgstr "" #: gajim/config.py:653 msgid "What would you like to do?" msgstr "" #: gajim/config.py:654 msgid "Remove only from Gajim" msgstr "" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "" #: gajim/config.py:745 msgid "Attention Message Received" msgstr "" #: gajim/config.py:746 msgid "First Message Received" msgstr "" #: gajim/config.py:747 msgid "Next Message Received Focused" msgstr "" #: gajim/config.py:748 msgid "Next Message Received Unfocused" msgstr "" #: gajim/config.py:749 msgid "Contact Connected" msgstr "" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "" #: gajim/config.py:751 msgid "Message Sent" msgstr "" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 msgid "?Group Chat Contact Affiliation:None" msgstr "" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 msgid "Member" msgstr "" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 msgid "Administrator" msgstr "" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 msgid "Owner" msgstr "" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr "" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr "" #: gajim/tooltips.py:574 msgid "Connected" msgstr "" #: gajim/tooltips.py:576 msgid "Disconnected" msgstr "Desconnectat" #: gajim/tooltips.py:624 msgid "?Noun:Download" msgstr "" #: gajim/tooltips.py:630 msgid "?Noun:Upload" msgstr "" #: gajim/tooltips.py:637 msgid "Type: " msgstr "" #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "" #: gajim/tooltips.py:645 msgid "Status: " msgstr "" #: gajim/tooltips.py:647 msgid "Description: " msgstr "" #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "" #: gajim/tooltips.py:676 #, fuzzy msgid "?transfer status:Paused" msgstr "?user status:_Disponible" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "?user status:_Disponible" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Disponible per parlar" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Absent" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Ocupat" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Desconnectat" #: gajim/statusicon.py:210 msgid "_Change Status Message…" msgstr "_Canvia Missatge d'Estat..." #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "" #: gajim/statusicon.py:306 msgid "_Manage Bookmarks…" msgstr "" #: gajim/statusicon.py:322 msgid "Hide _Roster" msgstr "" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "" #: gajim/dataforms_widget.py:584 msgid "Unable to load image" msgstr "" #: gajim/dataforms_widget.py:586 #, python-format msgid "Media type not supported: %s" msgstr "" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" #: gajim/disco.py:121 msgid "Others" msgstr "" #: gajim/disco.py:125 msgid "Conference" msgstr "" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "" #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "" #: gajim/disco.py:726 gajim/disco.py:736 msgid "Invalid Server Name" msgstr "" #: gajim/disco.py:794 #, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "" #: gajim/disco.py:841 msgid "Browse" msgstr "" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "" #: gajim/disco.py:1248 msgid "Execute Command" msgstr "" #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 msgid "Join" msgstr "" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Edita" #: gajim/disco.py:1450 #, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "" #: gajim/disco.py:1649 msgid "Users" msgstr "" #: gajim/disco.py:1657 msgid "Description" msgstr "" #: gajim/disco.py:1665 msgid "Id" msgstr "" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 msgid "_Bookmark" msgstr "Adreça d'interès" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "" #: gajim/disco.py:1722 #, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "" #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "" #: gajim/disco.py:1929 msgid "Subscribed" msgstr "" #: gajim/disco.py:1938 msgid "Node" msgstr "" #: gajim/disco.py:2005 msgid "New post" msgstr "" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "" #: gajim/disco.py:2017 msgid "_Unsubscribe" msgstr "" #: gajim/conversation_textview.py:320 msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" #: gajim/conversation_textview.py:541 msgid "_Quote" msgstr "" #: gajim/conversation_textview.py:549 #, python-format msgid "_Actions for \"%s\"" msgstr "" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "" #: gajim/conversation_textview.py:884 msgid "Invalid URL" msgstr "" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "" msgstr[1] "" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Entrada següent" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Envia missatge" #: gajim/message_window.py:243 msgid "You are going to close several tabs" msgstr "" #: gajim/message_window.py:244 msgid "Do you really want to close them all?" msgstr "" #: gajim/message_window.py:520 msgid "?Noun:Chats" msgstr "" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "" #: gajim/message_window.py:530 msgid "Messages" msgstr "" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 msgid "Unable to join group chat" msgstr "" #: gajim/gui_interface.py:170 #, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "" #: gajim/gui_interface.py:194 #, python-format msgid "Do you accept this request on account %s?" msgstr "" #: gajim/gui_interface.py:197 #, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 msgid "Connection Failed" msgstr "" #: gajim/gui_interface.py:327 #, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "" #: gajim/gui_interface.py:342 #, python-format msgid "%s is full" msgstr "" #: gajim/gui_interface.py:351 #, python-format msgid "You are banned from group chat %s." msgstr "" #: gajim/gui_interface.py:358 #, python-format msgid "Remote server %s does not exist." msgstr "" #: gajim/gui_interface.py:362 #, python-format msgid "Group chat %s does not exist." msgstr "" #: gajim/gui_interface.py:365 msgid "Group chat creation is not permitted." msgstr "" #: gajim/gui_interface.py:367 msgid "Unable to join groupchat" msgstr "" #: gajim/gui_interface.py:368 #, python-format msgid "You must use your registered nickname in %s." msgstr "" #: gajim/gui_interface.py:373 #, python-format msgid "You are not in the members list in groupchat %s." msgstr "" #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, python-format msgid "Error %(code)s: %(msg)s" msgstr "" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "" #: gajim/gui_interface.py:503 gajim/notify.py:194 msgid "Subscription request" msgstr "" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "" #: gajim/gui_interface.py:530 #, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "" #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "" #: gajim/gui_interface.py:539 msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" #: gajim/gui_interface.py:560 gajim/notify.py:194 msgid "Unsubscribed" msgstr "" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, python-brace-format msgid "You are invited to {room} by {user}" msgstr "" #: gajim/gui_interface.py:658 msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "" #: gajim/gui_interface.py:663 msgid "Wrong passphrase" msgstr "" #: gajim/gui_interface.py:668 msgid "Wrong OpenPGP passphrase" msgstr "" #: gajim/gui_interface.py:682 msgid "Certificate Passphrase Required" msgstr "" #: gajim/gui_interface.py:683 #, python-format msgid "Enter the certificate passphrase for account %s" msgstr "" #: gajim/gui_interface.py:706 msgid "Untrusted OpenPGP key" msgstr "" #: gajim/gui_interface.py:706 msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "" #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "" #: gajim/gui_interface.py:1013 msgid "File Transfer Failed" msgstr "" #: gajim/gui_interface.py:1035 #, python-format msgid "%(filename)s received from %(name)s." msgstr "" #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "" #: gajim/gui_interface.py:1043 #, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "" #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "" #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "" #: gajim/gui_interface.py:1064 #, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "" #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "" #: gajim/gui_interface.py:1178 msgid "Please type a new username for your local account" msgstr "" #: gajim/gui_interface.py:1201 msgid "Resource Conflict" msgstr "" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "" #: gajim/gui_interface.py:1259 #, python-format msgid "%s wants to start a voice chat." msgstr "" #: gajim/gui_interface.py:1261 msgid "Voice Chat Request" msgstr "" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 msgid "Certificate Already in File" msgstr "" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" #: gajim/gui_interface.py:1351 #, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "" #: gajim/gui_interface.py:1354 #, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "" #: gajim/gui_interface.py:1362 #, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, fuzzy, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" "Afegir aquest certificat a la llista de certificats confiables.\n" "Hash SHA1 del certificat:\n" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "" #: gajim/gui_interface.py:1380 #, python-format msgid "SSL Certificate Verification for %s" msgstr "" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 msgid "Insecure connection" msgstr "" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "" #: gajim/gui_interface.py:1489 msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "" #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "" #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Uneix-te al xat en grup" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 msgid "You cannot join a group chat while you are invisible" msgstr "" #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "" #: gajim/gui_interface.py:2824 #, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "" #: gajim/gui_interface.py:2841 msgid "OpenPGP key expired" msgstr "" #: gajim/gui_interface.py:2842 #, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "" #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "" #: gajim/gui_interface.py:2853 msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "" #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "" #: gajim/htmltextview.py:532 msgid "Loading" msgstr "" #: gajim/atom_window.py:123 #, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "" msgstr[1] "" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "Has rebut una nova entrada:" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "Comandes Ad-Hoc - Gajim" #: gajim/adhoc_commands.py:326 msgid "Cancel confirmation" msgstr "" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "" #: gajim/adhoc_commands.py:422 #, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "El Contacte ha entrat" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 msgid "Contact Changed Status" msgstr "" #: gajim/notify.py:203 msgid "Open" msgstr "" #: gajim/notify.py:270 msgid "New E-mail" msgstr "" #: gajim/dialog_messages.py:32 msgid "You can not start a new conversation unless you are connected." msgstr "" #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 msgid "Invalid JID" msgstr "" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "" #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "" #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "" #: gajim/dialog_messages.py:53 msgid "To disable the account, you must be disconnected." msgstr "" #: gajim/dialog_messages.py:57 msgid "Invalid Form" msgstr "" #: gajim/dialog_messages.py:58 msgid "The form is not filled correctly." msgstr "" #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Invisible" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "" #: gajim/dialog_messages.py:72 msgid "JID already in list" msgstr "" #: gajim/dialog_messages.py:73 msgid "The JID you entered is already in the list. Choose another one." msgstr "" #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "" #: gajim/dialog_messages.py:78 #, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "" #: gajim/dialog_messages.py:83 msgid "Wrong Custom Hostname" msgstr "" #: gajim/dialog_messages.py:84 #, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "" #: gajim/dialog_messages.py:88 msgid "Error while removing privacy list" msgstr "" #: gajim/dialog_messages.py:89 #, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" #: gajim/dialog_messages.py:95 msgid "Invisibility not supported" msgstr "" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "" #: gajim/dialog_messages.py:100 msgid "Unregister failed" msgstr "" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "" #: gajim/dialog_messages.py:105 msgid "Registration succeeded" msgstr "" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 msgid "Registration failed" msgstr "" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Uneix-te al xat en grup" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "" #: gajim/dialog_messages.py:126 msgid "Wrong host" msgstr "" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 msgid "Could not request upload slot" msgstr "" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 msgid "Could not open file" msgstr "" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 msgid "Server returned unsecure transport (HTTP)" msgstr "" #: gajim/dialog_messages.py:161 msgid "Could not upload file" msgstr "" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 msgid "Encryption Error" msgstr "" #: gajim/dialog_messages.py:172 msgid "For the chosen encryption there is no encryption method available" msgstr "" #: gajim/dialog_messages.py:176 msgid "Avatar upload failed" msgstr "" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "" #: gajim/gajim_remote.py:77 msgid "Shows a help on specific command" msgstr "" #: gajim/gajim_remote.py:80 msgid "command" msgstr "" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "" #: gajim/gajim_remote.py:85 msgid "Lists all contacts in roster, one for each line" msgstr "" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "Compte" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "" #: gajim/gajim_remote.py:97 msgid "Changes the status of account(s)" msgstr "" #: gajim/gajim_remote.py:100 msgid "?CLI:status" msgstr "" #: gajim/gajim_remote.py:100 msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "" #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "missatge" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" #: gajim/gajim_remote.py:108 msgid "Changes the priority of account(s)" msgstr "" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "Priori_tat:" #: gajim/gajim_remote.py:110 msgid "priority you want to give to the account" msgstr "" #: gajim/gajim_remote.py:112 msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" #: gajim/gajim_remote.py:118 msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "" #: gajim/gajim_remote.py:131 msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" #: gajim/gajim_remote.py:136 msgid "subject" msgstr "" #: gajim/gajim_remote.py:136 msgid "message subject" msgstr "" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "" #: gajim/gajim_remote.py:147 msgid "JID of the room that will receive the message" msgstr "" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "" #: gajim/gajim_remote.py:168 msgid "file" msgstr "" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "" #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "" #: gajim/gajim_remote.py:181 msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "" #: gajim/gajim_remote.py:188 msgid "key" msgstr "" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" #: gajim/gajim_remote.py:221 msgid "Returns number of unread messages" msgstr "" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "" #: gajim/gajim_remote.py:229 msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" #: gajim/gajim_remote.py:235 msgid "Change the avatar" msgstr "" #: gajim/gajim_remote.py:237 msgid "Picture to use" msgstr "" #: gajim/gajim_remote.py:238 msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" #: gajim/gajim_remote.py:245 msgid "Check if Gajim is running" msgstr "" #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "" #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "" #: gajim/gajim_remote.py:383 #, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" #: gajim/gajim_remote.py:453 #, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" #: gajim/gajim_remote.py:458 #, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "" #: gajim/common/fuzzyclock.py:36 msgid "one" msgstr "" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "" #: gajim/common/fuzzyclock.py:36 msgid "three" msgstr "" #: gajim/common/fuzzyclock.py:36 msgid "four" msgstr "" #: gajim/common/fuzzyclock.py:37 msgid "five" msgstr "" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "" #: gajim/common/fuzzyclock.py:37 msgid "seven" msgstr "" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "" #: gajim/common/fuzzyclock.py:37 msgid "nine" msgstr "" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "" #: gajim/common/fuzzyclock.py:38 msgid "eleven" msgstr "" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "" #: gajim/common/fuzzyclock.py:46 #, python-format msgid "five past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:47 #, python-format msgid "ten past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:48 #, python-format msgid "quarter past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:49 #, python-format msgid "twenty past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:50 #, python-format msgid "twenty five past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:52 #, python-format msgid "twenty five to %(1)s" msgstr "" #: gajim/common/fuzzyclock.py:53 #, python-format msgid "twenty to %(1)s" msgstr "" #: gajim/common/fuzzyclock.py:54 #, python-format msgid "quarter to %(1)s" msgstr "" #: gajim/common/fuzzyclock.py:55 #, python-format msgid "ten to %(1)s" msgstr "" #: gajim/common/fuzzyclock.py:56 #, python-format msgid "five to %(1)s" msgstr "" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "" #: gajim/common/fuzzyclock.py:63 msgid "Morning" msgstr "" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "" #: gajim/common/fuzzyclock.py:65 msgid "Noon" msgstr "" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "" #: gajim/common/fuzzyclock.py:67 msgid "Evening" msgstr "" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, python-format msgid "%s is a directory but should be a file" msgstr "" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Crea nou missatge" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 msgid "Room has been destroyed" msgstr "" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "" #: gajim/common/connection_handlers_events.py:598 #, python-format msgid "Unknown SSL error: %d" msgstr "" #: gajim/common/connection_handlers_events.py:990 #, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "" msgstr[1] "" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s han entrat" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "" #: gajim/common/contacts.py:427 msgid "Not in roster" msgstr "" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "" #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "" #: gajim/common/config.py:87 msgid "$S (Away as a result of being idle more than $T min)" msgstr "" #: gajim/common/config.py:87 msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "" #: gajim/common/config.py:90 msgid "$S (Not available as a result of being idle more than $T min)" msgstr "" #: gajim/common/config.py:90 msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" #: gajim/common/config.py:93 msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 msgid "Contact signed in notification color." msgstr "" #: gajim/common/config.py:100 msgid "Contact signout notification color" msgstr "" #: gajim/common/config.py:101 msgid "New message notification color." msgstr "" #: gajim/common/config.py:102 msgid "File transfer request notification color." msgstr "" #: gajim/common/config.py:103 msgid "File transfer error notification color." msgstr "" #: gajim/common/config.py:104 msgid "File transfer complete or stopped notification color." msgstr "" #: gajim/common/config.py:105 msgid "Groupchat invitation notification color" msgstr "" #: gajim/common/config.py:106 msgid "Background color of status changed notification" msgstr "" #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "" #: gajim/common/config.py:109 msgid "default" msgstr "" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "" #: gajim/common/config.py:122 msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "" #: gajim/common/config.py:174 msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" #: gajim/common/config.py:177 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "" #: gajim/common/config.py:185 #, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "" #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "" #: gajim/common/config.py:194 msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" #: gajim/common/config.py:195 msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" #: gajim/common/config.py:196 msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" #: gajim/common/config.py:199 msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "" #: gajim/common/config.py:202 msgid "Notify of events in the notification area." msgstr "" #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "" #: gajim/common/config.py:210 msgid "Show tabbed notebook border in chat windows?" msgstr "" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "" #: gajim/common/config.py:224 msgid "Preview new messages in notification popup?" msgstr "" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" #: gajim/common/config.py:228 msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" #: gajim/common/config.py:231 msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "" #: gajim/common/config.py:238 msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" #: gajim/common/config.py:239 msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "" #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "" #: gajim/common/config.py:245 msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" #: gajim/common/config.py:249 msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "" #: gajim/common/config.py:252 msgid "If true, pressing the escape key closes a tab/window." msgstr "" #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "" #: gajim/common/config.py:255 msgid "Hides the group chat occupants list in group chat window." msgstr "" #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "" #: gajim/common/config.py:258 msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "" #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "" #: gajim/common/config.py:260 msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" #: gajim/common/config.py:261 msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" #: gajim/common/config.py:262 msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" #: gajim/common/config.py:263 msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" #: gajim/common/config.py:264 msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" #: gajim/common/config.py:266 msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" #: gajim/common/config.py:269 msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "" #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" #: gajim/common/config.py:272 msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "" #: gajim/common/config.py:325 msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" #: gajim/common/config.py:326 msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "" #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "" #: gajim/common/config.py:337 msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "" #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "" #: gajim/common/config.py:354 msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "" #: gajim/common/config.py:385 msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "" #: gajim/common/config.py:386 msgid "Allow Gajim to send your local time." msgstr "" #: gajim/common/config.py:389 msgid "Message that is sent to contacts you want to add" msgstr "" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 msgid "Latest token for OAuth 2.0 authentication." msgstr "" #: gajim/common/config.py:393 msgid "client_id for OAuth 2.0 authentication." msgstr "" #: gajim/common/config.py:394 msgid "redirect_url for OAuth 2.0 authentication." msgstr "" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 msgid "Language for which misspelled words will be checked" msgstr "" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" #: gajim/common/config.py:442 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "" #: gajim/common/config.py:452 msgid "Back soon" msgstr "" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "" #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "" #: gajim/common/config.py:454 msgid "Movie" msgstr "" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "" #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "" #: gajim/common/config.py:455 msgid "I'm working." msgstr "" #: gajim/common/config.py:456 msgid "Phone" msgstr "" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "" #: gajim/common/config.py:457 msgid "Out" msgstr "" #: gajim/common/config.py:457 msgid "I'm out enjoying life." msgstr "" #: gajim/common/config.py:468 msgid "I'm available." msgstr "" #: gajim/common/config.py:469 msgid "I'm free for chat." msgstr "" #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "" #: gajim/common/config.py:471 msgid "I'm not available." msgstr "" #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "" #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "" #: gajim/common/config.py:490 msgid "Tor" msgstr "" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "" #: gajim/common/const.py:205 msgid "Doing Chores" msgstr "" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "" #: gajim/common/const.py:207 msgid "Cleaning" msgstr "" #: gajim/common/const.py:208 msgid "Cooking" msgstr "" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "" #: gajim/common/const.py:212 msgid "Gardening" msgstr "" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "" #: gajim/common/const.py:214 msgid "Walking the Dog" msgstr "" #: gajim/common/const.py:216 msgid "Drinking" msgstr "" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "" #: gajim/common/const.py:227 msgid "Exercising" msgstr "" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "" #: gajim/common/const.py:229 msgid "Dancing" msgstr "" #: gajim/common/const.py:230 msgid "Hiking" msgstr "" #: gajim/common/const.py:231 msgid "Jogging" msgstr "" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "" #: gajim/common/const.py:233 msgid "Running" msgstr "" #: gajim/common/const.py:234 msgid "Skiing" msgstr "" #: gajim/common/const.py:235 msgid "Swimming" msgstr "" #: gajim/common/const.py:236 msgid "Working out" msgstr "" #: gajim/common/const.py:238 msgid "Grooming" msgstr "" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "" #: gajim/common/const.py:242 msgid "Shaving" msgstr "" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Inactiva" #: gajim/common/const.py:249 msgid "Day Off" msgstr "" #: gajim/common/const.py:250 msgid "Hanging out" msgstr "" #: gajim/common/const.py:251 msgid "Hiding" msgstr "" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "" #: gajim/common/const.py:253 msgid "Praying" msgstr "" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "" #: gajim/common/const.py:256 msgid "Thinking" msgstr "" #: gajim/common/const.py:258 msgid "Relaxing" msgstr "" #: gajim/common/const.py:259 msgid "Fishing" msgstr "" #: gajim/common/const.py:260 msgid "Gaming" msgstr "" #: gajim/common/const.py:261 msgid "Going out" msgstr "" #: gajim/common/const.py:262 msgid "Partying" msgstr "" #: gajim/common/const.py:263 msgid "Reading" msgstr "" #: gajim/common/const.py:264 msgid "Rehearsing" msgstr "" #: gajim/common/const.py:265 msgid "Shopping" msgstr "" #: gajim/common/const.py:266 msgid "Smoking" msgstr "" #: gajim/common/const.py:267 msgid "Socializing" msgstr "" #: gajim/common/const.py:268 msgid "Sunbathing" msgstr "" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "" #: gajim/common/const.py:270 msgid "Watching a Movie" msgstr "" #: gajim/common/const.py:272 msgid "Talking" msgstr "" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "" #: gajim/common/const.py:274 msgid "On the Phone" msgstr "" #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "" #: gajim/common/const.py:277 msgid "Traveling" msgstr "" #: gajim/common/const.py:278 msgid "Commuting" msgstr "" #: gajim/common/const.py:280 msgid "Driving" msgstr "" #: gajim/common/const.py:281 msgid "In a Car" msgstr "" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "" #: gajim/common/const.py:283 msgid "On a Plane" msgstr "" #: gajim/common/const.py:284 msgid "On a Train" msgstr "" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "" #: gajim/common/const.py:286 msgid "Walking" msgstr "" #: gajim/common/const.py:289 msgid "Coding" msgstr "" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "" #: gajim/common/const.py:291 msgid "Studying" msgstr "" #: gajim/common/const.py:292 msgid "Writing" msgstr "" #: gajim/common/const.py:295 msgid "Afraid" msgstr "" #: gajim/common/const.py:296 msgid "Amazed" msgstr "" #: gajim/common/const.py:297 msgid "Amorous" msgstr "" #: gajim/common/const.py:298 msgid "Angry" msgstr "" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "" #: gajim/common/const.py:300 msgid "Anxious" msgstr "" #: gajim/common/const.py:301 msgid "Aroused" msgstr "" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "" #: gajim/common/const.py:303 msgid "Bored" msgstr "" #: gajim/common/const.py:304 msgid "Brave" msgstr "" #: gajim/common/const.py:305 msgid "Calm" msgstr "" #: gajim/common/const.py:306 msgid "Cautious" msgstr "" #: gajim/common/const.py:307 msgid "Cold" msgstr "" #: gajim/common/const.py:308 msgid "Confident" msgstr "" #: gajim/common/const.py:309 msgid "Confused" msgstr "" #: gajim/common/const.py:310 msgid "Contemplative" msgstr "" #: gajim/common/const.py:311 msgid "Contented" msgstr "" #: gajim/common/const.py:312 msgid "Cranky" msgstr "" #: gajim/common/const.py:313 msgid "Crazy" msgstr "" #: gajim/common/const.py:314 msgid "Creative" msgstr "" #: gajim/common/const.py:315 msgid "Curious" msgstr "" #: gajim/common/const.py:316 msgid "Dejected" msgstr "" #: gajim/common/const.py:317 msgid "Depressed" msgstr "" #: gajim/common/const.py:318 msgid "Disappointed" msgstr "" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "" #: gajim/common/const.py:320 msgid "Dismayed" msgstr "" #: gajim/common/const.py:321 msgid "Distracted" msgstr "" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "" #: gajim/common/const.py:323 msgid "Envious" msgstr "" #: gajim/common/const.py:324 msgid "Excited" msgstr "" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "" #: gajim/common/const.py:327 msgid "Grateful" msgstr "" #: gajim/common/const.py:328 msgid "Grieving" msgstr "" #: gajim/common/const.py:329 msgid "Grumpy" msgstr "" #: gajim/common/const.py:330 msgid "Guilty" msgstr "" #: gajim/common/const.py:331 msgid "Happy" msgstr "" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "" #: gajim/common/const.py:333 msgid "Hot" msgstr "" #: gajim/common/const.py:334 msgid "Humbled" msgstr "" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "" #: gajim/common/const.py:336 msgid "Hungry" msgstr "" #: gajim/common/const.py:337 msgid "Hurt" msgstr "" #: gajim/common/const.py:338 msgid "Impressed" msgstr "" #: gajim/common/const.py:339 msgid "In Awe" msgstr "" #: gajim/common/const.py:340 msgid "In Love" msgstr "" #: gajim/common/const.py:341 msgid "Indignant" msgstr "" #: gajim/common/const.py:342 msgid "Interested" msgstr "" #: gajim/common/const.py:343 msgid "Intoxicated" msgstr "" #: gajim/common/const.py:344 msgid "Invincible" msgstr "" #: gajim/common/const.py:345 msgid "Jealous" msgstr "" #: gajim/common/const.py:346 msgid "Lonely" msgstr "" #: gajim/common/const.py:347 msgid "Lost" msgstr "" #: gajim/common/const.py:348 msgid "Lucky" msgstr "" #: gajim/common/const.py:349 msgid "Mean" msgstr "" #: gajim/common/const.py:350 msgid "Moody" msgstr "" #: gajim/common/const.py:351 msgid "Nervous" msgstr "" #: gajim/common/const.py:352 msgid "Neutral" msgstr "" #: gajim/common/const.py:353 msgid "Offended" msgstr "" #: gajim/common/const.py:354 msgid "Outraged" msgstr "" #: gajim/common/const.py:355 msgid "Playful" msgstr "" #: gajim/common/const.py:356 msgid "Proud" msgstr "" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "" #: gajim/common/const.py:358 msgid "Relieved" msgstr "" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "" #: gajim/common/const.py:360 msgid "Restless" msgstr "" #: gajim/common/const.py:361 msgid "Sad" msgstr "" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "" #: gajim/common/const.py:363 msgid "Satisfied" msgstr "" #: gajim/common/const.py:364 msgid "Serious" msgstr "" #: gajim/common/const.py:365 msgid "Shocked" msgstr "" #: gajim/common/const.py:366 msgid "Shy" msgstr "" #: gajim/common/const.py:367 msgid "Sick" msgstr "" #: gajim/common/const.py:368 msgid "Sleepy" msgstr "" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "" #: gajim/common/const.py:370 msgid "Stressed" msgstr "" #: gajim/common/const.py:371 msgid "Strong" msgstr "" #: gajim/common/const.py:372 msgid "Surprised" msgstr "" #: gajim/common/const.py:373 msgid "Thankful" msgstr "" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "" #: gajim/common/const.py:375 msgid "Tired" msgstr "" #: gajim/common/const.py:376 msgid "Undefined" msgstr "" #: gajim/common/const.py:377 msgid "Weak" msgstr "" #: gajim/common/const.py:378 msgid "Worried" msgstr "" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 msgid "alt" msgstr "" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 msgid "bearing" msgstr "" #: gajim/common/const.py:386 msgid "building" msgstr "" #: gajim/common/const.py:387 msgid "country" msgstr "" #: gajim/common/const.py:388 msgid "countrycode" msgstr "" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 msgid "description" msgstr "" #: gajim/common/const.py:391 msgid "error" msgstr "" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 msgid "lon" msgstr "" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 msgid "room" msgstr "" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "" #: gajim/common/const.py:412 msgid "Unable to decode issuer public key" msgstr "" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "" #: gajim/common/const.py:430 msgid "Invalid CA certificate" msgstr "" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "" #: gajim/common/connection.py:740 #, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "" #: gajim/common/connection.py:1090 #, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "" #: gajim/common/connection.py:1093 #, python-format msgid "Could not connect to \"%(host)s\"" msgstr "" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "" #: gajim/common/connection.py:1100 #, python-format msgid "Server replied: %s" msgstr "" #: gajim/common/connection.py:1115 msgid "Connection to proxy failed" msgstr "" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, python-format msgid "Could not connect to account %s" msgstr "" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "" #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "" #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "" #: gajim/common/dbus_support.py:54 msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "" #: gajim/common/dbus_support.py:57 msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "" #: gajim/common/multimedia_helpers.py:49 msgid "Default device" msgstr "" #: gajim/common/multimedia_helpers.py:70 msgid "Audio test" msgstr "" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, python-format msgid "ALSA: %s" msgstr "" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, python-format msgid "Pulse: %s" msgstr "" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 msgid "Screen" msgstr "" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, python-format msgid "%s configuration error" msgstr "" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "" #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "" #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "" #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "" #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "Ocupat" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "_No Disponible" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "" #: gajim/common/helpers.py:273 msgid "?user status:_Available" msgstr "?user status:_Disponible" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "Desconnectat" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "_Invisible" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "" #: gajim/common/helpers.py:315 msgid "To" msgstr "" #: gajim/common/helpers.py:317 msgid "From" msgstr "" #: gajim/common/helpers.py:319 msgid "Both" msgstr "" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 msgid "Unknown" msgstr "" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Moderadors" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "" #: gajim/common/helpers.py:408 msgid "is composing a message…" msgstr "" #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "" msgstr[1] "" #: gajim/common/helpers.py:1000 #, python-format msgid "from room %s" msgstr "" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, python-format msgid "from user %s" msgstr "" #: gajim/common/helpers.py:1005 #, python-format msgid "from %s" msgstr "" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "" msgstr[1] "" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Voldria afegir-te a la meva llista de contactes." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 msgid "Timeout loading image" msgstr "" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "" #: gajim/common/helpers.py:1383 msgid "PyCURL is not installed" msgstr "" #: gajim/common/helpers.py:1422 msgid "Error loading image" msgstr "" #: gajim/common/configpaths.py:85 #, python-format msgid "%s is a file but it should be a directory" msgstr "" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "" #: gajim/common/exceptions.py:45 #, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" #: gajim/common/exceptions.py:81 #, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "" #: gajim/common/exceptions.py:93 #, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 msgid "Please check if Avahi or Bonjour is installed." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, python-format msgid "Unable to bind to port %d." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:217 msgid "Please check if avahi/bonjour-daemon is running." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, python-format msgid "Could not change status of account \"%s\"" msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:349 msgid "Your message could not be sent." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "" #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, python-format msgid "Error while adding service. %s" msgstr "" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "missatge" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "" #: gajim/common/modules/message.py:164 #, python-format msgid "error: %s" msgstr "" #: gajim/common/modules/httpupload.py:134 msgid "File is empty" msgstr "" #: gajim/common/modules/httpupload.py:137 msgid "File does not exist" msgstr "" #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 msgid "Change status information" msgstr "" #: gajim/common/modules/adhoc_commands.py:113 msgid "Change status" msgstr "" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "" #: gajim/common/modules/adhoc_commands.py:121 msgid "Free for chat" msgstr "Lliure per xatejar" #: gajim/common/modules/adhoc_commands.py:122 msgid "Online" msgstr "Connectat" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "" #: gajim/common/modules/adhoc_commands.py:132 msgid "Presence description:" msgstr "" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "" #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 msgid "Leave Groupchats" msgstr "" #: gajim/common/modules/adhoc_commands.py:231 #, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "" #: gajim/common/modules/adhoc_commands.py:235 msgid "You have not joined a groupchat." msgstr "" #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "" #: gajim/common/modules/adhoc_commands.py:292 msgid "You left the following groupchats:" msgstr "" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" #: gajim/common/modules/roster_item_exchange.py:100 #, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "" #: gajim/common/modules/roster_item_exchange.py:104 msgid "Sent contacts:" msgstr "" #: gajim/data/gui/blocked_contacts_window.ui:13 msgid "Blocked Contacts" msgstr "Contactes blocats" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Editor de Configuració Avançada" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Filtra:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Descripció" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "" "NOTA: Hauries de reiniciar Gajim per a que la configuració tingui " "efecte" #: gajim/data/gui/advanced_configuration_window.ui:161 msgid "_Reset to default" msgstr "_Reinicia a configuració per defecte" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Entra automàticament" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Compte" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Sala:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Contrasenya:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "Afegeix aquesta sala a les adreces d'interès" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "Adreça d'interès" #: gajim/data/gui/join_groupchat_window.ui:339 msgid "Recently used group chats" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 msgid "HTTP Connect" msgstr "Connecta HTTP" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "SOCKS5" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "BOSH" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Gestió de perfils de proxy" #: gajim/data/gui/manage_proxies_window.ui:148 msgid "_Name:" msgstr "_Nom:" #: gajim/data/gui/manage_proxies_window.ui:161 msgid "_Type:" msgstr "_Tipus:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Propietats" #: gajim/data/gui/manage_proxies_window.ui:234 msgid "_BOSH URL:" msgstr "URL BOSH:" #: gajim/data/gui/manage_proxies_window.ui:258 msgid "Proxy _Host:" msgstr "Servidor intermediari:" #: gajim/data/gui/manage_proxies_window.ui:269 msgid "Use HTTP prox_y" msgstr "Utilitza un servidor intermediari d'HTTP" #: gajim/data/gui/manage_proxies_window.ui:288 msgid "Proxy _Port:" msgstr "Port del servidor intermediari:" #: gajim/data/gui/manage_proxies_window.ui:299 msgid "Use proxy auth_entication" msgstr "Fa ús d'autenticació proxy" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "_Nom d'usuari:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "Contrasenya:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Configuració" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Desa la contrasenya" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Canviar contrasenya" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "Registra _les converses" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 msgid "Contact" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:234 msgid "First Name:" msgstr "Nom:" #: gajim/data/gui/zeroconf_information_window.ui:247 msgid "Last Name:" msgstr "Cognom:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "ID de Jabber:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "Correu electrònic:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 msgid "Personal" msgstr "" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "Envia Missatge Privat" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Envia _Fitxer" #: gajim/data/gui/gc_occupants_menu.ui:29 msgid "Occupant Actions" msgstr "Accions Ocupant" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Veu" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Mo_derador" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Membre" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Administra" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "Propietari" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "Fes fora" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Bandeja" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "_Afegeix a llista de contactes" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "_Executa Comanda...." #: gajim/data/gui/tooltip_roster_contact.ui:125 msgid "Idle since:" msgstr "" #: gajim/data/gui/tooltip_roster_contact.ui:151 msgid "Mood:" msgstr "Estat d'Ànim:" #: gajim/data/gui/tooltip_roster_contact.ui:164 msgid "Activity:" msgstr "Activitat:" #: gajim/data/gui/tooltip_roster_contact.ui:178 msgid "Tune:" msgstr "" #: gajim/data/gui/tooltip_roster_contact.ui:191 msgid "Location:" msgstr "" #: gajim/data/gui/tooltip_roster_contact.ui:255 msgid "OpenPGP:" msgstr "" #: gajim/data/gui/tooltip_roster_contact.ui:281 msgid "Subscription:" msgstr "" #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "Estat" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Modifica Compte..." #: gajim/data/gui/atom_entry_window.ui:8 msgid "New entry received" msgstr "S'ha rebut una nova entrada" #: gajim/data/gui/atom_entry_window.ui:92 msgid "Feed name:" msgstr "Nom de feed:" #: gajim/data/gui/atom_entry_window.ui:119 msgid "Entry:" msgstr "Entrada:" #: gajim/data/gui/atom_entry_window.ui:131 msgid "Last modified:" msgstr "Última modificació:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "Entrada següent" #: gajim/data/gui/gc_control_popup_menu.ui:11 msgid "Change _Nickname..." msgstr "Canvia _Nick..." #: gajim/data/gui/gc_control_popup_menu.ui:20 msgid "_Manage Room" msgstr "Gestiona Sala" #: gajim/data/gui/gc_control_popup_menu.ui:31 msgid "Change _Subject..." msgstr "Canvia Tema..." #: gajim/data/gui/gc_control_popup_menu.ui:38 msgid "Configure _Room..." msgstr "Configura Sala..." #: gajim/data/gui/gc_control_popup_menu.ui:52 msgid "_Destroy Room" msgstr "_Destrueix Sala" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "_Minimitza en tancar" #: gajim/data/gui/gc_control_popup_menu.ui:85 msgid "_Request Voice" msgstr "Sol.licita Veu" #: gajim/data/gui/profile_window.ui:67 msgid "Clear Avatar" msgstr "" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Esborra" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 #, fuzzy msgid "Full Name" msgstr "Nom:" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 msgid "Phone No." msgstr "" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 msgid "Birthday" msgstr "" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Pàgina d'inici:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "Correu electrònic:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 msgid "Jabber ID" msgstr "ID de Jabber" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 msgid "Family" msgstr "" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 msgid "Given" msgstr "" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 msgid "Middle" msgstr "" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Prefereix" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 msgid "Suffix" msgstr "" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 msgid "Street" msgstr "" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "_Copia adreça JID/Email" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 msgid "City" msgstr "" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Estat" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 msgid "Postal Code" msgstr "" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "Entrada:" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 msgid "Address" msgstr "" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Configuració" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "S'està creant la composició" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 msgid "Department" msgstr "" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Descripció:" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "1" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Sobre l'aplicació" #: gajim/data/gui/filetransfers.ui:20 msgid "Con_tinue" msgstr "Con_tinua" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Pausa" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Cancel·la" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Obre Carpeta Contenidora" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Transferències de fitxers" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "llista de trasferència de fitxers" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "" "Una llista de les transferències de fitxers actives, completades i aturades" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "Neteja" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "" "Esborra de la llista les transferències completades, cancel.lades o fallides" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Esborra transferència de fitxer de la llista." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "Aquesta acció esborra una única transferència de fitxer de la llista. Si " "està activa, primer s'atura i després s'esborra." #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "" "Cancel.la la transferència seleccionada i esborra els fitxers incomplets." #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Cancel.la la transferència de fitxer." #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Cancel.la la transferència de fitxer seleccionada." #: gajim/data/gui/filetransfers.ui:176 msgid "_Close" msgstr "" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Amaga la finestra" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Notifica'm quan una transferència de fitxer ha acabat" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "Quan una transferència de fitxer acabi mostra una notificació (popup)" #: gajim/data/gui/filetransfers.ui:229 msgid "Shows a list of file transfers between you and others" msgstr "Mostra una llista de transferències de fitxers entre tu i els altres" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Negreta" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Cursiva" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 msgid "Underline" msgstr "Subratllat" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 msgid "Strike" msgstr "Ratllat" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "Color" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 msgid "Font" msgstr "Tipus de lletra" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 msgid "Clear formatting" msgstr "Neteja el format" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Connexió" #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Mostra una llista d'emoticones (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 msgid "Event Type" msgstr "Tipus d'esdeveniment" #: gajim/data/gui/popup_notification_window.ui:100 msgid "Event desc" msgstr "Descripció d'esdeveniment" #: gajim/data/gui/chat_control.ui:44 msgid "1" msgstr "1" #: gajim/data/gui/chat_control.ui:66 msgid "2 abc" msgstr "2 abc" #: gajim/data/gui/chat_control.ui:87 msgid "3 def" msgstr "3 def" #: gajim/data/gui/chat_control.ui:108 msgid "4 ghi" msgstr "4 ghi" #: gajim/data/gui/chat_control.ui:129 msgid "5 jkl" msgstr "5 jkl" #: gajim/data/gui/chat_control.ui:150 msgid "6 mno" msgstr "6 mno" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "7 pqrs" #: gajim/data/gui/chat_control.ui:191 msgid "8 tuv" msgstr "8 tuv" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "9 wxyz" #: gajim/data/gui/chat_control.ui:232 msgid "*" msgstr "*" #: gajim/data/gui/chat_control.ui:252 msgid "0" msgstr "0" #: gajim/data/gui/chat_control.ui:272 msgid "#" msgstr "#" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "#" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 msgid "Always" msgstr "Sempre" #: gajim/data/gui/mam_preferences.ui:18 msgid "Roster" msgstr "Llista" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 msgid "Never" msgstr "Mai" #: gajim/data/gui/mam_preferences.ui:111 msgid "Default:" msgstr "Per defecte:" #: gajim/data/gui/mam_preferences.ui:203 msgid "Archive" msgstr "" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Recurs:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "" #: gajim/data/gui/vcard_information_window.ui:106 msgid "Client" msgstr "" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 msgid "System" msgstr "" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "El Contacte ha entrat" #: gajim/data/gui/vcard_information_window.ui:240 msgid "User avatar" msgstr "" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Configura" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 msgid "Ask" msgstr "" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "_Subscripció" #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 msgid "Personal Info" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "" #: gajim/data/gui/preferences_window.ui:38 msgid "Use default applications" msgstr "Aplicacions per defecte" #: gajim/data/gui/preferences_window.ui:41 msgid "Custom" msgstr "Personalitzat" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 msgid "All chat states" msgstr "Tots els estats del xat" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 msgid "Composing only" msgstr "Component només" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Inhabilitat" #: gajim/data/gui/preferences_window.ui:89 msgid "Only when pending events" msgstr "Només en esdeveniments pendents" #: gajim/data/gui/preferences_window.ui:103 msgid "Pop it up" msgstr "" #: gajim/data/gui/preferences_window.ui:106 msgid "Notify me about it" msgstr "" #: gajim/data/gui/preferences_window.ui:109 msgid "Show only in roster" msgstr "" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 msgid "Last state" msgstr "" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "" #: gajim/data/gui/preferences_window.ui:236 msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" #: gajim/data/gui/preferences_window.ui:250 msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "" #: gajim/data/gui/preferences_window.ui:254 msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "" #: gajim/data/gui/preferences_window.ui:275 msgid "Sort contacts by status" msgstr "" #: gajim/data/gui/preferences_window.ui:285 msgid "in _roster" msgstr "" #: gajim/data/gui/preferences_window.ui:302 msgid "in _group chats" msgstr "" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "" #: gajim/data/gui/preferences_window.ui:359 msgid "Spell _checker" msgstr "" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" #: gajim/data/gui/preferences_window.ui:376 msgid "Show message recei_pts" msgstr "" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 msgid "_Window behavior" msgstr "" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "C_onecta al servidor quan s'inicia" #: gajim/data/gui/preferences_window.ui:484 msgid "_Ignore rich content in incoming messages" msgstr "" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" #: gajim/data/gui/preferences_window.ui:503 msgid "Show subject after joining a group chat" msgstr "" #: gajim/data/gui/preferences_window.ui:523 msgid "Chat Appearance" msgstr "" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "S'ha rebut una nova entrada" #: gajim/data/gui/preferences_window.ui:623 msgid "Notify me about contacts that sign _in" msgstr "" #: gajim/data/gui/preferences_window.ui:641 msgid "Notify me about contacts that sign _out" msgstr "" #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" #: gajim/data/gui/preferences_window.ui:676 msgid "Allow popup/notifications when a chat window is opened" msgstr "" #: gajim/data/gui/preferences_window.ui:701 msgid "Show notification area icon" msgstr "" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "" #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "" #: gajim/data/gui/preferences_window.ui:861 msgid "Notifications" msgstr "" #: gajim/data/gui/preferences_window.ui:898 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "Mostra els canvis d'estat" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" #: gajim/data/gui/preferences_window.ui:965 msgid "_Send chat state notifications" msgstr "" #: gajim/data/gui/preferences_window.ui:987 msgid "Chat state notifications" msgstr "" #: gajim/data/gui/preferences_window.ui:1009 msgid "Personal Events" msgstr "" #: gajim/data/gui/preferences_window.ui:1043 msgid "_Away after" msgstr "" #: gajim/data/gui/preferences_window.ui:1047 msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "_No Disponible" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1166 msgid "Auto Status" msgstr "" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "_Canvia Missatge d'Estat" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" #: gajim/data/gui/preferences_window.ui:1291 msgid "Default Message" msgstr "" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 msgid "Enabled" msgstr "" #: gajim/data/gui/preferences_window.ui:1332 msgid "Status Messages" msgstr "" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 msgid "Themes" msgstr "" #: gajim/data/gui/preferences_window.ui:1525 msgid "_Theme" msgstr "" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "Personalització Temes Gajim" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "Personalització Temes Gajim" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "_Canvia Missatge d'Estat" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "_Canvia Missatge d'Estat" #: gajim/data/gui/preferences_window.ui:1697 msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" #: gajim/data/gui/preferences_window.ui:1724 msgid "_Convert ASCII Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1808 msgid "Style" msgstr "" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 msgid "Audio" msgstr "" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 msgid "Video" msgstr "" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Servidor MUC" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 msgid "Connection" msgstr "" #: gajim/data/gui/preferences_window.ui:2159 msgid "Audio/Video" msgstr "" #: gajim/data/gui/preferences_window.ui:2229 msgid "_Mail client" msgstr "" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "Navega..." #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "Transferència de Fitxers" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "" #: gajim/data/gui/preferences_window.ui:2363 msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" #: gajim/data/gui/preferences_window.ui:2377 msgid "Allow client / _OS information to be sent" msgstr "" #: gajim/data/gui/preferences_window.ui:2381 msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "" #: gajim/data/gui/preferences_window.ui:2395 msgid "Allow local system time information to be sent" msgstr "" #: gajim/data/gui/preferences_window.ui:2399 msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "" #: gajim/data/gui/preferences_window.ui:2413 msgid "Allow my _idle time to be sent" msgstr "" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 msgid "_Manage..." msgstr "Administra..." #: gajim/data/gui/preferences_window.ui:2500 msgid "Privacy" msgstr "" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Miscel·lània" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "" #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Comença Xat" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Envia un _Missatge únic..." #: gajim/data/gui/contact_context_menu.ui:28 msgid "Send _File..." msgstr "Envia un _fitxer..." #: gajim/data/gui/contact_context_menu.ui:44 msgid "Invite _Contacts" msgstr "Convida _Contactes" #: gajim/data/gui/contact_context_menu.ui:73 msgid "E_xecute Command..." msgstr "E_xecuta Comanda..." #: gajim/data/gui/contact_context_menu.ui:82 msgid "M_anage Contact" msgstr "Gestiona Contacte" #: gajim/data/gui/contact_context_menu.ui:92 msgid "_Rename..." msgstr "Canvia el nom..." #: gajim/data/gui/contact_context_menu.ui:99 msgid "Edit _Groups..." msgstr "Edita els _Grups..." #: gajim/data/gui/contact_context_menu.ui:106 msgid "Assign Open_PGP Key..." msgstr "Assigna Clau Open_PGP..." #: gajim/data/gui/contact_context_menu.ui:115 msgid "Add Special _Notification..." msgstr "Afegeix _Notificació Especial..." #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Subscripció" #: gajim/data/gui/contact_context_menu.ui:138 msgid "_Allow contact to see my status" msgstr "Permet el contacte veure el meu estat" #: gajim/data/gui/contact_context_menu.ui:146 msgid "A_sk to see contact status" msgstr "Demana veure l'estat del contacte" #: gajim/data/gui/contact_context_menu.ui:154 msgid "_Forbid contact to see my status" msgstr "Prohibeix el contacte veure el meu estat" #: gajim/data/gui/contact_context_menu.ui:182 msgid "_Unignore" msgstr "No ignora" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "_Ignora" #: gajim/data/gui/contact_context_menu.ui:197 msgid "_Add to Roster..." msgstr "Afegeix a la llista de contactes..." #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gaim: Ajuda a Creació de Compte" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Necessites un compte per a connectar-te\n" "a la xarxa Jabber." #: gajim/data/gui/account_creation_wizard_window.ui:95 msgid "I already have an account I want to _use" msgstr "Ja tinc un compte que vull _usar" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "Vull _registrar-me amb un nou compte" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Si us plau esculli una de les següents opcions:" #: gajim/data/gui/account_creation_wizard_window.ui:167 msgid "Please fill in the data for your existing account" msgstr "Si us plau ompli les dades del seu compte existent" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "ID _Jabber:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 msgid "Anon_ymous authentication" msgstr "Autenticació Anònima" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Contrasenya:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Guarda contrasenya" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Si està marcat, Gajim recordarà la contrasenya d'aquest compte" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "Si us plau seleccioni un servidor" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Servidor:" #: gajim/data/gui/account_creation_wizard_window.ui:423 msgid "Prox_y:" msgstr "Prox_y:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Gestiona..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Fa servir nomdeservidor/port" #: gajim/data/gui/account_creation_wizard_window.ui:491 msgid "_Hostname:" msgstr "Nom del servidor:" #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Port:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "_Avançat" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" "Afegir aquest certificat a la llista de certificats confiables.\n" "Hash SHA1 del certificat:\n" #: gajim/data/gui/account_creation_wizard_window.ui:687 msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Connectant al servidor\n" "\n" "Si us plau esperi..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Connecta quan jo cliqui Acabar" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Estableix el meu perfil quan jo connecti" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "Acaba" #: gajim/data/gui/privacy_lists_window.ui:34 msgid "Privacy Lists:" msgstr "" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 msgid "Select the contacts you want to synchronise" msgstr "" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Edita els grups" #: gajim/data/gui/search_window.ui:42 msgid "Please wait while retrieving search form..." msgstr "" #: gajim/data/gui/search_window.ui:80 msgid "_Add contact" msgstr "" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Missatges preconfigurats:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Activitat:" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Escriu el teu nou missatge d'estat" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 msgid "Synchronise contacts" msgstr "" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "ID _Jabber:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "Sobrenom:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "_Grup:" #: gajim/data/gui/add_new_contact_window.ui:159 #, fuzzy msgid "Choose or type new group name" msgstr "Escull un grup o escriu-ne un de nou" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "Compte:" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "_Protocol:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "Permet a aquest contacte de veure el meu estat" #: gajim/data/gui/add_new_contact_window.ui:341 msgid "_Save subscription message" msgstr "Guarda missatge de subscripció" #: gajim/data/gui/add_new_contact_window.ui:367 msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" "Has de registrar-te amb aquest transport\n" "per a poder afegir un contacte des\n" "d'aquest protocol. Clica al botó Registra\n" "per a seguir." #: gajim/data/gui/add_new_contact_window.ui:382 msgid "_Register" msgstr "_Registra" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" "Has d'estar connectat al transport per a poder\n" "afegir un contacte des d'aquest protocol." #: gajim/data/gui/roster_window.ui:61 msgid "Change Status Message…" msgstr "Canvia Missatge d'Estat..." #: gajim/data/gui/change_mood_dialog.ui:73 msgid "Mood:" msgstr "Estat d'ànim:" #: gajim/data/gui/change_mood_dialog.ui:85 msgid "Message:" msgstr "Missatge:" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "Connectors" #: gajim/data/gui/plugins_window.ui:74 #, fuzzy msgid "Install Plugin from File" msgstr "Instal·la des d'un zip" #: gajim/data/gui/plugins_window.ui:75 #, fuzzy msgid "Install from File…" msgstr "Instal·la des d'un zip" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Desinstal·la" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Connectors" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Connectors" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Descripció:" #: gajim/data/gui/plugins_window.ui:258 #, fuzzy msgid "Version" msgstr "Versió:" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "Autors:" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 msgid "Installed" msgstr "Instal·lat" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" "La descripció del plugin s'hauria de mostrar aquí. Aquest text s'esborrarà " "durant la inicialització PluginsWindow." #: gajim/data/gui/privacy_list_window.ui:18 msgid "none" msgstr "" #: gajim/data/gui/privacy_list_window.ui:21 msgid "both" msgstr "" #: gajim/data/gui/privacy_list_window.ui:24 msgid "from" msgstr "" #: gajim/data/gui/privacy_list_window.ui:27 msgid "to" msgstr "" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "" #: gajim/data/gui/privacy_list_window.ui:557 msgid "All (including subscription)" msgstr "" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "" #: gajim/data/gui/manage_sounds_window.ui:23 msgid "Manage sounds" msgstr "Gestiona sons" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Activa" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Si us plau espera mentre es recupera la llista de comandes..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Escull la comanda per executar:" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Comprova una vegada més" #: gajim/data/gui/adhoc_commands_window.ui:147 msgid "Please wait while the command is being sent..." msgstr "Si us plau espera mentre la comanda s'envia..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Aquesta entitat jabber no exposa cap comanda." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Hi ha hagut un error:" #: gajim/data/gui/adhoc_commands_window.ui:339 msgid "F_inish" msgstr "Acabar" #: gajim/data/gui/account_context_menu.ui:20 msgid "_Personal Events" msgstr "Events _Personals" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "Inicia Xat de _Grup" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Afegeix Contacte..." #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Descobreix Serveis" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "_Executa Comanda...." #: gajim/data/gui/application_menu.ui:8 msgid "View" msgstr "Veure" #: gajim/data/gui/application_menu.ui:11 msgid "Show Roster" msgstr "Mostra Roster" #: gajim/data/gui/application_menu.ui:16 msgid "Show Offline Contacts" msgstr "Mostra els contactes desconnectats" #: gajim/data/gui/application_menu.ui:21 msgid "Show Active Contacts" msgstr "Mostra Contactes Actius" #: gajim/data/gui/application_menu.ui:26 msgid "Show Transports" msgstr "Mostra Transports" #: gajim/data/gui/application_menu.ui:43 msgid "Help" msgstr "Ajuda" #: gajim/data/gui/application_menu.ui:46 msgid "Contents" msgstr "Contingut" #: gajim/data/gui/application_menu.ui:50 msgid "FAQ" msgstr "PMF (Preguntes més freqüents)" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "Dreceres de teclat" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 msgid "Features" msgstr "Característiques" #: gajim/data/gui/application_menu.ui:81 msgid "Bookmarks" msgstr "Adreces d'interès" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Preferències" #: gajim/data/gui/application_menu.ui:99 msgid "Quit" msgstr "Surt" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Cancel·la" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "Llista de possibles prestacions a Gajim:" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "Grups de xat" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "Afegeix aquesta sala a les adreces d'interès" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Servidor:" #: gajim/data/gui/manage_bookmarks_window.ui:219 #, fuzzy msgid "Roo_m" msgstr "Sala:" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Contrasenya:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Entra a aquesta sala _automàticament quan em connecto" #: gajim/data/gui/manage_bookmarks_window.ui:342 #, fuzzy msgid "Minimize on Auto Join" msgstr "Minimitza quan es connecta automàticament" #: gajim/data/gui/manage_bookmarks_window.ui:376 msgid "Status messages displayed in chat window" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "_Canvia Missatge d'Estat" #: gajim/data/gui/send_file_dialog.ui:43 msgid "Description:" msgstr "Descripció:" #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Fitxer de Certificat de Client:" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 #, fuzzy msgid "Send" msgstr "Envia" #: gajim/data/gui/send_file_dialog.ui:106 msgid "Files:" msgstr "" #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" "S'ha detectat un error de programació.\n" "Probablement no és fatal, però caldria\n" "informar-ne els desenvolupadors." #: gajim/data/gui/exception_dialog.ui:115 msgid "Report Bug" msgstr "Informa de l'error" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "Inicia Xat" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "Missatges preconfigurats:" #: gajim/data/gui/emoji_chooser.ui:98 msgid "No Results Found" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "Convida Amics!" #: gajim/data/gui/chat_to_muc_window.ui:39 msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "" "Estàs entrant a un xat de grup.\n" "Selecciona els contactes que vols convidar" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "Si us plau selecciona un servidor MUC." #: gajim/data/gui/chat_to_muc_window.ui:141 msgid "MUC server" msgstr "Servidor MUC" #: gajim/data/gui/chat_to_muc_window.ui:176 msgid "In_vite" msgstr "Con_vida" #: gajim/data/gui/history_manager.ui:11 msgid "_Export" msgstr "_Exporta" #: gajim/data/gui/history_manager.ui:93 msgid "Welcome to Gajim History Logs Manager" msgstr "Benvinguts al Gestor Gajim d'Històric de Registres" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" "Aquest gestor de registres no està dissenyat com a visor. Si vols aquesta " "funcionalitat, fes ús de la finestra d'històric.\n" "\n" "Des servir aquest gestor per a esborrar o exportar registres. Pots " "seleccionarlos a l'esquerra i/o cercar abaix." #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "AVÍS:\n" "Si preveus esborrats massius, assegura't que Gajim no està en execució. " "Evita esborrats amb contactes amb els quals estàs parlant." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "Cerca Base de Dades" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 msgid "Message composition" msgstr "" #: gajim/data/gui/shortcuts_window.ui:17 msgid "Send the message" msgstr "" #: gajim/data/gui/shortcuts_window.ui:24 msgid "Add new line" msgstr "" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Missatges preconfigurats:" #: gajim/data/gui/shortcuts_window.ui:52 msgid "Next sent messages" msgstr "" #: gajim/data/gui/shortcuts_window.ui:59 msgid "Quote previous message" msgstr "" #: gajim/data/gui/shortcuts_window.ui:66 msgid "Quote next message" msgstr "" #: gajim/data/gui/shortcuts_window.ui:73 msgid "Clear message entry" msgstr "" #: gajim/data/gui/shortcuts_window.ui:81 msgid "Recent history" msgstr "" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 msgid "Clear" msgstr "" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 msgid "File transfers" msgstr "" #: gajim/data/gui/shortcuts_window.ui:196 msgid "Join a group chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:203 msgid "Set the status message" msgstr "" #: gajim/data/gui/shortcuts_window.ui:210 msgid "Quit Gajim" msgstr "" #: gajim/data/gui/shortcuts_window.ui:218 msgid "Appearance" msgstr "" #: gajim/data/gui/shortcuts_window.ui:223 msgid "Show offline contacts" msgstr "Mostra els contactes desconnectats" #: gajim/data/gui/shortcuts_window.ui:230 msgid "Show only active contacts" msgstr "Mostra només contactes actius" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:250 msgid "Contact information" msgstr "" #: gajim/data/gui/shortcuts_window.ui:257 msgid "Rename contact" msgstr "" #: gajim/data/gui/shortcuts_window.ui:264 msgid "Delete contact" msgstr "" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Contrasenya" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "Mostra els canvis d'estat" #: gajim/data/gui/history_window.ui:233 msgid "Mode" msgstr "" #: gajim/data/gui/history_window.ui:246 msgid "Search complete history" msgstr "" #: gajim/data/gui/history_window.ui:263 #, fuzzy msgid "Search selected day only" msgstr "Nomes cerca al dia seleccionat" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Històric de converses" #: gajim/data/gui/history_window.ui:315 msgid "Chat" msgstr "" #: gajim/data/gui/history_window.ui:329 msgid "Record history for this chat" msgstr "" #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Historial" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "_Títol:" #: gajim/data/gui/manage_pep_services_window.ui:13 msgid "PEP Service Configuration" msgstr "Configuració Servei PEP:" #: gajim/data/gui/manage_pep_services_window.ui:69 msgid "_Configure" msgstr "_Configura" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Crea nou missatge" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "Des de:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Assumpte:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Omple el formulari." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Configuració de Sala" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "" #: gajim/data/gui/systray_context_menu.ui:20 msgid "_Start Chat..." msgstr "Inicia Xat..." #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Preferències" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "Surt" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Envia missatge" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "Estableix Activitat" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "Estableix una activitat" #: gajim/data/gui/change_activity_dialog.ui:337 msgid "Message: " msgstr "Missatge:" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 msgid "Missing arguments" msgstr "" #: gajim/command_system/mapping.py:263 msgid "Too many arguments" msgstr "" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 msgid "Send a message to the contact" msgstr "" #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, python-format msgid "%s: Nothing found" msgstr "" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 msgid "Available" msgstr "Disponible" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 msgid "Clear the text window" msgstr "" #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 msgid "Send a ping to the contact" msgstr "" #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 msgid "Command is not supported for zeroconf accounts" msgstr "" #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 msgid "No open audio sessions with the contact" msgstr "" #: gajim/command_system/implementation/standard.py:191 #, python-format msgid "%s is not a valid tone" msgstr "" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "" #: gajim/command_system/implementation/standard.py:201 msgid "Audio sessions are not available" msgstr "" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "" #: gajim/command_system/implementation/standard.py:211 msgid "Video sessions are not available" msgstr "" #: gajim/command_system/implementation/standard.py:218 msgid "Send a message to the contact that will attract their attention" msgstr "" #: gajim/command_system/implementation/standard.py:257 msgid "Change your nickname in a group chat" msgstr "" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 msgid "Invalid nickname" msgstr "" #: gajim/command_system/implementation/standard.py:267 msgid "Open a private chat window with a specified occupant" msgstr "" #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 msgid "Nickname not found" msgstr "" #: gajim/command_system/implementation/standard.py:276 msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" #: gajim/command_system/implementation/standard.py:285 msgid "Display or change a group chat topic" msgstr "" #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "" #: gajim/command_system/implementation/standard.py:301 msgid "Join a group chat given by a JID" msgstr "" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 msgid "Kick user by a nick from a groupchat" msgstr "" #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 msgid "Invalid role given" msgstr "" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 msgid "Invalid affiliation given" msgstr "" #: gajim/command_system/implementation/standard.py:365 msgid "Display names of all group chat occupants" msgstr "" #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 msgid "Start new Conversation" msgstr "" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Grups de xat" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Afegeix un contacte nou" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "" #: gajim/gtk/single_message.py:238 #, python-format msgid "Form %s" msgstr "" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "" #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "" #: gajim/gtk/pep_config.py:133 #, python-format msgid "Configure %s" msgstr "" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "_Registra" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 msgid "Registration successful" msgstr "" #: gajim/gtk/dialogs.py:82 #, python-format msgid "Dictionary for language \"%s\" not available" msgstr "" #: gajim/gtk/dialogs.py:83 #, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" #: gajim/gtk/dialogs.py:440 #, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 msgid "The nickname contains invalid characters." msgstr "" #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, python-format msgid "Certificate for account %s" msgstr "" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Certificat de client" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Canviar contrasenya" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Escriu nova contrasenya:" #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "" #: gajim/gtk/add_contact.py:30 msgid "GG Number" msgstr "" #: gajim/gtk/add_contact.py:31 msgid "ICQ Number" msgstr "" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Afegeix Contacte..." #: gajim/gtk/add_contact.py:234 #, python-format msgid "%s Missing" msgstr "" #: gajim/gtk/add_contact.py:235 #, python-format msgid "You must supply the %s of the new contact." msgstr "" #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "" #: gajim/gtk/add_contact.py:274 msgid "You cannot add yourself to your roster." msgstr "" #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Desconnectat" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "" #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "" #: gajim/gtk/add_contact.py:459 msgid "Error while adding transport contact" msgstr "" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "S'està creant la composició" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Inactiva" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 msgid "Chatstate Paused" msgstr "" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "Missatges\n" "MUC Dirigits" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "" "Missatges\n" "MUC" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Fila del compte " #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Fila del grup" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "Fila del contacte" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Històric de converses" #: gajim/gtk/themes.py:113 msgid "Incoming Nickname Color" msgstr "" #: gajim/gtk/themes.py:117 msgid "Outgoing Nickname Color" msgstr "" #: gajim/gtk/themes.py:121 msgid "Incoming Message Text Color" msgstr "" #: gajim/gtk/themes.py:125 msgid "Incoming Message Text Font" msgstr "" #: gajim/gtk/themes.py:129 msgid "Outgoing Message Text Color" msgstr "" #: gajim/gtk/themes.py:133 msgid "Outgoing Message Text Font" msgstr "" #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "_Canvia Missatge d'Estat" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "_Canvia Missatge d'Estat" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Color" #: gajim/gtk/themes.py:149 msgid "Highlight Message Color" msgstr "" #: gajim/gtk/themes.py:153 msgid "Message Correcting" msgstr "" #: gajim/gtk/themes.py:157 msgid "Restored Message Color" msgstr "" #: gajim/gtk/themes.py:161 msgid "Contact Disconnected Background" msgstr "" #: gajim/gtk/themes.py:165 msgid "Contact Connected Background " msgstr "" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "Personalització Temes Gajim" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Gestiona Sala" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 msgid "Spaces are not allowed" msgstr "" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Activa" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "" #: gajim/gtk/history.py:588 #, python-format msgid "Error: %s" msgstr "" #: gajim/gtk/history.py:590 msgid "Error" msgstr "" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "" #: gajim/gtk/history_sync.py:204 msgid "How far back do you want to go?" msgstr "" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Connexió" #: gajim/gtk/history_sync.py:252 #, python-format msgid "%(received)s of %(max)s" msgstr "" #: gajim/gtk/history_sync.py:256 #, python-format msgid "Downloaded %s Messages" msgstr "" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 msgid "A GTK+ XMPP client" msgstr "" #: gajim/gtk/about.py:48 #, fuzzy, python-format msgid "GTK+ Version: %s" msgstr "Versió:" #: gajim/gtk/about.py:49 #, python-format msgid "PyGObject Version: %s" msgstr "" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 msgid "Current Developers" msgstr "" #: gajim/gtk/about.py:54 msgid "Past Developers" msgstr "" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 msgid "we would like to thank all the package maintainers." msgstr "" #: gajim/gtk/about.py:61 msgid "Thanks" msgstr "" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "" #: gajim/gtk/filechoosers.py:87 msgid "Choose File to Send…" msgstr "" #: gajim/gtk/filechoosers.py:93 msgid "Choose Avatar…" msgstr "" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Perfil" #: gajim/gtk/filechoosers.py:98 msgid "JPEG files" msgstr "" #: gajim/gtk/filechoosers.py:99 msgid "SVG files" msgstr "" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "" #: gajim/gtk/filechoosers.py:135 msgid "Choose Archive" msgstr "" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Perfil" #: gajim/gtk/filechoosers.py:142 msgid "Save File as…" msgstr "" #: gajim/gtk/profile.py:72 msgid "Retrieving profile…" msgstr "" #: gajim/gtk/profile.py:187 msgid "Wrong date format" msgstr "" #: gajim/gtk/profile.py:190 msgid "Format of the date must be YYYY-MM-DD" msgstr "" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "" #: gajim/gtk/profile.py:333 msgid "Without a connection, you can not publish your contact information." msgstr "" #: gajim/gtk/profile.py:346 msgid "Sending profile…" msgstr "" #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Gestiona Sala" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 msgid "Invalid Nickname" msgstr "" #: gajim/gtk/join_groupchat.py:223 msgid "Please choose a nickname" msgstr "" #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 msgid "Wrong server" msgstr "" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, python-format msgid "%s is not a groupchat server" msgstr "" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Your Archiving Preferences have been saved!" msgstr "" #: gajim/gtk/mam_preferences.py:100 msgid "No response from the Server" msgstr "" #: gajim/gtk/mam_preferences.py:102 msgid "Error received: {}" msgstr "" #: gajim/gtk/mam_preferences.py:106 msgid "Error!" msgstr "" #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "Nom del servidor:" #: gajim/gtk/server_info.py:193 msgid "Server Software" msgstr "" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Servidor:" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "" #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 msgid "Command line" msgstr "" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "" #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "" #: gajim/gtk/features.py:61 msgid "OpenPGP message encryption" msgstr "" #: gajim/gtk/features.py:63 msgid "Ability to encrypting chat messages with OpenPGP." msgstr "" #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "" #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 msgid "Password encryption" msgstr "" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "" #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "" #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 msgid "Requires Gspell" msgstr "" #: gajim/gtk/features.py:76 msgid "Automatic status" msgstr "" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "" #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "" #: gajim/gtk/features.py:81 msgid "RST Generator" msgstr "" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "" #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "" #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 msgid "Requires gir1.2-gupnpigd-1.0." msgstr "" #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "?user status:_Disponible" #: gajim/gtk/features.py:109 msgid "Feature" msgstr "" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "" #: gajim/gtk/privacy_list.py:152 #, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "" #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "El compte s'ha configurat correctament" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Pots configurar opcions avançades amb el botó Avançat, o més tard amb el " "submenú Comptes del menú Edita de la finestra principal." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "" #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 msgid "Invalid server" msgstr "" #: gajim/gtk/account_wizard.py:255 msgid "Please provide a server on which you want to register." msgstr "" #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "" #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "" #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Filtra:" #: gajim/gtk/xml_console.py:79 msgid "XML Input" msgstr "" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Gestiona Sala" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "" #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Afegeix Contacte..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "Esborra" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Comptes" #: gajim/gtk/accounts.py:549 #, fuzzy msgid "Use PGP Agent" msgstr "Fes ús d'Agent G_PG" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Connexió" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Convida _Contactes" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Certificat de client" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Assigna Clau Open_PGP..." #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "C_onecta al servidor quan s'inicia" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Reconnexió automàtica quan es perd la connexió" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Guarda registre de les converses amb tots els contactes" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "Envia Missatge Privat" #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Estat" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Sincronit_za l'estat del compte amb l'estat global" #: gajim/gtk/accounts.py:623 msgid "Message Carbons" msgstr "" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Fer ús de proxis per a transferència de fitxers" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "fa ús de la variable d'entorn HTTP__PROXY" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Prox_y:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "Avís abans d'una connexió insegura" #: gajim/gtk/accounts.py:650 #, fuzzy msgid "Send keep-alive packets" msgstr "Enviar paquets _keep-alive" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "Priori_tat:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Sinc_ronitza l'estat del compte amb l'estat global" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Nom:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Cognom:" #: gajim/gtk/accounts.py:707 msgid "Email" msgstr "" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "Ajustar a estat" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Port:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Connexió" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Certificat de client" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "El Certificat està xifrat" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Desa la contrasenya" #: gajim/gtk/accounts.py:800 msgid "Login Options" msgstr "" #: gajim/gtk/bookmarks.py:72 #, fuzzy msgid "?print_status:All" msgstr "Estat d'impressió:" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "" #: gajim/gtk/bookmarks.py:74 #, fuzzy msgid "?print_status:None" msgstr "Estat d'impressió:" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "" #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 msgid "Character not allowed" msgstr "" #: gajim/gtk/bookmarks.py:367 msgid "Invalid room" msgstr "" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 msgid "Archive empty" msgstr "" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 msgid "Archive is malformed" msgstr "" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 msgid "Plugin already exists" msgstr "" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, python-format msgid "Warning: %s" msgstr "" #: gajim/plugins/gui.py:203 msgid "Plugin failed" msgstr "" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 msgid "Configuration" msgstr "" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Només en esdeveniments pendents" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Característiques" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 msgid "Automatic spell-checking for your messages" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 msgid "Support for service discovery including nodes and search for users" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 msgid "Roster, list of contacts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Grups de xat" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Historial" #: data/org.gajim.Gajim.appdata.xml.in:68 msgid "Plugin manager" msgstr "" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Transferències de fitxers" #~ msgid "_Verify" #~ msgstr "_Verifica" #, fuzzy #~ msgid "(ESession info)" #~ msgstr "Descripció" #~ msgid "Save as Preset..." #~ msgstr "Guardar com a Configuració..." #, fuzzy #~ msgid "Presence" #~ msgstr "Preferència" #~ msgid "Chat Banner" #~ msgstr "Banner del Xat" #~ msgid "Text _color:" #~ msgstr "_Color del text:" #~ msgid "_Background:" #~ msgstr "Fons:" #~ msgid "Text _font:" #~ msgstr "Tipus de lletra:" #~ msgid "Font style:" #~ msgstr "Estil de lletra:" #~ msgid "Paused" #~ msgstr "Aturat" #~ msgid "Gone" #~ msgstr "Desaparegut" #~ msgid "Chatstate Tab Colors" #~ msgstr "Colors Pestanya Estat de Xat" #, fuzzy #~ msgid "Chat message" #~ msgstr "missatge" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "El Contacte ha entrat" #, fuzzy #~ msgid "Contact's message" #~ msgstr "_Canvia Missatge d'Estat" #, fuzzy #~ msgid "_Status message" #~ msgstr "_Canvia Missatge d'Estat" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Grups de xat" #, fuzzy #~ msgid "Your nickname" #~ msgstr "Sobrenom:" #, fuzzy #~ msgid "Your message" #~ msgstr "missatge" #~ msgid "Search:" #~ msgstr "Cerca:" #~ msgid "_In date search" #~ msgstr "Creca en data" #~ msgid "Enter it again for confirmation:" #~ msgstr "Torna-ho a escriure per a confirmació:" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Entra automàticament" #~ msgid "<empty>" #~ msgstr "<buit>" #~ msgid "Homepage:" #~ msgstr "Pàgina d'inici:" #~ msgid "Manage Bookmarks" #~ msgstr "Gestiona els marcadors" #~ msgid "_Nickname:" #~ msgstr "Sobrenom:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "Si està marcat, Gajim entrarà en aquest xat de grup a l'inici" #~ msgid "Pr_int status:" #~ msgstr "Estat d'impressió:" #~ msgid "Preference:" #~ msgstr "Preferència:" #~ msgid "Preference" #~ msgstr "Preferència" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "Si us plau ompli les dades del seu compte existent" #, fuzzy #~ msgid "Recently" #~ msgstr "Recentment:" #~ msgid "Add New Contact" #~ msgstr "Afegeix un contacte nou" #~ msgid "_User ID:" #~ msgstr "ID d'_Usuari:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "ID d'_Usuari:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Sobrenom:" #~ msgid "Personal Information" #~ msgstr "Informació personal" #~ msgid "Please wait..." #~ msgstr "Espereu…" #~ msgid "_Send" #~ msgstr "Envia" #~ msgid "Gajim History Logs Manager" #~ msgstr "Gajim Gestor Històric Registres" #, fuzzy #~ msgid "" #~ "Add this certificate to the list of trusted certificates.\n" #~ "SHA-1 fingerprint of the certificate:\n" #~ "%(sha1)s\n" #~ "SHA256 fingerprint of the certificate:\n" #~ "%(sha256)s" #~ msgstr "" #~ "Afegir aquest certificat a la llista de certificats confiables.\n" #~ "Hash SHA1 del certificat:\n" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Instal·lat" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Instal·lat" #, fuzzy #~ msgid "Install and Upgrade Plugins" #~ msgstr "Instal·lat" #, fuzzy #~ msgid "Send File..." #~ msgstr "Envia un _fitxer..." #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Transferència de Fitxers" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "Fusiona comptes" #~ msgid "Exception" #~ msgstr "Excepció" #~ msgid "_Actions" #~ msgstr "_Accions" #~ msgid "jid" #~ msgstr "jid" #~ msgid "Server:" #~ msgstr "Servidor:" #~ msgid "Password:" #~ msgstr "Contrasenya:" #~ msgid "Bro_wse Rooms" #~ msgstr "Navega per les sales" #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Canvia el teu nick (Ctrl+N)" #~ msgid "Change the room's subject (Alt+T)" #~ msgstr "Canvia el tema de la sala (Alt+T)" #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "Afegeix la sala a llista de preferits (Ctrl+B)" #~ msgid "Browse the chat history (Ctrl+H)" #~ msgstr "Navega per l'historial de xat (Ctrl+H)" #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Mostra funcions avançades (Alt+D)" #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Afegeix aquest contacte a la llista de contactes (Ctrl+D)" #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "Convida contactes a la conversa (Ctrl+G)" #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Mostra el perfil del contacte (Ctrl+I)" #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Mostra el perfil del contacte (Ctrl+I)" #~ msgid "Set Custom _Avatar..." #~ msgstr "Estableix _Avatar..." #~ msgid "_Open Gmail Inbox" #~ msgstr "_Obre Safata d'entrada Gmail" #~ msgid "Re_name" #~ msgstr "Reescriu" #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "El recurs s'envia al servidor per a diferenciar el mateix JID en dos o " #~ "més parts depenent del nombre de clients connectats al mateix servidor " #~ "amb el mateix compte. Per exemple podria estar connectat amb el mateix " #~ "compte alhora amb recursos 'Casa' i 'Feina'. El recurs que tingui la " #~ "prioritat més alta rebrà els events. (veure a baix)" #~ msgid "Priority will change automatically according to your status." #~ msgstr "La prioritat canviarà automàticament d'acord amb l'estat." #~ msgid "Anonymous authentication" #~ msgstr "Autenticació Anònima." #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "La prioritat es fa servir per a determinar qui rep els events del " #~ "servidor quan dos o més clients estan connectats amb el mateix compte; El " #~ "client amb la prioritat més alta rep els events" #~ msgid "Click to request authorization to all contacts of another account" #~ msgstr "" #~ "Cliqui per a demanar autorització a tots els contactes d'un altre compte" #~ msgid "Chan_ge Password" #~ msgstr "Canvia Contrasenya" #~ msgid "Click to change account's password" #~ msgstr "Cliqui per a canviar la contrasenya del compte" #~ msgid "Administration operations" #~ msgstr "Operacions d'Administració" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Si està marcat, Gajim, quan s'iniciï, es connectarà automàticament al " #~ "servidor amb aquest compte" #~ msgid "Synchronize logs with server" #~ msgstr "Sincronitza els registres amb el servidor" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Si està marcat, qualsevol canvi a l'estat global (indicat pel control al " #~ "final de la finestra de la llista) canviarà l'estat del compte" #~ msgid "" #~ "Receive conversations from other resources (provided the server has " #~ "support for it)" #~ msgstr "Rep converses des d'altres recursos (si el servidor ho suporta)" #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Si està marcat, Gajim també publicarà algunes IPs més a part de la teva, " #~ "per a que les transferències de fitxers tinguin més possibilitat de " #~ "funcionar." #~ msgid "Proxy" #~ msgstr "Servidor intermediari" #~ msgid "" #~ "Check this so Gajim will ask you before sending your password over an " #~ "insecure connection." #~ msgstr "" #~ "Marcar per a que se't demani confirmació abans d'enviar la contrasenya " #~ "sobre una connexió insegura." #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Si està marcat, Gajim enviarà paquets keep-alive per a evitar " #~ "desconnexions per timeout" #~ msgid "Use cust_om hostname/port" #~ msgstr "Fa ús de nomdeservidor/port" #~ msgid "_Hostname: " #~ msgstr "Nom de servidor:" #~ msgid "_Port: " #~ msgstr "_Port:" #~ msgid "No key selected" #~ msgstr "No s'ha seleccionat cap clau" #~ msgid "Choose _Key..." #~ msgstr "Escull Clau..." #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "" #~ "Si està marcat, Gajim obtindrà la contrasenya d'un agent GPG com seahorse" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #~ msgid "_Edit Personal Information..." #~ msgstr "_Edita Informació Personal..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Informació sobre tu, tal i com està guardada al servidor" #~ msgid "Personal Information" #~ msgstr "Informació Personal" #~ msgid "Co_nnect on Gajim startup" #~ msgstr "Co_nnecta a l'inici" #~ msgid "Use cust_om port:" #~ msgstr "Fes ús de port especificat:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Si el port per defecte que es fa servir per a missatges d'entrada no està " #~ "disponible aquí pots seleccionar-ne un altre.\n" #~ "Hauries de considerar possibles canvis al tallafocs." #~ msgid "No" #~ msgstr "No" #~ msgid "Yes" #~ msgstr "Sí" #~ msgid "Concede" #~ msgstr "Dóna permís" #~ msgid "Forbid" #~ msgstr "Prohibeix" #~ msgid "Auto" #~ msgstr "Automàtic" #~ msgid "Method Auto" #~ msgstr "Mètode Automàtic" #~ msgid "Method Local" #~ msgstr "Mètode Local" #~ msgid "Method Manual" #~ msgstr "Mètode Manual" #~ msgid "body" #~ msgstr "cos" #~ msgid "false" #~ msgstr "fals" #~ msgid "stream" #~ msgstr "Flux de dades" #~ msgid "approve" #~ msgstr "Aprova" #~ msgid "concede" #~ msgstr "dóna permís" #~ msgid "forbid" #~ msgstr "prohibeix" #~ msgid "oppose" #~ msgstr "oposa" #~ msgid "prefer" #~ msgstr "prefereix" #~ msgid "require" #~ msgstr "requereix" #~ msgid "expire" #~ msgstr "expira" #~ msgid "otr" #~ msgstr "otr" #~ msgid "save" #~ msgstr "desa" gajim-gajim-1.1.3/po/cs.po000066400000000000000000012775541345766322700153170ustar00rootroot00000000000000# translation of gajim.po to Czech # Czech translations for Gajim package. # Copyright (C) 2003-2005 Gajim Team # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 2 only. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # This file is distributed under the same license as the Gajim package. # Petr Mensik , 2005. # Pihhan , 2005, 2006. # Pihhan , 2008. # scippio , 2008. # Pihhan , 2009. # msgid "" msgstr "" "Project-Id-Version: gajim\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2010-01-22 14:35+0100\n" "Last-Translator: Petr Menšík \n" "Language-Team: <>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Poedit-Language: Czech\n" "X-Poedit-Country: CZECH REPUBLIC\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "Opravdu odeslat soubor?" #: gajim/chat_control_base.py:1103 #, fuzzy, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "Pokud odešlete soubor %s, tak bude znát vaše skutečné Jabber ID." #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Soubor" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Čas" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Průběh" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Soubor: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Velikost: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "Vy" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Odesílatel: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Příjemce: " #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Uloženo do: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Přenos soubor dokončen" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 #, fuzzy msgid "Open _Containing Folder" msgstr "_Otevřít obsahující složku" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "Přenos souboru zrušen" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "Spojení s protistranou se nepodařilo navázat." #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "Příjemce: %s" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "Chybová zpráva: %s" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 msgid "File transfer stopped" msgstr "Přenos souboru zastaven" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" #: gajim/filetransfers_window.py:341 #, fuzzy msgid "Gajim can not read this file" msgstr "Gajim nemůže otevřít tento soubor" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "" #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "Nemohu přepsat existující soubor \"%s\"" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "Soubor tohoto jména již existuje a ty nemáš oprávnění k jeho přepsání." #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Tento soubor už existuje" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "Co by jste rád(a) dělal(a)?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "Adresář \"%s\" není zapisovatelný" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "Nemáš oprávnění k vytváření souborů v tomto adresáři." #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Soubor: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Typ: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Popis: %s" # #: ../src/filetransfers_window.py:309 # #, python-format # msgid "Description: %s" # msgstr "Popis: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "%s Vám chce poslat soubor:" #: gajim/filetransfers_window.py:487 #, fuzzy msgid "Checking file…" msgstr "Odesílám profil..." #: gajim/filetransfers_window.py:501 #, fuzzy msgid "File error" msgstr "Chyba přenosu souboru" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/s)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Neplatný soubor" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Soubor: " #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "Není možné posílat prázdné soubory" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Jméno: " #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Odesílatel: " #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Pauza" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "_Pokračovat" #: gajim/filetransfers_window.py:1019 #, fuzzy msgid "Choose a File to Send…" msgstr "Vyber soubor k odeslání..." #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "Rozšíření není podporováno" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" "Obrázek nelze uložit ve formátu %(type)s. Uložit jako %(new_filename)s?" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 #, fuzzy msgid "Save _As" msgstr "Má" #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "?Client:Neznámý" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "?OS:Neznámý" #: gajim/vcard.py:326 gajim/vcard.py:329 msgid "?Time:Unknown" msgstr "?Time:Neznámý" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "" #: gajim/vcard.py:384 msgid "Affiliation:" msgstr "Vztah" #: gajim/vcard.py:391 #, fuzzy msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "Tento kontakt zajímá Váš stav, ale Vy se nezajímate o jeho stav" #: gajim/vcard.py:393 #, fuzzy msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "Vy se zajímáte o stav kontaktu, ale on se nezajímá o Váš stav" #: gajim/vcard.py:395 #, fuzzy msgid "The contact and you want to exchange presence information" msgstr "Vy i kontakt se zajímáte o stav toho druhého" #: gajim/vcard.py:397 #, fuzzy msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "Vy i kontakt se zajímáte o stav toho druhého" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "Čekáte na odpověď kontaktu na vaši žádost o autorizaci" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "Není zde žádný nevyřízený požadavek." #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr "zdroj s prioritou " #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "Všechny soubory" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 #, fuzzy msgid "Clear File" msgstr "Uklízím" #: gajim/options_dialog.py:484 #, fuzzy msgid "Manage Proxies" msgstr "Spravovat profily Proxy" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Žádný" #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "N_astavit podle stavu" #: gajim/options_dialog.py:528 msgid "On" msgstr "" #: gajim/options_dialog.py:528 #, fuzzy msgid "Off" msgstr "Odpojen" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Selhalo získání privátního klíče" #: gajim/options_dialog.py:565 msgid "There is no OpenPGP secret key available." msgstr "Není dostupný tajný klíč OpenPGP." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "Výběr OpenPGP klíče" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Vyberte Váš OpenPGP klíč" #: gajim/gui_menu_builder.py:95 msgid "_New Group Chat" msgstr "_Nová diskuze" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Není v Rosteru" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "Rád bych si Vás přidal(a) do svého seznamu" #: gajim/gui_menu_builder.py:502 #, fuzzy msgid "Send Single _Message…" msgstr "Odeslat jednoduchou _zprávu" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 msgid "Send Cus_tom Status" msgstr "Poslat vlastní stav" #: gajim/gui_menu_builder.py:535 #, fuzzy msgid "E_xecute Command…" msgstr "Spustit _příkaz..." #: gajim/gui_menu_builder.py:543 msgid "_Manage Transport" msgstr "Transporty" #: gajim/gui_menu_builder.py:549 msgid "_Modify Transport" msgstr "_Upravit transport" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 #, fuzzy msgid "_Rename…" msgstr "_Přejmenovat" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "_Odblokovat" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "_Blokovat" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 msgid "Remo_ve" msgstr "Odst_ranit" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 msgid "_Information" msgstr "Informace o kontaktu" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 #, fuzzy msgid "Send File…" msgstr "Odeslat _Soubor" #: gajim/gui_menu_builder.py:602 #, fuzzy msgid "Upload File…" msgstr "Uložit jako..." #: gajim/gui_menu_builder.py:603 #, fuzzy msgid "Send File Directly…" msgstr "Uložit jako..." #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Pozvat kontakt" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "Přid_at do Seznamu" #: gajim/gui_menu_builder.py:607 #, fuzzy msgid "Audio Session" msgstr "Audio / Video" #: gajim/gui_menu_builder.py:608 #, fuzzy msgid "Video Session" msgstr "Velikost videa" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "Informace o kontaktu" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 #, fuzzy msgid "History" msgstr "_Historie" #: gajim/gui_menu_builder.py:634 #, fuzzy msgid "Manage Room" msgstr "Spravuj Místnost" #: gajim/gui_menu_builder.py:635 #, fuzzy msgid "Change Subject" msgstr "Změnit _předmět" #: gajim/gui_menu_builder.py:636 #, fuzzy msgid "Configure Room" msgstr "Nastavit _místnost" #: gajim/gui_menu_builder.py:637 #, fuzzy msgid "Upload Avatar…" msgstr "Vyberte obrázek" #: gajim/gui_menu_builder.py:638 #, fuzzy msgid "Destroy Room" msgstr "_Zničit místnost" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "" #: gajim/gui_menu_builder.py:641 #, fuzzy msgid "Change Nick" msgstr "Změ_nit přezdívku" #: gajim/gui_menu_builder.py:642 #, fuzzy msgid "Bookmark Room" msgstr "Přidat tuto místnost do záložek" #: gajim/gui_menu_builder.py:643 #, fuzzy msgid "Request Voice" msgstr "_Hlas" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 #, fuzzy msgid "Notify on all messages" msgstr "Uložené stavy:" #: gajim/gui_menu_builder.py:645 #, fuzzy msgid "Minimize on close" msgstr "_Minimalizovat při zavření" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 #, fuzzy msgid "Execute command" msgstr "Spustit _příkaz..." #: gajim/gui_menu_builder.py:648 #, fuzzy msgid "Disconnect" msgstr "_Odpojit" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "" #: gajim/gui_menu_builder.py:680 #, fuzzy, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "před %i dny" msgstr[1] "před %i dny" msgstr[2] "před %i dny" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Připojit se do diskuze" #: gajim/gui_menu_builder.py:734 #, fuzzy msgid "Add Contact…" msgstr "Přid_at kontakt..." #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 #, fuzzy msgid "Profile" msgstr "soubor" # FIXME: chtelo by to cesky vyraz pro service discovery #: gajim/gui_menu_builder.py:737 #, fuzzy msgid "Discover Services" msgstr "_Prohlížet služby" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Odeslat jednoduchou _zprávu" #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Rozšířené" #: gajim/gui_menu_builder.py:740 #, fuzzy msgid "Archiving Preferences" msgstr "_Nastavení" #: gajim/gui_menu_builder.py:741 #, fuzzy msgid "Synchronise History" msgstr "Synchronizovat" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "Soukromý Seznam" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 #, fuzzy msgid "Server Info" msgstr "Server" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "XML Konzole" #: gajim/gui_menu_builder.py:746 #, fuzzy msgid "Admin" msgstr "_Správce" #: gajim/gui_menu_builder.py:747 #, fuzzy msgid "Send Server Message…" msgstr "Ode_slat zprávu serveru" #: gajim/gui_menu_builder.py:748 #, fuzzy msgid "Set MOTD…" msgstr "Nastavit MOTD" #: gajim/gui_menu_builder.py:749 #, fuzzy msgid "Update MOTD…" msgstr "Upravit MOTD" #: gajim/gui_menu_builder.py:750 #, fuzzy msgid "Delete MOTD…" msgstr "Smazat MOTD" #: gajim/gui_menu_builder.py:799 #, fuzzy msgid "No Accounts available" msgstr "Žádný účet není dostupný" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Účty" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 #, fuzzy msgid "Copy JID" msgstr "JID Místnosti" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Připojit se do diskuze" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Začít rozhovor" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 #, fuzzy msgid "Add to Roster…" msgstr "Přid_at do Seznamu" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "_Kopírovat odkaz" #: gajim/gui_menu_builder.py:881 #, fuzzy msgid "Open Link in Browser" msgstr "_Otevřít v prohlížeči" #: gajim/gui_menu_builder.py:886 #, fuzzy msgid "Copy Email Address" msgstr "_Kopírovat JID/Emailovou adresu" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Otevři Emailový editor" #: gajim/gui_menu_builder.py:892 #, fuzzy msgid "Copy JID/Email" msgstr "_Kopírovat JID/Emailovou adresu" #: gajim/history_manager.py:71 #, fuzzy msgid "Usage:" msgstr "zpráva" #: gajim/history_manager.py:73 #, fuzzy msgid "Options:" msgstr "_Smajlíky:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "Nemůžu nalézt databázi s historií" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Datum" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Přezdívka" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Zpráva" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Předmět" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "Chcete pročistit databázi? (VELICE NEDOPORUČUJEME POKUD GAJIM BĚŽÍ)" #: gajim/history_manager.py:257 #, fuzzy msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" "Běžně se velikost alokovaná databází neuvolňuje, pouze se označí k novému " "použití. Pokud opravdu chcete snížit velikost databáze, klikněte ANO, jinak " "NE.\n" "\n" "V případě kliknutí na ANO prosím vyčkejte..." #: gajim/history_manager.py:262 #, fuzzy msgid "Database Cleanup" msgstr "Chyba Databáze" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(who)s v %(time)s řekl(a): %(message)s\n" #: gajim/history_manager.py:577 #, fuzzy, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Vážně chcete smazat vybranou zprávu?" #: gajim/history_manager.py:581 #, fuzzy msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "Vážně chcete smazat všechny záznamy historie vybraného kontaktu?" #: gajim/history_manager.py:583 #, fuzzy msgid "This can not be undone." msgstr "Tato služba nebyla nalezena" #: gajim/history_manager.py:585 gajim/history_manager.py:624 #, fuzzy msgid "Deletion Confirmation" msgstr "Zrušit ověření" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Vážně chcete smazat vybranou zprávu?" msgstr[1] "Vážně chcete smazat vybrané zprávy?" msgstr[2] "Vážně chcete smazat vybrané zprávy?" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "Tato operace je nevratná." #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "Jméno kontaktu: %s" #: gajim/dialogs.py:84 #, fuzzy, python-format msgid "JID: %s" msgstr "Jabber ID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "Obecné" #: gajim/dialogs.py:200 msgid "Group" msgstr "Skupina" #: gajim/dialogs.py:207 msgid "In the group" msgstr "Ve skupině" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "ID klíče" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Jméno kontaktu" #: gajim/dialogs.py:483 msgid "Set Mood" msgstr "Nastavit Náladu" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "Text stavu %s" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Text stavu" #: gajim/dialogs.py:807 msgid "Overwrite Status Message?" msgstr "Přepsat Text stavu?" #: gajim/dialogs.py:808 msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "Toto jméno je již použito. Chcete přepsat text stavu?" #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Uložit jako přednastavený stav" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Napište jméno pro tento stav" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Žádost o autorizaci" #: gajim/dialogs.py:857 #, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Žádost o autorizaci na účtu %(account)s od %(jid)s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Žádost o autorizaci od %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "Nejste připojen(a) k serveru" #: gajim/dialogs.py:928 msgid "Without a connection, you can not synchronise your contacts." msgstr "Nemůžete měnit heslo, pokud nejste připojen(a)." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Jméno" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Server" #: gajim/dialogs.py:978 msgid "This account is not connected to the server" msgstr "Tento účet není připojen k serveru" #: gajim/dialogs.py:979 msgid "You cannot synchronize with an account unless it is connected." msgstr "Nemůžete synchronyzovat účet pokud nění připojen." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "Synchronizovat" #: gajim/dialogs.py:1065 msgid "add" msgstr "přidat" #: gajim/dialogs.py:1065 msgid "modify" msgstr "upravit" #: gajim/dialogs.py:1066 msgid "remove" msgstr "odebrat" #: gajim/dialogs.py:1095 #, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "" "%(jid)s by chtěl(a), aby jste %(action)s některé kontakty z " "vašeho rosteru." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 msgid "Add" msgstr "Přidat" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 msgid "Modify" msgstr "Upravit" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Smazat" #: gajim/dialogs.py:1125 msgid "Groups" msgstr "Skupiny" #: gajim/dialogs.py:1233 #, python-format msgid "%s suggested me to add you in my roster." msgstr "%s mi doporučila přidat si Vás od mého rosteru." #: gajim/dialogs.py:1247 #, fuzzy, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "Přidáno %s kontaktů" msgstr[1] "Přidáno %s kontaktů" msgstr[2] "Přidáno %s kontaktů" #: gajim/dialogs.py:1285 #, fuzzy, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "Odstraněno %s kontaktů" msgstr[1] "Odstraněno %s kontaktů" msgstr[2] "Odstraněno %s kontaktů" #: gajim/dialogs.py:1305 msgid "You are invited to a groupchat" msgstr "Jste pozván do diskuze" #: gajim/dialogs.py:1308 msgid "$Contact has invited you to join a discussion" msgstr "$Contact Vás pozval(a) do místnosti %(room_jid)s" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "$Contact Vás pozval(a) do místnosti %(room_jid)s" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Komentář: %s" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "Chcete přijmout pozvání?" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Skupinová pozvánka" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "audio a video" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "audio" #: gajim/dialogs.py:1628 msgid "a video" msgstr "video" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "%(contact)s chce zahájit %(type) sezení. Chcete na volání odpovědět?" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 #, fuzzy msgid "File Transfer" msgstr "Přenosy souborů" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "" #: gajim/dialogs.py:1764 #, fuzzy msgid "Encrypting file…" msgstr "E2E Šifrování vypnuto" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%(nick)s se přejmenoval na %(new_nick)s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s je nyní %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Odesílání soukromé zprávy selhalo" #: gajim/groupchat_control.py:253 #, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "Už nejsi v místnosti \"%(room)s\" nebo \"%(nick)s\" odešel(a)." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 #, fuzzy msgid "No File Transfer available" msgstr "Přenos souboru dokončen" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Měním Téma" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Prosím zadejte nové téma:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Měním přezdívku" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Prosím zadejte novou přezdívku, kterou chcete používat:" #: gajim/groupchat_control.py:711 #, fuzzy msgid "Invalid group chat JID" msgstr "Neplatné Jabber ID diskuzní místnosti" #: gajim/groupchat_control.py:712 #, fuzzy msgid "The group chat JID has not allowed characters." msgstr "Jabber ID diskuze obsahuje nepřijatelné znaky." #: gajim/groupchat_control.py:724 #, python-format msgid "Destroying %s" msgstr "Likviduji: %s" #: gajim/groupchat_control.py:725 #, fuzzy msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" "Místnost bude s konečnou platností zničena.\n" "Můžete specifikovat důvod zničení:" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "Také můžete specifikovat náhradní místo:" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "Nezdařilo se načtení obrázku" #: gajim/groupchat_control.py:934 msgid "Insert Nickname" msgstr "Vložit přezdívku" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 msgid "and authenticated" msgstr "a autentizovaný" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 msgid "and NOT authenticated" msgstr "a NEautentizovaný" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, fuzzy, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" "Šifrování %(type)s %(status)s aktivní %(authenticated)s.\n" "Váš rozhovor %(logged)s zaznamenáván." #: gajim/groupchat_control.py:1157 msgid "Conversation with " msgstr "Rozhovor s" #: gajim/groupchat_control.py:1159 msgid "Continued conversation" msgstr "Pokračování v rozhovoru" #: gajim/groupchat_control.py:1525 #, fuzzy, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(jid)s nastavil předmět na %(subject)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "Každý návštěvník uvidí váš úplný JID" #: gajim/groupchat_control.py:1556 #, fuzzy msgid "Room now shows unavailable members" msgstr "Místnost nyní zobrazuje nedostupné členy" #: gajim/groupchat_control.py:1558 #, fuzzy msgid "Room now does not show unavailable members" msgstr "místnost nyní nezobrazuje nedostupné členy" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "Zaznamenávání historie je zapnuto" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "Zaznamenávání historie je vypnuto" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "Místnost není anonymní" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "Místnost je částečně anonymní" #: gajim/groupchat_control.py:1576 #, fuzzy msgid "Room is now fully anonymous" msgstr "Místnost je plně anonymní" #: gajim/groupchat_control.py:1615 #, fuzzy, python-format msgid "Ping? (%s)" msgstr "Pong! (%s s.)" #: gajim/groupchat_control.py:1618 #, fuzzy, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "Pong! (%s s.)" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 msgid "Error." msgstr "Chyba." #: gajim/groupchat_control.py:1845 #, fuzzy, python-format msgid "You (%s) joined the room" msgstr "%s vstoupil do místnosti" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, fuzzy, python-format msgid "%(jid)s has been invited in this room" msgstr "%(nick)s byli vyhozeni z místnosti: %(reason)s" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "Zaznamenávání historie je povoleno" #: gajim/groupchat_control.py:1879 msgid "A new room has been created" msgstr "Nová místnost byla vytvořena" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "Server přidělil nebo změnil název vaší místnosti" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s byli vyhozeni: %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(nick)s byli vyhozeni od %(who)s: %(reason)s" # FIXME: preklad pro ban? zabanovani je hnusne #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "%(nick)s byli zakázáni: %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(nick)s byl zakázán od %(who)s: %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "Jste nyní znám(a) jako %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(nick)s byli vyhozeni z místnosti: %(reason)s" #: gajim/groupchat_control.py:1950 msgid "affiliation changed" msgstr "Příslušnost:" #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "nastavení místnosti se změnilo na vstup pouze členům" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "vypnout systém" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "** %(actor)s nastavil(a) vztah %(nick)s na %(affiliation)s" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "** Vztah %(nick)s byl nastaven na %(affiliation)s" #: gajim/groupchat_control.py:2034 #, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "** %(actor)s nastavil(a) postavení %(nick)s na %(role)s" #: gajim/groupchat_control.py:2038 #, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "** Postavení %(nick)s bylo nastaveno na %(role)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "%s odešel(a)" #: gajim/groupchat_control.py:2067 #, python-format msgid "%s has joined the group chat" msgstr "%s vstoupil do místnosti" #: gajim/groupchat_control.py:2374 #, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Jste si jistý(á), že chcete opustit místnost \"%s\"?" #: gajim/groupchat_control.py:2376 msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "Pokud zavřete toto okno, budete odpojen(a) z této místnosti." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 #, fuzzy msgid "_Do not ask me again" msgstr "Příště _nezobrazovat" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Vyhazuji %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Můžete uvést důvod níže:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Zakazuji %s" #: gajim/chat_control.py:389 msgid "Show a list of formattings" msgstr "Zobrazit seznam formátování" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 #, fuzzy msgid "This contact does not support HTML" msgstr "Tento kontakt nepodporuje přenos souborů." #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "%(type)s stav: %(state)s, důvod: %(reason)s" #: gajim/chat_control.py:660 #, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s z diskuze %(room_name)s" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "Právě jsi obdržela novou zprávu od \"%s\"" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Pokud zavřete toto okno a historie je vypnutá, tato zpráva bude ztracena." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "Ping?" #: gajim/chat_control.py:1205 #, fuzzy, python-format msgid "Pong! (%s seconds)" msgstr "Pong! (%s s.)" #: gajim/chat_control.py:1313 #, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Předmět: %(subject)s\n" "%(message)s" #: gajim/chat_control.py:1416 #, fuzzy, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(name)s je nyní %(status)s" #: gajim/chat_control.py:1471 #, fuzzy msgid "File transfer" msgstr "Přenosy souborů" #: gajim/chat_control.py:1474 #, fuzzy msgid "Size" msgstr "Velikost: %s" #: gajim/chat_control.py:1476 #, fuzzy msgid "Accept" msgstr "Přijmi" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Vstoupit" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 msgid "Remote contact stopped transfer" msgstr "Protějšek zastavil přenos" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 msgid "Error opening file" msgstr "Chyba při čtení souboru" #: gajim/application.py:68 #, fuzzy msgid "Show the application's version" msgstr "Notification-daemon" #: gajim/application.py:75 #, fuzzy msgid "Show only critical errors" msgstr "_Zobrazit událost v rosteru" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 #, fuzzy msgid "Use defined profile in configuration directory" msgstr "Editor rozšířeného nastavení" #: gajim/application.py:105 #, fuzzy msgid "Set configuration directory" msgstr "Nastavení místnosti" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 #, fuzzy msgid "Show all warnings" msgstr "Zobrazit všechny čekající _události" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 msgid "Pops up a window with the next pending event" msgstr "Zobrazí okno s další nepřečtenou událostí" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 #, fuzzy msgid "Start a new chat" msgstr "Začít rozhovor" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "Chyba Databáze" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Spojené účty" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Transporty" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 msgid "Groupchats" msgstr "Diskuze" #: gajim/roster_window.py:2056 #, fuzzy msgid "Authorization sent" msgstr "Autorizace byla odeslána" #: gajim/roster_window.py:2057 #, fuzzy, python-format msgid "\"%s\" will now see your status." msgstr "Nyní bude \"%s\" znát váš stav." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Žádost o autorizaci byla odeslána" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "Pokud \"%s\" povolí Vaši žádost o autorizaci, budete vidět jeho stav." #: gajim/roster_window.py:2095 #, fuzzy msgid "Authorization removed" msgstr "Autorizace byla zrušena" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "Nyní Vás \"%s\" uvidí vždy jako odpojeného." #: gajim/roster_window.py:2120 #, fuzzy msgid "OpenPGP is not usable" msgstr "GPG je nepoužitelné" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Účinkujete v jedné nebo více diskuzích" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Změna vašeho stavu na neviditelný způsobí odpojení od těchto diskuzí. Jste " "si jistý(á), že se chcete stát neviditelným(ou)?" # FIXME: mozna nejak lepe? :/ #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "nesynchronizováno" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "Opravdu ukončit Gajim?" #: gajim/roster_window.py:2426 msgid "Are you sure you want to quit Gajim?" msgstr "Opravdu chcete ukončit Gajim?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "Vždy zavřít Gajim" #: gajim/roster_window.py:2514 #, fuzzy msgid "You have running file transfers" msgstr "Zrušit přenos souboru" #: gajim/roster_window.py:2515 #, fuzzy msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" "Pokud chcete teď odejít, veškeré právě probíhající přenosy budou zastaveny. " "Opravdu chcete odejít?" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Máte nepřečtené zprávy" #: gajim/roster_window.py:2547 msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "Zprávy bude možné číst později, pokud máte povolený záznam historie a " "kontakt je v rosteru." #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "Musíš si je přečíst před smazáním transportu." #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Transport \"%s\" bude smazán" #: gajim/roster_window.py:2829 msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" "Už více nebudete moci posílat i přijímat zprávy od kontaktů z tohoto " "transportu." #: gajim/roster_window.py:2832 msgid "Transports will be removed" msgstr "Transport bude smazán" #: gajim/roster_window.py:2837 #, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" "Už více nebudete moci posílat ani přijímat zprávy od kontaktů z těchto " "transportů:%s" #: gajim/roster_window.py:2891 msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "Chystáte se zablokovat kontakt. Určitě chcete pokračovat?" #: gajim/roster_window.py:2893 #, fuzzy msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" "Tento kontakt vás uvidí jako odpojeného a nebudete dostávat zprávy, které " "vám pošle." #: gajim/roster_window.py:2939 msgid "Rename Contact" msgstr "Přejmenovat kontakt" #: gajim/roster_window.py:2940 #, python-format msgid "Enter a new nickname for contact %s" msgstr "Zadej novou přezdívku pro kontakt %s." #: gajim/roster_window.py:2947 msgid "Rename Group" msgstr "Přejmenovat skupinu" #: gajim/roster_window.py:2948 #, python-format msgid "Enter a new name for group %s" msgstr "Zadej nové jméno pro skupinu %s." #: gajim/roster_window.py:2993 msgid "Remove Group" msgstr "Odstranit skupinu" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "Chceš smazat skupinu %s z rosteru?" #: gajim/roster_window.py:2995 msgid "Also remove all contacts in this group from your roster" msgstr "Odstranit také všechny kontakty v této skupině z Vašeho rosteru" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Přiřadit OpenPGP klíč" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "Vybrat klíč k použítí s kontaktem" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "Kontakt \"%s\" bude smazán z Vašeho rosteru" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "Chystáte se smazat \"%(name)s\" (%(jid)s) z vašeho rosteru.\n" #: gajim/roster_window.py:3448 #, fuzzy msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "Smazáním těchto kontaktů:%s\n" "také zrušíte autorizaci. Kontakty Vás tak vždy uvidí jako odpojeného." #: gajim/roster_window.py:3454 msgid "Do you want to continue?" msgstr "Chcete pokračovat?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "Smazáním kontaktu také zrušíte autorizaci. Kontakt Vás tak vždy uvidí jako " "odpojeného." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Chci aby tento kontakt věděl o mém stavu i po odstranění" #: gajim/roster_window.py:3465 msgid "Contacts will be removed from your roster" msgstr "Kontakty budou smazány z Vašeho rosteru" #: gajim/roster_window.py:3470 #, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "Smazáním těchto kontaktů:%s\n" "také zrušíte autorizaci. Kontakty Vás tak vždy uvidí jako odpojeného." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "Chystáte se poslat vlastní stav. Určitě chcete pokračovat?" #: gajim/roster_window.py:3531 #, fuzzy, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" "Tento kontakt váš dočasně uvidí jako %(status)s, ale pouze do první změny " "vašeho stavu. Poté uvidí váš globální stav." #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Žádný účet není dostupný" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "" "Musíte vytvořit účet před tím, než budete moci hovořit s jinými uživateli." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "Uložení metakontaktů není podporováno serverem" #: gajim/roster_window.py:4180 #, fuzzy msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" "Tvůj server nepodporuje ukládání metakontaktů. Tyto informace nebudou při " "přístím připojení uloženy." #: gajim/roster_window.py:4276 msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "Chystáte se vytvořit metacontact. Určitě chcete pokračovat?" #: gajim/roster_window.py:4278 #, fuzzy msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" "Metakontakty jsou způsob k organizaci několika kontaktů do jednoho. Obecně " "jsou užitečné, když jeden člověk má víc účtů v síti Jabber nebo účty v " "transportech." #: gajim/roster_window.py:4400 msgid "Invalid file URI:" msgstr "Neplatná cesta k souboru:" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Odeslat _Soubor" #: gajim/roster_window.py:4412 #, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "Chcete poslat %s tento soubor:" msgstr[1] "Chcete poslat %s tyto soubory:" msgstr[2] "Chcete poslat %s tyto soubory:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Odeslat %s %s" #: gajim/roster_window.py:4565 #, fuzzy, python-format msgid "Make %s first contact" msgstr "Udělej %s a %s metakontaktem" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Udělej %s a %s metakontaktem" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "Z_měnit popis stavu" #: gajim/roster_window.py:4965 msgid "Publish Tune" msgstr "_Zveřejnit hudbu" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "_Zveřejnit hudbu" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "_Nastavit služby..." #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "_Maximalizovat Vše" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 msgid "Send Group M_essage" msgstr "Ode_slat skupinovou zprávu" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "Všem uživatelům" #: gajim/roster_window.py:5135 msgid "To all online users" msgstr "Všem dostupným uživatelům" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "_Pozvat do" #: gajim/roster_window.py:5299 msgid "_Manage Contacts" msgstr "_Spravovat kontakty" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Upravit _skupiny" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "Odst_ranit" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "_Maximalizovat" #: gajim/roster_window.py:5370 msgid "_Reconnect" msgstr "_Znovu připojit" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 msgid "_Disconnect" msgstr "_Odpojit" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Historie" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Správce historie" #: gajim/roster_window.py:5475 msgid "_Join New Group Chat" msgstr "_Připojit se do diskuze" #: gajim/config.py:359 msgid "Ban List" msgstr "Ban List" #: gajim/config.py:360 msgid "Member List" msgstr "Seznam členů" #: gajim/config.py:360 msgid "Owner List" msgstr "Seznam vlastníků" #: gajim/config.py:361 msgid "Administrator List" msgstr "Seznam správců" #: gajim/config.py:435 msgid "Reason" msgstr "Důvod" #: gajim/config.py:442 msgid "Nick" msgstr "Přezdívka" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "Postavení" #: gajim/config.py:478 #, fuzzy msgid "Banning…" msgstr "Zakazuji..." #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Koho chcete zakázat?\n" "\n" #: gajim/config.py:482 #, fuzzy msgid "Adding Member…" msgstr "Přidávám člena..." #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "Kdo se má stát členem?\n" #: gajim/config.py:485 #, fuzzy msgid "Adding Owner…" msgstr "Přidávám vlastníka..." #: gajim/config.py:486 msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "Kdo se má stát vlastníkem?\n" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "Přidávám správce..." #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "Kdo se má stát správcem?\n" #: gajim/config.py:490 msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" "Může být jedno z následujících:\n" "1. uživatel@doména/zdroj (pouze zdroji, který je uveden).\n" "2. uživatel@doména (kterýkoliv zdroj odpovídá).\n" "3. doména/zdroj (pouze zdroji, který je uveden).\n" "4. doména (doména samotná odpovídá, stejně jako kterýkoliv uživatel@doména,\n" "doména/zdroj, nebo adresa obsahující poddoménu)." #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Odstraňuju účet %s" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Smajlíci byly vypnuty" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Vyžadováno heslo" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Zadejte heslo pro účet %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Uložit heslo" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Účet \"%s\" se připojil k serveru" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Pokud jej smažete, připojení bude ztraceno." #: gajim/config.py:652 #, fuzzy, python-format msgid "Connection to server %s failed" msgstr "Spojení s proxy selhalo" #: gajim/config.py:653 #, fuzzy msgid "What would you like to do?" msgstr "Co by jste rád(a) dělal(a)?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Odstranit účet _pouze z Gajimu" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Waw soubory" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "První zpráva přijata" #: gajim/config.py:746 msgid "First Message Received" msgstr "První zpráva přijata" #: gajim/config.py:747 msgid "Next Message Received Focused" msgstr "Další zpráva přijata zvýrazněná" #: gajim/config.py:748 msgid "Next Message Received Unfocused" msgstr "Další zpráva přijata nezvýrazněná" #: gajim/config.py:749 msgid "Contact Connected" msgstr "Kontakt se připojil" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "Kontakt se odpojil" #: gajim/config.py:751 msgid "Message Sent" msgstr "Zpráva odeslána" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "Zvýraznění zprávy v diskuzi" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "Přijetí zprávy v diskuzi" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "%(owner_or_admin_or_member)s této diskuze" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 msgid "?Group Chat Contact Affiliation:None" msgstr "?Group Chat Contact Affiliation:Žádná" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 msgid "Member" msgstr "Člen" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 msgid "Administrator" msgstr "Správce" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 msgid "Owner" msgstr "Vlastník" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr "[blokováno]" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr "[minimalizováno]" #: gajim/tooltips.py:574 msgid "Connected" msgstr "Spojeno" #: gajim/tooltips.py:576 msgid "Disconnected" msgstr "Odpojenol" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Stáhnout" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Nahrát" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Typ: " #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Přeneseno: " #: gajim/tooltips.py:645 msgid "Status: " msgstr "Stav: " #: gajim/tooltips.py:647 msgid "Description: " msgstr "Popis:" #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Dokončeno" #: gajim/tooltips.py:676 msgid "?transfer status:Paused" msgstr "?transfer status:Pozastaveno" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "Stagnuje" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "Přenáším" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "Nespuštěno" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "?transfer status:Pozastaveno" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Ukecaný" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Pryč" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Nerušit" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Nedostupný" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Odpojen" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "Z_měnit popis stavu" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "pomocí účtu %s" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Spravovat záložky" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "v _rosteru" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "Zobrazit _Seznam" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Skryje toto menu" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Nelze nahrát idle modul" #: gajim/dataforms_widget.py:586 #, fuzzy, python-format msgid "Media type not supported: %s" msgstr "Neviditelnost není podporována" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "Toto pole je povinné" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "new@jabber.id" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "new%d@jabber.id" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "Tato služba dosud neodpověděla s detaily" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "Tato služba nemůže odpovědět s více podrobnostmi.\n" "Pravděpodobně je stará nebo rozbitá" #: gajim/disco.py:121 msgid "Others" msgstr "Ostatní" #: gajim/disco.py:125 msgid "Conference" msgstr "Diskuze" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "Bez spojení nemůžete prohlížet dostupné služby" #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "Procházení služeb s použitím účtu %s" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Service Discovery" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "Tato služba nebyla nalezena" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "Služba na zadané adrese neexistuje, nebo neodpovídá. Zkontrolujte adresu a " "opakujte znovu." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "Službu nelze prohlížet" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "Tento typ služby neobsahuje žádné položky, které je možné prohlížet." #: gajim/disco.py:726 gajim/disco.py:736 msgid "Invalid Server Name" msgstr "Neplatné jméno serveru" #: gajim/disco.py:794 #, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "Procházím %(address)s pomocí účtu %(account)s" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Prohlížet" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "Tato služba neobsahuje žádné položky, které je možno prohlížet." #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "Spustit _příkaz..." #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "Re_gistrace" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "_Vstoupit" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "Najít" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Úpravy" #: gajim/disco.py:1450 #, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "Skenuji %(current)d / %(total)d.." #: gajim/disco.py:1649 msgid "Users" msgstr "Uživatelé" #: gajim/disco.py:1657 msgid "Description" msgstr "Popis" #: gajim/disco.py:1665 msgid "Id" msgstr "č." #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 msgid "_Bookmark" msgstr "_Záložky" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Záložka je už nastavena" #: gajim/disco.py:1722 #, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "Diskuze \"%s\" už je ve Vašich záložkách." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Záložka byla úspěšně přidána" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "Můžete spravovat Vaše záložky přes menu Akce ve vašem Seznamu." #: gajim/disco.py:1929 msgid "Subscribed" msgstr "Autorizován" #: gajim/disco.py:1938 msgid "Node" msgstr "Uzel" #: gajim/disco.py:2005 msgid "New post" msgstr "Nový záznam" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "_Žádat autorizaci" #: gajim/disco.py:2017 msgid "_Unsubscribe" msgstr "_Zrušit autorizaci" #: gajim/conversation_textview.py:320 msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" "Text pod touto čarou označuje to, co bylo řečeno \n" "po posledním čtení této diskuze" #: gajim/conversation_textview.py:541 #, fuzzy msgid "_Quote" msgstr "_Konec" #: gajim/conversation_textview.py:549 #, python-format msgid "_Actions for \"%s\"" msgstr "_Akce pro \"%s\"" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Číst článkek na _Wikipedia" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Vyhledat ve _slovníku" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "URL slovníku chybí \"%s\" a není to WIKTIONARY" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "URL pro hledání na webu chybí \"%s\"" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "_Hledat na Webu" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "Otevřít jako _Odkaz" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "Neplatné JID" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, fuzzy, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "Včera" msgstr[1] "před %i dny" msgstr[2] "před %i dny" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Nespuštěno" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Předmět: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Nová soukromá zpráva" #: gajim/message_window.py:243 msgid "You are going to close several tabs" msgstr "Chystáte se zavřít několik panelů" #: gajim/message_window.py:244 msgid "Do you really want to close them all?" msgstr "Opravdu je chcete všechny zavřít?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Diskuze" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "Soukromé rozhovory" #: gajim/message_window.py:530 msgid "Messages" msgstr "Zprávy" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 msgid "Unable to join group chat" msgstr "Nelze se připojit se do diskuze" #: gajim/gui_interface.py:170 #, fuzzy, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "Tebou požadované přezdívka se již používá v diskuzi %s nebo je " "zaregistrována někým jiným.\n" "Níže vyber jinou přezdívku:" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Chcete přijmout tuto žádost?" #: gajim/gui_interface.py:194 #, python-format msgid "Do you accept this request on account %s?" msgstr "Chcete přijmout tuto žádost na účtě %s?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "HTTP (%(method)s) Autorizace pro %(url)s (id: %(id)s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 msgid "Connection Failed" msgstr "Spojení selhalo" #: gajim/gui_interface.py:327 #, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "Pro připojení do místnosti %s je vyžadováno heslo. Zadejte, prosím." #: gajim/gui_interface.py:342 #, fuzzy, python-format msgid "%s is full" msgstr "Písmo" #: gajim/gui_interface.py:351 #, fuzzy, python-format msgid "You are banned from group chat %s." msgstr "Máš zakázán přístup do diskuze %s." #: gajim/gui_interface.py:358 #, fuzzy, python-format msgid "Remote server %s does not exist." msgstr "Diskuze %s neexistuje." #: gajim/gui_interface.py:362 #, fuzzy, python-format msgid "Group chat %s does not exist." msgstr "Diskuze %s neexistuje." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "Vytváření místností není povoleno." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Nelze se připojit se do diskuze" #: gajim/gui_interface.py:368 #, fuzzy, python-format msgid "You must use your registered nickname in %s." msgstr "Musí být použita přezdívka, jež máte zaregistrovánu v diskuzi %s." #: gajim/gui_interface.py:373 #, python-format msgid "You are not in the members list in groupchat %s." msgstr "Nejsi v seznamu členů diskuze %s." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, python-format msgid "Error %(code)s: %(msg)s" msgstr "Chyba %(code)s: %(msg)s" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, fuzzy, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "chyba při odesílání %s ( %s )" #: gajim/gui_interface.py:503 gajim/notify.py:194 msgid "Subscription request" msgstr "Žádost o autorizaci" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "Přihlížející" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Autorizace přijata" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "Kontakt \"%s\" Vás autorizoval k zobrazení jeho stavu." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Kontakt \"%s\" Vám odebral autorizaci" #: gajim/gui_interface.py:539 #, fuzzy msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" "Vždy uvidíte jeho nebo ji odpojeného/odpojenou.\n" "Opravdu jeho/ji chcete odstrani ze seznamu kontaktů?" #: gajim/gui_interface.py:560 gajim/notify.py:194 msgid "Unsubscribed" msgstr "Autorizace zrušena" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, fuzzy, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Jste pozván do diskuze" #: gajim/gui_interface.py:658 #, fuzzy msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" "Nastavily jste Gajim aby používal GPG agenta, ale žádný GPG agent není " "spuštěný nebo vrátil chybné heslo.\n" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "Momentálně jste připojen(a) bez vašeho OpenPGP klíče." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Nesprávné heslo" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Nesprávné heslo" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "Platnost certifikátu vypršela" #: gajim/gui_interface.py:683 #, fuzzy, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Zadej heslo GPG klíče pro účet %(keyid)s (účet %(account)s)." #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Vyberte Váš OpenPGP klíč" #: gajim/gui_interface.py:706 #, fuzzy msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" "GPG klíč použitý k šifrování rozhovoru není důvěryhodný. Opravdu chcete " "šifrovat tuto zprávu?" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Chyba přenosu souboru" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "%s Vám chce poslat soubor." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Žádost o přenos souboru" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "Chyba SSL certifikátu" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Přenos souboru dokončen" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Přenos souboru zastaven" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Přenos souboru dokončen" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Přenos souboru %(filename)s od %(name)s byl zastaven." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Přenos souboru %(filename)s od %(name)s byl zastaven." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Přenos souboru %(filename)s od %(name)s byl zastaven." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Soubor %(filename)s byl uspěšně odeslán %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Přenos souboru %(filename)s pro %(name)s byl zastaven." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Přenos souboru %(filename)s pro %(name)s byl zastaven." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "Konflikt uživatelských jmen" #: gajim/gui_interface.py:1178 msgid "Please type a new username for your local account" msgstr "Prosím zadejte nové uživatelské jméno pro lokální účet" #: gajim/gui_interface.py:1201 msgid "Resource Conflict" msgstr "Konflikt Zdrojů" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "Už jsi připojen(a) k tomuto účtu se stejným zdrojem. Prosím zadej nový" #: gajim/gui_interface.py:1259 #, python-format msgid "%s wants to start a voice chat." msgstr "%s chce zahájit hlasový rozhovor. " #: gajim/gui_interface.py:1261 msgid "Voice Chat Request" msgstr "Žádost o hlasový rozhovor" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 msgid "Certificate Already in File" msgstr "Certifikát je již v souboru" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "Tento certifikát je již v souboru %s, takže nebude znova přidán." #: gajim/gui_interface.py:1351 #, fuzzy, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "Autentizace certifikátu %s je neplatná." #: gajim/gui_interface.py:1354 #, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "" "\n" "Neznámá SSL chyba: %d" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" "\n" "SSL Error: %s" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "Chyba ověřování SSL certifikátu" #: gajim/gui_interface.py:1362 #, fuzzy, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" "Chyba při ověřování SSL vertifikátu na vašem jabber serveru: %(error)s\n" "Chcete se přesto připojit?" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, fuzzy, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" "Přidat tento certifikát do důvěryhodných.\n" "SHA1 otisk certifikátu:\n" "%s" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "Ignorovat tuto chybu certifikátu." #: gajim/gui_interface.py:1380 #, fuzzy, python-format msgid "SSL Certificate Verification for %s" msgstr "Chyba SSL certifikátu" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 msgid "Insecure connection" msgstr "Nezabezpečené Spojení" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" "Abyste nemuseli posílat heslo nezabezpečeným připojením nainstalujte si " "PyOpenSSL. Jste si jisti, že to chcete udělat?" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "Ano, chci se připojit nezabezpečeně" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "" "Chystáte se poslat vaše heslo nezabezpečeným spojením. Jste si jistý(á), že " "to skutečně chcete udělat?" #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "Nemůžete vstoupit do diskuze pokud nejste připojen(a)." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Tohle není diskuze" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "Tohle není diskuze" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 msgid "You cannot join a group chat while you are invisible" msgstr "Nemůžete vstoupit do diskuze, pokud jste neviditelný(á)" # FIXME: jaky je rozdil mezi settings a preferences? - kdo vi :) #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Nelze uložit Vaše nastavení" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Heslo Vyžadováno" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "Zadej heslo GPG klíče pro účet %(keyid)s (účet %(account)s)." #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "GPG klíč vypršel" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "Váš GPG klíč vypršel, k %s budete připojen(a) bez OpenPGP." #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "Nesprávné heslo" #: gajim/gui_interface.py:2853 #, fuzzy msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "Prosím zopakujte Vaše heslo pro GPG klíč, nebo stiskněte Zrušit." # FIXME: hmm kdovi co to je.. #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "Čekání na výsledky" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "Chyba v příchozím datagramu" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "Žádný výsledek" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "Programuji" #: gajim/atom_window.py:123 #, fuzzy, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "Dostal(a) jste novou položku: " msgstr[1] "Dostal(a) jste novou položku: " msgstr[2] "Dostal(a) jste novou položku: " #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "Dostal(a) jste novou položku: " #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "Ad-hoc příkazy - Gajim" #: gajim/adhoc_commands.py:326 msgid "Cancel confirmation" msgstr "Zrušit ověření" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "Právě se provadí příkaz. Chcete ho skutečně přerušit?" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "Služba odeslala chybné data" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "Služba změnila identifikátor sezení." #: gajim/adhoc_commands.py:422 #, fuzzy, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "Ad-hoc příkazy - Gajim" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "Služba vrátila chybu." #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Kontakt se přihlásil" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Kontakt se odhlásil" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Nová zpráva" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Nová jednoduché zpráva" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Nová soukromá zpráva" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 msgid "Contact Changed Status" msgstr "Kontakt změnil stav" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenGPG" #: gajim/notify.py:270 msgid "New E-mail" msgstr "Nový E-mail" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "Nemůžete vstoupit do diskuze pokud nejste připojen(a)." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 msgid "Invalid JID" msgstr "Neplatné JID" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "Není možné poslat zprávu kontaktu %s, takové JID není platné." #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "Nepřečtené zprávy" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "Přečtěte si všechny čekající zprávy, než smažete tento účet." #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "Nejste přávě připojen(a) k serveru" #: gajim/dialog_messages.py:53 msgid "To disable the account, you must be disconnected." msgstr "Chcete-li deaktivovat účet, musíte se nejdříve odpojit." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Neplatná místnost" #: gajim/dialog_messages.py:58 #, fuzzy msgid "The form is not filled correctly." msgstr "Jabber ID diskuze obsahuje nepřijatelné znaky." #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Neviditelný" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "Spojení není dostupné" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "Va¹e zpráva nemù¾e být odeslána dokud se nepøipojíte." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "Jabber ID je již na seznamu" #: gajim/dialog_messages.py:73 #, fuzzy msgid "The JID you entered is already in the list. Choose another one." msgstr "Jabber ID je již na seznamu. Vyberte jiné." #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "Neplatná odpověď" #: gajim/dialog_messages.py:78 #, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "Transport %(name)s odpověděl chybně na požadavek registrace: %(error)s" #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Použít vlastní jméno počítače/port" #: gajim/dialog_messages.py:84 #, fuzzy, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Použít vlastní jméno počítače/port" #: gajim/dialog_messages.py:88 msgid "Error while removing privacy list" msgstr "Chyba při odebírání privacy listu" #: gajim/dialog_messages.py:89 #, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" "Privacy list %s nebyl odstraněn. Možná je aktivní v jednom z připojených " "zdrojů. Zruště jeho používání a zkuste znovu." #: gajim/dialog_messages.py:95 msgid "Invisibility not supported" msgstr "Neviditelnost není podporována" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "Účet %s nepodporuje neviditelnost." #: gajim/dialog_messages.py:100 msgid "Unregister failed" msgstr "Odregistrace selhala" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "Zrušení registrace ze serveru %(server)s selhalo: %(error)s" #: gajim/dialog_messages.py:105 msgid "Registration succeeded" msgstr "Registrace úspěšná" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "Registrace k agentu %s uspěla" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 msgid "Registration failed" msgstr "Registrace selhala" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" "Registrace s agentem %(agent)s failed with error %(error)s: %(error_msg)s" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Nelze se připojit se do diskuze" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, fuzzy, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "Chybová zpráva: %s" #: gajim/dialog_messages.py:126 msgid "Wrong host" msgstr "Nesprávné jméno počítače" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "Neplatná místní adresa? :-O" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "Chyba Avahi" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" "%s\n" "Zasílání lokálních zpráv nemusí fungovat správně." #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 #, fuzzy msgid "Could not request upload slot" msgstr "Nepodařilo se spustit lokální službu" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 #, fuzzy msgid "Could not open file" msgstr "Nezdařilo se načtení obrázku" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 #, fuzzy msgid "Server returned unsecure transport (HTTP)" msgstr "Služba vrátila chybu." #: gajim/dialog_messages.py:161 #, fuzzy msgid "Could not upload file" msgstr "Nezdařilo se načtení obrázku" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 #, fuzzy msgid "Encryption Error" msgstr "E2E Šifrování vypnuto" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "Spojení není dostupné" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "publikování vizitky se nezdařilo" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "D-Bus není přítomna na tohto stroji nebo modul pythonu chybí" #: gajim/gajim_remote.py:77 msgid "Shows a help on specific command" msgstr "Zobrazí nápovědu pro konkrétní příkaz" #: gajim/gajim_remote.py:80 msgid "command" msgstr "příkaz" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "zobraz nápovědu k příkazu" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "Vytiskne seznam všech kontaktů v rosteru. Každý kontakt se objeví na " "samostatném řádku" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "účet" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "zobraz pouze kontakty zadaného účtu" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "Vypíše seznam registrovaných účtů" #: gajim/gajim_remote.py:97 #, fuzzy msgid "Changes the status of account(s)" msgstr "Změní stav účtu nebo účtů" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "stav" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "" "jeden z: odpojen, připojen, ukecaný, pryč, nedostupný, nerušit, neviditelný " #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "zpráva" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "text stavu" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "změnit stav účtu \"account\". Pokud není uveden, zkuste změnit stav všech " "účtů které mají povolenu volbu \"sync with global status\" " #: gajim/gajim_remote.py:108 #, fuzzy msgid "Changes the priority of account(s)" msgstr "Změní prioritu jednoho nebo více účtů" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "priorita" #: gajim/gajim_remote.py:110 msgid "priority you want to give to the account" msgstr "priorita vámi přidělená účtu" #: gajim/gajim_remote.py:112 #, fuzzy msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "změnit stav účtu \"account\". Pokud není uveden, zkuste změnit stav všech " "účtů které mají povolenu volbu \"sync with global status\" " #: gajim/gajim_remote.py:118 msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Poslat nový rozhovor kontaktu v Seznamu. Obojí OpenPGP klíč a účet jsou " "volitelné. Pokud chcete nastavit pouze 'account' bez 'OpenPGP key', nastavte " "prostě 'OpenPGP key' na ''." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID kontaktu, který obdrží zprávu" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "Tělo zprávy" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "pokud bude uvedeno, zpráva bude zašifrována tímto veřejným klíčem" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "pokud bude uvedeno, zpráva bude odeslána z tohoto účtu" #: gajim/gajim_remote.py:131 #, fuzzy msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Poslat nový rozhovor kontaktu v Seznamu. Obojí OpenPGP klíč a účet jsou " "volitelné. Pokud chcete nastavit pouze 'account' bez 'OpenPGP key', nastavte " "prostě 'OpenPGP key' na ''." #: gajim/gajim_remote.py:136 msgid "subject" msgstr "předmět" #: gajim/gajim_remote.py:136 msgid "message subject" msgstr "předmět zprávy" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "Poslat novou zprávu do diskuze ke které jste připojeni." #: gajim/gajim_remote.py:147 msgid "JID of the room that will receive the message" msgstr "JID diskuze do které přijde zpráva" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Získej detailní informace o kontaktu" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "JID kontaktu" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "Získej detailní informace o účtu" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "Jméno účtu" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Pošle soubor kontaktu" #: gajim/gajim_remote.py:168 msgid "file" msgstr "soubor" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Cesta k souboru" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "pokud bude uvedeno, zpráva bude odeslána z tohoto účtu" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Vypíše všechna nastavení a jejich hodnoty" # FIXME: opravit, pokud je mozne prekladat i key & value #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "Nastaví hodnotu klíče 'key' na hodnotu 'value'" #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "klíč=hodnota" # FIXME: opet #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "'klíč' je jméno volby, 'hodnota' je hodnota která se nastavuje" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "Smaže položku nastavení" #: gajim/gajim_remote.py:188 msgid "key" msgstr "klíč" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "jméno volby, která bude smazána" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "Zapíše aktuální nastavení do souboru .config" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Odstraní kontakt ze Seznamu" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "pokud uvedeno, kontakt bude vzít ze seznamu kontaktů pro tento účet" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "Vrátí aktuální stav (globální, pokud není uveden účet)" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "Vrací aktuální popis stavu (globální, pokud není uveden účet)" #: gajim/gajim_remote.py:221 msgid "Returns number of unread messages" msgstr "Vrací počet nepřečtených zpráv" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "Poslat vlastní XML" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "XML k odeslání" #: gajim/gajim_remote.py:229 #, fuzzy msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" "Účet, ze kterého bude xml odesláno; pokud nebude uvedeno, xml bude odeslání " "ze všech účtů" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Změnit stav" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "Přezdívka kterou chete použít" #: gajim/gajim_remote.py:238 #, fuzzy msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" "Účet, ze kterého bude xml odesláno; pokud nebude uvedeno, xml bude odeslání " "ze všech účtů" #: gajim/gajim_remote.py:245 msgid "Check if Gajim is running" msgstr "Zkontrolujte, zda Gajim již běží." #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "Chybí parametry \"contact_jid\"" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "'%s' není ve vašem Seznamu.\n" "Prosím uveďte účet, přes který bude odeslána zpráva." #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "Nemáte aktivní účet" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "Vypadá to, že Gajim neběží. Proto nemůžete použít gajim-remote" #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" "Použití: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Parametry:" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "%s nebyl nalezen" #: gajim/gajim_remote.py:383 #, fuzzy, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Použití: %s příkaz [parametry]\n" "Příkaz je jeden z:\n" #: gajim/gajim_remote.py:453 #, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Příliš mnoho parametrů. \n" "Napište \"%(basename)s help %(command)s\" pro více informací" #: gajim/gajim_remote.py:458 #, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Parametr \"%(arg)s\" nebyl uveden. \n" "Napište \"%(basename)s help %(command)s\" pro více informací" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "dvanáct" #: gajim/common/fuzzyclock.py:36 msgid "one" msgstr "jeden" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "dva" #: gajim/common/fuzzyclock.py:36 msgid "three" msgstr "tři" #: gajim/common/fuzzyclock.py:36 msgid "four" msgstr "čtyři" #: gajim/common/fuzzyclock.py:37 msgid "five" msgstr "pět" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "šest" #: gajim/common/fuzzyclock.py:37 msgid "seven" msgstr "sedm" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "osm" #: gajim/common/fuzzyclock.py:37 msgid "nine" msgstr "devět" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "deset" #: gajim/common/fuzzyclock.py:38 msgid "eleven" msgstr "jedenáct" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "%(0)s hodin" #: gajim/common/fuzzyclock.py:46 #, python-format msgid "five past %(0)s" msgstr "pět po %(0)s" #: gajim/common/fuzzyclock.py:47 #, python-format msgid "ten past %(0)s" msgstr "deset po %(0)s" #: gajim/common/fuzzyclock.py:48 #, python-format msgid "quarter past %(0)s" msgstr "čtvrt po %(0)s" #: gajim/common/fuzzyclock.py:49 #, python-format msgid "twenty past %(0)s" msgstr "dvacet po %(0)s" #: gajim/common/fuzzyclock.py:50 #, python-format msgid "twenty five past %(0)s" msgstr "dvacet pět po %(0)s" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "půl %(0)s" #: gajim/common/fuzzyclock.py:52 #, python-format msgid "twenty five to %(1)s" msgstr "dvacet pět do %(1)s" #: gajim/common/fuzzyclock.py:53 #, python-format msgid "twenty to %(1)s" msgstr "dvacet do %(1)s" #: gajim/common/fuzzyclock.py:54 #, python-format msgid "quarter to %(1)s" msgstr "tři čtvrtě na %(1)s" #: gajim/common/fuzzyclock.py:55 #, python-format msgid "ten to %(1)s" msgstr "za deset %(1)s" #: gajim/common/fuzzyclock.py:56 #, python-format msgid "five to %(1)s" msgstr "za pět %(1)s" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "%(1)s hodin" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "Noc" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "Brzy ráno" #: gajim/common/fuzzyclock.py:63 msgid "Morning" msgstr "Ráno" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "Skoro poledne" #: gajim/common/fuzzyclock.py:65 msgid "Noon" msgstr "Poledne" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "Odpoledne" #: gajim/common/fuzzyclock.py:67 msgid "Evening" msgstr "Večer" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "Pozdě večer" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "Začátek týdne" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "Uprostřed týdne" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "Konec týdne" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "Víkend!" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, python-format msgid "%s is a directory but should be a file" msgstr "%s je adresář, ale měl by to být soubor" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Jím" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 msgid "Room has been destroyed" msgstr "Místnost byla zničena" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "Můžete se připojit do této místnosti: %s" #: gajim/common/connection_handlers_events.py:598 #, python-format msgid "Unknown SSL error: %d" msgstr "Neznámá SSL chyba: %d" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Nová zpráva od %(nickname)s" msgstr[1] "Nová zpráva od %(nickname)s" msgstr[2] "Nová zpráva od %(nickname)s" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s Změnil(a) stav" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s se přihlásil" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "%(nickname)s se odhlásil" #: gajim/common/contacts.py:427 msgid "Not in roster" msgstr "Není v rosteru" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "Přehrávat zvuk, je-li uživatel zaneprázdněn" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "Zobraz v rosteru pouze online kontakty nebo kontakty hledající pokec." #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "Čas v minutách, po kterém se Váš stav přepne na pryč." #: gajim/common/config.py:87 msgid "$S (Away as a result of being idle more than $T min)" msgstr "$S (Pryč z důvodu nečinosti po více než $T minut)" # FIXME: asi blbe #: gajim/common/config.py:87 #, fuzzy msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "$S bude změněn na aktuální stav, čas: $T" #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "Čas v minutách, po kterém se Váš stav přepne na nedostupný." #: gajim/common/config.py:90 msgid "$S (Not available as a result of being idle more than $T min)" msgstr "$S (Nedostupný z důvodu nečinosti po více než $T minut)" # FIXME: asi blbe #: gajim/common/config.py:90 #, fuzzy msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "$S bude změněn na aktuální stav, čas: $T" #: gajim/common/config.py:93 #, fuzzy msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" "Kdy zobrazit ikonu v oznamovací oblasti. Může být jedno z nikdy='never', při " "události='on_event', vždy='always'." #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "_Zobrazit událost v rosteru" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "_Zobrazit událost v rosteru" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "Zobrazit náhled nové zprávy ve vyskakovacím okně?" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Požadavek přenosu souboru" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Přenos souboru zrušen" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "Zobraz upozornění, až bude přenos souboru dokončen" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "Skupinová pozvánka" #: gajim/common/config.py:106 #, fuzzy msgid "Background color of status changed notification" msgstr "Barva pozadí kontaktů, jež se zrovna přihlásili." #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "" "Seznam (oddělené mezerami) řádků (účtů a skupin), které budou \"zhroucené\"." #: gajim/common/config.py:109 msgid "default" msgstr "výchozí" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "Jazyk použitý kontrolou pravopisu" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" "'vždy' - vypiš čas pro každou zprávu.\n" "'někdy' - vypiš čas každou print_ichat_every_foo_minutes minutu.\n" "'nikdy' - nevypisuj čas." #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" "Vypiš čas v rozhovorech s použitím Fuzzy Clock. Hodnota náhodnosti je od 1 " "to 4, nebo 0 pro vypnutí Fuzzy Clock. 1 je nejpřesnější čas, 4 nejméně " "přesný. Toto se použije jenom při print_time nastaveném na 'někdy'." #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "Ber * / _ páry jako možné formátovací znaky." #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "Pokud zapnuto, nemažte */_ . Potom *abc* bude tučně ale s * * neodstraněnými." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" "Pokud je vybráno, použije ReStructured text markup k odeslání HTML, navíc s " "ascii formátování. Pro syntaxi navštivte http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html (Pokud si to chcete prohlédnout, " "nainstalujte docutils)" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" "Znak, který se přidá za přezdívku po použití doplňování jména tabulátorem v " "diskuzi." #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" "Znak navržený pro přidání za zamýšlenou přezdívku, pokud už ji používá někdo " "jiný v diskuzi." #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" "Tato volba umožní vlastní formátování času, který je zobrazován v " "rozhovorech. Například \"[%H:%M]\" zobrazí \"[hodina:minuta]\". Pro víc " "informací shlédněte dokumentaci pythonu funkce strftime na: http://docs." "python.org/lib/module-time.html" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "Znaky, které budou vypisovány před přezdívkou v rozhovorech" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "Znaky, které budou vypisovány za přezdívkou v rozhovorech" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Přidat * a [n] k titulku Seznamu?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Jak moc řádků si pamatovat z předchozího rozhovoru, když je okno/záložka " "rozhovoru znovu otevřena." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 #, fuzzy msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "Kolik řádek požadovat od serveru při připojení k diskuzi." #: gajim/common/config.py:177 #, fuzzy msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "Kolik minut zpátky do historie při připojení k diskuzi." #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" "Kolik vteřin čekat před automatickým znovu vstoupením do diskuze, ze které " "jste odpojován(a). Nastavte na 0 pro vypnutí automatického znovu vstoupení." #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" "Odeslat zprávu při Ctrl+Enter a při Enter přejít na nový řádek (výchozí " "chování klienta Mirabilis ICQ)." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Kolik řádků uložit pro Ctrl+Šipka nahoru." #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Buď vlastní url s %s v těle, kde %s je slovo nebo fráze, nebo 'WIKTIONARY', " "která znamená že se použije wiktionary." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "Pokud zaškrtnuta, Gajim může být ovládán vzdáleně pomocí gajim-remote." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" "Odešílat události stavu rozhovoru. Může být pouze jediná, composing_only, " "vypnutá." #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" "Zobraz stavy rozhovoru v okně rozhovoru. Může být jedno z all, " "composing_only nebo disabled." #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" "Když nevypisuji čas pro každou zprávu (print_time=='někdy'), vypisuj ji " "každých x minut." #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Ptát se před zavřením oken/záložek diskuzí." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" "Vždy se ptát před zavřením oken/panelů diskuzí uvedených v tomto seznamu " "mezerami oddělením Jabber ID místností." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" "Nikdy se neptát před zavřením oken/záložek diskuzí uvedených v tomto seznamu " "mezerami oddělenými Jabber ID místností." #: gajim/common/config.py:196 #, fuzzy msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" "Ptát se před zavřením okna s panely rozhovorů, jsou-li tam prvky, které " "mohou ztratit data (rozhovor, soukromý rozhovor, diskuze které nebudou " "minimalizovány)" #: gajim/common/config.py:199 #, fuzzy msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" "Čárkami oddělený seznam počítačů kterým posíláme, navíc k lokálním síťovým " "rozhraním, pro přenos souborů v případě překladu adres nebo přesměrováním " "portů." #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "IEC standard říká KiB = 1024 bytů, KB = 1000 bytů." #: gajim/common/config.py:202 #, fuzzy msgid "Notify of events in the notification area." msgstr "Upozorni na události v systémovém trayi." #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Zobrazit záložku při jediném rozhovoru?" #: gajim/common/config.py:210 msgid "Show tabbed notebook border in chat windows?" msgstr "Zobrazit okraj panelu v oknech rozhovorů?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Zobrazit tlačitko zavřít v záložce?" #: gajim/common/config.py:224 msgid "Preview new messages in notification popup?" msgstr "Zobrazit náhled nové zprávy ve vyskakovacím okně?" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "Středníkem oddělený seznam slov, které budou zvýrazněny v diskuzích." #: gajim/common/config.py:228 #, fuzzy msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" "Pokud zapnuto, ukonči Gajim když bude stisknuto tlačítko X v titulku okna. " "Toto nastavení se použije pouze tehdy, pokud je použita ikona v trayi." #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 #, fuzzy msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" "Pokud zapnuto, Gajim zobrazí ikonu v každé záložce obsahující nepřečtené " "zprávy. V závislosti na tématu, tato ikona může být animovaná." #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" "Pokud zapnuto, Gajim zobrazí popis stavu, pokud není prázdný, pro každý " "kontakt pod jménem v okně Seznamu." #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "Nastavení pozice avatara v rosteru. Může být vlevo nebo vpravo" #: gajim/common/config.py:238 #, fuzzy msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" "Pokud vypnuto, Gajim nebude zobrazovat stavové řádky v rozhovorech, když " "kontakt změní jeho stav a/nebo jeho stavovou zprávu." #: gajim/common/config.py:239 #, fuzzy msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" "může být \"none\", \"all\", \"in_and_out\". Pokud je \"none\", Gajim nebude " "nadále vypisovat stavy v diskuzích když účastník změní svůj stav nebo " "stavovou zprávu. Pokud je \"all\", Gajim bude vypisovat všechny změny stavů. " "Při \"in_and_out\" Gajim vypíše stav jenom při vstupu a odchodu z místnosti." #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 #, fuzzy msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" "Pokud je povoleno, minulé zprávy budou vypsány menším písmem, než je výchozí." #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "Nezobrazuj avatara pro transport samotný." #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "Nezobrazuj roster v liště úloh." #: gajim/common/config.py:245 #, fuzzy msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" "Pokud je True a instalované GTK+ a PyGTK verze jsou alespoň 2.8, blikej " "oknem (výchozí chování ve většině Window Managerů) pokud čekají nové " "události." #: gajim/common/config.py:249 #, fuzzy msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" "Řídí okno, kam budou doručeny nové zprávy.\n" "'vždy' - Všechny zprávy jsou odeslány do jediného okna.\n" "'nikdy' - Všechny zprávy dostanou svoje vlastní okno.\n" "'peracct' - Zprávy pro každý účet jsou doručeny do zvláštních oken.\n" "'pertype' - Každý typ zprávy (např. rohovor vs diskuze) jsou odeslány do " "zvláštního okna. Vězte, že změna této volby vyžaduje restartování Gajimu, " "aby se projevila" #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "Pokud je False, nebudete nadále vidět avatary v okně rozhovoru" #: gajim/common/config.py:252 #, fuzzy msgid "If true, pressing the escape key closes a tab/window." msgstr "Pokud je True, stiskem escape zavřete panel nebo okno" #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "Skryje nadpis v okně diskuze" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "Skryje nadpis v okně rozhovoru dvou lidí" #: gajim/common/config.py:255 msgid "Hides the group chat occupants list in group chat window." msgstr "Skryje seznam lidí místnosti v okně diskuze." #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" "V rozhovoru zobraz přezdívku na začátku řádku pouze v případě, když to není " "stejný člověk, jako v předchozí zprávě." # FIXME: netusim co to je... najit #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "Odsazení při použítí spojení po sobě jdoucích přezdívek." #: gajim/common/config.py:258 msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "" "Seznam barev, oddělený pomocí \":\", použitý k obarvení přezdívek v " "diskuzích." #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "Ctrl-Tab jde na další rozepsanou záložku, když žádný není nepřečtená." #: gajim/common/config.py:260 #, fuzzy msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" "Mám zobrazit dialog vytvoření metakontaktu nebo ne? Prázdný řetezec znamená " "nikdy nezobrazovat dialog." #: gajim/common/config.py:261 #, fuzzy msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" "Mám zobrazit dialog potvrzení blokace, nebo ne? Prázdný řetezec znamená " "nikdy nezobrazovat dialog." #: gajim/common/config.py:262 #, fuzzy msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" "Mám zobrazit dialog vlastního stavu nebo ne? Prázdný řetezec znamená nikdy " "nezobrazovat dialog." #: gajim/common/config.py:263 #, fuzzy msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" "Je-li povoleno, bude možné použít zápornou prioritu účtu v okně úprava účtu. " "BUĎ OPATRNÝ, když jsi přihlášen se zápornou prioritou, nedostaneš od serveru " "žádnou zprávu." #: gajim/common/config.py:264 #, fuzzy msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" "Je-li povoleno, Gajim zobrazí počet dostupných a všech kontaktů v účtu a u " "řádků skupin." #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" "Může být prázdný, 'chat' nebo 'message'. Není-lí prázdné, považuj všechny " "příchozí zprávy jako uvedený typ" #: gajim/common/config.py:266 #, fuzzy msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" "Je-li povoleno, Gajim bude posune a vybere kontakt, který vám poslal " "poslední zprávu, pokud již okno rozhovoru není otevřené." #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "Čas neaktivity před zavřením okna změny stavu." #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" "Maximální počet řádků, které se vypíší v konverzacích. Nejstarší řádky jsou " "smazány." #: gajim/common/config.py:269 #, fuzzy msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" "Je-li povoleno, Upozorňovací démon přidá upozornění do systémové lišty." #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "Vyberte interval mezi dvěma stavy nečinnosti." #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" "Platná uri schémata. Pouze schémata v tomto seznamu budou akceptována jako " "\"skutečné\" URI. (mailto a xmpp jsou obsluhovány zvlášť)" #: gajim/common/config.py:272 #, fuzzy msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" "Je-li True, doplňování přezdívek v diskuzích bude porobné doplňování shellu" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" "Kdy bude zobrazena řádka vlastního kontaktu. Může být \"always\", " "\"when_other_resource\" nebo \"never\"" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 #, fuzzy msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" "Pokud zaškrtnuto, Gajim se nebude pokáždé ptát na zprávu stavu. Místo toho " "použije výchozí nadefinovanou zprávu." #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 #, fuzzy msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" "Je-li povoleno, Gajim použije Gnome Keyring (je-li dostupný) k uložení hesel " "k účtům." #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" "Priorita se změní automaticky podle tvého stavu. Priority jsou definovány v " "nastavení jako položky autopriority_*." #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" "Stav použitý při auto-připojení. Může být 'připojen', 'ukecaný', 'pryč', " "'nedostupný', 'nerušit', 'neviditelný'. POZNÁMKA: toto nastavení může být " "použito pouze pokud restore_last_status je vypnutý" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "Je-li povoleno, nastaví se vždy poslední použitý stav." #: gajim/common/config.py:325 #, fuzzy msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "Je-li True, kontakty požadující autorizaci budou automaticky přijaty." #: gajim/common/config.py:326 msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "" "Pokud je False, účet bude deaktivován a nebude zobrazen v okně rosteru." #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" "Je-li zakázáno, spojení nebude podepsané GPG klíčem, pokud je GPG klíč " "nastavený." #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 #, fuzzy msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "Zobrazit varování před odesláním hesla přes nezabezpečené spojení." #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "Zobrazit varování před použitím standartní SSL knihovny." #: gajim/common/config.py:337 #, fuzzy msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "Zobrazit varování před odesláním hesla přes nezabezpečené spojení." #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "Mezerami oddělovaný seznam ssl chyb, které se mají ignorovat." #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "Při neaktivitě odeslán bílý znak" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "XMPP ping zaslán při neaktivitě" #: gajim/common/config.py:354 #, fuzzy msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" "Kolik sekund se má čekat na odpověď pingu před tím, než se znovu pokusit o " "připojení." #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "Jabberd2 workaround" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" "Pokud je zaškrtnuto, Gajim použije Vaší IP a proxy servery definované ve " "volbě pro přenos souborů file_transfer_proxies." #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "Odpověď na doručení žádosti" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "Poslat žádost" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "Pokud je zaškrtnuto, Gajim se připojí do této místnosti při spuštění" #: gajim/common/config.py:386 #, fuzzy msgid "Allow Gajim to send your local time." msgstr "%s Vám chce poslat soubor." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Prosím vyplňte údaje o kontaktu, který chcete přidat" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Anonymní autentizace" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Anon_ymní autentizace" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Anon_ymní autentizace" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 #, fuzzy msgid "Language for which misspelled words will be checked" msgstr "Jazyk, pro který chcete kontrolovat překlepy ve slovech" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 #, fuzzy msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "Kolik řádek požadovat od serveru při připojení k diskuzi." #: gajim/common/config.py:442 #, fuzzy msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "Kolik minut zpátky do historie při připojení k diskuzi." #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "Spím" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Hned jsem zpět" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Jsem zpátky za pár minut." #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "Jím" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "Právě jím, prosím zanechte mi zprávu." #: gajim/common/config.py:454 msgid "Movie" msgstr "Film" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "Dívám se na film." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "Pracuji" #: gajim/common/config.py:455 msgid "I'm working." msgstr "Právě pracuji." #: gajim/common/config.py:456 msgid "Phone" msgstr "Telefon" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Zrovna telefonuji." #: gajim/common/config.py:457 msgid "Out" msgstr "Venku" #: gajim/common/config.py:457 msgid "I'm out enjoying life." msgstr "Užívám si života venku." #: gajim/common/config.py:468 msgid "I'm available." msgstr "Jsem dostupný." #: gajim/common/config.py:469 msgid "I'm free for chat." msgstr "Hledám někoho na pokec." #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "Hned jsem zpět." #: gajim/common/config.py:471 msgid "I'm not available." msgstr "Nejsem dostupný." #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "Nerušit." #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "Zdar!" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" "Zvuk, který bude přehrán, pokud zpráva diskuze obsahuje jedno ze slov v " "muc_highlight_words, nebo když obsahuje Vaši přezdívku." #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "Přehraný zvuk při příchodu jakékoliv MUC zprávy." #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "Příjemce" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Chyba: nemůžu otevřít %s pro čtení" #: gajim/common/const.py:205 msgid "Doing Chores" msgstr "Domácí práce" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "Nakupuji potraviny" #: gajim/common/const.py:207 msgid "Cleaning" msgstr "Uklízím" #: gajim/common/const.py:208 msgid "Cooking" msgstr "Vařím" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "Dělám údržbu" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "Umývám nádobí" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "Peru" #: gajim/common/const.py:212 msgid "Gardening" msgstr "Zahradničím" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "Vyřizuji" #: gajim/common/const.py:214 msgid "Walking the Dog" msgstr "Venčím psa" #: gajim/common/const.py:216 #, fuzzy msgid "Drinking" msgstr "Piju" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "Piju pivo" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "Na kávě" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "Dávám si čaj" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "Svačím" #: gajim/common/const.py:223 #, fuzzy msgid "Having Breakfast" msgstr "Snídám" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "Večeřím" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "Obědvám" #: gajim/common/const.py:227 msgid "Exercising" msgstr "Cvičím" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "Jedu na kole" #: gajim/common/const.py:229 msgid "Dancing" msgstr "Tančím" #: gajim/common/const.py:230 msgid "Hiking" msgstr "Na výšlapu" #: gajim/common/const.py:231 msgid "Jogging" msgstr "Běhám" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "Sportuji" #: gajim/common/const.py:233 msgid "Running" msgstr "Běhám" #: gajim/common/const.py:234 msgid "Skiing" msgstr "Lyžuji" #: gajim/common/const.py:235 msgid "Swimming" msgstr "Plavu" #: gajim/common/const.py:236 msgid "Working out" msgstr "Posiluji" #: gajim/common/const.py:238 #, fuzzy msgid "Grooming" msgstr "Pečuji o sebe" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "V lázních" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "Čistím si zuby" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "U holiče" #: gajim/common/const.py:242 msgid "Shaving" msgstr "Holím se" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "Koupu se" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "Sprchuji se" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "Mám schůzku" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Neaktivní" #: gajim/common/const.py:249 msgid "Day Off" msgstr "Den volna" #: gajim/common/const.py:250 #, fuzzy msgid "Hanging out" msgstr "Venku za zábavou" #: gajim/common/const.py:251 msgid "Hiding" msgstr "Skrývám se" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "Na dovolené" #: gajim/common/const.py:253 msgid "Praying" msgstr "Modlím se" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "Plánovaná dovolená" #: gajim/common/const.py:256 msgid "Thinking" msgstr "Přemýšlím" #: gajim/common/const.py:258 #, fuzzy msgid "Relaxing" msgstr "Relaxuji" #: gajim/common/const.py:259 msgid "Fishing" msgstr "Rybařím" #: gajim/common/const.py:260 msgid "Gaming" msgstr "Hraji hry" #: gajim/common/const.py:261 #, fuzzy msgid "Going out" msgstr "Venku" #: gajim/common/const.py:262 msgid "Partying" msgstr "Na párty" #: gajim/common/const.py:263 msgid "Reading" msgstr "Čtu si" #: gajim/common/const.py:264 #, fuzzy msgid "Rehearsing" msgstr "Nacvičuji" #: gajim/common/const.py:265 msgid "Shopping" msgstr "Nakupuji" #: gajim/common/const.py:266 msgid "Smoking" msgstr "Kouřím" #: gajim/common/const.py:267 msgid "Socializing" msgstr "Ve společnosti" #: gajim/common/const.py:268 msgid "Sunbathing" msgstr "Opaluji se" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "Sleduji TV" #: gajim/common/const.py:270 msgid "Watching a Movie" msgstr "Dívám se na film" #: gajim/common/const.py:272 msgid "Talking" msgstr "Povídám si" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "Ve skutečném světě" #: gajim/common/const.py:274 msgid "On the Phone" msgstr "Telefonuji" #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "Mám videohovor" #: gajim/common/const.py:277 msgid "Traveling" msgstr "Cestuji" #: gajim/common/const.py:278 msgid "Commuting" msgstr "Dojíždím" #: gajim/common/const.py:280 msgid "Driving" msgstr "Řídím" #: gajim/common/const.py:281 msgid "In a Car" msgstr "V autě" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "V autobuse" #: gajim/common/const.py:283 msgid "On a Plane" msgstr "V letadle" #: gajim/common/const.py:284 msgid "On a Train" msgstr "Ve vlaku" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "Na výletě" #: gajim/common/const.py:286 msgid "Walking" msgstr "Na procházce" #: gajim/common/const.py:289 msgid "Coding" msgstr "Programuji" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "Na setkání" #: gajim/common/const.py:291 msgid "Studying" msgstr "Učím se" #: gajim/common/const.py:292 msgid "Writing" msgstr "Píši" #: gajim/common/const.py:295 msgid "Afraid" msgstr "Vylekaný" #: gajim/common/const.py:296 msgid "Amazed" msgstr "Užaslý" #: gajim/common/const.py:297 msgid "Amorous" msgstr "Milující" #: gajim/common/const.py:298 msgid "Angry" msgstr "Rozzlobený" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "Mrzutý" #: gajim/common/const.py:300 msgid "Anxious" msgstr "Znepokojený" #: gajim/common/const.py:301 msgid "Aroused" msgstr "Vzrušený" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "Zahanbený" #: gajim/common/const.py:303 msgid "Bored" msgstr "Znuděný" #: gajim/common/const.py:304 msgid "Brave" msgstr "Statečný" #: gajim/common/const.py:305 msgid "Calm" msgstr "Klidný" #: gajim/common/const.py:306 msgid "Cautious" msgstr "Opatrný" #: gajim/common/const.py:307 msgid "Cold" msgstr "Chladný" #: gajim/common/const.py:308 msgid "Confident" msgstr "Sebevědomý" #: gajim/common/const.py:309 msgid "Confused" msgstr "Zmatený" #: gajim/common/const.py:310 msgid "Contemplative" msgstr "Zamyšlený" #: gajim/common/const.py:311 msgid "Contented" msgstr "Spokojený" #: gajim/common/const.py:312 msgid "Cranky" msgstr "Potrhlý" #: gajim/common/const.py:313 msgid "Crazy" msgstr "Šílený" #: gajim/common/const.py:314 msgid "Creative" msgstr "Tvořivý" #: gajim/common/const.py:315 msgid "Curious" msgstr "Zvědavý" #: gajim/common/const.py:316 msgid "Dejected" msgstr "Odmítnutý" #: gajim/common/const.py:317 msgid "Depressed" msgstr "Deprimovaný" #: gajim/common/const.py:318 msgid "Disappointed" msgstr "Zklamaný" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "Znechucený" #: gajim/common/const.py:320 msgid "Dismayed" msgstr "Zděšený" #: gajim/common/const.py:321 msgid "Distracted" msgstr "Roztržitý" #: gajim/common/const.py:322 #, fuzzy msgid "Embarrassed" msgstr "Rozpačitý" #: gajim/common/const.py:323 msgid "Envious" msgstr "Závidějící" #: gajim/common/const.py:324 msgid "Excited" msgstr "Nadšený" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "Záletný" #: gajim/common/const.py:326 #, fuzzy msgid "Frustrated" msgstr "Rozčarovaný" #: gajim/common/const.py:327 msgid "Grateful" msgstr "Vděčný" #: gajim/common/const.py:328 msgid "Grieving" msgstr "Truchlící" #: gajim/common/const.py:329 #, fuzzy msgid "Grumpy" msgstr "Nevrlý" #: gajim/common/const.py:330 msgid "Guilty" msgstr "Provinilý" #: gajim/common/const.py:331 msgid "Happy" msgstr "Šťastný" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "Doufající" #: gajim/common/const.py:333 msgid "Hot" msgstr "Rozpálený" #: gajim/common/const.py:334 msgid "Humbled" msgstr "Pokorný" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "Ponížený" #: gajim/common/const.py:336 msgid "Hungry" msgstr "Hladový" #: gajim/common/const.py:337 msgid "Hurt" msgstr "Raněný" #: gajim/common/const.py:338 #, fuzzy msgid "Impressed" msgstr "Ohromený" #: gajim/common/const.py:339 msgid "In Awe" msgstr "S respektem" #: gajim/common/const.py:340 msgid "In Love" msgstr "Zamilovaný" #: gajim/common/const.py:341 msgid "Indignant" msgstr "Rozhořčený" #: gajim/common/const.py:342 msgid "Interested" msgstr "Zaujatý" #: gajim/common/const.py:343 #, fuzzy msgid "Intoxicated" msgstr "Opilý/Zfetovaný" #: gajim/common/const.py:344 msgid "Invincible" msgstr "Nepřekonatelný" #: gajim/common/const.py:345 msgid "Jealous" msgstr "Žárlivý" #: gajim/common/const.py:346 msgid "Lonely" msgstr "Osamělý" #: gajim/common/const.py:347 msgid "Lost" msgstr "Ztracený" #: gajim/common/const.py:348 msgid "Lucky" msgstr "Šťastný" #: gajim/common/const.py:349 msgid "Mean" msgstr "Nízký" #: gajim/common/const.py:350 msgid "Moody" msgstr "Náladový" #: gajim/common/const.py:351 msgid "Nervous" msgstr "Nervózní" #: gajim/common/const.py:352 msgid "Neutral" msgstr "Bez emocí" #: gajim/common/const.py:353 msgid "Offended" msgstr "Uražený" #: gajim/common/const.py:354 msgid "Outraged" msgstr "Rozčílený" #: gajim/common/const.py:355 msgid "Playful" msgstr "Hravý" #: gajim/common/const.py:356 msgid "Proud" msgstr "Hrdý" #: gajim/common/const.py:357 #, fuzzy msgid "Relaxed" msgstr "Uvolněný" #: gajim/common/const.py:358 #, fuzzy msgid "Relieved" msgstr "Uvolněný" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "Kajícný" #: gajim/common/const.py:360 msgid "Restless" msgstr "Netrpělivý" #: gajim/common/const.py:361 msgid "Sad" msgstr "Smutný" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "Jízlivý" #: gajim/common/const.py:363 msgid "Satisfied" msgstr "Spokojený" #: gajim/common/const.py:364 msgid "Serious" msgstr "Vážný" #: gajim/common/const.py:365 msgid "Shocked" msgstr "Šokovaný" #: gajim/common/const.py:366 msgid "Shy" msgstr "Plachý" #: gajim/common/const.py:367 msgid "Sick" msgstr "Nemocný" #: gajim/common/const.py:368 msgid "Sleepy" msgstr "Ospalý" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "Spontánní" #: gajim/common/const.py:370 msgid "Stressed" msgstr "Stresovaný" #: gajim/common/const.py:371 msgid "Strong" msgstr "Silný" #: gajim/common/const.py:372 msgid "Surprised" msgstr "Překvapený" #: gajim/common/const.py:373 msgid "Thankful" msgstr "Děkovný" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "Žíznivý" #: gajim/common/const.py:375 msgid "Tired" msgstr "Unavený" #: gajim/common/const.py:376 msgid "Undefined" msgstr "Nedefinováno" #: gajim/common/const.py:377 msgid "Weak" msgstr "Slabý" #: gajim/common/const.py:378 msgid "Worried" msgstr "Ustaraný" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "výchozí" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "mariňák" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Skrývám se" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "Země:" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Účet" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Popis" #: gajim/common/const.py:391 #, fuzzy msgid "error" msgstr "Chyba" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "jeden" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 msgid "room" msgstr "místnost" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "Nepodařilo se získat certifikát vydavatele" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "Nepodařilo se získat certifikát CRL" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "Nepodařilo se dešifrovat podpis certifikátu" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "Nepodařilo se dešifrovat podpis CRL certifikátu" #: gajim/common/const.py:412 msgid "Unable to decode issuer public key" msgstr "Nepodařilo se dešifrovat veřejný klíč vydavatele" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "Chyba podpisu certifikátu" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "Chyba podpisu CRL certifikátu" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "Certifikát není správný" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "Platnost certifikátu vypršela" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "CRL certifikát není správný" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "Platnost CRL certifikátu vypršela" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "Chyba certifikátu v poli: platnost před" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "Chyba certifikátu v poli: platnost po" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "Chyba CRL certifikátu v poli: poslední aktualizace" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "Chyba CRL certifikátu v poli: příští aktualizace" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "Nedostatek paměti" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "Sám sebou podepsaný certifikát" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "Sám sebou podepsaný certifikát v certifikačním řetězci " #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "Nepodařilo se získat certifikát lokálního vydavatele" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "Nepodařilo se ověřit první certifikát" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "Certifikační řetězec je přiliš dlouhý" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "Certifikát je zrušený" #: gajim/common/const.py:430 msgid "Invalid CA certificate" msgstr "Neplatný CA certifikát" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "Překročena delká cesty" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "Nepodporované osvědčení certifikátu" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "Certifikát je nedůvěryhodný" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "Certifikát odmítnut" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "Neshoduje se název vydavatele" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "Název klíče se neshoduje s Autoritou" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "Vydavatelovo sériové číslo se neshoduje s Autoritou" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "Použítý klíč neobsahuje podpis certifikátu" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "Ověřování aplikace skončilo neúspěchem" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "%s není platný loglevel" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Spojení s účtem \"%s\" bylo ztraceno" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "Znovu připojit ručně." #: gajim/common/connection.py:740 #, fuzzy, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "Server %s odpověděl chybně na požadavek regisrace: %s" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "Server %s poskytnul rozdílný registrační formulář" #: gajim/common/connection.py:1090 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Nemůžu se připojit k \"%s\"" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Nemůžu se připojit k \"%s\"" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Ověřte spojení nebo zkuste později." #: gajim/common/connection.py:1100 #, python-format msgid "Server replied: %s" msgstr "Server odpověděl: %s" #: gajim/common/connection.py:1115 msgid "Connection to proxy failed" msgstr "Spojení s proxy selhalo" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, python-format msgid "Could not connect to account %s" msgstr "Selhalo připojení k účti %s" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "Spojení s účtem %s bylo ztraceno. Opět se připojte." #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Nemůžu se připojit k \"%s\"" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "Autentizace selhala s \"%s\"" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Prosím zkontrolujte správnost jména a hesla." #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "D-Bus python bindings chybí na tomto počítači" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "Možnosti D-Bus nemohou být použity" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "na tomto stroji neběží D-Bus korektně" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "na tomto stroji neběží D-Bus korektně" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "na tomto stroji neběží D-Bus korektně" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Výchozí Zpráva" #: gajim/common/multimedia_helpers.py:70 #, fuzzy msgid "Audio test" msgstr "Audio / Video" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Velikost: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Soubor: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "zelený" #: gajim/common/multimedia_helpers.py:115 #, fuzzy msgid "Fake video output" msgstr "video výstup" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, fuzzy, python-format msgid "%s configuration error" msgstr "Nastavení místnosti" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 #, fuzzy msgid "audio input" msgstr "audio vstup" #: gajim/common/jingle_rtp.py:392 #, fuzzy msgid "audio output" msgstr "audio výstup" #: gajim/common/jingle_rtp.py:450 #, fuzzy msgid "video input" msgstr "video vstup" #: gajim/common/jingle_rtp.py:457 #, fuzzy msgid "video output" msgstr "video výstup" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Neplatný znak v hostname." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Je potřeba adresa serveru." #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Neplatný znak v uživatelském jméně." #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "Neplatný znak ve zdroji." #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "_Nerušit" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "Ne_dostupný" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "_Ukecaný" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "?transfer status:Pozastaveno" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "Připojuji se" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "_Pryč" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "_Odpojen" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "Ne_viditelný" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "?contact has status:Neznámý" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "stav" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "?Subscription we already have:Žádná" #: gajim/common/helpers.py:315 msgid "To" msgstr "Příjemce" #: gajim/common/helpers.py:317 msgid "From" msgstr "Odesílatel" #: gajim/common/helpers.py:319 msgid "Both" msgstr "Oboustranná" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "?OS:Neznámý" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "?Ask (for Subscription):Není" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Žádat autorizaci" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "?Group Chat Contact Role:Žádná" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Moderátoři" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Moderátor" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Účastníci" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Účastník" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Návštěvníci" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Návštěvník" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "věnuje pozornost rozhovoru" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "dělá něco jiného" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "píše zprávu..." #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "pozastavil(a) psaní zprávy" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "zavřel(a) okno zprávy" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s GiB" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s GB" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s MiB" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s MB" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s KiB" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s KB" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s B" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "Čeká %d zpráva" msgstr[1] "Čekají %d zprávy" msgstr[2] "Čeká %d zpráv" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr "z místností %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, fuzzy, python-format msgid "from user %s" msgstr "od uživatele %s" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr "od %s" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "Čeká %d událost" msgstr[1] "Čekají %d události" msgstr[2] "Čeká %d událostí" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Chtěl(a) bych si Vás přidat do mého Seznamu." #: gajim/common/helpers.py:1249 #, fuzzy msgid "Hello, I am $name." msgstr "Ahoj, já jsem $name" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 msgid "Timeout loading image" msgstr "Nezdařilo se načtení obrázku" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "Obrázek je příliš veliký" #: gajim/common/helpers.py:1383 #, fuzzy msgid "PyCURL is not installed" msgstr "CRL certifikát není správný" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Nezdařilo se načtení obrázku" #: gajim/common/configpaths.py:85 #, python-format msgid "%s is a file but it should be a directory" msgstr "%s je soubor, ale měl by být adresář" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Gajim se nyní ukončí" #: gajim/common/exceptions.py:45 #, fuzzy, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" "Nelze přečíst soubor databáze (%s). Opravte ho (viz http://trac.gajim.org/" "wiki/DatabaseBackup) nebo smažte (tím ztratítu všechny zprávy v historii)." #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "Služba není dostupná. Gajim neběží, nebo remote_control je vypnutý" #: gajim/common/exceptions.py:81 #, fuzzy, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "" "Session bus není k dispozici.\n" "Zkuste přečíst http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/exceptions.py:93 #, fuzzy, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" "Session bus není k dispozici.\n" "Zkuste přečíst http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 msgid "Please check if Avahi or Bonjour is installed." msgstr "Zkontrolujte zda je Avahi nebo Bonjour nainstalováno." #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "Nepodařilo se spustit lokální službu" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, python-format msgid "Unable to bind to port %d." msgstr "Nemůžu naslouchat na portu %d." #: gajim/common/zeroconf/connection_zeroconf.py:217 #, fuzzy msgid "Please check if avahi/bonjour-daemon is running." msgstr "Zkontrolujte, zda avahi-daemon běží." #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, python-format msgid "Could not change status of account \"%s\"" msgstr "Nemůžu změnit stav účtu \"%s\"" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "Zkontrolujte, zda avahi-daemon běží." #: gajim/common/zeroconf/connection_zeroconf.py:349 msgid "Your message could not be sent." msgstr "Vaše zpráva nemohla být odeslána." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "Kontakt je offline. Vaše zpráva nemohla být odeslána." #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "Spojení k počítači nebylo navázáno:Vypršel čas při odesílání dat." #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, python-format msgid "Error while adding service. %s" msgstr "Chyba při přidávání služby. %s" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "zpráva" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "Rád(a) bych si tě přidal(a) do seznamu." #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Chyba: %s" #: gajim/common/modules/httpupload.py:134 msgid "File is empty" msgstr "Soubor je prázdný" #: gajim/common/modules/httpupload.py:137 msgid "File does not exist" msgstr "Soubor neexistuje" #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 msgid "Change status information" msgstr "Informace o změně stavu" #: gajim/common/modules/adhoc_commands.py:113 msgid "Change status" msgstr "Změnit stav" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "Nastav typ přítomnosti a popisek" #: gajim/common/modules/adhoc_commands.py:121 msgid "Free for chat" msgstr "Ukecaný" #: gajim/common/modules/adhoc_commands.py:122 msgid "Online" msgstr "Připojen" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "Dlouho pryč" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "Nerušit" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "Odpojený - odpojit" #: gajim/common/modules/adhoc_commands.py:132 msgid "Presence description:" msgstr "Popis stavu: " #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "Stav se změnil." #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 msgid "Leave Groupchats" msgstr "Opustit diskuzi" #: gajim/common/modules/adhoc_commands.py:231 #, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s v %(room_jid)s" #: gajim/common/modules/adhoc_commands.py:235 msgid "You have not joined a groupchat." msgstr "Nepřipojil jsi se k diskuzi." #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "Vyber diskuze, které chceš opustit" #: gajim/common/modules/adhoc_commands.py:292 msgid "You left the following groupchats:" msgstr "Opustil(a) jste následující diskuze:" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "Neznámý Umělec" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "Neznámý Název" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "Neznámý Zdroj" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" "\"%(title)s\" od %(artist)s\n" "z %(source)s" #: gajim/common/modules/roster_item_exchange.py:100 #, fuzzy, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "Odeslán kontakt: \"%s\" (%s)" #: gajim/common/modules/roster_item_exchange.py:104 msgid "Sent contacts:" msgstr "Odeslány kontakty:" #: gajim/data/gui/blocked_contacts_window.ui:13 msgid "Blocked Contacts" msgstr "Blokované Kontakty" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Editor rozšířeného nastavení" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Filtr:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Popis" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "" "POZNÁMKA: Měl(a) by jste restartovat gajim, aby se projevila všechna " "nastavení" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "_Vrátit k výchozím barvám" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Automaticky vstoupit" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Účet" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Místnost:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Heslo:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "Přidat tuto místnost do záložek" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "_Záložky" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "v _diskuzích" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 #, fuzzy msgid "HTTP Connect" msgstr "" "HTTP Connect\n" "SOCKS5\n" "BOSH" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Spravovat profily Proxy" #: gajim/data/gui/manage_proxies_window.ui:148 msgid "_Name:" msgstr "_Jméno: " #: gajim/data/gui/manage_proxies_window.ui:161 msgid "_Type:" msgstr "_Typ:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Vlastnosti" #: gajim/data/gui/manage_proxies_window.ui:234 msgid "_BOSH URL:" msgstr "_BOSH URL:" #: gajim/data/gui/manage_proxies_window.ui:258 msgid "Proxy _Host:" msgstr "P_očítač Proxy:" #: gajim/data/gui/manage_proxies_window.ui:269 msgid "Use HTTP prox_y" msgstr "Použij HTTP prox_y" #: gajim/data/gui/manage_proxies_window.ui:288 msgid "Proxy _Port:" msgstr "_Port Proxy:" #: gajim/data/gui/manage_proxies_window.ui:299 msgid "Use proxy auth_entication" msgstr "Použít při_hlášení k proxy" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "_Uživatel:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "He_slo:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Nastavení" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Uložit heslo" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Změnit heslo" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Informace o kontaktu" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "Lokální jid: " #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "Zdroj:" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Stav:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Zaznamenat historii konverzace" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 msgid "Contact" msgstr "Kontakt" #: gajim/data/gui/zeroconf_information_window.ui:234 msgid "First Name:" msgstr "Křestní:" #: gajim/data/gui/zeroconf_information_window.ui:247 msgid "Last Name:" msgstr "Příjmení:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "Jabber ID:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "E-Mail:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 msgid "Personal" msgstr "Osobní" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "_Odeslat soukromou zprávu" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Odeslat _Soubor" #: gajim/data/gui/gc_occupants_menu.ui:29 msgid "Occupant Actions" msgstr "_Akce účastníků" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Hlas" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Mo_derátor" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "Č_len" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Správce" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "_Vlastník" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "Vy_kopnout" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Zakázat" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "Přid_at do Seznamu" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "Spustit _příkaz..." #: gajim/data/gui/tooltip_roster_contact.ui:125 #, fuzzy msgid "Idle since:" msgstr " od %s" #: gajim/data/gui/tooltip_roster_contact.ui:151 msgid "Mood:" msgstr "Nálada:" #: gajim/data/gui/tooltip_roster_contact.ui:164 msgid "Activity:" msgstr "Činnost:" #: gajim/data/gui/tooltip_roster_contact.ui:178 msgid "Tune:" msgstr "Píseň" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Upozornění" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP: " #: gajim/data/gui/tooltip_roster_contact.ui:281 msgid "Subscription:" msgstr "Autorizace: " #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "_Stav" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "Upravit úč_et..." #: gajim/data/gui/atom_entry_window.ui:8 msgid "New entry received" msgstr "Přijat nový záznam" #: gajim/data/gui/atom_entry_window.ui:92 msgid "Feed name:" msgstr "Jméno kanálu:" #: gajim/data/gui/atom_entry_window.ui:119 msgid "Entry:" msgstr "Položka:" #: gajim/data/gui/atom_entry_window.ui:131 msgid "Last modified:" msgstr "Naposledy upraveno:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 msgid "Change _Nickname..." msgstr "Změ_nit přezdívku" #: gajim/data/gui/gc_control_popup_menu.ui:20 msgid "_Manage Room" msgstr "Spravuj Místnost" #: gajim/data/gui/gc_control_popup_menu.ui:31 msgid "Change _Subject..." msgstr "Změnit _předmět" #: gajim/data/gui/gc_control_popup_menu.ui:38 msgid "Configure _Room..." msgstr "Nastavit _místnost" #: gajim/data/gui/gc_control_popup_menu.ui:52 msgid "_Destroy Room" msgstr "_Zničit místnost" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "_Minimalizovat při zavření" #: gajim/data/gui/gc_control_popup_menu.ui:85 #, fuzzy msgid "_Request Voice" msgstr "_Hlas" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "Avatar:" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Vyberte obrázek" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 msgid "Full Name" msgstr "Celé jméno" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Telefon" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Formát: RRRR-MM-DD" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 #, fuzzy msgid "Birthday" msgstr "Narozeniny:" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Dom. stránka:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "E-Mail:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 msgid "Jabber ID" msgstr "Jabber ID" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 #, fuzzy msgid "Family" msgstr "Příjmení:" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 #, fuzzy msgid "Given" msgstr "Křestní:" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Prostřední:" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Titul:" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Za jménem:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Stresovaný" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "Další adresa:" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 #, fuzzy msgid "City" msgstr "Město:" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Stát:" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 #, fuzzy msgid "Postal Code" msgstr "PSČ:" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "Země:" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 msgid "Address" msgstr "Adresa" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Jméno:" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Společnost:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 #, fuzzy msgid "Department" msgstr "Oddělení:" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Pozice:" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Čas kontaktu:" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Práce" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Komentář" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "_Pokračovat" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Pauza" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Zrušit" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Otevřít obsahující složku" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Přenosy souborů" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "výpis přenosů souborů" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "Seznam aktivních, dokončených a zastavených přenosů souborů" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "_Vymazat" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "Odstraní dokončené, zrušené nebo přenosy které selhaly, z výpisu" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Odstranit přenos souboru ze výpisu." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "Tato akce smaže jeden přenos souboru z výpisu. Pokud je přenos aktivní, bude " "nejdříve zastaven a potom smazán" #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "Zruší vybraný přenos souboru a smaže nedokončený soubor" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Zrušit přenos souboru" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Zruší vybraný přenos souboru" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "Ode_slat a zavřít" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Skryje okno" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Upozornit mě po dokončení přenosu souboru" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "Zobraz upozornění, až bude přenos souboru dokončen" #: gajim/data/gui/filetransfers.ui:229 msgid "Shows a list of file transfers between you and others" msgstr "Zobrazí výpis přenosů souborů mezi Vámi a ostatními" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Tučné" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Latinka" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 msgid "Underline" msgstr "Podtrhnout" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 msgid "Strike" msgstr "Přeškrtnout" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "Barva" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 msgid "Font" msgstr "Font" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Smazat formátování" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Vyber soubor k odeslání..." #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Zobraz seznam smajlíků (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Událost" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Událost" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Písmo" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "č." #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Pryč" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "Zobrazit _Seznam" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "Server" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "Výchozí" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "Soubor je prázdný" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Zdroj:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Stav" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Klient:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 #, fuzzy msgid "System" msgstr "Systému:" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Jméno kontaktu" #: gajim/data/gui/vcard_information_window.ui:240 #, fuzzy msgid "User avatar" msgstr "Avatar:" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Nastavit avatara" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 #, fuzzy msgid "Ask" msgstr "Oslovení:" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Autorizace: " #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 msgid "Personal Info" msgstr "Osobní údaje" #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "Vlastní poznámky" #: gajim/data/gui/preferences_window.ui:38 #, fuzzy msgid "Use default applications" msgstr "Vždy použít OS/X výchozí aplikace" #: gajim/data/gui/preferences_window.ui:41 msgid "Custom" msgstr "Vlastní" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Všechny stavy" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 #, fuzzy msgid "Composing only" msgstr "Píšu zprávu" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Vypnuto" #: gajim/data/gui/preferences_window.ui:89 #, fuzzy msgid "Only when pending events" msgstr "" "Nikdy\n" "Pouze při čekajících událostech\n" "Vždy" #: gajim/data/gui/preferences_window.ui:103 msgid "Pop it up" msgstr "" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "Upozorni mě na kontakty které se odhlásí" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "_Zobrazit událost v rosteru" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 #, fuzzy msgid "Last state" msgstr "Poslední stav: %s" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "Zobrazovat a_vatary kontaktů v seznamu" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Pokud zaškrtnuto, Gajim bude zobrazovat avatary kontaktů v okně Seznamu a v " "diskuzích" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "Zobrazovat p_opis stavu kontaktů v Seznamu" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Pokud zaškrtnuto, Gajim bude zobrazovat popisy stavů kontaktů pod jménem v " "okně Seznamu a v diskuzích" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Zobrazovat _nálady kontaktů v seznamu" #: gajim/data/gui/preferences_window.ui:254 msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "" "Pokud zaškrtnuto, Gajim bude zobrazovat avatary kontaktů v okně Seznamu a v " "diskuzích" #: gajim/data/gui/preferences_window.ui:275 msgid "Sort contacts by status" msgstr "Seřadit podle stavu" #: gajim/data/gui/preferences_window.ui:285 msgid "in _roster" msgstr "v _rosteru" #: gajim/data/gui/preferences_window.ui:302 msgid "in _group chats" msgstr "v _diskuzích" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "Vzhled Rosteru" #: gajim/data/gui/preferences_window.ui:359 #, fuzzy msgid "Spell _checker" msgstr "Kontrola Pravopisu" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" "Pokud je zaškrtnuto, Gajim zvýrazní překlepy při psaní zprávy.Pokud není " "nastavení jazyk přes pravé tlačítko na vstupním poli, tak se použije výchozí " "jazyk pro tento kontakt nebo diskuzi." #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "Tělo zprávy" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 #, fuzzy msgid "_Window behavior" msgstr "Chování _okna" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "Zobrazit _Seznam" #: gajim/data/gui/preferences_window.ui:484 msgid "_Ignore rich content in incoming messages" msgstr "_Ignoruj formátování v příchozích zprávách" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" "Některé zprávy mohou obsahovat formátování (odsazení, barvy aj.). Pokud je " "zaškrtnuto, Gajim zobrazí pouze čistý text." #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Nelze se připojit se do diskuze" #: gajim/data/gui/preferences_window.ui:523 msgid "Chat Appearance" msgstr "Vzhled diskuze" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "Když je přijata nová zpráva" #: gajim/data/gui/preferences_window.ui:623 msgid "Notify me about contacts that sign _in" msgstr "Upozorni mě na kontakty které se přihlásí" #: gajim/data/gui/preferences_window.ui:641 msgid "Notify me about contacts that sign _out" msgstr "Upozorni mě na kontakty které se odhlásí" #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Gajim Vás upozorní o přávě odpojených kontaktech pomocí popupu v pravém " "dolním rohu obrazovky" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" "Povolit popup/upozornění pokud jsem _pryč/nedostupný/nerušit/neviditelný" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "" "Povolit popup/upozornění pokud jsem _pryč/nedostupný/nerušit/neviditelný" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "Notification-daemon" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Vizuální upozornění" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "Přehrávat _zvuky" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "Sp_ravovat..." #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "Povolit zvuk, když jsem zaneprázněn" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Zvuky" #: gajim/data/gui/preferences_window.ui:861 msgid "Notifications" msgstr "Upozornění" #: gajim/data/gui/preferences_window.ui:898 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "Gajim umí ohlašovat svoji schopnost posílat a přijímat meta-informace " "vztahující se k rozhovoru. Tady můžete nastavit, které stavy rozhovoru " "chcete zobrazovat v oknech rozhovoru." #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "Zobrazovat _události stavu rozhovoru:" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim umí ohlašovat svoji schopnost posílat a přijímat meta-informace " "vztahující se k rozhovoru. Tady můžete nastavit, které stavy rozhovoru " "chcete posílat svému protějšku." #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "Zobrazovat _události stavu rozhovoru:" #: gajim/data/gui/preferences_window.ui:987 msgid "Chat state notifications" msgstr "Vizuální upozornění" # FIXME: snad je to ok? #: gajim/data/gui/preferences_window.ui:1009 msgid "Personal Events" msgstr "Moje události" #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "_Automaticky pryč po:" #: gajim/data/gui/preferences_window.ui:1047 msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" "Pokud je zaškrtnuto, Gajim změnít stav na 'Pryč' pokud je počítač nepoužíván." #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "Automaticky _nedostupný po:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" "Pokud je zaškrtnuto, Gajim změní stav na 'Nedostupný' pokud se počítač " "nepoužívá delší dobu" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "minutách" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" "Popis stavu automatického stavu 'Pryč'. Pokud je prázdná, tak Gajim nezmění " "současný popis stavu\n" "$S se nahradí za předchozí popis stavu\n" "$T se nahradí dobou nečinnosti před zapnutím stavu Pryč" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" "Automatická popia stavu 'Nedostupný'. Pokud je prázdná, tak Gajim nezmění " "současný popis stavu\n" "$S se nahradí za předchozí popis stavu\n" "$T se nahradí dobou nečinnosti před zapnutím stavu Nedostupný" #: gajim/data/gui/preferences_window.ui:1166 msgid "Auto Status" msgstr "Automatický Stav" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Ptej se na stav při:" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "_Přihlásí" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "_Odhlásí" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" "Pokud zaškrtnuto, Gajim se nebude pokáždé ptát na zprávu stavu. Místo toho " "použije výchozí nadefinovanou zprávu." #: gajim/data/gui/preferences_window.ui:1291 msgid "Default Message" msgstr "Výchozí Zpráva" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 msgid "Enabled" msgstr "Povolit" #: gajim/data/gui/preferences_window.ui:1332 msgid "Status Messages" msgstr "Přednastavené stavy" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Přednastavené stavy" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Téma" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Téma" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "Nastav barvu a písmo uživatelského rozhraní" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "gajim-remote" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "gajim-remote" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "Výchozí _ikony stavů:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Používat ikony _transportů" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Pokud zaškrtnuto, Gajim použije ikony specifické pro protokol (např. kontakt " "z MSN bude mít odpovídající ikonu msn pro stavy připojen, pryč, nerušit, " "atd...)" #: gajim/data/gui/preferences_window.ui:1724 msgid "_Convert ASCII Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1808 msgid "Style" msgstr "Styl" #: gajim/data/gui/preferences_window.ui:1845 #, fuzzy msgid "Audio input device" msgstr "Audio vstupní zařízení" #: gajim/data/gui/preferences_window.ui:1860 #, fuzzy msgid "Audio output device" msgstr "Audio výstupní zařízení" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Akce" #: gajim/data/gui/preferences_window.ui:1929 #, fuzzy msgid "Video input device" msgstr "Video vstupní zařízení" #: gajim/data/gui/preferences_window.ui:1944 #, fuzzy msgid "Video output device" msgstr "Video výstupní zařízení" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 #, fuzzy msgid "Video size" msgstr "Velikost videa" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Prostřední:" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Server:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 #, fuzzy msgid "(example: stun.iptel.org)" msgstr "(například: stunserver.org)" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Podmínky" #: gajim/data/gui/preferences_window.ui:2159 #, fuzzy msgid "Audio/Video" msgstr "Audio / Video" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "E-_mailový klient:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "_Prohlížeč:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "_Správce souborů:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Vlastní" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Aplikace" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "_Ignorovat události od kontaktů mimo můj Seznam" #: gajim/data/gui/preferences_window.ui:2363 msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Zaškrtněte pouze pokud Vás obtěžuje někdo, koho nemáte v rosteru. Použijte s " "rozvahou, protože tato volba zakáže všechny zprávy od kontaktů, které ještě " "nemáte v rosteru" #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Povolit odeslání informace o _OS" #: gajim/data/gui/preferences_window.ui:2381 msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "Pokud je zaškrtnuto, Gajim se připojí do této místnosti při spuštění" #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Povolit odeslání informace o _OS" #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "Pokud je zaškrtnuto, Gajim se připojí do této místnosti při spuštění" #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Povolit odeslání informace o _OS" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 msgid "_Manage..." msgstr "_Spravovat..." #: gajim/data/gui/preferences_window.ui:2500 msgid "Privacy" msgstr "Soukromí" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "Zaznamenávat změny _stavu kontaktů" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Příslušenství" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "_Otevřít..." #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Editor rozšířeného nastavení" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Začít _rozhovor" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Odeslat jednoduchou _zprávu..." #: gajim/data/gui/contact_context_menu.ui:28 msgid "Send _File..." msgstr "Odeslat _Soubor" #: gajim/data/gui/contact_context_menu.ui:44 msgid "Invite _Contacts" msgstr "Pozvat kontakt" #: gajim/data/gui/contact_context_menu.ui:73 msgid "E_xecute Command..." msgstr "P_rovést příkaz..." #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "_Spravovat kontakt" #: gajim/data/gui/contact_context_menu.ui:92 msgid "_Rename..." msgstr "_Přejmenovat" #: gajim/data/gui/contact_context_menu.ui:99 msgid "Edit _Groups..." msgstr "Upravit _skupiny" #: gajim/data/gui/contact_context_menu.ui:106 msgid "Assign Open_PGP Key..." msgstr "Přiřadit Open_PGP Klíč..." #: gajim/data/gui/contact_context_menu.ui:115 msgid "Add Special _Notification..." msgstr "Přidat zvláštní _upozornění" #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Autorizace" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "Dovol kontaktu vidět můj stav" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "Požádat o zobrazení je(jí)ho _stavu" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "_Zakaž mu/jí vidět můj stav" #: gajim/data/gui/contact_context_menu.ui:182 msgid "_Unignore" msgstr "_Neignorovat" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "_Ignorovat" #: gajim/data/gui/contact_context_menu.ui:197 msgid "_Add to Roster..." msgstr "Přid_at do Seznamu" #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim: Průvodce vytváření účtu" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "Potřebujete mít účet pro připojení k síti Jabber." #: gajim/data/gui/account_creation_wizard_window.ui:95 msgid "I already have an account I want to _use" msgstr "Už mám účet který bych rád(a) použil(a)" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "Chtěl(a) bych za_registrovat nový účet" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Prosím zvolte z následujících možností:" #: gajim/data/gui/account_creation_wizard_window.ui:167 msgid "Please fill in the data for your existing account" msgstr "Prosím vyplňte údaje pro Váš nový účet" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "_Jabber ID:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 msgid "Anon_ymous authentication" msgstr "Anon_ymní autentizace" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Heslo:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Uložit _heslo" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Pokud bude zaškrtnuto, Gajim si bude pamatovat heslo pro tento účet" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "Prosím Vyberte server" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Server:" #: gajim/data/gui/account_creation_wizard_window.ui:423 msgid "Prox_y:" msgstr "Prox_y:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Spravovat..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Použít vlastní jméno počítače/port" #: gajim/data/gui/account_creation_wizard_window.ui:491 msgid "_Hostname:" msgstr "Počítač: " #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Port:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "_Rozšířené" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" "Přidat tento certifikát do důvěryhodných.\n" "SHA1 otisk certifikátu:\n" #: gajim/data/gui/account_creation_wizard_window.ui:687 msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Vytváří se účet\n" "\n" "Prosím čekejte..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Připojit když stisknu Dokončit" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Nastavit profil, když se připojuji" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Dokončit" #: gajim/data/gui/privacy_lists_window.ui:34 msgid "Privacy Lists:" msgstr "Nastavení Soukromí:" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Adresa:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "_Jdi" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "Synchronizace: vybrat kontakty" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 msgid "Select the contacts you want to synchronise" msgstr "JID kontaktu, se kterým chcete komunikovat" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Upravit skupiny" #: gajim/data/gui/search_window.ui:42 msgid "Please wait while retrieving search form..." msgstr "Prosím vyčkejte než stáhnu seznam příkazů..." #: gajim/data/gui/search_window.ui:80 msgid "_Add contact" msgstr "Přidat _kontakt" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "_Najít" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Uložené stavy:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Činnost" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Napište nový popis stavu" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 msgid "Synchronise contacts" msgstr "Synchronizovat kontakty" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "Vybrat účet pro synchronizaci" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "_Jabber ID:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "_Přezdívka:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "_Skupina:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "Úče_t: " #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "P_rotokol:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "Dovol kontaktu vidět můj stav" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "_Autorizace" #: gajim/data/gui/add_new_contact_window.ui:367 #, fuzzy msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" "Musíš se zaregistrovat s tímto transportem,\n" "abys mohl(a) přidat kontakty z tohoto protokolu.\n" "Klikni na tlačítko registrovat pro pokračování." #: gajim/data/gui/add_new_contact_window.ui:382 msgid "_Register" msgstr "_Registrovat" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" "Musíš být připojen(á) k trasportu před přidáním\n" " kontaktu z tohoto protokolu." #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "Z_měnit popis stavu" #: gajim/data/gui/change_mood_dialog.ui:73 msgid "Mood:" msgstr "Nálada:" #: gajim/data/gui/change_mood_dialog.ui:85 msgid "Message:" msgstr "Zpráva:" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Stagnuje" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Registrace selhala" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Registrace selhala" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Popis" #: gajim/data/gui/plugins_window.ui:258 #, fuzzy msgid "Version" msgstr "GTK+ verze: " #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "Au_torizuj" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 #, fuzzy msgid "Installed" msgstr "Stagnuje" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "jeden" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "Oboustranná" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "Odesílatel" #: gajim/data/gui/privacy_list_window.ui:27 #, fuzzy msgid "to" msgstr "dva" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "Nastavení Soukromí" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "Nastavení Soukromí" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "Aktivní pro toto sezení" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "Aktivní při každém startu" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "Seznam pravidel" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "Přidej / Uprav pravidlo" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "Povolit" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Odmítnout" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "Jabber ID" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "všem ve skupině" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "všechny podle autorizace" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "Vše" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "odeslat zprávu" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "pro zaslání dotazu" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "Dovol mu/jí vidět můj stav" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "Požádat o zobrazení je(jí)ho stavu" #: gajim/data/gui/privacy_list_window.ui:557 msgid "All (including subscription)" msgstr "Všechno (včetně autorizací)" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "Pořadí:" #: gajim/data/gui/manage_sounds_window.ui:23 #, fuzzy msgid "Manage sounds" msgstr "Spravovat účty" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Aktivní" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Událost" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Vyberte zvuk" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Odstranit účet _pouze z Gajimu" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Odstranit účet z Gajimu i ze _serveru" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "Co by jste rád(a) dělal(a)?" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Prosím vyčkejte než stáhnu seznam příkazů..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Vyber příkaz k provedení:" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Zkontroluj ještě jednou" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Prosím vyčkejte než bude příkaz odeslán..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Tento kontakt neobsahuje žádné příkazy." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Nastala chyba:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Dokončit" #: gajim/data/gui/account_context_menu.ui:20 msgid "_Personal Events" msgstr "Osobní údaje" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "Vstoupit do _Diskuze" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "Přid_at kontakt..." # FIXME: chtelo by to cesky vyraz pro service discovery #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Prohlížet služby" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "Provést příkaz..." #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Zobraz" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Zobrazit _Seznam" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Zobrazit _odpojené kontakty" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Zobrazit pouze _aktivní kontakty" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Zobrazuj trans_porty" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Nápověda" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Obsah" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_FAQ" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 msgid "Features" msgstr "Vlastnosti serveru" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "_Záložky" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Nastavení" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Konec" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Zrušit" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "Seznam dostupných vlastností v Gajimu: " #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "_Diskuze" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "Přidat tuto místnost do záložek" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Server:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Heslo:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Kontakt se odpojil" #: gajim/data/gui/manage_bookmarks_window.ui:342 #, fuzzy msgid "Minimize on Auto Join" msgstr "Minimalizovat po připojení" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Odeslat zprávu a zavřít okno" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Text stavu" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Popis:" #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Uklízím" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 #, fuzzy msgid "Send" msgstr "Ode_slat" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Soubor: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "Pravděpodobně není fatální, ale přesto by měla být ohlášena vývojářům." #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Ohlásit chybu" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Začít rozhovor" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "O_dmítnout" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "Odmítne autorizaci od kontaktu, takže nezjistí kdy jste připojen(a)" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "Au_torizuj" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "Autorizovat kontakt, aby věděl kdy jsi připojený(á)" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "_Stav" #: gajim/data/gui/emoji_chooser.ui:98 #, fuzzy msgid "No Results Found" msgstr "Žádný výsledek" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "Pozvat přátele !" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "" "Začátek Více-uživatelského rozhovoru.\n" "Vyberte kontakty, které chcete pozvat" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "Prosím, vyberte MUC server." #: gajim/data/gui/chat_to_muc_window.ui:141 msgid "MUC server" msgstr "MUC server" #: gajim/data/gui/chat_to_muc_window.ui:176 msgid "In_vite" msgstr "_Pozvat do" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Export" #: gajim/data/gui/history_manager.ui:93 msgid "Welcome to Gajim History Logs Manager" msgstr "Vítejte do Gajimova Správce Historie" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" "Tento správce logů není určený pro jejich prohlížení. Místo toho použijte " "okno s historií.\n" "\n" "Použijte tento program pro mazání nebo export zpráv. Můžete vybrat logy " "vlevo a/nebo je dole vyhledat v databázi." #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "VAROVÁNÍ:\n" "Pokud plánujete rozsáhlé promazání, ujistěte se, že Gajim neběží. Obecně se " "vyvarujte mazání historie kontaktu, se kterým si právě píšete." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Hledat v databázi" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "Obsah zprávy" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Odeslat zprávu" #: gajim/data/gui/shortcuts_window.ui:24 #, fuzzy msgid "Add new line" msgstr "Vytvoř nový zápis" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Uložené stavy:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Uložené stavy:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "text stavu" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Odeslat zprávu" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Zpráva odeslána" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Nedávno:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Uklízím" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 #, fuzzy msgid "Close chat" msgstr "Zavřít" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Přenosy souborů" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "v _diskuzích" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "text stavu" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 #, fuzzy msgid "Appearance" msgstr "Vzhled diskuze" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Zobrazit _odpojené kontakty" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Zobrazit pouze _aktivní kontakty" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Kontakty" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Informace o kontaktu" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Přejmenovat kontakt" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Odeslány kontakty:" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Heslo" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "Zaznamenávat změny _stavu kontaktů" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Moderátor" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Nedávno:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Historie konverzace" #: gajim/data/gui/history_window.ui:315 #, fuzzy msgid "Chat" msgstr "Rozhovory" #: gajim/data/gui/history_window.ui:329 #, fuzzy msgid "Record history for this chat" msgstr "Ignorovat tuto chybu certifikátu." #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Nedávno:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Titul:" #: gajim/data/gui/manage_pep_services_window.ui:13 msgid "PEP Service Configuration" msgstr "Nastavení PEP služby" #: gajim/data/gui/manage_pep_services_window.ui:69 msgid "_Configure" msgstr "_Nastavit" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Vytvoř nový zápis" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "Odesílatel:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Předmět:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Vyplňte formulář." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Nastavení místnosti" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "Výměna položky rosteru" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_OK" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "S_tav" #: gajim/data/gui/systray_context_menu.ui:20 msgid "_Start Chat..." msgstr "_Začít rozhovor" #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Zobrazit všechny čekající _události" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "Vypnout zvuky" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Nastavení" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Konec" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Příjemce:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "O_deslat" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Odeslat zprávu" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Odpovědět" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Odpovědět na tuto zprávu" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "Ode_slat a zavřít" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Odeslat zprávu a zavřít okno" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "Nastavit Činnosti" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "Nastavit činnost" #: gajim/data/gui/change_activity_dialog.ui:337 msgid "Message: " msgstr "Zpráva:" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Chybí parametry \"contact_jid\"" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Chybí parametry \"contact_jid\"" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 #, fuzzy msgid "Send a message to the contact" msgstr "Použití: /%s, pošle zprávu kontaktu" #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "%s nebyl nalezen" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "Přip_ojen" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 #, fuzzy msgid "Clear the text window" msgstr "Použití: /%s, smaže zprávy v okně." #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Použití: /%s, pošle ping kontaktu" #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 #, fuzzy msgid "Command is not supported for zeroconf accounts" msgstr "Příkaz není podporován pro zeroconf účet." #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 #, fuzzy msgid "No open audio sessions with the contact" msgstr "Kliknutím zobraz staré rozhovory s tímto kontaktem" #: gajim/command_system/implementation/standard.py:191 #, fuzzy, python-format msgid "%s is not a valid tone" msgstr "%s není platný loglevel" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "Přepnout audio" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "Spojení není dostupné" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "Přepnout video" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "Spojení není dostupné" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Použití: /%s, pošle zprávu kontaktu" #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Změ_nit přezdívku" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 msgid "Invalid nickname" msgstr "Neplatné uživatelské jméno" #: gajim/command_system/implementation/standard.py:267 #, fuzzy msgid "Open a private chat window with a specified occupant" msgstr "" "Použití: /%s , otevře okno soukromého rozhovoru uvedenému " "nájemníkovi." #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 msgid "Nickname not found" msgstr "Přezdívka nenalezena: %s" #: gajim/command_system/implementation/standard.py:276 #, fuzzy msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" "Použití: /%s , otevře okno soukromého rozhovoru uvedenému " "nájemníkovi." #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Ptát se před zavřením oken/záložek diskuzí." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "Pozval(a) %(contact_jid)s do %(room_jid)s." #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "v _diskuzích" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Jste pozván do diskuze" #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Neplatný server" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "Příslušnost:" #: gajim/command_system/implementation/standard.py:365 #, fuzzy msgid "Display names of all group chat occupants" msgstr "Použití: /%s , zobrazí jména nájemníků v místnosti." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Pokračování v rozhovoru" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Nová diskuze" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Přidat nový kontakt" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "Jednoduchá zpráva z účtu %s" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "Jednoduchá zpráva z účtu %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Jednoduchá zpráva" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Odeslat %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Přijaté %s" #: gajim/gtk/single_message.py:238 #, python-format msgid "Form %s" msgstr "Od %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "Spojení není dostupné" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Prosím ujistěte se že jste připojen s účtem \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "RE: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s napsal(a):\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "PEP uzel nebyl smazán" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "PEP uzel %(node)s se nepodařilo odstranit: %(message)s" #: gajim/gtk/pep_config.py:133 #, fuzzy, python-format msgid "Configure %s" msgstr "_Nastavit" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "_Registrovat" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Registrace úspěšná" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "Slovník pro jazyk %s není dostupný" #: gajim/gtk/dialogs.py:83 #, fuzzy, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" "Musíš nainstalovat %s slovník k použití kontroly pravopisu, nebo vybrat jiný " "jazyk nastavením volby speller_language." #: gajim/gtk/dialogs.py:440 #, fuzzy, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "" "Abyste nemuseli posílat heslo nezabezpečeným připojením nainstalujte si " "PyOpenSSL. Jste si jisti, že to chcete udělat?" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "Jabber ID diskuze obsahuje nepřijatelné znaky." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "pro účet %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Sám sebou podepsaný certifikát" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Změnit heslo" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Musíte zadat heslo." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Hesla se neshodují" #: gajim/gtk/add_contact.py:30 #, fuzzy msgid "GG Number" msgstr "GG číslo: " #: gajim/gtk/add_contact.py:31 #, fuzzy msgid "ICQ Number" msgstr "ICQ číslo: " #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "Přid_at kontakt..." #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s MiB" #: gajim/gtk/add_contact.py:235 #, python-format msgid "You must supply the %s of the new contact." msgstr "" #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "Neplatný identifikátor uživatele" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "User ID nesmí obsahovat zdroj." #: gajim/gtk/add_contact.py:274 msgid "You cannot add yourself to your roster." msgstr "Rád(a) bych si tě přidal(a) do seznamu." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Odpojen" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Kontakt už je v Seznamu" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Tento kontakt už je obsažen ve Vašem seznamu." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "Uživatel:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "Chyba při přidávání služby. %s" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "Píšu zprávu" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Neaktivní" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Změnit stav" # FIXME: I dont really know what this is and where it is #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "MUC Directed\n" "Messages" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Nová zpráva" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Účet" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Skupina" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "_Zobrazit událost v rosteru" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Rozhovor s" #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Barva příchozí přezdívky." #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Barva odchozí přezdívky." #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "Barva příchozího textu." #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "Písmo příchozího textu." #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "Barva odchozího textu." #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "Písmo odchozího textu." #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Text stavu" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Text stavu" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Barva" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "Zvýrazňovat _slova s překlepy" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Zprávy" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "_Vrátit k výchozím barvám" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Kontakt se odpojil" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Kontakt se připojil" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "gajim-remote" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Neplatné uživatelské jméno" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Znak nebyl povolen" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Aktivní" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "Chyba disku" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s je nyní %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, python-format msgid "Error: %s" msgstr "Chyba: %s" #: gajim/gtk/history.py:590 msgid "Error" msgstr "Chyba" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Stav je nyní %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Stav je nyní %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "Co by jste rád(a) dělal(a)?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Připojuji se" #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Přenos souboru %(filename)s od %(name)s byl zastaven." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "Přeposlat nepřečtené zprávy" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "GTK+ Jabber klient" #: gajim/gtk/about.py:48 #, fuzzy, python-format msgid "GTK+ Version: %s" msgstr "GTK+ verze: " #: gajim/gtk/about.py:49 #, fuzzy, python-format msgid "PyGObject Version: %s" msgstr "PyGTK verze: " #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Aktivní vývojáři:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Vysloužilí vývojáři:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 #, fuzzy msgid "we would like to thank all the package maintainers." msgstr "" "Poslední, nikoliv nejmenší, poděkování patří všem správcům instalačních " "balíčků." #: gajim/gtk/about.py:61 #, fuzzy msgid "Thanks" msgstr "Děkovný" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "" "Petr Menšík \n" "scippio " #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Vyber soubor k odeslání..." #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Vyberte obrázek" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Všechny soubory" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Všechny soubory" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Odeslat _Soubor" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Obrázky" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Vyberte obrázek" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Všechny soubory" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Uložit jako..." #: gajim/gtk/profile.py:72 #, fuzzy msgid "Retrieving profile…" msgstr "Stahuji profil..." #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Informace o kontaktu" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Formát: RRRR-MM-DD" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "Informace přijata" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "Bez opětovného připojení nemůžete zveřejnit Vaše osobní údaje." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Odesílám profil..." #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "Informace NEBYLY zveřejněny" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "publikování vizitky se nezdařilo" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "Nastala chyba při publikování Vašich osobních údajů, zkuste to později znovu." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Neplatná místnost" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 msgid "Invalid Nickname" msgstr "Neplatné uživatelské jméno" #: gajim/gtk/join_groupchat.py:223 #, fuzzy msgid "Please choose a nickname" msgstr "Vytvořte vaše nové téma." #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Nesprávné uri" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "Tohle není diskuze" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Nastavení" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Nejste připojen(a) k serveru" #: gajim/gtk/mam_preferences.py:102 #, fuzzy msgid "Error received: {}" msgstr "Chyba v příchozím datagramu" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Chyba" #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "Aktivní" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "Neaktivní" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "Boolean" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "Číslo" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Text" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Název volby" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Hodnota" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Typ" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Žádný)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Skryté" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "Počítač: " #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Vlastnosti serveru" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Server odpověděl: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "Bonjour / Zeroconf" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" "Serverless automaticky komunikuje s klienty detekovanými v místní síti." #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "Je potřeba python-dbus." #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 msgid "Command line" msgstr "Příkazový řádek" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "Skript, který ovládá Gajim z příkazové řádky." #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "Vlastnost není k dispozici pod Windows." #: gajim/gtk/features.py:61 #, fuzzy msgid "OpenPGP message encryption" msgstr "Šifrování zpráv OpenGPG " #: gajim/gtk/features.py:63 #, fuzzy msgid "Ability to encrypting chat messages with OpenPGP." msgstr "Šifruji zprávy gpg klíči." #: gajim/gtk/features.py:64 #, fuzzy, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "Je potřeba gpg a python-GnuPGInterface." #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 msgid "Password encryption" msgstr "Šifrování hesla" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "Heslo může být bezpečně uloženo." #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "Kontrola Pravopisu" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "Kontrola Pravopisu psaných zpráv." #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 #, fuzzy msgid "Requires Gspell" msgstr "Vyžaduje libgtkspell." #: gajim/gtk/features.py:76 msgid "Automatic status" msgstr "Automatický stav" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "Funkce pro měření času nečinnosti pro nastavení automatického stavu." #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "Vyžaduje knihovnu libxss." #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "Je potřeba python2.5." #: gajim/gtk/features.py:81 msgid "RST Generator" msgstr "RST Generátor" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" "Generuje XHTML výstup pro RST kód (viz.: http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "Je potřeba python-docutils." #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "Audio / Video" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "Schopnost zahájit audio a video rozhovor." #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 #, fuzzy msgid "Requires gir1.2-gupnpigd-1.0." msgstr "Je potřeba python-gnome2." #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "Připojen" #: gajim/gtk/features.py:109 msgid "Feature" msgstr "Vlastnost" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "Soukromý seznam %s" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "Soukromý seznam pro %s" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "Pořadí: %(order)s, akce: %(action)s, typ: %(type)s, hodnota: %(value)s" #: gajim/gtk/privacy_list.py:152 #, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Pořadí: %(order)s, akce: %(action)s" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "Upravit pravidlo" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "Přidat pravidlo" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "Soukromý seznam pro %s" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "Neplatné jméno seznamu" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "Musíte zadat jméno pro vytvoření privacy listu." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Účet byl úspěšně přidán" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 #, fuzzy msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Můžete nastavit rozšířené volby účtu po stisknutí tlačítka Rozšířené, nebo " "později stisknutím v položce menu Účty v nabídce Úpravy hlavního okna." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Váš účet byl úspěšně vytvořen" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Neplatné uživatelské jméno" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Musíte zadat uživatelské jméno před nastavením tohoto účtu." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 msgid "Invalid server" msgstr "Neplatný server" #: gajim/gtk/account_wizard.py:255 msgid "Please provide a server on which you want to register." msgstr "Prosím zadejte server u kterého se chcete zaregistrovat." #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Neplatný záznam" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "Vlastní port musí být číslo portu." #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" "Bezpečnostní Varování\n" "\n" "SSL certifikát pro %(hostname)s nemusí být pravý.\n" "SSL Chyba: %(error)s\n" "Přesto se chcete k serveru připojit?" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "Nastala chyba při vytváření účtu" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Jméno účtu se používá" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Již máte účet s tímto jménem." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Filtr:" #: gajim/gtk/xml_console.py:79 #, fuzzy msgid "XML Input" msgstr "Vstup XML" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Neplatný soubor" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "Výchozí" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "titulek stavu" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "text stavu" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Připojit se teď znovu?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "Pokud chcete, aby se změny projevily ihned, musíte se znovu přihlásit." #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "Otevřel(a) jsi rozhovor z účtu %s" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "" "Všechna okna rozhovorů a diskuzí budou zavřena. Opravdu chceš pokračovat?" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "Přid_at kontakt..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "Odst_ranit" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Spojené účty" #: gajim/gtk/accounts.py:549 #, fuzzy msgid "Use PGP Agent" msgstr "Použít GPG _Agenta" #: gajim/gtk/accounts.py:565 #, fuzzy msgid "Label" msgstr "označit" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Spojení" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Pozvat kontakt" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Sám sebou podepsaný certifikát" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Přiřadit OpenPGP klíč" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "_Připojit po startu Gajimu" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Automaticky se znovu připojit při ztrátě spojení" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Uložit _historii pro všechny kontakty" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "Ode_slat zprávu serveru" #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Všechny stavy" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Změní stav účtu nebo účtů" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Zprávy" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Použij proxy při přenosu souborů" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "_použít proměnnou prostředí HTTP_PROXY" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Proxy:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "_Varovat před použitím nezabezpečeného spojení" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Odesílat keep-alive pakety" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "Priori_ta:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Změní stav účtu nebo účtů" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Křestní:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Příjmení:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Nový E-mail" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "N_astavit podle stavu" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Povolit" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Port:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Spojení" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Sám sebou podepsaný certifikát" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Sám sebou podepsaný certifikát" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Uložit heslo" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "_Smajlíky:" #: gajim/gtk/bookmarks.py:72 msgid "?print_status:All" msgstr "?print_status:Všechny" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "Pouze při vstupu a výstupu" #: gajim/gtk/bookmarks.py:74 msgid "?print_status:None" msgstr "?print_status:Žádný" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "Nová diskuze" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Tato záložka má neplatná data" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "" "Prosím nezapomeňte vyplnit políčka server a místnost, nebo smažte tuto " "záložku." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 msgid "Character not allowed" msgstr "Znak nebyl povolen" #: gajim/gtk/bookmarks.py:367 msgid "Invalid room" msgstr "Neplatná místnost" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Soubor je prázdný" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 #, fuzzy msgid "Archive is malformed" msgstr "Služba odeslala chybné data" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Tento soubor už existuje" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 #, fuzzy msgid "Plugin" msgstr "P_luginy" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Zakazuji %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Registrace selhala" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Nastavení místnosti" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Jabber IM klient" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "GTK+ Jabber klient" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Zobrazit všechny čekající _události" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Vlastnosti serveru" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 #, fuzzy msgid "Automatic spell-checking for your messages" msgstr "Kontrola Pravopisu psaných zpráv." #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Procházení služeb s použitím účtu %s" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "Zaznamenávat změny _stavu kontaktů" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Diskuze" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Nedávno:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Registrace selhala" #~ msgid "Stopped" #~ msgstr "Zastaveno" #~ msgid "Error reading file:" #~ msgstr "Chyba při čtení souboru:" #~ msgid "Error parsing file:" #~ msgstr "Chyba parsování souboru:" #, fuzzy #~ msgid "Audio / video conferences" #~ msgstr "Audio / Video" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Chyba přenosu souboru" #, fuzzy #~ msgid "XML console interface" #~ msgstr "XML Konzole" #~ msgid "" #~ "A list of modp groups to use in a Diffie-Hellman, highest preference " #~ "first, separated by commas. Valid groups are 1, 2, 5, 14, 15, 16, 17 and " #~ "18. Higher numbers are more secure, but take longer to calculate when you " #~ "start a session." #~ msgstr "" #~ "Seznam modp skupin pro použití s Diffie-Hellman, první jsou nejvyšší, " #~ "oddělené čárkami. Povolené skupiny jsou 1, 2, 5, 14, 15, 16, 17 a 18. " #~ "Vyšší čísla jsou více bezpečná, ale vyžadují delší dobu výpočtu při " #~ "startu sezení." #~ msgid "_Verify" #~ msgstr "_Kontroluj" #~ msgid "(ESession info)" #~ msgstr "(ESession informace)" # FIXME: not accurate #~ msgid "Save as Preset..." #~ msgstr "Uložit stav..." #~ msgid "Always use this nickname when there is a conflict" #~ msgstr "Vždy při konfliktu použij tuto přezdívku." #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "Jabberd1.4 nemá rád sha informaci, pokud někdo vstupuje do místnosti " #~ "chráněné heslem. Zaškrtněte tuto volbu na False, aby se sha informace " #~ "neposílala v presenci u diskuzí." #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim nahradí ascii smajlíky jako ':)' za ekvivalentní " #~ "animované nebo statické grafické smajlíky" #, fuzzy #~ msgid "_Emoticons" #~ msgstr "_Smajlíky:" #~ msgid "_Highlight misspelled words" #~ msgstr "Zvýrazňovat _slova s překlepy" #, fuzzy #~ msgid "Notify by icon when your messages are received" #~ msgstr "Přehraný zvuk při příchodu jakékoliv MUC zprávy." #, fuzzy #~ msgid "T_heme" #~ msgstr "_Téma:" #~ msgid "Themes" #~ msgstr "Témata" #, fuzzy #~ msgid "Presence" #~ msgstr "_Stav" #~ msgid "Emoticons disabled" #~ msgstr "Smajlíci byly vypnuty" #, fuzzy #~ msgid "" #~ "Your configured emoticons theme could not be loaded. See the log for more " #~ "details." #~ msgstr "" #~ "Vámi nastavené téma pro smajlíky nebylo nalezeno, proto budou smajlíci " #~ "vypnuty " #~ msgid "You cannot make changes to the default theme" #~ msgstr "Nemůžete měnit výchozí téma" #, fuzzy #~ msgid "Please create a new clean theme." #~ msgstr "Vytvořte vaše nové téma." #~ msgid "theme name" #~ msgstr "jméno tématu" #~ msgid "You cannot delete your current theme" #~ msgstr "Nemůžete smazat právě používané téma" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Nová jednoduché zpráva od %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Nová soukromá zpráva z místnosti %s" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s: %(message)s" #~ msgid "Messaged by %(nickname)s" #~ msgstr "Nová zpráva od %(nickname)s" #~ msgid "Status message text color." #~ msgstr "Barva stavové zprávy." #~ msgid "Incoming nickname font." #~ msgstr "Písmo příchozí přezdívky." #~ msgid "Outgoing nickname font." #~ msgstr "Písmo odchozí přezdívky." #~ msgid "Status message text font." #~ msgstr "Písmo stavové zprávy." #~ msgid "Background color of contacts when they just signed in." #~ msgstr "Barva pozadí kontaktů, jež se zrovna přihlásili." #~ msgid "Background color of contacts when they just signed out." #~ msgstr "Barva pozadí kontaktů, jež se přávě odhlásili." #~ msgid "green" #~ msgstr "zelený" #~ msgid "grocery" #~ msgstr "potraviny" #~ msgid "human" #~ msgstr "člověk" #~ msgid "marine" #~ msgstr "mariňák" #, fuzzy #~ msgid "Contact row" #~ msgstr "Kontakt" #~ msgid "Gajim Themes Customization" #~ msgstr "Úprava témat Gajimu" #~ msgid "Text _color:" #~ msgstr "_Barva textu:" #~ msgid "_Background:" #~ msgstr "_Pozadí:" #~ msgid "Text _font:" #~ msgstr "Písmo textu:" #~ msgid "Font style:" #~ msgstr "Styly písma:" #~ msgid "Paused" #~ msgstr "Pozastaveno" #~ msgid "Gone" #~ msgstr "Pryč" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "Zprávy\n" #~ "z MUC" # FIXME: better czech translation #~ msgid "Chatstate Tab Colors" #~ msgstr "Barvy stavů u záložek rozhovoru" #, fuzzy #~ msgid "Chat message" #~ msgstr "Zpráva diskuze:" #~ msgid "Use system _default" #~ msgstr "Použij nastavení _systému" #~ msgid "Font" #~ msgstr "Písmo" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Přezdívka kontaktu:" #, fuzzy #~ msgid "Contact's message" #~ msgstr "Zpráva kontaktu:" #, fuzzy #~ msgid "_Status message" #~ msgstr "_Stav:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Zvýraznění zprávy v diskuzi" #, fuzzy #~ msgid "Your nickname" #~ msgstr "Vaše přezdívka:" #, fuzzy #~ msgid "Your message" #~ msgstr "Vaše zpráva:" #, fuzzy #~ msgid "_URL highlight" #~ msgstr "Zvýraznění _URL:" # FIXME: better czech translation -co takhle? #~ msgid "Chat Line Colors" #~ msgstr "Barvy Řádků V Diskuzi" #~ msgid "Jabber ID:" #~ msgstr "Jabber ID:" #~ msgid "Resource:" #~ msgstr "Zdroj:" #~ msgid "Status:" #~ msgstr "Stav:" #~ msgid "Client:" #~ msgstr "Klient:" #~ msgid "Contact time:" #~ msgstr "Čas kontaktu:" #~ msgid "Ask:" #~ msgstr "Žádá:" #~ msgid "Subscription:" #~ msgstr "Autorizace:" #~ msgid "Name:" #~ msgstr "Jméno:" #~ msgid "Nickname:" #~ msgstr "Přezdívka:" #~ msgid "Street:" #~ msgstr "Ulice:" #~ msgid "City:" #~ msgstr "Město:" #~ msgid "State:" #~ msgstr "Stát:" #~ msgid "Extra Address:" #~ msgstr "Další adresa:" #~ msgid "Postal Code:" #~ msgstr "PSČ:" #~ msgid "Country:" #~ msgstr "Stát:" #~ msgid "Homepage:" #~ msgstr "Domovská stránka:" #~ msgid "E-Mail:" #~ msgstr "E-Mail:" #~ msgid "Phone No.:" #~ msgstr "Telefon:" #~ msgid "Birthday:" #~ msgstr "Narozeniny:" #~ msgid "Family:" #~ msgstr "Příjmení:" #~ msgid "Middle:" #~ msgstr "Prostřední:" #~ msgid "Prefix:" #~ msgstr "Před jménem" #~ msgid "Given:" #~ msgstr "Křestní:" #~ msgid "Suffix:" #~ msgstr "Za jménem:" #~ msgid "Full Name" #~ msgstr "Celé jméno:" #~ msgid "Company:" #~ msgstr "Společnost:" #~ msgid "Department:" #~ msgstr "Oddělení:" #~ msgid "Position:" #~ msgstr "Pozice:" #~ msgid "Role:" #~ msgstr "Postavení:" #~ msgid "- messages will be logged" #~ msgstr "- zprávy budou zaznamenány" #~ msgid "- messages will not be logged" #~ msgstr "- zprvý nebudou zaznamenány" #~ msgid "Edit %s" #~ msgstr "Uprav %s" #~ msgid "Register to %s" #~ msgstr "Registrovat k %s" #~ msgid "Conversation History with %s" #~ msgstr "Historie rozhovorů s %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Kontakt s \"%s\" nebyl navázán" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "Registrační informace pro transport %s nedorazily včas" #~ msgid "Register to" #~ msgstr "Zaregistrovat" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Jméno kontaktu" #~ msgid "Search:" #~ msgstr "Najít:" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Nemůžete měnit heslo, pokud nejste připojen(a)." #~ msgid "Invalid password" #~ msgstr "Neplatné heslo" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "Hesla zadaná v obou políčkách musí být identická." #~ msgid "Enter new password:" #~ msgstr "Zadejte heslo:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Zadejte znovu pro ověření:" #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "JID %s neodpovídá RFC. Nebude přidáno do tvého rosteru. Použij nástroje " #~ "pro správu rosteru jako je http://jru.jabberstudio.org/ k jeho odstranění" #~ msgid "unsubscribe request from %s" #~ msgstr "Žádost o zrušení autorizace od %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Automaticky vstoupit" #~ msgid "Homepage:" #~ msgstr "Dom. stránka:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Nastavit" #~ msgid "Manage Bookmarks" #~ msgstr "Spravovat záložky" #~ msgid "_Nickname:" #~ msgstr "_Přezdívka:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "" #~ "Pokud je zaškrtnuto, Gajim se připojí do této místnosti při spuštění" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Vypiš stav:" #, fuzzy #~ msgid "Add JID" #~ msgstr "Jabber ID" #, fuzzy #~ msgid "Preference:" #~ msgstr "Nastavení" #, fuzzy #~ msgid "Preference" #~ msgstr "Nastavení" #, fuzzy #~ msgid "JID:" #~ msgstr "Vaše JID:" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "Prosím vyplňte údaje kontaktu, který chcete přidat do účtu %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Prosím vyplňte údaje o kontaktu, který chcete přidat" #, fuzzy #~ msgid "Recently" #~ msgstr "Nedávno:" #~ msgid "Add New Contact" #~ msgstr "Přidat nový kontakt" #~ msgid "_User ID:" #~ msgstr "_Uživatel:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "Uživatel:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Přezdívka" #~ msgid "Personal Information" #~ msgstr "Osobní údaje" #~ msgid "Avatar:" #~ msgstr "Avatar:" #~ msgid "Click to set your avatar" #~ msgstr "Klikni pro nastavení tvého avatara" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "Odstranit skupinu" #~ msgid "Not fetched because of invisible status" #~ msgstr "Nestáhnuto z důvodu stavu neviditelnosti" #~ msgid "Please wait..." #~ msgstr "Prosím čekejte..." #~ msgid "" #~ "When negotiating an encrypted session, should Gajim assume you want your " #~ "messages to be logged?" #~ msgstr "" #~ "Pokud sestavuji šifrované sezení, má Gajim přepokládat povolení " #~ "zaznamenávání zpráv?" #~ msgid "Log _encrypted chat session" #~ msgstr "Logovat šifrované rozhovory" #, fuzzy #~ msgid "" #~ "If checked, Gajim will keep logs for encrypted messages. Please note that " #~ "when using end-to-end encryption the remote party has to agree on " #~ "logging, else the messages will not be logged." #~ msgstr "" #~ "Pokud je zaškrtnuto, Gajim ponechá záznamy šifrovaných zpráv. Avšak při " #~ "použití E2E musí protějšek souhlasit se záznamem, jinak zprávy nebudou " #~ "zaznamenávány." #~ msgid "Yahoo! Address:" #~ msgstr "Yahoo! adresa:" #~ msgid "Forward unread messages" #~ msgstr "Přeposlat nepřečtené zprávy" #~ msgid "All unread messages have been forwarded." #~ msgstr "Všechny nepřečtené zprávy byly přeposlány." #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "Přeposlat nepřečtené zprávy" #~ msgid "AIM Address:" #~ msgstr "AIM adresa:" #~ msgid "MSN Address:" #~ msgstr "MSN adresa:" #~ msgid "Confirm these session options" #~ msgstr "Potvrdit volby pro toto sezení" #, fuzzy #~ msgid "" #~ "The remote client wants to negotiate a session with these features:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Are these options acceptable?" #~ msgstr "" #~ "Vzdálený klient chce navázat sezení s těmito volbamy:\n" #~ "\n" #~ "\t%s\n" #~ "\n" #~ "\tJsou tyto volby přijatelné?" #~ msgid "" #~ "The remote client selected these options:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Continue with the session?" #~ msgstr "" #~ "Vzdálený klient vybral tyto volby:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Pokračovat v komunikaci?" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "Je OpenPGP povoleno pro tento kontakt?" #~ msgid "End to End message encryption" #~ msgstr "End to End šifrování zpráv" #~ msgid "Encrypting chat messages." #~ msgstr "Šifruji zprávy." #~ msgid "Requires python-crypto." #~ msgstr "Je potřeba python-crypto." #~ msgid "Session negotiation cancelled" #~ msgstr "Sezení bylo zrušeno" #, fuzzy #~ msgid "This session WILL NOT be archived on server" #~ msgstr "Sezení NEBUDE logováno" #~ msgid "This session is encrypted" #~ msgstr "Toto sezení je šifrované" #~ msgid " and WILL be logged" #~ msgstr "a BUDE zaznamenáváno" #~ msgid " and WILL NOT be logged" #~ msgstr "a NEBUDE zaznamenáváno" #~ msgid "" #~ "Remote contact's identity not verified. Click the shield button for more " #~ "details." #~ msgstr "" #~ "Kontakt nebyl ověřen. Klikněte na tlačítko štítu pro více informací." #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "GPG Šifrování vypnuto" #~ msgid "" #~ "Unable to decrypt message from %s\n" #~ "It may have been tampered with." #~ msgstr "" #~ "Nepodařilo se dešifrovat zprávu od %s\n" #~ "Možná je falešná." #~ msgid "Unable to decrypt message" #~ msgstr "Nepodařilo se dešifrovat zprávu" #~ msgid "Enable ESessions encryption for this account." #~ msgstr "Povolit ESessions šifrování pro tento účet." #~ msgid "Should Gajim automatically start an encrypted session when possible?" #~ msgstr "" #~ "Má se Gajim automaticky připojovat šifrovaným spojením je-li to možné?" #~ msgid "" #~ "[This is part of an encrypted session. If you see this message, something " #~ "went wrong.]" #~ msgstr "" #~ "[Tato zpráva je součástí šifrovaného sezení. Pokud vidíte tuto zprávu, " #~ "tak je něco špatně.]" #~ msgid "Requires python-avahi." #~ msgstr "Je potřeba python-avahi." #~ msgid "_Send" #~ msgstr "Ode_slat" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Uložit obrázek jako..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Exportuji záznamy historie..." #~ msgid "Choose Image" #~ msgstr "Vyberte obrázek" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Vyber soubor k odeslání..." #~ msgid "When %s becomes:" #~ msgstr "Kdy %s může být:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Přidávám zvláštní notifikaci pro %s" #, fuzzy #~ msgid "" #~ "It seems the SSL certificate of account %(account)s has changed and is " #~ "not valid or your connection is being compromised.\n" #~ "\n" #~ "Old SHA-1 fingerprint: %(old_sha1)s\n" #~ "Old SHA-256 fingerprint: %(old_sha256)s\n" #~ "\n" #~ "New SHA-1 fingerprint: %(new_sha1)s\n" #~ "New SHA-256 fingerprint: %(new_sha256)s\n" #~ "\n" #~ "Do you still want to connect and update the fingerprint of the " #~ "certificate?" #~ msgstr "" #~ "Vypadá to, že se SSL certifikát účtu %(account)s změnil nebo někdo " #~ "hackuje vaše spojení.\n" #~ "Starý otisk: %(old)s\n" #~ "Nový otisk: %(new)s\n" #~ "\n" #~ "Chcete se stále připojit a aktualizovat otisk certifikátu?" #, fuzzy #~ msgid "" #~ "The authenticity of the %s certificate could be invalid.\n" #~ "The certificate does not cover this domain." #~ msgstr "Autentizace certifikátu %s je neplatná." #~ msgid "Unable to load idle module" #~ msgstr "Nelze nahrát idle modul" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s je adresář, ale měl by to být soubor" #~ msgid "creating logs database" #~ msgstr "vytvářím databázi historie" #, fuzzy #~ msgid "creating cache database" #~ msgstr "vytvářím databázi historie" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Odeslat %s %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Gajimův Správce Historie" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Přejmenovat účet" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Odeslat jednoduchou _zprávu..." #, fuzzy #~ msgid "We received an error: {}" #~ msgstr "Služba vrátila chybu." #~ msgid "E2E encryption disabled" #~ msgstr "E2E Šifrování vypnuto" #, fuzzy #~ msgid "" #~ "Add this certificate to the list of trusted certificates.\n" #~ "SHA-1 fingerprint of the certificate:\n" #~ "%(sha1)s\n" #~ "SHA256 fingerprint of the certificate:\n" #~ "%(sha256)s" #~ msgstr "" #~ "Přidat tento certifikát do důvěryhodných.\n" #~ "SHA1 otisk certifikátu:\n" #~ "%s" #~ msgid "uri" #~ msgstr "uri" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Stagnuje" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Stagnuje" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Registrace selhala" #~ msgid "cyan" #~ msgstr "azurová" #~ msgid "migrating logs database to indices" #~ msgstr "převádím záznamy historie k použítí indexů" #, fuzzy #~ msgid "Send File..." #~ msgstr "Odeslat _Soubor" #, fuzzy #~ msgid "HTTP File Upload not supported by your server" #~ msgstr "Uložení metakontaktů není podporováno serverem" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Přenosy souborů" #~ msgid "" #~ "Your configured emoticons theme has not been found, so emoticons have " #~ "been disabled." #~ msgstr "" #~ "Vámi nastavené téma pro smajlíky nebylo nalezeno, proto budou smajlíci " #~ "vypnuty " #~ msgid "Shows or hides the roster window" #~ msgstr "Zobrazí nebo skryje okno Seznamu" #~ msgid "Shows or hides the ipython window" #~ msgstr "Zobrazí nebo skryje okno ipythonu" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "XMPP účet %s@%s" #, fuzzy #~ msgid "Exception" #~ msgstr "Popis" #, fuzzy #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "" #~ "%(jid)s by chtěl(a), aby jste %(action)s některé kontakty " #~ "z vašeho rosteru." #~ msgid "" #~ "Ordered list (space separated) of connection type to try. Can contain " #~ "tls, ssl or plain" #~ msgstr "" #~ "Řazený seznam (oddělený mezerami) spojení, která má Gajim zkusit. " #~ "Možnosti jsou: tls, ssl nebo plain" #~ msgid "_Actions" #~ msgstr "_Akce" #, fuzzy #~ msgid "Requires upower and python-dbus." #~ msgstr "Je potřeba python-dbus." #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Začít rozhovor" #~ msgid "You are already in group chat %s" #~ msgstr "Už jsi v místnosti %s" #~ msgid "Join Group Chat with account %s" #~ msgstr "Vstoupit do diskuze z účtu %s" #~ msgid "Invalid Account" #~ msgstr "Neplatný účtu" #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "Musíte vybrat účet, ze kterého chcete vstoupit do diskuze." #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "JProsím zadejte Jabber ID diskuze ve formě místnost@server." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "Jabber ID diskuze obsahuje nepřijatelné znaky." #~ msgid "Start Chat with account %s" #~ msgstr "Začít rozhovor z účtu %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Vyplňte Jabber ID nebo přezdívku kontaktu, se kterým chcete začít " #~ "rozhovor:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Dvakrát použité Jabber ID" #~ msgid "Unable to parse \"%s\"." #~ msgstr "Nemůžu dekódovat \"%s\"." #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "Zobrazte okno rozhovoru, aby jste mohl(a) poslat zprávu kontaktu" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID kontaktu, se kterým chcete komunikovat" #~ msgid "message content. The account must be specified or \"\"" #~ msgstr "obsah zprávy. Účet musí být uveden, nebo prázdné \"\"" #~ msgid "Adds contact to roster" #~ msgstr "Přidat kontakt do Seznamu" #~ msgid "jid" #~ msgstr "jid" #~ msgid "Adds new contact to this account" #~ msgstr "Přidá nový kontakt do tohoto účtu" #~ msgid "Opens 'Start Chat' dialog" #~ msgstr "Otevře dialog 'Začít rozhovor'" #~ msgid "Starts chat, using this account" #~ msgstr "Začít rozhovor z tohoto účtu" #, fuzzy #~ msgid "Handle a xmpp:/ URI" #~ msgstr "Obsluhovat xmpp:/ uri" #~ msgid "URI to handle" #~ msgstr "URI k obsluze" #~ msgid "Account in which you want to handle it" #~ msgstr "Účet s kterým chcete manipulovat" #~ msgid "Message content" #~ msgstr "Obsah zprávy" #~ msgid "Join a MUC room" #~ msgstr "_Vstoupit do místnosti MUC" #~ msgid "Nickname to use" #~ msgstr "Přezdívka kterou chete použít" #~ msgid "Password to enter the room" #~ msgstr "Heslo pro vstup do místnosti" #~ msgid "Account from which you want to enter the room" #~ msgstr "Účet z kterého chcete vstoupit do místnosti" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Nesprávné uri" #~ msgid "Nickname:" #~ msgstr "Přezdívka:" #~ msgid "Server:" #~ msgstr "Server:" #~ msgid "Password:" #~ msgstr "Heslo:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Připoj se do této místnosti automaticky po připojení" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Prohlížet" #, fuzzy #~ msgid "Requires libgtkspell and libenchant." #~ msgstr "Vyžaduje libgtkspell." #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "Správce sítě (network-manager)" #~ msgid "Autodetection of network status." #~ msgstr "Autodetekce stavu sítě." #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Je potřeba gnome-network-manager a python-dbus." #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "Vlastnost není k dispozici pod Windows." #~ msgid "This contact does not support file transfer." #~ msgstr "Tento kontakt nepodporuje přenos souborů." #, fuzzy #~ msgid "You need to know the real JID of the contact to send them a file." #~ msgstr "" #~ "Musíš znát skutečné JID kontaktu, aby mu bylo možné poslat souboru." #~ msgid "" #~ "You have to install %s dictionary to use spellchecking, or choose another " #~ "language by setting the speller_language option." #~ msgstr "" #~ "Musíš nainstalovat %s slovník k použití kontroly pravopisu, nebo vybrat " #~ "jiný jazyk nastavením volby speller_language." #~ msgid "Hides the buttons in chat windows." #~ msgstr "Skryje tlačítka v okně diskuze." #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Změ_nit přezdívku" #~ msgid "Change the room's subject (Alt+T)" #~ msgstr "Změnit téma místnosti (Alt+T)" #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "Přidat tuto místnost do záložek" #~ msgid "Browse the chat history (Ctrl+H)" #~ msgstr "Procházet historii diskuze (Ctrl+H)" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Zobrazit nabídku rozšířených funkcí (Alt+D)" #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Přidat kontakt do Seznamu (Ctrl+D)" #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "Pozvat kontakty k rozhovoru (Ctrl+G)" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Zobrazit profil kontaktu (Ctrl+I)" #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Zobrazit profil kontaktu (Ctrl+I)" #~ msgid "Ma_ke message windows compact" #~ msgstr "Udělej o_kna zpráv kompaktní" #~ msgid "Hide all buttons in chat windows" #~ msgstr "Skryje tlačítka v okně diskuze." #, fuzzy #~ msgid "Hide the chat buttons" #~ msgstr "Použití: /%s, skryje tlačítka rozhovoru." #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "pokud zapnuto, Gajim se zeptá na avatara každého kontaktu který neměl " #~ "naposledy avatara nebo kterého uložený je příliš starý." #~ msgid "Disk Write Error" #~ msgstr "Chyba zápisu na disk (možná je plný?)" #~ msgid "Set Custom _Avatar..." #~ msgstr "Nastavit vlastní Avatar" #, fuzzy #~ msgid "SSL certificate validation" #~ msgstr "Validace SSL certifikátu" #~ msgid "" #~ "A library used to validate server certificates to ensure a secure " #~ "connection." #~ msgstr "" #~ "Knihovna se používá k ověření certifikátu serveru pro zabezpečené spojení." #, fuzzy #~ msgid "Requires python-pyopenssl > 0.12 and pyasn1." #~ msgstr "Je potřeba python-pyopenssl." #, fuzzy #~ msgid "?CLI:room" #~ msgstr "místnost" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "přezdívka" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "heslo" #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "Používej DBus a Notifikačního démona k zobrazování notifikací" #~ msgid "Notification" #~ msgstr "Upozornění" #~ msgid "Passive popups notifying for new events." #~ msgstr "Pasivní okna oznamující nové události." #~ msgid "" #~ "Requires python-notify or instead python-dbus in conjunction with " #~ "notification-daemon." #~ msgstr "" #~ " Je potřeba python-notify nebo python-dbus ve spojení s notification-" #~ "daemon." #~ msgid "Ignore" #~ msgstr "Ignorovat" #~ msgid "_Open Gmail Inbox" #~ msgstr "_Otevři schránku Gmailu" #~ msgid "Notify on new _GMail email" #~ msgstr "Upozorni při novém _GMail emailu" #~ msgid "" #~ "If checked, Gajim will show a notification when a new e-mail is received " #~ "via GMail" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim uvede také informaci o odesilateli zprávy nového " #~ "emailu" #~ msgid "Display _extra email details" #~ msgstr "Zobraz _podrobnosti emailu" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim uvede také informaci o odesilateli zprávy nového " #~ "emailu" #~ msgid "GMail Options" #~ msgstr "Volby GMail" #, fuzzy #~ msgid "12" #~ msgstr "1" #, fuzzy #~ msgid "20" #~ msgstr "2" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Odeslat %s %s" #~ msgid "GMail Email Received" #~ msgstr "Přišel GMail Email" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Nový E-mail pro %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "Máte %d nepřečtený E-mail" #~ msgstr[1] "Máte %d nepřečtené E-maily" #~ msgstr[2] "Máte %d nepřečtených E-mailů" #~ msgid "" #~ "\n" #~ "\n" #~ "From: %(from_address)s\n" #~ "Subject: %(subject)s\n" #~ "%(snippet)s" #~ msgstr "" #~ "\n" #~ "\n" #~ "Od: %(from_address)s\n" #~ "Předmět: %(subject)s\n" #~ "%(snippet)s" #~ msgid "Re_name" #~ msgstr "Přejme_novat" #~ msgid "Resour_ce:" #~ msgstr "Zd_roj: " #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "Zdroj je odeslán Jabber serveru pro oddělení stejné JID na dvě nebo více " #~ "částí závisejících na počtu připojených klientů na stejný server se " #~ "stejným účtem. Takže můžete být připojeni ke stejnému účtu se zdroji " #~ "'Domov' a 'Práce' zároveň. Zdroj, který má nejvyšší prioritu obdrží " #~ "zprávy. (více následuje)" #~ msgid "A_djust to status" #~ msgstr "_Nastavit podle stavu" #~ msgid "Priority will change automatically according to your status." #~ msgstr "Priorita se automaticky změní podle vašeho stavu." #~ msgid "Anonymous authentication" #~ msgstr "Anonymní autentizace" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "Priorita je v Jabberu použita ke zjištění, kdo obdrží zprávu od jabber " #~ "serveru, pokud je připojeno více klientů přes stejný účet. Zprávu obdrží " #~ "klient s vyšší prioritou" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Synchronizovat kontakty" #~ msgid "Click to request authorization to all contacts of another account" #~ msgstr "Klikněte k vyžádání autorizace od všech kontaktů jiného účtu" #~ msgid "Chan_ge Password" #~ msgstr "_Změnit heslo" #~ msgid "Click to change account's password" #~ msgstr "Klikněte pro změnu hesla k účtu" #~ msgid "Administration operations" #~ msgstr "Seznam správců" #~ msgid "Browse..." #~ msgstr "Procházet..." #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "Certifikát odmítnut" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim po spuštění se automaticky připojí pomocí tohoto " #~ "účtu" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Synchronizovat kontakty" #~ msgid "Synch_ronize account status with global status" #~ msgstr "Synch_ronizovat stav účtu s globálním stavem" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Pokud zaškrtnuto, jakákoliv změna globálního stavu (pomocí comboboxu na " #~ "spodní straně Seznamu) změní stav tohoto účtu také" #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Pokud je zaškrtnuto, Gajim ohlásí navíc několik dalších IP kromě Vaší IP, " #~ "takže přenos souboru má větší šanci správného fungování." #~ msgid "Proxy" #~ msgstr "Proxy" #~ msgid "" #~ "Check this so Gajim will ask you before sending your password over an " #~ "insecure connection." #~ msgstr "" #~ "Zaškrtněte pokud se má Gajim ptát předtím než odešlete vaše heslo přes " #~ "nezabezpečené připojení." #~ msgid "Send _keep-alive packets" #~ msgstr "Odesílat keep-alive pakety" #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim bude posílat keep-alive pakety, aby předešel " #~ "ztrátě spojení způsobeném vypršením spojení" #~ msgid "Use cust_om hostname/port" #~ msgstr "Použít vlastní _jméno počítače/port" #~ msgid "_Hostname: " #~ msgstr "_Počítač: " #~ msgid "_Port: " #~ msgstr "_Port:" #~ msgid "No key selected" #~ msgstr "Není zvolen žádný klíč" #~ msgid "Choose _Key..." #~ msgstr "Vyberte _klíč..." #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "Pokud bude zaškrtnuto, Gajim si bude pamatovat heslo pro tento účet" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #~ msgid "_Edit Personal Information..." #~ msgstr "_Upravit osobní informace..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Informace o Vás, jak jsou uloženy na serveru" #~ msgid "Personal Information" #~ msgstr "Osobní údaje" #~ msgid "Co_nnect on Gajim startup" #~ msgstr "_Připojit po startu Gajimu" #~ msgid "Synchroni_ze account status with global status" #~ msgstr "Synch_ronizovat stav účtu s globálním stavem" #~ msgid "Use cust_om port:" #~ msgstr "Použít _vlastní port:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Pokud výchozí port použitý k přijímání zpráv nevyhovuje tvému nastavení, " #~ "můžeš si zvolit jiný.\n" #~ "Můžeš také zvážit změnu nastavení firewallu." #~ msgid "Mer_ge accounts" #~ msgstr "_Spojit účty" #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "OpenPGP na tomto počítači není použitelné" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Ke změně jména účtu se musite odpojit." #~ msgid "To change the account name, you must read all pending events." #~ msgstr "Před změnou jména účtu si musíte přečíst všechny čekající zprávy." #~ msgid "Account Name Already Used" #~ msgstr "Jméno účtu už existuje" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "Toto jméno je už použito pro jiný účet. Zvolte jiné, prosím." #~ msgid "Invalid account name" #~ msgstr "Neplatné jméno účtu" #~ msgid "Account name cannot be empty." #~ msgstr "Jméno účtu nemůže být prázdné." #~ msgid "Account name cannot contain spaces." #~ msgstr "Jméno účtu nesmí obsahovat mezery." #~ msgid "Enter a new name for account %s" #~ msgstr "Zadej nové jméno pro účet %s." #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "Jabber ID musí být ve tvaru \"uživatel@jménoserveru\"." #~ msgid "No such account available" #~ msgstr "Takový účet není dostupný" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "Musíte vytvořit účet před úpravou vašich osobních údajů." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "Bez připojení nemůžete upravovat osobní údaje." #, fuzzy #~ msgid "Your server does not have vCard support" #~ msgstr "Váš server nepodporuje vizitky." #~ msgid "Your server can't save your personal information." #~ msgstr "Váš server neumí uložit Vaše osobní informace." #~ msgid "Account Local already exists." #~ msgstr "Účet Local už existuje." #~ msgid "Please rename or remove it before enabling link-local messaging." #~ msgstr "Prosím přejmenujte nebo odstraňte před povolením lokálních zpráv." #~ msgid "THANKS:" #~ msgstr "DÍKY:" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "Nemůžu zapsat do %s. Podpora správy sezení nebude fungovat" #~ msgid "Jabber Traffic" #~ msgstr "Provoz Jabberu" #~ msgid "_Enable" #~ msgstr "_Povolit" #, fuzzy #~ msgid "Filter" #~ msgstr "Písmo" #~ msgid "_IQ" #~ msgstr "_IQ" #~ msgid "Info/Query" #~ msgstr "Info/Query" #~ msgid "_Message" #~ msgstr "_Zpráva" #~ msgid "XML Input" #~ msgstr "Vstup XML" #~ msgid "XML Console for %s" #~ msgstr "XML Konzole pro %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "XML Konzole pro %s" #~ msgid "Last status: %s" #~ msgstr "Poslední stav: %s" #~ msgid " since %s" #~ msgstr " od %s" #~ msgid "since %s" #~ msgstr "od %s" #, fuzzy #~ msgid "No" #~ msgstr "Žádný" #~ msgid "Yes" #~ msgstr "Ano" #, fuzzy #~ msgid "Prefer" #~ msgstr "Nastavení" #, fuzzy #~ msgid "Forbid" #~ msgstr "Zakázat" #, fuzzy #~ msgid "Auto" #~ msgstr "Automaticky vstoupit" #, fuzzy #~ msgid "body" #~ msgstr "tělo" #, fuzzy #~ msgid "approve" #~ msgstr "schválit" #, fuzzy #~ msgid "otr" #~ msgstr "Ostatní" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Neplatné jméno serveru" #, fuzzy #~ msgid "There is an error" #~ msgstr "Služba vrátila chybu." #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "Kolik minut by měly řádky z předchozího rozhovoru zůstat." #~ msgid "" #~ "Your configured emoticons theme cannot been loaded. You maybe need to " #~ "update the format of emoticons.py file. See http://trac.gajim.org/wiki/" #~ "Emoticons for more details." #~ msgstr "" #~ "Vámi nastavené téma smajlíků se nepodařilo načíst. Možná je potřeba " #~ "aktualizovat formát v souboru emoticons.py. Viz.: http://trac.gajim.org/" #~ "wiki/Emoticons " #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Budete připojen(a) k %s bez OpenPGP." #~ msgid "The following message was NOT encrypted" #~ msgstr "Následující zpráva NEBYLA šifrovaná" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Povolit ESessions šifrování pro tento účet." #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Přepnout Open_PGP šifrování" #~ msgid "Toggle End to End Encryption" #~ msgstr "Přepnout šifrování mezi uživateli" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "GPG Šifrování zapnuto" #, fuzzy #~ msgid "No OpenPGP key assigned" #~ msgstr "Nepřiřazen GPG klíč" #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages with OpenPGP." #~ msgstr "" #~ "Tento kontakt nemá přiřazen GPG klíč. Proto nemůžeš šifrovat pomocí GPG " #~ "zprávy." #~ msgid "Session WILL be logged" #~ msgstr "Sezení BUDE logováno" #~ msgid "Session WILL NOT be logged" #~ msgstr "Sezení NEBUDE logováno" #~ msgid "is" #~ msgstr "je" #~ msgid "is NOT" #~ msgstr "NENÍ" #~ msgid "will" #~ msgstr "bude" #~ msgid "will NOT" #~ msgstr "NEBUDE" #~ msgid "The following message was encrypted" #~ msgstr "Následující zpráva byla šifrovaná" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Přepnout Open_PGP šifrování" #~ msgid "Is OpenPGP enabled for this contact?" #~ msgstr "Je OpenPGP povoleno pro tento kontakt?" #~ msgid "" #~ "Should Gajim automatically start an encrypted session with this contact " #~ "when possible?" #~ msgstr "" #~ "Má Gajim uskutečnit šifrované spojení s tímto kontaktem je-li k dispozici?" # FIXME: co to je? #~ msgid "Neither the remote presence is signed, nor a key was assigned." #~ msgstr "Není podepsaná přítomnost ani není přiřazen klíč." #~ msgid "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "Klíč kontaktu (%s) se neshoduje s klíčem v Gajimu." #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Tato zpráva je *zašifrovaná* (Viz :XEP:\"27\")]" #~ msgid "" #~ "Your chat session with %(jid)s is encrypted.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Vaš rozhovor s %(jid)s je šifrovaný.\n" #~ "\n" #~ "Krátký Autentizační řetězec pro toto sezení je: %(sas)s" #~ msgid "You have already verified this contact's identity." #~ msgstr "Už jste prověřoval identitu tohoto kontaktu." #~ msgid "Contact's identity verified" #~ msgstr "Identita kontaktu ověřena" #, fuzzy #~ msgid "Verify again…" #~ msgstr "Ověřit znovu" #~ msgid "" #~ "To be certain that only the expected person can read your messages " #~ "or send you messages, you need to verify their identity by clicking the " #~ "button below." #~ msgstr "" #~ "Chcete-li mít jistotu, že pouze důvěryhodné osoby mohou číst vaše " #~ "zprávy nebo vám poslat zprávu, je potřeba ověřit jejich identitu kliknutí " #~ "na tlačítko dole." #~ msgid "Contact's identity NOT verified" #~ msgstr "Identita kontaktu NENÍ ověřena" #, fuzzy #~ msgid "Verify…" #~ msgstr "_Kontroluj" #~ msgid "Have you verified the contact's identity?" #~ msgstr "Ověřil(a) jste identitu kontaktu?" #~ msgid "" #~ "To prevent talking to an unknown person, you should speak to %(jid)s directly (in person or on the phone) and verify that they see the same " #~ "Short Authentication String (SAS) as you.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Pro zabránění man-in-the-middle útoku, si promluvte přímo s %(jid)s (například osobně nebo po telefonu) a ověřte zda vidí stejný Krátký " #~ "Autentizační řetězec (SAS) jako vy.\n" #~ "Krátký Autentizační řetězec: %(sas)s" #~ msgid "Did you talk to the remote contact and verify the SAS?" #~ msgstr "Mluvily jste se vzdáleným kontaktem a ověřil s ním SAS?" #~ msgid "" #~ "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "" #~ "Klíč kontaktu (%s) se neshoduje s klíčem přiřazeným v Gajimu." #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages." #~ msgstr "" #~ "Tomuto kontaktu není přiřazen GPG klíč. Proto nemůžete šifrovat zprávy." #, fuzzy #~ msgid "" #~ "OpenPGP key is assigned to this contact, but you do not trust their " #~ "key, so message cannot be encrypted. Use your OpenPGP client " #~ "to trust their key." #~ msgstr "" #~ "Tomuto kontaktu je přiřazen GPG klíč, ale Vy nedůvěřujete jeho klíči, proto zpráva nemůže být zašifrovaná. Použijte Váš GPG klient " #~ "pro nastavení důvěry." #, fuzzy #~ msgid "" #~ "OpenPGP Key is assigned to this contact, and you trust their key, so " #~ "messages will be encrypted." #~ msgstr "" #~ "Tento kontakt má přiřazen GPG klíč a tomuto klíči důvěřujete, zprávy tedy " #~ "budou šifrované." #~ msgid "" #~ "This icon indicates that this message has not yet\n" #~ "been received by the remote end. If this icon stays\n" #~ "for a long time, it's likely the message got lost." #~ msgstr "" #~ "Tato ikona indikuje, že zpráva ještě nebyla přijata protější\n" #~ "stranou. Pokud zůstává dlouho, zpráva je pravděpodobně\n" #~ "ztracena." #~ msgid "" #~ "If True, listen to D-Bus signals from NetworkManager and change the " #~ "status of accounts (provided they do not have listen_to_network_manager " #~ "set to False and they sync with global status) based upon the status of " #~ "the network connection." #~ msgstr "" #~ "Je-li povoleno, čeká na D-Bus signál z NetworkManager a změní stav účtů " #~ "(pokud nemají nastaveno listen_to_network_manager nastavený na False a " #~ "synchronizují se s globálním stavem) v závislosti na stavu síťového " #~ "připojení." #~ msgid "" #~ "The database file (%s) cannot be read. Try to repair it or remove it (all " #~ "history will be lost)." #~ msgstr "" #~ "Nelze přečíst soubor databáze (%s). Opravte ho nebo smažte (tím ztratíte " #~ "všechny zprávy v historii)." #~ msgid "Database cannot be read." #~ msgstr "Nemohu číst z databáze." #~ msgid "A message from a non-valid JID arrived, it has been ignored." #~ msgstr "Přišla zpráva od neplatného JID a byla ignorována." #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Jemné posouvání v okně diskuze" #~ msgid "Show _XML Console" #~ msgstr "Zobrazit _XML konzoli" #~ msgid "Edit _Privacy Lists..." #~ msgstr "Upravit kontrolu soukromí..." #~ msgid "_Administrator" #~ msgstr "_Správce" #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "Poslat zprávu momentálně připojeným uživatelům tohoto serveru" #~ msgid "Sets Message of the Day" #~ msgstr "Nastaví Zprávu dne" #~ msgid "Updates Message of the Day" #~ msgstr "Upraví Zprávu dne" #~ msgid "Deletes Message of the Day" #~ msgstr "Smaže zprávu dne" #~ msgid "Add _Contact..." #~ msgstr "Přid_at Kontakt..." #~ msgid "_Accounts" #~ msgstr "Úč_ty" #~ msgid "Profile, A_vatar" #~ msgstr "Profil, A_vatar" #, fuzzy #~ msgid "P_lugins" #~ msgstr "P_luginy" #~ msgid "File _Transfers" #~ msgstr "_Přenosy souborů" #~ msgid "Help online" #~ msgstr "Nápověda online" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Často kladené dotazy - FAQ (online)" #~ msgid "Fea_tures" #~ msgstr "Vlastnosti serveru" #~ msgid "to %s account" #~ msgstr "do účtu %s" #~ msgid "using %s account" #~ msgstr "pomocí účtu %s" #~ msgid "of account %s" #~ msgstr "účtu %s" #~ msgid "for account %s" #~ msgstr "pro účet %s" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Smazáním kontaktu také zrušíte autorizaci. Kontakt Vás tak vždy uvidí " #~ "jako odpojeného." #~ msgid "Invalid Jabber ID" #~ msgstr "Neplatné Jabber ID" #~ msgid "Verify..." #~ msgstr "Ověřit..." #~ msgid "This file is being used by another process." #~ msgstr "Tento soubor je používán jiným procesem." #~ msgid "pgp key" #~ msgstr "pgp klíč" #~ msgid "" #~ "Sends new single message to a contact in the roster. Both OpenPGP key and " #~ "account are optional. If you want to set only 'account', without 'OpenPGP " #~ "key', just set 'OpenPGP key' to ''." #~ msgstr "" #~ "Poslat novou prostou zprávu kontaktu v Seznamu. Obojí OpenPGP klíč a účet " #~ "jsou volitelné. Pokud chcete nastavit pouze 'account' bez 'OpenPGP key', " #~ "nastavte prostě 'OpenPGP key' na ''." #, fuzzy #~ msgid "Please first choose another theme as your current theme." #~ msgstr "Vyberte prosím napřed jiné téma." #~ msgid "A non-privacy-related room configuration change has occurred" #~ msgstr "Nastala změna nastavení netýkající se soukromí" #, fuzzy #~ msgid "Maximum number of users for %s has been reached" #~ msgstr "V %s byl dosažen maximální počet uživatelů" #~ msgid "Your passphrase is incorrect" #~ msgstr "Vaše heslo je neplatné" #, fuzzy #~ msgid "OpenPGP Passphrase Incorrect" #~ msgstr "Heslo OpenGPG není platné" #, fuzzy #~ msgid "OpenPGP key not trusted" #~ msgstr "GPG klíč není důvěryhodný" #~ msgid "You successfully received %(filename)s from %(name)s." #~ msgstr "Soubor %(filename)s od %(name)s byl úspěsně přijat." #, fuzzy #~ msgid "Set logs directory" #~ msgstr "vytvářím adresář %s " #~ msgid "_Manage Bookmarks..." #~ msgstr "Spravovat _záložky..." # FIXME: nejak divne, asi spatne prelozene -ne myslim ze to je ok #~ msgid "Change Status Message..." #~ msgstr "Změnit popis stavu..." #~ msgid "_Change Status Message..." #~ msgstr "_Změnit popis stavu..." #~ msgid "" #~ "You are not interested in the contact's presence, and neither he/she is " #~ "interested in yours" #~ msgstr "Vy ani kontakt se nezajímáte o stav toho druhého" #~ msgid "Error description..." #~ msgstr "Popis chyby..." #, fuzzy #~ msgid "View contact information (Ctrl+I)" #~ msgstr "Pozvat kontakty k rozhovoru (Ctrl+G)" #~ msgid "3" #~ msgstr "3" #~ msgid "4" #~ msgstr "4" #~ msgid "5" #~ msgstr "5" #~ msgid "6" #~ msgstr "6" #~ msgid "7" #~ msgstr "7" #~ msgid "8" #~ msgstr "8" #~ msgid "9" #~ msgstr "9" #~ msgid "*" #~ msgstr "*" #, fuzzy #~ msgid "Groupchat Histories" #~ msgstr "Diskuze" #, fuzzy #~ msgid "All Chat Histories" #~ msgstr "Všechny stavy" #, fuzzy #~ msgid "homepage url" #~ msgstr "Dom. stránka:" #~ msgid "More" #~ msgstr "Více" #~ msgid "creating %s directory" #~ msgstr "vytvářím adresář %s " #~ msgid "" #~ "If True, Gajim will use KDE Wallet (if kwalletcli is available) to store " #~ "account passwords." #~ msgstr "" #~ "Je-li povoleno, Gajim použije KDE Wallet (je-li dostupný kwalletcli) k " #~ "uložení hesel účtů." #~ msgid "%s is not the name of a group chat." #~ msgstr "%s není jméno diskuze." #~ msgid "Session Management" #~ msgstr "Správa Sezení" #~ msgid "Gajim session is stored on logout and restored on login." #~ msgstr "" #~ "Sezení Gajimu je uloženo při odhlášení a znovu načteno při přihlášení." #~ msgid "Requires python-gnome2." #~ msgstr "Je potřeba python-gnome2." #~ msgid "Requires gnome-keyring and python-gnome2-desktop, or kwalletcli." #~ msgstr "Je potřeba gnome-keyring a python-gnome2-desktop, nebo kwalletcli." #~ msgid "SRV" #~ msgstr "SRV" #~ msgid "Ability to connect to servers which are using SRV records." #~ msgstr "Schopnost připojit se na servery používající SRV záznamy." #~ msgid "Requires dnsutils." #~ msgstr "Je potřeba dnsutils." #~ msgid "Requires nslookup to use SRV records." #~ msgstr "Je potřeba nslookup pro použití SRV záznamů." #~ msgid "Gajim needs X server to run. Quiting..." #~ msgstr "Gajim vyžaduje k běhu X server. Končím..." #~ msgid "importing PyGTK failed: %s" #~ msgstr "import PyGTK selhal: %s" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above" #~ msgstr "Gajim vyžaduje PyGTK 2.12 nebo novější" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above to run. Quiting..." #~ msgstr "Gajim vyžaduje PyGTK 2.12 nebo novější. Končím..." #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above" #~ msgstr "Gajim potřebuje GTK 2.12 nebo novější" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above to run. Quiting..." #~ msgstr "Gajim vyžaduje GTK 2.12 nebo novější. Končím..." #~ msgid "Gajim needs pywin32 to run" #~ msgstr "Gajim potřebuje k běhu pywin32" #~ msgid "" #~ "Please make sure that Pywin32 is installed on your system. You can get it " #~ "at %s" #~ msgstr "" #~ "Prosím ujistěte se, že Pywin32 je nainstalován na vašem počítači. Můžete " #~ "jej získat na %s" #~ msgid "Gajim is already running" #~ msgstr "Gajim již běží" #~ msgid "" #~ "Another instance of Gajim seems to be running\n" #~ "Run anyway?" #~ msgstr "" #~ "Jiná instance Gajimu pravděpodobně již běží\n" #~ "Přesto spustit?" # FIXME: neni presne #~ msgid "A programming error has been detected" #~ msgstr "Byla objevena chyba v programu" #~ msgid "Details" #~ msgstr "Detaily" #, fuzzy #~ msgid "" #~ "Gnome Keyring is installed but not correctly started (environment " #~ "variable probably not correctly set)" #~ msgstr "" #~ "Gnome Keyring je nainstalován ale není správně spuštěn (proměná prostředí " #~ "není asi správně nastavena)" #~ msgid "Jabber ID: " #~ msgstr "Jabber ID:" #~ msgid "Resource: " #~ msgstr "Zdroj: " #~ msgid "Subscription: " #~ msgstr "Autorizace: " #, fuzzy #~ msgid "Mood: " #~ msgstr "Nálada:" #, fuzzy #~ msgid "Activity: " #~ msgstr "Činnost:" #~ msgid "Join _Group Chat..." #~ msgstr "Vstoupit do _Diskuze" #~ msgid "_Modify Account" #~ msgstr "Upravit účet" #~ msgid "Check on startup if Gajim is the _default Jabber client" #~ msgstr "Vždy při startu zkontroluj, zda je Gajim _výchozí Jabber klient" #~ msgid "" #~ "If True, Gajim will check if it's the default jabber client on each " #~ "startup." #~ msgstr "" #~ "Pokud zapnuto, Gajim zkontroluje, zda je výchozí jabber klient, při " #~ "každém startu." #~ msgid "Gajim is not the default Jabber client" #~ msgstr "Gajim není výchozí Jabber klient" #~ msgid "Would you like to make Gajim the default Jabber client?" #~ msgstr "Chcete nastavit Gajim jako výchozí Jabber klient?" #~ msgid "Always check to see if Gajim is the default Jabber client on startup" #~ msgstr "Vždy zkontroluj při startu, zda je Gajim výchozí Jabber klient." #~ msgid "Send Single Message" #~ msgstr "Ode_slat jednoduchou zprávu" #~ msgid "Execute Command..." #~ msgstr "Provést příkaz..." #~ msgid " a window/tab opened with that contact " #~ msgstr "okno/žáložka otevřená s tímto kontaktem" #~ msgid "Actions" #~ msgstr "Akce" #~ msgid "Conditions" #~ msgstr "Podmínky" #~ msgid "Advanced Actions" #~ msgstr "Pokročilé akce" #~ msgid "Advanced Notifications Control" #~ msgstr "Pokročilá správa upozorňování" #~ msgid "Busy " #~ msgstr "Nerušit" #, fuzzy #~ msgid "Contact Change Status " #~ msgstr "Kontakt změnil stav" #~ msgid "Don't have " #~ msgstr "Nemá" #~ msgid "File Transfer Started " #~ msgstr "Přenos souboru zahájen" #, fuzzy #~ msgid "Group Chat Message Highlight " #~ msgstr "Zvýraznění zprávy v diskuzi" #, fuzzy #~ msgid "Group Chat Message Received " #~ msgstr "Přijetí zprávy v diskuzi" #~ msgid "Launch a command" #~ msgstr "Provést příkaz" #~ msgid "One or more special statuses..." #~ msgstr "Jeden nebo více zvláštních stavů..." #~ msgid "Online / Free For Chat" #~ msgstr "Připojen / Ukecaný" #~ msgid "Play a sound" #~ msgstr "Přehrát zvuk" #~ msgid "When " #~ msgstr "Když" #~ msgid "" #~ "_Activate window manager's UrgencyHint to make chat window in taskbar " #~ "flash" #~ msgstr "" #~ "_Aktivuj UrgencyHint window manageru pro blikání okna rozhovoru v liště " #~ "úloh" #~ msgid "_Disable auto opening chat window" #~ msgstr "_Vypnout automatické otevírání okna rozhovoru" #~ msgid "_Disable existing popup window" #~ msgstr "_Vypnout vyskakování existujících oken" #~ msgid "_Disable existing sound for this event" #~ msgstr "_Vypnout existující zvuky pro tuto událost" #, fuzzy #~ msgid "_Disable showing event in notification area" #~ msgstr "_Vypnout zobrazování události v rosteru" #~ msgid "_Disable showing event in roster" #~ msgstr "_Vypnout zobrazování události v rosteru" #~ msgid "_Inform me with a popup window" #~ msgstr "_Upozorni mě vyskočením okna" #~ msgid "_Open chat window with user" #~ msgstr "_Otevři okno rozhovoru s uživatelem" #~ msgid "_Show event in roster" #~ msgstr "_Zobrazit událost v rosteru" #~ msgid "and I " #~ msgstr "a já" #~ msgid "contact(s)" #~ msgstr "kontakt(y)" #~ msgid "everybody" #~ msgstr "každý" #~ msgid "for " #~ msgstr "pro" #, fuzzy #~ msgid "group(s)" #~ msgstr "Skupiny" #~ msgid "when I'm in" #~ msgstr "když jsem v " #~ msgid "_Allow him/her to see my status" #~ msgstr "_Dovol kontaktu vidět můj stav" #, fuzzy #~ msgid "Descrition:" #~ msgstr "Popis:" #~ msgid "Advanced..." #~ msgstr "Rozšířené..." #~ msgid "Display _activity of contacts in roster" #~ msgstr "Zobrazovat čin_nosti kontaktů v seznamu" #~ msgid "Display _tunes of contacts in roster" #~ msgstr "Zobrazovat _hudbu kontaktů v seznamu" #~ msgid "Display m_ood of contacts in roster" #~ msgstr "Zobrazovat _nálady kontaktů v seznamu" #~ msgid "" #~ "If checked, Gajim will display the activity of contacts in the roster " #~ "window" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim bude zobrazovat avatary kontaktů v okně Seznamu a " #~ "v diskuzích" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the location of contacts in the roster " #~ "window" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim bude zobrazovat avatary kontaktů v okně Seznamu a " #~ "v diskuzích" #~ msgid "" #~ "If checked, Gajim will display the tunes of contacts in the roster window" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim bude zobrazovat avatary kontaktů v okně Seznamu a " #~ "v diskuzích" #~ msgid "Gajim Instant Messenger" #~ msgstr "Gajim Instant Messenger" #~ msgid "English" #~ msgstr "Angličtina" #~ msgid "Belarusian" #~ msgstr "Běloruština" #~ msgid "Bulgarian" #~ msgstr "Bulharština" #~ msgid "Breton" #~ msgstr "Bretonština" #~ msgid "Czech" #~ msgstr "Čeština" #~ msgid "German" #~ msgstr "Němčina" #~ msgid "Greek" #~ msgstr "Řečtina" #~ msgid "British" #~ msgstr "Britština" #~ msgid "Esperanto" #~ msgstr "Esperanto" #~ msgid "Spanish" #~ msgstr "Španělština" #~ msgid "Basque" #~ msgstr "Baskičtina" #~ msgid "French" #~ msgstr "Francouzština" #~ msgid "Croatian" #~ msgstr "Chorvatština" #~ msgid "Italian" #~ msgstr "Italština" #~ msgid "Norwegian (b)" #~ msgstr "Norština (b)" #~ msgid "Dutch" #~ msgstr "Holandština" #~ msgid "Norwegian" #~ msgstr "Norština" #~ msgid "Polish" #~ msgstr "Polština" #~ msgid "Portuguese" #~ msgstr "Portugalština" #~ msgid "Brazilian Portuguese" #~ msgstr "Brazilská portugalština" #~ msgid "Russian" #~ msgstr "Ruština" #~ msgid "Serbian" #~ msgstr "Srbština" #~ msgid "Slovak" #~ msgstr "Slovenština" #~ msgid "Swedish" #~ msgstr "Švédština" #~ msgid "Chinese (Ch)" #~ msgstr "Čínština" #~ msgid "Spelling language" #~ msgstr "Kontrola jazyka" #~ msgid "" #~ "If True, Gajim will convert string between $$ and $$ to an image using " #~ "dvips and convert before insterting it in chat window." #~ msgstr "" #~ "Je-li povoleno, Gajim převede řetězec mezi $$ a $$ na obrázek pomocí " #~ "dvips a převede před vložením do okna rozhovoru." #~ msgid "" #~ "Change the value to change the size of latex formulas displayed. The " #~ "higher is larger." #~ msgstr "" #~ "Změnou hodnoty změníte velikost zobrazovaných formulí latexu. Vyšší " #~ "znamená větší." #~ msgid "all or space separated status" #~ msgstr "všechny nebo mezerou oddělené stavy" #~ msgid "'yes', 'no', or 'both'" #~ msgstr "'yes', 'no', nebo 'both'" #~ msgid "'yes', 'no' or ''" #~ msgstr "'yes', 'no' nebo ''" #~ msgid "Check your connection or try again later" #~ msgstr "Ověřte připojení nebo zkuste později" #~ msgid "Error executing \"%(command)s\": %(error)s" #~ msgstr "chyba při spouštění \"%(command)s\": %(error)s" #~ msgid "error: cannot open %s for reading" #~ msgstr "chyba: nemůžu otevřít %s pro čtení" #~ msgid "Unable to bind to port %s." #~ msgstr "Nemohu naslouchat na portu %s." #~ msgid "" #~ "Maybe you have another running instance of Gajim. File Transfer will be " #~ "cancelled." #~ msgstr "" #~ "Možná máš puštěnou jinou instanci Gajimu. Přenos souborů bude zrušen." #~ msgid "A GTK+ jabber client" #~ msgstr "GTK+ Jabber client" #~ msgid "Condition" #~ msgstr "Podmínka" #~ msgid "when I am " #~ msgstr "když jsem " #~ msgid "Requires pybonjour (http://o2s.csail.mit.edu/o2s-wiki/pybonjour)." #~ msgstr "Je potřeba pybonjour (http://o2s.csail.mit.edu/o2s-wiki/pybonjour)." #~ msgid "LaTeX" #~ msgstr "LaTeX" #~ msgid "Transform LaTeX expressions between $$ $$." #~ msgstr "Převede LaTeX výraz mezi $$ $$." #, fuzzy #~ msgid "" #~ "Requires texlive-latex-base and (dvipng or ImageMagick). You have to set " #~ "'use_latex' to True in the Advanced Configuration Editor." #~ msgstr "" #~ "Je potřeba texlive-latex-base a dvipng. Dále musíte nastavit 'use_latex' " #~ "na True v Editoru rozšířeného nastavení." #, fuzzy #~ msgid "" #~ "Requires texlive-latex-base and (dvipng or ImageMagick) (All is in " #~ "MikTeX). You have to set 'use_latex' to True in the Advanced " #~ "Configuration Editor." #~ msgstr "" #~ "Je potřeba texlive-latex-base a dvipng (vše je v MikTeXu). Dále musíte " #~ "nastavit 'use_latex' na True v Editoru rozšířeného nastavení." #~ msgid "Requires python-farsight." #~ msgstr "Je potřeba python-farsight." #, fuzzy #~ msgid "one of: offline, online, chat, away, xa, dnd, invisible " #~ msgstr "" #~ "jeden z: odpojen, připojen, ukecaný, pryč, nedostupný, nerušit, " #~ "neviditelný " #, fuzzy #~ msgid "" #~ "Returns current status message(the global one unless account is specified)" #~ msgstr "Vrací aktuální popis stavu (globální, pokud není uveden účet)" #~ msgid "" #~ "Usage: %s %s %s \n" #~ "\t %s" #~ msgstr "" #~ "Použití: %s %s %s \n" #~ "\t %s" #, fuzzy #~ msgid "" #~ "Too many arguments. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Příliš mnoho parametrů. \n" #~ "Napište \"%(basename)s help %(command)s\" pro více informací" #, fuzzy #~ msgid "" #~ "Argument \"%s\" is not specified. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Parametr \"%(arg)s\" nebyl uveden. \n" #~ "Napište \"%(basename)s help %(command)s\" pro více informací" #~ msgid "Disk WriteError" #~ msgstr "Chyba zápisu na disk" #~ msgid "Subject: %s" #~ msgstr "Předmět: %s" #, fuzzy #~ msgid "Mood: %s" #~ msgstr "Nálada:" #, fuzzy #~ msgid "Activity: %s" #~ msgstr "Činnost:" #~ msgid "_Disable showing event in systray" #~ msgstr "_Vypnout zobrazování události vy systrayi" #~ msgid "_Show event in systray" #~ msgstr "_Zobrazit událost v systrayi" #~ msgid "Always use GNOME default applications" #~ msgstr "Vždy použít OS/X výchozí aplikace" #~ msgid "Always use Xfce default applications" #~ msgstr "Vždy použít OS/X výchozí aplikace" #~ msgid "Autodetect on every Gajim startup" #~ msgstr "_Připojit po startu Gajimu" #~ msgid "Show systray:" #~ msgstr "Zobraz oznamovací oblast:" #~ msgid "Nickname not allowed: %s" #~ msgstr "Přezdívka nepovolena: %s" #~ msgid "we are now subscribed to %s" #~ msgstr "jsme nyní zapsáni k %s" #~ msgid "we are now unsubscribed from %s" #~ msgstr "byla nám zrušena autorizace od %s" #~ msgid "Account Modification" #~ msgstr "Úprava účtu" #~ msgid "" #~ "Check this so Gajim will connect in port 5223 where legacy servers are " #~ "expected to have SSL capabilities. Note that Gajim uses TLS encryption by " #~ "default if broadcasted by the server, and with this option enabled TLS " #~ "will be disabled" #~ msgstr "" #~ "Zaškrtněte pokud se má Gajim připojit na port 5223, kde obvykle nabízejí " #~ "starší servery SSL. Pozor- Gajim použije TLS šifrování standardně, pokud " #~ "server ohlásí jeho podporu. Touto volbou bude TLS vypnuto" #~ msgid "Edit Personal Information..." #~ msgstr "Upravit osobní informace..." #~ msgid "Hostname: " #~ msgstr "Počítač: " #~ msgid "" #~ "If checked, Gajim will store the password in ~/.gajim/config with 'read' " #~ "permission only for you" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim uloží heslo v ~/.gajim/config s právem čtení " #~ "pouze pro Vás" #~ msgid "Port: " #~ msgstr "Port: " #~ msgid "Save _passphrase (insecure)" #~ msgstr "Uložit _heslo (nebezpečné)" #~ msgid "Use _SSL (legacy)" #~ msgstr "Použít _SSL (staré)" #~ msgid "gtk-add" #~ msgstr "gtk-add" #~ msgid "gtk-close" #~ msgstr "gtk-close" #~ msgid "gtk-remove" #~ msgstr "gtk-remove" #~ msgid "" #~ "Receive a Message\n" #~ "Contact Disconnected \n" #~ "Contact Change Status \n" #~ "Group Chat Message Highlight \n" #~ "Group Chat Message Received \n" #~ "File Transfer Request \n" #~ "File Transfer Started \n" #~ "File Transfer Finished" #~ msgstr "" #~ "Obdržet zprávu \n" #~ "Kontakt odpojen \n" #~ "Kontakt změnil stav \n" #~ "Zvýraznění zprávy z diskuze \n" #~ "Obdržení zprávy z diskuze \n" #~ "Žádost o přenos souboru \n" #~ "Začátek přenosu souboru \n" #~ "Ukončení přenosu souboru" #~ msgid "" #~ "contact(s)\n" #~ "group(s)\n" #~ "everybody" #~ msgstr "" #~ "kontakty\n" #~ "skupiny\n" #~ "všichni" #~ msgid "" #~ "Account row\n" #~ "Group row\n" #~ "Contact row\n" #~ "Chat Banner" #~ msgstr "" #~ "Řádek účtu\n" #~ "Řádek skupiny\n" #~ "Řádek kontaktu\n" #~ "Nadpis rozhovoru" #~ msgid "" #~ "Enter JID or Contact name\n" #~ "Groupchat Histories\n" #~ "All Chat Histories" #~ msgstr "" #~ "Zadej JID nebo jméno kontaktu\n" #~ "Historie diskuzí\n" #~ "Historie všech rozhovorů" #~ msgid "gtk-delete" #~ msgstr "gtk-delete" #~ msgid "Send a file (Ctrl+F)" #~ msgstr "Poslat soubor (Ctrl+F)" #~ msgid "" #~ "All chat states\n" #~ "Composing only\n" #~ "Disabled" #~ msgstr "" #~ "Všechny stavy rozhovoru\n" #~ "Pouze píšu zprávu\n" #~ "Vypnuto" #~ msgid "" #~ "Autodetect on every Gajim startup\n" #~ "Always use GNOME default applications\n" #~ "Always use KDE default applications\n" #~ "Always use Xfce default applications\n" #~ "Custom" #~ msgstr "" #~ "Automaticky zjistit při každém startu aplikace\n" #~ "Vždy použít výchozí aplikace z GNOME\n" #~ "Vždy použít výchozí aplikace z KDE\n" #~ "Vždy použít výchozí aplikace z Xfce\n" #~ "Vlastní" #~ msgid "" #~ "Detached roster with detached chats\n" #~ "Detached roster with single chat\n" #~ "Single window for everything\n" #~ "Detached roster with chat grouped by account\n" #~ "Detached roster with chat grouped by type" #~ msgstr "" #~ "Samostatný roster a samostatná okna pro diskuze\n" #~ "Samostatný roster s jedním diskuzním oknem\n" #~ "Samostatné okno pro všechno\n" #~ "Samostatný roster a samostatná okna pro diskuze pro každý účet\n" #~ "Samostatný roster s diskuzními okny podle typu" #~ msgid "" #~ "Pop it up\n" #~ "Notify me about it\n" #~ "Show only in roster" #~ msgstr "" #~ "Upozorni mě aktivací okna\n" #~ "Upozorni mě\n" #~ "Zobrazit pouze v rosteru" #~ msgid "" #~ "none\n" #~ "both\n" #~ "from\n" #~ "to" #~ msgstr "" #~ "žádná\n" #~ "oboustranná\n" #~ "ode mě\n" #~ "ke mě" #~ msgid "gtk-cancel" #~ msgstr "gtk-close" #~ msgid "pysqlite2 (aka python-pysqlite2) dependency is missing. Exiting..." #~ msgstr "" #~ "Závislost na pysqlite2 (neboli python-pysqlite2) není splněna. Končím..." #~ msgid "Banners and clickable links" #~ msgstr "Bannery a klikatelné odkazy" #~ msgid "Ability to have clickable URLs in chat and groupchat window banners." #~ msgstr "" #~ "Funkce umožňující mít klikatelné URL odkazy v rozhovoru a předmětu " #~ "diskuze." #~ msgid "Requires python-sexy." #~ msgstr "Je potřeba python-sexy." #~ msgid "GTK+ runtime is missing libglade support" #~ msgstr "GTK+ runtime vyžaduje podporu libglade" #~ msgid "" #~ "Please remove your current GTK+ runtime and install the latest stable " #~ "version from %s" #~ msgstr "" #~ "Prosím odinstalujte stávající GTK+ runtime a nainstalujte poslední " #~ "stabilní verzi z %s" #~ msgid "" #~ "Please make sure that GTK+ and PyGTK have libglade support in your system." #~ msgstr "" #~ "Ujistěte se prosím, že GTK+ a PyGTK ve Vašem systému podporují libglade." #~ msgid "Gajim needs PySQLite2 to run" #~ msgstr "Gajim vyžaduje PySQLite2" #~ msgid "_Incoming message:" #~ msgstr "_Příchozí zpráva:" #~ msgid "_Outgoing message:" #~ msgstr "_Odchozí zpráva:" #~ msgid "gtk-ok" #~ msgstr "gtk-close" #~ msgid "" #~ "The host %s you configured as the ft_add_hosts_to_send advanced option is " #~ "not valid, so ignored." #~ msgstr "" #~ "Host %s nastevený jako ft_add_hosts_to_send má rozšířenou volbu chybnou, " #~ "bude ignorována." #~ msgid "OpenPGP passphrase was not given" #~ msgstr "OpenPGP heslo nebylo zadáno" #~ msgid "" #~ "To continue sending and receiving messages, you will need to reconnect." #~ msgstr "" #~ "Pro pokračování v přijímání a odesílání zpráv se musíte znovu připojit." #~ msgid "" #~ "You are not connected or not visible to others. Your message could not be " #~ "sent." #~ msgstr "" #~ "Nejsi připojen nebo viditelný pro ostatní. Tvoje zpráva nemůže být " #~ "odeslána." #~ msgid "[This message is encrypted]" #~ msgstr "[Tato zpráva je zašifrovaná]" #~ msgid "Trayicon" #~ msgstr "Tray ikona" #~ msgid "A icon in systemtray reflecting the current presence." #~ msgstr "Ikona v systémové liště zobrazující aktuální stav." #~ msgid "" #~ "Requires python-gnome2-extras or compiled trayicon module from Gajim " #~ "sources." #~ msgstr "" #~ "Je potřeba python-gnome2-extras nebo zkompilovaný trayicon modul ze " #~ "zdrojáků Gajima." #~ msgid "Requires PyGTK >= 2.10." #~ msgstr "Je potřeba PyGTK verze 2.10. nebo vyšší." #~ msgid "Add Special _Notification" #~ msgstr "Přidat zvláštní _upozornění" #~ msgid "Assign Open_PGP Key" #~ msgstr "Přiřadit Open_PGP klíč" #~ msgid "Commands: %s" #~ msgstr "Příkazy: %s" #~ msgid "" #~ "Usage: /%(command)s , sends action to the current group chat. Use " #~ "third person. (e.g. /%(command)s explodes.)" #~ msgstr "" #~ "Použití: /%(command)s , pošle akci do aktuální místnosti. Použijte " #~ "třetí osobu (například /%(command)s explodoval.)" #~ msgid "No help info for /%s" #~ msgstr "Žádná další nápověda pro /%s" #~ msgid "Enable link-local/zeroconf messaging" #~ msgstr "Povolit lokální zprávy typu zeroconf" #~ msgid "Nickname not found: %s" #~ msgstr "Přezdívka nenalezena: %s" #~ msgid "This group chat has no subject" #~ msgstr "Místnost nemá žádné téma" #~ msgid "" #~ "Usage: /%s [reason], bans the JID from the group chat. The " #~ "nickname of an occupant may be substituted, but not if it contains \"@\". " #~ "If the JID is currently in the group chat, he/she/it will also be kicked." #~ msgstr "" #~ "Použití: /%s [důvod], zakáže JID přístup do místnosti. " #~ "Přezdívka nájemníka může být nahrazena, pokud neobsahuje \"@\". Pokud je " #~ "JID právě v místnosti, bude vyhozen. NEpodporuje mezery v přezdívce." #~ msgid "" #~ "Usage: /%s [reason], closes the current window or tab, displaying reason " #~ "if specified." #~ msgstr "" #~ "Použití: /%s [důvod], uzavře toto okno nebo záložku, a vypíše důvod, " #~ "pokud byl uveden." #~ msgid "" #~ "Usage: /%s [reason], invites JID to the current group chat, " #~ "optionally providing a reason." #~ msgstr "" #~ "Použití: /%s [důvod], pozve JID do této místnosti, případně s " #~ "uvedeným důvodem." #~ msgid "" #~ "Usage: /%s @[/nickname], offers to join room@server " #~ "optionally using specified nickname." #~ msgstr "" #~ "Použití: /%s @[/přezdívka], nabízí vstup do místnosti " #~ "místnost@server, případně s uvedenou přezdívkou." #~ msgid "" #~ "Usage: /%s [reason], removes the occupant specified by " #~ "nickname from the group chat and optionally displays a reason." #~ msgstr "" #~ "Použití: /%s [důvod], odstraní nájemníka určeného přezdívkou " #~ "z místnosti a případně zobrazí důvod. NEpodporuje mezery v přezdívce." #~ msgid "" #~ "Usage: /%s [message], opens a private message window and sends " #~ "message to the occupant specified by nickname." #~ msgstr "" #~ "Použití: /%s [zpráva], otevře okno se soukromou zprávou a " #~ "odešle zprávu nájemníkovi určeném přezdívkou." #~ msgid "Usage: /%s , changes your nickname in current group chat." #~ msgstr "Použití: /%s , změní Vaši přezdívku v aktuální místnosti" #~ msgid "" #~ "Usage: /%s [topic], displays or updates the current group chat topic." #~ msgstr "" #~ "Použití: /%s [téma], zobrazí nebo aktualizuje téma v aktuální místnosti." #~ msgid "" #~ "Usage: /%s , sends a message without looking for other commands." #~ msgstr "Použití: /%s , odešle zprávu bez hledání jiných příkazů." #~ msgid "" #~ "Usage: /%s , allow to send you messages and private " #~ "messages." #~ msgstr "Použití: /%s , změní Vaši přezdívku v aktuální místnosti" #~ msgid "B_OSH Port:" #~ msgstr "B_OSH Port:" #~ msgid "Select the account with which to synchronise" #~ msgstr "Vybrat účet pro synchronizaci" #~ msgid "File transfer stopped by the contact at the other end" #~ msgstr "Přenos souboru byl ukončen protistranou" #~ msgid "Generic" #~ msgstr "Obecné" #~ msgid "" #~ "%(title)s by %(artist)s\n" #~ "from %(source)s" #~ msgstr "" #~ "%(title)s od %(artist)s\n" #~ "z %(source)s" #~ msgid "This account is already configured in Gajim." #~ msgstr "Tento účet už je nastaven v Gajimu." #~ msgid "Mood" #~ msgstr "Nálada" #~ msgid "Click to see features (like MSN, ICQ transports) of jabber servers" #~ msgstr "" #~ "Klikněte pro seznam vlastností (jako MSN, ICQ transporty) jabber serverů" #~ msgid "Click to see past conversation in this room" #~ msgstr "Kliknutím zobraz historii konverzace v této místnosti" #~ msgid "History Viewer" #~ msgstr "Prohlížeč historie" #~ msgid "JID Selection" #~ msgstr "Výběr JID" #~ msgid "" #~ "Choose the chatlog you want to view. \n" #~ "Enter the jid of a groupchat or a contact here. For online accounts you " #~ "can even enter a a contact's nickname." #~ msgstr "" #~ "Vyber záznam rozhovoru pro zobrazení.\n" #~ "Zadej jid diskuze nebo kontaktu. Pro připojené účty můžeš zadat také " #~ "přezdívku kontaktu." #~ msgid "in" #~ msgstr "v" #~ msgid "Invitation Received" #~ msgstr "Přišlo pozvání" #~ msgid "Name:" #~ msgstr "Jméno:" #~ msgid "Publish and Subscribe" #~ msgstr "Zveřejni a odebírej" #~ msgid "Allow others to see your:" #~ msgstr "Povol ostatním vidět tvůj:" #~ msgid "" #~ "If checked, Gajim will sort contacts in roster window and groupcahts by " #~ "their status and not by the shown name" #~ msgstr "" #~ "Pokud zaškrtnuto, Gajim bude řadit kontakty v okně rosteru podle stavu, " #~ "nikoliv zobrazeného jména" #~ msgid "Receive your contact's:" #~ msgstr "Přijmi tvé kontakty:" #~ msgid "Tune" #~ msgstr "Píseň" #~ msgid "Avatar:" #~ msgstr "Avatar:" #~ msgid "Role:" #~ msgstr "Postavení:" #~ msgid "A_ccounts" #~ msgstr "Úč_ty" #~ msgid "_Services" #~ msgstr "_Služby" #~ msgid "OS:" #~ msgstr "OS:" #~ msgid "Modify Account" #~ msgstr "Upravit účet" #~ msgid "inactive" #~ msgstr "Neaktivní" #~ msgid "working" #~ msgstr "Pracuji" #~ msgid "day_off" #~ msgstr "volný den" #~ msgid "having_a_beer" #~ msgstr "Na pivě" #~ msgid "having_tea" #~ msgstr "Holím se" #~ msgid "in_a_car" #~ msgstr "v autě" #~ msgid "in_real_life" #~ msgstr "v reálném životě" #~ msgid "on_a_bus" #~ msgstr "v autobuse" #~ msgid "on_a_plane" #~ msgstr "V letadle" #~ msgid "on_a_train" #~ msgstr "Ve vlaku" #~ msgid "on_a_trip" #~ msgstr "na cestě" #~ msgid "on_the_phone" #~ msgstr "Zrovna telefonuji." #~ msgid "sleeping" #~ msgstr "Spím" #~ msgid "walking" #~ msgstr "Procházím se" #~ msgid "watching_tv" #~ msgstr "Sleduji TV" #~ msgid "watching_a_movie" #~ msgstr "Dívám se na film." #~ msgid "cold" #~ msgstr "Tučné" #~ msgid "hot" #~ msgstr "Vášnivý" #~ msgid "in_awe" #~ msgstr "devět" #~ msgid "in_love" #~ msgstr "zamilovaný" #~ msgid "moody" #~ msgstr "Náladový" #~ msgid "sick" #~ msgstr "Nemocný" #~ msgid "PyOpenSSL" #~ msgstr "PyOpenSSL" #~ msgid "gnome-keyring" #~ msgstr "gnome-keyring" #~ msgid "" #~ "Requires python-gnome2-extras or compilation of gtkspell module from " #~ "Gajim sources." #~ msgstr "" #~ "Je potřeba python-gnome2-extras nebo zkompilovaný gtkspell modul ze " #~ "zdrojáků Gajima." #~ msgid "Idle" #~ msgstr "Nečinný" #~ msgid "Requires compilation of the idle module from Gajim sources." #~ msgstr "Je potřeba zkompilovat idle modul ze zdrojáků Gajima." #~ msgid "" #~ "Requires texlive-latex-base, dvips and imagemagick. You have to set " #~ "'use_latex' to True in the Advanced Configuration Editor." #~ msgstr "" #~ "Vyžaduje texlive-latex-base, dvips a imagemagick. Dále musíte nastavit " #~ "'use_latex' na True v Editoru rozšířeného nastavení." #~ msgid "libsexy" #~ msgstr "libsexy" #~ msgid "%s is now known as %s" #~ msgstr "%s se nyní nazývá %s" #~ msgid "%s is now %s (%s)" #~ msgstr "%s je nyní %s (%s)" #~ msgid "%s is now %s" #~ msgstr "%s je nyní %s" #~ msgid "" #~ "\n" #~ "From: %(from_address)s" #~ msgstr "" #~ "\n" #~ "Odesílatel: %(from_address)s" #~ msgid "Network Manager support not available" #~ msgstr "Podpora Network Manageru není dostupná" #~ msgid "Session Management support not available (missing gnome.ui module)" #~ msgstr "Podpora Správce sezení není dostupná (schází gnome.ui modul)" #~ msgid "No such command: /%s (if you want to send this, prefix it with /say)" #~ msgstr "" #~ "Neexistující příkaz: /%s (chceš-li poslat tohle, napiš před to /say)" #~ msgid "" #~ "Usage: /%s , sends action to the current group chat. Use third " #~ "person. (e.g. /%s explodes.)" #~ msgstr "" #~ "Použití: /%s , pošle akci do aktuální místnosti. Použijte třetí " #~ "osobu (například /%s explodoval.)" #~ msgid "E2E encryption enabled" #~ msgstr "E2E šifrování zapnuto" #~ msgid "OK to continue with negotiation?" #~ msgstr "Pokračovat s dohadováním?" #~ msgid "" #~ "You've begun an encrypted session with %s, but it can't be guaranteed " #~ "that you're talking directly to the person you think you are.\n" #~ "\n" #~ "You should speak with them directly (in person or on the phone) and " #~ "confirm that their Short Authentication String is identical to this one: " #~ "%s\n" #~ "\n" #~ "Would you like to continue with the encrypted session?" #~ msgstr "" #~ "Započal(a) jsi šifrované sezení s %s, ale nemůžu zaručit, že mluvíš přímo " #~ "se zamýšleným člověkem.\n" #~ "Měl(a) by sis s ním promluvit přímo (tváří v tvář nebo telefonicky) a " #~ "ujistit se, zda je jeho Short Authentication String identická s tímto: " #~ "%s\n" #~ "\n" #~ "Přejete si pokračovat s šifrovaném sezení?" #~ msgid "Yes, I verified the Short Authentication String" #~ msgstr "Ano, ověřil(a) jsem Short Authentication String" #~ msgid "\"%(title)s\" by %(artist)s" #~ msgstr "\"%(title)s\" od %(artist)s" #~ msgid "" #~ "To continue, Gajim needs to access your stored secrets. Enter your " #~ "passphrase" #~ msgstr "Pro pokračování potřebuje Gajim uložená tajemství.Zadej heslo" #~ msgid "Confirm Passphrase" #~ msgstr "Potvrďte heslo" #~ msgid "Enter your new passphrase again for confirmation" #~ msgstr "Zadejte nové heslo znovu pro ověření" #~ msgid "Create Passphrase" #~ msgstr "Vytvořit heslo" #~ msgid "Passphrases did not match.\n" #~ msgstr "Hesla se neshodují.\n" #~ msgid "Gajim needs you to create a passphrase to encrypt stored secrets" #~ msgstr "Gajim potřebuje vytvořit heslo pro zašifrování uložených tajemství" #~ msgid "Affiliation:" #~ msgstr "Vztah:" #~ msgid "" #~ "If checked, Gajim can regularly poll a Last.fm account and adjust the " #~ "status message to reflect recently played songs. " #~ "set_status_msg_from_current_music_track option must be False." #~ msgstr "" #~ "Při zaškrtnutí bude Gajim pravidelně kontrolovat Last.fm účet a " #~ "nastavovat stavovou zprávu podle posledních přehrávaných skladeb.Volba " #~ "set_status_msg_from_current_track musí být False" #~ msgid "The username used to identify the Last.fm account." #~ msgstr "Uživatelské jméno pro Last.gm účet." #~ msgid "" #~ "When negotiating an encrypted session, should Gajim prefer to use public " #~ "keys for identification?" #~ msgstr "" #~ "Pokud sestavuji šifrované sezení, má Gajim upřednostnit použití veřejných " #~ "klíčů k identifikaci?" #~ msgid "" #~ "Subject: %s\n" #~ "%s" #~ msgstr "" #~ "Předmět: %s\n" #~ "%s" #~ msgid "Gajim account %s" #~ msgstr "Gajim účet %s" #~ msgid "Connection to host could not be established" #~ msgstr "Spojení s počítačem se nepodařilo navázat." #~ msgid "" #~ "Connection to host could not be established: Incorrect answer from server." #~ msgstr "Spojení k počítači nebylo navázáno: Neplatná odpověd od serveru" #~ msgid "Verify remote identity" #~ msgstr "Ověřit identitu" #~ msgid "\"%(title)s\" by " #~ msgstr "\"%(title)s\" od" #~ msgid "Thoughtful" #~ msgstr "Zamyšlený" gajim-gajim-1.1.3/po/da.po000066400000000000000000012436151345766322700152650ustar00rootroot00000000000000# Danish translations for Gajim package. # Copyright (C) 2007 GAJIM'S COPYRIGHT HOLDER # This file is distributed under the same license as the Gajim package. # # Niels Felsted Thorsen , 2007, 2009. msgid "" msgstr "" "Project-Id-Version: Gajim 0.13\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2009-11-18 19:33+0100\n" "Last-Translator: Niels Felsted Thorsen \n" "Language-Team: <>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Emacs 22.1.50.1, po-mode 2.02+0.4\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "Virkelig send denne fil?" #: gajim/chat_control_base.py:1103 #, fuzzy, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "" "Hvis du sender en fil til %s, vil han eller hun få at vide dit rigtige " "Jabber ID." #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Fil" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Tid" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Fremgang" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Filnavn: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Størrelse: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "Du" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Afsender: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Modtager: " #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Gemt i: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Filoverførsel er fuldført" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 #, fuzzy msgid "Open _Containing Folder" msgstr "_Åbn folderen med filen" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "Filoverførsel er afbrudt" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "Tilslutning til ligeværdige kan ikke oprettes." #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "Modtager: %s" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "Fejl besked: %s" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 msgid "File transfer stopped" msgstr "Filoverførsel stoppede" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" #: gajim/filetransfers_window.py:341 msgid "Gajim can not read this file" msgstr "Gajim kan ikke læse denne fil" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "En anden process bruger denne fil." #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "Kan ikke overskrive den eksisterende fil \"%s\"" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "" "En fil med dette navn eksisterer allerede og du har ikke rettigheder til at " "overskrive den." #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Denne fil eksisterer allerede" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "Hvad vil du gøre?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "Kataloget \"%s\" er ikke skrivbart" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "Du har ikke rettigheder til at oprette filer i dette katalog." #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Fil: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Type: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Beskrivelse: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "%s vil gerne sende dig en fil:" #: gajim/filetransfers_window.py:487 msgid "Checking file…" msgstr "Tjekker fil..." #: gajim/filetransfers_window.py:501 msgid "File error" msgstr "Fejl i filen" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/s)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Ugyldig Fil" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Fil: " #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "Det er ikke mulig at sende tomme filer" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Navn: " #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Afsender: " #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Pause" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "_Fortsæt" #: gajim/filetransfers_window.py:1019 #, fuzzy msgid "Choose a File to Send…" msgstr "Vælg en fil at sende..." #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "Udvidelse er ikke understøttet" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "Billede kan ikke gemmes i formatet %(type)s. Gem som %(new_filename)s?" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 #, fuzzy msgid "Save _As" msgstr "Har" #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "?Client:Ukendt" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "?OS:Ukendt" #: gajim/vcard.py:326 gajim/vcard.py:329 msgid "?Time:Unknown" msgstr "?Tid:Ukendt" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "" #: gajim/vcard.py:384 msgid "Affiliation:" msgstr "Tilknytning:" #: gajim/vcard.py:391 #, fuzzy msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "" "Denne kontakt er interesseret i din tilstedeværelses information, men du er " "ikke interesseret i hans/hendes tilstedeværelse" #: gajim/vcard.py:393 #, fuzzy msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "" "Du er interesseret i kontaktens tilstedeværelses information, men han/hun er " "ikke interesseret i din" #: gajim/vcard.py:395 #, fuzzy msgid "The contact and you want to exchange presence information" msgstr "" "Du og kontakten er begge interessered i hinandens tilstedeværelses " "information" #: gajim/vcard.py:397 #, fuzzy msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "" "Du og kontakten er begge interessered i hinandens tilstedeværelses " "information" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "Du venter på kontaktens svar om din abonnements forespørsel" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "Der er ikke nogen ventende abbonerings forespørgsler." #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr " ressource med prioritet " #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "Alle filer" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 #, fuzzy msgid "Clear File" msgstr "Gør Rent" #: gajim/options_dialog.py:484 #, fuzzy msgid "Manage Proxies" msgstr "Håndter Proxy Profiler" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Ingen" #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "_Tilpas til status" #: gajim/options_dialog.py:528 msgid "On" msgstr "" #: gajim/options_dialog.py:528 #, fuzzy msgid "Off" msgstr "Afkoblet" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Forsøg på at hente krypteringsnøgler mislykkedes" #: gajim/options_dialog.py:565 msgid "There is no OpenPGP secret key available." msgstr "Der er ikke nogen hemmelig OpenPGP nøgle tilgængelig." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "OpenPGP Nøgle Valg" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Vælg din OpenPGP Nøgle" #: gajim/gui_menu_builder.py:95 msgid "_New Group Chat" msgstr "_Ny Gruppe Samtale" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Ikke i Kontaktvinduet" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "Jeg vil gerne tilføje dig til mit kontaktvindue" #: gajim/gui_menu_builder.py:502 #, fuzzy msgid "Send Single _Message…" msgstr "Send en Enkel _Besked" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 msgid "Send Cus_tom Status" msgstr "Send _Tilpasset Status" #: gajim/gui_menu_builder.py:535 #, fuzzy msgid "E_xecute Command…" msgstr "_Kør Kommando" #: gajim/gui_menu_builder.py:543 msgid "_Manage Transport" msgstr "Hå_ndter Transport" #: gajim/gui_menu_builder.py:549 msgid "_Modify Transport" msgstr "_Modificer Transport" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 #, fuzzy msgid "_Rename…" msgstr "_Omdøb" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "_Fjern blokering" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "_Bloker" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 msgid "Remo_ve" msgstr "_Fjern" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 msgid "_Information" msgstr "_Information" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 #, fuzzy msgid "Send File…" msgstr "Send _Fil" #: gajim/gui_menu_builder.py:602 #, fuzzy msgid "Upload File…" msgstr "Gem Fil som..." #: gajim/gui_menu_builder.py:603 #, fuzzy msgid "Send File Directly…" msgstr "Gem Fil som..." #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Inviter _Kontakter" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "_Tilføj til Kontaktliste" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "_Information" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 #, fuzzy msgid "History" msgstr "_Historie" #: gajim/gui_menu_builder.py:634 #, fuzzy msgid "Manage Room" msgstr "Håndter Ru_m" #: gajim/gui_menu_builder.py:635 #, fuzzy msgid "Change Subject" msgstr "Ændre _Emne..." #: gajim/gui_menu_builder.py:636 #, fuzzy msgid "Configure Room" msgstr "Tilpas _Rum..." #: gajim/gui_menu_builder.py:637 #, fuzzy msgid "Upload Avatar…" msgstr "Vælg Billede" #: gajim/gui_menu_builder.py:638 #, fuzzy msgid "Destroy Room" msgstr "_Slet rum" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "" #: gajim/gui_menu_builder.py:641 #, fuzzy msgid "Change Nick" msgstr "Ændre _Kælenavn..." #: gajim/gui_menu_builder.py:642 #, fuzzy msgid "Bookmark Room" msgstr "Bogmærk dette rom" #: gajim/gui_menu_builder.py:643 #, fuzzy msgid "Request Voice" msgstr "_Stemme" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 #, fuzzy msgid "Notify on all messages" msgstr "Forvalgte beskeder:" #: gajim/gui_menu_builder.py:645 #, fuzzy msgid "Minimize on close" msgstr "_Minimer ved lukning" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 #, fuzzy msgid "Execute command" msgstr "_Kør Kommando" #: gajim/gui_menu_builder.py:648 #, fuzzy msgid "Disconnect" msgstr "Afbry_d tilslutningen" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "" #: gajim/gui_menu_builder.py:680 #, fuzzy, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "%i dage siden" msgstr[1] "%i dage siden" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Bliv med i en Gruppe Samtale" #: gajim/gui_menu_builder.py:734 #, fuzzy msgid "Add Contact…" msgstr "_Tilføj Kontakt..." #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 #, fuzzy msgid "Profile" msgstr "fil" #: gajim/gui_menu_builder.py:737 #, fuzzy msgid "Discover Services" msgstr "Op_dag Tjenester" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Send en Enkel _Besked" #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Avanceret" #: gajim/gui_menu_builder.py:740 #, fuzzy msgid "Archiving Preferences" msgstr "_Indstillinger" #: gajim/gui_menu_builder.py:741 #, fuzzy msgid "Synchronise History" msgstr "Synkroniser" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "Privatlivs lister" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 #, fuzzy msgid "Server Info" msgstr "Server" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "XML Konsol" #: gajim/gui_menu_builder.py:746 #, fuzzy msgid "Admin" msgstr "_Administrator" #: gajim/gui_menu_builder.py:747 #, fuzzy msgid "Send Server Message…" msgstr "_Send Server Besked..." #: gajim/gui_menu_builder.py:748 #, fuzzy msgid "Set MOTD…" msgstr "Sæt MOTD..." #: gajim/gui_menu_builder.py:749 #, fuzzy msgid "Update MOTD…" msgstr "Opdater MOTD..." #: gajim/gui_menu_builder.py:750 #, fuzzy msgid "Delete MOTD…" msgstr "Slet MOTD" #: gajim/gui_menu_builder.py:799 #, fuzzy msgid "No Accounts available" msgstr "Ingen konto tilgængelig" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Konti" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 #, fuzzy msgid "Copy JID" msgstr "Rum JID" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Bliv med i en Gruppe Samtale" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Start Samtale" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 #, fuzzy msgid "Add to Roster…" msgstr "_Tilføj til Kontaktliste" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "_Kopier Henvisning" #: gajim/gui_menu_builder.py:881 #, fuzzy msgid "Open Link in Browser" msgstr "_Åbn Henvisning i Netlæser" #: gajim/gui_menu_builder.py:886 #, fuzzy msgid "Copy Email Address" msgstr "_Kopier JID/E-post Adresse" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Åbn E-post Program" #: gajim/gui_menu_builder.py:892 #, fuzzy msgid "Copy JID/Email" msgstr "_Kopier JID/E-post Adresse" #: gajim/history_manager.py:71 #, fuzzy msgid "Usage:" msgstr "besked" #: gajim/history_manager.py:73 #, fuzzy msgid "Options:" msgstr "Føl_elsesikoner:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "Kan ikke finde historik log databasen" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Dato" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Kælenavn" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Besked" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Emne" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" "Vil du rydde op i databasen? (DETTE ER IKKE ANBEFALET HVIS GAJIM KØRER)" #: gajim/history_manager.py:257 #, fuzzy msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" "Normalt vil den allokerede database størrelse ikke blive frigjort, den vil " "bare kunne genbruges. Hvis du virkelig vil reducere database filstørrelsen, " "tryk JA, eller tryk NEJ.\n" "\n" "I tilfælde du trykker JA, venligst vent..." #: gajim/history_manager.py:262 #, fuzzy msgid "Database Cleanup" msgstr "Database Fejl" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(who)s klokken %(time)s sagde: %(message)s\n" #: gajim/history_manager.py:577 #, fuzzy, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Vil du virkelig slette den valgte besked?" #: gajim/history_manager.py:581 #, fuzzy msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "Vil du virkelig slette loggen for den valgte kontakt?" #: gajim/history_manager.py:583 #, fuzzy msgid "This can not be undone." msgstr "Tjenesten findes ikke" #: gajim/history_manager.py:585 gajim/history_manager.py:624 #, fuzzy msgid "Deletion Confirmation" msgstr "Annuller bekræftelse" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Vil du virkelig slette den valgte besked?" msgstr[1] "Vil du virkelig slette de valgte beskeder?" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "Dette er en irreversibel handling." #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "Kontakt navn: %s" #: gajim/dialogs.py:84 #, fuzzy, python-format msgid "JID: %s" msgstr "Jabber ID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "General" #: gajim/dialogs.py:200 msgid "Group" msgstr "Gruppe" #: gajim/dialogs.py:207 msgid "In the group" msgstr "I gruppen" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "Nøgle ID" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Kontakt navn" #: gajim/dialogs.py:483 msgid "Set Mood" msgstr "Sæt Humørstemning" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "%s Status Besked" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Status Besked" #: gajim/dialogs.py:807 msgid "Overwrite Status Message?" msgstr "Overskriv Status Besked?" #: gajim/dialogs.py:808 msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "Dette navn er allerede i brug. Vil du overskrive denne status besked?" #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Gem som Forvalgt Status Besked" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Skriv et navn for denne status besked" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Abonnement Forespørgsel" #: gajim/dialogs.py:857 #, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Forespørgsel på abonnering for konto %(account)s fra %(jid)s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Forespørgsel om abonnering fra %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "Du er ikke tilsluttet til serveren" #: gajim/dialogs.py:928 msgid "Without a connection, you can not synchronise your contacts." msgstr "Du kan kun synkronisere dine kontakter når du er tilsluttet." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Navn" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Server" #: gajim/dialogs.py:978 msgid "This account is not connected to the server" msgstr "Denne konto er ikke tilsluttet til serveren" #: gajim/dialogs.py:979 msgid "You cannot synchronize with an account unless it is connected." msgstr "Du kan kun synkronisere med en konto hvis du er tilsluttet." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "Synkroniser" #: gajim/dialogs.py:1065 #, fuzzy msgid "add" msgstr "Trist" #: gajim/dialogs.py:1065 #, fuzzy msgid "modify" msgstr "Ændre" #: gajim/dialogs.py:1066 #, fuzzy msgid "remove" msgstr "_Fjern" #: gajim/dialogs.py:1095 #, fuzzy, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "" "%s vil gerne at du %s nogle kontakter i dit kontaktvindue." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 msgid "Add" msgstr "Tilføj" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 msgid "Modify" msgstr "Ændre" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Slet" #: gajim/dialogs.py:1125 msgid "Groups" msgstr "Grupper" #: gajim/dialogs.py:1233 #, python-format msgid "%s suggested me to add you in my roster." msgstr "%s foreslog mig at tilføje dig til min kontaktliste." #: gajim/dialogs.py:1247 #, fuzzy, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "Tilføj Kont_akt" msgstr[1] "Tilføj Kont_akt" #: gajim/dialogs.py:1285 #, fuzzy, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "Fjerner kontakt fra kontaktvinduet" msgstr[1] "Fjerner kontakt fra kontaktvinduet" #: gajim/dialogs.py:1305 msgid "You are invited to a groupchat" msgstr "Du er inviteret til en gruppesamtale." #: gajim/dialogs.py:1308 msgid "$Contact has invited you to join a discussion" msgstr "$Contact har inviteret dig til at deltage i en diskussion" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "" "$Contact har inviteret dig til at deltage i en gruppe samtale %(room_jid)s" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Kommentar: %s" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "Vil du acceptere denne invitation?" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Gruppesamtale Invitation" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "" #: gajim/dialogs.py:1628 msgid "a video" msgstr "" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 #, fuzzy msgid "File Transfer" msgstr "Filoverførsler" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "" #: gajim/dialogs.py:1764 #, fuzzy msgid "Encrypting file…" msgstr "E2E kryptering ikke aktiveret" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%(nick)s er nu kendt som %(new_nick)s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s er nu %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Sending af privat besked fejlede" #: gajim/groupchat_control.py:253 #, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "" "Du er ikke længere i gruppe samtale \"%(room)s\" eller \"%(nick)s\" har " "forladt rummet." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 #, fuzzy msgid "No File Transfer available" msgstr "Filoverførsler" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Ændre emne" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Anfør et nyt emne:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Ændre kælenavn" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Anfør dit nye kælenavn:" #: gajim/groupchat_control.py:711 #, fuzzy msgid "Invalid group chat JID" msgstr "Ugyldig gruppe samtale Jabber ID" #: gajim/groupchat_control.py:712 #, fuzzy msgid "The group chat JID has not allowed characters." msgstr "Gruppe samtale Jabber ID'en indeholder ikke tilladte tegn." #: gajim/groupchat_control.py:724 #, python-format msgid "Destroying %s" msgstr "Fjern %s" #: gajim/groupchat_control.py:725 #, fuzzy msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" "Du er ved at definitivt fjerne dette rum.\n" "Du kan anføre en grund herunder:" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "Du kan også indtaste et alternativt mødested:" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "Kunne ikke laste billede" #: gajim/groupchat_control.py:934 msgid "Insert Nickname" msgstr "Indsæt Kælenavn" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 msgid "and authenticated" msgstr "og godkendt" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 msgid "and NOT authenticated" msgstr "og IKKE godkendt" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, fuzzy, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" "%(type)s kryptering %(status)s aktiv %(authenticated)s.\n" "Din samtale session %(logged)s blive logget." #: gajim/groupchat_control.py:1157 msgid "Conversation with " msgstr "Samtale med " #: gajim/groupchat_control.py:1159 msgid "Continued conversation" msgstr "Fortsat samtale" #: gajim/groupchat_control.py:1525 #, fuzzy, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(jid)s har sat emnet til %(subject)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "En hvilken som helst deltager har lov til at se din fulde JID" #: gajim/groupchat_control.py:1556 #, fuzzy msgid "Room now shows unavailable members" msgstr "Rummet viser nu; ikke tilgængelige medlemmer" #: gajim/groupchat_control.py:1558 #, fuzzy msgid "Room now does not show unavailable members" msgstr "Rummet viser nu ikke; ikke tilgængelige medlemmer" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "Rum logging er nu aktiveret" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "Rum logging er nu deaktiveret" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "Rummet er nu ikke-anonymt" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "Rummet er nu semi-anonymt" #: gajim/groupchat_control.py:1576 #, fuzzy msgid "Room is now fully anonymous" msgstr "Rummet er nu helt anonymt" #: gajim/groupchat_control.py:1615 #, fuzzy, python-format msgid "Ping? (%s)" msgstr "Pong! (%s .s)" #: gajim/groupchat_control.py:1618 #, fuzzy, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "Pong! (%s .s)" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 msgid "Error." msgstr "Fejl." #: gajim/groupchat_control.py:1845 #, fuzzy, python-format msgid "You (%s) joined the room" msgstr "%s deltager nu i gruppe samtalen" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, fuzzy, python-format msgid "%(jid)s has been invited in this room" msgstr "%(nick)s er blevet fjernet fra rummet %(reason)s" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "Rum logging er aktiveret" #: gajim/groupchat_control.py:1879 msgid "A new room has been created" msgstr "Et nyt rum er blevet oprettet" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "Serveren har fastsat eller ændret dit kælenavn for rummet" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s er blevet udvist: %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(nick)s er blevet udvist af %(who)s: %(reason)s" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "%(nick)s er blevet uønsket: %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(nick)s er blevet uønsket af %(who)s: %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "Du er nu kendt som %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(nick)s er blevet fjernet fra rummet %(reason)s" #: gajim/groupchat_control.py:1950 msgid "affiliation changed" msgstr "tilknytning ændret" #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "Rum konfiguration er blevet ændret til 'kun for medlemmer'" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "computeren slukkes" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "" "** Tilhørsforholdet for %(nick)s er blevet sat til %(affiliation)s af " "%(actor)s" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "** Tilhørsforholdet for %(nick)s er blevet sat til %(affiliation)s" #: gajim/groupchat_control.py:2034 #, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "** %(nick)s rolle er blevet sat til %(role)s af %(actor)s" #: gajim/groupchat_control.py:2038 #, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "** %(nick)s rolle er blevet sat til %(role)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "%s har forladt samtalen" #: gajim/groupchat_control.py:2067 #, python-format msgid "%s has joined the group chat" msgstr "%s deltager nu i gruppe samtalen" #: gajim/groupchat_control.py:2374 #, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Er du sikker på du vil forlade gruppe samtalen \"%s\"?" #: gajim/groupchat_control.py:2376 msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "" "Hvis du lukker dette vindue vil du blive frakoblet fra denne gruppe samtale." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 #, fuzzy msgid "_Do not ask me again" msgstr "Ikke spørg mig ige_n" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Sparker %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Du kan anføre en begrundelse under:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Udeluk %s" #: gajim/chat_control.py:389 msgid "Show a list of formattings" msgstr "Hvis en liste over følelsesikoner" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 #, fuzzy msgid "This contact does not support HTML" msgstr "Denne kontakt understøtter ikke fil overførsler." #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "" #: gajim/chat_control.py:660 #, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s fra gruppesamtale %(room_name)s" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "Du har netop modtaget en besked fra \"%s\"" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Hvis du lukker dette faneblad og ikke har aktiveret historie loggen, vil du\n" "miste denne besked." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "Ping?" #: gajim/chat_control.py:1205 #, fuzzy, python-format msgid "Pong! (%s seconds)" msgstr "Pong! (%s .s)" #: gajim/chat_control.py:1313 #, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Emne: %(subject)s\n" "%(message)s" #: gajim/chat_control.py:1416 #, fuzzy, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(name)s er nu %(status)s" #: gajim/chat_control.py:1471 #, fuzzy msgid "File transfer" msgstr "Filoverførsler" #: gajim/chat_control.py:1474 #, fuzzy msgid "Size" msgstr "Størrelse: %s" #: gajim/chat_control.py:1476 #, fuzzy msgid "Accept" msgstr "K_ontoer" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Bliv med:" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 msgid "Remote contact stopped transfer" msgstr "Den fjerne kontakt stoppede filoverførslen" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 msgid "Error opening file" msgstr "Fejl ved åbning af fil" #: gajim/application.py:68 #, fuzzy msgid "Show the application's version" msgstr "Vis et faneblad når der kun er en samtale?" #: gajim/application.py:75 #, fuzzy msgid "Show only critical errors" msgstr "_Vis hændelse i kontaktvindue" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 #, fuzzy msgid "Use defined profile in configuration directory" msgstr "Avanceret Konfigurations Behandler" #: gajim/application.py:105 #, fuzzy msgid "Set configuration directory" msgstr "Rum Konfigurering" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 #, fuzzy msgid "Show all warnings" msgstr "Vis Alle Ventende Hænd_elser" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 msgid "Pops up a window with the next pending event" msgstr "Popper op et vindue ved næste hændelse" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 #, fuzzy msgid "Start a new chat" msgstr "Start Samtale" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "Database Fejl" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Flettede konti" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Transporter" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 msgid "Groupchats" msgstr "Gruppesamtaler" #: gajim/roster_window.py:2056 #, fuzzy msgid "Authorization sent" msgstr "Godkendelse er blevet sendt" #: gajim/roster_window.py:2057 #, fuzzy, python-format msgid "\"%s\" will now see your status." msgstr "Nu vil %s vide din status." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Forespørgsel på abonnering er blevet sendt" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "" "Hvis %s accepterer denne forespørsel vil du kunne se hans eller hendes " "status." #: gajim/roster_window.py:2095 #, fuzzy msgid "Authorization removed" msgstr "Godkendelse er blevet fjernet" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "Nu vil %s altid se dig som offline." #: gajim/roster_window.py:2120 #, fuzzy msgid "OpenPGP is not usable" msgstr "GPG er ikke brugbar" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Du deltager i en eller flere gruppesamtaler" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Hvis du ændrer din status til usynlig vil det resultere i at du bliver " "frakoblet fra disse gruppesamtaler. Er du sikker på du vil gøre dig usynlig?" #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "ikke synkroniseret" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "Skal Gajim afsluttes?" #: gajim/roster_window.py:2426 msgid "Are you sure you want to quit Gajim?" msgstr "Er du sikker på du vil afslutte Gajim?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "Altid afslut Gajim" #: gajim/roster_window.py:2514 #, fuzzy msgid "You have running file transfers" msgstr "Annuller filoverførsel" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Du har ulæste beskeder" #: gajim/roster_window.py:2547 msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "Beskeder vil kun være tilgængelige for læsning senere hvis du har historik " "aktiveret og kontakten er i dit kontaktvindue." #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "Du må læse dem før du fjerner denne transport." #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Transport \"%s\" vil blive fjernet" #: gajim/roster_window.py:2829 msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" "Du vil ikke længere være i stand til at sende og modtage beskeder fra " "kontakter som bruger denne transport." #: gajim/roster_window.py:2832 msgid "Transports will be removed" msgstr "Transporter vil blive fjernet" #: gajim/roster_window.py:2837 #, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" "Du vil ikke længere være i stand til at sende og modtage beskeder fra " "kontakter som bruger disse transporter: %s" #: gajim/roster_window.py:2891 msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "Du er ved at blokere en kontakt. Er du sikker på du vil fortsætte?" #: gajim/roster_window.py:2893 #, fuzzy msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" "Denne kontakt vil se dig offline og du vil ikke modtage beskeder han sender " "dig." #: gajim/roster_window.py:2939 msgid "Rename Contact" msgstr "Omdøb Kontakt" #: gajim/roster_window.py:2940 #, python-format msgid "Enter a new nickname for contact %s" msgstr "Indtast et nyt kælenavn for kontakt %s" #: gajim/roster_window.py:2947 msgid "Rename Group" msgstr "Omdøb Gruppe" #: gajim/roster_window.py:2948 #, python-format msgid "Enter a new name for group %s" msgstr "Indtast et nyt navn for gruppen %s" #: gajim/roster_window.py:2993 msgid "Remove Group" msgstr "Fjern Gruppen" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "Vil du fjerne gruppen %s fra kontaktvinduet?" #: gajim/roster_window.py:2995 msgid "Also remove all contacts in this group from your roster" msgstr "Fjern også alle kontakter i denne gruppe fra kontaktvinduet" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Tildel OpenPGP Nøgle" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "Vælg den nøgle du vil anvende til kontakten" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "Kontakt %s vil blive fjernet fra dit kontaktvindue" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "Du er ved at fjerne \"%(name)s\" (%(jid)s) fra dit kontaktvindue.\n" #: gajim/roster_window.py:3448 #, fuzzy msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "Ved at fjerne disse kontakter:%s\n" "fjerner du også godkendelsen, hvilket medfører at de altid vil se dig som " "offline." #: gajim/roster_window.py:3454 msgid "Do you want to continue?" msgstr "Vil du fortsætte?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "Ved at fjerne denne kontakt fjerner du også samtidig godkendelsen, så han " "eller hun altid vil se dig som offline." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Jeg vil at denne kontakt kan se min status efter den er blevet fjernet" #: gajim/roster_window.py:3465 msgid "Contacts will be removed from your roster" msgstr "Kontakter vil blive fjernet fra dit kontaktvindue" #: gajim/roster_window.py:3470 #, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "Ved at fjerne disse kontakter:%s\n" "fjerner du også godkendelsen, hvilket medfører at de altid vil se dig som " "offline." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "" "Du er ved at sende en personlig status. Er du sikker på du vil fortsætte?" #: gajim/roster_window.py:3531 #, fuzzy, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" "Denne kontakt vil midlertidig se dig som %(status)s, men kun indtil du " "ændrer din status. Da vil han se din globale status." #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Ingen konto tilgængelig" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "" "Du må oprette en konto før du kan begynde en samtale med andre kontakter." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "Metakontakt lagring er ikke understøttet af din server" #: gajim/roster_window.py:4180 #, fuzzy msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" "Din server understøtter ikke muligheden for at gemme metakontakt " "information. Så denne information vil ikke blive gemt til næste gang du " "tilslutter dig." #: gajim/roster_window.py:4276 msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "Du er ved at oprette en metakontakt. Er du sikker på du vil fortsætte?" #: gajim/roster_window.py:4278 #, fuzzy msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" "Metakontakter er en måde at gruppere flere kontakter på en linie. Oftest " "bruges det når den samme person har flere Jabber eller transport konti." #: gajim/roster_window.py:4400 msgid "Invalid file URI:" msgstr "Ugyldig Fil URI:" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Send _Fil" #: gajim/roster_window.py:4412 #, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "Vil du sende denne fil til %s:" msgstr[1] "Vil du sende disse filer til %s:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Send %s til %s" #: gajim/roster_window.py:4565 #, fuzzy, python-format msgid "Make %s first contact" msgstr "Lav %s og %s til metakontakter" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Lav %s og %s til metakontakter" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "_Ændre Status Besked" #: gajim/roster_window.py:4965 msgid "Publish Tune" msgstr "Publicer Melodi" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "Publicer Melodi" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "Tilpas Tjenester..." #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "_Maksimer alt" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 msgid "Send Group M_essage" msgstr "Send Gruppeb_esked" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "Til alle brugere" #: gajim/roster_window.py:5135 msgid "To all online users" msgstr "Til alle brugere på net" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "In_viter til" #: gajim/roster_window.py:5299 msgid "_Manage Contacts" msgstr "_Håndter Kontakter" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Ændre _Grupper" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "_Kan fjernes" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "_Maksimer" #: gajim/roster_window.py:5370 msgid "_Reconnect" msgstr "_Tilslut igen" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 msgid "_Disconnect" msgstr "Afbry_d tilslutningen" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Historie" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Historik Håndterer" #: gajim/roster_window.py:5475 msgid "_Join New Group Chat" msgstr "_Deltag i Ny Gruppe Samtale" #: gajim/config.py:359 msgid "Ban List" msgstr "Liste over bandlyste" #: gajim/config.py:360 msgid "Member List" msgstr "Medlems Liste" #: gajim/config.py:360 msgid "Owner List" msgstr "Ejer Liste" #: gajim/config.py:361 msgid "Administrator List" msgstr "Administrator Liste" #: gajim/config.py:435 msgid "Reason" msgstr "Grund" #: gajim/config.py:442 msgid "Nick" msgstr "Kælenavne" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "Rolle" #: gajim/config.py:478 #, fuzzy msgid "Banning…" msgstr "Bandlysning..." #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Hvem vil du bandlyse?\n" "\n" #: gajim/config.py:482 #, fuzzy msgid "Adding Member…" msgstr "Tilføj Medlem..." #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" "Hvem vil du gøre til medlem?\n" "\n" #: gajim/config.py:485 #, fuzzy msgid "Adding Owner…" msgstr "Tilføj Ejer..." #: gajim/config.py:486 msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "" "Hvem vil du gøre til ejer?\n" "\n" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "Tilføj Administrator..." #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" "Hvem vil du gøre til administrator?\n" "\n" #: gajim/config.py:490 msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" "Kan være en af de følgende:\n" "1. bruger@domæne/resource (kun denne resource træffer).\n" "2. bruger@domæne (en hvilket som helst resource træffer).\n" "3. domæne/resource (kun denne resource træffer).\n" "4. domæne (domænet træffer, ligeledes et hvilken som helst bruger@domæne,\n" "domæne/resource, eller adresse indeholdende et subdomæne." #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Fjerne kontoen med navnet %s" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Følelsesikoner er ikke aktiveret" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Adgangskode er Påkrævet" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Skriv din adgangskode for kontoen %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Gem adgangskode" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Kontoen \"%s\" er tilsluttet til serveren" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Hvis du fjerne den vil tilslutningen tabes." #: gajim/config.py:652 #, fuzzy, python-format msgid "Connection to server %s failed" msgstr "Tilslutning til proxy fejlede" #: gajim/config.py:653 #, fuzzy msgid "What would you like to do?" msgstr "Hvad vil du gøre?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Fjern kun k_ontoen fra Gajim" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Wav Lyde" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "Første Besked er Modtaget" #: gajim/config.py:746 msgid "First Message Received" msgstr "Første Besked er Modtaget" #: gajim/config.py:747 msgid "Next Message Received Focused" msgstr "Næste Besked Modtages i Fokus" #: gajim/config.py:748 msgid "Next Message Received Unfocused" msgstr "Næste Besked Modtages uden Fokus" #: gajim/config.py:749 msgid "Contact Connected" msgstr "Kontakt er Tilsluttet" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "Kontakt er ikke Tilsluttet" #: gajim/config.py:751 msgid "Message Sent" msgstr "Besked er Sendt" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "Gruppe Samtale Besked Fremhævning" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "Gruppe Samtale Besked Modtaget" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "%(owner_or_admin_or_member)s af denne gruppe samtale" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 msgid "?Group Chat Contact Affiliation:None" msgstr "?Group Chat Contact Affiliation:Ingen" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 msgid "Member" msgstr "Medlem" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 msgid "Administrator" msgstr "Administrator" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 msgid "Owner" msgstr "Ejer" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr " [blokeret]" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr " [minimeret]" #: gajim/tooltips.py:574 msgid "Connected" msgstr "Tilsluttet" #: gajim/tooltips.py:576 msgid "Disconnected" msgstr "Tilslutning afbrudt" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Hent" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Send" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Type: " #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Overført: " #: gajim/tooltips.py:645 msgid "Status: " msgstr "Status: " #: gajim/tooltips.py:647 msgid "Description: " msgstr "Beskrivelse: " #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Fuldført" #: gajim/tooltips.py:676 msgid "?transfer status:Paused" msgstr "?transfer status:Midlertidig stoppet" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "Hænger" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "Overfører" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "Ikke startet" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "?transfer status:Midlertidig stoppet" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Tilgængelig for samtale" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Borte" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Travlt" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Ikke Tilgængelig" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Afkoblet" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "_Ændre Status Besked" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "med konto %s" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Håndter Bogmærker" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "i _kontaktvinduet" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "Vis _Kontaktvindue" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Skjul denne menu" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Ikke i stand til at indlæse tomgangs modulet" #: gajim/dataforms_widget.py:586 #, fuzzy, python-format msgid "Media type not supported: %s" msgstr "Usynlighed er ikke understøttet" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "ny@jabber.id" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "ny%d@jabber.id" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "Denne tjeneste har endnu ikke svaret med detaljeret information" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "Denne tjeneste kunne ikke svare med detaljeret information.\n" "Den er højst sandsynlig ikke fungerende" #: gajim/disco.py:121 msgid "Others" msgstr "Andre" #: gajim/disco.py:125 msgid "Conference" msgstr "Konference" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "Du kan kun gennemse tilgængelige tjenester hvis du er tilsluttet" #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "Opdag Tjenester med kontoen %s" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Opdag Tjenester" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "Tjenesten findes ikke" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "Der er ikke nogen tjenester på den adresse som du indtastede, eller serveren " "gav intet svar. Kontroller adressen og prøv igen." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "Det er ikke mulig at gennemse denne tjeneste" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "Denne type tjeneste har ingen elementer som kan gennemses." #: gajim/disco.py:726 gajim/disco.py:736 msgid "Invalid Server Name" msgstr "Ikke gyldigt server navn" #: gajim/disco.py:794 #, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "Gennemse %(address)s med konto %(account)s" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Gennemse" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "Denne tjeneste har ingen elementer som kan gennemses." #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "_Kør Kommando" #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "Re_gistrer" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "_Bliv med:" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "Søg" #: gajim/disco.py:1407 msgid "_Edit" msgstr "R_ediger" #: gajim/disco.py:1450 #, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "Skanner %(current)d / %(total)d.." #: gajim/disco.py:1649 msgid "Users" msgstr "Brugere" #: gajim/disco.py:1657 msgid "Description" msgstr "Beskrivelse" #: gajim/disco.py:1665 msgid "Id" msgstr "Id" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 msgid "_Bookmark" msgstr "_Bogmærke" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Bogmærke er allerede sat" #: gajim/disco.py:1722 #, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "Gruppe samtale \"%s\" er allerede i dine bogmærker." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Bogmærket er blevet tilføjet succesfuldt" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "" "De kan håndtere dine bogmærker via Handlings menuen i dit kontaktvindue." #: gajim/disco.py:1929 msgid "Subscribed" msgstr "Abonnerede" #: gajim/disco.py:1938 msgid "Node" msgstr "Knude" #: gajim/disco.py:2005 msgid "New post" msgstr "Ny post" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "_Abonner" #: gajim/disco.py:2017 msgid "_Unsubscribe" msgstr "_Frameld abonnement" #: gajim/conversation_textview.py:320 msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" "Teksten under denne linje er hvad der er blevet sagt siden\n" "sidste gang du var opmærksom på denne gruppe samtale" #: gajim/conversation_textview.py:541 msgid "_Quote" msgstr "_Citat" #: gajim/conversation_textview.py:549 #, python-format msgid "_Actions for \"%s\"" msgstr "_Handlinger for \"%s\"" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Læs _Wikipedia Artikel" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Slå dette op i Or_dbogen" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "Ordbogens URL mangler en \"%s\" og det må ikke være WIKTIONARY" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "Web søge URL'en mangler en \"%s\"" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "Søg på nettet efter det" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "Åbn som et _Link" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "Ugyldig JID" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, fuzzy, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "I går" msgstr[1] "I går" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Ikke startet" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Emne: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Ny Privat Besked" #: gajim/message_window.py:243 msgid "You are going to close several tabs" msgstr "Du er ved at lukke flere faneblade" #: gajim/message_window.py:244 msgid "Do you really want to close them all?" msgstr "Vil du virkelig lukke dem alle?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Gruppe Samtaler" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "Private Samtaler" #: gajim/message_window.py:530 msgid "Messages" msgstr "Beskeder" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 msgid "Unable to join group chat" msgstr "Ikke i stand til at deltage i gruppesamtale." #: gajim/gui_interface.py:170 #, fuzzy, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "Dit ønskede kælenavn i gruppesamtalen %s er i brug eller registreret af en " "anden indehaver.\n" "Specificer venligst et andet kælenavn under:" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Accepterer du denne forespørsel?" #: gajim/gui_interface.py:194 #, python-format msgid "Do you accept this request on account %s?" msgstr "Accepterer du denne forespørgsel for konto %s?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "HTTP (%(method)s) Autorisering for %(url)s (id: %(id)s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 msgid "Connection Failed" msgstr "Tilslutning Fejlede" #: gajim/gui_interface.py:327 #, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "" "En adgangskode er påkrævet for at deltage i rummet %s. Venligst skriv den." #: gajim/gui_interface.py:342 #, fuzzy, python-format msgid "%s is full" msgstr "Skrifttype" #: gajim/gui_interface.py:351 #, fuzzy, python-format msgid "You are banned from group chat %s." msgstr "Du er bandlyst fra gruppesamtalen %s." #: gajim/gui_interface.py:358 #, fuzzy, python-format msgid "Remote server %s does not exist." msgstr "Gruppesamtalen %s eksisterer ikke." #: gajim/gui_interface.py:362 #, fuzzy, python-format msgid "Group chat %s does not exist." msgstr "Gruppesamtalen %s eksisterer ikke." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "Gruppesamtale oprettelse er begrænset." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Ikke i stand til at deltage i gruppesamtale." #: gajim/gui_interface.py:368 #, fuzzy, python-format msgid "You must use your registered nickname in %s." msgstr "Dit registrerede kælenavn skal bruges i gruppesamtalen %s." #: gajim/gui_interface.py:373 #, python-format msgid "You are not in the members list in groupchat %s." msgstr "Du er ikke i medlemslisten for gruppesamtalen %s." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, python-format msgid "Error %(code)s: %(msg)s" msgstr "Fejl %(code)s: %(msg)s" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "fejl opstod under sending %(message)s ( %(error)s )" #: gajim/gui_interface.py:503 gajim/notify.py:194 msgid "Subscription request" msgstr "Abonnement forespørgsel" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "Iagttagere" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Autorisering accepteret" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "Kontakten \"%s\" har godkendt dig til at se hans eller hendes status." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Kontakt \"%s\" har fjernet abonneringen på dig" #: gajim/gui_interface.py:539 #, fuzzy msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" "Du vil altid se ham eller hende som offline.\n" "Vil du fjerne ham eller hende fra din kontakt liste?" #: gajim/gui_interface.py:560 gajim/notify.py:194 msgid "Unsubscribed" msgstr "Frameldt abonnement" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, fuzzy, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Du er inviteret til en gruppesamtale." #: gajim/gui_interface.py:658 #, fuzzy msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" "Du har konfigureret Gajim til at bruge GPG agenten, men der er ingen GPG " "agent som kører eller den returnerede en forkert gpg-løsen.\n" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "Du er for øjeblikket tilsluttet uden din OpenPGP nøgle." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Forkert Adgangskode" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Forkert Adgangskode" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "Certifikatet er udløbet" #: gajim/gui_interface.py:683 #, fuzzy, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Indtast adgangskoden til GPG nøglen %(keyid)s (Konto %(account)s)." #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Vælg din OpenPGP Nøgle" #: gajim/gui_interface.py:706 #, fuzzy msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" "GPG nøglen brugt til at kryptere den samtale er ikke til at stole på. Vil du " "virkelig kryptere den besked?" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Filoverførsel Fejl" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "%s vil gerne sende dig en fil." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Filoverførsel Forespørgsel" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "SSL certifikat fejl" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Filoverførsel er Fuldført" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Filoverførsel Stoppede" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Filoverførsler" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Filoverførsel af %(filename)s fra %(name)s er stoppet." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Filoverførsel af %(filename)s fra %(name)s er stoppet." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Filoverførsel af %(filename)s fra %(name)s er stoppet." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Du har succesfuldt sendt %(filename)s til %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Filoverførsel af %(filename)s til %(name)s er stoppet." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Filoverførsel af %(filename)s til %(name)s er stoppet." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "Brugernavns Konflikt" #: gajim/gui_interface.py:1178 msgid "Please type a new username for your local account" msgstr "Skriv et nyt brugernavn for din lokale konto" #: gajim/gui_interface.py:1201 msgid "Resource Conflict" msgstr "Ressource Konflikt" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "" "Du er allerede tilsluttet til denne konto med den samme ressource. Skriv " "venligst en ny" #: gajim/gui_interface.py:1259 #, fuzzy, python-format msgid "%s wants to start a voice chat." msgstr "%s vil gerne sende dig en fil." #: gajim/gui_interface.py:1261 #, fuzzy msgid "Voice Chat Request" msgstr "Filoverførsel Forespørgsel" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 msgid "Certificate Already in File" msgstr "Certifikatet er allerede i filen" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" "Dette certifikat er allerede i filen %s, så det bliver ikke tilføjet igen." #: gajim/gui_interface.py:1351 #, fuzzy, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "Ægtheden af %s certifikatet kan være ugyldig." #: gajim/gui_interface.py:1354 #, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "" "\n" "Ukendt SSL fejl: %d" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" "\n" "SSL Fejl: %s" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "Fejl under verificering af SSL certifikat" #: gajim/gui_interface.py:1362 #, fuzzy, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" "Der var en fejl under verificeringen af SSL certifikatet fra din jabber " "server: %(error)s\n" "Vil du stadig prøve på at forbinde til denne server?" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, fuzzy, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" "Tilføj dette certifikat til listen af certifikater du har tillid til.\n" "Certifikatets SHA1 fingeraftryk:\n" "%s" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "Ignorer denne fejl for dette certifikat." #: gajim/gui_interface.py:1380 #, fuzzy, python-format msgid "SSL Certificate Verification for %s" msgstr "SSL certifikat fejl" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 msgid "Insecure connection" msgstr "Ikke sikker forbindelse" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" "Du er ved at sende din adgangskode på en usikker forbindelse. Du bør " "installere PyOpenSSL for at forhindre dette. Er du sikker på du vil gøre " "dette?" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "Ja, jeg vil virkelig gerne tilslutte mig uden sikkerhed" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "" "Du er ved at sende din adgangskode over en ikke krypteret forbindelse. Er du " "sikker på du vil gøre dette?" #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "Du kan kun deltage i en gruppe samtale hvis du er tilsluttet." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Dette er ikke en gruppe samtale" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "Dette er ikke en gruppe samtale" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 msgid "You cannot join a group chat while you are invisible" msgstr "Du kan ikke deltage i en gruppe samtale mens du er usynlig" #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Kunne ikke gemme din opsætning og indstillinger" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Adgangskode Påkrævet" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "Indtast adgangskoden til GPG nøglen %(keyid)s (Konto %(account)s)." #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "GPG nøgle er udløbet" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "Din GPG nøgle er udløbet, du vil blive tilsuttet til %s uden OpenPGP." #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "Forkert Adgangskode" #: gajim/gui_interface.py:2853 #, fuzzy msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "Indtast din GPG adgangskode igen eller annuller." #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "Venter på resultater" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "Fejl i modtaget dataform" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "Intet resultat" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "Koder" #: gajim/atom_window.py:123 #, fuzzy, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "Du har modtaget en nye hændelser (og %(count)d er ikke vist):" msgstr[1] "Du har modtaget en nye hændelser (og %(count)d er ikke vist):" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "Du har modtaget en ny hændelse:" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "Ad-hoc Kommandoer - Gajim" #: gajim/adhoc_commands.py:326 msgid "Cancel confirmation" msgstr "Annuller bekræftelse" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "" "Du er i færd med at køre en kommando. Er du sikker på du vil afbryde den?" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "Tjeneste sendte malformeret data" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "Tjeneste ændrede sessionsnøglen." #: gajim/adhoc_commands.py:422 #, fuzzy, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "Ad-hoc Kommandoer - Gajim" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "Tjeneste returnerede en fejl." #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Kontakt Loggede Ind" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Kontakt Loggede Ud" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Ny Besked" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Ny Enkel Besked" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Ny Privat Besked" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 msgid "Contact Changed Status" msgstr "Kontakt Ændrede Status" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenPGP: " #: gajim/notify.py:270 msgid "New E-mail" msgstr "Ny E-post" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "Du kan kun deltage i en gruppe samtale hvis du er tilsluttet." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 msgid "Invalid JID" msgstr "Ugyldig JID" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "Det er ikke mulig at sende en besked til %s, denne JID er ikke gyldig." #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "Ulæste hændelser" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "Læs alle ventende hændelser før denne konto fjernes." #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "Du er for øjeblikket tilsluttet til serveren" #: gajim/dialog_messages.py:53 msgid "To disable the account, you must be disconnected." msgstr "For at deaktivere din konto må du afbryde din tilslutning." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Ugyldig rum" #: gajim/dialog_messages.py:58 #, fuzzy msgid "The form is not filled correctly." msgstr "Kælenavnet har ikke tilladte tegn." #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Usynlig" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "En tilslutning er ikke tilgængelig" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "Din besked kan ikke blive sendt før du er tilsluttet." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "Jabber ID er allerede i listen" #: gajim/dialog_messages.py:73 #, fuzzy msgid "The JID you entered is already in the list. Choose another one." msgstr "Den Jabber ID som de skrev er allerede i listen. Vælg en anden." #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "Forkert svar" #: gajim/dialog_messages.py:78 #, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "" "Transport %(name)s svarede forkert på indskrivnings forespørgslen: %(error)s" #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Brug tilpasset værtsnavn/port" #: gajim/dialog_messages.py:84 #, fuzzy, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Brug tilpasset værtsnavn/port" #: gajim/dialog_messages.py:88 msgid "Error while removing privacy list" msgstr "Fejl under fjernelse af privatlivs liste" #: gajim/dialog_messages.py:89 #, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" "Privatlivs liste %s er ikke blevet fjernet. Den er måske aktiv i en af dine " "tilsluttede ressourcer. Deaktivér den og prøv igen." #: gajim/dialog_messages.py:95 msgid "Invisibility not supported" msgstr "Usynlighed er ikke understøttet" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "Konto %s understøtter ikke usynlighed." #: gajim/dialog_messages.py:100 msgid "Unregister failed" msgstr "Tilslutning fejlede" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "Frakobling fra serveren %(server)s mislykkedes: %(error)s" #: gajim/dialog_messages.py:105 msgid "Registration succeeded" msgstr "Tilslutning lykkedes" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "Tilslutning med agenten %s lykkedes" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 msgid "Registration failed" msgstr "Tilslutning fejlede" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" "Tilslutning med agenten %(agent)s mislykkedes med fejlen %(error)s: " "%(error_msg)s" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Ikke i stand til at deltage i gruppesamtale." #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, fuzzy, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "Fejl besked: %s" #: gajim/dialog_messages.py:126 msgid "Wrong host" msgstr "Forkert vært" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "Invalid local address? :-O" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "Avahi fejl" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" "%s\n" "Link-local beskeder vil sandsynligvis ikke virke ordentligt." #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 #, fuzzy msgid "Could not request upload slot" msgstr "Kunne ikke starte lokal tjeneste" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 #, fuzzy msgid "Could not open file" msgstr "Kunne ikke laste billede" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 #, fuzzy msgid "Server returned unsecure transport (HTTP)" msgstr "Tjeneste returnerede en fejl." #: gajim/dialog_messages.py:161 #, fuzzy msgid "Could not upload file" msgstr "Kunne ikke laste billede" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 msgid "Encryption Error" msgstr "" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "En tilslutning er ikke tilgængelig" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "vCard publicering fejlede" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "" "D-Bus er ikke tilgængelig på denne maskine eller et python modul mangler" #: gajim/gajim_remote.py:77 msgid "Shows a help on specific command" msgstr "Viser hjælp for en specifik kommando" #: gajim/gajim_remote.py:80 msgid "command" msgstr "Kommando" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "Vis hjælp for kommando" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "Udskriver en liste af alle kontakter i kontaktvinduet. Hver kontakt placeres " "på en separat linie" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "Konto" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "viser kun kontakter for den givne konto" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "Udskriver en liste af registrerede konti" #: gajim/gajim_remote.py:97 msgid "Changes the status of account(s)" msgstr "Ændrer status for kontoen eller konti" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "status" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "en af: offline, online, chat, away, xa, dnd, invisible" #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "besked" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "status besked" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "Ændre status for konto \"konto\". Hvis ikke specificeret, prøv at ændre " "status for alle konti der har sat \"synkroniser med generel status\" " "indstillingen" #: gajim/gajim_remote.py:108 msgid "Changes the priority of account(s)" msgstr "Ændrer prioriteringen for kontoen eller konti" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "prioritet" #: gajim/gajim_remote.py:110 msgid "priority you want to give to the account" msgstr "prioriteten du vil give til kontoen" #: gajim/gajim_remote.py:112 msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "ændre prioritet for en given konto. Hvis ikke specificeret, ændrer status " "for alle konti der har sat \"synkroniser med generel status\" indstillingen" #: gajim/gajim_remote.py:118 msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Sender en ny besked til en kontakt i kontaktvinduet. Både OpenPGP nøgle og " "konto er valgfri. Hvis du ønsker at sætte en 'konto' uden 'OpenPGP nøgle', " "bare set 'OpenPGP nøgle' til ''." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID på den kontakt som skal modtage beskeden" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "besked indhold" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "hvis specificeret vil beskeden blive krypteret med denne nøgle" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "hvis specificeret vil beskeden blive sendt med denne konto" #: gajim/gajim_remote.py:131 #, fuzzy msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Sender en ny besked til en kontakt i kontaktvinduet. Både OpenPGP nøgle og " "konto er valgfri. Hvis du ønsker at sætte en 'konto' uden 'OpenPGP nøgle', " "bare set 'OpenPGP nøgle' til ''." #: gajim/gajim_remote.py:136 msgid "subject" msgstr "emne" #: gajim/gajim_remote.py:136 msgid "message subject" msgstr "emne på besked" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "Send en ny besked til en gruppesamtale du deltager i." #: gajim/gajim_remote.py:147 msgid "JID of the room that will receive the message" msgstr "JID på den rum som skal modtage beskeden" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Få detaljeret information om kontakten" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "Kontaktens JID" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "Få detaljeret information om kontoen" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "Navn på kontoen" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Send en fil til en kontakt" #: gajim/gajim_remote.py:168 msgid "file" msgstr "fil" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Filsti" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "hvis specificeret vil filen blive sendt med denne konto" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Hvis alle indstillinger og deres værdier" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "Sætter værdien for 'nøglen' til 'værdi'." #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "nøgle=værdi" #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "" "'nøgle' er navnet for indstillingen, 'værdi' er den værdi den er sat til" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "Sletter et indstillingspunkt" #: gajim/gajim_remote.py:188 msgid "key" msgstr "nøgle" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "navn på den indstilling som skal slettes" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "" "Skriver den nuværende tilstand af Gajims indstillinger til .config filen" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Fjerner kontakt fra kontaktvinduet" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "" "hvis specificeret vil kontakten tages fra kontaktlisten fra denne konto" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "" "Returnere den nuværende status (den globale status hvis ikke en konto er " "valgt)" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" "Returnere den nuværende statusbesked (den globale status besked hvis ikke en " "konto er valgt)" #: gajim/gajim_remote.py:221 msgid "Returns number of unread messages" msgstr "Returnerer antal ikke læste beskeder" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "Sender tilpasset XML" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "XML som skal sendes" #: gajim/gajim_remote.py:229 msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" "Den konto hvor XML vil blive sendt; hvis ikke den er specificeret, vil XML " "blive sendt til alle konti" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Ændre status" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "Kælenavn som skal bruges" #: gajim/gajim_remote.py:238 msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" "Den konto hvor XML vil blive sendt; hvis ikke den er specificeret, vil XML " "blive sendt til alle konti" #: gajim/gajim_remote.py:245 msgid "Check if Gajim is running" msgstr "Kontroller om Gajim kører" #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "Manglende argument \"contact_jid\"" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "'%s' er ikke i dit kontaktvindue.\n" "Specificer venligst en konto for at sende beskeden." #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "Du har ingen aktiv konto" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "Det ser ud til at Gajim ikke kører. Så du kan ikke bruge gajim-remote." #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" "Brug: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Argumenter:" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "%s ikke fundet" #: gajim/gajim_remote.py:383 #, fuzzy, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Brug: %s kommando [argumenter]\n" "Kommando er en af:\n" #: gajim/gajim_remote.py:453 #, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "For mange argumenter. \n" "Skriv \"%(basename)s help %(command)s\" for mere information" #: gajim/gajim_remote.py:458 #, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Argument \"%(arg)s\" er ikke specificeret. \n" "Skriv \"%(basename)s help %(command)s\" for mere information" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "tolv" #: gajim/common/fuzzyclock.py:36 msgid "one" msgstr "en" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "to" #: gajim/common/fuzzyclock.py:36 msgid "three" msgstr "tre" #: gajim/common/fuzzyclock.py:36 msgid "four" msgstr "fire" #: gajim/common/fuzzyclock.py:37 msgid "five" msgstr "fem" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "seks" #: gajim/common/fuzzyclock.py:37 msgid "seven" msgstr "syv" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "otte" #: gajim/common/fuzzyclock.py:37 msgid "nine" msgstr "ni" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "ti" #: gajim/common/fuzzyclock.py:38 msgid "eleven" msgstr "elleve" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "klokken %(0)s" #: gajim/common/fuzzyclock.py:46 #, python-format msgid "five past %(0)s" msgstr "fem over %(0)s" #: gajim/common/fuzzyclock.py:47 #, python-format msgid "ten past %(0)s" msgstr "ti over %(0)s" #: gajim/common/fuzzyclock.py:48 #, python-format msgid "quarter past %(0)s" msgstr "kvart over %(0)s" #: gajim/common/fuzzyclock.py:49 #, python-format msgid "twenty past %(0)s" msgstr "tyve over %(0)s" #: gajim/common/fuzzyclock.py:50 #, python-format msgid "twenty five past %(0)s" msgstr "femogtyve over %(0)s" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "halv %(1)s" #: gajim/common/fuzzyclock.py:52 #, python-format msgid "twenty five to %(1)s" msgstr "femogtyve minutter i %(1)s" #: gajim/common/fuzzyclock.py:53 #, python-format msgid "twenty to %(1)s" msgstr "tyve minutter i %(1)s" #: gajim/common/fuzzyclock.py:54 #, python-format msgid "quarter to %(1)s" msgstr "kvart på %(1)s" #: gajim/common/fuzzyclock.py:55 #, python-format msgid "ten to %(1)s" msgstr "ti på %(1)s" #: gajim/common/fuzzyclock.py:56 #, python-format msgid "five to %(1)s" msgstr "fem på %(1)s" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "klokken %(1)s" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "Nat" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "Tidlig morgen" #: gajim/common/fuzzyclock.py:63 msgid "Morning" msgstr "Morgen" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "Næsten middag" #: gajim/common/fuzzyclock.py:65 msgid "Noon" msgstr "Middag" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "Eftermiddag" #: gajim/common/fuzzyclock.py:67 msgid "Evening" msgstr "Aften" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "Sen aften" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "Ugestart" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "Midten af ugen" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "Slutten af ugen" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "Weekend!" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, python-format msgid "%s is a directory but should be a file" msgstr "%s er et katalog men burde være en fil" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Fjern %s" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 msgid "Room has been destroyed" msgstr "Rummet er blevet ødelagt" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "Du kan deltage i dette rum i stedet: %s" #: gajim/common/connection_handlers_events.py:598 #, python-format msgid "Unknown SSL error: %d" msgstr "Ukendt SSL fejl: %d" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Ny Besked fra %(nickname)s" msgstr[1] "Ny Besked fra %(nickname)s" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s Ændrede Status" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s Loggede Ind" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "%(nickname)s Loggede Ud" #: gajim/common/contacts.py:427 msgid "Not in roster" msgstr "Ikke i kontaktvindue" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "Spil en lyd når brugeren er optaget" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "" "Vis kun brugere på net og brugere klar for en samtale i kontaktvinduet." #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "Tid i minutter før din status ændres til borte." #: gajim/common/config.py:87 msgid "$S (Away as a result of being idle more than $T min)" msgstr "$S (Væk som et resultat af at være inaktiv i mere end $T minutter)" #: gajim/common/config.py:87 #, fuzzy msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" "$S vil blive ombyttet med den nuværende status besked, $T ved automatisk væk " "tid." #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "Tid i minutter før din status ændres til ikke tilgængelig." #: gajim/common/config.py:90 msgid "$S (Not available as a result of being idle more than $T min)" msgstr "" "$S (Ikke tilgængelig som et resultat af at være inaktiv i mere end $T " "minutter)" #: gajim/common/config.py:90 #, fuzzy msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" "$S vil blive erstattet med den nuværende status besked, $T ved ikke " "tilgængelig tid." #: gajim/common/config.py:93 #, fuzzy msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" "Når skal systembakke ikonet vises? Kan være 'never', 'on_event', 'always'." #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "_Vis hændelse i kontaktvindue" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "_Vis hændelse i kontaktvindue" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "Forhåndsvis nye beskeder i et påmindelses pop op vinduer?" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Filoverførsel Forespørgsel" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Filoverførsel er afbrudt" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "Når en filoverførsel er færdig, vis en pop op påmindelse" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "Gruppesamtale Invitation" #: gajim/common/config.py:106 #, fuzzy msgid "Background color of status changed notification" msgstr "Baggrundsfarve på kontakter når de netop har tilsluttet sig." #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "" "Liste (separeret med mellemrum) af rækker (konti og grupper) som er " "kollapset." #: gajim/common/config.py:109 msgid "default" msgstr "standard" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "Sprog brugt af stavelseskontrollen" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" "'altid' - skriv tid for hver besked.\n" "'nogen ganger' - skriv tid for hver print_ichat_every_foo_minutes minutter.\n" "'aldrig' - skriv aldrig tiden." #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" "Print tiden i samtaler med en upræcis klokke. Værdien for hvor upræcis " "klokken skal være kan rangere fra 1 til 4, eller 0 for at deaktivere den " "upræcise klokke. 1 er den mest præcise klokke, 4 den mindst præcise. Dette " "bruges kun hvis print_time er 'nogen ganger'." #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "Behandle * / _ par som mulige formaterings tegn." #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "Hvis sandt, ikke fjern */_. Således at *abc* bliver skrevet med fed skrift " "men * * bliver ikke fjernet." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" "Bruger ReStruktureret tekst redigering til at sende HTML, plus ascii " "formatering hvis valgt. For syntaks, se http://docutils.sourceforge.net/docs/" "ref/rst/restructuredtext.html (Hvis du vil bruge dette, installer docutils)" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" "Tegn som tilføjes efter kælenavn når der bruges kælenavnsfuldførelse (tab) i " "en gruppesamtale." #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" "Tegnforslag til at tilføje efter det ønskede kælenavn, når det ønskede " "kælenavn er i brug af en anden i gruppesamtalen." #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" "Denne valgmulighed giver dig muligheden for at tilpasse hvordan " "klokkeslettet bliver skrevet i en samtale. For eksempel [%H:%M] vil vise " "[timer:minutter]. Se python dokumentationen for strftime: http://docs.python." "org/lib/module-time.html" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "Tegn som bliver skrevet før kælenavnet i samtaler" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "Tegn som bliver skrevet efter kælenavnet i samtaler" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Tilføj * og [n] i tittelen på kontaktvinduet?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Hvor mange linjer skal huskes fra forrige samtale når et samtale vindue/" "faneblad genåbnes." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 #, fuzzy msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" "Hvor mange linjer skal hentes fra serveren når man deltager i en " "gruppesamtale." #: gajim/common/config.py:177 #, fuzzy msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" "Hvor mange minutter tilbage skal der hentes log fra når man deltager i en " "gruppesamtale." #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" "Hvor mange sekunder skal der ventes før der prøves at oprette en ny " "forbindelse til en konference som du er blevet afbrudt fra. Sæt værdien til " "0 for at forhindre at der prøves at oprette ny forbindelse." #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" "Send besked med Ctrl+Enter og lave en ny linie med Enter (standard Mirabilis " "ICQ klient adfærd)." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Hvor mange linjer skal gemmes for Ctrl+KeyUP." #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Enten en tilpasset url som indeholder %s hvor %s er ordet/frasen, eller " "'WIKTIONARY' som betyder brug wiktionary." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "" "Hvis valgt kan Gajim blive kontrolleret eksternt ved hjælp af gajim-remote." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" "Send samtale status påmindelser. Kan være en af disse: all, composing_only, " "disabled." #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" "Vis samtale status påmindelser i samtale vinduer. Kan være en af disse: all, " "composing_only, disabled." #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" "Når der ikke skrives tid for hver besked (print_time==sometimes), skriv " "tiden for hver x minutter." #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Spørg før et gruppesamtale vindue/faneblad lukkes." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" "Altid spørg før et gruppesamtale vindue/faneblad lukkes, hvis den findes i " "denne mellemrums separerede liste af gruppesamtale jids." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" "Aldrig spørg før et gruppesamtale vindue/faneblad lukkes, hvis den findes i " "denne mellemrums separerede liste af gruppesamtale jids." #: gajim/common/config.py:196 #, fuzzy msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" "Spørg før et faneblad i samtale vinduet lukkes hvis der kan mistes dat " "(samtale, privat samtale, gruppe samtale som ikke vil minimere)" #: gajim/common/config.py:199 #, fuzzy msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" "Komma separeret liste af værter som vi sender, i tillæg til lokale " "grænseflader, for filoverførsler i tilfælde af adresse omskrivning/port " "videresending." #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "IEC standard siger KiB = 1024 byte, KB = 1000 byte." #: gajim/common/config.py:202 #, fuzzy msgid "Notify of events in the notification area." msgstr "Vis påmindelse af hændelser i statusfelt ikonet." #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Vis et faneblad når der kun er en samtale?" #: gajim/common/config.py:210 msgid "Show tabbed notebook border in chat windows?" msgstr "Vis faneblade i samtalevinduer?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Vis lukke knap i faneblad?" #: gajim/common/config.py:224 msgid "Preview new messages in notification popup?" msgstr "Forhåndsvis nye beskeder i et påmindelses pop op vinduer?" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" "En semikolon-separeret liste af ord som vil blive fremhævet i gruppesamtaler." #: gajim/common/config.py:228 #, fuzzy msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" "Hvis Sandt, lukker Gajim når X knappen fra vindueshåndteringen klikkes. " "Denne indstilling tages der kun hensyn til hvis et statusfelt ikon bruges." #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 #, fuzzy msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" "Hvis Sandt, vil Gajim vise et ikon på hvert faneblad som indeholder ulæste " "beskeder. Afhængig af temaet, kan dette ikon være animeret." #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" "Hvis Sandt, vil Gajim vise status beskeder, hvis ikke tomme, for hver " "kontakt under kontaktnavnet i kontaktvinduet." #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "" "Definer positionen af avataren i kontaktvinduet. Kan være venstre eller højre" #: gajim/common/config.py:238 #, fuzzy msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" "Hvis Falsk, vil Gajim ikke længere skrive statuslinjer i samtaler når en " "kontakt ændrer hans eller hendes status og/eller hans eller hendes status " "besked." #: gajim/common/config.py:239 #, fuzzy msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" "kan være \"none\", \"all\" eller \"in_and_out\". Hvis \"nono\" vil Gajim " "ikke længere skrive statuslinier i gruppesamtaler når et medlem ændrer hans " "eller hendes status og/eller hans eller hendes status besked. Hvis \"all\" " "vil Gajim skrive alle status beskeder. Hvis \"in_and_out\" vil Gajim kun " "skrive FOO kommer/forlader gruppesamtalen." #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 #, fuzzy msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" "Hvis Sandt vil gamle beskeder fra forrige samtale bruge en mindre skrifttype " "end den som er standard." #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "Ikke vis en avatar for selve transporten." #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "Ikke hvis kontaktvindue i vindueslisten." #: gajim/common/config.py:245 #, fuzzy msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" "Hvis Sandt og GTK+ og PyGTK installerede versioner er mindst 2.8, blink med " "vinduet (standard adfærd i de fleste vindueshåndterere) når det indeholder " "ventende begivenheder." #: gajim/common/config.py:249 #, fuzzy msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" "Kontrollerer vinduet hvor nye beskeder er placeret.\n" "'always' - Alle beskeder bliver vist i et enkelt vindue.\n" "'always_with_roster' - Som 'always' men beskederne er i et enkelt vindue " "sammen med kontaktvinduet.\n" "'never' - Alle beskeder får deres eget vindue.\n" "'peracct' - Beskeder for den enkelte konto bliver sendt til specifikke " "vinduer.\n" "'pertype' - Hver besked type (for eks. samtaler versus gruppesamtaler) " "bliver sendt til et specifikt vindue." #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "Hvis Falsk vil du ikke længere se en avatar i samtale vinduet." #: gajim/common/config.py:252 #, fuzzy msgid "If true, pressing the escape key closes a tab/window." msgstr "Hvis Sandt vil tryk på escape tasten lukke et vindue/faneblad." #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "Skjuler banneret i et gruppesamtale vindue" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "Skjuler banneret i et to personers samtalevindue" #: gajim/common/config.py:255 msgid "Hides the group chat occupants list in group chat window." msgstr "Skjuler gruppesamtale deltagerlisten i gruppesamtale vinduer." #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" "I en samtale, vis kælenavn i begyndelsen af en linie kun når det ikke er den " "samme person som snakker som i forrige besked." #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "Indrykning når man fletter ens kælenavne." #: gajim/common/config.py:258 msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "" "Liste af farver, separeret med \":\", som vil blive brugt til at farve " "kælenavne i gruppesamtaler." #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "Ctrl-Tab gå til næste faneblad når ingen er ulæste." #: gajim/common/config.py:260 #, fuzzy msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" "Skal vi vise bekræftelses vinduet for oprettelse af metakontakter? Tom " "streng betyder at vi aldrig viser vinduet." #: gajim/common/config.py:261 #, fuzzy msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" "Skal vi vise bekræftelses vinduet for blokering af kontakter? Tom streng " "betyder at vi aldrig viser vinduet." #: gajim/common/config.py:262 #, fuzzy msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" "Skal vi vise bekræftelses vinduet for ændring af personlig status? Tom " "streng betyder at vi aldrig viser vinduet." #: gajim/common/config.py:263 #, fuzzy msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" "Hvis Sandt vil du være i stand til at sætte en negativ prioritet til din " "konto i kontoændrings vinduet. VÆR FORSIGTIG, når du er logget med en " "negativ prioritet vil du IKKE modtage nogen beskeder fra din server." #: gajim/common/config.py:264 #, fuzzy msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" "Hvis Sandt vil Gajim vise antallet af online og totale kontakter i konto og " "gruppe rækker." #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" "Kan være tom, 'chat' eller 'normal'. Hvis ikke tom, behandl alle indkommende " "beskeder som om de var af denne type" #: gajim/common/config.py:266 #, fuzzy msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" "Hvis Sandt vil Gajim rulle ned/op og vælge den kontakt som sendte dig den " "sidste besked, hvis ikke allerede kontaktvinduet er åbent." #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" "Tid med inaktivitet der skal gå før vinduet til at ændre status lukkes." #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" "Maksimum antal linjer som bliver skrevet i samtaler. De ældste linjer bliver " "slettet." #: gajim/common/config.py:269 #, fuzzy msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" "Hvis sandt vil påmindelses vinduer fra påmindelses dæmonen blive fæstet til " "ikonet i systembakken." #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "Vælg interval mellem 2 kontroller for ingen aktivitet." #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" "Gyldige uri skemaer. Kun skemaer i denne liste vil blive accepteret som " "\"rigtige\" uri. (mailto og xmpp bliver behandlet separat)" #: gajim/common/config.py:272 #, fuzzy msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" "Hvis sandt, vil færdiggørelse i gruppe samtaler fungere på samme måde som " "færdiggørelse i kommandolinjen" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" "Når bliver selv kontakt rækken vist. Kan være \"always\", " "\"when_other_resource\" eller \"never\"" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 #, fuzzy msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" "Hvis aktiveret vil Gajim i spørge for en status besked. Den valgte standard " "besked vil blive brugt i stedet." #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 #, fuzzy msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" "Hvis Sandt vil Gajim bruge Gnome Nøglering (hvis tilgængelig) til at gemme " "konto adgangskoder." #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" "Prioriteten vil ændres automatisk ifølge din status. Prioriteter er " "defineret i autopriority_* indstillingerne." #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" "Din status som bruges når du automatisk forbindes. Kan være online, samtale, " "væk, ikke tilgængelig, vil ikke forstyrres, usynlig. NOTE: denne " "valgmulighed bliver kun brugt hvis restore_last_status er deaktiveret" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "Hvis valgt, gendan den sidste status som var brugt." #: gajim/common/config.py:325 #, fuzzy msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" "Hvis sandt, kontakter som beder om autorisering vil automatisk blive " "accepteret." #: gajim/common/config.py:326 msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "" "Hvis Falsk vil denne konto blive deaktiveret og vil ikke vises i " "kontaktvinduet." #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" "Hvis deaktiveret, ikke signer tilstedeværelser med GPG nøgle, selvom GPG er " "konfigureret." #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 #, fuzzy msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" "Hvis en advarsels dialog før en adgangskode sendes over en forbindelse i " "klar tekst." #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "Hvis en advarsels dialog før brugen af standard SSL biblioteket." #: gajim/common/config.py:337 #, fuzzy msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" "Hvis en advarsels dialog før en adgangskode sendes over en forbindelse i " "klar tekst." #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "Mellemrums adskilt liste af ssl fejl som skal ignoreres." #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "Mellemrum sendt efter inaktivitet" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "XMPP ping sendt efter inaktivitet" #: gajim/common/config.py:354 #, fuzzy msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" "Hvor mange sekunder skal der ventes på svaret af en holdilive pakke, før vi " "prøver at forbinde igen." #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "Jabberd2 tilpasning" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" "Hvis valgt vil Gajim bruge din IP og proxy defineret i file_transfer_proxies " "indstillingen for filoverførsler." #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "Svar til modtagelses forespørgsel" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "Sendte modtagelses forespørgsler" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "" "Hvis valgt vil Gajim tillade andre at kunne se det operativ system du bruger" #: gajim/common/config.py:386 #, fuzzy msgid "Allow Gajim to send your local time." msgstr "%s vil gerne sende dig en fil." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Fyld ind data for den kontakt som du vil tilføje" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Anonym godkendelse" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Anonym godkendelse" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Anonym godkendelse" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 #, fuzzy msgid "Language for which misspelled words will be checked" msgstr "Sprog som vi vil bruge til at kontrollere for stavefejl" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 #, fuzzy msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" "Hvor mange linjer skal hentes fra serveren når man deltager i en " "gruppesamtale." #: gajim/common/config.py:442 #, fuzzy msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" "Hvor mange minutter tilbage skal der hentes log fra når man deltager i en " "gruppesamtale." #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "Sover" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Snart tilbage" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Tilbage om få minutter." #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "Spiser" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "Jeg spiser, så læg en besked." #: gajim/common/config.py:454 msgid "Movie" msgstr "Film" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "Jeg ser en film." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "Arbejder" #: gajim/common/config.py:455 msgid "I'm working." msgstr "Jeg arbejder." #: gajim/common/config.py:456 msgid "Phone" msgstr "Telefon" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Jeg snakker i telefon." #: gajim/common/config.py:457 msgid "Out" msgstr "Ude" #: gajim/common/config.py:457 msgid "I'm out enjoying life." msgstr "Jeg er ude og nyder livet." #: gajim/common/config.py:468 msgid "I'm available." msgstr "Jeg er tilgængelig." #: gajim/common/config.py:469 msgid "I'm free for chat." msgstr "Jeg er tilgængelig for en samtale." #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "Er straks tilbage." #: gajim/common/config.py:471 msgid "I'm not available." msgstr "Jeg er ikke tilgængelig." #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "Ikke forstyr." #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "Farvel!" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" "Lyd som spilles når en gruppesamtale besked indeholder en af følgende ord i " "muc_highlight_words, eller når en gruppesamtale besked indeholder dit " "kælenavn." #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "Lyd som spilles når en hvilken som helst MUC besked ankommer." #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "Til" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Fejl: kan ikke åbne %s for læsning" #: gajim/common/const.py:205 msgid "Doing Chores" msgstr "Laver Husarbejde" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "Køber ind" #: gajim/common/const.py:207 msgid "Cleaning" msgstr "Gør Rent" #: gajim/common/const.py:208 msgid "Cooking" msgstr "Laver Mad" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "Gør Vedligeholdsarbejde" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "Vasker op" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "Vasker Tøj" #: gajim/common/const.py:212 msgid "Gardening" msgstr "Laver Havearbejde" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "Løber et Ærinde" #: gajim/common/const.py:214 msgid "Walking the Dog" msgstr "Går tur med hunden" #: gajim/common/const.py:216 msgid "Drinking" msgstr "Drikker" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "Drikker en Øl" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "Drikke Kaffe" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "Drikker Te" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "Spiser et lille Mellemmåltid" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "Spiser Morgenmad" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "Spiser Middag" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "Spiser Frokost" #: gajim/common/const.py:227 msgid "Exercising" msgstr "Træner" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "Cykler" #: gajim/common/const.py:229 msgid "Dancing" msgstr "Danser" #: gajim/common/const.py:230 msgid "Hiking" msgstr "Vandrer" #: gajim/common/const.py:231 msgid "Jogging" msgstr "Jogger" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "Dyrker Sport" #: gajim/common/const.py:233 msgid "Running" msgstr "Løber" #: gajim/common/const.py:234 msgid "Skiing" msgstr "Står på ski" #: gajim/common/const.py:235 msgid "Swimming" msgstr "Svømmer" #: gajim/common/const.py:236 msgid "Working out" msgstr "Træner" #: gajim/common/const.py:238 msgid "Grooming" msgstr "Plejer" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "I Spabad" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "Børster Tænder" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "Bliver Klippet" #: gajim/common/const.py:242 msgid "Shaving" msgstr "Barberer" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "Tager et Bad" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "Tager et Brusebad" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "Har en Aftale" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Ikke aktiv" #: gajim/common/const.py:249 msgid "Day Off" msgstr "Fridag" #: gajim/common/const.py:250 msgid "Hanging out" msgstr "Hænge ud" #: gajim/common/const.py:251 msgid "Hiding" msgstr "Skjult" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "Få Ferie" #: gajim/common/const.py:253 msgid "Praying" msgstr "Ber" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "Planlagt Ferie" #: gajim/common/const.py:256 msgid "Thinking" msgstr "Tænker" #: gajim/common/const.py:258 msgid "Relaxing" msgstr "Slapper af" #: gajim/common/const.py:259 msgid "Fishing" msgstr "Fisker" #: gajim/common/const.py:260 msgid "Gaming" msgstr "Spiller" #: gajim/common/const.py:261 msgid "Going out" msgstr "Går ud" #: gajim/common/const.py:262 msgid "Partying" msgstr "Fester" #: gajim/common/const.py:263 msgid "Reading" msgstr "Læser" #: gajim/common/const.py:264 msgid "Rehearsing" msgstr "Øver" #: gajim/common/const.py:265 msgid "Shopping" msgstr "Køber ind" #: gajim/common/const.py:266 msgid "Smoking" msgstr "Ryger" #: gajim/common/const.py:267 msgid "Socializing" msgstr "Socialiserer" #: gajim/common/const.py:268 msgid "Sunbathing" msgstr "Solbader" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "Ser TV" #: gajim/common/const.py:270 msgid "Watching a Movie" msgstr "Ser en film." #: gajim/common/const.py:272 msgid "Talking" msgstr "Taler" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "I det virkelige liv" #: gajim/common/const.py:274 msgid "On the Phone" msgstr "Snakker i telefon." #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "Taler i Video Telefon" #: gajim/common/const.py:277 msgid "Traveling" msgstr "Rejser" #: gajim/common/const.py:278 msgid "Commuting" msgstr "Pendler" #: gajim/common/const.py:280 msgid "Driving" msgstr "Kører" #: gajim/common/const.py:281 msgid "In a Car" msgstr "I en Bil" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "På en Bus" #: gajim/common/const.py:283 msgid "On a Plane" msgstr "Flyver" #: gajim/common/const.py:284 msgid "On a Train" msgstr "Kører i tog" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "På Rejse" #: gajim/common/const.py:286 msgid "Walking" msgstr "Går" #: gajim/common/const.py:289 msgid "Coding" msgstr "Koder" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "I et Møde" #: gajim/common/const.py:291 msgid "Studying" msgstr "Studerer" #: gajim/common/const.py:292 msgid "Writing" msgstr "Skriver" #: gajim/common/const.py:295 msgid "Afraid" msgstr "Bange for" #: gajim/common/const.py:296 msgid "Amazed" msgstr "Forbavset" #: gajim/common/const.py:297 msgid "Amorous" msgstr "Erotisk" #: gajim/common/const.py:298 msgid "Angry" msgstr "Gal" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "Misfornøjet" #: gajim/common/const.py:300 msgid "Anxious" msgstr "Ængstelig" #: gajim/common/const.py:301 msgid "Aroused" msgstr "Vækket" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "Skamfuld" #: gajim/common/const.py:303 msgid "Bored" msgstr "Keder mig" #: gajim/common/const.py:304 msgid "Brave" msgstr "Modig" #: gajim/common/const.py:305 msgid "Calm" msgstr "Rolig" #: gajim/common/const.py:306 msgid "Cautious" msgstr "Forsigtig" #: gajim/common/const.py:307 msgid "Cold" msgstr "Fryser" #: gajim/common/const.py:308 msgid "Confident" msgstr "Sikker" #: gajim/common/const.py:309 msgid "Confused" msgstr "Forvirret" #: gajim/common/const.py:310 msgid "Contemplative" msgstr "Dybsindig" #: gajim/common/const.py:311 msgid "Contented" msgstr "Tilfreds" #: gajim/common/const.py:312 msgid "Cranky" msgstr "Forskruet" #: gajim/common/const.py:313 msgid "Crazy" msgstr "Vanvittig" #: gajim/common/const.py:314 msgid "Creative" msgstr "Kreativ" #: gajim/common/const.py:315 msgid "Curious" msgstr "Nysgerrig" #: gajim/common/const.py:316 msgid "Dejected" msgstr "Nedslået" #: gajim/common/const.py:317 msgid "Depressed" msgstr "Deprimeret" #: gajim/common/const.py:318 msgid "Disappointed" msgstr "Skuffet" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "Væmmes" #: gajim/common/const.py:320 msgid "Dismayed" msgstr "Forfærdet" #: gajim/common/const.py:321 msgid "Distracted" msgstr "Forstyrret" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "Forlegen" #: gajim/common/const.py:323 msgid "Envious" msgstr "Misundelig" #: gajim/common/const.py:324 msgid "Excited" msgstr "Spændt" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "Flirtende" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "Frustreret" #: gajim/common/const.py:327 msgid "Grateful" msgstr "Taknemlig" #: gajim/common/const.py:328 msgid "Grieving" msgstr "Sørge" #: gajim/common/const.py:329 msgid "Grumpy" msgstr "Gnaven" #: gajim/common/const.py:330 msgid "Guilty" msgstr "Skyldig" #: gajim/common/const.py:331 msgid "Happy" msgstr "Glad" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "Håbefuld" #: gajim/common/const.py:333 msgid "Hot" msgstr "Varm" #: gajim/common/const.py:334 msgid "Humbled" msgstr "Ydmyg" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "Ydmyget" #: gajim/common/const.py:336 msgid "Hungry" msgstr "Sulten" #: gajim/common/const.py:337 msgid "Hurt" msgstr "Såret" #: gajim/common/const.py:338 msgid "Impressed" msgstr "Imponeret" #: gajim/common/const.py:339 msgid "In Awe" msgstr "Ærefrygt" #: gajim/common/const.py:340 msgid "In Love" msgstr "Forelsket" #: gajim/common/const.py:341 msgid "Indignant" msgstr "Indigneret" #: gajim/common/const.py:342 msgid "Interested" msgstr "Interesseret" #: gajim/common/const.py:343 msgid "Intoxicated" msgstr "Beruset" #: gajim/common/const.py:344 msgid "Invincible" msgstr "Uovervindelig" #: gajim/common/const.py:345 msgid "Jealous" msgstr "Jaloux" #: gajim/common/const.py:346 msgid "Lonely" msgstr "Ensom" #: gajim/common/const.py:347 msgid "Lost" msgstr "Tabt" #: gajim/common/const.py:348 msgid "Lucky" msgstr "Heldig" #: gajim/common/const.py:349 msgid "Mean" msgstr "Ondskabsfuld" #: gajim/common/const.py:350 msgid "Moody" msgstr "Gnaven" #: gajim/common/const.py:351 msgid "Nervous" msgstr "Nervøs" #: gajim/common/const.py:352 msgid "Neutral" msgstr "Neutral" #: gajim/common/const.py:353 msgid "Offended" msgstr "Fornærmet" #: gajim/common/const.py:354 msgid "Outraged" msgstr "Oprørt" #: gajim/common/const.py:355 msgid "Playful" msgstr "Spøgefuld" #: gajim/common/const.py:356 msgid "Proud" msgstr "Stolt" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "Afslappet" #: gajim/common/const.py:358 msgid "Relieved" msgstr "Lettet" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "Angrende" #: gajim/common/const.py:360 msgid "Restless" msgstr "Hvileløs" #: gajim/common/const.py:361 msgid "Sad" msgstr "Trist" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "Sarkastisk" #: gajim/common/const.py:363 msgid "Satisfied" msgstr "Tilfreds" #: gajim/common/const.py:364 msgid "Serious" msgstr "Seriøs" #: gajim/common/const.py:365 msgid "Shocked" msgstr "Sjokeret" #: gajim/common/const.py:366 msgid "Shy" msgstr "Genert" #: gajim/common/const.py:367 msgid "Sick" msgstr "Syg" #: gajim/common/const.py:368 msgid "Sleepy" msgstr "Søvnig" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "Spontan" #: gajim/common/const.py:370 msgid "Stressed" msgstr "Stresset" #: gajim/common/const.py:371 msgid "Strong" msgstr "Stærk" #: gajim/common/const.py:372 msgid "Surprised" msgstr "Overrasket" #: gajim/common/const.py:373 msgid "Thankful" msgstr "Taknemlig" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "Tørstig" #: gajim/common/const.py:375 msgid "Tired" msgstr "Træt" #: gajim/common/const.py:376 msgid "Undefined" msgstr "Uforklaret" #: gajim/common/const.py:377 msgid "Weak" msgstr "Svag" #: gajim/common/const.py:378 msgid "Worried" msgstr "Bekymret" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "standard" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "marint" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Skjult" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "Konto" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Konto" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Beskrivelse" #: gajim/common/const.py:391 #, fuzzy msgid "error" msgstr "Fejl" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "en" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 msgid "room" msgstr "rum" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "Ikke i stand til at skaffer udstedelses certifikat" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "Ikke i stand til at skaffe certifikat CRL" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "Ikke i stand til at dekryptere certifikatets signatur" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "Ikke i stand til at dekryptere CRL's signatur" #: gajim/common/const.py:412 msgid "Unable to decode issuer public key" msgstr "Ikke i stand til at dekode udstederens offentlige nøgle" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "Certifikat signaturen fejlede" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "CRL signatur fejl" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "Certifikatet er ikke gyldigt endnu" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "Certifikatet er udløbet" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "CRL er endnu ikke gyldigt" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "CRL er udløbet" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "Formateringsfejl i certifikatets notBefore felt" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "Formateringsfejl i certifikatets notAfter felt" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "Formateringsfejl i CRL's lastUpdate felt" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "Formateringsfejl i CRL's nextUpdate felt" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "Ikke mere hukommelse" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "Selvsigneret certifikat" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "Selvsigneret certifikat i certifikats kæden" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "Ikke i stand til at skaffe lokalt udstedelses certifikat" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "Ikke i stand til at verificere det første certifikat" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "Certifikat kæde er for lang" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "Certifikat tilbagekaldt" #: gajim/common/const.py:430 msgid "Invalid CA certificate" msgstr "Ugyldig CA certifikat" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "Sti længde begrænsning overskredet" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "Ikke understøttet formål for certifikatet" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "Certifikatet er ikke til at stole på" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "Certifikatet afvist" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "Emne udsteder uoverensstemmelse" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "Autoritet og emne nøgle identifikations uoverensstemmelse" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "Autoritet og udstedelses serie nummer uoverensstemmelse" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "Nøglebrug indeholder ikke certifikat signering" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "Kunne ikke verificere programmet" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "%s er ikke et gyldigt logniveau" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Tilslutning til konto \"%s\" er blevet afbrudt" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "Tilslut manuelt." #: gajim/common/connection.py:740 #, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "" "Server %(name)s svarede forkert på indskrivnings forespørgslen: %(error)s" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "Serveren %s gav en anderledes registreringsform" #: gajim/common/connection.py:1090 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Kunne ikke tilslutte til \"%s\"" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Kunne ikke tilslutte til \"%s\"" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Kontroller din tilslutning eller forsøg igen senere." #: gajim/common/connection.py:1100 #, python-format msgid "Server replied: %s" msgstr "Server svarede: %s" #: gajim/common/connection.py:1115 msgid "Connection to proxy failed" msgstr "Tilslutning til proxy fejlede" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, python-format msgid "Could not connect to account %s" msgstr "Kunne ikke tilslutte til kontoen %s" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "" "Tilslutning til kontoen \"%s\" er blevet afbrudt. Prøv at tilslutte igen." #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Kunne ikke tilslutte til \"%s\"" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "Godkendelse fejlede med \"%s\"" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Venligst kontroller om dit logind og adgangskode er korrekt." #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "D-Bus python bindinger mangler på denne computer" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "Gajims D-Bus evner kan ikke bruges" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "D-Bus kører ikke korrekt på denne maskine" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "D-Bus kører ikke korrekt på denne maskine" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "D-Bus kører ikke korrekt på denne maskine" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Standard Besked" #: gajim/common/multimedia_helpers.py:70 msgid "Audio test" msgstr "" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Størrelse: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Fil: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "grøn" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, fuzzy, python-format msgid "%s configuration error" msgstr "Rum Konfigurering" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Ugyldig karakter i værtsnavn." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Server adresse påkrævet." #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Ugyldig karakter i brugernavn." #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "Ugyldig karakter i ressource." #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "_Travlt" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "_Ikke tilgængelig" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "_Tilgængelig for samtale" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "?transfer status:Midlertidig stoppet" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "Tilslutter" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "_Væk" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "_Afkoblet" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "_Usynlig" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "?contact has status:Ukendt" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "?contact has status:Har fejl" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "?Subscription we already have:Intet" #: gajim/common/helpers.py:315 msgid "To" msgstr "Til" #: gajim/common/helpers.py:317 msgid "From" msgstr "Fra" #: gajim/common/helpers.py:319 msgid "Both" msgstr "Begge" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "?OS:Ukendt" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "?Ask (for Subscription):Intet" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Abonner" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "?Group Chat Contact Role:Ingen" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Moderatorer" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Moderator" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Deltagere" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Deltager" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Besøgende" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Besøgende" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "er opmærksom på samtalen" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "gør noget andet" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "komponerer en besked..." #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "holder pause med at komponere en besked" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "har lukket samtalevinduet eller fanebladet" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s GiB" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s GB" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s MiB" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s MB" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s KiB" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s KB" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s B" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "%d besked venter" msgstr[1] "%d beskeder venter" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr "fra rum %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, fuzzy, python-format msgid "from user %s" msgstr "fra bruger %s" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr " fra %s" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "%d hændelse venter" msgstr[1] "%d hændelser venter" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Jeg vil gerne tilføje dig til min kontakt liste." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 msgid "Timeout loading image" msgstr "Tidsudløb nået for at laste billede" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "Billede er for stort" #: gajim/common/helpers.py:1383 #, fuzzy msgid "PyCURL is not installed" msgstr "CRL er endnu ikke gyldigt" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Tidsudløb nået for at laste billede" #: gajim/common/configpaths.py:85 #, python-format msgid "%s is a file but it should be a directory" msgstr "%s er en fil, men burde være et katalog" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Gajim vil nu slutte" #: gajim/common/exceptions.py:45 #, fuzzy, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" "Database filen (%s) kan ikke læses. Prøv at reparere den (se http://trac." "gajim.org/wiki/DatabaseBackup) eller fjerne den (hele historikken vil tabes)." #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" "Tjeneste ikke tilgængelig: Gajim kører ikke, eller remote_control er Falsk" #: gajim/common/exceptions.py:81 #, fuzzy, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "" "Sessions bussen er ikke tilgængelig.\n" "Prøv at læse http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/exceptions.py:93 #, fuzzy, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" "Sessions bussen er ikke tilgængelig.\n" "Prøv at læse http://trac.gajim.org/wiki/GajimDBus" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 msgid "Please check if Avahi or Bonjour is installed." msgstr "Kontroller venligst om Avahi eller Bonjour er installeret." #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "Kunne ikke starte lokal tjeneste" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, python-format msgid "Unable to bind to port %d." msgstr "Ikke i stand til at tildele port %d." #: gajim/common/zeroconf/connection_zeroconf.py:217 #, fuzzy msgid "Please check if avahi/bonjour-daemon is running." msgstr "Kontroller venligst om avahi-dæmonen kører." #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, python-format msgid "Could not change status of account \"%s\"" msgstr "Kunne ikke ændre status på kontoen \"%s\"" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "Kontroller venligst om avahi-dæmonen kører." #: gajim/common/zeroconf/connection_zeroconf.py:349 msgid "Your message could not be sent." msgstr "Din besked kunne ikke sendes." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "Kontakt er afkoblet. Din besked kunne ikke sendes." #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "" "Tilslutning til vært kunne ikke etableres: Tidsudløb mens data var blevet " "sendt." #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, python-format msgid "Error while adding service. %s" msgstr "Fejl ved tilføjelse af tjeneste. %s" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "besked" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "Jeg vil gerne tilføje dig til min kontaktliste." #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Fejl: %s" #: gajim/common/modules/httpupload.py:134 msgid "File is empty" msgstr "Filen er tom" #: gajim/common/modules/httpupload.py:137 msgid "File does not exist" msgstr "Filen eksisterer ikke" #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 msgid "Change status information" msgstr "Ændre status information" #: gajim/common/modules/adhoc_commands.py:113 msgid "Change status" msgstr "Ændre status" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "Sæt tilstedeværelses type og beskrivelse" #: gajim/common/modules/adhoc_commands.py:121 msgid "Free for chat" msgstr "Åben for samtaler" #: gajim/common/modules/adhoc_commands.py:122 msgid "Online" msgstr "Online" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "Udvidet borte" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "Forstyr ikke" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "Ofline - ikke tilsluttet" #: gajim/common/modules/adhoc_commands.py:132 msgid "Presence description:" msgstr "Tilstedeværelses beskrivelse:" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "Din status er blevet ændret." #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 msgid "Leave Groupchats" msgstr "Forlad Gruppesamtaler" #: gajim/common/modules/adhoc_commands.py:231 #, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s i %(room_jid)s" #: gajim/common/modules/adhoc_commands.py:235 msgid "You have not joined a groupchat." msgstr "Du detlager ikke i en gruppesamtale." #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "Vælg de gruppesamtaler du vil forlade" #: gajim/common/modules/adhoc_commands.py:292 msgid "You left the following groupchats:" msgstr "Du forlod de følgende gruppesamtaler:" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "Ukendt Artist" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "Ukendt Titel" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "Ukendt Kilde" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" "\"%(title)s\" af %(artist)s\n" "fra %(source)s" #: gajim/common/modules/roster_item_exchange.py:100 #, fuzzy, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "Sendt kontakt: \"%s\" (%s)" #: gajim/common/modules/roster_item_exchange.py:104 msgid "Sent contacts:" msgstr "Sendte kontakter:" #: gajim/data/gui/blocked_contacts_window.ui:13 msgid "Blocked Contacts" msgstr "Blokerede Kontakter" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Avanceret Konfigurations Behandler" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Filter:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Beskrivelse" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "" "NOTE: Du skal genstarte Gajim for at nogle af ændringerne kan træde i " "kraft" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "_Nulstil til Standard Farver" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Bliv automatisk med" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Konto" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Rum:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Adgangskode:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "Bogmærk dette rom" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "_Bogmærke" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "i _gruppe samtaler" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 #, fuzzy msgid "HTTP Connect" msgstr "" "HTTP Tilslutning\n" "SOCKS5\n" "BOSH" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Håndter Proxy Profiler" #: gajim/data/gui/manage_proxies_window.ui:148 msgid "_Name:" msgstr "_Navn:" #: gajim/data/gui/manage_proxies_window.ui:161 msgid "_Type:" msgstr "_Type:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Egenskaber" #: gajim/data/gui/manage_proxies_window.ui:234 msgid "_BOSH URL:" msgstr "_BOSH URL:" #: gajim/data/gui/manage_proxies_window.ui:258 msgid "Proxy _Host:" msgstr "Proxy _vært:" #: gajim/data/gui/manage_proxies_window.ui:269 msgid "Use HTTP prox_y" msgstr "Brug HTTP prox_y" #: gajim/data/gui/manage_proxies_window.ui:288 msgid "Proxy _Port:" msgstr "Proxy _Port:" #: gajim/data/gui/manage_proxies_window.ui:299 msgid "Use proxy auth_entication" msgstr "Brug proxy godkendelse" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "_Brugernavn:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "Adgangs_kode" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Opsætning" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Gem adgangskode" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Ændre Adgangskode" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Kontakt Information" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "Lokal jid:" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "Resource:" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Status:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Log samtale historie" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 msgid "Contact" msgstr "Kontakt" #: gajim/data/gui/zeroconf_information_window.ui:234 msgid "First Name:" msgstr "Fornavn:" #: gajim/data/gui/zeroconf_information_window.ui:247 msgid "Last Name:" msgstr "Efternavn:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "Jabber ID:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "Epost:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 msgid "Personal" msgstr "Personlig" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "_Send en Privat Besked" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Send _Fil" #: gajim/data/gui/gc_occupants_menu.ui:29 msgid "Occupant Actions" msgstr "Beboer Handlinger" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Stemme" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Or_dstyrer" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Medlem" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Administrator" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "_Ejer" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "_Kast ud" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Udvis" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "_Tilføj til Kontaktliste" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "_Kør Kommando" #: gajim/data/gui/tooltip_roster_contact.ui:125 #, fuzzy msgid "Idle since:" msgstr " siden %s" #: gajim/data/gui/tooltip_roster_contact.ui:151 msgid "Mood:" msgstr "Humør:" #: gajim/data/gui/tooltip_roster_contact.ui:164 msgid "Activity:" msgstr "Aktivitet:" #: gajim/data/gui/tooltip_roster_contact.ui:178 #, fuzzy msgid "Tune:" msgstr "Melodi:" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Påmindelse" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP: " #: gajim/data/gui/tooltip_roster_contact.ui:281 #, fuzzy msgid "Subscription:" msgstr "Abonnering: " #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "_Status" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Ændre Konto" #: gajim/data/gui/atom_entry_window.ui:8 msgid "New entry received" msgstr "Ny hændelse modtaget" #: gajim/data/gui/atom_entry_window.ui:92 msgid "Feed name:" msgstr "Feed navn:" #: gajim/data/gui/atom_entry_window.ui:119 msgid "Entry:" msgstr "Indgang:" #: gajim/data/gui/atom_entry_window.ui:131 msgid "Last modified:" msgstr "Sidst ændret:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 msgid "Change _Nickname..." msgstr "Ændre _Kælenavn..." #: gajim/data/gui/gc_control_popup_menu.ui:20 msgid "_Manage Room" msgstr "Håndter Ru_m" #: gajim/data/gui/gc_control_popup_menu.ui:31 msgid "Change _Subject..." msgstr "Ændre _Emne..." #: gajim/data/gui/gc_control_popup_menu.ui:38 msgid "Configure _Room..." msgstr "Tilpas _Rum..." #: gajim/data/gui/gc_control_popup_menu.ui:52 msgid "_Destroy Room" msgstr "_Slet rum" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "_Minimer ved lukning" #: gajim/data/gui/gc_control_popup_menu.ui:85 #, fuzzy msgid "_Request Voice" msgstr "_Stemme" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "Bruger avatar:" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Vælg Billede" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 #, fuzzy msgid "Full Name" msgstr "Fuldt Navn" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Telefon" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Format: YYYY-MM-DD" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 #, fuzzy msgid "Birthday" msgstr "Fødselsdag:" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Hjemmeside:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "Epost:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 msgid "Jabber ID" msgstr "Jabber ID" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 #, fuzzy msgid "Family" msgstr "Efternavn:" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 msgid "Given" msgstr "" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Midten af ugen" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Indstillinger" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Endetillæg:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Stresset" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "Ekstra Adresse:" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 msgid "City" msgstr "" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Status" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 #, fuzzy msgid "Postal Code" msgstr "Postnummer:" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "Konto" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 msgid "Address" msgstr "Adresse" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Navn:" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Firma:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 #, fuzzy msgid "Department" msgstr "Afdeling:" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Betingelse" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Kontakt tid:" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Arbejde" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Om" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "_Fortsæt" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Pause" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Afbryd" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Åbn folderen med filen" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Filoverførsler" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "filoverførsel liste" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "En liste over aktive, færdige og stoppede filoverførsler" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "Ryd _op" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "Fjerner færdige, annullerede og mislykkede filoverførsler fra listen" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Fjern filoverførsler fra listen." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "Denne handling fjerner en enkelt filoverførsel fra listen. Hvis overførslen " "er i gang, bliver den først stoppet og derefter fjernet" #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "Annullerer den valgte filoverførsel og fjerner den ikke fuldførte fil" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Annuller filoverførsel" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Annullerer den valgte filoverførsel" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "_Send & Luk" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Skjuler vinduet" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Påmind mig når en filoverførsel er færdig" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "Når en filoverførsel er færdig, vis en pop op påmindelse" #: gajim/data/gui/filetransfers.ui:229 msgid "Shows a list of file transfers between you and others" msgstr "Viser en liste over filoverførsler mellem dig og andre" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Fed" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Kursiv" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 msgid "Underline" msgstr "Understregning" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 msgid "Strike" msgstr "Streg" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "Farve" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 msgid "Font" msgstr "Font" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Fjern formatering" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Vælg en Fil at Sende..." #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Hvis en liste over følelsesikoner (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Hændelse" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Hændelse" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Skrifttype" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "#" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Borte" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "Vis _Kontaktvindue" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "Server" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "Standard" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "Filen er tom" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Resource:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Status" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Klient:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 #, fuzzy msgid "System" msgstr "System:" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Kontakt navn" #: gajim/data/gui/vcard_information_window.ui:240 #, fuzzy msgid "User avatar" msgstr "Avatar:" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Konfigureret avatar:" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 msgid "Ask" msgstr "" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Abonnering: " #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 msgid "Personal Info" msgstr "Personlig Information" #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "Kommentarer" #: gajim/data/gui/preferences_window.ui:38 msgid "Use default applications" msgstr "" #: gajim/data/gui/preferences_window.ui:41 #, fuzzy msgid "Custom" msgstr "Tilpasset Opsætning" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Status For Alle" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 #, fuzzy msgid "Composing only" msgstr "Komponere" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Ikke aktiveret" #: gajim/data/gui/preferences_window.ui:89 #, fuzzy msgid "Only when pending events" msgstr "" "Aldrig\n" "Kun ved ventende hændelser\n" "Altid" #: gajim/data/gui/preferences_window.ui:103 msgid "Pop it up" msgstr "" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "Påmind mig om kontakter som logger u_d" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "_Vis hændelse i kontaktvindue" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 #, fuzzy msgid "Last state" msgstr "Sidste status: %s" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "Vis kontakternes a_vatarer i kontaktvinduet" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Hvis valgt vil Gajim vise avatarer af kontakter i kontaktvinduet og i gruppe " "samtaler" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "Vis status _beskeder for kontakter i kontaktvinduet" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Hvis valgt vil Gajim vise status beskeder af kontakter under kontaktnavnet i " "kontaktvinduet og i gruppe samtaler" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Vis kontakternes humør i kontaktvinduet" #: gajim/data/gui/preferences_window.ui:254 msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "Hvis valgt vil Gajim vise kontakternes humør i kontaktvinduet" #: gajim/data/gui/preferences_window.ui:275 msgid "Sort contacts by status" msgstr "Sorter kontakter efter status" #: gajim/data/gui/preferences_window.ui:285 msgid "in _roster" msgstr "i _kontaktvinduet" #: gajim/data/gui/preferences_window.ui:302 msgid "in _group chats" msgstr "i _gruppe samtaler" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "Kontaktvinduets Udseende" #: gajim/data/gui/preferences_window.ui:359 #, fuzzy msgid "Spell _checker" msgstr "Stavekontrol" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" "Hvis valgt vil Gajim fremhæve stavefejl i tekstbokse i samtale vinduet. Hvis " "intet sprog er valgt ved at højreklikke i indtastningsfeltet, vil standard " "sproget blive brugt for denne kontakt eller gruppe samtale." #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "besked indhold" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 #, fuzzy msgid "_Window behavior" msgstr "_Vinduets adfærd:" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "T_ilslut når Gajim startes" #: gajim/data/gui/preferences_window.ui:484 msgid "_Ignore rich content in incoming messages" msgstr "_Ignorer rigt indhold i indkommende beskeder" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" "Nogle beskeder kan indeholde rigt indhold (formatering, farver osv.). Hvis " "valgt\n" "vil Gajim kun vise den rå tekst." #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Ikke i stand til at deltage i gruppesamtale." #: gajim/data/gui/preferences_window.ui:523 msgid "Chat Appearance" msgstr "Samtale udseende" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "Når en ny hændelse er modtaget:" #: gajim/data/gui/preferences_window.ui:623 msgid "Notify me about contacts that sign _in" msgstr "Påmind mig om kontakter logger _ind" #: gajim/data/gui/preferences_window.ui:641 msgid "Notify me about contacts that sign _out" msgstr "Påmind mig om kontakter som logger u_d" #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Gajim vil påminde dig med et pop op vindue i højre bund af skærmen når en " "kontakt logger af" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" "Tillad pop op påmindelser når jeg er _borte/ikke tilgængelig/travel/usynlig" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "" "Tillad pop op påmindelser når jeg er _borte/ikke tilgængelig/travel/usynlig" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "Vis et faneblad når der kun er en samtale?" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Synlige Påmindelser" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "Afspil _lyde" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "Hå_ndtere..." #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "Tillad lyde når jeg er o_ptaget" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Lyde" #: gajim/data/gui/preferences_window.ui:861 msgid "Notifications" msgstr "Påmindelser" #: gajim/data/gui/preferences_window.ui:898 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "Gajim kan sende og modtage meta-information relateret til en samtale du har " "med en kontakt. Her kan du specificere hvilke typer samtalestatus du vil " "vise i samtalevinduerne." #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "Vis samtalestatus påmin_delser:" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim kan sende og modtage meta-information relateret til en samtale du har " "med en kontakt. Her kan du specificere hvilke typer samtalestatus du vil " "sende til modparten." #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "_Send samtalestatus påmindelser:" #: gajim/data/gui/preferences_window.ui:987 msgid "Chat state notifications" msgstr "Samtalestatus påmindelser" #: gajim/data/gui/preferences_window.ui:1009 msgid "Personal Events" msgstr "Personlig Hændelser" #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "_Væk efter:" #: gajim/data/gui/preferences_window.ui:1047 msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" "Hvis valgt vil Gajim ændre status til Væk når computeren ikke bliver brugt." #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "Ikke tilgæ_ngelig efter:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" "Hvis valgt vil Gajim ændre status til Ikke Tilgængelig når computeren ikke " "har været brugt i endnu længere tid" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "minutter" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" "Den automatiske jeg er væk status besked. Hvis tom vil Gajim ikke ændre den " "nuværende status besked\n" "$S vil blive erstattet med den forrige status besked\n" "$T vil blive erstattet med auto-away tidsudløb" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" "Den automatiske jeg er ikke tilgængelig status besked. Hvis tom vil Gajim " "ikke ændre den nuværende status besked\n" "$S vil blive erstattet med den forrige status besked\n" "$T vil blive erstattet med auto-not-available timeout" #: gajim/data/gui/preferences_window.ui:1166 msgid "Auto Status" msgstr "Automatisk Status" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Spørg om status besked når jeg:" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "Logge _ind" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "Log _af" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" "Hvis aktiveret vil Gajim i spørge for en status besked. Den valgte standard " "besked vil blive brugt i stedet." #: gajim/data/gui/preferences_window.ui:1291 msgid "Default Message" msgstr "Standard Besked" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 msgid "Enabled" msgstr "Aktiveret" #: gajim/data/gui/preferences_window.ui:1332 msgid "Status Messages" msgstr "Status Beskeder" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Nuværende Status Beskeder" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "Konfigurér farve og skrifttyper for brugergrænsefladen" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "Status _ikonsæt:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Brug _transportens ikonsæt" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Hvis valgt vil Gajim bruge protokol specifikke status ikoner. (F.eks. En " "kontakt fra MSN vil have det tilsvarende msn ikon for status tilsluttet, " "borte, Travlt, etc...)" #: gajim/data/gui/preferences_window.ui:1724 msgid "_Convert ASCII Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1808 msgid "Style" msgstr "Stil" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Handlinger" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Mellemnavn:" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Server:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Betingelser" #: gajim/data/gui/preferences_window.ui:2159 #, fuzzy msgid "Audio/Video" msgstr "Lyd / Billede" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "_E-post klient:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "_Netlæser:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "_Filhåndterer:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Tilpasset Opsætning" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Programmer" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "_Ignorer hændelser fra kontakter som ikke er i kontaktvinduet" #: gajim/data/gui/preferences_window.ui:2363 msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Hvis valgt vil Gajim ignorere indkommende hændelser fra uautoriserede " "kontakter. Brug med forsigtighed fordi det vil blokere alle beskeder fra " "alle kontakter som ikke er i kontaktvinduet." #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Tillad _OS information at blive sendt" #: gajim/data/gui/preferences_window.ui:2381 msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "" "Hvis valgt vil Gajim tillade andre at kunne se det operativ system du bruger" #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Tillad _OS information at blive sendt" #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "" "Hvis valgt vil Gajim tillade andre at kunne se det operativ system du bruger" #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Tillad _OS information at blive sendt" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 msgid "_Manage..." msgstr "Hå_ndter..." #: gajim/data/gui/preferences_window.ui:2500 msgid "Privacy" msgstr "Privatliv" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "_Log status ændringer hos kontakter" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Diverse" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "_Åbn..." #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Avanceret Konfigurations Behandler" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Start _samtale" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Send en Enkel _Besked" #: gajim/data/gui/contact_context_menu.ui:28 msgid "Send _File..." msgstr "Send _Fil..." #: gajim/data/gui/contact_context_menu.ui:44 msgid "Invite _Contacts" msgstr "Inviter _Kontakter" #: gajim/data/gui/contact_context_menu.ui:73 msgid "E_xecute Command..." msgstr "Kør K_ommando..." #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "_Håndter Kontakt" #: gajim/data/gui/contact_context_menu.ui:92 msgid "_Rename..." msgstr "_Omdøb..." #: gajim/data/gui/contact_context_menu.ui:99 msgid "Edit _Groups..." msgstr "Ændre _Grupper..." #: gajim/data/gui/contact_context_menu.ui:106 msgid "Assign Open_PGP Key..." msgstr "Tilskriv Open_PGP Nøgle..." #: gajim/data/gui/contact_context_menu.ui:115 msgid "Add Special _Notification..." msgstr "Tilføj Speciel Påmi_ndelse..." #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Abonnement" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "Ti_llad denne kontakt at se min status" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "_Spørg om at kunne se hans/hendes status" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "_Nægt ham/hende at se min status" #: gajim/data/gui/contact_context_menu.ui:182 msgid "_Unignore" msgstr "Ikke ign_orer" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "_Ignorer" #: gajim/data/gui/contact_context_menu.ui:197 msgid "_Add to Roster..." msgstr "_Tilføj til Kontaktliste..." #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim: Konto Oprettelses Guide" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Du behøver en konto for at tilslutte dig\n" "til Jabber netværket" #: gajim/data/gui/account_creation_wizard_window.ui:95 msgid "I already have an account I want to _use" msgstr "Jeg har allerede en konto jeg vil br_uge" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "Jeg vil _registrere en ny konto" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Vælg en af mulighederne under:" #: gajim/data/gui/account_creation_wizard_window.ui:167 msgid "Please fill in the data for your existing account" msgstr "Fyld ind data for din eksisterende konto" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "_Jabber ID:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 msgid "Anon_ymous authentication" msgstr "Anonym godkendelse" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Adgangskode" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Gem adgangs_kode" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Hvis valgt vil Gajim huske adgangskoden for denne konto" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "Vælg venligst en server" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Server:" #: gajim/data/gui/account_creation_wizard_window.ui:423 msgid "Prox_y:" msgstr "Pro_xy:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Håndter..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Brug tilpasset værtsnavn/port" #: gajim/data/gui/account_creation_wizard_window.ui:491 msgid "_Hostname:" msgstr "_Værtsnavn:" #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Port:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "_Avanceret" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" "Tilføj dette certifikat til listen af certifikater du stoler på.\n" "SHA1 fingeraftryk af certifikatet:\n" #: gajim/data/gui/account_creation_wizard_window.ui:687 msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Tilslutter til server\n" "\n" "Vent venligst..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Tilslut når jeg trykke Færdig" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Sæt min profil når jeg tilslutter" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Færdig" #: gajim/data/gui/privacy_lists_window.ui:34 msgid "Privacy Lists:" msgstr "Privatlivs Lister:" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Adresse:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "N_aviger" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "Synkronisering : vælg kontakter" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 msgid "Select the contacts you want to synchronise" msgstr "Vælg de kontakter som du vil synkronisere" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Rediger Grupper" #: gajim/data/gui/search_window.ui:42 msgid "Please wait while retrieving search form..." msgstr "Vent mens en søge form hentes..." #: gajim/data/gui/search_window.ui:80 msgid "_Add contact" msgstr "Tilføj Kont_akt" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "_Søg" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Forvalgte beskeder:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Aktivitet:" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Skriv din nye status besked" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 msgid "Synchronise contacts" msgstr "Synkroniser kontakter" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "Vælg den konto som du vil synkronisere med" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "_Jabber ID:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "_Kælenavn:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "_Gruppe:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "K_onto:" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "_Protokol:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "Ti_llad denne kontakt at se min status" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "_Abonnement" #: gajim/data/gui/add_new_contact_window.ui:367 #, fuzzy msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" "Du må registrere dig for denne transport\n" "for at være i stand til at tilføje kontakter fra denne\n" "protokol. Klik på registrer knappen for at\n" "fortsætte." #: gajim/data/gui/add_new_contact_window.ui:382 msgid "_Register" msgstr "Kan _registreres" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" "Du må være tilsluttet til transporten for at kunne\n" "tilføje en kontakt for denne protokol." #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "_Ændre Status Besked" #: gajim/data/gui/change_mood_dialog.ui:73 msgid "Mood:" msgstr "Humør:" #: gajim/data/gui/change_mood_dialog.ui:85 msgid "Message:" msgstr "Besked:" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Hænger" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Tilslutning fejlede" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Tilslutning fejlede" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Beskrivelse" #: gajim/data/gui/plugins_window.ui:258 #, fuzzy msgid "Version" msgstr "GTK+ Version:" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "Au_torisere" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 #, fuzzy msgid "Installed" msgstr "Hænger" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "en" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "Begge" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "Fra" #: gajim/data/gui/privacy_list_window.ui:27 #, fuzzy msgid "to" msgstr "to" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "Privatlivs Liste" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "Privatlivs Liste" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "Aktiv i denne session" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "Aktiv efter hver start" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "Liste af regler" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "Tilføj / Ændre en regel" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "Tillad" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Nægt" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "Jabber ID" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "Alle i gruppen" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "Alle efter abonnering" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "Alle" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "at sende mig beskeder" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "at sende mig forespørgsler" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "at se min status" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "at sende mig status" #: gajim/data/gui/privacy_list_window.ui:557 msgid "All (including subscription)" msgstr "Alle (inkluderende abonnering)" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "Bestil:" #: gajim/data/gui/manage_sounds_window.ui:23 msgid "Manage sounds" msgstr "Håndter lyde" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Aktiv" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Hændelse" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Vælg Lyd" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Fjern kun k_ontoen fra Gajim" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Fjern konto fra Gajim og fra _serveren" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "Hvad vil du gøre?" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Vent mens kommandolisten bliver modtaget..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Vælg kommando som skal udføres:" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Kontroller en gang til" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Vent mens kommandoen bliver sendt..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Denne jabber enhed eksponerer ikke nogen kommandoer." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "En fejl er opstået:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Færdig" #: gajim/data/gui/account_context_menu.ui:20 msgid "_Personal Events" msgstr "_Personlige hændelser" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "Bliv med i en _Gruppe Samtale" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Tilføj Kontakt..." #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "Op_dag Tjenester" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "_Udfør Kommando..." #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Vis" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Vis _Kontaktvindue" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Vis _Afkoblede Kontakter" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Vis Kun _Aktive Kontakter" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Vis Trans_porter" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Hjælp" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Indhold" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_OSS" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 msgid "Features" msgstr "Egenskaber" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "_Bogmærke" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Indstillinger" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Afslut" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Afbryd" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "Liste over mulige egenskaber i Gajim: " #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "_Gruppe Chat" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "Bogmærk dette rom" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Server:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Adgangskode" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Kontakt er ikke Tilsluttet" #: gajim/data/gui/manage_bookmarks_window.ui:342 #, fuzzy msgid "Minimize on Auto Join" msgstr "Minimer ved Automatisk Deltagelse" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Send besked og luk vinduet" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Status Besked" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Beskrivelse: " #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Gør Rent" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 #, fuzzy msgid "Send" msgstr "_Send" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Fil: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" "Den er sikkert ikke kritisk, men bør alligevel rapporteres til udviklerne." #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Rapporter Fejl" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Start Samtale" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "_Nægt" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" "Nægt autorisation fra kontakter så han eller hun ikke kan opnå information " "om at du er tilsluttet" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "Au_torisere" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "" "Autoriser kontakt så han eller hun kan opnå information om at du er " "tilsluttet" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "_Tilstedeværelse" #: gajim/data/gui/emoji_chooser.ui:98 #, fuzzy msgid "No Results Found" msgstr "Intet resultat" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "Inviter Venner!" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "" "Du er ved at begynde en Multibruger samtale.\n" "Vælg de kontakter du vil invitere" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "Vælg en MUC server." #: gajim/data/gui/chat_to_muc_window.ui:141 msgid "MUC server" msgstr "MUC server" #: gajim/data/gui/chat_to_muc_window.ui:176 msgid "In_vite" msgstr "In_viter" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Eksporter" #: gajim/data/gui/history_manager.ui:93 msgid "Welcome to Gajim History Logs Manager" msgstr "Velkommen til Gajims Loghistorie Håndterer" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" "Denne loghåndterer er ikke ment til at gennemse loggene. Hvis du leder efter " "den funktionalitet, brug historik vinduet i stedet.\n" "\n" "Brug dette program til at slette eller eksportere logger. Du kan selektere " "logger fra venstre og/eller søge databasen under. " #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "ADVARSEL:\n" "Hvis du planlægger at gøre massive sletninger, vær sikker på at Gajim ikke " "kører. \n" "Generelt undgå at slette logger fra kontakter du samtidig snakker med." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Søg Database" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "Besked indhold" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Send besked" #: gajim/data/gui/shortcuts_window.ui:24 #, fuzzy msgid "Add new line" msgstr "Lav en ny post" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Forvalgte beskeder:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Forvalgte beskeder:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "status besked" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Send besked" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Besked er Sendt" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "For nylig:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Gør Rent" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Filoverførsler" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "i _gruppe samtaler" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "status besked" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 #, fuzzy msgid "Appearance" msgstr "Samtale udseende" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Vis _Afkoblede Kontakter" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Vis Kun _Aktive Kontakter" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Kontakter" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Kontakt Information" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Omdøb Kontakt" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Sendte kontakter:" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "PGP-løsen" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "_Log status ændringer hos kontakter" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Moderator" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "For nylig:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Samtale Historie" #: gajim/data/gui/history_window.ui:315 #, fuzzy msgid "Chat" msgstr "Samtaler" #: gajim/data/gui/history_window.ui:329 #, fuzzy msgid "Record history for this chat" msgstr "Ignorer denne fejl for dette certifikat." #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "For nylig:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Titel:" #: gajim/data/gui/manage_pep_services_window.ui:13 msgid "PEP Service Configuration" msgstr "PEP Tjeneste Konfigurering" #: gajim/data/gui/manage_pep_services_window.ui:69 msgid "_Configure" msgstr "_Konfigurere" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Lav en ny post" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "Fra:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Emne:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Udfyld formen." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Rum Konfigurering" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "Bytte af punkt i kontaktvinduet" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_OK" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "Sta_tus" #: gajim/data/gui/systray_context_menu.ui:20 msgid "_Start Chat..." msgstr "_Start Samtale..." #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Vis Alle Ventende Hænd_elser" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "Slå lyden af" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Indstillinger" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Afslut" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Til:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "Sen_d" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Send besked" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "Sva_r" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Send et svar til denne besked" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "_Send & Luk" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Send besked og luk vinduet" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "Sæt Aktivitet" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "Sæt en aktivitet" #: gajim/data/gui/change_activity_dialog.ui:337 msgid "Message: " msgstr "Besked:" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Manglende argument \"contact_jid\"" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Manglende argument \"contact_jid\"" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 #, fuzzy msgid "Send a message to the contact" msgstr "Send en fil til en kontakt" #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "%s ikke fundet" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "Ti_lgængelig" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 #, fuzzy msgid "Clear the text window" msgstr "Skjuler vinduet" #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Send en fil til en kontakt" #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 msgid "Command is not supported for zeroconf accounts" msgstr "" #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 msgid "No open audio sessions with the contact" msgstr "" #: gajim/command_system/implementation/standard.py:191 #, fuzzy, python-format msgid "%s is not a valid tone" msgstr "%s er ikke et gyldigt logniveau" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "En tilslutning er ikke tilgængelig" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "Tilslutning er ikke tilgængelig" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Send en fil til en kontakt" #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Ændre dit kælenavn (Ctrl+N)" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 msgid "Invalid nickname" msgstr "Ugyldigt kælenavn" #: gajim/command_system/implementation/standard.py:267 #, fuzzy msgid "Open a private chat window with a specified occupant" msgstr "_Åbn samtale vindue med bruger" #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 #, fuzzy msgid "Nickname not found" msgstr "Kælenavn som skal bruges" #: gajim/command_system/implementation/standard.py:276 msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Spørg før et gruppesamtale vindue/faneblad lukkes." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "Send %s til %s" #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "i _gruppe samtaler" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Du er inviteret til en gruppesamtale." #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Ugyldigt server" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "tilknytning ændret" #: gajim/command_system/implementation/standard.py:365 #, fuzzy msgid "Display names of all group chat occupants" msgstr "%s er ikke navnet på en gruppe samtale." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Fortsat samtale" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Ny Gruppe Samtale" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Tilføj Ny Kontakt" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "Enkel Besked med konto %s" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "Enkel Besked i konto %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Enkel Besked" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Send %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Modtaget %s" #: gajim/gtk/single_message.py:238 #, python-format msgid "Form %s" msgstr "Formular %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "Tilslutning er ikke tilgængelig" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Vær venligst sikker på at du er tilsluttet med \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "SV: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s skrev:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "PEP knude blev ikke fjernet" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "PEP knude %(node)s blev ikke fjernet: %(message)s" #: gajim/gtk/pep_config.py:133 #, fuzzy, python-format msgid "Configure %s" msgstr "_Konfigurere" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "Kan _registreres" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Tilslutning lykkedes" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "Ordbog for sproget %s er ikke tilgængelig" #: gajim/gtk/dialogs.py:83 #, fuzzy, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" "Du må installere en %s ordbog for at bruge stavekontrol, eller vælge et " "andet sprog med stavekontrol sprog indstillingen.\n" "\n" "Egenskaben med at fremhæve stavefejl vil ikke blive brugt" #: gajim/gtk/dialogs.py:440 #, fuzzy, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "" "Du er ved at sende din adgangskode på en usikker forbindelse. Du bør " "installere PyOpenSSL for at forhindre dette. Er du sikker på du vil gøre " "dette?" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "Kælenavnet har ikke tilladte tegn." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "for konto %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Selvsigneret certifikat" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Ændre Adgangskode" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Du må indtaste en adgangskode." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Adgangskoderne er ikke ens" #: gajim/gtk/add_contact.py:30 #, fuzzy msgid "GG Number" msgstr "GG Nummer:" #: gajim/gtk/add_contact.py:31 #, fuzzy msgid "ICQ Number" msgstr "ICQ Nummer:" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Tilføj Kontakt..." #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s MiB" #: gajim/gtk/add_contact.py:235 #, python-format msgid "You must supply the %s of the new contact." msgstr "" #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "Ugyldig Bruger ID" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "Bruger ID'en må ikke indeholde en resource." #: gajim/gtk/add_contact.py:274 msgid "You cannot add yourself to your roster." msgstr "Du kan ikke tilføje dig selv til kontaktvinduet." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Afkoblet" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Kontakten er allerede i kontaktvinduet" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Denne kontakt er allered i dit kontaktvindue" #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "Bruger ID:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "Fejl ved tilføjelse af tjeneste. %s" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "Komponere" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Ikke aktiv" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Ændre status" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "MUC Sendte\n" "Meldinger" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Ny Besked" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Konto" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Gruppe" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "_Vis hændelse i kontaktvindue" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Samtale med " #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Indgående farve på kælenavn." #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Farve på udgående kælenavn." #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "Indgående farve på tekst." #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "Indgående font på tekst." #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "Udgående farve på tekst." #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "Udgående font på tekst." #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Status Besked" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Status Besked" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Farve" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "Frem_hæv stavefejl" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Beskeder" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "_Nulstil til Standard Farver" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Kontakt er ikke Tilsluttet" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Kontakt er Tilsluttet" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "Gajim - %s" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Ugyldig Kælenavn" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Tegn ikke tilladt: %s" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Aktiv" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "Disk Skrivefejl" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s er nu %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, python-format msgid "Error: %s" msgstr "Fejl: %s" #: gajim/gtk/history.py:590 msgid "Error" msgstr "Fejl" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Status er nu: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Status er nu: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "Hvad vil du gøre?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Tilslutter" #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Filoverførsel af %(filename)s fra %(name)s er stoppet." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "Videresend ulæste beskeder" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "En GTK+ Jabber klient" #: gajim/gtk/about.py:48 #, fuzzy, python-format msgid "GTK+ Version: %s" msgstr "GTK+ Version:" #: gajim/gtk/about.py:49 #, fuzzy, python-format msgid "PyGObject Version: %s" msgstr "PyGTK Version:" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Nuværende Programudviklere:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Tidligere Programudviklerer:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 #, fuzzy msgid "we would like to thank all the package maintainers." msgstr "Sidst men ikke mindst, vil vi gerne takke alle pakke vedligeholdere." #: gajim/gtk/about.py:61 #, fuzzy msgid "Thanks" msgstr "Taknemlig" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "Niels Felsted Thorsen " #: gajim/gtk/filechoosers.py:87 msgid "Choose File to Send…" msgstr "Vælg en fil at sende..." #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Vælg Billede" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Alle filer" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Alle filer" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Send _Fil" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Billeder" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Vælg Billede" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Alle filer" #: gajim/gtk/filechoosers.py:142 msgid "Save File as…" msgstr "Gem fil som..." #: gajim/gtk/profile.py:72 #, fuzzy msgid "Retrieving profile…" msgstr "Henter profil..." #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Kontakt Information" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Format: YYYY-MM-DD" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "Information modtaget" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "Uden en tilslutning kan du ikke publicere din kontakt information." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Sender profil..." #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "Information er IKKE publiceret" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "vCard publicering fejlede" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "Der var en fejl under publicering af din personlige information, prøv igen " "senere." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Ugyldig rum" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 msgid "Invalid Nickname" msgstr "Ugyldig Kælenavn" #: gajim/gtk/join_groupchat.py:223 #, fuzzy msgid "Please choose a nickname" msgstr "Opret et nyt tema med dit ønskede navn." #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Forkert uri" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "Dette er ikke en gruppe samtale" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Indstillinger" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Du er ikke tilsluttet til serveren" #: gajim/gtk/mam_preferences.py:102 #, fuzzy msgid "Error received: {}" msgstr "Fejl i modtaget dataform" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Fejl" #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "Aktiveret" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "Ikke aktiveret" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "Boolean" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "Heltal" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Tekst" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Foretrukket Navn" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Værdi" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Type" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Ingen)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Skjult" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "_Værtsnavn:" #: gajim/gtk/server_info.py:193 msgid "Server Software" msgstr "" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Server svarede: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "Bonjour / Zeroconf" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" "Serverløs samtale med automatisk opdagede klienter i et lokalt netværk." #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "Kræver python-dbus." #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "Kræver pybonjour og bonjour SDK kører (%(url)s)" #: gajim/gtk/features.py:56 msgid "Command line" msgstr "Kommandolinje" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "Et script til at kontrollere Gajim via kommandolinjen." #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "Egenskab ikke tilgængelig under Windows." #: gajim/gtk/features.py:61 msgid "OpenPGP message encryption" msgstr "OpenPGP besked kryptering" #: gajim/gtk/features.py:63 msgid "Ability to encrypting chat messages with OpenPGP." msgstr "Understøt kryptering af chat beskeder med OpenPGP" #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "Kræver gpg og python-Gnupg (%(url)s)" #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "Kræver gpg.exe i PATH" #: gajim/gtk/features.py:66 msgid "Password encryption" msgstr "Adgangskodekryptering" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "Adgangskoder kan blive gemt sikkert og ikke bare i ren tekst." #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" "Kræver libsecret og en udbyder (f.eks. GNOME Keyring og KSecretService)" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "På Windows bruges Windows Credential Vault." #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "Stavekontrol" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "Stavekontrol af forfattede beskeder." #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 msgid "Requires Gspell" msgstr "Kræver Gspell" #: gajim/gtk/features.py:76 msgid "Automatic status" msgstr "Automatisk status" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "Evnen til at måle tomgangs tid, for at kunne sætte automatisk status." #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "Biblioteket libxss kræves" #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "Kræver python2.5." #: gajim/gtk/features.py:81 msgid "RST Generator" msgstr "RST Generator" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" "Generer XHTML uddata fra RST kode (se http://docutils.sourceforge.net/docs/" "ref/rst/restructuredtext.html)." #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "Kræver python-docutils." #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "Lyd / Billede" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "Understøtter start af lyd og billede chat." #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 #, fuzzy msgid "Requires gir1.2-gupnpigd-1.0." msgstr "Kræver python-gnome2." #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "Tilgængelig" #: gajim/gtk/features.py:109 msgid "Feature" msgstr "Egenskab" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "Privatlivs Liste %s" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "Privatlivs Liste for %s" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "" "Rækkefølge: %(order)s, handling: %(action)s, type: %(type)s, værdi: %(value)s" #: gajim/gtk/privacy_list.py:152 #, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Rækkefølge: %(order)s, handling: %(action)s" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "Rediger en regel" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "Tilføj en regel" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "Privatlivs Liste for %s" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "Ugyldig Listenavn" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "Du må indtaste et navn for at skabe en privatlivs liste." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Kontoen er blevet tilføjet med succes" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Du kan sætte avancerede konto indstillinger ved at trykke Avanceret knappen, " "eller senere ved at vælge kontoens menupunkt under Rediger menuen fra " "hovedvinduet." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Din nye konto er blevet oprettet med succes" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Ugyldigt brugernavn" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Du må give et brugernavn for at konfigurere denne konto." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 msgid "Invalid server" msgstr "Ugyldigt server" #: gajim/gtk/account_wizard.py:255 msgid "Please provide a server on which you want to register." msgstr "Anfør en server som du vil registrere dig ved." #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Ugyldig indgang" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "Personlig port må være et port nummer." #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" "Sikkerhedsadvarsel\n" "\n" "Pålideligheden af %(hostname)s SSL certifikat kan være ugyldig\n" "SSL Fejl: %(error)s\n" "Vil du stadig prøve at forbinde til denne server?" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "Under oprettelsen af kontoen opstod der en fejl" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Kontonavnet er i brug" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Du har allered en konto med dette navn." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Filter:" #: gajim/gtk/xml_console.py:79 #, fuzzy msgid "XML Input" msgstr "XML Inddata" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Ugyldig Fil" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "Standard" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "status besked Titel" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "status besked tekst" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Log ind igen nu?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "" "Hvis du vil at alle ændringerne skal træde i kraft nu, må du logge ind igen." #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "Du har en åben samtale med kontonavnet %s" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "" "Alle samtale og gruppesamtale vinduer vil blive lukket. Vil du fortsætte?" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Tilføj Kontakt..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "_Kan fjernes" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Flettede konti" #: gajim/gtk/accounts.py:549 #, fuzzy msgid "Use PGP Agent" msgstr "Brug G_PG Agenten" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Tilslutning" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Inviter _Kontakter" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Selvsigneret certifikat" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Tildel OpenPGP Nøgle" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "T_ilslut når Gajim startes" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Tilslut automatisk hvis tilslutningen tabes" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Gem konversations _logger for alle kontakter" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "_Send Server Besked..." #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Status For Alle" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Ændrer status for kontoen eller konti" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Beskeder" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Brug fil transport proxy" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "br_ug HTTP__PROXY miljøvariablen" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Proxy:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "Ad_var mig før jeg bruger en usikker forbindelse" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Send hold-i-live pakker" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "Priori_tet:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Ændrer status for kontoen eller konti" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Fornavn:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Efternavn:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Ny E-post" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "_Tilpas til status" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Aktiver" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Port:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Tilslutning" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Selvsigneret certifikat" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Selvsigneret certifikat" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Gem adgangskode" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "Føl_elsesikoner:" #: gajim/gtk/bookmarks.py:72 msgid "?print_status:All" msgstr "?print_status:Alle" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "Gå kun ind og ud" #: gajim/gtk/bookmarks.py:74 msgid "?print_status:None" msgstr "?print_status:Ingen" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "Ny Gruppe Samtale" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Dette bogmærke er ugyldigt" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "" "Fyld ud server og rum tekstindtastningsfelterne eller fjern dette bogmærke." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 msgid "Character not allowed" msgstr "Tegn ikke tilladt: %s" #: gajim/gtk/bookmarks.py:367 msgid "Invalid room" msgstr "Ugyldig rum" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Filen er tom" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 #, fuzzy msgid "Archive is malformed" msgstr "Tjeneste sendte malformeret data" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Denne fil eksisterer allerede" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Udeluk %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Tilslutning fejlede" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Rum Konfigurering" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Jabber IM Klient" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "En GTK+ Jabber klient" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Vis Alle Ventende Hænd_elser" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Egenskaber" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 #, fuzzy msgid "Automatic spell-checking for your messages" msgstr "Stavekontrol af forfattede beskeder." #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Opdag Tjenester med kontoen %s" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "_Log status ændringer hos kontakter" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Gruppesamtaler" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "For nylig:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Tilslutning fejlede" #~ msgid "Stopped" #~ msgstr "Stoppet" #~ msgid "Error reading file:" #~ msgstr "Fejl ved læsning af fil:" #~ msgid "Error parsing file:" #~ msgstr "Fejl ved fortolkning af fil:" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Filoverførsel Fejl" #, fuzzy #~ msgid "XML console interface" #~ msgstr "XML Konsol" #~ msgid "" #~ "A list of modp groups to use in a Diffie-Hellman, highest preference " #~ "first, separated by commas. Valid groups are 1, 2, 5, 14, 15, 16, 17 and " #~ "18. Higher numbers are more secure, but take longer to calculate when you " #~ "start a session." #~ msgstr "" #~ "En liste af modp grupper til at bruges i en Diffie-Hellman, højest " #~ "præference først, adskilt af kommaer. Gyldige grupper er 1, 2, 5, 14, 15, " #~ "16, 17 og 18. Højere tal er mere sikre, men tager længere tid at udregne " #~ "når du starter en session." #~ msgid "_Verify" #~ msgstr "Efterprø_v" #~ msgid "(ESession info)" #~ msgstr "(ESession info)" #~ msgid "Save as Preset..." #~ msgstr "Gem som Forvalgt..." #~ msgid "Always use this nickname when there is a conflict" #~ msgstr "Altid brug dette kælenavn når der er en konflikt" #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "Jabberd1.4 kan ikke lide sha information når man deltager i en " #~ "adgangskode beskyttet gruppesamtale. Sæt dette valg til Falsk for at " #~ "stoppe med at sende sha information i gruppesamtaler." #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Hvis valgt vil Gajim erstatte tekst smileys som denne ':)' med den " #~ "tilsvarende animerede eller statiske grafiske følelsesikon" #, fuzzy #~ msgid "_Emoticons" #~ msgstr "Føl_elsesikoner:" #~ msgid "_Highlight misspelled words" #~ msgstr "Frem_hæv stavefejl" #, fuzzy #~ msgid "Notify by icon when your messages are received" #~ msgstr "Lyd som spilles når en hvilken som helst MUC besked ankommer." #, fuzzy #~ msgid "T_heme" #~ msgstr "T_ema:" #~ msgid "Themes" #~ msgstr "Temaer" #, fuzzy #~ msgid "Presence" #~ msgstr "_Tilstedeværelse" #~ msgid "Emoticons disabled" #~ msgstr "Følelsesikoner er ikke aktiveret" #, fuzzy #~ msgid "" #~ "Your configured emoticons theme could not be loaded. See the log for more " #~ "details." #~ msgstr "" #~ "Dit konfigurerede følelsesikon tema blev ikke fundet, så følelsesikoner " #~ "er blevet deaktiveret." #~ msgid "You cannot make changes to the default theme" #~ msgstr "Du kan ikke lave ændringer til standard temaet" #, fuzzy #~ msgid "Please create a new clean theme." #~ msgstr "Opret et nyt tema med dit ønskede navn." #~ msgid "theme name" #~ msgstr "Tema navn" #~ msgid "You cannot delete your current theme" #~ msgstr "Du kan ikke slette det nuværende tema" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Ny Besked fra %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Ny Privat Besked fra gruppe samtale %s" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s: %(message)s" #~ msgid "Messaged by %(nickname)s" #~ msgstr "Besked fra %(nickname)s" #~ msgid "Status message text color." #~ msgstr "Status besked farve på tekst." #~ msgid "Incoming nickname font." #~ msgstr "Udgående farve på kælenavn." #~ msgid "Outgoing nickname font." #~ msgstr "Udgående font på kælenavn." #~ msgid "Status message text font." #~ msgstr "Status besked font på tekst" #~ msgid "Background color of contacts when they just signed in." #~ msgstr "Baggrundsfarve på kontakter når de netop har tilsluttet sig." #~ msgid "Background color of contacts when they just signed out." #~ msgstr "Baggrundsfarve på kontakter når de netop har afbrudt tilslutningen." #~ msgid "green" #~ msgstr "grøn" #~ msgid "grocery" #~ msgstr "købmandsvarer" #~ msgid "human" #~ msgstr "menneske" #~ msgid "marine" #~ msgstr "marint" #, fuzzy #~ msgid "Contact row" #~ msgstr "Kontakt" #~ msgid "Gajim Themes Customization" #~ msgstr "Gajim Tema Tilpasning" #~ msgid "Text _color:" #~ msgstr "Tekst _farve:" #~ msgid "_Background:" #~ msgstr "_Baggrund:" #~ msgid "Text _font:" #~ msgstr "Tekst _font:" #~ msgid "Font style:" #~ msgstr "Font stil:" #~ msgid "Paused" #~ msgstr "Sat på pause" #~ msgid "Gone" #~ msgstr "Borte" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "MUC\n" #~ "Beskeder" #~ msgid "Chatstate Tab Colors" #~ msgstr "Samtalestatus Fane Farver" #, fuzzy #~ msgid "Chat message" #~ msgstr "Samtale besked:" #~ msgid "Use system _default" #~ msgstr "Brug system stan_dard" #~ msgid "Font" #~ msgstr "Skrifttype" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Kontakt navn" #, fuzzy #~ msgid "Contact's message" #~ msgstr "Samtale besked:" #, fuzzy #~ msgid "_Status message" #~ msgstr "_Status besked:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Gruppe Samtale Besked Fremhævning" #, fuzzy #~ msgid "Your nickname" #~ msgstr "Kælenavn:" #, fuzzy #~ msgid "Your message" #~ msgstr "Fejl besked: %s" #, fuzzy #~ msgid "_URL highlight" #~ msgstr "_URL fremhævning:" #~ msgid "Chat Line Colors" #~ msgstr "Samtalelinie Farver" #~ msgid "Jabber ID:" #~ msgstr "Jabber ID:" #~ msgid "Resource:" #~ msgstr "Ressource:" #~ msgid "Status:" #~ msgstr "Status:" #~ msgid "Contact time:" #~ msgstr "Kontakt tid:" #~ msgid "Ask:" #~ msgstr "Spørg:" #~ msgid "Subscription:" #~ msgstr "Abonnering:" #~ msgid "Name:" #~ msgstr "Navn:" #~ msgid "Nickname:" #~ msgstr "Kælenavn:" #~ msgid "Street:" #~ msgstr "Gade:" #~ msgid "City:" #~ msgstr "By:" #~ msgid "State:" #~ msgstr "Stat:" #~ msgid "Extra Address:" #~ msgstr "Ekstra Adresse:" #~ msgid "Postal Code:" #~ msgstr "Postnummer:" #~ msgid "Country:" #~ msgstr "Land:" #~ msgid "Homepage:" #~ msgstr "Hjemmeside:" #~ msgid "E-Mail:" #~ msgstr "E-post:" #~ msgid "Phone No.:" #~ msgstr "Telefonnr.:" #~ msgid "Birthday:" #~ msgstr "Fødselsdag:" #~ msgid "Family:" #~ msgstr "Efternavn:" #~ msgid "Middle:" #~ msgstr "Mellemnavn:" #~ msgid "Prefix:" #~ msgstr "Titel:" #~ msgid "Given:" #~ msgstr "Fornavn:" #~ msgid "Suffix:" #~ msgstr "Endetillæg:" #~ msgid "Full Name" #~ msgstr "Fuldt Navn" #~ msgid "Company:" #~ msgstr "Firma:" #~ msgid "Department:" #~ msgstr "Afdeling:" #~ msgid "Position:" #~ msgstr "Stilling:" #~ msgid "Role:" #~ msgstr "Rolle:" #~ msgid "- messages will be logged" #~ msgstr "- beskeder vil blive logget" #~ msgid "- messages will not be logged" #~ msgstr "- beskeder vil ikke blive logget" #~ msgid "Edit %s" #~ msgstr "Rediger %s" #~ msgid "Register to %s" #~ msgstr "Registrer til %s" #~ msgid "Conversation History with %s" #~ msgstr "Konversations Historik med %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Kontakt med \"%s\" kan ikke blive etableret" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "" #~ "Registrerings information for transporten %s har ikke ankommet i tide" #~ msgid "Register to" #~ msgstr "Registrer til" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Kontakt navn" #~ msgid "Search:" #~ msgstr "Søg:" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Du kan kun ændre din adgangskode hvis du er tilsluttet." #~ msgid "Invalid password" #~ msgstr "Ugyldig adgangskode" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "Adgangskoderene i de to tekstindtastningsfelter må være identiske." #~ msgid "Enter new password:" #~ msgstr "Skriv en ny adgangskode:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Skriv adgangskoden igen for at bekræfte:" #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "JID %s er ikke RFC føjelig. Den vil ikke blive tilføjet til dit " #~ "kontaktvindue. Brug kontaktvindue håndterings redskaber som http://jru." #~ "jabberstudio.org/ til at fjerne det." #~ msgid "unsubscribe request from %s" #~ msgstr "forespørsel om ophør på abonnement fra %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Bliv automatisk med" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Hjemmeside:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Konfigurere" #~ msgid "Manage Bookmarks" #~ msgstr "Håndter Bogmærker" #~ msgid "_Nickname:" #~ msgstr "_Kælenavn:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "Hvis valgt vil Gajim deltage i denne gruppe samtale ved start" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Skriv status:" #, fuzzy #~ msgid "Add JID" #~ msgstr "Jabber ID" #, fuzzy #~ msgid "Preference:" #~ msgstr "Indstillinger" #, fuzzy #~ msgid "Preference" #~ msgstr "Indstillinger" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "" #~ "Fyld ind data for den kontakt som du vil tilføje kontoen med navnet %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Fyld ind data for den kontakt som du vil tilføje" #, fuzzy #~ msgid "Recently" #~ msgstr "For nylig:" #~ msgid "Add New Contact" #~ msgstr "Tilføj Ny Kontakt" #~ msgid "_User ID:" #~ msgstr "_Bruger ID:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "Bruger ID:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Kælenavn" #~ msgid "Personal Information" #~ msgstr "Personlig Information" #~ msgid "Avatar:" #~ msgstr "Avatar:" #~ msgid "Click to set your avatar" #~ msgstr "Tryk for at se din avatar" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "Fjern Gruppen" #~ msgid "Not fetched because of invisible status" #~ msgstr "Ikke hentet på grund af usynlig status" #~ msgid "Please wait..." #~ msgstr "Vent venligst..." #~ msgid "" #~ "When negotiating an encrypted session, should Gajim assume you want your " #~ "messages to be logged?" #~ msgstr "" #~ "Ved forhandling af en krypteret session, skal Gajim da antage at du vil " #~ "have dine beskeder logget?" #~ msgid "Log _encrypted chat session" #~ msgstr "Log krypt_eret samtale session" #, fuzzy #~ msgid "" #~ "If checked, Gajim will keep logs for encrypted messages. Please note that " #~ "when using end-to-end encryption the remote party has to agree on " #~ "logging, else the messages will not be logged." #~ msgstr "" #~ "Hvis valgt vil Gajim gemme en log for krypterede beskeder. Vær venligst " #~ "opmærksom på når der bruges E2E kryptering må den anden i samtalen " #~ "godkende evt. logning, ellers vil samtalen i blive logget." #~ msgid "Yahoo! Address:" #~ msgstr "Yahoo! Adresse:" #~ msgid "Forward unread messages" #~ msgstr "Videresend ulæste beskeder" #~ msgid "All unread messages have been forwarded." #~ msgstr "Alle ulæste beskeder er blevet videresendt." #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "Videresend ulæste beskeder" #~ msgid "AIM Address:" #~ msgstr "AIM Adresse:" #~ msgid "MSN Address:" #~ msgstr "MSN Adresse:" #~ msgid "Confirm these session options" #~ msgstr "Bekræft disse sessions indstillinger" #, fuzzy #~ msgid "" #~ "The remote client wants to negotiate a session with these features:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Are these options acceptable?" #~ msgstr "" #~ "Den fjerne klient vil forhandle en session med disse egenskaber:\n" #~ "\n" #~ "\t%s\n" #~ "\n" #~ "\tKan disse indstillinger godkendes?" #~ msgid "" #~ "The remote client selected these options:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Continue with the session?" #~ msgstr "" #~ "Den fjerne klient valgte disse indstillinger:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Fortsæt med sessionen?" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "Er OpenPGP aktiveret for denne kontakt?" #~ msgid "End to End message encryption" #~ msgstr "Ende til Ende besked kryptering" #~ msgid "Encrypting chat messages." #~ msgstr "Krypterer samtale beskeder." #~ msgid "Requires python-crypto." #~ msgstr "Kræver python-crypto." #~ msgid "Session negotiation cancelled" #~ msgstr "Session forhandling annulleret" #, fuzzy #~ msgid "This session WILL NOT be archived on server" #~ msgstr "Session VIL IKKE blive logget" #~ msgid "This session is encrypted" #~ msgstr "Denne session er krypteret" #~ msgid " and WILL be logged" #~ msgstr " og VIL blive logget" #~ msgid " and WILL NOT be logged" #~ msgstr " og VIL IKKE blive logget" #~ msgid "" #~ "Remote contact's identity not verified. Click the shield button for more " #~ "details." #~ msgstr "" #~ "Kontaktens identitet er ikke verificeret Tryk på skjold knappen for flere " #~ "detaljer." #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "GPG kryptering ikke aktiveret" #~ msgid "" #~ "Unable to decrypt message from %s\n" #~ "It may have been tampered with." #~ msgstr "" #~ "Ikke i stand til at dekryptere beskeden fra %s\n" #~ "Det er mulig den er blevet forfalsket." #~ msgid "Unable to decrypt message" #~ msgstr "Ikke i stand til at dekryptere beskeden" #~ msgid "Enable ESessions encryption for this account." #~ msgstr "Aktiver ESessions kryptering for denne konto." #~ msgid "Should Gajim automatically start an encrypted session when possible?" #~ msgstr "" #~ "Skal Gajim automatisk starte en krypteret session når det er muligt?" #~ msgid "" #~ "[This is part of an encrypted session. If you see this message, something " #~ "went wrong.]" #~ msgstr "" #~ "[Dette er en del af en krypteret session. Hvis du ser denne besked gik " #~ "noget galt.]" #~ msgid "Requires python-avahi." #~ msgstr "Kræver python-avahi." #~ msgid "_Send" #~ msgstr "_Send" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Gem Billede som..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Eksporter Historik Log..." #~ msgid "Choose Image" #~ msgstr "Vælg Billede" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Vælg en Fil at Sende..." #~ msgid "When %s becomes:" #~ msgstr "Når %s bliver:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Tilføj Speciel Påmindelse for %s" #, fuzzy #~ msgid "" #~ "It seems the SSL certificate of account %(account)s has changed and is " #~ "not valid or your connection is being compromised.\n" #~ "\n" #~ "Old SHA-1 fingerprint: %(old_sha1)s\n" #~ "Old SHA-256 fingerprint: %(old_sha256)s\n" #~ "\n" #~ "New SHA-1 fingerprint: %(new_sha1)s\n" #~ "New SHA-256 fingerprint: %(new_sha256)s\n" #~ "\n" #~ "Do you still want to connect and update the fingerprint of the " #~ "certificate?" #~ msgstr "" #~ "Det ser ud til at SSL certifikatet for kontoen %(account)s er blevet " #~ "ændret eller din forbindelse er blevet kompromitteret\n" #~ "Gammelt fingeraftryk: %(old)s\n" #~ "Nyt fingeraftryk: %(new)s\n" #~ "\n" #~ "Vil du stadig forbinde og opdatere fingeraftrykket for certifikatet?" #, fuzzy #~ msgid "" #~ "The authenticity of the %s certificate could be invalid.\n" #~ "The certificate does not cover this domain." #~ msgstr "Ægtheden af %s certifikatet kan være ugyldig." #~ msgid "Unable to load idle module" #~ msgstr "Ikke i stand til at indlæse tomgangs modulet" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s er et katalog men burde være en fil" #~ msgid "creating logs database" #~ msgstr "opretter log database" #, fuzzy #~ msgid "creating cache database" #~ msgstr "opretter log database" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Send %s til %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Gajim Loghistorie Håndterer" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Omdøb Konto" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Send en Enkel _Besked..." #, fuzzy #~ msgid "We received an error: {}" #~ msgstr "Tjeneste returnerede en fejl." #~ msgid "E2E encryption disabled" #~ msgstr "E2E kryptering ikke aktiveret" #, fuzzy #~ msgid "" #~ "Add this certificate to the list of trusted certificates.\n" #~ "SHA-1 fingerprint of the certificate:\n" #~ "%(sha1)s\n" #~ "SHA256 fingerprint of the certificate:\n" #~ "%(sha256)s" #~ msgstr "" #~ "Tilføj dette certifikat til listen af certifikater du har tillid til.\n" #~ "Certifikatets SHA1 fingeraftryk:\n" #~ "%s" #~ msgid "uri" #~ msgstr "uri" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Hænger" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Hænger" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Tilslutning fejlede" #~ msgid "cyan" #~ msgstr "cyan" #~ msgid "migrating logs database to indices" #~ msgstr "flytter log databasen til flere indeks" #, fuzzy #~ msgid "Send File..." #~ msgstr "Send _Fil..." #, fuzzy #~ msgid "HTTP File Upload not supported by your server" #~ msgstr "Metakontakt lagring er ikke understøttet af din server" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Filoverførsler" #~ msgid "" #~ "Your configured emoticons theme has not been found, so emoticons have " #~ "been disabled." #~ msgstr "" #~ "Dit konfigurerede følelsesikon tema blev ikke fundet, så følelsesikoner " #~ "er blevet deaktiveret." #~ msgid "Shows or hides the roster window" #~ msgstr "Viser eller gemmer kontaktvinduet" #~ msgid "Shows or hides the ipython window" #~ msgstr "Viser eller gemmer ipython vinduet" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "XMPP konto %s@%s" #, fuzzy #~ msgid "Exception" #~ msgstr "Beskrivelse" #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "" #~ "nogen@etsted.com vil gerne at du tilføjer nogen kontakter i " #~ "dit kontaktvindue." #~ msgid "" #~ "Ordered list (space separated) of connection type to try. Can contain " #~ "tls, ssl or plain" #~ msgstr "" #~ "En ordnet liste (adskilt af mellemrum) af forbindelses typer som skal " #~ "prøves. Kan indeholde tls, ssl eller plain" #~ msgid "_Actions" #~ msgstr "_Handlinger" #, fuzzy #~ msgid "Requires upower and python-dbus." #~ msgstr "Kræver python-dbus." #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Start Samtale..." #~ msgid "You are already in group chat %s" #~ msgstr "Du er allerede i en gruppe samtale %s" #~ msgid "Join Group Chat with account %s" #~ msgstr "Deltag i Gruppe Samtale med kontoen %s" #~ msgid "Invalid Account" #~ msgstr "Ugyldig Konto" #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "" #~ "Du må vælge en konto som du vil bruge til at tilslutte gruppe samtalen " #~ "med." #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "Gruppe samtale Jabber ID'en indeholder ikke tilladte tegn." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "Gruppe samtale Jabber ID'en indeholder ikke tilladte tegn." #~ msgid "Start Chat with account %s" #~ msgstr "Start en samtale med konto %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Udfyld kælenavnet eller Jabber ID'en for den kontakt du vil sende\n" #~ "en besked til:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Ugyldigt Jabber ID" #~ msgid "Unable to parse \"%s\"." #~ msgstr "Kan ikke fortolke \"%s\"." #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "Vis samtale vinduet så du kan sende beskeder til en kontakt" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "Kontaktens JID som du vil samtale med" #~ msgid "message content. The account must be specified or \"\"" #~ msgstr "besked indhold. Kontoen må specificeres eller \"\"" #~ msgid "Adds contact to roster" #~ msgstr "Tilføjer kontakt til kontaktvinduet" #~ msgid "jid" #~ msgstr "jid" #~ msgid "Adds new contact to this account" #~ msgstr "Tilføjer ny kontakt til denne konto" #~ msgid "Opens 'Start Chat' dialog" #~ msgstr "Åbner 'Start Samtale' vinduet" #~ msgid "Starts chat, using this account" #~ msgstr "Starter en samtale med denne konto" #, fuzzy #~ msgid "Handle a xmpp:/ URI" #~ msgstr "Håndter en xmpp:/ uri" #~ msgid "URI to handle" #~ msgstr "URI som skal håndteres" #~ msgid "Account in which you want to handle it" #~ msgstr "Den konto som du vil håndtere det med" #~ msgid "Message content" #~ msgstr "Besked indhold" #~ msgid "Join a MUC room" #~ msgstr "Deltag i et MUC rum" #~ msgid "Nickname to use" #~ msgstr "Kælenavn som skal bruges" #~ msgid "Password to enter the room" #~ msgstr "Adgangskode for at slutte sig til rummet" #~ msgid "Account from which you want to enter the room" #~ msgstr "Vælg den konto som du vil slutte dig til rummet med" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Forkert uri" #~ msgid "Nickname:" #~ msgstr "Kælenavn:" #~ msgid "Server:" #~ msgstr "Server:" #~ msgid "Password:" #~ msgstr "Adgangskode:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Bliv med i dette rum automatisk når jeg tilsutter" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Gennemse" #, fuzzy #~ msgid "Requires libgtkspell and libenchant." #~ msgstr "Kræver libgtkspell." #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "Network-manager" #~ msgid "Autodetection of network status." #~ msgstr "Automatisk opdagelse af netværksstatus." #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Kræver gnome-network-manager og python-dbus." #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "Egenskab ikke tilgængelig under Windows." #~ msgid "This contact does not support file transfer." #~ msgstr "Denne kontakt understøtter ikke fil overførsler." #, fuzzy #~ msgid "You need to know the real JID of the contact to send them a file." #~ msgstr "" #~ "Du trænger den rigtige JID fra kontakten for at kunne sende ham eller " #~ "hende en fil." #~ msgid "" #~ "You have to install %s dictionary to use spellchecking, or choose another " #~ "language by setting the speller_language option." #~ msgstr "" #~ "For at bruge stavekontrollen må du installer en %s ordbog, eller vælge et " #~ "andet sprog ved indstillingen for sprog til stavekontrollen." #~ msgid "Hides the buttons in chat windows." #~ msgstr "Skjuler knapperne i samtale vinduer." #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Ændre dit kælenavn (Ctrl+N)" #~ msgid "Change the room's subject (Alt+T)" #~ msgstr "Ændre emne for rummet (Alt+T)" #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "Bogmærk dette rom (Ctrl+B)" #~ msgid "Browse the chat history (Ctrl+H)" #~ msgstr "Gennemse samtale historik (Ctrl+H)" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Vis en menu med avancerede funktioner (Alt+A)" #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Tilføj denne kontakt til kontaktvinduet (Ctrl+D)" #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "Inviter kontakter til samtalen (Ctrl+G)" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Vis kontaktens profil (Ctrl+I)" #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Vis kontaktens profil (Ctrl+I)" #~ msgid "Ma_ke message windows compact" #~ msgstr "Gør samtalevinduer _kompakte" #~ msgid "Hide all buttons in chat windows" #~ msgstr "Skjul alle knapperne i samtale vinduer." #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "Hvis Sandt, vil Gajim spørge for en avatar for hver kontakt som ikke " #~ "havde en avatar sidste gang eller har en gemt som er for gammel." #~ msgid "Disk Write Error" #~ msgstr "Disk skrivefejl" #~ msgid "Set Custom _Avatar..." #~ msgstr "Angiv Personlig _Avatar..." #, fuzzy #~ msgid "SSL certificate validation" #~ msgstr "SSL certifikat validering" #~ msgid "" #~ "A library used to validate server certificates to ensure a secure " #~ "connection." #~ msgstr "" #~ "Et bibliotek brugt til at validere server certifikater for at sikre en " #~ "sikker forbindelse." #, fuzzy #~ msgid "Requires python-pyopenssl > 0.12 and pyasn1." #~ msgstr "Kræver python-pyopenssl." #, fuzzy #~ msgid "?CLI:room" #~ msgstr "rum" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "kælenavn" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "adgangskode" #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "" #~ "Brug D-Bus og Påmindelses-dæmonen (Notification-Daemon) til at vise " #~ "påmindelser" #~ msgid "Notification" #~ msgstr "Påmindelse" #~ msgid "Passive popups notifying for new events." #~ msgstr "Passive pop op vinduer som påminder om nye hændelser." #~ msgid "" #~ "Requires python-notify or instead python-dbus in conjunction with " #~ "notification-daemon." #~ msgstr "" #~ "Kræver python-notify eller python-dbus i forbindelse med påmindelses-" #~ "dæmonen." #~ msgid "Ignore" #~ msgstr "Ignorer" #~ msgid "_Open Gmail Inbox" #~ msgstr "_Åbn Gmail Indboks" #~ msgid "Notify on new _GMail email" #~ msgstr "Påmind mig ved ny _GMail e-post" #~ msgid "" #~ "If checked, Gajim will show a notification when a new e-mail is received " #~ "via GMail" #~ msgstr "" #~ "Hvis valgt vil Gajim vise en påmindelse når en ny e-post er modtaget via " #~ "Gmail" #~ msgid "Display _extra email details" #~ msgstr "Vis _ekstra e-post detaljer" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Hvis valgt vil Gajim også inkludere information om senderen af den nye e-" #~ "post" #~ msgid "GMail Options" #~ msgstr "GMail Indstillinger" #, fuzzy #~ msgid "20" #~ msgstr "0" #~ msgid "GMail Email Received" #~ msgstr "GMail E-post Modtaget" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Ny e-post på %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "Du har %d ny e-post samtale" #~ msgstr[1] "Du har %d nye e-post samtaler" #~ msgid "" #~ "\n" #~ "\n" #~ "From: %(from_address)s\n" #~ "Subject: %(subject)s\n" #~ "%(snippet)s" #~ msgstr "" #~ "\n" #~ "\n" #~ "Fra: %(from_address)s\n" #~ "Emne: %(subject)s\n" #~ "%(snippet)s" #~ msgid "Re_name" #~ msgstr "Om_døb" #~ msgid "Resour_ce:" #~ msgstr "Ressour_ce:" #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "Ressource bliver sendt til Jabber serveren for at separere den samme JID " #~ "i to eller flere dele afhængig af antallet klienter som tilsluttet til " #~ "den samme server med den samme konto. Det vil sige du kan være tilsluttet " #~ "med denne samme konto med ressourcerne 'Hjemme' og 'Arbejde' på den samme " #~ "tid. Ressourcen med den højeste prioritet vil få hændelserne. (se under)" #~ msgid "A_djust to status" #~ msgstr "_Tilpas til status" #~ msgid "Priority will change automatically according to your status." #~ msgstr "Prioritet vil automatisk ændres ifølge din status." #~ msgid "Anonymous authentication" #~ msgstr "Anonym godkendelse" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "Prioritet er brugt i Jabber for at bestemme hvem som får hændelser fra " #~ "jabber serveren når to eller flere klienter er tilsluttet med den samme " #~ "konto: Klienten med den højeste prioritet får hændelserne" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Synkroniser kontakter" #~ msgid "Click to request authorization to all contacts of another account" #~ msgstr "" #~ "Tryk for at forespørge om autorisering for alle kontakter af en anden " #~ "konto" #~ msgid "Chan_ge Password" #~ msgstr "Ænd_re Adgangskode" #~ msgid "Click to change account's password" #~ msgstr "Tryk for at ændre kontoens adgangskode" #~ msgid "Administration operations" #~ msgstr "Administrative handlinger" #, fuzzy #~ msgid "Browse..." #~ msgstr "_Gennemse" #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "Certifikatet afvist" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Hvis valgt vil Gajim vil Gajim, når den startes, automatisk tilslutte sig " #~ "til jabber med denne konto" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Synkroniser kontakter" #~ msgid "Synch_ronize account status with global status" #~ msgstr "Synk_roniser konto status med global status" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Hvis valgt vil en hvilket som helst ændring til den globale status " #~ "(håndteret med kombinationsfeltet i bunden af kontaktvinduet) ændre " #~ "status på denne konto" #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Hvis valgt vil Gajim rundsende flere IP adresser udover din egen IP " #~ "adresse, filoverførsler har en større chance for at lykkes." #~ msgid "Proxy" #~ msgstr "Proxy" #~ msgid "" #~ "Check this so Gajim will ask you before sending your password over an " #~ "insecure connection." #~ msgstr "" #~ "Hvis valgt vil Gajim spørge dig før din adgangskode bliver sendt over en " #~ "usikker forbindelse." #~ msgid "Send _keep-alive packets" #~ msgstr "Send hold-i-live pa_kker" #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Hvis valgt vil Gajim sende hold-i-live pakker for at forhindre at " #~ "tilslutningen afbrydes pga et tidsudløb" #~ msgid "Use cust_om hostname/port" #~ msgstr "Brug tilpasset værtsnavn/p_ort" #~ msgid "_Hostname: " #~ msgstr "_Værtsnavn:" #~ msgid "_Port: " #~ msgstr "_Port: " #~ msgid "No key selected" #~ msgstr "Ingen nøgle er valgt" #~ msgid "Choose _Key..." #~ msgstr "Vælg _Nøgle..." #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "" #~ "Hvis valgt vil Gajim hente adgangskoden fra en GPG agent som seahorse" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #~ msgid "_Edit Personal Information..." #~ msgstr "R_ediger Personlig Information..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Information om dig, som er gemt på serveren" #~ msgid "Personal Information" #~ msgstr "Personlig Information" #~ msgid "Co_nnect on Gajim startup" #~ msgstr "Tilslut _når Gajim startes" #~ msgid "Synchroni_ze account status with global status" #~ msgstr "Synk_roniser konto status med global status" #~ msgid "Use cust_om port:" #~ msgstr "Brug pers_onlig port:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Hvis den standard port der bruges til indkomne beskeder ikke passer dig " #~ "eller\n" #~ "din opsætning kan du vælge en anden her.\n" #~ "Du bør også ændre opsætning tilsvarende på en evt. brandmur." #~ msgid "Mer_ge accounts" #~ msgstr "Fle_t konti" #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "Det er ikke muligt at bruge OpenPGP på denne computer" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "For at ændre kontonavnet må du afbryde din tilslutning" #~ msgid "To change the account name, you must read all pending events." #~ msgstr "For at ændre kontonavnet må du læse alle ventende hændelser." #~ msgid "Account Name Already Used" #~ msgstr "Kontonavnet er allerede i brug" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "" #~ "Dette navn er allerede brugt til en af dine andre konti. Vælg venligst et " #~ "andet navn." #~ msgid "Invalid account name" #~ msgstr "Ugyldigt kontonavn" #~ msgid "Account name cannot be empty." #~ msgstr "Kontonavnet kan ikke være tomt." #~ msgid "Account name cannot contain spaces." #~ msgstr "Kontonavnet kan ikke indeholde mellemrom." #~ msgid "Enter a new name for account %s" #~ msgstr "Indtast et nyt navn for kontoen %s" #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "Et Jabber ID må være på formen \"bruger@servernavn\"." #~ msgid "No such account available" #~ msgstr "Ingen konto ved det navn er tilgængelig" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "" #~ "Du må oprette en konto før du kan redigere din personlige information." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "" #~ "Uden en tilslutning kan du ikke redigere din personlige information." #, fuzzy #~ msgid "Your server does not have vCard support" #~ msgstr "Din server understøtter ikke Vcard" #~ msgid "Your server can't save your personal information." #~ msgstr "Din server kan ikke gemme din personlige information." #~ msgid "Account Local already exists." #~ msgstr "Den Lokale Konto eksisterer allerede." #~ msgid "Please rename or remove it before enabling link-local messaging." #~ msgstr "Omdøb eller fjern den før du aktiverer link-local beskeder." #~ msgid "THANKS:" #~ msgstr "TAK:" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "" #~ "Kunne ikke skrive til %s. Sessions håndterings understøttelse vil ikke " #~ "virke" #~ msgid "Jabber Traffic" #~ msgstr "Jabber Trafik" #~ msgid "_Enable" #~ msgstr "Aktiv_er" #, fuzzy #~ msgid "Filter" #~ msgstr "Skrifttype" #~ msgid "_IQ" #~ msgstr "_IQ" #~ msgid "Info/Query" #~ msgstr "Information/Forespørgsel (Info/Query)" #~ msgid "_Message" #~ msgstr "_Besked" #~ msgid "XML Input" #~ msgstr "XML Inddata" #~ msgid "XML Console for %s" #~ msgstr "XML Konsol for %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "XML Konsol for %s" #, fuzzy #~ msgid "" #~ "Request offline status messages from all contacts upon connecting. " #~ "WARNING: This causes a lot of requests to be sent!" #~ msgstr "" #~ "Spørg om offline status beskeder til alle offline kontakter når en " #~ "forbindelse til en konto bliver etableret. ADVARSEL: Dette forårsager en " #~ "masse forespørgsler!" #~ msgid "Last status: %s" #~ msgstr "Sidste status: %s" #~ msgid " since %s" #~ msgstr " siden %s" #~ msgid "since %s" #~ msgstr "siden %s" #, fuzzy #~ msgid "No" #~ msgstr "Ingen" #, fuzzy #~ msgid "Auto" #~ msgstr "Bliv automatisk med" #, fuzzy #~ msgid "otr" #~ msgstr "Varm" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Ikke gyldigt server navn" #, fuzzy #~ msgid "There is an error" #~ msgstr "Tjeneste returnerede en fejl." #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "Hvor mange minutter skal sidste linjer fra forrige samtale vare." #~ msgid "" #~ "Your configured emoticons theme cannot been loaded. You maybe need to " #~ "update the format of emoticons.py file. See http://trac.gajim.org/wiki/" #~ "Emoticons for more details." #~ msgstr "" #~ "Dit konfigurerede følelsesikon tema kan ikke findes. Du er måske nød til " #~ "at opdatere formatet for filen emoticons.py. Se http://trac.gajim.org/" #~ "wiki/Emoticons for flere detaljer." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Du vil blive tilsluttet til %s uden OpenPGP." #~ msgid "The following message was NOT encrypted" #~ msgstr "Den følgende besked var IKKE krypteret" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Aktiver ESessions kryptering for denne konto." #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Slå til/fra Open_PGP Kryptering" #~ msgid "Toggle End to End Encryption" #~ msgstr "Slå til/fra ende til ende Kryptering" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "GPG kryptering aktiveret" #, fuzzy #~ msgid "No OpenPGP key assigned" #~ msgstr "Ingen GPG nøgle valgt" #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages with OpenPGP." #~ msgstr "" #~ "Ingen GPG nøgle er valgt for denne kontakt. Derfor kan du ikke kryptere " #~ "beskeder med GPG." #~ msgid "Session WILL be logged" #~ msgstr "Session VIL blive logget" #~ msgid "Session WILL NOT be logged" #~ msgstr "Session VIL IKKE blive logget" #~ msgid "is" #~ msgstr "er" #~ msgid "is NOT" #~ msgstr "er IKKE" #~ msgid "will" #~ msgstr "vil" #~ msgid "will NOT" #~ msgstr "vil IKKE" #~ msgid "The following message was encrypted" #~ msgstr "Den følgende besked var krypteret" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Slå til/fra Open_PGP Kryptering" #~ msgid "Is OpenPGP enabled for this contact?" #~ msgstr "Er OpenPGP aktiveret for denne kontakt?" #~ msgid "" #~ "Should Gajim automatically start an encrypted session with this contact " #~ "when possible?" #~ msgstr "" #~ "Skal Gajim automatisk starte en krypteret session med denne kontakt når " #~ "det er muligt?" #~ msgid "Neither the remote presence is signed, nor a key was assigned." #~ msgstr "" #~ "Den fjerne tilstedeværelse er ikke signeret og en nøgle blev ikke angivet." #~ msgid "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "Kontaktens nøgle (%s) passer ikke til den angivne nøgle i Gajim." #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Denne besked er *krypteret* (Se :XEP:`27`]" #~ msgid "" #~ "Your chat session with %(jid)s is encrypted.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Din samtale session med %(jid)s er krypteret.\n" #~ "\n" #~ "Denne sessions Korte Ægtheds Streng er: %(sas)s" #~ msgid "You have already verified this contact's identity." #~ msgstr "Du har allerede verificeret denne kontakts identitet." #~ msgid "Contact's identity verified" #~ msgstr "Kontaktens identitet er verificeret" #, fuzzy #~ msgid "Verify again…" #~ msgstr "Verificer igen..." #~ msgid "" #~ "To be certain that only the expected person can read your messages " #~ "or send you messages, you need to verify their identity by clicking the " #~ "button below." #~ msgstr "" #~ "For at være sikker på at kun den person du forventer kan læse dine " #~ "beskeder eller sende dig beskeder, må du verificere deres identitet ved " #~ "at trykke på knappen under." #~ msgid "Contact's identity NOT verified" #~ msgstr "Kontaktens identitet er IKKE verificeret" #, fuzzy #~ msgid "Verify…" #~ msgstr "Efterprø_v" #~ msgid "Have you verified the contact's identity?" #~ msgstr "Har du bekræftet den kontaktens identitet?" #~ msgid "" #~ "To prevent talking to an unknown person, you should speak to %(jid)s directly (in person or on the phone) and verify that they see the same " #~ "Short Authentication String (SAS) as you.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "For at forhindre at du snakker til en ukendt person, bør du snakke " #~ "direkte til %(jid)s (person til person, eller på telefonen) og " #~ "verificere at de ser den samme Korte Ægtheds Streng (KÆS) som dig.\n" #~ "\n" #~ "Denne sessions Korte Ægtheds Streng: %(sas)s" #~ msgid "Did you talk to the remote contact and verify the SAS?" #~ msgstr "Har du snakket med den fjerne kontakt og verificeret KÆS?" #~ msgid "" #~ "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "" #~ "Kontaktens nøgle (%s) passer ikke til den angivne nøgle i Gajim." #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages." #~ msgstr "" #~ "Ingen GPG nøgle er tildelt denne kontakt. Derfor kan du ikke kryptere " #~ "beskeder." #, fuzzy #~ msgid "" #~ "OpenPGP key is assigned to this contact, but you do not trust their " #~ "key, so message cannot be encrypted. Use your OpenPGP client " #~ "to trust their key." #~ msgstr "" #~ "GPG nøgle er tildelt til denne kontakt, men du stoler ikke på denne " #~ "nøgle, så beskeder kan ikke krypteres. Brug din GPG klient til " #~ "at ændre dette." #, fuzzy #~ msgid "" #~ "OpenPGP Key is assigned to this contact, and you trust their key, so " #~ "messages will be encrypted." #~ msgstr "" #~ "GPG Nøgle er tildet til denne kontakt, og du stoler på denne nøgle, så " #~ "beskeder vil blive krypteret." #~ msgid "" #~ "This icon indicates that this message has not yet\n" #~ "been received by the remote end. If this icon stays\n" #~ "for a long time, it's likely the message got lost." #~ msgstr "" #~ "Dette ikon indikerer at denne besked endnu ikke\n" #~ "er blevet modtaget i den anden ende. Hvis dette\n" #~ "ikon forbliver på skærmen længe er det sandsynlig\n" #~ "at beskeden gik tabt." #~ msgid "" #~ "If True, listen to D-Bus signals from NetworkManager and change the " #~ "status of accounts (provided they do not have listen_to_network_manager " #~ "set to False and they sync with global status) based upon the status of " #~ "the network connection." #~ msgstr "" #~ "Hvis Sandt, lyt til D-Bus signaler fra NetworkManager og ændre status på " #~ "konti (forudsat at de ikke har listen_to_network_manager sat til Falsk og " #~ "de synkroniserer med global status) baseret på status af " #~ "netværksforbindelsen." #~ msgid "" #~ "The database file (%s) cannot be read. Try to repair it or remove it (all " #~ "history will be lost)." #~ msgstr "" #~ "Database filen (%s) kan ikke læses. Prøv at reparere den eller fjerne den " #~ "(hele historikken vil tabes)." #~ msgid "Database cannot be read." #~ msgstr "Database kan ikke læses." #~ msgid "A message from a non-valid JID arrived, it has been ignored." #~ msgstr "" #~ "En besked fra en ugyldig JID blev modtaget, den er blevet ignoreret." #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Udglattet rulning af beskeder i samtale vinduet" #~ msgid "Show _XML Console" #~ msgstr "Vis _XML Konsol" #~ msgid "Edit _Privacy Lists..." #~ msgstr "Rediger _Privatlivs Liste..." #~ msgid "_Administrator" #~ msgstr "_Administrator" #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "Send en besked til brugere som er tilsluttet denne server" #~ msgid "Sets Message of the Day" #~ msgstr "Sæt Dagens Besked" #~ msgid "Updates Message of the Day" #~ msgstr "Opdater Dagens Besked" #~ msgid "Deletes Message of the Day" #~ msgstr "Slet Dagens Besked" #~ msgid "Add _Contact..." #~ msgstr "_Tilføj Kontakt..." #~ msgid "_Accounts" #~ msgstr "K_ontoer" #~ msgid "Profile, A_vatar" #~ msgstr "Profil, A_vatar" #~ msgid "File _Transfers" #~ msgstr "Filover_førsler" #~ msgid "Help online" #~ msgstr "Hjælp på net" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Ofte Stillede Spørgsmål (på net)" #~ msgid "Fea_tures" #~ msgstr "_Egenskaber" #~ msgid "to %s account" #~ msgstr "til %s konto" #~ msgid "using %s account" #~ msgstr "bruger %s konto" #~ msgid "of account %s" #~ msgstr "fra konto %s" #~ msgid "for account %s" #~ msgstr "for konto %s" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Ved at fjerne denne kontakt fjerner du også godkendelsen, så han eller " #~ "hun vil altid se dig som offline." #~ msgid "Message Body

Lista prywatności" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "Aktywny w tej sesji" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "P_ołącz przy starcie programu" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "Lista reguł" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "Dodaj / Edytuj regułę" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "Zezwól" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Odmów" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "JID" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "według grupy" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "według autoryzacji" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "wszystkim" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "wysyłać mi wiadomości" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "wysyłać kwerendy" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "widzieć mój status" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "wysyłać mi status" #: gajim/data/gui/privacy_list_window.ui:557 msgid "All (including subscription)" msgstr "Wszystko (łącznie z zubskrypcją)" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "Kolejność:" #: gajim/data/gui/manage_sounds_window.ui:23 msgid "Manage sounds" msgstr "Zarządzaj dźwiękami" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Aktywny" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Zdarzenie" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Wybierz dźwięk" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Usuń konto _tylko z Gajima" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Usuń konto z Gajima i z _serwera" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "Co chcesz zrobić?" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Proszę czekać, trwa pobieranie listy komend..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Wybierz komendę do wykonania:" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Sprawdź ponownie" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Proszę czekać, trwa wysyłanie komendy..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Ten obiekt Jabbera nie udostępnia żadnych komend." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Wystąpił błąd:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Zakończ" #: gajim/data/gui/account_context_menu.ui:20 msgid "_Personal Events" msgstr "_Zdarzenia" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "Dołącz do _pokoju" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Dodaj kontakt..." #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Wyszukuj usługi" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "_Wykonaj komendę" #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Widok" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Pokaż _listę kontaktów" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Pokaż kontakty _niepołączone" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Pokaż kontakty _połączone" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Pokaż trans_porty" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Pomoc" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Zawartość" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_FAQ" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 msgid "Features" msgstr "Możliwości programu" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "Dodaj _zakładkę dla tego pokoju" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Ustawienia" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Zakończ" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Anuluj" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "Lista możliwych funkcjonalności Gajima:" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "Pokój" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "_Dodaj zakładkę do tego pokoju" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Serwer:" #: gajim/data/gui/manage_bookmarks_window.ui:219 #, fuzzy msgid "Roo_m" msgstr "_Pokój" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Hasło:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Kontakt rozłączył się" #: gajim/data/gui/manage_bookmarks_window.ui:342 #, fuzzy msgid "Minimize on Auto Join" msgstr "Minimalizuj po automatycznym wejściu" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Wyślij wiadomość i zamknij okno" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Opis statusu" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Opis: " #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Sprzątam" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 msgid "Send" msgstr "Wyślij" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Plik: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" "Nie jest prawdopodnie krytyczny, ale powinien zostać mimo to zgłoszony " "deweloperom." #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Zgłoś Błąd" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Rozpocznij rozmowę" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "O_dmów" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" "Odmów autoryzacji kontaktowi, nie będzie on wówczas wiedział kiedy jesteś " "połączony" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "_Autoryzuj" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "Autoryzuj kontakt - będzie wówczas wiedział, kiedy jesteś połączony" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "_Obecność" #: gajim/data/gui/emoji_chooser.ui:98 #, fuzzy msgid "No Results Found" msgstr "Brak wyników" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "Zaproś przyjaciół!" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "" "Zamierzasz rozpocząć czat.\n" "Wybierz kontakty, które chcesz do niego zaprosić" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "Proszę wybrać serwer MUC." #: gajim/data/gui/chat_to_muc_window.ui:141 msgid "MUC server" msgstr "Serwer MUC" #: gajim/data/gui/chat_to_muc_window.ui:176 msgid "In_vite" msgstr "_Zaproś" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Eksport" #: gajim/data/gui/history_manager.ui:93 msgid "Welcome to Gajim History Logs Manager" msgstr "Witaj w menedżerze historii rozmów Gajima" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" "Menedżer logów nie powinien być używany do przeglądania logów. Jeżeli " "szukasz tej funkcjonalności, użyj okna historii rozmów.\n" "\n" "Programu tego używać należy do usuwania lub eksportowania logów. Możesz " "wskazać logi po lewej stronie okna lub przeszukać ich bazę używając " "poniższego pola." #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "UWAGA:\n" "Jeżeli chcesz usuwać wiele danych, upewnij się najpierw że Gajim nie jest " "uruchomiony. Unikaj też usuwania historii rozmów kontaktów, z którymi " "właśnie rozmawiasz." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Szukaj w bazie" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "Treść wiadomości" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Wyślij wiadomość" #: gajim/data/gui/shortcuts_window.ui:24 #, fuzzy msgid "Add new line" msgstr "Utwórz nowy wpis" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Szablony opisów:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Szablony opisów:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "informacja o statusie" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Wyślij wiadomość" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Wiadomość została wysłana" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Ostatnio:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 msgid "Clear" msgstr "Wyczyść" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 #, fuzzy msgid "Close chat" msgstr "Zamknij" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Przesyłane pliki" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "w _konferencji" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "informacja o statusie" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 #, fuzzy msgid "Appearance" msgstr "Tożsamość na czacie" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Pokaż kontakty _niepołączone" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Pokaż kontakty _połączone" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Kontakty" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Informacje o kontakcie" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Zmień nazwę dla kontaktu" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Wyślij kontakty:" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Hasło" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "_Zapisuj w logach zmiany statusów kontaktów" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Moderator" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Ostatnio:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Historia rozmowy" #: gajim/data/gui/history_window.ui:315 msgid "Chat" msgstr "Rozmowa" #: gajim/data/gui/history_window.ui:329 #, fuzzy msgid "Record history for this chat" msgstr "Ignoruj komunikat o tym błędzie." #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Ostatnio:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Tytuł:" #: gajim/data/gui/manage_pep_services_window.ui:13 msgid "PEP Service Configuration" msgstr "Konfiguracja usługi PEP" #: gajim/data/gui/manage_pep_services_window.ui:69 msgid "_Configure" msgstr "_Konfiguruj" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Utwórz nowy wpis" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "Od:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Temat:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Wypełnij formularz." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Konfiguracja pokoju" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_OK" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "Sta_tus" #: gajim/data/gui/systray_context_menu.ui:20 msgid "_Start Chat..." msgstr "_Rozpocznij rozmowę" #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Pokaż wszystkie oczekujące _zdarzenia" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "Wyłącz dźwięki" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Ustawienia" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Zakończ" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Do:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "_Wyślij" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Wyślij wiadomość" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Odpowiedz" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Odpowiedz na tę wiadomość" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "_Wyślij i zamknij" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Wyślij wiadomość i zamknij okno" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "Ustaw Aktywność" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "Ustaw Aktywność" #: gajim/data/gui/change_activity_dialog.ui:337 msgid "Message: " msgstr "Wiadomość:" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Brak argumentu \"contact_jid\"" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Brak argumentu \"contact_jid\"" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 #, fuzzy msgid "Send a message to the contact" msgstr "Użycie: /%s wysyła wiadomość do kontaktu" #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "Nie znaleziono %s" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "Limit musi być wartością integer" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" "\n" " Ustaw obecny status\n" "\n" " Status może otrzymać następujące wartości:\n" " online, away, chat, xa, dnd.\n" " " #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "Dostępny" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 #, fuzzy msgid "Clear the text window" msgstr "Użycie: /%s czyście okno tekstowe." #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Uzycie: /%s, wysyła sygnał ping do kontaktu" #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 #, fuzzy msgid "Command is not supported for zeroconf accounts" msgstr "Komenda nie jest wspierana dla konta zeroconf." #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 #, fuzzy msgid "No open audio sessions with the contact" msgstr "Kliknij by zobaczyć poprzednie rozmowy z tym kontaktem" #: gajim/command_system/implementation/standard.py:191 #, fuzzy, python-format msgid "%s is not a valid tone" msgstr "%s nie jest prawidłowym poziomem logowania" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "Przełącz sesję audio" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "Połączenie jest niemożliwe" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "Przełącz sesję wideo" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "Połączenie jest niedostępne" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Użycie: /%s wysyła wiadomość do kontaktu" #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Zmień swoją nazwę (Ctrl+N)" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 msgid "Invalid nickname" msgstr "Niepoprawny pseudonim" #: gajim/command_system/implementation/standard.py:267 #, fuzzy msgid "Open a private chat window with a specified occupant" msgstr "Użycie: /%s , otwiera okno prywatnej rozmowy z tą osobą." #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 #, fuzzy msgid "Nickname not found" msgstr "Pseudonim nie został odnaleziony: %s" #: gajim/command_system/implementation/standard.py:276 #, fuzzy msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "Użycie: /%s , otwiera okno prywatnej rozmowy z tą osobą." #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Zapytaj przed zamknięciem karty/okna rozmowy grupowej." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "%(contact_jid)s zaproszony do %(room_jid)s." #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "w _konferencji" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Jestes zaproszony do rozmowy grupowej" #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Niepoprawna nazwa serwera" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "afiliacja została zmieniona " #: gajim/command_system/implementation/standard.py:365 #, fuzzy msgid "Display names of all group chat occupants" msgstr "Użycie: /%s , wyświetla osoby obecne w danym pokoju." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "Błąd podczas wykonywania polecenia" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 msgid "Start new Conversation" msgstr "Rozpocznij nową konwersację" #: gajim/gtk/start_chat.py:300 msgid "New Groupchat" msgstr "Nowa rozmowa grupowa" #: gajim/gtk/start_chat.py:302 msgid "New Contact" msgstr "Dodaj nowy kontakt" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "Wiadomość z konta %s" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "Wiadomość z konta %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Pojedyncza wiadomość" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Wyślij %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Odebrane %s" #: gajim/gtk/single_message.py:238 #, python-format msgid "Form %s" msgstr "Od %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "Połączenie jest niedostępne" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Sprawdź, czy jesteś połączony z \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "RE: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s napisał:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "Węzeł PEP nie został usunięty" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "Węzeł PEP %(node)s nie został usunięty: %(message)s" #: gajim/gtk/pep_config.py:133 #, fuzzy, python-format msgid "Configure %s" msgstr "Konfiguruj" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "Za_rejestruj" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Rejestracja zakończyła się sukcesem" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "Brak słownika dla tego języka (%s)" #: gajim/gtk/dialogs.py:83 #, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" "Musisz zainstalować słownik %s aby aktywować sprawdzanie pisowni lub wybrać " "inny język przez ustawienie opcji speller_langugage.\n" "Bez tego podświetlanie błędnie napisanych słów nie będzie działać." #: gajim/gtk/dialogs.py:440 #, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "" "Zamierzasz połączyć się z kontem %(account)s (%(server)s) za pomocą " "niezabezpieczonego połączenia. Oznacza to, że konwersacje nie będą " "szyfrowane i jest zdecydowanie odradzane. \n" "Czy na pewno chcesz to zrobić?" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "Gajim nie nawiąże połączenia, jeżeli nie będzie zaznaczone to pole" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "_Przywróć" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "Zastąp" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "Używany przez ciebie pseudonim zawiera niedozwolone znaki." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "dla konta %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Pokaż certyfikat..." #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Zmień hasło" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Musisz wpisać hasło." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Hasła nie zgadzają się" #: gajim/gtk/add_contact.py:30 #, fuzzy msgid "GG Number" msgstr "Numer GG:" #: gajim/gtk/add_contact.py:31 #, fuzzy msgid "ICQ Number" msgstr "Numer ICQ:" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Dodaj kontakt..." #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s MiB" #: gajim/gtk/add_contact.py:235 #, fuzzy, python-format msgid "You must supply the %s of the new contact." msgstr "Musisz wpisać hasło dla nowego konta." #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "Niepoprawny identyfikator użytkownika" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "ID użytkownika nie może zawierać zasobu." #: gajim/gtk/add_contact.py:274 msgid "You cannot add yourself to your roster." msgstr "Ty nie możesz dodać siebie do swojej listy kontaktów." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Rozłączony" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Kontakt jest już na liście kontaktów" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Ten kontakt znajduje się już na twojej liście kontaktów." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "ID uzytkownika:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "Błąd przy dodawaniu usługi %s" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" "Ten błąd wystąpił podczas dodawania kontaktu dla transportu %(transport)s: \n" "\n" "%(error)s" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "Tworzenie wiadomości" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Nieaktywny" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Zmień status" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "" "Czat\n" "Wiadomości" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Nowa wiadomość" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Konto" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Grupa" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "_Pokaż zdarzenie w obszarze powiadomienia" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Rozmowa z" #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Kolor przychodzącego pseudonimu." #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Kolor wychodzącego pseudonimu." #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "Wiadomość _otrzymana:" #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "Wiadomość _otrzymana:" #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "Wysłana wiadomość :" #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "Wysłana wiadomość :" #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Opis statusu" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Opis statusu" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Kolor" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "Podś_wietlaj błędy w pisowni" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Wiadomości" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "Wróć do kolorów _domyślnych" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Kontakt rozłączył się" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Kontakt połączył się" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "gajim-remote" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Niepoprawny pseudonim" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Niedozwolony znak" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Aktywny" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "Błąd zapisu lub odczytu na dysku" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s jes teraz %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, python-format msgid "Error: %s" msgstr "Błąd: %s" #: gajim/gtk/history.py:590 msgid "Error" msgstr "Błąd" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Obecny status: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Obecny status: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "Co chcesz zrobić?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "Miesiąc" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "Kwartał" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "Rok" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "Wszystko" #: gajim/gtk/history_sync.py:240 msgid "Connecting..." msgstr "Łączenie..." #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Przesyłanie pliku %(filename)s od %(name)s zostało zatrzymane." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "Prześlij dalej nieprzeczytane wiadomości" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 msgid "A GTK+ XMPP client" msgstr "Klient Jabbera w GTK+" #: gajim/gtk/about.py:48 #, python-format msgid "GTK+ Version: %s" msgstr "Wersja GTK+: %s" #: gajim/gtk/about.py:49 #, python-format msgid "PyGObject Version: %s" msgstr "Wersja PyGTK: %s" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Bieżący deweloperzy:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Poprzedni deweloperzy:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "Wykonawcy" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 msgid "we would like to thank all the package maintainers." msgstr "I wreszcie, chcielibyśmy podziękować wszystkim opiekunom pakietów." #: gajim/gtk/about.py:61 #, fuzzy msgid "Thanks" msgstr "Wdzięczny" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "" "Tłumaczenie na język polski: Witold Kieraś\n" "Maciej Chojnacki \n" "Sławomir Domagała \n" "Dominik Kozaczko \n" "Jacek Sowiński \n" "kompowiec2 " #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Wybierz plik do wysłania..." #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Wybierz archiwum" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Wszystkie pliki" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Wszystkie pliki" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Wyślij _plik" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Obrazki" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Wybierz archiwum" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Archiwa Zip" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Zapisz obraz jako..." #: gajim/gtk/profile.py:72 msgid "Retrieving profile…" msgstr "Pobieranie profilu..." #: gajim/gtk/profile.py:187 msgid "Wrong date format" msgstr "Nieprawidłowy format daty" #: gajim/gtk/profile.py:190 msgid "Format of the date must be YYYY-MM-DD" msgstr "Data musi być podana w formacie RRRR-MM-DD" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "Informacja została odebrana" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "Nie możesz wysłać informacji o sobie jeśli nie jesteś połączony." #: gajim/gtk/profile.py:346 msgid "Sending profile…" msgstr "Wysyłanie profilu..." #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "Informacja NIE ZOSTAŁA opublikowana" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "Publikacja vCard nie powiodła się" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "W czasie publikowanie informacji o tobie wystąpił błąd, spróbuj ponownie " "później." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Niepoprawny pokój" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "Proszę wybrać pokój" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 msgid "Invalid Nickname" msgstr "Niepoprawny pseudonim" #: gajim/gtk/join_groupchat.py:223 #, fuzzy msgid "Please choose a nickname" msgstr "Proszę utworzyć nowy temat i nadać mu nazwę." #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Błędny adres URI" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "To nie jest czat" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "Zachowanie Ustawień dla %s" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Your Archiving Preferences have been saved!" msgstr "Twoje preferencje archiwizacji zostały zapisane!" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Nie jesteś połączony z serwerem" #: gajim/gtk/mam_preferences.py:102 msgid "Error received: {}" msgstr "Odebrany błąd: {}" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Błąd" #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "Aktywny" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "Nieaktywny" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "Zmienna logiczna" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "Liczba całkowita" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Tekst" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Nazwa opcji" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Wartość" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Typ" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Brak)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Ukryte" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "_Nazwa hosta: " #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Możliwości serwerów" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Serwer odpowiedział: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "Bonjour / Zeroconf" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" "Rozmowy w sieci lokalnej, bez pośrednictwa serwera i z automatycznym " "wykrywaniem klientów." #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "Wymaga python-dbus" #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 msgid "Command line" msgstr "Linia poleceń" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "Skrypt pozwalający na sterowanie Gajimem z linii poleceń." #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "Funkcjonalność niedostępna dla systemu Windows." #: gajim/gtk/features.py:61 msgid "OpenPGP message encryption" msgstr "Szyfrowanie OpenPGP" #: gajim/gtk/features.py:63 msgid "Ability to encrypting chat messages with OpenPGP." msgstr "Możliwość Szyfrowania wiadomości kluczami GPG." #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "Wymaga GPG oraz python-gnupg (%(url)s)." #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "Wymaga GPG.exe w ścieżce." #: gajim/gtk/features.py:66 msgid "Password encryption" msgstr "Hasło" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "Bezpieczne przechowywanie haseł." #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "Słownik" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "Zwraca uwagę na błędy w wysyłanych wiadomościach." #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 #, fuzzy msgid "Requires Gspell" msgstr "Wymaga libgtkspell" #: gajim/gtk/features.py:76 msgid "Automatic status" msgstr "Automatyczny status" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" "Umożliwia mierzenie czasu bezczynności i odpowiednie ustawienie statusu." #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "Wymaga biblioteki libxss." #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "Wymaga python2.5" #: gajim/gtk/features.py:81 msgid "RST Generator" msgstr "Generator RST" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" "Tworzy XHTML z kodu RST (patrz http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html)." #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "Wymaga python-docutils." #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "Audio / Video" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "Można rozpocząć rozmowę głosową i wideo." #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" "wymaga gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "UPnP-IGD" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 #, fuzzy msgid "Requires gir1.2-gupnpigd-1.0." msgstr "Wymaga python-gnome2." #: gajim/gtk/features.py:102 msgid "?features:Available" msgstr "Dostępny" #: gajim/gtk/features.py:109 msgid "Feature" msgstr "Możliwości" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "Lista prywatności %s" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "Lista prywatności dla %s" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "" "Kolejność: %(order)s, akcja: %(action)s, typ: %(type)s, wartość: %(value)s" #: gajim/gtk/privacy_list.py:152 #, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Kolejność: %(order)s, akcja: %(action)s" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "Edytuj regułę" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "Dodaj regułę" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "Listy prywatności dla %s" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "Niepoprawna nazwa listy" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "Musisz podać nazwę nowej listy prywatności." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Konto zostało pomyślnie dodane" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Możesz ustawić opcje zaawansowane wciskając przycisk Zaawansowane lub " "później wybierając pozycję Konta z menu Edycja w głównym oknie programu." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Twoje konto zostało założone" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Niepoprawna nazwa użytkownika" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Musisz wpisać nazwę użytkownika aby skonfigurować to konto." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 msgid "Invalid server" msgstr "Niepoprawna nazwa serwera" #: gajim/gtk/account_wizard.py:255 msgid "Please provide a server on which you want to register." msgstr "Wpisz adres serwera, na którym chcesz się zarejestrować." #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Niepoprawny wpis" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "Wybrany port musi być numerem portu." #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" "Ostrzeżenie o zabezpieczeniach\n" "\n" "Autentyczność certyfikatu SSL od %(hostname)s nie może zostać potwierdzona.\n" "Błąd SSL: %(error)s\n" "Czy nadal chcesz się połączyć z tym serwerem?" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "Wystąpił błąd w trakcie tworzenia konta" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Nazwa konta jest już zajęta" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Masz już konto o takiej nazwie." #: gajim/gtk/xml_console.py:74 msgid "Filter" msgstr "Filtr:" #: gajim/gtk/xml_console.py:79 msgid "XML Input" msgstr "Wejście XML" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Niepoprawny plik" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "Domyślny" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "nagłówek informacji o statusie" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "treść informacji o statusie" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Czy zalogować się ponownie?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "" "Jeżeli chcesz by wszelkie zmiany odniosły natychmiastowy skutek, musisz " "zalogować się ponownie." #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "Masz otwarte okno rozmowy na koncie %s" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "" "Wszystkie otwarte zakładki rozmów i czatów zostaną zamknięte. Kontynuować?" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Dodaj kontakt..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "_Usuń" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Połączone konta" #: gajim/gtk/accounts.py:549 #, fuzzy msgid "Use PGP Agent" msgstr "Użyj Agenta G_PG" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Połączenie" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Zaproś kontakty" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Certyfikat klienta" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Przypisz klucz OpenPGP" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "P_ołącz przy starcie programu" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Automatyczne połącz po zerwaniu połączenia" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Zapisz _logi rozmów dla wszystkich kontaktów" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "_Wyślij wiadomość do serwera..." #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Dowolny status" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Zmienia status kont lub kont" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Wiadomości" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Używaj serwerów proxy do przesyłania plików" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "_używaj zmiennej środowiskowej HTTP__PROXY" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Serwer Proxy:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "_Ostrzegaj przed użyciem niezaszyfrowanego połączenia" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Wysyłaj pakiety podtrzymujące" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "Priory_tet:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Zmienia status kont lub kont" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Imię:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Nazwisko:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Nowy adres e-mail" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "_Dostosuj do statusu" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Włącz" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Port:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Połączenie" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "Pliki PKCS12" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Certyfikat klienta" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Certyfikat klienta" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Zapisz hasło" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "_Emotikony:" #: gajim/gtk/bookmarks.py:72 msgid "?print_status:All" msgstr "?print_status:Wszystkie" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "Jedynie wejdź i wyjdź" #: gajim/gtk/bookmarks.py:74 msgid "?print_status:None" msgstr "?print_status:Żaden" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "Nowa rozmowa grupowa" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Ta zakładka zawiera niepoprawne dane" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "Upewnij się, że wypełniłeś pola serwer i pokój lub usuń tę zakładkę." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 msgid "Character not allowed" msgstr "Niedozwolony znak" #: gajim/gtk/bookmarks.py:367 msgid "Invalid room" msgstr "Niepoprawny pokój" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Plik jest pusty" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 #, fuzzy msgid "Archive is malformed" msgstr "Usługa wysłała niepoprawne dane" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Ten plik już istnieje" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 #, fuzzy msgid "Plugin" msgstr "_Wtyczki" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Zabanuj %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Rejestracja nie powiodła się" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "Nie można poprawnie usunąć wtyczki" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "Nadpisać?" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Konfiguracja pokoju" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Klient komunikatora Jabber" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "Klient Jabbera w GTK+" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Pokaż wszystkie oczekujące _zdarzenia" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Możliwości programu" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 #, fuzzy msgid "Automatic spell-checking for your messages" msgstr "Zwraca uwagę na błędy w wysyłanych wiadomościach." #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Przeglądanie usług przy użyciu konta %s" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "_Zapisuj w logach zmiany statusów kontaktów" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Pokoje" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Ostatnio:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Rejestracja nie powiodła się" #~ msgid "Stopped" #~ msgstr "Zatrzymany" #~ msgid "Error reading file:" #~ msgstr "Błąd odczytu pliku:" #~ msgid "Error parsing file:" #~ msgstr "Błąd przetwarzania pliku:" #, fuzzy #~ msgid "Audio / video conferences" #~ msgstr "Audio / Video" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Błąd przesyłania pliku" #, fuzzy #~ msgid "XML console interface" #~ msgstr "Konsola XML" #~ msgid "" #~ "A list of modp groups to use in a Diffie-Hellman, highest preference " #~ "first, separated by commas. Valid groups are 1, 2, 5, 14, 15, 16, 17 and " #~ "18. Higher numbers are more secure, but take longer to calculate when you " #~ "start a session." #~ msgstr "" #~ "Lista modp-grup wykorzystywany w Diffie-Hellman, najwyższa preferencja " #~ "jest pierwsza, oddzielonych przecinkiem. Odpowiednie grupy to 1, 2, 5, " #~ "14, 15, 16, 17 i 18. Wyższy numery są bardziej bezpiecznie, lecz " #~ "obliczanie zajmie więcej czasu podczas rozpoczynania sesji." #~ msgid "_Verify" #~ msgstr "_Weryfikuj" #~ msgid "(ESession info)" #~ msgstr "Opis" #~ msgid "Save as Preset..." #~ msgstr "Zapisz jako szablon..." #~ msgid "Always use this nickname when there is a conflict" #~ msgstr "W przypadku konfliktu zawsze używaj tego pseudonimu" #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "Demon Jabberd1.4 nie toleruje wysyłania \"sha info\" podczas wchodzenia " #~ "do pokoju chronionego hasłem. Ustaw tą opcję na False aby zabronić " #~ "Gajimowi wysyłania takiej informacji." #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje zastąpienie emotikon tekstowych jak ':)' " #~ "emotikonami graficznymi" #, fuzzy #~ msgid "_Emoticons" #~ msgstr "_Emotikony:" #~ msgid "_Highlight misspelled words" #~ msgstr "Podś_wietlaj błędy w pisowni" #, fuzzy #~ msgid "Notify by icon when your messages are received" #~ msgstr "Dźwięk, jaki będzie odtwarzany, gdy nadejdzie wiadomość MUC." #, fuzzy #~ msgid "T_heme" #~ msgstr "_Motyw:" #~ msgid "Themes" #~ msgstr "Tematy" #, fuzzy #~ msgid "Presence" #~ msgstr "_Obecność" #~ msgid "Emoticons disabled" #~ msgstr "Emotoikony wyłączone" #, fuzzy #~ msgid "" #~ "Your configured emoticons theme could not be loaded. See the log for more " #~ "details." #~ msgstr "" #~ "Wybrany przez ciebie styl emotikonów nie został znaleziony, emotikony " #~ "będą wyłączone." #~ msgid "You cannot make changes to the default theme" #~ msgstr "Nie możesz dokonywać zmian w obecnie używanym motywie" #, fuzzy #~ msgid "Please create a new clean theme." #~ msgstr "Proszę utworzyć nowy temat i nadać mu nazwę." #~ msgid "theme name" #~ msgstr "nazwa motywu" #~ msgid "You cannot delete your current theme" #~ msgstr "Nie możesz skasować obecnie używanego motywu" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Nowa wiadomość od %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Nowa wiadomość prywatna z pokoju %s" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s: %(message)s" #~ msgid "Messaged by %(nickname)s" #~ msgstr "Nowa wiadomość od %(nickname)s" #~ msgid "Status message text color." #~ msgstr "Kolor tekstu opisu." #~ msgid "Incoming nickname font." #~ msgstr "Czcionka pseudonimu przychodzącego." #~ msgid "Outgoing nickname font." #~ msgstr "Czcionka wychodzącego pseudonimu." #~ msgid "Status message text font." #~ msgstr "Czcionka opisu." #~ msgid "Background color of contacts when they just signed in." #~ msgstr "Kolor tła dla logujących się kontaktów." #~ msgid "Background color of contacts when they just signed out." #~ msgstr "Kolor tła dla kontaktów w trakcie wylogowywania." #~ msgid "green" #~ msgstr "zielony" #~ msgid "grocery" #~ msgstr "grocery" #~ msgid "human" #~ msgstr "human" #~ msgid "marine" #~ msgstr "morski" #, fuzzy #~ msgid "Contact row" #~ msgstr "Kontakt" #~ msgid "Gajim Themes Customization" #~ msgstr "Wybieranie motywów dla Gajim" #~ msgid "Text _color:" #~ msgstr "_Kolor tekstu:" #~ msgid "_Background:" #~ msgstr "_Tło:" #~ msgid "Text _font:" #~ msgstr "_Czcionka tekstu:" #~ msgid "Font style:" #~ msgstr "Styl czcionki:" #~ msgid "Paused" #~ msgstr "Zatrzymany" #~ msgid "Gone" #~ msgstr "Zniknął" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "MUC\n" #~ "Wiadomości" #~ msgid "Chatstate Tab Colors" #~ msgstr "Kolory kart w oknie czatu" #, fuzzy #~ msgid "Chat message" #~ msgstr "Wiadomość:" #~ msgid "Use system _default" #~ msgstr "Użyj _domyślnej dla systemu" #~ msgid "Font" #~ msgstr "Czcionka" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Pseudonim kontaktu:" #, fuzzy #~ msgid "Contact's message" #~ msgstr "Wiadomość:" #, fuzzy #~ msgid "_Status message" #~ msgstr "_Informacja o statusie:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Podświetlenie wiadomości z czatu" #, fuzzy #~ msgid "Your nickname" #~ msgstr "Twój pseudonim:" #, fuzzy #~ msgid "Your message" #~ msgstr "Twoja wiadomość:" #, fuzzy #~ msgid "_URL highlight" #~ msgstr "_Podświetlanie URL:" #~ msgid "Chat Line Colors" #~ msgstr "Kolory wierszy czatu" #~ msgid "Jabber ID:" #~ msgstr "Jabber ID:" #~ msgid "Resource:" #~ msgstr "Zasób::" #~ msgid "Status:" #~ msgstr "Status:" #~ msgid "Client:" #~ msgstr "Klient:" #~ msgid "Contact time:" #~ msgstr "Czas u niego/niej:" #~ msgid "Ask:" #~ msgstr "Pytaj:" #~ msgid "Subscription:" #~ msgstr "Subskrybcja:" #~ msgid "Name:" #~ msgstr "Imię:" #~ msgid "Nickname:" #~ msgstr "Pseudonim:" #~ msgid "Street:" #~ msgstr "Ulica:" #~ msgid "City:" #~ msgstr "Miasto:" #~ msgid "State:" #~ msgstr "Województwo:" #~ msgid "Extra Address:" #~ msgstr "Dodatkowy adres:" #~ msgid "Postal Code:" #~ msgstr "Kod pocztowy:" #~ msgid "Country:" #~ msgstr "Kraj:" #~ msgid "Homepage:" #~ msgstr "Strona domowa:" #~ msgid "E-Mail:" #~ msgstr "Adres e-mail:" #~ msgid "Phone No.:" #~ msgstr "Telefon:" #~ msgid "Birthday:" #~ msgstr "Data urodzenia:" #~ msgid "Family:" #~ msgstr "Nazwisko:" #~ msgid "Middle:" #~ msgstr "Drugie imię:" #~ msgid "Prefix:" #~ msgstr "Prefiks:" #~ msgid "Given:" #~ msgstr "Imię:" #~ msgid "Suffix:" #~ msgstr "Sufiks:" #~ msgid "Full Name" #~ msgstr "Imię i nazwisko" #~ msgid "Company:" #~ msgstr "Firma:" #~ msgid "Department:" #~ msgstr "Dział:" #~ msgid "Position:" #~ msgstr "Stanowisko:" #~ msgid "Role:" #~ msgstr "Rola:" #~ msgid "- messages will be logged" #~ msgstr "- wiadomości będzie logowanych" #~ msgid "- messages will not be logged" #~ msgstr "- wiadomości nie będzie logowanych" #~ msgid "Edit %s" #~ msgstr "Modyfikuj %s" #~ msgid "Register to %s" #~ msgstr "Zarejestruj na %s" #~ msgid "Conversation History with %s" #~ msgstr "Historia rozmowy z %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Nie można ustanowić połączenia z \"%s\"" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "Informacje rejestracyjne transportu %s nie dotarły na czas" #~ msgid "Register to" #~ msgstr "Zarejestruj w" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Wpisz JID lub nazwę kontaktu" #~ msgid "Search:" #~ msgstr "Szukaj" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Nie możesz zmienić hasła, jeśli nie jesteś połączony." #~ msgid "Invalid password" #~ msgstr "Niepoprawne hasło" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "Hasła wpisane w obydwu polach muszą być identyczne." #~ msgid "Enter new password:" #~ msgstr "Wpisz nowe hasło:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Wpisz ponownie nowe hasło:" #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "Jid %s nie jest kompatybilny z RFC. Nie zostanie dodany do listy " #~ "kontaktów. Skorzystaj z narzędzi do zarządzania listą kontaktów, takich " #~ "jak http://jru.jabberstudio.org/ aby go usunąć" #~ msgid "unsubscribe request from %s" #~ msgstr "Prośba o cofnięcie autoryzacji od %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Połącz automatycznie" #~ msgid "<empty>" #~ msgstr "<empty>" #~ msgid "Homepage:" #~ msgstr "Strona domowa:" #, fuzzy #~ msgid "Configure" #~ msgstr "Konfiguruj" #~ msgid "Manage Bookmarks" #~ msgstr "Zarządzaj zakładkami" #~ msgid "_Nickname:" #~ msgstr "_Pseudonim:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "Zaznaczenie spowoduje łączenie z tym pokojem przy starcie programu" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Wyświetlaj status:" #, fuzzy #~ msgid "Add JID" #~ msgstr "Jabber ID" #, fuzzy #~ msgid "Preference:" #~ msgstr "Ustawienia" #, fuzzy #~ msgid "Preference" #~ msgstr "Ustawienia" #~ msgid "JID:" #~ msgstr "JID: " #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "Wypełnij informacje o kontakcie, który chcesz dodać do konta %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Wypełnij informacje o kontakcie, który chcesz dodać" #, fuzzy #~ msgid "Recently" #~ msgstr "Ostatnio:" #~ msgid "Add New Contact" #~ msgstr "Dodaj nowy kontakt" #~ msgid "_User ID:" #~ msgstr "_Identyfikator użytkownika:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "ID uzytkownika:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Pseudonim" #~ msgid "Personal Information" #~ msgstr "Informacje osobiste" #~ msgid "Avatar:" #~ msgstr "Awatar:" #~ msgid "Click to set your avatar" #~ msgstr "Kliknij aby ustawić avatar" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "Usuń grupę" #~ msgid "Not fetched because of invisible status" #~ msgstr "Nie wysłano z powodu statusu 'niewidoczny'" #~ msgid "Please wait..." #~ msgstr "Proszę czekać..." #~ msgid "" #~ "When negotiating an encrypted session, should Gajim assume you want your " #~ "messages to be logged?" #~ msgstr "" #~ "Czy podczas negocjowania szyfrowanej sesji Gajim ma przyjąć, że chcesz ją " #~ "logować?" #~ msgid "Log _encrypted chat session" #~ msgstr "Loguj _zaszyfrowane wiadomości" #, fuzzy #~ msgid "" #~ "If checked, Gajim will keep logs for encrypted messages. Please note that " #~ "when using end-to-end encryption the remote party has to agree on " #~ "logging, else the messages will not be logged." #~ msgstr "" #~ "Po uaktywnieniu tej opcji, Gajim będzie logował wiadomości zaszyfrowane " #~ "przez GPG oraz E2E. W przypadku E2E zgodę na logowanie wyrazić musi " #~ "rozmówca. Jeżeli zgoda nie zostanie udzielona, wiadomości NIE BĘDĄ " #~ "logowane." #~ msgid "Yahoo! Address:" #~ msgstr "Adres _Yahoo:" #~ msgid "Forward unread messages" #~ msgstr "Prześlij dalej nieprzeczytane wiadomości" #~ msgid "All unread messages have been forwarded." #~ msgstr "Wszystkie nieprzeczytane wiadomości zostały przesłane dalej." #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "Prześlij dalej nieprzeczytane wiadomości" #~ msgid "AIM Address:" #~ msgstr "_Adres AIM:" #~ msgid "MSN Address:" #~ msgstr "_Adres MSN:" #~ msgid "Confirm these session options" #~ msgstr "Potwierdź opcje sesji" #, fuzzy #~ msgid "" #~ "The remote client wants to negotiate a session with these features:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Are these options acceptable?" #~ msgstr "" #~ "Zdalny klient chce przeprowadzić negocjację sesji z poniższymi " #~ "ustawieniami:\n" #~ "\n" #~ "\t\t%s\n" #~ "\n" #~ "\t\tCzy akceptujesz te ustawienia?" #~ msgid "" #~ "The remote client selected these options:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Continue with the session?" #~ msgstr "" #~ "Zdalny kilent wybrał następujące opcje:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Kontynuować?" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "Czy OpenPGP jest włączone dla tego kontaktu?" #~ msgid "End to End message encryption" #~ msgstr "Szyfrowanie typu \"end to end\"" #~ msgid "Encrypting chat messages." #~ msgstr "Szyfrowanie wysyłanych wiadomości." #~ msgid "Requires python-crypto." #~ msgstr "Wymaga python-crypto." #~ msgid "Session negotiation cancelled" #~ msgstr "Negocjowanie sesji zostało przerwane" #~ msgid "This session WILL be archived on server" #~ msgstr "Obecna sesja zostanie zachowania w archiwum na serwerze" #, fuzzy #~ msgid "This session WILL NOT be archived on server" #~ msgstr "Ta sesja NIE BĘDZIE archiwizowana na serwerze" #~ msgid "This session is encrypted" #~ msgstr "[Ta wiadomość jest zaszyfrowana]" #~ msgid " and WILL be logged" #~ msgstr "i BĘDZIE logowana" #~ msgid " and WILL NOT be logged" #~ msgstr "i NIE BĘDZIE logowana" #~ msgid "" #~ "Remote contact's identity not verified. Click the shield button for more " #~ "details." #~ msgstr "" #~ "Tożsamość zdalnego rozmówny nie jest zweryfikowana. Kliknij na przycisk " #~ "tarczy po więcej szczegółów." #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "Szyfrowanie GPG wyłączone" #~ msgid "" #~ "Unable to decrypt message from %s\n" #~ "It may have been tampered with." #~ msgstr "" #~ "Nie można odszyfrować wiadomości od %s\n" #~ "To mogło być sfałszowane." #~ msgid "Unable to decrypt message" #~ msgstr "Nie można odszyfrować wiadomości" #~ msgid "Enable ESessions encryption for this account." #~ msgstr "Włączono szyfrowanie ESession dla tego konta." #~ msgid "Should Gajim automatically start an encrypted session when possible?" #~ msgstr "" #~ "Czy Gajim powinien automatycznie zaczynać zaszyfrowaną sesje jeśli to " #~ "możliwe?" #~ msgid "" #~ "[This is part of an encrypted session. If you see this message, something " #~ "went wrong.]" #~ msgstr "" #~ "[To jest część zaszyfrowanej wiadomości. Jeżeli widzisz tą wiadomość, " #~ "oznacza to, że coś poszło źle.]" #~ msgid "Requires python-avahi." #~ msgstr "Wymaga python-avahi." #~ msgid "URL:" #~ msgstr "URL:" #~ msgid "_Send" #~ msgstr "_Wyślij" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Zapisz plik jako..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Przenoszenie logów rozmów..." #~ msgid "Choose Image" #~ msgstr "Wybierz obrazek" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Wybierz plik do wysłania..." #~ msgid "Choose Client Cert #PCKS12" #~ msgstr "Proszę wybrać certyfikat klienta #PCKS12" #~ msgid "When %s becomes:" #~ msgstr "Gdy %s ma status:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Dodaję specjalne powiadomienia dla %s" #, fuzzy #~ msgid "" #~ "It seems the SSL certificate of account %(account)s has changed and is " #~ "not valid or your connection is being compromised.\n" #~ "\n" #~ "Old SHA-1 fingerprint: %(old_sha1)s\n" #~ "Old SHA-256 fingerprint: %(old_sha256)s\n" #~ "\n" #~ "New SHA-1 fingerprint: %(new_sha1)s\n" #~ "New SHA-256 fingerprint: %(new_sha256)s\n" #~ "\n" #~ "Do you still want to connect and update the fingerprint of the " #~ "certificate?" #~ msgstr "" #~ "Certyfikat SSL konta %(account)s uległ zmianie lub połączenie to jest " #~ "podsłuchiwane.\n" #~ "Poprzedni odcisk klucza: %(old)s\n" #~ "Nowy odcisk klucza: %(new)s\n" #~ "\n" #~ "Czy nadal chcesz połączyć się i zaktualizować odcisk klucza certyfikatu?" #, fuzzy #~ msgid "" #~ "The authenticity of the %s certificate could be invalid.\n" #~ "The certificate does not cover this domain." #~ msgstr "Nie można potwierdzić autentyczności certyfikatu %s." #~ msgid "Unable to load idle module" #~ msgstr "Nie można załadować modułu idle" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s jest katalogiem choć powinien być plikiem" #~ msgid "creating logs database" #~ msgstr "tworzenie bazy danych z logami" #, fuzzy #~ msgid "creating cache database" #~ msgstr "tworzenie bazy danych z logami" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Wyślij %s do %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Historia rozmów" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Zmień nazwę konta" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Wyślij _wiadomość..." #, fuzzy #~ msgid "We received an error: {}" #~ msgstr "Wystąpił błąd" #~ msgid "E2E encryption disabled" #~ msgstr "Szyfrowanie E2E wyłączone" #, fuzzy #~ msgid "" #~ "Add this certificate to the list of trusted certificates.\n" #~ "SHA-1 fingerprint of the certificate:\n" #~ "%(sha1)s\n" #~ "SHA256 fingerprint of the certificate:\n" #~ "%(sha256)s" #~ msgstr "" #~ "Dodaj ten certyfikat do listy zaufanych.\n" #~ "Odcisk klucza SHA1 certyfikatu:\n" #~ "%s" #~ msgid "uri" #~ msgstr "URI" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Zainstalowany" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Zainstalowany" #, fuzzy #~ msgid "Install and Upgrade Plugins" #~ msgstr "Zainstalowany" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Rejestracja nie powiodła się" #, fuzzy #~ msgid "Security error during download" #~ msgstr "Błąd zabezpieczeń przy połączeniu z \"%s\"" #, fuzzy #~ msgid "Error in download" #~ msgstr "Błąd zabezpieczeń przy połączeniu z \"%s\"" #~ msgid "cyan" #~ msgstr "cyjan" #~ msgid "migrating logs database to indices" #~ msgstr "indeksowanie archiwum rozmów" #, fuzzy #~ msgid "Send File..." #~ msgstr "Wyślij _plik..." #, fuzzy #~ msgid "HTTP File Upload not supported by your server" #~ msgstr "Twój serwer uniemożliwia przechowywanie metakontaktów" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Przesyłane pliki" #~ msgid "" #~ "Your configured emoticons theme has not been found, so emoticons have " #~ "been disabled." #~ msgstr "" #~ "Wybrany przez ciebie styl emotikonów nie został znaleziony, emotikony " #~ "będą wyłączone." #~ msgid "Shows or hides the roster window" #~ msgstr "Pokazuje lub ukrywa okno listy kontaktów" #~ msgid "Shows or hides the ipython window" #~ msgstr "Pokazuje lub ukrywa okno iptyhon" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "Konto XMPP %s@%s" #, fuzzy #~ msgid "Exception" #~ msgstr "Opis" #, fuzzy #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "" #~ "%(jid)s chciałby %(action)s kilka kontaktów w Twoim " #~ "rosterze." #~ msgid "" #~ "Ordered list (space separated) of connection type to try. Can contain " #~ "tls, ssl or plain" #~ msgstr "" #~ "Lista połączeń (rozdzielona spacjami) zawierająca wykaz rodzajów " #~ "połączeń. Może zawierać tls, ssl lub plain" #~ msgid "_Actions" #~ msgstr "_Działania" #, fuzzy #~ msgid "Requires upower and python-dbus." #~ msgstr "Wymaga python-dbus" #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Rozpocznij rozmowę" #~ msgid "You are already in group chat %s" #~ msgstr "Już jesteś w pokoju %s" #~ msgid "Join Group Chat with account %s" #~ msgstr "Dołącz do pokoju z konta %s" #~ msgid "Invalid Account" #~ msgstr "Niepoprawne konto" #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "Wskaż konto, z którym chcesz wejść do pokoju" #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "Proszę wprowadzić JID konferencji w postaci pokój@serwer." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "Używane przez ciebie Jabber ID zawiera niedozwolone znaki." #~ msgid "Start Chat with account %s" #~ msgstr "Rozpocznij rozmowę z konta %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Wpisz JID lub nazwę użytkownika kontaktu, któremu chcesz\n" #~ "wysłać wiadomość:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Taki Jabber ID już istnieje!" #~ msgid "Unable to parse \"%s\"." #~ msgstr "Nie można sparsować \"%s\"." #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "" #~ "Pokazuje okno dialogowe umożliwiające wysłanie wiadomości do kontaktu" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID osoby, z którą chcesz porozmawiać" #~ msgid "Adds contact to roster" #~ msgstr "Dodaje kontakt do listy kontaktów" #~ msgid "jid" #~ msgstr "jid" #~ msgid "Adds new contact to this account" #~ msgstr "Dodaje nowy kontakt do tego konta" #~ msgid "Opens 'Start Chat' dialog" #~ msgstr "Otwiera okno dialogowe 'Rozpocznij rozmowę'" #~ msgid "Starts chat, using this account" #~ msgstr "Rozpocznij rozmowę z tego konta" #, fuzzy #~ msgid "Handle a xmpp:/ URI" #~ msgstr "Obsługuj URI xmpp:/" #~ msgid "URI to handle" #~ msgstr "URI do obsługi" #~ msgid "Account in which you want to handle it" #~ msgstr "Wskaż konto, z którym chcesz zsynchronizować kontakty" #~ msgid "Message content" #~ msgstr "Treść wiadomości" #~ msgid "Join a MUC room" #~ msgstr "Dołącz do nowego pokoju" #~ msgid "Nickname to use" #~ msgstr "Nick" #~ msgid "Password to enter the room" #~ msgstr "Hasło do pokoju" #~ msgid "Account from which you want to enter the room" #~ msgstr "Wskaż konto, z którym chcesz wejść do pokoju" #, fuzzy #~ msgid "No URI given" #~ msgstr "Nie podano uri" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Błędny adres URI" #~ msgid "Nickname:" #~ msgstr "Pseudonim:" #~ msgid "Server:" #~ msgstr "Serwer:" #~ msgid "Password:" #~ msgstr "Hasło:" #~ msgid "Join this room _automatically when I connect" #~ msgstr "_Automatycznie dołącz do tego pokoju po uzyskaniu połączenia" #~ msgid "Bro_wse Rooms" #~ msgstr "Prze_glądaj pokoje" #, fuzzy #~ msgid "Requires libgtkspell and libenchant." #~ msgstr "Wymaga libgtkspell" #, fuzzy #~ msgid "Last MAM id we are syncronized with" #~ msgstr "Czas ostatniej synchronizacji logów z serwerem" #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "Menedżer sieci" #~ msgid "Autodetection of network status." #~ msgstr "Automatyczne wykrywanie stanu sieci." #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Wymaga gnome-network-manager oraz python-dbus." #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "Funkcjonalność niedostępna dla systemu Windows." #~ msgid "This contact does not support file transfer." #~ msgstr "Ten kontakt nie może przesyłać i odbierać plików." #, fuzzy #~ msgid "You need to know the real JID of the contact to send them a file." #~ msgstr "Ty musisz znać prawdziwy JID kontaktu, aby wysłać jej/jemu plik." #~ msgid "" #~ "You have to install %s dictionary to use spellchecking, or choose another " #~ "language by setting the speller_language option." #~ msgstr "" #~ "Musisz zainstalować słownik %s aby aktywować sprawdzanie pisowni lub " #~ "wybrać inny język korzystać z opcji speller_langugage." #~ msgid "Hides the buttons in chat windows." #~ msgstr "Ukrywa przyciski w oknie czatu." #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Zmień swoją nazwę (Ctrl+N)" #~ msgid "Change the room's subject (Alt+T)" #~ msgstr "Zmień temat pokoju (Ctrl+T)" #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "Dodaj pokój do zakładek (Ctrl+B)" #~ msgid "Browse the chat history (Ctrl+H)" #~ msgstr "Historia wiadomości (Ctrl+H)" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Pokaż menu zaawansowanych funkcji (Alt+D)" #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Dodaje kontakt do listy kontaktów (Ctrl+D)" #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "Zaproś kontakt do rozmowy (Ctrl+G)" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Pokaż profil kontaktu (Ctrl+I)" #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Pokaż profil kontaktu (Ctrl+I)" #~ msgid "Ma_ke message windows compact" #~ msgstr "_Spraw by okna rozmowy były zwarte" #~ msgid "Hide all buttons in chat windows" #~ msgstr "Ukryj przyciski w oknie rozmowy" #, fuzzy #~ msgid "Hide the chat buttons" #~ msgstr "Użycie: /%s ukrywa przyciski czatu." #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "Jeśli ma wartość True, Gajim wyśle zapytanie o awatar każdego kontaktu, " #~ "który ostatnio nie miał awatara lub ma zapisany jedynie stary." #~ msgid "Disk Write Error" #~ msgstr "Błąd zapisu na dysk" #~ msgid "Set Custom _Avatar..." #~ msgstr "Ustaw własny _avatar..." #, fuzzy #~ msgid "SSL certificate validation" #~ msgstr "Sprawdzanie certyfikatu SSL" #~ msgid "" #~ "A library used to validate server certificates to ensure a secure " #~ "connection." #~ msgstr "" #~ "Biblioteka używana do weryfikacji certyfikatów w celu zapewnienia " #~ "bezpiecznego połączenia." #, fuzzy #~ msgid "Requires python-pyopenssl > 0.12 and pyasn1." #~ msgstr "Wymaga python-pyopenssl" #~ msgid "?CLI:uri" #~ msgstr "?CLI:uri" #, fuzzy #~ msgid "?CLI:room" #~ msgstr "pokój" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "nick" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "hasło" #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "Korzystaj z DBus i Demona Powiadomień aby wyświetlać powiadomienia" #~ msgid "Notification" #~ msgstr "Powiadomienia" #~ msgid "Passive popups notifying for new events." #~ msgstr "Wyświetla okna informujące o nowych zdarzeniach." #~ msgid "" #~ "Requires python-notify or instead python-dbus in conjunction with " #~ "notification-daemon." #~ msgstr "" #~ "Wymaga python-notify lub python-dbus w połączeniu z notification-daemon." #~ msgid "Ignore" #~ msgstr "Ignoruj" #~ msgid "_Open Gmail Inbox" #~ msgstr "_Otwórz skrzynkę Gmail" #~ msgid "Notify on new _GMail email" #~ msgstr "Powiadamiaj o nowej poczcie na koncie _Gmail" #~ msgid "" #~ "If checked, Gajim will show a notification when a new e-mail is received " #~ "via GMail" #~ msgstr "" #~ "Jeżeli opcja ta zostanie uaktywniona, Gajim będzie również wyświetlał " #~ "informacje o nowej poczty w twojej skrzynce GMail" #~ msgid "Display _extra email details" #~ msgstr "Wyświetlaj _dodatkowe informacje o poczcie e-mail" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Jeżeli opcja ta zostanie uaktywniona, Gajim będzie również wyświetlał " #~ "informacje o nadawcach nowej poczty w twojej skrzynce" #~ msgid "GMail Options" #~ msgstr "Opcje konta Gmail" #, fuzzy #~ msgid "12" #~ msgstr "1" #, fuzzy #~ msgid "20" #~ msgstr "2" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Wyślij %s do %s" #~ msgid "GMail Email Received" #~ msgstr "Nowa poczta na koncie Gmail" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Nowa poczta w skrzynce %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "Masz %d nieprzeczytaną wiadomość pocztową" #~ msgstr[1] "Masz %d nieprzeczytane wiadomości pocztowe" #~ msgstr[2] "Masz %d nieprzeczytane wiadomości pocztowe" #~ msgid "" #~ "\n" #~ "\n" #~ "From: %(from_address)s\n" #~ "Subject: %(subject)s\n" #~ "%(snippet)s" #~ msgstr "" #~ "\n" #~ "\n" #~ "Od: %(from_address)s\n" #~ "Temat: %(subject)s\n" #~ "%(snippet)s" #~ msgid "Re_name" #~ msgstr "_Zmień nazwę" #~ msgid "Resour_ce:" #~ msgstr "Za_sób: " #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "Informację wysłano do serwera w celu rozdzielenia tego samego JID na dwie " #~ "lub więcej części, w zależności od liczby klientów połączonych z serwerem " #~ "z tego samego konta. Możesz być połączony z z tym samym kontem z " #~ "informacjami 'Dom' i 'Praca' w tym samym czasie. Klient o najwyższym " #~ "będzie odbierał wiadomości (patrz niżej)" #~ msgid "A_djust to status" #~ msgstr "D_ostosuj do statusu" #~ msgid "Priority will change automatically according to your status." #~ msgstr "" #~ "Priorytet ulegnie zmianie automatycznie, stosownie do twojego statusu." #~ msgid "Anonymous authentication" #~ msgstr "Używaj autoryzacji serwera proxy" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "Priorytet służy do określenia, który program ma odbierać wiadomości z " #~ "serwera gdy dwa klienty (lub więcej) są połączone z tym samym kontem. Ten " #~ "który ma wyższy priorytet, będzie odbierał wiadomości" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Synchronizuj kontakty" #~ msgid "Click to request authorization to all contacts of another account" #~ msgstr "" #~ "Kliknij aby poprosić o autoryzację od wszystkich kontaktów z innego konta" #~ msgid "Chan_ge Password" #~ msgstr "Z_mień hasło" #~ msgid "Click to change account's password" #~ msgstr "Kliknij, aby zmienić hasło dla konta" #~ msgid "Administration operations" #~ msgstr "Operacje administracyjne" #~ msgid "_Client Cert File:" #~ msgstr "Plik _certyfikatu klienta" #~ msgid "Browse..." #~ msgstr "Prze_glądaj..." #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "Certyfikat odrzucony" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Zaznaczanie tej opcji spowoduje automatyczne łączenie z siecią Jabber z " #~ "wykorzystaniem tego konta" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Synchronizuj kontakty" #~ msgid "Synch_ronize account status with global status" #~ msgstr "Synch_ronizuj status konta z globalnym statusem" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Jeśli jest zaznaczone, to każda zmiana statusu globalnego (ustawianego z " #~ "menu na dole okna listy kontaktów) wpłynie odpowiednio na status tego " #~ "konta" #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Jeżeli opcja jest aktywna, Gajim roześle kilka dodatkowych adresów IP " #~ "poza Twoim, tak aby przesyłanie plików przebiegało sprawniej." #~ msgid "Proxy" #~ msgstr "Proxy" #~ msgid "" #~ "Check this so Gajim will ask you before sending your password over an " #~ "insecure connection." #~ msgstr "" #~ "Po uaktywnieniu tej opcji Gajim zapyta przed wysłaniem hasła przez " #~ "nieszyfrowane połączenie." #~ msgid "Send _keep-alive packets" #~ msgstr "Wysyłaj pakiety _podtrzymujące" #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje wysyłanie pakietów podtrzymujących " #~ "połączenie, co zapobiega rozłączaniu" #~ msgid "Use cust_om hostname/port" #~ msgstr "Użyj wła_snej nazwy hosta/portu" #~ msgid "_Hostname: " #~ msgstr "_Nazwa hosta: " #~ msgid "_Port: " #~ msgstr "_Port:" #~ msgid "No key selected" #~ msgstr "Nie wybrano żadnego klucza" #~ msgid "Choose _Key..." #~ msgstr "Wybierz _klucz..." #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje pobieranie hasła z agenta GPG, np. " #~ "Seahorse" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #~ msgid "_Edit Personal Information..." #~ msgstr "_Zmień informacje o sobie..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Informacje o Tobie, takie jakie są przechowywane na serwerze" #~ msgid "Personal Information" #~ msgstr "Informacje o sobie" #~ msgid "Co_nnect on Gajim startup" #~ msgstr "P_ołącz przy starcie programu" #~ msgid "Synchroni_ze account status with global status" #~ msgstr "Synch_ronizuj status konta z globalnym statusem" #~ msgid "Use cust_om port:" #~ msgstr "Użyj inn_ego portu:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Jeżeli domyślny port, na którym przyjmowane są nadchodzące wiadomości nie " #~ "odpowiada ci, możesz wskazać numer portu, jakiego chcesz używać.\n" #~ "Konieczna stać się może ponowna konfiguracja firewalla." #~ msgid "Mer_ge accounts" #~ msgstr "_Połącz konta" #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "Nie można używać OpenPGP na tym komputerze" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Aby zmienić nazwę konta, musisz być rozłączony." #~ msgid "To change the account name, you must read all pending events." #~ msgstr "" #~ "Aby zmienić nazwę konta, musisz przeczytać wszystkie zaległe wiadomości." #~ msgid "Account Name Already Used" #~ msgstr "Konto o takiej nazwie już istnieje" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "Posiadasz już konto o tej nazwie. Zmień nazwę konta na unikalną." #~ msgid "Invalid account name" #~ msgstr "Niepoprawna nazwa konta" #~ msgid "Account name cannot be empty." #~ msgstr "Nazwa konta nie może być pusta." #~ msgid "Account name cannot contain spaces." #~ msgstr "Nazwa konta nie może zawierać spacji." #~ msgid "Enter a new name for account %s" #~ msgstr "Wpisz nową nazwę dla kontaktu %s." #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "Jabber ID musi być postaci \"użytkownik@nazwaserwera\"." #~ msgid "No such account available" #~ msgstr "Takie konto nie jest dostępne" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "Musisz najpierw stworzyć konto by móc edytować informacje o sobie." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "Musisz być połączony, aby móc zmieniać informacje o sobie." #, fuzzy #~ msgid "Your server does not have vCard support" #~ msgstr "Twój serwer nie akceptuje Vcard" #~ msgid "Your server can't save your personal information." #~ msgstr "Twój serwer nie potrafi zapisać informacji osobistych." #~ msgid "Account Local already exists." #~ msgstr "Konto o takiej nazwie już istnieje." #~ msgid "Please rename or remove it before enabling link-local messaging." #~ msgstr "" #~ "Proszę go zmienić lub usunąć przed uaktywnieniem komunikacji link-local." #~ msgid "THANKS:" #~ msgstr "Podziękowania:" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "" #~ "Nie można zapisywać do %s. Wsparcie dla Menadżera Sesji nie będzie działać" #~ msgid "Jabber Traffic" #~ msgstr "Jabber Traffic" #~ msgid "_Enable" #~ msgstr "_Włącz" #, fuzzy #~ msgid "Filter" #~ msgstr "Filtr" #~ msgid "_IQ" #~ msgstr "_IQ" #~ msgid "Info/Query" #~ msgstr "Informacje/Zapytanie" #~ msgid "_Message" #~ msgstr "Wiado_mość" #~ msgid "XML Input" #~ msgstr "Wejście XML" #~ msgid "XML Console for %s" #~ msgstr "Kosola XML dla %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "Bezczynny przez %s" #, fuzzy #~ msgid "" #~ "Request offline status messages from all contacts upon connecting. " #~ "WARNING: This causes a lot of requests to be sent!" #~ msgstr "" #~ "Pytaj o opis statusu \"Niepołączony\" wszystkich niepołączonych " #~ "kontaktów, kiedy jest połączenie z kontem. OSTRZEŻENIE: To może być " #~ "przyczyną wysyłania wielu zapytań!" #~ msgid "Last status: %s" #~ msgstr "Ostatni status %s" #~ msgid " since %s" #~ msgstr " od %s" #~ msgid "since %s" #~ msgstr "od %s" #, fuzzy #~ msgid "No" #~ msgstr "Żaden" #, fuzzy #~ msgid "Prefer" #~ msgstr "Ustawienia" #, fuzzy #~ msgid "Auto" #~ msgstr "Połącz automatycznie" #~ msgid "false" #~ msgstr "fałszywe" #~ msgid "stream" #~ msgstr "strumieniowane" #~ msgid "approve" #~ msgstr "zaakceptowane" #~ msgid "concede" #~ msgstr "przyznane" #~ msgid "forbid" #~ msgstr "zabronione" #~ msgid "prefer" #~ msgstr "zalecane" #~ msgid "require" #~ msgstr "wymagane" #~ msgid "expire" #~ msgstr "przedawnione" #~ msgid "otr" #~ msgstr "otr" #~ msgid "save" #~ msgstr "zapamiętane" #~ msgid "Last time we syncronized with logs from server." #~ msgstr "Czas ostatniej synchronizacji logów z serwerem" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Niepoprawna nazwa serwera" #, fuzzy #~ msgid "There is an error" #~ msgstr "Wystąpił błąd" #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "Ile minut powinny być widoczne linie z poprzedniej rozmowy." #~ msgid "" #~ "Your configured emoticons theme cannot been loaded. You maybe need to " #~ "update the format of emoticons.py file. See http://trac.gajim.org/wiki/" #~ "Emoticons for more details." #~ msgstr "" #~ "Ustawiony przez ciebie styl emotikonów nie mógł zostać załadowany. Ty " #~ "możesz potrzebować aktualizacji formatu pliku emoticons.file. Aby poznać " #~ "więcej szczegółów, zobacz http://trac.gajim.org/wiki/Emoticons." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Zostanie połączony z %s bez obsługi OpenPGP." #~ msgid "The following message was NOT encrypted" #~ msgstr "Ta wiadomość NIE została zaszyfrowana" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Włączono szyfrowanie ESession dla tego konta." #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Włącz/wyłącz szyfrowanie Open_PGP" #~ msgid "Toggle End to End Encryption" #~ msgstr "Włącz/wyłącz _szyfrowanie połączenia" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "Szyfrowanie GPG włączone" #, fuzzy #~ msgid "No OpenPGP key assigned" #~ msgstr "Nie ma przypisanego klucza GPG" #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages with OpenPGP." #~ msgstr "" #~ "Nie ma klucza GPG przypisanego do tego kontaktu. Więc nie możesz " #~ "szyfrować wiadomości do tego kontaktu, używając GPG." #~ msgid "Session WILL be logged" #~ msgstr "Sesja BĘDZIE logowana" #~ msgid "Session WILL NOT be logged" #~ msgstr "Sesja NIE BĘDZIE logowana" #~ msgid "is" #~ msgstr "jest" #~ msgid "is NOT" #~ msgstr "NIE jest" #~ msgid "will" #~ msgstr "będzie" #~ msgid "will NOT" #~ msgstr "NIE będzie" #~ msgid "The following message was encrypted" #~ msgstr "Ta wiadomość została zaszyfrowana" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Włącz/wyłącz szyfrowanie Open_PGP" #~ msgid "Is OpenPGP enabled for this contact?" #~ msgstr "Czy OpenPGP jest włączone dla tego kontaktu?" #~ msgid "" #~ "Should Gajim automatically start an encrypted session with this contact " #~ "when possible?" #~ msgstr "" #~ "Czy Gajim powinien automatycznie rozpoczynać zaszyfrowana sesję z tym " #~ "kontaktem, jeśli to możliwe?" #~ msgid "Neither the remote presence is signed, nor a key was assigned." #~ msgstr "" #~ "Komunikat o statusie obecności nie jest podpisany, nie przypisano mu też " #~ "klucza." #~ msgid "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "Klucz kontaktu (%s) nie pasuje do klucza przypisanego w Gajimie." #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Ta wiadomość jest zaszyfrowana (Zobacz :XEP: '27']" #~ msgid "" #~ "Your chat session with %(jid)s is encrypted.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Twoja rozmowa z %(jid)s jest szyfrowana.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgid "You have already verified this contact's identity." #~ msgstr "Już zweryfikowałeś tożsamość tego kontaktu." #~ msgid "Contact's identity verified" #~ msgstr "Tożsamość rozmówcy zweryfikowana" #, fuzzy #~ msgid "Verify again…" #~ msgstr "Ponowna weryfikacja..." #~ msgid "" #~ "To be certain that only the expected person can read your messages " #~ "or send you messages, you need to verify their identity by clicking the " #~ "button below." #~ msgstr "" #~ "Aby być pewnym, że tylko oczekiwane osoby będą mogły czytać twoje " #~ "wiadomości lub wysyłać wiadomości do ciebie, powinieneś zweryfikować ich " #~ "tożsamość poprzez kliknięcie przycisku poniżej." #~ msgid "Contact's identity NOT verified" #~ msgstr "Tożsamość rozmówcy NIE zweryfikowana" #, fuzzy #~ msgid "Verify…" #~ msgstr "_Weryfikuj" #~ msgid "Have you verified the contact's identity?" #~ msgstr "Czy zweryfikowałeś/zweryfikowałaś tożsamość zdalnego rozmówcy?" #~ msgid "" #~ "To prevent talking to an unknown person, you should speak to %(jid)s directly (in person or on the phone) and verify that they see the same " #~ "Short Authentication String (SAS) as you.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Aby uniemożliwić rozmowę z nieznaną osobą, powinieneś porozmawiać z " #~ "%(jid)s bezpośrednio(np. przez telefon) i zweryfikować jej tożsamość, " #~ "ta osoba zobaczy ten sam Short Authentication String (SAS) jak ty.\n" #~ "Tej sesji Short Authentication String to %(sas)s." #~ msgid "Did you talk to the remote contact and verify the SAS?" #~ msgstr "Czy rozmawiałeś(aś) ze zdalnym rozmówcą i zweryfikowałeś(aś) SAS?" #~ msgid "" #~ "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "" #~ "Klucz kontaktu (%s) nie pasuje do klucza przypisanego w Gajimie." #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages." #~ msgstr "" #~ "Nie ma klucza GPG przypisanego do tego kontaktu. Więc nie możesz " #~ "szyfrować wiadomości do niego, używając GPG." #, fuzzy #~ msgid "" #~ "OpenPGP key is assigned to this contact, but you do not trust their " #~ "key, so message cannot be encrypted. Use your OpenPGP client " #~ "to trust their key." #~ msgstr "" #~ "Klucz GPG jest przypisany do tego kontaktu, lecz ty nie importowałeś " #~ "tego klucza, więc wiadomość nie będzie odszyfrowana. Użyj " #~ "twojego klienta GPG, aby importować klucz." #, fuzzy #~ msgid "" #~ "OpenPGP Key is assigned to this contact, and you trust their key, so " #~ "messages will be encrypted." #~ msgstr "" #~ "Ten użytkownik ma przypisany klucz, zweryfikowałeś ten klucz, więc " #~ "wiadomości będą szyfrowane" #~ msgid "" #~ "This icon indicates that this message has not yet\n" #~ "been received by the remote end. If this icon stays\n" #~ "for a long time, it's likely the message got lost." #~ msgstr "" #~ "Ta ikona wskazuje, że ta wiadomość jeszcze nie została\n" #~ "odebrana. Jeśli ta ikona zostanie przez długi czas,\n" #~ "może oznaczać, że wiadomości została zgubiona." #~ msgid "" #~ "If True, listen to D-Bus signals from NetworkManager and change the " #~ "status of accounts (provided they do not have listen_to_network_manager " #~ "set to False and they sync with global status) based upon the status of " #~ "the network connection." #~ msgstr "" #~ "Jeżeli opcja ustawiona jest na True, Gajim nasłuchuje komunikatów D-Bus " #~ "wysyłanych przez NetworkManagera i zmienia status poszczególnych kont (o " #~ "ile nie mają ustawionej opcji listen_to_network_manager) na False i " #~ "synchronizują się ze statusem globalnym) w oparciu o status " #~ "wykorzystywanego połączenia sieciowego." #~ msgid "" #~ "The database file (%s) cannot be read. Try to repair it or remove it (all " #~ "history will be lost)." #~ msgstr "" #~ "Plik (%s) bazy danych nie może zostać odczytany. Spróbuj to naprawić lub " #~ "usunąć ten plik (cała historia rozmów będzie usunięta)." #~ msgid "Database cannot be read." #~ msgstr "Baza danych nie może zostać odczytana." #~ msgid "A message from a non-valid JID arrived, it has been ignored." #~ msgstr "Doszła wiadomość od nieprawidłowego JID, będzie zignorowana" #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Płynne przewijanie w oknie rozmowy" #~ msgid "Show _XML Console" #~ msgstr "Konsola _XML" #~ msgid "Edit _Privacy Lists..." #~ msgstr "_Edytuj listy prywatności" #~ msgid "_Administrator" #~ msgstr "_Administrator" #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "" #~ "Wysyła wiadomość do użytkowników aktualnie połączonych z tym serwerem" #~ msgid "Sets Message of the Day" #~ msgstr "Ustawia Wiadomość Dnia" #~ msgid "Updates Message of the Day" #~ msgstr "Uaktualnia Wiadomość Dnia" #~ msgid "Deletes Message of the Day" #~ msgstr "Usuwa Wiadomość Dnia" #~ msgid "Add _Contact..." #~ msgstr "Dodaj _kontakt..." #~ msgid "_Accounts" #~ msgstr "_Konta" #~ msgid "Profile, A_vatar" #~ msgstr "Profil, _Awatar" #~ msgid "P_lugins" #~ msgstr "_Wtyczki" #~ msgid "File _Transfers" #~ msgstr "_Przesyłanie plików" #~ msgid "Help online" #~ msgstr "Pomoc w sieci" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Najczęściej Zadawane Pytania (w sieci)" #~ msgid "Fea_tures" #~ msgstr "_Możliwości programu" #~ msgid "to %s account" #~ msgstr "do konta %s" #~ msgid "using %s account" #~ msgstr "używając konta %s" #~ msgid "of account %s" #~ msgstr "dla konta %s" #~ msgid "for account %s" #~ msgstr "dla konta %s" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Usuwając kontakt cofniesz mu również autoryzację, co spowoduje, że " #~ "kontakt będzie zawsze widział Cię jako rozłączonego." #~ msgid "Invalid Jabber ID" #~ msgstr "Niepoprawny Jabber ID" #~ msgid "Verify..." #~ msgstr "Weryfikowanie..." #~ msgid "This file is being used by another process." #~ msgstr "Ten plik jest używany przez inny proces." #~ msgid "pgp key" #~ msgstr "klucz pgp" #~ msgid "" #~ "Sends new single message to a contact in the roster. Both OpenPGP key and " #~ "account are optional. If you want to set only 'account', without 'OpenPGP " #~ "key', just set 'OpenPGP key' to ''." #~ msgstr "" #~ "Wysyła nową wiadomość do kontaktu z listy. Zarówno klucz OpenPGP jak i " #~ "konto nie są wymagane. Jeśli chcesz ustawić jedynie 'konto' bez 'klucza " #~ "OpenPGP', to ustaw 'klucz OpenPGP' na ''." #, fuzzy #~ msgid "Please first choose another theme as your current theme." #~ msgstr "Ustaw najpierw inny motyw." #~ msgid "A non-privacy-related room configuration change has occurred" #~ msgstr "Nastąpiła zmiana konfiguracji pokoju (nie powiązana z prywatnością)" #, fuzzy #~ msgid "Maximum number of users for %s has been reached" #~ msgstr "Osiągnięto maksymalną liczbę użytkowników dla %s" #~ msgid "Your passphrase is incorrect" #~ msgstr "Twoje hasło jest niepoprawne" #, fuzzy #~ msgid "OpenPGP Passphrase Incorrect" #~ msgstr "Niepoprawne hasło OpenPGP" #, fuzzy #~ msgid "OpenPGP key not trusted" #~ msgstr "GPG nie jest zaufany" #~ msgid "You successfully received %(filename)s from %(name)s." #~ msgstr "Otrzymałeś plik %(filename)s od %(name)s." #, fuzzy #~ msgid "Set logs directory" #~ msgstr "tworzenie katalogu %s" #~ msgid "Chats" #~ msgstr "Rozmowy" #~ msgid "_Manage Bookmarks..." #~ msgstr "_Zarządzaj zakładkami..." #~ msgid "Change Status Message..." #~ msgstr "Zmień opis statusu..." #~ msgid "_Change Status Message..." #~ msgstr "_Zmień opis statusu..." #~ msgid "" #~ "You are not interested in the contact's presence, and neither he/she is " #~ "interested in yours" #~ msgstr "" #~ "Nie jesteś zainteresowany informacjami o statusie kontaktu i on również " #~ "nie jest zainteresowany twoim" #~ msgid "Error description..." #~ msgstr "Opis błędu..." #, fuzzy #~ msgid "View contact information (Ctrl+I)" #~ msgstr "Zaproś kontakt do rozmowy (Ctrl+G)" #~ msgid "3" #~ msgstr "3" #~ msgid "4" #~ msgstr "4" #~ msgid "5" #~ msgstr "5" #~ msgid "6" #~ msgstr "6" #~ msgid "7" #~ msgstr "7" #~ msgid "8" #~ msgstr "8" #~ msgid "9" #~ msgstr "9" #, fuzzy #~ msgid "Groupchat Histories" #~ msgstr "Pokoje" #, fuzzy #~ msgid "All Chat Histories" #~ msgstr "Stare historie" #~ msgid "homepage url" #~ msgstr "adres strony domowej" #~ msgid "More" #~ msgstr "Więcej" #~ msgid "creating %s directory" #~ msgstr "tworzenie katalogu %s" #~ msgid "" #~ "If True, Gajim will use KDE Wallet (if kwalletcli is available) to store " #~ "account passwords." #~ msgstr "" #~ "Po włączeniu Gajim użyje aplikacji KDE Wallet do przechowywania haseł (o " #~ "ile biblioteka kwalletcli jest zainstalowana)." #~ msgid "%s is not the name of a group chat." #~ msgstr "%s nie jest nazwą czatu." #~ msgid "Session Management" #~ msgstr "Zarządzanie sesją" #~ msgid "Gajim session is stored on logout and restored on login." #~ msgstr "" #~ "Sesja jest zapisywana przy wylogowaniu z serwera i przywracana przy " #~ "logowaniu." #~ msgid "Requires python-gnome2." #~ msgstr "Wymaga python-gnome2." #~ msgid "Requires gnome-keyring and python-gnome2-desktop, or kwalletcli." #~ msgstr "Wymaga gnome-keyring oraz python-gnome2-desktop albo kwalletcli." #~ msgid "SRV" #~ msgstr "SRV" #~ msgid "Ability to connect to servers which are using SRV records." #~ msgstr "Możliwość połączenia z serwerami, które używają rekordów SRV." #~ msgid "Requires dnsutils." #~ msgstr "Wymaga dnsutils." #~ msgid "Requires nslookup to use SRV records." #~ msgstr "Wymaga nslookup." #~ msgid "Gajim needs X server to run. Quiting..." #~ msgstr "Gajim wymaga do działania serwera X. Zamykanie programu..." #~ msgid "importing PyGTK failed: %s" #~ msgstr "import PyGTK nie powiódł się: %s" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above" #~ msgstr "Gajim wymaga PyGTK w wersji 2.16 lub wyższej" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above to run. Quiting..." #~ msgstr "" #~ "Gajim wymaga do działania PyGTK w wersji 2.16 lub wyższej. Zamykanie " #~ "programu..." #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above" #~ msgstr "Gajim wymaga GTK w wersji 2.16 lub wyższej" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above to run. Quiting..." #~ msgstr "" #~ "Gajim wymaga do działania GTK w wersji 2.16 lub wyższej. Zamykanie " #~ "programu..." #~ msgid "Gajim needs pywin32 to run" #~ msgstr "Gajim wymaga do działania pakietu pywin32" #~ msgid "" #~ "Please make sure that Pywin32 is installed on your system. You can get it " #~ "at %s" #~ msgstr "" #~ "Proszę upewnić się, że zainstalowany jest pakiet Pywin32. Możesz go " #~ "pobrać spod adresu %s" #~ msgid "Gajim is already running" #~ msgstr "Gajim jest już uruchomiony" #~ msgid "" #~ "Another instance of Gajim seems to be running\n" #~ "Run anyway?" #~ msgstr "" #~ "Wydaje się, że w tle działa już inna kopia Gajima.\n" #~ "Czy mimo to chcesz uruchomić program?" #~ msgid "A programming error has been detected" #~ msgstr "Wykryto błąd programistyczny" #~ msgid "Details" #~ msgstr "Szczegóły" #, fuzzy #~ msgid "" #~ "Gnome Keyring is installed but not correctly started (environment " #~ "variable probably not correctly set)" #~ msgstr "" #~ "Menedżer bazy kluczy GNOME jest zainstalowany, ale nie został \t\t\t" #~ "\tprawidłowo uruchomiony(zmienna środowiskowa prawdopodobnie nie jest \t\t" #~ "\t\t właściwie ustawiona)" #~ msgid "Jabber ID: " #~ msgstr "Jabber ID:" #~ msgid "Resource: " #~ msgstr "Zasoby: " #~ msgid "Subscription: " #~ msgstr "Autoryzacja: " #, fuzzy #~ msgid "Mood: " #~ msgstr "Nastrój:" #, fuzzy #~ msgid "Activity: " #~ msgstr "Aktywność:" #~ msgid "Join _Group Chat..." #~ msgstr "Dołącz do _pokoju" #~ msgid "_Modify Account" #~ msgstr "_Modyfikuj konto" #~ msgid "Check on startup if Gajim is the _default Jabber client" #~ msgstr "" #~ "Przy starcie zawsze sprawdzaj czy Gajim jest _domyślnym klientem Jabbera" #~ msgid "_Group Chat" #~ msgstr "_Pokój" #~ msgid "" #~ "If True, Gajim will check if it's the default jabber client on each " #~ "startup." #~ msgstr "" #~ "Jeśli ma wartość True, Gajim sprawdzi przy każdym uruchomieniu czy jest " #~ "domyślnym klientem Jabbera." #~ msgid "Gajim is not the default Jabber client" #~ msgstr "Gajim nie jest domyślnym klinetem Jabbera" #~ msgid "Would you like to make Gajim the default Jabber client?" #~ msgstr "Czy chciałbyś by Gajim stał się klientem domyślnym?" #~ msgid "Always check to see if Gajim is the default Jabber client on startup" #~ msgstr "Przy starcie sprawdzaj czy Gajim jest domyślnym klinetem Jabbera" #~ msgid "Send Single Message" #~ msgstr "Wyślij wiadomość" #~ msgid "Execute Command..." #~ msgstr "Wykonaj komendę..." #~ msgid " a window/tab opened with that contact " #~ msgstr "z tym kontaktem " #~ msgid "Actions" #~ msgstr "Akcje" #~ msgid "Conditions" #~ msgstr "Warunki" #~ msgid "Advanced Actions" #~ msgstr "Opcje zaawansowane" #~ msgid "Advanced Notifications Control" #~ msgstr "Edytor ustawień zaawansowanych" #~ msgid "Busy " #~ msgstr "Zajęty " #, fuzzy #~ msgid "Contact Change Status " #~ msgstr "Kontakt zmienił status" #~ msgid "Don't have " #~ msgstr "nie rozmawiam " #, fuzzy #~ msgid "File Transfer Started " #~ msgstr "Przesyłanie pliku zatrzymane" #, fuzzy #~ msgid "Group Chat Message Highlight " #~ msgstr "Podświetlenie wiadomości z czatu" #, fuzzy #~ msgid "Group Chat Message Received " #~ msgstr "Otrzymano wiadomość na czacie" #~ msgid "Launch a command" #~ msgstr "Wykonaj komendę" #~ msgid "One or more special statuses..." #~ msgstr "Jeden bądź więcej określonych statusów..." #~ msgid "Online / Free For Chat" #~ msgstr "Dostępny / Chętny do rozmowy" #~ msgid "Play a sound" #~ msgstr "Odtwórz dźwięk" #~ msgid "When " #~ msgstr "Jeżeli " #~ msgid "" #~ "_Activate window manager's UrgencyHint to make chat window in taskbar " #~ "flash" #~ msgstr "_Migaj obramowaniem zminimalizowanego okna rozmowy" #~ msgid "_Disable auto opening chat window" #~ msgstr "Wyłącz _automatyczne otwieranie okna czatu" #~ msgid "_Disable existing popup window" #~ msgstr "_Wyłącz wyskakujące okienka" #~ msgid "_Disable existing sound for this event" #~ msgstr "_Wyłącz dźwięki dla tego zdarzenia" #, fuzzy #~ msgid "_Disable showing event in notification area" #~ msgstr "Wyłącz _pokazywanie zdarzenia na liście kontaktów" #~ msgid "_Disable showing event in roster" #~ msgstr "Wyłącz _pokazywanie zdarzenia na liście kontaktów" #~ msgid "_Inform me with a popup window" #~ msgstr "_Powiadom mnie wyskakującym okienkiem" #~ msgid "_Open chat window with user" #~ msgstr "_Otwórz okno rozmowy z kontaktem" #~ msgid "_Show event in roster" #~ msgstr "_Pokaż zdarzenie na liście kontaktów" #~ msgid "and I " #~ msgstr "podczas, gdy " #~ msgid "contact(s)" #~ msgstr "kontakt(y)" #~ msgid "for " #~ msgstr "dla " #~ msgid "group(s)" #~ msgstr "grupa/y" #~ msgid "when I'm in" #~ msgstr "kiedy jestem obecny" #~ msgid "_Allow him/her to see my status" #~ msgstr "_Pozwól mu/jej widzieć swój status" #~ msgid "Descrition:" #~ msgstr "Opis:" #~ msgid "Advanced..." #~ msgstr "Zaawansowane..." #~ msgid "Display _activity of contacts in roster" #~ msgstr "Wyświetlaj aktywność kontaktów z listy" #~ msgid "Display _tunes of contacts in roster" #~ msgstr "Wyświetlaj muzyczne ikonki kontaktów z listy" #~ msgid "Display m_ood of contacts in roster" #~ msgstr "Wyświetlaj nastroje kontaktów z listy" #~ msgid "" #~ "If checked, Gajim will display the activity of contacts in the roster " #~ "window" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje wyświetlanie aktywności kontaktów z listy " #~ "kontaktów" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the location of contacts in the roster " #~ "window" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje wyświetlanie nastrojów w oknie listy " #~ "kontaktów (roster oraz okno czatu)" #~ msgid "" #~ "If checked, Gajim will display the tunes of contacts in the roster window" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje wyświetlanie muzycznych ikonek w oknie " #~ "listy kontaktów (roster oraz okno czatu)" #~ msgid "Gajim Instant Messenger" #~ msgstr "Komunikator Gajim" #~ msgid "English" #~ msgstr "angielski" #~ msgid "Belarusian" #~ msgstr "bułgarski" #~ msgid "Bulgarian" #~ msgstr "bułgarski" #~ msgid "Breton" #~ msgstr "bretoński" #~ msgid "Czech" #~ msgstr "czeski" #~ msgid "German" #~ msgstr "niemiecki" #~ msgid "Greek" #~ msgstr "grecki" #~ msgid "British" #~ msgstr "brytyjski" #~ msgid "Esperanto" #~ msgstr "esperanto" #~ msgid "Spanish" #~ msgstr "hiszpański" #~ msgid "Basque" #~ msgstr "baskijski" #~ msgid "French" #~ msgstr "francuski" #~ msgid "Croatian" #~ msgstr "chorwacki" #~ msgid "Italian" #~ msgstr "włoski" #~ msgid "Norwegian (b)" #~ msgstr "norweski (b)" #~ msgid "Dutch" #~ msgstr "holenderski" #~ msgid "Norwegian" #~ msgstr "norweski" #~ msgid "Polish" #~ msgstr "polski" #~ msgid "Portuguese" #~ msgstr "portugalski" #~ msgid "Brazilian Portuguese" #~ msgstr "portugalski (Brazylia)" #~ msgid "Russian" #~ msgstr "rosyjski" #~ msgid "Serbian" #~ msgstr "serbski" #~ msgid "Slovak" #~ msgstr "słowacki" #~ msgid "Swedish" #~ msgstr "szwedzki" #~ msgid "Chinese (Ch)" #~ msgstr "chiński (Ch)" #~ msgid "Spelling language" #~ msgstr "Wybierz słownik" #~ msgid "Requires python-farsight." #~ msgstr "Wymaga python-farsight." #~ msgid "" #~ "If True, Gajim will convert string between $$ and $$ to an image using " #~ "dvips and convert before insterting it in chat window." #~ msgstr "" #~ "Jeżeli ustawiono na 'True', Gajim dokona konwersji ciągów zawartych " #~ "pomiędzy $$ i $$ do postaci obrazu (z wykorzystaniem dvips) przed " #~ "wstawieniem ich do okna rozmowy." #~ msgid "" #~ "Change the value to change the size of latex formulas displayed. The " #~ "higher is larger." #~ msgstr "Zmień rozmiar pokazywanych formuł latex-a." #~ msgid "all or space separated status" #~ msgstr "all lub komunikaty stanu rozdzielone spacjami" #~ msgid "'yes', 'no', or 'both'" #~ msgstr "'yes', 'no' lub 'both'" #~ msgid "'yes', 'no' or ''" #~ msgstr "'yes', 'no' lub \"" #~ msgid "Check your connection or try again later" #~ msgstr "Sprawdź swoje połączenie lub spróbuj później" #~ msgid "Error executing \"%(command)s\": %(error)s" #~ msgstr "Błąd przy wykonywaniu \"%(command)s\": %(error)s" #~ msgid "error: cannot open %s for reading" #~ msgstr "błąd: nie można otworzyć %s do odczytu" #~ msgid "Unable to bind to port %s." #~ msgstr "Nie można podłączyć się do portu %s." #~ msgid "" #~ "Maybe you have another running instance of Gajim. File Transfer will be " #~ "cancelled." #~ msgstr "" #~ "Być może masz już uruchomioną inną kopię Gajima. Przesyłanie plików " #~ "zostanie anulowane." #~ msgid "A GTK+ jabber client" #~ msgstr "Klient jabbera w GTK+." #~ msgid "Condition" #~ msgstr "Warunek" #~ msgid "when I am " #~ msgstr "kiedy mam " #~ msgid "Requires pybonjour (http://o2s.csail.mit.edu/o2s-wiki/pybonjour)." #~ msgstr "Wymaga pybonjour (http://o2s.csail.mit.edu/o2s-wiki/pybonjour)" #~ msgid "LaTeX" #~ msgstr "LaTeX" #~ msgid "Transform LaTeX expressions between $$ $$." #~ msgstr "Przekształcanie wyrażeń jezyka LaTeX pomiędzy $$ $$." #, fuzzy #~ msgid "" #~ "Requires texlive-latex-base and (dvipng or ImageMagick). You have to set " #~ "'use_latex' to True in the Advanced Configuration Editor." #~ msgstr "" #~ "Wymaga texlive-latex-base, dvipng. Musisz ustawić zmienną 'use_latex' na " #~ "'True' w Zaawansowanym Edytorze Ustawień." #, fuzzy #~ msgid "" #~ "Requires texlive-latex-base and (dvipng or ImageMagick) (All is in " #~ "MikTeX). You have to set 'use_latex' to True in the Advanced " #~ "Configuration Editor." #~ msgstr "" #~ "Wymaga texlive-latex-base, dvipng (Wszystko jest w MikTeX). Musisz " #~ "ustawić zmienną 'use_latex' na 'True' w Zaawansowanym Edytorze Ustawień." #~ msgid "one of: offline, online, chat, away, xa, dnd, invisible " #~ msgstr "" #~ "jeden z: rozłączony, dostępny, chętny do rozmowy, zaraz wracam, " #~ "nieobecny, zajęty, niewidoczny " #, fuzzy #~ msgid "" #~ "Returns current status message(the global one unless account is specified)" #~ msgstr "Zwraca obecny status (globalny, chyba że zostało wskazane konto)." #~ msgid "" #~ "Usage: %s %s %s \n" #~ "\t %s" #~ msgstr "" #~ "Użycie: %s %s %s \n" #~ "\t %s" #, fuzzy #~ msgid "" #~ "Too many arguments. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Za dużo argumentów. \n" #~ "Wpisz \"%(basename)s help %(command)s\" aby uzyskać więcej informacji" #, fuzzy #~ msgid "" #~ "Argument \"%s\" is not specified. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Argument \"%(arg)s\" nie jest określony. \n" #~ "Wpisz \"%(basename)s help %(command)s\" aby uzyskać więcej informacji" #~ msgid "Disk WriteError" #~ msgstr "Błąd zapisu na dysk" #~ msgid "Subject: %s" #~ msgstr "Temat: %s" #~ msgid "Mood: %s" #~ msgstr "Nastrój: %s" #, fuzzy #~ msgid "Activity: %s" #~ msgstr "Aktywność:" #~ msgid "@" #~ msgstr "@" #~ msgid "_Disable showing event in systray" #~ msgstr "Wyłącz pokazywanie _zdarzenia w obszarze powiadamiania" #~ msgid "_Show event in systray" #~ msgstr "Pokaż _zdarzenie w obszarze powiadamiania" #, fuzzy #~ msgid "Always use GNOME default applications" #~ msgstr "Zawsze używaj domyślnych apikacji OS X" #, fuzzy #~ msgid "Always use Xfce default applications" #~ msgstr "Zawsze używaj domyślnych apikacji OS X" #, fuzzy #~ msgid "Autodetect on every Gajim startup" #~ msgstr "P_ołącz przy starcie programu" #~ msgid "Show systray:" #~ msgstr "Pokaż _zdarzenie w obszarze powiadamiania" #~ msgid "Nickname not allowed: %s" #~ msgstr "Pseudonim jest niedozwolony: %s" #~ msgid "we are now subscribed to %s" #~ msgstr "Zapisaliśmy się do %s" #~ msgid "we are now unsubscribed from %s" #~ msgstr "Wypisaliśmy się z %s" #~ msgid "Account Modification" #~ msgstr "Modyfikacja konta" #~ msgid "" #~ "Check this so Gajim will connect in port 5223 where legacy servers are " #~ "expected to have SSL capabilities. Note that Gajim uses TLS encryption by " #~ "default if broadcasted by the server, and with this option enabled TLS " #~ "will be disabled" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje łączenia na porcie 5223 gdzie większość " #~ "serwerów udostępnia usługę SSL. Gajim używa szyfrowania TLS domyślnie, " #~ "jeśli tylko serwer daje taką możliwość. Ta opcja wyłącza TLS" #~ msgid "Edit Personal Information..." #~ msgstr "Zmień informacje o sobie..." #~ msgid "Hostname: " #~ msgstr "Nazwa hosta: " #~ msgid "" #~ "If checked, Gajim will store the password in ~/.gajim/config with 'read' " #~ "permission only for you" #~ msgstr "" #~ "Zaznaczanie tej opcji spowoduje przechowywanie hasła w pliku ~/.gajim/" #~ "config z prawem do odczytu tylko dla ciebie" #~ msgid "Port: " #~ msgstr "Port: " #~ msgid "Save _passphrase (insecure)" #~ msgstr "Zapisz _hasło (nie jest to bezpieczne)" #~ msgid "Use _SSL (legacy)" #~ msgstr "Korzystaj z _SSL" #~ msgid "gtk-add" #~ msgstr "gtk-add" #~ msgid "gtk-close" #~ msgstr "gtk-close" #~ msgid "gtk-remove" #~ msgstr "gtk-remove" #~ msgid "" #~ "Receive a Message\n" #~ "Contact Disconnected \n" #~ "Contact Change Status \n" #~ "Group Chat Message Highlight \n" #~ "Group Chat Message Received \n" #~ "File Transfer Request \n" #~ "File Transfer Started \n" #~ "File Transfer Finished" #~ msgstr "" #~ "otrzymam wiadomość\n" #~ "kontakt się rozłączy \n" #~ "kontakt zmieni status \n" #~ "na czacie pojawi się słowo kluczowe \n" #~ "otrzymam wiadomość na czacie \n" #~ "pojawi się żądanie przesłania pliku \n" #~ "rozpocznie się transfer pliku \n" #~ "zakończy się transfer pliku" #~ msgid "" #~ "contact(s)\n" #~ "group(s)\n" #~ "everybody" #~ msgstr "" #~ "kontaktu(-ów)\n" #~ "grupy(grup)\n" #~ "wszystkich" #~ msgid "" #~ "Account row\n" #~ "Group row\n" #~ "Contact row\n" #~ "Chat Banner" #~ msgstr "" #~ "Konto\n" #~ "Grupa\n" #~ "Kontakt\n" #~ "Banner" #~ msgid "" #~ "Enter JID or Contact name\n" #~ "Groupchat Histories\n" #~ "All Chat Histories" #~ msgstr "" #~ "Wpisz JID lub nazwe kontaktu\n" #~ "Historia rozmów grupowych\n" #~ "Wszystkie historie rozmów" #~ msgid "gtk-delete" #~ msgstr "gtk-delete" #~ msgid "Send a file (Ctrl+F)" #~ msgstr "Wyślij plik (Ctrl+F)" #~ msgid "" #~ "All chat states\n" #~ "Composing only\n" #~ "Disabled" #~ msgstr "" #~ "Wszystkie stany rozmowy\n" #~ "Tylko dotyczące pisania\n" #~ "Wyłączone" #~ msgid "" #~ "Autodetect on every Gajim startup\n" #~ "Always use GNOME default applications\n" #~ "Always use KDE default applications\n" #~ "Always use Xfce default applications\n" #~ "Custom" #~ msgstr "" #~ "Automatyczne wykrywanie przy każdym uruchomieniu Gajima\n" #~ "Zawsze używaj domyślnych aplikacji GNOME\n" #~ "Zawsze używaj domyślnych aplikacji KDE\n" #~ "Zawsze używaj domyślnych aplikacji Xfce\n" #~ "Własne" #~ msgid "" #~ "Detached roster with detached chats\n" #~ "Detached roster with single chat\n" #~ "Single window for everything\n" #~ "Detached roster with chat grouped by account\n" #~ "Detached roster with chat grouped by type" #~ msgstr "" #~ "Oddzielne okno rostera, oddzielne okna czatów\n" #~ "Oddzielne okno rostera, wspólne okno rozmów\n" #~ "Jedno, wspólne okno dla rostera i rozmów\n" #~ "Oddzielne okno rostera, rozmowy grupowane według konta\n" #~ "Oddzielne okno rostera, rozmowy grupowane według typu" #~ msgid "" #~ "Pop it up\n" #~ "Notify me about it\n" #~ "Show only in roster" #~ msgstr "" #~ "Otwórz okno\n" #~ "Powiadom mnie o tym\n" #~ "Pokaż tylko w rosterze" #~ msgid "" #~ "none\n" #~ "both\n" #~ "from\n" #~ "to" #~ msgstr "" #~ "brak\n" #~ "obie\n" #~ "od\n" #~ "do" #~ msgid "gtk-cancel" #~ msgstr "gtk-cancel" #~ msgid "pysqlite2 (aka python-pysqlite2) dependency is missing. Exiting..." #~ msgstr "" #~ "Nie znaleziono biblioteki pysqlite2 (lub python-pysqlite2). Kończenie " #~ "pracy programu..." #~ msgid "Banners and clickable links" #~ msgstr "Banery i klikalne linki" #~ msgid "Ability to have clickable URLs in chat and groupchat window banners." #~ msgstr "Dodaje możliwość wyświetlania aktywnych ('klikalnych') adresów URL." #~ msgid "Requires python-sexy." #~ msgstr "Wymaga python-sexy" #~ msgid "GTK+ runtime is missing libglade support" #~ msgstr "W GTK+ brakuje wsparcia dla libglade" #~ msgid "" #~ "Please remove your current GTK+ runtime and install the latest stable " #~ "version from %s" #~ msgstr "" #~ "Proszę usunąć obecną wersje GTK+ i zainstalować najnowszą stabilną wesję " #~ "z %s" #~ msgid "" #~ "Please make sure that GTK+ and PyGTK have libglade support in your system." #~ msgstr "" #~ "Sprawdź, czy GTK+ oraz PyGTK posiadają w twoim systemie wsparcie dla " #~ "libglade." #~ msgid "Gajim needs PySQLite2 to run" #~ msgstr "Gajim wymaga do działania PySQLite2" #, fuzzy #~ msgid "gtk-ok" #~ msgstr "gtk-close" #~ msgid "" #~ "The host %s you configured as the ft_add_hosts_to_send advanced option is " #~ "not valid, so ignored." #~ msgstr "" #~ "Nazwa hosta %s, którą określiłeś w opcji ft_add_hosts_to_send jest " #~ "niepoprawna, będzie więc ignorowana." #~ msgid "OpenPGP passphrase was not given" #~ msgstr "Nie podano klucza OpenPGP" #~ msgid "" #~ "To continue sending and receiving messages, you will need to reconnect." #~ msgstr "" #~ "Aby dalej wysyłać i odbierać wiadomości musisz się ponownie połączyć." #~ msgid "" #~ "You are not connected or not visible to others. Your message could not be " #~ "sent." #~ msgstr "" #~ "Nie jesteś połączony, lub masz status 'niewidoczny'. Twoja wiadomość nie " #~ "mogła zostać wysłana." #~ msgid "[This message is encrypted]" #~ msgstr "[Ta wiadomość jest zaszyfrowana]" #~ msgid "Trayicon" #~ msgstr "Ikona w obszarze powiadamiania" #~ msgid "A icon in systemtray reflecting the current presence." #~ msgstr "Ikona w obszarze powiadamiania odzwierciedla aktualny status." #~ msgid "" #~ "Requires python-gnome2-extras or compiled trayicon module from Gajim " #~ "sources." #~ msgstr "" #~ "Wymaga python-gnome2-extras lub skompilowanego modułu trayicon ze źródeł " #~ "Gajima." #~ msgid "Requires PyGTK >= 2.10." #~ msgstr "Wymaga PyGTK >= 2.10." #~ msgid "Add Special _Notification" #~ msgstr "Dodaj powiadomienia _specjalne" #~ msgid "Assign Open_PGP Key" #~ msgstr "Przypisz klucz Open_PGP" #~ msgid "Commands: %s" #~ msgstr "Polecenia: %s" #~ msgid "" #~ "Usage: /%(command)s , sends action to the current group chat. Use " #~ "third person. (e.g. /%(command)s explodes.)" #~ msgstr "" #~ "Użycie: /%(command)s spowoduje wysłanie działania do " #~ "aktualnego pokoju. Używaj w trzeciej osobie. (np. /%(command)s " #~ "eksploduje.)" #~ msgid "No help info for /%s" #~ msgstr "Brak informacji o pomocy dla /%s" #~ msgid "Enable link-local/zeroconf messaging" #~ msgstr "Uaktywnij komunikację link-local/zeroconf" #~ msgid "Nickname not found: %s" #~ msgstr "Pseudonim nie został odnaleziony: %s" #~ msgid "This group chat has no subject" #~ msgstr "Ten pokój nie ma tematu" #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], bans the JID from the group chat. The " #~ "nickname of an occupant may be substituted, but not if it contains \"@\". " #~ "If the JID is currently in the group chat, he/she/it will also be kicked." #~ msgstr "" #~ "Użycie: /%s [powód] banuje JID w pokoju. Pseudonim osoby " #~ "może zostać zmieniony o ile nie zawiera \"@\". Jeśli JID jest obecnie w " #~ "pokoju, to zostanie z niego wyrzucony. NIE toleruje spacji w pseudonimie." #~ msgid "" #~ "Usage: /%s [reason], closes the current window or tab, displaying reason " #~ "if specified." #~ msgstr "" #~ "Użycie: /%s [powód] zamyka aktualne okno lub kartę i wyświetla powóc, " #~ "jeśli został podany." #~ msgid "" #~ "Usage: /%s [reason], invites JID to the current group chat, " #~ "optionally providing a reason." #~ msgstr "" #~ "Użycie: /%s [powód] zaprasza JID do aktualnego pokoju, opcjonalnie " #~ "wyświetlając powód." #~ msgid "" #~ "Usage: /%s @[/nickname], offers to join room@server " #~ "optionally using specified nickname." #~ msgstr "" #~ "Użycie: /%s @[/pseudonim] oferuje przyłączenie się do " #~ "pokój@serwer opcjonalnie z wykorzystaniem podanego psedonimu." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], removes the occupant specified by " #~ "nickname from the group chat and optionally displays a reason." #~ msgstr "" #~ "Użycie: /%s [powód] usuwa podaną poprzez pseudonim osobę z " #~ "pokoju i opcjonalnie wyświetla powód. NIE wspiera spacji w pseudonimie." #~ msgid "" #~ "Usage: /%s [message], opens a private message window and sends " #~ "message to the occupant specified by nickname." #~ msgstr "" #~ "Użycie: /%s [wiadomość] otwiera okno prywatnej wiadomości i " #~ "wysyła ją do osoby o takim pseudonimie." #~ msgid "Usage: /%s , changes your nickname in current group chat." #~ msgstr "Użycie: /%s zmienia twój pseudonim w aktualnym pokoju." #~ msgid "" #~ "Usage: /%s [topic], displays or updates the current group chat topic." #~ msgstr "" #~ "Użycie: /%s [temat] wyświetla lub aktualizuje temat aktualnego pokoju." #~ msgid "" #~ "Usage: /%s , sends a message without looking for other commands." #~ msgstr "" #~ "Użycie: /%s wysyła wiadomość bez sprawdzania innych poleceń." #, fuzzy #~ msgid "" #~ "Usage: /%s , allow to send you messages and private " #~ "messages." #~ msgstr "Użycie: /%s zmienia twój pseudonim w aktualnym pokoju." #~ msgid "B_OSH Port:" #~ msgstr "B_OSH Port:" #~ msgid "File transfer stopped by the contact at the other end" #~ msgstr "Przesyłanie pliku zostało zatrzymane przez drugą osobę" #~ msgid "Generic" #~ msgstr "Ogólne" #~ msgid "Select the account with which to synchronise" #~ msgstr "Wskaż konto, z którym chcesz zsynchronizować kontakty" #~ msgid "" #~ "%(title)s by %(artist)s\n" #~ "from %(source)s" #~ msgstr "\"%(title)s\" w wykonaniu %(artist)sz %(source)s" #~ msgid "Click to see features (like MSN, ICQ transports) of jabber servers" #~ msgstr "" #~ "Kliknij by zobaczyć możliwości serwerów jabbera (np. transporty MSN czy " #~ "ICQ)" #~ msgid "Your JID:" #~ msgstr "Twój JID:" #~ msgid "Name:" #~ msgstr "Nazwa:" #~ msgid "_Host:" #~ msgstr "_Host:" #~ msgid "Modify Account" #~ msgstr "Modyfikuj konto" #~ msgid "Gajim account %s" #~ msgstr "Konto Gajim'a %s" #~ msgid "This account is already configured in Gajim." #~ msgstr "Konto o takiej nazwie jest już skonfigurowane." #~ msgid "PyOpenSSL" #~ msgstr "PyOpenSSL" #~ msgid "gnome-keyring" #~ msgstr "Baza kluczy GNOME" #~ msgid "" #~ "Requires python-gnome2-extras or compilation of gtkspell module from " #~ "Gajim sources." #~ msgstr "" #~ "Wymaga python-gnome2-extras lub kompilacji gtkspell ze źródeł Gajima." #~ msgid "Notification-daemon" #~ msgstr "Powiadamianie o zdarzeniach" #~ msgid "Idle" #~ msgstr "Stan bezczynności" #~ msgid "Requires compilation of the idle module from Gajim sources." #~ msgstr "Wymaga kompilacji modułu idle ze źródeł Gajima." #~ msgid "libsexy" #~ msgstr "libsexy" #~ msgid "Mood" #~ msgstr "Nastrój" #~ msgid "%s has not broadcast an OpenPGP key, nor has one been assigned" #~ msgstr "" #~ "Ani %s nie przesyła swojego klucza OpenPGP, ani Ty nie przypisałeś mu " #~ "żadnego klucza" #~ msgid "No such command: /%s (if you want to send this, prefix it with /say)" #~ msgstr "" #~ "Nie ma takiego polecenia: /%s (jeśli chcesz je wysłać, poprzedź je " #~ "znakami: /say)" #, fuzzy #~ msgid "" #~ "Usage: /%s , sends action to the current group chat. Use third " #~ "person. (e.g. /%s explodes.)" #~ msgstr "" #~ "Użycie: /%s wysyła działanie do aktualnego pokoju. Używaj w " #~ "trzeciej osobie (np. /%s eksploduje.)" #~ msgid "" #~ "If checked, Gajim will sort contacts in roster window and groupchats by " #~ "their status and not by the shown name" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje posortowanie listy kontaktów według ich " #~ "statusu a nie według nazw" #~ msgid "The username used to identify the Last.fm account." #~ msgstr "Nazwa użytkownika serwisu Last.fm." #~ msgid "Network Manager support not available" #~ msgstr "Brak wsparcia dla Network Managera" #~ msgid "Session Management support not available (missing gnome.ui module)" #~ msgstr "Wsparcie dla Menadżera Sesji jest niedostępne (brak modułu gnome.ui" #~ msgid "E2E encryption enabled" #~ msgstr "Szyfrowanie E2E włączone" #~ msgid "General:" #~ msgstr "Ogólne" #~ msgid "_Make message windows compact" #~ msgstr "_Spraw, by okna wiadomości były zwarte" #~ msgid "A_ccounts" #~ msgstr "_Konta" #, fuzzy #~ msgid "\"%(title)s\" by " #~ msgstr "\"%(title)s\" w wykonaniu %(artist)s" #, fuzzy #~ msgid "The following message was " #~ msgstr "Ta wiadomość została jest zaszyfrowana" #~ msgid "%s is now %s" #~ msgstr "%s ma teraz status %s" #~ msgid "cold" #~ msgstr "Zziębnięty" #~ msgid "hot" #~ msgstr "napalony" #~ msgid "moody" #~ msgstr "markotny" #~ msgid "working" #~ msgstr "pracuję" #~ msgid "inactive" #~ msgstr "nieaktywny" #~ msgid "walking" #~ msgstr "Spaceruję" #~ msgid "sleeping" #~ msgstr "Śpię" #, fuzzy #~ msgid "mood" #~ msgstr "markotny" #~ msgid "%s - %s" #~ msgstr "%s - %s" #~ msgid "Click to see past conversation in this room" #~ msgstr "Kliknij by zobaczyć poprzednie rozmowy w tym pokoju" #~ msgid "History Viewer" #~ msgstr "Przeglądanie historii" #~ msgid "JID Selection" #~ msgstr "Wybór JID-a" #~ msgid "" #~ "Choose the chatlog you want to view. \n" #~ "Enter the jid of a groupchat or a contact here. For online accounts you " #~ "can even enter a a contact's nickname." #~ msgstr "" #~ "Wybierz katalog, który chcesz przejrzeć. \n" #~ "Tu wpisz JID czatu lub kontaktu. Jeżeli kontakt jest online, możesz podać " #~ "sam nick." #~ msgid "in" #~ msgstr "w" #~ msgid "Invitation Received" #~ msgstr "Zaproszenie Odebrane" #~ msgid "Publish and Subscribe" #~ msgstr "Publikuj i subskrybuj" #~ msgid "Allow others to see your:" #~ msgstr "_Pozwól innym widzieć swój:" #~ msgid "Receive your contact's:" #~ msgstr "Odbieraj powiadomomienia o zmianie:" #~ msgid "Tune" #~ msgstr "Muzyka" #~ msgid "" #~ "\n" #~ "From: %(from_address)s" #~ msgstr "" #~ "\n" #~ "Od: %(from_address)s" #~ msgid "OK to continue with negotiation?" #~ msgstr "Czy kontynuować negocjację?" #~ msgid "" #~ "You've begun an encrypted session with %s, but it can't be guaranteed " #~ "that you're talking directly to the person you think you are.\n" #~ "\n" #~ "You should speak with them directly (in person or on the phone) and " #~ "confirm that their Short Authentication String is identical to this one: " #~ "%s\n" #~ "\n" #~ "Would you like to continue with the encrypted session?" #~ msgstr "" #~ "Rozpocząłeś szyfrowaną sesję z %s, ale nie można zagwarantować, że " #~ "rozmawiasz bezpośrednio z odpowiednią osobą.\n" #~ "\n" #~ "Powienieneś(-winnaś) porozmawiać z nią w cztery osobiście lub za " #~ "pośrednictwem telefonu i potwierdzić, że jej SAS (Short Authentication " #~ "String) jest identyczny z poniższym: %s\n" #~ "Czy chcesz kontynuować tą sesję?" #~ msgid "Yes, I verified the Short Authentication String" #~ msgstr "Tak, SAS został zweryfikowany." #~ msgid "" #~ "To continue, Gajim needs to access your stored secrets. Enter your " #~ "passphrase" #~ msgstr "" #~ "Aby kontynuować, Gajim musi uzyskać dostęp do Twoich haseł. Proszę podać " #~ "hasło główne" #~ msgid "Confirm Passphrase" #~ msgstr "Potwierdź hasło" #~ msgid "Enter your new passphrase again for confirmation" #~ msgstr "Wpisz ponownie nowe hasło" #~ msgid "Create Passphrase" #~ msgstr "Utwórz hasło" #~ msgid "Passphrases did not match.\n" #~ msgstr "Hasła nie zgadzają się.\n" #~ msgid "Gajim needs you to create a passphrase to encrypt stored secrets" #~ msgstr "Proszę podać hasło główne służące do zaszyfrowania danych poufnych" #~ msgid "Role:" #~ msgstr "Funkcja:" #~ msgid "Affiliation:" #~ msgstr "Afiliacja: " #~ msgid "" #~ "If checked, Gajim can regularly poll a Last.fm account and sends recently " #~ "played songs through PEP." #~ msgstr "" #~ "Po zaznaczeniu tej opcji Gajim będzie wysyłał (via PEP) do serwisu Last." #~ "fm informacje o odtwarzanych utworach." #~ msgid "" #~ "When negotiating an encrypted session, should Gajim prefer to use public " #~ "keys for identification?" #~ msgstr "" #~ "Czy podczas negocjowania szyfrowanej sesji Gajim ma kluczy publicznych?" #~ msgid "Connection to host could not be established" #~ msgstr "Nie można ustanowić połączenia z hostem" #~ msgid "" #~ "Connection to host could not be established: Incorrect answer from server." #~ msgstr "Nie można ustanowić połączenia z hostem. Nieprawidłowa odpowiedź." #~ msgid "Format of a line" #~ msgstr "Format linii" #~ msgid "" #~ "An example: If you have enabled status message for away, Gajim won't ask " #~ "you anymore for a status message when you change your status to away; it " #~ "will use the default one set here" #~ msgstr "" #~ "Przykład: jeżeli ustawiłeś status opisowy dla stanu 'nieobecny', Gajim " #~ "zapamięta go i nie będzie prosił o jego zmianę po ponownym ustawieniu " #~ "takiego stanu" #~ msgid "" #~ "Determined by sender\n" #~ "Chat message\n" #~ "Single message" #~ msgstr "" #~ "Określa nadawca\n" #~ "Rozmowę\n" #~ "Pojedynczą wiadomość" #~ msgid "Hides buttons in chatwindows to " #~ msgstr "Ukrywa przyciski w oknie czatu " #~ msgid "" #~ "Never\n" #~ "Always\n" #~ "Per account\n" #~ "Per type" #~ msgstr "" #~ "Nigdy\n" #~ "Zawsze\n" #~ "Według konta\n" #~ "Według typu" #~ msgid "Privacy" #~ msgstr "Prywatność" #~ msgid "Set status message to reflect currently playing _music track" #~ msgstr "Wyświetlaj informacje o odtwarzanej _muzyce w statusie opisowym" #~ msgid "The auto away status message" #~ msgstr "Automatyczny status \"Zaraz wracam\"" #~ msgid "The auto not available status message" #~ msgstr "Automatyczny status \"Nieobecny\"" #~ msgid "Treat all incoming messages as:" #~ msgstr "Traktuj wszystkie otrzymane wiadomości jako:" #~ msgid "Use only one message _window:" #~ msgstr "_Grupuj okna:" #~ msgid "" #~ "Works for Rhythmbox and Muine players. For more players, please visit " #~ "http://trac.gajim.org/wiki/GajimAndMusicPlayer" #~ msgstr "" #~ "Funkcja ta działa z programami Rhythmbox oraz Muine. Jeżeli zależy ci na " #~ "obsłudze innego oprogramowania, odwiedź stronę http://trac.gajim.org/wiki/" #~ "GajimAndMusicPlayer" #~ msgid "_Advanced Notifications Control..." #~ msgstr "_Edytor zaawansowanych ustawień" #~ msgid "_Player:" #~ msgstr "_Program odtwarzający dźwięk:" #~ msgid "OS:" #~ msgstr "System operacyjny:" #~ msgid "You will always see him or her as offline." #~ msgstr "Zawsze będziesz widział ten kontakt jako niepołączony." #~ msgid "%s is now %s (%s)" #~ msgstr "%s ma teraz status %s (%s)" #~ msgid "%s - Gajim" #~ msgstr "%s - Gajim" #~ msgid "_New group chat" #~ msgstr "_Nowa rozmowa grupowa" #~ msgid "_Log off" #~ msgstr "R_ozłącz" #~ msgid "_Log on" #~ msgstr "_Połącz" #~ msgid "Save passphrase" #~ msgstr "Zapisz hasło" #~ msgid "Connected to server %s:%s with %s" #~ msgstr "Połączony z serwerem %s: %s z %s" #~ msgid "Build custom query" #~ msgstr "Stwórz własne zapytanie" #~ msgid "" #~ "Enter a contact jid or MUC jid here to view its history.\n" #~ "If a contact is connected you can even enter his nick name.\n" #~ msgstr "" #~ "Wprowadź nazwę użytkownika z rostera lub czatu aby przejrzeć historię " #~ "rozmów.\n" #~ "Jeżeli jest połączony, możesz podać jego nazwę.\n" #~ msgid "Query Builder..." #~ msgstr "Kreator zapytań..." #~ msgid "_Discover Services..." #~ msgstr "_Wyszukuj usługi..." #~ msgid "_Retype Password:" #~ msgstr "_Powtórz hasło:" #~ msgid "" #~ "If checked, all local contacts that use a Bonjour compatible chat client " #~ "(like iChat, Trillian or Gaim) will be shown in roster. You don't need to " #~ "be connected to a jabber server for it to work.\n" #~ "This is only available if python-avahi is installed and avahi-daemon is " #~ "running." #~ msgstr "" #~ "Jeżeli opcja ta zostanie uaktywniona, znajdujące się w twojej sieci " #~ "lokalnej kontakty używające klienta wykorzystującego technologię Bonjour " #~ "(jak iChat, Trillian czy Gaim) pojawią się na rosterze. Nie musisz łączyć " #~ "się z serwerem Jabbera, by z nimi rozmawiać." #~ msgid "" #~ "If you have 2 or more accounts and this is checked, Gajim will list all " #~ "contacts as if you had one account" #~ msgstr "" #~ "Jeśli masz dwa konta lub więcej, to dzięki tej opcji Gajim pokaże " #~ "wszystkie kontakty w taki sposób, jakby było to jedno konto" #~ msgid "_Enable link-local messaging" #~ msgstr "_Uaktywnij przesyłanie wiadomości do adresów link-local" #~ msgid "_Blocked Contacts" #~ msgstr "_Kontakty zablokowane" #~ msgid "_Compact View Alt+C" #~ msgstr "Widok _zwarty Alt+C" #~ msgid "Interface Customization" #~ msgstr "Własne ustawienia interfejsu" #~ msgid "Also known as iChat style" #~ msgstr "Znany także jako styl iChat" #~ msgid "E_very 5 minutes" #~ msgstr "Co 5 _minut" #~ msgid "" #~ "Gajim will automatically show new events by popping up the relevant window" #~ msgstr "" #~ "Gajim automatycznie wyświetli nową wiadomość w nowym oknie lub w nowej " #~ "karcie otwartego okna rozmowy" #~ msgid "" #~ "Gajim will notify you for new events via a popup in the bottom right of " #~ "the screen" #~ msgstr "" #~ "Gajim powiadomi Cię o nadejściu nowej wiadomości wyświetlając okienko w " #~ "prawym dolnym rogu ekranu" #~ msgid "" #~ "Gajim will notify you via a popup window in the bottom right of the " #~ "screen about contacts that just signed in" #~ msgstr "" #~ "Gajim powiadomi automatycznie przy pomocy okna w prawym dolnym rogu o " #~ "kontaktach, które zmieniają status na Dostępny" #~ msgid "" #~ "Gajim will only change the icon of the contact that triggered the new " #~ "event" #~ msgstr "Gajim zmieni jedynie ikonę kontaktu, który przysłał nową wiadomość" #~ msgid "" #~ "If checked, Gajim will remember the roster and chat window positions in " #~ "the screen and the sizes of them next time you run it" #~ msgstr "" #~ "Zaznaczenie tej opcji spowoduje zapamiętanie położenia głównego okna " #~ "programu na ekranie oraz jego rozmiaru" #~ msgid "On every _message" #~ msgstr "W każdej _wiadomości" #~ msgid "Outgoing Chat state noti_fications:" #~ msgstr "Wysyłanie powiadomienia o stanie _rozmowy:" #~ msgid "Print time:" #~ msgstr "Wyświetlaj czas:" #~ msgid "Save _position and size for roster and chat windows" #~ msgstr "Zapisz _pozycję i rozmiar okna kontaktów i okna rozmowy" #~ msgid "" #~ "When a new event (message, file transfer request etc..) is received, the " #~ "following methods may be used to inform you about it. Please note that " #~ "events about new messages only occur if it is a new message from a " #~ "contact you are not already chatting with" #~ msgstr "" #~ "Kiedy pojawi się nowe zdarzenie (wiadomość, prośba o przesłanie pliku " #~ "itp.), możesz zostać o tym powiadomiony na takie sposoby. UWAGA: Nowa " #~ "wiadomość pojawia się jeśli nie pochodzi od osoby, z którą aktualnie " #~ "rozmawiasz" #~ msgid "Send cus_tom status" #~ msgstr "Wyślij _odrębny status" #~ msgid "_Remove from Roster" #~ msgstr "_Usuń z listy kontaktów" #~ msgid "_Filter:" #~ msgstr "_Filtr:" #~ msgid "Click to force avatar" #~ msgstr "Kliknij aby ustawić avatar" #~ msgid "" #~ "If that is not your language for which you want to highlight misspelled " #~ "words, then please set your $LANG as appropriate. Eg. for French do " #~ "export LANG=fr_FR or export LANG=fr_FR.UTF-8 in ~/.bash_profile or to " #~ "make it global in /etc/profile.\n" #~ "\n" #~ "Highlighting misspelled words feature will not be used" #~ msgstr "" #~ "Jeśli podświetlanie błędów w pisowni działa dla niewłaściwego języka, to " #~ "ustaw odpowiednio zmienną środowiskową $LANG. Np. dla języka polskiego " #~ "wpisz export LANG=pl_PL do pliku ~/.bash_profile lub globalnie do pliku " #~ "in /etc/profile.\n" #~ "\n" #~ "Podświedlanie błędów w pisowni nie będzie używane" #~ msgid "Every %s _minutes" #~ msgstr "Co %s _minut" #~ msgid "Blocked Contacts for %s" #~ msgstr "Kontakty zablokowane (dla %s)" #~ msgid "%s does not appear to be a valid JID" #~ msgstr "%s nie wygląda na poprawny JID" #~ msgid "Drop %s in group %s" #~ msgstr "Usuń %s z grupy %s" #~ msgid "Hides the buttons in two persons chat window." #~ msgstr "Ukrywa przyciski podczas rozmowy dwóch osób." #~ msgid "" #~ "The server's key has changed, or someone is trying to hack your " #~ "connection." #~ msgstr "" #~ "Zmienił się klucz twojego serwera lub ktoś próbuje podsłuchać połączenie." #~ msgid "Unable to check fingerprint for %s. Connection could be insecure." #~ msgstr "" #~ "Nie można sprawdzić odcisku klucza %s. Połączenie może nie być bezpieczne" #~ msgid "Missing fingerprint in SSL connection to %s" #~ msgstr "Brak odcisku klucza w połączeniu SSL z %s" #~ msgid "Fingerprint mismatch for %s: Got %s, expected %s" #~ msgstr "Niezgodność odcisku klucza %s. Oczekiwano %s, otrzymano %s" #~ msgid " %d unread single message" #~ msgid_plural " %d unread single messages" #~ msgstr[0] "%d nieprzeczytana wiadomość" #~ msgstr[1] "%d nieprzeczytane wiadomości" #~ msgstr[2] "Gajim - %d nieprzeczytane wiadomości" #~ msgid " %d unread group chat message" #~ msgid_plural " %d unread group chat messages" #~ msgstr[0] "%d nieprzeczytana wiadomość z czatu" #~ msgstr[1] "%d nieprzeczytane wiadomości z czatu" #~ msgstr[2] "Gajim - %d nieprzeczytane wiadomości" #~ msgid " %d unread private message" #~ msgid_plural " %d unread private messages" #~ msgstr[0] "%d nieprzeczytana wiadomość prywatna" #~ msgstr[1] "%d nieprzeczytane wiadomości prywatne" #~ msgstr[2] "Gajim - %d nieprzeczytane wiadomości" #~ msgid "gtk+" #~ msgstr "gtk+" #~ msgid "2003-12-13T18:30:02Z" #~ msgstr "2003-12-13T18:30:02Z" #~ msgid "Romeo and Juliet" #~ msgstr "Romeo i Julia" #~ msgid "Soliloquy" #~ msgstr "Monolog" #~ msgid "Private Chat" #~ msgstr "Rozmowa prywatna" #~ msgid "I'm %s" #~ msgstr "Jestem %s" #~ msgid "A_fter nickname:" #~ msgstr "_Za pseudonimem:" #~ msgid "_After time:" #~ msgstr "_Po czasie:" #~ msgid "_Before time:" #~ msgstr "P_rzed czasem:" #~ msgid "_Retrieve" #~ msgstr "_Przywróć" #~ msgid "Information published" #~ msgstr "Informacja została opublikowana" #~ msgid "Without a connection, you can not get your contact information." #~ msgstr "Musisz być połączony by uzyskać informacje o kontakcie." #~ msgid "This is result of query." #~ msgstr "Oto wynik zapytania." #~ msgid "Edit items on the list" #~ msgstr "Edytuj obiekty na liście" #~ msgid "Merge consecutive nickname in chat window." #~ msgstr "Łącz następujące po sobie te same nicki w oknie czata." #~ msgid "Role: " #~ msgstr "Funkcja: " #~ msgid "" #~ "Sound to play when any MUC message arrives. (This setting is taken into " #~ "account only if notify_on_all_muc_messages is True)" #~ msgstr "" #~ "Dźwięk, który zostanie odtworzony, gdy nadejdzie wiadomość MUC. (Ta opcja " #~ "jest brana pod uwagę jedynie gdy zmienna notify_on_all_muc_messages ma " #~ "wartość True)" #~ msgid "Away " #~ msgstr "Zaraz wracam " #~ msgid "Down" #~ msgstr "W dół" #~ msgid "List of special notifications settings" #~ msgstr "Lista akcji dla powiadomień" #~ msgid "Not Available " #~ msgstr "Nieobecny " #~ msgid "Up" #~ msgstr "Do góry" #~ msgid "Create your own Privacy Lists" #~ msgstr "Stwórz własną listę prywatności" #~ msgid "Server-based Privacy Lists" #~ msgstr "Listy prywatności po stronie serwera" #~ msgid "Contact _Info" #~ msgstr "_Informacje o kontakcie" #~ msgid "Jabber" #~ msgstr "Jabber" #~ msgid "Invalid room or server name" #~ msgstr "Niepoprawna nazwa pokoju lub serwera" #~ msgid "Your personal information has been published successfully." #~ msgstr "Informacje o tobie zostały opublikowane." #~ msgid "Migrating Logs..." #~ msgstr "Przenoszenie logów..." #~ msgid "Gajim - %d unread message" #~ msgid_plural "Gajim - %d unread messages" #~ msgstr[0] "Gajim - %d nieprzeczytana wiadomość" #~ msgstr[1] "Gajim - %d nieprzeczytane wiadomości" #~ msgstr[2] "Gajim - %d nieprzeczytane wiadomości" #~ msgid "Since %s" #~ msgstr "Od %s" gajim-gajim-1.1.3/po/pt.po000066400000000000000000011664421345766322700153260ustar00rootroot00000000000000# Portuguese translations for Gajim package. # Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Gajim package. # msgid "" msgstr "" "Project-Id-Version: Gajim 0.6\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2005-08-18 18:21-0300\n" "Last-Translator: Miguel Fonseca \n" "Language-Team: none\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "Desfazer" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "Limpar" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "Quer mesmo enviar o ficheiro?" #: gajim/chat_control_base.py:1103 #, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "Se enviar um ficheiro a %s, seu JID será revelado." #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Ficheiro" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Tempo" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Progresso" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Nome do ficheiro: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Tamanho: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "Você" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Remetente: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Destinatário: " #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Guardado em: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Transferência de ficheiro completada" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 msgid "Open _Containing Folder" msgstr "Abrir _Pasta" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "Transferência de ficheiro cancelada" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "Ligação ao peer não pode ser estabelecida." #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "Destinatário: %s" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "Mensagem de erro: %s" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 msgid "File transfer stopped" msgstr "Transferência de ficheiro parada" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" "O ficheiro %(file)s foi recebido, mas parece ter sido danificado durante o " "envio.\n" "Quer descarregá-lo novamente?" #: gajim/filetransfers_window.py:341 msgid "Gajim can not read this file" msgstr "Gajim não consegue aceder a este ficheiro" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "Outro aplicativo está a usar este ficheiro." #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "Não é possível sobrescrever o ficheiro \"%s\"" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "Há um ficheiro com este nome e não tem permissão para sobrescrevê-lo." #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Este ficheiro já existe" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 #, fuzzy msgid "What do you want to do?" msgstr "O que pretende fazer?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "A pasta \"%s\" não pode ser modificada" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "Não tem permissão para criar ficheiros nesta pasta." #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Ficheiro: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Tipo: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Descrição: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "%s quer enviar-lhe um ficheiro:" #: gajim/filetransfers_window.py:487 msgid "Checking file…" msgstr "Examinando ficheiro…" #: gajim/filetransfers_window.py:501 msgid "File error" msgstr "Ficheiro com erro" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(horas)02.d:%(minutos)02.d:%(segundos)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/s)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Ficheiro Inválido" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Ficheiro: " #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "Não é possível enviar ficheiros vazios" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Nome: " #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Remetente: " #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Pausa" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "_Continuar" #: gajim/filetransfers_window.py:1019 msgid "Choose a File to Send…" msgstr "Escolha o ficheiro para enviar…" #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "Este formato de ficheiro não é suportado" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" "A imagem não pode ser guardada como %(type)s. Guardar como %(new_filename)s?" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 msgid "Save _As" msgstr "Guardar _Como" #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "?Cliente:Desconhecido" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "?SO:Desconhecido" #: gajim/vcard.py:326 gajim/vcard.py:329 msgid "?Time:Unknown" msgstr "?Tempo:Desconhecido" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "?Função no chat do grupo:Role:" #: gajim/vcard.py:384 #, fuzzy msgid "Affiliation:" msgstr "Aplicações" #: gajim/vcard.py:391 msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "" "Este contacto está interessado/a em sua informação de presença, mas você não " "está interessado/a na dele/a" #: gajim/vcard.py:393 msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "" "Está interessado na informação de presença do contacto, mas não é recíproco" #: gajim/vcard.py:395 msgid "The contact and you want to exchange presence information" msgstr "Você e o contacto querem partilhar a informação de presença" #: gajim/vcard.py:397 msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "" "Você e o contacto não estão interessados em partilhar a informação de " "presença entre si" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "Está à espera da resposta do contacto sobre o seu pedido de subscrição" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "Não há pedido de subscrição pendente." #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr " recurso com prioridade " #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "Todos os ficheiros" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 msgid "Clear File" msgstr "Eliminar Ficheiro" #: gajim/options_dialog.py:484 msgid "Manage Proxies" msgstr "Gerir perfis de Proxy" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Nenhum" # This translation doesn't match the original - except if there's a meaning in the context I'm not aware of #: gajim/options_dialog.py:516 #, fuzzy msgid "Adjust to Status" msgstr "Pedir para ver o estado dele/dela" #: gajim/options_dialog.py:528 msgid "On" msgstr "Ativo" #: gajim/options_dialog.py:528 msgid "Off" msgstr "Desconectado" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Erro ao receber as chaves secretas" #: gajim/options_dialog.py:565 msgid "There is no OpenPGP secret key available." msgstr "Não há chave secreta OpenPGP disponível." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "Selecionar encriptação de chave OpenPGP" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Escolha sua chave OpenPGP" #: gajim/gui_menu_builder.py:95 msgid "_New Group Chat" msgstr "_Novo Grupo de Chat" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Fora da lista" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "Eu gostaria de o adicionar à minha lista" #: gajim/gui_menu_builder.py:502 msgid "Send Single _Message…" msgstr "Enviar _Mensagem…Individual" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 msgid "Send Cus_tom Status" msgstr "Enviar informação personalizada de estado" # Is not clear why the word E_xecute is separated or this is a typo #: gajim/gui_menu_builder.py:535 #, fuzzy msgid "E_xecute Command…" msgstr "comando" #: gajim/gui_menu_builder.py:543 msgid "_Manage Transport" msgstr "_Gerenciar Transporte" #: gajim/gui_menu_builder.py:549 msgid "_Modify Transport" msgstr "_Modificar Transporte" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 msgid "_Rename…" msgstr "_Renomear…" #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "_Desbloquear" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "_Bloquear" # The same as before: "Remo_ve" is a typo? #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 #, fuzzy msgid "Remo_ve" msgstr "_Remover" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 #, fuzzy msgid "_Information" msgstr "Informações do Contacto" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 msgid "Send File…" msgstr "Enviar Ficheiro…" #: gajim/gui_menu_builder.py:602 msgid "Upload File…" msgstr "Carregar Ficheiro..." #: gajim/gui_menu_builder.py:603 msgid "Send File Directly…" msgstr "Enviar Ficheiro Diretamente..." #: gajim/gui_menu_builder.py:605 #, fuzzy msgid "Invite Contacts" msgstr "Contacto:" #: gajim/gui_menu_builder.py:606 #, fuzzy msgid "Add to Roster" msgstr "_Adicionar à Lista" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "Sessão de áudio" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "Sessão de vídeo" #: gajim/gui_menu_builder.py:609 #, fuzzy msgid "Information" msgstr "Informações do Contacto" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 msgid "History" msgstr "Histórico" #: gajim/gui_menu_builder.py:634 msgid "Manage Room" msgstr "Gerir Sala" #: gajim/gui_menu_builder.py:635 msgid "Change Subject" msgstr "Modificar Assunto" #: gajim/gui_menu_builder.py:636 msgid "Configure Room" msgstr "Configurar Sala" #: gajim/gui_menu_builder.py:637 msgid "Upload Avatar…" msgstr "Carregar Avatar…" #: gajim/gui_menu_builder.py:638 msgid "Destroy Room" msgstr "Eliminar Sala" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "Sincronizar Limite" #: gajim/gui_menu_builder.py:641 msgid "Change Nick" msgstr "Mudar Alcunha" #: gajim/gui_menu_builder.py:642 msgid "Bookmark Room" msgstr "Adicionar esta Sala aos Bookmarks" #: gajim/gui_menu_builder.py:643 #, fuzzy msgid "Request Voice" msgstr "_Voz" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 #, fuzzy msgid "Notify on all messages" msgstr "mensagem de estado:" #: gajim/gui_menu_builder.py:645 msgid "Minimize on close" msgstr "Minimizar ao fechar" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 msgid "Execute command" msgstr "Executar comando" #: gajim/gui_menu_builder.py:648 msgid "Disconnect" msgstr "Desconectar" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "Sem limite definido" #: gajim/gui_menu_builder.py:680 #, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "Há %i dia atrás" msgstr[1] "Há %i dias atrás" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Entrar num Chat" #: gajim/gui_menu_builder.py:734 msgid "Add Contact…" msgstr "Adicionar Contacto…" #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 msgid "Profile" msgstr "Perfil" #: gajim/gui_menu_builder.py:737 msgid "Discover Services" msgstr "Descobrir Recursos" #: gajim/gui_menu_builder.py:738 #, fuzzy msgid "Send Single Message…" msgstr "Enviar _Mensagem Simples" #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Avançado" #: gajim/gui_menu_builder.py:740 msgid "Archiving Preferences" msgstr "Guardar Preferências" #: gajim/gui_menu_builder.py:741 msgid "Synchronise History" msgstr "Sincronizar histórico" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "Listas privadas" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 msgid "Server Info" msgstr "Informação do Servidor" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "Consola XML" #: gajim/gui_menu_builder.py:746 msgid "Admin" msgstr "Admin" #: gajim/gui_menu_builder.py:747 msgid "Send Server Message…" msgstr "Enviar Mensagem do Servidor…" #: gajim/gui_menu_builder.py:748 msgid "Set MOTD…" msgstr "Definir MOTD…" #: gajim/gui_menu_builder.py:749 msgid "Update MOTD…" msgstr "Atualizar MOTD…" #: gajim/gui_menu_builder.py:750 msgid "Delete MOTD…" msgstr "Apagar MOTD…" #: gajim/gui_menu_builder.py:799 #, fuzzy msgid "No Accounts available" msgstr "Nenhuma conta disponível" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Contas" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 msgid "Copy JID" msgstr "Copiar JID" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 #, fuzzy msgid "Join Groupchat" msgstr "Entrar num Chat" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Iniciar Conversa" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 msgid "Add to Roster…" msgstr "Adicionar à Lista de Contactos…" #: gajim/gui_menu_builder.py:880 #, fuzzy msgid "Copy Link Location" msgstr "_Copiar Localização do Link" #: gajim/gui_menu_builder.py:881 msgid "Open Link in Browser" msgstr "Abrir Link no Navegador" #: gajim/gui_menu_builder.py:886 msgid "Copy Email Address" msgstr "Copiar Endereço de Email" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 #, fuzzy msgid "Open Email Composer" msgstr "_Abrir Compositor de Email" #: gajim/gui_menu_builder.py:892 msgid "Copy JID/Email" msgstr "Copiar JID/Endereço de Email" #: gajim/history_manager.py:71 msgid "Usage:" msgstr "Uso:" #: gajim/history_manager.py:73 msgid "Options:" msgstr "Opções:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "Mostrar esta mensagem de ajuda e sair" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "Designar a pasta para registo de ficheiro" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "O histórico da base de dados dos logs não foi encontrado" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Data" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Alcunha" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Mensagem" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Assunto" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" "Quer limpar a base de dados? (ESTA AÇÃO É FORTEMENTE DESACONSELHADA SE O " "GAJIM ESTIVER ATIVO)" #: gajim/history_manager.py:257 msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" "O tamanho da base de dados normalmente designada não será modificado, apenas " "se tornará reutilizável. Se quer realmente reduzir o tamanho da base de " "dados pressione SIM, ou do contrário pressione NÃO.\n" "\n" "Caso pressione SIM, por favor aguarde…" #: gajim/history_manager.py:262 msgid "Database Cleanup" msgstr "Limpar a base de dados" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(who)s às %(time)s disse: %(message)s\n" #: gajim/history_manager.py:577 #, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Quer eliminar todas as mensagens com %(jid)s?" #: gajim/history_manager.py:581 msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "Quer eliminar todas as mensagens com os contactos selecionados?" #: gajim/history_manager.py:583 msgid "This can not be undone." msgstr "Esta ação não pode ser desfeita." #: gajim/history_manager.py:585 gajim/history_manager.py:624 msgid "Deletion Confirmation" msgstr "Eliminação realizada" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Quer realmente eliminar a mensagem selecionada?" msgstr[1] "Quer realmente eliminar as mensagens selecionadas?" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "Esta operação não pode ser revertida." #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "Nome do contacto %s" #: gajim/dialogs.py:84 #, python-format msgid "JID: %s" msgstr "JID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "Geral" #: gajim/dialogs.py:200 msgid "Group" msgstr "Grupo" #: gajim/dialogs.py:207 msgid "In the group" msgstr "Neste grupo" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "KeyID" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Nome do contacto" #: gajim/dialogs.py:483 msgid "Set Mood" msgstr "Definir humor" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "Mensagem de Estado de %s" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Mensagem de Estado" #: gajim/dialogs.py:807 msgid "Overwrite Status Message?" msgstr "Sobrescrever a Mensagem de Estado?" #: gajim/dialogs.py:808 msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "Este nome já está em uso. Quer sobrescrever esta mensagem de estado?" #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Guardar como Mensagem de Estado Pré-definida" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Por favor defina um nome para esta mensagem de estado" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Pedido de Subscrição" #: gajim/dialogs.py:857 #, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Pedido de subscrição para a conta %(account)s por parte de %(jid)s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Pedido de subscrição de %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "Não está ligado ao servidor" #: gajim/dialogs.py:928 msgid "Without a connection, you can not synchronise your contacts." msgstr "Não é possível sincronizar seus contactos sem uma conexão." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Nome" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Servidor" #: gajim/dialogs.py:978 msgid "This account is not connected to the server" msgstr "Esta conta não está ligada ao servidor" #: gajim/dialogs.py:979 msgid "You cannot synchronize with an account unless it is connected." msgstr "Não pode sincronizar com uma conta se não estiver conectada." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "Sincronizar" #: gajim/dialogs.py:1065 msgid "add" msgstr "adicionar" #: gajim/dialogs.py:1065 msgid "modify" msgstr "modificar" #: gajim/dialogs.py:1066 msgid "remove" msgstr "remover" #: gajim/dialogs.py:1095 #, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "" "%(jid)s gostaria que você %(actions)s alguns contactos à sua " "lista de contactos." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 msgid "Add" msgstr "Adicionar" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 msgid "Modify" msgstr "Modificar" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Apagar" #: gajim/dialogs.py:1125 msgid "Groups" msgstr "Grupos" #: gajim/dialogs.py:1233 #, python-format msgid "%s suggested me to add you in my roster." msgstr "%s me sugere que o adicione à minha lista de contactos." #: gajim/dialogs.py:1247 #, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "Contacto %d adicionado" msgstr[1] "Contactos %d adicionados" #: gajim/dialogs.py:1285 #, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "O contacto %d foi removido" msgstr[1] "Os contactos %d foram removidos" #: gajim/dialogs.py:1305 msgid "You are invited to a groupchat" msgstr "Foi convidado para um chat" #: gajim/dialogs.py:1308 msgid "$Contact has invited you to join a discussion" msgstr "$Contact o convidou para um chat" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "$Contact o convidou para um chat de grupo %(room_jid)s" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Comentário: %s" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "Aceita o convite?" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "Motivo (se não aceita):" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Convite para chat de grupo" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "áudio e vídeo" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "de áudio" #: gajim/dialogs.py:1628 msgid "a video" msgstr "de vídeo" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "%(contact)s quer iniciar sessão %(type)s com você. Aceita a chamada?" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 msgid "File Transfer" msgstr "Transferência de Ficheiros" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "" #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "A carregar um ficheiro via HTTP…" #: gajim/dialogs.py:1764 msgid "Encrypting file…" msgstr "Encriptar ficheiro…" #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%(nick)s agora é conhecido como %(new_nick)s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s está agora %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Falha ao enviar uma mensagem privada" #: gajim/groupchat_control.py:253 #, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "Já não se encontra na sala \"%(room)s\" ou \"%(nick)s\" saiu." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 msgid "No File Transfer available" msgstr "Nenhuma Transferência de Ficheiros disponível" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Mudar Assunto" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Por favor, especifique o novo assunto:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Mudar Alcunha" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Por favor, especifique a nova alcunha a usar:" #: gajim/groupchat_control.py:711 #, fuzzy msgid "Invalid group chat JID" msgstr "Jabber ID Inválido" #: gajim/groupchat_control.py:712 #, fuzzy msgid "The group chat JID has not allowed characters." msgstr "Esta sala não tem assunto" #: gajim/groupchat_control.py:724 #, fuzzy, python-format msgid "Destroying %s" msgstr "Descrição: %s" #: gajim/groupchat_control.py:725 msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "" #: gajim/groupchat_control.py:934 #, fuzzy msgid "Insert Nickname" msgstr "Muda Alcu_nha" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 #, fuzzy msgid "and authenticated" msgstr "Usar autenticação" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 #, fuzzy msgid "and NOT authenticated" msgstr "Usar autenticação" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "" #: gajim/groupchat_control.py:1157 #, fuzzy msgid "Conversation with " msgstr "Histórico das Conversas" #: gajim/groupchat_control.py:1159 #, fuzzy msgid "Continued conversation" msgstr "Ligação" #: gajim/groupchat_control.py:1525 #, fuzzy, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(nick)s foi expulso: %(reason)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "" #: gajim/groupchat_control.py:1556 msgid "Room now shows unavailable members" msgstr "" #: gajim/groupchat_control.py:1558 msgid "Room now does not show unavailable members" msgstr "" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "" #: gajim/groupchat_control.py:1576 msgid "Room is now fully anonymous" msgstr "" #: gajim/groupchat_control.py:1615 #, python-format msgid "Ping? (%s)" msgstr "" #: gajim/groupchat_control.py:1618 #, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 #, fuzzy msgid "Error." msgstr "Erro:" #: gajim/groupchat_control.py:1845 #, python-format msgid "You (%s) joined the room" msgstr "Você (%s) se uniu à sala" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, python-format msgid "%(jid)s has been invited in this room" msgstr "%(jid)s foi convidado a participar desta sala" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "" #: gajim/groupchat_control.py:1879 #, fuzzy msgid "A new room has been created" msgstr "A sua nova conta foi criada com sucesso" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s foi expulso: %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(nick)s foi expulso por %(who)s: %(reason)s" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "%(nick)s foi banido: %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(nick)s foi banido por %(who)s: %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "É agora conhecido como %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(nick)s foi expulso da sala (%(reason)s)" #: gajim/groupchat_control.py:1950 #, fuzzy msgid "affiliation changed" msgstr "Filiação: " #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "" #: gajim/groupchat_control.py:2034 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "%(nick)s foi expulso por %(who)s: %(reason)s" #: gajim/groupchat_control.py:2038 #, fuzzy, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "%(nick)s foi expulso: %(reason)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "%s saiu da sala" #: gajim/groupchat_control.py:2067 #, fuzzy, python-format msgid "%s has joined the group chat" msgstr "Neste grupo" #: gajim/groupchat_control.py:2374 #, fuzzy, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Tem a certeza de que deseja sair da sala \"%s\"?" #: gajim/groupchat_control.py:2376 #, fuzzy msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "Se fechar esta janela, perder-se-á a ligação a esta sala." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 #, fuzzy msgid "_Do not ask me again" msgstr "_Não voltar a perguntar" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Expulsando %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Pode especificar uma razão em baixo:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Banindo %s" #: gajim/chat_control.py:389 #, fuzzy msgid "Show a list of formattings" msgstr "Clique para inserir um emoticon (Alt+E)" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "" #: gajim/chat_control.py:396 #, fuzzy msgid "This contact does not support HTML" msgstr "Uma lista de transferências de ficheiros activas, completas e paradas" #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "" #: gajim/chat_control.py:660 #, fuzzy, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s na sala %(room_name)s enviou-lhe uma nova mensagem." #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "Recebeu uma nova mensagem de \"%s\"" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Se fechar esta aba e o histórico estiver desactivado, esta mensagem será " "perdida." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "" #: gajim/chat_control.py:1205 #, python-format msgid "Pong! (%s seconds)" msgstr "" #: gajim/chat_control.py:1313 #, fuzzy, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Assunto: %s\n" "%s" #: gajim/chat_control.py:1416 #, fuzzy, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(nick)s está agora %(status)s" #: gajim/chat_control.py:1471 #, fuzzy msgid "File transfer" msgstr "Transferências de Ficheiros" #: gajim/chat_control.py:1474 #, fuzzy msgid "Size" msgstr "Tamanho: " #: gajim/chat_control.py:1476 #, fuzzy msgid "Accept" msgstr "Aceitar" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Entrar" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 #, fuzzy msgid "Remote contact stopped transfer" msgstr "Remove o contacto da lista" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 #, fuzzy msgid "Error opening file" msgstr "Erro na leitura do ficheiro:" #: gajim/application.py:68 #, fuzzy msgid "Show the application's version" msgstr "_Ícone na bandeja (também conhecido por área de notificação)" #: gajim/application.py:75 #, fuzzy msgid "Show only critical errors" msgstr "Mostrar apenas na _lista" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "" #: gajim/application.py:97 #, fuzzy msgid "Use defined profile in configuration directory" msgstr "Editor de Configuração Avançada" #: gajim/application.py:105 #, fuzzy msgid "Set configuration directory" msgstr "Configuração da Sala" #: gajim/application.py:113 msgid "Configure logging system" msgstr "" #: gajim/application.py:121 #, fuzzy msgid "Show all warnings" msgstr "Mostrar Todos os _Eventos Pedentes" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "" #: gajim/application.py:135 #, fuzzy msgid "Pops up a window with the next pending event" msgstr "Abre uma janela com a próxima mensagem não lida" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 #, fuzzy msgid "Start a new chat" msgstr "Iniciar Conversa" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Contas fundidas" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Transportes" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 #, fuzzy msgid "Groupchats" msgstr "Chat" #: gajim/roster_window.py:2056 #, fuzzy msgid "Authorization sent" msgstr "Autorização foi enviada" #: gajim/roster_window.py:2057 #, fuzzy, python-format msgid "\"%s\" will now see your status." msgstr "Agora \"%s\" saberá o seu estado." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Pedido de subscrição foi enviado" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "Se \"%s\" aceitar este pedido, você passará a saber o seu estado." #: gajim/roster_window.py:2095 #, fuzzy msgid "Authorization removed" msgstr "Autorização foi removida" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "Doravante, \"%s\" vê-lo-á sempre como estando offline." #: gajim/roster_window.py:2120 #, fuzzy msgid "OpenPGP is not usable" msgstr "Não é possível usar OpenPGP neste computador" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Está a participar num ou mais chats" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Mudar o seu estado para invisível fará com que seja desligado desses chats. " "De certeza que deseja tornar-se invisível?" #: gajim/roster_window.py:2358 #, fuzzy msgid "desynced" msgstr "Avançado" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "" #: gajim/roster_window.py:2426 #, fuzzy msgid "Are you sure you want to quit Gajim?" msgstr "Tem a certeza de que deseja sair das salas \"%s\"?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "" #: gajim/roster_window.py:2514 #, fuzzy msgid "You have running file transfers" msgstr "Cancelar transferência de ficheiro" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Tem mensagens não lidas" #: gajim/roster_window.py:2547 #, fuzzy msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "As mensagens só poderão ser lidas mais tarde caso tenha o histórico activado." #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "" #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Transporte \"%s\" será removido" #: gajim/roster_window.py:2829 #, fuzzy msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" "Deixará de poder enviar e receber mensagens aos contactos desde este " "transport." #: gajim/roster_window.py:2832 #, fuzzy msgid "Transports will be removed" msgstr "Transporte \"%s\" será removido" #: gajim/roster_window.py:2837 #, fuzzy, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" "Deixará de poder enviar e receber mensagens aos contactos desde este " "transport." #: gajim/roster_window.py:2891 #, fuzzy msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "Tem de criar uma conta antes de poder conversar com outros contactos." #: gajim/roster_window.py:2893 msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" #: gajim/roster_window.py:2939 #, fuzzy msgid "Rename Contact" msgstr "Contacto:" #: gajim/roster_window.py:2940 #, fuzzy, python-format msgid "Enter a new nickname for contact %s" msgstr "Introduza a chave GPG para a conta %s" #: gajim/roster_window.py:2947 #, fuzzy msgid "Rename Group" msgstr "_Renomear" #: gajim/roster_window.py:2948 #, fuzzy, python-format msgid "Enter a new name for group %s" msgstr "Introduza a chave GPG para a conta %s" #: gajim/roster_window.py:2993 #, fuzzy msgid "Remove Group" msgstr "_Remover" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "" #: gajim/roster_window.py:2995 #, fuzzy msgid "Also remove all contacts in this group from your roster" msgstr "Remove o contacto da lista" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Atribuir chave OpenPGP" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "Selecione uma chave para aplicar ao contacto" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "Contacto \"%s\" será removido de sua lista" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "" #: gajim/roster_window.py:3448 #, fuzzy msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "Ao remover este contacto, também remove a autorização. O contacto vê-lo-á " "sempre como offline." #: gajim/roster_window.py:3454 #, fuzzy msgid "Do you want to continue?" msgstr "O que pretende fazer?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "Ao remover este contacto, também remove a autorização. O contacto vê-lo-á " "sempre como offline." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Quero que este contacto saiba o meu estado depois da remoção" #: gajim/roster_window.py:3465 #, fuzzy msgid "Contacts will be removed from your roster" msgstr "Contacto \"%s\" será removido de sua lista" #: gajim/roster_window.py:3470 #, fuzzy, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "Ao remover este contacto, também remove a autorização. O contacto vê-lo-á " "sempre como offline." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "Tem de criar uma conta antes de poder conversar com outros contactos." #: gajim/roster_window.py:3531 #, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Nenhuma conta disponível" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "Tem de criar uma conta antes de poder conversar com outros contactos." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "" #: gajim/roster_window.py:4180 msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" #: gajim/roster_window.py:4276 #, fuzzy msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "Tem de criar uma conta antes de poder conversar com outros contactos." #: gajim/roster_window.py:4278 msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" #: gajim/roster_window.py:4400 #, fuzzy msgid "Invalid file URI:" msgstr "Ficheiro Inválido" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Enviar _Ficheiro" #: gajim/roster_window.py:4412 #, fuzzy, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "%s quer enviar-lhe um ficheiro:" msgstr[1] "%s quer enviar-lhe um ficheiro:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Enviar %s" #: gajim/roster_window.py:4565 #, fuzzy, python-format msgid "Make %s first contact" msgstr "Envia um ficheiro a um contacto" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Envia um ficheiro a um contacto" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "_Mudar Mensagem de Estado" #: gajim/roster_window.py:4965 #, fuzzy msgid "Publish Tune" msgstr "_Publicar" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "_Publicar" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "_Descobrir Recursos..." #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 #, fuzzy msgid "Send Group M_essage" msgstr "Nova Mensagem" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "" #: gajim/roster_window.py:5135 #, fuzzy msgid "To all online users" msgstr "Utilizadores _Online" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "" #: gajim/roster_window.py:5299 #, fuzzy msgid "_Manage Contacts" msgstr "Contacto:" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Editar _Grupos" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "_Remover" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "" #: gajim/roster_window.py:5370 #, fuzzy msgid "_Reconnect" msgstr "Contacto Entrou" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 #, fuzzy msgid "_Disconnect" msgstr "Contacto Entrou" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Histórico" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 #, fuzzy msgid "History Manager" msgstr "_Histórico" #: gajim/roster_window.py:5475 #, fuzzy msgid "_Join New Group Chat" msgstr "_Entrar num Chat" #: gajim/config.py:359 msgid "Ban List" msgstr "" #: gajim/config.py:360 #, fuzzy msgid "Member List" msgstr "_Membro" #: gajim/config.py:360 #, fuzzy msgid "Owner List" msgstr "_Dono" #: gajim/config.py:361 #, fuzzy msgid "Administrator List" msgstr "_Administrador" #: gajim/config.py:435 msgid "Reason" msgstr "" #: gajim/config.py:442 #, fuzzy msgid "Nick" msgstr "_Expulsar" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 #, fuzzy msgid "Role" msgstr "Função:" #: gajim/config.py:478 msgid "Banning…" msgstr "Banindo..." #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Quem pretende banir?\n" "\n" #: gajim/config.py:482 msgid "Adding Member…" msgstr "" #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" "Quem quer tornar membro?\n" "\n" #: gajim/config.py:485 msgid "Adding Owner…" msgstr "" #: gajim/config.py:486 #, fuzzy msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "O que pretende fazer?" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "_Administrador" #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" "Quem quer eleger como administrador?\n" "\n" #: gajim/config.py:490 msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Removendo %s conta" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Encriptação desactivada" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Senha Necessária" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Introduza a sua senha para a conta %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Guardar senha" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Conta \"%s\" está ligada ao servidor" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Se remover isto, a ligação será perdida." #: gajim/config.py:652 #, python-format msgid "Connection to server %s failed" msgstr "A ligação ao servidor %s falhou" #: gajim/config.py:653 msgid "What would you like to do?" msgstr "O que pretende fazer?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Remover conta _apenas do Gajim" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Sons Wav" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "Nova Mensagem" #: gajim/config.py:746 msgid "First Message Received" msgstr "" #: gajim/config.py:747 #, fuzzy msgid "Next Message Received Focused" msgstr "Nova Mensagem" #: gajim/config.py:748 #, fuzzy msgid "Next Message Received Unfocused" msgstr "Nova Mensagem" #: gajim/config.py:749 #, fuzzy msgid "Contact Connected" msgstr "Nome do Contacto" #: gajim/config.py:750 #, fuzzy msgid "Contact Disconnected" msgstr "Contacto Entrou" #: gajim/config.py:751 #, fuzzy msgid "Message Sent" msgstr "Mensagem" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 #, fuzzy msgid "?Group Chat Contact Affiliation:None" msgstr "?Função do Contacto no Chat:Nenhuma" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 #, fuzzy msgid "Member" msgstr "_Membro" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 #, fuzzy msgid "Administrator" msgstr "_Administrador" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 #, fuzzy msgid "Owner" msgstr "_Dono" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr "" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr "" #: gajim/tooltips.py:574 #, fuzzy msgid "Connected" msgstr "Ligação" #: gajim/tooltips.py:576 #, fuzzy msgid "Disconnected" msgstr "Contacto Entrou" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Download" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Upload" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Tipo: " #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Transferido: " #: gajim/tooltips.py:645 msgid "Status: " msgstr "Estado: " #: gajim/tooltips.py:647 #, fuzzy msgid "Description: " msgstr "Descrição: %s" #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Completa" #: gajim/tooltips.py:676 #, fuzzy msgid "?transfer status:Paused" msgstr "Mostrar hora:" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "Interrompida" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "A transferir" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "Não iniciada" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "Mostrar hora:" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Livre para conversar" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Ausente" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Ocupado" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Indisponível" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Offline" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "_Mudar Mensagem de Estado" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "usando a conta %s" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Gerir Bookmarks" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "Fora da lista" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "Mostrar _Lista de Contactos" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Esconder este menú" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Impossível entrar na sala" #: gajim/dataforms_widget.py:586 #, python-format msgid "Media type not supported: %s" msgstr "" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "Este serviço/recurso ainda não respondeu com informações detalhadas" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "Este serviço/recurso não pôde responder com informações detalhadas.\n" "Provavelmente está legacy ou broken" #: gajim/disco.py:121 msgid "Others" msgstr "Outros" #: gajim/disco.py:125 msgid "Conference" msgstr "Conferência" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "Tem de estar ligado para ver os serviços" #: gajim/disco.py:593 #, fuzzy, python-format msgid "Service Discovery using account %s" msgstr "Buscar Serviço usando conta %s" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Buscar Serviço" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "O serviço não pôde ser encontrado" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "Não há serviço/recurso no endereço que introduziu, ou pelo menos não " "responde. Verifique o endereço e tente novamente." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "Serviço não explorável" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "Este tipo de serviço/recurso não contém itens para explorar." #: gajim/disco.py:726 gajim/disco.py:736 #, fuzzy msgid "Invalid Server Name" msgstr "Nome de utilizador inválido" #: gajim/disco.py:794 #, fuzzy, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "usando a conta %s" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Explorar" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "Este serviço não contém quaisquer itens para explorar" #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "comando" #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "Re_gistar" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "_Entrar" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 #, fuzzy msgid "Search" msgstr "_Pesquisar" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Editar" #: gajim/disco.py:1450 #, fuzzy, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "Buscando %d / %d.." #: gajim/disco.py:1649 msgid "Users" msgstr "Utilizadores" #: gajim/disco.py:1657 msgid "Description" msgstr "Descrição" #: gajim/disco.py:1665 msgid "Id" msgstr "" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 #, fuzzy msgid "_Bookmark" msgstr "Adicionar esta Sala aos _Bookmarks" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Bookmark já está configurado" #: gajim/disco.py:1722 #, fuzzy, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "Sala \"%s\" já existe nos seus bookmarks." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Bookmark foi adicionado com sucesso" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "Pode gerir os seus bookmarks pelo menu de Acções na sua janela." #: gajim/disco.py:1929 #, fuzzy msgid "Subscribed" msgstr "Subscrição" #: gajim/disco.py:1938 msgid "Node" msgstr "Nó" #: gajim/disco.py:2005 msgid "New post" msgstr "" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "_Subscrever" #: gajim/disco.py:2017 #, fuzzy msgid "_Unsubscribe" msgstr "_Subscrever" #: gajim/conversation_textview.py:320 #, fuzzy msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" "O texto abaixo desta linha é o que foi dito desde que prestou atenção a este " "chat pela última vez." #: gajim/conversation_textview.py:541 #, fuzzy msgid "_Quote" msgstr "_Sair" #: gajim/conversation_textview.py:549 #, fuzzy, python-format msgid "_Actions for \"%s\"" msgstr "Acções para \"%s\"" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Ler Artigo _Wikipedia" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Procurar no _Dicionário" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "Falta um \"%s\" no URL do Dicionário e como tal não é WIKTIONARY" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "URL de Procura na Web não existe \"%s\"" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "_Pesquisar na Web sobre o assunto" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "Jabber ID Inválido" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" #: gajim/conversation_textview.py:1115 #, fuzzy, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "Ontem" msgstr[1] "Ontem" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Não iniciada" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Assunto: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Nova Mensagem Privada" #: gajim/message_window.py:243 #, fuzzy msgid "You are going to close several tabs" msgstr "Não está ligado ao servidor" #: gajim/message_window.py:244 #, fuzzy msgid "Do you really want to close them all?" msgstr "O que pretende fazer?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Chat" #: gajim/message_window.py:524 #, fuzzy msgid "Private Chats" msgstr "Iniciar Conversa" #: gajim/message_window.py:530 #, fuzzy msgid "Messages" msgstr "Mensagem" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 #, fuzzy msgid "Unable to join group chat" msgstr "Impossível entrar na sala" #: gajim/gui_interface.py:170 #, fuzzy, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "A alcunha que deseja encontra-se em uso ou registado por outro ocupante.\n" "Por favor, introduza outra alcunha em baixo:" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Aceita este pedido?" #: gajim/gui_interface.py:194 #, fuzzy, python-format msgid "Do you accept this request on account %s?" msgstr "Aceita este pedido?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "HTTP (%s) Autorização para %s (id: %s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 #, fuzzy msgid "Connection Failed" msgstr "Ligação" #: gajim/gui_interface.py:327 #, fuzzy, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "É necessária uma palavra-passe para esta sala." #: gajim/gui_interface.py:342 #, fuzzy, python-format msgid "%s is full" msgstr "Registos" #: gajim/gui_interface.py:351 #, fuzzy, python-format msgid "You are banned from group chat %s." msgstr "Está banido/a desta sala." #: gajim/gui_interface.py:358 #, fuzzy, python-format msgid "Remote server %s does not exist." msgstr "Tal sala não existe." #: gajim/gui_interface.py:362 #, fuzzy, python-format msgid "Group chat %s does not exist." msgstr "Tal sala não existe." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "Criação de salas encontra-se restrita." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Impossível entrar na sala" #: gajim/gui_interface.py:368 #, fuzzy, python-format msgid "You must use your registered nickname in %s." msgstr "A sua alcunha registada tem de ser usada." #: gajim/gui_interface.py:373 #, fuzzy, python-format msgid "You are not in the members list in groupchat %s." msgstr "Não está na lista de membros." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, fuzzy, python-format msgid "Error %(code)s: %(msg)s" msgstr "Introduza a sua mensagem :" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, fuzzy, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "erro ao enviar" #: gajim/gui_interface.py:503 gajim/notify.py:194 #, fuzzy msgid "Subscription request" msgstr "Pedido de Subscrição" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 #, fuzzy msgid "Observers" msgstr "Servidor" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Autorização aceite" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "O contacto \"%s\" autorizou-o a ver o seu estado." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Contacto \"%s\" removeu a sua subscrição para si" #: gajim/gui_interface.py:539 msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" #: gajim/gui_interface.py:560 gajim/notify.py:194 #, fuzzy msgid "Unsubscribed" msgstr "_Subscrever" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "" #: gajim/gui_interface.py:644 #, fuzzy, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Está banido/a desta sala." #: gajim/gui_interface.py:658 msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "Está neste momento ligado sem a sua chave OpenPGP." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Frase de acesso" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Frase de acesso" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "Frase de acesso Necessária" #: gajim/gui_interface.py:683 #, fuzzy, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Introduza a chave GPG para a conta %s" #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Escolha sua chave OpenPGP" #: gajim/gui_interface.py:706 msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Erro na Transferência de Ficheiro" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "%s quer enviar-lhe um ficheiro." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Pedido de Transferência de Ficheiro" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Transferência de Ficheiro Completa" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Transferência de Ficheiro Parada" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Transferências de Ficheiros" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Transferência de %(filename)s de %(name)s interrompida." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Transferência de %(filename)s de %(name)s interrompida." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Transferência de %(filename)s de %(name)s interrompida." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Enviou com sucesso %(filename)s para %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Transferência de %(filename)s para %(name)s interrompida." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Transferência de %(filename)s para %(name)s interrompida." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "" #: gajim/gui_interface.py:1178 #, fuzzy msgid "Please type a new username for your local account" msgstr "Por favor preencha os dados para a sua nova conta" #: gajim/gui_interface.py:1201 #, fuzzy msgid "Resource Conflict" msgstr "Recurso: " #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "" #: gajim/gui_interface.py:1259 #, fuzzy, python-format msgid "%s wants to start a voice chat." msgstr "%s quer enviar-lhe um ficheiro." #: gajim/gui_interface.py:1261 #, fuzzy msgid "Voice Chat Request" msgstr "Pedido de Transferência de Ficheiro" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 #, fuzzy msgid "Certificate Already in File" msgstr "Contacto já se encontra na lista" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" #: gajim/gui_interface.py:1351 #, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "" #: gajim/gui_interface.py:1354 #, fuzzy, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "Versão D-Bus desconhecida: %s" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "" #: gajim/gui_interface.py:1362 #, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "" #: gajim/gui_interface.py:1380 #, python-format msgid "SSL Certificate Verification for %s" msgstr "" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 #, fuzzy msgid "Insecure connection" msgstr "Ligação" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "Tem de criar uma conta antes de poder conversar com outros contactos." #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "Não pode entrar num chat sem estar ligado." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 #, fuzzy msgid "You cannot join a group chat while you are invisible" msgstr "Não pode entrar numa sala quando está invisível" #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Impossível salvar as suas definições e preferências" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Frase de acesso Necessária" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "Introduza a chave GPG para a conta %s" #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "Encriptação OpenPGP" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "O utilizador será ligado a %s sem OpenPGP." #: gajim/gui_interface.py:2852 #, fuzzy msgid "Wrong Passphrase" msgstr "Frase de acesso" #: gajim/gui_interface.py:2853 msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "" #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "Ligação" #: gajim/atom_window.py:123 #, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "" msgstr[1] "" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "" #: gajim/adhoc_commands.py:326 #, fuzzy msgid "Cancel confirmation" msgstr "Informações do Contacto" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "" #: gajim/adhoc_commands.py:422 #, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Contacto Entrou" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Contacto Saiu" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Nova Mensagem" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Nova Mensagem Instantânea" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Nova Mensagem Privada" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 #, fuzzy msgid "Contact Changed Status" msgstr "Contacto Saiu" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenPGP: " #: gajim/notify.py:270 #, fuzzy msgid "New E-mail" msgstr "E-Mail" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "Não pode entrar num chat sem estar ligado." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 #, fuzzy msgid "Invalid JID" msgstr "Jabber ID Inválido" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, fuzzy, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "Não é possível enviar ficheiros vazios" #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "" #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "Está neste momento ligado ao servidor" #: gajim/dialog_messages.py:53 #, fuzzy msgid "To disable the account, you must be disconnected." msgstr "Para mudar o nome da conta, deve estar disconectado." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Entrada inválida" #: gajim/dialog_messages.py:58 msgid "The form is not filled correctly." msgstr "O formulário não foi preenchido correctamente" #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Invisível" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "Uma ligação não está disponível" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "A sua mensagem não pode ser enviada enquanto não estiver ligado." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "Cliente de IM Jabber" #: gajim/dialog_messages.py:73 msgid "The JID you entered is already in the list. Choose another one." msgstr "" #: gajim/dialog_messages.py:77 #, fuzzy msgid "Invalid answer" msgstr "Senha Inválida" #: gajim/dialog_messages.py:78 #, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "" #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Usar hostname/porta personalizados" #: gajim/dialog_messages.py:84 #, fuzzy, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Usar hostname/porta personalizados" #: gajim/dialog_messages.py:88 #, fuzzy msgid "Error while removing privacy list" msgstr "erro ao enviar" #: gajim/dialog_messages.py:89 #, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" #: gajim/dialog_messages.py:95 msgid "Invisibility not supported" msgstr "" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "" #: gajim/dialog_messages.py:100 #, fuzzy msgid "Unregister failed" msgstr "Publicação vCard falhou" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "" #: gajim/dialog_messages.py:105 #, fuzzy msgid "Registration succeeded" msgstr "Publicação vCard deu-se com sucesso" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 #, fuzzy msgid "Registration failed" msgstr "Publicação vCard falhou" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Impossível entrar na sala" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, fuzzy, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "Introduza a sua mensagem :" #: gajim/dialog_messages.py:126 #, fuzzy msgid "Wrong host" msgstr "Frase de acesso" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 msgid "Could not request upload slot" msgstr "" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 msgid "Could not open file" msgstr "" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 msgid "Server returned unsecure transport (HTTP)" msgstr "" #: gajim/dialog_messages.py:161 msgid "Could not upload file" msgstr "" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 #, fuzzy msgid "Encryption Error" msgstr "Encriptação activada" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "Uma ligação não está disponível" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "Publicação vCard falhou" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "D-Bus não está presente nesta máquina, ou falta módulo python" #: gajim/gajim_remote.py:77 #, fuzzy msgid "Shows a help on specific command" msgstr "Exibe ajuda acerca de um comando específico" #: gajim/gajim_remote.py:80 msgid "command" msgstr "comando" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "mostrar ajuda sobre comando" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "Mostra uma lista de todos os contactos na lista. Cada contacto aparece numa " "linha separada" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "conta" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "mostrar apenas contactos da conta indicada" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "Mostra uma lista de contas registadas" #: gajim/gajim_remote.py:97 #, fuzzy msgid "Changes the status of account(s)" msgstr "Muda o estado de uma ou várias contas" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "estado" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "" "um de: offline, disponível, livre para conversar, ausente, indisponível, " "ocupado, invisível" #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "mensagem" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "mensagem de estado:" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "mudar estado da conta \"account\". Se não especificado, tentará mudar o " "estado de todas as contas que têm a opção \"sincronizar com estado global\" " "activada" #: gajim/gajim_remote.py:108 #, fuzzy msgid "Changes the priority of account(s)" msgstr "Muda o estado de uma ou várias contas" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "_Prioridade" #: gajim/gajim_remote.py:110 #, fuzzy msgid "priority you want to give to the account" msgstr "Quero _registar uma nova conta" #: gajim/gajim_remote.py:112 #, fuzzy msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "mudar estado da conta \"account\". Se não especificado, tentará mudar o " "estado de todas as contas que têm a opção \"sincronizar com estado global\" " "activada" #: gajim/gajim_remote.py:118 #, fuzzy msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Envia uma nova mensagem a um contacto da lista. Ambas a chave OpenPGP e a " "conta são opcionais. Se quiser definir apenas 'conta', sem 'chave OpenPGP', " "basta definir 'chave OpenPGP' para ''." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID do destinatário da mensagem" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "conteúdo da mensagem" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "se especificado, a mensagem será encriptada usando esta chave pública" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "se especificado, a mensagem será enviada usadando esta conta" #: gajim/gajim_remote.py:131 #, fuzzy msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Envia uma nova mensagem a um contacto da lista. Ambas a chave OpenPGP e a " "conta são opcionais. Se quiser definir apenas 'conta', sem 'chave OpenPGP', " "basta definir 'chave OpenPGP' para ''." #: gajim/gajim_remote.py:136 #, fuzzy msgid "subject" msgstr "Assunto:" #: gajim/gajim_remote.py:136 #, fuzzy msgid "message subject" msgstr "Mensagem" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "" #: gajim/gajim_remote.py:147 #, fuzzy msgid "JID of the room that will receive the message" msgstr "JID do destinatário da mensagem" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Busca informações detalhadas sobre um contacto" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "JID do contacto" #: gajim/gajim_remote.py:160 #, fuzzy msgid "Gets detailed info on a account" msgstr "Busca informações detalhadas sobre um contacto" #: gajim/gajim_remote.py:162 #, fuzzy msgid "Name of the account" msgstr "Não tem nenhuma conta activa" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Envia um ficheiro a um contacto" #: gajim/gajim_remote.py:168 msgid "file" msgstr "Ficheiro" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Localização do ficheiro" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "se especificado, a mensagem será enviada usadando esta conta" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Exibe todas as preferências e os seus valores" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "Define o valor de 'chave' para 'valor'." #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "chave=valor" #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "" "'chave' é o nome da preferência, 'valor' é o valor da qual se pretende " "definir" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "Apaga um item das preferências" #: gajim/gajim_remote.py:188 msgid "key" msgstr "chave" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "nome da preferência a apagar" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "" "Escreve o estado actual das preferências do Gajim para o ficheiro .config" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Remove o contacto da lista" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "" "se especificado, o contacto é escolhido da lista de contactos desta conta" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "" "Indica o estado actual (o estado global, a não ser que uma conta seja " "especificada)." #: gajim/gajim_remote.py:214 #, fuzzy msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" "Indica o estado actual (o estado global, a não ser que uma conta seja " "especificada)." #: gajim/gajim_remote.py:221 #, fuzzy msgid "Returns number of unread messages" msgstr "Tem mensagens não lidas" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "" #: gajim/gajim_remote.py:228 #, fuzzy msgid "XML to send" msgstr "Consola XML" #: gajim/gajim_remote.py:229 msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Contacto Saiu" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "Alcunha não encontrada: %s" #: gajim/gajim_remote.py:238 msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" #: gajim/gajim_remote.py:245 msgid "Check if Gajim is running" msgstr "" #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "Argumento em falta \"contacto_jid\"" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "'%s' não está na sua lista.\n" "Por favor, especifique a conta para enviar a mensagem" #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "Não tem nenhuma conta activa" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "" #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Argumentos:" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "%s não encontrado" #: gajim/gajim_remote.py:383 #, fuzzy, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Uso: %s comando [argumentos]\n" "Comando é um de:\n" #: gajim/gajim_remote.py:453 #, fuzzy, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Argumento \"%s\" não está especificado. \n" "Escreva \"%s help %s\" para mais informações" #: gajim/gajim_remote.py:458 #, fuzzy, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Argumento \"%s\" não está especificado. \n" "Escreva \"%s help %s\" para mais informações" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "" #: gajim/common/fuzzyclock.py:36 #, fuzzy msgid "one" msgstr "Nenhum" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "" #: gajim/common/fuzzyclock.py:36 #, fuzzy msgid "three" msgstr "Rua:" #: gajim/common/fuzzyclock.py:36 #, fuzzy msgid "four" msgstr "Porta:" #: gajim/common/fuzzyclock.py:37 #, fuzzy msgid "five" msgstr "Ficheiro" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "" #: gajim/common/fuzzyclock.py:37 #, fuzzy msgid "seven" msgstr "Evento" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "" #: gajim/common/fuzzyclock.py:37 #, fuzzy msgid "nine" msgstr "_Continuar" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "" #: gajim/common/fuzzyclock.py:38 #, fuzzy msgid "eleven" msgstr "Apagar MOTD" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "" #: gajim/common/fuzzyclock.py:46 #, fuzzy, python-format msgid "five past %(0)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:47 #, fuzzy, python-format msgid "ten past %(0)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:48 #, fuzzy, python-format msgid "quarter past %(0)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:49 #, fuzzy, python-format msgid "twenty past %(0)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:50 #, fuzzy, python-format msgid "twenty five past %(0)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "" #: gajim/common/fuzzyclock.py:52 #, fuzzy, python-format msgid "twenty five to %(1)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:53 #, fuzzy, python-format msgid "twenty to %(1)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:54 #, fuzzy, python-format msgid "quarter to %(1)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:55 #, fuzzy, python-format msgid "ten to %(1)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:56 #, fuzzy, python-format msgid "five to %(1)s" msgstr "Registar para %s" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "" #: gajim/common/fuzzyclock.py:63 #, fuzzy msgid "Morning" msgstr "A trabalhar" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "" #: gajim/common/fuzzyclock.py:65 #, fuzzy msgid "Noon" msgstr "Nenhum" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "" #: gajim/common/fuzzyclock.py:67 #, fuzzy msgid "Evening" msgstr "Evento" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, fuzzy, python-format msgid "%s is a directory but should be a file" msgstr "%s é um directório, mas deveria ser um ficheiro" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Descrição: %s" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 #, fuzzy msgid "Room has been destroyed" msgstr "Autorização foi removida" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "" #: gajim/common/connection_handlers_events.py:598 #, fuzzy, python-format msgid "Unknown SSL error: %d" msgstr "Versão D-Bus desconhecida: %s" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Nova Mensagem como %s" msgstr[1] "Nova Mensagem como %s" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s Mudou de Estado" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s Iniciou Sessão" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "%(nickname)s Terminou Sessão" #: gajim/common/contacts.py:427 #, fuzzy msgid "Not in roster" msgstr "Fora da lista" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "" #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "Tempo, em minutos, após o qual o seu estado muda para Ausente." #: gajim/common/config.py:87 #, fuzzy msgid "$S (Away as a result of being idle more than $T min)" msgstr "Ausente por estar inactivo" #: gajim/common/config.py:87 msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "Tempo, em minutos, após o qual o seu estado muda para Indisponível." #: gajim/common/config.py:90 #, fuzzy msgid "$S (Not available as a result of being idle more than $T min)" msgstr "Indisponível por estar inactivo" #: gajim/common/config.py:90 msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" #: gajim/common/config.py:93 msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "Mostrar apenas na _lista" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "Mostrar apenas na _lista" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "Noti_ficação do estado da conversa:" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Pedido de Transferência de Ficheiro" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Transferência de ficheiro cancelada" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "" "Quando uma transferência de ficheiro é concluida, exibir um popup de " "notificação" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "?Função do Contacto no Chat:Nenhuma" #: gajim/common/config.py:106 msgid "Background color of status changed notification" msgstr "" #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "" #: gajim/common/config.py:109 #, fuzzy msgid "default" msgstr "Apagar MOTD" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "" #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "Se Verdadeiro (True), não remover */_ . Para que *abc* fique em negrito " "(bold) mas * * não seja removido." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Adicionar * e [n] no título da lista de contactos?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Número de linhas, da conversa anterior, a lembrar para quando uma janela/aba " "de conversa seja reaberta." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" #: gajim/common/config.py:177 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" "Enviar mensagem ao premir Ctrl+Enter e fazer nova linha com Enter " "(Comportamento por defeito do cliente ICQ Mirabilis)." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Número de linhas a guardar ao premir Ctrl+TeclaCIMA." #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Ou um endereço URL personalizado contendo %s, onde %s é a palavra ou frase, " "ou 'WIKTIONARY', que significa que será usado o Wiktionary." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "Se marcado, Gajim pode ser controlado à distância usando gajim-remote." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/common/config.py:196 msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" #: gajim/common/config.py:199 #, fuzzy msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" "Overrides the host we send for File Transfer in case of address translation/" "port forwarding." #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "O standart IEC diz: KiB = 1024 bytes, KB = 1000 bytes." #: gajim/common/config.py:202 msgid "Notify of events in the notification area." msgstr "" #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Mostrar aba quando apenas numa conversa?" #: gajim/common/config.py:210 #, fuzzy msgid "Show tabbed notebook border in chat windows?" msgstr "Mostrar borda da aba quando apenas numa conversa?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Mostrar botão de fechar na aba?" #: gajim/common/config.py:224 #, fuzzy msgid "Preview new messages in notification popup?" msgstr "Noti_ficação do estado da conversa:" #: gajim/common/config.py:227 #, fuzzy msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" "Uma lista de palavras separadas por ponto-e-vírgula e que serão sublinhadas " "num chat de vários utilizadores." #: gajim/common/config.py:228 #, fuzzy msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" "Se Verdadeiro (True), sai do Gajim quando o botão X do Window Manager for " "clicado. Esta definição só será aplicada se o trayicon estiver a ser usado." #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 #, fuzzy msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" "Se Verdadeiro (True), Gajim mostrará um ícone em cada aba contendo mensagens " "não lidas. Dependendo do tema, este ícone poderá ser animado." #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" "Se Verdadeiro (True), Gajim exibirá a mensagem de estado, caso houver, de " "cada contacto debaixo do nome de cada um deles na lista" #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "" #: gajim/common/config.py:238 #, fuzzy msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" "Se Falso (False), deixará de ver a linha de estados em conversas quando um " "contacto mudar de estado ou de mensagem de estado." #: gajim/common/config.py:239 msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "" #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "" #: gajim/common/config.py:245 msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" #: gajim/common/config.py:249 msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "" #: gajim/common/config.py:252 msgid "If true, pressing the escape key closes a tab/window." msgstr "" #: gajim/common/config.py:253 #, fuzzy msgid "Hides the banner in a group chat window" msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "" #: gajim/common/config.py:255 #, fuzzy msgid "Hides the group chat occupants list in group chat window." msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "" #: gajim/common/config.py:258 #, fuzzy msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "" "Uma lista de palavras separadas por ponto-e-vírgula e que serão sublinhadas " "num chat de vários utilizadores." #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "" #: gajim/common/config.py:260 msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" #: gajim/common/config.py:261 msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" #: gajim/common/config.py:262 msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" #: gajim/common/config.py:263 msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" #: gajim/common/config.py:264 msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" #: gajim/common/config.py:266 msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" #: gajim/common/config.py:269 msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "" #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" #: gajim/common/config.py:272 msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "" #: gajim/common/config.py:325 msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" #: gajim/common/config.py:326 msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "" #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "" #: gajim/common/config.py:337 msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "" #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "" #: gajim/common/config.py:354 msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "Se marcado, o Gajim juntar-se-á a este chat no arranque" #: gajim/common/config.py:386 msgid "Allow Gajim to send your local time." msgstr "Permitir que o Gajim envie a sua hora local." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Por favor preencha os dados do contacto que deseja adicionar" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Usar autenticação" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Usar autenticação" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Usar autenticação" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 msgid "Language for which misspelled words will be checked" msgstr "" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" #: gajim/common/config.py:442 msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "A dormir" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Volto logo" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Volto daqui a alguns minutos" #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "A comer" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "Estou a comer, por isso deixe-me uma mensagem" #: gajim/common/config.py:454 msgid "Movie" msgstr "Filme" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "Estou a ver um filme." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "A trabalhar" #: gajim/common/config.py:455 msgid "I'm working." msgstr "Estou a trabalhar" #: gajim/common/config.py:456 msgid "Phone" msgstr "Telefone" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Estou ao telefone." #: gajim/common/config.py:457 msgid "Out" msgstr "Estou fora" #: gajim/common/config.py:457 #, fuzzy msgid "I'm out enjoying life." msgstr "Estou fora, fui apreciar a vida" #: gajim/common/config.py:468 #, fuzzy msgid "I'm available." msgstr "Disponível" #: gajim/common/config.py:469 #, fuzzy msgid "I'm free for chat." msgstr "Livre para conversar" #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "" #: gajim/common/config.py:471 #, fuzzy msgid "I'm not available." msgstr "Serviço não disponível" #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "" #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "" #: gajim/common/config.py:485 #, fuzzy msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" "Som a tocar quando uma mensagem de chat conter uma das palavras da lista " "muc_highlight_words, or quando uma mensagem conter a sua alcunha." #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "" #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "Para" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Erro: impossível abrir %s para leitura" #: gajim/common/const.py:205 #, fuzzy msgid "Doing Chores" msgstr "Frase de acesso" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "" #: gajim/common/const.py:207 #, fuzzy msgid "Cleaning" msgstr "Evento" #: gajim/common/const.py:208 #, fuzzy msgid "Cooking" msgstr "A trabalhar" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "" #: gajim/common/const.py:212 #, fuzzy msgid "Gardening" msgstr "A trabalhar" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "" #: gajim/common/const.py:214 #, fuzzy msgid "Walking the Dog" msgstr "Neste grupo" #: gajim/common/const.py:216 #, fuzzy msgid "Drinking" msgstr "A trabalhar" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "" #: gajim/common/const.py:227 msgid "Exercising" msgstr "" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "" #: gajim/common/const.py:229 #, fuzzy msgid "Dancing" msgstr "Evento" #: gajim/common/const.py:230 #, fuzzy msgid "Hiking" msgstr "Expulsando %s" #: gajim/common/const.py:231 #, fuzzy msgid "Jogging" msgstr "_Entrar" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "" #: gajim/common/const.py:233 msgid "Running" msgstr "" #: gajim/common/const.py:234 #, fuzzy msgid "Skiing" msgstr "A trabalhar" #: gajim/common/const.py:235 msgid "Swimming" msgstr "" #: gajim/common/const.py:236 #, fuzzy msgid "Working out" msgstr "A trabalhar" #: gajim/common/const.py:238 msgid "Grooming" msgstr "" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "" #: gajim/common/const.py:242 #, fuzzy msgid "Shaving" msgstr "A comer" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "" #: gajim/common/const.py:248 #, fuzzy msgid "Inactive" msgstr "Activo" #: gajim/common/const.py:249 msgid "Day Off" msgstr "" #: gajim/common/const.py:250 #, fuzzy msgid "Hanging out" msgstr "Mudar Assunto" #: gajim/common/const.py:251 #, fuzzy msgid "Hiding" msgstr "Expulsando %s" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "" #: gajim/common/const.py:253 #, fuzzy msgid "Praying" msgstr "A comer" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "" #: gajim/common/const.py:256 #, fuzzy msgid "Thinking" msgstr "A trabalhar" #: gajim/common/const.py:258 #, fuzzy msgid "Relaxing" msgstr "simples" #: gajim/common/const.py:259 #, fuzzy msgid "Fishing" msgstr "Expulsando %s" #: gajim/common/const.py:260 #, fuzzy msgid "Gaming" msgstr "A comer" #: gajim/common/const.py:261 #, fuzzy msgid "Going out" msgstr "_Desligar" #: gajim/common/const.py:262 #, fuzzy msgid "Partying" msgstr "A comer" #: gajim/common/const.py:263 #, fuzzy msgid "Reading" msgstr "A comer" #: gajim/common/const.py:264 msgid "Rehearsing" msgstr "" #: gajim/common/const.py:265 #, fuzzy msgid "Shopping" msgstr "A dormir" #: gajim/common/const.py:266 #, fuzzy msgid "Smoking" msgstr "A trabalhar" #: gajim/common/const.py:267 msgid "Socializing" msgstr "" #: gajim/common/const.py:268 #, fuzzy msgid "Sunbathing" msgstr "A comer" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "" #: gajim/common/const.py:270 #, fuzzy msgid "Watching a Movie" msgstr "Estou a ver um filme." #: gajim/common/const.py:272 #, fuzzy msgid "Talking" msgstr "A comer" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "" #: gajim/common/const.py:274 #, fuzzy msgid "On the Phone" msgstr "Estou ao telefone." #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "" #: gajim/common/const.py:277 #, fuzzy msgid "Traveling" msgstr "A transferir" #: gajim/common/const.py:278 #, fuzzy msgid "Commuting" msgstr "Ligando" #: gajim/common/const.py:280 msgid "Driving" msgstr "" #: gajim/common/const.py:281 msgid "In a Car" msgstr "" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "" #: gajim/common/const.py:283 msgid "On a Plane" msgstr "" #: gajim/common/const.py:284 msgid "On a Train" msgstr "" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "" #: gajim/common/const.py:286 #, fuzzy msgid "Walking" msgstr "A trabalhar" #: gajim/common/const.py:289 #, fuzzy msgid "Coding" msgstr "Ligação" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "" #: gajim/common/const.py:291 msgid "Studying" msgstr "" #: gajim/common/const.py:292 #, fuzzy msgid "Writing" msgstr "A trabalhar" #: gajim/common/const.py:295 msgid "Afraid" msgstr "" #: gajim/common/const.py:296 msgid "Amazed" msgstr "" #: gajim/common/const.py:297 msgid "Amorous" msgstr "" #: gajim/common/const.py:298 msgid "Angry" msgstr "" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "" #: gajim/common/const.py:300 msgid "Anxious" msgstr "" #: gajim/common/const.py:301 #, fuzzy msgid "Aroused" msgstr "Pausada" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "" #: gajim/common/const.py:303 #, fuzzy msgid "Bored" msgstr "Negrito" #: gajim/common/const.py:304 msgid "Brave" msgstr "" #: gajim/common/const.py:305 msgid "Calm" msgstr "" #: gajim/common/const.py:306 #, fuzzy msgid "Cautious" msgstr "Conversa" #: gajim/common/const.py:307 #, fuzzy msgid "Cold" msgstr "Negrito" #: gajim/common/const.py:308 #, fuzzy msgid "Confident" msgstr "_Conteúdo" #: gajim/common/const.py:309 msgid "Confused" msgstr "" #: gajim/common/const.py:310 #, fuzzy msgid "Contemplative" msgstr "Completa" #: gajim/common/const.py:311 #, fuzzy msgid "Contented" msgstr "_Conteúdo" #: gajim/common/const.py:312 msgid "Cranky" msgstr "" #: gajim/common/const.py:313 msgid "Crazy" msgstr "" #: gajim/common/const.py:314 #, fuzzy msgid "Creative" msgstr "Activo" #: gajim/common/const.py:315 #, fuzzy msgid "Curious" msgstr "_Anterior" #: gajim/common/const.py:316 #, fuzzy msgid "Dejected" msgstr "Apagar MOTD" #: gajim/common/const.py:317 msgid "Depressed" msgstr "" #: gajim/common/const.py:318 msgid "Disappointed" msgstr "" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "" #: gajim/common/const.py:320 msgid "Dismayed" msgstr "" #: gajim/common/const.py:321 msgid "Distracted" msgstr "" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "" #: gajim/common/const.py:323 #, fuzzy msgid "Envious" msgstr "_Anterior" #: gajim/common/const.py:324 msgid "Excited" msgstr "" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "" #: gajim/common/const.py:327 msgid "Grateful" msgstr "" #: gajim/common/const.py:328 msgid "Grieving" msgstr "" #: gajim/common/const.py:329 #, fuzzy msgid "Grumpy" msgstr "Grupo" #: gajim/common/const.py:330 msgid "Guilty" msgstr "" #: gajim/common/const.py:331 msgid "Happy" msgstr "" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "" #: gajim/common/const.py:333 #, fuzzy msgid "Hot" msgstr "_Host:" #: gajim/common/const.py:334 msgid "Humbled" msgstr "" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "" #: gajim/common/const.py:336 msgid "Hungry" msgstr "" #: gajim/common/const.py:337 msgid "Hurt" msgstr "" #: gajim/common/const.py:338 #, fuzzy msgid "Impressed" msgstr "mensagem" #: gajim/common/const.py:339 msgid "In Awe" msgstr "" #: gajim/common/const.py:340 msgid "In Love" msgstr "" #: gajim/common/const.py:341 msgid "Indignant" msgstr "" #: gajim/common/const.py:342 msgid "Interested" msgstr "" #: gajim/common/const.py:343 msgid "Intoxicated" msgstr "" #: gajim/common/const.py:344 #, fuzzy msgid "Invincible" msgstr "Invisível" #: gajim/common/const.py:345 msgid "Jealous" msgstr "" #: gajim/common/const.py:346 #, fuzzy msgid "Lonely" msgstr "Nenhum" #: gajim/common/const.py:347 #, fuzzy msgid "Lost" msgstr "_Host:" #: gajim/common/const.py:348 msgid "Lucky" msgstr "" #: gajim/common/const.py:349 #, fuzzy msgid "Mean" msgstr "Geral" #: gajim/common/const.py:350 #, fuzzy msgid "Moody" msgstr "_Modificar" #: gajim/common/const.py:351 #, fuzzy msgid "Nervous" msgstr "_Anterior" #: gajim/common/const.py:352 msgid "Neutral" msgstr "" #: gajim/common/const.py:353 #, fuzzy msgid "Offended" msgstr "Offline" #: gajim/common/const.py:354 msgid "Outraged" msgstr "" #: gajim/common/const.py:355 msgid "Playful" msgstr "" #: gajim/common/const.py:356 #, fuzzy msgid "Proud" msgstr "Grupo" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "" #: gajim/common/const.py:358 #, fuzzy msgid "Relieved" msgstr "Apagar MOTD" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "" #: gajim/common/const.py:360 msgid "Restless" msgstr "" #: gajim/common/const.py:361 #, fuzzy msgid "Sad" msgstr "Interrompida" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "" #: gajim/common/const.py:363 #, fuzzy msgid "Satisfied" msgstr "Nome:" #: gajim/common/const.py:364 #, fuzzy msgid "Serious" msgstr "_Anterior" #: gajim/common/const.py:365 msgid "Shocked" msgstr "" #: gajim/common/const.py:366 msgid "Shy" msgstr "" #: gajim/common/const.py:367 #, fuzzy msgid "Sick" msgstr "_Expulsar" #: gajim/common/const.py:368 #, fuzzy msgid "Sleepy" msgstr "A dormir" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "" #: gajim/common/const.py:370 #, fuzzy msgid "Stressed" msgstr "Rua:" #: gajim/common/const.py:371 msgid "Strong" msgstr "" #: gajim/common/const.py:372 #, fuzzy msgid "Surprised" msgstr "Subscrição" #: gajim/common/const.py:373 msgid "Thankful" msgstr "" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "" #: gajim/common/const.py:375 #, fuzzy msgid "Tired" msgstr "Tempo" #: gajim/common/const.py:376 #, fuzzy msgid "Undefined" msgstr "Sublinhar" #: gajim/common/const.py:377 msgid "Weak" msgstr "" #: gajim/common/const.py:378 msgid "Worried" msgstr "" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "Apagar MOTD" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "marine" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Expulsando %s" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "País:" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Conta" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Descrição" #: gajim/common/const.py:391 #, fuzzy msgid "error" msgstr "Erro:" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "Nenhum" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 #, fuzzy msgid "room" msgstr "De" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "" #: gajim/common/const.py:412 #, fuzzy msgid "Unable to decode issuer public key" msgstr "Impossível entrar na sala" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "" #: gajim/common/const.py:430 #, fuzzy msgid "Invalid CA certificate" msgstr "Nome de utilizador inválido" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Ligação com conta \"%s\" foi perdida" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "" #: gajim/common/connection.py:740 #, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "" #: gajim/common/connection.py:1090 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Impossível ligar a \"%s\"" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Impossível ligar a \"%s\"" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Verifique a sua ligação ou tente novamente mais tarde." #: gajim/common/connection.py:1100 #, fuzzy, python-format msgid "Server replied: %s" msgstr "Guardado em: %s" #: gajim/common/connection.py:1115 #, fuzzy msgid "Connection to proxy failed" msgstr "Ligação" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, fuzzy, python-format msgid "Could not connect to account %s" msgstr "Impossível ligar a \"%s\"" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, fuzzy, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "Ligação com conta \"%s\" foi perdida" #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Impossível ligar a \"%s\"" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "Falha na autenticação com \"%s\"" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Por favor, verifique se o seu login e senha estão correctos." #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "Bindings do python D-Bus estão em falta neste computador" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "As potencialidades do D-Bus no Gajim não podem ser usadas" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "D-Bus não está presente nesta máquina, ou falta módulo python" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "D-Bus não está presente nesta máquina, ou falta módulo python" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Mensagem de Estado" #: gajim/common/multimedia_helpers.py:70 msgid "Audio test" msgstr "" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Tamanho: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Ficheiro: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "green" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, python-format msgid "%s configuration error" msgstr "%s erro de configuração" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Caractere inválido no hostname." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Endereço de servidor necessário." #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Caractere inválido no nome de utilizador" #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "Caractere inválido no recurso." #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "_Ocupado" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "_Indisponível" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "_Livre para conversar" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "_Disponível" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "Ligando" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "A_usente" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "_Offline" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "In_visível" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "Desconhecido" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "Contém erros" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "Nenhuma" #: gajim/common/helpers.py:315 msgid "To" msgstr "Para" #: gajim/common/helpers.py:317 msgid "From" msgstr "De" #: gajim/common/helpers.py:319 msgid "Both" msgstr "Ambos" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "?SO:Desconhecido" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "Nenhum" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Subscrição" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "?Função do Contacto no Chat:Nenhuma" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Moderadores" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Moderador" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Participantes" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Participante" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Visitantes" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Visitante" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "está a prestar atenção à conversa" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "está a fazer outra coisa qualquer" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "está a escrever uma mensagem..." #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "pausa na composição da mensagem" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "fechou a janela de conversa ou aba" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s GiB" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s GB" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s MiB" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s MB" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s KiB" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s KB" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s B" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "%d mensagem pendente" msgstr[1] "%d mensagens pendentes" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr "De %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, fuzzy, python-format msgid "from user %s" msgstr "De %s" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr "De %s" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "" msgstr[1] "" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Gostaria de o adicionar à minha lista de contactos." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 msgid "Timeout loading image" msgstr "" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "Imagem é muito grande" #: gajim/common/helpers.py:1383 msgid "PyCURL is not installed" msgstr "" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Erro na leitura do ficheiro:" #: gajim/common/configpaths.py:85 #, fuzzy, python-format msgid "%s is a file but it should be a directory" msgstr "%s é um ficheiro, mas deveria ser um directório" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Gajim irá agora sair" #: gajim/common/exceptions.py:45 #, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" "Serviço/Recurso indisponível: Gajim não está a correr, ou remote_control é " "False" #: gajim/common/exceptions.py:81 #, fuzzy, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "Bus da sessão não está disponível." #: gajim/common/exceptions.py:93 #, fuzzy, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "Bus da sessão não está disponível." #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 msgid "Please check if Avahi or Bonjour is installed." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, fuzzy, python-format msgid "Unable to bind to port %d." msgstr "Impossível entrar na sala" #: gajim/common/zeroconf/connection_zeroconf.py:217 msgid "Please check if avahi/bonjour-daemon is running." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, fuzzy, python-format msgid "Could not change status of account \"%s\"" msgstr "Impossível ligar a \"%s\"" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:349 #, fuzzy msgid "Your message could not be sent." msgstr "A sua mensagem não pode ser enviada enquanto não estiver ligado." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "" #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "" #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, fuzzy, python-format msgid "Error while adding service. %s" msgstr "erro ao enviar" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "mensagem" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "Eu gostaria de o adicionar à minha lista" #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Introduza a sua mensagem :" #: gajim/common/modules/httpupload.py:134 #, fuzzy msgid "File is empty" msgstr "Localização do ficheiro" #: gajim/common/modules/httpupload.py:137 #, fuzzy msgid "File does not exist" msgstr "Tal sala não existe." #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 #, fuzzy msgid "Change status information" msgstr "Informações do Contacto" #: gajim/common/modules/adhoc_commands.py:113 #, fuzzy msgid "Change status" msgstr "Contacto Saiu" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "" #: gajim/common/modules/adhoc_commands.py:121 #, fuzzy msgid "Free for chat" msgstr "Livre para conversar" #: gajim/common/modules/adhoc_commands.py:122 #, fuzzy msgid "Online" msgstr "_Continuar" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "" #: gajim/common/modules/adhoc_commands.py:132 #, fuzzy msgid "Presence description:" msgstr "Descrição" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "" #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 #, fuzzy msgid "Leave Groupchats" msgstr "Chat" #: gajim/common/modules/adhoc_commands.py:231 #, fuzzy, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s na sala %(room_name)s enviou-lhe uma nova mensagem." #: gajim/common/modules/adhoc_commands.py:235 #, fuzzy msgid "You have not joined a groupchat." msgstr "Neste grupo" #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "" #: gajim/common/modules/adhoc_commands.py:292 msgid "You left the following groupchats:" msgstr "Saiu das seguintes conversas de grupo:" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "Artista Desconhecido" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "Título Desconhecido" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "Fonte Desconhecida" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" #: gajim/common/modules/roster_item_exchange.py:100 #, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "" #: gajim/common/modules/roster_item_exchange.py:104 #, fuzzy msgid "Sent contacts:" msgstr "Contacto:" #: gajim/data/gui/blocked_contacts_window.ui:13 #, fuzzy msgid "Blocked Contacts" msgstr "Contacto:" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Editor de Configuração Avançada" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Filtro:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Descrição" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "Voltar às Cores Padrão" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Entrar automaticamente" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Conta" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Sala:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Senha:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "Adicionar esta Sala aos _Bookmarks" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "Adicionar esta Sala aos _Bookmarks" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "_Entrar num Chat" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 #, fuzzy msgid "HTTP Connect" msgstr "Ligação HTTP" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Gerir Perfis de Proxy" #: gajim/data/gui/manage_proxies_window.ui:148 #, fuzzy msgid "_Name:" msgstr "_Nome: " #: gajim/data/gui/manage_proxies_window.ui:161 #, fuzzy msgid "_Type:" msgstr "Tipo:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Propriedades" #: gajim/data/gui/manage_proxies_window.ui:234 msgid "_BOSH URL:" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:258 #, fuzzy msgid "Proxy _Host:" msgstr "Proxy:" #: gajim/data/gui/manage_proxies_window.ui:269 #, fuzzy msgid "Use HTTP prox_y" msgstr "_Usar proxy" #: gajim/data/gui/manage_proxies_window.ui:288 #, fuzzy msgid "Proxy _Port:" msgstr "_Porta:" #: gajim/data/gui/manage_proxies_window.ui:299 #, fuzzy msgid "Use proxy auth_entication" msgstr "Usar autenticação" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "Nome de _utilizador" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "_Senha:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Definições" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Guardar senha" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Mudar Senha" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Informações do Contacto" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "Recurso:" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Estado:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Histórico das Conversas" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 #, fuzzy msgid "Contact" msgstr "Contacto:" #: gajim/data/gui/zeroconf_information_window.ui:234 #, fuzzy msgid "First Name:" msgstr "Nome:" #: gajim/data/gui/zeroconf_information_window.ui:247 #, fuzzy msgid "Last Name:" msgstr "Nome:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "Jabber ID:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "E-Mail:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 #, fuzzy msgid "Personal" msgstr "Detalhes Pessoais..." #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "E_nviar Mensagem Privada" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Enviar _Ficheiro" #: gajim/data/gui/gc_occupants_menu.ui:29 #, fuzzy msgid "Occupant Actions" msgstr "Acções de _Ocupantes" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Voz" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Mo_derador" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Membro" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Admin" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "_Dono" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "_Expulsar" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Banir" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "_Adicionar à Lista" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "comando" #: gajim/data/gui/tooltip_roster_contact.ui:125 #, fuzzy msgid "Idle since:" msgstr "Versão %s" #: gajim/data/gui/tooltip_roster_contact.ui:151 #, fuzzy msgid "Mood:" msgstr "Sala:" #: gajim/data/gui/tooltip_roster_contact.ui:164 #, fuzzy msgid "Activity:" msgstr "Activo" #: gajim/data/gui/tooltip_roster_contact.ui:178 #, fuzzy msgid "Tune:" msgstr "Tipo:" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Modificação da Conta" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP: " #: gajim/data/gui/tooltip_roster_contact.ui:281 msgid "Subscription:" msgstr "Subscrição:" #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "E_stado" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Modificar Conta..." #: gajim/data/gui/atom_entry_window.ui:8 #, fuzzy msgid "New entry received" msgstr "Quando um novo evento é recebido" #: gajim/data/gui/atom_entry_window.ui:92 #, fuzzy msgid "Feed name:" msgstr "nome do tema" #: gajim/data/gui/atom_entry_window.ui:119 #, fuzzy msgid "Entry:" msgstr "País:" #: gajim/data/gui/atom_entry_window.ui:131 #, fuzzy msgid "Last modified:" msgstr "Nome:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 #, fuzzy msgid "Change _Nickname..." msgstr "Muda Alcu_nha" #: gajim/data/gui/gc_control_popup_menu.ui:20 #, fuzzy msgid "_Manage Room" msgstr "Gerir Bookmarks" #: gajim/data/gui/gc_control_popup_menu.ui:31 #, fuzzy msgid "Change _Subject..." msgstr "Muda A_ssunto" #: gajim/data/gui/gc_control_popup_menu.ui:38 #, fuzzy msgid "Configure _Room..." msgstr "Configurar _Sala" #: gajim/data/gui/gc_control_popup_menu.ui:52 #, fuzzy msgid "_Destroy Room" msgstr "Descrição: %s" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:85 #, fuzzy msgid "_Request Voice" msgstr "_Voz" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "_Escolher Avatar" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Escolha chave" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 #, fuzzy msgid "Full Name" msgstr "Definições Personalizadas" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Telefone" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Formato: AAAA-MM-DD" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 #, fuzzy msgid "Birthday" msgstr "Aniversário" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Página pessoal:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "E-Mail:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 #, fuzzy msgid "Jabber ID" msgstr "Jabber ID:" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 #, fuzzy msgid "Family" msgstr "Família:" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 #, fuzzy msgid "Given" msgstr "Nome Dado:" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Nome do meio:" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Prefixo:" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Sufixo:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Rua:" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 #, fuzzy msgid "Extra Address" msgstr "Endereço Extra:" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 #, fuzzy msgid "City" msgstr "Cidade:" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Estado:" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 #, fuzzy msgid "Postal Code" msgstr "Código Postal:" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "País:" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 #, fuzzy msgid "Address" msgstr "Formato de uma linha" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Definições Personalizadas" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Empresa:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 #, fuzzy msgid "Department" msgstr "Departamento:" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Cargo:" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Definições" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Trabalho" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Sobre" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "_Continuar" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Pausa" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Cancelar" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Abrir Pasta" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Transferências de Ficheiros" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "lista de transferências de ficheiros" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "Uma lista de transferências de ficheiros activas, completas e paradas" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "_Limpar" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "" "Remove transferências de ficheiros completas, canceladas e falhadas da lista" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Remover a transferência de ficheiro da lista." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "Esta acção remove uma única transferência de ficheiro da lista. Se a " "transferência estiver activa, será primeiro interrompida e depois removida." #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "" "Cancela a transferência de ficheiro seleccionada e remove o ficheiro " "incompleto" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Cancelar transferência de ficheiro" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Cancela a transferência de ficheiro seleccionada" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "E_nviar & Fechar" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Esconde a janela" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Notificar-me quando uma transferência de ficheiro estiver completa" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "" "Quando uma transferência de ficheiro é concluida, exibir um popup de " "notificação" #: gajim/data/gui/filetransfers.ui:229 #, fuzzy msgid "Shows a list of file transfers between you and others" msgstr "" "Mostra uma lista de transferências de ficheiros entre si e outras pessoas" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Negrito" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Itálico" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 #, fuzzy msgid "Underline" msgstr "Sublinhar" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 #, fuzzy msgid "Strike" msgstr "Serviço" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 #, fuzzy msgid "Font" msgstr "Letra:" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Informações do Contacto" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Escolher Ficheiro para Enviar" #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Clique para inserir um emoticon (Alt+E)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Evento" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Eventos" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Registos" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Registos" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Registos" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Registos" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Registos" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Registos" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Registos" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Registos" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Registos" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Registos" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Ausente" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "Mostrar _Lista de Contactos" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "_Nunca" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "Apagar MOTD" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "Localização do ficheiro" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Recurso:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Estado" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Cliente:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 #, fuzzy msgid "System" msgstr "Definições Personalizadas" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Nome do Contacto" #: gajim/data/gui/vcard_information_window.ui:240 #, fuzzy msgid "User avatar" msgstr "Definir _Avatar" #: gajim/data/gui/vcard_information_window.ui:255 #, fuzzy msgid "Configured avatar" msgstr "Configurar _Sala" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 #, fuzzy msgid "Ask" msgstr "Perguntar:" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Subscrição:" #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 #, fuzzy msgid "Personal Info" msgstr "Detalhes Pessoais..." #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "Comentários" #: gajim/data/gui/preferences_window.ui:38 msgid "Use default applications" msgstr "" #: gajim/data/gui/preferences_window.ui:41 msgid "Custom" msgstr "Definições Personalizadas" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Estado: " #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 msgid "Composing only" msgstr "" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "" #: gajim/data/gui/preferences_window.ui:89 msgid "Only when pending events" msgstr "" #: gajim/data/gui/preferences_window.ui:103 #, fuzzy msgid "Pop it up" msgstr "_Mostrar a mensagem como pop-up" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "_Notificar-me" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "Mostrar apenas na _lista" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 #, fuzzy msgid "Last state" msgstr "Iconset de _estados padrão:" #: gajim/data/gui/preferences_window.ui:214 #, fuzzy msgid "Display a_vatars of contacts in roster" msgstr "Exibir imagens pessoais (avatars) dos contactos na lista" #: gajim/data/gui/preferences_window.ui:218 #, fuzzy msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Se marcado, Gajim exibirá imagens pessoais (avatars) dos seus contactos na " "lista" #: gajim/data/gui/preferences_window.ui:232 #, fuzzy msgid "Display status _messages of contacts in roster" msgstr "Exibir mensagens de estado dos contactos na lista" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Se marcado, Gajim exibirá as mensagens de estado dos contactos debaixo dos " "nomes de cada um na janela principal" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Exibir imagens pessoais (avatars) dos contactos na lista" #: gajim/data/gui/preferences_window.ui:254 #, fuzzy msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "" "Se marcado, Gajim exibirá imagens pessoais (avatars) dos seus contactos na " "lista" #: gajim/data/gui/preferences_window.ui:275 #, fuzzy msgid "Sort contacts by status" msgstr "Ordenar contactos por estados" #: gajim/data/gui/preferences_window.ui:285 #, fuzzy msgid "in _roster" msgstr "Fora da lista" #: gajim/data/gui/preferences_window.ui:302 #, fuzzy msgid "in _group chats" msgstr "_Entrar num Chat" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "" #: gajim/data/gui/preferences_window.ui:359 msgid "Spell _checker" msgstr "" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "conteúdo da mensagem" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 msgid "_Window behavior" msgstr "" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "Mostrar janela principal ao arranque" #: gajim/data/gui/preferences_window.ui:484 msgid "_Ignore rich content in incoming messages" msgstr "" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Impossível entrar na sala" #: gajim/data/gui/preferences_window.ui:523 #, fuzzy msgid "Chat Appearance" msgstr "Formato de uma linha" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "Quando um novo evento é recebido" #: gajim/data/gui/preferences_window.ui:623 #, fuzzy msgid "Notify me about contacts that sign _in" msgstr "Notificar-me sobre contactos que acabem de se: " #: gajim/data/gui/preferences_window.ui:641 #, fuzzy msgid "Notify me about contacts that sign _out" msgstr "Notificar-me sobre contactos que acabem de se: " #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Gajim o notificará através de um popup no canto inferior direito do ecrã " "sobre os contactos que se desligarem" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" "Permitir popup/notificações quando estou _ausente/indisponível/ocupado/" "invisível" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "" "Permitir popup/notificações quando estou _ausente/indisponível/ocupado/" "invisível" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "_Ícone na bandeja (também conhecido por área de notificação)" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Notificações Visuais" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "Tocar _Sons" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 #, fuzzy msgid "Ma_nage..." msgstr "Gerir..." #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Sons" #: gajim/data/gui/preferences_window.ui:861 #, fuzzy msgid "Notifications" msgstr "Modificação da Conta" #: gajim/data/gui/preferences_window.ui:898 #, fuzzy msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "Gajim pode enviar e receber meta-informação relativa a uma conversa que " "esteja a ter com um contacto " #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "Noti_ficação do estado da conversa:" #: gajim/data/gui/preferences_window.ui:959 #, fuzzy msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim pode enviar e receber meta-informação relativa a uma conversa que " "esteja a ter com um contacto " #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "Noti_ficação do estado da conversa:" #: gajim/data/gui/preferences_window.ui:987 #, fuzzy msgid "Chat state notifications" msgstr "Notificações Visuais" #: gajim/data/gui/preferences_window.ui:1009 #, fuzzy msgid "Personal Events" msgstr "Detalhes Pessoais..." #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "Marcar automaticamente como _ausente depois de:" #: gajim/data/gui/preferences_window.ui:1047 #, fuzzy msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "Se marcado, o Gajim terá também um ícone na área de notificação" #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "Marcar automaticamente como _indisponível depois de:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "minutos" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" #: gajim/data/gui/preferences_window.ui:1166 #, fuzzy msgid "Auto Status" msgstr "Aplicações" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Pedir a mensagem de estado quando eu me: " #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "_Ligar" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "_Desligar" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" #: gajim/data/gui/preferences_window.ui:1291 #, fuzzy msgid "Default Message" msgstr "Mensagem de Estado" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 #, fuzzy msgid "Enabled" msgstr "Activar" #: gajim/data/gui/preferences_window.ui:1332 #, fuzzy msgid "Status Messages" msgstr "Configurar Mensagens de Estado" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Configurar Mensagens de Estado" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "Gajim - %s" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "Iconset de _estados padrão:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Usar iconsets de _transportes" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Se marcado, o Gajim usará ícones de estado específicos a cada protocolo. " "(Por exemplo, um contacto do MSN terá o ícone msn equivalente para o estado " "disponível, ausente, ocupado, etc...)" #: gajim/data/gui/preferences_window.ui:1724 #, fuzzy msgid "_Convert ASCII Emojis" msgstr "Gerir Emoticons" #: gajim/data/gui/preferences_window.ui:1808 #, fuzzy msgid "Style" msgstr "Interrompida" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Aplicações" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Formato de uma linha" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Servidor:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Sons" #: gajim/data/gui/preferences_window.ui:2159 msgid "Audio/Video" msgstr "" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "Cliente de e_mail:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "_Navegador:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "Gestor de ficheiros:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Definições Personalizadas" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Aplicações" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "_Ignorar eventos de contactos que não estão na lista" #: gajim/data/gui/preferences_window.ui:2363 #, fuzzy msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Marque esta opção apenas se alguem que não está na sua lista o estiver a " "spammar/incomodar. Use com precaução, pois isto bloqueia todas as mensagens " "de qualquer contacto que não estiver na sua lista." #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Permitir o envio de informações do _SO " #: gajim/data/gui/preferences_window.ui:2381 #, fuzzy msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "Se marcado, o Gajim juntar-se-á a este chat no arranque" #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Permitir o envio de informações do _SO " #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "Se marcado, o Gajim juntar-se-á a este chat no arranque" #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Permitir o envio de informações do _SO " #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 #, fuzzy msgid "_Manage..." msgstr "Gerir..." #: gajim/data/gui/preferences_window.ui:2500 #, fuzzy msgid "Privacy" msgstr "Propriedades" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "_Arquivar mudanças de estado dos contactos" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Diversos" #: gajim/data/gui/preferences_window.ui:2584 #, fuzzy msgid "_Open..." msgstr "Abrir..." #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Editor de Configuração Avançada" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Iniciar _Conversa" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 #, fuzzy msgid "Send Single _Message..." msgstr "Enviar _Mensagem Simples" #: gajim/data/gui/contact_context_menu.ui:28 #, fuzzy msgid "Send _File..." msgstr "Enviar _Ficheiro" #: gajim/data/gui/contact_context_menu.ui:44 #, fuzzy msgid "Invite _Contacts" msgstr "Contacto:" #: gajim/data/gui/contact_context_menu.ui:73 #, fuzzy msgid "E_xecute Command..." msgstr "comando" #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "Contacto:" #: gajim/data/gui/contact_context_menu.ui:92 #, fuzzy msgid "_Rename..." msgstr "_Renomear" #: gajim/data/gui/contact_context_menu.ui:99 #, fuzzy msgid "Edit _Groups..." msgstr "Editar _Grupos" #: gajim/data/gui/contact_context_menu.ui:106 #, fuzzy msgid "Assign Open_PGP Key..." msgstr "Atribuir chave OpenPGP" #: gajim/data/gui/contact_context_menu.ui:115 #, fuzzy msgid "Add Special _Notification..." msgstr "Notificações Visuais" #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Subscrição" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "Permitir que ele/ela veja o meu estado" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "Pedir para ver o estado dele/dela" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "Proibí-lo /-la de ver o meu estado" #: gajim/data/gui/contact_context_menu.ui:182 #, fuzzy msgid "_Unignore" msgstr "_Continuar" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "" #: gajim/data/gui/contact_context_menu.ui:197 #, fuzzy msgid "_Add to Roster..." msgstr "_Adicionar à Lista" #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim: Criação Passo-a-passo de uma Conta" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Necessita de uma conta para se poder ligar\n" "à rede Jabber." #: gajim/data/gui/account_creation_wizard_window.ui:95 #, fuzzy msgid "I already have an account I want to _use" msgstr "Já tenho uma conta e quero usá-la" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "Quero _registar uma nova conta" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Por favor escolha uma das opções abaixo:" #: gajim/data/gui/account_creation_wizard_window.ui:167 msgid "Please fill in the data for your existing account" msgstr "Por favor preencha os dados para a sua conta existente" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "_Jabber ID:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 #, fuzzy msgid "Anon_ymous authentication" msgstr "Usar autenticação" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Senha:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Guardar _senha" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Se marcado, o Gajim lembrar-se-á da senha para esta conta" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Servidor:" #: gajim/data/gui/account_creation_wizard_window.ui:423 #, fuzzy msgid "Prox_y:" msgstr "Proxy:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Gerir..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Usar hostname/porta personalizados" #: gajim/data/gui/account_creation_wizard_window.ui:491 #, fuzzy msgid "_Hostname:" msgstr "Nome do Host:" #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Porta:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "Avançado" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" #: gajim/data/gui/account_creation_wizard_window.ui:687 #, fuzzy msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Conta está a ser criada\n" "\n" "Por favor, aguarde..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Ligar quando eu premir Concluir" #: gajim/data/gui/account_creation_wizard_window.ui:789 #, fuzzy msgid "Set my profile when I connect" msgstr "Definir uma imagem pessoal (avatar) quando me ligo" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Terminar" #: gajim/data/gui/privacy_lists_window.ui:34 #, fuzzy msgid "Privacy Lists:" msgstr "Iniciar Conversa" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Endereço:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "_Ir" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 #, fuzzy msgid "Select the contacts you want to synchronise" msgstr "JID do contacto com quem deseja conversar" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Editar Grupos" #: gajim/data/gui/search_window.ui:42 #, fuzzy msgid "Please wait while retrieving search form..." msgstr "" "Por favor, aguarde enquanto que a migração dos seus registos de conversas é " "feita " #: gajim/data/gui/search_window.ui:80 #, fuzzy msgid "_Add contact" msgstr "Adicionar _Contacto" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "_Pesquisar" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "mensagem de estado:" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Activo" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 #, fuzzy msgid "_Type your new status message" msgstr "Escreva a sua nova mensagem de estado" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 #, fuzzy msgid "Synchronise contacts" msgstr "Mostrar Contactos _Offline" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "_Jabber ID:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "_Alcunha:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "Grupo:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "Conta:" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "Protocolo:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "Permitir que ele/ela veja o meu estado" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "_Subscrição" #: gajim/data/gui/add_new_contact_window.ui:367 msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" #: gajim/data/gui/add_new_contact_window.ui:382 #, fuzzy msgid "_Register" msgstr "Re_gistar" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "_Mudar Mensagem de Estado" #: gajim/data/gui/change_mood_dialog.ui:73 #, fuzzy msgid "Mood:" msgstr "Registos" #: gajim/data/gui/change_mood_dialog.ui:85 #, fuzzy msgid "Message:" msgstr "Registos" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Interrompida" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Publicação vCard falhou" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Publicação vCard falhou" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Descrição" #: gajim/data/gui/plugins_window.ui:258 msgid "Version" msgstr "" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "_Autorizar" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 #, fuzzy msgid "Installed" msgstr "Interrompida" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "Nenhum" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "Ambos" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "De" #: gajim/data/gui/privacy_list_window.ui:27 msgid "to" msgstr "" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "" #: gajim/data/gui/privacy_list_window.ui:94 #, fuzzy msgid "Active on each startup" msgstr "_Ligar ao arranque" #: gajim/data/gui/privacy_list_window.ui:132 #, fuzzy msgid "List of rules" msgstr "Formato de uma linha" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Negar" #: gajim/data/gui/privacy_list_window.ui:317 #, fuzzy msgid "JabberID" msgstr "Jabber ID:" #: gajim/data/gui/privacy_list_window.ui:358 #, fuzzy msgid "all in the group" msgstr "Neste grupo" #: gajim/data/gui/privacy_list_window.ui:407 #, fuzzy msgid "all by subscription" msgstr "_Subscrição" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "" #: gajim/data/gui/privacy_list_window.ui:493 #, fuzzy msgid "to send me messages" msgstr "Enviar mensagem" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "" #: gajim/data/gui/privacy_list_window.ui:525 #, fuzzy msgid "to view my status" msgstr "Permitir que ele/ela veja o meu estado" #: gajim/data/gui/privacy_list_window.ui:541 #, fuzzy msgid "to send me status" msgstr "Pedir para ver o estado dele/dela" #: gajim/data/gui/privacy_list_window.ui:557 #, fuzzy msgid "All (including subscription)" msgstr "_Subscrição" #: gajim/data/gui/privacy_list_window.ui:598 #, fuzzy msgid "Order:" msgstr "Servidor:" #: gajim/data/gui/manage_sounds_window.ui:23 #, fuzzy msgid "Manage sounds" msgstr "Gerir Contas" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Activo" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Evento" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Escolher Som" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Remover conta _apenas do Gajim" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Remover conta do Gajim e do _servidor" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "O que pretende fazer?" #: gajim/data/gui/adhoc_commands_window.ui:35 #, fuzzy msgid "Please wait while retrieving command list..." msgstr "" "Por favor, aguarde enquanto que a migração dos seus registos de conversas é " "feita " #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "" "Por favor, aguarde enquanto que a migração dos seus registos de conversas é " "feita " #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "" #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Ocorreu um erro:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Terminar" #: gajim/data/gui/account_context_menu.ui:20 #, fuzzy msgid "_Personal Events" msgstr "Detalhes Pessoais..." #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "_Entrar num Chat" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Adicionar Contacto" #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Descobrir Recursos" #: gajim/data/gui/account_context_menu.ui:65 #, fuzzy msgid "_Execute Command..." msgstr "comando" #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Voz" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Mostrar _Lista de Contactos" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Mostrar Contactos _Offline" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Mostrar Contactos _Offline" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Transportes" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Ajuda" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "_Conteúdo" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_FAQ" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 #, fuzzy msgid "Features" msgstr "Recursos dos Servidores" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "Adicionar esta Sala aos _Bookmarks" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Preferências" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Sair" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Cancelar" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "Chat" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "Adicionar esta Sala aos _Bookmarks" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Servidor:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Senha:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Contacto Entrou" #: gajim/data/gui/manage_bookmarks_window.ui:342 msgid "Minimize on Auto Join" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Enviar mensagem e fechar a janela" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Mensagem de Estado" #: gajim/data/gui/send_file_dialog.ui:43 msgid "Description:" msgstr "Descrição:" #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Evento" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 msgid "Send" msgstr "Enviar" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Ficheiro: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "" "Foi detectado um erro de programação.\n" "Provavelmente não é fatal, mesmo assim deverá ser comunicado\n" " aos programadores" #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Reportar Erro (Bug)" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Iniciar Conversa" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "_Negar" #: gajim/data/gui/subscription_request_window.ui:100 #, fuzzy msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" "Recusar autorização do contacto, para que ele não possa saber quando você " "está ligado" #: gajim/data/gui/subscription_request_window.ui:133 #, fuzzy msgid "Au_thorize" msgstr "_Autorizar" #: gajim/data/gui/subscription_request_window.ui:138 #, fuzzy msgid "Authorize contact so he or she can know when you're connected" msgstr "Autorize o contacto para ele saber quando você está ligado" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "_Presença" #: gajim/data/gui/emoji_chooser.ui:98 msgid "No Results Found" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:39 msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "" "Está neste momento a entrar numa conversa de grupo.\n" "Seleccione os contactos que quer convidar" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "" #: gajim/data/gui/chat_to_muc_window.ui:141 #, fuzzy msgid "MUC server" msgstr "Servidor" #: gajim/data/gui/chat_to_muc_window.ui:176 #, fuzzy msgid "In_vite" msgstr "Invisível" #: gajim/data/gui/history_manager.ui:11 msgid "_Export" msgstr "" #: gajim/data/gui/history_manager.ui:93 msgid "Welcome to Gajim History Logs Manager" msgstr "" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" #: gajim/data/gui/history_manager.ui:222 #, fuzzy msgid "_Search Database" msgstr "_Pesquisar" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "conteúdo da mensagem" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Enviar mensagem" #: gajim/data/gui/shortcuts_window.ui:24 msgid "Add new line" msgstr "" #: gajim/data/gui/shortcuts_window.ui:31 #, fuzzy msgid "Select an emoji" msgstr "Usar _emoticons" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "mensagem de estado:" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "mensagem de estado:" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "Ou escolha uma mensagem pré-definida:" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Enviar mensagem" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Mensagem" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Histórico dos registos" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Evento" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Transferências de Ficheiros" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "_Entrar num Chat" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "mensagem de estado:" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 msgid "Appearance" msgstr "Aparência" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Mostrar Contactos _Offline" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Mostrar Contactos _Offline" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 #, fuzzy msgid "Contacts" msgstr "Contacto:" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Informações do Contacto" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Contacto:" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Contacto:" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Frase de acesso" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "_Arquivar mudanças de estado dos contactos" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Moderador" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Histórico dos registos" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Histórico das Conversas" #: gajim/data/gui/history_window.ui:315 msgid "Chat" msgstr "Conversa" #: gajim/data/gui/history_window.ui:329 msgid "Record history for this chat" msgstr "" #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Histórico dos registos" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Título:" #: gajim/data/gui/manage_pep_services_window.ui:13 #, fuzzy msgid "PEP Service Configuration" msgstr "Configuração da Sala" #: gajim/data/gui/manage_pep_services_window.ui:69 #, fuzzy msgid "_Configure" msgstr "_Continuar" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "De:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Assunto:" #: gajim/data/gui/data_form_window.ui:19 #, fuzzy msgid "Fill in the form." msgstr "Neste grupo" #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Configuração da Sala" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_OK" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "Es_tado" #: gajim/data/gui/systray_context_menu.ui:20 #, fuzzy msgid "_Start Chat..." msgstr "_Iniciar Conversa" #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Mostrar Todos os _Eventos Pedentes" #: gajim/data/gui/systray_context_menu.ui:59 #, fuzzy msgid "Mute Sounds" msgstr "Sons Wav" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Preferências" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Sair" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Para:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "_Enviar" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Enviar mensagem" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Responder" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Responder a esta mensagem" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "E_nviar & Fechar" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Enviar mensagem e fechar a janela" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "" #: gajim/data/gui/change_activity_dialog.ui:337 #, fuzzy msgid "Message: " msgstr "Configurar Mensagens de Estado" #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Argumento em falta \"contacto_jid\"" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Argumento em falta \"contacto_jid\"" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 msgid "Send a message to the contact" msgstr "Enviar uma mensagem ao contacto" #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "%s não encontrado" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "Indisponível" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 msgid "Clear the text window" msgstr "Limpar a janela de texto" #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 #, fuzzy msgid "Send a ping to the contact" msgstr "Uso: /%s, muda a janela de chat para o modo compacto." #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 msgid "Command is not supported for zeroconf accounts" msgstr "" #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 #, fuzzy msgid "No open audio sessions with the contact" msgstr "Clique para ver conversas anteriores com este contacto" #: gajim/command_system/implementation/standard.py:191 #, python-format msgid "%s is not a valid tone" msgstr "" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "Sessão bus não está disponível" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "Sessão bus não está disponível" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Enviar uma mensagem ao contacto" #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Muda Alcu_nha" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 #, fuzzy msgid "Invalid nickname" msgstr "Nome de utilizador inválido" #: gajim/command_system/implementation/standard.py:267 msgid "Open a private chat window with a specified occupant" msgstr "Abrir uma janela de conversação privada com um ocupante específico" #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 msgid "Nickname not found" msgstr "Alcunha não encontrada" #: gajim/command_system/implementation/standard.py:276 msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" "Abrir uma janela de conversação privada com um ocupante específico e enviar-" "lhe uma mensagem" #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, fuzzy, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "%(contact_jid)s foi convidado(a) para %(room_jid)s." #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "_Entrar num Chat" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Está banido/a desta sala." #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Nome de utilizador inválido" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "Filiação: " #: gajim/command_system/implementation/standard.py:365 msgid "Display names of all group chat occupants" msgstr "Mostrar nomes de todos os ocupantes da conversa de grupo" #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Ligação" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Chat" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Adicionar Novo Contacto" #: gajim/gtk/single_message.py:185 #, fuzzy, python-format msgid "Single Message using account %s" msgstr "Mensagem Simples com a conta %s" #: gajim/gtk/single_message.py:187 #, fuzzy, python-format msgid "Single Message in account %s" msgstr "Mensagem Simples com a conta %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Mensagem Simples" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Enviar %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Recebido %s" #: gajim/gtk/single_message.py:238 #, fuzzy, python-format msgid "Form %s" msgstr "De %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "Ligação indisponível" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Por favor, verifique se está ligado com \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "RE: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s escreveu:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "" #: gajim/gtk/pep_config.py:133 #, python-format msgid "Configure %s" msgstr "Configurar %s" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "Re_gistar" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Registo da conta efectuado com sucesso" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "Uma ligação não está disponível" #: gajim/gtk/dialogs.py:83 #, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" #: gajim/gtk/dialogs.py:440 #, fuzzy, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "Tem de criar uma conta antes de poder conversar com outros contactos." #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "Alcunha não encontrada: %s" #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "para conta %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Nome de utilizador inválido" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Mudar Senha" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Deve introduzir uma senha." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "As senhas não conferem" #: gajim/gtk/add_contact.py:30 msgid "GG Number" msgstr "" #: gajim/gtk/add_contact.py:31 msgid "ICQ Number" msgstr "" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Adicionar Contacto" #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s MiB" #: gajim/gtk/add_contact.py:235 #, fuzzy, python-format msgid "You must supply the %s of the new contact." msgstr "Deve indicar uma palavra-passe à qual a nova conta será associada" #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "ID de Utilizador inválido" #: gajim/gtk/add_contact.py:269 #, fuzzy msgid "The user ID must not contain a resource." msgstr "Este serviço não contém quaisquer itens para explorar" #: gajim/gtk/add_contact.py:274 #, fuzzy msgid "You cannot add yourself to your roster." msgstr "Eu gostaria de o adicionar à minha lista" #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Offline" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Contacto já se encontra na lista" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Este contacto já se encontra na sua lista de contactos." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 #, fuzzy msgid "User ID:" msgstr "ID do Utilizador:" #: gajim/gtk/add_contact.py:459 #, fuzzy msgid "Error while adding transport contact" msgstr "erro ao enviar" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 msgid "Chatstate Composing" msgstr "" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Activo" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Contacto Saiu" #: gajim/gtk/themes.py:53 #, fuzzy msgid "MUC Tab New Directed Message" msgstr "Nova Mensagem Privada" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Nova Mensagem" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Conta" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Grupo" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "Mostrar apenas na _lista" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Histórico das Conversas" #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Nome de utilizador inválido" #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Mudar Alcunha" #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "Mensagem recebida:" #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "Mensagem recebida:" #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "Mensagem a enviar:" #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "Mensagem a enviar:" #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Mensagem de Estado" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Mensagem de Estado" #: gajim/gtk/themes.py:145 msgid "URL Color" msgstr "" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "_Destacar palavras mal soletradas" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Mensagem" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "Voltar às Cores Padrão" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Contacto Entrou" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Nome do Contacto" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "Gajim - %s" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Nome de utilizador inválido" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Carácter não permitido" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Activo" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 #, fuzzy msgid "Disk Error" msgstr "Erro:" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s está agora %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, fuzzy, python-format msgid "Error: %s" msgstr "Introduza a sua mensagem :" #: gajim/gtk/history.py:590 #, fuzzy msgid "Error" msgstr "Erro:" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "O estado é agora: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Estado é agora: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "O que pretende fazer?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Ligando" #: gajim/gtk/history_sync.py:252 #, fuzzy, python-format msgid "%(received)s of %(max)s" msgstr "Transferência de %(filename)s de %(name)s interrompida." #: gajim/gtk/history_sync.py:256 #, fuzzy, python-format msgid "Downloaded %s Messages" msgstr "Gajim - %d mensagem não lida" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "Cliente Jabber GTK+" #: gajim/gtk/about.py:48 #, python-format msgid "GTK+ Version: %s" msgstr "" #: gajim/gtk/about.py:49 #, python-format msgid "PyGObject Version: %s" msgstr "" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 msgid "Current Developers" msgstr "" #: gajim/gtk/about.py:54 msgid "Past Developers" msgstr "" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 msgid "we would like to thank all the package maintainers." msgstr "" #: gajim/gtk/about.py:61 msgid "Thanks" msgstr "" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "Miguel Fonseca " #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Escolher Ficheiro para Enviar" #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Escolha chave" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Todos os ficheiros" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Todos os ficheiros" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Enviar Ficheiro" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Imagens" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Escolha chave" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Todos os ficheiros" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Guardar Ficheiro como..." #: gajim/gtk/profile.py:72 msgid "Retrieving profile…" msgstr "" #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Informações do Contacto" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Formato: AAAA-MM-DD" #: gajim/gtk/profile.py:257 #, fuzzy msgid "Information received" msgstr "Convite Recebido" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "" "É necessária uma ligação para poder publicar as suas informações de contacto." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Enviar Ficheiro" #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "Publicação vCard falhou" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "Ocorreu um erro na publicação das suas informações pessoais. Tenta novamente " "mais tarde." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Entrada inválida" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 #, fuzzy msgid "Invalid Nickname" msgstr "Nome de utilizador inválido" #: gajim/gtk/join_groupchat.py:223 msgid "Please choose a nickname" msgstr "" #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "Frase de acesso" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, fuzzy, python-format msgid "%s is not a groupchat server" msgstr "Perguntar antes de fechar uma janela/aba de chat." #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Preferências" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Não está ligado ao servidor" #: gajim/gtk/mam_preferences.py:102 msgid "Error received: {}" msgstr "" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Erro:" #: gajim/gtk/advanced_config.py:86 #, fuzzy msgid "Activated" msgstr "Activo" #: gajim/gtk/advanced_config.py:86 #, fuzzy msgid "Deactivated" msgstr "Activo" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "" #: gajim/gtk/advanced_config.py:89 #, fuzzy msgid "Integer" msgstr "Neste grupo" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Texto" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Nome Preferencial" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Valor" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Tipo" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Nenhum)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Escondida" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "Nome do Host:" #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Recursos dos Servidores" #: gajim/gtk/server_info.py:194 #, fuzzy msgid "Server Uptime" msgstr "Guardado em: %s" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "" #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 #, fuzzy msgid "Command line" msgstr "Comandos: %s" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "" #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "" #: gajim/gtk/features.py:61 #, fuzzy msgid "OpenPGP message encryption" msgstr "Encriptação OpenPGP" #: gajim/gtk/features.py:63 #, fuzzy msgid "Ability to encrypting chat messages with OpenPGP." msgstr "Mensagem recebida:" #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "" #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 #, fuzzy msgid "Password encryption" msgstr "As senhas não conferem" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "" #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "" #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 msgid "Requires Gspell" msgstr "" #: gajim/gtk/features.py:76 #, fuzzy msgid "Automatic status" msgstr "Pedir para ver o estado dele/dela" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "" #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "" #: gajim/gtk/features.py:81 #, fuzzy msgid "RST Generator" msgstr "Geral" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "" #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "" #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 msgid "Requires gir1.2-gupnpigd-1.0." msgstr "" #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "Disponível" #: gajim/gtk/features.py:109 #, fuzzy msgid "Feature" msgstr "Recursos dos Servidores" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "" #: gajim/gtk/privacy_list.py:152 #, fuzzy, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Descrição: %s" #: gajim/gtk/privacy_list.py:208 #, fuzzy msgid "Edit a rule" msgstr "Formato de uma linha" #: gajim/gtk/privacy_list.py:321 #, fuzzy msgid "Add a rule" msgstr "Formato de uma linha" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "" #: gajim/gtk/privacy_list.py:526 #, fuzzy msgid "Invalid List Name" msgstr "Nome de utilizador inválido" #: gajim/gtk/privacy_list.py:527 #, fuzzy msgid "You must enter a name to create a privacy list." msgstr "Deve indicar uma palavra-passe à qual a nova conta será associada" #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "A conta foi adicionada com sucesso" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 #, fuzzy msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Pode ajustar opções de conta avançadas clicando no botão Avançadas, ou mais " "tarde clicando no item de menu Contas dentro do menu Editar a partir da " "janela principal." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "A sua nova conta foi criada com sucesso" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Nome de utilizador inválido" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Deve introduzir um nome de utilizador para configurar esta conta." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 #, fuzzy msgid "Invalid server" msgstr "Nome de utilizador inválido" #: gajim/gtk/account_wizard.py:255 #, fuzzy msgid "Please provide a server on which you want to register." msgstr "Por favor, especifique a nova alcunha a usar:" #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Entrada inválida" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "A porta do proxy deve ser um número de porta" #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 #, fuzzy msgid "An error occurred during account creation" msgstr "Ocorreu um erro ao criar a conta" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Nome de conta em uso" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Já tem uma conta usando este nome." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Filtro:" #: gajim/gtk/xml_console.py:79 #, fuzzy msgid "XML Input" msgstr "Entrada XML" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Ficheiro Inválido" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 #, fuzzy msgid "Default" msgstr "Apagar MOTD" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "título da mensagem de estado" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "texto da mensagem de estado" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "" #: gajim/gtk/accounts.py:224 #, fuzzy, python-format msgid "You have opened chat in account %s" msgstr "Não tem nenhuma conta activa" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Adicionar Contacto" #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "_Remover" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Contas fundidas" #: gajim/gtk/accounts.py:549 msgid "Use PGP Agent" msgstr "" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Ligação" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Contacto:" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Nome de utilizador inválido" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Atribuir chave OpenPGP" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "_Ligar ao arranque" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Religar automaticamente em caso de perda de ligação." #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Guardar _históricos das conversas para todos os contactos" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "E_nviar Mensagem de Servidor" #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Estado: " #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Muda o estado de uma ou várias contas" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Mensagem" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 #, fuzzy msgid "Use file transfer proxies" msgstr "lista de transferências de ficheiros" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "Sessão bus não está disponível" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Proxy:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "Ligação" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Enviar pacotes keep-alive" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "_Prioridade" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Muda o estado de uma ou várias contas" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Nome:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Nome:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "E-Mail" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "Pedir para ver o estado dele/dela" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Activar" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Porta:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Ligação" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Nome de utilizador inválido" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Nome de utilizador inválido" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Guardar senha" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "Gerir Emoticons" #: gajim/gtk/bookmarks.py:72 #, fuzzy msgid "?print_status:All" msgstr "Mostrar hora:" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "" #: gajim/gtk/bookmarks.py:74 #, fuzzy msgid "?print_status:None" msgstr "Mostrar hora:" #: gajim/gtk/bookmarks.py:143 #, fuzzy msgid "New Group Chat" msgstr "Chat" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Este bookmark tem dados inválidos" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "" "Por favor, verifique se preencheu os campos servidor e sala ou remova este " "bookmark" #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 msgid "Character not allowed" msgstr "Carácter não permitido" #: gajim/gtk/bookmarks.py:367 #, fuzzy msgid "Invalid room" msgstr "Entrada inválida" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "Localização do ficheiro" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 msgid "Archive is malformed" msgstr "" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Este ficheiro já existe" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Banindo %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Publicação vCard falhou" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Configuração da Sala" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Cliente de IM Jabber" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "Cliente Jabber GTK+" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Mostrar Todos os _Eventos Pedentes" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Recursos dos Servidores" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 msgid "Automatic spell-checking for your messages" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Buscar Serviço usando conta %s" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "_Arquivar mudanças de estado dos contactos" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Chat" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Histórico dos registos" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Publicação vCard falhou" #~ msgid "Stopped" #~ msgstr "Parada" #~ msgid "Error reading file:" #~ msgstr "Erro na leitura do ficheiro:" #~ msgid "Error parsing file:" #~ msgstr "Erro na interpretação (parsing) do ficheiro:" #, fuzzy #~ msgid "Toggle full / compact view" #~ msgstr "Usar sempre _vista compacta" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Erro na Transferência de Ficheiro" #, fuzzy #~ msgid "XML console interface" #~ msgstr "Consola XML" #, fuzzy #~ msgid "(ESession info)" #~ msgstr "Descrição" #, fuzzy #~ msgid "Save as Preset..." #~ msgstr "Guardar Ficheiro como..." #, fuzzy #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Se marcado, o Gajim trocará smilies ASCII tais como ':)' pelos emoticons " #~ "gráficos equivalentes." #, fuzzy #~ msgid "_Emoticons" #~ msgstr "Gerir Emoticons" #~ msgid "_Highlight misspelled words" #~ msgstr "_Destacar palavras mal soletradas" #, fuzzy #~ msgid "T_heme" #~ msgstr "Tema:" #, fuzzy #~ msgid "Themes" #~ msgstr "Propriedades" #, fuzzy #~ msgid "Presence" #~ msgstr "_Presença" #, fuzzy #~ msgid "Emoticons disabled" #~ msgstr "Encriptação desactivada" #, fuzzy #~ msgid "You cannot make changes to the default theme" #~ msgstr "Não pode apagar o seu tema actual" #~ msgid "theme name" #~ msgstr "nome do tema" #~ msgid "You cannot delete your current theme" #~ msgstr "Não pode apagar o seu tema actual" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Nova Mensagem Única de %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Nova Mensagem Privada da conversa de grupo %s" #, fuzzy #~ msgid "Messaged by %(nickname)s" #~ msgstr "Nova Mensagem como %s" #, fuzzy #~ msgid "Status message text color." #~ msgstr "texto da mensagem de estado" #, fuzzy #~ msgid "Incoming nickname font." #~ msgstr "Nome de utilizador inválido" #, fuzzy #~ msgid "Status message text font." #~ msgstr "texto da mensagem de estado" #~ msgid "green" #~ msgstr "green" #~ msgid "grocery" #~ msgstr "grocery" #~ msgid "human" #~ msgstr "human" #~ msgid "marine" #~ msgstr "marine" #, fuzzy #~ msgid "Contact row" #~ msgstr "Contacto:" #, fuzzy #~ msgid "Chat Banner" #~ msgstr "Faixa:" #~ msgid "Gajim Themes Customization" #~ msgstr "Personalização de Temas do Gajim" #~ msgid "Text _color:" #~ msgstr "_Cor do texto" #~ msgid "_Background:" #~ msgstr "Cor _de fundo" #~ msgid "Text _font:" #~ msgstr "_Letra do texto" #~ msgid "Font style:" #~ msgstr "Estilo da letra:" #~ msgid "Paused" #~ msgstr "Pausada" #, fuzzy #~ msgid "Gone" #~ msgstr "Nenhum" #, fuzzy #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "Mensagem" #, fuzzy #~ msgid "Chat message" #~ msgstr "Mensagem de estado:" #, fuzzy #~ msgid "Font" #~ msgstr "Registos" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Nome do Contacto" #, fuzzy #~ msgid "Contact's message" #~ msgstr "Mensagem de estado:" #, fuzzy #~ msgid "_Status message" #~ msgstr "Mensagem de estado:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Chat" #, fuzzy #~ msgid "Your nickname" #~ msgstr "Antes da alcunha:" #, fuzzy #~ msgid "Your message" #~ msgstr "Introduza a sua mensagem :" #, fuzzy #~ msgid "Chat Line Colors" #~ msgstr "Mudanças na última versão" #, fuzzy #~ msgid "Jabber ID:" #~ msgstr "Jabber ID:" #~ msgid "Resource:" #~ msgstr "Recurso:" #, fuzzy #~ msgid "Status:" #~ msgstr "Definições" #, fuzzy #~ msgid "Client:" #~ msgstr "Definições Personalizadas" #, fuzzy #~ msgid "Contact time:" #~ msgstr "Definições" #, fuzzy #~ msgid "Ask:" #~ msgstr "Aplicações" #, fuzzy #~ msgid "Subscription:" #~ msgstr "Descrição" #, fuzzy #~ msgid "Name:" #~ msgstr "Definições Personalizadas" #~ msgid "Nickname:" #~ msgstr "Alcunha:" #, fuzzy #~ msgid "Street:" #~ msgstr "Definições" #, fuzzy #~ msgid "City:" #~ msgstr "Definições Personalizadas" #, fuzzy #~ msgid "State:" #~ msgstr "Definições" #~ msgid "Extra Address:" #~ msgstr "Endereço Extra:" #~ msgid "Postal Code:" #~ msgstr "Código Postal:" #, fuzzy #~ msgid "Country:" #~ msgstr "Sons" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Página pessoal:" #~ msgid "E-Mail:" #~ msgstr "Correio Electrónico" #~ msgid "Phone No.:" #~ msgstr "N.º Telefone:" #, fuzzy #~ msgid "Birthday:" #~ msgstr "Aniversário" #~ msgid "Family:" #~ msgstr "Família:" #, fuzzy #~ msgid "Middle:" #~ msgstr "Formato de uma linha" #, fuzzy #~ msgid "Prefix:" #~ msgstr "Propriedades" #, fuzzy #~ msgid "Given:" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "Suffix:" #~ msgstr "Sons" #, fuzzy #~ msgid "Full Name" #~ msgstr "Definições Personalizadas" #, fuzzy #~ msgid "Company:" #~ msgstr "Definições Personalizadas" #~ msgid "Department:" #~ msgstr "Departamento:" #, fuzzy #~ msgid "Position:" #~ msgstr "Sons" #, fuzzy #~ msgid "Role:" #~ msgstr "Registos" #~ msgid "Edit %s" #~ msgstr "_Editar %s" #~ msgid "Register to %s" #~ msgstr "Registar para %s" #~ msgid "Conversation History with %s" #~ msgstr "Histórico de Conversas com %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Contacto com \"%s\" não pode ser estabelecido" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "Informação de registo para o transport %s não chegou a tempo" #~ msgid "Register to" #~ msgstr "Registar para" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Nome do Contacto" #, fuzzy #~ msgid "Search:" #~ msgstr "_Pesquisar" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Tem de estar ligado para poder mudar a sua senha." #~ msgid "Invalid password" #~ msgstr "Senha Inválida" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "As senhas introduzidas em ambos os campos devem ser idênticas." #~ msgid "Enter new password:" #~ msgstr "Introduza a nova senha:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Introduza novamente para confirmação" #, fuzzy #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "JID %s não é compatível com RFC. Não será adicionado à sua lista. Utilize " #~ "ferramentas de gestão de lista (roster) tais como http://jru.jabberstudio." #~ "org/ para o remover." #~ msgid "unsubscribe request from %s" #~ msgstr "pedido de remoção de subscrição por %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Entrar automaticamente" #, fuzzy #~ msgid "Homepage:" #~ msgstr "Página pessoal:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Continuar" #~ msgid "Manage Bookmarks" #~ msgstr "Gerir Bookmarks" #~ msgid "_Nickname:" #~ msgstr "_Alcunha:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "Se marcado, o Gajim juntar-se-á a este chat no arranque" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Mostrar hora:" #, fuzzy #~ msgid "Add JID" #~ msgstr "Jabber ID:" #, fuzzy #~ msgid "Preference:" #~ msgstr "Preferências" #, fuzzy #~ msgid "Preference" #~ msgstr "Preferências" #, fuzzy #~ msgid "JID:" #~ msgstr "O seu JID:" #, fuzzy #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "" #~ "Por favor preencha os dados do contacto que deseja adicionar na conta %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Por favor preencha os dados do contacto que deseja adicionar" #, fuzzy #~ msgid "Recently" #~ msgstr "Recentemente:" #~ msgid "Add New Contact" #~ msgstr "Adicionar Novo Contacto" #, fuzzy #~ msgid "_User ID:" #~ msgstr "ID do Utilizador:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "ID do Utilizador:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Alcunha:" #~ msgid "Personal Information" #~ msgstr "Detalhes Pessoais..." #, fuzzy #~ msgid "Avatar:" #~ msgstr "Definir _Avatar" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "_Remover" #, fuzzy #~ msgid "Yahoo! Address:" #~ msgstr "Complemento:" #, fuzzy #~ msgid "Forward unread messages" #~ msgstr "Gajim - %d mensagem não lida" #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "Gajim - %d mensagem não lida" #, fuzzy #~ msgid "AIM Address:" #~ msgstr "_Endereço:" #, fuzzy #~ msgid "MSN Address:" #~ msgstr "_Endereço:" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "Não é possível usar OpenPGP neste computador" #, fuzzy #~ msgid "End to End message encryption" #~ msgstr "Encriptação OpenPGP" #, fuzzy #~ msgid "Encrypting chat messages." #~ msgstr "Mensagem recebida:" #, fuzzy #~ msgid "This session is encrypted" #~ msgstr "[Esta mensagem é encriptada]" #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "Encriptação desactivada" #, fuzzy #~ msgid "Unable to decrypt message" #~ msgstr "Em todas as _mensagens" #~ msgid "_Send" #~ msgstr "E_nviar" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Guardar Ficheiro como..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Fazendo a 'migração' dos logs..." #~ msgid "Choose Image" #~ msgstr "Escolha chave" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Escolher Ficheiro para Enviar" #, fuzzy #~ msgid "Unable to load idle module" #~ msgstr "Impossível entrar na sala" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s é um directório, mas deveria ser um ficheiro" #~ msgid "creating logs database" #~ msgstr "a criar base de dados dos logs" #, fuzzy #~ msgid "creating cache database" #~ msgstr "a criar base de dados dos logs" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Enviar %s" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Gerir Contas" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "Enviar _Mensagem Simples" #, fuzzy #~ msgid "E2E encryption disabled" #~ msgstr "Encriptação desactivada" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Interrompida" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Interrompida" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Publicação vCard falhou" #~ msgid "cyan" #~ msgstr "cyan" #, fuzzy #~ msgid "migrating logs database to indices" #~ msgstr "a criar base de dados dos logs" #, fuzzy #~ msgid "Send File..." #~ msgstr "Enviar _Ficheiro" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Transferências de Ficheiros" #~ msgid "Shows or hides the roster window" #~ msgstr "Mostra ou esconde a janela principal" #, fuzzy #~ msgid "Shows or hides the ipython window" #~ msgstr "Mostra ou esconde a janela principal" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "para conta %s" #, fuzzy #~ msgid "Exception" #~ msgstr "Descrição" #, fuzzy #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "Gostaria de o adicionar à minha lista de contactos." #~ msgid "_Actions" #~ msgstr "_Acções" #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Iniciar Conversa" #, fuzzy #~ msgid "You are already in group chat %s" #~ msgstr "Já está na sala %s" #~ msgid "Join Group Chat with account %s" #~ msgstr "Entrar num Chat com a conta %s" #, fuzzy #~ msgid "Invalid Account" #~ msgstr "Nome de conta inválido" #, fuzzy #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "" #~ "Tem de criar uma conta antes de poder conversar com outros contactos." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "Alcunha não encontrada: %s" #~ msgid "Start Chat with account %s" #~ msgstr "Iniciar conversa com a conta %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Introduza o ID do contacto a quem gostaria\n" #~ "de enviar uma mensagem instantânea:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Jabber ID Inválido" #, fuzzy #~ msgid "Unable to parse \"%s\"." #~ msgstr "Impossível escrever ficheiro em %s" #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "" #~ "Mostra uma caixa de conversa para que possa enviar mensagens a um contacto" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID do contacto com quem deseja conversar" #~ msgid "Adds contact to roster" #~ msgstr "Adiciona o contacto à lista" #, fuzzy #~ msgid "Adds new contact to this account" #~ msgstr "Adiciona um novo contacto nesta conta." #, fuzzy #~ msgid "Starts chat, using this account" #~ msgstr "Iniciar conversa com a conta %s" #, fuzzy #~ msgid "Message content" #~ msgstr "conteúdo da mensagem" #, fuzzy #~ msgid "Join a MUC room" #~ msgstr "_Juntar-se a uma Nova Sala" #, fuzzy #~ msgid "Nickname to use" #~ msgstr "Alcunha não encontrada: %s" #, fuzzy #~ msgid "Password to enter the room" #~ msgstr "As senhas não conferem" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "Frase de acesso" #~ msgid "Nickname:" #~ msgstr "Alcunha:" #~ msgid "Server:" #~ msgstr "Servidor:" #~ msgid "Password:" #~ msgstr "Senha:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Definir uma imagem pessoal (avatar) quando me ligo" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Explorar" #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "_Histórico" #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "_Histórico" #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "A mensagem de estado auto-indisponível" #, fuzzy #~ msgid "This contact does not support file transfer." #~ msgstr "" #~ "Uma lista de transferências de ficheiros activas, completas e paradas" #, fuzzy #~ msgid "Hides the buttons in chat windows." #~ msgstr "Perguntar antes de fechar uma janela/aba de chat." #, fuzzy #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Muda Alcu_nha" #, fuzzy #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "Adicionar esta Sala aos _Bookmarks" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Clique para inserir um emoticon (Alt+E)" #, fuzzy #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Adiciona o contacto à lista" #, fuzzy #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "está a prestar atenção à conversa" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Adiciona o contacto à lista" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Adiciona o contacto à lista" #, fuzzy #~ msgid "Ma_ke message windows compact" #~ msgstr "Enviar mensagem e fechar a janela" #, fuzzy #~ msgid "Hide all buttons in chat windows" #~ msgstr "Perguntar antes de fechar uma janela/aba de chat." #~ msgid "Hide the chat buttons" #~ msgstr "Ocultar os botões da conversa" #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "Se Verdadeiro (True), Gajim perguntará por um avatar a cada contacto que " #~ "não tinha um da última vez ou tenha um na memória cache há demasiado " #~ "tempo." #, fuzzy #~ msgid "?CLI:room" #~ msgstr "De" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "_Expulsar" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "Senha:" #, fuzzy #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "Usar DBus e Notification-Daemon para mostrar notificações" #, fuzzy #~ msgid "Notification" #~ msgstr "Modificação da Conta" #, fuzzy #~ msgid "Ignore" #~ msgstr "_Continuar" #, fuzzy #~ msgid "_Open Gmail Inbox" #~ msgstr "_Abrir Compositor de Email" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Se marcado, Gajim exibirá imagens pessoais (avatars) dos seus contactos " #~ "na lista" #, fuzzy #~ msgid "GMail Options" #~ msgstr "Aplicações" #, fuzzy #~ msgid "20" #~ msgstr "0" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Enviar %s" #, fuzzy #~ msgid "GMail Email Received" #~ msgstr "Convite Recebido" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "Tem mensagens não lidas" #~ msgstr[1] "Tem mensagens não lidas" #~ msgid "Re_name" #~ msgstr "Re_nomear" #, fuzzy #~ msgid "Resour_ce:" #~ msgstr "Re_curso: " #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "O recurso é enviado ao servidor jabber para separar o mesmo JID em duas " #~ "ou mais partes dependentemente do número de clientes ligados ao mesmo " #~ "servidor com as mesma conta. Por exemplo, pode estar ligado à mesma conta " #~ "com os recursos 'Casa' e 'Trabalho' ao mesmo tempo. O recurso com a maior " #~ "prioridade receberá os eventos. (ver em baixo)" #, fuzzy #~ msgid "Anonymous authentication" #~ msgstr "Usar autenticação" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "A prioridade é usada no Jabber para determinar quem recebe os eventos do " #~ "servidor jabber quando dois ou mais clientes estão ligados usando a mesma " #~ "conta; O cliente com a maior prioridade receberá os eventos" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Mostrar Contactos _Offline" #~ msgid "Chan_ge Password" #~ msgstr "Mu_dar Senha" #~ msgid "Click to change account's password" #~ msgstr "Clique para mudar a senha da conta" #, fuzzy #~ msgid "Administration operations" #~ msgstr "_Administrador" #, fuzzy #~ msgid "Browse..." #~ msgstr "_Explorar" #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "[Esta mensagem é encriptada]" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Se marcado, o Gajim, quando iniciado, ligar-se-á automaticamente ao " #~ "jabber usando esta conta" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Mostrar Contactos _Offline" #~ msgid "Synch_ronize account status with global status" #~ msgstr "Sinc_ronizar estado da conta com estado global" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Se marcado, qualquer mudança feita ao estado global (gerido pelo combobox " #~ "no fundo da lista de contactos) alterará também o estado desta conta" #, fuzzy #~ msgid "Proxy" #~ msgstr "Registos" #, fuzzy #~ msgid "Send _keep-alive packets" #~ msgstr "Enviar pacotes keep-alive" #, fuzzy #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Se marcado, o Gajim enviará pacotes keep-alive para evitar timeouts da " #~ "ligação, os quais resultam na perda dessa ligação" #, fuzzy #~ msgid "Use cust_om hostname/port" #~ msgstr "Usar hostname/porta personalizados" #, fuzzy #~ msgid "_Hostname: " #~ msgstr "Nome do Host:" #, fuzzy #~ msgid "_Port: " #~ msgstr "_Porta:" #~ msgid "No key selected" #~ msgstr "Nenhuma chave seleccionada" #~ msgid "Choose _Key..." #~ msgstr "_Escolha chave..." #, fuzzy #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "Se marcado, o Gajim lembrar-se-á da senha para esta conta" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #, fuzzy #~ msgid "_Edit Personal Information..." #~ msgstr "Editar Detalhes Pessoais..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Informações sobre si, tal como estão gravadas no servidor" #~ msgid "Personal Information" #~ msgstr "Detalhes Pessoais" #, fuzzy #~ msgid "Co_nnect on Gajim startup" #~ msgstr "_Ligar ao arranque" #, fuzzy #~ msgid "Synchroni_ze account status with global status" #~ msgstr "Sinc_ronizar estado da conta com estado global" #, fuzzy #~ msgid "Use cust_om port:" #~ msgstr "Usar hostname/porta personalizados" #, fuzzy #~ msgid "Mer_ge accounts" #~ msgstr "_Fundir contas" #, fuzzy #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "Não é possível usar OpenPGP neste computador" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Para mudar o nome da conta, deve estar disconectado." #, fuzzy #~ msgid "To change the account name, you must read all pending events." #~ msgstr "Para mudar o nome da conta, deve estar disconectado." #, fuzzy #~ msgid "Account Name Already Used" #~ msgstr "Nome de conta em uso" #~ msgid "Invalid account name" #~ msgstr "Nome de conta inválido" #~ msgid "Account name cannot be empty." #~ msgstr "Nome da conta não pode ser vazio" #~ msgid "Account name cannot contain spaces." #~ msgstr "Nome da conta não pode conter espaços" #, fuzzy #~ msgid "Enter a new name for account %s" #~ msgstr "Introduza a chave GPG para a conta %s" #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "Um Jabber ID deve estar no formato \"utilizador@nomedoservidor\"." #~ msgid "No such account available" #~ msgstr "Tal conta não está disponível" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "Deve primeiro criar sua conta antes de editar suas informações" #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "" #~ "Sem ligação, não lhe é possível editar as suas informações pessoais." #, fuzzy #~ msgid "Your server can't save your personal information." #~ msgstr "Deve primeiro criar sua conta antes de editar suas informações" #, fuzzy #~ msgid "Account Local already exists." #~ msgstr "Nome de conta em uso" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "Impossível escrever para %s. Session Management não será suportado" #~ msgid "Jabber Traffic" #~ msgstr "Tráfego Jabber" #, fuzzy #~ msgid "_Enable" #~ msgstr "Activar" #, fuzzy #~ msgid "Filter" #~ msgstr "Registos" #~ msgid "_IQ" #~ msgstr "_IC" #~ msgid "Info/Query" #~ msgstr "Info/Consulta" #~ msgid "_Message" #~ msgstr "_Mensagem" #~ msgid "XML Input" #~ msgstr "Entrada XML" #~ msgid "XML Console for %s" #~ msgstr "Consola XML para %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "Consola XML para %s" #, fuzzy #~ msgid "Last status: %s" #~ msgstr "Iconset de _estados padrão:" #, fuzzy #~ msgid " since %s" #~ msgstr "Versão %s" #, fuzzy #~ msgid "since %s" #~ msgstr "Versão %s" #, fuzzy #~ msgid "No" #~ msgstr "Nenhum" #, fuzzy #~ msgid "Prefer" #~ msgstr "Preferências" #, fuzzy #~ msgid "Auto" #~ msgstr "Entrar automaticamente" #, fuzzy #~ msgid "otr" #~ msgstr "_Host:" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Nome de utilizador inválido" #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "" #~ "Número de minutos que as últimas linhas da conversa anterior devem durar." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "O utilizador será ligado a %s sem OpenPGP." #, fuzzy #~ msgid "The following message was NOT encrypted" #~ msgstr "[Esta mensagem é encriptada]" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Não é possível usar OpenPGP neste computador" #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Activar/Desactivar Encriptação Open_PGP" #, fuzzy #~ msgid "Toggle End to End Encryption" #~ msgstr "Activar/Desactivar Encriptação Open_PGP" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "Encriptação activada" #, fuzzy #~ msgid "The following message was encrypted" #~ msgstr "[Esta mensagem é encriptada]" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Activar/Desactivar Encriptação Open_PGP" #, fuzzy #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Esta mensagem é encriptada]" #, fuzzy #~ msgid "Database cannot be read." #~ msgstr "Nome da conta não pode ser vazio" #, fuzzy #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Enviar mensagem e fechar a janela" #~ msgid "Show _XML Console" #~ msgstr "Mostrar Consola _XML" #, fuzzy #~ msgid "Edit _Privacy Lists..." #~ msgstr "Iniciar Conversa" #~ msgid "_Administrator" #~ msgstr "_Administrador" #, fuzzy #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "" #~ "Envia uma mensagem aos utilizadores ligados ao servidor neste momento" #~ msgid "Sets Message of the Day" #~ msgstr "Define a Mensagem do Dia" #~ msgid "Updates Message of the Day" #~ msgstr "Actualiza a Mensagem do Dia" #~ msgid "Deletes Message of the Day" #~ msgstr "Apaga a Mensagem do Dia" #, fuzzy #~ msgid "Add _Contact..." #~ msgstr "_Adicionar Contacto" #, fuzzy #~ msgid "_Accounts" #~ msgstr "Contas" #, fuzzy #~ msgid "Profile, A_vatar" #~ msgstr "Perfil, Avatar" #~ msgid "File _Transfers" #~ msgstr "_Transferências de Ficheiros" #~ msgid "Help online" #~ msgstr "Ajuda online" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Questões Perguntadas Frequentemente (FAQ) (online)" #, fuzzy #~ msgid "Fea_tures" #~ msgstr "Recursos dos Servidores" #~ msgid "to %s account" #~ msgstr "para conta %s" #~ msgid "using %s account" #~ msgstr "usando conta %s" #, fuzzy #~ msgid "of account %s" #~ msgstr "para conta %s" #~ msgid "for account %s" #~ msgstr "para conta %s" #, fuzzy #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Ao remover este contacto, também remove a autorização. O contacto vê-lo-á " #~ "sempre como offline." #~ msgid "Invalid Jabber ID" #~ msgstr "Jabber ID Inválido" #~ msgid "This file is being used by another process." #~ msgstr "Este ficheiro está a ser usado por outro processo." #~ msgid "pgp key" #~ msgstr "chave pgp" #, fuzzy #~ msgid "" #~ "Sends new single message to a contact in the roster. Both OpenPGP key and " #~ "account are optional. If you want to set only 'account', without 'OpenPGP " #~ "key', just set 'OpenPGP key' to ''." #~ msgstr "" #~ "Envia uma nova mensagem a um contacto da lista. Ambas a chave OpenPGP e a " #~ "conta são opcionais. Se quiser definir apenas 'conta', sem 'chave " #~ "OpenPGP', basta definir 'chave OpenPGP' para ''." #, fuzzy #~ msgid "Please first choose another theme as your current theme." #~ msgstr "Por favor, escolha primeiro outro para o seu tema actual." #~ msgid "Your passphrase is incorrect" #~ msgstr "A sua chave de acesso está incorrecta" #, fuzzy #~ msgid "OpenPGP Passphrase Incorrect" #~ msgstr "A sua chave de acesso está incorrecta" #~ msgid "You successfully received %(filename)s from %(name)s." #~ msgstr "Recebeu com sucesso %(filename)s de %(name)s." #, fuzzy #~ msgid "Set logs directory" #~ msgstr "a criar directório %s" #, fuzzy #~ msgid "Chats" #~ msgstr "Conversa" #, fuzzy #~ msgid "_Manage Bookmarks..." #~ msgstr "Gerir Bookmarks..." #~ msgid "Change Status Message..." #~ msgstr "Mudar Mensagem de Estado..." #~ msgid "_Change Status Message..." #~ msgstr "_Mudar Mensagem de Estado..." #~ msgid "" #~ "You are not interested in the contact's presence, and neither he/she is " #~ "interested in yours" #~ msgstr "" #~ "Não está interessado na presença do contacto, nem ele/ela está na sua" #, fuzzy #~ msgid "Error description..." #~ msgstr "Descrição" #, fuzzy #~ msgid "View contact information (Ctrl+I)" #~ msgstr "está a prestar atenção à conversa" #, fuzzy #~ msgid "Groupchat Histories" #~ msgstr "Chat" #, fuzzy #~ msgid "All Chat Histories" #~ msgstr "Estado: " #~ msgid "More" #~ msgstr "Mais" #~ msgid "creating %s directory" #~ msgstr "a criar directório %s" #, fuzzy #~ msgid "%s is not the name of a group chat." #~ msgstr "Perguntar antes de fechar uma janela/aba de chat." #, fuzzy #~ msgid "Session Management" #~ msgstr "Mensagem" #, fuzzy #~ msgid "Gajim needs X server to run. Quiting..." #~ msgstr "Gajim necesita do Xserver para ser executado. Saindo..." #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above" #~ msgstr "Gajim necessita do PyGTK versão 2.6 ou acima" #, fuzzy #~ msgid "Gajim needs PyGTK 2.22 or above to run. Quiting..." #~ msgstr "" #~ "Gajim necessita do PyGTK versão 2.6 ou acima para ser executado. Saindo..." #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above" #~ msgstr "Gajim necessita do GTK versão 2.6 ou acima" #, fuzzy #~ msgid "Gajim needs GTK 2.22 or above to run. Quiting..." #~ msgstr "" #~ "Gajim necessita do GTK versão 2.6 ou acima para ser executado. Saindo..." #, fuzzy #~ msgid "Gajim needs pywin32 to run" #~ msgstr "Gajim necessita do PySQLite2 para ser executado" #~ msgid "A programming error has been detected" #~ msgstr "Um erro de programação foi detectado" #~ msgid "Details" #~ msgstr "Detalhes" #, fuzzy #~ msgid "Jabber ID: " #~ msgstr "Jabber ID:" #~ msgid "Resource: " #~ msgstr "Recurso: " #~ msgid "Subscription: " #~ msgstr "Subscrição:" #, fuzzy #~ msgid "Mood: " #~ msgstr "Sala:" #, fuzzy #~ msgid "Activity: " #~ msgstr "Activo" #~ msgid "Join _Group Chat..." #~ msgstr "_Entrar num Chat..." #, fuzzy #~ msgid "_Modify Account" #~ msgstr "_Modificar Conta..." #~ msgid "_Group Chat" #~ msgstr "C_hat" #, fuzzy #~ msgid "" #~ "If True, Gajim will check if it's the default jabber client on each " #~ "startup." #~ msgstr "Se Verdadeiro (True), Gajim registará para xmpp:// a cada arranque." #, fuzzy #~ msgid "Gajim is not the default Jabber client" #~ msgstr "Gajim - Um cliente Jabber GTK+" #, fuzzy #~ msgid "Would you like to make Gajim the default Jabber client?" #~ msgstr "Deseja sobre-escrevê-lo?" #, fuzzy #~ msgid "Send Single Message" #~ msgstr "E_nviar Mensagem Simples" #, fuzzy #~ msgid "Actions" #~ msgstr "Aplicações" #, fuzzy #~ msgid "Conditions" #~ msgstr "Sons" #, fuzzy #~ msgid "Advanced Actions" #~ msgstr "Acções A_vançadas" #, fuzzy #~ msgid "Advanced Notifications Control" #~ msgstr "Editor de Configuração Avançada" #, fuzzy #~ msgid "Busy " #~ msgstr "Ocupado" #, fuzzy #~ msgid "Contact Change Status " #~ msgstr "Contacto Saiu" #, fuzzy #~ msgid "File Transfer Started " #~ msgstr "Transferência de Ficheiro Parada" #, fuzzy #~ msgid "Group Chat Message Received " #~ msgstr "Nova Mensagem" #, fuzzy #~ msgid "Launch a command" #~ msgstr "comando" #, fuzzy #~ msgid "Online / Free For Chat" #~ msgstr "Livre para conversar" #, fuzzy #~ msgid "Play a sound" #~ msgstr "Tocar _Sons" #, fuzzy #~ msgid "_Disable auto opening chat window" #~ msgstr "Perguntar antes de fechar uma janela/aba de chat." #, fuzzy #~ msgid "_Open chat window with user" #~ msgstr "Usar uma única janela de conversa com _abas" #, fuzzy #~ msgid "_Show event in roster" #~ msgstr "Mostrar apenas na _lista" #, fuzzy #~ msgid "contact(s)" #~ msgstr "Contacto:" #, fuzzy #~ msgid "for " #~ msgstr "Porta:" #, fuzzy #~ msgid "group(s)" #~ msgstr "Grupo" #, fuzzy #~ msgid "_Allow him/her to see my status" #~ msgstr "Permitir que ele/ela veja o meu estado" #, fuzzy #~ msgid "Descrition:" #~ msgstr "Descrição: %s" #, fuzzy #~ msgid "Advanced..." #~ msgstr "Avançado" #, fuzzy #~ msgid "Display _activity of contacts in roster" #~ msgstr "Exibir imagens pessoais (avatars) dos contactos na lista" #, fuzzy #~ msgid "Display _tunes of contacts in roster" #~ msgstr "Exibir imagens pessoais (avatars) dos contactos na lista" #, fuzzy #~ msgid "Display m_ood of contacts in roster" #~ msgstr "Exibir imagens pessoais (avatars) dos contactos na lista" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the activity of contacts in the roster " #~ "window" #~ msgstr "" #~ "Se marcado, Gajim exibirá imagens pessoais (avatars) dos seus contactos " #~ "na lista" #, fuzzy #~ msgid "" #~ "If checked, Gajim will display the tunes of contacts in the roster window" #~ msgstr "" #~ "Se marcado, Gajim exibirá imagens pessoais (avatars) dos seus contactos " #~ "na lista" #, fuzzy #~ msgid "German" #~ msgstr "Geral" #, fuzzy #~ msgid "Greek" #~ msgstr "green" #, fuzzy #~ msgid "Croatian" #~ msgstr "Morada" #, fuzzy #~ msgid "Italian" #~ msgstr "Itálico" #, fuzzy #~ msgid "Polish" #~ msgstr "_Publicar" #, fuzzy #~ msgid "Serbian" #~ msgstr "Geral" #~ msgid "Check your connection or try again later" #~ msgstr "Verifique a sua ligação ou tente novamente mais tarde" #~ msgid "error: cannot open %s for reading" #~ msgstr "erro: impossível abrir %s para leitura" #, fuzzy #~ msgid "Unable to bind to port %s." #~ msgstr "Impossível entrar na sala" #~ msgid "A GTK+ jabber client" #~ msgstr "Um cliente Jabber GTK+" #, fuzzy #~ msgid "Condition" #~ msgstr "Ligação" #, fuzzy #~ msgid "one of: offline, online, chat, away, xa, dnd, invisible " #~ msgstr "" #~ "um de: offline, disponível, livre para conversar, ausente, indisponível, " #~ "ocupado, invisível" #, fuzzy #~ msgid "" #~ "Returns current status message(the global one unless account is specified)" #~ msgstr "" #~ "Indica o estado actual (o estado global, a não ser que uma conta seja " #~ "especificada)." #, fuzzy #~ msgid "" #~ "Usage: %s %s %s \n" #~ "\t %s" #~ msgstr "" #~ "Uso: %s %s %s \n" #~ "\t" #, fuzzy #~ msgid "" #~ "Too many arguments. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Argumento \"%s\" não está especificado. \n" #~ "Escreva \"%s help %s\" para mais informações" #, fuzzy #~ msgid "" #~ "Argument \"%s\" is not specified. \n" #~ "Type \"%s help %s\" for more info" #~ msgstr "" #~ "Argumento \"%s\" não está especificado. \n" #~ "Escreva \"%s help %s\" para mais informações" #, fuzzy #~ msgid "Subject: %s" #~ msgstr "Assunto: %s\n" #, fuzzy #~ msgid "Mood: %s" #~ msgstr "Sala:" #, fuzzy #~ msgid "Activity: %s" #~ msgstr "Activo" #, fuzzy #~ msgid "_Show event in systray" #~ msgstr "Mostrar apenas na _lista" #, fuzzy #~ msgid "Autodetect on every Gajim startup" #~ msgstr "_Ligar ao arranque" #, fuzzy #~ msgid "Show systray:" #~ msgstr "Mostrar apenas na _lista" #, fuzzy #~ msgid "Nickname not allowed: %s" #~ msgstr "Alcunha não encontrada: %s" #~ msgid "we are now subscribed to %s" #~ msgstr "estamos agora subscritos a %s" #~ msgid "we are now unsubscribed from %s" #~ msgstr "já não estamos subscritos a %s" #~ msgid "Account Modification" #~ msgstr "Modificação da Conta" #~ msgid "" #~ "Check this so Gajim will connect in port 5223 where legacy servers are " #~ "expected to have SSL capabilities. Note that Gajim uses TLS encryption by " #~ "default if broadcasted by the server, and with this option enabled TLS " #~ "will be disabled" #~ msgstr "" #~ "Marque esta opção se quiser que o Gajim se ligue usando a porta 5223, " #~ "onde se espera que servidores específicos possuem capacidades SSL. Note " #~ "que o Gajim usa encriptação TLS por defeito se emitida pelo servidor, e " #~ "que com esta opção marcada o TLS será desactivado." #~ msgid "Edit Personal Information..." #~ msgstr "Editar Detalhes Pessoais..." #~ msgid "Hostname: " #~ msgstr "Nome do Host:" #~ msgid "" #~ "If checked, Gajim will store the password in ~/.gajim/config with 'read' " #~ "permission only for you" #~ msgstr "" #~ "Se marcado, o Gajim guardará a sua senha em ~/.gajim/config com permissão " #~ "de 'leitura' apenas para si" #~ msgid "Port: " #~ msgstr "Porta:" #~ msgid "Save _passphrase (insecure)" #~ msgstr "Guardar _frase de acesso (inseguro)" #~ msgid "Use _SSL (legacy)" #~ msgstr "Usar _SSL (específica)" #, fuzzy #~ msgid "" #~ "Account row\n" #~ "Group row\n" #~ "Contact row\n" #~ "Chat Banner" #~ msgstr "" #~ "Count\n" #~ "Grupo\n" #~ "Contacto\n" #~ "Banner" #, fuzzy #~ msgid "gtk-delete" #~ msgstr "Apagar MOTD" #~ msgid "" #~ "All chat states\n" #~ "Composing only\n" #~ "Disabled" #~ msgstr "" #~ "Todos os estados da conversa\n" #~ "Apenas compondo uma mensagem\n" #~ "Desactivado" #, fuzzy #~ msgid "" #~ "Autodetect on every Gajim startup\n" #~ "Always use GNOME default applications\n" #~ "Always use KDE default applications\n" #~ "Always use Xfce default applications\n" #~ "Custom" #~ msgstr "" #~ "Auto-detectar a cada arranque da aplicação\n" #~ "Usar sempre aplicações GNOME padrão\n" #~ "Usar sempre aplicações KDE padrão\n" #~ "Personalizar" #, fuzzy #~ msgid "gtk-cancel" #~ msgstr "Apagar MOTD" #~ msgid "GTK+ runtime is missing libglade support" #~ msgstr "Falta suporte libglade para o runtime GTK+" #~ msgid "" #~ "Please remove your current GTK+ runtime and install the latest stable " #~ "version from %s" #~ msgstr "" #~ "Por favor remova o seu runtime GTK+ actual e instale a última versão " #~ "estável de %s" #, fuzzy #~ msgid "" #~ "Please make sure that GTK+ and PyGTK have libglade support in your system." #~ msgstr "" #~ "Por favor, certifique-se de que o GTK e o PyGTK têm suporte libglade no " #~ "seu sistema." #~ msgid "Gajim needs PySQLite2 to run" #~ msgstr "Gajim necessita do PySQLite2 para ser executado" #~ msgid "OpenPGP passphrase was not given" #~ msgstr "Palavra-chave do OpenPGP não foi recebida" #~ msgid "" #~ "To continue sending and receiving messages, you will need to reconnect." #~ msgstr "" #~ "Para continuar a enviar e receber mensagens, precisará de se reconectar." #, fuzzy #~ msgid "Add Special _Notification" #~ msgstr "Notificações Visuais" #~ msgid "Assign Open_PGP Key" #~ msgstr "Atribuir chave OpenPGP" #~ msgid "Commands: %s" #~ msgstr "Comandos: %s" #, fuzzy #~ msgid "" #~ "Usage: /%(command)s , sends action to the current group chat. Use " #~ "third person. (e.g. /%(command)s explodes.)" #~ msgstr "" #~ "Uso: /%s , envia uma acção para a sala actual. Utilize a terceira " #~ "pessoa. (Por exemplo, /%s explode.)" #~ msgid "No help info for /%s" #~ msgstr "Não há informações de ajuda para /%s" #~ msgid "Nickname not found: %s" #~ msgstr "Alcunha não encontrada: %s" #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], bans the JID from the group chat. The " #~ "nickname of an occupant may be substituted, but not if it contains \"@\". " #~ "If the JID is currently in the group chat, he/she/it will also be kicked." #~ msgstr "" #~ "Uso: /%s [razão], bane o JID da sala. A alcunha de um " #~ "ocupante pode ser substituida, mas não se conter \"@\". Se o JID estiver " #~ "neste momento na sala, este será também expulso. Não suporta espaços numa " #~ "alcunha." #~ msgid "" #~ "Usage: /%s [reason], closes the current window or tab, displaying reason " #~ "if specified." #~ msgstr "" #~ "Uso: /%s [razão], fecha a janela ou aba actual, exibindo a razão se " #~ "especificada." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], invites JID to the current group chat, " #~ "optionally providing a reason." #~ msgstr "" #~ "Uso: /%s [razão], convida o JID para a sala actual, fornecendo " #~ "opcionalmente uma razão." #~ msgid "" #~ "Usage: /%s @[/nickname], offers to join room@server " #~ "optionally using specified nickname." #~ msgstr "" #~ "Uso: /%s @[/alcunha], convida a juntar-se a " #~ "sala@servidor, usando opcionalmente uma alcunha especificada." #, fuzzy #~ msgid "" #~ "Usage: /%s [reason], removes the occupant specified by " #~ "nickname from the group chat and optionally displays a reason." #~ msgstr "" #~ "Uso: /%s [razão], remove o ocupante especificado pela alcunha " #~ "da sala e opcionalmente exibe uma razão. Não suporta espaços na alcunha." #, fuzzy #~ msgid "" #~ "Usage: /%s [message], opens a private message window and sends " #~ "message to the occupant specified by nickname." #~ msgstr "" #~ "Uso: /%s [mensagem], abre uma janela de mensagem privada e " #~ "envia uma mensagem ao ocupante da sala especificado pela alcunha." #, fuzzy #~ msgid "Usage: /%s , changes your nickname in current group chat." #~ msgstr "Uso: /%s , muda a sua alcunha na sala actual." #, fuzzy #~ msgid "" #~ "Usage: /%s [topic], displays or updates the current group chat topic." #~ msgstr "Uso: /%s [tópico], exibe ou actualiza o tópico da sala actual." #~ msgid "" #~ "Usage: /%s , sends a message without looking for other commands." #~ msgstr "" #~ "Uso: /%s , envia uma mensagem sem procurar por outros comandos." #, fuzzy #~ msgid "" #~ "Usage: /%s , allow to send you messages and private " #~ "messages." #~ msgstr "Uso: /%s , muda a sua alcunha na sala actual." #~ msgid "Click to see features (like MSN, ICQ transports) of jabber servers" #~ msgstr "" #~ "Clique para ver os serviços (tais como transportes MSN e ICQ) dos " #~ "servidores jabber" #~ msgid "Name:" #~ msgstr "Nome:" #~ msgid "_Host:" #~ msgstr "_Host:" #, fuzzy #~ msgid "Show _roster" #~ msgstr "Mostrar _Lista de Contactos" #, fuzzy #~ msgid "Modify Account" #~ msgstr "_Modificar Conta..." #, fuzzy #~ msgid "Gajim account %s" #~ msgstr "para conta %s" #, fuzzy #~ msgid "This account is already configured in Gajim." #~ msgstr "Este contacto já se encontra na sua lista de contactos." #, fuzzy #~ msgid "File transfer stopped by the contact at the other end" #~ msgstr "Transferência de ficheiro parada pelo contacto na outra ponta" #, fuzzy #~ msgid "Generic" #~ msgstr "Geral" #, fuzzy #~ msgid "%s has not broadcast an OpenPGP key, nor has one been assigned" #~ msgstr "%s não emitiu uma chave OpenPGP nem você associou uma" #, fuzzy #~ msgid "No such command: /%s (if you want to send this, prefix it with /say)" #~ msgstr "" #~ "Comando inexistente: /%s (se desejar enviar isto, escreva primeiro /say)" #, fuzzy #~ msgid "" #~ "Usage: /%s , sends action to the current group chat. Use third " #~ "person. (e.g. /%s explodes.)" #~ msgstr "" #~ "Uso: /%s , envia uma acção para a sala actual. Utilize a terceira " #~ "pessoa. (Por exemplo, /%s explode.)" #~ msgid "Please fill in the data for your new account" #~ msgstr "Por favor preencha os dados para a sua nova conta" #, fuzzy #~ msgid "_Retype Password:" #~ msgstr "_Senha:" #~ msgid "" #~ "If you have 2 or more accounts and it is checked, Gajim will list all " #~ "contacts as if you had one account" #~ msgstr "" #~ "Se tem duas ou mais contas e esta opção for marcada, o Gajim listará " #~ "todos os contactos como se tivesse apenas uma conta" #~ msgid "_Compact View Alt+C" #~ msgstr "Vista _Compacta Alt+C" #~ msgid "Click to see past conversation in this room" #~ msgstr "Clique para ver conversas anteriores nesta sala" #~ msgid "Build custom query" #~ msgstr "Build custom query" #~ msgid "Query Builder..." #~ msgstr "Query Builder..." #~ msgid "Invitation Received" #~ msgstr "Convite Recebido" #~ msgid "Format of a line" #~ msgstr "Formato de uma linha" #~ msgid "Interface Customization" #~ msgstr "Personalização da Interface" #, fuzzy #~ msgid "A_fter nickname:" #~ msgstr "Depois da alcunha:" #~ msgid "Also known as iChat style" #~ msgstr "Conhecido também como estilo iChat" #, fuzzy #~ msgid "E_very 5 minutes" #~ msgstr "De 5 em 5 _minutos" #, fuzzy #~ msgid "" #~ "Gajim will automatically show new events by poping up the relative window" #~ msgstr "" #~ "Gajim exibirá automaticamente a nova mensagem recebida numa nova janela " #~ "de conversa ou numa aba numa janela existente" #, fuzzy #~ msgid "" #~ "Gajim will notify you for new events via a popup in the bottom right of " #~ "the screen" #~ msgstr "" #~ "Gajim o notificará a cada nova mensagem através de um popup no canto " #~ "inferior direito do ecrã" #~ msgid "" #~ "Gajim will notify you via a popup window in the bottom right of the " #~ "screen about contacts that just signed in" #~ msgstr "" #~ "Gajim o notificará através de um popup no canto inferior direito do ecrã " #~ "sobre os contactos que se ligarem" #, fuzzy #~ msgid "" #~ "Gajim will only change the icon of the contact that triggered the new " #~ "event" #~ msgstr "Gajim mudará apenas o ícone do contacto que enviou a nova mensagem" #~ msgid "" #~ "If checked, Gajim will remember the roster and chat window positions in " #~ "the screen and the sizes of them next time you run it" #~ msgstr "" #~ "Se marcado, o Gajim lembrar-se-á da posição da janela principal na " #~ "próxima vez que for executado" #, fuzzy #~ msgid "Outgoing Chat state noti_fications:" #~ msgstr "Noti_ficação do estado da conversa:" #~ msgid "Print time:" #~ msgstr "Mostrar hora:" #~ msgid "Save _position and size for roster and chat windows" #~ msgstr "" #~ "Guardar _posição e tamanho das janelas de conversa e lista de contactos" #~ msgid "The auto away status message" #~ msgstr "A mensagem de estado auto-ausente" #, fuzzy #~ msgid "" #~ "When a new event (message, file transfer request etc..) is received, the " #~ "following methods may be used to inform you about it. Please note that " #~ "events about new messages only occur if it is a new message from a " #~ "contact you are not already chatting with" #~ msgstr "" #~ "Quando um novo evento (mensagem, pedido de transferência de ficheiro, " #~ "etc...) é recebido, os métodos seguintes poderão ser usados para o " #~ "informar. NOTA: Eventos de nova mensagem recebida só ocorrem se for uma " #~ "nova mensagem de um contacto com quem ainda não estiver a conversar." #, fuzzy #~ msgid "_Advanced Notifications Control..." #~ msgstr "Editor de Configuração Avançada" #, fuzzy #~ msgid "_After time:" #~ msgstr "Depois da hora:" #, fuzzy #~ msgid "_Before time:" #~ msgstr "Antes da hora:" #~ msgid "_Player:" #~ msgstr "_Tocador de som:" #~ msgid "Address" #~ msgstr "Endereço" #~ msgid "Role:" #~ msgstr "Função:" #~ msgid "_Retrieve" #~ msgstr "_Recuperar" #~ msgid "_Remove from Roster" #~ msgstr "_Remover da Lista" #~ msgid "A_ccounts" #~ msgstr "_Contas" #~ msgid "_Filter:" #~ msgstr "_Filtro:" #~ msgid "OS:" #~ msgstr "SO:" #~ msgid "" #~ "If that is not your language for which you want to highlight misspelled " #~ "words, then please set your $LANG as appropriate. Eg. for French do " #~ "export LANG=fr_FR or export LANG=fr_FR.UTF-8 in ~/.bash_profile or to " #~ "make it global in /etc/profile.\n" #~ "\n" #~ "Highlighting misspelled words feature will not be used" #~ msgstr "" #~ "Se esta não for a língua para a qual quer destacar palavras mal " #~ "soletradas, ajuste, por favor, o seu $LANG como apropriado. Por " #~ "exemplo, para o francês, faça 'export LANG=fr_FR' ou 'export LANG=fr_FR." #~ "UTF-8' em ~/.bash_profile ou, para o fazer globalmente, em /etc/profile.\n" #~ "\n" #~ "A função de destaque de palavras mal soletradas não será usada" #~ msgid "Every %s _minutes" #~ msgstr "Todos os %s _minutos" #~ msgid "You will always see him or her as offline." #~ msgstr "Vê-lo-á sempre como estando offline." #~ msgid "%s is now %s (%s)" #~ msgstr "%s está agora %s (%s)" #, fuzzy #~ msgid "Network Manager support not available" #~ msgstr "Uma ligação não está disponível" #~ msgid "Session Management support not available (missing gnome.ui module)" #~ msgstr "Session Management não é suportado (módulo gnome.ui em falta)" #, fuzzy #~ msgid "Private Chat" #~ msgstr "Iniciar Conversa" #~ msgid "%s is now %s" #~ msgstr "%s está agora %s" #~ msgid "%s does not appear to be a valid JID" #~ msgstr "%s não parece ser um JID válido" #, fuzzy #~ msgid "%s - Gajim" #~ msgstr "Gajim" #~ msgid "Without a connection, you can not get your contact information." #~ msgstr "" #~ "É necessária uma ligação para receber as suas informações de contacto." #, fuzzy #~ msgid "_New group chat" #~ msgstr "Chat" #~ msgid "_Log on" #~ msgstr "_Ligar" #~ msgid "Log _off" #~ msgstr "_Desligar" #~ msgid "Save passphrase" #~ msgstr "Guardar frase de acesso" #, fuzzy #~ msgid "Drop %s in group %s" #~ msgstr "De %s na sala %s" #, fuzzy #~ msgid "Affiliation:" #~ msgstr "Filiação: " #, fuzzy #~ msgid "Hides the buttons in two persons chat window." #~ msgstr "Perguntar antes de fechar uma janela/aba de chat." #~ msgid "Connected to server %s:%s with %s" #~ msgstr "Ligado ao servidor %s:%s com %s" #~ msgid "invisible" #~ msgstr "Invisível" #~ msgid "offline" #~ msgstr "offline" #~ msgid "I'm %s" #~ msgstr "Estou %s" #, fuzzy #~ msgid " %d unread single message" #~ msgid_plural " %d unread single messages" #~ msgstr[0] "Gajim - %d mensagem não lida" #~ msgstr[1] "Gajim - %d mensagens não lidas" #, fuzzy #~ msgid " %d unread group chat message" #~ msgid_plural " %d unread group chat messages" #~ msgstr[0] "Gajim - %d mensagem de chat não lida" #~ msgstr[1] "Gajim - %d mensagens de chat não lidas" #, fuzzy #~ msgid " %d unread private message" #~ msgid_plural " %d unread private messages" #~ msgstr[0] "Gajim - %d mensagem privada não lida" #~ msgstr[1] "Gajim - %d mensagens privadas não lidas" #, fuzzy #~ msgid "Connection to host could not be established" #~ msgstr "Ligação ao peer não pode ser estabelecida." #, fuzzy #~ msgid "_New room" #~ msgstr "Nova Sala" #~ msgid "Role: " #~ msgstr "Função: " #~ msgid "" #~ "Sound to play when any MUC message arrives. (This setting is taken into " #~ "account only if notify_on_all_muc_messages is True)" #~ msgstr "" #~ "Som a tocar quando uma mensagem de chat chegar. (Apenas aplicável se " #~ "notify_on_all_muc_messages estiver definido como Verdadeiro)" #, fuzzy #~ msgid "Away " #~ msgstr "Ausente" #, fuzzy #~ msgid "Down" #~ msgstr "Download" #, fuzzy #~ msgid "List of special notifications settings" #~ msgstr "Notificações Visuais" #, fuzzy #~ msgid "Not Available " #~ msgstr "Indisponível" #~ msgid "Contact _Info" #~ msgstr "_Infos do Contacto" #~ msgid "Jabber" #~ msgstr "Jabber" #, fuzzy #~ msgid "Invalid room or server name" #~ msgstr "Nome de utilizador inválido" #~ msgid "Your personal information has been published successfully." #~ msgstr "As suas informações pessoais foram publicadas com sucesso." #~ msgid "Migrating Logs..." #~ msgstr "Fazendo a 'migração' dos logs..." #~ msgid "Gajim - %d unread message" #~ msgid_plural "Gajim - %d unread messages" #~ msgstr[0] "Gajim - %d mensagem não lida" #~ msgstr[1] "Gajim - %d mensagens não lidas" #, fuzzy #~ msgid "Since %s" #~ msgstr "Tamanho: %s" #~ msgid "Automatically authorize contact" #~ msgstr "Autorizar automaticamente contacto" #~ msgid "_Join New Room..." #~ msgstr "_Juntar-se a uma Nova Sala..." #, fuzzy #~ msgid "Please modify your special notification below" #~ msgstr "Por favor escolha uma das opções abaixo:" #~ msgid "Delete Message of the Day" #~ msgstr "Apagar Mensagem do Dia" #, fuzzy #~ msgid "I want to listen to:" #~ msgstr "%s quer enviar-lhe um ficheiro:" #~ msgid "Send _New Message..." #~ msgstr "Enviar _Nova Mensagem..." #~ msgid "Set Message of the Day" #~ msgstr "Definir a Mensagem do Dia" #~ msgid "Update Message of the Day" #~ msgstr "Actualizar Mensagem do Dia" #~ msgid "_XML Console..." #~ msgstr "Consola _XML..." #~ msgid "Use compact view when you open a chat window" #~ msgstr "Usar vista compacta quando uma janela de conversa é aberta" #~ msgid "Use compact view when you open a group chat window" #~ msgstr "Usar vista compacta quando uma janela de chat é aberta" #~ msgid "%s has sent you a new message." #~ msgstr "%s enviou-lhe uma nova mensagem." #~ msgid "Logs have been successfully migrated to the database." #~ msgstr "A migração dos registos de conversas (logs) deu-se com sucesso." #, fuzzy #~ msgid "Start Chat with Contact" #~ msgstr "Iniciar conversa com a conta %s" #~ msgid "All contacts in this group are offline or have errors" #~ msgstr "Todos os contactos deste grupo estão offline ou têm erros" #~ msgid "Sound" #~ msgstr "Som" #~ msgid "Image" #~ msgstr "Imagem" #~ msgid "To %s" #~ msgstr "Para %s" #~ msgid "You have been invited to the %(room_jid)s room by %(contact_jid)s" #~ msgstr "Foi convidado para a sala %(room_jid)s por %(contact_jid)s" #~ msgid "_Set Image..." #~ msgstr "_Definir Imagem" #~ msgid "Switch to %s" #~ msgstr "Mudar para %s" #~ msgid "using account " #~ msgstr "usando conta " #~ msgid "The filesize of image \"%s\" is too large" #~ msgstr "O tamanho da imagem \"%s\" é muito grande" #~ msgid "The file must not be more than 32 kilobytes." #~ msgstr "O tamanho do ficheiro não deve exceder os 32 kilobytes." #~ msgid "Timeout" #~ msgstr "Timeout" #~ msgid "account: " #~ msgstr "conta: " #~ msgid "If you close this window, you will be disconnected from these rooms." #~ msgstr "Se fechar esta janela, perder-se-á a ligação a estas salas." #~ msgid "Activate/Disable notification for when a file transfer is complete" #~ msgstr "" #~ "Activar/Desactivar notificação para quando uma transferência de ficheiro " #~ "estiver completa" #~ msgid "Removing selected file transfer" #~ msgstr "Removendo transferência de ficheiro seleccionada" #~ msgid "Stoping selected file transfer" #~ msgstr "Parando a transferência de ficheiro seleccionada" #~ msgid "" #~ "If you close this tab and you have history disabled, the message will be " #~ "lost." #~ msgstr "" #~ "Se fechar esta aba e o histórico estiver desactivado, a mensagem será " #~ "perdida." #~ msgid "Cannot remove last group" #~ msgstr "Não é possível remover o último grupo" #~ msgid "At least one contact group must be present." #~ msgstr "Ao menos um grupo do contacto deve estar presente." #~ msgid "" #~ "pysqlite2 (aka python-pysqlite2) dependency is missing. After you install " #~ "pysqlite3, if you want to migrate your logs to the new database, please " #~ "read: http://trac.gajim.org/wiki/MigrateLogToDot9DB Exiting..." #~ msgstr "" #~ "Dependência pysqlite2 (aka python-pysqlite2) em falta. Depois de instalar " #~ "pysqlite3, se quiser migrar os seus logs para a nova base de dados, por " #~ "favor, leia: http://trac.gajim.org/wiki/MigrateLogToDot9DB . Saindo..." #~ msgid "" #~ "Image for emoticon has to be less than or equal to 24 pixels in width and " #~ "24 in height." #~ msgstr "" #~ "Imagem para emoticon tem de ser menor ou igual a 24 pixels em largura e " #~ "24 em altura." #~ msgid "Check for new _version on Gajim startup" #~ msgstr "Procurar por uma nova versão ao arranque" #~ msgid "New version of Gajim available" #~ msgstr "Uma nova versão do Gajim está disponível" #~ msgid "Open Download Page" #~ msgstr "Abrir Página para Download" #, fuzzy #~ msgid "with account " #~ msgstr "conta: " #~ msgid "Chat with" #~ msgstr "Conversa com" #~ msgid "as %s" #~ msgstr "como %s" #~ msgid "as " #~ msgstr "como " #, fuzzy #~ msgid "Send _New Message" #~ msgstr "_Nova Mensagem" #~ msgid "Re_quest Authorization from" #~ msgstr "Pedir Autorização de" #~ msgid "Send Authorization to" #~ msgstr "Enviar Autorização para" #~ msgid "Log presences in _contact's log file" #~ msgstr "Registar as presenças no ficheiro de log do _contacto" #~ msgid "Log presences in an _external file" #~ msgstr "Registar as presenças num ficheiro _externo" #, fuzzy #~ msgid "" #~ "You can set advanced account options by pressing Advanced button,or later " #~ "by clicking in Accounts menuitem under Edit menu from the main window." #~ msgstr "" #~ "Conta foi adicionada com sucesso.\n" #~ "Pode configurar opções avançadas em \"Editar->Contas\" na janela " #~ "principal. " #~ msgid "" #~ "When a new message is received which is not from a contact already in a " #~ "chat window, the three following actions may happen in order for you to " #~ "be informed about it" #~ msgstr "" #~ "Quando uma nova mensagem - cujo remetente não está já numa janela de " #~ "conversa - é recebida, as três seguintes acções podem ocorrer para o " #~ "informar" #~ msgid "_Earliest" #~ msgstr "_Primeiro" #~ msgid "_Latest" #~ msgstr "Ú_ltimo" #~ msgid "%s is now %s: %s" #~ msgstr "%s está agora %s: %s" #~ msgid "" #~ "\n" #~ "\n" #~ "\n" #~ "== Original Message ==\n" #~ "%s" #~ msgstr "" #~ "\n" #~ "\n" #~ "\n" #~ "== Mensagem Original ==\n" #~ "%s" #, fuzzy #~ msgid "" #~ "Your new account has been created successfully.\n" #~ "You can set advanced account options by pressing Advanced button,\n" #~ "or later by clicking in Accounts menuitem under Edit menu from the main " #~ "window." #~ msgstr "" #~ "Conta foi adicionada com sucesso.\n" #~ "Pode configurar opções avançadas em \"Editar->Contas\" na janela " #~ "principal. " #~ msgid "" #~ "Your new account has been created and added to your gajim configuration.\n" #~ "You can set advanced account options using \"Edit->Accounts\" in the main " #~ "window menu." #~ msgstr "" #~ "A sua nova conta foi criada e adicionada às suas configurações do gajim.\n" #~ "Pode configurar opções avançadas em \"Editar->Contas\" na janela " #~ "principal. " #~ msgid "You need to enter a valid server address to add an account." #~ msgstr "" #~ "Deve introduzir um endereço de servidor válido para adicionar uma conta." #~ msgid "Contact names must be of the form \"user@servername\"." #~ msgstr "" #~ "Nomes de contacto devem estar no formato \"utilizador@nomedoservidor\"." #~ msgid "Invalid contact ID" #~ msgstr "ID de contacto inválido" #~ msgid "Contact ID must be of the form \"username@servername\"." #~ msgstr "ID de contacto deve estar no formato \"utilizador@nomedoservidor\"." #~ msgid "The account \"%s\" has been registered with the Jabber server." #~ msgstr "A conta \"%s\" foi registada no servidor Jabber." #~ msgid "theme_name" #~ msgstr "nome_do_tema" #~ msgid "Edit" #~ msgstr "Editar" #~ msgid "Check if you want to register for a new jabber account" #~ msgstr "Marque se quiser registar uma nova conta Jabber" #~ msgid "Click to get contact's extended information" #~ msgstr "Clique para receber informações detalhadas do contacto" #~ msgid "_Compact View" #~ msgstr "Vista _Compacta" #~ msgid "_Refresh" #~ msgstr "_Actualizar" #~ msgid "_Register new account" #~ msgstr "_Registar nova conta" #~ msgid "You just received a new message in room \"%s\"" #~ msgstr "Recebeu uma mensagem na sala \"%s\"" #~ msgid "" #~ "If you close this window and you have history disabled, this message will " #~ "be lost." #~ msgstr "" #~ "Se fechar esta janela e o histórico estiver desactivado, esta mensagem " #~ "será perdida." #~ msgid "New _Room" #~ msgstr "Nova _Sala" #~ msgid "" #~ "If checked, all chat and group chat windows will have the information " #~ "area in the top and the buttons area in the bottom hidden. You can quick " #~ "toggle compact view with Alt+C. NOTE: The last state you leave a window/" #~ "tab is not a permanent one" #~ msgstr "" #~ "Se marcado, todas as janelas de conversa e de chat terão a área de " #~ "informação no topo e área dos botões no fundo escondidas. Pode alternar " #~ "entre as vistas normal e compacta premindo Alt+C. NOTA: A última vista " #~ "com a qual fechar a janela/aba não é permanente." #, fuzzy #~ msgid "Inactivate account" #~ msgstr "Não tem nenhuma conta activa" #, fuzzy #~ msgid "Po_sition:" #~ msgstr "Cargo:" #~ msgid "_Service Discovery" #~ msgstr "_Busca de Serviços" #~ msgid "_Service Discovery..." #~ msgstr "_Busca de Serviços..." #~ msgid "error appeared while processing xmpp:" #~ msgstr "erro ocorreu quando processava xmpp:" #~ msgid "" #~ "Cancels the selected file transfer. If there is an incomplete file, kept " #~ "in the file system it will be removed. This operation is not reversable" #~ msgstr "" #~ "Cancela a transferência de ficheiro seleccionada. Se existir um ficheiro " #~ "incompleto, este será removido. Esta operação é irreversível." #~ msgid "Chan_ge" #~ msgstr "_Mudar" #~ msgid "Gajim - one unread message" #~ msgid_plural "Gajim - %d unread messages" #~ msgstr[0] "Gajim - uma mensagem não lida" #~ msgstr[1] "Gajim - %d mensagens não lidas" #~ msgid "Gajim disconnected you from %s" #~ msgstr "Gajim desligou-o de %s" #~ msgid "" #~ "%s seconds have passed and server did not reply to our keep-alive. If you " #~ "believe such disconnection should not have happened, you can disable " #~ "sending keep-alive packets by modifying this account." #~ msgstr "" #~ "Passaram %s segundos e o servidor não respondeu ao nosso keep-alive. Se " #~ "acredita que tal não deve ter acontecido, pode desactivar o envio de " #~ "pacotes keep-alive modificando esta conta." #~ msgid "error: cannot open %s for reading\n" #~ msgstr "erro: impossível abrir %s para leitura\n" #~ msgid "If you close the window, this message will be lost." #~ msgstr "Se fechar esta janela, esta mensagem será perdida." #~ msgid "Stop file transfer" #~ msgstr "Parar a transferência de ficheiro" #~ msgid "_About" #~ msgstr "_Sobre" #~ msgid "paused" #~ msgstr "pausado" gajim-gajim-1.1.3/po/pt_BR.po000066400000000000000000013262061345766322700157050ustar00rootroot00000000000000# translation of pt_BR.po to Português Brasileiro # Portuguese translations for Gajim package. # Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Gajim package. # junix , 2005. # Gajim , 2007. # Djavan Fagundes , 2009, 2010. # msgid "" msgstr "" "Project-Id-Version: pt_BR\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-04-17 02:05+0000\n" "PO-Revision-Date: 2009-12-31 23:22-0300\n" "Last-Translator: Djavan Fagundes \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Virtaal 0.5.0\n" "X-Poedit-Language: Portuguese\n" "X-Poedit-Country: BRAZIL\n" #: gajim/chat_control_base.py:549 msgid "_Undo" msgstr "_Desfazer" #: gajim/chat_control_base.py:557 gajim/conversation_textview.py:530 msgid "_Clear" msgstr "_Limpar" #: gajim/chat_control_base.py:562 msgid "Paste as quote" msgstr "" #: gajim/chat_control_base.py:1102 msgid "Really send file?" msgstr "Realmente enviar o arquivo?" #: gajim/chat_control_base.py:1103 #, python-format msgid "If you send a file to %s, your real JID will be revealed." msgstr "Se você enviar um arquivo para %s, ele(a) saberá o seu JID real." #: gajim/filetransfers_window.py:97 msgid "File" msgstr "Arquivo" #: gajim/filetransfers_window.py:112 msgid "Time" msgstr "Tempo" #: gajim/filetransfers_window.py:124 msgid "Progress" msgstr "Progresso" #: gajim/filetransfers_window.py:231 gajim/filetransfers_window.py:287 #, python-format msgid "Filename: %s" msgstr "Nome do arquivo: %s" #: gajim/filetransfers_window.py:232 gajim/filetransfers_window.py:440 #, python-format msgid "Size: %s" msgstr "Tamanho: %s" #: gajim/filetransfers_window.py:241 gajim/filetransfers_window.py:251 #: gajim/history_manager.py:527 msgid "You" msgstr "Você" #: gajim/filetransfers_window.py:242 #, python-format msgid "Sender: %s" msgstr "Remetente: %s" #: gajim/filetransfers_window.py:243 gajim/filetransfers_window.py:718 #: gajim/tooltips.py:631 msgid "Recipient: " msgstr "Destinatário: " #: gajim/filetransfers_window.py:254 #, python-format msgid "Saved in: %s" msgstr "Salvo em: %s" #: gajim/filetransfers_window.py:256 gajim/chat_control.py:1497 msgid "File transfer completed" msgstr "Transferência de arquivos completa" #: gajim/filetransfers_window.py:258 gajim/chat_control.py:1501 msgid "Open _Containing Folder" msgstr "Abrir _Pasta do Arquivo" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:278 #: gajim/chat_control.py:1556 msgid "File transfer cancelled" msgstr "Transferência de arquivos cancelada" #: gajim/filetransfers_window.py:271 gajim/filetransfers_window.py:279 #: gajim/chat_control.py:1557 msgid "Connection with peer cannot be established." msgstr "Conexão com o par não pode ser estabelecida." #: gajim/filetransfers_window.py:288 #, python-format msgid "Recipient: %s" msgstr "Conteúdo: %s" #: gajim/filetransfers_window.py:290 #, python-format msgid "Error message: %s" msgstr "Mensagem de erro: %s" #: gajim/filetransfers_window.py:291 gajim/chat_control.py:1553 msgid "File transfer stopped" msgstr "Transferência do arquivo parada" #: gajim/filetransfers_window.py:327 #, python-format msgid "" "The file %(file)s has been received, but it seems to have been damaged along " "the way.\n" "Do you want to download it again?" msgstr "" "O arquivo %(file)s foi recebido, mas parece ter se danificado no caminho.\n" "Deseja baixá-lo novamente?" #: gajim/filetransfers_window.py:341 msgid "Gajim can not read this file" msgstr "Gajim não pode ler este arquivo" #: gajim/filetransfers_window.py:342 msgid "Another process is using this file." msgstr "Outro processo está usando o arquivo." #: gajim/filetransfers_window.py:388 gajim/gtkgui_helpers.py:443 #, python-format msgid "Cannot overwrite existing file \"%s\"" msgstr "Não é possível sobrescrever o arquivo \"%s\"" #: gajim/filetransfers_window.py:389 gajim/gtkgui_helpers.py:444 msgid "" "A file with this name already exists and you do not have permission to " "overwrite it." msgstr "" "Um arquivo com este nome já existe e você não tem permissão para sobrescrevê-" "lo." #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "This file already exists" msgstr "Este arquivo já existe" #: gajim/filetransfers_window.py:405 gajim/gtkgui_helpers.py:448 msgid "What do you want to do?" msgstr "O que você quer fazer?" #: gajim/filetransfers_window.py:416 gajim/gtkgui_helpers.py:454 #, python-format msgid "Directory \"%s\" is not writable" msgstr "O diretório \"%s\" não é gravável" #: gajim/filetransfers_window.py:417 gajim/gtkgui_helpers.py:455 msgid "You do not have permission to create files in this directory." msgstr "Você não tem permissão para criar este diretório." #: gajim/filetransfers_window.py:437 #, python-format msgid "File: %s" msgstr "Arquivo: %s" #: gajim/filetransfers_window.py:443 #, python-format msgid "Type: %s" msgstr "Tipo: %s" #: gajim/filetransfers_window.py:445 #, python-format msgid "Description: %s" msgstr "Descrição: %s" #: gajim/filetransfers_window.py:446 #, python-format msgid "%s wants to send you a file:" msgstr "%s quer te enviar um arquivo:" #: gajim/filetransfers_window.py:487 msgid "Checking file…" msgstr "Checando o arquivo..." #: gajim/filetransfers_window.py:501 msgid "File error" msgstr "Erro no arquivo" #: gajim/filetransfers_window.py:538 #, python-format msgid "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" msgstr "%(hours)02.d:%(minutes)02.d:%(seconds)02.d" #: gajim/filetransfers_window.py:632 #, python-format msgid "(%(filesize_unit)s/s)" msgstr "(%(filesize_unit)s/s)" #: gajim/filetransfers_window.py:685 gajim/filetransfers_window.py:688 msgid "Invalid File" msgstr "Arquivo inválido" #: gajim/filetransfers_window.py:685 msgid "File: " msgstr "Arquivo: " #: gajim/filetransfers_window.py:689 msgid "It is not possible to send empty files" msgstr "Não é possível enviar arquivos vazios" #: gajim/filetransfers_window.py:714 gajim/tooltips.py:622 msgid "Name: " msgstr "Nome: " #: gajim/filetransfers_window.py:716 gajim/tooltips.py:625 msgid "Sender: " msgstr "Remetente: " #: gajim/filetransfers_window.py:844 msgid "Pause" msgstr "Pausa" #: gajim/filetransfers_window.py:855 msgid "_Continue" msgstr "_Continuar" #: gajim/filetransfers_window.py:1019 msgid "Choose a File to Send…" msgstr "Escolha o Arquivo para Enviar..." #: gajim/gtkgui_helpers.py:432 msgid "Extension not supported" msgstr "Extensão não suportada" #: gajim/gtkgui_helpers.py:433 #, python-format msgid "Image cannot be saved in %(type)s format. Save as %(new_filename)s?" msgstr "" "A imagem não pode ser salva no formato %(type)s. Salvar como " "%(new_filename)s?" #: gajim/vcard.py:164 gajim/vcard.py:516 gajim/chat_control.py:587 #: gajim/gtk/profile.py:165 msgid "Save _As" msgstr "Salvar _Como" #: gajim/vcard.py:288 gajim/vcard.py:295 msgid "?Client:Unknown" msgstr "?Cliente:Desconhecido" #: gajim/vcard.py:292 gajim/vcard.py:297 msgid "?OS:Unknown" msgstr "?SO:Desconhecido" #: gajim/vcard.py:326 gajim/vcard.py:329 msgid "?Time:Unknown" msgstr "?Tempo:Desconhecido" #: gajim/vcard.py:380 msgid "?Role in Group Chat:Role:" msgstr "?Cargo no Chat em Grupo:Role:" #: gajim/vcard.py:384 msgid "Affiliation:" msgstr "Afiliação:" #: gajim/vcard.py:391 msgid "" "This contact is interested in your presence information, but you are not " "interested in their presence" msgstr "" "Este contato está interessado em sua informação de presença, mas você não " "está interessado na presença dele/dela" #: gajim/vcard.py:393 msgid "" "You are interested in the contact's presence information, but it is not " "mutual" msgstr "" "Você está interessado na informação da presença do contato, mas ele/ela não " "está interessado na sua" #: gajim/vcard.py:395 msgid "The contact and you want to exchange presence information" msgstr "" "Você e o contato estão interessados na informação da presença de cada um" #: gajim/vcard.py:397 msgid "" "You and the contact have a mutual disinterest in each-others presence " "information" msgstr "" "Você e o contato não estão interessados na informação da presença de cada um" #: gajim/vcard.py:403 msgid "You are waiting contact's answer about your subscription request" msgstr "" "Você está esperando a resposta do contato sobre seu pedido de inscrição" #: gajim/vcard.py:405 msgid "There is no pending subscription request." msgstr "Não há requisições de inscrições pendentes." #: gajim/vcard.py:410 gajim/vcard.py:456 gajim/vcard.py:571 msgid " resource with priority " msgstr " recurso com prioridade " #: gajim/options_dialog.py:393 gajim/config.py:707 gajim/gtk/filechoosers.py:88 #: gajim/gtk/filechoosers.py:136 gajim/gtk/filechoosers.py:143 msgid "All files" msgstr "Todos os arquivos" #: gajim/options_dialog.py:402 gajim/data/gui/manage_sounds_window.ui:109 msgid "Clear File" msgstr "Limpar Arquivo" #: gajim/options_dialog.py:484 msgid "Manage Proxies" msgstr "Gerenciar Perfis de Proxy" #: gajim/options_dialog.py:494 gajim/options_dialog.py:560 #: gajim/options_dialog.py:581 gajim/dialogs.py:320 gajim/dialogs.py:322 #: gajim/dialogs.py:528 gajim/dialogs.py:541 gajim/roster_window.py:3002 #: gajim/roster_window.py:3008 gajim/roster_window.py:3013 gajim/config.py:85 #: gajim/config.py:195 gajim/data/gui/account_creation_wizard_window.ui:22 #: gajim/data/gui/change_mood_dialog.ui:98 gajim/gtk/account_wizard.py:268 #: gajim/gtk/account_wizard.py:347 gajim/gtk/preferences.py:996 #: gajim/gtk/preferences.py:1010 gajim/gtk/preferences.py:1015 msgid "None" msgstr "Nenhum" #: gajim/options_dialog.py:516 msgid "Adjust to Status" msgstr "_Ajustar para Status" #: gajim/options_dialog.py:528 msgid "On" msgstr "Ativado" #: gajim/options_dialog.py:528 msgid "Off" msgstr "Desativado" #: gajim/options_dialog.py:564 msgid "Failed to get secret keys" msgstr "Falha enquanto recebia as chaves secretas" #: gajim/options_dialog.py:565 msgid "There is no OpenPGP secret key available." msgstr "Não há chave secreta OpenPGP disponível." #: gajim/options_dialog.py:570 msgid "OpenPGP Key Selection" msgstr "Seleção de chave OpenPGP" #: gajim/options_dialog.py:570 msgid "Choose your OpenPGP key" msgstr "Escolha sua chave OpenPGP" #: gajim/gui_menu_builder.py:95 msgid "_New Group Chat" msgstr "_Nova conferência" #: gajim/gui_menu_builder.py:286 gajim/gui_menu_builder.py:410 #: gajim/dialogs.py:890 gajim/dialogs.py:919 gajim/dialogs.py:1138 #: gajim/chat_control.py:289 gajim/roster_window.py:827 #: gajim/roster_window.py:1754 gajim/roster_window.py:1756 #: gajim/roster_window.py:2079 gajim/roster_window.py:3424 #: gajim/roster_window.py:3451 gajim/gui_interface.py:515 #: gajim/common/contacts.py:191 gajim/common/contacts.py:318 #: gajim/common/helpers.py:69 gajim/common/helpers.py:294 #: gajim/gtk/add_contact.py:294 msgid "Not in Roster" msgstr "Fora da lista" #: gajim/gui_menu_builder.py:423 msgid "I would like to add you to my roster" msgstr "Eu gostaria de adiciona-lo à minha lista" #: gajim/gui_menu_builder.py:502 msgid "Send Single _Message…" msgstr "Enviar Uma _Mensagem…" #: gajim/gui_menu_builder.py:515 gajim/roster_window.py:5155 #: gajim/data/gui/contact_context_menu.ui:58 msgid "Send Cus_tom Status" msgstr "Enviar status perso_nalizado" #: gajim/gui_menu_builder.py:535 msgid "E_xecute Command…" msgstr "E_xecutar Comando..." #: gajim/gui_menu_builder.py:543 msgid "_Manage Transport" msgstr "_Gerenciar transporte" #: gajim/gui_menu_builder.py:549 msgid "_Modify Transport" msgstr "_Modificar transporte" #: gajim/gui_menu_builder.py:556 gajim/roster_window.py:5183 msgid "_Rename…" msgstr "_Renomear..." #: gajim/gui_menu_builder.py:567 gajim/roster_window.py:5199 #: gajim/roster_window.py:5314 gajim/data/gui/blocked_contacts_window.ui:52 #: gajim/data/gui/gc_occupants_menu.ui:148 #: gajim/data/gui/contact_context_menu.ui:166 msgid "_Unblock" msgstr "_Desbloquear" #: gajim/gui_menu_builder.py:570 gajim/roster_window.py:5204 #: gajim/roster_window.py:5318 gajim/data/gui/gc_occupants_menu.ui:140 #: gajim/data/gui/contact_context_menu.ui:174 msgid "_Block" msgstr "_Bloquear" #: gajim/gui_menu_builder.py:578 gajim/roster_window.py:5211 #: gajim/data/gui/contact_context_menu.ui:204 msgid "Remo_ve" msgstr "Remo_ver" #: gajim/gui_menu_builder.py:588 gajim/data/gui/contact_context_menu.ui:221 #: gajim/data/gui/search_window.ui:98 msgid "_Information" msgstr "_Informações" #: gajim/gui_menu_builder.py:601 gajim/groupchat_control.py:640 #: gajim/chat_control.py:326 msgid "Send File…" msgstr "Enviar Arquivo..." #: gajim/gui_menu_builder.py:602 msgid "Upload File…" msgstr "Enviar Arquivo..." #: gajim/gui_menu_builder.py:603 msgid "Send File Directly…" msgstr "Enviar Arquivo Diretamente..." #: gajim/gui_menu_builder.py:605 msgid "Invite Contacts" msgstr "Convidar Contatos" #: gajim/gui_menu_builder.py:606 msgid "Add to Roster" msgstr "Adicionar à Lista de contatos" #: gajim/gui_menu_builder.py:607 msgid "Audio Session" msgstr "Sessão de Áudio" #: gajim/gui_menu_builder.py:608 msgid "Video Session" msgstr "Sessão de Vídeo" #: gajim/gui_menu_builder.py:609 msgid "Information" msgstr "Informações" #: gajim/gui_menu_builder.py:610 gajim/gui_menu_builder.py:647 #: gajim/data/gui/application_menu.ui:37 msgid "History" msgstr "Histórico" #: gajim/gui_menu_builder.py:634 msgid "Manage Room" msgstr "Gerenciar Sala" #: gajim/gui_menu_builder.py:635 msgid "Change Subject" msgstr "Alterar Assunto" #: gajim/gui_menu_builder.py:636 msgid "Configure Room" msgstr "Configurar Sala" #: gajim/gui_menu_builder.py:637 msgid "Upload Avatar…" msgstr "Enviar Avatar..." #: gajim/gui_menu_builder.py:638 msgid "Destroy Room" msgstr "Excluir Sala" #: gajim/gui_menu_builder.py:640 msgid "Sync Threshold" msgstr "Limiar de Sincronização" #: gajim/gui_menu_builder.py:641 msgid "Change Nick" msgstr "Alterar Apelido" #: gajim/gui_menu_builder.py:642 msgid "Bookmark Room" msgstr "Adicionar Sala aos Marcadores" #: gajim/gui_menu_builder.py:643 msgid "Request Voice" msgstr "Solicitar Voz" #: gajim/gui_menu_builder.py:644 gajim/data/gui/gc_control_popup_menu.ui:72 msgid "Notify on all messages" msgstr "Notificar em todas mensagens" #: gajim/gui_menu_builder.py:645 msgid "Minimize on close" msgstr "Minimizar ao fechar" #: gajim/gui_menu_builder.py:646 gajim/roster_window.py:5383 msgid "Execute command" msgstr "Executar comando" #: gajim/gui_menu_builder.py:648 msgid "Disconnect" msgstr "Desconectar" #: gajim/gui_menu_builder.py:678 msgid "No threshold" msgstr "Sem limiar" #: gajim/gui_menu_builder.py:680 #, python-format msgid "%i day" msgid_plural "%i days" msgstr[0] "%i dia" msgstr[1] "%i dias" #: gajim/gui_menu_builder.py:695 gajim/gui_menu_builder.py:735 #: gajim/gtk/join_groupchat.py:38 msgid "Join Group Chat" msgstr "Ingressar numa conferência" #: gajim/gui_menu_builder.py:734 msgid "Add Contact…" msgstr "Adicionar Contato..." #: gajim/gui_menu_builder.py:736 gajim/gtk/profile.py:50 #: gajim/gtk/accounts.py:572 gajim/gtk/accounts.py:671 #: gajim/gtk/accounts.py:711 msgid "Profile" msgstr "Perfil" #: gajim/gui_menu_builder.py:737 msgid "Discover Services" msgstr "Descobrir Serviços" #: gajim/gui_menu_builder.py:738 msgid "Send Single Message…" msgstr "Enviar Uma Única Mensagem..." #: gajim/gui_menu_builder.py:739 gajim/data/gui/preferences_window.ui:2620 msgid "Advanced" msgstr "Avançado" #: gajim/gui_menu_builder.py:740 msgid "Archiving Preferences" msgstr "Preferências de Arquivamento" #: gajim/gui_menu_builder.py:741 msgid "Synchronise History" msgstr "Sincronizar História" #: gajim/gui_menu_builder.py:742 gajim/gtk/privacy_list.py:427 msgid "Privacy Lists" msgstr "Listas de privacidade" #: gajim/gui_menu_builder.py:743 gajim/gtk/server_info.py:32 msgid "Server Info" msgstr "Informações do Servidor" #: gajim/gui_menu_builder.py:744 gajim/gui_menu_builder.py:755 #: gajim/data/gui/xml_console_window.ui:77 msgid "XML Console" msgstr "Console XML" #: gajim/gui_menu_builder.py:746 msgid "Admin" msgstr "Administração" #: gajim/gui_menu_builder.py:747 msgid "Send Server Message…" msgstr "Enviar Mensagem de Servidor..." #: gajim/gui_menu_builder.py:748 msgid "Set MOTD…" msgstr "Definir MOTD..." #: gajim/gui_menu_builder.py:749 msgid "Update MOTD…" msgstr "Atualizar MOTD..." #: gajim/gui_menu_builder.py:750 msgid "Delete MOTD…" msgstr "Excluir MOTD..." #: gajim/gui_menu_builder.py:799 msgid "No Accounts available" msgstr "Nenhuma Conta disponível" #: gajim/gui_menu_builder.py:810 gajim/data/gui/application_menu.ui:5 #: gajim/data/gui/application_menu.ui:71 gajim/data/gui/shortcuts_window.ui:168 #: gajim/gtk/accounts.py:52 msgid "Accounts" msgstr "Contas" #: gajim/gui_menu_builder.py:868 gajim/gui_menu_builder.py:873 msgid "Copy JID" msgstr "Copiar JID" #: gajim/gui_menu_builder.py:869 gajim/gui_menu_builder.py:895 msgid "Join Groupchat" msgstr "Entrar em um grupo de chat" #: gajim/gui_menu_builder.py:874 gajim/gui_menu_builder.py:894 #: gajim/data/gui/application_menu.ui:76 msgid "Start Chat" msgstr "Iniciar conversa" #: gajim/gui_menu_builder.py:875 gajim/gui_menu_builder.py:896 msgid "Add to Roster…" msgstr "Adicionar à Lista de Contatos..." #: gajim/gui_menu_builder.py:880 msgid "Copy Link Location" msgstr "Copiar Endereço" #: gajim/gui_menu_builder.py:881 msgid "Open Link in Browser" msgstr "Abrir no Navegador" #: gajim/gui_menu_builder.py:886 msgid "Copy Email Address" msgstr "Copiar Endereço de E-mail" #: gajim/gui_menu_builder.py:887 gajim/gui_menu_builder.py:893 msgid "Open Email Composer" msgstr "Abrir Cliente de E-mail" #: gajim/gui_menu_builder.py:892 msgid "Copy JID/Email" msgstr "Copiar JID/E-mail" #: gajim/history_manager.py:71 msgid "Usage:" msgstr "Uso:" #: gajim/history_manager.py:73 msgid "Options:" msgstr "Opções:" #: gajim/history_manager.py:75 msgid "Show this help message and exit" msgstr "Mostrar essa mensagem de ajuda e sair" #: gajim/history_manager.py:76 msgid "Choose folder for logfile" msgstr "Escolher pasta para arquivo de registros" #: gajim/history_manager.py:115 msgid "Cannot find history logs database" msgstr "Não foi encontrado banco de dados do histórico de logs" #: gajim/history_manager.py:156 gajim/history_manager.py:207 #: gajim/dialogs.py:1119 gajim/config.py:425 gajim/disco.py:817 msgid "JID" msgstr "JID" #: gajim/history_manager.py:169 gajim/history_manager.py:213 #: gajim/data/gui/history_window.ui:89 gajim/gtk/history.py:113 msgid "Date" msgstr "Data:" #: gajim/history_manager.py:176 gajim/history_manager.py:232 #: gajim/data/gui/join_groupchat_window.ui:208 #: gajim/data/gui/profile_window.ui:214 #: gajim/data/gui/vcard_information_window.ui:443 msgid "Nickname" msgstr "Apelido" #: gajim/history_manager.py:185 gajim/history_manager.py:220 #: gajim/gtk/history.py:122 msgid "Message" msgstr "Mensagem" #: gajim/history_manager.py:193 gajim/history_manager.py:226 msgid "Subject" msgstr "Assunto" #: gajim/history_manager.py:255 msgid "" "Do you want to clean up the database? (STRONGLY NOT RECOMMENDED IF GAJIM IS " "RUNNING)" msgstr "" "Você quer limpar o banco de dados? (ALTAMENTE NÃO RECOMENDADO COM O GAJIM EM " "EXECUÇÃO)" #: gajim/history_manager.py:257 msgid "" "Normally allocated database size will not be freed, it will just become " "reusable. If you really want to reduce database filesize, click YES, else " "click NO.\n" "\n" "In case you click YES, please wait…" msgstr "" "Normalmente, o tamanho alocado da base de dados não será liberado, ele se " "tornará apenas reusável. Se você quiser realmente reduzir o tamanho do " "arquivo da base de dados, clique SIM, senão clique NÃO.\n" "\n" "Se caso você clicar no SIM, por favor aguarde..." #: gajim/history_manager.py:262 msgid "Database Cleanup" msgstr "Limpeza da Base de Dados" #: gajim/history_manager.py:539 #, python-format msgid "%(who)s on %(time)s said: %(message)s\n" msgstr "%(who)s em %(time)s disse: %(message)s\n" #: gajim/history_manager.py:577 #, python-format msgid "Do you wish to delete all correspondence with %(jid)s?" msgstr "Você quer excluir todas as correspondências com %(jid)s?" #: gajim/history_manager.py:581 msgid "Do you wish to delete all correspondence with the selected contacts?" msgstr "" "Você realmente quer excluir os registros de mensagens do contato selecionado?" #: gajim/history_manager.py:583 msgid "This can not be undone." msgstr "Isso não pode ser desfeito." #: gajim/history_manager.py:585 gajim/history_manager.py:624 msgid "Deletion Confirmation" msgstr "Confirmação de Deleção" #: gajim/history_manager.py:619 msgid "Do you really want to delete the selected message?" msgid_plural "Do you really want to delete the selected messages?" msgstr[0] "Você realmente quer excluir a mensagem selecionada?" msgstr[1] "Você realmente quer excluir as mensagens selecionadas?" #: gajim/history_manager.py:622 msgid "This is an irreversible operation." msgstr "Esta é uma operação irreversível." #: gajim/dialogs.py:82 #, python-format msgid "Contact name: %s" msgstr "Nome do contato: %s" #: gajim/dialogs.py:84 #, python-format msgid "JID: %s" msgstr "JID: %s" #: gajim/dialogs.py:114 gajim/dialogs.py:127 gajim/roster_window.py:2944 #: gajim/roster_window.py:3951 gajim/roster_window.py:5221 #: gajim/common/contacts.py:141 gajim/common/contacts.py:175 #: gajim/data/gui/preferences_window.ui:540 #: gajim/data/gui/shortcuts_window.ui:163 gajim/gtk/accounts.py:575 msgid "General" msgstr "Geral" #: gajim/dialogs.py:200 msgid "Group" msgstr "Grupo" #: gajim/dialogs.py:207 msgid "In the group" msgstr "Neste grupo" #: gajim/dialogs.py:302 msgid "KeyID" msgstr "KeyID" #: gajim/dialogs.py:307 msgid "Contact name" msgstr "Nome do contato" #: gajim/dialogs.py:483 msgid "Set Mood" msgstr "Definir humor" #: gajim/dialogs.py:603 #, python-format msgid "%s Status Message" msgstr "%s mensagem de status" #: gajim/dialogs.py:617 msgid "Status Message" msgstr "Mensagem de status" #: gajim/dialogs.py:807 msgid "Overwrite Status Message?" msgstr "Sobrescrever mensagem de status?" #: gajim/dialogs.py:808 msgid "" "This name is already used. Do you want to overwrite this status message?" msgstr "" "Este nome já está sendo usado. Você quer sobrescrever essa mensagem de " "status?" #: gajim/dialogs.py:816 msgid "Save as Preset Status Message" msgstr "Salvar como a mensagem de status pré-configurada" #: gajim/dialogs.py:817 msgid "Please type a name for this status message" msgstr "Por favor, escreva um nome para esta mensagem de status" #: gajim/dialogs.py:848 msgid "Subscription Request" msgstr "Solicitação de inscrição" #: gajim/dialogs.py:857 #, python-format msgid "Subscription request for account %(account)s from %(jid)s" msgstr "Solicitação de inscrição para conta %(account)s de %(jid)s" #: gajim/dialogs.py:860 #, python-format msgid "Subscription request from %s" msgstr "Solicitação de inscrição de %s" #: gajim/dialogs.py:927 gajim/disco.py:503 gajim/gui_interface.py:1757 #: gajim/dialog_messages.py:31 gajim/gtk/profile.py:332 #: gajim/gtk/join_groupchat.py:234 msgid "You are not connected to the server" msgstr "Você não está conectado ao servidor" #: gajim/dialogs.py:928 msgid "Without a connection, you can not synchronise your contacts." msgstr "Sem uma conexão, você pode não sincronizar seus contatos." #: gajim/dialogs.py:939 gajim/dialogs.py:1010 gajim/dialogs.py:1122 #: gajim/disco.py:810 gajim/disco.py:1639 gajim/disco.py:1920 #: gajim/data/gui/manage_bookmarks_window.ui:125 gajim/gtk/history.py:104 msgid "Name" msgstr "Nome" #: gajim/dialogs.py:942 gajim/data/gui/join_groupchat_window.ui:163 msgid "Server" msgstr "Servidor" #: gajim/dialogs.py:978 msgid "This account is not connected to the server" msgstr "Esta conta não está conectada ao servidor" #: gajim/dialogs.py:979 msgid "You cannot synchronize with an account unless it is connected." msgstr "Você não pode sincronizar com uma conta a menos que esteja conectado." #: gajim/dialogs.py:1008 msgid "Synchronise" msgstr "Sincronizar" #: gajim/dialogs.py:1065 msgid "add" msgstr "adicionar" #: gajim/dialogs.py:1065 msgid "modify" msgstr "modificar" #: gajim/dialogs.py:1066 msgid "remove" msgstr "remover" #: gajim/dialogs.py:1095 #, python-format msgid "" "%(jid)s would like you to %(action)s some contacts in your " "roster." msgstr "" "%(jid)s gostaria que você %(action)s alguns contatos na sua " "lista." #: gajim/dialogs.py:1111 gajim/dialogs.py:1157 msgid "Add" msgstr "Adicionar" #: gajim/dialogs.py:1113 gajim/dialogs.py:1188 msgid "Modify" msgstr "Modificar" #: gajim/dialogs.py:1115 gajim/dialogs.py:1212 msgid "Delete" msgstr "Deletar" #: gajim/dialogs.py:1125 msgid "Groups" msgstr "Grupos" #: gajim/dialogs.py:1233 #, python-format msgid "%s suggested me to add you in my roster." msgstr "%s me sugeriu adicionar você à minha lista." #: gajim/dialogs.py:1247 #, python-format msgid "Added %d contact" msgid_plural "Added %d contacts" msgstr[0] "%d contato adicionado" msgstr[1] "%d contatos adicionados" #: gajim/dialogs.py:1285 #, python-format msgid "Removed %d contact" msgid_plural "Removed %d contacts" msgstr[0] "%d contato removido" msgstr[1] "%d contatos removidos" #: gajim/dialogs.py:1305 msgid "You are invited to a groupchat" msgstr "Você foi convidado para uma conferência" #: gajim/dialogs.py:1308 msgid "$Contact has invited you to join a discussion" msgstr "$Contact convidou você para ingressar em uma discussão" #: gajim/dialogs.py:1310 #, python-format msgid "$Contact has invited you to group chat %(room_jid)s" msgstr "$Contact convidou você para entrar na conferência %(room_jid)s" #: gajim/dialogs.py:1319 #, python-format msgid "Comment: %s" msgstr "Comentário: %s" #: gajim/dialogs.py:1321 msgid "Do you want to accept the invitation?" msgstr "Você quer aceitar este convite?" #: gajim/dialogs.py:1337 msgid "Reason (if you decline):" msgstr "Motivo (se você recusar):" #: gajim/dialogs.py:1339 gajim/chat_control.py:1527 gajim/gui_interface.py:643 #: gajim/notify.py:193 gajim/notify.py:212 gajim/notify.py:279 msgid "Groupchat Invitation" msgstr "Convite para conferência" #: gajim/dialogs.py:1624 msgid "an audio and video" msgstr "um áudio e vídeo" #: gajim/dialogs.py:1626 msgid "an audio" msgstr "um áudio" #: gajim/dialogs.py:1628 msgid "a video" msgstr "um video" #: gajim/dialogs.py:1632 #, python-format msgid "" "%(contact)s wants to start %(type)s session with you. Do you want to answer " "the call?" msgstr "" "O %(contact)s quer iniciar uma sessão %(type)s com você. Você quer " "responder a chamada?" #: gajim/dialogs.py:1736 gajim/data/gui/application_menu.ui:32 msgid "File Transfer" msgstr "Transferência de Arquivos" #: gajim/dialogs.py:1756 msgid "Requesting HTTP Upload Slot…" msgstr "Requisitando Slot para Envio por HTTP..." #: gajim/dialogs.py:1760 msgid "Uploading file via HTTP File Upload…" msgstr "Enviando arquivo por HTTP..." #: gajim/dialogs.py:1764 msgid "Encrypting file…" msgstr "Criptografando Arquivo..." #: gajim/dialogs.py:1790 #, python-format msgid "%(progress)s of %(total)s MiB sent" msgstr "" #: gajim/groupchat_control.py:203 gajim/groupchat_control.py:1926 #, python-format msgid "%(nick)s is now known as %(new_nick)s" msgstr "%(nick)s agora é conhecido como %(new_nick)s" #: gajim/groupchat_control.py:222 gajim/groupchat_control.py:2069 #: gajim/common/connection_handlers_events.py:1120 gajim/gtk/history.py:580 #, python-format msgid "%(nick)s is now %(status)s" msgstr "%(nick)s agora está %(status)s" #: gajim/groupchat_control.py:251 msgid "Sending private message failed" msgstr "Falha ao enviar uma mensagem privada" #: gajim/groupchat_control.py:253 #, python-format msgid "You are no longer in group chat \"%(room)s\" or \"%(nick)s\" has left." msgstr "" "Você não está mais na sala da conversa \"%(room)s\" ou \"%(nick)s\" saiu." #: gajim/groupchat_control.py:642 gajim/chat_control.py:328 msgid "No File Transfer available" msgstr "Nenhuma Transferência de Arquivo disponível" #: gajim/groupchat_control.py:684 gajim/groupchat_control.py:2415 msgid "Changing Subject" msgstr "Mudando assunto" #: gajim/groupchat_control.py:685 gajim/groupchat_control.py:2416 msgid "Please specify the new subject:" msgstr "Por favor, especifique o novo assunto:" #: gajim/groupchat_control.py:692 msgid "Changing Nickname" msgstr "Mudando apelido" #: gajim/groupchat_control.py:693 msgid "Please specify the new nickname you want to use:" msgstr "Por favor, especifique o novo apelido que você quer usar:" #: gajim/groupchat_control.py:711 msgid "Invalid group chat JID" msgstr "JID da conversa em grupo inválido" #: gajim/groupchat_control.py:712 msgid "The group chat JID has not allowed characters." msgstr "O JID da conversa em grupo possui caracteres não permitidos." #: gajim/groupchat_control.py:724 #, python-format msgid "Destroying %s" msgstr "Excluindo %s" #: gajim/groupchat_control.py:725 msgid "" "You are going to remove this room permanently.\n" "You may specify a reason below:" msgstr "" "Você está prestes a excluir esta sala permanentemente.\n" "Você pode especificar um motivo abaixo:" #: gajim/groupchat_control.py:727 msgid "You may also enter an alternate venue:" msgstr "Você também pode entrar com um ponto de encontro alternativo:" #: gajim/groupchat_control.py:802 gajim/gtk/profile.py:133 msgid "Could not load image" msgstr "A imagem não pode ser carregada" #: gajim/groupchat_control.py:934 msgid "Insert Nickname" msgstr "Inserir apelido" #: gajim/groupchat_control.py:1102 gajim/chat_control.py:803 msgid "and authenticated" msgstr "e autenticada" #: gajim/groupchat_control.py:1106 gajim/chat_control.py:807 msgid "and NOT authenticated" msgstr "e NÃO autenticada" #: gajim/groupchat_control.py:1110 gajim/chat_control.py:811 #, python-format msgid "%(type)s encryption is active %(authenticated)s." msgstr "Criptografia %(type)s está ativa %(authenticated)s." #: gajim/groupchat_control.py:1157 msgid "Conversation with " msgstr "Conversação com " #: gajim/groupchat_control.py:1159 msgid "Continued conversation" msgstr "Conversação continuada" #: gajim/groupchat_control.py:1525 #, python-format msgid "%(nick)s has set the subject to %(subject)s" msgstr "%(nick)s alterou o assunto para %(subject)s" #: gajim/groupchat_control.py:1553 gajim/groupchat_control.py:1870 msgid "Any occupant is allowed to see your full JID" msgstr "Algum ocupante tem permissão de ver o seu JID inteiro" #: gajim/groupchat_control.py:1556 msgid "Room now shows unavailable members" msgstr "A sala agora exibe membros indisponíveis" #: gajim/groupchat_control.py:1558 msgid "Room now does not show unavailable members" msgstr "A sala agora não mostra membros indisponíveis" #: gajim/groupchat_control.py:1560 msgid "A setting not related to privacy has been changed" msgstr "Uma configuração não relacionada a privacidade foi alterada" #: gajim/groupchat_control.py:1566 msgid "Room logging is now enabled" msgstr "A gravação das conversas da sala está ativo agora" #: gajim/groupchat_control.py:1568 msgid "Room logging is now disabled" msgstr "A gravação das conversas da sala está desligado agora" #: gajim/groupchat_control.py:1570 msgid "Room is now non-anonymous" msgstr "Agora a sala é não-anônima" #: gajim/groupchat_control.py:1573 msgid "Room is now semi-anonymous" msgstr "Agora a sala é semi-anônima" #: gajim/groupchat_control.py:1576 msgid "Room is now fully anonymous" msgstr "A sala agora é totalmente anônima" #: gajim/groupchat_control.py:1615 #, python-format msgid "Ping? (%s)" msgstr "Ping? (%s)" #: gajim/groupchat_control.py:1618 #, python-format msgid "Pong! (%(nick)s %(delay)s s.)" msgstr "Pong! (%(nick)s %(delay)s s.)" #: gajim/groupchat_control.py:1621 gajim/chat_control.py:1207 msgid "Error." msgstr "Erro." #: gajim/groupchat_control.py:1845 #, python-format msgid "You (%s) joined the room" msgstr "Você (%s) entrou na sala" #: gajim/groupchat_control.py:1863 gajim/groupchat_control.py:2444 #: gajim/roster_window.py:3131 gajim/gui_interface.py:602 #, python-format msgid "%(jid)s has been invited in this room" msgstr "%(jid)s foi convidado para esta sala" #: gajim/groupchat_control.py:1875 msgid "Room logging is enabled" msgstr "A gravação das conversas da sala está ligado" #: gajim/groupchat_control.py:1879 msgid "A new room has been created" msgstr "Uma nova sala foi criada" #: gajim/groupchat_control.py:1882 msgid "The server has assigned or modified your roomnick" msgstr "O servidor atribuiu ou modificou o apelido da sua sala" #: gajim/groupchat_control.py:1890 #, python-format msgid "%s kicked us due to an error" msgstr "%s nos expulsou devido a um erro" #: gajim/groupchat_control.py:1892 #, python-format msgid "%s has left due to an error" msgstr "%s saiu devido a um erro" #: gajim/groupchat_control.py:1898 #, python-format msgid "%(nick)s has been kicked: %(reason)s" msgstr "%(nick)s foi chutado: %(reason)s" #: gajim/groupchat_control.py:1901 #, python-format msgid "%(nick)s has been kicked by %(who)s: %(reason)s" msgstr "%(nick)s foi chutado por %(who)s: %(reason)s" #: gajim/groupchat_control.py:1910 #, python-format msgid "%(nick)s has been banned: %(reason)s" msgstr "%(nick)s foi banido: %(reason)s" #: gajim/groupchat_control.py:1913 #, python-format msgid "%(nick)s has been banned by %(who)s: %(reason)s" msgstr "%(nick)s foi banido por %(who)s: %(reason)s" #: gajim/groupchat_control.py:1924 gajim/groupchat_control.py:1994 #, python-format msgid "You are now known as %s" msgstr "Você agora é conhecido como %s" #: gajim/groupchat_control.py:1948 gajim/groupchat_control.py:1953 #: gajim/groupchat_control.py:1959 #, python-format msgid "%(nick)s has been removed from the room (%(reason)s)" msgstr "%(nick)s foi removido da sala (%(reason)s)" #: gajim/groupchat_control.py:1950 msgid "affiliation changed" msgstr "filiação alterada" #: gajim/groupchat_control.py:1955 msgid "room configuration changed to members-only" msgstr "a configuração da sala mudou para aceitar apenas membros" #: gajim/groupchat_control.py:1961 msgid "system shutdown" msgstr "desligamento do sistema" #: gajim/groupchat_control.py:2015 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s by %(actor)s" msgstr "" "** A afiliação de %(nick)s foi alterada para %(affiliation)s por %(actor)s" #: gajim/groupchat_control.py:2019 #, python-format msgid "** Affiliation of %(nick)s has been set to %(affiliation)s" msgstr "** A afiliação de %(nick)s foi alterado para %(affiliation)s" #: gajim/groupchat_control.py:2034 #, python-format msgid "** Role of %(nick)s has been set to %(role)s by %(actor)s" msgstr "** O cargo de %(nick)s foi definido para %(role)s por %(actor)s" #: gajim/groupchat_control.py:2038 #, python-format msgid "** Role of %(nick)s has been set to %(role)s" msgstr "** O cargo de %(nick)s foi definido para %(role)s" #: gajim/groupchat_control.py:2062 #, python-format msgid "%s has left" msgstr "%s saiu da sala" #: gajim/groupchat_control.py:2067 #, python-format msgid "%s has joined the group chat" msgstr "%s entrou na conferência" #: gajim/groupchat_control.py:2374 #, python-format msgid "Are you sure you want to leave group chat \"%s\"?" msgstr "Você tem certeza que quer deixar a conferência \"%s\"?" #: gajim/groupchat_control.py:2376 msgid "" "If you close this window, you will be disconnected from this group chat." msgstr "Se você fechar esta janela, será desconectado desta conferência." #: gajim/groupchat_control.py:2380 gajim/roster_window.py:2896 #: gajim/roster_window.py:3535 gajim/roster_window.py:4282 #: gajim/message_window.py:245 gajim/gui_interface.py:708 #: gajim/gui_interface.py:1451 gajim/gui_interface.py:1492 #: gajim/gtk/dialogs.py:447 msgid "_Do not ask me again" msgstr "_Não me pergunte novamente" #: gajim/groupchat_control.py:2596 #, python-format msgid "Kicking %s" msgstr "Chutando %s" #: gajim/groupchat_control.py:2597 gajim/groupchat_control.py:2897 msgid "You may specify a reason below:" msgstr "Você deve especificar uma razão abaixo:" #: gajim/groupchat_control.py:2896 #, python-format msgid "Banning %s" msgstr "Banindo %s" #: gajim/chat_control.py:389 msgid "Show a list of formattings" msgstr "Exibe uma lista de formatações" #: gajim/chat_control.py:393 msgid "Formatting is not available so long as GPG is active" msgstr "A formatação não é disponível quando o GPG está ativo" #: gajim/chat_control.py:396 msgid "This contact does not support HTML" msgstr "Este contato não suporta HTML" #: gajim/chat_control.py:519 #, python-format msgid "%(type)s state : %(state)s, reason: %(reason)s" msgstr "%(type)s estado: %(state)s, razão: %(reason)s" #: gajim/chat_control.py:660 #, python-format msgid "%(nickname)s from group chat %(room_name)s" msgstr "%(nickname)s da conferência %(room_name)s" #: gajim/chat_control.py:1159 #, python-format msgid "You just received a new message from \"%s\"" msgstr "Você acabou de receber uma nova mensagem de \"%s\"" #: gajim/chat_control.py:1161 msgid "" "If you close this tab and you have history disabled, this message will be " "lost." msgstr "" "Se você fechar esta aba e o histórico estiver desabilitado, esta mensagem " "será perdida." #: gajim/chat_control.py:1202 msgid "Ping?" msgstr "Ping?" #: gajim/chat_control.py:1205 #, python-format msgid "Pong! (%s seconds)" msgstr "Pong! (%s segundos)" #: gajim/chat_control.py:1313 #, python-format msgid "" "Subject: %(subject)s\n" "%(message)s" msgstr "" "Assunto: %(subject)s\n" "%(message)s" #: gajim/chat_control.py:1416 #, python-format msgid "%(name)s is now %(show)s %(status)s" msgstr "%(name)s está agora %(show)s %(status)s" #: gajim/chat_control.py:1471 msgid "File transfer" msgstr "Transferência de arquivos" #: gajim/chat_control.py:1474 msgid "Size" msgstr "Tamanho" #: gajim/chat_control.py:1476 msgid "Accept" msgstr "Aceitar" #: gajim/chat_control.py:1530 gajim/disco.py:1699 msgid "_Join" msgstr "_Ingressar" #: gajim/chat_control.py:1549 gajim/roster_window.py:1995 #: gajim/gui_interface.py:988 msgid "Remote contact stopped transfer" msgstr "O contato remoto parou a transferência" #: gajim/chat_control.py:1551 gajim/roster_window.py:1997 #: gajim/gui_interface.py:991 msgid "Error opening file" msgstr "Erro abrindo arquivo" #: gajim/application.py:68 msgid "Show the application's version" msgstr "Mostrar versão do aplicativo" #: gajim/application.py:75 msgid "Show only critical errors" msgstr "Mostrar somente erros críticos" #: gajim/application.py:82 msgid "Separate profile files completely (even history database and plugins)" msgstr "" "Separar completamente arquivos de perfil (até base de dados de histórico e " "plugins)" #: gajim/application.py:90 msgid "Print XML stanzas and other debug information" msgstr "Imprime stanzas XML e outras informações de depuração" #: gajim/application.py:97 msgid "Use defined profile in configuration directory" msgstr "Usar perfil escolhido no diretório de configuração" #: gajim/application.py:105 msgid "Set configuration directory" msgstr "Definir diretório de configuração" #: gajim/application.py:113 msgid "Configure logging system" msgstr "Configurar sistema de registros" #: gajim/application.py:121 msgid "Show all warnings" msgstr "Mostrar todas advertências" #: gajim/application.py:128 msgid "Open IPython shell" msgstr "Abrir terminal do IPython" #: gajim/application.py:135 msgid "Pops up a window with the next pending event" msgstr "Exibir uma janela popup com o próximo evento pendente" #: gajim/application.py:141 gajim/data/gui/shortcuts_window.ui:189 #: data/org.gajim.Gajim.desktop.in:21 msgid "Start a new chat" msgstr "Iniciar uma nova conversa" #: gajim/application.py:148 msgid "Simulate loss of connectivity" msgstr "Simular perda de conectividade" #: gajim/application.py:155 msgid "Simulate regaining connectivity" msgstr "Simular a recuperação de conectividade" #: gajim/application.py:196 gajim/gui_interface.py:139 msgid "Database Error" msgstr "Erro na base de dados" #: gajim/roster_window.py:291 gajim/roster_window.py:1072 msgid "Merged accounts" msgstr "Juntar contas" #: gajim/roster_window.py:894 gajim/roster_window.py:1666 #: gajim/roster_window.py:1699 gajim/roster_window.py:1750 #: gajim/roster_window.py:1752 gajim/roster_window.py:1913 #: gajim/roster_window.py:2584 gajim/roster_window.py:5145 gajim/disco.py:122 #: gajim/disco.py:123 gajim/disco.py:1403 gajim/common/contacts.py:173 #: gajim/common/contacts.py:419 gajim/common/helpers.py:69 msgid "Transports" msgstr "Transportes" #: gajim/roster_window.py:1758 gajim/roster_window.py:1760 #: gajim/roster_window.py:2611 gajim/roster_window.py:5115 #: gajim/message_window.py:522 gajim/gui_interface.py:1930 #: gajim/gui_interface.py:1955 gajim/common/contacts.py:171 #: gajim/common/helpers.py:69 gajim/common/modules/adhoc_commands.py:248 msgid "Groupchats" msgstr "Salas" #: gajim/roster_window.py:2056 msgid "Authorization sent" msgstr "Autorização enviada" #: gajim/roster_window.py:2057 #, python-format msgid "\"%s\" will now see your status." msgstr "Agora \"%s\" saberá seu status." #: gajim/roster_window.py:2080 msgid "Subscription request has been sent" msgstr "Solicitação de inscrição foi enviada" #: gajim/roster_window.py:2081 #, python-format msgid "If \"%s\" accepts this request you will know his or her status." msgstr "Se \"%s\" aceitar esta solicitação, você saberá o status dele ou dela." #: gajim/roster_window.py:2095 msgid "Authorization removed" msgstr "Autorização removida" #: gajim/roster_window.py:2096 #, python-format msgid "Now \"%s\" will always see you as offline." msgstr "Agora \"%s\" você sempre o verá como offline." #: gajim/roster_window.py:2120 msgid "OpenPGP is not usable" msgstr "OpenPGP não é usável" #: gajim/roster_window.py:2121 #, python-format msgid "" "Gajim needs python-gnupg >= 0.3.8\n" "Beware there is an incompatible Python package called gnupg.\n" "You will be connected to %s without OpenPGP." msgstr "" "Gajim requer python-gnupg >= 0.3.8\n" "Atenção que há um pacote Python incompatível denominado gnupg.\n" "Você será conectado a %s sem usar OpenPGP." #: gajim/roster_window.py:2330 gajim/roster_window.py:3631 msgid "You are participating in one or more group chats" msgstr "Você está participando em uma ou mais conferências" #: gajim/roster_window.py:2331 gajim/roster_window.py:3632 msgid "" "Changing your status to invisible will result in disconnection from those " "group chats. Are you sure you want to go invisible?" msgstr "" "Mudando seu status para invisível resulta na desconexão daquelas " "conferências. Você tem certeza que quer ir invisível?" #: gajim/roster_window.py:2358 msgid "desynced" msgstr "não sincronizado" #: gajim/roster_window.py:2425 msgid "Really quit Gajim?" msgstr "Realmente sair do Gajim?" #: gajim/roster_window.py:2426 msgid "Are you sure you want to quit Gajim?" msgstr "Você tem certeza que deseja sair?" #: gajim/roster_window.py:2427 msgid "Always close Gajim" msgstr "Sempre fechar o Gajim" #: gajim/roster_window.py:2514 msgid "You have running file transfers" msgstr "Você possui arquivos sendo transferidos" #: gajim/roster_window.py:2515 msgid "" "If you quit now, the file(s) being transferred will be stopped. Do you still " "want to quit?" msgstr "" "Se você sair agora, a transferência do(s) arquivo(s) em trânsito será " "interrompida. Ainda deseja sair?" #: gajim/roster_window.py:2546 gajim/roster_window.py:2824 msgid "You have unread messages" msgstr "Você tem mensagens não lidas" #: gajim/roster_window.py:2547 msgid "" "Messages will only be available for reading them later if you have history " "enabled and contact is in your roster." msgstr "" "Mensagens somente estarão disponíveis para leitura mais tarde se você tiver " "o histórico habilitado e contato na sua lista." #: gajim/roster_window.py:2825 msgid "You must read them before removing this transport." msgstr "Você precisa lê-los antes de remover este transporte." #: gajim/roster_window.py:2828 #, python-format msgid "Transport \"%s\" will be removed" msgstr "Transporte \"%s\" será removido" #: gajim/roster_window.py:2829 msgid "" "You will no longer be able to send and receive messages from contacts using " "this transport." msgstr "" "Você não poderá mais enviar e receber mensagens dos contatos usando este " "transporte." #: gajim/roster_window.py:2832 msgid "Transports will be removed" msgstr "Os transportes serão removidos" #: gajim/roster_window.py:2837 #, python-format msgid "" "You will no longer be able to send and receive messages to contacts from " "these transports: %s" msgstr "" "Você não poderá mais enviar e receber mensagens para contatos destes " "transportes: %s" #: gajim/roster_window.py:2891 msgid "You are about to block a contact. Are you sure you want to continue?" msgstr "" "Você está prestes a bloquear um contato. Tem certeza que quer continuar?" #: gajim/roster_window.py:2893 msgid "" "This contact will see you offline and you will not receive messages it sends " "you." msgstr "" "Este contato irá ver você desconectado e você não irá receber mensagens que " "ele enviar para você." #: gajim/roster_window.py:2939 msgid "Rename Contact" msgstr "Renomear contato" #: gajim/roster_window.py:2940 #, python-format msgid "Enter a new nickname for contact %s" msgstr "Entre com um novo apelido para o contato %s" #: gajim/roster_window.py:2947 msgid "Rename Group" msgstr "Renomear grupo" #: gajim/roster_window.py:2948 #, python-format msgid "Enter a new name for group %s" msgstr "Entre com um novo nome para o grupo %s" #: gajim/roster_window.py:2993 msgid "Remove Group" msgstr "Remover grupo" #: gajim/roster_window.py:2994 #, python-format msgid "Do you want to remove group %s from the roster?" msgstr "Você quer remover o grupo %s da lista?" #: gajim/roster_window.py:2995 msgid "Also remove all contacts in this group from your roster" msgstr "Também remove todos os contatos neste grupo da sua lista" #: gajim/roster_window.py:3034 msgid "Assign OpenPGP Key" msgstr "Atribuir chave OpenPGP" #: gajim/roster_window.py:3035 msgid "Select a key to apply to the contact" msgstr "Selecione uma chave para atribuir ao contato" #: gajim/roster_window.py:3441 #, python-format msgid "Contact \"%s\" will be removed from your roster" msgstr "Contato \"%s\" será removido de sua lista" #: gajim/roster_window.py:3443 #, python-format msgid "You are about to remove \"%(name)s\" (%(jid)s) from your roster.\n" msgstr "Você realmente deseja remover \"%(name)s\" (%(jid)s) da sua lista.\n" #: gajim/roster_window.py:3448 msgid "" "By removing this contact you also remove authorization resulting in them " "always seeing you as offline." msgstr "" "Ao remover este contato, você também remove a autorização, fazendo com que " "eles sempre o vejam como offline." #: gajim/roster_window.py:3454 msgid "Do you want to continue?" msgstr "Você quer continuar?" #: gajim/roster_window.py:3458 #, fuzzy msgid "" "By removing this contact you also by default remove authorization resulting " "in them always seeing you as offline." msgstr "" "Removendo este contato, você também, por padrão, removerá a autorização, " "resultando em ele ou ela sempre o verá offiline." #: gajim/roster_window.py:3461 msgid "I want this contact to know my status after removal" msgstr "Eu quero que este contato saiba meu status após a remoção" #: gajim/roster_window.py:3465 msgid "Contacts will be removed from your roster" msgstr "Os contatos serão removidos da sua lista" #: gajim/roster_window.py:3470 #, python-format msgid "" "By removing these contacts:%s\n" "you also remove authorization resulting in them always seeing you as offline." msgstr "" "Removendo estes contatos:%s\n" "você também remove a autorização fazendo com que eles sempre vejam você " "offline." #: gajim/roster_window.py:3529 #, fuzzy msgid "" "You are about to send a custom status. Are you sure you want to continue?" msgstr "" "Você está prestes a enviar um status customizado. Tem certeza que quer " "continuar?" #: gajim/roster_window.py:3531 #, fuzzy, python-format msgid "" "This contact will temporarily see you as %(status)s, but only until you " "change your status. Then they will see your global status." msgstr "" "Este contato irá temporariamente ver você como %(status)s, mas somente até " "você alterar o seu status. Então ele irá ver o seu status global." #: gajim/roster_window.py:3550 msgid "No account available" msgstr "Conta não disponível" #: gajim/roster_window.py:3551 msgid "You must create an account before you can chat with other contacts." msgstr "" "Você deve configurar uma conta antes de poder conversar com outros contatos." #: gajim/roster_window.py:4178 msgid "Metacontacts storage not supported by your server" msgstr "O armazenamento de metacontatos não é suportado pelo seu servidor" #: gajim/roster_window.py:4180 #, fuzzy msgid "" "Your server does not support storing metacontacts information. So this " "information will not be saved on next reconnection." msgstr "" "O seu servidor não suporta a gravação de informação de metacontatos, então " "essas informações não estarão salvas na próxima vez que você conectar." #: gajim/roster_window.py:4276 msgid "" "You are about to create a metacontact. Are you sure you want to continue?" msgstr "" "Você está prestes a criar um metacontato. Tem certeza que quer continuar?" #: gajim/roster_window.py:4278 #, fuzzy msgid "" "Metacontacts are a way to regroup several contacts in one line. Generally it " "is used when the same person has several XMPP- or transport -accounts." msgstr "" "Os metacontatos são uma forma de reagrupar muitos contatos em uma linha. " "Geralmente isso é usado quando a mesma pessoa possui muitas contas de Jabber " "ou transportes." #: gajim/roster_window.py:4400 msgid "Invalid file URI:" msgstr "Arquivo URI inválido:" #: gajim/roster_window.py:4411 #, fuzzy msgid "Send file?" msgstr "Enviar _arquivo" #: gajim/roster_window.py:4412 #, python-format msgid "Do you want to send this file to %s:" msgid_plural "Do you want to send these files to %s:" msgstr[0] "Você quer enviar este arquivo para %s:" msgstr[1] "Você quer enviar estes arquivos para %s:" #: gajim/roster_window.py:4552 #, fuzzy, python-format msgid "Send %(from)s to %(to)s" msgstr "Enviar %s para %s" #: gajim/roster_window.py:4565 #, python-format msgid "Make %s first contact" msgstr "Tornar %s primeiro contato" #: gajim/roster_window.py:4570 #, fuzzy, python-format msgid "Make %(contact1)s and %(contact2)s metacontacts" msgstr "Fazer %s e %s metacontatos" #: gajim/roster_window.py:4945 gajim/roster_window.py:5043 msgid "_Change Status Message" msgstr "_Mudar mensagem de status" #: gajim/roster_window.py:4965 msgid "Publish Tune" msgstr "Publicar sintonia" #: gajim/roster_window.py:4976 #, fuzzy msgid "Publish Location" msgstr "Publicar sintonia" #: gajim/roster_window.py:4988 #, fuzzy msgid "Configure Services…" msgstr "Configurar serviços..." #: gajim/roster_window.py:5117 msgid "_Maximize All" msgstr "_Maximizar tudo" #: gajim/roster_window.py:5124 gajim/roster_window.py:5283 msgid "Send Group M_essage" msgstr "Enviar m_ensagem de grupo" #: gajim/roster_window.py:5131 msgid "To all users" msgstr "Para todos os usuários" #: gajim/roster_window.py:5135 msgid "To all online users" msgstr "Para todos os usuários conectados" #: gajim/roster_window.py:5147 gajim/roster_window.py:5289 #: gajim/data/gui/gc_occupants_menu.ui:110 #: gajim/data/gui/contact_context_menu.ui:36 msgid "In_vite to" msgstr "Con_vidar para" #: gajim/roster_window.py:5299 msgid "_Manage Contacts" msgstr "_Gerenciar contatos" #: gajim/roster_window.py:5305 #, fuzzy msgid "Edit _Groups…" msgstr "Editar _grupos" #: gajim/roster_window.py:5326 gajim/data/gui/filetransfers.ui:11 #: gajim/data/gui/remove_account_window.ui:137 msgid "_Remove" msgstr "_Remover" #: gajim/roster_window.py:5363 msgid "_Maximize" msgstr "_Maximizar" #: gajim/roster_window.py:5370 msgid "_Reconnect" msgstr "_Reconectar" #: gajim/roster_window.py:5375 gajim/data/gui/gc_control_popup_menu.ui:120 msgid "_Disconnect" msgstr "_Desconectar" #: gajim/roster_window.py:5391 gajim/data/gui/gc_occupants_menu.ui:170 #: gajim/data/gui/gc_control_popup_menu.ui:113 #: gajim/data/gui/contact_context_menu.ui:228 msgid "_History" msgstr "_Histórico" #: gajim/roster_window.py:5467 gajim/data/gui/application_menu.ui:86 #: gajim/data/gui/history_window.ui:57 msgid "History Manager" msgstr "Gerenciador de histórico" #: gajim/roster_window.py:5475 msgid "_Join New Group Chat" msgstr "_Ingressar em uma nova Conferência" #: gajim/config.py:359 msgid "Ban List" msgstr "Lista de banidos" #: gajim/config.py:360 msgid "Member List" msgstr "Lista de membros" #: gajim/config.py:360 msgid "Owner List" msgstr "Lista de proprietários" #: gajim/config.py:361 msgid "Administrator List" msgstr "Lista de administradores" #: gajim/config.py:435 msgid "Reason" msgstr "Razão" #: gajim/config.py:442 msgid "Nick" msgstr "Apelido" #: gajim/config.py:448 gajim/data/gui/profile_window.ui:945 #: gajim/data/gui/vcard_information_window.ui:1135 msgid "Role" msgstr "Cargo" #: gajim/config.py:478 #, fuzzy msgid "Banning…" msgstr "Banindo..." #: gajim/config.py:480 msgid "" "Whom do you want to ban?\n" "\n" msgstr "" "Quem você quer banir?\n" "\n" #: gajim/config.py:482 #, fuzzy msgid "Adding Member…" msgstr "Adicionando membro..." #: gajim/config.py:483 msgid "" "Whom do you want to make a member?\n" "\n" msgstr "" "Quem você quer fazer como membro?\n" "\n" #: gajim/config.py:485 #, fuzzy msgid "Adding Owner…" msgstr "Adicionando proprietário..." #: gajim/config.py:486 msgid "" "Whom do you want to make an owner?\n" "\n" msgstr "" "Quem você quer tornar um proprietário?\n" "\n" #: gajim/config.py:488 #, fuzzy msgid "Adding Administrator…" msgstr "Adicionando administrador..." #: gajim/config.py:489 msgid "" "Whom do you want to make an administrator?\n" "\n" msgstr "" "Quem você quer tornar um administrador?\n" "\n" #: gajim/config.py:490 msgid "" "Can be one of the following:\n" "1. user@domain/resource (only that resource matches).\n" "2. user@domain (any resource matches).\n" "3. domain/resource (only that resource matches).\n" "4. domain (the domain itself matches, as does any user@domain,\n" "domain/resource, or address containing a subdomain)." msgstr "" "Pode ser uma dos seguintes:\n" "1. usuario@dominio/recurso (somente este recurso combina).\n" "2. usuario@dominio (qualquer recurso combina).\n" "3. domínio/recurso (somente este recurso combina).\n" "4. domínio (o domínio combina por si com qualquer usuario@dominio,\n" "domínio/recurso, ou endereço contendo um subdomínio." #: gajim/config.py:593 #, python-format msgid "Removing %s account" msgstr "Removendo %s conta" #: gajim/config.py:608 #, fuzzy msgid "Account is disabled" msgstr "Emoticons desabilitados" #: gajim/config.py:609 msgid "To unregister from a server, account must be enabled." msgstr "" #: gajim/config.py:623 gajim/gui_interface.py:326 gajim/gui_interface.py:731 msgid "Password Required" msgstr "Senha é obrigatória" #: gajim/config.py:624 gajim/gui_interface.py:716 #, python-format msgid "Enter your password for account %s" msgstr "Entre com a senha para conta %s" #: gajim/config.py:625 gajim/gui_interface.py:731 msgid "Save password" msgstr "Salvar senha" #: gajim/config.py:636 #, python-format msgid "Account \"%s\" is connected to the server" msgstr "Conta \"%s\" está conectada ao servidor" #: gajim/config.py:637 msgid "If you remove it, the connection will be lost." msgstr "Se você remover-lo, a conexão será perdida." #: gajim/config.py:652 #, python-format msgid "Connection to server %s failed" msgstr "A conexão ao servidor %s falhou" #: gajim/config.py:653 #, fuzzy msgid "What would you like to do?" msgstr "O que você quer fazer?" #: gajim/config.py:654 #, fuzzy msgid "Remove only from Gajim" msgstr "Remover conta _somente do Gajim" #: gajim/config.py:655 msgid "Don't remove anything. I'll try again later" msgstr "" #: gajim/config.py:712 msgid "Wav Sounds" msgstr "Sons wav" #: gajim/config.py:745 #, fuzzy msgid "Attention Message Received" msgstr "Primeira mensagem recebida" #: gajim/config.py:746 msgid "First Message Received" msgstr "Primeira mensagem recebida" #: gajim/config.py:747 msgid "Next Message Received Focused" msgstr "Nova mensagem recebida com foco" #: gajim/config.py:748 msgid "Next Message Received Unfocused" msgstr "Nova mensagem recebida sem foco" #: gajim/config.py:749 msgid "Contact Connected" msgstr "Contato conectado" #: gajim/config.py:750 msgid "Contact Disconnected" msgstr "Contato desconectou" #: gajim/config.py:751 msgid "Message Sent" msgstr "Mensagem enviada" #: gajim/config.py:752 msgid "Group Chat Message Highlight" msgstr "Mensagem destacada de conferência" #: gajim/config.py:753 msgid "Group Chat Message Received" msgstr "Mensagem de conferência recebida" #: gajim/tooltips.py:235 #, python-format msgid "%(owner_or_admin_or_member)s of this group chat" msgstr "%(owner_or_admin_or_member)s dessa sala" #: gajim/tooltips.py:264 gajim/common/helpers.py:359 msgid "?Group Chat Contact Affiliation:None" msgstr "?Filiação do contato de conferência:Nenhuma" #: gajim/tooltips.py:266 gajim/common/helpers.py:365 msgid "Member" msgstr "Membro" #: gajim/tooltips.py:268 gajim/common/helpers.py:363 msgid "Administrator" msgstr "Administrador" #: gajim/tooltips.py:270 gajim/common/helpers.py:361 msgid "Owner" msgstr "Dono" #: gajim/tooltips.py:398 msgid " [blocked]" msgstr " [bloqueado]" #: gajim/tooltips.py:402 msgid " [minimized]" msgstr " [minimizado]" #: gajim/tooltips.py:574 msgid "Connected" msgstr "Conectado" #: gajim/tooltips.py:576 msgid "Disconnected" msgstr "Desconectado" #: gajim/tooltips.py:624 #, fuzzy msgid "?Noun:Download" msgstr "Download" #: gajim/tooltips.py:630 #, fuzzy msgid "?Noun:Upload" msgstr "Upload" #: gajim/tooltips.py:637 msgid "Type: " msgstr "Tipo: " #: gajim/tooltips.py:643 msgid "Transferred: " msgstr "Transferido: " #: gajim/tooltips.py:645 msgid "Status: " msgstr "Status: " #: gajim/tooltips.py:647 msgid "Description: " msgstr "Descrição: " #: gajim/tooltips.py:672 msgid "Aborted" msgstr "" #: gajim/tooltips.py:674 msgid "Completed" msgstr "Completo" #: gajim/tooltips.py:676 msgid "?transfer status:Paused" msgstr "?status da transferência:Parado" #: gajim/tooltips.py:679 msgid "Stalled" msgstr "Parado" #: gajim/tooltips.py:683 msgid "Transferring" msgstr "Transferindo" #: gajim/tooltips.py:684 gajim/tooltips.py:685 msgid "Not started" msgstr "Não iniciado" #: gajim/tooltips.py:695 gajim/common/helpers.py:275 #, fuzzy msgid "?user status:Available" msgstr "?status da transferência:Parado" #: gajim/tooltips.py:697 gajim/common/helpers.py:270 msgid "Free for Chat" msgstr "Livre para conversa" #: gajim/tooltips.py:699 gajim/common/helpers.py:282 #: gajim/common/modules/adhoc_commands.py:123 #: gajim/command_system/implementation/standard.py:139 msgid "Away" msgstr "Afastado" #: gajim/tooltips.py:701 gajim/common/helpers.py:260 msgid "Busy" msgstr "Ocupado" #: gajim/tooltips.py:703 gajim/common/helpers.py:265 msgid "Not Available" msgstr "Não disponível" #: gajim/tooltips.py:705 gajim/common/helpers.py:287 msgid "Offline" msgstr "Desconectado" #: gajim/statusicon.py:210 #, fuzzy msgid "_Change Status Message…" msgstr "_Mudar mensagem de status" #: gajim/statusicon.py:244 gajim/statusicon.py:289 gajim/statusicon.py:296 #, python-format msgid "using account %s" msgstr "usando conta %s" #: gajim/statusicon.py:306 #, fuzzy msgid "_Manage Bookmarks…" msgstr "Gerenciar marcadores" #: gajim/statusicon.py:322 #, fuzzy msgid "Hide _Roster" msgstr "na _lista" #: gajim/statusicon.py:326 msgid "Show _Roster" msgstr "Exibir _lista" #: gajim/statusicon.py:334 msgid "Hide this menu" msgstr "Esconder este menu" #: gajim/dataforms_widget.py:584 #, fuzzy msgid "Unable to load image" msgstr "Incapaz de carregar o módulo inativo" #: gajim/dataforms_widget.py:586 #, python-format msgid "Media type not supported: %s" msgstr "Tipo de mídia não suportado: %s" #: gajim/dataforms_widget.py:601 msgid "This field is required" msgstr "" #: gajim/dataforms_widget.py:655 msgid "new@jabber.id" msgstr "novo@jabber.id" #: gajim/dataforms_widget.py:658 gajim/dataforms_widget.py:660 #, python-format msgid "new%d@jabber.id" msgstr "novo%d@jabber.id" #: gajim/disco.py:67 msgid "This service has not yet responded with detailed information" msgstr "Este serviço não respondeu ainda com informação detalhada" #: gajim/disco.py:68 msgid "" "This service could not respond with detailed information.\n" "It is most likely legacy or broken" msgstr "" "Este serviço não pode responder com informações detalhadas.\n" "É provável que esteja quebrado" #: gajim/disco.py:121 msgid "Others" msgstr "Outros" #: gajim/disco.py:125 msgid "Conference" msgstr "Conferência" #: gajim/disco.py:504 msgid "Without a connection, you can not browse available services" msgstr "Você deve estar conectado para visualizar os serviços disponíveis" #: gajim/disco.py:593 #, python-format msgid "Service Discovery using account %s" msgstr "Buscar serviços usando conta %s" #: gajim/disco.py:595 msgid "Service Discovery" msgstr "Buscar serviços" #: gajim/disco.py:676 msgid "The service could not be found" msgstr "O serviço não pode ser encontrado" #: gajim/disco.py:677 msgid "" "There is no service at the address you entered, or it is not responding. " "Check the address and try again." msgstr "" "Não existe serviço para o endereço que você entrou, ou não está respondendo. " "Verifique o endereço e tente novamente." #: gajim/disco.py:684 gajim/disco.py:1036 msgid "The service is not browsable" msgstr "Serviço não navegável" #: gajim/disco.py:685 msgid "This type of service does not contain any items to browse." msgstr "Este tipo de serviço não contém nenhum item para navegar." #: gajim/disco.py:726 gajim/disco.py:736 msgid "Invalid Server Name" msgstr "Nome do servidor inválido" #: gajim/disco.py:794 #, python-format msgid "Browsing %(address)s using account %(account)s" msgstr "Explorando %(address)s usando conta %(account)s" #: gajim/disco.py:841 #, fuzzy msgid "Browse" msgstr "_Navegar" #: gajim/disco.py:1037 msgid "This service does not contain any items to browse." msgstr "Este serviço não contém nenhum item para navegar." #: gajim/disco.py:1248 #, fuzzy msgid "Execute Command" msgstr "_Executar comando" #: gajim/disco.py:1252 gajim/disco.py:1409 msgid "Re_gister" msgstr "Re_gistrar" #: gajim/disco.py:1261 gajim/data/gui/join_groupchat_window.ui:437 #, fuzzy msgid "Join" msgstr "_Ingressar" #: gajim/disco.py:1270 gajim/data/gui/search_window.ui:23 msgid "Search" msgstr "Buscar" #: gajim/disco.py:1407 msgid "_Edit" msgstr "_Editar" #: gajim/disco.py:1450 #, python-format msgid "Scanning %(current)d / %(total)d.." msgstr "Varrendo %(current)d / %(total)d.." #: gajim/disco.py:1649 msgid "Users" msgstr "Usuários" #: gajim/disco.py:1657 msgid "Description" msgstr "Descrição" #: gajim/disco.py:1665 msgid "Id" msgstr "Id" #: gajim/disco.py:1695 gajim/data/gui/gc_control_popup_menu.ui:99 msgid "_Bookmark" msgstr "Ma_rcadores" #: gajim/disco.py:1721 msgid "Bookmark already set" msgstr "Marcador já configurado" #: gajim/disco.py:1722 #, python-format msgid "Group Chat \"%s\" is already in your bookmarks." msgstr "A sala \"%s\" já existe nos marcadores." #: gajim/disco.py:1734 msgid "Bookmark has been added successfully" msgstr "Marcador foi adicionado com sucesso" #: gajim/disco.py:1735 msgid "You can manage your bookmarks via Actions menu in your roster." msgstr "" "Você pode gerenciar seus marcadores pelo menu de ações na janela principal." #: gajim/disco.py:1929 msgid "Subscribed" msgstr "Inscrito" #: gajim/disco.py:1938 msgid "Node" msgstr "Nó" #: gajim/disco.py:2005 msgid "New post" msgstr "Nova postagem" #: gajim/disco.py:2011 msgid "_Subscribe" msgstr "_Inscrever" #: gajim/disco.py:2017 msgid "_Unsubscribe" msgstr "_Desinscrever" #: gajim/conversation_textview.py:320 msgid "" "Text below this line is what has been said since the\n" "last time you paid attention to this group chat" msgstr "" "O texto abaixo desta linha é o que foi dito desde a\n" "última vez onde você prestou a atenção a conferência" #: gajim/conversation_textview.py:541 msgid "_Quote" msgstr "_Frase" #: gajim/conversation_textview.py:549 #, python-format msgid "_Actions for \"%s\"" msgstr "_Ações para \"%s\"" #: gajim/conversation_textview.py:563 msgid "Read _Wikipedia Article" msgstr "Ler artigo da _Wikipedia" #: gajim/conversation_textview.py:568 msgid "Look it up in _Dictionary" msgstr "Procurar no _dicionário" #: gajim/conversation_textview.py:585 #, python-format msgid "Dictionary URL is missing an \"%s\" and it is not WIKTIONARY" msgstr "URL do dicionário não existe \"%s\" e isto não é WIKTIONARY" #: gajim/conversation_textview.py:599 #, python-format msgid "Web Search URL is missing an \"%s\"" msgstr "URL de procura na web não existe \"%s\"" #: gajim/conversation_textview.py:602 msgid "Web _Search for it" msgstr "_Procura na web por isto" #: gajim/conversation_textview.py:608 msgid "Open as _Link" msgstr "Abrir como _link" #: gajim/conversation_textview.py:884 #, fuzzy msgid "Invalid URL" msgstr "JID inválido:" #: gajim/conversation_textview.py:969 msgid "" "Message corrected. Original message:\n" "{}" msgstr "" "Mensagem corrigida. Mensagem original:\n" "{}" #: gajim/conversation_textview.py:1115 #, python-format msgid "Yesterday" msgid_plural "%(nb_days)i days ago" msgstr[0] "Ontem" msgstr[1] "%(nb_days)i dias atrás" #: gajim/conversation_textview.py:1145 #, fuzzy msgid "Not encrypted" msgstr "Não iniciado" #: gajim/conversation_textview.py:1241 gajim/gtk/history.py:617 #, python-format msgid "Subject: %s\n" msgstr "Assunto: %s\n" #: gajim/message_textview.py:43 #, fuzzy msgid "Write a message…" msgstr "Enviar mensagem privada" #: gajim/message_window.py:243 msgid "You are going to close several tabs" msgstr "Você está prestes a fechar todas as abas" #: gajim/message_window.py:244 msgid "Do you really want to close them all?" msgstr "Você realmente deseja fechar todas?" #: gajim/message_window.py:520 #, fuzzy msgid "?Noun:Chats" msgstr "Conferências" #: gajim/message_window.py:524 msgid "Private Chats" msgstr "Conversas privadas" #: gajim/message_window.py:530 msgid "Messages" msgstr "Mensagens" #: gajim/gui_interface.py:169 gajim/gui_interface.py:341 #: gajim/gui_interface.py:350 gajim/gui_interface.py:357 #: gajim/gui_interface.py:361 gajim/gui_interface.py:364 #: gajim/gui_interface.py:372 msgid "Unable to join group chat" msgstr "Impossível ingressar na sala" #: gajim/gui_interface.py:170 #, python-format msgid "" "Your desired nickname in group chat\n" "%s\n" "is in use or registered by another occupant.\n" "Please specify another nickname below:" msgstr "" "Seu apelido desejado na sala de bate-papo\n" "%s\n" "já está em uso ou foi registrado por outro ocupante.\n" "Por favor, especifique outro apelido abaixo:" #: gajim/gui_interface.py:192 msgid "Do you accept this request?" msgstr "Você aceita a solicitação?" #: gajim/gui_interface.py:194 #, python-format msgid "Do you accept this request on account %s?" msgstr "Você aceita essa requisição na conta %s?" #: gajim/gui_interface.py:197 #, fuzzy, python-format msgid "HTTP (%(method)s) Authorization for %(url)s (ID: %(id)s)" msgstr "Autorização HTTP (%(method)s) para %(url)s (id: %(id)s)" #: gajim/gui_interface.py:240 gajim/notify.py:194 gajim/notify.py:214 msgid "Connection Failed" msgstr "Falha na conexão" #: gajim/gui_interface.py:327 #, python-format msgid "A Password is required to join the room %s. Please type it." msgstr "Uma senha é requerida para ingressar na sala %s. Por favor, digite-a." #: gajim/gui_interface.py:342 #, python-format msgid "%s is full" msgstr "%s está cheio" #: gajim/gui_interface.py:351 #, python-format msgid "You are banned from group chat %s." msgstr "Você está banido da sala %s." #: gajim/gui_interface.py:358 #, python-format msgid "Remote server %s does not exist." msgstr "O servidor remoto %s não existe." #: gajim/gui_interface.py:362 #, python-format msgid "Group chat %s does not exist." msgstr "A sala %s não existe." #: gajim/gui_interface.py:365 #, fuzzy msgid "Group chat creation is not permitted." msgstr "A criação de sala é restrita." #: gajim/gui_interface.py:367 #, fuzzy msgid "Unable to join groupchat" msgstr "Impossível ingressar na sala" #: gajim/gui_interface.py:368 #, python-format msgid "You must use your registered nickname in %s." msgstr "Você deve usar seu apelido registrado em %s." #: gajim/gui_interface.py:373 #, python-format msgid "You are not in the members list in groupchat %s." msgstr "Você não está na lista de membros da sala %s." #: gajim/gui_interface.py:447 gajim/gui_interface.py:451 #, python-format msgid "Error %(code)s: %(msg)s" msgstr "Erro %(code)s: %(msg)s" #: gajim/gui_interface.py:462 gajim/gui_interface.py:478 #: gajim/common/modules/message.py:161 #, python-format msgid "error while sending %(message)s ( %(error)s )" msgstr "erro ao enviar %(message)s ( %(error)s )" #: gajim/gui_interface.py:503 gajim/notify.py:194 msgid "Subscription request" msgstr "Solicitação de inscrição" #: gajim/gui_interface.py:515 gajim/common/contacts.py:169 #: gajim/common/helpers.py:69 msgid "Observers" msgstr "Observadores" #: gajim/gui_interface.py:529 msgid "Authorization accepted" msgstr "Autorização aceita" #: gajim/gui_interface.py:530 #, fuzzy, python-format msgid "The contact \"%s\" has authorized you to see their status." msgstr "O contato \"%s\" autorizou você para ver seu status." #: gajim/gui_interface.py:538 #, python-format msgid "Contact \"%s\" removed subscription from you" msgstr "Contato \"%s\" removeu sua inscrição" #: gajim/gui_interface.py:539 #, fuzzy msgid "" "You will always see them as offline.\n" "Do you want to remove them from your contact list?" msgstr "" "Você irá sempre ver ele ou ela como desconectado.\n" "Você quer removê-lo ou removê-la da sua lista de contatos?" #: gajim/gui_interface.py:560 gajim/notify.py:194 msgid "Unsubscribed" msgstr "Desinscrever" #: gajim/gui_interface.py:621 #, python-format msgid "%(jid)s declined the invitation: %(reason)s" msgstr "%(jid)s negou o convite: %(reason)s" #: gajim/gui_interface.py:626 #, python-format msgid "%(jid)s declined the invitation" msgstr "%(jid)s negou o convite" #: gajim/gui_interface.py:644 #, python-brace-format msgid "You are invited to {room} by {user}" msgstr "Você foi convidado para a conferência {room} por {user}" #: gajim/gui_interface.py:658 #, fuzzy msgid "" "You configured Gajim to use OpenPGP agent, but there is no OpenPGP agent " "running or it returned a wrong passphrase.\n" msgstr "" "Você configurou o Gajim para usar o agente do GPG, mas não há agente do GPG " "rodando ou então ele retornou uma frase secreta incorreta.\n" #: gajim/gui_interface.py:661 gajim/gui_interface.py:669 msgid "You are currently connected without your OpenPGP key." msgstr "Você está atualmente conectado sem sua chave OpenPGP." #: gajim/gui_interface.py:663 #, fuzzy msgid "Wrong passphrase" msgstr "Frase de acesso errada" #: gajim/gui_interface.py:668 #, fuzzy msgid "Wrong OpenPGP passphrase" msgstr "Frase de acesso errada" #: gajim/gui_interface.py:682 #, fuzzy msgid "Certificate Passphrase Required" msgstr "O certificado expirou" #: gajim/gui_interface.py:683 #, python-format msgid "Enter the certificate passphrase for account %s" msgstr "Insira a senha do certificado para a conta %s" #: gajim/gui_interface.py:706 #, fuzzy msgid "Untrusted OpenPGP key" msgstr "Escolha sua chave OpenPGP" #: gajim/gui_interface.py:706 #, fuzzy msgid "" "The OpenPGP key used to encrypt this chat is not trusted. Do you really want " "to encrypt this message?" msgstr "" "A chave GPG usada para criptografar esta conversa não é confiável. Você " "realmente deseja criptografar esta mensagem?" #: gajim/gui_interface.py:752 msgid "" "Please copy / paste the refresh token from the website that has just been " "opened." msgstr "" #: gajim/gui_interface.py:755 msgid "Oauth2 Credentials" msgstr "" #: gajim/gui_interface.py:833 gajim/gui_interface.py:864 gajim/notify.py:192 #: gajim/notify.py:274 msgid "File Transfer Error" msgstr "Erro na transferência de arquivos" #: gajim/gui_interface.py:898 #, python-format msgid "%s wants to send you a file." msgstr "%s quer te enviar um arquivo." #: gajim/gui_interface.py:900 gajim/notify.py:191 gajim/notify.py:272 msgid "File Transfer Request" msgstr "Solicitação de transferência de arquivos" #: gajim/gui_interface.py:996 msgid "SSL certificate error" msgstr "Erro de certificado SSL" #: gajim/gui_interface.py:1005 gajim/gui_interface.py:1034 #: gajim/gui_interface.py:1055 gajim/notify.py:192 gajim/notify.py:276 msgid "File Transfer Completed" msgstr "Transferência do arquivo completa" #: gajim/gui_interface.py:1009 gajim/gui_interface.py:1038 #: gajim/gui_interface.py:1059 gajim/notify.py:193 gajim/notify.py:277 msgid "File Transfer Stopped" msgstr "Transferência do arquivo parada" #: gajim/gui_interface.py:1013 #, fuzzy msgid "File Transfer Failed" msgstr "Transferência de arquivos" #: gajim/gui_interface.py:1035 #, fuzzy, python-format msgid "%(filename)s received from %(name)s." msgstr "Transferência de arquivo de %(filename)s de %(name)s parou." #: gajim/gui_interface.py:1039 #, python-format msgid "File transfer of %(filename)s from %(name)s stopped." msgstr "Transferência de arquivo de %(filename)s de %(name)s parou." #: gajim/gui_interface.py:1043 #, fuzzy, python-format msgid "File transfer of %(filename)s from %(name)s failed." msgstr "Transferência de arquivo de %(filename)s de %(name)s parou." #: gajim/gui_interface.py:1056 #, python-format msgid "You successfully sent %(filename)s to %(name)s." msgstr "Você enviou com sucesso o %(filename)s para %(name)s." #: gajim/gui_interface.py:1060 #, python-format msgid "File transfer of %(filename)s to %(name)s stopped." msgstr "Transferência de arquivo de %(filename)s para %(name)s parado." #: gajim/gui_interface.py:1064 #, fuzzy, python-format msgid "File transfer of %(filename)s to %(name)s failed." msgstr "Transferência de arquivo de %(filename)s para %(name)s parado." #: gajim/gui_interface.py:1177 msgid "Username Conflict" msgstr "Conflito de nome de usuário" #: gajim/gui_interface.py:1178 msgid "Please type a new username for your local account" msgstr "Por favor digite um novo nome de usuário para sua conta local" #: gajim/gui_interface.py:1201 msgid "Resource Conflict" msgstr "Conflito de recurso" #: gajim/gui_interface.py:1202 msgid "" "You are already connected to this account with the same resource. Please " "type a new one" msgstr "" "Você já está conectado a essa conta com o mesmo recurso. Por favor digite um " "novo" #: gajim/gui_interface.py:1259 #, python-format msgid "%s wants to start a voice chat." msgstr "%s quer iniciar uma conversa com voz." #: gajim/gui_interface.py:1261 msgid "Voice Chat Request" msgstr "Solicitação de conversa com voz" #: gajim/gui_interface.py:1329 gajim/gtk/account_wizard.py:314 msgid "Certificate Already in File" msgstr "Certificado já está no arquivo" #: gajim/gui_interface.py:1330 gajim/gtk/account_wizard.py:315 #, python-format msgid "This certificate is already in file %s, so it's not added again." msgstr "" "Este certificado já está no arquivo %s, então, ele não será adicionado " "novamente." #: gajim/gui_interface.py:1351 #, fuzzy, python-format msgid "The authenticity of the %s certificate could be invalid" msgstr "A autenticidade do certificado %s pode ser inválida." #: gajim/gui_interface.py:1354 #, python-format msgid "" "\n" "Unknown SSL error: %d" msgstr "" "\n" "Erro de SSL desconhecido: %d" #: gajim/gui_interface.py:1356 #, python-format msgid "" "\n" "SSL Error: %s" msgstr "" "\n" "Erro de SSL: %s" #: gajim/gui_interface.py:1361 msgid "Error verifying SSL certificate" msgstr "Erro ao verificar o certificado SSL" #: gajim/gui_interface.py:1362 #, fuzzy, python-format msgid "" "There was an error verifying the SSL certificate of your XMPP server: " "%(error)s\n" "Do you still want to connect to this server?" msgstr "" "Ocorreu um erro ao verificar o certificado SSL do seu servidor jabber: " "%(error)s\n" "Você ainda deseja conectar-se a este servidor?" #: gajim/gui_interface.py:1366 gajim/gtk/account_wizard.py:415 #, python-format msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA-1 fingerprint of the certificate:\n" "%(sha1)s\n" "SHA-256 fingerprint of the certificate:\n" "%(sha256)s" msgstr "" "Adicionar este certificado à lista de certificados confiáveis.\n" "Impressão digital SHA-1 do certificado:\n" "%(sha1)s\n" "Impressão digital SHA-256 do certificado:\n" "%(sha256)s" #: gajim/gui_interface.py:1372 msgid "Ignore this error for this certificate." msgstr "Ignorar este erro para este certificado." #: gajim/gui_interface.py:1380 #, python-format msgid "SSL Certificate Verification for %s" msgstr "Verificação de certificado SSL para %s" #: gajim/gui_interface.py:1385 msgid "Non Anonymous Server" msgstr "" #: gajim/gui_interface.py:1446 gajim/gui_interface.py:1488 #: gajim/gtk/dialogs.py:439 gajim/gtk/dialogs.py:454 msgid "Insecure connection" msgstr "Conexão não-segura" #: gajim/gui_interface.py:1447 msgid "" "You are about to send your password on an insecure connection. You should " "install PyOpenSSL to prevent that. Are you sure you want to do that?" msgstr "" "Você está enviando sua senha em uma conexão não-segura. Você deve instalar o " "PyOpenSSL para prevenir isto. Você tem certeza que quer fazer isso?" #: gajim/gui_interface.py:1450 gajim/gui_interface.py:1491 #: gajim/gtk/dialogs.py:445 msgid "Yes, I really want to connect insecurely" msgstr "Sim, eu realmente quero me conectar de modo não-seguro" #: gajim/gui_interface.py:1489 #, fuzzy msgid "" "You are about to send your password unencrypted on an insecure connection. " "Are you sure you want to do that?" msgstr "" "Você está prestes a enviar sua senha em um conexão não-criptografada. Tem " "certeza que quer fazer isto?" #: gajim/gui_interface.py:1758 gajim/gtk/join_groupchat.py:235 msgid "You can not join a group chat unless you are connected." msgstr "" "Você não pode ingressar em uma sala de conferência até que esteja conectado." #: gajim/gui_interface.py:1764 #, fuzzy msgid "JID is not a Groupchat" msgstr "Isto não é uma conferência" #: gajim/gui_interface.py:1895 msgid "This is not a group chat" msgstr "Isto não é uma conferência" #: gajim/gui_interface.py:1896 #, python-format msgid "" "%(room_jid)s is already in your roster. Please check if %(room_jid)s is a " "correct group chat name. If it is, delete it from your roster and try " "joining the group chat again." msgstr "" #: gajim/gui_interface.py:1921 gajim/dialog_messages.py:63 msgid "You cannot join a group chat while you are invisible" msgstr "Você não pode ingressar em uma sala enquanto estiver invisível" #: gajim/gui_interface.py:2280 msgid "Could not save your settings and preferences" msgstr "Impossível salvar suas preferências" #: gajim/gui_interface.py:2823 msgid "Passphrase Required" msgstr "Frase de acesso é obrigatória" #: gajim/gui_interface.py:2824 #, fuzzy, python-format msgid "Enter OpenPGP key passphrase for key %(keyid)s (account %(account)s)." msgstr "" "Entre com a frase de acesso da chave GPG %(keyid)s para conta (account " "%(account)s)." #: gajim/gui_interface.py:2841 #, fuzzy msgid "OpenPGP key expired" msgstr "A chave GPG expirou" #: gajim/gui_interface.py:2842 #, fuzzy, python-format msgid "" "Your OpenPGP key has expired, you will be connected to %s without OpenPGP." msgstr "Sua chave GPG expirou, você será conectado ao %s sem OpenPGP." #: gajim/gui_interface.py:2852 msgid "Wrong Passphrase" msgstr "Frase de acesso errada" #: gajim/gui_interface.py:2853 #, fuzzy msgid "Please retype your OpenPGP passphrase or press Cancel." msgstr "Por favor, reescreva sua frase secreta de GPG ou pressione Cancelar." #: gajim/search_window.py:107 msgid "Waiting for results" msgstr "Esperando resultados" #: gajim/search_window.py:145 gajim/search_window.py:223 msgid "Error in received dataform" msgstr "Erro no formulário de dados recebido" #: gajim/search_window.py:180 gajim/search_window.py:215 msgid "No result" msgstr "Sem resultados" #: gajim/htmltextview.py:532 #, fuzzy msgid "Loading" msgstr "Codificado" #: gajim/atom_window.py:123 #, python-format msgid "You have received new entries (and %d not displayed):" msgid_plural "You have received new entries (and %d not displayed):" msgstr[0] "Você recebeu novas entradas (e %d não exibida):" msgstr[1] "Você recebeu novas entradas (e %d não exibidas):" #: gajim/atom_window.py:128 gajim/data/gui/atom_entry_window.ui:20 msgid "You have received new entry:" msgstr "Você recebeu uma nova entrada:" #: gajim/adhoc_commands.py:125 gajim/data/gui/adhoc_commands_window.ui:9 msgid "Ad-hoc Commands - Gajim" msgstr "Comandos ad-hoc - Gajim" #: gajim/adhoc_commands.py:326 msgid "Cancel confirmation" msgstr "Cancelar confirmação" #: gajim/adhoc_commands.py:327 msgid "" "You are in process of executing command. Do you really want to cancel it?" msgstr "Você está na execução de um comando. Você realmente deseja cancelar?" #: gajim/adhoc_commands.py:394 gajim/adhoc_commands.py:417 msgid "Service sent malformed data" msgstr "O serviço enviou dados inválidos" #: gajim/adhoc_commands.py:402 msgid "Service changed the session identifier." msgstr "O serviço alterou o identificador da sessão." #: gajim/adhoc_commands.py:422 #, python-format msgid "%s - Ad-hoc Commands - Gajim" msgstr "%s - Comandos Ad-hoc - Gajim" #: gajim/adhoc_commands.py:516 msgid "Service returned an error." msgstr "O serviço retornou um erro." #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:265 #: gajim/common/connection_handlers_events.py:1130 msgid "Contact Signed In" msgstr "Contato conectou" #: gajim/notify.py:189 gajim/notify.py:209 gajim/notify.py:267 #: gajim/common/connection_handlers_events.py:1136 msgid "Contact Signed Out" msgstr "Contato desconectou" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:985 msgid "New Message" msgstr "Nova mensagem" #: gajim/notify.py:190 gajim/notify.py:216 gajim/notify.py:269 #: gajim/common/connection_handlers_events.py:979 msgid "New Single Message" msgstr "Nova mensagem" #: gajim/notify.py:190 gajim/notify.py:217 gajim/notify.py:270 #: gajim/common/connection_handlers_events.py:982 msgid "New Private Message" msgstr "Enviar mensagem privada" #: gajim/notify.py:191 gajim/notify.py:210 gajim/notify.py:281 #: gajim/common/connection_handlers_events.py:1124 msgid "Contact Changed Status" msgstr "O contato alterou seu status" #: gajim/notify.py:203 #, fuzzy msgid "Open" msgstr "OpenGPG" #: gajim/notify.py:270 msgid "New E-mail" msgstr "Novo e-mail" #: gajim/dialog_messages.py:32 #, fuzzy msgid "You can not start a new conversation unless you are connected." msgstr "" "Você não pode ingressar em uma sala de conferência até que esteja conectado." #: gajim/dialog_messages.py:36 gajim/dialog_messages.py:41 #: gajim/gtk/single_message.py:297 gajim/gtk/join_groupchat.py:211 #: gajim/gtk/account_wizard.py:231 msgid "Invalid JID" msgstr "JID inválido:" #: gajim/dialog_messages.py:42 gajim/gtk/single_message.py:298 #, python-format msgid "It is not possible to send a message to %s, this JID is not valid." msgstr "Não é possível enviar uma mensagem para %s, este não é um JID válido." #: gajim/dialog_messages.py:47 msgid "Unread events" msgstr "Eventos não lidos" #: gajim/dialog_messages.py:48 msgid "Read all pending events before removing this account." msgstr "Ler todos os eventos pendentes antes de remover esta conta." #: gajim/dialog_messages.py:52 msgid "You are currently connected to the server" msgstr "Você está atualmente conectado ao servidor" #: gajim/dialog_messages.py:53 msgid "To disable the account, you must be disconnected." msgstr "Para desativar esta conta, você deve estar desconectado." #: gajim/dialog_messages.py:57 #, fuzzy msgid "Invalid Form" msgstr "Sala inválida" #: gajim/dialog_messages.py:58 #, fuzzy msgid "The form is not filled correctly." msgstr "O apelido possui caracteres não permitidos." #: gajim/dialog_messages.py:62 gajim/common/helpers.py:292 msgid "Invisible" msgstr "Invisível" #: gajim/dialog_messages.py:67 msgid "A connection is not available" msgstr "Uma conexão não está disponível" #: gajim/dialog_messages.py:68 msgid "Your message can not be sent until you are connected." msgstr "Sua mensagem não pode ser enviada até que esteja conectado." #: gajim/dialog_messages.py:72 #, fuzzy msgid "JID already in list" msgstr "Jabber ID já existente na lista" #: gajim/dialog_messages.py:73 #, fuzzy msgid "The JID you entered is already in the list. Choose another one." msgstr "O Jabber ID que você forneceu já está na lista. Escolha outro." #: gajim/dialog_messages.py:77 msgid "Invalid answer" msgstr "Resposta inválida" #: gajim/dialog_messages.py:78 #, python-format msgid "Transport %(name)s answered wrongly to register request: %(error)s" msgstr "" "O transporte %(name)s respondeu erroneamente à requisição de registro do " "pedido: %(error)s" #: gajim/dialog_messages.py:83 #, fuzzy msgid "Wrong Custom Hostname" msgstr "Usa nome de máquina/porta customizados" #: gajim/dialog_messages.py:84 #, python-format msgid "Wrong custom hostname \"%s\". Ignoring it." msgstr "Nome de host incorreto \"%s\". Ignorando." #: gajim/dialog_messages.py:88 msgid "Error while removing privacy list" msgstr "Erro ao remover lista de privacidade" #: gajim/dialog_messages.py:89 #, python-format msgid "" "Privacy list %s has not been removed. It is maybe active in one of your " "connected resources. Deactivate it and try again." msgstr "" "A lista de privacidade %s não foi removida. Ela pode estar ativa em um ou " "mais recursos conectados. Desative-os e tente novamente." #: gajim/dialog_messages.py:95 msgid "Invisibility not supported" msgstr "Sem suporte a invisibilidade" #: gajim/dialog_messages.py:96 #, python-format msgid "Account %s doesn't support invisibility." msgstr "A conta %s não suporta invisibilidade." #: gajim/dialog_messages.py:100 msgid "Unregister failed" msgstr "Falha ao cancelar registro" #: gajim/dialog_messages.py:101 #, python-format msgid "Unregistration with server %(server)s failed: %(error)s" msgstr "Cancelamento de registro com o servidor %(server)s falhou: %(error)s:" #: gajim/dialog_messages.py:105 msgid "Registration succeeded" msgstr "Registro realizado com sucesso" #: gajim/dialog_messages.py:106 #, python-format msgid "Registration with agent %s succeeded" msgstr "Registro com o agente %s completado com sucesso" #: gajim/dialog_messages.py:110 gajim/gtk/service_registration.py:216 msgid "Registration failed" msgstr "Falha ao registrar" #: gajim/dialog_messages.py:111 #, python-format msgid "" "Registration with agent %(agent)s failed with error %(error)s: %(error_msg)s" msgstr "" "Registro com o agente %(agent)s falhou com erro %(error)s: %(error_msg)s" #: gajim/dialog_messages.py:116 #, fuzzy msgid "Unable to join Groupchat" msgstr "Impossível ingressar na sala" #: gajim/dialog_messages.py:121 msgid "GStreamer error" msgstr "" #: gajim/dialog_messages.py:122 #, python-format msgid "" "Error: %(error)s\n" "Debug: %(debug)s" msgstr "" "Erro: %(error)s\n" "Depuração: %(debug)s" #: gajim/dialog_messages.py:126 msgid "Wrong host" msgstr "Servidor errado" #: gajim/dialog_messages.py:127 msgid "Invalid local address? :-O" msgstr "Endereço local inválido? :-O" #: gajim/dialog_messages.py:131 msgid "Avahi error" msgstr "Erro do Avahi" #: gajim/dialog_messages.py:132 #, python-format msgid "" "%s\n" "Link-local messaging might not work properly." msgstr "" "%s\n" "Mensagens link-local podem não funcionar adequadamente." #: gajim/dialog_messages.py:136 gajim/dialog_messages.py:141 #, fuzzy msgid "Could not request upload slot" msgstr "Impossível iniciar o serviço local" #: gajim/dialog_messages.py:142 msgid "Got unexpected response from server (see log)" msgstr "" #: gajim/dialog_messages.py:146 gajim/dialog_messages.py:151 #, fuzzy msgid "Could not open file" msgstr "A imagem não pode ser carregada" #: gajim/dialog_messages.py:147 msgid "Exception raised while opening file (see log)" msgstr "" #: gajim/dialog_messages.py:156 msgid "Unsecure" msgstr "" #: gajim/dialog_messages.py:157 #, fuzzy msgid "Server returned unsecure transport (HTTP)" msgstr "O serviço retornou um erro." #: gajim/dialog_messages.py:161 #, fuzzy msgid "Could not upload file" msgstr "A imagem não pode ser carregada" #: gajim/dialog_messages.py:162 #, python-format msgid "HTTP response code from server: %s" msgstr "" #: gajim/dialog_messages.py:166 msgid "Upload Error" msgstr "" #: gajim/dialog_messages.py:171 #, fuzzy msgid "Encryption Error" msgstr "Criptografia habilitada" #: gajim/dialog_messages.py:172 #, fuzzy msgid "For the chosen encryption there is no encryption method available" msgstr "Uma conexão não está disponível" #: gajim/dialog_messages.py:176 #, fuzzy msgid "Avatar upload failed" msgstr "Publicação do vCard falhou" #: gajim/gajim_remote.py:55 gajim/common/exceptions.py:70 msgid "D-Bus is not present on this machine or python module is missing" msgstr "" "O D-Bus não está presente nesta máquina ou o módulo do Python está faltando" #: gajim/gajim_remote.py:77 msgid "Shows a help on specific command" msgstr "Mostra uma ajuda para um comando específico" #: gajim/gajim_remote.py:80 msgid "command" msgstr "comando" #: gajim/gajim_remote.py:81 msgid "show help on command" msgstr "exibir ajuda no comando" #: gajim/gajim_remote.py:85 #, fuzzy msgid "Lists all contacts in roster, one for each line" msgstr "" "Exibir uma lista de todos os contatos na lista. Cada contato aparecerá em " "uma linha separada" #: gajim/gajim_remote.py:87 gajim/gajim_remote.py:102 gajim/gajim_remote.py:112 #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 gajim/gajim_remote.py:170 #: gajim/gajim_remote.py:200 gajim/gajim_remote.py:209 #: gajim/gajim_remote.py:216 #, fuzzy msgid "?CLI:account" msgstr "conta" #: gajim/gajim_remote.py:87 msgid "show only contacts of the given account" msgstr "exibir somente os contatos desta conta" #: gajim/gajim_remote.py:93 msgid "Prints a list of registered accounts" msgstr "Imprimir uma lista das contas registradas" #: gajim/gajim_remote.py:97 msgid "Changes the status of account(s)" msgstr "Mudar o status da conta ou das contas" #: gajim/gajim_remote.py:100 #, fuzzy msgid "?CLI:status" msgstr "status" #: gajim/gajim_remote.py:100 #, fuzzy msgid "" "one of: offline, online, chat, away, xa, dnd, invisible. If not set, use " "account's previous status" msgstr "" "um desses: desconectado, conectado, bate-papo, inativo, fora, np, invisível " #: gajim/gajim_remote.py:101 gajim/gajim_remote.py:123 #: gajim/gajim_remote.py:137 gajim/gajim_remote.py:148 #, fuzzy msgid "?CLI:message" msgstr "mensagem" #: gajim/gajim_remote.py:101 msgid "status message" msgstr "mensagem de status" #: gajim/gajim_remote.py:102 msgid "" "change status of account \"account\". If not specified, try to change status " "of all accounts that have \"sync with global status\" option set" msgstr "" "mudar status da conta \"account\". Se não especificado, tentará mudar o " "status de todas as contas existentes com a opção \"sincronizar com status " "global\" marcada" #: gajim/gajim_remote.py:108 #, fuzzy msgid "Changes the priority of account(s)" msgstr "Mudar a prioridade da conta ou das contas" #: gajim/gajim_remote.py:110 #, fuzzy msgid "?CLI:priority" msgstr "prioridade:" #: gajim/gajim_remote.py:110 msgid "priority you want to give to the account" msgstr "prioridade que deseja dar para a conta" #: gajim/gajim_remote.py:112 msgid "" "change the priority of the given account. If not specified, change status of " "all accounts that have \"sync with global status\" option set" msgstr "" "mudar status da conta. Se não especificado, tentará mudar o status de todas " "as contas existentes com a opção \"sincronizar com status global\" marcada" #: gajim/gajim_remote.py:118 msgid "" "Sends new chat message to a contact in the roster. Both OpenPGP key and " "account are optional. If you want to set only 'account', without 'OpenPGP " "key', just set 'OpenPGP key' to ''." msgstr "" "Envia nova mensagem para um contato na lista. Ambas chave OpenPGP e conta " "são opcionais. Se você quer configurar somente a 'conta', sem a 'chave " "OpenPGP', apenas configure a 'chave OpenPGP' para ''." #: gajim/gajim_remote.py:122 gajim/gajim_remote.py:135 msgid "JID of the contact that will receive the message" msgstr "JID do contato que irá receber a mensagem" #: gajim/gajim_remote.py:123 gajim/gajim_remote.py:137 #: gajim/gajim_remote.py:148 msgid "message contents" msgstr "conteúdos da mensagem" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "PGP key" msgstr "" #: gajim/gajim_remote.py:124 gajim/gajim_remote.py:138 msgid "if specified, the message will be encrypted using this public key" msgstr "" "se especificada, a mensagem será criptografada usando esta chave pública" #: gajim/gajim_remote.py:126 gajim/gajim_remote.py:140 #: gajim/gajim_remote.py:149 msgid "if specified, the message will be sent using this account" msgstr "se especificada, a mensagem será enviada usando esta conta" #: gajim/gajim_remote.py:131 msgid "" "Sends a chat message to someone on your roster. Optionally with OpenPGP key " "and account. If you want to only set the latter, set OpenPGP key to \"\"." msgstr "" "Envia nova mensagem para um contato na lista. A chave OpenPGP e a conta são " "opcionais. Se você quer configurar somente a 'conta', sem a 'chave OpenPGP', " "apenas configure a 'chave OpenPGP' para ''." #: gajim/gajim_remote.py:136 msgid "subject" msgstr "assunto" #: gajim/gajim_remote.py:136 msgid "message subject" msgstr "assunto da mensagem" #: gajim/gajim_remote.py:145 msgid "Sends new message to a groupchat you've joined." msgstr "" "Envia uma nova messagem para uma conferência em que você tiver ingressado." #: gajim/gajim_remote.py:147 msgid "JID of the room that will receive the message" msgstr "O JID do contato que receberá a mensagem" #: gajim/gajim_remote.py:154 msgid "Gets detailed info on a contact" msgstr "Informações detalhadas do contato" #: gajim/gajim_remote.py:156 gajim/gajim_remote.py:169 #: gajim/gajim_remote.py:199 msgid "JID of the contact" msgstr "JID do contato" #: gajim/gajim_remote.py:160 msgid "Gets detailed info on a account" msgstr "Informações detalhadas do contato" #: gajim/gajim_remote.py:162 msgid "Name of the account" msgstr "Nome da conta" #: gajim/gajim_remote.py:166 msgid "Sends file to a contact" msgstr "Enviar arquivo para um contato" #: gajim/gajim_remote.py:168 msgid "file" msgstr "arquivo" #: gajim/gajim_remote.py:168 msgid "File path" msgstr "Caminho do arquivo" #: gajim/gajim_remote.py:170 msgid "if specified, file will be sent using this account" msgstr "se especificada, arquivo irá ser enviado usando esta conta" #: gajim/gajim_remote.py:175 msgid "Lists all preferences and their values" msgstr "Lista todas as preferências e seus valores" #: gajim/gajim_remote.py:179 msgid "Sets value of 'key' to 'value'." msgstr "Ajusta o valor da 'chave' ao 'valor '." #: gajim/gajim_remote.py:181 msgid "key=value" msgstr "chave=valor" #: gajim/gajim_remote.py:181 #, fuzzy msgid "'key' is the name of the preference, 'value' is what to set it to" msgstr "'chave' é o nome de preferência, 'valor' é o valor para ajustá-la" #: gajim/gajim_remote.py:186 msgid "Deletes a preference item" msgstr "Deleta um item de preferência" #: gajim/gajim_remote.py:188 msgid "key" msgstr "chave" #: gajim/gajim_remote.py:188 msgid "name of the preference to be deleted" msgstr "nome da preferência a ser deletada" #: gajim/gajim_remote.py:192 msgid "Writes the current state of Gajim preferences to the .config file" msgstr "Escreve o estado atual das preferências do Gajim em um arquivo .config" #: gajim/gajim_remote.py:197 msgid "Removes contact from roster" msgstr "Remover contato da lista" #: gajim/gajim_remote.py:200 msgid "if specified, contact is taken from the contact list of this account" msgstr "se especificado, o contato é feito da lista de contatos desta conta" #: gajim/gajim_remote.py:207 msgid "Returns current status (the global one unless account is specified)" msgstr "Retorna o status atual (global a menos que o cliente for especificado)" #: gajim/gajim_remote.py:214 msgid "" "Returns current status message (the global one unless account is specified)" msgstr "" "Retorna a mensagem de status atual (global a menos que a conta for " "especificada)" #: gajim/gajim_remote.py:221 msgid "Returns number of unread messages" msgstr "Retorna o número das mensagens não lidas" #: gajim/gajim_remote.py:226 msgid "Sends custom XML" msgstr "Envia XML personalizado" #: gajim/gajim_remote.py:228 msgid "XML to send" msgstr "XML a enviar" #: gajim/gajim_remote.py:229 #, fuzzy msgid "" "Account to which the XML will be sent; if not specified, XML will be sent to " "all accounts" msgstr "" "A conta em que o XML será enviado; se não estiver especificado, será enviado " "para todas as contas" #: gajim/gajim_remote.py:235 #, fuzzy msgid "Change the avatar" msgstr "Alterar status" #: gajim/gajim_remote.py:237 #, fuzzy msgid "Picture to use" msgstr "Apelido a ser usado" #: gajim/gajim_remote.py:238 #, fuzzy msgid "" "Account in which the avatar will be set; if not specified, the avatar will " "be set for all accounts" msgstr "" "A conta em que o XML será enviado; se não estiver especificado, será enviado " "para todas as contas" #: gajim/gajim_remote.py:245 msgid "Check if Gajim is running" msgstr "Checar se o Gajim está rodando" #: gajim/gajim_remote.py:271 msgid "Missing argument \"contact_jid\"" msgstr "Argumento não informado \"contact_jid\"" #: gajim/gajim_remote.py:291 #, python-format msgid "" "'%s' is not in your roster.\n" "Please specify account for sending the message." msgstr "" "'%s' não está em sua lista.\n" "Por favor, especifique a conta para enviar a mensagem." #: gajim/gajim_remote.py:294 msgid "You have no active account" msgstr "Você não tem uma conta ativa" #: gajim/gajim_remote.py:342 msgid "It seems Gajim is not running. So you can't use gajim-remote." msgstr "" "Parece que o Gajim não está rodando. Então você não pode usar o gajim-remote." #: gajim/gajim_remote.py:369 #, python-format msgid "" "Usage: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" msgstr "" "Uso: %(basename)s %(command)s %(arguments)s \n" "\t %(help)s" #: gajim/gajim_remote.py:373 msgid "Arguments:" msgstr "Argumentos:" #: gajim/gajim_remote.py:377 #, python-format msgid "%s not found" msgstr "%s não encontrado" #: gajim/gajim_remote.py:383 #, python-format msgid "" "Usage:\n" " %s command [arguments]\n" "\n" "Command is one of:\n" msgstr "" "Uso:\n" " %s comando [argumentos]\n" "\n" "Comando é um dos seguintes:\n" #: gajim/gajim_remote.py:453 #, python-format msgid "" "Too many arguments. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Muitos argumentos. \n" "Digite \"%(basename)s help %(command)s\" para mais informações" #: gajim/gajim_remote.py:458 #, python-format msgid "" "Argument \"%(arg)s\" is not specified. \n" "Type \"%(basename)s help %(command)s\" for more info" msgstr "" "Argumento \"%(arg)s\" não está especificado. \n" "Digite\"%(basename)s help %(command)s\" para maiores informações" #: gajim/common/fuzzyclock.py:36 msgid "twelve" msgstr "doze" #: gajim/common/fuzzyclock.py:36 msgid "one" msgstr "um" #: gajim/common/fuzzyclock.py:36 msgid "two" msgstr "dois" #: gajim/common/fuzzyclock.py:36 msgid "three" msgstr "três" #: gajim/common/fuzzyclock.py:36 msgid "four" msgstr "quatro" #: gajim/common/fuzzyclock.py:37 msgid "five" msgstr "cinco" #: gajim/common/fuzzyclock.py:37 msgid "six" msgstr "seis" #: gajim/common/fuzzyclock.py:37 msgid "seven" msgstr "sete" #: gajim/common/fuzzyclock.py:37 msgid "eight" msgstr "oito" #: gajim/common/fuzzyclock.py:37 msgid "nine" msgstr "nove" #: gajim/common/fuzzyclock.py:37 msgid "ten" msgstr "dez" #: gajim/common/fuzzyclock.py:38 msgid "eleven" msgstr "onze" #: gajim/common/fuzzyclock.py:45 #, python-format msgid "%(0)s o'clock" msgstr "%(0)s horas" #: gajim/common/fuzzyclock.py:46 #, python-format msgid "five past %(0)s" msgstr "%(0)s e cinco" #: gajim/common/fuzzyclock.py:47 #, python-format msgid "ten past %(0)s" msgstr "%(0)s e dez" #: gajim/common/fuzzyclock.py:48 #, python-format msgid "quarter past %(0)s" msgstr "%(0)s e quinze" #: gajim/common/fuzzyclock.py:49 #, python-format msgid "twenty past %(0)s" msgstr "%(0)s e vinte" #: gajim/common/fuzzyclock.py:50 #, python-format msgid "twenty five past %(0)s" msgstr "%(0)s e vinte e cinco" #: gajim/common/fuzzyclock.py:51 #, python-format msgid "half past %(0)s" msgstr "%(0)s e meia" #: gajim/common/fuzzyclock.py:52 #, python-format msgid "twenty five to %(1)s" msgstr "vinte e cinco para as %(1)s" #: gajim/common/fuzzyclock.py:53 #, python-format msgid "twenty to %(1)s" msgstr "vinte para as %(1)s" #: gajim/common/fuzzyclock.py:54 #, python-format msgid "quarter to %(1)s" msgstr "quinze para as %(1)s" #: gajim/common/fuzzyclock.py:55 #, python-format msgid "ten to %(1)s" msgstr "dez para as %(1)s" #: gajim/common/fuzzyclock.py:56 #, python-format msgid "five to %(1)s" msgstr "cinco para %(1)s" #: gajim/common/fuzzyclock.py:57 #, python-format msgid "%(1)s o'clock" msgstr "%(1)s horas" #: gajim/common/fuzzyclock.py:61 gajim/common/fuzzyclock.py:69 msgid "Night" msgstr "Noite" #: gajim/common/fuzzyclock.py:62 msgid "Early morning" msgstr "Madrugada" #: gajim/common/fuzzyclock.py:63 msgid "Morning" msgstr "Manhã" #: gajim/common/fuzzyclock.py:64 msgid "Almost noon" msgstr "Quase meio-dia" #: gajim/common/fuzzyclock.py:65 msgid "Noon" msgstr "Meio-dia" #: gajim/common/fuzzyclock.py:66 msgid "Afternoon" msgstr "Tarde" #: gajim/common/fuzzyclock.py:67 msgid "Evening" msgstr "Noite" #: gajim/common/fuzzyclock.py:68 msgid "Late evening" msgstr "Tarde da noite" #: gajim/common/fuzzyclock.py:73 msgid "Start of week" msgstr "Começo da semana" #: gajim/common/fuzzyclock.py:74 gajim/common/fuzzyclock.py:75 #: gajim/common/fuzzyclock.py:76 msgid "Middle of week" msgstr "Meio da semana" #: gajim/common/fuzzyclock.py:77 msgid "End of week" msgstr "Fim da semana" #: gajim/common/fuzzyclock.py:78 gajim/common/fuzzyclock.py:79 msgid "Weekend!" msgstr "Final de semana!" #: gajim/common/logger.py:142 gajim/common/logger.py:147 #, python-format msgid "%s is a directory but should be a file" msgstr "%s é um diretório, mas deveria ser um arquivo" #: gajim/common/logger.py:167 #, fuzzy, python-format msgid "Creating %s" msgstr "Excluindo %s" #. #destroyroom #: gajim/common/connection_handlers_events.py:367 msgid "Room has been destroyed" msgstr "A sala foi excluída" #: gajim/common/connection_handlers_events.py:375 #, python-format msgid "You can join this room instead: %s" msgstr "Você pode entrar nessa sala ao invés: %s" #: gajim/common/connection_handlers_events.py:598 #, python-format msgid "Unknown SSL error: %d" msgstr "Erro de SSL desconhecido: %d" #: gajim/common/connection_handlers_events.py:990 #, fuzzy, python-format msgid "New message from %(nickname)s" msgid_plural "%(n_msgs)i unread messages from %(nickname)s" msgstr[0] "Nova mensagem de %(nickname)s" msgstr[1] "Nova mensagem de %(nickname)s" #: gajim/common/connection_handlers_events.py:1118 #, python-format msgid "%(nick)s Changed Status" msgstr "%(nick)s alterou seu status" #: gajim/common/connection_handlers_events.py:1126 #, python-format msgid "%(nickname)s Signed In" msgstr "%(nickname)s conectou" #: gajim/common/connection_handlers_events.py:1132 #, python-format msgid "%(nickname)s Signed Out" msgstr "%(nickname)s desconectou" #: gajim/common/contacts.py:427 msgid "Not in roster" msgstr "Fora da lista" #: gajim/common/config.py:80 msgid "" "Show desktop notification even when a chat window is opened for this contact " "and does not have focus" msgstr "" #: gajim/common/config.py:81 msgid "Play sound when user is busy" msgstr "Tocar som quando usuário estiver ocupado" #: gajim/common/config.py:83 msgid "Show only online and free for chat contacts in roster." msgstr "Exibir somente contatos disponíveis e livres para conversa na lista." #: gajim/common/config.py:86 msgid "Time in minutes, after which your status changes to away." msgstr "Tempo em minutos, depois do qual seu status muda para a afastado." #: gajim/common/config.py:87 msgid "$S (Away as a result of being idle more than $T min)" msgstr "$S (Afastado em conseqüência de estar inativo há mais de $T min)" #: gajim/common/config.py:87 #, fuzzy msgid "$S will be replaced by current status message, $T by autoawaytime." msgstr "" "$S será substituída pela mensagem de status atual, $T pelo tempo de ausência " "automática." #: gajim/common/config.py:89 msgid "Time in minutes, after which your status changes to not available." msgstr "Tempo em minutos, depois do qual seu status muda para não disponível." #: gajim/common/config.py:90 msgid "$S (Not available as a result of being idle more than $T min)" msgstr "$S (Não disponível em conseqüência de estar inativo há mais de $T min)" #: gajim/common/config.py:90 #, fuzzy msgid "$S will be replaced by current status message, $T by autoxatime." msgstr "" "$S será substituída pela mensagem de status atual, $T pelo tempo de " "indisponibilidade automática." #: gajim/common/config.py:93 msgid "" "When to show notification area icon. Can be 'never', 'on_event', 'always'." msgstr "" "Quando exibir um ícone na área de notificação. Pode ser \"nunca\", com " "\"eventos\" ou \"sempre\"." #: gajim/common/config.py:94 msgid "Allow to hide the roster window even if the tray icon is not shown." msgstr "" #: gajim/common/config.py:99 #, fuzzy msgid "Contact signed in notification color." msgstr "Mo_strar somente na lista" #: gajim/common/config.py:100 #, fuzzy msgid "Contact signout notification color" msgstr "Mo_strar somente na lista" #: gajim/common/config.py:101 #, fuzzy msgid "New message notification color." msgstr "Pré-visualizar novas mensagens em uma janela popup?" #: gajim/common/config.py:102 #, fuzzy msgid "File transfer request notification color." msgstr "Solicitação de transferência de arquivos" #: gajim/common/config.py:103 #, fuzzy msgid "File transfer error notification color." msgstr "Transferência de arquivos cancelada" #: gajim/common/config.py:104 #, fuzzy msgid "File transfer complete or stopped notification color." msgstr "Exibir um alerta visual quanto uma transferência de arquivo terminar" #: gajim/common/config.py:105 #, fuzzy msgid "Groupchat invitation notification color" msgstr "Convite para conferência" #: gajim/common/config.py:106 #, fuzzy msgid "Background color of status changed notification" msgstr "Cor de fundo dos contatos quando eles simplesmente conectarem." #: gajim/common/config.py:107 msgid "Other dialogs color." msgstr "" #: gajim/common/config.py:108 msgid "" "List (space separated) of rows (accounts and groups) that are collapsed." msgstr "" "Lista (separada por espaços) de linhas (contas e grupos) que estão agrupados." #: gajim/common/config.py:109 msgid "default" msgstr "padrão" #: gajim/common/config.py:115 msgid "Language used by speller" msgstr "Idioma usado pelo corretor ortográfico" #: gajim/common/config.py:116 msgid "" "'always' - print time for every message.\n" "'sometimes' - print time every print_ichat_every_foo_minutes minute.\n" "'never' - never print time." msgstr "" "'sempre' - exibir hora para cada mensagem.\n" "'às vezes' - exibir hora a cada print_ichat_every_foo_minutes minutos.\n" "'nunca' - nunca exibir a hora." #: gajim/common/config.py:117 msgid "" "Print time in chats using Fuzzy Clock. Value of fuzziness from 1 to 4, or 0 " "to disable fuzzyclock. 1 is the most precise clock, 4 the least precise one. " "This is used only if print_time is 'sometimes'." msgstr "" "Exibir a hora nas conversas usando relógio impreciso. O valor de imprecisão " "varia de 1 a 4, 0 desabilita a função. 1 é relógio mais preciso, 4 é o " "menos. Isto é usado apenas se o valor de print_time for 'às vezes'." #: gajim/common/config.py:119 msgid "When enabled, ASCII emojis will be converted to graphical emojis." msgstr "" #: gajim/common/config.py:121 msgid "Treat * / _ pairs as possible formatting characters." msgstr "Aproveite os pare * /_ como caracteres de formatação." #: gajim/common/config.py:122 #, fuzzy msgid "" "If true, do not remove */_ . So *abc* will be bold but with * * not removed." msgstr "" "Se verdadeiro, não remova */_. Assim *ABC* será negrito mas com * * não " "removido." #: gajim/common/config.py:125 msgid "" "Uses ReStructured text markup to send HTML, plus ascii formatting if " "selected. For syntax, see http://docutils.sourceforge.net/docs/ref/rst/" "restructuredtext.html (If you want to use this, install docutils)" msgstr "" "Usar marcação de texto ReStructured para HTML, mais formatação ASCII, se " "selecionada. Para informações sobre sintaxe, veja http://docutils." "sourceforge.net/docs/ref/rst/restructuredtext.html (Se você quiser usar " "isso, instale o docutils)" #: gajim/common/config.py:134 msgid "" "Character to add after nickname when using nick completion (tab) in group " "chat." msgstr "" "Caracter a adicionar ao apelido quando se estiver usando o recurso de " "completar apelido (tecla Tab) na conferência." #: gajim/common/config.py:135 msgid "" "Character to propose to add after desired nickname when desired nickname is " "used by someone else in group chat." msgstr "" "O caracter a ser proposto para adicionar ao final do apelido desejado quando " "ele já estiver sendo usado por outra pessoa na conferência." #: gajim/common/config.py:157 msgid "" "If true, Gajim will save roster position when hiding roster, and restore it " "when showing roster." msgstr "" #: gajim/common/config.py:163 msgid "Place the roster on the right in single window mode" msgstr "" #: gajim/common/config.py:169 msgid "" "This option let you customize timestamp that is printed in conversation. For " "exemple \"[%H:%M] \" will show \"[hour:minute] \". See python doc on " "strftime for full documentation: http://docs.python.org/lib/module-time.html" msgstr "" "Esta opção lhe permite personalizar o carimbo de tempo que é exibido na " "conversação. Por exemplo: \"[%H:%M]\" exibirá \"[hora:minuto]\". Procure por " "strftime na documentação do Python: http://docs.python.org/lib/module-time." "html" #: gajim/common/config.py:170 msgid "Characters that are printed before the nickname in conversations" msgstr "Os caracteres que são exibidos antes do apelido nas conversas" #: gajim/common/config.py:171 msgid "Characters that are printed after the nickname in conversations" msgstr "Os caracteres que são exibidos após o apelidos nas conversas" #: gajim/common/config.py:173 msgid "Add * and [n] in roster title?" msgstr "Adicionar * e [n] no título da lista?" #: gajim/common/config.py:174 #, fuzzy msgid "" "How many history messages should be restored when a chat tab/window is " "reopened?" msgstr "" "Quantas linhas lembrar da conversação anterior quando uma aba/janela de bate-" "papo for reaberta." #: gajim/common/config.py:175 msgid "How far back in time (minutes) history is restored. -1 means no limit." msgstr "" #: gajim/common/config.py:176 #, fuzzy msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit" msgstr "" "Quantas linhas requisitar ao servidor quando entrar em uma conferência." #: gajim/common/config.py:177 #, fuzzy msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit" msgstr "" "Quantos minutos esperar para requisitar registros quando entrar em uma sala." #: gajim/common/config.py:178 msgid "" "How many seconds to wait before trying to autorejoin to a conference you are " "being disconnected from. Set to 0 to disable autorejoining." msgstr "" "Quantos segundos aguardar antes de tentar reconectar a uma conferência que " "você foi desconectado. Definir para 0 irá desabilitar a tentativa de re-" "conexão (autorejoining)." #: gajim/common/config.py:179 msgid "Should autorejoin be activated when kicked from a conference?" msgstr "" #: gajim/common/config.py:180 msgid "" "Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ " "Client default behaviour)." msgstr "" "Enviar a mensagem com Ctrl+Enter e criar uma nova linha com Enter " "(comportamento padrão do cliente ICQ da Mirabilis)." #: gajim/common/config.py:182 msgid "How many lines to store for Ctrl+KeyUP." msgstr "Quantas linhas armazenar com Ctrl+Acima." #: gajim/common/config.py:185 #, fuzzy, python-format msgid "" "Either custom URL with %%s in it where %%s is the word/phrase or " "'WIKTIONARY' which means use Wikitionary." msgstr "" "Uma ou outra URL costuma vir com %s onde %s é a palvra/frase ou em " "'WIKTIONARY' que significam o uso wiktionary." #: gajim/common/config.py:188 msgid "If checked, Gajim can be controlled remotely using gajim-remote." msgstr "" "Se verificado, Gajim pode ser remotamente controlado usando gajim-remoto." #: gajim/common/config.py:189 msgid "" "Sent chat state notifications. Can be one of all, composing_only, disabled." msgstr "" "Notificações de estado de conversa enviados. Pode ser one of all, " "composing_only, disabled." #: gajim/common/config.py:190 msgid "" "Displayed chat state notifications in chat windows. Can be one of all, " "composing_only, disabled." msgstr "" "Notificações de estado de conversa exibidos nas janelas de conversa. Pode " "ser one of all, composing_only, disabled." #: gajim/common/config.py:192 msgid "" "When not printing time for every message (print_time==sometimes), print it " "every x minutes." msgstr "" "Quando não estiver exibindo a hora para cada mensagem (print_time == " "simetimes), exibi-lo a cada x minutos." #: gajim/common/config.py:193 msgid "Ask before closing a group chat tab/window." msgstr "Perguntar antes de fechar um aba ou janela de conferência." #: gajim/common/config.py:194 #, fuzzy msgid "" "Always ask for confirmation before closing groupchats with any of the JIDs " "on this space separated list." msgstr "" "Sempre perguntar antes de fechar um aba/janela nesta lista separada por " "espaço de JID's de conferências." #: gajim/common/config.py:195 #, fuzzy msgid "" "Never ask for confirmation before closing groupchats with any of the JIDs on " "this space separated list." msgstr "" "Nunca perguntar antes de fechar uma aba/janela de conferência nesta lista " "separada por espaço de salas separadas por jids." #: gajim/common/config.py:196 #, fuzzy msgid "" "Ask before closing tabbed chat window if there are controls that can lose " "data (chat, private chat, groupchat that will not be minimized)" msgstr "" "Perguntar antes de fechar uma aba de janela de conversa se ela puder perder " "dados (conversa, conversa privada, conferências que não podem ser " "minimizadas)" #: gajim/common/config.py:199 #, fuzzy msgid "" "Comma separated list of sent hosts, in addition of local interfaces, for " "File Transfer in case of address translation/port forwarding." msgstr "" "Lista separada por vírgula dos servidores que nós enviaremos, em adição às " "interfaces locais, para Transferência de Arquivo no caso de tradução de " "endereço/encaminhamento de porta." #: gajim/common/config.py:200 msgid "IEC standard says KiB = 1024 bytes, KB = 1000 bytes." msgstr "Padrão da IEC diz que KiB = 1024 bytes e KB = 1000 bytes." #: gajim/common/config.py:202 #, fuzzy msgid "Notify of events in the notification area." msgstr "Notificar os eventos no ícone da bandeja do sistema." #: gajim/common/config.py:203 msgid "" "If False, Gajim will display a static event icon instead of the blinking " "status icon in the notification area when notifying on event." msgstr "" #: gajim/common/config.py:209 msgid "Show tab when only one conversation?" msgstr "Exibir aba quando tiver apenas uma bate papo?" #: gajim/common/config.py:210 msgid "Show tabbed notebook border in chat windows?" msgstr "Exibir borda de caderno tabulada nas janelas de conversa?" #: gajim/common/config.py:211 msgid "Show close button in tab?" msgstr "Exibir botão de fechar na aba?" #: gajim/common/config.py:224 msgid "Preview new messages in notification popup?" msgstr "Pré-visualizar novas mensagens em uma janela popup?" #: gajim/common/config.py:227 msgid "" "A semicolon-separated list of words that will be highlighted in group chats." msgstr "" "Uma lista separada por ponto-e-vírgula das palavras que serão destacadas nas " "conferências." #: gajim/common/config.py:228 #, fuzzy msgid "" "If true, quits Gajim when X button of Window Manager is clicked. This " "setting is taken into account only if notification icon is used." msgstr "" "Se verdadeiro, o Gajim sairá quando o botão sair da janela for clicado. Esta " "opção só faz sentido quando a opção trayicon está sendo usada." #: gajim/common/config.py:229 msgid "" "If true, Gajim hides the Roster window on pressing the X button instead of " "minimizing into the Dock." msgstr "" #: gajim/common/config.py:230 #, fuzzy msgid "" "If true, Gajim will display an icon on each tab containing unread messages. " "Depending on the theme, this icon may be animated." msgstr "" "Se verdadeiro, Gajim exibirá um ícone para cada aba contendo mensagens não " "lidas. Dependendo do tema, este ícone pode ser animado." #: gajim/common/config.py:231 #, fuzzy msgid "" "If true, Gajim will display the status message, if not empty, for every " "contact under the contact name in roster window." msgstr "" "Se verdadeiro, o Gajim indicará a mensagem de status, se não estiver vazia, " "para cada contato sob o nome do contato na janela da lista." #: gajim/common/config.py:237 msgid "Define the position of the avatar in roster. Can be left or right" msgstr "Define a posição do avatar na lista. Pode ser esquerda ou direita" #: gajim/common/config.py:238 #, fuzzy msgid "" "If False, Gajim will no longer print status line in chats when a contact " "changes their status and/or their status message." msgstr "" "Se falso, você não verá por mais muito tempo a linha de status nas conversas " "quando um contato alterar seu status e/ou sua mensagem de status." #: gajim/common/config.py:239 #, fuzzy msgid "" "Can be \"none\", \"all\" or \"in_and_out\". If \"none\", Gajim will no " "longer print status line in groupchats when a member changes their status " "and/or their status message. If \"all\" Gajim will print all status " "messages. If \"in_and_out\", Gajim will only print FOO enters/leaves group " "chat." msgstr "" "pode ser \"none\" (nenhum), \"all\" (todos) ou \"in_and_out\" (dentro e " "fora). Se for \"none\", o Gajim não exibirá mais o status nas conferências " "quando um membro alterar seu status e/ou sua mensagem de status. Se for \"all" "\" o Gajim exibirá todas as mensagens de status. Se for \"in_and_out\" o " "Gajim só exibirá FOO entradas/saídas em conferências." #: gajim/common/config.py:241 msgid "Log XHTML messages instead of plain text messages." msgstr "" #: gajim/common/config.py:242 #, fuzzy msgid "" "If true, restored messages will use a smaller font than the default one." msgstr "" "Se Verdadeiro, as mensagens restauradas usarão uma fonte menor que o padrão." #: gajim/common/config.py:243 msgid "Don't show avatar for the transport itself." msgstr "Não exibir o avatar para o próprio transporte." #: gajim/common/config.py:244 msgid "Don't show roster in the system taskbar." msgstr "Não exibir a lista na bandeja do sistema." #: gajim/common/config.py:245 #, fuzzy msgid "" "If true, make the window flash (the default behaviour in most Window " "Managers) when holding pending events." msgstr "" "Se Verdadeiro e as versões do GTK+ e PyGTK instaladas são menores que 2.8, " "faz a janela piscar (o comportamento padrão na maioria dos Gerenciadores de " "Janela) quando esperam eventos pendentes." #: gajim/common/config.py:249 #, fuzzy msgid "" "Controls the window where new messages are placed.\n" "'always' - All messages are sent to a single window.\n" "'always_with_roster' - Like 'always' but the messages are in a single window " "along with the roster.\n" "'never' - All messages get their own window.\n" "'peracct' - Messages for each account are sent to a specific window.\n" "'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a " "specific window." msgstr "" "Controlar a janela onde novas mensagens são colocadas.\n" "'always' - Todas as mensagens são enviadas para uma única janela.\n" "'always_with_roster' - Tal como 'always' mas as mensagens estão em uma " "janela simples junto com a lista.\n" "'never' - Todas as mensagens recebem sua própria janela.\n" "'peracct' - As mensagens para cada conta são enviadas a uma janela " "específica.\n" "'pertype' - Cada tipo de mensagem (ex. bate-papo vs. conferência) são " "enviadas para uma janela específica." #: gajim/common/config.py:250 msgid "" "Show roster on startup.\n" "'always' - Always show roster.\n" "'never' - Never show roster.\n" "'last_state' - Restore the last state roster." msgstr "" #: gajim/common/config.py:251 msgid "If False, you will no longer see the avatar in the chat window." msgstr "" "Se falso, você não verá por muito tempo o avatar na janela do bate-papo." #: gajim/common/config.py:252 #, fuzzy msgid "If true, pressing the escape key closes a tab/window." msgstr "Se verdadeiro, pressionando a tecla Esc fecha a aba/janela." #: gajim/common/config.py:253 msgid "Hides the banner in a group chat window" msgstr "Esconder o banner na janela de conferência" #: gajim/common/config.py:254 msgid "Hides the banner in two persons chat window" msgstr "Esconder o banner na janela de conversa para duas pessoas" #: gajim/common/config.py:255 msgid "Hides the group chat occupants list in group chat window." msgstr "Esconder a lista dos ocupantes da sala na janela da conferência." #: gajim/common/config.py:256 msgid "" "In a chat, show the nickname at the beginning of a line only when it's not " "the same person talking than in previous message." msgstr "" "Em uma conferência, exibir o apelido no começo da linha apenas quando a " "mensagem atual não for da mesma pessoa que mandou a última." #: gajim/common/config.py:257 msgid "Indentation when using merge consecutive nickname." msgstr "Usar identação ao mesclar apelidos consecutivos." #: gajim/common/config.py:258 msgid "" "List of colors, separated by \":\", that will be used to color nicknames in " "group chats." msgstr "" "A lista de cores, separadas por \":\", que serão usadas para colorir os " "apelidos nas salas de conferência." #: gajim/common/config.py:259 msgid "Ctrl-Tab go to next composing tab when none is unread." msgstr "" "Quando nenhum aba tiver uma mensagem não lida, Ctrl + Tab vai para a próxima " "aba." #: gajim/common/config.py:260 #, fuzzy msgid "" "Show the confirm metacontacts creation dialog or not? Empty string means " "never show the dialog." msgstr "" "Devemos exibir o diálogo de confirmação de metacontatos ou não? Uma string " "vazia significa que nós nunca devemos exibir o diálogo." #: gajim/common/config.py:261 #, fuzzy msgid "" "Show the confirm block contact dialog or not? Empty string means never show " "the dialog." msgstr "" "Devemos exibir o diálogo de confirmação de metacontatos ou não? Uma string " "vazia significa que nós nunca devemos exibir o diálogo." #: gajim/common/config.py:262 #, fuzzy msgid "" "Show the confirm custom status dialog or not? Empty string means never show " "the dialog." msgstr "" "Devemos exibir o diálogo de confirmação status customizados ou não? Uma " "string vazia significa que nós nunca devemos exibir o diálogo." #: gajim/common/config.py:263 #, fuzzy msgid "" "If true, you will be able to set a negative priority to your account in " "account modification window. BE CAREFUL, when you are logged in with a " "negative priority, you will NOT receive any message from your server." msgstr "" "Se Verdadeiro, você poderá especificar uma prioridade negativa para a sua " "conta na janela de modificação da conta. CUIDADO, quando você estiver " "autenticado com uma prioridade negativa, você NÃO poderá receber nenhuma " "mensagem do seu servidor." #: gajim/common/config.py:264 #, fuzzy msgid "" "If true, Gajim will show number of online and total contacts in account and " "group rows." msgstr "" "Se Verdadeiro, o Gajim exibirá o número de contatos online e do total de " "contatos nas linha de conta e grupo." #: gajim/common/config.py:265 msgid "" "Can be empty, 'chat' or 'normal'. If not empty, treat all incoming messages " "as if they were of this type" msgstr "" "Pode ser vazio, 'chat' ou 'normal'. Se for vazio, trata todas as mensagens " "recebidas como se elas fossem do tipo especificado" #: gajim/common/config.py:266 #, fuzzy msgid "" "If true, Gajim will scroll and select the contact who sent you the last " "message, if chat window is not already opened." msgstr "" "Se Verdadeiro, o Gajim irá rolar e selecionar o contato que lhe enviou a " "última mensagem, se a janela de conversa ainda não estiver aberta." #: gajim/common/config.py:267 msgid "Time of inactivity needed before the change status window closes down." msgstr "" "O tempo de inatividade necessário antes de fechar a janela de alteração de " "status." #: gajim/common/config.py:268 msgid "" "Maximum number of lines that are printed in conversations. Oldest lines are " "cleared." msgstr "" "Número máximo de linhas que são exibidas em conversações. As linhas mais " "antigas são apagadas." #: gajim/common/config.py:269 #, fuzzy msgid "" "If true, notification windows from notification-daemon will be attached to " "notification icon." msgstr "" "Se marcado como Verdadeiro as janelas de notificação do notification-daemon " "serão anexadas ao ícone da bandeja do sistema." #: gajim/common/config.py:270 msgid "Choose interval between 2 checks of idleness." msgstr "Escolha intervalo entre 2 verificações de inatividade." #: gajim/common/config.py:271 msgid "" "Valid uri schemes. Only schemes in this list will be accepted as \"real\" " "uri. (mailto and xmpp are handled separately)" msgstr "" "Esquema uri válido. Somente esquemas nesta lista irão ser aceitos como uri " "\"real\". (mailto e xmpp são manipulados separadamente)" #: gajim/common/config.py:272 #, fuzzy msgid "If true, completion in groupchats will be like a shell auto-completion" msgstr "" "Se verdadeiro, a ação de auto-completar na conferência irá ser como a do " "shell" #: gajim/common/config.py:273 msgid "" "When is self contact row displayed. Can be \"always\", \"when_other_resource" "\" or \"never\"" msgstr "" "Quando a linha de auto contatos é exibida. Pode ser \"sempre\", " "\"quando_em_outro_recurso\" ou \"nunca\"" #: gajim/common/config.py:278 msgid "Optionally fix jingle output video framerate. Example: 10/1 or 25/2" msgstr "" #: gajim/common/config.py:279 msgid "Optionally resize jingle output video. Example: 320x240" msgstr "" #: gajim/common/config.py:280 msgid "If true, You will also see your webcam" msgstr "" #: gajim/common/config.py:283 msgid "" "If true, Gajim will try to use a STUN server when using Jingle. The one in " "\"stun_server\" option, or the one given by the XMPP server." msgstr "" #: gajim/common/config.py:284 msgid "STUN server to use when using Jingle" msgstr "" #: gajim/common/config.py:285 msgid "" "If true, Gajim will show affiliation of groupchat occupants by adding a " "colored square to the status icon" msgstr "" #: gajim/common/config.py:286 msgid "" "Proxy used for all outgoing connections if the account does not have a " "specific proxy configured" msgstr "" #: gajim/common/config.py:287 msgid "If true, Gajim will ignore incoming attention requestd (\"wizz\")." msgstr "" #: gajim/common/config.py:288 msgid "" "If enabled, Gajim will reopen chat windows that were opened last time Gajim " "was closed." msgstr "" #: gajim/common/config.py:289 #, fuzzy msgid "" "If enabled, Gajim will show an icon to show that sent message has been " "received by your contact" msgstr "" "Se habilitado, o Gajim não irá perguntar por mensagem de status. A mensagem " "padrão especificada será usada neste caso." #: gajim/common/config.py:290 msgid "Show a mini avatar in chat window tabs and in window icon" msgstr "" #: gajim/common/config.py:291 #, fuzzy msgid "If true, Gajim will use the Systems Keyring to store account passwords." msgstr "" "Se verdadeiro, o Gajim usará o Gnome Keyring (se disponível) para armazenar " "as senhas das contas." #: gajim/common/config.py:292 msgid "Sets the encoding used by python-gnupg" msgstr "" #: gajim/common/config.py:293 msgid "If true, Gajim will execute XEP-0146 Commands." msgstr "" #: gajim/common/config.py:294 msgid "2: System, 1: Enabled, 0: Disabled" msgstr "" #: gajim/common/config.py:295 msgid "Options in days which can be chosen in the sync threshold menu" msgstr "" #: gajim/common/config.py:296 msgid "" "Maximum history in days we request from a public room archive. 0: As much as " "possible" msgstr "" #: gajim/common/config.py:297 msgid "" "Maximum history in days we request from a private room archive. 0: As much " "as possible" msgstr "" #: gajim/common/config.py:298 msgid "If the room subject is shown in chat on join" msgstr "" #: gajim/common/config.py:314 msgid "" "Priority will change automatically according to your status. Priorities are " "defined in autopriority_* options." msgstr "" "A prioridade será alterada automaticamente de acordo com o seu status. As " "prioridades são definidas nas opções autopriority_*." #: gajim/common/config.py:322 msgid "" "Status used to autoconnect as. Can be online, chat, away, xa, dnd, " "invisible. NOTE: this option is used only if restore_last_status is disabled" msgstr "" "Status usado para conexão automática. Pode ser conectado, bate-papo, " "inativo, fora, np, invisível. NOTA: esta opção é usada somente se a opção " "restore_last_status estiver desativada" #: gajim/common/config.py:323 msgid "If enabled, restore the last status that was used." msgstr "Se habilitado, restaura o último status que foi usado." #: gajim/common/config.py:325 #, fuzzy msgid "" "If true, Contacts requesting authorization will be automatically accepted." msgstr "" "Se verdadeiro, requisição de autorização de contatos irão ser " "automaticamente aceitos." #: gajim/common/config.py:326 msgid "" "If False, this account will be disabled and will not appear in roster window." msgstr "" "Se falso, esta conta será desativada e não irá aparecer na lista de contatos." #: gajim/common/config.py:329 msgid "" "If disabled, don't sign presences with GPG key, even if GPG is configured." msgstr "" "Se desativado, não assinar presenças com chaves GPG, se o GPG estiver " "configurado." #: gajim/common/config.py:331 msgid "Allow plaintext connections" msgstr "" #: gajim/common/config.py:334 msgid "" "List (space separated) of authentication mechanisms to try. Can contain " "ANONYMOUS, EXTERNAL, GSSAPI, SCRAM-SHA-1-PLUS, SCRAM-SHA-1, DIGEST-MD5, " "PLAIN, X-MESSENGER-OAUTH2 or XEP-0078" msgstr "" #: gajim/common/config.py:335 msgid "" "Show a warning dialog before sending password on an plaintext connection. " "Can be 'warn', 'connect', 'disconnect'" msgstr "" "Exibir uma mensagem de alerta antes de enviar uma senha em uma conexão de " "texto puro. Pode ser 'avisar', 'conectar' ou 'desconectar'" #: gajim/common/config.py:336 msgid "Show a warning dialog before using standard SSL library." msgstr "Exibir uma mensagem de alerta antes de usar uma biblioteca padrão SSL." #: gajim/common/config.py:337 #, fuzzy msgid "" "Show a warning dialog before sending PLAIN password over a plain connection." msgstr "" "Exibir uma mensagem de alerta antes de enviar uma senha em uma conexão de " "texto puro." #: gajim/common/config.py:338 msgid "Space separated list of ssl errors to ignore." msgstr "Lista separada por espaços de erros do ssl para ignorar." #: gajim/common/config.py:344 msgid "" "Space separated list of JIDs for which you do not want to store logs. You " "can also add account name to log nothing for this account." msgstr "" #: gajim/common/config.py:345 msgid "" "On startup, Gajim will download logs stored on server, provided the server " "supports XEP-0313" msgstr "" #: gajim/common/config.py:346 msgid "" "Space separated list of JIDs for which you accept to not log conversations " "if he does not want to." msgstr "" #: gajim/common/config.py:349 msgid "Whitespace sent after inactivity" msgstr "Espaço em branco enviado após inatividade" #: gajim/common/config.py:350 msgid "XMPP ping sent after inactivity" msgstr "Ping XMPP enviado após inatividade" #: gajim/common/config.py:354 #, fuzzy msgid "" "How many seconds to wait for the answer of ping alive packet before trying " "to reconnect?" msgstr "" "Quantos segundos aguardar a resposta do pacote de tempo-de-vida antes de " "tentar reconectar." #: gajim/common/config.py:358 msgid "Jabberd2 workaround" msgstr "Jabberd2 rodando" #: gajim/common/config.py:361 msgid "" "If checked, Gajim will use your IP and proxies defined in " "file_transfer_proxies option for file transfer." msgstr "" "Se checado, o Gaijm usará seu IP e proxies definidos no " "file_transfer_proxies, em opções para transferência de arquivos." #: gajim/common/config.py:362 msgid "" "If true, Gajim will test file transfer proxies on startup to be sure it " "works. Openfire's proxies are known to fail this test even if they work." msgstr "" #: gajim/common/config.py:375 msgid "Answer to receipt requests" msgstr "Respostas para requisições recebidas" #: gajim/common/config.py:376 msgid "Sent receipt requests" msgstr "Requisições recebidas enviadas" #: gajim/common/config.py:385 #, fuzzy msgid "" "Allow Gajim to send information about the operating system you are running." msgstr "" "Se marcado, o Gajim irá permitir que os outros detectem qual o sistema " "operacional está usando" #: gajim/common/config.py:386 msgid "Allow Gajim to send your local time." msgstr "Permitir ao Gajim enviar sua hora local." #: gajim/common/config.py:389 #, fuzzy msgid "Message that is sent to contacts you want to add" msgstr "Por favor preencha os dados do contato que você quer adicionar" #: gajim/common/config.py:390 msgid "" "If enabled and if server supports this feature, Gajim will receive messages " "sent and received by other resources." msgstr "" #: gajim/common/config.py:391 msgid "" "If enabled, Gajim will send your local IPs so your contact can connect to " "your machine to transfer files." msgstr "" #: gajim/common/config.py:392 #, fuzzy msgid "Latest token for OAuth 2.0 authentication." msgstr "Autenticação anônima" #: gajim/common/config.py:393 #, fuzzy msgid "client_id for OAuth 2.0 authentication." msgstr "Autenticação anôn_ima" #: gajim/common/config.py:394 #, fuzzy msgid "redirect_url for OAuth 2.0 authentication." msgstr "Autenticação anôn_ima" #: gajim/common/config.py:395 msgid "" "Space separated list of JIDs for which chat window will be re-opened on next " "startup." msgstr "" #: gajim/common/config.py:397 msgid "HTTP Upload: Enable HTTPS Verification" msgstr "" #: gajim/common/config.py:398 msgid "" "Preferred file transfer mechanism for file drag&drop on chat window. Can be " "'httpupload' (default) or 'jingle'" msgstr "" #: gajim/common/config.py:399 msgid "Allow cert verification with POSH" msgstr "" #: gajim/common/config.py:434 gajim/common/config.py:440 #, fuzzy msgid "Language for which misspelled words will be checked" msgstr "Idioma a usar na verificação ortográficas das palavras" #: gajim/common/config.py:437 msgid "The currently active encryption for that contact" msgstr "" #: gajim/common/config.py:441 #, fuzzy msgid "" "How many lines to request from server when entering a groupchat. -1 means no " "limit, -2 means global value" msgstr "" "Quantas linhas requisitar ao servidor quando entrar em uma conferência." #: gajim/common/config.py:442 #, fuzzy msgid "" "Minutes of backlog to request when entering a groupchat. -1 means no limit, " "-2 means global value" msgstr "" "Quantos minutos esperar para requisitar registros quando entrar em uma sala." #: gajim/common/config.py:443 msgid "State whether a notification is created for every message in this room" msgstr "" #: gajim/common/config.py:446 msgid "" "State whether plugins should be activated on startup (this is saved on Gajim " "exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI " "instead." msgstr "" #: gajim/common/config.py:451 gajim/common/const.py:255 msgid "Sleeping" msgstr "Dormindo" #: gajim/common/config.py:452 msgid "Back soon" msgstr "Volto logo" #: gajim/common/config.py:452 msgid "Back in some minutes." msgstr "Volto em alguns minutos." #: gajim/common/config.py:453 gajim/common/const.py:221 msgid "Eating" msgstr "Comendo" #: gajim/common/config.py:453 msgid "I'm eating, so leave me a message." msgstr "Eu estou comendo, então deixe-me uma mensagem." #: gajim/common/config.py:454 msgid "Movie" msgstr "Filme" #: gajim/common/config.py:454 msgid "I'm watching a movie." msgstr "Estou assistindo um filme." #: gajim/common/config.py:455 gajim/common/const.py:288 msgid "Working" msgstr "Trabalhando" #: gajim/common/config.py:455 msgid "I'm working." msgstr "Estou trabalhando." #: gajim/common/config.py:456 msgid "Phone" msgstr "Telefone" #: gajim/common/config.py:456 msgid "I'm on the phone." msgstr "Estou no telefone." #: gajim/common/config.py:457 msgid "Out" msgstr "Estou fora" #: gajim/common/config.py:457 msgid "I'm out enjoying life." msgstr "Estou fora curtindo a vida." #: gajim/common/config.py:468 msgid "I'm available." msgstr "Estou disponível." #: gajim/common/config.py:469 msgid "I'm free for chat." msgstr "Estou livre para conversar." #: gajim/common/config.py:470 gajim/gtk/accounts.py:166 msgid "Be right back." msgstr "Estou de volta." #: gajim/common/config.py:471 msgid "I'm not available." msgstr "Não estou disponível." #: gajim/common/config.py:472 msgid "Do not disturb." msgstr "Não perturbe." #: gajim/common/config.py:473 gajim/common/config.py:474 msgid "Bye!" msgstr "Tchau!" #: gajim/common/config.py:485 msgid "" "Sound to play when a group chat message contains one of the words in " "muc_highlight_words, or when a group chat message contains your nickname." msgstr "" "Som para tocar quando uma mensagem MUC conter uma das palavras no " "muc_hightlight_words, ou quando uma mensagem MUC contiver seu apelido." #: gajim/common/config.py:486 msgid "Sound to play when any MUC message arrives." msgstr "Som a ser tocado quando qualquer mensagem MUC chegar." #: gajim/common/config.py:490 #, fuzzy msgid "Tor" msgstr "Para" #: gajim/common/optparser.py:52 #, python-format msgid "Error: cannot open %s for reading" msgstr "Erro: impossível abrir %s para leitura" #: gajim/common/const.py:205 msgid "Doing Chores" msgstr "Atarefado" #: gajim/common/const.py:206 msgid "Buying Groceries" msgstr "Fazendo compras" #: gajim/common/const.py:207 msgid "Cleaning" msgstr "Limpando" #: gajim/common/const.py:208 msgid "Cooking" msgstr "Cozinhando" #: gajim/common/const.py:209 msgid "Doing Maintenance" msgstr "Fazendo manutenção" #: gajim/common/const.py:210 msgid "Doing the Dishes" msgstr "Lavando a louça" #: gajim/common/const.py:211 msgid "Doing the Laundry" msgstr "Lavando roupas" #: gajim/common/const.py:212 msgid "Gardening" msgstr "Fazendo jardinagem" #: gajim/common/const.py:213 msgid "Running an Errand" msgstr "Realizando uma tarefa" #: gajim/common/const.py:214 msgid "Walking the Dog" msgstr "Passeando com o cachorro" #: gajim/common/const.py:216 msgid "Drinking" msgstr "Bebendo" #: gajim/common/const.py:217 msgid "Having a Beer" msgstr "Bebendo uma cerveja" #: gajim/common/const.py:218 msgid "Having Coffee" msgstr "Tomando café" #: gajim/common/const.py:219 msgid "Having Tea" msgstr "Tomando chá" #: gajim/common/const.py:222 msgid "Having a Snack" msgstr "Fazendo um lanche" #: gajim/common/const.py:223 msgid "Having Breakfast" msgstr "Tomando café da manhã" #: gajim/common/const.py:224 msgid "Having Dinner" msgstr "Jantando" #: gajim/common/const.py:225 msgid "Having Lunch" msgstr "Almoçando" #: gajim/common/const.py:227 msgid "Exercising" msgstr "Exercitando" #: gajim/common/const.py:228 gajim/common/const.py:279 msgid "Cycling" msgstr "Andando de bicicleta" #: gajim/common/const.py:229 msgid "Dancing" msgstr "Dançando" #: gajim/common/const.py:230 msgid "Hiking" msgstr "Fazendo caminhada" #: gajim/common/const.py:231 msgid "Jogging" msgstr "Correndo" #: gajim/common/const.py:232 msgid "Playing Sports" msgstr "Praticando esportes" #: gajim/common/const.py:233 msgid "Running" msgstr "Correndo" #: gajim/common/const.py:234 msgid "Skiing" msgstr "Esquiando" #: gajim/common/const.py:235 msgid "Swimming" msgstr "Nadando" #: gajim/common/const.py:236 msgid "Working out" msgstr "Trabalhando fora" #: gajim/common/const.py:238 msgid "Grooming" msgstr "Afagando" #: gajim/common/const.py:239 msgid "At the Spa" msgstr "No Spa" #: gajim/common/const.py:240 msgid "Brushing Teeth" msgstr "Escovando os dentes" #: gajim/common/const.py:241 msgid "Getting a Haircut" msgstr "Cortando o cabelo" #: gajim/common/const.py:242 msgid "Shaving" msgstr "Fazendo barba" #: gajim/common/const.py:243 msgid "Taking a Bath" msgstr "Tomando banho" #: gajim/common/const.py:244 msgid "Taking a Shower" msgstr "Tomando uma ducha" #: gajim/common/const.py:246 msgid "Having an Appointment" msgstr "Em um compromisso" #: gajim/common/const.py:248 msgid "Inactive" msgstr "Inativo" #: gajim/common/const.py:249 msgid "Day Off" msgstr "De folga" #: gajim/common/const.py:250 msgid "Hanging out" msgstr "Me descontraindo" #: gajim/common/const.py:251 msgid "Hiding" msgstr "Me escondendo" #: gajim/common/const.py:252 msgid "On Vacation" msgstr "Em férias" #: gajim/common/const.py:253 msgid "Praying" msgstr "Orando" #: gajim/common/const.py:254 msgid "Scheduled Holiday" msgstr "Feriado" #: gajim/common/const.py:256 msgid "Thinking" msgstr "Pensando" #: gajim/common/const.py:258 msgid "Relaxing" msgstr "Relaxando" #: gajim/common/const.py:259 msgid "Fishing" msgstr "Pescando" #: gajim/common/const.py:260 msgid "Gaming" msgstr "Jogando" #: gajim/common/const.py:261 msgid "Going out" msgstr "Saindo" #: gajim/common/const.py:262 msgid "Partying" msgstr "Festejando" #: gajim/common/const.py:263 msgid "Reading" msgstr "Lendo" #: gajim/common/const.py:264 msgid "Rehearsing" msgstr "Ensaiando" #: gajim/common/const.py:265 msgid "Shopping" msgstr "Comprando" #: gajim/common/const.py:266 msgid "Smoking" msgstr "Fumando" #: gajim/common/const.py:267 msgid "Socializing" msgstr "Socializando" #: gajim/common/const.py:268 msgid "Sunbathing" msgstr "Tomando banho de sol" #: gajim/common/const.py:269 msgid "Watching TV" msgstr "Assitindo TV" #: gajim/common/const.py:270 msgid "Watching a Movie" msgstr "Assistindo um filme" #: gajim/common/const.py:272 msgid "Talking" msgstr "Falando" #: gajim/common/const.py:273 msgid "In Real Life" msgstr "No mundo real" #: gajim/common/const.py:274 msgid "On the Phone" msgstr "Ao telefone" #: gajim/common/const.py:275 msgid "On Video Phone" msgstr "Ao telefone" #: gajim/common/const.py:277 msgid "Traveling" msgstr "Viajando" #: gajim/common/const.py:278 msgid "Commuting" msgstr "Em trânsito" #: gajim/common/const.py:280 msgid "Driving" msgstr "Dirigindo" #: gajim/common/const.py:281 msgid "In a Car" msgstr "Em um carro" #: gajim/common/const.py:282 msgid "On a Bus" msgstr "Em um ônibus" #: gajim/common/const.py:283 msgid "On a Plane" msgstr "Em um avião" #: gajim/common/const.py:284 msgid "On a Train" msgstr "Em um trem" #: gajim/common/const.py:285 msgid "On a Trip" msgstr "Em um passeio" #: gajim/common/const.py:286 msgid "Walking" msgstr "Andando" #: gajim/common/const.py:289 msgid "Coding" msgstr "Codificado" #: gajim/common/const.py:290 msgid "In a Meeting" msgstr "Em um encontro" #: gajim/common/const.py:291 msgid "Studying" msgstr "Estudando" #: gajim/common/const.py:292 msgid "Writing" msgstr "Escrevendo" #: gajim/common/const.py:295 msgid "Afraid" msgstr "Amedrontado" #: gajim/common/const.py:296 msgid "Amazed" msgstr "Surpreso" #: gajim/common/const.py:297 msgid "Amorous" msgstr "Amoroso" #: gajim/common/const.py:298 msgid "Angry" msgstr "Irado" #: gajim/common/const.py:299 msgid "Annoyed" msgstr "Chateado" #: gajim/common/const.py:300 msgid "Anxious" msgstr "Ansioso" #: gajim/common/const.py:301 msgid "Aroused" msgstr "Estimulado" #: gajim/common/const.py:302 msgid "Ashamed" msgstr "Envergonhado" #: gajim/common/const.py:303 msgid "Bored" msgstr "Entediado" #: gajim/common/const.py:304 msgid "Brave" msgstr "Corajoso" #: gajim/common/const.py:305 msgid "Calm" msgstr "Calmo" #: gajim/common/const.py:306 msgid "Cautious" msgstr "Cauteloso" #: gajim/common/const.py:307 msgid "Cold" msgstr "Indiferente" #: gajim/common/const.py:308 msgid "Confident" msgstr "Confidente" #: gajim/common/const.py:309 msgid "Confused" msgstr "Confuso" #: gajim/common/const.py:310 msgid "Contemplative" msgstr "Contemplativo" #: gajim/common/const.py:311 msgid "Contented" msgstr "Contente" #: gajim/common/const.py:312 msgid "Cranky" msgstr "Nervoso" #: gajim/common/const.py:313 msgid "Crazy" msgstr "Louco" #: gajim/common/const.py:314 msgid "Creative" msgstr "Criativo" #: gajim/common/const.py:315 msgid "Curious" msgstr "Curioso" #: gajim/common/const.py:316 msgid "Dejected" msgstr "Abatido" #: gajim/common/const.py:317 msgid "Depressed" msgstr "Deprimido" #: gajim/common/const.py:318 msgid "Disappointed" msgstr "Desapontado" #: gajim/common/const.py:319 msgid "Disgusted" msgstr "Enojado" #: gajim/common/const.py:320 msgid "Dismayed" msgstr "Consternado" #: gajim/common/const.py:321 msgid "Distracted" msgstr "Distraído" #: gajim/common/const.py:322 msgid "Embarrassed" msgstr "Envergonhado" #: gajim/common/const.py:323 msgid "Envious" msgstr "Com inveja" #: gajim/common/const.py:324 msgid "Excited" msgstr "Excitado" #: gajim/common/const.py:325 msgid "Flirtatious" msgstr "Paquerador" #: gajim/common/const.py:326 msgid "Frustrated" msgstr "Frustrado" #: gajim/common/const.py:327 msgid "Grateful" msgstr "Agradecido" #: gajim/common/const.py:328 msgid "Grieving" msgstr "Angustiado" #: gajim/common/const.py:329 msgid "Grumpy" msgstr "Mal-humorado" #: gajim/common/const.py:330 msgid "Guilty" msgstr "Culpado" #: gajim/common/const.py:331 msgid "Happy" msgstr "Feliz" #: gajim/common/const.py:332 msgid "Hopeful" msgstr "Esperançoso" #: gajim/common/const.py:333 msgid "Hot" msgstr "Quente" #: gajim/common/const.py:334 msgid "Humbled" msgstr "Humilde" #: gajim/common/const.py:335 msgid "Humiliated" msgstr "Humilhado" #: gajim/common/const.py:336 msgid "Hungry" msgstr "Com fome" #: gajim/common/const.py:337 msgid "Hurt" msgstr "Machucado" #: gajim/common/const.py:338 msgid "Impressed" msgstr "Impressionado" #: gajim/common/const.py:339 msgid "In Awe" msgstr "Chocado" #: gajim/common/const.py:340 msgid "In Love" msgstr "Apaixonado" #: gajim/common/const.py:341 msgid "Indignant" msgstr "Indignado" #: gajim/common/const.py:342 msgid "Interested" msgstr "Interessado" #: gajim/common/const.py:343 msgid "Intoxicated" msgstr "Intoxicado" #: gajim/common/const.py:344 msgid "Invincible" msgstr "Invencível" #: gajim/common/const.py:345 msgid "Jealous" msgstr "Envergonhado" #: gajim/common/const.py:346 msgid "Lonely" msgstr "Sozinho" #: gajim/common/const.py:347 msgid "Lost" msgstr "Perdido" #: gajim/common/const.py:348 msgid "Lucky" msgstr "Sortudo" #: gajim/common/const.py:349 msgid "Mean" msgstr "Mau" #: gajim/common/const.py:350 msgid "Moody" msgstr "Mal-humorado" #: gajim/common/const.py:351 msgid "Nervous" msgstr "Nervoso" #: gajim/common/const.py:352 msgid "Neutral" msgstr "Neutro" #: gajim/common/const.py:353 msgid "Offended" msgstr "Ofendido" #: gajim/common/const.py:354 msgid "Outraged" msgstr "Indignado" #: gajim/common/const.py:355 msgid "Playful" msgstr "Brincalhão" #: gajim/common/const.py:356 msgid "Proud" msgstr "Orgulhoso" #: gajim/common/const.py:357 msgid "Relaxed" msgstr "Relaxado" #: gajim/common/const.py:358 msgid "Relieved" msgstr "Aliviado" #: gajim/common/const.py:359 msgid "Remorseful" msgstr "Arrependido" #: gajim/common/const.py:360 msgid "Restless" msgstr "Inquieto" #: gajim/common/const.py:361 msgid "Sad" msgstr "Triste" #: gajim/common/const.py:362 msgid "Sarcastic" msgstr "Sarcástico" #: gajim/common/const.py:363 msgid "Satisfied" msgstr "Satisfeito" #: gajim/common/const.py:364 msgid "Serious" msgstr "Sério" #: gajim/common/const.py:365 msgid "Shocked" msgstr "Chocado" #: gajim/common/const.py:366 msgid "Shy" msgstr "Tímido" #: gajim/common/const.py:367 msgid "Sick" msgstr "Doente" #: gajim/common/const.py:368 msgid "Sleepy" msgstr "Com sono" #: gajim/common/const.py:369 msgid "Spontaneous" msgstr "Espontâneo" #: gajim/common/const.py:370 msgid "Stressed" msgstr "Estressado" #: gajim/common/const.py:371 msgid "Strong" msgstr "Forte" #: gajim/common/const.py:372 msgid "Surprised" msgstr "Surpreso" #: gajim/common/const.py:373 msgid "Thankful" msgstr "Agradecido" #: gajim/common/const.py:374 msgid "Thirsty" msgstr "Com sede" #: gajim/common/const.py:375 msgid "Tired" msgstr "Cansado" #: gajim/common/const.py:376 msgid "Undefined" msgstr "Indefinido" #: gajim/common/const.py:377 msgid "Weak" msgstr "Fraco" #: gajim/common/const.py:378 msgid "Worried" msgstr "Preocupado" #: gajim/common/const.py:382 msgid "accuracy" msgstr "" #: gajim/common/const.py:383 #, fuzzy msgid "alt" msgstr "padrão" #: gajim/common/const.py:384 msgid "area" msgstr "" #: gajim/common/const.py:385 #, fuzzy msgid "bearing" msgstr "marinho" #: gajim/common/const.py:386 #, fuzzy msgid "building" msgstr "Me escondendo" #: gajim/common/const.py:387 #, fuzzy msgid "country" msgstr "País:" #: gajim/common/const.py:388 #, fuzzy msgid "countrycode" msgstr "Conta" #: gajim/common/const.py:389 msgid "datum" msgstr "" #: gajim/common/const.py:390 #, fuzzy msgid "description" msgstr "Descrição" #: gajim/common/const.py:391 #, fuzzy msgid "error" msgstr "Erro" #: gajim/common/const.py:392 msgid "floor" msgstr "" #: gajim/common/const.py:393 msgid "lat" msgstr "" #: gajim/common/const.py:394 msgid "locality" msgstr "" #: gajim/common/const.py:395 #, fuzzy msgid "lon" msgstr "um" #: gajim/common/const.py:396 msgid "postalcode" msgstr "" #: gajim/common/const.py:397 msgid "region" msgstr "" #: gajim/common/const.py:398 msgid "room" msgstr "sala" #: gajim/common/const.py:399 msgid "speed" msgstr "" #: gajim/common/const.py:400 msgid "street" msgstr "" #: gajim/common/const.py:401 msgid "text" msgstr "" #: gajim/common/const.py:402 msgid "timestamp" msgstr "" #: gajim/common/const.py:403 msgid "URI" msgstr "" #: gajim/common/const.py:408 msgid "Unable to get issuer certificate" msgstr "Não foi possível obter o certificado do emissor" #: gajim/common/const.py:409 msgid "Unable to get certificate CRL" msgstr "Não foi possível obter certificado CRL" #: gajim/common/const.py:410 msgid "Unable to decrypt certificate's signature" msgstr "Não foi possível descriptografar a assinatura do certificado" #: gajim/common/const.py:411 msgid "Unable to decrypt CRL's signature" msgstr "Não foi possível descriptografar a assinatura CRL" #: gajim/common/const.py:412 msgid "Unable to decode issuer public key" msgstr "Não foi possível decodificar a chave pública do emissor" #: gajim/common/const.py:413 msgid "Certificate signature failure" msgstr "Assinatura do certificado falhou" #: gajim/common/const.py:414 msgid "CRL signature failure" msgstr "Falha na assinatura CRL" #: gajim/common/const.py:415 msgid "Certificate is not yet valid" msgstr "O certificado ainda não é válido" #: gajim/common/const.py:416 msgid "Certificate has expired" msgstr "O certificado expirou" #: gajim/common/const.py:417 msgid "CRL is not yet valid" msgstr "CRL ainda não é válido" #: gajim/common/const.py:418 msgid "CRL has expired" msgstr "CRL expirou" #: gajim/common/const.py:419 msgid "Format error in certificate's notBefore field" msgstr "Erro de formato nos certificados no campo notBefore" #: gajim/common/const.py:420 msgid "Format error in certificate's notAfter field" msgstr "Erro de formato nos certificados no campo notAfter" #: gajim/common/const.py:421 msgid "Format error in CRL's lastUpdate field" msgstr "Erro de formato no campo lastUpdate do CRL" #: gajim/common/const.py:422 msgid "Format error in CRL's nextUpdate field" msgstr "Erro de formato no campo nextUpdate do CRL" #: gajim/common/const.py:423 msgid "Out of memory" msgstr "Memória insuficiente" #: gajim/common/const.py:424 msgid "Self signed certificate" msgstr "Certificado próprio" #: gajim/common/const.py:425 msgid "Self signed certificate in certificate chain" msgstr "Certificado próprio na cadeia de certificados" #: gajim/common/const.py:426 msgid "Unable to get local issuer certificate" msgstr "Não foi possível obter o certificado do emissor local" #: gajim/common/const.py:427 msgid "Unable to verify the first certificate" msgstr "Não foi possível verificar o primeiro certificado" #: gajim/common/const.py:428 msgid "Certificate chain too long" msgstr "A cadeia de certificados é muito longa" #: gajim/common/const.py:429 msgid "Certificate revoked" msgstr "Certificado revocado" #: gajim/common/const.py:430 msgid "Invalid CA certificate" msgstr "Certificado CA inválido" #: gajim/common/const.py:431 msgid "Path length constraint exceeded" msgstr "Limite de comprimento do caminho excedido" #: gajim/common/const.py:432 msgid "Unsupported certificate purpose" msgstr "Certificado de propósito não suportado" #: gajim/common/const.py:433 msgid "Certificate not trusted" msgstr "Certificado não confiável" #: gajim/common/const.py:434 msgid "Certificate rejected" msgstr "Certificado rejeitado" #: gajim/common/const.py:435 msgid "Subject issuer mismatch" msgstr "Assunto do emissor não coincide" #: gajim/common/const.py:436 msgid "Authority and subject key identifier mismatch" msgstr "Chave identificadora de autoridade e assunto não coincidem" #: gajim/common/const.py:437 msgid "Authority and issuer serial number mismatch" msgstr "Autoridade e número serial do emissor não coincidem" #: gajim/common/const.py:438 msgid "Key usage does not include certificate signing" msgstr "O uso das chaves não inclui assinatura de certificado" #: gajim/common/const.py:439 msgid "Application verification failure" msgstr "Verificação do aplicativo falhou" #: gajim/common/logging_helpers.py:31 #, python-format msgid "%s is not a valid loglevel" msgstr "%s não é um nível de gravação (loglevel) válido" #: gajim/common/connection.py:717 #, python-format msgid "Connection with account \"%s\" has been lost" msgstr "Conexão com a conta \"%s\" foi perdida" #: gajim/common/connection.py:718 msgid "Reconnect manually." msgstr "Reconecte manualmente." #: gajim/common/connection.py:740 #, python-format msgid "Server %(name)s answered wrongly to register request: %(error)s" msgstr "" "O servidor %(name)s respondeu erroneamente à requisição de registro: " "%(error)s" #: gajim/common/connection.py:782 #, python-format msgid "Server %s provided a different registration form" msgstr "O servidor %s forneceu um formulário de registro diferente" #: gajim/common/connection.py:1090 #, python-format msgid "Could not connect to \"%(host)s\" via proxy \"%(proxy)s\"" msgstr "Não foi possível conectar a \"%(host)s\" pelo proxy \"%(proxy)s\"" #: gajim/common/connection.py:1093 #, fuzzy, python-format msgid "Could not connect to \"%(host)s\"" msgstr "Impossível conectar a \"%s\"" #: gajim/common/connection.py:1095 gajim/common/connection.py:1317 msgid "Check your connection or try again later." msgstr "Verifique sua conexão ou tente novamente mais tarde." #: gajim/common/connection.py:1100 #, python-format msgid "Server replied: %s" msgstr "O servidor respondeu: %s" #: gajim/common/connection.py:1115 msgid "Connection to proxy failed" msgstr "Falha na conexão com o proxy" #: gajim/common/connection.py:1154 gajim/common/connection.py:1275 #, python-format msgid "Could not connect to account %s" msgstr "Não foi possível conectar a conta %s" #: gajim/common/connection.py:1155 gajim/common/connection.py:1276 #, python-format msgid "Connection with account %s has been lost. Retry connecting." msgstr "A conexão com a conta %s foi perdida. Tentando reconectar." #: gajim/common/connection.py:1316 gajim/common/connection.py:1632 #: gajim/common/zeroconf/connection_zeroconf.py:201 #, python-format msgid "Could not connect to \"%s\"" msgstr "Impossível conectar a \"%s\"" #: gajim/common/connection.py:1354 #, python-format msgid "Authentication failed with \"%s\"" msgstr "Falha na autenticação com \"%s\"" #: gajim/common/connection.py:1355 msgid "Please check your login and password for correctness." msgstr "Por favor, verifique se seu login e senha estão corretos." #: gajim/common/dbus_support.py:40 msgid "D-Bus python bindings are missing in this computer" msgstr "Acesso ao python D-Bus foi perdido neste computador" #: gajim/common/dbus_support.py:41 gajim/common/dbus_support.py:52 msgid "D-Bus capabilities of Gajim cannot be used" msgstr "As potencialidades do D-Bus no Gajim não podem ser usadas" #: gajim/common/dbus_support.py:51 msgid "D-Bus does not run correctly on this machine" msgstr "O D-Bus não está sendo executado corretamente nesta máquina" #: gajim/common/dbus_support.py:54 #, fuzzy msgid "D-Bus does not run correctly on this machine: system bus not present" msgstr "O D-Bus não está sendo executado corretamente nesta máquina" #: gajim/common/dbus_support.py:57 #, fuzzy msgid "D-Bus does not run correctly on this machine: session bus not present" msgstr "O D-Bus não está sendo executado corretamente nesta máquina" #: gajim/common/multimedia_helpers.py:49 #, fuzzy msgid "Default device" msgstr "Mensagem padrão" #: gajim/common/multimedia_helpers.py:70 #, fuzzy msgid "Audio test" msgstr "Áudio / Vídeo" #: gajim/common/multimedia_helpers.py:73 gajim/common/multimedia_helpers.py:89 #: gajim/common/multimedia_helpers.py:103 #: gajim/common/multimedia_helpers.py:121 msgid "Autodetect" msgstr "" #: gajim/common/multimedia_helpers.py:76 gajim/common/multimedia_helpers.py:91 #, fuzzy, python-format msgid "ALSA: %s" msgstr "Tamanho: %s" #: gajim/common/multimedia_helpers.py:79 gajim/common/multimedia_helpers.py:93 #, fuzzy, python-format msgid "Pulse: %s" msgstr "Arquivo: %s" #: gajim/common/multimedia_helpers.py:87 msgid "Fake audio output" msgstr "" #: gajim/common/multimedia_helpers.py:100 msgid "Video test" msgstr "" #: gajim/common/multimedia_helpers.py:105 #, python-format msgid "V4L2: %s" msgstr "" #: gajim/common/multimedia_helpers.py:108 #, fuzzy msgid "Screen" msgstr "verde" #: gajim/common/multimedia_helpers.py:115 msgid "Fake video output" msgstr "" #: gajim/common/multimedia_helpers.py:118 #, python-format msgid "X Window System (X11/XShm/Xv): %s" msgstr "" #: gajim/common/multimedia_helpers.py:120 msgid "X Window System (without Xv)" msgstr "" #: gajim/common/jingle_rtp.py:122 #, python-format msgid "%s configuration error" msgstr "%s erro de configuração" #: gajim/common/jingle_rtp.py:123 #, python-format msgid "" "Couldn’t set up %(text)s. Check your configuration.\n" "\n" "Pipeline was:\n" "%(pipeline)s\n" "\n" "Error was:\n" "%(error)s" msgstr "" #: gajim/common/jingle_rtp.py:388 msgid "audio input" msgstr "" #: gajim/common/jingle_rtp.py:392 msgid "audio output" msgstr "" #: gajim/common/jingle_rtp.py:450 msgid "video input" msgstr "" #: gajim/common/jingle_rtp.py:457 msgid "video output" msgstr "" #: gajim/common/helpers.py:196 msgid "Server must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:200 msgid "Invalid character in hostname." msgstr "Caracter inválido no nome do host." #: gajim/common/helpers.py:202 msgid "Server address required." msgstr "Endereço do servidor é requerido." #: gajim/common/helpers.py:206 msgid "Username must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:210 msgid "Invalid character in username." msgstr "Caracter inválido no nome do usuário." #: gajim/common/helpers.py:216 msgid "Resource must be between 1 and 1023 bytes" msgstr "" #: gajim/common/helpers.py:220 msgid "Invalid character in resource." msgstr "Caracter inválido no recurso." #: gajim/common/helpers.py:258 msgid "_Busy" msgstr "_Ocupado" #: gajim/common/helpers.py:263 msgid "_Not Available" msgstr "_Não disponível" #: gajim/common/helpers.py:268 msgid "_Free for Chat" msgstr "Livre para _conversa" #: gajim/common/helpers.py:273 #, fuzzy msgid "?user status:_Available" msgstr "?status da transferência:Parado" #: gajim/common/helpers.py:277 msgid "Connecting" msgstr "Conectando" #: gajim/common/helpers.py:280 msgid "A_way" msgstr "_Afastado" #: gajim/common/helpers.py:285 msgid "_Offline" msgstr "_Desconectado" #: gajim/common/helpers.py:290 msgid "_Invisible" msgstr "_Invisível" #: gajim/common/helpers.py:296 msgid "?contact has status:Unknown" msgstr "?contato tem status:Desconhecido" #: gajim/common/helpers.py:298 msgid "?contact has status:Has errors" msgstr "?contato tem status:Com erros" #: gajim/common/helpers.py:313 msgid "?Subscription we already have:None" msgstr "?Inscrição existente:Nenhuma" #: gajim/common/helpers.py:315 msgid "To" msgstr "Para" #: gajim/common/helpers.py:317 msgid "From" msgstr "De" #: gajim/common/helpers.py:319 msgid "Both" msgstr "Ambos" #: gajim/common/helpers.py:321 gajim/gtk/server_info.py:133 #, fuzzy msgid "Unknown" msgstr "?SO:Desconhecido" #: gajim/common/helpers.py:327 msgid "?Ask (for Subscription):None" msgstr "?Pergunta (para inscrição):Nenhuma" #: gajim/common/helpers.py:329 msgid "Subscribe" msgstr "Inscrever" #: gajim/common/helpers.py:338 msgid "?Group Chat Contact Role:None" msgstr "?Regra do contato para conversa em grupo:Nenhuma" #: gajim/common/helpers.py:341 msgid "Moderators" msgstr "Moderadores" #: gajim/common/helpers.py:343 msgid "Moderator" msgstr "Moderador" #: gajim/common/helpers.py:346 msgid "Participants" msgstr "Participantes" #: gajim/common/helpers.py:348 msgid "Participant" msgstr "Participante" #: gajim/common/helpers.py:351 msgid "Visitors" msgstr "Visitantes" #: gajim/common/helpers.py:353 msgid "Visitor" msgstr "Visitante" #: gajim/common/helpers.py:404 msgid "is paying attention to the conversation" msgstr "está prestando a atenção na conversa" #: gajim/common/helpers.py:406 msgid "is doing something else" msgstr "está fazendo outra coisa" #: gajim/common/helpers.py:408 #, fuzzy msgid "is composing a message…" msgstr "está digitando..." #: gajim/common/helpers.py:411 msgid "paused composing a message" msgstr "parou de digitar" #: gajim/common/helpers.py:413 msgid "has closed the chat window or tab" msgstr "fechou a janela de conversa ou aba" #: gajim/common/helpers.py:577 #, python-format msgid "%s GiB" msgstr "%s GiB" #: gajim/common/helpers.py:580 #, python-format msgid "%s GB" msgstr "%s GB" #: gajim/common/helpers.py:584 #, python-format msgid "%s MiB" msgstr "%s MiB" #: gajim/common/helpers.py:587 #, python-format msgid "%s MB" msgstr "%s MB" #: gajim/common/helpers.py:591 #, python-format msgid "%s KiB" msgstr "%s KiB" #: gajim/common/helpers.py:594 #, python-format msgid "%s KB" msgstr "%s KB" #: gajim/common/helpers.py:597 #, python-format msgid "%s B" msgstr "%s B" #: gajim/common/helpers.py:986 gajim/common/helpers.py:993 #, python-format msgid "%d message pending" msgid_plural "%d messages pending" msgstr[0] "%d mensagem pendente" msgstr[1] "%d mensagens pendentes" #: gajim/common/helpers.py:1000 #, fuzzy, python-format msgid "from room %s" msgstr " da sala %s" #: gajim/common/helpers.py:1003 gajim/common/helpers.py:1020 #, fuzzy, python-format msgid "from user %s" msgstr " do usuário %s" #: gajim/common/helpers.py:1005 #, fuzzy, python-format msgid "from %s" msgstr " de %s" #: gajim/common/helpers.py:1012 gajim/common/helpers.py:1018 #, python-format msgid "%d event pending" msgid_plural "%d events pending" msgstr[0] "%d evento pendente" msgstr[1] "%d eventos pendentes" #: gajim/common/helpers.py:1036 gajim/common/helpers.py:1048 #: gajim/data/gui/roster_window.ui:85 data/org.gajim.Gajim.desktop.in:4 #: data/org.gajim.Gajim.appdata.xml.in:9 msgid "Gajim" msgstr "Gajim" #: gajim/common/helpers.py:1050 #, python-format msgid "Gajim - %s" msgstr "Gajim - %s" #: gajim/common/helpers.py:1247 gajim/data/gui/add_new_contact_window.ui:20 msgid "I would like to add you to my contact list." msgstr "Por favor, eu gostaria de adicioná-lo à minha lista." #: gajim/common/helpers.py:1249 msgid "Hello, I am $name." msgstr "" #: gajim/common/helpers.py:1353 gajim/common/helpers.py:1362 #: gajim/common/helpers.py:1420 msgid "Timeout loading image" msgstr "Tempo esgotado ao carregar a imagem" #: gajim/common/helpers.py:1372 gajim/common/helpers.py:1418 msgid "Image is too big" msgstr "A imagem é grande demais" #: gajim/common/helpers.py:1383 #, fuzzy msgid "PyCURL is not installed" msgstr "CRL ainda não é válido" #: gajim/common/helpers.py:1422 #, fuzzy msgid "Error loading image" msgstr "Tempo esgotado ao carregar a imagem" #: gajim/common/configpaths.py:85 #, python-format msgid "%s is a file but it should be a directory" msgstr "%s é um arquivo, mas deveria ser um diretório" #: gajim/common/configpaths.py:86 msgid "Gajim will now exit" msgstr "Gajim sairá agora" #: gajim/common/exceptions.py:45 #, fuzzy, python-format msgid "" "The database file (%s) cannot be read. Try to repair it (see https://dev." "gajim.org/gajim/gajim/wikis/help/DatabaseBackup) or remove it (all history " "will be lost)." msgstr "" "O arquivo da base de dados (%s) não pôde ser lido. Tente repará-lo (veja " "http://trac.gajim.org/wiki/DatabaseBackup) ou removê-lo (todo o histórico " "será perdido)." #: gajim/common/exceptions.py:59 msgid "Service not available: Gajim is not running, or remote_control is False" msgstr "" "Serviço não disponível: o Gajim não está funcionando ou a opção " "remote_control está definida como False" #: gajim/common/exceptions.py:81 #, python-format msgid "" "Session bus is not available.\n" "Try reading %(url)s" msgstr "" "O bus de sessão não está disponível.\n" "Tente ler %(url)s" #: gajim/common/exceptions.py:93 #, python-format msgid "" "System bus is not available.\n" "Try reading %(url)s" msgstr "" "O bus de sessão não está disponível.\n" "Tente ler %(url)s" #: gajim/common/zeroconf/connection_zeroconf.py:202 gajim/gtk/accounts.py:416 msgid "Please check if Avahi or Bonjour is installed." msgstr "Por favor verifique se o Avahi ou o Bonjour estão instalados." #: gajim/common/zeroconf/connection_zeroconf.py:212 #: gajim/common/zeroconf/connection_zeroconf.py:216 msgid "Could not start local service" msgstr "Impossível iniciar o serviço local" #: gajim/common/zeroconf/connection_zeroconf.py:213 #, python-format msgid "Unable to bind to port %d." msgstr "Impossível conectar-se à porta %d." #: gajim/common/zeroconf/connection_zeroconf.py:217 #, fuzzy msgid "Please check if avahi/bonjour-daemon is running." msgstr "Por favor verifique se o serviço avahi-daemon está rodando." #: gajim/common/zeroconf/connection_zeroconf.py:303 #: gajim/common/zeroconf/connection_zeroconf.py:316 #: gajim/common/zeroconf/connection_zeroconf.py:332 #, python-format msgid "Could not change status of account \"%s\"" msgstr "Impossível alterar status da conta \"%s\"" #: gajim/common/zeroconf/connection_zeroconf.py:304 #: gajim/common/zeroconf/connection_zeroconf.py:317 #: gajim/common/zeroconf/connection_zeroconf.py:333 msgid "Please check if avahi-daemon is running." msgstr "Por favor verifique se o serviço avahi-daemon está rodando." #: gajim/common/zeroconf/connection_zeroconf.py:349 msgid "Your message could not be sent." msgstr "Sua mensagem não pode ser enviada." #: gajim/common/zeroconf/connection_zeroconf.py:364 msgid "Contact is offline. Your message could not be sent." msgstr "O contato está offline. Sua mensagem não pode ser enviada." #: gajim/common/zeroconf/connection_zeroconf.py:388 msgid "" "Connection to host could not be established: Timeout while sending data." msgstr "" "A conexão ao computador não pode ser estabelecida: tempo excedido ao " "transmitir os dados." #: gajim/common/zeroconf/zeroconf_bonjour.py:231 #: gajim/common/zeroconf/zeroconf_bonjour.py:256 #: gajim/common/zeroconf/zeroconf_bonjour.py:302 #: gajim/common/zeroconf/zeroconf_avahi.py:237 #, python-format msgid "Error while adding service. %s" msgstr "Erro ao adicionar serviço. %s" #: gajim/common/zeroconf/connection_handlers_zeroconf.py:176 #: gajim/common/modules/message.py:286 msgid "message" msgstr "mensagem" #: gajim/common/dbus/logind.py:72 msgid "Machine is going to sleep" msgstr "" #: gajim/common/dbus/logind.py:97 msgid "Disconnect from the network" msgstr "" #: gajim/common/modules/presence.py:85 msgid "I would like to add you to my roster." msgstr "Eu gostaria de adiciona-lo à minha lista." #: gajim/common/modules/message.py:164 #, fuzzy, python-format msgid "error: %s" msgstr "Erro: %s" #: gajim/common/modules/httpupload.py:134 msgid "File is empty" msgstr "O arquivo está vazio" #: gajim/common/modules/httpupload.py:137 msgid "File does not exist" msgstr "O arquivo não existe" #: gajim/common/modules/httpupload.py:144 #: gajim/common/modules/httpupload.py:214 #, python-format msgid "File is too large, maximum allowed file size is: %s" msgstr "" #: gajim/common/modules/misc.py:32 msgid "This message was encrypted with OTR and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:35 msgid "" "This message was encrypted with Legacy OpenPGP and could not be decrypted. " "You can install the PGP plugin to handle those messages." msgstr "" #: gajim/common/modules/misc.py:39 msgid "" "This message was encrypted with OpenPGP for XMPP and could not be decrypted." msgstr "" #: gajim/common/modules/misc.py:42 #, python-format msgid "This message was encrypted with %s and could not be decrypted." msgstr "" #: gajim/common/modules/adhoc_commands.py:89 msgid "Change status information" msgstr "Alterar informação de status" #: gajim/common/modules/adhoc_commands.py:113 msgid "Change status" msgstr "Alterar status" #: gajim/common/modules/adhoc_commands.py:114 msgid "Set the presence type and description" msgstr "Definir o tipo e a descrição da presença" #: gajim/common/modules/adhoc_commands.py:121 msgid "Free for chat" msgstr "Livre para conversa" #: gajim/common/modules/adhoc_commands.py:122 msgid "Online" msgstr "Conectado" #: gajim/common/modules/adhoc_commands.py:124 msgid "Extended away" msgstr "Muito afastado" #: gajim/common/modules/adhoc_commands.py:125 msgid "Do not disturb" msgstr "Não perturbe" #: gajim/common/modules/adhoc_commands.py:126 msgid "Offline - disconnect" msgstr "Desconectado" #: gajim/common/modules/adhoc_commands.py:132 msgid "Presence description:" msgstr "Descrição da presença:" #: gajim/common/modules/adhoc_commands.py:171 msgid "The status has been changed." msgstr "O status foi alterado." #: gajim/common/modules/adhoc_commands.py:205 #: gajim/common/modules/adhoc_commands.py:242 msgid "Leave Groupchats" msgstr "Sair das salas" #: gajim/common/modules/adhoc_commands.py:231 #, python-format msgid "%(nickname)s on %(room_jid)s" msgstr "%(nickname)s da sala %(room_jid)s" #: gajim/common/modules/adhoc_commands.py:235 msgid "You have not joined a groupchat." msgstr "Você não entrou em uma sala." #: gajim/common/modules/adhoc_commands.py:243 msgid "Choose the groupchats you want to leave" msgstr "Selecione as salas das quais você quer sair" #: gajim/common/modules/adhoc_commands.py:292 msgid "You left the following groupchats:" msgstr "Você saiu das seguintes salas:" #: gajim/common/modules/user_tune.py:51 msgid "Unknown Artist" msgstr "Artista desconhecido" #: gajim/common/modules/user_tune.py:54 msgid "Unknown Title" msgstr "Título desconhecido" #: gajim/common/modules/user_tune.py:57 msgid "Unknown Source" msgstr "Fonte desconhecida" #: gajim/common/modules/user_tune.py:60 #, python-format msgid "" "\"%(title)s\" by %(artist)s\n" "from %(source)s" msgstr "" "\"%(title)s\" por %(artist)s\n" "de %(source)s" #: gajim/common/modules/roster_item_exchange.py:100 #, fuzzy, python-format msgid "Sent contact: \"%(jid)s\" (%(name)s)" msgstr "Enviar contato: \"%s\" (%s)" #: gajim/common/modules/roster_item_exchange.py:104 msgid "Sent contacts:" msgstr "Enviar contatos:" #: gajim/data/gui/blocked_contacts_window.ui:13 msgid "Blocked Contacts" msgstr "Contatos bloqueados" #: gajim/data/gui/advanced_configuration_window.ui:13 msgid "Advanced Configuration Editor" msgstr "Editor de configurações avançado" #: gajim/data/gui/advanced_configuration_window.ui:35 msgid "Filter:" msgstr "Filtro:" #: gajim/data/gui/advanced_configuration_window.ui:107 #: gajim/data/gui/features_window.ui:78 msgid "Description" msgstr "Descrição" #: gajim/data/gui/advanced_configuration_window.ui:136 msgid "NOTE: You should restart Gajim for some settings to take effect" msgstr "" "NOTA: Você deve reiniciar o Gajim para que algumas configurações " "tenham efeito" #: gajim/data/gui/advanced_configuration_window.ui:161 #, fuzzy msgid "_Reset to default" msgstr "Voltar para as cores _padrões" #: gajim/data/gui/join_groupchat_window.ui:56 #: gajim/data/gui/chat_to_muc_window.ui:67 #: gajim/data/gui/chat_to_muc_window.ui:78 msgid "column" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:97 msgid "Join group chat every time Gajim is started" msgstr "" #: gajim/data/gui/join_groupchat_window.ui:113 #: gajim/data/gui/manage_bookmarks_window.ui:301 #, fuzzy msgid "Auto Join" msgstr "Ingresso automático" #: gajim/data/gui/join_groupchat_window.ui:131 #: gajim/data/gui/profile_window.ui:233 msgid "Account" msgstr "Conta" #: gajim/data/gui/join_groupchat_window.ui:147 #, fuzzy msgid "Room" msgstr "Sala:" #: gajim/data/gui/join_groupchat_window.ui:180 gajim/gtk/accounts.py:788 #, fuzzy msgid "Password" msgstr "Senha:" #: gajim/data/gui/join_groupchat_window.ui:253 #, fuzzy msgid "Bookmark group chat" msgstr "Adicionar esta sala aos marcadores" #: gajim/data/gui/join_groupchat_window.ui:270 #, fuzzy msgid "Bookmark" msgstr "Ma_rcadores" #: gajim/data/gui/join_groupchat_window.ui:339 #, fuzzy msgid "Recently used group chats" msgstr "em uma c_onferência" #: gajim/data/gui/join_groupchat_window.ui:360 msgid "Search group chats on selected server" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:12 msgid "HTTP Connect" msgstr "Conexão HTTP" #: gajim/data/gui/manage_proxies_window.ui:15 msgid "SOCKS5" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:18 msgid "BOSH" msgstr "" #: gajim/data/gui/manage_proxies_window.ui:25 msgid "Manage Proxy Profiles" msgstr "Gerenciar perfis de proxy" #: gajim/data/gui/manage_proxies_window.ui:148 msgid "_Name:" msgstr "_Nome:" #: gajim/data/gui/manage_proxies_window.ui:161 msgid "_Type:" msgstr "_Tipo:" #: gajim/data/gui/manage_proxies_window.ui:205 msgid "Properties" msgstr "Propriedades" #: gajim/data/gui/manage_proxies_window.ui:234 msgid "_BOSH URL:" msgstr "URL _BOSH:" #: gajim/data/gui/manage_proxies_window.ui:258 msgid "Proxy _Host:" msgstr "Máqu_ina Proxy:" #: gajim/data/gui/manage_proxies_window.ui:269 msgid "Use HTTP prox_y" msgstr "Usar prox_y HTTP" #: gajim/data/gui/manage_proxies_window.ui:288 msgid "Proxy _Port:" msgstr "_Porta do máquina:" #: gajim/data/gui/manage_proxies_window.ui:299 msgid "Use proxy auth_entication" msgstr "Usar aut_enticação de proxy" #: gajim/data/gui/manage_proxies_window.ui:318 msgid "_Username:" msgstr "Nome de _usuário:" #: gajim/data/gui/manage_proxies_window.ui:331 msgid "Pass_word:" msgstr "_Senha:" #: gajim/data/gui/manage_proxies_window.ui:391 msgid "Settings" msgstr "Configurações" #: gajim/data/gui/change_password_dialog.ui:17 #, fuzzy msgid "New Password" msgstr "Salvar senha" #: gajim/data/gui/change_password_dialog.ui:31 #, fuzzy msgid "Confirm New Password" msgstr "Alterar senha" #: gajim/data/gui/zeroconf_information_window.ui:8 #: gajim/data/gui/vcard_information_window.ui:8 msgid "Contact Information" msgstr "Informações do contato" #: gajim/data/gui/zeroconf_information_window.ui:54 msgid "Local jid:" msgstr "JID local:" #: gajim/data/gui/zeroconf_information_window.ui:67 #: gajim/data/gui/tooltip_roster_contact.ui:55 #: gajim/data/gui/tooltip_gc_contact.ui:75 msgid "Resource:" msgstr "Recurso:" #: gajim/data/gui/zeroconf_information_window.ui:80 #: gajim/data/gui/tooltip_roster_contact.ui:110 msgid "Status:" msgstr "Status:" #: gajim/data/gui/zeroconf_information_window.ui:89 msgid "_Log conversation history" msgstr "_Histórico de conversação" #: gajim/data/gui/zeroconf_information_window.ui:215 #: gajim/data/gui/vcard_information_window.ui:390 msgid "Contact" msgstr "Contato" #: gajim/data/gui/zeroconf_information_window.ui:234 msgid "First Name:" msgstr "Primeiro nome:" #: gajim/data/gui/zeroconf_information_window.ui:247 msgid "Last Name:" msgstr "Último nome:" #: gajim/data/gui/zeroconf_information_window.ui:260 #: gajim/data/gui/tooltip_roster_contact.ui:30 #: gajim/data/gui/tooltip_gc_contact.ui:50 msgid "Jabber ID:" msgstr "Jabber ID:" #: gajim/data/gui/zeroconf_information_window.ui:273 msgid "E-Mail:" msgstr "Email:" #: gajim/data/gui/zeroconf_information_window.ui:354 #: gajim/data/gui/profile_window.ui:825 msgid "Personal" msgstr "Pessoal" #: gajim/data/gui/gc_occupants_menu.ui:12 msgid "_Send Private Message" msgstr "_Enviar mensagem privada" #: gajim/data/gui/gc_occupants_menu.ui:21 msgid "Send _File" msgstr "Enviar _arquivo" #: gajim/data/gui/gc_occupants_menu.ui:29 msgid "Occupant Actions" msgstr "Ações de ocupante" #: gajim/data/gui/gc_occupants_menu.ui:38 msgid "_Voice" msgstr "_Voz" #: gajim/data/gui/gc_occupants_menu.ui:46 msgid "Mo_derator" msgstr "Mo_derador" #: gajim/data/gui/gc_occupants_menu.ui:60 msgid "_Member" msgstr "_Membro" #: gajim/data/gui/gc_occupants_menu.ui:68 msgid "_Admin" msgstr "_Administração" #: gajim/data/gui/gc_occupants_menu.ui:76 msgid "_Owner" msgstr "Proprietári_o" #: gajim/data/gui/gc_occupants_menu.ui:90 msgid "_Kick" msgstr "_Chutar" #: gajim/data/gui/gc_occupants_menu.ui:98 msgid "_Ban" msgstr "_Banir" #: gajim/data/gui/gc_occupants_menu.ui:124 msgid "_Add to Roster" msgstr "_Adicionar à lista" #: gajim/data/gui/gc_occupants_menu.ui:132 #, fuzzy msgid "_Execute command" msgstr "_Executar comando" #: gajim/data/gui/tooltip_roster_contact.ui:125 msgid "Idle since:" msgstr "Ocioso desde:" #: gajim/data/gui/tooltip_roster_contact.ui:151 msgid "Mood:" msgstr "Humor:" #: gajim/data/gui/tooltip_roster_contact.ui:164 msgid "Activity:" msgstr "Atividade:" #: gajim/data/gui/tooltip_roster_contact.ui:178 #, fuzzy msgid "Tune:" msgstr "Sintonia:" #: gajim/data/gui/tooltip_roster_contact.ui:191 #, fuzzy msgid "Location:" msgstr "Notificação" #: gajim/data/gui/tooltip_roster_contact.ui:255 #, fuzzy msgid "OpenPGP:" msgstr "OpenPGP: " #: gajim/data/gui/tooltip_roster_contact.ui:281 msgid "Subscription:" msgstr "Inscrição:" #: gajim/data/gui/zeroconf_context_menu.ui:11 #: gajim/data/gui/account_context_menu.ui:11 msgid "_Status" msgstr "_Status" #: gajim/data/gui/zeroconf_context_menu.ui:26 #: gajim/data/gui/account_context_menu.ui:79 msgid "_Modify Account..." msgstr "_Alterar conta..." #: gajim/data/gui/atom_entry_window.ui:8 msgid "New entry received" msgstr "Novo evento recebido" #: gajim/data/gui/atom_entry_window.ui:92 msgid "Feed name:" msgstr "Nome do feed:" #: gajim/data/gui/atom_entry_window.ui:119 msgid "Entry:" msgstr "Entrada:" #: gajim/data/gui/atom_entry_window.ui:131 msgid "Last modified:" msgstr "Modificado:" #: gajim/data/gui/atom_entry_window.ui:196 msgid "Next entry" msgstr "" #: gajim/data/gui/gc_control_popup_menu.ui:11 msgid "Change _Nickname..." msgstr "Alterar _apelido..." #: gajim/data/gui/gc_control_popup_menu.ui:20 msgid "_Manage Room" msgstr "_Gerenciar sala" #: gajim/data/gui/gc_control_popup_menu.ui:31 msgid "Change _Subject..." msgstr "Alterar as_sunto..." #: gajim/data/gui/gc_control_popup_menu.ui:38 msgid "Configure _Room..." msgstr "Configurar _sala..." #: gajim/data/gui/gc_control_popup_menu.ui:52 msgid "_Destroy Room" msgstr "_Excluir sala" #: gajim/data/gui/gc_control_popup_menu.ui:64 msgid "_Minimize on close" msgstr "_Minimizar ao fechar" #: gajim/data/gui/gc_control_popup_menu.ui:85 #, fuzzy msgid "_Request Voice" msgstr "_Voz" #: gajim/data/gui/profile_window.ui:67 #, fuzzy msgid "Clear Avatar" msgstr "Avatar do usuário:" #: gajim/data/gui/profile_window.ui:137 #, fuzzy msgid "Set Avatar…" msgstr "Escolha imagem" #: gajim/data/gui/profile_window.ui:175 #: gajim/data/gui/vcard_information_window.ui:412 msgid "Full Name" msgstr "Nome Completo" #: gajim/data/gui/profile_window.ui:307 gajim/data/gui/profile_window.ui:1004 #: gajim/data/gui/vcard_information_window.ui:721 #: gajim/data/gui/vcard_information_window.ui:1397 #, fuzzy msgid "Phone No." msgstr "Telefone" #: gajim/data/gui/profile_window.ui:344 #: gajim/data/gui/vcard_information_window.ui:765 msgid "Format: YYYY-MM-DD" msgstr "Formato: YYYY-MM-DD" #: gajim/data/gui/profile_window.ui:351 #: gajim/data/gui/vcard_information_window.ui:771 msgid "Birthday" msgstr "Aniversário" #: gajim/data/gui/profile_window.ui:370 #: gajim/data/gui/vcard_information_window.ui:689 #: gajim/data/gui/plugins_window.ui:323 #, fuzzy msgid "Homepage" msgstr "Site pessoal:" #: gajim/data/gui/profile_window.ui:387 gajim/data/gui/profile_window.ui:976 #: gajim/data/gui/vcard_information_window.ui:705 #: gajim/data/gui/vcard_information_window.ui:1381 #, fuzzy msgid "E-Mail" msgstr "Email:" #: gajim/data/gui/profile_window.ui:404 gajim/data/gui/mam_preferences.ui:184 #: gajim/data/gui/vcard_information_window.ui:55 gajim/gtk/add_contact.py:29 #: gajim/gtk/accounts.py:704 msgid "Jabber ID" msgstr "Jabber ID" #: gajim/data/gui/profile_window.ui:440 msgid "Main" msgstr "" #. Family Name #: gajim/data/gui/profile_window.ui:462 #: gajim/data/gui/vcard_information_window.ui:806 msgid "Family" msgstr "Família" #. Given Name #: gajim/data/gui/profile_window.ui:489 #: gajim/data/gui/vcard_information_window.ui:897 #, fuzzy msgid "Given" msgstr "Nome:" #. Middle Name #: gajim/data/gui/profile_window.ui:516 #: gajim/data/gui/vcard_information_window.ui:822 #, fuzzy msgid "Middle" msgstr "Nome do meio:" #. Prefix in Name #: gajim/data/gui/profile_window.ui:532 #: gajim/data/gui/vcard_information_window.ui:838 #, fuzzy msgid "Prefix" msgstr "Prefixo:" #. Suffix in Name #: gajim/data/gui/profile_window.ui:569 #: gajim/data/gui/vcard_information_window.ui:913 #, fuzzy msgid "Suffix" msgstr "Sobrenome:" #: gajim/data/gui/profile_window.ui:596 gajim/data/gui/profile_window.ui:1031 #: gajim/data/gui/vcard_information_window.ui:490 #: gajim/data/gui/vcard_information_window.ui:1180 #, fuzzy msgid "Street" msgstr "Estressado" #: gajim/data/gui/profile_window.ui:624 gajim/data/gui/profile_window.ui:1058 #: gajim/data/gui/vcard_information_window.ui:580 #: gajim/data/gui/vcard_information_window.ui:1228 msgid "Extra Address" msgstr "Complemento" #: gajim/data/gui/profile_window.ui:652 gajim/data/gui/profile_window.ui:1085 #: gajim/data/gui/vcard_information_window.ui:506 #: gajim/data/gui/vcard_information_window.ui:1196 #, fuzzy msgid "City" msgstr "Cidade:" #: gajim/data/gui/profile_window.ui:669 gajim/data/gui/profile_window.ui:1148 #: gajim/data/gui/vcard_information_window.ui:522 #: gajim/data/gui/vcard_information_window.ui:1212 #, fuzzy msgid "State" msgstr "Estado:" #: gajim/data/gui/profile_window.ui:716 gajim/data/gui/profile_window.ui:1112 #: gajim/data/gui/vcard_information_window.ui:596 #: gajim/data/gui/vcard_information_window.ui:1245 msgid "Postal Code" msgstr "Código Postal" #: gajim/data/gui/profile_window.ui:743 gajim/data/gui/profile_window.ui:1175 #: gajim/data/gui/vcard_information_window.ui:612 #: gajim/data/gui/vcard_information_window.ui:1261 #, fuzzy msgid "Country" msgstr "País:" #: gajim/data/gui/profile_window.ui:761 gajim/data/gui/profile_window.ui:1192 #: gajim/data/gui/vcard_information_window.ui:672 #: gajim/data/gui/vcard_information_window.ui:1364 msgid "Address" msgstr "Endereço" #: gajim/data/gui/profile_window.ui:786 #: gajim/data/gui/vcard_information_window.ui:959 #, fuzzy msgid "Name Details" msgstr "Nome:" #: gajim/data/gui/profile_window.ui:853 #: gajim/data/gui/vcard_information_window.ui:1041 #, fuzzy msgid "Company" msgstr "Empresa:" #: gajim/data/gui/profile_window.ui:881 #: gajim/data/gui/vcard_information_window.ui:1074 msgid "Department" msgstr "Departamento" #: gajim/data/gui/profile_window.ui:908 #: gajim/data/gui/vcard_information_window.ui:1105 #, fuzzy msgid "Position" msgstr "Cargo:" #: gajim/data/gui/profile_window.ui:1207 #, fuzzy msgid "Contact" msgstr "Tempo do contato:" #: gajim/data/gui/profile_window.ui:1261 #: gajim/data/gui/vcard_information_window.ui:1453 msgid "Work" msgstr "Trabalho" #. "About" is the text of a tab of vcard window #: gajim/data/gui/profile_window.ui:1297 #: gajim/data/gui/vcard_information_window.ui:1485 #: gajim/data/gui/application_menu.ui:62 msgid "About" msgstr "Sobre" #: gajim/data/gui/filetransfers.ui:20 #, fuzzy msgid "Con_tinue" msgstr "_Continuar" #: gajim/data/gui/filetransfers.ui:28 gajim/data/gui/filetransfers.ui:135 msgid "_Pause" msgstr "_Pausa" #: gajim/data/gui/filetransfers.ui:36 gajim/data/gui/filetransfers.ui:152 msgid "_Cancel" msgstr "_Cancelar" #: gajim/data/gui/filetransfers.ui:50 msgid "_Open Containing Folder" msgstr "_Abrir pasta do arquivo" #: gajim/data/gui/filetransfers.ui:59 gajim/data/gui/filetransfers.ui:228 msgid "File Transfers" msgstr "Transferência de arquivos" #: gajim/data/gui/filetransfers.ui:90 msgid "file transfers list" msgstr "lista de transferência de arquivos" #: gajim/data/gui/filetransfers.ui:91 msgid "A list of active, completed and stopped file transfers" msgstr "Uma lista de transferências de arquivo ativas, completadas e paradas" #: gajim/data/gui/filetransfers.ui:111 msgid "Clean _up" msgstr "_Limpar" #: gajim/data/gui/filetransfers.ui:117 #, fuzzy msgid "Remove completed, cancelled and failed file transfers from the list" msgstr "" "Remover da lista as transferências de arquivos completas, canceladas ou " "interrompidas" #: gajim/data/gui/filetransfers.ui:122 msgid "Remove file transfer from the list." msgstr "Remover a transferência de arquivo da lista." #: gajim/data/gui/filetransfers.ui:123 msgid "" "This action removes single file transfer from the list. If the transfer is " "active, it is first stopped and then removed" msgstr "" "Esta ação remove uma única transferência de arquivo da lista. Se a " "transferência está ativa, isto vai pará-la e removê-la" #: gajim/data/gui/filetransfers.ui:158 #, fuzzy msgid "Cancel the selected file transfer and remove incomplete files" msgstr "" "Cancela a transferência de arquivo selecionada e remove o arquivo incompleto" #: gajim/data/gui/filetransfers.ui:163 msgid "Cancel file transfer" msgstr "Cancelar transferência de arquivo" #: gajim/data/gui/filetransfers.ui:164 msgid "Cancels the selected file transfer" msgstr "Cancela a transferência de arquivo selecionada" #: gajim/data/gui/filetransfers.ui:176 #, fuzzy msgid "_Close" msgstr "_Enviar & fechar" #: gajim/data/gui/filetransfers.ui:182 #, fuzzy msgid "Hide the window" msgstr "Esconder a janela" #: gajim/data/gui/filetransfers.ui:202 msgid "_Notify me when a file transfer is complete" msgstr "_Notificar-me quando a transmissão do arquivo terminar" #: gajim/data/gui/filetransfers.ui:211 msgid "When a file transfer is complete show a popup notification" msgstr "Exibir um alerta visual quanto uma transferência de arquivo terminar" #: gajim/data/gui/filetransfers.ui:229 msgid "Shows a list of file transfers between you and others" msgstr "Exibe uma lista de transferências de arquivos entre você e os outros" #: gajim/data/gui/groupchat_control.ui:13 gajim/data/gui/chat_control.ui:293 msgid "Bold" msgstr "Negrito" #: gajim/data/gui/groupchat_control.ui:22 gajim/data/gui/chat_control.ui:302 msgid "Italic" msgstr "Itálico" #: gajim/data/gui/groupchat_control.ui:31 gajim/data/gui/chat_control.ui:311 msgid "Underline" msgstr "Sublinhado" #: gajim/data/gui/groupchat_control.ui:40 gajim/data/gui/chat_control.ui:320 msgid "Strike" msgstr "Tachado" #: gajim/data/gui/groupchat_control.ui:54 gajim/data/gui/chat_control.ui:334 #: gajim/gtk/advanced_config.py:91 msgid "Color" msgstr "Cor" #: gajim/data/gui/groupchat_control.ui:62 gajim/data/gui/chat_control.ui:342 msgid "Font" msgstr "Fonte" #: gajim/data/gui/groupchat_control.ui:76 gajim/data/gui/chat_control.ui:356 #, fuzzy msgid "Clear formatting" msgstr "Limpar formatação" #: gajim/data/gui/groupchat_control.ui:286 gajim/data/gui/chat_control.ui:874 #, fuzzy msgid "Choose encryption" msgstr "Escolha o arquivo para enviar..." #: gajim/data/gui/groupchat_control.ui:332 gajim/data/gui/chat_control.ui:656 #, fuzzy msgid "Show a list of emojis (Alt+M)" msgstr "Exibe uma lista de emoticons (Alt+M)" #: gajim/data/gui/popup_notification_window.ui:55 #, fuzzy msgid "Event Type" msgstr "Evento" #: gajim/data/gui/popup_notification_window.ui:100 #, fuzzy msgid "Event desc" msgstr "Eventos" #: gajim/data/gui/chat_control.ui:44 #, fuzzy msgid "1" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:66 #, fuzzy msgid "2 abc" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:87 #, fuzzy msgid "3 def" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:108 #, fuzzy msgid "4 ghi" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:129 #, fuzzy msgid "5 jkl" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:150 #, fuzzy msgid "6 mno" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:170 msgid "7 pqrs" msgstr "" #: gajim/data/gui/chat_control.ui:191 #, fuzzy msgid "8 tuv" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:212 msgid "9 wxyz" msgstr "" #: gajim/data/gui/chat_control.ui:232 #, fuzzy msgid "*" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:252 #, fuzzy msgid "0" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:272 #, fuzzy msgid "#" msgstr "Fonte" #: gajim/data/gui/chat_control.ui:453 msgid "The last message was written on a mobile client" msgstr "" #: gajim/data/gui/chat_control.ui:787 msgid "#" msgstr "#" #: gajim/data/gui/mam_preferences.ui:14 gajim/data/gui/preferences_window.ui:92 #: gajim/data/gui/preferences_window.ui:143 #, fuzzy msgid "Always" msgstr "Afastado" #: gajim/data/gui/mam_preferences.ui:18 #, fuzzy msgid "Roster" msgstr "Exibir _lista" #: gajim/data/gui/mam_preferences.ui:22 gajim/data/gui/preferences_window.ui:86 #: gajim/data/gui/preferences_window.ui:146 #, fuzzy msgid "Never" msgstr "_Nunca" #: gajim/data/gui/mam_preferences.ui:111 #, fuzzy msgid "Default:" msgstr "Padrão" #: gajim/data/gui/mam_preferences.ui:203 #, fuzzy msgid "Archive" msgstr "O arquivo está vazio" #: gajim/data/gui/vcard_information_window.ui:72 gajim/gtk/accounts.py:657 #, fuzzy msgid "Resource" msgstr "Recurso:" #: gajim/data/gui/vcard_information_window.ui:89 #: gajim/data/gui/preferences_window.ui:1280 #: gajim/data/gui/preferences_window.ui:1480 msgid "Status" msgstr "Status" #: gajim/data/gui/vcard_information_window.ui:106 #, fuzzy msgid "Client" msgstr "Cliente:" #: gajim/data/gui/vcard_information_window.ui:123 #: gajim/data/gui/preferences_window.ui:1588 msgid "System" msgstr "Sistema" #: gajim/data/gui/vcard_information_window.ui:140 #, fuzzy msgid "Contact time" msgstr "Nome do contato" #: gajim/data/gui/vcard_information_window.ui:240 msgid "User avatar" msgstr "Avatar do usuário" #: gajim/data/gui/vcard_information_window.ui:255 msgid "Configured avatar" msgstr "Avatar configurado" #. Given Name #: gajim/data/gui/vcard_information_window.ui:287 #, fuzzy msgid "Ask" msgstr "Perguntar:" #. Family Name #: gajim/data/gui/vcard_information_window.ui:304 #, fuzzy msgid "Subscription" msgstr "Inscrição:" #: gajim/data/gui/vcard_information_window.ui:974 #: gajim/data/gui/vcard_information_window.ui:993 #: gajim/data/gui/vcard_information_window.ui:1427 msgid "button" msgstr "" #: gajim/data/gui/vcard_information_window.ui:1018 msgid "Personal Info" msgstr "Informações pessoais" #: gajim/data/gui/vcard_information_window.ui:1515 msgid "Comments" msgstr "Comentários" #: gajim/data/gui/preferences_window.ui:38 #, fuzzy msgid "Use default applications" msgstr "Sempre usar as aplicações padrões do OS/X" #: gajim/data/gui/preferences_window.ui:41 msgid "Custom" msgstr "Personalizar" #: gajim/data/gui/preferences_window.ui:52 #: gajim/data/gui/preferences_window.ui:69 #, fuzzy msgid "All chat states" msgstr "Totos os status" #: gajim/data/gui/preferences_window.ui:55 #: gajim/data/gui/preferences_window.ui:72 #, fuzzy msgid "Composing only" msgstr "Escrevendo" #: gajim/data/gui/preferences_window.ui:58 #: gajim/data/gui/preferences_window.ui:75 #: gajim/data/gui/preferences_window.ui:1590 msgid "Disabled" msgstr "Desabilitado" #: gajim/data/gui/preferences_window.ui:89 msgid "Only when pending events" msgstr "Apenas para eventos pendentes" #: gajim/data/gui/preferences_window.ui:103 #, fuzzy msgid "Pop it up" msgstr "_Alerta visual" #: gajim/data/gui/preferences_window.ui:106 #, fuzzy msgid "Notify me about it" msgstr "_Notifique-me sobre isto" #: gajim/data/gui/preferences_window.ui:109 #, fuzzy msgid "Show only in roster" msgstr "Mostre somente na _lista" #: gajim/data/gui/preferences_window.ui:120 msgid "Detached roster with detached chats" msgstr "" #: gajim/data/gui/preferences_window.ui:123 msgid "Detached roster with single chat" msgstr "" #: gajim/data/gui/preferences_window.ui:126 msgid "Single window for everything" msgstr "" #: gajim/data/gui/preferences_window.ui:129 msgid "Detached roster with chat grouped by account" msgstr "" #: gajim/data/gui/preferences_window.ui:132 msgid "Detached roster with chat grouped by type" msgstr "" #: gajim/data/gui/preferences_window.ui:149 msgid "Last state" msgstr "Último estado" #: gajim/data/gui/preferences_window.ui:214 msgid "Display a_vatars of contacts in roster" msgstr "Exibir a_vatar dos contatos na lista" #: gajim/data/gui/preferences_window.ui:218 msgid "" "If checked, Gajim will display avatars of contacts in roster window and in " "group chats" msgstr "" "Se marcado, Gajim exibirá avatars dos contatos na janela da lista e na " "conferência" #: gajim/data/gui/preferences_window.ui:232 msgid "Display status _messages of contacts in roster" msgstr "Exibir _mensagem de status da lista de contato" #: gajim/data/gui/preferences_window.ui:236 #, fuzzy msgid "" "If checked, Gajim will display status messages of contacts under the contact " "name, in roster window and in group chats" msgstr "" "Se marcado, Gajim indicará mensagens de status dos contatos sob o nome do " "contato na janela da lista e na conferência" #: gajim/data/gui/preferences_window.ui:250 #, fuzzy msgid "Display e_xtra information of contacts in roster (mood, activity, ...)" msgstr "Exibir hum_or dos contatos na lista" #: gajim/data/gui/preferences_window.ui:254 msgid "" "If checked, Gajim will display the mood of contacts in the roster window" msgstr "Se marcado, Gajim exibirá o humor dos contatos na janela da lista" #: gajim/data/gui/preferences_window.ui:275 msgid "Sort contacts by status" msgstr "Ordena contatos pelo status" #: gajim/data/gui/preferences_window.ui:285 msgid "in _roster" msgstr "na _lista" #: gajim/data/gui/preferences_window.ui:302 msgid "in _group chats" msgstr "em uma c_onferência" #: gajim/data/gui/preferences_window.ui:331 msgid "Roster Appearance" msgstr "Aparência da lista" #: gajim/data/gui/preferences_window.ui:359 #, fuzzy msgid "Spell _checker" msgstr "Verificador ortográfico" #: gajim/data/gui/preferences_window.ui:362 msgid "" "If checked, Gajim will highlight spelling errors in input fields of chat " "windows. If no language is explicitly set via right click on the input " "field, the default language will be used for this contact or group chat." msgstr "" "Se marcado, o Gajim irá destacar erros de ortografia em campos de entrada " "nas janelas de conversa. Se nenhuma linguagem foi explicitamente definida " "através de um clique com o botão direito no campo de entrada, a linguagem " "padrão será usada para este contato ou conferência." #: gajim/data/gui/preferences_window.ui:376 #, fuzzy msgid "Show message recei_pts" msgstr "conteúdos da mensagem" #: gajim/data/gui/preferences_window.ui:393 msgid "Show _avatar in chat tabs" msgstr "" #: gajim/data/gui/preferences_window.ui:413 #, fuzzy msgid "_Window behavior" msgstr "Comportamento da jan_ela:" #: gajim/data/gui/preferences_window.ui:469 #, fuzzy msgid "_Show roster on startup" msgstr "Exibi_r lista" #: gajim/data/gui/preferences_window.ui:484 msgid "_Ignore rich content in incoming messages" msgstr "_Ignorar conteúdo formatado nas mensagens recebidas" #: gajim/data/gui/preferences_window.ui:488 msgid "" "Some messages may include rich content (formatting, colors etc). If checked, " "Gajim will just display the raw message text." msgstr "" "Algumas mensagens podem incluir conteúdo rico (formatação, cores etc). Se " "marcado, o Gajim apenas exibirá as mensagens em texto puro." #: gajim/data/gui/preferences_window.ui:503 #, fuzzy msgid "Show subject after joining a group chat" msgstr "Impossível ingressar na sala" #: gajim/data/gui/preferences_window.ui:523 msgid "Chat Appearance" msgstr "Aparência da conversa" #: gajim/data/gui/preferences_window.ui:582 #, fuzzy msgid "When new event is received" msgstr "Quando novo evento é recebido:" #: gajim/data/gui/preferences_window.ui:623 msgid "Notify me about contacts that sign _in" msgstr "Notifique-me sobre contatos ao _conectar" #: gajim/data/gui/preferences_window.ui:641 msgid "Notify me about contacts that sign _out" msgstr "Notifique-me sobre contatos ao _desconectar" #: gajim/data/gui/preferences_window.ui:645 msgid "" "Gajim will notify you via a popup window in the bottom right of the screen " "about contacts that just signed out" msgstr "" "Gajim notificará você através de um alerta visual na parte inferior direita " "da tela sobre os contatos que se desconectaram" #: gajim/data/gui/preferences_window.ui:659 msgid "Allow popup/notifications when I'm _away/na/busy/invisible" msgstr "" "Permite janela/notificação quando eu estou _afastado/ND/ocupado/invisível" #: gajim/data/gui/preferences_window.ui:676 #, fuzzy msgid "Allow popup/notifications when a chat window is opened" msgstr "" "Permite janela/notificação quando eu estou _afastado/ND/ocupado/invisível" #: gajim/data/gui/preferences_window.ui:701 #, fuzzy msgid "Show notification area icon" msgstr "Usar ícone na bandeja (também conhecido por área de notificação)" #: gajim/data/gui/preferences_window.ui:745 msgid "Visual Notifications" msgstr "Notificações visuais" #: gajim/data/gui/preferences_window.ui:778 msgid "Play _sounds" msgstr "Tocar _sons" #: gajim/data/gui/preferences_window.ui:795 #: gajim/data/gui/preferences_window.ui:1551 msgid "Ma_nage..." msgstr "Gere_nciar..." #: gajim/data/gui/preferences_window.ui:818 msgid "Allow sound when I'm _busy" msgstr "Permitir som quando eu estiver _ocupado" #: gajim/data/gui/preferences_window.ui:840 msgid "Sounds" msgstr "Sons" #: gajim/data/gui/preferences_window.ui:861 msgid "Notifications" msgstr "Notificações" #: gajim/data/gui/preferences_window.ui:898 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "display in chat windows." msgstr "" "O Gajim pode enviar e receber meta-informações relacionadas a conversação " "que você pode ter com um contato. Aqui você pode especificar quais " "caracteres você quer para enviar a outra parte." #: gajim/data/gui/preferences_window.ui:904 #, fuzzy msgid "_Display chat state notifications" msgstr "_Exibir notificações de status de conversa:" #: gajim/data/gui/preferences_window.ui:959 msgid "" "Gajim can send and receive meta-information related to a conversation you " "may have with a contact. Here you can specify which chatstates you want to " "send to the other party." msgstr "" "Gajim pode enviar e receber meta-informações relacionadas a conversação que " "você pode ter com um contato. Aqui você pode especificar quais caracteres " "você quer para enviar a outra parte." #: gajim/data/gui/preferences_window.ui:965 #, fuzzy msgid "_Send chat state notifications" msgstr "_Enviar notificações de status de conversa:" #: gajim/data/gui/preferences_window.ui:987 msgid "Chat state notifications" msgstr "Notificações do estado da conversa" #: gajim/data/gui/preferences_window.ui:1009 msgid "Personal Events" msgstr "Eventos pessoais" #: gajim/data/gui/preferences_window.ui:1043 #, fuzzy msgid "_Away after" msgstr "_Afastado depois:" #: gajim/data/gui/preferences_window.ui:1047 msgid "" "If checked, Gajim will change status to Away when the computer is unused." msgstr "" "Se marcado, o Gajim irá alterar o status para Ausente quando o computador " "não estiver em uso." #: gajim/data/gui/preferences_window.ui:1060 #, fuzzy msgid "_Not available after" msgstr "_Não disponível depois:" #: gajim/data/gui/preferences_window.ui:1064 msgid "" "If checked, Gajim will change status to Not Available when the computer has " "not been used even longer" msgstr "" "Se marcado, o Gajim irá alterar o status para Não disponível quando o " "computador não estiver mais em uso" #: gajim/data/gui/preferences_window.ui:1080 #: gajim/data/gui/preferences_window.ui:1092 msgid "minutes" msgstr "minutos" #: gajim/data/gui/preferences_window.ui:1103 msgid "" "The auto away status message. If empty, Gajim will not change the current " "status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-away timeout" msgstr "" "A mensagem de status de ausência automática. Se vazia, o Gajim não irá " "alterar a mensagem de status atual\n" "$S será substituída pela mensagem de status anterior\n" "$T será substituída pela mensagem automática de ausência" #: gajim/data/gui/preferences_window.ui:1118 msgid "" "The auto not available status message. If empty, Gajim will not change the " "current status message\n" "$S will be replaced by previous status message\n" "$T will be replaced by auto-not-available timeout" msgstr "" "A mensagem de status de não disponibilidade automática. Se vazia, o Gajim " "não irá alterar a mensagem de status atual\n" "$S irá ser substituída pela mensagem de status anterior\n" "$T irá ser substituída pela mensagem de ausência automática" #: gajim/data/gui/preferences_window.ui:1166 msgid "Auto Status" msgstr "Status automático" #: gajim/data/gui/preferences_window.ui:1202 #, fuzzy msgid "Ask status message when I" msgstr "Solicite uma mensagem de status quanto eu:" #: gajim/data/gui/preferences_window.ui:1218 msgid "Sign _in" msgstr "_Conectar" #: gajim/data/gui/preferences_window.ui:1235 msgid "Sign _out" msgstr "_Desconectar" #: gajim/data/gui/preferences_window.ui:1268 msgid "" "If enabled, Gajim will not ask for a status message. The specified default " "message will be used instead." msgstr "" "Se habilitado, o Gajim não irá perguntar por mensagem de status. A mensagem " "padrão especificada será usada neste caso." #: gajim/data/gui/preferences_window.ui:1291 msgid "Default Message" msgstr "Mensagem padrão" #: gajim/data/gui/preferences_window.ui:1306 #: gajim/data/gui/preferences_window.ui:1589 msgid "Enabled" msgstr "Habilitado" #: gajim/data/gui/preferences_window.ui:1332 msgid "Status Messages" msgstr "Mensagens de status" #: gajim/data/gui/preferences_window.ui:1460 msgid "Preset Status Messages" msgstr "Mensagens de status disponíveis" #: gajim/data/gui/preferences_window.ui:1509 gajim/data/gui/themes_window.ui:65 #, fuzzy msgid "Themes" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1525 #, fuzzy msgid "_Theme" msgstr "Tema" #: gajim/data/gui/preferences_window.ui:1556 msgid "Configure color and font of the interface" msgstr "Configurar cores e fontes da interface" #: gajim/data/gui/preferences_window.ui:1570 #, fuzzy msgid "_Dark Theme" msgstr "gajim-remote" #: gajim/data/gui/preferences_window.ui:1604 msgid "Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1621 #, fuzzy msgid "_Emoji Theme" msgstr "gajim-remote" #: gajim/data/gui/preferences_window.ui:1650 msgid "Icons" msgstr "" #: gajim/data/gui/preferences_window.ui:1667 #, fuzzy msgid "_Status iconset" msgstr "_Conjunto de ícones de status:" #: gajim/data/gui/preferences_window.ui:1693 #, fuzzy msgid "Use transports _icons" msgstr "Usar ícones de _transportes" #: gajim/data/gui/preferences_window.ui:1697 #, fuzzy msgid "" "If checked, Gajim will use protocol-specific status icons. (e.g. A contact " "from ICQ will have the equivalent ICQ icon for status online, away, busy, " "etc...)" msgstr "" "Se marcado, o Gajim usará ícones protocolo-específicos do status. (por " "exemplo, um contato do MSN terá o ícone equivalente do MSN para o status " "conectado, ausente, ocupado, etc....)" #: gajim/data/gui/preferences_window.ui:1724 msgid "_Convert ASCII Emojis" msgstr "" #: gajim/data/gui/preferences_window.ui:1808 msgid "Style" msgstr "Estilo" #: gajim/data/gui/preferences_window.ui:1845 msgid "Audio input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1860 msgid "Audio output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1898 #, fuzzy msgid "Audio" msgstr "Ações" #: gajim/data/gui/preferences_window.ui:1929 msgid "Video input device" msgstr "" #: gajim/data/gui/preferences_window.ui:1944 msgid "Video output device" msgstr "" #: gajim/data/gui/preferences_window.ui:1959 msgid "Video framerate" msgstr "" #: gajim/data/gui/preferences_window.ui:1974 msgid "Video size" msgstr "" #: gajim/data/gui/preferences_window.ui:1986 msgid "View own video source" msgstr "" #: gajim/data/gui/preferences_window.ui:2050 #, fuzzy msgid "Video" msgstr "Nome do meio:" #: gajim/data/gui/preferences_window.ui:2081 #, fuzzy msgid "STUN server" msgstr "Servidor:" #: gajim/data/gui/preferences_window.ui:2110 msgid "" "STUN server hostname. If none given, Gajim will try\n" "to discover one from server." msgstr "" #: gajim/data/gui/preferences_window.ui:2124 msgid "(example: stun.iptel.org)" msgstr "" #: gajim/data/gui/preferences_window.ui:2138 #, fuzzy msgid "Connection" msgstr "Condições" #: gajim/data/gui/preferences_window.ui:2159 #, fuzzy msgid "Audio/Video" msgstr "Áudio / Vídeo" #: gajim/data/gui/preferences_window.ui:2229 #, fuzzy msgid "_Mail client" msgstr "_Cliente de email:" #: gajim/data/gui/preferences_window.ui:2246 #, fuzzy msgid "_Browser" msgstr "_Navegar:" #: gajim/data/gui/preferences_window.ui:2263 #, fuzzy msgid "_File manager" msgstr "_Gerenciamento de arquivos:" #. a header for custom browser/client/file manager. so translate sth like: Custom Settings #: gajim/data/gui/preferences_window.ui:2314 msgid "Custom" msgstr "Customizar" #: gajim/data/gui/preferences_window.ui:2331 msgid "Applications" msgstr "Aplicações" #: gajim/data/gui/preferences_window.ui:2359 msgid "_Ignore events from contacts not in the roster" msgstr "_Ignore eventos de contatos que não estejam na minha lista" #: gajim/data/gui/preferences_window.ui:2363 msgid "" "If checked, Gajim will ignore incoming events from unauthorized contacts. " "Use with caution, because it blocks all messages from any contact that is " "not in the roster" msgstr "" "Se marcado, o Gajim irá ignorar eventos que venham de contatos não " "autorizados. Utilize com cuidado, porque isto bloqueia todas as mensagens de " "qualquer contato que você não possuir na sua lista" #: gajim/data/gui/preferences_window.ui:2377 #, fuzzy msgid "Allow client / _OS information to be sent" msgstr "Permitir o envio de informações do _SO" #: gajim/data/gui/preferences_window.ui:2381 msgid "" "If checked, Gajim will allow others to detect the operation system you are " "using" msgstr "" "Se marcado, o Gajim irá permitir que os outros detectem qual o sistema " "operacional está usando" #: gajim/data/gui/preferences_window.ui:2395 #, fuzzy msgid "Allow local system time information to be sent" msgstr "Permitir o envio de informações do _SO" #: gajim/data/gui/preferences_window.ui:2399 #, fuzzy msgid "If checked, Gajim will allow others to detect the time on your system" msgstr "" "Se marcado, o Gajim irá permitir que os outros detectem qual o sistema " "operacional está usando" #: gajim/data/gui/preferences_window.ui:2413 #, fuzzy msgid "Allow my _idle time to be sent" msgstr "Permitir o envio de informações do _SO" #: gajim/data/gui/preferences_window.ui:2437 msgid "Global proxy" msgstr "" #: gajim/data/gui/preferences_window.ui:2472 msgid "_Manage..." msgstr "Gere_nciar..." #: gajim/data/gui/preferences_window.ui:2500 msgid "Privacy" msgstr "Privacidade" #: gajim/data/gui/preferences_window.ui:2527 msgid "_Log status changes of contacts" msgstr "_Log mudanças de status dos contatos" #: gajim/data/gui/preferences_window.ui:2544 msgid "Enable debug logging" msgstr "" #: gajim/data/gui/preferences_window.ui:2565 msgid "Miscellaneous" msgstr "Diversos" #: gajim/data/gui/preferences_window.ui:2584 msgid "_Open..." msgstr "_Abrir..." #: gajim/data/gui/preferences_window.ui:2600 msgid "Advanced Configuration Editor" msgstr "Editor de configurações avançadas" #: gajim/data/gui/contact_context_menu.ui:12 msgid "Start _Chat" msgstr "Iniciar _conversa" #: gajim/data/gui/contact_context_menu.ui:20 #: gajim/data/gui/systray_context_menu.ui:36 msgid "Send Single _Message..." msgstr "Enviar _mensagem simples..." #: gajim/data/gui/contact_context_menu.ui:28 msgid "Send _File..." msgstr "Enviar _arquivo..." #: gajim/data/gui/contact_context_menu.ui:44 msgid "Invite _Contacts" msgstr "Convidar _contatos" #: gajim/data/gui/contact_context_menu.ui:73 msgid "E_xecute Command..." msgstr "E_xecutar comando..." #: gajim/data/gui/contact_context_menu.ui:82 #, fuzzy msgid "M_anage Contact" msgstr "_Gerenciar contato" #: gajim/data/gui/contact_context_menu.ui:92 msgid "_Rename..." msgstr "_Renomear..." #: gajim/data/gui/contact_context_menu.ui:99 msgid "Edit _Groups..." msgstr "Editar _grupos..." #: gajim/data/gui/contact_context_menu.ui:106 msgid "Assign Open_PGP Key..." msgstr "Atribuir chave Open_PGP..." #: gajim/data/gui/contact_context_menu.ui:115 msgid "Add Special _Notification..." msgstr "Adicionar _notificação especial..." #: gajim/data/gui/contact_context_menu.ui:129 msgid "_Subscription" msgstr "_Inscrição" #: gajim/data/gui/contact_context_menu.ui:138 #, fuzzy msgid "_Allow contact to see my status" msgstr "D_eixar este contato ver meu status" #: gajim/data/gui/contact_context_menu.ui:146 #, fuzzy msgid "A_sk to see contact status" msgstr "P_eça para ver o status dele/dela" #: gajim/data/gui/contact_context_menu.ui:154 #, fuzzy msgid "_Forbid contact to see my status" msgstr "_Proibir ele/ela de ver meu status" #: gajim/data/gui/contact_context_menu.ui:182 msgid "_Unignore" msgstr "Nã_o ignorar" #: gajim/data/gui/contact_context_menu.ui:190 msgid "_Ignore" msgstr "_Ignorar" #: gajim/data/gui/contact_context_menu.ui:197 msgid "_Add to Roster..." msgstr "_Adicionar à lista..." #: gajim/data/gui/account_creation_wizard_window.ui:43 msgid "Gajim: Account Creation Wizard" msgstr "Gajim: Assistente de configuração de conta" #: gajim/data/gui/account_creation_wizard_window.ui:70 msgid "" "You need to have an account in order to connect\n" "to the Jabber network." msgstr "" "Você precisa ter uma conta para conectar na\n" "rede Jabber." #: gajim/data/gui/account_creation_wizard_window.ui:95 msgid "I already have an account I want to _use" msgstr "Eu já tenho uma conta e quero _usá-la" #: gajim/data/gui/account_creation_wizard_window.ui:112 msgid "I want to _register for a new account" msgstr "Eu quero _registrar uma nova conta" #: gajim/data/gui/account_creation_wizard_window.ui:133 msgid "Please choose one of the options below:" msgstr "Por favor escolha uma das opções abaixo:" #: gajim/data/gui/account_creation_wizard_window.ui:167 msgid "Please fill in the data for your existing account" msgstr "Por favor, preencha os dados para sua conta existente" #: gajim/data/gui/account_creation_wizard_window.ui:187 msgid "_Jabber ID:" msgstr "_Jabber ID:" #: gajim/data/gui/account_creation_wizard_window.ui:239 #: gajim/data/gui/account_creation_wizard_window.ui:394 msgid "Anon_ymous authentication" msgstr "Autenticação anôn_ima" #: gajim/data/gui/account_creation_wizard_window.ui:259 msgid "_Password:" msgstr "_Senha:" #: gajim/data/gui/account_creation_wizard_window.ui:281 msgid "Save pass_word" msgstr "Salvar sen_ha" #: gajim/data/gui/account_creation_wizard_window.ui:285 msgid "If checked, Gajim will remember the password for this account" msgstr "Se marcado, o Gajim irá memorizar a senha para esta conta" #: gajim/data/gui/account_creation_wizard_window.ui:339 msgid "Please select a server" msgstr "Por favor, selecione um servidor" #: gajim/data/gui/account_creation_wizard_window.ui:358 msgid "_Server:" msgstr "_Servidor:" #: gajim/data/gui/account_creation_wizard_window.ui:423 msgid "Prox_y:" msgstr "Prox_y:" #: gajim/data/gui/account_creation_wizard_window.ui:450 msgid "Manage..." msgstr "Gerenciar..." #: gajim/data/gui/account_creation_wizard_window.ui:465 msgid "Use custom hostname/port" msgstr "Usa nome de máquina/porta customizados" #: gajim/data/gui/account_creation_wizard_window.ui:491 msgid "_Hostname:" msgstr "_Nome do computador:" #: gajim/data/gui/account_creation_wizard_window.ui:517 msgid "_Port:" msgstr "_Porta:" #: gajim/data/gui/account_creation_wizard_window.ui:553 #: gajim/data/gui/account_creation_wizard_window.ui:884 msgid "_Advanced" msgstr "_Avançado" #: gajim/data/gui/account_creation_wizard_window.ui:624 msgid "" "Add this certificate to the list of trusted certificates.\n" "SHA1 fingerprint of the certificate:\n" msgstr "" "Adicionar este certificado na lista de certificados confiáveis.\n" "SHA1 fingerprint do certificado:\n" #: gajim/data/gui/account_creation_wizard_window.ui:687 msgid "" "Connecting to server\n" "\n" "Please wait..." msgstr "" "Conectando ao servidor\n" "\n" "Por favor aguarde..." #: gajim/data/gui/account_creation_wizard_window.ui:772 msgid "Connect when I press Finish" msgstr "Conectar quando eu clicar em Concluir" #: gajim/data/gui/account_creation_wizard_window.ui:789 msgid "Set my profile when I connect" msgstr "Configurar perfil quando eu conectar" #: gajim/data/gui/account_creation_wizard_window.ui:901 msgid "_Finish" msgstr "_Concluir" #: gajim/data/gui/privacy_lists_window.ui:34 msgid "Privacy Lists:" msgstr "Listas de privacidade:" #: gajim/data/gui/service_discovery_window.ui:87 msgid "_Address:" msgstr "_Endereço:" #: gajim/data/gui/service_discovery_window.ui:118 msgid "G_o" msgstr "_Ir" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:8 msgid "Synchronise : select contacts" msgstr "Sincronizar: selecionar contatos" #: gajim/data/gui/synchronise_select_contacts_dialog.ui:67 msgid "Select the contacts you want to synchronise" msgstr "Selecione os contatos que você quer sincronizar" #: gajim/data/gui/edit_groups_dialog.ui:8 msgid "Edit Groups" msgstr "Editar grupos" #: gajim/data/gui/search_window.ui:42 msgid "Please wait while retrieving search form..." msgstr "" "Por favor aguarde enquanto o formulário de pesquisa está sendo obtido..." #: gajim/data/gui/search_window.ui:80 msgid "_Add contact" msgstr "_Adicionar contato" #: gajim/data/gui/search_window.ui:116 msgid "_Search" msgstr "_Buscar" #: gajim/data/gui/change_status_message_dialog.ui:116 msgid "Save this message as a preset" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:152 #, fuzzy msgid "Preset _messages" msgstr "Modelos de mensagens" #: gajim/data/gui/change_status_message_dialog.ui:170 #, fuzzy msgid "Ac_tivity" msgstr "Atividade" #: gajim/data/gui/change_status_message_dialog.ui:187 msgid "M_ood" msgstr "" #: gajim/data/gui/change_status_message_dialog.ui:314 msgid "_Type your new status message" msgstr "_Digite sua nova mensagem de status" #: gajim/data/gui/synchronise_select_account_dialog.ui:8 msgid "Synchronise contacts" msgstr "Sincronizar contatos" #: gajim/data/gui/synchronise_select_account_dialog.ui:68 msgid "Select the account with which you want to synchronise" msgstr "Selecione a conta que você quer sincronizar" #: gajim/data/gui/voip_call_received_dialog.ui:15 msgid "Incoming call" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:79 #, fuzzy msgid "_Jabber ID" msgstr "_Jabber ID:" #: gajim/data/gui/add_new_contact_window.ui:95 #: gajim/data/gui/manage_bookmarks_window.ui:189 #, fuzzy msgid "_Nickname" msgstr "_Apelido:" #: gajim/data/gui/add_new_contact_window.ui:112 #, fuzzy msgid "_Group" msgstr "_Grupo:" #: gajim/data/gui/add_new_contact_window.ui:159 msgid "Choose or type new group name" msgstr "" #: gajim/data/gui/add_new_contact_window.ui:174 #, fuzzy msgid "A_ccount" msgstr "C_onta:" #: gajim/data/gui/add_new_contact_window.ui:190 #, fuzzy msgid "_Protocol" msgstr "_Protocolo:" #: gajim/data/gui/add_new_contact_window.ui:290 #, fuzzy msgid "A_llow contact to view my status" msgstr "D_eixar este contato ver meu status" #: gajim/data/gui/add_new_contact_window.ui:341 #, fuzzy msgid "_Save subscription message" msgstr "_Inscrição" #: gajim/data/gui/add_new_contact_window.ui:367 #, fuzzy msgid "" "You have to register with this transport\n" "to be able to add a contact from this\n" "protocol. Click on Register button to\n" "proceed." msgstr "" "Você deve estar registrado para este \n" "transporte para poder adicionar \n" "contatos deste protocolo. Clique no \n" "botão Registrar para aceitar." #: gajim/data/gui/add_new_contact_window.ui:382 msgid "_Register" msgstr "_Registrar" #: gajim/data/gui/add_new_contact_window.ui:411 msgid "" "You must be connected to the transport to be able\n" "to add a contact from this protocol." msgstr "" "Você deve estar conectado para que o transporte \n" "possa adicionar um contato desse protocolo." #: gajim/data/gui/roster_window.ui:61 #, fuzzy msgid "Change Status Message…" msgstr "_Mudar mensagem de status" #: gajim/data/gui/change_mood_dialog.ui:73 msgid "Mood:" msgstr "Humor:" #: gajim/data/gui/change_mood_dialog.ui:85 msgid "Message:" msgstr "Mensagem:" #: gajim/data/gui/plugins_window.ui:10 gajim/data/gui/application_menu.ui:90 msgid "Plugins" msgstr "" #: gajim/data/gui/plugins_window.ui:74 msgid "Install Plugin from File" msgstr "" #: gajim/data/gui/plugins_window.ui:75 msgid "Install from File…" msgstr "" #: gajim/data/gui/plugins_window.ui:89 #, fuzzy msgid "Uninstall Plugin" msgstr "Parado" #: gajim/data/gui/plugins_window.ui:135 #, fuzzy msgid "" msgstr "Falha ao registrar" #: gajim/data/gui/plugins_window.ui:152 #, fuzzy msgid "Plugin Settings" msgstr "Falha ao registrar" #: gajim/data/gui/plugins_window.ui:234 #, fuzzy msgid "" msgstr "Descrição" #: gajim/data/gui/plugins_window.ui:258 #, fuzzy msgid "Version" msgstr "Versão do GTK+:" #: gajim/data/gui/plugins_window.ui:290 #, fuzzy msgid "Authors" msgstr "Au_torizar" #: gajim/data/gui/plugins_window.ui:338 msgid "" msgstr "" #: gajim/data/gui/plugins_window.ui:368 #, fuzzy msgid "Installed" msgstr "Parado" #: gajim/data/gui/plugins_window.ui:384 msgid "" "Plug-in decription should be displayed here. This text will be erased during " "PluginsWindow initialization." msgstr "" #: gajim/data/gui/privacy_list_window.ui:18 #, fuzzy msgid "none" msgstr "um" #: gajim/data/gui/privacy_list_window.ui:21 #, fuzzy msgid "both" msgstr "Ambos" #: gajim/data/gui/privacy_list_window.ui:24 #, fuzzy msgid "from" msgstr "De" #: gajim/data/gui/privacy_list_window.ui:27 #, fuzzy msgid "to" msgstr "dois" #: gajim/data/gui/privacy_list_window.ui:47 gajim/gtk/privacy_list.py:76 msgid "Privacy List" msgstr "Lista de privacidade" #: gajim/data/gui/privacy_list_window.ui:66 msgid "Privacy List" msgstr "Lista de privacidade" #: gajim/data/gui/privacy_list_window.ui:77 msgid "Active for this session" msgstr "Ativo para esta sessão" #: gajim/data/gui/privacy_list_window.ui:94 msgid "Active on each startup" msgstr "Ativar ao iniciar o programa" #: gajim/data/gui/privacy_list_window.ui:132 msgid "List of rules" msgstr "Lista de regras" #: gajim/data/gui/privacy_list_window.ui:244 msgid "Add / Edit a rule" msgstr "Adicionar / Editar regra" #: gajim/data/gui/privacy_list_window.ui:266 msgid "Allow" msgstr "Permitir" #: gajim/data/gui/privacy_list_window.ui:282 msgid "Deny" msgstr "Negar" #: gajim/data/gui/privacy_list_window.ui:317 msgid "JabberID" msgstr "Jabber ID" #: gajim/data/gui/privacy_list_window.ui:358 msgid "all in the group" msgstr "todos no grupo" #: gajim/data/gui/privacy_list_window.ui:407 msgid "all by subscription" msgstr "todos por inscrição" #: gajim/data/gui/privacy_list_window.ui:456 msgid "All" msgstr "Todos" #: gajim/data/gui/privacy_list_window.ui:493 msgid "to send me messages" msgstr "para me enviar mensagens" #: gajim/data/gui/privacy_list_window.ui:509 msgid "to send me queries" msgstr "para enviar minhas requisições" #: gajim/data/gui/privacy_list_window.ui:525 msgid "to view my status" msgstr "para ver meu status" #: gajim/data/gui/privacy_list_window.ui:541 msgid "to send me status" msgstr "para seu status para mim" #: gajim/data/gui/privacy_list_window.ui:557 msgid "All (including subscription)" msgstr "Todos (incluindo inscrições)" #: gajim/data/gui/privacy_list_window.ui:598 msgid "Order:" msgstr "Ordem:" #: gajim/data/gui/manage_sounds_window.ui:23 #, fuzzy msgid "Manage sounds" msgstr "Gerenciar contas" #: gajim/data/gui/manage_sounds_window.ui:52 gajim/plugins/gui.py:99 msgid "Active" msgstr "Ativo" #: gajim/data/gui/manage_sounds_window.ui:66 msgid "Event" msgstr "Evento" #: gajim/data/gui/manage_sounds_window.ui:95 msgid "Choose Sound" msgstr "Escolher som" #: gajim/data/gui/remove_account_window.ui:56 msgid "Remove account _only from Gajim" msgstr "Remover conta _somente do Gajim" #: gajim/data/gui/remove_account_window.ui:73 msgid "Remove account from Gajim and from _server" msgstr "Remover conta do Gajim e do _servidor" #: gajim/data/gui/remove_account_window.ui:94 msgid "What do you want to do?" msgstr "O que você quer fazer?" #: gajim/data/gui/adhoc_commands_window.ui:35 msgid "Please wait while retrieving command list..." msgstr "Por favor aguarde enquanto a lista de comandos é recuperada..." #: gajim/data/gui/adhoc_commands_window.ui:67 msgid "Choose command to execute:" msgstr "Escolha um comando para executar" #: gajim/data/gui/adhoc_commands_window.ui:110 #: gajim/data/gui/adhoc_commands_window.ui:197 msgid "Check once more" msgstr "Verificar novamente" #: gajim/data/gui/adhoc_commands_window.ui:147 #, fuzzy msgid "Please wait while the command is being sent..." msgstr "Por favor aguarde enquanto a lista de comandos é enviada..." #: gajim/data/gui/adhoc_commands_window.ui:183 msgid "This jabber entity does not expose any commands." msgstr "Esta entidade jabber não expõe quaisquer comandos." #: gajim/data/gui/adhoc_commands_window.ui:233 msgid "An error has occurred:" msgstr "Ocorreu um erro:" #: gajim/data/gui/adhoc_commands_window.ui:339 #, fuzzy msgid "F_inish" msgstr "_Concluir" #: gajim/data/gui/account_context_menu.ui:20 msgid "_Personal Events" msgstr "Eventos _pessoais" #: gajim/data/gui/account_context_menu.ui:35 #: gajim/data/gui/systray_context_menu.ui:28 msgid "Join _Group Chat" msgstr "_Entrar em uma conferência" #: gajim/data/gui/account_context_menu.ui:49 msgid "_Add Contact..." msgstr "_Adicionar contato..." #: gajim/data/gui/account_context_menu.ui:57 msgid "_Discover Services" msgstr "_Descubra serviços" #: gajim/data/gui/account_context_menu.ui:65 msgid "_Execute Command..." msgstr "_Executar comando..." #: gajim/data/gui/application_menu.ui:8 #, fuzzy msgid "View" msgstr "_Ver" #: gajim/data/gui/application_menu.ui:11 #, fuzzy msgid "Show Roster" msgstr "Exibir _lista" #: gajim/data/gui/application_menu.ui:16 #, fuzzy msgid "Show Offline Contacts" msgstr "Exibir desc_onectados" #: gajim/data/gui/application_menu.ui:21 #, fuzzy msgid "Show Active Contacts" msgstr "Exibir somente _ativos" #: gajim/data/gui/application_menu.ui:26 #, fuzzy msgid "Show Transports" msgstr "Exibir trans_portes" #: gajim/data/gui/application_menu.ui:43 #, fuzzy msgid "Help" msgstr "_Ajuda" #: gajim/data/gui/application_menu.ui:46 #, fuzzy msgid "Contents" msgstr "Índi_ces" #: gajim/data/gui/application_menu.ui:50 #, fuzzy msgid "FAQ" msgstr "_FAQ" #: gajim/data/gui/application_menu.ui:54 msgid "Keyboard Shortcuts" msgstr "" #: gajim/data/gui/application_menu.ui:58 gajim/gtk/features.py:37 msgid "Features" msgstr "Recursos" #: gajim/data/gui/application_menu.ui:81 #, fuzzy msgid "Bookmarks" msgstr "Ma_rcadores" #: gajim/data/gui/application_menu.ui:94 gajim/data/gui/shortcuts_window.ui:175 #: gajim/gtk/preferences.py:60 gajim/gtk/accounts.py:367 msgid "Preferences" msgstr "Preferências" #: gajim/data/gui/application_menu.ui:99 #, fuzzy msgid "Quit" msgstr "_Sair" #: gajim/data/gui/httpupload_progress_dialog.ui:71 #, fuzzy msgid "Cancel Upload" msgstr "_Cancelar" #: gajim/data/gui/features_window.ui:22 msgid "List of possible features in Gajim:" msgstr "Listas dos possíveis recursos do Gajim:" #: gajim/data/gui/manage_bookmarks_window.ui:13 #, fuzzy msgid "Group Chat Bookmarks" msgstr "_Conferência" #: gajim/data/gui/manage_bookmarks_window.ui:143 #, fuzzy msgid "Bookmark Name" msgstr "Adicionar esta sala aos marcadores" #: gajim/data/gui/manage_bookmarks_window.ui:158 #, fuzzy msgid "_Server" msgstr "_Servidor:" #: gajim/data/gui/manage_bookmarks_window.ui:219 msgid "Roo_m" msgstr "" #: gajim/data/gui/manage_bookmarks_window.ui:248 #, fuzzy msgid "_Password" msgstr "_Senha:" #: gajim/data/gui/manage_bookmarks_window.ui:293 #, fuzzy msgid "Join chat when connected" msgstr "Contato desconectou" #: gajim/data/gui/manage_bookmarks_window.ui:342 #, fuzzy msgid "Minimize on Auto Join" msgstr "Minimizar ao entrar automaticamente" #: gajim/data/gui/manage_bookmarks_window.ui:376 #, fuzzy msgid "Status messages displayed in chat window" msgstr "Enviar mensagem e fechar a janela" #: gajim/data/gui/manage_bookmarks_window.ui:384 #, fuzzy msgid "Status Messages" msgstr "Mensagem de status" #: gajim/data/gui/send_file_dialog.ui:43 #, fuzzy msgid "Description:" msgstr "Descrição: " #: gajim/data/gui/send_file_dialog.ui:76 #, fuzzy msgid "Select Files" msgstr "Limpando" #: gajim/data/gui/send_file_dialog.ui:90 gajim/gtk/xml_console.py:83 #, fuzzy msgid "Send" msgstr "_Enviar" #: gajim/data/gui/send_file_dialog.ui:106 #, fuzzy msgid "Files:" msgstr "Arquivo: " #: gajim/data/gui/exception_dialog.ui:45 #, fuzzy msgid "" "A programming error has been detected. It probably is not fatal, but should " "be reported to the developers nonetheless." msgstr "Não é provavelmente fatal, mas deve ser reportado aos desenvolvedores." #: gajim/data/gui/exception_dialog.ui:115 #, fuzzy msgid "Report Bug" msgstr "_Reportar erro" #: gajim/data/gui/subscription_request_window.ui:12 msgid "_Start Chat" msgstr "_Iniciar conversa" #: gajim/data/gui/subscription_request_window.ui:95 msgid "_Deny" msgstr "_Negar" #: gajim/data/gui/subscription_request_window.ui:100 msgid "" "Deny authorization from contact so he or she cannot know when you're " "connected" msgstr "" "Negar a autorização do contato, assim ele não poderá saber quando você está " "conectado" #: gajim/data/gui/subscription_request_window.ui:133 msgid "Au_thorize" msgstr "Au_torizar" #: gajim/data/gui/subscription_request_window.ui:138 msgid "Authorize contact so he or she can know when you're connected" msgstr "" "Autorize o contato para que ele ou ela saiba quando você estiver conectado" #: gajim/data/gui/xml_console_window.ui:149 #, fuzzy msgid "Presets" msgstr "_Presença" #: gajim/data/gui/emoji_chooser.ui:98 #, fuzzy msgid "No Results Found" msgstr "Sem resultados" #: gajim/data/gui/chat_to_muc_window.ui:24 msgid "Invite Friends!" msgstr "Convidar amigos!" #: gajim/data/gui/chat_to_muc_window.ui:39 #, fuzzy msgid "" "You are now entering a groupchat.\n" "Select the contacts you want to invite" msgstr "" "Você está prestes a iniciar uma Conversa Multi-Usuário (MUC).\n" "Selecione os contatos que você quer convidar" #: gajim/data/gui/chat_to_muc_window.ui:112 msgid "Please select a MUC server." msgstr "Por favor, selecione um servidor MUC." #: gajim/data/gui/chat_to_muc_window.ui:141 msgid "MUC server" msgstr "Servidor MUC" #: gajim/data/gui/chat_to_muc_window.ui:176 msgid "In_vite" msgstr "Con_vidar" #: gajim/data/gui/history_manager.ui:11 #, fuzzy msgid "_Export" msgstr "Exportar" #: gajim/data/gui/history_manager.ui:93 msgid "Welcome to Gajim History Logs Manager" msgstr "Gerenciador de histórico de conversas do Gajim" #: gajim/data/gui/history_manager.ui:107 msgid "" "This log manager is not intended for log viewing. If you are looking for " "such functionality, use the history window instead.\n" "\n" "Use this program to delete or export logs. You can select logs from the left " "and/or search database from below." msgstr "" "Este gerenciador de logs não tem a intenção de ser um visualizador de logs. " "Se você está procurando por esta funcionalidade, use a janela de histórico.\n" "\n" "Use este programa para deletar ou exportar logs. Você pode selecionar logs " "ao lado e/ou pesquisar na base de dados abaixo." #: gajim/data/gui/history_manager.ui:123 msgid "" "WARNING:\n" "If you plan to do massive deletions, please make sure Gajim is not running. " "Generally avoid deletions with contacts you currently chat with." msgstr "" "CUIDADO:\n" "Se você planeja fazer apagamentos maciços, certifique-se por favor que o " "Gajim não está executando. Evite apagamentos com contatos que você esteja " "conversando no momento." #: gajim/data/gui/history_manager.ui:222 msgid "_Search Database" msgstr "_Buscar no banco de dados" #: gajim/data/gui/shortcuts_window.ui:8 msgid "Chat Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:12 #, fuzzy msgid "Message composition" msgstr "Conteúdo da mensagem" #: gajim/data/gui/shortcuts_window.ui:17 #, fuzzy msgid "Send the message" msgstr "Enviar mensagem" #: gajim/data/gui/shortcuts_window.ui:24 #, fuzzy msgid "Add new line" msgstr "Criar nova postagem" #: gajim/data/gui/shortcuts_window.ui:31 msgid "Select an emoji" msgstr "" #: gajim/data/gui/shortcuts_window.ui:38 msgid "Complete a command or a nick" msgstr "" #: gajim/data/gui/shortcuts_window.ui:45 #, fuzzy msgid "Previously sent message" msgstr "Modelos de mensagens" #: gajim/data/gui/shortcuts_window.ui:52 #, fuzzy msgid "Next sent messages" msgstr "Modelos de mensagens" #: gajim/data/gui/shortcuts_window.ui:59 #, fuzzy msgid "Quote previous message" msgstr "mensagem de status" #: gajim/data/gui/shortcuts_window.ui:66 #, fuzzy msgid "Quote next message" msgstr "Enviar mensagem" #: gajim/data/gui/shortcuts_window.ui:73 #, fuzzy msgid "Clear message entry" msgstr "Mensagem enviada" #: gajim/data/gui/shortcuts_window.ui:81 #, fuzzy msgid "Recent history" msgstr "Recentemente:" #: gajim/data/gui/shortcuts_window.ui:86 msgid "Scroll up" msgstr "" #: gajim/data/gui/shortcuts_window.ui:93 msgid "Scroll down" msgstr "" #: gajim/data/gui/shortcuts_window.ui:100 gajim/gtk/xml_console.py:69 #, fuzzy msgid "Clear" msgstr "Limpando" #: gajim/data/gui/shortcuts_window.ui:108 msgid "Tabs" msgstr "" #: gajim/data/gui/shortcuts_window.ui:113 msgid "Switch to the previous tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:120 msgid "Switch to the next tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:127 msgid "Switch to the first - ninth tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:134 msgid "Switch to the previous unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:141 msgid "Switch to the next unread tab" msgstr "" #: gajim/data/gui/shortcuts_window.ui:148 msgid "Close chat" msgstr "" #: gajim/data/gui/shortcuts_window.ui:159 msgid "Roster Shortcuts" msgstr "" #: gajim/data/gui/shortcuts_window.ui:182 #, fuzzy msgid "File transfers" msgstr "Transferência de arquivos" #: gajim/data/gui/shortcuts_window.ui:196 #, fuzzy msgid "Join a group chat" msgstr "em uma c_onferência" #: gajim/data/gui/shortcuts_window.ui:203 #, fuzzy msgid "Set the status message" msgstr "mensagem de status" #: gajim/data/gui/shortcuts_window.ui:210 #, fuzzy msgid "Quit Gajim" msgstr "Gajim" #: gajim/data/gui/shortcuts_window.ui:218 msgid "Appearance" msgstr "Aparência" #: gajim/data/gui/shortcuts_window.ui:223 #, fuzzy msgid "Show offline contacts" msgstr "Exibir desc_onectados" #: gajim/data/gui/shortcuts_window.ui:230 #, fuzzy msgid "Show only active contacts" msgstr "Exibir somente _ativos" #: gajim/data/gui/shortcuts_window.ui:237 msgid "Enable roster filtering" msgstr "" #: gajim/data/gui/shortcuts_window.ui:245 msgid "Contacts" msgstr "Contatos" #: gajim/data/gui/shortcuts_window.ui:250 #, fuzzy msgid "Contact information" msgstr "Informações do contato" #: gajim/data/gui/shortcuts_window.ui:257 #, fuzzy msgid "Rename contact" msgstr "Renomear contato" #: gajim/data/gui/shortcuts_window.ui:264 #, fuzzy msgid "Delete contact" msgstr "Enviar contatos:" #: gajim/data/gui/passphrase_dialog.ui:8 msgid "Passphrase" msgstr "Frase de acesso" #: gajim/data/gui/history_window.ui:27 #, fuzzy msgid "Display status changes" msgstr "_Log mudanças de status dos contatos" #: gajim/data/gui/history_window.ui:233 #, fuzzy msgid "Mode" msgstr "Moderador" #: gajim/data/gui/history_window.ui:246 #, fuzzy msgid "Search complete history" msgstr "Recentemente:" #: gajim/data/gui/history_window.ui:263 msgid "Search selected day only" msgstr "" #: gajim/data/gui/history_window.ui:283 msgid "Conversation History" msgstr "Histórico de conversação" #: gajim/data/gui/history_window.ui:315 msgid "Chat" msgstr "Conversa" #: gajim/data/gui/history_window.ui:329 #, fuzzy msgid "Record history for this chat" msgstr "Ignorar este erro para este certificado." #: gajim/data/gui/history_window.ui:344 #, fuzzy msgid "Record History" msgstr "Recentemente:" #: gajim/data/gui/history_window.ui:362 #, fuzzy msgid "Ttitle" msgstr "Título:" #: gajim/data/gui/manage_pep_services_window.ui:13 msgid "PEP Service Configuration" msgstr "Configuração do serviço PEP" #: gajim/data/gui/manage_pep_services_window.ui:69 msgid "_Configure" msgstr "_Configurar" #: gajim/data/gui/groups_post_window.ui:9 msgid "Create new post" msgstr "Criar nova postagem" #: gajim/data/gui/groups_post_window.ui:29 #: gajim/data/gui/single_message_window.ui:46 msgid "From:" msgstr "De:" #: gajim/data/gui/groups_post_window.ui:41 #: gajim/data/gui/single_message_window.ui:70 msgid "Subject:" msgstr "Assunto:" #: gajim/data/gui/data_form_window.ui:19 msgid "Fill in the form." msgstr "Preencha o formulário." #: gajim/data/gui/data_form_window.ui:229 msgid "Room Configuration" msgstr "Configuração da sala" #: gajim/data/gui/roster_item_exchange_window.ui:8 msgid "Roster Item Exchange" msgstr "Troca de itens na lista de contatos" #: gajim/data/gui/roster_item_exchange_window.ui:126 gajim/gtk/dialogs.py:946 msgid "_OK" msgstr "_OK" #: gajim/data/gui/systray_context_menu.ui:12 msgid "Sta_tus" msgstr "Sta_tus" #: gajim/data/gui/systray_context_menu.ui:20 msgid "_Start Chat..." msgstr "_Iniciar conversa..." #: gajim/data/gui/systray_context_menu.ui:50 msgid "Show All Pending _Events" msgstr "Exibir todos _eventos pendentes" #: gajim/data/gui/systray_context_menu.ui:59 msgid "Mute Sounds" msgstr "Sons mudos" #: gajim/data/gui/systray_context_menu.ui:75 #, fuzzy msgid "_Preferences" msgstr "Preferências" #: gajim/data/gui/systray_context_menu.ui:90 #, fuzzy msgid "_Quit" msgstr "_Sair" #: gajim/data/gui/single_message_window.ui:59 msgid "To:" msgstr "Para:" #: gajim/data/gui/single_message_window.ui:118 msgid "0" msgstr "0" #: gajim/data/gui/single_message_window.ui:210 msgid "Sen_d" msgstr "E_nviar" #: gajim/data/gui/single_message_window.ui:216 msgid "Send message" msgstr "Enviar mensagem" #: gajim/data/gui/single_message_window.ui:229 msgid "_Reply" msgstr "_Responder" #: gajim/data/gui/single_message_window.ui:235 msgid "Reply to this message" msgstr "Resposta para esta mensagem" #: gajim/data/gui/single_message_window.ui:248 msgid "_Send & Close" msgstr "_Enviar & fechar" #: gajim/data/gui/single_message_window.ui:254 msgid "Send message and close window" msgstr "Enviar mensagem e fechar a janela" #: gajim/data/gui/change_activity_dialog.ui:8 msgid "Set Activity" msgstr "Definir atividade" #: gajim/data/gui/change_activity_dialog.ui:65 msgid "Set an activity" msgstr "Define uma atividade" #: gajim/data/gui/change_activity_dialog.ui:337 msgid "Message: " msgstr "Mensagem: " #: gajim/command_system/mapping.py:166 gajim/command_system/mapping.py:176 #: gajim/command_system/mapping.py:196 #, fuzzy msgid "Missing arguments" msgstr "Argumento não informado \"contact_jid\"" #: gajim/command_system/mapping.py:263 #, fuzzy msgid "Too many arguments" msgstr "Argumento não informado \"contact_jid\"" #: gajim/command_system/implementation/execute.py:54 msgid "Execute expression inside a shell, show output" msgstr "" #: gajim/command_system/implementation/execute.py:110 msgid "Execute expression inside a shell, send output" msgstr "" #: gajim/command_system/implementation/standard.py:45 msgid "" "Show help on a given command or a list of available commands if -a is given" msgstr "" #: gajim/command_system/implementation/standard.py:73 msgid "Send a message to the contact" msgstr "Enviar uma mensagem ao contato" #: gajim/command_system/implementation/standard.py:78 msgid "Send action (in the third person) to the current chat" msgstr "" #: gajim/command_system/implementation/standard.py:83 msgid "Show logged messages which mention given text" msgstr "" #: gajim/command_system/implementation/standard.py:88 #, fuzzy, python-format msgid "%s: Nothing found" msgstr "%s não encontrado" #: gajim/command_system/implementation/standard.py:94 msgid "Limit must be an integer" msgstr "" #: gajim/command_system/implementation/standard.py:118 msgid "" "\n" " Set the current status\n" "\n" " Status can be given as one of the following values:\n" " online, away, chat, xa, dnd.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:136 msgid "Set the current status to away" msgstr "" #: gajim/command_system/implementation/standard.py:150 msgid "Set the current status to online" msgstr "" #: gajim/command_system/implementation/standard.py:153 #, fuzzy msgid "Available" msgstr "Dis_ponível" #: gajim/command_system/implementation/standard.py:173 #: gajim/command_system/implementation/standard.py:250 msgid "Clear the text window" msgstr "Limpar a janela de texto" #: gajim/command_system/implementation/standard.py:178 #: gajim/command_system/implementation/standard.py:397 msgid "Send a ping to the contact" msgstr "Envie um ping para o contato" #: gajim/command_system/implementation/standard.py:181 #: gajim/command_system/implementation/standard.py:400 #, fuzzy msgid "Command is not supported for zeroconf accounts" msgstr "Comando sem suporte para conta zeroconf." #: gajim/command_system/implementation/standard.py:185 msgid "Send DTMF sequence through an open audio session" msgstr "" #: gajim/command_system/implementation/standard.py:188 #, fuzzy msgid "No open audio sessions with the contact" msgstr "Clique para ver o histórico de conversas com este contato" #: gajim/command_system/implementation/standard.py:191 #, fuzzy, python-format msgid "%s is not a valid tone" msgstr "%s não é um nível de gravação (loglevel) válido" #: gajim/command_system/implementation/standard.py:198 msgid "Toggle audio session" msgstr "Alternar sessão de áudio" #: gajim/command_system/implementation/standard.py:201 #, fuzzy msgid "Audio sessions are not available" msgstr "Uma conexão não está disponível" #: gajim/command_system/implementation/standard.py:208 msgid "Toggle video session" msgstr "Alternar sessão de vídeo" #: gajim/command_system/implementation/standard.py:211 #, fuzzy msgid "Video sessions are not available" msgstr "Conexão não disponível" #: gajim/command_system/implementation/standard.py:218 #, fuzzy msgid "Send a message to the contact that will attract their attention" msgstr "Enviar uma mensagem ao contato" #: gajim/command_system/implementation/standard.py:257 #, fuzzy msgid "Change your nickname in a group chat" msgstr "Alterar o seu apelido (Ctrl+N)" #: gajim/command_system/implementation/standard.py:262 gajim/gtk/dialogs.py:751 #: gajim/gtk/bookmarks.py:306 msgid "Invalid nickname" msgstr "Apelido inválido" #: gajim/command_system/implementation/standard.py:267 msgid "Open a private chat window with a specified occupant" msgstr "Abrir uma janela de conversação privada com um ocupante específico" #: gajim/command_system/implementation/standard.py:273 #: gajim/command_system/implementation/standard.py:282 #: gajim/command_system/implementation/standard.py:332 #: gajim/command_system/implementation/standard.py:345 #: gajim/command_system/implementation/standard.py:357 msgid "Nickname not found" msgstr "Apelido não encontrado" #: gajim/command_system/implementation/standard.py:276 msgid "" "Open a private chat window with a specified occupant and send him a message" msgstr "" "Abrir uma janela de conversação privada com um ocupante específico e enviar-" "lhe uma mensagem" #: gajim/command_system/implementation/standard.py:285 #, fuzzy msgid "Display or change a group chat topic" msgstr "Perguntar antes de fechar um aba ou janela de conferência." #: gajim/command_system/implementation/standard.py:294 msgid "Invite a user to a room for a reason" msgstr "" #: gajim/command_system/implementation/standard.py:297 #, python-format msgid "Invited %(jid)s to %(room_jid)s" msgstr "convidado %(jid)s para %(room_jid)s" #: gajim/command_system/implementation/standard.py:301 #, fuzzy msgid "Join a group chat given by a JID" msgstr "em uma c_onferência" #: gajim/command_system/implementation/standard.py:309 msgid "" "Leave the groupchat, optionally giving a reason, and close tab or window" msgstr "" #: gajim/command_system/implementation/standard.py:314 msgid "" "\n" " Ban user by a nick or a JID from a groupchat\n" "\n" " If given nickname is not found it will be treated as a JID.\n" " " msgstr "" #: gajim/command_system/implementation/standard.py:329 #, fuzzy msgid "Kick user by a nick from a groupchat" msgstr "Você foi convidado para uma conferência" #: gajim/command_system/implementation/standard.py:338 msgid "" "Set occupant role in group chat.\n" " Role can be given as one of the following values:\n" " moderator, participant, visitor, none" msgstr "" #: gajim/command_system/implementation/standard.py:343 #, fuzzy msgid "Invalid role given" msgstr "Servidor inválido" #: gajim/command_system/implementation/standard.py:350 msgid "" "Set occupant affiliation in group chat.\n" " Affiliation can be given as one of the following values:\n" " owner, admin, member, outcast, none" msgstr "" #: gajim/command_system/implementation/standard.py:355 #, fuzzy msgid "Invalid affiliation given" msgstr "filiação alterada" #: gajim/command_system/implementation/standard.py:365 msgid "Display names of all group chat occupants" msgstr "Mostrar nomes de todos os ocupantes da sala." #: gajim/command_system/implementation/standard.py:387 msgid "Forbid an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/standard.py:392 msgid "Allow an occupant to send you public or private messages" msgstr "" #: gajim/command_system/implementation/middleware.py:74 msgid "Error during command execution!" msgstr "" #: gajim/command_system/implementation/custom.py:107 msgid "The same as using a doc-string, except it supports translation" msgstr "" #: gajim/gtk/start_chat.py:38 #, fuzzy msgid "Start new Conversation" msgstr "Conversação continuada" #: gajim/gtk/start_chat.py:300 #, fuzzy msgid "New Groupchat" msgstr "Nova conferência" #: gajim/gtk/start_chat.py:302 #, fuzzy msgid "New Contact" msgstr "Adicionar novo contato" #: gajim/gtk/single_message.py:185 #, python-format msgid "Single Message using account %s" msgstr "Mensagem simples usando conta %s" #: gajim/gtk/single_message.py:187 #, python-format msgid "Single Message in account %s" msgstr "Mensagem simples na conta %s" #: gajim/gtk/single_message.py:189 msgid "Single Message" msgstr "Mensagem simples" #: gajim/gtk/single_message.py:192 #, python-format msgid "Send %s" msgstr "Enviar %s" #: gajim/gtk/single_message.py:215 #, python-format msgid "Received %s" msgstr "Recebido %s" #: gajim/gtk/single_message.py:238 #, python-format msgid "Form %s" msgstr "Formulário %s" #: gajim/gtk/single_message.py:266 gajim/gtk/xml_console.py:155 msgid "Connection not available" msgstr "Conexão não disponível" #: gajim/gtk/single_message.py:267 gajim/gtk/xml_console.py:156 #, python-format msgid "Please make sure you are connected with \"%s\"." msgstr "Por favor, tenha certeza que você está conectado com \"%s\"." #: gajim/gtk/single_message.py:321 #, python-format msgid "RE: %s" msgstr "RE: %s" #: gajim/gtk/single_message.py:322 #, python-format msgid "%s wrote:\n" msgstr "%s escreveu:\n" #: gajim/gtk/pep_config.py:99 msgid "PEP node was not removed" msgstr "O nó PEP não foi removido" #: gajim/gtk/pep_config.py:100 #, python-format msgid "PEP node %(node)s was not removed: %(message)s" msgstr "O nó PEP %(node)s não foi removido: %(message)s" #: gajim/gtk/pep_config.py:133 #, python-format msgid "Configure %s" msgstr "Configurar %s" #: gajim/gtk/service_registration.py:143 gajim/gtk/service_registration.py:157 #: gajim/gtk/service_registration.py:164 #, fuzzy msgid "Register" msgstr "_Registrar" #: gajim/gtk/service_registration.py:193 gajim/gtk/service_registration.py:205 #, fuzzy msgid "Registration successful" msgstr "Registro realizado com sucesso" #: gajim/gtk/dialogs.py:82 #, fuzzy, python-format msgid "Dictionary for language \"%s\" not available" msgstr "O dicionário para o idioma %s não está disponível" #: gajim/gtk/dialogs.py:83 #, fuzzy, python-format msgid "" "You have to install the dictionary \"%s\" to use spellchecking, or choose " "another language by setting the speller_language option.\n" "\n" "Highlighting misspelled words feature will not be used" msgstr "" "Você precisa instalar o dicionário %s para usar a correção ortográfica ou " "selecionar outro idioma definindo a opção speller_language.\n" "\n" "O recurso de destacar palavras grafadas incorretamente não será usado" #: gajim/gtk/dialogs.py:440 #, python-format msgid "" "You are about to connect to the account %(account)s (%(server)s) insecurely. " "This means conversations will not be encrypted, and is strongly " "discouraged.\n" "Are you sure you want to do that?" msgstr "" "Você está prestes a conectar na conta %(account)s (%(server)s) de forma " "insegura. Isto significa que as conversas não serão criptografadas, e é " "altamente desencorajado.\n" "Você tem certeza que deseja fazer isso?" #: gajim/gtk/dialogs.py:446 msgid "Gajim will NOT connect unless you check this box" msgstr "" #: gajim/gtk/dialogs.py:543 msgid "_Resume" msgstr "" #: gajim/gtk/dialogs.py:551 msgid "Re_place" msgstr "" #: gajim/gtk/dialogs.py:752 #, fuzzy msgid "The nickname contains invalid characters." msgstr "O apelido possui caracteres não permitidos." #: gajim/gtk/dialogs.py:872 gajim/gtk/dialogs.py:907 #, fuzzy, python-format msgid "Certificate for account %s" msgstr "para conta %s" #: gajim/gtk/dialogs.py:872 #, python-format msgid "" "Issued to:\n" "Common Name (CN): %(scn)s\n" "Organization (O): %(sorg)s\n" "Organizationl Unit (OU): %(sou)s\n" "Serial Number: %(sn)s\n" "\n" "Issued by:\n" "Common Name (CN): %(icn)s\n" "Organization (O): %(iorg)s\n" "Organizationl Unit (OU): %(iou)s\n" "\n" "Validity:\n" "Issued on: %(io)s\n" "Expires on: %(eo)s\n" "\n" "Fingerprint\n" "SHA-1 Fingerprint: %(sha1)s\n" "\n" "SHA-256 Fingerprint: %(sha256)s\n" msgstr "" #: gajim/gtk/dialogs.py:919 #, fuzzy msgid "View certificate…" msgstr "Certificado próprio" #: gajim/gtk/dialogs.py:932 gajim/gtk/accounts.py:795 msgid "Change Password" msgstr "Alterar senha" #: gajim/gtk/dialogs.py:959 #, fuzzy msgid "You must enter a password" msgstr "Você deve entrar com uma senha." #: gajim/gtk/dialogs.py:963 msgid "Passwords do not match" msgstr "Senhas não conferem" #: gajim/gtk/add_contact.py:30 #, fuzzy msgid "GG Number" msgstr "Número de GG:" #: gajim/gtk/add_contact.py:31 #, fuzzy msgid "ICQ Number" msgstr "Número de ICQ:" #: gajim/gtk/add_contact.py:39 #, fuzzy msgid "Add Contact" msgstr "_Adicionar contato..." #: gajim/gtk/add_contact.py:234 #, fuzzy, python-format msgid "%s Missing" msgstr "%s MiB" #: gajim/gtk/add_contact.py:235 #, python-format msgid "You must supply the %s of the new contact." msgstr "Você deve fornecer o %s do novo contato." #: gajim/gtk/add_contact.py:262 gajim/gtk/add_contact.py:268 #: gajim/gtk/add_contact.py:273 msgid "Invalid User ID" msgstr "Inválido ID do usuário" #: gajim/gtk/add_contact.py:269 msgid "The user ID must not contain a resource." msgstr "O ID do usuário não contém um recurso." #: gajim/gtk/add_contact.py:274 msgid "You cannot add yourself to your roster." msgstr "Você não pode adicionar você mesmo na sua lista." #: gajim/gtk/add_contact.py:279 #, fuzzy msgid "Account Offline" msgstr "Desconectado" #: gajim/gtk/add_contact.py:280 msgid "Your account must be online to add new contacts." msgstr "" #: gajim/gtk/add_contact.py:296 msgid "Contact already in roster" msgstr "Contato já foi adicionado à lista" #: gajim/gtk/add_contact.py:297 msgid "This contact is already listed in your roster." msgstr "Este contato já encontra-se em sua lista." #: gajim/gtk/add_contact.py:354 gajim/gtk/add_contact.py:392 msgid "User ID:" msgstr "ID do usuário:" #: gajim/gtk/add_contact.py:459 msgid "Error while adding transport contact" msgstr "Erro ao adicionar contato de transporte" #: gajim/gtk/add_contact.py:460 #, python-format msgid "" "This error occured while adding a contact for transport %(transport)s:\n" "\n" "%(error)s" msgstr "" #: gajim/gtk/themes.py:37 #, fuzzy msgid "Chatstate Composing" msgstr "Escrevendo" #: gajim/gtk/themes.py:41 #, fuzzy msgid "Chatstate Inactive" msgstr "Inativo" #: gajim/gtk/themes.py:45 msgid "Chatstate Gone" msgstr "" #: gajim/gtk/themes.py:49 #, fuzzy msgid "Chatstate Paused" msgstr "Alterar status" #: gajim/gtk/themes.py:53 msgid "MUC Tab New Directed Message" msgstr "Aba do MUC com Nova Mensagem Direcionada" #: gajim/gtk/themes.py:57 #, fuzzy msgid "MUC Tab New Message" msgstr "Nova mensagem" #: gajim/gtk/themes.py:61 msgid "Banner Foreground Color" msgstr "" #: gajim/gtk/themes.py:65 msgid "Banner Background Color" msgstr "" #: gajim/gtk/themes.py:69 msgid "Banner Font" msgstr "" #: gajim/gtk/themes.py:73 msgid "Account Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:77 msgid "Account Row Background Color" msgstr "" #: gajim/gtk/themes.py:81 #, fuzzy msgid "Account Row Font" msgstr "Conta" #: gajim/gtk/themes.py:85 msgid "Group Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:89 msgid "Group Row Background Color" msgstr "" #: gajim/gtk/themes.py:93 #, fuzzy msgid "Group Row Font" msgstr "Grupo" #: gajim/gtk/themes.py:97 msgid "Contact Row Foreground Color" msgstr "" #: gajim/gtk/themes.py:101 msgid "Contact Row Background Color" msgstr "" #: gajim/gtk/themes.py:105 #, fuzzy msgid "Contact Row Font" msgstr "Mo_strar somente na lista" #: gajim/gtk/themes.py:109 #, fuzzy msgid "Conversation Font" msgstr "Conversação com " #: gajim/gtk/themes.py:113 #, fuzzy msgid "Incoming Nickname Color" msgstr "Cor do apelido de entrada." #: gajim/gtk/themes.py:117 #, fuzzy msgid "Outgoing Nickname Color" msgstr "Cor do apelido de saída." #: gajim/gtk/themes.py:121 #, fuzzy msgid "Incoming Message Text Color" msgstr "Cor do texto de entrada." #: gajim/gtk/themes.py:125 #, fuzzy msgid "Incoming Message Text Font" msgstr "Fonte do texto de entrada." #: gajim/gtk/themes.py:129 #, fuzzy msgid "Outgoing Message Text Color" msgstr "Cor do texto de saída." #: gajim/gtk/themes.py:133 #, fuzzy msgid "Outgoing Message Text Font" msgstr "Fonte do texto de saída." #: gajim/gtk/themes.py:137 #, fuzzy msgid "Status Message Color" msgstr "Mensagem de status" #: gajim/gtk/themes.py:141 #, fuzzy msgid "Status Message Font" msgstr "Mensagem de status" #: gajim/gtk/themes.py:145 #, fuzzy msgid "URL Color" msgstr "Cor" #: gajim/gtk/themes.py:149 #, fuzzy msgid "Highlight Message Color" msgstr "_Destacar palavras mal escritas" #: gajim/gtk/themes.py:153 #, fuzzy msgid "Message Correcting" msgstr "Mensagens" #: gajim/gtk/themes.py:157 #, fuzzy msgid "Restored Message Color" msgstr "Voltar para as cores _padrões" #: gajim/gtk/themes.py:161 #, fuzzy msgid "Contact Disconnected Background" msgstr "Contato desconectou" #: gajim/gtk/themes.py:165 #, fuzzy msgid "Contact Connected Background " msgstr "Contato conectado" #: gajim/gtk/themes.py:179 #, fuzzy msgid "Gajim Themes" msgstr "gajim-remote" #: gajim/gtk/themes.py:217 gajim/gtk/themes.py:224 #, fuzzy msgid "Invalid Name" msgstr "Apelido inválido" #: gajim/gtk/themes.py:218 msgid "Name default is not allowed" msgstr "" #: gajim/gtk/themes.py:225 #, fuzzy msgid "Spaces are not allowed" msgstr "Caractere não permitido" #: gajim/gtk/themes.py:307 #, fuzzy msgid "Active Theme" msgstr "Ativo" #: gajim/gtk/themes.py:308 msgid "" "You tried to delete the currently active theme. Please switch to a different " "theme first." msgstr "" #: gajim/gtk/history.py:410 gajim/gtk/history.py:464 msgid "Disk Error" msgstr "Erro de disco" #: gajim/gtk/history.py:575 #, python-format msgid "%(nick)s is now %(status)s: %(status_msg)s" msgstr "%(nick)s é agora %(status)s: %(status_msg)s" #: gajim/gtk/history.py:588 #, python-format msgid "Error: %s" msgstr "Erro: %s" #: gajim/gtk/history.py:590 msgid "Error" msgstr "Erro" #: gajim/gtk/history.py:592 #, python-format msgid "Status is now: %(status)s: %(status_msg)s" msgstr "Status agora é: %(status)s: %(status_msg)s" #: gajim/gtk/history.py:596 #, python-format msgid "Status is now: %(status)s" msgstr "Status agora é: %(status)s" #: gajim/gtk/history_sync.py:204 #, fuzzy msgid "How far back do you want to go?" msgstr "O que você quer fazer?" #: gajim/gtk/history_sync.py:209 msgid "One Month" msgstr "" #: gajim/gtk/history_sync.py:210 msgid "Three Months" msgstr "" #: gajim/gtk/history_sync.py:211 msgid "One Year" msgstr "" #: gajim/gtk/history_sync.py:212 msgid "Everything" msgstr "" #: gajim/gtk/history_sync.py:240 #, fuzzy msgid "Connecting..." msgstr "Conectando" #: gajim/gtk/history_sync.py:252 #, python-format msgid "%(received)s of %(max)s" msgstr "%(received)s de %(max)s" #: gajim/gtk/history_sync.py:256 #, python-format msgid "Downloaded %s Messages" msgstr "Baixadas %s Mensagens" #: gajim/gtk/history_sync.py:276 #, python-brace-format msgid "" "\n" " Finished synchronising your History.\n" " {received} Messages downloaded.\n" " " msgstr "" #: gajim/gtk/history_sync.py:283 msgid "" "\n" " Gajim is fully synchronised\n" " with the Archive.\n" " " msgstr "" #: gajim/gtk/history_sync.py:290 msgid "" "\n" " There is already a synchronisation in\n" " progress. Please try later.\n" " " msgstr "" #: gajim/gtk/about.py:47 data/org.gajim.Gajim.appdata.xml.in:10 #, fuzzy msgid "A GTK+ XMPP client" msgstr "Um cliente Jabber GTK+" #: gajim/gtk/about.py:48 #, python-format msgid "GTK+ Version: %s" msgstr "Versão do GTK+: %s" #: gajim/gtk/about.py:49 #, python-format msgid "PyGObject Version: %s" msgstr "Versão do PyGObject: %s" #: gajim/gtk/about.py:50 #, python-format msgid "python-nbxmpp Version: %s" msgstr "" #: gajim/gtk/about.py:53 #, fuzzy msgid "Current Developers" msgstr "Desenvolvedores atuais:" #: gajim/gtk/about.py:54 #, fuzzy msgid "Past Developers" msgstr "Desenvolvedores passados:" #: gajim/gtk/about.py:55 msgid "Artists" msgstr "" #: gajim/gtk/about.py:59 msgid "Last but not least" msgstr "" #: gajim/gtk/about.py:60 #, fuzzy msgid "we would like to thank all the package maintainers." msgstr "Nós gostaríamos de agradecer todos os mantedores do pacote." #: gajim/gtk/about.py:61 #, fuzzy msgid "Thanks" msgstr "Agradecido" #: gajim/gtk/about.py:63 msgid "translator-credits" msgstr "" "Alfredo Jr. - Junix \n" "Juracy Filho \n" "Djavan Fagundes \n" "Og Maciel " #: gajim/gtk/filechoosers.py:87 #, fuzzy msgid "Choose File to Send…" msgstr "Escolha o arquivo para enviar..." #: gajim/gtk/filechoosers.py:93 #, fuzzy msgid "Choose Avatar…" msgstr "Escolha imagem" #: gajim/gtk/filechoosers.py:97 #, fuzzy msgid "PNG files" msgstr "Todos os arquivos" #: gajim/gtk/filechoosers.py:98 #, fuzzy msgid "JPEG files" msgstr "Todos os arquivos" #: gajim/gtk/filechoosers.py:99 #, fuzzy msgid "SVG files" msgstr "Enviar _arquivo" #: gajim/gtk/filechoosers.py:101 gajim/gtk/filechoosers.py:150 msgid "Images" msgstr "Imagens" #: gajim/gtk/filechoosers.py:135 #, fuzzy msgid "Choose Archive" msgstr "Escolha imagem" #: gajim/gtk/filechoosers.py:137 #, fuzzy msgid "ZIP files" msgstr "Todos os arquivos" #: gajim/gtk/filechoosers.py:142 #, fuzzy msgid "Save File as…" msgstr "Salvar arquivo como..." #: gajim/gtk/profile.py:72 #, fuzzy msgid "Retrieving profile…" msgstr "Recuperando perfil..." #: gajim/gtk/profile.py:187 #, fuzzy msgid "Wrong date format" msgstr "Informações do contato" #: gajim/gtk/profile.py:190 #, fuzzy msgid "Format of the date must be YYYY-MM-DD" msgstr "Formato: YYYY-MM-DD" #: gajim/gtk/profile.py:257 msgid "Information received" msgstr "Informação recebida" #: gajim/gtk/profile.py:333 #, fuzzy msgid "Without a connection, you can not publish your contact information." msgstr "Você deve estar conectado para publicar suas informações de contato." #: gajim/gtk/profile.py:346 #, fuzzy msgid "Sending profile…" msgstr "Enviando perfil..." #: gajim/gtk/profile.py:365 msgid "Information NOT published" msgstr "Informação NÃO publicada" #: gajim/gtk/profile.py:373 msgid "vCard publication failed" msgstr "Publicação do vCard falhou" #: gajim/gtk/profile.py:374 msgid "" "There was an error while publishing your personal information, try again " "later." msgstr "" "Houve um erro ao publicar sua informação pessoal, tente outra vez mais tarde." #: gajim/gtk/join_groupchat.py:202 #, fuzzy msgid "Invalid Room" msgstr "Sala inválida" #: gajim/gtk/join_groupchat.py:203 msgid "Please choose a room" msgstr "" #: gajim/gtk/join_groupchat.py:222 gajim/gtk/join_groupchat.py:229 msgid "Invalid Nickname" msgstr "Apelido inválido" #: gajim/gtk/join_groupchat.py:223 #, fuzzy msgid "Please choose a nickname" msgstr "Crie um novo tema com o nome que você desejar." #: gajim/gtk/join_groupchat.py:285 gajim/gtk/join_groupchat.py:291 #, fuzzy msgid "Wrong server" msgstr "URI incorreta" #: gajim/gtk/join_groupchat.py:286 gajim/gtk/join_groupchat.py:292 #, python-format msgid "%s is not a groupchat server" msgstr "%s não é um servidor de conferência" #: gajim/gtk/mam_preferences.py:36 #, python-format msgid "Archiving Preferences for %s" msgstr "" #: gajim/gtk/mam_preferences.py:89 msgid "Success!" msgstr "" #: gajim/gtk/mam_preferences.py:89 #, fuzzy msgid "Your Archiving Preferences have been saved!" msgstr "_Preferências" #: gajim/gtk/mam_preferences.py:100 #, fuzzy msgid "No response from the Server" msgstr "Você não está conectado ao servidor" #: gajim/gtk/mam_preferences.py:102 msgid "Error received: {}" msgstr "Erro recebido: {}" #: gajim/gtk/mam_preferences.py:106 #, fuzzy msgid "Error!" msgstr "Erro" #: gajim/gtk/advanced_config.py:86 msgid "Activated" msgstr "Ativado" #: gajim/gtk/advanced_config.py:86 msgid "Deactivated" msgstr "Desativado" #: gajim/gtk/advanced_config.py:88 msgid "Boolean" msgstr "Booleano" #: gajim/gtk/advanced_config.py:89 msgid "Integer" msgstr "Inteiro" #: gajim/gtk/advanced_config.py:90 msgid "Text" msgstr "Texto" #: gajim/gtk/advanced_config.py:102 msgid "Preference Name" msgstr "Nome da preferência" #: gajim/gtk/advanced_config.py:109 msgid "Value" msgstr "Valor" #: gajim/gtk/advanced_config.py:118 msgid "Type" msgstr "Tipo" #: gajim/gtk/advanced_config.py:174 msgid "(None)" msgstr "(Nada)" #: gajim/gtk/advanced_config.py:305 msgid "Hidden" msgstr "Escondido" #: gajim/gtk/server_info.py:126 #, python-format msgid "%(days)s days, %(hours)s hours" msgstr "" #: gajim/gtk/server_info.py:192 gajim/gtk/accounts.py:653 #: gajim/gtk/accounts.py:755 #, fuzzy msgid "Hostname" msgstr "_Nome do computador:" #: gajim/gtk/server_info.py:193 #, fuzzy msgid "Server Software" msgstr "Recursos dos Servidores" #: gajim/gtk/server_info.py:194 msgid "Server Uptime" msgstr "Funcionamento do Servidor" #: gajim/gtk/server_info.py:236 msgid "" "\n" "Disabled in config" msgstr "" #: gajim/gtk/features.py:51 msgid "Bonjour / Zeroconf" msgstr "Bonjour / Zeroconf" #: gajim/gtk/features.py:53 msgid "Serverless chatting with autodetected clients in a local network." msgstr "" "Conversa sem servidor com clientes detectados automaticamente em uma rede " "local." #: gajim/gtk/features.py:54 gajim/gtk/features.py:59 msgid "Requires python-dbus." msgstr "Requer o python-dbus." #: gajim/gtk/features.py:55 #, python-format msgid "Requires pybonjour and bonjour SDK running (%(url)s)" msgstr "" #: gajim/gtk/features.py:56 msgid "Command line" msgstr "Linha de comando" #: gajim/gtk/features.py:58 msgid "A script to control Gajim via commandline." msgstr "Um script para controlar o Gajim via linha de comando." #: gajim/gtk/features.py:60 gajim/gtk/features.py:90 gajim/gtk/features.py:95 msgid "Feature not available under Windows." msgstr "Recurso não disponível no Windows." #: gajim/gtk/features.py:61 #, fuzzy msgid "OpenPGP message encryption" msgstr "Criptografia de mensagem OpenPGP" #: gajim/gtk/features.py:63 #, fuzzy msgid "Ability to encrypting chat messages with OpenPGP." msgstr "Criptografando as mensagens das conversas com chaves gpg." #: gajim/gtk/features.py:64 #, python-format msgid "Requires gpg and python-gnupg (%(url)s)." msgstr "Requer gpg e python-gnupg (%(url)s)." #: gajim/gtk/features.py:65 msgid "Requires gpg.exe in PATH." msgstr "" #: gajim/gtk/features.py:66 msgid "Password encryption" msgstr "Criptografia de senha" #: gajim/gtk/features.py:68 msgid "Passwords can be stored securely and not just in plaintext." msgstr "" "As senhas podem ser armazenadas de maneira segura e não apenas em texto " "plano." #: gajim/gtk/features.py:69 msgid "" "Requires libsecret and a provider (such as GNOME Keyring and KSecretService)." msgstr "" #: gajim/gtk/features.py:70 msgid "On Windows the Windows Credential Vault is used." msgstr "" #: gajim/gtk/features.py:71 msgid "Spell Checker" msgstr "Verificador ortográfico" #: gajim/gtk/features.py:73 msgid "Spellchecking of composed messages." msgstr "Verificação ortográfica das mensagens escritas." #: gajim/gtk/features.py:74 gajim/gtk/features.py:75 #, fuzzy msgid "Requires Gspell" msgstr "Requer libgtkspell." #: gajim/gtk/features.py:76 msgid "Automatic status" msgstr "Status automático" #: gajim/gtk/features.py:78 msgid "Ability to measure idle time, in order to set auto status." msgstr "" "Habilidade de medir o tempo de inatividade para definir o status automático." #: gajim/gtk/features.py:79 msgid "Requires libxss library." msgstr "Requer biblioteca libxss." #: gajim/gtk/features.py:80 msgid "Requires python2.5." msgstr "Requer python2.5" #: gajim/gtk/features.py:81 msgid "RST Generator" msgstr "Gerador RST" #: gajim/gtk/features.py:83 msgid "" "Generate XHTML output from RST code (see http://docutils.sourceforge.net/" "docs/ref/rst/restructuredtext.html)." msgstr "" "Gera saída XHTML a partir de código RST (veja http://docutils.sourceforge." "net/docs/ref/rst/restructuredtext.html)." #: gajim/gtk/features.py:84 gajim/gtk/features.py:85 msgid "Requires python-docutils." msgstr "Requer python-docutils." #: gajim/gtk/features.py:86 msgid "Audio / Video" msgstr "Áudio / Vídeo" #: gajim/gtk/features.py:88 msgid "Ability to start audio and video chat." msgstr "Habilidade para iniciar uma conversa da áudio e vídeo." #: gajim/gtk/features.py:89 msgid "" "Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and " "gstreamer1.0-plugins-ugly." msgstr "" #: gajim/gtk/features.py:91 msgid "UPnP-IGD" msgstr "" #: gajim/gtk/features.py:93 msgid "Ability to request your router to forward port for file transfer." msgstr "" #: gajim/gtk/features.py:94 #, fuzzy msgid "Requires gir1.2-gupnpigd-1.0." msgstr "Requer python-gnome2." #: gajim/gtk/features.py:102 #, fuzzy msgid "?features:Available" msgstr "Disponível" #: gajim/gtk/features.py:109 msgid "Feature" msgstr "Recurso" #: gajim/gtk/privacy_list.py:70 #, python-format msgid "Privacy List %s" msgstr "Lista de privacidade %s" #: gajim/gtk/privacy_list.py:74 #, python-format msgid "Privacy List for %s" msgstr "Lista de privacidade para %s" #: gajim/gtk/privacy_list.py:147 #, python-format msgid "Order: %(order)s, action: %(action)s, type: %(type)s, value: %(value)s" msgstr "Ordem: %(order)s, ação: %(action)s tipo: %(type)s, valor: %(value)s" #: gajim/gtk/privacy_list.py:152 #, python-format msgid "Order: %(order)s, action: %(action)s" msgstr "Ordem: %(order)s, ação: %(action)s" #: gajim/gtk/privacy_list.py:208 msgid "Edit a rule" msgstr "Editar uma regra" #: gajim/gtk/privacy_list.py:321 msgid "Add a rule" msgstr "Adicionar uma regra" #: gajim/gtk/privacy_list.py:425 #, python-format msgid "Privacy Lists for %s" msgstr "Lista de privacidade para %s" #: gajim/gtk/privacy_list.py:526 msgid "Invalid List Name" msgstr "Nome de lista inválido" #: gajim/gtk/privacy_list.py:527 msgid "You must enter a name to create a privacy list." msgstr "Você deve digitar um nome para criar uma lista de privacidade." #: gajim/gtk/account_wizard.py:167 msgid "Account has been added successfully" msgstr "Conta foi adicionada com sucesso" #: gajim/gtk/account_wizard.py:168 gajim/gtk/account_wizard.py:174 msgid "" "You can set advanced account options by pressing the Advanced button, or " "later by choosing the Accounts menu item under the Edit menu from the main " "window." msgstr "" "Você pode configurar as opções avançadas da conta pressionando o botão " "avançado, ou mais tarde clicando em contas no menu editar da janela " "principal." #: gajim/gtk/account_wizard.py:173 msgid "Your new account has been created successfully" msgstr "Sua nova conta foi criada com sucesso" #: gajim/gtk/account_wizard.py:211 msgid "Invalid username" msgstr "Nome de usuário inválido" #: gajim/gtk/account_wizard.py:213 msgid "You must provide a username to configure this account." msgstr "Você deve entrar com um nome para configurar esta conta." #: gajim/gtk/account_wizard.py:254 gajim/gtk/bookmarks.py:324 #: gajim/gtk/bookmarks.py:337 msgid "Invalid server" msgstr "Servidor inválido" #: gajim/gtk/account_wizard.py:255 msgid "Please provide a server on which you want to register." msgstr "Por favor, forneça um servidor no qual você queira se registrar." #: gajim/gtk/account_wizard.py:279 msgid "Invalid entry" msgstr "Entrada inválida" #: gajim/gtk/account_wizard.py:280 msgid "Custom port must be a port number." msgstr "A porta do proxy deve ser um número de porta." #: gajim/gtk/account_wizard.py:408 #, python-format msgid "" "Security Warning\n" "\n" "The authenticity of the %(hostname)s SSL certificate could be invalid.\n" "SSL Error: %(error)s\n" "Do you still want to connect to this server?" msgstr "" "Aviso se segurança\n" "\n" "A autenticidade do certificado SSL do %(hostname)s pode ser inválido.\n" "Erro do SSL: %(error)s\n" "Você ainda quer conectar com este servidor?" #: gajim/gtk/account_wizard.py:449 gajim/gtk/account_wizard.py:483 msgid "An error occurred during account creation" msgstr "Um erro ocorreu durante a criação da conta" #: gajim/gtk/account_wizard.py:550 msgid "Account name is in use" msgstr "Nome de conta em uso" #: gajim/gtk/account_wizard.py:551 msgid "You already have an account using this name." msgstr "Você já tem uma conta usando este nome." #: gajim/gtk/xml_console.py:74 #, fuzzy msgid "Filter" msgstr "Filtro:" #: gajim/gtk/xml_console.py:79 msgid "XML Input" msgstr "Entrada XML" #: gajim/gtk/xml_console.py:168 #, fuzzy msgid "Invalid Node" msgstr "Arquivo inválido" #: gajim/gtk/preferences.py:377 gajim/gtk/preferences.py:381 #: gajim/gtk/bookmarks.py:72 msgid "Default" msgstr "Padrão" #: gajim/gtk/preferences.py:962 msgid "status message title" msgstr "título da mensagem de status" #: gajim/gtk/preferences.py:963 msgid "status message text" msgstr "texto da mensagem de status" #: gajim/gtk/accounts.py:170 msgid "Relogin now?" msgstr "Re-autenticar agora?" #: gajim/gtk/accounts.py:171 msgid "If you want all the changes to apply instantly, you must relogin." msgstr "Se você quer aplicar todas as mudanças, deve se re-autenticar." #: gajim/gtk/accounts.py:224 #, python-format msgid "You have opened chat in account %s" msgstr "Você iniciou uma conversa usando a conta %s" #: gajim/gtk/accounts.py:225 msgid "All chat and groupchat windows will be closed. Do you want to continue?" msgstr "Todas as janelas de conversa e conferência serão fechadas. Confirma?" #: gajim/gtk/accounts.py:338 #, fuzzy msgid "Add Account…" msgstr "_Adicionar contato..." #: gajim/gtk/accounts.py:514 #, fuzzy msgid "Remove" msgstr "_Remover" #: gajim/gtk/accounts.py:546 #, fuzzy msgid "Merge Accounts" msgstr "Juntar contas" #: gajim/gtk/accounts.py:549 #, fuzzy msgid "Use PGP Agent" msgstr "Usar o Agente G_PG" #: gajim/gtk/accounts.py:565 msgid "Label" msgstr "" #: gajim/gtk/accounts.py:569 msgid "Login" msgstr "" #: gajim/gtk/accounts.py:578 msgid "Connection" msgstr "Conexão" #: gajim/gtk/accounts.py:581 #, fuzzy msgid "Import Contacts" msgstr "Convidar _contatos" #: gajim/gtk/accounts.py:584 gajim/gtk/accounts.py:772 #, fuzzy msgid "Client Certificate" msgstr "Certificado próprio" #: gajim/gtk/accounts.py:587 gajim/gtk/accounts.py:686 #, fuzzy msgid "OpenPGP Key" msgstr "Atribuir chave OpenPGP" #: gajim/gtk/accounts.py:602 gajim/gtk/accounts.py:674 #, fuzzy msgid "Connect on startup" msgstr "C_onectar na inicialização do Gajim" #: gajim/gtk/accounts.py:605 #, fuzzy msgid "Reconnect when connection is lost" msgstr "Reconectar automaticamente quando a conexão cair" #: gajim/gtk/accounts.py:608 gajim/gtk/accounts.py:678 #, fuzzy msgid "Save conversations for all contacts" msgstr "Salvar his_tórico para todos os contatos desta conta" #: gajim/gtk/accounts.py:610 gajim/gtk/accounts.py:680 msgid "Store conversations on the harddrive" msgstr "" #: gajim/gtk/accounts.py:612 #, fuzzy msgid "Server Message Archive" msgstr "_Enviar mensagem de servidor..." #: gajim/gtk/accounts.py:614 msgid "" "Messages get stored on the server.\n" "The archive is used to sync messages\n" "between multiple devices.\n" "XEP-0313" msgstr "" #: gajim/gtk/accounts.py:619 gajim/gtk/accounts.py:682 #, fuzzy msgid "Global Status" msgstr "Totos os status" #: gajim/gtk/accounts.py:621 #, fuzzy msgid "Synchronise the status of all accounts" msgstr "Mudar o status da conta ou contas" #: gajim/gtk/accounts.py:623 #, fuzzy msgid "Message Carbons" msgstr "Mensagens" #: gajim/gtk/accounts.py:625 msgid "" "All your other online devices get copies\n" "of sent and received messages.\n" "XEP-0280" msgstr "" #: gajim/gtk/accounts.py:629 msgid "Use file transfer proxies" msgstr "Usar proxies de transferência de arquivos" #: gajim/gtk/accounts.py:641 gajim/gtk/accounts.py:676 #, fuzzy msgid "Use environment variable" msgstr "_usar variável de ambiente HTTP__PROXY" #: gajim/gtk/accounts.py:643 #, fuzzy msgid "Proxy" msgstr "Proxy:" #: gajim/gtk/accounts.py:646 #, fuzzy msgid "Warn on insecure connection" msgstr "A_visar antes de usar uma conexão não-segura" #: gajim/gtk/accounts.py:650 msgid "Send keep-alive packets" msgstr "Enviar pacotes para manter a conexão (keep-alive)" #: gajim/gtk/accounts.py:654 msgid "Manually set the hostname for the server" msgstr "" #: gajim/gtk/accounts.py:660 gajim/gtk/accounts.py:729 #: gajim/gtk/accounts.py:734 #, fuzzy msgid "Priority" msgstr "_Prioridade:" #: gajim/gtk/accounts.py:684 #, fuzzy msgid "Synchronize the status of all accounts" msgstr "Mudar o status da conta ou contas" #: gajim/gtk/accounts.py:698 #, fuzzy msgid "First Name" msgstr "Primeiro nome:" #: gajim/gtk/accounts.py:701 #, fuzzy msgid "Last Name" msgstr "Último nome:" #: gajim/gtk/accounts.py:707 #, fuzzy msgid "Email" msgstr "Novo e-mail" #: gajim/gtk/accounts.py:725 #, fuzzy msgid "Adjust to status" msgstr "_Ajustar para status" #: gajim/gtk/accounts.py:752 msgid "Enable" msgstr "Habilitar" #: gajim/gtk/accounts.py:759 #, fuzzy msgid "Port" msgstr "_Porta:" #: gajim/gtk/accounts.py:764 #, fuzzy msgid "Connection Options" msgstr "Conexão" #: gajim/gtk/accounts.py:774 msgid "PKCS12 Files" msgstr "" #: gajim/gtk/accounts.py:776 #, fuzzy msgid "Encrypted Certificate" msgstr "Certificado próprio" #: gajim/gtk/accounts.py:780 #, fuzzy msgid "Certificate Options" msgstr "Certificado próprio" #: gajim/gtk/accounts.py:792 #, fuzzy msgid "Save Password" msgstr "Salvar senha" #: gajim/gtk/accounts.py:800 #, fuzzy msgid "Login Options" msgstr "_Emoticons:" #: gajim/gtk/bookmarks.py:72 msgid "?print_status:All" msgstr "?exibir_status:Todos" #: gajim/gtk/bookmarks.py:73 msgid "Enter and leave only" msgstr "Apenas entre e saia" #: gajim/gtk/bookmarks.py:74 msgid "?print_status:None" msgstr "?exibir_status:Nenhum" #: gajim/gtk/bookmarks.py:143 msgid "New Group Chat" msgstr "Nova conferência" #: gajim/gtk/bookmarks.py:184 msgid "This bookmark has invalid data" msgstr "Este marcador tem dados inválidos" #: gajim/gtk/bookmarks.py:185 msgid "" "Please be sure to fill out server and room fields or remove this bookmark." msgstr "" "Por favor, tenha certeza que preencheu os campos servidor e sala ou remova " "este marcador." #: gajim/gtk/bookmarks.py:307 gajim/gtk/bookmarks.py:325 #: gajim/gtk/bookmarks.py:338 gajim/gtk/bookmarks.py:368 msgid "Character not allowed" msgstr "Caractere não permitido" #: gajim/gtk/bookmarks.py:367 msgid "Invalid room" msgstr "Sala inválida" #: gajim/plugins/pluginmanager.py:739 gajim/plugins/pluginmanager.py:745 msgid "Archive corrupted" msgstr "" #: gajim/plugins/pluginmanager.py:741 #, fuzzy msgid "Archive empty" msgstr "O arquivo está vazio" #: gajim/plugins/pluginmanager.py:753 gajim/plugins/pluginmanager.py:761 #: gajim/plugins/gui.py:254 #, fuzzy msgid "Archive is malformed" msgstr "O serviço enviou dados inválidos" #: gajim/plugins/pluginmanager.py:769 gajim/plugins/gui.py:278 #: gajim/plugins/gui.py:286 #, fuzzy msgid "Plugin already exists" msgstr "Este arquivo já existe" #: gajim/plugins/gui.py:81 msgid "Click to view Gajim's wiki page on how to install plugins in Flatpak." msgstr "" #: gajim/plugins/gui.py:88 msgid "Plugin" msgstr "" #: gajim/plugins/gui.py:148 #, fuzzy, python-format msgid "Warning: %s" msgstr "Banindo %s" #: gajim/plugins/gui.py:203 #, fuzzy msgid "Plugin failed" msgstr "Falha ao registrar" #: gajim/plugins/gui.py:242 msgid "Unable to properly remove the plugin" msgstr "" #: gajim/plugins/gui.py:278 msgid "Overwrite?" msgstr "" #: gajim/plugins/gui.py:309 #, fuzzy msgid "Configuration" msgstr "Configuração da sala" #: data/org.gajim.Gajim.desktop.in:5 msgid "Jabber IM Client" msgstr "Um cliente de IM Jabber" #: data/org.gajim.Gajim.desktop.in:6 msgid "A GTK+ Jabber client" msgstr "Um cliente Jabber GTK+" #: data/org.gajim.Gajim.desktop.in:8 msgid "chat;messaging;im;xmpp;bonjour;voip;" msgstr "" #: data/org.gajim.Gajim.desktop.in:11 data/org.gajim.Gajim.desktop.in:22 #: data/org.gajim.Gajim.desktop.in:27 msgid "org.gajim.Gajim" msgstr "" #: data/org.gajim.Gajim.desktop.in:26 #, fuzzy msgid "Show next pending event" msgstr "Exibir todos _eventos pendentes" #: data/org.gajim.Gajim.appdata.xml.in:12 msgid "" "Gajim aims to be an easy to use and fully-featured XMPP client. With Gajim " "you can chat through various XMPP services of your choice (e.g. Jabber.org) " "as well as transports (e.g. Facebook, IRC)." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:16 msgid "" "Just chat with your friends or family, easily share pictures and thoughts or " "discuss the news with your groups." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:19 msgid "" "Gajim integrates well with your other devices: just chat and see what's been " "said on your mobile device." msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:22 #, fuzzy msgid "Features:" msgstr "Recursos" #: data/org.gajim.Gajim.appdata.xml.in:24 msgid "Never miss a message, keep all your chat clients synchronized" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:25 msgid "Invite friends to group chats or join one" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:26 msgid "Easily send pictures, videos or other files to friends and groups" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:27 msgid "Chat securely with End-to-End encryption via OMEMO or PGP" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:28 msgid "Use your favorite emoticons, set your own profile picture" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:29 msgid "Keep and manage all your chat history" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:30 msgid "Organize your chats with tabs" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:31 #, fuzzy msgid "Automatic spell-checking for your messages" msgstr "Verificação ortográfica das mensagens escritas." #: data/org.gajim.Gajim.appdata.xml.in:32 msgid "Connect to other Messengers via Transports (Facebook, IRC, ...)" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:33 msgid "" "Lookup things on Wikipedia, dictionaries or other search engines directly " "from the chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:34 msgid "" "Set your activity, tune, and mood to show your friends how you are feeling" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:35 msgid "Support for multiple accounts" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:36 msgid "Group multiple contacts from one friend to a single Meta-Contact" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:37 msgid "XML console to see what's happening on the protocol layer" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:38 msgid "Serverless messaging (Bonjour/Zeroconf), BOSH" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:39 #, fuzzy msgid "Support for service discovery including nodes and search for users" msgstr "Descoberta de serviço incluindo nós, pesquisa de usuário" #: data/org.gajim.Gajim.appdata.xml.in:40 msgid "Even more features via plugins" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:52 #, fuzzy msgid "Roster, list of contacts" msgstr "_Log mudanças de status dos contatos" #: data/org.gajim.Gajim.appdata.xml.in:56 msgid "Tabbed chat window" msgstr "" #: data/org.gajim.Gajim.appdata.xml.in:60 #, fuzzy msgid "Group chat support" msgstr "Salas" #: data/org.gajim.Gajim.appdata.xml.in:64 #, fuzzy msgid "Chat history" msgstr "Recentemente:" #: data/org.gajim.Gajim.appdata.xml.in:68 #, fuzzy msgid "Plugin manager" msgstr "Falha ao registrar" #~ msgid "Stopped" #~ msgstr "Parado" #~ msgid "Error reading file:" #~ msgstr "Erro lendo arquivo:" #~ msgid "Error parsing file:" #~ msgstr "Erro ao analisar o arquivo:" #, fuzzy #~ msgid "Audio / video conferences" #~ msgstr "Áudio / Vídeo" #, fuzzy #~ msgid "File transfer, room bookmarks" #~ msgstr "Erro na transferência de arquivos" #, fuzzy #~ msgid "XML console interface" #~ msgstr "Console XML" #~ msgid "" #~ "A list of modp groups to use in a Diffie-Hellman, highest preference " #~ "first, separated by commas. Valid groups are 1, 2, 5, 14, 15, 16, 17 and " #~ "18. Higher numbers are more secure, but take longer to calculate when you " #~ "start a session." #~ msgstr "" #~ "Uma lista de grupos modp para usar em uma Diffie-Hellman, preferências " #~ "maiores primeiro, separadas por vírgula. Grupos válidos são 1, 2, 5, 14, " #~ "15, 16, 17 e 18. Números maiores são mais seguros, mas demoram mais para " #~ "calcular quando você inicia uma sessão." #~ msgid "_Verify" #~ msgstr "_Verificar" #~ msgid "(ESession info)" #~ msgstr "(Informações ESession)" #~ msgid "Save as Preset..." #~ msgstr "Salvar como modelos..." #~ msgid "Always use this nickname when there is a conflict" #~ msgstr "Sempre usar este apelido quando houver um conflito" #~ msgid "" #~ "Jabberd1.4 does not like sha info when one join a password protected " #~ "group chat. Turn this option to False to stop sending sha info in group " #~ "chat presences." #~ msgstr "" #~ "O Jabberd1.4 não trata informações sha quando alguém entra numa sala " #~ "protegida por senha. Mude esta opção para Falso para parar de emitir as " #~ "informações sha na presenças de conferências." #~ msgid "" #~ "If not disabled, Gajim will replace ascii smilies like ':)' with " #~ "equivalent animated or static graphical emoticons" #~ msgstr "" #~ "Se habilitado, Gajim substituirá o ascii para smilies, como ':)' com a " #~ "animação equivalente ou estático emoticons gráfico" #, fuzzy #~ msgid "_Emoticons" #~ msgstr "_Emoticons:" #~ msgid "_Highlight misspelled words" #~ msgstr "_Destacar palavras mal escritas" #, fuzzy #~ msgid "Notify by icon when your messages are received" #~ msgstr "Som a ser tocado quando qualquer mensagem MUC chegar." #, fuzzy #~ msgid "T_heme" #~ msgstr "_Tema:" #~ msgid "Themes" #~ msgstr "Tema" #, fuzzy #~ msgid "Presence" #~ msgstr "_Presença" #~ msgid "Emoticons disabled" #~ msgstr "Emoticons desabilitados" #, fuzzy #~ msgid "" #~ "Your configured emoticons theme could not be loaded. See the log for more " #~ "details." #~ msgstr "" #~ "Você configurou um tema de emoticons que não foi encontrado, então os " #~ "emoticons estão desativados." #~ msgid "You cannot make changes to the default theme" #~ msgstr "Você não pode fazer alterações no tema padrão" #, fuzzy #~ msgid "Please create a new clean theme." #~ msgstr "Crie um novo tema com o nome que você desejar." #~ msgid "theme name" #~ msgstr "nome do tema" #~ msgid "You cannot delete your current theme" #~ msgstr "Você não pode apagar o seu tema corrente" #~ msgid "New Single Message from %(nickname)s" #~ msgstr "Nova mensagem simples de %(nickname)s" #~ msgid "New Private Message from group chat %s" #~ msgstr "Nova mensagem privada da conferência %s" #~ msgid "%(nickname)s: %(message)s" #~ msgstr "%(nickname)s: %(message)s" #~ msgid "Messaged by %(nickname)s" #~ msgstr "Mensagem enviada por %(nickname)s" #~ msgid "Status message text color." #~ msgstr "Cor do texto da mensagem de status." #~ msgid "Incoming nickname font." #~ msgstr "Fonte do apelido de entrada." #~ msgid "Outgoing nickname font." #~ msgstr "Fonte do apelido de saída." #~ msgid "Status message text font." #~ msgstr "Fonte do texto da mensagem de status." #~ msgid "Background color of contacts when they just signed in." #~ msgstr "Cor de fundo dos contatos quando eles simplesmente conectarem." #~ msgid "Background color of contacts when they just signed out." #~ msgstr "Cor de fundo dos contatos quando eles simplesmente desconectarem." #~ msgid "green" #~ msgstr "verde" #~ msgid "grocery" #~ msgstr "mantimento" #~ msgid "human" #~ msgstr "humano" #~ msgid "marine" #~ msgstr "marinho" #, fuzzy #~ msgid "Contact row" #~ msgstr "Contato" #~ msgid "Gajim Themes Customization" #~ msgstr "Customização de temas do Gajim" #~ msgid "Text _color:" #~ msgstr "_Cor do texto" #~ msgid "_Background:" #~ msgstr "Cor _de fundo" #~ msgid "Text _font:" #~ msgstr "_Fonte do texto" #~ msgid "Font style:" #~ msgstr "Estilo da fonte:" #~ msgid "Paused" #~ msgstr "Pausado" #~ msgid "Gone" #~ msgstr "Enviado" #~ msgid "" #~ "MUC\n" #~ "Messages" #~ msgstr "" #~ "MUC\n" #~ "mensagens" #~ msgid "Chatstate Tab Colors" #~ msgstr "Aba de cores do bate-papo" #, fuzzy #~ msgid "Chat message" #~ msgstr "Mensagem da conversa:" #~ msgid "Use system _default" #~ msgstr "Usar o _padrão do sistema" #~ msgid "Font" #~ msgstr "Fonte" #, fuzzy #~ msgid "Contact's nickname" #~ msgstr "Apelido do contato:" #, fuzzy #~ msgid "Contact's message" #~ msgstr "Mensagem do contato:" #, fuzzy #~ msgid "_Status message" #~ msgstr "_Mensagem de status:" #, fuzzy #~ msgid "Group chat highlight" #~ msgstr "Mensagem destacada de conferência" #, fuzzy #~ msgid "Your nickname" #~ msgstr "Seu apelido:" #, fuzzy #~ msgid "Your message" #~ msgstr "Sua mensagem:" #, fuzzy #~ msgid "_URL highlight" #~ msgstr "Destaque de _URL:" #~ msgid "Chat Line Colors" #~ msgstr "Cores da linha da conversa" #~ msgid "Jabber ID:" #~ msgstr "Jabber ID:" #~ msgid "Resource:" #~ msgstr "Recurso:" #~ msgid "Status:" #~ msgstr "Status:" #~ msgid "Client:" #~ msgstr "Cliente:" #~ msgid "Contact time:" #~ msgstr "Tempo do contato:" #~ msgid "Ask:" #~ msgstr "Pergunta:" #~ msgid "Subscription:" #~ msgstr "Inscrição:" #~ msgid "Name:" #~ msgstr "Nome:" #~ msgid "Nickname:" #~ msgstr "Apelido:" #~ msgid "Street:" #~ msgstr "Rua:" #~ msgid "City:" #~ msgstr "Cidade:" #~ msgid "State:" #~ msgstr "Estado:" #~ msgid "Extra Address:" #~ msgstr "Complemento:" #~ msgid "Postal Code:" #~ msgstr "Código postal:" #~ msgid "Country:" #~ msgstr "País:" #~ msgid "Homepage:" #~ msgstr "Página pessoal:" #~ msgid "E-Mail:" #~ msgstr "Email:" #~ msgid "Phone No.:" #~ msgstr "Telefone:" #~ msgid "Birthday:" #~ msgstr "Aniversário:" #~ msgid "Family:" #~ msgstr "Família:" #~ msgid "Middle:" #~ msgstr "Nome do meio:" #~ msgid "Prefix:" #~ msgstr "Prefixo" #~ msgid "Given:" #~ msgstr "Primeiro nome:" #~ msgid "Suffix:" #~ msgstr "Sufixo" #~ msgid "Full Name" #~ msgstr "Nome completo" #~ msgid "Company:" #~ msgstr "Empresa:" #~ msgid "Department:" #~ msgstr "Departamento:" #~ msgid "Position:" #~ msgstr "Posição:" #~ msgid "Role:" #~ msgstr "Cargo:" #~ msgid "- messages will be logged" #~ msgstr "- as mensagens serão gravadas" #~ msgid "- messages will not be logged" #~ msgstr "- as mensagens não serão gravadas" #~ msgid "Edit %s" #~ msgstr "Editar %s" #~ msgid "Register to %s" #~ msgstr "Registro para %s" #~ msgid "Conversation History with %s" #~ msgstr "Histórico de conversação com %s" #~ msgid "Contact with \"%s\" cannot be established" #~ msgstr "Contato com \"%s\" não pode ser estabelecido" #~ msgid "Registration information for transport %s has not arrived in time" #~ msgstr "A informação do registo para o transporte %s não chegou a tempo" #~ msgid "Register to" #~ msgstr "Registrar para" #, fuzzy #~ msgid "Enter name / JID of contact or groupchat" #~ msgstr "Nome do contato" #~ msgid "Search:" #~ msgstr "Pesquisar:" #~ msgid "Without a connection, you can not change your password." #~ msgstr "Você deve estar conectado para mudar sua senha." #~ msgid "Invalid password" #~ msgstr "Senha inválida" #~ msgid "The passwords typed in both fields must be identical." #~ msgstr "As senhas digitadas em ambos os campos devem ser idênticas." #~ msgid "Enter new password:" #~ msgstr "Digite sua nova senha:" #~ msgid "Enter it again for confirmation:" #~ msgstr "Digite novamente para confirmar:" #~ msgid "" #~ "JID %s is not RFC compliant. It will not be added to your roster. Use " #~ "roster management tools such as http://jru.jabberstudio.org/ to remove it" #~ msgstr "" #~ "O JID %s não é uma compilação da RFC. Não se adicionará a sua lista. Use " #~ "ferramentas de gerência da lista como http://jru.jabberstudio.org/ para " #~ "removê-lo" #~ msgid "unsubscribe request from %s" #~ msgstr "remoção de inscrição solicitada por %s" #, fuzzy #~ msgid "Autojoin" #~ msgstr "Ingresso automático" #~ msgid "Homepage:" #~ msgstr "Site pessoal:" #, fuzzy #~ msgid "Configure" #~ msgstr "_Configurar" #~ msgid "Manage Bookmarks" #~ msgstr "Gerenciar marcadores" #~ msgid "_Nickname:" #~ msgstr "_Apelido:" #~ msgid "If checked, Gajim will join this group chat on startup" #~ msgstr "" #~ "Se marcado, o Gajim irá ingressar na conferência no ínicio da aplicação" #, fuzzy #~ msgid "Pr_int status:" #~ msgstr "Imprimir status:" #, fuzzy #~ msgid "Add JID" #~ msgstr "Jabber ID" #, fuzzy #~ msgid "Preference:" #~ msgstr "Preferências" #, fuzzy #~ msgid "Preference" #~ msgstr "Preferências" #, fuzzy #~ msgid "JID:" #~ msgstr "Seu JID:" #~ msgid "" #~ "Please fill in the data of the contact you want to add to your account " #~ "%s" #~ msgstr "" #~ "Preencha os dados do contato que você quer adicionar em sua conta %s" #~ msgid "Please fill in the data of the contact you want to add" #~ msgstr "Por favor preencha os dados do contato que você quer adicionar" #, fuzzy #~ msgid "Recently" #~ msgstr "Recentemente:" #~ msgid "Add New Contact" #~ msgstr "Adicionar novo contato" #~ msgid "_User ID:" #~ msgstr "_ID do usuário:" #, fuzzy #~ msgid "Type User ID" #~ msgstr "ID do usuário:" #, fuzzy #~ msgid "Type Nickname" #~ msgstr "Apelido" #~ msgid "Personal Information" #~ msgstr "Informações pessoais" #~ msgid "Avatar:" #~ msgstr "Avatar:" #~ msgid "Click to set your avatar" #~ msgstr "Clique para definir seu avatar" #, fuzzy #~ msgid "Remove Avatar" #~ msgstr "Remover grupo" #~ msgid "Not fetched because of invisible status" #~ msgstr "Não baixado por causa do status invisível" #~ msgid "Please wait..." #~ msgstr "Por favor aguarde..." #~ msgid "" #~ "When negotiating an encrypted session, should Gajim assume you want your " #~ "messages to be logged?" #~ msgstr "" #~ "Ao negociar uma sessão criptografada, o Gajim deve assumir que você quer " #~ "que suas mensagens sejam gravadas?" #~ msgid "Log _encrypted chat session" #~ msgstr "Registrar sessão de conversa _criptografada" #, fuzzy #~ msgid "" #~ "If checked, Gajim will keep logs for encrypted messages. Please note that " #~ "when using end-to-end encryption the remote party has to agree on " #~ "logging, else the messages will not be logged." #~ msgstr "" #~ "Se marcado, o Gajim irá manter os logs para mensagens criptografadas. Por " #~ "favor, note que quando estiver usando criptografia E2E o remote party não " #~ "concorda com o registro, então a mensagem não será gravada." #~ msgid "Yahoo! Address:" #~ msgstr "Endereço Yahoo!:" #~ msgid "Forward unread messages" #~ msgstr "Encaminhar mensagens não lidas" #~ msgid "All unread messages have been forwarded." #~ msgstr "Todas as mensagens não lidas foram encaminhadas." #, fuzzy #~ msgid "Forward unread message then disconnect" #~ msgstr "Encaminhar mensagens não lidas" #~ msgid "AIM Address:" #~ msgstr "Endereço AIM:" #~ msgid "MSN Address:" #~ msgstr "Endereço MSN:" #~ msgid "Confirm these session options" #~ msgstr "Confirme essas opções de sessão" #, fuzzy #~ msgid "" #~ "The remote client wants to negotiate a session with these features:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Are these options acceptable?" #~ msgstr "" #~ "O cliente remoto quer negociar uma sessão com esses recursos:\n" #~ "\n" #~ "\t%s\n" #~ "\n" #~ "\tEssas opções são aceitáveis?" #~ msgid "" #~ "The remote client selected these options:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Continue with the session?" #~ msgstr "" #~ "O cliente remoto selecionou essas opções:\n" #~ "\n" #~ "%s\n" #~ "\n" #~ "Continuar com a sessão?" #, fuzzy #~ msgid "Always accept for this contact" #~ msgstr "O OpenPGP está ativado para este contato?" #~ msgid "End to End message encryption" #~ msgstr "Criptografia de mensagem End to End" #~ msgid "Encrypting chat messages." #~ msgstr "Criptografando mensagens da conversa." #~ msgid "Requires python-crypto." #~ msgstr "Requer python-crypto." #~ msgid "Session negotiation cancelled" #~ msgstr "Negociação da sessão cancelada" #, fuzzy #~ msgid "This session WILL NOT be archived on server" #~ msgstr "A sessão NÃO SERÁ gravada" #~ msgid "This session is encrypted" #~ msgstr "Esta sessão está criptografada" #~ msgid " and WILL be logged" #~ msgstr " e SERÁ gravada" #~ msgid " and WILL NOT be logged" #~ msgstr " e NÃO SERÁ gravada" #~ msgid "" #~ "Remote contact's identity not verified. Click the shield button for more " #~ "details." #~ msgstr "" #~ "Identidade do contato remoto não verificada. Clique no botão de proteção " #~ "para mais detalhes." #, fuzzy #~ msgid "end-to-end encryption disabled" #~ msgstr "Criptografia GPG desabilitada" #~ msgid "" #~ "Unable to decrypt message from %s\n" #~ "It may have been tampered with." #~ msgstr "" #~ "Não foi possível descriptografar a mensagem de %s\n" #~ "Ela pode ter sido adulterada." #~ msgid "Unable to decrypt message" #~ msgstr "Não foi possível descriptografar a mensagem" #~ msgid "Enable ESessions encryption for this account." #~ msgstr "Habilitar criptografia ESessions para esta conta." #~ msgid "Should Gajim automatically start an encrypted session when possible?" #~ msgstr "" #~ "O Gajim deve iniciar automaticamente em sessão criptografada quando " #~ "possível?" #~ msgid "" #~ "[This is part of an encrypted session. If you see this message, something " #~ "went wrong.]" #~ msgstr "" #~ "[Isto é parte de uma sessão criptografada. Se você estiver vendo esta " #~ "mensagem, alguma coisa vai errada.]" #~ msgid "Requires python-avahi." #~ msgstr "Requer o python-avahi." #~ msgid "_Send" #~ msgstr "_Enviar" #, fuzzy #~ msgid "Save Image as…" #~ msgstr "Salvar imagem como..." #, fuzzy #~ msgid "Exporting History Logs…" #~ msgstr "Exportando histórico de logs..." #~ msgid "Choose Image" #~ msgstr "Escolha imagem" #, fuzzy #~ msgid "Choose file to send" #~ msgstr "Escolha o arquivo para enviar..." #~ msgid "When %s becomes:" #~ msgstr "Quando %s chega:" #~ msgid "Adding Special Notification for %s" #~ msgstr "Adicionando notificação especial para %s" #, fuzzy #~ msgid "" #~ "It seems the SSL certificate of account %(account)s has changed and is " #~ "not valid or your connection is being compromised.\n" #~ "\n" #~ "Old SHA-1 fingerprint: %(old_sha1)s\n" #~ "Old SHA-256 fingerprint: %(old_sha256)s\n" #~ "\n" #~ "New SHA-1 fingerprint: %(new_sha1)s\n" #~ "New SHA-256 fingerprint: %(new_sha256)s\n" #~ "\n" #~ "Do you still want to connect and update the fingerprint of the " #~ "certificate?" #~ msgstr "" #~ "Parece que o certificado SSL da conta %(account)s foi alterado ou sua " #~ "conexão foi hackeada.\n" #~ "Fingerprint antigo: %(old)s\n" #~ "Novo fingerprint: %(new)s\n" #~ "\n" #~ "Você ainda quer conectar e atualizar o fingerprint do certificado?" #, fuzzy #~ msgid "" #~ "The authenticity of the %s certificate could be invalid.\n" #~ "The certificate does not cover this domain." #~ msgstr "A autenticidade do certificado %s pode ser inválida." #~ msgid "Unable to load idle module" #~ msgstr "Incapaz de carregar o módulo inativo" #, fuzzy #~ msgid "%s or %s is a directory but should be a file" #~ msgstr "%s é um diretório, mas deveria ser um arquivo" #~ msgid "creating logs database" #~ msgstr "criando banco de dados de logs" #, fuzzy #~ msgid "creating cache database" #~ msgstr "criando banco de dados de logs" #, fuzzy #~ msgid "moving %(src)s to %(dst)s" #~ msgstr "Enviar %s para %s" #~ msgid "Gajim History Logs Manager" #~ msgstr "Gerenciador de histórico de logs do Gajim" #, fuzzy #~ msgid "Rename account label" #~ msgstr "Renomear conta" #, fuzzy #~ msgid "Send Single Message..." #~ msgstr "_Enviar mensagem simples..." #, fuzzy #~ msgid "We received an error: {}" #~ msgstr "O serviço retornou um erro." #~ msgid "E2E encryption disabled" #~ msgstr "Criptografia E2E desabilitada" #, fuzzy #~ msgid "" #~ "Add this certificate to the list of trusted certificates.\n" #~ "SHA-1 fingerprint of the certificate:\n" #~ "%(sha1)s\n" #~ "SHA256 fingerprint of the certificate:\n" #~ "%(sha256)s" #~ msgstr "" #~ "Adicionar este certificado na lista de certificados confiáveis.\n" #~ "SHA1 fingerprint do certificado:\n" #~ "%s" #~ msgid "uri" #~ msgstr "URI" #, fuzzy #~ msgid "" #~ "Install /\n" #~ "Upgrade" #~ msgstr "Parado" #, fuzzy #~ msgid "Install/Upgrade" #~ msgstr "Parado" #, fuzzy #~ msgid "Plugins updates" #~ msgstr "Falha ao registrar" #, fuzzy #~ msgid "Security error during download" #~ msgstr "Erro de segurança ao conectar a \"%s\"" #, fuzzy #~ msgid "Error in download" #~ msgstr "Erro de segurança ao conectar a \"%s\"" #~ msgid "cyan" #~ msgstr "azul celeste" #~ msgid "migrating logs database to indices" #~ msgstr "migrando base de dados de registros para índices" #, fuzzy #~ msgid "Send File..." #~ msgstr "Enviar _arquivo..." #, fuzzy #~ msgid "HTTP File Upload not supported by your server" #~ msgstr "O armazenamento de metacontatos não é suportado pelo seu servidor" #, fuzzy #~ msgid "Jingle File Transfer" #~ msgstr "Transferência de arquivos" #~ msgid "" #~ "Your configured emoticons theme has not been found, so emoticons have " #~ "been disabled." #~ msgstr "" #~ "Você configurou um tema de emoticons que não foi encontrado, então os " #~ "emoticons estão desativados." #~ msgid "Shows or hides the roster window" #~ msgstr "exibe ou esconder a janela principal" #~ msgid "Shows or hides the ipython window" #~ msgstr "Exibe ou esconder a janela ipython" #, fuzzy #~ msgid "XMPP account %s" #~ msgstr "Conta XMPP %s@%s" #, fuzzy #~ msgid "Exception" #~ msgstr "Descrição" #~ msgid "" #~ "someone@somewhere.com would like you to add some contacts " #~ "in your roster." #~ msgstr "" #~ "alguem@algumacoisa.com gostaria que você adicionasse alguns " #~ "contatos em sua lista de contatos." #~ msgid "" #~ "Ordered list (space separated) of connection type to try. Can contain " #~ "tls, ssl or plain" #~ msgstr "" #~ "Lista ordenada de tipos de conexão (separada por espaço) para tentar. " #~ "Pode conter tls, ssl ou simples" #~ msgid "_Actions" #~ msgstr "_Ações" #, fuzzy #~ msgid "Requires upower and python-dbus." #~ msgstr "Requer o python-dbus." #, fuzzy #~ msgid "Start Chat..." #~ msgstr "_Iniciar conversa..." #~ msgid "You are already in group chat %s" #~ msgstr "Você já está na conferência %s" #~ msgid "Join Group Chat with account %s" #~ msgstr "Ingressar numa conferência com a conta %s" #~ msgid "Invalid Account" #~ msgstr "Conta inválida" #~ msgid "" #~ "You have to choose an account from which you want to join the groupchat." #~ msgstr "Selecione a conta que você quer usar para para entrar na sala." #, fuzzy #~ msgid "Please enter the group chat JID as room@server." #~ msgstr "Por favor, digite o Jabber ID da conferência como sala@servidor." #, fuzzy #~ msgid "The group chat JID contains invalid characters." #~ msgstr "O Jabber ID da conferência possui caracteres não permitidos." #~ msgid "Start Chat with account %s" #~ msgstr "Iniciar uma conferência com a conta %s" #, fuzzy #~ msgid "" #~ "Fill in the nickname or the JID of the contact you would like\n" #~ "to send a chat message to:" #~ msgstr "" #~ "Digite o apelido ou o Jabber ID do contato para o qual\n" #~ "você quer enviar uma mensagem:" #, fuzzy #~ msgid "Nickname / JID" #~ msgstr "Jabber ID duplicado" #~ msgid "Unable to parse \"%s\"." #~ msgstr "Impossível gravar o arquivo em \"%s\"." #~ msgid "Shows the chat dialog so that you can send messages to a contact" #~ msgstr "" #~ "Exibe o diálogo do bate-papo onde você pode enviar mensagens para um " #~ "contato" #~ msgid "JID of the contact that you want to chat with" #~ msgstr "JID do contato que você quer conversar" #~ msgid "message content. The account must be specified or \"\"" #~ msgstr "conteúdo da mensagem. A conta deve estar especificada ou \"\"" #~ msgid "Adds contact to roster" #~ msgstr "Adicionar contato para a lista" #~ msgid "jid" #~ msgstr "JID" #~ msgid "Adds new contact to this account" #~ msgstr "Adicionar novo contato para esta conta" #~ msgid "Opens 'Start Chat' dialog" #~ msgstr "Abrir o diálogo 'Iniciar Conversa'" #~ msgid "Starts chat, using this account" #~ msgstr "Iniciar conversa, usando esta conta" #, fuzzy #~ msgid "Handle a xmpp:/ URI" #~ msgstr "Manipular uma URI xmpp:/" #~ msgid "URI to handle" #~ msgstr "URI a manipular" #~ msgid "Account in which you want to handle it" #~ msgstr "Selecione a conta na qual você quer manipular isto" #~ msgid "Message content" #~ msgstr "Conteúdo da mensagem" #~ msgid "Join a MUC room" #~ msgstr "Entrar em uma sala MUC" #~ msgid "Nickname to use" #~ msgstr "Apelido a ser usado" #~ msgid "Password to enter the room" #~ msgstr "Senhas para entrar na sala" #~ msgid "Account from which you want to enter the room" #~ msgstr "Selecione a conta que você quer para entrar na sala" #, fuzzy #~ msgid "Wrong URI" #~ msgstr "URI incorreta" #~ msgid "Nickname:" #~ msgstr "Apelido:" #~ msgid "Server:" #~ msgstr "Servidor:" #~ msgid "Password:" #~ msgstr "Senha:" #, fuzzy #~ msgid "Join this room _automatically when I connect" #~ msgstr "Entrar nesta sala automaticamente quando eu conectar" #, fuzzy #~ msgid "Bro_wse Rooms" #~ msgstr "_Navegar" #, fuzzy #~ msgid "Requires libgtkspell and libenchant." #~ msgstr "Requer libgtkspell." #, fuzzy #~ msgid "Network-Watcher" #~ msgstr "Network-manager" #~ msgid "Autodetection of network status." #~ msgstr "Detecção automática do status da rede." #, fuzzy #~ msgid "Requires gnome-network-manager" #~ msgstr "Requer gnome-network-manager e python-dbus." #, fuzzy #~ msgid "Feature not available, see Help->Features" #~ msgstr "Recurso não disponível no Windows." #~ msgid "This contact does not support file transfer." #~ msgstr "Este contato não suporta transferência de arquivo." #, fuzzy #~ msgid "You need to know the real JID of the contact to send them a file." #~ msgstr "" #~ "Você precisa saber o JID real do usuário para lhe enviar um arquivo." #~ msgid "" #~ "You have to install %s dictionary to use spellchecking, or choose another " #~ "language by setting the speller_language option." #~ msgstr "" #~ "Você precisa instalar o dicionário %s para usar a correção ortográfica ou " #~ "selecionar outro idioma ajustando a opção 'speller_language'." #~ msgid "Hides the buttons in chat windows." #~ msgstr "Esconder os botões nas janelas de conversa." #~ msgid "Change your nickname (Ctrl+N)" #~ msgstr "Alterar o seu apelido (Ctrl+N)" #~ msgid "Change the room's subject (Alt+T)" #~ msgstr "Alterar o assunto da sala (Alt+T)" #~ msgid "Bookmark this room (Ctrl+B)" #~ msgstr "Adicionar esta sala aos marcadores (Ctrl+B)" #~ msgid "Browse the chat history (Ctrl+H)" #~ msgstr "Pesquisar o histórico de conversas (Ctrl+H)" #, fuzzy #~ msgid "Show advanced functions (Alt+D)" #~ msgstr "Exibir um menu com funções avançadas (Alt+D)" #~ msgid "Add this contact to roster (Ctrl+D)" #~ msgstr "Adicionar este contato para a lista (Ctrl+D)" #~ msgid "Invite contacts to the conversation (Ctrl+G)" #~ msgstr "Convidar contatos para a conversa (Ctrl+G)" #, fuzzy #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Exibir o perfil do contato (Ctrl+I)" #~ msgid "Show the contact's profile (Ctrl+I)" #~ msgstr "Exibir o perfil do contato (Ctrl+I)" #~ msgid "Ma_ke message windows compact" #~ msgstr "T_ornar a janela de mensagem compacta" #~ msgid "Hide all buttons in chat windows" #~ msgstr "Esconder todos os botões nas janelas de conversa" #, fuzzy #~ msgid "Hide the chat buttons" #~ msgstr "Uso: /%s, esconde os botões do bate-papo." #~ msgid "" #~ "If True, Gajim will ask for avatar each contact that did not have an " #~ "avatar last time or has one cached that is too old." #~ msgstr "" #~ "Se verdadeiro, Gajim pedirá por avatar cada contato que não teve um " #~ "avatar ou tem um cache que é velho demais." #~ msgid "Disk Write Error" #~ msgstr "Erro de escrita em disco" #~ msgid "Set Custom _Avatar..." #~ msgstr "Definir _avatar personalizado..." #, fuzzy #~ msgid "SSL certificate validation" #~ msgstr "Validação de certificado SSL" #~ msgid "" #~ "A library used to validate server certificates to ensure a secure " #~ "connection." #~ msgstr "" #~ "Uma biblioteca usada para validar os certificados do servidor para " #~ "garantir uma conexão segura." #, fuzzy #~ msgid "Requires python-pyopenssl > 0.12 and pyasn1." #~ msgstr "Requer o python-pyopenssl." #, fuzzy #~ msgid "?CLI:room" #~ msgstr "sala" #, fuzzy #~ msgid "?CLI:nick" #~ msgstr "apelido" #, fuzzy #~ msgid "?CLI:password" #~ msgstr "senha" #~ msgid "Use D-Bus and Notification-Daemon to show notifications" #~ msgstr "Usar DBus e Notification-Daemon para exibir notificações" #~ msgid "Notification" #~ msgstr "Notificação" #~ msgid "Passive popups notifying for new events." #~ msgstr "Popups passivos notificando novos eventos." #~ msgid "" #~ "Requires python-notify or instead python-dbus in conjunction with " #~ "notification-daemon." #~ msgstr "" #~ "Requer python-notify ou então python-dbus em conjunto com notification-" #~ "daemon." #~ msgid "Ignore" #~ msgstr "Ignorar" #~ msgid "_Open Gmail Inbox" #~ msgstr "_Abrir caixa de entrada do GMail" #~ msgid "Notify on new _GMail email" #~ msgstr "Notificar cada nova mensagem do _GMail" #~ msgid "" #~ "If checked, Gajim will show a notification when a new e-mail is received " #~ "via GMail" #~ msgstr "" #~ "Se marcado, o Gajim irá exibir uma notificação quando um novo email via " #~ "GMail for recebido" #~ msgid "Display _extra email details" #~ msgstr "Exibir detalhes _extras dos emails" #, fuzzy #~ msgid "" #~ "If checked, Gajim will also include information about the sender of new " #~ "emails" #~ msgstr "" #~ "Se marcado, o Gajim também incluirá informação sobre o remetente de novos " #~ "emails" #~ msgid "GMail Options" #~ msgstr "Opções do GMail" #, fuzzy #~ msgid "20" #~ msgstr "0" #, fuzzy #~ msgid "Invited %s to %s" #~ msgstr "Enviar %s para %s" #~ msgid "GMail Email Received" #~ msgstr "Email do GMail recebido" #, fuzzy #~ msgid "New e-mail on %(gmail_mail_address)s" #~ msgstr "Novo email em %(gmail_mail_address)s" #, fuzzy #~ msgid "You have %d new e-mail conversation" #~ msgid_plural "You have %d new e-mail conversations" #~ msgstr[0] "Você tem %d nova mensagem de email" #~ msgstr[1] "Você tem %d novas mensagens de email" #~ msgid "" #~ "\n" #~ "\n" #~ "From: %(from_address)s\n" #~ "Subject: %(subject)s\n" #~ "%(snippet)s" #~ msgstr "" #~ "\n" #~ "\n" #~ "De: %(from_address)s\n" #~ "Assunto: %(subject)s\n" #~ "%(snippet)s" #~ msgid "Re_name" #~ msgstr "Re_nomear" #~ msgid "Resour_ce:" #~ msgstr "Recur_so:" #~ msgid "" #~ "Resource is sent to the Jabber server in order to separate the same JID " #~ "in two or more parts depending on the number of the clients connected in " #~ "the same server with the same account. So you might be connected in the " #~ "same account with resource 'Home' and 'Work' at the same time. The " #~ "resource which has the highest priority will get the events. (see below)" #~ msgstr "" #~ "Um recurso é enviado ao servidor jabber com o objetivo de 'separar' o " #~ "mesmo JID em duas ou mais partes dependendo do número de clientes " #~ "conectados no mesmo servidor com a mesma conta. Então você pode estar " #~ "conectado na mesma conta com o recurso 'Casa' e 'Trabalho' ao mesmo " #~ "tempo. O recurso que possuir a maior prioridade receberá os eventos. " #~ "(veja abaixo)" #~ msgid "A_djust to status" #~ msgstr "Aj_ustar para status" #~ msgid "Priority will change automatically according to your status." #~ msgstr "" #~ "A prioridade será alterada automaticamente de acordo com o seu status." #~ msgid "Anonymous authentication" #~ msgstr "Autenticação anônima" #~ msgid "" #~ "Priority is used in Jabber to determine who gets the events from the " #~ "jabber server when two or more clients are connected using the same " #~ "account; The client with the highest priority gets the events" #~ msgstr "" #~ "A prioridade é usada no Jabber para determinar quem recebe os eventos do " #~ "servidor jabber quando dois ou mais clientes estão conectados usando a " #~ "mesma conta; O cliente com a maior prioridade receberá os eventos" #, fuzzy #~ msgid "Synchronize contacts" #~ msgstr "Sincronizar contatos" #~ msgid "Click to request authorization to all contacts of another account" #~ msgstr "" #~ "Clique para requisitar autorização para todos os contatos de outra conta" #~ msgid "Chan_ge Password" #~ msgstr "A_lterar senha" #~ msgid "Click to change account's password" #~ msgstr "Clique para mudar a senha da conta" #~ msgid "Administration operations" #~ msgstr "Operações de administração" #, fuzzy #~ msgid "Browse..." #~ msgstr "_Navegar" #, fuzzy #~ msgid "Certificate is e_ncrypted" #~ msgstr "Certificado rejeitado" #~ msgid "" #~ "If checked, Gajim, when launched, will automatically connect to jabber " #~ "using this account" #~ msgstr "" #~ "Se marcado, o Gajim, quando carregado, irá conectar automaticamente ao " #~ "jabber usando esta conta" #, fuzzy #~ msgid "Synchronize logs with server" #~ msgstr "Sincronizar contatos" #~ msgid "Synch_ronize account status with global status" #~ msgstr "_Sincronizar status da conta com status global" #~ msgid "" #~ "If checked, any change to the global status (handled by the combobox at " #~ "the bottom of the roster window) will change the status of this account " #~ "accordingly" #~ msgstr "" #~ "Se marcada, o status deste cliente será alterado de acordo com qualquer " #~ "mudança no status global (definido pela caixa no fundo da janela da lista)" #~ msgid "" #~ "If checked, Gajim will also broadcast some more IPs except from just your " #~ "IP, so file transfer has higher chances of working." #~ msgstr "" #~ "Se marcado, o Gajim irá transmitir também alguns outros IP's exceto o " #~ "seu, então a transferência de arquivo tem grandes possibilidades de " #~ "executar corretamente." #~ msgid "Proxy" #~ msgstr "Proxy" #~ msgid "" #~ "Check this so Gajim will ask you before sending your password over an " #~ "insecure connection." #~ msgstr "" #~ "Marcando esta opção, o Gajim irá perguntar você antes de enviar sua senha " #~ "através de uma conexão não-segura." #~ msgid "Send _keep-alive packets" #~ msgstr "Enviar pacotes para manter a conexão (keep-alive)" #~ msgid "" #~ "If checked, Gajim will send keep-alive packets to prevent connection " #~ "timeout which results in disconnection" #~ msgstr "" #~ "Se marcado, o Gajim irá enviar pacotes keep-alive para prevenir timeout " #~ "na conexão, evitando-a cair" #~ msgid "Use cust_om hostname/port" #~ msgstr "Usa nome de máquina/porta personalizad_os" #~ msgid "_Hostname: " #~ msgstr "_Nome do computador:" #~ msgid "_Port: " #~ msgstr "_Porta:" #~ msgid "No key selected" #~ msgstr "Nenhuma chave selecionada" #~ msgid "Choose _Key..." #~ msgstr "_Escolha a chave..." #~ msgid "" #~ "If checked, Gajim will get the password from a GPG agent like seahorse" #~ msgstr "Se marcado, o Gajim obterá a senha de um agente GPG como o Seahorse" #~ msgid "OpenPGP" #~ msgstr "OpenPGP" #~ msgid "_Edit Personal Information..." #~ msgstr "_Editar detalhes pessoais..." #~ msgid "Information about you, as stored in the server" #~ msgstr "Informações sobre você são gravadas no servidor" #~ msgid "Personal Information" #~ msgstr "Informações pessoais" #~ msgid "Co_nnect on Gajim startup" #~ msgstr "Co_nectar na inicialização do Gajim" #~ msgid "Synchroni_ze account status with global status" #~ msgstr "Sincroni_zar status da conta com status global" #~ msgid "Use cust_om port:" #~ msgstr "Usar porta pers_onalizada:" #~ msgid "" #~ "If the default port that is used for incoming messages is unfitting for " #~ "your setup you can select another one here.\n" #~ "You might consider to change possible firewall settings." #~ msgstr "" #~ "Se a porta padrão usada para recebimento de mensagens não for adequada " #~ "você pode selecionar outra aqui.\n" #~ "Considere a possível modificação das regras do seu firewall." #~ msgid "Mer_ge accounts" #~ msgstr "Mes_clar contas" #~ msgid "OpenPGP is not usable on this computer" #~ msgstr "OpenPGP não disponível neste computador" #~ msgid "To change the account name, you must be disconnected." #~ msgstr "Para mudar o nome da conta, você deve estar desconectado." #~ msgid "To change the account name, you must read all pending events." #~ msgstr "" #~ "Para mudar o nome da conta, você deve ler todas os eventos pendentes." #~ msgid "Account Name Already Used" #~ msgstr "Nome de conta já está em uso" #~ msgid "" #~ "This name is already used by another of your accounts. Please choose " #~ "another name." #~ msgstr "" #~ "Este nome já está sendo usado por outra de suas contas. Por favor, " #~ "escolha outro nome." #~ msgid "Invalid account name" #~ msgstr "Nome de conta inválido" #~ msgid "Account name cannot be empty." #~ msgstr "Nome da conta não pode ser vazio." #~ msgid "Account name cannot contain spaces." #~ msgstr "Nome da conta não pode conter espaços." #~ msgid "Enter a new name for account %s" #~ msgstr "Entre com um novo nome para a conta %s" #, fuzzy #~ msgid "A JID must be in the form \"user@servername\"." #~ msgstr "" #~ "Um Jabber ID deve ter o seguinte formato \"usuario@nomedoservidor\"." #~ msgid "No such account available" #~ msgstr "Conta não disponível" #~ msgid "" #~ "You must create your account before editing your personal information." #~ msgstr "" #~ "Você deve primeiro criar sua conta antes de editar suas informações " #~ "pessoais." #~ msgid "Without a connection, you can not edit your personal information." #~ msgstr "Você deve estar conectado para editar suas informações pessoais." #, fuzzy #~ msgid "Your server does not have vCard support" #~ msgstr "Seu servidor não suporta Vcard" #~ msgid "Your server can't save your personal information." #~ msgstr "Seu servidor não pode salvar suas informações pessoais." #~ msgid "Account Local already exists." #~ msgstr "Conta local já existe." #~ msgid "Please rename or remove it before enabling link-local messaging." #~ msgstr "" #~ "Por favor renomeie ou remova-o antes de ativar troca de mensagens \"link-" #~ "local\"." #~ msgid "THANKS:" #~ msgstr "AGRADECIMENTOS:" #~ msgid "Could not write to %s. Session Management support will not work" #~ msgstr "" #~ "Não foi possível escrever em %s. O suporte de gerência da sessão não " #~ "funciona" #~ msgid "Jabber Traffic" #~ msgstr "Trafégo do Jabber" #~ msgid "_Enable" #~ msgstr "Ha_bilitar" #, fuzzy #~ msgid "Filter" #~ msgstr "Fonte" #~ msgid "_IQ" #~ msgstr "_IQ" #~ msgid "Info/Query" #~ msgstr "Info/Consulta" #~ msgid "_Message" #~ msgstr "_Mensagem" #~ msgid "XML Input" #~ msgstr "Entrada XML" #~ msgid "XML Console for %s" #~ msgstr "Console XML para %s" #, fuzzy #~ msgid "Idle for:" #~ msgstr "Console XML para %s" #, fuzzy #~ msgid "" #~ "Request offline status messages from all contacts upon connecting. " #~ "WARNING: This causes a lot of requests to be sent!" #~ msgstr "" #~ "Perguntar a mensagem de status para todos os contatos desconectados " #~ "quando a conexão com uma conta for estabelecida. AVISO: Isto pode " #~ "resultar em muitas requisições a serem enviadas." #~ msgid "Last status: %s" #~ msgstr "Último status: %s" #~ msgid " since %s" #~ msgstr " desde %s" #~ msgid "since %s" #~ msgstr "desde %s" #, fuzzy #~ msgid "No" #~ msgstr "Nenhum" #, fuzzy #~ msgid "Prefer" #~ msgstr "Preferências" #, fuzzy #~ msgid "Auto" #~ msgstr "Ingresso automático" #, fuzzy #~ msgid "otr" #~ msgstr "Quente" #, fuzzy #~ msgid "Invalid expire value" #~ msgstr "Nome do servidor inválido" #, fuzzy #~ msgid "There is an error" #~ msgstr "O serviço retornou um erro." #~ msgid "How many minutes should last lines from previous conversation last." #~ msgstr "Quantos minutos exibir as últimas linhas da conversação anterior." #~ msgid "" #~ "Your configured emoticons theme cannot been loaded. You maybe need to " #~ "update the format of emoticons.py file. See http://trac.gajim.org/wiki/" #~ "Emoticons for more details." #~ msgstr "" #~ "Você configurou um tema de emoticons que não podem ser carregados. Você " #~ "pode precisar atualizar o formato do arquivo emoticons.py. Veja http://" #~ "trac.gajim.org/wiki/Emoticons para mais detalhes." #~ msgid "You will be connected to %s without OpenPGP." #~ msgstr "Você será conectado ao %s sem OpenPGP." #~ msgid "The following message was NOT encrypted" #~ msgstr "A seguinte mensagem NÃO estava criptografada" #, fuzzy #~ msgid "Encryption used for this contact." #~ msgstr "Habilitar criptografia ESessions para esta conta." #~ msgid "Toggle Open_PGP Encryption" #~ msgstr "Ativar criptografia Open_PGP" #~ msgid "Toggle End to End Encryption" #~ msgstr "Alternar para criptografia End to End" #, fuzzy #~ msgid "OpenPGP encryption enabled" #~ msgstr "Criptografia GPG habilitada" #, fuzzy #~ msgid "No OpenPGP key assigned" #~ msgstr "Nenhuma chave GPG atribuída" #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages with OpenPGP." #~ msgstr "" #~ "Nenhuma chave GPG está atribuída para este contato. Você não poderá " #~ "criptografar mensagem com GPG." #~ msgid "Session WILL be logged" #~ msgstr "A sessão SERÁ gravada" #~ msgid "Session WILL NOT be logged" #~ msgstr "A sessão NÃO SERÁ gravada" #~ msgid "is" #~ msgstr "está" #~ msgid "is NOT" #~ msgstr "NÃO está" #~ msgid "will" #~ msgstr "será" #~ msgid "will NOT" #~ msgstr "NÃO será" #~ msgid "The following message was encrypted" #~ msgstr "A seguinte mensagem estava criptografada" #, fuzzy #~ msgid "Toggle the OpenPGP encryption" #~ msgstr "Ativar criptografia Open_PGP" #~ msgid "Is OpenPGP enabled for this contact?" #~ msgstr "O OpenPGP está ativado para este contato?" #~ msgid "" #~ "Should Gajim automatically start an encrypted session with this contact " #~ "when possible?" #~ msgstr "" #~ "O Gajim deve iniciar automaticamente uma sessão criptografada com este " #~ "contato quando possível?" #~ msgid "Neither the remote presence is signed, nor a key was assigned." #~ msgstr "Nem a presença remota está assinada, nem uma chave foi atribuída." #~ msgid "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "" #~ "A chave do contato (%s) não coincide com a chave atribuída no Gajim." #~ msgid "[This message is *encrypted* (See :XEP:`27`]" #~ msgstr "[Esta mensagem está *criptografada* (Veja :XEP:`27`)]" #~ msgid "" #~ "Your chat session with %(jid)s is encrypted.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Sua conversa com %(jid)s será criptografada.\n" #~ "\n" #~ "A String Curta de Autenticação (SAS) da sessão é %(sas)s." #~ msgid "You have already verified this contact's identity." #~ msgstr "Você já verificou a identidade deste contato." #~ msgid "Contact's identity verified" #~ msgstr "Identidade do contato verificada" #, fuzzy #~ msgid "Verify again…" #~ msgstr "Verificar novamente..." #~ msgid "" #~ "To be certain that only the expected person can read your messages " #~ "or send you messages, you need to verify their identity by clicking the " #~ "button below." #~ msgstr "" #~ "Para ter certeza que somente a pessoa esperada pode ler suas " #~ "mensagens e enviar mensagens, você precisa verificar a identidade dela " #~ "clicando no botão abaixo." #~ msgid "Contact's identity NOT verified" #~ msgstr "A identidade do contato NÃO foi verificada" #, fuzzy #~ msgid "Verify…" #~ msgstr "_Verificar" #~ msgid "Have you verified the contact's identity?" #~ msgstr "Você verificou a identidade deste contato?" #~ msgid "" #~ "To prevent talking to an unknown person, you should speak to %(jid)s directly (in person or on the phone) and verify that they see the same " #~ "Short Authentication String (SAS) as you.\n" #~ "\n" #~ "This session's Short Authentication String is %(sas)s." #~ msgstr "" #~ "Para evitar falar com uma pessoa desconhecida, você deve falar com " #~ "%(jid)s diretamente (em pessoa ou por telefone) e verificar se eles " #~ "vêem a mesma String de Autenticação Curta (SAS), como você.\n" #~ "\n" #~ "Esta String de Autenticação Curta é %(sas)s." #~ msgid "Did you talk to the remote contact and verify the SAS?" #~ msgstr "Você quer falar com o contato remoto e verificar a SAS?" #~ msgid "" #~ "The contact's key (%s) does not match the key assigned in Gajim." #~ msgstr "" #~ "A chave do contato (%s) não corresponde com a chave atribuída no " #~ "Gajim." #, fuzzy #~ msgid "" #~ "No OpenPGP key is assigned to this contact. So you cannot encrypt " #~ "messages." #~ msgstr "" #~ "Nenhuma chave GPG está atribuída para este contato. Então, você não pode " #~ "criptografar mensagens." #, fuzzy #~ msgid "" #~ "OpenPGP key is assigned to this contact, but you do not trust their " #~ "key, so message cannot be encrypted. Use your OpenPGP client " #~ "to trust their key." #~ msgstr "" #~ "Uma chave GPG está atribuída para este contato, mas você não validou " #~ "nesta chave, então as mensagens não podem ser criptografadas. " #~ "Use seu cliente de GPG para validar esta chave." #, fuzzy #~ msgid "" #~ "OpenPGP Key is assigned to this contact, and you trust their key, so " #~ "messages will be encrypted." #~ msgstr "" #~ "A chave GPG está atribuída para este contato, e você validou esta chave, " #~ "então as mensagens serão criptografadas." #~ msgid "" #~ "This icon indicates that this message has not yet\n" #~ "been received by the remote end. If this icon stays\n" #~ "for a long time, it's likely the message got lost." #~ msgstr "" #~ "Este ícone indica que esta mensagem ainda não foi \n" #~ "recebida por um fim remoto. Se este ícone continuar\n" #~ "por muito tempo, isso indica que a mensagem foi perdida." #~ msgid "" #~ "If True, listen to D-Bus signals from NetworkManager and change the " #~ "status of accounts (provided they do not have listen_to_network_manager " #~ "set to False and they sync with global status) based upon the status of " #~ "the network connection." #~ msgstr "" #~ "Se verdadeiro, ouve aos sinais do D-Bus do NetworkManager e altera os " #~ "status das contas (fornecido se eles não tiverem a opção " #~ "listen_to_network_manager configurado para Falso e se estiverem " #~ "sincronizadas com o status global) baseado no status da conexão de rede." #~ msgid "" #~ "The database file (%s) cannot be read. Try to repair it or remove it (all " #~ "history will be lost)." #~ msgstr "" #~ "O arquivo da base de dados (%s) não pode ser lido. Tente repará-lo ou " #~ "removê-lo. (todo o histórico será perdido)." #~ msgid "Database cannot be read." #~ msgstr "A base de dados não pôde ser lida." #~ msgid "A message from a non-valid JID arrived, it has been ignored." #~ msgstr "Uma mensagem de um JID não-valido recebida, ela foi ignorada." #~ msgid "Smooth scroll message in conversation window" #~ msgstr "Suavizar a rolagem de mensagens na janela de conversação" #~ msgid "Show _XML Console" #~ msgstr "Exibir console _XML" #~ msgid "Edit _Privacy Lists..." #~ msgstr "Editar listas de _privacidade..." #~ msgid "_Administrator" #~ msgstr "_Administrador" #~ msgid "Sends a message to users currently connected to this server" #~ msgstr "" #~ "Envia uma mensagem para os usuários atualmente conectados a este servidor" #~ msgid "Sets Message of the Day" #~ msgstr "Configurar mensagem do dia" #~ msgid "Updates Message of the Day" #~ msgstr "Atualizar mensagem do dia" #~ msgid "Deletes Message of the Day" #~ msgstr "Excluir mensagem do dia" #~ msgid "Add _Contact..." #~ msgstr "Adicionar _contato..." #~ msgid "_Accounts" #~ msgstr "Cont_as" #~ msgid "Profile, A_vatar" #~ msgstr "Perfil, A_vatar" #~ msgid "File _Transfers" #~ msgstr "Transferência de _arquivos" #~ msgid "Help online" #~ msgstr "Ajuda online" #~ msgid "Frequently Asked Questions (online)" #~ msgstr "Perguntas freqüentes (online)" #~ msgid "Fea_tures" #~ msgstr "Re_cursos" #~ msgid "to %s account" #~ msgstr "para %s conta" #~ msgid "using %s account" #~ msgstr "usando %s conta" #~ msgid "of account %s" #~ msgstr "da conta %s" #~ msgid "for account %s" #~ msgstr "para conta %s" #~ msgid "" #~ "By removing this contact you also remove authorization resulting in him " #~ "or her always seeing you as offline." #~ msgstr "" #~ "Removendo este contato, você também removerá a autorização, resultando em " #~ "ele ou ela sempre o verá offiline." #~ msgid "Message Body

W n { o \ C $    g )   U v f XW D / >  s   (} X @.  M R t A O I a ? % 6 b(A QrbMR;B}6)T Mt , LnB*h9Q*m_% ^ I0  L F k 5 < 3 H % ={]i WjGb7'L'\ "In 7Sm.AY6wZ0]O2,qv ay)o&Rc(rDnH' wooqy +O{Hz e.oXOaJX`f0. z,slP e^FSHVCBgB=D?S-U  V u !%  z F!_VO   1 t k  ', }b   N  > a  . E V ` d b" Z3 KA 4L T Z Z Z eT +N E 9 [, "  c   H  { r S ,/  @  I ^ H 0 B 6 ] $ (  n - |\hTx(@-)w ]2werp$qGvf ""66KN_nw%T@h%b2pJ^Jgk(Ut? dCj%M 6# +D_0S D[o.'|!cyS1[e|I_9 9l"<@M ABKHQ{M_ lxn;~uMc  E~ 2   A V 1ya-  u & pq  P A } n  # LQ }    = V1 kN yg   { m Z =     W    <  z 9g R x; "  8  T  cY / h c s Y A K 7 _ $ !  _ ~ f?M5NK 6sth^BXoW'ZEa]jqy .!L/n<0Pae7y7gi@t'5ZJtDMne[PO=F1D(H&Q(b.v;Ni-c A}0N3AgOONiqBhnBy\ I +?f8ZxQ  2}:?7} (7   Y  _ Z20U  I _ J  0G   W J  B   5 \ A ^ w    !2qAXK9QSSO~IB>6*h  e   9  `e C z    z L  r  ^ G  F + X    H fGf+pfp `KS IOAw@E'L>YSkbk t)yNx C|'[:VI|NEn)&zm'2Mi?oA$Lz(R,q>l,r"slK~+ B#4/C=W_pe.;de2!DZ^l`r  m G `  HR  (7] ^  nt  e m C  @ `   ;" xR ~   & ?P.\I``^uVE.[ {Ol^KN8! '  O  go J r  s m h 5 [  G \ /   e " e  FO  *f mgPb@E3|,(B)i0;+M>eIP6W`Z]/bj gNp}>C>_h=U/sCCJkXJ?9n9[;OAFNB_FvJYn6q ?zDQNY $ d7O/&4 WX*4E^&Y  / # J jbCjWwOsy  *!<!"j" ":#dU####$ $,$2$.$ $ $#f#F#-]##""4"!x! !{ y' w{0sf"VA*d (o2Agr46w`+]g#H 6  7 ( 'a rM@]>~ \ < A  P O.| E|kbL{ _ "eHmw7 Efk7 }'Mev[i"S=8w|I'n* (wsxq7sߌߛ߲ <3sa]i,n~9+(mRN m%Frg2nDG% / ~ e: ^k cs 3I O~ ;M   y=  0"Ep{&0L ]    ( _   e 5  (Td.Oe 3YN[qVHX&!yOj@^; Li&5hy   # L v w\+J\GJ2nB!' h 8 4 { J j>t6Ot'WnL8Qxh2r.j= O#wH)hR+-}ob1XM\C6(71^( .^'y"v(=\Rf}3"8yX]zO!8n"[j$5y^M"'xj;o w~M` a o , : D H aE03|b>1R,|m >u0DRzoS%B-SWI+Mq7n> H   ]  C  !    j5 L P NJ ; e*   * ( E P q  0 sr @   "f '  $  ) f%(  -z L H(  s   @  fh 3 y  t? Y_ /f fcv4 @vS*.gnAp{EV!>6(?`Y^ i_jfkqE!a1 6bf )~Jp\M*R`j[?7Y.^181]&fl1)pf2(u{HD V=      + 2 2K0)#/r!'*2c>KW`d2bEUK@I#8b(R pR)q c  y \D : q   S  sC#AgxaF9 FS[)tm.vX5' #OEm(aF;BYz;`!{;E?&qR*H{hhy=&g[w^K;0,.62EwXm!{1\3lG-Hd=eF0J^V3 p q 2 u\ > F  a  \ A}-uLJ|!i.V~:H2f e/ AJ d {   l 7    >  a     p   s  Q ]   # m2AY[w(8Mr sGmTz{p$WH:y*4[TEGF^d[|<xAStAJWmR.SShQv\(Y%kOjK*e(ek+XNP_zf_QE XBr) lNU ^>$K sy9JdKb)ck'MO/x | 8   . t ? \  z a 2+ Pow{Te".-?<h9O fd :P A3[|Pg aGQAA  F V  3  (] ;t#uh"\}H:.phK*. B  T " Bfy!t$=zqLfs <\KmA(n/n5 tt*_H->;$pyuqkuw5{}+}{Iyso/dZO4E:4=026L> K^u{ߎd߭^^q%Q}߫W GgOsaSEZ@;L\W n~<-Mt#yR2 %>TdiLd S7l  ^  U 0q 4 $:gS =g q n xX 2G1`|aRq8= <av=He]I8~b8 A'8&@:%E!^^ J1 a   S  Gt^] I{qwYI-zxT^El% `N  y< G '6p&[J._=#bv<R\?=~$N> 6NV{zS1dAD=dxCAT> xS`WRoiGmy9, L9M'MH~8  ?] h o  ]  5 vz ZCB.'Sv`p YK tT0@   ]   7 OR t x  X ` A 1  "   E ,[ Z y j   F w q o8 wm8/ap5W8[c%QP' 1 w c 7 Y n  9I Fc Pr W!^Tm-`+|I{jeBJ%*hRx1/yxFg U{m\b`fqc7%a;An "R>_Qp VWsd-;^b:HU =s-4^dC S= d h > lH   f"K qW$^eI0^&]]l1 V B  {2 > = < {V00 vNx"y]<-MpmI(;tP!~$a*@&h@p!P 913B2_U?;`]wxoT0 *X&V!8FOQQ MHDBD8H]Q]jyL,u6nY;^$1@AT+iW =`? l ! MH x .  E } k /6n7.qR8{>Nu! i1Ut6w(_!xO[{9' Q Kv    E   U   < q  ' y [ A @ ! R  ] ^}QR!8g~tQ*\ ;p}bgN +L[Dwb@|#G,r =@D~6c}QzR_VHI IxPb.[$^2vja_cn L^8Y9V`2w0e@I4{3^^ v[X4!K&S/K=0Qw[ a   (   -  x XX>'( VhJP d( 02.$mQ% n > "!e!!:!!!9!!p!!i!C! !  ]  ) ~  d XA?]T^&H%mNc:/1W07iF^^> ^ W m (" f zJ/p3urK#-j|g[VLEENIRZePq|P Dzs:o}mmo_u| g+]%Yu4i`$VNXc1;^~f+\ g?cS]5OXZi, ts & mv  TM 4 s_  aAx\-e6z3-'S $V:_j*F'_ /gLb1W|R *^23zrnintW~]y "=IuwN , p v Q0 ) F M yEKDV8,U {R*#>fv]B7$pTlI'[ uO4-!Mpykego;!vW,^"Ln *KsO)W"Nt  $&(0-T3}9DN%[dgt~)jWK4NQt#8.Of}D t M 8 _- z  @MslPcC>ID~ P NuK8r$_zV80k]  1 B 2O W |] a d Fd a fa ] s Y S t J > d +  L  % }IV{F5hA8<N,zOo0ya4YBm|:7tURj1bwmb a=]:zA=|vL<'eL7$%UXP pEJ>K&q pjO-f S.3TnpWa)CnK4|&&w->Yw {  N  V / p  q _* Pc @ /  %Mly:G} }d!E' ! !g !. @" " "n #% H# n# #4 # #~ # # #O z#a#yD#  #"&""<S" "P!i!c ! w5 G;3WRIq &tn[s&$a_& Bw p M +E x ?po`T'KTEEGNX6icy"S#2L>KU^ hWr} MW &p"(-[-($o @ ,*:Qz޼ݸWݱݭܧhܠ,ܚےیۇۃۇۇێ۔۞۫ܺ,Z7FWzݢXI4or4}@ic0bjwQ)7&l$6`U|hvJ|kC {  P - C2 b    x 5 V Gqzx<hzHT0EXfiz{/6fqPe&.j 5 le  ; a ! .!} A! N! R! N! E! 0!}! _  4D  Yu'u53'UXmWj0R(~^~+XAs%"t6 T x A a #efN>,1p'##4)v3BU3ns+k9o2w%f U/tHLP 6j59 {XilJmJ#}<(~Z,~3Y9 @ PK 5-Nup5r4w&`h(D{`:Dmyt=Vo:sP  !  F# ' `) ) {' % ! 2  h   AvmO0[1|i VA -j  $ q S ! * ^  T & J   7  k RC9"Yp8Cc 3$?Zxb4a%xV\2 J rL%FqM8 m H"   y+ 4 } ( b x [j  El2rc22HfgF) PY4z Bte%M Vi;^U{yfWWI@D:8?:@BKYJlXfw&Pz:4]g6/l=8 H ~ S O a  /L U { M)>M Y+`-d'b\SG6#O e  d B1  }  fN . p p/ l/V$T'f)8VR*]^vtc+N7 ^ #qVC7 0).P0x29=A C$G4KCNNTV\`ioy-4nhH BtEq.Kd-Ow#KtX^9Xr-U}%WF NOaR[ p(#.:3 I Z hA { Z !  #T B d#L+Wa Z"Y;7 oNS2`;v, k$&"W&Rl|> N6Kabw@etu a  @   iq G !+ &pt=  Rh-"es0/qP4sW)Kg5^{0j)ZANkH3CiH?)`.PK2g3=]^<Q.I2f\ [W"&sb(8HD*Vy{!}FU,#pLuy]'?% /? [7Rjm Z    H v   q ] G" 0; R g x   k 6   k o X _;    !p !: " }""<#I## $z=$-g$$$>$$$?$$$-k$I$r"$##Z~#9#"D"@"!<s!! D TmBt-cf)fI^6 IJ|xpg a [% YO Wx Y [aiv>b&>GdiB+jHd=j7%RXk.i, rTM _!ld޲xި ޗ݉HxgV`D5&r Cھڼڼ۾Ju5*Fa߄ߨN*\n4:vn.Tn?-@0,Da>_ =jqfA+;Mc\{:  0  U T s    ? V ^f 4s w w s 8m d Z RM ? 0 [   <  Nk 7 6  l B   q (!P!Rs!!!!!E!!i!!! u!N! !  l #' #>&-*:WMqitd'E\ FXQ |A?MxS@/ " j ? [.v/SxI?dz96yeNV0~Wr j z,2[O6"m*!39_){4i3Vb#@k]I.P@j&=Z|&Fe-f-|*#U*./00.*&lVIFTj~g$N3Mt%j@M-ZroI#$%W/ xluQ6p]2wN: $   Z ~ Y 78  5 =  h!K`+ h+>>Ncx`C&&7AEeC==. W%tQd-6MW+ c " u D Q  q Z# , , { a >`5l{ fSCB6+ #f #+T6EWLnKY;g}:?V &Y[lO~6O * }fQB9)@4Yt32/1$RxU 2 Xv } # w  'W D _ { N '6>A<0!  ~ N  d B a  b. . z  LQ { b'&:k(IRP[jepA |#@ Ckn>@2iC LKp_|SPH&@>@HUgEs 46EWZyoH8he@dv W 6`T ))bHj(r`AeQ0u@#* 0P4:?#ElKQXN^dk6quy+}}(.: C I S  3c J a{}7J4WM;+[VGyIG {7]| W8o:ftP+(JmYI,[AQ^UimoNmf\>O=o(     \ z V 1v cO.kbBsHb$Oyq z;)p) ]'y_#x5"y*'<8iY@D V[vEp Et#)00P0.)#cKIar.W<!߮ސ$oQ]4^ܿۤۇkm=T=(*Xs5&?_*|ߠYOOz@Sk<V{HFIHSe{2){.W~c, i,F^xM1i6]   6 ^   ~Go=X?#[Hck-fj3 #  !,C!q!x!!!d!!!E!!! !!Y!e!5!' X} 1 &,`cC;K{^u47mU'3GybEO@45.' )$ +t 2 < Kg ^ s XBL|&uZc aWg$nqP"}B4AW&GjDP6<0g,8?KoY@ _6 APq [)>`s\KA;(99?FGPXYm_aca]'YYND9 -J &w1lvQ1klmdmAjm~}W -9wb:`F{\77O~aY1p +s\JG4d#rkI j r Y @i )  ^  [  V 4u {/dNOh8| r&a.N599"7 ."lH#c>kG$h8 vX R / U  { Y? 6  _  f  s`XN=0=&'u(t4CVrmq p4b{.;|WTb,K_kA#Y.{dOv>/V%<&#-:pK[Rn.]  m  1 L^ i / n  = ^= ye    - < Ha Q9 W Y U Ol B- 1  V  V q M1 *^~ _/*O3:EAFz9MY@kI>q@W}B ^`KC*~U1 veWL}FwDyJ{[p5$gFl)U"Gk-]I }R(BeLGyI#dBdV -fRvSE.C'Vnds}4q)f a(m @'1:DeMWdAp ] 3 |   4` O l W  V  9 _O:4bg!OQ1v"W2i2k#MuDw 7$a1993&!Efl>  # 1 T@ H O pQ M H U@ 3 x%  q P  s O * =  t=?ZKu9(l;(V@9 <k+p([S45sv>]$Pv&PM[,y"44n`3Bf:Cq7weVGA?AGP^o*R|<f\H1pG<;uFVK=O>X}wL$B}HbkT [^{*R}-DY"lM~u(Y'^:tr[.Dt+VSjEe+n@nZ\T#v ߙEk?HݜwHU4ܬܗ܆wmd\'Z[Z^g om~ގߟߴe k1Y<\F|([b4WuftxF*u;ZBr&Y=g   + H#btw}<p]Hb/]4{VX,`Fk1Xj!<`=Pdxw)X2?VX vy!/dg(&<|JEB6{Y"<# uKNl ( ! *]b|W>lc=8}Vf3M/pxbG\] Kdx=v#MR"h/SftAU#(17=?f?M=67&/$  &8O}i]>O^6 A&Ww&%^5+V\+*a/|wn@ne`lDb!n~{^A# xii[RPJ:D?&=;975b1*-&6  h   C   $% /q 7 ? F@ H} J H D =7 3X *v   .:GOUXXlOUE>6%!  e o? V = $ t F  tK _ L 9 (]  O  u,Nt&-=TpXBK{u4[u9*v[)htuM0)UlQYH$:-#g@Q%- :v D S, _ l x! m : v  H +q > Q b p {  i = sa ` I 0 < 5 Yp + .dJ.[|d=itj-iMgf] jfq~o3ApO Kz5Gn/c Ml: |^Gi5V$E9.($ "(0 =L$`7zPq2!^WDFt;z(VE%+`~2NS.v^08/Sy30 3X>~W *tGb,{2&t#6\JaxF=?4M@ d } 9 % q  > ]W ~  C   ;6b)v 8fZ8L|WCwVH%O{Jz;[t.X 8 Y y z a B    & j3 2? F J iL J F r= 1 $ K  g  n  ` _ A :   y  9 V ?c^DIV~YK|M 2;jp B'XvC"[t DS~1]6MYI,Y ><V)&NcHz1U5"/7QPvnT&T2@+lFE?W/rB*k):uPBu>vli^-RG<2/WN}k*ZZH 5 #   ' D[nuJa}tpfUD^/3VfgAV'n @c   !.!YP!0k!!!!!\!4! !!m!J!|"![ 9 x 1 6vw:spTpp]uyU8 l(--F al|J  9U X u  J -)d>Qd wCz%\;rWw`SG+  f?X.#ttBy 9f.qR@@9OB\c*07Y)wEߡwR, |ޮzޕ|ހpaTLH W n tEGyfBS@y)$*qP,D,hP)M:FJHxBD3}MqA c7D SpO0/[w{y y{sX: +W M p,  n FIt( ?yu[<YUud eZV4yY`>}iw5p5V^+,]lW5VxVl  Q!&*g*3*&[:a=l< g.z%;Fnw4$Vi"0Pj ):nnR+Ik,Nx=\wj:7^o'M.W&]zg*TF9X1(!&&(M-5=~HTG_i vh~n\@**zAZq`1 p  = g    4 !S 's - 6 < @ B D D! B/ >: :> 1> +: !3 )   y b I .  X , h 6   !i86Qlg3Dpf4=wo?:cd=[`uY>n'(Eh/T l   t   b   5 v   & Z   + 8D%OAYU`fdsf{f}dy`qYbSOM6D: 0 # v A    B w R (S   A e /y  {4:LfY`{*a~^$Vl NEGzBADAyKN\t#^-b5wJkQ}|5;uGq`H#t`&1T[0Z9Xs < _       = Z ~t b C     i 1   n #   ,  p   0  A x BZ ; 4  n S <   p XiLAj=xu#iZ K*] P }Q<dR=B}kP1AdQ?-h.^jL%Hm@Z6uS:߽'߲߮߬߬,ߴ>Xw@5bx ^NnEu'{9+6?V^Zv%0rKP6 m2Yla4u{)j`[K< / / ]   .jC9Xdow;{~{Kywq2k`dVG8*l96z}aF- D e     y b K 6 ! n N % Ie U#AMK7':OLfo) 0;Wr*z   b   B $6GXdgu9W/y S~mX/Cy,_PrL"OYl8o1\"eiB+*h%].HVp NVWf-W%\,~mc]^9agu{Gnf^YUWY[i`hIr=Kl A@_~=f&*PuV,K{g M93g 0QnsL,8yWTx0 Q ! 6 ESD^fj8nplpppsp"pnjhbf\U$Kz@2#O '>O[rb]bJ_8U%F6d.}omb"XMG'?8o420F00u48?(GQ@\hOyTUQ !J @ d> 2 &  E n 'Y  0 kW) <FY{,d? tD{MP5- 8`9W  1 EF W f r P}  v D } r d S h> @'  Xm*V?,] dEY` \U$I7Le<~2/<`8PBnv3,u`: EmABtK[B-S gKF$N7LaKv6\,IBg98@f1~T-Hc |F}"Y.Id0d# J n  - > M [ j y  * 3 = F N T Z *_ ?a V_ mZ T J = /   ( G f r %[ QF }/   By)dgI.0uQp5[H5$$shed a   T   8    H    3 g    EfwffSE>'   \   ^ 0W   f ] " V  b ) Q7r5}W; Ugt}}|} (23PCzXOt=4iJ Qy8X ^3D [:paWQLHJNWar6_ JxA:`lQD_*5w Q|9((uEcY5~5\\ BX*x2pZD/rr8%w?3Vpj  (z b    K   &[nL$TB<RhQ=9g M2ZIn 8 ]    3 D T _3 gR go e a V J 9 $ * A X m } ` 4    \    F   O   9  l    s *Z ? +!   x g ; Q  } n 6 6y66 ]j j@b IFA|I.tg)YJhU"-lKRkV%VrC+$jc/t'`bT'|@c=lU߹G߭>ߠCߜKߜ\ߢu߫߹ ]5X,~~06ots-v1^~-\X cki8p$eI1; Yr#yf<y@i~ZJ 9 2# i   0Yc4<3HM[n~-VheEl P8Uj{s^C!Z< 4(o2=G+Vb=qB8$p-CBUhs{2K  Y   _  * 5b?H NdRVYgYVRmLF;w1$-?Z{[{<CyVP(/a+tfG afN uH"M{8$hi#jQID gB=RwvlBhfjs^4 BriP7$k S kC/1?[ J.CZ8sL/AQuCx92[|b 4Y^U-S}y- % _ 9 V t-7!4=Z"ug%{%W6DSa&nK}o #0m:EGQ^j|wB{2GF/F]+va%I= \k ~    4 2 YP  j  7g7[0bD+]uG(]+y*#\}- J Ct i " 3 T ]q  q ;   r! B( , , * # l D  m K_ .9  J  gL1Tz-4nYB&.g>q|g7R?b, !It 8|kpcYBNF@)95u31/|-/--/S39BLZY&gxlF $A^~qdZU:ShUZblB{~;|@)D_ N* w7en'tW&}+N~#u ;keZ4hU @Lt8AsS8 hF/(c\8/ o_  M , N k . f  R  ( : KM ` q  W   ( p   I   ! j   F   ! k   J * t  I  S  = s } w q <h jb Z Q K A )8 H0 c% z         z c H , x _ B "  h >  O } Gc    TB   E >  , P f D(!HR]xo x!{1y8v5n+h^ ViQNM2NU`otVD:E7x>UQoR/j%kdg.MzT3eE*(C(iN~ S<]JIN{/t\\t 'Gh!%$ &>WgrA    O & @ V wb n q =oc2R:[AkO7>!}Bg_, T!!"3##P$$S%%H&&0''(d(z(k )]V)N);))*,*K*\*i*m*k*b*T*C*,* *)))t)B) ) (/(9F(B'F'JE'H&D~&;&3%&6%$ L$#N#"K"!;!w W 4 Z|!E 5L.|u'X7X1u9 nJ  x - Z 0 P  n 1Pk  {1CmTfcu\J,`$(W8K,]n {V% .TV|'ޒ DqdObkBvb֌=զ7-d7қc?ќSTС\s5M- Es-EOsҞB-~ԽC6uװ%{`cۜSJNiZ߿n}:2Nl"*S'F\ #fT)S> uP[F A q 7kCD;], @gXd  x!"y#s$[)%%e&c&g''*I(d()) )W T* * +/ +z + 3, |,X , , -' -c - - , ,P , ], ,+j+_++**aZ* *I)k)  )(8(;';'&'&ps%$ $$[x#""ue! D UvBb[ 1<BmWlLy (>1q 3 / " F { fM: 'u`=[F/f{be =\h bx'>.,z%X? /j ,K 3* B }^] 8Y tA:F[hr%*uAB]pP|5>i5 z[/HCc3+ .2^=U<{ TzCDMpeT1I rIc2/ &8naW@-< Ox !$F;lZ(Z4OG\uYNP>G7!=(MR_i(W Q " [z C E { v U E * 8t^GS(5k?)f k+ :\cC  " D _B r | M~vj5YJ{;$/)|'')/z;HWScnetvVre%U;=EnSJ:#;~.CKKEa89' n7~^a*=   Z ]&   Ov 8 x  `   o  " j / 9\7L%4_q k=^f  S   /R I ^fh1iOgml'8\T-Iys_tM}PJh .X=mp9/s8Y6oJ( wqomqu{{vv{ )Fh$3CCiVkEyE)jlE7%Uop9v &E`k\@l;?+PSx e.ek]bJ'e69%etlWx/;P}+a Cz?5-n`M3   g,  ( b  F  v,  ^j)aTEuGy6l! ]  " _ _   4 \. zV w       u i \ P A 7 (      z B { ^ fA #  R   ' x bX 5  A }  W  <  N k 0D (V-h8 {tS\-D0^!xtJ$YC54?]p#[Gc2 ]w2P+":KYfpwvjcaclx ("T;Rez%b)rcl-\+g8 p?| gsP7@ n1f@?4g7 P_'Ps2)Wl'O &k/ 11/8-& R iy',f@5Go0i$p/Y{DU~Ri"7 Y }cLh7%#Os*s^[MA88{>OQ)m>d EP! _!&4EWrl:"pq*iggpiiLkg`wR?#&n 7veL27u) W )1e;F&NW[D[YUOPLHBHJR"ait4u;1bn.s-KKj(m;t.fC!   1 $ *7 L %c z "      . M j y  l  a  SF7{ash&`UI4:,"k   = {i E  ! O y  [ 3     m C     Z t( M   W y# 4PM@sY* )l: qi 2?   ` r F j cf4I\(e+cp7 9w> WH9!Io ^TYUqH;4[5 Hjkm&lSl$gw&s+'wgIm0 n M (.7P?ELTB\gu`~=!\Bl_Ym[dFny"XylhU@t)6 !>h4t*f6 GFu.o4IR}>iJr)!)|&9nK RAIp /Ar $ G q ) a (+BAhB 1:Bn;[+G/ m  ! o  ! 4 j,  2/DiGP#,2R0* n ;ii?ht1:gy2&TD4%Kmp/Sq,9ADA=3($+* &  !  v ] @    m4v1U  m+rB`_}.P5f`o(l]^ H 8 ' | " e n + d=` 6aZj~W0N4gs*&RLj,X:_/XY7hwCBr9 UOHߙ_`,-ܮۑzi_[EY]eNn tz׀j׃@ׅ׃փրրօ֋֕֨P דO8ؖrioCڲ&ۅOLfݮ qk}/ 7 Y/, |,Z(8EBFEW<*] q)rV@i30./;MXd!f#   G   _ z K  v ( u@9 0vGg~@x\^<*6z)E ~_`E@  !!#!MK"j""<#z####$2$?$G$L$P$P$R$T$R$hP$CL$E$9$*$$N####LL##"o"6"!t!7! b  8^c*O.b9i@[AA9+T u KT  - q  *i  6 6  _3  ! ( y ;iK \QUOUH[=[0Xi`Ox7@ "tp@ixiO1r. Qj\!]Aoi(ޣD]܎7Eۋ9T ۡWb8ړX$ٚrN/+Klߒ߻L߉b-Jnޔ.NmWKNIeB%JY( ?A &n@*TdpDvwr,fYUK<z-!J h 1 ' . 23w,U) u#c&]yL Q#<Y  n Z   s #z  n?!!!6"}""U"-#_#i###w# $9$"$ "$w$ $K## #e#Y# #;"o"d""!!#;!> [ {< },9PoHE3T~a'AY~d>7AT>#  : m & 3  /.w+Y+:|.P8}K& j32: ; h : ? 8  3  u- e(^ an5qfcW=O-KP:[dm&~ zH9RuUp8,_8~$p4hOjir$!V=;{k(Uh+F{KC dm&=V'lI'gG- m\MA;4226? GTbds>!^M}F8-p3*VQHTA`Q]eZ}VqS = 0 v  < -X q 7 C b Q % D f g 9    o +$ . 3 #3 . D &  H   A B V    g   D  \t c KQ @ + ]   , m   6  s ` cI 2  8 u    c C $       h M 3  yiVA#wO(p/Y@/(c`6 >"V&[[&25U*!    Km  T  nB 32&Qt> lVf2D6_6-=Rn@t6unP *K=zY;Jy<ip=bSG:-#pW@+)7 HWet#'-4:@DI,MGOcQzSUUUUUSSUU0U@WQWbWuWWWSOIB:/%  '-3;BJR[cit|7R-qMr4(OJjg!BEnq``HP1Kt3x=`}6p)!nSX!up/7EZ M]u9z4q /' Yd    0N k    ? -f < @ > 8 - !  + 8 @ F F #D 4@ F5 Y) j y    { ld Y? B )   e 5    a ' f!H]osg^5XTROTV\od$oyJw2r6^0cA+"@Wl}tpnpt&{=Tp67OVkv 6b ) D ] v F v : l & 7 F 3T ca m x  " P ~    % M rz o a P ; & ( @ T g x d 8  s8x1ziDT@&8 x>[2`vyG  zD nUX;@`c@; rw4g~[AVTD]po)$XbpdBY yY:S!zkPG$,$?xgnjl pKx(Tz2rfe]WDSW_n%9XwRj-#4I`yC)uU .8As/B{pd(ei$g/1EyH V7IU W 3  { H    `9c0p:[)It>  Z5  . K '  7  C{|k)SKj9W  ~+90BHJ'HtD;/F",^tW6 !1>FqHEF>4#Lb`#0c ;RQ {?0rJ_*$o q  [ a % ? B z  H U :,[`{-o0p -j$#(j-en89e-][P!^L mX)7?ZRH16^}t @߭Cj߀I(,߇Bߐ`'4E hޖߢ߄+iaPޚ=, Rޕ ,%Cue'މIidBvP2SaS) [kI3P0'c,?glBpVZ%0}F+ \g$2cl2;  Tx E  > Zf >f*C} +A  ^ z .  #3)|#jq^>VH1#bR]% XH h C  !   T   f } c W D ,!m!!\!"@"h"R"""]"""G""|"""-""=w"^"?>""4!!"!g!,!w  Th  '.a~+" hV   ?}  m?   !f6/?`>39/u!R4n N'{ {a - V 2 wR3w C;tDS7Ah@@I O_ K8h4&kg(C{t:Q\(4op'Fi:n Oq- }ܲCܗ~kXI?966=IIVe;wՊ՟gմ-4rShwdԞlw7vԻNTէYkֵop.?ؐ.[K.ڟMܐݖ"{߲SE*vKd=IxD*7.X{CWS   ,  U  t   ( / 9 , A D AC AQ5&ZZL}N*Wt6 _t*=38ln !!&"Nq"t"@##$`$$%f%%!&#H&!&&&"'C'^'o'w'~'y'gk'FZ'"C'(''&}&K&r&D&&{%A%S% %$Hg$ $#B#:"b"!cs! v 9jVK8L tD64D |  = h  # oK   M$  [ 'o & H R   j ;H_,z0mLblvy5\'-09o@LE.JMTY bk.xF]y 8-T]t?6/m 'Py$Dz)RDv3z;Q#c5iXhIE=%40.4;EVk0h85\,>Gh )ds15l\"!1T6eGd  u^ 6  c w6e Z I H r u   w  T%/94@->z,Tl $>xl^2t5rCktQ+m4|7QR5{nZ4 4Yv=u>o!&   L   b   \q3a^Q~= (+G c r } \ J :* -3 %6!9"<)E7THh`+>IqlT&[Q:f,X/x@H\oLX C4(\%Z(*6EXopD 3s]M'&a|Z9`7r"Nq- othI&* 8R|aFs*4NZn[HY:+!RKD4)8PFYn;o 50c`E$WY;9^~ol*l+<]OdZy`ebWH4 .1( wB  w d_ O 8 #q  %   3   0} ~LqdVE2Ju 8^zaH/   }fQ:%s^I2kT?(xLt5talP%@ / N   r ) E V  Y { wsQpnnDlll6lll.nnp-sw}6Ii"S +]9'HYgx`6pV$A9-Nb u#2 @M-Y=fPpc{x*CZs{nbQ>+-:FOYahmnIp&rrnh]RQ"@-KYdAVp=A fd'{,m,7g$DW\A@tw16ju+7uz=>cl3Cw\C.>j>Uh.|"Nz`>5X|g^)`xGe#AmEWr5)g/$V(|6rti5t Z,f:}65fk+bGkN # N@ Y p  > w    J    * g   ) n   D    b   ' f C z } r # f ` Y O D ! < f 1 ) ! ,  k   I{3_Amyq8i^`ZQIA8.1#Ja zp_$J,52 9 ;;;4.&tW:qMg&H']3U #zS9'hb.y# k Y " @ }h E d )zy?[0LYYg_g,Fx=aS*ng5,xx?>V\%6`+5=Um)J8o@4BdoL,Gc%߳ߤߘqߍQ߁6tf WH5%yf,>p|}L1%MlP9z7?u aW pF(T`wO?ek/`SPzAE>   < Y  61  lm*O@- J  N|  MX  J3  C ~ 8 U"-di!v2]R iTj H[r=  "M1;; ;D5*2mtDOl'k6 D l}{,Q(kr!\(h;u*@AGp?+-P xpH s ; 5 Y u T   s  5#R( +f,p+!v#|f+D17d6<jB,NBdP"\O"hfxF.-Dg/.eSB!$kr%(߷HM {ߓ޻\a*ݽpݯ)ݒ{ݧlufGf#jvۉۢ ;gܙ8 XKyܐߡ'z/h9ݦ=ޚ"޳`LLDX}l-Nt;"Ze65 -|Zl!aZSNtIRD2?81'vEg+ } Fw _ A #b;U&\%  V d   T| 'V() ~|%Xn   @5!!]!,"is""b"#HH#g####L## z#ec#H#-#` #""D " `" ," !&!!N!q!o!$!! !x ! !!E!!c!!n!!q!!m!!fg!E!R ! 1  W g wK pa eYZ?  vS   4H  M6_dmb [WQPC1[tr8O e( 4 h z9 ^ qL?B CsL=_k}/=UttZ/PH[Z=l"|V$2BrK#R duX}A.; `.pR(2@?I8Ve=wN߾q'CS݃ݷ<(edܢ(`ۣiH',lۯ ?ڍ2ۊ*JJk۱ۍCua3Ng<޴U-ߤY m 4NS@v p1; X}n6V>c% -_nJ(1:8 t `1 O >* 1 $'  (  'wF  i  #L w  hPx%A|,-yhP5n]~mT#5(s|k[JH5" 5eb4 ^ "j/w~:a?|=[n#%ZC   ia   Y 5  . ^ [   ?  , d = G=E9]%} 4|\R 9  t (  a I > g|f-E8& @nEbNafYr^Y.PKy;I1384GG_cs#K 9V[VN|LX,j@]7u^lKJ=+2 *!!{#`(I,026 ?IVf{#Q"V0dN4T$usu 6-d?3oM8]#vM(&<uUS*o0f:eC}4c3R;ID@F4=%_d&3D  o k O : ;  .z  !N  v{C+|J  R & i  < u0 s   H@ |   T 7 ^  Cs+F_vwZ;"0=GPrV@Z \\ZSTNC75(B:  & h Qc 7  2  ]   \ 2&  9s A K  ^ n r8    \ *!  > k Q, a j o'  \'MJ~>Wu=2+i&y#d~%0q[9qa@/lo>L* lD!yZ=!(CpaXA*0d]w]F&-i0soBR2*~-_7BR`2K*kt7I_'%nGKe[,7Ney E-Qu^7  3DPv[_aHg5i%ki iec_]Y TL/FF=a1$ LzjM:0o]uC`K7\$'`-gNN5\l(wfXWK1>6 0{)%R! ~ 0[^vhY]OD>8]3/- )A%q! ' @ W n { m ^ Q G = 4 . & " & ( * ( & "     n ] J 8 %  *:Mby{fQ!=J&v4fmY;Dv1 .qBcpb?UH<1j'V M@    a    O    '- /c 8 B O W? dq p }  .CS\bb`ZS KC8".(!/3 5 5 3 1 /a (. "  } 8   V   c p O +a  KP8x;KPw-SP?L7I{B6U"! {P_{B..J"b| ) 4>?cL"`S~*Fn6bN t*Ff-qCsM* pcYVtVc[RcHm?~=AHTg 6fAWq9-Y01 5e?hID%7v:"|L,e}%r P"'p( 4[J`hy7B^Rr fzytr,gFXH l 3 5   i ] 6 1  p ZEpgoE S#   $i e ?  $ `z  L  OW 1&PnK ci [,6;=AC==2w$ Kwg@;YtsKTHQpGV;:% [g +  8  R^  z  P  u!%/,>vP_UluB|\} m  v u i #S =6[ w{ C0dWv%P{1m} 'T02wDMb hFBJ"p{cK dz{R*EpuQ1p;xy}s6mifdPd(f fmu݀݌ݝݮ7!Z4dj"CD/Oq = 7 w O  W 7 X U UpW\feoVO2 RGCW!Lh*9m|6Mm{'/<FQ]_rjr{}rdSv>X%;iv;H ps78~F9yb0s=p6z^UA|%TQz %J 5 w > 5 A Y =  3   (5  W {u Y18Qq~S %>Z[v%T6KH_ru> m!<&|)U+4./2y3i1d,e(r),C3|@Xdpm"#RU&nX2u*ޚYޭށU. *X߻߶߶߻> u!I.unW`j46O_6A4?=}\H/uv\iE+c b{]iC+;p.i& I qNL$9we0H{S  A  Dd  } C  t lJn  ;!!!FC"""X#S##W###9$$$0$7$?5$y.$"$$#D#r##_#+#"B"a`""!c!! 7 ^ qx  o[4e!|~aD-$*z[+kOP  - u N  O 6&pRNW4B!rUk qE $j ? 1 j B =Q]of]mVrXuawwz{-{b{Gz{Lyhz#`&e@(5G\tCp$F8lo (O`=b=DYIMl9tD{Y?p.YG'8-*''8+2H>OZb{lz ; n$.kB `]u|O4$ !u-[F?j!9m{"Ez '{ = A M c  D { - $ i 3 '7b>7hED$Nz'  X  y % > Q b nuwy{[yu0qjd\^UOnG<2^%#[\35R n|JM  s 9   ~ c@ F $ o %   fL <  l # ~GCY_wB)a=tP%j2  = ?  < e  0 Qv  Y H6Ix []$CY-)uy`P(RMgD"UhlAYG6w%6{C pBrM+ iVC4&  +8GWhy&/7BN[izxpg]RH>1$ uf\OB80'! %.:GWj} *>;_K\m~&TU1S tJ"ZT-rODBVt'nUGi"iR;<|2aj*k3_-n 47\zG/ MB h{    ; a       2 G \ o } $ $ & ( ( & $    m X ? #     z T ,    y H  k.m-f#^ [&1;WHR]gVrzc+\+d@!,8AKT\ddIm0sy}uk^T,E=6Q&hx]#?/ <FQ[hhv>Pp3!p#+%%%T#!!indI"W{f!Q?;U ]?{Kߕ%c5 ޥސ{j]SMKMS,[Qh{wߌߥ'n;mm8` @3*4QJ0 tJK1e8 xT2yjVpE6i)gfghh b{ c WJ 0E0i<k M`/}8W  *,  a \  !  % = ! ! !QC"" "e-#l##s# $5$qZ$z$$a$$$;$$$$I$s$N$"$=#v#|#<#"I"yU""!J! D f .7- [.S gghF%U:uA  c  W F  @*vXZYDE3-Fl3  G '  h2 27 6 l.E' {]:}| M!?eL1uo9[\[{ ;u*\c &IQ%}Q-mP4tlm~ +\F,LmU X4&d@t~aWNTLQ[Qj p8T{Xh=r-;*4 Jo-7_o UJo)4~d&%y"l/w#wL"w#Vz'(1r@ 6   `,  l  H 2\Q  gV  y @  x  +|7\0'|3CSX=O I7[x:]}mT9OnQ6i&LZ*bgg3[W>wm0>hn-\>\| 0|   F%  < U V \ n  a   "^  : V P  eD } ,$m;OUr.k 7IU&ua$<GxkV"K5u{ uQK#~Lw^Kf;<*dG,0CZu#O}Rf[!?k^*W+],Hd Q7NKcZ~ z3Ib% ?s)jn_KTB1K}My & p ` g  [*  HO*eqhs/nC`KJ  / A  s * <s   J@ z  6 { N z 4 j  4S?q_z '1:<@gBHB"@<71d'+ dz"j6}jWU>j*o  g  U ~ ;c H ,  N  u } ] 3 >   C   Ky X 2 P   T m A \  m ] &- Go=u Gm 7|Qru^{w6"rJ3vu8:qG% h_?$0}E3m;9Il<[ |QB% t~=V. dz}].> AC>G~OXf7usW3]"P|R;ZEyWC/F]MrxN+  i$Q(-7/357 7;=p?DgHL`PTYVYP[[=YVRLF[=5-{$1   5   ( s   D    " P }x j W B -  !2>IQUwX^XES,MC4# z Y 5  \ 7   Y 4 [ )   y TZ .#   z ? p H  S  `b<&r5}aHK/m8t{DobVMIjGBEGKTZdeqC$gR6>S+r%Mw L}zunh b?^sYUQODMwKIGE3B]@><<:*:R:y:8886:6[4{22.+'#{]}<lYF1g4T}`C#Q s$zV|1' ubd6 KT*&hi;9 p {>MsJg9 .sc;lu%pSC:#z<\,_="%Bd ";Vv>c2`*VBOa3Zn eT|<)[g9 ReERuB5/[&w@b_I4  >] |hH (C^yQ   t  .  4 Q> l  A   4+LnS (ER|{E)nY$PB]v#X1 h    N    8 s    rU ] D + " R    {U0.Zm7-JcN|Z  _    J   j   x~ a, F ' : ?d6?  \ <   2]  ~ & 6 r  A e  8 U{ET1yGek U0GDBUa>k?tyB~GP ay#.0T@ S>ms2Eqv3MD 4k58O~T(I~rTU18wofbbbf k-uV6y<[b]Ast8 Z|b-{W&XjC}6Z]<';`"9=[a![4:M}[`c[KL44 } " P o   w a  + O & s ' UIu@x 9c d'@7Uj{K1y1i*Qu{hUB.wXm6R5[$nHp"-X U*g  ]x H  ?  t U ! 2  V I r   e *   't 8 * $ { :   v 3 v fb!JM-t~+[K4 iyO3!G[,Y`h.|/f9Q }R\B,R }IkYb&I=r5:?w6L`m(|N9jq%PCWh Eߖ QzޓVZ1"ݹ݉[1 ݮݔ }&hEXkKC=826q8=ENQfy\.#S6;e| SSbDET^'W3eG1xk_sOBb4'P :% } _  ;x\{<Fbe.jz6_]? [ W  ,  D ] A! ! %"Q " " W# # $D R$l $ $ % E% s% %1 %L %c %z % % % % % % % % l% @% % $$V$ $ # c##"E"!m!   |] .   D   ?   $i  9 x 2 l   J  s k  e O_ X R J (= _.    D  h 8 : | o G? % s| J  l h z% :C tAQ;+/o0P?[%X!a.[ DsV,eit1 sM)+ =Pf~ )Mx F)Kp'v &]{+VQ)wV kbs:/[*}wtsqXsyG:56 ->YEO$_Y`!ffp@{1E,DUe_UbJ^?R2C'/"w4Y O5 p o )5 O L t  M)B<T`\g!f`_  P B t4   r & K3 m  4Y)6BRMU[`b6`W[uSK@0 iE"xJ\s68|9oL(e0l @ 5   f) % s  V  T B -   b C  *  UH   y / =fI"[ Lpw# Gy8jNH3j8sG~[9{'f9SNBc4z'9Xz<\{ . <+KFYcjy,Ie~'7H[n'8IWhw*7CP \i(w7FTcr!8K`r 0EZm1Lk%FhCk&Nv6`GuFz:pZ\M[>{"b7x+nE9` T&e+tELy`M# a - e  P  * O s, `     D n  # / < F S 7 Y L _ \ d m f z a [ Q B /   x k Z E {1 \ ? !    W - _ ;  o 8  { Q 'J    @ b=i;eD"KVn]U >)fw(>Yy:uqoso4oqswV|$nDsX?* #)28<BGMQUW[[([4[CYTSgM{B8+ :WwmR9 $?[vvL"4\O#hx>MT!'-1K366w6.3/)R# y2^RoV=!Se,rP1e<`:oS8! \6c@4fSDs%)S|u`K7P$j c b|t n[gccYcei\nt|{DwB`&i=VqbS -@Sy!iD-pj ,7`c:t4O(ig,o<U7"q}dmZGW4 G:z-a~H/#w j   V  l [8 H : ) Q    Z   ZH;e2Oj   w^B#ykZK;a*5l3|a>B  m $   h> @  K   uF I  / irD3[Q!-YB)T_qCdd^X(THb=4/!`=s\rFL$2 {Q' ~e N7$+EgtR21qelwY0I>2e%(_7|zusuw~7]$`2+5B\ykQJ$LVvp(.Xh \Q q,3po60sf@5XV+.wQlH&.y[r J  9   d[/+kP2uP6jtX/k(I{-  6 _ h  ) $ !J Z!o ! ! ! #" E" `"? w"Z "u " " " " s" ^" E" %" " ! ! o!% 3!- 5 > Y F  L S OW [ ] _ a >_ ] MY Q PJ @ B8 - (!   h  4   S   au ` K g4   b  [ q  R T 3   Q   Wf @  cwm?9 fr=8 l:bJb<*4i5$@GTn`%9Rf ^:F:>&Ih cRFHDGAY3"yW^)JbEARn#zgO[ PJFFDDHL]T)_n~yV6*R|8n"gI2VQ}xMG Tt&   ff '  r f ( b  e 9&  e d # ,b&9@xA? <t0B    u = i  M c-0lBgJ-X.jvUDA3s@)&$W)%*s3CBXp7v 2Oak34sY_"[{B fb,=yR<\W*)v~NV(. }cfFU)F:2+'''+4l[EMoS)Yq:3 ltPZ6"U[(m%1@=M_]4s{M7X`u-p/7y?I6rQ  V $ ]Z  W  8R k G54b`9/aP `,I f[= D }% 6 B Q =[ if p y     * 8 C G I{ Gt An 6h (_ W Q M D > 8 c/ 7#   `!IqXRA,:m$8v?_A<$,    d\ D '1  b({bKG*  f ~c:@Z nMR+ $o`Y;IEzNP)d"\]4 SlkB$l6wM#hM~6V!/ lF#.AXqoM, #OrT"9_`7nYD/i ^YVUsk^PTI?K7,&D9 $ q  H T I +a$*)4W=GR\i"uDe.Ie/Id"D+g8BKU`.jZu!WAA  Q &/'5s;FNRYcp4|hWK:(4A_P\k!y^ D {    T    ! +2 4S <o F O W ] f l r y }        } ym rS l4 f ` U K @k 4; '   d + y=qZ~A;(n'KaB"k"DdDo%*c$iGl(2Sv]B+`4 aF-pdYME<60+)))).06:BKU`jw /AR'e9vL]p ,:(I4X?dGqP}X\`bbb`\XRIA4(yqxhY^7QE6&uGQzeRs?8-A{8nYiB$-R @u4uk`rV1KE=w6:0*&!X$g@!(0;GTwd^uE.-BUl7'_>Zw(Ms Hr32SirY!I"niC"B)_y|nm.wAV/i|Ih'Fb#Dd#9CB   7   ! o   F    N   8l'Nt.EZ%m4|DWj}1LiueR=$ 4RmjD){DO`!{   X $   x > - 7 ? FG J N N PJ N L J DH = 5* ?r-YfD!AtT/&`c/KOx3VbLQ  :?lp'*V[DE{v8/sb2rN3|7Ij%~P$XxJN$CY4EQwfk0`TG9V,"_1fC! *;vLa\PmA~3& 2Q$u3DXmFt 42^g:Qr(Ji*4}{/YP?,g{Np>9jAlUto6ritBo"di NW.KuC@  9 ; v ) o  I y F  x # D /c  E  S  T  K  4   t  4   8    J  l O - 8 X u  h <     T "   q QH , ^i/ad"yf#%ti*Sp19{Q>^eRhet@[ O n? > /  W +} fNd?6! cAs cUHt]=F/5-,-w/^E7,>IVey~p_N=5+Vz 8}fjWG56'p RBD|gPV; &|;I\|4pe[ND91~+p"gaaclx'/9DGRu_rY/|$=~\~@Gsut Bx<(kdH!b:/vCOg$6g,#uMgXp9BX&!rwM>   % jW   3tW&{Z-) B nh   :  _ ( uA X }k | t  V  #   * z   E t e R  ; 5 & W  r f D # p Q +  b8f*iR?Sl.BTjusP*kW6|]=w?^nSn:! o   j   d ~o]^N=X*Yat2vi[[N@,/ uZHn>Q2?FZ{v[:5m TV(Y i9q*pc>& sM? kw5T2`)^.zvtxvLx$~fE#,Kkq^PC/9]0,(&1(k*29#CdNZi6z_O'GjNZ>ny@ A yo>%`xGTXT*)ptLT6,w S`5)pmB:i\2-r`$=~E;uY   #] Y  S  * ]>    k G q A / HQ p   2 i    ./ \? P ] i t '~ J l        0| ?t Ik Ta \T `F c5 c" c ` Z R E 9 *t U 6  zWs1M (KR$g([']}`0.  5  g 3'  j  Q C  t e *8z_B h,2F`Y#w{C 6Sk9q$tDKwgB;{`pJ&YfdI=/t7^.|mbVNeGEA(= ;9;=?EKT^iu6Qj(AZv(Lr6\ 2Z)S|Dl*T 3[0`#KqN~!A@q_{%O{)@"WNlx*T /Y'-39>?BeDHJNPRGUoWY[]_:adcceeg.iUlnprv xH|rIu0` P(9GXiEyw >p ;2pI`w8k+ Y  " / ; H3 TZ _ k x   : \ {       % 3 B O W ] c tf eh Wh Ff 5_ $Y O B 1     l M -} X 2    ^ ;R    v < iF"}:gnK':KjM[1 dozw)fZM:C80U* #!y4!m&/,2:}EFO\hw~R*iP+;B(Wp 0I^u +;Pe|$1>J=W\a~irv| ~1~W~}|vpg]9R_F7)  ,Khu\>#%% *Pw@qh`RE90F(v"I$,-4f?KX i>ys ;n4Q7ri0+^T~+;Nkr<t!;R[iOQY$g4yGTw^gTC0]T?xucP; &J }    ; g   w d Q< @d 0     ) D _ x      ~ s k `. V= NJ CV ;_ 2g *m $q s v v s q m g c Z V N E ; . "    x i ] N @} 1a "D '  \ 6 { d K 4 a 3  j x3 ]@%MPsV6@g~aD3$>AdM;4.x^s?dVI?4Z,$5r P+l R(2@=GT6^ku7>St,d+'1j%_ u`Kf8)%IzJybP?,rK %y\A& .!G=bZy)MS}* m=t=\%x&[>-v t ZVCM9K=IN[Xu `+Xg*mklUgEX9:  +  xH   f . b Q 3  > jc   .  O  e  o& * n, , a&  I  !   L   R_ <  + l  f 4 A g  X    [  Mv/[S1q&f)FX fkCYt.1Yn{2}@).`*,%g 9  m tZ Q -F 2gG~( kYK~BkY:H78$6;DTgudUG:.+!U }GbRwoNg`ZZT PKtG*CAAY????X?ACGvKARXbiu[4oV ?#(<Sn&Jn 4(`=Tm>n>j7k= xAy:!U]0NdS9nrA Au|B|r(NR|$d6ZH{'d/KAd{}X(T v  " & - /! 3 3& 3 3'1-'*$" vR}3td*Ow<'K=ru\E,?\sx_F-s`G,w `D)k9Iu\Eu.(3#zcaJ11Wup!^ I& 6 #'  !  v_rH1]G1ytdO`8#M :-#iR;$&3I{fgQ<)O(pumgXK?72(h) }ImL* $.;IXgu (Hk/F`yAs!a*F._xz`S:TRm h-`':0Oat_w+-4)4>OGOUt\b4hlpDuy}2{F P#nJV/` D$t1@P _?pq 1 [    * A \ u; V q     < Y% wE d     ( H e ' 8 D S ] j 6t R k           + 8 B M U [ ] b b ` Y Qt Hc <S -@ )       j kG P# 0   ~ P |" T +  Y % n> }AsA Fn}96\`)~3QK^Mp e90DwSZ/ t*OoZG~6=(|=W!Z,.p=PK1^o{j\8OSEl>8668>E3OP\mhw2Kd} 3H_x#8M_ r.Ru!@`1#P%n''''%%#0G^u '>Ul{tld[UMF@ <6"/3)A%R!ap|!#'-3:@HQ[fr&}6GXds.<+MJ^jp8Y{"1@L7YYe|p| N| 8f;c    & M u<d1Ni(x6pGgT_bWmPuJ}D>71-)$ }umdZOC4("'+17@HRt][g?t& tW8.?RueTw2kJ+' 8M^n}lM0~bG,|eP9" r^G0jWB0eC t_[M1:'S%j}@GIrORU3^fp}wj`WQ KG+B;>L8]2n)~!  !;R k#4EUh}1Kf ;U1rRv*X(MsDu:d3cBs2m7'ij=;q^K1x+cO +Ex{b#[S1Hg60^!n R: a  4     _ , J c 7 | |  G  @ }    &  Z  # Q }   x ] >A _$     n B  "0=}GKLRTTcT$PJAf7#* V9z[Y:w*o>F  bm 5 : @ ` y 4 L V Fl  wX!x ~LpbjBL+iy^CB,}[=$lT9}g [ b0EzZ0o]K2DCWlF b.-BYvnN(}fO:.#?P`qyqmk mq)}:K]n'>U n$;Vp*TA`ZS:aa 88f)+7_^7-moKI&-e{hI[X-]dhz;m(,X8FR > \_  h t }    (  7 C N V Z ta a \_ ] <V N C z7 * ?   S   P r S 2/ u +`kC(DT]"pQu=~iT;_(}MIu\? 7vD<&^4_ #nGJ'cu } ^ ? !   yr]pH3d XNB9wd1O<)+'(-8I~i]T?w($Ju vaEL7 + {'5lUS> '{4m.o`JPA0$o K* xcP=* *=Pe| 7Pk@d:Z({T 6Cdu?KM(c)rQ T H>5IADf1;wo'GbJgF&-\#Q(yPxnaP&E<b(   o - < Z H U < _ j  r ~ y  I   h   s } v sn f [ _Q D 6 4) u  %Yu+\LAk& tT3b:~aB sGwGrFe(l]>}.R 5+U$q L ^ +  I h 6v  1 d0Xz [&+KYi'b70Y{p @3^Y-"Se!A[8~~c$H/rp~.Lu0k.J/bJ8gk?Lk.%Y/{gtpprMxDA$E9PgD8#sM{RS$ RJ E4[> &GD]t){"x*6 ;; >FXn%te5RB1= >@Ayh@YK<7-f:    F    G    > x    L |   'Ms1LczwjkQ^7N?. qI   i l7 W B ) [ ! h ( p S 8]  > vX[@%i psu^Gp0fZNx@me]6TNH,D?~=&;9{9%9;~?,DHN;V_iUt |4i'l2#4EXZk*}zU1/BUyf`xI4! ) 08%>6BGGWKhM}MMMIE@<-4N.r% POp]NH~6! EwSkQ: !H Gi4Tj?*1_M{nfO[UMHD@Bl@@BF K-QNYpdny7Vu* D)_Bz[r?d/F]t@f)S(8IX-iWy"Gm+>O<`^n}1Lcz "*3; DJ!P*V0[6];aAaCaEcGaGaE_C[?Y;R4L.F(?7/ $ jzUk>]%L =- dE&|uYf5YK<0#}U0 mEsg]Z5NA4(}Y8nO1vcR@-u^G2 sYB)xmclXOP1HA;731y-Z*:((&&((|*]*;-/13579b=D?'D HLPV[aqgZpCv.z|~tznviterarapapararepipnktg|aXNA3$ .AT}gp{f[QF:-4Kd{qXA,*?Ti#x6nEcVWdLs@5-$"&/'73@>HHRS]]ihvp{2Mk.%<FMj^l(T~ 85kLe~1d"+=^\y+_8Y2{g8+lNr3eAb!P~%+DUd}9](D[p8Tm  !' &6 &D &S #_ l v           z a H -      ny Kp #f [ O @ ~1 R! $ c3mdV-?& RznY59Qb:n6mXC!N]-Wd)2y^P*(NnL+h +v:w[D-EVp6|oeKXNC9W0*"j2e4W+ y K  sN, $(.49?CpI_PNX>^/gow!4I`w'5=F_YlKy;\8lJEpA)Y S()^u  [DE9x68-y~$FwneaGM-}- t f  F R   =C   + {% W  i   X. R q D   / z  X1 v   C  I g : E r  C v s H  !o I4 q  z 7   /f H _t?Rbkrw'p].F-9KjEa 8c 1 c Y ! W  h ( \  _  t = @ u\Dpm{E'*~e(F'y!qey fSY@0OIFDCFOgDw4'8kK*^uj+{ E)FeV.4\rN++WfID2t ?sQ7r&^O!6<Qym/i>hZ B;}i T0f!TW&m<hO @3Vz=G0]Iby~B rA    Y # 5# # !   f  H (tP(kVj A *;   o  3  m RR 3 ` [pO-C \{X6H~ ]29XzhG#%-24|4Z09' xY;zV0zuFW:\LnS8hu o { b G[ ,  : t  | _B ?"u 9dtYOLr[l|5Rp !"8*O2d;yEKT\ekqw |  ' 1 < D M S Y ] a f h j j ~j |h wf ua s_ oY kS gJ bB ^8 Z- V! R N GC?;42.*k&T": !rP/ wO' "&*,V0*49=CvGHNV\bkUq%w\*_-b0l< }O!mA~rqKb%TE4$sR2v]Be$L 3lK)}p{fUY/O D<4+q%K#_9#{+U2/: DMU^h^p=ykP73H]r{l[OB8-#4G\ s+Fb} %/<GS-b?nT}i~ 2"M;hTn!;6ZHw[n:]'>UDli:d'9L:_frGu3,c?Rew"TDu'63DcUduKy/] 1&[/7@HNW:]^cgkrvz |6 ~Q l     ~ | z v r n$ g, c5 ]; WA PF HH @J 9H 1F &C = 7 / $         t Y y: j ^QD8)b8 N{ByToe\TPK C=7@.("k$J n#Fm#L}:s4|@b-oCaB$ zpcWH9)sf^UMIEE{EfGQK:Q#Y blydB#$u;QR0ii H,$IglD:Wu{T0 (JinP5$C`lM/-KhygVE;.9$Xx :\})Mp+ S}*;N`'uR~2`4OlKy /;Tn|4!gMy+[4dA*m_2AhiJ# D d 2 l  W  , = CN ] i v 0~ j    T    ; s~ t g Z OJ 9 $   N ~   n :M f+   < ka ?     V5 &P m   U    y ?( 8 I Z Wf s }  j -   w ;    N   u bj )^ O ? . H  o :  t V r7 ?  W] +6 ZV2& [$aB"{BMuY@%J:i"o`PJA4&l# @Zv*Kq(R ~~:~k&c$u>uG.l=BPbubC)/Kh /RxCo%S :VWw4o/U!|]&OP| L8n KJQCPIKY>y$i$[:,]^= D !l l  Q $ C 5c ~   e   D  ! $. n8 A G IK O O !M hK G ? 56 x, !  : y   / j g  J L ,  K w Y 1  ! F j X ,    g 57 N c s b +    M    k 1    D    Vx e R = i& 1 G v U 1 d ) {f C:  c~ -L  Y{ 'D b`0&rr5By:b:y8t|3X7l+b~ aH-WM F{phAb^Y~W?UUW\B`fnyG Rd+/JgN |.HT|}K#O}\ 0@rjEFy%!Yu\9@r'T6nsia\GZ{Z\agJm|v 9g:`0Id1NnDp7k.AT dEs{)e"e8i ZOF?{:qgZ:PC6@*GORPvgHYL=;- (s U   , o   {4 ls ` Q B' 6_ )   . _    6\ ' D)aK|rBg*= M\kwlL)U%m V ? $J    Q  g F $?   c  n G / CwN"R`vL"o|+d@4;}_BB)KUbm}-A[y2ZF@Ig3yquEokd^VsONG*=4* lQ<%ziVD1 -@UjnQ:Es~bIK0>|vA[@$ U7y*d~Q>++5EU g{6GRZ+`D`}gk+R`|A$M wI: Ft r  V D ! IM y  _   : QQ f z  7 c    ( b   ' l   9 x    ? b t _ H 1     8 U r` :     5c N5 c t  r @  q:~Yzxtphk+e_VmL.?3&r5 w8|=BMa)}wKrnllzjHfbYQBY1-X0 u^G2~a B$ nRr3[D/nM+ bA ~yisDqmmkk{mQo)qw~[1^2_3 -:K[dl8b8 -DYap7 jB(C`{Z7)FdgH) =_jQ:% .Mm6Sr|uqo!mEmhmosw~ 9Pg|#8 M;dV{q7_%4B O7[bhu8bL $A-5;BjHLRPW[ag^ntz B{6v,<3|?y-l7`|vp1 ir a Y P HR @ 7 / $ 8 d     B j     { j& Y9 IJ 6V #c m v ~      y e P ; &   v a H ,  i R ; $ j H %  }o hC S > ' z ?  > ps].O>-g$]AY wkf^TKoC:2~*/#I d2Lj#M F~vmMe[RJbA*;5/*P&"d: ^;nWB- {yy{} 1F]t -?Pe x&C`~.W!0AO`3qa"T--DhYn$i; Y+<*Mp^n?lj"'A3>HWP[cRnv~4{ S94:   1 |   C }    @ l     = e     8Odw $(*.2479;q=`=M?6ACC G I Nv RN V$ \ b g mp s@ y   o 6   ~ ;   d  8[ '@08@iIS^f3r}:CcSU  O(/7=RDJNPjR6RNJFw@K7!/$~W/ {Y<!jS<!wgTqCR22"]5 ^0vH^.m;n:qAa7  uO*+4?KXbqb~C$ta'PL]n6[1_.Ig(\+6]Y}M{DpF|!P~4u8@h=3ti(IPu1jMQ V>z!M2ws0n  / +> gM [ j y \    M    7 p    I }    D t  , r Z [ B )   C ` {  o T 6    ) : pJ HY f r }  n @    x gl ?] O > +  x N "    jw 8X :   q C v J   e > M  }sU:.L ]3 Hum,G#Pn#aA"AWhfH+r!{,w`=K6!Sk7|kQ[L=s1*$ [\!q;g5W2 qXA, &1;DLWak v,?Ti<$f2CTb%sY=w) h1D'Yin;j -[AXmPB7.Mk,%v #n:QheXG:b/| 9Xa)l"39tPey2q% ] ) O y * X  & P x ! G j    0 = K1 VO bj q ~        ) @ U j {            x a F +  } } { w tq pM j* b U H : )i ?     O  mZ{GG4!k3M~eJ-\a"pS8f'm0xo;XA( ESnU>f',Lt>s bSBk26!n; W+tldZ[0SJB8-i#DnO0qZC{,qfZOA4& xrlgc_x]g]T_?c*gnxpU:2NiuX;+Qwi$JU- (`uW:U[|!ebN9$+nA!o]|xvIvz~+tEY-.vAVmIQ 8h7kL6fE% %S W & _C c  d Q  * O? O b Js   0 u   2 j    P    K    d} q b /S mC 0   C o    g ! H B ( a  }  Y ( 1 J i    b 6    x F    y B    i 0    H    Y    `m "R 5  e ' f 'p W < h! ) h*oKm&/t8Y-IY/e-`Q4TP$ n[D)e4\8r@ iuR@; &n:b.X$QyC g15Ng^)'\K(s_/Bpn@;s'ef;(itP,/m/r}dAM6# q[E$l= O a!8Q(li#]Bn5g9qK'sf) i' D a 2{ w  Q F  V" ( / 1 3 H3 / * o$  '  ) }  t  r |Y @ :%  nAfCp&z~TX( O y M  F   ` .S   ! g_ 5   1 jX 6|    k 9  0pE>Z oyI]/T,ydO:#e?  lg MH -&   O  u ^ I 4I !  t = l 6 M~|||H|~w1bTGu*.=PbWw:h!1KfTJ 7DPkEJ. Id^#K%:O~fN{`4 .<`K9Yfp}lN1ybK8#           0CZq Bg 5`#Y@~I}wp!jjd^WJSOI*EsB> :W640N+'#^# U AD5*8]&J N % b  D x " \ Q'Sx!)4>IU`jw  (.59;95*  1@PaptL%U,   *x 9E I X g w[    ?   V   j  %-28@IHOW^UdlrVyJ<0-0{u8lf^CUOGP<2'b 6e"oZdC',yA|ia7D$W0 `>eI.vU1}Zr4cUJ>5~-]';"b D%%'+15xyT2~cJ3uf\QKEB@@BGKSYdny $,4A K X9dUqp~Ag- D6``{Fv5XzG~':bZ{J$ 2J}fbO:#{ .Lnt%_M8R#H Oq^Ki82&c3|\g6R?(kTA. t`H4u^G0(?Vo~e J0/W1c}fM 6G S/zmXEb2UPV h ~:Ul'? Q"9R]iZK )G1hz Q-_ ] 6 qH | ! Y 2 \ / a ' 0B h[ t  a 6   W    \    : p } h S H< #   0 m  j G W!    " NZ x1    { 8J ^ }I : Y { p 9    Y ! ( 7 uF =R ] i v R    h -   ~ C    ] $ ~ q {c BV F 5 $ h 1 \ ( l S ]: - l>{X4^4 ~Y3 g@tK#fD#wK!srXF?&lB|iiY=J9- _ 3Y.W+{O# +p9DHYl~b6yI2KeY(@fd4k&9Pzl9(Vp> BtzL ;mg<:oqFM}'%\mT5=i&2b%UDr  9ETkq44dSp5n(\=Pc%tn aq2[Bc&Y.~p a|RA^1> K wh]D+x*6  m R? 4  :    a e H ( Z   2ldM+ "LtmN. &9GTn^Ng/m sx||~p|Qz2uoeXJ7v"Y :hBhK.uI g\ L( 1   D  {E d M 6z 5  a  Cs^Ie6$4I[ n|ti4aYPJJF@b;97x5+779G;=@eDHLR>W]egnvN @|;.|?>RdyKg0!Sj0Ol'Nx55iNgO] A.=K{9zK'r V:!n YRV ^ *a5?JXVamBzg= Y  2 G* Zm o , d  1 #[ : S l  9 X v  0 M l .:1CRIrMMKE> 8C.g#   B f  x Z 9  ; _  n @   0 Ry sE    o 7  8 Q hM  Gt*$3AMNYaog$kprFttrhpkgaA[RHc;/ <h#lVO1Tdd?+Ti!9 cw7D sp=O-a'yo>XE2Sf*zA]'MR"l@yV*44=GR\golyWB/ )4>KUblw"5J_t"54HTYun 2[ $? Z7we!R4U{K?iTO,}b <6jj':Wn $>[r=;ukU'SJv+T|Em;^>h%Db(He-?Rev(2=EKTX\^^\XQ#I&?(4(((( &#! p]H1nOv-cR?-sV8{bH-gH&dyGU&4_w9Z?$[4 eJ/mCtJjU@+nB_1pa{UMF:-#g ; W)uIpD}wqwmOf)`\VOIoCN=*4 .& pR7lz\kK[>L09%(pY @)%0`2rByDs?ym`TcE-6( Mj1t[OD*t=hdK--RyZv;@ l8pN+q?{Y6W)`^=8au;ZA(}W2 pJ#|zxxzT|*V*{O9!Vsd4)UvF >pW%I`0<}rLD(sb 6U 7iE fQz]<@'-|gIys"ogjjj4owsy>}7r"BKe} 1 .Y Z  M/ J e ~ - i 4 ~  f  ]   V  K 9 , }v ] )C ( 4 J h B ^ hq C]?R`O7sX;% f T   N n 4   : Nd    i 3+ O t U   * O? T e v V ( t H   Y 4  s c kR M= 0&  } [ p: [ H 5 $  d <  c 3  j 6 \#z?U`$e&+9fJ%Yizg&g'f*%?Vkf%b#-cF$b{f'k ,;Vrr3y<,GbI}[ )Du_:}\&'@UW"n`2$;ZP3e zfH/ ,=KZiw}}!'/-N4p:@DK M=QmUY^ `Gdfh hNjjh.h~fd!bu^[ WvSO&KG@6:4-W'!b?nEym^KPA0y"BuDvzg=WD1O   F # f }- jn Y I 8( 'e   Ew BaxlaWMD:1) #$( *,*(" r U3#)1}8U@,HQ Y dv lC v l 1 y 8 q ,  ' 4Y @ MWd:p{[t';JY iz+@Y u * Lw/g$ew(hYKu::+ Z$]-xfQ>})S+oL*y fQ?,zaH1vk_yRlHb;W1O(G@:4 0.,)),.26/q!d.:G\S^j]uiw$zmM e2 w F    L  " $ $* 'Z ) ) + - / 18 3U 5r 7 ; > @ D F J L3 PC UR Ya ]k cq gx nz tx zs m e Z N A 1         l L (/ 4 C R ` o} S *    o ?    #n 28 B Q`n\}#v9B +?5@HzP7Y_erk0ptxm|*~g'|fx'rken[1RF;}-E  e/]{-dK2qEezEW$3rNu)Y>% d<noB`TE;.m$C rHwM%dAvW7 nS&:,#29AGPX`iqy~qg^TNGA=;9779/=@ASGfNyV^is3Nk6M,fPs65`WxF x2ZG{'SQ 9#iY.5^n")`[S'\7k-c*X4g12]b $5R_ ; g(?Viy>h Aa6Qm w b# M1 8> !H S ] f n v } k N 1      j Fy #p h _ U J g> ?/   zP({bG`,8urPN*(nbH8$ Ts$Q0[&}aKF+b(r5mXE}2> @{:v5xppi1c]VqR2NJHvF9DA??G? =??`?*?AADWF$HHJLhNL+HD?95/&   '9Nc|yj[O@91^#2b/e{qdTXMC8[.&+r M/{eVJ(2:?KZ+kz{gQ'7@Wp\)j3T&xcI4\ H v  > a  9 Z z  # G h  0 "? HM pX ` f m o "q Ao \m yf ` V K A 2 #  4 K b y   t X ;   $ 5 F Wp cJ r% ~V*xH]+$*0i68;AEIrPBTX\^}`MdggiiZk*kkkknk@kmmmkYk.iigdbS`)\XTPIXE.?82,$a9 yS- yV2~pcTFe5D&$jM2{hS>+ybK4w^E,~pcYnNPF3>71-)$u"S"2""$)+1]78@JUaps~K!vJ ";Voj>+VO(rk=;eU'GwuK:"l;[p5G}nQ!6Y6nJukc\"XVVTVX#^UemzHv*#T@~b<`>gR7Rk2p1r=#.8CHIOVZT\\\#\kZVQDME=!4l*Jb%dr[D-WAynO#1Y&VoK**OuxR/  < Y ut O )     m G$ "5 C R _ i et B~  j G # t S 1| q e Z N ? q3 Q$ 4  e Ht -[ @ % t[oBM+, |V1~ iVC0lB k?xYn+cYNFn=@5/&"~N  W$ ^ + d 1&-5=fF4P]gtg5j8m!86K`up= wD! )  h G (  v N (   (Y 4- C Q`qsCv? #f6/H[nPi/{!>2@O^Il yR^j+u8  H  ]#yA e/^)}n`bQ2@0zL yQ)vdQ<)oN, zu_dFQ/A0{shbv\gU[SNQAQ7U-W"^dl w7Wv0ZK "-*i3=H*Rm_ivB"p ^S&4PEVhTy_n$)7:J]>p=2!p!2 BVSdu4{ D 3 i  + ; L( ]Q ny ~    ) F c }    0 A R b s          # 4 G W h {} h O 5      u -O =* N a r  Z 1    y H  &{2G=IT^gi-qyF ^$t9K{sXi^RCi6-&Gh~1eJ-\(n[K*%n@b;mEa3ygIF&U#y`G^/,g7wsFgZNC9b.6&  iD pQ2q\G 4"&.7=ENX`ku +>Qd$w7I^s(B ]%vDb * K/mTzFElo;Kgw3Mc}&@Xr:Ql >Iry G>|nM.\@n@lGq=e8]$Gi ; T)kFb} "7J [k||gT?(tW:{v\g;YH9&zY7nWn>M'+ imIP*2 |taRF1- [6ybI2uN&Wx+fUD3#S%tF`u2k^TIz?L4* f8 X,~T+z`t8kc]TLF\=;5-"eL3uftWhK[>Q4D+6%)#)08ByMmY`hRwE8.! /LnEoKyH~*dW!4VEZm^)l<:Yy P" Fek0p,V5}t.+kWU4`/c/W#~Oy E m8 W y   ) K n  * = P _ m 5z L c x           (| 2o =c CV KH P7 T& V X Z Z X X V Rn PQ K3 G C=82*s$O,mFwM!~rg]oPCF;/"] /p@P}rh`[U)MD<2d)4!n< wENyq[i+^VKCo9?.$ Y-U+|nea?RD5' nN/nu\`IK46!# {dM6mQ8#6Kx`]y?" /RpvQ4Am~`C'&Y+cz]B(M F}fFQ<)IQ^)l~yw2wswwy4~r&cG2SIb{Ak -Np,Mo0\ ) > >Q la p  * [  K {  D x v j G[ {J : '  Br({T\?)Q{tP*@ed:.Kbi6 W+4H`utGg9 *_53A JT]gfp>x}W3`?iN1ztkchYQP:F#9- wgXIt;`,K6qT8|Y7~zxvvt[t6ttvx|o~El@W)j: (6sECTdsxDwD%8wKE]rzH "S9#Rig; &]=5Q ksM+ -F_xqV=& #:Qhz z"z9Pg~,A9VTks~+W':LKYj{,g!d/v  V&/@7=F1LRW#[u_acfeegUgecDa_]7YTN%HuB93[+ 4 w>}/iudCSuB0 / Y      * mH Xa Cz 0         t _ L 7! "# # !    y h W G 8 '  v a L 5   a xD n# f ]WOHy@V:23 /)%!vP* b8b4T&n@X(i9 yIW)k: P"j{U0 q^vIQ4+ sM*rW;zV5fG%pO/xS/ w\?u$Q,tnNT*=$ tQ- {hWGb6C%$v]D+ysmiwbf`W\IZ"'_-ydf0VC2!d1`._*zpe[bP/H=5-m$=  T&{Q)kI&nR7}ytpnwjhh\dObE]:[2W+U%Q!OKFB@<8#6'1./6-@)K'W%d#s! ;WvCk!%>)l-48>-DaMS[d6lowU HA 3H]BrG  L!8QkPM3QBp~.i )G dBt 7e-Jg8`2K g) D _ y      ) : K [ j {" * / 3 5 5 3 1 , ( "           y d M 3  kK*xR-wnff<[SKB8g0='_3}O#k=Y+wKl@f=~|iw?usomktgMe%`\XTNdI?C=4.&eB  {[>tcRuB\/A( w|biIY2J;-  fJ/fI, vX 9)9J]pfF) 4T{s`E*%Muzc"LN7| ?qF}wj`(UaKB:4M-)%#>!{!#%2'n-4:'BeMYfrX D(_5Ng4g&+IYo/6T`z 5!a?ZsEu 8 j! - 8 @ 2F dM Q S U 'U US Q M H @ 98 e/ %   <f(wN`rG..Idg~H&{W)4:KYfryR,g=uK#X0gy@ndYOD{8S+.nH#skbGP#?,vR1kWlBM--{^wC`&I 2t[Dk/R7z_nB`'Q B6)y\<hJ+ mM, mL#-2 >M[lpQ45RopXA*$KsrH_tJ7$$P|2`pdUFGt8+!# O{"Lv Ku@f!92[BzUj.Id~3Pp!)I8qHWdp{M{ 9i0b1f:p{pFdzWK<-Ew 4`oX9Aa*CdtY= +DYnnO2sR2 "*39p=PA1DFHHFDpAQ=293-&} _B%}dIr0bQ@/ t_J5"q\E0yj]QzDg8T-@#+nU<% oV=$pP1 %-8yBYO<[httQ-oI #&/9eD?P[ivY4 sK& pN+& .6AKVfbGm)w kT=()6x@rMlWgacjata}acglrx.<K7WPfisBh /)Y9HYg x8i-b=v*9#E^R\i uD}%^ B|*eI & [    $ T 4]?a,?O`|os{i^VKA7," {odXK=.~t lcYPH@7i/N)1  jM/iEa;}w`p:jb\SM~GV>.82+'!iD `:_:{pddWAJ>1#xX7{dmH^+O?0w`G2r]J7$rcTF9-  p`O>/~~~ ~ +5BN[gv+:*K?[Tli~ 9)R@kYp# ?(ZFua~ 'F,fIf:#WBud"2@U]yx"Fg7Pi7X| 4I#[Bnd5R p&3@LYcp2zEXiy  {kXE0|tt[i@_&R H;/"hK-pe^GK,8#lR7|bK2u`Kr6U!9lO0paSD8)xY8qO. gH}&wqhb\VpOSI8C=62,&!uZ?$ r]J5$|tkc}[pPfH[=Q3K(B>:86668:<@DIMSW`wflnbyYOF<4+# -BYn2Pm4W{ 3'X4~>KWdrCk>h1Jc@|lFp8TqGq -QrBl @1bW| '0HRgs0-PHod4 K"b7yJ[k| -=L[gt~ziYH5|"t i_RH;/"fK-uV4{jYI6%]7pIo`wRNA$2$zN$yM!zncpWDLB7-"kA tN&hD{sj`WiMEE!:0%|]@"nY{Dn-aUF:+o^PA4(udVE6(rcT F7**4CR`q ##DXKOSY'][djpw+b5i ?u-G9{HVevDt.\.C/XWm3Tt-B[r,AViy6Oh+D[t2I`uq^K8# )<Mt`Vp9tQ- o$G/7=FL|RRY(]cgk}nQr'rtttwrKpnkgepaD]YTNJlD@=71("nDyQ,tP{/n `SG8+`>gI.ueTC2"r]H3  xeUB/{l ^QD:/'s`M 8%jU@+#-m:TI=U&dpp[F1/F]t}fO84!T q-Omr\I8&(Px?fvi_T/JWB91+$%Oy $ N x  Ci"+3=H'RKapn| Ba,E`{0Kd~4Uy# 41DXSbn{#O{1_Ky5cKyynbUH+:W+ $LroZ!CA,`g4LH3[nnQ4bE(pR3yhW}F`4B!%vYs>Z!C*{`Ep*R7|epPS96$ kP}2hUB/ v]B) ylqQg6^TKC;0(!t]F /kQ:! !k&V*?.(28?GPXdor{]H1%o4\BKS;b(r 5H]zrpg_YRNHD@4=K;b9y999;=B F#J:PQWh_gpz #<Ul!4I^s1H_v!:Wr&;Pe y(Hg0)T:uK[l}'JnBf&19B7JYRzYagkr vAz`|~0Kf~zvrng(c=[RTeNzF;3(  *4=EMTrZd^SdBi2kmoooommigub`\NX9R$KE;2(zeP9$payNd=O+:%p[xIf4SB / qZA(sdXMA|6e*N7" hQ8!|xhtQpH Q[&f4rA}O^m} $-3@DSRfcxt.B&Y8nK^q-BW6lMd}  #0<CUVngw )D_z-8DQ9[Tfmp{ !:Sj "7L_r $*046888640*w$nh` WOG<4)! |iTB+ymj`OT6E9,uX; zln[NJ19)jO4}jWE2nW@)t_J8#ykZK=.{dM4v_H3 |xtpkge{af_Q]<['XVTTRPNNLwLiJXJKH=H0H$HH HHHHHHHHHHFFFDDDDDDDDDDDFFHHHJJJLLLNNPR.T?VP[`]saegkrvz6Qj3Rp0Q(s4AM\huBf:^!3F Y1lUv"Cb.@Qdw!@^{/"D;WTln~ 2E"X0i?yN\ky#)-16 8<<>>>!<#:%6%1%-%)###!{mZI6$|siv^]TFG+=2(lO2yZ9|tlapYLP+H>5-'{W4dBoK(|[9}yslf`fYHS-ME>6.%iM 2p_N=/rf[M@3% }yupnnqnbnTnGp8r*uw y}xkaTJ?5"*5 FY k~2Kd )Ff&JkCh#Hp  (01U;}DNXcp@|g&Kq!0)AMOp`q;[|'<Q,fG{b{ #:1OFfY{j{5Le| 2I^u  4GYl{jYF4!  &1;FPYkcPi6rx~nN/jI%ztne]uRRJ.@5(vR-uO{+fS>)rO)wu^TG0.iJ~*e L3nQ1hO6u\E.xaJ3 p[H5$yfTC0{unxhkb_^RWFU9Q/O"OOQSUY`djry 1}B{Wyiw~wtrpnl l&j?jZhuhjjll n)rHtjy{7[=d/Y' Q{(3="JLTvamzEo6^*=Obu;]$A1`H{_v- D%Y>lYu+F_ z"&(*2-K-e*($"%:QdytbO:&%3@LYckt|gK0cD$`>xpg]RFo;K/( xU1 lY\G82 hF%u`K4 `A!pg[JF-1nU<%lYG4#s`K8&rfWH<-|ri_WNF@93-{(o$d"Z M C 6 ,"$&+/37=DHNW]en~xti_TH=3&*=Pdw #:{Srlld]WQK F&BD>a:|841///./M/k/1468<#@BD_HOU[dlt:}Ww/Ll /?Pc0vKg00GG^[ur #:S l1@N]kz8Ql 9Rl $9Pey):K[jyxnaTH9- "(/5;}@lD[FIJ6L#NNPPNNLJHuD`@K;97$1-$ |gR;'rd}ShDS4<#'~niYRF=1& t]sFb/O=,lS<# xi]NA{3d&M3 {fO:&}wpjd]YvSeMTHDD3>$:841/--++--//1w4p6h8`:Y>S@OBHDDH@M>Q@DHOSY`fnw  *7DP]ix"1?N_m~ ,=K\m}#4EVhy -@Sh{'8HYhx)>Qfy '4/BBOW\ih~u(;N^q "+5@HR[en-v:GS`lw &.7?ENV\ekqy{ndWK@4% ueTCu2k"`VI?2& p]J9'raP>+lYG4#ubQ>+p_O<+n_O@3%y k\M?0!{uohdx^kZaVXTNODM9K/I&GGE EEEEGGIIKMQTVZ\`bfkmquy{{wtpnlllllnprtw{}(3?LXer~(8I\m/DWl'<Qh}"#7-L8_BtMWanx .?P`q!0>M\jy%0:DOYb'j7rF{Uet $0;ENX`iou~}wnhbYQI@80~%wqibZTKC;0( ~qbVG9* |peYNBx5g+UD1 {fQ<{'ndYOB8.#xa J3s\E.}rj_UJ@|6e-P#9" yfSB/wmdZQIA8{0o(bVKA6,$  !*2=GT^kw)JW a)nIxh"Ba~ 4!R)o4>IQYdl2uM}f$;Pez '/7$@0F=NIWV_`gkpux~$,29~?uEmKbRXXK\?b2g&kquy~kWB-pW<#~yuokey^^XAP"GA7.&lL- lK)|n_Pf@D1% dE&}l\Kp:P)3nU<#r dSD6' s^K6${odZOEz:p2i(a[TPLFB@;997777;=BHLT[cnv$4EXk~/Hb{1Li4Qq +Jj %&E,d28?EMT"\Bdam~u}2Pm -G'`6yDSar1FYn~!4GYn $.8A)K@TUZl`gkqswy{{0~G{\{qywuqmgb\TM2EB;S2d(ut cR@-"$&&(&&$w bK6 ybI0udS@0gL3s\dEK,0}iaPH7/}ldSK:4!}xfaOJ:3%ro`\MK::)*{o`tTiG];R.H$?5-$ &0=IVdq)>Sj  (3;(FDN]Xxep|6To#0B?_O`q6Uu)< O-dJvi7R.oBWl'@Yp 1DWi|  3H[n~(7ET`o|(2=GPX^dkoswy{{{{y#u's+o-i0d2\4V6M8C8;808&86 442-+'#r_ L9&lU@)ymbXK?m4T(;" pW;"~paRF7h)M2 x_D+{l^O@2#u\C*kxTl=](OB3' p]K8'sh^QG=0&~si`XPG?82,($|!v&r*m0i6e?aE_M]V[^XiVqV{TTTTVVX[]_ae%g8kKp]vpz/D[t4(K2d?}IVbo{1Mh 0%I1`@wMYht/F]r !+$44>EIVQgYudlu}%08@IQY`fnu{ $)-159>DHLPU[_ei{pwtpzjf^WOI@80% ym ^&R,E097,;AEKPTXZ^`begzili]iPiBi3g'ge b`^ZXTNIC=4u,f$YM@4% ~n_N>x-na WM@6)ubM:%vwaoOf<\)TKA80& o`TE8*|xvrpmkiigeeccaaaccegikmptvz|~ #.6?GQZbmu} #,4=GOZf q{!)/8>DMSY_flrx%1>JWdp'4BO^jy %)04 :>)E5KBONU[\gbthns{  *2=ENV^gm u| '-5;BHNU[agntz|uoibZTKC;2*"|vpic]WNHB93+v$i_R H;1$ }p{duUlIf<`.Y!SMG@<60+%!}p aUF8+wk^QE8,}|xttkncj[fT_NYHUAO=H9B5>18-1*+&%$  "&*15;AH{LuRoXh_be^mXtT|MIEA=842.,*(&##!(!4!AM!Z!f!s##&(*,.048: ?C)I8MFTUXd^rdkqw}+:GUdp#+3>FO Ya$j1t>}HUalx '2:E OYd&n,y4;AGNTZ^eiosw | -7DN[gr~ $.;EPZeoy|wqk e^XRKE?92,$  |pcwWiJ\>N/=".zpe^PM;:')u^Gj0WB-v_H1{hVA.oZG2 p_L;* xi]NA7* { pf[QH@8/'!  #)/6 >DO&W/b9lAwLVakx (9HXk |!.:GT`my*?Th}+B[)r3@JWdp{.G^u3Lc)z6BO\hu2I^s"1+>>LQ[bgrv &"30==HKRX[gcskrx~ '06>DKQU[|`vbnfeh]jTlLlBn7n-l ljfd`[UOIB:w2d)Q!>+ mV?u&eTC0  x_D+p[F1pU:u}`aKF8+#sX?t#a O>+ v_H1ufZMtAb6Q*>+ yog^VPIC?~;z6v4t2p0k0i0e0c0a2]4[6X;V?TCRGPMNTLZLbLkJuJJJJJJJJLLL NN+PO^l{$5HYl|   ,;"I&V+e-s/133331/-($  %+06:>BGIMOQQQwSjS[QOQ@O4O%MIGB@<62+'!wgV C2  |iW~Dq1eX K=0"p^K8'xgWF3"n[H6#p^K8%wfVE4#}jWF3!xi]NA{3k&XG 6&zk{]rPjDd5[(UOHD>:64/--+++++-/148:>BHMSY`hpy *; L]$m1~?N]m~#8Mb y0CVk})>Sj#8Odx.E\s+@Sfw-@Rex-;J Wc,p;|KZiw %-6<DKQ W"[$b$f&j&n&r&w&y&{$$$"  }ywu p lhd`YUOI@:2+#~qeVG9, ~|xlr[lJg9a'[RLF@71+"sb O<)ta{Qn>d-WK @4'sbQC4#th[OB8+xkaVLA9/& }wohb\XQMGCA=8640..,,,,,..0246:=AE GKO(V3Z=^HdRh_oiut{&6GXk{ !'/6'<8BHH[OlSY_dhnrv{ .>O`p -9FR]it~  """"""   %+28@GMU^fnw|vng_Y PJ B)913;+D"LU] ent|ysld^WQIB<60)# ztlc[ULD;3)  ynf}^{S{Kx@v8v.t%trp pnljhfda][YWUSQOJ{HrFlDdB[>SFLR Y_el p$v)|/37>BFJPUY_cglpvz~~vpg_WNF;3) xpe[yRjH^>Q1B'6' xujf[WMI>:/+!{ulh[\MO>C/6!,sf\OE8.~#ztpkgca][XVTTTTTVX[_aeimrv| !,8COZfq}+8#D*Q0]8j?vGMV^dms{+6BMWdny )3>HS_jv )19DLU_g#p2x@O^n}$5FYi z$*07=AG(N;RKX\\m`~egkmqsuwy|~+6BMWblu~|wuqokgb^ZVRKE?92*$ yndYOB6) |pcWHs;`/K 9$t]Fu-dUE4#pW@'p_Q@n/W@+yoh\XII6:#, teXvLiA_5R(F;1 & $ /;H&R1_;mHzR_iv ,?O`s,=M\m}-BUh}+>Oat 4G\p 0@Sfy "5H]p -@Par&7EVeu*7ER^kw'2<GQYbjry !#%''')'''%#! yrh`WMB8-! wk`TIw=g0V$E2 "varLc7U"F 7) u`I2ufWI:)lU@){ftQh=Y(M>1% |kXH7&uh^TI?4,}!rh`UMD<4-'! ~z v rmkig%e+c1a8_@_H_Q_[_f_p_}accgikptvz$7J[m*AXo#0:GQ/^Fk_wv !:Qj '6DQ_n}3H]r ).6=BNO\\khwu  #$)--30;4B6J8P:W<]<c<i<p<v<z:8640+'# uk`TI?2(vg[L@3$ uhYM>2% xrpfe[]ORBH6>+3)sdyWoIf:^+VK C:2,#tdUF8) wk`TI=2*  !*2:CMV`hs}*2:EM+X8bDmQu]jv #'-48@BMMYWfapl}v )19B'H.P4W:_@eGlMrSxY~`djpu{  ~zv r"l$g'c)]+Y-U/N/J1D3@59737-9);">>@@ BBDDDDDDDBB@@>>;9975}3u1n-f+^)W$O"G>6.'  xpja[S}MwFp>j8d1`+Y%SMIB >82.)# {xvtpnlhfa_[YUQOJF D@<8%3-13-<)B%J!S[dlr{ '08@GOW^flu{%+18>DMS[djr{ }ys)n2j<fGbO^YYdUlQwMIE@>:842.+)'%# !)1;DNWait|!#%')+ .046$8(<,>0B4E9I=K?OCQESGWKYK^N`PdRfRjRlRpRsRwPyP{N}KIEC?;72.*$ znaUH{9y-usnjf`\WQKG@y:j4Y.I'8!' p_O>- xpjaYQsJfBX:I3=+0## |xrmiec_][XXVVVVXX[]_aegkpvz~#.8CKV`ku %+1:@HOW ]f#l-t8}BOYdnx %0'82B>KIUS^^hjpu{'1'>1H9RD_NiYta~lv~",4= ENV \&e,k0s7y;?CGKNRTXZ\\^^^^^\ZXVTRNIEA=92,& yqi`XPE;0&tgYL>/ rcRD5$sbQ@0 sbQ@0p_O<+ p_QB3w%hZK=.!wm`VKA6~,v!me]VPJD=951-(&$  "$(-15~9~=|D|JzPzVz]zezkztz|||~ &2?MZhw!/@Q!_*p0:CKT^fq{.<M\l{'3@M Yh$t1>JWcpz!0>M^l}$*07=$C5GDNRRaXr\`eimoqsuwy y|&|2|?|I|V|`|m|wyywwusomigb^ZVRNIC?92, &     xncYNB7- w mbVI=0"yl^QE8)p_P@/ }napS^FM8:+)}l[Js:f'ZOC6,{m`QC6(zrke]VPLFA=x9p5g1_/X-R*J(D&?&9$3$/$*$&$"& &(*/159=DJPV]ek"t$|(-15;AHNT]ckt |(6ETbq(6E'Q:`Jo]}n %)8:KJ\Ynj{ )9'J8YGiUxfu  *"4/?9IFTP\[eempux~ ~wqib ZRKC90(  ~reYL@3~'xp ia[ULF>7/) sdU G8) {l]O@1#ufZK{?s0j#bY QG<2'|tkc[TLF?v;n5d/Y*O&D"< 1) "(-17=DLR[cmv!0AQ`q /@Sfx !%!)2-E/U3h8y<>BFHMOSWY"]1_BdPf_hnl|nprtvx{ (07?EKRX^bgkosuwyy||||yywusqmkgb^ZTNIA;4,& xlaUJ>3'!'+28>EKwQlWb`UhKp@y4) { rjd ['U/O7H>BDBFJ OSW[_dhlptx}}xtrnjfa][WSOMHD@ >:83/-#)%')#+!046:<>B E IKOQUW\^`dfhjnpsuwy{}}{yw usppn%l)j/h3f:d@dFbM`U^[\d\jYrW{WUUSSQQOOOMMMMKKKK KK!K.K8MBMOMYObOlQuQ}QSSUUWWYY\^^`bddf$h/h9jBlJlPnYn_peplsrsxsuuuwwwwwwwwwwuusspnljhfdb`\YWSQMIE@<840)%zriaYPH{@r7l-f$_W QJD>81+% uh^QG:0# rh[QD:-# }umd\VME ?60*!!'-18 >DJQW]djpv #'.26<@EI MQUY^&b*d0h8l?pEsMwTyZ}bkqy'1>HU_lx)8EQ`l{  $3DRap ~"')+-/1357;>> @,B9DEFRH^HiJuJ~JJJJJJJHHFFDDB@>9751-)$  yoeZNC}7u*j `UK@6+! tcRB1 xlaUJ>y3j)YG6%}n_SwDo6d)\T KE=4.& wmbZQIA80(!  !(08?GQZbmu#!*-.:4H:UAdGpMTZbhou} %4BQ`l{ '/8B+J7SD]Pf]pixv#.&8.B4M=WCdInPyV\`ekosuy|~"-5@HR]gr|~|wuqmib^XTNGA;2 ,$" (.29=?CEEGGGEEzCpAc?W=J;;9/4"2.,(&" sdSE4%znrcaYQN@D19!-" sdTE6s(dW M@4)zpe[RH?v7l1a(W"MD:1 ' {ws$o-k5f=bF`P\XZcVmTxQOMKIIGGEEE EE.E=EMG^GqGIIKMOQTVX'Z:\O`advfkosuy}':Obw 3DUev !)/ 6<(D2J?QIYV_^hinsv|}#)28@GMS\bhnu{yqibXPG=4*"  |$r+e/[5N;BB7F+JNRUWY[]__acegi{nppdtYvOzB|8.! ~|zvtpnlixgnefc[aQ_F]>[3W)U!PLFB;5/)" yqhbZQKE=60*}#ujbY QG>6.%xrlfa[WQJF@<61+'# (.6 ?GOXbku}'3@MYf r !#%)+/+386E:S>`@lDyHJOSWY]_dhjn ptv){3}>HR[cnv~ztne]WNF>7/'  {s%j+`2W6O:G@>E6I.M%SW^ dls{xrjd]UOHB< 6/)# $)- 1355777777777777799777531/-)'" }wsnhb^WSMGB<82 .)##+18> FMU[djrx #+{4v:rBlKhQdY_`[hUnQwM}HB>:6/+'!   "')+-/13557799999}7{7y7w5u3s3q1o/m-m)k'k$h hhhhh h kkmoqsuw{}{unhb\SMG@#:+46.@'J#S]hr  )6EQ^jw $3BN[gr~ $&(*,,.. . . .......,,*(&$    zpg]RH>5+  {n{dvYpMlBh8d.]#YU QMJFB><831-+'%x#nf[QF>3)!{sm!f%`'Z+T-O1I3C8?<8@4D.H*M&Q!UY]ah l rv}%) 06:@EK#O*S.Y2^8d?hElIsOwX{^dms{)3@MYfr   "'$4)B+Q/`1n579>@BFHJLNP R-U9WDYPY][g]t]____aaaa___]]&[0Y9W?UERNPTLZJ^FeDk@q;w7~3/)$ ujbUK~@w6o+i`XNE;2( }pdYMB6+teWH9+ yq{hl`^XOQ>I0C:4.(! }naSF8+wmdZQIA8 0(!( .4=CIQZ`hq{ !+8BO[ht !.:GS` ly!(.4:AGMV\d ms {+3>FPYaitz )3>HU_jv+:GUbn{"1>L[gv~xr$i,c7]AUINTF\>e7k/q'w| yndYOE~:w0q%ke\TKC=4,$xnaWMB6+!xl ]NB3' {sh{`jX\MKE<=.4,# {naUH LYgv%+16<BFMSW]djn$t,{4=EKRX^ekouy~!'.4~:yBuIqOmWi^bf^lXuR{KE?90*"   z'p-e1[5P9F>9B/D$HJ NRW[_cgnrvz|wj^SG:0# ~||zzxxxvttrprlfi[eOaD]8W-R!LH B>71-'" }uk`XME:2*!wphbYSKB:4+#{vrplhd_]YWS!Q,M6JAHKFVD`Bm@y><:88633111 //)/8-F-U-d-t-----////1 11+3<3K3\6j6y88::<<>>>@ @B$B1D@FLFYHeHpJ|JJMMOOOOQQSSSUUU UUU W$W(W,W0W4W9W;W=W?WAWAWCYCYCYCYCYAYAY?Y=Y;[9[4[2[.[*[&]"]]__ aaddfhjjlnprtvx{}|ti_WLB7-"}sh`UK@8%.+%28>EKOU\`flsy}tnh_YSMF@:3-'#   $)+/1355799;>>@@BBDDDDDBB@>>;97531/-+)'$"  {unhd#^'Y-S3O8I>BB>H8M4S.Y)]#dhnrx !'.48>{EvKrQpUl\hbffal]sYwW}SOMHD@>:61-)%#    }ywusqom m k kkkhkkkmmoqsuwy}{wp lfb'^/W<<::8866633w3l3`3U1K1@161)333 3668::<>@BDFHJxOnQfS[WQYF]>a3d)h!lptx}{skd\VMGA82, &# )04:@EKOUY`djnsw} &.6AIT^hu!1@O]l} 0@Qdu '5DUcr ",7?IRZbks|{wsnjfb\WQMGB<60)#woi`XPG?7,$xph_WOH@8|/p)c!UH9 -p`QB4%}ywsqmk{hlf]dQbBb6`)``^^```bbdfhkmo{qqufy^{VKC:2,# #-6>HQ[dnv#.8BMWblu !(.6=C KQZ$b-h3q;yDJRY_gntz#/:FS]jv %2@O\jw-;HWcp||vpga[RJ&D.;93A+G"PV^ eiosw|~}sh^SG<0%~yuqkg`ZTNGAx9l2a*U"J>3'|reYL@y1o$f^ VME=4.&{ l^QB4' xl_SF:-# {uoh b^X#T,O4I=GECM?V:`8k6s2}0..,***((((* **',3,B.Q0]2l4{68:=ACGIMO TX)\8^GbWffkuosw{-9HUanx%$+*1064<;B?HEOIUK[PdTjVpXvZ}\^^````^^\ZXVTPNIEA=72),2(:"EMU`hs{~vla WL B)71-9"@H NW]cgnrx|wlbUK@6+! }rj_UMB:/'z vpic]UNHB93-$ysmd^XQKE?:4.*#}unf^ UME<4+# xtnjf_ [WUQM&H,F2B8@?>G:O8V6^3f1o/y-+))''%%%%####%%'%3%@%M'Y'f)t))+--/11368 8:%<4>B@OB^BlD{FHJMMOQSSUW YY$[1];]H_Ua_aidtd~ffhhhjjjllllllnnnn nnnnn n"n$n&n(n*n,n,n,n.n.n,n,n,n*p(p&p$p"p rrttt vvx{{}xpg_WND;1)   %{+s2h8^<UBKGBM8Q0U%\`d hlsw{{tld[SJB:3+#{wsomhdb`\ZXVTQOOMKKKIIIIIKKMMOQTVXZ\^bdhmosw}{yuplhfb^YUS OKG)E3@><H:Q6[2f0p+{'#! !+6>IS^fp{ '-5;BH}NxUtYp_lchidn_r[vWzS~OHD@<61-'# |xtpnic_[WPLF@;5/)" }ulf^UOG> 60'!)1<DOYdnxx%r0l:fGaQ[^WhQuMFB>:3/+'#!   '-5>FNW_entz !#%)+-/138:<>@BFHMQSWYz]vapdifcj_lYnRpLrFt@t9v1x+{$ {sjbWOG>6+#  xph_#W'O+F.>266-:%<@E IMQUY^bfjnpuy}}wqhb\VOIC=82,(!  &,2:CKT\doy{yup#n/j>hJdYbf^t\WUQOMIGE@><.8>6O4^0l.}+'%#! '5 B P_lx&,29?EKPTX\`beggiiiiiiiiggeb`^ZXTPKG}Ax=v7r0p*l$jfa_[WSOJFB><831/+)'v%l#aUJ>3'  }pdWK>2%  } rf[OD:/#%'+/16<@DHOUY_flrx{uof`ZTOIC?840,&! % +2:@GOU\bjpw} #(,2 6 =AGMTZ`f o u"}$''))++----////---)-6-@+M+Y+d)p)}'$$" )6 B Q^ly+5BNYcnx}yslfb \UOI"B&:*4..0'479; =?ACEEEEEECCA?;940,($xrjd [UOF@:1+% ~tlaWL@5+  sh\OE8}.{!{y wwwwwwwwyy{}}rh]UJB8/'#+3<}D{MyUw]ufspqxoommkkkkkkkkmmmo oq!s)s4u>wGyQ{\}dny $+3;BJPY_elrx~ %)/6<BHOU[ahnv} )2:EMW`hs~{xrle_WPJB93+"  ")/7>DJNU[_ciunjtbxW|MB:0%tlaYQF>6-~%ztp le_[UNHB;5-'  {uqmhd`\XTOMI{EsCj?b=Y8Q6I4@2800.).!,,, ,,,,,,...0022468:?AEIM{QvVrZl^hbdh_m[qWwS}QMHFB@>:86311/--++)))%'-'8'B'M'W)a)l)v)++--//113688:<%>2@>BIDUFbHlJyMOQSUWY[]_addfh$j/l9nDnNpYratlttv|xx{{}         xpg]ULD91'  !'{+p2h6^<S@IE>K4O)SWY ^bfhlpuw{}rjaYQJB:1)# }{wsqmkhdbb`^^\\ZZZZZZZZZZZZZ\\^^}`{bydyhwkuosqpupwn{ljhhfdb``^\YWUUSQOMMKIGGEB @@>#<+:38<8D6M4U2]0h.p.x+)'%%#! # +6@IS^fp{  '/5;BHLRY]aglpt}xx|rnjf_[WSMHD>:6/+'! ~zvtplgc_YUPJF@95/)$  w!p'h-b3Y@DFHJLNPRUWWYY[[[[[[[[[[YYYWWURRPNLJHDB@;9731-+'$   #'+/3:>BHMSW]ahlrv}yslf`YSMG@:4.'! #)06<BIMSY`djpu{xrlf_YSJD>81+%    }y u q m h f b ` \ZXVTQOMKKKII I I IKKMMOQTVZ\`dhmqu{ysnhb'^1W><<<<:::::<<<<<>>>>>>>>>>>>@@@~@zBtBnBeD_DYFRFLHDH>J7J/M)M MOO QQSSUUWYY[]__adfhwhnjfl\nSpKr@t8x.{%} {rjaYQH@8/)! !%+06:>EIOSW^}byfsjopkufyb}^ZVQMKGCA?:864200.,,*********,..0246:=?CGKOTX\`fmqw'1>HUalx+8GSbn{{yupnjfd`\YU)Q3M@KJGUB_>i:t6|20+'#       {vrlhd]YUQJFB>:83/z+r'i%a!YPH@7- $ ujbWME:0' }tld]UOF@81 +%# )-38>DJQW]djrx%.6>EMU^dls{ "'+/37;>BFH LNPRU#W)Y-[1]8_<_BaHaMcScYc_edejepevc}cccaa_]][YWURPLJHDB>97!3'/0+8'@"IQYbj py {sl"d)^-U3M7G;>@6F0H'LPRWY[]_aaccceeecccaa_]v]n[hW_UYRQNJLDH)9#3/+'  {unf`YSMG@:4.'! } {xvt#r)p/n6n>lDjJhShYfadhdpaxa___]]][[[[YYYYYYY YYY%Y.Y8Y@YIYQYYYbYjYsY{YYYY[[[[[[[[[[[[[[[ ]]]"])]/]5]9]@]F]J]P]U]Y]_]c]g]l]p]t]v_z_~____aaadddffhhjjllnprrtvx{}~zxtpnie_[WRLHB>71+$  #'.4:@EKQ{Ws\jbbhYlQsIw@}80'}vnh_YSJD>6/)# {yusnlhfb`\YUSOMKGEB@<:86420.+)'%#!  !'/6>DMU[dlt} '0:BKU^hp{ ")17>DJPW[aglpt}z{~vtpnlhfa_]YWUQOMHFDB@>:86311/-+))''%~%z#v#r#n#i#c#_#Y#U#N%H%D'>'7)1)++$-/13 68<>BDHMQUY]afjntx}}uld\SKB:2)#  #)06<BxIpOjUd\[bUfOlHsBw:{3/)#  !%+18<BHQW]djpx}yuplhb^YUOKG@#<+8228.@'G#OU\d jpw}xrlf_YS M F@:3-'! "$' )++-///111111111///--+)''$"   }wslhb^!W)S3MW8a4l.v)# #.8BOYdny{vt plh d'_/]5Y;UDSJONMUH[FaDe@i>p!9#3#/%)'$)+-/ 1368<>@BFHJOQUWY]_dfjlp{tsxl{f`WQKB<60'!  xrlf#_'Y+S2M6F:@>:B3I/M)Q#U\`dhlpuy#+1:BJS[dlt}yuplhb^YU QM!I)B4>>:I6S2^.h'p#{ $+17>DJNUY]aeilptvx|~}{vtpnjhfa_][YU~S|QzQxOvMrJpHnFiDgDcB_@[>W`@YBSBMDGF@H:J4M.M'O!QUWY[]adfjlprvx}{vplhd]YUQMFB>:61-)'# #' +06:>BGMQUY^bfjnsw{ !%)-38<BFMSW]djpv}'.6>GOW`hpy{yusnlhfb^\WSQMIE@>:6 2.)% !'+/35 9>@BFHJLLNPPRRRRRRRPPNLJHFD@>97}3x/t-p)j$f a]YU QMHD@<83/+)%! yslf^WQKE>82+% #'+/38<{@xDvHtOrSpWn]lajhjlhrfxd}da__]][[[YYWWWWUUUUUUUUUUU#U)U0U6U>UEUKUQUWU^WfWlWsWyWYYYY[[[]]]__aaadddffhhjjlln nprrttv"x$x'{)}+}//1357799;;;;;;;;;;99775531/-+)'$    #'+048<@EIMQUyYs\j`dd^hWjQnIsBu<y6}.'! {tnha[SOHB<6/+% }{wuspljhfd`^\YWUSOMKIGEBB@><:8864220..++))''%%###!!! #)/3:@DJQW]dhnt{ %+2:@GOU\bhpw} }xvtp"n$j'h)f+a-_/]1[3W3U5S7Q7O7M9J9H9F9D9B9@9>7<7<7:5858361616/3-3+3)3'1$1"1133336 6 88:<<>@BDHJMQSWY]_dhlnrv}yunhb^WQKG@:4.)# !'.4:@GKQW^bhlsw}{vplha]YSOJF@<83/+'#  }y!w%u)p-n1j8h<842.+'#!  %+28@GMS\bhnu{{vtplhda]YWSQM JHDB@> <":'8)6+3-1//1-3+5+7)7'9%9%;#;!;!;;;;;;9975531/-)'$   !#%'+-/36:>@DHMQUY]dhl}rwvp}lf`YSOIB<60)#  !'.6<BKQW^flsy{tpjf_[UQMHB>:61-)%!  !%)-18<@FJOUY_djnt}{ywsplhfb^YUQMKGB@<862.+'# #).48>BIMSY^bhlpw{}vrnhd_YUQJFB<83/+'! }yu snjhd%`+^/Y6U{@xBvBvDtDrFrFpFpFnFnFlFlDjDjBhBh@h>f;f9f7d5d3d1a-a+a)a$a"aaaaaa adddddfffhhjjllnpprrttvxx{}}wslf`\UOKE>82.'! }xtnjfa ] YUSOJFB!@%<':)6.30/4-6):'<%@!BEIKMQSUY\^ ` d fhjnpsuwy{} !#%)+-/36:<@BFJMQUY[_dhlptx}}{ywuspnlhfdb`\YWUQOM#K)G.E4B8@><B:I8M4S2W0^+b)f%l#p!u{ }{xvtrppnljjhfddaa___]]]}]y]u]p[j[f[b[^[W[S[O[I[E]@]<]6]2_._)a%a!dffhj llnprtvx{{} !#').0268:>@BEIKMOQ}U}W}Y}\{^{`{bxdxfxhvjvlvnvptptstutwrwryr{r}r}rrrppppppppprrrrrrtttvvxx{{}}}}{{ywuusp nlljh#f'd.d2b6`:^@\EYIWMUQSUQYM^KbIfGjBn@s>w:{8620.)'#! }xtpnjfd_[YWSQ}M{JwHuFpDn@j>h)<):'6'4'2'.'+')'%'#'!)))++--// 1 3668:<>@BDHJMQSWY]_dhjnrtx} #'.28<@GKOUY`dhnsw{}}}}}}}}}}}}}}yunjd ^ YSMIB<8!2%+'')!.046 :<>BEGKMOSUWY^`bdfhlnpsuw{yv{p{l}fa]WSOJFB<861-)%! }}{ywuuspn l jhfdb`!^#\'Y+W/U3S8Qf<j:p6t4{20.+)'#!  !'+28<BIMSW^bhlpw{}{xvtpnljhfda_][YYWUSSQOMMJHHFFDDBBBBB@@@@BBBBBDDDFFHHJMOQQUWY[]_dfj{lwpsrnvjxf}b^YUQMIE@<840+'!  #)06<BGMSY`djpu{}xvrplhfd_]YWUSOMJHFD@><::86311/--+))'''%%%%%%%%%%'''))++--/13368:<>BDFJM}OySuWpYl]hadd`h\lWpStOxK}GB>:62.)%!  #).26<@EIMQUY^bfjnsw{{xtrpljfda][YWUQOMJHFDB@>><:8663311//-------------///113668:<>@BDFHMOQUW[]afhlptv{}ywsnlhd`\YUQMIE@<:62.)%!  %)048>BGMQUY^dhlpuy}{xtrpljhfd_][YWUSQQOMJJHHFFDDDBBBBBBBBBBBDDDFFHHJJMOQQSUW[]_adhjlprt{xw{upljfb`\YUQOKGB><840+'#!  !#'+026:<@BGIMOSUW\^`bdfhllnpsuwy}y{{x{v}trpnljjhfdaa_]][[YYWWWUUUUSSSSS}S}S{S{SySwSwUuUuUsUpWpWnYlYjYj[h]f]d_d_ba`d^d\fYhWjWlUlSnQpOrMtKvIxG{E}B@><:86420.+)''%#!  !#'+026:>BEIMQUW\`dhjnsuy}}yuplhd`\WSOKE@<840)%! }}}}} } }}}}}}}}}}}}}!#%%'))+..0224668::<>>@@BEEGIIKKMMOOQQSSUUWWYYY\\^^^````bbbbddddddddffffffffddddddbbbb`` `^^\\\Y!Y#W'W)U+S0S2Q4O8O:M<K@IBGEGIEKBM@Q>S<U:W8\8^6`4b0d.f+h)j'l%n!npsuuwy{ { }}}{{yywusspnlljhfdb`^^\Y}W{U{SxQvOvMtKtIrGrErBp@p<p:n8n6n4n4l2l0l.l+l)n'n%n#n!pprrttvvx{{}   !#%')+.02468:<>@BEGIKMOQQSUWYY\^`bbdfhhjllnppssuuwwyy{{}}}}{{ywwuuspnljjhfdb`^\YW S QOMKGEB>#<%:'6)4.00.2+4'8%:!<@BEIKM OSUWY^`bdfhlnpsuwy{}}{vtrpljhfda_][YWWUSSQQOMMMJJH{HyHwHuHsHnHlHjHfHdH`H^JYJWMSMQOMOIQGQBS@S<U8W6Y2Y.[)]'_#adhjln r tv{} %).26:>BGKOSW\}`}d}f}j{n{s{w{yx}xxxxxxxxxxxx{{{{{}}}}}}yuplhd`\WSO K GB>840!+#%'!+.268<>BEIMOSUY\`bfhlnpuwy}}xtpnjfa][WSQMJFDB><:831/--+)'%%##!!!}!{#y#w%s'p'l)j+h-d/b1^3\6W8U:Q>O@KBIFEJBM>Q:U8Y4[2_.d+h'l%p!t{  !%)04:>BIMQU\`dhlpuy}}}}{{{xxxvvvvvvvvvvvvvvvvxxx{{}}}{yuspljfdb^\WUQOKIEB><8620+)%#  !#'+0268<@BGIMOSUY\^bdfjlnsuwy{}}}{{{xxxvvvvvvtttvvvvvvvxxxx{{{}}}{yuspnlhfdb^\WUSOMIEB><842.+'#!  #%')+02468:<@BEGIKKMOQSS}U{WxYxYv\t^r^r`p`nbnbldldjfjfjfhhhhhhhhhjhjhjhjhjhjhlhlhlhljljljlllljnjnjpjrjrjthvhvhxh{f}ffdddbbb``^^\\YYWWUUSSQQOMMKIIGEEB@@><::864420.++)'%#!  !# % ')+.02244688:<>>@BBEGGIKKMOOQQSSUUWWY\\\^^``bbddfffhhhjjjjllllnnnnnnnnpppnnnnnnllljjjhhhffddb``^\YWUUSQOMKIEB@><:8420+)'#!  !#%%')++..0224466888:::<<<<<>>>>>>>><<<<<<::::::888666442200..++))''%%#!!       !##%%')+.02468:<>@@BEEGIIKMMOQQSSUWWYYY \ \ ^ ^ ^^`````````^^^^^^^^\\\\YYWWUUSSQQOMMKIGGEB@><<:886420.+))'%#!  !#%'))+.02468::<>>@BEGIKMOQQQSUWYY\^``bdddffhhjjllnnnppppsssssssssp p ppnnllljhhffdb`^!^#\#\#Y#W%U%Q'O'M)K)I+G+E.B.@0<0:262422404+4)4%4#6!6888::: <<>>>@@@BBBBBBEEEEGGGIIIIKKKKKKMMMMMMMMMMMMMMMMMMKKKK}I{I{IxGxGvGvEtEtBtBr@r@r>t>t>t<t:t:t8t6t4t4v2v0v.v.x+x){'{%}#!  #%').0266:<>BBEGKMOOQSUWY\\^`bdffhhjjllnnpsssuuuuuuwwwwwwwwwwwwwwwuuuussspppnnnlljjhffdbbb`^\\YWUSSQOMKIGGEB@>::8642..+)% # !   !#%'+..04688<>@BEGIKOOQSUWYY^`bdddfhjlnnnppssuuuwwwwwwwwwwuuuuuusspnnljj}h}h}f{d{b{`{^{\{Y{W{U{S{Q{O{K{I}G}E}@><8622.)'%!  !%').0468<@BEGKKOQSUW\^^`bffhjlnnpssuwwwyy{{}}}}}}}}}{{yywwuussspnlljhhfdb``^\YWUUSQMMKIGEB@<: :6420.))%!##!%')+.024 6 8::<>BBEGIIIKMOQQQSSUWWYYYY\\^^^`````````````````^^^^\\YYYWWUUUSSQQOMMM}K}I}I}G}E}E}B}B}@}>}<<:864420..++'%%#!  ##').2268:>@BEGIMMOQSUWY\\^`bbddfhhhhjjlllnnnnnnnnnlllljjjhhfffddb`^^^\YWWUSQOOMKIGEBB@<::84420.+)'%#!  !!###%%%%%''')))++)++++...00000002224446666666888:::<<<<<<<>>>>@@@@@@@@@@@@@@@@@@@@@@@>>><<::::88644420..+)''%#!!                         !!!!## % % % % % ' ' ) ) ) ) ))+++......00000022222222222222200000.-----**(((((&&$$"""   !!!!!!!!####%%%%%%%%%&&&&&&&&&&&(((((((((((((&&&&&&& & & & $ $ $ " """   " " "$$&&&(((**,,,,.00002222335555577799999999999;;9999999977777553333111/--+**''%#!!   ""$&))*,..01135778::===?@@@BBDDFFFGGGGGIIIKIIIIKKKKKJJJIIIIIIIIGGEEEECCCCA@@?><<998664420 0 / - - + )((%#!   !!##%%'')))+,,...00223333555778888;;;;;;;;;<<<<<<;;::::::886664443311//-,,**(''$"!!   "#&')+,,01134699:<==??AABBBDFEEEGGGGIIIIIIIHHHHHGGGEEEECCCBB@@@>>==;99885542200/-++**(&%%"!!           "$$&&'''))***,,..-////11111222222222222222222220000/////---+++**(((''%%###!!   ""$$$%%''''(((******++++++++++++++++++))))((((&&&&%%%%###"""                                        LIST@INFOISFTSony Sound Forge 7.0IENG ICRD 2004-08-23gajim-gajim-1.1.3/gajim/data/sounds/gc_message1.wav000066400000000000000000001742461345766322700221350ustar00rootroot00000000000000RIFFWAVEfmt DXdata0 ",6BN[g[PD8WvlSx 7iAR/LC&DbaB r$KrT72iN 1V|8#Io fkV`idgG#r_3Fwj!|A4o.Dr6M |*--'"BvlQ.>Sh$G}F n:HUbp[F1=^H?^Ni wFRqGWG~$h)|>_v.g vJIHHGd!Z0z?A|5/~O473-V}dJ;P 1}`bdegR<'gfTB1pKfiY * zY8zCByx>^ONk|  [  t >/\JT !XLR"F  d j42L0Wt[Ce6ymHK|PbtlV@g D& })A@4SQ{F>Qc BVk }X4t&+RJz ~`X[ $1=i<;EvCzn?nh4\';ADHLOv8^ :t,p ,=750,Ry_D*TM{U0 $cpk ;WRNJEdN9$4Yblu~>"?e#bM06WI<. Z$ke JEA@!0>L:(.ZmhQ: "  ?v S{=Dv0gzdv>F#Ny`=>a$!{V2]J\n.cR>b B&2>{3"FHHz6%01223:BIPjPC=HS^i: L%"0B"\ ;o`k ,7BN p BzK X'#;a6rdL&UQNJFa8\D~zuK!4FXkBIh\3:4M|(-^/rY )Lo*\%6>ELTcr-COZfrcTD5\C}D/_[W$ESPUB\3tF.{{T.LkpU:4"X zF:.#HxH@hTmv4 ,#VdrT5(X|0yJ]"A_ `  x;d+;p"N/y wJ[S.h65f+w *8Gy T 2Jby2~fEsFn'(B:]@<71+mrT5Y~HTFz (2<EOJD>9+tE}B`)NQKE' Ex~cPF@3zU0 V7X0:lwZRJA90(f a4Sr]wsplh8p@k41EYm_<}@Re Yht>H4 n1Mhcvn$]N>.n8(C;3+#V>PW:Uph_WO~ s((r{5l@"DT[I >Sh>'JJ` f8QjzbJ2nR6#|\<taN\iv!URf%ch'j,2x~~n.n:+C:L |1*Ln$< >p0r-^4|uZWIk-fzN}~32|6[td1Dh_0&7Ieh-R 7cM8" E~*>\yL &VoYC-;HVdr-Ck.u6*hPu,CZqJ nKMHC>9 x<T"vR.$ &Kp/h!`+Y\`cf(p$7:\v"qNm(Lx&0uw4sU7?GOWr%Eh9[/NntI`rbC,R/BNA 1XY*;zR^ hBMoZF W>9Bj{HY RD$MIEA=B90(h Ti~<<Quvj7;>BF4H$+k}n \:Y  )]x8wW7  @:xI&jEx@ ^%b<^Zzj 5_a9,n$` ^<1^ T?_~"/<JJJJJ@6+!n9HJv[mW@&XxW6@JT}Na7\Wqvc*g`YRKDtV>%x"cBd|6dB  zh/W!*4n {nbUHrtfm{uoic'"D,D]xhG7'KnT;Zu4(A[gt(^L&tr`\XSO0RL{R*XT_".9DP>+,x\zh WTQfz4d^XRL~cV6Ncx~cH-cB vU4yncuEx`JEuP }M]XRMHRF}f *V}PCxS6zk^R2k@! 2G\[ZZY axb| 7Jxvtqo_P@0x RB3$>iqyW_qtwz|>HYnXB-6Vgx!0(_@xk^QD6)Wd ]HZ4TGDDFpjS<%:fb`p2stN)i<qP..\1m#` 20.-+M1e~-?LUkn)B`o&TjE 08,5 2x:74~ U1 6[n4pj@. `.}B c@:Uq9d 6_wZ1 n }(~[x$m'p%>VtJ>z"w!w#Fhfdb`@ RY~,gErGB! p@X+BX^elrz,XSD$c2d/yw 0LU;JZVQLH%XXT* #v 3nH!`~sC~tfWBj: ` ]PYF4"%n:~J<962/L$\/^7xzz z:5pKS6K|8FPwq C;Jzzzyy8Ln>7RDvX[^beF&G~jVBYp&6V-=M]2Of5:]*i<Y tJxZ;dTaq36Md|m)KGrw"v!R +IbzmX2 p9LXPHA9Uph(!PUV8=- 3j_q\"Y_B&b :To <TDc,7x -=.oP2!&-4 'p|O'K#BXs^Ma e4Xajt}kYG5DIJ>h<HU?j4$vPFpYB*Z2[\8,azk\,qg]UME="iceJ07YF2 |\:qK(aRKrlf}dL j7Q +b:&?$[o[ ;v)~ dir,`7AT7(y?Pu\D,7"7e~ysF,>Pc+5qclo.LrT7La<:]ft:8`'|H%w=p+v U,sP. 4Me>r.r?M\jxM"Qtrh;y4l_vH6#@*laIdX49p& a6V`BRukEchlpu(A:3OkBJd$x#fbCR ]z;X *",>QcL5Q/$n#/Lyu/ 27d%D`RSTVW2 F~u ?z_D( LZ(PifIHwC-Lj4R5]8M^(X,U~\L )2:>|obUH;.L0y|~Z0BsBbFxFQ Py;d;}(|)j W2M=[$Y/} sA+0n*2;DLOXo*1~6nH!<.tc `&)-04nc]W\afkl1 3GQjK+}CGVetOK~0lu#fvH{<Q}x7?d|Vf`^[XVTrXPB~n^RE8,$n/@h\OB6VwlaVK"R7zjo 4G8_dBp\vl4+~&P@h-F` Ab&QJzlGIKprQV\af7` djv{_$">[4LQJnB(feis.(e(Mr6k6=Rm8J!-8DP VL(j ]zRd?4)j+'X tDL<^cG*2UxOg%}[ZZYXi?d>\!X,_d9H)Z?sZB*Vrb4d>g'<e~3QJf7J]p o"L:1(x*bm(\8B}=Hi;Lz@G>,`vX:}V.gRD6(0G^tbZSE8*=^qZB9*Ip:d>||Rneh6HAq2Le~:|bcb`^]PCl`Np8{C[s6NgQc!"n!>|V1K&2wbo4{'~*,}_~ d5| 4\~gPv-pu7$u{`= =n8{+anm=R\$,3579;"<WtGB!B^$5GXK>0#A$GjhB!/\<3h,{Rdg15GYk~/jyL *Fb*hDjLB8-#nM;(]hov~&Jo>{T.;)sNL&3TU|^WZ]XR4{vrm&O"o rbRAl8W0BTgD Dj&fK0Svp%L%`rdMgTQ]c8y;^.2<Fa|N#[3b:(4zaN<*(8$9,%,D[rJyVrR1>%$S.Am{~8e{yV4?JVa'c(8j;[z*pV&]+_,iJ*1a]0xPqM k-SrH xh `iM15SqCZ%c6gP9" ":QhG|2H_v\B(9@Q@VNA-WnJ%irX> l5xkj2xCp],X eqR3pf>?Sh|^-*(%"8C@=:7<#6CP\i RA~c_ZVR8@b`<*n9OAdK%\z9$ 8bHsP [PeD"5+BHM}8.(y|GN#kCejU}xtoj4B|5,&Ja2*#" ,:GUPqF,zgTGwl8l60*#|;*E8*3+ydV8hhijjBZ#\\\[[w:_pvg: X+R v#h8FS`n43JZGt,b/\IL6qo2uL95,Szh |>&wRZNXNS"+3<DW<w6WxyiY@ jG$q2 8d$-$wW6m[b=(z5BN[hr{T"@^djpv\A;&i(Z)hV_k/3HFtNCDPeE%&(*+Fb}->PaVLB7yX82,%BdZ D~|[ k\Pk[L<,i! 1DN|7D6w+3~D @w? -eQ['S~6r_M&t8GGNT[bF$kV'I^CT>v2pl+DPteVG826d5| d2_R&rT6ns |)?gT d2nLN2xqL#_4.(#p6HC$Jq 0?N\k^RE8" ,V &A6,"McO $L^-:4J{6(]b.#^pd f6 ,CQ C{6>^~mG!N>wb$0Hngv<\{"r `<aK*S|c@|\tY\:F25dCv8> JDy"N @% l0*[QyaL7dhknr:9.Ns|G~"DflS4!?`Y!r1lK)6CP]#ex(|%JnxY9o &)Ct tCDE&@5ChFV6>3V.~q^t62auV@%>2kgc/Q6/b8VtnJ%dpg.vj^RvNN~z^B& 4OcxtU6]3X&vfMKJHFv1Jc'L6XDZfi(exVQLZ"l0zP v2CuE|b2;lc.a.o~2\.l $L3_Cqi4(Y`'|Q7A Nha `,)]6p@p|X6nzk$N.:gG'8HYjIEkbA! #6>FOWL@4) nM, /dD2bzKtlToqsuw WgN4| RH>5+hdL3G&>U>(1wC)vT2jb&nW^v)Vt 4DD5|d-?u 4h/qg]dka^" \:l5(XA H)JB:1){T.  tcRW\bg>oDTcrgL1Sv)e*M|BsJJ`NMKGporvy|=,Y ]s(1@BLK3C;Py_E?9z=DDA`~DTZ0fP!eL`j>e#>Pa c#8ln;JZ-)x6oqKVrzS-,tM{5" *Ln9}C/6<CJ.f>y{~ @b ,  vHB\F0%EekliF]tuF"[jz$v D5%(=0gzh`Axu 4& PL)obB"(/6<v dj_$#d ` a ~B;4.'Ffy7]D~XjWv*tsFU:*%b"VtroGLyr z(Z;F( !=|9 S1FZn]L:)~P"z`_^]\m~*Jj i0Q{`FUds,e aK*NrX># bMo@[6>fiDNX.%FfR21]zwW7[';O7Q@->V(D f F~({%+}&2Yth)V`'[0EMJ<.XbtcLGk$1bF_.XoV8Tpvk`:f6\K:(!*4>Xr #  ,<KZjypGpB$LT*r v43uctCWj~lXC.d ~d\TEa~ ^'AFFdDhe?6.~DhB?MF(ZiF$,WJ=Xs@4bGI,QtqNV5gl R(|&z:z|Hn1[-)Jl.D[qxzpf\RG<0%  n]KIGECR`n}>i)LT\dlO2x8k$yF(TRVp,kt|S:l&Gg V0 ~H33333Bk^VR2R2H^HwXjM2>\jx\$Cbbb0teVF7(D1-8|;V`YR2ITcN+}T8BgS dl48_1OmscQ?-~zu>]})Z-t7yk]OA`A]7x /ARHq&tfXK!pjT9Y^c _D?0+. i".:FR z2>KJI40v<=CL&|&*.26\(<@C[: |_D-+p~>X*aYH02'Xf;j$]Hv(T}aE) 2F[piH(uN(Bs#bKI,/` 't Z$?4TsiD iBb=lP4@g{@-z>i&?HmP4@opB:1DN=R*w_F.Fu6Z7gav\0F"Zn+&M)rrBx8x1]1 6`LrtX="} *6BN[htlXC/tS2 "Eh$X5RoysFw.YjF! ,effa 7bSD4%H>}(*o~BA|?5ht$4SsLQ4J_us;"^(U,*Jjh>BFKO0g0~@hd`\X~4wJ-`e24>i5:pbz4:rkd]V\>}Z"y}Q^)V&[}tj&[5v]${ bl5G1aVJ?4{=,{%yN";v>,v Tz^)h"b&jrz+dAr3,$}W1 vdR?=;97FVet0=JVcdfghfc`^YTOJD=60(~xz|~:ZyiBtJ+ N+f3^\9N ?pB<5.(NtL*yN\ o z'b(0_66:u&,27= {#snL&Y545j dx)2~L>jLdN|pK%d$p46h7m"#$%& xT1 mT<60+%4BP_x':L^qv|}xtld[SH>3(0DXk}[8gO6':dBs5>HR[B*a/L"zl=t2u%\y[S x/J=0"4RpW2}@|?p 2H4 7VuA%t<wq3x0Z!ubP>+D^wE R1dsr[D~A\. 8c+_ !iDrQD8,)2 hs~EQ9VtP ~<z=lOXbkt8zA9Vt~Mz9LuF1f:Vqh^TK#t? xJ&Fe 3X~lK*lZHFDCAQ`p(?N]l{|}~xpibWLA6* "/<IRZclpsvzrjc[J8'ng`ZS\dlu+F`zlG"mI34OjCn210/.RW%6h4h2SUXZ\=u@ a)#Z5j;]]\\\<r=j6"U#X @BCDF* uFP19d=hdAydO:9865EVfv+FXj{vjYH6% "(.02579;=?@@AB<61+!*>Rdvu\B)t^G>6-$0bA @b#Mt 0&p? U*8`"V(>SH<1&OT%"JrFu,AVLB9/^+l@>`"Lv$ jBaJ4!:Sl>^~sZ@' xd_ZUPZclv/@Rdmv~wlbWH8) ):FS`lrx}}{m_QC0vgb]XS_kw:VloU;|^@0! &Ff Hk  yJjA2St%Q~ "<962/xF~M4VAp"><:97T"h: *Gt*Y $"! Z0ZC,,AVy-SydB!vbMIEA=IT`l1DXk~~o`QB.!,8DJPV\[ZZYTPLG?80( /BQ`ps`L8j`VMCIPV\o:Xv{W4]I5! +D\u)Lp|R'~S:! $;R{Hr  ^5 hO6 "7Ms 5^fF&fK0)"#2BQq7YolU>!nd[RHOV^ez-@Sfq|th[G3 ~ ,<MWblvvvwwmdZPA2#(<OZfr}~~~vne\L=. yoe[agms2G\p~l[?#ziXH7:Hd;Sk~jW;teVHKNRUhz 6Mdp|tjVB.~ytpkt| -<L\enxti^R>*(;N`ju~paRD2 |xsnv~$;L\l}zhVE*ymaUIOTZ`t0Ib{uX:p^L97531BRct0PpwZ<mU=70*$1>JWu.Mf~x`H(x]QF:.6>FNf~ '@YrxeH+sdTDDEFFWhz,GbulT;"yd^YTNW`ir&;Pf{tbQ9 ymlllku+DVi||r`N;)wnprtv0F]iv|siXF5$zqh`W^fmt5Kaw{jZB*xhXWVVUbp}"=XmlR9 r]UNF>HR]g<Ri}hS6o`RC47:>AVl.Jf|_B%|hUA@?>=M\l|:Ugzs\D,rjb[SY`fl~4KbxtdT>(}omjhfp{5H\or`N;&vjjihhv&=Sbr|r_L8%xof^U\cjq &<Rg}n]B& xiZJJJIIZj{3NiztY>$zeOJE@;GR^j9QjybJ-ui\PDHKNRex)D^xpV; ubPMJGDQ^ly3ObvvdR?% ~rg\PUZ^cu "7Lanz{pZD.ojfa\fpz+?Th|~l[I0tgZ\]^`n|*C\niP8 xd^WPJRZbj~*BZs~jV;zl_RSTUVfv.Hctw`H1|ic^XRZbks/E[qq^J2rdVWXYZix.Harv`I2mga[U^fnw*=PdwrbQ:" }pddeffs/EVhzlWB-tld]U[bhn1H`x~lZ@& tfWVVVUds-Hbrs^H2~jc\VOYblv2G\qoZF,|rh]_bdfv3Jao|thR<%tqnlit~ 5DTdsyzueUE5 ~ .AS]gq{zzzyoe[QB2"{ />M\cjpwusqof\RI8&~} .=LZipw~{vq`P@/~wz~ .ATanz~reYD/usqomw #9J[l}kXD0|sjbfkpt-BWlxn]L6xkkjjjx(>Ucrzm`L8%~zvs|+:JZipw~|wrdVI;(%5BO\imptxrle_QD6(&8JU`lwvtrqh_VM>/ #4DTemv~|xj\OA,srrrq~ "7M]l|{pZD/qkf`Zclt}.DZo{hTA(}rh]RX^ci{0F\s~vgX@'~pbbbaao~'>VdrujVC0|yvrox,=N`jt~~paRD0 #4@LYehlpsmga[N@3&,;FPZehknqjd]VG8) .?PZepzyxvuj_TI9) zu}3EVhz{tdTD4 zodfhjl|*@Vmyzm_H0{jYYYYYgv #:Rbr|fO8"|id_ZU`ju 8J]pp]J7 vmdinty&:M`jtreXJ6# ,8ER^bfkokhd`VK@6&#3=GQ[^`cfb^YUJ>2'$4DMV^gjmpsmga[L<, }w}#5HZlu~tdSC-uhijjkx,D\l|qcL4xgda^[ht6O_n~|s_L8$ vqlgbkt~*<M^px}l\L;&{~"4FR^iuvwxyndZO>- !-8DPTX]a^ZWTJ@7-  #.9DOSVZ^ZWTPG>4++5?ISW\`da^[XL@3'$4DP]jvxyz|sj`WE2 ~zvrnx&<M^n}ubN;(~xrmgov~':L^qyp_N=&zqglpty':NbmxxiZL6twz|"4FR^kwxyz{pdXM;* '2>ITVY\^YTNI>4)#-27<ABBBC>:61*"  #+3;>BFIFDA>6-$ $1:DNWZ\^aZTNG9+ +9GUcipv|vqlfVF7'zrw|(;N`s{|l[J:" ypfjotx,@Tit~zj[L5zpruxz%8KXerzncXD/(8CNZegjlnf_XPA2#(3>CHLQOLJH@81)   (-26;<<=>;852,% ,4<DLPTW[WTPLA6*"4EVhpx~{kZJ:$ zpfjotx,AVkwscS: xk^_`abr2Kdtp`H0ufdb`^kx #<Uev|n`J4}{xvt(<HUbnpsvxph_WH:, (2=BFKPNLJHA:3,$  ")-159:<>?=;970( ,8ER^adhkd\TM@2%&8J[mu|~zk\N?*}pcfilo,AVlwteV>% tgY\^`ct #:Qhv|m^F.p`````n}*BYgv|obL6 zzzyy!4BP_mpsvypg^UF7( &0:?DHMLJHG@:4-" &.6=@BDGD@=:3,$ *6BNZ_dhmhb]XJ=0"| !3EWirz~pbSE0zl^adhk|*AXo{{k[B)sdUWXZ\m~ 8PhvrcJ0rdeffgu%<R_lzti]I5! 0<HUacfhjc\TM@2$  !+048=;:862-($ %+17=>@AB>;84*  &4BOW^fnljhfZNA5"|~ 6Kan{tdU=&|n```__o~6OhxrbH.xiZ[\\]l{0JdtvfL2}n`````o~'?Wgw}oaJ4%7CO[gjlnqh`XO@2$ &/7:<?B?<:70(!  !#&(*+,-.+(%" $0=ELT\\\[[RJA8* $7JWdq~~rg\H3 oljher~ 8Pbs~r[D,ta^ZVS`n{ ;Vhyu_H2xeb`]Zgt/FVfw{q\H3~{xvs|2BRcsx|}tlcQ?- &2=ILPTWRNJE<2(    %,4;BBCDD>70*  .;HUbfjnrkd^WG8(~x 7HYj{xp^L:(yrjbjr{3G[op\H3xphaYajrz4H\plXE2}vnfmt{-?QcuzzrjYH6% '4@LPUZ^YTNI>4)  !$'&&%$!   &,.035420/(! "/<JQX`geca_TJ@5$ 4I^ju{m_Q9" yl`behj{ $<Tkz~n]B' reWY\^`q ";Tlzo^D*}pcdfghw-DZhvsfXC.~~~}} 3FQ\fqpppodZPE6' "(/6<<<;;72.*$  !$$%&&$"  %19BJRSTVWPIB;.! -?KXdpsvy|sjbYH6${wtplw0FVfvzpZC,~mjhfcnz0HYj{~s\F/uspnlv(>N^ozoeP<(!4AN[hjlmof\RI;,$,4;<=>?:61,$    (16:?DB@?=6.'  "1@NV]dljhecWJ>2 ~0CVhqz~zjYH8! |sjpv{%9Nbvn[H4|unfnv},?RexwcP<(~yt| 1@N]lptw{rjbYG6$,4=FNNOPPG>6-!"$&'"   "+049><:86.& #0<IVZ^cgb\VQB3$ 4IVcp}~~th\P<(uttts0F\jx}n_P8! |qsvxz$9Nbmx}l\L;%y~#3CScintzslf_P@1" (1:DMNOPQJC<5*  !$(+(&$!    "*135794.(#$1?HR[dcb`_RF:-+:IXgnu|}vpjXF5# |xsnx+AQbr|qfP:%pnmljw)@XfttfW@*stuvw0DYdp{|xj[L>*!0>LQV\a\XTOB5( #)06<:986.'  $'*.1.,*'  %3<FOXXYZZQH?6&$6HZclv|xurbSD4 wnty~(;Nbu}|iVC0xrlenw 7HZk|vnZG4 }xtoy,AN\jwz|xncYG5#(9CNXbba``VMD:,  (+.2520-*$   "',,,,,&!,8CNRVY]VPJC4& 0CP^kxyz{|peZN9$vwxyz 3H\huzj[K4|rhlptx)>ShtubP>& yqw| !3FXjqxxpiXF5$*6CP\^`bdZQH>0!!+/26:8631)!   "()*+,($!  *4?EJPVSPMJ?4) -;IWeinrvnf_WF4#~{ 5KYgu|pdWA+~qrrrs2I_lxwhXH0{rvz}-BVjrz~xq_N<*,:GTbehlog`XP@0! -5<DLKJJIA80( "(((''"  "$%'# %,3:<>@B=82-" !.<IPX_fc`\YL>1$ 3CScsw|{ri`M:'}yuq{6O^n}th[F0sqomkx,BYfsxj\N8" svxz}&9L^fnw{vrn`QB4! +8ERVZ^b\VPJ=0$  "(-287665.("    "&*-+*(&  &3;CKSRRRQH@7. %6HYbjr{wsok\N@1x}+=N`ryxq^L9&}wqkt}$;L\l}|riUA-|zwtr}0ER^kxyz|}rg\Q>,"1@HQZb`_^\RH=3#"+47:<?;73/&     "# $,5>BEHLGB=8, -=HS^iklnpf[PF3 !6J_jup_N>(|svz~.BVjs|ziXF5xpw~'9J\ntzxpiWF4" .:GT`bdgiaYQI:,(.5<BA@?>6.'     %07>ELJHFD:/$ '4BO\`ejnhaZTE6'*=JXfsvy|uj`VB.~}||{,AVbnzvhZL6! twz}#4FW`ir{xurobTG:& &2>JNSX\XTOK?3' %*0666772-(#     $'%#!  #.5<DKJJIH@7.& )8GV]djqlgb]N@2# 3DTev|zpgS?+~zvs}3JXgv}pdXD0{{zzz(<P]jv~paRD/"1@OU\bhd_ZVI<.! (08@ABBC<4-&  !"""#   #! $-58<@C@<85*  +:DNWabbbcYND:)"3DT]fpyvtqn`QB4 |*;L\msy~vngTB0|(<IVcprstvlbYO>, !0>FNV^\ZYWMB8.$-58;>A=840'  !#%'$   "&%$"!   *06<BA@>=5.&%0;FQTWZ]WRLF8* .@LXcoopppeZPE3  0CU_hr|yvro`RD5! $3BQ`flqwqjd^N>. 0;FQ\^_`bYPG>/ &16:?DB@=;2*! #&*.,*'%!')*,.*&!   )2:=@CFA<83($1?GNV^\ZYWLB7, &5DTchmrwph`YI:*%8FTaortwzpf\R@. %7IR\fonlkj^RF:($1>LQV\a\VQL@3& $+29@@@??82+$ !&&&&&"   "$'%"  $.38=B@=:8.$ .7@JSTUVWOF>6( ,;KS\dljgdbUH</ .>M\bipvpkf`P@0 "3>JVacfhjbZRJ:* *8@HOWVUTSI@6, $,469<>:61-$  $&()+&" !%%$$$ %*/4988870)"*5@KNRUXRLE?3' *:DMV```aaXOF=- ,<LT]fnlifdXL?3! -:GTY^bgb\WRE8* "1:BJSSSSSKC;3&  *48<@D@<84,$ LISTBINFOISFT5GoldWave (C) Chris S. Craig, http://www.goldwave.comgajim-gajim-1.1.3/gajim/data/sounds/gc_message2.wav000066400000000000000000001222661345766322700221310ustar00rootroot00000000000000RIFFWAVEfmt DXdata@ wP*Cu,z  /DZpxI@fP' z-oY%>YZZ[\fE$a`IH 9RjrzBh82L < o b#2h1H_ cx)c!X e Sj")0BydP^lllll* e   2 ;|X%MwU2F Y l  1 N ks{aBtn_ &?U! 0 t r ^ 3lH#u`9ao*0m 0 U z ?   \ "'$ fO h0i   R s3zS@. W@z@[ aN<60*$ TIjP6P$apb / D Yn"a( P y $(a<R4,8E C 3nY9 ~"k8G(KG;h k?j b /n J$t9^"y&XEE P \]I4 H2]6>a0d0Je F 6 crT7Z' ' ~8\ C jn v \ G 2|MO [.>T Bw3 N h<lF W`16g?{T  $x Z.b.]+B*  F x l - NQ2,s>2Rexy = !@ < & ]8(LqBo W Dh L  6 K Z#j ?]H{hVC+xM" 9 1j]-br%j8 # 2Vyi4 ^(>N{rD |T, O 0F$`@r y.h6>  "TX ( z-6k(j,oBP^l z h UB0Jc < 'nx6pp20X$ 1 D lY:$Inu4{Z8 + #  <m 8 ^ s.\b7eV  * 4r 3w2Kd}2BfK0p {T ; ".vDP|=w%d  < Y3|na T F R ^jvR'^2i(f4!b R N  r> ^<~JNRUY? <m5 b S`gn v } p cVIc5{gX>VeJ / #  P % * wA d(wG\p(p< E '=AD H L [ jx;V@:w+b*q . 8 C NXX{ j zXMB7,vwS/^*?~< " s"8M b x {J'd@r2RZ'{$    (:\ .Zy${bH.Fv7~ S  $s F >]{? m6Z   $ (-|A 6 ,G4"TrT7OgUN ^4e 0Cp*S|rCpJ%Il/t\ C 2!Lx *WK  (S 2 p3Tv,hr/Kfb^[W /  | @  x 2{0r\G"Dt\ D  E Z  g>@iv>N, D w W # 0<HU?*Ft]F0n( < u S ;jL..Li|vp Z` * f  kT<$DnDf6Dy8 p ,M  y , hAIPX`ir{ Nh?O`p \  V gxr^J2Xj?_1Qrn* T  n P 3 Zt\yC":Natyrj F  uTH=nuJ k& 6`E w / W O G 2  "Dg4e * #  z^o2V%1Om. o 0 q f \ H 4$.V~96 ( y 'K.M818E = i 3 z = N _ ;  .BVK@6+LnS0 . [ .I;-cM@l 9Nte$ [ . _  !rW=WqnR6LbwVzp h > q 2_sg[,ypRdfvp; d . + ^ f noppqm$Xzqhd`\X V ( g >k zZ6ne7Og~Nu H  ` 7 k  Fq_M;)7DR` H  Z bixD6^? o4  d  g  9#@]z^$. Q N  G *vfVF6Zd 3[> G o  x&8J[mv~b6 $~tQ . =  : p 9|}~,4GIKjW w m 5 G  yc0q> '0  V &  > y 4s3l\M8$ e b ` ^ [ 4 t ,  (2Hr> P\ X C D  k w*0i5rVY' 1 ; E O )  { @  !A`?}Nb&M9 '  $ p  z:AGNU64o> }\jH& % $ " !  O  &Gi}*O}fP}xtr q p n  r ( CLV`il,bZGd/ { W 2  NU L9a^\YVB - 2 8 I  v2~Hz6:dlNYj z x l K *  X2Vmb#c4PE W  V ? >b"H h\B( x:  , < > ? @ B 7 , dOrCN;HlRj  ) 4 1 < T 8c<Dr6i!^&~=y    + 7. <>.r,XftY="| : {   N Gk5OnHs>N6V v " - 8 C Nx-V-8vagZN > > v  Z ZK j+Hd^L F t  7 W w F+az$y"L! ~kjh  { , s  v 20sZ,;IVdrdx@ 2 d  B f iG1e&Ad$ d,27 n + 0 F,l`,8DQ[eoy4d#` & d  N U5*V3K=B[R*pL' S  n  V(pPAHPX__```hpy,+c Y  < v  S 7+R J[UUZJ%W/@ ] ( j ' ]0r8D~zvmdZQbH6h M  N Tb Vb;% VPMo\ ' T j?6expi%gq9 | ( } % w  X-ZT#v2|c)6D X % nS?],(#xV4DTP Q g  d  /Z7b^/8x*o$ l J '  u0IbL5}X35\WF u 2 Q  3T6MMLLV B>x V 4  TrqeXL@jC R M n 1 H 6mhR~v8@!\vfls\D ,  nO"Q"Ttl<z  T * TC|UZZ0\hdB 1~*yGMd\.e  P 8 w"(7TpnN D-zB WX^0s;  ~  n"?xT=\2Rr&N^V { w t p l e^H#w\B(`|+9UN8x{ }  ! h*=4jTB=JVcp%pS 6 ; @ D I h Vx ~8c:4Kn,y@ 4 A f `-B{=~ =>@BCXnO0   . d C~\:o~M3~:^ CV i Q |~@X &@1"zgVD  & E z U b=H(< Tej3x( M ^  B=[,CyjZ4| h f . +($!'-l (QPONM$f! A y B NSUW6`vk@ . \N8 | L  N|[>_wne\2^ vP I - s76rG|@tn.rT X ,  !1Am>-PsC(y=%) r *  xGDb_.4;8N%.}z' f I ,  %:NcL6}DbTj/6>FM<  zU0 v&{h6G8C $  Fq#:r D_&h&)-  x[>!ZWuJVS c$    /albM&7h WSZK | %}bGfV': [8;2l*    (WhZ2Ol>Q-be*F a wZ=+zO$W(^|t"y^{B  "Xr"++AXnS"Z&TI#; l  ,{TBr`N;)SAV1pTc _oh0X"Hn{:JZjzX5 {OJr8'Pxs\E$nFRSj2\ x=-RxI.A2# pe T)h(LpX'E0r6s\U] ".:Rx "8Od{Fs.xKMcy].=|8xn@RdwNh#SX\af~1,D\%hu&l.#Cm>?XDx-n~N2TvB Bcyp%h?<852m2H]spl9j0#p\ ;i FX1 $EfF' y;>T 0t#0;F 6T0 d t&+G+B& zFd l+ $Z*:'oO0; ` "FplA|,6@1"h4>HR\W0r$q2 mK(YRD6)^ D~V3.)&# Y\`dg1eEvChi)iCd"bSD5&aHplAP#,4<Emw,X8I1Ur/nN- {U.vcP=*a 2[dD$E.UTRPO @p J 1=JVb+zb?eA_sZAbDvQ,"bv 4H\oP^yJn$4exn]oZ:F}tT4SrxB(o|}V.  -:l]%Mu>~{'}tU;"2t|SUWTRPMy{!tpmuNG@819ApR8Vt$`bdfhzrX>teVHFDB@]zxY;GQcjotzvm @:Zy[X^chn.jJ-^J5& Iq~cH,H^wd$)@P`p,29@GN$GrN)!(HgkP4v0Dg0$9+?DJPUL.MHvP6,D/LcQZL 4$+3< 0 :jWT/&^"n$`J4 d ^  x#, '6E6' 7dz4 n2p> s*g[NB66788dHJ$.9DOZeUE6&UK fpkQ>,]~ulcZ0 M}xtpg 5@K`v~m\XPwPbtr`MGA+n@JRY`htS>RftiLT%@[vn\K<-(rR ?tmf_X^dkq2u+S{eJa7ESaoXB+@&>1$ &A@@?>DINTH{Du;9(nQ&,2% zq-C rcTD5BN:& VL \ MzG)eJ 1)nS8^ .@]u]YU: dNjU$).3X~hFz9 wlb'$7FTcr&eJ0i,/nZb3<FPYHhmb2_WC/H^ b({p;c, $WlN0-N 4>Ir!28\(ob$f.KFr Y4gZs"4F^vX:l!EtI?k.y3\ 0XDLSUVXZNAe<Qv$e _{#x"g)j,,uU<MhH(wNM{jXk@T=aQH'q`O G'{%wKF`%q\F0( O~F|0/lMd0$F0]<TK*0E&]*NR-VF6& >x#XJV!d? j3En#B8*`jw,Mv:y0m>1$ #\D%P_t@j+]=WDt(G/YpN`  qA8.$"c&cp/\q:p 2aJVV>JC^xFl'l:,](a (RhMsLv.S-iJV/Vz ]T y@g~ YERF9$CW n!]6PZ]<w g0*Ot\C@ qam [VX[D,U]G_i+dd*fX:FW#>ZvAenVKzbP; |_B%vi TaXt9pwBi bJr!~-Hb| :KTh62dV dS.CvY6@6'FF~X)oYnuCZ k3 AB0:mnnop\\q"zZivD>3,S\0\`2!^w&@/wg zBHNTZPb6Rw:{5pf~  D}T,ZZ2= t:V*6yL~L*:JZ g|IY>}SXk~9wR,fqP^*R:z\HZ(2;DFa> k)08N'XJVbM)Op]pGt\}S'^&!:dR(DXkE D|3/I.>z. 4VP$lKR r2"Di#[z6l`@voDM|(!5bvr0p-`d94?BDFI<2QErh-pnT!4rI!NzB*57<}*llXFijfa\X8|u]{a(qxnTVtzMp? pdtc~la_:|pd4zxu$zB^zx>Yu}r{$[z?y GvgXJKx~ \xBV-HdQ"Z!"A gA o m,k^QD7M iPmyD!>\zKS~ &?yMw}nX cXL@5I}hTS ":Qi64awt$T$j/ pV J@7.$7nxl6y2 1.H,\x C}P$/>~T+h!p*p0K] Bzc^Xj;8|!%X[,-.lT4R ~;DXll:p q=0#K=T7GXs:TC:1=T0Ne|(++YPf(/b _r8PG2zh(q "h*Qx 8$ JxJ `" 6y m}|feO" Q9" F&6NJ`uh\Ob .>b 54Q)Gd_H"M6> 3KJ`seXMm .;Hj1:[38aEG3 uN7  L+8Lhh"bcL;0R 1D f*FRtJ$<`>5 l B5( jLWfym" LG6(H "8M=Vb#_6 :P*&|U@/[ DYp5RD&F  4IyB`n#R*0W2$n@{- T>Xp6_T9 |'|4t@]c&g@(GZ/$pC{"P@XpM 8vZ- {`j*t 8Xk4tP,9U_-b6p @,Ce'` Gd7vj vD"QpR}V0 ":Slg.X+_t)*YHr*" JtN(s Th>(_e `9,F`{$x>H4fe#3[L>82,&` q8 ~_Db7(`bb>6Rm+|8 x:0c^*b6m(YOD:0f n9 uK0}W/~%b%vwP(@Xq'v2 z3 T^8n 8g&e[RH>r j&^9*{a8.k.(`;Nbu"n$^ R\,hB};uj`UJyf#V)xga<?FBf9K^p^~TyLe%B}M>vh[N@q`wFfZwfDC SFj>N^m}\ tAjB|g*H{MCzl_RDt`uL#nQjvU5M+WEY)h]RF;nbt? ZKikMR*VAe:NatcR g8rj/S#XHtfYL>mT d>fUtvX`7`?\0CVi|^zKq ?ue*R/dQwi[M?lNd7 ^XwrQR*WEc6HYj| PnEd4l_$S<nXq`N=kR g@gSmzZ9N-[Di?O_o`t=V+fm4`9fLuj^SHvY f1L?_dFU2_YZhvPZ$L*hh,W<lVzm`R bh2L?[vqR4L>~%s]iuZ^{6L[$X?{7vcYV 6<]~hM1Q>w$,} ^Zw5:qrtvwDRL-HvSC kp1PpybL6bX;0lvLLj"~3osw{Nd ZRf{h@J@{9*p[q x.\uj_W8*{D O\r.uIXgv`:HF2MxZL{*1^}pcV_P:~E OZr1r6H[n\8RWNMQ`^/DYn_<UT/H}bPspLyndZOVL@T RV f!d+<N`qL(DM9T/v^n^-WND;2PJJl6 :h` bQ 1BR0>XOv- ;|U\N@:4/)R] _ |D @n]T7t(;!Lli>9vGI+v.,*)'a a cMDnN@%d%<!IjdI) C}A2hW l|,k3?c@*z J,N x'@lH$9o-~"o Vi?DM  @`%g ]2t2 f&?NlH$;p%q V>r  u*K_]! (CSJ)p7"j,H\c<5feO1cw0Z hg,,GQG'n *f+Rh\4 "TVA(] =et#b" :WO$fj4Zl"d:2d`D+^ |6ek`"8VU9 Mp8g8xN# 8f T/x @v>j}.F1 $ta> Rx~Q%VBk:0&1RrS*v0h]&n#NlL+ ".:n T-p9^zS+d"Mr@6,":\}[&kUX"m%X|^@!,8CN|HWDnY2j(]_TH=2NjP\ BwNv5w:~]|Ld|xKDNxX]bfk E2o6\z\=J N zk\sL~3o @Xoxl?}B_(hjloqI6r6^vV6vA_2tauEw5t9Qh~re:~@\&uxz|O:u6[wX8r;Ixj\t$X FH^stf8 t8Tnrw|R@z6ZoP0i1D|pc{*] I@Ti~vgY.q5Ofkpv{M0i*Qx{_C'~FP"~oauH{4r <Sjtg<~AY"mprux@{-g.VdH,WW(vcQdv2d$dG`z~R'Tb'ghhhi4n"_-VfJ.We3zhVh{7i%d=XtY.\d(\^_`b-hZ.Yv\A j*i7xdP`p$UL0Kf_6m1|@jfb_[}TE#R{bJh(g5vaM^n~MW<Xt`6 h+r5~VTRPNrVP*VfN=w>{dL5J^s&Z`>Yt`4c&p4ccccc*dP$QgMk*f4r]HYj|MV:Xu`5 i.~C uojd^UHJurX? m0yElXgv(YS-JfW0h+~E ojfa\{PF N{}dKx6q?lXfuHAx:Xw]8u:Fojfa\~VDIwrZB i+r? n[kz#QDz?`h@s4F yvrolH4s;iwpX@v:T#~hu!M9q6Ro|wR-u>`)zriK1l+Wftn]LXr=irz2n$Z:Zy|~eF&`(v;yq :lSDVgx{l^O$j0Nrx~%`I<^gF$g3Gzm_v$YD :M`txj\M"l5_+wz}T>v(Jknrux\?"q?T(zl,]E 8L`u{l^P%j1Ty%\7l Ejpv{fJ/t>X.}.]2i)@Wnxk^Q'n3Z)+b<q!Dfkpty\> h4Q*.[3l.DYnwj^Q&n8f4&Z+_8]bfjoU: n;^6.\4m!6J_tgZNAm4b0S,b9\bhmsX< uEi=%R&^2I`wndZQ)yB p? N'\3W\bhmS9rA kB%S+d,@Uj`VMCJyDOT*MSZ`fO8  S{N"/[$Y !6LbYPG>wFPP T(LSZbiP8 ~PxO&$P| W0E[SLD<Q V#NEx6?HPYE2 SzP',U~Jv+BZTNGAJS$J{Dx<DMV^G0W#_6&MtDr(=SLD<5xHW' (XIz3:AHO;'zNc<(NuFq 4JD>82V'm?" O~ >o%-5=E2 ].yP&,Pt2_(>:63/d8 }M.?j"Q".;G8* sBZ08YGt98887nBU4 2\I|%4CRD5&|JZ-5YEr <>@BD( zM [8/ZAr/@PB4'Qb8 6WCp"?@@@A& xJZ:-U}6g .?PD8, ]-tH%Ds1`:;<=>&^3wR-&Ox2b"3E:.#`1~T):h"R38>CH.\/oM+ Dl$U},>4*!^2^4$@n#Nz!&*\3~\:,Rx%Rv,%f9 ^36PxBl"b<sS3 5Vv7^ ^4 sN9$ #9Ow<d iGdE%  2Pn1Tx sM'dL4 !6Kn$JofEnO0# 8Ur'Jnf=}XC.(hK/$ 'B^z*Lo|X4_L9&(nTJ?4*06=CZp7TqxX9p^K98643@N[h-Kbz{cK, k^RE8ACXl+Fa|kP6lXQJB;FQ\g"?TjzhU9rdUGJLORct:Vr}dK2xbMHB=8ER`m:RizfR7p]J889::Nbu6Rm~fL2mXPH@8BLV`z"@Vk|hT6oaRD69<@CVj~#@\xlR7}fOHB<5?JT^w7PhmZ>"{l\L=@BEHYj{7SolT=%~hRKD>7CO[g;Rhs`F+q`O>>>==N`q *HfzhO6nULB8/8AJSl,D\u}jM0r^J76432DUfx (FdwlT<pWL@5*29@H^t3NjwZ>!taN;9864CRbq7UknV?"gZNA4:?DJ_t-HdhI* |hS>:62.708BLV`w*BZqt`D' zk\MMLLLZgt:VjqX?& md[RINRV[p 'A[un\B( LISTBINFOISFT5GoldWave (C) Chris S. Craig, http://www.goldwave.comgajim-gajim-1.1.3/gajim/data/sounds/message1.wav000066400000000000000000001742461345766322700214640ustar00rootroot00000000000000RIFFWAVEfmt DXdata0 ",6BN[g[PD8WvlSx 7iAR/LC&DbaB r$KrT72iN 1V|8#Io fkV`idgG#r_3Fwj!|A4o.Dr6M |*--'"BvlQ.>Sh$G}F n:HUbp[F1=^H?^Ni wFRqGWG~$h)|>_v.g vJIHHGd!Z0z?A|5/~O473-V}dJ;P 1}`bdegR<'gfTB1pKfiY * zY8zCByx>^ONk|  [  t >/\JT !XLR"F  d j42L0Wt[Ce6ymHK|PbtlV@g D& })A@4SQ{F>Qc BVk }X4t&+RJz ~`X[ $1=i<;EvCzn?nh4\';ADHLOv8^ :t,p ,=750,Ry_D*TM{U0 $cpk ;WRNJEdN9$4Yblu~>"?e#bM06WI<. Z$ke JEA@!0>L:(.ZmhQ: "  ?v S{=Dv0gzdv>F#Ny`=>a$!{V2]J\n.cR>b B&2>{3"FHHz6%01223:BIPjPC=HS^i: L%"0B"\ ;o`k ,7BN p BzK X'#;a6rdL&UQNJFa8\D~zuK!4FXkBIh\3:4M|(-^/rY )Lo*\%6>ELTcr-COZfrcTD5\C}D/_[W$ESPUB\3tF.{{T.LkpU:4"X zF:.#HxH@hTmv4 ,#VdrT5(X|0yJ]"A_ `  x;d+;p"N/y wJ[S.h65f+w *8Gy T 2Jby2~fEsFn'(B:]@<71+mrT5Y~HTFz (2<EOJD>9+tE}B`)NQKE' Ex~cPF@3zU0 V7X0:lwZRJA90(f a4Sr]wsplh8p@k41EYm_<}@Re Yht>H4 n1Mhcvn$]N>.n8(C;3+#V>PW:Uph_WO~ s((r{5l@"DT[I >Sh>'JJ` f8QjzbJ2nR6#|\<taN\iv!URf%ch'j,2x~~n.n:+C:L |1*Ln$< >p0r-^4|uZWIk-fzN}~32|6[td1Dh_0&7Ieh-R 7cM8" E~*>\yL &VoYC-;HVdr-Ck.u6*hPu,CZqJ nKMHC>9 x<T"vR.$ &Kp/h!`+Y\`cf(p$7:\v"qNm(Lx&0uw4sU7?GOWr%Eh9[/NntI`rbC,R/BNA 1XY*;zR^ hBMoZF W>9Bj{HY RD$MIEA=B90(h Ti~<<Quvj7;>BF4H$+k}n \:Y  )]x8wW7  @:xI&jEx@ ^%b<^Zzj 5_a9,n$` ^<1^ T?_~"/<JJJJJ@6+!n9HJv[mW@&XxW6@JT}Na7\Wqvc*g`YRKDtV>%x"cBd|6dB  zh/W!*4n {nbUHrtfm{uoic'"D,D]xhG7'KnT;Zu4(A[gt(^L&tr`\XSO0RL{R*XT_".9DP>+,x\zh WTQfz4d^XRL~cV6Ncx~cH-cB vU4yncuEx`JEuP }M]XRMHRF}f *V}PCxS6zk^R2k@! 2G\[ZZY axb| 7Jxvtqo_P@0x RB3$>iqyW_qtwz|>HYnXB-6Vgx!0(_@xk^QD6)Wd ]HZ4TGDDFpjS<%:fb`p2stN)i<qP..\1m#` 20.-+M1e~-?LUkn)B`o&TjE 08,5 2x:74~ U1 6[n4pj@. `.}B c@:Uq9d 6_wZ1 n }(~[x$m'p%>VtJ>z"w!w#Fhfdb`@ RY~,gErGB! p@X+BX^elrz,XSD$c2d/yw 0LU;JZVQLH%XXT* #v 3nH!`~sC~tfWBj: ` ]PYF4"%n:~J<962/L$\/^7xzz z:5pKS6K|8FPwq C;Jzzzyy8Ln>7RDvX[^beF&G~jVBYp&6V-=M]2Of5:]*i<Y tJxZ;dTaq36Md|m)KGrw"v!R +IbzmX2 p9LXPHA9Uph(!PUV8=- 3j_q\"Y_B&b :To <TDc,7x -=.oP2!&-4 'p|O'K#BXs^Ma e4Xajt}kYG5DIJ>h<HU?j4$vPFpYB*Z2[\8,azk\,qg]UME="iceJ07YF2 |\:qK(aRKrlf}dL j7Q +b:&?$[o[ ;v)~ dir,`7AT7(y?Pu\D,7"7e~ysF,>Pc+5qclo.LrT7La<:]ft:8`'|H%w=p+v U,sP. 4Me>r.r?M\jxM"Qtrh;y4l_vH6#@*laIdX49p& a6V`BRukEchlpu(A:3OkBJd$x#fbCR ]z;X *",>QcL5Q/$n#/Lyu/ 27d%D`RSTVW2 F~u ?z_D( LZ(PifIHwC-Lj4R5]8M^(X,U~\L )2:>|obUH;.L0y|~Z0BsBbFxFQ Py;d;}(|)j W2M=[$Y/} sA+0n*2;DLOXo*1~6nH!<.tc `&)-04nc]W\afkl1 3GQjK+}CGVetOK~0lu#fvH{<Q}x7?d|Vf`^[XVTrXPB~n^RE8,$n/@h\OB6VwlaVK"R7zjo 4G8_dBp\vl4+~&P@h-F` Ab&QJzlGIKprQV\af7` djv{_$">[4LQJnB(feis.(e(Mr6k6=Rm8J!-8DP VL(j ]zRd?4)j+'X tDL<^cG*2UxOg%}[ZZYXi?d>\!X,_d9H)Z?sZB*Vrb4d>g'<e~3QJf7J]p o"L:1(x*bm(\8B}=Hi;Lz@G>,`vX:}V.gRD6(0G^tbZSE8*=^qZB9*Ip:d>||Rneh6HAq2Le~:|bcb`^]PCl`Np8{C[s6NgQc!"n!>|V1K&2wbo4{'~*,}_~ d5| 4\~gPv-pu7$u{`= =n8{+anm=R\$,3579;"<WtGB!B^$5GXK>0#A$GjhB!/\<3h,{Rdg15GYk~/jyL *Fb*hDjLB8-#nM;(]hov~&Jo>{T.;)sNL&3TU|^WZ]XR4{vrm&O"o rbRAl8W0BTgD Dj&fK0Svp%L%`rdMgTQ]c8y;^.2<Fa|N#[3b:(4zaN<*(8$9,%,D[rJyVrR1>%$S.Am{~8e{yV4?JVa'c(8j;[z*pV&]+_,iJ*1a]0xPqM k-SrH xh `iM15SqCZ%c6gP9" ":QhG|2H_v\B(9@Q@VNA-WnJ%irX> l5xkj2xCp],X eqR3pf>?Sh|^-*(%"8C@=:7<#6CP\i RA~c_ZVR8@b`<*n9OAdK%\z9$ 8bHsP [PeD"5+BHM}8.(y|GN#kCejU}xtoj4B|5,&Ja2*#" ,:GUPqF,zgTGwl8l60*#|;*E8*3+ydV8hhijjBZ#\\\[[w:_pvg: X+R v#h8FS`n43JZGt,b/\IL6qo2uL95,Szh |>&wRZNXNS"+3<DW<w6WxyiY@ jG$q2 8d$-$wW6m[b=(z5BN[hr{T"@^djpv\A;&i(Z)hV_k/3HFtNCDPeE%&(*+Fb}->PaVLB7yX82,%BdZ D~|[ k\Pk[L<,i! 1DN|7D6w+3~D @w? -eQ['S~6r_M&t8GGNT[bF$kV'I^CT>v2pl+DPteVG826d5| d2_R&rT6ns |)?gT d2nLN2xqL#_4.(#p6HC$Jq 0?N\k^RE8" ,V &A6,"McO $L^-:4J{6(]b.#^pd f6 ,CQ C{6>^~mG!N>wb$0Hngv<\{"r `<aK*S|c@|\tY\:F25dCv8> JDy"N @% l0*[QyaL7dhknr:9.Ns|G~"DflS4!?`Y!r1lK)6CP]#ex(|%JnxY9o &)Ct tCDE&@5ChFV6>3V.~q^t62auV@%>2kgc/Q6/b8VtnJ%dpg.vj^RvNN~z^B& 4OcxtU6]3X&vfMKJHFv1Jc'L6XDZfi(exVQLZ"l0zP v2CuE|b2;lc.a.o~2\.l $L3_Cqi4(Y`'|Q7A Nha `,)]6p@p|X6nzk$N.:gG'8HYjIEkbA! #6>FOWL@4) nM, /dD2bzKtlToqsuw WgN4| RH>5+hdL3G&>U>(1wC)vT2jb&nW^v)Vt 4DD5|d-?u 4h/qg]dka^" \:l5(XA H)JB:1){T.  tcRW\bg>oDTcrgL1Sv)e*M|BsJJ`NMKGporvy|=,Y ]s(1@BLK3C;Py_E?9z=DDA`~DTZ0fP!eL`j>e#>Pa c#8ln;JZ-)x6oqKVrzS-,tM{5" *Ln9}C/6<CJ.f>y{~ @b ,  vHB\F0%EekliF]tuF"[jz$v D5%(=0gzh`Axu 4& PL)obB"(/6<v dj_$#d ` a ~B;4.'Ffy7]D~XjWv*tsFU:*%b"VtroGLyr z(Z;F( !=|9 S1FZn]L:)~P"z`_^]\m~*Jj i0Q{`FUds,e aK*NrX># bMo@[6>fiDNX.%FfR21]zwW7[';O7Q@->V(D f F~({%+}&2Yth)V`'[0EMJ<.XbtcLGk$1bF_.XoV8Tpvk`:f6\K:(!*4>Xr #  ,<KZjypGpB$LT*r v43uctCWj~lXC.d ~d\TEa~ ^'AFFdDhe?6.~DhB?MF(ZiF$,WJ=Xs@4bGI,QtqNV5gl R(|&z:z|Hn1[-)Jl.D[qxzpf\RG<0%  n]KIGECR`n}>i)LT\dlO2x8k$yF(TRVp,kt|S:l&Gg V0 ~H33333Bk^VR2R2H^HwXjM2>\jx\$Cbbb0teVF7(D1-8|;V`YR2ITcN+}T8BgS dl48_1OmscQ?-~zu>]})Z-t7yk]OA`A]7x /ARHq&tfXK!pjT9Y^c _D?0+. i".:FR z2>KJI40v<=CL&|&*.26\(<@C[: |_D-+p~>X*aYH02'Xf;j$]Hv(T}aE) 2F[piH(uN(Bs#bKI,/` 't Z$?4TsiD iBb=lP4@g{@-z>i&?HmP4@opB:1DN=R*w_F.Fu6Z7gav\0F"Zn+&M)rrBx8x1]1 6`LrtX="} *6BN[htlXC/tS2 "Eh$X5RoysFw.YjF! ,effa 7bSD4%H>}(*o~BA|?5ht$4SsLQ4J_us;"^(U,*Jjh>BFKO0g0~@hd`\X~4wJ-`e24>i5:pbz4:rkd]V\>}Z"y}Q^)V&[}tj&[5v]${ bl5G1aVJ?4{=,{%yN";v>,v Tz^)h"b&jrz+dAr3,$}W1 vdR?=;97FVet0=JVcdfghfc`^YTOJD=60(~xz|~:ZyiBtJ+ N+f3^\9N ?pB<5.(NtL*yN\ o z'b(0_66:u&,27= {#snL&Y545j dx)2~L>jLdN|pK%d$p46h7m"#$%& xT1 mT<60+%4BP_x':L^qv|}xtld[SH>3(0DXk}[8gO6':dBs5>HR[B*a/L"zl=t2u%\y[S x/J=0"4RpW2}@|?p 2H4 7VuA%t<wq3x0Z!ubP>+D^wE R1dsr[D~A\. 8c+_ !iDrQD8,)2 hs~EQ9VtP ~<z=lOXbkt8zA9Vt~Mz9LuF1f:Vqh^TK#t? xJ&Fe 3X~lK*lZHFDCAQ`p(?N]l{|}~xpibWLA6* "/<IRZclpsvzrjc[J8'ng`ZS\dlu+F`zlG"mI34OjCn210/.RW%6h4h2SUXZ\=u@ a)#Z5j;]]\\\<r=j6"U#X @BCDF* uFP19d=hdAydO:9865EVfv+FXj{vjYH6% "(.02579;=?@@AB<61+!*>Rdvu\B)t^G>6-$0bA @b#Mt 0&p? U*8`"V(>SH<1&OT%"JrFu,AVLB9/^+l@>`"Lv$ jBaJ4!:Sl>^~sZ@' xd_ZUPZclv/@Rdmv~wlbWH8) ):FS`lrx}}{m_QC0vgb]XS_kw:VloU;|^@0! &Ff Hk  yJjA2St%Q~ "<962/xF~M4VAp"><:97T"h: *Gt*Y $"! Z0ZC,,AVy-SydB!vbMIEA=IT`l1DXk~~o`QB.!,8DJPV\[ZZYTPLG?80( /BQ`ps`L8j`VMCIPV\o:Xv{W4]I5! +D\u)Lp|R'~S:! $;R{Hr  ^5 hO6 "7Ms 5^fF&fK0)"#2BQq7YolU>!nd[RHOV^ez-@Sfq|th[G3 ~ ,<MWblvvvwwmdZPA2#(<OZfr}~~~vne\L=. yoe[agms2G\p~l[?#ziXH7:Hd;Sk~jW;teVHKNRUhz 6Mdp|tjVB.~ytpkt| -<L\enxti^R>*(;N`ju~paRD2 |xsnv~$;L\l}zhVE*ymaUIOTZ`t0Ib{uX:p^L97531BRct0PpwZ<mU=70*$1>JWu.Mf~x`H(x]QF:.6>FNf~ '@YrxeH+sdTDDEFFWhz,GbulT;"yd^YTNW`ir&;Pf{tbQ9 ymlllku+DVi||r`N;)wnprtv0F]iv|siXF5$zqh`W^fmt5Kaw{jZB*xhXWVVUbp}"=XmlR9 r]UNF>HR]g<Ri}hS6o`RC47:>AVl.Jf|_B%|hUA@?>=M\l|:Ugzs\D,rjb[SY`fl~4KbxtdT>(}omjhfp{5H\or`N;&vjjihhv&=Sbr|r_L8%xof^U\cjq &<Rg}n]B& xiZJJJIIZj{3NiztY>$zeOJE@;GR^j9QjybJ-ui\PDHKNRex)D^xpV; ubPMJGDQ^ly3ObvvdR?% ~rg\PUZ^cu "7Lanz{pZD.ojfa\fpz+?Th|~l[I0tgZ\]^`n|*C\niP8 xd^WPJRZbj~*BZs~jV;zl_RSTUVfv.Hctw`H1|ic^XRZbks/E[qq^J2rdVWXYZix.Harv`I2mga[U^fnw*=PdwrbQ:" }pddeffs/EVhzlWB-tld]U[bhn1H`x~lZ@& tfWVVVUds-Hbrs^H2~jc\VOYblv2G\qoZF,|rh]_bdfv3Jao|thR<%tqnlit~ 5DTdsyzueUE5 ~ .AS]gq{zzzyoe[QB2"{ />M\cjpwusqof\RI8&~} .=LZipw~{vq`P@/~wz~ .ATanz~reYD/usqomw #9J[l}kXD0|sjbfkpt-BWlxn]L6xkkjjjx(>Ucrzm`L8%~zvs|+:JZipw~|wrdVI;(%5BO\imptxrle_QD6(&8JU`lwvtrqh_VM>/ #4DTemv~|xj\OA,srrrq~ "7M]l|{pZD/qkf`Zclt}.DZo{hTA(}rh]RX^ci{0F\s~vgX@'~pbbbaao~'>VdrujVC0|yvrox,=N`jt~~paRD0 #4@LYehlpsmga[N@3&,;FPZehknqjd]VG8) .?PZepzyxvuj_TI9) zu}3EVhz{tdTD4 zodfhjl|*@Vmyzm_H0{jYYYYYgv #:Rbr|fO8"|id_ZU`ju 8J]pp]J7 vmdinty&:M`jtreXJ6# ,8ER^bfkokhd`VK@6&#3=GQ[^`cfb^YUJ>2'$4DMV^gjmpsmga[L<, }w}#5HZlu~tdSC-uhijjkx,D\l|qcL4xgda^[ht6O_n~|s_L8$ vqlgbkt~*<M^px}l\L;&{~"4FR^iuvwxyndZO>- !-8DPTX]a^ZWTJ@7-  #.9DOSVZ^ZWTPG>4++5?ISW\`da^[XL@3'$4DP]jvxyz|sj`WE2 ~zvrnx&<M^n}ubN;(~xrmgov~':L^qyp_N=&zqglpty':NbmxxiZL6twz|"4FR^kwxyz{pdXM;* '2>ITVY\^YTNI>4)#-27<ABBBC>:61*"  #+3;>BFIFDA>6-$ $1:DNWZ\^aZTNG9+ +9GUcipv|vqlfVF7'zrw|(;N`s{|l[J:" ypfjotx,@Tit~zj[L5zpruxz%8KXerzncXD/(8CNZegjlnf_XPA2#(3>CHLQOLJH@81)   (-26;<<=>;852,% ,4<DLPTW[WTPLA6*"4EVhpx~{kZJ:$ zpfjotx,AVkwscS: xk^_`abr2Kdtp`H0ufdb`^kx #<Uev|n`J4}{xvt(<HUbnpsvxph_WH:, (2=BFKPNLJHA:3,$  ")-159:<>?=;970( ,8ER^adhkd\TM@2%&8J[mu|~zk\N?*}pcfilo,AVlwteV>% tgY\^`ct #:Qhv|m^F.p`````n}*BYgv|obL6 zzzyy!4BP_mpsvypg^UF7( &0:?DHMLJHG@:4-" &.6=@BDGD@=:3,$ *6BNZ_dhmhb]XJ=0"| !3EWirz~pbSE0zl^adhk|*AXo{{k[B)sdUWXZ\m~ 8PhvrcJ0rdeffgu%<R_lzti]I5! 0<HUacfhjc\TM@2$  !+048=;:862-($ %+17=>@AB>;84*  &4BOW^fnljhfZNA5"|~ 6Kan{tdU=&|n```__o~6OhxrbH.xiZ[\\]l{0JdtvfL2}n`````o~'?Wgw}oaJ4%7CO[gjlnqh`XO@2$ &/7:<?B?<:70(!  !#&(*+,-.+(%" $0=ELT\\\[[RJA8* $7JWdq~~rg\H3 oljher~ 8Pbs~r[D,ta^ZVS`n{ ;Vhyu_H2xeb`]Zgt/FVfw{q\H3~{xvs|2BRcsx|}tlcQ?- &2=ILPTWRNJE<2(    %,4;BBCDD>70*  .;HUbfjnrkd^WG8(~x 7HYj{xp^L:(yrjbjr{3G[op\H3xphaYajrz4H\plXE2}vnfmt{-?QcuzzrjYH6% '4@LPUZ^YTNI>4)  !$'&&%$!   &,.035420/(! "/<JQX`geca_TJ@5$ 4I^ju{m_Q9" yl`behj{ $<Tkz~n]B' reWY\^`q ";Tlzo^D*}pcdfghw-DZhvsfXC.~~~}} 3FQ\fqpppodZPE6' "(/6<<<;;72.*$  !$$%&&$"  %19BJRSTVWPIB;.! -?KXdpsvy|sjbYH6${wtplw0FVfvzpZC,~mjhfcnz0HYj{~s\F/uspnlv(>N^ozoeP<(!4AN[hjlmof\RI;,$,4;<=>?:61,$    (16:?DB@?=6.'  "1@NV]dljhecWJ>2 ~0CVhqz~zjYH8! |sjpv{%9Nbvn[H4|unfnv},?RexwcP<(~yt| 1@N]lptw{rjbYG6$,4=FNNOPPG>6-!"$&'"   "+049><:86.& #0<IVZ^cgb\VQB3$ 4IVcp}~~th\P<(uttts0F\jx}n_P8! |qsvxz$9Nbmx}l\L;%y~#3CScintzslf_P@1" (1:DMNOPQJC<5*  !$(+(&$!    "*135794.(#$1?HR[dcb`_RF:-+:IXgnu|}vpjXF5# |xsnx+AQbr|qfP:%pnmljw)@XfttfW@*stuvw0DYdp{|xj[L>*!0>LQV\a\XTOB5( #)06<:986.'  $'*.1.,*'  %3<FOXXYZZQH?6&$6HZclv|xurbSD4 wnty~(;Nbu}|iVC0xrlenw 7HZk|vnZG4 }xtoy,AN\jwz|xncYG5#(9CNXbba``VMD:,  (+.2520-*$   "',,,,,&!,8CNRVY]VPJC4& 0CP^kxyz{|peZN9$vwxyz 3H\huzj[K4|rhlptx)>ShtubP>& yqw| !3FXjqxxpiXF5$*6CP\^`bdZQH>0!!+/26:8631)!   "()*+,($!  *4?EJPVSPMJ?4) -;IWeinrvnf_WF4#~{ 5KYgu|pdWA+~qrrrs2I_lxwhXH0{rvz}-BVjrz~xq_N<*,:GTbehlog`XP@0! -5<DLKJJIA80( "(((''"  "$%'# %,3:<>@B=82-" !.<IPX_fc`\YL>1$ 3CScsw|{ri`M:'}yuq{6O^n}th[F0sqomkx,BYfsxj\N8" svxz}&9L^fnw{vrn`QB4! +8ERVZ^b\VPJ=0$  "(-287665.("    "&*-+*(&  &3;CKSRRRQH@7. %6HYbjr{wsok\N@1x}+=N`ryxq^L9&}wqkt}$;L\l}|riUA-|zwtr}0ER^kxyz|}rg\Q>,"1@HQZb`_^\RH=3#"+47:<?;73/&     "# $,5>BEHLGB=8, -=HS^iklnpf[PF3 !6J_jup_N>(|svz~.BVjs|ziXF5xpw~'9J\ntzxpiWF4" .:GT`bdgiaYQI:,(.5<BA@?>6.'     %07>ELJHFD:/$ '4BO\`ejnhaZTE6'*=JXfsvy|uj`VB.~}||{,AVbnzvhZL6! twz}#4FW`ir{xurobTG:& &2>JNSX\XTOK?3' %*0666772-(#     $'%#!  #.5<DKJJIH@7.& )8GV]djqlgb]N@2# 3DTev|zpgS?+~zvs}3JXgv}pdXD0{{zzz(<P]jv~paRD/"1@OU\bhd_ZVI<.! (08@ABBC<4-&  !"""#   #! $-58<@C@<85*  +:DNWabbbcYND:)"3DT]fpyvtqn`QB4 |*;L\msy~vngTB0|(<IVcprstvlbYO>, !0>FNV^\ZYWMB8.$-58;>A=840'  !#%'$   "&%$"!   *06<BA@>=5.&%0;FQTWZ]WRLF8* .@LXcoopppeZPE3  0CU_hr|yvro`RD5! $3BQ`flqwqjd^N>. 0;FQ\^_`bYPG>/ &16:?DB@=;2*! #&*.,*'%!')*,.*&!   )2:=@CFA<83($1?GNV^\ZYWLB7, &5DTchmrwph`YI:*%8FTaortwzpf\R@. %7IR\fonlkj^RF:($1>LQV\a\VQL@3& $+29@@@??82+$ !&&&&&"   "$'%"  $.38=B@=:8.$ .7@JSTUVWOF>6( ,;KS\dljgdbUH</ .>M\bipvpkf`P@0 "3>JVacfhjbZRJ:* *8@HOWVUTSI@6, $,469<>:61-$  $&()+&" !%%$$$ %*/4988870)"*5@KNRUXRLE?3' *:DMV```aaXOF=- ,<LT]fnlifdXL?3! -:GTY^bgb\WRE8* "1:BJSSSSSKC;3&  *48<@D@<84,$ LISTBINFOISFT5GoldWave (C) Chris S. Craig, http://www.goldwave.comgajim-gajim-1.1.3/gajim/data/sounds/message2.wav000066400000000000000000001222661345766322700214600ustar00rootroot00000000000000RIFFWAVEfmt DXdata@ wP*Cu,z  /DZpxI@fP' z-oY%>YZZ[\fE$a`IH 9RjrzBh82L < o b#2h1H_ cx)c!X e Sj")0BydP^lllll* e   2 ;|X%MwU2F Y l  1 N ks{aBtn_ &?U! 0 t r ^ 3lH#u`9ao*0m 0 U z ?   \ "'$ fO h0i   R s3zS@. W@z@[ aN<60*$ TIjP6P$apb / D Yn"a( P y $(a<R4,8E C 3nY9 ~"k8G(KG;h k?j b /n J$t9^"y&XEE P \]I4 H2]6>a0d0Je F 6 crT7Z' ' ~8\ C jn v \ G 2|MO [.>T Bw3 N h<lF W`16g?{T  $x Z.b.]+B*  F x l - NQ2,s>2Rexy = !@ < & ]8(LqBo W Dh L  6 K Z#j ?]H{hVC+xM" 9 1j]-br%j8 # 2Vyi4 ^(>N{rD |T, O 0F$`@r y.h6>  "TX ( z-6k(j,oBP^l z h UB0Jc < 'nx6pp20X$ 1 D lY:$Inu4{Z8 + #  <m 8 ^ s.\b7eV  * 4r 3w2Kd}2BfK0p {T ; ".vDP|=w%d  < Y3|na T F R ^jvR'^2i(f4!b R N  r> ^<~JNRUY? <m5 b S`gn v } p cVIc5{gX>VeJ / #  P % * wA d(wG\p(p< E '=AD H L [ jx;V@:w+b*q . 8 C NXX{ j zXMB7,vwS/^*?~< " s"8M b x {J'd@r2RZ'{$    (:\ .Zy${bH.Fv7~ S  $s F >]{? m6Z   $ (-|A 6 ,G4"TrT7OgUN ^4e 0Cp*S|rCpJ%Il/t\ C 2!Lx *WK  (S 2 p3Tv,hr/Kfb^[W /  | @  x 2{0r\G"Dt\ D  E Z  g>@iv>N, D w W # 0<HU?*Ft]F0n( < u S ;jL..Li|vp Z` * f  kT<$DnDf6Dy8 p ,M  y , hAIPX`ir{ Nh?O`p \  V gxr^J2Xj?_1Qrn* T  n P 3 Zt\yC":Natyrj F  uTH=nuJ k& 6`E w / W O G 2  "Dg4e * #  z^o2V%1Om. o 0 q f \ H 4$.V~96 ( y 'K.M818E = i 3 z = N _ ;  .BVK@6+LnS0 . [ .I;-cM@l 9Nte$ [ . _  !rW=WqnR6LbwVzp h > q 2_sg[,ypRdfvp; d . + ^ f noppqm$Xzqhd`\X V ( g >k zZ6ne7Og~Nu H  ` 7 k  Fq_M;)7DR` H  Z bixD6^? o4  d  g  9#@]z^$. Q N  G *vfVF6Zd 3[> G o  x&8J[mv~b6 $~tQ . =  : p 9|}~,4GIKjW w m 5 G  yc0q> '0  V &  > y 4s3l\M8$ e b ` ^ [ 4 t ,  (2Hr> P\ X C D  k w*0i5rVY' 1 ; E O )  { @  !A`?}Nb&M9 '  $ p  z:AGNU64o> }\jH& % $ " !  O  &Gi}*O}fP}xtr q p n  r ( CLV`il,bZGd/ { W 2  NU L9a^\YVB - 2 8 I  v2~Hz6:dlNYj z x l K *  X2Vmb#c4PE W  V ? >b"H h\B( x:  , < > ? @ B 7 , dOrCN;HlRj  ) 4 1 < T 8c<Dr6i!^&~=y    + 7. <>.r,XftY="| : {   N Gk5OnHs>N6V v " - 8 C Nx-V-8vagZN > > v  Z ZK j+Hd^L F t  7 W w F+az$y"L! ~kjh  { , s  v 20sZ,;IVdrdx@ 2 d  B f iG1e&Ad$ d,27 n + 0 F,l`,8DQ[eoy4d#` & d  N U5*V3K=B[R*pL' S  n  V(pPAHPX__```hpy,+c Y  < v  S 7+R J[UUZJ%W/@ ] ( j ' ]0r8D~zvmdZQbH6h M  N Tb Vb;% VPMo\ ' T j?6expi%gq9 | ( } % w  X-ZT#v2|c)6D X % nS?],(#xV4DTP Q g  d  /Z7b^/8x*o$ l J '  u0IbL5}X35\WF u 2 Q  3T6MMLLV B>x V 4  TrqeXL@jC R M n 1 H 6mhR~v8@!\vfls\D ,  nO"Q"Ttl<z  T * TC|UZZ0\hdB 1~*yGMd\.e  P 8 w"(7TpnN D-zB WX^0s;  ~  n"?xT=\2Rr&N^V { w t p l e^H#w\B(`|+9UN8x{ }  ! h*=4jTB=JVcp%pS 6 ; @ D I h Vx ~8c:4Kn,y@ 4 A f `-B{=~ =>@BCXnO0   . d C~\:o~M3~:^ CV i Q |~@X &@1"zgVD  & E z U b=H(< Tej3x( M ^  B=[,CyjZ4| h f . +($!'-l (QPONM$f! A y B NSUW6`vk@ . \N8 | L  N|[>_wne\2^ vP I - s76rG|@tn.rT X ,  !1Am>-PsC(y=%) r *  xGDb_.4;8N%.}z' f I ,  %:NcL6}DbTj/6>FM<  zU0 v&{h6G8C $  Fq#:r D_&h&)-  x[>!ZWuJVS c$    /albM&7h WSZK | %}bGfV': [8;2l*    (WhZ2Ol>Q-be*F a wZ=+zO$W(^|t"y^{B  "Xr"++AXnS"Z&TI#; l  ,{TBr`N;)SAV1pTc _oh0X"Hn{:JZjzX5 {OJr8'Pxs\E$nFRSj2\ x=-RxI.A2# pe T)h(LpX'E0r6s\U] ".:Rx "8Od{Fs.xKMcy].=|8xn@RdwNh#SX\af~1,D\%hu&l.#Cm>?XDx-n~N2TvB Bcyp%h?<852m2H]spl9j0#p\ ;i FX1 $EfF' y;>T 0t#0;F 6T0 d t&+G+B& zFd l+ $Z*:'oO0; ` "FplA|,6@1"h4>HR\W0r$q2 mK(YRD6)^ D~V3.)&# Y\`dg1eEvChi)iCd"bSD5&aHplAP#,4<Emw,X8I1Ur/nN- {U.vcP=*a 2[dD$E.UTRPO @p J 1=JVb+zb?eA_sZAbDvQ,"bv 4H\oP^yJn$4exn]oZ:F}tT4SrxB(o|}V.  -:l]%Mu>~{'}tU;"2t|SUWTRPMy{!tpmuNG@819ApR8Vt$`bdfhzrX>teVHFDB@]zxY;GQcjotzvm @:Zy[X^chn.jJ-^J5& Iq~cH,H^wd$)@P`p,29@GN$GrN)!(HgkP4v0Dg0$9+?DJPUL.MHvP6,D/LcQZL 4$+3< 0 :jWT/&^"n$`J4 d ^  x#, '6E6' 7dz4 n2p> s*g[NB66788dHJ$.9DOZeUE6&UK fpkQ>,]~ulcZ0 M}xtpg 5@K`v~m\XPwPbtr`MGA+n@JRY`htS>RftiLT%@[vn\K<-(rR ?tmf_X^dkq2u+S{eJa7ESaoXB+@&>1$ &A@@?>DINTH{Du;9(nQ&,2% zq-C rcTD5BN:& VL \ MzG)eJ 1)nS8^ .@]u]YU: dNjU$).3X~hFz9 wlb'$7FTcr&eJ0i,/nZb3<FPYHhmb2_WC/H^ b({p;c, $WlN0-N 4>Ir!28\(ob$f.KFr Y4gZs"4F^vX:l!EtI?k.y3\ 0XDLSUVXZNAe<Qv$e _{#x"g)j,,uU<MhH(wNM{jXk@T=aQH'q`O G'{%wKF`%q\F0( O~F|0/lMd0$F0]<TK*0E&]*NR-VF6& >x#XJV!d? j3En#B8*`jw,Mv:y0m>1$ #\D%P_t@j+]=WDt(G/YpN`  qA8.$"c&cp/\q:p 2aJVV>JC^xFl'l:,](a (RhMsLv.S-iJV/Vz ]T y@g~ YERF9$CW n!]6PZ]<w g0*Ot\C@ qam [VX[D,U]G_i+dd*fX:FW#>ZvAenVKzbP; |_B%vi TaXt9pwBi bJr!~-Hb| :KTh62dV dS.CvY6@6'FF~X)oYnuCZ k3 AB0:mnnop\\q"zZivD>3,S\0\`2!^w&@/wg zBHNTZPb6Rw:{5pf~  D}T,ZZ2= t:V*6yL~L*:JZ g|IY>}SXk~9wR,fqP^*R:z\HZ(2;DFa> k)08N'XJVbM)Op]pGt\}S'^&!:dR(DXkE D|3/I.>z. 4VP$lKR r2"Di#[z6l`@voDM|(!5bvr0p-`d94?BDFI<2QErh-pnT!4rI!NzB*57<}*llXFijfa\X8|u]{a(qxnTVtzMp? pdtc~la_:|pd4zxu$zB^zx>Yu}r{$[z?y GvgXJKx~ \xBV-HdQ"Z!"A gA o m,k^QD7M iPmyD!>\zKS~ &?yMw}nX cXL@5I}hTS ":Qi64awt$T$j/ pV J@7.$7nxl6y2 1.H,\x C}P$/>~T+h!p*p0K] Bzc^Xj;8|!%X[,-.lT4R ~;DXll:p q=0#K=T7GXs:TC:1=T0Ne|(++YPf(/b _r8PG2zh(q "h*Qx 8$ JxJ `" 6y m}|feO" Q9" F&6NJ`uh\Ob .>b 54Q)Gd_H"M6> 3KJ`seXMm .;Hj1:[38aEG3 uN7  L+8Lhh"bcL;0R 1D f*FRtJ$<`>5 l B5( jLWfym" LG6(H "8M=Vb#_6 :P*&|U@/[ DYp5RD&F  4IyB`n#R*0W2$n@{- T>Xp6_T9 |'|4t@]c&g@(GZ/$pC{"P@XpM 8vZ- {`j*t 8Xk4tP,9U_-b6p @,Ce'` Gd7vj vD"QpR}V0 ":Slg.X+_t)*YHr*" JtN(s Th>(_e `9,F`{$x>H4fe#3[L>82,&` q8 ~_Db7(`bb>6Rm+|8 x:0c^*b6m(YOD:0f n9 uK0}W/~%b%vwP(@Xq'v2 z3 T^8n 8g&e[RH>r j&^9*{a8.k.(`;Nbu"n$^ R\,hB};uj`UJyf#V)xga<?FBf9K^p^~TyLe%B}M>vh[N@q`wFfZwfDC SFj>N^m}\ tAjB|g*H{MCzl_RDt`uL#nQjvU5M+WEY)h]RF;nbt? ZKikMR*VAe:NatcR g8rj/S#XHtfYL>mT d>fUtvX`7`?\0CVi|^zKq ?ue*R/dQwi[M?lNd7 ^XwrQR*WEc6HYj| PnEd4l_$S<nXq`N=kR g@gSmzZ9N-[Di?O_o`t=V+fm4`9fLuj^SHvY f1L?_dFU2_YZhvPZ$L*hh,W<lVzm`R bh2L?[vqR4L>~%s]iuZ^{6L[$X?{7vcYV 6<]~hM1Q>w$,} ^Zw5:qrtvwDRL-HvSC kp1PpybL6bX;0lvLLj"~3osw{Nd ZRf{h@J@{9*p[q x.\uj_W8*{D O\r.uIXgv`:HF2MxZL{*1^}pcV_P:~E OZr1r6H[n\8RWNMQ`^/DYn_<UT/H}bPspLyndZOVL@T RV f!d+<N`qL(DM9T/v^n^-WND;2PJJl6 :h` bQ 1BR0>XOv- ;|U\N@:4/)R] _ |D @n]T7t(;!Lli>9vGI+v.,*)'a a cMDnN@%d%<!IjdI) C}A2hW l|,k3?c@*z J,N x'@lH$9o-~"o Vi?DM  @`%g ]2t2 f&?NlH$;p%q V>r  u*K_]! (CSJ)p7"j,H\c<5feO1cw0Z hg,,GQG'n *f+Rh\4 "TVA(] =et#b" :WO$fj4Zl"d:2d`D+^ |6ek`"8VU9 Mp8g8xN# 8f T/x @v>j}.F1 $ta> Rx~Q%VBk:0&1RrS*v0h]&n#NlL+ ".:n T-p9^zS+d"Mr@6,":\}[&kUX"m%X|^@!,8CN|HWDnY2j(]_TH=2NjP\ BwNv5w:~]|Ld|xKDNxX]bfk E2o6\z\=J N zk\sL~3o @Xoxl?}B_(hjloqI6r6^vV6vA_2tauEw5t9Qh~re:~@\&uxz|O:u6[wX8r;Ixj\t$X FH^stf8 t8Tnrw|R@z6ZoP0i1D|pc{*] I@Ti~vgY.q5Ofkpv{M0i*Qx{_C'~FP"~oauH{4r <Sjtg<~AY"mprux@{-g.VdH,WW(vcQdv2d$dG`z~R'Tb'ghhhi4n"_-VfJ.We3zhVh{7i%d=XtY.\d(\^_`b-hZ.Yv\A j*i7xdP`p$UL0Kf_6m1|@jfb_[}TE#R{bJh(g5vaM^n~MW<Xt`6 h+r5~VTRPNrVP*VfN=w>{dL5J^s&Z`>Yt`4c&p4ccccc*dP$QgMk*f4r]HYj|MV:Xu`5 i.~C uojd^UHJurX? m0yElXgv(YS-JfW0h+~E ojfa\{PF N{}dKx6q?lXfuHAx:Xw]8u:Fojfa\~VDIwrZB i+r? n[kz#QDz?`h@s4F yvrolH4s;iwpX@v:T#~hu!M9q6Ro|wR-u>`)zriK1l+Wftn]LXr=irz2n$Z:Zy|~eF&`(v;yq :lSDVgx{l^O$j0Nrx~%`I<^gF$g3Gzm_v$YD :M`txj\M"l5_+wz}T>v(Jknrux\?"q?T(zl,]E 8L`u{l^P%j1Ty%\7l Ejpv{fJ/t>X.}.]2i)@Wnxk^Q'n3Z)+b<q!Dfkpty\> h4Q*.[3l.DYnwj^Q&n8f4&Z+_8]bfjoU: n;^6.\4m!6J_tgZNAm4b0S,b9\bhmsX< uEi=%R&^2I`wndZQ)yB p? N'\3W\bhmS9rA kB%S+d,@Uj`VMCJyDOT*MSZ`fO8  S{N"/[$Y !6LbYPG>wFPP T(LSZbiP8 ~PxO&$P| W0E[SLD<Q V#NEx6?HPYE2 SzP',U~Jv+BZTNGAJS$J{Dx<DMV^G0W#_6&MtDr(=SLD<5xHW' (XIz3:AHO;'zNc<(NuFq 4JD>82V'm?" O~ >o%-5=E2 ].yP&,Pt2_(>:63/d8 }M.?j"Q".;G8* sBZ08YGt98887nBU4 2\I|%4CRD5&|JZ-5YEr <>@BD( zM [8/ZAr/@PB4'Qb8 6WCp"?@@@A& xJZ:-U}6g .?PD8, ]-tH%Ds1`:;<=>&^3wR-&Ox2b"3E:.#`1~T):h"R38>CH.\/oM+ Dl$U},>4*!^2^4$@n#Nz!&*\3~\:,Rx%Rv,%f9 ^36PxBl"b<sS3 5Vv7^ ^4 sN9$ #9Ow<d iGdE%  2Pn1Tx sM'dL4 !6Kn$JofEnO0# 8Ur'Jnf=}XC.(hK/$ 'B^z*Lo|X4_L9&(nTJ?4*06=CZp7TqxX9p^K98643@N[h-Kbz{cK, k^RE8ACXl+Fa|kP6lXQJB;FQ\g"?TjzhU9rdUGJLORct:Vr}dK2xbMHB=8ER`m:RizfR7p]J889::Nbu6Rm~fL2mXPH@8BLV`z"@Vk|hT6oaRD69<@CVj~#@\xlR7}fOHB<5?JT^w7PhmZ>"{l\L=@BEHYj{7SolT=%~hRKD>7CO[g;Rhs`F+q`O>>>==N`q *HfzhO6nULB8/8AJSl,D\u}jM0r^J76432DUfx (FdwlT<pWL@5*29@H^t3NjwZ>!taN;9864CRbq7UknV?"gZNA4:?DJ_t-HdhI* |hS>:62.708BLV`w*BZqt`D' zk\MMLLLZgt:VjqX?& md[RINRV[p 'A[un\B( LISTBINFOISFT5GoldWave (C) Chris S. Craig, http://www.goldwave.comgajim-gajim-1.1.3/gajim/data/sounds/sent.wav000066400000000000000000001665361345766322700207330ustar00rootroot00000000000000RIFFVWAVEfmt DXdata  $530.,uj^SH\p2Kd>VP7]4 \VsoB"0=JXp`5 J uI*;Gx|Y10V>4#Ito8j!Df qao: !*4i>H|zd_[]^`bM:&6RmN\8 `qudD2  #0*~zvF8Z|Z>vI;XXXXX"e@ 6s2v<ZxU2r~PM]XK*a=S@-ff-6?HQ2Nr[q  86{,d:tll`4\JR}IJLMNU\.%J9vmd/ c  ?HPXa$kwhsr.]N6ilptw :8 rv{L(t-swz~5Qx]@f ; f F^<dO2.Bd\N>|_BW(O347klllm @ w L ! v rSc0iI6"sFP[fp7?8b(]3;BJRdv_$ G j R : N b w  h < Ok"$%&(oRt08@-HG<~\:2Nj(la'~E  f u L # HT$W~'Zn8P3p3Lf:6DG[i {4Ec3QZ}[ 2 X  & s  \X:rI@&oE%l?.IdBJOU$-fhwL!~6 M z  p  Tri82:!h=l_RTV >T@`KS~4H$6  5 V $ 3 &Z>?gTXlp Gw@ V2\`c,5F4vE*@ W  O M L J H t .H0<x-sGt_'41FZNj.g9HH\"7G  T o P 0  9 b|/Dp(D*Xz sIJ,"7|>7o e.p V 3 A N \ j  j  f:Z(XB*w)F b 4 E ]-xiQ`dM(7, `}Y5d*V\pZ  # ? 6 . &  1 ceY?(b<c(Q e^, (6Dcf PPhd,.j KX3 Z ' e4d8 8d.fid^u'/ |EMU&xX8<_|  {  Y ( to[7U#A_}0ZK$EZ $0\*6ALT LJM @j_T. 6 f f F  -\B-Gg*`uZ`j|h4y/>&`/R vR-T, f h M 1 l+}&+>YeP z\h7zu]KO=+j)xqp!30,-; x \ ? "  a*BW~$x(@&r#|g 8~"b!$&lVFX BUL a W N D : y9>eYjb%cWB,,%xo.)e"Y%m{C3:z; > @ B E  ~<&IJ]JXje,R :8/F XX qJF5W9+h! 1 B R b  u&rDLV9Trl3_$t=i+J:k"H,q\7*~(g# : R j : cMqt@!uq$~5KHDQ"VMsw]>*r]JIV" 2 C T d ' qJbV$xiH l,DNX"V*\X7t$Zr-nO{ 1 B h6U_Ei-o'M*p.jL. `F"u(CHXjAr  $ 4 D  )DWcT* D~H\:DhN4J$j{7Fw1RD5` :SaT**t_zl`Tw sfYL?=;97y?/%+*=;h$ 3Y~j-.,(<&z! y;vbN;72.*e">q m6d;2* Cp|]>!:)ruj SlVAHPW^>6/BVl%6rnN1kmQ54Z@(HM'''6F(u 6_B&Hi FND`I$W$ie`\X7B10 pL(2lOR'8_`;BHOV\VRgKMNPR4VNI>,bL e(U8]6z )Km-q ~H WBFKPT3PVd^B%u0PBx`,5c>t8\*h RTWw"n&1 b+T~L+\&WJeBZ#2c2Vd"X|@|:Yl L2S. @Y'pGX-[HXN}>K PbdU>_.G.r(M)L%o6i@! ,^hZGJ RZH_>Rg.b8J+n4`@!Xk F&pB[$pso,r6TdfDL|2Q|9\RVE$v,HW0j. }R&$!9V$ #V Zb9q4=),/lD pSLE\|K2U`f5-P|Kh( f$d<WWco.[:"rXPh8" @pFOv 1fKXd|~6sNrZ_d4l; vl\~S@.,QvHZ$@y:^m|cJ^Zm EiV|9 yIyUI<0$@\wB[. 1)FcXLT\8\#IXhL0Z7(&.L|dYNC8Mbx4Dvm @r4CRJA,{i.@bp]lB9>Qs = ncXNCVj}(u2lT ]I:,cv_06jlmhd*bHG`@ c\TMFR^kwN hZL{I&6F#VWviF#YO vNJf L=:62/DYn3ncXSNn4*4=S j`8TMVLc(b"b^ZVRfzXz_PAe+ns=Fhh@@ c1keFs0e]UME^vL_;RhtR5n/9_~R'|'~|zyxcN"|^i'p_{ G+lll{Cb|j0.}8np_/Y   {L>]PPwf3b}<_2TN g>mbWLAT }[J8Fn*|Q"CFIJJbz 4-`6}"Y\`dg6`$EN>66\[Z] {4j/p2*"nQ| *8 ;iD\P@/1FMEXQ1LVH2*81)*,P3^#x/SGnldVVdln-l6lG"TdXvc n[OpAlHoZ wpv+UDv[@$$%&&a`Eycipyyq]<V)R|H]Ex( "8n i.jPLHEApVZvPGSvvR,l2$NyGXC2 2`h raQRRRSy@AlG78ING+bn!Nzx3cK SD61,WM^wwvvvZ a}H";B0 r=^"Up_Na9l-4:4.X&kt&/o3d='! S$~1&Y]aeibZRKq :tXdqdVK5L[>k:yzzLk"~0kqv|mXB-b X&Lf~}6objL&Z1wmdZ.Z a8DOZfVE4$eE}Em6j]z. b8xN" CR:v(4@LXA*rCL,`x#6P(u,S)4u8c6rdTE;%^ .AT>)UK"R{(1AX2>tG8Z G_0nSH<;O !6L5Y'F*Zn1Nj<>zM "Hm"^ b*fK.am @x,D/b3V 0Sy 4`ut=H c6DoXOtO*fP V"Z2T;" \*f$Kr ,\ %^\ zLAh7CtL$ ~bBU&T0tEV6Wx3j-p}H|KPqV8 n1>:ptIJ[Fm$H~O>k[K;+;JZj"_GN~lN%Tt12h~uL$O^ Q'@Z ^Q^ pbSD6DRaoN4:gN0~@Z]Nf~lJ(Zt"h+Fa8w^ ik]N@2?LZg;4@kP7GV eUh{~`C%W`L$Cb&`Ljuj`VKYhv$YFTT. y>VL9TohJ,Wf[:HV^[ l{ws}1cZWh5 {[nr]$>XsoT8\shA_}4w&:X*} :iTJVhN lqX8VtcF( @K@0On.u&DvG:^XZp'hM lb9x6Tsg[OC$\%@4| cDjx8T#'Jm2t2SL~IQ*`Ah^TJ@ d4RD7&`!rFa-'JlPN h#@i93|.c<60*$X.db>5xG+Nh5 CfRDOb+X!$s%V$).38f: p"v]O L;b#|G-T|G}4EUr8k XO)-048b3jvcB\NbzO$*OtW>?Mu5KFK % NRf_8tM[ }6tJ6! Fr:q8+R jpns,i ~J\|$sE786QbN:&?bR$pw1ShmdWx N`0%ePCh(HSQ>AXPs\WRMHe'\[JR efbAz:bZ0d'T bISh|tfX8j3`u&.vx(Vh1w|;aH0+~&xm ]&b$Qcv~qcC#r:fv"z(4/Jh>@iZ=. tqbS&<RipbSD$^*^u$0ktJ N=cLw8|P$hG>4*!0@P_z0bb6~Z6} E~AjnU,q3t1h$XPyLsj`VMV_hqDu)j7|Y8Cv'Lrv\Ad/?v2g"[n?dZQH>JVamQ;| T3zG>u(IkxpXA)Oi.v3j&a&Q"xl_S\fpy5fA~BU#f$Z *K\nx`G.T"D6d$j.\.znbr -YP R$g"X*^*:JZjfc`\F1Ow6u5{@NtD2^V OMD,b,>PbdfikWB.p@t:<v8NZ.0]J|0q9|5p >o&<SjjjiiT?*\*H FJ^$d8(Py>w.m)h \9n 0CDDDE5$wDv>TZn6W;9bG}(b a#c,Z|$:::;;)xL Wh(n0~E T41Z Cy.n&aG$[~ .1469+T"Rx@@OeF(  8bJ$[K9t'Nu $'*tJ\$t8F i4`B# "8Mv#T!V>zEu.X  W(\'F Pm6 iL06NtBq By3qS 1Vz%1$ W.s> DN}KsX< $8Kn2`:s$_4g(Py  a8Jd)y>_2nQ4& )>a Kv"[PBu 1Tx  gBtD[j.k=tS3&  ,=No-[/fK*[BktL$j5c/SmAcE6( )8Hm 8f,^<u!R.Sxz_7mDK^-oF^M<+ "3DUf 4`$W6j4` 4]vu_=uDt@{FxJq^L:'%$" 1BSd 3]#W+b5b&H`xp[6pDZ#}J[0s`N<840,TjvbN0{MNU"`3paQMJFBP]jx 3Y?tEv6d,BXmvcO0|P$_+\)pE|l[XVTQ^ly<`H{Dt2a"8NcyxdP=lBR#f6xK}olifcoz+RxHw7j(T ":SlxvbO;pH!k8n= _6rmhd_mz"Gl"R8hKw6Ngr}|jXE3b9`/n@tO0 2W|"Mz2`?j.DQ^lytojeSA/X.Y,uF{W; 6XzBp&T*Su "9DP[fc`^[N@2% lFp@P!]?" *Ih :h%X8b1LV`kunhb[J9(c<Z/W*bE( 8[~It&V1Zz ":@GNTPKFB5( tN(oB`4|^?  #Cc?kL{"Kl,8CNZWTRO>, |X4]/|R(`@ Ad&O|.X Fl)06<CBBA@0 kH%`6 b8 t[B)(Gf?l Mz!Ji&0;EB>:7&lL, g9 f@lN0&8Ur$Lx$Lu7Wx &/-*(& lH$g@rGfL2 %:Xv"Go?j 3Qp#-,,+* iK-yN$zO%fI, 2Nj(*Gd 0Ty:b#Df`<Z0`7nS7%(:Wt )Nt=g8Vs  bB"g?rH'pU?("/F]td={T0 rWH8( %4B\u%Hk*Rx (Gf| pW>%qL&nM, zeP:%$4DVi|,U~Ce8]x lQ6~Y4_8jWD14J`w Fk&Ox6Zr  x]BmH$^7yeP<(  .BVkAf-Sy +Mhx^C!qL(kF"jQ8 4Kbx$Hk)S~2Rl  hL+ zS,^7nXB- -F_xBf 4\3Sm ~eL*tM&fBiS='+?Rfz:_Ad8Rl|cJ* xP(kH%lYF3(",@Tg{<_El B\w v]D"rL'mJ&xbK4(*6H[n8_@d7Rnt[C$|W1gG'v_H>3($,5GZl~0Rs 1V|">ZwqX?#hEkI'kUG:, %.BVk%Fg 0Sv$A^zv]D&dBkI'u]E:/$ (/BTfy2Rs Fk3Le~|fP3uS/ zT/ycRB1 "*2DWj|"@_Bh"=Xst\E) nK&xY9v]RG<1/.,*18?FWhx7Y{:Z{8Rlt\C' qQ- zW4k^PC641.,28?EXl,Hd8\ &@Ynr^I+ qQ/ a?(qbRBCDDEINRVbny&Ed"Df5ObvlU>"uW6mJ.|n`QJD=6;@EJ\n %>Wy.V}0FZovgXH,zZ9uU:znaTPMJFLRX^kx&Ed8Vw #<N_p|kZ@% tR1^>vj]PJD>8>DJP_n} 'C_|Di,CVhzzhVD,`=uU: tdSRPNMWaku )Hf6Qo9JZk|p^L; |`C& eF( pa\VQLQV\ao~0Mi:Xx4EVgxveTB1{\=iM1p`\WRNTZagt *Fc *He8J\nudTD3pQ5mP4zriadhlo~6Rn9Xw0>LYgq|tgVD3"{^? pVL[aflrstuvng`XF5$jL/nT:! ztuvxy-D[z8Ys 3FXkrx~wph`N<+uZ= {bH.|wy|~)@Wn=]x):JZ`gntsrrqjd^WD2  ycG*lV?( $?Zt6Rl-@RY`gnnnnng`ZSD5&z`E*hP9! (B[t+Fb~ 0@JS\fhjlng`ZSD4%t[@% t]F/ 4Jax+E]v$3<ENWVTRQLHC>0#r[C*x`G/ )>Rf~8Rk$5?JT^\[ZXRMHB5(|gO6hR;* *@Uk/Id~*4>GQPONMID@<1&jT=&|fP>,$:Pey4Oj#0<HIJJKHFC@6,!gR=(~hQ?. +@Ul+F`z$0<HMRW\XTOK?3' zbI0hP>, .>Xq-Hb| +6BMRVZ_YSMG<0% iN4{bL5-A\x(AZs&,3:@FLRXVSPNB7, pYB,wZC,$8Kc{.Hb{#/;GMRX^WPHA6*kR8pV@* 5Jc|,BYp  (08@EJPUSQOMB6+ lT;# pWA+&8Kcz)B[t(4?FMT[WSOK=0"lO2wcK4(8Haz0CVj&09>DINMLJI=1% qW=# }gR>)"2AXp $;Ri!*38>DIIJJJ>1$ |`D)u]F. .?Th}.G`t&1468;=@BD<4+#kT=!nZF1 0AVl2Lg|*6;@DIHGFE<2) ~fO8r\F1 -AXn0Jcy (5CEGIKLLLME>6.ydN9 lXD1"5HYj{ 'B]p$38>DIGDB@92+$nYD( wfUD3 &8Pg~(B\q %36:=@?>=<60)#r^J5q\F1 0CVh{ $@[p)2:BKHEB?80)"jT>% ~lZG5$)@Xo&?Yr +2:BIFDA>82,& mXB-s^J5& "4I^r2Ng",5>HD@;7.%t^I3xeR>/  %?Xr.C[r&-4<:875/("xbL7" fK1$ 1EYm7Ph ",78:;<3*  |fQ9" p\H7& "/DXl"7K`t"(../00*$ t]F0t`K:* *9L`s2I`v#(.381*"}hR;$ r^I:,*6H[n 4H[n $%&'("|fP9" |hSB0*6HZk} 2H_u "& t_I4xdOB5( (3>LZiw*=Pcv   s_K6 p^N>/  $0=M^n~&9L`s   p_H2{fTB1-*r`UJ?4( $2?L\l{-?Qcu|jWD0p`TH=1'  #/;GSfx&:OdxxhWF4#tbVK@4*  '6DRbr,BWl  xdO;)rbUH;.# $.9DN`s *=Pdwo\J8'taTHHQZix .@Qcq}m\L<. wk_SKC;3.*% "$&(,037AJT^n}%6HYhvugYK;+ uj^RJB91+& &-482-''&&&.5BFKRY`gs (5CRap~qdXK=. wjbZSKFB=876549>DIS^hr~"1@P[fq|zof\SJ:* |pf\SIEB>:::;;>BFIQZbjt~)6BN[htui^RF7( ymdZQHFC@>>>??BEHKU^hr| .;HT`lxwkaWMC4& sjbYPNLKIHHHGJMPS]gq{&3@NXblv}rg\RG<0# zrjaYVTROOOOOSVZ^gpy,9FQ\hs{zpf[PD9." vnf]ZXURRRSSVZ]`hov~ '6ENXbkrx~ulcWJ>2(xqjfb_[\]^_behkrx~*7BLWbipx~ulcXND9/&|umiea]`behjmprv{ $2<GR\cjpwzrj_TI>4* }vpib\^`acfjmpv{,8DP\cjqxxph\PE9/$|vpkf`abcdhlquz~ ,8DP\dkrz~xqjdYNB7,  zuqmiedcbafjnsz !+6@JU]dltx||vpjdZPE;0$ }ytplllmmrv{'2>IT\dltx|~zrjbZQH>5*  |yvxyz| +6@KT^gptx{}wqke^VNG<1&~zvqmnprsx| )4>IS]gquz~|wrlg`YRK?3' |zxtqnjjjkkqw}'1;ENXbkotx|~~ysnhb]XRMD;2)|xtroljjjiiotz &.6ALXcipv|~xrlfa[QH>4' ~zvqmkhfdddddjpv|%.8BLVakrx~xoh`YRI@6- ~xspmjghijkry #*06=FNV_hpx{umd\TJ?4*zvqpponnmllpty}%0;FPZelt||tj`WMB8.#|xsstttttuuy|&.7>FNU]emuy~ytnh`YRJB:1) ~&1:DMV]dlswz~zuph_VNG@92*!}zxvsvxz}  ,8?FNU\dkrx~zuqi`XPH@80' ~{xuwxz|~"+3;CKRZbinsx}~~~}|yvtqjb[TKB:1)"}zwvvvuvwxy~)2;DMTZ`gmrx~zvrlf_YPG>5,"|xyz{|!+4>GPW^elrw|~{xvutrjaXPF<2( )4>ITY^bglpty{~~}{wsokd]VOF>6-& *2;DLSZ`gmrx~~}zxurnjg`ZTME<4,# #,6@IOU[adhknpruwvtsrmhc^XSNH?6.% !*2:AINRV[_cgknqtwusqojfb]YUQMF>70& &0:DLSZbehlorvy|{zxwrmhc^YTOF<3*  '07>FMRX]behjmortvtsrpkfb]XRMHA:4-$ '.6>FNV^chmrtuvxwvutplie_YSME<4,# &.6>FNU\dgjmpqrrsttuvrmhd]VNG@92+# "+29@GNU\chmrwwvvvtsrpkfa\VPJD>70*! !*2;DLSZbfilpppqqrrstpmjf`ZSMF>70'  (.4:@GNU\`dgklnoponnmjfb_ZTNIC<60'   '.4<DKSWZ^bcddefhjkjjjic]WQKE?92+$   '.4;AHNTZ_djlorttsrroljgc^ZVOHB;2*" !(08>DKQW]cikmoqqrrrpnlje`ZUNF>70*#   (1:?DINSX^chlqvvvvvspliea]YRJC<4,%  "+4:@FLRX^dgjmpnligfdba^\YVNF=5.& "+4:?DJMPRUZ`ejjjiifda^ZWTPJD?92,% $+28?FLRY_cfjnmljihfdca`^\UNG@6-$   *4:AHNRUX\`dgklnopmjgd^XSMG@:4.("$*06<BHNSY\_bedba`]ZXUTRPOJFB=4,$  &.7@HQTWZ]^`abdfhjhfdb\WRLF@;50*$ #*16<BGLQV[^adgffedb`][WSOKFB=80(!  '.5<DKNPSVWXZ[]^`ba``_ZTOJFB=93,&  &-39?EINRVX[^`bdegd`\YUQMIFB?<4,#   &,3:@EJNSUVXZ[\]^]\\[XTQNHB<6.'   ")06=BFJOTX\acegifdb_\XTQLHC>70(! ")06=DINRWZ\^abbbccccc_[WSMGA;5.(" !)/4:@FMTZ]`cfffeedba`\YVRLGB<60*$ %+17?FNVX[^```__`abc`]ZWOG?71*$   (-28=CHNTWZ]`bcdfdba_[VRNID>92,& "',27<BHMQTX\]^_``_^^\YVTPLHD=6/("&.5<AFKPTX\`bdgihhgfc`]ZTNGA;4.( &-4;@DINRUX\^_`ba`^]ZWTQKE?92+$  !(.5:@EJNRW[\\]^]\\[XVTQLF@;4.(!   '.5<@EJNQTX[]^`b_\ZWTQNKFB>92*# %,3:=@DGKNRVXZ]_\ZXURNKHEB>;5.("&,37:>BFILPSVZ][ZXVSPNKHD@=82-(   $,37;?CFHJMORTVVVUURPNKHDA>82+%  "(/4:?DFHJLMNPQQRRRPNLJGD@=84/*#$*06<CIMPTXZ\_a``_^ZWTPLHD@:4/)!  "(/5:@FKNQTWXYZ[[ZZZXURPKF@;60+&  $*05:@EGIKMOPRTTUVVSPNKFB=82-(" %*.37;?CGKOSTTUVVUTTQNKHC>:5/)# #(,16:>CFJNQQPPPPPPPNLKID@;60+&   $(-159=BFKPQRTUUTTTRPOMHD?:4.'! #(,048=BHMOQSUTTSRQPONID?:2+$  #(,16:>BFJLORTTSRROLJGB>:5/)#  %+049>DINTUVXYWTRPNMLJGD@=60*#  "(/6:=@DFGHJLNOQPPONLJHFB>:61,&!  "&+.269<@DGHJLMLJHGEB@><;:83.*%  &+06;=>@BDGJLMNOPNKHFB>:61,'"  #(-27:=@CFILONNMLIFDA?=;94.(#  "',27:=@CEGIKLLMNLJHFB?<83.*%   &,/258;>BEHJMPPQRRPNKIFC@=940,%  #(.49<@CFGHHIJJKLJHGEA>:62-($  "',05:>ADHJLMOOPPPMJHEB>;840-)" #)/38<@CFJMNNOPPQRRPNMKFB>952.*#$(-26;@DHKOPPQRRQPPNMLJFB?;62.)" "(-16:>ADHKLNPQQQQQOMKID>83-("   $).26:>BFIMNNOPONNMJHEB>:73.)$   $(-159=ADHLOPPPQONLJHFCA=951,&!  &,26:>BEHJMNOPQONLJHFCA>;850+&!  #(.48<AEGHJLMNOPONLKHEB?<841+%  $+147:=?BDFILORPNMKGD@<:864.(#  &,37<@DFGHJLNPRRQPPNKHFB>;70*$ "(.37:>BEHJMOPRTRPOMID@<:853.("  ")049>BDEFHJKLNNNNNJGD@<840,'" !&,158<@BEHJJJJJJJJJFB>:62-)%"  #(-28=@BDGFDCBBBBB@?><84/+($   %*.38<?BDGIJLNNMLLIFC@<72.+($!  "&*-159=@DHKJJJIHGFEDB@?;840*$  $*.27;=?ACEFHJJIHHEB>;840-($   !%),/259=AEEEEEC@><;:9840-)$  LISTBINFOISFT5GoldWave (C) Chris S. Craig, http://www.goldwave.comgajim-gajim-1.1.3/gajim/data/style/000077500000000000000000000000001345766322700170475ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/style/default-dark.css000066400000000000000000000005511345766322700221250ustar00rootroot00000000000000.gajim-incoming-nickname { color: rgb(207, 49, 47) } .gajim-outgoing-nickname { color: rgb(38, 139, 210) } .gajim-url { color: rgb(53, 132, 228) } .gajim-highlight-message { color: rgb(245, 121, 0) } .gajim-msg-correcting text { background: rgb(131, 148, 150) } .gajim-status-message { color: rgb(115, 210, 22) } gajim-gajim-1.1.3/gajim/data/style/default.css000066400000000000000000000010431345766322700212030ustar00rootroot00000000000000 .gajim-incoming-nickname { color: rgb(164, 0, 0) } .gajim-outgoing-nickname { color: rgb(52, 101, 164) } .gajim-outgoing-message-text { color: rgb(85, 87, 83) } .gajim-status-message { color: rgb(78, 154, 6) } .gajim-url { color: rgb(32, 74, 135) } .gajim-highlight-message { color: rgb(255, 128, 128) } .gajim-restored-message { color: rgb(85, 87, 83) } .gajim-roster-disconnected { background: rgb(171 ,97 ,97) } .gajim-roster-connected { background: rgb(173, 195, 198) } gajim-gajim-1.1.3/gajim/data/style/gajim-dark.css000066400000000000000000000000471345766322700215700ustar00rootroot00000000000000/* Gajim Dark Application CSS File */ gajim-gajim-1.1.3/gajim/data/style/gajim.css000066400000000000000000000167211345766322700206570ustar00rootroot00000000000000/* Gajim Application CSS File */ .gajim-state-composing { color: rgb(0, 139, 0) } .gajim-state-inactive { color: rgb(158, 158, 158) } .gajim-state-gone { color: rgb(128, 128, 128) } .gajim-state-paused { color: rgb(0, 0, 205) } .gajim-msg-correcting text { background: rgb(238, 232, 170) } .gajim-state-tab-muc-directed-msg { color: rgb(238, 0, 0) } .gajim-state-tab-muc-msg { color: rgb(0, 0, 205) } .gajim-banner { font-size: 13pt; font-weight: 700 } .chatcontrol-actionbar-button { padding: 0px 5px 0px 5px; background-color: @theme_base_color; border: none; } .scrolled-no-border {border: none} .no-scroll-indicator undershoot.top, undershoot.bottom { background-image: none; } .scrollbar-style scrollbar trough {background-color:@theme_base_color; } .scrollbar-style scrollbar {border:none; } .scrollbar-style slider {min-width: 3px; background-color: #a0a3a4} .actionbar-no-border box {border: none} .actionbar-no-border button { padding: 0px; background-color: @theme_base_color; border: none; background-image: none; } .dialog-margin > box { margin: 18px;} #MessageWindow, #RosterWindow paned { background-color: @theme_base_color; } .chatcontrol-separator-top {margin-top: 5px;} .chatcontrol-separator {margin-bottom: 5px;} #SubjectPopover box { padding: 10px; } /* VCardWindow */ .VCard-GtkLinkButton { padding-left: 5px; border-left: none; } /* Emoticon Popover */ popover#EmoticonPopover button { background: none; border: none; box-shadow:none; padding: 0px;} popover#EmoticonPopover button > label { font-size: 24px; } popover#EmoticonPopover flowboxchild > label { font-size: 24px; } popover#EmoticonPopover flowboxchild { padding-top: 5px; padding-bottom: 5px; } popover#EmoticonPopover scrolledwindow { border: none; } popover#EmoticonPopover { padding: 5px; background-color: @theme_unfocused_base_color} .emoji-chooser-heading { font-size: 13px; font-weight: bold; padding: 5px;} .emoji-chooser-flowbox { padding-left: 5px; padding-right: 11px; } .emoji-modifier-chooser-flowbox { padding-left: 5px; } /* HistorySyncAssistant */ #HistorySyncAssistant list { border: 1px solid; border-color: @borders; } #HistorySyncAssistant progressbar text { color: #000; font-size: 18px; padding: 10px;} #HistorySyncAssistant list > row { padding: 10px 30px 10px 30px; } #HistorySyncAssistant list > row > label { color: @insensitive_fg_color } #HistorySyncAssistant list > row.activatable > label { color: @theme_text_color; } #HistorySyncAssistant list > row.activatable:selected > label { color: @theme_selected_fg_color; } #FinishedLabel { font-size: 14px; font-weight: bold } /* Server Info */ #ServerInfoGrid > list { border: 1px solid; border-color: @borders; } #ServerInfoGrid > list > row:first-child { border-top: 1px solid; border-color: @borders; } #ServerInfoGrid > list > row { padding: 10px 20px 10px 10px; } #ServerInfoGrid > list > label { padding:10px; color: @insensitive_fg_color; font-weight: bold; } #ServerInfoGrid > list > row.activatable:active { box-shadow: none; } /* OptionsBox */ #OptionsBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; } #OptionsBox > row:last-child { border-bottom: 0px} #OptionsBox > row.activatable:active { box-shadow: none; } #OptionsBox > row { padding: 10px 20px 10px 10px; } #OptionsBox > row:not(.activatable) label { color: @insensitive_fg_color } /* GenericOption */ #SubDescription { color: @insensitive_fg_color;} #GenericOptionBox { margin-left: 30px; } #GenericOptionBox > label { padding-right: 3px; } /* Generic Popover Menu with Buttons */ .PopoverButtonListbox { padding-left: 0px; padding-right: 0px; } .PopoverButtonListbox > list { margin-top: 10px; margin-bottom: 10px; } .PopoverButtonListbox > list > row { padding: 10px 20px 10px 20px; } .PopoverButtonListbox > list > row.activatable:active { box-shadow: none; background-color: @theme_selected_bg_color } /* Settings ListBox */ list.settings { border: @borders 1px solid; } list.settings > row:not(:last-child) { border-bottom: @theme_unfocused_bg_color 1px solid; } list.settings row { min-height: 52px; } list.settings > row > box { margin: 6px 18px; } /* Accounts Window */ #AccountsWindow > box > stack { padding:30px 30px 30px 30px;} #AccountsWindow scrolledwindow {border: none;} #AccountsWindow stack list {border: 1px solid; border-color: @borders;} #AccountsWindow > box > box { border-right: 1px solid; border-color: @borders; } .account-list > row { padding: 20px 20px 20px 10px; } /* StartChatListBox */ #StartChatListBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; } #StartChatListBox > row:last-child { border-bottom: 0px} #StartChatListBox > row.activatable:active { box-shadow: none; } #StartChatListBox > row { padding: 10px 20px 10px 10px; } #StartChatListBox > row:not(.activatable) label { color: @insensitive_fg_color } /* Popover Treeview */ .popover_treeview { border-radius: 3px; background-color: @theme_bg_color; } .popover_treeview { padding: 6px; } .popover_treeview :hover { background-color: @theme_selected_bg_color; } /* .inline-toolbar linked from top */ .ontop-bar { border-width: 1px; border-bottom: none; border-radius: 3px 3px 0 0; padding: 5px; } /* Container with buttons linked from below */ .linked-up * { border-top: none; border-top-left-radius: 0; border-top-right-radius: 0; } /* Highlighted label */ .tagged { background-color: @theme_selected_bg_color; color: @theme_selected_fg_color; padding: 0 3px; margin: 0 -3px; border-radius: 3px; text-shadow: none; opacity: 0.95; } /* ThemesWindow */ #ThemesWindow grid { padding: 12px; } .theme_listbox row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; padding: 5px 10px 5px 10px;} .theme_listbox row:last-child { border-bottom: 0px} .theme_listbox row.activatable:active { box-shadow: none; } .theme_listbox row:not(.activatable) label { color: @insensitive_fg_color } .theme_listbox row:focus { outline: none; } .theme_listbox row:hover { background-color: @theme_base_color } .theme_remove_button { background-color: @theme_base_color; border: none; background-image: none; } .theme_remove_button:focus {outline: none;} .theme_popover_listbox { padding: 10px; } .theme_popover_listbox row { padding: 5px; } .theme_popover_listbox row:focus { outline: none; } /* Text style */ .bold { font-weight: bold; } .bold16 { font-size: 16px; font-weight: bold; } .bold24 { font-size: 24px; font-weight: bold; } .large-header { font-size: 20px; font-weight: bold; } .status-away { color: #ff8533;} .status-dnd { color: #e62e00;} .status-online { color: #66bf10;} /* Padding/Margins */ .margin-top6 { margin-top: 6px; } /* Treeview */ treeview.space { padding: 6px; } /* GtkLinkButton style */ button.flat.link { padding: 0; border: 0; } /*MessageWindow Notebook*/ .notebook-tab-label {min-width: 80px} /*SendFileDialog*/ #SendFileDialog grid {padding: 12px} #SendFileDialog grid list { background-color: @theme_bg_color} /*Icon colors*/ .success-color { color: @success_color; } .error-color { color: @error_color; } .warning-color { color: @warning_color; } /*Encryption*/ .encrypted-color { color: rgb(75, 181, 67) } .unencrypted-color { color: @error_color } /*Dataforms*/ .field-fixed { font-size: 16px; font-weight: bold; padding-top:5px;} .data-form-title { font-size: 16px; font-weight: bold; } .data-form-widget scrolledwindow { border: 1px solid; border-color:@unfocused_borders; } .data-form-widget treeview { padding: 5px; } gajim-gajim-1.1.3/gajim/dataforms_widget.py000066400000000000000000000653221345766322700207030ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2006 Tomasz Melcer # Copyright (C) 2006-2007 Jean-Marie Traissard # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . ''' This module contains widget that can display data form (XEP-0004). Words single and multiple refers here to types of data forms: single means these with one record of data (without element), multiple - these which may contain more data (with element).''' import itertools import base64 from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import GObject from gi.repository import GLib from gajim import gtkgui_helpers from gajim.common.modules import dataforms from gajim.common import helpers from gajim.common import app from gajim.common.i18n import _ class DataFormWidget(Gtk.Alignment): # "public" interface """ Data Form widget. Use like any other widget """ __gsignals__ = dict(validated=( GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, ())) def __init__(self, dataformnode=None): ''' Create a widget. ''' GObject.GObject.__init__(self, xscale=1.0, yscale=1.0) self._data_form = None self.selectable = False self.clean_cb = None self.xml = gtkgui_helpers.get_gtk_builder('data_form_window.ui', 'data_form_vbox') self.xml.connect_signals(self) for name in ('instructions_label', 'instructions_hseparator', 'single_form_viewport', 'data_form_types_notebook', 'single_form_scrolledwindow', 'multiple_form_hbox', 'records_treeview', 'buttons_vbox', 'add_button', 'remove_button', 'edit_button', 'up_button', 'down_button', 'clear_button'): self.__dict__[name] = self.xml.get_object(name) self.add(self.xml.get_object('data_form_vbox')) if dataformnode is not None: self.set_data_form(dataformnode) selection = self.records_treeview.get_selection() selection.connect('changed', self.on_records_selection_changed) selection.set_mode(Gtk.SelectionMode.MULTIPLE) def on_data_form_vbox_key_press_event(self, widget, event): print('key pressed') def set_data_form(self, dataform): """ Set the data form (nbxmpp.DataForm) displayed in widget """ assert isinstance(dataform, dataforms.DataForm) self.del_data_form() self._data_form = dataform if isinstance(dataform, dataforms.SimpleDataForm): self.build_single_data_form() else: self.build_multiple_data_form() # create appropriate description for instructions field if there isn't any if dataform.instructions == '': self.instructions_label.set_no_show_all(True) self.instructions_label.hide() else: self.instructions_label.set_text(dataform.instructions) gtkgui_helpers.label_set_autowrap(self.instructions_label) def get_data_form(self): """ Data form displayed in the widget or None if no form """ return self._data_form def del_data_form(self): self.clean_data_form() self._data_form = None data_form = property(get_data_form, set_data_form, del_data_form, 'Data form presented in a widget') def get_title(self): """ Get the title of data form. If no title or no form, returns ''. Useful for setting window title """ if self._data_form is not None: if self._data_form.title is not None: return self._data_form.title return '' title = property(get_title, None, None, 'Data form title') def show(self): ''' Treat 'us' as one widget. ''' self.show_all() # "private" methods # we have actually two different kinds of data forms: one is a simple form to fill, # second is a table with several records; def empty_method(self): pass def clean_data_form(self): """ Remove data about existing form. This metod is empty, because it is rewritten by build_*_data_form, according to type of form which is actually displayed """ if self.clean_cb: self.clean_cb() def build_single_data_form(self): '''Invoked when new single form is to be created.''' assert isinstance(self._data_form, dataforms.SimpleDataForm) self.clean_data_form() self.singleform = SingleForm(self._data_form, selectable=self.selectable) def _on_validated(widget): self.emit('validated') self.singleform.connect('validated', _on_validated) self.singleform.show() self.single_form_viewport.add(self.singleform) self.data_form_types_notebook.set_current_page( self.data_form_types_notebook.page_num( self.single_form_scrolledwindow)) self.clean_cb = self.clean_single_data_form def clean_single_data_form(self): """ Called as clean_data_form, read the docs of clean_data_form(). Remove form from widget """ self.singleform.destroy() self.clean_cb = None # we won't call it twice del self.singleform def build_multiple_data_form(self): """ Invoked when new multiple form is to be created """ assert isinstance(self._data_form, dataforms.MultipleDataForm) self.clean_data_form() # creating model for form... fieldtypes = [] fieldvars = [] for field in self._data_form.reported.iter_fields(): # note: we store also text-private and hidden fields, # we just do not display them. # TODO: boolean fields #elif field.type_=='boolean': fieldtypes.append(bool) fieldtypes.append(str) fieldvars.append(field.var) self.multiplemodel = Gtk.ListStore(*fieldtypes) # moving all data to model for item in self._data_form.iter_records(): iter_ = self.multiplemodel.append() for field in item.iter_fields(): if field.var in fieldvars: self.multiplemodel.set_value(iter_, fieldvars.index(field.var), field.value) # constructing columns... for field, counter in zip(self._data_form.reported.iter_fields(), itertools.count()): self.records_treeview.append_column( Gtk.TreeViewColumn(field.label, Gtk.CellRendererText(), text=counter)) self.records_treeview.set_model(self.multiplemodel) self.records_treeview.show_all() self.data_form_types_notebook.set_current_page( self.data_form_types_notebook.page_num( self.multiple_form_hbox)) self.clean_cb = self.clean_multiple_data_form readwrite = self._data_form.type_ != 'result' if not readwrite: self.buttons_vbox.set_no_show_all(True) self.buttons_vbox.hide() else: self.buttons_vbox.set_no_show_all(False) # refresh list look self.refresh_multiple_buttons() def clean_multiple_data_form(self): """ Called as clean_data_form, read the docs of clean_data_form(). Remove form from widget """ self.clean_cb = None # we won't call it twice del self.multiplemodel def refresh_multiple_buttons(self): """ Checks for treeview state and makes control buttons sensitive """ selection = self.records_treeview.get_selection() model = self.records_treeview.get_model() count = selection.count_selected_rows() if count == 0: self.remove_button.set_sensitive(False) self.edit_button.set_sensitive(False) self.up_button.set_sensitive(False) self.down_button.set_sensitive(False) elif count == 1: self.remove_button.set_sensitive(True) self.edit_button.set_sensitive(True) _, (path,) = selection.get_selected_rows() iter_ = model.get_iter(path) if model.iter_next(iter_) is None: self.up_button.set_sensitive(True) self.down_button.set_sensitive(False) elif path == (0, ): self.up_button.set_sensitive(False) self.down_button.set_sensitive(True) else: self.up_button.set_sensitive(True) self.down_button.set_sensitive(True) else: self.remove_button.set_sensitive(True) self.edit_button.set_sensitive(True) self.up_button.set_sensitive(False) self.down_button.set_sensitive(False) if not model: self.clear_button.set_sensitive(False) else: self.clear_button.set_sensitive(True) def on_clear_button_clicked(self, widget): self.records_treeview.get_model().clear() def on_remove_button_clicked(self, widget): selection = self.records_treeview.get_selection() model, rowrefs = selection.get_selected_rows() # rowref is a list of paths for index, _path in enumerate(rowrefs): rowrefs[index] = Gtk.TreeRowReference.new(model, rowrefs[index]) # rowref is a list of row references; need to convert because we will # modify the model, paths would change for rowref in rowrefs: del model[rowref.get_path()] def on_up_button_clicked(self, widget): selection = self.records_treeview.get_selection() model, (path,) = selection.get_selected_rows() iter_ = model.get_iter(path) # constructing path for previous iter previter = model.get_iter((path[0]-1,)) model.swap(iter_, previter) self.refresh_multiple_buttons() def on_down_button_clicked(self, widget): selection = self.records_treeview.get_selection() model, (path,) = selection.get_selected_rows() iter_ = model.get_iter(path) nextiter = model.iter_next(iter_) model.swap(iter_, nextiter) self.refresh_multiple_buttons() def on_records_selection_changed(self, widget): self.refresh_multiple_buttons() class SingleForm(Gtk.Table): """ Widget that represent DATAFORM_SINGLE mode form. Because this is used not only to display single forms, but to form input windows of multiple-type forms, it is in another class """ __gsignals__ = dict(validated=( GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, ()) ) def __init__(self, dataform, selectable=False): assert isinstance(dataform, dataforms.SimpleDataForm) GObject.GObject.__init__(self) self.set_col_spacings(12) self.set_row_spacings(6) def decorate_with_tooltip(widget, field): """ Adds a tooltip containing field's description to a widget. Creates EventBox if widget doesn't have its own gdk window. Returns decorated widget """ if field.description != '': if not widget.get_window(): #if widget.flags() & Gtk.NO_WINDOW: evbox = Gtk.EventBox() evbox.add(widget) widget = evbox widget.set_tooltip_text(field.description) return widget self._data_form = dataform # building widget linecounter = 0 # is the form changeable? readwrite = dataform.type_ != 'result' # for each field... for field in self._data_form.iter_fields(): if field.type_ == 'hidden': continue commonlabel = True commonlabelcenter = False commonwidget = True widget = None if field.type_ == 'boolean': commonlabelcenter = True widget = Gtk.CheckButton() widget.connect('toggled', self.on_boolean_checkbutton_toggled, field) widget.set_active(field.value) elif field.type_ == 'fixed': leftattach = 1 rightattach = 2 if field.label is None: commonlabel = False leftattach = 0 commonwidget = False widget = Gtk.Label(label=field.value) widget.set_property('selectable', selectable) widget.set_line_wrap(True) self.attach(widget, leftattach, rightattach, linecounter, linecounter + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) elif field.type_ == 'list-single': # TODO: What if we have radio buttons and non-required field? # TODO: We cannot deactivate them all... if len(field.options) < 6: # 5 option max: show radiobutton widget = Gtk.VBox() first_radio = None for value, label in field.iter_options(): if not label: label = value radio = Gtk.RadioButton.new_with_label_from_widget( first_radio, label) radio.connect('toggled', self.on_list_single_radiobutton_toggled, field, value) if first_radio is None: first_radio = radio if field.value == '': # TODO: is None when done field.value = value if value == field.value: radio.set_active(True) widget.pack_start(radio, False, True, 0) else: # more than 5 options: show combobox def on_list_single_combobox_changed(combobox, f): iter_ = combobox.get_active_iter() if iter_: model = combobox.get_model() f.value = model[iter_][1] else: f.value = '' widget = gtkgui_helpers.create_combobox(field.options, field.value) widget.connect('changed', on_list_single_combobox_changed, field) widget.set_sensitive(readwrite) elif field.type_ == 'list-multi': # TODO: When more than few choices, make a list if len(field.options) < 6: # 5 option max: show checkbutton widget = Gtk.VBox() for value, label in field.iter_options(): check = Gtk.CheckButton(label=label, use_underline=False) check.set_active(value in field.values) check.connect('toggled', self.on_list_multi_checkbutton_toggled, field, value) widget.pack_start(check, False, True, 0) widget.set_sensitive(readwrite) else: # more than 5 options: show combobox def on_list_multi_treeview_changed(selection, field_): def for_selected(treemodel, _path, iter_): vals.append(treemodel[iter_][1]) vals = [] selection.selected_foreach(for_selected) field_.values = vals[:] widget = Gtk.ScrolledWindow() widget.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) tv = gtkgui_helpers.create_list_multi(field.options, field.values) widget.add(tv) widget.set_size_request(-1, 120) tv.get_selection().connect('changed', on_list_multi_treeview_changed, field) tv.set_sensitive(readwrite) elif field.type_ == 'jid-single': widget = Gtk.Entry() widget.connect('changed', self.on_text_single_entry_changed, field) widget.set_text(field.value) elif field.type_ == 'jid-multi': commonwidget = False xml = gtkgui_helpers.get_gtk_builder('data_form_window.ui', 'multiple_form_hbox') widget = xml.get_object('multiple_form_hbox') treeview = xml.get_object('records_treeview') listmodel = Gtk.ListStore(str) for value in field.iter_values(): # nobody will create several megabytes long stanza listmodel.insert(999999, (value,)) treeview.set_model(listmodel) renderer = Gtk.CellRendererText() renderer.set_property('editable', True) renderer.connect('edited', self.on_jid_multi_cellrenderertext_edited, treeview, listmodel, field) treeview.append_column(Gtk.TreeViewColumn(None, renderer, text=0)) decorate_with_tooltip(treeview, field) add_button = xml.get_object('add_button') add_button.connect('clicked', self.on_jid_multi_add_button_clicked, treeview, listmodel, field) edit_button = xml.get_object('edit_button') edit_button.connect('clicked', self.on_jid_multi_edit_button_clicked, treeview) remove_button = xml.get_object('remove_button') remove_button.connect('clicked', self.on_jid_multi_remove_button_clicked, treeview, field) clear_button = xml.get_object('clear_button') clear_button.connect('clicked', self.on_jid_multi_clean_button_clicked, listmodel, field) if not readwrite: add_button.set_no_show_all(True) edit_button.set_no_show_all(True) remove_button.set_no_show_all(True) clear_button.set_no_show_all(True) widget.set_sensitive(readwrite) self.attach(widget, 1, 2, linecounter, linecounter+1) del xml elif field.type_ == 'text-private': commonlabelcenter = True widget = Gtk.Entry() widget.connect('changed', self.on_text_single_entry_changed, field) widget.set_visibility(False) widget.set_text(field.value) elif field.type_ == 'text-multi': # TODO: bigger text view commonwidget = False textwidget = Gtk.TextView() textwidget.set_wrap_mode(Gtk.WrapMode.WORD) textwidget.get_buffer().connect('changed', self.on_text_multi_textbuffer_changed, field) textwidget.get_buffer().set_text(field.value) if readwrite: textwidget.set_sensitive(True) else: if selectable: textwidget.set_editable(True) else: textwidget.set_sensitive(False) widget = Gtk.ScrolledWindow() widget.add(textwidget) widget = decorate_with_tooltip(widget, field) self.attach(widget, 1, 2, linecounter, linecounter+1) else: # field.type_ == 'text-single' or field.type_ is nonstandard: # JEP says that if we don't understand some type, we # should handle it as text-single commonlabelcenter = True if readwrite: widget = Gtk.Entry() def kpe(widget, event): if event.keyval == Gdk.KEY_Return or \ event.keyval == Gdk.KEY_KP_Enter: self.emit('validated') widget.connect('key-press-event', kpe) widget.connect('changed', self.on_text_single_entry_changed, field) widget.set_sensitive(readwrite) if field.value is None: field.value = '' widget.set_text(field.value) else: commonwidget = False widget = Gtk.Label(label=field.value) widget.set_property('selectable', selectable) widget.set_sensitive(True) widget.set_halign(Gtk.Align.START) widget.set_valign(Gtk.Align.CENTER) widget = decorate_with_tooltip(widget, field) self.attach(widget, 1, 2, linecounter, linecounter+1, yoptions=Gtk.AttachOptions.FILL) if commonlabel and field.label is not None: label = Gtk.Label(label=field.label) if commonlabelcenter: label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.CENTER) else: label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) label = decorate_with_tooltip(label, field) self.attach(label, 0, 1, linecounter, linecounter+1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) if field.media is not None: for uri in field.media.uris: if uri.type_.startswith('image/'): try: img_data = base64.b64decode(uri.uri_data) pixbuf_l = GdkPixbuf.PixbufLoader() pixbuf_l.write(img_data) pixbuf_l.close() media = Gtk.Image.new_from_pixbuf(pixbuf_l.\ get_pixbuf()) except Exception: media = Gtk.Label(label=_('Unable to load image')) else: media = Gtk.Label(label=_('Media type not supported: %s') % \ uri.type_) linecounter += 1 self.attach(media, 0, 1, linecounter, linecounter+1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) if commonwidget: assert widget is not None widget.set_sensitive(readwrite) widget = decorate_with_tooltip(widget, field) self.attach(widget, 1, 2, linecounter, linecounter+1, yoptions=Gtk.AttachOptions.FILL) if field.required: label = Gtk.Label(label='*') label.set_tooltip_text(_('This field is required')) self.attach(label, 2, 3, linecounter, linecounter+1, xoptions=0, yoptions=0) linecounter += 1 if self.get_property('visible'): self.show_all() def show(self): # simulate that we are one widget self.show_all() def on_boolean_checkbutton_toggled(self, widget, field): field.value = widget.get_active() def on_list_single_radiobutton_toggled(self, widget, field, value): field.value = value def on_list_multi_checkbutton_toggled(self, widget, field, value): # TODO: make some methods like add_value and remove_value if widget.get_active() and value not in field.values: field.values += [value] elif not widget.get_active() and value in field.values: field.values = [v for v in field.values if v != value] def on_text_single_entry_changed(self, widget, field): field.value = widget.get_text() def on_text_multi_textbuffer_changed(self, widget, field): field.value = widget.get_text(widget.get_start_iter(), widget.get_end_iter(), True) def on_jid_multi_cellrenderertext_edited(self, cell, path, newtext, treeview, model, field): old = model[path][0] if old == newtext: return try: newtext = helpers.parse_jid(newtext) except helpers.InvalidFormat as s: app.interface.raise_dialog('invalid-jid-with-error', str(s)) return if newtext in field.values: app.interface.raise_dialog('jid-in-list') GLib.idle_add(treeview.set_cursor, path) return model[path][0] = newtext values = field.values values[values.index(old)] = newtext field.values = values def on_jid_multi_add_button_clicked(self, widget, treeview, model, field): #Default jid jid = _('new@jabber.id') if jid in field.values: i = 1 while _('new%d@jabber.id') % i in field.values: i += 1 jid = _('new%d@jabber.id') % i iter_ = model.insert(999999, (jid,)) treeview.set_cursor(model.get_path(iter_), treeview.get_column(0), True) field.values = field.values + [jid] def on_jid_multi_edit_button_clicked(self, widget, treeview): model, iter_ = treeview.get_selection().get_selected() assert iter_ is not None treeview.set_cursor(model.get_path(iter_), treeview.get_column(0), True) def on_jid_multi_remove_button_clicked(self, widget, treeview, field): selection = treeview.get_selection() deleted = [] def remove(model, path, iter_, deleted): deleted += model[iter_] model.remove(iter_) selection.selected_foreach(remove, deleted) field.values = (v for v in field.values if v not in deleted) def on_jid_multi_clean_button_clicked(self, widget, model, field): model.clear() del field.values gajim-gajim-1.1.3/gajim/dev/000077500000000000000000000000001345766322700155545ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/dev/__init__.py000066400000000000000000000000001345766322700176530ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/dev/ipython_view.py000066400000000000000000000614011345766322700206540ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2008-2014 Yann Leboulanger # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # # Copyright (c) 2007, IBM Corporation # All rights reserved. ## Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ## * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ## * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ## * Neither the name of the IBM Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ Provides IPython console widget @author: Eitan Isaacson @organization: IBM Corporation @copyright: Copyright (c) 2007 IBM Corporation @license: BSD All rights reserved. This program and the accompanying materials are made available under the terms of the BSD which accompanies this distribution, and is available at U{http://www.opensource.org/licenses/bsd-license.php} """ import re import sys import os from io import StringIO from functools import reduce from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject from gi.repository import GLib from gi.repository import Pango try: import IPython except ImportError: IPython = None HAS_IPYTHON5 = True try: from pygments.token import Token from IPython.core.displayhook import DisplayHook from IPython.core.display_trap import DisplayTrap class MyPromptDisplayHook(DisplayHook): def __init__(self, shell, view): DisplayHook.__init__(self, shell=shell) self.view = view def write_output_prompt(self): tokens = self.shell.prompts.out_prompt_tokens() self.view.write('\n') self.view.write(tokens) except Exception: HAS_IPYTHON5 = False class IterableIPShell: """ Create an IPython instance. Does not start a blocking event loop, instead allow single iterations. This allows embedding in GTK+ without blockage @ivar IP: IPython instance. @type IP: IPython.iplib.InteractiveShell @ivar iter_more: Indicates if the line executed was a complete command, or we should wait for more. @type iter_more: integer @ivar history_level: The place in history where we currently are when pressing up/down. @type history_level: integer @ivar complete_sep: Seperation delimeters for completion function. @type complete_sep: _sre.SRE_Pattern """ def __init__(self, argv=None, user_ns=None, user_global_ns=None, cin=None, cout=None, cerr=None, input_func=None): """ @param argv: Command line options for IPython @type argv: list @param user_ns: User namespace. @type user_ns: dictionary @param user_global_ns: User global namespace. @type user_global_ns: dictionary. @param cin: Console standard input. @type cin: IO stream @param cout: Console standard output. @type cout: IO stream @param cerr: Console standard error. @type cerr: IO stream @param input_func: Replacement for builtin raw_input() @type input_func: function """ if argv is None: argv = [] io = IPython.utils.io if input_func: if IPython.version_info[0] >= 1: IPython.terminal.interactiveshell.raw_input_original = input_func else: IPython.frontend.terminal.interactiveshell.raw_input_original = input_func if cin: io.stdin = io.IOStream(cin) if cout: io.stdout = io.IOStream(cout) if cerr: io.stderr = io.IOStream(cerr) # This is to get rid of the blockage that accurs during # IPython.Shell.InteractiveShell.user_setup() io.raw_input = lambda x: None os.environ['TERM'] = 'dumb' excepthook = sys.excepthook if IPython.version_info[0] >= 5: from traitlets.config.loader import Config else: from IPython.config.loader import Config cfg = Config() cfg.InteractiveShell.colors = "Linux" # InteractiveShell's __init__ overwrites io.stdout,io.stderr with # sys.stdout, sys.stderr, this makes sure they are right old_stdout, old_stderr = sys.stdout, sys.stderr sys.stdout, sys.stderr = io.stdout.stream, io.stderr.stream # InteractiveShell inherits from SingletonConfigurable so use instance() if IPython.version_info[0] >= 1: self.IP = IPython.terminal.embed.InteractiveShellEmbed.instance(config=cfg, user_ns=user_ns, user_module=user_global_ns) else: self.IP = IPython.frontend.terminal.embed.InteractiveShellEmbed.instance(config=cfg, user_ns=user_ns) sys.stdout, sys.stderr = old_stdout, old_stderr self.IP.system = lambda cmd: self.shell(self.IP.var_expand(cmd), header='IPython system call: ', local_ns=user_ns) #global_ns=user_global_ns) #verbose=self.IP.rc.system_verbose) self.IP.raw_input = input_func sys.excepthook = excepthook self.iter_more = 0 self.history_level = 0 self.complete_sep = re.compile(r'[\s\{\}\[\]\(\)]') self.updateNamespace({'exit':lambda: None}) self.updateNamespace({'quit':lambda: None}) #self.IP.readline_startup_hook(self.IP.pre_readline) # Workaround for updating namespace with sys.modules # self.__update_namespace() def __update_namespace(self): ''' Update self.IP namespace for autocompletion with sys.modules ''' for k, v in sys.modules.items(): if not '.' in k: self.IP.user_ns.update({k:v}) def execute(self): """ Execute the current line provided by the shell object """ self.history_level = 0 orig_stdout = sys.stdout sys.stdout = IPython.utils.io.stdout orig_stdin = sys.stdin sys.stdin = IPython.utils.io.stdin self.prompt = self.generatePrompt(self.iter_more) self.IP.hooks.pre_prompt_hook() if self.iter_more: try: self.prompt = self.generatePrompt(True) except Exception: self.IP.showtraceback() if self.IP.autoindent: self.IP.rl_do_indent = True try: line = self.IP.raw_input(self.prompt) except KeyboardInterrupt: self.IP.write('\nKeyboardInterrupt\n') self.IP.input_splitter.reset() except Exception: self.IP.showtraceback() else: self.IP.input_splitter.push(line) self.iter_more = self.IP.input_splitter.push_accepts_more() self.prompt = self.generatePrompt(self.iter_more) if not self.iter_more: if IPython.version_info[0] >= 2: source_raw = self.IP.input_splitter.raw_reset() else: source_raw = self.IP.input_splitter.source_raw_reset()[1] self.IP.run_cell(source_raw, store_history=True) self.IP.rl_do_indent = False else: # TODO: Auto-indent # self.IP.rl_do_indent = True sys.stdout = orig_stdout sys.stdin = orig_stdin def generatePrompt(self, is_continuation): ''' Generate prompt depending on is_continuation value @param is_continuation @type is_continuation: boolean @return: The prompt string representation @rtype: string ''' # Backwards compatibility with ipyton-0.11 # ver = IPython.__version__ if '0.11' in ver: prompt = self.IP.hooks.generate_prompt(is_continuation) else: # Prompt for IPython >=5.0: if hasattr(self.IP, 'prompts'): if is_continuation: prompt = self.IP.prompts.continuation_prompt_tokens(self.IP.prompts) else: prompt = self.IP.prompts.in_prompt_tokens(self.IP.prompts) # Prompt for IPython < 5.0 elif hasattr(self.IP, 'prompt_manager'): if is_continuation: prompt = self.IP.prompt_manager.render('in2') else: prompt = self.IP.prompt_manager.render('in') return prompt def historyBack(self): """ Provide one history command back @return: The command string. @rtype: string """ self.history_level -= 1 return self._getHistory() def historyForward(self): """ Provide one history command forward @return: The command string. @rtype: string """ self.history_level += 1 return self._getHistory() def _getHistory(self): """ Get the command string of the current history level @return: Historic command string. @rtype: string """ try: rv = self.IP.user_ns['In'][self.history_level].strip('\n') except IndexError: self.history_level = 0 rv = '' return rv def updateNamespace(self, ns_dict): """ Add the current dictionary to the shell namespace @param ns_dict: A dictionary of symbol-values. @type ns_dict: dictionary """ self.IP.user_ns.update(ns_dict) def complete(self, line): """ Returns an auto completed line and/or possibilities for completion @param line: Given line so far. @type line: string @return: Line completed as for as possible, and possible further completions. @rtype: tuple """ split_line = self.complete_sep.split(line) if split_line[-1]: possibilities = self.IP.complete(split_line[-1]) else: completed = line possibilities = ['', []] if possibilities: def _commonPrefix(str1, str2): ''' Reduction function. returns common prefix of two given strings. @param str1: First string. @type str1: string @param str2: Second string @type str2: string @return: Common prefix to both strings. @rtype: string ''' for i in range(len(str1)): if not str2.startswith(str1[:i+1]): return str1[:i] return str1 if possibilities[1]: common_prefix = reduce(_commonPrefix, possibilities[1]) or line[-1] completed = line[:-len(split_line[-1])]+common_prefix else: completed = line else: completed = line return completed, possibilities[1] class ConsoleView(Gtk.TextView): """ Specialized text view for console-like workflow @cvar ANSI_COLORS: Mapping of terminal colors to X11 names. @type ANSI_COLORS: dictionary @ivar text_buffer: Widget's text buffer. @type text_buffer: Gtk.TextBuffer @ivar color_pat: Regex of terminal color pattern @type color_pat: _sre.SRE_Pattern @ivar mark: Scroll mark for automatic scrolling on input. @type mark: Gtk.TextMark @ivar line_start: Start of command line mark. @type line_start: Gtk.TextMark """ ANSI_COLORS = {'0;30': 'Black', '0;31': 'Red', '0;32': 'Green', '0;33': 'Brown', '0;34': 'Blue', '0;35': 'Purple', '0;36': 'Cyan', '0;37': 'LightGray', '1;30': 'DarkGray', '1;31': 'DarkRed', '1;32': 'SeaGreen', '1;33': 'Yellow', '1;34': 'LightBlue', '1;35': 'MediumPurple', '1;36': 'LightCyan', '1;37': 'White'} def __init__(self): """ Initialize console view """ GObject.GObject.__init__(self) self.override_font(Pango.FontDescription('Mono')) self.set_cursor_visible(True) self.text_buffer = self.get_buffer() self.mark = self.text_buffer.create_mark('scroll_mark', self.text_buffer.get_end_iter(), False) for code in self.ANSI_COLORS: self.text_buffer.create_tag(code, foreground=self.ANSI_COLORS[code], weight=700) self.text_buffer.create_tag('0') self.text_buffer.create_tag('notouch', editable=False) self.color_pat = re.compile(r'\x01?\x1b\[(.*?)m\x02?') if HAS_IPYTHON5: self.style_dict = { Token.Prompt: '0;32', Token.PromptNum: '1;32', Token.OutPrompt: '0;31', Token.OutPromptNum: '1;31', } self.line_start = \ self.text_buffer.create_mark('line_start', self.text_buffer.get_end_iter(), True) self.connect('key-press-event', self.onKeyPress) def write(self, text, editable=False): if isinstance(text, str): GLib.idle_add(self._write, text, editable) elif IPython.version_info[0] >= 5: GLib.idle_add(self._write5, text, editable) def _write5(self, text, editable=False): """ Write given text to buffer @param text: Text to append. @type text: list of (token: string) @param editable: If true, added text is editable. @type editable: boolean """ start_mark = self.text_buffer.create_mark(None, self.text_buffer.get_end_iter(), True) for token, segment in text: tag = self.style_dict[token] self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(), segment, tag) if not editable: self.text_buffer.apply_tag_by_name('notouch', self.text_buffer.get_iter_at_mark(start_mark), self.text_buffer.get_end_iter()) self.text_buffer.delete_mark(start_mark) self.scroll_mark_onscreen(self.mark) def _write(self, text, editable=False): """ Write given text to buffer @param text: Text to append. @type text: string @param editable: If true, added text is editable. @type editable: boolean """ if isinstance(text, list) and IPython.version_info[0] >= 5: self._write5(text, editable) return segments = self.color_pat.split(text) segment = segments.pop(0) start_mark = self.text_buffer.create_mark(None, self.text_buffer.get_end_iter(), True) self.text_buffer.insert(self.text_buffer.get_end_iter(), segment) if segments: ansi_tags = self.color_pat.findall(text) for tag in ansi_tags: i = segments.index(tag) self.text_buffer.insert_with_tags_by_name(self.text_buffer.get_end_iter(), segments[i+1], str(tag)) segments.pop(i) if not editable: self.text_buffer.apply_tag_by_name('notouch', self.text_buffer.get_iter_at_mark(start_mark), self.text_buffer.get_end_iter()) self.text_buffer.delete_mark(start_mark) self.scroll_mark_onscreen(self.mark) def showPrompt(self, prompt): GLib.idle_add(self._showPrompt, prompt) def _showPrompt(self, prompt): """ Print prompt at start of line @param prompt: Prompt to print. @type prompt: string """ self._write(prompt) self.text_buffer.move_mark(self.line_start, self.text_buffer.get_end_iter()) def changeLine(self, text): GLib.idle_add(self._changeLine, text) def _changeLine(self, text): """ Replace currently entered command line with given text @param text: Text to use as replacement. @type text: string """ iter_ = self.text_buffer.get_iter_at_mark(self.line_start) iter_.forward_to_line_end() self.text_buffer.delete(self.text_buffer.get_iter_at_mark(self.line_start), iter_) self._write(text, True) def getCurrentLine(self): """ Get text in current command line @return: Text of current command line. @rtype: string """ rv = self.text_buffer.get_slice( self.text_buffer.get_iter_at_mark(self.line_start), self.text_buffer.get_end_iter(), False) return rv def showReturned(self, text): GLib.idle_add(self._showReturned, text) def _showReturned(self, text): """ Show returned text from last command and print new prompt @param text: Text to show. @type text: string """ iter_ = self.text_buffer.get_iter_at_mark(self.line_start) iter_.forward_to_line_end() self.text_buffer.apply_tag_by_name( 'notouch', self.text_buffer.get_iter_at_mark(self.line_start), iter_) self._write('\n'+text) if text: self._write('\n') self._showPrompt(self.prompt) self.text_buffer.move_mark(self.line_start, self.text_buffer.get_end_iter()) self.text_buffer.place_cursor(self.text_buffer.get_end_iter()) if self.IP.rl_do_indent: indentation = self.IP.input_splitter.indent_spaces * ' ' self.text_buffer.insert_at_cursor(indentation) def onKeyPress(self, _widget, event): """ Key press callback used for correcting behavior for console-like interfaces. For example 'home' should go to prompt, not to beginning of line @param widget: Widget that key press occurred in. @type widget: Gtk.Widget @param event: Event object @type event: Gdk.Event @return: Return True if event should not trickle. @rtype: boolean """ insert_mark = self.text_buffer.get_insert() insert_iter = self.text_buffer.get_iter_at_mark(insert_mark) selection_mark = self.text_buffer.get_selection_bound() selection_iter = self.text_buffer.get_iter_at_mark(selection_mark) start_iter = self.text_buffer.get_iter_at_mark(self.line_start) if event.keyval == Gdk.KEY_Home: if event.get_state() == 0: self.text_buffer.place_cursor(start_iter) return True if event.get_state() == Gdk.ModifierType.SHIFT_MASK: self.text_buffer.move_mark(insert_mark, start_iter) return True if event.keyval == Gdk.KEY_Left: insert_iter.backward_cursor_position() if not insert_iter.editable(True): return True elif not event.string: pass elif start_iter.compare(insert_iter) <= 0 and \ start_iter.compare(selection_iter) <= 0: pass elif start_iter.compare(insert_iter) > 0 and \ start_iter.compare(selection_iter) > 0: self.text_buffer.place_cursor(start_iter) elif insert_iter.compare(selection_iter) < 0: self.text_buffer.move_mark(insert_mark, start_iter) elif insert_iter.compare(selection_iter) > 0: self.text_buffer.move_mark(selection_mark, start_iter) return self.onKeyPressExtend(event) def onKeyPressExtend(self, event): """ For some reason we can't extend onKeyPress directly (bug #500900) """ pass class IPythonView(ConsoleView, IterableIPShell): ''' Sub-class of both modified IPython shell and L{ConsoleView} this makes a GTK+ IPython console. ''' def __init__(self): """ Initialize. Redirect I/O to console """ ConsoleView.__init__(self) self.cout = StringIO() IterableIPShell.__init__(self, cout=self.cout, cerr=self.cout, input_func=self.raw_input) if HAS_IPYTHON5: displayhook = MyPromptDisplayHook(shell=self.IP, view=self) self.IP.displayhook = displayhook self.IP.display_trap = DisplayTrap(hook=displayhook) # self.connect('key_press_event', self.keyPress) self.interrupt = False self.execute() self.prompt = self.generatePrompt(False) self.cout.truncate(0) self.showPrompt(self.prompt) def prompt_for_code(self): # IPython 5.0 calls prompt_for_code instead of raw_input return self.raw_input(self) def raw_input(self, _prompt=''): """ Custom raw_input() replacement. Get's current line from console buffer @param prompt: Prompt to print. Here for compatibility as replacement. @type prompt: string @return: The current command line text. @rtype: string """ if self.interrupt: self.interrupt = False raise KeyboardInterrupt return self.getCurrentLine() def onKeyPressExtend(self, event): """ Key press callback with plenty of shell goodness, like history, autocompletions, etc @param widget: Widget that key press occurred in. @type widget: Gtk.Widget @param event: Event object. @type event: Gdk.Event @return: True if event should not trickle. @rtype: boolean """ if event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == 99: self.interrupt = True self._processLine() return True if event.keyval == Gdk.KEY_Return: self._processLine() return True if event.keyval == Gdk.KEY_Up: self.changeLine(self.historyBack()) return True if event.keyval == Gdk.KEY_Down: self.changeLine(self.historyForward()) return True if event.keyval == Gdk.KEY_Tab: if not self.getCurrentLine().strip(): return False completed, possibilities = self.complete(self.getCurrentLine()) if len(possibilities) > 1: slice_ = self.getCurrentLine() self.write('\n') for symbol in possibilities: self.write(symbol+'\n') self.showPrompt(self.prompt) self.changeLine(completed or slice_) return True def _processLine(self): """ Process current command line """ self.history_pos = 0 self.execute() rv = self.cout.getvalue() if rv: rv = rv.strip('\n') self.showReturned(rv) self.cout.truncate(0) self.cout.seek(0) gajim-gajim-1.1.3/gajim/dialog_messages.py000066400000000000000000000140601345766322700204770ustar00rootroot00000000000000# Copyright (C) 2017 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from collections import namedtuple from gi.repository import GLib from gajim.common.app import app from gajim.common.i18n import _ from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import InformationDialog Message = namedtuple('Message', ['title', 'text', 'dialog']) messages = { 'start-chat-not-connected': Message( _('You are not connected to the server'), _('You can not start a new conversation unless you are connected.'), ErrorDialog), 'invalid-jid-with-error': Message( _('Invalid JID'), '%s', ErrorDialog), 'invalid-jid': Message( _('Invalid JID'), _('It is not possible to send a message ' 'to %s, this JID is not valid.'), ErrorDialog), 'unread-events-on-remove-account': Message( _('Unread events'), _('Read all pending events before removing this account.'), ErrorDialog), 'connected-on-disable-account': Message( _('You are currently connected to the server'), _('To disable the account, you must be disconnected.'), ErrorDialog), 'invalid-form': Message( _('Invalid Form'), _('The form is not filled correctly.'), ErrorDialog), 'join-while-invisible': Message( _('Invisible'), _('You cannot join a group chat while you are invisible'), ErrorDialog), 'not-connected-while-sending': Message( _('A connection is not available'), _('Your message can not be sent until you are connected.'), ErrorDialog), 'jid-in-list': Message( _('JID already in list'), _('The JID you entered is already in the list. Choose another one.'), ErrorDialog), 'invalid-answer': Message( _('Invalid answer'), _('Transport %(name)s answered wrongly to ' 'register request: %(error)s'), ErrorDialog), 'invalid-custom-hostname': Message( _('Wrong Custom Hostname'), _('Wrong custom hostname "%s". Ignoring it.'), ErrorDialog), 'privacy-list-error': Message( _('Error while removing privacy list'), _('Privacy list %s has not been removed. ' 'It is maybe active in one of your connected resources. ' 'Deactivate it and try again.'), ErrorDialog), 'invisibility-not-supported': Message( _('Invisibility not supported'), _('Account %s doesn\'t support invisibility.'), ErrorDialog), 'unregister-error': Message( _('Unregister failed'), _('Unregistration with server %(server)s failed: %(error)s'), ErrorDialog), 'agent-register-success': Message( _('Registration succeeded'), _('Registration with agent %s succeeded'), InformationDialog), 'agent-register-error': Message( _('Registration failed'), _('Registration with agent %(agent)s failed with error %(error)s: ' '%(error_msg)s'), ErrorDialog), 'unable-join-groupchat': Message( _('Unable to join Groupchat'), '%s', ErrorDialog), 'gstreamer-error': Message( _('GStreamer error'), _('Error: %(error)s\nDebug: %(debug)s'), ErrorDialog), 'wrong-host': Message( _('Wrong host'), _('Invalid local address? :-O'), ErrorDialog), 'avahi-error': Message( _('Avahi error'), _('%s\nLink-local messaging might not work properly.'), ErrorDialog), 'request-upload-slot-error': Message( _('Could not request upload slot'), '%s', ErrorDialog), 'request-upload-slot-error2': Message( _('Could not request upload slot'), _('Got unexpected response from server (see log)'), ErrorDialog), 'open-file-error': Message( _('Could not open file'), _('Exception raised while opening file (see log)'), ErrorDialog), 'open-file-error2': Message( _('Could not open file'), '%s', ErrorDialog), 'unsecure-error': Message( _('Unsecure'), _('Server returned unsecure transport (HTTP)'), ErrorDialog), 'httpupload-response-error': Message( _('Could not upload file'), _('HTTP response code from server: %s'), ErrorDialog), 'httpupload-error': Message( _('Upload Error'), '%s', ErrorDialog), 'httpupload-encryption-not-available': Message( _('Encryption Error'), _('For the chosen encryption there is no encryption method available'), ErrorDialog), 'avatar-upload-error': Message( _('Avatar upload failed'), '%s', ErrorDialog), } def get_dialog(dialog_name, *args, **kwargs): message = messages.get(dialog_name, None) if message is None: raise ValueError('Dialog %s does not exist' % dialog_name) # Set transient window transient_for = kwargs.get('transient_for', None) if transient_for is None: transient_for = app.get_active_window() else: del kwargs['transient_for'] if args: message_text = message.text % args elif kwargs: message_text = message.text % kwargs else: message_text = message.text dialog = message.dialog(message.title, GLib.markup_escape_text(message_text), transient_for=transient_for) return dialog gajim-gajim-1.1.3/gajim/dialogs.py000066400000000000000000002156431345766322700170050ustar00rootroot00000000000000# Copyright (C) 2003-2005 Vincent Hanquez # Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Alex Mauer # Copyright (C) 2005-2006 Dimitur Kirov # Travis Shirk # Copyright (C) 2005-2008 Nikos Kouremenos # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # Copyright (C) 2007-2008 Brendan Taylor # Julien Pivotto # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Dict # pylint: disable=unused-import from typing import List # pylint: disable=unused-import from typing import Tuple # pylint: disable=unused-import import os import logging from random import randrange from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gajim import gtkgui_helpers from gajim import vcard from gajim import dataforms_widget from gajim.common import ged from gajim.common.i18n import _ from gajim.common.const import ACTIVITIES from gajim.common.const import MOODS from gajim.common import app from gajim.common import helpers from gajim.common import i18n from gajim.common.modules import dataforms from gajim.common.exceptions import GajimGeneralException # Compat with Gajim 1.0.3 for plugins from gajim.gtk.dialogs import * from gajim.gtk.add_contact import AddNewContactWindow from gajim.gtk.util import get_builder log = logging.getLogger('gajim.dialogs') class EditGroupsDialog: """ Class for the edit group dialog window """ def __init__(self, list_): """ list_ is a list of (contact, account) tuples """ self.xml = gtkgui_helpers.get_gtk_builder('edit_groups_dialog.ui') self.dialog = self.xml.get_object('edit_groups_dialog') self.dialog.set_transient_for(app.interface.roster.window) self.list_ = list_ self.changes_made = False self.treeview = self.xml.get_object('groups_treeview') if len(list_) == 1: contact = list_[0][0] self.xml.get_object('nickname_label').set_markup( _('Contact name: %s') % contact.get_shown_name()) self.xml.get_object('jid_label').set_markup( _('JID: %s') % contact.jid) else: self.xml.get_object('nickname_label').set_no_show_all(True) self.xml.get_object('nickname_label').hide() self.xml.get_object('jid_label').set_no_show_all(True) self.xml.get_object('jid_label').hide() self.xml.connect_signals(self) self.init_list() self.dialog.show_all() if self.changes_made: for (contact, account) in self.list_: app.connections[account].update_contact(contact.jid, contact.name, contact.groups) def on_edit_groups_dialog_response(self, widget, response_id): if response_id == Gtk.ResponseType.CLOSE: self.dialog.destroy() def remove_group(self, group): """ Remove group group from all contacts and all their brothers """ for (contact, account) in self.list_: app.interface.roster.remove_contact_from_groups(contact.jid, account, [group]) # FIXME: Ugly workaround. # pylint: disable=undefined-loop-variable app.interface.roster.draw_group(_('General'), account) def add_group(self, group): """ Add group group to all contacts and all their brothers """ for (contact, account) in self.list_: app.interface.roster.add_contact_to_groups(contact.jid, account, [group]) # FIXME: Ugly workaround. # Maybe we haven't been in any group (defaults to General) # pylint: disable=undefined-loop-variable app.interface.roster.draw_group(_('General'), account) def on_add_button_clicked(self, widget): group = self.xml.get_object('group_entry').get_text() if not group: return # Do not allow special groups if group in helpers.special_groups: return # check if it already exists model = self.treeview.get_model() iter_ = model.get_iter_first() while iter_: if model.get_value(iter_, 0) == group: return iter_ = model.iter_next(iter_) self.changes_made = True model.append((group, True, False)) self.add_group(group) self.init_list() # Re-draw list to sort new item def group_toggled_cb(self, cell, path): self.changes_made = True model = self.treeview.get_model() if model[path][2]: model[path][2] = False model[path][1] = True else: model[path][1] = not model[path][1] group = model[path][0] if model[path][1]: self.add_group(group) else: self.remove_group(group) def init_list(self): store = Gtk.ListStore(str, bool, bool) self.treeview.set_model(store) for column in self.treeview.get_columns(): # Clear treeview when re-drawing self.treeview.remove_column(column) accounts = [] # Store groups in a list so we can sort them and the number of contacts in # it groups = {} for (contact, account) in self.list_: if account not in accounts: accounts.append(account) for g in app.groups[account].keys(): if g in groups: continue groups[g] = 0 c_groups = contact.groups for g in c_groups: groups[g] += 1 group_list = [] # Remove special groups if they are empty for group in groups: if group not in helpers.special_groups or groups[group] > 0: group_list.append(group) group_list.sort() for group in group_list: iter_ = store.append() store.set(iter_, 0, group) # Group name if groups[group] == 0: store.set(iter_, 1, False) else: store.set(iter_, 1, True) if groups[group] == len(self.list_): # all contacts are in this group store.set(iter_, 2, False) else: store.set(iter_, 2, True) column = Gtk.TreeViewColumn(_('Group')) column.set_expand(True) self.treeview.append_column(column) renderer = Gtk.CellRendererText() column.pack_start(renderer, True) column.add_attribute(renderer, 'text', 0) column = Gtk.TreeViewColumn(_('In the group')) column.set_expand(False) self.treeview.append_column(column) renderer = Gtk.CellRendererToggle() column.pack_start(renderer, True) renderer.set_property('activatable', True) renderer.connect('toggled', self.group_toggled_cb) column.add_attribute(renderer, 'active', 1) column.add_attribute(renderer, 'inconsistent', 2) class PassphraseDialog: """ Class for Passphrase dialog """ def __init__(self, titletext, labeltext, checkbuttontext=None, ok_handler=None, cancel_handler=None, transient_for=None): self.xml = gtkgui_helpers.get_gtk_builder('passphrase_dialog.ui') self.window = self.xml.get_object('passphrase_dialog') self.passphrase_entry = self.xml.get_object('passphrase_entry') self.passphrase = -1 self.window.set_title(titletext) self.xml.get_object('message_label').set_text(labeltext) self.ok = False self.cancel_handler = cancel_handler self.ok_handler = ok_handler okbutton = self.xml.get_object('ok_button') okbutton.connect('clicked', self.on_okbutton_clicked) cancelbutton = self.xml.get_object('cancel_button') cancelbutton.connect('clicked', self.on_cancelbutton_clicked) self.xml.connect_signals(self) if transient_for is None: transient_for = app.app.get_active_window() self.window.set_transient_for(transient_for) self.window.show_all() self.check = bool(checkbuttontext) checkbutton = self.xml.get_object('save_passphrase_checkbutton') if self.check: checkbutton.set_label(checkbuttontext) else: checkbutton.hide() def on_okbutton_clicked(self, widget): if not self.ok_handler: return passph = self.passphrase_entry.get_text() if self.check: checked = self.xml.get_object('save_passphrase_checkbutton').\ get_active() else: checked = False self.ok = True self.window.destroy() if isinstance(self.ok_handler, tuple): self.ok_handler[0](passph, checked, *self.ok_handler[1:]) else: self.ok_handler(passph, checked) def on_cancelbutton_clicked(self, widget): self.window.destroy() def on_passphrase_dialog_destroy(self, widget): if self.cancel_handler and not self.ok: self.cancel_handler() class ChooseGPGKeyDialog: """ Class for GPG key dialog """ def __init__(self, title_text, prompt_text, secret_keys, on_response, selected=None, transient_for=None): '''secret_keys : {keyID: userName, ...}''' self.on_response = on_response xml = gtkgui_helpers.get_gtk_builder('choose_gpg_key_dialog.ui') self.window = xml.get_object('choose_gpg_key_dialog') self.window.set_title(title_text) self.window.set_transient_for(transient_for) self.keys_treeview = xml.get_object('keys_treeview') prompt_label = xml.get_object('prompt_label') prompt_label.set_text(prompt_text) model = Gtk.ListStore(str, str) model.set_sort_func(1, self.sort_keys) model.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.keys_treeview.set_model(model) #columns renderer = Gtk.CellRendererText() self.keys_treeview.insert_column_with_attributes(-1, _('KeyID'), renderer, text=0) col = self.keys_treeview.get_column(0) col.set_sort_column_id(0) renderer = Gtk.CellRendererText() self.keys_treeview.insert_column_with_attributes(-1, _('Contact name'), renderer, text=1) col = self.keys_treeview.get_column(1) col.set_sort_column_id(1) self.keys_treeview.set_search_column(1) self.fill_tree(secret_keys, selected) self.window.connect('response', self.on_dialog_response) self.window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.window.show_all() def sort_keys(self, model, iter1, iter2, data=None): value1 = model[iter1][1] value2 = model[iter2][1] if value1 == _('None'): return -1 if value2 == _('None'): return 1 if value1 < value2: return -1 return 1 def on_dialog_response(self, dialog, response): selection = self.keys_treeview.get_selection() (model, iter_) = selection.get_selected() if iter_ and response == Gtk.ResponseType.OK: keyID = [model[iter_][0], model[iter_][1]] else: keyID = None self.on_response(keyID) self.window.destroy() def fill_tree(self, list_, selected): model = self.keys_treeview.get_model() for keyID in list_.keys(): iter_ = model.append((keyID, list_[keyID])) if keyID == selected: path = model.get_path(iter_) self.keys_treeview.set_cursor(path) class ChangeActivityDialog: PAGELIST = [ 'doing_chores', 'drinking', 'eating', 'exercising', 'grooming', 'having_appointment', 'inactive', 'relaxing', 'talking', 'traveling', 'working'] def __init__(self, on_response, activity_=None, subactivity_=None, text=''): self.on_response = on_response self.activity = activity_ self.subactivity = subactivity_ self.text = text self.xml = gtkgui_helpers.get_gtk_builder('change_activity_dialog.ui') self.window = self.xml.get_object('change_activity_dialog') self.window.set_transient_for(app.interface.roster.window) self.checkbutton = self.xml.get_object('enable_checkbutton') self.notebook = self.xml.get_object('notebook') self.entry = self.xml.get_object('description_entry') rbtns = {} group = None for category in ACTIVITIES: item = self.xml.get_object(category + '_image') item.set_from_pixbuf( gtkgui_helpers.load_activity_icon(category).get_pixbuf()) item.set_tooltip_text(ACTIVITIES[category]['category']) vbox = self.xml.get_object(category + '_vbox') vbox.set_border_width(5) # Other act = category + '_other' if group: rbtns[act] = Gtk.RadioButton() rbtns[act].join_group(group) else: rbtns[act] = group = Gtk.RadioButton() icon = gtkgui_helpers.load_activity_icon(category, self.activity) hbox = Gtk.HBox(homogeneous=False, spacing=5) hbox.pack_start(icon, False, False, 0) lbl = Gtk.Label( label='%s' % ACTIVITIES[category]['category']) lbl.set_use_markup(True) hbox.pack_start(lbl, False, False, 0) rbtns[act].add(hbox) rbtns[act].connect( 'toggled', self.on_rbtn_toggled, [category, 'other']) vbox.pack_start(rbtns[act], False, False, 0) activities = list(ACTIVITIES[category].keys()) activities.sort() for activity in activities: if activity == 'category': continue act = category + '_' + activity if group: rbtns[act] = Gtk.RadioButton() rbtns[act].join_group(group) else: rbtns[act] = group = Gtk.RadioButton() icon = gtkgui_helpers.load_activity_icon(category, activity) label = Gtk.Label(label=ACTIVITIES[category][activity]) hbox = Gtk.HBox(homogeneous=False, spacing=5) hbox.pack_start(icon, False, False, 0) hbox.pack_start(label, False, False, 0) rbtns[act].connect( 'toggled', self.on_rbtn_toggled, [category, activity]) rbtns[act].add(hbox) vbox.pack_start(rbtns[act], False, False, 0) self.default_radio = rbtns['doing_chores_other'] if self.activity in ACTIVITIES: if not self.subactivity in ACTIVITIES[self.activity]: self.subactivity = 'other' rbtns[self.activity + '_' + self.subactivity].set_active(True) self.checkbutton.set_active(True) self.notebook.set_sensitive(True) self.entry.set_sensitive(True) self.notebook.set_current_page( self.PAGELIST.index(self.activity)) self.entry.set_text(text) else: self.checkbutton.set_active(False) self.xml.connect_signals(self) self.window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.window.show_all() def on_enable_checkbutton_toggled(self, widget): self.notebook.set_sensitive(widget.get_active()) self.entry.set_sensitive(widget.get_active()) if not self.activity: self.default_radio.set_active(True) def on_rbtn_toggled(self, widget, data): if widget.get_active(): self.activity = data[0] self.subactivity = data[1] def on_ok_button_clicked(self, widget): """ Return activity and messsage (None if no activity selected) """ if self.checkbutton.get_active(): self.on_response( self.activity, self.subactivity, self.entry.get_text()) else: self.on_response(None, None, '') self.window.destroy() def on_cancel_button_clicked(self, widget): self.window.destroy() class ChangeMoodDialog: COLS = 11 def __init__(self, on_response, mood_=None, text=''): self.on_response = on_response self.mood = mood_ self.text = text self.xml = gtkgui_helpers.get_gtk_builder('change_mood_dialog.ui') self.window = self.xml.get_object('change_mood_dialog') self.window.set_transient_for(app.interface.roster.window) self.window.set_title(_('Set Mood')) table = self.xml.get_object('mood_icons_table') self.label = self.xml.get_object('mood_label') self.entry = self.xml.get_object('description_entry') no_mood_button = self.xml.get_object('no_mood_button') no_mood_button.set_mode(False) no_mood_button.connect('clicked', self.on_mood_button_clicked, None) x = 1 y = 0 self.mood_buttons = {} # Order them first self.MOODS = [] for mood in MOODS: self.MOODS.append(mood) self.MOODS.sort() for mood in self.MOODS: self.mood_buttons[mood] = Gtk.RadioButton() self.mood_buttons[mood].join_group(no_mood_button) self.mood_buttons[mood].set_mode(False) self.mood_buttons[mood].add(gtkgui_helpers.load_mood_icon(mood)) self.mood_buttons[mood].set_relief(Gtk.ReliefStyle.NONE) self.mood_buttons[mood].set_tooltip_text(MOODS[mood]) self.mood_buttons[mood].connect('clicked', self.on_mood_button_clicked, mood) table.attach(self.mood_buttons[mood], x, y, 1, 1) # Calculate the next position x += 1 if x >= self.COLS: x = 0 y += 1 if self.mood in MOODS: self.mood_buttons[self.mood].set_active(True) self.label.set_text(MOODS[self.mood]) self.entry.set_sensitive(True) if self.text: self.entry.set_text(self.text) else: self.label.set_text(_('None')) self.entry.set_text('') self.entry.set_sensitive(False) self.xml.connect_signals(self) self.window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.window.show_all() def on_mood_button_clicked(self, widget, data): if data: self.label.set_text(MOODS[data]) self.entry.set_sensitive(True) else: self.label.set_text(_('None')) self.entry.set_text('') self.entry.set_sensitive(False) self.mood = data def on_ok_button_clicked(self, widget): '''Return mood and messsage (None if no mood selected)''' message = self.entry.get_text() self.on_response(self.mood, message) self.window.destroy() def on_cancel_button_clicked(self, widget): self.window.destroy() class TimeoutDialog: """ Class designed to be derivated to create timeout'd dialogs (dialogs that closes automatically after a timeout) """ def __init__(self, timeout): self.countdown_left = timeout self.countdown_enabled = True self.title_text = '' def run_timeout(self): if self.countdown_left > 0: self.countdown() GLib.timeout_add_seconds(1, self.countdown) def on_timeout(self): """ To be implemented in derivated classes """ pass def countdown(self): if self.countdown_enabled: if self.countdown_left <= 0: self.on_timeout() return False self.dialog.set_title('%s [%s]' % ( self.title_text, str(self.countdown_left))) self.countdown_left -= 1 return True self.dialog.set_title(self.title_text) return False class ChangeStatusMessageDialog(TimeoutDialog): def __init__(self, on_response, show=None, show_pep=True): countdown_time = app.config.get('change_status_window_timeout') TimeoutDialog.__init__(self, countdown_time) self.show = show self.pep_dict = {} self.show_pep = show_pep self.on_response = on_response self.xml = gtkgui_helpers.get_gtk_builder('change_status_message_dialog.ui') self.dialog = self.xml.get_object('change_status_message_dialog') self.dialog.set_transient_for(app.interface.roster.window) msg = None if show: uf_show = helpers.get_uf_show(show) self.title_text = _('%s Status Message') % uf_show msg = app.config.get_per('statusmsg', '_last_' + self.show, 'message') self.pep_dict['activity'] = app.config.get_per('statusmsg', '_last_' + self.show, 'activity') self.pep_dict['subactivity'] = app.config.get_per('statusmsg', '_last_' + self.show, 'subactivity') self.pep_dict['activity_text'] = app.config.get_per('statusmsg', '_last_' + self.show, 'activity_text') self.pep_dict['mood'] = app.config.get_per('statusmsg', '_last_' + self.show, 'mood') self.pep_dict['mood_text'] = app.config.get_per('statusmsg', '_last_' + self.show, 'mood_text') else: self.title_text = _('Status Message') self.dialog.set_title(self.title_text) message_textview = self.xml.get_object('message_textview') self.message_buffer = message_textview.get_buffer() self.message_buffer.connect('changed', self.on_message_buffer_changed) if not msg: msg = '' msg = helpers.from_one_line(msg) self.message_buffer.set_text(msg) # have an empty string selectable, so user can clear msg self.preset_messages_dict = {'': ['', '', '', '', '', '']} for msg_name in app.config.get_per('statusmsg'): if msg_name.startswith('_last_'): continue opts = [] for opt in ['message', 'activity', 'subactivity', 'activity_text', 'mood', 'mood_text']: opts.append(app.config.get_per('statusmsg', msg_name, opt)) opts[0] = helpers.from_one_line(opts[0]) self.preset_messages_dict[msg_name] = opts sorted_keys_list = helpers.get_sorted_keys(self.preset_messages_dict) self.message_liststore = Gtk.ListStore(str) # msg_name self.message_combobox = self.xml.get_object('message_combobox') self.message_combobox.set_model(self.message_liststore) cellrenderertext = Gtk.CellRendererText() self.message_combobox.pack_start(cellrenderertext, True) self.message_combobox.add_attribute(cellrenderertext, 'text', 0) for msg_name in sorted_keys_list: self.message_liststore.append((msg_name,)) if show_pep: self.draw_activity() self.draw_mood() else: # remove acvtivity / mood lines self.xml.get_object('activity_label').set_no_show_all(True) self.xml.get_object('activity_button').set_no_show_all(True) self.xml.get_object('mood_label').set_no_show_all(True) self.xml.get_object('mood_button').set_no_show_all(True) self.xml.get_object('activity_label').hide() self.xml.get_object('activity_button').hide() self.xml.get_object('mood_label').hide() self.xml.get_object('mood_button').hide() self.xml.connect_signals(self) self.run_timeout() self.dialog.connect('response', self.on_dialog_response) self.dialog.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.dialog.show_all() def draw_activity(self): """ Set activity button """ img = self.xml.get_object('activity_image') label = self.xml.get_object('activity_button_label') if 'activity' in self.pep_dict and self.pep_dict['activity'] in \ ACTIVITIES: if 'subactivity' in self.pep_dict and self.pep_dict['subactivity'] \ in ACTIVITIES[self.pep_dict['activity']]: img.set_from_pixbuf(gtkgui_helpers.load_activity_icon( self.pep_dict['activity'], self.pep_dict['subactivity']).\ get_pixbuf()) else: img.set_from_pixbuf(gtkgui_helpers.load_activity_icon( self.pep_dict['activity']).get_pixbuf()) if self.pep_dict['activity_text']: label.set_text(self.pep_dict['activity_text']) else: label.set_text('') else: img.set_from_pixbuf(None) label.set_text('') def draw_mood(self): """ Set mood button """ img = self.xml.get_object('mood_image') label = self.xml.get_object('mood_button_label') if 'mood' in self.pep_dict and self.pep_dict['mood'] in MOODS: img.set_from_pixbuf(gtkgui_helpers.load_mood_icon( self.pep_dict['mood']).get_pixbuf()) if self.pep_dict['mood_text']: label.set_text(self.pep_dict['mood_text']) else: label.set_text('') else: img.set_from_pixbuf(None) label.set_text('') def on_timeout(self): # Prevent GUI freeze when the combobox menu is opened on close self.message_combobox.popdown() self.dialog.response(Gtk.ResponseType.OK) def on_dialog_response(self, dialog, response): if response == Gtk.ResponseType.OK: beg, end = self.message_buffer.get_bounds() message = self.message_buffer.get_text(beg, end, True).strip() message = helpers.remove_invalid_xml_chars(message) msg = helpers.to_one_line(message) if self.show: app.config.set_per('statusmsg', '_last_' + self.show, 'message', msg) if self.show_pep: app.config.set_per('statusmsg', '_last_' + self.show, 'activity', self.pep_dict['activity']) app.config.set_per('statusmsg', '_last_' + self.show, 'subactivity', self.pep_dict['subactivity']) app.config.set_per('statusmsg', '_last_' + self.show, 'activity_text', self.pep_dict['activity_text']) app.config.set_per('statusmsg', '_last_' + self.show, 'mood', self.pep_dict['mood']) app.config.set_per('statusmsg', '_last_' + self.show, 'mood_text', self.pep_dict['mood_text']) else: message = None # user pressed Cancel button or X wm button self.dialog.destroy() self.on_response(message, self.pep_dict) def on_message_combobox_changed(self, widget): self.countdown_enabled = False model = widget.get_model() active = widget.get_active() if active < 0: return None name = model[active][0] self.message_buffer.set_text(self.preset_messages_dict[name][0]) self.pep_dict['activity'] = self.preset_messages_dict[name][1] self.pep_dict['subactivity'] = self.preset_messages_dict[name][2] self.pep_dict['activity_text'] = self.preset_messages_dict[name][3] self.pep_dict['mood'] = self.preset_messages_dict[name][4] self.pep_dict['mood_text'] = self.preset_messages_dict[name][5] self.draw_activity() self.draw_mood() def on_change_status_message_dialog_key_press_event(self, widget, event): self.countdown_enabled = False if event.keyval == Gdk.KEY_Return or \ event.keyval == Gdk.KEY_KP_Enter: # catch CTRL+ENTER if event.get_state() & Gdk.ModifierType.CONTROL_MASK: self.dialog.response(Gtk.ResponseType.OK) # Stop the event return True def on_message_buffer_changed(self, widget): self.countdown_enabled = False self.toggle_sensitiviy_of_save_as_preset() def toggle_sensitiviy_of_save_as_preset(self): btn = self.xml.get_object('save_as_preset_button') if self.message_buffer.get_char_count() == 0: btn.set_sensitive(False) else: btn.set_sensitive(True) def on_save_as_preset_button_clicked(self, widget): self.countdown_enabled = False start_iter, finish_iter = self.message_buffer.get_bounds() status_message_to_save_as_preset = self.message_buffer.get_text( start_iter, finish_iter, True) def on_ok(msg_name): msg_text = status_message_to_save_as_preset msg_text_1l = helpers.to_one_line(msg_text) if not msg_name: # msg_name was '' msg_name = msg_text_1l def on_ok2(): self.preset_messages_dict[msg_name] = [ msg_text, self.pep_dict.get('activity'), self.pep_dict.get('subactivity'), self.pep_dict.get('activity_text'), self.pep_dict.get('mood'), self.pep_dict.get('mood_text')] app.config.set_per('statusmsg', msg_name, 'message', msg_text_1l) app.config.set_per('statusmsg', msg_name, 'activity', self.pep_dict.get('activity')) app.config.set_per('statusmsg', msg_name, 'subactivity', self.pep_dict.get('subactivity')) app.config.set_per('statusmsg', msg_name, 'activity_text', self.pep_dict.get('activity_text')) app.config.set_per('statusmsg', msg_name, 'mood', self.pep_dict.get('mood')) app.config.set_per('statusmsg', msg_name, 'mood_text', self.pep_dict.get('mood_text')) if msg_name in self.preset_messages_dict: ConfirmationDialog(_('Overwrite Status Message?'), _('This name is already used. Do you want to overwrite this ' 'status message?'), on_response_ok=on_ok2, transient_for=self.dialog) return app.config.add_per('statusmsg', msg_name) on_ok2() iter_ = self.message_liststore.append((msg_name,)) # select in combobox the one we just saved self.message_combobox.set_active_iter(iter_) InputDialog(_('Save as Preset Status Message'), _('Please type a name for this status message'), is_modal=False, ok_handler=on_ok) def on_activity_button_clicked(self, widget): self.countdown_enabled = False def on_response(activity, subactivity, text): self.pep_dict['activity'] = activity or '' self.pep_dict['subactivity'] = subactivity or '' self.pep_dict['activity_text'] = text self.draw_activity() ChangeActivityDialog(on_response, self.pep_dict['activity'], self.pep_dict['subactivity'], self.pep_dict['activity_text']) def on_mood_button_clicked(self, widget): self.countdown_enabled = False def on_response(mood, text): self.pep_dict['mood'] = mood or '' self.pep_dict['mood_text'] = text self.draw_mood() ChangeMoodDialog(on_response, self.pep_dict['mood'], self.pep_dict['mood_text']) class SubscriptionRequestWindow(Gtk.ApplicationWindow): def __init__(self, jid, text, account, user_nick=None): Gtk.ApplicationWindow.__init__(self) self.set_name('SubscriptionRequest') self.set_application(app.app) self.set_show_menubar(False) self.set_resizable(False) self.set_position(Gtk.WindowPosition.CENTER) self.set_title(_('Subscription Request')) xml = gtkgui_helpers.get_gtk_builder('subscription_request_window.ui') self.add(xml.get_object('subscription_box')) self.jid = jid self.account = account self.user_nick = user_nick if len(app.connections) >= 2: prompt_text = \ _('Subscription request for account %(account)s from %(jid)s')\ % {'account': account, 'jid': self.jid} else: prompt_text = _('Subscription request from %s') % self.jid from_label = xml.get_object('from_label') from_label.set_text(prompt_text) textview = xml.get_object('message_textview') textview.get_buffer().set_text(text) self.set_default(xml.get_object('authorize_button')) xml.connect_signals(self) self.show_all() def on_subscription_request_window_destroy(self, widget): """ Close window """ if self.jid in app.interface.instances[self.account]['sub_request']: # remove us from open windows del app.interface.instances[self.account]['sub_request'][self.jid] def on_close_button_clicked(self, widget): self.destroy() def on_authorize_button_clicked(self, widget): """ Accept the request """ app.connections[self.account].get_module('Presence').subscribed(self.jid) self.destroy() contact = app.contacts.get_contact(self.account, self.jid) if not contact or _('Not in Roster') in contact.groups: AddNewContactWindow(self.account, self.jid, self.user_nick) def on_contact_info_activate(self, widget): """ Ask vcard """ if self.jid in app.interface.instances[self.account]['infos']: app.interface.instances[self.account]['infos'][self.jid].window.present() else: contact = app.contacts.create_contact(jid=self.jid, account=self.account) app.interface.instances[self.account]['infos'][self.jid] = \ vcard.VcardWindow(contact, self.account) # Remove jabber page app.interface.instances[self.account]['infos'][self.jid].xml.\ get_object('information_notebook').remove_page(0) def on_start_chat_activate(self, widget): """ Open chat """ app.interface.new_chat_from_jid(self.account, self.jid) def on_deny_button_clicked(self, widget): """ Refuse the request """ app.connections[self.account].get_module('Presence').unsubscribed(self.jid) contact = app.contacts.get_contact(self.account, self.jid) if contact and _('Not in Roster') in contact.get_shown_groups(): app.interface.roster.remove_contact(self.jid, self.account) self.destroy() class SynchroniseSelectAccountDialog: def __init__(self, account): # 'account' can be None if we are about to create our first one if not account or app.connections[account].connected < 2: ErrorDialog(_('You are not connected to the server'), _('Without a connection, you can not synchronise your contacts.')) raise GajimGeneralException('You are not connected to the server') self.account = account self.xml = gtkgui_helpers.get_gtk_builder('synchronise_select_account_dialog.ui') self.dialog = self.xml.get_object('synchronise_select_account_dialog') self.dialog.set_transient_for(app.get_app_window('AccountsWindow')) self.accounts_treeview = self.xml.get_object('accounts_treeview') model = Gtk.ListStore(str, str, bool) self.accounts_treeview.set_model(model) # columns renderer = Gtk.CellRendererText() self.accounts_treeview.insert_column_with_attributes(-1, _('Name'), renderer, text=0) renderer = Gtk.CellRendererText() self.accounts_treeview.insert_column_with_attributes(-1, _('Server'), renderer, text=1) self.xml.connect_signals(self) self.init_accounts() self.dialog.show_all() def on_accounts_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def init_accounts(self): """ Initialize listStore with existing accounts """ model = self.accounts_treeview.get_model() model.clear() for remote_account in app.connections: if remote_account == self.account: # Do not show the account we're sync'ing continue iter_ = model.append() model.set(iter_, 0, remote_account, 1, app.get_hostname_from_account(remote_account)) def on_cancel_button_clicked(self, widget): self.dialog.destroy() def on_ok_button_clicked(self, widget): sel = self.accounts_treeview.get_selection() (model, iter_) = sel.get_selected() if not iter_: return remote_account = model.get_value(iter_, 0) if app.connections[remote_account].connected < 2: ErrorDialog(_('This account is not connected to the server'), _('You cannot synchronize with an account unless it is connected.')) return try: SynchroniseSelectContactsDialog(self.account, remote_account) except GajimGeneralException: # if we showed ErrorDialog, there will not be dialog instance return self.dialog.destroy() @staticmethod def on_destroy(widget): del app.interface.instances['import_contacts'] class SynchroniseSelectContactsDialog: def __init__(self, account, remote_account): self.local_account = account self.remote_account = remote_account self.xml = gtkgui_helpers.get_gtk_builder( 'synchronise_select_contacts_dialog.ui') self.dialog = self.xml.get_object('synchronise_select_contacts_dialog') self.contacts_treeview = self.xml.get_object('contacts_treeview') model = Gtk.ListStore(bool, str) self.contacts_treeview.set_model(model) # columns renderer1 = Gtk.CellRendererToggle() renderer1.set_property('activatable', True) renderer1.connect('toggled', self.toggled_callback) self.contacts_treeview.insert_column_with_attributes(-1, _('Synchronise'), renderer1, active=0) renderer2 = Gtk.CellRendererText() self.contacts_treeview.insert_column_with_attributes(-1, _('Name'), renderer2, text=1) self.xml.connect_signals(self) self.init_contacts() self.dialog.show_all() def toggled_callback(self, cell, path): model = self.contacts_treeview.get_model() iter_ = model.get_iter(path) model[iter_][0] = not cell.get_active() def on_contacts_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def init_contacts(self): """ Initialize listStore with existing accounts """ model = self.contacts_treeview.get_model() model.clear() # recover local contacts local_jid_list = app.contacts.get_contacts_jid_list(self.local_account) remote_jid_list = app.contacts.get_contacts_jid_list( self.remote_account) for remote_jid in remote_jid_list: if remote_jid not in local_jid_list: iter_ = model.append() model.set(iter_, 0, True, 1, remote_jid) def on_cancel_button_clicked(self, widget): self.dialog.destroy() def on_ok_button_clicked(self, widget): model = self.contacts_treeview.get_model() iter_ = model.get_iter_first() while iter_: if model[iter_][0]: # it is selected remote_jid = model[iter_][1] message = 'I\'m synchronizing my contacts from my %s account, could you please add this address to your contact list?' % \ app.get_hostname_from_account(self.remote_account) remote_contact = app.contacts.get_first_contact_from_jid( self.remote_account, remote_jid) # keep same groups and same nickname app.interface.roster.req_sub(self, remote_jid, message, self.local_account, groups=remote_contact.groups, nickname=remote_contact.name, auto_auth=True) iter_ = model.iter_next(iter_) self.dialog.destroy() #Action that can be done with an incoming list of contacts TRANSLATED_ACTION = {'add': _('add'), 'modify': _('modify'), 'remove': _('remove')} class RosterItemExchangeWindow: """ Windows used when someone send you a exchange contact suggestion """ def __init__(self, account, action, exchange_list, jid_from, message_body=None): self.account = account self.action = action self.exchange_list = exchange_list self.message_body = message_body self.jid_from = jid_from show_dialog = False # Connect to gtk builder self.xml = gtkgui_helpers.get_gtk_builder( 'roster_item_exchange_window.ui') self.window = self.xml.get_object('roster_item_exchange_window') # Add Widgets. for widget_to_add in ['accept_button_label', 'type_label', 'body_scrolledwindow', 'body_textview', 'items_list_treeview']: self.__dict__[widget_to_add] = self.xml.get_object(widget_to_add) # Set labels # self.action can be 'add', 'modify' or 'remove' self.type_label.set_label( _('%(jid)s would like you to %(action)s some contacts ' 'in your roster.') % {'jid': jid_from, 'action': TRANSLATED_ACTION[self.action]}) if message_body: buffer_ = self.body_textview.get_buffer() buffer_.set_text(self.message_body) else: self.body_scrolledwindow.hide() # Treeview model = Gtk.ListStore(bool, str, str, str, str) self.items_list_treeview.set_model(model) # columns renderer1 = Gtk.CellRendererToggle() renderer1.set_property('activatable', True) renderer1.connect('toggled', self.toggled_callback) if self.action == 'add': title = _('Add') elif self.action == 'modify': title = _('Modify') elif self.action == 'delete': title = _('Delete') self.items_list_treeview.insert_column_with_attributes(-1, title, renderer1, active=0) renderer2 = Gtk.CellRendererText() self.items_list_treeview.insert_column_with_attributes(-1, _('JID'), renderer2, text=1) renderer3 = Gtk.CellRendererText() self.items_list_treeview.insert_column_with_attributes(-1, _('Name'), renderer3, text=2) renderer4 = Gtk.CellRendererText() self.items_list_treeview.insert_column_with_attributes(-1, _('Groups'), renderer4, text=3) # Init contacts model = self.items_list_treeview.get_model() model.clear() if action == 'add': for jid in self.exchange_list: groups = '' is_in_roster = True contact = app.contacts.get_contact_with_highest_priority( self.account, jid) if not contact or _('Not in Roster') in contact.groups: is_in_roster = False name = self.exchange_list[jid][0] num_list = len(self.exchange_list[jid][1]) current = 0 for group in self.exchange_list[jid][1]: current += 1 if contact and not group in contact.groups: is_in_roster = False if current == num_list: groups = groups + group else: groups = groups + group + ', ' if not is_in_roster: show_dialog = True iter_ = model.append() model.set(iter_, 0, True, 1, jid, 2, name, 3, groups) # Change label for accept_button to action name instead of 'OK'. self.accept_button_label.set_label(_('Add')) elif action == 'modify': for jid in self.exchange_list: groups = '' is_in_roster = True is_right = True contact = app.contacts.get_contact_with_highest_priority( self.account, jid) name = self.exchange_list[jid][0] if not contact: is_in_roster = False is_right = False else: if name != contact.name: is_right = False num_list = len(self.exchange_list[jid][1]) current = 0 for group in self.exchange_list[jid][1]: current += 1 if contact and not group in contact.groups: is_right = False if current == num_list: groups = groups + group else: groups = groups + group + ', ' if not is_right and is_in_roster: show_dialog = True iter_ = model.append() model.set(iter_, 0, True, 1, jid, 2, name, 3, groups) # Change label for accept_button to action name instead of 'OK'. self.accept_button_label.set_label(_('Modify')) elif action == 'delete': for jid in self.exchange_list: groups = '' is_in_roster = True contact = app.contacts.get_contact_with_highest_priority( self.account, jid) name = self.exchange_list[jid][0] if not contact: is_in_roster = False num_list = len(self.exchange_list[jid][1]) current = 0 for group in self.exchange_list[jid][1]: current += 1 if current == num_list: groups = groups + group else: groups = groups + group + ', ' if is_in_roster: show_dialog = True iter_ = model.append() model.set(iter_, 0, True, 1, jid, 2, name, 3, groups) # Change label for accept_button to action name instead of 'OK'. self.accept_button_label.set_label(_('Delete')) if show_dialog: self.window.show_all() self.xml.connect_signals(self) def toggled_callback(self, cell, path): model = self.items_list_treeview.get_model() iter_ = model.get_iter(path) model[iter_][0] = not cell.get_active() def on_accept_button_clicked(self, widget): model = self.items_list_treeview.get_model() iter_ = model.get_iter_first() if self.action == 'add': a = 0 while iter_: if model[iter_][0]: a += 1 # it is selected #remote_jid = model[iter_][1] message = _('%s suggested me to add you in my roster.' % self.jid_from) # keep same groups and same nickname groups = model[iter_][3].split(', ') if groups == ['']: groups = [] jid = model[iter_][1] if app.jid_is_transport(self.jid_from): con = app.connections[self.account] con.get_module('Presence').automatically_added.append(jid) app.interface.roster.req_sub(self, jid, message, self.account, groups=groups, nickname=model[iter_][2], auto_auth=True) iter_ = model.iter_next(iter_) InformationDialog(i18n.ngettext('Added %d contact', 'Added %d contacts', a, a, a)) elif self.action == 'modify': a = 0 while iter_: if model[iter_][0]: a += 1 # it is selected jid = model[iter_][1] # keep same groups and same nickname groups = model[iter_][3].split(', ') if groups == ['']: groups = [] for u in app.contacts.get_contact(self.account, jid): u.name = model[iter_][2] app.connections[self.account].update_contact(jid, model[iter_][2], groups) self.draw_contact(jid, self.account) # Update opened chat ctrl = app.interface.msg_win_mgr.get_control(jid, self.account) if ctrl: ctrl.update_ui() win = app.interface.msg_win_mgr.get_window(jid, self.account) win.redraw_tab(ctrl) win.show_title() iter_ = model.iter_next(iter_) elif self.action == 'delete': a = 0 while iter_: if model[iter_][0]: a += 1 # it is selected jid = model[iter_][1] app.connections[self.account].get_module('Presence').unsubscribe(jid) app.interface.roster.remove_contact(jid, self.account) app.contacts.remove_jid(self.account, jid) iter_ = model.iter_next(iter_) InformationDialog(i18n.ngettext('Removed %d contact', 'Removed %d contacts', a, a, a)) self.window.destroy() def on_cancel_button_clicked(self, widget): self.window.destroy() class InvitationReceivedDialog: def __init__(self, account, room_jid, contact_fjid, password=None, comment=None, is_continued=False): self.room_jid = room_jid self.account = account self.password = password self.is_continued = is_continued self.contact_fjid = contact_fjid jid = app.get_jid_without_resource(contact_fjid) pritext = _('''You are invited to a groupchat''') #Don't translate $Contact if is_continued: sectext = _('$Contact has invited you to join a discussion') else: sectext = _('$Contact has invited you to group chat %(room_jid)s')\ % {'room_jid': room_jid} contact = app.contacts.get_first_contact_from_jid(account, jid) contact_text = contact and contact.name or jid sectext = i18n.direction_mark + sectext.replace('$Contact', contact_text) if comment: # only if not None and not '' comment = GLib.markup_escape_text(comment) comment = _('Comment: %s') % comment sectext += '\n\n%s' % comment sectext += '\n\n' + _('Do you want to accept the invitation?') def on_yes(checked, text): if self.is_continued: app.interface.join_gc_room(self.account, self.room_jid, app.nicks[self.account], self.password, is_continued=True) else: app.interface.join_gc_minimal( self.account, self.room_jid, password=self.password) def on_no(text): app.connections[account].get_module('MUC').decline( self.room_jid, self.contact_fjid, text) dlg = YesNoDialog(pritext, sectext, text_label=_('Reason (if you decline):'), on_response_yes=on_yes, on_response_no=on_no) dlg.set_title(_('Groupchat Invitation')) class ProgressDialog: def __init__(self, title_text, during_text, messages_queue): """ During text is what to show during the procedure, messages_queue has the message to show in the textview """ self.xml = gtkgui_helpers.get_gtk_builder('progress_dialog.ui') self.dialog = self.xml.get_object('progress_dialog') self.label = self.xml.get_object('label') self.label.set_markup('' + during_text + '') self.progressbar = self.xml.get_object('progressbar') self.dialog.set_title(title_text) self.dialog.set_default_size(450, 250) self.window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.dialog.show_all() self.xml.connect_signals(self) self.update_progressbar_timeout_id = GLib.timeout_add(100, self.update_progressbar) def update_progressbar(self): if self.dialog: self.progressbar.pulse() return True # loop forever return False def on_progress_dialog_delete_event(self, widget, event): return True # WM's X button or Escape key should not destroy the window class TransformChatToMUC: # Keep a reference on windows so garbage collector don't restroy them instances = [] # type: List[TransformChatToMUC] def __init__(self, account, jids, preselected=None): """ This window is used to trasform a one-to-one chat to a MUC. We do 2 things: first select the server and then make a guests list """ self.instances.append(self) self.account = account self.auto_jids = jids self.preselected_jids = preselected self.xml = gtkgui_helpers.get_gtk_builder('chat_to_muc_window.ui') self.window = self.xml.get_object('chat_to_muc_window') for widget_to_add in ('invite_button', 'cancel_button', 'server_list_comboboxentry', 'guests_treeview', 'guests_store', 'server_and_guests_hseparator', 'server_select_label'): self.__dict__[widget_to_add] = self.xml.get_object(widget_to_add) server_list = [] self.servers = Gtk.ListStore(str) self.server_list_comboboxentry.set_model(self.servers) cell = Gtk.CellRendererText() self.server_list_comboboxentry.pack_start(cell, True) self.server_list_comboboxentry.add_attribute(cell, 'text', 0) # get the muc server of our server if 'jabber' in app.connections[account].muc_jid: server_list.append(app.connections[account].muc_jid['jabber']) # add servers or recently joined groupchats recently_groupchat = app.config.get_per('accounts', account, 'recent_groupchats').split() for g in recently_groupchat: server = app.get_server_from_jid(g) if server not in server_list and not server.startswith('irc'): server_list.append(server) # add a default server if not server_list: server_list.append('conference.jabber.org') for s in server_list: self.servers.append([s]) self.server_list_comboboxentry.set_active(0) # set treeview # name, jid self.guests_store.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.guests_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) # All contacts beside the following can be invited: # transports, zeroconf contacts, minimized groupchats def invitable(contact, contact_transport=None): return (contact.jid not in self.auto_jids and contact.jid != app.get_jid_from_account(account) and contact.jid not in app.interface.minimized_controls[account] and not contact.is_transport() and contact_transport in ('jabber', None)) # set jabber id and pseudos for account_ in app.contacts.get_accounts(): if app.connections[account_].is_zeroconf: continue for jid in app.contacts.get_jid_list(account_): contact = app.contacts.get_contact_with_highest_priority( account_, jid) contact_transport = app.get_transport_name_from_jid(jid) # Add contact if it can be invited if invitable(contact, contact_transport) and \ contact.show not in ('offline', 'error'): icon_name = gtkgui_helpers.get_iconset_name_for(contact.show) name = contact.name if name == '': name = jid.split('@')[0] iter_ = self.guests_store.append([icon_name, name, jid]) # preselect treeview rows if self.preselected_jids and jid in self.preselected_jids: path = self.guests_store.get_path(iter_) self.guests_treeview.get_selection().select_path(path) app.ged.register_event_handler('unique-room-id-supported', ged.GUI1, self._nec_unique_room_id_supported) app.ged.register_event_handler('unique-room-id-not-supported', ged.GUI1, self._nec_unique_room_id_not_supported) # show all self.window.show_all() self.xml.connect_signals(self) def on_chat_to_muc_window_destroy(self, widget): app.ged.remove_event_handler('unique-room-id-supported', ged.GUI1, self._nec_unique_room_id_supported) app.ged.remove_event_handler('unique-room-id-not-supported', ged.GUI1, self._nec_unique_room_id_not_supported) self.instances.remove(self) def on_chat_to_muc_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: # ESCAPE self.window.destroy() def on_invite_button_clicked(self, widget): row = self.server_list_comboboxentry.get_child().get_displayed_row() model = self.server_list_comboboxentry.get_model() server = model[row][0].strip() if server == '': return app.connections[self.account].check_unique_room_id_support(server, self) def _nec_unique_room_id_supported(self, obj): if obj.instance != self: return guest_list = [] guests = self.guests_treeview.get_selection().get_selected_rows() for guest in guests[1]: iter_ = self.guests_store.get_iter(guest) guest_list.append(self.guests_store[iter_][2]) for guest in self.auto_jids: guest_list.append(guest) room_jid = obj.room_id + '@' + obj.server app.automatic_rooms[self.account][room_jid] = {} app.automatic_rooms[self.account][room_jid]['invities'] = guest_list app.automatic_rooms[self.account][room_jid]['continue_tag'] = True app.interface.join_gc_room(self.account, room_jid, app.nicks[self.account], None, is_continued=True) self.window.destroy() def on_cancel_button_clicked(self, widget): self.window.destroy() def _nec_unique_room_id_not_supported(self, obj): if obj.instance != self: return obj.room_id = app.nicks[self.account].lower().replace(' ', '') + \ str(randrange(9999999)) self._nec_unique_room_id_supported(obj) class Dialog(Gtk.Dialog): def __init__(self, parent, title, buttons, default=None, on_response_ok=None, on_response_cancel=None): Gtk.Dialog.__init__(self, title, parent, Gtk.DialogFlags.DESTROY_WITH_PARENT) self.user_response_ok = on_response_ok self.user_response_cancel = on_response_cancel self.set_border_width(6) self.get_content_area().set_spacing(12) self.set_resizable(False) for stock, response in buttons: self.add_button(stock, response) if default is not None: self.set_default_response(default) else: self.set_default_response(buttons[-1][1]) self.connect('response', self.on_response) def on_response(self, widget, response_id): if response_id == Gtk.ResponseType.OK: if self.user_response_ok: if isinstance(self.user_response_ok, tuple): self.user_response_ok[0](*self.user_response_ok[1:]) else: self.user_response_ok() self.destroy() elif response_id == Gtk.ResponseType.CANCEL: if self.user_response_cancel: if isinstance(self.user_response_cancel, tuple): self.user_response_cancel[0](*self.user_response_ok[1:]) else: self.user_response_cancel() self.destroy() def just_destroy(self, widget): self.destroy() def get_button(self, index): buttons = self.get_action_area().get_children() return index < len(buttons) and buttons[index] or None class DataFormWindow(Dialog): def __init__(self, form, on_response_ok): self.df_response_ok = on_response_ok Dialog.__init__(self, None, 'test', [(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL), (Gtk.STOCK_OK, Gtk.ResponseType.OK)], on_response_ok=self.on_ok) self.set_resizable(True) gtkgui_helpers.resize_window(self, 600, 400) self.dataform_widget = dataforms_widget.DataFormWidget() self.dataform = dataforms.extend_form(node=form) self.dataform_widget.set_sensitive(True) self.dataform_widget.data_form = self.dataform self.dataform_widget.show_all() self.get_content_area().pack_start(self.dataform_widget, True, True, 0) def on_ok(self): form = self.dataform_widget.data_form if isinstance(self.df_response_ok, tuple): self.df_response_ok[0](form, *self.df_response_ok[1:]) else: self.df_response_ok(form) self.destroy() class ResourceConflictDialog(TimeoutDialog, InputDialog): def __init__(self, title, text, resource, ok_handler): TimeoutDialog.__init__(self, 15) InputDialog.__init__(self, title, text, input_str=resource, is_modal=False, ok_handler=ok_handler) self.title_text = title self.run_timeout() def on_timeout(self): self.on_okbutton_clicked(None) class VoIPCallReceivedDialog: instances = {} # type: Dict[Tuple[str, str], VoIPCallReceivedDialog] def __init__(self, account, contact_jid, sid, content_types): self.instances[(contact_jid, sid)] = self self.account = account self.fjid = contact_jid self.sid = sid self.content_types = content_types xml = gtkgui_helpers.get_gtk_builder('voip_call_received_dialog.ui') xml.connect_signals(self) jid = app.get_jid_without_resource(self.fjid) contact = app.contacts.get_first_contact_from_jid(account, jid) if contact and contact.name: self.contact_text = '%s (%s)' % (contact.name, jid) else: self.contact_text = contact_jid self.dialog = xml.get_object('voip_call_received_messagedialog') self.set_secondary_text() self.dialog.show_all() @classmethod def get_dialog(cls, jid, sid): if (jid, sid) in cls.instances: return cls.instances[(jid, sid)] return None def set_secondary_text(self): if 'audio' in self.content_types and 'video' in self.content_types: types_text = _('an audio and video') elif 'audio' in self.content_types: types_text = _('an audio') elif 'video' in self.content_types: types_text = _('a video') # do the substitution self.dialog.set_property('secondary-text', _('%(contact)s wants to start %(type)s session with you. Do you want ' 'to answer the call?') % {'contact': self.contact_text, 'type': types_text}) def add_contents(self, content_types): for type_ in content_types: if type_ not in self.content_types: self.content_types.add(type_) self.set_secondary_text() def remove_contents(self, content_types): for type_ in content_types: if type_ in self.content_types: self.content_types.remove(type_) if not self.content_types: self.dialog.destroy() else: self.set_secondary_text() def on_voip_call_received_messagedialog_destroy(self, dialog): if (self.fjid, self.sid) in self.instances: del self.instances[(self.fjid, self.sid)] def on_voip_call_received_messagedialog_close(self, dialog): return self.on_voip_call_received_messagedialog_response(dialog, Gtk.ResponseType.NO) def on_voip_call_received_messagedialog_response(self, dialog, response): # we've got response from user, either stop connecting or accept the call session = app.connections[self.account].get_jingle_session(self.fjid, self.sid) if not session: dialog.destroy() return if response == Gtk.ResponseType.YES: #TODO: Ensure that ctrl.contact.resource == resource jid = app.get_jid_without_resource(self.fjid) ctrl = (app.interface.msg_win_mgr.get_control(self.fjid, self.account) or app.interface.msg_win_mgr.get_control(jid, self.account) or app.interface.new_chat_from_jid(self.account, jid)) # Chat control opened, update content's status audio = session.get_content('audio') video = session.get_content('video') if audio and not audio.negotiated: ctrl.set_audio_state('connecting', self.sid) if video and not video.negotiated: video_hbox = ctrl.xml.get_object('video_hbox') video_hbox.set_no_show_all(False) if app.config.get('video_see_self'): fixed = ctrl.xml.get_object('outgoing_fixed') fixed.set_no_show_all(False) video_hbox.show_all() ctrl.xml.get_object('incoming_drawingarea').realize() if os.name == 'nt': in_xid = ctrl.xml.get_object('incoming_drawingarea').\ get_window().handle else: in_xid = ctrl.xml.get_object('incoming_drawingarea').\ get_property('window').get_xid() content = session.get_content('video') # move outgoing stream to chat window if app.config.get('video_see_self'): ctrl.xml.get_object('outgoing_drawingarea').realize() if os.name == 'nt': out_xid = ctrl.xml.get_object('outgoing_drawingarea').\ get_window().handle else: out_xid = ctrl.xml.get_object('outgoing_drawingarea').\ get_property('window').get_xid() b = content.src_bin for e in b.children: if not e.get_name().startswith('autovideosink'): continue for f in e.children: if f.get_name().startswith('autovideosink'): f.set_window_handle(out_xid) content.out_xid = out_xid break break content.in_xid = in_xid ctrl.set_video_state('connecting', self.sid) # Now, accept the content/sessions. # This should be done after the chat control is running if not session.accepted: session.approve_session() for content in self.content_types: session.approve_content(content) else: # response==Gtk.ResponseType.NO if not session.accepted: session.decline_session() else: for content in self.content_types: session.reject_content(content) dialog.destroy() class ProgressWindow(Gtk.ApplicationWindow): def __init__(self, file): Gtk.ApplicationWindow.__init__(self) self.set_name('HTTPUploadProgressWindow') self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_title(_('File Transfer')) self.event = file.event self.file = file self._ui = get_builder('httpupload_progress_dialog.ui') self.add(self._ui.box) self.pulse = GLib.timeout_add(100, self._pulse_progressbar) self.show_all() self.connect('destroy', self._on_destroy) self._ui.connect_signals(self) app.ged.register_event_handler('httpupload-progress', ged.CORE, self._on_httpupload_progress) def _on_httpupload_progress(self, obj): if self.file != obj.file: return if obj.status == 'request': self._ui.label.set_text(_('Requesting HTTP Upload Slot…')) elif obj.status == 'close': self.destroy() elif obj.status == 'upload': self._ui.label.set_text(_('Uploading file via HTTP File Upload…')) elif obj.status == 'update': self.update_progress(obj.seen, obj.total) elif obj.status == 'encrypt': self._ui.label.set_text(_('Encrypting file…')) def _pulse_progressbar(self): self._ui.progressbar.pulse() return True def on_cancel_upload_button_clicked(self, widget): self.destroy() def _on_destroy(self, *args): self.event.set() if self.pulse: GLib.source_remove(self.pulse) app.ged.remove_event_handler('httpupload-progress', ged.CORE, self._on_httpupload_progress) def update_progress(self, seen, total): if self.event.isSet(): return if self.pulse: GLib.source_remove(self.pulse) self.pulse = None self._ui.progressbar.set_fraction(float(seen) / total) size_total = round(total / (1024 * 1024), 1) size_progress = round(seen / (1024 * 1024), 1) self._ui.progress_label.set_text( _('%(progress)s of %(total)s MiB sent') % \ {'progress': str(size_progress), 'total': str(size_total)}) gajim-gajim-1.1.3/gajim/disco.py000066400000000000000000002337051345766322700164630ustar00rootroot00000000000000# Copyright (C) 2005-2006 Stéphan Kochen # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # The appearance of the treeview, and parts of the dialog, are controlled by # AgentBrowser (sub-)classes. Methods that probably should be overridden when # subclassing are: (look at the docstrings and source for additional info) # - def cleanup(self) * # - def _create_treemodel(self) * # - def _add_actions(self) # - def _clean_actions(self) # - def update_theme(self) * # - def update_actions(self) # - def default_action(self) # - def _find_item(self, jid, node) # - def _add_item(self, jid, node, parent_node, item, force) # - def _update_item(self, iter_, jid, node, item) # - def _update_info(self, iter_, jid, node, identities, features, data) # - def _update_error(self, iter_, jid, node) # # * Should call the super class for this method. # All others do not have to call back to the super class. (but can if they want # the functionality) # There are more methods, of course, but this is a basic set. import types import weakref import nbxmpp from gi.repository import GLib from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gajim import gtkgui_helpers from gajim import groups from gajim import adhoc_commands from gajim import search_window from gajim.common import app from gajim.common.i18n import _ from gajim.common import helpers from gajim.common.const import StyleAttr from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import InformationDialog from gajim.gtk.service_registration import ServiceRegistration LABELS = { 1: _('This service has not yet responded with detailed information'), 2: _('This service could not respond with detailed information.\n' 'It is most likely legacy or broken'), } # Dictionary mapping category, type pairs to browser class, image pairs. # This is a function, so we can call it after the classes are declared. # For the browser class, None means that the service will only be browsable # when it advertises disco as it's feature, False means it's never browsable. def _gen_agent_type_info(): return { # Defaults (0, 0): (None, None), # Jabber server ('server', 'im'): (ToplevelAgentBrowser, 'jabber'), ('services', 'jabber'): (ToplevelAgentBrowser, 'jabber'), ('hierarchy', 'branch'): (AgentBrowser, 'jabber'), # Services ('conference', 'text'): (MucBrowser, 'conference'), ('headline', 'rss'): (AgentBrowser, 'rss'), ('headline', 'weather'): (False, 'weather'), ('gateway', 'weather'): (False, 'weather'), ('_jid', 'weather'): (False, 'weather'), ('gateway', 'sip'): (False, 'sip'), ('directory', 'user'): (None, 'jud'), ('pubsub', 'generic'): (PubSubBrowser, 'pubsub'), ('pubsub', 'service'): (PubSubBrowser, 'pubsub'), ('proxy', 'bytestreams'): (None, 'bytestreams'), # Socks5 FT proxy ('headline', 'newmail'): (ToplevelAgentBrowser, 'mail'), # Transports ('conference', 'irc'): (ToplevelAgentBrowser, 'irc'), ('_jid', 'irc'): (False, 'irc'), ('gateway', 'irc'): (False, 'irc'), ('gateway', 'gadu-gadu'): (False, 'gadu-gadu'), ('_jid', 'gadugadu'): (False, 'gadu-gadu'), ('gateway', 'http-ws'): (False, 'http-ws'), ('gateway', 'icq'): (False, 'icq'), ('_jid', 'icq'): (False, 'icq'), ('gateway', 'sms'): (False, 'sms'), ('_jid', 'sms'): (False, 'sms'), ('gateway', 'smtp'): (False, 'mail'), ('gateway', 'mrim'): (False, 'mrim'), ('_jid', 'mrim'): (False, 'mrim'), ('gateway', 'facebook'): (False, 'facebook'), ('_jid', 'facebook'): (False, 'facebook'), ('gateway', 'tv'): (False, 'tv'), ('gateway', 'twitter'): (False, 'twitter'), } # Category type to "human-readable" description string _cat_to_descr = { 'other': _('Others'), 'gateway': _('Transports'), '_jid': _('Transports'), #conference is a category for listing mostly groupchats in service discovery 'conference': _('Conference'), } class CacheDictionary: """ A dictionary that keeps items around for only a specific time. Lifetime is in minutes. Getrefresh specifies whether to refresh when an item is merely accessed instead of set as well """ def __init__(self, lifetime, getrefresh=True): self.lifetime = lifetime * 1000 * 60 self.getrefresh = getrefresh self.cache = {} class CacheItem: """ An object to store cache items and their timeouts """ def __init__(self, value): self.value = value self.source = None def __call__(self): return self.value def cleanup(self): for key in list(self.cache.keys()): item = self.cache[key] if item.source: GLib.source_remove(item.source) del self.cache[key] def _expire_timeout(self, key): """ The timeout has expired, remove the object """ if key in self.cache: del self.cache[key] return False def _refresh_timeout(self, key): """ The object was accessed, refresh the timeout """ item = self.cache[key] if item.source: GLib.source_remove(item.source) if self.lifetime: source = GLib.timeout_add_seconds(int(self.lifetime/1000), self._expire_timeout, key) item.source = source def __getitem__(self, key): item = self.cache[key] if self.getrefresh: self._refresh_timeout(key) return item() def __setitem__(self, key, value): item = self.CacheItem(value) self.cache[key] = item self._refresh_timeout(key) def __delitem__(self, key): item = self.cache[key] if item.source: GLib.source_remove(item.source) del self.cache[key] def __contains__(self, key): return key in self.cache _icon_cache = CacheDictionary(15) def get_agent_address(jid, node=None): """ Get an agent's address for displaying in the GUI """ if node: return '%s@%s' % (node, str(jid)) return str(jid) class Closure: """ A weak reference to a callback with arguments as an object Weak references to methods immediately die, even if the object is still alive. Besides a handy way to store a callback, this provides a workaround that keeps a reference to the object instead. Userargs and removeargs must be tuples. """ def __init__(self, cb, userargs=(), remove=None, removeargs=()): self.userargs = userargs self.remove = remove self.removeargs = removeargs if isinstance(cb, types.MethodType): self.meth_self = weakref.ref(cb.__self__, self._remove) self.meth_name = cb.__name__ elif callable(cb): self.meth_self = None self.cb = weakref.ref(cb, self._remove) else: raise TypeError('Object is not callable') def _remove(self, ref): if self.remove: self.remove(self, *self.removeargs) def __call__(self, *args, **kwargs): if self.meth_self: obj = self.meth_self() cb = getattr(obj, self.meth_name) else: cb = self.cb() args = args + self.userargs return cb(*args, **kwargs) class ServicesCache: """ Class that caches our query results. Each connection will have it's own ServiceCache instance """ def __init__(self, account): self.account = account self._items = CacheDictionary(0, getrefresh=False) self._info = CacheDictionary(0, getrefresh=False) self._subscriptions = CacheDictionary(5, getrefresh=False) self._cbs = {} def cleanup(self): self._items.cleanup() self._info.cleanup() def _clean_closure(self, cb, type_, addr): # A closure died, clean up cbkey = (type_, addr) try: self._cbs[cbkey].remove(cb) except KeyError: return except ValueError: return # Clean an empty list if not self._cbs[cbkey]: del self._cbs[cbkey] def get_icon(self, identities=None, addr=''): """ Return the icon for an agent """ if identities is None: identities = [] # Grab the first identity with an icon quiet = False for identity in identities: try: cat, type_ = identity['category'], identity['type'] info = _agent_type_info[(cat, type_)] except KeyError: continue filename = info[1] if filename: break else: # Loop fell through, default to unknown filename = addr.split('.')[0] quiet = True # Use the cache if possible if filename in _icon_cache: return _icon_cache[filename] # Or load it pix = gtkgui_helpers.get_icon_pixmap('gajim-agent-' + filename, size=32, quiet=quiet) if pix: # Store in cache _icon_cache[filename] = pix return pix if 'jabber' in _icon_cache: return _icon_cache['jabber'] pix = gtkgui_helpers.get_icon_pixmap('gajim-agent-jabber', size=32) _icon_cache['jabber'] = pix return pix def get_browser(self, identities=None, features=None): """ Return the browser class for an agent """ if identities is None: identities = [] if features is None: features = [] # First pass, we try to find a ToplevelAgentBrowser for identity in identities: try: cat, type_ = identity['category'], identity['type'] info = _agent_type_info[(cat, type_)] except KeyError: continue browser = info[0] if browser and browser == ToplevelAgentBrowser: return browser # second pass, we haven't found a ToplevelAgentBrowser for identity in identities: try: cat, type_ = identity['category'], identity['type'] info = _agent_type_info[(cat, type_)] except KeyError: continue browser = info[0] if browser: return browser # NS_BROWSE is deprecated, but we check for it anyways. # Some services list it in features and respond to # NS_DISCO_ITEMS anyways. # Allow browsing for unknown types as well. if (not features and not identities) or \ nbxmpp.NS_DISCO_ITEMS in features or nbxmpp.NS_BROWSE in features: return ToplevelAgentBrowser return None def get_info(self, jid, node, cb, force=False, nofetch=False, args=()): """ Get info for an agent """ addr = get_agent_address(jid, node) # Check the cache if addr in self._info and not force: args = self._info[addr] + args cb(jid, node, *args) return if nofetch: return # Create a closure object cbkey = ('info', addr) cb = Closure(cb, userargs=args, remove=self._clean_closure, removeargs=cbkey) # Are we already fetching this? if cbkey in self._cbs: self._cbs[cbkey].append(cb) else: self._cbs[cbkey] = [cb] con = app.connections[self.account] con.get_module('Discovery').disco_info( jid, node, self._disco_info_received, self._disco_info_error) def get_items(self, jid, node, cb, force=False, nofetch=False, args=()): """ Get a list of items in an agent """ addr = get_agent_address(jid, node) # Check the cache if addr in self._items and not force: args = (self._items[addr],) + args cb(jid, node, *args) return if nofetch: return # Create a closure object cbkey = ('items', addr) cb = Closure(cb, userargs=args, remove=self._clean_closure, removeargs=cbkey) # Are we already fetching this? if cbkey in self._cbs: self._cbs[cbkey].append(cb) else: self._cbs[cbkey] = [cb] con = app.connections[self.account] con.get_module('Discovery').disco_items( jid, node, self._disco_items_received, self._disco_items_error) def _disco_info_received(self, from_, identities, features, data, node): """ Callback for when we receive an agent's info array is (agent, node, identities, features, data) """ if not identities: # Ejabberd doesn't send identities when using admin nodes identities = [{'category': 'server', 'type': 'im', 'name': node}] self._on_agent_info(str(from_), node, identities, features, data) def _disco_info_error(self, from_, error): """ Callback for when a query fails. Even after the browse and agents namespaces """ addr = get_agent_address(from_) # Call callbacks cbkey = ('info', addr) if cbkey in self._cbs: for cb in self._cbs[cbkey]: cb(str(from_), '', 0, 0, 0) # clean_closure may have beaten us to it if cbkey in self._cbs: del self._cbs[cbkey] def _on_agent_info(self, fjid, node, identities, features, data): addr = get_agent_address(fjid, node) # Store in cache self._info[addr] = (identities, features, data) # Call callbacks cbkey = ('info', addr) if cbkey in self._cbs: for cb in self._cbs[cbkey]: cb(fjid, node, identities, features, data) # clean_closure may have beaten us to it if cbkey in self._cbs: del self._cbs[cbkey] def _disco_items_received(self, from_, node, items): """ Callback for when we receive an agent's items array is (agent, node, items) """ addr = get_agent_address(from_, node) # Store in cache self._items[addr] = items # Call callbacks cbkey = ('items', addr) if cbkey in self._cbs: for cb in self._cbs[cbkey]: cb(str(from_), node, items) # clean_closure may have beaten us to it if cbkey in self._cbs: del self._cbs[cbkey] def _disco_items_error(self, from_, error): """ Callback for when a query fails. Even after the browse and agents namespaces """ addr = get_agent_address(from_) # Call callbacks cbkey = ('items', addr) if cbkey in self._cbs: for cb in self._cbs[cbkey]: cb(str(from_), '', 0) # clean_closure may have beaten us to it if cbkey in self._cbs: del self._cbs[cbkey] class ServiceDiscoveryWindow: """ Class that represents the Services Discovery window """ def __init__(self, account, jid='', node='', address_entry=False, parent=None, initial_identities=None): self._account = account self.parent = parent if not jid: jid = app.config.get_per('accounts', account, 'hostname') node = '' self.jid = None self.browser = None self.children = [] self.dying = False self.node = None self.reloading = False # Check connection if app.connections[account].connected < 2: ErrorDialog(_('You are not connected to the server'), _('Without a connection, you can not browse available services')) raise RuntimeError('You must be connected to browse services') # Get a ServicesCache object. try: self.cache = app.connections[account].services_cache except AttributeError: self.cache = ServicesCache(account) app.connections[account].services_cache = self.cache if initial_identities: self.cache._on_agent_info(jid, node, initial_identities, [], None) self.xml = gtkgui_helpers.get_gtk_builder('service_discovery_window.ui') self.window = self.xml.get_object('service_discovery_window') self.services_treeview = self.xml.get_object('services_treeview') self.model = None # This is more reliable than the cursor-changed signal. selection = self.services_treeview.get_selection() selection.connect_after('changed', self.on_services_treeview_selection_changed) self.services_scrollwin = self.xml.get_object('services_scrollwin') self.progressbar = self.xml.get_object('services_progressbar') self.banner = self.xml.get_object('banner_agent_label') self.banner_icon = self.xml.get_object('banner_agent_icon') self.banner_eventbox = self.xml.get_object('banner_agent_eventbox') self.style_event_id = 0 self.banner.realize() self.action_buttonbox = self.xml.get_object('action_buttonbox') # Address combobox self.address_comboboxtext = None address_table = self.xml.get_object('address_table') if address_entry: self.address_comboboxtext = self.xml.get_object( 'address_comboboxtext') self.address_comboboxtext_entry = self.xml.get_object( 'address_entry') self.latest_addresses = app.config.get( 'latest_disco_addresses').split() if jid in self.latest_addresses: self.latest_addresses.remove(jid) self.latest_addresses.insert(0, jid) if len(self.latest_addresses) > 10: self.latest_addresses = self.latest_addresses[0:10] for j in self.latest_addresses: self.address_comboboxtext.append_text(j) self.address_comboboxtext.get_child().set_text(jid) else: # Don't show it at all if we didn't ask for it address_table.set_no_show_all(True) address_table.hide() accel_group = Gtk.AccelGroup() keyval, mod = Gtk.accelerator_parse('r') accel_group.connect(keyval, mod, Gtk.AccelFlags.VISIBLE, self.accel_group_func) self.window.add_accel_group(accel_group) self._initial_state() self.xml.connect_signals(self) self.travel(jid, node) self.window.show_all() @property def account(self): return self._account @account.setter def account(self, value): self._account = value self.cache.account = value if self.browser: self.browser.account = value def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def accel_group_func(self, accel_group, acceleratable, keyval, modifier): if (modifier & Gdk.ModifierType.CONTROL_MASK) and (keyval == Gdk.KEY_r): self.reload() def _initial_state(self): """ Set some initial state on the window. Separated in a method because it's handy to use within browser's cleanup method """ self.progressbar.hide() title_text = _('Service Discovery using account %s') % self.account self.window.set_title(title_text) self._set_window_banner_text(_('Service Discovery')) self.banner_icon.clear() self.banner_icon.hide() # Just clearing it doesn't work def _set_window_banner_text(self, text, text_after=None): markup = '%s' % (text) if text_after is not None: markup += '\n%s' % text_after self.banner.set_markup(markup) def destroy(self, chain=False): """ Close the browser. This can optionally close its children and propagate to the parent. This should happen on actions like register, or join to kill off the entire browser chain """ if self.dying: return self.dying = True # self.browser._get_agent_address() would break when no browser. addr = get_agent_address(self.jid, self.node) if addr in app.interface.instances[self.account]['disco']: del app.interface.instances[self.account]['disco'][addr] if self.browser: self.window.hide() self.browser.cleanup() self.browser = None self.window.destroy() for child in self.children[:]: child.parent = None if chain: child.destroy(chain=chain) self.children.remove(child) if self.parent: if self in self.parent.children: self.parent.children.remove(self) if chain and not self.parent.children: self.parent.destroy(chain=chain) self.parent = None else: self.cache.cleanup() def reload(self): if not self.jid: return self.reloading = True self.travel(self.jid, self.node) def travel(self, jid, node): """ Travel to an agent within the current services window """ if self.browser: self.browser.cleanup() self.browser = None # Update the window list if self.jid: old_addr = get_agent_address(self.jid, self.node) if old_addr in app.interface.instances[self.account]['disco']: del app.interface.instances[self.account]['disco'][old_addr] addr = get_agent_address(jid, node) app.interface.instances[self.account]['disco'][addr] = self # We need to store these, self.browser is not always available. self.jid = jid self.node = node self.cache.get_info(jid, node, self._travel, force=self.reloading) def _travel(self, jid, node, identities, features, data): """ Continuation of travel """ if self.dying or jid != self.jid or node != self.node: return if not identities: if not self.address_comboboxtext: # We can't travel anywhere else. self.destroy() ErrorDialog( _('The service could not be found'), _('There is no service at the address you entered, or it is ' 'not responding. Check the address and try again.'), transient_for=self.window) return klass = self.cache.get_browser(identities, features) if not klass: ErrorDialog( _('The service is not browsable'), _('This type of service does not contain any items to browse.'), transient_for=self.window) return if klass is None: klass = AgentBrowser self.browser = klass(self.account, jid, node) self.browser.prepare_window(self) self.browser.browse(force=self.reloading) self.reloading = False def open(self, jid, node): """ Open an agent. By default, this happens in a new window """ try: win = app.interface.instances[self.account]['disco']\ [get_agent_address(jid, node)] win.window.present() return except KeyError: pass try: win = ServiceDiscoveryWindow(self.account, jid, node, parent=self) except RuntimeError: # Disconnected, perhaps return self.children.append(win) def on_service_discovery_window_destroy(self, widget): self.destroy() def on_close_button_clicked(self, widget): self.destroy() def on_address_comboboxtext_changed(self, widget): if self.address_comboboxtext.get_active() != -1: # user selected one of the entries so do auto-visit jid = self.address_comboboxtext_entry.get_text() try: jid = helpers.parse_jid(jid) except helpers.InvalidFormat as s: pritext = _('Invalid Server Name') ErrorDialog(pritext, str(s)) return self.travel(jid, '') def on_go_button_clicked(self, widget): jid = self.address_comboboxtext_entry.get_text() try: jid = helpers.parse_jid(jid) except helpers.InvalidFormat as s: pritext = _('Invalid Server Name') ErrorDialog(pritext, str(s), transient_for=self.window) return if jid == self.jid: # jid has not changed return if jid in self.latest_addresses: self.latest_addresses.remove(jid) self.latest_addresses.insert(0, jid) if len(self.latest_addresses) > 10: self.latest_addresses = self.latest_addresses[0:10] self.address_comboboxtext.get_model().clear() for j in self.latest_addresses: self.address_comboboxtext.append_text(j) app.config.set('latest_disco_addresses', ' '.join(self.latest_addresses)) self.travel(jid, '') def on_services_treeview_row_activated(self, widget, path, col=0): if self.browser: self.browser.default_action() def on_services_treeview_selection_changed(self, widget): if self.browser: self.browser.update_actions() def _on_entry_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Return or event.keyval == Gdk.KEY_KP_Enter: self.on_go_button_clicked(widget) class AgentBrowser: """ Class that deals with browsing agents and appearance of the browser window. This class and subclasses should basically be treated as "part" of the ServiceDiscoveryWindow class, but had to be separated because this part is dynamic """ def __init__(self, account, jid, node): self.account = account self.jid = jid self.node = node self._total_items = 0 self.browse_button = None # This is for some timeout callbacks self.active = False def _get_agent_address(self): """ Get the agent's address for displaying in the GUI """ return get_agent_address(self.jid, self.node) def _set_initial_title(self): """ Set the initial window title based on agent address """ self.window.window.set_title(_('Browsing %(address)s using account ' '%(account)s') % {'address': self._get_agent_address(), 'account': self.account}) self.window._set_window_banner_text(self._get_agent_address()) def _create_treemodel(self): """ Create the treemodel for the services treeview. When subclassing, note that the first two columns should ALWAYS be of type string and contain the JID and node of the item respectively """ # JID, node, name, address self.model = Gtk.ListStore(str, str, str, str) self.model.set_sort_column_id(3, Gtk.SortType.ASCENDING) self.window.services_treeview.set_model(self.model) # Name column col = Gtk.TreeViewColumn(_('Name')) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', 2) self.window.services_treeview.insert_column(col, -1) col.set_resizable(True) # Address column col = Gtk.TreeViewColumn(_('JID')) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', 3) self.window.services_treeview.insert_column(col, -1) col.set_resizable(True) self.window.services_treeview.set_headers_visible(True) def _clean_treemodel(self): self.model.clear() for col in self.window.services_treeview.get_columns(): self.window.services_treeview.remove_column(col) self.window.services_treeview.set_headers_visible(False) def _add_actions(self): """ Add the action buttons to the buttonbox for actions the browser can perform """ self.browse_button = Gtk.Button() self.browse_button.connect('clicked', self.on_browse_button_clicked) self.window.action_buttonbox.add(self.browse_button) image = Gtk.Image.new_from_icon_name("document-open", Gtk.IconSize.BUTTON) self.browse_button.set_image(image) label = _('Browse') self.browse_button.set_label(label) self.browse_button.show_all() def _clean_actions(self): """ Remove the action buttons specific to this browser """ if self.browse_button: self.browse_button.destroy() self.browse_button = None def _set_title(self, jid, node, identities, features, data): """ Set the window title based on agent info """ # Set the banner and window title name = '' if len(identities) > 1: # Check if an identity with server category is present for _index, identity in enumerate(identities): if identity['category'] == 'server' and 'name' in identity: name = identity['name'] break elif 'name' in identities[0]: name = identities[0]['name'] if name: self.window._set_window_banner_text(self._get_agent_address(), name) # Add an icon to the banner. pix = self.cache.get_icon(identities, addr=self._get_agent_address()) self.window.banner_icon.set_from_pixbuf(pix) self.window.banner_icon.show() def _clean_title(self): # Everything done here is done in window._initial_state # This is for subclasses. pass def prepare_window(self, window): """ Prepare the service discovery window. Called when a browser is hooked up with a ServiceDiscoveryWindow instance """ self.window = window self.cache = window.cache self._set_initial_title() self._create_treemodel() self._add_actions() # This is a hack. The buttonbox apparently doesn't care about pack_start # or pack_end, so we repack the close button here to make sure it's last close_button = self.window.xml.get_object('close_button') self.window.action_buttonbox.remove(close_button) self.window.action_buttonbox.pack_end(close_button, True, True, 0) close_button.show_all() self.update_actions() self.active = True self.cache.get_info(self.jid, self.node, self._set_title) def cleanup(self): """ Cleanup when the window intends to switch browsers """ self.active = False self._clean_actions() self._clean_treemodel() self._clean_title() self.window._initial_state() def update_theme(self): """ Called when the default theme is changed """ pass def on_browse_button_clicked(self, widget=None): """ When we want to browse an agent: open a new services window with a browser for the agent type """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return jid = model[iter_][0] if jid: node = model[iter_][1] self.window.open(jid, node) def update_actions(self): """ When we select a row: activate action buttons based on the agent's info """ if self.browse_button: self.browse_button.set_sensitive(False) model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return jid = model[iter_][0] node = model[iter_][1] if jid: self.cache.get_info(jid, node, self._update_actions, nofetch=True) def _update_actions(self, jid, node, identities, features, data): """ Continuation of update_actions """ if not identities or not self.browse_button: return klass = self.cache.get_browser(identities, features) if klass: self.browse_button.set_sensitive(True) def default_action(self): """ When we double-click a row: perform the default action on the selected item """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return jid = model[iter_][0] node = model[iter_][1] if jid: self.cache.get_info(jid, node, self._default_action, nofetch=True) def _default_action(self, jid, node, identities, features, data): """ Continuation of default_action """ if self.cache.get_browser(identities, features): # Browse if we can self.on_browse_button_clicked() return True return False def browse(self, force=False): """ Fill the treeview with agents, fetching the info if necessary """ self.model.clear() self._total_items = self._progress = 0 self.window.progressbar.show() self._pulse_timeout = GLib.timeout_add(250, self._pulse_timeout_cb) self.cache.get_items(self.jid, self.node, self._agent_items, force=force, args=(force,)) def _pulse_timeout_cb(self, *args): """ Simple callback to keep the progressbar pulsing """ if not self.active: return False self.window.progressbar.pulse() return True def _find_item(self, jid, node): """ Check if an item is already in the treeview. Return an iter to it if so, None otherwise """ iter_ = self.model.get_iter_first() while iter_: cjid = self.model.get_value(iter_, 0) cnode = self.model.get_value(iter_, 1) if jid == cjid and node == cnode: break iter_ = self.model.iter_next(iter_) if iter_: return iter_ return None def add_self_line(self): pass def _agent_items(self, jid, node, items, force): """ Callback for when we receive a list of agent items """ self.model.clear() self.add_self_line() self._total_items = 0 GLib.source_remove(self._pulse_timeout) self.window.progressbar.hide() # The server returned an error if items == 0: if not self.window.address_comboboxtext: # We can't travel anywhere else. self.window.destroy() ErrorDialog(_('The service is not browsable'), _('This service does not contain any items to browse.'), transient_for=self.window.window) return # We got a list of items def fill_partial_rows(items): '''Generator to fill the listmodel of a treeview progressively.''' self.window.services_treeview.freeze_child_notify() for item in items: if self.window.dying: yield False jid_ = item['jid'] node_ = item.get('node', '') # If such an item is already here: don't add it if self._find_item(jid_, node_): continue self._total_items += 1 self._add_item(jid_, node_, node, item, force) if (self._total_items % 10) == 0: self.window.services_treeview.thaw_child_notify() yield True self.window.services_treeview.freeze_child_notify() self.window.services_treeview.thaw_child_notify() #stop idle_add() yield False loader = fill_partial_rows(items) GLib.idle_add(next, loader) def _agent_info(self, jid, node, identities, features, data): """ Callback for when we receive info about an agent's item """ iter_ = self._find_item(jid, node) if not iter_: # Not in the treeview, stop return if identities == 0: # The server returned an error self._update_error(iter_, jid, node) else: # We got our info self._update_info(iter_, jid, node, identities, features, data) self.update_actions() def _add_item(self, jid, node, parent_node, item, force): """ Called when an item should be added to the model. The result of a disco#items query """ self.model.append((jid, node, item.get('name', ''), get_agent_address(jid, node))) self.cache.get_info(jid, node, self._agent_info, force=force) def _update_item(self, iter_, jid, node, item): """ Called when an item should be updated in the model. The result of a disco#items query """ if 'name' in item: self.model[iter_][2] = item['name'] def _update_info(self, iter_, jid, node, identities, features, data): """ Called when an item should be updated in the model with further info. The result of a disco#info query """ name = identities[0].get('name', '') if name: self.model[iter_][2] = name def _update_error(self, iter_, jid, node): '''Called when a disco#info query failed for an item.''' pass class ToplevelAgentBrowser(AgentBrowser): """ This browser is used at the top level of a jabber server to browse services such as transports, conference servers, etc """ def __init__(self, *args): AgentBrowser.__init__(self, *args) self._progressbar_sourceid = None self._renderer = None self._progress = 0 self.register_button = None self.join_button = None self.execute_button = None self.search_button = None # Keep track of our treeview signals self._view_signals = [] self._scroll_signal = None def add_self_line(self): addr = get_agent_address(self.jid, self.node) descr = "%s" % addr # Guess which kind of service this is identities = [] type_ = app.get_transport_name_from_jid(self.jid, use_config_setting=False) if type_: identity = {'category': '_jid', 'type': type_} identities.append(identity) # Set the pixmap for the row pix = self.cache.get_icon(identities, addr=addr) self.model.append(None, (self.jid, self.node, pix, descr, LABELS[1])) # Grab info on the service self.cache.get_info(self.jid, self.node, self._agent_info, force=False) def _pixbuf_renderer_data_func(self, col, cell, model, iter_, data=None): """ Callback for setting the pixbuf renderer's properties """ jid = model.get_value(iter_, 0) if jid: pix = model.get_value(iter_, 2) cell.set_property('visible', True) cell.set_property('pixbuf', pix) else: cell.set_property('visible', False) def _text_renderer_data_func(self, col, cell, model, iter_, data=None): """ Callback for setting the text renderer's properties """ jid = model.get_value(iter_, 0) markup = model.get_value(iter_, 3) state = model.get_value(iter_, 4) cell.set_property('markup', markup) if jid: cell.set_property('cell_background_set', False) if state is not None: # fetching or error cell.set_property('foreground_set', True) else: # Normal/success cell.set_property('foreground_set', False) else: bgcolor = app.css_config.get_value('.gajim-group-row', StyleAttr.BACKGROUND) if bgcolor: cell.set_property('cell_background_set', True) cell.set_property('foreground_set', False) def _treemodel_sort_func(self, model, iter1, iter2, data=None): """ Sort function for our treemode """ # Compare state state1 = model.get_value(iter1, 4) state2 = model.get_value(iter2, 4) if state1 is not None: return 1 if state2 is not None: return -1 descr1 = model.get_value(iter1, 3) descr2 = model.get_value(iter2, 3) # Compare strings if descr1 > descr2: return 1 if descr1 < descr2: return -1 return 0 def _create_treemodel(self): # JID, node, icon, description, state # state is None on success or has a string # from LABELS on error or while fetching view = self.window.services_treeview self.model = Gtk.TreeStore(str, str, GdkPixbuf.Pixbuf, str, str) self.model.set_sort_func(4, self._treemodel_sort_func) self.model.set_sort_column_id(4, Gtk.SortType.ASCENDING) view.set_model(self.model) col = Gtk.TreeViewColumn() # Icon Renderer renderer = Gtk.CellRendererPixbuf() renderer.set_property('xpad', 6) col.pack_start(renderer, False) col.set_cell_data_func(renderer, self._pixbuf_renderer_data_func) # Text Renderer renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.set_cell_data_func(renderer, self._text_renderer_data_func) renderer.set_property('foreground', 'dark gray') # Save this so we can go along with theme changes self._renderer = renderer self.update_theme() view.set_tooltip_column(4) view.insert_column(col, -1) col.set_resizable(True) def _clean_treemodel(self): # Disconnect signals view = self.window.services_treeview for sig in self._view_signals: view.disconnect(sig) self._view_signals = [] if self._scroll_signal: scrollwin = self.window.services_scrollwin scrollwin.disconnect(self._scroll_signal) self._scroll_signal = None AgentBrowser._clean_treemodel(self) def _add_actions(self): AgentBrowser._add_actions(self) self.execute_button = Gtk.Button() self.execute_button.connect('clicked', self.on_execute_button_clicked) self.window.action_buttonbox.add(self.execute_button) image = Gtk.Image.new_from_icon_name("system-run", Gtk.IconSize.BUTTON) self.execute_button.set_image(image) label = _('Execute Command') self.execute_button.set_label(label) self.execute_button.show_all() self.register_button = Gtk.Button(label=_("Re_gister"), use_underline=True) self.register_button.connect('clicked', self.on_register_button_clicked) self.window.action_buttonbox.add(self.register_button) self.register_button.show_all() self.join_button = Gtk.Button() self.join_button.connect('clicked', self.on_join_button_clicked) self.window.action_buttonbox.add(self.join_button) label = _('Join') self.join_button.set_label(label) self.join_button.show_all() self.search_button = Gtk.Button() self.search_button.connect('clicked', self.on_search_button_clicked) self.window.action_buttonbox.add(self.search_button) image = Gtk.Image.new_from_icon_name("edit-find", Gtk.IconSize.BUTTON) self.search_button.set_image(image) label = _('Search') self.search_button.set_label(label) self.search_button.show_all() def _clean_actions(self): if self.execute_button: self.execute_button.destroy() self.execute_button = None if self.register_button: self.register_button.destroy() self.register_button = None if self.join_button: self.join_button.destroy() self.join_button = None if self.search_button: self.search_button.destroy() self.search_button = None AgentBrowser._clean_actions(self) def on_search_button_clicked(self, widget=None): """ When we want to search something: open search window """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return service = model[iter_][0] if service in app.interface.instances[self.account]['search']: app.interface.instances[self.account]['search'][service].window.\ present() else: app.interface.instances[self.account]['search'][service] = \ search_window.SearchWindow(self.account, service) def cleanup(self): AgentBrowser.cleanup(self) def update_theme(self): bgcolor = app.css_config.get_value('.gajim-group-row', StyleAttr.BACKGROUND) if bgcolor: self._renderer.set_property('cell-background', bgcolor) self.window.services_treeview.queue_draw() def on_execute_button_clicked(self, widget=None): """ When we want to execute a command: open adhoc command window """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return service = model[iter_][0] node = model[iter_][1] adhoc_commands.CommandWindow(self.account, service, commandnode=node) def on_register_button_clicked(self, widget=None): """ When we want to register an agent: request information about registering with the agent and close the window """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return jid = model[iter_][0] if jid: ServiceRegistration(self.account, jid) self.window.destroy(chain=True) def on_join_button_clicked(self, widget): """ When we want to join an IRC room or create a new MUC room: Opens the join_groupchat_window """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return service = model[iter_][0] app.interface.join_gc_minimal(self.account, service, transient_for=self.window.window) def update_actions(self): if self.execute_button: self.execute_button.set_sensitive(False) if self.register_button: self.register_button.set_sensitive(False) if self.browse_button: self.browse_button.set_sensitive(False) if self.join_button: self.join_button.set_sensitive(False) if self.search_button: self.search_button.set_sensitive(False) model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return if not model[iter_][0]: # We're on a category row return if model[iter_][4] is not None: # We don't have the info (yet) # It's either unknown or a transport, register button should be active if self.register_button: self.register_button.set_sensitive(True) # Guess what kind of service we're dealing with if self.browse_button: jid = model[iter_][0] type_ = app.get_transport_name_from_jid( jid, use_config_setting=False) if type_: identity = {'category': '_jid', 'type': type_} klass = self.cache.get_browser([identity]) if klass: self.browse_button.set_sensitive(True) else: # We couldn't guess self.browse_button.set_sensitive(True) else: # Normal case, we have info AgentBrowser.update_actions(self) def _update_actions(self, jid, node, identities, features, data): AgentBrowser._update_actions(self, jid, node, identities, features, data) if self.execute_button and nbxmpp.NS_COMMANDS in features: self.execute_button.set_sensitive(True) if self.search_button and nbxmpp.NS_SEARCH in features: self.search_button.set_sensitive(True) # Don't authorize to register with a server via disco if self.register_button and nbxmpp.NS_REGISTER in features and \ jid != self.jid: # We can register this agent registered_transports = [] jid_list = app.contacts.get_jid_list(self.account) for jid_ in jid_list: contact = app.contacts.get_first_contact_from_jid( self.account, jid_) if _('Transports') in contact.groups: registered_transports.append(jid_) registered_transports.append(self.jid) if jid in registered_transports: self.register_button.set_label(_('_Edit')) else: self.register_button.set_label(_('Re_gister')) self.register_button.set_sensitive(True) if self.join_button and nbxmpp.NS_MUC in features: self.join_button.set_sensitive(True) def _default_action(self, jid, node, identities, features, data): if AgentBrowser._default_action(self, jid, node, identities, features, data): return True if nbxmpp.NS_REGISTER in features: # Register if we can't browse self.on_register_button_clicked() return True return False def browse(self, force=False): self._progress = 0 AgentBrowser.browse(self, force=force) def _expand_all(self): """ Expand all items in the treeview """ # GTK apparently screws up here occasionally. :/ #def expand_all(*args): # self.window.services_treeview.expand_all() # self.expanding = False # return False #self.expanding = True #GLib.idle_add(expand_all) self.window.services_treeview.expand_all() def _update_progressbar(self): """ Update the progressbar """ # Refresh this every update if self._progressbar_sourceid: GLib.source_remove(self._progressbar_sourceid) fraction = 0 if self._total_items: self.window.progressbar.set_text(_("Scanning %(current)d / %(total)d.." ) % {'current': self._progress, 'total': self._total_items}) fraction = float(self._progress) / float(self._total_items) if self._progress >= self._total_items: # We show the progressbar for just a bit before hiding it. id_ = GLib.timeout_add_seconds(2, self._hide_progressbar_cb) self._progressbar_sourceid = id_ else: self.window.progressbar.show() # Hide the progressbar if we're timing out anyways. (20 secs) id_ = GLib.timeout_add_seconds(20, self._hide_progressbar_cb) self._progressbar_sourceid = id_ self.window.progressbar.set_fraction(fraction) def _hide_progressbar_cb(self, *args): """ Simple callback to hide the progressbar a second after we finish """ if self.active: self.window.progressbar.hide() return False def _friendly_category(self, category, type_=None): """ Get the friendly category name """ cat = None if type_: # Try type-specific override try: cat = _cat_to_descr[(category, type_)] except KeyError: pass if not cat: try: cat = _cat_to_descr[category] except KeyError: cat = _cat_to_descr['other'] return cat def _create_category(self, cat, type_=None): """ Creates a category row """ cat = self._friendly_category(cat, type_) return self.model.append(None, ('', '', None, cat, None)) def _find_category(self, cat, type_=None): """ Looks up a category row and returns the iterator to it, or None """ cat = self._friendly_category(cat, type_) iter_ = self.model.get_iter_first() while iter_: if self.model.get_value(iter_, 3) == cat: break iter_ = self.model.iter_next(iter_) if iter_: return iter_ return None def _find_item(self, jid, node): iter_ = None cat_iter = self.model.get_iter_first() while cat_iter and not iter_: cjid = self.model.get_value(cat_iter, 0) cnode = self.model.get_value(cat_iter, 1) if jid == cjid and node == cnode: iter_ = cat_iter break iter_ = self.model.iter_children(cat_iter) while iter_: cjid = self.model.get_value(iter_, 0) cnode = self.model.get_value(iter_, 1) if jid == cjid and node == cnode: break iter_ = self.model.iter_next(iter_) cat_iter = self.model.iter_next(cat_iter) if iter_: return iter_ return None def _add_item(self, jid, node, parent_node, item, force): # Row text addr = get_agent_address(jid, node) if 'name' in item: descr = "%s\n%s" % (item['name'], addr) else: descr = "%s" % addr # Guess which kind of service this is identities = [] type_ = app.get_transport_name_from_jid( jid, use_config_setting=False) if type_: identity = {'category': '_jid', 'type': type_} identities.append(identity) cat_args = ('_jid', type_) else: # Put it in the 'other' category for now cat_args = ('other',) # Set the pixmap for the row pix = self.cache.get_icon(identities, addr=addr) # Put it in the right category cat = self._find_category(*cat_args) if not cat: cat = self._create_category(*cat_args) self.model.append(cat, (jid, node, pix, descr, LABELS[1])) GLib.idle_add(self._expand_all) # Grab info on the service self.cache.get_info(jid, node, self._agent_info, force=force) self._update_progressbar() def _update_item(self, iter_, jid, node, item): addr = get_agent_address(jid, node) if 'name' in item: descr = "%s\n%s" % (item['name'], addr) else: descr = "%s" % addr self.model[iter_][3] = descr def _update_info(self, iter_, jid, node, identities, features, data): addr = get_agent_address(jid, node) if not identities: descr = "%s" % addr else: name = identities[0].get('name', '') if name: descr = "%s\n%s" % (name, addr) else: descr = "%s" % addr # Update progress self._progress += 1 self._update_progressbar() # Search for an icon and category we can display pix = self.cache.get_icon(identities, addr=addr) cat, type_ = None, None for identity in identities: try: cat, type_ = identity['category'], identity['type'] except KeyError: continue break # Check if we have to move categories old_cat_iter = self.model.iter_parent(iter_) if not old_cat_iter or self.model.get_value(old_cat_iter, 3) == cat: # Already in the right category, just update self.model[iter_][2] = pix self.model[iter_][3] = descr self.model[iter_][4] = None return # Not in the right category, move it. self.model.remove(iter_) old_cat = self.model.get_value(old_cat_iter, 3) # Check if the old category is empty if not self.model.iter_is_valid(old_cat_iter): old_cat_iter = self._find_category(old_cat) if not self.model.iter_children(old_cat_iter): self.model.remove(old_cat_iter) cat_iter = self._find_category(cat, type_) if not cat_iter: cat_iter = self._create_category(cat, type_) self.model.append(cat_iter, (jid, node, pix, descr, None)) self._expand_all() def _update_error(self, iter_, jid, node): self.model[iter_][4] = LABELS[2] self._progress += 1 self._update_progressbar() class MucBrowser(AgentBrowser): def __init__(self, *args, **kwargs): AgentBrowser.__init__(self, *args, **kwargs) self.join_button = None self.bookmark_button = None def _create_treemodel(self): # JID, node, name, users_int, users_str, description, fetched # This is rather long, I'd rather not use a data_func here though. # Users is a string, because want to be able to leave it empty. self.model = Gtk.ListStore(str, str, str, int, str, str, bool) self.model.set_sort_column_id(2, Gtk.SortType.ASCENDING) self.window.services_treeview.set_model(self.model) # Name column col = Gtk.TreeViewColumn(_('Name')) col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) col.set_fixed_width(100) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', 2) col.set_sort_column_id(2) self.window.services_treeview.insert_column(col, -1) col.set_resizable(True) # Users column col = Gtk.TreeViewColumn(_('Users')) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', 4) col.set_sort_column_id(3) self.window.services_treeview.insert_column(col, -1) col.set_resizable(True) # Description column col = Gtk.TreeViewColumn(_('Description')) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', 5) col.set_sort_column_id(4) self.window.services_treeview.insert_column(col, -1) col.set_resizable(True) # Id column col = Gtk.TreeViewColumn(_('Id')) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', 0) col.set_sort_column_id(0) self.window.services_treeview.insert_column(col, -1) col.set_resizable(True) self.window.services_treeview.set_headers_visible(True) self.window.services_treeview.set_headers_clickable(True) # Source id for idle callback used to start disco#info queries. self._fetch_source = None # Query failure counter self._broken = 0 # Connect to scrollwindow scrolling self.vadj = self.window.services_scrollwin.get_property('vadjustment') self.vadj_cbid = self.vadj.connect('value-changed', self.on_scroll) # And to size changes self.size_cbid = self.window.services_scrollwin.connect( 'size-allocate', self.on_scroll) def _clean_treemodel(self): if self.size_cbid: self.window.services_scrollwin.disconnect(self.size_cbid) self.size_cbid = None if self.vadj_cbid: self.vadj.disconnect(self.vadj_cbid) self.vadj_cbid = None AgentBrowser._clean_treemodel(self) def _add_actions(self): self.bookmark_button = Gtk.Button(label=_('_Bookmark'), use_underline=True) self.bookmark_button.connect('clicked', self.on_bookmark_button_clicked) self.window.action_buttonbox.add(self.bookmark_button) self.bookmark_button.show_all() self.join_button = Gtk.Button(label=_('_Join'), use_underline=True) self.join_button.connect('clicked', self.on_join_button_clicked) self.window.action_buttonbox.add(self.join_button) self.join_button.show_all() def _clean_actions(self): if self.bookmark_button: self.bookmark_button.destroy() self.bookmark_button = None if self.join_button: self.join_button.destroy() self.join_button = None def on_bookmark_button_clicked(self, *args): con = app.connections[self.account] model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return room_jid = model[iter_][0] if room_jid in con.get_module('Bookmarks').bookmarks: ErrorDialog( _('Bookmark already set'), _('Group Chat "%s" is already in your bookmarks.') % room_jid, transient_for=self.window.window) return con.get_module('Bookmarks').add_bookmark(room_jid.split('@')[0], room_jid, False, False, '', '') InformationDialog( _('Bookmark has been added successfully'), _('You can manage your bookmarks via Actions menu in your roster.'), transient_for=self.window.window) def on_join_button_clicked(self, *args): """ When we want to join a conference: ask specific informations about the selected agent and close the window """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_: return service = model[iter_][0] window = app.get_app_window('JoinGroupchatWindow') if window is None: app.interface.join_gc_minimal(self.account, service) else: window.set_room(service) window.present() self.window.destroy() def update_actions(self): sens = self.window.services_treeview.get_selection().count_selected_rows() if self.bookmark_button: self.bookmark_button.set_sensitive(sens > 0) if self.join_button: self.join_button.set_sensitive(sens > 0) def default_action(self): self.on_join_button_clicked() def _start_info_query(self): """ Idle callback to start checking for visible rows """ self._fetch_source = None self._query_visible() return False def on_scroll(self, *args): """ Scrollwindow callback to trigger new queries on scrolling """ # This apparently happens when inactive sometimes self._query_visible() def _query_visible(self): """ Query the next visible row for info """ if self._fetch_source: # We're already fetching return view = self.window.services_treeview if not view.get_realized(): # Prevent a silly warning, try again in a bit. self._fetch_source = GLib.timeout_add(100, self._start_info_query) return range_ = view.get_visible_range() if not range_: return start, end = range_ iter_ = self.model.get_iter(start) while iter_: if not self.model.get_value(iter_, 6): jid = self.model.get_value(iter_, 0) node = self.model.get_value(iter_, 1) self.cache.get_info(jid, node, self._agent_info) self._fetch_source = True return if self.model.get_path(iter_) == end: break iter_ = self.model.iter_next(iter_) self._fetch_source = None def _channel_altinfo(self, jid, node, items, name=None): """ Callback for the alternate disco#items query. We try to at least get the amount of users in the room if the service does not support MUC dataforms """ if items == 0: # The server returned an error self._broken += 1 if self._broken >= 3: # Disable queries completely after 3 failures if self.size_cbid: self.window.services_scrollwin.disconnect(self.size_cbid) self.size_cbid = None if self.vadj_cbid: self.vadj.disconnect(self.vadj_cbid) self.vadj_cbid = None self._fetch_source = None return else: iter_ = self._find_item(jid, node) if iter_: if name: self.model[iter_][2] = name self.model[iter_][3] = len(items) # The number of users self.model[iter_][4] = str(len(items)) # The number of users self.model[iter_][6] = True self._fetch_source = None self._query_visible() def _add_item(self, jid, node, parent_node, item, force): self.model.append((jid, node, item.get('name', ''), -1, '', '', False)) if not self._fetch_source: self._fetch_source = GLib.idle_add(self._start_info_query) def _update_info(self, iter_, jid, node, identities, features, data): name = identities[0].get('name', '') for form in data: typefield = form.getField('FORM_TYPE') if typefield and typefield.getValue() == \ 'http://jabber.org/protocol/muc#roominfo': # Fill model row from the form's fields users = form.getField('muc#roominfo_occupants') descr = form.getField('muc#roominfo_description') if users: self.model[iter_][3] = int(users.getValue()) self.model[iter_][4] = users.getValue() if descr and descr.getValue(): self.model[iter_][5] = descr.getValue() # Only set these when we find a form with additional info # Some servers don't support forms and put extra info in # the name attribute, so we preserve it in that case. self.model[iter_][2] = name self.model[iter_][6] = True break else: # We didn't find a form, switch to alternate query mode self.cache.get_items(jid, node, self._channel_altinfo, args=(name,)) return # Continue with the next self._fetch_source = None self._query_visible() def _update_error(self, iter_, jid, node): # switch to alternate query mode self.cache.get_items(jid, node, self._channel_altinfo) def PubSubBrowser(account, jid, node): """ Return an AgentBrowser subclass that will display service discovery for particular pubsub service. Different pubsub services may need to present different data during browsing """ # for now, only discussion groups are supported... # TODO: check if it has appropriate features to be such kind of service return DiscussionGroupsBrowser(account, jid, node) class DiscussionGroupsBrowser(AgentBrowser): """ For browsing pubsub-based discussion groups service """ def __init__(self, account, jid, node): AgentBrowser.__init__(self, account, jid, node) # this will become set object when we get subscriptions; None means # we don't know yet which groups are subscribed self.subscriptions = None # this will become our action widgets when we create them; None means # we don't have them yet (needed for check in callback) self.subscribe_button = None self.unsubscribe_button = None con = app.connections[account] con.get_module('PubSub').send_pb_subscription_query( jid, self._on_pep_subscriptions) def _create_treemodel(self): """ Create treemodel for the window """ # JID, node, name (with description) - pango markup, don't have info?, subscribed? self.model = Gtk.TreeStore(str, str, str, bool, bool) # sort by name self.model.set_sort_column_id(2, Gtk.SortType.ASCENDING) self.window.services_treeview.set_model(self.model) # Name column # Pango markup for name and description, description printed with # font renderer = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('Name')) col.pack_start(renderer, True) col.add_attribute(renderer, 'markup', 2) col.set_resizable(True) self.window.services_treeview.insert_column(col, -1) self.window.services_treeview.set_headers_visible(True) # Subscription state renderer = Gtk.CellRendererToggle() col = Gtk.TreeViewColumn(_('Subscribed')) col.pack_start(renderer, True) col.add_attribute(renderer, 'inconsistent', 3) col.add_attribute(renderer, 'active', 4) col.set_resizable(False) self.window.services_treeview.insert_column(col, -1) # Node Column renderer = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('Node')) col.pack_start(renderer, True) col.add_attribute(renderer, 'markup', 1) col.set_resizable(True) self.window.services_treeview.insert_column(col, -1) def _add_items(self, jid, node, items, force): for item in items: jid_ = item['jid'] node_ = item.get('node', '') self._total_items += 1 self._add_item(jid_, node_, node, item, force) def _in_list_foreach(self, model, path, iter_, node): if model[path][1] == node: self.in_list = True def _in_list(self, node): self.in_list = False self.model.foreach(self._in_list_foreach, node) return self.in_list def _add_item(self, jid, node, parent_node, item, force): """ Called when we got basic information about new node from query. Show the item """ name = item.get('name', '') if self.subscriptions is not None: dunno = False subscribed = node in self.subscriptions else: dunno = True subscribed = False name = GLib.markup_escape_text(name) name = '%s' % name if parent_node: parent_iter = self._get_iter(parent_node) else: parent_iter = None if not node or not self._in_list(node): self.model.append(parent_iter, (jid, node, name, dunno, subscribed)) self.cache.get_items( jid, node, self._add_items, force=force, args=(force,)) def _get_child_iter(self, parent_iter, node): child_iter = self.model.iter_children(parent_iter) while child_iter: if self.model[child_iter][1] == node: return child_iter child_iter = self.model.iter_next(child_iter) return None def _get_iter(self, node): ''' Look for an iter with the given node ''' self.found_iter = None def is_node(model, path, iter_, node): if model[iter_][1] == node: self.found_iter = iter_ return True self.model.foreach(is_node, node) return self.found_iter def _add_actions(self): self.post_button = Gtk.Button(label=_('New post'), use_underline=True) self.post_button.set_sensitive(False) self.post_button.connect('clicked', self.on_post_button_clicked) self.window.action_buttonbox.add(self.post_button) self.post_button.show_all() self.subscribe_button = Gtk.Button(label=_('_Subscribe'), use_underline=True) self.subscribe_button.set_sensitive(False) self.subscribe_button.connect('clicked', self.on_subscribe_button_clicked) self.window.action_buttonbox.add(self.subscribe_button) self.subscribe_button.show_all() self.unsubscribe_button = Gtk.Button(label=_('_Unsubscribe'), use_underline=True) self.unsubscribe_button.set_sensitive(False) self.unsubscribe_button.connect('clicked', self.on_unsubscribe_button_clicked) self.window.action_buttonbox.add(self.unsubscribe_button) self.unsubscribe_button.show_all() def _clean_actions(self): if self.post_button is not None: self.post_button.destroy() self.post_button = None if self.subscribe_button is not None: self.subscribe_button.destroy() self.subscribe_button = None if self.unsubscribe_button is not None: self.unsubscribe_button.destroy() self.unsubscribe_button = None def update_actions(self): """ Called when user selected a row. Make subscribe/unsubscribe buttons sensitive appropriately """ # we have nothing to do if we don't have buttons... if self.subscribe_button is None: return model, iter_ = self.window.services_treeview.get_selection().get_selected() if not iter_ or self.subscriptions is None: # no item selected or no subscriptions info, all buttons are insensitive self.post_button.set_sensitive(False) self.subscribe_button.set_sensitive(False) self.unsubscribe_button.set_sensitive(False) else: subscribed = model.get_value(iter_, 4) # 4 = subscribed? self.post_button.set_sensitive(subscribed) self.subscribe_button.set_sensitive(not subscribed) self.unsubscribe_button.set_sensitive(subscribed) def on_post_button_clicked(self, widget): """ Called when 'post' button is pressed. Open window to create post """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if iter_ is None: return groupnode = model.get_value(iter_, 1) # 1 = groupnode groups.GroupsPostWindow(self.account, self.jid, groupnode) def on_subscribe_button_clicked(self, widget): """ Called when 'subscribe' button is pressed. Send subscribtion request """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if iter_ is None: return node = model.get_value(iter_, 1) # 1 = groupnode con = app.connections[self.account] con.get_module('PubSub').send_pb_subscribe( self.jid, node, self._on_pep_subscribe, groupnode=node) def on_unsubscribe_button_clicked(self, widget): """ Called when 'unsubscribe' button is pressed. Send unsubscription request """ model, iter_ = self.window.services_treeview.get_selection().get_selected() if iter_ is None: return node = model.get_value(iter_, 1) # 1 = groupnode con = app.connections[self.account] con.get_module('PubSub').send_pb_unsubscribe( self.jid, node, self._on_pep_unsubscribe, groupnode=node) def _on_pep_subscriptions(self, conn, request): """ We got the subscribed groups list stanza. Now, if we already have items on the list, we should actualize them """ try: subscriptions = request.getTag('pubsub').getTag('subscriptions') except Exception: return groups_ = set() for child in subscriptions.getTags('subscription'): groups_.add(child['node']) self.subscriptions = groups_ # try to setup existing items in model model = self.window.services_treeview.get_model() for row in model: # 1 = group node # 3 = insensitive checkbox for subscribed # 4 = subscribed? groupnode = row[1] row[3] = False row[4] = groupnode in groups_ # we now know subscriptions, update button states self.update_actions() def _on_pep_subscribe(self, conn, request, groupnode): """ We have just subscribed to a node. Update UI """ self.subscriptions.add(groupnode) model = self.window.services_treeview.get_model() for row in model: if row[1] == groupnode: # 1 = groupnode row[4] = True break self.update_actions() def _on_pep_unsubscribe(self, conn, request, groupnode): """ We have just unsubscribed from a node. Update UI """ self.subscriptions.remove(groupnode) model = self.window.services_treeview.get_model() for row in model: if row[1] == groupnode: # 1 = groupnode row[4] = False break self.update_actions() # Fill the global agent type info dictionary _agent_type_info = _gen_agent_type_info() gajim-gajim-1.1.3/gajim/filetransfers_window.py000066400000000000000000001247311345766322700216160ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Dimitur Kirov # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2006 Travis Shirk # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import time import logging from functools import partial from pathlib import Path from enum import IntEnum, unique from datetime import datetime from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import GLib from gi.repository import Pango from nbxmpp.protocol import NS_JINGLE_FILE_TRANSFER_5 from gajim import gtkgui_helpers from gajim import tooltips from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.file_props import FilesProp from gajim.common.protocol.bytestream import (is_transfer_active, is_transfer_paused, is_transfer_stopped) from gajim.gtk.dialogs import HigDialog from gajim.gtk.dialogs import InformationDialog from gajim.gtk.dialogs import YesNoDialog from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import FTOverwriteConfirmationDialog from gajim.gtk.dialogs import NonModalConfirmationDialog from gajim.gtk.filechoosers import FileSaveDialog from gajim.gtk.filechoosers import FileChooserDialog log = logging.getLogger('gajim.filetransfer_window') @unique class Column(IntEnum): IMAGE = 0 LABELS = 1 FILE = 2 TIME = 3 PROGRESS = 4 PERCENT = 5 PULSE = 6 SID = 7 class FileTransfersWindow: def __init__(self): self.files_props = {'r' : {}, 's': {}} self.height_diff = 0 self.xml = gtkgui_helpers.get_gtk_builder('filetransfers.ui') self.window = self.xml.get_object('file_transfers_window') self.tree = self.xml.get_object('transfers_list') self.cancel_button = self.xml.get_object('cancel_button') self.pause_button = self.xml.get_object('pause_restore_button') self.cleanup_button = self.xml.get_object('cleanup_button') self.notify_ft_checkbox = self.xml.get_object( 'notify_ft_complete_checkbox') shall_notify = app.config.get('notify_on_file_complete') self.notify_ft_checkbox.set_active(shall_notify) self.model = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, str, str, int, int, str) self.tree.set_model(self.model) col = Gtk.TreeViewColumn() render_pixbuf = Gtk.CellRendererPixbuf() col.pack_start(render_pixbuf, True) render_pixbuf.set_property('xpad', 3) render_pixbuf.set_property('ypad', 3) render_pixbuf.set_property('yalign', .0) col.add_attribute(render_pixbuf, 'pixbuf', 0) self.tree.append_column(col) col = Gtk.TreeViewColumn(_('File')) renderer = Gtk.CellRendererText() col.pack_start(renderer, False) col.add_attribute(renderer, 'markup', Column.LABELS) renderer.set_property('yalign', 0.) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'markup', Column.FILE) renderer.set_property('xalign', 0.) renderer.set_property('yalign', 0.) renderer.set_property('ellipsize', Pango.EllipsizeMode.END) col.set_resizable(True) col.set_expand(True) self.tree.append_column(col) col = Gtk.TreeViewColumn(_('Time')) renderer = Gtk.CellRendererText() col.pack_start(renderer, False) col.add_attribute(renderer, 'markup', Column.TIME) renderer.set_property('yalign', 0.5) renderer.set_property('xalign', 0.5) renderer = Gtk.CellRendererText() renderer.set_property('ellipsize', Pango.EllipsizeMode.END) col.set_resizable(True) col.set_expand(False) self.tree.append_column(col) col = Gtk.TreeViewColumn(_('Progress')) renderer = Gtk.CellRendererProgress() renderer.set_property('yalign', 0.5) renderer.set_property('xalign', 0.5) col.pack_start(renderer, False) col.add_attribute(renderer, 'text', Column.PROGRESS) col.add_attribute(renderer, 'value', Column.PERCENT) col.add_attribute(renderer, 'pulse', Column.PULSE) col.set_resizable(True) col.set_expand(False) self.tree.append_column(col) self.images = {} self.icons = { 'upload': 'go-up', 'download': 'go-down', 'stop': 'window-close', 'waiting': 'view-refresh', 'pause': 'media-playback-pause', 'continue': 'media-playback-start', 'ok': 'emblem-ok-symbolic', 'computing': 'system-run', 'hash_error': 'network-error-symbolic', } self.tree.get_selection().set_mode(Gtk.SelectionMode.SINGLE) self.tree.get_selection().connect('changed', self.selection_changed) # Tooltip self.tree.connect('query-tooltip', self._query_tooltip) self.tree.set_has_tooltip(True) self.tooltip = tooltips.FileTransfersTooltip() self.file_transfers_menu = self.xml.get_object('file_transfers_menu') self.open_folder_menuitem = self.xml.get_object('open_folder_menuitem') self.cancel_menuitem = self.xml.get_object('cancel_menuitem') self.pause_menuitem = self.xml.get_object('pause_menuitem') self.continue_menuitem = self.xml.get_object('continue_menuitem') self.remove_menuitem = self.xml.get_object('remove_menuitem') self.xml.connect_signals(self) def _query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): try: x_pos, y_pos = widget.convert_widget_to_bin_window_coords( x_pos, y_pos) row = widget.get_path_at_pos(x_pos, y_pos)[0] except TypeError: self.tooltip.clear_tooltip() return False if not row: self.tooltip.clear_tooltip() return False iter_ = None try: model = widget.get_model() iter_ = model.get_iter(row) except Exception: self.tooltip.clear_tooltip() return False sid = self.model[iter_][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) value, widget = self.tooltip.get_tooltip(file_props, sid) tooltip.set_custom(widget) return value def find_transfer_by_jid(self, account, jid): """ Find all transfers with peer 'jid' that belong to 'account' """ active_transfers = [[], []] # ['senders', 'receivers'] allfp = FilesProp.getAllFileProp() for file_props in allfp: if file_props.type_ == 's' and file_props.tt_account == account: # 'account' is the sender receiver_jid = file_props.receiver.split('/')[0] if jid == receiver_jid and not is_transfer_stopped(file_props): active_transfers[0].append(file_props) elif file_props.type_ == 'r' and file_props.tt_account == account: # 'account' is the recipient sender_jid = file_props.sender.split('/')[0] if jid == sender_jid and not is_transfer_stopped(file_props): active_transfers[1].append(file_props) else: raise Exception('file_props has no type') return active_transfers def show_completed(self, jid, file_props): """ Show a dialog saying that file (file_props) has been transferred """ def on_open(widget, file_props): dialog.destroy() if not file_props.file_name: return path = os.path.split(file_props.file_name)[0] if os.path.exists(path) and os.path.isdir(path): helpers.launch_file_manager(path) self.tree.get_selection().unselect_all() if file_props.type_ == 'r': # file path is used below in 'Save in' (file_path, file_name) = os.path.split(file_props.file_name) else: file_name = file_props.name sectext = '\t' + _('Filename: %s') % GLib.markup_escape_text(file_name) sectext += '\n\t' + _('Size: %s') % \ helpers.convert_bytes(file_props.size) if file_props.type_ == 'r': jid = file_props.sender.split('/')[0] sender_name = app.contacts.get_first_contact_from_jid( file_props.tt_account, jid).get_shown_name() sender = sender_name else: #You is a reply of who sent a file sender = _('You') sectext += '\n\t' + _('Sender: %s') % sender sectext += '\n\t' + _('Recipient: ') if file_props.type_ == 's': jid = file_props.receiver.split('/')[0] receiver_name = app.contacts.get_first_contact_from_jid( file_props.tt_account, jid).get_shown_name() recipient = receiver_name else: #You is a reply of who received a file recipient = _('You') sectext += recipient if file_props.type_ == 'r': sectext += '\n\t' + _('Saved in: %s') % file_path dialog = HigDialog(app.interface.roster.window, Gtk.MessageType.INFO, Gtk.ButtonsType.NONE, _('File transfer completed'), sectext) if file_props.type_ == 'r': button = Gtk.Button.new_with_mnemonic(_('Open _Containing Folder')) button.connect('clicked', on_open, file_props) dialog.action_area.pack_start(button, True, True, 0) ok_button = dialog.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK) def on_ok(widget): dialog.destroy() ok_button.connect('clicked', on_ok) dialog.show_all() def show_request_error(self, file_props): """ Show error dialog to the recipient saying that transfer has been canceled """ InformationDialog(_('File transfer cancelled'), _('Connection with peer cannot be established.')) self.tree.get_selection().unselect_all() def show_send_error(self, file_props): """ Show error dialog to the sender saying that transfer has been canceled """ InformationDialog(_('File transfer cancelled'), _('Connection with peer cannot be established.')) self.tree.get_selection().unselect_all() def show_stopped(self, jid, file_props, error_msg=''): if file_props.type_ == 'r': file_name = os.path.basename(file_props.file_name) else: file_name = file_props.name sectext = '\t' + _('Filename: %s') % GLib.markup_escape_text(file_name) sectext += '\n\t' + _('Recipient: %s') % jid if error_msg: sectext += '\n\t' + _('Error message: %s') % error_msg ErrorDialog(_('File transfer stopped'), sectext) self.tree.get_selection().unselect_all() def show_hash_error(self, jid, file_props, account): def on_yes(dummy, fjid, file_props, account): # Delete old file os.remove(file_props.file_name) jid, resource = app.get_room_and_nick_from_fjid(fjid) if resource: contact = app.contacts.get_contact(account, jid, resource) else: contact = app.contacts.get_contact_with_highest_priority( account, jid) fjid = contact.get_full_jid() # Request the file to the sender sid = helpers.get_random_string_16() new_file_props = FilesProp.getNewFileProp(account, sid) new_file_props.file_name = file_props.file_name new_file_props.name = file_props.name new_file_props.desc = file_props.desc new_file_props.size = file_props.size new_file_props.date = file_props.date new_file_props.hash_ = file_props.hash_ new_file_props.type_ = 'r' tsid = app.connections[account].start_file_transfer(fjid, new_file_props, True) new_file_props.transport_sid = tsid self.add_transfer(account, contact, new_file_props) if file_props.type_ == 'r': file_name = os.path.basename(file_props.file_name) else: file_name = file_props.name YesNoDialog(('File transfer error'), _('The file %(file)s has been received, but it seems to have ' 'been damaged along the way.\nDo you want to download it again?') % \ {'file': file_name}, on_response_yes=(on_yes, jid, file_props, account), type_=Gtk.MessageType.ERROR) def show_file_send_request(self, account, contact): send_callback = partial(self.send_file, account, contact) SendFileDialog(send_callback, self.window) def send_file(self, account, contact, file_path, file_desc=''): """ Start the real transfer(upload) of the file """ if gtkgui_helpers.file_is_locked(file_path): pritext = _('Gajim can not read this file') sextext = _('Another process is using this file.') ErrorDialog(pritext, sextext) return if isinstance(contact, str): if contact.find('/') == -1: return (jid, resource) = contact.split('/', 1) contact = app.contacts.create_contact(jid=jid, account=account, resource=resource) file_name = os.path.split(file_path)[1] file_props = self.get_send_file_props(account, contact, file_path, file_name, file_desc) if file_props is None: return False if contact.supports(NS_JINGLE_FILE_TRANSFER_5): log.info('contact %s supports jingle file transfer', contact.get_full_jid()) app.connections[account].start_file_transfer(contact.get_full_jid(), file_props) self.add_transfer(account, contact, file_props) else: log.info('contact does not support jingle file transfer') file_props.transport_sid = file_props.sid app.connections[account].send_file_request(file_props) self.add_transfer(account, contact, file_props) return True def _start_receive(self, file_path, account, contact, file_props): file_dir = os.path.dirname(file_path) if file_dir: app.config.set('last_save_dir', file_dir) file_props.file_name = file_path file_props.type_ = 'r' self.add_transfer(account, contact, file_props) app.connections[account].send_file_approval(file_props) def on_file_request_accepted(self, account, contact, file_props): def on_ok(account, contact, file_props, file_path): if os.path.exists(file_path): app.config.set('last_save_dir', os.path.dirname(file_path)) # check if we have write permissions if not os.access(file_path, os.W_OK): file_name = GLib.markup_escape_text(os.path.basename( file_path)) ErrorDialog( _('Cannot overwrite existing file "%s"' % file_name), _('A file with this name already exists and you do not ' 'have permission to overwrite it.')) return stat = os.stat(file_path) dl_size = stat.st_size file_size = file_props.size dl_finished = dl_size >= file_size def on_response(response): if response < 0: return if response == 100: file_props.offset = dl_size self._start_receive(file_path, account, contact, file_props) dialog = FTOverwriteConfirmationDialog( _('This file already exists'), _('What do you want to do?'), propose_resume=not dl_finished, on_response=on_response) dialog.set_destroy_with_parent(True) return dirname = os.path.dirname(file_path) if not os.access(dirname, os.W_OK) and os.name != 'nt': # read-only bit is used to mark special folder under # windows, not to mark that a folder is read-only. # See ticket #3587 ErrorDialog( _('Directory "%s" is not writable') % dirname, _('You do not have permission to create files ' 'in this directory.')) return self._start_receive(file_path, account, contact, file_props) con = app.connections[account] accept_cb = partial(on_ok, account, contact, file_props) cancel_cb = partial(con.send_file_rejection, file_props) FileSaveDialog(accept_cb, cancel_cb, path=app.config.get('last_save_dir'), file_name=file_props.name) def show_file_request(self, account, contact, file_props): """ Show dialog asking for comfirmation and store location of new file requested by a contact """ if not file_props or not file_props.name: return sec_text = '\t' + _('File: %s') % GLib.markup_escape_text( file_props.name) if file_props.size: sec_text += '\n\t' + _('Size: %s') % \ helpers.convert_bytes(file_props.size) if file_props.mime_type: sec_text += '\n\t' + _('Type: %s') % file_props.mime_type if file_props.desc: sec_text += '\n\t' + _('Description: %s') % file_props.desc prim_text = _('%s wants to send you a file:') % contact.jid dialog = None def on_response_ok(account, contact, file_props): self.on_file_request_accepted(account, contact, file_props) def on_response_cancel(account, file_props): app.connections[account].send_file_rejection(file_props) dialog = NonModalConfirmationDialog(prim_text, sec_text, on_response_ok=(on_response_ok, account, contact, file_props), on_response_cancel=(on_response_cancel, account, file_props)) dialog.connect('delete-event', lambda widget, event: on_response_cancel(account, file_props)) dialog.popup() def get_icon(self, ident): return self.images.setdefault(ident, gtkgui_helpers.get_icon_pixmap(self.icons[ident], 24)) def set_status(self, file_props, status): """ Change the status of a transfer to state 'status' """ iter_ = self.get_iter_by_sid(file_props.type_, file_props.sid) if iter_ is None: return if status == 'stop': file_props.stopped = True elif status == 'ok': file_props.completed = True text = self._format_percent(100) received_size = int(file_props.received_len) full_size = file_props.size text += helpers.convert_bytes(received_size) + '/' + \ helpers.convert_bytes(full_size) self.model.set(iter_, Column.PROGRESS, text) self.model.set(iter_, Column.PULSE, GLib.MAXINT32) elif status == 'computing': self.model.set(iter_, Column.PULSE, 1) text = _('Checking file…') + '\n' received_size = int(file_props.received_len) full_size = file_props.size text += helpers.convert_bytes(received_size) + '/' + \ helpers.convert_bytes(full_size) self.model.set(iter_, Column.PROGRESS, text) def pulse(): p = self.model.get(iter_, Column.PULSE)[0] if p == GLib.MAXINT32: return False self.model.set(iter_, Column.PULSE, p + 1) return True GLib.timeout_add(100, pulse) elif status == 'hash_error': text = _('File error') + '\n' received_size = int(file_props.received_len) full_size = file_props.size text += helpers.convert_bytes(received_size) + '/' + \ helpers.convert_bytes(full_size) self.model.set(iter_, Column.PROGRESS, text) self.model.set(iter_, Column.PULSE, GLib.MAXINT32) self.model.set(iter_, Column.IMAGE, self.get_icon(status)) path = self.model.get_path(iter_) self.select_func(path) def _format_percent(self, percent): """ Add extra spaces from both sides of the percent, so that progress string has always a fixed size """ _str = ' ' if percent != 100.: _str += ' ' if percent < 10: _str += ' ' _str += str(percent) + '% \n' return _str def _format_time(self, _time): times = {'hours': 0, 'minutes': 0, 'seconds': 0} _time = int(_time) times['seconds'] = _time % 60 if _time >= 60: _time /= 60 times['minutes'] = _time % 60 if _time >= 60: times['hours'] = _time / 60 #Print remaining time in format 00:00:00 #You can change the places of (hours), (minutes), (seconds) - #they are not translatable. return _('%(hours)02.d:%(minutes)02.d:%(seconds)02.d') % times def _get_eta_and_speed(self, full_size, transfered_size, file_props): if not file_props.transfered_size: return 0., 0. if len(file_props.transfered_size) == 1: speed = round(float(transfered_size) / file_props.elapsed_time) else: # first and last are (time, transfered_size) first = file_props.transfered_size[0] last = file_props.transfered_size[-1] transfered = last[1] - first[1] tim = last[0] - first[0] if tim == 0: return 0., 0. speed = round(float(transfered) / tim) if speed == 0.: return 0., 0. remaining_size = full_size - transfered_size eta = remaining_size / speed return eta, speed def _remove_transfer(self, iter_, sid, file_props): self.model.remove(iter_) if not file_props: return if file_props.tt_account: # file transfer is set account = file_props.tt_account if account in app.connections: # there is a connection to the account app.connections[account].remove_transfer(file_props) if file_props.type_ == 'r': # we receive a file other = file_props.sender else: # we send a file other = file_props.receiver if isinstance(other, str): jid = app.get_jid_without_resource(other) else: # It's a Contact instance jid = other.jid for ev_type in ('file-error', 'file-completed', 'file-request-error', 'file-send-error', 'file-stopped'): for event in app.events.get_events(account, jid, [ev_type]): if event.file_props.sid == file_props.sid: app.events.remove_events(account, jid, event) app.interface.roster.draw_contact(jid, account) app.interface.roster.show_title() FilesProp.deleteFileProp(file_props) del file_props def set_progress(self, typ, sid, transfered_size, iter_=None): """ Change the progress of a transfer with new transfered size """ file_props = FilesProp.getFilePropByType(typ, sid) full_size = file_props.size if full_size == 0: percent = 0 else: percent = round(float(transfered_size) / full_size * 100, 1) if iter_ is None: iter_ = self.get_iter_by_sid(typ, sid) if iter_ is not None: just_began = False if self.model[iter_][Column.PERCENT] == 0 and int(percent > 0): just_began = True text = self._format_percent(percent) if transfered_size == 0: text += '0' else: text += helpers.convert_bytes(transfered_size) text += '/' + helpers.convert_bytes(full_size) # Kb/s # remaining time if file_props.offset: transfered_size -= file_props.offset full_size -= file_props.offset if file_props.elapsed_time > 0: file_props.transfered_size.append((file_props.last_time, transfered_size)) if len(file_props.transfered_size) > 6: file_props.transfered_size.pop(0) eta, speed = self._get_eta_and_speed(full_size, transfered_size, file_props) self.model.set(iter_, Column.PROGRESS, text) self.model.set(iter_, Column.PERCENT, int(percent)) text = self._format_time(eta) text += '\n' #This should make the string Kb/s, #where 'Kb' part is taken from %s. #Only the 's' after / (which means second) should be translated. text += _('(%(filesize_unit)s/s)') % {'filesize_unit': helpers.convert_bytes(speed)} self.model.set(iter_, Column.TIME, text) # try to guess what should be the status image if file_props.type_ == 'r': status = 'download' else: status = 'upload' if file_props.paused is True: status = 'pause' elif file_props.stalled is True: status = 'waiting' if file_props.connected is False: status = 'stop' self.model.set(iter_, 0, self.get_icon(status)) if transfered_size == full_size: # If we are receiver and this is a jingle session if file_props.type_ == 'r' and \ file_props.session_type == 'jingle' and file_props.hash_: # Show that we are computing the hash self.set_status(file_props, 'computing') else: self.set_status(file_props, 'ok') elif just_began: path = self.model.get_path(iter_) self.select_func(path) def get_iter_by_sid(self, typ, sid): """ Return iter to the row, which holds file transfer, identified by the session id """ iter_ = self.model.get_iter_first() while iter_: if typ + sid == self.model[iter_][Column.SID]: return iter_ iter_ = self.model.iter_next(iter_) def __convert_date(self, epoch): # Converts date-time from seconds from epoch to iso 8601 dt = datetime.utcfromtimestamp(epoch) return dt.isoformat() + 'Z' def get_send_file_props(self, account, contact, file_path, file_name, file_desc=''): """ Create new file_props object and set initial file transfer properties in it """ if os.path.isfile(file_path): stat = os.stat(file_path) else: ErrorDialog(_('Invalid File'), _('File: ') + file_path) return None if stat[6] == 0: ErrorDialog(_('Invalid File'), _('It is not possible to send empty files')) return None file_props = FilesProp.getNewFileProp(account, sid=helpers.get_random_string_16()) mod_date = os.path.getmtime(file_path) file_props.file_name = file_path file_props.name = file_name file_props.date = self.__convert_date(mod_date) file_props.type_ = 's' file_props.desc = file_desc file_props.elapsed_time = 0 file_props.size = stat[6] file_props.sender = account file_props.receiver = contact file_props.tt_account = account return file_props def add_transfer(self, account, contact, file_props): """ Add new transfer to FT window and show the FT window """ if file_props is None: return file_props.elapsed_time = 0 iter_ = self.model.prepend() text_labels = '' + _('Name: ') + '\n' if file_props.type_ == 'r': text_labels += '' + _('Sender: ') + '' else: text_labels += '' + _('Recipient: ') + '' if file_props.type_ == 'r': file_name = os.path.split(file_props.file_name)[1] else: file_name = file_props.name text_props = GLib.markup_escape_text(file_name) + '\n' text_props += contact.get_shown_name() self.model.set(iter_, 1, text_labels, 2, text_props, Column.PULSE, -1, Column.SID, file_props.type_ + file_props.sid) self.set_progress(file_props.type_, file_props.sid, 0, iter_) if file_props.started is False: status = 'waiting' elif file_props.type_ == 'r': status = 'download' else: status = 'upload' file_props.tt_account = account self.set_status(file_props, status) self.set_cleanup_sensitivity() self.window.show_all() def on_transfers_list_row_activated(self, widget, path, col): # try to open the containing folder self.on_open_folder_menuitem_activate(widget) def set_cleanup_sensitivity(self): """ Check if there are transfer rows and set cleanup_button sensitive, or insensitive if model is empty """ if not self.model: self.cleanup_button.set_sensitive(False) else: self.cleanup_button.set_sensitive(True) def set_all_insensitive(self): """ Make all buttons/menuitems insensitive """ self.pause_button.set_sensitive(False) self.pause_menuitem.set_sensitive(False) self.continue_menuitem.set_sensitive(False) self.remove_menuitem.set_sensitive(False) self.cancel_button.set_sensitive(False) self.cancel_menuitem.set_sensitive(False) self.open_folder_menuitem.set_sensitive(False) self.set_cleanup_sensitivity() def set_buttons_sensitive(self, path, is_row_selected): """ Make buttons/menuitems sensitive as appropriate to the state of file transfer located at path 'path' """ if path is None: self.set_all_insensitive() return current_iter = self.model.get_iter(path) sid = self.model[current_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) self.remove_menuitem.set_sensitive(is_row_selected) self.open_folder_menuitem.set_sensitive(is_row_selected) is_stopped = False if is_transfer_stopped(file_props): is_stopped = True self.cancel_button.set_sensitive(not is_stopped) self.cancel_menuitem.set_sensitive(not is_stopped) if not is_row_selected: # no selection, disable the buttons self.set_all_insensitive() elif not is_stopped and file_props.continue_cb: if is_transfer_active(file_props): # file transfer is active self.toggle_pause_continue(True) self.pause_button.set_sensitive(True) elif is_transfer_paused(file_props): # file transfer is paused self.toggle_pause_continue(False) self.pause_button.set_sensitive(True) else: self.pause_button.set_sensitive(False) self.pause_menuitem.set_sensitive(False) self.continue_menuitem.set_sensitive(False) else: self.pause_button.set_sensitive(False) self.pause_menuitem.set_sensitive(False) self.continue_menuitem.set_sensitive(False) return True def selection_changed(self, args): """ Selection has changed - change the sensitivity of the buttons/menuitems """ selection = args selected = selection.get_selected_rows() if selected[1] != []: selected_path = selected[1][0] self.select_func(selected_path) else: self.set_all_insensitive() def select_func(self, path): is_selected = False selected = self.tree.get_selection().get_selected_rows() if selected[1] != []: selected_path = selected[1][0] if selected_path == path: is_selected = True self.set_buttons_sensitive(path, is_selected) self.set_cleanup_sensitivity() return True def on_cleanup_button_clicked(self, widget): i = len(self.model) - 1 while i >= 0: iter_ = self.model.get_iter((i)) sid = self.model[iter_][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) if is_transfer_stopped(file_props): self._remove_transfer(iter_, sid, file_props) i -= 1 self.tree.get_selection().unselect_all() self.set_all_insensitive() def toggle_pause_continue(self, status): if status: label = _('Pause') self.pause_button.set_label(label) self.pause_button.set_image(Gtk.Image.new_from_icon_name( "media-playback-pause", Gtk.IconSize.MENU)) self.pause_menuitem.set_sensitive(True) self.pause_menuitem.set_no_show_all(False) self.continue_menuitem.hide() self.continue_menuitem.set_no_show_all(True) else: label = _('_Continue') self.pause_button.set_label(label) self.pause_button.set_image(Gtk.Image.new_from_icon_name( "media-playback-start", Gtk.IconSize.MENU)) self.pause_menuitem.hide() self.pause_menuitem.set_no_show_all(True) self.continue_menuitem.set_sensitive(True) self.continue_menuitem.set_no_show_all(False) def on_pause_restore_button_clicked(self, widget): selected = self.tree.get_selection().get_selected() if selected is None or selected[1] is None: return s_iter = selected[1] sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) if is_transfer_paused(file_props): file_props.last_time = time.time() file_props.paused = False types = {'r' : 'download', 's' : 'upload'} self.set_status(file_props, types[sid[0]]) self.toggle_pause_continue(True) if file_props.continue_cb: file_props.continue_cb() elif is_transfer_active(file_props): file_props.paused = True self.set_status(file_props, 'pause') # reset that to compute speed only when we resume file_props.transfered_size = [] self.toggle_pause_continue(False) def on_cancel_button_clicked(self, widget): selected = self.tree.get_selection().get_selected() if selected is None or selected[1] is None: return s_iter = selected[1] sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) account = file_props.tt_account if account not in app.connections: return con = app.connections[account] # Check if we are in a IBB transfer if file_props.direction: con.CloseIBBStream(file_props) con.disconnect_transfer(file_props) self.set_status(file_props, 'stop') def on_notify_ft_complete_checkbox_toggled(self, widget): app.config.set('notify_on_file_complete', widget.get_active()) def on_file_transfers_dialog_delete_event(self, widget, event): self.window.hide() return True # do NOT destroy window def on_close_button_clicked(self, widget): self.window.hide() def show_context_menu(self, event, iter_): # change the sensitive property of the buttons and menuitems if iter_: path = self.model.get_path(iter_) self.set_buttons_sensitive(path, True) event_button = gtkgui_helpers.get_possible_button_event(event) self.file_transfers_menu.show_all() self.file_transfers_menu.popup(None, self.tree, None, None, event_button, event.time) def on_transfers_list_key_press_event(self, widget, event): """ When a key is pressed in the treeviews """ iter_ = None try: iter_ = self.tree.get_selection().get_selected()[1] except TypeError: self.tree.get_selection().unselect_all() if iter_ is not None: path = self.model.get_path(iter_) self.tree.get_selection().select_path(path) if event.keyval == Gdk.KEY_Menu: self.show_context_menu(event, iter_) return True def on_transfers_list_button_release_event(self, widget, event): # hide tooltip, no matter the button is pressed path = None try: path = self.tree.get_path_at_pos(int(event.x), int(event.y))[0] except TypeError: self.tree.get_selection().unselect_all() if path is None: self.set_all_insensitive() else: self.select_func(path) def on_transfers_list_button_press_event(self, widget, event): # hide tooltip, no matter the button is pressed path, iter_ = None, None try: path = self.tree.get_path_at_pos(int(event.x), int(event.y))[0] except TypeError: self.tree.get_selection().unselect_all() if event.button == 3: # Right click if path: self.tree.get_selection().select_path(path) iter_ = self.model.get_iter(path) self.show_context_menu(event, iter_) if path: return True def on_open_folder_menuitem_activate(self, widget): selected = self.tree.get_selection().get_selected() if not selected or not selected[1]: return s_iter = selected[1] sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) if not file_props.file_name: return path = os.path.split(file_props.file_name)[0] if os.path.exists(path) and os.path.isdir(path): helpers.launch_file_manager(path) def on_cancel_menuitem_activate(self, widget): self.on_cancel_button_clicked(widget) def on_continue_menuitem_activate(self, widget): self.on_pause_restore_button_clicked(widget) def on_pause_menuitem_activate(self, widget): self.on_pause_restore_button_clicked(widget) def on_remove_menuitem_activate(self, widget): selected = self.tree.get_selection().get_selected() if not selected or not selected[1]: return s_iter = selected[1] sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) self._remove_transfer(s_iter, sid, file_props) self.set_all_insensitive() def on_file_transfers_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: # ESCAPE self.window.hide() class SendFileDialog(Gtk.ApplicationWindow): def __init__(self, send_callback, transient_for): active_window = app.app.get_active_window() Gtk.ApplicationWindow.__init__(self) self.set_name('SendFileDialog') self.set_application(app.app) self.set_show_menubar(False) self.set_resizable(True) self.set_default_size(400, 250) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.set_transient_for(active_window) self.set_title(_('Choose a File to Send…')) self.set_destroy_with_parent(True) self._send_callback = send_callback xml = gtkgui_helpers.get_gtk_builder('send_file_dialog.ui') grid = xml.get_object('send_file_grid') self._filebox = xml.get_object('listbox') self._description = xml.get_object('description') self.add(grid) self.connect('key-press-event', self._key_press_event) xml.connect_signals(self) self.show_all() def _send(self, button): for file in self._filebox.get_children(): self._send_callback(str(file.path), self._get_description()) self.destroy() def _select_files(self, button): FileChooserDialog(self._set_files, select_multiple=True, transient_for=self, path=app.config.get('last_send_dir')) def _set_files(self, filenames): # Clear the ListBox self._filebox.foreach(self._remove_widget, None) for file in filenames: row = FileRow(file) if row.path.is_dir(): continue last_dir = row.path.parent self._filebox.add(row) self._filebox.show_all() app.config.set('last_send_dir', str(last_dir)) def _remove_widget(self, widget, data): self._filebox.remove(widget) def _get_description(self): buffer_ = self._description.get_buffer() start, end = buffer_.get_bounds() return buffer_.get_text(start, end, False) def _key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() class FileRow(Gtk.ListBoxRow): def __init__(self, path): Gtk.ListBoxRow.__init__(self) self.path = Path(path) label = Gtk.Label(label=self.path.name) label.set_ellipsize(Pango.EllipsizeMode.END) label.set_xalign(0) self.add(label) gajim-gajim-1.1.3/gajim/gajim.py000066400000000000000000000071111345766322700164370ustar00rootroot00000000000000# Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys import signal import platform from ctypes import CDLL, byref, create_string_buffer from ctypes.util import find_library from distutils.version import LooseVersion as V # Install _() in namespace from gajim.common import i18n _MIN_NBXMPP_VER = "0.6.10" _MIN_GTK_VER = "3.22.0" def _check_required_deps(): try: import nbxmpp except ImportError: print('Gajim needs python-nbxmpp to run. Quitting…') sys.exit(1) if V(nbxmpp.__version__) < V(_MIN_NBXMPP_VER): print('Gajim needs python-nbxmpp >= %s to run. ' 'Quitting...' % _MIN_NBXMPP_VER) sys.exit(1) def _init_gui(gui): if gui == 'GTK': _init_gtk() def _init_gtk(): import gi gi.require_version('GLib', '2.0') gi.require_version('Gio', '2.0') gi.require_version('Gtk', '3.0') gi.require_version('Gdk', '3.0') gi.require_version('GObject', '2.0') gi.require_version('Pango', '1.0') from gi.repository import Gtk gtk_ver = '%s.%s.%s' % (Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) if V(gtk_ver) < V(_MIN_GTK_VER): print('Gajim needs GTK+ >= %s to run. ' 'Quitting...' % _MIN_GTK_VER) sys.exit(1) from gajim import gtkexcepthook gtkexcepthook.init() i18n.initialize_direction_mark() from gajim.application import GajimApplication # Fix bug in 3.24.1 with flickering tooltips if sys.platform in ('darwin', 'win32'): settings = Gtk.Settings.get_default() settings.set_property('gtk-cursor-theme-size', 16) application = GajimApplication() _install_sginal_handlers(application) application.run(sys.argv) def _set_proc_title(): sysname = platform.system() if sysname in ('Linux', 'FreeBSD', 'OpenBSD', 'NetBSD'): libc = CDLL(find_library('c')) # The constant defined in which is used to set the name # of the process. PR_SET_NAME = 15 if sysname == 'Linux': proc_name = b'gajim' buff = create_string_buffer(len(proc_name)+1) buff.value = proc_name libc.prctl(PR_SET_NAME, byref(buff), 0, 0, 0) elif sysname in ('FreeBSD', 'OpenBSD', 'NetBSD'): libc.setproctitle('gajim') def _install_sginal_handlers(application): def sigint_cb(num, stack): print('SIGINT/SIGTERM received') application.quit() # ^C exits the application normally signal.signal(signal.SIGINT, sigint_cb) signal.signal(signal.SIGTERM, sigint_cb) if os.name != 'nt': signal.signal(signal.SIGPIPE, signal.SIG_DFL) def main(): if sys.platform != 'win32': if os.geteuid() == 0: sys.exit("You must not launch gajim as root, it is insecure.") _check_required_deps() _set_proc_title() _init_gui('GTK') gajim-gajim-1.1.3/gajim/gajim_remote.py000066400000000000000000000512041345766322700200140ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (C) 2005-2006 Dimitur Kirov # Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2006 Junglecow # Travis Shirk # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Julien Pivotto # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # gajim-remote help will show you the D-BUS API of Gajim import os import sys import locale import signal from gajim.common import exceptions from gajim.common.i18n import _ from gajim.common.i18n import Q_ signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application try: PREFERRED_ENCODING = locale.getpreferredencoding() except Exception: PREFERRED_ENCODING = 'UTF-8' def send_error(error_message): '''Writes error message to stderr and exits''' print(error_message, file=sys.stderr) sys.exit(1) try: import dbus import dbus.service # import dbus.glib # test if dbus-x11 is installed bus = dbus.SessionBus() except Exception: print(_('D-Bus is not present on this machine or python module is missing')) sys.exit(1) OBJ_PATH = '/org/gajim/dbus/RemoteObject' INTERFACE = 'org.gajim.dbus.RemoteInterface' SERVICE = 'org.gajim.Gajim' BASENAME = 'gajim-remote' class GajimRemote: def __init__(self): self.argv_len = len(sys.argv) # define commands dict. Prototype : # { # 'command': [comment, [list of arguments] ] # } # # each argument is defined as a tuple: # (argument name, help on argument, is mandatory) # self.commands = { 'help': [ _('Shows a help on specific command'), [ #User gets help for the command, specified by this parameter (_('command'), _('show help on command'), False) ] ], 'list_contacts': [ _('Lists all contacts in roster, one for each line'), [ (Q_('?CLI:account'), _('show only contacts of the given account'), False) ] ], 'list_accounts': [ _('Prints a list of registered accounts'), [] ], 'change_status': [ _('Changes the status of account(s)'), [ #offline, online, chat, away, xa, dnd, invisible should not be translated (Q_('?CLI:status'), _('one of: offline, online, chat, away, xa, dnd, invisible. If not set, use account\'s previous status'), False), (Q_('?CLI:message'), _('status message'), False), (Q_('?CLI:account'), _('change status of account "account". ' 'If not specified, try to change status of all accounts that have ' '"sync with global status" option set'), False) ] ], 'set_priority': [ _('Changes the priority of account(s)'), [ (Q_('?CLI:priority'), _('priority you want to give to the account'), True), (Q_('?CLI:account'), _('change the priority of the given account. ' 'If not specified, change status of all accounts that have' ' "sync with global status" option set'), False) ] ], 'send_chat_message': [ _('Sends new chat message to a contact in the roster. Both OpenPGP key ' 'and account are optional. If you want to set only \'account\', ' 'without \'OpenPGP key\', just set \'OpenPGP key\' to \'\'.'), [ ('jid', _('JID of the contact that will receive the message'), True), (Q_('?CLI:message'), _('message contents'), True), (_('PGP key'), _('if specified, the message will be encrypted ' 'using this public key'), False), (Q_('?CLI:account'), _('if specified, the message will be sent ' 'using this account'), False), ] ], 'send_single_message': [ _('Sends a chat message to someone on your roster. ' 'Optionally with OpenPGP key and account. If you want ' 'to only set the latter, set OpenPGP key to "".'), [ ('jid', _('JID of the contact that will receive the message'), True), (_('subject'), _('message subject'), True), (Q_('?CLI:message'), _('message contents'), True), (_('PGP key'), _('if specified, the message will be encrypted ' 'using this public key'), False), (Q_('?CLI:account'), _('if specified, the message will be sent ' 'using this account'), False), ] ], 'send_groupchat_message': [ _('Sends new message to a groupchat you\'ve joined.'), [ ('room_jid', _('JID of the room that will receive the message'), True), (Q_('?CLI:message'), _('message contents'), True), (Q_('?CLI:account'), _('if specified, the message will be sent ' 'using this account'), False), ] ], 'contact_info': [ _('Gets detailed info on a contact'), [ ('jid', _('JID of the contact'), True) ] ], 'account_info': [ _('Gets detailed info on a account'), [ ('account', _('Name of the account'), True) ] ], 'send_file': [ _('Sends file to a contact'), [ (_('file'), _('File path'), True), ('jid', _('JID of the contact'), True), (Q_('?CLI:account'), _('if specified, file will be sent using this ' 'account'), False) ] ], 'prefs_list': [ _('Lists all preferences and their values'), [] ], 'prefs_put': [ _('Sets value of \'key\' to \'value\'.'), [ (_('key=value'), _('\'key\' is the name of the preference, ' '\'value\' is what to set it to'), True) ] ], 'prefs_del': [ _('Deletes a preference item'), [ (_('key'), _('name of the preference to be deleted'), True) ] ], 'prefs_store': [ _('Writes the current state of Gajim preferences to the .config ' 'file'), [] ], 'remove_contact': [ _('Removes contact from roster'), [ ('jid', _('JID of the contact'), True), (Q_('?CLI:account'), _('if specified, contact is taken from the ' 'contact list of this account'), False) ] ], 'get_status': [ _('Returns current status (the global one unless account is specified)'), [ (Q_('?CLI:account'), '', False) ] ], 'get_status_message': [ _('Returns current status message (the global one unless account is specified)'), [ (Q_('?CLI:account'), '', False) ] ], 'get_unread_msgs_number': [ _('Returns number of unread messages'), [] ], 'send_xml': [ _('Sends custom XML'), [ ('xml', _('XML to send'), True), ('account', _('Account to which the XML will be sent; ' 'if not specified, XML will be sent to all accounts'), False) ] ], 'change_avatar': [ _('Change the avatar'), [ ('picture', _('Picture to use'), True), ('account', _('Account in which the avatar will be set; ' 'if not specified, the avatar will be set for all accounts'), False) ] ], 'check_gajim_running': [ _('Check if Gajim is running'), [] ], } self.sbus = None if self.argv_len < 2 or sys.argv[1] not in self.commands.keys(): # no args or bad args send_error(self.compose_help()) self.command = sys.argv[1] if self.command == 'help': if self.argv_len == 3: print(self.help_on_command(sys.argv[2]).encode( PREFERRED_ENCODING)) else: print(self.compose_help().encode(PREFERRED_ENCODING)) sys.exit(0) if self.command == 'check_gajim_running': print(self.check_gajim_running()) sys.exit(0) self.init_connection() self.check_arguments() if self.command == 'contact_info': if self.argv_len < 3: send_error(_('Missing argument "contact_jid"')) try: res = self.call_remote_method() except exceptions.ServiceNotAvailable: # At this point an error message has already been displayed sys.exit(1) else: self.print_result(res) def print_result(self, res): """ Print retrieved result to the output """ if res is not None: if self.command in ('send_chat_message', 'send_single_message'): self.argv_len -= 2 if res is False: if self.argv_len < 4: send_error(_('\'%s\' is not in your roster.\n' 'Please specify account for sending the message.') % sys.argv[2]) else: send_error(_('You have no active account')) elif self.command == 'list_accounts': if isinstance(res, list): for account in res: print(account) elif self.command == 'account_info': if res: print(self.print_info(0, res, True)) elif self.command == 'list_contacts': for account_dict in res: print(self.print_info(0, account_dict, True)) elif self.command == 'prefs_list': pref_keys = sorted(res.keys()) for pref_key in pref_keys: result = '%s = %s' % (pref_key, res[pref_key]) print(result) elif self.command == 'contact_info': print(self.print_info(0, res, True)) elif res: print(res) def check_gajim_running(self): if not self.sbus: try: self.sbus = dbus.SessionBus() except Exception: raise exceptions.SessionBusNotPresent test = False if hasattr(self.sbus, 'name_has_owner'): if self.sbus.name_has_owner(SERVICE): test = True elif dbus.dbus_bindings.bus_name_has_owner(self.sbus.get_connection(), SERVICE): test = True return test def init_connection(self): """ Create the connection to the session dbus, or exit if it is not possible """ try: self.sbus = dbus.SessionBus() except Exception: raise exceptions.SessionBusNotPresent if not self.check_gajim_running(): #Do not translate "gajim-remote" send_error(_('It seems Gajim is not running. So you can\'t use gajim-remote.')) obj = self.sbus.get_object(SERVICE, OBJ_PATH) interface = dbus.Interface(obj, INTERFACE) # get the function asked self.method = interface.__getattr__(self.command) def make_arguments_row(self, args): """ Return arguments list. Mandatory arguments are enclosed with: '<', '>', optional arguments - with '[', ']' """ s = '' for arg in args: if arg[2]: s += ' <' + arg[0] + '>' else: s += ' [' + arg[0] + ']' return s def help_on_command(self, command): """ Return help message for a given command """ if command in self.commands: command_props = self.commands[command] arguments_str = self.make_arguments_row(command_props[1]) str_ = _('Usage: %(basename)s %(command)s %(arguments)s \n\t %(help)s')\ % {'basename': BASENAME, 'command': command, 'arguments': arguments_str, 'help': command_props[0]} if command_props[1]: str_ += '\n\n' + _('Arguments:') + '\n' for argument in command_props[1]: str_ += ' ' + argument[0] + ' - ' + argument[1] + '\n' return str_ send_error(_('%s not found') % command) def compose_help(self): """ Print usage, and list available commands """ s = _('Usage:\n %s command [arguments]\n\nCommand is one of:\n') % ( BASENAME) for command in sorted(self.commands): s += ' ' + command for arg in self.commands[command][1]: if arg[2]: s += ' <' + arg[0] + '>' else: s += ' [' + arg[0] + ']' s += '\n' return s def print_info(self, level, prop_dict, encode_return=False): """ Return formatted string from data structure """ if prop_dict is None or not isinstance(prop_dict, (dict, list, tuple)): return '' ret_str = '' if isinstance(prop_dict, (list, tuple)): ret_str = '' spacing = ' ' * level * 4 for val in prop_dict: if val is None: ret_str += '\t' elif isinstance(val, int): ret_str += '\t' + str(val) elif isinstance(val, str): ret_str += '\t' + val elif isinstance(val, (list, tuple)): res = '' for items in val: res += self.print_info(level+1, items) if res != '': ret_str += '\t' + res elif isinstance(val, dict): ret_str += self.print_info(level+1, val) ret_str = '%s(%s)\n' % (spacing, ret_str[1:]) elif isinstance(prop_dict, dict): for key in prop_dict.keys(): val = prop_dict[key] spacing = ' ' * level * 4 if isinstance(val, (int, str)): if val is not None: val = val.strip() ret_str += '%s%-10s: %s\n' % (spacing, key, val) elif isinstance(val, (list, tuple)): res = '' for items in val: res += self.print_info(level+1, items) if res != '': ret_str += '%s%s: \n%s' % (spacing, key, res) elif isinstance(val, dict): res = self.print_info(level+1, val) if res != '': ret_str += '%s%s: \n%s' % (spacing, key, res) if encode_return: try: ret_str = ret_str.encode(PREFERRED_ENCODING) except Exception: pass return ret_str def check_arguments(self): """ Make check if all necessary arguments are given """ argv_len = self.argv_len - 2 args = self.commands[self.command][1] if len(args) < argv_len: send_error(_('Too many arguments. \n' 'Type "%(basename)s help %(command)s" for more info') % { 'basename': BASENAME, 'command': self.command}) if len(args) > argv_len: if args[argv_len][2]: send_error(_('Argument "%(arg)s" is not specified. \n' 'Type "%(basename)s help %(command)s" for more info') % {'arg': args[argv_len][0], 'basename': BASENAME, 'command': self.command}) self.arguments = [] i = 0 for arg in sys.argv[2:]: i += 1 if i < len(args): self.arguments.append(arg) else: # it's latest argument with spaces self.arguments.append(' '.join(sys.argv[i+1:])) break # add empty string for missing args self.arguments += ['']*(len(args)-i) def call_remote_method(self): """ Calls self.method with arguments from sys.argv[2:] """ args = [dbus.String(i) for i in self.arguments] try: res = self.method(*args) return res except Exception: raise exceptions.ServiceNotAvailable return None def main(): if os.geteuid() == 0: sys.exit("You must not launch gajim as root, it is insecure.") GajimRemote() if __name__ == '__main__': main() gajim-gajim-1.1.3/gajim/groupchat_control.py000066400000000000000000003652631345766322700211230ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2006 Dimitur Kirov # Alex Mauer # Copyright (C) 2006-2008 Jean-Marie Traissard # Travis Shirk # Copyright (C) 2007-2008 Julien Pivotto # Stephan Erb # Copyright (C) 2008 Brendan Taylor # Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Optional import time import locale import base64 import logging from enum import IntEnum, unique import nbxmpp from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import Pango from gi.repository import GLib from gi.repository import Gio from gajim import gtkgui_helpers from gajim import gui_menu_builder from gajim import message_control from gajim import tooltips from gajim import config from gajim import vcard from gajim import dataforms_widget from gajim import adhoc_commands from gajim.common.const import AvatarSize from gajim.common.caps_cache import muc_caps_cache from gajim.common import events from gajim.common import app from gajim.common import helpers from gajim.common.helpers import launch_browser_mailer from gajim.common.helpers import AdditionalDataDict from gajim.common.modules import dataforms from gajim.common import ged from gajim.common import i18n from gajim.common.i18n import _ from gajim.common import contacts from gajim.common.const import StyleAttr from gajim.common.const import Chatstate from gajim.chat_control import ChatControl from gajim.chat_control_base import ChatControlBase from gajim.command_system.implementation.hosts import PrivateChatCommands from gajim.command_system.implementation.hosts import GroupChatCommands from gajim.common.connection_handlers_events import GcMessageOutgoingEvent from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import InputTextDialog from gajim.gtk.dialogs import ConfirmationDialogCheck from gajim.gtk.dialogs import DoubleInputDialog from gajim.gtk.dialogs import InputDialog from gajim.gtk.dialogs import ChangeNickDialog from gajim.gtk.filechoosers import AvatarChooserDialog from gajim.gtk.add_contact import AddNewContactWindow log = logging.getLogger('gajim.groupchat_control') @unique class Column(IntEnum): IMG = 0 # image to show state (online, new message etc) NICK = 1 # contact nickname or ROLE name TYPE = 2 # type of the row ('contact' or 'role') TEXT = 3 # text shown in the cellrenderer AVATAR_IMG = 4 # avatar of the contact empty_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 1, 1) empty_pixbuf.fill(0xffffff00) def cell_data_func(column, renderer, model, iter_, user_data): # Background color has to be rendered for all cells theme = app.config.get('roster_theme') has_parent = bool(model.iter_parent(iter_)) if has_parent: bgcolor = app.css_config.get_value('.gajim-contact-row', StyleAttr.BACKGROUND) renderer.set_property('cell-background', bgcolor) else: bgcolor = app.css_config.get_value('.gajim-group-row', StyleAttr.BACKGROUND) renderer.set_property('cell-background', bgcolor) if user_data == 'status': status_cell_data_func(column, renderer, model, iter_, has_parent) elif user_data == 'name': text_cell_data_func(column, renderer, model, iter_, has_parent, theme) elif user_data == 'avatar': avatar_cell_data_func(column, renderer, model, iter_, has_parent) def status_cell_data_func(column, renderer, model, iter_, has_parent): renderer.set_property('width', 26) image = model[iter_][Column.IMG] surface = image.get_property('surface') renderer.set_property('surface', surface) def avatar_cell_data_func(column, renderer, model, iter_, has_parent): image = model[iter_][Column.AVATAR_IMG] if image is None: renderer.set_property('surface', None) else: surface = image.get_property('surface') renderer.set_property('surface', surface) renderer.set_property('xalign', 0.5) if has_parent: renderer.set_property('visible', True) renderer.set_property('width', AvatarSize.ROSTER) else: renderer.set_property('visible', False) def text_cell_data_func(column, renderer, model, iter_, has_parent, theme): # cell data func is global, because we don't want it to keep # reference to GroupchatControl instance (self) if has_parent: color = app.css_config.get_value('.gajim-contact-row', StyleAttr.COLOR) renderer.set_property('foreground', color) desc = app.css_config.get_font('.gajim-contact-row') renderer.set_property('font-desc', desc) else: color = app.css_config.get_value('.gajim-group-row', StyleAttr.COLOR) renderer.set_property('foreground', color) desc = app.css_config.get_font('.gajim-group-row') renderer.set_property('font-desc', desc) class PrivateChatControl(ChatControl): TYPE_ID = message_control.TYPE_PM # Set a command host to bound to. Every command given through a private chat # will be processed with this command host. COMMAND_HOST = PrivateChatCommands def __init__(self, parent_win, gc_contact, contact, account, session): room_jid = gc_contact.room_jid self.room_ctrl = app.interface.msg_win_mgr.get_gc_control(room_jid, account) if room_jid in app.interface.minimized_controls[account]: self.room_ctrl = app.interface.minimized_controls[account][room_jid] if self.room_ctrl: self.room_name = self.room_ctrl.name else: self.room_name = room_jid self.gc_contact = gc_contact ChatControl.__init__(self, parent_win, contact, account, session) self.TYPE_ID = 'pm' app.ged.register_event_handler('update-gc-avatar', ged.GUI1, self._nec_update_avatar) app.ged.register_event_handler('caps-update', ged.GUI1, self._nec_caps_received_pm) app.ged.register_event_handler('gc-presence-received', ged.GUI1, self._nec_gc_presence_received) def get_our_nick(self): return self.room_ctrl.nick def shutdown(self): super(PrivateChatControl, self).shutdown() app.ged.remove_event_handler('update-gc-avatar', ged.GUI1, self._nec_update_avatar) app.ged.remove_event_handler('caps-update', ged.GUI1, self._nec_caps_received_pm) app.ged.remove_event_handler('gc-presence-received', ged.GUI1, self._nec_gc_presence_received) def _nec_caps_received_pm(self, obj): if obj.conn.name != self.account or \ obj.fjid != self.gc_contact.get_full_jid(): return self.update_contact() def _nec_gc_presence_received(self, obj): if obj.conn.name != self.account: return if obj.fjid != self.full_jid: return if '303' in obj.status_code: self.print_conversation(_('%(nick)s is now known as ' '%(new_nick)s') % {'nick': obj.nick, 'new_nick': obj.new_nick}, 'status') gc_c = app.contacts.get_gc_contact(obj.conn.name, obj.room_jid, obj.new_nick) c = gc_c.as_contact() self.gc_contact = gc_c self.contact = c self.draw_banner() old_jid = obj.room_jid + '/' + obj.nick new_jid = obj.room_jid + '/' + obj.new_nick app.interface.msg_win_mgr.change_key(old_jid, new_jid, obj.conn.name) else: self.contact.show = obj.show self.contact.status = obj.status self.gc_contact.show = obj.show self.gc_contact.status = obj.status uf_show = helpers.get_uf_show(obj.show) self.print_conversation(_('%(nick)s is now %(status)s') % { 'nick': obj.nick, 'status': uf_show}, 'status') if obj.status: self.print_conversation(' (', 'status', simple=True) self.print_conversation('%s' % (obj.status), 'status', simple=True) self.print_conversation(')', 'status', simple=True) self.parent_win.redraw_tab(self) self.update_ui() def send_message(self, message, xhtml=None, process_commands=True, attention=False): """ Call this method to send the message """ message = helpers.remove_invalid_xml_chars(message) if not message: return # We need to make sure that we can still send through the room and that # the recipient did not go away contact = app.contacts.get_first_contact_from_jid(self.account, self.contact.jid) if not contact: # contact was from pm in MUC room, nick = app.get_room_and_nick_from_fjid(self.contact.jid) gc_contact = app.contacts.get_gc_contact(self.account, room, nick) if not gc_contact: ErrorDialog( _('Sending private message failed'), #in second %s code replaces with nickname _('You are no longer in group chat "%(room)s" or ' '"%(nick)s" has left.') % {'room': '\u200E' + room, 'nick': nick}, transient_for=self.parent_win.window) return ChatControl.send_message(self, message, xhtml=xhtml, process_commands=process_commands, attention=attention) def update_ui(self): if self.contact.show == 'offline': self.got_disconnected() else: self.got_connected() ChatControl.update_ui(self) def _nec_update_avatar(self, obj): if obj.contact != self.gc_contact: return self.show_avatar() def show_avatar(self): if not app.config.get('show_avatar_in_chat'): return scale = self.parent_win.window.get_scale_factor() surface = app.interface.get_avatar( self.gc_contact.avatar_sha, AvatarSize.CHAT, scale) image = self.xml.get_object('avatar_image') image.set_from_surface(surface) def update_contact(self): self.contact = self.gc_contact.as_contact() def got_disconnected(self): ChatControl.got_disconnected(self) class GroupchatControl(ChatControlBase): TYPE_ID = message_control.TYPE_GC # Set a command host to bound to. Every command given through a group chat # will be processed with this command host. COMMAND_HOST = GroupChatCommands def __init__(self, parent_win, contact, nick, acct, is_continued=False): ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'groupchat_control', contact, acct) self.force_non_minimizable = False self.is_continued = is_continued self.is_anonymous = True self.join_time = 0 # Controls the state of autorejoin. # None - autorejoin is neutral. # False - autorejoin is to be prevented (gets reset to initial state in # got_connected()). # int - autorejoin is being active and working (gets reset to initial # state in got_connected()). self.autorejoin = None # Keep error dialog instance to be sure to have only once at a time self.error_dialog = None # Source id for saving the handle position self._handle_timeout_id = None self.emoticons_button = self.xml.get_object('emoticons_button') self.toggle_emoticons() formattings_button = self.xml.get_object('formattings_button') formattings_button.set_sensitive(False) self._state_change_handler_id = None if parent_win is not None: # On AutoJoin with minimize Groupchats are created without parent # Tooltip Window and Actions have to be created with parent self.set_tooltip() self.add_actions() GLib.idle_add(self.update_actions) self.scale_factor = parent_win.window.get_scale_factor() self._connect_window_state_change(parent_win) else: self.scale_factor = app.interface.roster.scale_factor widget = self.xml.get_object('list_treeview') id_ = widget.connect('row_expanded', self.on_list_treeview_row_expanded) self.handlers[id_] = widget id_ = widget.connect('row_collapsed', self.on_list_treeview_row_collapsed) self.handlers[id_] = widget id_ = widget.connect('row_activated', self.on_list_treeview_row_activated) self.handlers[id_] = widget id_ = widget.connect('button_press_event', self.on_list_treeview_button_press_event) self.handlers[id_] = widget id_ = widget.connect('key_press_event', self.on_list_treeview_key_press_event) self.handlers[id_] = widget self.room_jid = self.contact.jid self.nick = nick self.new_nick = '' bm_module = app.connections[self.account].get_module('Bookmarks') self.name = bm_module.get_name_from_bookmark(self.room_jid) self.contact.name = self.name self.widget_set_visible(self.xml.get_object('banner_eventbox'), app.config.get('hide_groupchat_banner')) # muc attention flag (when we are mentioned in a muc) # if True, the room has mentioned us self.attention_flag = False # sorted list of nicks who mentioned us (last at the end) self.attention_list = [] self.nick_hits = [] self.last_key_tabs = False self.subject = '' # nickname coloring self.gc_count_nicknames_colors = -1 self.gc_custom_colors = {} self.number_of_colors = len(app.config.get('gc_nicknames_colors').\ split(':')) self.name_label = self.xml.get_object('banner_name_label') self.event_box = self.xml.get_object('banner_eventbox') self.list_treeview = self.xml.get_object('list_treeview') id_ = self.list_treeview.connect('style-set', self.on_list_treeview_style_set) self.handlers[id_] = self.list_treeview # flag that stops hpaned position event # when the handle gets resized in another control self._resize_from_another_muc = False self.hpaned = self.xml.get_object('hpaned') # set the position of the current hpaned hpaned_position = app.config.get('gc-hpaned-position') self.hpaned.set_position(hpaned_position) # Holds the Gtk.TreeRowReference for each contact self._contact_refs = {} # Holds the Gtk.TreeRowReference for each role self._role_refs = {} #status_image, shown_nick, type, nickname, avatar self.columns = [Gtk.Image, str, str, str, Gtk.Image] self.model = Gtk.TreeStore(*self.columns) self.model.set_sort_func(Column.NICK, self.tree_compare_iters) # columns column = Gtk.TreeViewColumn() # list of renderers with attributes / properties in the form: # (name, renderer_object, expand?, attribute_name, attribute_value, # cell_data_func, func_arg) self.renderers_list = [] # Number of renderers plugins added self.nb_ext_renderers = 0 self.renderers_propertys = {} renderer_text = Gtk.CellRendererText() self.renderers_propertys[renderer_text] = ('ellipsize', Pango.EllipsizeMode.END) self.renderers_list += ( # status img ('icon', Gtk.CellRendererPixbuf(), False, None, Column.IMG, cell_data_func, 'status'), # contact name ('name', renderer_text, True, 'markup', Column.TEXT, cell_data_func, 'name')) # avatar img avatar_renderer = ('avatar', Gtk.CellRendererPixbuf(), False, None, Column.AVATAR_IMG, cell_data_func, 'avatar') if app.config.get('avatar_position_in_roster') == 'right': self.renderers_list.append(avatar_renderer) else: self.renderers_list.insert(0, avatar_renderer) self.fill_column(column) self.list_treeview.append_column(column) # workaround to avoid gtk arrows to be shown column = Gtk.TreeViewColumn() # 2nd COLUMN renderer = Gtk.CellRendererPixbuf() column.pack_start(renderer, False) self.list_treeview.append_column(column) column.set_visible(False) self.list_treeview.set_expander_column(column) self.setup_seclabel() self.form_widget = None # Send file self.sendfile_button = self.xml.get_object('sendfile_button') self.sendfile_button.set_action_name('win.send-file-' + \ self.control_id) # Encryption self.lock_image = self.xml.get_object('lock_image') self.authentication_button = self.xml.get_object( 'authentication_button') id_ = self.authentication_button.connect('clicked', self._on_authentication_button_clicked) self.handlers[id_] = self.authentication_button self.set_lock_image() self.encryption_menu = self.xml.get_object('encryption_menu') self.encryption_menu.set_menu_model( gui_menu_builder.get_encryption_menu(self.control_id, self.type_id)) self.set_encryption_menu_icon() # Banner self.banner_actionbar = self.xml.get_object('banner_actionbar') self.hide_roster_button = Gtk.Button.new_from_icon_name( 'go-next-symbolic', Gtk.IconSize.MENU) self.hide_roster_button.connect('clicked', lambda *args: self.show_roster()) self.subject_button = Gtk.MenuButton() self.subject_button.set_image(Gtk.Image.new_from_icon_name( 'go-down-symbolic', Gtk.IconSize.MENU)) self.subject_button.set_popover(SubjectPopover()) self.subject_button.set_no_show_all(True) self.banner_actionbar.pack_end(self.hide_roster_button) self.banner_actionbar.pack_start(self.subject_button) # GC Roster tooltip self.gc_tooltip = tooltips.GCTooltip() self.control_menu = gui_menu_builder.get_groupchat_menu(self.control_id) settings_menu = self.xml.get_object('settings_menu') settings_menu.set_menu_model(self.control_menu) app.ged.register_event_handler('gc-presence-received', ged.GUI1, self._nec_gc_presence_received) app.ged.register_event_handler('gc-message-received', ged.GUI1, self._nec_gc_message_received) app.ged.register_event_handler('mam-decrypted-message-received', ged.GUI1, self._nec_mam_decrypted_message_received) app.ged.register_event_handler('vcard-published', ged.GUI1, self._nec_vcard_published) app.ged.register_event_handler('update-gc-avatar', ged.GUI1, self._nec_update_avatar) app.ged.register_event_handler('update-room-avatar', ged.GUI1, self._nec_update_room_avatar) app.ged.register_event_handler('gc-subject-received', ged.GUI1, self._nec_gc_subject_received) app.ged.register_event_handler('gc-config-changed-received', ged.GUI1, self._nec_gc_config_changed_received) app.ged.register_event_handler('signed-in', ged.GUI1, self._nec_signed_in) app.ged.register_event_handler('decrypted-message-received', ged.GUI2, self._nec_decrypted_message_received) app.ged.register_event_handler('gc-stanza-message-outgoing', ged.OUT_POSTCORE, self._message_sent) self.is_connected = False # disable win, we are not connected yet ChatControlBase.got_disconnected(self) self.update_ui() self.widget.show_all() if app.config.get('hide_groupchat_occupants_list'): # Roster is shown by default, so toggle the roster button to hide it self.show_roster() # PluginSystem: adding GUI extension point for this GroupchatControl # instance object app.plugin_manager.gui_extension_point('groupchat_control', self) def add_actions(self): super().add_actions() actions = [ ('change-subject-', self._on_change_subject), ('change-nick-', self._on_change_nick), ('disconnect-', self._on_disconnect), ('destroy-', self._on_destroy_room), ('configure-', self._on_configure_room), ('bookmark-', self._on_bookmark_room), ('request-voice-', self._on_request_voice), ('execute-command-', self._on_execute_command), ('upload-avatar-', self._on_upload_avatar), ] for action in actions: action_name, func = action act = Gio.SimpleAction.new(action_name + self.control_id, None) act.connect("activate", func) self.parent_win.window.add_action(act) non_minimized_gc = app.config.get_per( 'accounts', self.account, 'non_minimized_gc').split() value = self.contact.jid not in non_minimized_gc act = Gio.SimpleAction.new_stateful( 'minimize-' + self.control_id, None, GLib.Variant.new_boolean(value)) act.connect('change-state', self._on_minimize) self.parent_win.window.add_action(act) value = app.config.get_per( 'rooms', self.contact.jid, 'notify_on_all_messages') act = Gio.SimpleAction.new_stateful( 'notify-on-message-' + self.control_id, None, GLib.Variant.new_boolean(value)) act.connect('change-state', self._on_notify_on_all_messages) self.parent_win.window.add_action(act) archive_info = app.logger.get_archive_infos(self.contact.jid) threshold = helpers.get_sync_threshold(self.contact.jid, archive_info) inital = GLib.Variant.new_string(str(threshold)) act = Gio.SimpleAction.new_stateful( 'choose-sync-' + self.control_id, inital.get_type(), inital) act.connect('change-state', self._on_sync_threshold) self.parent_win.window.add_action(act) def update_actions(self): if self.parent_win is None: return win = self.parent_win.window contact = app.contacts.get_gc_contact( self.account, self.room_jid, self.nick) con = app.connections[self.account] # Destroy Room win.lookup_action('destroy-' + self.control_id).set_enabled( self.is_connected and contact.affiliation == 'owner') # Configure Room win.lookup_action('configure-' + self.control_id).set_enabled( self.is_connected and contact.affiliation in ('admin', 'owner')) # Bookmarks con = app.connections[self.account] bookmark_support = con.get_module('Bookmarks').available bookmarked = self.room_jid in con.get_module('Bookmarks').bookmarks win.lookup_action('bookmark-' + self.control_id).set_enabled( self.is_connected and bookmark_support and not bookmarked) # Request Voice role = self.get_role(self.nick) win.lookup_action('request-voice-' + self.control_id).set_enabled( self.is_connected and role == 'visitor') # Change Subject subject = False if contact is not None: subject = muc_caps_cache.is_subject_change_allowed( self.room_jid, contact.affiliation) win.lookup_action('change-subject-' + self.control_id).set_enabled( self.is_connected and subject) # Change Nick win.lookup_action('change-nick-' + self.control_id).set_enabled( self.is_connected) # Execute command win.lookup_action('execute-command-' + self.control_id).set_enabled( self.is_connected) # Send file (HTTP File Upload) httpupload = win.lookup_action( 'send-file-httpupload-' + self.control_id) httpupload.set_enabled( self.is_connected and con.get_module('HTTPUpload').available) win.lookup_action('send-file-' + self.control_id).set_enabled( httpupload.get_enabled()) if self.is_connected and httpupload.get_enabled(): tooltip_text = _('Send File…') else: tooltip_text = _('No File Transfer available') self.sendfile_button.set_tooltip_text(tooltip_text) # Upload Avatar vcard_support = muc_caps_cache.supports(self.room_jid, nbxmpp.NS_VCARD) win.lookup_action('upload-avatar-' + self.control_id).set_enabled( self.is_connected and vcard_support and contact.affiliation == 'owner') # Sync Threshold has_mam = muc_caps_cache.has_mam(self.room_jid) win.lookup_action('choose-sync-' + self.control_id).set_enabled(has_mam) def _on_room_created(self): if self.parent_win is None: return win = self.parent_win.window self.update_actions() # After the room has been created, reevaluate threshold if muc_caps_cache.has_mam(self.contact.jid): archive_info = app.logger.get_archive_infos(self.contact.jid) threshold = helpers.get_sync_threshold(self.contact.jid, archive_info) win.change_action_state('choose-sync-%s' % self.control_id, GLib.Variant('s', str(threshold))) def _connect_window_state_change(self, parent_win): if self._state_change_handler_id is None: id_ = parent_win.window.connect('notify::is-maximized', self._on_window_state_change) self._state_change_handler_id = id_ # Actions def _on_change_subject(self, action, param): def on_ok(subject): # Note, we don't update self.subject since we don't know whether it # will work yet con = app.connections[self.account] con.get_module('MUC').set_subject(self.room_jid, subject) InputTextDialog(_('Changing Subject'), _('Please specify the new subject:'), input_str=self.subject, ok_handler=on_ok, transient_for=self.parent_win.window) def _on_change_nick(self, action, param): if 'change_nick_dialog' in app.interface.instances: app.interface.instances['change_nick_dialog'].dialog.present() else: title = _('Changing Nickname') prompt = _('Please specify the new nickname you want to use:') app.interface.instances['change_nick_dialog'] = \ ChangeNickDialog(self.account, self.room_jid, title, prompt, change_nick=True, transient_for=self.parent_win.window) def _on_disconnect(self, action, param): self.force_non_minimizable = True self.parent_win.remove_tab(self, self.parent_win.CLOSE_COMMAND) self.force_non_minimizable = False def _on_destroy_room(self, action, param): def on_ok(reason, jid): if jid: # Test jid try: jid = helpers.parse_jid(jid) except Exception: ErrorDialog( _('Invalid group chat JID'), _('The group chat JID has not allowed characters.')) return con = app.connections[self.account] con.get_module('MUC').destroy(self.room_jid, reason, jid) con.get_module('Bookmarks').bookmarks.pop(self.room_jid, None) con.get_module('Bookmarks').store_bookmarks() gui_menu_builder.build_bookmark_menu(self.account) self.force_non_minimizable = True self.parent_win.remove_tab(self, self.parent_win.CLOSE_COMMAND) self.force_non_minimizable = False # Ask for a reason DoubleInputDialog(_('Destroying %s') % '\u200E' + \ self.room_jid, _('You are going to remove this room permanently.' '\nYou may specify a reason below:'), _('You may also enter an alternate venue:'), ok_handler=on_ok, transient_for=self.parent_win.window) def _on_configure_room(self, action, param): c = app.contacts.get_gc_contact( self.account, self.room_jid, self.nick) if c.affiliation == 'owner': con = app.connections[self.account] con.get_module('MUC').request_config(self.room_jid) elif c.affiliation == 'admin': if self.room_jid not in app.interface.instances[self.account][ 'gc_config']: app.interface.instances[self.account]['gc_config'][ self.room_jid] = config.GroupchatConfigWindow(self.account, self.room_jid) def _on_bookmark_room(self, action, param): """ Bookmark the room, without autojoin and not minimized """ password = app.gc_passwords.get(self.room_jid, '') con = app.connections[self.account] con.get_module('Bookmarks').add_bookmark(self.name, self.room_jid, True, True, password, self.nick) self.update_actions() def _on_request_voice(self, action, param): """ Request voice in the current room """ con = app.connections[self.account] con.get_module('MUC').request_voice(self.room_jid) def _on_minimize(self, action, param): """ When a groupchat is minimized, unparent the tab, put it in roster etc """ action.set_state(param) non_minimized_gc = app.config.get_per( 'accounts', self.account, 'non_minimized_gc').split() minimize = param.get_boolean() if minimize: non_minimized_gc.remove(self.contact.jid) else: non_minimized_gc.append(self.contact.jid) app.config.set_per('accounts', self.account, 'non_minimized_gc', ' '.join(non_minimized_gc)) def _on_notify_on_all_messages(self, action, param): action.set_state(param) app.config.set_per('rooms', self.contact.jid, 'notify_on_all_messages', param.get_boolean()) def _on_sync_threshold(self, action, param): threshold = param.get_string() action.set_state(param) app.logger.set_archive_infos(self.contact.jid, sync_threshold=threshold) def _on_execute_command(self, action, param): """ Execute AdHoc commands on the current room """ adhoc_commands.CommandWindow(self.account, self.room_jid) def _on_upload_avatar(self, action, param): def _on_accept(filename): sha = app.interface.save_avatar(filename, publish=True) if sha is None: ErrorDialog( _('Could not load image'), transient_for=self.parent_win.window) return publish = app.interface.get_avatar(sha, publish=True) avatar = base64.b64encode(publish).decode('utf-8') con = app.connections[self.account] con.get_module('VCardTemp').upload_room_avatar( self.room_jid, avatar) AvatarChooserDialog(_on_accept, transient_for=self.parent_win.window, modal=True) def show_roster(self): new_state = not self.hpaned.get_child2().is_visible() image = self.hide_roster_button.get_image() if new_state: self.hpaned.get_child2().show() image.set_from_icon_name('go-next-symbolic', Gtk.IconSize.MENU) else: self.hpaned.get_child2().hide() image.set_from_icon_name('go-previous-symbolic', Gtk.IconSize.MENU) def on_groupchat_maximize(self): self.set_tooltip() self.add_actions() self.update_actions() self.set_lock_image() self._connect_window_state_change(self.parent_win) def set_tooltip(self): widget = self.xml.get_object('list_treeview') if widget.get_tooltip_window(): return widget.set_has_tooltip(True) id_ = widget.connect('query-tooltip', self.query_tooltip) self.handlers[id_] = widget def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): try: row = self.list_treeview.get_path_at_pos(x_pos, y_pos)[0] except TypeError: self.gc_tooltip.clear_tooltip() return False if not row: self.gc_tooltip.clear_tooltip() return False iter_ = None try: iter_ = self.model.get_iter(row) except Exception: self.gc_tooltip.clear_tooltip() return False typ = self.model[iter_][Column.TYPE] nick = self.model[iter_][Column.NICK] if typ != 'contact': self.gc_tooltip.clear_tooltip() return False contact = app.contacts.get_gc_contact( self.account, self.room_jid, nick) if not contact: self.gc_tooltip.clear_tooltip() return False value, widget = self.gc_tooltip.get_tooltip(contact) tooltip.set_custom(widget) return value def fill_column(self, col): for rend in self.renderers_list: col.pack_start(rend[1], rend[2]) if rend[0] not in ('avatar', 'icon'): col.add_attribute(rend[1], rend[3], rend[4]) col.set_cell_data_func(rend[1], rend[5], rend[6]) # set renderers properties for renderer in self.renderers_propertys: renderer.set_property(self.renderers_propertys[renderer][0], self.renderers_propertys[renderer][1]) def tree_compare_iters(self, model, iter1, iter2, data=None): """ Compare two iterators to sort them """ type1 = model[iter1][Column.TYPE] type2 = model[iter2][Column.TYPE] if not type1 or not type2: return 0 nick1 = model[iter1][Column.NICK] nick2 = model[iter2][Column.NICK] if not nick1 or not nick2: return 0 if type1 == 'role': return locale.strcoll(nick1, nick2) if type1 == 'contact': gc_contact1 = app.contacts.get_gc_contact(self.account, self.room_jid, nick1) if not gc_contact1: return 0 if type2 == 'contact': gc_contact2 = app.contacts.get_gc_contact(self.account, self.room_jid, nick2) if not gc_contact2: return 0 if type1 == 'contact' and type2 == 'contact' and \ app.config.get('sort_by_show_in_muc'): cshow = {'chat':0, 'online': 1, 'away': 2, 'xa': 3, 'dnd': 4, 'invisible': 5, 'offline': 6, 'error': 7} show1 = cshow[gc_contact1.show] show2 = cshow[gc_contact2.show] if show1 < show2: return -1 if show1 > show2: return 1 # We compare names name1 = gc_contact1.get_shown_name() name2 = gc_contact2.get_shown_name() return locale.strcoll(name1.lower(), name2.lower()) def on_msg_textview_populate_popup(self, textview, menu): """ Override the default context menu and we prepend Clear and the ability to insert a nick """ ChatControlBase.on_msg_textview_populate_popup(self, textview, menu) item = Gtk.SeparatorMenuItem.new() menu.prepend(item) item = Gtk.MenuItem.new_with_label(_('Insert Nickname')) menu.prepend(item) submenu = Gtk.Menu() item.set_submenu(submenu) for nick in sorted(app.contacts.get_nick_list(self.account, self.room_jid)): item = Gtk.MenuItem.new_with_label(nick) item.set_use_underline(False) submenu.append(item) id_ = item.connect('activate', self.append_nick_in_msg_textview, nick) self.handlers[id_] = item menu.show_all() def resize_occupant_treeview(self, position): if self.hpaned.get_position() == position: return self._resize_from_another_muc = True self.hpaned.set_position(position) def _reset_flag(): self._resize_from_another_muc = False # Reset the flag when everything will be redrawn, and in particular when # on_treeview_size_allocate will have been called. GLib.timeout_add(500, _reset_flag) def _on_window_state_change(self, win, param): # Add with timeout, because state change happens before # the hpaned notifys us about a new handle position GLib.timeout_add(100, self._check_for_resize) def _on_hpaned_release_button(self, hpaned, event): if event.get_button()[1] != 1: # We want only to catch the left mouse button return self._check_for_resize() def _check_for_resize(self): # Check if we have a new position pos = self.hpaned.get_position() if pos == app.config.get('gc-hpaned-position'): return # Save new position self._remove_handle_timeout() app.config.set('gc-hpaned-position', pos) # Resize other MUC rosters for account in app.gc_connected: for room_jid in [i for i in app.gc_connected[account] if \ app.gc_connected[account][i] and i != self.room_jid]: ctrl = app.interface.msg_win_mgr.get_gc_control(room_jid, account) if not ctrl and room_jid in \ app.interface.minimized_controls[account]: ctrl = app.interface.minimized_controls[account][room_jid] if ctrl and app.config.get('one_message_window') != 'never': ctrl.resize_occupant_treeview(pos) def _on_hpaned_handle_change(self, hpaned, param): if self._resize_from_another_muc: return # Window was resized, save new handle pos pos = hpaned.get_position() if pos != app.config.get('gc-hpaned-position'): self._remove_handle_timeout(renew=True) def _remove_handle_timeout(self, renew=False): if self._handle_timeout_id is not None: GLib.source_remove(self._handle_timeout_id) self._handle_timeout_id = None if renew: pos = self.hpaned.get_position() self._handle_timeout_id = GLib.timeout_add_seconds( 2, self._save_handle_position, pos) def _save_handle_position(self, pos): self._handle_timeout_id = None app.config.set('gc-hpaned-position', pos) def iter_contact_rows(self): """ Iterate over all contact rows in the tree model """ role_iter = self.model.get_iter_first() while role_iter: contact_iter = self.model.iter_children(role_iter) while contact_iter: yield self.model[contact_iter] contact_iter = self.model.iter_next(contact_iter) role_iter = self.model.iter_next(role_iter) def on_list_treeview_style_set(self, treeview, style): """ When style (theme) changes, redraw all contacts """ # Get the room_jid from treeview for contact in self.iter_contact_rows(): nick = contact[Column.NICK] self.draw_contact(nick) def get_tab_label(self, chatstate): """ Markup the label if necessary. Returns a tuple such as: (new_label_str, color) either of which can be None if chatstate is given that means we have HE SENT US a chatstate """ has_focus = self.parent_win.window.get_property('has-toplevel-focus') current_tab = self.parent_win.get_active_control() == self color = None if chatstate == 'attention' and (not has_focus or not current_tab): self.attention_flag = True color = 'tab-muc-directed-msg' elif chatstate == 'active' or (current_tab and has_focus): self.attention_flag = False # get active color from gtk color = 'active' elif chatstate == 'newmsg' and (not has_focus or not current_tab) \ and not self.attention_flag: color = 'tab-muc-msg' if self.is_continued: # if this is a continued conversation label_str = self.get_continued_conversation_name() else: label_str = self.name label_str = GLib.markup_escape_text(label_str) # count waiting highlighted messages unread = '' num_unread = self.get_nb_unread() if num_unread == 1: unread = '*' elif num_unread > 1: unread = '[' + str(num_unread) + ']' label_str = unread + label_str return (label_str, color) def get_tab_image(self, count_unread=True): tab_image = None if self.is_connected: tab_image = gtkgui_helpers.get_iconset_name_for('muc-active') else: tab_image = gtkgui_helpers.get_iconset_name_for('muc-inactive') return tab_image def update_ui(self): ChatControlBase.update_ui(self) for nick in app.contacts.get_nick_list(self.account, self.room_jid): self.draw_contact(nick) def set_lock_image(self): encryption_state = {'visible': self.encryption is not None, 'enc_type': self.encryption, 'authenticated': False} if self.encryption: app.plugin_manager.extension_point( 'encryption_state' + self.encryption, self, encryption_state) self._show_lock_image(**encryption_state) def _show_lock_image(self, visible, enc_type='', authenticated=False): """ Set lock icon visibility and create tooltip """ if authenticated: authenticated_string = _('and authenticated') self.lock_image.set_from_icon_name( 'security-high', Gtk.IconSize.MENU) else: authenticated_string = _('and NOT authenticated') self.lock_image.set_from_icon_name( 'security-low', Gtk.IconSize.MENU) tooltip = _('%(type)s encryption is active %(authenticated)s.') % { 'type': enc_type, 'authenticated': authenticated_string} self.authentication_button.set_tooltip_text(tooltip) self.widget_set_visible(self.authentication_button, not visible) self.lock_image.set_sensitive(visible) def _on_authentication_button_clicked(self, widget): app.plugin_manager.extension_point( 'encryption_dialog' + self.encryption, self) def _change_style(self, model, path, iter_, option): model[iter_][Column.NICK] = model[iter_][Column.NICK] def change_roster_style(self): self.model.foreach(self._change_style, None) def repaint_themed_widgets(self): ChatControlBase.repaint_themed_widgets(self) self.change_roster_style() def _update_banner_state_image(self): banner_status_img = self.xml.get_object('gc_banner_status_image') if self.is_connected: if self.contact.avatar_sha: surface = app.interface.get_avatar(self.contact.avatar_sha, AvatarSize.ROSTER, self.scale_factor) banner_status_img.set_from_surface(surface) return icon = gtkgui_helpers.get_iconset_name_for('muc-active') else: icon = gtkgui_helpers.get_iconset_name_for('muc-inactive') banner_status_img.set_from_icon_name(icon, Gtk.IconSize.DND) def get_continued_conversation_name(self): """ Get the name of a continued conversation. Will return Continued Conversation if there isn't any other contact in the room """ nicks = [] for nick in app.contacts.get_nick_list(self.account, self.room_jid): if nick != self.nick: nicks.append(nick) if nicks != []: title = ', ' title = _('Conversation with ') + title.join(nicks) else: title = _('Continued conversation') return title def draw_banner_text(self): """ Draw the text in the fat line at the top of the window that houses the room jid, subject """ self.name_label.set_ellipsize(Pango.EllipsizeMode.END) if self.is_continued: name = self.get_continued_conversation_name() else: name = self.room_jid self.name_label.set_text(name) if self.subject: subject = GLib.markup_escape_text(self.subject) subject_text = self.urlfinder.sub(self.make_href, subject) self.subject_button.get_popover().set_text(subject_text) def _nec_vcard_published(self, obj): if obj.conn.name != self.account: return show = app.SHOW_LIST[obj.conn.connected] status = obj.conn.status obj.conn.send_gc_status(self.nick, self.room_jid, show, status) def _nec_update_avatar(self, obj): if obj.contact.room_jid != self.room_jid: return app.log('avatar').debug('Draw Groupchat Avatar: %s %s', obj.contact.name, obj.contact.avatar_sha) self.draw_avatar(obj.contact) def _nec_update_room_avatar(self, obj): if obj.jid != self.room_jid: return self._update_banner_state_image() def _nec_mam_decrypted_message_received(self, obj): if obj.conn.name != self.account: return if not obj.groupchat: return if obj.archive_jid != self.room_jid: return self.print_conversation( obj.msgtxt, contact=obj.nick, tim=obj.timestamp, correct_id=obj.correct_id, encrypted=obj.encrypted, msg_stanza_id=obj.message_id, additional_data=obj.additional_data) def _nec_gc_message_received(self, obj): if obj.room_jid != self.room_jid or obj.conn.name != self.account: return if obj.captcha_form: if self.form_widget: self.form_widget.hide() self.form_widget.destroy() self.btn_box.destroy() dataform = dataforms.extend_form(node=obj.captcha_form) self.form_widget = dataforms_widget.DataFormWidget(dataform) def on_send_dataform_clicked(widget): if not self.form_widget: return form_node = self.form_widget.data_form.get_purged() form_node.type_ = 'submit' obj.conn.send_captcha(self.room_jid, form_node) self.form_widget.hide() self.form_widget.destroy() self.btn_box.destroy() self.form_widget = None del self.btn_box self.form_widget.connect('validated', on_send_dataform_clicked) self.form_widget.show_all() vbox = self.xml.get_object('gc_textviews_vbox') vbox.pack_start(self.form_widget, False, True, 0) valid_button = Gtk.Button(stock=Gtk.STOCK_OK) valid_button.connect('clicked', on_send_dataform_clicked) self.btn_box = Gtk.HButtonBox() self.btn_box.set_layout(Gtk.ButtonBoxStyle.END) self.btn_box.pack_start(valid_button, True, True, 0) self.btn_box.show_all() vbox.pack_start(self.btn_box, False, False, 0) if self.parent_win: self.parent_win.redraw_tab(self, 'attention') else: self.attention_flag = True if '100' in obj.status_code: # Room is not anonymous self.is_anonymous = False if not obj.nick: # message from server self.print_conversation( obj.msgtxt, tim=obj.timestamp, xhtml=obj.xhtml_msgtxt, displaymarking=obj.displaymarking, additional_data=obj.additional_data) else: # message from someone if obj.delayed: # don't print xhtml if it's an old message. # Like that xhtml messages are grayed too. self.print_old_conversation( obj.msgtxt, contact=obj.nick, tim=obj.timestamp, xhtml=None, encrypted=obj.encrypted, displaymarking=obj.displaymarking, msg_stanza_id=obj.id_, additional_data=obj.additional_data) else: if obj.nick == self.nick: self.last_sent_txt = obj.msgtxt self.print_conversation( obj.msgtxt, contact=obj.nick, tim=obj.timestamp, xhtml=obj.xhtml_msgtxt, displaymarking=obj.displaymarking, encrypted=obj.encrypted, correct_id=obj.correct_id, msg_stanza_id=obj.id_, additional_data=obj.additional_data) obj.needs_highlight = self.needs_visual_notification(obj.msgtxt) def on_private_message(self, nick, sent, msg, tim, xhtml, session, msg_log_id=None, encrypted=False, displaymarking=None): # Do we have a queue? fjid = self.room_jid + '/' + nick no_queue = len(app.events.get_events(self.account, fjid)) == 0 event = events.PmEvent(msg, '', 'incoming', tim, encrypted, '', msg_log_id, xhtml=xhtml, session=session, form_node=None, displaymarking=displaymarking, sent_forwarded=sent) app.events.add_event(self.account, fjid, event) autopopup = app.config.get('autopopup') autopopupaway = app.config.get('autopopupaway') iter_ = self.get_contact_iter(nick) path = self.model.get_path(iter_) if not autopopup or (not autopopupaway and \ app.connections[self.account].connected > 2): if no_queue: # We didn't have a queue: we change icons icon_name = gtkgui_helpers.get_iconset_name_for('event') surface = Gtk.IconTheme.get_default().load_surface( icon_name, 16, self.scale_factor, None, 0) image = Gtk.Image.new_from_surface(surface) self.model[iter_][Column.IMG] = image if self.parent_win: self.parent_win.show_title() self.parent_win.redraw_tab(self) else: self._start_private_message(nick) # Scroll to line path_ = path.copy() path_.up() self.list_treeview.expand_row(path_, False) self.list_treeview.scroll_to_cell(path) self.list_treeview.set_cursor(path) contact = app.contacts.get_contact_with_highest_priority( self.account, self.room_jid) if contact: app.interface.roster.draw_contact(self.room_jid, self.account) def get_contact_iter(self, nick: str) -> Optional[Gtk.TreeIter]: try: ref = self._contact_refs[nick] except KeyError: return None path = ref.get_path() if path is None: return None return self.model.get_iter(path) def print_old_conversation(self, text, contact='', tim=None, xhtml=None, displaymarking=None, msg_stanza_id=None, encrypted=None, additional_data=None): if additional_data is None: additional_data = AdditionalDataDict() if contact: if contact == self.nick: # it's us kind = 'outgoing' else: kind = 'incoming' else: kind = 'status' if app.config.get('restored_messages_small'): small_attr = ['small'] else: small_attr = [] ChatControlBase.print_conversation_line(self, text, kind, contact, tim, small_attr, small_attr + ['restored_message'], small_attr + ['restored_message'], count_as_new=False, xhtml=xhtml, displaymarking=displaymarking, msg_stanza_id=msg_stanza_id, encrypted=encrypted, additional_data=additional_data) def print_conversation(self, text, contact='', tim=None, xhtml=None, graphics=True, displaymarking=None, correct_id=None, msg_stanza_id=None, encrypted=None, additional_data=None): """ Print a line in the conversation If contact is set: it's a message from someone or an info message (contact = 'info' in such a case). If contact is not set: it's a message from the server or help. """ if additional_data is None: additional_data = AdditionalDataDict() other_tags_for_name = [] other_tags_for_text = [] if contact: if contact == self.nick: # it's us kind = 'outgoing' elif contact == 'info': kind = 'info' contact = None else: kind = 'incoming' # muc-specific chatstate if self.parent_win: self.parent_win.redraw_tab(self, 'newmsg') else: kind = 'status' if kind == 'incoming': # it's a message NOT from us # highlighting and sounds highlight, _sound = self.highlighting_for_message(text, tim) if contact in self.gc_custom_colors: other_tags_for_name.append('gc_nickname_color_' + \ str(self.gc_custom_colors[contact])) else: self.gc_count_nicknames_colors += 1 if self.gc_count_nicknames_colors == self.number_of_colors: self.gc_count_nicknames_colors = 0 self.gc_custom_colors[contact] = \ self.gc_count_nicknames_colors other_tags_for_name.append('gc_nickname_color_' + \ str(self.gc_count_nicknames_colors)) if highlight: # muc-specific chatstate if self.parent_win: self.parent_win.redraw_tab(self, 'attention') else: self.attention_flag = True other_tags_for_name.append('bold') other_tags_for_text.append('marked') if contact in self.attention_list: self.attention_list.remove(contact) elif len(self.attention_list) > 6: self.attention_list.pop(0) # remove older self.attention_list.append(contact) if text.startswith('/me ') or text.startswith('/me\n'): other_tags_for_text.append('gc_nickname_color_' + \ str(self.gc_custom_colors[contact])) self.check_and_possibly_add_focus_out_line() ChatControlBase.print_conversation_line(self, text, kind, contact, tim, other_tags_for_name, [], other_tags_for_text, xhtml=xhtml, graphics=graphics, displaymarking=displaymarking, correct_id=correct_id, msg_stanza_id=msg_stanza_id, encrypted=encrypted, additional_data=additional_data) def get_nb_unread(self): type_events = ['printed_marked_gc_msg'] if app.config.get('notify_on_all_muc_messages') or \ app.config.get_per('rooms', self.room_jid, 'notify_on_all_messages'): type_events.append('printed_gc_msg') nb = len(app.events.get_events(self.account, self.room_jid, type_events)) nb += self.get_nb_unread_pm() return nb def get_nb_unread_pm(self): nb = 0 for nick in app.contacts.get_nick_list(self.account, self.room_jid): nb += len(app.events.get_events(self.account, self.room_jid + \ '/' + nick, ['pm'])) return nb def highlighting_for_message(self, text, tim): """ Returns a 2-Tuple. The first says whether or not to highlight the text, the second, what sound to play """ highlight, sound = (None, None) # Are any of the defined highlighting words in the text? if self.needs_visual_notification(text): highlight = True if app.config.get_per('soundevents', 'muc_message_highlight', 'enabled'): sound = 'highlight' # Do we play a sound on every muc message? elif app.config.get_per('soundevents', 'muc_message_received', \ 'enabled'): sound = 'received' # Is it a history message? Don't want sound-floods when we join. if tim is not None and time.mktime(time.localtime()) - tim > 1: sound = None return (highlight, sound) def check_and_possibly_add_focus_out_line(self): """ Check and possibly add focus out line for room_jid if it needs it and does not already have it as last event. If it goes to add this line - remove previous line first """ win = app.interface.msg_win_mgr.get_window(self.room_jid, self.account) if win and self.room_jid == win.get_active_jid() and\ win.window.get_property('has-toplevel-focus') and\ self.parent_win.get_active_control() == self: # it's the current room and it's the focused window. # we have full focus (we are reading it!) return self.conv_textview.show_focus_out_line() def needs_visual_notification(self, text): """ Check text to see whether any of the words in (muc_highlight_words and nick) appear """ special_words = app.config.get('muc_highlight_words').split(';') special_words.append(self.nick) con = app.connections[self.account] special_words.append(con.get_own_jid().getStripped()) # Strip empties: ''.split(';') == [''] and would highlight everything. # Also lowercase everything for case insensitive compare. special_words = [word.lower() for word in special_words if word] text = text.lower() for special_word in special_words: found_here = text.find(special_word) while found_here > -1: end_here = found_here + len(special_word) if (found_here == 0 or not text[found_here - 1].isalpha()) and \ (end_here == len(text) or not text[end_here].isalpha()): # It is beginning of text or char before is not alpha AND # it is end of text or char after is not alpha return True # continue searching start = found_here + 1 found_here = text.find(special_word, start) return False def set_subject(self, subject): self.subject = subject self.draw_banner_text() def _nec_gc_subject_received(self, event): if event.account != self.account: return if event.jid != self.room_jid: return if self.subject == event.subject: # Probably a rejoin, we already showed that subject return self.set_subject(event.subject) text = _('%(nick)s has set the subject to %(subject)s') % { 'nick': event.resource, 'subject': event.subject} if event.delayed: date = time.strftime('%d-%m-%Y %H:%M:%S', time.localtime(event.timestamp)) text = '%s - %s' % (text, date) just_joined = self.join_time > time.time() - 10 if app.config.get('show_subject_on_join') or not just_joined: self.print_conversation(text) if event.subject == '': self.subject_button.hide() else: self.subject_button.show() def _nec_gc_config_changed_received(self, obj): # statuscode is a list # http://www.xmpp.org/extensions/xep-0045.html#roomconfig-notify # http://www.xmpp.org/extensions/xep-0045.html#registrar-statuscodes... # -init if obj.room_jid != self.room_jid or obj.conn.name != self.account: return changes = [] if '100' in obj.status_code: # Can be a presence (see chg_contact_status in groupchat_control.py) changes.append(_('Any occupant is allowed to see your full JID')) self.is_anonymous = False if '102' in obj.status_code: changes.append(_('Room now shows unavailable members')) if '103' in obj.status_code: changes.append(_('Room now does not show unavailable members')) if '104' in obj.status_code: changes.append(_('A setting not related to privacy has been ' 'changed')) app.connections[self.account].get_module('Discovery').disco_muc( self.room_jid, self.update_actions, update=True) if '170' in obj.status_code: # Can be a presence (see chg_contact_status in groupchat_control.py) changes.append(_('Room logging is now enabled')) if '171' in obj.status_code: changes.append(_('Room logging is now disabled')) if '172' in obj.status_code: changes.append(_('Room is now non-anonymous')) self.is_anonymous = False if '173' in obj.status_code: changes.append(_('Room is now semi-anonymous')) self.is_anonymous = True if '174' in obj.status_code: changes.append(_('Room is now fully anonymous')) self.is_anonymous = True for change in changes: self.print_conversation(change) def _nec_signed_in(self, obj): if obj.conn.name != self.account: return password = app.gc_passwords.get(self.room_jid, '') obj.conn.join_gc(self.nick, self.room_jid, password, rejoin=True) def _nec_decrypted_message_received(self, obj): if obj.conn.name != self.account: return if obj.gc_control == self and obj.resource: # We got a pm from this room nick = obj.resource if obj.session.control: # print if a control is open frm = '' if obj.sent: frm = 'out' obj.session.control.print_conversation(obj.msgtxt, frm, tim=obj.timestamp, xhtml=obj.xhtml, encrypted=obj.encrypted, displaymarking=obj.displaymarking, msg_stanza_id=obj.id_, correct_id=obj.correct_id) else: # otherwise pass it off to the control to be queued self.on_private_message(nick, obj.sent, obj.msgtxt, obj.timestamp, obj.xhtml, self.session, msg_log_id=obj.msg_log_id, encrypted=obj.encrypted, displaymarking=obj.displaymarking) def _nec_ping(self, obj): if self.contact.jid != obj.contact.room_jid: return nick = obj.contact.get_shown_name() if obj.name == 'ping-sent': self.print_conversation(_('Ping? (%s)') % nick) elif obj.name == 'ping-reply': self.print_conversation( _('Pong! (%(nick)s %(delay)s s.)') % {'nick': nick, 'delay': obj.seconds}) elif obj.name == 'ping-error': self.print_conversation(_('Error.')) @property def is_connected(self) -> bool: return app.gc_connected[self.account][self.room_jid] @is_connected.setter def is_connected(self, value: bool) -> None: app.gc_connected[self.account][self.room_jid] = value def got_connected(self): self.join_time = time.time() # Make autorejoin stop. if self.autorejoin: GLib.source_remove(self.autorejoin) self.autorejoin = None if muc_caps_cache.has_mam(self.room_jid): # Request MAM con = app.connections[self.account] con.get_module('MAM').request_archive_on_muc_join( self.room_jid) self.is_connected = True ChatControlBase.got_connected(self) # Sort model and assign it to treeview self.model.set_sort_column_id(Column.NICK, Gtk.SortType.ASCENDING) self.list_treeview.set_model(self.model) self.list_treeview.expand_all() # We don't redraw the whole banner here, because only icon change self._update_banner_state_image() if self.parent_win: self.parent_win.redraw_tab(self) formattings_button = self.xml.get_object('formattings_button') formattings_button.set_sensitive(True) self.update_actions() def got_disconnected(self): formattings_button = self.xml.get_object('formattings_button') formattings_button.set_sensitive(False) self.model.set_sort_column_id(Gtk.TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, Gtk.SortType.ASCENDING) self.list_treeview.set_model(None) self._contact_refs = {} self._role_refs = {} self.model.clear() nick_list = app.contacts.get_nick_list(self.account, self.room_jid) for nick in nick_list: # Update pm chat window fjid = self.room_jid + '/' + nick gc_contact = app.contacts.get_gc_contact(self.account, self.room_jid, nick) ctrl = app.interface.msg_win_mgr.get_control(fjid, self.account) if ctrl: gc_contact.show = 'offline' gc_contact.status = '' ctrl.update_ui() if ctrl.parent_win: ctrl.parent_win.redraw_tab(ctrl) app.contacts.remove_gc_contact(self.account, gc_contact) self.is_connected = False ChatControlBase.got_disconnected(self) # We don't redraw the whole banner here, because only icon change self._update_banner_state_image() if self.parent_win: self.parent_win.redraw_tab(self) # Autorejoin stuff goes here. # Notice that we don't need to activate autorejoin if connection is lost # or in progress. if self.autorejoin is None and app.account_is_connected(self.account): ar_to = app.config.get('muc_autorejoin_timeout') if ar_to: self.autorejoin = GLib.timeout_add_seconds(ar_to, self.rejoin) self.update_actions() def rejoin(self): if not self.autorejoin: return False password = app.gc_passwords.get(self.room_jid, '') app.connections[self.account].join_gc(self.nick, self.room_jid, password, rejoin=True) return True def draw_roster(self): self.model.clear() for nick in app.contacts.get_nick_list(self.account, self.room_jid): gc_contact = app.contacts.get_gc_contact(self.account, self.room_jid, nick) self.add_contact_to_roster(nick, gc_contact.show, gc_contact.role, gc_contact.affiliation, gc_contact.status, gc_contact.jid) self.draw_all_roles() # Recalculate column width for ellipsizin self.list_treeview.columns_autosize() def on_send_pm(self, widget=None, model=None, iter_=None, nick=None, msg=None): """ Open a chat window and if msg is not None - send private message to a contact in a room """ if nick is None: nick = model[iter_][Column.NICK] ctrl = self._start_private_message(nick) if ctrl and msg: ctrl.send_message(msg) def draw_contact(self, nick): iter_ = self.get_contact_iter(nick) if not iter_: return gc_contact = app.contacts.get_gc_contact(self.account, self.room_jid, nick) theme = Gtk.IconTheme.get_default() if app.events.get_events(self.account, self.room_jid + '/' + nick): icon_name = gtkgui_helpers.get_iconset_name_for('event') surface = theme.load_surface(icon_name, 16, self.scale_factor, None, 0) else: icon_name = gtkgui_helpers.get_iconset_name_for(gc_contact.show) surface = theme.load_surface(icon_name, 16, self.scale_factor, None, 0) name = GLib.markup_escape_text(gc_contact.name) # Strike name if blocked fjid = self.room_jid + '/' + nick if helpers.jid_is_blocked(self.account, fjid): name = '%s' % name status = gc_contact.status # add status msg, if not empty, under contact name in the treeview if status and app.config.get('show_status_msgs_in_roster'): status = status.strip() if status != '': status = helpers.reduce_chars_newlines(status, max_lines=1) # escape markup entities and make them small italic and fg color name += ('\n' '{}'.format(GLib.markup_escape_text(status))) if (gc_contact.affiliation != 'none' and app.config.get('show_affiliation_in_groupchat')): gtkgui_helpers.draw_affiliation(surface, gc_contact.affiliation) image = Gtk.Image.new_from_surface(surface) self.model[iter_][Column.IMG] = image self.model[iter_][Column.TEXT] = name def draw_avatar(self, gc_contact): if not app.config.get('show_avatars_in_roster'): return iter_ = self.get_contact_iter(gc_contact.name) if not iter_: return surface = app.interface.get_avatar( gc_contact.avatar_sha, AvatarSize.ROSTER, self.scale_factor) image = Gtk.Image.new_from_surface(surface) self.model[iter_][Column.AVATAR_IMG] = image def draw_role(self, role): role_iter = self.get_role_iter(role) if not role_iter: return role_name = helpers.get_uf_role(role, plural=True) if app.config.get('show_contacts_number'): nbr_role, nbr_total = app.contacts.get_nb_role_total_gc_contacts( self.account, self.room_jid, role) role_name += ' (%s/%s)' % (repr(nbr_role), repr(nbr_total)) self.model[role_iter][Column.TEXT] = role_name def draw_all_roles(self): for role in ('visitor', 'participant', 'moderator'): self.draw_role(role) def _nec_gc_presence_received(self, obj): if obj.room_jid != self.room_jid or obj.conn.name != self.account: return if obj.ptype == 'error': return role = obj.role if not role: role = 'visitor' affiliation = obj.affiliation if not affiliation: affiliation = 'none' newly_created = False nick = i18n.direction_mark + obj.nick nick_jid = nick + i18n.direction_mark # Set to true if role or affiliation have changed right_changed = False if obj.real_jid: # delete resource simple_jid = app.get_jid_without_resource(obj.real_jid) nick_jid += ' (%s)' % simple_jid con = app.connections[self.account] bookmarks = con.get_module('Bookmarks').bookmarks bookmark = bookmarks.get(self.room_jid, None) if bookmark is None or not bookmark['print_status']: print_status = app.config.get('print_status_in_muc') else: print_status = bookmark['print_status'] # status_code # http://www.xmpp.org/extensions/xep-0045.html#registrar-statuscodes-\ # init if obj.status_code and obj.nick == self.nick: if '110' in obj.status_code: if not self.is_connected: # We just join the room self.print_conversation( _('You (%s) joined the room') % self.nick, 'info', graphics=False) if self.room_jid in app.automatic_rooms[self.account] and \ app.automatic_rooms[self.account][self.room_jid]['invities']: if self.room_jid not in app.interface.instances[ self.account]['gc_config']: if obj.affiliation == 'owner': # We need to configure the room if it's a new one. # We cannot know it's a new one. Status 201 is not # sent by all servers. con = app.connections[self.account] con.get_module('MUC').request_config(self.room_jid) elif 'continue_tag' in app.automatic_rooms[ self.account][self.room_jid]: # We just need to invite contacts for jid in app.automatic_rooms[self.account][ self.room_jid]['invities']: obj.conn.get_module('MUC').invite(self.room_jid, jid) self.print_conversation(_('%(jid)s has been ' 'invited in this room') % {'jid': jid}, graphics=False) if '100' in obj.status_code: # Can be a message (see handle_event_gc_config_change in # app.py) self.print_conversation( _('Any occupant is allowed to see your full JID')) self.is_anonymous = False if '170' in obj.status_code: # Can be a message (see handle_event_gc_config_change in # app.py) self.print_conversation(_('Room logging is enabled')) if '201' in obj.status_code: app.connections[self.account].get_module('Discovery').disco_muc( self.room_jid, self._on_room_created, update=True) self.print_conversation(_('A new room has been created')) if '210' in obj.status_code: self.print_conversation(\ _('The server has assigned or modified your roomnick')) if obj.show in ('offline', 'error'): if obj.status_code: if '333' in obj.status_code: # Handle 333 before 307, some MUCs add both if print_status != 'none': if obj.nick == self.nick: s = _('%s kicked us due to an error' % self.room_jid) else: s = _('%s has left due to an error' % nick) if obj.reason: s += ' (%s)' % obj.reason self.print_conversation(s, 'info', graphics=False) elif '307' in obj.status_code: if obj.actor is None: # do not print 'kicked by None' s = _('%(nick)s has been kicked: %(reason)s') % { 'nick': nick, 'reason': obj.reason} else: s = _('%(nick)s has been kicked by %(who)s: ' '%(reason)s') % {'nick': nick, 'who': obj.actor, 'reason': obj.reason} self.print_conversation(s, 'info', graphics=False) if obj.nick == self.nick and not app.config.get( 'muc_autorejoin_on_kick'): self.autorejoin = False elif '301' in obj.status_code: if obj.actor is None: # do not print 'banned by None' s = _('%(nick)s has been banned: %(reason)s') % { 'nick': nick, 'reason': obj.reason} else: s = _('%(nick)s has been banned by %(who)s: ' '%(reason)s') % {'nick': nick, 'who': obj.actor, 'reason': obj.reason} self.print_conversation(s, 'info', graphics=False) if obj.nick == self.nick: self.autorejoin = False elif '303' in obj.status_code: # Someone changed their nick if obj.new_nick == self.new_nick or obj.nick == self.nick: # We changed our nick self.nick = obj.new_nick self.new_nick = '' s = _('You are now known as %s') % self.nick else: s = _('%(nick)s is now known as %(new_nick)s') % { 'nick': nick, 'new_nick': obj.new_nick} tv = self.conv_textview if obj.nick in tv.last_received_message_id: tv.last_received_message_id[obj.new_nick] = \ tv.last_received_message_id[obj.nick] del tv.last_received_message_id[obj.nick] # We add new nick to muc roster here, so we don't see # that "new_nick has joined the room" when he just changed # nick. # add_contact_to_roster will be called a second time # after that, but that doesn't hurt self.add_contact_to_roster(obj.new_nick, obj.show, role, affiliation, obj.status, obj.real_jid) if obj.nick in self.attention_list: self.attention_list.remove(obj.nick) # keep nickname color if obj.nick in self.gc_custom_colors: self.gc_custom_colors[obj.new_nick] = \ self.gc_custom_colors[obj.nick] self.print_conversation(s, 'info', graphics=False) elif '321' in obj.status_code: s = _('%(nick)s has been removed from the room ' '(%(reason)s)') % {'nick': nick, 'reason': _('affiliation changed')} self.print_conversation(s, 'info', graphics=False) elif '322' in obj.status_code: s = _('%(nick)s has been removed from the room ' '(%(reason)s)') % {'nick': nick, 'reason': _('room configuration changed to ' 'members-only')} self.print_conversation(s, 'info', graphics=False) elif '332' in obj.status_code: s = _('%(nick)s has been removed from the room ' '(%(reason)s)') % {'nick': nick, 'reason': _('system shutdown')} self.print_conversation(s, 'info', graphics=False) # Room has been destroyed. elif 'destroyed' in obj.status_code: self.autorejoin = False self.print_conversation(obj.reason, 'info', graphics=False) if not app.events.get_events( self.account, jid=obj.fjid, types=['pm']): self.remove_contact(obj.nick) self.draw_all_roles() else: c = app.contacts.get_gc_contact(self.account, self.room_jid, obj.nick) c.show = obj.show c.status = obj.status if obj.nick == self.nick and (not obj.status_code or \ '303' not in obj.status_code): # We became offline self.got_disconnected() contact = app.contacts.\ get_contact_with_highest_priority(self.account, self.room_jid) if contact: app.interface.roster.draw_contact(self.room_jid, self.account) if self.parent_win: self.parent_win.redraw_tab(self) else: iter_ = self.get_contact_iter(obj.nick) if not iter_: if '210' in obj.status_code: # Server changed our nick self.nick = obj.nick s = _('You are now known as %s') % nick self.print_conversation(s, 'info', graphics=False) iter_ = self.add_contact_to_roster(obj.nick, obj.show, role, affiliation, obj.status, obj.real_jid, obj.avatar_sha) newly_created = True self.draw_all_roles() if obj.status_code and '201' in obj.status_code: # We just created the room con = app.connections[self.account] con.get_module('MUC').request_config(self.room_jid) else: gc_c = app.contacts.get_gc_contact(self.account, self.room_jid, obj.nick) if not gc_c: log.error('%s has an iter, but no gc_contact instance', obj.nick) return actual_affiliation = gc_c.affiliation if affiliation != actual_affiliation: if obj.actor: st = _('** Affiliation of %(nick)s has been set to ' '%(affiliation)s by %(actor)s') % {'nick': nick_jid, 'affiliation': affiliation, 'actor': obj.actor} else: st = _('** Affiliation of %(nick)s has been set to ' '%(affiliation)s') % {'nick': nick_jid, 'affiliation': affiliation} if obj.reason: st += ' (%s)' % obj.reason self.print_conversation(st, graphics=False) right_changed = True actual_role = self.get_role(obj.nick) if role != actual_role: self.remove_contact(obj.nick) self.add_contact_to_roster(obj.nick, obj.show, role, affiliation, obj.status, obj.real_jid) self.draw_role(actual_role) self.draw_role(role) if obj.actor: st = _('** Role of %(nick)s has been set to %(role)s ' 'by %(actor)s') % {'nick': nick_jid, 'role': role, 'actor': obj.actor} else: st = _('** Role of %(nick)s has been set to ' '%(role)s') % {'nick': nick_jid, 'role': role} if obj.reason: st += ' (%s)' % obj.reason self.print_conversation(st, graphics=False) right_changed = True else: if gc_c.show == obj.show and gc_c.status == obj.status and \ gc_c.affiliation == affiliation: # no change return gc_c.show = obj.show gc_c.affiliation = affiliation gc_c.status = obj.status self.draw_contact(obj.nick) if self.is_connected and obj.nick != self.nick \ and (not obj.status_code or '303' not in obj.status_code) and not \ right_changed: st = '' if obj.show == 'offline': if obj.nick in self.attention_list: self.attention_list.remove(obj.nick) if obj.show == 'offline' and print_status in ('all', 'in_and_out') \ and (not obj.status_code or '307' not in obj.status_code): st = _('%s has left') % nick_jid if obj.reason: st += ' [%s]' % obj.reason else: if newly_created and print_status in ('all', 'in_and_out'): st = _('%s has joined the group chat') % nick_jid elif print_status == 'all': st = _('%(nick)s is now %(status)s') % {'nick': nick_jid, 'status': helpers.get_uf_show(obj.show)} if st: if obj.status: st += ' (' + obj.status + ')' self.print_conversation(st, graphics=False) # Update Actions if obj.status_code: if '110' in obj.status_code: self.update_actions() def add_contact_to_roster(self, nick, show, role, affiliation, status, jid='', avatar_sha=None): role_name = helpers.get_uf_role(role, plural=True) resource = '' if jid: jids = jid.split('/', 1) j = jids[0] if len(jids) > 1: resource = jids[1] else: j = '' name = nick # Add Contact gc_contact = app.contacts.create_gc_contact( room_jid=self.room_jid, account=self.account, name=nick, show=show, status=status, role=role, affiliation=affiliation, jid=j, resource=resource, avatar_sha=avatar_sha) app.contacts.add_gc_contact(self.account, gc_contact) # Create Role role_iter = self.get_role_iter(role) if not role_iter: image = gtkgui_helpers.get_image_from_icon_name('closed', self.scale_factor) ext_columns = [None] * self.nb_ext_renderers row = [image, role, 'role', role_name, None] + ext_columns role_iter = self.model.append(None, row) self._role_refs[role] = Gtk.TreeRowReference( self.model, self.model.get_path(role_iter)) self.draw_all_roles() # Avatar image = None if app.config.get('show_avatars_in_roster'): surface = app.interface.get_avatar( avatar_sha, AvatarSize.ROSTER, self.scale_factor) image = Gtk.Image.new_from_surface(surface) # Add to model ext_columns = [None] * self.nb_ext_renderers row = [image, nick, 'contact', name, None] + ext_columns iter_ = self.model.append(role_iter, row) self._contact_refs[nick] = Gtk.TreeRowReference( self.model, self.model.get_path(iter_)) self.draw_contact(nick) if nick == self.nick: # we became online self.got_connected() if self.list_treeview.get_model(): self.list_treeview.expand_row( (self.model.get_path(role_iter)), False) if self.is_continued: self.draw_banner_text() return iter_ def get_role_iter(self, role: str) -> Optional[Gtk.TreeIter]: try: ref = self._role_refs[role] except KeyError: return None path = ref.get_path() if path is None: return None return self.model.get_iter(path) def remove_contact(self, nick): """ Remove a user from the contacts_list """ iter_ = self.get_contact_iter(nick) if not iter_: return gc_contact = app.contacts.get_gc_contact( self.account, self.room_jid, nick) if gc_contact: app.contacts.remove_gc_contact(self.account, gc_contact) parent_iter = self.model.iter_parent(iter_) if parent_iter is None: # This is not a child, should never happen return self.model.remove(iter_) del self._contact_refs[nick] if self.model.iter_n_children(parent_iter) == 0: role = self.model[parent_iter][Column.NICK] del self._role_refs[role] self.model.remove(parent_iter) def _message_sent(self, obj): if not obj.message: return if obj.account != self.account: return if obj.jid != self.room_jid: return # we'll save sent message text when we'll receive it in # _nec_gc_message_received self.last_sent_msg = obj.stanza_id if self.correcting: self.correcting = False gtkgui_helpers.remove_css_class( self.msg_textview, 'gajim-msg-correcting') def send_message(self, message, xhtml=None, process_commands=True): """ Call this function to send our message """ if not message: return if self.encryption: self.sendmessage = True app.plugin_manager.extension_point( 'send_message' + self.encryption, self) if not self.sendmessage: return if process_commands and self.process_as_command(message): return message = helpers.remove_invalid_xml_chars(message) if not message: return label = self.get_seclabel() if message != '' or message != '\n': self.save_message(message, 'sent') if self.correcting and self.last_sent_msg: correct_id = self.last_sent_msg else: correct_id = None con = app.connections[self.account] chatstate = con.get_module('Chatstate').get_active_chatstate( self.contact) # Send the message app.nec.push_outgoing_event(GcMessageOutgoingEvent( None, account=self.account, jid=self.room_jid, message=message, xhtml=xhtml, label=label, chatstate=chatstate, correct_id=correct_id, automatic_message=False)) self.msg_textview.get_buffer().set_text('') self.msg_textview.grab_focus() def get_role(self, nick): gc_contact = app.contacts.get_gc_contact( self.account, self.room_jid, nick) if gc_contact: return gc_contact.role return 'visitor' def minimizable(self): if self.force_non_minimizable: return False if self.contact.jid not in app.config.get_per('accounts', self.account, 'non_minimized_gc').split(' '): return True return False def minimize(self, status='offline'): # Minimize it win = app.interface.msg_win_mgr.get_window(self.contact.jid, self.account) ctrl = win.get_control(self.contact.jid, self.account) ctrl_page = win.notebook.page_num(ctrl.widget) control = win.notebook.get_nth_page(ctrl_page) win.notebook.remove_page(ctrl_page) control.unparent() ctrl.parent_win = None con = app.connections[self.account] con.get_module('Chatstate').set_chatstate(self.contact, Chatstate.INACTIVE) app.interface.roster.minimize_groupchat( self.account, self.contact.jid, status=self.subject) del win._controls[self.account][self.contact.jid] def shutdown(self, status='offline'): # PluginSystem: calling shutdown of super class (ChatControlBase) # to let it remove it's GUI extension points super(GroupchatControl, self).shutdown() # PluginSystem: removing GUI extension points connected with # GrouphatControl instance object app.plugin_manager.remove_gui_extension_point('groupchat_control', self) # Preventing autorejoin from being activated self.autorejoin = False app.ged.remove_event_handler('gc-presence-received', ged.GUI1, self._nec_gc_presence_received) app.ged.remove_event_handler('gc-message-received', ged.GUI1, self._nec_gc_message_received) app.ged.remove_event_handler('vcard-published', ged.GUI1, self._nec_vcard_published) app.ged.remove_event_handler('update-gc-avatar', ged.GUI1, self._nec_update_avatar) app.ged.remove_event_handler('update-room-avatar', ged.GUI1, self._nec_update_room_avatar) app.ged.remove_event_handler('gc-subject-received', ged.GUI1, self._nec_gc_subject_received) app.ged.remove_event_handler('gc-config-changed-received', ged.GUI1, self._nec_gc_config_changed_received) app.ged.remove_event_handler('signed-in', ged.GUI1, self._nec_signed_in) app.ged.remove_event_handler('decrypted-message-received', ged.GUI2, self._nec_decrypted_message_received) app.ged.remove_event_handler('mam-decrypted-message-received', ged.GUI1, self._nec_mam_decrypted_message_received) app.ged.remove_event_handler('gc-stanza-message-outgoing', ged.OUT_POSTCORE, self._message_sent) if self.is_connected: app.connections[self.account].send_gc_status(self.nick, self.room_jid, show='offline', status=status) nick_list = app.contacts.get_nick_list(self.account, self.room_jid) for nick in nick_list: # Update pm chat window fjid = self.room_jid + '/' + nick ctrl = app.interface.msg_win_mgr.get_gc_control(fjid, self.account) if ctrl: contact = app.contacts.get_gc_contact(self.account, self.room_jid, nick) contact.show = 'offline' contact.status = '' ctrl.update_ui() ctrl.parent_win.redraw_tab(ctrl) # They can already be removed by the destroy function if self.room_jid in app.contacts.get_gc_list(self.account): app.contacts.remove_room(self.account, self.room_jid) del app.gc_connected[self.account][self.room_jid] # Save hpaned position app.config.set('gc-hpaned-position', self.hpaned.get_position()) # remove all register handlers on wigets, created by self.xml # to prevent circular references among objects for i in list(self.handlers.keys()): if self.handlers[i].handler_is_connected(i): self.handlers[i].disconnect(i) del self.handlers[i] # Remove unread events from systray app.events.remove_events(self.account, self.room_jid) def safe_shutdown(self): if self.minimizable(): return True includes = app.config.get('confirm_close_muc_rooms').split(' ') excludes = app.config.get('noconfirm_close_muc_rooms').split(' ') # whether to ask for confirmation before closing muc if (app.config.get('confirm_close_muc') or self.room_jid in includes)\ and self.is_connected and self.room_jid not in excludes: return False return True def allow_shutdown(self, method, on_yes, on_no, on_minimize): if self.minimizable(): on_minimize(self) return if method == self.parent_win.CLOSE_ESC: iter_ = self.list_treeview.get_selection().get_selected()[1] if iter_: self.list_treeview.get_selection().unselect_all() on_no(self) return includes = app.config.get('confirm_close_muc_rooms').split(' ') excludes = app.config.get('noconfirm_close_muc_rooms').split(' ') # whether to ask for confirmation before closing muc if (app.config.get('confirm_close_muc') or self.room_jid in includes)\ and self.is_connected and self.room_jid \ not in excludes: def on_ok(clicked): if clicked: # user does not want to be asked again app.config.set('confirm_close_muc', False) on_yes(self) def on_cancel(clicked): if clicked: # user does not want to be asked again app.config.set('confirm_close_muc', False) on_no(self) pritext = _('Are you sure you want to leave group chat "%s"?')\ % self.name sectext = _('If you close this window, you will be disconnected ' 'from this group chat.') ConfirmationDialogCheck(pritext, sectext, _('_Do not ask me again'), on_response_ok=on_ok, on_response_cancel=on_cancel, transient_for=self.parent_win.window) return on_yes(self) def set_control_active(self, state): self.conv_textview.allow_focus_out_line = True self.attention_flag = False ChatControlBase.set_control_active(self, state) if not state: # add the focus-out line to the tab we are leaving self.check_and_possibly_add_focus_out_line() # Sending active to undo unread state self.parent_win.redraw_tab(self, 'active') def get_specific_unread(self): # returns the number of the number of unread msgs # for room_jid & number of unread private msgs with each contact # that we have nb = 0 for nick in app.contacts.get_nick_list(self.account, self.room_jid): fjid = self.room_jid + '/' + nick nb += len(app.events.get_events(self.account, fjid)) # gc can only have messages as event return nb def _on_change_subject_menuitem_activate(self, widget): def on_ok(subject): # Note, we don't update self.subject since we don't know whether it # will work yet con = app.connections[self.account] con.get_module('MUC').set_subject(self.room_jid, subject) InputTextDialog(_('Changing Subject'), _('Please specify the new subject:'), input_str=self.subject, ok_handler=on_ok, transient_for=self.parent_win.window) def _on_drag_data_received(self, widget, context, x, y, selection, target_type, timestamp): if not selection.get_data(): return # get contact info contact = contacts.Contact(jid=self.room_jid, account=self.account) if target_type == self.TARGET_TYPE_URI_LIST: # file drag and drop (handled in chat_control_base) self.drag_data_file_transfer(contact, selection, self) else: # Invite contact to groupchat treeview = app.interface.roster.tree model = treeview.get_model() data = selection.get_data() path = treeview.get_selection().get_selected_rows()[1][0] iter_ = model.get_iter(path) type_ = model[iter_][2] if type_ != 'contact': # source is not a contact return contact_jid = data con = app.connections[self.account] con.get_module('MUC').invite(self.room_jid, contact_jid) self.print_conversation(_('%(jid)s has been invited in this room') % {'jid': contact_jid}, graphics=False) def _on_message_textview_key_press_event(self, widget, event): res = ChatControlBase._on_message_textview_key_press_event(self, widget, event) if res: return True if event.keyval == Gdk.KEY_Tab: # TAB message_buffer = widget.get_buffer() start_iter, end_iter = message_buffer.get_bounds() cursor_position = message_buffer.get_insert() end_iter = message_buffer.get_iter_at_mark(cursor_position) text = message_buffer.get_text(start_iter, end_iter, False) splitted_text = text.split() # nick completion # check if tab is pressed with empty message if splitted_text: # if there are any words begin = splitted_text[-1] # last word we typed else: begin = '' gc_refer_to_nick_char = app.config.get('gc_refer_to_nick_char') with_refer_to_nick_char = False after_nick_len = 1 # the space that is printed after we type [Tab] # first part of this if : works fine even if refer_to_nick_char if gc_refer_to_nick_char and text.endswith( gc_refer_to_nick_char + ' '): with_refer_to_nick_char = True after_nick_len = len(gc_refer_to_nick_char + ' ') if self.nick_hits and self.last_key_tabs and \ text[:-after_nick_len].endswith(self.nick_hits[0]): # we should cycle # Previous nick in list may had a space inside, so we check text # and not splitted_text and store it into 'begin' var self.nick_hits.append(self.nick_hits[0]) begin = self.nick_hits.pop(0) else: self.nick_hits = [] # clear the hit list list_nick = app.contacts.get_nick_list(self.account, self.room_jid) list_nick.sort(key=str.lower) # case-insensitive sort if begin == '': # empty message, show lasts nicks that highlighted us first for nick in self.attention_list: if nick in list_nick: list_nick.remove(nick) list_nick.insert(0, nick) if self.nick in list_nick: list_nick.remove(self.nick) # Skip self for nick in list_nick: fjid = self.room_jid + '/' + nick if nick.lower().startswith(begin.lower()) and not \ helpers.jid_is_blocked(self.account, fjid): # the word is the beginning of a nick self.nick_hits.append(nick) if self.nick_hits: if len(splitted_text) < 2 or with_refer_to_nick_char: # This is the 1st word of the line or no word or we are cycling # at the beginning, possibly with a space in one nick add = gc_refer_to_nick_char + ' ' else: add = ' ' start_iter = end_iter.copy() if self.last_key_tabs and with_refer_to_nick_char or (text and \ text[-1] == ' '): # have to accommodate for the added space from last # completion # gc_refer_to_nick_char may be more than one char! start_iter.backward_chars(len(begin) + len(add)) elif self.last_key_tabs and not app.config.get( 'shell_like_completion'): # have to accommodate for the added space from last # completion start_iter.backward_chars(len(begin) + \ len(gc_refer_to_nick_char)) else: start_iter.backward_chars(len(begin)) message_buffer.delete(start_iter, end_iter) # get a shell-like completion # if there's more than one nick for this completion, complete # only the part that all these nicks have in common if app.config.get('shell_like_completion') and \ len(self.nick_hits) > 1: end = False completion = '' add = "" # if nick is not complete, don't add anything while not end and len(completion) < len(self.nick_hits[0]): completion = self.nick_hits[0][:len(completion)+1] for nick in self.nick_hits: if completion.lower() not in nick.lower(): end = True completion = completion[:-1] break # if the current nick matches a COMPLETE existing nick, # and if the user tab TWICE, complete that nick (with the # "add") if self.last_key_tabs: for nick in self.nick_hits: if nick == completion: # The user seems to want this nick, so # complete it as if it were the only nick # available add = gc_refer_to_nick_char + ' ' else: completion = self.nick_hits[0] message_buffer.insert_at_cursor(completion + add) self.last_key_tabs = True return True self.last_key_tabs = False def on_list_treeview_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: selection = widget.get_selection() iter_ = selection.get_selected()[1] if iter_: widget.get_selection().unselect_all() return True def on_list_treeview_row_expanded(self, widget, iter_, path): """ When a row is expanded: change the icon of the arrow """ model = widget.get_model() image = gtkgui_helpers.get_image_from_icon_name( 'opened', self.scale_factor) model[iter_][Column.IMG] = image def on_list_treeview_row_collapsed(self, widget, iter_, path): """ When a row is collapsed: change the icon of the arrow """ model = widget.get_model() image = gtkgui_helpers.get_image_from_icon_name( 'closed', self.scale_factor) model[iter_][Column.IMG] = image def kick(self, widget, nick): """ Kick a user """ def on_ok(reason): con = app.connections[self.account] con.get_module('MUC').set_role(self.room_jid, nick, 'none', reason) # ask for reason InputDialog(_('Kicking %s') % nick, _('You may specify a reason below:'), ok_handler=on_ok, transient_for=self.parent_win.window) def mk_menu(self, event, iter_): """ Make contact's popup menu """ nick = self.model[iter_][Column.NICK] c = app.contacts.get_gc_contact(self.account, self.room_jid, nick) fjid = self.room_jid + '/' + nick jid = c.jid target_affiliation = c.affiliation target_role = c.role # looking for user's affiliation and role user_nick = self.nick user_affiliation = app.contacts.get_gc_contact(self.account, self.room_jid, user_nick).affiliation user_role = self.get_role(user_nick) # making menu from gtk builder xml = gtkgui_helpers.get_gtk_builder('gc_occupants_menu.ui') # these conditions were taken from JEP 0045 item = xml.get_object('kick_menuitem') if user_role != 'moderator' or \ (user_affiliation == 'admin' and target_affiliation == 'owner') or \ (user_affiliation == 'member' and target_affiliation in ('admin', 'owner')) or (user_affiliation == 'none' and target_affiliation != \ 'none'): item.set_sensitive(False) id_ = item.connect('activate', self.kick, nick) self.handlers[id_] = item item = xml.get_object('voice_checkmenuitem') item.set_active(target_role != 'visitor') if user_role != 'moderator' or \ user_affiliation == 'none' or \ (user_affiliation == 'member' and target_affiliation != 'none') or \ target_affiliation in ('admin', 'owner'): item.set_sensitive(False) id_ = item.connect('activate', self.on_voice_checkmenuitem_activate, nick) self.handlers[id_] = item item = xml.get_object('moderator_checkmenuitem') item.set_active(target_role == 'moderator') if not user_affiliation in ('admin', 'owner') or \ target_affiliation in ('admin', 'owner'): item.set_sensitive(False) id_ = item.connect('activate', self.on_moderator_checkmenuitem_activate, nick) self.handlers[id_] = item item = xml.get_object('ban_menuitem') if not user_affiliation in ('admin', 'owner') or \ (target_affiliation in ('admin', 'owner') and\ user_affiliation != 'owner'): item.set_sensitive(False) id_ = item.connect('activate', self.ban, jid) self.handlers[id_] = item item = xml.get_object('member_checkmenuitem') item.set_active(target_affiliation != 'none') if not user_affiliation in ('admin', 'owner') or \ (user_affiliation != 'owner' and target_affiliation in ('admin', 'owner')): item.set_sensitive(False) id_ = item.connect('activate', self.on_member_checkmenuitem_activate, jid) self.handlers[id_] = item item = xml.get_object('admin_checkmenuitem') item.set_active(target_affiliation in ('admin', 'owner')) if not user_affiliation == 'owner': item.set_sensitive(False) id_ = item.connect('activate', self.on_admin_checkmenuitem_activate, jid) self.handlers[id_] = item item = xml.get_object('owner_checkmenuitem') item.set_active(target_affiliation == 'owner') if not user_affiliation == 'owner': item.set_sensitive(False) id_ = item.connect('activate', self.on_owner_checkmenuitem_activate, jid) self.handlers[id_] = item item = xml.get_object('invite_menuitem') if jid and c.name != self.nick: bookmarked = False contact = app.contacts.get_contact(self.account, jid, c.resource) if contact and contact.supports(nbxmpp.NS_CONFERENCE): bookmarked = True gui_menu_builder.build_invite_submenu(item, ((c, self.account),), ignore_rooms=[self.room_jid], show_bookmarked=bookmarked) else: item.set_sensitive(False) item = xml.get_object('information_menuitem') id_ = item.connect('activate', self.on_info, nick) self.handlers[id_] = item item = xml.get_object('history_menuitem') id_ = item.connect('activate', self.on_history, nick) self.handlers[id_] = item item = xml.get_object('add_to_roster_menuitem') our_jid = app.get_jid_from_account(self.account) if not jid or jid == our_jid or not app.connections[self.account].\ roster_supported: item.set_sensitive(False) else: id_ = item.connect('activate', self.on_add_to_roster, jid) self.handlers[id_] = item item = xml.get_object('execute_command_menuitem') id_ = item.connect('activate', self._on_execute_command_occupant, nick) self.handlers[id_] = item item = xml.get_object('block_menuitem') item2 = xml.get_object('unblock_menuitem') if not app.connections[self.account].get_module('PrivacyLists').supported: item2.set_no_show_all(True) item.set_no_show_all(True) item.hide() item2.hide() elif helpers.jid_is_blocked(self.account, fjid): item.set_no_show_all(True) item.hide() id_ = item2.connect('activate', self.on_unblock, nick) self.handlers[id_] = item2 else: id_ = item.connect('activate', self.on_block, nick) self.handlers[id_] = item item2.set_no_show_all(True) item2.hide() item = xml.get_object('send_private_message_menuitem') id_ = item.connect('activate', self.on_send_pm, self.model, iter_) self.handlers[id_] = item item = xml.get_object('send_file_menuitem') if not c.resource: item.set_sensitive(False) else: item.set_sensitive(False) # ToDo: integrate HTTP File Upload id_ = item.connect('activate', self._on_send_file_jingle, c) self.handlers[id_] = item # show the popup now! menu = xml.get_object('gc_occupants_menu') menu.show_all() menu.attach_to_widget(app.interface.roster.window, None) menu.popup(None, None, None, None, event.button, event.time) def _start_private_message(self, nick): gc_c = app.contacts.get_gc_contact(self.account, self.room_jid, nick) nick_jid = gc_c.get_full_jid() ctrl = app.interface.msg_win_mgr.get_control(nick_jid, self.account) if not ctrl: ctrl = app.interface.new_private_chat(gc_c, self.account) if ctrl: ctrl.parent_win.set_active_tab(ctrl) return ctrl def _on_execute_command_occupant(self, widget, nick): jid = self.room_jid + '/' + nick adhoc_commands.CommandWindow(self.account, jid) def on_row_activated(self, widget, path): """ When an iter is activated (double click or single click if gnome is set this way) """ if path.get_depth() == 1: # It's a group if widget.row_expanded(path): widget.collapse_row(path) else: widget.expand_row(path, False) else: # We want to send a private message nick = self.model[path][Column.NICK] self._start_private_message(nick) def on_list_treeview_row_activated(self, widget, path, col=0): """ When an iter is double clicked: open the chat window """ if not app.single_click: self.on_row_activated(widget, path) def on_list_treeview_button_press_event(self, widget, event): """ Popup user's group's or agent menu """ try: pos = widget.get_path_at_pos(int(event.x), int(event.y)) path, x = pos[0], pos[2] except TypeError: widget.get_selection().unselect_all() return if event.button == 3: # right click widget.get_selection().select_path(path) iter_ = self.model.get_iter(path) if path.get_depth() == 2: self.mk_menu(event, iter_) return True if event.button == 2: # middle click widget.get_selection().select_path(path) iter_ = self.model.get_iter(path) if path.get_depth() == 2: nick = self.model[iter_][Column.NICK] self._start_private_message(nick) return True if event.button == 1: # left click if app.single_click and not event.get_state() & Gdk.ModifierType.SHIFT_MASK: self.on_row_activated(widget, path) return True iter_ = self.model.get_iter(path) nick = self.model[iter_][Column.NICK] if not nick in app.contacts.get_nick_list( self.account, self.room_jid): # it's a group if x < 27: if widget.row_expanded(path): widget.collapse_row(path) else: widget.expand_row(path, False) elif event.get_state() & Gdk.ModifierType.SHIFT_MASK: self.append_nick_in_msg_textview(self.msg_textview, nick) self.msg_textview.grab_focus() return True def append_nick_in_msg_textview(self, widget, nick): self.msg_textview.remove_placeholder() message_buffer = self.msg_textview.get_buffer() start_iter, end_iter = message_buffer.get_bounds() cursor_position = message_buffer.get_insert() end_iter = message_buffer.get_iter_at_mark(cursor_position) text = message_buffer.get_text(start_iter, end_iter, False) start = '' if text: # Cursor is not at first position if not text[-1] in (' ', '\n', '\t'): start = ' ' add = ' ' else: gc_refer_to_nick_char = app.config.get('gc_refer_to_nick_char') add = gc_refer_to_nick_char + ' ' message_buffer.insert_at_cursor(start + nick + add) def grant_voice(self, widget, nick): """ Grant voice privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_role(self.room_jid, nick, 'participant') def revoke_voice(self, widget, nick): """ Revoke voice privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_role(self.room_jid, nick, 'visitor') def grant_moderator(self, widget, nick): """ Grant moderator privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_role(self.room_jid, nick, 'moderator') def revoke_moderator(self, widget, nick): """ Revoke moderator privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_role(self.room_jid, nick, 'participant') def ban(self, widget, jid): """ Ban a user """ def on_ok(reason): con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, {jid: {'affiliation': 'outcast', 'reason': reason}}) # to ban we know the real jid. so jid is not fakejid nick = app.get_nick_from_jid(jid) # ask for reason InputDialog(_('Banning %s') % nick, _('You may specify a reason below:'), ok_handler=on_ok, transient_for=self.parent_win.window) def grant_membership(self, widget, jid): """ Grant membership privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, {jid: {'affiliation': 'member'}}) def revoke_membership(self, widget, jid): """ Revoke membership privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, {jid: {'affiliation': 'none'}}) def grant_admin(self, widget, jid): """ Grant administrative privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, {jid: {'affiliation': 'admin'}}) def revoke_admin(self, widget, jid): """ Revoke administrative privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, {jid: {'affiliation': 'member'}}) def grant_owner(self, widget, jid): """ Grant owner privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, {jid: {'affiliation': 'owner'}}) def revoke_owner(self, widget, jid): """ Revoke owner privilege to a user """ con = app.connections[self.account] con.get_module('MUC').set_affiliation( self.room_jid, {jid: {'affiliation': 'admin'}}) def on_info(self, widget, nick): """ Call vcard_information_window class to display user's information """ gc_contact = app.contacts.get_gc_contact(self.account, self.room_jid, nick) contact = gc_contact.as_contact() if contact.jid in app.interface.instances[self.account]['infos']: app.interface.instances[self.account]['infos'][contact.jid].\ window.present() else: app.interface.instances[self.account]['infos'][contact.jid] = \ vcard.VcardWindow(contact, self.account, gc_contact) def on_history(self, widget, nick): jid = app.construct_fjid(self.room_jid, nick) self._on_history_menuitem_activate(widget=widget, jid=jid) def on_add_to_roster(self, widget, jid): AddNewContactWindow(self.account, jid) def on_block(self, widget, nick): fjid = self.room_jid + '/' + nick con = app.connections[self.account] con.get_module('PrivacyLists').block_gc_contact(fjid) self.draw_contact(nick) def on_unblock(self, widget, nick): fjid = self.room_jid + '/' + nick con = app.connections[self.account] con.get_module('PrivacyLists').unblock_gc_contact(fjid) self.draw_contact(nick) def on_voice_checkmenuitem_activate(self, widget, nick): if widget.get_active(): self.grant_voice(widget, nick) else: self.revoke_voice(widget, nick) def on_moderator_checkmenuitem_activate(self, widget, nick): if widget.get_active(): self.grant_moderator(widget, nick) else: self.revoke_moderator(widget, nick) def on_member_checkmenuitem_activate(self, widget, jid): if widget.get_active(): self.grant_membership(widget, jid) else: self.revoke_membership(widget, jid) def on_admin_checkmenuitem_activate(self, widget, jid): if widget.get_active(): self.grant_admin(widget, jid) else: self.revoke_admin(widget, jid) def on_owner_checkmenuitem_activate(self, widget, jid): if widget.get_active(): self.grant_owner(widget, jid) else: self.revoke_owner(widget, jid) class SubjectPopover(Gtk.Popover): def __init__(self): Gtk.Popover.__init__(self) self.set_name('SubjectPopover') scrolledwindow = Gtk.ScrolledWindow() scrolledwindow.set_max_content_height(250) scrolledwindow.set_propagate_natural_height(True) scrolledwindow.set_propagate_natural_width(True) scrolledwindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.label = Gtk.Label() self.label.set_line_wrap(True) self.label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) self.label.set_max_width_chars(80) self.label.connect('activate-link', self._on_activate_link) scrolledwindow.add(self.label) box = Gtk.Box() box.add(scrolledwindow) box.show_all() self.add(box) self.connect_after('show', self._after_show) def set_text(self, text): self.label.set_markup(text) def _after_show(self, *args): # Gtk Bug: If we set selectable True, on show # everything inside the Label is selected. # So we switch after show to False and again to True self.label.set_selectable(False) self.label.set_selectable(True) @staticmethod def _on_activate_link(_label, uri): # We have to use this, because the default GTK handler # is not cross-platform compatible launch_browser_mailer(None, uri) return Gdk.EVENT_STOP gajim-gajim-1.1.3/gajim/groups.py000066400000000000000000000050651345766322700166750ustar00rootroot00000000000000# Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2006 Tomasz Melcer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . '''Window to create new post for discussion groups service.''' import uuid from gajim.common import app from nbxmpp import Node from gajim import gtkgui_helpers class GroupsPostWindow: def __init__(self, account, servicejid, groupid): """ Open new 'create post' window to create message for groupid on servicejid service """ assert isinstance(servicejid, str) assert isinstance(groupid, str) self.account = account self.servicejid = servicejid self.groupid = groupid self.xml = gtkgui_helpers.get_gtk_builder('groups_post_window.ui') self.window = self.xml.get_object('groups_post_window') for name in ('from_entry', 'subject_entry', 'contents_textview'): self.__dict__[name] = self.xml.get_object(name) self.xml.connect_signals(self) self.window.show_all() def on_cancel_button_clicked(self, w): """ Close window """ self.window.destroy() def on_send_button_clicked(self, w): """ Gather info from widgets and send it as a message """ # constructing item to publish... that's atom:entry element item = Node('entry', {'xmlns':'http://www.w3.org/2005/Atom'}) author = item.addChild('author') author.addChild('name', {}, [self.from_entry.get_text()]) item.addChild('generator', {}, ['Gajim']) item.addChild('title', {}, [self.subject_entry.get_text()]) buf = self.contents_textview.get_buffer() item.addChild('content', {}, [buf.get_text(buf.get_start_iter(), buf.get_end_iter(), True)]) # publish it to node con = app.connections[self.account] con.get_module('PubSub').send_pb_publish( self.servicejid, self.groupid, item, str(uuid.uuid4())) # close the window self.window.destroy() gajim-gajim-1.1.3/gajim/gtk/000077500000000000000000000000001345766322700155635ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/gtk/__init__.py000066400000000000000000000034231345766322700176760ustar00rootroot00000000000000# Copyright (C) 2003-2005 Vincent Hanquez # Copyright (C) 2005 Alex Podaras # Stéphan Kochen # Alex Mauer # Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Dimitur Kirov # Travis Shirk # Copyright (C) 2005-2008 Nikos Kouremenos # Copyright (C) 2006 Junglecow J # Copyright (C) 2006-2007 Travis Shirk # Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 James Newton # Lukas Petrovicky # Copyright (C) 2007-2008 Brendan Taylor # Julien Pivotto # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . gajim-gajim-1.1.3/gajim/gtk/about.py000066400000000000000000000065321345766322700172550ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import nbxmpp from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GObject from gajim.common import app from gajim.common.helpers import launch_browser_mailer from gajim.common.i18n import _ from gajim.common.const import DEVS_CURRENT from gajim.common.const import DEVS_PAST from gajim.common.const import ARTISTS from gajim.common.const import THANKS class AboutDialog(Gtk.AboutDialog): def __init__(self): Gtk.AboutDialog.__init__(self) self.set_transient_for(app.interface.roster.window) self.set_name('Gajim') self.set_version(app.version) self.set_copyright('Copyright © 2003-2019 Gajim Team') self.set_license_type(Gtk.License.GPL_3_0_ONLY) self.set_website('https://gajim.org/') gtk_ver = '%i.%i.%i' % ( Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) gobject_ver = '.'.join(map(str, GObject.pygobject_version)) comments = [] comments.append(_('A GTK+ XMPP client')) comments.append(_('GTK+ Version: %s' % gtk_ver)) comments.append(_('PyGObject Version: %s') % gobject_ver) comments.append(_('python-nbxmpp Version: %s') % nbxmpp.__version__) self.set_comments("\n".join(comments)) self.add_credit_section(_('Current Developers'), DEVS_CURRENT) self.add_credit_section(_('Past Developers'), DEVS_PAST) self.add_credit_section(_('Artists'), ARTISTS) thanks = list(THANKS) thanks.append('') thanks.append(_('Last but not least')) thanks.append(_('we would like to thank all the package maintainers.')) self.add_credit_section(_('Thanks'), thanks) self.set_translator_credits(_('translator-credits')) self.set_logo_icon_name('org.gajim.Gajim') self.connect( 'response', lambda dialog, *args: Gtk.AboutDialog.do_close(dialog)) self.show() self.connect('activate-link', self._on_activate_link) # See https://gitlab.gnome.org/GNOME/gtk/issues/1561 self._connect_link_handler(self) @staticmethod def _on_activate_link(_label, uri): # We have to use this, because the default GTK handler # is not cross-platform compatible launch_browser_mailer(None, uri) return Gdk.EVENT_STOP def _connect_link_handler(self, parent): def _find_child(parent_): if not hasattr(parent_, 'get_children'): return for child in parent_.get_children(): if isinstance(child, Gtk.Label): if 'href' in child.get_label(): child.connect('activate-link', self._on_activate_link) _find_child(child) _find_child(parent) gajim-gajim-1.1.3/gajim/gtk/account_wizard.py000066400000000000000000000625151345766322700211620ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gajim.common import app from gajim.common import ged from gajim.common import configpaths from gajim.common import helpers from gajim.common import connection from gajim.common.i18n import _ from gajim.common.modules import dataforms from gajim import gtkgui_helpers from gajim import dataforms_widget from gajim import gui_menu_builder from gajim.config import ManageProxiesWindow from gajim.config import FakeDataForm from gajim.gtk.util import get_builder from gajim.gtk.dialogs import ErrorDialog class AccountCreationWizard: def __init__(self): self.xml = get_builder('account_creation_wizard_window.ui') self.window = self.xml.get_object('account_creation_wizard_window') active_window = app.app.get_active_window() self.window.set_transient_for(active_window) # Connect events from comboboxtext_entry server_comboboxtext = self.xml.get_object('server_comboboxtext') entry = self.xml.get_object('server_comboboxtext_entry') entry.connect('key_press_event', self.on_entry_key_press_event, server_comboboxtext) server_comboboxtext1 = self.xml.get_object('server_comboboxtext1') self.update_proxy_list() # parse servers.json server_file_path = os.path.join( configpaths.get('DATA'), 'other', 'servers.json') servers = helpers.load_json(server_file_path, 'servers', []) servers_model = self.xml.get_object('server_liststore') for server in servers: servers_model.append((server,)) server_comboboxtext.set_model(servers_model) server_comboboxtext1.set_model(servers_model) # Generic widgets self.notebook = self.xml.get_object('notebook') self.cancel_button = self.xml.get_object('cancel_button') self.back_button = self.xml.get_object('back_button') self.forward_button = self.xml.get_object('forward_button') self.finish_button = self.xml.get_object('finish_button') self.advanced_button = self.xml.get_object('advanced_button') self.finish_label = self.xml.get_object('finish_label') self.go_online_checkbutton = self.xml.get_object( 'go_online_checkbutton') self.show_vcard_checkbutton = self.xml.get_object( 'show_vcard_checkbutton') self.progressbar = self.xml.get_object('progressbar') # some vars self.update_progressbar_timeout_id = None self.notebook.set_current_page(0) self.xml.connect_signals(self) self.window.show_all() app.ged.register_event_handler( 'new-account-connected', ged.GUI1, self._nec_new_acc_connected) app.ged.register_event_handler( 'new-account-not-connected', ged.GUI1, self._nec_new_acc_not_connected) app.ged.register_event_handler( 'account-created', ged.GUI1, self._nec_acc_is_ok) app.ged.register_event_handler( 'account-not-created', ged.GUI1, self._nec_acc_is_not_ok) def on_wizard_window_destroy(self, widget): page = self.notebook.get_current_page() if page in (4, 5) and self.account in app.connections: # connection instance is saved in app.connections and we canceled # the addition of the account del app.connections[self.account] if self.account in app.config.get_per('accounts'): app.config.del_per('accounts', self.account) app.ged.remove_event_handler( 'new-account-connected', ged.GUI1, self._nec_new_acc_connected) app.ged.remove_event_handler( 'new-account-not-connected', ged.GUI1, self._nec_new_acc_not_connected) app.ged.remove_event_handler( 'account-created', ged.GUI1, self._nec_acc_is_ok) app.ged.remove_event_handler( 'account-not-created', ged.GUI1, self._nec_acc_is_not_ok) del app.interface.instances['account_creation_wizard'] def on_save_password_checkbutton_toggled(self, widget): self.xml.get_object('password_entry').grab_focus() def on_cancel_button_clicked(self, widget): self.window.destroy() def on_back_button_clicked(self, widget): cur_page = self.notebook.get_current_page() self.forward_button.set_sensitive(True) if cur_page in (1, 2): self.notebook.set_current_page(0) self.back_button.set_sensitive(False) elif cur_page == 3: self.xml.get_object('form_vbox').remove(self.data_form_widget) self.notebook.set_current_page(2) # show server page elif cur_page == 4: if self.account in app.connections: del app.connections[self.account] if self.account in app.config.get_per('accounts'): app.config.del_per('accounts', self.account) self.notebook.set_current_page(2) self.xml.get_object('form_vbox').remove(self.data_form_widget) elif cur_page == 6: # finish page self.forward_button.show() if self.modify: self.notebook.set_current_page(1) # Go to parameters page else: self.notebook.set_current_page(2) # Go to server page def on_anonymous_checkbutton1_toggled(self, widget): active = widget.get_active() self.xml.get_object('username_entry').set_sensitive(not active) self.xml.get_object('password_entry').set_sensitive(not active) self.xml.get_object('save_password_checkbutton').set_sensitive( not active) def show_finish_page(self): self.cancel_button.hide() self.back_button.hide() self.forward_button.hide() if self.modify: finish_text = '%s\n\n%s' % ( _('Account has been added successfully'), _('You can set advanced account options by pressing the ' 'Advanced button, or later by choosing the Accounts menu item ' 'under the Edit menu from the main window.')) else: finish_text = '%s\n\n%s' % ( _('Your new account has been created successfully'), _('You can set advanced account options by pressing the ' 'Advanced button, or later by choosing the Accounts menu item ' 'under the Edit menu from the main window.')) self.finish_label.set_markup(finish_text) self.finish_button.show() self.finish_button.set_property('has-default', True) self.advanced_button.show() self.go_online_checkbutton.show() img = self.xml.get_object('finish_image') if self.modify: img.set_from_icon_name(Gtk.STOCK_APPLY, Gtk.IconSize.DIALOG) else: path_to_file = gtkgui_helpers.get_icon_path('org.gajim.Gajim', 48) img.set_from_file(path_to_file) self.show_vcard_checkbutton.set_active(not self.modify) self.notebook.set_current_page(6) # show finish page def on_forward_button_clicked(self, widget): cur_page = self.notebook.get_current_page() if cur_page == 0: widget = self.xml.get_object('use_existing_account_radiobutton') if widget.get_active(): self.modify = True self.notebook.set_current_page(1) else: self.modify = False self.notebook.set_current_page(2) self.back_button.set_sensitive(True) return elif cur_page == 1: # We are adding an existing account anonymous = self.xml.get_object('anonymous_checkbutton1').\ get_active() username = self.xml.get_object('username_entry').get_text().strip() if not username and not anonymous: pritext = _('Invalid username') sectext = _( 'You must provide a username to configure this account.') ErrorDialog(pritext, sectext) return server = self.xml.get_object('server_comboboxtext_entry').\ get_text().strip() savepass = self.xml.get_object('save_password_checkbutton').\ get_active() password = self.xml.get_object('password_entry').get_text() if anonymous: jid = '' else: jid = username + '@' jid += server # check if jid is conform to RFC and stringprep it try: jid = helpers.parse_jid(jid) except helpers.InvalidFormat as s: pritext = _('Invalid JID') ErrorDialog(pritext, str(s)) return self.account = server i = 1 while self.account in app.config.get_per('accounts'): self.account = server + str(i) i += 1 username, server = app.get_name_and_server_from_jid(jid) if self.xml.get_object('anonymous_checkbutton1').get_active(): self.save_account('', server, False, '', anonymous=True) else: self.save_account(username, server, savepass, password) self.show_finish_page() elif cur_page == 2: # We are creating a new account server = self.xml.get_object('server_comboboxtext_entry1').\ get_text() if not server: ErrorDialog( _('Invalid server'), _('Please provide a server on which you want to register.')) return self.account = server i = 1 while self.account in app.config.get_per('accounts'): self.account = server + str(i) i += 1 config = self.get_config('', server, '', '') # Get advanced options proxies_combobox = self.xml.get_object('proxies_combobox') active = proxies_combobox.get_active() proxy = proxies_combobox.get_model()[active][0] if proxy == _('None'): proxy = '' config['proxy'] = proxy config['use_custom_host'] = self.xml.get_object( 'custom_host_port_checkbutton').get_active() custom_port = self.xml.get_object('custom_port_entry').get_text() try: custom_port = int(custom_port) except Exception: ErrorDialog( _('Invalid entry'), _('Custom port must be a port number.')) return config['custom_port'] = custom_port config['custom_host'] = self.xml.get_object( 'custom_host_entry').get_text() if self.xml.get_object('anonymous_checkbutton2').get_active(): self.modify = True self.save_account('', server, False, '', anonymous=True) self.show_finish_page() else: self.notebook.set_current_page(5) # show creating page self.back_button.hide() self.forward_button.hide() self.update_progressbar_timeout_id = GLib.timeout_add( 100, self.update_progressbar) # Get form from serveur con = connection.Connection(self.account) app.plugin_manager.register_modules_for_account(con) app.connections[self.account] = con con.new_account(self.account, config) elif cur_page == 3: checked = self.xml.get_object('ssl_checkbutton').get_active() if checked: hostname = app.connections[self.account].new_account_info[ 'hostname'] # Check if cert is already in file certs = '' my_ca_certs = configpaths.get('MY_CACERTS') if os.path.isfile(my_ca_certs): with open(my_ca_certs) as f: certs = f.read() if self.ssl_cert in certs: ErrorDialog( _('Certificate Already in File'), _('This certificate is already in file %s, so it\'s ' 'not added again.') % my_ca_certs) else: with open(my_ca_certs, 'a') as f: f.write(hostname + '\n') f.write(self.ssl_cert + '\n\n') app.connections[self.account].new_account_info[ 'ssl_fingerprint_sha1'] = self.ssl_fingerprint_sha1 app.connections[self.account].new_account_info[ 'ssl_fingerprint_sha256'] = self.ssl_fingerprint_sha256 self.notebook.set_current_page(4) # show fom page elif cur_page == 4: if self.is_form: form = self.data_form_widget.data_form else: form = self.data_form_widget.get_infos() app.connections[self.account].send_new_account_infos( form, self.is_form) self.xml.get_object('form_vbox').remove(self.data_form_widget) self.xml.get_object('progressbar_label').set_markup( 'Account is being created\n\nPlease wait…') self.notebook.set_current_page(5) # show creating page self.back_button.hide() self.forward_button.hide() self.update_progressbar_timeout_id = GLib.timeout_add( 100, self.update_progressbar) def update_proxy_list(self): proxies_combobox = self.xml.get_object('proxies_combobox') model = Gtk.ListStore(str) proxies_combobox.set_model(model) proxies = app.config.get_per('proxies') proxies.insert(0, _('None')) for proxy in proxies: model.append([proxy]) proxies_combobox.set_active(0) def on_manage_proxies_button_clicked(self, widget): if 'manage_proxies' in app.interface.instances: app.interface.instances['manage_proxies'].window.present() else: app.interface.instances['manage_proxies'] = \ ManageProxiesWindow() def on_custom_host_port_checkbutton_toggled(self, widget): self.xml.get_object('custom_host_hbox').set_sensitive( widget.get_active()) def update_progressbar(self): self.progressbar.pulse() return True # loop forever def _nec_new_acc_connected(self, obj): """ Connection to server succeded, present the form to the user """ # We receive events from all accounts from GED if obj.conn.name != self.account: return if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) self.back_button.show() self.forward_button.show() self.is_form = obj.is_form empty_config = True if obj.is_form: dataform = dataforms.extend_form(node=obj.config) self.data_form_widget = dataforms_widget.DataFormWidget() self.data_form_widget.selectable = True self.data_form_widget.set_data_form(dataform) empty_config = False else: self.data_form_widget = FakeDataForm(obj.config, selectable=True) for field in obj.config: if field in ('key', 'instructions', 'x', 'registered'): continue empty_config = False break self.data_form_widget.show_all() self.xml.get_object('form_vbox').pack_start( self.data_form_widget, True, True, 0) if empty_config: self.forward_button.set_sensitive(False) self.notebook.set_current_page(4) # show form page return self.ssl_fingerprint_sha1 = obj.ssl_fingerprint_sha1 self.ssl_fingerprint_sha256 = obj.ssl_fingerprint_sha256 self.ssl_cert = obj.ssl_cert if obj.ssl_msg: # An SSL warning occured, show it hostname = app.connections[self.account].new_account_info[ 'hostname'] self.xml.get_object('ssl_label').set_markup(_( 'Security Warning' '\n\nThe authenticity of the %(hostname)s SSL certificate could' ' be invalid.\nSSL Error: %(error)s\n' 'Do you still want to connect to this server?') % { 'hostname': hostname, 'error': obj.ssl_msg}) if obj.errnum in (18, 27): text = _( 'Add this certificate to the list of trusted ' 'certificates.\nSHA-1 fingerprint of the certificate:\n' '%(sha1)s\nSHA-256 fingerprint of the certificate:\n' '%(sha256)s') % {'sha1': obj.ssl_fingerprint_sha1, 'sha256': obj.ssl_fingerprint_sha256} self.xml.get_object('ssl_checkbutton').set_label(text) else: self.xml.get_object('ssl_checkbutton').set_no_show_all(True) self.xml.get_object('ssl_checkbutton').hide() self.notebook.set_current_page(3) # show SSL page else: self.notebook.set_current_page(4) # show form page def _nec_new_acc_not_connected(self, obj): """ Account creation failed: connection to server failed """ # We receive events from all accounts from GED if obj.conn.name != self.account: return if self.account not in app.connections: return if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) del app.connections[self.account] if self.account in app.config.get_per('accounts'): app.config.del_per('accounts', self.account) self.back_button.show() self.cancel_button.show() self.go_online_checkbutton.hide() self.show_vcard_checkbutton.hide() img = self.xml.get_object('finish_image') img.set_from_icon_name("dialog-error", Gtk.IconSize.DIALOG) finish_text = '%s\n\n%s' % ( _('An error occurred during account creation'), obj.reason) self.finish_label.set_markup(finish_text) self.notebook.set_current_page(6) # show finish page def _nec_acc_is_ok(self, obj): """ Account creation succeeded """ # We receive events from all accounts from GED if obj.conn.name != self.account: return self.create_vars(obj.account_info) self.show_finish_page() if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) def _nec_acc_is_not_ok(self, obj): """ Account creation failed """ # We receive events from all accounts from GED if obj.conn.name != self.account: return self.back_button.show() self.cancel_button.show() self.go_online_checkbutton.hide() self.show_vcard_checkbutton.hide() del app.connections[self.account] if self.account in app.config.get_per('accounts'): app.config.del_per('accounts', self.account) img = self.xml.get_object('finish_image') img.set_from_icon_name("dialog-error", Gtk.IconSize.DIALOG) finish_text = '%s\n\n%s' % (_( 'An error occurred during account creation'), obj.reason) self.finish_label.set_markup(finish_text) self.notebook.set_current_page(6) # show finish page if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) def on_advanced_button_clicked(self, widget): from gajim.gtk.accounts import AccountsWindow window = app.get_app_window(AccountsWindow) if window is None: window = AccountsWindow() else: window.present() window.select_account(self.account) self.window.destroy() def on_finish_button_clicked(self, widget): go_online = self.xml.get_object('go_online_checkbutton').get_active() show_vcard = self.xml.get_object('show_vcard_checkbutton').get_active() self.window.destroy() if show_vcard: app.interface.show_vcard_when_connect.append(self.account) if go_online: app.interface.roster.send_status(self.account, 'online', '') def on_username_entry_key_press_event(self, widget, event): # Check for pressed @ and jump to combobox if found if event.keyval == Gdk.KEY_at: entry = self.xml.get_object('server_comboboxtext_entry') entry.grab_focus() entry.set_position(-1) return True def on_entry_key_press_event(self, widget, event, combobox): # If backspace is pressed in empty field, return to the nick entry field backspace = event.keyval == Gdk.KEY_BackSpace empty = len(combobox.get_active_text()) == 0 if backspace and empty and self.modify: username_entry = self.xml.get_object('username_entry') username_entry.grab_focus() username_entry.set_position(-1) return True def get_config(self, login, server, savepass, password, anonymous=False): config = {} config['name'] = login config['account_label'] = '%s@%s' % (login, server) config['hostname'] = server config['savepass'] = savepass config['password'] = password config['anonymous_auth'] = anonymous config['priority'] = 5 config['autoconnect'] = True config['no_log_for'] = '' config['sync_with_global_status'] = True config['proxy'] = '' config['use_custom_host'] = False config['custom_port'] = 0 config['custom_host'] = '' config['keyname'] = '' config['keyid'] = '' return config def save_account(self, login, server, savepass, password, anonymous=False): if self.account in app.connections: ErrorDialog( _('Account name is in use'), _('You already have an account using this name.')) return con = connection.Connection(self.account) con.password = password config = self.get_config(login, server, savepass, password, anonymous) if not self.modify: con.new_account(self.account, config) return app.connections[self.account] = con self.create_vars(config) def create_vars(self, config): app.config.add_per('accounts', self.account) config['account_label'] = '%s@%s' % (config['name'], config['hostname']) if not config['savepass']: config['password'] = '' for opt in config: app.config.set_per('accounts', self.account, opt, config[opt]) # update variables app.interface.instances[self.account] = { 'infos': {}, 'disco': {}, 'gc_config': {}, 'search': {}, 'online_dialog': {}, 'sub_request': {}} app.interface.minimized_controls[self.account] = {} app.connections[self.account].connected = 0 app.connections[self.account].keepalives = app.config.get_per( 'accounts', self.account, 'keep_alive_every_foo_secs') app.groups[self.account] = {} app.contacts.add_account(self.account) app.gc_connected[self.account] = {} app.automatic_rooms[self.account] = {} app.newly_added[self.account] = [] app.to_be_removed[self.account] = [] app.nicks[self.account] = config['name'] app.block_signed_in_notifications[self.account] = True app.sleeper_state[self.account] = 'off' app.last_message_time[self.account] = {} app.status_before_autoaway[self.account] = '' app.gajim_optional_features[self.account] = [] app.caps_hash[self.account] = '' helpers.update_optional_features(self.account) # action must be added before account window is updated app.app.add_account_actions(self.account) # refresh accounts window window = app.get_app_window('AccountsWindow') if window is not None: window.add_account(self.account) # refresh roster if len(app.connections) >= 2: # Do not merge accounts if only one exists app.interface.roster.regroup = app.config.get('mergeaccounts') else: app.interface.roster.regroup = False app.interface.roster.setup_and_draw_roster() gui_menu_builder.build_accounts_menu() gajim-gajim-1.1.3/gajim/gtk/accounts.py000066400000000000000000000720001345766322700177530ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from functools import partial from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gajim.common import app from gajim.common import passwords from gajim.common import helpers from gajim.common import ged from gajim.common.i18n import _ from gajim.common.connection import Connection from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf from gajim.common.const import Option from gajim.common.const import OptionKind from gajim.common.const import OptionType from gajim import gtkgui_helpers from gajim import gui_menu_builder from gajim import config from gajim.options_dialog import OptionsDialog from gajim.options_dialog import OptionsBox from gajim.gtk.dialogs import ConfirmationDialog from gajim.gtk.dialogs import YesNoDialog class AccountsWindow(Gtk.ApplicationWindow): def __init__(self): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_name('AccountsWindow') self.set_default_size(700, 550) self.set_resizable(False) self.set_title(_('Accounts')) self.need_relogin = {} glade_objects = ['stack', 'box', 'account_list'] self.builder = gtkgui_helpers.get_gtk_builder('accounts_window.ui') for obj in glade_objects: setattr(self, obj, self.builder.get_object(obj)) self.account_list.add(Preferences(self)) account_item = AddAccount() self.account_list.add(account_item) account_item.set_activatable() accounts = app.config.get_per('accounts') accounts.sort() for account in accounts: self.need_relogin[account] = self.get_relogin_options(account) account_item = Account(account, self) self.account_list.add(account_item) account_item.set_activatable() self.add(self.box) self.builder.connect_signals(self) self.connect('destroy', self.on_destroy) self.connect('key-press-event', self.on_key_press) self._activate_preferences_page() self.show_all() app.ged.register_event_handler( 'our-show', ged.GUI2, self._nec_our_status) def _nec_our_status(self, event): self.update_accounts() def _activate_preferences_page(self): row = self.account_list.get_row_at_index(0) self.account_list.select_row(row) self.account_list.emit('row-activated', row) def on_key_press(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() def on_destroy(self, *args): self.check_relogin() app.ged.remove_event_handler( 'our-show', ged.GUI2, self._nec_our_status) def on_child_visible(self, stack, *args): page = stack.get_visible_child_name() if page is None: return if page == 'account': self.check_relogin() def update_accounts(self): for row in self.account_list.get_children(): row.get_child().update() @staticmethod def on_row_activated(listbox, row): row.get_child().on_row_activated() def remove_all_pages(self): for page in self.stack.get_children(): self.stack.remove(page) def set_page(self, page, name): self.remove_all_pages() self.stack.add_named(page, name) page.update() page.show_all() self.stack.set_visible_child(page) def update_proxy_list(self): page = self.stack.get_child_by_name('connection') if page is None: return page.listbox.get_option('proxy').update_values() def check_relogin(self): for account in self.need_relogin: options = self.get_relogin_options(account) active = app.config.get_per('accounts', account, 'active') if options != self.need_relogin[account]: self.need_relogin[account] = options if active: self.relog(account) break def relog(self, account): if app.connections[account].connected == 0: return if account == app.ZEROCONF_ACC_NAME: app.connections[app.ZEROCONF_ACC_NAME].update_details() return def login(account, show_before, status_before): """ Login with previous status """ # first make sure connection is really closed, # 0.5 may not be enough app.connections[account].disconnect(True) app.interface.roster.send_status( account, show_before, status_before) def relog(account): show_before = app.SHOW_LIST[app.connections[account].connected] status_before = app.connections[account].status app.interface.roster.send_status( account, 'offline', _('Be right back.')) GLib.timeout_add(500, login, account, show_before, status_before) YesNoDialog( _('Relogin now?'), _('If you want all the changes to apply instantly, ' 'you must relogin.'), transient_for=self, on_response_yes=lambda *args: relog(account)) @staticmethod def get_relogin_options(account): if account == app.ZEROCONF_ACC_NAME: options = ['zeroconf_first_name', 'zeroconf_last_name', 'zeroconf_jabber_id', 'zeroconf_email', 'keyid'] else: options = ['client_cert', 'proxy', 'resource', 'use_custom_host', 'custom_host', 'custom_port', 'keyid'] values = [] for option in options: values.append(app.config.get_per('accounts', account, option)) return values def on_remove_account(self, button, account): if app.events.get_events(account): app.interface.raise_dialog('unread-events-on-remove-account') return if app.config.get_per('accounts', account, 'is_zeroconf'): # Should never happen as button is insensitive return win_opened = False if app.interface.msg_win_mgr.get_controls(acct=account): win_opened = True elif account in app.interface.instances: for key in app.interface.instances[account]: if (app.interface.instances[account][key] and key != 'remove_account'): win_opened = True break # Detect if we have opened windows for this account def remove(account): if (account in app.interface.instances and 'remove_account' in app.interface.instances[account]): dialog = app.interface.instances[account]['remove_account'] dialog.window.present() else: if account not in app.interface.instances: app.interface.instances[account] = {} app.interface.instances[account]['remove_account'] = \ config.RemoveAccountWindow(account) if win_opened: ConfirmationDialog( _('You have opened chat in account %s') % account, _('All chat and groupchat windows will be closed. ' 'Do you want to continue?'), on_response_ok=(remove, account), transient_for=self) else: remove(account) def remove_account(self, account): for row in self.account_list.get_children(): if row.get_child().account == account: self.account_list.remove(row) del self.need_relogin[account] break self._activate_preferences_page() def add_account(self, account): account_item = Account(account, self) self.account_list.add(account_item) account_item.set_activatable() self.account_list.show_all() self.stack.show_all() self.need_relogin[account] = self.get_relogin_options(account) def select_account(self, account): for row in self.account_list.get_children(): if row.get_child().account == account: self.account_list.select_row(row) self.account_list.emit('row-activated', row) break @staticmethod def enable_account(account): if account == app.ZEROCONF_ACC_NAME: app.connections[account] = ConnectionZeroconf(account) else: app.connections[account] = Connection(account) app.plugin_manager.register_modules_for_account( app.connections[account]) # update variables app.interface.instances[account] = { 'infos': {}, 'disco': {}, 'gc_config': {}, 'search': {}, 'online_dialog': {}, 'sub_request': {}} app.interface.minimized_controls[account] = {} app.connections[account].connected = 0 app.groups[account] = {} app.contacts.add_account(account) app.gc_connected[account] = {} app.automatic_rooms[account] = {} app.newly_added[account] = [] app.to_be_removed[account] = [] if account == app.ZEROCONF_ACC_NAME: app.nicks[account] = app.ZEROCONF_ACC_NAME else: app.nicks[account] = app.config.get_per( 'accounts', account, 'name') app.block_signed_in_notifications[account] = True app.sleeper_state[account] = 'off' app.last_message_time[account] = {} app.status_before_autoaway[account] = '' app.gajim_optional_features[account] = [] app.caps_hash[account] = '' helpers.update_optional_features(account) # refresh roster if len(app.connections) >= 2: # Do not merge accounts if only one exists app.interface.roster.regroup = app.config.get('mergeaccounts') else: app.interface.roster.regroup = False app.interface.roster.setup_and_draw_roster() gui_menu_builder.build_accounts_menu() @staticmethod def disable_account(account): app.interface.roster.close_all(account) if account == app.ZEROCONF_ACC_NAME: app.connections[account].disable_account() app.connections[account].cleanup() del app.connections[account] del app.interface.instances[account] del app.interface.minimized_controls[account] del app.nicks[account] del app.block_signed_in_notifications[account] del app.groups[account] app.contacts.remove_account(account) del app.gc_connected[account] del app.automatic_rooms[account] del app.to_be_removed[account] del app.newly_added[account] del app.sleeper_state[account] del app.last_message_time[account] del app.status_before_autoaway[account] del app.gajim_optional_features[account] del app.caps_hash[account] if len(app.connections) >= 2: # Do not merge accounts if only one exists app.interface.roster.regroup = app.config.get('mergeaccounts') else: app.interface.roster.regroup = False app.config.set_per( 'accounts', account, 'roster_version', '') app.interface.roster.setup_and_draw_roster() gui_menu_builder.build_accounts_menu() class AddAccount(Gtk.Box): def __init__(self): Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=12) self.account = None self.label = Gtk.Label(label=_('Add Account…')) self.label.set_halign(Gtk.Align.START) self.label.set_hexpand(True) self.image = Gtk.Image.new_from_icon_name( 'list-add-symbolic', Gtk.IconSize.MENU) self.add(self.image) self.add(self.label) def set_activatable(self): self.get_parent().set_selectable(False) def on_row_activated(self): app.app.activate_action('add-account') def update(self): pass class Preferences(Gtk.Box): def __init__(self, parent): Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=12) self.options = PreferencesPage() self.parent = parent self.account = None self.label = Gtk.Label(label=_('Preferences')) self.label.set_halign(Gtk.Align.START) self.label.set_hexpand(True) self.image = Gtk.Image.new_from_icon_name( 'system-run-symbolic', Gtk.IconSize.MENU) self.add(self.image) self.add(self.label) def set_activatable(self): pass def on_row_activated(self): self.options.update_states() self.parent.set_page(self.options, 'pref') def update(self): pass class Account(Gtk.Box): def __init__(self, account, parent): Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=12) self.account = account if account == app.ZEROCONF_ACC_NAME: self.options = ZeroConfPage(account, parent) else: self.options = AccountPage(account, parent) self.parent = parent self.label = Gtk.Label(app.get_account_label(account)) self.label.set_halign(Gtk.Align.START) self.label.set_hexpand(True) self.image = Gtk.Image() self._update_image() self.add(self.image) self.add(self.label) def set_activatable(self): if self.account == app.ZEROCONF_ACC_NAME: zeroconf = app.is_installed('ZEROCONF') self.get_parent().set_activatable(zeroconf) self.get_parent().set_sensitive(zeroconf) if not zeroconf: self.get_parent().set_tooltip_text( _('Please check if Avahi or Bonjour is installed.')) def on_row_activated(self): self.options.update_states() self.parent.set_page(self.options, 'account') def update(self): self.label.set_text(app.get_account_label(self.account)) self._update_image() def _update_image(self): show = helpers.get_current_show(self.account) icon = gtkgui_helpers.get_iconset_name_for(show) self.image.set_from_icon_name(icon, Gtk.IconSize.MENU) class GenericOptionPage(Gtk.Box): def __init__(self, account, parent, options): Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=12) self.account = account self.parent = parent button = Gtk.Button.new_from_icon_name( 'go-previous-symbolic', Gtk.IconSize.MENU) button.set_halign(Gtk.Align.START) button.connect('clicked', self._on_back_button) if not isinstance(self, (AccountPage, PreferencesPage, ZeroConfPage)): self.pack_start(button, False, True, 0) self.listbox = OptionsBox(account) self.listbox.set_selection_mode(Gtk.SelectionMode.NONE) self.listbox.set_vexpand(False) self.listbox.set_valign(Gtk.Align.END) for option in options: self.listbox.add_option(option) self.listbox.update_states() self.pack_end(self.listbox, True, True, 0) self.listbox.connect('row-activated', self.on_row_activated) def _on_back_button(self, *args): account_window = self.get_toplevel() child = account_window.stack.get_visible_child() account_window.remove_all_pages() account_window.stack.add_named(child.parent, 'account') account_window.stack.set_visible_child_name('account') def update_states(self): self.listbox.update_states() def on_row_activated(self, listbox, row): row.get_child().on_row_activated() def set_entry_text(self, toggle, update=False): account_label = app.get_account_label(self.account) if update: self.entry.set_text(account_label) return if toggle.get_active(): self.entry.set_sensitive(True) self.entry.grab_focus() else: self.entry.set_sensitive(False) value = self.entry.get_text() if not value: value = account_label app.config.set_per('accounts', self.account, 'account_label', value or self.account) if app.config.get_per('accounts', self.account, 'active'): app.interface.roster.draw_account(self.account) gui_menu_builder.build_accounts_menu() def update(self): pass def set_page(self, options, name): options.update_states() self.get_toplevel().set_page(options, name) def _add_top_buttons(self, parent): # This adds the Account enable switch and the back button box = Gtk.Box() box.set_hexpand(True) box.set_halign(Gtk.Align.FILL) switch = Gtk.Switch() switch.set_active(app.config.get_per('accounts', self.account, 'active')) switch.set_vexpand(False) switch.set_valign(Gtk.Align.CENTER) switch.set_halign(Gtk.Align.END) if self.account == app.ZEROCONF_ACC_NAME and not app.is_installed('ZEROCONF'): switch.set_sensitive(False) switch.set_active(False) switch.connect('notify::active', self._on_enable_switch, self.account) box.pack_start(switch, False, False, 0) if self.account != app.ZEROCONF_ACC_NAME: button = Gtk.Button(label=_('Remove')) button.connect( 'clicked', parent.on_remove_account, self.account) button.get_style_context().add_class('destructive-action') button.set_halign(Gtk.Align.END) switch.set_vexpand(False) box.pack_end(button, False, False, 0) self.pack_start(box, True, True, 0) def _on_enable_switch(self, switch, param, account): old_state = app.config.get_per('accounts', account, 'active') state = switch.get_active() if old_state == state: return if (account in app.connections and app.connections[account].connected > 0): # connecting or connected app.interface.raise_dialog('connected-on-disable-account') switch.set_active(not state) return if state: self.parent.enable_account(account) else: self.parent.disable_account(account) app.config.set_per('accounts', account, 'active', state) class PreferencesPage(GenericOptionPage): def __init__(self): options = [ Option(OptionKind.SWITCH, _('Merge Accounts'), OptionType.ACTION, 'merge'), Option(OptionKind.SWITCH, _('Use PGP Agent'), OptionType.ACTION, 'agent'), ] GenericOptionPage.__init__(self, None, None, options) class AccountPage(GenericOptionPage): def __init__(self, account, parent=None): general = partial( self.set_page, GeneralPage(account, self), 'general') connection = partial( self.set_page, ConnectionPage(account, self), 'connection') options = [ Option(OptionKind.ENTRY, _('Label'), OptionType.ACCOUNT_CONFIG, 'account_label', callback=self._on_account_name_change), Option(OptionKind.LOGIN, _('Login'), OptionType.DIALOG, props={'dialog': LoginDialog}), Option(OptionKind.ACTION, _('Profile'), OptionType.ACTION, '-profile', props={'action_args': account}), Option(OptionKind.CALLBACK, _('General'), name='general', props={'callback': general}), Option(OptionKind.CALLBACK, _('Connection'), name='connection', props={'callback': connection}), Option(OptionKind.ACTION, _('Import Contacts'), OptionType.ACTION, '-import-contacts', props={'action_args': account}), Option(OptionKind.DIALOG, _('Client Certificate'), OptionType.DIALOG, props={'dialog': CertificateDialog}), Option(OptionKind.GPG, _('OpenPGP Key'), OptionType.DIALOG, props={'dialog': None}), ] GenericOptionPage.__init__(self, account, parent, options) self._add_top_buttons(parent) def _on_account_name_change(self, account_name, *args): self.parent.update_accounts() class GeneralPage(GenericOptionPage): def __init__(self, account, parent=None): options = [ Option(OptionKind.SWITCH, _('Connect on startup'), OptionType.ACCOUNT_CONFIG, 'autoconnect'), Option(OptionKind.SWITCH, _('Reconnect when connection is lost'), OptionType.ACCOUNT_CONFIG, 'autoreconnect'), Option(OptionKind.SWITCH, _('Save conversations for all contacts'), OptionType.ACCOUNT_CONFIG, 'no_log_for', desc=_('Store conversations on the harddrive')), Option(OptionKind.SWITCH, _('Server Message Archive'), OptionType.ACCOUNT_CONFIG, 'sync_logs_with_server', desc=_('Messages get stored on the server.\n' 'The archive is used to sync messages\n' 'between multiple devices.\n' 'XEP-0313')), Option(OptionKind.SWITCH, _('Global Status'), OptionType.ACCOUNT_CONFIG, 'sync_with_global_status', desc=_('Synchronise the status of all accounts')), Option(OptionKind.SWITCH, _('Message Carbons'), OptionType.ACCOUNT_CONFIG, 'enable_message_carbons', desc=_('All your other online devices get copies\n' 'of sent and received messages.\n' 'XEP-0280')), Option(OptionKind.SWITCH, _('Use file transfer proxies'), OptionType.ACCOUNT_CONFIG, 'use_ft_proxies'), ] GenericOptionPage.__init__(self, account, parent, options) class ConnectionPage(GenericOptionPage): def __init__(self, account, parent=None): options = [ Option(OptionKind.SWITCH, 'HTTP_PROXY', OptionType.ACCOUNT_CONFIG, 'use_env_http_proxy', desc=_('Use environment variable')), Option(OptionKind.PROXY, _('Proxy'), OptionType.ACCOUNT_CONFIG, 'proxy', name='proxy'), Option(OptionKind.SWITCH, _('Warn on insecure connection'), OptionType.ACCOUNT_CONFIG, 'warn_when_insecure_ssl_connection'), Option(OptionKind.SWITCH, _('Send keep-alive packets'), OptionType.ACCOUNT_CONFIG, 'keep_alives_enabled'), Option(OptionKind.HOSTNAME, _('Hostname'), OptionType.DIALOG, desc=_('Manually set the hostname for the server'), props={'dialog': CutstomHostnameDialog}), Option(OptionKind.ENTRY, _('Resource'), OptionType.ACCOUNT_CONFIG, 'resource'), Option(OptionKind.PRIORITY, _('Priority'), OptionType.DIALOG, props={'dialog': PriorityDialog}), ] GenericOptionPage.__init__(self, account, parent, options) class ZeroConfPage(GenericOptionPage): def __init__(self, account, parent=None): options = [ Option(OptionKind.DIALOG, _('Profile'), OptionType.DIALOG, props={'dialog': ZeroconfProfileDialog}), Option(OptionKind.SWITCH, _('Connect on startup'), OptionType.ACCOUNT_CONFIG, 'autoconnect', desc=_('Use environment variable')), Option(OptionKind.SWITCH, _('Save conversations for all contacts'), OptionType.ACCOUNT_CONFIG, 'no_log_for', desc=_('Store conversations on the harddrive')), Option(OptionKind.SWITCH, _('Global Status'), OptionType.ACCOUNT_CONFIG, 'sync_with_global_status', desc=_('Synchronize the status of all accounts')), Option(OptionKind.GPG, _('OpenPGP Key'), OptionType.DIALOG, props={'dialog': None}), ] GenericOptionPage.__init__(self, account, parent, options) self._add_top_buttons(None) class ZeroconfProfileDialog(OptionsDialog): def __init__(self, account, parent): options = [ Option(OptionKind.ENTRY, _('First Name'), OptionType.ACCOUNT_CONFIG, 'zeroconf_first_name'), Option(OptionKind.ENTRY, _('Last Name'), OptionType.ACCOUNT_CONFIG, 'zeroconf_last_name'), Option(OptionKind.ENTRY, _('Jabber ID'), OptionType.ACCOUNT_CONFIG, 'zeroconf_jabber_id'), Option(OptionKind.ENTRY, _('Email'), OptionType.ACCOUNT_CONFIG, 'zeroconf_email'), ] OptionsDialog.__init__(self, parent, _('Profile'), Gtk.DialogFlags.MODAL, options, account) class PriorityDialog(OptionsDialog): def __init__(self, account, parent): neg_priority = app.config.get('enable_negative_priority') if neg_priority: range_ = (-128, 127) else: range_ = (0, 127) options = [ Option(OptionKind.SWITCH, _('Adjust to status'), OptionType.ACCOUNT_CONFIG, 'adjust_priority_with_status', 'adjust'), Option(OptionKind.SPIN, _('Priority'), OptionType.ACCOUNT_CONFIG, 'priority', enabledif=('adjust', False), props={'range_': range_}), ] OptionsDialog.__init__(self, parent, _('Priority'), Gtk.DialogFlags.MODAL, options, account) self.connect('destroy', self.on_destroy) def on_destroy(self, *args): # Update priority if self.account not in app.connections: return show = app.SHOW_LIST[app.connections[self.account].connected] status = app.connections[self.account].status app.connections[self.account].change_status(show, status) class CutstomHostnameDialog(OptionsDialog): def __init__(self, account, parent): options = [ Option(OptionKind.SWITCH, _('Enable'), OptionType.ACCOUNT_CONFIG, 'use_custom_host', name='custom'), Option(OptionKind.ENTRY, _('Hostname'), OptionType.ACCOUNT_CONFIG, 'custom_host', enabledif=('custom', True)), Option(OptionKind.ENTRY, _('Port'), OptionType.ACCOUNT_CONFIG, 'custom_port', enabledif=('custom', True)), ] OptionsDialog.__init__(self, parent, _('Connection Options'), Gtk.DialogFlags.MODAL, options, account) class CertificateDialog(OptionsDialog): def __init__(self, account, parent): options = [ Option(OptionKind.FILECHOOSER, _('Client Certificate'), OptionType.ACCOUNT_CONFIG, 'client_cert', props={'filefilter': (_('PKCS12 Files'), '*.p12')}), Option(OptionKind.SWITCH, _('Encrypted Certificate'), OptionType.ACCOUNT_CONFIG, 'client_cert_encrypted'), ] OptionsDialog.__init__(self, parent, _('Certificate Options'), Gtk.DialogFlags.MODAL, options, account) class LoginDialog(OptionsDialog): def __init__(self, account, parent): options = [ Option(OptionKind.ENTRY, _('Password'), OptionType.ACCOUNT_CONFIG, 'password', name='password', enabledif=('savepass', True)), Option(OptionKind.SWITCH, _('Save Password'), OptionType.ACCOUNT_CONFIG, 'savepass', name='savepass'), Option(OptionKind.CHANGEPASSWORD, _('Change Password'), OptionType.DIALOG, callback=self.on_password_change, props={'dialog': None}), ] OptionsDialog.__init__(self, parent, _('Login Options'), Gtk.DialogFlags.MODAL, options, account) self.connect('destroy', self.on_destroy) def on_password_change(self, new_password, data): passwords.save_password(self.account, new_password) def on_destroy(self, *args): savepass = app.config.get_per('accounts', self.account, 'savepass') if not savepass: passwords.save_password(self.account, '') gajim-gajim-1.1.3/gajim/gtk/add_contact.py000066400000000000000000000444221345766322700204060ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gdk from gi.repository import Gtk from gajim.common import app from gajim.common import ged from gajim.common import helpers from gajim.common.i18n import _ from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.util import get_builder class AddNewContactWindow(Gtk.ApplicationWindow): uid_labels = {'jabber': _('Jabber ID'), 'gadu-gadu': _('GG Number'), 'icq': _('ICQ Number')} def __init__(self, account=None, jid=None, user_nick=None, group=None): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_resizable(False) self.set_title(_('Add Contact')) self.connect('destroy', self._on_destroy) self.connect('key-press-event', self._on_key_press) self.account = account self.adding_jid = False # fill accounts with active accounts accounts = app.get_enabled_accounts_with_labels() if not accounts: return if not account: self.account = accounts[0][0] self.xml = get_builder('add_new_contact_window.ui') self.add(self.xml.get_object('add_contact_box')) self.xml.connect_signals(self) for w in ('account_combobox', 'account_label', 'prompt_label', 'uid_label', 'uid_entry', 'protocol_combobox', 'protocol_jid_combobox', 'protocol_label', 'nickname_entry', 'message_scrolledwindow', 'save_message_checkbutton', 'register_hbox', 'add_button', 'message_textview', 'connected_label', 'group_comboboxentry', 'auto_authorize_checkbutton', 'save_message_revealer', 'nickname_label', 'group_label'): self.__dict__[w] = self.xml.get_object(w) self.subscription_table = [self.uid_label, self.uid_entry, self.nickname_label, self.nickname_entry, self.group_label, self.group_comboboxentry] self.add_button.grab_default() self.agents = {'jabber': []} self.gateway_prompt = {} # types to which we are not subscribed but account has an agent for it self.available_types = [] for acct in accounts: for j in app.contacts.get_jid_list(acct[0]): if app.jid_is_transport(j): type_ = app.get_transport_name_from_jid(j, False) if not type_: continue if type_ in self.agents: self.agents[type_].append(j) else: self.agents[type_] = [j] self.gateway_prompt[j] = {'desc': None, 'prompt': None} # Now add the one to which we can register for acct in accounts: for type_ in app.connections[acct[0]].available_transports: if type_ in self.agents: continue self.agents[type_] = [] for jid_ in app.connections[acct[0]].available_transports[type_]: if jid_ not in self.agents[type_]: self.agents[type_].append(jid_) self.gateway_prompt[jid_] = {'desc': None, 'prompt': None} self.available_types.append(type_) uf_type = {'jabber': 'XMPP', 'gadu-gadu': 'Gadu Gadu', 'icq': 'ICQ'} # Jabber as first liststore = self.protocol_combobox.get_model() liststore.append(['XMPP', 'xmpp', 'jabber']) for type_ in self.agents: if type_ == 'jabber': continue if type_ in uf_type: liststore.append([uf_type[type_], type_ + '-online', type_]) else: liststore.append([type_, type_ + '-online', type_]) if account: for service in self.agents[type_]: app.connections[account].request_gateway_prompt(service) self.protocol_combobox.set_active(0) self.auto_authorize_checkbutton.show() if jid: self.jid_escaped = True type_ = app.get_transport_name_from_jid(jid) if not type_: type_ = 'jabber' if type_ == 'jabber': self.uid_entry.set_text(jid) transport = None else: uid, transport = app.get_name_and_server_from_jid(jid) self.uid_entry.set_text(uid.replace('%', '@', 1)) # set protocol_combobox model = self.protocol_combobox.get_model() iter_ = model.get_iter_first() i = 0 while iter_: if model[iter_][2] == type_: self.protocol_combobox.set_active(i) break iter_ = model.iter_next(iter_) i += 1 # set protocol_jid_combobox self.protocol_jid_combobox.set_active(0) model = self.protocol_jid_combobox.get_model() iter_ = model.get_iter_first() i = 0 while iter_: if model[iter_][0] == transport: self.protocol_jid_combobox.set_active(i) break iter_ = model.iter_next(iter_) i += 1 if user_nick: self.nickname_entry.set_text(user_nick) self.nickname_entry.grab_focus() else: self.jid_escaped = False self.uid_entry.grab_focus() group_names = [] for acct in accounts: for g in app.groups[acct[0]].keys(): if g not in helpers.special_groups and g not in group_names: group_names.append(g) group_names.sort() i = 0 for g in group_names: self.group_comboboxentry.append_text(g) if group == g: self.group_comboboxentry.set_active(i) i += 1 if len(accounts) > 1: liststore = self.account_combobox.get_model() for acc in accounts: liststore.append(acc) self.account_combobox.set_active_id(self.account) self.account_label.show() self.account_combobox.show() if len(self.agents) > 1: self.protocol_label.show() self.protocol_combobox.show() if self.account: message_buffer = self.message_textview.get_buffer() msg = helpers.from_one_line(helpers.get_subscription_request_msg( self.account)) message_buffer.set_text(msg) self.show_all() app.ged.register_event_handler('gateway-prompt-received', ged.GUI1, self._nec_gateway_prompt_received) app.ged.register_event_handler('presence-received', ged.GUI1, self._nec_presence_received) def _on_destroy(self, widget): app.ged.remove_event_handler('presence-received', ged.GUI1, self._nec_presence_received) app.ged.remove_event_handler('gateway-prompt-received', ged.GUI1, self._nec_gateway_prompt_received) def on_register_button_clicked(self, widget): model = self.protocol_jid_combobox.get_model() row = self.protocol_jid_combobox.get_active() jid = model[row][0] from gajim.gtk.service_registration import ServiceRegistration ServiceRegistration(self.account, jid) def _on_key_press(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() def on_cancel_button_clicked(self, widget): """ When Cancel button is clicked """ self.destroy() def on_message_textbuffer_changed(self, widget): self.save_message_revealer.show() self.save_message_revealer.set_reveal_child(True) def on_add_button_clicked(self, widget): """ When Subscribe button is clicked """ jid = self.uid_entry.get_text().strip() if not jid: ErrorDialog( _('%s Missing') % self.uid_label.get_text(), _('You must supply the %s of the new contact.' % self.uid_label.get_text()) ) return model = self.protocol_combobox.get_model() row = self.protocol_combobox.get_active_iter() type_ = model[row][2] if type_ != 'jabber': model = self.protocol_jid_combobox.get_model() row = self.protocol_jid_combobox.get_active() transport = model[row][0] if self.account and not self.jid_escaped: self.adding_jid = (jid, transport, type_) app.connections[self.account].request_gateway_prompt( transport, jid) else: jid = jid.replace('@', '%') + '@' + transport self._add_jid(jid, type_) else: self._add_jid(jid, type_) def _add_jid(self, jid, type_): # check if jid is conform to RFC and stringprep it try: jid = helpers.parse_jid(jid) except helpers.InvalidFormat as s: pritext = _('Invalid User ID') ErrorDialog(pritext, str(s)) return # No resource in jid if jid.find('/') >= 0: pritext = _('Invalid User ID') ErrorDialog(pritext, _('The user ID must not contain a resource.')) return if jid == app.get_jid_from_account(self.account): pritext = _('Invalid User ID') ErrorDialog(pritext, _('You cannot add yourself to your roster.')) return if not app.account_is_connected(self.account): ErrorDialog( _('Account Offline'), _('Your account must be online to add new contacts.') ) return nickname = self.nickname_entry.get_text() or '' # get value of account combobox, if account was not specified if not self.account: model = self.account_combobox.get_model() index = self.account_combobox.get_active() self.account = model[index][1] # Check if jid is already in roster if jid in app.contacts.get_jid_list(self.account): c = app.contacts.get_first_contact_from_jid(self.account, jid) if _('Not in Roster') not in c.groups and c.sub in ('both', 'to'): ErrorDialog( _('Contact already in roster'), _('This contact is already listed in your roster.')) return if type_ == 'jabber': message_buffer = self.message_textview.get_buffer() start_iter = message_buffer.get_start_iter() end_iter = message_buffer.get_end_iter() message = message_buffer.get_text(start_iter, end_iter, True) if self.save_message_checkbutton.get_active(): msg = helpers.to_one_line(message) app.config.set_per('accounts', self.account, 'subscription_request_msg', msg) else: message = '' group = self.group_comboboxentry.get_child().get_text() groups = [] if group: groups = [group] auto_auth = self.auto_authorize_checkbutton.get_active() app.interface.roster.req_sub( self, jid, message, self.account, groups=groups, nickname=nickname, auto_auth=auto_auth) self.destroy() def on_account_combobox_changed(self, widget): account = widget.get_active_id() message_buffer = self.message_textview.get_buffer() message_buffer.set_text(helpers.get_subscription_request_msg(account)) self.account = account def on_protocol_jid_combobox_changed(self, widget): model = widget.get_model() iter_ = widget.get_active_iter() if not iter_: return jid_ = model[iter_][0] model = self.protocol_combobox.get_model() iter_ = self.protocol_combobox.get_active_iter() type_ = model[iter_][2] desc = None if self.agents[type_] and jid_ in self.gateway_prompt: desc = self.gateway_prompt[jid_]['desc'] if desc: self.prompt_label.set_markup(desc) self.prompt_label.show() else: self.prompt_label.hide() prompt = None if self.agents[type_] and jid_ in self.gateway_prompt: prompt = self.gateway_prompt[jid_]['prompt'] if not prompt: if type_ in self.uid_labels: prompt = self.uid_labels[type_] else: prompt = _('User ID:') self.uid_label.set_text(prompt) def on_protocol_combobox_changed(self, widget): model = widget.get_model() iter_ = widget.get_active_iter() type_ = model[iter_][2] model = self.protocol_jid_combobox.get_model() model.clear() if self.agents[type_]: for jid_ in self.agents[type_]: model.append([jid_]) self.protocol_jid_combobox.set_active(0) desc = None if self.agents[type_]: jid_ = self.agents[type_][0] if jid_ in self.gateway_prompt: desc = self.gateway_prompt[jid_]['desc'] if desc: self.prompt_label.set_markup(desc) self.prompt_label.show() else: self.prompt_label.hide() if len(self.agents[type_]) > 1: self.protocol_jid_combobox.show() else: self.protocol_jid_combobox.hide() prompt = None if self.agents[type_]: jid_ = self.agents[type_][0] if jid_ in self.gateway_prompt: prompt = self.gateway_prompt[jid_]['prompt'] if not prompt: if type_ in self.uid_labels: prompt = self.uid_labels[type_] else: prompt = _('User ID:') self.uid_label.set_text(prompt) if type_ == 'jabber': self.message_scrolledwindow.show() self.save_message_checkbutton.show() else: self.message_scrolledwindow.hide() self.save_message_checkbutton.hide() if type_ in self.available_types: self.register_hbox.show() self.auto_authorize_checkbutton.hide() self.connected_label.hide() self._subscription_table_hide() self.add_button.set_sensitive(False) else: self.register_hbox.hide() if type_ != 'jabber': model = self.protocol_jid_combobox.get_model() row = self.protocol_jid_combobox.get_active() jid = model[row][0] contact = app.contacts.get_first_contact_from_jid( self.account, jid) if contact is None or contact.show in ('offline', 'error'): self._subscription_table_hide() self.connected_label.show() self.add_button.set_sensitive(False) self.auto_authorize_checkbutton.hide() return self._subscription_table_show() self.auto_authorize_checkbutton.show() self.connected_label.hide() self.add_button.set_sensitive(True) def transport_signed_in(self, jid): model = self.protocol_jid_combobox.get_model() row = self.protocol_jid_combobox.get_active() _jid = model[row][0] if _jid == jid: self.register_hbox.hide() self.connected_label.hide() self._subscription_table_show() self.auto_authorize_checkbutton.show() self.add_button.set_sensitive(True) def transport_signed_out(self, jid): model = self.protocol_jid_combobox.get_model() row = self.protocol_jid_combobox.get_active() _jid = model[row][0] if _jid == jid: self._subscription_table_hide() self.auto_authorize_checkbutton.hide() self.connected_label.show() self.add_button.set_sensitive(False) def _nec_presence_received(self, obj): if app.jid_is_transport(obj.jid): if obj.old_show == 0 and obj.new_show > 1: self.transport_signed_in(obj.jid) elif obj.old_show > 1 and obj.new_show == 0: self.transport_signed_out(obj.jid) def _nec_gateway_prompt_received(self, obj): if self.adding_jid: jid, transport, type_ = self.adding_jid if obj.stanza.getError(): ErrorDialog( _('Error while adding transport contact'), _('This error occured while adding a contact for transport ' '%(transport)s:\n\n%(error)s') % { 'transport': transport, 'error': obj.stanza.getErrorMsg()}) return if obj.prompt_jid: self._add_jid(obj.prompt_jid, type_) else: jid = jid.replace('@', '%') + '@' + transport self._add_jid(jid, type_) elif obj.jid in self.gateway_prompt: if obj.desc: self.gateway_prompt[obj.jid]['desc'] = obj.desc if obj.prompt: self.gateway_prompt[obj.jid]['prompt'] = obj.prompt def _subscription_table_hide(self): for widget in self.subscription_table: widget.hide() def _subscription_table_show(self): for widget in self.subscription_table: widget.show() gajim-gajim-1.1.3/gajim/gtk/advanced_config.py000066400000000000000000000323711345766322700212350ustar00rootroot00000000000000# Copyright (C) 2005 Travis Shirk # Vincent Hanquez # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2006-2007 Jean-Marie Traissard # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from enum import IntEnum, unique from gi.repository import Gtk from gi.repository import GLib from gi.repository import Pango from gajim.common import app from gajim.common.i18n import _ from gajim.gtk.util import get_builder @unique class Column(IntEnum): NAME = 0 VALUE = 1 TYPE = 2 def rate_limit(rate): """ Call func at most *rate* times per second """ def decorator(func): timeout = [None] def f(*args, **kwargs): if timeout[0] is not None: GLib.source_remove(timeout[0]) timeout[0] = None def timeout_func(): func(*args, **kwargs) timeout[0] = None timeout[0] = GLib.timeout_add(int(1000.0 / rate), timeout_func) return f return decorator def tree_model_iter_children(model, treeiter): it = model.iter_children(treeiter) while it: yield it it = model.iter_next(it) def tree_model_pre_order(model, treeiter): yield treeiter for childiter in tree_model_iter_children(model, treeiter): for it in tree_model_pre_order(model, childiter): yield it class AdvancedConfig: def __init__(self, transient): self.xml = get_builder('advanced_configuration_window.ui') self.window = self.xml.get_object('advanced_configuration_window') self.window.set_transient_for(transient) self.entry = self.xml.get_object('advanced_entry') self.desc_label = self.xml.get_object('advanced_desc_label') self.restart_box = self.xml.get_object('restart_box') self.reset_button = self.xml.get_object('reset_button') # Format: # key = option name (root/subopt/opt separated by \n then) # value = array(oldval, newval) self.changed_opts = {} # For i18n self.right_true_dict = {True: _('Activated'), False: _('Deactivated')} self.types = { 'boolean': _('Boolean'), 'integer': _('Integer'), 'string': _('Text'), 'color': _('Color')} treeview = self.xml.get_object('advanced_treeview') self.treeview = treeview self.model = Gtk.TreeStore(str, str, str) self.fill_model() self.model.set_sort_column_id(0, Gtk.SortType.ASCENDING) self.modelfilter = self.model.filter_new() self.modelfilter.set_visible_func(self.visible_func) renderer_text = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('Preference Name'), renderer_text, text=0) treeview.insert_column(col, -1) col.set_resizable(True) renderer_text = Gtk.CellRendererText() renderer_text.connect('edited', self.on_config_edited) renderer_text.set_property('ellipsize', Pango.EllipsizeMode.END) col = Gtk.TreeViewColumn(_('Value'), renderer_text, text=1) treeview.insert_column(col, -1) col.set_cell_data_func(renderer_text, self.cb_value_column_data) col.props.resizable = True col.props.expand = True col.props.sizing = Gtk.TreeViewColumnSizing.FIXED renderer_text = Gtk.CellRendererText() col = Gtk.TreeViewColumn(_('Type'), renderer_text, text=2) treeview.insert_column(col, -1) col.props.sizing = Gtk.TreeViewColumnSizing.FIXED treeview.set_model(self.modelfilter) # connect signal for selection change treeview.get_selection().connect('changed', self.on_advanced_treeview_selection_changed) self.xml.connect_signals(self) self.restart_box.set_no_show_all(True) self.window.show_all() app.interface.instances['advanced_config'] = self def cb_value_column_data(self, col, cell, model, iter_, data): """ Check if it's boolean or holds password stuff and if yes make the cellrenderertext not editable, else - it's editable """ optname = model[iter_][Column.NAME] opttype = model[iter_][Column.TYPE] if opttype == self.types['boolean'] or optname == 'password': cell.set_property('editable', False) else: cell.set_property('editable', True) @staticmethod def get_option_path(model, iter_): # It looks like path made from reversed array # path[0] is the true one optname # path[1] is the key name # path[2] is the root of tree # last two is optional path = [model[iter_][0]] parent = model.iter_parent(iter_) while parent: path.append(model[parent][0]) parent = model.iter_parent(parent) return path def on_advanced_treeview_selection_changed(self, treeselection): model, iter_ = treeselection.get_selected() # Check for GtkTreeIter if iter_: opt_path = self.get_option_path(model, iter_) # Get text from first column in this row desc = None if len(opt_path) == 3: desc = app.config.get_desc_per(opt_path[2], opt_path[0]) elif len(opt_path) == 1: desc = app.config.get_desc(opt_path[0]) if desc: self.desc_label.set_text(desc) else: #we talk about option description in advanced configuration editor self.desc_label.set_text(_('(None)')) if len(opt_path) == 3 or (len(opt_path) == 1 and not \ model.iter_has_child(iter_)): self.reset_button.set_sensitive(True) else: self.reset_button.set_sensitive(False) else: self.reset_button.set_sensitive(False) def remember_option(self, option, oldval, newval): if option in self.changed_opts: self.changed_opts[option] = (self.changed_opts[option][0], newval) else: self.changed_opts[option] = (oldval, newval) def on_advanced_treeview_row_activated(self, treeview, path, column): modelpath = self.modelfilter.convert_path_to_child_path(path) modelrow = self.model[modelpath] option = modelrow[0] if modelrow[2] == self.types['boolean']: for key in self.right_true_dict: if self.right_true_dict[key] == modelrow[1]: modelrow[1] = str(key) newval = {'False': True, 'True': False}[modelrow[1]] if len(modelpath.get_indices()) > 1: optnamerow = self.model[modelpath.get_indices()[0]] optname = optnamerow[0] modelpath.up() keyrow = self.model[modelpath] key = keyrow[0] self.remember_option(option + '\n' + key + '\n' + optname, modelrow[1], newval) app.config.set_per(optname, key, option, newval) else: self.remember_option(option, modelrow[1], newval) app.config.set(option, newval) modelrow[1] = self.right_true_dict[newval] self.check_for_restart() def check_for_restart(self): self.restart_box.hide() for opt in self.changed_opts: opt_path = opt.split('\n') if len(opt_path) == 3: restart = app.config.get_restart_per(opt_path[2], opt_path[1], opt_path[0]) else: restart = app.config.get_restart(opt_path[0]) if restart: if self.changed_opts[opt][0] != self.changed_opts[opt][1]: self.restart_box.set_no_show_all(False) self.restart_box.show_all() break def on_config_edited(self, cell, path, text): # convert modelfilter path to model path path = Gtk.TreePath.new_from_string(path) modelpath = self.modelfilter.convert_path_to_child_path(path) modelrow = self.model[modelpath] option = modelrow[0] if modelpath.get_depth() > 2: modelpath.up() # Get parent keyrow = self.model[modelpath] key = keyrow[0] modelpath.up() # Get parent optnamerow = self.model[modelpath] optname = optnamerow[0] self.remember_option(option + '\n' + key + '\n' + optname, modelrow[1], text) app.config.set_per(optname, key, option, text) else: self.remember_option(option, modelrow[1], text) app.config.set(option, text) modelrow[1] = text self.check_for_restart() @staticmethod def on_advanced_configuration_window_destroy(widget): del app.interface.instances['advanced_config'] def on_reset_button_clicked(self, widget): model, iter_ = self.treeview.get_selection().get_selected() # Check for GtkTreeIter if iter_: path = model.get_path(iter_) opt_path = self.get_option_path(model, iter_) if len(opt_path) == 1: default = app.config.get_default(opt_path[0]) elif len(opt_path) == 3: default = app.config.get_default_per(opt_path[2], opt_path[0]) if model[iter_][Column.TYPE] == self.types['boolean']: if self.right_true_dict[default] == model[iter_][Column.VALUE]: return modelpath = self.modelfilter.convert_path_to_child_path(path) modelrow = self.model[modelpath] option = modelrow[0] if len(modelpath) > 1: optnamerow = self.model[modelpath[0]] optname = optnamerow[0] keyrow = self.model[modelpath[:2]] key = keyrow[0] self.remember_option(option + '\n' + key + '\n' + optname, modelrow[Column.VALUE], default) app.config.set_per(optname, key, option, default) else: self.remember_option(option, modelrow[Column.VALUE], default) app.config.set(option, default) modelrow[Column.VALUE] = self.right_true_dict[default] self.check_for_restart() else: if str(default) == model[iter_][Column.VALUE]: return self.on_config_edited(None, path.to_string(), str(default)) def on_advanced_close_button_clicked(self, widget): self.window.destroy() def fill_model(self, node=None, parent=None): for item, option in app.config.get_children(node): name = item[-1] if option is None: # Node newparent = self.model.append(parent, [name, '', '']) self.fill_model(item, newparent) else: # Leaf if len(item) == 1: type_ = self.types[app.config.get_type(name)] elif len(item) == 3: type_ = self.types[app.config.get_type_per(item[0], item[2])] if name == 'password': value = _('Hidden') else: if type_ == self.types['boolean']: value = self.right_true_dict[option] else: try: value = str(option) except Exception: value = option self.model.append(parent, [name, value, type_]) def visible_func(self, model, treeiter, data): search_string = self.entry.get_text().lower() for it in tree_model_pre_order(model, treeiter): if model[it][Column.TYPE] != '': opt_path = self.get_option_path(model, it) if len(opt_path) == 3: desc = app.config.get_desc_per(opt_path[2], opt_path[0]) elif len(opt_path) == 1: desc = app.config.get_desc(opt_path[0]) if search_string in model[it][Column.NAME] or (desc and \ search_string in desc.lower()): return True return False @rate_limit(3) def on_advanced_entry_changed(self, widget): self.modelfilter.refilter() if not widget.get_text(): # Maybe the expanded rows should be remembered here ... self.treeview.collapse_all() else: # ... and be restored correctly here self.treeview.expand_all() gajim-gajim-1.1.3/gajim/gtk/bookmarks.py000066400000000000000000000355641345766322700201420ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gtk from gi.repository import Gdk from gajim.common import app from gajim.common import helpers from gajim.common.i18n import Q_ from gajim.common.i18n import _ from gajim import gui_menu_builder from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.util import get_builder class ManageBookmarksWindow: def __init__(self): self.xml = get_builder('manage_bookmarks_window.ui') self.window = self.xml.get_object('manage_bookmarks_window') self.window.set_transient_for(app.interface.roster.window) self.ignore_events = False # Account-JID, RoomName, Room-JID, Autojoin, Minimize, Password, Nick, # Show_Status self.treestore = Gtk.TreeStore(str, str, str, bool, bool, str, str, str, str) self.treestore.set_sort_column_id(1, Gtk.SortType.ASCENDING) # Store bookmarks in treeview. for account, account_label in app.get_enabled_accounts_with_labels( connected_only=True, private_storage_only=True): iter_ = self.treestore.append(None, [ None, account, None, None, None, None, None, None, account_label]) con = app.connections[account] bookmarks = con.get_module('Bookmarks').get_sorted_bookmarks() for jid, bookmark in bookmarks.items(): print_status = bookmark.get('print_status', '') if print_status not in ('', 'all', 'in_and_out', 'none'): print_status = '' self.treestore.append(iter_, [account, bookmark['name'], jid, bookmark['autojoin'], bookmark['minimize'], bookmark['password'], bookmark['nick'], print_status, bookmark['name']]) self.print_status_combobox = self.xml.get_object( 'print_status_combobox') model = Gtk.ListStore(str, str) self.option_list = { '': _('Default'), 'all': Q_('?print_status:All'), 'in_and_out': _('Enter and leave only'), 'none': Q_('?print_status:None')} for opt, label in sorted(self.option_list.items()): model.append([label, opt]) self.print_status_combobox.set_model(model) self.print_status_combobox.set_active(1) self.view = self.xml.get_object('bookmarks_treeview') self.view.set_model(self.treestore) self.view.expand_all() renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn('Bookmarks', renderer, text=8) self.view.append_column(column) self.selection = self.view.get_selection() self.selection.connect('changed', self.bookmark_selected) # Prepare input fields self.title_entry = self.xml.get_object('title_entry') self.title_entry.connect('changed', self.on_title_entry_changed) self.nick_entry = self.xml.get_object('nick_entry') self.nick_entry.connect('changed', self.on_nick_entry_changed) self.server_entry = self.xml.get_object('server_entry') self.server_entry.connect( 'focus-out-event', self.on_server_entry_focus_out) self.room_entry = self.xml.get_object('room_entry') self.room_entry_changed_id = self.room_entry.connect( 'changed', self.on_room_entry_changed) self.pass_entry = self.xml.get_object('pass_entry') self.pass_entry.connect('changed', self.on_pass_entry_changed) self.autojoin_checkbutton = self.xml.get_object('autojoin_checkbutton') self.minimize_checkbutton = self.xml.get_object('minimize_checkbutton') self.settings_box = self.xml.get_object('settings_box') self.remove_bookmark_button = self.xml.get_object( 'remove_bookmark_button') self.xml.connect_signals(self) self.window.show_all() # select root iter first_iter = self.treestore.get_iter_first() if first_iter: self.selection.select_iter(first_iter) def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def on_add_bookmark_button_clicked(self, widget): """ Add a new bookmark """ # Get the account that is currently used # (the parent of the currently selected item) (model, iter_) = self.selection.get_selected() if not iter_: # Nothing selected, do nothing return parent = model.iter_parent(iter_) if parent: # We got a bookmark selected, so we add_to the parent add_to = parent else: # No parent, so we got an account -> add to this. add_to = iter_ account = model[add_to][1] nick = app.nicks[account] label = _('New Group Chat') iter_ = self.treestore.append(add_to, [ account, label, '@', False, False, '', nick, 'in_and_out', label]) self.view.expand_row(model.get_path(add_to), True) self.view.set_cursor(model.get_path(iter_)) def on_remove_bookmark_button_clicked(self, widget): """ Remove selected bookmark """ (model, iter_) = self.selection.get_selected() if not iter_: # Nothing selected return if not model.iter_parent(iter_): # Don't remove account iters return self.ignore_events = True model.remove(iter_) self.selection.unselect_all() self.clear_fields() self.set_sensitive_all(False) self.ignore_events = False def check_valid_bookmark(self): """ Check if all necessary fields are entered correctly """ (model, iter_) = self.selection.get_selected() if not model.iter_parent(iter_): # Account data can't be changed return server = self.server_entry.get_text() room = self.room_entry.get_text() if server == '' or room == '': ErrorDialog( _('This bookmark has invalid data'), _('Please be sure to fill out server and room fields ' 'or remove this bookmark.')) return False return True def on_ok_button_clicked(self, widget): """ Parse the treestore data into our new bookmarks array, then send the new bookmarks to the server. """ (model, iter_) = self.selection.get_selected() if iter_ and model.iter_parent(iter_): # bookmark selected, check it if not self.check_valid_bookmark(): return for account in self.treestore: acct = account[1] con = app.connections[acct] con.get_module('Bookmarks').bookmarks = {} for bm in account.iterchildren(): # create the bookmark-dict bmdict = { 'name': bm[1], 'autojoin': bm[3], 'minimize': bm[4], 'password': bm[5], 'nick': bm[6], 'print_status': bm[7]} jid = bm[2] con.get_module('Bookmarks').bookmarks[jid] = bmdict con.get_module('Bookmarks').store_bookmarks() gui_menu_builder.build_bookmark_menu(acct) self.window.destroy() def on_cancel_button_clicked(self, widget): self.window.destroy() def bookmark_selected(self, selection): """ Fill in the bookmark's data into the fields. """ (model, iter_) = selection.get_selected() if not iter_: # After removing the last bookmark for one account # this will be None, so we will just: return if model.iter_parent(iter_): # make the fields sensitive self.set_sensitive_all(True) else: # Top-level has no data (it's the account fields) # clear fields & make them insensitive self.clear_fields() self.set_sensitive_all(False) return # Fill in the data for childs self.title_entry.set_text(model[iter_][1]) room_jid = model[iter_][2] room_jid_s = room_jid.split('@') if len(room_jid_s) == 1: room = '' server = room_jid else: (room, server) = room_jid_s self.room_entry.handler_block(self.room_entry_changed_id) self.room_entry.set_text(room) self.room_entry.handler_unblock(self.room_entry_changed_id) self.server_entry.set_text(server) self.autojoin_checkbutton.set_active(model[iter_][3]) self.minimize_checkbutton.set_active(model[iter_][4]) # sensitive only if auto join is checked self.minimize_checkbutton.set_sensitive(model[iter_][3]) if model[iter_][5] is not None: password = model[iter_][5] else: password = None if password: self.pass_entry.set_text(password) else: self.pass_entry.set_text('') nick = model[iter_][6] if nick: self.nick_entry.set_text(nick) else: self.nick_entry.set_text('') print_status = model[iter_][7] opts = sorted(self.option_list.keys()) self.print_status_combobox.set_active(opts.index(print_status)) def on_title_entry_changed(self, widget): if self.ignore_events: return (model, iter_) = self.selection.get_selected() if iter_: # After removing a bookmark, we got nothing selected if model.iter_parent(iter_): # Don't clear the title field for account nodes model[iter_][1] = self.title_entry.get_text() def on_nick_entry_changed(self, widget): if self.ignore_events: return (model, iter_) = self.selection.get_selected() if iter_: nick = self.nick_entry.get_text() try: nick = helpers.parse_resource(nick) except helpers.InvalidFormat: ErrorDialog( _('Invalid nickname'), _('Character not allowed'), transient_for=self.window) self.nick_entry.set_text(model[iter_][6]) return True model[iter_][6] = nick def on_server_entry_focus_out(self, widget, event): if self.ignore_events: return (model, iter_) = self.selection.get_selected() if not iter_: return server = widget.get_text() if not server: return if '@' in server: ErrorDialog( _('Invalid server'), _('Character not allowed'), transient_for=self.window) widget.set_text(server.replace('@', '')) room = self.room_entry.get_text().strip() if not room: return room_jid = room + '@' + server.strip() try: room_jid = helpers.parse_jid(room_jid) except helpers.InvalidFormat: ErrorDialog( _('Invalid server'), _('Character not allowed'), transient_for=self.window) self.server_entry.set_text(model[iter_][2].split('@')[1]) return True model[iter_][2] = room_jid def on_room_entry_changed(self, widget): if self.ignore_events: return (model, iter_) = self.selection.get_selected() if not iter_: return room = widget.get_text() if not room: return if '@' in room: room, server = room.split('@', 1) widget.set_text(room) if server: self.server_entry.set_text(server) self.server_entry.grab_focus() server = self.server_entry.get_text().strip() if not server: return room_jid = room.strip() + '@' + server try: room_jid = helpers.parse_jid(room_jid) except helpers.InvalidFormat: ErrorDialog( _('Invalid room'), _('Character not allowed'), transient_for=self.window) return True model[iter_][2] = room_jid def on_pass_entry_changed(self, widget): if self.ignore_events: return (model, iter_) = self.selection.get_selected() if iter_: model[iter_][5] = self.pass_entry.get_text() def on_autojoin_checkbutton_toggled(self, widget, *args): if self.ignore_events: return (model, iter_) = self.selection.get_selected() if iter_: model[iter_][3] = self.autojoin_checkbutton.get_active() self.minimize_checkbutton.set_sensitive(model[iter_][3]) def on_minimize_checkbutton_toggled(self, widget, *args): if self.ignore_events: return (model, iter_) = self.selection.get_selected() if iter_: model[iter_][4] = self.minimize_checkbutton.get_active() def on_print_status_combobox_changed(self, widget): if self.ignore_events: return active = widget.get_active() model = widget.get_model() print_status = model[active][1] (model2, iter_) = self.selection.get_selected() if iter_: model2[iter_][7] = print_status def clear_fields(self): widgets = [ self.title_entry, self.nick_entry, self.room_entry, self.server_entry, self.pass_entry] for field in widgets: field.set_text('') self.autojoin_checkbutton.set_active(False) self.minimize_checkbutton.set_active(False) self.print_status_combobox.set_active(1) def set_sensitive_all(self, sensitive): widgets = [ self.title_entry, self.nick_entry, self.room_entry, self.server_entry, self.pass_entry, self.settings_box, self.remove_bookmark_button] for field in widgets: field.set_sensitive(sensitive) gajim-gajim-1.1.3/gajim/gtk/const.py000066400000000000000000000014611345766322700172650ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # Constants for the gtk module from collections import namedtuple from enum import IntEnum, unique Filter = namedtuple('Filter', 'name pattern default') @unique class Theme(IntEnum): NOT_DARK = 0 DARK = 1 SYSTEM = 2 gajim-gajim-1.1.3/gajim/gtk/css_config.py000066400000000000000000000433071345766322700202610ustar00rootroot00000000000000# Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import math import logging import cssutils from gi.repository import Gtk from gi.repository import Gdk from gi.repository import Pango from gajim.common import app from gajim.common import configpaths from gajim.common.const import StyleAttr, CSSPriority from gajim.gtk.const import Theme log = logging.getLogger('gajim.gtk.css') settings = Gtk.Settings.get_default() class CSSConfig(): def __init__(self): """CSSConfig handles loading and storing of all relevant Gajim style files The order in which CSSConfig loads the styles 1. gajim.css 2. gajim-dark.css (Only if gtk-application-prefer-dark-theme = True) 3. default.css or default-dark.css (from gajim/data/style) 4. user-theme.css (from ~/.config/Gajim/theme) # gajim.css: This is the main style and the application default # gajim-dark.css Has only entrys which we want to override in gajim.css # default.css or default-dark.css Has all the values that are changeable via UI (see themes.py). Depending on `gtk-application-prefer-dark-theme` either default.css or default-dark.css gets loaded # user-theme.css These are the themes the Themes Dialog stores. Because they are loaded at last they overwrite everything else. Users should add custom css here.""" # Delete empty rules cssutils.ser.prefs.keepEmptyRules = False # Holds the currently selected theme in the Theme Editor self._pre_css = None self._pre_css_path = None # Holds the default theme, its used if values are not found # in the selected theme self._default_css = None self._default_css_path = None # Holds the currently selected theme self._css = None self._css_path = None # User Theme CSS Provider self._provider = Gtk.CssProvider() # Cache of recently requested values self._cache = {} # Holds all currently available themes self.themes = [] self.set_dark_theme() self._load_css() self._gather_available_themes() self._load_default() self._load_selected() self._activate_theme() Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), self._provider, CSSPriority.USER_THEME) @property def prefer_dark(self): setting = app.config.get('dark_theme') if setting == Theme.SYSTEM: if settings is None: return False return settings.get_property('gtk-application-prefer-dark-theme') return setting == Theme.DARK @staticmethod def set_dark_theme(value=None): if value is None: value = app.config.get('dark_theme') else: app.config.set('dark_theme', value) if settings is None: return if value == Theme.SYSTEM: settings.reset_property('gtk-application-prefer-dark-theme') return settings.set_property('gtk-application-prefer-dark-theme', bool(value)) def _load_css(self): self._load_css_from_file('gajim.css', CSSPriority.APPLICATION) if self.prefer_dark: self._load_css_from_file('gajim-dark.css', CSSPriority.APPLICATION_DARK) self._load_css_from_file('default.css', CSSPriority.DEFAULT_THEME) if self.prefer_dark: self._load_css_from_file('default-dark.css', CSSPriority.DEFAULT_THEME_DARK) def _load_css_from_file(self, filename, priority): path = os.path.join(configpaths.get('STYLE'), filename) try: with open(path, "r") as f: css = f.read() except Exception as exc: log.error('Error loading css: %s', exc) return self._activate_css(css, priority) def _activate_css(self, css, priority): try: provider = Gtk.CssProvider() provider.load_from_data(bytes(css.encode('utf-8'))) Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider, priority) except Exception: log.exception('Error loading application css') @staticmethod def _pango_to_css_weight(number): # Pango allows for weight values between 100 and 1000 # CSS allows only full hundred numbers like 100, 200 .. number = int(number) if number < 100: return 100 if number > 900: return 900 return int(math.ceil(number / 100.0)) * 100 def _gather_available_themes(self): files = os.listdir(configpaths.get('MY_THEME')) self.themes = [file[:-4] for file in files if file.endswith('.css')] if 'default' in self.themes: # Ignore user created themes that are named 'default' self.themes.remove('default') def get_theme_path(self, theme, user=True): if theme == 'default' and self.prefer_dark: theme = 'default-dark' if user: return os.path.join(configpaths.get('MY_THEME'), '%s.css' % theme) return os.path.join(configpaths.get('STYLE'), '%s.css' % theme) def _determine_theme_path(self): # Gets the path of the currently active theme. # If it does not exist, it falls back to the default theme theme = app.config.get('roster_theme') if theme == 'default': return self.get_theme_path(theme, user=False) theme_path = self.get_theme_path(theme) if not theme or not os.path.exists(theme_path): log.warning('Theme %s not found, fallback to default', theme) app.config.set('roster_theme', 'default') log.info('Use Theme: default') return self.get_theme_path('default', user=False) log.info('Use Theme: %s', theme) return theme_path def _load_selected(self, new_path=None): if new_path is None: self._css_path = self._determine_theme_path() else: self._css_path = new_path self._css = cssutils.parseFile(self._css_path) def _load_default(self): self._default_css_path = self.get_theme_path('default', user=False) self._default_css = cssutils.parseFile(self._default_css_path) def _load_pre(self, theme): log.info('Preload theme %s', theme) self._pre_css_path = self.get_theme_path(theme) self._pre_css = cssutils.parseFile(self._pre_css_path) def _write(self, pre): path = self._css_path css = self._css if pre: path = self._pre_css_path css = self._pre_css with open(path, 'w', encoding='utf-8') as file: file.write(css.cssText.decode('utf-8')) active = self._pre_css_path == self._css_path if not pre or active: self._load_selected() self._activate_theme() def set_value(self, selector, attr, value, pre=False): if attr == StyleAttr.FONT: # forward to set_font() for convenience return self.set_font(selector, value, pre) if isinstance(attr, StyleAttr): attr = attr.value css = self._css if pre: css = self._pre_css for rule in css: if rule.type != rule.STYLE_RULE: continue if rule.selectorText == selector: log.info('Set %s %s %s', selector, attr, value) rule.style[attr] = value if not pre: self._add_to_cache(selector, attr, value) self._write(pre) return # The rule was not found, so we add it to this theme log.info('Set %s %s %s', selector, attr, value) rule = cssutils.css.CSSStyleRule(selectorText=selector) rule.style[attr] = value css.add(rule) self._write(pre) def set_font(self, selector, description, pre=False): css = self._css if pre: css = self._pre_css family, size, style, weight = self._get_attr_from_description( description) for rule in css: if rule.type != rule.STYLE_RULE: continue if rule.selectorText == selector: log.info('Set Font for: %s %s %s %s %s', selector, family, size, style, weight) rule.style['font-family'] = family rule.style['font-style'] = style rule.style['font-size'] = '%spt' % size rule.style['font-weight'] = weight if not pre: self._add_to_cache( selector, 'fontdescription', description) self._write(pre) return # The rule was not found, so we add it to this theme log.info('Set Font for: %s %s %s %s %s', selector, family, size, style, weight) rule = cssutils.css.CSSStyleRule(selectorText=selector) rule.style['font-family'] = family rule.style['font-style'] = style rule.style['font-size'] = '%spt' % size rule.style['font-weight'] = weight css.add(rule) self._write(pre) def _get_attr_from_description(self, description): size = description.get_size() / Pango.SCALE style = self._get_string_from_pango_style(description.get_style()) weight = self._pango_to_css_weight(int(description.get_weight())) family = description.get_family() return family, size, style, weight def _get_default_rule(self, selector, attr): for rule in self._default_css: if rule.type != rule.STYLE_RULE: continue if rule.selectorText == selector: log.info('Get Default Rule %s', selector) return rule def get_font(self, selector, pre=False): if pre: css = self._pre_css else: css = self._css try: return self._get_from_cache(selector, 'fontdescription') except KeyError: pass if css is None: return for rule in css: if rule.type != rule.STYLE_RULE: continue if rule.selectorText == selector: log.info('Get Font for: %s', selector) style = rule.style.getPropertyValue('font-style') or None size = rule.style.getPropertyValue('font-size') or None weight = rule.style.getPropertyValue('font-weight') or None family = rule.style.getPropertyValue('font-family') or None desc = self._get_description_from_css( family, size, style, weight) if not pre: self._add_to_cache(selector, 'fontdescription', desc) return desc def _get_description_from_css(self, family, size, style, weight): if family is None: return desc = Pango.FontDescription() desc.set_family(family) if weight is not None: desc.set_weight(Pango.Weight(int(weight))) if style is not None: desc.set_style(self._get_pango_style_from_string(style)) if size is not None: desc.set_size(int(size[:-2]) * Pango.SCALE) return desc @staticmethod def _get_pango_style_from_string(style: str) -> int: if style == 'normal': return Pango.Style(0) if style == 'oblique': return Pango.Style(1) # Pango.Style.ITALIC: return Pango.Style(2) @staticmethod def _get_string_from_pango_style(style: Pango.Style) -> str: if style == Pango.Style.NORMAL: return 'normal' if style == Pango.Style.ITALIC: return 'italic' # Pango.Style.OBLIQUE: return 'oblique' def get_value(self, selector, attr, pre=False): if attr == StyleAttr.FONT: # forward to get_font() for convenience return self.get_font(selector, pre) if isinstance(attr, StyleAttr): attr = attr.value if pre: css = self._pre_css else: css = self._css try: return self._get_from_cache(selector, attr) except KeyError: pass if css is not None: for rule in css: if rule.type != rule.STYLE_RULE: continue if rule.selectorText == selector: log.info('Get %s %s: %s', selector, attr, rule.style[attr] or None) value = rule.style.getPropertyValue(attr) or None if not pre: self._add_to_cache(selector, attr, value) return value # We didnt find the selector in the selected theme # search in default theme if not pre: rule = self._get_default_rule(selector, attr) if rule is not None: self._add_to_cache(selector, attr, rule.style[attr]) return rule.style[attr] def remove_value(self, selector, attr, pre=False): if attr == StyleAttr.FONT: # forward to remove_font() for convenience return self.remove_font(selector, pre) if isinstance(attr, StyleAttr): attr = attr.value css = self._css if pre: css = self._pre_css for rule in css: if rule.type != rule.STYLE_RULE: continue if rule.selectorText == selector: log.info('Remove %s %s', selector, attr) rule.style.removeProperty(attr) break self._write(pre) def remove_font(self, selector, pre=False): css = self._css if pre: css = self._pre_css for rule in css: if rule.type != rule.STYLE_RULE: continue if rule.selectorText == selector: log.info('Remove Font from: %s', selector) rule.style.removeProperty('font-family') rule.style.removeProperty('font-size') rule.style.removeProperty('font-style') rule.style.removeProperty('font-weight') break self._write(pre) def change_theme(self, theme): user = not theme == 'default' theme_path = self.get_theme_path(theme, user=user) if not os.path.exists(theme_path): log.error('Change Theme: Theme %s does not exist', theme_path) return False self._load_selected(theme_path) self._activate_theme() app.config.set('roster_theme', theme) log.info('Change Theme: Successful switched to %s', theme) return True def change_preload_theme(self, theme): theme_path = self.get_theme_path(theme) if not os.path.exists(theme_path): log.error('Change Preload Theme: Theme %s does not exist', theme_path) return False self._load_pre(theme) log.info('Successful switched to %s', theme) return True def rename_theme(self, old_theme, new_theme): if old_theme not in self.themes: log.error('Rename Theme: Old theme %s not found', old_theme) return False if new_theme in self.themes: log.error('Rename Theme: New theme %s exists already', new_theme) return False old_theme_path = self.get_theme_path(old_theme) new_theme_path = self.get_theme_path(new_theme) os.rename(old_theme_path, new_theme_path) self.themes.remove(old_theme) self.themes.append(new_theme) self._load_pre(new_theme) log.info('Rename Theme: Successful renamed theme from %s to %s', old_theme, new_theme) return True def _activate_theme(self): log.info('Activate theme') self._invalidate_cache() self._provider.load_from_data(self._css.cssText) def add_new_theme(self, theme): theme_path = self.get_theme_path(theme) if os.path.exists(theme_path): log.error('Add Theme: %s exists already', theme_path) return False with open(theme_path, 'w', encoding='utf8'): pass self.themes.append(theme) log.info('Add Theme: Successful added theme %s', theme) return True def remove_theme(self, theme): theme_path = self.get_theme_path(theme) if os.path.exists(theme_path): os.remove(theme_path) self.themes.remove(theme) log.info('Remove Theme: Successful removed theme %s', theme) def _add_to_cache(self, selector, attr, value): self._cache[selector + attr] = value def _get_from_cache(self, selector, attr): return self._cache[selector + attr] def _invalidate_cache(self): self._cache = {} gajim-gajim-1.1.3/gajim/gtk/dataform.py000066400000000000000000000266211345766322700177410ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gtk from gi.repository import Pango class DataFormWidget(Gtk.ScrolledWindow): def __init__(self, form_node): Gtk.ScrolledWindow.__init__(self) self.set_hexpand(True) self.set_vexpand(True) self.get_style_context().add_class('data-form-widget') self._form_node = form_node self._form_grid = FormGrid(form_node) self.add(self._form_grid) @property def title(self): return self._form_grid.title @property def instructions(self): return self._form_grid.instructions def get_submit_form(self): self._form_node.type_ = 'submit' return self._form_node class FormGrid(Gtk.Grid): def __init__(self, form_node): Gtk.Grid.__init__(self) self.set_column_spacing(12) self.set_row_spacing(12) self.set_halign(Gtk.Align.CENTER) self.row_count = 0 self.rows = [] self._data_form = form_node self.title = None self.instructions = None self._fields = { 'boolean': BooleanField, 'fixed': FixedField, 'list-single': ListSingleField, 'list-multi': ListMultiField, 'jid-single': JidSingleField, 'jid-multi': JidMultiField, 'text-single': TextSingleField, 'text-private': TextPrivateField, 'text-multi': TextMultiField } if form_node.title is not None: self.title = form_node.title self.add_row(Title(form_node.title)) if form_node.instructions is not None: self.instructions = form_node.instructions self.add_row(Instructions(form_node.instructions)) self.parse_form(form_node) def add_row(self, field): field.add(self, self.row_count) self.row_count += 1 self.rows.append(field) def parse_form(self, form_node): for field in form_node.iter_fields(): if field.type_ == 'hidden': continue widget = self._fields[field.type_] self.add_row(widget(field)) def is_valid(self): return self._data_form.is_valid() class Title: def __init__(self, title): self._label = Gtk.Label(label=title) self._label.get_style_context().add_class('data-form-title') def add(self, form_grid, row_number): form_grid.attach(self._label, 0, row_number, 2, 1) class Instructions: def __init__(self, instructions): self._label = Gtk.Label(label=instructions) self._label.set_line_wrap(True) self._label.set_line_wrap_mode(Pango.WrapMode.WORD) def add(self, form_grid, row_number): form_grid.attach(self._label, 0, row_number, 2, 1) class Field: def __init__(self, field): self._field = field self._label = Gtk.Label(label=field.label) self._label.set_single_line_mode(False) self._label.set_line_wrap(True) self._label.set_line_wrap_mode(Pango.WrapMode.WORD) self._label.set_width_chars(15) self._label.set_size_request(100, -1) self._label.set_xalign(1) self._label.set_tooltip_text(field.description) def add(self, form_grid, row_number): form_grid.attach(self._label, 0, row_number, 1, 1) form_grid.attach_next_to( self._widget, self._label, Gtk.PositionType.RIGHT, 1, 1) class BooleanField(Field): def __init__(self, field): Field.__init__(self, field) self._widget = Gtk.CheckButton() self._widget.set_active(field.value) self._widget.connect('toggled', self._toggled) def _toggled(self, widget): self._field.value = self._widget.get_active() class FixedField(Field): def __init__(self, field): Field.__init__(self, field) self._label.set_text(field.value) # If the value is more than 30 chars it proabably isnt # meant as a section header if len(field.value) < 30: self._label.get_style_context().add_class('field-fixed') else: self._label.set_xalign(0.5) def add(self, form_grid, row_number): if len(self._field.value) < 30: form_grid.attach(self._label, 0, row_number, 1, 1) else: form_grid.attach(self._label, 0, row_number, 2, 1) class ListSingleField(Field): def __init__(self, field): Field.__init__(self, field) self._widget = Gtk.ComboBoxText() for value, label in field.iter_options(): if not label: label = value self._widget.append(value, label) self._widget.set_active_id(field.value) self._widget.connect('changed', self._changed) def _changed(self, widget): self._field.value = widget.get_active_id() class ListMultiField(Field): def __init__(self, field): Field.__init__(self, field) self._label.set_valign(Gtk.Align.START) self._treeview = ListMutliTreeView(field) self._widget = Gtk.ScrolledWindow() self._widget.set_propagate_natural_height(True) self._widget.set_min_content_height(100) self._widget.set_max_content_height(300) self._widget.add(self._treeview) class ListMutliTreeView(Gtk.TreeView): def __init__(self, field): Gtk.TreeView.__init__(self) self._field = field self._store = Gtk.ListStore(str, str, bool) col = Gtk.TreeViewColumn() cell = Gtk.CellRendererText() col.pack_start(cell, True) col.set_attributes(cell, text=0) self.append_column(col) col = Gtk.TreeViewColumn() cell = Gtk.CellRendererToggle() cell.set_activatable(True) cell.connect('toggled', self._toggled) col.pack_start(cell, True) col.set_attributes(cell, active=2) self.append_column(col) self.set_headers_visible(False) for option in field.options: # option = (label, value) self._store.append( [*option, option[1] in field.values]) self.set_model(self._store) def _toggled(self, renderer, path): iter_ = self._store.get_iter(path) current_value = self._store[iter_][2] self._store.set_value(iter_, 2, not current_value) self._set_values() def _set_values(self): values = [] for row in self.get_model(): if not row[2]: continue values.append(row[1]) self._field.values = values class JidMultiField(Field): def __init__(self, field): Field.__init__(self, field) self._label.set_valign(Gtk.Align.START) self._treeview = JidMutliTreeView(field) self._add_button = Gtk.Button.new_from_icon_name( 'list-add-symbolic', Gtk.IconSize.MENU) self._add_button.connect('clicked', self._add_clicked) self._add_button.set_halign(Gtk.Align.START) self._remove_button = Gtk.Button.new_from_icon_name( 'list-remove-symbolic', Gtk.IconSize.MENU) self._remove_button.connect('clicked', self._remove_clicked) self._remove_button.set_halign(Gtk.Align.START) self._button_box = Gtk.ButtonBox( orientation=Gtk.Orientation.HORIZONTAL) self._button_box.set_layout(Gtk.ButtonBoxStyle.START) self._button_box.add(self._add_button) self._button_box.add(self._remove_button) self._button_box.set_child_non_homogeneous(self._add_button, True) self._button_box.set_child_non_homogeneous(self._remove_button, True) self._widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self._widget.set_spacing(6) self._scrolled_window = Gtk.ScrolledWindow() self._scrolled_window.set_propagate_natural_height(True) self._scrolled_window.set_min_content_height(100) self._scrolled_window.set_max_content_height(300) self._scrolled_window.add(self._treeview) self._widget.pack_start(self._scrolled_window, True, True, 0) self._widget.pack_end(self._button_box, False, False, 0) def _add_clicked(self, widget): self._treeview.get_model().append(['']) def _remove_clicked(self, widget): mod, paths = self._treeview.get_selection().get_selected_rows() for path in paths: iter_ = mod.get_iter(path) self._treeview.get_model().remove(iter_) jids = [] for row in self._treeview.get_model(): if not row[0]: continue jids.append(row[0]) self._field.values = jids class JidMutliTreeView(Gtk.TreeView): def __init__(self, field): Gtk.TreeView.__init__(self) self._field = field self._store = Gtk.ListStore(str) col = Gtk.TreeViewColumn() cell = Gtk.CellRendererText() cell.set_property('editable', True) cell.set_property('placeholder-text', 'user@example.org') cell.connect('edited', self._jid_edited) col.pack_start(cell, True) col.set_attributes(cell, text=0) self.append_column(col) self.set_headers_visible(False) for value in field.values: self._store.append([value]) self.set_model(self._store) def _jid_edited(self, renderer, path, new_text): iter_ = self._store.get_iter(path) self._store.set_value(iter_, 0, new_text) self._set_values() def _set_values(self): jids = [] for row in self._store: if not row[0]: continue jids.append(row[0]) self._field.values = jids class TextSingleField(Field): def __init__(self, field): Field.__init__(self, field) self._widget = Gtk.Entry() self._widget.set_text(field.value) self._widget.connect('changed', self._changed) def _changed(self, widget): self._field.value = self._widget.get_text() class TextPrivateField(TextSingleField): def __init__(self, field): TextSingleField.__init__(self, field) self._widget.set_input_purpose(Gtk.InputPurpose.PASSWORD) self._widget.set_visibility(False) class JidSingleField(TextSingleField): def __init__(self, field): TextSingleField.__init__(self, field) class TextMultiField(Field): def __init__(self, field): Field.__init__(self, field) self._label.set_valign(Gtk.Align.START) self._widget = Gtk.ScrolledWindow() self._widget.set_propagate_natural_height(True) self._widget.set_min_content_height(100) self._widget.set_max_content_height(300) self._textview = Gtk.TextView() self._textview.get_buffer().set_text(field.value) self._textview.get_buffer().connect('changed', self._changed) self._widget.add(self._textview) def _changed(self, widget): self._field.value = widget.get_text(*widget.get_bounds(), False) gajim-gajim-1.1.3/gajim/gtk/dialogs.py000066400000000000000000001123031345766322700175570ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gtk from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.gtk.util import get_builder from gajim.gtk.util import load_icon class HigDialog(Gtk.MessageDialog): def __init__(self, parent, type_, buttons, pritext, sectext, on_response_ok=None, on_response_cancel=None, on_response_yes=None, on_response_no=None): self.call_cancel_on_destroy = True Gtk.MessageDialog.__init__(self, transient_for=parent, modal=True, destroy_with_parent=True, message_type=type_, buttons=buttons, text=pritext) self.format_secondary_markup(sectext) self.possible_responses = {Gtk.ResponseType.OK: on_response_ok, Gtk.ResponseType.CANCEL: on_response_cancel, Gtk.ResponseType.YES: on_response_yes, Gtk.ResponseType.NO: on_response_no} self.connect('response', self.on_response) self.connect('destroy', self.on_dialog_destroy) def on_response(self, dialog, response_id): if response_id not in self.possible_responses: return if not self.possible_responses[response_id]: self.destroy() elif isinstance(self.possible_responses[response_id], tuple): if len(self.possible_responses[response_id]) == 1: self.possible_responses[response_id][0](dialog) else: self.possible_responses[response_id][0](dialog, *self.possible_responses[response_id][1:]) else: self.possible_responses[response_id](dialog) def on_dialog_destroy(self, widget): if not self.call_cancel_on_destroy: return cancel_handler = self.possible_responses[Gtk.ResponseType.CANCEL] if not cancel_handler: return False if isinstance(cancel_handler, tuple): cancel_handler[0](None, *cancel_handler[1:]) else: cancel_handler(None) def popup(self): """ Show dialog """ vb = self.get_children()[0].get_children()[0] # Give focus to top vbox # vb.set_flags(Gtk.CAN_FOCUS) vb.grab_focus() self.show_all() class AspellDictError: def __init__(self, lang): ErrorDialog( _('Dictionary for language "%s" not available') % lang, _('You have to install the dictionary "%s" to use spellchecking, ' 'or choose another language by setting the speller_language ' 'option.\n\n' 'Highlighting misspelled words feature will not be used') % lang) class ConfirmationDialog(HigDialog): """ HIG compliant confirmation dialog """ def __init__(self, pritext, sectext='', on_response_ok=None, on_response_cancel=None, transient_for=None): self.user_response_ok = on_response_ok self.user_response_cancel = on_response_cancel HigDialog.__init__(self, transient_for, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, pritext, sectext, self.on_response_ok, self.on_response_cancel) self.popup() def on_response_ok(self, widget): if self.user_response_ok: if isinstance(self.user_response_ok, tuple): self.user_response_ok[0](*self.user_response_ok[1:]) else: self.user_response_ok() self.call_cancel_on_destroy = False self.destroy() def on_response_cancel(self, widget): if self.user_response_cancel: if isinstance(self.user_response_cancel, tuple): self.user_response_cancel[0](*self.user_response_ok[1:]) else: self.user_response_cancel() self.call_cancel_on_destroy = False self.destroy() class NonModalConfirmationDialog(HigDialog): """ HIG compliant non modal confirmation dialog """ def __init__(self, pritext, sectext='', on_response_ok=None, on_response_cancel=None): self.user_response_ok = on_response_ok self.user_response_cancel = on_response_cancel if hasattr(app.interface, 'roster') and app.interface.roster: parent = app.interface.roster.window else: parent = None HigDialog.__init__(self, parent, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, pritext, sectext, self.on_response_ok, self.on_response_cancel) self.set_modal(False) def on_response_ok(self, widget): if self.user_response_ok: if isinstance(self.user_response_ok, tuple): self.user_response_ok[0](*self.user_response_ok[1:]) else: self.user_response_ok() self.call_cancel_on_destroy = False self.destroy() def on_response_cancel(self, widget): if self.user_response_cancel: if isinstance(self.user_response_cancel, tuple): self.user_response_cancel[0](*self.user_response_cancel[1:]) else: self.user_response_cancel() self.call_cancel_on_destroy = False self.destroy() class WarningDialog(HigDialog): """ HIG compliant warning dialog """ def __init__(self, pritext, sectext='', transient_for=None): if not transient_for and hasattr(app.interface, 'roster') and \ app.interface.roster: transient_for = app.interface.roster.window HigDialog.__init__(self, transient_for, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, pritext, sectext) self.set_modal(False) self.popup() class InformationDialog(HigDialog): """ HIG compliant info dialog """ def __init__(self, pritext, sectext='', transient_for=None): if transient_for: parent = transient_for elif hasattr(app.interface, 'roster') and app.interface.roster: parent = app.interface.roster.window else: parent = None HigDialog.__init__(self, parent, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, pritext, sectext) self.set_modal(False) self.popup() class ErrorDialog(HigDialog): """ HIG compliant error dialog """ def __init__(self, pritext, sectext='', on_response_ok=None, on_response_cancel=None, transient_for=None): if transient_for: parent = transient_for elif hasattr(app.interface, 'roster') and app.interface.roster: parent = app.interface.roster.window else: parent = None HigDialog.__init__(self, parent, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, pritext, sectext, on_response_ok=on_response_ok, on_response_cancel=on_response_cancel) self.popup() class YesNoDialog(HigDialog): """ HIG compliant YesNo dialog """ def __init__(self, pritext, sectext='', checktext='', text_label=None, on_response_yes=None, on_response_no=None, type_=Gtk.MessageType.QUESTION, transient_for=None): self.user_response_yes = on_response_yes self.user_response_no = on_response_no if transient_for: parent = transient_for elif hasattr(app.interface, 'roster') and app.interface.roster: parent = app.interface.roster.window else: parent = None HigDialog.__init__(self, parent, type_, Gtk.ButtonsType.YES_NO, pritext, sectext, on_response_yes=self.on_response_yes, on_response_no=self.on_response_no) vbox = self.get_content_area() if checktext: self.checkbutton = Gtk.CheckButton.new_with_mnemonic(checktext) vbox.pack_start(self.checkbutton, False, True, 0) else: self.checkbutton = None if text_label: label = Gtk.Label(label=text_label) vbox.pack_start(label, False, True, 0) buff = Gtk.TextBuffer() self.textview = Gtk.TextView.new_with_buffer(buff) frame = Gtk.Frame() frame.set_shadow_type(Gtk.ShadowType.IN) frame.add(self.textview) vbox.pack_start(frame, False, True, 0) else: self.textview = None self.set_modal(False) self.popup() def on_response_yes(self, widget): if self.user_response_yes: if self.textview: buff = self.textview.get_buffer() start, end = buff.get_bounds() txt = self.textview.get_buffer().get_text(start, end, True) if isinstance(self.user_response_yes, tuple): if self.textview: self.user_response_yes[0](self.is_checked(), txt, *self.user_response_yes[1:]) else: self.user_response_yes[0](self.is_checked(), *self.user_response_yes[1:]) else: if self.textview: self.user_response_yes(self.is_checked(), txt) else: self.user_response_yes(self.is_checked()) self.call_cancel_on_destroy = False self.destroy() def on_response_no(self, widget): if self.user_response_no: if self.textview: buff = self.textview.get_buffer() start, end = buff.get_bounds() txt = self.textview.get_buffer().get_text(start, end, True) if isinstance(self.user_response_no, tuple): if self.textview: self.user_response_no[0](txt, *self.user_response_no[1:]) else: self.user_response_no[0](*self.user_response_no[1:]) else: if self.textview: self.user_response_no(txt) else: self.user_response_no() self.call_cancel_on_destroy = False self.destroy() def is_checked(self): """ Get active state of the checkbutton """ if not self.checkbutton: return False return self.checkbutton.get_active() class ConfirmationDialogCheck(ConfirmationDialog): """ HIG compliant confirmation dialog with checkbutton """ def __init__(self, pritext, sectext='', checktext='', on_response_ok=None, on_response_cancel=None, is_modal=True, transient_for=None): self.user_response_ok = on_response_ok self.user_response_cancel = on_response_cancel if transient_for: parent = transient_for elif hasattr(app.interface, 'roster') and app.interface.roster: parent = app.interface.roster.window else: parent = None HigDialog.__init__(self, parent, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, pritext, sectext, self.on_response_ok, self.on_response_cancel) self.set_default_response(Gtk.ResponseType.OK) ok_button = self.get_widget_for_response(Gtk.ResponseType.OK) ok_button.grab_focus() self.checkbutton = Gtk.CheckButton.new_with_mnemonic(checktext) self.get_content_area().pack_start(self.checkbutton, False, True, 0) self.set_modal(is_modal) self.popup() def on_response_ok(self, widget): if self.user_response_ok: if isinstance(self.user_response_ok, tuple): self.user_response_ok[0](self.is_checked(), *self.user_response_ok[1:]) else: self.user_response_ok(self.is_checked()) self.call_cancel_on_destroy = False self.destroy() def on_response_cancel(self, widget): if self.user_response_cancel: if isinstance(self.user_response_cancel, tuple): self.user_response_cancel[0](self.is_checked(), *self.user_response_cancel[1:]) else: self.user_response_cancel(self.is_checked()) self.call_cancel_on_destroy = False self.destroy() def is_checked(self): """ Get active state of the checkbutton """ return self.checkbutton.get_active() class ConfirmationDialogDoubleCheck(ConfirmationDialog): """ HIG compliant confirmation dialog with 2 checkbuttons """ def __init__(self, pritext, sectext='', checktext1='', checktext2='', tooltip1='', tooltip2='', on_response_ok=None, on_response_cancel=None, is_modal=True): self.user_response_ok = on_response_ok self.user_response_cancel = on_response_cancel if hasattr(app.interface, 'roster') and app.interface.roster: parent = app.interface.roster.window else: parent = None HigDialog.__init__(self, parent, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, pritext, sectext, self.on_response_ok, self.on_response_cancel) self.set_default_response(Gtk.ResponseType.OK) ok_button = self.get_widget_for_response(Gtk.ResponseType.OK) ok_button.grab_focus() vbox = self.get_content_area() if checktext1: self.checkbutton1 = Gtk.CheckButton.new_with_mnemonic(checktext1) if tooltip1: self.checkbutton1.set_tooltip_text(tooltip1) vbox.pack_start(self.checkbutton1, False, True, 0) else: self.checkbutton1 = None if checktext2: self.checkbutton2 = Gtk.CheckButton.new_with_mnemonic(checktext2) if tooltip2: self.checkbutton2.set_tooltip_text(tooltip2) vbox.pack_start(self.checkbutton2, False, True, 0) else: self.checkbutton2 = None self.set_modal(is_modal) self.popup() def on_response_ok(self, widget): if self.user_response_ok: if isinstance(self.user_response_ok, tuple): self.user_response_ok[0](self.is_checked(), *self.user_response_ok[1:]) else: self.user_response_ok(self.is_checked()) self.call_cancel_on_destroy = False self.destroy() def on_response_cancel(self, widget): if self.user_response_cancel: if isinstance(self.user_response_cancel, tuple): self.user_response_cancel[0](*self.user_response_cancel[1:]) else: self.user_response_cancel() self.call_cancel_on_destroy = False self.destroy() def is_checked(self): ''' Get active state of the checkbutton ''' if self.checkbutton1: is_checked_1 = self.checkbutton1.get_active() else: is_checked_1 = False if self.checkbutton2: is_checked_2 = self.checkbutton2.get_active() else: is_checked_2 = False return [is_checked_1, is_checked_2] class PlainConnectionDialog(ConfirmationDialogDoubleCheck): """ Dialog that is shown when using an insecure connection """ def __init__(self, account, on_ok, on_cancel): pritext = _('Insecure connection') sectext = _('You are about to connect to the account %(account)s ' '(%(server)s) insecurely. This means conversations will not be ' 'encrypted, and is strongly discouraged.\nAre you sure you want ' 'to do that?') % {'account': account, 'server': app.get_hostname_from_account(account)} checktext1 = _('Yes, I really want to connect insecurely') tooltip1 = _('Gajim will NOT connect unless you check this box') checktext2 = _('_Do not ask me again') ConfirmationDialogDoubleCheck.__init__(self, pritext, sectext, checktext1, checktext2, tooltip1=tooltip1, on_response_ok=on_ok, on_response_cancel=on_cancel, is_modal=False) self.ok_button = self.get_widget_for_response(Gtk.ResponseType.OK) self.ok_button.set_sensitive(False) self.checkbutton1.connect('clicked', self.on_checkbutton_clicked) self.set_title(_('Insecure connection')) def on_checkbutton_clicked(self, widget): self.ok_button.set_sensitive(widget.get_active()) class ConfirmationDialogDoubleRadio(ConfirmationDialog): """ HIG compliant confirmation dialog with 2 radios """ def __init__(self, pritext, sectext='', radiotext1='', radiotext2='', on_response_ok=None, on_response_cancel=None, is_modal=True, transient_for=None): self.user_response_ok = on_response_ok self.user_response_cancel = on_response_cancel if transient_for is None: transient_for = app.app.get_active_window() HigDialog.__init__(self, transient_for, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, pritext, sectext, self.on_response_ok, self.on_response_cancel) self.set_default_response(Gtk.ResponseType.OK) ok_button = self.get_widget_for_response(Gtk.ResponseType.OK) ok_button.grab_focus() vbox = self.get_content_area() self.radiobutton1 = Gtk.RadioButton(label=radiotext1) vbox.pack_start(self.radiobutton1, False, True, 0) self.radiobutton2 = Gtk.RadioButton(group=self.radiobutton1, label=radiotext2) vbox.pack_start(self.radiobutton2, False, True, 0) self.set_modal(is_modal) self.popup() def on_response_ok(self, widget): if self.user_response_ok: if isinstance(self.user_response_ok, tuple): self.user_response_ok[0](self.is_checked(), *self.user_response_ok[1:]) else: self.user_response_ok(self.is_checked()) self.call_cancel_on_destroy = False self.destroy() def on_response_cancel(self, widget): if self.user_response_cancel: if isinstance(self.user_response_cancel, tuple): self.user_response_cancel[0](*self.user_response_cancel[1:]) else: self.user_response_cancel() self.call_cancel_on_destroy = False self.destroy() def is_checked(self): ''' Get active state of the checkbutton ''' if self.radiobutton1: is_checked_1 = self.radiobutton1.get_active() else: is_checked_1 = False if self.radiobutton2: is_checked_2 = self.radiobutton2.get_active() else: is_checked_2 = False return [is_checked_1, is_checked_2] class FTOverwriteConfirmationDialog(ConfirmationDialog): """ HIG compliant confirmation dialog to overwrite or resume a file transfert """ def __init__(self, pritext, sectext='', propose_resume=True, on_response=None, transient_for=None): if transient_for: parent = transient_for elif hasattr(app.interface, 'roster') and app.interface.roster: parent = app.interface.roster.window else: parent = None HigDialog.__init__(self, parent, Gtk.MessageType.QUESTION, Gtk.ButtonsType.CANCEL, pritext, sectext) self.on_response = on_response if propose_resume: b = Gtk.Button(label='', stock=Gtk.STOCK_REFRESH) align = b.get_children()[0] hbox = align.get_children()[0] label = hbox.get_children()[1] label.set_text(_('_Resume')) label.set_use_underline(True) self.add_action_widget(b, 100) b = Gtk.Button(label='', stock=Gtk.STOCK_SAVE_AS) align = b.get_children()[0] hbox = align.get_children()[0] label = hbox.get_children()[1] label.set_text(_('Re_place')) label.set_use_underline(True) self.add_action_widget(b, 200) self.connect('response', self.on_dialog_response) self.show_all() def on_dialog_response(self, dialog, response): if self.on_response: if isinstance(self.on_response, tuple): self.on_response[0](response, *self.on_response[1:]) else: self.on_response(response) self.call_cancel_on_destroy = False self.destroy() class CommonInputDialog: """ Common Class for Input dialogs """ def __init__(self, title, label_str, is_modal, ok_handler, cancel_handler, transient_for=None): self.dialog = self.xml.get_object('input_dialog') label = self.xml.get_object('label') self.dialog.set_title(title) label.set_markup(label_str) self.cancel_handler = cancel_handler self.vbox = self.xml.get_object('vbox') if transient_for: self.dialog.set_transient_for(transient_for) else: self.dialog.set_transient_for(app.interface.roster.window) self.ok_handler = ok_handler okbutton = self.xml.get_object('okbutton') okbutton.connect('clicked', self.on_okbutton_clicked) cancelbutton = self.xml.get_object('cancelbutton') cancelbutton.connect('clicked', self.on_cancelbutton_clicked) self.xml.connect_signals(self) self.dialog.show_all() def on_input_dialog_destroy(self, widget): if self.cancel_handler: self.cancel_handler() def on_okbutton_clicked(self, widget): user_input = self.get_text() if user_input: user_input = user_input self.cancel_handler = None self.dialog.destroy() if isinstance(self.ok_handler, tuple): self.ok_handler[0](user_input, *self.ok_handler[1:]) else: self.ok_handler(user_input) def on_cancelbutton_clicked(self, widget): self.dialog.destroy() def destroy(self): self.dialog.destroy() class InputDialog(CommonInputDialog): """ Class for Input dialog """ def __init__(self, title, label_str, input_str=None, is_modal=True, ok_handler=None, cancel_handler=None, transient_for=None): self.xml = get_builder('input_dialog.ui') CommonInputDialog.__init__(self, title, label_str, is_modal, ok_handler, cancel_handler, transient_for=transient_for) self.input_entry = self.xml.get_object('input_entry') if input_str: self.set_entry(input_str) def on_input_dialog_delete_event(self, widget, event): ''' may be implemented by subclasses ''' pass def set_entry(self, value): self.input_entry.set_text(value) self.input_entry.select_region(0, -1) # select all def get_text(self): return self.input_entry.get_text() class InputDialogCheck(InputDialog): """ Class for Input dialog """ def __init__(self, title, label_str, checktext='', input_str=None, is_modal=True, ok_handler=None, cancel_handler=None, transient_for=None): self.xml = get_builder('input_dialog.ui') InputDialog.__init__(self, title, label_str, input_str=input_str, is_modal=is_modal, ok_handler=ok_handler, cancel_handler=cancel_handler, transient_for=transient_for) self.input_entry = self.xml.get_object('input_entry') if input_str: self.input_entry.set_text(input_str) self.input_entry.select_region(0, -1) # select all if checktext: self.checkbutton = Gtk.CheckButton.new_with_mnemonic(checktext) self.vbox.pack_start(self.checkbutton, False, True, 0) self.checkbutton.show() def on_okbutton_clicked(self, widget): user_input = self.get_text() if user_input: user_input = user_input self.cancel_handler = None self.dialog.destroy() if isinstance(self.ok_handler, tuple): self.ok_handler[0](user_input, self.is_checked(), *self.ok_handler[1:]) else: self.ok_handler(user_input, self.is_checked()) def get_text(self): return self.input_entry.get_text() def is_checked(self): """ Get active state of the checkbutton """ try: return self.checkbutton.get_active() except Exception: # There is no checkbutton return False class ChangeNickDialog(InputDialogCheck): """ Class for changing room nickname in case of conflict """ def __init__(self, account, room_jid, title, prompt, check_text=None, change_nick=False, transient_for=None): """ change_nick must be set to True when we are already occupant of the room and we are changing our nick """ InputDialogCheck.__init__(self, title, '', input_str='', is_modal=True, ok_handler=None, cancel_handler=None, transient_for=transient_for) self.room_queue = [(account, room_jid, prompt, change_nick)] self.check_next() def on_input_dialog_delete_event(self, widget, event): self.on_cancelbutton_clicked(widget) return True def setup_dialog(self): self.gc_control = app.interface.msg_win_mgr.get_gc_control( self.room_jid, self.account) if not self.gc_control and \ self.room_jid in app.interface.minimized_controls[self.account]: self.gc_control = \ app.interface.minimized_controls[self.account][self.room_jid] if not self.gc_control: self.check_next() return label = self.xml.get_object('label') label.set_markup(self.prompt) self.set_entry(self.gc_control.nick + \ app.config.get('gc_proposed_nick_char')) def check_next(self): if not self.room_queue: self.cancel_handler = None self.dialog.destroy() if 'change_nick_dialog' in app.interface.instances: del app.interface.instances['change_nick_dialog'] return self.account, self.room_jid, self.prompt, self.change_nick = \ self.room_queue.pop(0) self.setup_dialog() self.dialog.show() def on_okbutton_clicked(self, widget): nick = self.get_text() if nick: nick = nick # send presence to room try: nick = helpers.parse_resource(nick) except Exception: # invalid char ErrorDialog(_('Invalid nickname'), _('The nickname contains invalid characters.')) return self.on_ok(nick, self.is_checked()) def on_ok(self, nick, is_checked): app.connections[self.account].join_gc(nick, self.room_jid, None, change_nick=self.change_nick) if app.gc_connected[self.account][self.room_jid]: # We are changing nick, we will change self.nick when we receive # presence that inform that it works self.gc_control.new_nick = nick else: # We are connecting, we will not get a changed nick presence so # change it NOW. We don't already have a nick so it's harmless self.gc_control.nick = nick self.check_next() def on_cancelbutton_clicked(self, widget): self.gc_control.new_nick = '' self.check_next() def add_room(self, account, room_jid, prompt, change_nick=False): if (account, room_jid, prompt, change_nick) not in self.room_queue: self.room_queue.append((account, room_jid, prompt, change_nick)) class InputTextDialog(CommonInputDialog): """ Class for multilines Input dialog (more place than InputDialog) """ def __init__(self, title, label_str, input_str=None, is_modal=True, ok_handler=None, cancel_handler=None, transient_for=None): self.xml = get_builder('input_text_dialog.ui') CommonInputDialog.__init__(self, title, label_str, is_modal, ok_handler, cancel_handler, transient_for=transient_for) self.input_buffer = self.xml.get_object('input_textview').get_buffer() if input_str: self.input_buffer.set_text(input_str) start_iter, end_iter = self.input_buffer.get_bounds() self.input_buffer.select_range(start_iter, end_iter) # select all def get_text(self): start_iter, end_iter = self.input_buffer.get_bounds() return self.input_buffer.get_text(start_iter, end_iter, True) class DoubleInputDialog: """ Class for Double Input dialog """ def __init__(self, title, label_str1, label_str2, input_str1=None, input_str2=None, is_modal=True, ok_handler=None, cancel_handler=None, transient_for=None): self.xml = get_builder('dubbleinput_dialog.ui') self.dialog = self.xml.get_object('dubbleinput_dialog') label1 = self.xml.get_object('label1') self.input_entry1 = self.xml.get_object('input_entry1') label2 = self.xml.get_object('label2') self.input_entry2 = self.xml.get_object('input_entry2') self.dialog.set_title(title) label1.set_markup(label_str1) label2.set_markup(label_str2) self.cancel_handler = cancel_handler if input_str1: self.input_entry1.set_text(input_str1) self.input_entry1.select_region(0, -1) # select all if input_str2: self.input_entry2.set_text(input_str2) self.input_entry2.select_region(0, -1) # select all if transient_for: self.dialog.set_transient_for(transient_for) self.dialog.set_modal(is_modal) self.ok_handler = ok_handler okbutton = self.xml.get_object('okbutton') okbutton.connect('clicked', self.on_okbutton_clicked) cancelbutton = self.xml.get_object('cancelbutton') cancelbutton.connect('clicked', self.on_cancelbutton_clicked) self.xml.connect_signals(self) self.dialog.show_all() def on_dubbleinput_dialog_destroy(self, widget): if not self.cancel_handler: return False if isinstance(self.cancel_handler, tuple): self.cancel_handler[0](*self.cancel_handler[1:]) else: self.cancel_handler() def on_okbutton_clicked(self, widget): user_input1 = self.input_entry1.get_text() user_input2 = self.input_entry2.get_text() self.cancel_handler = None self.dialog.destroy() if not self.ok_handler: return if isinstance(self.ok_handler, tuple): self.ok_handler[0](user_input1, user_input2, *self.ok_handler[1:]) else: self.ok_handler(user_input1, user_input2) def on_cancelbutton_clicked(self, widget): self.dialog.destroy() if not self.cancel_handler: return if isinstance(self.cancel_handler, tuple): self.cancel_handler[0](*self.cancel_handler[1:]) else: self.cancel_handler() class CertificatDialog(InformationDialog): def __init__(self, parent, account, cert): issuer = cert.get_issuer() subject = cert.get_subject() InformationDialog.__init__(self, _('Certificate for account %s') % account, _('''Issued to: Common Name (CN): %(scn)s Organization (O): %(sorg)s Organizationl Unit (OU): %(sou)s Serial Number: %(sn)s Issued by: Common Name (CN): %(icn)s Organization (O): %(iorg)s Organizationl Unit (OU): %(iou)s Validity: Issued on: %(io)s Expires on: %(eo)s Fingerprint SHA-1 Fingerprint: %(sha1)s SHA-256 Fingerprint: %(sha256)s ''') % { 'scn': subject.commonName, 'sorg': subject.organizationName, 'sou': subject.organizationalUnitName, 'sn': cert.get_serial_number(), 'icn': issuer.commonName, 'iorg': issuer.organizationName, 'iou': issuer.organizationalUnitName, 'io': cert.get_notBefore().decode('utf-8'), 'eo': cert.get_notAfter().decode('utf-8'), 'sha1': cert.digest('sha1').decode('utf-8'), 'sha256': cert.digest('sha256').decode('utf-8')}) surface = load_icon('application-certificate', self, size=32) if surface is not None: img = Gtk.Image.new_from_surface(surface) img.show_all() self.set_image(img) self.set_transient_for(parent) self.set_title(_('Certificate for account %s') % account) class SSLErrorDialog(ConfirmationDialogDoubleCheck): def __init__(self, account, certificate, pritext, sectext, checktext1, checktext2, on_response_ok=None, on_response_cancel=None): self.account = account self.cert = certificate ConfirmationDialogDoubleCheck.__init__( self, pritext, sectext, checktext1, checktext2, on_response_ok=on_response_ok, on_response_cancel=on_response_cancel, is_modal=False) b = Gtk.Button(_('View certificate…')) b.connect('clicked', self.on_cert_clicked) b.show_all() area = self.get_action_area() area.pack_start(b, True, True, 0) def on_cert_clicked(self, button): CertificatDialog(self, self.account, self.cert) class ChangePasswordDialog(Gtk.Dialog): def __init__(self, account, success_cb, transient_for): flags = Gtk.DialogFlags.DESTROY_WITH_PARENT super().__init__(_('Change Password'), None, flags) self._account = account self._success_cb = success_cb self._builder = get_builder('change_password_dialog.ui') self.get_content_area().add( self._builder.get_object('change_password_box')) self._password1_entry = self._builder.get_object('password1_entry') self._password2_entry = self._builder.get_object('password2_entry') self._error_label = self._builder.get_object('error_label') self.set_transient_for(transient_for) self.add_button(_('_OK'), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.get_style_context().add_class('dialog-margin') self.connect('response', self._on_dialog_response) self.show_all() def _on_dialog_response(self, dialog, response): if response != Gtk.ResponseType.OK: self.destroy() return password1 = self._password1_entry.get_text() if not password1: self._error_label.set_text(_('You must enter a password')) return password2 = self._password2_entry.get_text() if password1 != password2: self._error_label.set_text(_('Passwords do not match')) return self._password1_entry.set_sensitive(False) self._password2_entry.set_sensitive(False) con = app.connections[self._account] con.get_module('Register').change_password( password1, self._on_success, self._on_error) def _on_success(self): self._success_cb(self._password1_entry.get_text()) self.destroy() def _on_error(self, error_text): self._error_label.set_text(error_text) self._password1_entry.set_sensitive(True) self._password2_entry.set_sensitive(True) class NewConfirmationDialog(Gtk.MessageDialog): def __init__(self, text, sec_text, buttons, transient_for=None): Gtk.MessageDialog.__init__(self, transient_for=transient_for, message_type=Gtk.MessageType.QUESTION, text=text) self._buttons = buttons for response, button in buttons.items(): self.add_button(button.text, response) if button.action is not None: widget = self.get_widget_for_response(response) widget.get_style_context().add_class(button.action.value) self.format_secondary_markup(sec_text) self.connect('response', self._on_response) self.run() def _on_response(self, dialog, response): if response == Gtk.ResponseType.DELETE_EVENT: # Look if DELETE_EVENT is mapped to another response response = self._buttons.get(response, None) if response is None: # If DELETE_EVENT was not mapped we assume CANCEL response = Gtk.ResponseType.CANCEL button = self._buttons.get(response, None) if button is None: self.destroy() return if button.callback is not None: button.callback() self.destroy() class ShortcutsWindow: def __init__(self): transient = app.app.get_active_window() builder = get_builder('shortcuts_window.ui') self.window = builder.get_object('shortcuts_window') self.window.connect('destroy', self._on_window_destroy) self.window.set_transient_for(transient) self.window.show_all() self.window.present() def _on_window_destroy(self, widget): self.window = None gajim-gajim-1.1.3/gajim/gtk/emoji_chooser.py000066400000000000000000000337661345766322700210010ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys import logging import weakref from collections import OrderedDict from gi.repository import Gtk from gi.repository import GLib from gi.repository import GdkPixbuf from gi.repository import Pango from gajim.common import app from gajim.common import helpers from gajim.common import configpaths from gajim.gtk.util import get_builder from gajim.gtk.emoji_data import emoji_data from gajim.gtk.emoji_data import emoji_pixbufs from gajim.gtk.emoji_data import Emoji MODIFIER_MAX_CHILDREN_PER_LINE = 6 MAX_CHILDREN_PER_LINE = 10 log = logging.getLogger('gajim.emoji') class Section(Gtk.Box): def __init__(self, name, search_entry, press_cb, chooser): Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL) self._chooser = chooser self._press_cb = press_cb self.pixbuf_generator = None self.heading = Gtk.Label(label=name) self.heading.set_halign(Gtk.Align.START) self.heading.get_style_context().add_class('emoji-chooser-heading') self.add(self.heading) self.flowbox = Gtk.FlowBox() self.flowbox.get_style_context().add_class('emoji-chooser-flowbox') self.flowbox.set_max_children_per_line(MAX_CHILDREN_PER_LINE) self.flowbox.set_filter_func(self._filter_func, search_entry) self.flowbox.connect('child-activated', press_cb) self.add(self.flowbox) self.show_all() def _filter_func(self, child, search_entry): name = search_entry.get_text() if not name: self.show() return True if name in child.desc: self.show() return True return False def add_emoji(self, codepoint, attrs): # Return always True, this method is used for the emoji factory # called by GLib.idle_add() pixbuf = self._get_next_pixbuf() variations = attrs.get('variations', None) if variations is None: if pixbuf is None: return True self.flowbox.add(EmojiChild(codepoint, pixbuf, attrs['desc'])) if pixbuf != 'font': # We save the pixbuf for fast access if we need to # replace a codepoint in the textview emoji_pixbufs[codepoint] = pixbuf else: if pixbuf is not None: chooser = ModifierChooser() # Iterate over the variations and add the codepoints for codepoint_ in variations.keys(): pixbuf_ = self._get_next_pixbuf() if pixbuf_ is None: continue if pixbuf_ == 'font': if not self._chooser._font_supports_codepoint( codepoint_): continue else: emoji_pixbufs[codepoint_] = pixbuf_ # Only codepoints are added which the # font or theme supports chooser.add_emoji(codepoint_, pixbuf_) # Check if we successfully added codepoints with modifiers if chooser.has_child: # If we have children then add a button # and set the popover child = EmojiModifierChild( codepoint, pixbuf, attrs['desc']) child.button.set_popover(chooser) chooser.flowbox.connect( 'child-activated', self._press_cb) else: # If no children were added, destroy the chooser # and add a EmojiChild instead of a EmojiModifierChild chooser.destroy() child = EmojiChild(codepoint, pixbuf, attrs['desc']) if pixbuf != 'font': emoji_pixbufs[codepoint] = pixbuf self.flowbox.add(child) else: # We dont have a image for the base codepoint # so skip all modifiers of it for _entry in variations: pixbuf = self._get_next_pixbuf() return True def clear_emojis(self): def _remove_emoji(emoji): self.flowbox.remove(emoji) emoji.destroy() self.flowbox.foreach(_remove_emoji) def _get_next_pixbuf(self): if self.pixbuf_generator is None: return 'font' return next(self.pixbuf_generator, False) class EmojiChild(Gtk.FlowBoxChild): def __init__(self, codepoint, pixbuf, desc): Gtk.FlowBoxChild.__init__(self) self.desc = desc self.codepoint = codepoint self.pixbuf = pixbuf if pixbuf == 'font': self.add(Gtk.Label(label=codepoint)) else: self.add(Gtk.Image.new_from_pixbuf(pixbuf)) self.set_tooltip_text(desc) self.show_all() def get_emoji(self): if self.pixbuf != 'font': pixbuf = self.get_child().get_pixbuf() pixbuf = pixbuf.scale_simple(Emoji.INPUT_SIZE, Emoji.INPUT_SIZE, GdkPixbuf.InterpType.HYPER) return self.codepoint, pixbuf return self.codepoint, None class EmojiModifierChild(Gtk.FlowBoxChild): def __init__(self, codepoint, pixbuf, desc): Gtk.FlowBoxChild.__init__(self) self.desc = desc self.codepoint = codepoint self.pixbuf = pixbuf self.button = Gtk.MenuButton() self.button.set_relief(Gtk.ReliefStyle.NONE) self.button.connect('button-press-event', self._button_press) if pixbuf == 'font': self.button.remove(self.button.get_child()) label = Gtk.Label(label=codepoint) self.button.add(label) else: self.button.get_child().set_from_pixbuf(pixbuf) self.set_tooltip_text(desc) self.add(self.button) self.show_all() def _button_press(self, button, event): if event.button == 3: button.get_popover().show() button.get_popover().get_child().unselect_all() return True if event.button == 1: self.get_parent().emit('child-activated', self) return True def get_emoji(self): if self.pixbuf != 'font': pixbuf = self.button.get_child().get_pixbuf() pixbuf = pixbuf.scale_simple(Emoji.INPUT_SIZE, Emoji.INPUT_SIZE, GdkPixbuf.InterpType.HYPER) return self.codepoint, pixbuf return self.codepoint, None class ModifierChooser(Gtk.Popover): def __init__(self): Gtk.Popover.__init__(self) self.set_name('EmoticonPopover') self._has_child = False self.flowbox = Gtk.FlowBox() self.flowbox.get_style_context().add_class( 'emoji-modifier-chooser-flowbox') self.flowbox.set_size_request(200, -1) self.flowbox.set_max_children_per_line(MODIFIER_MAX_CHILDREN_PER_LINE) self.flowbox.show() self.add(self.flowbox) @property def has_child(self): return self._has_child def add_emoji(self, codepoint, pixbuf): self.flowbox.add(EmojiChild(codepoint, pixbuf, None)) self._has_child = True class EmojiChooser(Gtk.Popover): _section_names = [ 'Smileys & People', 'Animals & Nature', 'Food & Drink', 'Travel & Places', 'Activities', 'Objects', 'Symbols', 'Flags' ] def __init__(self): super().__init__() self.set_name('EmoticonPopover') self._text_widget = None self._load_source_id = None self._pango_layout = Pango.Layout(self.get_pango_context()) self._builder = get_builder('emoji_chooser.ui') self._search = self._builder.get_object('search') self._stack = self._builder.get_object('stack') self._sections = OrderedDict() for name in self._section_names: self._sections[name] = Section( name, self._search, self._on_emoticon_press, self) section_box = self._builder.get_object('section_box') for section in self._sections.values(): section_box.add(section) self.add(self._builder.get_object('box')) self.connect('key-press-event', self._key_press) self._builder.connect_signals(self) self.show_all() @property def text_widget(self): return self._text_widget @text_widget.setter def text_widget(self, value): # Hold only a weak reference so if we can destroy # the ChatControl self._text_widget = weakref.ref(value) def _key_press(self, widget, event): return self._search.handle_event(event) def _search_changed(self, entry): for section in self._sections.values(): section.hide() section.flowbox.invalidate_filter() self._switch_stack() def _clear_sections(self): for section in self._sections.values(): section.clear_emojis() def _switch_stack(self): for section in self._sections.values(): if section.is_visible(): self._stack.set_visible_child_name('list') return self._stack.set_visible_child_name('not-found') def _get_current_theme(self): theme = app.config.get('emoticons_theme') themes = helpers.get_available_emoticon_themes() if theme not in themes: if sys.platform not in ('win32', 'darwin'): app.config.set('emoticons_theme', 'font') theme = 'font' else: # Win/Mac fallback to noto app.config.set('emoticons_theme', 'noto') theme = 'noto' return theme @staticmethod def _get_emoji_theme_path(theme): if theme == 'font': return 'font' emoticons_data_path = os.path.join(configpaths.get('EMOTICONS'), theme, '%s.png' % theme) if os.path.exists(emoticons_data_path): return emoticons_data_path emoticons_user_path = os.path.join(configpaths.get('MY_EMOTS'), '%s.png' % theme) if os.path.exists(emoticons_user_path): return emoticons_user_path log.warning('Could not find emoji theme: %s', theme) def load(self): theme = self._get_current_theme() path = self._get_emoji_theme_path(theme) if not theme or path is None: self._clear_sections() emoji_pixbufs.clear() return # Attach pixbuf generator pixbuf_generator = None if theme != 'font': pixbuf_generator = self._get_next_pixbuf(path) for section in self._sections.values(): section.pixbuf_generator = pixbuf_generator if self._load_source_id is not None: GLib.source_remove(self._load_source_id) # When we change emoji theme self._clear_sections() emoji_pixbufs.clear() factory = self._emoji_factory(theme == 'font') self._load_source_id = GLib.idle_add(lambda: next(factory, False), priority=GLib.PRIORITY_LOW) def _emoji_factory(self, font): for codepoint, attrs in emoji_data.items(): if not attrs['fully-qualified']: # We dont add these to the UI continue if font and not self._font_supports_codepoint(codepoint): continue section = self._sections[attrs['group']] yield section.add_emoji(codepoint, attrs) self._load_source_id = None emoji_pixbufs.complete = True def _font_supports_codepoint(self, codepoint): self._pango_layout.set_text(codepoint, -1) if self._pango_layout.get_unknown_glyphs_count(): return False if len(codepoint) > 1: # The font supports each of the codepoints # Check if the rendered glyph is more than one char if self._pango_layout.get_size()[0] > 19000: return False return True def _get_next_pixbuf(self, path): src_x = src_y = cur_column = 0 atlas = GdkPixbuf.Pixbuf.new_from_file(path) while True: src_x = cur_column * Emoji.PARSE_WIDTH subpixbuf = atlas.new_subpixbuf(src_x, src_y, Emoji.PARSE_WIDTH, Emoji.PARSE_HEIGHT) if list(subpixbuf.get_pixels())[0:4] == [0, 0, 0, 255]: # top left corner is a black pixel means image is missing subpixbuf = None if cur_column == Emoji.PARSE_COLUMNS - 1: src_y += Emoji.PARSE_WIDTH cur_column = 0 else: cur_column += 1 yield subpixbuf def _on_emoticon_press(self, flowbox, child): GLib.timeout_add(100, flowbox.unselect_child, child) codepoint, pixbuf = child.get_emoji() self._text_widget().insert_emoji(codepoint, pixbuf) def do_destroy(self): # Remove the references we hold to other objects self._text_widget = None # Never destroy, creating a new EmoticonPopover is expensive return True emoji_chooser = EmojiChooser() gajim-gajim-1.1.3/gajim/gtk/emoji_data.py000066400000000000000000034225761345766322700202540ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import re import weakref from enum import IntEnum from collections import OrderedDict from gi.repository import GdkPixbuf _MODIFIERS = ['\U0001F3FB', '\U0001F3FC', '\U0001F3FD', '\U0001F3FE', '\U0001F3FF'] class Emoji(IntEnum): TEXT_SIZE = 18 INPUT_SIZE = 14 PARSE_HEIGHT = 24 PARSE_WIDTH = 24 PARSE_COLUMNS = 20 def is_emoji(codepoints): if codepoints in emoji_data: return True if codepoints in emoji_ascii_data: return True return False def get_emoji_pixbuf(codepoints): ascii_codepoint = emoji_ascii_data.get(codepoints, None) if ascii_codepoint is not None: codepoints = ascii_codepoint pixbuf = emoji_pixbufs.get(codepoints, None) if pixbuf is None: return pixbuf = pixbuf.scale_simple(Emoji.TEXT_SIZE, Emoji.TEXT_SIZE, GdkPixbuf.InterpType.HYPER) return pixbuf class EmojiData(OrderedDict): def __getitem__(self, key): try: return OrderedDict.__getitem__(self, key) except KeyError: for mod in _MODIFIERS: if mod in key: key = key.replace(mod, '') return OrderedDict.__getitem__(self, key) raise KeyError def __contains__(self, item): try: return bool(self[item]) except KeyError: return False def get_regex(self): emojis = [] for codepoint, attrs in self.items(): if attrs.get('variations', False): for variation in attrs['variations'].keys(): emojis.append(variation) emojis.append(codepoint) emojis = sorted(emojis, key=len, reverse=True) return '(' + '|'.join(re.escape(u) for u in emojis) + ')' class EmojiPixbufs(dict): _complete = False def __init__(self): dict.__init__(self) self._marks = weakref.WeakKeyDictionary() @property def complete(self): return self._complete @complete.setter def complete(self, value): if value is True: self._replace_emojis() self._marks.clear() self._complete = value def clear(self): self.complete = False self._marks.clear() dict.clear(self) def append_marks(self, textview, start, end, codepoint): # We have to asign some dummy data to the mark, or else # pygobject will not keep the python wrapper alive, which in turn # makes the weakref invalid as soon as the method ends start.dummy = 'x' start = weakref.ref(start) end.dummy = 'x' end = weakref.ref(end) if textview in self._marks: self._marks[textview].append((start, end, codepoint)) else: self._marks[textview] = [(start, end, codepoint)] def _replace_emojis(self): for textview, emojis in self._marks.items(): for emoji in emojis: start, end, codepoint = emoji if start() is None or end() is None: # Marks are gone continue ascii_codepoint = emoji_ascii_data.get(codepoint, None) if ascii_codepoint is not None: codepoint = ascii_codepoint pixbuf = self.get(codepoint, None) if pixbuf is None: # theme does not support this codepoint continue pixbuf = pixbuf.scale_simple(Emoji.TEXT_SIZE, Emoji.TEXT_SIZE, GdkPixbuf.InterpType.HYPER) textview.replace_emojis( start(), end(), pixbuf.copy(), codepoint) class EmojiAsciiData(dict): def get_regex(self): # When an emoticon is bordered by an alpha-numeric character it # is NOT expanded. e.g., foo:) NO, foo :) YES, (brb) NO, # (:)) YES, etc. We still allow multiple emoticons # side-by-side like :P:P:P # TODO: Refactor this keys = sorted(self.keys(), key=len, reverse=True) pre_pattern = '' post_pattern = '' emoticon_length = 0 emoticons_pattern = '' for emoticon in keys: # escape regexp metachars emoticon_escaped = re.escape(emoticon) emoticons_pattern += emoticon_escaped + '|' if emoticon_length != len(emoticon): # Build up expressions to match emoticons next to others pre_pattern = pre_pattern[:-1] + ')|(?<=' post_pattern = post_pattern[:-1] + ')|(?=' emoticon_length = len(emoticon) pre_pattern += emoticon_escaped + '|' post_pattern += emoticon_escaped + '|' # We match from our list of emoticons, but they must either have # whitespace, or another emoticon next to it to match successfully # [\w.] alphanumeric and dot (for not matching 8) in (2.8)) emoticons_pattern = r'(?:(?:/', '\U0001F615'), ('*\\O/*', '\U0001F646'), ('#)', '\U0001F635'), (":'-)", '\U0001F602'), ('B-)', '\U0001F60e'), ('=#', '\U0001F636'), (':@', '\U0001F620'), ('=*', '\U0001F618'), (':-*', '\U0001F618'), ('>:\\', '\U0001F615'), ('\\O/', '\U0001F646'), ('D:', '\U0001F628'), ('*\\0/*', '\U0001F646'), (':-Þ', '\U0001F61b'), ('8)', '\U0001F60e'), (';D', '\U0001F609'), ('%)', '\U0001F635'), ('=X', '\U0001F636'), ('>:(', '\U0001F620'), (':-X', '\U0001F636'), ('>:O', '\U0001F62e'), (":')", '\U0001F602'), ('=)', '\U0001F642'), ('=(', '\U0001F61e'), ('>:-)', '\U0001F606'), ('=]', '\U0001F642'), ('O:-3', '\U0001F607'), ('-__-', '\U0001F611'), ('>:P', '\U0001F61c'), ("'=D", '\U0001F605'), ("'=(", '\U0001F613'), (':-(', '\U0001F61e'), (':-P', '\U0001F61b'), ('0;^)', '\U0001F607'), (':P', '\U0001F61b'), ("'=)", '\U0001F605'), (':-D', '\U0001F603'), (':\\', '\U0001F615'), ('0:)', '\U0001F607'), ('>:[', '\U0001F61e'), (';]', '\U0001F609'), (':Þ', '\U0001F61b'), (':-.', '\U0001F615'), (':b', '\U0001F61b'), (':-#', '\U0001F636'), ('\\0/', '\U0001F646'), ('O_O', '\U0001F62e'), ('>:-(', '\U0001F620'), (":'-(", '\U0001F622'), (':#', '\U0001F636'), ('>.<', '\U0001F623'), ('0:3', '\U0001F607'), ('O;-)', '\U0001F607'), ('=/', '\U0001F615'), (':D', '\U0001F603'), (':[', '\U0001F61e'), (':-[', '\U0001F61e'), ('=\\', '\U0001F615'), ('8-)', '\U0001F60e'), (':*', '\U0001F618'), ("':(", '\U0001F613'), ("':D", '\U0001F605'), ('*)', '\U0001F609'), ('<3', '\U00002764'), ('X)', '\U0001F635'), (';)', '\U0001F609'), ('8-D', '\U0001F60e'), ('O:)', '\U0001F607'), (':L', '\U0001F615'), ('B)', '\U0001F60e'), ('>;)', '\U0001F606'), ('=)', '\U0001F606'), (';^)', '\U0001F609'), (':-/', '\U0001F615'), ('O=)', '\U0001F607'), (':$', '\U0001F633'), (':-b', '\U0001F61b'), (';-(', '\U0001F622'), ('%-)', '\U0001F635'), (':/', '\U0001F615'), (':-)', '\U0001F642'), ('0:-3', '\U0001F607'), (":'(", '\U0001F622'), ('0;-)', '\U0001F607'), ('#-)', '\U0001F635'), (':(', '\U0001F61e'), ('B-D', '\U0001F60e'), (';-]', '\U0001F609'), ("':-)", '\U0001F605'), ('X-)', '\U0001F635'), (':]', '\U0001F642'), ('(y)', '\U0001F44d'), ('>:)', '\U0001F606'), ('0:-)', '\U0001F607'), ('O:-)', '\U0001F607'), ('O:3', '\U0001F607'), ('=L', '\U0001F615'), (':X', '\U0001F636'), ('=$', '\U0001F633'), (';-)', '\U0001F609'), ("':)", '\U0001F605'), ('X-P', '\U0001F61c'), ('-___-', '\U0001F611'), ('=P', '\U0001F61b'), (':^*', '\U0001F618'), ('=D', '\U0001F603'), ('*-)', '\U0001F609'), ("':-(", '\U0001F613'), ('-_-', '\U0001F611') ]) emoji_data = EmojiData([ ('\U0001F600', { 'desc': 'grinning face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F601', { 'desc': 'beaming face with smiling eyes', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F602', { 'desc': 'face with tears of joy', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F923', { 'desc': 'rolling on the floor laughing', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F603', { 'desc': 'grinning face with big eyes', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F604', { 'desc': 'grinning face with smiling eyes', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F605', { 'desc': 'grinning face with sweat', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F606', { 'desc': 'grinning squinting face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F609', { 'desc': 'winking face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F60A', { 'desc': 'smiling face with smiling eyes', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F60B', { 'desc': 'face savoring food', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F60E', { 'desc': 'smiling face with sunglasses', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F60D', { 'desc': 'smiling face with heart-eyes', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F618', { 'desc': 'face blowing a kiss', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F970', { 'desc': 'smiling face with 3 hearts', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F617', { 'desc': 'kissing face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F619', { 'desc': 'kissing face with smiling eyes', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F61A', { 'desc': 'kissing face with closed eyes', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000263A\U0000FE0F', { 'desc': 'smiling face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True }), ('\U0000263A', { 'desc': 'smiling face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F642', { 'desc': 'slightly smiling face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F917', { 'desc': 'hugging face', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F929', { 'desc': 'star-struck', 'group': 'Smileys & People', 'subgroup': 'face-positive', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F914', { 'desc': 'thinking face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F928', { 'desc': 'face with raised eyebrow', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F610', { 'desc': 'neutral face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F611', { 'desc': 'expressionless face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F636', { 'desc': 'face without mouth', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F644', { 'desc': 'face with rolling eyes', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F60F', { 'desc': 'smirking face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F623', { 'desc': 'persevering face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F625', { 'desc': 'sad but relieved face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F62E', { 'desc': 'face with open mouth', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F910', { 'desc': 'zipper-mouth face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F62F', { 'desc': 'hushed face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F62A', { 'desc': 'sleepy face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F62B', { 'desc': 'tired face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F634', { 'desc': 'sleeping face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F60C', { 'desc': 'relieved face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F61B', { 'desc': 'face with tongue', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F61C', { 'desc': 'winking face with tongue', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F61D', { 'desc': 'squinting face with tongue', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F924', { 'desc': 'drooling face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F612', { 'desc': 'unamused face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F613', { 'desc': 'downcast face with sweat', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F614', { 'desc': 'pensive face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F615', { 'desc': 'confused face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F643', { 'desc': 'upside-down face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F911', { 'desc': 'money-mouth face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F632', { 'desc': 'astonished face', 'group': 'Smileys & People', 'subgroup': 'face-neutral', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002639\U0000FE0F', { 'desc': 'frowning face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True }), ('\U00002639', { 'desc': 'frowning face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F641', { 'desc': 'slightly frowning face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F616', { 'desc': 'confounded face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F61E', { 'desc': 'disappointed face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F61F', { 'desc': 'worried face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F624', { 'desc': 'face with steam from nose', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F622', { 'desc': 'crying face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F62D', { 'desc': 'loudly crying face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F626', { 'desc': 'frowning face with open mouth', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F627', { 'desc': 'anguished face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F628', { 'desc': 'fearful face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F629', { 'desc': 'weary face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F92F', { 'desc': 'exploding head', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F62C', { 'desc': 'grimacing face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F630', { 'desc': 'anxious face with sweat', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F631', { 'desc': 'face screaming in fear', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F975', { 'desc': 'hot face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F976', { 'desc': 'cold face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F633', { 'desc': 'flushed face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F92A', { 'desc': 'zany face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F635', { 'desc': 'dizzy face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F621', { 'desc': 'pouting face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F620', { 'desc': 'angry face', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F92C', { 'desc': 'face with symbols on mouth', 'group': 'Smileys & People', 'subgroup': 'face-negative', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F637', { 'desc': 'face with medical mask', 'group': 'Smileys & People', 'subgroup': 'face-sick', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F912', { 'desc': 'face with thermometer', 'group': 'Smileys & People', 'subgroup': 'face-sick', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F915', { 'desc': 'face with head-bandage', 'group': 'Smileys & People', 'subgroup': 'face-sick', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F922', { 'desc': 'nauseated face', 'group': 'Smileys & People', 'subgroup': 'face-sick', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F92E', { 'desc': 'face vomiting', 'group': 'Smileys & People', 'subgroup': 'face-sick', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F927', { 'desc': 'sneezing face', 'group': 'Smileys & People', 'subgroup': 'face-sick', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F607', { 'desc': 'smiling face with halo', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F920', { 'desc': 'cowboy hat face', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F973', { 'desc': 'partying face', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F974', { 'desc': 'woozy face', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F97A', { 'desc': 'pleading face', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F925', { 'desc': 'lying face', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F92B', { 'desc': 'shushing face', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F92D', { 'desc': 'face with hand over mouth', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9D0', { 'desc': 'face with monocle', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F913', { 'desc': 'nerd face', 'group': 'Smileys & People', 'subgroup': 'face-role', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F608', { 'desc': 'smiling face with horns', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F47F', { 'desc': 'angry face with horns', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F921', { 'desc': 'clown face', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F479', { 'desc': 'ogre', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F47A', { 'desc': 'goblin', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F480', { 'desc': 'skull', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002620\U0000FE0F', { 'desc': 'skull and crossbones', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True }), ('\U00002620', { 'desc': 'skull and crossbones', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F47B', { 'desc': 'ghost', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F47D', { 'desc': 'alien', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F47E', { 'desc': 'alien monster', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F916', { 'desc': 'robot face', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A9', { 'desc': 'pile of poo', 'group': 'Smileys & People', 'subgroup': 'face-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F63A', { 'desc': 'grinning cat face', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F638', { 'desc': 'grinning cat face with smiling eyes', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F639', { 'desc': 'cat face with tears of joy', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F63B', { 'desc': 'smiling cat face with heart-eyes', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F63C', { 'desc': 'cat face with wry smile', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F63D', { 'desc': 'kissing cat face', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F640', { 'desc': 'weary cat face', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F63F', { 'desc': 'crying cat face', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F63E', { 'desc': 'pouting cat face', 'group': 'Smileys & People', 'subgroup': 'cat-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F648', { 'desc': 'see-no-evil monkey', 'group': 'Smileys & People', 'subgroup': 'monkey-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F649', { 'desc': 'hear-no-evil monkey', 'group': 'Smileys & People', 'subgroup': 'monkey-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F64A', { 'desc': 'speak-no-evil monkey', 'group': 'Smileys & People', 'subgroup': 'monkey-face', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F476', { 'desc': 'baby', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F476\U0001F3FB', { 'desc': 'baby: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F476\U0001F3FC', { 'desc': 'baby: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F476\U0001F3FD', { 'desc': 'baby: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F476\U0001F3FE', { 'desc': 'baby: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F476\U0001F3FF', { 'desc': 'baby: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D2', { 'desc': 'child', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D2\U0001F3FB', { 'desc': 'child: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D2\U0001F3FC', { 'desc': 'child: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D2\U0001F3FD', { 'desc': 'child: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D2\U0001F3FE', { 'desc': 'child: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D2\U0001F3FF', { 'desc': 'child: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F466', { 'desc': 'boy', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F466\U0001F3FB', { 'desc': 'boy: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F466\U0001F3FC', { 'desc': 'boy: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F466\U0001F3FD', { 'desc': 'boy: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F466\U0001F3FE', { 'desc': 'boy: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F466\U0001F3FF', { 'desc': 'boy: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F467', { 'desc': 'girl', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F467\U0001F3FB', { 'desc': 'girl: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F467\U0001F3FC', { 'desc': 'girl: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F467\U0001F3FD', { 'desc': 'girl: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F467\U0001F3FE', { 'desc': 'girl: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F467\U0001F3FF', { 'desc': 'girl: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D1', { 'desc': 'adult', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D1\U0001F3FB', { 'desc': 'adult: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D1\U0001F3FC', { 'desc': 'adult: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D1\U0001F3FD', { 'desc': 'adult: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D1\U0001F3FE', { 'desc': 'adult: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D1\U0001F3FF', { 'desc': 'adult: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F468', { 'desc': 'man', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB', { 'desc': 'man: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F468\U0001F3FC', { 'desc': 'man: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F468\U0001F3FD', { 'desc': 'man: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F468\U0001F3FE', { 'desc': 'man: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F468\U0001F3FF', { 'desc': 'man: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F469', { 'desc': 'woman', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB', { 'desc': 'woman: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F469\U0001F3FC', { 'desc': 'woman: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F469\U0001F3FD', { 'desc': 'woman: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F469\U0001F3FE', { 'desc': 'woman: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F469\U0001F3FF', { 'desc': 'woman: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D3', { 'desc': 'older adult', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D3\U0001F3FB', { 'desc': 'older adult: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D3\U0001F3FC', { 'desc': 'older adult: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D3\U0001F3FD', { 'desc': 'older adult: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D3\U0001F3FE', { 'desc': 'older adult: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D3\U0001F3FF', { 'desc': 'older adult: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F474', { 'desc': 'old man', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F474\U0001F3FB', { 'desc': 'old man: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F474\U0001F3FC', { 'desc': 'old man: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F474\U0001F3FD', { 'desc': 'old man: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F474\U0001F3FE', { 'desc': 'old man: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F474\U0001F3FF', { 'desc': 'old man: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F475', { 'desc': 'old woman', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F475\U0001F3FB', { 'desc': 'old woman: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F475\U0001F3FC', { 'desc': 'old woman: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F475\U0001F3FD', { 'desc': 'old woman: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F475\U0001F3FE', { 'desc': 'old woman: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F475\U0001F3FF', { 'desc': 'old woman: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F468\U0000200D\U00002695\U0000FE0F', { 'desc': 'man health worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U00002695\U0000FE0F', { 'desc': 'man health worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U00002695\U0000FE0F', { 'desc': 'man health worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U00002695\U0000FE0F', { 'desc': 'man health worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U00002695\U0000FE0F', { 'desc': 'man health worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U00002695\U0000FE0F', { 'desc': 'man health worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U00002695', { 'desc': 'man health worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U00002695', { 'desc': 'man health worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FC\U0000200D\U00002695', { 'desc': 'man health worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FD\U0000200D\U00002695', { 'desc': 'man health worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FE\U0000200D\U00002695', { 'desc': 'man health worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FF\U0000200D\U00002695', { 'desc': 'man health worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F469\U0000200D\U00002695\U0000FE0F', { 'desc': 'woman health worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U00002695\U0000FE0F', { 'desc': 'woman health worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U00002695\U0000FE0F', { 'desc': 'woman health worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U00002695\U0000FE0F', { 'desc': 'woman health worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U00002695\U0000FE0F', { 'desc': 'woman health worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U00002695\U0000FE0F', { 'desc': 'woman health worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U00002695', { 'desc': 'woman health worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U00002695', { 'desc': 'woman health worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FC\U0000200D\U00002695', { 'desc': 'woman health worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FD\U0000200D\U00002695', { 'desc': 'woman health worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FE\U0000200D\U00002695', { 'desc': 'woman health worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FF\U0000200D\U00002695', { 'desc': 'woman health worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F468\U0000200D\U0001F393', { 'desc': 'man student', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F393', { 'desc': 'man student: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F393', { 'desc': 'man student: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F393', { 'desc': 'man student: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F393', { 'desc': 'man student: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F393', { 'desc': 'man student: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F393', { 'desc': 'woman student', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F393', { 'desc': 'woman student: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F393', { 'desc': 'woman student: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F393', { 'desc': 'woman student: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F393', { 'desc': 'woman student: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F393', { 'desc': 'woman student: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F3EB', { 'desc': 'man teacher', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F3EB', { 'desc': 'man teacher: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F3EB', { 'desc': 'man teacher: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F3EB', { 'desc': 'man teacher: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F3EB', { 'desc': 'man teacher: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F3EB', { 'desc': 'man teacher: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F3EB', { 'desc': 'woman teacher', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F3EB', { 'desc': 'woman teacher: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F3EB', { 'desc': 'woman teacher: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F3EB', { 'desc': 'woman teacher: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F3EB', { 'desc': 'woman teacher: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F3EB', { 'desc': 'woman teacher: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U00002696\U0000FE0F', { 'desc': 'man judge', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U00002696\U0000FE0F', { 'desc': 'man judge: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U00002696\U0000FE0F', { 'desc': 'man judge: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U00002696\U0000FE0F', { 'desc': 'man judge: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U00002696\U0000FE0F', { 'desc': 'man judge: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U00002696\U0000FE0F', { 'desc': 'man judge: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U00002696', { 'desc': 'man judge', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U00002696', { 'desc': 'man judge: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FC\U0000200D\U00002696', { 'desc': 'man judge: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FD\U0000200D\U00002696', { 'desc': 'man judge: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FE\U0000200D\U00002696', { 'desc': 'man judge: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FF\U0000200D\U00002696', { 'desc': 'man judge: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F469\U0000200D\U00002696\U0000FE0F', { 'desc': 'woman judge', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U00002696\U0000FE0F', { 'desc': 'woman judge: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U00002696\U0000FE0F', { 'desc': 'woman judge: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U00002696\U0000FE0F', { 'desc': 'woman judge: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U00002696\U0000FE0F', { 'desc': 'woman judge: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U00002696\U0000FE0F', { 'desc': 'woman judge: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U00002696', { 'desc': 'woman judge', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U00002696', { 'desc': 'woman judge: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FC\U0000200D\U00002696', { 'desc': 'woman judge: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FD\U0000200D\U00002696', { 'desc': 'woman judge: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FE\U0000200D\U00002696', { 'desc': 'woman judge: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FF\U0000200D\U00002696', { 'desc': 'woman judge: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F468\U0000200D\U0001F33E', { 'desc': 'man farmer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F33E', { 'desc': 'man farmer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F33E', { 'desc': 'man farmer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F33E', { 'desc': 'man farmer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F33E', { 'desc': 'man farmer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F33E', { 'desc': 'man farmer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F33E', { 'desc': 'woman farmer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F33E', { 'desc': 'woman farmer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F33E', { 'desc': 'woman farmer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F33E', { 'desc': 'woman farmer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F33E', { 'desc': 'woman farmer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F33E', { 'desc': 'woman farmer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F373', { 'desc': 'man cook', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F373', { 'desc': 'man cook: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F373', { 'desc': 'man cook: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F373', { 'desc': 'man cook: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F373', { 'desc': 'man cook: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F373', { 'desc': 'man cook: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F373', { 'desc': 'woman cook', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F373', { 'desc': 'woman cook: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F373', { 'desc': 'woman cook: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F373', { 'desc': 'woman cook: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F373', { 'desc': 'woman cook: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F373', { 'desc': 'woman cook: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F527', { 'desc': 'man mechanic', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F527', { 'desc': 'man mechanic: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F527', { 'desc': 'man mechanic: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F527', { 'desc': 'man mechanic: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F527', { 'desc': 'man mechanic: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F527', { 'desc': 'man mechanic: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F527', { 'desc': 'woman mechanic', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F527', { 'desc': 'woman mechanic: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F527', { 'desc': 'woman mechanic: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F527', { 'desc': 'woman mechanic: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F527', { 'desc': 'woman mechanic: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F527', { 'desc': 'woman mechanic: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F3ED', { 'desc': 'man factory worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F3ED', { 'desc': 'man factory worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F3ED', { 'desc': 'man factory worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F3ED', { 'desc': 'man factory worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F3ED', { 'desc': 'man factory worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F3ED', { 'desc': 'man factory worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F3ED', { 'desc': 'woman factory worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F3ED', { 'desc': 'woman factory worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F3ED', { 'desc': 'woman factory worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F3ED', { 'desc': 'woman factory worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F3ED', { 'desc': 'woman factory worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F3ED', { 'desc': 'woman factory worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F4BC', { 'desc': 'man office worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F4BC', { 'desc': 'man office worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F4BC', { 'desc': 'man office worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F4BC', { 'desc': 'man office worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F4BC', { 'desc': 'man office worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F4BC', { 'desc': 'man office worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F4BC', { 'desc': 'woman office worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F4BC', { 'desc': 'woman office worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F4BC', { 'desc': 'woman office worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F4BC', { 'desc': 'woman office worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F4BC', { 'desc': 'woman office worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F4BC', { 'desc': 'woman office worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F52C', { 'desc': 'man scientist', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F52C', { 'desc': 'man scientist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F52C', { 'desc': 'man scientist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F52C', { 'desc': 'man scientist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F52C', { 'desc': 'man scientist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F52C', { 'desc': 'man scientist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F52C', { 'desc': 'woman scientist', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F52C', { 'desc': 'woman scientist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F52C', { 'desc': 'woman scientist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F52C', { 'desc': 'woman scientist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F52C', { 'desc': 'woman scientist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F52C', { 'desc': 'woman scientist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F4BB', { 'desc': 'man technologist', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F4BB', { 'desc': 'man technologist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F4BB', { 'desc': 'man technologist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F4BB', { 'desc': 'man technologist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F4BB', { 'desc': 'man technologist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F4BB', { 'desc': 'man technologist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F4BB', { 'desc': 'woman technologist', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F4BB', { 'desc': 'woman technologist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F4BB', { 'desc': 'woman technologist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F4BB', { 'desc': 'woman technologist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F4BB', { 'desc': 'woman technologist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F4BB', { 'desc': 'woman technologist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F3A4', { 'desc': 'man singer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F3A4', { 'desc': 'man singer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F3A4', { 'desc': 'man singer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F3A4', { 'desc': 'man singer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F3A4', { 'desc': 'man singer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F3A4', { 'desc': 'man singer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F3A4', { 'desc': 'woman singer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F3A4', { 'desc': 'woman singer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F3A4', { 'desc': 'woman singer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F3A4', { 'desc': 'woman singer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F3A4', { 'desc': 'woman singer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F3A4', { 'desc': 'woman singer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F3A8', { 'desc': 'man artist', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F3A8', { 'desc': 'man artist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F3A8', { 'desc': 'man artist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F3A8', { 'desc': 'man artist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F3A8', { 'desc': 'man artist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F3A8', { 'desc': 'man artist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F3A8', { 'desc': 'woman artist', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F3A8', { 'desc': 'woman artist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F3A8', { 'desc': 'woman artist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F3A8', { 'desc': 'woman artist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F3A8', { 'desc': 'woman artist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F3A8', { 'desc': 'woman artist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U00002708\U0000FE0F', { 'desc': 'man pilot', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U00002708\U0000FE0F', { 'desc': 'man pilot: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U00002708\U0000FE0F', { 'desc': 'man pilot: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U00002708\U0000FE0F', { 'desc': 'man pilot: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U00002708\U0000FE0F', { 'desc': 'man pilot: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U00002708\U0000FE0F', { 'desc': 'man pilot: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U00002708', { 'desc': 'man pilot', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U00002708', { 'desc': 'man pilot: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FC\U0000200D\U00002708', { 'desc': 'man pilot: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FD\U0000200D\U00002708', { 'desc': 'man pilot: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FE\U0000200D\U00002708', { 'desc': 'man pilot: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F468\U0001F3FF\U0000200D\U00002708', { 'desc': 'man pilot: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F469\U0000200D\U00002708\U0000FE0F', { 'desc': 'woman pilot', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U00002708\U0000FE0F', { 'desc': 'woman pilot: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U00002708\U0000FE0F', { 'desc': 'woman pilot: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U00002708\U0000FE0F', { 'desc': 'woman pilot: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U00002708\U0000FE0F', { 'desc': 'woman pilot: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U00002708\U0000FE0F', { 'desc': 'woman pilot: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U00002708', { 'desc': 'woman pilot', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U00002708', { 'desc': 'woman pilot: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FC\U0000200D\U00002708', { 'desc': 'woman pilot: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FD\U0000200D\U00002708', { 'desc': 'woman pilot: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FE\U0000200D\U00002708', { 'desc': 'woman pilot: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F469\U0001F3FF\U0000200D\U00002708', { 'desc': 'woman pilot: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F468\U0000200D\U0001F680', { 'desc': 'man astronaut', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F680', { 'desc': 'man astronaut: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F680', { 'desc': 'man astronaut: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F680', { 'desc': 'man astronaut: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F680', { 'desc': 'man astronaut: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F680', { 'desc': 'man astronaut: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F680', { 'desc': 'woman astronaut', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F680', { 'desc': 'woman astronaut: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F680', { 'desc': 'woman astronaut: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F680', { 'desc': 'woman astronaut: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F680', { 'desc': 'woman astronaut: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F680', { 'desc': 'woman astronaut: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F692', { 'desc': 'man firefighter', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F692', { 'desc': 'man firefighter: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F692', { 'desc': 'man firefighter: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F692', { 'desc': 'man firefighter: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F692', { 'desc': 'man firefighter: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F692', { 'desc': 'man firefighter: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F692', { 'desc': 'woman firefighter', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F692', { 'desc': 'woman firefighter: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F692', { 'desc': 'woman firefighter: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F692', { 'desc': 'woman firefighter: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F692', { 'desc': 'woman firefighter: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F692', { 'desc': 'woman firefighter: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F46E', { 'desc': 'police officer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F46E\U0001F3FB', { 'desc': 'police officer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F46E\U0001F3FC', { 'desc': 'police officer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F46E\U0001F3FD', { 'desc': 'police officer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F46E\U0001F3FE', { 'desc': 'police officer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F46E\U0001F3FF', { 'desc': 'police officer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F46E\U0000200D\U00002642\U0000FE0F', { 'desc': 'man police officer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F46E\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man police officer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man police officer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man police officer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man police officer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man police officer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F46E\U0000200D\U00002642', { 'desc': 'man police officer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F46E\U0001F3FB\U0000200D\U00002642', { 'desc': 'man police officer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FC\U0000200D\U00002642', { 'desc': 'man police officer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FD\U0000200D\U00002642', { 'desc': 'man police officer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FE\U0000200D\U00002642', { 'desc': 'man police officer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FF\U0000200D\U00002642', { 'desc': 'man police officer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F46E\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman police officer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F46E\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman police officer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman police officer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman police officer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman police officer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F46E\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman police officer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F46E\U0000200D\U00002640', { 'desc': 'woman police officer', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F46E\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman police officer: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman police officer: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman police officer: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman police officer: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F46E\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman police officer: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F575\U0000FE0F', { 'desc': 'detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F575\U0001F3FB', { 'desc': 'detective: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F575\U0001F3FC', { 'desc': 'detective: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F575\U0001F3FD', { 'desc': 'detective: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F575\U0001F3FE', { 'desc': 'detective: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F575\U0001F3FF', { 'desc': 'detective: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0001F575', { 'desc': 'detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F575\U0000FE0F\U0000200D\U00002642\U0000FE0F', { 'desc': 'man detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F575\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man detective: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man detective: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man detective: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man detective: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man detective: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F575\U0000200D\U00002642\U0000FE0F', { 'desc': 'man detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0000FE0F\U0000200D\U00002642', { 'desc': 'man detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F575\U0001F3FB\U0000200D\U00002642', { 'desc': 'man detective: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FC\U0000200D\U00002642', { 'desc': 'man detective: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FD\U0000200D\U00002642', { 'desc': 'man detective: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FE\U0000200D\U00002642', { 'desc': 'man detective: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FF\U0000200D\U00002642', { 'desc': 'man detective: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F575\U0000200D\U00002642', { 'desc': 'man detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0000FE0F\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F575\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman detective: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman detective: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman detective: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman detective: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F575\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman detective: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F575\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0000FE0F\U0000200D\U00002640', { 'desc': 'woman detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F575\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman detective: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman detective: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman detective: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman detective: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F575\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman detective: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F575\U0000200D\U00002640', { 'desc': 'woman detective', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482', { 'desc': 'guard', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F482\U0001F3FB', { 'desc': 'guard: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F482\U0001F3FC', { 'desc': 'guard: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F482\U0001F3FD', { 'desc': 'guard: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F482\U0001F3FE', { 'desc': 'guard: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F482\U0001F3FF', { 'desc': 'guard: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F482\U0000200D\U00002642\U0000FE0F', { 'desc': 'man guard', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F482\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man guard: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man guard: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man guard: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man guard: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man guard: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F482\U0000200D\U00002642', { 'desc': 'man guard', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F482\U0001F3FB\U0000200D\U00002642', { 'desc': 'man guard: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FC\U0000200D\U00002642', { 'desc': 'man guard: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FD\U0000200D\U00002642', { 'desc': 'man guard: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FE\U0000200D\U00002642', { 'desc': 'man guard: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FF\U0000200D\U00002642', { 'desc': 'man guard: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F482\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman guard', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F482\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman guard: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman guard: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman guard: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman guard: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F482\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman guard: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F482\U0000200D\U00002640', { 'desc': 'woman guard', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F482\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman guard: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman guard: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman guard: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman guard: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F482\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman guard: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F477', { 'desc': 'construction worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F477\U0001F3FB', { 'desc': 'construction worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F477\U0001F3FC', { 'desc': 'construction worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F477\U0001F3FD', { 'desc': 'construction worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F477\U0001F3FE', { 'desc': 'construction worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F477\U0001F3FF', { 'desc': 'construction worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F477\U0000200D\U00002642\U0000FE0F', { 'desc': 'man construction worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F477\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man construction worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man construction worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man construction worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man construction worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man construction worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F477\U0000200D\U00002642', { 'desc': 'man construction worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F477\U0001F3FB\U0000200D\U00002642', { 'desc': 'man construction worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FC\U0000200D\U00002642', { 'desc': 'man construction worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FD\U0000200D\U00002642', { 'desc': 'man construction worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FE\U0000200D\U00002642', { 'desc': 'man construction worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FF\U0000200D\U00002642', { 'desc': 'man construction worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F477\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman construction worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F477\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman construction worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman construction worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman construction worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman construction worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F477\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman construction worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F477\U0000200D\U00002640', { 'desc': 'woman construction worker', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F477\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman construction worker: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman construction worker: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman construction worker: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman construction worker: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F477\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman construction worker: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F934', { 'desc': 'prince', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F934\U0001F3FB', { 'desc': 'prince: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F934\U0001F3FC', { 'desc': 'prince: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F934\U0001F3FD', { 'desc': 'prince: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F934\U0001F3FE', { 'desc': 'prince: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F934\U0001F3FF', { 'desc': 'prince: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F478', { 'desc': 'princess', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F478\U0001F3FB', { 'desc': 'princess: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F478\U0001F3FC', { 'desc': 'princess: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F478\U0001F3FD', { 'desc': 'princess: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F478\U0001F3FE', { 'desc': 'princess: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F478\U0001F3FF', { 'desc': 'princess: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F473', { 'desc': 'person wearing turban', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F473\U0001F3FB', { 'desc': 'person wearing turban: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F473\U0001F3FC', { 'desc': 'person wearing turban: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F473\U0001F3FD', { 'desc': 'person wearing turban: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F473\U0001F3FE', { 'desc': 'person wearing turban: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F473\U0001F3FF', { 'desc': 'person wearing turban: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F473\U0000200D\U00002642\U0000FE0F', { 'desc': 'man wearing turban', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F473\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man wearing turban: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man wearing turban: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man wearing turban: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man wearing turban: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man wearing turban: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F473\U0000200D\U00002642', { 'desc': 'man wearing turban', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F473\U0001F3FB\U0000200D\U00002642', { 'desc': 'man wearing turban: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FC\U0000200D\U00002642', { 'desc': 'man wearing turban: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FD\U0000200D\U00002642', { 'desc': 'man wearing turban: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FE\U0000200D\U00002642', { 'desc': 'man wearing turban: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FF\U0000200D\U00002642', { 'desc': 'man wearing turban: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F473\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman wearing turban', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F473\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman wearing turban: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman wearing turban: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman wearing turban: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman wearing turban: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F473\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman wearing turban: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F473\U0000200D\U00002640', { 'desc': 'woman wearing turban', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F473\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman wearing turban: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman wearing turban: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman wearing turban: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman wearing turban: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F473\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman wearing turban: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F472', { 'desc': 'man with Chinese cap', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F472\U0001F3FB', { 'desc': 'man with Chinese cap: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F472\U0001F3FC', { 'desc': 'man with Chinese cap: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F472\U0001F3FD', { 'desc': 'man with Chinese cap: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F472\U0001F3FE', { 'desc': 'man with Chinese cap: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F472\U0001F3FF', { 'desc': 'man with Chinese cap: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D5', { 'desc': 'woman with headscarf', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D5\U0001F3FB', { 'desc': 'woman with headscarf: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D5\U0001F3FC', { 'desc': 'woman with headscarf: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D5\U0001F3FD', { 'desc': 'woman with headscarf: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D5\U0001F3FE', { 'desc': 'woman with headscarf: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D5\U0001F3FF', { 'desc': 'woman with headscarf: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D4', { 'desc': 'bearded person', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D4\U0001F3FB', { 'desc': 'bearded person: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D4\U0001F3FC', { 'desc': 'bearded person: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D4\U0001F3FD', { 'desc': 'bearded person: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D4\U0001F3FE', { 'desc': 'bearded person: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D4\U0001F3FF', { 'desc': 'bearded person: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F471', { 'desc': 'blond-haired person', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F471\U0001F3FB', { 'desc': 'blond-haired person: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F471\U0001F3FC', { 'desc': 'blond-haired person: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F471\U0001F3FD', { 'desc': 'blond-haired person: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F471\U0001F3FE', { 'desc': 'blond-haired person: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F471\U0001F3FF', { 'desc': 'blond-haired person: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F471\U0000200D\U00002642\U0000FE0F', { 'desc': 'blond-haired man', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F471\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'blond-haired man: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'blond-haired man: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'blond-haired man: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'blond-haired man: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'blond-haired man: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F471\U0000200D\U00002642', { 'desc': 'blond-haired man', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F471\U0001F3FB\U0000200D\U00002642', { 'desc': 'blond-haired man: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FC\U0000200D\U00002642', { 'desc': 'blond-haired man: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FD\U0000200D\U00002642', { 'desc': 'blond-haired man: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FE\U0000200D\U00002642', { 'desc': 'blond-haired man: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FF\U0000200D\U00002642', { 'desc': 'blond-haired man: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F471\U0000200D\U00002640\U0000FE0F', { 'desc': 'blond-haired woman', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F471\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'blond-haired woman: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'blond-haired woman: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'blond-haired woman: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'blond-haired woman: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F471\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'blond-haired woman: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F471\U0000200D\U00002640', { 'desc': 'blond-haired woman', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F471\U0001F3FB\U0000200D\U00002640', { 'desc': 'blond-haired woman: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FC\U0000200D\U00002640', { 'desc': 'blond-haired woman: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FD\U0000200D\U00002640', { 'desc': 'blond-haired woman: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FE\U0000200D\U00002640', { 'desc': 'blond-haired woman: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }), ('\U0001F471\U0001F3FF\U0000200D\U00002640', { 'desc': 'blond-haired woman: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': False }) ]) }), ('\U0001F468\U0000200D\U0001F9B0', { 'desc': 'man, red haired', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F9B0', { 'desc': 'man, red haired: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F9B0', { 'desc': 'man, red haired: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F9B0', { 'desc': 'man, red haired: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F9B0', { 'desc': 'man, red haired: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F9B0', { 'desc': 'man, red haired: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F9B0', { 'desc': 'woman, red haired', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F9B0', { 'desc': 'woman, red haired: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F9B0', { 'desc': 'woman, red haired: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F9B0', { 'desc': 'woman, red haired: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F9B0', { 'desc': 'woman, red haired: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F9B0', { 'desc': 'woman, red haired: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F9B1', { 'desc': 'man, curly haired', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F9B1', { 'desc': 'man, curly haired: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F9B1', { 'desc': 'man, curly haired: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F9B1', { 'desc': 'man, curly haired: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F9B1', { 'desc': 'man, curly haired: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F9B1', { 'desc': 'man, curly haired: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F9B1', { 'desc': 'woman, curly haired', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F9B1', { 'desc': 'woman, curly haired: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F9B1', { 'desc': 'woman, curly haired: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F9B1', { 'desc': 'woman, curly haired: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F9B1', { 'desc': 'woman, curly haired: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F9B1', { 'desc': 'woman, curly haired: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F9B2', { 'desc': 'man, bald', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F9B2', { 'desc': 'man, bald: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F9B2', { 'desc': 'man, bald: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F9B2', { 'desc': 'man, bald: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F9B2', { 'desc': 'man, bald: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F9B2', { 'desc': 'man, bald: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F9B2', { 'desc': 'woman, bald', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F9B2', { 'desc': 'woman, bald: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F9B2', { 'desc': 'woman, bald: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F9B2', { 'desc': 'woman, bald: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F9B2', { 'desc': 'woman, bald: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F9B2', { 'desc': 'woman, bald: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F9B3', { 'desc': 'man, white haired', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F468\U0001F3FB\U0000200D\U0001F9B3', { 'desc': 'man, white haired: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FC\U0000200D\U0001F9B3', { 'desc': 'man, white haired: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FD\U0000200D\U0001F9B3', { 'desc': 'man, white haired: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FE\U0000200D\U0001F9B3', { 'desc': 'man, white haired: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F468\U0001F3FF\U0000200D\U0001F9B3', { 'desc': 'man, white haired: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F9B3', { 'desc': 'woman, white haired', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F469\U0001F3FB\U0000200D\U0001F9B3', { 'desc': 'woman, white haired: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FC\U0000200D\U0001F9B3', { 'desc': 'woman, white haired: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FD\U0000200D\U0001F9B3', { 'desc': 'woman, white haired: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FE\U0000200D\U0001F9B3', { 'desc': 'woman, white haired: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }), ('\U0001F469\U0001F3FF\U0000200D\U0001F9B3', { 'desc': 'woman, white haired: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F935', { 'desc': 'man in tuxedo', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F935\U0001F3FB', { 'desc': 'man in tuxedo: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F935\U0001F3FC', { 'desc': 'man in tuxedo: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F935\U0001F3FD', { 'desc': 'man in tuxedo: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F935\U0001F3FE', { 'desc': 'man in tuxedo: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F935\U0001F3FF', { 'desc': 'man in tuxedo: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F470', { 'desc': 'bride with veil', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F470\U0001F3FB', { 'desc': 'bride with veil: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F470\U0001F3FC', { 'desc': 'bride with veil: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F470\U0001F3FD', { 'desc': 'bride with veil: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F470\U0001F3FE', { 'desc': 'bride with veil: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F470\U0001F3FF', { 'desc': 'bride with veil: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F930', { 'desc': 'pregnant woman', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F930\U0001F3FB', { 'desc': 'pregnant woman: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F930\U0001F3FC', { 'desc': 'pregnant woman: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F930\U0001F3FD', { 'desc': 'pregnant woman: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F930\U0001F3FE', { 'desc': 'pregnant woman: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F930\U0001F3FF', { 'desc': 'pregnant woman: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F931', { 'desc': 'breast-feeding', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F931\U0001F3FB', { 'desc': 'breast-feeding: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F931\U0001F3FC', { 'desc': 'breast-feeding: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F931\U0001F3FD', { 'desc': 'breast-feeding: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F931\U0001F3FE', { 'desc': 'breast-feeding: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F931\U0001F3FF', { 'desc': 'breast-feeding: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-role', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F47C', { 'desc': 'baby angel', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F47C\U0001F3FB', { 'desc': 'baby angel: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F47C\U0001F3FC', { 'desc': 'baby angel: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F47C\U0001F3FD', { 'desc': 'baby angel: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F47C\U0001F3FE', { 'desc': 'baby angel: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F47C\U0001F3FF', { 'desc': 'baby angel: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F385', { 'desc': 'Santa Claus', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F385\U0001F3FB', { 'desc': 'Santa Claus: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F385\U0001F3FC', { 'desc': 'Santa Claus: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F385\U0001F3FD', { 'desc': 'Santa Claus: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F385\U0001F3FE', { 'desc': 'Santa Claus: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F385\U0001F3FF', { 'desc': 'Santa Claus: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F936', { 'desc': 'Mrs. Claus', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F936\U0001F3FB', { 'desc': 'Mrs. Claus: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F936\U0001F3FC', { 'desc': 'Mrs. Claus: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F936\U0001F3FD', { 'desc': 'Mrs. Claus: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F936\U0001F3FE', { 'desc': 'Mrs. Claus: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F936\U0001F3FF', { 'desc': 'Mrs. Claus: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9B8', { 'desc': 'superhero', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B8\U0001F3FB', { 'desc': 'superhero: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B8\U0001F3FC', { 'desc': 'superhero: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B8\U0001F3FD', { 'desc': 'superhero: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B8\U0001F3FE', { 'desc': 'superhero: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B8\U0001F3FF', { 'desc': 'superhero: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9B8\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman superhero', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B8\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman superhero: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman superhero: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman superhero: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman superhero: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman superhero: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9B8\U0000200D\U00002640', { 'desc': 'woman superhero', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9B8\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman superhero: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman superhero: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman superhero: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman superhero: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman superhero: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9B8\U0000200D\U00002642\U0000FE0F', { 'desc': 'man superhero', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B8\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man superhero: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man superhero: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man superhero: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man superhero: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B8\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man superhero: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9B8\U0000200D\U00002642', { 'desc': 'man superhero', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9B8\U0001F3FB\U0000200D\U00002642', { 'desc': 'man superhero: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FC\U0000200D\U00002642', { 'desc': 'man superhero: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FD\U0000200D\U00002642', { 'desc': 'man superhero: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FE\U0000200D\U00002642', { 'desc': 'man superhero: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B8\U0001F3FF\U0000200D\U00002642', { 'desc': 'man superhero: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9B9', { 'desc': 'supervillain', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B9\U0001F3FB', { 'desc': 'supervillain: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B9\U0001F3FC', { 'desc': 'supervillain: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B9\U0001F3FD', { 'desc': 'supervillain: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B9\U0001F3FE', { 'desc': 'supervillain: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B9\U0001F3FF', { 'desc': 'supervillain: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9B9\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman supervillain', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B9\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman supervillain: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman supervillain: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman supervillain: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman supervillain: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman supervillain: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9B9\U0000200D\U00002640', { 'desc': 'woman supervillain', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9B9\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman supervillain: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman supervillain: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman supervillain: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman supervillain: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman supervillain: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9B9\U0000200D\U00002642\U0000FE0F', { 'desc': 'man supervillain', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B9\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man supervillain: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man supervillain: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man supervillain: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man supervillain: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9B9\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man supervillain: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9B9\U0000200D\U00002642', { 'desc': 'man supervillain', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9B9\U0001F3FB\U0000200D\U00002642', { 'desc': 'man supervillain: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FC\U0000200D\U00002642', { 'desc': 'man supervillain: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FD\U0000200D\U00002642', { 'desc': 'man supervillain: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FE\U0000200D\U00002642', { 'desc': 'man supervillain: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9B9\U0001F3FF\U0000200D\U00002642', { 'desc': 'man supervillain: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9D9', { 'desc': 'mage', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D9\U0001F3FB', { 'desc': 'mage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D9\U0001F3FC', { 'desc': 'mage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D9\U0001F3FD', { 'desc': 'mage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D9\U0001F3FE', { 'desc': 'mage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D9\U0001F3FF', { 'desc': 'mage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D9\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mage', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D9\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D9\U0000200D\U00002640', { 'desc': 'woman mage', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D9\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman mage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman mage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman mage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman mage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman mage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9D9\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mage', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D9\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9D9\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D9\U0000200D\U00002642', { 'desc': 'man mage', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D9\U0001F3FB\U0000200D\U00002642', { 'desc': 'man mage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FC\U0000200D\U00002642', { 'desc': 'man mage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FD\U0000200D\U00002642', { 'desc': 'man mage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FE\U0000200D\U00002642', { 'desc': 'man mage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9D9\U0001F3FF\U0000200D\U00002642', { 'desc': 'man mage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DA', { 'desc': 'fairy', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DA\U0001F3FB', { 'desc': 'fairy: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DA\U0001F3FC', { 'desc': 'fairy: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DA\U0001F3FD', { 'desc': 'fairy: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DA\U0001F3FE', { 'desc': 'fairy: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DA\U0001F3FF', { 'desc': 'fairy: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9DA\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman fairy', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DA\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman fairy: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman fairy: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman fairy: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman fairy: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman fairy: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DA\U0000200D\U00002640', { 'desc': 'woman fairy', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DA\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman fairy: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman fairy: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman fairy: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman fairy: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman fairy: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DA\U0000200D\U00002642\U0000FE0F', { 'desc': 'man fairy', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DA\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man fairy: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man fairy: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man fairy: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man fairy: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DA\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man fairy: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DA\U0000200D\U00002642', { 'desc': 'man fairy', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DA\U0001F3FB\U0000200D\U00002642', { 'desc': 'man fairy: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FC\U0000200D\U00002642', { 'desc': 'man fairy: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FD\U0000200D\U00002642', { 'desc': 'man fairy: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FE\U0000200D\U00002642', { 'desc': 'man fairy: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DA\U0001F3FF\U0000200D\U00002642', { 'desc': 'man fairy: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DB', { 'desc': 'vampire', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DB\U0001F3FB', { 'desc': 'vampire: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DB\U0001F3FC', { 'desc': 'vampire: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DB\U0001F3FD', { 'desc': 'vampire: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DB\U0001F3FE', { 'desc': 'vampire: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DB\U0001F3FF', { 'desc': 'vampire: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9DB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman vampire', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DB\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman vampire: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman vampire: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman vampire: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman vampire: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman vampire: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DB\U0000200D\U00002640', { 'desc': 'woman vampire', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DB\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman vampire: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman vampire: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman vampire: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman vampire: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman vampire: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man vampire', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DB\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man vampire: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man vampire: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man vampire: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man vampire: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DB\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man vampire: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DB\U0000200D\U00002642', { 'desc': 'man vampire', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DB\U0001F3FB\U0000200D\U00002642', { 'desc': 'man vampire: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FC\U0000200D\U00002642', { 'desc': 'man vampire: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FD\U0000200D\U00002642', { 'desc': 'man vampire: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FE\U0000200D\U00002642', { 'desc': 'man vampire: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DB\U0001F3FF\U0000200D\U00002642', { 'desc': 'man vampire: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DC', { 'desc': 'merperson', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DC\U0001F3FB', { 'desc': 'merperson: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DC\U0001F3FC', { 'desc': 'merperson: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DC\U0001F3FD', { 'desc': 'merperson: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DC\U0001F3FE', { 'desc': 'merperson: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DC\U0001F3FF', { 'desc': 'merperson: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9DC\U0000200D\U00002640\U0000FE0F', { 'desc': 'mermaid', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DC\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'mermaid: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'mermaid: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'mermaid: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'mermaid: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'mermaid: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DC\U0000200D\U00002640', { 'desc': 'mermaid', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DC\U0001F3FB\U0000200D\U00002640', { 'desc': 'mermaid: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FC\U0000200D\U00002640', { 'desc': 'mermaid: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FD\U0000200D\U00002640', { 'desc': 'mermaid: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FE\U0000200D\U00002640', { 'desc': 'mermaid: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FF\U0000200D\U00002640', { 'desc': 'mermaid: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DC\U0000200D\U00002642\U0000FE0F', { 'desc': 'merman', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DC\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'merman: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'merman: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'merman: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'merman: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DC\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'merman: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DC\U0000200D\U00002642', { 'desc': 'merman', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DC\U0001F3FB\U0000200D\U00002642', { 'desc': 'merman: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FC\U0000200D\U00002642', { 'desc': 'merman: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FD\U0000200D\U00002642', { 'desc': 'merman: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FE\U0000200D\U00002642', { 'desc': 'merman: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DC\U0001F3FF\U0000200D\U00002642', { 'desc': 'merman: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DD', { 'desc': 'elf', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DD\U0001F3FB', { 'desc': 'elf: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DD\U0001F3FC', { 'desc': 'elf: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DD\U0001F3FD', { 'desc': 'elf: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DD\U0001F3FE', { 'desc': 'elf: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9DD\U0001F3FF', { 'desc': 'elf: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9DD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman elf', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DD\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman elf: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman elf: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman elf: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman elf: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman elf: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DD\U0000200D\U00002640', { 'desc': 'woman elf', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DD\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman elf: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman elf: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman elf: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman elf: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman elf: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man elf', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9DD\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man elf: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man elf: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man elf: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man elf: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }), ('\U0001F9DD\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man elf: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DD\U0000200D\U00002642', { 'desc': 'man elf', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9DD\U0001F3FB\U0000200D\U00002642', { 'desc': 'man elf: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FC\U0000200D\U00002642', { 'desc': 'man elf: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FD\U0000200D\U00002642', { 'desc': 'man elf: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FE\U0000200D\U00002642', { 'desc': 'man elf: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DD\U0001F3FF\U0000200D\U00002642', { 'desc': 'man elf: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }) ]) }), ('\U0001F9DE', { 'desc': 'genie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9DE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman genie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DE\U0000200D\U00002640', { 'desc': 'woman genie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man genie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DE\U0000200D\U00002642', { 'desc': 'man genie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DF', { 'desc': 'zombie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9DF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman zombie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DF\U0000200D\U00002640', { 'desc': 'woman zombie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F9DF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man zombie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F9DF\U0000200D\U00002642', { 'desc': 'man zombie', 'group': 'Smileys & People', 'subgroup': 'person-fantasy', 'fully-qualified': False }), ('\U0001F64D', { 'desc': 'person frowning', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64D\U0001F3FB', { 'desc': 'person frowning: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64D\U0001F3FC', { 'desc': 'person frowning: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64D\U0001F3FD', { 'desc': 'person frowning: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64D\U0001F3FE', { 'desc': 'person frowning: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64D\U0001F3FF', { 'desc': 'person frowning: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F64D\U0000200D\U00002642\U0000FE0F', { 'desc': 'man frowning', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64D\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man frowning: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man frowning: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man frowning: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man frowning: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man frowning: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F64D\U0000200D\U00002642', { 'desc': 'man frowning', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F64D\U0001F3FB\U0000200D\U00002642', { 'desc': 'man frowning: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FC\U0000200D\U00002642', { 'desc': 'man frowning: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FD\U0000200D\U00002642', { 'desc': 'man frowning: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FE\U0000200D\U00002642', { 'desc': 'man frowning: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FF\U0000200D\U00002642', { 'desc': 'man frowning: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F64D\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman frowning', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64D\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman frowning: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman frowning: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman frowning: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman frowning: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64D\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman frowning: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F64D\U0000200D\U00002640', { 'desc': 'woman frowning', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F64D\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman frowning: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman frowning: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman frowning: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman frowning: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64D\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman frowning: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F64E', { 'desc': 'person pouting', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64E\U0001F3FB', { 'desc': 'person pouting: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64E\U0001F3FC', { 'desc': 'person pouting: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64E\U0001F3FD', { 'desc': 'person pouting: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64E\U0001F3FE', { 'desc': 'person pouting: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64E\U0001F3FF', { 'desc': 'person pouting: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F64E\U0000200D\U00002642\U0000FE0F', { 'desc': 'man pouting', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64E\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man pouting: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man pouting: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man pouting: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man pouting: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man pouting: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F64E\U0000200D\U00002642', { 'desc': 'man pouting', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F64E\U0001F3FB\U0000200D\U00002642', { 'desc': 'man pouting: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FC\U0000200D\U00002642', { 'desc': 'man pouting: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FD\U0000200D\U00002642', { 'desc': 'man pouting: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FE\U0000200D\U00002642', { 'desc': 'man pouting: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FF\U0000200D\U00002642', { 'desc': 'man pouting: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F64E\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman pouting', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64E\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman pouting: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman pouting: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman pouting: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman pouting: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64E\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman pouting: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F64E\U0000200D\U00002640', { 'desc': 'woman pouting', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F64E\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman pouting: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman pouting: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman pouting: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman pouting: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64E\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman pouting: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F645', { 'desc': 'person gesturing NO', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F645\U0001F3FB', { 'desc': 'person gesturing NO: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F645\U0001F3FC', { 'desc': 'person gesturing NO: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F645\U0001F3FD', { 'desc': 'person gesturing NO: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F645\U0001F3FE', { 'desc': 'person gesturing NO: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F645\U0001F3FF', { 'desc': 'person gesturing NO: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F645\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing NO', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F645\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing NO: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing NO: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing NO: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing NO: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing NO: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F645\U0000200D\U00002642', { 'desc': 'man gesturing NO', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F645\U0001F3FB\U0000200D\U00002642', { 'desc': 'man gesturing NO: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FC\U0000200D\U00002642', { 'desc': 'man gesturing NO: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FD\U0000200D\U00002642', { 'desc': 'man gesturing NO: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FE\U0000200D\U00002642', { 'desc': 'man gesturing NO: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FF\U0000200D\U00002642', { 'desc': 'man gesturing NO: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F645\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing NO', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F645\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing NO: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing NO: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing NO: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing NO: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F645\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing NO: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F645\U0000200D\U00002640', { 'desc': 'woman gesturing NO', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F645\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman gesturing NO: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman gesturing NO: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman gesturing NO: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman gesturing NO: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F645\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman gesturing NO: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F646', { 'desc': 'person gesturing OK', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F646\U0001F3FB', { 'desc': 'person gesturing OK: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F646\U0001F3FC', { 'desc': 'person gesturing OK: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F646\U0001F3FD', { 'desc': 'person gesturing OK: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F646\U0001F3FE', { 'desc': 'person gesturing OK: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F646\U0001F3FF', { 'desc': 'person gesturing OK: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F646\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing OK', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F646\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing OK: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing OK: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing OK: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing OK: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man gesturing OK: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F646\U0000200D\U00002642', { 'desc': 'man gesturing OK', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F646\U0001F3FB\U0000200D\U00002642', { 'desc': 'man gesturing OK: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FC\U0000200D\U00002642', { 'desc': 'man gesturing OK: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FD\U0000200D\U00002642', { 'desc': 'man gesturing OK: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FE\U0000200D\U00002642', { 'desc': 'man gesturing OK: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FF\U0000200D\U00002642', { 'desc': 'man gesturing OK: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F646\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing OK', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F646\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing OK: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing OK: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing OK: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing OK: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F646\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman gesturing OK: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F646\U0000200D\U00002640', { 'desc': 'woman gesturing OK', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F646\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman gesturing OK: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman gesturing OK: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman gesturing OK: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman gesturing OK: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F646\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman gesturing OK: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F481', { 'desc': 'person tipping hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F481\U0001F3FB', { 'desc': 'person tipping hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F481\U0001F3FC', { 'desc': 'person tipping hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F481\U0001F3FD', { 'desc': 'person tipping hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F481\U0001F3FE', { 'desc': 'person tipping hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F481\U0001F3FF', { 'desc': 'person tipping hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F481\U0000200D\U00002642\U0000FE0F', { 'desc': 'man tipping hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F481\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man tipping hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man tipping hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man tipping hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man tipping hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man tipping hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F481\U0000200D\U00002642', { 'desc': 'man tipping hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F481\U0001F3FB\U0000200D\U00002642', { 'desc': 'man tipping hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FC\U0000200D\U00002642', { 'desc': 'man tipping hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FD\U0000200D\U00002642', { 'desc': 'man tipping hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FE\U0000200D\U00002642', { 'desc': 'man tipping hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FF\U0000200D\U00002642', { 'desc': 'man tipping hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F481\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman tipping hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F481\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman tipping hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman tipping hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman tipping hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman tipping hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F481\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman tipping hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F481\U0000200D\U00002640', { 'desc': 'woman tipping hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F481\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman tipping hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman tipping hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman tipping hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman tipping hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F481\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman tipping hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F64B', { 'desc': 'person raising hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64B\U0001F3FB', { 'desc': 'person raising hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64B\U0001F3FC', { 'desc': 'person raising hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64B\U0001F3FD', { 'desc': 'person raising hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64B\U0001F3FE', { 'desc': 'person raising hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64B\U0001F3FF', { 'desc': 'person raising hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F64B\U0000200D\U00002642\U0000FE0F', { 'desc': 'man raising hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64B\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man raising hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man raising hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man raising hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man raising hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man raising hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F64B\U0000200D\U00002642', { 'desc': 'man raising hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F64B\U0001F3FB\U0000200D\U00002642', { 'desc': 'man raising hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FC\U0000200D\U00002642', { 'desc': 'man raising hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FD\U0000200D\U00002642', { 'desc': 'man raising hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FE\U0000200D\U00002642', { 'desc': 'man raising hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FF\U0000200D\U00002642', { 'desc': 'man raising hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F64B\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman raising hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64B\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman raising hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman raising hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman raising hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman raising hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F64B\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman raising hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F64B\U0000200D\U00002640', { 'desc': 'woman raising hand', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F64B\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman raising hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman raising hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman raising hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman raising hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F64B\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman raising hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F647', { 'desc': 'person bowing', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F647\U0001F3FB', { 'desc': 'person bowing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F647\U0001F3FC', { 'desc': 'person bowing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F647\U0001F3FD', { 'desc': 'person bowing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F647\U0001F3FE', { 'desc': 'person bowing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F647\U0001F3FF', { 'desc': 'person bowing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F647\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bowing', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F647\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bowing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bowing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bowing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bowing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bowing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F647\U0000200D\U00002642', { 'desc': 'man bowing', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F647\U0001F3FB\U0000200D\U00002642', { 'desc': 'man bowing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FC\U0000200D\U00002642', { 'desc': 'man bowing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FD\U0000200D\U00002642', { 'desc': 'man bowing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FE\U0000200D\U00002642', { 'desc': 'man bowing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FF\U0000200D\U00002642', { 'desc': 'man bowing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F647\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bowing', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F647\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bowing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bowing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bowing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bowing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F647\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bowing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F647\U0000200D\U00002640', { 'desc': 'woman bowing', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F647\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman bowing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman bowing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman bowing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman bowing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F647\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman bowing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F926', { 'desc': 'person facepalming', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F926\U0001F3FB', { 'desc': 'person facepalming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F926\U0001F3FC', { 'desc': 'person facepalming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F926\U0001F3FD', { 'desc': 'person facepalming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F926\U0001F3FE', { 'desc': 'person facepalming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F926\U0001F3FF', { 'desc': 'person facepalming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F926\U0000200D\U00002642\U0000FE0F', { 'desc': 'man facepalming', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F926\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man facepalming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man facepalming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man facepalming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man facepalming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man facepalming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F926\U0000200D\U00002642', { 'desc': 'man facepalming', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F926\U0001F3FB\U0000200D\U00002642', { 'desc': 'man facepalming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FC\U0000200D\U00002642', { 'desc': 'man facepalming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FD\U0000200D\U00002642', { 'desc': 'man facepalming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FE\U0000200D\U00002642', { 'desc': 'man facepalming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FF\U0000200D\U00002642', { 'desc': 'man facepalming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F926\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman facepalming', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F926\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman facepalming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman facepalming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman facepalming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman facepalming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F926\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman facepalming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F926\U0000200D\U00002640', { 'desc': 'woman facepalming', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F926\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman facepalming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman facepalming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman facepalming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman facepalming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F926\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman facepalming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F937', { 'desc': 'person shrugging', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F937\U0001F3FB', { 'desc': 'person shrugging: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F937\U0001F3FC', { 'desc': 'person shrugging: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F937\U0001F3FD', { 'desc': 'person shrugging: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F937\U0001F3FE', { 'desc': 'person shrugging: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F937\U0001F3FF', { 'desc': 'person shrugging: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F937\U0000200D\U00002642\U0000FE0F', { 'desc': 'man shrugging', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F937\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man shrugging: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man shrugging: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man shrugging: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man shrugging: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man shrugging: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F937\U0000200D\U00002642', { 'desc': 'man shrugging', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F937\U0001F3FB\U0000200D\U00002642', { 'desc': 'man shrugging: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FC\U0000200D\U00002642', { 'desc': 'man shrugging: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FD\U0000200D\U00002642', { 'desc': 'man shrugging: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FE\U0000200D\U00002642', { 'desc': 'man shrugging: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FF\U0000200D\U00002642', { 'desc': 'man shrugging: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F937\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman shrugging', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F937\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman shrugging: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman shrugging: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman shrugging: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman shrugging: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }), ('\U0001F937\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman shrugging: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F937\U0000200D\U00002640', { 'desc': 'woman shrugging', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F937\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman shrugging: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman shrugging: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman shrugging: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman shrugging: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }), ('\U0001F937\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman shrugging: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-gesture', 'fully-qualified': False }) ]) }), ('\U0001F486', { 'desc': 'person getting massage', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F486\U0001F3FB', { 'desc': 'person getting massage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F486\U0001F3FC', { 'desc': 'person getting massage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F486\U0001F3FD', { 'desc': 'person getting massage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F486\U0001F3FE', { 'desc': 'person getting massage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F486\U0001F3FF', { 'desc': 'person getting massage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F486\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting massage', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F486\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting massage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting massage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting massage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting massage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting massage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F486\U0000200D\U00002642', { 'desc': 'man getting massage', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F486\U0001F3FB\U0000200D\U00002642', { 'desc': 'man getting massage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FC\U0000200D\U00002642', { 'desc': 'man getting massage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FD\U0000200D\U00002642', { 'desc': 'man getting massage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FE\U0000200D\U00002642', { 'desc': 'man getting massage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FF\U0000200D\U00002642', { 'desc': 'man getting massage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F486\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting massage', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F486\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting massage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting massage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting massage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting massage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F486\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting massage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F486\U0000200D\U00002640', { 'desc': 'woman getting massage', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F486\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman getting massage: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman getting massage: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman getting massage: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman getting massage: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F486\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman getting massage: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F487', { 'desc': 'person getting haircut', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F487\U0001F3FB', { 'desc': 'person getting haircut: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F487\U0001F3FC', { 'desc': 'person getting haircut: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F487\U0001F3FD', { 'desc': 'person getting haircut: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F487\U0001F3FE', { 'desc': 'person getting haircut: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F487\U0001F3FF', { 'desc': 'person getting haircut: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F487\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting haircut', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F487\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting haircut: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting haircut: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting haircut: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting haircut: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man getting haircut: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F487\U0000200D\U00002642', { 'desc': 'man getting haircut', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F487\U0001F3FB\U0000200D\U00002642', { 'desc': 'man getting haircut: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FC\U0000200D\U00002642', { 'desc': 'man getting haircut: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FD\U0000200D\U00002642', { 'desc': 'man getting haircut: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FE\U0000200D\U00002642', { 'desc': 'man getting haircut: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FF\U0000200D\U00002642', { 'desc': 'man getting haircut: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F487\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting haircut', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F487\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting haircut: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting haircut: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting haircut: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting haircut: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F487\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman getting haircut: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F487\U0000200D\U00002640', { 'desc': 'woman getting haircut', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F487\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman getting haircut: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman getting haircut: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman getting haircut: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman getting haircut: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F487\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman getting haircut: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F6B6', { 'desc': 'person walking', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B6\U0001F3FB', { 'desc': 'person walking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B6\U0001F3FC', { 'desc': 'person walking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B6\U0001F3FD', { 'desc': 'person walking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B6\U0001F3FE', { 'desc': 'person walking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B6\U0001F3FF', { 'desc': 'person walking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F6B6\U0000200D\U00002642\U0000FE0F', { 'desc': 'man walking', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B6\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man walking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man walking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man walking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man walking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man walking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6B6\U0000200D\U00002642', { 'desc': 'man walking', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6B6\U0001F3FB\U0000200D\U00002642', { 'desc': 'man walking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FC\U0000200D\U00002642', { 'desc': 'man walking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FD\U0000200D\U00002642', { 'desc': 'man walking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FE\U0000200D\U00002642', { 'desc': 'man walking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FF\U0000200D\U00002642', { 'desc': 'man walking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F6B6\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman walking', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B6\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman walking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman walking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman walking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman walking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F6B6\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman walking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6B6\U0000200D\U00002640', { 'desc': 'woman walking', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6B6\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman walking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman walking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman walking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman walking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F6B6\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman walking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F3C3', { 'desc': 'person running', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C3\U0001F3FB', { 'desc': 'person running: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C3\U0001F3FC', { 'desc': 'person running: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C3\U0001F3FD', { 'desc': 'person running: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C3\U0001F3FE', { 'desc': 'person running: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C3\U0001F3FF', { 'desc': 'person running: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F3C3\U0000200D\U00002642\U0000FE0F', { 'desc': 'man running', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C3\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man running: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man running: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man running: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man running: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man running: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3C3\U0000200D\U00002642', { 'desc': 'man running', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3C3\U0001F3FB\U0000200D\U00002642', { 'desc': 'man running: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FC\U0000200D\U00002642', { 'desc': 'man running: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FD\U0000200D\U00002642', { 'desc': 'man running: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FE\U0000200D\U00002642', { 'desc': 'man running: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FF\U0000200D\U00002642', { 'desc': 'man running: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F3C3\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman running', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C3\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman running: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman running: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman running: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman running: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F3C3\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman running: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3C3\U0000200D\U00002640', { 'desc': 'woman running', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3C3\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman running: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman running: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman running: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman running: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F3C3\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman running: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F483', { 'desc': 'woman dancing', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F483\U0001F3FB', { 'desc': 'woman dancing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F483\U0001F3FC', { 'desc': 'woman dancing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F483\U0001F3FD', { 'desc': 'woman dancing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F483\U0001F3FE', { 'desc': 'woman dancing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F483\U0001F3FF', { 'desc': 'woman dancing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F57A', { 'desc': 'man dancing', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F57A\U0001F3FB', { 'desc': 'man dancing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F57A\U0001F3FC', { 'desc': 'man dancing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F57A\U0001F3FD', { 'desc': 'man dancing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F57A\U0001F3FE', { 'desc': 'man dancing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F57A\U0001F3FF', { 'desc': 'man dancing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F46F', { 'desc': 'people with bunny ears', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F46F\U0000200D\U00002642\U0000FE0F', { 'desc': 'men with bunny ears', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F46F\U0000200D\U00002642', { 'desc': 'men with bunny ears', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F46F\U0000200D\U00002640\U0000FE0F', { 'desc': 'women with bunny ears', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F46F\U0000200D\U00002640', { 'desc': 'women with bunny ears', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6', { 'desc': 'person in steamy room', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D6\U0001F3FB', { 'desc': 'person in steamy room: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D6\U0001F3FC', { 'desc': 'person in steamy room: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D6\U0001F3FD', { 'desc': 'person in steamy room: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D6\U0001F3FE', { 'desc': 'person in steamy room: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D6\U0001F3FF', { 'desc': 'person in steamy room: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D6\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in steamy room', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D6\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in steamy room: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in steamy room: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in steamy room: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in steamy room: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in steamy room: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D6\U0000200D\U00002640', { 'desc': 'woman in steamy room', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D6\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman in steamy room: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman in steamy room: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman in steamy room: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman in steamy room: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman in steamy room: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F9D6\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in steamy room', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D6\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in steamy room: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in steamy room: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in steamy room: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in steamy room: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D6\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in steamy room: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D6\U0000200D\U00002642', { 'desc': 'man in steamy room', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D6\U0001F3FB\U0000200D\U00002642', { 'desc': 'man in steamy room: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FC\U0000200D\U00002642', { 'desc': 'man in steamy room: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FD\U0000200D\U00002642', { 'desc': 'man in steamy room: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FE\U0000200D\U00002642', { 'desc': 'man in steamy room: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D6\U0001F3FF\U0000200D\U00002642', { 'desc': 'man in steamy room: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F9D7', { 'desc': 'person climbing', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D7\U0001F3FB', { 'desc': 'person climbing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D7\U0001F3FC', { 'desc': 'person climbing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D7\U0001F3FD', { 'desc': 'person climbing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D7\U0001F3FE', { 'desc': 'person climbing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D7\U0001F3FF', { 'desc': 'person climbing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D7\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman climbing', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D7\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman climbing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman climbing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman climbing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman climbing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman climbing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D7\U0000200D\U00002640', { 'desc': 'woman climbing', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D7\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman climbing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman climbing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman climbing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman climbing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman climbing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F9D7\U0000200D\U00002642\U0000FE0F', { 'desc': 'man climbing', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D7\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man climbing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man climbing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man climbing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man climbing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D7\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man climbing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D7\U0000200D\U00002642', { 'desc': 'man climbing', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D7\U0001F3FB\U0000200D\U00002642', { 'desc': 'man climbing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FC\U0000200D\U00002642', { 'desc': 'man climbing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FD\U0000200D\U00002642', { 'desc': 'man climbing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FE\U0000200D\U00002642', { 'desc': 'man climbing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D7\U0001F3FF\U0000200D\U00002642', { 'desc': 'man climbing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F9D8', { 'desc': 'person in lotus position', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D8\U0001F3FB', { 'desc': 'person in lotus position: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D8\U0001F3FC', { 'desc': 'person in lotus position: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D8\U0001F3FD', { 'desc': 'person in lotus position: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D8\U0001F3FE', { 'desc': 'person in lotus position: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9D8\U0001F3FF', { 'desc': 'person in lotus position: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9D8\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in lotus position', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D8\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in lotus position: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in lotus position: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in lotus position: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in lotus position: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman in lotus position: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D8\U0000200D\U00002640', { 'desc': 'woman in lotus position', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D8\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman in lotus position: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman in lotus position: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman in lotus position: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman in lotus position: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman in lotus position: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F9D8\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in lotus position', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9D8\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in lotus position: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in lotus position: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in lotus position: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in lotus position: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F9D8\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man in lotus position: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F9D8\U0000200D\U00002642', { 'desc': 'man in lotus position', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F9D8\U0001F3FB\U0000200D\U00002642', { 'desc': 'man in lotus position: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FC\U0000200D\U00002642', { 'desc': 'man in lotus position: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FD\U0000200D\U00002642', { 'desc': 'man in lotus position: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FE\U0000200D\U00002642', { 'desc': 'man in lotus position: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }), ('\U0001F9D8\U0001F3FF\U0000200D\U00002642', { 'desc': 'man in lotus position: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False }) ]) }), ('\U0001F6C0', { 'desc': 'person taking bath', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6C0\U0001F3FB', { 'desc': 'person taking bath: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6C0\U0001F3FC', { 'desc': 'person taking bath: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6C0\U0001F3FD', { 'desc': 'person taking bath: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6C0\U0001F3FE', { 'desc': 'person taking bath: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6C0\U0001F3FF', { 'desc': 'person taking bath: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F6CC', { 'desc': 'person in bed', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6CC\U0001F3FB', { 'desc': 'person in bed: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6CC\U0001F3FC', { 'desc': 'person in bed: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6CC\U0001F3FD', { 'desc': 'person in bed: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6CC\U0001F3FE', { 'desc': 'person in bed: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6CC\U0001F3FF', { 'desc': 'person in bed: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F574\U0000FE0F', { 'desc': 'man in suit levitating', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F574\U0001F3FB', { 'desc': 'man in suit levitating: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F574\U0001F3FC', { 'desc': 'man in suit levitating: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F574\U0001F3FD', { 'desc': 'man in suit levitating: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F574\U0001F3FE', { 'desc': 'man in suit levitating: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F574\U0001F3FF', { 'desc': 'man in suit levitating: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0001F574', { 'desc': 'man in suit levitating', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F5E3\U0000FE0F', { 'desc': 'speaking head', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True }), ('\U0001F5E3', { 'desc': 'speaking head', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F464', { 'desc': 'bust in silhouette', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F465', { 'desc': 'busts in silhouette', 'group': 'Smileys & People', 'subgroup': 'person-activity', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F93A', { 'desc': 'person fencing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3C7', { 'desc': 'horse racing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C7\U0001F3FB', { 'desc': 'horse racing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C7\U0001F3FC', { 'desc': 'horse racing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C7\U0001F3FD', { 'desc': 'horse racing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C7\U0001F3FE', { 'desc': 'horse racing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C7\U0001F3FF', { 'desc': 'horse racing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U000026F7\U0000FE0F', { 'desc': 'skier', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F7', { 'desc': 'skier', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3C2', { 'desc': 'snowboarder', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C2\U0001F3FB', { 'desc': 'snowboarder: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C2\U0001F3FC', { 'desc': 'snowboarder: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C2\U0001F3FD', { 'desc': 'snowboarder: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C2\U0001F3FE', { 'desc': 'snowboarder: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C2\U0001F3FF', { 'desc': 'snowboarder: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F3CC\U0000FE0F', { 'desc': 'person golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CC\U0001F3FB', { 'desc': 'person golfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CC\U0001F3FC', { 'desc': 'person golfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CC\U0001F3FD', { 'desc': 'person golfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CC\U0001F3FE', { 'desc': 'person golfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CC\U0001F3FF', { 'desc': 'person golfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0001F3CC', { 'desc': 'person golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F3CC\U0000FE0F\U0000200D\U00002642\U0000FE0F', { 'desc': 'man golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CC\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man golfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man golfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man golfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man golfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man golfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3CC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0000FE0F\U0000200D\U00002642', { 'desc': 'man golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3CC\U0001F3FB\U0000200D\U00002642', { 'desc': 'man golfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FC\U0000200D\U00002642', { 'desc': 'man golfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FD\U0000200D\U00002642', { 'desc': 'man golfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FE\U0000200D\U00002642', { 'desc': 'man golfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FF\U0000200D\U00002642', { 'desc': 'man golfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3CC\U0000200D\U00002642', { 'desc': 'man golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0000FE0F\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CC\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman golfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman golfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman golfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman golfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CC\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman golfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3CC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0000FE0F\U0000200D\U00002640', { 'desc': 'woman golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3CC\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman golfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman golfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman golfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman golfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CC\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman golfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3CC\U0000200D\U00002640', { 'desc': 'woman golfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4', { 'desc': 'person surfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C4\U0001F3FB', { 'desc': 'person surfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C4\U0001F3FC', { 'desc': 'person surfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C4\U0001F3FD', { 'desc': 'person surfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C4\U0001F3FE', { 'desc': 'person surfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3C4\U0001F3FF', { 'desc': 'person surfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F3C4\U0000200D\U00002642\U0000FE0F', { 'desc': 'man surfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C4\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man surfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man surfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man surfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man surfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man surfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3C4\U0000200D\U00002642', { 'desc': 'man surfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3C4\U0001F3FB\U0000200D\U00002642', { 'desc': 'man surfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FC\U0000200D\U00002642', { 'desc': 'man surfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FD\U0000200D\U00002642', { 'desc': 'man surfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FE\U0000200D\U00002642', { 'desc': 'man surfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FF\U0000200D\U00002642', { 'desc': 'man surfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3C4\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman surfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3C4\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman surfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman surfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman surfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman surfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3C4\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman surfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3C4\U0000200D\U00002640', { 'desc': 'woman surfing', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3C4\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman surfing: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman surfing: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman surfing: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman surfing: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3C4\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman surfing: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F6A3', { 'desc': 'person rowing boat', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6A3\U0001F3FB', { 'desc': 'person rowing boat: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6A3\U0001F3FC', { 'desc': 'person rowing boat: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6A3\U0001F3FD', { 'desc': 'person rowing boat: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6A3\U0001F3FE', { 'desc': 'person rowing boat: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6A3\U0001F3FF', { 'desc': 'person rowing boat: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F6A3\U0000200D\U00002642\U0000FE0F', { 'desc': 'man rowing boat', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6A3\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man rowing boat: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man rowing boat: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man rowing boat: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man rowing boat: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man rowing boat: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6A3\U0000200D\U00002642', { 'desc': 'man rowing boat', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6A3\U0001F3FB\U0000200D\U00002642', { 'desc': 'man rowing boat: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FC\U0000200D\U00002642', { 'desc': 'man rowing boat: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FD\U0000200D\U00002642', { 'desc': 'man rowing boat: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FE\U0000200D\U00002642', { 'desc': 'man rowing boat: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FF\U0000200D\U00002642', { 'desc': 'man rowing boat: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F6A3\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman rowing boat', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6A3\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman rowing boat: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman rowing boat: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman rowing boat: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman rowing boat: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6A3\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman rowing boat: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6A3\U0000200D\U00002640', { 'desc': 'woman rowing boat', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6A3\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman rowing boat: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman rowing boat: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman rowing boat: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman rowing boat: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6A3\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman rowing boat: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3CA', { 'desc': 'person swimming', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CA\U0001F3FB', { 'desc': 'person swimming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CA\U0001F3FC', { 'desc': 'person swimming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CA\U0001F3FD', { 'desc': 'person swimming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CA\U0001F3FE', { 'desc': 'person swimming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CA\U0001F3FF', { 'desc': 'person swimming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F3CA\U0000200D\U00002642\U0000FE0F', { 'desc': 'man swimming', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CA\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man swimming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man swimming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man swimming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man swimming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man swimming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3CA\U0000200D\U00002642', { 'desc': 'man swimming', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3CA\U0001F3FB\U0000200D\U00002642', { 'desc': 'man swimming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FC\U0000200D\U00002642', { 'desc': 'man swimming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FD\U0000200D\U00002642', { 'desc': 'man swimming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FE\U0000200D\U00002642', { 'desc': 'man swimming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FF\U0000200D\U00002642', { 'desc': 'man swimming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3CA\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman swimming', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CA\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman swimming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman swimming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman swimming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman swimming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CA\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman swimming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3CA\U0000200D\U00002640', { 'desc': 'woman swimming', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3CA\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman swimming: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman swimming: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman swimming: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman swimming: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CA\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman swimming: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U000026F9\U0000FE0F', { 'desc': 'person bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U000026F9\U0001F3FB', { 'desc': 'person bouncing ball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U000026F9\U0001F3FC', { 'desc': 'person bouncing ball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U000026F9\U0001F3FD', { 'desc': 'person bouncing ball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U000026F9\U0001F3FE', { 'desc': 'person bouncing ball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U000026F9\U0001F3FF', { 'desc': 'person bouncing ball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U000026F9', { 'desc': 'person bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U000026F9\U0000FE0F\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U000026F9\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bouncing ball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bouncing ball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bouncing ball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bouncing ball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bouncing ball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U000026F9\U0000200D\U00002642\U0000FE0F', { 'desc': 'man bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0000FE0F\U0000200D\U00002642', { 'desc': 'man bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U000026F9\U0001F3FB\U0000200D\U00002642', { 'desc': 'man bouncing ball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FC\U0000200D\U00002642', { 'desc': 'man bouncing ball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FD\U0000200D\U00002642', { 'desc': 'man bouncing ball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FE\U0000200D\U00002642', { 'desc': 'man bouncing ball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FF\U0000200D\U00002642', { 'desc': 'man bouncing ball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U000026F9\U0000200D\U00002642', { 'desc': 'man bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0000FE0F\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U000026F9\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bouncing ball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bouncing ball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bouncing ball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bouncing ball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U000026F9\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bouncing ball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U000026F9\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0000FE0F\U0000200D\U00002640', { 'desc': 'woman bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U000026F9\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman bouncing ball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman bouncing ball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman bouncing ball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman bouncing ball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U000026F9\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman bouncing ball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U000026F9\U0000200D\U00002640', { 'desc': 'woman bouncing ball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0000FE0F', { 'desc': 'person lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CB\U0001F3FB', { 'desc': 'person lifting weights: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CB\U0001F3FC', { 'desc': 'person lifting weights: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CB\U0001F3FD', { 'desc': 'person lifting weights: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CB\U0001F3FE', { 'desc': 'person lifting weights: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F3CB\U0001F3FF', { 'desc': 'person lifting weights: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0001F3CB', { 'desc': 'person lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F3CB\U0000FE0F\U0000200D\U00002642\U0000FE0F', { 'desc': 'man lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CB\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man lifting weights: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man lifting weights: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man lifting weights: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man lifting weights: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man lifting weights: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3CB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0000FE0F\U0000200D\U00002642', { 'desc': 'man lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3CB\U0001F3FB\U0000200D\U00002642', { 'desc': 'man lifting weights: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FC\U0000200D\U00002642', { 'desc': 'man lifting weights: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FD\U0000200D\U00002642', { 'desc': 'man lifting weights: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FE\U0000200D\U00002642', { 'desc': 'man lifting weights: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FF\U0000200D\U00002642', { 'desc': 'man lifting weights: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3CB\U0000200D\U00002642', { 'desc': 'man lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0000FE0F\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F3CB\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman lifting weights: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman lifting weights: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman lifting weights: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman lifting weights: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CB\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman lifting weights: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F3CB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0000FE0F\U0000200D\U00002640', { 'desc': 'woman lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F3CB\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman lifting weights: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman lifting weights: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman lifting weights: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman lifting weights: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F3CB\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman lifting weights: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3CB\U0000200D\U00002640', { 'desc': 'woman lifting weights', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4', { 'desc': 'person biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B4\U0001F3FB', { 'desc': 'person biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B4\U0001F3FC', { 'desc': 'person biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B4\U0001F3FD', { 'desc': 'person biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B4\U0001F3FE', { 'desc': 'person biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B4\U0001F3FF', { 'desc': 'person biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F6B4\U0000200D\U00002642\U0000FE0F', { 'desc': 'man biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B4\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6B4\U0000200D\U00002642', { 'desc': 'man biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6B4\U0001F3FB\U0000200D\U00002642', { 'desc': 'man biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FC\U0000200D\U00002642', { 'desc': 'man biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FD\U0000200D\U00002642', { 'desc': 'man biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FE\U0000200D\U00002642', { 'desc': 'man biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FF\U0000200D\U00002642', { 'desc': 'man biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F6B4\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B4\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B4\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6B4\U0000200D\U00002640', { 'desc': 'woman biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6B4\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B4\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F6B5', { 'desc': 'person mountain biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B5\U0001F3FB', { 'desc': 'person mountain biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B5\U0001F3FC', { 'desc': 'person mountain biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B5\U0001F3FD', { 'desc': 'person mountain biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B5\U0001F3FE', { 'desc': 'person mountain biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F6B5\U0001F3FF', { 'desc': 'person mountain biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F6B5\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mountain biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B5\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mountain biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mountain biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mountain biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mountain biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man mountain biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6B5\U0000200D\U00002642', { 'desc': 'man mountain biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6B5\U0001F3FB\U0000200D\U00002642', { 'desc': 'man mountain biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FC\U0000200D\U00002642', { 'desc': 'man mountain biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FD\U0000200D\U00002642', { 'desc': 'man mountain biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FE\U0000200D\U00002642', { 'desc': 'man mountain biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FF\U0000200D\U00002642', { 'desc': 'man mountain biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F6B5\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mountain biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F6B5\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mountain biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mountain biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mountain biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mountain biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F6B5\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman mountain biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F6B5\U0000200D\U00002640', { 'desc': 'woman mountain biking', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F6B5\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman mountain biking: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman mountain biking: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman mountain biking: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman mountain biking: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F6B5\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman mountain biking: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F3CE\U0000FE0F', { 'desc': 'racing car', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CE', { 'desc': 'racing car', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3CD\U0000FE0F', { 'desc': 'motorcycle', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F3CD', { 'desc': 'motorcycle', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F938', { 'desc': 'person cartwheeling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F938\U0001F3FB', { 'desc': 'person cartwheeling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F938\U0001F3FC', { 'desc': 'person cartwheeling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F938\U0001F3FD', { 'desc': 'person cartwheeling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F938\U0001F3FE', { 'desc': 'person cartwheeling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F938\U0001F3FF', { 'desc': 'person cartwheeling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F938\U0000200D\U00002642\U0000FE0F', { 'desc': 'man cartwheeling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F938\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man cartwheeling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man cartwheeling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man cartwheeling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man cartwheeling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man cartwheeling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F938\U0000200D\U00002642', { 'desc': 'man cartwheeling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F938\U0001F3FB\U0000200D\U00002642', { 'desc': 'man cartwheeling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FC\U0000200D\U00002642', { 'desc': 'man cartwheeling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FD\U0000200D\U00002642', { 'desc': 'man cartwheeling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FE\U0000200D\U00002642', { 'desc': 'man cartwheeling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FF\U0000200D\U00002642', { 'desc': 'man cartwheeling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F938\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman cartwheeling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F938\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman cartwheeling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman cartwheeling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman cartwheeling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman cartwheeling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F938\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman cartwheeling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F938\U0000200D\U00002640', { 'desc': 'woman cartwheeling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F938\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman cartwheeling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman cartwheeling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman cartwheeling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman cartwheeling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F938\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman cartwheeling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F93C', { 'desc': 'people wrestling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F93C\U0000200D\U00002642\U0000FE0F', { 'desc': 'men wrestling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F93C\U0000200D\U00002642', { 'desc': 'men wrestling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93C\U0000200D\U00002640\U0000FE0F', { 'desc': 'women wrestling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F93C\U0000200D\U00002640', { 'desc': 'women wrestling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D', { 'desc': 'person playing water polo', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F93D\U0001F3FB', { 'desc': 'person playing water polo: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93D\U0001F3FC', { 'desc': 'person playing water polo: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93D\U0001F3FD', { 'desc': 'person playing water polo: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93D\U0001F3FE', { 'desc': 'person playing water polo: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93D\U0001F3FF', { 'desc': 'person playing water polo: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F93D\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing water polo', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F93D\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing water polo: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing water polo: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing water polo: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing water polo: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing water polo: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F93D\U0000200D\U00002642', { 'desc': 'man playing water polo', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F93D\U0001F3FB\U0000200D\U00002642', { 'desc': 'man playing water polo: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FC\U0000200D\U00002642', { 'desc': 'man playing water polo: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FD\U0000200D\U00002642', { 'desc': 'man playing water polo: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FE\U0000200D\U00002642', { 'desc': 'man playing water polo: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FF\U0000200D\U00002642', { 'desc': 'man playing water polo: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F93D\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing water polo', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F93D\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing water polo: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing water polo: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing water polo: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing water polo: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93D\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing water polo: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F93D\U0000200D\U00002640', { 'desc': 'woman playing water polo', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F93D\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman playing water polo: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman playing water polo: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman playing water polo: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman playing water polo: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93D\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman playing water polo: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F93E', { 'desc': 'person playing handball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F93E\U0001F3FB', { 'desc': 'person playing handball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93E\U0001F3FC', { 'desc': 'person playing handball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93E\U0001F3FD', { 'desc': 'person playing handball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93E\U0001F3FE', { 'desc': 'person playing handball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F93E\U0001F3FF', { 'desc': 'person playing handball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F93E\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing handball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F93E\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing handball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing handball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing handball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing handball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man playing handball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F93E\U0000200D\U00002642', { 'desc': 'man playing handball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F93E\U0001F3FB\U0000200D\U00002642', { 'desc': 'man playing handball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FC\U0000200D\U00002642', { 'desc': 'man playing handball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FD\U0000200D\U00002642', { 'desc': 'man playing handball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FE\U0000200D\U00002642', { 'desc': 'man playing handball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FF\U0000200D\U00002642', { 'desc': 'man playing handball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F93E\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing handball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F93E\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing handball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing handball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing handball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing handball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F93E\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman playing handball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F93E\U0000200D\U00002640', { 'desc': 'woman playing handball', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F93E\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman playing handball: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman playing handball: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman playing handball: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman playing handball: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F93E\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman playing handball: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F939', { 'desc': 'person juggling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F939\U0001F3FB', { 'desc': 'person juggling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F939\U0001F3FC', { 'desc': 'person juggling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F939\U0001F3FD', { 'desc': 'person juggling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F939\U0001F3FE', { 'desc': 'person juggling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F939\U0001F3FF', { 'desc': 'person juggling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F939\U0000200D\U00002642\U0000FE0F', { 'desc': 'man juggling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F939\U0001F3FB\U0000200D\U00002642\U0000FE0F', { 'desc': 'man juggling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FC\U0000200D\U00002642\U0000FE0F', { 'desc': 'man juggling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FD\U0000200D\U00002642\U0000FE0F', { 'desc': 'man juggling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FE\U0000200D\U00002642\U0000FE0F', { 'desc': 'man juggling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FF\U0000200D\U00002642\U0000FE0F', { 'desc': 'man juggling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F939\U0000200D\U00002642', { 'desc': 'man juggling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F939\U0001F3FB\U0000200D\U00002642', { 'desc': 'man juggling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FC\U0000200D\U00002642', { 'desc': 'man juggling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FD\U0000200D\U00002642', { 'desc': 'man juggling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FE\U0000200D\U00002642', { 'desc': 'man juggling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FF\U0000200D\U00002642', { 'desc': 'man juggling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F939\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman juggling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F939\U0001F3FB\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman juggling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FC\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman juggling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FD\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman juggling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FE\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman juggling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }), ('\U0001F939\U0001F3FF\U0000200D\U00002640\U0000FE0F', { 'desc': 'woman juggling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': True }) ]), 'Emoji_ZWJ_Sequence': True }), ('\U0001F939\U0000200D\U00002640', { 'desc': 'woman juggling', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False, 'variations': OrderedDict([ ('\U0001F939\U0001F3FB\U0000200D\U00002640', { 'desc': 'woman juggling: light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FC\U0000200D\U00002640', { 'desc': 'woman juggling: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FD\U0000200D\U00002640', { 'desc': 'woman juggling: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FE\U0000200D\U00002640', { 'desc': 'woman juggling: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }), ('\U0001F939\U0001F3FF\U0000200D\U00002640', { 'desc': 'woman juggling: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'person-sport', 'fully-qualified': False }) ]) }), ('\U0001F46B', { 'desc': 'man and woman holding hands', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F46C', { 'desc': 'two men holding hands', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F46D', { 'desc': 'two women holding hands', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F48F', { 'desc': 'kiss', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F469\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F48B\U0000200D\U0001F468', { 'desc': 'kiss: woman, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U00002764\U0000200D\U0001F48B\U0000200D\U0001F468', { 'desc': 'kiss: woman, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': False }), ('\U0001F468\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F48B\U0000200D\U0001F468', { 'desc': 'kiss: man, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U00002764\U0000200D\U0001F48B\U0000200D\U0001F468', { 'desc': 'kiss: man, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': False }), ('\U0001F469\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F48B\U0000200D\U0001F469', { 'desc': 'kiss: woman, woman', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U00002764\U0000200D\U0001F48B\U0000200D\U0001F469', { 'desc': 'kiss: woman, woman', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': False }), ('\U0001F491', { 'desc': 'couple with heart', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F469\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F468', { 'desc': 'couple with heart: woman, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U00002764\U0000200D\U0001F468', { 'desc': 'couple with heart: woman, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': False }), ('\U0001F468\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F468', { 'desc': 'couple with heart: man, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U00002764\U0000200D\U0001F468', { 'desc': 'couple with heart: man, man', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': False }), ('\U0001F469\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F469', { 'desc': 'couple with heart: woman, woman', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U00002764\U0000200D\U0001F469', { 'desc': 'couple with heart: woman, woman', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': False }), ('\U0001F46A', { 'desc': 'family', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F468\U0000200D\U0001F469\U0000200D\U0001F466', { 'desc': 'family: man, woman, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F469\U0000200D\U0001F467', { 'desc': 'family: man, woman, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F469\U0000200D\U0001F467\U0000200D\U0001F466', { 'desc': 'family: man, woman, girl, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F469\U0000200D\U0001F466\U0000200D\U0001F466', { 'desc': 'family: man, woman, boy, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F469\U0000200D\U0001F467\U0000200D\U0001F467', { 'desc': 'family: man, woman, girl, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F468\U0000200D\U0001F466', { 'desc': 'family: man, man, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F468\U0000200D\U0001F467', { 'desc': 'family: man, man, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F468\U0000200D\U0001F467\U0000200D\U0001F466', { 'desc': 'family: man, man, girl, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F468\U0000200D\U0001F466\U0000200D\U0001F466', { 'desc': 'family: man, man, boy, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F468\U0000200D\U0001F467\U0000200D\U0001F467', { 'desc': 'family: man, man, girl, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F469\U0000200D\U0001F466', { 'desc': 'family: woman, woman, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F469\U0000200D\U0001F467', { 'desc': 'family: woman, woman, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F469\U0000200D\U0001F467\U0000200D\U0001F466', { 'desc': 'family: woman, woman, girl, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F469\U0000200D\U0001F466\U0000200D\U0001F466', { 'desc': 'family: woman, woman, boy, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F469\U0000200D\U0001F467\U0000200D\U0001F467', { 'desc': 'family: woman, woman, girl, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F466', { 'desc': 'family: man, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F466\U0000200D\U0001F466', { 'desc': 'family: man, boy, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F467', { 'desc': 'family: man, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F467\U0000200D\U0001F466', { 'desc': 'family: man, girl, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F468\U0000200D\U0001F467\U0000200D\U0001F467', { 'desc': 'family: man, girl, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F466', { 'desc': 'family: woman, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F466\U0000200D\U0001F466', { 'desc': 'family: woman, boy, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F467', { 'desc': 'family: woman, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F467\U0000200D\U0001F466', { 'desc': 'family: woman, girl, boy', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F469\U0000200D\U0001F467\U0000200D\U0001F467', { 'desc': 'family: woman, girl, girl', 'group': 'Smileys & People', 'subgroup': 'family', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F933', { 'desc': 'selfie', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F933\U0001F3FB', { 'desc': 'selfie: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F933\U0001F3FC', { 'desc': 'selfie: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F933\U0001F3FD', { 'desc': 'selfie: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F933\U0001F3FE', { 'desc': 'selfie: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F933\U0001F3FF', { 'desc': 'selfie: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F4AA', { 'desc': 'flexed biceps', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F4AA\U0001F3FB', { 'desc': 'flexed biceps: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F4AA\U0001F3FC', { 'desc': 'flexed biceps: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F4AA\U0001F3FD', { 'desc': 'flexed biceps: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F4AA\U0001F3FE', { 'desc': 'flexed biceps: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F4AA\U0001F3FF', { 'desc': 'flexed biceps: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9B5', { 'desc': 'leg', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B5\U0001F3FB', { 'desc': 'leg: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B5\U0001F3FC', { 'desc': 'leg: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B5\U0001F3FD', { 'desc': 'leg: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B5\U0001F3FE', { 'desc': 'leg: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B5\U0001F3FF', { 'desc': 'leg: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9B6', { 'desc': 'foot', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F9B6\U0001F3FB', { 'desc': 'foot: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B6\U0001F3FC', { 'desc': 'foot: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B6\U0001F3FD', { 'desc': 'foot: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B6\U0001F3FE', { 'desc': 'foot: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F9B6\U0001F3FF', { 'desc': 'foot: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F448', { 'desc': 'backhand index pointing left', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F448\U0001F3FB', { 'desc': 'backhand index pointing left: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F448\U0001F3FC', { 'desc': 'backhand index pointing left: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F448\U0001F3FD', { 'desc': 'backhand index pointing left: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F448\U0001F3FE', { 'desc': 'backhand index pointing left: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F448\U0001F3FF', { 'desc': 'backhand index pointing left: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F449', { 'desc': 'backhand index pointing right', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F449\U0001F3FB', { 'desc': 'backhand index pointing right: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F449\U0001F3FC', { 'desc': 'backhand index pointing right: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F449\U0001F3FD', { 'desc': 'backhand index pointing right: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F449\U0001F3FE', { 'desc': 'backhand index pointing right: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F449\U0001F3FF', { 'desc': 'backhand index pointing right: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0000261D\U0000FE0F', { 'desc': 'index pointing up', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0000261D\U0001F3FB', { 'desc': 'index pointing up: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000261D\U0001F3FC', { 'desc': 'index pointing up: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000261D\U0001F3FD', { 'desc': 'index pointing up: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000261D\U0001F3FE', { 'desc': 'index pointing up: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000261D\U0001F3FF', { 'desc': 'index pointing up: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0000261D', { 'desc': 'index pointing up', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F446', { 'desc': 'backhand index pointing up', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F446\U0001F3FB', { 'desc': 'backhand index pointing up: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F446\U0001F3FC', { 'desc': 'backhand index pointing up: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F446\U0001F3FD', { 'desc': 'backhand index pointing up: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F446\U0001F3FE', { 'desc': 'backhand index pointing up: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F446\U0001F3FF', { 'desc': 'backhand index pointing up: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F595', { 'desc': 'middle finger', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F595\U0001F3FB', { 'desc': 'middle finger: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F595\U0001F3FC', { 'desc': 'middle finger: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F595\U0001F3FD', { 'desc': 'middle finger: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F595\U0001F3FE', { 'desc': 'middle finger: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F595\U0001F3FF', { 'desc': 'middle finger: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F447', { 'desc': 'backhand index pointing down', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F447\U0001F3FB', { 'desc': 'backhand index pointing down: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F447\U0001F3FC', { 'desc': 'backhand index pointing down: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F447\U0001F3FD', { 'desc': 'backhand index pointing down: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F447\U0001F3FE', { 'desc': 'backhand index pointing down: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F447\U0001F3FF', { 'desc': 'backhand index pointing down: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0000270C\U0000FE0F', { 'desc': 'victory hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0000270C\U0001F3FB', { 'desc': 'victory hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270C\U0001F3FC', { 'desc': 'victory hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270C\U0001F3FD', { 'desc': 'victory hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270C\U0001F3FE', { 'desc': 'victory hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270C\U0001F3FF', { 'desc': 'victory hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0000270C', { 'desc': 'victory hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F91E', { 'desc': 'crossed fingers', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F91E\U0001F3FB', { 'desc': 'crossed fingers: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91E\U0001F3FC', { 'desc': 'crossed fingers: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91E\U0001F3FD', { 'desc': 'crossed fingers: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91E\U0001F3FE', { 'desc': 'crossed fingers: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91E\U0001F3FF', { 'desc': 'crossed fingers: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F596', { 'desc': 'vulcan salute', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F596\U0001F3FB', { 'desc': 'vulcan salute: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F596\U0001F3FC', { 'desc': 'vulcan salute: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F596\U0001F3FD', { 'desc': 'vulcan salute: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F596\U0001F3FE', { 'desc': 'vulcan salute: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F596\U0001F3FF', { 'desc': 'vulcan salute: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F918', { 'desc': 'sign of the horns', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F918\U0001F3FB', { 'desc': 'sign of the horns: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F918\U0001F3FC', { 'desc': 'sign of the horns: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F918\U0001F3FD', { 'desc': 'sign of the horns: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F918\U0001F3FE', { 'desc': 'sign of the horns: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F918\U0001F3FF', { 'desc': 'sign of the horns: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F919', { 'desc': 'call me hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F919\U0001F3FB', { 'desc': 'call me hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F919\U0001F3FC', { 'desc': 'call me hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F919\U0001F3FD', { 'desc': 'call me hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F919\U0001F3FE', { 'desc': 'call me hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F919\U0001F3FF', { 'desc': 'call me hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F590\U0000FE0F', { 'desc': 'hand with fingers splayed', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F590\U0001F3FB', { 'desc': 'hand with fingers splayed: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F590\U0001F3FC', { 'desc': 'hand with fingers splayed: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F590\U0001F3FD', { 'desc': 'hand with fingers splayed: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F590\U0001F3FE', { 'desc': 'hand with fingers splayed: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F590\U0001F3FF', { 'desc': 'hand with fingers splayed: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0001F590', { 'desc': 'hand with fingers splayed', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0000270B', { 'desc': 'raised hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0000270B\U0001F3FB', { 'desc': 'raised hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270B\U0001F3FC', { 'desc': 'raised hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270B\U0001F3FD', { 'desc': 'raised hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270B\U0001F3FE', { 'desc': 'raised hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270B\U0001F3FF', { 'desc': 'raised hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F44C', { 'desc': 'OK hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F44C\U0001F3FB', { 'desc': 'OK hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44C\U0001F3FC', { 'desc': 'OK hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44C\U0001F3FD', { 'desc': 'OK hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44C\U0001F3FE', { 'desc': 'OK hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44C\U0001F3FF', { 'desc': 'OK hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F44D', { 'desc': 'thumbs up', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F44D\U0001F3FB', { 'desc': 'thumbs up: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44D\U0001F3FC', { 'desc': 'thumbs up: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44D\U0001F3FD', { 'desc': 'thumbs up: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44D\U0001F3FE', { 'desc': 'thumbs up: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44D\U0001F3FF', { 'desc': 'thumbs up: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F44E', { 'desc': 'thumbs down', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F44E\U0001F3FB', { 'desc': 'thumbs down: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44E\U0001F3FC', { 'desc': 'thumbs down: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44E\U0001F3FD', { 'desc': 'thumbs down: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44E\U0001F3FE', { 'desc': 'thumbs down: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44E\U0001F3FF', { 'desc': 'thumbs down: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0000270A', { 'desc': 'raised fist', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0000270A\U0001F3FB', { 'desc': 'raised fist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270A\U0001F3FC', { 'desc': 'raised fist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270A\U0001F3FD', { 'desc': 'raised fist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270A\U0001F3FE', { 'desc': 'raised fist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270A\U0001F3FF', { 'desc': 'raised fist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F44A', { 'desc': 'oncoming fist', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F44A\U0001F3FB', { 'desc': 'oncoming fist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44A\U0001F3FC', { 'desc': 'oncoming fist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44A\U0001F3FD', { 'desc': 'oncoming fist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44A\U0001F3FE', { 'desc': 'oncoming fist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44A\U0001F3FF', { 'desc': 'oncoming fist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F91B', { 'desc': 'left-facing fist', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F91B\U0001F3FB', { 'desc': 'left-facing fist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91B\U0001F3FC', { 'desc': 'left-facing fist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91B\U0001F3FD', { 'desc': 'left-facing fist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91B\U0001F3FE', { 'desc': 'left-facing fist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91B\U0001F3FF', { 'desc': 'left-facing fist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F91C', { 'desc': 'right-facing fist', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F91C\U0001F3FB', { 'desc': 'right-facing fist: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91C\U0001F3FC', { 'desc': 'right-facing fist: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91C\U0001F3FD', { 'desc': 'right-facing fist: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91C\U0001F3FE', { 'desc': 'right-facing fist: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91C\U0001F3FF', { 'desc': 'right-facing fist: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F91A', { 'desc': 'raised back of hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F91A\U0001F3FB', { 'desc': 'raised back of hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91A\U0001F3FC', { 'desc': 'raised back of hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91A\U0001F3FD', { 'desc': 'raised back of hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91A\U0001F3FE', { 'desc': 'raised back of hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91A\U0001F3FF', { 'desc': 'raised back of hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F44B', { 'desc': 'waving hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F44B\U0001F3FB', { 'desc': 'waving hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44B\U0001F3FC', { 'desc': 'waving hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44B\U0001F3FD', { 'desc': 'waving hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44B\U0001F3FE', { 'desc': 'waving hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44B\U0001F3FF', { 'desc': 'waving hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F91F', { 'desc': 'love-you gesture', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F91F\U0001F3FB', { 'desc': 'love-you gesture: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91F\U0001F3FC', { 'desc': 'love-you gesture: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91F\U0001F3FD', { 'desc': 'love-you gesture: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91F\U0001F3FE', { 'desc': 'love-you gesture: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F91F\U0001F3FF', { 'desc': 'love-you gesture: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0000270D\U0000FE0F', { 'desc': 'writing hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0000270D\U0001F3FB', { 'desc': 'writing hand: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270D\U0001F3FC', { 'desc': 'writing hand: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270D\U0001F3FD', { 'desc': 'writing hand: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270D\U0001F3FE', { 'desc': 'writing hand: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0000270D\U0001F3FF', { 'desc': 'writing hand: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]) }), ('\U0000270D', { 'desc': 'writing hand', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False, 'Emoji': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F44F', { 'desc': 'clapping hands', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F44F\U0001F3FB', { 'desc': 'clapping hands: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44F\U0001F3FC', { 'desc': 'clapping hands: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44F\U0001F3FD', { 'desc': 'clapping hands: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44F\U0001F3FE', { 'desc': 'clapping hands: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F44F\U0001F3FF', { 'desc': 'clapping hands: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F450', { 'desc': 'open hands', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F450\U0001F3FB', { 'desc': 'open hands: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F450\U0001F3FC', { 'desc': 'open hands: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F450\U0001F3FD', { 'desc': 'open hands: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F450\U0001F3FE', { 'desc': 'open hands: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F450\U0001F3FF', { 'desc': 'open hands: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F64C', { 'desc': 'raising hands', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64C\U0001F3FB', { 'desc': 'raising hands: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64C\U0001F3FC', { 'desc': 'raising hands: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64C\U0001F3FD', { 'desc': 'raising hands: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64C\U0001F3FE', { 'desc': 'raising hands: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64C\U0001F3FF', { 'desc': 'raising hands: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F932', { 'desc': 'palms up together', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F932\U0001F3FB', { 'desc': 'palms up together: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F932\U0001F3FC', { 'desc': 'palms up together: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F932\U0001F3FD', { 'desc': 'palms up together: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F932\U0001F3FE', { 'desc': 'palms up together: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F932\U0001F3FF', { 'desc': 'palms up together: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F64F', { 'desc': 'folded hands', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F64F\U0001F3FB', { 'desc': 'folded hands: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64F\U0001F3FC', { 'desc': 'folded hands: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64F\U0001F3FD', { 'desc': 'folded hands: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64F\U0001F3FE', { 'desc': 'folded hands: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F64F\U0001F3FF', { 'desc': 'folded hands: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F91D', { 'desc': 'handshake', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F485', { 'desc': 'nail polish', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F485\U0001F3FB', { 'desc': 'nail polish: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F485\U0001F3FC', { 'desc': 'nail polish: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F485\U0001F3FD', { 'desc': 'nail polish: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F485\U0001F3FE', { 'desc': 'nail polish: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F485\U0001F3FF', { 'desc': 'nail polish: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F442', { 'desc': 'ear', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F442\U0001F3FB', { 'desc': 'ear: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F442\U0001F3FC', { 'desc': 'ear: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F442\U0001F3FD', { 'desc': 'ear: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F442\U0001F3FE', { 'desc': 'ear: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F442\U0001F3FF', { 'desc': 'ear: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F443', { 'desc': 'nose', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'variations': OrderedDict([ ('\U0001F443\U0001F3FB', { 'desc': 'nose: light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F443\U0001F3FC', { 'desc': 'nose: medium-light skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F443\U0001F3FD', { 'desc': 'nose: medium skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F443\U0001F3FE', { 'desc': 'nose: medium-dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }), ('\U0001F443\U0001F3FF', { 'desc': 'nose: dark skin tone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_Modifier_Sequence': True }) ]), 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Modifier_Base': True, 'Extended_Pictographic': True }), ('\U0001F9B0', { 'desc': 'red-haired', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Component': True, 'Extended_Pictographic': True }), ('\U0001F9B1', { 'desc': 'curly-haired', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Component': True, 'Extended_Pictographic': True }), ('\U0001F9B2', { 'desc': 'bald', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Component': True, 'Extended_Pictographic': True }), ('\U0001F9B3', { 'desc': 'white-haired', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Emoji_Component': True, 'Extended_Pictographic': True }), ('\U0001F463', { 'desc': 'footprints', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F440', { 'desc': 'eyes', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F441\U0000FE0F', { 'desc': 'eye', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True }), ('\U0001F441', { 'desc': 'eye', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F441\U0000FE0F\U0000200D\U0001F5E8\U0000FE0F', { 'desc': 'eye in speech bubble', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F441\U0000200D\U0001F5E8\U0000FE0F', { 'desc': 'eye in speech bubble', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False }), ('\U0001F441\U0000FE0F\U0000200D\U0001F5E8', { 'desc': 'eye in speech bubble', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False }), ('\U0001F441\U0000200D\U0001F5E8', { 'desc': 'eye in speech bubble', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': False }), ('\U0001F9E0', { 'desc': 'brain', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9B4', { 'desc': 'bone', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9B7', { 'desc': 'tooth', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F445', { 'desc': 'tongue', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F444', { 'desc': 'mouth', 'group': 'Smileys & People', 'subgroup': 'body', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F48B', { 'desc': 'kiss mark', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F498', { 'desc': 'heart with arrow', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002764\U0000FE0F', { 'desc': 'red heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True }), ('\U00002764', { 'desc': 'red heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F493', { 'desc': 'beating heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F494', { 'desc': 'broken heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F495', { 'desc': 'two hearts', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F496', { 'desc': 'sparkling heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F497', { 'desc': 'growing heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F499', { 'desc': 'blue heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F49A', { 'desc': 'green heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F49B', { 'desc': 'yellow heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E1', { 'desc': 'orange heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F49C', { 'desc': 'purple heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5A4', { 'desc': 'black heart', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F49D', { 'desc': 'heart with ribbon', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F49E', { 'desc': 'revolving hearts', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F49F', { 'desc': 'heart decoration', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002763\U0000FE0F', { 'desc': 'heavy heart exclamation', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True }), ('\U00002763', { 'desc': 'heavy heart exclamation', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F48C', { 'desc': 'love letter', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A4', { 'desc': 'zzz', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A2', { 'desc': 'anger symbol', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A3', { 'desc': 'bomb', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A5', { 'desc': 'collision', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A6', { 'desc': 'sweat droplets', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A8', { 'desc': 'dashing away', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4AB', { 'desc': 'dizzy', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4AC', { 'desc': 'speech balloon', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5E8\U0000FE0F', { 'desc': 'left speech bubble', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True }), ('\U0001F5E8', { 'desc': 'left speech bubble', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5EF\U0000FE0F', { 'desc': 'right anger bubble', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True }), ('\U0001F5EF', { 'desc': 'right anger bubble', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4AD', { 'desc': 'thought balloon', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F573\U0000FE0F', { 'desc': 'hole', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': True }), ('\U0001F573', { 'desc': 'hole', 'group': 'Smileys & People', 'subgroup': 'emotion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F453', { 'desc': 'glasses', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F576\U0000FE0F', { 'desc': 'sunglasses', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True }), ('\U0001F576', { 'desc': 'sunglasses', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F97D', { 'desc': 'goggles', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F97C', { 'desc': 'lab coat', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F454', { 'desc': 'necktie', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F455', { 'desc': 't-shirt', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F456', { 'desc': 'jeans', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E3', { 'desc': 'scarf', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E4', { 'desc': 'gloves', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E5', { 'desc': 'coat', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E6', { 'desc': 'socks', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F457', { 'desc': 'dress', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F458', { 'desc': 'kimono', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F459', { 'desc': 'bikini', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F45A', { 'desc': 'woman�s clothes', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F45B', { 'desc': 'purse', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F45C', { 'desc': 'handbag', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F45D', { 'desc': 'clutch bag', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6CD\U0000FE0F', { 'desc': 'shopping bags', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True }), ('\U0001F6CD', { 'desc': 'shopping bags', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F392', { 'desc': 'school backpack', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F45E', { 'desc': 'man�s shoe', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F45F', { 'desc': 'running shoe', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F97E', { 'desc': 'hiking boot', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F97F', { 'desc': 'woman�s flat shoe', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F460', { 'desc': 'high-heeled shoe', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F461', { 'desc': 'woman�s sandal', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F462', { 'desc': 'woman�s boot', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F451', { 'desc': 'crown', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F452', { 'desc': 'woman�s hat', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3A9', { 'desc': 'top hat', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F393', { 'desc': 'graduation cap', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E2', { 'desc': 'billed cap', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026D1\U0000FE0F', { 'desc': 'rescue worker�s helmet', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True }), ('\U000026D1', { 'desc': 'rescue worker�s helmet', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4FF', { 'desc': 'prayer beads', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F484', { 'desc': 'lipstick', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F48D', { 'desc': 'ring', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F48E', { 'desc': 'gem stone', 'group': 'Smileys & People', 'subgroup': 'clothing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F435', { 'desc': 'monkey face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F412', { 'desc': 'monkey', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F98D', { 'desc': 'gorilla', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F436', { 'desc': 'dog face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F415', { 'desc': 'dog', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F429', { 'desc': 'poodle', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F43A', { 'desc': 'wolf face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F98A', { 'desc': 'fox face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F99D', { 'desc': 'raccoon', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F431', { 'desc': 'cat face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F408', { 'desc': 'cat', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F981', { 'desc': 'lion face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F42F', { 'desc': 'tiger face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F405', { 'desc': 'tiger', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F406', { 'desc': 'leopard', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F434', { 'desc': 'horse face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F40E', { 'desc': 'horse', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F984', { 'desc': 'unicorn face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F993', { 'desc': 'zebra', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F98C', { 'desc': 'deer', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F42E', { 'desc': 'cow face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F402', { 'desc': 'ox', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F403', { 'desc': 'water buffalo', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F404', { 'desc': 'cow', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F437', { 'desc': 'pig face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F416', { 'desc': 'pig', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F417', { 'desc': 'boar', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F43D', { 'desc': 'pig nose', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F40F', { 'desc': 'ram', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F411', { 'desc': 'ewe', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F410', { 'desc': 'goat', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F42A', { 'desc': 'camel', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F42B', { 'desc': 'two-hump camel', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F999', { 'desc': 'llama', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F992', { 'desc': 'giraffe', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F418', { 'desc': 'elephant', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F98F', { 'desc': 'rhinoceros', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F99B', { 'desc': 'hippopotamus', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F42D', { 'desc': 'mouse face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F401', { 'desc': 'mouse', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F400', { 'desc': 'rat', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F439', { 'desc': 'hamster face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F430', { 'desc': 'rabbit face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F407', { 'desc': 'rabbit', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F43F\U0000FE0F', { 'desc': 'chipmunk', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True }), ('\U0001F43F', { 'desc': 'chipmunk', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F994', { 'desc': 'hedgehog', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F987', { 'desc': 'bat', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F43B', { 'desc': 'bear face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F428', { 'desc': 'koala', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F43C', { 'desc': 'panda face', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F998', { 'desc': 'kangaroo', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9A1', { 'desc': 'badger', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F43E', { 'desc': 'paw prints', 'group': 'Animals & Nature', 'subgroup': 'animal-mammal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F983', { 'desc': 'turkey', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F414', { 'desc': 'chicken', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F413', { 'desc': 'rooster', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F423', { 'desc': 'hatching chick', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F424', { 'desc': 'baby chick', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F425', { 'desc': 'front-facing baby chick', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F426', { 'desc': 'bird', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F427', { 'desc': 'penguin', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F54A\U0000FE0F', { 'desc': 'dove', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True }), ('\U0001F54A', { 'desc': 'dove', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F985', { 'desc': 'eagle', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F986', { 'desc': 'duck', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9A2', { 'desc': 'swan', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F989', { 'desc': 'owl', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F99A', { 'desc': 'peacock', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F99C', { 'desc': 'parrot', 'group': 'Animals & Nature', 'subgroup': 'animal-bird', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F438', { 'desc': 'frog face', 'group': 'Animals & Nature', 'subgroup': 'animal-amphibian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F40A', { 'desc': 'crocodile', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F422', { 'desc': 'turtle', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F98E', { 'desc': 'lizard', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F40D', { 'desc': 'snake', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F432', { 'desc': 'dragon face', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F409', { 'desc': 'dragon', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F995', { 'desc': 'sauropod', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F996', { 'desc': 'T-Rex', 'group': 'Animals & Nature', 'subgroup': 'animal-reptile', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F433', { 'desc': 'spouting whale', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F40B', { 'desc': 'whale', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F42C', { 'desc': 'dolphin', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F41F', { 'desc': 'fish', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F420', { 'desc': 'tropical fish', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F421', { 'desc': 'blowfish', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F988', { 'desc': 'shark', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F419', { 'desc': 'octopus', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F41A', { 'desc': 'spiral shell', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F980', { 'desc': 'crab', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F99E', { 'desc': 'lobster', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F990', { 'desc': 'shrimp', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F991', { 'desc': 'squid', 'group': 'Animals & Nature', 'subgroup': 'animal-marine', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F40C', { 'desc': 'snail', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F98B', { 'desc': 'butterfly', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F41B', { 'desc': 'bug', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F41C', { 'desc': 'ant', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F41D', { 'desc': 'honeybee', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F41E', { 'desc': 'lady beetle', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F997', { 'desc': 'cricket', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F577\U0000FE0F', { 'desc': 'spider', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True }), ('\U0001F577', { 'desc': 'spider', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F578\U0000FE0F', { 'desc': 'spider web', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True }), ('\U0001F578', { 'desc': 'spider web', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F982', { 'desc': 'scorpion', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F99F', { 'desc': 'mosquito', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9A0', { 'desc': 'microbe', 'group': 'Animals & Nature', 'subgroup': 'animal-bug', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F490', { 'desc': 'bouquet', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F338', { 'desc': 'cherry blossom', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4AE', { 'desc': 'white flower', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3F5\U0000FE0F', { 'desc': 'rosette', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True }), ('\U0001F3F5', { 'desc': 'rosette', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F339', { 'desc': 'rose', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F940', { 'desc': 'wilted flower', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F33A', { 'desc': 'hibiscus', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F33B', { 'desc': 'sunflower', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F33C', { 'desc': 'blossom', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F337', { 'desc': 'tulip', 'group': 'Animals & Nature', 'subgroup': 'plant-flower', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F331', { 'desc': 'seedling', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F332', { 'desc': 'evergreen tree', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F333', { 'desc': 'deciduous tree', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F334', { 'desc': 'palm tree', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F335', { 'desc': 'cactus', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F33E', { 'desc': 'sheaf of rice', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F33F', { 'desc': 'herb', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002618\U0000FE0F', { 'desc': 'shamrock', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True }), ('\U00002618', { 'desc': 'shamrock', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F340', { 'desc': 'four leaf clover', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F341', { 'desc': 'maple leaf', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F342', { 'desc': 'fallen leaf', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F343', { 'desc': 'leaf fluttering in wind', 'group': 'Animals & Nature', 'subgroup': 'plant-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F347', { 'desc': 'grapes', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F348', { 'desc': 'melon', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F349', { 'desc': 'watermelon', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F34A', { 'desc': 'tangerine', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F34B', { 'desc': 'lemon', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F34C', { 'desc': 'banana', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F34D', { 'desc': 'pineapple', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F96D', { 'desc': 'mango', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F34E', { 'desc': 'red apple', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F34F', { 'desc': 'green apple', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F350', { 'desc': 'pear', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F351', { 'desc': 'peach', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F352', { 'desc': 'cherries', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F353', { 'desc': 'strawberry', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F95D', { 'desc': 'kiwi fruit', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F345', { 'desc': 'tomato', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F965', { 'desc': 'coconut', 'group': 'Food & Drink', 'subgroup': 'food-fruit', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F951', { 'desc': 'avocado', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F346', { 'desc': 'eggplant', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F954', { 'desc': 'potato', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F955', { 'desc': 'carrot', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F33D', { 'desc': 'ear of corn', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F336\U0000FE0F', { 'desc': 'hot pepper', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True }), ('\U0001F336', { 'desc': 'hot pepper', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F952', { 'desc': 'cucumber', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F96C', { 'desc': 'leafy green', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F966', { 'desc': 'broccoli', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F344', { 'desc': 'mushroom', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F95C', { 'desc': 'peanuts', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F330', { 'desc': 'chestnut', 'group': 'Food & Drink', 'subgroup': 'food-vegetable', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F35E', { 'desc': 'bread', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F950', { 'desc': 'croissant', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F956', { 'desc': 'baguette bread', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F968', { 'desc': 'pretzel', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F96F', { 'desc': 'bagel', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F95E', { 'desc': 'pancakes', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9C0', { 'desc': 'cheese wedge', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F356', { 'desc': 'meat on bone', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F357', { 'desc': 'poultry leg', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F969', { 'desc': 'cut of meat', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F953', { 'desc': 'bacon', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F354', { 'desc': 'hamburger', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F35F', { 'desc': 'french fries', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F355', { 'desc': 'pizza', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F32D', { 'desc': 'hot dog', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F96A', { 'desc': 'sandwich', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F32E', { 'desc': 'taco', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F32F', { 'desc': 'burrito', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F959', { 'desc': 'stuffed flatbread', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F95A', { 'desc': 'egg', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F373', { 'desc': 'cooking', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F958', { 'desc': 'shallow pan of food', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F372', { 'desc': 'pot of food', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F963', { 'desc': 'bowl with spoon', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F957', { 'desc': 'green salad', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F37F', { 'desc': 'popcorn', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9C2', { 'desc': 'salt', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F96B', { 'desc': 'canned food', 'group': 'Food & Drink', 'subgroup': 'food-prepared', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F371', { 'desc': 'bento box', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F358', { 'desc': 'rice cracker', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F359', { 'desc': 'rice ball', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F35A', { 'desc': 'cooked rice', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F35B', { 'desc': 'curry rice', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F35C', { 'desc': 'steaming bowl', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F35D', { 'desc': 'spaghetti', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F360', { 'desc': 'roasted sweet potato', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F362', { 'desc': 'oden', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F363', { 'desc': 'sushi', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F364', { 'desc': 'fried shrimp', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F365', { 'desc': 'fish cake with swirl', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F96E', { 'desc': 'moon cake', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F361', { 'desc': 'dango', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F95F', { 'desc': 'dumpling', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F960', { 'desc': 'fortune cookie', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F961', { 'desc': 'takeout box', 'group': 'Food & Drink', 'subgroup': 'food-asian', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F366', { 'desc': 'soft ice cream', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F367', { 'desc': 'shaved ice', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F368', { 'desc': 'ice cream', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F369', { 'desc': 'doughnut', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F36A', { 'desc': 'cookie', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F382', { 'desc': 'birthday cake', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F370', { 'desc': 'shortcake', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9C1', { 'desc': 'cupcake', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F967', { 'desc': 'pie', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F36B', { 'desc': 'chocolate bar', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F36C', { 'desc': 'candy', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F36D', { 'desc': 'lollipop', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F36E', { 'desc': 'custard', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F36F', { 'desc': 'honey pot', 'group': 'Food & Drink', 'subgroup': 'food-sweet', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F37C', { 'desc': 'baby bottle', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F95B', { 'desc': 'glass of milk', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002615', { 'desc': 'hot beverage', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F375', { 'desc': 'teacup without handle', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F376', { 'desc': 'sake', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F37E', { 'desc': 'bottle with popping cork', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F377', { 'desc': 'wine glass', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F378', { 'desc': 'cocktail glass', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F379', { 'desc': 'tropical drink', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F37A', { 'desc': 'beer mug', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F37B', { 'desc': 'clinking beer mugs', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F942', { 'desc': 'clinking glasses', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F943', { 'desc': 'tumbler glass', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F964', { 'desc': 'cup with straw', 'group': 'Food & Drink', 'subgroup': 'drink', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F962', { 'desc': 'chopsticks', 'group': 'Food & Drink', 'subgroup': 'dishware', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F37D\U0000FE0F', { 'desc': 'fork and knife with plate', 'group': 'Food & Drink', 'subgroup': 'dishware', 'fully-qualified': True }), ('\U0001F37D', { 'desc': 'fork and knife with plate', 'group': 'Food & Drink', 'subgroup': 'dishware', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F374', { 'desc': 'fork and knife', 'group': 'Food & Drink', 'subgroup': 'dishware', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F944', { 'desc': 'spoon', 'group': 'Food & Drink', 'subgroup': 'dishware', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F52A', { 'desc': 'kitchen knife', 'group': 'Food & Drink', 'subgroup': 'dishware', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3FA', { 'desc': 'amphora', 'group': 'Food & Drink', 'subgroup': 'dishware', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F30D', { 'desc': 'globe showing Europe-Africa', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F30E', { 'desc': 'globe showing Americas', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F30F', { 'desc': 'globe showing Asia-Australia', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F310', { 'desc': 'globe with meridians', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5FA\U0000FE0F', { 'desc': 'world map', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': True }), ('\U0001F5FA', { 'desc': 'world map', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5FE', { 'desc': 'map of Japan', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9ED', { 'desc': 'compass', 'group': 'Travel & Places', 'subgroup': 'place-map', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D4\U0000FE0F', { 'desc': 'snow-capped mountain', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True }), ('\U0001F3D4', { 'desc': 'snow-capped mountain', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000026F0\U0000FE0F', { 'desc': 'mountain', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True }), ('\U000026F0', { 'desc': 'mountain', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F30B', { 'desc': 'volcano', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5FB', { 'desc': 'mount fuji', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D5\U0000FE0F', { 'desc': 'camping', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True }), ('\U0001F3D5', { 'desc': 'camping', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3D6\U0000FE0F', { 'desc': 'beach with umbrella', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True }), ('\U0001F3D6', { 'desc': 'beach with umbrella', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3DC\U0000FE0F', { 'desc': 'desert', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True }), ('\U0001F3DC', { 'desc': 'desert', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3DD\U0000FE0F', { 'desc': 'desert island', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True }), ('\U0001F3DD', { 'desc': 'desert island', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3DE\U0000FE0F', { 'desc': 'national park', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': True }), ('\U0001F3DE', { 'desc': 'national park', 'group': 'Travel & Places', 'subgroup': 'place-geographic', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3DF\U0000FE0F', { 'desc': 'stadium', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True }), ('\U0001F3DF', { 'desc': 'stadium', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3DB\U0000FE0F', { 'desc': 'classical building', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True }), ('\U0001F3DB', { 'desc': 'classical building', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3D7\U0000FE0F', { 'desc': 'building construction', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True }), ('\U0001F3D7', { 'desc': 'building construction', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F9F1', { 'desc': 'bricks', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D8\U0000FE0F', { 'desc': 'houses', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True }), ('\U0001F3D8', { 'desc': 'houses', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3DA\U0000FE0F', { 'desc': 'derelict house', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True }), ('\U0001F3DA', { 'desc': 'derelict house', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3E0', { 'desc': 'house', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E1', { 'desc': 'house with garden', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E2', { 'desc': 'office building', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E3', { 'desc': 'Japanese post office', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E4', { 'desc': 'post office', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E5', { 'desc': 'hospital', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E6', { 'desc': 'bank', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E8', { 'desc': 'hotel', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E9', { 'desc': 'love hotel', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3EA', { 'desc': 'convenience store', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3EB', { 'desc': 'school', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3EC', { 'desc': 'department store', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3ED', { 'desc': 'factory', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3EF', { 'desc': 'Japanese castle', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3F0', { 'desc': 'castle', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F492', { 'desc': 'wedding', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5FC', { 'desc': 'Tokyo tower', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5FD', { 'desc': 'Statue of Liberty', 'group': 'Travel & Places', 'subgroup': 'place-building', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026EA', { 'desc': 'church', 'group': 'Travel & Places', 'subgroup': 'place-religious', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F54C', { 'desc': 'mosque', 'group': 'Travel & Places', 'subgroup': 'place-religious', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F54D', { 'desc': 'synagogue', 'group': 'Travel & Places', 'subgroup': 'place-religious', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026E9\U0000FE0F', { 'desc': 'shinto shrine', 'group': 'Travel & Places', 'subgroup': 'place-religious', 'fully-qualified': True }), ('\U000026E9', { 'desc': 'shinto shrine', 'group': 'Travel & Places', 'subgroup': 'place-religious', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F54B', { 'desc': 'kaaba', 'group': 'Travel & Places', 'subgroup': 'place-religious', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026F2', { 'desc': 'fountain', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026FA', { 'desc': 'tent', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F301', { 'desc': 'foggy', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F303', { 'desc': 'night with stars', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D9\U0000FE0F', { 'desc': 'cityscape', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True }), ('\U0001F3D9', { 'desc': 'cityscape', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F304', { 'desc': 'sunrise over mountains', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F305', { 'desc': 'sunrise', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F306', { 'desc': 'cityscape at dusk', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F307', { 'desc': 'sunset', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F309', { 'desc': 'bridge at night', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002668\U0000FE0F', { 'desc': 'hot springs', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True }), ('\U00002668', { 'desc': 'hot springs', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F30C', { 'desc': 'milky way', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3A0', { 'desc': 'carousel horse', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3A1', { 'desc': 'ferris wheel', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3A2', { 'desc': 'roller coaster', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F488', { 'desc': 'barber pole', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3AA', { 'desc': 'circus tent', 'group': 'Travel & Places', 'subgroup': 'place-other', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F682', { 'desc': 'locomotive', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F683', { 'desc': 'railway car', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F684', { 'desc': 'high-speed train', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F685', { 'desc': 'bullet train', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F686', { 'desc': 'train', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F687', { 'desc': 'metro', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F688', { 'desc': 'light rail', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F689', { 'desc': 'station', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F68A', { 'desc': 'tram', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F69D', { 'desc': 'monorail', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F69E', { 'desc': 'mountain railway', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F68B', { 'desc': 'tram car', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F68C', { 'desc': 'bus', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F68D', { 'desc': 'oncoming bus', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F68E', { 'desc': 'trolleybus', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F690', { 'desc': 'minibus', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F691', { 'desc': 'ambulance', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F692', { 'desc': 'fire engine', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F693', { 'desc': 'police car', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F694', { 'desc': 'oncoming police car', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F695', { 'desc': 'taxi', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F696', { 'desc': 'oncoming taxi', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F697', { 'desc': 'automobile', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F698', { 'desc': 'oncoming automobile', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F699', { 'desc': 'sport utility vehicle', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F69A', { 'desc': 'delivery truck', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F69B', { 'desc': 'articulated lorry', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F69C', { 'desc': 'tractor', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6B2', { 'desc': 'bicycle', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F4', { 'desc': 'kick scooter', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F9', { 'desc': 'skateboard', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F5', { 'desc': 'motor scooter', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F68F', { 'desc': 'bus stop', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6E3\U0000FE0F', { 'desc': 'motorway', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True }), ('\U0001F6E3', { 'desc': 'motorway', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6E4\U0000FE0F', { 'desc': 'railway track', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True }), ('\U0001F6E4', { 'desc': 'railway track', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6E2\U0000FE0F', { 'desc': 'oil drum', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True }), ('\U0001F6E2', { 'desc': 'oil drum', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000026FD', { 'desc': 'fuel pump', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A8', { 'desc': 'police car light', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A5', { 'desc': 'horizontal traffic light', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A6', { 'desc': 'vertical traffic light', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6D1', { 'desc': 'stop sign', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A7', { 'desc': 'construction', 'group': 'Travel & Places', 'subgroup': 'transport-ground', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002693', { 'desc': 'anchor', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026F5', { 'desc': 'sailboat', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F6', { 'desc': 'canoe', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A4', { 'desc': 'speedboat', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F3\U0000FE0F', { 'desc': 'passenger ship', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True }), ('\U0001F6F3', { 'desc': 'passenger ship', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000026F4\U0000FE0F', { 'desc': 'ferry', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True }), ('\U000026F4', { 'desc': 'ferry', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6E5\U0000FE0F', { 'desc': 'motor boat', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True }), ('\U0001F6E5', { 'desc': 'motor boat', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6A2', { 'desc': 'ship', 'group': 'Travel & Places', 'subgroup': 'transport-water', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002708\U0000FE0F', { 'desc': 'airplane', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True }), ('\U00002708', { 'desc': 'airplane', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6E9\U0000FE0F', { 'desc': 'small airplane', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True }), ('\U0001F6E9', { 'desc': 'small airplane', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6EB', { 'desc': 'airplane departure', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6EC', { 'desc': 'airplane arrival', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4BA', { 'desc': 'seat', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F681', { 'desc': 'helicopter', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F69F', { 'desc': 'suspension railway', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A0', { 'desc': 'mountain cableway', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A1', { 'desc': 'aerial tramway', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F0\U0000FE0F', { 'desc': 'satellite', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True }), ('\U0001F6F0', { 'desc': 'satellite', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F680', { 'desc': 'rocket', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F8', { 'desc': 'flying saucer', 'group': 'Travel & Places', 'subgroup': 'transport-air', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6CE\U0000FE0F', { 'desc': 'bellhop bell', 'group': 'Travel & Places', 'subgroup': 'hotel', 'fully-qualified': True }), ('\U0001F6CE', { 'desc': 'bellhop bell', 'group': 'Travel & Places', 'subgroup': 'hotel', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F9F3', { 'desc': 'luggage', 'group': 'Travel & Places', 'subgroup': 'hotel', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000231B', { 'desc': 'hourglass done', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023F3', { 'desc': 'hourglass not done', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000231A', { 'desc': 'watch', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023F0', { 'desc': 'alarm clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023F1\U0000FE0F', { 'desc': 'stopwatch', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True }), ('\U000023F1', { 'desc': 'stopwatch', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000023F2\U0000FE0F', { 'desc': 'timer clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True }), ('\U000023F2', { 'desc': 'timer clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F570\U0000FE0F', { 'desc': 'mantelpiece clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True }), ('\U0001F570', { 'desc': 'mantelpiece clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F55B', { 'desc': 'twelve o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F567', { 'desc': 'twelve-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F550', { 'desc': 'one o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F55C', { 'desc': 'one-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F551', { 'desc': 'two o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F55D', { 'desc': 'two-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F552', { 'desc': 'three o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F55E', { 'desc': 'three-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F553', { 'desc': 'four o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F55F', { 'desc': 'four-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F554', { 'desc': 'five o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F560', { 'desc': 'five-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F555', { 'desc': 'six o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F561', { 'desc': 'six-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F556', { 'desc': 'seven o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F562', { 'desc': 'seven-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F557', { 'desc': 'eight o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F563', { 'desc': 'eight-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F558', { 'desc': 'nine o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F564', { 'desc': 'nine-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F559', { 'desc': 'ten o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F565', { 'desc': 'ten-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F55A', { 'desc': 'eleven o�clock', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F566', { 'desc': 'eleven-thirty', 'group': 'Travel & Places', 'subgroup': 'time', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F311', { 'desc': 'new moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F312', { 'desc': 'waxing crescent moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F313', { 'desc': 'first quarter moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F314', { 'desc': 'waxing gibbous moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F315', { 'desc': 'full moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F316', { 'desc': 'waning gibbous moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F317', { 'desc': 'last quarter moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F318', { 'desc': 'waning crescent moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F319', { 'desc': 'crescent moon', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F31A', { 'desc': 'new moon face', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F31B', { 'desc': 'first quarter moon face', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F31C', { 'desc': 'last quarter moon face', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F321\U0000FE0F', { 'desc': 'thermometer', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F321', { 'desc': 'thermometer', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002600\U0000FE0F', { 'desc': 'sun', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U00002600', { 'desc': 'sun', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F31D', { 'desc': 'full moon face', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F31E', { 'desc': 'sun with face', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002B50', { 'desc': 'star', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F31F', { 'desc': 'glowing star', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F320', { 'desc': 'shooting star', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002601\U0000FE0F', { 'desc': 'cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U00002601', { 'desc': 'cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000026C5', { 'desc': 'sun behind cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026C8\U0000FE0F', { 'desc': 'cloud with lightning and rain', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U000026C8', { 'desc': 'cloud with lightning and rain', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F324\U0000FE0F', { 'desc': 'sun behind small cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F324', { 'desc': 'sun behind small cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F325\U0000FE0F', { 'desc': 'sun behind large cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F325', { 'desc': 'sun behind large cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F326\U0000FE0F', { 'desc': 'sun behind rain cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F326', { 'desc': 'sun behind rain cloud', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F327\U0000FE0F', { 'desc': 'cloud with rain', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F327', { 'desc': 'cloud with rain', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F328\U0000FE0F', { 'desc': 'cloud with snow', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F328', { 'desc': 'cloud with snow', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F329\U0000FE0F', { 'desc': 'cloud with lightning', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F329', { 'desc': 'cloud with lightning', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F32A\U0000FE0F', { 'desc': 'tornado', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F32A', { 'desc': 'tornado', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F32B\U0000FE0F', { 'desc': 'fog', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F32B', { 'desc': 'fog', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F32C\U0000FE0F', { 'desc': 'wind face', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U0001F32C', { 'desc': 'wind face', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F300', { 'desc': 'cyclone', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F308', { 'desc': 'rainbow', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F302', { 'desc': 'closed umbrella', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002602\U0000FE0F', { 'desc': 'umbrella', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U00002602', { 'desc': 'umbrella', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002614', { 'desc': 'umbrella with rain drops', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026F1\U0000FE0F', { 'desc': 'umbrella on ground', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U000026F1', { 'desc': 'umbrella on ground', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000026A1', { 'desc': 'high voltage', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002744\U0000FE0F', { 'desc': 'snowflake', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U00002744', { 'desc': 'snowflake', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002603\U0000FE0F', { 'desc': 'snowman', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U00002603', { 'desc': 'snowman', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000026C4', { 'desc': 'snowman without snow', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002604\U0000FE0F', { 'desc': 'comet', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True }), ('\U00002604', { 'desc': 'comet', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F525', { 'desc': 'fire', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A7', { 'desc': 'droplet', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F30A', { 'desc': 'water wave', 'group': 'Travel & Places', 'subgroup': 'sky & weather', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F383', { 'desc': 'jack-o-lantern', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F384', { 'desc': 'Christmas tree', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F386', { 'desc': 'fireworks', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F387', { 'desc': 'sparkler', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E8', { 'desc': 'firecracker', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002728', { 'desc': 'sparkles', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F388', { 'desc': 'balloon', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F389', { 'desc': 'party popper', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F38A', { 'desc': 'confetti ball', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F38B', { 'desc': 'tanabata tree', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F38D', { 'desc': 'pine decoration', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F38E', { 'desc': 'Japanese dolls', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F38F', { 'desc': 'carp streamer', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F390', { 'desc': 'wind chime', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F391', { 'desc': 'moon viewing ceremony', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E7', { 'desc': 'red envelope', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F380', { 'desc': 'ribbon', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F381', { 'desc': 'wrapped gift', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F397\U0000FE0F', { 'desc': 'reminder ribbon', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True }), ('\U0001F397', { 'desc': 'reminder ribbon', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F39F\U0000FE0F', { 'desc': 'admission tickets', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True }), ('\U0001F39F', { 'desc': 'admission tickets', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3AB', { 'desc': 'ticket', 'group': 'Activities', 'subgroup': 'event', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F396\U0000FE0F', { 'desc': 'military medal', 'group': 'Activities', 'subgroup': 'award-medal', 'fully-qualified': True }), ('\U0001F396', { 'desc': 'military medal', 'group': 'Activities', 'subgroup': 'award-medal', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3C6', { 'desc': 'trophy', 'group': 'Activities', 'subgroup': 'award-medal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3C5', { 'desc': 'sports medal', 'group': 'Activities', 'subgroup': 'award-medal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F947', { 'desc': '1st place medal', 'group': 'Activities', 'subgroup': 'award-medal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F948', { 'desc': '2nd place medal', 'group': 'Activities', 'subgroup': 'award-medal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F949', { 'desc': '3rd place medal', 'group': 'Activities', 'subgroup': 'award-medal', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026BD', { 'desc': 'soccer ball', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026BE', { 'desc': 'baseball', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F94E', { 'desc': 'softball', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3C0', { 'desc': 'basketball', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D0', { 'desc': 'volleyball', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3C8', { 'desc': 'american football', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3C9', { 'desc': 'rugby football', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3BE', { 'desc': 'tennis', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F94F', { 'desc': 'flying disc', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B3', { 'desc': 'bowling', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3CF', { 'desc': 'cricket game', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D1', { 'desc': 'field hockey', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D2', { 'desc': 'ice hockey', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F94D', { 'desc': 'lacrosse', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3D3', { 'desc': 'ping pong', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3F8', { 'desc': 'badminton', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F94A', { 'desc': 'boxing glove', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F94B', { 'desc': 'martial arts uniform', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F945', { 'desc': 'goal net', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026F3', { 'desc': 'flag in hole', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026F8\U0000FE0F', { 'desc': 'ice skate', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True }), ('\U000026F8', { 'desc': 'ice skate', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3A3', { 'desc': 'fishing pole', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3BD', { 'desc': 'running shirt', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3BF', { 'desc': 'skis', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6F7', { 'desc': 'sled', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F94C', { 'desc': 'curling stone', 'group': 'Activities', 'subgroup': 'sport', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3AF', { 'desc': 'direct hit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B1', { 'desc': 'pool 8 ball', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F52E', { 'desc': 'crystal ball', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9FF', { 'desc': 'nazar amulet', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3AE', { 'desc': 'video game', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F579\U0000FE0F', { 'desc': 'joystick', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True }), ('\U0001F579', { 'desc': 'joystick', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3B0', { 'desc': 'slot machine', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B2', { 'desc': 'game die', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9E9', { 'desc': 'jigsaw', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9F8', { 'desc': 'teddy bear', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002660\U0000FE0F', { 'desc': 'spade suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True }), ('\U00002660', { 'desc': 'spade suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002665\U0000FE0F', { 'desc': 'heart suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True }), ('\U00002665', { 'desc': 'heart suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002666\U0000FE0F', { 'desc': 'diamond suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True }), ('\U00002666', { 'desc': 'diamond suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002663\U0000FE0F', { 'desc': 'club suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True }), ('\U00002663', { 'desc': 'club suit', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000265F\U0000FE0F', { 'desc': 'chess pawn', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True }), ('\U0000265F', { 'desc': 'chess pawn', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F0CF', { 'desc': 'joker', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F004', { 'desc': 'mahjong red dragon', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B4', { 'desc': 'flower playing cards', 'group': 'Activities', 'subgroup': 'game', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3AD', { 'desc': 'performing arts', 'group': 'Activities', 'subgroup': 'arts & crafts', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5BC\U0000FE0F', { 'desc': 'framed picture', 'group': 'Activities', 'subgroup': 'arts & crafts', 'fully-qualified': True }), ('\U0001F5BC', { 'desc': 'framed picture', 'group': 'Activities', 'subgroup': 'arts & crafts', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3A8', { 'desc': 'artist palette', 'group': 'Activities', 'subgroup': 'arts & crafts', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9F5', { 'desc': 'thread', 'group': 'Activities', 'subgroup': 'arts & crafts', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9F6', { 'desc': 'yarn', 'group': 'Activities', 'subgroup': 'arts & crafts', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F507', { 'desc': 'muted speaker', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F508', { 'desc': 'speaker low volume', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F509', { 'desc': 'speaker medium volume', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F50A', { 'desc': 'speaker high volume', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E2', { 'desc': 'loudspeaker', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E3', { 'desc': 'megaphone', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4EF', { 'desc': 'postal horn', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F514', { 'desc': 'bell', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F515', { 'desc': 'bell with slash', 'group': 'Objects', 'subgroup': 'sound', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3BC', { 'desc': 'musical score', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B5', { 'desc': 'musical note', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B6', { 'desc': 'musical notes', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F399\U0000FE0F', { 'desc': 'studio microphone', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True }), ('\U0001F399', { 'desc': 'studio microphone', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F39A\U0000FE0F', { 'desc': 'level slider', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True }), ('\U0001F39A', { 'desc': 'level slider', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F39B\U0000FE0F', { 'desc': 'control knobs', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True }), ('\U0001F39B', { 'desc': 'control knobs', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3A4', { 'desc': 'microphone', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3A7', { 'desc': 'headphone', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4FB', { 'desc': 'radio', 'group': 'Objects', 'subgroup': 'music', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B7', { 'desc': 'saxophone', 'group': 'Objects', 'subgroup': 'musical-instrument', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B8', { 'desc': 'guitar', 'group': 'Objects', 'subgroup': 'musical-instrument', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3B9', { 'desc': 'musical keyboard', 'group': 'Objects', 'subgroup': 'musical-instrument', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3BA', { 'desc': 'trumpet', 'group': 'Objects', 'subgroup': 'musical-instrument', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3BB', { 'desc': 'violin', 'group': 'Objects', 'subgroup': 'musical-instrument', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F941', { 'desc': 'drum', 'group': 'Objects', 'subgroup': 'musical-instrument', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F1', { 'desc': 'mobile phone', 'group': 'Objects', 'subgroup': 'phone', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F2', { 'desc': 'mobile phone with arrow', 'group': 'Objects', 'subgroup': 'phone', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000260E\U0000FE0F', { 'desc': 'telephone', 'group': 'Objects', 'subgroup': 'phone', 'fully-qualified': True }), ('\U0000260E', { 'desc': 'telephone', 'group': 'Objects', 'subgroup': 'phone', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4DE', { 'desc': 'telephone receiver', 'group': 'Objects', 'subgroup': 'phone', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4DF', { 'desc': 'pager', 'group': 'Objects', 'subgroup': 'phone', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E0', { 'desc': 'fax machine', 'group': 'Objects', 'subgroup': 'phone', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F50B', { 'desc': 'battery', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F50C', { 'desc': 'electric plug', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4BB', { 'desc': 'laptop computer', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5A5\U0000FE0F', { 'desc': 'desktop computer', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True }), ('\U0001F5A5', { 'desc': 'desktop computer', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5A8\U0000FE0F', { 'desc': 'printer', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True }), ('\U0001F5A8', { 'desc': 'printer', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002328\U0000FE0F', { 'desc': 'keyboard', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True }), ('\U00002328', { 'desc': 'keyboard', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5B1\U0000FE0F', { 'desc': 'computer mouse', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True }), ('\U0001F5B1', { 'desc': 'computer mouse', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5B2\U0000FE0F', { 'desc': 'trackball', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True }), ('\U0001F5B2', { 'desc': 'trackball', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4BD', { 'desc': 'computer disk', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4BE', { 'desc': 'floppy disk', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4BF', { 'desc': 'optical disk', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C0', { 'desc': 'dvd', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9EE', { 'desc': 'abacus', 'group': 'Objects', 'subgroup': 'computer', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3A5', { 'desc': 'movie camera', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F39E\U0000FE0F', { 'desc': 'film frames', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True }), ('\U0001F39E', { 'desc': 'film frames', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4FD\U0000FE0F', { 'desc': 'film projector', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True }), ('\U0001F4FD', { 'desc': 'film projector', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3AC', { 'desc': 'clapper board', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4FA', { 'desc': 'television', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F7', { 'desc': 'camera', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F8', { 'desc': 'camera with flash', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F9', { 'desc': 'video camera', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4FC', { 'desc': 'videocassette', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F50D', { 'desc': 'magnifying glass tilted left', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F50E', { 'desc': 'magnifying glass tilted right', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F56F\U0000FE0F', { 'desc': 'candle', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True }), ('\U0001F56F', { 'desc': 'candle', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4A1', { 'desc': 'light bulb', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F526', { 'desc': 'flashlight', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3EE', { 'desc': 'red paper lantern', 'group': 'Objects', 'subgroup': 'light & video', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D4', { 'desc': 'notebook with decorative cover', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D5', { 'desc': 'closed book', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D6', { 'desc': 'open book', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D7', { 'desc': 'green book', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D8', { 'desc': 'blue book', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D9', { 'desc': 'orange book', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4DA', { 'desc': 'books', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D3', { 'desc': 'notebook', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D2', { 'desc': 'ledger', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C3', { 'desc': 'page with curl', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4DC', { 'desc': 'scroll', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C4', { 'desc': 'page facing up', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F0', { 'desc': 'newspaper', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5DE\U0000FE0F', { 'desc': 'rolled-up newspaper', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True }), ('\U0001F5DE', { 'desc': 'rolled-up newspaper', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4D1', { 'desc': 'bookmark tabs', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F516', { 'desc': 'bookmark', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3F7\U0000FE0F', { 'desc': 'label', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': True }), ('\U0001F3F7', { 'desc': 'label', 'group': 'Objects', 'subgroup': 'book-paper', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4B0', { 'desc': 'money bag', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B4', { 'desc': 'yen banknote', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B5', { 'desc': 'dollar banknote', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B6', { 'desc': 'euro banknote', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B7', { 'desc': 'pound banknote', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B8', { 'desc': 'money with wings', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B3', { 'desc': 'credit card', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9FE', { 'desc': 'receipt', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B9', { 'desc': 'chart increasing with yen', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B1', { 'desc': 'currency exchange', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4B2', { 'desc': 'heavy dollar sign', 'group': 'Objects', 'subgroup': 'money', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002709\U0000FE0F', { 'desc': 'envelope', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True }), ('\U00002709', { 'desc': 'envelope', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4E7', { 'desc': 'e-mail', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E8', { 'desc': 'incoming envelope', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E9', { 'desc': 'envelope with arrow', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E4', { 'desc': 'outbox tray', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E5', { 'desc': 'inbox tray', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E6', { 'desc': 'package', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4EB', { 'desc': 'closed mailbox with raised flag', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4EA', { 'desc': 'closed mailbox with lowered flag', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4EC', { 'desc': 'open mailbox with raised flag', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4ED', { 'desc': 'open mailbox with lowered flag', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4EE', { 'desc': 'postbox', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5F3\U0000FE0F', { 'desc': 'ballot box with ballot', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': True }), ('\U0001F5F3', { 'desc': 'ballot box with ballot', 'group': 'Objects', 'subgroup': 'mail', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000270F\U0000FE0F', { 'desc': 'pencil', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': True }), ('\U0000270F', { 'desc': 'pencil', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002712\U0000FE0F', { 'desc': 'black nib', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': True }), ('\U00002712', { 'desc': 'black nib', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F58B\U0000FE0F', { 'desc': 'fountain pen', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': True }), ('\U0001F58B', { 'desc': 'fountain pen', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F58A\U0000FE0F', { 'desc': 'pen', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': True }), ('\U0001F58A', { 'desc': 'pen', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F58C\U0000FE0F', { 'desc': 'paintbrush', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': True }), ('\U0001F58C', { 'desc': 'paintbrush', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F58D\U0000FE0F', { 'desc': 'crayon', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': True }), ('\U0001F58D', { 'desc': 'crayon', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4DD', { 'desc': 'memo', 'group': 'Objects', 'subgroup': 'writing', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4BC', { 'desc': 'briefcase', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C1', { 'desc': 'file folder', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C2', { 'desc': 'open file folder', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5C2\U0000FE0F', { 'desc': 'card index dividers', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U0001F5C2', { 'desc': 'card index dividers', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4C5', { 'desc': 'calendar', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C6', { 'desc': 'tear-off calendar', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5D2\U0000FE0F', { 'desc': 'spiral notepad', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U0001F5D2', { 'desc': 'spiral notepad', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5D3\U0000FE0F', { 'desc': 'spiral calendar', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U0001F5D3', { 'desc': 'spiral calendar', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4C7', { 'desc': 'card index', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C8', { 'desc': 'chart increasing', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4C9', { 'desc': 'chart decreasing', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4CA', { 'desc': 'bar chart', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4CB', { 'desc': 'clipboard', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4CC', { 'desc': 'pushpin', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4CD', { 'desc': 'round pushpin', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4CE', { 'desc': 'paperclip', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F587\U0000FE0F', { 'desc': 'linked paperclips', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U0001F587', { 'desc': 'linked paperclips', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F4CF', { 'desc': 'straight ruler', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4D0', { 'desc': 'triangular ruler', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002702\U0000FE0F', { 'desc': 'scissors', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U00002702', { 'desc': 'scissors', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5C3\U0000FE0F', { 'desc': 'card file box', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U0001F5C3', { 'desc': 'card file box', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5C4\U0000FE0F', { 'desc': 'file cabinet', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U0001F5C4', { 'desc': 'file cabinet', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5D1\U0000FE0F', { 'desc': 'wastebasket', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': True }), ('\U0001F5D1', { 'desc': 'wastebasket', 'group': 'Objects', 'subgroup': 'office', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F512', { 'desc': 'locked', 'group': 'Objects', 'subgroup': 'lock', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F513', { 'desc': 'unlocked', 'group': 'Objects', 'subgroup': 'lock', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F50F', { 'desc': 'locked with pen', 'group': 'Objects', 'subgroup': 'lock', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F510', { 'desc': 'locked with key', 'group': 'Objects', 'subgroup': 'lock', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F511', { 'desc': 'key', 'group': 'Objects', 'subgroup': 'lock', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F5DD\U0000FE0F', { 'desc': 'old key', 'group': 'Objects', 'subgroup': 'lock', 'fully-qualified': True }), ('\U0001F5DD', { 'desc': 'old key', 'group': 'Objects', 'subgroup': 'lock', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F528', { 'desc': 'hammer', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026CF\U0000FE0F', { 'desc': 'pick', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U000026CF', { 'desc': 'pick', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002692\U0000FE0F', { 'desc': 'hammer and pick', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U00002692', { 'desc': 'hammer and pick', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6E0\U0000FE0F', { 'desc': 'hammer and wrench', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U0001F6E0', { 'desc': 'hammer and wrench', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5E1\U0000FE0F', { 'desc': 'dagger', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U0001F5E1', { 'desc': 'dagger', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002694\U0000FE0F', { 'desc': 'crossed swords', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U00002694', { 'desc': 'crossed swords', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F52B', { 'desc': 'pistol', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3F9', { 'desc': 'bow and arrow', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6E1\U0000FE0F', { 'desc': 'shield', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U0001F6E1', { 'desc': 'shield', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F527', { 'desc': 'wrench', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F529', { 'desc': 'nut and bolt', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002699\U0000FE0F', { 'desc': 'gear', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U00002699', { 'desc': 'gear', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5DC\U0000FE0F', { 'desc': 'clamp', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U0001F5DC', { 'desc': 'clamp', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002696\U0000FE0F', { 'desc': 'balance scale', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U00002696', { 'desc': 'balance scale', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F517', { 'desc': 'link', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026D3\U0000FE0F', { 'desc': 'chains', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True }), ('\U000026D3', { 'desc': 'chains', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F9F0', { 'desc': 'toolbox', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9F2', { 'desc': 'magnet', 'group': 'Objects', 'subgroup': 'tool', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002697\U0000FE0F', { 'desc': 'alembic', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': True }), ('\U00002697', { 'desc': 'alembic', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F9EA', { 'desc': 'test tube', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9EB', { 'desc': 'petri dish', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9EC', { 'desc': 'dna', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F52C', { 'desc': 'microscope', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F52D', { 'desc': 'telescope', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4E1', { 'desc': 'satellite antenna', 'group': 'Objects', 'subgroup': 'science', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F489', { 'desc': 'syringe', 'group': 'Objects', 'subgroup': 'medical', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F48A', { 'desc': 'pill', 'group': 'Objects', 'subgroup': 'medical', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6AA', { 'desc': 'door', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6CF\U0000FE0F', { 'desc': 'bed', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True }), ('\U0001F6CF', { 'desc': 'bed', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6CB\U0000FE0F', { 'desc': 'couch and lamp', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True }), ('\U0001F6CB', { 'desc': 'couch and lamp', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6BD', { 'desc': 'toilet', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6BF', { 'desc': 'shower', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6C1', { 'desc': 'bathtub', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9F4', { 'desc': 'lotion bottle', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9F7', { 'desc': 'safety pin', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9F9', { 'desc': 'broom', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9FA', { 'desc': 'basket', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9FB', { 'desc': 'roll of paper', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9FC', { 'desc': 'soap', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9FD', { 'desc': 'sponge', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F9EF', { 'desc': 'fire extinguisher', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6D2', { 'desc': 'shopping cart', 'group': 'Objects', 'subgroup': 'household', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6AC', { 'desc': 'cigarette', 'group': 'Objects', 'subgroup': 'other-object', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026B0\U0000FE0F', { 'desc': 'coffin', 'group': 'Objects', 'subgroup': 'other-object', 'fully-qualified': True }), ('\U000026B0', { 'desc': 'coffin', 'group': 'Objects', 'subgroup': 'other-object', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000026B1\U0000FE0F', { 'desc': 'funeral urn', 'group': 'Objects', 'subgroup': 'other-object', 'fully-qualified': True }), ('\U000026B1', { 'desc': 'funeral urn', 'group': 'Objects', 'subgroup': 'other-object', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F5FF', { 'desc': 'moai', 'group': 'Objects', 'subgroup': 'other-object', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3E7', { 'desc': 'ATM sign', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6AE', { 'desc': 'litter in bin sign', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6B0', { 'desc': 'potable water', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000267F', { 'desc': 'wheelchair symbol', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6B9', { 'desc': 'men�s room', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6BA', { 'desc': 'women�s room', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6BB', { 'desc': 'restroom', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6BC', { 'desc': 'baby symbol', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6BE', { 'desc': 'water closet', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6C2', { 'desc': 'passport control', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6C3', { 'desc': 'customs', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6C4', { 'desc': 'baggage claim', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6C5', { 'desc': 'left luggage', 'group': 'Symbols', 'subgroup': 'transport-sign', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026A0\U0000FE0F', { 'desc': 'warning', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True }), ('\U000026A0', { 'desc': 'warning', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F6B8', { 'desc': 'children crossing', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026D4', { 'desc': 'no entry', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6AB', { 'desc': 'prohibited', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6B3', { 'desc': 'no bicycles', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6AD', { 'desc': 'no smoking', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6AF', { 'desc': 'no littering', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6B1', { 'desc': 'non-potable water', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6B7', { 'desc': 'no pedestrians', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F5', { 'desc': 'no mobile phones', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F51E', { 'desc': 'no one under eighteen', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002622\U0000FE0F', { 'desc': 'radioactive', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True }), ('\U00002622', { 'desc': 'radioactive', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002623\U0000FE0F', { 'desc': 'biohazard', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': True }), ('\U00002623', { 'desc': 'biohazard', 'group': 'Symbols', 'subgroup': 'warning', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002B06\U0000FE0F', { 'desc': 'up arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002B06', { 'desc': 'up arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002197\U0000FE0F', { 'desc': 'up-right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002197', { 'desc': 'up-right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000027A1\U0000FE0F', { 'desc': 'right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U000027A1', { 'desc': 'right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002198\U0000FE0F', { 'desc': 'down-right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002198', { 'desc': 'down-right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002B07\U0000FE0F', { 'desc': 'down arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002B07', { 'desc': 'down arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002199\U0000FE0F', { 'desc': 'down-left arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002199', { 'desc': 'down-left arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002B05\U0000FE0F', { 'desc': 'left arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002B05', { 'desc': 'left arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002196\U0000FE0F', { 'desc': 'up-left arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002196', { 'desc': 'up-left arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002195\U0000FE0F', { 'desc': 'up-down arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002195', { 'desc': 'up-down arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002194\U0000FE0F', { 'desc': 'left-right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002194', { 'desc': 'left-right arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000021A9\U0000FE0F', { 'desc': 'right arrow curving left', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U000021A9', { 'desc': 'right arrow curving left', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000021AA\U0000FE0F', { 'desc': 'left arrow curving right', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U000021AA', { 'desc': 'left arrow curving right', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002934\U0000FE0F', { 'desc': 'right arrow curving up', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002934', { 'desc': 'right arrow curving up', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002935\U0000FE0F', { 'desc': 'right arrow curving down', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True }), ('\U00002935', { 'desc': 'right arrow curving down', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F503', { 'desc': 'clockwise vertical arrows', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F504', { 'desc': 'counterclockwise arrows button', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F519', { 'desc': 'BACK arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F51A', { 'desc': 'END arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F51B', { 'desc': 'ON! arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F51C', { 'desc': 'SOON arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F51D', { 'desc': 'TOP arrow', 'group': 'Symbols', 'subgroup': 'arrow', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6D0', { 'desc': 'place of worship', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000269B\U0000FE0F', { 'desc': 'atom symbol', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U0000269B', { 'desc': 'atom symbol', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F549\U0000FE0F', { 'desc': 'om', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U0001F549', { 'desc': 'om', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002721\U0000FE0F', { 'desc': 'star of David', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U00002721', { 'desc': 'star of David', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002638\U0000FE0F', { 'desc': 'wheel of dharma', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U00002638', { 'desc': 'wheel of dharma', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000262F\U0000FE0F', { 'desc': 'yin yang', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U0000262F', { 'desc': 'yin yang', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000271D\U0000FE0F', { 'desc': 'latin cross', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U0000271D', { 'desc': 'latin cross', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002626\U0000FE0F', { 'desc': 'orthodox cross', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U00002626', { 'desc': 'orthodox cross', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000262A\U0000FE0F', { 'desc': 'star and crescent', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U0000262A', { 'desc': 'star and crescent', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000262E\U0000FE0F', { 'desc': 'peace symbol', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True }), ('\U0000262E', { 'desc': 'peace symbol', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F54E', { 'desc': 'menorah', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F52F', { 'desc': 'dotted six-pointed star', 'group': 'Symbols', 'subgroup': 'religion', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002648', { 'desc': 'Aries', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002649', { 'desc': 'Taurus', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000264A', { 'desc': 'Gemini', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000264B', { 'desc': 'Cancer', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000264C', { 'desc': 'Leo', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000264D', { 'desc': 'Virgo', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000264E', { 'desc': 'Libra', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000264F', { 'desc': 'Scorpio', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002650', { 'desc': 'Sagittarius', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002651', { 'desc': 'Capricorn', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002652', { 'desc': 'Aquarius', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002653', { 'desc': 'Pisces', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026CE', { 'desc': 'Ophiuchus', 'group': 'Symbols', 'subgroup': 'zodiac', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F500', { 'desc': 'shuffle tracks button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F501', { 'desc': 'repeat button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F502', { 'desc': 'repeat single button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000025B6\U0000FE0F', { 'desc': 'play button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000025B6', { 'desc': 'play button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000023E9', { 'desc': 'fast-forward button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023ED\U0000FE0F', { 'desc': 'next track button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000023ED', { 'desc': 'next track button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000023EF\U0000FE0F', { 'desc': 'play or pause button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000023EF', { 'desc': 'play or pause button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000025C0\U0000FE0F', { 'desc': 'reverse button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000025C0', { 'desc': 'reverse button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000023EA', { 'desc': 'fast reverse button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023EE\U0000FE0F', { 'desc': 'last track button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000023EE', { 'desc': 'last track button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F53C', { 'desc': 'upwards button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023EB', { 'desc': 'fast up button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F53D', { 'desc': 'downwards button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023EC', { 'desc': 'fast down button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000023F8\U0000FE0F', { 'desc': 'pause button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000023F8', { 'desc': 'pause button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000023F9\U0000FE0F', { 'desc': 'stop button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000023F9', { 'desc': 'stop button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000023FA\U0000FE0F', { 'desc': 'record button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000023FA', { 'desc': 'record button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000023CF\U0000FE0F', { 'desc': 'eject button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True }), ('\U000023CF', { 'desc': 'eject button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3A6', { 'desc': 'cinema', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F505', { 'desc': 'dim button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F506', { 'desc': 'bright button', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F6', { 'desc': 'antenna bars', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F3', { 'desc': 'vibration mode', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4F4', { 'desc': 'mobile phone off', 'group': 'Symbols', 'subgroup': 'av-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002640\U0000FE0F', { 'desc': 'female sign', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002640', { 'desc': 'female sign', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002642\U0000FE0F', { 'desc': 'male sign', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002642', { 'desc': 'male sign', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002695\U0000FE0F', { 'desc': 'medical symbol', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002695', { 'desc': 'medical symbol', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000267E\U0000FE0F', { 'desc': 'infinity', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U0000267E', { 'desc': 'infinity', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000267B\U0000FE0F', { 'desc': 'recycling symbol', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U0000267B', { 'desc': 'recycling symbol', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000269C\U0000FE0F', { 'desc': 'fleur-de-lis', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U0000269C', { 'desc': 'fleur-de-lis', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F531', { 'desc': 'trident emblem', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4DB', { 'desc': 'name badge', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F530', { 'desc': 'Japanese symbol for beginner', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002B55', { 'desc': 'heavy large circle', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002705', { 'desc': 'white heavy check mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002611\U0000FE0F', { 'desc': 'ballot box with check', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002611', { 'desc': 'ballot box with check', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002714\U0000FE0F', { 'desc': 'heavy check mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002714', { 'desc': 'heavy check mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002716\U0000FE0F', { 'desc': 'heavy multiplication x', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002716', { 'desc': 'heavy multiplication x', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000274C', { 'desc': 'cross mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000274E', { 'desc': 'cross mark button', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002795', { 'desc': 'heavy plus sign', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002796', { 'desc': 'heavy minus sign', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002797', { 'desc': 'heavy division sign', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000027B0', { 'desc': 'curly loop', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000027BF', { 'desc': 'double curly loop', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0000303D\U0000FE0F', { 'desc': 'part alternation mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U0000303D', { 'desc': 'part alternation mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002733\U0000FE0F', { 'desc': 'eight-spoked asterisk', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002733', { 'desc': 'eight-spoked asterisk', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002734\U0000FE0F', { 'desc': 'eight-pointed star', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002734', { 'desc': 'eight-pointed star', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002747\U0000FE0F', { 'desc': 'sparkle', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002747', { 'desc': 'sparkle', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0000203C\U0000FE0F', { 'desc': 'double exclamation mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U0000203C', { 'desc': 'double exclamation mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002049\U0000FE0F', { 'desc': 'exclamation question mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002049', { 'desc': 'exclamation question mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002753', { 'desc': 'question mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002754', { 'desc': 'white question mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002755', { 'desc': 'white exclamation mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002757', { 'desc': 'exclamation mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00003030\U0000FE0F', { 'desc': 'wavy dash', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00003030', { 'desc': 'wavy dash', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000000A9\U0000FE0F', { 'desc': 'copyright', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U000000A9', { 'desc': 'copyright', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000000AE\U0000FE0F', { 'desc': 'registered', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U000000AE', { 'desc': 'registered', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00002122\U0000FE0F', { 'desc': 'trade mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': True }), ('\U00002122', { 'desc': 'trade mark', 'group': 'Symbols', 'subgroup': 'other-symbol', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00000023\U0000FE0F\U000020E3', { 'desc': 'keycap: #', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000023\U000020E3', { 'desc': 'keycap: #', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U0000002A\U0000FE0F\U000020E3', { 'desc': 'keycap: *', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U0000002A\U000020E3', { 'desc': 'keycap: *', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000030\U0000FE0F\U000020E3', { 'desc': 'keycap: 0', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000030\U000020E3', { 'desc': 'keycap: 0', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000031\U0000FE0F\U000020E3', { 'desc': 'keycap: 1', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000031\U000020E3', { 'desc': 'keycap: 1', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000032\U0000FE0F\U000020E3', { 'desc': 'keycap: 2', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000032\U000020E3', { 'desc': 'keycap: 2', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000033\U0000FE0F\U000020E3', { 'desc': 'keycap: 3', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000033\U000020E3', { 'desc': 'keycap: 3', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000034\U0000FE0F\U000020E3', { 'desc': 'keycap: 4', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000034\U000020E3', { 'desc': 'keycap: 4', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000035\U0000FE0F\U000020E3', { 'desc': 'keycap: 5', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000035\U000020E3', { 'desc': 'keycap: 5', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000036\U0000FE0F\U000020E3', { 'desc': 'keycap: 6', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000036\U000020E3', { 'desc': 'keycap: 6', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000037\U0000FE0F\U000020E3', { 'desc': 'keycap: 7', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000037\U000020E3', { 'desc': 'keycap: 7', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000038\U0000FE0F\U000020E3', { 'desc': 'keycap: 8', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000038\U000020E3', { 'desc': 'keycap: 8', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U00000039\U0000FE0F\U000020E3', { 'desc': 'keycap: 9', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji_Keycap_Sequence': True }), ('\U00000039\U000020E3', { 'desc': 'keycap: 9', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': False, 'Emoji_Keycap_Sequence': True }), ('\U0001F51F', { 'desc': 'keycap: 10', 'group': 'Symbols', 'subgroup': 'keycap', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4AF', { 'desc': 'hundred points', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F520', { 'desc': 'input latin uppercase', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F521', { 'desc': 'input latin lowercase', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F522', { 'desc': 'input numbers', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F523', { 'desc': 'input symbols', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F524', { 'desc': 'input latin letters', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F170\U0000FE0F', { 'desc': 'A button (blood type)', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U0001F170', { 'desc': 'A button (blood type)', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F18E', { 'desc': 'AB button (blood type)', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F171\U0000FE0F', { 'desc': 'B button (blood type)', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U0001F171', { 'desc': 'B button (blood type)', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F191', { 'desc': 'CL button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F192', { 'desc': 'COOL button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F193', { 'desc': 'FREE button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002139\U0000FE0F', { 'desc': 'information', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U00002139', { 'desc': 'information', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F194', { 'desc': 'ID button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000024C2\U0000FE0F', { 'desc': 'circled M', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U000024C2', { 'desc': 'circled M', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F195', { 'desc': 'NEW button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F196', { 'desc': 'NG button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F17E\U0000FE0F', { 'desc': 'O button (blood type)', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U0001F17E', { 'desc': 'O button (blood type)', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F197', { 'desc': 'OK button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F17F\U0000FE0F', { 'desc': 'P button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U0001F17F', { 'desc': 'P button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F198', { 'desc': 'SOS button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F199', { 'desc': 'UP! button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F19A', { 'desc': 'VS button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F201', { 'desc': 'Japanese �here� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F202\U0000FE0F', { 'desc': 'Japanese �service charge� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U0001F202', { 'desc': 'Japanese �service charge� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F237\U0000FE0F', { 'desc': 'Japanese �monthly amount� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U0001F237', { 'desc': 'Japanese �monthly amount� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F236', { 'desc': 'Japanese �not free of charge� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F22F', { 'desc': 'Japanese �reserved� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F250', { 'desc': 'Japanese �bargain� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F239', { 'desc': 'Japanese �discount� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F21A', { 'desc': 'Japanese �free of charge� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F232', { 'desc': 'Japanese �prohibited� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F251', { 'desc': 'Japanese �acceptable� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F238', { 'desc': 'Japanese �application� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F234', { 'desc': 'Japanese �passing grade� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F233', { 'desc': 'Japanese �vacancy� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00003297\U0000FE0F', { 'desc': 'Japanese �congratulations� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U00003297', { 'desc': 'Japanese �congratulations� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U00003299\U0000FE0F', { 'desc': 'Japanese �secret� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True }), ('\U00003299', { 'desc': 'Japanese �secret� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F23A', { 'desc': 'Japanese �open for business� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F235', { 'desc': 'Japanese �no vacancy� button', 'group': 'Symbols', 'subgroup': 'alphanum', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000025AA\U0000FE0F', { 'desc': 'black small square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True }), ('\U000025AA', { 'desc': 'black small square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000025AB\U0000FE0F', { 'desc': 'white small square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True }), ('\U000025AB', { 'desc': 'white small square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000025FB\U0000FE0F', { 'desc': 'white medium square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True }), ('\U000025FB', { 'desc': 'white medium square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000025FC\U0000FE0F', { 'desc': 'black medium square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True }), ('\U000025FC', { 'desc': 'black medium square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U000025FD', { 'desc': 'white medium-small square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000025FE', { 'desc': 'black medium-small square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002B1B', { 'desc': 'black large square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U00002B1C', { 'desc': 'white large square', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F536', { 'desc': 'large orange diamond', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F537', { 'desc': 'large blue diamond', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F538', { 'desc': 'small orange diamond', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F539', { 'desc': 'small blue diamond', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F53A', { 'desc': 'red triangle pointed up', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F53B', { 'desc': 'red triangle pointed down', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F4A0', { 'desc': 'diamond with a dot', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F518', { 'desc': 'radio button', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F532', { 'desc': 'black square button', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F533', { 'desc': 'white square button', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026AA', { 'desc': 'white circle', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U000026AB', { 'desc': 'black circle', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F534', { 'desc': 'red circle', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F535', { 'desc': 'blue circle', 'group': 'Symbols', 'subgroup': 'geometric', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3C1', { 'desc': 'chequered flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F6A9', { 'desc': 'triangular flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F38C', { 'desc': 'crossed flags', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3F4', { 'desc': 'black flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': True, 'Emoji': True, 'Emoji_Presentation': True, 'Extended_Pictographic': True }), ('\U0001F3F3\U0000FE0F', { 'desc': 'white flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': True }), ('\U0001F3F3', { 'desc': 'white flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': False, 'Emoji': True, 'Extended_Pictographic': True }), ('\U0001F3F3\U0000FE0F\U0000200D\U0001F308', { 'desc': 'rainbow flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F3F3\U0000200D\U0001F308', { 'desc': 'rainbow flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': False }), ('\U0001F3F4\U0000200D\U00002620\U0000FE0F', { 'desc': 'pirate flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': True, 'Emoji_ZWJ_Sequence': True }), ('\U0001F3F4\U0000200D\U00002620', { 'desc': 'pirate flag', 'group': 'Flags', 'subgroup': 'flag', 'fully-qualified': False }), ('\U0001F1E6\U0001F1E8', { 'desc': 'Ascension Island', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1E9', { 'desc': 'Andorra', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1EA', { 'desc': 'United Arab Emirates', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1EB', { 'desc': 'Afghanistan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1EC', { 'desc': 'Antigua & Barbuda', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1EE', { 'desc': 'Anguilla', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1F1', { 'desc': 'Albania', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1F2', { 'desc': 'Armenia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1F4', { 'desc': 'Angola', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1F6', { 'desc': 'Antarctica', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1F7', { 'desc': 'Argentina', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1F8', { 'desc': 'American Samoa', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1F9', { 'desc': 'Austria', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1FA', { 'desc': 'Australia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1FC', { 'desc': 'Aruba', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1FD', { 'desc': '�land Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E6\U0001F1FF', { 'desc': 'Azerbaijan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1E6', { 'desc': 'Bosnia & Herzegovina', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1E7', { 'desc': 'Barbados', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1E9', { 'desc': 'Bangladesh', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1EA', { 'desc': 'Belgium', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1EB', { 'desc': 'Burkina Faso', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1EC', { 'desc': 'Bulgaria', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1ED', { 'desc': 'Bahrain', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1EE', { 'desc': 'Burundi', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1EF', { 'desc': 'Benin', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F1', { 'desc': 'St. Barth�lemy', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F2', { 'desc': 'Bermuda', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F3', { 'desc': 'Brunei', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F4', { 'desc': 'Bolivia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F6', { 'desc': 'Caribbean Netherlands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F7', { 'desc': 'Brazil', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F8', { 'desc': 'Bahamas', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1F9', { 'desc': 'Bhutan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1FB', { 'desc': 'Bouvet Island', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1FC', { 'desc': 'Botswana', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1FE', { 'desc': 'Belarus', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E7\U0001F1FF', { 'desc': 'Belize', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1E6', { 'desc': 'Canada', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1E8', { 'desc': 'Cocos (Keeling) Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1E9', { 'desc': 'Congo - Kinshasa', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1EB', { 'desc': 'Central African Republic', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1EC', { 'desc': 'Congo - Brazzaville', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1ED', { 'desc': 'Switzerland', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1EE', { 'desc': 'C�te d�Ivoire', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1F0', { 'desc': 'Cook Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1F1', { 'desc': 'Chile', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1F2', { 'desc': 'Cameroon', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1F3', { 'desc': 'China', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1F4', { 'desc': 'Colombia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1F5', { 'desc': 'Clipperton Island', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1F7', { 'desc': 'Costa Rica', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1FA', { 'desc': 'Cuba', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1FB', { 'desc': 'Cape Verde', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1FC', { 'desc': 'Cura�ao', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1FD', { 'desc': 'Christmas Island', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1FE', { 'desc': 'Cyprus', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E8\U0001F1FF', { 'desc': 'Czechia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E9\U0001F1EA', { 'desc': 'Germany', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E9\U0001F1EC', { 'desc': 'Diego Garcia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E9\U0001F1EF', { 'desc': 'Djibouti', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E9\U0001F1F0', { 'desc': 'Denmark', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E9\U0001F1F2', { 'desc': 'Dominica', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E9\U0001F1F4', { 'desc': 'Dominican Republic', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1E9\U0001F1FF', { 'desc': 'Algeria', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1E6', { 'desc': 'Ceuta & Melilla', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1E8', { 'desc': 'Ecuador', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1EA', { 'desc': 'Estonia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1EC', { 'desc': 'Egypt', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1ED', { 'desc': 'Western Sahara', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1F7', { 'desc': 'Eritrea', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1F8', { 'desc': 'Spain', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1F9', { 'desc': 'Ethiopia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EA\U0001F1FA', { 'desc': 'European Union', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EB\U0001F1EE', { 'desc': 'Finland', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EB\U0001F1EF', { 'desc': 'Fiji', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EB\U0001F1F0', { 'desc': 'Falkland Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EB\U0001F1F2', { 'desc': 'Micronesia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EB\U0001F1F4', { 'desc': 'Faroe Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EB\U0001F1F7', { 'desc': 'France', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1E6', { 'desc': 'Gabon', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1E7', { 'desc': 'United Kingdom', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1E9', { 'desc': 'Grenada', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1EA', { 'desc': 'Georgia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1EB', { 'desc': 'French Guiana', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1EC', { 'desc': 'Guernsey', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1ED', { 'desc': 'Ghana', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1EE', { 'desc': 'Gibraltar', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F1', { 'desc': 'Greenland', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F2', { 'desc': 'Gambia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F3', { 'desc': 'Guinea', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F5', { 'desc': 'Guadeloupe', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F6', { 'desc': 'Equatorial Guinea', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F7', { 'desc': 'Greece', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F8', { 'desc': 'South Georgia & South Sandwich Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1F9', { 'desc': 'Guatemala', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1FA', { 'desc': 'Guam', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1FC', { 'desc': 'Guinea-Bissau', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EC\U0001F1FE', { 'desc': 'Guyana', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1ED\U0001F1F0', { 'desc': 'Hong Kong SAR China', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1ED\U0001F1F2', { 'desc': 'Heard & McDonald Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1ED\U0001F1F3', { 'desc': 'Honduras', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1ED\U0001F1F7', { 'desc': 'Croatia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1ED\U0001F1F9', { 'desc': 'Haiti', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1ED\U0001F1FA', { 'desc': 'Hungary', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1E8', { 'desc': 'Canary Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1E9', { 'desc': 'Indonesia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1EA', { 'desc': 'Ireland', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F1', { 'desc': 'Israel', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F2', { 'desc': 'Isle of Man', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F3', { 'desc': 'India', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F4', { 'desc': 'British Indian Ocean Territory', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F6', { 'desc': 'Iraq', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F7', { 'desc': 'Iran', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F8', { 'desc': 'Iceland', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EE\U0001F1F9', { 'desc': 'Italy', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EF\U0001F1EA', { 'desc': 'Jersey', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EF\U0001F1F2', { 'desc': 'Jamaica', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EF\U0001F1F4', { 'desc': 'Jordan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1EF\U0001F1F5', { 'desc': 'Japan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1EA', { 'desc': 'Kenya', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1EC', { 'desc': 'Kyrgyzstan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1ED', { 'desc': 'Cambodia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1EE', { 'desc': 'Kiribati', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1F2', { 'desc': 'Comoros', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1F3', { 'desc': 'St. Kitts & Nevis', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1F5', { 'desc': 'North Korea', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1F7', { 'desc': 'South Korea', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1FC', { 'desc': 'Kuwait', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1FE', { 'desc': 'Cayman Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F0\U0001F1FF', { 'desc': 'Kazakhstan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1E6', { 'desc': 'Laos', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1E7', { 'desc': 'Lebanon', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1E8', { 'desc': 'St. Lucia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1EE', { 'desc': 'Liechtenstein', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1F0', { 'desc': 'Sri Lanka', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1F7', { 'desc': 'Liberia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1F8', { 'desc': 'Lesotho', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1F9', { 'desc': 'Lithuania', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1FA', { 'desc': 'Luxembourg', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1FB', { 'desc': 'Latvia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F1\U0001F1FE', { 'desc': 'Libya', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1E6', { 'desc': 'Morocco', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1E8', { 'desc': 'Monaco', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1E9', { 'desc': 'Moldova', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1EA', { 'desc': 'Montenegro', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1EB', { 'desc': 'St. Martin', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1EC', { 'desc': 'Madagascar', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1ED', { 'desc': 'Marshall Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F0', { 'desc': 'Macedonia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F1', { 'desc': 'Mali', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F2', { 'desc': 'Myanmar (Burma)', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F3', { 'desc': 'Mongolia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F4', { 'desc': 'Macau SAR China', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F5', { 'desc': 'Northern Mariana Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F6', { 'desc': 'Martinique', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F7', { 'desc': 'Mauritania', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F8', { 'desc': 'Montserrat', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1F9', { 'desc': 'Malta', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1FA', { 'desc': 'Mauritius', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1FB', { 'desc': 'Maldives', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1FC', { 'desc': 'Malawi', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1FD', { 'desc': 'Mexico', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1FE', { 'desc': 'Malaysia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F2\U0001F1FF', { 'desc': 'Mozambique', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1E6', { 'desc': 'Namibia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1E8', { 'desc': 'New Caledonia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1EA', { 'desc': 'Niger', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1EB', { 'desc': 'Norfolk Island', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1EC', { 'desc': 'Nigeria', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1EE', { 'desc': 'Nicaragua', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1F1', { 'desc': 'Netherlands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1F4', { 'desc': 'Norway', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1F5', { 'desc': 'Nepal', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1F7', { 'desc': 'Nauru', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1FA', { 'desc': 'Niue', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F3\U0001F1FF', { 'desc': 'New Zealand', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F4\U0001F1F2', { 'desc': 'Oman', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1E6', { 'desc': 'Panama', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1EA', { 'desc': 'Peru', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1EB', { 'desc': 'French Polynesia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1EC', { 'desc': 'Papua New Guinea', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1ED', { 'desc': 'Philippines', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1F0', { 'desc': 'Pakistan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1F1', { 'desc': 'Poland', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1F2', { 'desc': 'St. Pierre & Miquelon', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1F3', { 'desc': 'Pitcairn Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1F7', { 'desc': 'Puerto Rico', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1F8', { 'desc': 'Palestinian Territories', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1F9', { 'desc': 'Portugal', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1FC', { 'desc': 'Palau', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F5\U0001F1FE', { 'desc': 'Paraguay', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F6\U0001F1E6', { 'desc': 'Qatar', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F7\U0001F1EA', { 'desc': 'R�union', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F7\U0001F1F4', { 'desc': 'Romania', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F7\U0001F1F8', { 'desc': 'Serbia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F7\U0001F1FA', { 'desc': 'Russia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F7\U0001F1FC', { 'desc': 'Rwanda', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1E6', { 'desc': 'Saudi Arabia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1E7', { 'desc': 'Solomon Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1E8', { 'desc': 'Seychelles', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1E9', { 'desc': 'Sudan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1EA', { 'desc': 'Sweden', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1EC', { 'desc': 'Singapore', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1ED', { 'desc': 'St. Helena', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1EE', { 'desc': 'Slovenia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1EF', { 'desc': 'Svalbard & Jan Mayen', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F0', { 'desc': 'Slovakia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F1', { 'desc': 'Sierra Leone', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F2', { 'desc': 'San Marino', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F3', { 'desc': 'Senegal', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F4', { 'desc': 'Somalia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F7', { 'desc': 'Suriname', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F8', { 'desc': 'South Sudan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1F9', { 'desc': 'S�o Tom� & Pr�ncipe', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1FB', { 'desc': 'El Salvador', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1FD', { 'desc': 'Sint Maarten', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1FE', { 'desc': 'Syria', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F8\U0001F1FF', { 'desc': 'Swaziland', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1E6', { 'desc': 'Tristan da Cunha', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1E8', { 'desc': 'Turks & Caicos Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1E9', { 'desc': 'Chad', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1EB', { 'desc': 'French Southern Territories', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1EC', { 'desc': 'Togo', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1ED', { 'desc': 'Thailand', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1EF', { 'desc': 'Tajikistan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1F0', { 'desc': 'Tokelau', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1F1', { 'desc': 'Timor-Leste', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1F2', { 'desc': 'Turkmenistan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1F3', { 'desc': 'Tunisia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1F4', { 'desc': 'Tonga', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1F7', { 'desc': 'Turkey', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1F9', { 'desc': 'Trinidad & Tobago', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1FB', { 'desc': 'Tuvalu', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1FC', { 'desc': 'Taiwan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1F9\U0001F1FF', { 'desc': 'Tanzania', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FA\U0001F1E6', { 'desc': 'Ukraine', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FA\U0001F1EC', { 'desc': 'Uganda', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FA\U0001F1F2', { 'desc': 'U.S. Outlying Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FA\U0001F1F3', { 'desc': 'United Nations', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FA\U0001F1F8', { 'desc': 'United States', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FA\U0001F1FE', { 'desc': 'Uruguay', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FA\U0001F1FF', { 'desc': 'Uzbekistan', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FB\U0001F1E6', { 'desc': 'Vatican City', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FB\U0001F1E8', { 'desc': 'St. Vincent & Grenadines', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FB\U0001F1EA', { 'desc': 'Venezuela', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FB\U0001F1EC', { 'desc': 'British Virgin Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FB\U0001F1EE', { 'desc': 'U.S. Virgin Islands', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FB\U0001F1F3', { 'desc': 'Vietnam', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FB\U0001F1FA', { 'desc': 'Vanuatu', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FC\U0001F1EB', { 'desc': 'Wallis & Futuna', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FC\U0001F1F8', { 'desc': 'Samoa', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FD\U0001F1F0', { 'desc': 'Kosovo', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FE\U0001F1EA', { 'desc': 'Yemen', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FE\U0001F1F9', { 'desc': 'Mayotte', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FF\U0001F1E6', { 'desc': 'South Africa', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FF\U0001F1F2', { 'desc': 'Zambia', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F1FF\U0001F1FC', { 'desc': 'Zimbabwe', 'group': 'Flags', 'subgroup': 'country-flag', 'fully-qualified': True, 'Emoji_Flag_Sequence': True }), ('\U0001F3F4\U000E0067\U000E0062\U000E0065\U000E006E\U000E0067\U000E007F', { 'desc': 'England', 'group': 'Flags', 'subgroup': 'subdivision-flag', 'fully-qualified': True, 'Emoji_Tag_Sequence': True }), ('\U0001F3F4\U000E0067\U000E0062\U000E0073\U000E0063\U000E0074\U000E007F', { 'desc': 'Scotland', 'group': 'Flags', 'subgroup': 'subdivision-flag', 'fully-qualified': True, 'Emoji_Tag_Sequence': True }), ('\U0001F3F4\U000E0067\U000E0062\U000E0077\U000E006C\U000E0073\U000E007F', { 'desc': 'Wales', 'group': 'Flags', 'subgroup': 'subdivision-flag', 'fully-qualified': True, 'Emoji_Tag_Sequence': True }) ]) gajim-gajim-1.1.3/gajim/gtk/emoji_data.pyi000066400000000000000000000020041345766322700203760ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from enum import IntEnum from collections import OrderedDict from gi.repository import GdkPixbuf class Emoji(IntEnum): ... def is_emoji(codepoints: str) -> bool: ... def get_emoji_pixbuf(codepoints: str) -> GdkPixbuf.Pixbuf: ... class EmojiData(OrderedDict): ... class EmojiPixbufs(dict): ... class EmojiAsciiData(dict): ... emoji_pixbufs = EmojiPixbufs() emoji_ascii_data = EmojiAsciiData() emoji_data = EmojiData() gajim-gajim-1.1.3/gajim/gtk/features.py000066400000000000000000000157201345766322700177600ustar00rootroot00000000000000# Copyright (C) 2007 Jean-Marie Traissard # Julien Pivotto # Stefan Bethge # Stephan Erb # Copyright (C) 2007-2014 Yann Leboulanger # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import gi from gi.repository import Gtk, Gdk from gajim.common import app from gajim.common.i18n import Q_ from gajim.common.i18n import _ from gajim.gtk.util import get_builder class FeaturesDialog(Gtk.Dialog): def __init__(self): flags = Gtk.DialogFlags.DESTROY_WITH_PARENT super().__init__(_('Features'), None, flags) self.connect('key-press-event', self.on_key_press_event) self.set_transient_for(app.interface.roster.window) self.builder = get_builder('features_window.ui') content = self.get_content_area() content.add(self.builder.get_object('features_box')) treeview = self.builder.get_object('features_treeview') self.desc_label = self.builder.get_object('feature_desc_label') # {name: (available_function, unix_text, windows_text)} self.features = { _('Bonjour / Zeroconf'): ( self.zeroconf_available, _('Serverless chatting with autodetected clients in a local network.'), _('Requires python-dbus.'), _('Requires pybonjour and bonjour SDK running (%(url)s)') % {'url': 'https://developer.apple.com/opensource/).'}), _('Command line'): ( self.dbus_available, _('A script to control Gajim via commandline.'), _('Requires python-dbus.'), _('Feature not available under Windows.')), _('OpenPGP message encryption'): ( self.gpg_available, _('Ability to encrypting chat messages with OpenPGP.'), _('Requires gpg and python-gnupg (%(url)s).') % {'url': 'https://bitbucket.org/vinay.sajip/python-gnupg'}, _('Requires gpg.exe in PATH.')), _('Password encryption'): ( self.some_keyring_available, _('Passwords can be stored securely and not just in plaintext.'), _('Requires libsecret and a provider (such as GNOME Keyring and KSecretService).'), _('On Windows the Windows Credential Vault is used.')), _('Spell Checker'): ( self.speller_available, _('Spellchecking of composed messages.'), _('Requires Gspell'), _('Requires Gspell')), _('Automatic status'): ( self.idle_available, _('Ability to measure idle time, in order to set auto status.'), _('Requires libxss library.'), _('Requires python2.5.')), _('RST Generator'): ( self.docutils_available, _('Generate XHTML output from RST code (see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html).'), _('Requires python-docutils.'), _('Requires python-docutils.')), _('Audio / Video'): ( self.farstream_available, _('Ability to start audio and video chat.'), _('Requires gir1.2-farstream-0.2, gir1.2-gstreamer-1.0, gstreamer1.0-libav and gstreamer1.0-plugins-ugly.'), _('Feature not available under Windows.')), _('UPnP-IGD'): ( self.gupnp_igd_available, _('Ability to request your router to forward port for file transfer.'), _('Requires gir1.2-gupnpigd-1.0.'), _('Feature not available under Windows.')), } # name, supported self.model = Gtk.ListStore(str, bool) treeview.set_model(self.model) col = Gtk.TreeViewColumn(Q_('?features:Available')) treeview.append_column(col) cell = Gtk.CellRendererToggle() cell.set_property('radio', True) col.pack_start(cell, True) col.add_attribute(cell, 'active', 1) col = Gtk.TreeViewColumn(_('Feature')) treeview.append_column(col) cell = Gtk.CellRendererText() col.pack_start(cell, True) col.add_attribute(cell, 'text', 0) # Fill model for feature in self.features: func = self.features[feature][0] rep = func() self.model.append([feature, rep]) self.model.set_sort_column_id(0, Gtk.SortType.ASCENDING) self.builder.connect_signals(self) self.show_all() def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() def on_close_button_clicked(self, widget): self.destroy() def on_features_treeview_cursor_changed(self, widget): selection = widget.get_selection() if not selection: return rows = selection.get_selected_rows()[1] if not rows: return path = rows[0] feature = self.model[path][0] text = self.features[feature][1] + '\n' if os.name == 'nt': text = text + self.features[feature][3] else: text = text + self.features[feature][2] self.desc_label.set_text(text) def zeroconf_available(self): return app.is_installed('ZEROCONF') def dbus_available(self): from gajim.common import dbus_support return dbus_support.supported def gpg_available(self): return app.is_installed('GPG') def some_keyring_available(self): if os.name == 'nt': return True try: gi.require_version('Secret', '1') from gi.repository import Secret # pylint: disable=unused-variable except (ValueError, ImportError): return False return True def speller_available(self): return app.is_installed('GSPELL') def idle_available(self): from gajim.common import idle return idle.Monitor.is_available() def docutils_available(self): try: __import__('docutils') except Exception: return False return True def farstream_available(self): return app.is_installed('FARSTREAM') def gupnp_igd_available(self): return app.is_installed('UPNP') gajim-gajim-1.1.3/gajim/gtk/filechoosers.py000066400000000000000000000155201345766322700206250ustar00rootroot00000000000000# Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys from pathlib import Path from gi.repository import Gtk from gi.repository import GdkPixbuf from gi.repository import GObject from gajim.common import app from gajim.common.i18n import _ from gajim.gtk.const import Filter from gajim.gtk.types import FilterList # pylint: disable=unused-import def _require_native() -> bool: if app.is_flatpak(): return True if sys.platform in ('win32', 'darwin'): return True return False # Notes: Adding mime types to Gtk.FileFilter forces non-native dialogs class BaseFileChooser: def _on_response(self, dialog, response, accept_cb, cancel_cb): if response == Gtk.ResponseType.ACCEPT: if self.get_select_multiple(): accept_cb(dialog.get_filenames()) else: accept_cb(dialog.get_filename()) if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT): if cancel_cb is not None: cancel_cb() def _add_filters(self, filters): for filterinfo in filters: filter_ = Gtk.FileFilter() filter_.set_name(filterinfo.name) if isinstance(filterinfo.pattern, list): for mime_type in filterinfo.pattern: filter_.add_mime_type(mime_type) else: filter_.add_pattern(filterinfo.pattern) self.add_filter(filter_) if filterinfo.default: self.set_filter(filter_) def _update_preview(self, filechooser): path_to_file = filechooser.get_preview_filename() preview = filechooser.get_preview_widget() if path_to_file is None or os.path.isdir(path_to_file): # nothing to preview preview.clear() return try: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( path_to_file, *self._preivew_size) except GObject.GError: preview.clear() return filechooser.get_preview_widget().set_from_pixbuf(pixbuf) class BaseFileOpenDialog: _title = _('Choose File to Send…') _filters = [Filter(_('All files'), '*', True)] # type: FilterList class BaseAvatarChooserDialog: _title = _('Choose Avatar…') _preivew_size = (100, 100) if _require_native(): _filters = [Filter(_('PNG files'), '*.png', True), Filter(_('JPEG files'), '*.jp*g', False), Filter(_('SVG files'), '*.svg', False)] # type: FilterList else: _filters = [Filter(_('Images'), ['image/png', 'image/jpeg', 'image/svg+xml'], True)] class NativeFileChooserDialog(Gtk.FileChooserNative, BaseFileChooser): _title = '' _filters = [] # type: FilterList _action = Gtk.FileChooserAction.OPEN def __init__(self, accept_cb, cancel_cb=None, transient_for=None, path=None, file_name=None, select_multiple=False, modal=False): Gtk.FileChooserNative.__init__(self, title=self._title, action=self._action, transient_for=transient_for) self.set_current_folder(path or str(Path.home())) if file_name is not None: self.set_current_name(file_name) self.set_select_multiple(select_multiple) self.set_do_overwrite_confirmation(True) self.set_modal(modal) self._add_filters(self._filters) self.connect('response', self._on_response, accept_cb, cancel_cb) self.show() class ArchiveChooserDialog(NativeFileChooserDialog): _title = _('Choose Archive') _filters = [Filter(_('All files'), '*', False), Filter(_('ZIP files'), '*.zip', True)] class FileSaveDialog(NativeFileChooserDialog): _title = _('Save File as…') _filters = [Filter(_('All files'), '*', True)] _action = Gtk.FileChooserAction.SAVE class AvatarSaveDialog(FileSaveDialog): if sys.platform == 'win32': _filters = [Filter(_('Images'), '*.png;*.jpg;*.jpeg;*.svg', True)] class NativeFileOpenDialog(BaseFileOpenDialog, NativeFileChooserDialog): pass class NativeAvatarChooserDialog(BaseAvatarChooserDialog, NativeFileChooserDialog): pass class GtkFileChooserDialog(Gtk.FileChooserDialog, BaseFileChooser): _title = '' _filters = [] # type: FilterList _action = Gtk.FileChooserAction.OPEN _preivew_size = (200, 200) def __init__(self, accept_cb, cancel_cb=None, transient_for=None, path=None, file_name=None, select_multiple=False, preview=True, modal=False): Gtk.FileChooserDialog.__init__( self, title=self._title, action=self._action, buttons=[Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT], transient_for=transient_for) self.set_current_folder(path or str(Path.home())) if file_name is not None: self.set_current_name(file_name) self.set_select_multiple(select_multiple) self.set_do_overwrite_confirmation(True) self.set_modal(modal) self._add_filters(self._filters) if preview: self.set_use_preview_label(False) self.set_preview_widget(Gtk.Image()) self.connect('selection-changed', self._update_preview) self.connect('response', self._on_response, accept_cb, cancel_cb) self.show() def _on_response(self, *args): super()._on_response(*args) self.destroy() class GtkFileOpenDialog(BaseFileOpenDialog, GtkFileChooserDialog): pass class GtkAvatarChooserDialog(BaseAvatarChooserDialog, GtkFileChooserDialog): pass def FileChooserDialog(*args, **kwargs): if _require_native(): return NativeFileOpenDialog(*args, **kwargs) return GtkFileOpenDialog(*args, **kwargs) def AvatarChooserDialog(*args, **kwargs): if _require_native(): return NativeAvatarChooserDialog(*args, **kwargs) return GtkAvatarChooserDialog(*args, **kwargs) gajim-gajim-1.1.3/gajim/gtk/history.py000066400000000000000000000763041345766322700176500ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005 Vincent Hanquez # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2006 Dimitur Kirov # Travis Shirk # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Brendan Taylor # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import time import datetime from enum import IntEnum, unique from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gajim.common import app from gajim.common import helpers from gajim.common import exceptions from gajim.common.i18n import _ from gajim.common.const import ShowConstant from gajim.common.const import KindConstant from gajim.common.const import StyleAttr from gajim import conversation_textview from gajim.gtk import util from gajim.gtk.util import python_month, gtk_month from gajim.gtk.dialogs import ErrorDialog @unique class InfoColumn(IntEnum): '''Completion dict''' JID = 0 ACCOUNT = 1 NAME = 2 COMPLETION = 3 @unique class Column(IntEnum): LOG_JID = 0 CONTACT_NAME = 1 UNIXTIME = 2 MESSAGE = 3 TIME = 4 LOG_LINE_ID = 5 class HistoryWindow: """ Class for browsing logs of conversations with contacts """ def __init__(self, jid=None, account=None): xml = util.get_builder('history_window.ui') self.window = xml.get_object('history_window') self.window.set_application(app.app) self.calendar = xml.get_object('calendar') self.button_first_day = xml.get_object('button_first_day') self.button_previous_day = xml.get_object('button_previous_day') self.button_next_day = xml.get_object('button_next_day') self.button_last_day = xml.get_object('button_last_day') scrolledwindow = xml.get_object('scrolledwindow') self.history_textview = conversation_textview.ConversationTextview( account, used_in_history_window=True) scrolledwindow.add(self.history_textview.tv) self.history_buffer = self.history_textview.tv.get_buffer() highlight_color = app.css_config.get_value( '.gajim-highlight-message', StyleAttr.COLOR) self.history_buffer.create_tag('highlight', background=highlight_color) self.history_buffer.create_tag('invisible', invisible=True) self.checkbutton = xml.get_object('log_history_checkbutton') self.show_status_checkbutton = xml.get_object('show_status_checkbutton') self.search_entry = xml.get_object('search_entry') self.query_liststore = xml.get_object('query_liststore') self.jid_entry = xml.get_object('query_entry') self.results_treeview = xml.get_object('results_treeview') self.results_window = xml.get_object('results_scrolledwindow') self.search_in_date = xml.get_object('search_in_date') self.date_label = xml.get_object('date_label') self.search_menu_button = xml.get_object('search_menu_button') self.clearing_search = False # jid, contact_name, date, message, time, log_line_id model = Gtk.ListStore(str, str, str, str, str, int) self.results_treeview.set_model(model) col = Gtk.TreeViewColumn(_('Name')) self.results_treeview.append_column(col) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', Column.CONTACT_NAME) # user can click this header and sort col.set_sort_column_id(Column.CONTACT_NAME) col.set_resizable(True) col = Gtk.TreeViewColumn(_('Date')) self.results_treeview.append_column(col) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', Column.UNIXTIME) # user can click this header and sort col.set_sort_column_id(Column.UNIXTIME) col.set_resizable(True) col = Gtk.TreeViewColumn(_('Message')) self.results_treeview.append_column(col) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) col.add_attribute(renderer, 'text', Column.MESSAGE) col.set_resizable(True) self.jid = None # The history we are currently viewing self.account = account self.completion_dict = {} self.accounts_seen_online = [] # Update dict when new accounts connect self.jids_to_search = [] # This will load history too task = self._fill_completion_dict() GLib.idle_add(next, task) if jid: self.jid_entry.get_child().set_text(jid) else: self._load_history(None) util.resize_window(self.window, app.config.get('history_window_width'), app.config.get('history_window_height')) util.move_window(self.window, app.config.get('history_window_x-position'), app.config.get('history_window_y-position')) xml.connect_signals(self) self.window.show_all() # PluginSystem: adding GUI extension point for # HistoryWindow instance object app.plugin_manager.gui_extension_point( 'history_window', self) def _fill_completion_dict(self): """ Fill completion_dict for key auto completion. Then load history for current jid (by calling another function) Key will be either jid or full_completion_name (contact name or long description like "pm-contact from groupchat...."). {key : (jid, account, nick_name, full_completion_name} This is a generator and does pseudo-threading via idle_add(). """ liststore = util.get_completion_liststore( self.jid_entry.get_child()) liststore.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.jid_entry.get_child().get_completion().connect( 'match-selected', self.on_jid_entry_match_selected) self.jid_entry.set_model(liststore) # Add all jids in logs.db: db_jids = app.logger.get_jids_in_db() completion_dict = dict.fromkeys(db_jids) self.accounts_seen_online = list(app.contacts.get_accounts()) # Enhance contacts of online accounts with contact. # Needed for mapping below for account in self.accounts_seen_online: completion_dict.update( helpers.get_contact_dict_for_account(account)) muc_active_icon = util.get_iconset_name_for('muc-active') online_icon = util.get_iconset_name_for('online') keys = list(completion_dict.keys()) # Move the actual jid at first so we load history faster actual_jid = self.jid_entry.get_child().get_text() if actual_jid in keys: keys.remove(actual_jid) keys.insert(0, actual_jid) if '' in keys: keys.remove('') if None in keys: keys.remove(None) # Map jid to info tuple # Warning : This for is time critical with big DB for key in keys: completed = key completed2 = None contact = completion_dict[completed] if contact: info_name = contact.get_shown_name() info_completion = info_name info_jid = contact.jid else: # Corresponding account is offline, we know nothing info_name = completed.split('@')[0] info_completion = completed info_jid = completed info_acc = self._get_account_for_jid(info_jid) if (app.logger.jid_is_room_jid(completed) or app.logger.jid_is_from_pm(completed)): icon = muc_active_icon if app.logger.jid_is_from_pm(completed): # It's PM. Make it easier to find room, nick = app.get_room_and_nick_from_fjid(completed) info_completion = '%s from %s' % (nick, room) completed = info_completion info_completion2 = '%s/%s' % (room, nick) completed2 = info_completion2 info_name = nick else: icon = online_icon if len(completed) > 70: completed = completed[:70] + '[\u2026]' liststore.append((icon, completed)) self.completion_dict[key] = ( info_jid, info_acc, info_name, info_completion) self.completion_dict[completed] = ( info_jid, info_acc, info_name, info_completion) if completed2: if len(completed2) > 70: completed2 = completed2[:70] + '[\u2026]' liststore.append((icon, completed2)) self.completion_dict[completed2] = ( info_jid, info_acc, info_name, info_completion2) if key == actual_jid: self._load_history(info_jid, self.account or info_acc) yield True keys.sort() yield False def _get_account_for_jid(self, jid): """ Return the corresponding account of the jid. May be None if an account could not be found """ accounts = app.contacts.get_accounts() account = None for acc in accounts: jid_list = app.contacts.get_jid_list(acc) gc_list = app.contacts.get_gc_list(acc) if jid in jid_list or jid in gc_list: account = acc break return account def on_history_window_delete_event(self, widget, *args): self.save_state() def on_history_window_destroy(self, widget): # PluginSystem: removing GUI extension points connected with # HistoryWindow instance object app.plugin_manager.remove_gui_extension_point( 'history_window', self) self.history_textview.del_handlers() del app.interface.instances['logs'] def on_history_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.save_state() self.window.destroy() def on_jid_entry_match_selected(self, widget, model, iter_, *args): self._jid_entry_search(model[iter_][1]) return True def on_jid_entry_changed(self, widget): # only if selected from combobox jid = self.jid_entry.get_child().get_text() if jid == self.jid_entry.get_active_id(): self._jid_entry_search(jid) def on_jid_entry_activate(self, widget): self._jid_entry_search(self.jid_entry.get_child().get_text()) def _jid_entry_search(self, jid): self._load_history(jid, self.account) self.results_window.set_property('visible', False) def _load_history(self, jid_or_name, account=None): """ Load history for the given jid/name and show it """ if jid_or_name and jid_or_name in self.completion_dict: # a full qualified jid or a contact name was entered info_jid, info_account, _info_name, info_completion = self.completion_dict[jid_or_name] self.jids_to_search = [info_jid] self.jid = info_jid if account: self.account = account else: self.account = info_account if self.account is None: # We don't know account. Probably a gc not opened or an # account not connected. # Disable possibility to say if we want to log or not self.checkbutton.set_sensitive(False) else: # Are log disabled for account ? if self.account in app.config.get_per( 'accounts', self.account, 'no_log_for').split(' '): self.checkbutton.set_active(False) self.checkbutton.set_sensitive(False) else: # Are log disabled for jid ? log = True if self.jid in app.config.get_per( 'accounts', self.account, 'no_log_for').split(' '): log = False self.checkbutton.set_active(log) self.checkbutton.set_sensitive(True) self.jids_to_search = [info_jid] # Get first/last date we have logs with contact self.first_log = app.logger.get_first_date_that_has_logs( self.account, self.jid) self.first_day = self._get_date_from_timestamp(self.first_log) self.last_log = app.logger.get_last_date_that_has_logs( self.account, self.jid) self.last_day = self._get_date_from_timestamp(self.last_log) # Select logs for last date we have logs with contact self.search_menu_button.set_sensitive(True) month = gtk_month(self.last_day.month) self.calendar.select_month(month, self.last_day.year) self.calendar.select_day(self.last_day.day) self.button_previous_day.set_sensitive(True) self.button_next_day.set_sensitive(True) self.button_first_day.set_sensitive(True) self.button_last_day.set_sensitive(True) self.search_entry.set_sensitive(True) self.search_entry.grab_focus() self.jid_entry.get_child().set_text(info_completion) else: # neither a valid jid, nor an existing contact name was entered # we have got nothing to show or to search in self.jid = None self.account = None self.history_buffer.set_text('') # clear the buffer self.search_entry.set_sensitive(False) self.checkbutton.set_sensitive(False) self.search_menu_button.set_sensitive(False) self.calendar.clear_marks() self.button_previous_day.set_sensitive(False) self.button_next_day.set_sensitive(False) self.button_first_day.set_sensitive(False) self.button_last_day.set_sensitive(False) self.results_window.set_property('visible', False) def on_calendar_day_selected(self, widget): if not self.jid: return year, month, day = self.calendar.get_date() # integers month = python_month(month) date_str = datetime.date(year, month, day).strftime('%x') self.date_label.set_text(date_str) self._load_conversation(year, month, day) def on_calendar_month_changed(self, widget): """ Ask for days in this month, if they have logs it bolds them (marks them) """ if not self.jid: return year, month, _day = widget.get_date() # integers if year < 1900: widget.select_month(0, 1900) widget.select_day(1) return widget.clear_marks() month = python_month(month) try: log_days = app.logger.get_days_with_logs( self.account, self.jid, year, month) except exceptions.PysqliteOperationalError as error: ErrorDialog(_('Disk Error'), str(error)) return for date in log_days: widget.mark_day(date.day) def _get_date_from_timestamp(self, timestamp): # Conversion from timestamp to date log = time.localtime(timestamp) y, m, d = log[0], log[1], log[2] date = datetime.datetime(y, m, d) return date def _change_date(self, widget): # Get day selected in calendar y, m, d = self.calendar.get_date() py_m = python_month(m) _date = datetime.datetime(y, py_m, d) if widget is self.button_first_day: gtk_m = gtk_month(self.first_day.month) self.calendar.select_month(gtk_m, self.first_day.year) self.calendar.select_day(self.first_day.day) return if widget is self.button_last_day: gtk_m = gtk_month( self.last_day.month) self.calendar.select_month(gtk_m, self.last_day.year) self.calendar.select_day(self.last_day.day) return if widget is self.button_previous_day: end_date = self.first_day timedelta = datetime.timedelta(days=-1) if end_date >= _date: return elif widget is self.button_next_day: end_date = self.last_day timedelta = datetime.timedelta(days=1) if end_date <= _date: return # Iterate through days until log entry found or # supplied end_date (first_log / last_log) reached logs = None while logs is None: _date = _date + timedelta if _date == end_date: break try: logs = app.logger.get_date_has_logs( self.account, self.jid, _date) except exceptions.PysqliteOperationalError as e: ErrorDialog(_('Disk Error'), str(e)) return gtk_m = gtk_month(_date.month) self.calendar.select_month(gtk_m, _date.year) self.calendar.select_day(_date.day) def _get_string_show_from_constant_int(self, show): if show == ShowConstant.ONLINE: show = 'online' elif show == ShowConstant.CHAT: show = 'chat' elif show == ShowConstant.AWAY: show = 'away' elif show == ShowConstant.XA: show = 'xa' elif show == ShowConstant.DND: show = 'dnd' elif show == ShowConstant.OFFLINE: show = 'offline' return show def _load_conversation(self, year, month, day): """ Load the conversation between `self.jid` and `self.account` held on the given date into the history textbuffer. Values for `month` and `day` are 1-based. """ self.history_buffer.set_text('') self.last_time_printout = 0 show_status = self.show_status_checkbutton.get_active() date = datetime.datetime(year, month, day) conversation = app.logger.get_conversation_for_date( self.account, self.jid, date) for message in conversation: if not show_status and message.kind in (KindConstant.GCSTATUS, KindConstant.STATUS): continue self._add_message(message) def _add_message(self, msg): if not msg.message and msg.kind not in (KindConstant.STATUS, KindConstant.GCSTATUS): return tim = msg.time kind = msg.kind show = msg.show message = msg.message subject = msg.subject log_line_id = msg.log_line_id contact_name = msg.contact_name additional_data = msg.additional_data buf = self.history_buffer end_iter = buf.get_end_iter() # Make the beginning of every message searchable by its log_line_id buf.create_mark(str(log_line_id), end_iter, left_gravity=True) if app.config.get('print_time') == 'always': timestamp_str = app.config.get('time_stamp') timestamp_str = helpers.from_one_line(timestamp_str) tim = time.strftime(timestamp_str, time.localtime(float(tim))) buf.insert(end_iter, tim) elif app.config.get('print_time') == 'sometimes': every_foo_seconds = 60 * app.config.get( 'print_ichat_every_foo_minutes') seconds_passed = tim - self.last_time_printout if seconds_passed > every_foo_seconds: self.last_time_printout = tim tim = time.strftime('%X ', time.localtime(float(tim))) buf.insert_with_tags_by_name( end_iter, tim + '\n', 'time_sometimes') # print the encryption icon if kind in (KindConstant.CHAT_MSG_SENT, KindConstant.CHAT_MSG_RECV): self.history_textview.print_encryption_status( end_iter, additional_data) tag_name = '' tag_msg = '' show = self._get_string_show_from_constant_int(show) if kind == KindConstant.GC_MSG: tag_name = 'incoming' elif kind in (KindConstant.SINGLE_MSG_RECV, KindConstant.CHAT_MSG_RECV): contact_name = self.completion_dict[self.jid][InfoColumn.NAME] tag_name = 'incoming' tag_msg = 'incomingtxt' elif kind in (KindConstant.SINGLE_MSG_SENT, KindConstant.CHAT_MSG_SENT): if self.account: contact_name = app.nicks[self.account] else: # we don't have roster, we don't know our own nick, use first # account one (urk!) account = list(app.contacts.get_accounts())[0] contact_name = app.nicks[account] tag_name = 'outgoing' tag_msg = 'outgoingtxt' elif kind == KindConstant.GCSTATUS: # message here (if not None) is status message if message: message = _('%(nick)s is now %(status)s: %(status_msg)s') % { 'nick': contact_name, 'status': helpers.get_uf_show(show), 'status_msg': message} else: message = _('%(nick)s is now %(status)s') % { 'nick': contact_name, 'status': helpers.get_uf_show(show)} tag_msg = 'status' else: # 'status' # message here (if not None) is status message if show is None: # it means error if message: message = _('Error: %s') % message else: message = _('Error') elif message: message = _('Status is now: %(status)s: %(status_msg)s') % { 'status': helpers.get_uf_show(show), 'status_msg': message} else: message = _('Status is now: %(status)s') % { 'status': helpers.get_uf_show(show)} tag_msg = 'status' if message.startswith('/me ') or message.startswith('/me\n'): tag_msg = tag_name else: # do not do this if gcstats, avoid dupping contact_name # eg. nkour: nkour is now Offline if contact_name and kind != KindConstant.GCSTATUS: # add stuff before and after contact name before_str = app.config.get('before_nickname') before_str = helpers.from_one_line(before_str) after_str = app.config.get('after_nickname') after_str = helpers.from_one_line(after_str) format_ = before_str + contact_name + after_str + ' ' if tag_name: buf.insert_with_tags_by_name(end_iter, format_, tag_name) else: buf.insert(end_iter, format_) if subject: message = _('Subject: %s\n') % subject + message xhtml = None if message.startswith('. import logging from enum import IntEnum from datetime import datetime, timedelta from gi.repository import Gtk from gi.repository import GLib from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ from gajim.common.const import ArchiveState from gajim.gtk.util import load_icon log = logging.getLogger('gajim.gtk.history_sync') class Pages(IntEnum): TIME = 0 SYNC = 1 SUMMARY = 2 class HistorySyncAssistant(Gtk.Assistant): def __init__(self, account, parent): Gtk.Assistant.__init__(self) # self.set_title(_('Synchronise History')) self.set_resizable(False) self.set_default_size(300, -1) self.set_name('HistorySyncAssistant') self.set_transient_for(parent) self.account = account self.con = app.connections[self.account] self.timedelta = None self.now = datetime.utcnow() self.query_id = None self.start = None self.end = None self.next = None self.hide_buttons() own_jid = self.con.get_own_jid().getStripped() mam_start = ArchiveState.NEVER archive = app.logger.get_archive_infos(own_jid) if archive is not None and archive.oldest_mam_timestamp is not None: mam_start = int(float(archive.oldest_mam_timestamp)) if mam_start == ArchiveState.NEVER: self.current_start = self.now elif mam_start == ArchiveState.ALL: self.current_start = datetime.utcfromtimestamp(0) else: self.current_start = datetime.fromtimestamp(mam_start) self.select_time = SelectTimePage(self) self.append_page(self.select_time) self.set_page_type(self.select_time, Gtk.AssistantPageType.INTRO) self.download_history = DownloadHistoryPage(self) self.append_page(self.download_history) self.set_page_type(self.download_history, Gtk.AssistantPageType.PROGRESS) self.set_page_complete(self.download_history, True) self.summary = SummaryPage(self) self.append_page(self.summary) self.set_page_type(self.summary, Gtk.AssistantPageType.SUMMARY) self.set_page_complete(self.summary, True) app.ged.register_event_handler('archiving-count-received', ged.GUI1, self._received_count) app.ged.register_event_handler('archiving-interval-finished', ged.GUI1, self._received_finished) app.ged.register_event_handler('raw-mam-message-received', ged.PRECORE, self._nec_mam_message_received) self.connect('prepare', self.on_page_change) self.connect('destroy', self.on_destroy) self.connect("cancel", self.on_close_clicked) self.connect("close", self.on_close_clicked) if mam_start == ArchiveState.ALL: self.set_current_page(Pages.SUMMARY) self.summary.nothing_to_do() self.show_all() def hide_buttons(self): ''' Hide some of the standard buttons that are included in Gtk.Assistant ''' if self.get_property('use-header-bar'): action_area = self.get_children()[1] else: box = self.get_children()[0] content_box = box.get_children()[1] action_area = content_box.get_children()[1] for button in action_area.get_children(): button_name = Gtk.Buildable.get_name(button) if button_name == 'back': button.connect('show', self._on_show_button) elif button_name == 'forward': self.next = button button.connect('show', self._on_show_button) @staticmethod def _on_show_button(button): button.hide() def prepare_query(self): if self.timedelta: self.start = self.now - self.timedelta self.end = self.current_start log.info('get mam_start_date: %s', self.current_start) log.info('now: %s', self.now) log.info('start: %s', self.start) log.info('end: %s', self.end) self.query_id = self.con.get_module('MAM').request_archive_count( self.start, self.end) def _received_count(self, event): if event.query_id != self.query_id: return if event.count is not None: self.download_history.count = int(event.count) self.query_id = self.con.get_module('MAM').request_archive_interval( self.start, self.end) def _received_finished(self, event): if event.query_id != self.query_id: return self.query_id = None log.info('query finished') GLib.idle_add(self.download_history.finished) self.set_current_page(Pages.SUMMARY) self.summary.finished() def _nec_mam_message_received(self, event): if event.conn.name != self.account: return result = event.stanza.getTag('result') queryid = result.getAttr('queryid') if queryid != self.query_id: return log.debug('received message') GLib.idle_add(self.download_history.set_fraction) def on_row_selected(self, listbox, row): self.timedelta = row.get_child().get_delta() if row: self.set_page_complete(self.select_time, True) else: self.set_page_complete(self.select_time, False) def on_page_change(self, assistant, page): if page == self.download_history: self.next.hide() self.prepare_query() def on_destroy(self, *args): app.ged.remove_event_handler('archiving-count-received', ged.GUI1, self._received_count) app.ged.remove_event_handler('archiving-interval-finished', ged.GUI1, self._received_finished) app.ged.remove_event_handler('raw-mam-message-received', ged.PRECORE, self._nec_mam_message_received) del app.interface.instances[self.account]['history_sync'] def on_close_clicked(self, *args): self.destroy() class SelectTimePage(Gtk.Box): def __init__(self, assistant): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(18) self.assistant = assistant label = Gtk.Label(label=_('How far back do you want to go?')) listbox = Gtk.ListBox() listbox.set_hexpand(False) listbox.set_halign(Gtk.Align.CENTER) listbox.add(TimeOption(_('One Month'), 1)) listbox.add(TimeOption(_('Three Months'), 3)) listbox.add(TimeOption(_('One Year'), 12)) listbox.add(TimeOption(_('Everything'))) listbox.connect('row-selected', assistant.on_row_selected) for row in listbox.get_children(): option = row.get_child() if not option.get_delta(): continue if assistant.now - option.get_delta() > assistant.current_start: row.set_activatable(False) row.set_selectable(False) self.pack_start(label, True, True, 0) self.pack_start(listbox, False, False, 0) class DownloadHistoryPage(Gtk.Box): def __init__(self, assistant): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(18) self.assistant = assistant self.count = 0 self.received = 0 surface = load_icon('folder-download-symbolic', self, size=64) image = Gtk.Image.new_from_surface(surface) self.progress = Gtk.ProgressBar() self.progress.set_show_text(True) self.progress.set_text(_('Connecting...')) self.progress.set_pulse_step(0.1) self.progress.set_vexpand(True) self.progress.set_valign(Gtk.Align.CENTER) self.pack_start(image, False, False, 0) self.pack_start(self.progress, False, False, 0) def set_fraction(self): self.received += 1 if self.count: self.progress.set_fraction(self.received / self.count) self.progress.set_text(_('%(received)s of %(max)s' % { 'received': self.received, 'max': self.count})) else: self.progress.pulse() self.progress.set_text(_('Downloaded %s Messages' % self.received)) def finished(self): self.progress.set_fraction(1) class SummaryPage(Gtk.Box): def __init__(self, assistant): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(18) self.assistant = assistant self.label = Gtk.Label() self.label.set_name('FinishedLabel') self.label.set_valign(Gtk.Align.CENTER) self.pack_start(self.label, True, True, 0) def finished(self): received = self.assistant.download_history.received finished = _(''' Finished synchronising your History. {received} Messages downloaded. '''.format(received=received)) self.label.set_text(finished) def nothing_to_do(self): nothing_to_do = _(''' Gajim is fully synchronised with the Archive. ''') self.label.set_text(nothing_to_do) def query_already_running(self): already_running = _(''' There is already a synchronisation in progress. Please try later. ''') self.label.set_text(already_running) class TimeOption(Gtk.Label): def __init__(self, label, months=None): super().__init__(label=label) self.date = months if months: self.date = timedelta(days=30 * months) def get_delta(self): return self.date gajim-gajim-1.1.3/gajim/gtk/join_groupchat.py000066400000000000000000000261071345766322700211560ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import nbxmpp from gi.repository import Gtk from gi.repository import Gdk from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.caps_cache import muc_caps_cache from gajim.common.exceptions import GajimGeneralException from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.util import get_builder class JoinGroupchatWindow(Gtk.ApplicationWindow): def __init__(self, account, room_jid, password=None, automatic=None, transient_for=None): Gtk.ApplicationWindow.__init__(self) self.set_name('JoinGroupchat') self.set_application(app.app) self.set_show_menubar(False) self.set_resizable(False) self.set_position(Gtk.WindowPosition.CENTER) self.set_title(_('Join Group Chat')) if transient_for: self.set_transient_for(transient_for) self.automatic = automatic self.password = password self.requested_jid = None self.room_jid = room_jid self.account = account if self.room_jid is None: self.minimal_mode = False else: self.minimal_mode = True glade_objects = ['main_box', 'account_label', 'account_combo', 'server_label', 'server_combo', 'room_entry', 'recently_button', 'recently_popover', 'recently_treeview', 'search_button', 'password_label', 'password_entry', 'nick_entry', 'bookmark_switch', 'autojoin_switch'] self.builder = get_builder('join_groupchat_window.ui') for obj in glade_objects: setattr(self, obj, self.builder.get_object(obj)) self.add(self.main_box) # Show widgets depending on the mode the window is in if not self.minimal_mode: self.recently_button.show() self.search_button.show() accounts = app.get_enabled_accounts_with_labels() account_liststore = self.account_combo.get_model() for acc in accounts: account_liststore.append(acc) if not accounts: return if not self.account: self.account = accounts[0][0] self.builder.connect_signals(self) self.connect('key-press-event', self._on_key_press_event) # Hide account combobox if there is only one account if len(accounts) == 1: self.account_combo.hide() self.account_label.hide() self.account_combo.set_active_id(self.account) if self.minimal_mode: if '@' in self.room_jid: (room, server) = self.room_jid.split('@') self.room_entry.set_text(room) if not muc_caps_cache.supports( self.room_jid, 'muc_passwordprotected'): self.password_entry.hide() self.password_label.hide() self.nick_entry.grab_focus() else: self.password_entry.grab_focus() else: server = self.room_jid self.room_entry.grab_focus() self.server_combo.insert_text(0, server) self.server_combo.set_active(0) if self.password is not None: self.password_entry.set_text(self.password) # Set bookmark switch sensitive if server supports bookmarks acc = self.account_combo.get_active_id() con = app.connections[acc] if not con.get_module('Bookmarks').available: self.bookmark_switch.set_sensitive(False) self.autojoin_switch.set_sensitive(False) self.show_all() def set_room(self, room_jid): room, server = app.get_name_and_server_from_jid(room_jid) self.room_entry.set_text(room) self.server_combo.get_child().set_text(server) def _fill_recent_and_servers(self, account): recently_liststore = self.recently_treeview.get_model() recently_liststore.clear() self.server_combo.remove_all() recent = app.get_recent_groupchats(account) servers = [] for groupchat in recent: label = '%s@%s' % (groupchat.room, groupchat.server) recently_liststore.append([groupchat.server, groupchat.room, groupchat.nickname, label]) servers.append(groupchat.server) self.recently_button.set_sensitive(bool(recent)) for server in set(servers): self.server_combo.append_text(server) # Add own Server to ComboBox muc_domain = app.get_muc_domain(account) if muc_domain is not None: self.server_combo.insert_text(0, muc_domain) def _on_recent_selected(self, treeview, *args): (model, iter_) = treeview.get_selection().get_selected() self.server_combo.get_child().set_text(model[iter_][0]) self.room_entry.set_text(model[iter_][1]) self.nick_entry.set_text(model[iter_][2]) self.recently_popover.popdown() def _on_account_combo_changed(self, combo): account = combo.get_active_id() self.account = account self.nick_entry.set_text(app.nicks[account]) self._fill_recent_and_servers(account) def _on_jid_detection_changed(self, widget): text = widget.get_text() if text.startswith('xmpp:'): text = text[5:] if '@' in text: room, server = text.split('@', 1) server = server.split('?')[0] widget.set_text('') if room: self.room_entry.set_text(room) if server: self.server_combo.get_child().set_text(server) else: self.server_combo.grab_focus() def _on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() if event.keyval == Gdk.KEY_Return: self._on_join_clicked() return True def _on_join_clicked(self, *args): account = self.account_combo.get_active_id() nickname = self.nick_entry.get_text() invisible_show = app.SHOW_LIST.index('invisible') if app.connections[account].connected == invisible_show: app.interface.raise_dialog('join-while-invisible') return server = self.server_combo.get_active_text() room = self.room_entry.get_text() if room == '': ErrorDialog(_('Invalid Room'), _('Please choose a room'), transient_for=self) return self.room_jid = '%s@%s' % (room, server) try: self.room_jid = helpers.parse_jid(self.room_jid) except helpers.InvalidFormat as error: ErrorDialog(_('Invalid JID'), str(error), transient_for=self) return if app.in_groupchat(account, self.room_jid): # If we already in the groupchat, join_gc_room will bring # it to front app.interface.join_gc_room(account, self.room_jid, nickname, '') self.destroy() return if nickname == '': ErrorDialog(_('Invalid Nickname'), _('Please choose a nickname'), transient_for=self) return try: helpers.parse_resource(nickname) except helpers.InvalidFormat as error: ErrorDialog(_('Invalid Nickname'), str(error), transient_for=self) return if not app.account_is_connected(account): ErrorDialog( _('You are not connected to the server'), _('You can not join a group chat unless you are connected.'), transient_for=self) return password = self.password_entry.get_text() self._add_bookmark(account, nickname, password) app.add_recent_groupchat(account, self.room_jid, nickname) if self.automatic: app.automatic_rooms[self.account][self.room_jid] = self.automatic app.interface.join_gc_room(account, self.room_jid, nickname, password) self.destroy() def _on_cancel_clicked(self, *args): self.destroy() def _on_bookmark_activate(self, switch, param): bookmark_state = switch.get_active() self.autojoin_switch.set_sensitive(bookmark_state) if not bookmark_state: self.autojoin_switch.set_active(False) def _add_bookmark(self, account, nickname, password): con = app.connections[account] add_bookmark = self.bookmark_switch.get_active() if not add_bookmark: return autojoin = self.autojoin_switch.get_active() # Add as bookmark, with autojoin and not minimized name = app.get_nick_from_jid(self.room_jid) con.get_module('Bookmarks').add_bookmark(name, self.room_jid, autojoin, True, password, nickname) def _on_search_clicked(self, widget): server = self.server_combo.get_active_text().strip() con = app.connections[self.account] con.get_module('Discovery').disco_info( server, success_cb=self._disco_info_received, error_cb=self._disco_info_error) def _disco_info_error(self, from_, error): ErrorDialog(_('Wrong server'), _('%s is not a groupchat server') % from_, transient_for=self) def _disco_info_received(self, from_, identities, features, data, node): if nbxmpp.NS_MUC not in features: ErrorDialog(_('Wrong server'), _('%s is not a groupchat server') % from_, transient_for=self) return jid = str(from_) if jid in app.interface.instances[self.account]['disco']: app.interface.instances[self.account]['disco'][jid].window.\ present() else: try: # Object will add itself to the window dict from gajim.disco import ServiceDiscoveryWindow ServiceDiscoveryWindow( self.account, jid, initial_identities=[{'category': 'conference', 'type': 'text'}]) except GajimGeneralException: pass gajim-gajim-1.1.3/gajim/gtk/mam_preferences.py000066400000000000000000000126051345766322700212740ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging from gi.repository import Gtk from gi.repository import Gdk from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ from gajim.gtk.util import get_builder from gajim.gtk.dialogs import HigDialog log = logging.getLogger('gajim.gtk.mam_preferences') class MamPreferences(Gtk.ApplicationWindow): def __init__(self, account): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_title(_('Archiving Preferences for %s') % account) self.connect('destroy', self._on_destroy) self.connect('key-press-event', self._on_key_press) self.account = account self._con = app.connections[account] self._builder = get_builder('mam_preferences.ui') self.add(self._builder.get_object('preferences_grid')) self._default = self._builder.get_object('default_cb') self._pref_store = self._builder.get_object('preferences_store') self._overlay = self._builder.get_object('overlay') self._spinner = Gtk.Spinner() self._overlay.add_overlay(self._spinner) app.ged.register_event_handler('mam-prefs-received', ged.GUI1, self._mam_prefs_received) app.ged.register_event_handler('mam-prefs-saved', ged.GUI1, self._mam_prefs_saved) app.ged.register_event_handler('mam-prefs-error', ged.GUI1, self._mam_prefs_error) self._set_grid_state(False) self._builder.connect_signals(self) self.show_all() self._activate_spinner() self._con.get_module('MAM').request_mam_preferences() def _mam_prefs_received(self, obj): if obj.conn.name != self.account: return self._disable_spinner() self._set_grid_state(True) self._default.set_active_id(obj.default) self._pref_store.clear() for item in obj.rules: self._pref_store.append(item) def _mam_prefs_saved(self, obj): if obj.conn.name != self.account: return self._disable_spinner() def on_ok(dialog): self.destroy() dialog = HigDialog( self, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _('Success!'), _('Your Archiving Preferences have been saved!'), on_response_ok=on_ok, on_response_cancel=on_ok) dialog.popup() def _mam_prefs_error(self, obj=None): if obj and obj.conn.name != self.account: return self._disable_spinner() if not obj: msg = _('No response from the Server') else: msg = _('Error received: {}').format(obj.error_msg) dialog = HigDialog( self, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _('Error!'), msg) dialog.popup() self._set_grid_state(True) def _set_grid_state(self, state): self._builder.get_object('preferences_grid').set_sensitive(state) def _jid_edited(self, renderer, path, new_text): iter_ = self._pref_store.get_iter(path) self._pref_store.set_value(iter_, 0, new_text) def _pref_toggled(self, renderer, path): iter_ = self._pref_store.get_iter(path) current_value = self._pref_store[iter_][1] self._pref_store.set_value(iter_, 1, not current_value) def _on_add(self, button): self._pref_store.append(['', False]) def _on_remove(self, button): pref_view = self._builder.get_object('pref_view') mod, paths = pref_view.get_selection().get_selected_rows() for path in paths: iter_ = mod.get_iter(path) self._pref_store.remove(iter_) def _on_save(self, button): self._activate_spinner() self._set_grid_state(False) items = [] default = self._default.get_active_id() for item in self._pref_store: items.append((item[0].lower(), item[1])) self._con.get_module('MAM').set_mam_preferences(items, default) def _activate_spinner(self): self._spinner.show() self._spinner.start() def _disable_spinner(self): self._spinner.hide() self._spinner.stop() def _on_key_press(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() def _on_destroy(self, widget): app.ged.remove_event_handler('mam-prefs-received', ged.GUI1, self._mam_prefs_received) app.ged.remove_event_handler('mam-prefs-saved', ged.GUI1, self._mam_prefs_saved) app.ged.remove_event_handler('mam-prefs-error', ged.GUI1, self._mam_prefs_error) gajim-gajim-1.1.3/gajim/gtk/pep_config.py000066400000000000000000000122221345766322700202450ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gtk from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import WarningDialog from gajim.gtk.util import get_builder class ManagePEPServicesWindow: def __init__(self, account): self.xml = get_builder('manage_pep_services_window.ui') self.window = self.xml.get_object('manage_pep_services_window') self.window.set_transient_for(app.interface.roster.window) self.xml.get_object('configure_button').set_sensitive(False) self.xml.get_object('delete_button').set_sensitive(False) self.xml.connect_signals(self) self.account = account self._con = app.connections[self.account] self.init_services() self.xml.get_object('services_treeview').get_selection().connect( 'changed', self.on_services_selection_changed) app.ged.register_event_handler( 'pubsub-config-received', ged.GUI1, self._nec_pep_config_received) self.window.show_all() def on_manage_pep_services_window_destroy(self, widget): del app.interface.instances[self.account]['pep_services'] app.ged.remove_event_handler( 'pubsub-config-received', ged.GUI1, self._nec_pep_config_received) def on_close_button_clicked(self, widget): self.window.destroy() def on_services_selection_changed(self, sel): self.xml.get_object('configure_button').set_sensitive(True) self.xml.get_object('delete_button').set_sensitive(True) def init_services(self): self.treeview = self.xml.get_object('services_treeview') # service, access_model, group self.treestore = Gtk.ListStore(str) self.treeview.set_model(self.treestore) col = Gtk.TreeViewColumn('Service') self.treeview.append_column(col) cellrenderer_text = Gtk.CellRendererText() col.pack_start(cellrenderer_text, True) col.add_attribute(cellrenderer_text, 'text', 0) jid = self._con.get_own_jid().getStripped() self._con.get_module('Discovery').disco_items( jid, success_cb=self._items_received, error_cb=self._items_error) def _items_received(self, from_, node, items): jid = self._con.get_own_jid().getStripped() for item in items: if item['jid'] == jid and 'node' in item: self.treestore.append([item['node']]) def _items_error(self, from_, error): ErrorDialog('Error', error) def node_removed(self, jid, node): if jid != app.get_jid_from_account(self.account): return model = self.treeview.get_model() iter_ = model.get_iter_first() while iter_: if model[iter_][0] == node: model.remove(iter_) break iter_ = model.iter_next(iter_) def node_not_removed(self, jid, node, msg): if jid != app.get_jid_from_account(self.account): return WarningDialog( _('PEP node was not removed'), _('PEP node %(node)s was not removed: %(message)s') % { 'node': node, 'message': msg}) def on_delete_button_clicked(self, widget): selection = self.treeview.get_selection() if not selection: return model, iter_ = selection.get_selected() node = model[iter_][0] our_jid = app.get_jid_from_account(self.account) con = app.connections[self.account] con.get_module('PubSub').send_pb_delete(our_jid, node, on_ok=self.node_removed, on_fail=self.node_not_removed) def on_configure_button_clicked(self, widget): selection = self.treeview.get_selection() if not selection: return model, iter_ = selection.get_selected() node = model[iter_][0] our_jid = app.get_jid_from_account(self.account) con = app.connections[self.account] con.get_module('PubSub').request_pb_configuration(our_jid, node) def _nec_pep_config_received(self, obj): def on_ok(form, node): form.type_ = 'submit' our_jid = app.get_jid_from_account(self.account) con = app.connections[self.account] con.get_module('PubSub').send_pb_configure(our_jid, node, form) from gajim.dialogs import DataFormWindow window = DataFormWindow(obj.form, (on_ok, obj.node)) title = _('Configure %s') % obj.node window.set_title(title) window.show_all() gajim-gajim-1.1.3/gajim/gtk/preferences.py000066400000000000000000001212161345766322700204410ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys from gi.repository import Gtk from gi.repository import Gdk from gi.repository import Pango from gajim.common import app from gajim.common import helpers from gajim.common import configpaths from gajim.common import config as c_config from gajim.common import idle from gajim.common.i18n import _ from gajim import message_control from gajim import cell_renderer_image from gajim import gtkgui_helpers from gajim.chat_control_base import ChatControlBase from gajim.config import ManageProxiesWindow from gajim.config import ManageSoundsWindow from gajim.gtk.util import get_builder from gajim.gtk.dialogs import AspellDictError from gajim.gtk.themes import Themes from gajim.gtk.advanced_config import AdvancedConfig try: from gajim.common.multimedia_helpers import AudioInputManager, AudioOutputManager from gajim.common.multimedia_helpers import VideoInputManager, VideoOutputManager HAS_GST = True except (ImportError, ValueError): HAS_GST = False if app.is_installed('GSPELL'): from gi.repository import Gspell class Preferences(Gtk.ApplicationWindow): def __init__(self): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_title(_('Preferences')) self.set_default_size(-1, 400) self.xml = get_builder('preferences_window.ui') self.notebook = self.xml.get_object('preferences_notebook') self.add(self.notebook) self.one_window_type_combobox = self.xml.get_object( 'one_window_type_combobox') self.iconset_combobox = self.xml.get_object('iconset_combobox') self.notify_on_signin_checkbutton = self.xml.get_object( 'notify_on_signin_checkbutton') self.notify_on_signout_checkbutton = self.xml.get_object( 'notify_on_signout_checkbutton') self.auto_popup_away_checkbutton = self.xml.get_object( 'auto_popup_away_checkbutton') self.auto_popup_chat_opened_checkbutton = self.xml.get_object( 'auto_popup_chat_opened_checkbutton') self.sound_dnd_checkbutton = self.xml.get_object('sound_dnd_checkbutton') self.auto_away_checkbutton = self.xml.get_object('auto_away_checkbutton') self.auto_away_time_spinbutton = self.xml.get_object( 'auto_away_time_spinbutton') self.auto_away_message_entry = self.xml.get_object( 'auto_away_message_entry') self.auto_xa_checkbutton = self.xml.get_object('auto_xa_checkbutton') self.auto_xa_time_spinbutton = self.xml.get_object( 'auto_xa_time_spinbutton') self.auto_xa_message_entry = self.xml.get_object('auto_xa_message_entry') ### General tab ### # Display avatars in roster st = app.config.get('show_avatars_in_roster') self.xml.get_object('show_avatars_in_roster_checkbutton'). \ set_active(st) # Display status msg under contact name in roster st = app.config.get('show_status_msgs_in_roster') self.xml.get_object('show_status_msgs_in_roster_checkbutton'). \ set_active(st) # Display PEP in roster st1 = app.config.get('show_mood_in_roster') st2 = app.config.get('show_activity_in_roster') st3 = app.config.get('show_tunes_in_roster') st4 = app.config.get('show_location_in_roster') w = self.xml.get_object('show_pep_in_roster_checkbutton') if st1 == st2 == st3 == st4: w.set_active(st1) else: w.set_inconsistent(True) # Sort contacts by show st = app.config.get('sort_by_show_in_roster') self.xml.get_object('sort_by_show_in_roster_checkbutton').set_active(st) st = app.config.get('sort_by_show_in_muc') self.xml.get_object('sort_by_show_in_muc_checkbutton').set_active(st) # Set default for single window type choices = c_config.opt_one_window_types type_ = app.config.get('one_message_window') if type_ in choices: self.one_window_type_combobox.set_active(choices.index(type_)) else: self.one_window_type_combobox.set_active(0) # Show roster on startup show_roster_combobox = self.xml.get_object('show_roster_on_startup') choices = c_config.opt_show_roster_on_startup type_ = app.config.get('show_roster_on_startup') if type_ in choices: show_roster_combobox.set_active(choices.index(type_)) else: show_roster_combobox.set_active(0) # Ignore XHTML st = app.config.get('ignore_incoming_xhtml') self.xml.get_object('xhtml_checkbutton').set_active(st) # use speller if app.is_installed('GSPELL'): st = app.config.get('use_speller') self.xml.get_object('speller_checkbutton').set_active(st) else: self.xml.get_object('speller_checkbutton').set_sensitive(False) # XEP-0184 positive ack st = app.config.get('positive_184_ack') self.xml.get_object('positive_184_ack_checkbutton').set_active(st) st = app.config.get('show_subject_on_join') self.xml.get_object('subject_on_join').set_active(st) # Show avatar in tabs st = app.config.get('show_avatar_in_tabs') self.xml.get_object('show_avatar_in_tabs_checkbutton').set_active(st) ### Style tab ### # Themes theme_combobox = self.xml.get_object('theme_combobox') self.changed_id = theme_combobox.connect( 'changed', self.on_theme_combobox_changed) self.update_theme_list() # iconset iconsets_list = os.listdir( os.path.join(configpaths.get('DATA'), 'iconsets')) if os.path.isdir(configpaths.get('MY_ICONSETS')): iconsets_list += os.listdir(configpaths.get('MY_ICONSETS')) # new model, image in 0, string in 1 model = Gtk.ListStore(Gtk.Image, str) renderer_image = cell_renderer_image.CellRendererImage(0, 0) renderer_text = Gtk.CellRendererText() renderer_text.set_property('xpad', 5) self.iconset_combobox.pack_start(renderer_image, False) self.iconset_combobox.pack_start(renderer_text, True) self.iconset_combobox.add_attribute(renderer_text, 'text', 1) self.iconset_combobox.add_attribute(renderer_image, 'image', 0) self.iconset_combobox.set_model(model) dirlist = [] for dir_ in iconsets_list: if not os.path.isdir(os.path.join(configpaths.get('DATA'), 'iconsets', dir_)) \ and not os.path.isdir(os.path.join(configpaths.get('MY_ICONSETS'), dir_)): continue if dir_ not in ('.svn', 'transports'): dirlist.append(dir_) if not dirlist: dirlist.append(' ') for index, dir_ in enumerate(dirlist): preview = Gtk.Image() files = [] files.append(os.path.join(helpers.get_iconset_path(dir_), '16x16', 'online.png')) files.append(os.path.join(helpers.get_iconset_path(dir_), '16x16', 'online.gif')) for file_ in files: if os.path.exists(file_): preview.set_from_file(file_) model.append([preview, dir_]) if app.config.get('iconset') == dir_: self.iconset_combobox.set_active(index) # Use transports iconsets st = app.config.get('use_transports_iconsets') self.xml.get_object('transports_iconsets_checkbutton').set_active(st) # Dark theme dark_theme_combo = self.xml.get_object('dark_theme_combobox') dark_theme_combo.set_active_id(str(app.config.get('dark_theme'))) # Emoticons emoticons_combobox = self.xml.get_object('emoticons_combobox') emoticon_themes = helpers.get_available_emoticon_themes() for theme in emoticon_themes: emoticons_combobox.append_text(theme) config_theme = app.config.get('emoticons_theme') if config_theme not in emoticon_themes: config_theme = 'font' emoticons_combobox.set_id_column(0) emoticons_combobox.set_active_id(config_theme) self.xml.ascii_emoticons.set_active(app.config.get('ascii_emoticons')) ### Personal Events tab ### # outgoing send chat state notifications st = app.config.get('outgoing_chat_state_notifications') combo = self.xml.get_object('outgoing_chat_states_combobox') if st == 'all': combo.set_active(0) elif st == 'composing_only': combo.set_active(1) else: # disabled combo.set_active(2) # displayed send chat state notifications st = app.config.get('displayed_chat_state_notifications') combo = self.xml.get_object('displayed_chat_states_combobox') if st == 'all': combo.set_active(0) elif st == 'composing_only': combo.set_active(1) else: # disabled combo.set_active(2) ### Notifications tab ### # On new event on_event_combobox = self.xml.get_object('on_event_combobox') if app.config.get('autopopup'): on_event_combobox.set_active(0) elif app.config.get('notify_on_new_message'): on_event_combobox.set_active(1) else: on_event_combobox.set_active(2) # notify on online statuses st = app.config.get('notify_on_signin') self.notify_on_signin_checkbutton.set_active(st) # notify on offline statuses st = app.config.get('notify_on_signout') self.notify_on_signout_checkbutton.set_active(st) # autopopupaway st = app.config.get('autopopupaway') self.auto_popup_away_checkbutton.set_active(st) # autopopup_chat_opened st = app.config.get('autopopup_chat_opened') self.auto_popup_chat_opened_checkbutton.set_active(st) # sounddnd st = app.config.get('sounddnd') self.sound_dnd_checkbutton.set_active(st) # Systray systray_combobox = self.xml.get_object('systray_combobox') if app.config.get('trayicon') == 'never': systray_combobox.set_active(0) elif app.config.get('trayicon') == 'on_event': systray_combobox.set_active(1) else: systray_combobox.set_active(2) # sounds if app.config.get('sounds_on'): self.xml.get_object('play_sounds_checkbutton').set_active(True) else: self.xml.get_object('manage_sounds_button').set_sensitive(False) #### Status tab ### # Autoaway st = app.config.get('autoaway') self.auto_away_checkbutton.set_active(st) # Autoawaytime st = app.config.get('autoawaytime') self.auto_away_time_spinbutton.set_value(st) self.auto_away_time_spinbutton.set_sensitive(app.config.get('autoaway')) # autoaway message st = app.config.get('autoaway_message') self.auto_away_message_entry.set_text(st) self.auto_away_message_entry.set_sensitive(app.config.get('autoaway')) # Autoxa st = app.config.get('autoxa') self.auto_xa_checkbutton.set_active(st) # Autoxatime st = app.config.get('autoxatime') self.auto_xa_time_spinbutton.set_value(st) self.auto_xa_time_spinbutton.set_sensitive(app.config.get('autoxa')) # autoxa message st = app.config.get('autoxa_message') self.auto_xa_message_entry.set_text(st) self.auto_xa_message_entry.set_sensitive(app.config.get('autoxa')) if not idle.Monitor.is_available(): self.xml.get_object('autoaway_table').set_sensitive(False) # ask_status when online / offline st = app.config.get('ask_online_status') self.xml.get_object('prompt_online_status_message_checkbutton').\ set_active(st) st = app.config.get('ask_offline_status') self.xml.get_object('prompt_offline_status_message_checkbutton').\ set_active(st) # Default Status messages self.default_msg_tree = self.xml.get_object('default_msg_treeview') self.fill_default_msg_treeview() # Status messages self.msg_tree = self.xml.get_object('msg_treeview') renderer = Gtk.CellRendererText() renderer.connect('edited', self.on_msg_cell_edited) renderer.set_property('editable', True) col = Gtk.TreeViewColumn('name', renderer, text=0) self.msg_tree.append_column(col) self.fill_msg_treeview() buf = self.xml.get_object('msg_textview').get_buffer() buf.connect('end-user-action', self.on_msg_textview_changed) ### Audio / Video tab ### def create_av_combobox(opt_name, device_dict, config_name=None, key=None): combobox = self.xml.get_object(opt_name + '_combobox') cell = Gtk.CellRendererText() cell.set_property('ellipsize', Pango.EllipsizeMode.END) cell.set_property('ellipsize-set', True) combobox.pack_start(cell, True) combobox.add_attribute(cell, 'text', 0) model = Gtk.ListStore(str, str) combobox.set_model(model) if config_name: config = app.config.get(config_name) else: config = app.config.get(opt_name + '_device') for index, (name, value) in enumerate(sorted(device_dict.items(), key=key)): model.append((name, value)) if config == value: combobox.set_active(index) if HAS_GST and app.is_installed('FARSTREAM'): create_av_combobox('audio_input', AudioInputManager().get_devices()) create_av_combobox('audio_output', AudioOutputManager().get_devices( )) create_av_combobox('video_input', VideoInputManager().get_devices()) create_av_combobox('video_output', VideoOutputManager().get_devices( )) create_av_combobox('video_framerate', {_('Default'): '', '15fps': '15/1', '10fps': '10/1', '5fps': '5/1', '2.5fps': '5/2'}, 'video_framerate', key=lambda x: -1 if \ not x[1] else float(x[0][:-3])) create_av_combobox('video_size', {_('Default'): '', '800x600': '800x600', '640x480': '640x480', '320x240': '320x240'}, 'video_size', key=lambda x: -1 if \ not x[1] else int(x[0][:3])) st = app.config.get('video_see_self') self.xml.get_object('video_see_self_checkbutton').set_active(st) else: for opt_name in ('audio_input', 'audio_output', 'video_input', 'video_output', 'video_framerate', 'video_size'): combobox = self.xml.get_object(opt_name + '_combobox') combobox.set_sensitive(False) # STUN cb = self.xml.get_object('stun_checkbutton') st = app.config.get('use_stun_server') cb.set_active(st) entry = self.xml.get_object('stun_server_entry') entry.set_text(app.config.get('stun_server')) if not st: entry.set_sensitive(False) ### Advanced tab ### # open links with if os.name == 'nt': applications_frame = self.xml.get_object('applications_frame') applications_frame.set_no_show_all(True) applications_frame.hide() else: self.applications_combobox = self.xml.get_object( 'applications_combobox') self.xml.get_object('custom_apps_frame').hide() self.xml.get_object('custom_apps_frame').set_no_show_all(True) if app.config.get('autodetect_browser_mailer'): self.applications_combobox.set_active(0) else: self.applications_combobox.set_active(1) self.xml.get_object('custom_apps_frame').show() self.xml.get_object('custom_browser_entry').set_text( app.config.get('custombrowser')) self.xml.get_object('custom_mail_client_entry').set_text( app.config.get('custommailapp')) self.xml.get_object('custom_file_manager_entry').set_text( app.config.get('custom_file_manager')) # log status changes of contacts st = app.config.get('log_contact_status_changes') self.xml.get_object('log_show_changes_checkbutton').set_active(st) # send os info w = self.xml.get_object('send_os_info_checkbutton') st = self.get_per_account_option('send_os_info') if st == 'mixed': w.set_inconsistent(True) else: w.set_active(st) # send absolute time info w = self.xml.get_object('send_time_info_checkbutton') st = self.get_per_account_option('send_time_info') if st == 'mixed': w.set_inconsistent(True) else: w.set_active(st) # send idle time w = self.xml.get_object('send_idle_time_checkbutton') st = self.get_per_account_option('send_idle_time') if st == 'mixed': w.set_inconsistent(True) else: w.set_active(st) self.update_proxy_list() # Ignore messages from unknown contacts w = self.xml.get_object('ignore_events_from_unknown_contacts_checkbutton') st = self.get_per_account_option('ignore_unknown_contacts') if st == 'mixed': w.set_inconsistent(True) else: w.set_active(st) if sys.platform == 'win32': w = self.xml.get_object('enable_logging') w.set_active(app.get_win_debug_mode()) w.show() self.xml.connect_signals(self) self.connect('key-press-event', self._on_key_press) self.msg_tree.get_model().connect('row-changed', self.on_msg_treemodel_row_changed) self.msg_tree.get_model().connect('row-deleted', self.on_msg_treemodel_row_deleted) self.default_msg_tree.get_model().connect('row-changed', self.on_default_msg_treemodel_row_changed) self.sounds_preferences = None self.theme_preferences = None self.notebook.set_current_page(0) self.show_all() def _on_key_press(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() def get_per_account_option(self, opt): """ Return the value of the option opt if it's the same in all accounts else returns "mixed" """ if not app.connections: # a non existent key return default value return app.config.get_per('accounts', '__default__', opt) val = None for account in app.connections: v = app.config.get_per('accounts', account, opt) if val is None: val = v elif val != v: return 'mixed' return val def on_subject_on_join_toggled(self, widget): app.config.set('show_subject_on_join', widget.get_active()) def on_checkbutton_toggled(self, widget, config_name, change_sensitivity_widgets=None): app.config.set(config_name, widget.get_active()) if change_sensitivity_widgets: for w in change_sensitivity_widgets: w.set_sensitive(widget.get_active()) def on_per_account_checkbutton_toggled(self, widget, config_name, change_sensitivity_widgets=None): for account in app.connections: app.config.set_per('accounts', account, config_name, widget.get_active()) if change_sensitivity_widgets: for w in change_sensitivity_widgets: w.set_sensitive(widget.get_active()) def _get_all_controls(self): for ctrl in app.interface.msg_win_mgr.get_controls(): yield ctrl for account in app.connections: for ctrl in app.interface.minimized_controls[account].values(): yield ctrl def _get_all_muc_controls(self): for ctrl in app.interface.msg_win_mgr.get_controls( message_control.TYPE_GC): yield ctrl for account in app.connections: for ctrl in app.interface.minimized_controls[account].values(): yield ctrl def on_sort_by_show_in_roster_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'sort_by_show_in_roster') app.interface.roster.setup_and_draw_roster() def on_sort_by_show_in_muc_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'sort_by_show_in_muc') # Redraw groupchats for ctrl in self._get_all_muc_controls(): ctrl.draw_roster() def on_show_avatars_in_roster_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'show_avatars_in_roster') app.interface.roster.setup_and_draw_roster() # Redraw groupchats (in an ugly way) for ctrl in self._get_all_muc_controls(): ctrl.draw_roster() def on_show_status_msgs_in_roster_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'show_status_msgs_in_roster') app.interface.roster.setup_and_draw_roster() for ctrl in self._get_all_muc_controls(): ctrl.update_ui() def on_show_pep_in_roster_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'show_mood_in_roster') self.on_checkbutton_toggled(widget, 'show_activity_in_roster') self.on_checkbutton_toggled(widget, 'show_tunes_in_roster') self.on_checkbutton_toggled(widget, 'show_location_in_roster') app.interface.roster.setup_and_draw_roster() def on_emoticons_combobox_changed(self, widget): active = widget.get_active() model = widget.get_model() emot_theme = model[active][0] app.config.set('emoticons_theme', emot_theme) from gajim.gtk.emoji_chooser import emoji_chooser emoji_chooser.load() self.toggle_emoticons() def toggle_emoticons(self): """ Update emoticons state in Opened Chat Windows """ for ctrl in self._get_all_controls(): ctrl.toggle_emoticons() def on_one_window_type_combo_changed(self, widget): active = widget.get_active() config_type = c_config.opt_one_window_types[active] app.config.set('one_message_window', config_type) app.interface.msg_win_mgr.reconfig() def on_show_roster_on_startup_changed(self, widget): active = widget.get_active() config_type = c_config.opt_show_roster_on_startup[active] app.config.set('show_roster_on_startup', config_type) def on_xhtml_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'ignore_incoming_xhtml') helpers.update_optional_features() def apply_speller(self): for ctrl in self._get_all_controls(): if isinstance(ctrl, ChatControlBase): ctrl.set_speller() def on_speller_checkbutton_toggled(self, widget): active = widget.get_active() app.config.set('use_speller', active) if not active: return lang = app.config.get('speller_language') gspell_lang = Gspell.language_lookup(lang) if gspell_lang is None: gspell_lang = Gspell.language_get_default() if gspell_lang is None: AspellDictError(lang) app.config.set('use_speller', False) widget.set_active(False) else: app.config.set('speller_language', gspell_lang.get_code()) self.apply_speller() def on_positive_184_ack_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'positive_184_ack') def on_show_avatar_in_tabs_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'show_avatar_in_tabs') @staticmethod def on_theme_combobox_changed(combobox): theme = combobox.get_active_id() app.config.set('roster_theme', theme) app.css_config.change_theme(theme) # begin repainting themed widgets throughout app.interface.roster.repaint_themed_widgets() app.interface.roster.change_roster_style(None) def update_theme_list(self): theme_combobox = self.xml.get_object('theme_combobox') with theme_combobox.handler_block(self.changed_id): theme_combobox.remove_all() theme_combobox.append('default', 'default') for config_theme in app.css_config.themes: theme_combobox.append(config_theme, config_theme) theme_combobox.set_active_id(app.config.get('roster_theme')) def on_manage_theme_button_clicked(self, widget): window = app.get_app_window(Themes) if window is None: Themes(self) else: window.present() def on_iconset_combobox_changed(self, widget): model = widget.get_model() active = widget.get_active() icon_string = model[active][1] app.config.set('iconset', icon_string) gtkgui_helpers.reload_jabber_state_images() def on_convert_ascii_toggle(self, widget): app.config.set('ascii_emoticons', widget.get_active()) app.interface.make_regexps() def on_transports_iconsets_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'use_transports_iconsets') gtkgui_helpers.reload_jabber_state_images() def on_dark_theme_changed(self, widget): app.css_config.set_dark_theme(int(widget.get_active_id())) def on_outgoing_chat_states_combobox_changed(self, widget): active = widget.get_active() old_value = app.config.get('outgoing_chat_state_notifications') if active == 0: # all app.config.set('outgoing_chat_state_notifications', 'all') elif active == 1: # only composing app.config.set('outgoing_chat_state_notifications', 'composing_only') else: # disabled app.config.set('outgoing_chat_state_notifications', 'disabled') new_value = app.config.get('outgoing_chat_state_notifications') if 'disabled' in (old_value, new_value): # we changed from disabled to sth else or vice versa helpers.update_optional_features() def on_displayed_chat_states_combobox_changed(self, widget): active = widget.get_active() if active == 0: # all app.config.set('displayed_chat_state_notifications', 'all') elif active == 1: # only composing app.config.set('displayed_chat_state_notifications', 'composing_only') else: # disabled app.config.set('displayed_chat_state_notifications', 'disabled') def on_ignore_events_from_unknown_contacts_checkbutton_toggled(self, widget): widget.set_inconsistent(False) self.on_per_account_checkbutton_toggled(widget, 'ignore_unknown_contacts') def on_on_event_combobox_changed(self, widget): active = widget.get_active() if active == 0: app.config.set('autopopup', True) app.config.set('notify_on_new_message', False) elif active == 1: app.config.set('autopopup', False) app.config.set('notify_on_new_message', True) else: app.config.set('autopopup', False) app.config.set('notify_on_new_message', False) def on_notify_on_signin_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'notify_on_signin') def on_notify_on_signout_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'notify_on_signout') def on_auto_popup_away_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'autopopupaway') def on_auto_popup_chat_opened_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'autopopup_chat_opened') def on_sound_dnd_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'sounddnd') def on_systray_combobox_changed(self, widget): active = widget.get_active() if active == 0: app.config.set('trayicon', 'never') app.interface.systray_enabled = False app.interface.systray.hide_icon() elif active == 1: app.config.set('trayicon', 'on_event') app.interface.systray_enabled = True app.interface.systray.show_icon() else: app.config.set('trayicon', 'always') app.interface.systray_enabled = True app.interface.systray.show_icon() def on_play_sounds_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'sounds_on', [self.xml.get_object('manage_sounds_button')]) def on_manage_sounds_button_clicked(self, widget): if self.sounds_preferences is None: self.sounds_preferences = ManageSoundsWindow(self) else: self.sounds_preferences.window.present() def on_auto_away_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'autoaway', [self.auto_away_time_spinbutton, self.auto_away_message_entry]) def on_auto_away_time_spinbutton_value_changed(self, widget): aat = widget.get_value_as_int() app.config.set('autoawaytime', aat) idle.Monitor.set_interval(app.config.get('autoawaytime') * 60, app.config.get('autoxatime') * 60) def on_auto_away_message_entry_changed(self, widget): app.config.set('autoaway_message', widget.get_text()) def on_auto_xa_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'autoxa', [self.auto_xa_time_spinbutton, self.auto_xa_message_entry]) def on_auto_xa_time_spinbutton_value_changed(self, widget): axt = widget.get_value_as_int() app.config.set('autoxatime', axt) idle.Monitor.set_interval(app.config.get('autoawaytime') * 60, app.config.get('autoxatime') * 60) def on_auto_xa_message_entry_changed(self, widget): app.config.set('autoxa_message', widget.get_text()) def on_prompt_online_status_message_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'ask_online_status') def on_prompt_offline_status_message_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'ask_offline_status') def fill_default_msg_treeview(self): model = self.default_msg_tree.get_model() model.clear() status = [] for status_ in app.config.get_per('defaultstatusmsg'): status.append(status_) status.sort() for status_ in status: msg = app.config.get_per('defaultstatusmsg', status_, 'message') msg = helpers.from_one_line(msg) enabled = app.config.get_per('defaultstatusmsg', status_, 'enabled') iter_ = model.append() uf_show = helpers.get_uf_show(status_) model.set(iter_, 0, status_, 1, uf_show, 2, msg, 3, enabled) def on_default_msg_cell_edited(self, cell, row, new_text): model = self.default_msg_tree.get_model() iter_ = model.get_iter_from_string(row) model.set_value(iter_, 2, new_text) def default_msg_toggled_cb(self, cell, path): model = self.default_msg_tree.get_model() model[path][3] = not model[path][3] def on_default_msg_treemodel_row_changed(self, model, path, iter_): status = model[iter_][0] message = model[iter_][2] message = helpers.to_one_line(message) app.config.set_per('defaultstatusmsg', status, 'enabled', model[iter_][3]) app.config.set_per('defaultstatusmsg', status, 'message', message) def save_status_messages(self, model): for msg in app.config.get_per('statusmsg'): app.config.del_per('statusmsg', msg) iter_ = model.get_iter_first() while iter_: val = model[iter_][0] if model[iter_][1]: # we have a preset message if not val: # no title, use message text for title val = model[iter_][1] app.config.add_per('statusmsg', val) msg = helpers.to_one_line(model[iter_][1]) app.config.set_per('statusmsg', val, 'message', msg) i = 2 # store mood / activity for subname in ('activity', 'subactivity', 'activity_text', 'mood', 'mood_text'): val2 = model[iter_][i] if not val2: val2 = '' app.config.set_per('statusmsg', val, subname, val2) i += 1 iter_ = model.iter_next(iter_) def on_msg_treemodel_row_changed(self, model, path, iter_): self.save_status_messages(model) def on_msg_treemodel_row_deleted(self, model, path): self.save_status_messages(model) def on_av_combobox_changed(self, combobox, config_name): model = combobox.get_model() active = combobox.get_active() device = model[active][1] app.config.set(config_name, device) def on_audio_input_combobox_changed(self, widget): self.on_av_combobox_changed(widget, 'audio_input_device') def on_audio_output_combobox_changed(self, widget): self.on_av_combobox_changed(widget, 'audio_output_device') def on_video_input_combobox_changed(self, widget): self.on_av_combobox_changed(widget, 'video_input_device') def on_video_output_combobox_changed(self, widget): self.on_av_combobox_changed(widget, 'video_output_device') def on_video_framerate_combobox_changed(self, widget): self.on_av_combobox_changed(widget, 'video_framerate') def on_video_size_combobox_changed(self, widget): self.on_av_combobox_changed(widget, 'video_size') def on_video_see_self_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'video_see_self') def on_stun_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'use_stun_server', [ self.xml.get_object('stun_server_entry')]) def stun_server_entry_changed(self, widget): app.config.set('stun_server', widget.get_text()) def on_applications_combobox_changed(self, widget): if widget.get_active() == 0: app.config.set('autodetect_browser_mailer', True) self.xml.get_object('custom_apps_frame').hide() elif widget.get_active() == 1: app.config.set('autodetect_browser_mailer', False) self.xml.get_object('custom_apps_frame').show() def on_custom_browser_entry_changed(self, widget): app.config.set('custombrowser', widget.get_text()) def on_custom_mail_client_entry_changed(self, widget): app.config.set('custommailapp', widget.get_text()) def on_custom_file_manager_entry_changed(self, widget): app.config.set('custom_file_manager', widget.get_text()) def on_log_show_changes_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'log_contact_status_changes') def on_send_os_info_checkbutton_toggled(self, widget): widget.set_inconsistent(False) self.on_per_account_checkbutton_toggled(widget, 'send_os_info') def on_send_time_info_checkbutton_toggled(self, widget): widget.set_inconsistent(False) self.on_per_account_checkbutton_toggled(widget, 'send_time_info') def on_send_idle_time_checkbutton_toggled(self, widget): widget.set_inconsistent(False) self.on_per_account_checkbutton_toggled(widget, 'send_idle_time') def fill_msg_treeview(self): self.xml.get_object('delete_msg_button').set_sensitive(False) model = self.msg_tree.get_model() model.clear() preset_status = [] for msg_name in app.config.get_per('statusmsg'): if msg_name.startswith('_last_'): continue preset_status.append(msg_name) preset_status.sort() for msg_name in preset_status: msg_text = app.config.get_per('statusmsg', msg_name, 'message') msg_text = helpers.from_one_line(msg_text) activity = app.config.get_per('statusmsg', msg_name, 'activity') subactivity = app.config.get_per('statusmsg', msg_name, 'subactivity') activity_text = app.config.get_per('statusmsg', msg_name, 'activity_text') mood = app.config.get_per('statusmsg', msg_name, 'mood') mood_text = app.config.get_per('statusmsg', msg_name, 'mood_text') iter_ = model.append() model.set(iter_, 0, msg_name, 1, msg_text, 2, activity, 3, subactivity, 4, activity_text, 5, mood, 6, mood_text) def on_msg_cell_edited(self, cell, row, new_text): model = self.msg_tree.get_model() iter_ = model.get_iter_from_string(row) model.set_value(iter_, 0, new_text) def on_msg_treeview_cursor_changed(self, widget, data=None): sel = self.msg_tree.get_selection() if not sel: return (model, iter_) = sel.get_selected() if not iter_: return self.xml.get_object('delete_msg_button').set_sensitive(True) buf = self.xml.get_object('msg_textview').get_buffer() msg = model[iter_][1] buf.set_text(msg) def on_new_msg_button_clicked(self, widget, data=None): model = self.msg_tree.get_model() iter_ = model.append() model.set( iter_, 0, _('status message title'), 1, _('status message text')) self.msg_tree.set_cursor(model.get_path(iter_)) def on_delete_msg_button_clicked(self, widget, data=None): sel = self.msg_tree.get_selection() if not sel: return (model, iter_) = sel.get_selected() if not iter_: return buf = self.xml.get_object('msg_textview').get_buffer() model.remove(iter_) buf.set_text('') self.xml.get_object('delete_msg_button').set_sensitive(False) def on_msg_textview_changed(self, widget, data=None): sel = self.msg_tree.get_selection() if not sel: return (model, iter_) = sel.get_selected() if not iter_: return buf = self.xml.get_object('msg_textview').get_buffer() first_iter, end_iter = buf.get_bounds() model.set_value(iter_, 1, buf.get_text(first_iter, end_iter, True)) def on_msg_treeview_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Delete: self.on_delete_msg_button_clicked(widget) def on_proxies_combobox_changed(self, widget): active = widget.get_active() proxy = widget.get_model()[active][0] if proxy == _('None'): proxy = '' app.config.set('global_proxy', proxy) def on_manage_proxies_button_clicked(self, widget): if 'manage_proxies' in app.interface.instances: app.interface.instances['manage_proxies'].window.present() else: app.interface.instances['manage_proxies'] = ManageProxiesWindow(self) def update_proxy_list(self): our_proxy = app.config.get('global_proxy') if not our_proxy: our_proxy = _('None') proxy_combobox = self.xml.get_object('proxies_combobox') model = proxy_combobox.get_model() model.clear() proxies = app.config.get_per('proxies') proxies.insert(0, _('None')) for index, proxy in enumerate(proxies): model.append([proxy]) if our_proxy == proxy: proxy_combobox.set_active(index) def on_open_advanced_editor_button_clicked(self, widget, data=None): if 'advanced_config' in app.interface.instances: app.interface.instances['advanced_config'].window.present() else: app.interface.instances['advanced_config'] = AdvancedConfig(self) def on_enable_logging_toggled(self, widget): app.set_win_debug_mode(widget.get_active()) gajim-gajim-1.1.3/gajim/gtk/privacy_list.py000066400000000000000000000567101345766322700206560ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GLib from gi.repository import GObject from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.util import get_builder class PrivacyListWindow: def __init__(self, account, privacy_list_name, action): '''action is 'EDIT' or 'NEW' depending on if we create a new priv list or edit an already existing one''' self.account = account self.privacy_list_name = privacy_list_name # Dicts and Default Values self.active_rule = '' self.global_rules = {} self.list_of_groups = {} self.max_order = 0 # Default Edit Values self.edit_rule_type = 'jid' self.allow_deny = 'allow' # Connect to gtk builder self.xml = get_builder('privacy_list_window.ui') self.window = self.xml.get_object('privacy_list_edit_window') # Add Widgets for widget_to_add in ('title_hbox', 'privacy_lists_title_label', 'list_of_rules_label', 'add_edit_rule_label', 'delete_open_buttons_hbox', 'privacy_list_active_checkbutton', 'privacy_list_default_checkbutton', 'list_of_rules_combobox', 'delete_open_buttons_hbox', 'delete_rule_button', 'open_rule_button', 'edit_allow_radiobutton', 'edit_deny_radiobutton', 'edit_type_jabberid_radiobutton', 'edit_type_jabberid_entry', 'edit_type_group_radiobutton', 'edit_type_group_combobox', 'edit_type_subscription_radiobutton', 'edit_type_subscription_combobox', 'edit_type_select_all_radiobutton', 'edit_queries_send_checkbutton', 'edit_send_messages_checkbutton', 'edit_view_status_checkbutton', 'edit_all_checkbutton', 'edit_order_spinbutton', 'new_rule_button', 'save_rule_button', 'privacy_list_refresh_button', 'privacy_list_close_button', 'edit_send_status_checkbutton', 'add_edit_vbox', 'privacy_list_active_checkbutton', 'privacy_list_default_checkbutton'): self.__dict__[widget_to_add] = self.xml.get_object(widget_to_add) self.privacy_lists_title_label.set_label( _('Privacy List %s') % GLib.markup_escape_text(self.privacy_list_name)) if len(app.connections) > 1: title = _('Privacy List for %s') % self.account else: title = _('Privacy List') self.delete_rule_button.set_sensitive(False) self.open_rule_button.set_sensitive(False) self.privacy_list_active_checkbutton.set_sensitive(False) self.privacy_list_default_checkbutton.set_sensitive(False) self.list_of_rules_combobox.set_sensitive(False) # set jabber id completion jids_list_store = Gtk.ListStore(GObject.TYPE_STRING) for jid in app.contacts.get_jid_list(self.account): jids_list_store.append([jid]) jid_entry_completion = Gtk.EntryCompletion() jid_entry_completion.set_text_column(0) jid_entry_completion.set_model(jids_list_store) jid_entry_completion.set_popup_completion(True) self.edit_type_jabberid_entry.set_completion(jid_entry_completion) if action == 'EDIT': self.refresh_rules() model = self.edit_type_group_combobox.get_model() count = 0 for group in app.groups[self.account]: self.list_of_groups[group] = count count += 1 model.append([group]) self.edit_type_group_combobox.set_active(0) self.window.set_title(title) app.ged.register_event_handler('privacy-list-received', ged.GUI1, self._nec_privacy_list_received) app.ged.register_event_handler('privacy-lists-received', ged.GUI1, self._nec_privacy_lists_received) self.window.show_all() self.add_edit_vbox.hide() self.xml.connect_signals(self) def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def on_privacy_list_edit_window_destroy(self, widget): key_name = 'privacy_list_%s' % self.privacy_list_name if key_name in app.interface.instances[self.account]: del app.interface.instances[self.account][key_name] app.ged.remove_event_handler('privacy-list-received', ged.GUI1, self._nec_privacy_list_received) app.ged.remove_event_handler('privacy-lists-received', ged.GUI1, self._nec_privacy_lists_received) def _nec_privacy_lists_received(self, obj): if obj.conn.name != self.account: return if obj.active_list == self.privacy_list_name: self.privacy_list_active_checkbutton.set_active(True) else: self.privacy_list_active_checkbutton.set_active(False) if obj.default_list == self.privacy_list_name: self.privacy_list_default_checkbutton.set_active(True) else: self.privacy_list_default_checkbutton.set_active(False) def privacy_list_received(self, rules): model = self.list_of_rules_combobox.get_model() model.clear() self.global_rules = {} for rule in rules: if 'type' in rule: text_item = _('Order: %(order)s, action: %(action)s, type: %(type)s' ', value: %(value)s') % {'order': rule['order'], 'action': rule['action'], 'type': rule['type'], 'value': rule['value']} else: text_item = _('Order: %(order)s, action: %(action)s') % \ {'order': rule['order'], 'action': rule['action']} if int(rule['order']) > self.max_order: self.max_order = int(rule['order']) self.global_rules[text_item] = rule model.append([text_item]) if not rules: self.title_hbox.set_sensitive(False) self.list_of_rules_combobox.set_sensitive(False) self.delete_rule_button.set_sensitive(False) self.open_rule_button.set_sensitive(False) self.privacy_list_active_checkbutton.set_sensitive(False) self.privacy_list_default_checkbutton.set_sensitive(False) else: self.list_of_rules_combobox.set_active(0) self.title_hbox.set_sensitive(True) self.list_of_rules_combobox.set_sensitive(True) self.delete_rule_button.set_sensitive(True) self.open_rule_button.set_sensitive(True) self.privacy_list_active_checkbutton.set_sensitive(True) self.privacy_list_default_checkbutton.set_sensitive(True) self.reset_fields() con = app.connections[self.account] con.get_module('PrivacyLists').get_privacy_lists() def _nec_privacy_list_received(self, obj): if obj.conn.name != self.account: return if obj.list_name != self.privacy_list_name: return self.privacy_list_received(obj.rules) def refresh_rules(self): con = app.connections[self.account] con.get_module('PrivacyLists').get_privacy_list(self.privacy_list_name) def on_delete_rule_button_clicked(self, widget): model = self.list_of_rules_combobox.get_model() iter_ = self.list_of_rules_combobox.get_active_iter() _rule = model[iter_][0] tags = [] for rule in self.global_rules: if rule != _rule: tags.append(self.global_rules[rule]) con = app.connections[self.account] con.get_module('PrivacyLists').set_privacy_list( self.privacy_list_name, tags) self.privacy_list_received(tags) self.add_edit_vbox.hide() if not tags: # we removed latest rule if 'privacy_lists' in app.interface.instances[self.account]: win = app.interface.instances[self.account]['privacy_lists'] win.remove_privacy_list_from_combobox(self.privacy_list_name) win.draw_widgets() def on_open_rule_button_clicked(self, widget): self.add_edit_rule_label.set_label(_('Edit a rule')) active_num = self.list_of_rules_combobox.get_active() if active_num == -1: self.active_rule = '' else: model = self.list_of_rules_combobox.get_model() iter_ = self.list_of_rules_combobox.get_active_iter() self.active_rule = model[iter_][0] if self.active_rule != '': rule_info = self.global_rules[self.active_rule] self.edit_order_spinbutton.set_value(int(rule_info['order'])) if 'type' in rule_info: if rule_info['type'] == 'jid': self.edit_type_jabberid_radiobutton.set_active(True) self.edit_type_jabberid_entry.set_text(rule_info['value']) elif rule_info['type'] == 'group': self.edit_type_group_radiobutton.set_active(True) if rule_info['value'] in self.list_of_groups: self.edit_type_group_combobox.set_active( self.list_of_groups[rule_info['value']]) else: self.edit_type_group_combobox.set_active(0) elif rule_info['type'] == 'subscription': self.edit_type_subscription_radiobutton.set_active(True) sub_value = rule_info['value'] if sub_value == 'none': self.edit_type_subscription_combobox.set_active(0) elif sub_value == 'both': self.edit_type_subscription_combobox.set_active(1) elif sub_value == 'from': self.edit_type_subscription_combobox.set_active(2) elif sub_value == 'to': self.edit_type_subscription_combobox.set_active(3) else: self.edit_type_select_all_radiobutton.set_active(True) else: self.edit_type_select_all_radiobutton.set_active(True) self.edit_send_messages_checkbutton.set_active(False) self.edit_queries_send_checkbutton.set_active(False) self.edit_view_status_checkbutton.set_active(False) self.edit_send_status_checkbutton.set_active(False) self.edit_all_checkbutton.set_active(False) if not rule_info['child']: self.edit_all_checkbutton.set_active(True) else: if 'presence-out' in rule_info['child']: self.edit_send_status_checkbutton.set_active(True) if 'presence-in' in rule_info['child']: self.edit_view_status_checkbutton.set_active(True) if 'iq' in rule_info['child']: self.edit_queries_send_checkbutton.set_active(True) if 'message' in rule_info['child']: self.edit_send_messages_checkbutton.set_active(True) if rule_info['action'] == 'allow': self.edit_allow_radiobutton.set_active(True) else: self.edit_deny_radiobutton.set_active(True) self.add_edit_vbox.show() def on_edit_all_checkbutton_toggled(self, widget): if widget.get_active(): self.edit_send_messages_checkbutton.set_active(True) self.edit_queries_send_checkbutton.set_active(True) self.edit_view_status_checkbutton.set_active(True) self.edit_send_status_checkbutton.set_active(True) self.edit_send_messages_checkbutton.set_sensitive(False) self.edit_queries_send_checkbutton.set_sensitive(False) self.edit_view_status_checkbutton.set_sensitive(False) self.edit_send_status_checkbutton.set_sensitive(False) else: self.edit_send_messages_checkbutton.set_active(False) self.edit_queries_send_checkbutton.set_active(False) self.edit_view_status_checkbutton.set_active(False) self.edit_send_status_checkbutton.set_active(False) self.edit_send_messages_checkbutton.set_sensitive(True) self.edit_queries_send_checkbutton.set_sensitive(True) self.edit_view_status_checkbutton.set_sensitive(True) self.edit_send_status_checkbutton.set_sensitive(True) def on_privacy_list_active_checkbutton_toggled(self, widget): name = None if widget.get_active(): name = self.privacy_list_name con = app.connections[self.account] con.get_module('PrivacyLists').set_active_list(name) def on_privacy_list_default_checkbutton_toggled(self, widget): name = None if widget.get_active(): name = self.privacy_list_name con = app.connections[self.account] con.get_module('PrivacyLists').set_default_list(name) def on_new_rule_button_clicked(self, widget): self.reset_fields() self.add_edit_vbox.show() def reset_fields(self): self.edit_type_jabberid_entry.set_text('') self.edit_allow_radiobutton.set_active(True) self.edit_type_jabberid_radiobutton.set_active(True) self.active_rule = '' self.edit_send_messages_checkbutton.set_active(False) self.edit_queries_send_checkbutton.set_active(False) self.edit_view_status_checkbutton.set_active(False) self.edit_send_status_checkbutton.set_active(False) self.edit_all_checkbutton.set_active(False) self.edit_order_spinbutton.set_value(self.max_order + 1) self.edit_type_group_combobox.set_active(0) self.edit_type_subscription_combobox.set_active(0) self.add_edit_rule_label.set_label(_('Add a rule')) def get_current_tags(self): if self.edit_type_jabberid_radiobutton.get_active(): edit_type = 'jid' edit_value = self.edit_type_jabberid_entry.get_text() elif self.edit_type_group_radiobutton.get_active(): edit_type = 'group' model = self.edit_type_group_combobox.get_model() iter_ = self.edit_type_group_combobox.get_active_iter() edit_value = model[iter_][0] elif self.edit_type_subscription_radiobutton.get_active(): edit_type = 'subscription' subs = ['none', 'both', 'from', 'to'] edit_value = subs[self.edit_type_subscription_combobox.get_active()] elif self.edit_type_select_all_radiobutton.get_active(): edit_type = '' edit_value = '' edit_order = str(self.edit_order_spinbutton.get_value_as_int()) if self.edit_allow_radiobutton.get_active(): edit_deny = 'allow' else: edit_deny = 'deny' child = [] if not self.edit_all_checkbutton.get_active(): if self.edit_send_messages_checkbutton.get_active(): child.append('message') if self.edit_queries_send_checkbutton.get_active(): child.append('iq') if self.edit_send_status_checkbutton.get_active(): child.append('presence-out') if self.edit_view_status_checkbutton.get_active(): child.append('presence-in') if edit_type != '': return {'order': edit_order, 'action': edit_deny, 'type': edit_type, 'value': edit_value, 'child': child} return {'order': edit_order, 'action': edit_deny, 'child': child} def on_save_rule_button_clicked(self, widget): tags = [] current_tags = self.get_current_tags() if int(current_tags['order']) > self.max_order: self.max_order = int(current_tags['order']) if self.active_rule == '': tags.append(current_tags) for rule in self.global_rules: if rule != self.active_rule: tags.append(self.global_rules[rule]) else: tags.append(current_tags) con = app.connections[self.account] con.get_module('PrivacyLists').set_privacy_list( self.privacy_list_name, tags) self.refresh_rules() self.add_edit_vbox.hide() if 'privacy_lists' in app.interface.instances[self.account]: win = app.interface.instances[self.account]['privacy_lists'] win.add_privacy_list_to_combobox(self.privacy_list_name) win.draw_widgets() def on_list_of_rules_combobox_changed(self, widget): self.add_edit_vbox.hide() def on_edit_type_radiobutton_changed(self, widget, radiobutton): active_bool = widget.get_active() if active_bool: self.edit_rule_type = radiobutton def on_edit_allow_radiobutton_changed(self, widget, radiobutton): active_bool = widget.get_active() if active_bool: self.allow_deny = radiobutton def on_close_button_clicked(self, widget): self.window.destroy() class PrivacyListsWindow: """ Window that is the main window for Privacy Lists; we can list there the privacy lists and ask to create a new one or edit an already there one """ def __init__(self, account): self.account = account self.privacy_lists_save = [] self.xml = get_builder('privacy_lists_window.ui') self.window = self.xml.get_object('privacy_lists_first_window') for widget_to_add in ( 'list_of_privacy_lists_combobox', 'delete_privacy_list_button', 'open_privacy_list_button', 'new_privacy_list_button', 'new_privacy_list_entry', 'privacy_lists_refresh_button', 'close_privacy_lists_window_button'): self.__dict__[widget_to_add] = self.xml.get_object(widget_to_add) self.draw_privacy_lists_in_combobox([]) self.privacy_lists_refresh() self.enabled = True if len(app.connections) > 1: title = _('Privacy Lists for %s') % self.account else: title = _('Privacy Lists') self.window.set_title(title) app.ged.register_event_handler('privacy-lists-received', ged.GUI1, self._nec_privacy_lists_received) app.ged.register_event_handler('privacy-list-removed', ged.GUI1, self._nec_privacy_lists_removed) self.window.show_all() self.xml.connect_signals(self) def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.window.destroy() def on_privacy_lists_first_window_destroy(self, widget): if 'privacy_lists' in app.interface.instances[self.account]: del app.interface.instances[self.account]['privacy_lists'] app.ged.remove_event_handler('privacy-lists-received', ged.GUI1, self._nec_privacy_lists_received) app.ged.remove_event_handler('privacy-list-removed', ged.GUI1, self._nec_privacy_lists_removed) def remove_privacy_list_from_combobox(self, privacy_list): if privacy_list not in self.privacy_lists_save: return model = self.list_of_privacy_lists_combobox.get_model() for entry in model: if entry[0] == privacy_list: model.remove(entry.iter) self.privacy_lists_save.remove(privacy_list) def add_privacy_list_to_combobox(self, privacy_list): if privacy_list in self.privacy_lists_save: return model = self.list_of_privacy_lists_combobox.get_model() model.append([privacy_list]) self.privacy_lists_save.append(privacy_list) def draw_privacy_lists_in_combobox(self, privacy_lists): self.list_of_privacy_lists_combobox.set_active(-1) self.list_of_privacy_lists_combobox.get_model().clear() self.privacy_lists_save = [] for add_item in privacy_lists: self.add_privacy_list_to_combobox(add_item) self.draw_widgets() def draw_widgets(self): if not self.privacy_lists_save: self.list_of_privacy_lists_combobox.set_sensitive(False) self.open_privacy_list_button.set_sensitive(False) self.delete_privacy_list_button.set_sensitive(False) else: self.list_of_privacy_lists_combobox.set_sensitive(True) self.list_of_privacy_lists_combobox.set_active(0) self.open_privacy_list_button.set_sensitive(True) self.delete_privacy_list_button.set_sensitive(True) def on_close_button_clicked(self, widget): self.window.destroy() def on_delete_privacy_list_button_clicked(self, widget): active_list = self.privacy_lists_save[ self.list_of_privacy_lists_combobox.get_active()] con = app.connections[self.account] con.get_module('PrivacyLists').del_privacy_list(active_list) def privacy_list_removed(self, active_list): self.privacy_lists_save.remove(active_list) self.privacy_lists_received(self.privacy_lists_save) def _nec_privacy_lists_removed(self, obj): if obj.conn.name != self.account: return self.privacy_list_removed(obj.list_name) def privacy_lists_received(self, lists): privacy_lists = [] for privacy_list in lists: privacy_lists.append(privacy_list) self.draw_privacy_lists_in_combobox(privacy_lists) def _nec_privacy_lists_received(self, obj): if obj.conn.name != self.account: return self.privacy_lists_received(obj.lists) def privacy_lists_refresh(self): con = app.connections[self.account] con.get_module('PrivacyLists').get_privacy_lists() def on_new_privacy_list_button_clicked(self, widget): name = self.new_privacy_list_entry.get_text() if not name: ErrorDialog( _('Invalid List Name'), _('You must enter a name to create a privacy list.'), transient_for=self.window) return key_name = 'privacy_list_%s' % name if key_name in app.interface.instances[self.account]: app.interface.instances[self.account][key_name].window.present() else: app.interface.instances[self.account][key_name] = \ PrivacyListWindow(self.account, name, 'NEW') self.new_privacy_list_entry.set_text('') def on_privacy_lists_refresh_button_clicked(self, widget): self.privacy_lists_refresh() def on_open_privacy_list_button_clicked(self, widget): name = self.privacy_lists_save[ self.list_of_privacy_lists_combobox.get_active()] key_name = 'privacy_list_%s' % name if key_name in app.interface.instances[self.account]: app.interface.instances[self.account][key_name].window.present() else: app.interface.instances[self.account][key_name] = \ PrivacyListWindow(self.account, name, 'EDIT') gajim-gajim-1.1.3/gajim/gtk/profile.py000066400000000000000000000351651345766322700176070ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2006-2008 Jean-Marie Traissard # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import base64 import time import logging import hashlib from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ from gajim.common.const import AvatarSize from gajim import gtkgui_helpers from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import InformationDialog from gajim.gtk.util import get_builder from gajim.gtk.filechoosers import AvatarChooserDialog log = logging.getLogger('gajim.profile') class ProfileWindow(Gtk.ApplicationWindow): def __init__(self, account): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_title(_('Profile')) self.connect('destroy', self.on_profile_window_destroy) self.connect('key-press-event', self.on_profile_window_key_press_event) self.xml = get_builder('profile_window.ui') self.add(self.xml.get_object('profile_box')) self.progressbar = self.xml.get_object('progressbar') self.statusbar = self.xml.get_object('statusbar') self.context_id = self.statusbar.get_context_id('profile') self.account = account self.jid = app.get_jid_from_account(account) account_label = app.config.get_per( 'accounts', account, 'account_label') self.set_value('account_label', account_label) self.dialog = None self.avatar_mime_type = None self.avatar_encoded = None self.avatar_sha = None self.message_id = self.statusbar.push(self.context_id, _('Retrieving profile…')) self.update_progressbar_timeout_id = GLib.timeout_add( 100, self.update_progressbar) self.remove_statusbar_timeout_id = None self.xml.connect_signals(self) app.ged.register_event_handler('vcard-published', ged.GUI1, self._nec_vcard_published) app.ged.register_event_handler('vcard-not-published', ged.GUI1, self._nec_vcard_not_published) self.show_all() self.xml.get_object('ok_button').grab_focus() app.connections[account].get_module('VCardTemp').request_vcard( self._nec_vcard_received, self.jid) def on_information_notebook_switch_page(self, widget, page, page_num): GLib.idle_add(self.xml.get_object('ok_button').grab_focus) def update_progressbar(self): self.progressbar.pulse() return True def remove_statusbar(self, message_id): self.statusbar.remove(self.context_id, message_id) self.remove_statusbar_timeout_id = None def on_profile_window_destroy(self, widget): if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) if self.remove_statusbar_timeout_id is not None: GLib.source_remove(self.remove_statusbar_timeout_id) app.ged.remove_event_handler( 'vcard-published', ged.GUI1, self._nec_vcard_published) app.ged.remove_event_handler( 'vcard-not-published', ged.GUI1, self._nec_vcard_not_published) if self.dialog: # Image chooser dialog self.dialog.destroy() def on_profile_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() def _clear_photo(self, widget): # empty the image button = self.xml.get_object('PHOTO_button') image = self.xml.get_object('PHOTO_image') image.set_from_pixbuf(None) button.hide() text_button = self.xml.get_object('NOPHOTO_button') text_button.show() self.avatar_encoded = None self.avatar_sha = None self.avatar_mime_type = None def on_set_avatar_button_clicked(self, widget): def on_ok(path_to_file): sha = app.interface.save_avatar(path_to_file, publish=True) if sha is None: ErrorDialog( _('Could not load image'), transient_for=self) return scale = self.get_scale_factor() surface = app.interface.get_avatar(sha, AvatarSize.VCARD, scale) button = self.xml.get_object('PHOTO_button') image = self.xml.get_object('PHOTO_image') image.set_from_surface(surface) button.show() text_button = self.xml.get_object('NOPHOTO_button') text_button.hide() self.avatar_sha = sha publish = app.interface.get_avatar(sha, publish=True) self.avatar_encoded = base64.b64encode(publish).decode('utf-8') self.avatar_mime_type = 'image/png' AvatarChooserDialog(on_ok, transient_for=self) def on_PHOTO_button_press_event(self, widget, event): """ If right-clicked, show popup """ if event.button == 3: # right click menu = Gtk.Menu() nick = app.config.get_per('accounts', self.account, 'name') if self.avatar_sha is None: return menuitem = Gtk.MenuItem.new_with_mnemonic(_('Save _As')) menuitem.connect( 'activate', gtkgui_helpers.on_avatar_save_as_menuitem_activate, self.avatar_sha, nick) menu.append(menuitem) menu.connect('selection-done', lambda w: w.destroy()) # show the menu menu.show_all() menu.attach_to_widget(widget, None) menu.popup(None, None, None, None, event.button, event.time) elif event.button == 1: # left click self.on_set_avatar_button_clicked(widget) def on_BDAY_entry_focus_out_event(self, widget, event): txt = widget.get_text() if not txt: return try: time.strptime(txt, '%Y-%m-%d') except ValueError: if not widget.is_focus(): pritext = _('Wrong date format') ErrorDialog( pritext, _('Format of the date must be YYYY-MM-DD'), transient_for=self) GLib.idle_add(widget.grab_focus) return True def set_value(self, entry_name, value): try: widget = self.xml.get_object(entry_name) val = widget.get_text() if val: value = val + ' / ' + value widget.set_text(value) except AttributeError: pass def set_values(self, vcard_): button = self.xml.get_object('PHOTO_button') image = self.xml.get_object('PHOTO_image') text_button = self.xml.get_object('NOPHOTO_button') if 'PHOTO' not in vcard_: # set default image image.set_from_pixbuf(None) button.hide() text_button.show() for i in vcard_.keys(): if i == 'PHOTO': photo_encoded = vcard_[i]['BINVAL'] if photo_encoded == '': continue self.avatar_encoded = photo_encoded photo_decoded = base64.b64decode(photo_encoded.encode('utf-8')) self.avatar_sha = hashlib.sha1(photo_decoded).hexdigest() if 'TYPE' in vcard_[i]: self.avatar_mime_type = vcard_[i]['TYPE'] scale = self.get_scale_factor() surface = app.interface.get_avatar( self.avatar_sha, AvatarSize.VCARD, scale) if surface is None: pixbuf = gtkgui_helpers.scale_pixbuf_from_data( photo_decoded, AvatarSize.VCARD) surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale) image.set_from_surface(surface) button.show() text_button.hide() continue if i in ('ADR', 'TEL', 'EMAIL'): for entry in vcard_[i]: add_on = '_HOME' if 'WORK' in entry: add_on = '_WORK' for j in entry.keys(): self.set_value(i + add_on + '_' + j + '_entry', entry[j]) if isinstance(vcard_[i], dict): for j in vcard_[i].keys(): self.set_value(i + '_' + j + '_entry', vcard_[i][j]) else: if i == 'DESC': self.xml.get_object('DESC_textview').get_buffer().set_text( vcard_[i], len(vcard_[i].encode('utf-8'))) else: self.set_value(i + '_entry', vcard_[i]) if self.update_progressbar_timeout_id is not None: if self.message_id: self.statusbar.remove(self.context_id, self.message_id) self.message_id = self.statusbar.push( self.context_id, _('Information received')) self.remove_statusbar_timeout_id = GLib.timeout_add_seconds( 3, self.remove_statusbar, self.message_id) GLib.source_remove(self.update_progressbar_timeout_id) self.progressbar.hide() self.progressbar.set_fraction(0) self.update_progressbar_timeout_id = None def _nec_vcard_received(self, jid, resource, room, vcard_, *args): self.set_values(vcard_) def add_to_vcard(self, vcard_, entry, txt): """ Add an information to the vCard dictionary """ entries = entry.split('_') loc = vcard_ if len(entries) == 3: # We need to use lists if entries[0] not in loc: loc[entries[0]] = [] for e in loc[entries[0]]: if entries[1] in e: e[entries[2]] = txt break else: loc[entries[0]].append({entries[1]: '', entries[2]: txt}) return vcard_ while len(entries) > 1: if entries[0] not in loc: loc[entries[0]] = {} loc = loc[entries[0]] del entries[0] loc[entries[0]] = txt return vcard_ def make_vcard(self): """ Make the vCard dictionary """ entries = [ 'FN', 'NICKNAME', 'BDAY', 'EMAIL_HOME_USERID', 'JABBERID', 'URL', 'TEL_HOME_NUMBER', 'N_FAMILY', 'N_GIVEN', 'N_MIDDLE', 'N_PREFIX', 'N_SUFFIX', 'ADR_HOME_STREET', 'ADR_HOME_EXTADR', 'ADR_HOME_LOCALITY', 'ADR_HOME_REGION', 'ADR_HOME_PCODE', 'ADR_HOME_CTRY', 'ORG_ORGNAME', 'ORG_ORGUNIT', 'TITLE', 'ROLE', 'TEL_WORK_NUMBER', 'EMAIL_WORK_USERID', 'ADR_WORK_STREET', 'ADR_WORK_EXTADR', 'ADR_WORK_LOCALITY', 'ADR_WORK_REGION', 'ADR_WORK_PCODE', 'ADR_WORK_CTRY'] vcard_ = {} for e in entries: txt = self.xml.get_object(e + '_entry').get_text() if txt != '': vcard_ = self.add_to_vcard(vcard_, e, txt) # DESC textview buff = self.xml.get_object('DESC_textview').get_buffer() start_iter = buff.get_start_iter() end_iter = buff.get_end_iter() txt = buff.get_text(start_iter, end_iter, False) if txt != '': vcard_['DESC'] = txt # Avatar if self.avatar_encoded: vcard_['PHOTO'] = {'BINVAL': self.avatar_encoded} if self.avatar_mime_type: vcard_['PHOTO']['TYPE'] = self.avatar_mime_type return vcard_, self.avatar_sha def on_ok_button_clicked(self, widget): if self.update_progressbar_timeout_id: # Operation in progress return if app.connections[self.account].connected < 2: ErrorDialog( _('You are not connected to the server'), _('Without a connection, you can not publish your contact ' 'information.'), transient_for=self) return vcard_, sha = self.make_vcard() nick = vcard_.get('NICKNAME') or None app.connections[self.account].get_module('UserNickname').send(nick) if not nick: nick = app.config.get_per('accounts', self.account, 'name') app.nicks[self.account] = nick app.connections[self.account].get_module('VCardTemp').send_vcard( vcard_, sha) self.message_id = self.statusbar.push( self.context_id, _('Sending profile…')) self.progressbar.show() self.update_progressbar_timeout_id = GLib.timeout_add( 100, self.update_progressbar) def _nec_vcard_published(self, obj): if obj.conn.name != self.account: return if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) self.update_progressbar_timeout_id = None self.destroy() def _nec_vcard_not_published(self, obj): if obj.conn.name != self.account: return if self.message_id: self.statusbar.remove(self.context_id, self.message_id) self.message_id = self.statusbar.push( self.context_id, _('Information NOT published')) self.remove_statusbar_timeout_id = GLib.timeout_add_seconds( 3, self.remove_statusbar, self.message_id) if self.update_progressbar_timeout_id is not None: GLib.source_remove(self.update_progressbar_timeout_id) self.progressbar.set_fraction(0) self.update_progressbar_timeout_id = None InformationDialog( _('vCard publication failed'), _('There was an error while publishing your personal information, ' 'try again later.'), transient_for=self) def on_cancel_button_clicked(self, widget): self.destroy() gajim-gajim-1.1.3/gajim/gtk/server_info.py000066400000000000000000000241561345766322700204660ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging from collections import namedtuple from datetime import timedelta import nbxmpp from gi.repository import Gtk from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ log = logging.getLogger('gajim.gtk.serverinfo') class ServerInfoDialog(Gtk.Dialog): def __init__(self, account): flags = Gtk.DialogFlags.DESTROY_WITH_PARENT super().__init__(_('Server Info'), None, flags) self.account = account self.set_transient_for(app.interface.roster.window) self.set_resizable(False) grid = Gtk.Grid() grid.set_name('ServerInfoGrid') grid.set_row_spacing(10) grid.set_hexpand(True) self.info_listbox = Gtk.ListBox() self.info_listbox.set_selection_mode(Gtk.SelectionMode.NONE) self.info_listbox.set_header_func(self.header_func, 'Information') grid.attach(self.info_listbox, 0, 0, 1, 1) self.feature_listbox = Gtk.ListBox() self.feature_listbox.set_selection_mode(Gtk.SelectionMode.NONE) self.feature_listbox.set_header_func(self.header_func, 'Features') grid.attach(self.feature_listbox, 0, 1, 1, 1) box = self.get_content_area() box.pack_start(grid, True, True, 0) box.set_property('margin', 12) box.set_spacing(18) self.connect('response', self.on_response) self.connect('destroy', self.on_destroy) app.ged.register_event_handler('version-result-received', ged.CORE, self._nec_version_result_received) app.ged.register_event_handler('server-disco-received', ged.GUI1, self._server_disco_received) self.version = '' self.uptime = '' self.hostname = app.get_hostname_from_account(account) con = app.connections[account] con.get_module('SoftwareVersion').request_os_info(self.hostname, None) self.request_last_activity() for feature in self.get_features(): self.add_feature(feature) for info in self.get_infos(): self.add_info(info) self.show_all() @staticmethod def header_func(row, before, user_data): if before: row.set_header(None) else: label = Gtk.Label(label=user_data) label.set_halign(Gtk.Align.START) row.set_header(label) @staticmethod def update(func, listbox): for index, item in enumerate(func()): row = listbox.get_row_at_index(index) row.get_child().update(item) row.set_tooltip_text(row.get_child().tooltip) def request_last_activity(self): if not app.account_is_connected(self.account): return con = app.connections[self.account] iq = nbxmpp.Iq(to=self.hostname, typ='get', queryNS=nbxmpp.NS_LAST) con.connection.SendAndCallForResponse(iq, self._on_last_activity) def _on_last_activity(self, stanza): if 'server_info' not in app.interface.instances[self.account]: # Window got closed in the meantime return if not nbxmpp.isResultNode(stanza): log.warning('Received malformed result: %s', stanza) return if stanza.getQueryNS() != nbxmpp.NS_LAST: log.warning('Wrong namespace on result: %s', stanza) return try: seconds = int(stanza.getQuery().getAttr('seconds')) except (ValueError, TypeError, AttributeError): log.exception('Received malformed last activity result') else: delta = timedelta(seconds=seconds) hours = 0 if seconds >= 3600: hours = delta.seconds // 3600 self.uptime = _('%(days)s days, %(hours)s hours') % { 'days': delta.days, 'hours': hours} self.update(self.get_infos, self.info_listbox) def _nec_version_result_received(self, obj): if obj.jid != self.hostname: return self.version = obj.client_info or _('Unknown') self.update(self.get_infos, self.info_listbox) def _server_disco_received(self, obj): self.update(self.get_features, self.feature_listbox) def add_feature(self, feature): item = FeatureItem(feature) self.feature_listbox.add(item) item.get_parent().set_tooltip_text(item.tooltip) def get_features(self): con = app.connections[self.account] Feature = namedtuple('Feature', ['name', 'available', 'tooltip', 'enabled']) carbons_enabled = app.config.get_per('accounts', self.account, 'enable_message_carbons') mam_enabled = app.config.get_per('accounts', self.account, 'sync_logs_with_server') return [ Feature('XEP-0016: Privacy Lists', con.get_module('PrivacyLists').supported, '', None), Feature('XEP-0045: Multi-User Chat', con.muc_jid, '', None), Feature('XEP-0054: vcard-temp', con.get_module('VCardTemp').supported, '', None), Feature('XEP-0163: Personal Eventing Protocol', con.get_module('PEP').supported, '', None), Feature('XEP-0163: #publish-options', con.get_module('PubSub').publish_options, '', None), Feature('XEP-0191: Blocking Command', con.get_module('Blocking').supported, nbxmpp.NS_BLOCKING, None), Feature('XEP-0198: Stream Management', con.sm.enabled, nbxmpp.NS_STREAM_MGMT, None), Feature('XEP-0258: Security Labels in XMPP', con.get_module('SecLabels').supported, nbxmpp.NS_SECLABEL, None), Feature('XEP-0280: Message Carbons', con.get_module('Carbons').supported, nbxmpp.NS_CARBONS, carbons_enabled), Feature('XEP-0313: Message Archive Management', con.get_module('MAM').archiving_namespace, con.get_module('MAM').archiving_namespace, mam_enabled), Feature('XEP-0363: HTTP File Upload', con.get_module('HTTPUpload').available, con.get_module('HTTPUpload').httpupload_namespace, None), Feature('XEP-0398: Avatar Conversion', con.avatar_conversion, '', None) ] def add_info(self, info): self.info_listbox.add(ServerInfoItem(info)) def get_infos(self): Info = namedtuple('Info', ['name', 'value', 'tooltip']) return [ Info(_('Hostname'), self.hostname, None), Info(_('Server Software'), self.version, None), Info(_('Server Uptime'), self.uptime, None)] def on_response(self, dialog, response): if response == Gtk.ResponseType.OK: self.destroy() def on_destroy(self, *args): del app.interface.instances[self.account]['server_info'] app.ged.remove_event_handler('version-result-received', ged.CORE, self._nec_version_result_received) app.ged.remove_event_handler('server-disco-received', ged.GUI1, self._server_disco_received) class FeatureItem(Gtk.Grid): def __init__(self, feature): super().__init__() self.tooltip = feature.tooltip self.set_column_spacing(6) self.icon = Gtk.Image() self.feature_label = Gtk.Label(label=feature.name) self.set_feature(feature.available, feature.enabled) self.add(self.icon) self.add(self.feature_label) def set_feature(self, available, enabled): self.icon.get_style_context().remove_class('error-color') self.icon.get_style_context().remove_class('warning-color') self.icon.get_style_context().remove_class('success-color') if not available: self.icon.set_from_icon_name('window-close-symbolic', Gtk.IconSize.MENU) self.icon.get_style_context().add_class('error-color') elif enabled is False: self.icon.set_from_icon_name('dialog-warning-symbolic', Gtk.IconSize.MENU) self.tooltip += _('\nDisabled in config') self.icon.get_style_context().add_class('warning-color') else: self.icon.set_from_icon_name('emblem-ok-symbolic', Gtk.IconSize.MENU) self.icon.get_style_context().add_class('success-color') def update(self, feature): self.tooltip = feature.tooltip self.set_feature(feature.available, feature.enabled) class ServerInfoItem(Gtk.Grid): def __init__(self, info): super().__init__() self.tooltip = info.tooltip self.set_hexpand(True) self.insert_column(0) self.set_column_homogeneous(True) self.info = Gtk.Label(label=info.name) self.info.set_halign(Gtk.Align.START) self.info.set_hexpand(True) self.value = Gtk.Label(label=info.value) self.value.set_halign(Gtk.Align.START) self.value.set_hexpand(True) self.value.set_selectable(True) self.add(self.info) self.add(self.value) def update(self, info): self.value.set_text(info.value) gajim-gajim-1.1.3/gajim/gtk/service_registration.py000066400000000000000000000160271345766322700223750ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import logging from enum import IntEnum from gi.repository import Gtk from gajim.common import app from gajim.common.modules import dataforms from gajim.common.i18n import _ from gajim.gtk.dataform import DataFormWidget log = logging.getLogger('gajim.gtk.registration') class Page(IntEnum): REQUEST = 0 FORM = 1 SENDING = 2 SUCCESS = 3 ERROR = 4 class ServiceRegistration(Gtk.Assistant): def __init__(self, account, agent): Gtk.Assistant.__init__(self) self._con = app.connections[account] self._agent = agent self._account = account self._data_form_widget = None self._is_form = None self.set_application(app.app) self.set_resizable(True) self.set_position(Gtk.WindowPosition.CENTER) self.set_default_size(600, 400) self.get_style_context().add_class('dialog-margin') self._add_page(RequestPage()) self._add_page(FormPage()) self._add_page(SendingPage()) self._add_page(SuccessfulPage()) self._add_page(ErrorPage()) self.connect('prepare', self._on_page_change) self.connect('cancel', self._on_cancel) self.connect('close', self._on_cancel) self._remove_sidebar() self.show_all() def _add_page(self, page): self.append_page(page) self.set_page_type(page, page.type_) self.set_page_title(page, page.title) self.set_page_complete(page, page.complete) def _remove_sidebar(self): main_box = self.get_children()[0] sidebar = main_box.get_children()[0] main_box.remove(sidebar) def _build_dataform(self, form, is_form): if not is_form: from gajim import config return config.FakeDataForm(form) dataform = dataforms.extend_form(node=form) return DataFormWidget(dataform) def _on_page_change(self, assistant, page): if self.get_current_page() == Page.REQUEST: self._con.get_module('Register').get_register_form( self._agent, self._on_get_success, self._on_error) elif self.get_current_page() == Page.SENDING: self._register() self.commit() def _on_get_success(self, form, is_form): log.info('Show Form page') self._is_form = is_form self._data_form_widget = self._build_dataform(form, is_form) self.get_nth_page(Page.FORM).set_form(self._data_form_widget) self.set_current_page(Page.FORM) def _on_error(self, error_text, form=None, is_form=False): if form is not None: log.info('Show Form page') self._is_form = is_form self._data_form_widget = self._build_dataform(form, is_form) self.get_nth_page(Page.FORM).set_form(self._data_form_widget, error_text=error_text) self.set_current_page(Page.FORM) else: log.info('Show Error page') self.get_nth_page(Page.ERROR).set_text(error_text) self.set_current_page(Page.ERROR) def _on_cancel(self, widget): self.destroy() def _register(self): log.info('Show Sending page') if self._is_form: form = self._data_form_widget.get_submit_form() else: form = self._data_form_widget.get_infos() if 'instructions' in form: del form['instructions'] if 'registered' in form: del form['registered'] self._con.get_module('Register').register_agent( self._agent, form, self._is_form, self._on_register_success, self._on_error) def _on_register_success(self): log.info('Show Success page') self.set_current_page(Page.SUCCESS) class RequestPage(Gtk.Box): type_ = Gtk.AssistantPageType.INTRO title = _('Register') complete = False def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(18) spinner = Gtk.Spinner() self.pack_start(spinner, True, True, 0) spinner.start() class SendingPage(RequestPage): type_ = Gtk.AssistantPageType.PROGRESS title = _('Register') complete = False class FormPage(Gtk.Box): type_ = Gtk.AssistantPageType.INTRO title = _('Register') complete = True def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self._form = None self._label = Gtk.Label() self._label.set_no_show_all(True) self._label.get_style_context().add_class('error-color') self.pack_end(self._label, False, False, 0) def set_form(self, form, error_text=None): if self._form is not None: self.remove(self._form) self._form.destroy() self._label.hide() self._form = form if error_text is not None: self._label.set_text(error_text) self._label.show() self.pack_start(form, True, True, 0) self._form.show_all() class SuccessfulPage(Gtk.Box): type_ = Gtk.AssistantPageType.SUMMARY title = _('Registration successful') complete = True def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(12) self.set_homogeneous(True) icon = Gtk.Image.new_from_icon_name('object-select-symbolic', Gtk.IconSize.DIALOG) icon.get_style_context().add_class('success-color') icon.set_valign(Gtk.Align.END) label = Gtk.Label(label=_('Registration successful')) label.get_style_context().add_class('bold16') label.set_valign(Gtk.Align.START) self.add(icon) self.add(label) class ErrorPage(Gtk.Box): type_ = Gtk.AssistantPageType.SUMMARY title = _('Registration failed') complete = True def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(12) self.set_homogeneous(True) icon = Gtk.Image.new_from_icon_name('dialog-error-symbolic', Gtk.IconSize.DIALOG) icon.get_style_context().add_class('error-color') icon.set_valign(Gtk.Align.END) self._label = Gtk.Label() self._label.get_style_context().add_class('bold16') self._label.set_valign(Gtk.Align.START) self.add(icon) self.add(self._label) def set_text(self, text): self._label.set_text(text) gajim-gajim-1.1.3/gajim/gtk/single_message.py000066400000000000000000000331151345766322700211250ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import List # pylint: disable=unused-import from gi.repository import Gdk from gi.repository import GLib from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.modules import dataforms from gajim.common.connection_handlers_events import MessageOutgoingEvent from gajim.dataforms_widget import DataFormWidget from gajim.conversation_textview import ConversationTextview from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import AspellDictError from gajim.gtk.util import get_builder from gajim.gtk.util import get_iconset_name_for from gajim.gtk.util import get_completion_liststore from gajim.gtk.util import move_window from gajim.gtk.util import resize_window if app.is_installed('GSPELL'): from gi.repository import Gspell class SingleMessageWindow: """ SingleMessageWindow can send or show a received singled message depending on action argument which can be 'send' or 'receive' """ # Keep a reference on windows so garbage collector don't restroy them instances = [] # type: List[SingleMessageWindow] def __init__(self, account, to='', action='', from_whom='', subject='', message='', resource='', session=None, form_node=None): self.instances.append(self) self.account = account self.action = action self.subject = subject self.message = message self.to = to self.from_whom = from_whom self.resource = resource self.session = session self.xml = get_builder('single_message_window.ui') self.window = self.xml.get_object('single_message_window') self.count_chars_label = self.xml.get_object('count_chars_label') self.from_label = self.xml.get_object('from_label') self.from_entry = self.xml.get_object('from_entry') self.to_label = self.xml.get_object('to_label') self.to_entry = self.xml.get_object('to_entry') self.subject_entry = self.xml.get_object('subject_entry') self.message_scrolledwindow = self.xml.get_object( 'message_scrolledwindow') self.message_textview = self.xml.get_object('message_textview') self.message_tv_buffer = self.message_textview.get_buffer() self.conversation_scrolledwindow = self.xml.get_object( 'conversation_scrolledwindow') self.conversation_textview = ConversationTextview( account, used_in_history_window=True) self.conversation_textview.tv.show() self.conversation_tv_buffer = self.conversation_textview.tv.get_buffer() self.xml.get_object('conversation_scrolledwindow').add( self.conversation_textview.tv) self.form_widget = None parent_box = self.xml.get_object('conversation_scrolledwindow').\ get_parent() if form_node: dataform = dataforms.extend_form(node=form_node) dataform.type_ = 'submit' self.form_widget = DataFormWidget(dataform) self.form_widget.show_all() parent_box.add(self.form_widget) parent_box.child_set_property(self.form_widget, 'position', parent_box.child_get_property(self.xml.get_object( 'conversation_scrolledwindow'), 'position')) self.action = 'form' self.send_button = self.xml.get_object('send_button') self.reply_button = self.xml.get_object('reply_button') self.send_and_close_button = self.xml.get_object('send_and_close_button') self.cancel_button = self.xml.get_object('cancel_button') self.close_button = self.xml.get_object('close_button') self.message_tv_buffer.connect('changed', self.update_char_counter) if isinstance(to, list): jid = ', '.join([i[0].get_full_jid() for i in to]) self.to_entry.set_text(jid) self.to_entry.set_sensitive(False) else: self.to_entry.set_text(to) if app.config.get('use_speller') and app.is_installed('GSPELL') and action == 'send': lang = app.config.get('speller_language') gspell_lang = Gspell.language_lookup(lang) if gspell_lang is None: AspellDictError(lang) else: spell_buffer = Gspell.TextBuffer.get_from_gtk_text_buffer( self.message_textview.get_buffer()) spell_buffer.set_spell_checker(Gspell.Checker.new(gspell_lang)) spell_view = Gspell.TextView.get_from_gtk_text_view( self.message_textview) spell_view.set_inline_spell_checking(True) spell_view.set_enable_language_menu(True) self.prepare_widgets_for(self.action) # set_text(None) raises TypeError exception if self.subject is None: self.subject = '' self.subject_entry.set_text(self.subject) if to == '': liststore = get_completion_liststore(self.to_entry) self.completion_dict = helpers.get_contact_dict_for_account(account) keys = sorted(self.completion_dict.keys()) for jid in keys: contact = self.completion_dict[jid] status_icon = get_iconset_name_for(contact.show) liststore.append((status_icon, jid)) else: self.completion_dict = {} self.xml.connect_signals(self) # get window position and size from config resize_window(self.window, app.config.get('single-msg-width'), app.config.get('single-msg-height')) move_window(self.window, app.config.get('single-msg-x-position'), app.config.get('single-msg-y-position')) self.window.show_all() def on_single_message_window_destroy(self, widget): self.instances.remove(self) c = app.contacts.get_contact_with_highest_priority(self.account, self.from_whom) if not c: # Groupchat is maybe already destroyed return if c.is_groupchat() and self.from_whom not in \ app.interface.minimized_controls[self.account] and self.action == \ 'receive' and app.events.get_nb_roster_events(self.account, self.from_whom, types=['chat', 'normal']) == 0: app.interface.roster.remove_groupchat(self.from_whom, self.account) def set_cursor_to_end(self): end_iter = self.message_tv_buffer.get_end_iter() self.message_tv_buffer.place_cursor(end_iter) def save_pos(self): # save the window size and position x, y = self.window.get_position() app.config.set('single-msg-x-position', x) app.config.set('single-msg-y-position', y) width, height = self.window.get_size() app.config.set('single-msg-width', width) app.config.set('single-msg-height', height) def on_single_message_window_delete_event(self, window, ev): self.save_pos() def prepare_widgets_for(self, action): if len(app.connections) > 1: if action == 'send': title = _('Single Message using account %s') % self.account else: title = _('Single Message in account %s') % self.account else: title = _('Single Message') if action == 'send': # prepare UI for Sending title = _('Send %s') % title self.send_button.show() self.send_and_close_button.show() self.to_label.show() self.to_entry.show() self.reply_button.hide() self.from_label.hide() self.from_entry.hide() self.conversation_scrolledwindow.hide() self.message_scrolledwindow.show() if self.message: # we come from a reply? self.message_textview.grab_focus() self.cancel_button.hide() self.close_button.show() self.message_tv_buffer.set_text(self.message) GLib.idle_add(self.set_cursor_to_end) else: # we write a new message (not from reply) self.close_button.hide() if self.to: # do we already have jid? self.subject_entry.grab_focus() elif action == 'receive': # prepare UI for Receiving title = _('Received %s') % title self.reply_button.show() self.from_label.show() self.from_entry.show() self.send_button.hide() self.send_and_close_button.hide() self.to_label.hide() self.to_entry.hide() self.conversation_scrolledwindow.show() self.message_scrolledwindow.hide() if self.message: self.conversation_textview.print_real_text(self.message) fjid = self.from_whom if self.resource: fjid += '/' + self.resource # Full jid of sender (with resource) self.from_entry.set_text(fjid) self.from_entry.set_property('editable', False) self.subject_entry.set_property('editable', False) self.reply_button.grab_focus() self.cancel_button.hide() self.close_button.show() elif action == 'form': # prepare UI for Receiving title = _('Form %s') % title self.send_button.show() self.send_and_close_button.show() self.to_label.show() self.to_entry.show() self.reply_button.hide() self.from_label.hide() self.from_entry.hide() self.conversation_scrolledwindow.hide() self.message_scrolledwindow.hide() self.window.set_title(title) def on_cancel_button_clicked(self, widget): self.save_pos() self.window.destroy() def on_close_button_clicked(self, widget): self.save_pos() self.window.destroy() def update_char_counter(self, widget): characters_no = self.message_tv_buffer.get_char_count() self.count_chars_label.set_text(str(characters_no)) def send_single_message(self): if app.connections[self.account].connected <= 1: # if offline or connecting ErrorDialog(_('Connection not available'), _('Please make sure you are connected with "%s".') % self.account) return True if isinstance(self.to, list): sender_list = [] for i in self.to: if i[0].resource: sender_list.append(i[0].jid + '/' + i[0].resource) else: sender_list.append(i[0].jid) else: sender_list = [j.strip() for j in self.to_entry.get_text().split( ',')] subject = self.subject_entry.get_text() begin, end = self.message_tv_buffer.get_bounds() message = self.message_tv_buffer.get_text(begin, end, True) if self.form_widget: form_node = self.form_widget.data_form else: form_node = None recipient_list = [] for to_whom_jid in sender_list: if to_whom_jid in self.completion_dict: to_whom_jid = self.completion_dict[to_whom_jid].jid try: to_whom_jid = helpers.parse_jid(to_whom_jid) except helpers.InvalidFormat: ErrorDialog(_('Invalid JID'), _('It is not possible to send a message to %s, this JID is not ' 'valid.') % to_whom_jid) return True if '/announce/' in to_whom_jid: app.connections[self.account].send_motd(to_whom_jid, subject, message) continue recipient_list.append(to_whom_jid) app.nec.push_outgoing_event(MessageOutgoingEvent(None, account=self.account, jid=recipient_list, message=message, type_='normal', subject=subject, form_node=form_node)) self.subject_entry.set_text('') # we sent ok, clear the subject self.message_tv_buffer.set_text('') # we sent ok, clear the textview def on_send_button_clicked(self, widget): self.send_single_message() def on_reply_button_clicked(self, widget): # we create a new blank window to send and we preset RE: and to jid self.subject = _('RE: %s') % self.subject self.message = _('%s wrote:\n') % self.from_whom + self.message # add > at the begining of each line self.message = self.message.replace('\n', '\n> ') + '\n\n' self.window.destroy() SingleMessageWindow(self.account, to=self.from_whom, action='send', from_whom=self.from_whom, subject=self.subject, message=self.message, session=self.session) def on_send_and_close_button_clicked(self, widget): if self.send_single_message(): return self.save_pos() self.window.destroy() def on_single_message_window_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: # ESCAPE self.save_pos() self.window.destroy() gajim-gajim-1.1.3/gajim/gtk/start_chat.py000066400000000000000000000302771345766322700203020ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import locale from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GLib from gi.repository import Pango from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.const import AvatarSize from gajim.gtk.util import get_iconset_name_for from gajim.gtk.util import get_builder class StartChatDialog(Gtk.ApplicationWindow): def __init__(self): Gtk.ApplicationWindow.__init__(self) self.set_name('StartChatDialog') self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_title(_('Start new Conversation')) self.set_default_size(-1, 400) self.ready_to_destroy = False self.builder = get_builder('start_chat_dialog.ui') self.listbox = self.builder.get_object('listbox') self.search_entry = self.builder.get_object('search_entry') self.box = self.builder.get_object('box') self.add(self.box) self.new_contact_row_visible = False self.new_contact_rows = {} self.new_groupchat_rows = {} self.accounts = app.connections.keys() self.add_contacts() self.add_groupchats() self.search_entry.connect('search-changed', self._on_search_changed) self.search_entry.connect('next-match', self._select_new_match, 'next') self.search_entry.connect('previous-match', self._select_new_match, 'prev') self.search_entry.connect('stop-search', lambda *args: self.search_entry.set_text('')) self.listbox.set_filter_func(self._filter_func, None) self.listbox.set_sort_func(self._sort_func, None) self.listbox.connect('row-activated', self._on_row_activated) self.connect('key-press-event', self._on_key_press) self.connect('destroy', self._destroy) self.select_first_row() self.show_all() def add_contacts(self): show_account = len(self.accounts) > 1 for account in self.accounts: self.new_contact_rows[account] = None for jid in app.contacts.get_jid_list(account): contact = app.contacts.get_contact_with_highest_priority( account, jid) if contact.is_groupchat(): continue row = ContactRow(account, contact, jid, contact.get_shown_name(), show_account) self.listbox.add(row) def add_groupchats(self): show_account = len(self.accounts) > 1 for account in self.accounts: self.new_groupchat_rows[account] = None con = app.connections[account] bookmarks = con.get_module('Bookmarks').bookmarks groupchats = {} for jid, bookmark in bookmarks.items(): groupchats[jid] = bookmark['name'] for jid in app.contacts.get_gc_list(account): if jid in groupchats: continue groupchats[jid] = None for jid in groupchats: name = groupchats[jid] if not name: name = app.get_nick_from_jid(jid) row = ContactRow(account, None, jid, name, show_account, True) self.listbox.add(row) def _on_row_activated(self, listbox, row): row = row.get_child() self._start_new_chat(row) def _on_key_press(self, widget, event): if event.keyval in (Gdk.KEY_Down, Gdk.KEY_Tab): self.search_entry.emit('next-match') return True if (event.state == Gdk.ModifierType.SHIFT_MASK and event.keyval == Gdk.KEY_ISO_Left_Tab): self.search_entry.emit('previous-match') return True if event.keyval == Gdk.KEY_Up: self.search_entry.emit('previous-match') return True if event.keyval == Gdk.KEY_Escape: if self.search_entry.get_text() != '': self.search_entry.emit('stop-search') else: self.destroy() return True if event.keyval == Gdk.KEY_Return: row = self.listbox.get_selected_row() if row is not None: row.emit('activate') return True self.search_entry.grab_focus_without_selecting() def _start_new_chat(self, row): if row.new: if not app.account_is_connected(row.account): app.interface.raise_dialog('start-chat-not-connected') return try: helpers.parse_jid(row.jid) except helpers.InvalidFormat as e: app.interface.raise_dialog('invalid-jid-with-error', str(e)) return if row.groupchat: app.interface.join_gc_minimal(row.account, row.jid) else: app.interface.new_chat_from_jid(row.account, row.jid) self.ready_to_destroy = True def _on_search_changed(self, entry): search_text = entry.get_text() if '@' in search_text: self._add_new_jid_row() self._update_new_jid_rows(search_text) else: self._remove_new_jid_row() self.listbox.invalidate_filter() def _add_new_jid_row(self): if self.new_contact_row_visible: return for account in self.new_contact_rows: show_account = len(self.accounts) > 1 row = ContactRow(account, None, '', None, show_account) self.new_contact_rows[account] = row group_row = ContactRow(account, None, '', None, show_account, True) self.new_groupchat_rows[account] = group_row self.listbox.add(row) self.listbox.add(group_row) row.get_parent().show_all() self.new_contact_row_visible = True def _remove_new_jid_row(self): if not self.new_contact_row_visible: return for account in self.new_contact_rows: self.listbox.remove(self.new_contact_rows[account].get_parent()) self.listbox.remove(self.new_groupchat_rows[account].get_parent()) self.new_contact_row_visible = False def _update_new_jid_rows(self, search_text): for account in self.new_contact_rows: self.new_contact_rows[account].update_jid(search_text) self.new_groupchat_rows[account].update_jid(search_text) def _select_new_match(self, entry, direction): selected_row = self.listbox.get_selected_row() index = selected_row.get_index() if direction == 'next': index += 1 else: index -= 1 while True: new_selected_row = self.listbox.get_row_at_index(index) if new_selected_row is None: return if new_selected_row.get_child_visible(): self.listbox.select_row(new_selected_row) new_selected_row.grab_focus() return if direction == 'next': index += 1 else: index -= 1 def select_first_row(self): first_row = self.listbox.get_row_at_y(0) self.listbox.select_row(first_row) def _filter_func(self, row, user_data): search_text = self.search_entry.get_text().lower() search_text_list = search_text.split() row_text = row.get_child().get_search_text().lower() for text in search_text_list: if text not in row_text: GLib.timeout_add(50, self.select_first_row) return GLib.timeout_add(50, self.select_first_row) return True @staticmethod def _sort_func(row1, row2, user_data): name1 = row1.get_child().get_search_text() name2 = row2.get_child().get_search_text() account1 = row1.get_child().account account2 = row2.get_child().account is_groupchat1 = row1.get_child().groupchat is_groupchat2 = row2.get_child().groupchat new1 = row1.get_child().new new2 = row2.get_child().new result = locale.strcoll(account1.lower(), account2.lower()) if result != 0: return result if new1 != new2: return 1 if new1 else -1 if is_groupchat1 != is_groupchat2: return 1 if is_groupchat1 else -1 return locale.strcoll(name1.lower(), name2.lower()) @staticmethod def _destroy(*args): del app.interface.instances['start_chat'] class ContactRow(Gtk.Grid): def __init__(self, account, contact, jid, name, show_account, groupchat=False): Gtk.Grid.__init__(self) self.set_column_spacing(12) self.set_size_request(260, -1) self.account = account self.account_label = app.get_account_label(account) self.show_account = show_account self.jid = jid self.contact = contact self.name = name self.groupchat = groupchat self.new = jid == '' if self.groupchat: muc_icon = get_iconset_name_for( 'muc-inactive' if self.new else 'muc-active') image = Gtk.Image.new_from_icon_name(muc_icon, Gtk.IconSize.DND) else: scale = self.get_scale_factor() avatar = app.contacts.get_avatar( account, jid, AvatarSize.ROSTER, scale) if avatar is None: image = Gtk.Image.new_from_icon_name( 'avatar-default', Gtk.IconSize.DND) else: image = Gtk.Image.new_from_surface(avatar) image.set_size_request(AvatarSize.ROSTER, AvatarSize.ROSTER) self.add(image) middle_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0) middle_box.set_hexpand(True) if self.name is None: if self.groupchat: self.name = _('New Groupchat') else: self.name = _('New Contact') self.name_label = Gtk.Label(label=self.name) self.name_label.set_ellipsize(Pango.EllipsizeMode.END) self.name_label.set_xalign(0) self.name_label.set_width_chars(25) self.name_label.set_halign(Gtk.Align.START) self.name_label.get_style_context().add_class('bold16') status = contact.show if contact else 'offline' css_class = helpers.get_css_show_color(status) if css_class is not None: self.name_label.get_style_context().add_class(css_class) middle_box.add(self.name_label) self.jid_label = Gtk.Label(label=jid) self.jid_label.set_ellipsize(Pango.EllipsizeMode.END) self.jid_label.set_xalign(0) self.jid_label.set_width_chars(25) self.jid_label.set_halign(Gtk.Align.START) middle_box.add(self.jid_label) self.add(middle_box) if show_account: account_label = Gtk.Label(label=self.account_label) account_label.set_halign(Gtk.Align.START) account_label.set_valign(Gtk.Align.START) right_box = Gtk.Box() right_box.set_vexpand(True) right_box.add(account_label) self.add(right_box) self.show_all() def update_jid(self, jid): self.jid = jid self.jid_label.set_text(jid) def get_search_text(self): if self.contact is None and not self.groupchat: return self.jid if self.show_account: return '%s %s %s' % (self.name, self.jid, self.account_label) return '%s %s' % (self.name, self.jid) gajim-gajim-1.1.3/gajim/gtk/themes.py000066400000000000000000000322121345766322700174220ustar00rootroot00000000000000# Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from collections import namedtuple from enum import IntEnum from gi.repository import Gtk from gi.repository import Gdk from gajim.common import app from gajim.common.i18n import _ from gajim.common.const import StyleAttr from gajim.common.const import DialogButton from gajim.common.const import ButtonAction from gajim.common.connection_handlers_events import StyleChanged from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import NewConfirmationDialog from gajim.gtk.util import get_builder StyleOption = namedtuple('StyleOption', 'label selector attr') CSS_STYLE_OPTIONS = [ StyleOption(_('Chatstate Composing'), '.gajim-state-composing', StyleAttr.COLOR), StyleOption(_('Chatstate Inactive'), '.gajim-state-inactive', StyleAttr.COLOR), StyleOption(_('Chatstate Gone'), '.gajim-state-gone', StyleAttr.COLOR), StyleOption(_('Chatstate Paused'), '.gajim-state-paused', StyleAttr.COLOR), StyleOption(_('MUC Tab New Directed Message'), '.gajim-state-tab-muc-directed-msg', StyleAttr.COLOR), StyleOption(_('MUC Tab New Message'), '.gajim-state-tab-muc-msg', StyleAttr.COLOR), StyleOption(_('Banner Foreground Color'), '.gajim-banner', StyleAttr.COLOR), StyleOption(_('Banner Background Color'), '.gajim-banner', StyleAttr.BACKGROUND), StyleOption(_('Banner Font'), '.gajim-banner', StyleAttr.FONT), StyleOption(_('Account Row Foreground Color'), '.gajim-account-row', StyleAttr.COLOR), StyleOption(_('Account Row Background Color'), '.gajim-account-row', StyleAttr.BACKGROUND), StyleOption(_('Account Row Font'), '.gajim-account-row', StyleAttr.FONT), StyleOption(_('Group Row Foreground Color'), '.gajim-group-row', StyleAttr.COLOR), StyleOption(_('Group Row Background Color'), '.gajim-group-row', StyleAttr.BACKGROUND), StyleOption(_('Group Row Font'), '.gajim-group-row', StyleAttr.FONT), StyleOption(_('Contact Row Foreground Color'), '.gajim-contact-row', StyleAttr.COLOR), StyleOption(_('Contact Row Background Color'), '.gajim-contact-row', StyleAttr.BACKGROUND), StyleOption(_('Contact Row Font'), '.gajim-contact-row', StyleAttr.FONT), StyleOption(_('Conversation Font'), '.gajim-conversation-font', StyleAttr.FONT), StyleOption(_('Incoming Nickname Color'), '.gajim-incoming-nickname', StyleAttr.COLOR), StyleOption(_('Outgoing Nickname Color'), '.gajim-outgoing-nickname', StyleAttr.COLOR), StyleOption(_('Incoming Message Text Color'), '.gajim-incoming-message-text', StyleAttr.COLOR), StyleOption(_('Incoming Message Text Font'), '.gajim-incoming-message-text', StyleAttr.FONT), StyleOption(_('Outgoing Message Text Color'), '.gajim-outgoing-message-text', StyleAttr.COLOR), StyleOption(_('Outgoing Message Text Font'), '.gajim-outgoing-message-text', StyleAttr.FONT), StyleOption(_('Status Message Color'), '.gajim-status-message', StyleAttr.COLOR), StyleOption(_('Status Message Font'), '.gajim-status-message', StyleAttr.FONT), StyleOption(_('URL Color'), '.gajim-url', StyleAttr.COLOR), StyleOption(_('Highlight Message Color'), '.gajim-highlight-message', StyleAttr.COLOR), StyleOption(_('Message Correcting'), '.gajim-msg-correcting text', StyleAttr.BACKGROUND), StyleOption(_('Restored Message Color'), '.gajim-restored-message', StyleAttr.COLOR), StyleOption(_('Contact Disconnected Background'), '.gajim-roster-disconnected', StyleAttr.BACKGROUND), StyleOption(_('Contact Connected Background '), '.gajim-roster-connected', StyleAttr.BACKGROUND), ] class Column(IntEnum): THEME = 0 class Themes(Gtk.ApplicationWindow): def __init__(self, transient): Gtk.Window.__init__(self) self.set_application(app.app) self.set_title(_('Gajim Themes')) self.set_name('ThemesWindow') self.set_show_menubar(False) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.set_transient_for(transient) self.set_resizable(True) self.set_default_size(600, 400) self.builder = get_builder('themes_window.ui') self.add(self.builder.get_object('theme_grid')) widgets = ['option_listbox', 'remove_theme_button', 'theme_store', 'theme_treeview', 'choose_option_listbox', 'add_option_button'] for widget in widgets: setattr(self, '_%s' % widget, self.builder.get_object(widget)) # Doesnt work if we set it in Glade self._add_option_button.set_sensitive(False) self._get_themes() self.builder.connect_signals(self) self.connect('destroy', self._on_destroy) self.show_all() self._fill_choose_listbox() def _get_themes(self): for theme in app.css_config.themes: self._theme_store.append([theme]) def _on_theme_name_edit(self, renderer, path, new_name): iter_ = self._theme_store.get_iter(path) old_name = self._theme_store[iter_][Column.THEME] if new_name == 'default': ErrorDialog( _('Invalid Name'), _('Name default is not allowed'), transient_for=self) return if ' ' in new_name: ErrorDialog( _('Invalid Name'), _('Spaces are not allowed'), transient_for=self) return if new_name == '': return result = app.css_config.rename_theme(old_name, new_name) if result is False: return self._theme_store.set_value(iter_, Column.THEME, new_name) def _select_theme_row(self, iter_): self._theme_treeview.get_selection().select_iter(iter_) def _on_theme_selected(self, tree_selection): store, iter_ = tree_selection.get_selected() if iter_ is None: self._clear_options() return theme = store[iter_][Column.THEME] app.css_config.change_preload_theme(theme) self._add_option_button.set_sensitive(True) self._remove_theme_button.set_sensitive(True) self._load_options(theme) def _load_options(self, name): self._option_listbox.foreach(self._remove_option) for option in CSS_STYLE_OPTIONS: value = app.css_config.get_value( option.selector, option.attr, pre=True) if value is None: continue row = Option(option, value) self._option_listbox.add(row) def _add_option(self, listbox, row): for option in self._option_listbox.get_children(): if option == row: return row = Option(row.option, None) self._option_listbox.add(row) def _clear_options(self): self._option_listbox.foreach(self._remove_option) def _fill_choose_listbox(self): for option in CSS_STYLE_OPTIONS: self._choose_option_listbox.add(ChooseOption(option)) def _remove_option(self, row): self._option_listbox.remove(row) row.destroy() def _on_add_new_theme(self, *args): name = self._create_theme_name() if not app.css_config.add_new_theme(name): return self._remove_theme_button.set_sensitive(True) iter_ = self._theme_store.append([name]) self._select_theme_row(iter_) @staticmethod def _create_theme_name(): i = 0 while 'newtheme%s' % i in app.css_config.themes: i += 1 return 'newtheme%s' % i def _on_remove_theme(self, *args): store, iter_ = self._theme_treeview.get_selection().get_selected() if iter_ is None: return theme = store[iter_][Column.THEME] if theme == app.config.get('roster_theme'): ErrorDialog( _('Active Theme'), _('You tried to delete the currently active theme. ' 'Please switch to a different theme first.'), transient_for=self) return def _remove_theme(): app.css_config.remove_theme(theme) store.remove(iter_) first = store.get_iter_first() if first is None: self._remove_theme_button.set_sensitive(False) self._add_option_button.set_sensitive(False) self._clear_options() buttons = { Gtk.ResponseType.CANCEL: DialogButton('Keep Theme'), Gtk.ResponseType.OK: DialogButton('Delete', _remove_theme, ButtonAction.DESTRUCTIVE), } NewConfirmationDialog('Delete Theme', 'Do you want to permanently delete this theme?', buttons, transient_for=self) @staticmethod def _on_destroy(*args): window = app.get_app_window('Preferences') if window is not None: window.update_theme_list() class Option(Gtk.ListBoxRow): def __init__(self, option, value): Gtk.ListBoxRow.__init__(self) self._option = option self._box = Gtk.Box(spacing=12) label = Gtk.Label() label.set_text(option.label) label.set_hexpand(True) label.set_halign(Gtk.Align.START) self._box.add(label) if option.attr in (StyleAttr.COLOR, StyleAttr.BACKGROUND): self._init_color(value) elif option.attr == StyleAttr.FONT: self._init_font(value) remove_button = Gtk.Button.new_from_icon_name( 'list-remove-symbolic', Gtk.IconSize.MENU) remove_button.get_style_context().add_class('theme_remove_button') remove_button.connect('clicked', self._on_remove) self._box.add(remove_button) self.add(self._box) self.show_all() def _init_color(self, color): color_button = Gtk.ColorButton() if color is not None: rgba = Gdk.RGBA() rgba.parse(color) color_button.set_rgba(rgba) color_button.set_halign(Gtk.Align.END) color_button.connect('color-set', self._on_color_set) self._box.add(color_button) def _init_font(self, desc): font_button = Gtk.FontButton() if desc is not None: font_button.set_font_desc(desc) font_button.set_halign(Gtk.Align.END) font_button.connect('font-set', self._on_font_set) self._box.add(font_button) def _on_color_set(self, color_button): color = color_button.get_rgba() color_string = color.to_string() app.css_config.set_value( self._option.selector, self._option.attr, color_string, pre=True) app.nec.push_incoming_event(StyleChanged(None)) def _on_font_set(self, font_button): desc = font_button.get_font_desc() app.css_config.set_font(self._option.selector, desc, pre=True) app.nec.push_incoming_event(StyleChanged(None,)) def _on_remove(self, *args): self.get_parent().remove(self) app.css_config.remove_value( self._option.selector, self._option.attr, pre=True) app.nec.push_incoming_event(StyleChanged(None)) self.destroy() def __eq__(self, other): if isinstance(other, ChooseOption): return other.option == self._option return other._option == self._option class ChooseOption(Gtk.ListBoxRow): def __init__(self, option): Gtk.ListBoxRow.__init__(self) self.option = option label = Gtk.Label(label=option.label) label.set_xalign(0) self.add(label) self.show_all() gajim-gajim-1.1.3/gajim/gtk/types.py000066400000000000000000000013431345766322700173020ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # Types for typechecking from typing import ClassVar from typing import List from gajim.gtk.const import Filter FilterList = ClassVar[List[Filter]] gajim-gajim-1.1.3/gajim/gtk/util.py000066400000000000000000000204271345766322700171170ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from typing import Any from typing import List from typing import Tuple import os import sys import logging import xml.etree.ElementTree as ET from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GLib from gajim.common import app from gajim.common import configpaths from gajim.common import i18n from gajim.common.i18n import _ from gajim.common.const import Display _icon_theme = Gtk.IconTheme.get_default() _icon_theme.append_search_path(configpaths.get('ICONS')) log = logging.getLogger('gajim.gtk.util') class Builder: def __init__(self, filename: str, widgets: List[str] = None, domain: str = None, gettext_: Any = None) -> None: self._builder = Gtk.Builder() if domain is None: domain = i18n.DOMAIN self._builder.set_translation_domain(domain) if gettext_ is None: gettext_ = _ file_path = os.path.join(configpaths.get('GUI'), filename) if sys.platform == "win32": # This is a workaround for non working translation on Windows tree = ET.parse(file_path) for node in tree.iter(): if 'translatable' in node.attrib and node.text is not None: node.text = gettext_(node.text) xml_text = ET.tostring(tree.getroot(), encoding='unicode', method='xml') if widgets is not None: self._builder.add_objects_from_string(xml_text, widgets) else: # Workaround # https://gitlab.gnome.org/GNOME/pygobject/issues/255 Gtk.Builder.__mro__[1].add_from_string( self._builder, xml_text, len(xml_text.encode("utf-8"))) else: if widgets is not None: self._builder.add_objects_from_file(file_path, widgets) else: self._builder.add_from_file(file_path) def __getattr__(self, name): try: return getattr(self._builder, name) except AttributeError: return self._builder.get_object(name) def get_builder(file_name: str, widgets: List[str] = None) -> Builder: return Builder(file_name, widgets) def load_icon(icon_name, widget, size=16, pixbuf=False, flags=Gtk.IconLookupFlags.FORCE_SIZE): scale = widget.get_scale_factor() if not scale: log.warning('Could not determine scale factor') scale = 1 try: iconinfo = _icon_theme.lookup_icon_for_scale( icon_name, size, scale, flags) if pixbuf: return iconinfo.load_icon() return iconinfo.load_surface(None) except GLib.GError as error: log.error('Unable to load icon %s: %s', icon_name, str(error)) def get_iconset_name_for(name: str) -> str: if name == 'not in roster': name = 'notinroster' iconset = app.config.get('iconset') if not iconset: iconset = app.config.DEFAULT_ICONSET return '%s-%s' % (iconset, name) def get_total_screen_geometry() -> Tuple[int, int]: total_width = 0 total_height = 0 display = Gdk.Display.get_default() monitors = display.get_n_monitors() for num in range(0, monitors): monitor = display.get_monitor(num) geometry = monitor.get_geometry() total_width += geometry.width total_height = max(total_height, geometry.height) log.debug('Get screen geometry: %s %s', total_width, total_height) return total_width, total_height def resize_window(window: Gtk.Window, width: int, height: int) -> None: """ Resize window, but also checks if huge window or negative values """ screen_w, screen_h = get_total_screen_geometry() if not width or not height: return if width > screen_w: width = screen_w if height > screen_h: height = screen_h window.resize(abs(width), abs(height)) def move_window(window: Gtk.Window, pos_x: int, pos_y: int) -> None: """ Move the window, but also check if out of screen """ screen_w, screen_h = get_total_screen_geometry() if pos_x < 0: pos_x = 0 if pos_y < 0: pos_y = 0 width, height = window.get_size() if pos_x + width > screen_w: pos_x = screen_w - width if pos_y + height > screen_h: pos_y = screen_h - height window.move(pos_x, pos_y) def restore_roster_position(window): if not app.config.get('save-roster-position'): return if app.is_display(Display.WAYLAND): return move_window(window, app.config.get('roster_x-position'), app.config.get('roster_y-position')) def get_completion_liststore(entry: Gtk.Entry) -> Gtk.ListStore: """ Create a completion model for entry widget completion list consists of (Pixbuf, Text) rows """ completion = Gtk.EntryCompletion() liststore = Gtk.ListStore(str, str) render_pixbuf = Gtk.CellRendererPixbuf() completion.pack_start(render_pixbuf, False) completion.add_attribute(render_pixbuf, 'icon_name', 0) render_text = Gtk.CellRendererText() completion.pack_start(render_text, True) completion.add_attribute(render_text, 'text', 1) completion.set_property('text_column', 1) completion.set_model(liststore) entry.set_completion(completion) return liststore def get_cursor(attr: str) -> Gdk.Cursor: display = Gdk.Display.get_default() cursor = getattr(Gdk.CursorType, attr) return Gdk.Cursor.new_for_display(display, cursor) def scroll_to_end(widget: Gtk.ScrolledWindow) -> bool: """Scrolls to the end of a GtkScrolledWindow. Args: widget (GtkScrolledWindow) Returns: bool: The return value is False so it can be used with GLib.idle_add. """ adj_v = widget.get_vadjustment() if adj_v is None: # This can happen when the Widget is already destroyed when called # from GLib.idle_add return False max_scroll_pos = adj_v.get_upper() - adj_v.get_page_size() adj_v.set_value(max_scroll_pos) adj_h = widget.get_hadjustment() adj_h.set_value(0) return False def at_the_end(widget: Gtk.ScrolledWindow) -> bool: """Determines if a Scrollbar in a GtkScrolledWindow is at the end. Args: widget (GtkScrolledWindow) Returns: bool: The return value is True if at the end, False if not. """ adj_v = widget.get_vadjustment() max_scroll_pos = adj_v.get_upper() - adj_v.get_page_size() return adj_v.get_value() == max_scroll_pos def get_image_button(icon_name, tooltip, toggle=False): if toggle: button = Gtk.ToggleButton() image = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.MENU) button.set_image(image) else: button = Gtk.Button.new_from_icon_name( icon_name, Gtk.IconSize.MENU) button.set_tooltip_text(tooltip) return button def python_month(month: int) -> int: return month + 1 def gtk_month(month: int) -> int: return month - 1 def convert_rgb_to_hex(rgb_string: str) -> str: rgb = Gdk.RGBA() rgb.parse(rgb_string) rgb.to_color() red = int(rgb.red * 255) green = int(rgb.green * 255) blue = int(rgb.blue * 255) return '#%02x%02x%02x' % (red, green, blue) def get_primary_accel_mod(): """ Returns the primary Gdk.ModifierType modifier. cmd on osx, ctrl everywhere else. """ return Gtk.accelerator_parse("")[1] def get_hardware_key_codes(keyval): keymap = Gdk.Keymap.get_for_display(Gdk.Display.get_default()) valid, key_map_keys = keymap.get_entries_for_keyval(keyval) if not valid: return [] return [key.keycode for key in key_map_keys] gajim-gajim-1.1.3/gajim/gtk/xml_console.py000066400000000000000000000230251345766322700204610ustar00rootroot00000000000000# This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import time import nbxmpp from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GLib from gajim.common import app from gajim.common import ged from gajim.common.i18n import _ from gajim.common.const import Option from gajim.common.const import OptionKind from gajim.common.const import OptionType from gajim.common.const import StyleAttr from gajim.gtk import util from gajim.gtk.util import get_builder from gajim.gtk.util import get_image_button from gajim.gtk.dialogs import ErrorDialog from gajim.options_dialog import OptionsDialog UNDECLARED = 'http://www.gajim.org/xmlns/undeclared' class XMLConsoleWindow(Gtk.Window): def __init__(self, account): Gtk.Window.__init__(self) self.account = account self.enabled = True self.presence = True self.message = True self.iq = True self.stream = True self.incoming = True self.outgoing = True self.filter_dialog = None glade_objects = ['textview', 'input', 'scrolled_input', 'headerbar', 'scrolled', 'actionbar', 'paned', 'box', 'menubutton'] self.builder = get_builder('xml_console_window.ui') for obj in glade_objects: setattr(self, obj, self.builder.get_object(obj)) self.set_titlebar(self.headerbar) jid = app.get_jid_from_account(account) self.headerbar.set_subtitle(jid) self.set_default_size(600, 600) self.add(self.box) self.paned.set_position(self.paned.get_property('max-position')) button = get_image_button( 'edit-clear-all-symbolic', _('Clear')) button.connect('clicked', self.on_clear) self.actionbar.pack_start(button) button = get_image_button( 'applications-system-symbolic', _('Filter')) button.connect('clicked', self.on_filter_options) self.actionbar.pack_start(button) button = get_image_button( 'document-edit-symbolic', _('XML Input'), toggle=True) button.connect('toggled', self.on_input) self.actionbar.pack_start(button) button = get_image_button('emblem-ok-symbolic', _('Send')) button.connect('clicked', self.on_send) self.actionbar.pack_end(button) self.actionbar.pack_start(self.menubutton) self.create_tags() self.show_all() self.scrolled_input.hide() self.menubutton.hide() self.connect("destroy", self.on_destroy) self.connect('key_press_event', self.on_key_press_event) self.builder.connect_signals(self) app.ged.register_event_handler( 'stanza-received', ged.GUI1, self._nec_stanza_received) app.ged.register_event_handler( 'stanza-sent', ged.GUI1, self._nec_stanza_sent) def create_tags(self): buffer_ = self.textview.get_buffer() in_color = app.css_config.get_value( '.gajim-incoming-nickname', StyleAttr.COLOR) out_color = app.css_config.get_value( '.gajim-outgoing-nickname', StyleAttr.COLOR) tags = ['presence', 'message', 'stream', 'iq'] tag = buffer_.create_tag('incoming') tag.set_property('foreground', in_color) tag = buffer_.create_tag('outgoing') tag.set_property('foreground', out_color) for tag_name in tags: buffer_.create_tag(tag_name) def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy() def on_row_activated(self, listbox, row): text = row.get_child().get_text() input_text = None if text == 'Presence': input_text = ( '\n' '\n' '\n' '\n' '') elif text == 'Message': input_text = ( '\n' '\n' '') elif text == 'Iq': input_text = ( '\n' '\n' '') if input_text is not None: buffer_ = self.input.get_buffer() buffer_.set_text(input_text) self.input.grab_focus() def on_send(self, *args): if app.connections[self.account].connected <= 1: # if offline or connecting ErrorDialog( _('Connection not available'), _('Please make sure you are connected with "%s".') % self.account) return buffer_ = self.input.get_buffer() begin_iter, end_iter = buffer_.get_bounds() stanza = buffer_.get_text(begin_iter, end_iter, True) if stanza: try: node = nbxmpp.Protocol(node=stanza) if node.getNamespace() == UNDECLARED: node.setNamespace(nbxmpp.NS_CLIENT) except Exception as error: ErrorDialog(_('Invalid Node'), str(error)) return app.connections[self.account].connection.send(node) buffer_.set_text('') def on_input(self, button, *args): if button.get_active(): self.paned.get_child2().show() self.menubutton.show() self.input.grab_focus() else: self.paned.get_child2().hide() self.menubutton.hide() def on_filter_options(self, *args): if self.filter_dialog: self.filter_dialog.present() return options = [ Option(OptionKind.SWITCH, 'Presence', OptionType.VALUE, self.presence, callback=self.on_option, data='presence'), Option(OptionKind.SWITCH, 'Message', OptionType.VALUE, self.message, callback=self.on_option, data='message'), Option(OptionKind.SWITCH, 'Iq', OptionType.VALUE, self.iq, callback=self.on_option, data='iq'), Option(OptionKind.SWITCH, 'Stream\nManagement', OptionType.VALUE, self.stream, callback=self.on_option, data='stream'), Option(OptionKind.SWITCH, 'In', OptionType.VALUE, self.incoming, callback=self.on_option, data='incoming'), Option(OptionKind.SWITCH, 'Out', OptionType.VALUE, self.outgoing, callback=self.on_option, data='outgoing'), ] self.filter_dialog = OptionsDialog(self, 'Filter', Gtk.DialogFlags.DESTROY_WITH_PARENT, options, self.account) self.filter_dialog.connect('destroy', self.on_filter_destroyed) def on_filter_destroyed(self, win): self.filter_dialog = None def on_clear(self, *args): self.textview.get_buffer().set_text('') def on_destroy(self, *args): del app.interface.instances[self.account]['xml_console'] app.ged.remove_event_handler( 'stanza-received', ged.GUI1, self._nec_stanza_received) app.ged.remove_event_handler( 'stanza-sent', ged.GUI1, self._nec_stanza_sent) def on_enable(self, switch, param): self.enabled = switch.get_active() def on_option(self, value, data): setattr(self, data, value) value = not value table = self.textview.get_buffer().get_tag_table() tag = table.lookup(data) if data in ('incoming', 'outgoing'): if value: tag.set_priority(table.get_size() - 1) else: tag.set_priority(0) tag.set_property('invisible', value) def _nec_stanza_received(self, obj): if obj.conn.name != self.account: return self.print_stanza(obj.stanza_str, 'incoming') def _nec_stanza_sent(self, obj): if obj.conn.name != self.account: return self.print_stanza(obj.stanza_str, 'outgoing') def print_stanza(self, stanza, kind): # kind must be 'incoming' or 'outgoing' if not self.enabled: return if not stanza: return at_the_end = util.at_the_end(self.scrolled) buffer_ = self.textview.get_buffer() end_iter = buffer_.get_end_iter() type_ = kind if stanza.startswith('<', '>\n<')) buffer_.insert_with_tags_by_name(end_iter, stanza, type_, kind) if at_the_end: GLib.idle_add(util.scroll_to_end, self.scrolled) gajim-gajim-1.1.3/gajim/gtkexcepthook.py000066400000000000000000000105001345766322700202230ustar00rootroot00000000000000# Copyright (C) 2016-2018 Philipp Hörist # Copyright (C) 2005-2006 Nikos Kouremenos # Copyright (C) 2005-2014 Yann Leboulanger # Copyright (C) 2008 Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import sys import os import traceback import threading import webbrowser import platform from io import StringIO from urllib.parse import urlencode import nbxmpp from gi.repository import Gtk, GObject try: import gajim gajim_version = gajim.__version__ except ImportError: # For standalone testing gajim_version = 'Package not installed' if __name__ == '__main__': glade_file = os.path.join('data', 'gui', 'exception_dialog.ui') else: from gajim.common import configpaths gui_path = configpaths.get('GUI') glade_file = os.path.join(gui_path, 'exception_dialog.ui') _exception_in_progress = threading.Lock() ISSUE_TEXT = '''## Versions - OS: {} - GTK+ Version: {} - PyGObject Version: {} - python-nbxmpp Version: {} - Gajim Version: {} ## Traceback ``` {} ``` ## Steps to reproduce the problem ...''' def _hook(type_, value, tb): if not _exception_in_progress.acquire(False): # Exceptions have piled up, so we use the default exception # handler for such exceptions sys.__excepthook__(type_, value, tb) return ExceptionDialog(type_, value, tb) _exception_in_progress.release() class ExceptionDialog(): def __init__(self, type_, value, tb): builder = Gtk.Builder() builder.add_from_file(glade_file) self.dialog = builder.get_object("ExceptionDialog") builder.connect_signals(self) builder.get_object("report_btn").grab_focus() self.exception_view = builder.get_object("exception_view") buffer_ = self.exception_view.get_buffer() trace = StringIO() traceback.print_exception(type_, value, tb, None, trace) self.text = self.get_issue_text(trace.getvalue()) buffer_.set_text(self.text) print(self.text, file=sys.stderr) self.exception_view.set_editable(False) self.dialog.show() if __name__ == '__main__': self.dialog.connect('delete-event', self._on_delete_event) def on_report_clicked(self, *args): issue_url = 'https://dev.gajim.org/gajim/gajim/issues/new' params = {'issue[description]': self.text} url = '{}?{}'.format(issue_url, urlencode(params)) webbrowser.open(url, new=2) def on_close_clicked(self, *args): self.dialog.destroy() if __name__ == '__main__': Gtk.main_quit() def _on_delete_event(self, *args): Gtk.main_quit() def get_issue_text(self, traceback_text): gtk_ver = '%i.%i.%i' % ( Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version()) gobject_ver = '.'.join(map(str, GObject.pygobject_version)) return ISSUE_TEXT.format(get_os_info(), gtk_ver, gobject_ver, nbxmpp.__version__, gajim_version, traceback_text) def init(): if os.name == 'nt' or not sys.stderr.isatty(): sys.excepthook = _hook def get_os_info(): if os.name == 'nt' or sys.platform == 'darwin': return platform.system() + " " + platform.release() if os.name == 'posix': try: import distro return distro.name(pretty=True) except ImportError: return platform.system() return '' # this is just to assist testing (python3 gtkexcepthook.py) if __name__ == '__main__': init() print(sys.version) ExceptionDialog(None, None, None) Gtk.main() gajim-gajim-1.1.3/gajim/gtkgui_helpers.py000066400000000000000000000660601345766322700203740ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2006 Dimitur Kirov # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2006 Travis Shirk # Copyright (C) 2006-2007 Junglecow J # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 James Newton # Julien Pivotto # Copyright (C) 2007-2008 Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import cairo import os import sys import math import logging from io import BytesIO import xml.etree.ElementTree as ET from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import GLib from gi.repository import Pango try: from PIL import Image except Exception: pass from gajim.common import i18n from gajim.common.i18n import _ from gajim.common import app from gajim.common import configpaths from gajim.common.const import PEPEventType, ACTIVITIES, MOODS log = logging.getLogger('gajim.gtkgui_helpers') gtk_icon_theme = Gtk.IconTheme.get_default() gtk_icon_theme.append_search_path(configpaths.get('ICONS')) class Color: BLACK = Gdk.RGBA(red=0, green=0, blue=0, alpha=1) GREEN = Gdk.RGBA(red=115/255, green=210/255, blue=22/255, alpha=1) RED = Gdk.RGBA(red=204/255, green=0, blue=0, alpha=1) GREY = Gdk.RGBA(red=195/255, green=195/255, blue=192/255, alpha=1) ORANGE = Gdk.RGBA(red=245/255, green=121/255, blue=0/255, alpha=1) def get_icon_pixmap(icon_name, size=16, color=None, quiet=False): try: iconinfo = gtk_icon_theme.lookup_icon(icon_name, size, 0) if not iconinfo: raise GLib.GError if color: pixbuf, _was_symbolic = iconinfo.load_symbolic(*color) return pixbuf return iconinfo.load_icon() except GLib.GError as error: if not quiet: log.error('Unable to load icon %s: %s', icon_name, str(error)) def get_icon_path(icon_name, size=16): try: icon_info = gtk_icon_theme.lookup_icon(icon_name, size, 0) if icon_info is None: log.error('Icon not found: %s', icon_name) return '' return icon_info.get_filename() except GLib.GError as error: log.error('Unable to find icon %s: %s', icon_name, str(error)) HAS_PYWIN32 = True if os.name == 'nt': try: import win32file import win32con import pywintypes except ImportError: HAS_PYWIN32 = False from gajim.common import helpers def get_total_screen_geometry(): screen = Gdk.Screen.get_default() window = Gdk.Screen.get_root_window(screen) w, h = window.get_width(), window.get_height() log.debug('Get screen geometry: %s %s', w, h) return w, h def add_image_to_button(button, icon_name): img = Gtk.Image() path_img = get_icon_path(icon_name) img.set_from_file(path_img) button.set_image(img) def get_image_button(icon_name, tooltip, toggle=False): if toggle: button = Gtk.ToggleButton() icon = get_icon_pixmap(icon_name) image = Gtk.Image() image.set_from_pixbuf(icon) button.set_image(image) else: button = Gtk.Button.new_from_icon_name( icon_name, Gtk.IconSize.MENU) button.set_tooltip_text(tooltip) return button def get_gtk_builder(file_name, widget=None): file_path = os.path.join(configpaths.get('GUI'), file_name) builder = Gtk.Builder() builder.set_translation_domain(i18n.DOMAIN) if sys.platform == "win32": # This is a workaround for non working translation on Windows tree = ET.parse(file_path) for node in tree.iter(): if 'translatable' in node.attrib and node.text is not None: node.text = _(node.text) xml_text = ET.tostring(tree.getroot(), encoding='unicode', method='xml') if widget is not None: builder.add_objects_from_string(xml_text, [widget]) else: # Workaround # https://gitlab.gnome.org/GNOME/pygobject/issues/255 Gtk.Builder.__mro__[1].add_from_string( builder, xml_text, len(xml_text.encode("utf-8"))) else: if widget is not None: builder.add_objects_from_file(file_path, [widget]) else: builder.add_from_file(file_path) return builder def get_completion_liststore(entry): """ Create a completion model for entry widget completion list consists of (Pixbuf, Text) rows """ completion = Gtk.EntryCompletion() liststore = Gtk.ListStore(str, str) render_pixbuf = Gtk.CellRendererPixbuf() completion.pack_start(render_pixbuf, False) completion.add_attribute(render_pixbuf, 'icon_name', 0) render_text = Gtk.CellRendererText() completion.pack_start(render_text, True) completion.add_attribute(render_text, 'text', 1) completion.set_property('text_column', 1) completion.set_model(liststore) entry.set_completion(completion) return liststore def move_window(window, x, y): """ Move the window, but also check if out of screen """ screen_w, screen_h = get_total_screen_geometry() if x < 0: x = 0 if y < 0: y = 0 w, h = window.get_size() if x + w > screen_w: x = screen_w - w if y + h > screen_h: y = screen_h - h window.move(x, y) def resize_window(window, w, h): """ Resize window, but also checks if huge window or negative values """ screen_w, screen_h = get_total_screen_geometry() if not w or not h: return if w > screen_w: w = screen_w if h > screen_h: h = screen_h window.resize(abs(w), abs(h)) def at_the_end(widget): """Determines if a Scrollbar in a GtkScrolledWindow is at the end. Args: widget (GtkScrolledWindow) Returns: bool: The return value is True if at the end, False if not. """ adj_v = widget.get_vadjustment() max_scroll_pos = adj_v.get_upper() - adj_v.get_page_size() return adj_v.get_value() == max_scroll_pos def scroll_to_end(widget): """Scrolls to the end of a GtkScrolledWindow. Args: widget (GtkScrolledWindow) Returns: bool: The return value is False so it can be used with GLib.idle_add. """ adj_v = widget.get_vadjustment() if adj_v is None: # This can happen when the Widget is already destroyed when called # from GLib.idle_add return False max_scroll_pos = adj_v.get_upper() - adj_v.get_page_size() adj_v.set_value(max_scroll_pos) adj_h = widget.get_hadjustment() adj_h.set_value(0) return False def set_unset_urgency_hint(window, unread_messages_no): """ Sets/unset urgency hint in window argument depending if we have unread messages or not """ if app.config.get('use_urgency_hint'): window.props.urgency_hint = unread_messages_no > 0 def get_pixbuf_from_data(file_data): """ Get image data and returns GdkPixbuf.Pixbuf """ pixbufloader = GdkPixbuf.PixbufLoader() try: pixbufloader.write(file_data) pixbufloader.close() pixbuf = pixbufloader.get_pixbuf() except GLib.GError: pixbufloader.close() log.warning('loading avatar using pixbufloader failed, trying to ' 'convert avatar image using pillow') try: avatar = Image.open(BytesIO(file_data)).convert("RGBA") array = GLib.Bytes.new(avatar.tobytes()) width, height = avatar.size pixbuf = GdkPixbuf.Pixbuf.new_from_bytes( array, GdkPixbuf.Colorspace.RGB, True, 8, width, height, width * 4) except Exception: log.warning('Could not use pillow to convert avatar image, ' 'image cannot be displayed', exc_info=True) return return pixbuf def get_cursor(attr): display = Gdk.Display.get_default() cursor = getattr(Gdk.CursorType, attr) return Gdk.Cursor.new_for_display(display, cursor) def get_current_desktop(window): """ Return the current virtual desktop for given window NOTE: Window is a GDK window. """ prop = window.property_get('_NET_CURRENT_DESKTOP') if prop is None: # it means it's normal window (not root window) # so we look for it's current virtual desktop in another property prop = window.property_get('_NET_WM_DESKTOP') if prop is not None: # f.e. prop is ('CARDINAL', 32, [0]) we want 0 or 1.. from [0] current_virtual_desktop_no = prop[2][0] return current_virtual_desktop_no def file_is_locked(path_to_file): """ Return True if file is locked NOTE: Windows only. """ if os.name != 'nt': # just in case return if not HAS_PYWIN32: return secur_att = pywintypes.SECURITY_ATTRIBUTES() secur_att.Initialize() try: # try make a handle for READING the file hfile = win32file.CreateFile( path_to_file, # path to file win32con.GENERIC_READ, # open for reading 0, # do not share with other proc secur_att, win32con.OPEN_EXISTING, # existing file only win32con.FILE_ATTRIBUTE_NORMAL, # normal file 0 # no attr. template ) except pywintypes.error: return True else: # in case all went ok, close file handle (go to hell WinAPI) hfile.Close() return False def get_fade_color(treeview, selected, focused): """ Get a gdk RGBA color that is between foreground and background in 0.3 0.7 respectively colors of the cell for the given treeview """ context = treeview.get_style_context() if selected: if focused: # is the window focused? state = Gtk.StateFlags.SELECTED else: # is it not? NOTE: many gtk themes change bg on this state = Gtk.StateFlags.ACTIVE else: state = Gtk.StateFlags.NORMAL bg = context.get_property('background-color', state) fg = context.get_color(state) p = 0.3 # background q = 0.7 # foreground # p + q should do 1.0 return Gdk.RGBA(bg.red*p + fg.red*q, bg.green*p + fg.green*q, bg.blue*p + fg.blue*q) def make_gtk_month_python_month(month): """ GTK starts counting months from 0, so January is 0 but Python's time start from 1, so align to Python NOTE: Month MUST be an integer. """ return month + 1 def make_python_month_gtk_month(month): return month - 1 def make_pixbuf_grayscale(pixbuf): pixbuf2 = pixbuf.copy() pixbuf.saturate_and_pixelate(pixbuf2, 0.0, False) return pixbuf2 def get_possible_button_event(event): """ Mouse or keyboard caused the event? """ if event.type == Gdk.EventType.KEY_PRESS: return 0 # no event.button so pass 0 # BUTTON_PRESS event, so pass event.button return event.button def destroy_widget(widget): widget.destroy() def scale_with_ratio(size, width, height): if height == width: return size, size if height > width: ratio = height / float(width) return int(size / ratio), size ratio = width / float(height) return size, int(size / ratio) def scale_pixbuf(pixbuf, size): width, height = scale_with_ratio(size, pixbuf.get_width(), pixbuf.get_height()) return pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.BILINEAR) def scale_pixbuf_from_data(data, size): pixbuf = get_pixbuf_from_data(data) return scale_pixbuf(pixbuf, size) def on_avatar_save_as_menuitem_activate(widget, avatar, default_name=''): from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import ConfirmationDialog from gajim.gtk.dialogs import FTOverwriteConfirmationDialog from gajim.gtk.filechoosers import AvatarSaveDialog def on_continue(response, file_path): if response < 0: return app.config.set('last_save_dir', os.path.dirname(file_path)) if isinstance(avatar, str): # We got a SHA pixbuf = app.interface.get_avatar(avatar) else: # We got a pixbuf pixbuf = avatar extension = os.path.splitext(file_path)[1] if not extension: # Silently save as Jpeg image image_format = 'png' file_path += '.png' else: image_format = extension[1:] # remove leading dot # Save image try: pixbuf.savev(file_path, image_format, [], []) except Exception as error: log.error('Error saving avatar: %s', error) if os.path.exists(file_path): os.remove(file_path) new_file_path = '.'.join(file_path.split('.')[:-1]) + '.png' def on_ok(file_path, pixbuf): pixbuf.savev(file_path, 'png', [], []) ConfirmationDialog(_('Extension not supported'), _('Image cannot be saved in %(type)s format. Save as ' '%(new_filename)s?') % {'type': image_format, 'new_filename': new_file_path}, on_response_ok=(on_ok, new_file_path, pixbuf)) def on_ok(file_path): if os.path.exists(file_path): # check if we have write permissions if not os.access(file_path, os.W_OK): file_name = os.path.basename(file_path) ErrorDialog(_('Cannot overwrite existing file "%s"') % \ file_name, _('A file with this name already exists and you ' 'do not have permission to overwrite it.')) return dialog2 = FTOverwriteConfirmationDialog( _('This file already exists'), _('What do you want to do?'), propose_resume=False, on_response=(on_continue, file_path)) dialog2.set_destroy_with_parent(True) else: dirname = os.path.dirname(file_path) if not os.access(dirname, os.W_OK): ErrorDialog(_('Directory "%s" is not writable') % \ dirname, _('You do not have permission to create files in ' 'this directory.')) return on_continue(0, file_path) transient = app.app.get_active_window() AvatarSaveDialog(on_ok, path=app.config.get('last_save_dir'), file_name='%s.png' % default_name, transient_for=transient) def create_combobox(value_list, selected_value=None): """ Value_list is [(label1, value1)] """ liststore = Gtk.ListStore(str, str) combobox = Gtk.ComboBox.new_with_model(liststore) cell = Gtk.CellRendererText() combobox.pack_start(cell, True) combobox.add_attribute(cell, 'text', 0) i = -1 for value in value_list: liststore.append(value) if selected_value == value[1]: i = value_list.index(value) if i > -1: combobox.set_active(i) combobox.show_all() return combobox def create_list_multi(value_list, selected_values=None): """ Value_list is [(label1, value1)] """ liststore = Gtk.ListStore(str, str) treeview = Gtk.TreeView.new_with_model(liststore) treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) treeview.set_headers_visible(False) col = Gtk.TreeViewColumn() treeview.append_column(col) cell = Gtk.CellRendererText() col.pack_start(cell, True) col.set_attributes(cell, text=0) for value in value_list: iter_ = liststore.append(value) if value[1] in selected_values: treeview.get_selection().select_iter(iter_) treeview.show_all() return treeview def load_iconset(path, pixbuf2=None, transport=False): """ Load full iconset from the given path, and add pixbuf2 on top left of each static images """ path += '/' if transport: list_ = ('online', 'chat', 'away', 'xa', 'dnd', 'offline', 'not in roster') else: list_ = ('connecting', 'online', 'chat', 'away', 'xa', 'dnd', 'invisible', 'offline', 'error', 'requested', 'event', 'opened', 'closed', 'not in roster', 'muc_active', 'muc_inactive') if pixbuf2: list_ = ('connecting', 'online', 'chat', 'away', 'xa', 'dnd', 'offline', 'error', 'requested', 'event', 'not in roster') return _load_icon_list(list_, path, pixbuf2) def load_mood_icon(icon_name): """ Load an icon from the mood iconset in 16x16 """ iconset = app.config.get('mood_iconset') path = os.path.join(helpers.get_mood_iconset_path(iconset), '') icon_list = _load_icon_list([icon_name], path) return icon_list[icon_name] def load_activity_icon(category, activity=None): """ Load an icon from the activity iconset in 16x16 """ iconset = app.config.get('activity_iconset') path = os.path.join(helpers.get_activity_iconset_path(iconset), category, '') if activity is None: activity = 'category' icon_list = _load_icon_list([activity], path) return icon_list[activity] def get_pep_as_pixbuf(pep_class): if pep_class == PEPEventType.MOOD: received_mood = pep_class.data['mood'] mood = received_mood if received_mood in MOODS else 'unknown' pixbuf = load_mood_icon(mood).get_pixbuf() return pixbuf if pep_class == PEPEventType.TUNE: icon = get_icon_pixmap('audio-x-generic', quiet=True) if not icon: path = os.path.join( configpaths.get('DATA'), 'emoticons', 'static', 'music.png') return GdkPixbuf.Pixbuf.new_from_file(path) return icon if pep_class == PEPEventType.ACTIVITY: pep_ = pep_class.data activity = pep_['activity'] has_known_activity = activity in ACTIVITIES has_known_subactivity = (has_known_activity and 'subactivity' in pep_ and pep_['subactivity'] in ACTIVITIES[activity]) if has_known_activity: if has_known_subactivity: subactivity = pep_['subactivity'] return load_activity_icon(activity, subactivity).get_pixbuf() return load_activity_icon(activity).get_pixbuf() return load_activity_icon('unknown').get_pixbuf() if pep_class == PEPEventType.LOCATION: icon = get_icon_pixmap('applications-internet', quiet=True) if not icon: icon = get_icon_pixmap('gajim-earth') return icon return None def get_iconset_name_for(name): if name == 'not in roster': name = 'notinroster' iconset = app.config.get('iconset') if not iconset: iconset = app.config.DEFAULT_ICONSET return '%s-%s' % (iconset, name) def load_icons_meta(): """ Load and return - AND + small icons to put on top left of an icon for meta contacts """ iconset = app.config.get('iconset') path = os.path.join(helpers.get_iconset_path(iconset), '16x16') # try to find opened_meta.png file, else opened.png else nopixbuf merge path_opened = os.path.join(path, 'opened_meta.png') if not os.path.isfile(path_opened): path_opened = os.path.join(path, 'opened.png') if os.path.isfile(path_opened): pixo = GdkPixbuf.Pixbuf.new_from_file(path_opened) else: pixo = None # Same thing for closed path_closed = os.path.join(path, 'opened_meta.png') if not os.path.isfile(path_closed): path_closed = os.path.join(path, 'closed.png') if os.path.isfile(path_closed): pixc = GdkPixbuf.Pixbuf.new_from_file(path_closed) else: pixc = None return pixo, pixc def _load_icon_list(icons_list, path, pixbuf2=None): """ Load icons in icons_list from the given path, and add pixbuf2 on top left of each static images """ imgs = {} for icon in icons_list: # try to open a pixfile with the correct method icon_file = icon.replace(' ', '_') files = [] files.append(path + icon_file + '.gif') files.append(path + icon_file + '.png') image = Gtk.Image() image.show() imgs[icon] = image for file_ in files: # loop seeking for either gif or png if os.path.exists(file_): image.set_from_file(file_) if pixbuf2 and image.get_storage_type() == Gtk.ImageType.PIXBUF: # add pixbuf2 on top-left corner of image pixbuf1 = image.get_pixbuf() pixbuf2.composite(pixbuf1, 0, 0, pixbuf2.get_property('width'), pixbuf2.get_property('height'), 0, 0, 1.0, 1.0, GdkPixbuf.InterpType.NEAREST, 255) image.set_from_pixbuf(pixbuf1) break return imgs def make_jabber_state_images(): """ Initialize jabber_state_images dictionary """ iconset = app.config.get('iconset') if iconset: if helpers.get_iconset_path(iconset): path = os.path.join(helpers.get_iconset_path(iconset), '16x16') if not os.path.exists(path): iconset = app.config.DEFAULT_ICONSET app.config.set('iconset', iconset) else: iconset = app.config.DEFAULT_ICONSET app.config.set('iconset', iconset) else: iconset = app.config.DEFAULT_ICONSET app.config.set('iconset', iconset) path = os.path.join(helpers.get_iconset_path(iconset), '16x16') app.interface.jabber_state_images['16'] = load_iconset(path) pixo, pixc = load_icons_meta() app.interface.jabber_state_images['opened'] = load_iconset(path, pixo) app.interface.jabber_state_images['closed'] = load_iconset(path, pixc) path = os.path.join(helpers.get_iconset_path(iconset), '32x32') app.interface.jabber_state_images['32'] = load_iconset(path) path = os.path.join(helpers.get_iconset_path(iconset), '24x24') if os.path.exists(path): app.interface.jabber_state_images['24'] = load_iconset(path) else: # Resize 32x32 icons to 24x24 for each in app.interface.jabber_state_images['32']: img = Gtk.Image() pix = app.interface.jabber_state_images['32'][each] pix_type = pix.get_storage_type() if pix_type == Gtk.ImageType.ANIMATION: animation = pix.get_animation() pixbuf = animation.get_static_image() elif pix_type == Gtk.ImageType.EMPTY: pix = app.interface.jabber_state_images['16'][each] pix_16_type = pix.get_storage_type() if pix_16_type == Gtk.ImageType.ANIMATION: animation = pix.get_animation() pixbuf = animation.get_static_image() else: pixbuf = pix.get_pixbuf() else: pixbuf = pix.get_pixbuf() scaled_pix = pixbuf.scale_simple(24, 24, GdkPixbuf.InterpType.BILINEAR) img.set_from_pixbuf(scaled_pix) app.interface.jabber_state_images['24'][each] = img def reload_jabber_state_images(): make_jabber_state_images() app.interface.roster.update_jabber_state_images() def label_set_autowrap(widget): """ Make labels automatically re-wrap if their containers are resized. Accepts label or container widgets """ if isinstance(widget, Gtk.Container): children = widget.get_children() for i in list(range(len(children))): label_set_autowrap(children[i]) elif isinstance(widget, Gtk.Label): widget.set_line_wrap(True) widget.connect_after('size-allocate', __label_size_allocate) def __label_size_allocate(widget, allocation): """ Callback which re-allocates the size of a label """ layout = widget.get_layout() lw_old, lh_old = layout.get_size() # fixed width labels if lw_old/Pango.SCALE == allocation.width: return # set wrap width to the Pango.Layout of the labels ### widget.set_alignment(0.0, 0.0) layout.set_width(allocation.width * Pango.SCALE) lh = layout.get_size()[1] if lh_old != lh: widget.set_size_request(-1, lh / Pango.SCALE) def get_action(action): return app.app.lookup_action(action) def add_css_class(widget, class_name, prefix=None): if class_name and prefix: class_name = prefix + class_name style = widget.get_style_context() if prefix is not None: # Remove all css classes with prefix for css_cls in style.list_classes(): if css_cls.startswith(prefix): style.remove_class(css_cls) if class_name is not None: style.add_class(class_name) def add_css_to_widget(widget, css): provider = Gtk.CssProvider() provider.load_from_data(bytes(css.encode())) context = widget.get_style_context() context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_USER) def remove_css_class(widget, class_name): style = widget.get_style_context() style.remove_class(class_name) def draw_affiliation(surface, affiliation): icon_size = 16 size = 4 * 1 if affiliation not in ('owner', 'admin', 'member'): return ctx = cairo.Context(surface) ctx.rectangle(icon_size-size, icon_size-size, size, size) if affiliation == 'owner': ctx.set_source_rgb(204/255, 0, 0) elif affiliation == 'admin': ctx.set_source_rgb(255/255, 140/255, 0) elif affiliation == 'member': ctx.set_source_rgb(0, 255/255, 0) ctx.fill() def get_image_from_icon_name(icon_name, scale): icon = get_iconset_name_for(icon_name) surface = gtk_icon_theme.load_surface(icon, 16, scale, None, 0) return Gtk.Image.new_from_surface(surface) def pango_to_css_weight(number): # Pango allows for weight values between 100 and 1000 # CSS allows only full hundred numbers like 100, 200 .. number = int(number) if number < 100: return 100 if number > 900: return 900 return int(math.ceil(number / 100.0)) * 100 def get_monitor_scale_factor(): display = Gdk.Display.get_default() monitor = display.get_primary_monitor() if monitor is None: log.warning('Could not determine scale factor') return 1 return monitor.get_scale_factor() gajim-gajim-1.1.3/gajim/gui_interface.py000066400000000000000000003575441345766322700201760ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2004-2005 Vincent Hanquez # Copyright (C) 2005 Alex Podaras # Norman Rasmussen # Stéphan Kochen # Copyright (C) 2005-2006 Dimitur Kirov # Alex Mauer # Copyright (C) 2005-2007 Travis Shirk # Nikos Kouremenos # Copyright (C) 2006 Junglecow J # Stefan Bethge # Copyright (C) 2006-2008 Jean-Marie Traissard # Copyright (C) 2007 Lukas Petrovicky # James Newton # Copyright (C) 2007-2008 Brendan Taylor # Julien Pivotto # Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . import os import sys import re import time import hashlib import logging from functools import partial from threading import Thread from gi.repository import Gtk from gi.repository import GdkPixbuf from gi.repository import GLib from gi.repository import Gio from gi.repository import Gdk from nbxmpp import idlequeue from nbxmpp import Hashes2 import OpenSSL try: from PIL import Image except Exception: pass from gajim.common import app from gajim.common import events from gajim.common.dbus import screensaver from gajim.common.dbus import location from gajim.common.dbus import music_track from gajim.common.dbus import logind from gajim import gtkgui_helpers from gajim import gui_menu_builder from gajim import dialogs from gajim import notify from gajim import message_control from gajim.dialog_messages import get_dialog from gajim.dialogs import ProgressWindow from gajim.chat_control_base import ChatControlBase from gajim.chat_control import ChatControl from gajim.groupchat_control import GroupchatControl from gajim.groupchat_control import PrivateChatControl from gajim.message_window import MessageWindowMgr from gajim.filetransfers_window import FileTransfersWindow from gajim.atom_window import AtomWindow from gajim.session import ChatControlSession from gajim.common import idle from gajim.common.zeroconf import connection_zeroconf from gajim.common import resolver from gajim.common import caps_cache from gajim.common import proxy65_manager from gajim.common import socks5 from gajim.common import helpers from gajim.common import passwords from gajim.common import logging_helpers from gajim.common.i18n import _ from gajim.common.connection_handlers_events import ( OurShowEvent, FileRequestErrorEvent, FileTransferCompletedEvent, UpdateRosterAvatarEvent, UpdateGCAvatarEvent, UpdateRoomAvatarEvent) from gajim.common.modules.httpupload import HTTPUploadProgressEvent from gajim.common.connection import Connection from gajim.common.file_props import FilesProp from gajim.common.const import AvatarSize, SSLError, PEPEventType from gajim.common.const import ACTIVITIES, MOODS from gajim import roster_window from gajim import config from gajim.common import ged from gajim.common.caps_cache import muc_caps_cache from gajim.common import configpaths from gajim.common import optparser from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import WarningDialog from gajim.gtk.dialogs import InformationDialog from gajim.gtk.dialogs import InputDialog from gajim.gtk.dialogs import YesNoDialog from gajim.gtk.dialogs import InputTextDialog from gajim.gtk.dialogs import PlainConnectionDialog from gajim.gtk.dialogs import SSLErrorDialog from gajim.gtk.dialogs import ConfirmationDialogDoubleCheck from gajim.gtk.dialogs import ChangeNickDialog from gajim.gtk.profile import ProfileWindow from gajim.gtk.join_groupchat import JoinGroupchatWindow from gajim.gtk.filechoosers import FileChooserDialog from gajim.gtk.emoji_data import emoji_data from gajim.gtk.emoji_data import emoji_ascii_data parser = optparser.OptionsParser(configpaths.get('CONFIG_FILE')) log = logging.getLogger('gajim.interface') class Interface: ################################################################################ ### Methods handling events from connection ################################################################################ def handle_event_db_error(self, unused, error): #('DB_ERROR', account, error) if self.db_error_dialog: return self.db_error_dialog = ErrorDialog(_('Database Error'), error) def destroyed(win): self.db_error_dialog = None self.db_error_dialog.connect('destroy', destroyed) @staticmethod def handle_event_information(obj): if not obj.popup: return if obj.dialog_name is not None: get_dialog(obj.dialog_name, *obj.args, **obj.kwargs) return if obj.level == 'error': cls = ErrorDialog elif obj.level == 'warn': cls = WarningDialog elif obj.level == 'info': cls = InformationDialog else: return cls(obj.pri_txt, GLib.markup_escape_text(obj.sec_txt)) @staticmethod def raise_dialog(name, *args, **kwargs): get_dialog(name, *args, **kwargs) def handle_ask_new_nick(self, account, room_jid, parent_win): title = _('Unable to join group chat') prompt = _('Your desired nickname in group chat\n' '%s\n' 'is in use or registered by another occupant.\n' 'Please specify another nickname below:') % room_jid if 'change_nick_dialog' in self.instances: self.instances['change_nick_dialog'].add_room( account, room_jid, prompt) else: self.instances['change_nick_dialog'] = ChangeNickDialog( account, room_jid, title, prompt, transient_for=parent_win) @staticmethod def handle_event_http_auth(obj): #('HTTP_AUTH', account, (method, url, transaction_id, iq_obj, msg)) def response(account, answer): obj.conn.get_module('HTTPAuth').build_http_auth_answer( obj.stanza, answer) def on_yes(is_checked, obj): response(obj, 'yes') account = obj.conn.name sec_msg = _('Do you accept this request?') if app.get_number_of_connected_accounts() > 1: sec_msg = _('Do you accept this request on account %s?') % account if obj.msg: sec_msg = obj.msg + '\n' + sec_msg YesNoDialog(_('HTTP (%(method)s) Authorization for ' '%(url)s (ID: %(id)s)') % {'method': obj.method, 'url': obj.url, 'id': obj.iq_id}, sec_msg, on_response_yes=(on_yes, obj), on_response_no=(response, obj, 'no')) def handle_event_iq_error(self, obj): #('ERROR_ANSWER', account, (id_, fjid, errmsg, errcode)) if str(obj.errcode) in ('400', '403', '406') and obj.id_: # show the error dialog sid = obj.id_ if len(obj.id_) > 3 and obj.id_[2] == '_': sid = obj.id_[3:] file_props = FilesProp.getFileProp(obj.conn.name, sid) if file_props: if str(obj.errcode) == '400': file_props.error = -3 else: file_props.error = -4 app.nec.push_incoming_event(FileRequestErrorEvent(None, conn=obj.conn, jid=obj.jid, file_props=file_props, error_msg=obj.errmsg)) obj.conn.disconnect_transfer(file_props) return elif str(obj.errcode) == '404': sid = obj.id_ if len(obj.id_) > 3 and obj.id_[2] == '_': sid = obj.id_[3:] file_props = FilesProp.getFileProp(obj.conn.name, sid) if file_props: self.handle_event_file_send_error(obj.conn.name, (obj.fjid, file_props)) obj.conn.disconnect_transfer(file_props) return ctrl = self.msg_win_mgr.get_control(obj.fjid, obj.conn.name) if ctrl and ctrl.type_id == message_control.TYPE_GC: ctrl.print_conversation('Error %s: %s' % (obj.errcode, obj.errmsg)) @staticmethod def handle_event_connection_lost(obj): # ('CONNECTION_LOST', account, [title, text]) account = obj.conn.name app.notification.popup( _('Connection Failed'), account, account, 'connection-lost', 'gajim-connection_lost', obj.title, obj.msg) @staticmethod def unblock_signed_in_notifications(account): app.block_signed_in_notifications[account] = False def handle_event_status(self, obj): # OUR status #('STATUS', account, show) account = obj.conn.name if obj.show in ('offline', 'error'): for name in list(self.instances[account]['online_dialog'].keys()): # .keys() is needed to not have a dictionary length changed # during iteration error self.instances[account]['online_dialog'][name].destroy() if name in self.instances[account]['online_dialog']: # destroy handler may have already removed it del self.instances[account]['online_dialog'][name] for request in self.gpg_passphrase.values(): if request: request.interrupt(account=account) if account in self.pass_dialog: self.pass_dialog[account].window.destroy() if obj.show == 'offline': app.block_signed_in_notifications[account] = True else: # 30 seconds after we change our status to sth else than offline # we stop blocking notifications of any kind # this prevents from getting the roster items as 'just signed in' # contacts. 30 seconds should be enough time GLib.timeout_add_seconds(30, self.unblock_signed_in_notifications, account) if account in self.show_vcard_when_connect and obj.show not in ( 'offline', 'error'): self.edit_own_details(account) self.show_vcard_when_connect.remove(account) def edit_own_details(self, account): window = app.get_app_window(ProfileWindow) if window is None: ProfileWindow(account) else: window.present() @staticmethod def handle_gc_error(gc_control, pritext, sectext): if gc_control and gc_control.autorejoin is not None: if gc_control.error_dialog: gc_control.error_dialog.destroy() def on_close(dummy): gc_control.error_dialog.destroy() gc_control.error_dialog = None gc_control.error_dialog = ErrorDialog(pritext, sectext, on_response_ok=on_close, on_response_cancel=on_close) gc_control.error_dialog.set_modal(False) if gc_control.parent_win: gc_control.error_dialog.set_transient_for( gc_control.parent_win.window) else: d = ErrorDialog(pritext, sectext) if gc_control and gc_control.parent_win: d.set_transient_for(gc_control.parent_win.window) d.set_modal(False) def handle_gc_password_required(self, account, room_jid, nick): def on_ok(text): app.connections[account].join_gc(nick, room_jid, text) app.gc_passwords[room_jid] = text gc_control.error_dialog = None def on_cancel(): # get and destroy window if room_jid in app.interface.minimized_controls[account]: self.roster.on_disconnect(None, room_jid, account) else: win = self.msg_win_mgr.get_window(room_jid, account) ctrl = self.msg_win_mgr.get_gc_control(room_jid, account) win.remove_tab(ctrl, 3) gc_control.error_dialog = None gc_control = self.msg_win_mgr.get_gc_control(room_jid, account) if gc_control: if gc_control.error_dialog: gc_control.error_dialog.destroy() gc_control.error_dialog = InputDialog(_('Password Required'), _('A Password is required to join the room %s. Please type it.') % \ room_jid, is_modal=False, ok_handler=on_ok, cancel_handler=on_cancel) gc_control.error_dialog.input_entry.set_visibility(False) def handle_event_gc_presence(self, obj): gc_control = obj.gc_control parent_win = None if gc_control and gc_control.parent_win: parent_win = gc_control.parent_win.window if obj.ptype == 'error': if obj.errcode == '503': # maximum user number reached self.handle_gc_error(gc_control, _('Unable to join group chat'), _('%s is full')\ % obj.room_jid) elif (obj.errcode == '401') or (obj.errcon == 'not-authorized'): # password required to join self.handle_gc_password_required(obj.conn.name, obj.room_jid, obj.nick) elif (obj.errcode == '403') or (obj.errcon == 'forbidden'): # we are banned self.handle_gc_error(gc_control, _('Unable to join group chat'), _('You are banned from group chat %s.') % \ obj.room_jid) elif (obj.errcode == '404') or (obj.errcon in ('item-not-found', 'remote-server-not-found')): # remote server does not exist if obj.errcon == 'remote-server-not-found': self.handle_gc_error(gc_control, _('Unable to join group chat'), _('Remote server %s does not exist.') % obj.room_jid) # group chat does not exist else: self.handle_gc_error(gc_control, _('Unable to join group chat'), _('Group chat %s does not exist.') % obj.room_jid) elif (obj.errcode == '405') or (obj.errcon == 'not-allowed'): self.handle_gc_error(gc_control, _('Unable to join group chat'), _('Group chat creation is not permitted.')) elif (obj.errcode == '406') or (obj.errcon == 'not-acceptable'): self.handle_gc_error(gc_control, _('Unable to join groupchat'), _('You must use your registered nickname in %s.')\ % obj.room_jid) elif (obj.errcode == '407') or (obj.errcon == \ 'registration-required'): self.handle_gc_error(gc_control, _('Unable to join group chat'), _('You are not in the members list in groupchat %s.') % \ obj.room_jid) elif (obj.errcode == '409') or (obj.errcon == 'conflict'): self.handle_ask_new_nick(obj.conn.name, obj.room_jid, parent_win) elif gc_control: gc_control.print_conversation('Error %s: %s' % (obj.errcode, obj.errmsg)) if gc_control and gc_control.autorejoin: gc_control.autorejoin = False def handle_event_presence(self, obj): # 'NOTIFY' (account, (jid, status, status message, resource, # priority, # keyID, timestamp, contact_nickname)) # # Contact changed show account = obj.conn.name jid = obj.jid # unset custom status if (obj.old_show == 0 and obj.new_show > 1) or \ (obj.old_show > 1 and obj.new_show == 0 and obj.conn.connected > 1): if account in self.status_sent_to_users and \ jid in self.status_sent_to_users[account]: del self.status_sent_to_users[account][jid] if app.jid_is_transport(jid): # It must be an agent # transport just signed in/out, don't show # popup notifications for 30s account_jid = account + '/' + jid app.block_signed_in_notifications[account_jid] = True GLib.timeout_add_seconds(30, self.unblock_signed_in_notifications, account_jid) ctrl = self.msg_win_mgr.get_control(jid, account) if ctrl and ctrl.session and len(obj.contact_list) > 1: ctrl.remove_session(ctrl.session) def handle_event_msgerror(self, obj): #'MSGERROR' (account, (jid, error_code, error_msg, msg, time[session])) account = obj.conn.name jids = obj.fjid.split('/', 1) jid = jids[0] session = obj.session gc_control = self.msg_win_mgr.get_gc_control(jid, account) if not gc_control and \ jid in self.minimized_controls[account]: gc_control = self.minimized_controls[account][jid] if gc_control and gc_control.type_id != message_control.TYPE_GC: gc_control = None if gc_control: if len(jids) > 1: # it's a pm nick = jids[1] if session: ctrl = session.control else: ctrl = self.msg_win_mgr.get_control(obj.fjid, account) if not ctrl: tv = gc_control.list_treeview model = tv.get_model() iter_ = gc_control.get_contact_iter(nick) if iter_: show = model[iter_][3] else: show = 'offline' gc_c = app.contacts.create_gc_contact(room_jid=jid, account=account, name=nick, show=show) ctrl = self.new_private_chat(gc_c, account, session) ctrl.print_conversation(_('Error %(code)s: %(msg)s') % { 'code': obj.error_code, 'msg': obj.error_msg}, 'status') return gc_control.print_conversation(_('Error %(code)s: %(msg)s') % { 'code': obj.error_code, 'msg': obj.error_msg}, 'status') if gc_control.parent_win and \ gc_control.parent_win.get_active_jid() == jid: gc_control.set_subject(gc_control.subject) return if app.jid_is_transport(jid): jid = jid.replace('@', '') msg = obj.error_msg if obj.msg: msg = _('error while sending %(message)s ( %(error)s )') % { 'message': obj.msg, 'error': msg} if session: session.roster_message(jid, msg, obj.time_, msg_type='error') @staticmethod def handle_event_msgsent(obj): #('MSGSENT', account, (jid, msg, keyID)) # do not play sound when standalone chatstate message (eg no msg) if obj.message and app.config.get_per('soundevents', 'message_sent', 'enabled'): helpers.play_sound('message_sent') @staticmethod def handle_event_msgnotsent(obj): #('MSGNOTSENT', account, (jid, ierror_msg, msg, time, session)) msg = _('error while sending %(message)s ( %(error)s )') % { 'message': obj.message, 'error': obj.error} if not obj.session: # No session. This can happen when sending a message from # gajim-remote log.warning(msg) return obj.session.roster_message(obj.jid, msg, obj.time_, obj.conn.name, msg_type='error') def handle_event_subscribe_presence(self, obj): #('SUBSCRIBE', account, (jid, text, user_nick)) user_nick is JEP-0172 account = obj.conn.name if helpers.allow_popup_window(account) or not self.systray_enabled: if obj.jid in self.instances[account]['sub_request']: self.instances[account]['sub_request'][obj.jid].destroy() self.instances[account]['sub_request'][obj.jid] = \ dialogs.SubscriptionRequestWindow(obj.jid, obj.status, account, obj.user_nick) return event = events.SubscriptionRequestEvent(obj.status, obj.user_nick) self.add_event(account, obj.jid, event) if helpers.allow_showing_notification(account): event_type = _('Subscription request') app.notification.popup( event_type, obj.jid, account, 'subscription_request', 'gajim-subscription_request', event_type, obj.jid) def handle_event_subscribed_presence(self, obj): #('SUBSCRIBED', account, (jid, resource)) account = obj.conn.name if obj.jid in app.contacts.get_jid_list(account): c = app.contacts.get_first_contact_from_jid(account, obj.jid) c.resource = obj.resource self.roster.remove_contact_from_groups(c.jid, account, [_('Not in Roster'), _('Observers')], update=False) else: keyID = '' attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if obj.jid in attached_keys: keyID = attached_keys[attached_keys.index(obj.jid) + 1] name = obj.jid.split('@', 1)[0] name = name.split('%', 1)[0] contact1 = app.contacts.create_contact(jid=obj.jid, account=account, name=name, groups=[], show='online', status='online', ask='to', resource=obj.resource, keyID=keyID) app.contacts.add_contact(account, contact1) self.roster.add_contact(obj.jid, account) InformationDialog(_('Authorization accepted'), _('The contact "%s" has authorized you to see their status.') % obj.jid) def show_unsubscribed_dialog(self, account, contact): def on_yes(is_checked, list_): self.roster.on_req_usub(None, list_) list_ = [(contact, account)] YesNoDialog( _('Contact "%s" removed subscription from you') % contact.jid, _('You will always see them as offline.\nDo you want to ' 'remove them from your contact list?'), on_response_yes=(on_yes, list_)) # FIXME: Per RFC 3921, we can "deny" ack as well, but the GUI does # not show deny def handle_event_unsubscribed_presence(self, obj): #('UNSUBSCRIBED', account, jid) account = obj.conn.name contact = app.contacts.get_first_contact_from_jid(account, obj.jid) if not contact: return if helpers.allow_popup_window(account) or not self.systray_enabled: self.show_unsubscribed_dialog(account, contact) return event = events.UnsubscribedEvent(contact) self.add_event(account, obj.jid, event) if helpers.allow_showing_notification(account): event_type = _('Unsubscribed') app.notification.popup( event_type, obj.jid, account, 'unsubscribed', 'gajim-unsubscribed', event_type, obj.jid) def handle_event_gc_config(self, obj): #('GC_CONFIG', account, (jid, form_node)) config is a dict account = obj.conn.name if obj.jid in app.automatic_rooms[account]: if 'continue_tag' in app.automatic_rooms[account][obj.jid]: # We're converting chat to muc. allow participants to invite for f in obj.dataform.iter_fields(): if f.var == 'muc#roomconfig_allowinvites': f.value = True elif f.var == 'muc#roomconfig_publicroom': f.value = False elif f.var == 'muc#roomconfig_membersonly': f.value = True elif f.var == 'public_list': f.value = False obj.conn.get_module('MUC').set_config(obj.jid, obj.dataform.get_purged()) user_list = {} for jid in app.automatic_rooms[account][obj.jid]['invities']: user_list[jid] = {'affiliation': 'member'} obj.conn.get_module('MUC').set_affiliation(obj.jid, user_list) else: # use default configuration obj.conn.get_module('MUC').set_config(obj.jid, obj.form_node) # invite contacts # check if it is necessary to add continue_tag = False if 'continue_tag' in app.automatic_rooms[account][obj.jid]: continue_tag = True if 'invities' in app.automatic_rooms[account][obj.jid]: for jid in app.automatic_rooms[account][obj.jid]['invities']: obj.conn.get_module('MUC').invite( obj.jid, jid, continue_=continue_tag) gc_control = self.msg_win_mgr.get_gc_control(obj.jid, account) if gc_control: gc_control.print_conversation( _('%(jid)s has been invited in this room') % { 'jid': jid}, graphics=False) del app.automatic_rooms[account][obj.jid] elif obj.jid not in self.instances[account]['gc_config']: self.instances[account]['gc_config'][obj.jid] = \ config.GroupchatConfigWindow(account, obj.jid, obj.dataform) def handle_event_gc_affiliation(self, obj): #('GC_AFFILIATION', account, (room_jid, users_dict)) account = obj.conn.name if obj.room_jid in self.instances[account]['gc_config']: self.instances[account]['gc_config'][obj.room_jid].\ affiliation_list_received(obj.users_dict) def handle_event_gc_decline(self, obj): gc_control = self.msg_win_mgr.get_gc_control(obj.room_jid, obj.account) if gc_control: if obj.reason: gc_control.print_conversation( _('%(jid)s declined the invitation: %(reason)s') % { 'jid': obj.from_, 'reason': obj.reason}, graphics=False) else: gc_control.print_conversation( _('%(jid)s declined the invitation') % { 'jid': obj.from_}, graphics=False) def handle_event_gc_invitation(self, obj): if helpers.allow_popup_window(obj.account) or not self.systray_enabled: dialogs.InvitationReceivedDialog( obj.account, obj.room_jid, str(obj.from_), obj.password, obj.reason, is_continued=obj.is_continued) return event = events.GcInvitationtEvent( obj.room_jid, obj.reason, obj.password, obj.is_continued, str(obj.from_)) self.add_event(obj.account, str(obj.from_), event) if helpers.allow_showing_notification(obj.account): event_type = _('Groupchat Invitation') text = _('You are invited to {room} by {user}').format( room=obj.room_jid, user=str(obj.from_)) app.notification.popup( event_type, str(obj.from_), obj.account, 'gc-invitation', 'gajim-gc_invitation', event_type, text, room_jid=obj.room_jid) def forget_gpg_passphrase(self, keyid): if keyid in self.gpg_passphrase: del self.gpg_passphrase[keyid] return False def handle_event_bad_gpg_passphrase(self, obj): #('BAD_PASSPHRASE', account, ()) if obj.use_gpg_agent: sectext = _('You configured Gajim to use OpenPGP agent, but there ' 'is no OpenPGP agent running or it returned a wrong passphrase.' '\n') sectext += _('You are currently connected without your OpenPGP ' 'key.') WarningDialog(_('Wrong passphrase'), sectext) else: account = obj.conn.name app.notification.popup( 'warning', account, account, '', 'dialog-warning', _('Wrong OpenPGP passphrase'), _('You are currently connected without your OpenPGP key.')) self.forget_gpg_passphrase(obj.keyID) @staticmethod def handle_event_client_cert_passphrase(obj): def on_ok(passphrase, checked): obj.conn.on_client_cert_passphrase(passphrase, obj.con, obj.port, obj.secure_tuple) def on_cancel(): obj.conn.on_client_cert_passphrase('', obj.con, obj.port, obj.secure_tuple) dialogs.PassphraseDialog(_('Certificate Passphrase Required'), _('Enter the certificate passphrase for account %s') % \ obj.conn.name, ok_handler=on_ok, cancel_handler=on_cancel) def handle_event_gpg_password_required(self, obj): #('GPG_PASSWORD_REQUIRED', account, (callback,)) if obj.keyid in self.gpg_passphrase: request = self.gpg_passphrase[obj.keyid] else: request = PassphraseRequest(obj.keyid) self.gpg_passphrase[obj.keyid] = request request.add_callback(obj.conn.name, obj.callback) @staticmethod def handle_event_gpg_trust_key(obj): #('GPG_ALWAYS_TRUST', account, callback) def on_yes(checked): if checked: obj.conn.gpg.always_trust.append(obj.keyID) obj.callback(True) def on_no(): obj.callback(False) YesNoDialog(_('Untrusted OpenPGP key'), _('The OpenPGP key ' 'used to encrypt this chat is not trusted. Do you really want to ' 'encrypt this message?'), checktext=_('_Do not ask me again'), on_response_yes=on_yes, on_response_no=on_no) def handle_event_password_required(self, obj): #('PASSWORD_REQUIRED', account, None) account = obj.conn.name if account in self.pass_dialog: return text = _('Enter your password for account %s') % account def on_ok(passphrase, save): if save: app.config.set_per('accounts', account, 'savepass', True) passwords.save_password(account, passphrase) obj.conn.set_password(passphrase) del self.pass_dialog[account] def on_cancel(): self.roster.set_state(account, 'offline') self.roster.update_status_combobox() del self.pass_dialog[account] self.pass_dialog[account] = dialogs.PassphraseDialog( _('Password Required'), text, _('Save password'), ok_handler=on_ok, cancel_handler=on_cancel) def handle_oauth2_credentials(self, obj): account = obj.conn.name def on_ok(refresh): app.config.set_per('accounts', account, 'oauth2_refresh_token', refresh) st = app.config.get_per('accounts', account, 'last_status') msg = helpers.from_one_line(app.config.get_per('accounts', account, 'last_status_msg')) app.interface.roster.send_status(account, st, msg) del self.pass_dialog[account] def on_cancel(): app.config.set_per('accounts', account, 'oauth2_refresh_token', '') self.roster.set_state(account, 'offline') self.roster.update_status_combobox() del self.pass_dialog[account] instruction = _('Please copy / paste the refresh token from the website' ' that has just been opened.') self.pass_dialog[account] = InputTextDialog( _('Oauth2 Credentials'), instruction, is_modal=False, ok_handler=on_ok, cancel_handler=on_cancel) def handle_event_roster_info(self, obj): #('ROSTER_INFO', account, (jid, name, sub, ask, groups)) account = obj.conn.name contacts = app.contacts.get_contacts(account, obj.jid) if (not obj.sub or obj.sub == 'none') and \ (not obj.ask or obj.ask == 'none') and not obj.nickname and \ not obj.groups: # contact removed us. if contacts: self.roster.remove_contact(obj.jid, account, backend=True) return elif not contacts: if obj.sub == 'remove': return # Add new contact to roster keyID = '' attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if obj.jid in attached_keys: keyID = attached_keys[attached_keys.index(obj.jid) + 1] contact = app.contacts.create_contact(jid=obj.jid, account=account, name=obj.nickname, groups=obj.groups, show='offline', sub=obj.sub, ask=obj.ask, keyID=keyID, avatar_sha=obj.avatar_sha) app.contacts.add_contact(account, contact) self.roster.add_contact(obj.jid, account) else: # If contact has changed (sub, ask or group) update roster # Mind about observer status changes: # According to xep 0162, a contact is not an observer anymore when # we asked for auth, so also remove him if ask changed old_groups = contacts[0].groups if obj.sub == 'remove': # another of our instance removed a contact. Remove it here too self.roster.remove_contact(obj.jid, account, backend=True) return update = False if contacts[0].sub != obj.sub or contacts[0].ask != obj.ask\ or old_groups != obj.groups: # c.get_shown_groups() has changed. Reflect that in # roster_window self.roster.remove_contact(obj.jid, account, force=True) update = True for contact in contacts: contact.name = obj.nickname or '' contact.sub = obj.sub contact.ask = obj.ask contact.groups = obj.groups or [] if update: self.roster.add_contact(obj.jid, account) # Refilter and update old groups for group in old_groups: self.roster.draw_group(group, account) self.roster.draw_contact(obj.jid, account) if obj.jid in self.instances[account]['sub_request'] and obj.sub in ( 'from', 'both'): self.instances[account]['sub_request'][obj.jid].destroy() def handle_event_bookmarks(self, obj): gui_menu_builder.build_bookmark_menu(obj.account) def handle_event_file_send_error(self, account, array): jid = array[0] file_props = array[1] ft = self.instances['file_transfers'] ft.set_status(file_props, 'stop') if helpers.allow_popup_window(account): ft.show_send_error(file_props) return event = events.FileSendErrorEvent(file_props) self.add_event(account, jid, event) if helpers.allow_showing_notification(account): event_type = _('File Transfer Error') app.notification.popup( event_type, jid, account, 'file-send-error', 'gajim-ft_error', event_type, file_props.name) def handle_event_file_request_error(self, obj): # ('FILE_REQUEST_ERROR', account, (jid, file_props, error_msg)) ft = self.instances['file_transfers'] ft.set_status(obj.file_props, 'stop') errno = obj.file_props.error if helpers.allow_popup_window(obj.conn.name): if errno in (-4, -5): ft.show_stopped(obj.jid, obj.file_props, obj.error_msg) else: ft.show_request_error(obj.file_props) return if errno in (-4, -5): event_class = events.FileErrorEvent msg_type = 'file-error' else: event_class = events.FileRequestErrorEvent msg_type = 'file-request-error' event = event_class(obj.file_props) self.add_event(obj.conn.name, obj.jid, event) if helpers.allow_showing_notification(obj.conn.name): # check if we should be notified event_type = _('File Transfer Error') app.notification.popup( event_type, obj.jid, obj.conn.name, msg_type, 'gajim-ft_error', title=event_type, text=obj.file_props.name) def handle_event_file_request(self, obj): account = obj.conn.name if obj.jid not in app.contacts.get_jid_list(account): keyID = '' attached_keys = app.config.get_per('accounts', account, 'attached_gpg_keys').split() if obj.jid in attached_keys: keyID = attached_keys[attached_keys.index(obj.jid) + 1] contact = app.contacts.create_not_in_roster_contact(jid=obj.jid, account=account, keyID=keyID) app.contacts.add_contact(account, contact) self.roster.add_contact(obj.jid, account) contact = app.contacts.get_first_contact_from_jid(account, obj.jid) if obj.file_props.session_type == 'jingle': request = obj.stanza.getTag('jingle').getTag('content')\ .getTag('description').getTag('request') if request: # If we get a request instead ft_win = self.instances['file_transfers'] ft_win.add_transfer(account, contact, obj.file_props) return if helpers.allow_popup_window(account): self.instances['file_transfers'].show_file_request(account, contact, obj.file_props) return event = events.FileRequestEvent(obj.file_props) self.add_event(account, obj.jid, event) if helpers.allow_showing_notification(account): txt = _('%s wants to send you a file.') % app.get_name_from_jid( account, obj.jid) event_type = _('File Transfer Request') app.notification.popup( event_type, obj.jid, account, 'file-request', icon_name='gajim-ft_request', title=event_type, text=txt) @staticmethod def handle_event_file_error(title, message): ErrorDialog(title, message) def handle_event_file_progress(self, account, file_props): if time.time() - self.last_ftwindow_update > 0.5: # update ft window every 500ms self.last_ftwindow_update = time.time() self.instances['file_transfers'].set_progress(file_props.type_, file_props.sid, file_props.received_len) def __compare_hashes(self, account, file_props): session = app.connections[account].get_jingle_session(jid=None, sid=file_props.sid) ft_win = self.instances['file_transfers'] h = Hashes2() try: file_ = open(file_props.file_name, 'rb') except Exception: return hash_ = h.calculateHash(file_props.algo, file_) file_.close() # If the hash we received and the hash of the file are the same, # then the file is not corrupt jid = file_props.sender if file_props.hash_ == hash_: GLib.idle_add(self.popup_ft_result, account, jid, file_props) GLib.idle_add(ft_win.set_status, file_props, 'ok') else: # wrong hash, we need to get the file again! file_props.error = -10 GLib.idle_add(self.popup_ft_result, account, jid, file_props) GLib.idle_add(ft_win.set_status, file_props, 'hash_error') # End jingle session if session: session.end_session() def handle_event_file_rcv_completed(self, account, file_props): ft = self.instances['file_transfers'] if file_props.error == 0: ft.set_progress(file_props.type_, file_props.sid, file_props.received_len) app.nec.push_incoming_event(FileTransferCompletedEvent(None, file_props=file_props)) else: ft.set_status(file_props, 'stop') if not file_props.completed and (file_props.stalled or \ file_props.paused): return if file_props.type_ == 'r': # we receive a file app.socks5queue.remove_receiver(file_props.sid, True, True) if file_props.session_type == 'jingle': if file_props.hash_ and file_props.error == 0: # We compare hashes in a new thread self.hashThread = Thread(target=self.__compare_hashes, args=(account, file_props)) self.hashThread.start() else: # We disn't get the hash, sender probably don't support that jid = file_props.sender self.popup_ft_result(account, jid, file_props) if file_props.error == 0: ft.set_status(file_props, 'ok') session = app.connections[account].get_jingle_session(jid=None, sid=file_props.sid) # End jingle session # TODO: only if there are no other parallel downloads in this session if session: session.end_session() else: # we send a file jid = file_props.receiver app.socks5queue.remove_sender(file_props.sid, True, True) self.popup_ft_result(account, jid, file_props) def popup_ft_result(self, account, jid, file_props): ft = self.instances['file_transfers'] if helpers.allow_popup_window(account): if file_props.error == 0: if app.config.get('notify_on_file_complete'): ft.show_completed(jid, file_props) elif file_props.error == -1: ft.show_stopped(jid, file_props, error_msg=_('Remote contact stopped transfer')) elif file_props.error == -6: ft.show_stopped(jid, file_props, error_msg=_('Error opening file')) elif file_props.error == -10: ft.show_hash_error(jid, file_props, account) elif file_props.error == -12: ft.show_stopped(jid, file_props, error_msg=_('SSL certificate error')) return msg_type = '' event_type = '' if file_props.error == 0 and app.config.get( 'notify_on_file_complete'): event_class = events.FileCompletedEvent msg_type = 'file-completed' event_type = _('File Transfer Completed') elif file_props.error in (-1, -6): event_class = events.FileStoppedEvent msg_type = 'file-stopped' event_type = _('File Transfer Stopped') elif file_props.error == -10: event_class = events.FileHashErrorEvent msg_type = 'file-hash-error' event_type = _('File Transfer Failed') if event_type == '': # FIXME: ugly workaround (this can happen Gajim sent, Gaim recvs) # this should never happen but it does. see process_result() in # socks5.py # who calls this func (sth is really wrong unless this func is also # registered as progress_cb return if msg_type: event = event_class(file_props) self.add_event(account, jid, event) if file_props is not None: if file_props.type_ == 'r': # get the name of the sender, as it is in the roster sender = file_props.sender.split('/')[0] name = app.contacts.get_first_contact_from_jid(account, sender).get_shown_name() filename = os.path.basename(file_props.file_name) if event_type == _('File Transfer Completed'): txt = _('%(filename)s received from %(name)s.')\ % {'filename': filename, 'name': name} icon_name = 'gajim-ft_done' elif event_type == _('File Transfer Stopped'): txt = _('File transfer of %(filename)s from %(name)s ' 'stopped.') % {'filename': filename, 'name': name} icon_name = 'gajim-ft_stopped' else: # ft hash error txt = _('File transfer of %(filename)s from %(name)s ' 'failed.') % {'filename': filename, 'name': name} icon_name = 'gajim-ft_stopped' else: receiver = file_props.receiver if hasattr(receiver, 'jid'): receiver = receiver.jid receiver = receiver.split('/')[0] # get the name of the contact, as it is in the roster name = app.contacts.get_first_contact_from_jid(account, receiver).get_shown_name() filename = os.path.basename(file_props.file_name) if event_type == _('File Transfer Completed'): txt = _('You successfully sent %(filename)s to %(name)s.')\ % {'filename': filename, 'name': name} icon_name = 'gajim-ft_done' elif event_type == _('File Transfer Stopped'): txt = _('File transfer of %(filename)s to %(name)s ' 'stopped.') % {'filename': filename, 'name': name} icon_name = 'gajim-ft_stopped' else: # ft hash error txt = _('File transfer of %(filename)s to %(name)s ' 'failed.') % {'filename': filename, 'name': name} icon_name = 'gajim-ft_stopped' else: txt = '' icon_name = None if app.config.get('notify_on_file_complete') and \ (app.config.get('autopopupaway') or \ app.connections[account].connected in (2, 3)): # we want to be notified and we are online/chat or we don't mind # bugged when away/na/busy app.notification.popup( event_type, jid, account, msg_type, icon_name=icon_name, title=event_type, text=txt) def handle_event_signed_in(self, obj): """ SIGNED_IN event is emitted when we sign in, so handle it """ # ('SIGNED_IN', account, ()) # block signed in notifications for 30 seconds # Add our own JID into the DB app.logger.insert_jid(obj.conn.get_own_jid().getStripped()) account = obj.conn.name app.block_signed_in_notifications[account] = True connected = obj.conn.connected pep_supported = obj.conn.get_module('PEP').supported if not idle.Monitor.is_unknown() and connected in (2, 3): # we go online or free for chat, so we activate auto status app.sleeper_state[account] = 'online' elif not ((idle.Monitor.is_away() and connected == 4) or \ (idle.Monitor.is_xa() and connected == 5)): # If we are autoaway/xa and come back after a disconnection, do # nothing # Else disable autoaway app.sleeper_state[account] = 'off' if obj.conn.get_module('MAM').available and app.config.get_per('accounts', account, 'sync_logs_with_server'): obj.conn.get_module('MAM').request_archive_on_signin() invisible_show = app.SHOW_LIST.index('invisible') # We cannot join rooms if we are invisible if connected == invisible_show: return # send currently played music if (pep_supported and sys.platform not in ('win32', 'darwin') and app.config.get_per('accounts', account, 'publish_tune')): self.enable_music_listener() # enable location listener if (pep_supported and app.is_installed('GEOCLUE') and app.config.get_per('accounts', account, 'publish_location')): location.enable() @staticmethod def show_httpupload_progress(file): ProgressWindow(file) def send_httpupload(self, chat_control): accept_cb = partial(self.on_file_dialog_ok, chat_control) FileChooserDialog(accept_cb, select_multiple=True, transient_for=chat_control.parent_win.window) @staticmethod def on_file_dialog_ok(chat_control, paths): con = app.connections[chat_control.account] groupchat = chat_control.type_id == message_control.TYPE_GC for path in paths: con.get_module('HTTPUpload').check_file_before_transfer( path, chat_control.encryption, chat_control.contact, chat_control.session, groupchat) def encrypt_file(self, file, account, callback): app.nec.push_incoming_event(HTTPUploadProgressEvent( None, status='encrypt', file=file)) encryption = file.encryption plugin = app.plugin_manager.encryption_plugins[encryption] if hasattr(plugin, 'encrypt_file'): plugin.encrypt_file(file, account, callback) else: app.nec.push_incoming_event(HTTPUploadProgressEvent( None, status='close', file=file)) self.raise_dialog('httpupload-encryption-not-available') @staticmethod def handle_event_metacontacts(obj): app.contacts.define_metacontacts(obj.conn.name, obj.meta_list) @staticmethod def handle_atom_entry(obj): if obj != PEPEventType.ATOM: return if obj.get_entry(): AtomWindow.newAtomEntry(obj.get_entry()) def handle_event_zc_name_conflict(self, obj): def on_ok(new_name): app.config.set_per('accounts', obj.conn.name, 'name', new_name) show = obj.conn.old_show status = obj.conn.status obj.conn.username = new_name obj.conn.change_status(show, status) def on_cancel(): obj.conn.change_status('offline', '') InputDialog(_('Username Conflict'), _('Please type a new username for your local account'), input_str=obj.alt_name, is_modal=True, ok_handler=on_ok, cancel_handler=on_cancel, transient_for=self.roster.window) def handle_event_resource_conflict(self, obj): # ('RESOURCE_CONFLICT', account, ()) # First we go offline, but we don't overwrite status message account = obj.conn.name conn = obj.conn self.roster.send_status(account, 'offline', conn.status) def on_ok(new_resource): app.config.set_per('accounts', account, 'resource', new_resource) self.roster.send_status(account, conn.old_show, conn.status) proposed_resource = conn.server_resource if proposed_resource.startswith('gajim.'): # Dont notify the user about resource change if he didn't set # a custom resource on_ok('gajim.$rand') return proposed_resource += app.config.get('gc_proposed_nick_char') dialogs.ResourceConflictDialog(_('Resource Conflict'), _('You are already connected to this account with the same ' 'resource. Please type a new one'), resource=proposed_resource, ok_handler=on_ok) def handle_event_jingleft_cancel(self, obj): ft = self.instances['file_transfers'] file_props = None # get the file_props of our session file_props = FilesProp.getFileProp(obj.conn.name, obj.sid) if not file_props: return ft.set_status(file_props, 'stop') file_props.error = -4 # is it the right error code? ft.show_stopped(obj.jid, file_props, 'Peer cancelled ' + 'the transfer') def handle_event_jingle_incoming(self, obj): # ('JINGLE_INCOMING', account, peer jid, sid, tuple-of-contents==(type, # data...)) # TODO: conditional blocking if peer is not in roster account = obj.conn.name content_types = [obj.contents.media] # check type of jingle session if 'audio' in content_types or 'video' in content_types: # a voip session... # we now handle only voip, so the only thing we will do here is # not to return from function pass else: # unknown session type... it should be declined in common/jingle.py return ctrl = (self.msg_win_mgr.get_control(obj.fjid, account) or self.msg_win_mgr.get_control(obj.jid, account)) if ctrl: if 'audio' in content_types: ctrl.set_audio_state('connection_received', obj.sid) if 'video' in content_types: ctrl.set_video_state('connection_received', obj.sid) dlg = dialogs.VoIPCallReceivedDialog.get_dialog(obj.fjid, obj.sid) if dlg: dlg.add_contents(content_types) return if helpers.allow_popup_window(account): dialogs.VoIPCallReceivedDialog(account, obj.fjid, obj.sid, content_types) return event = events.JingleIncomingEvent(obj.fjid, obj.sid, content_types) self.add_event(account, obj.jid, event) if helpers.allow_showing_notification(account): # TODO: we should use another pixmap ;-) txt = _('%s wants to start a voice chat.') % \ app.get_name_from_jid(account, obj.fjid) event_type = _('Voice Chat Request') app.notification.popup( event_type, obj.fjid, account, 'jingle-incoming', icon_name='gajim-mic_active', title=event_type, text=txt) def handle_event_jingle_connected(self, obj): # ('JINGLE_CONNECTED', account, (peerjid, sid, media)) if obj.media in ('audio', 'video'): account = obj.conn.name ctrl = (self.msg_win_mgr.get_control(obj.fjid, account) or self.msg_win_mgr.get_control(obj.jid, account)) if ctrl: if obj.media == 'audio': ctrl.set_audio_state('connected', obj.sid) else: ctrl.set_video_state('connected', obj.sid) def handle_event_jingle_disconnected(self, obj): # ('JINGLE_DISCONNECTED', account, (peerjid, sid, reason)) account = obj.conn.name ctrl = (self.msg_win_mgr.get_control(obj.fjid, account) or self.msg_win_mgr.get_control(obj.jid, account)) if ctrl: if obj.media is None: ctrl.stop_jingle(sid=obj.sid, reason=obj.reason) elif obj.media == 'audio': ctrl.set_audio_state('stop', sid=obj.sid, reason=obj.reason) elif obj.media == 'video': ctrl.set_video_state('stop', sid=obj.sid, reason=obj.reason) dialog = dialogs.VoIPCallReceivedDialog.get_dialog(obj.fjid, obj.sid) if dialog: if obj.media is None: dialog.dialog.destroy() else: dialog.remove_contents((obj.media, )) def handle_event_jingle_error(self, obj): # ('JINGLE_ERROR', account, (peerjid, sid, reason)) account = obj.conn.name ctrl = (self.msg_win_mgr.get_control(obj.fjid, account) or self.msg_win_mgr.get_control(obj.jid, account)) if ctrl and obj.sid == ctrl.audio_sid: ctrl.set_audio_state('error', reason=obj.reason) @staticmethod def handle_event_roster_item_exchange(obj): # data = (action in [add, delete, modify], exchange_list, jid_from) dialogs.RosterItemExchangeWindow(obj.conn.name, obj.action, obj.exchange_items_list, obj.fjid) def handle_event_ssl_error(self, obj): account = obj.conn.name server = app.config.get_per('accounts', account, 'hostname') def on_ok(is_checked): del self.instances[account]['online_dialog']['ssl_error'] if is_checked[0]: pem = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, obj.cert).decode('utf-8') # Check if cert is already in file certs = '' my_ca_certs = configpaths.get('MY_CACERTS') if os.path.isfile(my_ca_certs): with open(my_ca_certs, encoding='utf-8') as f: certs = f.read() if pem in certs: ErrorDialog(_('Certificate Already in File'), _('This certificate is already in file %s, so it\'s ' 'not added again.') % my_ca_certs) else: with open(my_ca_certs, 'a', encoding='utf-8') as f: f.write(server + '\n') f.write(pem + '\n\n') if is_checked[1]: ignore_ssl_errors = app.config.get_per('accounts', account, 'ignore_ssl_errors').split() ignore_ssl_errors.append(str(obj.error_num)) app.config.set_per('accounts', account, 'ignore_ssl_errors', ' '.join(ignore_ssl_errors)) obj.conn.process_ssl_errors() def on_cancel(): del self.instances[account]['online_dialog']['ssl_error'] obj.conn.disconnect(on_purpose=True) app.nec.push_incoming_event(OurShowEvent(None, conn=obj.conn, show='offline')) text = _('The authenticity of the %s ' 'certificate could be invalid') % server default_text = _('\nUnknown SSL error: %d') % obj.error_num ssl_error_text = SSLError.get(obj.error_num, default_text) text += _('\nSSL Error: %s') % ssl_error_text fingerprint_sha1 = obj.cert.digest('sha1').decode('utf-8') fingerprint_sha256 = obj.cert.digest('sha256').decode('utf-8') pritext = _('Error verifying SSL certificate') sectext = _('There was an error verifying the SSL certificate of your ' 'XMPP server: %(error)s\nDo you still want to connect to this ' 'server?') % {'error': text} if obj.error_num in (18, 27): checktext1 = _('Add this certificate to the list of trusted ' 'certificates.\nSHA-1 fingerprint of the certificate:\n%(sha1)s' '\nSHA-256 fingerprint of the certificate:\n%(sha256)s') % \ {'sha1': fingerprint_sha1, 'sha256': fingerprint_sha256} else: checktext1 = '' checktext2 = _('Ignore this error for this certificate.') if 'ssl_error' in self.instances[account]['online_dialog']: self.instances[account]['online_dialog']['ssl_error'].destroy() self.instances[account]['online_dialog']['ssl_error'] = \ SSLErrorDialog(obj.conn.name, obj.cert, pritext, sectext, checktext1, checktext2, on_response_ok=on_ok, on_response_cancel=on_cancel) self.instances[account]['online_dialog']['ssl_error'].set_title( _('SSL Certificate Verification for %s') % account) def handle_event_non_anonymous_server(self, obj): account = obj.conn.name server = app.config.get_per('accounts', account, 'hostname') ErrorDialog(_('Non Anonymous Server'), sectext='Server "%s"' 'does not support anonymous connection' % server, transient_for=self.roster.window) def handle_event_plain_connection(self, obj): # ('PLAIN_CONNECTION', account, (connection)) def on_ok(is_checked): if not is_checked[0]: if is_checked[1]: app.config.set_per('accounts', obj.conn.name, 'action_when_plaintext_connection', 'disconnect') on_cancel() return # On cancel call del self.instances, so don't call it another time # before del self.instances[obj.conn.name]['online_dialog']\ ['plain_connection'] if is_checked[1]: app.config.set_per('accounts', obj.conn.name, 'action_when_plaintext_connection', 'connect') obj.conn.connection_accepted(obj.xmpp_client, 'plain') def on_cancel(): del self.instances[obj.conn.name]['online_dialog']\ ['plain_connection'] obj.conn.disconnect(on_purpose=True) app.nec.push_incoming_event(OurShowEvent(None, conn=obj.conn, show='offline')) if 'plain_connection' in self.instances[obj.conn.name]['online_dialog']: self.instances[obj.conn.name]['online_dialog']['plain_connection'].\ destroy() self.instances[obj.conn.name]['online_dialog']['plain_connection'] = \ PlainConnectionDialog(obj.conn.name, on_ok, on_cancel) def handle_event_insecure_ssl_connection(self, obj): # ('INSECURE_SSL_CONNECTION', account, (connection, connection_type)) def on_ok(is_checked): if not is_checked[0]: on_cancel() return del self.instances[obj.conn.name]['online_dialog']['insecure_ssl'] if is_checked[1]: app.config.set_per('accounts', obj.conn.name, 'warn_when_insecure_ssl_connection', False) if obj.conn.connected == 0: # We have been disconnecting (too long time since window is # opened) # re-connect with auto-accept obj.conn.connection_auto_accepted = True show, msg = obj.conn.continue_connect_info[:2] self.roster.send_status(obj.conn.name, show, msg) return obj.conn.connection_accepted(obj.xmpp_client, obj.conn_type) def on_cancel(): del self.instances[obj.conn.name]['online_dialog']['insecure_ssl'] obj.conn.disconnect(on_purpose=True) app.nec.push_incoming_event(OurShowEvent(None, conn=obj.conn, show='offline')) pritext = _('Insecure connection') sectext = _('You are about to send your password on an insecure ' 'connection. You should install PyOpenSSL to prevent that. Are you ' 'sure you want to do that?') checktext1 = _('Yes, I really want to connect insecurely') checktext2 = _('_Do not ask me again') if 'insecure_ssl' in self.instances[obj.conn.name]['online_dialog']: self.instances[obj.conn.name]['online_dialog']['insecure_ssl'].\ destroy() self.instances[obj.conn.name]['online_dialog']['insecure_ssl'] = \ ConfirmationDialogDoubleCheck(pritext, sectext, checktext1, checktext2, on_response_ok=on_ok, on_response_cancel=on_cancel, is_modal=False) def handle_event_insecure_password(self, obj): # ('INSECURE_PASSWORD', account, ()) def on_ok(is_checked): if not is_checked[0]: on_cancel() return del self.instances[obj.conn.name]['online_dialog']\ ['insecure_password'] if is_checked[1]: app.config.set_per('accounts', obj.conn.name, 'warn_when_insecure_password', False) if obj.conn.connected == 0: # We have been disconnecting (too long time since window is # opened) # re-connect with auto-accept obj.conn.connection_auto_accepted = True show, msg = obj.conn.continue_connect_info[:2] self.roster.send_status(obj.conn.name, show, msg) return obj.conn.accept_insecure_password() def on_cancel(): del self.instances[obj.conn.name]['online_dialog']\ ['insecure_password'] obj.conn.disconnect(on_purpose=True) app.nec.push_incoming_event(OurShowEvent(None, conn=obj.conn, show='offline')) pritext = _('Insecure connection') sectext = _('You are about to send your password unencrypted on an ' 'insecure connection. Are you sure you want to do that?') checktext1 = _('Yes, I really want to connect insecurely') checktext2 = _('_Do not ask me again') if 'insecure_password' in self.instances[obj.conn.name]\ ['online_dialog']: self.instances[obj.conn.name]['online_dialog']\ ['insecure_password'].destroy() self.instances[obj.conn.name]['online_dialog']['insecure_password'] = \ ConfirmationDialogDoubleCheck(pritext, sectext, checktext1, checktext2, on_response_ok=on_ok, on_response_cancel=on_cancel, is_modal=False) def create_core_handlers_list(self): self.handlers = { 'DB_ERROR': [self.handle_event_db_error], 'FILE_SEND_ERROR': [self.handle_event_file_send_error], 'pep-received': [self.handle_atom_entry], 'bad-gpg-passphrase': [self.handle_event_bad_gpg_passphrase], 'bookmarks-received': [self.handle_event_bookmarks], 'client-cert-passphrase': [ self.handle_event_client_cert_passphrase], 'connection-lost': [self.handle_event_connection_lost], 'file-request-error': [self.handle_event_file_request_error], 'file-request-received': [self.handle_event_file_request], 'gc-invitation-received': [self.handle_event_gc_invitation], 'gc-decline-received': [self.handle_event_gc_decline], 'gc-presence-received': [self.handle_event_gc_presence], 'gpg-password-required': [self.handle_event_gpg_password_required], 'gpg-trust-key': [self.handle_event_gpg_trust_key], 'http-auth-received': [self.handle_event_http_auth], 'information': [self.handle_event_information], 'insecure-password': [self.handle_event_insecure_password], 'insecure-ssl-connection': \ [self.handle_event_insecure_ssl_connection], 'iq-error-received': [self.handle_event_iq_error], 'jingle-connected-received': [self.handle_event_jingle_connected], 'jingle-disconnected-received': [ self.handle_event_jingle_disconnected], 'jingle-error-received': [self.handle_event_jingle_error], 'jingle-request-received': [self.handle_event_jingle_incoming], 'jingleFT-cancelled-received': [self.handle_event_jingleft_cancel], 'message-error': [self.handle_event_msgerror], 'message-not-sent': [self.handle_event_msgnotsent], 'message-sent': [self.handle_event_msgsent], 'metacontacts-received': [self.handle_event_metacontacts], 'muc-admin-received': [self.handle_event_gc_affiliation], 'muc-owner-received': [self.handle_event_gc_config], 'oauth2-credentials-required': [self.handle_oauth2_credentials], 'our-show': [self.handle_event_status], 'password-required': [self.handle_event_password_required], 'plain-connection': [self.handle_event_plain_connection], 'presence-received': [self.handle_event_presence], 'roster-info': [self.handle_event_roster_info], 'roster-item-exchange-received': \ [self.handle_event_roster_item_exchange], 'signed-in': [self.handle_event_signed_in], 'ssl-error': [self.handle_event_ssl_error], 'non-anonymous-server-error': [self.handle_event_non_anonymous_server], 'stream-conflict-received': [self.handle_event_resource_conflict], 'subscribe-presence-received': [ self.handle_event_subscribe_presence], 'subscribed-presence-received': [ self.handle_event_subscribed_presence], 'unsubscribed-presence-received': [ self.handle_event_unsubscribed_presence], 'zeroconf-name-conflict': [self.handle_event_zc_name_conflict], } def register_core_handlers(self): """ Register core handlers in Global Events Dispatcher (GED). This is part of rewriting whole events handling system to use GED. """ for event_name, event_handlers in self.handlers.items(): for event_handler in event_handlers: prio = ged.GUI1 if isinstance(event_handler, tuple): prio = event_handler[1] event_handler = event_handler[0] app.ged.register_event_handler(event_name, prio, event_handler) ################################################################################ ### Methods dealing with app.events ################################################################################ def add_event(self, account, jid, event): """ Add an event to the app.events var """ # We add it to the app.events queue # Do we have a queue? jid = app.get_jid_without_resource(jid) no_queue = len(app.events.get_events(account, jid)) == 0 # event can be in common.events.* # event_type can be in advancedNotificationWindow.events_list event_types = {'file-request': 'ft_request', 'file-completed': 'ft_finished'} event_type = event_types.get(event.type_) show_in_roster = notify.get_show_in_roster(event_type, account, jid) show_in_systray = notify.get_show_in_systray(event_type, account, jid) event.show_in_roster = show_in_roster event.show_in_systray = show_in_systray app.events.add_event(account, jid, event) self.roster.show_title() if no_queue: # We didn't have a queue: we change icons if app.contacts.get_contact_with_highest_priority(account, jid): self.roster.draw_contact(jid, account) else: self.roster.add_to_not_in_the_roster(account, jid) # Select the big brother contact in roster, it's visible because it has # events. family = app.contacts.get_metacontacts_family(account, jid) if family: _nearby_family, bb_jid, bb_account = \ app.contacts.get_nearby_family_and_big_brother(family, account) else: bb_jid, bb_account = jid, account self.roster.select_contact(bb_jid, bb_account) def handle_event(self, account, fjid, type_): w = None ctrl = None resource = app.get_resource_from_jid(fjid) jid = app.get_jid_without_resource(fjid) if type_ == 'connection-lost': app.interface.roster.window.present() return if type_ in ('printed_gc_msg', 'printed_marked_gc_msg', 'gc_msg'): w = self.msg_win_mgr.get_window(jid, account) if jid in self.minimized_controls[account]: self.roster.on_groupchat_maximized(None, jid, account) return ctrl = self.msg_win_mgr.get_gc_control(jid, account) elif type_ in ('printed_chat', 'chat', ''): # '' is for log in/out notifications ctrl = self.msg_win_mgr.search_control(jid, account, resource) if not ctrl: highest_contact = app.contacts.\ get_contact_with_highest_priority(account, jid) # jid can have a window if this resource was lower when he sent # message and is now higher because the other one is offline if resource and highest_contact.resource == resource and \ not self.msg_win_mgr.has_window(jid, account): # remove resource of events too app.events.change_jid(account, fjid, jid) resource = None fjid = jid contact = None if resource: contact = app.contacts.get_contact(account, jid, resource) if not contact: contact = highest_contact if not contact: # Maybe we deleted the contact from the roster return ctrl = self.new_chat(contact, account, resource=resource) app.last_message_time[account][jid] = 0 # long time ago w = ctrl.parent_win elif type_ in ('printed_pm', 'pm'): ctrl = self.msg_win_mgr.get_control(fjid, account) if not ctrl: room_jid = jid nick = resource gc_contact = app.contacts.get_gc_contact( account, room_jid, nick) if gc_contact: show = gc_contact.show else: show = 'offline' gc_contact = app.contacts.create_gc_contact( room_jid=room_jid, account=account, name=nick, show=show) ctrl = self.new_private_chat(gc_contact, account) w = ctrl.parent_win elif type_ in ('normal', 'file-request', 'file-request-error', 'file-send-error', 'file-error', 'file-stopped', 'file-completed', 'file-hash-error', 'jingle-incoming'): # Get the first single message event event = app.events.get_first_event(account, fjid, type_) if not event: # default to jid without resource event = app.events.get_first_event(account, jid, type_) if not event: return # Open the window self.roster.open_event(account, jid, event) else: # Open the window self.roster.open_event(account, fjid, event) elif type_ == 'gc-invitation': event = app.events.get_first_event(account, jid, type_) if event is None: return dialogs.InvitationReceivedDialog(account, event.room_jid, jid, event.password, event.reason, event.is_continued) app.events.remove_events(account, jid, event) self.roster.draw_contact(jid, account) elif type_ == 'subscription_request': event = app.events.get_first_event(account, jid, type_) if event is None: return dialogs.SubscriptionRequestWindow(jid, event.text, account, event.nick) app.events.remove_events(account, jid, event) self.roster.draw_contact(jid, account) elif type_ == 'unsubscribed': event = app.events.get_first_event(account, jid, type_) if event is None: return self.show_unsubscribed_dialog(account, event.contact) app.events.remove_events(account, jid, event) self.roster.draw_contact(jid, account) if w: w.set_active_tab(ctrl) w.window.present() # Using isinstance here because we want to catch all derived types if isinstance(ctrl, ChatControlBase): ctrl.scroll_to_end() def join_gc_minimal(self, account, room_jid, password=None, transient_for=None): if account is not None: if app.in_groupchat(account, room_jid): # If we already in the groupchat, join_gc_room will bring # it to front app.interface.join_gc_room(account, room_jid, '', '') return con = app.connections[account] bookmarks = con.get_module('Bookmarks').bookmarks bookmark = bookmarks.get(room_jid, None) if bookmark is not None: app.interface.join_gc_room( account, room_jid, bookmark['nick'], bookmark['password']) return try: room_jid = helpers.parse_jid(room_jid) except helpers.InvalidFormat: ErrorDialog('Invalid JID', transient_for=app.app.get_active_window()) return connected_accounts = app.get_connected_accounts() if account is not None and account not in connected_accounts: connected_accounts = None if not connected_accounts: ErrorDialog( _('You are not connected to the server'), _('You can not join a group chat unless you are connected.'), transient_for=app.app.get_active_window()) return def _on_discover_result(): if not muc_caps_cache.is_cached(room_jid): ErrorDialog(_('JID is not a Groupchat'), transient_for=app.app.get_active_window()) return JoinGroupchatWindow(account, room_jid, password=password, transient_for=transient_for) disco_account = connected_accounts[0] if account is None else account app.connections[disco_account].get_module('Discovery').disco_muc( room_jid, _on_discover_result) ################################################################################ ### Methods dealing with emoticons ################################################################################ @property def basic_pattern_re(self): if not self._basic_pattern_re: self._basic_pattern_re = re.compile(self.basic_pattern, re.IGNORECASE) return self._basic_pattern_re @property def emot_and_basic_re(self): if not self._emot_and_basic_re: self._emot_and_basic_re = re.compile( self.emot_and_basic, re.IGNORECASE) return self._emot_and_basic_re @property def sth_at_sth_dot_sth_re(self): if not self._sth_at_sth_dot_sth_re: self._sth_at_sth_dot_sth_re = re.compile(self.sth_at_sth_dot_sth) return self._sth_at_sth_dot_sth_re @property def invalid_XML_chars_re(self): if not self._invalid_XML_chars_re: self._invalid_XML_chars_re = re.compile(self.invalid_XML_chars) return self._invalid_XML_chars_re def make_regexps(self): # regexp meta characters are: . ^ $ * + ? { } [ ] \ | ( ) # one escapes the metachars with \ # \S matches anything but ' ' '\t' '\n' '\r' '\f' and '\v' # \s matches any whitespace character # \w any alphanumeric character # \W any non-alphanumeric character # \b means word boundary. This is a zero-width assertion that # matches only at the beginning or end of a word. # ^ matches at the beginning of lines # # * means 0 or more times # + means 1 or more times # ? means 0 or 1 time # | means or # [^*] anything but '*' (inside [] you don't have to escape metachars) # [^\s*] anything but whitespaces and '*' # (? in the matching string don't match ? or ) etc.. if at # the end # so http://be) will match http://be and http://be)be) will match # http://be)be self._basic_pattern_re = None self._emot_and_basic_re = None self._sth_at_sth_dot_sth_re = None self._invalid_XML_chars_re = None legacy_prefixes = r"((?<=\()(www|ftp)\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$"\ r"&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+(?=\)))"\ r"|((www|ftp)\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]"\ r"|%[A-Fa-f0-9]{2})+"\ r"\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+)" # NOTE: it's ok to catch www.gr such stuff exist! # FIXME: recognize xmpp: and treat it specially links = r"((?<=\()[A-Za-z][A-Za-z0-9\+\.\-]*:"\ r"([\w\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+"\ r"(?=\)))|(\w[\w\+\.\-]*:([^<>\s]|%[A-Fa-f0-9]{2})+)" # 2nd one: at_least_one_char@at_least_one_char.at_least_one_char mail = r'\bmailto:\S*[^\s\W]|' r'\b\S+@\S+\.\S*[^\s\W]' # detects eg. *b* *bold* *bold bold* test *bold* *bold*! (*bold*) # doesn't detect (it's a feature :P) * bold* *bold * * bold * test*bold* formatting = r'|(? AvatarSize.PUBLISH or height > AvatarSize.PUBLISH: # Scale only down, never up width, height = gtkgui_helpers.scale_with_ratio( AvatarSize.PUBLISH, width, height) pixbuf = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.BILINEAR) publish_path = os.path.join( configpaths.get('AVATAR'), 'temp_publish') pixbuf.savev(publish_path, 'png', [], []) with open(publish_path, 'rb') as file: data = file.read() return self.save_avatar(data) sha = hashlib.sha1(data).hexdigest() path = os.path.join(configpaths.get('AVATAR'), sha) try: with open(path, "wb") as output_file: output_file.write(data) except Exception: app.log('avatar').error('Saving avatar failed', exc_info=True) return return sha @staticmethod def get_avatar(filename, size=None, scale=None, publish=False): if filename is None or '': return if size is None and scale is not None: raise ValueError if scale is not None: size = size * scale if publish: path = os.path.join(configpaths.get('AVATAR'), filename) with open(path, 'rb') as file: data = file.read() return data try: pixbuf = app.avatar_cache[filename][size] if scale is None: return pixbuf return Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale) except KeyError: pass path = os.path.join(configpaths.get('AVATAR'), filename) if not os.path.isfile(path): return pixbuf = None try: if size is not None: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale( path, size, size, True) else: pixbuf = GdkPixbuf.Pixbuf.new_from_file(path) except GLib.GError: app.log('avatar').info( 'loading avatar %s failed. Try to convert ' 'avatar image using pillow', filename) try: with open(path, 'rb') as im_handle: img = Image.open(im_handle) avatar = img.convert("RGBA") except (NameError, OSError): app.log('avatar').warning('Pillow convert failed: %s', filename) app.log('avatar').debug('Error', exc_info=True) return array = GLib.Bytes.new(avatar.tobytes()) width, height = avatar.size pixbuf = GdkPixbuf.Pixbuf.new_from_bytes( array, GdkPixbuf.Colorspace.RGB, True, 8, width, height, width * 4) if size: width, height = gtkgui_helpers.scale_with_ratio( size, width, height) pixbuf = pixbuf.scale_simple( width, height, GdkPixbuf.InterpType.BILINEAR) if filename not in app.avatar_cache: app.avatar_cache[filename] = {} app.avatar_cache[filename][size] = pixbuf if scale is None: return pixbuf return Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale) @staticmethod def avatar_exists(filename): path = os.path.join(configpaths.get('AVATAR'), filename) if not os.path.isfile(path): return False return True # does JID exist only within a groupchat? def is_pm_contact(self, fjid, account): bare_jid = app.get_jid_without_resource(fjid) gc_ctrl = self.msg_win_mgr.get_gc_control(bare_jid, account) if not gc_ctrl and \ bare_jid in self.minimized_controls[account]: gc_ctrl = self.minimized_controls[account][bare_jid] return gc_ctrl and gc_ctrl.type_id == message_control.TYPE_GC @staticmethod def get_pep_icon(pep_obj): if pep_obj == PEPEventType.MOOD: received_mood = pep_obj.data['mood'] mood = received_mood if received_mood in MOODS else 'unknown' return gtkgui_helpers.load_mood_icon(mood).get_pixbuf() if pep_obj == PEPEventType.TUNE: path = os.path.join( configpaths.get('DATA'), 'emoticons', 'static', 'music.png') return GdkPixbuf.Pixbuf.new_from_file(path) if pep_obj == PEPEventType.ACTIVITY: pep_ = pep_obj.data activity = pep_['activity'] has_known_activity = activity in ACTIVITIES has_known_subactivity = (has_known_activity and 'subactivity' in pep_ and pep_['subactivity'] in ACTIVITIES[activity]) if has_known_activity: if has_known_subactivity: subactivity = pep_['subactivity'] return gtkgui_helpers.load_activity_icon( activity, subactivity).get_pixbuf() return gtkgui_helpers.load_activity_icon(activity).get_pixbuf() return gtkgui_helpers.load_activity_icon('unknown').get_pixbuf() if pep_obj == PEPEventType.LOCATION: icon = gtkgui_helpers.get_icon_pixmap( 'applications-internet', quiet=True) return icon @staticmethod def create_ipython_window(): try: from gajim.dev.ipython_view import IPythonView except ImportError: print('ipython_view not found') return from gi.repository import Pango if os.name == 'nt': font = 'Lucida Console 9' else: font = 'Luxi Mono 10' window = Gtk.Window() window.set_size_request(750, 550) window.set_resizable(True) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) view = IPythonView() view.override_font(Pango.FontDescription(font)) view.set_wrap_mode(Gtk.WrapMode.CHAR) sw.add(view) window.add(sw) window.show_all() def on_delete(win, event): win.hide() return True window.connect('delete_event', on_delete) view.updateNamespace({'gajim': app}) app.ipython_window = window def network_status_changed(self, monitor, connected): if connected == self.network_state: # This callback gets called a lot from GTK with the # same state, not only on change. return self.network_state = connected log.debug('NetworkMonitor state change: %s', connected) if connected: for connection in app.connections.values(): if connection.connected <= 0 and connection.time_to_reconnect: log.info('Connect %s', connection.name) connection.reconnect() else: for connection in app.connections.values(): if connection.connected > 1: log.info('Disconnect %s', connection.name) connection.disconnectedReconnCB() def create_zeroconf_default_config(self): if app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'name'): return log.info('Creating zeroconf account') app.config.add_per('accounts', app.ZEROCONF_ACC_NAME) app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'autoconnect', True) app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'no_log_for', '') app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'password', 'zeroconf') app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'sync_with_global_status', True) app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'custom_port', 5298) app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'is_zeroconf', True) app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'use_ft_proxies', False) app.config.set_per('accounts', app.ZEROCONF_ACC_NAME, 'active', False) def run(self, application): if app.config.get('trayicon') != 'never': self.show_systray() self.roster = roster_window.RosterWindow(application) if self.msg_win_mgr.mode == \ MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: self.msg_win_mgr.create_window(None, None, None) # Creating plugin manager from gajim import plugins app.plugin_manager = plugins.PluginManager() app.plugin_manager.init_plugins() helpers.update_optional_features() # prepopulate data which we are sure of; note: we do not log these info for account in app.connections: gajimcaps = caps_cache.capscache[ ('sha-1', app.caps_hash[account])] gajimcaps.identities = [app.gajim_identity] gajimcaps.features = app.gajim_common_features + \ app.gajim_optional_features[account] self.roster._before_fill() for account in app.connections: app.connections[account].get_module('Roster').load_roster() self.roster._after_fill() # get instances for windows/dialogs that will show_all()/hide() self.instances['file_transfers'] = FileTransfersWindow() GLib.timeout_add(100, self.autoconnect) if sys.platform == 'win32': timeout, in_seconds = 20, None else: timeout, in_seconds = app.idlequeue.PROCESS_TIMEOUT if in_seconds: GLib.timeout_add_seconds(timeout, self.process_connections) else: GLib.timeout_add(timeout, self.process_connections) GLib.timeout_add_seconds(app.config.get( 'check_idle_every_foo_seconds'), self.read_sleepy) def remote_init(): if app.config.get('remote_control'): try: from gajim import remote_control remote_control.GajimRemote() except Exception: pass GLib.timeout_add_seconds(5, remote_init) def __init__(self): app.interface = self app.thread_interface = ThreadInterface # This is the manager and factory of message windows set by the module self.msg_win_mgr = None self.jabber_state_images = {'16': {}, '24': {}, '32': {}, 'opened': {}, 'closed': {}} self.minimized_controls = {} self.status_sent_to_users = {} self.status_sent_to_groups = {} self.gpg_passphrase = {} self.pass_dialog = {} self.db_error_dialog = None self.handlers = {} self.roster = None self._invalid_XML_chars_re = None self._basic_pattern_re = None self._emot_and_basic_re = None self._sth_at_sth_dot_sth_re = None self.link_pattern_re = None self.invalid_XML_chars = None self.basic_pattern = None self.emot_and_basic = None self.sth_at_sth_dot_sth = None cfg_was_read = parser.read() if not cfg_was_read: # enable plugin_installer by default when creating config file app.config.set_per('plugins', 'plugin_installer', 'active', True) # Load CSS files app.load_css_config() app.logger.reset_shown_unread_messages() # override logging settings from config (don't take care of '-q' option) if app.config.get('verbose'): logging_helpers.set_verbose() for account in app.config.get_per('accounts'): if app.config.get_per('accounts', account, 'is_zeroconf'): app.ZEROCONF_ACC_NAME = account break # Is gnome configured to activate row on single click ? # try: # gi.require_version('GConf', '2.0') # from gi.repository import GConf # client = GConf.Client.get_default() # click_policy = client.get_string( # '/apps/nautilus/preferences/click_policy') # if click_policy == 'single': # app.single_click = True # except Exception: # pass # add default status messages if there is not in the config file if not app.config.get_per('statusmsg'): default = app.config.statusmsg_default for msg in default: app.config.add_per('statusmsg', msg) app.config.set_per('statusmsg', msg, 'message', default[msg][0]) app.config.set_per('statusmsg', msg, 'activity', default[msg][1]) app.config.set_per('statusmsg', msg, 'subactivity', default[msg][2]) app.config.set_per('statusmsg', msg, 'activity_text', default[msg][3]) app.config.set_per('statusmsg', msg, 'mood', default[msg][4]) app.config.set_per('statusmsg', msg, 'mood_text', default[msg][5]) # Add Tor proxy if there is not in the config if not app.config.get_per('proxies'): default = app.config.proxies_default for proxy in default: app.config.add_per('proxies', proxy) app.config.set_per('proxies', proxy, 'type', default[proxy][0]) app.config.set_per('proxies', proxy, 'host', default[proxy][1]) app.config.set_per('proxies', proxy, 'port', default[proxy][2]) app.idlequeue = idlequeue.get_idlequeue() # resolve and keep current record of resolved hosts app.resolver = resolver.get_resolver() app.socks5queue = socks5.SocksQueue(app.idlequeue, self.handle_event_file_rcv_completed, self.handle_event_file_progress, self.handle_event_file_error) app.proxy65_manager = proxy65_manager.Proxy65Manager(app.idlequeue) app.default_session_type = ChatControlSession # Creating Network Events Controller from gajim.common import nec app.nec = nec.NetworkEventsController() app.notification = notify.Notification() self.create_core_handlers_list() self.register_core_handlers() self.create_zeroconf_default_config() if app.config.get_per('accounts', app.ZEROCONF_ACC_NAME, 'active') \ and app.is_installed('ZEROCONF'): app.connections[app.ZEROCONF_ACC_NAME] = \ connection_zeroconf.ConnectionZeroconf(app.ZEROCONF_ACC_NAME) for account in app.config.get_per('accounts'): if not app.config.get_per('accounts', account, 'is_zeroconf') and\ app.config.get_per('accounts', account, 'active'): app.connections[account] = Connection(account) # gtk hooks # Gtk.about_dialog_set_email_hook(self.on_launch_browser_mailer, 'mail') # Gtk.about_dialog_set_url_hook(self.on_launch_browser_mailer, 'url') # Gtk.link_button_set_uri_hook(self.on_launch_browser_mailer, 'url') self.instances = {} for a in app.connections: self.instances[a] = {'infos': {}, 'disco': {}, 'gc_config': {}, 'search': {}, 'online_dialog': {}, 'sub_request': {}} # online_dialog contains all dialogs that have a meaning only when # we are not disconnected self.minimized_controls[a] = {} app.contacts.add_account(a) app.groups[a] = {} app.gc_connected[a] = {} app.automatic_rooms[a] = {} app.newly_added[a] = [] app.to_be_removed[a] = [] app.nicks[a] = app.config.get_per('accounts', a, 'name') app.block_signed_in_notifications[a] = True app.sleeper_state[a] = 0 app.last_message_time[a] = {} app.status_before_autoaway[a] = '' app.gajim_optional_features[a] = [] app.caps_hash[a] = '' self.remote_ctrl = None # Handle screensaver if sys.platform not in ('win32', 'darwin'): logind.enable() screensaver.enable() self.show_vcard_when_connect = [] idle.Monitor.set_interval(app.config.get('autoawaytime') * 60, app.config.get('autoxatime') * 60) gtkgui_helpers.make_jabber_state_images() self.systray_enabled = False from gajim import statusicon self.systray = statusicon.StatusIcon() pixs = [] for size in (16, 32, 48, 64, 128): pix = gtkgui_helpers.get_icon_pixmap('org.gajim.Gajim', size) if pix: pixs.append(pix) if pixs: # set the icon to all windows Gtk.Window.set_default_icon_list(pixs) # Init emoji_chooser from gajim.gtk.emoji_chooser import emoji_chooser emoji_chooser.load() self.make_regexps() # get transports type from DB app.transport_type = app.logger.get_transports_type() helpers.find_soundplayer() self.last_ftwindow_update = 0 self.music_track_changed_signal = None self.network_monitor = Gio.NetworkMonitor.get_default() self.network_monitor.connect('network-changed', self.network_status_changed) self.network_state = self.network_monitor.get_network_available() class PassphraseRequest: def __init__(self, keyid): self.keyid = keyid self.callbacks = [] self.dialog_created = False self.dialog = None self.passphrase = None self.completed = False def interrupt(self, account=None): if account: for (acct, cb) in self.callbacks: if acct == account: self.callbacks.remove((acct, cb)) else: self.callbacks = [] if not self.callbacks: self.dialog.window.destroy() def run_callback(self, account, callback): app.connections[account].gpg_passphrase(self.passphrase) callback() def add_callback(self, account, cb): if self.completed: self.run_callback(account, cb) else: self.callbacks.append((account, cb)) if not self.dialog_created: self.create_dialog(account) def complete(self, passphrase): self.passphrase = passphrase self.completed = True if passphrase is not None: GLib.timeout_add_seconds(30, app.interface.forget_gpg_passphrase, self.keyid) for (account, cb) in self.callbacks: self.run_callback(account, cb) self.callbacks = [] def create_dialog(self, account): title = _('Passphrase Required') second = _('Enter OpenPGP key passphrase for key %(keyid)s ' '(account %(account)s).') % {'keyid': self.keyid, 'account': account} def _cancel(): # user cancelled, continue without GPG self.complete(None) def _ok(passphrase, checked, count): result = app.connections[account].test_gpg_passphrase(passphrase) if result == 'ok': # passphrase is good self.complete(passphrase) return if result == 'expired': ErrorDialog( _('OpenPGP key expired'), _('Your OpenPGP key has expired, you will be connected to ' '%s without OpenPGP.') % account) # Don't try to connect with GPG app.connections[account].continue_connect_info[2] = False self.complete(None) return if count < 3: # ask again dialogs.PassphraseDialog( _('Wrong Passphrase'), _('Please retype your OpenPGP passphrase or press Cancel.'), ok_handler=(_ok, count + 1), cancel_handler=_cancel) else: # user failed 3 times, continue without GPG self.complete(None) self.dialog = dialogs.PassphraseDialog( title, second, ok_handler=(_ok, 1), cancel_handler=_cancel) self.dialog_created = True class ThreadInterface: def __init__(self, func, func_args=(), callback=None, callback_args=()): """ Call a function in a thread """ def thread_function(func, func_args, callback, callback_args): output = func(*func_args) if callback: GLib.idle_add(callback, output, *callback_args) Thread(target=thread_function, args=(func, func_args, callback, callback_args)).start() gajim-gajim-1.1.3/gajim/gui_menu_builder.py000066400000000000000000001060671345766322700207000ustar00rootroot00000000000000# Copyright (C) 2009-2014 Yann Leboulanger # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gtk, Gio, GLib from nbxmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC from nbxmpp.protocol import NS_JINGLE_FILE_TRANSFER_5, NS_CONFERENCE from gajim import gtkgui_helpers from gajim import message_control from gajim.gtkgui_helpers import get_action from gajim.common import app from gajim.common import helpers from gajim.common.i18n import ngettext from gajim.common.i18n import _ def build_resources_submenu(contacts, account, action, room_jid=None, room_account=None, cap=None): """ Build a submenu with contact's resources. room_jid and room_account are for action self.on_invite_to_room """ roster = app.interface.roster sub_menu = Gtk.Menu() iconset = app.config.get('iconset') if not iconset: iconset = app.config.DEFAULT_ICONSET for c in contacts: item = Gtk.MenuItem.new_with_label( '%s (%s)' % (c.resource, str(c.priority))) sub_menu.append(item) if action == roster.on_invite_to_room: item.connect('activate', action, [(c, account)], room_jid, room_account, c.resource) elif action == roster.on_invite_to_new_room: item.connect('activate', action, [(c, account)], c.resource) else: # start_chat, execute_command, send_file item.connect('activate', action, c, account, c.resource) if cap and not c.supports(cap): item.set_sensitive(False) return sub_menu def build_invite_submenu(invite_menuitem, list_, ignore_rooms=None, show_bookmarked=False, force_resource=False): """ list_ in a list of (contact, account) force_resource means we want to send invitation even if there is only one resource """ if ignore_rooms is None: ignore_rooms = [] roster = app.interface.roster # used if we invite only one contact with several resources contact_list = [] if len(list_) == 1: contact, account = list_[0] contact_list = app.contacts.get_contacts(account, contact.jid) contacts_transport = -1 connected_accounts = [] # -1 is at start, False when not from the same, None when jabber for (contact, account) in list_: if not account in connected_accounts: connected_accounts.append(account) transport = app.get_transport_name_from_jid(contact.jid) if transport == 'jabber': transport = None if contacts_transport == -1: contacts_transport = transport elif contacts_transport != transport: contacts_transport = False if contacts_transport is False: # they are not all from the same transport invite_menuitem.set_sensitive(False) return invite_to_submenu = Gtk.Menu() invite_menuitem.set_submenu(invite_to_submenu) invite_to_new_room_menuitem = Gtk.MenuItem.new_with_mnemonic(_( '_New Group Chat')) if len(contact_list) > 1: # several resources invite_to_new_room_menuitem.set_submenu(build_resources_submenu( contact_list, account, roster.on_invite_to_new_room, cap=NS_MUC)) elif len(list_) == 1 and contact.supports(NS_MUC): invite_menuitem.set_sensitive(True) # use resource if it's self contact if contact.jid == app.get_jid_from_account(account) or force_resource: resource = contact.resource else: resource = None invite_to_new_room_menuitem.connect('activate', roster.on_invite_to_new_room, list_, resource) elif len(list_) > 1: list2 = [] for (c, a) in list_: if c.supports(NS_MUC): list2.append((c, a)) if list2: invite_to_new_room_menuitem.connect('activate', roster.on_invite_to_new_room, list2, None) else: invite_menuitem.set_sensitive(False) else: invite_menuitem.set_sensitive(False) # transform None in 'jabber' c_t = contacts_transport or 'jabber' muc_jid = {} for account in connected_accounts: for t in app.connections[account].muc_jid: muc_jid[t] = app.connections[account].muc_jid[t] if c_t not in muc_jid: invite_to_new_room_menuitem.set_sensitive(False) rooms = [] # a list of (room_jid, account) tuple invite_to_submenu.append(invite_to_new_room_menuitem) minimized_controls = [] for account in connected_accounts: minimized_controls += \ list(app.interface.minimized_controls[account].values()) for gc_control in app.interface.msg_win_mgr.get_controls( message_control.TYPE_GC) + minimized_controls: acct = gc_control.account if acct not in connected_accounts: continue room_jid = gc_control.room_jid if room_jid in ignore_rooms: continue if room_jid in app.gc_connected[acct] and \ app.gc_connected[acct][room_jid] and \ contacts_transport in ['jabber', None]: rooms.append((room_jid, acct)) if rooms: item = Gtk.SeparatorMenuItem.new() # separator invite_to_submenu.append(item) for (room_jid, account) in rooms: menuitem = Gtk.MenuItem.new_with_label(room_jid.split('@')[0]) if len(contact_list) > 1: # several resources menuitem.set_submenu(build_resources_submenu( contact_list, account, roster.on_invite_to_room, room_jid, account)) else: # use resource if it's self contact if contact.jid == app.get_jid_from_account(account): resource = contact.resource else: resource = None menuitem.connect('activate', roster.on_invite_to_room, list_, room_jid, account, resource) invite_to_submenu.append(menuitem) if not show_bookmarked: return rooms2 = [] # a list of (room_jid, account) tuple r_jids = [] # list of room jids for account in connected_accounts: con = app.connections[account] boomarks = con.get_module('Bookmarks').bookmarks for jid in boomarks.keys(): if jid in r_jids: continue if jid not in app.gc_connected[account] or not \ app.gc_connected[account][jid]: rooms2.append((jid, account)) r_jids.append(jid) if not rooms2: return item = Gtk.SeparatorMenuItem.new() # separator invite_to_submenu.append(item) for (room_jid, account) in rooms2: menuitem = Gtk.MenuItem.new_with_label(room_jid.split('@')[0]) if len(contact_list) > 1: # several resources menuitem.set_submenu(build_resources_submenu( contact_list, account, roster.on_invite_to_room, room_jid, account)) else: # use resource if it's self contact if contact.jid == app.get_jid_from_account(account): resource = contact.resource else: resource = None menuitem.connect('activate', roster.on_invite_to_room, list_, room_jid, account, resource) invite_to_submenu.append(menuitem) def get_contact_menu(contact, account, use_multiple_contacts=True, show_start_chat=True, show_encryption=False, show_buttonbar_items=True, control=None, gc_contact=None, is_anonymous=True): """ Build contact popup menu for roster and chat window. If control is not set, we hide invite_contacts_menuitem """ if not contact: return jid = contact.jid our_jid = jid == app.get_jid_from_account(account) roster = app.interface.roster xml = gtkgui_helpers.get_gtk_builder('contact_context_menu.ui') contact_context_menu = xml.get_object('contact_context_menu') start_chat_menuitem = xml.get_object('start_chat_menuitem') execute_command_menuitem = xml.get_object('execute_command_menuitem') rename_menuitem = xml.get_object('rename_menuitem') edit_groups_menuitem = xml.get_object('edit_groups_menuitem') send_file_menuitem = xml.get_object('send_file_menuitem') assign_openpgp_key_menuitem = xml.get_object('assign_openpgp_key_menuitem') information_menuitem = xml.get_object('information_menuitem') history_menuitem = xml.get_object('history_menuitem') send_custom_status_menuitem = xml.get_object('send_custom_status_menuitem') send_single_message_menuitem = xml.get_object('send_single_message_menuitem') invite_menuitem = xml.get_object('invite_menuitem') block_menuitem = xml.get_object('block_menuitem') unblock_menuitem = xml.get_object('unblock_menuitem') ignore_menuitem = xml.get_object('ignore_menuitem') unignore_menuitem = xml.get_object('unignore_menuitem') # Subscription submenu subscription_menuitem = xml.get_object('subscription_menuitem') send_auth_menuitem, ask_auth_menuitem, revoke_auth_menuitem = \ subscription_menuitem.get_submenu().get_children() add_to_roster_menuitem = xml.get_object('add_to_roster_menuitem') remove_from_roster_menuitem = xml.get_object( 'remove_from_roster_menuitem') manage_contact_menuitem = xml.get_object('manage_contact') convert_to_gc_menuitem = xml.get_object('convert_to_groupchat_menuitem') last_separator = xml.get_object('last_separator') items_to_hide = [] contacts = app.contacts.get_contacts(account, jid) if len(contacts) > 1 and use_multiple_contacts: # several resources start_chat_menuitem.set_submenu(build_resources_submenu(contacts, account, app.interface.on_open_chat_window)) send_file_menuitem.set_submenu(build_resources_submenu(contacts, account, roster.on_send_file_menuitem_activate, cap=NS_FILE)) execute_command_menuitem.set_submenu(build_resources_submenu( contacts, account, roster.on_execute_command, cap=NS_COMMANDS)) else: start_chat_menuitem.connect('activate', app.interface.on_open_chat_window, contact, account) if contact.supports(NS_FILE) or contact.supports(NS_JINGLE_FILE_TRANSFER_5): send_file_menuitem.set_sensitive(True) send_file_menuitem.connect('activate', roster.on_send_file_menuitem_activate, contact, account) else: send_file_menuitem.set_sensitive(False) if contact.supports(NS_COMMANDS): execute_command_menuitem.set_sensitive(True) if gc_contact and gc_contact.jid and not is_anonymous: execute_command_menuitem.connect('activate', roster.on_execute_command, gc_contact, account, gc_contact.resource) else: execute_command_menuitem.connect('activate', roster.on_execute_command, contact, account, contact.resource) else: execute_command_menuitem.set_sensitive(False) rename_menuitem.connect('activate', roster.on_rename, 'contact', jid, account) history_menuitem.connect('activate', roster.on_history, contact, account) if control: convert_to_gc_menuitem.connect('activate', control._on_convert_to_gc_menuitem_activate) else: items_to_hide.append(convert_to_gc_menuitem) if _('Not in Roster') not in contact.get_shown_groups(): # contact is in normal group edit_groups_menuitem.connect('activate', roster.on_edit_groups, [(contact, account)]) if app.connections[account].gpg: assign_openpgp_key_menuitem.connect('activate', roster.on_assign_pgp_key, contact, account) else: assign_openpgp_key_menuitem.set_sensitive(False) else: # contact is in group 'Not in Roster' edit_groups_menuitem.set_sensitive(False) assign_openpgp_key_menuitem.set_sensitive(False) # Hide items when it's self contact row if our_jid: items_to_hide += [rename_menuitem, edit_groups_menuitem] # Unsensitive many items when account is offline if app.account_is_disconnected(account): for widget in (start_chat_menuitem, rename_menuitem, edit_groups_menuitem, send_file_menuitem, convert_to_gc_menuitem, information_menuitem): widget.set_sensitive(False) if not show_start_chat: items_to_hide.append(start_chat_menuitem) if not show_buttonbar_items: items_to_hide += [history_menuitem, send_file_menuitem, information_menuitem, convert_to_gc_menuitem, last_separator] if not control: items_to_hide.append(convert_to_gc_menuitem) # Hide items when it's a pm if gc_contact: items_to_hide += [rename_menuitem, edit_groups_menuitem, subscription_menuitem, remove_from_roster_menuitem] for item in items_to_hide: item.set_no_show_all(True) item.hide() # Zeroconf Account if app.config.get_per('accounts', account, 'is_zeroconf'): for item in (send_custom_status_menuitem, send_single_message_menuitem, invite_menuitem, block_menuitem, unblock_menuitem, ignore_menuitem, unignore_menuitem, subscription_menuitem, manage_contact_menuitem, convert_to_gc_menuitem): item.set_no_show_all(True) item.hide() if contact.show in ('offline', 'error'): information_menuitem.set_sensitive(False) send_file_menuitem.set_sensitive(False) else: information_menuitem.connect('activate', roster.on_info_zeroconf, contact, account) contact_context_menu.connect('selection-done', gtkgui_helpers.destroy_widget) contact_context_menu.show_all() return contact_context_menu # normal account # send custom status icon blocked = False if helpers.jid_is_blocked(account, jid): blocked = True else: for group in contact.get_shown_groups(): if helpers.group_is_blocked(account, group): blocked = True break transport = app.get_transport_name_from_jid(jid, use_config_setting=False) if transport and transport != 'jabber': # Transport contact, send custom status unavailable send_custom_status_menuitem.set_sensitive(False) elif blocked: send_custom_status_menuitem.set_sensitive(False) if gc_contact: if not gc_contact.jid: # it's a pm and we don't know real JID invite_menuitem.set_sensitive(False) else: bookmarked = False c_ = app.contacts.get_contact(account, gc_contact.jid, gc_contact.resource) if c_ and c_.supports(NS_CONFERENCE): bookmarked = True build_invite_submenu(invite_menuitem, [(gc_contact, account)], show_bookmarked=bookmarked) else: force_resource = False if control and control.resource: force_resource = True build_invite_submenu(invite_menuitem, [(contact, account)], show_bookmarked=contact.supports(NS_CONFERENCE), force_resource=force_resource) if app.account_is_disconnected(account): invite_menuitem.set_sensitive(False) # One or several resource, we do the same for send_custom_status status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): # icon MUST be different instance for every item status_menuitem = Gtk.MenuItem.new_with_label(helpers.get_uf_show(s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) status_menuitems.append(status_menuitem) send_single_message_menuitem.connect('activate', roster.on_send_single_message_menuitem_activate, account, contact) remove_from_roster_menuitem.connect('activate', roster.on_req_usub, [(contact, account)]) information_menuitem.connect('activate', roster.on_info, contact, account) if _('Not in Roster') not in contact.get_shown_groups(): # contact is in normal group add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) if contact.sub in ('from', 'both'): send_auth_menuitem.set_sensitive(False) else: send_auth_menuitem.connect('activate', roster.authorize, jid, account) if contact.sub in ('to', 'both'): ask_auth_menuitem.set_sensitive(False) else: ask_auth_menuitem.connect('activate', roster.req_sub, jid, _('I would like to add you to my roster'), account, contact.groups, contact.name) transport = app.get_transport_name_from_jid(jid, use_config_setting=False) if contact.sub in ('to', 'none') or transport not in ['jabber', None]: revoke_auth_menuitem.set_sensitive(False) else: revoke_auth_menuitem.connect('activate', roster.revoke_auth, jid, account) elif app.connections[account].roster_supported: # contact is in group 'Not in Roster' add_to_roster_menuitem.set_no_show_all(False) subscription_menuitem.set_sensitive(False) add_to_roster_menuitem.connect('activate', roster.on_add_to_roster, contact, account) else: add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) subscription_menuitem.set_sensitive(False) # Hide items when it's self contact row if our_jid: manage_contact_menuitem.set_sensitive(False) # Unsensitive items when account is offline if app.account_is_disconnected(account): for widget in (send_single_message_menuitem, subscription_menuitem, add_to_roster_menuitem, remove_from_roster_menuitem, execute_command_menuitem, send_custom_status_menuitem): widget.set_sensitive(False) con = app.connections[account] if con and (con.get_module('PrivacyLists').supported or con.get_module('Blocking').supported): if helpers.jid_is_blocked(account, jid): block_menuitem.set_no_show_all(True) block_menuitem.hide() if app.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': unblock_menuitem.set_no_show_all(True) unblock_menuitem.hide() unignore_menuitem.set_no_show_all(False) unignore_menuitem.connect('activate', roster.on_unblock, [(contact, account)]) else: unblock_menuitem.connect('activate', roster.on_unblock, [(contact, account)]) else: unblock_menuitem.set_no_show_all(True) unblock_menuitem.hide() if app.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': block_menuitem.set_no_show_all(True) block_menuitem.hide() ignore_menuitem.set_no_show_all(False) ignore_menuitem.connect('activate', roster.on_block, [(contact, account)]) else: block_menuitem.connect('activate', roster.on_block, [(contact, account)]) else: unblock_menuitem.set_no_show_all(True) block_menuitem.set_sensitive(False) unblock_menuitem.hide() contact_context_menu.connect('selection-done', gtkgui_helpers.destroy_widget) contact_context_menu.show_all() return contact_context_menu def get_transport_menu(contact, account): roster = app.interface.roster jid = contact.jid menu = Gtk.Menu() # Send single message item = Gtk.MenuItem.new_with_mnemonic(_('Send Single _Message…')) item.connect('activate', roster.on_send_single_message_menuitem_activate, account, contact) menu.append(item) if app.account_is_disconnected(account): item.set_sensitive(False) blocked = False if helpers.jid_is_blocked(account, jid): blocked = True # Send Custom Status send_custom_status_menuitem = Gtk.MenuItem.new_with_mnemonic( _('Send Cus_tom Status')) if blocked: send_custom_status_menuitem.set_sensitive(False) else: status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): status_menuitem = Gtk.MenuItem.new_with_label(helpers.get_uf_show( s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) status_menuitems.append(status_menuitem) menu.append(send_custom_status_menuitem) if app.account_is_disconnected(account): send_custom_status_menuitem.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Execute Command item = Gtk.MenuItem.new_with_mnemonic(_('E_xecute Command…')) menu.append(item) item.connect('activate', roster.on_execute_command, contact, account, contact.resource) if app.account_is_disconnected(account): item.set_sensitive(False) # Manage Transport submenu item = Gtk.MenuItem.new_with_mnemonic(_('_Manage Transport')) manage_transport_submenu = Gtk.Menu() item.set_submenu(manage_transport_submenu) menu.append(item) # Modify Transport item = Gtk.MenuItem.new_with_mnemonic(_('_Modify Transport')) manage_transport_submenu.append(item) item.connect('activate', roster.on_edit_agent, contact, account) if app.account_is_disconnected(account): item.set_sensitive(False) # Rename item = Gtk.MenuItem.new_with_mnemonic(_('_Rename…')) manage_transport_submenu.append(item) item.connect('activate', roster.on_rename, 'agent', jid, account) if app.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator manage_transport_submenu.append(item) # Block if blocked: item = Gtk.MenuItem.new_with_mnemonic(_('_Unblock')) item.connect('activate', roster.on_unblock, [(contact, account)]) else: item = Gtk.MenuItem.new_with_mnemonic(_('_Block')) item.connect('activate', roster.on_block, [(contact, account)]) manage_transport_submenu.append(item) if app.account_is_disconnected(account): item.set_sensitive(False) # Remove item = Gtk.MenuItem.new_with_mnemonic(_('Remo_ve')) manage_transport_submenu.append(item) item.connect('activate', roster.on_remove_agent, [(contact, account)]) if app.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Information information_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Information')) menu.append(information_menuitem) information_menuitem.connect('activate', roster.on_info, contact, account) if app.account_is_disconnected(account): information_menuitem.set_sensitive(False) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() return menu def get_singlechat_menu(control_id): singlechat_menu = [ (_('Send File…'), [ ('win.send-file-httpupload-', _('Upload File…')), ('win.send-file-jingle-', _('Send File Directly…')), ]), ('win.invite-contacts-', _('Invite Contacts')), ('win.add-to-roster-', _('Add to Roster')), ('win.toggle-audio-', _('Audio Session')), ('win.toggle-video-', _('Video Session')), ('win.information-', _('Information')), ('win.browse-history-', _('History')), ] def build_menu(preset): menu = Gio.Menu() for item in preset: if isinstance(item[1], str): action_name, label = item if action_name == 'win.browse-history-': menu.append(label, action_name + control_id + '::none') else: menu.append(label, action_name + control_id) else: label, sub_menu = item # This is a submenu submenu = build_menu(sub_menu) menu.append_submenu(label, submenu) return menu return build_menu(singlechat_menu) def get_groupchat_menu(control_id): groupchat_menu = [ (_('Manage Room'), [ ('win.change-subject-', _('Change Subject')), ('win.configure-', _('Configure Room')), ('win.upload-avatar-', _('Upload Avatar…')), ('win.destroy-', _('Destroy Room')), ]), (_('Sync Threshold'), []), ('win.change-nick-', _('Change Nick')), ('win.bookmark-', _('Bookmark Room')), ('win.request-voice-', _('Request Voice')), ('win.notify-on-message-', _('Notify on all messages')), ('win.minimize-', _('Minimize on close')), ('win.execute-command-', _('Execute command')), ('win.browse-history-', _('History')), ('win.disconnect-', _('Disconnect')), ] def build_menu(preset): menu = Gio.Menu() for item in preset: if isinstance(item[1], str): action_name, label = item if action_name == 'win.browse-history-': menu.append(label, action_name + control_id + '::none') else: menu.append(label, action_name + control_id) else: label, sub_menu = item if not sub_menu: # Sync threshold menu submenu = build_sync_menu() else: # This is a submenu submenu = build_menu(sub_menu) menu.append_submenu(label, submenu) return menu def build_sync_menu(): menu = Gio.Menu() days = app.config.get('threshold_options').split(',') days = [int(day) for day in days] action_name = 'win.choose-sync-%s::' % control_id for day in days: if day == 0: label = _('No threshold') else: label = ngettext('%i day', '%i days', day, day, day) menu.append(label, '%s%s' % (action_name, day)) return menu return build_menu(groupchat_menu) def get_bookmarks_menu(account, rebuild=False): con = app.connections[account] boomarks = con.get_module('Bookmarks').get_sorted_bookmarks(short_name=True) menu = Gio.Menu() # Build Join Groupchat action = 'app.{}-join-groupchat'.format(account) menuitem = Gio.MenuItem.new(_('Join Group Chat'), action) variant = GLib.Variant('as', [account, '']) menuitem.set_action_and_target_value(action, variant) menu.append_item(menuitem) # Build Bookmarks section = Gio.Menu() for jid, bookmark in boomarks.items(): name = bookmark['name'] action = 'app.{}-activate-bookmark'.format(account) menuitem = Gio.MenuItem.new(name, action) # Create Variant Dict dict_ = {'account': GLib.Variant('s', account), 'jid': GLib.Variant('s', jid)} if bookmark['nick']: dict_['nick'] = GLib.Variant('s', bookmark['nick']) if bookmark['password']: dict_['password'] = GLib.Variant('s', bookmark['password']) variant_dict = GLib.Variant('a{sv}', dict_) menuitem.set_action_and_target_value(action, variant_dict) section.append_item(menuitem) menu.append_section(None, section) if not rebuild: get_action(account + '-activate-bookmark').set_enabled(True) return menu def get_account_menu(account): ''' [(action, label/sub_menu)] action: string label: string sub menu: list ''' account_menu = [ ('-add-contact', _('Add Contact…')), ('-join-groupchat', _('Join Group Chat')), ('-profile', _('Profile')), ('-services', _('Discover Services')), ('-start-single-chat', _('Send Single Message…')), (_('Advanced'), [ ('-archive', _('Archiving Preferences')), ('-sync-history', _('Synchronise History')), ('-privacylists', _('Privacy Lists')), ('-server-info', _('Server Info')), ('-xml-console', _('XML Console')) ]), (_('Admin'), [ ('-send-server-message', _('Send Server Message…')), ('-set-motd', _('Set MOTD…')), ('-update-motd', _('Update MOTD…')), ('-delete-motd', _('Delete MOTD…')) ]), ] zeroconf_menu = [ ('-xml-console', _('XML Console')), ] def build_menu(preset): menu = Gio.Menu() for item in preset: if isinstance(item[1], str): action, label = item if action == '-join-groupchat': bookmark_menu = get_bookmarks_menu(account, True) if bookmark_menu: menu.append_submenu(label, bookmark_menu) continue action = 'app.{}{}'.format(account, action) menuitem = Gio.MenuItem.new(label, action) if 'add-contact' in action: variant = GLib.Variant('as', [account, '']) else: variant = GLib.Variant('s', account) menuitem.set_action_and_target_value(action, variant) menu.append_item(menuitem) else: label, sub_menu = item # This is a submenu submenu = build_menu(sub_menu) menu.append_submenu(label, submenu) return menu if account == 'Local': return build_menu(zeroconf_menu) return build_menu(account_menu) def build_accounts_menu(): menubar = app.app.get_menubar() # Accounts Submenu menu_position = 1 if app.prefers_app_menu(): menu_position = 0 acc_menu = menubar.get_item_link(menu_position, 'submenu') acc_menu.remove_all() accounts_list = sorted(app.contacts.get_accounts()) if not accounts_list: no_accounts = _('No Accounts available') acc_menu.append_item(Gio.MenuItem.new(no_accounts, None)) return if len(accounts_list) > 1: for acc in accounts_list: label = escape_mnemonic(app.get_account_label(acc)) acc_menu.append_submenu( label, get_account_menu(acc)) else: acc_menu = get_account_menu(accounts_list[0]) menubar.remove(menu_position) menubar.insert_submenu(menu_position, _('Accounts'), acc_menu) def build_bookmark_menu(account): menubar = app.app.get_menubar() bookmark_menu = get_bookmarks_menu(account) if not bookmark_menu: return menu_position = 1 if app.prefers_app_menu(): menu_position = 0 # Accounts Submenu acc_menu = menubar.get_item_link(menu_position, 'submenu') # We have more than one Account active if acc_menu.get_item_link(0, 'submenu'): for i in range(acc_menu.get_n_items()): label = acc_menu.get_item_attribute_value(i, 'label') account_label = escape_mnemonic( app.config.get_per('accounts', account, 'account_label')) if label.get_string() in (account_label, account): menu = acc_menu.get_item_link(i, 'submenu') else: # We have only one Account active menu = acc_menu label = menu.get_item_attribute_value(1, 'label').get_string() menu.remove(1) menu.insert_submenu(1, label, bookmark_menu) def get_encryption_menu(control_id, type_id, zeroconf=False): menu = Gio.Menu() menu.append( 'Disabled', 'win.set-encryption-{}::{}'.format(control_id, 'disabled')) for name, plugin in app.plugin_manager.encryption_plugins.items(): if type_id == 'gc': if not hasattr(plugin, 'allow_groupchat'): continue if type_id == 'pm': if not hasattr(plugin, 'allow_privatechat'): continue if zeroconf: if not hasattr(plugin, 'allow_zeroconf'): continue menu_action = 'win.set-encryption-{}::{}'.format( control_id, name) menu.append(name, menu_action) if menu.get_n_items() == 1: return None return menu def get_conv_context_menu(account, kind, text): if kind == 'xmpp': if '?join' in text: context_menu = [ ('copy-link', _('Copy JID')), ('-join-groupchat', _('Join Groupchat')), ] else: context_menu = [ ('copy-link', _('Copy JID')), ('-start-chat', _('Start Chat')), ('-add-contact', _('Add to Roster…')), ] elif kind == 'url': context_menu = [ ('copy-link', _('Copy Link Location')), ('open-link', _('Open Link in Browser')), ] elif kind == 'mail': context_menu = [ ('copy-link', _('Copy Email Address')), ('open-link', _('Open Email Composer')), ] elif kind == 'sth_at_sth': context_menu = [ ('copy-link', _('Copy JID/Email')), ('open-link', _('Open Email Composer')), ('-start-chat', _('Start Chat')), ('-join-groupchat', _('Join Groupchat')), ('-add-contact', _('Add to Roster…')), ] else: return menu = Gtk.Menu() for item in context_menu: action, label = item menuitem = Gtk.MenuItem() menuitem.set_label(label) if action.startswith('-'): text = text.replace('xmpp:', '') text = text.split('?')[0] action = 'app.%s%s' % (account, action) else: action = 'app.%s' % action menuitem.set_action_name(action) if action == 'app.open-link': value = GLib.Variant.new_strv([kind, text]) elif action == 'app.copy-link': value = GLib.Variant.new_string(text) else: value = GLib.Variant.new_strv([account, text]) menuitem.set_action_target_value(value) menuitem.show() menu.append(menuitem) return menu def escape_mnemonic(label): if label is None: return # Underscore inside a label means the next letter is a keyboard # shortcut. To show an underscore we have to use double underscore return label.replace('_', '__') gajim-gajim-1.1.3/gajim/history_manager.py000066400000000000000000000652341345766322700205550ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2006-2007 Jean-Marie Traissard # Nikos Kouremenos # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Stephan Erb # Copyright (C) 2008 Jonathan Schleifer # Copyright (C) 2018 Philipp Hörist # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . # NOTE: some method names may match those of logger.py but that's it # someday (TM) should have common class # that abstracts db connections and helpers on it # the same can be said for history.py import os import sys import time import getopt import sqlite3 from enum import IntEnum, unique import gi gi.require_version('Gtk', '3.0') gi.require_version('GLib', '2.0') gi.require_version('Gdk', '3.0') gi.require_version('Gio', '2.0') from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gio from gajim.common import app from gajim.common import i18n from gajim.common import configpaths from gajim.common.i18n import _ from gajim.common.const import StyleAttr def is_standalone(): # Determine if we are in standalone mode if Gio.Application.get_default() is None: return True if __name__ == '__main__': return True return False if is_standalone(): try: shortargs = 'hvsc:l:p:' longargs = 'help verbose separate config-path= loglevel= profile=' opts = getopt.getopt(sys.argv[1:], shortargs, longargs.split())[0] except getopt.error as msg: print(str(msg)) print('for help use --help') sys.exit(2) for o, a in opts: if o in ('-h', '--help'): print(_('Usage:') + \ '\n gajim-history-manager [options] filename\n\n' + \ _('Options:') + \ '\n -h, --help ' + \ _('Show this help message and exit') + \ '\n -c, --config-path ' + _('Choose folder for logfile') + '\n') sys.exit() elif o in ('-c', '--config-path'): configpaths.set_config_root(a) configpaths.init() app.load_css_config() from gajim.common.const import JIDConstant, KindConstant from gajim.common import helpers from gajim.gtk.dialogs import YesNoDialog from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import ConfirmationDialog from gajim.gtk.filechoosers import FileSaveDialog from gajim.gtk.util import convert_rgb_to_hex from gajim import gtkgui_helpers @unique class Column(IntEnum): UNIXTIME = 2 MESSAGE = 3 SUBJECT = 4 NICKNAME = 5 class HistoryManager: def __init__(self): pixs = [] for size in (16, 32, 48, 64, 128): pix = gtkgui_helpers.get_icon_pixmap('org.gajim.Gajim', size) if pix: pixs.append(pix) if pixs: # set the icon to all windows Gtk.Window.set_default_icon_list(pixs) log_db_path = configpaths.get('LOG_DB') if not os.path.exists(log_db_path): ErrorDialog(_('Cannot find history logs database'), '%s does not exist.' % log_db_path) sys.exit() xml = gtkgui_helpers.get_gtk_builder('history_manager.ui') self.window = xml.get_object('history_manager_window') self.jids_listview = xml.get_object('jids_listview') self.logs_listview = xml.get_object('logs_listview') self.search_results_listview = xml.get_object('search_results_listview') self.search_entry = xml.get_object('search_entry') self.logs_scrolledwindow = xml.get_object('logs_scrolledwindow') self.search_results_scrolledwindow = xml.get_object( 'search_results_scrolledwindow') self.welcome_vbox = xml.get_object('welcome_vbox') self.jids_already_in = [] # holds jids that we already have in DB self.AT_LEAST_ONE_DELETION_DONE = False self.con = sqlite3.connect( log_db_path, timeout=20.0, isolation_level='IMMEDIATE') self.con.execute("PRAGMA secure_delete=1") self.cur = self.con.cursor() self._init_jids_listview() self._init_logs_listview() self._init_search_results_listview() self._fill_jids_listview() self.search_entry.grab_focus() self.window.show_all() xml.connect_signals(self) def _init_jids_listview(self): self.jids_liststore = Gtk.ListStore(str, str) # jid, jid_id self.jids_listview.set_model(self.jids_liststore) self.jids_listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) renderer_text = Gtk.CellRendererText() # holds jid col = Gtk.TreeViewColumn(_('JID'), renderer_text, text=0) self.jids_listview.append_column(col) self.jids_listview.get_selection().connect('changed', self.on_jids_listview_selection_changed) def _init_logs_listview(self): # log_line_id(HIDDEN), jid_id(HIDDEN), time, message, subject, nickname self.logs_liststore = Gtk.ListStore(str, str, str, str, str, str) self.logs_listview.set_model(self.logs_liststore) self.logs_listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) renderer_text = Gtk.CellRendererText() # holds time col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) # user can click this header and sort col.set_sort_column_id(Column.UNIXTIME) col.set_resizable(True) self.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds nickname col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) # user can click this header and sort col.set_sort_column_id(Column.NICKNAME) col.set_resizable(True) col.set_visible(False) self.nickname_col_for_logs = col self.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds message col = Gtk.TreeViewColumn(_('Message'), renderer_text, markup=Column.MESSAGE) # user can click this header and sort col.set_sort_column_id(Column.MESSAGE) col.set_resizable(True) self.message_col_for_logs = col self.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds subject col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) col.set_sort_column_id(Column.SUBJECT) # user can click this header and sort col.set_resizable(True) col.set_visible(False) self.subject_col_for_logs = col self.logs_listview.append_column(col) def _init_search_results_listview(self): # log_line_id (HIDDEN), jid, time, message, subject, nickname self.search_results_liststore = Gtk.ListStore(int, str, str, str, str, str) self.search_results_listview.set_model(self.search_results_liststore) renderer_text = Gtk.CellRendererText() # holds JID (who said this) col = Gtk.TreeViewColumn(_('JID'), renderer_text, text=1) col.set_sort_column_id(1) # user can click this header and sort col.set_resizable(True) self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds time col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) # user can click this header and sort col.set_sort_column_id(Column.UNIXTIME) col.set_resizable(True) self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds message col = Gtk.TreeViewColumn(_('Message'), renderer_text, text=Column.MESSAGE) col.set_sort_column_id(Column.MESSAGE) # user can click this header and sort col.set_resizable(True) self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds subject col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) col.set_sort_column_id(Column.SUBJECT) # user can click this header and sort col.set_resizable(True) self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds nickname col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) # user can click this header and sort col.set_sort_column_id(Column.NICKNAME) col.set_resizable(True) self.search_results_listview.append_column(col) def on_history_manager_window_delete_event(self, widget, event): if not self.AT_LEAST_ONE_DELETION_DONE: if is_standalone(): Gtk.main_quit() return def on_yes(clicked): self.cur.execute('VACUUM') self.con.commit() if is_standalone(): Gtk.main_quit() def on_no(): if is_standalone(): Gtk.main_quit() dialog = YesNoDialog( _('Do you want to clean up the database? ' '(STRONGLY NOT RECOMMENDED IF GAJIM IS RUNNING)'), _('Normally allocated database size will not be freed, ' 'it will just become reusable. If you really want to reduce ' 'database filesize, click YES, else click NO.' '\n\nIn case you click YES, please wait…'), on_response_yes=on_yes, on_response_no=on_no) dialog.set_title(_('Database Cleanup')) button_box = dialog.get_children()[0].get_children()[1] button_box.get_children()[0].grab_focus() def _fill_jids_listview(self): # get those jids that have at least one entry in logs self.cur.execute('SELECT jid, jid_id FROM jids WHERE jid_id IN (' 'SELECT distinct logs.jid_id FROM logs) ORDER BY jid') # list of tuples: [('aaa@bbb',), ('cc@dd',)] rows = self.cur.fetchall() for row in rows: self.jids_already_in.append(row[0]) # jid self.jids_liststore.append([row[0], str(row[1])]) # jid, jid_id def on_jids_listview_selection_changed(self, widget, data=None): liststore, list_of_paths = self.jids_listview.get_selection()\ .get_selected_rows() self.logs_liststore.clear() if not list_of_paths: return self.welcome_vbox.hide() self.search_results_scrolledwindow.hide() self.logs_scrolledwindow.show() list_of_rowrefs = [] for path in list_of_paths: # make them treerowrefs (it's needed) list_of_rowrefs.append(Gtk.TreeRowReference.new(liststore, path)) for rowref in list_of_rowrefs: # FILL THE STORE, for all rows selected path = rowref.get_path() if path is None: continue jid = liststore[path][0] # jid self._fill_logs_listview(jid) def _get_jid_id(self, jid): """ jids table has jid and jid_id logs table has log_id, jid_id, contact_name, time, kind, show, message So to ask logs we need jid_id that matches our jid in jids table this method wants jid and returns the jid_id for later sql-ing on logs """ if jid.find('/') != -1: # if it has a / jid_is_from_pm = self._jid_is_from_pm(jid) if not jid_is_from_pm: # it's normal jid with resource jid = jid.split('/', 1)[0] # remove the resource self.cur.execute('SELECT jid_id FROM jids WHERE jid = ?', (jid,)) jid_id = self.cur.fetchone()[0] return str(jid_id) def _get_jid_from_jid_id(self, jid_id): """ jids table has jid and jid_id This method accepts jid_id and returns the jid for later sql-ing on logs """ self.cur.execute('SELECT jid FROM jids WHERE jid_id = ?', (jid_id,)) jid = self.cur.fetchone()[0] return jid def _jid_is_from_pm(self, jid): """ If jid is gajim@conf/nkour it's likely a pm one, how we know gajim@conf is not a normal guy and nkour is not his resource? We ask if gajim@conf is already in jids (with type room jid). This fails if user disables logging for room and only enables for pm (so higly unlikely) and if we fail we do not go chaos (user will see the first pm as if it was message in room's public chat) and after that everything is ok """ possible_room_jid = jid.split('/', 1)[0] self.cur.execute('SELECT jid_id FROM jids WHERE jid = ? AND type = ?', (possible_room_jid, JIDConstant.ROOM_TYPE)) row = self.cur.fetchone() if row is None: return False return True def _jid_is_room_type(self, jid): """ Return True/False if given id is room type or not eg. if it is room """ self.cur.execute('SELECT type FROM jids WHERE jid = ?', (jid,)) row = self.cur.fetchone() return row[0] == JIDConstant.ROOM_TYPE def _fill_logs_listview(self, jid): """ Fill the listview with all messages that user sent to or received from JID """ # no need to lower jid in this context as jid is already lowered # as we use those jids from db jid_id = self._get_jid_id(jid) self.cur.execute(''' SELECT log_line_id, jid_id, time, kind, message, subject, contact_name, show FROM logs WHERE jid_id = ? ORDER BY time ''', (jid_id,)) results = self.cur.fetchall() if self._jid_is_room_type(jid): # is it room? self.nickname_col_for_logs.set_visible(True) self.subject_col_for_logs.set_visible(False) else: self.nickname_col_for_logs.set_visible(False) self.subject_col_for_logs.set_visible(True) for row in results: # exposed in UI (TreeViewColumns) are only # time, message, subject, nickname # but store in liststore # log_line_id, jid_id, time, message, subject, nickname log_line_id, jid_id, time_, kind, message, subject, nickname, \ show = row try: time_ = time.strftime('%x', time.localtime(float(time_))) except ValueError: pass else: color = None if kind in (KindConstant.SINGLE_MSG_RECV, KindConstant.CHAT_MSG_RECV, KindConstant.GC_MSG): color = app.css_config.get_value( '.gajim-incoming-nickname', StyleAttr.COLOR) elif kind in (KindConstant.SINGLE_MSG_SENT, KindConstant.CHAT_MSG_SENT): color = app.css_config.get_value( '.gajim-outgoing-nickname', StyleAttr.COLOR) elif kind in (KindConstant.STATUS, KindConstant.GCSTATUS): color = app.css_config.get_value( '.gajim-status-message', StyleAttr.COLOR) # include status into (status) message if message is None: message = '' else: message = ' : ' + message message = helpers.get_uf_show(app.SHOW_LIST[show]) + \ message message_ = ' # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Nikos Kouremenos # Copyright (C) 2008 Jonathan Schleifer # Julien Pivotto # Stephan Erb # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . """ A Gtk.TextView-based renderer for XHTML-IM, as described in: http://xmpp.org/extensions/xep-0071.html Starting with the version posted by Gustavo Carneiro, I (Santiago Gala) am trying to make it more compatible with the markup that docutils generate, and also more modular. """ import re import logging import urllib import xml.sax import xml.sax.handler from io import StringIO from gi.repository import GObject from gi.repository import Pango from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import GLib from gajim.common import app from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.const import StyleAttr from gajim.gtk.util import load_icon from gajim.gtk.util import get_cursor from gajim.gui_menu_builder import get_conv_context_menu log = logging.getLogger('gajim.htmlview') __all__ = ['HtmlTextView'] whitespace_rx = re.compile('\\s+') allwhitespace_rx = re.compile('^\\s*$') # embryo of CSS classes classes = { #'system-message':';display: none', 'problematic': ';color: red', } # styles for elements _element_styles = { 'u' : ';text-decoration: underline', 'em' : ';font-style: oblique', 'cite' : '; background-color:rgb(170,190,250);' 'font-style: oblique', 'li' : '; margin-left: 1em; margin-right: 10%', 'strong' : ';font-weight: bold', 'pre' : '; background-color:rgb(190,190,190);' 'font-family: monospace; white-space: pre;' 'margin-left: 1em; margin-right: 10%', 'kbd' : ';background-color:rgb(210,210,210);' 'font-family: monospace', 'blockquote' : '; background-color:rgb(170,190,250);' 'margin-left: 2em; margin-right: 10%', 'dt' : ';font-weight: bold; font-style: oblique', 'dd' : ';margin-left: 2em; font-style: oblique' } # no difference for the moment _element_styles['dfn'] = _element_styles['em'] _element_styles['var'] = _element_styles['em'] # deprecated, legacy, presentational _element_styles['tt'] = _element_styles['kbd'] _element_styles['i'] = _element_styles['em'] _element_styles['b'] = _element_styles['strong'] # ========== # XEP-0071 # ========== # # This Integration Set includes a subset of the modules defined for # XHTML 1.0 but does not redefine any existing modules, nor # does it define any new modules. Specifically, it includes the # following modules only: # # - Structure # - Text # # * Block # # phrasal # addr, blockquote, pre # Struc # div,p # Heading # h1, h2, h3, h4, h5, h6 # # * Inline # # phrasal # abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var # structural # br, span # # - Hypertext (a) # - List (ul, ol, dl) # - Image (img) # - Style Attribute # # Therefore XHTML-IM uses the following content models: # # Block.mix # Block-like elements, e.g., paragraphs # Flow.mix # Any block or inline elements # Inline.mix # Character-level elements # InlineNoAnchor.class # Anchor element # InlinePre.mix # Pre element # # XHTML-IM also uses the following Attribute Groups: # # Core.extra.attrib # TBD # I18n.extra.attrib # TBD # Common.extra # style # # # ... # block level: # Heading h # ( pres = h1 | h2 | h3 | h4 | h5 | h6 ) # Block ( phrasal = address | blockquote | pre ) # NOT ( presentational = hr ) # ( structural = div | p ) # other: section # Inline ( phrasal = abbr | acronym | cite | code | dfn | em | # kbd | q | samp | strong | var ) # NOT ( presentational = b | big | i | small | sub | sup | tt ) # ( structural = br | span ) # Param/Legacy param, font, basefont, center, s, strike, u, dir, menu, # isindex BLOCK_HEAD = set(('h1', 'h2', 'h3', 'h4', 'h5', 'h6',)) BLOCK_PHRASAL = set(('address', 'blockquote', 'pre',)) BLOCK_PRES = set(('hr', )) #not in xhtml-im BLOCK_STRUCT = set(('div', 'p', )) BLOCK_HACKS = set(('table', 'tr')) # at the very least, they will start line ;) BLOCK = BLOCK_HEAD.union(BLOCK_PHRASAL).union(BLOCK_STRUCT).union(BLOCK_PRES).union(BLOCK_HACKS) INLINE_PHRASAL = set('abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var'.split(', ')) INLINE_PRES = set('b, i, u, tt'.split(', ')) #not in xhtml-im INLINE_STRUCT = set('br, span'.split(', ')) INLINE = INLINE_PHRASAL.union(INLINE_PRES).union(INLINE_STRUCT) LIST_ELEMS = set('dl, ol, ul'.split(', ')) for _name in BLOCK_HEAD: _num = int(_name[1]) _header_size = (_num - 1) // 2 _weight = (_num - 1) % 2 _element_styles[_name] = '; font-size: %s; %s' % (('large', 'medium', 'small')[_header_size], ('font-weight: bold', 'font-style: oblique')[_weight],) def _parse_css_color(color): if color.startswith('rgb(') and color.endswith(')'): red, green, blue = [int(c)*257 for c in color[4:-1].split(',')] return Gdk.Color(red, green, blue) return Gdk.color_parse(color) def style_iter(style): return ([x.strip() for x in item.split(':', 1)] for item in style.split(';')\ if len(item.strip())) class HtmlHandler(xml.sax.handler.ContentHandler): """ A handler to display html to a gtk textview It keeps a stack of "style spans" (start/end element pairs) and a stack of list counters, for nested lists. """ def __init__(self, textview, conv_textview, startiter): xml.sax.handler.ContentHandler.__init__(self) self.textbuf = textview.get_buffer() self.textview = textview self.iter = startiter self.conv_textview = conv_textview self.text = '' self.starting = True self.preserve = False self.styles = [] # a Gtk.TextTag or None, for each span level self.list_counters = [] # stack (top at head) of list # counters, or None for unordered list def _get_points_from_pixels(self, pixels): resolution = self.textview.get_screen().get_resolution() # points = pixels * 72 / resolution return pixels * 72 / resolution def _parse_style_color(self, tag, value): color = _parse_css_color(value) tag.set_property('foreground-gdk', color) def _parse_style_background_color(self, tag, value): color = _parse_css_color(value) tag.set_property('background-gdk', color) tag.set_property('paragraph-background-gdk', color) def __parse_length_frac_size_allocate(self, textview, allocation, frac, callback, args): callback(allocation.width*frac, *args) def _parse_length(self, value, font_relative, block_relative, minl, maxl, callback, *args): """ Parse/calc length, converting to pixels, calls callback(length, *args) when the length is first computed or changes """ if value.endswith('%'): val = float(value[:-1]) if val > 0: sign = 1 elif val < 0: sign = -1 else: sign = 0 # limits: 1% to 500% val = sign*max(1, min(abs(val), 500)) frac = val/100 if font_relative: callback(frac, '%', *args) elif block_relative: # CSS says 'Percentage values: refer to width of the closest # block-level ancestor' # This is difficult/impossible to implement, so we use # textview width instead; a reasonable approximation.. alloc = self.textview.get_allocation() self.__parse_length_frac_size_allocate(self.textview, alloc, frac, callback, args) self.textview.connect('size-allocate', self.__parse_length_frac_size_allocate, frac, callback, args) else: callback(frac, *args) return def get_val(min_val=minl, max_val=maxl): try: val = float(value[:-2]) except Exception: log.warning('Unable to parse length value "%s"', value) return None if val > 0: sign = 1 elif val < 0: sign = -1 else: sign = 0 # validate length return sign*max(min_val, min(abs(val), max_val)) if value.endswith('pt'): # points size = get_val(5, 50) if size is None: return callback(size, 'pt', *args) elif value.endswith('em'): size = get_val(0.3, 4) if size is None: return callback(size, 'em', *args) elif value.endswith('px'): # pixels size = get_val(5, 50) if size is None: return callback(size, 'px', *args) else: try: # TODO: isn't "no units" interpreted as pixels? val = int(value) if val > 0: sign = 1 elif val < 0: sign = -1 else: sign = 0 # validate length val = sign*max(5, min(abs(val), 70)) callback(val, 'px', *args) except Exception: log.warning('Unable to parse length value "%s"', value) def __parse_font_size_cb(self, size, type_, tag): if type_ in ('em', '%'): tag.set_property('scale', size) elif type_ == 'pt': tag.set_property('size-points', size) elif type_ == 'px': tag.set_property('size-points', self._get_points_from_pixels(size)) def _parse_style_display(self, tag, value): if value == 'none': tag.set_property('invisible', 'true') # FIXME: display: block, inline def _parse_style_font_size(self, tag, value): try: scale = { 'xx-small': 0.5787037037037, 'x-small': 0.6444444444444, 'small': 0.8333333333333, 'medium': 1.0, 'large': 1.2, 'x-large': 1.4399999999999, 'xx-large': 1.728, }[value] except KeyError: pass else: tag.set_property('scale', scale) return if value == 'smaller': tag.set_property('scale', 0.8333333333333) return if value == 'larger': tag.set_property('scale', 1.2) return # font relative (5 ~ 4pt, 110 ~ 72pt) self._parse_length( value, True, False, 5, 110, self.__parse_font_size_cb, tag) def _parse_style_font_style(self, tag, value): try: style = { 'normal': Pango.Style.NORMAL, 'italic': Pango.Style.ITALIC, 'oblique': Pango.Style.OBLIQUE, }[value] except KeyError: log.warning('unknown font-style %s', value) else: tag.set_property('style', style) def __frac_length_tag_cb(self, length, tag, propname): styles = self._get_style_tags() if styles: length += styles[-1].get_property(propname) tag.set_property(propname, length) def _parse_style_margin_left(self, tag, value): # block relative self._parse_length(value, False, True, 1, 1000, self.__frac_length_tag_cb, tag, 'left-margin') def _parse_style_margin_right(self, tag, value): # block relative self._parse_length(value, False, True, 1, 1000, self.__frac_length_tag_cb, tag, 'right-margin') def _parse_style_font_weight(self, tag, value): # TODO: missing 'bolder' and 'lighter' try: weight = { '100': Pango.Weight.ULTRALIGHT, '200': Pango.Weight.ULTRALIGHT, '300': Pango.Weight.LIGHT, '400': Pango.Weight.NORMAL, '500': Pango.Weight.NORMAL, '600': Pango.Weight.BOLD, '700': Pango.Weight.BOLD, '800': Pango.Weight.ULTRABOLD, '900': Pango.Weight.HEAVY, 'normal': Pango.Weight.NORMAL, 'bold': Pango.Weight.BOLD, }[value] except KeyError: log.warning('unknown font-style %s', value) else: tag.set_property('weight', weight) def _parse_style_font_family(self, tag, value): tag.set_property('family', value) def _parse_style_text_align(self, tag, value): try: align = { 'left': Gtk.Justification.LEFT, 'right': Gtk.Justification.RIGHT, 'center': Gtk.Justification.CENTER, 'justify': Gtk.Justification.FILL, }[value] except KeyError: log.warning('Invalid text-align: %s requested', value) else: tag.set_property('justification', align) def _parse_style_text_decoration(self, tag, value): values = value.split(' ') if 'none' in values: tag.set_property('underline', Pango.Underline.NONE) tag.set_property('strikethrough', False) if 'underline' in values: tag.set_property('underline', Pango.Underline.SINGLE) else: tag.set_property('underline', Pango.Underline.NONE) if 'line-through' in values: tag.set_property('strikethrough', True) else: tag.set_property('strikethrough', False) if 'blink' in values: log.warning('text-decoration:blink not implemented') if 'overline' in values: log.warning('text-decoration:overline not implemented') def _parse_style_white_space(self, tag, value): if value == 'pre': tag.set_property('wrap_mode', Gtk.WrapMode.NONE) elif value == 'normal': tag.set_property('wrap_mode', Gtk.WrapMode.WORD) elif value == 'nowrap': tag.set_property('wrap_mode', Gtk.WrapMode.NONE) def __length_tag_cb(self, value, tag, propname): try: tag.set_property(propname, value) except Exception: log.warning('Error with prop: %s for tag: %s', propname, str(tag)) def _parse_style_width(self, tag, value): if value == 'auto': return self._parse_length(value, False, False, 1, 1000, self.__length_tag_cb, tag, "width") def _parse_style_height(self, tag, value): if value == 'auto': return self._parse_length(value, False, False, 1, 1000, self.__length_tag_cb, tag, "height") # build a dictionary mapping styles to methods, for greater speed __style_methods = dict() for style in ('background-color', 'color', 'font-family', 'font-size', 'font-style', 'font-weight', 'margin-left', 'margin-right', 'text-align', 'text-decoration', 'white-space', 'display', 'width', 'height'): try: method = locals()['_parse_style_%s' % style.replace('-', '_')] except KeyError: log.warning('Style attribute "%s" not yet implemented', style) else: __style_methods[style] = method del style # pylint: disable=undefined-loop-variable # -- def _get_style_tags(self): return [tag for tag in self.styles if tag is not None] def _create_url(self, href, title, type_, id_): '''Process a url tag. ''' tag = self.textbuf.create_tag(id_) if href and href[0] != '#': tag.href = href tag.type_ = type_ # to be used by the URL handler tag.connect('event', self.textview.hyperlink_handler, 'url') tag.set_property('foreground', app.css_config.get_value('.gajim-url', StyleAttr.COLOR)) tag.set_property('underline', Pango.Underline.SINGLE) tag.is_anchor = True if title: tag.title = title return tag def _update_img(self, output, attrs, img_mark, tags): '''Callback function called after the function helpers.download_image. ''' mem, alt = output self._process_img(attrs, (mem, alt, img_mark, tags)) def _process_img(self, attrs, loaded=None): '''Process a img tag. ''' mem = '' pixbuf = None replace_mark = None replace_tags = None try: if attrs['src'].startswith('data:image/'): # The "data" URL scheme http://tools.ietf.org/html/rfc2397 import base64 img = attrs['src'].split(',')[1] mem = base64.standard_b64decode(urllib.parse.unquote( img).encode('utf-8')) elif loaded is not None: (mem, alt, replace_mark, replace_tags) = loaded else: if self.conv_textview: img_mark = self.textbuf.create_mark(None, self.iter, True) app.thread_interface(helpers.download_image, [ self.conv_textview.account, attrs], self._update_img, [attrs, img_mark, self._get_style_tags()]) alt = attrs.get('alt', '') if alt: alt += '\n' alt += _('Loading') pixbuf = load_icon('image-missing', self.textview, pixbuf=True) if mem: # Caveat: GdkPixbuf is known not to be safe to load # images from network... this program is now potentially # hackable ;) loader = GdkPixbuf.PixbufLoader() dims = [0, 0] def height_cb(length): dims[1] = length def width_cb(length): dims[0] = length # process width and height attributes w = attrs.get('width') h = attrs.get('height') # override with width and height styles for attr, val in style_iter(attrs.get('style', '')): if attr == 'width': w = val elif attr == 'height': h = val if w: self._parse_length(w, False, False, 1, 1000, width_cb) if h: self._parse_length(h, False, False, 1, 1000, height_cb) def set_size(pixbuf, w, h, dims): """ FIXME: Floats should be relative to the whole textview, and resize with it. This needs new pifbufs for every resize, GdkPixbuf.Pixbuf.scale_simple or similar. """ if isinstance(dims[0], float): dims[0] = int(dims[0]*w) elif not dims[0]: dims[0] = w if isinstance(dims[1], float): dims[1] = int(dims[1]*h) if not dims[1]: dims[1] = h loader.set_size(*dims) if w or h: loader.connect('size-prepared', set_size, dims) loader.write(mem) loader.close() pixbuf = loader.get_pixbuf() alt = attrs.get('alt', '') working_iter = self.iter if replace_mark is not None: working_iter = self.textbuf.get_iter_at_mark(replace_mark) next_iter = working_iter.copy() next_iter.forward_char() self.textbuf.delete(working_iter, next_iter) self.textbuf.delete_mark(replace_mark) if pixbuf is not None: if replace_mark: tags = replace_tags else: tags = self._get_style_tags() if tags: tmpmark = self.textbuf.create_mark(None, working_iter, True) self.textbuf.insert_pixbuf(working_iter, pixbuf) self.starting = False if tags: start = self.textbuf.get_iter_at_mark(tmpmark) for tag in tags: self.textbuf.apply_tag(tag, start, working_iter) self.textbuf.delete_mark(tmpmark) else: self._insert_text('[IMG: %s]' % alt, working_iter) except Exception as ex: log.error('Error loading image %s', str(ex)) pixbuf = None alt = attrs.get('alt', 'Broken image') try: loader.close() except Exception: pass return pixbuf def _begin_span(self, style, tag=None, id_=None): if style is None: self.styles.append(tag) return None if tag is None: if id_: tag = self.textbuf.create_tag(id_) else: tag = self.textbuf.create_tag() # we create anonymous tag for attr, val in style_iter(style): attr = attr.lower() val = val try: method = self.__style_methods[attr] except KeyError: log.warning('Style attribute "%s" requested ' 'but not yet implemented', attr) else: method(self, tag, val) self.styles.append(tag) def _end_span(self): self.styles.pop() def _jump_line(self): self.textbuf.insert_with_tags_by_name(self.iter, '\n', 'eol') self.starting = True def _insert_text(self, text, working_iter=None): if working_iter is None: working_iter = self.iter if self.starting and text != '\n': self.starting = (text[-1] == '\n') tags = self._get_style_tags() if tags: self.textbuf.insert_with_tags(working_iter, text, *tags) else: self.textbuf.insert(working_iter, text) def _starts_line(self): return self.starting or self.iter.starts_line() def _flush_text(self): if not self.text: return text, self.text = self.text, '' if not self.preserve: text = text.replace('\n', ' ') self.handle_specials(whitespace_rx.sub(' ', text)) else: self._insert_text(text.strip('\n')) def _anchor_event(self, tag, textview, event, iter_, href, type_): if event.type == Gdk.EventType.BUTTON_PRESS: self.textview.emit('url-clicked', href, type_) return True return False def handle_specials(self, text): if self.conv_textview: self.iter = self.conv_textview.detect_and_print_special_text(text, self._get_style_tags(), iter_=self.iter) else: self._insert_text(text) def characters(self, content): if self.preserve: self.text += content return if allwhitespace_rx.match(content) is not None and self._starts_line(): return self.text += content self.starting = False def startElement(self, name, attrs): self._flush_text() klass = [i for i in attrs.get('class', ' ').split(' ') if i] style = '' #Add styles defined for classes for k in klass: if k in classes: style += classes[k] tag = None #FIXME: if we want to use id, it needs to be unique across # the whole textview, so we need to add something like the # message-id to it. #id_ = attrs.get('id',None) id_ = None if name == 'a': #TODO: accesskey, charset, hreflang, rel, rev, tabindex, type href = attrs.get('href', None) if not href: href = attrs.get('HREF', None) # Gaim sends HREF instead of href title = attrs.get('title', attrs.get('rel', href)) type_ = attrs.get('type', None) tag = self._create_url(href, title, type_, id_) elif name == 'blockquote': cite = attrs.get('cite', None) if cite: tag = self.textbuf.create_tag(id_) tag.title = attrs.get('title', None) tag.is_anchor = True elif name in LIST_ELEMS: style += ';margin-left: 2em' elif name == 'img': tag = self._process_img(attrs) if name in _element_styles: style += _element_styles[name] # so that explicit styles override implicit ones, # we add the attribute last style += ";"+attrs.get('style', '') if style == '': style = None self._begin_span(style, tag, id_) if name == 'br': pass # handled in endElement elif name == 'hr': pass # handled in endElement elif name in BLOCK: if not self._starts_line(): self._jump_line() if name == 'pre': self.preserve = True elif name == 'span': pass elif name in ('dl', 'ul'): if not self._starts_line(): self._jump_line() self.list_counters.append(None) elif name == 'ol': if not self._starts_line(): self._jump_line() self.list_counters.append(0) elif name == 'li': if self.list_counters[-1] is None: li_head = chr(0x2022) else: self.list_counters[-1] += 1 li_head = '%i.' % self.list_counters[-1] self.text = ' '*len(self.list_counters)*4 + li_head + ' ' self._flush_text() self.starting = True elif name == 'dd': self._jump_line() elif name == 'dt': if not self.starting: self._jump_line() elif name in ('a', 'img', 'body', 'html'): pass elif name in INLINE: pass else: log.warning('Unhandled element "%s"', name) def endElement(self, name): endPreserving = False newLine = False if name == 'br': newLine = True elif name == 'hr': #FIXME: plenty of unused attributes (width, height,...) :) self._jump_line() self._insert_text('\u2015'*40) self._jump_line() elif name in LIST_ELEMS: self.list_counters.pop() elif name == 'li': newLine = True elif name == 'img': pass elif name in ('body', 'html'): pass elif name == 'a': pass elif name in INLINE: pass elif name in ('dd', 'dt', ): pass elif name in BLOCK: if name == 'pre': endPreserving = True elif name in BLOCK_STRUCT: newLine = True else: log.warning("Unhandled element '%s'", name) self._flush_text() if endPreserving: self.preserve = False if newLine: self._jump_line() self._end_span() class HtmlTextView(Gtk.TextView): def __init__(self, account=None): Gtk.TextView.__init__(self) self.set_wrap_mode(Gtk.WrapMode.CHAR) self.set_editable(False) self._changed_cursor = False self.set_has_tooltip(True) self.connect('realize', self.on_html_text_view_realized) self.connect('unrealize', self.on_html_text_view_unrealized) self.connect('copy-clipboard', self.on_html_text_view_copy_clipboard) self.id_ = self.connect('button-release-event', self.on_left_mouse_button_release) self.get_buffer().eol_tag = self.get_buffer().create_tag('eol') self.config = app.config self.interface = app.interface self.account = account self.plugin_modified = False def connect_tooltip(self, func=None): self.connect('query-tooltip', func or self.__query_tooltip) def create_tags(self): buffer_ = self.get_buffer() self.tagURL = buffer_.create_tag('url') color = app.css_config.get_value('.gajim-url', StyleAttr.COLOR) self.tagURL.set_property('foreground', color) self.tagURL.set_property('underline', Pango.Underline.SINGLE) self.tagURL.connect('event', self.hyperlink_handler, 'url') self.tagMail = buffer_.create_tag('mail') self.tagMail.set_property('foreground', color) self.tagMail.set_property('underline', Pango.Underline.SINGLE) self.tagMail.connect('event', self.hyperlink_handler, 'mail') self.tagXMPP = buffer_.create_tag('xmpp') self.tagXMPP.set_property('foreground', color) self.tagXMPP.set_property('underline', Pango.Underline.SINGLE) self.tagXMPP.connect('event', self.hyperlink_handler, 'xmpp') self.tagSthAtSth = buffer_.create_tag('sth_at_sth') self.tagSthAtSth.set_property('foreground', color) self.tagSthAtSth.set_property('underline', Pango.Underline.SINGLE) self.tagSthAtSth.connect('event', self.hyperlink_handler, 'sth_at_sth') def __query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): window = widget.get_window(Gtk.TextWindowType.TEXT) x_pos, y_pos = self.window_to_buffer_coords( Gtk.TextWindowType.TEXT, x_pos, y_pos) if Gtk.MINOR_VERSION > 18: iter_ = self.get_iter_at_position(x_pos, y_pos)[1] else: iter_ = self.get_iter_at_position(x_pos, y_pos)[0] for tag in iter_.get_tags(): if getattr(tag, 'is_anchor', False): text = getattr(tag, 'title', False) if text: if len(text) > 50: text = text[:47] + '…' tooltip.set_text(text) if not self._changed_cursor: window.set_cursor(get_cursor('HAND2')) self._changed_cursor = True return True if self._changed_cursor: window.set_cursor(get_cursor('XTERM')) self._changed_cursor = False return False def show_context_menu(self, _event, kind, text): menu = get_conv_context_menu(self.account, kind, text) if menu is None: return def destroy(menu, pspec): visible = menu.get_property('visible') if not visible: GLib.idle_add(menu.destroy) menu.attach_to_widget(self, None) menu.connect('notify::visible', destroy) menu.popup_at_pointer() def hyperlink_handler(self, texttag, _widget, event, iter_, kind): if event.type == Gdk.EventType.BUTTON_PRESS: begin_iter = iter_.copy() # we get the beginning of the tag while not begin_iter.begins_tag(texttag): begin_iter.backward_char() end_iter = iter_.copy() # we get the end of the tag while not end_iter.ends_tag(texttag): end_iter.forward_char() # Detect XHTML-IM link word = getattr(texttag, 'href', None) if word: if word.startswith('xmpp'): kind = 'xmpp' elif word.startswith('mailto:'): kind = 'mail' elif app.interface.sth_at_sth_dot_sth_re.match(word): # it's a JID or mail kind = 'sth_at_sth' else: word = self.get_buffer().get_text(begin_iter, end_iter, True) if event.button.button == 3: # right click self.show_context_menu(event, kind, word) return True self.plugin_modified = False app.plugin_manager.extension_point( 'hyperlink_handler', word, kind, self, self.get_toplevel()) if self.plugin_modified: return # we launch the correct application if kind == 'xmpp': word = word[5:] if '?' in word: (jid, action) = word.split('?') if action == 'join': app.interface.join_gc_minimal(self.account, jid) else: app.interface.new_chat_from_jid(self.account, jid) else: app.interface.new_chat_from_jid(self.account, word) # handle geo:-URIs elif word[:4] == 'geo:': location = word[4:] lat, _, lon = location.partition(',') if lon == '': return uri = 'https://www.openstreetmap.org/?' \ 'mlat=%(lat)s&mlon=%(lon)s&zoom=16' % \ {'lat': lat, 'lon': lon} helpers.launch_browser_mailer(kind, uri) # other URIs else: helpers.launch_browser_mailer(kind, word) def display_html(self, html, textview, conv_textview, iter_=None): buffer_ = self.get_buffer() if iter_: eob = iter_ else: eob = buffer_.get_end_iter() ## this works too if libxml2 is not available # parser = xml.sax.make_parser(['drv_libxml2']) # parser.setFeature(xml.sax.handler.feature_validation, True) parser = xml.sax.make_parser() parser.setContentHandler(HtmlHandler(textview, conv_textview, eob)) parser.parse(StringIO(html)) # too much space after :) #if not eob.starts_line(): # buffer_.insert(eob, '\n') def on_html_text_view_copy_clipboard(self, unused_data): clipboard = self.get_clipboard(Gdk.SELECTION_CLIPBOARD) selected = self.get_selected_text() clipboard.set_text(selected, -1) GObject.signal_stop_emission_by_name(self, 'copy-clipboard') def on_html_text_view_realized(self, unused_data): self.get_buffer().remove_selection_clipboard(self.get_clipboard( Gdk.SELECTION_PRIMARY)) def on_html_text_view_unrealized(self, unused_data): self.get_buffer().add_selection_clipboard(self.get_clipboard( Gdk.SELECTION_PRIMARY)) def on_left_mouse_button_release(self, widget, event): if event.button != 1: return bounds = self.get_buffer().get_selection_bounds() if bounds: # textview can be hidden while we add a new line in it. if self.has_screen(): clipboard = self.get_clipboard(Gdk.SELECTION_PRIMARY) selected = self.get_selected_text() clipboard.set_text(selected, -1) def get_selected_text(self): bounds = self.get_buffer().get_selection_bounds() selection = '' if bounds: (search_iter, end) = bounds while search_iter.compare(end): character = search_iter.get_char() if character == '\ufffc': anchor = search_iter.get_child_anchor() if anchor: text = anchor.plaintext if text: selection += text else: selection += character else: selection += character search_iter.forward_char() return selection def replace_emojis(self, start_mark, end_mark, pixbuf, codepoint): buffer_ = self.get_buffer() start_iter = buffer_.get_iter_at_mark(start_mark) end_iter = buffer_.get_iter_at_mark(end_mark) buffer_.delete(start_iter, end_iter) anchor = buffer_.create_child_anchor(start_iter) anchor.plaintext = codepoint emoji = Gtk.Image.new_from_pixbuf(pixbuf) emoji.show() self.add_child_at_anchor(emoji, anchor) buffer_.delete_mark(start_mark) buffer_.delete_mark(end_mark) gajim-gajim-1.1.3/gajim/message_control.py000066400000000000000000000157131345766322700205430ustar00rootroot00000000000000# Copyright (C) 2006 Dimitur Kirov # Nikos Kouremenos # Copyright (C) 2006-2007 Jean-Marie Traissard # Travis Shirk # Copyright (C) 2006-2014 Yann Leboulanger # Copyright (C) 2007 Julien Pivotto # Stephan Erb # Copyright (C) 2007-2008 Brendan Taylor # Copyright (C) 2008 Jonathan Schleifer # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gajim import gtkgui_helpers import uuid from gajim.common import app from gajim.common import helpers from gajim.common import ged # Derived types MUST register their type IDs here if custom behavor is required TYPE_CHAT = 'chat' TYPE_GC = 'gc' TYPE_PM = 'pm' #################### class MessageControl: """ An abstract base widget that can embed in the Gtk.Notebook of a MessageWindow """ def __init__(self, type_id, parent_win, widget_name, contact, account, resource=None): # dict { cb id : widget} # keep all registered callbacks of widgets, created by self.xml self.handlers = {} self.type_id = type_id self.parent_win = parent_win self.widget_name = widget_name self.contact = contact self.account = account self.resource = resource # control_id is a unique id for the control, # its used as action name for actions that belong to a control self.control_id = str(uuid.uuid4()) self.session = None app.last_message_time[self.account][self.get_full_jid()] = 0 self.xml = gtkgui_helpers.get_gtk_builder('%s.ui' % widget_name) self.xml.connect_signals(self) self.widget = self.xml.get_object('%s_hbox' % widget_name) app.ged.register_event_handler('message-outgoing', ged.OUT_GUI1, self._nec_message_outgoing) def get_full_jid(self): fjid = self.contact.jid if self.resource: fjid += '/' + self.resource return fjid def set_control_active(self, state): """ Called when the control becomes active (state is True) or inactive (state is False) """ pass # Derived classes MUST implement this method def minimizable(self): """ Called to check if control can be minimized Derived classes MAY implement this. """ return False def safe_shutdown(self): """ Called to check if control can be closed without losing data. returns True if control can be closed safely else False Derived classes MAY implement this. """ return True def allow_shutdown(self, method, on_response_yes, on_response_no, on_response_minimize): """ Called to check is a control is allowed to shutdown. If a control is not in a suitable shutdown state this method should call on_response_no, else on_response_yes or on_response_minimize Derived classes MAY implement this. """ on_response_yes(self) def shutdown(self): """ Derived classes MUST implement this """ app.ged.remove_event_handler('message-outgoing', ged.OUT_GUI1, self._nec_message_outgoing) def repaint_themed_widgets(self): """ Derived classes SHOULD implement this """ pass def update_ui(self): """ Derived classes SHOULD implement this """ pass def toggle_emoticons(self): """ Derived classes MAY implement this """ pass def update_font(self): """ Derived classes SHOULD implement this """ pass def update_tags(self): """ Derived classes SHOULD implement this """ pass def get_tab_label(self, chatstate): """ Return a suitable tab label string. Returns a tuple such as: (label_str, color) either of which can be None if chatstate is given that means we have HE SENT US a chatstate and we want it displayed Derivded classes MUST implement this. """ # Return a markup'd label and optional Gtk.Color in a tuple like: # return (label_str, None) pass def get_tab_image(self, count_unread=True): # Return a suitable tab image for display. # None clears any current label. return None def prepare_context_menu(self, hide_buttonbar_items=False): """ Derived classes SHOULD implement this """ return None def got_connected(self): pass def got_disconnected(self): pass def get_specific_unread(self): return len(app.events.get_events(self.account, self.contact.jid)) def set_session(self, session): oldsession = None if hasattr(self, 'session'): oldsession = self.session if oldsession and session == oldsession: return self.session = session if session: session.control = self if session and oldsession: oldsession.control = None def remove_session(self, session): if session != self.session: return self.session.control = None self.session = None def _nec_message_outgoing(self, obj): # Send the given message to the active tab. # Doesn't return None if error if obj.control != self: return obj.message = helpers.remove_invalid_xml_chars(obj.message) conn = app.connections[self.account] if not self.session: if (not obj.resource and obj.jid != app.get_jid_from_account(self.account)): if self.resource: obj.resource = self.resource else: obj.resource = self.contact.resource sess = conn.find_controlless_session(obj.jid, resource=obj.resource) if self.resource: obj.jid += '/' + self.resource if not sess: if self.type_id == TYPE_PM: sess = conn.make_new_session(obj.jid, type_='pm') else: sess = conn.make_new_session(obj.jid) self.set_session(sess) obj.session = self.session gajim-gajim-1.1.3/gajim/message_textview.py000066400000000000000000000362761345766322700207510ustar00rootroot00000000000000# Copyright (C) 2003-2014 Yann Leboulanger # Copyright (C) 2005-2007 Nikos Kouremenos # Copyright (C) 2006 Dimitur Kirov # Copyright (C) 2008-2009 Julien Pivotto # # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # Gajim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . from gi.repository import Gtk from gi.repository import GLib from gi.repository import GObject from gi.repository import Pango from gajim.common import app from gajim.common.i18n import _ from gajim import gtkgui_helpers if app.is_installed('GSPELL'): from gi.repository import Gspell class MessageTextView(Gtk.TextView): """ Class for the message textview (where user writes new messages) for chat/groupchat windows """ __gsignals__ = { 'text-changed': (GObject.SignalFlags.RUN_LAST, None, (Gtk.TextBuffer,)) } UNDO_LIMIT = 20 PLACEHOLDER = _('Write a message…') def __init__(self): Gtk.TextView.__init__(self) # set properties self.set_border_width(3) self.set_accepts_tab(True) self.set_editable(True) self.set_cursor_visible(True) self.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) self.set_left_margin(2) self.set_right_margin(2) self.set_pixels_above_lines(2) self.set_pixels_below_lines(2) self.get_style_context().add_class('gajim-conversation-font') # set undo list self.undo_list = [] # needed to know if we undid something self.undo_pressed = False buffer_ = self.get_buffer() buffer_.connect('changed', self._on_buffer_changed) self._last_text = '' self.begin_tags = {} self.end_tags = {} self.color_tags = [] self.fonts_tags = [] self.other_tags = {} self.placeholder_tag = buffer_.create_tag('placeholder') self.placeholder_tag.set_property('foreground_rgba', gtkgui_helpers.Color.GREY) self.other_tags['bold'] = buffer_.create_tag('bold') self.other_tags['bold'].set_property('weight', Pango.Weight.BOLD) self.begin_tags['bold'] = '' self.end_tags['bold'] = '' self.other_tags['italic'] = buffer_.create_tag('italic') self.other_tags['italic'].set_property('style', Pango.Style.ITALIC) self.begin_tags['italic'] = '' self.end_tags['italic'] = '' self.other_tags['underline'] = buffer_.create_tag('underline') self.other_tags['underline'].set_property('underline', Pango.Underline.SINGLE) self.begin_tags['underline'] = '' self.end_tags['underline'] = '' self.other_tags['strike'] = buffer_.create_tag('strike') self.other_tags['strike'].set_property('strikethrough', True) self.begin_tags['strike'] = '' self.end_tags['strike'] = '' self.connect('paste-clipboard', self._paste_clipboard) self.connect_after('paste-clipboard', self._after_paste_clipboard) self.connect('focus-in-event', self._on_grab_focus) self.connect('grab-focus', self._on_grab_focus) self.connect('focus-out-event', self._on_focus_out) def _on_buffer_changed(self, *args): text = self.get_text() # Because of inserting and removing PLACEHOLDER text # the signal becomes unreliable when determining if the user # typed in new text. So we send our own signal depending on if # there is real new text that is not the PLACEHOLDER if text != self._last_text: self.emit('text-changed', self.get_buffer()) self._last_text = text def has_text(self): buf = self.get_buffer() start, end = buf.get_bounds() text = buf.get_text(start, end, True) return text not in (self.PLACEHOLDER, '') def get_text(self): # gets the text if its not PLACEHOLDER buf = self.get_buffer() start, end = buf.get_bounds() text = self.get_buffer().get_text(start, end, True) if text == self.PLACEHOLDER: return '' return text def is_placeholder(self): buf = self.get_buffer() start, end = buf.get_bounds() text = buf.get_text(start, end, True) return text == self.PLACEHOLDER def remove_placeholder(self): if self.is_placeholder(): self.get_buffer().set_text('') self.toggle_speller(True) def _on_grab_focus(self, *args): self.remove_placeholder() def _on_focus_out(self, *args): buf = self.get_buffer() start, end = buf.get_bounds() text = buf.get_text(start, end, True) if text == '': buf.insert_with_tags( start, self.PLACEHOLDER, self.placeholder_tag) self.toggle_speller(False) def toggle_speller(self, activate): if app.is_installed('GSPELL') and app.config.get('use_speller'): spell_view = Gspell.TextView.get_from_gtk_text_view(self) spell_view.set_inline_spell_checking(activate) @staticmethod def _paste_clipboard(textview): if textview.is_placeholder(): textview.get_buffer().set_text('') @staticmethod def _after_paste_clipboard(textview): buffer_ = textview.get_buffer() mark = buffer_.get_insert() iter_ = buffer_.get_iter_at_mark(mark) if iter_.get_offset() == buffer_.get_end_iter().get_offset(): GLib.idle_add(gtkgui_helpers.scroll_to_end, textview.get_parent()) def make_clickable_urls(self, text): _buffer = self.get_buffer() start = 0 end = 0 index = 0 new_text = '' iterator = app.interface.link_pattern_re.finditer(text) for match in iterator: start, end = match.span() url = text[start:end] if start != 0: text_before_special_text = text[index:start] else: text_before_special_text = '' # we insert normal text new_text += text_before_special_text + \ '' + url + '' index = end # update index if end < len(text): new_text += text[end:] return new_text # the position after *last* special text def get_active_tags(self): start = self.get_active_iters()[0] active_tags = [] for tag in start.get_tags(): active_tags.append(tag.get_property('name')) return active_tags def get_active_iters(self): _buffer = self.get_buffer() return_val = _buffer.get_selection_bounds() if return_val: # if sth was selected start, finish = return_val[0], return_val[1] else: start, finish = _buffer.get_bounds() return (start, finish) def set_tag(self, tag): _buffer = self.get_buffer() start, finish = self.get_active_iters() if start.has_tag(self.other_tags[tag]): _buffer.remove_tag_by_name(tag, start, finish) else: if tag == 'underline': _buffer.remove_tag_by_name('strike', start, finish) elif tag == 'strike': _buffer.remove_tag_by_name('underline', start, finish) _buffer.apply_tag_by_name(tag, start, finish) def clear_tags(self): _buffer = self.get_buffer() start, finish = self.get_active_iters() _buffer.remove_all_tags(start, finish) def color_set(self, widget, response): if response in (-6, -4): widget.destroy() return color = widget.get_property('rgba') widget.destroy() _buffer = self.get_buffer() # Create #aabbcc color string from rgba color color_string = '#%02X%02X%02X' % (round(color.red*255), round(color.green*255), round(color.blue*255)) tag_name = 'color' + color_string if not tag_name in self.color_tags: tagColor = _buffer.create_tag(tag_name) tagColor.set_property('foreground', color_string) self.begin_tags[tag_name] = '' % color_string self.end_tags[tag_name] = '' self.color_tags.append(tag_name) start, finish = self.get_active_iters() for tag in self.color_tags: _buffer.remove_tag_by_name(tag, start, finish) _buffer.apply_tag_by_name(tag_name, start, finish) def font_set(self, widget, response, start, finish): if response in (-6, -4): widget.destroy() return font = widget.get_font() font_desc = widget.get_font_desc() family = font_desc.get_family() size = font_desc.get_size() size = size / Pango.SCALE weight = font_desc.get_weight() style = font_desc.get_style() widget.destroy() _buffer = self.get_buffer() tag_name = 'font' + font if not tag_name in self.fonts_tags: tagFont = _buffer.create_tag(tag_name) tagFont.set_property('font', family + ' ' + str(size)) self.begin_tags[tag_name] = \ '' self.end_tags[tag_name] = '' self.fonts_tags.append(tag_name) for tag in self.fonts_tags: _buffer.remove_tag_by_name(tag, start, finish) _buffer.apply_tag_by_name(tag_name, start, finish) if weight == Pango.Weight.BOLD: _buffer.apply_tag_by_name('bold', start, finish) else: _buffer.remove_tag_by_name('bold', start, finish) if style == Pango.Style.ITALIC: _buffer.apply_tag_by_name('italic', start, finish) else: _buffer.remove_tag_by_name('italic', start, finish) def get_xhtml(self): _buffer = self.get_buffer() old = _buffer.get_start_iter() tags = {} tags['bold'] = False iter_ = _buffer.get_start_iter() old = _buffer.get_start_iter() text = '' modified = False def xhtml_special(text): text = text.replace('<', '<') text = text.replace('>', '>') text = text.replace('&', '&') text = text.replace('\n', '
') return text for tag in iter_.get_toggled_tags(True): tag_name = tag.get_property('name') if tag_name not in self.begin_tags: continue text += self.begin_tags[tag_name] modified = True while (iter_.forward_to_tag_toggle(None) and not iter_.is_end()): text += xhtml_special(_buffer.get_text(old, iter_, True)) old.forward_to_tag_toggle(None) new_tags, old_tags, end_tags = [], [], [] for tag in iter_.get_toggled_tags(True): tag_name = tag.get_property('name') if tag_name not in self.begin_tags: continue new_tags.append(tag_name) modified = True for tag in iter_.get_tags(): tag_name = tag.get_property('name') if tag_name not in self.begin_tags or tag_name not in self.end_tags: continue if tag_name not in new_tags: old_tags.append(tag_name) for tag in iter_.get_toggled_tags(False): tag_name = tag.get_property('name') if tag_name not in self.end_tags: continue end_tags.append(tag_name) for tag in old_tags: text += self.end_tags[tag] for tag in end_tags: text += self.end_tags[tag] for tag in new_tags: text += self.begin_tags[tag] for tag in old_tags: text += self.begin_tags[tag] text += xhtml_special(_buffer.get_text(old, _buffer.get_end_iter(), True)) for tag in iter_.get_toggled_tags(False): tag_name = tag.get_property('name') if tag_name not in self.end_tags: continue text += self.end_tags[tag_name] if modified: return '

coU\٣t2|C I`{ymG[|?BLHw01 ǰ5Oe,[cTvC=( , ڱ{WLB;?5 jPP?|qȜ&Jw3NyVBH 2{6,)h{ȷ(daYm:n{I7I,1*8@DW(PÉEPl٦-gzɈF1&ͤ0 &p\hm7۶wY3?ӻ~8vٗi-ؼS}φ72 oHy^Zc0ӆfG&浾Z߻/:9?fLKfWEX|ʲZu_ΡA8d[V T{ _?& w/{G*?GF}C=I~cTwGoWߏy0{Tޯ@uOn2.;iAM~|_̸cX~WKLKW| " ]{г~87?;jyg+B6^|رzg~݅2 U&cYt#Lt_@ZP(I=b5$\CRh^[tTx?jo E>Z_*ajѺ0 ʂb@R Yl;kKNed6 ݄. -uQ$2{>돖M#ڱjϕ(KCL 'iAqb GzH0Ԩ1=͗eC]mjH/!&f[6,mA蕍&`Q^P@P;'Haf/Ta>P#Z7.<QuUtwؤ>J]u&U%En3k[B{'l~Uj C)eL&YBۃ KZCCX$nJ;ApI -\3 e]xN̲p]/T_Vh&7:eS z\4VQ F&OY[̒M'QڧnRC869>RWr.~QpQz.OBknQT];Ύc%l`ҽ_-ˢ/$>AhEowi&ؚjMzzzCƤe /uic[|}(@\";I2`FvzعNӽ",v7`Qx}Wѻ<҂ډ<ҳT:Z.{wzњ{M3Rpmm#0QޱsVE/WׂCm3(= BZs9JԒ9Qcou]ц EuSb"T2kaWM%9jTK_l^)j4FΟ oh eoNLqq&SWJncL̮j5&z21k[z\05Zo-EfŻXpR#qq0mܲ,F)"h0|Yyv~rRĀ; I81Ň d3i;Zkc[6;;sW{B2XE'm9Ҭ5GDk^B=xWwP|2nOio]yN噴,Z:X=dm8`I|l飳[{qQ戤QkXKe=V LLT#c Ff|4Jr>>}^aMC1d1:4c;CV=| 2$00tl ٶ vT6BDmM] xNÙ6p.PѬeCW_JMoo ׊mh!Pf XmB'H+v!ЃR!rX%TS 11wt%Bcր> Ҳik|;!ŷ_l-H:fWpo*D A$ɾ%jM0B984h.i{` A108-r|Fe(yvQn9.~~'ŚfbVuﲯF+Mޝ7ϡjbVKҕ:ͱkǜ4g/s?X]j$5ˀDj=)sӬ:k (oC|e=Tx@^Uw$^0dfڴ-] + ֔Mh|E̕J6&Tig?ֿC&둻'Jܘdgg/s\wB(>twq)d.?;O>[=B; _ $zNzزMbh|)lw05AS P,yˇm`ϬhPc;o;[NHq+fr ps;)TAՈ;)3 y3ʼn%0B&{Z%HX;}_A14*|зïљcn}N_q["j\ hg2_i1/kV+0\\wjdkqǩ !_yܾ,8JA/w 3Ϗ۶xw9J{;Vּ-8~ E,ƭw$ɨn,UQ,n=.zBcE/L04{O) B.; C+?!GU /Q*b!T ׭!ژ:KRQ7 eb2cy4{$HߠkBg:8CX3tR#:yvFu'&hߚgRALb@j=CT ;Cv\HM6*-ozly9I-u&:Izm=Z6,BmTdWC`ODS}"!sCWEupASb6[s>y%UQ ]tzHV~r4r_$ SE((*Z䌩4|V^)Pcȇ Hڹ G ȋ SoN\|;Tck\+xwI56>ڋg'*9~,zC.|BfDD2Z>l')0`^#pzat6Y%OCLmA\ KFg}E4_hG;v!0zZӒǩ~qJ3% {`(X6cVnK&S_+C =E ;ZҌM#5=>g4rU?\k={̙i !KHAj"^kد^ AM! "Ps黬~S=xGNy{;3.S|=oǏu]+5Ν:ǁh`1ݸv?WoNϖyRKpi2< IWAJT=4 b%Sr NO/+XQΓK%GH%>3wpD<ɹn"1IAUēnxZZXtLN:`ady; 賃˲o8 Թgdm|_A |8o$ֆzy=ӵ'$Ͼ` [\2n예zf^&pԊjoڼvTڌviB. E*n2ZUUy_ C\߫@)Zt]F;`bڟ#b۸?~2fa{֦TG HȦC 0u=k3 x$hn&WQݱjny??*üYzKubR!#U^1))Y~~#nEͪ]/Df᪇ԓ]is;[Mrхцc& |'9| Sm;>7%ʧ[$1AZ#fk҉X;7 ǂ)Fzmt3B,p:PG& n/2~x`r.!@gb-%;X lPGLqhp#)E*fEC@ksp\)dX;-AI2|awTyl w( ͢Cεql ױ8O (D) 0LtE}l lj𵆺̟ z =ܺA^ hOI3.|Ihƍ_7#q.61|Asr$'6hꝸahF Yw4-Z-Z-Gh&,c˦)dȔ=,sxsh ǵx{3G<nRDM*OˣC+QMw?3_ezyv9RCG&5.j\MF);j";@FL GR*C|eG5)f̦T v͟׊t"1"=oxހ\6j럥7? ĽA\cB7ȿC%>bZ?Qe#ԑI80ⷐR/%yT݉ǖuES zhBRkG35-|^m]XFMPmi#!$Azuaېn00v'Z`pձ9ORBKvm6FqҮ ^Y~u 6أwt6=UKۧ g)[JƠWF?\6 elW\!T:|-7 $AF&]+h HUDD:lmHҀ AhyY4Yk&FQkB,T铍ᇊC%щM$ȺsX 8$Gr -FiAFȸ^-3b*wH)IR/UY=jjxl:9^~{aT$$_V |=Բ&$%J!TX Fhmɳ˜~Od*jXpnB?JŠ\-EG.E|;k3+B/Q& Hw [.Rj;?gQ::lE+8w\KLO[gXē8,ZnI83^~cwXg,qjh[eNb#r ldËNnA,ӎcpiLƱ@;P h%|3{dC>R'ȝH/B'QHoLHj\ui J!N-BB-A~}LӲ#c"Sh,A3RPBLc4]=H@(! l-V91;/c[l MTi|(TvE.` r N[C94ӊL&Cd$4ZȤ\_?޽L@~ Tt3QŤ-ay0h;lf5_6(aP4#=w?BٻUqKJ!DTH!>L12#lkw2rC\~6vf!\BV<}~ݯW8af6"%4D:cjMʑlҝsW/;AgGjGZ6lN[4TZt}Rg\YcʏMeIR|sNWcݿ$jK!X;d*=\Z jR8:]dvş#:~=? B =i NwŎ vfssM+(ЇxaiVi>-*%w4ڟ}ĖW {DgOC2M!w|~#h2CpBlx:Mҵ},ZRY[Agge p{m Q4(3AxP ^87/4}C̈́z3AVf=D1u}ڸ2} ]@B,zB 9rNNPp}xkAP![3>$HH.ߟ^qP0ʀ,? _ lޭ\y41#8.Bg[tefg\ Q|-"y{cEƖxAt@0rJ5KY6olA _ `>I7n9-FW'DS1AKv| =ݺ_o7ƌ9,Ms}K!lL3S+g>ijjS?D)}Ln %}ܴ/G0ڠǝzJ2fnȤG<#㰯UT^ ǘ /04F ZzT\[TM%ι{j0QS߀ CT /'-K ob>%X;$ґ zkI!~nW3tgS:'ڇ157giǘ~>P9z qَ˔Jat_J",~wG|K)79l$L5Ap͓ xtetH6n,{3pTcpa~y1‚kqӻᄍDf NT~bX"O{Y2;@Jqn$6 {;`jcHƲ(IcI~yd>-X$,1!%;q|2FC,ij~+;Ѐ@{n#4xB 17b ~Lvpt8@=#Q7=C 6B:=]G E"C("X(+l+16s  vouCEW9UsQD1Dcs{A03G4CƑlԝ;XnNMߣɳܚr~ iϦCx& t3E.?}|mMٖFl Uwņhilj+٤Y/:hs^@lvAT7k/F @ii4#<3lA*ɴ>ӍAq}F{$vƣT bTcC0 ǜ^_a91;=-EQ~C3eOt;Yv'^d.1`<]lj痙y_Raشpׯjn Q@{F BNp90+sShQ %%aS=gvdP1xp#NƉNS0`_0 !CcK| / ;I ?F&2ڀD>5};!Bk~d)L 8ٸ a%$ok=M&ayr\`/s~g~>`BS>-U +$)\I$kŨƊ'Ǻ Ce*NsW?pA(7BX;?.=,r4ü"d'qaBx 0??D̎ҳhRX{t-E[Vz5nBt)ſݿ+N BbowzB\!hJ")AIl~.\6@!!PS_)Ԕ0GQMvxW;Ԋ䤏H:96H)v[{IقRa" ESnkAԆZ ma!f[t[>ڋ+4%`BLj̙!0xDY;Ew;&| IHLZ[-Кet eK^W|I8B)*2-k TCTàjQ8d_iЖ00 'ڟ@-̯ MӍM.nS4$.#2T I~'#-6A/ͬk!044Td"aE~55IRdH5Ȫ2644B-kҮo4Xu6y1nje (ZqWxp}C:g2bPx̘c :5Pa(?S>;[ I:i0O48vqi{xjUnM`o-s)}B"lтRQ2xB}s \+C2"K$, %B f hlnKk2b$'x-1# v5RdZ};h4|Ew &E7 "$䣫z1)ޯ磫zpc\&—* 8z<2q8cV&j-i κ14|EƄ$8tFO8XH2qxd슬h< 5E')fi:T 叄36 q@\&(XPt$\Qm ,KFhK?A&NBkaT m=02/P<^cs,J?A2({G xblK20\?ަ9IT "ڄ*DAH\Bszd1=1Ӓas&G]pmk_iHVfAFweS9R 7JJ-,R:{ܷE1OypHzD!vAt3Ĝv-x!XUfa22jiVmے0AobFk&ciBU)Y9ࠝS)rjS!zP5fpA|#9 ZǶW 6D}|?d/{6uE[bC) dj g8rMA*fPȫD|<}Ԏpk+tWV81I{{Qgjw ; Sckj=HdC <H*V pbڃn0A4Ro=27.[F3 9>~*:2Ib￿ъpJGġDj'ZdRŠM>Xg(c uL%:Ąu&^c,ƢwlzH` ]x\vٷe ?z;v],>2:?GeLSx<-FA^V" T<.9(!SܶdWl]QSV>vp&%8xdSJ׍U>='y 2H!JZdh%sCf[5dɞnƿ̼mKdOrNK e'F}-|Jc[iw9OƲwOk|a^^srܿx&[iy{fe4fF8qjw]uQ#fws\]O/9,2q57 ME6Sbk7@,>jmi#Q*J lxמ㸂i33dl6kp/8$f9읒iǞokcKu*C6dD*V 9z!h-w:t7X4=Π2f0 6e74}?$+qg޼߾{2G;҉,[{c3nM[m!maΜN<~&!W;$,ɣ4ܲ_2 pʾ,;ҋ`3?{Teݶ_֖# [o E1vORj"waAThB7կ@i#ݼ-h}SOw&Y{s9lRZ/NrK׽O9g{'=&ji&ZKL+y߇_>iB+h s^Sa4:RVdcs3Gx[$9gʬX2X3IxŌ򏍢h&[5>9/go𧗋{hm5exzGL,#>4hU F/?QplTm(iR6363:ySfXS6&C2څ,%5=@5W}#V;ln30q"Z?n<=m㢟qQ%=fCttO"2bD!!x y? 81Ipo_&T2ɓK[U&f rt `1F騔"abPv= n  ь 2s&-fFL3h۷~Gרx4$D &zTt:upͽXvND^{}&8|s|R<][OYP#|dxǟJ2F*#h ]+Il8[~ NfzA @=d*W=Sjt:d8ޢ9 읓&WJi<F>y@w쑢+i)>{˕Vl䒣;~6F-M.@Xƿ $Ѵ'm,z~nb|(m:(Ofr;dN h>㔽R,}`+?>y*p5yX(1ReThJy2 , ں];࿕}x[]7Q N@Ą iEk-=a!%f!q&kR< ZXd!(z@"I"&G3oD:9Sf$pS0j̒y,I=4P|N4 / g* "Jj:qG]Wܷ/Z$ Q w;:9Uàm:aG$jp| d̥͔;YjSTYbKw;W"kGwIďe^$iN'DƪNesZU'ZX*I1IcjC8MhScHrCܑƊTӚP.V<g6T :CkEJU ިZ81xXŏhD#,"ҺMKkpw 4e˗ܛ]ʹP",uwvx2k{B!>h¡8XX/ ;_xd̽BL\_FbҺcNW|=2 AtQ2Q.,7یK=G%|QzD7/@ 1zI5l}ibى 3_>Lce;d{?AؿB³{nLZ )cZ@_Kw×YyJw)$[_M~ߡgcֹ1G.p~#:0E_i%XZSv;;crm٧ѡ2= _?^n>7\I[nggRֹ\`٢;kF_U7|%,{ٙ}n<&"|IO 4=g/W>O5 %.>g΍9ݶU[PzQo7ݴr%.| N*~e[ -JPP=T7,ͲXIK!?K(.w;سx\baҎƯPF~&V Gh ҅vLJ?au ;*cB_cTQQWu w%GGB'}섓:WJg%nr"@+h<^7_+] 4BgԹte4P:4aO~[V2H>ɻuͻݶo^R@.II {#'ዦC͍C&rk #D$spdkSedS~=(p >oG4ud,1|cĜ?@bF`/сCE{|DTU|CI* Tz/Ș{u/G!h}ps̢Sy &0:j7\+WJHzEۭKtf1 7` hhOoP-]Ŗhrs)yQ~4ͮ;ES ٲ֞xfE c"گ߽(ە;=ύ;Qq1#@-!CK=Ջ[WJ?>sQ4Ցgmt[5Gt%$lT+O+WR7n߹x/u 7=UjcYKb<`hi],^+[K!"+q'#}oBZ mLPG{V;gŮpK~XM.&;9VmBV4RHa!Ej}Oؕn 8NjK yGe#%,,iWl/mxciry~d_y7L <"oP2!SKF`zVwZ?J&g"6QiΏ51ԪFX{>MD^0cdpڈ'(M'R}RGkȦ;m #-*E>?`-k]~>;`cl356>'qexF+zXd!3'GrrV7XD^IDu{!1צ؎ъz5d M9$R6BXa{!kSqX˗=sS˺Rech6iif$R޷c.˗_bB{ʕsVfeVCWƫFFG* C/f,\arx/^|Ix\>3lC0H$h-j2Bj!y1;~'NŸ._r% /\Kϵ':/˻(_5&q!$4RZAwj<׎~m5ƘqkTѾ$96^Hwl.ZQZ5c*%r=]74MgHh 4_h/Ļ8S2}۴Ls99ɾ 4=}/=mdrq°%M0 2tNIFGPRy ;3_U(!QN״=e?5&E"mڳ Qx;Ytzi3slgCBϐH9e`\-?UYg$=ƗjLutZk,=jI.T-Ϯhc˖-,Z~>;y϶c] FS"IXRXx@2pmEr&Z3~.~RHK(,n 0Xd L:cI#=_2's']9NpYg-'뵚k`2$Z0AR۶F4<%RI.񽯘 /r&xEae {]._״D?*#, VTW k]9V^xtlw~C=48ݸcU5 $Jd=:YёM^~ טwʱpSk pO?;%嶰u#𴰰L7vo҄XB@#T 7|q'li19eՆ׹}0}w}&} {y0)7sl tb}}lVlEmSWx[(3f+QO ת. aŕn zh1}j/˗/Q=gGWY씺>)!x1^s;zxƐwv XUuh7.XdC~rUX. oI,C`RaVT0A2?lom=+~jˬf-zO3! 43__~gٺqezejµ2!XxNy:5;.53M{_MHVX6W:oTng$|-&%BV0 ss$36=x|`nW65>首1QhVbq%ЈqND-Ǧ)#&6y72,FZas{|6Ш*b}qK˶͌+ { ,+5N(05+ cC ~U#Od+#k.MҼpM/OyGX=܋*x^Ԇ%/>R'xC,):/>R6,y2^J M?,_n? θKi$;:Dh=`x=wc?0Lbqh;\ /Dnp@tf2 5?5˗+.wqj(D">yZ+%}<]_9(_rpc(m~?gb \}|-BFUE=>WŭT_ S|SݴKD"ϩTjlb9 fj p֫ohP ȣD= 7!㓉%Uƅ >E[D*}X_uƚ',|u%d&,IeK(t(,v]1Lz_{FW"Nȷ۴9MHr%$o5+9t橜a}@Ir侧*O& &TW]p׬Ys bU| B*T _>_=u6=Z0irցgwL~YR(_x>NTj\f5̿M^e2k51K|ƹLm+Po48gxqfOy˹șW}ABf҈R\pk(\LЈLcI)V|G 35O!dSK&&(kWq2y.UD;}=3&S }% Y6>\=k$FeHڨy.QkV⪬ӆzB KTuURv!'GJT 1j$@d6V _}k67P+gq_V>4 Fr;MdyY^zB*gE n:䕿 kvQRF$vغN54B ewQؼnCN14߁->I«[(}ahnC}KoA_ sTrn\Qݓ=2&Q+WeLz'T~wcsORC(x_,WMO%C2ggN @!-+nB]HC_e_%CKW0l#H$dB,jtlkg||)dٻuFҥӧ ^l! zW~t)D$B2$r4 y"m'S;qeQG͘=X;GfمɩznO¶'_c~ȃ/_7]6D7v͢-Ɓk))3.}b,e~vjzfnhcYEićgSgs{YYp>sg u/_O>G+m^Rݙ_~K.͋v; Tjዘk_˃[6cNk3~Nxp|䁿F# |eun~y7muNkT5" LIp>PᅆݻR ,|W2*1 eem+1t鲥G~yv>9ynQW|ҺwW؍.}Gw˂&zҨV+}ONV=c)/:#1in#e .G,<7AXjG gFfli{&7"fU6sR#;MŌaǎ7q֗]κ8Y9+)x术88g]/~#1FGp|9 н{`6{ηϬn6{ڠ{&7/k}TJLx*/VHyAaF!|PƏQtMOA܄0#ڤ[5 n¢_`̓tMK0eRC14NKr:Y|Rsc67?ٍ"?ns̘tL8.ɢc# %4Zʹd'M!kO?o?Ae$*&'>I7Xwʥ?";i?DV3 Komi 6* IR;~ɶ~" ]K(Q^Bw~"޵ _L%Qa8&0se(M6K#w-=>d3 xkuGұdcDѴZ6&O'TʡI%bngj!U z*>B&2t&zG0b iB TFƌI'~.%ϗ.ezPwn)iʼnhTxO–9mP3~NBTĈJK|7noǤF 1+70_$̑H$)qA{ݺ@ەu|wΗ4Zi/hlϟ2cgOM9~~cLю4"w7mF(~]xg oۈJưg$bm`m.lcucmv|a Z(4i B$-~_~)|(`3wd|KFc/?ً1WkϗktOD˦;+Emk9;"f uVyG~ j2,ލi:gneADto¯GҎ8V HIY9uSUXt_= qVl(riYn|6_׉YݑXvБ 7ţ09ΪrǾ'^6E)k0uf\3Ķ59_-rS(r4:{΋1.14=heHlNl!2_#`Úmq(ˏ=ZroiMzXkQQ㙑c ϜB=;q%ipvO<^'@Iͳ4pdL=+.B_NOJג_gCxA*Q8f֡iug{h Ozf' Yb)3-=(=<~fk=uϑbndx:9Tp\9s i%B,СJKb3dە_`KS#s{M63ߧPk ` L/ZfJKbKAP$r8LPDI2K~%!\,XliYW 1vBmuXm:X_^Jm;q;N' 3?=HEd:J[G$m`%ӦB5P۟WH*8FiaTdhE<&,]X\JKGѦHd" ɊިsS?"R{9;qcւ\rXa Y#@ eIF`Fb:q7#?oE?4"+Bi,0/ Qƨw$LasH'7|p~ }5޽`rNk "􅱜~T8T’B@%오HN̊^ %0 8\/O#Ê?18S.]Թݼ5~ۘr`L?~E>fןf*sIhA!1Ae ϣw9cn) fҔHZM./ y|1L} OCUl [W8Tؼ6`˚ɂ5m[0pǒl^?jLl~Eyswx2SwόN@4' {17XvuAqom988jt7~Hj qҦ D&,-p%X$",cVبjnDbOHн!u8kV-}h^Js€#i6X~=UTP 8ן^R0Z×vlZ $JE#DBF[GcX6k#m :pb9yC)_׳QY)tVNp'Be(d35>N: / 6M  ximoYP?5,|)qi~ ^]G<eؙ ?1cr"1=nI* X|=i7rC=FwLnQ ?҃#"T4YNg צÄxBhS6I4BVt |0-L(pm:g 1t+REell~Xz*rpOudQf lFh\Dmܘ P1ēm mFXf|xj*U8*C}4 n}DǞYy]rZkL3Rzm BZTE Im6Bh_jMG~JaVaQh4Fցuh U䓗FF[aBڞc[C!H]R TԤZF*^!X#HgٙP k! 00=K<2q';akiёUO7ţ a mք(@O<}_|??WxES;9}\f 7Oչ>>7tw^G6=aDݫ+ntdzJa lʠFi#26恡%t3] AkP|֤b.JH)5&o,o{>{2 |cjӯKOPH9Q|1(UXv^ZCAPIMx%h:gx|_0I'S؎6R8R–Zk{!V\YV^8?ƨ='?=ˊKcALPx5Raah3^{ҪF-*;i4(hӍ+YVk}GepUdrM1s%=OUKBO(ĬN) hOS#3Y%$ڠg\A#Pc!I TlO1B RwjAQkʛH;lw#Ma8>j{[%-7_~Qݟ-D`^~Gp_)0M69O o9% R;}uVfB[V]ThgB [BG^=>ʰs=Ju* |?DXMK4as^k0t5CC@kA`*|쒣<򫟢Е3fy!~m&u},tWo_eAm{Wpw>gXn<}::e8{婷NA[BNM5N E2(U8S!~3iά9cȑ޼?5O˟?{rVLCn? 0b1߈F-hzBC,KhaY^QuZ*hU?ǷA)Ƿ}?=_R!.zE%ƌC&$_oF9S,$]6m]??3>_o-rս|z.d2h޷Nc)*!䏽9kzjcZ@P:"ש*=$ǞT׽h͍2"0ƈzj%¢2F!v' t`bE/6e4cKx(,'^|bړ}~fkO'^|,}Pl8hAx¢'y@b9]yn^~W܅u4.k!ٶ$W|v3,/̊"J7hV$tNN:0yJ3%gr/Hz7'gzLf6ܦ蜜&lncͺ^šgG%LŠ+Dp;P{춟Qqprc?<%@=Hx`<}&!{X}Na8Q))^աwǤt֦cwŦ'Ɍ5.@*V|U_,ӽż[Dw+I`% Ã|8+ogEsсփ \+Qg>mBN@ d;7g'\}7r7Xߍʊޖ35-qՊl =w)˸H{e:% ۖxS難kۥ/XvW`H%*/䣏[n6ӥRCWu&e._#JkD"0iFUD<m]9/Sh3|6´6]б!t0 1;v"Db-iVPd.&I g) 6zIrn~ f~c8T6N,Q _+ &~:] 0~+s.:4nm7_q u&# Hˆa08B4>W&n'ӥBmB1zO+%T!DhmclPJ_ymB?vth6>F/l,mB^}/ޏ )$g,P)#,DڰTt_]Zud0[MT1#Ԩ3^ę)$]fkIW?,nY+ytr]]8Ŗ|I|sxi:\9[+Pd1*F 1[C,eGv)m&*.U$5^-cR &>?Ogw;%ֿ2YC_ r?ee Łރvu}L}@f}Ozp'} fuܳwN3kBx k5oşOH84K<{I" +8:0K؎ q',0v,ic|z^uߤw5Nnk>_ы=T 8}=#k,RI)v$11I&)>/ ]H;ZQ!Se?/cld3}_GN+Z>]k D~6Wz8Yyt6gy/JT HzGHH3HJe]l~N"1;=Dgg9T8BCOl;*?<ΎU}sgde [HXCe _EEEJA *bDT Ȗ}I , [Mf3sUΖ${,^O>uΩSι'<ј'!Ew\vl]^ ?t˒,/Âs4חIքI1;{E+^+ԤKPq7dO'׮CWJלJO @,믇F6֠-RV~rmX.gOZ+--1[x/>F,BUҒBXBoy2 eI諕-oqxJH2[ 7M> 'QGaDA|NqbIH-ʖ_zߐ^ЧHP\>6izm}O8[t`ˈE-oR)P V Z^A+ARJZ{ˊsH44}[=RN/:}C~ӭiC.gKX^ɐ`Nv,h$V PD*p@cC4ߠl"%kP*PVĶʥ`/rI+RvĶoyVbD+z(I' y!Ba *eVP,|G|ҕNF+1CVPQ _kݲ){CO'a zX45Y[W s-+1FxٖeG8{w]c厯}'\%k0;YePB vݲ)(xG!#-/'XuyatT 2&ͽLa=d;Uq,X x+EDRΗTbc60xĭgr wdx)oU,XڶޡDv o Ô5 :&w`:%E+`.>zyٞ27|9K">^T}$>W OxuOHe|cYYκaW#PW&UMPw/)SY>Zu6 s;}s/o#sGW o&8=+OcS"9 &I2Uk"n}8+-n(9Ô{BǽԤI7pϯ|㨓j,MuCWWZ;῀t:k gLSp{lPb::i'Ouok_\S1B 12 LC̼7$&9S i(F ͅ}8nG( 4 6=r=[qi=&v'( =FQBوr0_n.{T*v@ASCdY{~AFtnqWٿ6A/ڲ%%Fk'psOs;.>K%E_bf+ FX yH?^vϯ)4w=3oǷ;~HX+0a|/\KZGyn^zJǐLЁ!][N#+H)J\DL(?˧܏I$fsu{yTV2Oê;2qOu}c\iZ򺐮-  ,Qn0th*q4?Ǿ;j0G7ذ7TT;H5NQ;DlwF7_~ic/}(2фd'@! L w]O\uM*aLS_ ]d2Ex=Ym)s؂ ?GLJ@1bhWjhq5n7k"|aHEaY=CUGpjD4vCp .csGj){yt c d#ٸ&7 /kd ?KU%v} 9L%RKMM*CU[,+ V?i%+ фyX8SwKJ]◇y3d. kgRl4$F#, BU9z1R(re/tJ )g;J8+:#L֭t^ߊ%amf :&SVJ-a2Y]7$jKii[ٷə]Tִ݂׻עz^:NEi#%y[ӷPTz_PZX"45fil$T Qh|-ϡ H?u{`\ >9ꋏ*Yx[X8dW|i:kl]B%VdQjRX+X"G{$g|MI]-7ח<\~i#4HΎEc wXX2Ni2T>v8jB85w+DBI)טK[[m@́‘kjfzsV$>r1M>M#*Mko, lY*{XMf?lEkY'~kp $&%S|Kٕ6cy[J`S.Mۛ8}WIY~ՓY9{~?]8ɘ!sɽX1AQv`5r)V._.[%f0o8K96?ړhXyϑLto7зYt=W}ְSNnknߠ^{p5RD}\O6{Dp_HED};(u*J[[sdSNXֺ Y3|5u,?_'lx>ipm he]CU>[ۯ53>#ߴxe{QV9tnPYv?P0詪F0H'ZtVǭW/ֱ>)漻Gn˒Nr&ۛ'q枘oнTppX'ԿJvEJ*)/ϟ|ᑤR!y'Ģ|:HwWrpg ؝n GayLSrI8Ad3.b丳/>CO XOW;q?,W tã|@)D*z)20(eX\W?Yttpᶲ`eτG>ϰE- mX =Hmq0Wa1Z:VOqa?XLM<?xsvaN,]^1KB<}t%uVX?k.N;&ҷl!߸xSIZC%Voy+z111۲}9s77c57h_y0WfR$;oَ{}^g6]]P~c)4&JlWAs_7X4n FJ[ Bc@>Q7@ tF@E.rOwdژ.E_ VC:O\y̅t8DBmtm+}Oշ'޳_mBncahi;\`,7zC"v½-˲L&mr9bUą:}I[6#I7 /=K,Ö/FszkBP6$3d\Bnѧ٢:Z|p*{P5H+3!e#6t,02F{Rvk-㰟^z:ior/+dˮ{A5sލ^]mB&B7rUO߫9,&ѱſx+/n-7 \&q>`G"hW.D\ϗMԉA% \xK_iE'?IXTM n'_1?EzMHzfdTQ6V˩kcb>dl$b3ioqg{H)ƗT2MX߶{q5+s r\&U3X|l.EǏY_K: +M?.*Gl;L#4඼Qk3l\ڻZ:w>[1a Bc/{O|[87L1bi^~yT9fԲwMhVYt`0V@?G=!ƞXNH )">ec!v"+|T6T\e=֨X`U_raTq55-(RHazM&"?Ē*xEь{M$ T U?F aA6,۲)ec:ߦmE`cd&yH&AP=4ğQO@m2OoZRuVmA.kDоk;G ,^1~IkV{Ŋ9-JD9B@A)%sp\BXD"6,XEK]߾KXCF[=(c]3eUI1ud &^|_\R9Ssj 16vT^sS;`1s`i;ï/t?k a%(4eqc/1)]:P ѿ3i tHǎTH#3WEA;8VxJOG~4&e~ej~?#?ﰿUoԯ{$۾qD ajtmApG_{mYcVWwi}l\f2jMQ-ғ\6re:ßLIq:mp -C|4`VocoP;ƯZW^a-ub·i@(^zλ\-_`Z}Fg9cCSB"v,6nVoVCꪲ効 Rid]dZheŒs#`… WKoFL'Ź LjƝ##r8b5@)@5^:Ȗ.]U;įZODjNqpW[Q ȭ&TpQ+_E%y\-usQ*FyRjS^e#WۓZϘhՉH[Te3Kʰ#_^],\z/jԴ+iv#0(a!c!o<Ճ~6]Q8=%MӔ]5! ׀M[*_Za*0ʷ"?2?lЕT`(؁? #?Ce.wԴ#g_ t>„m B49N2[~m+ ؑ¯M S8̳hrS|A!oWQra56lIk[h:=ʁҟV@#;_Qpc05F1ϲhVZ):KY9X^w}ۊ;R_w S1ynlK4EPJց2%O̙[?BwH).t\˖% ~kT^3X|꼅ҵΕ'hv6+n}+wg8b[ @4Fwߪۀ`w* t8 㞋 i5!JfV`[uv|ɯ*YЖspIi5YҖ V+]us V;RCC t驧,te\[󄰚TƯQ Vzp7=|2|+wsu1fliׄLM '$ 1__,Dmij%BlH8}zdǙH![}7nt]cXz'L]:̈E =PTLۄ úOcPwpz]S}l&VvםsώZss1BYu5igCu@_wϏNtDp"qIDATu:ޙd_s):L2w{~z%u~~-@Ϻ?*js)D߈OϺ{*|ǻg4[ <_?Ӓ28=:6?jw>)-Łu-k;z'gݢeuG ='{'gD[եsE(iKI\;4+66&\|!H7¶,Gy`[F_߃XU;G~raJ™gKV\tMgڻ'~Qqa*m>|Bsq"&"Q.kՉ_^I~V~X"O ?#5պ|_lj 4SsIgAs?o c'G$3|B|@"ŎD<.'|/_QNo49FSsb!0Mt-[Ӌ?.rĎ_-ۡ*ПaqXu!,nFc˚eNx:~mҲlJ[] & Hj#d4QΠ̔=7%݅y ~槰^#IÙe|D}|NԅyUA錑c8fd3!?M*Iv9C xV{AG[|fjErA!BݍGRJJ5̉=;~dV{0nZٴ,hz B@Q.U :l/nк̦mA/=/0шBVcp".Db`.P3ZHR_$?Ax^`#m<& 'IrgB<̆I6+mw/kqoy _H@T260IRP,Ȍ1"H;#_HIPG1z5X|•`܏_ǎAwmDܲ2 3 IKXAɣOe2iH4x܏+F% W ~~EMu`L*tBH$ 1?VWe+30L숋\MeQNWny[!0댟 iXE@];-0a'خ`d P>SM߁IN MsFگ`x#"Rjs~;!r^Tc`M)l'*f߻o 4JW71T*#S.kD$ƨܿU1ABs$ W_% Ԝ=t9G߭C[vƷt2SYX, =>~ DZWQ!\g.U6%be[( 1 ~vOcbzhgd+ #-q9~df&/ iW$J=ͅ^ތAd` 3P֬ 9AZBy,=+tC#A/S"~7UO}ۓǔ+aЛ<>Mtj ҉`1i8 7ˉ d8܏sr ˍc,{Dd==K?Mjp-6a%QCB (JNzR=Kׁǟt 3~Kb"4do$Ap/[ D!ѷt<N,4v/U@Ad#3I! V>=r57~gwd/|c!)HɞH&+s!ЁO h>S"uN'lUϊ _6wkmq ,E e5I6o#;F DY.JjE Hv\'7"ww˥ i9 7mK K g)Ch4ItػȟI<$N|h 8qA`kJ=ok KW;גf}i'j OHbn}39R͔w :hdv @ wEU'rΣsd}/sR fגqJ )]ߊw/(1+PJIoxhxc<,?,b_/tPG~s^[S?eF?I~YĦA^w9wQu3CҲ}H&ŋ9Hƭ_V3mg]@[;mJ m,H!(*yJ",h4A?!5^I4u6΢v. &3j sK¼?fϨ{بRX1'pI!\,8Ěok~KNdBj\0?FRe%y6CM:((酿{m~L~+n<ˌŷA^kcCߥnd )vϝA썿I*.7r'Oa'?arxusmOB~ɨNTLEFl?Ev_COށ=pϺ Xoz_r=>k\/;Zdj0J_”)Zq6P$AiO)N5\A;(?u$EH:$zagCd8$ dQV3Oq(n'ǒds-m?upb^33׶)u|A{#!t1]K,|oȖ,ʇ~;z&9 ePzj]/я+Jmu3԰7 8_tC%8sc,Tgu? 3}qX T{u #0#t8wBF)GW €* :>V҉^t PM煋!!HI_ TO8 >)1UoLn>YHu4{[:zF @L܎eG5F ƒ%Dj`4F@>ZG i)Z#ueqJLk_j'jX:4Z aᗑF#L[0ҟj &0eh`] f9< [߷)зclL9O6s6Dv .DEF]I Aa`K%c] _TBRv8'}!%,g)q/'ް[HX?@^gҰatu:?$6OOq 'J |2}%Zx w83i ;S~GT = kx+' ҍ2/ފ[ ](yU!"~F̎ T~JQ'ڸ+`Mߟ+Hy]{ש -k4;@$Y| [vD#&!0Ǐ6Q{^vO{(W _'ih!x37a t=B{=C%}dA]ObN'ULBbAyS |t>CkdB HOG!ܪ(w=oxm)ħ. n1It>m2Ud=߮Щ0 _"޿@3B߃Psɔ8~@~MFNu﵊/}U? ׌78zoNSyȽ|*w|D97Vy!.Unr#?%D3j2 :Q "?*,s_ >y&:j,TH ) ͕ | _ Trp\ɉR'_FsyUĘ}9L9G5g(MBrΠf&=Ƅ:ǓO r(e{чX^C+X^|S'Z3Nx9׻ Ѱqb~hb>ѽ^b &*RH7Ir >#?|Šɮ[`ՅEwOe|)C/xuK>i}d@e.nu,u6B~Hfv!B>j3ydU0,7;{:dTwvPA@–|d͕A ߻(Ғ@2Xn/2 m8HhmrsHFkL:XsATrqބК7^ߠۨq`IK -)1A.'.=݃Wzpmgq&uRat#ٲϵk^7 - f@"oAοo"^? (%y 'd22iQx?av{{.6F`+,zx'oÿ'ri}a!=ǎ[۸t% Doh,@F- oς}>tq37twFu@8)[CÉRan:)ކJC݌OͼsHw"v1:r)MpƷtK/d3_T@P^ 'Ĥ+2`Mrq? +EmU+^! sNϟ]̫bF[Uş*"]L"r4<L2rawx.*16M9=b`ottLRT=U- m }E3qRR>+k0ҥ7㹈E;> ew|n'Z\1NwBľdN^%[*,FkӿGGh*ߔ}~7dX*G0l_㯸ژϨ hل!!>@Wx(Y:467VPo w~n,Fߏܶ!~Uc\[iKTVa\K`Ra:_CD#;l|==_=KRd @; OkcVgw(Ӏ&tEP M<Ѿ~#7?k<7XMeNxu3i 3ɓg-|#ll5WXq:+Z!I7JyQ;)TL@`Kj=k'sw_˲v~ FzvFY}? z<|AŽ6pL\U>W dχ]<<+3;ï_oP*ykF*+00V9)`( }XСq\6ħ9Ȯbw Jk!!KsLT&UK ^]l+H~8²(myo2ǜGԯ;ٶa+9g}oדDV)  O/ XnϝDG )zt t'EYiὺ׃1E:ܺh1z?> Y|pSEg΢W'10tG{ax7Qa  -"nmi9z3 TFjhhl7׳þc$.p0:ܗnwv5Pш=~]nB8QDĥ[ɻyy)r3ZaQ\]_]3 WH֡d<#@ڑP?; KIX2vvD5i_m%Q kXGHtUK^w!(yC¾ctt^Fl7PtcFl 'NCU"\Eh1iԼoED\fb|C˱1#lY/'[0ʽ;Dzrs=GC<=GbI;Y]2? 2 -r^IXqge7Y̯ȽKlK{q93MB{Dm 1N&ޗ?WhlC/ |,&]D{_ mc5%V>' J? O@2\ɍ޻SF)cl!5~O2WI^9$m[*h'ϣ稍(%%VQW~r=޺!N5`fsAw4+}%"8`eْX4¶>P^t%BRi%mm\TGGQKJS$q3D{Ecy, SSr '!-4Ң/M.&0PDԞs-"(W\MP鿢+A#1gˢn4C! a DMbI9_/4D* ҕهؙq&IG:^ywفp\="1 'B!(yⱟP{qҵ=Q rhH v=r =mУ,0 ۶)nfŸHC+B#0ضM |RIǣT>7$mwL5(KF@hR&X5DC4s̆ ~Ua߱pb54jo}6"ワagA#ֶf|DS4y9t?!]Ln*Q ,55D_mڇ)1 Fb,Y`EȤ┞uMR/ l*GIo?"o3+k߃?<]*߱+&!ХəG=5IՇ.A9F?З+pɡ /'$rfH'_ci/ !}ry855bL:2=#Ce2M-Q;Ṩ{ߏ;Z f3vI\~9釐x zJZX^Dr17u i|VC''Mde|ʻ9O5Pn|zVE!A2meߟ`XF-8Fe1nX85<1V_7l#)y<,i77h@HA B @jAyfihtctu|7H~,@=sN x%nm㋸ndh^eM 'y]b`'2;:kJds>u (ADucl ~i '%ml)%k`:‰P*?|Ɏ«VcR ADxIgOg@ք1V EQzNjgS ׂW`,'ezoc F  -#=[~Dy%Rn#9b/AS2 :cdx 8qLPЁp@?G } VMz"(*p_wSIu%8q_N+!Km{&Guj%#dswRsε;Z>+0(F:? #ZDɴ\a\F5]"¯JGI{Wt`ul! 4C2;1`;xx^H' ^'unfRȗqs'k1tGſ~IE0w(fJw_EÙm/L(ٻMͶNu8nrߕ2:2 z"VV#$ôQC+`i:Tʧ|c%O_QwAՀQ`G> CշP#`([Ave/:k.J*?5eoQ+~O: SVm wy؋T4tխ_ ֛D7anᮍ],{} ܍e}'\O)>1zz7$pMְ,UZ=JF28Co_ |- Ei1P|>65WŔ7gHI0}}<DdiSg\2;SRLd fG!vψ43TCrX$).E#H%cdt |iQ+Ktv|ؗ 9d td-C9o)f)_Q0$ ; 7>1F&•#QK*"UzK!B*?FBx6"J 7 ,rY.UJ[P4[-ouqƮٲ!3RJc15t|EjTxiTLg $zfҫ]b5`4l{' 0+a 4nfݒRK#ebz_xɼƗOuw1CF\q"$H&lk[ ']uܾݩu|us/86,[Z&6ޫ?r^G=mgVssyMu\}G֦ʮ̣G}f&1t#ϟ ԴSVի9rV^=dz2l`ֺhcf埽]lt kgږv N~މw6cLe桇:{ݢrH)m-k *q @km"(J/]yoKUǤY#XrCV)=DۊAk+]C.ko7y5wo[渣B俫f5FTcZ 7oKxukn#/{o,Ę`ϟX`N9G8_BQ[`0`9lg|g㦤5k~d;hAzk7O~VfCءw{3~XUt߁9xtS׹OVsG^|̣\ ^YttUG~:;zk݇-ύTfgO[󱣏 c=`h--}X䛔O-m]7/cc47[CNXXc纖5ɵ-BO))?nܶ꽻'؄1F !ʕ+o2eʇl޼wys܌r4cLvRJ,@k=QJU%M֨JUT*~wKfRB@_gOb}z9+hCxie7_w}#ׯZ,nEL W+;cZv/0%&Pڲw&"5g4Pٛ)3%eOˠ1?->g` txs6}ڎힵcJ3a!.LkڵBf7* %NZQW655 rux%Bfk֬5V[c\uU|~q(a!o)K&CU޶Vن7L}p&pZ m%]`M>$G~@l/[V­6o {(GJKiۭ[[% av̢ȔQ1ֳ>y@?:YlheLb4ЎyOM$Lwn7;eG[\qGbd5~#}3)jAb)TӞwo}1>Lh]Q/?|q@[gaLhnX;ܿy#w1wގ2Cw={Dp3IEXv-Js>as>U+mPHIvq~{y\ƉI y/;Bu:?\f2?NvfcO%VQŝib9²*Pqۖ1!N=/o*.Jxٲe"xG=k֬rԩx≿ӟT?3Їz}h+2Hh JaRژMDD+q#bB]丸ۛH( 78oxַ1F|>|U{1i!Xw߶k̴SObO >ݍK[\R+o=}F%\q!,^lhk?6e6R*P" {h֦ k>7E_1?sSwV3@RS chE {5f|5cut_;H*!U绌8)JK@GW?sDO>b뮸+ֽ+S'%,lLȫԻiܻ-N5#xǿ>3]w@!({[ WyҎ\Hّ ōN*eof wv#YOXV>g[Z] {A%=Yݱ%u%u.4aŢVA ,~?c]4=u |!B * „%c`z4:'&=bѱdoӱM˖ ,xk}|߷,2A ,7o8蠃9/ӟжMMK p!ĸeW[k|m?=ˍ2Ak˲QR"R{5fN=OϾ7f%*/n3B ػ1s6Ahe,i[+ٺz/<?$='^GbI,#ls"5SFSeY"#_tⲡ1.T1?t@@[gEv|M{ֆ^?>{{{cmE ?rAۊ7F=cW/ 7ϟ}abC1_{聨b>\k% !0GܸpY1.@ю]*X[S3亹}MgqXb[fOK˶#2ƝG|7.h}+DD$!ljDQ"u|1 &I8mzI+ϣ7uGc7Qp=inb:K0wAT[[M$!LUgXuM{EAG(R|QS>{SwBo>=/_>a_W5ԺrrmrZ zʢΚٻ!šs=:HoF;0Q0C} F2{JNM݌j+7[fVc2њ5IjW1}=]B'""4wTIY;;ܿ1CIiJJ7fsVy4whcuV$?B=]2}YoZ舧5MzrMitF($N}=cLuӧU"J+]oE/{lІa`ϙ|#yGyǂZ-{U;jTzxfkSGu~؏k4)?Z:ضvVc vw7.}{9`gUO[0̟Γ}@ n?NL])~~8k+$7VՌPlC~LLUV>;,|~O[sk܄6aҔr/ 1+U+.k 6db5\-ZhlK9%'OrfB7c•,Bt藖Y_m0*vWࣦYB4K!:'N.F)BtFҮU DvXmb:'&uN3CFd*1F,_8Z[[essiooON[ݡp9hxub&A`YCY /o,>~ڡDžkx,:+0%ՑiʞҀ;|m[wt;sЫ̜9[hegcw/^rq .={7ƑBX~k>rXA`5H3,JEa 3|ZR> n<{Ks1o{FEw[QbA ̌;"k6>5MùzwVmZ:ލ4LwȮ~휆C.CZ_|:ꯍbrZ:G*F<{êͰ9ncBߺG_ãgCy n"4xh/L=-cƶҊ#j%k"v^! ɡkmPVgW~1ɝ5=X>>Ok9Ǎ5:`$Bn@T6|_4O-EiV 0#Y.&~n\$B[7> + d3 IӜ41?5NE0}{u9`z8#O10x ]|/7]yu{˲ 1+ IPM";3PUٮ@{p}1q/G_KI7~ĽCJtki7V-°kJoyZ Wηz Z拿.+5vM -wz_?ۂ/jYEd|ݍ{r6vUihm^+,r&fgJZ@>5%-S]Y=kYkfQt`&ʳ-_M{?:<C|i19?]qf /&<ˎKU.(AElnL _+6!dI=Xt)eke9}?xh6#G&d2G/=kEdԳ=OCc0ZCk::s:5BQJ 0BBn(7uG\qOΛwzlN+cA -^!~vܹ ]՘.q8㏗B'^{5T*u]yMkooTX3Z1`ʵR jBtzp؊qv~/_5H:qV(vۛYk:ƴqw/yTPb|#l9<[x>k¬}ܻ1 6G ޿z/_Zip㶢c8VeS3!1DĜr59g LKé6S!0yt /~{o#3][.UQ[^JEY<&y۶b3sz免ԃ_ٸ[Am:#^?M+򵇫{Cc3ߧWL2 !E2bwMTxfM~nU.Bk_b8Mk Uw}a䚨9]Ko:sc1d\}oF JYޝz :u+?{ݎR`|xxWp(`,-,92 (h؇*ѽaQuV8`M:عҸo{uMc05*ij6X7AhUvrbKAom%|܏810 YLv@)%,c Fe|M 44O:4֌4ڄ%HjLwѪOf}''S[ou)h- #FX &У'6ObمrY)y[^?yuZm8~$P[ttY^]wrYkQPJ8Jg]{o}MMnzg=QeuwŊ_9sfsT RmA>7lN:iu/C{QoOlY %P2IQp`=c019%090An "c"H B)gr3]?f'|sw3u==]]UO="g>M5.HRUb筡q1| #ؼ9ۨeO.t(^mOQp#n. K )H &Rqw4$<}߅Õzftf{kfY;,-e / r|@TjFtdQp,a)"3f1cSK{so8hڎڻYߜ iNTsU8ih#iCƣt2 wG5m+_\0ܿ`p{ LT r<ϹW4XO| pέM[ WDpW ˛Tl|9xos|o4oA[ு'KF IDkrٺ;="ڼH}Ӛ?}d(0/GȽNsרP\':9PµYKCQq>r::rZZ1h)T9@<3|آm!J{'KmCMN"4 an-`IӔ^0 DCċC΁M7ʀxҾhH# Khh~Z6.@Y?`SSKfJ1D2S2 zˑw7 ]nX[2HLI=[[N4FjgbDE{|k?O]|;=f  9ES/YkQN7G|僫>`c h5E ]"Ik`;/pи(G"ssԒ 42dj2`%'!u&@+_[|!cݖ6'\_~Ÿq.=dŸq =a…A=/礈ȯ<5~N~~Gcǎ=luNMMa"cO>Ő!C@Xk&8 :FD:coí=^);`J!ytFzz'hK=2^oOF?л? 'p;h2srY@EtaxDr{yPfCʌ1x 9{+iЪSc'tۻHkll<#<5&O?20{|vHX0`LS*e cvz"oARnayHI]LPR@X7SG"iTR ؍ a+j7:}Xlqf}zI aԐN(TnAKKa.#BRɴ$ N 0{JfBN RbgٻǰA)yހXi"M&4ͅqbC|>7L#[q5V kṶ3#ͯåQ8x$-,L@P I %`h@WO ILV 3-1!ɿ6l֞C04t1xG`im;v!?'/3}R?\24ȤؾJ͟{ɣ&FQxaK}rn3-waN&ŏOpi[?6zرim2Knsxog<rҤ9>6=gЛb~^{n݇^NfkB)sf͘+p h+: T꫘¨ Qc`i8RPy83;$J۹&er)\鿿ǔإE͸q.&-I)4!Zx܊VVpB} xIHD̥Ԥq t]\ZZzh<aÆO`Y[[k7Dǃ3;o999J4Ƙ4 C_z|d+v~La{_ko ~~zːO>" .%R)?0ck{ :2{1R1f8\Gt8UU&+4LIqHsqcϧO]V5u2-w8Qcgs/^Y ҙjdtiSc:tojzonӖ3W[’vlL\оy#8xgMKz?#K@JB3܈_cǗ ~? 2ʕ][ZƯTҢf{7ߗ}0އ{.RreSI2'?uS&)_2R)A[;ґݺczx%tN8%0n%AckWjZ!`]o\pC\_DI NyA1; qCR*tHE)(s쎛BqA` s li䗬m\8;8$+tQ \tK]''`I S|f`f;Rn@l)I.#RupBU A$@AS44oȺŨ|3Tv œqMYD uR|kjZyw]VxI$ D4^7 k#Aj!]+zuY7[`CӘ8_}؉@iu1< aEؾ>"f\:;뛱מ^49]I U(",p{+Zhf}&wnw; Lsoo%`z8z4Z]k ,0 ?=?_?Jб*g5, .B,IV- =skc]{O~=lx =끩f U)8Ud1EC8U՛̶99aơ3V]+>Lcl0r88. vRpcdBXqeAv1e{ُN Iv$0|teviZiY "XD0M , $ŦcJTQeM===fAAKJ)~2 c7[[[! Fً/)**R) \.mƍΪjD"/!4 &O>A~A4 7x d,#@; q](ͅi4uu!p(8HҖjJ,S.%IrY?$s YU-pEJTi\kֻcs,"Puu8@ G0{%'Y,es d$ ojzn37Q ٥\a)4:X gC @׏󯀞R VF\  z۠ SnnrCK{M,/Z9V5|6wG)\|9(W%16."U7_sF4sR(tr{@`:\Mk%%AٛQb 1mg Q vNRq`h*i (ڐ*CX|ݰ}АX@GnTU1J#7Wk 7VqK\|ݰ]-% FWtLo-wZE(Ԓ҄tpq%p3<Ӱ_߀&70gZԕp*E7S8 S/(4cRjPxGLK1e(f.TpD?EAH%݋!|j.^b8BE?gB(/99w>BM؅]yMA .TZfHq=q #b[K]1 ǔJǘl bl}a֖$P#m&q:[LgD~H*@;ND _{O'B1~i׆ч8hj%}(Ox̤ӔTқbniPmQklU8fդn]J)HNi]kW%Ca%^ *m'Cmop3ۏ J 3ΕI ]Y d"ԭxcAEOT*bZ2J5;3iC,} g\~ri~3&`C;o Ǻ73stˑm@X$}asڃ`AS*PK!KH Ӳ62aSemHX׈rg̘/p˲J>&;/ >d2)VMMM۫fΜRSSE"ݼGiYrsAeeHmW^\z0z yu(saY4׭a%`zxwˮ|os,{ ނ9 =dA)CqW)PB˅3a~ NQFmt`iehIrM a,!Ũ8s^V֯tAJr .P̌qD/D:@" 儝o뻫‚P*p[ MՖVbXYN` HHAd#/%IHK"V>W H9|XԖ5j+_j@@~V3ִ7N ƲC'c97no3c*Sx_l!|R9wWd*B Da{'R9;^xbORR83ZRO5"E;ohWR$\6M7KKKhu[H,pM>=\5|ߤR)! dR߶mۥvڢ j @0rsa}4⵵~8G']q-C2""hJ Qq%I;Agʐ)-) )q޸⃓]/xЫ#M%$]ә0Bok]:oe~Pvq=ဃU L H% @ Z[HASP$T:Ӹo` O{{uk=f6vty~fQHV弢ٹ~N'cfc+kno?nލgk˚ckL]՘+mV"/=sm%cf /_՘)9fYSrfyo|7>D -FYHNI=cEK\2ns ߵvWjҺYPn66{{9[Yͪ(?k2_?&c X^Q@uvNM^ڒn7Lgʵ'ᯭG$!GPVW㈪(j=d]lR ҃,W|l\|gwY"]6Q:;'U(I9oAİ4{K$#'.(}^0?X|[WUQ2 (9d2# \txҁ[;tx %gQ*HNвĠ^0w hޑ 3//AO 3// ;&GWsP1ҋ&%I BsCJ;Gig,zlܮ~&Cf@~ԑ%g=0heoS_rkHBH*0LVWm]m +4gtò.uۺt\̂ M .r\lݶ+G]9aYKortm{}v`%4i{lٯ]T9%n~ʇO"w(HR ;c^ Ha"(RYvj/K8eY])R$%SRK)FTV.bAe%#Fl,eY*eYvccRJie&7>}z^VVVN58֭[ӧ?'w눠LiӐuTf׮EKQ >2ڭ\)dvW{J pk\3ǧ}4bHoˋW}l8\+:uUEwԌ*RBCBBI +z!Ѩ~G:2CbAP T* (>X]PտuךԾ#l 5jhXsUћyAW\QVS )>{pa$k7O|z۵NzG7Hv[,ggAxUhr ̹b1jXtW;ƒC{>'\ _Z4XfCil3n!hr~7>D`!8L63Px7C_:/C8zV^,V#yq;!\yN;ˍ.bTYC ᵣ)L) n|8@?Y[Pɗ R?J!Ӈ$IBiL:dsv nPmqD @61 F=P8\kH" i%N+tU+s\ƙaIqy,XzնTVB*_ӂ t]0n2JKn)Tv`ˊ^ 8 B HM:>w -?2inL,}%:_ "@:"(G62rޓR:IR8Ռ^Gv~s3+ш5aakW\y|ÓIHyCW lz|Ӌ<~5~xbW42ڶYۺsykh:E v@K `W󼚫ȫޡ'%C I`XJ ;f=` CR J2̲ R`C#:uՁ &RpsemeltO+((84N#J10N PXVVϜL&Sak׮/b7ծ&L$;an;D9(NvqC'_WJ8_݇X\.pVj/)uӟbfZ1(]czӦk[W6ƍî {ԫ#`ZtFPМ91pVbxwy翁ΰS* >v$(hkn)+Yyo8Tvja(r/t`ێ -R`QDZY,rFjcr>׼0m Yud쁒NۓL@)Jvۦ"{l.Ѯ#DEVM a )%`) _0?`#bN/vp,cX@\o0+cV+ol)P8GMoNC[2FהQpXec`+Ϊ hSopXgwn^unlS=x;V}9 tԓy*ZVY5,<k:O=q|Ͽ?7rKpKMK=O{]&Mi,`AHJ\O.V1rU*ThU]385?wh,Pc6tK󼭀 ΪBϤ/ @n$E1hߐ%ҌhI.hCrr5htqc][__5Mhɐ eӾA;T _Ӥ\n7OW769-S Pd`Oa&-01 )rϡcYsM' >ƨ5Vb: 0kGUէYD`Dz@VSSS$77W=K@ bAARvV}̙Fs÷oLsN<O> o: Dx-FoC`֟Eg&\ D"&597q಻3ŻgY}__" [Τy#<6s6U[Q/=Zd,FdC9RQ=nwD V;w)yHn+H,r@U}F&{~E_/ hep, g ?{$c_Mpgx+< RlB^V ֧Z/zd$֟2{|'+3;_X)9ǥ1EnUCrn z mA)e|MPez rnieڊ :`EnbҤ4\ln >4,"pNl^UOxSc@1pJʻ>=%QwuhK_zp$"AP}7cPPyx1-~} ye hdI%3jWhWgz/|L3\T꾂3\m4at.c:`eB Ltfj4D{`?F9zWv,`4c, X"ubÓ0_ݖA$U_rD1Θl-yÇOJ)_;sq 2+doJ^(T jop_11SiMksHdCb{a|ԍ3Om 2eFS/ٸnK,+w9u↿I{̺ŌK3Iًayl.}r/ -1@wx+6^z!yDٍcxXֵl/6S LKqXHC0xg=x(qI!a"XRf`$ӹFT2bߋp17+G$Lr"ZKNjo*,QHt9P,by rS{aWUUI' .77weYV\\UJQ:fD"oݺs9"6'ip^/Kf!0嗑3~Vdynii)%0FhI6~Q͵x`L,`]׶CVK뀁() hمc*zQ[]4P6"|3r|qcc'TGXbywj<#]Xx99;K.( ]4A]@MHC%hBF0Ow|-o!skg8ދꚡ^YKC'<,E-8s۷O!T!ZgϐY> `X3dI-n`W 0MAHN" >t47% ""ך&%̤P,~S4%7~2\G(L)kBvn M3%\zI"K)%'DZʤnn_ˌue#sO-Ԧ[7A~D!ou~濍ޡYIAP!%?ji[rcIL~,;'slJ dTM]oe#cpŇ-)CŃPҐJ:>rvĊ9`;bhjQ5=w?wuX`#%JsJ!2^ pih"cRvyfAtŀUF "N' !2 ι~>GB8ZIs5e ˗i4WP98jPoT|tWwPN5WRVBTƎcK`o]c'5WS:>\taI./l1Z{r*{| a@R ݴݐLm|9;1YĪO V0a9]bH>_?@{M78+ٰD"?\h* P ^-oyM?C1K9cO˔ )ًPI"?6W&K秄RmHR ;C&KB>g@]/ N$ۂq@ 뵙+aڛN*ufmƶMt&:hORB1tNxѰΚ-0_)eB4*חWlx?Ǟ.e1Lh|G7I8D6EpSSYr7{fS΍dcoLG@*"E+ ?6wrpm5PWC&t-r6D8@' +\/?G.s Pv:LH"6ѣ%.(մڻq.}SUSߑLa p#'~pAӷXJAAI#!ƀhN$xth~]2Ѭ2$ԨM/mC(BTftu-|ҫi)ADI\apM {v&1$R^9#_XhU4\`x<>9 5)% Hۭ_5k\\SSM:W^VW))QpXӰ Q~9Hvwz#3 b%j~v? u[ľٺPMHdթ]n`Ʀ{sW<6>GV sF{f1\9/ 3O.Ie ;@!h7 ?Cn0wu DY'ocfs=L66@#WP!sG!a +waÑ? C (H؄ӣjЧDK=sZ{5y#dYmKB3tXa:{Y8?i^e/C-r=ڤ@^hcf"w[Y̐U`R9O$AC^2,޶ܨ^sAI4+ȑEf IƟ`^*a sf>*"e N{I9{h?nނ{s\<+nF+3> nn-8ug({N^ge'\>Oߪ!s|@C*ܪw;T 7 'B`0Tz;TpӋwA<cED19c nR~7X4L&9DT]lݿ1<xHn3;5~f@U= f@׎a&"O5eiРUVtߟczۺ R"jPf{愂HBG;P|EFt.d#@P Йqe ]-̈́GElżfVcYmaeUIѫ?넷Հ, ~gqy~\:df5%,h/mJpj pp&QpV~=a"!mfsӿ$Y꾓57W:_'Lc8il=a%>5iߌL6<˨~q B*ZZ:◧z~=B! @ƷO/ jcD2vF3`9LB]3cJkk-f$NR Ø(0cX,s暍U`%@2g z v!%ħ_s㪔g}F0 C[ k>`0gxݻj)9Ȥw~㾛s&@7yz mS$8>GAzҷrEl9>0ȒMeCcر-9ocT( @}YXש8|f/_|Z]|!C 4>} x<4ӒP˲h&N=^rwElO/[gS3TjeYylm˷eW9bb7jCr-s#UO7[jB~A4p/ȸp+`%:n}C6Q?thxo€tT0$!h@OyG,혿. /| &jnn /|4q BÛRJ!GVڋis?329wFB\d{A7gp1W^yey{{{i4!4MSw7> jɞBϻJD"QC=SSrumɵ=U~Z0TMIT;.fuܭ!S|K}cth0`Dg?4*Õ%"u"Pޟy]~6Xc#ԾzJf}v*` h97 A - (ۓvЫ6F~#̫QM >䔡^b:tDQó-mtjTLS} hܲl9*_vjH Q򜷺ځ{:gkuaψ#4_q˝NH?yBC4)c0rhw6 ʙܷfy8ޭ ^~У^Ko*Rߌd WB8g5|7~cO?]h}&|goơgi9g::tj Pl /.]S,`\.KR}2d]LLg!`?cZrUq&_NO=w/^OX.Dvmg(q[ MzP_ eVUc6d嘆nƆ=5D0y>#]{O~'N vIIMcƖ z)I1))OX?hޮN{HJu؄#\"ESuTpwc@R-^}ҥCן>x1yJunH&W?#8b csժU/])d#JMuY߄x>4ie}9s֯k_JQ>c> htf+hooyWaa.cOoÕu>D?<ɩdx!@_*xaqǽO!&MԴ0 "i4]C4p^Ünv_\VƘ1^{1>CpTXUTŚqIX59ce% 5塩G{0}PBWm}kW"o񤋗Z}d ?$a0.s>`3!L Yhw_]]>v@59۳UUoo|Eon|a~G$lӴyEBo{3{ sOܲu4%;l_}ճB.`ƈ`🦴.I|ֳHDgʔ~-A]?]clٵgxO8yǾ-s5? 1]`J)|F͛7೟ƢQbӦFNXaƍ,sOB2.뺮LR^jաi1[oCz$b\ƘҲ/}W#=U~:H/lSc|@`&T` qϟ! r:c:td&8, H֛8 *u|x1;JJJ?c6y|nFН^J+U*,r2L \XiÕcV׵zc(X܈Lc6eO ش::`." xy%>>p!W+^)8 qK.c8mCOjOGl$sNdϋh(?ޙgק9gO;{-;VLjVUUGpy++KUUU>l\ΘnpN[ 眂gn.̬@~C`L19?z߯m1>"*bV )SNqǵS$2`*+T-=ꨊq;:ViW9Ww`ԨQZN/_]eYcl0_.\x~j1urx~=9q "k[1pHdZ*zd2 9t]sH$c`{.\kf@?J)W,':II&ViY{3Wzg*Ӵ," (!;_i ˢG&?xQ͛89> lܹ>(*B7B?hۧRL ;!~TVWju:{);,O(kyJ{ z/w8 rR``1HR_ԊȴiL3ǘ< ?QӴ/',hъXwΘ 20ԩ:UEMV#ǂ0ySh4ħMtN2. 5%k=ܯIl`&cդ=v "LUuӦJQ33"slU@vV7~:35,f}jfs+и1Vf ˲s.87b8hЗJ@ĒBP#;%%^[ׯG٭Bh,.8hn{yH,[v*`J]=KvGYSb#dA?G,s͹YC-cg\9nhbspH栚)ϞzbB5JT19dWnwt쪑ܯJKɹ3~hB- ƋM&>Xʘ4w}Dc̪qsK?#Nۻ^)m{n̙c<ּy -[V+|VWW'.3T줣Q@6 #Zy#+(]R(mP{^S{_Y\qP:BSOp[&eY OoR w>#eʔX }x^ "iJ&s…0q"?a'Ӕ6k)#F7քBDc=>7& S>YTXYydy뭀i2ESvd$&Ҫ!h1YRRr|"Hr;v4466F:;;՜9sLRVTTTb1QRRrG}tI'MӴe٧8RZB)df;B!-[oX,hcc(,,sssyyywuu0yyyO\;::bg566GoVD"g{yyyZAACwΜ9k{X,v{OOj zPU~^#=HDbΪ:y5PuxLj 1ceow|ojW2MڵtgfN# q:C^i),)˃hlR ~Pw'awY#IBABY4n$ۓJ&cɇ$HaAg @astOA`L$tƳF ` ҕϨ17 5re+UL^ʢŸ6kZ>1"IB\m}afucY}t(Jti4D^@@RD S8oqxEǭ$1וu|u?>[ѽK/ h,/o:Z5~"8ěܥXO) bm^4%,''炞uD /ADbPH۶mB?l۶mP(>k@ccMmmmq@ VU%)%sד /* [ujhamBյr7=XJ~}C-tPoO7ַ7>Դ3 9ۃ!| JI=!c}ObL}JIϷr LCAJwnմXDؑL^y…_D_1mړ%- J;_qAe%Gg_ӎz< Bx9S[a>gƢϾy i9~8IqMx4h^0z ' |,1YmmeeeO`Pz=RQ4H*>FG1555Y%%%F^^ޕwy7xSd4a&a +//,˵1Ԏ;"wpxa(`OReVzꫯ+0v\On̬PU_~9_=EDIdH@zg͚t4|nw+3·P&qh\_xέxӑR(TB>VP8sOиq66AJSH xRBe;MUWW̖p8ٸq{ǍGKw~mrc @ǎHz*? ioF5!|.ޮPMHDTeѡ {Y!J L̟h|~''ubOy2%L4pѨm6NOc~s}$b)/# M# !A1k]-W~uDžîr_ȞĎ69 a`JXS,m&)( ǝty |Ң;6L&fܕڔ^(usL^duYX5_ gSZ5nJ@$ r4X`j%GdϑhULOoqT5rKޜgSBx3RB?i+k>u$m'/գGQYYYϝ;w[6o~Ϳ{joH$sx޽~M7>D"!mi fAAeOD"]{bDOPoAJ 0 pg-=ypjvQHve vǢlVàH JAΟ|^۝z`#XZj_]GH~:E"ǫ[2" KWTҪ)?'v.oK/YRk{Y̝6<ߡҢULV ߠ%2o_F$ɔo ^ݚYk#ZM*%.հ8!R֛niU$QF{"ڵS"87@<Ciʛni;y7KM I)o|'<5ͽ-x3x۬Tb'\oAy ;:(3=mp!ߠaǥSWO5Ss:d$  9E_9y3_mUΰ8h3ՃbVSA!jԚ>5ϯ:`r :6 }Ժ7ZDru*EKa+n!z;wQqJfLI2nJvtSm6pom/79- XԩS4K..]s=䜜RTE*ijB Rd񜜜yyy'G;b2n8Tq!י s{ _:ꛋ||˿-kk3ޠA1_ TVV:2NZƫkvUE QR x߳ը}RR/)nש_0TVjӢQG<:9LXV4w{:=Ev ,Td $/9[\4-ti%zEgMrݎզM&>[K4Mjkk{SN0NIeK>|'ֿnm۶ZT7\n[@׳h4*onzeYιky<[a={wW_WTT$WZuRU$Y?l͚5?,''kM7ݴ+pW]u_\ܯ]vbԔx<~ȃ>Xa,ˈ\spU!?݌E]tcl,;KGU혩+V̞1vlXgfH)+g tZ5;[GN-3Ycԧ(jkkMD#c؎s$If9d2FRrx<馛6vSP˹L*UHDrt֪g[_̻zcah@E7w\kp(4ƋY.&~?9[h2iع@ )SRI4()f~ 8Z<& ӢQ?㹒H8w}k8,J%'_}78wmڻS`Y?~ݜs1ڼys{[[UN'VJ2S*$s5iJ+!r2mYc$iN,KJJvHdy?Ouvv^\ G}z>5sl<uD^^h33J;Rʀ}tE#Dnczkk\16%Jwuu~MfG^Z# |GLZ@)YӴ~w+w̩zDR:\cZ}*5oup{(|u~3hzjjC5s묳=@eJvR`i qۚ ( 3W{+T%*Rc5"!nJA9D-vƭvWA68Y=%x-SM[aa?"Xz tNgT:vl%Vo'^RU٭W%,iK>hy2'h|2_W062І1tw,u]?\J7~_7x =rvwA܇Ag3>RA޼? a9"x~ۇ%s?׆30E i<C9_ꝋ$"5oY}ϓ,%D#Ip:--À49tn3a^C"c] e3ޜHlMO=#HdC) #o_M-B±GNyɈ#p\-[* m!LGirBi5J*Joߞ#DUW]uE0\uUkk%鼼mN=CJH˂;s2:߁Ycg^j׾/NCit2&|eY]^ﻼZ~Fڂɠ% /l ‹+RAK 0]gpX7u$;~|Q_ı}&ɘjWGL:t1N#H3L7c~w̲nj5=+fO9w"jsnŬRR|=9rBQկ=#vY# h,BT0SLK 0-=A0`9 lnT<󻃖=pٟ. KΗ\* Lʒy>f J(/]RA K '?RfZ,"SiYPR2%s%SILӲ@g_׋ +yӇ\½%h\xܲe+kB!m(ބa^>xraLCrijBx_~<Sjs{/[GF)↡T(2>C"Q~H$Ab:ʼnX*F:-;"( !D , [ ]/؞zʕJ:QJM LJmuJ- ]7=񙷋`Lt_p4K9y)HKη5*ձnŧe_><@QSSh˲Hӧ'(˲x^-]kfȐ!뮻~v|5-˺\*TDJu %7[J~-Sk\y{G3t?ϫ8٧\;L~c1ooMm@%Z_ ei˒Bȵ'ZUG::_r q˲dwwܰaguV]a'sNJRE!HpOg"]]]1*))q 2 袋Ym2@ zn.Btz^11^_3?2 !*,˂낈m7[" c@H$}6.H(+{'BVPP 8iy5mfʲt(Ƙwr)@ִjyھ}vFGtº.+vrr,륗NJ~v RJL)LdY ,"S:1Fy eZjs*k#ƈ|5ʱmŘ?}k D~_B =6f DjDѳHcJ1xg2|RLD0% ΥIVfSdeRlszLPkž-UU)Ԑ*&c}?~]%ҪiFgIEUշxMX J2fvĺh8;eV Mh~=U`D.(Uk\s#?rj݆~MAXUL: >AfZYV%>^%{*rda/e_@XmI'ۦ&躮ƍ)%ﻮVX<>axtĉOT09_2KGMXr6Kgj:`\~+Dž\42u|ҽw R&JA;stv=7] LiYR9eHD0̣eYcZK:ŒիW,8јTW`,5#F争&iK眷ӯjտLh~&T>3n{ii:K,1,)YfWWSQ\KHi*gRq!I$Qޗ^zs=w*v/\Dd(ZZZs=o~c1Uqy^^ޗng}vC8999osM)PJySR͛+B{ӿn޾}R8D"@"8&J!77bd?&S%g}iss3Rr4yVUW|Vp1[V 3*H.1Y|kl?aL\.^~;/t< ʐNSP_Z)1l}Y{K16j P&}8׫)CdѿQ@&-s *JxG-xf8K_-oxIڜOi$z_9{4q-)p&xÚů"o#I[ƻ?gJXi)oS_y+_6_()!M /Y;wWa Tԧ][ױ_\5")Ċ to{'1L²%'YZthJHk0\4Lo w|hmɜ7V^rƌ577W^וRd2Sv+g̘;sM]AXNɐ,d{2yɄ}#?~V LB{E~ڲ1g )[e&9w]U^k=禑:&BN"c|u qΌ:b/ $86"Hi.k{soB*3z}>^k=Fil3I2ahtiY !BR]ܭ5dr?-Yf_'rZVW)lixޟ ;_fk\r%0tzZ:iٲe\.$Zj0h4^2 س,c|,kwiBre]>²l*?TL.xW?#bz`Xl}\[۲eّ{*@ctOr$6UǷs>>szb =p\duooܸ[l{zzB6HNp]O===S![l/|,]T,^fUÛ_uɥ_ٳ36"&'3=Ϟkig9=G3U}o6٬ZĞ-Zc`5#`aY"TҒ ;y\-r51ʶ76xwyj]z]3eݳ%Vcտ^}SZN6/ s.,_\.׿cǎo5/__vXn]㨣z[x mllSq`#| n~fd]]vٳv-БJ~J^;66d2B}{e\[nw^x?2Ƅ\s͒iz1eʔ._\_pcJ~w]'T굣N&׿׽=! Cwq\}Zvlll`ֲ/s/`ttKN6uݟ@qX #8q i ^GFVuv^wey6 ;ccR³y衛 pla{+@AI2`Ea.0$Js1{1/{٫ݲL;yC8Ѥu377ۗqNv$\ }m|/>i$ KLyL4pEBFV"*cLz6>)۸h%y#}b Y{OeWwp"Q`<w7F7SV8-t^!z:K$Aڑ`FGjp˅>]hǮȹKTC\W0xjx6<ӻ7Ft<4Y LN~HX+?>asJA᷉JHrwl;\Ǝ-kÍ=SkXwbɒ%r֬Yx[AOOfϞ0 ޶m/N6۶aÆsttiӦ=mܸf!O~xf+n:X'xsámSdJ? ~ Gf8j+c=KZݪSg$mh ߷4>Ȯ{ƌW)1koֿ/Uӧ/-+k[-n۶vobiʕ'QBѨ.Yw/]3fnv@a/-[&^KT.[LN:պ?)S|+ɤD1zz;k^x;::ʌ3<3[('wvv0 ko;Zrz=L>Sֳ _KA~(~oLlp O+oEܙ_7϶ P2&t׆/W*uw_pY?_OZO=4#/W]f B  ּ諯P(c׾f>ϋ#8W_}^0XzC8j^zglEc0cc>s̼DWfM&4Q3[8޸Gȳk7j{ޞBZQPV.Nc`(|؇{b1bӦMtA'~߼o}m۶W3sn5cxJT񭹹eG|[.1Kjs<`\[w]|؈KսwvLP%x\veW * 7%N7͞= }o˖-3S⊝1LW}}}b(uROO,⦛nK^@P(<500pۭ3fXJWo e2 g<;J6iwJo}a0 l/C-H4 B>2BOxEv?C^½Aia!W\>|vE|3}:2bf?bRyµOvrЁю6с+4˅fc:gOljwj&5ߩlvGm˖S*|'a6xL]x7>0 + Mx77.{y/OgO^y"_@ut,R1.F׵L]z܏>`m󖫂=s+^Fm|QUZul3`‹tؕACj\%}ѧʥjۢIs9p]mmmWs1 .t1sg,˪ZU9s3Xpsu׭ȶGE2=24d|61"*cn`zGni^ssoo}lYa[ngͽ::n㺏O${ Q:2]g÷vt=`k0{fs~;6?[`=}}}Ι3뮻YŻ-[&WXa]?;ws}ي+_>`~Ύɿ\ W\q]|c}}}ƍ-[|?5_1cƩ}}}_2eʕ?dƌgwvv~nÆ ƍþ>')W\voۛ6mP25kֻW\yɪU•+W7t_Kfzw*ܴiv__+$'0TAlJ3VyɧV0Z}uKyۀw= qH|6+Vu#nkayTnTo/$ A+3VoG jFk1U>Kw;bYG pGϔ%F@:]-ߢ>vm.e$&4rYa,S4IYwE T(\ri^X9ҥ;a/[άKeL(l` V.K|73jVkR/M|m/#V_(`[* ȳwbkkky~o`Ozo6OӣXzudp_; x pM+4U\ B~I=KΉ 4l824V֭~Ҹc[36m+l1vVݝ%0$01Gm4+5cYG7|Q"Ytw_thfy'XCzٶ}}'kgV}_<-'f3!2E\61oͶ#J5څHZ~uoO T_&|iI!D_}tБFQ(juW՟.]Ԑ_~wUW]uܹs!TX~w/_~ /k)^1՘w @S\׼j4\s5>R۷ogttt[2ͮޕJVx7u֭.L:joo5\]ǎX,cǎם{&{lpy'=cb" CNjvo)1 -v$|0|[S.}Ѣx-}!RŀjZB) YgQgэ6q;uuY瞋x1q(oʪ[o5H)R{ܓ6FZc&1zOyKƪKV).A4>enwF).E+ڎp7cX8*yv?c []\$.}n^ciX+WnlҚ}!3gXGe H|s DL $KQJ},6qx@[.zVûK"]3O\R%@$fDZ>~I7@gwl/͜^N~K"pd=WJBC+@yڲSQZ^J)hژ. * BbAؾTzaͼT˲PE͈֓bDY'kE|k7UVK,o{1CCCkym\?Zk<}}}O^{wćC{O 8Icttt~$ K qUU`yoUeǵ a֋IczĘ0յtڏcH(I5w;UR %磍Aڶr)굺%bG= G7-C˕ tXn;c,Vxr$ѿ#^%KwS9x ;%'Ӗ=oK,;ho F0,1+{M:;LH)&as]V|]D+ˤBqSޮkk`(~fÂȢL~LzYv)_r!ɘT:K/cN~Zt`?m4~ֶ gR64Fk- Ps@Ry+X֛Q ;zӔ1F\~W_Mz\g>jD _tZld2ٺu돻044|>e ~Zh<Ѷ<~~'kcٲe/_f[JJeFWkXl6P>v\|y}h]۶L&3?EN=/ݍ'4q,Y23J6&{+µ_Ca\ryʕ+7}-tV['[pThp5 0ܾtςl-w$o˖!/G߱+gOXt/=,ھkA9`.>/|{Dž=Wy/s_{?ܽA8y ݍpz*os|gqCxn?ihb.qpROAX˖-Kz'nG>RE(3+<}{ݻ~Rfo^ǎ;vZSLy_~M!xpf-?V)h+VP*l phF)6Ƥ[gm;wI|"y)!&6Ygh~ifD|㮙9_ƼvB[eYlng;gl4v)"eTFʋ+? V?;9Lg4k`hJ13.7Jcljq)Mi;'ث7L=3N6ɼl(u訪_|]_=-ꉅ ]'ܞ˧980KJ;Vc[Ϳ;xԀ8[r ]wSLa'vl ƇOm]Nǔi&3i!!RҎ6`cN`tְN_%iZZI+AxROp JҚPDBmPJ)+!,tOc ,i_DG ŸtDkWkO_O]Ǡ} hHΟuΟBh~\x=Vi۾`J*J|-w~Iɵ]WpÇIGg;.&m+%1+_jqm;HK$dlK7ϓ˖c hLl162VwZ8:\B4#M(`I/ӼFL_#d&TqAa0B3M -v/c1{,bc"ho!M$|!Q3"}".7Xl[i4!K.)ty `BMy."IقPF+HHXj_¸ĸXW1hB3!&5 _iF*:Ƽ|BjC4*OPѨMI#U,K~~T?/~N6h?" ~qe"zG%@|!4^Tډ]1ntظYW&>z?Thb#tQx56ŋoSROgm0җ钯ןѹK<26v|1ݝ6jaMU*d,y9/vV:uuƕ_]0"-eN*M*Dik4mulRni@ji=#@`UAH2K:Ym$jɰ";]n =H>@!dS\;(̾dRǟԂڵ$mDg$BEɦ$$&z/b26_|Y՚߼XR _amOMDd4( P.2ӆ7>LEQ$3y0~ʬ-`+u6`N2MLK؇~&T5,4@] B'E:%P=B F@^ h7ʶ JC\F ,⃐vt&R:/*xZ[ RL"< 5\ Ad@ÏCulD}i Iar/b~=EZA*i4ع?h=8Bȉd~4x"L4Z~#Tb:6m!S^ij]kZ@2K"" RDsE-l&QBmm*D'Ov-1߿f}~HPzL1?կ~wnȲn>7Զ#uß+Wn:ל=xgFy<}͕4\cJFVM4Bu!-ƣ+!1H5d[`fHXǗJS_?xc0̦i/|ۿVXa\+Wرc5{;PA]5}xZLci&2/qhFsBr܍W,͵3^,3'pA``TÒBWTI&(QƢ^ᕋ,$R(Q6)CP㘜i5C _v[(ޱx] TZZ^_.~Ы^3G3ǒSʗuj+p]־5Cn{g)Ai-C@bǶjUR6GeCx!)ˠUGP O U"'X(0Z&C )fų C+8xFEn#sqFx!mpc LJפ .[`\G$QOU c-x0N4wo⠜Q=)ʞ&JT*L|#pmuO G,찰-_1wMod)%,qWH&'-M|۶9Rʃ*eQ[ L$ضL&s8FT*E[['VX'|Ҭ\R_ٺuccc0 r¦%ޫPDviO|JҞJ1Pj ICTuBv7Dr /4’z[~1@ 2 /|/jUXpPdD6^8vZ;O=5H2oZӧ}O6#74F?ij]j2ZUG%XQ,RA*3G?BR9=cC56y=Yhn ĩ8搮VO]cbߩ6(iPJZ<IMڡֈDɁK!4|AWA SۆybħM(R_DeWVrG4*,YC:a2Ej4~ ̝<^;นW!:WW9bN;F2c48|j'lg1|u#~2ݎHFջLWQ71J7++f?mm[2 ?˻jooI6-A`\5BaU[[U|0 BhcT*hO/j?'Z1AN, 4s:|>ΜӦ CM|w 'dW=>'mZb  m |I2P L'HZ%41s8gL|ÏA!b˔&n?^8-󵓺xmyl?7 bcȚ27nlpmqTA\ut^h"enbtaY8L_/_~7?K) BR6ZmJhZa(ɹtQT\.]9TEhHM9s3۹sNG.m`kj&7O@ V9>#l$icF7Fr\ˬ ׭nQPCҶ!)5tUtMЖMw$^%@X`o7uHeyRF8 T. [~ehm6Ai~G v\Q"9RgH4<}hG" 26D<)2mAH-PC\B@EMO )T"O(#gP0x?V$m#U&J*f0X6dA~ AHVۨ5v|gvaK5@h\){sFȧuzk/=T" Cy!"߬#!Zd@C1n[:VQ9%oT llj-4i)\AOڡ Rad0t ?;{6Mrգ;E): vƷjU O% T}>} wU(ɧ]~}tu$"oj<úҌ5BOS2V$ClVgy^vٲe6@\A@H)eXĶ7c>/}iZR ˲daH\\ou3},2[} iQd{ayzs)4B%Pl,H+}"L`elrY2;Juʾ ]i9$żV kW i+XvdTx":(JcŻo3 /`!h3q*kjuzg n_Ҹ e;hy+KxYI2`Xe{dB,f~'NÐ0hl8qj\:ɖ*yAa2΢yPqqr )R4Cұ B+`2Qo Qt"! /`zBb׼j^/S:vD;m?gZu^G1=Kɱ7 \DQmyʜvqϖBm8izqY}_JE~GD@5MQK/גŠ7+qi4zbWײ1ґ<qf\ JEŋUtc``=Mke|wff Xy̶jMmݝ'JcHvŋmjUx0`[bC5'h3d3<4jnw/E tlxle9pƐ|@6MpĪ&a[<98uSm2I7-t凛u585D2:2 Lګ&Jӣ+B+BPC#U0˧rqzAvb2|/;QiI;|&IjvgSp,__?\%uqʯdp'y|4 7O-o^3y-n/_ު'vE|վWرC7|LR9^'QBںui kF`7fvyfA)2X.L9ܹ#d)mPr6qJ%˛D^n + fjG.(ֆrόRԼAl&OoZ4z,܌ij_-[:m&P.W JpQ2s#b;tϘci2o&ѯ#Tux5< rn`.mw , -,VRjq,t]Z3Eu C2) Ɛv-NGGQ)xp#|W5 +iQ8rZ!-a$45?"훶ڒ9pCEV<3Je/ڪmDq]Jl/ du\=Hm'Қ@GvbGke7K?cm[gĖ[ Hzu?ا/}U;>Npw<-2i!jզ[N~ŒYԅkn20l¦1$Ͱ$iG! 巣_Fڮ%mr4fmdml:A)E j$SiRlxR\&5nC[h#SIB bU1-ƱM H(F=ǻ#V"Ov8d]դn5!2~2WTn W`)p|έ\xt~4REQ!Yg̗'eȚ,zO7ΏA(]ExM"; }0 -qM$JR>|RBCQZ}P|#%!T&c57>)gϟ4AGϳ佯 ay㦷HeNEʱAVq2śL]UxnƇ2mܺ~rl3CPF6 JtkFfXt]@T Dp-f6{ zze 86oL{P*K/]ȲeuoVɁg&5˖f}馏De/rV["VxM"F[{jz9FR:bAX͠V2# "6qr kv03n~Z 5/0g;E\#ZtEjƪ 1FVǢwoTd]Rqh߿s;kTjUDR9Ώ9ctddc ?&#BǍE359]pVW/T+z9Xp1iX:]+Eq5`!h4<ZAyO^3 qN߸q .N166F86}0MfDfP  Ҋpx#tL(r2v*QTIe#33%,^tvdFl F *%'16QAHzz1Z &?AQg~r\<]; ѡ!)3&2y:C1/֌25-Iْbp040Nl6Xs4G]A#Td]k"0T*D1vqW\i/Z xӭ'p«k˗:* 1P{ի׭X˗+m:o3ڽxݜWcE:ڢJT?|+!m-7=+#֭NPM|F!1.]]<¿>0F#UDR8X`a_لֲVnRpC~rXσ#Z %-sfrt_/~ָhfhcTsu-|zfD2XyQ]|o E1Ă˟ӑDr?\ gNm}[>k|Ndahlwy Wz:w|eT  Bk&h<Ϩf<Fj֬Yܶm۷<ϓel~x׿<ϸk|7 ҦCM"tʓ73+ഹ=znW8yFWGkYPMY؟ W4b6a^9 !%͵ncj>Jg6d; S(-=FQHD`\@3X 8;oMܐyJWz@o p3.W1L[4B@dlƂi6X52N[=]7_94b7h/]T59Llуf0_Vcq s`Hc= @hLD?GKZ tehs$נ=@ s!)ڙ &2\ m$+k&Z%QTүc*~{/5|F[&ɦ"j'/i~ +D!jp#iTE KIl2Ef5V`y1Ax}U!Vi.Lt!G !a1Wkݫd6 \pTդ<`iZ2i>s 8aF6"T4glbhf)HX2w7Z'=~g 1R HEkHĻfs vUXnG m40$J'lZBӅl6ÍC~~$[`s$,~ӮLtx,Cy y^Vt:-|w& DzT _k}ض}駟8۫ժH$h@ЊBl=@u1\04E&*'OH"a4-h?65!( Yy $B^7̐cp9sKRMgJijͶRɥj 6,ui$<+VPǾ[~xc:dhcB PG՚G{.= n6/oVȀyr?yxZ kh^³SXtd4 -k!hIybh_ig4 iP~9%0 SmΘ hnzn@,Ku|$ydG{xռnk҃Q2nˇ?_(u-%o*R2XtmP힇6 ßB[潫MރW,Ybm_> N)[@9$ٓee ݅+)#i`WF\uhMptlz`B3flNY䒑Ķ$qNnxj[rlsD Y󿩡6 ۶ ezl(xPrgmQ{h7&J' 4( B#8xߡmf[%H'kt?GSj,sy`v?k nQ!L!ER`LG7A[JքAH\Pc$9Qa ;aIc,mcjd2d2iY˲yPs]J)^q0|6TjV+J9^QΧ0`j.BARhfeTĵ^b PMzu5 ?6C dX =T>7S]Y64aڠCOf)!"SܷiLz810;Brs *4oj&$-/Ÿd\؂Q %yÂ(DM,Km5Jt[d"'ddžgfww=#tl5F(ha|e n _D%rd;*o7w]G s 3jo=r*F*R03 TEED6S3ܾn9eNG?́Xv o-J:d)U qsmxawWu-3cHm w搶3GpsD?QaIE3ɻ6dWP"uiAO|muTĵ2)+tySxY4Sa\'+Ww8m[nݞJ>;/;<Ѹ_;^C' .<V#ı3HʾqӉ b¨ɴuS|Y)cfIm4vs(٥:ʄhTkttAE!eЈJ$A`=cZS=nX痗>̺Ofyb*e>yb{|샙ӝǴJn诗\| hEl.s݆~mh*$ܞ@ƑuUE=Ga-"VD 8T62"k8mYc>x1}z׻R)/_W|;,O~2)g|hV@@}tJНvxbLY 2*jIHkVOG‰(ǝCm翷Zl )-6Inx|+5:N'pvjNA:wn!\0!65`_|r*|; {J7~p3yRQζ-%3ێm$HkSz?'V̶Ü\n0'ܮ,y:7TPvPP2_E~&Z6"+(0DZ- _9YKu<v~qTG|sʬH!4{ѼUiG2&d '_42[`sÜT8'Ϝ yz.)i qVbxe|?>~% iO|_9 FێeXzd|2JCk:9aa,YDrT%T:.WZW@3r;~|]ޯav~ /~ӟ~6뵻>:ʨ_1 A!NgGtC tՃIw e?'zW|[ɚrm FB.m%|#舴w%q=B{;<0I`|CL>ߌ$?P|ճ":]-eɥ J` h7>Qm>Qk݊ td (d\?І-:P8"1pE h}`'?6-fcYwo 5 +M]e+0nm*^ ƺ'H˨x`!4+0h id԰$$l >XO;q0\'6/F|:}<8O1P[u;)}sT7N1ذT q W[`#`Cя'Et[O!hx ;9f0F(oNUim(cg~j3 Y:R"ZJ\BWmg'+$3@8W瘩y>C%l"P5h)!r[N\pm-)߭czt.ODק\mռ52_j#HƘ-F+ 6l0-屒M:Y/ l!l#Ceҿ}? (씋 CG՞伟?FBDQ!M*䫏V e7LS/|[Nz/>Z*m, }LjA2~.PC5rZ[8h {o^+1T-lB8OS=z(Wj^ftƅkZuߴj71; be  _ /Ljǯ^/M h|-$-UZG/n|WW*MOTm0~SxqkcJ%y~~Š۳4Yj5|+s6]|̂-ke0 -15vfolVqOAZS_#$,3Lñ?>JeЕ4'MI\= _w\ꁇ1IɈm=Rڤ$'VD ̊Kn4}يlƒx}ds[/o&ߊ=^?6f8G5ovkg|Ǖu霵cw9}l'^GSLG.AE^İ"J0ZXݗhJEċ?-#f-F`ѷߧ_:ݹ]SRi/ݴ ѷQrԮvq $,ɎzcPv ^p?WH)b<Ϡ]K6.c4xL O}aØI莭aq))tewLK ݱ5>_@ZUl/?:0Ng[]m=ӂЏS ^ v-n) ;]szyn|)5vBӖ _/]'gժpwBx??]/{hI)@Vr!%vTP~[}bR-a@ZAoXRPqd9as@KԞ~Ě ( |aP"ga:@HESs† \VF~EQ MQ闀~) A`k(L _1Q0{Ir'֌[nWc QU@gc6 !)npok_C/Z~鷵1"J۽sGJrLꢋ{~Ty)Nރ*nEnv@D>7S= !{ :?z(˚C>0ϯ#3{iؤݺO=ۮ4_y:aJl&_A> ˼gA?]_7׿Q`Zz&rbb}3&4pw4=o{3^/;.o1 ۖQM|RpL_Vm׫n(:/ln@e9}ٌ1L>N4 Qq[A۶w6vws0~ c~q |ſ{h}M| 'Gnϙ6"@% T'I[=1!M7 g`:MNJSwGԪ]֘i{ؕQ C-D -d{|b-9f"36B@(Z`1j)""wA`@qZ4Z~e}8F owFDUda%`ߕ?!`(%"OH{DF8 ~  ">Y} .Pn;K: ^#D5I 0CIƘc$R$f}kn鲣-B ߷E!Ր}!],Xey15Vߗ|db -}񢮆e)K?NKڢDeIICFkIRNqUyI߲,ʣc0U\4' Ï 0̼"6~N7X"45؉( 1) 4jbs=Sk@+ujȤfZ0LW 2?hIj4ժD7Ai5*:B@*F&QiV4 N2j=P*$pƴ!tx`Om#e@Apmi(*P ,jw> /c07߈N3;$lFb%tvF jw)@3nRSDZhl2^u|dX^se"PE"ZwDغp鏲J?X42Sk@ +4*O"ՅjNn iv+n[[4Lzz;\]޲82Xb>|Vր29_h!v Q)L Dr&VoMnQH|o fEUgN:iG҆=>W滑AHJJoIDUՅ J̡Wb Ao__!Lxbʫk)}lOEІk_KXy 6}N *eC{ZXy)7i$'F!uno<ҼvN<@c77ח (ڙy7Hvv6tļﻇʡढg*q>~GFkmQ8ldoǶm,ۦR^>#ˢk6-L%^kgv2;˜?N):fvsMkG]?~aޱH `|m WEߌԨسi?Z׼TddNu73x?ӛiT/}$ $]~a齊RƱ'Q˶l6̩Xݨ3AvBUDT\1G26p2,cO[fP;b7#=,/B0z03Uh%4B9`ǠFEkn!6*28ُ5™u4Rm3-?F:p6puHЦu/u@#egb¢3>}jpD&%;;@fs93?TukL|$$&EHI~46#'*'~+–NjW!O>t|z;06F퇗$ZO2?FGrqJa@'ȤԊc2}͸LK/2ݍ$y*|d BOJYF6(r,u@d(Yh! ;ʧ+#BL$8Cd/Fk,Kb[rM Yx.m/.>w=b~L!e!AlEba-A&,|:M_yƙH p\)w@p[̡>v&6U:4;-rџN[Chh%mFGI^{h/~jq\GWQ6aDEcc_.cu^%l~H&2DDxҷd< 73+я`օaj5\Npe?=e>ʴ``.~?ƶ9_q?hށ2蠹7閻DvOE~#5CR,=/B @-$&!# S~F~1D)d'JC_m2:p)gbKIgALe'4IsJTjV}$ţϸ57D14CcIlC ju;1o"w̛Ө 9Xﺦe|L Ш{̎&(\6YGax!%۞[G_u]#J6n&7  (%9'#>S'3{9(JWV|6hpq_?*c28ۆ@izsz ܱavxlқKpMכ3S oyYSrÕr\b  eMis>2ǎTD_=c(ȴè6mܣ(|>[%h P.6x8nmB.ŠM E؁XW]˒2n(`lQ35,kGj?vj% m =õn~(NbQAhȄ%n~m7><7x ;xM| bk#Ɠ5)5\q}U*4"T:V! gy\-d+.Ԑ|n7oU ZxL2Gu˜Y+|F7gs]Ϯ@ Z,PN飶};N&~դ>C/g/'y3vL9<68]֬ݴd[?1퀴 =/VTd _ʂs!(";a=bjWOBҦe"{Uv?=BI*%tAAIĂx!+(($(:R }fZ{s{{_yNrk=k3yZ@±xNq;+Ioi(#k>m&uI?S2зiz[!cED7hey86"X GDc祈"5[vxbH.T%m-hEblܖ:_s vbq&=0IeSv CD6a<7l^ּGÞ t#y-Ćp9|lJ1Pܸ{&M4OLӉ'D2 w0ZS_uBJOAkV2f6_/l;$R"1oƶ,k"}LF?z/C|ߖ㐜{[_ץMoS@}]wҖNz]j3z4)S{QV6dkU_z V"g Ϟ',U`?'8j活,< iso»Ksxf;gOoa73*)Y|xPіI"hH^ +I86M50 mcA>~N~u8p(ofM)ۚC?4g\RM v2< ɦv<#|wat5Z `=Ljk5,@lƲ--l\9@*l{Pap]D!$'J=ݖPcH(c0^ʊ;7-TdgY3 Qm mOvL:"iS|{n{nbJk tr@kvyǭӒP|TMk&IWH"i;EBR j=;n乂*b ytK5PQ9˂By CU!"Aѣljh$#W-4ˀ7O`{Gz ӸB3嶗9~jG;r!K͹X[#lh%C& @ itDxc&12k![K Q\ J),))Yè3Ϥqモ?n';s.dR)֔WBf2XVϡ |7A&<4r!VF*u X!iGֆ(iŁ2$\ ]3T#j*n׳T&9(ғ?s ͓u%NX&t漇Ow=En=m'9 DLjhÂwjhM!UDŽ&~|]C#@yIZ6M-Mo~ag;*Qq󮥰q›O2ׂQfN&P=hC7Lsa5pgz9k$jd CFz) @JB1H2.GFGi2OC̞SX aXm&]M2b >0cgیkVG}Lԧ 2 A~&3ƦRTB:KY^^rn'0lκ>Z Nc-oo * !Fa_/!:<]^ )%59l1!Hj7i yzLU;Ϟ̒;MܱGf|qR$[j!,q, Tbiԛ4F K'i7ܺJĬ1<&fWa)c4,Zr`ќs@v+ e>rQxqYwC8{2 /ӆ25!fP.$.RBD@[Y [)fOPGÅ>5K񧗊\V?T-cF ROI$Rh.`*dR <6 00X 9zjo7kyh{Y-6I摯),3JZ7hҚ#ytGo?P6rFP’tB#e&)"t-PQC B1h0P2!ƍRWU&h뢾ָBYSIhUٍfzk_9 ǶN-xLn²CiGc|< %8pgL-eq~6V$^d@gTͤ)u'oy | q6eaХrTV~{O:Y~BCյ$6nK]Ce F%Dko\#1&;ْ1*A 8<!/#&ʓ!a3L3JμLeNj^hmNUɳi0aF )CTu%R  ,`u.F_ Dje'E6d5/ӠNeIe8hc& hT`Ɣdk0Ph+"ի?{63ɜr*݆NPXX# h }ut3D{;S,d`Y#;bATㅡ>Yԝ>u,Biw"c2D 0P_ YH!h$J8dt_u<2g2 @%`eOiY:8PeUOg%_k0jh|&qߋ\ ظ!بx1ԛR%"_ZvWjxM:ibHIM $]b *46̠1B#pM/piq” 5? jKxDjy% O”$ݳN9cQ0HۧΩ;W*.׽%cSOȟ162t˼m T4f$3`a;bj!BuW Pn85R D/8|,YM$I+BLvct臚dX#Yiͽ\XT*0$=ğ!0`>K}c{GӏfEG 1F:>u@.MlBZ>AƟu >Jr&l/*Qh ZDkg>WwE;k C=؉t|aDE3Ngմ|+Rx  H>S/Ə2{IGCb%0>ڌO5&QR#6xl"6⋏t]gOreᦕ=\l[>uwxamok#ќ!E҂Vs߶l%&/:l|G80&ڛ6C_5:r)&)T5^2JXP& Q5@5]BW|&vŀ g75H p4S\xo')OA 5rNsL Ȼ[ƞ@|쨈r)e8.譄 _Gn)~?8ki.Wތ1 /X5_㶵"MX9?aS.1/,^?>v/PH$1)0 _x۷.Y̟GWniM&⹥z}@E&a C H63NS VÆ_Kt 5U7,'5h2ҺzWCS .:1l t7(xm 3M: HEc>ph`/DCYl?F+& VtD!au?5K^Dqu&pK`I?qȉw4(B@"H%TـG! iQ)N9T{;AJrfE&mi&VIMTnyk4 /Y!JE4͞Me )Sѵ-[HO{QT%o:.yƁk5G_kviMce!l ]s/i9$R{,qxޱҦM4͞Ͷ&] $~sB5L:'U`Ҋh2fCRJ5rM.7-sD s- \\}&%W>?T {Bp;k q{l }_n%U5r(  MM$W 3\~d;K7 L$,zl+/Ui.(V}.zA+ !CluzpnhB{NhŐ6fQ=1rG!K3<6]n+oq=m#1I6QFmmlglB2?S )m}iw H,)QZQI1ֈW#L‘6FXWke2$g|gOืHO O޳d2GDVBc}yxl6P;HBa츃gONpgw@ϞRO)]cb?5m(+k>֗H[+R455{{hv f(e!lM9Fh/a `8W )D $޵z'gBQ2wM[Yi|Ml/8oBq ֭Tw$3q"ԩl xRc֎m,ϣgV7vdš ?w? [-$ӯoD#h]GC˘J% Ai`pLR&D0NT0hD6m&|"f]xT)O$iBBJƟw;a <dFAhM6eiCl`4 )KD:(-`I Q~Q$Ȼ-4(ndZ! ]`%Em0Q!9 3! ڈSw^ h:FBu3ݾ 1(p\AT<$Q :Z$pؖXτU7ۂ3DܽwA-Tb B_1wRǷ ' kja'nD[oWG㿕f!ZQqs MꐣkIl :uS0JvGa%z!ZENZE60+vpYGRYnZ[Ww͠~,_U6ӧ=2 ¶ <(I@ۼXd;OZ78H`Yxqd_Tc}!Iyyw߼~ǁw-gK}$mI҂J V&ϻq;gL7m&LDN6p&φe11~-RFG2E<\5Co ;Tu&|ylwH6*BȲM.7V|yL⍉<+N|@!&jf9N~b+N`\ X.(Ĝs(dҊ jX^wtB.X "Fˀ0hDQ(QF=%5R+vvu%p]F^k*Bcba Í938^'?Szvv$o)'o$S패a]߬UtH -~V8Fa @4 T#`!44 e'`7SOI6beQcm3<'L)Rh5_X"Y,ƱJҖ/}cǒ  wW5`[@7n k@&@ LN0%;l{`Jt#$^=īE"=H4xI'( t$Y\"TEA^|MZ[ }?waYq;ΓObRԊ Tܰf%4;8R1RQ6|>~N:C1!ϗ\St,4Xѡ".I'\*]]~Tƒ C"Ja[УB)L{%,Laj(lEƴIQxi1>`Z?8Nja5*P FP5,֢c'dv5 L9V"=" XɊ^S'+o$[hcf 7zeM)ZT:Mb}O<<%P{ֽÐLN{#nhlBآhe"ﵑj ;c۸Ԣ0$BPvc݀A Q-kN,7 * X1:*襢0 rԻ)K\2c ޴y03y]w#m&%{ԱdMA랤1JdulT>RAs3<,rS*H2˞hq挡 ,\GcKA#l!vCLFJb?YuEYYвlڗX1GMv4\pT!3qO-2mku[mFB1!#H iJQG񳟑޾JG!~}`YtM 7N[LFKm&8 !00{￐ )bP/!-g?l)8Ke~JWܔ#+/E]ֻe F a}mł/D(V1z} 7FJAͩ]%-:>ཪHG#,YÎE#Vݾ3}g=66{3=KTNQ6h0J|8#) !]0'G}dL?PAD_=_#-gѱh&,\ ݞf. c2`0Ƃ(V)'0~TL  $\Csh@Q(ck#VZZ6ٞ>Et]bunGTcM۷6n AheZE~+ 3s&8=7]"Ԍ2:kXMzQ:cPkA,a F lX6/ǻ wJlADj@]|_GF`Kt0mĐy{g/2ݶ1W4K,b3Hڊv"$GY^Vgk;?~b 0w1Z=V\s /+ .(yҮ}=H}c"E+=]r8_}ޫ;T(?v$J; {v+ҎBbCJB_+DN(lH =>2~F8',P?0Hx?!@A䕫VwVk:\w|(G*VcFb5> >Rn(A ջW}7h߭7~%F}?{`5]ĿlSAZ"MÝk eߒ(Tzi][=%['W=R~sthaΓvMS?[ldS J>R{B$8* DeKFw/Q2 U W?>Z{7ymtPDZEFѭn?6IuQtm~ͬ; zGU`Aƾ޲0Ð0`jk.g͚$ČRF90`2%Y3ժ+œT A5) nF_ASʴΨ FkMˊro͵\y*H?V;7qeD3f oy>׷{J_iˊuǨ=ԚdF(R諰f"$&FI_c2YD_X3jD?Z&~eb͜W_sͲIֶBXrO}b1^6-}k76kRKSrF&D`eo_ ty%K f%قf0Йv'5{bFh,bV]s߿`Jb|FkL&ETZpN9eR-f hey}o0Ys=yϳHk͞&= _^v;GLjz3Qz @L}ښ9_x*^GLjuE_ɍN_q-}Dod-3| _Gv?ufj3_~u _o|c\j6@ 15_~yc*_6qܵMMw,ƎAmXaI3}1Hǣֻc[QmβQx{ៈJzm]qxNJ #_<󗨹sza6&9Dz`ZJw^^7^t37/]JXw8g}ntӲ1ɦ5m< VY/_"D]YUn? ;K?yn*q9-G;-?a;?\^nG?yR= Ǿԉ9kw|B?B`F{pIgmK^s01,jvi"FӞ[Rmۖjpܯ?E"ݾ,k½ap)̾Ʋ]mRqFŖX2_eܬ|ovXpꬆBrEoyҥa޽ wN=ܜm׳9=+![SJt֔Zn^ ង߽~Z>>b2>{%ތ1v!>c,X WZ/џ5kYp᫉la[3ekW!RRlK@Ru@LWJ:2uEC)ZGiDNv**Ú1iW3 <ıU:RJC8a0tcY?獗o?-]%cMmik)+  V2ue=:Ǟ`!͘dJyfd2BmYCZcU^mBL&3~pppڌx-c'GRGnhdwhey* '\6:wtPaĄ#-KlyVgϿ]ccRG =mȦج9PrKaem7 -**ylz{5 cƤpLx `%BPVTR#E4zQwIeW*#??5]56z(C#|DIϕH9>v֍Yq%?qjl*yhq&P $8R3⬲Rg-]ݯ~%KUu~e `Su`"nUJӡ n/Nz=}Jm6[)V3B#B%/ywkC:<~rz06q]f"1nB8$B@R A2eS)J%c Rq6B1R(|$\/^J_I5I헅QACJm شuhJΡKݿ`}¥!"uhB#,!Ã<>9l]٘8Z,lvi< Euh֚jj\fؠc ~% Cl~E!\^Fk)eRDсQ'}@)cŞq>Z(>ev8W1@MkcjO\.m=+?PJ8teQ ~h2ݻO\2/Zp{ ZrZhFzݵHEATK%vKMJ5_ VH5 MʶDhTz;-4tĘzL{WD 2Xa |c#1Z2}RJ2h3䶕Rl6[f:ia]`%œ: 5JKiIрWj&):дݻC߹Df.O\p~ܹKpœ2G'j#IURH4L 405=4U}/9~ɒEϝkt^W 9֔U|%iNƣ^B>%~1r93 kU" j(my.K{IRmJň=•7cI&\.~گ}k8OҸ+ WOӚmQi (C jsAεYrX^ls]R m! n=BXjylsoq)+^Jq NLwɡDQSAGZk>=c\ǎ+t>KwbtA(ra :D<5+9?k\FJ0 b5La:}7^S6=@"$w ç_r5Ɏ a"Nm2]si"F`KDѣxظYdyïYXN(N?Z3Z'8PqP*Vʣ/A1ёT5bfDŽ8y,  :ێ+7H&@ZإmXh 5qޞRK K@k'3DgBR>C`ijmEK†忎*l _(SGq  %XVdT# Ӵ"$$< Fy=! AՄ71׺V?ֻεיի{,Yly;,sS0؍3fDӴvDs4CtMOEX4,>3:Q%a_27è#S؎KƲc@iFyBV +Hd(nb 灴BW81gK"E_\s]r:/į)PAH BM#_KY^7GH J>F 6|;DssJPr,s58^M+t8d۝g_ZKEzjk.8lʱ헒4Hi9cPP0R:p[0KF*&b;=N-gePIJ,THw5 <0ZϠ{/{ُ:vZU/ۄFD>gΜdN cm۶ NR)߱c^{ۡnX@8drd6MCE{gʱAILWeqj (Ko4PJ1?]K,|q#;Dz k5Rv,׉l1p!+Νܑ9(=QIS 5kmĄފ墅PMjuzSiԳKAokg/'^j0SgKU ϽQ5NM{fmBI8nÏmi^7S0Ķ0G\x N`}lO駋HGJG}Jk4>v: †pB>tn薃BԳoVuϾNFsbg͹U[b9ҲӮjm@/\p_%WB1.yĨh"{ȻP~I]!1a#IM=$W' !bdAGi2 3HbڏᇠkjR7u9گ.x 8wr"qP)T`]&Mf@h@79t=4'VɯIA0c !mGO6mپ|grqY8?o0bܨShΎDZ,j'fGGEw$MddG\:lHhB e*۟w`#;>Om?Ě6~J߻}/r@Ht5OuwL1^(mc28X=?bds?>>&TFr|;TC|ÿ LCVg.0u]V^M7\C=?׾5nF֭[W\'6mW\7̺u3fLzn@*vReauuaOʄ^BE2g3G?f.߼6²yAo`2oB.;᦭mOU5jO\rث4̀H(yv7-v1qVc#)E#zlDg lCy)M)tIM=jh?@FKʡ4sZw/JRodA0q]Bb#4K/h6 -V !/>0fqhnrClVeGW iQJ7J4`HVm2XTjL9 HA&&͋:N\NDzO y~BJSVTAK LEZ\S3ݎCV.SOceg`ҟn}b:d"Vڤ-ˤe~P!!,ܟ1N&*JO5hd\DX&{y䎽ζo CB)iMvJLf:uqFhLx!;:F75SYcWjw&LLaMMMlݺ5 ¾C={챯~z/!{hu+H}{2G=˲eYzO|kcTJy{!צt__VadrCQXtiCf'bl{t"A'AAdu۾Ϊu_`\|rCh% jL6j~wU'#ƱӔKwN{a?25%ܤմ:j};p~/- w nm2c FXV!hfLhwMО̰t!!c4j;{a-Iz[A@"`ʕ0}tƌQJٳiiiٳg3j(rtQ:]gX ؂jDyΑ_uYy`s,6uY/1{"'f/ZD~J kp^9~0PⰎwҚ[T5o RE,B`EmZ\1kX8 g,J}a%1aȢGJOnҌ*Eioei_pf;Ib8ƜpYca?}O܏ |ڏ9w z.}Mh*@CRcݹ)N>v4{PJ"G`1ϋ/lVXҊ)ŧ]ښH9eȵ{ ?|7/çCIѪ2e .(e)iY|ڥ[rN`EraL&/6|؇X ,%q!4rT>IPA` @ªL9sI_ M?e\TRD'!ȁ'ߏ>h>h~C"h0yH*e3>~m~m[cOtvTFP!- [xyT_c׫]m!aA+ͬ o)B`"K`[nJ؋(";т ĶE{:f `U-'}gt['q#(A+BTTֱ;(kce>&\l}nZʽL¸ƍ 2$]?u<' zظ rA{p='?F0_x?ܲs#/9CלE  NǼX%(;]q&ӈ>Wl/97kp~",[E %3s-oz?DGIϝǖk~ P(5o>~ٲa'dE}lus(lcm|WX_>BX:$Zh9cԶGcؼp۲9tDXpwl\YQ[R'*w+V_788ySS3k,goڶ}vgԩ2EVsoוU;}>+- C F =9}b/.^+9L;KgK&gF(ttX# 8D'*k5JAlT19! ~Uzp IrMNhB5y“ha*s%N*K ~viߤ}JqF*еVw3MBhiZ31Ǥ9Χ϶@&]܉m hzR*!D_=d,]˗~[o 6p%p뭷yf>OswSOEEl 0>iTf)-^QQJ=X\!Ul$f΂T=aKr\t R&i# jPhxqSҔi%_0w|BUC[*:uhFȆFBږn& AGUE/܅ (j#JLe@jhGlFBC"5cw~~ZFs]a!ͯԑ(O|U 02c0A 7}hway-7$]w~y>DO/H 7vs BFl(Tw`J7Srlmj"H===fJ j5Sz'| Wju~5o<\XMӂGj>q>סxUP (cdzPwno3a/r2 ij%p#dVS`K"ND0Rtn &>"&ItvҊ۰*! &Z$A's梫5$c7mگ] ٬]3@ARܹ PJŚ5kBm6^|Elݺk6>߰acǎFt0#`H( Q|o݋IG>cF6rF"en /Y8 LJq>J1oiG{h: @}w&S!HDt  "ͯo|3?H a uacrM'\. &:Ъs JZ8VcP>j=Ow>DOS] ϧgII90EÝ@G>mGɤo|ITlAUS>it?Ng?QQ|\'" FTA:$c"ZZ Ȃ 1ؖA8YkP/O0w._L2!,lFn)1JalӍoLK &]XQ*P&3 SG^kXJi+oX1ұEtw֢3l@iE[>F}?2h`'B) lm~5?ƕDzjec'y2t'Cؘ:R@x|G648Vȯ:E>եxMJHfhFTf} nKSQ,Qɾ ڣknv~f՝rHIFR|g}JюcRhGqvp>Y*O-'1Pؾk~ɨVzVL۟r,FT°gGv|}~, jHaևH:apΈ+qGDI09PjeR/HU7cݼ\׀ lj~1 tUhP*]ymHp]v/H+?k՘Wwoٲ%Rnf [lyݩ,;::|>}uguEPxO n .&Kx- W A ت{AC6bHϢ#ӹÝA8G<!<6]'I-|R!0I"3&3~\q[R;>ē`um[QolڀtIUvo [ijۿCbH?OK)o}|uN8ބQ:Adtz)Xۦ! &~`tty+V _&M`֭@H&`̘1Ll!ZN?_,0cؼǤ{+>ARdER?jU3sk&9rR&ᗋac -${7bNd htPZy } 4淮 w)mNb02vs V*wZPb#- __?cb{p"N#xuF!(Zř¶Sl/|s ӧ*2g] chQ#$]3i? I޷_Է=1ٸvN%t%RpCJ, v =߻tkF)*#0BhCk*R)(Ʃ aRT8K_9s&?HR\ve<xs1y|{cÆ r0@5D8֬𕯐:T-O=mlR38Ws񚚱IT+rvCq!P>X7>U(DY d(P,-_ ϵT}D&V{cI,\Oгo%@Xj'R=?PDZ0Fh=nS@&٩qP}$pI6bv#CJlBc0lIj j1Dl3to~ iHԪ!~Q?>CǩSZ~QC y-ћK$(. Zd&#,;(6q(Tҗ3V #%=y:o- .A ~0r~D t@iR?9D&K6,cI}x3Nb&0,}}gc*W*1+#X'B SJm?;4jVTmr8d\:_냺`[Sڭ(P CTb7w}wm:g}7{%p `B(ksZ߲`W `Q -}"I @ j¡ch99J$SO!Y(8hiioƶm<n s宻O}/w}?JӵmBQ6O| dpF<o410soַ|[oa D);a-6r_)525˶0&rdV *N&!h,sʁ3Ķv$i۶o#l(L ΑNEydIv=%RX `ǞUa. ?bX7 *Ĩ(Ũad,@NNP=e7iiҒ?9}uuy*LA/`|-YٽrJvA2ah4Bkj*]r4=`[ToQGH CTʡedSBMnY f۷d==J6X7 C?!cO8xGcMJw>7ItY#rrm߲dUh7D4OĤ2Cz, TtV.m19Oj,phm1*ı-E~{Y3FjŁ46#pch`Dk:#fYa7DP? &O<#,S)؉5rrB,!XQ}Q~9g#Y!-Wf3e?p'}oD-9p`3V_yX*z5Gm OuwdR5R8C+}'θZcuwTcǬeZL&9sشiO>$D;wH$(,_wtttn:rg3e^|E2Ppk’{{I]z)?vﻏM_Oހt]DZl'?fA/I6#\-Th@oRrѵ>[<:{-:6mȵZdx\#&* ضk60,'t6wBd˲{>T"\ ;ʢU8L auꈷ!Tm R@_Q3m;rktm3j)٘J%K_rQ95IΤ($$1Td:)P0޺^W5zE>um`ͳ0K uUx׶AH9@_=]w7-栟q\Z>efT*e* Axх?D! C{RiQblf V TOiYkmAJɰ+T_/A4wS/0>h9`E@_"h^o*z Ўs&עj!^%Zk}QVmK7~U7ƹzMy zMUx8Rnngs͆T+Rh# $zy>{RoYƹ0°LsAHsXzl6E/30?uyu߹T*H[P.hea_pˢmgWXI99GXKoKjSKhQED~s+<,c<˦{4Sq^eFOҲ |nL[&HU$cBT- j\uU9Dg}m۶sNXt)>,===477s}j*6o =2tfCGìܶL"</PXJOОKkK o䩗A!O*$ bd5oK.lxoiͫsbWoonii9^MZc۶@.45kV~"ЭPPzנ?^ŋ_UEGOGO /A] RR%q%uϱb- @ұzv@MHCJL&܈ yt),PQ)kP$SfaV5ahLX8nT´쨞~^'sO\JCœ&QL'"V.SalN$@f@-Esi<0NKޕ6!@W"N4SbaMبX;0UrFSS]qAQ`= *53!ZH$}1A088x{V?n.OH4)aL$p8LF&eaH@H",Lxhm`jFί`…KO]s- JNsB j)Q&!eiצtO/|pQN] '2lEJjpI&iN8 T8os+S] )P RKɦÈ8`?qpR /x_%]FH)#^yU[c)}*m?b_`ta\<)ruv_.+)_*K۶L%!fBK5[րvQNk;>q3/L\& ('Fz )@˄odK*,l/W.yՋvTڐWBdBc m gؖݰ| ԚjN#m_)J A^.BR}H';# cv-o!\RYeɤgusvnޚ¸+|]x>Okvpp\2rՍ!Rnq\D6RHD1FÔǕ!V|yA;*som/Iw' 1HafQdsyq\FGGa_JɌHa"nF*64$$HH;齶{9GUu:+y~c:UuV=Ѕa%QY)`x_Uۂ'WHhng^i6YB @+A*ܵCX4gj+||8*Ja̿aXACӀQaOC( ז&`bD #ǽġP!`ŝ#AR)J6P0JÎD򻺌Z 40Pv=X%%~B m :pv/ZnI.?li lh0  ¶e) }{2ke} MDxKW^ $>@- (|='$ L@x!Ѣ{#%kGG*-RUST&Hᙀ' l_xXsF sՈ?k-]}M-lSU5 F"X^:ɟJYxؓ_ -ܲ‡v/Xnڴz% 2RA̅]WHDKKae'vPj߾j[ XY@+ڡU 9H ԁA&#U>~ c l!Q>.4=k#SUizlM=nnxjѱz7` B9';F3,=ޛZ=VDq-JDudOv]J̱,je^GcV|`xfe[<jj=:}Ї~&7|cd2<4!10cܸqI?}tx޽jU^; ~}D*ܿ_erZ&SXT0D|q$ZFSQۘlKTѷ+9cFzzQ:mQ8f LEnOz|(vt'8.m~|3_ N<#l7gl[;7| hlzMEmdU?5snj:5Lr`ugdc`ʂ=lx]˃!Gq0eAK :߻f_vx.?Bˊe6yG9>bO!ۛ^{=G{̱$eMM5dXV@snjt\t_':^RiLHyj_ZkDz߾V^=fq+eYLl3gq}ҒTp{Sy-EDJ9_\XwT(U[K)} #tS5ɖUs=f{|0d.p4HD87HX#:/d\9 iww~VTTrF! 7/}iHqwuפU4{6.r7nU}}}8=hػwoΝ;/7o޶c|[۽~ Vر'?Sy=cn o/. ׎o^K;_6cǛw//uXk]Z 0Z׷^P"#l^Y7V,zcG뮻& r8>d?1RJ.r455jhhhNx# BسgOǮ]c,!?o@ PO6ծugu__ߊ{빋AfZL&s}.8N}~``po(ZDV\tE777{ w_~u}}ȲBԇ,K@N)7[q>~&^o|W^'CeK;֤RmC}}}/l߾{9Xb~tphsR|60w[/X588ҟooz{޳>h`H[[[xʕM3̬\.w뺓\׭QJC`.[X#bؕݿ)6ygF-G}~{,8Lt0J)~?_NyL_v\׈-;%ŀ^%8U8͋-a&l-Ϙj7,^RqX =lU7Z5cfp C6۲D8B `P=kUEo~mW+k˲ı֦}+RJݚZ9jԨjs9m[+і;^uύyW^9[ ^xi!?t `׮]k;::͛7X!\ x<ޜdZt:l6[Иm_p%%%k#ȢX,v.K.n [ǖDfE, 1Pp H@XR" 2Jaw:.Zsm 6;9P55\3v QށB a K#۳{۷{њ؂C_җw]K,Btc:o7NrƟ'c~XǤICo-)Fk@65HD([l6kuq6޺{/erc5`+# jrcuݽ@|}I':fo 5Li52ߜP)h$f_12.GR9qJZ8YX,)ةk"zU;^YU/܃cC|a kϊr'M_""fp>Y*eYhllDII d$D:FWWWqKKcY LD"@l۶ Kl7n\qՃ>mmm[v[]]-օil&?mD Bh!fnڵ_B,mkkb1;{_/2*L ;|D"*++/_זY~vs2=`qȽu))(m2dVIJ~܂_836557oBqzzz0o޼pcŊTUU )x駋Mn]]~+/^|WFiZ]ki`^g~|#$ cd1u3!| [" S[!JIx9 T3?CIpO?NvHNe:B4a2D~Ԫ 4 m /C+Pe(;h"c  DBPpմT!ǚAίG}u6@C<\#Q^^˧1CX=֛}QK'-}a m0YD"B =xkUUUD"ß ꄷ+|bD|QSS`0r9KJyET|.3PkjjZ /BJ$V2D2TwyE===K !,1cLGGW__;\{]wFV@K2V^|EҠUʲ 9S\VN)k UhJFHs\yQqv*q~`Us\6ٲ`U4Ѩ^xת\xz/} eYسg s.C~#Ho</WJsZhF1FkJjFٵs~2xկ<[rJًX_ZxWӄ z^{=w_EKKˀ1F,_<=3K"ȽԇN!/|kLY#,XvҤIqSV^N1d a8Fܓ\.7%H h隃 عXX[j,T |Gׄ:!к[!n;vM) )9;o͆_r/|MaRʓj.n~kdrqg>; 6˗ﯭE."wBZDmm-۰a>}:/_xWZH)O|Bk-zzz ޽[mDZ|@- )i")1:@o.{ٳېL}ToʥaeU6g߰ jV<SLy'g!PYYw]x0j(gy睇m۶7֭[1qDcTOOvk}sx6{7dֶ B؀>™Jd%D|ӛ#{ncu&\_XIٶm&LP !ycƌ/m'L8~„ع;:e޼ye\joo>?5v)GJ)ʢ}߫\.g_८.a8NՑ>l}y5&=H) vk…1uߘzԚpzW%TwfZ=BUspM ͷ./!NJdb>̿oJB dXL$@gB&1}4Dq"!\ &OEy҆RG91(,>sukh?͎7 Ə5\ڽ뇏Gy}?*IRs:Pa~ tl'\ұMLweE<4n/A\g7NfT8g]sn=R"8JrίhSv`dWO_鶲 O"O ;jd>k#?S#pq$Jb-}䗓yzM8qF.Sfdr95qg7ޘ[oL&3chhHٶmw544JJJflٲsOVȸ2u VHdƐ}F xv /V'|`y NJ|3fŘ1cn~'/ &'OƲe`6QSS/ؼy3ߏYfa 'M38O1Z1a)EU 0Sl}™?9kx"k3fSMm-5g1vмwYSƱW_[@8 RjwǛvv5 㮸ڲ+n;wb_"0S__sccܻwʄL !d*5ƘBMߎ&葻A?vOejC5$#[TWcdH 5!'CѾ$_f~ybwWn 7Ln *5_D^> [ 'DؼiթgؼKDc-rф =US]g {x\k <znşOQxF-G ߩU˽0~u65qh (u a\b#o3v{._g >VsOWrlzvzWұcs#yhGCc~j^wuO7\R,tV(b]{EaqQp [h\c{k 㡴 Ǫ!7"R }O5_4̑uǗ~" l6kNw BtRO gOr& _"'BN7LDڦDE8S:<3ƈ@OHDQ Vøqvϛ7o5k-[d6믿nrwc;v,&N7Od(2pW_}uڅ^mv hG7 h*wmׯ[7扦oW0uUw|l6; >P[_sj}VWURZZڲnݺ=`˖-hjj=y/Z#&#[r9f>7 &x'٤u=C"K[on`-OyގH@x 2lAMkZDVK2x7["uS[Ts8vBhϑ Hw=޼фc\,z*6fZ}7GdTl{o 'Yb2oQ[p帙Po<+z9 'sjm+km+O̟bq2 ʊ&"~+|҉Y,m;o@ yxT4ad gzvP}в ;˒3OF?2/UzWw|>r#~0XS2C}%jm:5%ф!Y)9뉰&֠հ+ FD>B~Wc¨ \O Kx޺îOG >l bH$5Phÿ́с9:5zy:q!U7=Qpո9jܜl'_{}‹Q!I 5,Tq\cC]q3&ɷ'*Q ~)>앀I)%{ܗZ^x!s޽b͑ gz2BH8pẘ4snS lt?ϊ$5Jf `mD "{z/"M\)"8l# FrEabmL"@J# *EC8eW}X=YptUd62QGFPGxyਆ)/"Ba5ݻwO9 0U0lf[5 ~/_.V 6~>>}tq+ |IFEii)PVVf~_@ PhDu%Gy!5RT}8.&V9R@R@9S)ԭ/ B]tю6mzn̘\N)da\ 蕖~$ ?.2NKl ;y!/x|Q__cNJ. FN7#.2RB (̳r9 Fc}St{w6mҐiuԞrq27=Ṯ Yn?0wꭿkW6,5VPk/'(n}74VPە KV>zzjXNʆЀ7V͙^W>zcO~U>=X9n@?tv: {^bܜۯ}}bs?:`}qZ*eqOΛwH&U8,j)<680ҞR݋fV__;a„]TOCCCTjjܹukB%-+۴%9ܙ/߼n}aWm|;v{ 2O=sΕs΅׹f`%W]XvYYGJJJ>SS]cKVl^g'3DɅLg'(ΕguU]]m`Bb#2[vmm5j(nW}}1cƬ]mvQowtn_iu1q2Q\'@i{j+1B(mpuD 7\2]|JwYt/Ji,+y[I PkYV0JYgcU[8B`OQYg[=Eaw#oGNօȹ0p\X*tC!\Gew)j]SxF(B88]@ Q>bl xdv5AL0ZO2E2Ao@t$sAZBhf#rWbSS!Ĭ &Tuݮ7ϙ3g]Zqĉ֭Ke޼y^zhkDXH adrZ:Ky,ۺ5bcT ԢSvZY3ztGcSSc}Ѓ?]KukL:={뺓1olQV^yeE"jWOv,' *+{ =Q|C㯚4i&83q&u+ײ.˲^m{mk7N2o>>rK"glR:}& YXl(WXA,\֮z^Ĕzz,VPXp_6sX=Wtw'n|vb|e޾ˬ޸'GN0W{O-76u=i 3OYѦ@`~q>J+OΞ}_2yZꑴ osfZ.l*ed5kd2hg/, ,2*֨s>,GOM,`i35R!FRcv.\_4nV[JU @> @{-6G+,&@ +M'BJ>Gb6%%%'2ދfZ)'RJk睞upB)msBt$8=9ӎ}vsZJd1OB9Wѣ8#555Wo\|KB&'N,qׯ_Zf ,Yrhᅁ0/Bfz2lI s+YW _e[NŅ73=Ee-[< fv\O]{oos}Gmۡɓ'Ӛ5k=ztk/fRO]|fb.y}hi5XJZF %Kd qњOa8f}gٺSp@C/5`:5֖.hֿ.KDa eo}֝*p |Zm܌th=/; ,!`b1ȫ}WfhmXӼ7Vt"|%~uS-7qs ӵsݘ[-8Bq=E\mLVâDXJS{{"Lf+'&tCJؑI3wַe;UC 4TWv\𔑥\wn*…-WmeHې|U/PIgr„Kh #盪]H0`H>{k)|OxgNCY={^'N c"۳gkUUU,k1N> UH˲UUU֙ɠ>`l5ڜb&)3y.gJjl(-eyCrJ ޽Z3jԨc\f3g `pd1DŠFņ|CN~v>{B@s>'c*+7l ӕQX@ѣv````?DWgwM9{c=6N1Sٳg{^vTc↱c`1TDžc2|Gl4}.BÎO4D]])c<|FyEtޔRhIB:ds(s\k]M+lε6wfݒBE!fo%έV9~#,ܺh=/A>hǡQXW|=;{wuۻ̺՝W|=(]x&+zޞ=;ٹnݘ'MX8hT Hok &9A)z^c 0iF:}Lq|@/FEƍ{U'ɮl_[6nܳ8o9ºEməK(u,LoM|3A3'XmdWGټ{nSzғdV[eZBYe2ꖖx<V۶mBueJdUY)WRg_~ǮܰTo% ՒL& sF|xi[M9W Z?~Pk)c< ~~7{_HwuuϘ X#O*z1\2}o'LvǑֲ6@ #}OmgbzjNžV3F{8M)YtSf6{۽]ܲH2JgVakX-%#+ =ly&=X=h{EގM۱]{EbF`dR7yr&yHnq=y[u`i}}'ZIub%5Z{PjTjmyiGG,6{˧g.Ixއ3w]9?O1[u_N?wqOX0'ݻIw>'|zf~m M&eDLluS:8U~ V\*aY)lq)-ȥɤpX~r%AeUgWǖn%R;ZxH&jhhS۶m`ʔ)w\q=k٪Ќ|RB+/^3fmmm?;۸q܁\{i ;yގOC: t);K^MbZh }-l.o÷oƛLMn>CQV@\r.zWPxo0$?q&'R1ŅH`Nbnrʌ+LmF)#QD,KhWBaʼne#q:Ro,>xZ<!Wu?Re(7%*-Q?Gc7_bFY,&kxgMSg ֨uYMDS"re[(7FG"kˆIRGm">&5 jך?<1ꫯ>VVVaʔ)32:teQHz6꫏c޼y= qZ`0hB {?ce3KJfdRNͨ ~,x,Ύ+;sq*$>C IÖQ3̊_H$aZx'zwTڍqn:]{)8쳟}tu~x>\s9 !~oѦubsjo,Evt o!Gupby[4"} GMnv'|ȷ62M.k9.y;3E'S[<90ׁ NUZѲexɭ3 cM.u(Lf=Zx)(sBHh8rTu@܌DeQ{<ÌbMwn}]ϕךn5s'"囜GvI!P0ލn”UTӷHߴf<?S->H-XZ+DX1V2g̘!ZZZgy榮jjjL65':gWkmB__M7x[č7~򓟼)>k.cL}}=nh4jВLsMݹsնmrFtrtn|7Z8k->vUZm389Z:=xӚ"8B$k_[yˣ>j o !r8Bɐq@/8|:)+MqT[[ǵeY5Ƽ|`1O۶q_rl/12L#Gtn#&]Xua-h=bp'|K][)'cXZ+uOX)c`idlש{CaF@~p"oѨeNχ;trZirrO}Y HGi8JW@f9?AK:b@KBX[Z(]^Uek^߇7wuʥP*J%P*`Rر{}kTyU^V:n[8oU~;U !Jׇ\.l6{B\.>Ri<#W<Zc߾};۾}FEEAKD"a]vevر0ڶm:&wmdY{ǎ /Ui#*Lh4j?\UUUruv]Wr9`WUU-aqN_yeLvaV)6foꃻm*ed^+g$[ k}p׷sem#mVZiMi^΅;UGrJ q]7Y___;k֬H$N{`n~`X`ʏɓQC(\y +DG ߢ}|lކKzy9J@Mp=Zv& A :DB#޼_}F hd,E˯=-Fdz VN -B!fd oOkE0FֱՎ-??!Č+ƌsѣ86R" Zݦ ^zBYßd2ϟog?[FnfUa#oJ)aTWWg?ٲdrdR͟o7/;!Ƅ rdۄ)<@PJkl ߴiYvAwś®l*%|:0@ji-oh|;_vn}}}7nW4 2IDATXL !O3BP7>my73`Ncrڶ)0‡&mۢ0R5B۶:pGkΟ9'E#B_ 8Va h7k9XiPhlK"K 1aj/s-k2 g.D5{Hk{X:_rp͘Yx!'4H`Hl 4T׶wϢ7 OmΝ;O8| K@gBJR8묳` w',,2@@J)?͞ϻ\OJZfE"_e ۶L&۷ݳgϢPavPk]z׿ [g ^q@J)U]]ʵ555VXV(۽`]i҇:T0Z ΊHQXN]Ka Xmf&v,W|)8fфkglծ%W)NR@ZBH2n};ԞE{m&c}hؽ{ pn ,8aoc–emכo,p``վ}@aq,O1JJJ:Fx:h|vIII1f1{ktԀ0s!VqhXt=Xz[T=%cnx\Ɋv/,eׄBz;y ]Gq0֛- =#סz Yv$i*Y7ߢ)֛BPGmmmA  :և}~I(~BD"a]}mϟ{w^W^^~}0cv}(y{Y=88⮻zK$ 'I9zŊmXl +//>NriRB%%%+**V̘1x<^ D4j]L2muҾ>(1>PZkϘXy~ ?3\' Үv@u1^(gqW}`@Vb B"x;QT6f( ))>!&ԡ?* :G>Bis]& cG;iCCCe}YY|8B ӱ߰‰ɟ=?ۗd{^p?T+h穚@Idk i=_snjp`pZ&9KZ”K.[5cL֖=X [nfϞ=ǩ`0аuɒ%=G{̱$kjj#ɰ*R}3ٵh98"@lv(2[QIG?Q11.Nfkҕb˅5s2Ȝs|"G+t>oƫx|V]#M,_:2c@b% X 0GִOX as=5忻 ^Z~77=3F~Yg BY@˲&YU }v}N! jȗep2&IVP*^r.ϟ/`zĒ`DDDX̞9s󍍍6m鴓f;֝J~c,ZJ XHdT˲/7_x+͈ Ql@Z; #_X냦@$0zRk_Ze¹kRg}s蛎brʕkuqF%ۋ k"":$5jTlԩnccchwv]Zke1Ju/²,ZnݲYfR~ϕ|"$pVA `u kƫ~Sa!]׽:˝ZeY}@`mۛH$f̘1}K_:h죉Fd2y-N Lt:7)9oWk] A 8[5pX,v[q 0o:`,@YT ]nl[cО^ [|c@.(i}hKGiJ)kgB,Bggg_?B?mpxy @(69R !K!#/^L&30P2errJssyxD"aT`" a^@聩԰I4$.@tMeP)P'5_L*RlV۶m_EZ>WmS]]=ƶl1FdYaih/DD^rǽd2RjJ__#?c=zgϞkF 5 pCa)X0hۅh׶`B0j_pQo ![B Bl6K/]~9r}Y֦CP~1I_uG+Sյ8񟈈tKk9l6{swwlhh8Fu~P(t .L` m7"WqX7f.ݐz;w0fFi@I4!3 ]AxB bĉw+>o} ŕ %HWuhqi?݃cх剮z#s)//?wʕӄV0ߪF"~@7 \=B: (PPx{?ť`AWW >!ttt{***c`ǟUD !L"n1L>bG7[0hQ:_x'f9 B2 hL0/S } h]A@IM8EBqpXGGv؁>|yoBJb/a\||^yW'- /hmFJ)eYJ($Q1@ co6'a j;@l 3 L3}I%`€k s[***ىj|²,@v7ԳBkk+nF|_׿utvv[oŸqO""Az0mdma1<Ȫ\.w / BYm7I)+1W)yMkٸaÆΑ;L$H4]x&UEi(Y{r1(.& ^ևʤ1jU@x#Sˆ]Ccc#ָ{s>яƆ ?nawK5bS_@DD o\PX8HMMׯK.YZ㏗cA8W"54<=ӑTC{AC0ЏPp7A(c` T6vTYv-teBȔ 5 ?7|s$uB;Q[[ c wc P*rf~WF0}xʕٽ{ӵƘ'׬Y#̙~8hFcrJ`W7\Bطogs\+LR8vbJw2F8x["pR h( FJ)100/ 6 /ǥ^l6\.5 lRCODD p<ױXLz>`ŋX,&/^K/Ů]iӦ|W>`Ic""vZRfh:N#|F~O;܏k_]_Mݝc!pUW!J ay DD69uvˣ>j o !r( :'ҕBE ( y=2j1* FV,$2&s0+6L_DeR xJ3.]SׯӹAyaY,//p؏[Xu]r98\σZL&#NP <m68 RJF>+Wx&ǎYf|"---=7u WFeSʹ j'"89mo\"ΐ]Z!ځ,L~*F) lqLUUն5Rʝmiù\ng(=;8)Raq`6ѵw/B\ׅ(d[]@k}!"": }}}7nW46dV%W nokqlV ^,} -<#(Ö6+]8:r/23,Y9Rsܤt:=3]dfy7uzuKow- LœyDDDoH*X,f;'xb˽11{CLlFх嶦#\0P!8$ 57~ԏ*|ş%jW<#5ﯖRRowc34eH$󩧞2Db'A}qqd`D +V"j(xXLFQk[Qb7ooƏ~&cLc8^Ң K1CFjaI"|c /^<|x%3/qR#ԜL2"0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>`LDD0DDD>~ "<ր|&"" `"""0|&"" `"""0|&"" `"""0|&"" `"""0|&"" `"""0|&""?`&,2IENDB`gajim-gajim-1.1.3/gajim/data/emoticons/twemoji/000077500000000000000000000000001345766322700213655ustar00rootroot00000000000000gajim-gajim-1.1.3/gajim/data/emoticons/twemoji/LICENSE000066400000000000000000000441411345766322700223760ustar00rootroot00000000000000Attribution 4.0 International ======================================================================= Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC- licensed material, or material used under an exception or limitation to copyright. More considerations for licensors: wiki.creativecommons.org/Considerations_for_licensors Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason--for example, because of any applicable exception or limitation to copyright--then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More_considerations for the public: wiki.creativecommons.org/Considerations_for_licensees ======================================================================= Creative Commons Attribution 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 -- Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 -- Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: a. reproduce and Share the Licensed Material, in whole or in part; and b. produce, reproduce, and Share Adapted Material. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a) (4) never produces Adapted Material. 5. Downstream recipients. a. Offer from the Licensor -- Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. b. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. Section 3 -- License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material (including in modified form), You must: a. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; b. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and c. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. Section 4 -- Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 -- Disclaimer of Warranties and Limitation of Liability. a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 -- Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 -- Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 -- Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ======================================================================= Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at creativecommons.org.gajim-gajim-1.1.3/gajim/data/emoticons/twemoji/twemoji.png000066400000000000000000033234211345766322700235610ustar00rootroot00000000000000PNG  IHDReIDATx]y\~.&;ᖩYdkV_7[2M23\R[~LRRw@QAA{枙9{q93Ϝ;y>PBP&2[# T26<|K-[ 'C Ff · z@6:SMܨ_ kw6Ñz_o/0G=h+ iT!yopg"iopɶ_GV!ء~v!?|q=D$W>vc7f"sc%7屿>ykÑ̞Z*~2'{+f|~g~;&+`Ǟs7˖oܑX8$ ~W\? ~J|Σ\*~=O&HM5#FTﶄS* LT42cjoݧҬ:Yl LsBbh"9(*pb&.,C5Ij0s6MޑR5#r9jO5)ΉwAb`(vxr->Fl÷5^h ෤!8>F#ϯw_Ēi$ۿ b~X o00ma_K!gon8ROf%`x$$EIo  6l 6<Ήt-.F Kd64gxt@[{!ӶǰΡưL OS(  3?`&z:Kt_[܆P+I?IN멷cIC*/w] ^|-u\/lc/KIda7Gx9j?}Z통G@v5ӗm/V|awBԩ ^w\?Y>f%1x~`2U,d}#%;@I+dY~"O kړ+Pi/ߧO:!rPxj2" ?_O^RK/7GFuA/.0Q.Xy;xޑ?_O̚ Q3bt`IEA` [һzv܏ /ߙ85|٥<4 tʀzp6g;7?|V*j:d0y\!|#SPTlAvGD|}ר_p pjaX 8WM*@FN9F&@57;[ Gy?Ư'f)C֞R4,oθ1}W)>i9xGSuĝ{4ŏ.٠ƶmu?Υ<9x.kKIX`ʘΒU.Uܵz0T`3R5#F{" Ezaz^;[ŒJ.Quf4_9 5% 1D }ހ/ወuarA35#=ap{a$őVc$ɿw%v޳KB2_t?oxNPSeXCɵLZ=y]TsPpߨց9/7!"1~Fag,VysVOXX͊tsX/F["Bu^!=GA X[pE@ Jק_?z GJ'bSס".Yn9~yf+-*BCn#KLDH@fVyTAv8<%ZZhw[|V6X:oz-V, -4?m!rPii П30ǛqeƅbW:,p_GpkS܍ b͑b^-x}ukPn~t} 0 $kCws"(=~5Sx~Ñ#t(|tV#s.rȜG_kt]2jvs+ԕb;#8Y 0Š7:|S+T[o9Դl|J)/Y W^1$KPVg^y6+95YH]Q-]H|u՟̰l~>@l:I?XSո[iǑ߯j,ʎ42|Yx}C #?tE,x ,2\_ % 4Ԯ>LCzK%LHkE3WS{3r?[br\kC|]*ǐ_AY⫛cy}tE8h_pe:-kkyfL_;2fxO}q$MvG־9Q偢,^qגB i8^YW6XWcs#ލ]0/R2 RM``R6 ~B*D#UPƛ=\då5(*A-ȷH~?j(Zɯ3ହ'aRxh<,,DT;4H ߆@rf@Q >GlE-0D/ދC&I;pBٽ\F?g=|xk3!w6d0*~JX|2K=R\I4҂D A's2G:VrtM:WcLj}T pi'㳹;2EL_nh%a.YWfHXĴū{7Eoe ѫ]JPKIzrV Ũ ɂdF/NE yOѳ t-w&(;7'3sqV~:T/T+Šj.ދeD\.,v{VA@rV펮=~s֕KZffmIHM+=n?_nL:v uY=Դ\ Xǯ=k8sGۥ7$3ϿßU,xu?_O6Q]09 \iԌ ~OϦ8/]_"qքnox+_< :\fs'nsD|AtGt TMWK3PoG;o4?z$KԂR֒a<1[Xa5; =c9qi|]dz=e 6ќ<7O\xNg0?3"{!W{//ƾY%vʼ#G`IL`̌CZOKL\Ia_["5-B.[j0rPRrPPTЯσx~w6~nM_ıA8X?jF f9!3_6| )N,V;%ӐN& /4jF fM?_n Gw%YWk%dn5 ~1XpcDp3K$c2Vl-kn[NHC$ۋ 3y,G Z/MРu1: ez6ηL˯ hD9hr-/Y\S4 Ҧɥkjمv ݅ɭ-1/r}o(&Y陠=YjYg ,O8_nKȮj}߯208dm]x>lV o5Φ5 j)'CkW*+pTH\)4Ѧ X?dg ,ܖLĕ3___(هOTCjZS԰Hocku LD,ৡ&EOwVXrx~X :@4DIoRnawzs*.0o!8647RZۮqh ےp>"6D65wx"L܄`, (Y(&ϩ+4+8.rnIe$4oKTc#/FHkgoIC 7C`:%d U?s=Vxg[c D@4@M"xn!^= 4cK[bݻd4@O[֟n[w%r4[%^u[hEe_ZYV*,-J,R+5/w,_@蒦?/XyQ3b,j* ԟ%b҂7ME}Ǿ>P|EKQz =0=KH= 8tl#NJ]ӦUՖ$~Pp?7i\_,̍KUOHL̵T*WFRR&> 3 h !1U=j Z 2Rì dR+gM@cL"L@f dB^V DlTxw7ŠsoCv~篣^ClN UNQe׽آ!o̫; w%ӐsO 4] c-8d< [qz:r98"$.܆u$xl穬 @"x`sZYd;]bE l`F=g-n5i+_@_WwG(. b Ґ^R+?Ӳe>jk5$HJITN.I_k̨ LCi tLS?jF ڍֿvc~bd;N>D Z:Kz\{3|.T Wϻnb#Q>#!1Y\o /ӄ>aw-/V޲w3wH>g6$PT&֦L$˹i cO3')3ǹi c8l)?5E 4H^pV@%WrmTQnǝA 5:ܤKԴHHL,hI- oܟ]5|gpo&YVK{ݘqit8{5?vd-8xfg:#cnn8ᅷ)pHZW {xcX*^P1@߁) \^_:o/T3?w2g1qّ|=ѥ.$abm\eV#a-(VG`Ʉ x{?Yc 2(?Wa*w.(b1?,VґZ+d^AS rgHr IP7r΀l']9bi [dɬ"Ŵ÷=Y:2n_o{VBjZ/52o$O_YiHfCF:֟FijA*Ox}]nqߦ.R.w' p+&\ys/TS.wp$1x~۠4-RR&VoGAQCJ_݂62>0~> \dHa2622805+ه=0(%dZq)ڦAk%cGb;#g&k;:÷CgJ:s3AY8yOu̧m30{GXYY.WPn%&ې]**~=rYa5,7+ypluM&1@O $ "MTeL@t_ng(Ki5<3Ψd;׆_·aQ G؊G a4_[~VgJ,"DGJ0 8XX 9{`JwE. *n Ew @yV-CeտH̶%^<&X$M(n~Pd Np&xN08U bC7 UBl9 ]:Sēe*fj|}X n^uU0 |&c ;#u/Q(ԿziſWŃ:>[]=`<ק?mV/Unv808$p8/2'9T5#F#U*ÿw%D͈єos/i淠UVO&l+L,H%XQ䧭_+` ?POd&[$g7GzQPT*2B#S@|f(K┓}$(#s}W 8~*K/#/|O~=Ƿ^Y#LuK8.L`xj io AX8K ]9}HbHB`({G_PoXx9D6B䥜5ꒄڧ`Cxde[iX|De\t1qKG4WRr#A)ـjmCvS\}ʘu<~*ײd.{OCBۄsD$ߊ[1`M8VGwV$L՚RR&.%g psKI>_n W_-ZZ5XR{Yn1Z"0*-e1kB7ADr51FT&RV@O1N+J:@>F+g$~_ntr;SXH~~ABb:/Z,P: J%.tc<^ßӹ-\D.hb6 Mt.pe8 ʐ $`vUL HjZ#ox4]EE,6@qwA( :-Z}i,+aA&Yzքֲ =)أ\,z~VJW4>e%k\dr.|;y3oaXs2ǃgy^1X#zzJaZϡ XOp))jҺvޑ%Axk>?v󋙽PˉPǷ GڴI;M,¢zYm?nAT#5X~%OJ,%P.Ntl2OeF=7$V jEF"ijṕ".R}N.=n↜5<įM\PToSw/[?e1WU{k>Lp5_LWle}9̫5ImQ@tǍ,UGYK_Sz^!N:o#)I%KXr#[Ye"?b8uf\zŘd-;(^UnR|=뉅z&;zjYAߨ*KvHR$%oq|4lw'[_1VoT?Ãou@j}~R5ϣ߷W34+)س&~QƊu g0_flFA!|/rsjWo7}t_'t[ -~$ڏ#0H.`001nM`K*끱k ֓G_|]Ym~/;MO[\௰sJpZ/cdgq,vWv_V}̴bh&nf,l?iUSh4"Z Lm/X_ _]'ƚq㞺Y Qyk?Y/qP7MK,_ro5G| O#(~g=:cY+ט$cDɖˠ1'q㶇V@4GTW>_gR:Fjhx\jTkӫ^I//o֫ԈX˗/v>L~'ƄD_zW Lm/FODxeh )ro,LoW[Crn+9vvO, ⫩F{[9r+9 IRu$ L-@mpGIm.8o*{h5: @Ñݥ֑FAk%z:x*~v0VP&j6I!=\&@U1[T졡vON_v9~ߤ_d`0HɲZ.J4῾t$Lt&euFI:킘6[]?zY%v.au &.[ku-j9G#WƏ}\LC,m=#YJus5_PP>?'(~%и{J6X "~^{8qzt=&!&s82[%3,NG%7@i{ӭ3YIy+(cq%#uV:GeOU?yoAS`ziDصú~PW q_?vqdՈ cm8 l3eZJ_U齯]F2Nͼra5&}?@"?sKk_k. GZ3]kcwѥ&w S|l!׷/t"S|Ycf{a_&cH W?LkMrV{x];?tyKěv8 K-F͈$Mjj'[DW[cex(ح?^&`S!R|i 9qLi`pv,|};(.W ?[CۿLy65q#TT",߷3{/K-񨄤[Q$הAŻxMo$-|-tcL~i"jFӎJEԌz'5MoQ\DpK_7Y4q P^9̬YFf.&WȈ 'PPPIH</jR2!((M}%7Y[Ȑ~$m`rT5W԰~m_ۄ_j&5+qY5x5"x:N@".0Nok['׏Ze3\L_w]x|7dG:w0 ˌ A:/+dn)faG{bT[p9yFW[R[ŋ<$25tQYwRb.x,DGk}dU6[ KpuIvwwt7#wfHkժZ5CeeefW 5C`d+=م];l99컇#?!1fhJMm_"z?+f1^.<~ Q÷>KKGj-Q:e9]#7n3$pJpW=Eߘ}p7 Jd^R/$|!b!Řh "h׶-| .)`wMVB7! w و!N|fAPWN)Ʒ(7ΤH`0Ilea#A)V v´A|".2XWH Ky^P6y/..slc2 دM5PK•pPꖀXZ\"-'&frdОOOW 6|w'n*V"bڏ#eҠogV(CȋHn۸sK ]Ҥ`_݃/C!ЈzY}QYɮnEYk%Yʲiq%tDٿH8,>UU^|ʝdo/7,F?EX 8u4T~m6c`"Ώ/דJT 0È@>b~ȋ C 0#_||瀶HY 6ֈ$ZmPnpCB{I}CA4ϱ"52Vpw募?JAi7cF,daG;ؙ{)x^Jc~8#3`Y'n w\_1R5UI`/> Tt{Hc]psqT|iŠZDR4h6g[ZEX芰x)߬mg\<}TT7&=m3qA\Ra9|8v0 lt#(busqЏJ˔{A[DLD A!5 aX["Ԕ7D`PWGcTO},(*x$`!]Ta ,SF7a[ߗn5 =-\2x,}z6xoH qԌ͞rq|Rx5/! 0;/YFnE`f+EDXhհ0G3-6hο,?Qj' p=?/boUu?{ռ|xaec)SkEQ Zq_~{3__4vɋ}Y㣛,[t#1@`7L[ R8JzD1bkAY 醒a  La(,P; [lpk4I`FG>~@#\qzF,0\|0`i҂((*ݏ&AsBysv@cH trX.fm0u<·U,`1+!H?_O̚N{Eۜ7RWaۚ8\BZTǛCؖ\$HA~(*)Et[aAW! n^lL=bHMˑD|_z{lmyns߲e>Pu"e*yl \CN MupssG=PS: _pkP/ e!͘ӐsNr^2 )"vI9Ns}dd Ė߈ir=;Z:z&ay-ãC$%a']sp)lz@_nNm^AûT7!h8ۡHNݟg%"E|VB%gŹE]8ҒR$l< qKӸrl_s/8jPHqAԌtz.Hq_^2Q3eI(S+Iъ  63]hH. l3׽"hҋ{:=XV[U9 ί=<e` Q-`E?929\W vutjE _|>~1 0q1l=Fv5IvqNvr l&O&Mв]wIW_ qHfe!(D_I4.)+u5몁~t 2`0Пp=%=ŗ|-U~"?АgpI|' h2Q̝9G'G5GX p9&9Y@~A֩ՙF@ᩰoCVءHn^Y'Q)"ͅ$jɈjmu ?fmjp@?>>=!1<~cX+O6@-h%{- ryd4rmsFl{{ ~ǂ<<3vmG{<߰:I#"_y?]*@Rcpxks(Ik]Ϥ~<.)]c·}z$.kҌ&;D5i/]±qCY˧H9M< ##X' V'KK+|q$y\"8[o)Wk1s<ܼu '<kۂCڣKX8.\_X\D/|n%DY>_~ |sVn~*/$@+¡ZNmhCYzVJ:jV+cmh[#)ԗx|T*2`]%m믶E'&4/ [#e͛ll+WC> ;_bn6F>@)5U'cʧBtj.uPUkdr0"[,ddPVdvN\)%'{ߺQ˗ f tԍ{.9t3w&W.)˥E0otk= kɋCN~8鉲;0T9r<'ISy~,܁0ȥ6^[wUD,u a9޼ۡCv,?ag;nsN=6:FIݑ(|:@UѸ [0@7_)իrl14XV=7npNHrk\B"2b Zw.+0 >b+]4>i9yp$nJI0H@Ť L#!Y_}{[1VR'=WI Y۴g \ Nb*ŗ^ɋ:.ۗ<Ĕ11eLg+EzDTy!A4$V'Ir/0Hڱ8%dK}0>OrN?R礆o50h:+s=;j;qz"J\<3KRo/4y8apu9+RJF;(WtҜJ Ҕϵ? ĶW^8[2?`¦$*(l_;1`7jF ~-|vnF(9|ɹIW|8^F?3.M|XrxQ0|1Z)/1?vQh"y7T{ќٮ/9s5i w%˄g|ww|A@ ^X KRr|.2g#2lM%:=>QW=.-@2|l zuGpH{f!NLଭ06s<,?!l[!Oe?&  !57%ŅżJ 2.A>doc|4v@ݚܮܴx_Tyl:I?Xո[m'% CؾrE T3j /o5$ި&9Z+ϰ:IM|x 0Pg0X…!%$lĨ*UiH7%sT=.&29*@H7.vƾEITpp3./0I8ULRyP~%LHˠwΌDEJS·۰ >H]+\( 0rg 0Ak%l#98/4L4R+ν̮y-C%_o]qdכ#Xn.˧&ʗ="){c`DJfC $۔#yU+VsSJmp*sKǁ>br |G˹If]_aǵ:EkFV䛣==:eS/n_WqK˺n~Y} Y ցY4> m\VnCkA,As{gcEYهo<8VUd=C787Sq'N//}JjPmr E)KgpKIZ㮳 H0rC}RwY W(ӧ*oH}W2KVpX|'?eO nyasz\\s\n 3q`Jwf}?+=FYy&[\0>Q:&ܖ1Q3iö!v>Z%R<ס]hnE&vt HֲO\!-rwq6jpTL6 j:F r 2XjTVe (!}[uF?,1%!]ovU!$ /הf.=1̜ә fgA#! g^q4L }ڱYr+ˆ{Ps0hBUJ#Z@Mؽ!vv`t]۴_υ1osڇM><٘Am5Rp(% NNp{ $o52;pjl3^jB.Rd;u'F\kGlct5KamΜtwi *Ga+ߪa:Gw}s÷VKyh 7rH+D@~V+^"$qj8cFv1_ӦNEa߾_5cΉV.,f^ZNf6A]Oԩ - s2w14nIΥU| b jLl"x:XQ[ئdW0-bA<~uY͍OsLj~&n[m,]S Z>8=в17BDvla X((us44N5n"/:|4vQ4K&bk3E9=`%xMa>uӿnF=nGie Xjx9pwuwuWZhyd/D~lel,/*6ŗ:{к\Q[ɾc?W^l3,IL/|63'iQgfܘoYrϱ/h[Vi.Jmņ436|j֑l'K>? y荂 @)' =@<>^)LG1{=`Di6n/? `lf`[hrNQat8=GcWd%]ypCbDk9na}NWAY˯aGspU]];/􆛛TOPP_~ s\z,_ֱZ7t›S 6_פ4;ֲO\$s~a ZN|cֲO^m524X|zd,Xz$~Zmb1qUͼ`P&ÅK#ir)3y^dۂdkfYLd57G~uԌRj4䂦ɳ+û/_nypRMVC)vaSN)GdmImx89Zskz~MOb6[RiAY0 _w+ ?w_Z*|G-{o֟%߈d+@CNc!O,ªh߱z==w 1AvQ6|4vK0k4g4Z٢^1K/sSk'/a#jH {m0'ό9a Faʧf{w$=ًލiWgz`nڏ# Ŭ ݘ Lg>bVo~uo%]Dk3`).mX YtQ=NOIJC z\31싦%)-XM+|A>ZtG)'$߂R#\ΛNnQsZ,so5k"-76Ş\bZxi8::c0!_3Oנ8R1dQėoGJh,nQFI"M/],Oj;\l GcWL #]ZG1޼*~ioШsù=JHc(Pv(¹MQͪ0YG\cK+vanV\9=hWWpB}\S^o"sgX&Z\žAWe/ՙ5bU=X b#ԥҢ:"z"Y YWxz8 /_,fy^hεـyw%4e! w~zܙKpyAI_4)׮!>miiDx;thx]',o]hT7G{MߋĀQOMG7 l0ވ:_l>S\"7sċ/Z 5 Zv?@-}G|YMp 0cvX70"ňWL:g)ヒ^#vfܽYӧałOC]{(H6)Y7K D 淋cxOׅ$._yoqiE?J8adGljUK( .n\Cxo-Nm#Űos.n(Pfk,-C Ts,_-(|e5a'#fJV| 7+Ӑ)`/uq|:_.z^yz % 37f_sw(/ܘ'{5A%ܖ˓Mƈ}"?vٯoܽSyѯûѡC;Ԯ%I а@  -N`p4%wc~zZ <׀Ũx> $83M/o;so`+'u';7:5zӮh b<7;FA Ҿ'SC  >[iمXW)Mş- @e=`a]Kk)h0@^|x`͸4B6Yki9>Gv]7Ltׂ&nAVRmb-XyHQ%y|d@ܥzW|]MҀ"S:HN+ Y;ܺr=yEw73σyX-ZTEp0O6tx$dv~EprX7~PA /UTrK]4B0V [%jrcAb`Jݱ BΈ7 )Y!tESVMP׆c]ťΎvm0I 5Ჩo|p, }sh_K)g)E(ʡoBuYҴyxyl| 㶷Ô p2/i;HDOi8D_4@"p!\Lߢ~{,|Xk=2FW.Mpժ5 TǹΣDziZvya#X>ּxK,/MEZR# eXi ƅÏp{ ~RU*PɆ̬D1[|j(8Aﯛh>-V#:rd5bE3?/H:A6=aeynSJ"$RI"ׂT-nY}),@qgA@V"nfdVcn}4ٺD=nqHԴL/`.1t1D͈9psqDAQ)Rrnv{|~P]UB4[⑐(bׄ/ts@l@Ei+ WŗX%IŁX,~Ehսv4mٹ6ژI3W[o:ʖPZZ{S7ɫ_n>Ϊn'VWKudĭ8C͜'|#֮cyDk_CpH{5z ėpˉԄϫA պ{!$L<z\bΙFBçEa3 H U'ع (}_71VA+f#+{[i9|$tHp]½`&0kB74$zy[[V۳<7^u5xd"yN:k'ϝRw7G,c^f5VZw$T,SXҍJdQ.:;t9y\cgR L~m6Px97m憐;Nė,BDXlupb_ o 6׹Ө_O8[ ˫:z=+"֩?AV,'V0_P>Yع:!htK@ ppH{VmkIԯ/`jXWѺɍ3wnNpmGZyac4* 8|t&\;2}NhD g/  vASԁFه8߾yn.lVϴns"Do52]3o:Wc<'sމw.Eܟ;doӖ~* m:PyvL~=-)_Q+wkZYϱթ)DoH}WNօfgw;{l1>2'֯a [=?9\c遠ֱ滛/IfT$/S%ms)XabRӺCfxָ0`٪V"hnBo?| ֭2N&v.W=kQpȭ+%H `bm@=C7߰_ɡVro52CiԴRO%R(st ÷wcc`!w*J:F.Gd[{2M6wZ`FMC+hDmMܞʾXſ!݇{o['diw= kw2O"4]Eee(6,%ga|ߖ ȋxuӿB̈XZ44 b'/ Mhȹ$A bΠw@/Iܼ頍ܼI6 f9)H`o#T?dFM!xȹd-+۴JznXhs}m5L'z>6hvG{91[|*읣Gzy`ؚ|~Ho;y] -&t^8d17D{toz[q0Hc`d} __.Gr b!wv=M[er*B"eYo,V-@ ϦY&&L/vY o`d21 0qAML,_64egd/qAM MaL4/V\:;.r.Im?+'t+_YsTsWcՑ[P<7"&{&(y(׿)??Qxʿy_>}{_W%gn̍٘jusguv/?bPꐤ**Bz)4i͛`-/Z%p0ޅK|:u{)^U^'-E@gQt΢{\RC:")۴lȔMO4l͟ɥt)ɀ / z.Mx\X!d7|W qak4@xlΝ;)^UqB@x7  kGlh\(,4#Fn9J;-܀98(BiU JK9N X\tWI զ XY]msF0\g#ن;ü*vJ .9i&̲\0;T0..fΈ\?3]sru!^xrَ?"t(}9oQ^OpSG6~OHN!u>y`oS߭BWf^5c}/L t_-0p"璃طmjf0ߦ۔_YPy۔_!5ǦrYj.e5&;$O-Բoqrv 7j> 5j]4iᇹO9i/bܻ}KlT:FyI (LK>k :OhW\o ʸ>&aw Y,|s *p! Gy_.3zv-̍- ܱ̔&}Ɉ/}b7e#t7{.S|> -::!<ƅ I+گM\]TA5qpy맍.\VtiVM-o-6Q&׳sÏ%N;vB0o~ۓ|.^q9UfX>'z?~\~_n50q /@͖-wKئXrKr@,Z5nˋQiVBa4%aaq W>G8`y7=<cVB~q?T;{'ľ]B`%hۜ1jiϺڜns~Cje8ـZ&g"QU4HC"(m XrNٝv@ˉS}lςS&)Mq.TI.(~pQQn(ʆ+vh {g';s|5UaN9'!kmC@sQV`_r5Ҡ%MOqD@^оž{J=a׎Q+Ǩ^u 4Ϻzt4q^Rs*-VwA\T<錓Ř^d$G_DI:}ևKpnw8ٙz&D+.qX@޵J'ncCf8t[Zr'sK qVb54 Z=>Üc}3vI s{aW1jS9w3 |\S唥c%8nVvˏlwq'UV5;(q{''1r;IeUn-ÚϰƊPݼ?ˆ>Lq^_| Ws>]/ߎ}OꌎvVܮd\>h:[*nk=xEC2l($?!0=(/ƃE%)Ӌoya~N5mOf5p FpHI'EY MG<^[^o(RH?͏ӟihy|v|)jDȒDhYv "K>ۮDdg"r,LVn^%yٮOK\Q DA%c[\2Qƒ NyB[?QRᄯSFbLZ~gxF'EaD&8ٕtV{^:xmjoE*JaB/q^ۇRǑq%ߋG= C FhFÏ]|ara G># Ӌvh]WMO\\6inmVES:&=E%s.K{ ;){:w!AXjQ X K~I{ؿOv1Q,ݟi.ʁ+[ɻqo-~޺Оq\b\<Ȭh.  @,Q~}U#y&/E)n@,6`nPY>-\x?,?l-z,<ק˓ a|xڋ~rZDi;ι?$_]M!KQN/v2ĊW O`ǟ uۡ-?vHr_̙u͟{&2Dڠd4  >'e%/RL|ۛViCdW `Ǩ?hvoKhs7t59!5R<%^YF4 l)Ï6T%zւm Ke#y]Q?90((|L~V0LAO'"[T}jt.z` ?%og//d_҂BMj4kl\v1zԯWpqم8Γr7o u f:d Cd39έVMmwQ:"Ξo߱ 0!'&K}zcF_kyÙ5{6ba? (cd;#ϼ?DL#gbOl5edX#!lj٠?[0DĝRjG=/#5%?~}zw[2׷~M{DYLHb/V#mELd޾A-o&Ofpq>OCۘ2ϝGiA!P3é̃K g^X{.q \zB9+ڤ D ?+P &㽀rr `2+KO(g^1\zB9+h.70m~OSc :|U}*4΢}mt-ןןגpL7HP@DX8xw 1@o0"?-hx n{cO"^&^x\(e9_oڀ^媕q2>1r37f b~[)Ke0xG]hUjՈyc^<mXx]-x-վ4]kp3F ,cbj|=YL/v7#q{(}G2_?_A-'E%˩ݖ%m2X.W ?%w%l悷/$l?0\d;jNKي3ObIYUYc Tgc%c0o3wSpXfhPPI$GBVczCe-`@e ?EppC>4Υ(@?܂ |mv-@57;V% xV<fx8pf]!X??糧r\#MG)'C%b fq{-ov׶|_S}Aet#?"/ZNHɱXD3ϝ57afSJ~W])0 ~ 5j ๠ϣE?FcN,U9wQ=~w0$UYsL0olMmܮߔRP7;Gh7Ϳ&'_)nx?OM|GNr 97#5_O) jHB&aECX/;X-xAkdܘFFˍAkdܘFFˍAkdҘ4Z)᫲ @(DPC2@o50[ҁ+e(򋂰eX$& ~W Fzg_lp\94& R!ȹdXo&Ö%ֱ?Ylc?1e^AppuE)٭VMծ7Z;PI LJ09|UAcXAol+Hmn~Sb ;G؄ߔXA¿&'& x?OǾ.;?/|UncupsI\(gyXrjQTը8>n4$U~nPI2M0v7lW)Rć"eH=ןMCgًKeym,w2}Fc"Rf6G6qW !@5B\0'ڜ`dkY;|?mm5DY==$˟%j#+Nc5lhWlmz\RN=ilmo|מj,$.Aj,ő{B'VV M jM?+;8}acik]}uh..Aܫ?tB}ן+<ySr_?vY}T_Ft{4IZ ]GV:.*p M4[Us=r~-VMԳ_U7>b~-V$X5GV_UcC/BK0m>?៶oC&~K.A-}~B' M@6z)[끋zV_IM?b"=|j L?BikOdlʾ>GVeN裛 %Pa+ėWa+ėWa+ėWa+ėWa+ėWak5Qak5Qak5*±i>MSqN=f 4/$<&;f~=O}5kyҨsd^:zL7kDm 䯗 d <@|76_Slh2_)  qcN=kښ7>&{:3}&ل?Kʽ6Gq>#?İ:v`%eLA3F i)hF3ԳF`k)hF3DI5)hF3{&ElhZw|j05\!sYb'ڌ {4fX#+ڌ0JUn~ĆinDnrW+z&O"bWgYp,-"c _g,"•}}L3prT?6TCҿP,A ZލyG?Zį("2ii;= |[K2 /s߀Aah^lH.()졉ۤ6i,߀ n'仃n O O }otċ-wGG{4o-A`rg4ؿ^ښ[ΎԢ&~n1A?;ZЮU3޵^奁y-jnjޟ~vf w}A~vAܟ[W!^LgR]E5w73w"2 Ei+bJECm$0gt?9(Rtzut{Es5{\ K(9ӝY.4g},) 7<91&BHУ3tzzں{.޵оU3ԫ wxT ~2 ,gMAAֻ(/ DEo(e.@Y1;zb@*-A,%t4Vгtpv-^a銅}\]ΩAсXF?..Y_4'ԚE aNY_htAq@֬/ZfupjhӺSk-pvt횉9*+'DIKRaxp\4? "{ĞdZq KOhȔ1qyijW^>Ŋi˽p &.? "{~{~[_\^;@-? " v;7YHV2(=kb89r71T hϐj`ðT+A?CbTTx1 ˢXY='XVy@G{U )p&t-_v w"o76f~q/jeEb,%`Zq\7fIJ|Ib>1r9 eqv"\bYqx*VIJ|I(g, KYV1\_(TM WKwGKɩV7 û^l/ ;4+|Q/}_u넼V{An$[B{U iB|kU@d0. Q~Rle ,O?g/Q_Q+wb(-@ڃ{;H])A2JZH]) @ˬ(@ zL[?o.@"Jt/G X* db޲lY|!6rJ1K,m<ʋ #AL\Lt09+X _,arVZolUAYjϠ%lH k V?H$vCסU$vCסU$vCסUD?i9Dr*pX1r5bqƹw^ٸyg>Gz\@qpƍ/ ->%D?Gz0sc @?ع:* Q"r#=Cqpt@5p=>Gz0sh5WTZkrQTYs$ 20"+ʑK6y/y0$WgԢ3ذ:y(Vr cyey=/FZ[߸SoHvtrvF]c5wkRE^q).ΖvǪH^=<*^UX.&J 7xm|":09I 7;62GphELzFWGum*stMaS$Y/wъ$녗pgwi_e`breOc! l>Rzw_g]Bu鮋_`]zzʰtaK=(ZaE+_/}?4&xLq`-u/N塵1)<6:ŗTژ_zд,hX>҄lEY_izbW"jO`]Gtu d^]¿7>Qf>d^+ǥ'S ʽBiX*j"lK&–/[*j"lh2:pxR̛az%|U)yGU==RIB-Q튅zPŊz*KQ. B i@z!g-?Ξ9g_>s'yfBr8^)$'ثJN WR]P"O^tcʿ/_C 8^~;/˗&O7_  0[R -k4ƲFѤ:D|,k4MCDzFcY;G/<_:#EZ;Ft _:CP|t^ώ. ~9פ賧ʏP18פ賧agaYι&5D=DP!iġX0q(qK wAo4pNP~`p;I2?.sb|2M.>='prv13E?eHojG OaGZ:'TCKHO? 18'~F&.‰sW$R57wXe;E .Ԛ[Oģk'n/Sk KP[X۹O7qm1vSQՈʪFJHO? ɇG{ ŠZV RV@z DiA'F򿾂}󴠎- O O` AG0O {OӋ8~ZPG(.4 uUWZoY*4?|';agPPth mႬE/۟'ë=Gr擝肉Cf)4j4j5`ˡ>ͅxuH>_ף+f?DtLm0E#;eզ} =ܯC:XQmޮvE(`GuDg_O<&&'sIK44Enɉ%I.4tΥtySJ-ɋqvTйZ|^i0B:O_mO6Bz_282 RIKVĵۼn"Is ꋸּD(K5KcBVcU|pGET{7 csQv9vqx 0}0~K]=2;#= gIGNcn2bϕ2x?]VĔ_ԂCH?t)e׽Vʕ+Ј׽W/a|Vodb߼'{i5VLmPiiOO޺|pb 霶#GΝPSX'/d9:'Lҋ~Zx9Mε(]7剑8ozDϾ򍆾7 pb_kni;_,^-g_+^~hg~ި}m@i;v?(H<1iߚ$[ӞCxƱ/[< Kd|"cxx=I2lޫ$q^P/Oߝ1S) uYyT@Vb+Ƶ]$)5NiPꌒˌZ*aB2u]fxY%O2_q]bڠ8H]WAYA U%ҧ*񽵆ZpgG֚2T< ( /m _a$-F O#G ^g$-]f2tDl7#]l#b&$.݌tIxȑ7㫃pz > !pNP0>> K/㻃pӅ9xpNTך0^b׽T_uY/%vև2ƎcĮ+j!9]Kz}.g<IհtAx:_1> m_P0ġ!kY#c&U_;5l+{פU&U kR$aj=PGk񖥊'[(-^6n՜[(-j3JMZ(-D=|?}j⻮-ٳ]C'Z(-Wޛ?[ij:i1h-K&w9@Qc)d|Ae7xP%iʴÌr<~E :ڡkRQ#}@D-Sg NXY MX(8z(bh]=|+SEϠQƺFQ~~m[Y ].bQ%It/ t~:ڃn?AaOG{P :P{Ё/=rn&70 ]EcI;w}LȄШ.?,E@zw|)gk{t/lmtpuD2,^x:uymu OqW^X繱Q!cD:^Xy!.?i}uZ)& '&GtMX^ھy2.w?Ϸ݄[w4iFJs[xm7ao?kԴ'2j Km7ao?kc]c ֊F>w7?v#.x/`z0 +jm7am?⪵MÛ{I^"f^R p97{" Iw/fM޽8|KS.p)}_w(0"OĤaYHMvg!)-p^ 2V> hh ! Bjk3ᷣW͈n0|&<+éoD`rGVѢpKo~ ۭ#fOU AG*_rM#Ox ]|;{ a. `K<6b>=L杽$s]lwLjUQyʴAG*lFX~[WgLb͖l;6fHf3x&/.[oKqGBngө"E Ce`!3Bd~^vZ:٨N~fޤՒ}>dN'FA ? uI4i }+l;y.I|نWjb{P~^/"FXgچ5{O!.4 B~f^6XriI1/E-7)5(S|v 0)xT憎 ɋqAaRt MZ+_Hm4¤ S\iIэ/])dpd;iIэ/27q8 t;~\kHsg_qAv!1:O ;˳/񛪽L_=)+" ?F'`}CI9oܻEA+W?4 QYFaa9Ov}<{S)}0wϰ|330Ly ;';S>a=k6i #1\8aW.f\v^k730: .;\FmpyEl02M2d=RX>ί^N^2}N {(Kuwd* /QШ.ϹM^2M _p N"Z9|VA$U_kW_oއֽ'Ӵe'o%DY|{4Uq>/?.xoϮ§gٟt"to<=KdcD_ƪwO:wܗ#Ls? ;vtY"#JGR|s|_7H024LjyN]|JcwհAp|G/@m-wA-/AKmȀ,r?2 $\ "/7xUۓRIVvƵĵ 5 CG)nY SLݲR:O7_K1i/ kubҖ_I{f|)_<S/W˧_!~HŖ5okTlinQ Ӎ?q8ŵHouj⡸H7oT#(v?$Hⷣķ?4%uܕqI7C^uuiO'o!'NW^ƺ/_=@1G3\YlYo^5}ex/OAךx\G1vYv#-(8ho.GNy]j?9'IuT'HJe4uT#b;/0?_W_`~b W |vq1o +H1b'!/PY|h}'E;CJO_{RՌ#mmđh֢}B_2(v~qr~wB$'|9\]y޲G@)%HCGs6/Vr?B(ɢud@7yG-Yt(բS?uAѿJ'ahX2֐NsK/0XxIrcR/)Ye)6/aI|ƗKK5hFX_%E3’R/)JN_Q,3Ug$Xm746ُbu!,委 pVJ^B8YJ^tM2ߺN9rMJ^B8YIUXxZe]'Kg67H[ɖjR3UЫjJ˪+-`a$l#R/V H7{V _e#ʗk|Y_=|Ɨu(_e'h,n>%Ѳ%8[:/̞_@x =I52{j|-d$MK ]5VFFyWM_)?ݝ2EoȟQ./)ڽpU{Ci s %&ڽ}+tOץӞY 'KW߾9WAۥF?Ēx ]`uD0T xi*۱,CʽJ3^xkn{Zۻ7;X|^8C!"/1<pqnW9F{T8. ~K?m@DЫ}kP:c l m3(:͟E"]I hI^.X0q(vc!"Q4yy 4bfUW;Z"]U_l'>C1o %CY-詐,{lbHfdp_0 $?D:5s/j+F,m5jqFc|WTxGo7r1!pjgx39iE38%I#pp Ñ[%iӣ1xsB}?”na/;@ݍmNOK(O/O$5>i}7K(Ok}>?a{#iOrK(O򚟦==~]#)8KY%GqpǓ3pM#_B,KI{.q1Ws DhME7eUcӍpAR Sυ;B7MsstnN:7(p[t", 3FXU|jxѯt<$wq=spJxXt4V-̷%..-}dk?V+'~dO:i~dKnDEB@F@?x\6f5ЖH ;&hIW^>3jJ qrƄ1҃c{_ p F85n'ػ& gW"{פ 蜹56`Bפ[ڌpFo=16߄z8(W /ѳUX@j{4wvoNFR%鞤.* ;~sQ`J7,8W$ǘl6fi@o5T)P67e KsJҧ3(EWmDxzT_7I( x5}q'OqO,uX算eur\[́`v acLjJ k[K3ZMi!u¾o‹tn7 eiL<b·"E +e\[:~"wngWg| Ƶw_FH90g<Ƶ﯃X"GnߎSu@{qҨ֓>OX+@pj.6?v=R+=QXaaCߩt}-.<^Ae-wDHW.l_v=sWD{+(mNzf_ P Jfk0E]kjT)|Ш?2ޏQl3 P($4$:RYO$4Ո}>/|![o91a{4-'9Ą jN-|pQ乺J?gL\Q) N>{D6|`@ظo~F+igHȸo~F+igHȸY,T2A曟9\1 3F=O af>waS|\ W2 3:^(S0T(y{.ެ?ٞW`lcxr2a{#^*\䭻F1T^SalcxralcxrBƔw$R#^<1;G#WqA8;v{#b̟Pf6p֞h\1נ͸'w_\+ kf\(xK4u.+^jxs>r~ٲXxEs?ș>#:A]3˖u.+:tzNG/[ֹ>88Ù_ZiȮssҤ{A9jhi5'\dzގ뙔}{2Dפm8=p:"{ tDl1؆cN˰7Eў R(3}AE{/Hٛh){S홾 eR>nR4IWSJ~jO)ęW,&#T}'μRvU"̀_\V۴ y/䧔8#?dw_<5\l']?/۟nth6C4qqaiʰ4 nR:>"u@CK/6mΝ$6m|G&tؼ Btؼ Ew jK[v)i}bK[Ζֽg~rʋ" O޺.=EH/Ȯ!BRZp ڐx_tMci\?W;JmS$o*wpG8iUSSwQmi\IN4JWw#&55)&kW% a2Ӡ%OJ R$欝=ؑ GR{bǣ >s~"t/&׌8Yٞp:Pj5FK>tJkW:N[ {\QC5W=v+O]@3064RiƆFT?S/s9J{m5sw8dO.b4О@ m8]ӷK@j\brkA{ QC+G')v8T=^+?0sb2bg߄sp6r ⛨L9?*0.O{&=>l&qӳl,9ւ48L qu5مScY K,U?ϭ'WmvJy'}B.//~;坍kBiºyz4pc&jsc&5{4y.FnSlvF0vc\O O2x mԜF`j_c\OyB(QqM^>]`J,v_NKkB ȯrT*<(PHҽR4~+j?FyPj?نOx7:)JhX{XҽRO݁tʃ%_x\B2ʃz y9ď/i\5k\ރY֐w QZO8뎬BASaim!uwcp~ouGBaq4:E{n|m%Zgkqs$ڧ.s>S;g;smj>KԿ*jLr'1>.ASкxl>7p5g$BM=xbs?ރ'&1#[=xbs?ރ'&1#[=xbs?ރ'&1#]S]92zM_iR4~+0OgImCӼ<w:uHچmG}'0E8"RjbkU Yea|uT4ZxG&೜';_62]k\Me~cx;/xxAڜDk^ٲvV,wvv_RN.K);b|IY;E|G/)kh/.}yIi>ݏ GG^.K;{W|mYsaY]͏~O'=ot yRF'=ot yRF'=ot yR^r~oP!(ǀ8^M`R2W֯3CG`H[_:]ʯ9Q8΢ +Ot$?`0'WXr̸O) 79tDП;{CG` Y_{(֢ KÃƓj@4uX-/]=@S}+Oƞz^ ky2?m^}{ )+X'HhS zwo LCG͕ҏ>tD_dNl4OOx}TdN6b|Ql}֢ԭ6=K^tM[^$~?A~vS =C?\ۯNFOas5lB}DxMsX$"c*s[/1kUfgd3watcuFF#3n2`d wH׳'3zwQcpwia~y0 Ck3\!.15ymŐ'K ¢b8gVeƶMӡ_\ѣ~DWFG[.1֟kUdeaCX-Fb(_݌ Ea>3Pnt$9 "bc-ym5Rf!\E==\JG#K Ww=5K^* 7\ۯέ[>!O :In(^,rWozٶns/X?k ˮQxus5z;?k=YC}e )CAN^tM?iu/AHה thZ꺃ʟ8o'rCSӽRnܰl9&V K/᫭YW~ YnMLݯiym;}Խkw(@8?FURۥnH/4?@!acP'-QN s-(l¿ Ҩ̃F$Y;cӫA_5\}E-$5_(FB3Xҿ:,w9×*j7djU{To:Tj&#FD?y==KU//-G~fJ;3By߮}ϲf7w¾ÙZPvJC};Wح~kwMoG3DB:T?Qbπ휗fC7E I5hҾҢk yhln;?zb?:섯'K3$/i68 DEJh|)\#|/-!&Ɨd#L*?9,]of9KJ?0{I^Nqhd4¢bׯ!~@pbHsAvGp@k(+*pOqtV0[ G(7',?ʿ0?]{[>:&GvUq ㈈(tlvek?hctڿ_8t'6:&G}妢<ױ ELO"v~v6qXD Bu䷧~w32F_hs^*#g3tC:J_R.)/f|InY$ϻ8?$^ƔM,%/fTvwNߑ9uA|YWx!+g+G,?c=T]rDeEg| S?MmWH)?ە,GT|ç=J^.:n+;U[emgȐ(̿Mirv>\vQ$$e%Tz߄agNF=@Ϊg'c˱Uw<-0w6^('2=0h4VtwW1l_Z,O~U6čEN=cf62`30>?ϟtہa4AK$jkT|{s=p"qpX!;}{2ːkRL p "w+tOj \pBc{Im:ߡ-ua+#^a\p8 fMĨb+iYՍ4pȌM݊jBD<@-1UoVܬBSS4]It %t&?53<:AkhjD]qr ?}'Δ?P1T<ژ|10 n> <@HcXO,2?-?~LOT4K|@lt;sġ(C7x!qN}-<>=%@|I#gl|g-55@B?]'W746` 5"w 0')IqE,x_I`UֈT68#aY3\V?hhkm-\Wgܗ`4pzx^=cp&LH7hj-x;]ө{%e8&36: mx wS^nE-qUHWS3gdt$*F *]j)K881Үߺ`dvv $Nq;|v.0JSk3@$ݓܿ9'-x*eY(*oK~N0UUjƭl1SVH+5/0MㄆL8 ǮCN_sa|@ @{W ۚ08v}EcE|7.@3ĂhڌP.tăJk4lvFC=mۙ|6.Goe|ȍI#c1%/\G9ȴ1&S-_ *4WR/qi I>4834sK2Ѻge|/p<ȴ#c)Jiwh]A=ź_Ǟ~y _pr%\2K{{g@j–);}-iY \ʏaxo|#MmH? CS`Y<p̸GbP1k;r ĈhvHBI8 CX0q(㗋(#דq$8$>0YRhz;ˈS'\.c|gH$\N%. ϙ6c4T~ {5qhMՋP1mz ? ςډ=Q#cYՕdSarp8aD9. ;>3wr׆~ۣ Ҁ1%Uj\(͂">6 p۝8-7^c S"~j4LM|.ZgL]Ffu,Wڈ6wL# 4!~Na>ifLa4`T=nU F78ř1[{oDžhlkywkjcopp?Iq[u|n+Nd|f.ZEqa쌦% OD}Nv_nCy0кgpӴ.ǧ/ǐ69;}%t-LiHC ąv3ۙ]@(y |ndIw?:_J7kh>vP1> -.Tj'/;IQ(zGJQ(;[2~VoТ{s`2 Wyy/Kl?ꆥ߳ JT3ƪ K6b4⫮}U_R5=@P%Z={/9GAqboowY: T/mΝU- Н*!nbsr[|tn\쥳Y|.&WG1W XĜ* }R+٣AD߹ Yq$Ld߼9 kx?a{?M{ÿh?}Lbgu,9|fTY9PPQA*K=,yDch3& h$M-=|"#=ԣ+6K֚x#S7yAORXvz5pX߹zOOQSXD' E[O{14A۪SgrP],%cxEnN&mkWUhw_9u]"v>mG7O%;ӷ!Iėt![vU/6$) # دkFzmHI՟H֘_u(1Zl(vlE.6ex=sQ*P*8Uy0k;\e:N*C~ 7Q7ބRwµW$W%e!(wz K+Kκ53cxrNڦy-. 2~JJ;X4q掺oz`\g䎢-҉siѳ1`7k>FF뿕2/۬}NBWD6^A2m4\"rT*(>Ш.) yԬvl+]jx$.~)7HCjIztFs;OL.şL%$p߉3qyWr)4T~ ^Mx7~zg ZfqW9zħ_1=qgwܭG|ZLgk?ϤzMvqTkW47†ϙg8*T cy'G/vP>9z!Fn>~&?̟1z@#)r ƖGV$J Wݳ2{lQdoE[jLth;8Htaߏ+1h< T+w+]PAnN ɶClEs5jn.϶7-[4.xЈ#Fjnil•Xu*y:~ ޸yݻ±-2tCP*a6;S*MLmĢ⋹{ung9`K,VנͲƀ%nst8o D15us; Z ChX'j[RuMV$Jy@0x.:hi5H11B"7I${-`:_/[|stܹ_|slr~ ҕ}ݎD @J0nC5$?TI*Fgt9ۑ-8q;#M042`hx` H-m+ZzCuZ\0O~-  y]С#ϭt[m+k|`ºfRR䭻\5tLPS_XUSTס.xxU7p`Ze?;{lԆf7JȎeSm-ДSm-̾5፡Re6{,omiCmy#jc9Y)ǻsmcK+aliN.s;\JΕS(/ƲFcYUuG#\\ Vz~+;fym4ӹ``dutĂj>LDi!޺`ɴދ`575r#y%Ѡ`)S\49C Kޞ?C/? u)M%?мUKTp KhTX%OEw7qcWZ' <\ 7%ō{Q*_6x/xlθpI [voed/fH1jkuƹVgW>f;?,w|wJh~Qm0W`zmkK \HIF/MSЪX_M4"|W9mh&%uܽ]MV4Mo罇n\bsRmޣ=l^` #s; 9(-bDt96 g[uz-9/X.gq;>释81bt_[¾,?gA=uð:i'=Z%Op_ Z(/r0 ܁PXtĆs\#ע&$snB=fC;_w`~~)Sƌ!ƾmv)Z@%~5*kg|i|e cPjysWV|s֏PD=%'0 K,*z2|qN|#4sp(J?#7.x;+H=sϱv~nj|D}+2_ħ~GCo?D;AX:"h)g_ ܌/-tDp ={5ܜ: ;kb't9745.~!8Utc/@Y :1^-gCfO8qZ8Ԏ+.B+o8[҇#0. 80 {v7Ljo|V 2/ĠkaU[oϕXT8E*]Iko1.+1pS)7eN{‚CGau?9|mAKaﱨ?ٓ}ߥSsm." mOhU63;u%oPSbMIDATԔ4Rgv^)۝^VTj[W77˳ -r=;R?{JPEW6RiDm#C&EH_/_^x+&9xp~D 'oG#vgK|-~T54:K`+_Yg@EM=| BkW_Bim=knݕ₏ !{bߥ_~D7~)6lk2 oB' S0nQU+&NȼFՃXCXh7:vMR>/$P^1tlL?TF+2zX5P(ْu#MA|"2Oht%n$Pߩ%Un/~,Z?]b,yD>oGG#n#;7۟ftupO[ ED'劽lje==[?B"jmd~ztlĠ]%ԫS&βǐWz)/7w(?;{^)EF nmЫ5/fĥ-cB[x=x9;~v*8u<_yoFsnqvK+ZbV1h %c 1G`?`bqk* z4x;^@1hwDW9Zp|s|ulGcQWη+?o,RdhmSPJL wlDUnĞuZN:^~cK#>35f(ӹ"-P@$n'߆~NSp\N/ޒᚬ~z`f4&|@ߗUPnFjpm7Z9f8!XQ{_ `*WQPeŜ1O2!/@$ϢJW\02A` H\'s^*Zj3PQg+%7*Qrؒ>८i|>Y Uz;6Yl;s_ o'1OL,x2{T;X^m\Zc^@2vW[+7>bC; |aGIN@wꀯ3?Wa%Jnnꀭ vIQ%x'lpV|_g6a-@UΪZPS%E&j|*6wgS|W'WQKWkI2E5t(`';C88Ɨz!cC|rkOYҶ!##8ƗC3m|p/[qlvY|*[9Ɨ-թF߹O2ɓ2Ei<ϱ*e|kt9ڡj;ƫBƗ!1hx| ^`H'b0dsY c~fW5l6n5 1XqQn%Q Py r̶Zjkv6Y|1KɈ#jJӦ)WۑbbƗT NdƯ4;_e=ɉ%wH}/=O mOƧE>tf"K珿.:`/U䶩A6Bӝ!V;hoČ-c񢴴G{?]Շ83_Re>(yqw칒.#Ts[ i<9O\LmdIߣr7%?8"bE_4ܪlEcJbO@T\}CƢO$6u=]4jvnu흈>ȩҝunWDw3th~\Xt:ϫLj|y$4ժ²,Hё/$D'өȗGa^E/h޷Ϯ3:]?|Tяr8~e]ێU99\?RtYp,ɑ FƗ w˃T|r@VO5lxQ4% |6w㒌2[7ϣW +@QL IQŇH2le!ܯ' +? .s&GS& )(Wv ~]D]_ąEE15ws9cmH{Zc{]wc@_67W5QsKnjw41eAy}<:䧶JKO~ mD3> 6&/4Ҡ]xSd˅o0 av3l2DMFg_~'=Zj0aQ=fX'{ (h\,cms:R@4d!?p+f>l>-0*@yA?fΗ QݜQIDDrŪ̞B}^vl~LR=E.AxaӛZ'6mŮh \q7̢!}i|X@glm3} nUVu0n*"h6}qHZ] `h09%°*0-$[D{XaJEo5Uu/:'Hh#N #߂S%^p<;'\9+G/$}YpDixe"4#fCfw!ixFu?5p& 7+KĨ^p{#(x:339~0sO?7x Z1 ؒ/)t@dh'CfMN3+ŧi8 /Z7 Q ~WP1ⓩ-- DMI?ELŰ<: 摡0 fIOO?'Ə'K % %<У[ LN察Wר9" $LJGRWwfN{#O_="`cKf'7FrG/q*"0^"{^hho(#KF\e| tWս(#KFVV)H9/{m0OO9SGU:-cDLo24P|Q{?.CFSNƘax|n+GCk#wó8)7rr#W0Ftpz#G ;K#;KR+^=GOO˥o/¢,Ic _H mYZs>}Afr||H.^[g!4?,BbxI:(&n.'4TgIj㡳UJ&d7K*cD,Us~ ~wZj8bt}dp+_jLw/@3H=&4 ƈX݈:̹̹'xJ{t,U֩?n7螺k}=Z6X4,wu?7m%/Ao3sv\yy8q&xsBz0}1w4 擇LrtS!y V%Y\OgxXQno5d0@5]Fּ"u\ SF'Rޙ?:J 뱁ZݫFo6H4/*"?aKY\#, 0$ܓ{Vٓs$ݝW4!O|)hhEucxF tdtP\}[(]qwrܑ'^m8bBu jS3։$h8~i޲F1~Hƣ1$xɴ.:YǺ0=g`?/[`#᪆ >휕uQA<9aa̠C95u]"։Lunx@FөPbI99Q]|:w~nf~)C-&I]^=^QJ#R3W [OC_~ mԙv_@+Rn>_K! tr6ІD R;HŌ_%#En*)q+o@tPoxO/>4eF`/'t Et Ng:2_K[Y{03ʟS_7xy1K7@(JUqY(0*JztUiwC1=rCtG7hr.}" 7t`NsG٨p+4|3|rI}]~R[w4fW3E\se.tZ44oUWE86i8^ox f4JqlۨN<m@E2} 7׆_ x;Uk@U^aio3}ev5*Mwn[L_-ő|Tvn16ߴʙ2ZHs!z>rrnjiio3}e5: sUR~G3 =슽UR~gLZ_=E}}DxbZpV/H^D[hօ_j {BYp܎^'ע?&gf\Ssev?ӿ{97O'Re.KV['<{\W?E3^I!pͪCc~Ƴ{%`2$`2BӢNz= {UV#tZ5^UYobv^6I id44C挻O,9q 紩h`ϩ{&QNпh}]}-&7O 5;q&v}n F̈́:*n3{U-Q P7w(W*J?w8opr'_\zHk{;\% mn#⭂_J{ l4{PpV GHA=|Xk\n*L؀r7=Հe~ `BL8u bͫ :O ~XNDHZ_YѵpGvƯ=C&[ybh3Z5j޾+FTax&{.88PFIw4imFsFT69E &Fr-ȭp~8DC:z/kCĞu1)3=] @0fJ *ڜ!65w 8~nQ!87^9=ȚP6Rww)GǪ6@]Q,N\I^yW77+_sv6|ہ^6 `KFG#{/\Cӭb]ȹ~}{>waaN-npOD@\0l ҞFE9f|㶑up; HUbNDU3I{Ի]q;訝ďUFt-ŞbEV_Cؑ@3}(ęO!W.`;KҺ3ތ xYz>`I0s=MF|bEf$0A)퍴9fH=Xzg|'=(b!7~w {0eettRJV.TH㪳Y!I Q *TݸSe"F~`J##)ҸjJ @@_Y?ʵJV.o(Ҹ4DGW&5QOG3`Z;۸jC;i|Z&SP[~q%.pu,kQZjPWr/'TfޣbsHx _5kQZzQ&dbɇ~WB; ^Z~zx[p۽t>_uZkpqsePu^2B'~&gηtG@ꌖYКԃ~e^woji|>a#{>u|y:IrbvޞM]v/P' ǒb#h}$-q{HyR| p&4{|='&ݫ2w"S4uRG~ĄcիU)@ VWX.lԃ/;Iڧ"x 454S/PƈHHo??E0phml^ht]xzaՖ\|P]]O,&eS?̭J>|fBU۩>*@xe@[vxiv o\ٟVN^!70$G`&^T?_={4?6xh9̄OwR܋D5("Vo8r#X̑qyrf%"c Wߥ.or#Fٷ.c_x _ΗC6?%1?8KvrhvYDyWGg%jӨv1_O}gi!z?Ի֝>!7Z)՝@ҧVYM%BSf4ĈځC^eq^NNRdק>}ϳF'}kiL1~Yy%.lZ&M77gQm.Ǐ}o^_>yuoo/ȟU17+9 \%09@!Y˶dTvK*bbo1i| {d_>rRMuPkg\6":_G7נV8#`SvOxqFUqRTWY+?r㻯޶+ tȥ3^;kK 8?b*,  _P2g48ksN}?3/Վk+cn4䧔0]zR8 kZ-@ֆ Ǣ_u,aO-I aXn%:$7geD3/A;N>#Tň?~VΉ~R=s-|ʿ6tD#jM3b}abe4^Y ~B|j֌;U+1|aN|*b=~O/vYj]瞦Vu>ɧkT~PxysRЂ.MƅセJ63w~HcW"[*%#^mLS?oڦnݝ1]?!:ՔG6{oۮxO9y7igkoB?{~ ZӧTrV9_u;`˦ X | ifT {/ekooFD/fZ,[]~JV)t7^"vqlz }X7/<h6ȇՠ)(Wi8&^_ ^ O'Ю!/QBi^ g' B]yBkt ](^] j:ab򓆳#?^BSRIH~)-6*i 9w= =wpz^5-j{,'h>|^VX k ?d rKZϴ ̛ ob+#neb|z</ҺO~J`ܸqS$|7n\Xz_浫W+}8u=/?ىG|l]| L&ۿ7n g]iࡁ ذT_$GlnۿK_ٞ B^Kll6>^ i^<[1 +o\ZQ;e o17碮E5uprss?;,r⯼C:ǿΏ#嗿I҃o:2G ?zk3^33xǎ^ڌ +O_;ߘu~ן6Mu8t%:Χ7V-OL;1ՏOpOcƊQ/{Q"a~vǤ(Y\y4s9Z]89Ytd,_{`cGoއ9HEuxgiO[ڏ=1ƪE|pES^Ϙ1"~)*; ҶI>^yP˿SEgObV#^[`x|z;z|x ; |)<;a!4_AG1b7#7?Z CNߑ6%t*<1b|8“7ߛ3N F^: ;ޝ/:<߽{-vyl+W?;[fE2bGqvٕh-v;\?Cw!3"MZfPY`ΤXfP+̆ЙďsYd9~WgjQ/~:C2f$| ?$8kR~bWL9'cn:>7L+]䝯*'0xd7J6-پMP U5piLe.S V$97OiU5߮o\}Rx=w..۾W*?߭X^U&\|Z3?+_@xU5wlKc2wq;P{kQ]ex;cpwwyQ[H}w|F͕M5Ho]߰h(wiۢʮ7_NNNNB __(4,;kXeՋ?>'/Z}.aqvEng.e\fPMvPގ?Q>|hW뿣wus|2|g:N.._R;~| ":x=y/0gZ=ƝcəGѵgHv-3eUWXͫZ j"GT^uv{T+ K0\R .ZQwToM?jQ[ /)T+ hqה [c1dP$6/lv/3>p`Hv` okRk\`Ia *bXrquݻ̀w&S /34^Ҧʌ`bieջտQs $czWHB$'x'Hvﴶp)^hΟDhEw ~.c3MF)oDNs 9|s?|| :- lĹfd״o-?_ov„Z X?%93\*4Pi0ly#2k E\UJ4̨l1|E3nմi+(J#;wҠC]MmX!wQ~SP׈K5qt Oiqc`o%zzCF]f#R;}ziUFwO[DΖV"Y+OHjf|It :~O_%WNNϓ3 &%eLݮ7`uj"|*:,+Exjvo~X?L~y~B}T;%p=6ztᤓC ZN04Òy f?(#rnxF!Ժ]u'W ziE:?Pp ~:>)wld[Z_WH;kdߨ&a 0#)י~rBg.`wY(Y~-2`O$ֿ^NfAZ7`G*Gue/(*WxFZwF+~~V@t<-kXRxcRR&BuI'2Rsȣ=,x5, Es2iQO!%w"dO/FUG)+%r+ٰȈ/o_du7wY{9M ɉ%1sLzvER* 委|wҼ58V8DHɋm0z9*\2s=D*B^7hDۉViy9*KJ(?NZJ)B`q꺃~8y6WU`2杀oW: PaCAF1ܐuF /VAu8 Sq {NICah5[)_>ܸefxȐV+wQFyߛ_/N)Gbklj+(:MAS1HHNEw.v W c(_0O3|!E݂,&K{gWຼx"~k~ W!b'8~}WxKq{"2ϸ ƪep村TĄGt;#qG3/&A$ƏrJ Y)+k4xrLO$E1ރ=`Д2zn%FCcygl FHb8 =+q@jmHf±3ç՜5g~qyLd7v*P }~.[ X>خpl)QW'FgC'tZ tay2dd *S6>Sq>J: onUSK._GlFZAij2(o!Y>Ro5aw7m|_,^}>gvjyrЩ(*n@ImU?tmV|>CCJJc;>74!~~XPl~Ʉ?qrNfCz3sʐ#h<@DU~m~[0F7'5QfTN./:d27s1,v|4K7g/]8?e).W_#+]XHV\ WG.ޙX(#T tO;]C~_ao"t\d bz4zAyQyA]YW?.Ǿw#d\1|ީCuyupτ؅0q:-i}5gu8Y%Y _W/o7]=~O_x:_q *s%oܓXϹbi,8=?R^OJsrӑ|`~1aGb;us5hsbngƪEpF =e?11.f/sޙ4BZfPY^OItZ CjOփ*Lh'?Z2+)$]PGSYE8WMO6Θ`o-\PzɌ|"ׅ_)EC?#i}uMG,wOX^ΝěF}Gs ›T!aѝxӏ*dP2o~6DOY[%s`j8i%#0bGEt97i7Ah}ȶCl0D8µshGkӺF1]9o[8pgRoh#ߪz *[b]%tPjΔ7.ǦbY c/O%Z~g|g Je])DBg^w?{ԏέ^wA_yʌus:t0#)-]?srYt'آB@k1=Q!,GdߡIƅzQ\Q/|im)~B|Dkai4rլ?y|e Y0)C@63l/LsP|| X>hɳE⫴9̪lB߹VX.^w6.wwdŭPݭl؞!Q&Q]#%MTxb`i-)]iua;kg2ʶ:>->VU@R%&H?`əkZ͂gոfP|v#vf!e4QTߤ|Jx)5BʪOr,cVeK3omnf?Ews{?}ng_JOe][ inV`A?j~W }%26|gMsDG<=z^+8y X{v+<_W+_"pЅ$cmHOXb߼-1oU a~ymi:N޺KӴ-]f.ZIx) * O*>h^)+sQgc]b/`Qt# pBA{g_sVGeuWѩYyIe=9i@|V17gpFt(#c٫C0h>@ ;q&. /> hs OpJb$vcznv= *47wP1J)0MxZz^'LєLJe/:]dX1" =a[ 'OOQrX,'^kwG) =Y,lN;5+GD$?*}dzأn fT^#^ߨQvb9A%K/4µ?i2nPcGr#\%E#N75*\ },Q;O },Q^idZm^tK`P}ۣW#g!B槔G~b*Ͽ>.br]#]RiazJlC\ďykDB؆fµuCs`jPUNBy.*j'_Vh4@9k ^~C Qa/F^}ptO1S }~4zb$򯙈fYH>Hr ?ɏ"w >~Q7,\&??ï(dLwqu^;#-K/ r߼%l3ebe.f_qgď gx;ɏ2e͉?1˹/\&&Gv`dw:%_)TG:q!p2 K?,?r`Bgw8hmjZ'gh]\;` 2t ]c?y˯Rc*:g]=޽6ZڠhQ9ʏHaO89":{#ާwOZf|zmȪ 終{F?oaLG^ L#; z?+/@Ŷb؆CF>l!%ƭiǛgFXnk?#Z'f||;2=@SW*ն miU#ىu`PE*OFZʇeyVtBd.Ipr{oW+0#ݫG@Pxw˓Cе|LqߘNB`3cҭ]mUڅ3xh`>o=40 _`GHMBy?w7``֥п! ղA~ʯpHg%riDt~bՏ!yt˺>S~WW=|Ho`Ԧ%W1 ueO3hiL#o~G1m{8vG:ˤ(Ȃ a,{p'$ e|/?|QEM~ߢАZ x޿£k;> 7'@{{/,Y}ƴ/v~_Z?nl_L/Y YDr"a/c Y#929YԻ\syH5?V~+r%;`q\cqIt[vڛQnzZm\L)W` Rp-ʵk7x~6H1|\ZQ1BY~5Fg~?eՠYsnVdPWHiҞH(Cݼ|7QU+Z(i.~DwmEWeUm )[T2p KyU~W:'*?7bt&aɚ5]+ Sl[3ȥkۋ6yeY3pw֌/\u]Oo@r]he.cl[3Ϧ{PQ` <Ʒ)}:5WFr^,Jqv>k`}ACӅ9En}]HRvvRhǜ/wْ zr-%X~^z.hEBZ'1:P_gc< !CY5KJ-|kƗTK][֌/"M|kƗ=&5K^qm[֌/)[g{n/.)QWYPm-gE<$#ƹ%7FM P_6&5UoX(M`?P)cĻS]rϩӛ \9/ʹvzܬbٌ+A6'˩ݼxW| N[kke0l;L o0m ?7VI$?C3mnB?kN\)|OsliNxS9E4+'xss\koqncwݜ|AăNoM 3'ѭhJ_͚To5 Cֹ7#*]5Ϭpʩp|ӨPR| |*QB,|OQB]SxZJ{"˯UATP|vj*Bl[sʲ"74@ζʮw0;Z{pE럠O@=83* #`k!@>!P)9:K_GfعK_X~އrB&}l/GLJP_vqHRmt8řG76':8aM@ú2ev)u>w^D[ \r^ڷ/L؁7qAz@0\O-Ds(_ H(ĭ . WyO@vĻA!{ÍppcSn-wp* rq6pY\b!|C j.v,N]lP`)|#P^„8=r>=،=g3ʻu΂q(4󎌳{7Ey %rg{Ad`u]P _S*-~$}cwZ*WFQޡy% <. 8:@UFK[v Jx8ZWz/#spDUp26µ>ܮ5Zu肗^ Nϙx|%O>K+7L?Fm H8xpoy y<<͒ <=FUԨ\ý˧x@fIOAѡKW1ҥQу86kթ9&!N((xz_vĄ#gCR+$ r3a[I0ඩ-g5MxG;p}'ƍ@JvB'K$Xͻe(T`ۉ-\;*!4g@Z] 1}aȣ,k6t#N]#g.3?䵲|-+,N7`4jPAK*sQ8Eį4bhC5ʭ@A.YZX6a +ONIK*HLUX{"j^/sNp/v SN}G0€?U6`O5ÁSf/xpg㳷fS}@6z{#(M emW}h @>wFg ZP-ރ=,dt݉jO5۸۲c$ բ pb>vsus@v+%('wsq3~JKsgpmw,%)&=_Oq 0Q<+-c,2B`­|iHY%߬DYH*n9%6yȃGsm^6a` Dh0;.I1tjt,Pq]n΀3J;/Up=^1&"[>Z@ktg-ѥ+"^h3r0fS#71D?.]Đb][b7/OǍIi] 9'V Vw°M}?iLͬ/Kz%ڰvS^4|OFx[8p4/:#\gO/c\o^9mڽMc\a/4]L>}!)UM_{ٸwe(lz!ߝ㻭l2R6Ӟ/Nڍ}\pnIՄc8?b^!#esue+~}Z);G)w7Gxο^]g,|rG-i_/Kd|3!n6]Qgot@񃦋j5<˼ӐSR(fsy%;(܅K{?pUY 5`Riq)/=9^M¼BT"_URU,lȯRI hhֶ3ωJMΈJǸotZJQb72=-DN7U@#q + U19ϐSP"ns=},?tw2P(PVaJe*4d5┮ozJ ʛsV:qbe{^2#Qc\> +oq81{EK)MxTs^#}'=Yրt"L`!wXZP`Z<^{ᓋ| /bgqiF{OI[wA_[Z+jZ%eq{5X0q #'rG ĿŊt;bhrw~\ G'K81|55~ǢNaSMbzV/:$wcY9ؾCYGqz-OJ_ed[1ӽl@yU:Y`i ~|lÙVj~,!gkrYGAS?.e}F@Uv{P9Q C 8i~t_ԁJ*3~=dt UƗ;r(şkJ ^TiB*ݹ* ;6SS6[\0:;;XWoQr"޵p{+.-_\{zuv9"ս3֛7}šz-*Bb gDyrOr5,* hCC뿱JѪ9cR^F&˙5*- Ys>y;=sy5 t;'$\\Ɨ׵!nus_p_:}L!n&/p_:. Cr_p_:?\FPj2e|YCf[j2e|ǾۺY=}iJFQ,9<!7}` th>~ ;{$e!ԳTaHn𚧫UT2 -%y0Onnk깮ہqʇ5o[oY0zK-6ŅgS+¿~SCOyA7|{(\NW˞(#ӝ|A7jhw.޵rHׅu$F+0{߯N17{V 췈7FEQ-a-< iT5= fC<ߡ}[0v!?PMy*i4L;Z}A=KM%^:;jVRbt*so*1m1b7)_M6sFә|wy-Os{t%\e!iק%-5Xt#cB-_,*::-,I`PUzVgW0ʯt ʟSuF_me&0I0p;|jio$Sq\|?F0f[Víϳ(OFn)1cf0~9u2 XtJ!|5R~h c Rͼ+ uׯ7֎*N*kxJHYr: /Yh:EC^hz}GY= C nW23t>ݳP#`VQ=m Ow~ #fw:n/}t`̽DxOx&E#GKTyZܯT z]tCPiuJVh6~ǩ{eA>zٺ*?ӑu7O(5c**GʖC+}i4V]rӖ'%RSPv*LEg_2Jg?ۣ|fԝM!8r>lG7%w/U?;bv;C ␘V]}BbH?>{Kr= ܉Ssߤ>${ߟo$}jZQPl5=@p?rL(ϧOM?nq?rN7ϼqh2T럕C|\dұ돔^o Ƶ3uik0|Zw,gLs=AjF_?kQYQs9xULD_gWԴUùcg9=L_?X sJ&`hO[%c(Y[LIL7Ԥh#?z,(\6*z5ퟫ F?$($TWeqvw0H\rZ7i)sPf2YFIHC \ZgcLq?)iOO'X~!ŕL>n_;Jxא-?5d=|e C֮P4~>$XH6ڢU5hyu<CN%RE ^Bw RA`W B˿?HNod./WP/.I]p \ƗJFF5/DC'he|%ƏͧHZ_F2}ƝXN{~gÿK֐C|L?u9 !a:?@^R_י^d.5D:fa:5>|wtO%Me5}ގz%?'ZZ ~ x,~z=c} EOgXxg،|Ɨy>t+=N_c4/p_6/@|0v RjGhg$5kŒgw;D ヸ Ecy 1Xck;0 ޑ@~'\1ehq q<&Pzw-VPNOi p5!B} LP uA vru^u }\-ou:LV\ݭ >_k|c(ʿ 01}Wh\ݭi!=%F)vFM:86|~>)hi99/:~Í@55L˟j 2_@,n>v 4ּYwjks`p#gcC9ʿƚb#n|7w7Ƨrd~DȺ0,x8O.o}dQ:sro査6f3@표ۨHۮʶ<;eX\wuǭG9V~?B2:ɥ\N^2=rd snC0 }\g_r> mؾ3aZoXe[sBǧwV4y]ӊlz|z)K.؆lj6d/u؆lmf6d SpaIˡvAOn>'?3%aIˡUEg%[D>0¤#xq"a;s7GƟ7Z 5w4Mw+B'U6|ĕ~|/J+WqOuuޘ E[_ABRPmt>>vr{afJ$r6L@#5RwN~=\ 7uep'cqZ,=d4m2 V5o+p2?>YoWӛO/W-&ͦ)N=67_xh!77lĪRb#S\ˊfqKa$Mb2\ U6ǂnɚnJ9[R<ƞnJ5wj?UUZB uue_RDt 2Mb{ K<0+ AQ \~u~6Gs .力aɆw ~WT_sUлܼCw%M*m 7'=z^i!_ /oEdXe)忰kX[ugv 1sCݱ*CLO˯2Ĕ`F!_m2i!CCV-}I|u${3J߭DbxOF!_™ߪUYid>0& x9uAo>EmM~E- box8"[Fd>EmM>=EՏ5"Z$21b򓒦!5#.c?dw_wD}Sf-[GxUNH+S}LW}yy+8,ٳŹ51Sw~]<wlbFo\w/31泏/wa'25FOT5J-(.Ì/̗!/o qsc|_Fr~Z o A-&5a tm.)" /}ov 1oÖv5w8-՛J~]Ld%6#뎝زs;Fƒd ڳ6wwlG,)KwVVyoy[Է_~o>bR\Oѫ##xb3G ۑg8s[?ޖQeWasLV,Aw|f݄SZxͥUנ䙠'.QCsbu ?G;J\uZmyaTaoĎ`n=,e_(jFZZ򶨖32꽃BNBbG0YM.Vz D-Iܸtzd5Jfɨg?I}= ,͟9{INzHu*vU*EժTPO \3 FCVW,A ^J2ZA*QZ.ptQUTA;82@crn*"w[p]*waTUEP6w;A'_8F *?YZu Jȇ .+?r7|Uۿ{JFQQVT.- x8 *? jJ!l_~PQYm?N.pu '/;vP7ԧQ@V5EܹX 7e,TyX^|!5k8mO:Hxs!ǭ;\DߞZ~!"(2/55ףTmtZG/Qz"ahoե$"n~v.5:C1NS7AevT9 +zccJE /1 amɬ(()օ  w`2b N=~ @ku`Nfl8S(qkA9~qilo) Z\Ź.uh^Zl[;6>zEu 3P"I[xH~Kׁ^Rt~Uar]0?^w\|}U~CpR!wc )Ueh[/xcw7t5Iӻ_00\|Z#gN+nbsJ3 KP!8R3j>d_0!F9r~f u:$n!_[C`899`PQ[v[a"_]Jş:MeziY[ZR!˜ 1Xqko |Cm/aNkT_ݭ(#@kT1ESGct 8fjg2_4uj|5NûDԔ)3bZnOP^#-j~#ğ:~&r 76H7N՛w":{ь< Fm@ֵU#lnҁNJ*s 鈑x4X-}#_wPUOJ{ .#ry@Lͫa+h6n>bXRC<:? hәٿ=܈8w)Űs?C þ``ڃX8/7ϥS21jJKk27gS_2֖dn|/2f[h;;5$s8mZ^ rr tx6%SuN viؤreY͊~lcĴ[d.p|b^ю%r?[]]q~z|u%q?Nx󙏎4Io!-|RG'/bt}7w3ya6ҽL\wv1FĶ,^7Vi:Q׍[n̴xMpV"8T^v|=g`e,ΩOsJkH[;m8g:߷|£ [Z~gtuOșG]ʗ_B4:iWBH8sTQz|=gϛ?!g38|hْ9X;u8gzcl;53)ilcxXp4EY$go7Vکñu0.^cw]|*h*s^TgLVi2uZRǝuߺ,6\C#rZe?VWj##TLG/{0\#Qѫx`V=#gb2cKErgExf6LG֤K7MJ)J+9,%GÏ8!/ͯ*Pe|Nk;LMO3p˟ۗfq5z&G? "FHR90k ΪL=@]q=8Cl3j'/]78 TKL)ylCM@ cKlz%GAW&omz6=zML ^^r`?d~ IYuDY(ѳ3wX/(\*T.FjL(۽}bEhJs|0v a-Q Gt)S#R3?b_D1;jʋ4¾S -n߻?třzE I#F>gXd!0OڿH^Fyxw@P]?~m_!p^(ٌRC._tHSW#=/F_ :Mn㵁k !-6;ٶ۵9]|gB>0M{;#o$>z 1r6KW^`l?Kz‡`}C%:DO! ђ_"* K&5mTɟcH0VU]<=]0f$~eU~.V@R?1$cbϙf=C~@uW6GHoOa{+Ӄ&Ք0TԦe^ަ85_y/ձCVF;\6iGڹ\{ncUE#@/xW6=vQn]4h:U>~EI#@/(+lō0++R FK>>Cf=AlFLتNҠ 3BY=Iw>6c#F_ ٜ_>"z0vn,?:ӶۄyܝE^BGgxO݈!AH"d#zlٗg޸s.׌Mk忚zTهuY|Ӎ@zv._v3qZ¶:{KvD^B/}±Y4~/n>iT=ˀ||(PhTJܡX~>}6zۜ)r> ӻ}q)'x@EʊC*x:# n8U$A^B[2beĂ~hcKD` uz/R|JߧUM—EVk _ $>0iUߐM; z}=j5m&ng@S^7^{N P=k{'WhkL׌;>A[NK~CRхX07g77_[?|1~ /t,1B[ykp+b-smX+` p7}K]y@~M^~YS6Y6^{ͣ;`S5+~b$ߔ|準mAg/:\yb|4\ˉ p7eiJ`d{Yf "j=N4*Ku'^J&H yvz:#[o|ba{&@Ή yna`4^)!1&JK(&EU_NoC.1?`ňx!ث@|4*T3ϣOHl*@gkp'_Zu JGz*%\ hRQmMpoxOU /%# ,w]C`>8a]/5\sa,7n;5N(nI6*h\0MnIw9u[]b/9Ti_(?רWCYt^w(aK fNF8Wy@4 *O(uOjE K,19@̎0fGG;`FA152u=r&:nNjj1;?$|zѩ7kx2-䉩E^ϡl*cmKLA ?H|0`/O/ DH}SIYsTɕNF26k@Aƹ &-h|BgxQPY4P'qqTYH<݄#"3E@ĄU,EեQwX|sbnwoS>@ӗGa|5c#o?"KD91N(uO9gpKM{Xjǩ~SW;X-:.9KD`íۣ[XF?}O_/qECWG?"֜QWgyw𷓣Xi%)I,@i W]Ū(' fǗV7 *c4QXA=+(2ޤҹqJ )#w(>4*%eC^34VE!cZ*n*22S769 F%oBl {V!V|\W:( Cihs8)qM'x莇V!Vyp] yDHRUFSPFn^&hnוv])2 ˚-p]kxn\OWMcB`/Dhԍ r7"Fe;y"fU&Ssxm~H [= \ED> %ֿ$BU*-DpPWWIϰ{5 _RB:pN;7V2(+ܪsc:pN6?Ui7wO>FG[ zg+`i ~5Y l~S_F kUX 3xtukͼevMS?\:Z7D6)wʱh8;X0z>[u^9}TcSFv|QK.ۗOS[ ,y_\b#8PX 6KyڐfZQmca`6BFV q7U~#oFVMp6Oj~~WW'q:7?.9gF󃒲xO|c/l=?BGHm? 65hƑ.[B$l m7&zBoyokv˦Es!m腑sRu'l iCigo|\҆|軧M|!mlr҆&V@iP({{{O|l"  yA$`-9y kn%5+?()Y?q5b#S(K!ډ}7AspW"G0b/v#6bG0b}yб uZp>]ܻ:׉]]5}43z@_׭̢N328#8N3CdEcREmC)>0LG-!WװҺ DK"iOpZש/QUP(&?Fx}8n{ԇ6Ok'ˆCԩ˿wȄDjz(sA~C4 +QԦߤ+VWY "qJʔ7*d'}VYR'PRRn1`ł kTǎ[#iT'-pt[:E}tcTth' ,֩"qa<~-EMEǴg@Q)AdC?~D,#϶?cϽk5 /AnahS٩Tn!-آq!A%xn߷owtOH|Gc7ix cgE@)#|cu oH!Y&-l@ΎC'8Eƨ0P;>{pxZL$[L:τzEGWaxovnxk:ܼ.Ռ>ɀ;񒺍q d08.Vjޜosx ֯.WT ZV~Y,w\mx9=1^]s+`rh}1ykܔiXB<_}J֏ۣ_Li1alݒai*K(dLioM{)G~ײ KSь-G(עV9PW[%1Net>ZAKq|KSt~PR?nt't øѝ0|KKStrIJ 1m8MbxB_GүJ %]ia8dڂ%-*W[C;4+YCEKZ_;>Lkʟ;yЗ~;p.;V4~Dbe6 $gf#Wإ=Xv;bbN_yTa.rSafn$*{Ri{73yqu#?Onxia6`XZu;S_?:Pi~iCuO&b|ܡSTW\N(;;tLƝϨ(?X ]bwur ۦO|/g f7\wlE;#38;Z]Gw$Mi_2pFd+og@vAJ}M܈V`vؕmiәX__ {;b-޷h~`b?I6[ kpP`9eK"bד;Zg9[4K$Nܖרó6;b|m0wNEo:w#m+@cX8,ؒoس2iXx$HOE5|G(~8md#Nd\kK;ahLotL}$rSG`ԷE-ٍ\%i$Cag4C"Ҫ ~~8INSG7?c[s/m< y\SMpo:0~݋޽Уo?Ab/"?s"vmzC^ΉKޑw}|܌{O[PVZKFْj$)U[3ܒc pT%`ۅeupИoݧSSBs%\jHuAz'F@u7wA9W5zBRE$Z r$F \'h?4cPǶ(TwW~U>pme4&Cy+$n)h?gPR14Ǘp2q GHס~}Z?Sg ϙuӟ!ATg@zgiHK2 G^& Ķ=S.$/ib 0]xGf0~GΝ"?ObA!(BwQ (~ϧ QQat%#2j\oM{tz$fW"cRsS,(k$oz\|O+a'>leg-+~ %Bwg-{>U.?THH΅X翊Kh5ޅ^֊0_RɊX4̚9N >nL2LbW[ cSjD(k^lfN O@ʖCh7\Ǽ 7$u=M`>~)hӧ:_ .uޢk)%p PLtl!]K/ƃtØg鸾Sj_CFcŇ|^MA'ټ!,= ,T Uz8y2'i<F+_\b$f?`U+lyL:-I:E d_-i!3[Z=~_Z,d6^ܑuUx6s|OGױlijv:#SH˥\3PCS #<ÈCEs~M_'Ohso؋ !3po'}|A =bt2zvao/Go^?w_C " v 7"!},IU"oLxɉx*J_gƿ&7'.2bnA9}|g|B^ir6(Ta>nw;R<>KK@O8˟MeQG&YED=MYr8BTx|&C]6\fdR'wIӮ rm.SqKW\?;]nٽcv% ,;_R4F\9=7g|ytӚXr{ۼ~_0VgEkl<)Ms~F&Giʹ UU 2lU,yyƿr?50M9T+QPDO 0w[qevoO-=5f|@: E6x9?47,:zթ,|ta]!\QLT]?-߷ԨZ wi!_uzitKӓי-fw:"U 4g#{~6v`zZ23g#9Jr?Ӈ8LX;%죨V?LX/tw!?sƮ1+|KSB/U-Y-!-0dvp?YJtȱ /0&2ʯy6k X=+w2|/yߛ _m_5`:~A71 {K=-2:d}\*=m-2am(_V|[]jj4f+/ iIuTW*ήYP ]E#BoWO[ehq 3{:u:|?'*}J-zӎKRkڋo9P?˳y\;BdFR+56kyRlUm^{1V]Y^̕SeU)kE2<՗}~/ׯ~\Jۄy[y 䈗TI>Tc=ۿG}؁:-cA⏿/'9Rjݲ8&~k/Ujݢ 6d[RkK}YkMKs z{w >/u/&yǵG h^c^cߟކOoK 1Z=#M۹cW';T*;J}F:`P@䒽ШOp #MԨ]TVA7wuaWR{L* 3em:W[(< C:y%ێ~$h95vpe xrD@[CLϬ?ؾ$oe)ʡ&|}Q! Ɇ%[ ơ!2>C_{IL!AoJp;  &-)(7_禗ݞYP~ܺΒoJp;  Xs?g}Ҩk%wXo:0,2$`J;xaz}_PkG~wX4b3a:)vXzQny5:0ku:d /)?ĩ#f3kO7"Skvbs`_[Wgs-}Q?5)<⏁io_Шpr#B,#ym 5c隱V=?ɈYpچ&g_"{ ;78j%}~<' ݷȉsy Ϳ_wm~k#O'd)>"MFn(y-F#@YnBt>ND<`}"~m _lߟ @琞e66ԏË<kr)ˌIRCgM)F2_qͼ/l7eT8?#s|mTT\Sd?mrEQWI~dy(p'+Ư1;<78\" '%`R @aW%12;:hyP5{sn;Q`ɹ8l^VatEYXQ-rzɎX=kXv>!;8tCCL1k<-zMj *%όJ}KP>ehQ60q1dn](-S/$|WgOo?f[}] $sr-2s~0Fm9\; :"QCײO$/(@;ۧn{A8?#گOm,6㷛V~6Bga:MCa*>Jt?|eK x߸c~flwr;I}փ<-~H#(vtY&0p|۱X ]c,9;1RV^(BiE1Ktz28# %*J ZZ?uZ-97 _"SRTTm]2qJ gKt N5f3 ?-#,Rht:1iQYO %X:H~no|Z$Ng|Z"OU~NK}ns|j Ō1~>N⒟'MB%i hYxTjx3Gq,S \(?ܻ(9I)~Sy*^mHE9iP)*iq%y(a[7%ܡ%Lۛț['̞0%SZ {hfA2wc?gbo^?Q]c5D n q.w5^/VՄπyOe& (;c|sKA&yY~g'fdVۿտz+[?2WJ/h*>g&sƁ%5AE` Fr[{^8D~B*PZNDǸ1e4u]uk":ia/7_Pof7/`%e:OH-Z~ߗ<|8:Y_i,M̧o1"39L7|Jjb}IѫD퇯^Ti1oY WwҲ(od>ecP+1,;tHãf7+@x}M*m?|rd.vLxNU6_?gi}x3_1K,,7i y̝i:)ǜUcU |h AIuzQf i8bn/5xNtFL&!ΟcMMQ:(5_bbS_d2)Y?fVdgLm!ZAJ9gm-:@n|/ڢ!Xu-ݴy5ABPD&~k>htFjNq6]Kӻޜoth/Zǣvüns􎖌Z:V,/!A|".W0 u?.9]c!&%eQIO$C6F-}ڏ,O;\neܽ`@ <#!')~]|!'i\rU`e/>%n>a/&=zO}ɑVۅg<_qqÍzp$ ayH3/I_>_u׍߫:v0O7YzC?'7?Rl;O1pK ]\Sm_WR']>#,%rzCs#`-Fx\r`-F8()K0#`FxCVl6+}Vդͼ) MU0)i-oJa84ŤHnA/'%mnt4 }lL H4fpQ~8/_)Xbpʻx_ _"/%e.#,X#,s&eK'nʠ}­`I f8ѳofoy?Eʿe~bͶ=AJb<1nt'<7r(G-J|q􎯇+MEc,GoipUVw+Q=w8L$dV,Nc6gRSoʧsGױ{,r7S~O*Wwk\+Ww9XmH O"ȑrywyjYSԜ+jY3k\ޑ2l6st̽O%!/^Dۑ0n4s||SB˿|><@X6y[G=h 9%ࡪ 7̷|ݪkPuo!?/P;ld`ڗpM(NiUO 6ネps2O[,lhU/7'g?bFKG{ C*OMoIR@ˋ<= Ox憚vD,777xyz _Mq,rH$=uF?'\+mB|ky Fn Z_yH7BuqiF ZJ2 P;yO:pF G. ^4ˉ* kiu0KcY]A{2NcJ7!.LRct+l.H7"gs waR(I=/otT252ִ[j=:˂ZL|)8ךf4C|ȫ{Fu"v"p9OHc 2tt:A@(2aG:˛O.W5}"Lr]@C_./~2"}>V3 ZH5{f:]32a.6Νa\;#iA' m`\/:,f%ߨ9T K27Nc~vкM|s%|8i zPH hn4ɵVy}0q 1oNMǿ{S<(%]:e*:{cLGğžq}7|w:a4)X>ۮ+bZ:{8yp'94BEߺBJE';o JD{+>ƗfFXHQ75)ijATxY #,TmSmo{VNUM¥ϐx? c aHdFPQFS*b5_͇~ ˜YqF}6f6ե̔.} b` Z1)5y$ L*=ji5|@Ã@_Ohե!61}#PxI[Bj;D9 B*/_şŦS^8>_vvӣ&0 1%7uUړo ob7GxPǛWo0 ]կNCehgCވ82h'~X %z!5d)}~ZҾK=U5J|80$-`}b+6\`+Ǎ'>CX܇iS̛'nkZbw*myo#vfvT B7Ʒ_ ѯR ^ڏ)lyrĞtƵ`D\aJ9];{{+ϒa?Ժ ̵z]+?N;V#Օ`42O~j.gG}0gR%=~b\Gsh/8{b*K%̸tk)X|}|Tt5q79̎ZҞ̆m1"qC㶦]bS8\z99NOēm7_nk F9i|3Dl(G9\\oM_b[ib5(.DaM<8o|ILn’q놁!wDu񛆵¨l#,e[fwZ!Y*F l'#65 pIG߈c=عpM+boU.MC.%BLAKsuޒdMk\?HmKxgôT5"Lźb;0x4.d}OZPߝ-t-cHғv.Y$G(fNǩ87 7*fO78ӗKsh%'C{sQf]-;E+48v򞠼O2KYq(eJl8rIPSc?Vb( I{;8j?|!]&|ZRΏo\f3-W4IV3F ud!0hDO 6(O\eD(mS$mNU0D43 JfiWSɡIӸɫq3g T V5t l.1:deA>@J+IL2a +] 7wM#coWZui6cK1Ř&S̵$p/**׮|dZ>~SӲ5a6`qgiyre*߷O۾כðߝhL&,H/AN?ҟ^=B#ۘhs"1xX->{Sij̽DE%L2 yD–@ N L}cG=|iottkjLV^[cLk>Lj Gluvsg7ܽ<2 ^`]oW lNP ozn-:$yub<"N$ : 4OZ=PE%ڊߞP( ~p8Luh>j%.^G}v%rv  :Ӹw@[WatZQ:;Or)[ҏ_/axZ3}dpg|5h9[P}d{|)'O%:Wd3Q姏lNnp[ߑ3QG33Qԅ0nBGfOZ8H &Q2)Q.׼ :gG+0W_BڌCEUX.j@_r[CO38h$GwGS{3 Ufb{sXz3G@{JPrw, K\fB+|f}eU[NIbb? kQ>G;D ihNX7҉IG`PlIP+1 0uqL]-j}gw[W;H#),}v(4*Ww,_=. u"?%iRa?2SFែo^:F8SI@F@Y[n1Rn9;פ{&&nh/Й=rQ0(}/=)iLV'٣/UxˤͯY,H#,,O|ԭ- YLa =ǘ70/yl'`bPP`vuqإvjWĞ4-*TvQkYT7Dp"RP[l1.uZ>u1w$b|I;1PJk`0ڶm60G*5:#-V=t6ϒ|MWo90aQ[E+ͳ0V~)/s/|_נ^7WsS4S1 N\w u>OuT}K)hЕaUfx+1ko_QSD~(vL:M345 50FsOث4ϤRP\Q]+78<@`93VO),vwKTI#LY3FjjӾ1{P[\)~!]LBU{q[ۼXwGCu4,7M=d9_"w`'wDP0kMC׷c9'7ɷsiqe̵EӼH'.o0tw_;G{#Oqf04~W j9cr|{ &D5'~E:q#É%ZcNϙE:qe9d4J"U,.s_(f]'ŗl;#_#okz urFw;Lmdq !E||Si3?cQj& f]JCǟks]Vf*`~RrkN+gzU5*wy.>_^% !cFLR x1:t4 +? 벣ޱwW1r=2Ś>+M&~T5#9ְ߭s;]k2䣪-s\#ӏ[>]mo&X,^ h5}s=tMxG54ayν,wAnjLu*†5O6wU 'Dߡٌ~7Y(bZmrS/HK_;q#DZ.h(qZk ~_6+?mnU츣f2/tDqRŘaf̝ݵu(DR盧3~ȺK?-DcL0wV|}nȸ,~kh~9.~DT$ryxJy;T?>*HmṁGV}[??<DQmoH 8?ͫhV\mk@Mj?"=0 e8pOPNx_n]H~TC'Eſu;M/#i7^Fߊ;BηP0O.E\^ݴZ$(a1ѷ>yxt$ߗwFh9%RwR.)HrpN/?_Q9rg/bmq_oɑ۽?a:Y~4c.߲eCr֒<ܹko}#XZm >a?'#n7gC]i뽫Lڥ_>#89'l%p>&h~'=zG 4RtQ;Dd>% D{pDFyC*.?ۜ^D { eX]u?7|"߳V?~DEPv׽E3/?aV~.(h(? ?-!a9ThN1Cf/ZI[|_3*W-N0ڗSxd->[Z:53RmwН.0~^[fu'xoo9˺8K~]Č48qxw)^يV(~T?g&g(NȞ?-J{C ȹW?g&dN7drcZz+ 2 O h{ƻ)ﻵOg3 SF1;?cc\lY~o?7 [ڛ_:xM!ڢOvǓDO}՜BT[ƹ|󣃣26Wxݞxr'/Xi?zV$~BGNaC9jK-:+[87S,}F-]W6!䜧%M,S`He 0;ߥ.SFؙrƵhdh\sBMeqzƵ_-#W8dv<5bP. Olm~[׀(j;{Fz B;<5zF&CQ<\C[נjԻh/C[qe]?ßkQoړqԨBFtEYǬzRC_ޥmẄ8z?Wܺd;@9zUvUA/;M#Q"76V G.gS"X߃Oӣʬ"{&TF]8fy;h(ltA]]1__ eOa,3g3gGס:;e-[?ic3CmK|-jr8Y u)1=.^3~+_' GH [#/śvp{@@$seS;{Yß?{q?VPVPg 𩅷ANG{.vwA}koi*jJQp'!`=rHXqpV XP$tp1gԥ*PsuNZi3xG ^9YҶ Yɭf|3|H H6y>>$Hьf殟#||4|H5~^pLS7h_ /(/ClqL7kT\x(}3WW!OFm_WvuCGȺ $!MmIMm#dG+6}g,trDSYvAF8B}rb?2`?Zx޹ZqO(FºoDY`;&U oDmW 2v$](Ax~ -BqCh:PBDA(KHC5Ds ר,q|]4r x5+=nVnx.uǝĞTʑ1l;*++lCX|-nZ$mZ.ֱAK4Ϛ+P* 5nt';<P]T>(. ѵl@l8rV4Os[x _ $K(4}Ԑp8RӀ`puJAN"$*HA&gK㣍{ѭkWf!/q!yиχÛ.3#O-W}ZJpq;:g.="i}+D{;A!ƍ&㏝1Z/gTV3\:#X6%  }x]0tBhѱ PQI^qU.}뿉e]38fuj&j>9ȜX&p ~Lr1ơJ]4wu'džJʢ mgx7Q,)qi$7%뱞RuȎ?S$7%kⱂCBJa J iI1P<(.zcK(\ ⓝ)]rpE\r3į-ʣLwH=;2O5[gf u0:WGNz"' %e1ꇫ +_Fn~)#]HJ|jCyUxr~{P|lTRj/r%ڋ~>x [ %򮑫4dN%9ى7w3UTAIYF!}NZF1KD9QHs3z)m!Re!oGH2BPʻ#H$̀6 9^I>a; wvpp`iI& L'±]~?eY{^NbV/H]aNܑ,Ȣ#f,E,_kQeZE-_pkN#J-oQ[+|})Fw7\|4#Ʋ ad*8V'߂l?>*ߗ;Kȴyq~ǒ,I^1n+VK,#~"ٿpKZ j>cBOk*;󩂑_ Ŵg_%>F4TʑY:m'Dʑqu&, z]+ԩ|-j>0 Z:e|?a=1h|.m3N, hq;!n(AJG3kvu\:w7-9b=,œR|=ĥg)\y9hL_|5Lx= O.7;ܖyPэygבOĀ +n эygaw Tޞ i|7bF:QS=fhn|;ӋI(+Wޚ׼3s>yUC I O4%wMUm{le  AQP6"(*e)S R٣B٥AHӌ&iܑ}y~^}59ӓoI){1_R6C.^l2bzPYzj~~/^@&5݆k~IU]+6l^/KjbҹaO8M>e}O8.-3SeC*LA iTVFi\zrBjzrtrf>f>gx]h=[,BdD >bpՕ2R0zB; TvZ rjQm:kRtPؗԕ2J.-.lqɬ0ȢIqmqUaXˠss.ݡiI%`y"tHTZkxgi?mO!*59I]Xc|mWZmּšsLqJYO1-Qsi\?ESwp'+ 4l]K'ߏp74Z՝.xUܰ>B-s67yoऺ5N6NNLGeΆ fÞ=eJT:TھbrV淿΂1 ;2|%[/B![kbv5%߃!>*a \&~.`tզhT@O, <.~Q1>Q tEL(Qϱ돰{g|]W}⸱J'Fx5Rim-+f}p5!`y/y_#*m/iʵp_f V =\' c2PV'VӪuz-H6T|ښ{8dP7Ba1Hsa R| 1ǞIc@F{?V=\ꈋ֑307Tt9z/LE?;f7EFbtlst*-_^??h !Z|"Q^h!֛!@QԎTկӅts/\#fOA r-dnPf§qήܛӼ1t`[ \*$p5]nqs s@o\r-=ݐQTFj^e7Ib,׎xLhG|>Nrag$}&㇐׈%kTZ%/nou''?@J賫7Qip&/? ;'~'|9totu2{sW8G= N@bCVJN~ձ =MX=%'>2%s */I$7XXB9`]#fI?kl`!zm_&5kR ~) DY? riBA9)C' Pս6]GGbs/ 4/w^~ɫunT|g'y+$U3kku,7Pmp$խ>XtF=yӺG >XεU,fO^7]d\#%F<=y+Zȹ|\#%g/ӷO2v]i$ E{{ =yeXiwmX-4]TZSfYD"cF=f3 p,VN{{z#N%3¸VxU_.7ғm+JMEֶ"Ia64e>gNejjov YUfgPq'nWn384?J~6_~DϙlbwC*@X'A*fiw ~4s^aEߪ%qsDۋȚa{I;$^24;g>owWh;9X{1Kwa4l;WN[$!mv^an-]A((Ӡ{h=~$~Ȯ-CJ}zl9m,3`50l"M5ͤ%O/keQ/=\ke_yL72ûj|`JÜ{/Us-;YRϢ~JʵH ZjPM\ aNU~v;Ys%CCC}d+ >T/2{zju| +-,ʥn _l8\_EnNOje+͟pUÿ/UʂzqqY9In^^)(ȗ V=YRN|.Ӿ OSn7I8XVdȸ7Oi^7DEF<+N<t}2K$o ~UDi7_wypZ> 0U/EÈ ~bJ'q-a< mEU5Dٌ C@0`&z{y%ۣhC.V׏/%G2^ ʹ[Wuqd\r ǂ#4/;PS]?DC%9Ku@>*k0T< xL?a+ļ[D  mvd9& //xK>!陧s}oS\vwhu ;q/P]b]2_v.W0gb kO? vى~v_woo?Y~xݬֿۧSPW]a1d.܂H݂PΗ# qt9Ie5[Qٞj<e'xO+o͗5+zMCӮ( |o(~ZY%/ȕέ\M/Ym3~@ Y x :r]| YYYTٶ|gjn(p g϶ p~Y,~7Ŵߩhm|Ft|]o.>r"=#)|>]2='ãd%Kp4Q?3rxəOٛk?ډPaƏ v$s4.O|Kv/mvcMj!*z[W/n43)G7ك=H*$~g'+L@`i*2M,`8zq?g`£@=.DOWtoֶ">]"LU@0=ܽZ`m+^=$Wec+>]4I,vv0V); `?H,8Nh/ȏtj= @%ae!&K U&ȧvbxuһè`OEJ>|5m?e mŸ{P)/_,þ_oLz=}Tee}˒]Ӵ~pL O7WN~zqn㖌 O/w߇QU͚ ]x#myrٹ֨QadVim?n4"/!F4?U㷭xLjjӜc^n/S2RJ"~#ni*jvzMq c 2{TJt ŎeS%>}O[.SL@`:(=c %S~6jix+$}7.ߋ)r1ܽ@;ʿQ}ՋR?kD֐@S*EK#BaL'_b+5 uБH{ii8tD܃-s<@Γl9»ns7R?=.Z?C~n6~?in<|p9vs!omÔ{(omaYcsRFzF&e?_cػIDAT>`7 Ot) Q2 2|IVܻtk`L] 8O,8_ 3D?xWн}`‚bxF,?VQ$#ٜ 1{cz@/&ˈiߨJ'%͹@5{sQ?؟D|b@ֻOn]ß9],qEQ0KVˆC$_(ϷscLunt?ϥ`?fkƿ,Iăɉ(R?\0΍/o~*~1TuG^4w d)a?Zؿs +z Z-zBv*Ioi5i5ۣ+o^!.WC7`ؐx'n8D$ȑi4i4=rd?;ૡӨ1z:!UU1l`dw* r LVVEAS`K~]ۣk2Gjjѭ;2'٫'Ϝ':Z@yB\{u074nx/'3!D*y[GiH] ~&X.'3!!ݻXMC*v]i[o1**OzݭϰVt#.U?VA"=mj=>Qn"@#?B|ul74mNҗ"wUR?_?!ԫm oJql\mUtF\v W77a׮_pZ1v 7w(ܱkcEuo?{TN5Ͼ}PC=Q wٷNUرnpP|5n [ nnغu n O9۱};6) v 7w{`׮_%< kd~OVIoD8~n+d- \x{.sz{G0ſYgo~ֆ9]W[WSSPYX8gJފX+OIFeqQW[GeQq%nܞ#io%¬)c]@w&Lju]ֽ{4@s1fMP `V\%vHTK@U^TypR>= ;2O=sA=6C[5ͼ>'zn; d'% Io ̯`gbYfHK`^p~BZh >/~k-}x |~YXp~–zw~n0 '_/_.m8cv |IU;aLްV]@:_O8tpuw ET%U/ 1ɚ6c i&c^Sԏ%U턭g5[: ]NdbfcOBe'u4K\ex Yoql|.toM__jS ߝ7ְs''4OkhE)#Oq?/m$hg?nc~S^?,S','| sjLl|aA=ӹK,K>!"Dmk?b\eyġΑ Wn/ˏ_{KB?=~\b8q!bP>!}[gq+ժGYC#OrE[g^=֪~,8%7퍴ዞH1yb$ O( snAe[-u =o |RV} |`HȅtOB"/I-Wfqѹ[qK\t._ gΝkӼB_|*ЄIV/p-Rk3Ɋ!9&\+Nį=l׍9g8~usx+W͈PpޓN hI'NGFsotWCB|'חs]#m|Ρk!Ɠ҇9t ԍX2+.ư>!lb?VǮhgSmg?>1W\]=T?ѳ^p g{1= oY@-J"_Nސs/sFġͤT~ھLI5,ϗ4sp0Bk_^k/w+ۿX!Qd_,?/mU(M=+Yħt"_ȤVo|/uQ|f;+ZҞ|8ڒpW\B?h_Mj|bnO |,4?ؒoZ㓚m#<ͷ C[7|[<5\eiuGHX/]6XuH=54l@$n15S:or]''> 3F& zXq{Pi{z'u1Pk p.?ǵZKLGܖgzvGP6+UX@A[q++ F]X\j~n2BYbMpȗmksȦiE:ozોQ#X~^0=gWos:-z ,`? 1Xus*?Sn2Z31 =keGȜ]!CɬW\U!^Mf=_q0S)|;5HɟqyZ}{IqSU}WXțMoOkiA!"u[JԪC%PRu ae|&U*Y%;mV5~t_tv?y^ڹ5L=Xd-QuJU %n~vKLկM?.c]Ge&Gxc=O` S.Q?ms9(8Q+%)iuؖ5LmY?2n3<沷;qlعlKa%,O8iٶ4XdKJ+' hL+7V?_LC]>eノlxS 0#xL ȣg8p2ՠY^3}o;whTН.5Ёm!bOYOwt{ᕮ0gx |ĝ w|8|7F&^>)75#$̣yMIy~&EӉcrOC1K]q=0'o9끥m^g!)Bw/y'CfFO'͌N!ač?Mv#$s{x^r: u`(R"S#rl<3L5$q[+*9=##8RT$ E/LBY>Eķi%`9\ ~>T@Eq9hT>-:4+Q&=Ɖ ,ZcoՒcw簆~Z: c;vI=<=b( 4џK52~K?%߲\8{߳@F/]2{`c\׭ Q@x!iloAeWXY!wV8w72B&e51Fm46q|t nʚoӝW~.ܸC5TVk6oqKD+-;N2(ikq/\L@^aݟQrT{oS?tlLĽЯϥn?z"H\ ӱs>y O #,I,C+|)/0]}3}33OϹ*Cb}YngJdD >bpJ5%s)z! o+\OS!'ݫ+~QwyjrfmP9kTP)9w}d+(*ZwX]3Ѭwquad!YFYi-mPi$ӼY4bAXfX_'zI:gX|r(&%f/'Jϋk |_[}ջ|_[Y6tȲ-zx|q#ڜY+7P_]Al2u$N$87~nsf̦*>P~ϊOg>ns7̦3=CD;gXĵZrq/7.[1J>zf1#Lf.'k?)?L1dkzb9_l+E, |{m巟6|oޯv"ok֌|oVY S2XAS =Wd[,٬ "4^]mA ++vPCϤ'+,+>z&e(^x 5LDV3b Yt=,briE\Η35ai?cLkMlV6+54fּLkM ̴ բ!L˧q8w;'V_7>QMX^ljaÓ-A&Xe=9W^Qc~dFA/pH]WNrWg3zUsGja\IW^mיO4f[2^^pN)CBro2z^ I==,FN.9/A o= 4ʨn_//(bw`/B;c=^]|ڑ'fjkɖYETXA0 /tZDž_5dA^ž:FO+V.8m~gZy>GWGSyLռF3X-NVXM$=V oN|z=-ԴmNix^M"%3iۿq5cu){B~&snuu6H!lSdOxEvKmǨT܄t e]_}ұqڊT)8ň'J^\4U3)'AcнYgZ+ɞpB U/~#/ރ+|ެ~~b)'-j=o2""|'Cܟ|o=T=?cuנ2"oww ]Ze {U9w| CGPy#jGjkbՕ[vm<65-R}-Wػ'D`\NvW?xRu m|@3ohFI rsZ`!C@`Wg ?M]o\tFCS1EgW7u%17s^1hr"kW._`'| _`q0gDr@_ |Y/) ÜMj\^!6@J '/7귫 ?1=ZnVIe|Wy_?a5 "~er FOԬcq`}ENQw ?KR?K~C xjT)2,?}W!KusyDϏmй(@@hw"G$!i$$+VgW!sB3PpȚY+nnrFL;1 ?"`(HmR A?Wv֬LheI{P ~$m(\>tm@ )%g9Ruøѡrh́$EU(?իDǎ5Ѽzz!?ha>JU· *d=޻i܅!rSN*3R_!8Ǿv!pv B H._M!Vmj"1dKmf3(?A[8o@}D҄ƍmfcٷ}7k%_WZFnƒ7 k$E<<]ڄK1}(~w,Gl$0] @\q?Gt`*]q?Ԅ0lpS%h4`U4hh;pZL_o"tZb )_ S ,@L~Xf,<g*|ϷRxiP^8c\'_bO |}ClQ?]C7LjUnڔZ]d9={U0o|‹`5cVЖP b4c/_[VV9p@ t[= [/Jy}?]-]/GxiӘfLjzKAUÄG}G9k4l1fzݐ(z^kqgz\˟[jBs#> eewf!giw>_& =# <`0ϪXގz4so,6^(WZɷ:>~Nq<Ӓ0gmYo>{"X+g/-TU[d)4jՕ=0[[~pOܹKԋm o=9{i0mvn,9Mn 5^B:ܷBy {CМ)__mI#cX#"qpRňt%Pkm$M"P#_yW r;DC@*^~`FjքwTQ›>n;j6erj~cU15~'@0?9pc8مGT& IS Gaz~Mm[[@"[OPXCYt`y?iG38ᡐh5@a Uڑ,E1嫚[6}^'qƗGs7 R3xiNaN}G\͞־][ 9z=r|IWXM 9[N/7a$}w\ ca bx@B:s9R7FH>_97*b.^IQp=-Q>^O87~'{Ȭ>Gcܵ,Cp|{IJ\a`\+' KÈ,]p+s$!8w%'(~9U^N;<7q}6 x qd~9ZI{~&>^.?n@ޮCGH{avԿX-vΓGccBR^%5ņhV|0"e+}bz~&dX(}v'/z}<7s*IzVs_BƓ<[? { |r3aX-$DҧI9gV}oG7QgF=Ocx̫q|t%~d U6?ĖohJˏ>F͞VB+F>zy/Xz5o%1GWcVsە/U/哛ouj{'hY3Zch*NIn&El6GƽO1b{X{Q߽Ơ܌ |K4::]X=grKI.6|yfEX叉-+`Km8+D/"9 U%%Nоy,칊䭈\}} wDc[ lІ9V.JKLpu]]V[}J2*Z irwalPn&|WlUN<+ C˼4|za?|~'@a2w(@܄Dx`3ۆ?O^@76.^W}pu(]G~6 ;gx-_o*3[p%cLJ_濙Q-9U[y&py. ȿ#_ۥc=}dJGJ85{yUp]}͉9^|~xCn;.(ToK A ˉ9Gγ>~p 3L5B**!8$u&L6BZO0B{ďL6Br85ĮhkhB\Ke\Ǘ? fs-uA>?\wLv؏/溿[%~,.sߝx; <_0q\w;K3 F8܆x`3 oo y];o CWF fe2sJ] &6z7x}3NnwM3A[*vԖ^Y.CU`fFO'͌Nmy=':-..(oHamo ^do9c WkjF2ybxܸ-S_ #> ߋ4d1/s294dXz(g!(˚VҐaw#$SCG٧aϴlGHu4# oɰg"8a?rs#M8^. n@P@MH@&Nk\݀m[6A͜:Ĕè46C0*-MUP/tPe AכJ×pYa@x65fH)7#Se͍󆱿dĺvTZDPrTB*"z~>5H]l[hPBy\T/@uöe "ѝ53:n)~[`-EwBC k tg-fz,ɉz9yfGH.ZJcfGH:U6JcfGH'{22$=`7ayA9NJ T=NT4~Ӿ񏊔_>-/S=`,uʑ ӹ/8pspbѮ1)Pל.bϤj@XwW1y3 *M9KMj22!&~n*zՒ w(Q ĝy@Rqn>'n8O 0RWW,KEQ>ŮhO\Ep@̳'O]F˵h[̇iԗ^E_\|rOWvB?2\/Ɠ3Ͱ C>N/*5r<} ׊?şx9 gky}&<DvYuuѐ0}Lx ECVS2Sv3jۼ=<|ztۼ׸RQQaDmOEXfh(Qkvr%T^OFtPDk5[A Cb>}_S5}|@]Lor^{jҔ)ww o\&r 0M({ota))O?t065 s'ܩfTZm;:lڍWjuHٰͩ45ÇZ@Oc~Nހ ^Ԋ5rV|rT@zZ+)1:toKx&_RQ}G9jV k5m`Z7r毿dv/#Ḯ=tn9tPxj1s|QYJ> 5+v/^ȅtmmZTdŋ_{m=mZ\'`^N{.&,5G:wg)̕9RL(m GfFTcTCSlUXێk?~c5CE%(*)GG٫u\C&m<`E\0.7 m<`}|Cm<`@p!)J6AUԩ:ԶP/ߒr-+\:_a?a\kQyAWSR# * =e6O]XeZU*=#T`47jwIr?ڊJ(%'U*]*P{O{Yɉ~SjN!b]LC] *~a?2̿+F}\=E{S«҉*צ$ܔ72'/?_/CIlќÛy~FLV-?]++]!j[ YK̕$w }D؏B[a,veȴv`7!/3|7a V݀2$]7O<tLxak`|IuZ' A)'l ʂl*ί4Qfpr0p{~FPNR -Jr3XNu#|'$n>Q輯@Wt|}"_OZi|/o;[(oF'|2v.]mn.|NJ~ Ec6BVy㒜Gȫ`o_@bBVy/b\YatZ宮m0n<#|9|[;Nzlө }us5uV~7GJ]ȍ*eOf/rk| ,FyH=KnQ* 5JΜ^.~QVuws|}@.έY_ZKr#8o,KDXo>Qݬ0A&x˗5K/qc,'#1#zQ 94}:2Z\.2":YA #W+ڈl lz1FF\mn`<|$Zxί׾~u_8O[k|4/.Gy#_Q /-XelbtڏcX`-")/= D~<hA#U y'|Hd£bt>AB4ӪrUV ~_uW&Igz}Ya9GX\ev^Fe.zè̵Id*͆?\[j/W鱛ˡ&D_ow;GXVU7>W`KmBe?9,`|XP/yJd,\}GQo^̶=vJ=wik`buWXY|MY*~";d_~ v;uHDƥ–߯ zȺ[ئKu8(ZY 12`WN솽lu59"'? [RÙD4e%EV!.mK2e3V_ 4 Ez? npii8^\)b_n #\p$3w^ ȿj!1*HB QaCE,d(/TqDrѬNH$a!:Q 9YP0}|o_ 83?`_/?>e1|F¼'[!_2%~} BOh#/;/~|i]܆DOО.UN>Jsq1n}tjPZR=ӕSBz 3­9pi%)dq|1u_GGrCZz3&՛D9R]RemaաwD9ଲ>3tmaժDsF~ M[=FMD&Anv>Ŷ?2Onl㧧ÓG-0?n+߅bWMH׮QPHA~ȅW ";1tr{4ǯ=5m ZEa8k;ɼs}[a?*sn!YA90HcC< l;guXa~۫"Ύh M]N?4!ij_GC#!3W]ImG)]չχ1\OSNþ[ p9ce5=aހ/3rUxXT;n9rpE#Oc] DadV w5xD=5 +}ɍC+{DG. _Fox0o1Vy+Ӽz rg:[4)tT5\!wvƉLvKMp;a?W΍DT={35S2OF$5&a}B uG\ϛĮh'o 0Y>,}]s0~6X!#lVY<)Nkۣ)_.y +Sr$RSJKAf y5Z Ǚ%@93ݚDfra6Wz;׊ ۴ _S(F=ݸԴEmy]َƹJZ^ 6)~@{_yT+uord>pߨl8Mx W)?(.oG.u"23.& yzzO6`}->(F,<;#L|Zt%<{ߋ&fڒ؎<;̱nCM{ی%T~zZ)8wf-y[_,64S{V)⺮gWOZ}qJx#:JT9{8`'b[W8G\ ÈPz'񫉑LJm"Y5_KNiǬ.m@rt5e8+-{lmMݕ~xӼPa4Yif칷 *MY*3TC▟CXBl;GXV\t.4X"~p u4iǜƿiaV4W7">45e8o:tfĕ\A]9ϽWĦ9 O?(EMRb#=}hg3Ԉ a?|p#u5bgݮyxPGdT'j?dH9 0|Alxc?KaNrl"W2*hӅOƅCQl, 3 G.~ݛ'zQPmHnz9ۆ@])$ζTZ smʾ|8`>np/xjO~‡Ԋ*?qVw؏ a?sSl1aQ=`r+]b>O]^}TY>cһ ?NQ=`YQp1c8zR+]1r|Wqs| j^6:zP7XpUޜǏՕ:}z_~L;w#(iN}8Ϭ+u۪ ?^ 98h6{ KWЯXZRҵǽjNl+ )V!Xހ^}ZN|N2EJ7u? S݃ ?Mm9\NP+tZ{,T&J>\i ŷV~٬3ۣ<*6\#CƐ7 jPx;1ouJDOҨG3 qaMi Ki}FDsG$psQ` TA4wEw1|l̴k֒n;3 9{RT:g9`c|3@846+4w?W(JC`h38W2|iå8`Wa~w|.|]~>[Wp9_TU>Eޗ1"vYM=pi(XqyޱqkV9b8; `*owɍ4! |Äd?nO%9;~}9ViE;C9w}곤p:piӶuq!rȡJn΋*k1|0k4eeb$>6b?Ôw1oPkDƣDuoMcE6IBpch P%Iq-VZ#uG6C@P4%׊-жI0\}iAg[ ܶV;S_o* 27 BA7kk$fi7|RG^qZz#;Gnm`J(##t+ k6%AՅECvN!"%D}؉^^B!~ ZֺYy- 9p u%*}l*4=$wPv wigw.kc:WD0x&eQhdRy~X^(}W[J~ hÂ."Xd!ٱfbzT,(cwq8r7 #cDswDASP?WH 8}!.xL_8'xHcZ?p8*?q8#=2ēWēWpEF{% j"n%ܥӯ4ȵxY'eTxƓ2<,gG[;rq;# +ii~a5pDi r= v~+F~Y9u> O}O7jMuw.ߡ\|@Ko~kJqN ED}f+FrU&@6 RdJMؽ|uM@JEYTxfnTZI[ż|9Ӓb݆7!ʼ6~ F :_{bTѷKeYbRazCw;mSayϟu$羷G3ɏ#0mo=lWWf EY0޼n;UVYYv;gЫgc 7#|;GXW\t.܅>Ԛ!Klg=;ḭL7y*\4mO}{; { lMH:ܵKo˧[CΑ6uC.o˧W}ۣMOwnӬwtFѳ^Zb iF}8zXR^d59 FPQдs葞ͱ]W*ٓTc^!=In<`E} jC8zvm<`=Ï|FAP4Y~ݍ'̽/j~zg'[v7AJ* si cw ^5]#y f^<ؑ4 S 06>}D2O?1Y(2Ng{XŢQ ˮϿ}ZΞn k^ *J'|)=0#vE;?4!ts|v$20H0Fws] ǟT)d$eMR7-_~<M_isx#FT c0#zKvԑ=n!*X}gs:RWi8A:_XŢ>j7p@ ΫXTJ\@ .XS>ez5(ӻu5puW@W.=H~~π=HV jR8{;ClS7Vhi6%1R5/-D~^cuOEKt&츖r3a[ƾ }Ӎ_,Z28d X!|l[*Cр/L‹'G~$O/$(L݈#.\~:Kd,:DF#,W8K2Վ ʟxBO)6,AE݂; Lu'a?Ƒ}񒤔#연>!oo0F>!_$c7aؙ2J%ͿGCF$us,y.4;7Z =bnDc ((#tA1fW -/ V? 5D_1&%W.k^3 s7>>xJ&ovO}w؏0i|wKJJN*nX/[=Yyڏ1TE*;ITvq1k?MVQ>2 e(>|#/cj.Ƭ8Y<`9@9`).@qzOUp:yUK;_C s91 <ٴ5D+?7>\5ؘ籵Br96y`?ש+bc)U4 L1SKXMW3"6yld$>et,Vyl/myݜm/my#~(O}O]?th6rW|ܣI7J*_@ F:Z.F{ a6gK5IGY~Z\\ |J[V7C9C,@ܹˬ'yȴ͝&{;uc'qyѬs&1z_z.SP*ݷY~O 3YOgQ/?3_("襤NJZmO P7ij ;X) 倪 Ix~oqĆ򣸚[$AK4@(|OO~a?~uϓ@+T^pREM^pj ~('$l4!^7WWIQPnA@/#ns<+ ϐ؅yb9Ht[س5 ͛~A)&}ܧ~>()+֔}c?/w؏z5m L}șzN*oi[Fw\1l(#J,IE6C(C2 &$~b]C#E[6/ґ\cQmL :W\l\/V$#'JwQ܉n&%e,-'̉0|2ope8Pq2So4ݎ8C:/_F{kNg-_5k@ů:Zňy۶4-̷Qe X |FzQXb Rsd"n9tlHC;t4q[_9l9|2y{=l͡4Z*?tU> HS_b$aq؏zqsUF"b;,FEtܱ EUA&M`g1wϠhKtz*gd۰o-)ު`0B&ZMgD'|:t: |3$%0G:_阃@TOY"f|`: Ō׆Ȟ$ 07s1}aޞ2Vm',x`3􍶈M_M],~x)*^M+s$&AW)\~l04t`[e.M&nohO\]tdRQDr؏fPaJG9WߕX\oů={@֌X0Z$*j'_lm˭L{9F3+ We!I$-{/\ayhL,{/\ayԼ2m=WcjfGP0<*)c_0+MOFJkM%[>D!Vš7CXs΅ 6\gŴl$V$a1{!}/Qia?VTO63jV>ǑOa}BNǬ+ (#WZ>Ůhw$/q~$g?qӡΑ'c>1c;r| hXqiiHKfsS@JR>}ndrqA> aOYTo>agu>L+V#F6TXeδbu ~U*=o(+L+VTL =+FO+V-JV<=Vb!_Kًaba=(/C^1]դ)_S_.#j|!1]Ե=>Ks9d-^GHEfѬYcDMs9dJ˯Y44}4A`LV3qZ0%W88K'kKLz5%&𱡬76fD<;v<=z1 Z E e;!__-d)i2]>:lиqM;ZT aT{5/Ed1Vϥ A|i 9xjY&CSCxA= 0+R6|pgx]'J] J9rWϽ_+4/wAVY*A~BWq3}Jkw؏Fa]׶ڙR˿V;"z xf&N\S䬁sNЖ}'PIUipa믌0C.3fm528zyqnk3wcm5pP=%g-ijŮ+g}'/ߖ8l"AG9#am [(>\HJ$m< K.$U^AmO{!ޗ>\HPV6AUX*ԶP/2 {uԷJQ[ 8ǚR& ɾ/C_Gɾ4{ȃjk8}-,>=th ar@{ jLlr]f̛81Jodޞu%F_||W;P 1 twvޫ5tn:+~O賊bpq>\G'r C/ljDѫqbqu\0r8|z4Y NIiSț6;Ɉy}ւ6H׆eץN_tcvnz.:[ɫ}&kD(~w8=>ro-u;pƭ۩xC ~{tz5L?zn ͂xh|W'Y9*zY9*|W'9z3~T(s=ǫ51hO )9LG}=P`A{Jr)Z3K)trTg;l"ы*ʙb폽Ґ2uVΛs0lK:B=*Qt&ԃ}}`2޾_.} ӜqW&=ɧWZA E*cy!NOxcpfpWAZs4ƧYdk.\e.p6MOR7GC?mcF{ @HIT]Zsҭ{e緊WU[$?d7-~.d-7_3擯_ӏXN[`Y~v/~j߹Wv~=~?#~X˲OͿpGi{ewXWk {퉥h=m",>תyh=b\90x`BA%foKf|H{ؖ-9Օ^T^/HSyx~8 Wk>YY!;Tx^wo#Mmʿؘ5 ߘ5K[gw؏0i?&ͦ"u8|Zͧu8# ?Ltf>ڍoɠk<'ߖ[2,fsMB䇇m>=~ ]|cKg SM'Ǽ/".r Z c GXӰ]/FDp,wEDhzkehԭ-5ge Geu4ř"]}ƙ"F\mD2Ε7w8WZDUz hU4X+Z"ͯG˚qR<ʚXϣ78Y|#G]WAgA\ RU:k7Y[s1h)?&qe_z|GLԏMkQ\/ ygzRsgz"9WδbE_L\'t8kęV苩DsoL?hՒ3Dm0'?>Da2B)~H?As׏~OwN}}o}_j*4FKڱ.HKڱ~)K! XLM0#u]w|ŏ]W:ZhE#淺WO/= &lmOp|rЄ Bө]0!?yK!)~HǞ2 (\_{6/ܸpBmhAbc~~ݞ.ms|r!x_>, kr8mf#UtλrRl+Ȥ2oTέG|f++Jj8^FN\SYYij}*맲Ҭa~ͦ'yrT,= ?n(Ԧ+ &$Պs ?Bz= ?zK| 8Z:rH]\0et @..ddݴZ!HX|LTZs]\\ J*'7Mu\|q!>+f yp^NIA>| ze@z˃m-U_OVVVjXnCRB%k{ju$ >'\[K2pm/sµu$ 1N80 zb&S4ư-˧٢z(_|+ါּK lV{)봐:GrF\Z17ET8~&ZsA~s a 0c+l}?z{^<.:w-!E.a2O?t>L~uƏ{Iv Є:MHZrs$r!!җhů=\gDzIWXTD &4T_\6FIC*FI  .]}5U(SC{f^EQZrO4_h0 WPԏ^7W£AxO+**e@iރ8Z 2a #M5{ @KսTFO8X :} 5kǙܷ8aƺ=6|c9`D]&ASǑD`Dk</nM!SwJ@9X.: Ôخ3< 9o^EUב-lg(fW fUām_A[:N?fOA׷ZaH[i<Ce=V<:s`.u=4?i<7+ ĉ#F,i<"+ F!M#sXi0cH$T1aj<4dXi6H$*WTCGҐaWֿ*y_No8eϱҐad29GXOX8 tu0gWo-w+ɏ7ʹ?%+V8ɏΝ1.r'qѹbC@i6tt5 i)(feΝևͿΗ.ɇ3w5$Na'Įh la!˓3ʖ]P14Pmu` 3!M! ?y.j s%BMԁ- q=yro=ygg<'|tUÕYV| &lڊ1'[ÇZ̾Š6Ks[tQG t#` ӪYv,,V[Me{h,hYv~`ͤc,,Ǚ4o a=M=倓zzSx)o:QrXދ 9jٓzsW1gx <Rd t6W^ =+/_hKbZq pJ H~'_6⎍hyLA=7|kNg &YqV*fQFV=5I5i8=jFcMNN]@N{ &g@o|2mOa)Q—K ^i3%i2GlhkmPLC5g#A6_L&zy䗭#(ʖ/7WDDއʑGTt~ϮDNiQ }q}5o͸\UΑSZ[!uW:b?n*WFpuYjA  ˚RdYp1q9T L"FU荩LJԄe?@tᓑx`31akSmvD.荩T!GaMlL-&w]НBI5kN;GXO0NZ#Yrx_i^uߠp;gꄟ34r4<~Gm0(8j3 E!Q!h+&Q!hځva'JȮV *![%dW\vb;~4c +{Dn"- *4/w^>9~nٍd%zvRϦ+z߻f|YRkvO5絢wSб \79b9 DkMG2{gU˰ i B&Eifir)VkKU-+RT4WDDAنe`f~̜3u{}xpgy?q wWLrhbqbGWV.ʯ#2OUZUPbXZ%##g:!%J8M'2_{#\N'2 ,e乃ϝf- Ĥ9ty)5xiyӐХɛ枮P^Z`$ۋxHk0RR 7#5/bG(/żqbG(/OƉ$e wlie(!#6ZB{?)JM-d/OK-yZO!O6BA (^ AJJu$D="o0rz;;=x)ASL M*:dJhzP!SBӃJ^V:̔ `<m۴#bٶM1Qħ ^YKMd&ac 2Xâ؝x%9ćXa/[&kd {g~x؏"Oolv`({,uD4kx'%s,|] nFcj.=G\Xb+n P$w&1ŸQ/7\ on^gFak̵uPU兮Au4!|'M.Yk?P5@t֑QO~ʏhOX,wgւsEo>Atܱ?Α2l|',~"k-4,y ~::>Iy{C`uQ)|?]08cIyR36 ~ F4j8jOxOZjOx/Z!CWCWo P1_;xǿرD7y׋^ܜW@lq|8/}7$~Jf}| ]_?1o\O|G %@A~&û?=֬?#`J3 ^ߦNX'ܙ;gt`^`7R'OȰhs !!vc2bYٽVG ϝ}]^]4|2c41z,]vmjoo[oûG&7kWYk7%ݍ<]-EMZm#%8z=+?vPyH5A wΰ\Vd/W507%_sǀ;Fza{/[yJ?tc<6QZXx7aEEF#j F*iE9 /sL5n[-gsV䯕nkGEFnW;x?J/޿Z-D%vE_،%( .S?#Nq2CV]ȗ8?`X߆vsL mp8hmȞIu:t߫sio ~mC5(>#‚#7MBzN^dw?i+kcA.ʪ*4 8YV%vNcM-J5"RlA-Xw MP8tuuT5:mWEڽ}D ~Wh T10DrK?O.vMwOkGsQV+>stoKwm=+O #̷P337nze~mr Mg_߿GuJ+kz](DCSSKG.? }s FI(>RO^t{Zt5>u@{{0#`X=u1E6SVI{TcBa2e =fe f(kb6pwpOxc|*+`lkXsTˍhqaa26 ߘAPTd!1 Tt^^|8wx?U$gZM* 783sΝ{zџߊ@;.w_?I%bLzbL59BqO@=OH7|v?& >jeN( ݸC܀S |}977?7T~=>.f}ϊ;W3.U03@O}Mf +.r^υ_[faMYGgv+8U԰^Qz[*$t{֪ڳR~=D,,fvzvztٜ)iN~1Ve/sd'Ӹ%e (XݧsNJ׻GZ W+ uF~vZz!_Rԫ5?I|6z]!ܩaIbiZE g$0j\"O1fV"IZuTz>^/h+:i(^Wծ&H0vo|{'Ď #\{ߋVKܠw7K)HH^'/Ҁr?n ߩtҳ575@6x6<3tat 0˟+|ut-Z$h#x̝I-tsz8$ń1i|')!L2)6>7Tn|ƚe#mdii4vJ `iiG7N|4af48T>wW1i?NM<_/Q^:XLϲ{F,~"Ϗ6ɻY!}8|b<uqʪWXBVruqʴQxNW|z`Lb1E]aF3Z3",@_'+Qi)$t *SƗIQkbmi<6?|S>ax`YV9姌/_CBʟ;5,{t+Whx^[`4f#UH#Ifc*o$Gfߏz.#m07mLBa1m iCici['T(?oƴ-7򕛆O|#_4Eo)|4||F4ze|4v@ֶactF'`_s& C6ϖ"l))/IYj7',ÞGƬ|{sW -eSfXW}cV-qf.]K0ìޚ1J(_yurNX=$ׯ@mȼܞ'l=$]~  9)EJTF/R⤊4z'Uы8"͞H*EJ3$?.Wb\ZZY| \/W|\>_w_țrI m@a /9 ijw> =3C0% J2&5ַYpylTdHa~#Z/?; V+/"2s E,sWt# Hq 댥[F :c÷qJH,SJDbmR"˕{\[ ˥{E۟ɁF;ϔ9F671zv8aIg؟0U}㞎-sHrF4ӟ'm=]cXR,&2f).Ketx}4{OCm1UqmmuoGckw6ĘP5p) Ut6Xn֣fF@ȿ_oф /!EBY݆#oRbjmyIW^jCLɊ'NsA +%m#D@%GbJi'*9Ob$>MF7&=uaW7ٶǬqL^F91NJT>7@ᣱ}׿Xv2W/AoZça R^ՍmIѰ֖*V-4ceq` n%f @ъqڟOhmCEG,ϝEg킦fO !)yYj9:s̙}F){X_z vǨ V##obmo;F=Qo#=QAjѴho;F=9EvEѳ])[QA56oQO_`^)iD]L!Bt/22_d Q*`hil :\5`2h>nHW>_S m`ʕ-Z"d|Mfm`Mj=Eu%_e`T>D4e۔a?N!ƗɰKO&Vi#K#*uI SoVXV`vkW`,U[-MFtzj[[KƗ77=vwR*zW+fCאI2]2GG,Af"kUmPt=s9cFdl(ObNEs'`x|ZZQ%mԫam^;5l!!& .p>e]HL6ow=xJ+1o혂o=L??nނ)Û`}iE1&M/~8_Y`&?-6 @P߼B4 UYx?֑yWLSe4\1/-yz2\1K|s0.)#ħ0W ߇M+C(.!& Epol $_ ܰ0e`~<ʣ> )>Ň;9{I#INE;vTḰ#cS.tFhc*4<;1q` T$>n6SK+J+QZQ5Dn緲S[mޏ?Ɨ~u1L0|b˶^hN⇑FS̑0i_/EOI#_w0i>5&|F|U>5&|ʝvؼᩬU9RDZ1I*[IZ$|EB4Ϛzz^0>DT?FJz*{>SQH_At($.+(0g H؄uu k)<$!D@V Ft1'R {?v6'\ lvf|m3v'YAZioY& pHUFmU~N ?D!JzBF2Argger? WjK؂bA~yZKF#<#^\Oœ9;,~Vv/Ygdw&◧%O!O xMbVv/^<|`;W LK+!)Ɨԗ%ڕ,/*OKėi|i9-o%k=|__ @d_JbFX$f_JbFX$f_JRp[w<|=|q>p}Jx٧\ۧEYxe3؂bż]\Iy_4ΐК廪!m=|/wuSq+nC/٧\6ιݦ٧{a>u-ĺUxzY!R5dz!rS2pIu?@OĶsvGslS3O@ (YR0wj}x a>[,g~QAIsQعv +8%BW#H{0STK T֓XD~kk&)m|K|=d+_ϖ8# |Uoo^H64<Ŋ x go ϟRC>XqCg]Y9ʮR +%G>Г|gߎ]?u\VUGu7PWOG;nx90e eU:\^ʺFI|@ۿtB9PUks& p6m _t]&4e+o Ɲ+x{JuS6@_;]|T^ミ_}q/{cԟ6Ri-`0L$~zցvu:3ZL /I0,I7Ot2$:4V/Ԯ/k'䴾a]zy! ̑sn\sDA~LmN{ }&O派+4ƥ  w~?ƍZ3(aYqёPm@ Sh;o^JZX)9fc2̯Sx;1rOSv{ZbCNըD^xP@B t6╪ttgy",;29#遠 8:A6+5SRz b>v)j㍓*5SYHwI&x!Yɣ }$2]#ܑi]#Mi]#]#S?"0n!܁ oh3sFr:p-&~B;U8%z i/{I]KIkV'UBU(Nz*wAras;m6/IKoSKmy ԫmayGJ4EnX_GJvσ8FK仫7fV"]D:pk\a|SGf'zX\O#"f'k=˵_R:p)'s<9|ΚGh'y/?/?Jć$og.Х31Ggt%dg:eZ1W/ցcٸU/ցc(uk|0>D/ցcxꏧRrPϗ;j+ԍZ1wØC1yd;hk_}Cdp5f֢\KP[hi#Z  bg޿lꇎw_P>c?+CoX >z}t#v;wmn]'g|1lH7xg/`1!tҜx{Gս#>NBo +?$9~s2ʀ|ѧW}ηFʜ2:@߯"Cؼ_x윓Q$^G85LSqC!IUl9I|c~ZyԊ۟'`Ǯ1J/IKķw;Q/RFl6Cv%SKZ8VW"?$ nI = ]nk_9HͶ-ͭl~NW |mWW̾ t+ħZ@߷"N$)'X KR& _f@Fdh_f@Fdh_f@Fdh_6Ulʐ+,M2zbS^"ؔ!cT/6e(M2F5#~0 pt-pv66C[24mx0Z7Necm@E ˜_!o^v:ZF^*)N#`< ")h I`)b(X`< "5qڄK 0mAj?:g]ǦJQLEGmo?t̼w饎^(1G1箠$Z&;qi[sc,DX6W{*A]E:zP[Y aQ;=JPbb*pf;_Q! q~)yꏰ %K}@Jh,A -A٧jh%E+Lbڿ_?|Y\9#]|1h|1g+/62te#c&,{D+Vl@+'=||ԼdѕV+hyy 8ߣX%qݠ!mh`_/uWHB 2ں}VI*C&!msnuڋ\eR{q@R{Q*[5u7+XD~(R'HD oOR^>#x~?=z"`ߠ m! *GGk/3({èmfG**O:X{G|ފ.M!w%|C|6 oSf/O2 1bsfrW/tSqb&_9N]e`3xK6jr:q8;>Ďmܻ+Jy ^"TuNVUg9S9eNEW){m SXK|u 5cXQ7rx|.»Q6BD<hYiWNco@B D7|1~6. Us+ztWjl7Nt]n"|zt]jx"yiGԼ_n⻠w:]vov+fP8.Du)I4gc]^Ո_w->O84.1*Rt^E| )}=z*Ah^62BՀAlbM)}R{2DQS!;G)+GiC,Ƨ 6 2rw;m 2r\`5mOj/S?)+$ӕ4X &Rtgú)++㧰T\ͧ,e0hA>e|S]GͧB T{f| }e@nzy-;õ@P_(:#8eDz=c~w܆2="{]B=j6EL>x/,/?3,~Lmkߕ AB[]?._8FKWNNeڣ8@L|ǞbF/AUE/FnaT=%7 S?/c烏`jL>䈂 x5,L1_3m5i SNk2P#6p;5ijCgس1-dR4f2[Ȟ ɻL'h9+7)x%S0gyY0EĈM10 \f!^:_|i?ESug4wpb/mSw6"Ňb?YaqL퇩d_pb 44!#6:CCc; C/v1fM+:ާ o҄-56> i70j8~xW?V=ӝ;7~I_K!8S-OK wmn]؝8/;G_KۧWN*YTj xPq9]r:;0>k$!pIƗwEV!4ok}ykvxs?Q¦{/祍By3cYfqP/r{MvB}/A* !}IƗ+w"+3^IƗ+!+oq$!9$!%Hʖ“r#vfS#e wG7P1۱vGRjr:oz!#e) sدogpIg$z,E/4mjnzb=2WNkkBn\#yR{,Y?OJ屍¯PN_}E^LR$_Er֋II|z1IPIѦ@$hzӁ>+!w@YN.Yi@u_X5N쑜n`OJr:p̓ҡ"-àS4(P8X~Qƴ_ƈO1e`92ڸX4B2 Dg:BʝmK~Ϋ ڔm6/NKoSMS۔GVo??MKڸyU:R=jyD#MۈE;jfA>?ټyZ['򳞹7PWq!D[cy;u?c6n%ZJ jO@#+%fj!T=DS*f!K/^BK8zQG#up'Q: $|'1q`q=1NdwPbR1;i'5;qJU=jF#'f'Kht?_'I_wb=y\1_Jޙfۀe^9Om@2n&6r3 T.cm^m@2 BT z)hAIɫ_1]1_J^ ߻]1_JT̗j|z3fVA 1f?\;pr92s \(/`~ ]79奤 'UxwP^&3EwwOp:knH#Dꏫx*DO򅜲)])])])])]]OߗmSr/fH|j g{ R%/UBy8bg4S\@ʖ hFPE3,G9h#&mDlC+bZg<|ZUYRBz켣WΓ7did~K3 %-Awm^2lfw- 7 @<{]24JzY(e?{F拸"ZNCsP!P>+~x9LG,G9_Ċ ؎Al>z#v4 Y(ngƭGJ.?Rq!F8w_ʫM!pV}0>]٣qtds]X c{-q L<ڈ5˜p6%67Xlʇ+,/6*M93F5bSΌQ"ؔ3cT/6YS4_zdiT(a1,a|f=hq#EԾƔq/t ^"y /G߿f1e:tP2?|БE㠙Gi 0/?^WPquE-Е? ;}88qj&6ͬ0q2%6/M93FŊbSΑ.?bS "R 3x}Dee߹VtJhQ%y|D|ro6>F[Ohq ?kU-!r^]@NDj4y?"{8\2^9Oۄ4z FAޭ#~mi %{*uɜY/?9DC UVb&bm^?W7z|:G &q0.oƩ~Jui#:ٰ.B|.My|D4-ʗҔG(_KSѢ|.My|D|ngh~+(+8nz#ٸU i?Ag%NSi8Gut?W*V3oYٽ>wRaj! k Sےɛ,$1B[)1B[)1_JL#,$Ɨ I4B2y\jVTfnIz4Bk|)-5^_@^̌Qzm*+7 f(*^@M^2`VU/QԺ§*$ V~؂| _h*Wj|ڰ _6|)ƗG z`C^G63VժP_찙Yq_e#,Te/U?v6ո/u?LB3 _56Tk zF*{a BTB]ݰ _6| _GyGy}Lحc#,}][#<#/Hpb9i# w\{.볤~ǥ(t}哮ϒ"|YRdRϼ>KWO6B#<迥usϙ`J{N4g+WGݖ+Sw[JUB<>ߦ/>ך%Rv&Sw[JUyZ,%8GFkJ2u 4b=eRg2I#0*3='!&6|&4b@O$tP$u^= yv:U^jIKtV")yJ$%/Yv:+ w8@m5LcF$'уR"$Mhx3z} {>w,U_߯|^*wj̛|)yM/%t|)y'hM-W̗7G)_b^/@Zq-3Ĭ]ԨcqW#oݐqn9λXF&a /vCsG&j<~ADLK掀)Lak߬VTr#`do_j?_©0eIjjns7L&vCsGB&>磆d&%V2̔؎V%LhU2̔؎V%LhU2̔؎VW7h9r$UGDIM9r$w4Iȑd>$#G|GDIMZ7g(9BXHA`@"_72t/\J_~zv#r+. }t笧xT5m,-?`1ǒ?k|{|WbZJ!ty}`L1QAĴ\6N=" p~/߃'dIw֨|R'odIqBd|s?O2$p;C1Z8bxa~B/k3+LN qxfSb\dҒ *4(?-aE4d@ xRq_.Kd1[ng=:oZ* )s"y@J{Q )]y↤u :Dz;B8*̾J:7oVv/o3s\qJMVq63w87oyZSYyl1$!c|n*!ۀe96rb \c|nHy=(- qvOp{^x3Ǘ{jwΞǗ{Xqˏ Iy #3 Iy瀛G KgA>)/0u,$#!)ZS?u6y6GW"U=oZU[;܎՟U%b+伺'VF'i[ɶ cqbgm%҉qbgfA(mdr'VEq!%ed#(V BDpst 0>dB 󡤼Y:ǒQ24 '0By(%d8[v֌PZΡ,.v/'o^sCP2~/2Y(]N+c=ڊY[}ޗ*g<Ӓ.d=l-TьfY(%Ͽzx6" P>e,)!CEv+IuݴM2}>]JޙQv޵z|}[J8yYRR##E|-'ϡ9]ꇗ0QeY[a?Գ}\@FC=? Y uz~~/Ŧͅ!=P1g F[OhÇNJZu$JVm #Go:+ h͹+(Z&;qz!i+  %G*ӻҀ>xyyA M̿+ hE}.?ќGFJs<]FXHbƗ+1ٍtk+cӆ.1ϖn7ឧ=EkR wi<؂6\'1~d^&S+]>1x}@Mf+,ft44qOvRDS򺝔*n'J=%IqOvRDS򺝔"w?R %Ƈ̗R>妗v&$㺧(:3 c]g~q$dϝ}Ao^.G{Ob/[7 v&ď-(dw((OKrbw->z04(H6µo`~f ~/y.,n~/fAK| z ۟8JiEX*d,WHsY2+R\ր b.k@r\mD GyGy~~?GyGԦ770aw#,o/d@nxݜ-sҤSw!{b"n\i% I6X6Xڕ>i%$I,TO 4xG'#ZMxIuɯqO=Ge#bڹW*01]70[cXˑn{Z| /rYQ}rt>0(!#VrgݫH dI]ɊŒiI+vKO! ZslpI(O6tRCUƏ)_ Ɵ޴{.rGSPYsBJZ*W> !SOV~YxF2_b %^`*n|#|*Aފ|'OXJ$o]h^ͧ%Sbd|)j1I/?ym|)jy癢fe _L&]S-d2E 5)1q/hjj&GSS~ ƿ0)Ye1~NzG1`!8wd,'좆ốJ,$YuqW ަ:tScڔ?$m3CPy 84 &f?d*E=g#9?x}8r1/o:5/=mSg.^7g)Z7g|8_7gUk Wͣ]Jͩ$ܩR9:w.8cv9SڷKVS:]ESh5fBc?*O`I7Aʛ*",!!x<@OOGDTņ 24?2GNAlMonG7W&zS^&qKTw4ս"K1#s#%!ShosnWksM7ΣzX ¯>ۗ\?많FC ZRƬ@7;9=w+߷M۔_}7R/Qwm޴{Yuh-2 5M03kz>YTSe[MT5GFaMbz?6i/WOpQF}iwuƃ$%!)NaLJ`CAtL2xaGN8s#ے a1Ǣz!Š D>t T(} 1hZ nПh~+4\O?Wb%{?8z \^ JWs'c@Ҙ #qb͍6V;\M}Sa8Uwܩ곿d'N??]ɪ;PKә}})xT.qua9B4tϏ|jugᔆ Xe|bvOFueQN_!$H?/l:nH[5VM2]XI<}OHNl?-DP#[Xr|Os79>|B>"?4- |c!֕Wupug*(!xpEw$+\+0;Ӂk:%);Ӂ۽\~RZU!{XRZ1^9)OoL2ҊimNyR&?ɏHJ+Nƈ́t%zStF|Yb* q*==Ҧ77 q doaCI_}z^57G/qP|zYΫ N)ܨmƶ)qZz'hڔZVߦ|OG#%X8nF/ɿL(D_q^Og="%¸""%#ZEwAt7_\9dĕCFDw󥍯el#ߘԁ(1;i5<98>1;i5 ]}]} >} lgǷCߎ|CT8{ߎ޷?*?"},\.?ň DHDdh +NDC-=EgXJ&~&i~^~/Vd@LJoQ#"b%zh3)-2Wۀ$i ۀe, lX[ l(  l̸Fiޚ8|)y"*KɫI}\1_Jޞ7IV1_Iެ"_7X--u["bt[O-EpUJfs+f6B1r;Gġx?Gw*IkE;hh6 }g/ )J&1SɌ{0.D%骣-K|JGEȳH 1 47Pbt8}|hn>4 ]ALnA_ֳVE|6 Տ?Bgi$#sm,xX!~D\\KXsq/a%5QY7xP^J*~O6bG(/%7{C#?XK787N'V2U|-IPۯh`|c*@^j|/XS=%KȈ%5 Dn _k&sBFԱm_n|VWsmGG΄ZU~-_| 047a$Q77}@<{ O"sGLh1;+ s^4O#X{>$|W߬ƺwg;& ^c oP ̰8\7@D|2 j'w=z0>uݴM2}3 %-#YJ޵z|DJ¸|,7PŊ,z%COpRI=,GeE|72_Dsh9y~#7T?/2(:cEjfmfVx_JY(}*>[.ϖ hFPE3,GAH|ba#&6" P>oﯴ`.Ɋk[iSϋW5ooooTO5AwcZvOqW`l,2bcw&'~ڐLiC2]θM݆Pܝq/~R~I^[Qq>iPFyik،8˿s"_ڀxִ5`3Rθ%Oz4D݇_gAD͂ ybSΌQ"ؔ3cT/6(M93F5B`ef!%LJFŌVS\}lёǍQ"VSzd~67:F|^ cYdy }a/ͬh+)?6u8:.?\Wr],c1ly}| Ǿw85 fVS}trT 6=RFe*uݫP:R׀U|rk7kP;DX]7޻<ߗj I~?_k5.| 2><;hCC%z{mks:cBCh[6\&ߪlkW6Ԅz'oNr#t)\is`xyr^]0ت'QGm ~Hȼ=zKBM&l0v<`35箠Sh5| nYygOX>Xcy%J`HUj54]#^?arf<`3*`؜xyyA Mp0+T~a\ȄԲV7z|:G &$G KJ?s .7-A%BJM"m)r׶r[5ܴrwr[5ܴrf-\nZWܖr .7hwsziblgk4Yg~^(㷗o8)})b/ė[~S @@@b{wf|^0z<٣7RgEꬹ\+{+:s{x5!yy3F!|p*}>|p*3k!}CR'gn DZ |ZOz9)4h,*uQ*1~&VVįm7V)3wڗR_I~SVۏ{_IW7@Ch//?-W?YaP[/g+c0w?:+9sƶ Y~*L/[:6B_J/%a n8'wI=zpuff\֪ZՃ+&70Y^GX+YqP?v6ո_̟^GX_]Ym^e~A^GX¸UAb~ַ?ټsw:;M+Ugw,loT Uͣ0p VR~ۿGv<2Oqz$O<#hq}|}qx%ŶQcbRgkmoy?.u Ri+W;v_^*[~j۵{Sox?\>5MNN$i[/h7aN3cMx (ЭΧ~>eǺd*|6z&X׽4̲hW eer[G/1oWjZ/<-mѵ M>m]rw('7Jy6\{4+ъ.d?\жVcw&`q ,iIn0i)Up'ִxa]p_Ko~D glV [u:Oɿ]'`f?(1kF@c/HTL~ d@Jr/zY@v8Qs8g*7gkJUK=*mP+mPsg@ Uڠ,F _>1R}r% _>1BƗOr#,d|$f=]o/J5T9b Þ6 |1vHڶ.-CWlL;/}' c^_XMGSol^%J.I.CbkA!1:lyJ@2Ybk bߏ)PSO((1rʑ+GJ)1rJM/9㖬؏=_Uٍ[̄D4'Η}A0_QgUVv/'GaWj[OLo(OK]r ]i۝cꓸp WGYe&31x8^p y<&ك5Zw o:VF$Re?I[.&C2bѯDi{I+5y>JMvuu(OKgzĖ_>m|1!-`OHs={+_ Sb=X?Sb/\7/|<<5G![ ScyļR0$cW@J-, GY_ ;/t S_{2WVKxX93 {U> 5-nGkK@z"CF>`s)Gk2^=Ch@_{#[ M( y;D{4q}]/8UM|Uބ^k.3RO󛖞i w=o*SQYyFeMc'# '`yIZh>K OZyIbuߧ3⳽Ҽ0փi^ܯV^;'#YžK'$ڡQ;ttu}5r^;U.~G è볨}^?UmESߟXa"ނa}.  +|jZhxd/L| `֡QU|WRSSRGñśu|` }uv; Ju8_RMӒSSRG+voz;LJ2Kr錾8_^#gK*F2$3i&d,=S1mTG!XsAHwM_TnOГQ0aUu8k,ߢQG?jvY Ǡ$Iħ 0k)Έ7~ LZ YԮb3S r }S Y$>3G,Ch2ϭ1ܐ%uWG}z]>/{֤=`ǾeoӢ>wX$4aeo Y#tŧZa c{|:YٛekRIV V|/{IcJ?n 28T+~-]O4YK p1*$dH珪6X˫ AvGtYٽ¤+B~6dNRͮdͰ&>>m1N㨒<-Irn 3|m%NepJ*@>m/?7l̨WⳘhXtxE˩Y@+njc;a& :|*t嗩 㗹OmFs>چV-k59~jGYٽ5 ]~v -e, S5GxdlA1턤omn@ 02OyZڄŝB_<{d1GY>S)dY--fmea9D>w k|`lCf4zˉ|>uT2e?<ϔIDATew_8xwoNg2\푙ۮt]_iʷ.7}0sϖwvzY,/r~76u /%_~A@Zg9@U]BwkOv8gQg=2$ԬC'k)w; tj(x L_Z,i-nCSS>j?pꃮ2>akPǹP(~2LVkTfLܼR`P9C!N sWg_L2$y2\d|IU2\o3fe2*'mA-<8o<0:0->oxV>qv'q77cE k%C%% m?#&2o~~ ptŷ0-8ZwJ}hq+TRxS//w3%׉lx(^^WkqK[%7}R} z~~&Ѥ$<}=z4C;v`? b2&bga+ϱE >64>z1D}8{,beO8ֳ!f1x +";''F7vB%R40WPZQv7ޥFzaҊb%\/uw6? i.sjjj¹.z-xZe-||r]gU_44(^D+Q+x""i~pc6nUiAC]#Ch\(W52~644?rK5zvR@O- CT_ꦮ V1\hěl uoK|ocB] 4g$DwMr/4NhkӛpK~;z~Na< CHήI n7ПWXo=< NVO($Đ4ҥůŵKlK􄘤h|?f-ۿftٛ:;EX ԅ7 qDOsf~MN:zh0v_sqe)|IDϢ?Gkvn`KThFt}yt\Ỳmtll#'i[4LqFԧWrFLɚ; b\TfqbxB /(q֖(iKAm/(FP`H[۪ s{uc +񟏔g7+|bnsBlR= kow>3zGX"$iiZQI-{ ͙n7p ֚%E{F<{L=3e}axm0Co5́3G#_}6S`416_F6kɔӽ |"tPf]?Z2>wC|,1d" UP9ήM .uQ}f$R#-L2?]"?_9ZQgw߫wy6\;a\[x>?=uG\$=r9@Yyk|=ޤOqo^faq0i~ $ewX@RF\mXRF\^Vb=3RrZ{`bё=eXY[Ѵhg*-0z"^?J+?` >d;R4kwģ~J+%OB|)˄+!?H%N˵ǗAFg'B/(vⷴVJ=K>4zWڕt\L&7+˟@g%pD+%;HY%ɟ?m:^qb ?,(F}Chg;7_~ btųwRSۣ+7xRgJFse_Ds*?w vK߼P,Xpmxn pmjt͛aكOyDଭo1 u >u7ɫ3&"elߟLL:> v"1ǍT3'x@;nz<]4Ewd%DHN6!&)d|Ir3bRd߰=r 1I=IƋ~ -a1\~SsUؾr 1I)Rߠ ;d3Í3@lr ~}좚ǿPqm|v[{N%Ӹ|4btw9qpf>;()9%\Z+WEM`z_"$ISj|;ݒ;dzKȈ}r[ώzk9!#|,^&*\5ѐ݋R3bWj2oӒ&d]Ƨ^^A{=aiڣ+c_}DtG̳K󹞰"5H@v.8\pqa +>R1w"o?eVLGikL+?Un3_~q ԡ6oF&qZ06qeLL@oQʯMѲ{mMknT_߬Mao!6/ttUu 1{; >ڱF)6X>~hE.|ASc*76[ۖ@6v 8f|KV%![ݜ-ù0Cpy\SdǜЉ'xinβNsx_.7{iԖy2tދKn]:9YUX7gxEͷ^:7c_ٛf.؃us<8-;M} 1ЮQM7XfGH;_9i6͎_[׌^dꂰP+u리v⫮W8YsmH0mnlR7خ `Q  A@?{Ӿ} ]]Su`6ZXK;n˸տ̆ڟm6ڃPY~~*34h,^t/l U%mZTT/ݖ^>/`3_sbWϭ|1ݬ7a*/nCD`s+>QN&~emgJM9SJa K0p{MuSҀRB|4ɀIfJ:/u /t%ᰆ9V&#LzsMXiU ?%3:K}N9לw+4~v~ڊrM2X^鈛γOJMaqt nl{ ݬ=Sf|nFo#ݤ pHMXr `1ѡR`?fmC^[dn:!2;'yR bBsOttu,W?}ڄ8?f;,0}"<`D&yrXTM-ws,)O^܍r{Z?&_:SFmi3oi޲o+^YĚp_Ko~"{ =߮)a;OהL+eKL^6%u8U^pJg~[~?y{r[ [.'`{狱ER~)Ct'M| aΔl#y 'WCnvGk롬a@^ʏu7\?xz(!#6t_|󨸄 ?,KQy+:w)?+'ΥX̭?JM~dA*+5e~_/wZӒb Y<-enXOb|0O.]?$loZgeKJ /kkew&Kg-՞~Ӓ${MFH⻻PV6-fR<4 ~k eʝ3BO)эO;o"w~ 4-DOBByvD@ȿC5;ׇgY߷o7|߾d0/ŗR~&?$T~*M' M'"Ha_;$ FW`|`HlA$ CW\.Z_䰬ѳ%+i/\Rb*35E (+6B3yYlN>>Y7Z%qoqJ``[g{Y3Vj @h-4 yjuKOR>MGK7dMGK5|jH$6-ՐIl:Z!t8}Oa]XP<*^^Wc]8 +vsprz6oO6[~z$q&!0ƗljOBY$ɢD_/7EmQ3Tr\pZ/4224oS~/ ߱MIbV ߕC{Fe>Ȳ$"zm`B|;t.G7~JfK(Z8c kfC@ Y2 ˆʫ%='e/`mjOa>Pד.{<eуY2"/w }瘓z%ގE>`{V ֒SWN4}Pd=NH!bU_|ݲ%1~6Qnq%}[2|'w8*'O9755IVSSVK%\VK%ζ,[ Z0&;4p;0SK=J]>h0 =t]wx"ϝ}!hI P./ͣOT Gaxdd?:M؂b95lTNb7 4=vnlgmQ#'H C'Iϋ+N)oR,h}胉r;s̎)1;r$&r;s̎?yɔL#srۙcv䤼9fGҤ͢aw.#yL~7koi>ޥF3z%9;þУײ &).vG |ɉ93Nk?ձoߤS YwUKӝ;d |)kYfܙO`Ĕ+l:XJ01JM!1G\8)-)LLiI rwӧڐ:]߶?5`5)ÝEs]S;5 ȟz I;bQH9+~wgӊp[~> VY`[2@gEKҭP0LYoNo޾̊~)DcU2LS6Q赳zުdpn7um ۍllW;SYYjYmH @TO+hwVe?? ӊRD0Xc6ne񗤥[2GH^Nגt댂|Ut˗B45z?jJtrOU"\1g0q{2~o;舏ǜd//a1s%+sسk-Aţ:Z3/2"RSٷPm:^<{%jo{Ή DSݟ\s4IY"IO8}t"]m5!yCPo5lf8w ! yB;f_j֣}:wuQ)gGJE͔x1Q3%!D͔,޵TQ>(^LL ix1q21{ .OXlk) +╁FH>^!{88.:py<(nRr[ʫpaxd%W }ywQYi·˪7z ]lQޯhm5X+hI]}A6Ѿ;{ Cǫhw4M8-4̧' $(Jl0uBBS/(Jl0BS/(Jl0BSGFlr\y<3_ŕ{CG).)ﵨi~ktxE s<&km44_9b(855mHKpCၳ"goKqIx?a'إ#:ɫ4_K@F =^Q ]KJ7nvQN &_.*7*-*.Tx7ퟁ HyH*iy]Yr7mo?j blh0{n*VРe#/wӖmceUqa aݴ4m>t* Ĥ=]YrA_Ξį_ z|2:t͊ u.7ݶY; _ gǟ{8MIvp~hl߯UQK[ y6Od~Vvw]SQk? e#VzΖtw'3wKUK` mxxQ} ؂b~ުyO oѳ]G:{^ædVwTu/m|[n9;]X#i#|2=Y'0\=cAj\r ycQZrג;|u)Zk h򆰼!e8f>ŧCC]k?#ӟq|u;OGXx"9CccQ|jm1PzJ/vZkj+JB`2?_FccQ|J4IT^/ۗ4?F$](Z?F$]N U{j/**/wp9$Ty뿀o/\ y㩼B뿹wBPuA?`6ET\V~ ]"}DfF̾ q"*Ξ#)|Qeh ^ZD4ET=2)|Qeh 4ec"*ΞV~i5BS4RqH˨,U|T?i|i%]( r%T7fSu~cѤh>P6:i'j;_ԂUd2uzJfǗW w -::i+=k`:63 `D<*xαɆiG3Fn "7dgt`)꩎rSN[~d4bJΓQf`{V%ۨY _yr6jWrnK$M}c哔;B /Yµɒ-r^zݦ:[j] F`Xѫ=g}Wb~SëR~RkiMG繃?odGsmd@Xܜ~K5 05IԺJQ%]WFmehiӉn5bFcҽ}hnΖg^_Ts|#&1戚2}||.pxHc@ ):$ `ޑpsćyo$(3"Y~Ųkޑpn1fbPf[Zޑp;Ƙ)Xza>-u &NJg SDԖJ}~b e-7ڄ"㪪>nhkS Tߔz bА.z_tȨ fX7v!|g=qk?\Cjf?GHx29 ZND꽆/WS.HԵd̤ǒUxs;6O#i?j\YϏ ԂI_DF{,q,U3i oKg Qm ?۱5^/z2D_ %rdSWz0>Dzzc2~x 7o".[#[n~PNJ_;~otrao;AsO~Q-ewR7<3Kj::Ũ_ϊZw`ߐN|0a>(:}hۆJOJѻGaҖ}5M\ϊ_|?}v-l?ܩr]}Yx 0pG$hܢx) )h/;kʝFOY[Zp ۟9"e SRqh{ ُ9"֍Z1Whl;3Gĺ1*/IK*GmnFA"K!6Z-D]/sD[SWOZO}-:Om+sD+?C̭}}UD8VMo;џ4uᏧ@w1kwS%W~V0di.Wb|F?ԥtNn>?k@h3͘=k,)DgnMݼ3*Ӭ={ H{ݽ'K+UM(+{4IJyxǿI}%.VRmMTPW((*ʎA)@ BYJٷҖi-Id&3$r>O&gy9fLi#),}P)qbsW_э &guOaI܍?wPl/c%MWrvv+qβ0}>/x^m{⯎-iVLOj5 ^Ӄ=?qCxZ/wŮ%=eC|ѨvYK?lYVUz;l}P{cǢ:}C'}69Ɣ'l5,%,z2olu6W4L([xu;J:~.rmHQ :k\߬Zې|@,8 O4d h΁ +2АX9 O9w?_{&^o7{-02T67֤&lO:^XIԔ|'lg?e4uvv[n[R9fOj|.nh|1g㼗%yY&e)_򻆜އ!q;1pN yψmȊ3Fr.C&l&WfOC&l&^v~rm]]OnrR&]ۿ_G*s@҂L_4ݮںEx)zw 95;N;_#KFtnßmZ9|RY ZڿԌv4Wx7 2~p;6U&noz{mu?$aG{;cszeSE7T⯕z_0gDw Rmc95?`-cN@RtAyl̢yt& @!z<$FO/hdF:ӋGZ$]4mS .VV5X*sS K** G}@";5{)u~\LA&`]z), I 2wvHˮZns"릭[eiY;LH$t:oXS `T*mjy!3gĦʶXM S:[ďKeoԽ'K2XfΎK=GJ.H0 ޱ2QkM6ͷ 8!&ng&ǥ2[>"[\>,s kp#f3bVn}{eibbWu#pGe5" ǜ$|R 7YW-=gޘK($[ _HeAT|:Eiceዪ?bz3"fb1G/ްb\LoV[|` -[Ƃ ~a,0Ȃ/pei46M,Ǐ G歬RϙEԿ!G1$nnrg%-\jhmP\bGtuB YZgbGմ:, J]jmԠ,x% :DɂVQU, ®΍A!q`rnT*4W\,Ş}&InH ڒdnK-hKR6"/ۖHBvAT'b'9>ۖ'm[1+7~>oź`Pܨ./6$?8_f Ǐש!L'qk~1܂^o׈::_]1 + B8eZu Αo3ߘZ"nD'x{`(Z!4طAN7zB|0aGAcqpN.(w(umoPj9|oCە0Urp $^Q6'CrO?)rJC3Ht.XMSH7 ɧ[{x 4pJR=TWCG81=p2=7Ԣ/.ﭓ;^9yЫxѹ5 O^v_0zOM@AƍcYĉ?O6Do;~Hy>7A>UŒ68zB6ؙHNqf֓mqp8>eܜjE! z'm2y)5U\[1 |r =`VQ;]&88&O xZS&M 8O0nRIS:=)j0`udO>y  it[^whxs2GF%i38gY;z!Y~J,k~1lo?{ d]+ +2{VGEp|I<9%*:t~ZjlN`ò*8cE6BB_|;T/|Soe,㆓C?uM6 7n89dj ^ oxoxz<ɂ`~ek?|ucS7_&JMj׍-6Fx+2-$|B )-E,ɧμ^';np G8񸓫&=vo\V{D3|c .JyeQe=s76 gjabiQ=:Rn'ar}Nkw7H3C)gS{\iTNaiޞ]J,tG;dO.zZ;tP|JW w|-U=Bj oh'H$]B:= CTBw/m+o^{yDJЏ9!H6 딬[E[Aa5s&_g e.X(lѺ;5@=W <|S6(qsHu|>fM{qNyH4͜pJR6H!Xvyqx(s8cqJTf[+2Wru0&P)Hx:ލL3)S 8rǤOYXc_g&'x<0i[]|ڣB|9˲}Ui0W} ` ~,?FgIBc~8yMWx;n+ yjH'!ϟjuT/;͙z|б ej'440 m5H |3ڱ we]ZUf/I{uOmz*c[y ȋ]^2e)lG$ee) lG (|'7z͚>9 W}'0z:~yH2tq&ɛQ[Pc,ԧ:?p<D{OJ\?wVb[k=htʉaԸǮG:iFR15pj;Dϩ~|N{|/VߋJ68H9:*[ rm}a} o>^iKqx ]NUW"_C UNO {5x%O[WVڱ _7=Ee? 9B[0GNeK\@3u>^)JKXK:\GG,Fjf7+TvK*~⤳s8Z~?^Oيݶ7Tg{7wĵ[igHkӗ(ScLMيoqF2O;5nmV.vizi[fוPu˒Kx]M<>{Wgd̈xEԧ۾/puG ې'fN?AUDO%8}xi׳:_-(R=9J×USēg2s4kTza=CJ|$/@ꭣ^SyYOqzR^)(M4v@Wa\DK'fEnw=#(r m(rts6s GN?΄6q/Fp_@xtܸ# /@prb$leJFw` l2|Ŵ=c+{^w!0fJf_RȶŮjK7_[&hZoF/S׋,d{0 ~<\DT2swOB8Q{#C; /=lAwwqKzzSM^mQ } ƣP +d4;b<9%hw9=ڢ:O/w+u іacw hkP|hkİDgs} * *RkŰD'DV'xR^Z53lK/Aj#5ގsNJ>j uTt)_槥ߩnYQeUD>VӃ=-'/LN4ۇ~n(D 6!12'%~KOџ`D$ Hɇ"KڟZU͇]-=Iɂp'c'"O@:=gDlӐ:8s B{91PW7.K{'Y^[HOkkGRH$K5GgA3҅B|RS8iaيZ5󈋡 OzQO7f ?-]ӵo;sRqV5cmtvNz .]ltgs ^S-5 pDV4g)r{+;~mQovNsrl0~f5Pvvp?t}Xs0VյΎpuf_ZS h/gp~,}u^ĄV-ga>Y7?KHHo6b꽅w#/o*ޢM']U \(~ㅔf1C˘oLCU vWm5T::|ctL([R;Ë5m{?n V b7=lb Vy6'%T˸ubĜُ[x{3䟈~d<0h8^ȂT&!{vDq,~HڶQ̵GM1):/JxW\?-e{ !DɭE*Xg=+âI T~r٣+2uG782 dY/0>da연k61`LmgQj,|||j%ڟ?͟i$>oc"1ߥ (~"&6˙?399\oof|rYG_"@4۱A\6Ntm s-83}ۖ25|{}Z9V >R>(3q3L_b_Lw]948_|R6VD]}s */߆hTwM7>^Ѣ^itor[F?`Gc5mb_HԸKR>_)r5+8XBLncpC~ !: 1sM'\[&G2ˏwW+1ݝ^;1ѭozlcFwٯ':W˓nU>?fNؓ yjT!SGoȗ_ِ_k4宺;3f7*!\l]>;}gbNLmL-0oK S޺ÿZoil')Lܐivo3_ِ)'GFr>[ F&Cs?YS 0^M}8u&~+`ކ$kؘW1l̫Wm5Ҍ__2L1A19 4ɻs7{_±Me4Rh!w 9CNwb88TV:۔Cg6&e_oE ҳ0,{ҿb&T1h3X EamcMm8`u#g#LVgd?!dM/lPʒ]g=ez^T6/j&L+i":M@Rt҆&M.!ϖu% ʏKՕ<\yiCWu%*YZVHWr _rϳʟyV?a6/e)mb,.VOOKK_HGq vdH 8vݯI '#4˻#Y&Lٖ6XS_s~҂ig˺:c|`Ϝ_x&C\X|VpwbKNgs-޾o'G- k?;csDʡ"u قSb V @i8(g'0^3[´VOcoUddOui )>?z)?\6RQol>TP1o}(}_%YZ9~5A8uGeM 77뎦_Bbd=^35vU=^sCE=^sp|z׌NDe;ka?zK?\6 o ![:}:'Wz[Q3eiY:}jDo[$N߀mE/"@yD_|yD_x`ބ)0yj{fӬfJ㳶$J3+* b k:} T&΍M3%s{fLIΕfJol>pq~k㱠Ҳ>s<huxYh'bHƈlthy(:g|O6B\O0 K?@`T6N`T-~*>`|ߪ?H`I|(R='- DdBlLl0%OyO)Y3FVHWߴQjx5n{7Q\uO#[T>{t-Wlo]5찢ar=V^B+_7y//Ct?^:wEM꥿w.9zIa<[7S>VMm=c=3^JG209z" ƴA܈N QmDÁ0F g_&O*]- ]k{F󦀛 oz!] Hm#-j p~r~rO?d'Fe ꛢ<P]u<9=-?mmڷ遁sgoO}y,ww__0į FtbcZb@Hڪ,?v]bvsۣ& ՟;MJ53{2OV{d^*G{:_V!|Ko'J4cso5/2yVg@kjuMG OV{Byݣ4T#c517؛mfyAu1j9{6 bf@?aKQex= 9Q nWk=焨2aM [BDW ÁZC >nx߫#~–(<o yj''HZ{@gp>M|pqx2c oQ!};5nEZj׋x:g_GGm ??z3r9^[a)hY>}`6oyq)3OBlxfwb_`7K8olmؐz1\w'!6FY_T ؙN΃"H 3sS8hZ}Xk5?i":r\n2å>JY9kw52K_Ԛ+T<ٜud.}5 Wz TKsC]<c*"+qzBG*QyHȚ_k Ykͺ ZnBZ.XȚSkֽg̥W1 Dq<jpJf?՗~]?{{m\@,5f1һ굛B!^ۯ܂Qor:- QWn8p+xi&^Y<[Zsg=ʇx! u ѭSs`=nQ Ǎt;.(N8o_(Ȝ+T6B@KFkUf}KXZiMDUnZ:>/ժ잮泵iV|K.P|;Ff.ڪl|"xKddռ*Jt=%a##F\[?[?{x|EV]V~g%J-?_k2ǟ86-`"Zw/i ~W (mF4 N2<`UA-;m HR.{tCSga O$T5^`y1w`cԏ8P[d#pP>$Xp W>@k9z.j|<PKExo'_͞.Y 'Zn=1W@y(gع,x0fJ)&1?0ZWwpObwl} tv-jn [mO8'½\kOxTjQaq8yO |}5Ku N$EȺ{i}&!s`=+ĠkW*Ź.(|4K"I:fo叵ǗX ?2so_ z4 )J.Q3+{yyWjPmJ4R<%t ą'O@ T0l8JU1Ժ;*rbD91LR15ISƞ>ߋ9σ Ƥ 9:'W11gQe'3bvD} @َT0R7Dt}]늾i?PXo3BGn;c7CJxJ$s c2 5C !žs6`P­,C$_Ag gMA̋ P^? XV^wc^L=A-P1X;K68ʧ9L@UT9r"IJ8z!>;peف3(|t'MƬ9@ϫAӅ[3[C.+Q{e%<$m烁:SV?6:vSC~2j^vSM&t~Ѯh׳<<#itʉax0 {J('I L *\&5^DCz^>N#{034oJS"''ʤޖT&m(~$=D~O=0i+Fd@u Don3qx b/iI|,y?/4Y<I[1ڬJ|,eBZF/QA`${a`+|Ow**7SLY;Mk-]8 ՟5Ӭ\ƓKfy 5Mf]VSz46s %"/)uap_=KD_R b`ݳDd%LJƺgNA39d濞.w nM/fX6$FK'=6_ع@6@o0֞wn #hS=7ZbUjh,$6:tWymJ#!bocsX eס\ȻbY'+i:>b@Q>=#FLbntB 'ciXk\I٥#>1:BF.& `2k߫r뺓Y{UYT`]up5˖%._vXeKOk;J4?|"*ƾ>nI>g>ո[\:xZK|.n z@ * -KҝC%{|}WIYh~7N]DUj/h 2_"0_P4ҽGM:Ӣwfژ>NW831PG<9zQ`"8'g}/eit%UQ`R~ !/U Łz#m,_tjP*U'g'Lw>'ĚjHI O7$F6VrN7LKJuUpMEF[jq6cUعH* ӈw/wu9jEW i}4sDaxElJ/@QyWo5_Qr q =2J6/SըD/  /1ԕr:G#yjU>/">,Jy,-ԪZIRV+Kjœ "|Mo,ЈZ{9Q/;,aX sl:>k RՇ]g2mNA9w_-ڄ1ldtu6y~ZduT4ժj>l/9'7+$3=td͊n2 *\4_"{N?)|Б_:?=س9,y$g+!k#v ȸr[a1e43RjC!7@+ʼn^UOmaوޔM]>e#V:Wh$^T5b{p{*w$:r^kId9(:jU}u-cG8,=PZB\8]PKOB9k?U֪Ts ]\gGRY)t)iϞ忝$PN-K[ϧ+tɧiϞ!vnkwW۹M}э9ܩ%w`c-Jy_۹M ?p?u<綝~:B&H(l/>~3I:OTvnd~ZϪ^:;GGmZ)J(DYrGY۹M͊*):UaΏ?o )5ʳs=P۹M`OYe:'WECf/a/qhUhi-VI%.rfF~E]ڹHM"D/eNl-S^[u(t@oo؋͛qCbxJ4; O4brY;mȫ ˭h:|Dɡgmt +6*&lx19l V/㧉>CbUYѽd2@ /g[kD_ /A~V-J6ʺM_Lj&/KfjMk}ScBvO꽅x(^.+\$2ɝVgJuZ`~E_ {ndu@@vAyQOc `r%45J),"CG7w8#aOΡ?_,/bw6%+u"0Y___ vvv'_۸O_0>| N[]EWa舄=:=n$qQ T#[>~OW +ah'g'$iz6崡^~zԞKǼdα)OC{: {u&#AM6վE3ƍ ֺj*przd"ׄoD"ieTL;"qjgEE<ܨ^/fN0c&5JxyN%exgy޾TcM2g<O{q%w#7n[_1+wFe/w'%F6' ܝqKѷ'70/БAy:[7ǯz1uD?Y֖N F qZp$ ?"NlU lV->eule׻:$־wcsJ*5a>B灷v}/)|36>j _M7Ǒ`-llPvi-˟F/:F^|kH8<PC.>df?.~ŵf3WPnjYe'u)kď^do6 x])5Do'ץ]'/=ٵޅF a׶6fsGYv⥾@ u:-H%ҳgAb?9:?/z1Af~kV=ukU'_ BrBg/Y&[n6w_g͡&ԬgOo@M=hI&|Be#͸6j@1rb g& |WqGO |kCBNf̧7n1?gUOo@7s_Gg!O?=^^" P*/cqpِ2>,޸l]]/)qپ^t[0gco\NgJ~n(s7)qy\ȜM k%{䖚SG3 ޾31IVU^;BCnͱC2i/c/,77[֪ B ,3E~mxUákň½ ִV5osyM=~IkQM~Ia_sZ}5b(>\W04WXלvDȡ[eSLi溺kN 78h*+ϥDs{T tO7p[RA/ٓlО |ל23r<> |לU}8.0_5o3e4za/ưFS'͘>, T3q<!1C3< W7p[CϘW'c̫?gTA|K~&G z14]1,x$[{:yOG=VioS&ݣ҇(K~nH o'%/0ițK|CԛtڬL4 Gvm#3.6&*ʝPQ.гg熠ֈ?I\DPN^D#nYc:7nN㟿֍(~ZH3YsI5 j'/o(^'JԬMߜk½9~coi 3.|4MMNcV,j,'Vd4WCBeOPYA^^p5}E|( eVs*|GOY!raW&#~=jlN#wR٧9"P_a_[>/7&lYmL(O%p6i$oPdlO:U>0SOcoqSRti*kdN~vH,\d0,]Ye/Vq8?پAeqATx#G0o?J.X a\8嬭 >WY.F_Vc5ߌV d?T/LOm~h#ŔP&,mlYak?gFJ.XÕ.-}W(6`=jdMAU Xl7]᛼Gg3;+*a,{t `ə&&eyȝ.<[]J^6PyL-Kj.N&;reine ||[LL49]5\RKNRqK7'"k^^BfDsgƚ6&{ yl1ȸETxs7]c,g]}t\9TY]+[1 w*wĸ-De2t<&qVƜ^= Ujn ~˃5:y6FtBݔ),pϵƬ9xF&P`1ot괠0N0N{?&^QʸoK,ִ.D^|"P^~$laF@'q\#[-4wbc5fZʯ|/ԜlN3K9#o[}ۡl|.x'ˎJsۚؗ} s*2Օn;?@z> ~ˎL\fIh<}i#h4;'GY~m| d=v9 )1gXvd֬/[1.W᭡cǥq\|:">vwW؍DDt2Zףq=*}Kq`{J`$lCExo'_= 8@CԵ-@r[\|M /r@dN:U gKc8|֠:5A*[8a`r޸ӷp:GV-=5>9wrѝܾG9=eq0WN- TAuYDCѯ?Zyhpu:r@߷p~ NgעFЖ?:* ϵGeo'}H˪O~WQX;u. 89bJ}Xs?B߰%jz?Bqx(M¦ oaطmN:‚N[62sLwwT vG4b-E0s)L>:bRLӈTkO9acWɧ&d-}NRh ع@FE:xCYXea*q5#MI[^>+ve?gع@[V mY)0g% tŮOQ3=}Ĥ!plmM%5plzMQP"Zz'ciXkU֢MZ' E\^H!ˆw}<ۜ71}ODMsDЛpMðfoRݽr!.^ nj(FoڙH]"cqݽƷwxD]gA#Pa~qz91>]? }sh3Y9)|_\d]]Vi?ߧ1 1QL S/Ub``F4KT| c?@zT=f>Bbdj5I *TzĿTWTj ;Z,PMODrkպ;B^>35TΡaCfSzh{L]Sk5YNA$a=2J6/SըD/  /1ԕrw 3ag044ko?-|XY&TXY^nL{7yA/o)+>Lm4-P -}?CɟP V뤎rfhh3dC6i>Z.ڌrf:,ڹHMh6e!MY6Cdv.VNh;Wjw {/wjgG0tr WAYm5_oo؋=__ƿX= {! u/b$NcP_Q4uIcЮ|77Y%dF}EjsP {v͇M˸ *F'W G;ʧ4z*5:ǣ4NNdOaeTUעH"9ko:Sxz k3:rjT+БӰLP?x*maV{K9{t[sU/Uts/f 6Ԁ 8 j^ vCh'9D 1csѽĎ=t[{ˋ2C@`~9 v/W藘98Hh= ouD5(b;sO~"ur{p> yLHO psu+opu?pj__ rwOc5]h ?'~C^Yh2ɷ[=q#i{1ŗ ; M큿:ZU\`M|PI$Nv}άfPowONlU V->eõkRe׻:$׾wcsJ*5Ix灷v}/)|36>j _M7Ǒ`-*NKk^LO71 ?<}#odbUQ; BU>uo^YN5]Dҍa?c/VoLo*~ݔݼk Ӽ|[> ?Dpejq ү _²s애;FkZjiFnά4^ow^xmjCh%9r̾:ɞn,cs>y<Kns^tz ۘ矢)˩2}2¢OBtW1b;1_Zi5p|>ƵZcꏭoýc\=ේZ~ݝ.T5=;[ P抆4AkEW2)"!\c>vDzlm?EY8/:fU'HQ^~~`jwnR bpƿ\s1+S 2k!Խ{j\s1׼H+Z#o?lzU;ޣ J[d{MZgqTZqqs/f4cW쳊ya=wiQ~ncZ|Vʹ:?xP%`X15nv3X&|Bbdfp鎓?}8vDN.KX.| GxR8kw,M~8x;K%Xqfob\nw":t ޝi f~u K >}w ¿܂i|+14ÓAt}5MUJVpv#KN!v.ޞ8w; y>w'B*ٙIq#:!BJʪxSMV!z_=ێ_BEe5?vD?7 ^m]i~h.q m!ftޠOg g|W|c8YKr93w^+#Sd svzۤ?UM^^Խsrs nf~5ޡ5X@dkdk cߣ]slx uәLf"P|'5.Xj" p8Kuͩ] s4|g/Pф=#iL>~d#l۔=rpq'.KmCKKbSe銽b~ OWHY$ƿΝ^ ۘƍ"tđ{o O6oQ9xfߏuMY[׽@WžA HϬ s i AM`'>f zZIɕOE_#^Y?u^~nƮ'~H>Xxo=O~wVj-=*rBP x\u=+ngJm?ٞFnr-PVM09i}tA;ރ'Q|mI/Z ܜO#Eڎ]OPk Iۏ= uZ-쥂PRT폨YhJxвKTUju=7ed,R<܍ٯΡoue ޏ22NۯykJ ^u5*p8/!A#ޤFS;a{S0LJ:+aP7''lGtnnʔέs#Jؓ91aO 7(Nώm7xOyl:qqCK" ^'O?'a'8Iq 2ş'_MGY/Gitۄ=y{|z}!OOۚ'/`i5*z6aO.a{zu^nit[SxPCӃoRcsF6aOCP;徣9#n/r>Uh}*YæNN΢Hq~wu?e{֩f2wp/T89`EumiF/POit[>KSOit[>SQƽ_4Pq8ng8?2m {u9hǛ֋oLHR[oQ> QGn].hv }éwe@0FQ/JψI+AgH>|28L Z TOqqGvͿ_rz:zpД y&CiI \zCw+A)WR=ed 6fo||** @=/6~ldAjԆYL!:WW&XG f4^7QOKڱMtp㉡| W6MXt[:CϦߝ݆7nk.Տdnk?d#RS (ݖX9!H/U=}D}5ߠ>Y\iD}v9Z,aWQsӇ2g/̗XʬB7<Й?B9?/ek x:g`ז{+bs2!-#XvErO09%\*hl [Orsa_9!zyq|8I4t&j&јT`)XyL?+v5fOaڟٶt&;ڟ'l4nCǚGu TM{/J'({/c|û^HںwEM}t5N"Ǹt~ OڃTJro `c0Հba,S (iŧWJU!@m*'׽[?*Ob^PYs+ٍE5E/0sQ[~XQWOt[|C4kk 'P~LÃ*.zݖoGsm_B :YUsb3,;#a0 ?r\OFgh?!;93[Wfށ2zvWPf17 HA FRXyW.G% s#),zݺ]*]4aF#Ìr){B4dN0m'>BI}W)oLɧOPfr3?1^>uS ɧOPFL._*B Q uacWlI@USheu@ac _[V! i 0_W#t<2L$m,;ݒj0T˥<5*Tׯ'j6yK"sCy{t.tʰ1J#۾"f,]?殟1cLɰO+|?Z-n'vb 1l,ۢ'ߣR&*.e'ëgg~q9D~sOiq5cؘcqNrXKs?>}"|"z`ؘcj:T7nNtoM&9W*'d2_z/TQ^nc̖Ӯ)~ _ uC{b%o˘`;̝{bez `/LS>|2_z/'Oi yzscW{G=+ps-1|V+'q2MىJxb 6oJ]S4ZQ_G8{~*.p :=ʃi֪ԛemW&Vl4QBI R}~F뗫Jx8¾N]!Ew+'I̴ܵޯÿ`'JΟgs{Vuךau֟{x)N>H=ŗOéI +ԙ?mb(v)9.2?V1ҪZxrl?O7V|&j{ 'VR>~G-Rmуh ~^wȓ]%+ߊ9PWSO$vša0ԕ!%GwO1d [׽CoUWNS>SM1[]9L{"_1Uwn0#n4}1XͯrmM *uÙĮ@T3>HP~)7tOYG<<=wޭq%c\rBu9FgcD߃K`A>G lꇹE?3{w~=U}P#ԏg*aoq7h!oJ& /}ҪUwa 9T XoT0fPN~R?'/_x?'읈:%{. V_V0b`{n~VSwq-FX>Ptjju n7H|.5:tΫCAyh>)z> w$Mtr/!kC(j'??z00:` ̽3~RFZ܋%a/#mVw`)>{?9 l D90_`dg|LczKPϲ3gUЯksGHo+qPVF|&lH!F=<\j5D~NxPJHE|K~ {_2J  '?FKi5:+3VN2{6p=C%Pq^*zQWNJgO_?C?@_Qj{k}\\TRcgC@\;T|儐ހVE &X=ٺytW9 p^ӥ+ߺ׌m][|(伦KWgq_Zə7_]yM>)<r/s-uPq^ӥk|_` g5]|R;j P3 !u"dZH|\9ʼn&4k gW'{j;J2;ҮMŲHŰiz~1Ѻi2 4 oK;iz~[1|zwܢG0wqlkNv玣h1$Y6w 6s^k:~.5Oܟ7v^Nad/yR93=Xs/6 6sfE'?b.57<=CTN3{r*cD$UOp={0|0vsQgoPP_ILswF# O"FA$Rg!7xe_֧kE}`S] ,!;Q")*z K~"JdEF[TX~"Jdjt~4J\C~4J5g/'D[)JΒ;yhʉ&G@|,5{ Ä@kYߙ ͤ䰹+o_j C{kAkuwG2Rkuӏq"OtZf@ˌZjɒ&uw\6RJ 6' `1*71& `1a6,ymtre*nq\B'Y[>u:*˰֗~'@ y{3?ilzvU'/Ú{ȞݰfmY"Ee%| k0 o+X]Շ=jJV;<=2wէaHqZ?-+" ձ.ы| o`~.YX7|1qEO+U=:?P7(_imH`w 7c?5/<3] %ЁvE6mo#:J ˎyX5T>ԲF'5 T|Vkw6YGB~l|-bBbMLU~ ƗeQ O]U>sF5Ve?6-WC%񘬍Mϫf>U0wrt60o um_5vU'6CD's(_jw_n1ݫ$4i&dkԻ#-.[ᗭSR4{bPl*b5ܙb ƏKl`|YZ_.o6&J_ L'nُD>;~|kۖȸ͚/ܴT^XEW|fxec^}]Q&fو"+uXWUf3^yq_R 4D "s_R /)uMïBN ̧ԁA 捬PeٿnFkLF+bXG6F/p ,[ᕭ/C,}D%z~`o GlR6.e}7?b_uXi _Le!7/Y7ƣ!& a=)з%N4tp^¼Â\[Ssm}xwŅa~N si0>]km./lT7B3?Ө!5* l {Þ? VZC}KC'O:܆?Sxqpsva]1eXW9;`BB~.Nx/i ǵ?hcNv>bLKQuaLi;soy+u{}JI'o7*gF5lWcVa6  M5k#FF67e#J:j5P?rēٜ`BnTQ^!sQ:S܇[$I!Q7 ~ A]Q*`W^uؔxuPV¥L.<@_^o~UھLj-^D-b욃go?~n(Q[ \QE72 ~q!ҿZ?}G7춽2jJ为n;I7~Zj6 %Σm2AU24x0 f-CJؓ?# R=\'Py/=m}H 'WN2yHpž~ANvN,EfÖފy.=*rBW{īq'7Wñcy=fiZ{}jj-/86#^v\=b-˧@Ea +b2uRoo0gdj꠮!&%8{+߹[ovc;N E Ls!b~7l5u(UVȅ[bV+i6q,NSN;5,59tFvpnBͺΈ_*uԡh c춽VWGE^Fӆ3槥ZşZ5IoQج2˧z {O@|O@DPD5!Ox.aO>=? N~qpy?'+#iLE6qϋq'Bl*{86kN5SⓍ'@TzTҺ pOh3lU|GG{{Q'tl]'8:CI50ul_/2Ļ`g?GzIS-]\) _8g|2=xd;'G8y:*b>|]'=@יnf()kޯqL1V_C׸kF3lde5N)%I& ptZhqe_gZ$x_T~qq]:*8y{ QuEEn}灌qSDYď|8u;N;:TEYķ~ 7WSE "E|,_SQre)C>xh' k{bx'?HgHѠ\_>fS,~e:_APwOnQ?uNg)YtG kj=h/ @֗L QhS ?M'3qNԅ9!ŏ|ЉhP#[1!Û0/DÛ(:*"C{x7Ugx8z)c8mq!p2cɮrEwvA h\*7Ӱp0<}~,jG79Z 3Yɉ&'^ף`J%Y1'1řLOશo~cE5|굱UrPʦ Mx7*춽ʟڨ͊<0aO~9oY>u%epT?̅/AWNdKL@! #h A e]=B~vvw,. lwƐCӰʉZv_5QәY—UOiYdNgOwg ?0r0ɧТr$VloU4,߽p%S4a267 zsrkDjhkpۊH>QFE}沵P?OTPCq,_W P.iJOXUyƓq|I'sL˨|$uadoV!)ZOո'0_mwO_HVnVr$aM DCŷ[㛫?*&0eʦ _4are bWl7t>L?_eZ4fJN"t@=o_C7wP)>5!K/-ON"5"~(8 O_ln)ӛjUmI=v v0_Q|3Z"ÇY'<3 |zjhI b⓹a&Ʒm|S2'sì6/x#{~'q}5SYKe 8w\ZcH%xE;,-3ηo? Ϗs|A= 2vWJ#}߁ =22sovE=` ~~XjSZk4~cDZfxWݮ^%>lS4!_`@K| &l&J&!dM6dM'%?UFe!RC4'oQ_, *A퐭 A=`K韢Η7=m߿s4#7Ǘer᧮?Rh+l9|oM*AnMǼ_gh'RԟQ]VGϮ4߶/|-1sFX>dKSJN\,^~ATUGxsFY|N͗Hu:_bïg3c]薨SpVd -<6dgl7z+}WJ V`a1St)Y:7B)z?|[?gm竔}7"c"mS #Za[ʮisow\Ϲ7[pe#\Rb6>V~RbB+?)_|>\p:ɟZ{7˿Wyp-ܗ'۴a@D"Y #˳q1>P֫ן /77._y '$[Z}z)uxTԡX5k%Ô] 8hJ7P$2[@N\b|o<!Xmzt ~GeOAͼ}. ~fv(~Pϋ=[:Nt=זfWPS}XR~>+DNm柼4Gԟ9{a}E^[ƒ x^[Fd?yw/ߠ}v݇ y"q#::zݐ'WfvW*+ _n(@/lYqNCc8g Eۢ|94K|춽{&wۅS)>槥~Avǰwzԁp5Oc4͊*.xn#qŧ1XjׅM0o[.SJ"yh >ul91:U?qNZg$ Z?m|ߓJ|jIc%y4GApFM"LJdi0LՃs=JL}}S&%2Yx,˲yMBGX&0=yhBV os< T\IV7~0 P1r$&c #7gyOKd*F.N 6+:@LtkS&&eoo`p)=س>h= kl@I5DS7ـk@M14v@6PS .OK_j͊DpeR| )҃=ѡ| )l폭1%!MN  i!9\&_IDNq1nFØ{7#F\a̽#0͈шICYca҄hMzR?b7}u˯-<"~bM,춽fI{ZTK[߬2}??,1f6cpqΆd 'R0S7|&3 i@W}>5QHǿl:`2@KS7JNGɩ&3 i@}`<!ԀTx-9J*]49pB~iFtWO^(9KHLs5 CsB/ _ iBГ C~/9XH5 >l93J5fWU] οUUm29LL$)=ɜjf2ߚg=G ?™N6\()-Vp'W=*)-w3l/.0\`7~B&{J҃=m!)e*5VCfR+OO1+H'/p]*|YqJSJ m0^π=Y;ׂ%FF[1FF|p_V#jl#FiCZFQc1ڗ).|m 򢨐ݫ6J2ЋzB`&r(Z@ֲ~zOql,C]m.nfu{L.鏘>9+`d{>u0^N9*&ȟz/\4a2oNS1w_9iAUqě~g"T _jVBQj%9{TJlZjoEE58y (mJ6_? VPf/W@,UIRP**g,ᗭ1Qo'\M(̾IQo't S iBW犿VCW[ T6M]=v/\)hVwQLLIP0 Dn!@ PAXA~wuwOXA]]E@A*4A% 9$@ 3IGOQ];׋Wfjީ OU]-nj炶Y@80~TE߯vm ]iGO>ۏ.~pC-[GAl7qp ?XCĻB~u9߆G'lB'kB=A'qh&u;^GU93ϡcb7Yo 590Eg7.u908.P 30>>j_s>}&c`+Gޏc7 nsrwj~Y[w( c| ?|nTl*>&<}mhZ wl-),$Ē`% SXH[д#mM {#<",Xӳ{?/ rs DXX)x[4BMs d굇s{<6$$%lņ=LІF'22`KqrD+aHAJ| a89S_nq6j ?#ѷnuoٝ^[Tj[7xvDGߺkJ-[vm'Ifѐ[?ǡsm"$q}]b>kH}ԫE^|"0y.w1Qo؋@ L4?ܕw2Pm-KĪAJɝk?33h ډމV5L]SWx/W1|p0QTCk1mKbZc,z:r95/&߷3ƽ:皑 fk[oVycWhlJt"敐Bz~h_O3?yp|{q51f~-utQmnQ`7*vD@Ŏjs bG bG]Qm΂ɺ񇑪-&(YpD\R|s-mGH80~-*4]l9<=k_^߹do/'\}cY7!sM#x-JEYi?+-NXe kq8a-ΗV'0kHJ9RuQuQuQuNpIS!BoN7xZZ#{_tߡ z.^߱"s=XFh@4 X41Qo$o o!kɤ f %90K8z};?罦e4w^Q :7fosۓZAc^W^xn .3啔_;U={q.t%E+PAAcm]=v[);(Ocy%|=v`/.ځ 5_ iDo1YZΟsG!&6u+V;3=N1@Z=Dyc~_"Ixʋ@7"ͧtºNX7 BCi ~BŏRGP7e—tUk湣%;}^D /NwJ1Iњ !EF$+k.m,/tx};95=/Po 6P{62b"Fi@ʾ6R#2,k#7If6rԃSG`Raӝ8{GY7l^dB6SIM5hG@m3Ǖn306&Bt2ok1q׎QÙhaqaL' p8&sl$}XQU?Է7wޅ;?ŏ?am<.)bpWD%槥?` ;pWkbgX[۩ }eT1}SFïڜd:1*uM7v,pV/9cg˟\oןDrkG|Reˏ|JslQ~Fqsl~>rmo7-nާ/ h{vlez.~[svR˕NԷuɉ8%xպrv"qzB69.&J pyC0M=dFNC%mIfqyrKNfPLn2g;n 2w6n†';n\ezrۻDevd9iX:&^ *'g4a^ *GQ{KG~{#r5a`OL_4&2+3o W!Ҝ[Ǡz?#~3 ?b"VKÔ52j~U.? g}z4ezuOfţ"?w''وf2Rpڸgtܶ+h&<2j?&V]w_ ڪi6{X6]R_wpu×4lxe뺆|0~;Ʃv7|00eI-b$̘u/zoA?@N\oD2{VF$gEJ\oD2{VF$gErF:ܧ7H+Z@٬dtd)50ŕ,?[5I05[?ݠ? Wκ߳[ xX~K56:U:!=){f?P_dwAEFk R旅Ej k߉{ 2sf/wu<??z'.x[\1v)Z烇1k#""TPAԿWTI˻|pL t $dq|] |]t/uJImT^'p>x??z'AaZ2zyTez旨< Y }L*U+54#n)+ ؏]/Kc?6JzHP~mF].($#V~myu̖[s {DbPx/}x3g}=OnK6T ? iؽ|i{^nߣj/8;nb1iϠK +".)RU 8V3;"^]1f1t_8^Ж?vEx`yccWZ@4kzQgfegb/l57v ,k`ThsJpEҺU$9C*)9 UW ';x&*Unw ';xfv*U.Gr54HLydzWW5pӨs: 5:bQ,y%U 8)*Az `(_[R4f(q%UHwufvJDIu;QR]5RC}.)+SRh"6ZzJ2bh)899޿Q`Ԇgջqa$OSLԽ0a5]iY]aw]0}_]'3_^b7wϫ"chBN[o6XyzθJY@Gʸ 'CCN2.¹H|%WG"^(T]+7EY\^.Bt3ѫǸ ]:z=\j[BMG(N`/sńa/=ZQCPW̺P> CBBޥ3N|sXHwM Գ!!.#Qjñ NX6@` wEeK܍M0Vy;:^w3_&FQ9 G{ߕD;/:{GP_KP#.w(^|68\P_ڀ@rKh՛x}jxM Z6^)Y7Z6^)9DWJ/6ײJI+|_Fߺѷn޵z[3N1xnsk.uwtm9:^)]iނNނؕC/nd2=nO|ڳȇ 6.=6A}-n]7R;Ө=?ɹx(7eA mc߻_܊wm!~KBh}T7-L6ۏ.$- bu OチM$uN$L,lʰUχeeb(}9Z\@ym4k E+^SmxC2togk \xAKBm@~W1?K;υ_cރX?}'ݐ8' {}olxs>?_ʐ*pzy;/ (o ߹( +?9W7_@CG\ ۆqP.+5&쮐Ppa(JmTPA"|g+NHU=Ä1f(;,yf}.+c\[z7R2TqI}r_* ?C rYh'e|.Vn,0 !-//g___ Ǒ `"{\VB~hc 畔 1o/.û/ZEY00~pQ#D/q0% K@IzH+9_JC|\I, T6Ȯ=O*vT9:0._Ŏj7_ŎjûWڜu㏲~/k<+-γ2j%>%>%>%>TGQ㏪f3Ye"6*&`,0٬0*#ݙӗ >gn6Ϳa{/s)zvfMtLI4T0/>Υdk޶-qr֭>w2:56F׎åej' øqHuE?greˏ|Jj:˖gH$7XJ;[^~X/gl#3v),sB-u:3ðg nVVK0mm6MHH-WJof*F''rv㬫8`XGk즩Efbmr\4g7uMN֕*8(2Ps(?{odz6/sLĄe#ӳ2;2X^ ΟgrLΆi@?qIMLȳHstYgucG-cLL|P j~UޑiڧjO;w@b'~3QuڻғlH>p5JGQ)3YNUW TWsL{ U^-ʓfM$U~DJMfU'#\M97_og&uQ4 8F1@[{f?=Ǐ•n얂$Vq(NpUNHOޫτ=q!|㏲MXATPAqriPI]r[%ggv*U.Gr5;JjVk Eu5IrsH>Z}4L& 瀹7*_WH#~]"ُnuu_ k?L݀rc_~ُQ|91/g?GQGv\ے1CF+/[WA׶HȏޑxQMu}yRUT;-uYi Lj؄}\LFK]V׮n.hꍺF6Z*Ɉn.ȇs"HU;q9qbzo?5pHYGoO=c)Ѣ[Z&xn=87:Z}u+Pu :Z$ ~h6XQEb`GF翑YB/.˗YB4/h_f 0a|%hC IPmF q`jܴYI*nf%6;/:{GD\PmFq`sCwIMkxM Z6^)Y7Z6^)9DWJ/6ײJI+|㏲~O&,!e#.9NRCoxtȃCF|ڏH( Q ;Z/@vF9_hrYG ks^ѡoPRc{Z).Lr.ދO^0miJً%ݺ^%xץmA5kP)OIg;,xOm)y{dK?iִX/g0T;3Z+0 xs P\ 1 e۞0w|lJm m(ZUT.Bׂ6atS))_|\\z~5yZ\k^W(Z\XZ/AQl{G;c7#WM7ht{bFw!eC0/S~ee`U<<OP+v !LSsʐEPs'y3 Hm\]Id7zaQw^&Q"6Ε"pLgwRÿiSu]=?|ѮGNnWȻە{ ' + * :ࠂ *7xX[lHم,$NhE:l z]k$=(?r9\Y;ZcVL]ko+GxZ[@쐛_E}[e$ m 4^~ O+)0C7KVL>=;ؖe(?dNwi)~a=68.:`q0% @ 9L |+9_J=@Η0h%>L$|R"{^6jGUQm~bGU *vT% , ? ?*pɋT Ϛ={r!&h&:`-gb\Z@rh1~VZ.-JE[lĻZ #vtt,[Tgt1>o;g[h+=rg/T|Up|!Q\A4Eh(ЭA;r_/<&u^$?h6}"kՎ{\t#diW\I$hSMB{ѐWzj[  7:_@߀K|}. f;GYG^׀|2c[[τF6a͛<VnYBUQ 4]8tG>!Vy=|gzmpzy%U؋t'Ey MB}(qN[P;__3  ںy%y%|{qf_rf~-߿DGQ Gl~4 ~4MX;+mGl`Ի)gCgݗ*f\җӳ39V5]#k@ӥ?Za} NYQ ۥ3 $5a]1qlNE ~FIpH&|=!VE.%E76<_+l|{&;hhdnW|n<"])Qrw`%#|;asDǃ'ۉuh$w^{OnqA|Fs?LMC~uNO~Ty )fiع=4M8֛&2>ړѬ^ofH'kO-қ*%!S]ATWf#tF~y7ۺo7& ~%# L\=\;22]}vZ!aaH )=qeF{8Ebdz? H؏754 } ɉQ[rJ拝/x\~P#,.&#QLE|,yi[| 3-.Q\ h,Z|``.8#L b%c k!FViHez5)R^=02Z U^,7L;㍏f0w:s'A-=m;Po<oXǻݗ$uҜOM~da*/ )Y!rSy4fͰw$2TU1~8>]:S{/g?*k#zc$$e/?O>lNr.>a;Adzۻ7R3 &wSV.ֿM } j4pO_'n_~,s8{mmmMHi,|Ymlvm*l:K1axї{^iD,c5O+ oZ?k?M΂;?l~˻?uwr{'i4_$퍺FMw| T~N/mf^Z/̜wXs ukkqϧ[\~ý߶m Ǝnr.8*AR=tFw71VT.BF Noݺ u9TƛJ~FG\BM=NK79\%_O.z90l\҉"嵦eq'}\7ڏIܲa~^} ' 7ُnmMt^v]E4/g?M5xzK?]5_p*3Uh?UUu$\h?~9e7]Lap=,)V^ǩ+㏞Gè"`k[v1\!ŘL~Ys"*QP1 k_Ž*xݭmzwY}xLohB6sDd?iԙ@RoF޶{ Ikb4{-Vڸsyrl4_.0a諯.FxKPł;v;<46KՍVoll$0Ah{zIPG?1|F p=k?g1VX-fAehk.")q1pܨorJ/yNohaQfK>W!8ܾ4-q>a74"HZkHn_8[oBkC|Y}^kVk iQg!̵Z{wq7O<gS|Y=ݧ7<2a iӝ~F\hp<~j ~Uq$qz$=yLx7ҿ9547)q:rKx i"-ebOB~.54K/Xю?o n8p^۲zujͦs^Oj5G?qfGyuɲ L磽h13헤+X|7RIxї.5m/h  .IDATi{R[i+LW]uRM? p:}Kkv08K_ay 7wb\w~m~^-_ KoN~%M$"۲3`Hc?1wo /}.\ߝfc~ynv~-NT^<Y17e5ugWԂ1Ul.cv|tHLL>:˙U1lL-đ*~A1j"G-(:S5xㆢg*O!-BCQ<>?Egcv< Wv|Yw8n:z Z<8SYL ~b(i;n DOiinE)dD siBƷQyR:uGH(~kڼn k MZ=?t M[Sml3LqQ}mFsCVd3frm'86΂"YJHg[LTِfS%xŝcA|PeIW=bOL^f$6Pn0mF~`Vkڌ$|݊uo,`n{fcff? ?B#hې;;Fv .ez?ϊuj/j58qU}T_Rz*pD;zwo>P߹-Ե?K#5>>x㖷䗯ubjDYgC/gQ{vUjw徨Xb ja6,x1PTyX"4;.JyFl6~7;䏂oX 5Hn5療yg678(+85ɹx#)2n!mj]6U'9--Q[>X*9seHIH7o.[/S|%%T3rm.&ÿ-$4~u2|CbGX̚ ]۞O{ NfM2|++UZov,obv,'WIL %CW~d@p5gbw7պ"aDg+TV8p5]/D2dv3~I+rK||IX#_)Lr.=$b+r;yj_y47\Y)R`"I?j9T_{wCgB}z@êle/ SWn{lpt?%iiR)BnԨ\*/^?_}3];#n/~{̉vǟO-`Ƙ%w)'wrwJ|-w͗TⷶWISnTSQܬHNZgKr^%~[+}ܬWnWfpEZI#hA<$Vy#쏩ȯH- ?4[ɧmv[v1-ޮY00~WnQCpQq)q, l >^Wye^?8&¥$E,I/?~~ӯ\ ZT\4A?'6Jz'~,-\1Cse`Ǜu|Np{.s8nq$=Ve hqGʀVRh(г .8#EK=Q{xY#:2mS燩 }$k9~X8[u0MȷWp}UӡC%w:PLl5Hn{+Xm}ٱ\zM̽>pȿ<_^M'H?xJwi9Ok=C7Lu΄v$O'?RLg s񌴌3ZO^>7sJ8SFm!:=G,w2Fޮ~ ̂I*_m_\Qw;Ѿ3LV=8֝sD#M$Y"eJƆjwtYLjϻZ2j@}?ʏDeJTl ~_t)Q3l{9/ ePو6U7XЊZh9WFsl{9VhE5oC'k?wl{9oͱ9+ڏW6m/?gB;ʦPb:RLg4n ^i8S* ?8W?~M4-XZcg6kiR?Wͪu}dp!(9}F?]Ԅo#fwnz mm6"Fzd\G#Ά9Q<=q~b_DGl~5sq]=NŃFMo#f;}MЧ;j$!0/_|_C>x[a$76>?m3? 6ĶO(Ybp xOR_K׌ꁉ]q3ۆ_߻s`upl@BL' )~= @#=Ӗ`Sqyr=bn0ٸF6~KyꋆjISM|Xr"wǹ/ܱ{5%:0Ɍ|;ƋED?t8{I\qc"_sf@P~:/w9s`Ce!(yyQ1`ңsgOg+rV2ˋ|vU'*+EU%IF''r䪫Y,/#"x[$gO.*?6q =59rV2ˋ|oPHf3KJLE9[Ư͗sl5z3,%)!قdpya {Zz.'ٌ&e>Z]ɷ+V3mC^)1/m$DVS׎OEXVZ&%=f06i v^ޓk/C3%y՝IP|!a%Umt^;{߻G[Rb4CN P@+55@Npb=FP#&Z8+%.ye1XnssLնDMΆ<BmF!O Ʃ'Nr.>!t"IYEj3a`Ou "_l["aڏL[emTc6#gRkkj`LU(OϘT&֚ avZDh%.UI$|wcn>r'kMjUٱ$/ٱ۞/᫦ c(&. < S4pI~pQb"NL gFUWj$'u!Ksn"bDlZF8eb ­TvLߧOfա R^=E2ayZ-x.LrGUWO>!Ilo~}drIA]Qҍ>ԥq%-*.ԥq%Y(Kc?6J*Iԥq-@{&:atς9*;Q+7&yr_O=?sbYKr0 4^ Zw-n6N_ޤ)R̝% Ѿٳ bWԧߎ2umOFJo EoZHK~veˌ~C^b'ߧe u0~ފf !EN/EŊ BJSV.o̙#s|!L%k J6e29%g8 _ϝg3rꢻsn3|q8N9T۞o3;ׂFֲmmD Y˶U[Q꿂e۪ i_R9zP}:Vzd{ĒsǪo^F4$Ib--ܡŎUdܫX'z;\)s)_]-Oo;`vE'VTZ+غl[%~[:s^uQuٶJ̻_~ߡuhٺl[%Q 绸6] oeۊ'Ee5NWFI1?$<e*>ȅ$W/$^]j\8@xur$I%|S{vZkN=$}u~-ep|8K#G+?x gn]Y;e೭e3?ǨkQ5hH6,~|$G"4sg p A7 ڲv{~[5~rhTV콋`pk8$fmW%9~0B`u_ϝ !Lw#?BCgVܝikkI;?gvˇxC36l]~fś 淸[]>dfZg5 zGly( w}fmGsLd,GKQhhn8mx~6d\(X +GL\N ;GCF4\Ʒ+VP燆F -BUe1nAmC3^[C l8;[{͎0%-79x[9UO`8|x㺏0}xIWz뚝 Ӝ(/iJ@}LOyIWJ|Zb͍M`)`76??*I;)0wH޴RŇV⏼̹z̹:]P*>?240 *C ~nޑ)RLFW/GPH\&nyKPH\&nĿ"[H\&n_2HPH\&n#fgI E7[mH;E7 >i'p9߀"Y|oY᧤LF26; >qTmFEh!?#ru:_.'Gl'r:_@ Ir=_`uWϘۯ6?fp~1SOWJ¯rMI 8|=% oAx8v=|+̎R-ӅKX?iP?kv,WܓS Wv.A/(S p|%ja%Bkj6&W ޯz~LMFZ?8~9v6ƿ7iϜwX~k4 m&( ?{AWjկox=HUM7q|o' OݧEhZ浨}$=)&SݧA; pٯfM64hf5 4zBhfl(F3լWee~5k jhSˢ:aǟ5̮_7_85=/R`mv8mfx {{5iw7b&c ?2ϕ!3,/^404w}5A$pz" DwK|啔.̓e|.Vn,0 rC8[d&_Hh?`m4?op;w1_r Y0P~Ac!d3^(P9:p~A~Y~~_OQT<5MPpM Nq3X[d_ߴ`?eMP^A% fV2&" ,?wy?Us6@^I,>b77LE9༒R/}d/.w _r&~΂ɚ|NPʃEzt}NW">>w s5 rS>s쳼P?s6~A|F[?wy?M#!)#FҦˈ|ڈQjɬ|ڈQj"'5Ijt_lp$%[2MX8Ys?+ڋ@ r{d:@yWʇ|:@A~jJJ(؋˨ZP(Zi|YڐVˊֆ:_V6%YQ8b%[sh-9`V4Xɖ0+GdKrkKl}x 4&I^\֮[h(qdrpWEITy"-  k+)͂'T^\o/./ZEh-|]YhW//kvP]4Ȫ?G rvN$+IQ/HRT_ǵ ̢&WR#T$ًˈ|@9sg~M%'? Ì؅QZ*;OԮ|s|ۓM/~{/+ە( im 9%ZM8[YMkK(/70Ԡ"RtA~MVW uNgK+)w[BkKID3wB-9~*ԷYBfs(eK"K,I&  ӷY]{^n=/n7|ϋM&bۓd۬I;{1QX:_=o&5]3fպZ(ŏL焟ԂNtšQ Os)&~/%$ &NX—8NWI遑2f_w={]0uHV/wJso,;rB`_GS3p n:|Z`fAX?Z}N^e B._jЉ{=lY`[uؽf䡗so՟{}R-̗ 3K| lS_}/7@(8%S.[KR@'U]T|$3II-m 9v#_ңT Оy_ 1 TUe)k d ĽM+ኾi{m޴' #dq_(MER< w1ԦݧETbm ჈,\*f <سqMᔕU̺in[nD OU/ 6ےR$t"/E'' ޳F.]O{"fl`@)!x˛ط B?Q{j8;[# K]وLcҙ\NO̽O̽{71 y@C^Kbr?$etP-f(38RjZڒͦ|s(#d ?+20 x(gKg/?/?Xg.뗥V|/ \M[ZUOoOo7LN!9|9|!$(|9'N7e6{ {-Lndg/Ģ%er5SM!!Y vHşlѠer"?{e%|GF!BOc?r`LU>ȉd?bmkKkKJ o^%Z%ZEJ"΀F@1n^5l9\3Wt]V/g}mߤս3ED'ae]_xj1u\XSkK _wgw*>ڼ'?C`)ċr_1MYxɦ8ĻLMHxŦ˸:SV.6M_~'nnͥݞzQ|2&M-yqxǧV_.Ca1%F]b8~.t@x0Qh*Ɉ]2㏠ֶ|V؏DEw(l# '^s~"bDOscT;S؏]pQziIIv'$@#!6TCE J7h/ ?+/Ɉ5U=Jv ^+ځxk jYav ^+V+ Ý4v g?L7pÞ4x g?g퇔g͟"- =ͷM AO5veh%hR@rvT^]&  ؋xc4) c8 3 %@4Tq8 kWA:'b%%=ܩ.){RNWB,& ?F>H;Hv/_PkJ~漕GN0Cauf+MdnS5 s0/z2UnmzwP\q 1FX:*N}l=]|f.7NMDzXL[ܨ)aё ی|!%B=ی[ǃOl9WdPqTI@h(8s+bF7? <1QpWWzcg=R>Ǐ#3#9>? ?u l(;9࣬mԭ-/.}¿su*2U4]#ϒ>_ѫ߀1ȇ >kz&^(>QÙ |\%$,td uUE7սzvK:ntgA⿶ezu[X\n^Bwx\N̳-1=IXN)+oZlI5I’gtbM_>Y7-1[O|4?, 7?IX>N7ZI’gtbd[$aY3^Ng8p!?Hjm5[Gr=|7Hol5[#AKc` BL͈Lx& ~pѠ&'sGjKFNk#'*0`سqĖ鍜 m!aD'>9˗FNk عb5F.-%@z#5Cۥ:'6yyJl ȑ2"~qg~2u?û'e4~,,)]QƟZ,7PjKH@/k/!ru*.ZB|YQ׸4 *Ɉ]Bt- J,WEh!?#ru:_.'Gl'ru:Hd`-ądKFq!ْA\><ɹ!>oz$b/>ozŸ4{ÂMoգow^o|}OŸ\]E0?[JPJ J7]izJZ>sa{+-Mb[IޭeijB܉[ŶBcKZ/u[Km–'ɑ*%V h ovo?CivFX2꺔>=Ի]G;Lp\W1Oٓgb$bR9~}jÎR}2F2\E &u0bcSi]b+T<h8ߗJ3[&V3xyLeZV8ޅny~c!dD{-8ߺwq|9p5(j3esz~>\. \.lɝ(71 y_v"~fۊeQ#8n|5^ ],K5^~CYv4i*r$1~;/-oC߹?vrNtšF?͈9#Ū;Q0ř*!Y _DpБ_iy%N6jۋ6X?sİӗ4Vna cH39y& }Ÿj˛^Rj̤T0/>ƥj0р48eE u+ϝԊNfUYcc O׎åԊedGFߝ{%\;Hc NY]3PZ>zU3`J6CkU;?SkVvV"-~VPܓ6$eތ0KdCrcGځsG%$g@*gk%$jG^jDڔ[dJSPkh*]ޏWR+?<ϭ4e.T-z,L#Gvq('0'& /iM2= ,()hh@3 Ŀ"iF|_5{FJ}{Ӛb Y {VwX.v+#5*+d1XiLϖ vw~֫mvԗ+cZ?-SWj%&݊ʷeV R{? }iOvAZLGr8JՌiL%vEOr{7J𾥙y>#p6L ^zۇGZ3g)௠In/gң+}tn"D+{01>za fua_B|R]@ZWj4}m_K>MYXf.tq5Ex._"MVJ<#.{Q??OIFgiG<Lc?Z_j4Up#ѪvrDW%}"/_} mxn:jC[FϦNQʙԏ{_;;'-r` Osp!(.=I]H#Y|{̘;߮j):|ݹ]5uI˗b;Hy}~zaQ]1Kڤ1;n*Qz~̀7` Gx$m ER|%i٭+2u5ꔴٽ#FG&A(Yb% RDɒ!|?rC%KvvP!!DɧCO@7rn>|=؏Wr_~ʮ.)+SRh"6Zz>櫖J2bhˉn>pY?uYpYUuYJhfŚZL_^3_K4yQ3_KX|-m۾ pOc(o /f2y3CCLx76/^:d ዗y3ae@.c >vN2.˹>K-;WG"^傸T]BY :z .|M\Q| оsumD?Y/͎׊>C@/0_?F@av,-\xC@sy1hP_ȯ C1~dq!k4crI̎^ X#_)]|tFWJWh_)]! d%}(ȅ{?_.x\ bν%޽*ȅ;$K{U. k WeD@.p}ge}^!IyԕYnGAe11ė1xXr\c;C6 ]-b/0_RPw.steCq"SDFj6m][eDrZw=+hzVj$պYI$Gu׳HVgE8:"'1=GGD:&舜HDS{dq=XR^n#er|CG'9Խo~o~JUWOrr@Iuy|_C8~ǥHu}9>ɡm#~CQ% <ھe%EP|Rp>c.8,夏wⰔy_v2/K9K7_rUƠ4_{w|(.v߱톿S/3il1xVzlx ':e=Vu^*u05I|& c~ ~B*~3`Hmow3tiAORAt"szWy]dxvΕ9"kR~; _/OtJJŷQûBY0YϗV@E3ju|8aΗ/'Eㄵ:_8av k#NXN]hͪбX^:>F-_C^ں.~^IRA⿟WR+){qK ȷy_rRA~VnB78^]S\j r{yU兎}vC///n_?%PJJ5yvCŷiPVnQۣZ:u2&9G0_r!1P?TpV/-S0螛s45!%zc {Nue9u{)Z_X*.k-:Y䰖99]EyCukϠxx?ʵ- qYsݽ8,zrK:5q}:s.!-^i)WR[T+2yp}Z@NwiܢrL~6̨iEnAJK?$9>WRA~_aÌ*>| 3|.| 3jk΂R$dAݶ_m|*[m&#ٸ~q]0hs˰xLFsip܁NvoQgZm,?8uNWKz"~+nv 5if# f` ٸ+I<` 5T?{!euKǶ&َR2ZiXD Ө)O-ߏ ۙ_;?;@ $-C2$94~9@F@gJO#ݲ wI'¹jzfƚȀ^c"\A|zM5_Fb9_D,ZoL%ђ mj~^IZ3DKm6- ҶDteAz-^y>5^A~]>=啔mTe=ӓB#LTxZyY|;JٸFӆŅ.;i mntpmn$eXfOֆ̬^p 1)/? ӊNvx JLODK^| Nϒ8j21Ip64!)QUHsx8p Iv֫PgLt$$$I^00FGقhRBސ0#hG>jkf2I\usӮAz$j~Hfx:2+-m#GHSgGYg,ٸ׍!8Ԣ4s OSj4rl1rlt>s#Φ()ob_͡ț{tqľL .@e9g蕑ҚR ׈AX$IzF $#عF $Y™ňApfSjDb#5δ6YtӁKfE_F?^Ϻ1/'?V`Uw8"{Z- .:XSo 5x.8!NgL1,?3Ovd\%vlm& f=а4;kݳm%l/6­Հ?WFaa47O2ǽNK~!&pc`lc;یf<4*DRc*? O8O8u@\ ΓMX5G\lڴ`^ċE#:܄0ۆ?}z'nc?; لUxO#,~D>kqСc*Ο)+S|sT8_2NRiqc]#U}-b#8J4RQ|HI ueIJ~WnW_]~'(9t8+VOI8i#f3|u' Kf>z&կ0,U } @sυ{_lut@٪E ͳ w}M3MQ}=0:e=-3NJs}~`CӆϜx{f& y;d^N=$3Z,~c e;$%(OzP#%ePOZ!i 4/~t~t~t~t~ /9G\NV54:qt:f>'U67NWHaYRW--8^O#; ][=t+{|ysćZ!VtI?[+ i̶{Oɲ,耧\rf>/@[?%R9m|.۞r$4;_/p O%XZN?xٱ\pK,-'^"irK$ /%/4?ɹXWiz^0j]ȿm<'VϜmP_ *۶HyAr&~1 5$?gF1Z⪋0) E,pएfF1;Tʏك,ÎC 6֪>|Y5ƅH ="E]2Ba)eo:m$ߖ~9\f*E 믳wK> Wl@plqbhX|pd#H5=s?Q*G="D4I)+V=q$t}s|ӄyT`q7^#]%h'"Uh<oP_PkltMgҔZJ ̗cGtSspʼnk%,s=pPL×@:&{}6|]zCq. t`B+3q?3vԕzJFt(+ǟr|V«%;b%uI\,ﷷIp !qՅ$ukI?&feTsq1Xoڋy޴niD2z^DD ћBM`5z^VKϦ=%%Y:_9]Xz"Dq`NA;ԖIkZ-N+hҳf-E5Km)Z,f-Zz,hҳf-E5Km)ZYjKѢgR[-=K$~exubh7ٯj]xv+c7Z~eFwų_WnTigc7R2;~eAcO;[ᤏt?Ļ[v/˥Nl;_q_צIʿM =`\RC;_qTi?+ƨ:_z~>-)߽ʀ/ p|f<|P:IWn':|flhD]㰀/ V鑋W,TgfOr.C?:=ztгu?j!Aw)?gOr.Cj^>vRY|]|WAٰ| ÙsU6lf^I'IK.*V6d,l~1GkOx {g05o>[%~H&غA&_d"|·lS Kcwwzπ'9?@6[q2R;c̲*{ɗ dvƬsH~2SYLA<O+Ε!# FdmFӒPy`YckO\Y)R<ؽ-'~EνQΞ6?$%ftx a+1/af3\9.S/ބ3g Nrbt9.S?YH,K=1f3\9.Sprtg$~ZYLsnbډfr]:gBϙH׵r]>{.0&ftƉ*2`̳R Wԟ~4 g* /Y&L T"9^v8}Rp?(᧦5ab^92eܜsg35 ?.@L(xe~Kw%)6&x+xeڛj͔[ZP{7 WԶya!$bf_ru"._ڢm/ 㢙٩e^~/xY]9^ ?79^ ?ec/)4g9^ցRϜsJ Nž@r;_w.8 |>|_NgK;m"ux7pe QAkp>t!=͹kI|gmps4"X_¿׵|][wɭV`s> z73n7}4㴛?;ڭe'!uу^9ym(z\.ɜxS(i> w:퐞WwD>|_Ng҃wD>|_Ng)|M>t!]{5Yқ25 4zwp_p)%˧ybJ#I g(2OȒJٱ .T|UFv!)޺_򧱑]H *+ildY0YWr6"hFm؈@4 @݈E/%6_*v#mIŎjs쒕 -RсU\~eP̓;:Ex2[Į\=l{S\cq|2x2j!!9!-3 @R _}PWSd8J.6V&sk؞kg \*;gb5*שP4J @; 'oECӸxVr.Rp6:OTW9ޙ 'I %M싁RL':*|q~%3'|m%`~|,sp5z O \C/Ό1ygzRDBC "xgLU3@JQ9i?GRgB+|-0^ɔwvr73K4;3~sZ"ݤ (v,9 Ym%Ux;U%H,- Zُ̡AK)#*=wˊ&kUt\E~Z>~l"z5C6J{P4琍Ұ9ȅ9lrǰ} To?ЃSGp];5w v2>z7=;3eUM5hG5E3P & }'ŤMec{cP?2\-6X32Zl*3-.$% g"y?OToҙ*㰺wN|%WJof6:j9{ iYLo~TS˕"#HΞ[rVJS{2yVjnASC:/ce1aG|waa Ec8QvJEUM-/6xH-psHgdqE GBSd8#Rsigg c&$yӳ #l33&)Ά&$ev.@ӳ07ƆKHL#wao?1ёp:[4=~-HIZӳdn$ Nw~'mtz?OKO6:_RN'mtz6MqNj8iMdnΗ5~-ceb S`~ >-M&3;_"4f!/t5^; %|.vAKнfÖ) WUY3dq#0| 굳SsgJK~!&` YgP=.3 ]z^o3H]BT jZZZZZ5]}Fi2M)+k2&MkkVz&ud=凬٪E^'x:nOSfuOdA$-Sp>z&{6 xyf-:~'ȤckcN iuss6ۨ6<(\}`ӱu~ڔQ}=!c{@M[]؏X;^`mZ>K^`E>eM&V9څ_n4fJM}*8 Uvy,`dytſ<*57͝. ;JɣY V2@FWJvOCM\xCװw,RF^*k?Q^9&MOz2K[PY)=}$HjUC'NHaIj͍R'20k{t*wK ΟnHBmx$*8߂]ȩAx#Iŭhm8[IrS7opd҄6!_h{\-79^E;mc%x؏,^K0c_xk+8^C 5xex~Phkۯ`!*.Ҽ[G̞D’375Y}m;& W܌7B8LV Ɂ TP6vXr:cנe1ɚנp(#6> ]B  u[־؞X~pd0rҫ[}㨪OcVҪbxKt|*p/eؔ_ ܡ4~Zź~U1+WINxWnkgv"a>f%,<ź{/CDd& ۊu!?2:_g؃{dlT/}f4I +i60Ty_ +)N˄4l UQl"J$Q$]؍In9'겉 :]pT-|B _NWseOw-"MǙN #44Lbj - j^&Ft|d5/1Wo]Yz=鉰 o+8r ?ijwDm5ۤ_@LZ &jAwsz޽U NU}&9P'E7_>sIJW~%WX|*kݽ{*_kʏ<]ϯg/w{(MUdT ԏ.h/,VL$~rU!SG}ˍ|Q K.9ٯj>պJ/~KJ,gYI׏-x+>ID/~+>ID/~+>ID/~+MFg_MR!-s˨210._3?; ;|Ǵ  ySV.B4 f B_g|?`˦xFM_ٗu yTXLSs9v;4Y7V~lc㛨IҴI4 -Ѕ B)"( z"rE"(K][ ({[Z ]iMHf23$_>W^$3g<=9g9y ?/ fu}'L aRykg>S$}s. _'L ~_ɜ x.0Z+J.^V5'L {c'5Lj?cqWNzmyc& {=p'u$$o.#3v5ZFWOxSCi!uX0sYLrZˢzSƲ{ɮpCBA.ke$ l=ajq0VV Bi~d­!, SGyꭝ\L^y|vr5M 0d䳫`AkY'〃3SOF>%Npuឩ'ɵlqjunI|fKVȚ^Ke[6(7r/[`3T7ȗOu|r3|P N>gZ)N>gZ򬎓Ou|ֿXN>gP,xygP,xy4Cz_Wq+rVR*.~ƅ^'Qz/9{}W/V?1|pzj% .? (Vsc8< #(~Flu,dpc%zo=}fk !r/rIoyw-Z))ey%)m4i$  ʏvHe~n6e^묻l%Oy[ʤ!H0qܲRͶX2%̯d]UVm:d+QngY./ -8C=ؾ.w^JN>ZK|ӻqݹNӻq?<+Gn\k_eݫZU,yO '-V{U+Y{^6&VJ*/O 2F-e]]_S~mntt8snů.;zN:e~κas87a5>09_ɆeVUC?gCs+"`6ulv6 .]E>klǫpx6L&L>ΆE_U]}lhQ[Y]!7B&SC&S;ZmW^yCЙlq0US~=  DLUCd`kϝH/?H7X5DLUU#:=!C@-"*?8:K$p!&RrV'q0UU]h7AV>Ñ/Y`[8Q^yWː0 ԔCPDŽ .ʡkR]v!8!4KNHp.Gp4pXPY]N:0 @CUeR쯪.&@+qr)+"EsJݪKȬfО )u~a6 췘B{Bbc{VW@="EP يMޞW^y1qnT=>I_4E/9:-FS+^s_͏twqV@kru2'G_սʜ~:>d*gik }nq\:GʜQqqgrk&tNXQ2ttu3H=zkz^ zj V o\[t #}t >ye4^4{|)Oc'Qm"FvBKoC~o#MuhjCO?*] Zq{^+?<񷧣MO,;-~G{]#ݛ>1KиTuEkCbBZ[;se TM͝1,}Sz>^@ܞ7)=ҫ_J.SG%"w(E%(-,q4E0^|v>Ds|(Xm&Us4uC.7ىwb319:>&9fٻn l)M.#6eO1L#;|}Rz5sOKؓ-s>!kҢ<·X7FjFJRm]MH~Sͷm {A|:1aդV};*P]Y6JΞGh7!R;GYQ[tL0p૪ F}&@WsB{F!ڠ_qa+Z] mFD!>ξ-KEյ|@S["4Hy"}e;P^ƞlR_Bw=7yi=ag:_l҄J ;I2 [xPRrv.t*kޣ7'Sbd@dՙisYC)s!ɉ~btSvzE;7Y*ݴ'hmxtRi3/~tR){A̘OŦ}y]FkO4Zs(N/kwfsj/\%߬F\C+d!>P[߂R󽳩ϓ֡~j/z-[p SƪV;{{2pq~P[i{;/;L s>V/9CslϦaМ,w 7_ᖙwc:_ eͦH͞-p/7jRu،YIczru:Ϙ(6v@oDW;ocFwfO1W:dd=yc͹Jp&]\+*֠6  tZ\zjteFuz?UqVđ5K/@V5'85r˝0u7Nfʊkg@GxzwM-wMBey5ÓCh$'EctJU?s$gɮcȊ?ݱdHs;\_n~Ĵ5k5K~k5NiS_1yI}LlMSBSyyE=evX+01,!W`3)bYBb=gRz^QϤz^QϤn?\s\"8~퇐5TRIE)D"wRQ ;(?h[u \4'iC;—[U;oq7>1:w8w|q2US>|FN2j|6y$8LT@^6C荟QF&}?sdLj|eHYGb|eĨoiWBY4,#FyiМ/}q@,#J]]¸5F];jr^dg%eaKƏߏ,^l`d70Z+J.Dk Sz(C71_fjUuՕ(,F#zDRт}F7㾙9 CK0m]dʭ|zD^{%#9fj=0s/W%Q~sʾ^'L| 6ښzoR[Z|6spq1p3'L| G!GH!䭹^nZċOacsϓ͹2d>w0'yy''t+3jy-WO@n;J)b^1W@cCpd1s bl\;.tG-\Y̵Bwbn\&tG-fsd1׎%W@=_\2jϗ),W{Lqde+ KLϗ*)?WfkcgZ?cŧ:X> U %|PzOu|W^ɧ:X> U/>ɧ:X> UOqO֝?-:` 3/0[W0G'̶U 8:a-n+pR9_BL',%tR9_BL',%tR9_BL'7~gt=rrA72 uֵ9 C2H1v`ע]G=YgnF㿛>Ox gyI۬h됝S N}iZ^J!ɆeG'?̩o=}GVrF>`ye>}vk!?}r0>XsLFlu,"V̇4wʧƸ1[i1jQn)ux7*|9,j{_*K|? ,DK[t1ٰL^J/Op%]WrX>sgt%>󌮸ggg:`N->`O$'_[%>zDo9#]DwSDzsA<?W]?p,{#jW^kCg N߹Mo`eq6ATSlj%Y0|`28p_U"-~9p22ԆK ;DF_>2-h3Zf9_SǢ(GQ|]?W6>s.?XN:e~|eQäPP9Zu~?T^!UY]xڱ>`6b+ z_~2C؃_[Q~x~uY)"vSTpYWv窖/;qI"UpYW?QIƗ{W^y@^W^yWn@ vlFDv+id~U墥ԲBSjd_Ijÿf፷e!/˞V^J-+O &S-9{E-+O /`X2}rjY>nN@pEv~"UΏɔUIw&J*(c%O_4EfC}c9-U\@(dFoP,B{>{Ud!qGQeqh|:`TQG”mTO]vQ=u}+پ8`gSG9`5kڜEN)S*'9&v1QsrW%泭NMg[3ץŋ泭/"\Rv7?8;ϲFԱ!~)m2!gksYX gk~)mSa|5Bڝ_϶Z{; A3ڃCC{xesxͿlt(g6F&}\\>0r9?<>CO(d .;2s( ײ`|΄vܼ:<8s&VIם8e{qAs*sX,-!'S KUPv =_G+n4 q-MB/ FK zУID=$\fsz?|C_.?|^wslbQy!:: @H}>ZOw⧑}S3:a6V"#m ;u0d Z,hgtLF Dh?t,ˢt %Nb>@2C2W|Pv z aGh f@SSym(7!0Vy |/ECesePCКph~յyQ[߂Z\YE-j[WpFյxoa|q(ZM+Zf|q<΁=UgOqKwy5d3&!g-5]#Ι:Sao0:zr\A;5^xXi?,8ׯo8|ߧRIFB8R"a|HNı^GUNΒ<b wg Y*su!EKѮ_\K˳iE<$RfOwZnjaeja%[_?{ 6s>RQe2SQg&YӍ c ?gYw9*9{n}|O#I@^߆>IJ"bހښݥOD9kp\@WsB{F!&kQ8hՕrE9k5(:mumFD!>.<\ VPtV.^ǭD:Ab}Ǣb5Y>^ h!0OlƓdӴaػM=D4p.~l\ ;q1,6{81R3N>h B ~I~Bp̝8a]پ_@?wyt-)7E;7 Cו:Kus~9`΍/"sX~xSR_0E ]S=_0E ]GY^w^Jrn|1tms;+pǵ*@YE;qVԲ6|= Xه{ m| mOOK]. jjj%/L8|?u0+Y+:]&T[I ޝF_2}Ԏ̀ 9ԛ搁@lr6UO.fypzGi}|"^U)V~مҾl|M+lxlPS]M7ʹs0 K( e3iSo֑q2J kPo ]b_h}):UQCa:ݢPsɌEN ۽cuW%~w /t/~? zwj&ӝ:iNyeR{NwqX2}95T/"K_47u}qxinZ̵[a51c>=?kK gc!e4;QT5Z)N/k=ߴpovj/\h7kц]f/dM#$zxk-p6%[==L6\XB4@ v:']o `̅SZ3l=a6G*sut'$ >[;1vZjf(etL^~Muu~v1"ZJvEcuv:Ǎ(cNzǏ/C]}t',"͑/ɁN#u8_OZ=ݟݓE||=!,nťԽ#Cg9C/:1),8x_v8 681D|=ޱ8f:#<`?_Lǔإo S{ U<ޣqdcqݏ!OB"%'U\t2Џ|R%~DB "Tk/8@|0I q]m۹L1у|PSD;O '͘Lk#\|Ok#69ԏE} .>\~4d3s1:_^˓|]hg'(:XB~0Ǔ;nţq]?grByiw5y}msk|! vg&c=v7Tk %Ɠ Z "xخeS[ z1lخeSC & z1lخuݟ LFI'?^e[;ggsy!-_Ʈ@ ߼ _6,[&+moކ+?pl#?`y5(LG,CLp>[;9ˇ h6qDm,5@TDBVݬ= +38Eg.!=+|4tȻA=i8GYûT]߈K3˽B2 VVz!Ļ5o1E7luX"6@ߧќs~)uJ:^p?@!{8 5?qd@BT1$DZ?N%ghZo_ n*sudL 䳧1 9KK,l"!Xoؕؗ֞0[}AUca k*(%ghTm{,lEz=Pi8J.4= @fs>-X,|\%O+w2١D1ɷ:?Xgw~/ʿyߕbݶ~]TʿL+lQiI&}?~72qn}֬CGBsY˸/ECW(e\U^Ed $?7SfW"Zz8%𪸔 ;0Z Ώ*1)2ğ}@K[;6mzm8(3&3*z<0A}\_sᠻW%?#AhL;P~/6}D[#$/gJ Ggy|PckuH);ptf)4~FY uGsƽH&h_fikɈv}KsC~JW gn&#_[J{JgLݲ~cw`qW8P/#eM+7h Gֆ3ҏ76ɈUhk6RzmXƧw>2/Ȉ5hQzhͫT~,)b]X8SOĻaXg!O'w;WP0Bz1ԞH{]#v|D|ҋD;y#ܽ4y-uXʻ{;(T\jmlQ8ۼ̈O={W1seC_c?GHZ4D"1#$w?9 qr\yv朆8vl¶[5˦{P!7wڂݏQK/]1m22=\.bܼMfug/V>j~P+'ZW5jG݂1PP?mU0 ԗ|ٴ|cs5}d\k1 ۂq=1~@/e*N`C#( ;'X؜}ň ;'XI%6'l`5ROl"S5ӟr&">[# }'clNК|D$ܧcsvepzɾӞ/c 'K1z0Ny/xXd)dԞ/u{3,c&Qg8Y☌p1 g8Y☌{?vQ?;Ӄ&Mo>qW7 aa)s}޲1⽪]Op,I>Wղ̯_-?ٰlHϽcg_6h6Ο?Fܫ3?x};Fs|ӰI6sGl%(o"fЇ&`Oԭ|c6F-%:et{adXIӣ+cm= $=N82=M {z Э6l'{ϝOO_6*E{jxFXT11teJu:aĦa_ *;5o3ṕ14"erx_Jt[OT.}?[<I'؏kB鄟3_J:{;)-^_'*aL~( u9^ %-8.s8u[8ale/?/?q8:E*^PPYWa#տ~,GH(1b.9J|#@!9Ĉ,PHOѶuwj\56z0 EE$ߚhh-8\[r ))$1?!bkcn$m?~qmZ Uڴ@6ĵiTmk҆ AϙZXz pq1Qe C{N@2EZ~r"nPNn$lE;7!˷h*j$6ᐗ;gikR/~N-,?u0ܪ*Kӓ>?&Y{ljnBlZc]MMmY&g=nfle({D'Cf]ne\))S,-C ʴŮm!WȹsU)oY#C@f'vnBMG۲FTy^+D1QC_8輔:q|O[oI~򃩎;K(oᗷ5yskpΏJp?m22o_,{U eήdmNM^wH&n}wlK^|x sڋWpnwݩ2mJj*NwEQ߂ޖ 3*(0WjZۉ N.-oRZ_7µ:+Kc_ଫΗ,w#9GߣɆe=h0_NfL&1E`yqd2,)y]w0a'H$r>qym_C_qv? ^8L!Imp IKm>Pj4~xãɆeޓ@qH'v<-1 ˫N*yZ/N-*s˵o._Ǡ7vf=Ư0 PZ{)EHf|I/lJ|$w dx|i46g[ e+J.d&oᗷkHHz\ݾ;'H4b,2v`}SD\eځG~_iSy{'ctsW=G5h@O ГOͿmp n̾F7g*=AwwP`̈NÏRz7ho'~i%ˢiNIzFYj}%]m?~ݚQHl JT+%.cRR&SPIl0HjO'ie_RdL x[Ί7*~v-g >;~)y63(][ݕ~5oч&jb {{w5o~ζuYo;xh]V8ۊA=А+l+D\AՕ+ʊHcI%] *+"%rOU|˹C?]&È۟QpNaķSRSr,s̭LVԤF )/0~+:^<@?+v۠szz >K옳uw (>*#c.ANSF6< @]l ?gGp/~($}ڦDmd<2LA@[S>c뎑@@DᛍOM -Ӏ0{ _i307B~ ~y-Z^m&y4|~m?:^TyGO8|_ 8[O/9/~:otr-_q8?v8e֩U$Of:v*^u8{)n'G꘼ JRJ9檎XA4e`gY~]{>|D.1j_=Rekwj~O󿄳eh4:_lљ I0ĈpLuMΗ*ptmrWj|gۏg=r8#;X T+BByXF kA m^id8v*9"ʼpUdIgc9bY|^>OVaZk ,6'{hGN{l0A3iϗM&h|6'N{l_"Go:K؞(?'ZMkg!<ʷVi7W\JӔͣp''=[T&~ qW&[3'ݨhnU$g2W' G=!x~퇟m?|[ ?'wHQZ:d`Pýyא\lFU0N~N&~Ds˶P RJ]cM.%WJ*YGU=m7NۏYã?zۧ;5q搠k|iaAoK\BߵdESM9+V8<DE#>O8a62Y3DJƯ\LsYsTW-uM1QO;).Z9KK dJzRje.^;5qÕ{+LXK_:mb{>I_4E~yۏW^yF9鶹]‚9gGz ̵&V 'LeK76-xGW%IgMl‘%6Jڎo#oᗷ~ke4 *|x>B8b qwwI {H)T˹md9KK~6E;/袦eX EU{vO!A{_lv\6qEVJgsvZX* k2I\ɕҒ/])1Axhl%Ǒ9eri;DG̨5E;7I^tG{30ơ S3NFdn)Kcܘ/ufwh3chֶ㮼_/spX&Xksu}i3܃Aqk+s7V91^%;߈OO5nOvalFm ӳ&JF!]v[ܦzIN7V 5R#鋦}K.kwe(bnj(HP4im?vMޫC(M8Pݷqg~/lpq=G;']?WY^(76#~T}x4>6S' c{~Tߗe`[qnZ{*0Z#v{DjoM^=wp7yP}tYuxZސ_7?&y?u0=eyě%4}*oק߾Ds[7L',\0i? K4xt|:0䵜!9 C;,qp%GAd2aj /쐼 w[nz{m?|^J ^9\n|~{~ԵM?OV n9 C^\. EՈ65{]\gl=`&=lJ ;`]Tr gf?rB]PrF uND:-M@Lz< )?9Cu J,)~m?lXv׶GcR1f3zm{fE^"ww|lIݝw[dVh?䜬d@/I߻:BզV gk|-{]Bq)P\ A(WSͷ [[q+ ` NG]ʜ!'ӤW)5q]]VZv-ZJŪBUr%yUej,O_ݴt˪kZdHc)y}߬I=:P?gY{.I!=iRyny7-]H~kq2|h5< &lX$ԦV5[FU-WG{q ^L8QߜC;ny57GUX,VY)epXm28,|߻iNtAe9Mb;iWm~/lٗZvx_Fc_3gaVw1{+-sעnYl?݁;?>ON.F^1{MK.?\=2~~JIQ]5ԪfA60y4":}6(*X9sUZe;@|g'<Y+]Vjw-Zi7JW]0_,K'ǎn|ZYSG<ͼ.NnZJh+&牷Ǻ4X}L[4]x ;l?_|<~>8膍?_7-]KCl?l.'ۏ)ڹut?W=%~PYDEv.<wΨk,sq!uqFZ|iZ vWx "WW9j!@8 ܕPiEڵhe9l,L[́o67m Yك`m|#:fn9(F濛~" ]0Oz  ʉۏOM7IaILۏOMO7I.>ۏO''n\|'NO$Ql?>y_daM; ǻ~ ,-N70/l?s ' qsGn:&{,-w=`ϓR..d8뀫:&/‡ԭr??|/|/@r|X~+Dӌ;=򝫪c4X,~|oS!Y*֤:&:lZ:G|bV~z/{Fd^G/ߩ?ȇIYа):!4 ̱e*G]P F-!Zǃ!ƨWh;ң|(*s1.5manm?~Օw5LwI]ׇR?/I| ,z`ѩ(QgD:G>EDRzT0nY*su[UIb9z ;T_TD$ f$\6R~m? !7DTH~1:_ ~?s3=b=~z[?Ҩ1bGTtYY*=KU/j6U'k `=sM [)7ۓm?Rj?>5$l?w]b~ĮU?q n81 K%cs 'YoaѤԭ 1F-[ *"Z/ԧɌ@kkV%Y rq~=z-;%o~d~O]wI~C?qr U!%oY [ p#  XøzBm–@c(N@p&Kp37X)TՏ7~, h]#m?N#ӣ/?ėbg?l*߬wV_@>_'hlƊ>ƣ#r'|Z }{us-ڙ5MN;tC`cX~'A|meI|6_<|K @~6r!|X7m @ax|Ewuj^{+A C?"Z(m?N#ㄯm$&?&/8ŧ}KygĠnBohVxE81|mޟC{GCV-廦S|śpTQmea\]FLcNMT+&3JTpH(ssM|O~o{&2U>f86nã{OhA/؊KN3aNX!f~Ę(wA"[9&fJ?2l2S%+*(eex_rlk?=}є]R+N+AYoy+su$3l2 giIS긳`!ZS KIiI | ɗ~!v~T|B9'(VdG&2W 1s8W%I+MNwjdd0ץK_ǁhh>۔4̨۝u_5YYOgFd67?|Bn7ڍ(kŮm7u7gM~7oMF#Q[3`H0&3qЅ=<}L;oF% FBh@\g"ݦtb#^=ܫ'!{hC1~T zh;D@d@6Q~kw%bI<_2}\]mݤ`MkLk(i p uΗ(5Η(ƽr c^8| ϼӫ:[rΝtDW%e\]tD>q oJ~E*g-y(US) s[, oE /[z)by\nS䃽[ t7JN$C~#YD]&9hK o\*HD[郻 %mia76sT]іLW(ڜ'5"qk:C{/;?j TO ,n}GS@gMU?@;XVh1TǢx `3[yF^B5 gjf?]޿y{?j,&ި:/n<L=cuey|K<1,?i?!~@Y6P!N<ǁ͗t>:Gq &cgseW74w>Yft,Ys>k<`ŴP vn¼6g37o[K= Zހ[ N_(ȧ?mb5O@Wlln[C={iL4  V5m,d+ 54{;cqP|gΏښ WdkT՝C:O>Q lp~eOh_u0ºw۾d?ŧݩ[/~ sWsۙc?`~csO_4ekw^)TM+zתYO<1"3  I19Ca pW_]x@jbQᶳ 8"Spϳ?N{V15"nR=cw9>\xM?-qCZZ="A kiXlv6>6.g PxB߳~37o-nZ4MP0t.NBAXߛ ֏KUvtP\ԏ(k6eV5/U%C3,o 5bWk-y5r=/Dj >>P^dcǟyKO?BAKJU 8ͽ ;.s0i"@:KGdnYt2/,t5@kYM! )@r" ZFNQ6prIG?,xa<ݞe>F~+tƿ;zkhm#Esr*#amg?M k/\AmE@U}z yXo;OI:k7(?,Tbzspto4%2U>0mF=A܄^&^y ڳ |bOC}Uգ';f(769GS' C.Z !hX~d8 U:(VM9f >zKƯ |N/waIQl/CܼM~L@ɼP/ L@lln$9UO |ҿ<72K<͗%4jY7Z1vu28( }yϳw/yCs'_;h4xqh~iƋG۝/#*Ի8ևcp8jZ&/QM#'s:DXj16@цXj1|2lR෿;kè?xpDv>)а`sWQy*LJ%/QڬC{bdx.^ɤ%ʰwdnlNikiZsW%L4W9gn6wj @fp|x-mnM/_?˧$/Kd\9g-n~$wX~W(bՉgqikaFD\x]W Plcjg+р_mFmNEwh^=|ỲQKce|(|fՈ30b 2TLo?3*,k ²g\ EX2bg\-ì!̨_pАA=vcÑdP)蕁Y2 Tk٫~Y:XG2?ߝw'~뿰?芄1_uiZځĖ%AES|FÁ?TNY{h_!I h^*WW+oÃl9+su, A?72<:3'ZI?蹾5:Ysu(8({Dks3P`jnGAwv~0;P5Po5 .< ȲML ^lkC!{އ_@J/_{=/;vmQrE=a0h_VBRzՅ's|~vnbKMzç +vO)-5uWJ/ѡ~:l&f.~tyN(p,T8k[xℵ@c; gfȴHL-0kDL[Xr1L[Xr~@uL[Xr0slc̨ũ0R#3Jf ߻̨Fcעo|.?9?>r=b0n}?.Ty˛Sc@w+GjUeFi-m*f&[(e-f F啹:-l w !N'W c< UAU#bueUޯ&_ ?ɬE+ޅ_@"s?Fd >tㇳk!*%~XCR?CZG'p諝8s?LAh_= g3;諝d9~`DV\F~@:;B>VyEʶDP1+XN7cy.^?gaW4ZU.]V0%Sg}Qid|[inSD,3JQþY2=bUZ}|H~WH>KY|)ԛOcC ߠOeZ$Yoq)*\Zt*Sc *~;͹E[kH^of*a*@qd_zl]~;q}õL~DZ(:9 Q|&qtwC tͺ1&2|FGlxEeb,]--HF |i *(1n[|/pvQD`l `)^XV')ZNQɮ[UeY{jUA< qǯ3sPG& ?2zEkǽl=!r)ٞ>W!u3Yſ`S3~{:w {e ~Rs__[BT KU KwgwX|WDvy|m~dFb2d[l͉`fHJ0+y?kOL N$S@;*|ף*Ng"sL@O& Kv`#@p6ϗMv~B`X{3=1Fיּ\,&H>~L筂LW?z+o;YZ+ 5TDzlM(m1IY?ݔ2t0fāu, -*suc1Qldۿ_mɌњ/!rΗ3=pp?2|OBܪY[D (;6ģP|ju|jHh[/3_zBG3Oeoh#_k{gÔH$_ 9r1Q$9 CxMc-<9%ң{[rO淶wU1bd'[vD)j0&FWZ\߾Jb=]8UySO ~Ϟ.BwW|P_b'1{M|z(ح`S> Ne\u8;re'<ɤ\Y0u䴠2:-'. *݂ʸㄩP>է%%׹7 Bu~u(h\[Gx Y^#Qr\)LTKu/n LvLg2(၎kUhR)=ŗy_&p\ɮK)Xt̸%ހyl#0*G"ƺ7HC4~e.@̨LΝs¸AǧYL<,Ip9h4ax GAO-,ٿ;5~|8`0Qvs:xTAٯmui1R1_gES;~fԀ36d^Jt]`VL>2~gg'b{ 6@= 뿗8Fd79\z=/(}:1fJ"oljjiABV(G_:w5u` Rt˫We HJfz?wk$C\#p'd++egN|yn*en<\}옍*ːpiΛlBٿJ994a ~/% q!Cq$%|L&'O;9}!sMg/8"ȇ%݂%Oϵ|yZ)K 1S %$%pj/mߣF5 q$`ScRM4,j]쎘!CRN>C^8%]i\mAFߵ(dr@q)rCvN#9a`\8w<=nN}Sy7M)7su(h~@U =Yi8s$LAQWDacW74w>YIӓc35)å6 Op2\UC2\Z;Ip)}JVs:{ Jw坲sf?ftg6&|| ˏ0LOr:G*b ֨2'Qռ|m [3"8/`djUAx_1zp)m.):BΧ$4pCm4U\!*ڹ )?Kx}k& KD>U[R7LwS'Y@AZwK %m(2_\ júf{*ڹ ]Mc×;م.>6 ;C >t?~0uV膭? ]naN R}?EB(\ԍvq2Ch^B F}~:-m#^8[CF{G}|עSs[l0[{K_~r.eP0st PqkdJrgE\|7-t\+4"ݩn=Wi,66eZ ]Z[|x\Zl1tO ~hZ3ES|leΐ +˹!H&];,Hkʯ] eH<7fP&4|ɛYMMbv{:=OPG눀+=`5ڇa3_u.@S?r`$LOsiIg\{ jK W]a͵3vCrk3{B5,'nO?qIg|FN^- UKAӄ39N`EkZ&1554/.[ooj4\U.}|1f:K|8f=LaA~HKN(ֹ&Z~sg~={C>V3n$PJ(ZϙJ YpGU#AVGlƄO_7 RDRp y[}4!v-Zi߶h&L[т3eBvhs|܊P 55@OWV}և}~CftwE? Z'ѡ?l[%Z[Qw'XU^Cv "Tj[QLAh~nGGĒC~=+VKe&+NbŽ'k\KGJ%bbb!i*oʱ}ikLxd&ۂ^ 4j`}/V_37o }[1u,"/`cb! ;?7D1 2S7Ȁa:Η( ƑCƁ8ߑ%N76@,6>XKI)iӖ 52EqA:L=T :&f-B. ze+CpSdmtEbhR2'eˍU32W[ W!5o/գt w?2oKn[v(m߉[29q#?%:f/~ĢUk̇D[󶁡9VZo7磘Z}c` ;#4om67bE 8S"4+۽`O.sCHpi8-ɘ{2o[^#x8Q{ާ3V' =L#,]5=W߱RJ&t '_.򮓣`עl.j ]9ud| +N&QP*|>_vD<L.A2YOl]u}d\5N5WD/׾],dm[i/=`[zգqf~/mw7Իxn4GUo8jztD6tܯ*+u`,ZEvh,ZtD6)GlHY F?huĄ%ʰc̤TTsW1fR*|2f&z.^ǡ1{|2|2lrVL]gm?B~6Vx_;m!!ڏCCn%\$ Q`F*S~yqn FM9T+=JX0,V ߜo!wS|n%M& )V#|n9󕐟 _Ou]Ќ{eM#(w4>}CIDATG{3 QK;v gq`rl̠,1^0 v27TH`@!ofP>] Gx:4U8!TeFpMbBǵ ۺ,Z}`s[,z{z︍vP^,&3ࣀI koԤoVc=&ODVa@Dk0@VA8&4h J_DsG'>5wtBCtH|.%H Am ,E(L0LX@6{D2|FhH,Y96ץ 1* d ,1z='C̰߁M3ۇe ۘPo Xu5A ۋ,䇮ڟ<"rrV<#am{T ڟEj;0v 8ҍ@7nYn@(wn¬@Ռ2@ܾր,Jﷺ$f/DW )7ço2'Tz*Ǣ Sy~(||EA6l0>PouI<'`RSi]` EK=3~RKt[$f-~tyN(p,T8k[bQ>q[dd yʏ|@xۯLw5]9Z*3~ߦ`R;6LD;&#:ЗP||cY I&t5R5f(+JN@:\`>Qu;J^~7\J嗝*UV6Ϭj0Nr,nF@tH0Єz0 "}"YۏR(?@͆ZJ>_QD7zg\Z6# _„HPZ^!vNjۮ3%4~'TSR\€T:K_*_PàOFḕo Η+|q`| {6;no/G.߭Z9z:M' q{NoOߦgbFC@Y-H0MJq՟M˂٥ KͿaBLwۖnGά¥ױ7?߇ w@V~j}"/Yo+eU90 UTvs5_O0o&Vw]%LU?04[&41q}ȔﮫDDZ(:9 Q|>sr7Hǐ)o@ʼn679 X|(܅W9=^G X/sE?uiEoi!]s(*WN9 "T!gmLN'L-i/wW: "rOgٗ1oras8"}p3Q{ s_ޱ7m~Xb;Wv/)Lj<]~dTzv8/Yp؟r,~yo;0?4, q,Ɠ?pY瀕=с^ю/hX:''n{:^B?x cx 7=#LգA;NuR/2<q#L@:^BiE#az.k%4{|8 aZ$_bXXbkE֏<">L tba=х19`Xo5Ct|αGg2=5<<ɧt~=s凅;|]s|Ȩ(Tt|r޲{9BBȝeg GGS#ڛ7k&/T GKa?ИxtoY^]lu}up>~yx `olo ΤP*κvZ`6k/ 21lF=Gk8Nտ–`\OOG^ aw|-H&2M|jE: ̍7B`#KѡoZ˾a96;[j}}3|h7U+ڛ-3z,T 5i: 3}.vNyrx" j {zDM}IM'>=tXR%z~H/};H 4p`O3 >]--< n=,Jk)5IO^~m4ِG9rm@IFk_ ;,|s7j.ҝiŭz}.A : M7e ,E a9S1";_m|׍w܉U-KۏCdq7P}Y+8`o6[j.ۯ k..w ɈSп_jOPk#mF=' U'q#FmwηD.y TݝLԇs@C!Y]6߯e OSw/h96U#7(cin+8Q:2 fKn;8"3q󂄐 nq0M)GӞ q_S?lTA _vaǥ C!2&his  N=Td 9xAiOr9_uutߍ^q\@Ʌ,WE`-@s%ޢGs/S-羾{3$IY2YPD{VȀk)S ^al |p%3nL~M"5S~aP[~dzԏIP+ᭅH>~_^ϥ3U+Ug?xw Qҥ-?1-2weۜШoS|K;&Cߌ-|h[Ilo*v}2^V7y~jo-e|=_1Jγ Pop;d|=_1:Яno1p|EF?~qx& 12{|yd+7cΚ ]ۓϱǴ?}*}Վ]<&[]TG䛀L!Ya;bpoa>&C&w~Ô;G|n7}j\Ϭ ;S2r->l3=?<l14yK1Nn.lw+ƹPo<$)S,ݖ90[R~pPs.8K6 ÃjIg ))kF9pٷo3N]oZ?F7G|['GB8{7_X;m\ƅs/G;| bvL7=[i?D.dڿvv >Jh`]Ns }~4Tؒ900s-`MR`?Z D(=}Y1+JjVpaA3w]/:m9N^ml vޒ52ȚU>0-W}۷uJ"eC 6mgvP=biW["@nv$Thm?'C;uի߯g/: jY1cqK揜鼐Jdz|O sz}{A/DLl bbcCգw@{ ǟ#RW`~f?~JaXBڞֿ>+Yp8,CCPPnިsKcr!r񓒇c B iAyd-X\&%#a`a ~؆mpH4AAju'k現 Ȱ$$ NFJk,\ϐaI2t4 +l-W,Xr YcW,|{8YVn zQc+  u\J1}%nc|pg_ ~Rt<j*{A#ljogTj~+7HO CWݯ>R%y|s> hmosA{ z~ɺ-OG(>_ʚ$?7Y' /yt AqZ m$>f B h@?G i oA}} +Ai!d3ZjXU=wU|,s~_l><(,UJS|kQi F"Xztb.QKkc_/yai|FQ0tt@$?XM~^XÄZzG d2LJ_Sд?00) _?|}ig`P`[[ZZ&? %E4}{6[U5Μ/c?a1D ^k.>I MKƇ/~}f-PmſEMD# h J+gF/#k3D[˰`侀p|˸WTRŞIH_hnGCP@3^I図3: "rږrnarL2<<)ߙ6+`05ݞH*I#$wpG8 ~;mF;Տ)3 %K<'O'};O=*>|JPՊ 2{_^v7s 4++@{-/#ya+:bB@]@^ŞU:/dF3E9KKUI?ԁ;5Q2~TA_/?~)_هnZ|J'"<269I0o>DsPԬO*˜^2Zioio Q>q=]$%ojAKO@^^av}>UaϽI)<>[rO*}Yϙbd'[vD)cb8|_RϞ.A弩h|gO@;gi L9:^矝2?gczW%şZXߝ?Kwv/?}o8h_8WJSFh zt0ǁcǵK0>r@jC.{ MuYx11o1hIQz e* ?L~MI&Q^AǞt6]E^^Ւ7eZd% ^ެIZB 0iEIL`{y~PG1>j~P"I/uΝoM1qwn _c޷%* ۊ]1c|\D=kT!hM5T pw {c6+8ޘA<}̧Vв||1xrd7t4]V͟8(CAӍכN {88)|;lТn[>Q;T:"o~&rT&uHSĮ2:̗tziܽ7c3+ Qv9~7E#ݚɧ{wr= . >s P( &+)i@-rCf]z&$k@R? պdIxf 20Pw{n# TF'=~־ۛ?ǁ`;7[)O^h)hhn|ڼt~{ۧߠ0u,_ѣ[5>k~+ *Va y瑗{O*?ޮmB 5=e ]eV}Ϗ-&E4cmB" 5Hwr0¢ͲF\E>$IsS:󥇊rôYn.ij2o֝i%uE_ x׌9~@>򗗁h/s|U޳~ ?m&z[bʧ7+~ri$?bnhn޾R_H E¶s Xg/StI>$2s-kuX?ps&ƗHt-knc|GW1ni|iI|魧3n%Va bQ.?/K0e$I}dQdD wI{yƋ]]R"GG*$hn,k$.H}]As(7z% Ѯ];}a>]?5.ݤ#]>>MRB$gF2B;YN/\^;aBq=\1fo=Bij ~juqOG5`w|Zw+?%s r c1`$-O  ttwn˅ZC\u|,>|dп?LwQRPCH{xǪ8C9MmS'wg b"0(^/*MݾLڴ\"99%]Ep6 =,$ t)?.mv0ٿz"Qm>e`8 5d]#d* TkgfR\|!; ciQ//ho zAP\_CK9i(Vvb)L5, Ar&^$3%2}&RWiRm9SSl8j=#]]Ͳj0g.tbl|a"ýWnv`4j gE#hn-g1}>\{c< ԦQelQ^@ cT[t zjc^x, 1-*O^.PbwU%]_v?\h@m/ u*c.>d0W2z,V=berzG\+FYUd0'~V2o-d8X7z!CDt#YʼHx uK?ɍ{FKjM6sarRi7{pRrR&ND'@MA x(Q)WqԫG%j6jb>m9.{V׻ޭ-Q_ TtkHRSer1 TWtM+zjRt+ moY{A 5;?!Z[pL)ơoZ{ Z!+ -|J%xVћׂ ZM)]h?"ثfN-_{R G+ou]Aׅϙd+%kc<P~Stˬbn/Vɼ};aeXyB4zkme[cKfN}skҋ:b-6_y[;*z1{wz&`3; cȑ'ǏLM+*K?N̷l^\(b_ڴTA>75 =̿aH$B-B(,#Pݷ~g#GQheaX|̀|eB@.6u/ @φY' jpD"gm`?O P-1#Z)H== pض8H$Bg!|PH#zBy-~7E,`wn2;l2҈ot=}I/c Ԙotoxy^>No0`s"[ׯ_:!fzvTKǰtD9H$Ⱥq%&h4e!{zs kW.OGaQm+UtwW7 5UjG+kF▓w8@;7!=*-0mdݺ̯(`$O^]]]УW,gm.rͽ~/.O${%PYD&f9S1bJܦAF}ת>s;zrG'3 tP+z6Gi?QϨ9y>-AB=;?[owmx~hh@A:w~.#GLjRl~9uSn"k<_ =AܘSA2񃂂 tPS_~*[4_lfI>F~`tO`PKh(u|g mH#߸~$P41͎œnE["QQ̧mѬoٗ?T-9Fv(/e1*{7دr}}óhW=͸[6P?&v8.3LʲYs"Z,i, ,ToXSR:XSŗ؜=`oҏux,X\48/ Ba|B??KY(^Y5/u4H{=,X\Ԧv̌}dzzYʂEm 3]o/ouRzЏ?SW|w6 Ye ~GPv{\pB9.`ݖ v{ e5J s"3 ΛQ.iVDO[a5 ˍ4=eZ.U|]JS zVu)M-S="S}Ax\qRIX'0TFr Nac{;&Κ:;L$Mֱ NJф.@9/ttTΨ!-_AKM?_=n'{Žw;[EGf'Ycn?Տ*;w~M] '_BLu;g^ݬޞOO+ m+&\ ;b a˄Iw:x`:`TU#E@4(ZxbMzi08ɛ*Gt3VwLظ*Gt0{ @a *GtSVwϰgQT9ꦻ6!쵺trTN4{m|=E$Kefu!#++4E %`eL/^b@ar m ". _=UnӯUS8^'YNqi _nwlįܫR*Yi YT&)-^^@gYeI$%L. R;%eXb}wtl"5U; *5Kt.F߶"l8/ǨhoVkW.Gw-EG]1W756j[_Y~*TD_kjޠmAdzOإ6"v+_οRd=9xJWunr>C=ĈKJW~97]܌Υ>%vꇫfto|Oi!)-""Ɋ;Wx K[4wƧw#ZIl-cEJd* "دz|a 5mΜR} nlMۦB{g7N×dnN{5m_o7M';e3)c2KѠVOv5/xl'Uw.@ ɛX iڊej%˵` OyLvy&! p⧧L[`FCBV XBpǬg㶫U m{8&$jhiop{/{ٮQkn>^ t '?Sg55VH'v3lW@,kď/-T֠ZW?"`ǽ!*f&zB(s|8.>X%UUV-KLo<1a9&JAX˯xĘISy?zXayw~kI |?|%bzcc'8{ɉ׿a&Z3ev;;S)knU~4t 5U__]4|3q\'IPC{m2vZ}[_Ӌtֹ3;ʭ0hfsCv.Ң&}}=f}+of:i{:m E\*#=fGc 3Mۭ}v?727QHNALڡh ?1m,o|H,|>J2@sg, ɫ{;?>z,~HNA,'D;P,$c!>{S@xCVeubbz/6A @B;4y;'Nbֲ4'{״ֲ4'>ִH,x)oC^ %1|x > /3W?>:Sx ;/F~yB4/썇;βt=BYY+EDw' g>x˼eZe+zNҐʁБ>;>_R͔!LeE05,x{z0#eW&$h=>敇xB."f:DK.hG=xXTQYݫWѣY 0[I_#DM~wt)86;?nݫĽ* Wr ށ/̟8-J)x7xv7=VW&j|/j5+y{c1e| Rߏ1k(KѬWa(mMjiPCX9 }:h]~=w)\~¨ƨx x3rSy !DF,ĺ}ڥi}!OhlrQ^Dz g,Gspiv ;1 7/݈ڶ|?mic Hж3M%EE$!F-tɪNjyv}pr "S7OmD<||/}To9 m>GC3ǚ֨G-t)ߑw90Or?zy{SN9T\;ucT[6v=|yHr%BR.h3PǨ2vj=L fr׬p_!W~qNAՉ3ܽu|\* (*MqlUYNR| ces|us?$xb.j:V'o1lyB4Tq /t#WT h5+UX$¶~^X$*^@&|YC7} KwMظd> %;Ƌl3_ 6}_ YS፿ '{>8bdͲ;v@x;Ƌr|):@7c dD}"=z ڄD^TO^FR|E71%qm~q; ;[>⏙PQ]zyǎp |]8늤rˮ~e=ރnwGE~8yB^h~ѻ\τ6qB{gib?!aJCS6I'ɯĀf6m] fn/qg ? Gx3|xn\o+Li-[Mo;}"|yxg +qʶC(ؙW-IU_j{tXNUGwyH ]w&;qH"_zwNq"`gHE,dViM7hc~psex{]P;QAwN9Oc+_d\ ~¶f74A ^@4I"w rݬnZj}]m$t ܟb„Ks"zL5V~zʴ S&HpmB9ټ|[;R}<'l5o#i](TXnU[%"$hۓ7I^o#hpRS\P=?3'%'>a⥰5w|<"+\,liz-I)>e⥰5=#o{Iw)*4?B&%d۟/Y+.>ߣ[:D&ؾY֨OyG_gm@YbL;%T=7̇x)lMUW _b]lN9_%)<D=DPB$#!*@$P Z^z3H z)4DIIH PM7jZZ PHM={ThP ,& ~- N-_OeFn1{>&٭gߤ=ymA}Zo6' ~av)Euv~9~b/'qY,oHU WnQ` rq.g?{l]~P?2'tYܥ)2p6!_k`o5vMMlnD@@'yO ]Z*J;Y'TԶ+_*#.gI_Z&XYhӻR `~pF~E[ 󱉟1Ǐ,iˢ&Tt&Mi+{ 'TKl⧧L#!sKzʶ=6&$C̜^m?Ǔy׻0|]~.i6ye̻]]Ԑ$VhRkh!5hHIj!IREJ(IJJ$hrwu (~L646YDs Mh~=ҢD}OklZU b ߵ_Zilb9MeNm^;7wSғܶ-9'=24|ڇzݽ⍿oi6-7׏fYz{K`wDRƓr|oP5+kk%vUfоòvbw7-.~8m~xhB*II$HݶOEi4w*8j5q6MTUsA7t~e_PR1RsE^blߩn _͹x!VB^ǫwH\+_j,zP_3Ӎs B{3.`Q.ȚWR [ç_I]p_sHY&37o3港˘GZ ޟ}Oݵ~ mL#`OUYm{֧L[26!,+f}aڄukIk[܍"TOVdw|.TFk7n$YNL=mO4$LAlMNmENS5@vп bۇnRo@A7CH:ɿtG,.+$.ڟ{]AaK){/{P1SNwB]#C/h? 7  r@Da'@QqH _-(/$(K ֊R k,b*Z+:K ֊R 3ĪD{:5'D@Hv 9Asdl Ν.Se 4;Mw߸~;~`p'IͲFKĠ6AƗHB !ۥb|zM$%j˱pzq Uk\-Ӄm{.Zrl|d\Z8߽-c ZC%ӫIjhK9DNϦ6](w|b,lPE]gd*:K-h[TQYjA:R UuZDDs`]"vsrIrU\FAn覺/g(h@E`܍X+.rӥҜXrpÊAO[huҬ&>Wmp~$30{$ƪ ?-ۄmZc.7zc_is<V ba7%(N"Z}_o;`눛zw||W'Hf"IuXE}1,qg/2o=TNwlTSӐ nnbxyfkhC[Y|p\qmRUmc&fpQy(!ϘGB-  5-+kYz9A8=eT  !_ѐPEڄDRvq ©>RWRT! Tj!HL Z3 dH 'vk%f/BL|v~, N#ֻW`}厺FTUPW?o oO7T6UIޞn*y@}CZd Eִ'l\B4W<(jxB(cYRDsŃ"kZS!EuuJ 61j5EִdƢFkeʠlbRȚfY#QWT$QU%3&5Y !FTԣ23T!5YE!B!$I2O^(RCPl|fy'-[ZN>;ޫolr)c 8s55ڀ( w$,xF*z&{A Ͳe\>4T RZ:Y$#dtZ]_O<7̇0zVFcl ZtAVAbWRBCar3h]niAK! B酶vAZ@HR{~{J7W~R4%$+%Qo* ps;*t=7ph"v]էKxaZ9{L".?EBrNtQk'?YָlJzǬt? 0 .YZ3a{p YqlǬL@< 3nǙWm_/>ߓSd,jk/%Զ3n7{m0R]o{WnɱRiEkMfڔp^}_l_3``Vv%rTUi}]ت*-^;jWQ o<5*. @?-)<F3g5<@B/OPo,[46[[I_`,'gr|"AXN9Ň4Kq0 Rn- <.s$Ek|Y YhL2{,sSX2 r_fqiS[4NTݖ;?VTgcch Gj}0y͌~@T%ɭ8삧7Z= efVŵߘ9/><ÿ4n&ػ48A'qW`>qw{TY'Qko7˚Ps>*9}=^tDP^ojFnI9 4Ě_}/ /x`^%iH ;x0bVx9&o)%icxOjb . ~?xa+sՏ˄vqb |NOMOH:|)7c_r-W~t?;vƣ3CdЩ +.5J";u#;u u&bq-_MҳRIdBN]m]@n-K9 {?+QFHL7\}{澽WC;)${l|$fEӿFP?|0 ]#^xQ\2(JQlj+kI/(J?gDhψ1OP1>$C ޷ʆZY^ҕ)Џ](tpT8#( y5r~{`{g~kKk b.,,s؝ke'%坬7݄?YZp5uhV K2t.ޝ[c؊N;7)c7뷔GnEl\abu"*ht0k䓸2P(ub9}oQ,|[VuN7po'Fƹ>q2(JʸqIfyqcˎNb9!g}'iAB:40[Y?=ջOo9U;uR=?v*Vk;z;M"mS dNbu6(a#cơt-i˨()M*8{,6)|@fI%&7}[O&@Pڵ g67you,"W2A*r&H8EI5[V_J6+>H}`I[CQ|-aζ)?8[5{I~yfًo;C݇4pڵ ?<86n㗓2},TμO~YT?Ӝs7Wf=w12}D@ )ocr&b|()BIvj [ͯN>t4\y3Yɏgk1%Ri|ɀ.P)ԯ;`Rey"6>wsHT@DmMhNVfMFfsGsJOFjTjB)imB"IT* D")8E)TF4ک"cdG/v٬NxU| 452GW@]}|`-At񳇞!õ+DK8XZG.a1PnŗI8E4e s}m$I#lxHr+KsKyu~ЀERtDco_#D#F>@d =9f]8vCv߯EFI=:%.Pwk$DN?><䩠(iW}qhwE_?]/~$C7gwE387Q:~{Pߋ"RB<$܀YhXLICJ2I!]톇اѲw\qiù٭jgIP5~[rڮ_x D%Z湳bKXTOieu$e|$+TV~㡴-tk07̇sٽ.{s$'~6BkjlXRrKg}F^՚J348!ewnRxS4G7˵aݣ}U<eF|1ݜ֣ԏ‡A4^kkV7hTtM20G{:>ɇqϫ~]t#6X8$xh(B]><NXW,]^*95Z<]} C]"8_Th\?GMo_~ƌh}4-?]sK&jה1wpmJ@eO"+-dly~\0ٽs>zEϙsi7MN[s6}уXR(8&noljœ:/W4{t A䑜pIfy2#mq/MFuCx"|xH{q}'ʊ ><$N~2#AA8"MBUe%_O/(8|7yCn#UĄ)TƗb_?q+lh;>o~'e=>geɲ_0 uxٳ^e$yWogR뫏‹#ݩ/8;+v iᆽKȑ#m/Κ}\ʍ:.c͂&7c@+]4@YV5I{hlk|SBM4`l{˄-g.xȈa:[R`d|FEw:>9 kZ<om~g'=3F~7F-~UgOEiR$7ObK;' -֑B<[{/>Ŕc D gۍ$r?;}]ǿjeY惝j/8>#NBC25`s֦ug_*ii 6w.8'-$J mfնGm5?*<@>P'>hw3OZ4ڼ4Mڼ̴3תg@>\>skN8[QZ`= ӏ#,tX7~p8nnSr}9jtR(}uW/gP`@3 |ݳ^R ܧI`fbH%IlOݺ~KIca=<L2ko)0Pe_ǵ,(n}d7]Uq& Oz~5Bo?A@*7޻rg~lS#u}c֏F@O~@",@Xzvtiu:Oz~M ?e׿~ j?.![O*QLJԈo~E/ +?&T3-cK'I[s.\Ql,if+`$*ع >+7km irύeɅΠD]v $VEo|e\YysV?;I&7Ƈ,Clk=H8뻴;iGXiA #붼bYj֧ۚB v-Zq.ڄwFSY=_/ߋJ恇vyXJ ]= ]绸O(9\\-_`nߍ[`;ʎ|#;~65WdZ%m.XI`:>fju"p)kp/VIfL'oX75a̝3S3Qcv..LǮ`ZNMdsޚsaJFBN2Ue:`rOSoovI٦gTH)+X\\쿚'_ @;i/ݾϸ"?w8(E>Ncrq'Xw84i$n84\UM/7'xzsI?tR[YT|+. JY˟\ qfU :XSj2W?{#>&=5߼ˇ ( 3_ꖮ-itNeaI9F>;ˤl\65S{Tr~@3|:HgpE}KT!/D?c~cSdp[ӟyCs+o1lrD5;68>q0H6wl5[HIi/d1%~JףZ`i9)mq.k1audc=ಉGE-F?=Iުg|k7-:}&eG< (ƨ]6ώ[)^*<q ND$ɖA|ǩ|q*9j90ȴ/WQs;FG\X9{\ E-kn3Z,ƅ?fjF~a<\V1g=ZtZ|4w7^u!жeyhDc m1}Q(iܒZ Sb2:xH>6>L|%:~?kQxo1SY`c1lO?g,XL|9[Eeb** ~VQYsdǂY<.YfM85<[>H_5k _OEp/jޮX F?VU_BuxB1zUoWv5Bw ʐY{J2Jt?ʼLN8)f8L.$c^^aCIke/ptYx˼7$A\J+gyi {SʏSItyO 4-Fs]rUdIv&kfA>׵Yw#TjXR2Nw 2˓O(֠6R@ؚr'Qpq.HooEK#&:Ͷaҳ{,@y:7< >@ϥEPpw 7nM4>Fܺ4m]ۄ|WQ>wkPo>@rjF{tUݷ]@|Wk7݌x遗 Jo?Lzy0V} 7]Fh)|ٴŹ]CUm49}I#%P|rO:w ex-i_hu^%%wp2RsD"^8Y U_wBQ߯]@@k8OO#(YmU|wE1(+ >e ufT+?1{' !W$ I|̅FXUriM"&\12iNAkFHD*moCm%ըN;=&&4G@P%J|U|oLc,c O35˷NVQsnk1Ϸ&gq*Ev)Kdf[wYRt'mgYA{x˼.Xk T]}D_}\{"+5 +V tSI6 Rw 2[@jT o8!/Jl6χ@4ۘ I`H27+RQUEB*WmJ —LSD$kKzg=[4WRw 6hץ.}$Wj$WG@_}:^JTh{i޾ v<5lA-3&@b9x5Џh瞂 SZUC?قZ,kpC}-ۚˬk8,y귕*o Eҏ*iQLDŽjK#I`#"/]G;Mdn3S Xt{$<ޕhAMjnACLl;$&՟q$<)|xH?%% j[lg80e֜bi_@SE,H_ŖwPy<*/:-~=[e R[\I+ls=o!C l (0Ю=o͎5lF4"-`*㖰sy|V/cMIC_OEΑLQϻ +wzzo]?= ȫQ? c߿V$vCT+R!s^kWGe.o[ >8lqNDmz,Kr-[|nh{D͡uY&R~9 V?)Vŵ\ <8d4+ ; d0: 8 ykW^b)Cֱ5'g4|WOn./dDj#߯}Ek:=ߖߊ^t_ۺ^m*Xu|ì/O(Hp XhNʳwkܼDGw[^[T|~@W&ZRυ=:I0ckdbu.q7. ɛʐI)"平~ʍǝ!0a!p1x?{mHݟ9qۓoͲFO 0޿_?q_jl< c s<ߦj~K֥>50ⸯ?{l|Ϸ)~Hw{X7~#Rw=( y5ֵq$l )+'Z/"hR2o(_be~=SG_ԒCJGߎ?r%~ޫ\x֑|G_ԒG#ʷ~\VZ}:GF[_?7"qd8dEV2'=I>82ڵż_D8U~v7ߪ_God8>i6Ur."q_C,_`(= o,`l=?xB/!{`|}'XԤ\} v]`>x]Z`)r-&镹LvIT@=TZѽ? ,<2/Rެϳo]~UY^1\B!,1`D-f6)axw_DD_rl~(7G[ G]sq%8R<"z8ڟbRi.F}^:{w0?? OD2A?o w`Oovgƅz p zT%I1حyW|ڮ!<̾^0Wf<-^.]~{_e}p.XR9NrQ?_e5h wT^aƈ|-[VPYӫ (Iu#צ}㝱6Sٳ АdCZX5RF`鑣6&$<>S kK( `L>$vm_ZzH\G?Ef~|vu.]^A Hwou\w.eM}Ğ-nJ6daʠjc3B,]Z|5M]ܚ$P6&%%?N8^|*J/$jeͧ1!>剄.n$'8)yA'\[?HI_04u?֯+֚- Zrinn \/@yB41,mg o٠{ĒzG1 /Jlb1vpt CavʘG{pD$.DKW/ܳ?mǞta߶iH2/X-iGE'AL MC"EMZuڄDrS`BK:ؘ+$\D_ɻNJlxg.!"Cu /zу[KeEDB\Ԍ9WqaM56.+cwF@~W[^s^E˓CYߟa Bn I8u&=qTP) -u)U Vwzf9c6!\hpLu^WqDu=7Zb"Ԙߛ`&[?oO ;BND*I XgqG Dokd>wob LG+"AfkT{?rlZ:ac! wjfW v'@u'_@@v7[q+%!* LrnjXY/[/SKFD[o۸k^G)v某Q;8Ҧ;NiZU r{,o/%*rS=ѿN;L?gˎYiz1M>ۢ¢/Rִj0&7V=_C WiZf? #,/LHqQ1jba%_nv]Db|c. p?,.H%Cr3ɭǖ (ϘEV8j8CƗy?eu(D"e㑴T[E<"Rw@GuTw3Al糘@RYQE?/mĉ$Y]Q}*:@zzK_2Z5]A@w~$0~}bdA!_ J~o2 ~m4|.X֘}OQ:! \^%n;jH-1|皊Rc˻;Eo_./_N62// <8ax,izwb5z%0|bzQ_[IB.K`ĐxqS{Lw#qذ<܀1=gr~F Poz?~I_W{B-mX?ڜDm  +/hgOz{q6@'}?(8w._AaAT-rk3SlV ׮\wVfuT. \(kQ\TʇϟσYu} A7PP+pmW?WPQtR?r45L2|2kQײ&eɆY4>/Qc0xZ`ܛ=4M|R(ViK&Ƒ.ґ|J% Z^DBz=ږPL]@+ mJcV#'IF>'B$߾+ 7nR8f ƽky;]NaK`2\kAˈ'JF|^/)R|oo]}P}jhk"%*42@7m V5+[7+Eh~7ďǜ dFg@.$BɠƬ DhsKXBwo!.wfO۝dv]'O_?3^;/ٯf@.ʘ'HX|2/=w{}hҖtu[2c-W7'7I@v.@R񒬋[%X{IQA參;gDH< tIk@A֕}eܭ=v=M[?M?6/klS]ST .B>)wNa5pH|{lz<[xݑ.]\wgڠ`ߊ`Gq+%[Iz ՙ?O}re]+--.NRLhr+Vp?ǭ7oIf,M //z. Qu5ȥO_|7<=!lϫ@~,W~Ok<*9/ÕƿFv>sh .R+%٫UѡSY 0HBO[ > _b LiQs{<,"|K4’B<VIoC[Y̷$ojy=OԺݝ%vH`R_MFSy7(~Px'j~='@Z?m D.n(WO:m/W]ԯvEqDh ~Pc8ǜ2NiI{ӷ|dP_S;t<^DjIv7\It"|ڞDtȷ8 dMr kO܀ ˗iCX.夺wP_]A(䭙sZV|:=}5n~+h!7݁BZA(MX/ݿJB!Wϲѡ-^6^~ia Բ Aumpan,r땼IJ,WnM_1!N<  _|29Y]D9ʿ, 0=H;FZ="ؒy3I$$^{)<\.|-L7Ğ1Ϻx{qχػ/ "ցp_q7ګYRTиzCD>?rV^n^24^S⚂^CV^(D ᯜaV=g[ȱ8W R?ޤq(m%lG$;,?f{c&?H7S I:]B0Wn!*K c/Ohi $KH0'Wͫd$?ۭHic+I%tÇ2^6u/^{݀ ;~yB4썇 icy;]NaWFb!P֪$!GCXxـ ) Z[P݁O~CobX^_>dpG22Tfͽc#4tg6ǿ{mDFbhq@/*,'/Xxۯ=Ƌ^Ø;ƋBr uxQCouxve$֛3h ^Ц$ /hEd?|˜?>:? LGkh1^t}coEp+@nP66 2ȿ2 N|LVLz4+}( v;H^݋7ڄD[mՁS}<GcT VyǗ֓H\+$v9]:'g,?m K>N,%|xȫIFA\OO^kIK>>I$νJ\mt}yBSD\*,81m!n/q!h{~-5O{V.?HiHDO|Of7?r~/#̘8Sqke|`vIf9k%- od,L{5q| ϽNZv(!9d</~ݣU9.w %}`ڞϬLS3c!‡wq yu8}#1]=5 +Y;41mzG.X!.9;@p`Cd!D$6uqɫ{r1clqSqOx@|wbkb#|𩇸hBwc'D%E?vobXb '%Jz?:e$dJoN]Ч7_].}t _~3 1m 1X^r~-</uwIp8fRú_7y^ՙ_L.\ksp ?1LyɅGC:#I Pd-v62 ϴ.Y~`϶f:#L&~aߚ﷋G kûH,'us?$o>pn/??M* Mm|K˖ u8 XG_'W~Wg|͓+k:~ԝ2Ot> \7O\Na;?\4\;gY[|Zʯ̧_9^_zhq_. rzHQ.|V9⼠.蠀5<=֢KWyijo~PK7qЌ9~5fϿ7,zK]V㇙O23`)~1!f/.ڄD21Ll*=TO2gǗ֓AYf?i+)=th_RS=(w{k1m̞El>͞/>L[T]|c%N[D $o.zNJK̜.bmyDÜ2eg Ì)󈈠fd#3m7>3`ñ:#!A؟ܟKk)ӎ@z!I*"eidz4_% B(R>oMH$&$zhTL'iuė2 7̛&m(~|i=_*h?L5'wu^/؍iG`ͩ #&xb/ PE<_?Vϫ޿MFVU~| \WLѵTT$ Z_pfpae]6sdn-?̤rFK(kT+#`)vLM?ldNNMo~6CM'F$+?7̛?z[V?NaQ/]:0IW?YfZ?LZO޶ 3G?g̰fVf U_ f"҅uV<Զr"č͘Gf$[,0{ J> 6rST}VӧrrXO>r6zݽ!EʼB|nufu[.7mCW9KT?&N_ۍHp?rEqEʼ36_V_[q:}H jtX""eHqRE~z idZ2зhRcf- KZ E Qۈ%7T#Ԓ"W5olOE~ |}q/i=,i 绛B58S;nqO~g_FJKj]3(b$~̽үv246ֿۋipڜf2W $>r?)ΰ鞢Uy^}TasR`:RfxO{wv/{@ Z. #N8&{ MUyNђ\'Z^X|SX@v d<泧ՏP<5B2/ۯoUrMRAx?w O!w@?3eXQ D$=Y⟀nQjA_~PN%#TNjB?TkLOSl|R ]]J67 ǍC ?'}ڎ:?nFH{zB8JILtwup%WzKٴ}ӬT=`gRqIXuJ$R3F͟1 p2^_n`YQjlʾϦ"&${<*~HW$I;t@GX"GP} Y|>yk=Abl_.ǜ}P(/n؇MRG"epf 5j(jhlj g73qMظĘoWY4Hl sOٶg$}z-j@S#:LGO @Rd02:B!Đdxu,k\?{ܬw5?@a>[ O^9ZZّ{8?vϳ+t{ ~L.]pEiwϦ L{ Ÿ0D[oH#7V#ퟲmA)&>&&y3+ANA{ Dtz"bkpI'06Mb!B4_z~Kg݌߄nL."﷥uEIČI8JCG<@{V;WAXXj;(2:xZP>hj('\LMȉđC 3Mm}x8^4° Ok2Dnpb Ήzh⠀6A4ٽuMN)Þokowvo*'Sb0~7;y`L~s1Ϥ"?5co.o5:Ts_1?+NFyuTaL>VNꎏ}nObØ0~/wWs㿒 c{P}pX YLwD|W{jkɨ [up'SbL^ oײV?8qNE~.^3SBoϕ4l#>.xfl*o7`ׅ/7'OJ=, =ӗ+Z<~[|οQx7~y]-vK|k7Ł3OS͑O [kNX,c^_']FoͿCeqn;hwhEY_JNl2Svg%**{ IobD^}~>S|+papל\ճ`o~K }Io9e Z'Y2NCU;H2=z36"= k?\{p?1lcՌİiK8?fhIPw#^`埿KѯHI'U6/0V~ǀ5r?QDn<7hykfkwCeT2^heFzWZ+I4~: &u!6o=- )_Kg=c0$ 5F%sD^OgRO{ ~Ƅ=RV> lS{"_lmi$T>زwF~ XhOE\^XܻU˂r wgơQ!d,˽M82d.7MdP G,0W1 ofmrrwՄ/<\Ցda'wWMxܬ?NB?{j!ewX<+ i/Dhs7ojnKϹM'o942t{+a׶N6y3_@9C2dgssH}!HrZ>mN}=@ lgRD1nCxZUƢ_}ցbnEhU5q7z(fr|*OY1<"/<c& [ٯP)pkc$OtLe,߬nL`?6>VlvoXj)0l/nNJըyTsnÎ]qB[t $|}'+a FmogkiEf[jHЫ\=UxZe'KǥLiB6#Q Oݙ,z$jz zs4)0x1eHeLFi˼?~?+oY|VCp b3ǗކϙoM3:2]b"[aCӹ ± 5ܺ0q\ 7" ,d1R#E\j> H|p YE?@¼xZsbY--vpc$"{ eM"ooQ NѪfPk=\YN+ʱBuxH3n_3r!ԏ'9s*^o~n^G`qnG =eMԠ c> .>A2V{qj+ {NaStcYre6ʪȕOd>AV oŴ` ǘd_ӡu\-j˹ʒwѭj ]]Z=…adm'an5еZ'>#/E.V?UKw'a;PNaה x2~ 8O^o +'0lk7vwo.^ Ԯ š>!!i#V~8ۋ71>6nP~?{`ff x)Q cl#5 'w|'wx)r)Wr)r@sIeMVu2i|ݺެrr)(c:o9#yyGO[ʟq]i)-`r)*-G)@nn[.,׾)  e,L.J^+ {<߽_YZeo[W-m j?@dܖVޘ yr-I l5:?P#!t82'+?cGO+ d kʲI@hp>~s6>?㭻h: uZFd*z\L @Ǔp ŏzǴonֆCI"년H01$5꺝/%o`*1Ǐ4ڟi,OR] 0^?mi?\Y: nKSa&=ei?\YvݿrrJ{t*-h%~=ןgh3AД㟀6k_ hoܳQV=W~q|ğ6& 6}1(-g~a+6ytj,:O[q0lNظdʙ2"`؊m|sZ>T<%0IBkӃ +~^wOy@&^ _wC у/|G [zW>=?˭+|נroʐʐ2dC̷~8v;LD矐A^VA*v>o̧SBNx=*&$ArC%M~;'Q/91?q#j3^?NagL2=_ мk?cŕcTqeרmsc'O;=~~ZaeKim|T?챌Ple$]֪$ݡ@6ҵsb93Ot\6۟2e~4 `%~||:E;{8wi=,n#__?3fYC'?S)8 yO_?Vp.]S\_~\S rܗ rR?==?Z?Əc"حpUg"KG|51Dut9^zA^>m|bcKdUپ -rN;N(oj>!wD0}F4&o1z=H飤Y6.axXD>=矑x5fS󭞆ĵm;NɟLŒXɛˌOb8 cVn E {hkXAZ˧l۳L? :䱫 sQ0t}C}kZӃ<;d5W]`?!R v\˨qnAV6_/qY\w K>r3J$(}N1OVKpq;B罵㏨zN2G$gVs%޵-eޤhxڟPYF@v5Ӌ O$Ͳf}t2d!yx7NJބ!2@ qI5裣! OVE(!)Bʶ=YLI?+Nc- ZY;'|Ƒ"M-e<|T7W8|w }?2| ޡ=9|?k5B7>= J8~J*C3$Ƭ_ojdf]Tݐ pR/GlpCMhf]qC>X{B<5*;*cx~0rپ/Pj}s[Cژ:7x=dSk6D߮T_?3W&9N;|X0`ZN^?w|';> GW;N_kSN9SN9YSN9SN9ŏ)r)r`r)r)r? ,.SN9:DQx܍~<|8?I;ǓW?>:J[wS@ Êz V=.9j&Ndt7oqoqoqo?i8 |CMw(VO׵m˜[߉}[w+?x>ao~ 1+=\'z$ yb"TO>229~6,?m|.KkLei-?rM@k _?@mZh ĎSVwbꝊ҂L18,seV'ީ /m52^̕Zz6x 2Wh Rt݆7Iai2Wh Rt݆&l\x Ms@Mz'v4ekn̕1u;;t]G̛eHݟq,&ɘi#|c?$FPoק܂A֏|:<'._Wqm'Z3>Z3񥲋bi9~Z3 bi+.f@ S).f@ Sk]Y?1oY&2eB=x)¤kڊe6.1rQ[j/?=eSվs{VOm~{kW.^LPM+xzSvϲ2AP]C"{zEU)YEl?&YsE@m57P[v9]N1TXWwcL$h&`X@sG?HOxY{P.ش%ϣ{,V2Moivo=R`= 8 YkJ'M݈&X2bmBb2 \>Ǘls9~\1KO[o)_/O(<0n\O&QuҡL΍eڸ \797fo}[ڸTpq,#"ڸTp[0܂AmiVlSKW>|-m #_dIm?ABCྜྷXG\:Ŗ,uwKU &DBԢuʀ^t㘽v/oy^G|βJTGWoFR@zB [ a{}yڵ.;ϣ&$kef!D7`n>?Ϊ?D022Tf|7[{!9㓿ϘGf?<[|BqxE(+"v>eR|Q}S>-ĉ lԢ绫_w!uzpU)e\^[v{ ?ЃEa2YWЪѺ{ mpBfy!=Q?{ mAM ҷcFo~LLX],_d!k|],,k4<4jn0W ?n=_sϳfDǘG!WsnFbӏGPÕ|gET򰻝7'Tm-*igq]m5ܽ"%SYMT$ݺJ^?c2U,J>(o#öi2UOeE}B%SYʯת0>LǠ<2nݺkAI YEj?Z2xaWzLܺn栎Z  \Bɇڍ=pGnU|ъ3;E(%jY6[b_fj;L_F7:wU|~7ږ֩,\OYNc_? | ?kt!?pk sJ!G- +PiT/?OxuWﳮ+^Óą(۸({\^YQatypN^Eḝv(_\+<νGnl#~!~ ǝI!棎)@bx?Uj)U GNS}T{1?x ;w/0?'i߿ʊTV B8crh=_Ot,P9k{\o1-k:Գ`"|s7QuXNP+,'% Q>l]tL51)Z~9.x @w+x ~h{Z a=rſT$E~O7׫Zacp2*R箰D]0Pa-Eþyl3+~LKyM~AT\iU u/vd&a5ɒ2eVG`nsFz ӒOjdD;EЊiQ2lQKY=,EӰFhaF5cmOUh$?t@CAp՝a=0F f56w?Ս:ó*kH(G_$N [Yo'~oUc>>e'oR_3k+w'׶̴Q-~n6_9@~VY~|iM75cf{͌GUQ7mBZPPj1?_Ln$So(clEK&M >toT@ӓwY|ywHfTЅOI_5B^Z`\r%YJȔyE5UkVݵ/gUA@5s…n1O훯k|QP#s/~u=(hbi? %-%P\zOo_w6LlWFuU~>~|8|WK.?Tt%͖־ kG/u ܢ*i) Ouwܢ*i)!_o5]t in 4䓪k Vz WIH$p5AK.OIܙʊU]Z&gk՚-]A|Hv5AK.VQŻlgjkV}uIU,Y|gVQ׻s\M.KPYn[ kExܿRv k:_;j7̩J<#S]=!lO߬]|~7AqՀ]r%RIHz|Ht4 2%`4`1vhrC/JXtQa篓hH8u/=uhgrf3G6b$XYȣ;Z {nn~hyY k;?wONMo>أ{9,ˣ#[o]1fn"q{[7%!6m?otVZ &kCD-4 {Nre;ZoӖ? Kk[S )%d%$&l.%iԖ?g^cJ{Zז?mM1m'b1$ھ*I]p*s5@{#ETU|mz5@Hb[+k˟!õ);[q@_S.}JN_<_@UJs٪0oS[=R95~_w@T;h[nl'@ѭCk\<&y=ukPu2ۓ|y(bh;lOFA>ha;O$_h(F@1 >l&2K{w]|&agz(-qج}f;dO%eV}#;euE/N{;~G?M^3`P{G?Bnb~,1WGGo(9=!яN((,x ͌9O%@u _TV5Krԣt9IWnb7{p ]MRD%KL!<~_C׀ͮ.eLQ_'銀N, ]61+GIO'@yWo<Ӓjlvu)c[A%27&銀 GnQ]&w,T X?|{ ϫ})~[ Xt9?86n{|xveԹ+'n\pSO,|i1ھ{%?Yt,>jT{cV-8Byn.kVf^Ya7CysR?95fq/?ۺ^?\PvSN5sCU>Wv?G?  {'vk-c#!ggO&xggO:˃:Acegy$`ӱ 8it-egOƶnA Aunn I4䍇چNx͛d{ 3̳'1ji湮gCD@_)G{xg1Fx5[Wɲ?uB# o*Vve>kֹA&y i<կ>2ڇu.q_ Bh*=qpCֹ72T?qFke+Y"٫-z Poh<=6Iv'ojVΎn[dEL(?a_lju.b<@do?fwY 'O%#o(\w 7~$b$\Ts4?iӌ @O$l.Mq)Gﱇqi*=w#tKɝC'pU`ͧ[J]Fջ`skEu*<-(j&$}!pqSJs?f0ܧ{~`pt"[t8^{×~{ !{* S٘~ W~ 16X~ 9\sOcB.xMS_51ik!wϣi?O\{aS4uq;?D&\:?\{ϞI\V3zf9=x}oлECT7yRǧE CׇC1XOc=߿آ:&h&aa5SǧEC|u=?@)zDHq:>}-rD#Xk$!O xf@IC$mi3;F#<Gߖ&<`4ߖ&u1:S\O0ٖ&^wkE5Xz# #-6(Ėz}m3*xB6ƋXLz% L}ؒc?!0໗OlmBץ"Еz7١%]A_wN?ՓfVTv˖1{|j >/ЯX^Mͥ:"pL3G k'[׫|q_0=HސUD}n5ӄ[~HʂSGG&Z/y#[F?[Ҕo23^4J/~R7.=ך|>O2z2jnݳ[ҔЏ3E NeNaqMφ_ w̏N%CP!wɢAXXeE||ek㬂Xȯ2 >q _ r >k4nU |xw{uy=8fF0e-~h3cKs+c'2Ge|.O z-٪] <ֺ̝|GKc@j_.S`v'>*}FSE _lU9qFhzY%J^.,(ܾ[o?,*_񵵙:CRY q;(hdCq <}<ڼv ga}DƤ,'~oLٽa ug+=sb$L+EI~E !7F_[OL`_M]v)_(φh$lqٟFҋL}v讗?}r,,0ncHھf*L߻). ߔ7?i N|MlY<.`͜`BZiܤڤm8Vx"NOhx{-O[Lo j~-{Qw'_:!M(o NeΈlYiON}5˾{qBQ,Oo*~ _\A6?.O,0ޙ[ne,dt}@jKKG6?2AHYO7nk1|XgaX>H=7xC e\|fi˜X>ꓥľ:X-h3}Î_7&O }ƭ:Lo]*X3]?=_ZtU ?".z-@Պk XѮm5s%"v;7Ėj`Y#":ws*q;} p=_o=KyNcjۭoisu|[lU+i݋ߌ @C<{etU7 dO=?Gn.::6: Owu5L)q4qR}sKY@]xe2xY 9\(!SJT ] [B/:@·2w3O훯k|Qt _d4IR紟2/$P\n\韭w*2~\{ e: {χTU߼yel>$.:@d3~>J ЬO_S A'_0~]l|޾!-Nta;n7u|%+|3y51g5@'_xOQQFkJ&@:>r|=PQ_;x& @'_V?5x.0w#/6,Hܪ-4hDV_@N|W'^&^r7.,Xu?\Qwg[̇$ NeZ*_%7q`uv >%x>*6/1ɧ/`n?N=?\w7{Os=;C%^@ds]OȔJƩkfdlQu} 7cPZ{- n.0آ~\ɢAkeԪZUeE*w.Ej3jb A:!©^Sg5?8CX:q6=:2GF$3צG?kۣMg)L28Ymz{4z ToIf'Mo[$3צGďpP6\ ѪSFxlvZlh_j,~iuu" hkjTeγN{AQy[J8miMmSZ(.,JU}}M]կFUQ*i"&y}m-VɂEMUWNGJ_.nr^%bUgDiϻ:~5~f~;uj:TkG }lk^{)ąؒ4R}>\zӉڬq;%Mi2~fhk(͖4I m>>V!&SjYۃwE+qe-iʓ︙~'4j6sw9ev)JeGs]|{ű4U#`]m>h=JwK@d)^K.xݎ%\rɔlp]>gwM6/>w|ys)]|ϙqpfSqR"u[dӟ}QSGm=\t󹄵ݔbv_2;=cHnJn1:cyFɣ#^$j7%]^/|̍9;[q@vSr}uS6p RB6[r@vS{17ǏJ^EjRIW@Y]87;7&e|!^51zYB<{6 ݠf~cjwQ+ w8߻1V# z0'3>?h#Q{/eFua|Y<X^t|qZs?Q~bu}af>#:.}|b.~F_j  82E'ߝ%KV}wsmB7L1;n>Z-ޒ"yp}Ə& W ?u_(_ItY7 kVD^Jm?$QM`P{^e@nO=$2Sb !5*)v?LNLܸx.'/ p+'كn5R[{Z{'!GmMȒ.U+|Cy0ڋZC.8I ;0o*@YR[iPڋ՚En&wW(q<-k0bzVC|̍é'eU8u>r X-l qՎ:Y]<)nkR  ?l ]|̞x?@:?<2 x2{ _H㧪OE<H0o2{+qR5*~$q=8tT ]<**/%~3CfeC*m9P6۟$MKcL6Um+׫ ׷߯lqgNerz&/*9շwگ q ?&`P;Dv~05l=|x;<{ PˮϽ<ˮ4_6IzfgOJz:׳}g=1] )@i[n-DDh@?<{ P~m'o*FPԨRU`Usi@ٛ1}ujT`@Z42@w2Sⓤ쿔>\čKS}{h{lTھ;:;Ny2Se\ 9GVTӂ<-(#C|S"ɧs9rj {`ssZskQ~#fm>T|ϓ:^ǩ2>ߪÌ|N@(_+y=xi7}[n.Lq$Tsv*Ck{G~|^r(d&$I";}?_+a]A{ 3mm>w#^@ylk!u1$G.8CZ}Hz\zq汭͇zVc{e%$Gn~;ylk3Թ+Hz&k4$uC#7 nC#WYyȽH80?;Zh3wG:Vi^O`!QM0`8R .0e}>^◅cʼn#n0V()ggۭkXqRQGup~_DA)`8ɫI3(U}cݞne-=~ZJQY%"(}wxKvUVJyΩW(p*ԩ|*+ ]x<g }/ک tQ*t\+аkDӻmӅ'\W`QwC45%'{O'_ZoruwIfqM W1Tik dvZ.k]qk|z>}tHU_TǦ~RIzG8g{0!OsėyO}Ƀdj~Pđ}&tʨ'Η}Q[:8ZN{^[8#]`zkER'i_J&޴^χNKwhބ>XU/&߰]cw~.BDGͥ]x>gXU&=Su\Oܸ g$k & G\_GmMЅwesqmz*4 2 :2[\[)Q yȚ,[ZQMɷwibN-=8`C| :!ktssZK ~6}W ǿ3- =wm53nEq]{U6 isMf|֬ZW8+O>_ slט8%)&<,LNX9kz_Ӕ]񣕫K.Y+idkt fqdXo-5,ȋ]#OkEØǁ6J!Y˯=qR.8>Zzz jrBFY Jx{]$5yf_&"W: _QeOMNXH* m* ?XlXi?Gg? { V7}}t|/xecJZI 䄅F ^UWoO??MC;}?y|%p".g:&',Q.ґ]V6to3Fn.hϏY$6(#?O̒+x@QvB,"@B#S>J([(el]e_d7ONXHު XDm; A͉ʻ[5Il;9ǾY!98>cVՀ366v"Q\*~2㳮,4Nwݕ3{䄅O0&ﱒ_ %Z~|]nhlcJMjqޔuǰ?L&% pٯt_p%'wܚyP\;MdW drr`1̜ mY|o7^XA Nر*5ţqM@w%ks^&[4n1[d}1##g<-k@g;)?e|m_]j<8(R;hW" !P7@NNp3j?@F=GǷ(kLNܨ;N>W%(Gm'X6ٸ]2y\w `}lKP&om8NlGv !q2e.Aͥq2e.AKc=W%(}7}LJe2Ne_{lKP&>c{]2<@0GzҢhnDfDGYԒ7̢ǤDt1ƧPR|AԪ?3i?򣋰uZfGWR:1 :Ҵ9_4bbVXgGw]?@g >2E9R{-=ze$Us_'#)f ZZg|V8kw~u pgL.7wW&vps\|C'h K6oڅ7Y`dPn-B@'l|.v!@HS5(N -曶? $ha1y i@S-?jmIzt1n Z#||um_V¢rJIc.`5gk)t|K.K.XlfA/v>s]gLqgTbvۿ=;M7:ҿ,FNbplk@^|ˤ,2eWF8x91<M%Bm>TJA̘x>;$b`K›jwA amGkó&r[I4s gc/?*-(#Z /T'ß+^,Wkh'1g '!QD^Jmk4_H=~ /N,$vx=:L2V|˴Svu Ϸc Irg+NdJMמ+An'{% t- e-i3EG-R.ufᮾ+?: }|5*.𦿘|>;Ma%`x@3uz_E4.ΧFz,³ K/yeBx_ Tsdؗk"&vzIeWn"7Y~kYʟ+y_ۈuGM'zfTf/BɈz&/*9շwگ q )c|ܞ1@ԚCBγ_{0gƺ;? p{f!`vbD{u] ?YIt/#G~g /$t}xĦFjS6; /kJv!:T< 4t/%G~o]f~Wd_TT6m[=[K]w>רnd!~dBGCO km74"y^ӻ;3E6>IJm.>Mhvg)^!G}\Rxfvb|5i8oF+~cU(IjʸWVolk4EN{>Nâb/?C_Www1ٺO[~Kc|wA5gAh1Jרxc0)kZ!}~P9. 5o׷F|5oѳƿ_nl^;|^Ja^(xid/L>I_;){bŧG<|ܞ=SB$k EE?=Ey@Op/=/>w$Eè<3M;r<@?Fǃx)AI\أffGgѦL4-(\@Csa-|Q|aaiTddzj.v3,4 ܋J=JO)٣fwF{k {݌@;{{?.({݌۾_WƏ&u1$,8v+)gv54׋:~Eu/3yM.fzVp>WϫI3(Uk]n*fKHH\|yGhP}FXԹ+HHܸTǟ //_Ҥw R4Qw~yf~~,xyyN[:T|}k|&/|^BYxy7'3~Usg'ڞvV)'T.;jhXhWRަPS**oDg39+HiJX?ZW-Ԥ)/dWjg7O K?50n: tgŢ bж.djCpyXgOV)"Pbqv|f'"S 3r3ؗ;(j{]/3. ;%Zwŏi)~XgBDG2 :2[\[)Q |Ց5Y@Þ^5VTt~<=y }ë {FZuR%\!x` gaKkO\JɷSyLtegljt *ʦ@S -yG3jnNZu &@\euYp*gk<=Dh%3 B4[CS@(!DK ͡ O؆t'H+$BwStv O0;V5Gz#]U)4(..h%_[pU|\<|ͧ/&[^czcܖ@٠/<,Mf5 {lϝt8t=w$xטy/*B٦B+oCoM>{;ێJ~+ZP⇫0#,UtyoGʗYfV>nx-Ck5 RgN?ڇ|Ӌ_;VxD$xN=ڇKV-1[תN6M}Ȗ[a3L^*X&>-ؖfQ>kwŏis3*߳c6-_PpV%RIm_/T jPFz=֜ U$9k*?Z/\A|[a ,߽*^hE _-φ I_8_ WAXO+jM6?O8 lGp~vԾPz'4?{=o}z*iuoH 1 j(Qh˫ BuuCGZ]6 g UTxPo Ol?o] gaGT{I#Z@6ٚ.t_}7Yb{-jt =Ḅp,K:mKVߡ6ٚ^]pۣ-|x;_΂g^i?=0돷+X6q[ɋXz?dkN@z^m5Y#=ǿM;?yE~#Nުu,=@]v><~ϙ:M_~UyUft ?qY/ױxV(㧫ɺ4p鏣˩( c_ u_kX>KxZV G/U,f~Q!:{kqnDBOW=? i>8^V^xZ 9Pd]Y2_ OJc h#+~LOPI X΂zz& jrBRAx^=.x>pydkSLmrBR[E@U5+VO+kY&qwO2I`d^UW?ZEHu; ^MNXHjkhެc؟hk c+d?J~6G[Ef~j*{ZmrBROFؗomK -GMNXHf#_lH~&7}lׁs{J7Ɔe??-3)r|{:nmC3{nE- u9kxa`ϰg\XT~^0V ?xaXGݭOyg$ΤȱjlzAZʝnR^=?k)e?L}n=Ky J?m(-:~5`fϭp lN'b-s?t>zS &[x^|Wǟz]co g@hl zz6ٚdk({27P3fByف%-?+wwBue%>cK $l7!+dϠ0 P,JzB] $_{E~b!q(XQX+;~܇j/f߅ٟShR[D!0GoYç_&Y~, e55@'A"KŊ1|$IKLQk@~'uǙ9nǖsԾnQ.DUSGO*¹ _§D߅ixJ+X}~.#'uÙ9.15IDATT\7)Cd_Jԍ_W5ohJU K[/3 Ъ7%@fYb?܏,yBͭ?t3Mf%A9=w{H`rBHYr5z?NǟH8_s%glMd ]E{c6|tPILe?`攫[@cT.7ꟙO&~WHq=9_S_"nowޠφ3mXOhMY[ TJ04s d5μ'ݳU˟3m>GXS {JLɲ?8tn*Y d>ikX=۳?d2?[jdS3zV]_ZBA N3}w$xqlrr'92Ѐ`DM5͵ӌv-G^S $'׵/j`_3;N3ڕC$'܌'QOR#SDj MտOR}IK,=F"@+GAIF4}eO$iFezSE#.#I +F)L/ N3oPjLLǗ2&<&km Z @@?W /F6N3o7U _m~cԔ h(_S @J{eR7'#%mʧgV=tLf"}f/fy7t$׺S5X|&Sƶ奜БH>x"VLx>ao7| (/ NDBONf`뾔皿A#~sԔq"apBE|BAm@{ow!vF 8jf4IM%ME_2/$%ڮ}ty6*"kY * e-aDQ~n" t/qv [Ҕ,I k_s욷HoEjm!Hdsv Ϩ iY$[-[ m?,ڮ!/Vh侮IqdMXǓ`0?oD's[XRI)TO֏D3'ЅhRº :}1zVD.<;m7Ta|Ѵ3Z+A'H:I$uFO"KkbU|7R >/CUutBQX~Rwǵ+52-vï;/#*"t쏒<%nbso&c%ِvP7ӭ㷉$׏ L.~v(_ J+:^p\;Z+oߔ<&06WI'X xf֐L?όI0goмWl_TIJ#GM-hm~~j+je(l̏ҐźL~?qUu/@X)Ia)XQ4?IL/ti՚ԠD]23&h?FsD-zV|`z D p4 gZe3 O&ɗwF;#2HL=~||gǏ~jQd`mѳd}C|5G{k+|+i4s$X@4~7)H/n$$vDq%KoՖ4%)魖#H\jl$ @綤)ICTaZO" @綤)IQQJNQw[3~T!EznKT?J*\p**,Qے$K5yQ޼Vze2ܖ4%y]\9T;bJL}Cu߿~)¿Hˇ_9'-Yoɳڭ-<0Ǘ<= R箰" mT_Ic,4$< /n]tE|֖^[[Z r{VX[A<$-?4l[o,X?|e?4|C 7.XUUM[4˜*+ k4oS^B} `DaQ1*(M$2ϷV~:b_ [a-9#9!!۪m86 #G4 oVwԳЪ}S._49ZINp?HI\:>.EZLqY2l@Jƥͬ9Z40ǧWھb>_44yhpIwT|zhFk3k#@֊j~`V;v'4!-9ӳI>QvEچN\ŐFIr7?5s§6[8!~j焿%%:+ ˠB?⊆*+ t60dB<9p50aQC*}#zyts3?)Q| vz<9no5Zf;ÿo>k<`_ Zg5,f.)Lc(BC2KS^:ytssܾ~c;Co|\# =֠*7m?p:_y}3b?Jؚ 1%Ơ*s2R^in51(p~N#ck-3U?<I?1OO0}|zP}N|8V!G*@7`kVvOϪ`~Ǒ L~?/C8dw͏~h?u|y B<| yGM~E?6Y;~C%X S \G/Q {%ZݎB?.z];iLJey5@^3;_S_^[epU^佦G<` o(3HPvONY%jݹv#$_8]cD'Kwuڎ:g| LpNk7A?5̉Nw"ݹ$_8SgB:tڍ9o| z&EǏ&a밶c$_)-վ ;,a |;!M=mJTRU1G|vӦ{J^׮Gm-)<{ψ-LI|cp=cVTKyc9͛e/|ģH9?UK K%Y} 8#ڽk/?qRɥǕ+ھ[rY^oƑ(CVVp=cVTKI qd;G?0f @ 2ݎw*Q|*Xzdpܬ`_bR]xL5k4}jq C 2oΝ/eуМ½1ߖjCdN*CѴ XbV0*8,O-;S a-?HwjV^~ٙÐs- 71M>L2Ad<6A,cEk 6}4-$17Q&i*hs̯?hW^ב!9AS2__ ,ПuJȋb՜/q@_v~3H';~*G)o=8zi`6T{xQpⅩ_Qkx' HG%:{L^k1DwI@3`zYl3ѓ+XgehQE53`$"wp~:(~?{eQ [CxP0'gt f3Q6Ƕ_ g`OB/ x#tE|S l_xX?J.뒭*F(~չVq^~}q Vsd!w:2ɸs7iĶoq>լO&s![UEJdkUtyoTdr5ċr^ y\S9Re?ȣFv߿sI8h/T Ű8Ul]{zaU|o7-3u܂3%?n_!؎S>;`~/<%iPVQ{̔j9\/&)i GW26b2݇3{13{kHZDQu. :K}x% ~]DEibguSg5&v&1OeXS6[Ε@6[7#5aspLaۺ:wq|s4F}FD@b.:F_p*Oun Q~\݀!V%ʔ2 .vOh |mJT /:ďI] g8𖦌WB$Ӫ<쾾R7;jZȲ ؋q +~%c6Qx]WVEpͽh37W]s.\ O\F#+^PR#Ǯɺ|y.n5"n>xZWfm{c?7s*OZ%/Ag &VyLtpiZ;sԏ gclko~b5`]c5 1.'oh=!4Njt-Ń[SlR3>xlڕ|Hu}`4sW֮[&o{']IO6j]ϺڕE,z֮/iv-#BǷve-)[X]7dCo+aMfު]wmdWRmxy,UU!< OЛs+-*slc$<3 }CF.U(*P=ġXd};#U/":bQk}>?UKxᛸxz?44A߅-G~AFjɖ-FH44Ao8Y?jɖH˕J#qK?CSQOxF.εƮCZ%Y^ƽ?KF99OjRji_Ń˦mîCZ2 H Cp'تE1h Gc,(]+; @Q&9E׃`ê+fS~yVMYscS @@~(@vo:~<}4|SS}Ʀ킩\єP녙:~M.0~S u>cS.AC:,߯U_@} SU-sb힧* v&\f~b{t߭iw4 S\M`[%+S6H|45*S/fӉw{+ҕCq79{{֘B^ 甁jΚw5˗4/vcC:pSwu?,].f׵QG:]\!mv\Aj}\A 䴟=z&\Au3Wb&5]0ӹ I>ݳ=k`RuLfg5]?)*g?Tu&KwfVs2@YouHݳ-zyNf tM4aO?ګ|e:칕&3]S ; y{xZNf}L4ewQ$xٖMN9E?)LZ*!zhK];uFpHBns$Ap#d~6C눽p=j~^rЏ,l̶z&֡ &H8ҭm$>-Zoє$"K˾.D.$f@5:|ն-gbo7^%]_B;r@ KFI͜5Ey.'H+b vK% 1}>,X̍뒉G~m? k/Jgwޑ>a^{JpheYG`S]0 ;n~x駺a^o@`8{Ǜ,bB}CFwPCv%>a%phk^j#F@| ʢL&18{oa2ٯрCtk}쳂'#0V}†L"Xm ~7tK#%6[гIc㠚17c2 agbN~Bi(}u5[<:&3z|5 ?@R5ԀN5'bo4å7cGk cW k(,,\ R⏆ϝذj3ȱ =8 v];!ƼV4 O0-u۞ѳ` SD(@o۸[ZdJ k۸gj"(vK xyKvAֶq'8]b/Ukdm;iԪt .Qi<~xD;q|:|PMmvP/~pV>WKu>?m|\=TWۥk#L 0#e  3: 걆ź^`⵱g(9M񆹟׎j\|zqjAH8aho%ڮ)~dǵD_9&s󷒆uI/xmP" !0ÿ^O>e11/FWHzb0|AX7_<`-Z5u޼#Ƚ?k*Du Dn2L~Hxh3W`XRj_&EHg ?f= l]G%MS|BY~;hb~#%º^AeKUi$H<\e~>(KP!-Ou/'`,(n~\xg)qՍo `w[I[sbN?5n:ɍ(cKDej%25elb2L-DVL-D1b_J}jPtAfMºs"{ӬE5U[!]|eK5=ΉsԄm7䃮_ShPߴ7f'>g I;*>qgXlM=svFhrK.1 5K._/,1\(E yb{J&2ڛ}PqPR8/qG]Q !áMvV  q8`ZvR(N+~L+~UIѷ\ֳuF#1_|i| 8.}|Y<2FdN۱/o枳%b|{ {vm Q&ߍOyk&2*Յ#S;/$4)x $ʗ37IJ pvf _@4\ ȭ !N6H6[Bb6p)|I"&j1$&v:.:TFZبz)CGn%0{I#'т? @^d򾿋/' ${|N#ϘM yĀAYS;~ VŃV wwS;}1=Rj N+iY~1f|,?Y>N,xhLfES+#AI|} X;ȺY0dU <;߇P}x{UóGB}vkl\c'T_\܊$(%k\lE|m¶/y>z@]a_-{v@4"IcHB_YrEX&lv^oT_t_/ڄm?ۿ-!yI>cS'HoXQ_+Qnn-.zC?Aْ ;ݣGQ 2e9>Gx`OYn@-퟼j}nčK3J!{*Q#Gmߝ1xh ;8TfƂ^)0~mp(S23[`L7;>7Lq8E9Ӳ5~ FA3k1j%5s;6ǿ@melVhyxw$9j+-ZZLqY2lVZ`c5GÃ,3kjIip9LZZ횣{z"|KgOz7ʩiX?t10uxe%9`:6N&/|oO%alI)lS:w]čKMNc&c/8i?.֊jvχcrp܊Lxq5[/SْccąYkQ<09(u_~GM8Uk1'ggpy?hcJo,/ſ̎-O*yU3\T܊ҦEM$_4®E%H|-+{ Y+Q&[Ҕ7_i-K3EġW tfUJ8: #Wx.'g%%8`pb^Yc&(u 𙵗[N>Ito:9E8ϬNEED>=r_!>GnCگ+~ wŏم8rCf<8Lצk͗ ڵ3E>3^dGߘ/~;yX}U$2Tx;^L,;Wvp{T}m#i~Q\?9({IOߒ$뛐hQO ˎDiW:M[>x+*U$^,g4& s̈́ l47LhF|s̈́ l47lF|s l47lXW7?fǣx `S8/Hʼ@ٝ6ؼhWZ?o؝iOz7% ٝvصxY?`o^a-=}ͱ{ .͖ fKTU\*|6j1(g?~1 GM}P*# |4)){GJ| M *˘d%lR|Ӕdy:w UMkfN2b3N:q_PPI-?#|˽|W;:~Z-G.\#}p}*=1ϩj'^. 31U;u6Kr9o[ K,~-e㈝sLrsZ#v1Uq9jɎyT-;/Ǵ*-2xRIH4[#" -iJrK͖fKO"6u NwEĮqWt_/ŏw Eiu%JstfȀ{ZUig-}ք68.|DRtyd : tyĤl&~Mmm[S|ȼ~!ۨXAX4g᧺U(}-Q2L)qRGmTSNov*|S1-KǦݐtM*S%7yGn=ʦ&Ń[SlR3`uloKzTקN sW40Z:6I}#gK 'feg]toK_,L]ԁϲoK_(Zs,:W0R6yM.%.o˜vdLGԠ,f9, ,헲 J?1'_0D'F&֕]K}Qkˉǯ+2,+h SUﲮI="b4?8uTwŏQ]cu.t@_j2P)8mbpo{DzXyOw$u嘆-ߍ&$Kz[g91@w4e8ѲN7?t(_h575uB^mMٺeW 5MMmzO1ZeO'nߘע]rɥތ!@7 T3ϖuj@_}:S zq .g;?c?uzWâ/m~]{\uC 5ӟV9v8XSM'o>G֭id=$_&Sϝ?1.ҿSV'B ?pB̼pW{ #/:ɲ:= WٝCOCu.?[րSz~~]xy&,F.&dٽr.#"4n~"Ȓ.j k;;=F"!7\]ytC-o.#"fP>|c1w?S=xֵ:AYK.ϓ;3`hTj# JȔ:+}I?4Ρ|CZWñ_hp:<:c暎aIq%5?.xxꋝEy7[#—WY>< :et`H¼gU\rɥM0Bkwp5;8t N|sIeʠ]U.J4y[ޓǛ~RTPHF n ˶h?ޒL/hCtboI&=zYK.M]rC5sdS3_=ZߒL,,(X><|z#9w\Ӑ\r+&ෛvV  qx-j`ZvR(dBF{GpӡbaեR5 m-l\G",[^ r +|4l,)J}@N)Y?_R<~La)j됐jDVD%dJ;6x. &49|YDvZ _&֋yhWGG:@11s.w_P ҥ^Ct :B?v2i>@=9/=u VH37N!fP6of+_ u37IJ pºB'HVA o*I! Rfwg5ʞcuH8*60hj d_IUI,߁2s)I'8{(S[Y+_̊ RS,Mœ:$lec-K;5 td]cl׀peKɧs T%> $[8Ɛcl1n6rt7~ 9M?,f80kN̩ނ)5ۡp)<Aк d0d=}-Aϋ$8/ rRD"@jrnOf߅<$u AR,yb?U7#˗vg 咁P.ڤX^c3Kd]N \fpPH 7'$e vÎuyp?_-Qb䱜7poя_an,r,W*^ Oɇoyj,W0o*͗˕| ev37ȕ|/e,)/Sjß뇋£tSjumQU[o:B1`T ;)A>6#;!1̍-[DџE&2I PT H=R4 ,/P+ŽcJK7?G'<%M1H8V֍w>@yyXP2.^?n|?B/ul  t5{Fџ)b?#DǯF(z/YfB4@O%_l Ph7tm!x+2k+*e4Wn7Ctm%Kg GfhytdtmED H_3woJM1xjS }WX2?fPT pF3ySh6#zu8zxk+vyI\mԣ`uRmE,Ymmnb_ZlkE(muVDl<=`t[ˡ|>Q>S,Jă~#lh b햗=O)[^[lB>h[^[lB7[^[lbYkd靷x@ŧw޲g{gς''s$F81~?'M%ʌϼoM^3N!gz$o=?>s(?aKEFΘ?BQn\g)qҌI+SIBM:?j@ḝѵޡ73e>LKaVc(?Ig $Җi/J=QJ=T*b[zbEVqUZ]qkxZ&3ϼt<5hʯv,ŭˤK(7X F<FPDFfǼf ; ;ҚCc{G^+OvHOr9ȎFߟ]<dGX3AM_ddG1?4 H6DU@Q*^/~-1M^K<ɠ^+Gqrg;hS7HRNG*>g93qz1ӑt:mtsc^G&.Uė;KF cՀ'r476,8?4$nQ'F "z#rx; OwLq:]euWn篥=ů I~^M,~Ų̍QWy4?rG^}$Qq捋^-!N;]M_rX/Y# _<gxEXKS,I{z[2{M3&`_WXWS۠k <>bp6McyA ΎonP?=QX՜bQwn{|ʼnyO5/3:o,F9d|^20 K%/ Bj[0zz/oNH⎊NOrLb/W;'=\C#y|S\׹ G#_y4-rW;EwS.+4m?\m?\'|,W~[܏i~eEl?&7}5 ,\T)]ѿU҄4lss{?py'| ;ƷUV@}I9$v@|+rcަW@]a>gZ_) gߊeK5,?w53w>䝾{vϦ[DϪ>|[9n; *GMJjȭ,ӓߘWSGG~CiSjMOי3Cjju65׹9o* @\ Rf%$ fAi^l# or7 _zڬ+' o͊,7 _z, o@~#dxq :UOxAW>B )H1ԇ"Z<2d*z'Ŵib3:\㏌v\!1 o8 Q]-[C-WMd0#-7,~䆏 #-8dO;elqEzց3u#3?+p'aajvf!, v˪Պ]3jfq|e| UCkz>ڹg?3;gf΃{49vfíg38>h|ӲYǽ?Ce]5\H)M7զәߦ'|xljTj'Y !ArA@ Ufx|GWf03F5oZ_?w\v΀|]~`Kֳ/~']A=)ݿ˞o ozj޹;R,?ᴧ,Y|K]g?~ g[)Kֳg&|W >9T ŋ //6LIu TLş~Q&S?..O\+.nXL$?x&dr?}jƍDnH~p^XM3~lLt C}hPb#Ysg͚b Ix>QQ?-‰NjЎ?fݸ 3\Yw\iDBxm5lӞo@oɩr, =߀<ޒ[YjS\xKiScP|N yO,ACGZ?yB)<l9 <<)r<(>yrAΓgOu%r<(>yrAIxP|F;$r<(>l9N6h'DKI+RH?A1: 9U511[NuS-i|s+n$1r+T7F7m?E5i|Ko$_Ԩ$7P&jnoj>@0 s[ޔ{l?r+֐h?jjאmUgCiS~l(P`kNHC8Ȳ/^:-gt71Q`#Mw?S9?[3|ki]7~/OLsxŒ-;OrXo2w] wL1? ?S@Lh0~v@ixTg r_ ҵr) y2UB!?~̙K\^#`3mk k?_?F%.U&1q3*> k?18;dѼ50;5i`ڋmD͡q=c{#R}8G44֗Oo`]ZWO }͓{Jy5 y5Zøc{Ecֺ|/mjZh(mj49BMG_QDEfVkEfW .6Di-n#,"YqS, )CsŐ1e,wm"2:\.Q[YQ'۟p/:oR$?猓=?nY%SfB,4;sK^&5ܢ3óvHsMons$*}սs$j?@g%k?zo?y>e)dEº霨hʽj/d*'>z>tZ?+ `k]a>}\#SK)YqSwO(/c+?iؚᢏs}8!ɾ?Rc}¸0<«O<|eτ5/85?.'gh78s"tBGqqPKiχ83XI ܁EG }vם?;>.>>n;s4 в x4qio78<=G b9 ϐ|ށ `ۦ;G O;D4!}Cè߶]?iB >:ם+<|uVh~(QƗz3CHFx$b\,m|gƗrΤ}x_^`pqYu-|Sk9Olf5tcyݾmVه ; ߛxㆸoLY_q3掫~cNZl(>*M;n)w>o`z˖LՊuEe?pekr2|7K YAfv%j'^#?S߮-m7;:_hZzTXհoh/^}=q/M*p?˖GL2픮3?+p'A J'sG.3Nݎ;R_u"{e0c7;[tj?A9nk\,;k&5a^7%n5G{~еׂz`D]YO2^T #N|s ?uӍGnz8הU'}i̥?p˗\rޑw׼":ұ ǙK}>d>pv<[rNPVG.^KS:ꗱ󥏸Eȵ:A9f3"=1n]0C j]{߷<>s)6lߊnޭh U\E^g.E̚pa<-@ *~B'^N;e|,\0/}7%eł_?MwH>Яv/ru4\7i\E 5_/n9anslѢ?{w0Yub2ذ.خELYik6Meg:݂EL)p[4de< "y~ڏCoAbLBԤ$͝.|ҋ0;O| n6+L;Pk&.oEtqq ۍ3}f穖r(b"hghp wj?j?>$MsCyR5[*U+[HefYe 喬?sCyR5Ԗ#[ kZ~ksEj?(k? (xgGz,MnkclK5]"HoJLJ53pPcpzW]\/|X@XLeU^:BG5*ǒ Q?%Vŧ~\cKoɫ OƖj? xQLaB=jZGmy9~Q>{kdS1/wNA3&Rb4'Eg4'Eg4'Eg4h9X/)>5uxpKnir9v^ 9uxy.7Ò,`%5u65HcտQ5ad7Tkc4퍰=7 FFvCse y2vΉ3GQG1s166Jw [3I8&}0;ʗ}5Ix䌲򙣏q(Zb$| !q(|jMudCGj?|7agܸ0yJ'M- _Y/~`lx >3O4.}Wp[Sb?Ow"ɩrlPUe_Go5eA?g_ ]kjj3~J7K`MiScP|~~wv:`vps;əщ?ԣǥ։c<>Lƣ1Z/hd³RMSZwvI$#i]3S:u$[%% 5\#;-̀CG ў%9/ZTΉ 1ahVigڹy5V C;Qs>eh -{Ek>eh,iNhO?'Z,C_A |5`ϞQ=ṫi({şl5g;xl{,BÉn=rf.^}]V퍰tN.B )K Kx;bJj׻BWK_|!%?B )$i Ի#B )Kv J[uggE2^yZUmxx1ԡj/nsо^{yyUY`GiL~[eT8ԐӘ,10lj \ǭ-?{ߓ`;㐍PwX?5~¥NfrHR /6{gtN$.}?{hه?[jNp)u {gu2weÎ൜/2:0sWx7rMXqhg3;A swm)>ư\hq| '9v\:wUSQƔ 9k7#%gNcM5, bRo4JI(@R;%mc2ǣdVo ,C d7UVH.84e~|iLf!/;t a or֊cNTVholHL";^:LG-g׻co}0e|cc^HGCl(V*. \㢴l/OrҲ#eQVH0]QVQw>:#Z_0_<0S?}&qqH*]51BnNÊ6FqpYW2frx)'7@K0fע[npթg, ކK6ir)'8:%` ˦ˊk< wt6F6ĚSL+OiAqvT2myMq}&,143ȟ`,}AlMZ/=3]޷)_ `HKJv o}ɧ3п-}o$"# ğ6O̊0MktGE:> ÷N]+NT.UL40'MC1љO6]?~L s #a#>А7@bJ`2ڹ?to|Z/Tr>31q3*ҹ?v 7L:3k>x|j[/SNuMuf 9NLsȭ?2uQ o]({kJv糾bf;s26>qObxxȩr1i~45fCe|m͗!:=d6(\2jΡuNtP6|DQ[kVY8R罵}цFE&Z…n2Bł9=lԌTX=c w|%oYyov㌐@ߧ߄ O=P0>AL Ä W<Ꙟ L'Oa@}5`:Pw4@rDTb-O/Sc0a|2y)2L}72 s?jkp<`Uˏ_B8b/MĦ0%DQ9]3N <P:7w "9]/c16MJy#[2s|l1}܇s}8bO7,Dtπ q5=}QL1 Oq@̟˨?R/gaſzeoNKL_;EN_/4uOpl>eE}/Jn%X1<<~YI/4^ҤOQKx!nw&h0=P…n` L|vl%d ld?{8{0 }j)%ҫ_?f*?U~V '!#= @OC(A~0W-OK6gOu ܀p.h}Ne-#8Ȫgѯ>;6RCH4pogߓLLw*.Ĺ܀_q+7&݋;WnH0UXxI}&MMܹӃU0ΝsQO胷`SLYx[/ eT5ӣQ''b͂|0'd|#&Z5/QR?w!DO#q.bׇOs1Y@ׅ?,=۟*fA8 <"Da/;}aLtwb){0fK},8e%k7LS|)ɿǎc85%KOCOw?HG+Nʥ/}O߮<ϧ_}v:^]>Ko|1^ {]fA?gITiL1᠟S!˭{|G%brL?hZ"XB5,ٿd|09S\ wOqf` !p~Inc(N&$(vdmiUC_5Y1'9&QD=KO];v鵳Et9Qv[ԙ Dt+o}@w;a Gza݈?-k|z䏏\J>y /$,˥Uc^e|jjnc_<9?\;65Pں]}"g>֨KtȬ}=6ȱ̷0{{W<O} (xZ`ͫk޻){ ;=s <.Ѷ[kC>x } T^}X}XPJLzZqgjj~_&͒36I|Ywwpr`/IyH{;U]{d2%rb .ysE:1pjKȚbN-r c#0OV`MmbHeFlL ޲}ߜ/}Έ1'GcŁhm_:fi}]-Sfaq^q>7zԬpg|kS}n,|v[|0)4'@3q˗#ߧ_vg|=5lĉvw-l#$gb}D׷mG0!SK\yG"~?0;Z17y"k:=<.#gjŶln!-_Ib*$ XN`/b[vN` ?ʱ^l{O?'Z1_I1=-<΅_ܓ&=FD\KKo>G| )8rH֕ N[.:]FqqF7wkeS^98f)TxLUT9N_JLϟAwVRC󊕬Sn-;YXcr[D|<`C.1be3>9q@W_tSi˿?y&Ng 5A1DOɥ o='ė7x [(u b3Po-Re6b$#R&8$i!-ubCX|1W*2[q N?rmy-&M3.m3T{[=I޺=<ԕH?4֕bbMR|Ʒo IEJξm{q|w"=^ѯo9s<2>|*6!<&LvYQ0:8×59ؽe3b-G+ʹAkb1>z6}?id4눹gNçNeaG3g sf#_xg>QoJK qQ{7q/aL|OoU̔1l,ם:n :6ptޅ8k,еzAL,mzjfsT& ę7z#c0/i{Y^$ƽ .:D=uiYxvx Û?+i¦SbY)FWRԋ_4 >~m{$iyƋ^cw~$4꣟F6_D%`yu{sg#J1 5*G?f?4O}o@O/p(HȩrŶ [ǚMg>_T9a6F96 nR ԮovɉȾ_}p\w0=(/w|B+<*oXl"/a0X>(+U~f>_$YvdG]x :T/*ņY8]z硃ޚZC^M!f7Pj|1d;:Ly71)mj465nd 3vf`ur##c˜q/liFGv .!guV ۬2GۃrKSV Cs8#Oz_hNS,/fXS0T9 }S]HSXNyԓU@OF|l>@9eq83yT c\h{6QNcdҙO?Ɨq_֟m|%;{}( CIxи>?}Ql܊cVֱ@|92XX(FgUo8+a^Re\瞈Y ^n$X SKpⳌnFgFXy* zfK\rXz=f }7^]O7\siK%״~aH ?%`Y=|Ujz2B4:WL/\OM$HME6QPç56 C:s!jlLx}XD˟ ^*΄;|*7`Cc&+/$xʈG%]d+GG['o_/Τ߾;[|}b|wl狨fe=7oAc7|U|c^M7aߴ~Gbj>O*6V*[*J {;l` 7xwyx;ecQU܆4DDX=sѵ]ǮAGZttq՜b14 "D1 , )I \ELS0_X_ˋz8<;SeP^$r=MjcÃ{!כ_uf`p@^@! G`NLc6uyí|!C+n|,HBfN=?>x܋SOAg _e,ak7Axbk9! \ bhD& "r&GbNIOmے?.cL@mC gys7˞- )H=\t]xH`|3BFxR~L s.%s[n$9I)'ṧ֨K;u}fPZK Zoβv z(^+?YH`|O!CZ3*䳮s -Kv̖c#ΞUv& Fo^:hpT oZUF[J7YpnEˉZ3M FRz21F jYI&ok%TSs@+'TltQUA pӟlٚؠz~kXd ױ}y7٦²gu:0*Qx{ɸ]t糞`#k79bguW4&o/oJMޘhV7{Vg.`E+ZNdM9grq j$1Oy|2R`~Nc2y֞y~g>YoJ8v#}g0Yky ҡ!^o[QWK^([M),\m2ih|y4|N?Z+w+${SZ]|^1B^'*TNurP9@@W}l|<{Vg+_%|{VN0^J2==|c|e^/C6j?%?r!Z~B|[NoVT~ɮJʋ(Un@#xx땔V`<5w{4myҪ.k]^Kѹ6}7FF. !$d*u 1}y8&sh o9zuK~^D<\uJ5$f$sg2U{VZYo4_gustPuU%g;G/l}&1ce$ 7̝%]˟Ds ITE|Lo)iw\駧0PxS&)9pMCu$u|yS^睮ȽN> 0Di7rB0̟4*}> 6|J}^loo/J,}>f! A|`6\hvЛ:u1C]n<>d9Izm•SQ7 b @$鄱=+I̘ Z` 2V ôdl8v CݼSĴ$&N a>>!*H dXi$ 1w'b"@L Y o|xa0)o` ;?w~"F8uMaW;Vk0|F0aٳQ-gk"7 |f+?SHC39)/WxiĈLVQ%! <<#f(I*{qJ26p` 1rDQF[yĉ0O/dd>HL=|a,>? Gߟ$0&%^`G"a6$`sfw+?!OHds #'p|Q? |'$&GuƄ@X˼HmL(]^yLLʩ @}a*ocߗ.0<\G?H~WRY}q0+ p>7G! qa"OԄ|"rzkp?8yl]ghfp~d1_woޞ=u rCsvgt,Fb)-Yn 9*~ֲ-1 ý%@,#G+};?ӛN99 ȹsr~ c/:G_T; l` ?wh(o)<n~z9S+qﯤ6]c|b˒`!v{Ԫ6][1U]`}x[.5iƾ><)PZn~gbvcVp/?L/]tn}h7F:c|_t)^R.z?i}70-?CmҌXty4)m@ttg( jV8RODfo3 ƌs_94#fw{ft]B_43ώos"~cWnZJ'c{3lFg%N Ǭdloݟ]o{/yEawA&1W ohMۇѵ×}Do.i)'`/F tr@KD>_޶fp ӦpY7ɘ/1 \w~ɺnjyIj? LCeN X3)l9}]L+:)>g\|\D"p:L";9tD/#@|T9 Դ'3+mqvtni<3ְa$g7ЄErc,_K}߹9SF{1_yp)g:λ~zs8 35=ύp4*lx|#Ӹx>#Zv}(p=̗5$a]di|d0]+#,[+$#?'mqz`#].\/!r*) R󊕬9F_NWySO&rӛ3 ۶ Fx%ApƼld~o_SMsg/oXQ^ Ԩ~Eڳ31(k?vڕ,krWRޅbN:_fBWeֈ[86`G7 @ӈb~-PZW ?TL㊶lhwLLaÛ\vŘ)ݟ1oXfg\ Xs/逡C=m 2O>C_~?mŌ4&ۤ$q bf/;Kf,y0`G@XE*KJQs'-Rj3$AMb Ԟ)k?v>S9Uk9g|xW!e*A|#>xPb =U5DF?WC$X?zW1+ƒ.c _o4+d|M+ǍC,Wl= uK{*d|k⫿QDM"^v>Dz$pշ}8}?R|7s5XOXh̹&3Ph&?3g!.7yLY,?1s0g ͳK,ql|tp2z~gHlR|!OqOxE2gNM< =w1gu P)`bٔ b\l;q aVI0<.8F/J7FNG9sb_t8eb -%_+10!^糦g Q;W h^Wg10̟CFN&%WeL5 6{._6<|E[SF;GV]㥅saCHtҁqݒRF{=)LF$F ?rvД[6z6x8{ !ri&o//Y> 6'o ):sqDr/"m>*PþUCHgLyI`J?? Vz__8?`!SyрFhH!l^,}?NGinV?`y.?΂ȓπ!]O?hOzTAȀ@EXzkYߋ{fz*My y_϶0~8}镫.Wef>t69&yOuqq\\cO0Չ"_<6KB e)F!n71]Ɍn5ny*dXnG^)𐛵ϏyNmy1_=Y/akjDuhFHCo^mQe4=ܩ/Ȳ}Qdq W>|tU9/6uny3;`_bk4ús>h|[׍3YBǸo0ϩ-DT5&X|5yzqG^?}T98-5ӯQ^c^gpIgK^HƘ /S c,cz ~ێ歔U^ KH=`{ ;ǒ`}~kŶKgMgW$<1`|k Qߓ* ᰅVq1—;2N0/֛Rӳx=,3ԟ s.PȏȦߛϿ\퇇YBWP^ #;"L(#֔/3@^#邜p\}y1ʗpg_ʉ 7M|nãL3aVw$^(G˹?_qVPa}s6'&ynexň 8\Ι%}bOe450omg~ƱoѶ(ra_Թo9k0(0DRlã,cza'^*ubڜm&!2Lq?C*' ;~xE[3;l郁~/JoȬMl)XӊwY_X[2f\mr/*bo 0dOƄX^;|7ާXE_MH+yg47e)1DMxGƉ޻'>}e\zj*;n@UY`.EXEok6Q`y1m? ?A=A,fI<| bžߘ_2 0\,T; qqbܵы_.2jm\c6~xD 6dQ`yKp~8-\/+8 d?ҵqqo} --+1"bE0/T~ W -ic6uͤt19z?]P蹣'tC&1|xӍO>'tk)u'ًmzKuʯҕ_d1pֱ!OO͜c/b\^0"fNKኚ9z5s9zGAܾTҳgF^l[3Nm&R}Io LN- F1LN̬}HON"yם&tj39u2:\t :u)` Y fbf7vj;c/O3BW,x8?NΰghΧڎgxTŁC^d/96j/3 '7% lEK^ wj?x\@Ӛ4ob|3^>an,Mݽ.ց LӔ7a~X I>P($W܆j[6Džp9"/WI14$`5n L#8>~UD`XUO\q7OÑQт(Dx$G{j}Gag'5 MOޕSXEejju65ʯvu7X`h &Nju.놝1i)?e[nُNju.1=u[|`dI `{h'N[. T@P 9,лcGx̧hb_w/-Ԃg30y -/ {y'i]IK$Х"ʩr4hQ!1VϫՕ_Ԩ+֕ߜbьSX)d|,,V2AKdEjjp _%2"KM8/sej{=|Z",ԜbY)d|,^ZXB9UzqqRʲz:S*siDTN#┥J.w=wF)KS,1S--襤󝔴pwRNJRN@*aF{-U-?, \5?6 0_51 "3K5/US,.| LA4&7س:}Uw:#3;M 嗳7/-PFo5 &?<)3 &>o7X*-ݨ!TlHtSղ"эLUD7j0U-/ݨ!TlHtS9UMb[=HVX(lS}InMuK7UdfƯv7Y̺S,2:\xL cLtowb{E7w6C1^l˦!zy^Kʳ)DQ>bgS|yŪ&EUd1gS|ypeS|"D=_T%f S(?Q0NU`F@:UT%{,v2eł~%A"pN*NB):$2>Z,_@Pd1Z/(!7aPcTH*^oneAQe#xy55Fَ65Uf;[rUf;ۜb1 K)^lBdQCr+t/mjԕ_roNhʷZѭV5c^065`^~+V8yʼb%§`H}<-=ҁ@ifp32ii9-/ W_hrnmny_={KzG:0Sw4K3EzG:0Sw4K3EzG:0Sw4Kjց/ '>?:%{m3e^whW'/]<4.ׅ?a ~닲}J6_6C6s0&?E73ٕԕO~!_Q81Ae $C. ;juj1:pASO=Z/0OLsʟ=kXW~ )A"Bx?(&1 FUpq :cӇ=Ї!Ds^.h$n^lʢXB&K5 +׌/n"3K3P"Y3PɌW@ض^l#f"vEaLoGF"\{ k9Vꈹw;a {{tC|&||q\WXvq:9ݪ/}zc%=HZ!xCgtt) gs$&MU7@gILT~_{}t֛DMBBk0ѱ%Lt,9`cK?Pt,1?-Eϙ~v9V=6]7N?n6M@RTm.?4RW1#gFTqbF8**I]qbF8:*SAxa՛TB1_mZnڒu{޲ . )FFx4:̟NNB[Tl1ƎPÓ8nDwa߷iS`Z8Íؾ7<k"mB7Rb{1qu 9Hw#!)p#%*(<st"#_!@k :Zkk_j|Z@Zs[r -':=o19?v`cNP$yX)`ISjT!-B*׫ŏHz2Qf\RW?2*F*׫W\RW?:2\*׫Z+6YSWJbʲ{W͗c1h.w|=+S,d*VA|U+Y D0_955RER2=iCvؠ =EFH 'x*!- Xd|rb=Akum!C=_h{,PTP!RH!t!RH!SWDM&r:W7ӹMtn"sWڔBmJZb`R}I`R]aF9BS?sًm54q>T_Rk|B0REf "RFǗ|F$P[/zM`k&ҏI,g5j%,ZG&1~]a>֑I_udYXk:23:\k:2elE"_,V|,BZŲi"?$ Fd(5+%((Cd(5?V3>J/mjԌORc]nd(59Ţ`GZ `?_Z `?_Z `?_Z `?_Z `??VƖR3r'R3r'RMO$ƛӟHJ71??Xݒ[Y$(8$;זڠkKiSc|ε/ѹ4Xd&7WJ%BqsTW/7WJYBqsTd1+ ͕RFK7W*qri+B2E|BZE|BҦFE|Bj[_*q9ŢT?t}Iy`PW+"3KW~Ŭ+?å_ô۲l( udф/aGPIMB&~4 ud뜗T9ED2]y5KuWܺS,ZCPkiR_7‘lًmDNàpd+[%DneAV 󉼚Z‘lUdfM#[*j۠pd+[.b D3Dm9UK[9>ei(r|jj,Ql (65XPįv,Ql ()ۋm9UuFtKөelhSˢuJ5>ןׇۋm%cƯ+m}D7~EfVo/srʽz l֍Oz6'=u㓞ͺIfR'_3k`fZ@@#N͝qP_RNxci݌鹋=}3|%tzzA7x>ޒ|NtԌ§fTyA7%02䡲|s` &lWyrȠ rKWlx>Ch`2m#gEzfƲT9KoY# eFb|S}ga][_R>Lu^/:t OLI%z6um]aZ7Wo RxR}I9{I+ yu ]),AU+yvK.]=skVϫՕ_Ԩ+֕ߜbYS zdzz=7@a_Rff\^^oޱQH_%ENR덏#!%g|,#.Xfɩ2>`ڞ"&`jUsT96)(Ii2E|jjj,mjTW~VW~9Ţ ?H~ײWؖ@~ײQؖ@~ײQؖ@~ײQؖ@~ײQؖ@~ײQؖ)faʟ6"G:G]'3҇=4 {G@i}Cã~@9eI˩r}ϭ,ӕWS+QW~˭+9߹r>';׍O~\7>'sLI9ELNgK9Nŗrг%%1 R-- }]{ٮ+R)!ʡtJP%2MuZMYҦFME ք7XŶ9 $#W%@N2rUW/:ɨUEf Q~,ȯv5gt)M2rIԫ^F.iz%͒oGZnɭ,[Ğހ%A /mj\Ğހj{I{z# )B>e/(j\՗a_W//Up$ /:3Ii%Ɋ+]{H-WB[t# $_ϵB )BRٶO.BR@  RH!RH!$=!e/YOdm$ W%,\'+gQEf_Ԩ)bf]nM.9Ţ)+H%ʡc$В[Y91hɫ՜Xnj)mjԜXnjv534YR $rQ~ EA8JҪ(IbuT :$Z!~C_JÚPbA::&ʯ/)'HG'U"DuJÚ("3ZO>,fb^Wdfm$xQY.ƌJlRH!$fbv|v/)WWp]ab"3K1_Mzb3.ڟ?B IS)0ҥrr"]T^TI˕azEflaz,MARH!DV#Yב{u{u{u{5 pH!ҏCj/חʯ+ו_+b pH!O_:C|!RH?ŶTr;./)O%袺Tr;.J%"9N2:\.!%3J9Z  JSއE:`x(nPȜڎZ-k4Jd^ Z+?mr bnʲry5 uVȖ `ܱ3t*Fu;kƧ:]Ú s5sxM*37g_EK537Wܚ3:\49tÂwj`jcW+K+>:2(.K,W*4Q9dOX >,hT'WS4_-mj /ՉVA:K|TaPWA?ԤzEzE26cߥ_ؠA _d@Sp@SUW&ŶR/)ו_W+"3KW~Ŭ+?å?ʱ&aȩr15-H[Y&̐[Y&]r$ͫ]WSkȫ._H965/mj465`-3ƸvT܆j[6|u$`κ/-9ϒZ1Q KxLT |!~0" 5)RZ@4N,!6pfi' 5'Ee=@ɚjcf՟gv4Pk J󆅙{X9üO )I yi:oXq1>1'z/r5Z۝6^ 3sswmm(9URUneZ]M]n])]!X1/p>1#%R0Ƃ|rļ]jXO_ |1#%⎈},8U5c„ ]`} /&ƽ^L`AQpv\^d`1hϲ!RH?&T9Zx:Vr+t'}XW-HXv}!f|A)sPjsՄRH)C PaN=AtSxSu'' gT9VY2]y5KuWܺS,CiIK̓[EaBя$+u,hU[ъ/F_lF+V|5)֫{XQ=׊*(ˍfĆxY!^uAlu܇0 6˺NCj>ޙO,WjĢq֙On#|bQRǍb$&|)Y~:5M lI"lUܺS,xPPЀ2Gԅ9.4/u%~(oCJ+mCJ+mCJ+mCJ+mCJ+mCz3 _kM5lҽE͇Wܛ5lҽ[9Ų)PnNS, :DZ|rj]պ1 :DSnP ZnP ZnP ZnP ZnP Znߟ ^CG/m5%"FDBq"֨H6N ƉXZ"!ۚS,ŶVGZ%wYJ%|R+k<"3K/wYJE(_2:\|Ŷ ăă ă7IL ])RH!XE>4pkNcZ>,V4eCXZ\ԪbiEsZԨO>4pk˭O>4pksE5_+NAḑ@c. )BI+غdonUgXIkWϘ? \1c%)'dyE|ƌ$ 2 +3f$ dyE|92[4 <ڮvQIJH#*ݚXrD["@\tkb^nM,ۋRҭ@!@H@DNj.=ӻjO9DN֋s;>BkLTO,ˑCn&{)c퐛jԉAX;f).aer3QٚyF)[2ًsT<"R9xej 2(lL&' SɆ.Tl| 2(lo؋m{xX擯5X.rG}I9 ¯+wR]Y,ތ,fGLFEp92:\Uq/^l+`VS=w ;ח%4Hbږ O+g i[1c ]GY,>3[PbVKCg"/i_1ߑ9<2:\,>sx[1_{p)Ɂʔ(En|rE7>\KV[l\~xLն_r1֞d'JGDDY{uPK>?l\~d뜕l:Q፜bbp6S"c]3>5+22хO͊çfEFFԬȘ.|RwJW{-'f1qk$לIv9^s>'ٽ|JhwЩ'ybvq̎uЩ? OٱY(VxR>YEZ''Θ*\5N?abr1* VYbI q 0Gr+ ܤǂPk!j+$@&̩Ť%jgN-8i#YigkgN-L99x´SYkbȕDNHg,]lJ"&X *aߐ*gg=6!~$^9Q0f_+gg,D~DVNUN#'|[Y9|WS9|UԨ9|Urkg:_5Xx|Cf_,Y|7:of|X۸Ӕ--8<0""e㏍|XFa2sց0:|!ًmJ׆5ZY ûN>g^] ë axu3 |\'rA=&Xn}N=&Xmٱw: w;&MzjY6ʑ9s~u FCU-aT{Q*od-ۍzuB|#n8v#$`o7q(w^l˥ HT(\7X'Ȅє4KsK 2aܺ|L9"3+"3Ԍ_d1Y'ܧfWnFԌOr׫v~'_"kr׫;Xg|ұ&|P|ұ&|q|ұ&|q'kr׫9Xk׊Y3:݁xb΢%,8I?TCEzLI,)A|,Zdz˘b96}owk? fWj/^3rw*r͘Nf$4?mF:HzXR܇{#m:@b ?gf|Fگ&bOj"FӦьh34\D6Cɵߠeȑ!DL'۲ADwb[:HPaFto\Kz4Ec׉Xҡ0_0Kz49V%_EB=Lap!E,~LB=Law{g9r[eIg6)gFa?S!Ý8owqO1 J*Au"dE|ODOu;v|&dE|qws ">q⟢,hNG T9UaSBfc.o̭,g A1, {ې<;*1V6.F#ڑ4y:U~ciSl>]vbRRU~c-h"|w;15Jߨ6,.rf":ʱqJXmO_V`.?eA+Vi)#p2sr{6\)~/2sba)~t2sb>SLyYsqM 9)tSـzJ"^߼;>ӗUAծV7"rJTV : RM?,86=u%RgH_@~~x ԉD{ZENq?NA@>}=~JL= I ħ҄$q ȧ҄$q ȧXg|!MϿg|!M.O^% @̢T|<22ԓh QS,h&õ9Ų^^r{r`~Z.t-qx V]>sO=_[.cgX@|h &Ў]X0O@k0مvva^WBj;D0a\m0i2Kd9xi'wu'/ {Sŧ+RA׉ڔ~ۏY | ~ x5k8 $KŶԜ*G8wL٠9BVmXFʕDCQ8LfFP+XHe9'-])C| }괓hsCQ:qyPgLO֔oEikY=kzb>5hv^ 48VX5Lc4r:W͡ Kl(&iКX,ք%GJgZ+`.Q"~Lv_Q1FnEm^l۬d_mccΚK,3-樸|}=;>I'LG〈)gZQq]af%{u"1i*&&3i1GY u%hCB9L9*.7+ۏq/D Sδ`3| ~3r| a&fas+˂~ư0fajjⷷl?,~iScP0WAh40/׆QÜnJ#rI'_#`Lj'ŶrO|E= tt}Iz9{C8yr{^>v0RttEfz9o+ʂyipzśTFg)6]d1uA90=MGY඗Ϗ#jf,^F !,.aq0H~ؽ))tg9ۍh3L1f7=]6ؒr׉(D{s4̕5<)SN9ZieOؗŗ>夙Sŗ> `__4@}Y*saq#w92Q~9߼ZQ~9ҦFq~4_K9(?̉/%Ac5SܸT96 A pNC4t0Ӈr+DDʫG=CiS8?*x~-gL'UsESR|W Tǫ_Ղ/jxl'Qy+0 "9 `<_z4?W64 l ZLTZ^LTZ^LTR^l,;sKVKVKVKVKVk?L_k勵%bK plXxW,~x>/5=-gZ_A׀UAUAUAUAUAU5A6Qt 'ч,mBC6!I!Kd$%Ms}&d9>dIIQҧ)j%}GIQҧ Sh˩r8q\R W+22Vg@[N-ϩr4' s+˂擁y5A@ҦƠd tA~4 .(1Z/)k0_U>,AV,fAV3:\|-)ix=t BQ~0^P3@  )Ex=t!Qu_]ӓF=Tm OT%4_I+̧JUEfW@,f$q\17M\ GD<8sHɃ3WD<8sHɃ3WD<8s¤Ƀ3׮YK׮i&d⢍1qSdT\r_ZyR|]dT"3K>'(uyRt X!ϏϕlGӲ۬bz/)֗j|k]azrI}bY3e t寞:QWEN 9ִ!%(ض9 I\W~]a,]E.|fZHN6Ti!8ڔ&RapjjkSHRSMi"fZHN6T8ڔ$Ryqp6H#n/n`r:~4IJ__RsnusN^ 0+nrh1F-GQ+jA(7U#}_|F>]}t3gSʗA+dR#T%  X>˔]5"~ukɵ_گn|rW7> -C|JbjSP}IjSP]ajS.eHߏŶtpִt/)t+tt)y|-gd,~3bIJ/65|ҧD7>S)эO'}Jt×uဥGu_HKCrݗ\eIX+rݗ&a=W/AƚoT䠶yb,}g,}g,}g,}g,}IX p}Iy^^PWߪ3Tdf Es^^j <$ .h/rާ*哞\{|P_Wy_e%;R"3+^1b)_d1r+gtdGgtr9P/ٓ ̂9U19[h>9{ϭ,kS'gO60޳y5 c{sL=xW c{99ֶ$Ns3ϼ:inWDv&$Vdbx>k" RiA<_@&=*"[~65Gd珏o73r5GdI8zos]a>#c^>L"3{1i=~8b=2&;M@>fj.5G9U b55ac6'璍ks+6ԗ2\W_R.ʗWS0庺|QҦ Y4h/Udf,mT,f_r"Y/gi9Ų!ES,6F{.%rOMFnW>kJZʫ5WXyujʫ5QV^]cX\p?IZ5wGV9" YwYwt~YwtHr;E:xK!YCHv H ̥״^sAYSq<~β߿-(~t 9'uρ 7:ZIfr=}"~y"D#bj4rf"gP㠕0$޲E$D%$Ya&.:N!8hM=q&o"6+&e-CqК<%laGll<fʴ6P㠕AV(/EE hvE.Q~FKy5X|~ELbrH;N\|(_,#\.iєsDbrFe{w~,TfO n.w1iA񻎴!1i)A;!1,Ư ֠]$'2''1X/Y/ڿ'$2QO;¤XY)٨{B"tH;y/qTl=! x:ҊX SUdfD ej 4u^$ΫK'ΫRD$ZB#D7sxe'&t Vxe9,96^Wǚe9,Wxwo:?X,[|l;naiqhBK\pIv78 M |BKLa[8钐iHnK%K/\\5j zi[)dA=a$I>HUtxa^7K‚nƗ_\2d~X7 yeX+Z\Wȩ]jsUzNw+vEUֲU*VtŌ1Ůhye)2`:EI7Ģ6y׬DrчҨb)oβ )o2ԔXTגk ЊF#ÖQn$;%H"[ d{z`Q~ߛg0K0K#z`QKZ fHT6ٮ0Yiam?}IKJ*i0'Q#|~a~b=5$+9ߚ2ǔg|oM-)K"Ӛ25gjŷfbI@f>}LN`rjm&nKDŌwVG=yg F qZwV 7?~mLީ<^?Nݚw:L䋹yH ~$]9*>|PI;SE]oj>T\SB Rqe%:Zpf/+ѩBTE0{YN**Jt*P(U'^VmTEDr6= \~FR]q|i FmLS_l/fv1EF0j;`ʘ b#%Վhs#Q 0G10sD2•[*ڿ[jnEmko;tXW1M]z~EMY~f-l(\TwL֝/EE.Rф|/M(Rф|/M(WRFEau /NXԽ_:F:lQħ] 1Խ7P(Sb|:F%hGʅOr!j|)>Hr?k|)>Hr?k8q?ZFdϪ5çwܦ苩p44pp ?pp ?pp ?pp ?pZTɸ{YJ{Dnhq~ݺqCuS%8]tS%8^n|d2ߡ CV UIu@UFkPdZTe$YUI0?6-|V߭0?mK+.]= WM3-8M3-8M3-8M3-8M3-855 ED^`DHj@+@*2]WlKJb3WvofKb3WvfRf$}(>DE܇ԟ=:@Ǯcԟ=:zԟ=:N;4LT>:٨éqt{?;w2;՝<)'UAMRb#_KF&)/QjX2ʿ#g*jz$1F|g*jz|,eo5ͬnY%RP0=/(Z_2+PP ((j~hV2+P9ɬ@gCY%q2BܟtF~g ~Gከts]Ts?-cYtH70DܟJeeHMe;jF:}TmhU:ݡi e֍?є$/gc4 IAf4 Ia$?0l()Ӝ|uOLn3#`1i7|1߉dFL,6̼ EIDAT= {@$1eȄbTH=WNxPTaLue^TLGǟ$f⿒6L>#+V\bȮtS1M ]RO~8'*4me2+킗:\7gFsa].x9V!{|߄.*,Yų")|g栠x .+~)Hu$ ^iN~)G:׻`Y$dfmkd[z&L8BZk`45ժ `KZul5"IG7zfaED{NqO%׆ _ Y6j229UJtpO{hLt3_x|{r*mI)'56Naߖ@PY0.]NjaurUh5uR m {Y~;Mj'Z[G.i7;HzwSY9o_;HzwþsixT$tƼv,Ey| *=1ST$"6Ux-@ U$)bCc?]n *M)85|K UȏgjGT$X4>B" KK;SCBEBG*x{GYH^YQ)*g`bOT!?݉ O|ʠ ) >*?F v|壓|u/?~HwѮYE#|h"* >_"ڵ{D>oYrC_J}3Hݔ$:3#Cȍ0IQZDuW,DIkѴw+a6#d)yɂ,~yX]G/1ڒk)%ͨ5=Bx|[z83BRkmjK';HDj~SYjKۓSaD^7#Ԉ|v_2!jKحLg:O_U<#喤PWG',$ va%)T&ea%)T&{XnI |_z0Ҋ5}J~#*n2we5tWrfanTѡ~ѕv7өX0Eʆtx^F=/ UHRހS1=Ѓl7Ȼf%zNwc0YM --BY'G/Tx92? GZe8_1}p)+Nj ٰ8L W>:mSW=8y^y{[O^YX |dwl~ç ,bl~Ĭ|<5^'=ן^y~2щix}䵮 3iVrmy 9+ жL-CZkSfa.E!EOؐ2iNLLzD!1T._)zXUjn,#/WXUjnK%(LA1|RzS򀻥U 1w޼ W ~Q{Zm {EUw5oȩ|F=jQC[Zk9ע4I_ԞV:4sEk#h*+U'ldAa r#s+EiQӈ/ t[A*j&Bh0,_5cZW)D  oF /5),/\̵)D >y٪jF^_+3`4&/%_qj{{#ڏH!9uB3oy׬Cs]!,+CsV;҃ez` Z7NRSYy .ITǔ_:U'tQ%Zm *΃NEk R[|B:IU/Jm $]TɾjOxI}-~@''tQ%Z>NF2Y-̊gē,(|H< dA1^/3/H_эģHj1M2b)/bJU|GJS/I{RrA46{vu kY ׅZVwv/v<^M5eb^M5eb:N&P4c딺٪Es;)uSE~XnuJZe ٹwVx&}+f\\Ř3s0|Yvٵv~SEO~vz d=~壓S\<ޭ?~Ƞt Ö3' Na$;{}bk J0ɩwO>Na$mL~@Vm: k9dybG* +~!,̕ "8=3G6Ȋ?Ge qz ?* ,)AAd-+쏶RR_|䠰 B|A*ĪLe99* c|;ߨ27j/c|ߨ^9N7US ErVIf dH jUvt!DS%` qʯIEbM?~@2lQXg $e5y@2lQXqS<= {r*3 S_6;c??݊t2;^j/Tm {%bXJZ[- RrIXR9|,*JIXjXהAŚNk:VYix1808pAF9R:٨N/#_Ӹiⳓw6&>;.+oZ1M|v2}1ݟׯ#-U]ȃ}c2*T87|zm;EQoO"Ȩ7jH99 2ꍚ^:ȷJ/_m {_Zk__vE|Ɨ"4Y3?'H>`YĻo1#aNK~,.2#af$a^Bd KWp 3#aSK/7Cnf$̗l/k)AyRb-Eڣ5(OJH{Ii֠<)"G4-؁XhE;Kbbi]@_bj\jD;P+ cK/y{)9|q|In*#r3̮Bs,p@G+s[JMsdUwG?|.lb92mG6M\=Ï"d[ĪB3( Ps ?++RdrZb#_`) ~gV6c)ĻuDA1#:ھW^cU57qm {("f^GīPaZ[}DA1#v \w{L_rZ8# 1N_lm9GD3bc,VJùf/c#zEW\q] T "+ ONȕL@T\ur%'J֕Oȕ++YW׻EW<[m {EZjkg\uN:]uN(_|\qӉI0:1}bl[y{x=V߭;mp:;mp-hAF[Ђ$իQSu`#+j"f|j"f|j"f|j"f|jB7>ZWyݥ-)*O;_n|*O;aTvW1Tvׯw"*=qkSF,J-+=IViFZj媑ZjVŪL_{(tr^hkثao(Fkmn ~QrMeun:_tt[!RL{={e_(Zok֝Z[:;Unvu:3ۧCwtYҵT=jw=`z4fNL3F$~2q9ye֕ɘ훁!L0?]9,9ʋp\ o_,: 9|91? kx~WבaXk8nx9}Y.L`MHgx-7×3g{J{jFr $Cj?mnCjn6϶C~ <1xhzïr3<%N%Ƿ7#Ost|&Xed.Hě6l O!3+O_M ܗl OLL!3SQ65&@$sdb9;;ބ]!joF 95+$Yg֥)8^_Cy.-+}K#w|}t?tҸl6_Cw_HI2 L KNoEyiXU)r$gÉ+.rcɐ.|=`.{`{pzF%\?'u⏹1pIxg\1/.^^I2H"=ĉ%9"CX-"=ĉ%9"CSB!忟HqR+uZ ,QSj 0\wĒְ7cʯsc/\$s1r긮|\П{s[W>{vtBcs#ҕϞ<~ʊh47:Pꖥ3Laz&Zw{ᄅ3P Kӱ˸ 3,y'Ƈ0<#q:/_ wهV,_*M9:1aaп}yMW pvz poL;>)H§W^| a^xoU=517*8ܜF(} cp ߦryUߖ-tMMKmk+f ډMGP~#Mȷ2#লr!?Ex-,J߫uL ډ f/w9S SYE`|I9aeb?g7#+ ]c8S~Ric#>^1/g™bgZU-LÔ m}&<21 y2q.\`8B. "^ y>@v|6oP.]HDlw bōO~ k"XMTep_ٳo0fQTt ֮ vH>ۃXy`b$$9u Y$b !)4` X-'9^!K@;'ߖ$cO)\-<Â%|.hnk_ HpLbo,ۮNA=E5mf?:)Ř~Z[ZzpP}Je76E),'S jU7;XnSTr9vGKɩ}JƸ[YKMGʆ;5lO..^'i*}& y28o^`S0L`L;K-:w4›oCͷ7x #Nl0_Ȗ~ #(9wJj'r>/-|=&:Zd;,i}CjJs~q9SOL)e+T rk)X++=EL4eDbK(S-?˧cʿ1YW W_]879Mz-3AgU^j-UM 3ͼg/5bZ3K|R#Oئ?Ê%Z(gͪя+jazN"O.wx <;O.wyw 2#dIAE^2O_AWLHzg!NR~>zܴ@6Rڿ2$ZR@0Rv0hHvuc I$,^?hH&uw0|]#`I?_ x^f^QLaxM:μ\f^bA|J0<؋޳+) ԷCb^zPo8?ƼD,+^cGBSr̈́Xm'ǮbdHUO'( |xŘW0,%~:Ay~P0,%~:AY~0$)mC68Ϝfx4L/B`|TMBJ*ζ9>ӗ/o#ƚfFҲIYIPr>D/P3Õ _z͚ K3g{7/+Rt"" A~/( mXٓ~&>ېS9>mXƵlCN gޑSPFmȩ 6·x=9lCN gvu^YU6Tr6?϶7Jy^drTxP=5R G-_i&,|fW K+_q&,!c0?ͻC J=YT,'Uh2nOeMQ{F,? 03-隦C+P$cUh}n\$ckں2YMzU097__=* r4ճ~3C_=* ;SS4ճ~Z]_=*!QTT[ɥiu&4I%4ϗZ;/ߵw>_kI||ג|%j^2Lg0eɽ*W[ޚS|d ZrV&&Tj*+=KMX^pYKU:Ho;\ޚc"|HGt:=܍j `ħ:O%jOJa$#`$%RN|4 vUM4 vm;tiyi::]'Dc֣ǢG-wE[Z=m=j{/Y:_a%g4FXIVyFcta%g4F8yW\&̈́8C(#ڡJG.UW:rjґ eDU\(#tBQ+>lR3srG٭(аW(6_Ւ|Ej*+-W.W[$_qW\Wd p\.SK3-mݮ7")qw_Vw>=E~7bXw>=E[޻&Kw68vk5;8_LʖCZY?eۡâ|`˲<ֳ^%[fv )f.zR2"[kE/Rr3gЍu{#^r$[kH1sJ^ S/#kSKc֦p֦xlFd}厬M-bWLa~SYyzń_簇WL0ow%S\g$3}7?nb:gVϞoGd]ճZ+7Vj?,Y{df>݉8Nwehӝ-vǫOw gib>PƯ'UĥꐏVnI񩇲񩇲񩇲2=% DeS#ULc1S)nbDb8?Χz]뻽G_i}@uț52x҂5uRL5ՕZ[^dn֕TV^dn*+ו_su]t_Nzx6m {Xnp[3G)WkmuMn֕TV^ru9E,7Qaו_:-b¥^]l׻vPلb;lB1Qkm*PLTV&9;lB1QwMHTϬejN襽U^ ;FFaDJ>ְaou?,Yg?zii?vK;28KN*O2򚦲Sÿ<ȽTdFu{M]8 ʓ̨t[S: )~FaQzߡ=Wh+?5..ikKfD2%NdJ$]\TVKfD2%uS,Dx$d/8}ΧRL:ʤLݒgg5S:7#C[F%g^gzf [kyIYx?Go*+oPrLZW9~d3y6؟xQYr8s ?k?%#Pw>W<nk̚!nfdIZkYݢ|f<ӪMe(W?u#0Sͯs؛Q;L _:mGR|tj~\q)CgzNݒũ6 icm:fdmj9"ȍ`݄yV)^Mk"~uWz.a BǼ`6vE+v //Sml]?/7_ͩ6Kڮ_y N)^6v1~^*"mgKaP"a,_aP"Z/2Ԭw:|ֻ#+=z1Hq{wG}C3RQG"sRrm~o0}m MK;SHٰT곽UUy`;5hW7V.Mf2(<үְjneF CuKz/#m+Xt˗xCX[|n*+yL1ӍpQ.Bβbu{A_1yTmрI1G'l)E{逷dC򀻣~gVϞq޼]{|&?>ڽ*UwG[^+dXm {j&S5ۡ=S|h3O\UKh[^=FZr mu{L^qݖƩW$;6e09eC:32m"yP/Foo=:9rӯLu _n{s:՜kVr>|.KKɹWrq>|.)F77+ O)gY3e+/^g>E)/sq>|.-s!eȒ᳌.|k g!U~~#z*ďPwasbҰnK((Zn˃Z|ٚ }8v|ܿ'n,|qJG/sy&G8o,S5.gJ87^ wZOEפ;%C\޸pe 6ZTm {Ei䭕Skm(?Ȼ_HZ)Em'}qqa1j]fnfϽ<ӫ`373:ǙbzgfFX NӫHt)T-]|IJIed)T-]|IJI-bUy~w5'O|]¼zu՜ٕ;^3z jJ|vHtw0|9/̼xidY>T1g{T*8>N6") ~ ?8̏H2rF.7J ,eEk0ܦ<m" ٥Ozp!/|EKLfFrɩ 4 ^ Kx].IhIIe<&<,S}$;>8h4H|jÏO&2>Q^kUqOj\Uײ`/rDֲaGqf!;+9z~3*EirbUA&{ +}i4RyP@&,PmJ(ѮcD~SY.^?_? K+9ѝ}3bMD dȠd{ &i :OLaFa4>0yß&h3Qy{񥧰1.-'aGxͨr? l*>ݏ4w|t %OUlq9jvY~zW7o*+g:u3.޳wy9 .׾!\$KYd+IБl;?wʘvq}贃{Ʋr|uUwo)9:%"wu۪Sr "׿U@D|VuHL.A1,KJQAL6jnE<Ŗ,`رaL TaoT.,v]}pL aCkmj~"k?N 󘡩\5?{Ypy錚osV5w'|t픬F *KlTsx)#lvY0Ivb|[RM{%;S`ϧQ5َDgLT#O&a68Dk(=G-Ά`MO=|[bs%ك ,6Xrm+H,c/UQ빳g89uI9%;L#+ QN]w[&,)66jv谁~)[:5A$|'OpIݳEpI5ޭO$/_{HEkq#oTU7J*ت\1_жCDi۸ :.odik3/bUZ[-ʏ&nVSY(?Zu(?Z^QM-GTGԴFk)S?%|jZCWOMkJi _IП>5!k kw=ZabְW/RRZkE"%,lYs-HAW6ZbmP#˷wf$_rNL+y8?38?ΏʕЕ`40j9gJ0xЕ`bCed(N!y3U`Zzɝ#/z^0{KHXYp*Ta*SJW*SJW-oP+y TҕGpUW˯sc/ؾe< &yճXn;YâSvL\3.~7V6':GX+0Š?,YlMaZ_VߑlُaE[_giG']`D,W> `:9sMXY72Sm {t fs ퟡREwJs|Z[ fP5#|* E#/ 0޳|Φr7]0SKR[w"_/ѼDO[NE;踄`Z |fP,9 7:<;L>]Y {B _|Z~>\{?F ݬ + 9ac3|vZ~aAd[dlݦ _QѾ05:fΟ,Ï(?ڦvt6W:_sL~?3햋;|<+01a7kn0mЁ9/˜~z6Zw9|#l4Px][k%Fh4byjLsc3=pKhDlLLxm&8%Fh4` NLsΟ8HdTm wU^ ?z)NfA (5hk~|cS*!̂PohdS*!D (7W4we8&*n@1as÷xN~m;DNHXs #?k+)F~2ߡZXx7y?j!]uOL ᤵN~f 9S7"{Fy'aG*~Z*&/q-o\7Fd3 Fj(h R9|NGb‚`pzcpn"*,a#J'UcǺVd2ˣOe9|꧲і٧Ǽ#{փZ[/@KźP;agGIh~W1ճY::ٜ9aLIkM-N2.7V2|v3#kMoN=G*JaZN6Y-Gʛ]Ff!g @#/^3\aCH\3β[<^Ϯ;pi˹ן7'OxNUe ]?qXaJO"֩WG% \zWcw#u #:ʺw\ٶT-{'7~]G{Emnj;I?je;.*ZNnF6u︨vsZNnv73aYI%/<oYW͚᳌.|Z8)wP10m {^J5w6KIƲc-o9썬m@= 싎O%~>w;mmS6갑w{%glS5_'?B)^tmU`1U׻/T§hMvw1"&+DrU`hk~Qħ͌G3៏J[a'^D& g٪O ao5 G x/7M_M?#-3L?Qħ͌G&l!g A)+sq'ѹKX0G [&/"W!+-o(o8Iu.`0TBY#D1= 7"0>&kzWh2Ƶwa%b%]7&7%k|0Fa%b%e+ F 2eԜ7/Ch0`߀nw5׻Y춞Wa0 pjf߈( &33]pln;r8 &37dbFTϾZkzݶt7&|΃}FfK)}TVga4Mqh42#Xڎ#fh`uGsY ^)`6bƟ^Ax>>-8}+ކm$3aqiC}[nV$;o>wCr 3VwWtT!9fVƄ~k0VPG81[ܭ~ 2WZH́9@81?؆'>͟ˑ?n:tg #S:Qtr$ #+- %^?uTA*{r*FrG^+|jӖ>fq$mYy˃"}L[X`;nLb#*=Gs}COfӢ"vuc:9$"|HMe|{l@ASP^ / AZjyU5): v0HHSy"8Ր`SZ}-,>pt7r#1)LO'\Gh6=|XmvM|:_%2O!3Ӆ$O'\ƪIGayR3Y>pxea-|t@gJt8\}-ojn*əKEFX:l3^lvdf/M4eIC šc=۰ MC !6|]ҴX65*S <ggY65*JwY3/ئB"/8˴_p3Ovw!{Fd="b߸V"Y|tddEk_ 4OL G"YoOJ<78UZ/8Y]07S%0?6qGUi4SҳLrjE4'*9݉4VZ.`*{r*3wZQSk]0r6fSSk]rRVwZ_Hِ.a1K_H_{,߆XJ߆\"Y> As?= MI%Z E PSY[mkP.fpi~V[P34tVSa{ )d0KHۧ{#m-qZ!cCȽK0s _M8>Ų?Dtri]d06]!RG3(Gwu3|߄hѾ "hӱtG#wJF8ZKؚd6FfKؚL 2I&K"f I/)bk3-0$- {{a 0d"ߜO{a &4S2<#/'aGn}а"_n};*वJ"HUQݔ)SFQSwK `1\rlѠK ?0>wdPsqQ}\A0BX5qMaxi@EX:PsqQe+=)v^OCжЌmQV_V/l|LHh˰D pzF{ $%Z%ݖ:8t'KO]~[)8?&XdKHO; < /sAOO"p>uFNGËc\dw|Rxh&n"E= bdI}}Ch6ގq/._ŔW$s0:9I$A\NPA s#9FX׻~(a=./CAփϩ(V2м"~7'&ŒkcXYP7g-= !BhVgC9ےӝɯ ,`7%+vy|cȃ5 <6KۓSA= ({ϊSW.S;i"H)n|>dE^I?o{/m8pKQf/eZ5O?E| uS[j*CG3k +÷aϚ?EY$RP^QмilՓ_v8^8\x賾'9_2ǿϮ.n:HL$RP{wW1g7asO5S~A"9`>B\b za6 _/#e}Ǘ:a6e _G#'C]ymR. t`X5| zۡ:J*>M(Tu|lA AV+9w9\jpIR^|t~@ %רΎH}6~|si񅍑l,qӗ|CĄ lGp/o+Og678ܥ*wO#zc&L^:1 1?ŘuV l֥LP@5g{ʿ|^ofIK$&T`7ğ2Py}=_](v$_ m+yLO/6J9|7UHd'kdRi+-N6R9?Kn,WFys p׹O(FNNLMEFX[FXKA#^?]ߔ̺Ht<+(Μ9Oq~F{.-'ϐOyKӰ'ҔCقbXK5LL @Ǿ_uD8A$&Z1; NJ9_0{j7%-FIAKa~KKa~KKaҠϧ(i1¤AO/QbQ[b ji)ƠFJotvL|p*U]4sL_8O|qj'Lw*#_<=}D梩QR4׻Eȗ1 Ǩ>tES ߳8b/_`cT?)f$N3O|BZ)_x}e+93SE}d2J$b||eH*%i#l4'1D>m2J$b||e(n|?sn̼c f3ճnP\)3#K?2H_"%k~r%we0|{r*)3#K.FH ar?38AXj Z 3j/Uys1E=xۦ'˿f5o/K/yPXro1@~-C~ջ`rzDW~dh =0 F_ bln3/O9M:gj3':s.hú``C_l_Y]Tцu=#~%b|e_vQE&<{zNw~%b|e. =gA1Ua?ŖV c_lōO0[MeAd9|b4*O/ȷ5o'?7H̼cqTu.QV>Uo *wuDŽOa1SESVwlW83ZM1o[F_1ȵ?K/c;^D"N0%Zٷ]0zfۗ9|ӻZ$Sah4|Wn C˿.;I>`uh8}CKGru9h=y*rFQ֦#V7`KÆ c ;DB5+L8'/.~I7~8\`f f,.kX|S᰾%~bpX냊D o1cQFM@I֦YZMqť,D 0&aL0lO%YlˋaI˂ђ%,ؖqlEB f$'[riŞS3,$؜p %% f&$r6+-6$ZHlIY-jZq H<4q>,B{+L wXt;7VD_m {J%kHuoV۱Ҏ"`:YSYp7eU1c-oTa?z(c2*f̱Rru^(x9;*9;.eU1cFєɚt*ߨd6aMO)bFE{L9M&ctK*g1U]nOikڿ[_1m9ܩ6M1uSmcJNnJ i֕ɘAbaC2\|׹^ b7/Yhц?8{n>fFY2rx{^ӆ> GK}Q+[|bZ1v$=fk;e% I}53'QY紬!"GϨ{ Dyse\}OC\: w|2ѡ˩GVdERGDBHE #*M-򀻋ݮa//wS~~km5/wSC9r"_&8]8:ȗɩ?x|.~[HSB`Zo?*'39VKIm 0K\:CuypyՖHm 0IҐ6j:zW\yݡEUS9`mF( 4 lc7_;q<*>US( 46T7 9b 0 @j*ƞG$bTHzeF>`-9TӛFƏ\ 6nYaUz; F=qo4ER`gHS^5G3UPN҆px)C5 {fz˧حxi+gp܂ƓF{'XUYj4fMwqg,Kn#;1ӣc§GCVdT ѭѐh&!+-3IohY'FaI6ZdY'<&9m(]lI7%(#JohQ-!WF"-M%r6QB8Co0|^/ h# 5wGҙYnj7x4iCC3hf\qE+M;MȲ mLM;MkhzJ% 0X6y&9#iFf63٣][R`݆ߎͤ܄s`vm߼2vl&5;ڥ]R#` W\Q`QҬAN0= 6xÞ0#ج\`]0Mig:*7s{(^jk{^/V%KMeGIR~^/8(ɓbJK@o۰EpT^Lv 6lQ,T^B3mbq<V+)w2"J{O8|Rw U;fs'>ns' QK{8xq_?aJgfR#b#*Ĵ?`#Fg|FRjwuTPtQ[^ڦZk|j.j*+mamt+STjv_|Ws⻚69$ a4⻚&5zS[^cӳ=VI15OIգOF c]"fzoh$TIi`Vґ}p;uCXrENc,@N۴*οB H/ѬzW tӬ55@d^Y5t8׍OkJOo Yzh,_iq)9V3ߠܔPz86G\N'L H^#P8?_bѯ*ǥs8m\K⥥?D W}.vyH4pm {Em { ZZ[H4gMeGx|sEu#tS3(K(xGf3wIB5 !^pHy*1B y ~<>FFϼtbI><>FތA#H 1Jt@'FchH* 1JD?Q$tIӰ0=>kQ,L#y0ruZU|y3~^+ؗsUB7"""efU|]3BYd-+JG(4>kB9dSGrb64/{Hq̆摗̈+.* X +ZrcJ1҆T)U>6T>n9`zI[ d6IL 2M"\rUyߟ%K?8u7 \U-gI34\m;tX/a"7g A?,W: R䆜!y`;;A__ 995ru2t3dݐ3Rd0q;$:R2-YĠ,Z$;$K+4):u7hYlVްFP'V' (a 1([*A\ZёrY,/O@lA\gCĈhBlbPD+g #HɊĠ,hYJI ӣ--RPmihKԧG[Zj|̳ UCvE|*,d/*w*#c1=tB 4_tJJ#zd,fSR*#c1Rh蔔JG X  '\oÞ (zs2W77]8-'ߏymbRr_?*SQt]+! F;p~祢$KϪ =豄T=M\}O/OEIқy70ο}9]O <dzdF]̻CS%fN wK8=j!{ssp>,8l-o\,jnwl-iB gۗ$vm÷ۅ p,W1w~{I6ALOs,oZSR ?pݐ>*|2 \J[!I7J(rnzJ*&>=KH2T M`Yn1 I%ħI7fGI:*wL ұrNwm$_N&[>{n7O 0(oK<`* &A|z|z;r|[m.SM-,_`g=1;4뱤+rlLyeQ cW'c D:XK|`))YsbyrYo(,3,m|K8%6AZ$$OLL@"*[AF9Xy>Et +MjPDN{5 } Y{s^9{@B{ *8. ['9@f8=fKһ^o{cW߽z{͋Ebǒk} 5Ovfh =ɦ"cI:ȝ ۝wu -d Ebǒ4y`}bj?oRSz?$_ Fdc38c ĎUH`U"o2_.L4&4ۮI]I%8^+,ª jۡDC _]': YD O &$0g YDQW|dɛWGǢr`~;+kwW՜c oЃ/dV7_D_|o'D_yE%v?zێ(C_cɫ#OV?,ꇋr_9F޹#},ittK9F* :躳+ea<8CG' vӣmUщ¶Da[|ztj>=:QV5>|7|So[u}b| w_|oɟlŷLgO@7՟]oUՏ7%S܉'S՟;w<|y;#CH.ջ5t~3]OѤ+!:h;A>_hH? |CX |Ksj Uw§j օOwuӅOzڻ|.|Zzpy^bY*U,KS%z=eiDW,Mj|EYO/ ο ֡5UҡV+kPtubtŲ Fd,za~20?FEo#OƢ'cQz 0| C= @eZN6&l,ڬtΖHSb"2(W:gKrv;0"G - ȿIY-U .F% ]+j9;h԰lB^.}9[+'MLRDyS|IaN"'9D/ryS|IaNr`怷ĉp~{(0 yeɵa1+ØKI5e#cav,dy20;S1KIV3ݘ!9݉r^Ṅs3i8JTSY9=9ؓSQP'b~~g?JT0?d 9W݆a&KIx1/abUA&[17ctK-"jd>Vz{IrWeN.U(T8o^SJ]npFTܼ̎"@G*dsgAeJSge,4,CkaY1r 9((ZŊK2)2;t' r`$`ḽ˜.JOL$Z[C k>ߌ-v+^r?+)!E9ͨkְWR!,{nk+oEȻ&"V9|%E.:WR!gYt$]ax9|%Ezt(zzWIm {Em {V[k7ʣ9:=j~W_:~WTٝ3C9W.NSy2vf =~\OWL7kܫ_|Zv_Yx ְkGF'DvUXî+˿hRm{5x1+_bN2lYe!T$zv,k2wΚ_b&!tv,gj$@(Ye!6kR#{'hg^jTL~gYQU$g f<ȹ;0rےRFֲHuTg/]%b`q˟͊@Yd\ؘv["Ye9iIИ5-fN!mT}/IثAb;8ȷ80-Iؔh)gT"ZUk0?Ý͸@+=a0EnujEW -_hXeMRRՊhef!s._hb|Fc/Ugr؁V\FcKU+l榱8T++\N:8 6ʩ[W)ߜ-X/~rֺT-6n j13m oXos?FyyU*bg(/VOp_13mW,Pʏ+w$$w<źYE{FqVw[{Kl 1j[X_w[[^vyqz `vKW-vp[km`EҡK-aYcmMecܓ9yLosƄXZ/|wxۇƄݑ -}2!ˏ+ث"hwӃU HоaoL17ǔ_ǔ_:Փ/`-iAlXlMf&HK+7dbd21AZZ~'+[F X|>?rbtV~\q}ErAQgE j6a̼ "_YW&3ۣ?r8=bsa pݪ=1w9+3'Μvj~YLG#)*ՙ]T0ARS~cx1HWiIHKMw(IϬ +mK_NU|>}&XsSWb~g?PabCgP#5iQbMG'ɪ{c)8sud4sUNpFR{5Xlk37m’IWKoH@=TVރWGkdNL=ZHxړEŤړ"ꠏSRCi9$r _I:J tJ1|%(5cJQ*--GW=2 sE9Gߏִ/P\yKjCW={EXҘWMUaw9Ttt ƴxۡD>]uwJcZOW=>{DnMq ^?OW=:;FU{dP|2A_2Bb$D](Y6VwMoc/'ҝO]~Bw>mtnC,W2ٓI ?Z'1|~4|~4|}Hc󣡣ZDxZ3ֺyZ=|֝3֚W \|xN)ݞ^ 6snn ]7YOQ>>o+[UxJi^ ot>u.5k v ](V|QjG2MjGՎ׻dBdKajklKʒʰs%SâZ[lsdwK"{r"VSY9-%EtEVRE/6V'tNl_z&BketёA ^G|a|H[kE"#]q7EF"sE"#]QڗxE|EڮSږ Pj Pj Pj Pj|jĩ:8)d= V ?~0*\JYQ*( ~:~f(?/u yN̨WT^I2ʌ.["폊Wbt+1 ڋ]|%FWA{Q(?t{%m=r›oS'_ɏ)׮I1VF1B[Yb/-E*rl-BPx&d ̅22+cϫzt0.(|s#?rSHJvso}o T-#%K>uVYCMd ,W1nOmSY|h,΋ ֿ &I^wCe+fߋ >iǏ~;n3_] @Y"-7r+?]a\W..?[upOKwW)~1o;t8]b?ǔ2ߡwe$v 6;Y) 6l*&&>۰j?T@ѝl*&Nq 6bdn#`ZzH*XKIk!`-$R7M$+`-* `z6axN4v谁 CvѮcR0 =ډF~)DH0D7Nb7x|Ce+Vhzm~$Di_)2#ʢy**|#v(y2믯/Z`IpoݝOwO|Fp{w}֦=}F郬{ tVTX~HFx`-޿]yu|%5wݾ!b;@TP:)؜9# FĴHDWD ?{zrcu=XOcPLV=li#Gu$ydxnOIcA U&Zz;y6RXu'U s$?kS?Z E}ЍY ?q [M}o=YrRZ) 6>׹C]YRIG732;I?'k}}ޖá{ >l|*ܦPuM=źjlz`p [z~/}!y}4N1 [TFHe_{5fF8Vן֯dܿj+\~?kS,T[Yk5m'9}o( qZ>' R-o=Ya(}߻W)?:幠ilQ6~G7T:A龋v p#xopPzZF2 M8~-?л{5;)0#_ 0<JAODA[[n2ƪGc_B֟ JΟeѩWs]p^/iBl$~uo4s &>')0x>t.hzN2n7O|I7g3L7?'7´%w>'}޿ʼQ/AEGraC717cO~zD+<" ܿ*kh\|5.0`Yg,<0[NLݜ] yyj]Uj4w]M.`xiPnI%Q-"#ulv+VI (8Lm,iM,Nz_+6]^YRf5;%*8> L 0fWėPv 7.|D {)eD)wT;w ϟo=Y ߘLoP֓a6{;owl 4Bvz$$Fƙ{?.Č]-YO.fUs/VIf{Iw&s9)VytŎ;nUĬcO5=܇]PO b89TaXΚԜ SFʃ%(ouV> @zN5ݾ1֓d Ah~q-?'{&c3E/Ød@әzo|̎`d /,0ۃZt˄>P1"nf; ?_vwS(z,M: pƯ8=eߞ1wlJ_qmז<`m~ז%m٢ٿ*k` I6,/%!k.縀KP w[x/-}mŎ+KQtNC etU/-'utMn!YF_i%rˌ=tD3[3ئ@; /,pTۿ0=F="1dU)v~d+ ђO?3K,fal2⿏A ?~_w>9Ɋ`h={>);Yw#5/v.Ki4ԯ ^(/QmyotjHH@'ȅa'N!<3;߃DEm.\Q>^w<;u At@T6"HXH2x>~R[5u&<;{5(%%Nq"bm~W@hlN bȾFgϏw: X7K>-̨6aM]^Ɠ= xi{lHyotP溫|ŹnQNs:)/?t$n0Lb~ } kuorz$9h­m?8'ˆGRr|҆?~rO0/q`,/amSJk{x 6fݮSiG7(gm0-[ssf :fg{H6e M0܋-J@15ػX\_%_+|ȳuFEEX-Pl'f%WNgd=oG!dm+j[jMZG ^^ɮ+%l&{"m@ˋDe_6saoҾ7t(-ߌ,GF˖֖@d^y @Ɋ\טc8}dú% `v?mz׿{9R)4+#R;H8q1K/ co$gfci͟yU1>׹KBP[%Jz&뼋KYqOc>s 6䬁3XZTD1oZH)&Ibx`W^bzv˼ݏ f _Ҫ Qx~V)xKx,"򑵘? /HY{l3{ ,ʗ;WbDg "1_,I-Cr$';T,Z w:cWά-aaeHK#~[p=w'Gѡ<=_`yҮusKt 1VƖ+?ɏ b)){d" 9F`(Ԥ GwN/f_ IsH ׆h008F򩰇FtM#z&@Q3U{}YU "VbAlof ~'kS./{DqAPFC*^}Vh ɺ ) @h\b/e0莿<-Y̶Ӹdb DnZmcG2_e\ ׬[a<"E?.^7{^ ?{we[mߪH۴[,Eή(]Ʒ1 ._ӆ7R~ "h/ngBg몐GMc5׿b؆ݯh_@W41*o*?x𙽞isT;ԯKdQڂے9_ےQ#s9]byÇqmz\[bHƗu `] k]F1xHTE2)+F(JVMufZc3F&jVy''m1TA]X-y50A.pP}2%RBN_ H%I>'k5 Mf7/?ol$X71_}߻x~aQ=]Al?55<0&v]5]Wb ۏϱ}T{QnSڞUPVܿQ+b;?w~u6OHZ6G o1 {Vu?HO15YC"h3un &%VG#,&kDIEHftwtE_(XC?~hZ֟ ԫt 7B4IG`j8|ZGfnH#5%P7gK}rD5,g6׬>x;DGp3;z}80뺩=6B 1싚[FW@^uE-S\X@Mߓu W>OuB(յs^#,7Q):kTS~jbgz5مUD둋IE`KA4N/LWTfAj_S=Z~?K`sNT/.|=Kl,f\FV( D"4GZq[6 Hnc)jJAz|)Ka;稍ϟw}؁Y$i %%7oAsAyw{c{:u}^jhFcsE_v6;9~1j)&cƾX|}1N*.; DqαN&4h5 \0TnH%a׾htw^`14']̹Png %5c`|%A[0-+:Z]GG+/- zq~qEMO9FWWJ=fww/db&\ z稃x*=a[bm{:w* E2wӢjCO64J`(|&áɉ)^Wķ ˹+jGcc-:CUKq ;]I:o+?+RujͿ?Q2.(kS )qJk5jY3&1wi̼TW.6ǿփ*UpQ`mN)B$cڴ}$);`ݙӽR'[#_B/~N|H|RzփǶqo=xLWqBE~|G SVSVQGsoxX{tν- `kmns ;stz'V.zu贇/$I,˿>|H_y,g'V_y,Rd?N,&I~?Wv)HO9o=#}K-֘\׫@X#We;or#B9_^v~6%ƗVoV`|5i#jFXħ㫉OakT_5!2"|THε-I4uEG//Č0&d]w\g ,K$`@4I4INԘf˅(^r;4jM[QrDw F {,XK33|?g^})g.Q݅V2ͧ6r Mrɗ3>FNμE/,drW Qv:E--=4N}0jjkB }?W0$zݜ2-FK5zIw )^1>Ń~GL׵R'_ȡe+V .*1)6v\WĪH[Gvg[FuC`pIsL.ܢ?iVE61шAoT/Jh1NOŒWAC2"@ՑÆRt+%@45yΔRvS,֩mѩ ;U>7d`yQT`/EZ28RT^HQu ʷ[2akT faMk )$_Y S[2L?LddE m!Z:+%ş\UtrP|ӽ [ q3_R#pp!ӼEK|ǖտTp.67׻~0%N(`!E/r2̅b{0>䥷bdoIVꂨ!Qr漕&>@lFJ7h~p!ߘო>f^+<Ђ~w$&tK̶S&l&Yy`19vA"!%omIzܺ`|`!9&7IF: ?aIZ$Y^LTjv"`%_)[H~mU+!`2COj .0ڊ49?}}1Ю2޸@3Iy._-m348;.C€@ PkAP9|i4=; ?6a床L'U _5uZ2Zv-Mg7 n&-}+k}9k~FOJx[~bEu~͑ek5,ڥږg3jӠvIϊ ooʐ/@iD'o|l#|ٗOQt gJh Ŧ6h&iMX^{ѐoy5Gx+CӳraYsRˀф]ǣ}n|<$-7.\Rycr {}Aǿ2ixuىΔI!f-8-=>uun*%t0!Д rx>tM\f~B6x֕a O}8#E\rV'tr<{%˳H[gٚL(9sSY7-$_1_@8ޗ11z=sd$%A~Z'g4/ǹ4h'~zn,DSr:lysHÚ M#Z*68?!N4 _Nһ)ݞuE-jgNt-SgE~҄s3A/\^LLTwtA=ς?sRejbTZkV{4_7XsIZyc0sJH;]Q*R䌣K 8u~\a\m@b~ XΏ;,:߳h 9fS.iybLg[ǤC.I6MttRiX; c:5  4Ugk P`F(MZ0l-~jl-XP#h x\TEP#SmW6|I.V4~C^b&v{Ϫ]]]P1b(B5E=2c{%*ߩgY[ȫVf`F+k-_UnӽmV"<-BGPy M`t8W@ւ7 0ƺT=V_?b~Z3sTk;A)`p8?jqvu @оeb4_~ "mɿ{)0 p$;V׮+y{Nn\eׅnɰk}N%!#bE'O<*Eŵg҂3{ܛFOS07Jᵜ &qcVk7mMYʵ[Z6?kL˚ÚmSHrV8(0Bc :E 2|kjkot׬}R,0DÆP#&V˴\ t\9MQ,-xŽz+I!҂ Bo._,-xs"+ڐ@giZȃTE GguN#3]IMk<,͢Ztd]_E!ZtUp1nMYI̋?~1";m yySV?;U<؂BO+SKzD;gKQy-ͧ͵=eS9&Ww` t=:|'E L.k~FT`& "=@i$゚ˤĎOw[$/᳽_0/-,5g\5 )B15 )JIȘ^۲3`%<mAL\ZcC^"__o|adȄ y(`ӽ3w'WU?Jrj~'"׎99]zwy4O@a#h$ h1fXm B Jç" $.~DFkQqvr|j=cFW5Wش/^16e8CNġ$Bh1ɿClzd`U3i,+&teFCWZY|WP=+1 jj*浽E@ JrU;zxSE9 ͯg@EEig`K;c!?M:ĜTO*w: K#@B1҂@Yr_Lk_﯎6z OQ3 mEp6SV^źt !+ ;OϕDRA鹒\n\IvW T܇ۣPMcEeud]ȷ?R-bEx4? 2ӄ*ݑş\!_~^JPm܉`M4.x`f$|.9:FB @`kh !e!cJ?5G.y"Vd4MbL̆"#(e^CLEY+B~;LQ_4?EڿrTRXH>SW6/*y>t"L_9Ն딭IYFjI>Jh zx*J }0aa4b٭v!H~r8P ie)G^0aS1aSA@4,x{ rn,hf*!5I/67Kx4q e*WOQv B"57/r|lAYZed^&KHVb98vB*,7[`_F8x>M+=lЄKL+{fu`];6_n ON)CD{ng2,=?玡 8fY Zź:i~90aG}Oj&(sؐCE"ᄁPNnۆ90!/Ogb-%):Wi^ T4,2NhrI[lmHؖI bJκy,%s=37/%):7"a%_o۹(Uy*8 ?zg䓰@$Sr:oP{vF[4n+UTRhikN[5D|ɺ۷qUQ<]/wN#$b`?WZ:7h.n7uDwf$3œX4^]]B7њMM^e,$nM/t" q+)%VBxivξmIͥM5{O*j~{ J$k3s/QE3Β?gAnÝbTA/h p w[U;oI`ggl1%ysvz]14!peܸ|Y:z}Z"ř?1 q+y)XW:Sɚ*.+6f,\]*Qe0" 3 BG@s,+\!t |Т_T\;"@@VMmL=YA1+jQ\^.MlT4>x1 `_,Yk>(;5Pbim|=&I 9(kmL5 x]ݜj^u<po";c #p JJX4妭eugV>xމ޾[-ܺj@K`p_jԵ/4>!#&u{0ڋE_[[uuF͙C-ڇďJ_[0XPF0FDjʼncWXɵJ$ -oRRaG_TavWCʒ@{{"Ox}IV|ڱ$z׼) NGvAOoԃ$-'ifY|YQGw,_o zwO/fܸ\) 00G\ϴ jJzy{rE vAH 4qk&eUefYbӶ`fRpNx4̟$n<'K[Y_ ̔~/H3ȗF_%UƳemopR#Lm8z46<;d4\]#2lP6y~yW`<ʮa11imȓ{ j BMBq eTsTwV ݺ!)_n|(n\.B#'ΈkOI %((TJ'~*8,Sǘa1d0-y[2 0r yY@V2 qbs9_>8V)!VKC4VK+)AXP&aKCFc̈G0f#2ڢ?G k_E66CVf#de6mePw:i8{ew̘5ϯu92'<z}RAh; 3`g碗?^3so07W|, Dc[}άD+'LEMESMra ct{OG_.> usʲ50}jIshS˕.$!#?϶P]ִjٶ xzÛJ_M hij[I%ܧƋP͇Sw+8QR+ }{q D",(Bָ),g> k兂^k_E+.ͭ-*7뇖ke܊0>W6g- 2j/uNK,Sf y)E֮MV?1X !;cK59 ?mMz OMN'WUbƘQ~մ)RoIs~h229a}\yox BmM F5 77s=hO/Y65x ]CBuo\x ޾޾EJѣ1MμЇ!]Y .hC䉈%{稴p(6*@ z9T\: W7w C{tCh3/FK*%B52b.\b,:z\cy90-ĭk2::Lpqq/^2DE՞ummLYq&W<S2H [6άnw|u)rW^EXZl̰67p H ՆY+h~e 5AuNk >Dt |[Z~>a2u gw'`JlQ\&ފ=ޘ2`X0H!=+˚P7ȀĭĈ>x9-­^WfІB5 ,-dFƠ*&6A9uh',f2s).k+:L}u͟#|s=@(`@l: qڂah=+ܼr n^ȷ>xq\.L?Up}f :qBc4449MJ;62!aݮM-157F _#3euN2\Y] bю:G !9|&oȆ9RIi̷C$ڇOd2\]]ӄ[7o[2l8 pegG ]SpqqEp`w=1Ueajk:$nMg+SXr@֔ڂ2Y9=gs#Bd\wifFn}f&Cy>5f( 3f/}2#Bc e2ҭ?^P wfTU 5fj_\}1SOWv-t>3O`H@p02OuzΊ|7mg|do`1gGbSϭ-Udb %Zrm#)g̱L~":|XlԠv6:DCݛ 1CZSAakO 27 ho/o=Evh uC%:<py9 zh0޲hokiF+Gmmjx PN[Aaw[ݾ Wa]Q9XEhmoP2¿jՏcɀC3}pPJh"zl|e %XaC(uR#2h`IԽnJO]XibJ0/{3D =42*0٧9ӳ})=<042*Ul{C1ppfY\jChLqqc`eXtXo/OT<;MDv2j⦱nrȸSWX[ (]Zc^|'ÎlH itl [557+ѥ{0|UpX/hOo3F45Dh57+E =U:^uVgBh47Vĭ3rԀq~^ҩتT.~ |7'"J&`2|75j GTJI?òdEWzFq=QaDx\+\a7Eۚ!|_3lPBG\|=a ?9=G~4M>So-&5_n _^G[ͦ:<ϼ&=yNxvƖH, 8ǰ/.厀N`\[I:SRqIpukWҋu&TpuuV&P!=5#Ki3n]5 Wy!"j23̦ĦZ#3z3hflb@ vE:?Up-͍6'"Jw dyXjeDx"-v- T*'"Tbt\vPvL'6>."b15`y^ Tyϥ] [oWu.mQL'Jȶ0E7FڪYxsH; DFs\YEeeE:<=e\|A+ `N Cʒ? V零k ;Y1کMll_G_cU4㯂X^kS v WL9N}:UEdk9f {8Ц9c0D,%sewkkzU%w*:zI19#fЯ퐪]<Œkì |C(X %~Qa0LmmV~O"tsW\hx;vy*"d3Xi^i"VzG@Ov-MnN#Y"Agޘ"2Eh'zIbNH{ nB Ն]SfΜ^APbsmVRyNzvn>:6^=Bsk]w7WxyYrYcN=bw ~ jQbd㣤:<ݺw苉`BaC;cE\rIV) @L@?? s5a#cуy-!I$?ϵҌ^R1Dɽ+E(w NTtnd*k+Qƥp{9ӗm$YhVTΣG_*mkEqlߍ˿XxP6TΣ{o5\,i`! \Go5._8n_2 GS/.7$nͅrNDl-h^^, %_θ'HDQBu  VfўApss[ygvE97i9@eƯrF*z#_Y[03`&}O<$_T8}/[3E|78'uȀe [6D3g45o?sO}~󐝱%Y˰pE:-UJ+d|*Wvįr X˯ruz‘`.Nf%v-gƿpJMLlř?m^*6S[03|)'.iL3z% F5[6JSȗD@Vt0̼$q"b+/;x"b=CpYAV晁@KAn{ģ wjơSKQL 9؜bIfCTʣ^SWzrM*@idNу/q亵Z `G#rp(F`Ϫ/a۪"`ސ(q{n'l~`ʯ^l5ښcAC1ZSbF,iq%f<wJOS8oN&Ҙ}s|߀N¯}Va]To\op ͡ ӔO'HHN ~mitr&;Ikv{='5-oY(cΐ!]Q~mPO<ʶmmhkKvG/ LM-jX:/Wyzoq9vRI$U]\j/0LKJT_#@@ԠKS4XmUMcSu/ǝ͌"pC^ƻLmY+zlb;bxj~z%Ο<6]vaQjZ뵟nU5X+@FE 6h&>fQ# ݳǘqS[kWTx wwL~\m3.)>#_)K!a~znvWn[F(!&fUz1,3fg1SI8jAS %S+a:0M7=D@uXaճ9*OuM,4#Vo8l .;ܝtzMeOo= vC3۞@ '~:ZZ~ VhlC5ls%nnnڦiF%r) 6 |@3IdK{ʽ|K@Sk r9cT?v<܇X'Wr`D_5!w[Ug#_fE=~0Ch*V5`9 #ފVV`'WI99_j<ݛ֞ M-!_jT>֣nBW?_j]μί4[7h&҆%8:2˜.NJ"CD XD:@٤"MZlBmmhs*-,c#&ilkEFKs㤎ydm8МHWټ+0O/@sB 8*MF'2:ǘwêmHt)OScri?*ҙAr1S b!Yl~y` @otv>3fxgrsş\%&Ƴ^/Ӧ8M 4 ~^8QvJ;B)"4Gu8DXG6Ҳ%?gTfQ#|}}AuhwlF|S3Gr&*p~7jmgIeH|?/ 䘔-缘{ׂ*i (cҰJ UV/}zʒ̵ " 7h&GuӅ p%Bf !Ws[3E^ou4 yo?w|ŋ_ot=&̡YJe 9POzy&/:Ag9+(Xc kMH9crzf0?tİh\_=̖cql`  h:j\qq`J Xr8զy[xA7_rig+_ǎx0aT|B[(nGn\/Cݬ5MNWz͟N@p[}92c(!{kBB [0޾Rвl`7{JBUdqW;h^LIc1eG0÷Gʔj)^/=e 'b~Bv,L"d[[|P. a+AC)\eATg]h@ _ =շ݄F@WA w d";?~̋gԓWSj)¤Ӓzؕp:f9MV;,m;j~|Tn- l!2l!2 &,ّ$ 6hV|Np|MtUE:jFspn]oՈt=l@ta )S4F [k[h%xs pq܈ei7nU~5֮ nI5Xڇ_ՓD %%74&?J־kG;%c!;?$!,:9ڲez[6x*`k]Eq"P!`G41;f[.]%ѴL!SuOGxD|?GBb!JRhj{e8 Sfo 7xX@xK_Ug@My ^F6jFO+8R;:m~x@_d u>xlͳ'mm#cFY>7QPpnי-C$S7 Dw/J(<0@G8Q/_ş\M_CYvN`=h_)_F2}>*"FgBM8v/7غf O_"HkDVfUjEy3Z8ȝt؆rd@8wlm B`s *בCP1Oh®MFGU bS {lq!ZzzE:Ɩ/5``2'jCc;}Κ7Ծ`2GsNS/D] ?iľwEmO|9 @{z'WT Նff-рX4qȸ=#HC>2NЪ%PyH,4ʻe?{܁lCaf_yv<͸ȟ3jm?\iu?9x%R2`W$e :|-Pg'TlgBĸIO`d*05&=!H]4Y9ka҂iXTf-+1yRygqC{u'`ls\wTnN7v Pz .4%}RwqS|ÓʮVX<2ŵO/9N="?֞~yɡ {%+Pm\yNӄ?ED8:)o!.KqIP{Lu$Yl֔i42TG8ȟ3*&df IXcۭb3->&50jwkK mɪ|qBܶ|*P{RT~tg>̽Ҙ'tv r%bSK`W,wxD#U\"}z`Q>ƪH?#AtD \ZYLB!y]uǎ4z9IH qE~vк3΀9|wz>]xao/tk}P,q<2Qln}1?rGLc,y'$,IH]"L!^~*)M3.e-.bJTzcS3=s"n7Xh3r_W)%r+wo RǓ+g6~@m]~ k 5k5G %@F+lr`7[t x߶a,|}(Wa+Pc#pv/|M.m1YN7#!-Mnfb!hmtZf-iqUlV>ED|`Ѿ}|\-|}5,D|ۻ5sC;T eت+Jjvb LI-{ 6XXL+!1|8ϓ ۥ֓99FpÓ 2rd?U+?vd|(p&J*UP.PZWj"jww8r^o?e47 ^a+ocʩ/_aC¥6rG*<?gDPgQP7ia-Y 5 El5jC f S7zlRQ JfȁOӢ^[*0Yq|#@$t4 ׃Z19Ϛ7]947T"wvR/mө(qW&;q$:p2_ Z/s!ߠ^r ו_A}̭tWÐBK ՆD*2/-[|O4 EO UϱJBpٍ[ ]vA$ZUm/Dk M 5暖;͡$85j.~q74gX@ 4Z}њY ǬXZ@OՐC <SyvhťKZ\- ?A8i'L*NJޑ*Tp~>r]r&l;er B|J' u0hSuODQr-WڐLV OMMc$F`b:؜Aܸr]rMPgcW@Nh8!|kMi\4zgnt0x"Ihd@;䐠{LA]񤧼"T" mn~ }-X&uLË Aj>9grZXh ńkVzĊXjqH*y2P֞όG CA|h0()T)d5hX/9ud{c&&'av.9V9x@f&VW ڍ\r'=B4K'76im"l! ,/aiRż.ȟN a ?vA˷ |E_h󂕞,D*R`a쟡aO;Ɲnv?қ[HH[5(U=]-. OLMesyme Rk{( @1JS61{]'`qOY.+.͞mϘj|s9\jC陒ain4ȗ V /:A|9)k+.̶^emEa1 q0(z52i/v) Pxj&?!X>i-ڊ<ͰIsvtܱa{r cxs̟N 2؆Wqr<y)wW<5g'ꍊK3ع 5nمQ Iw&c75fj,ĭx'"`A53hyVK_Gۚʾ?boC\Xh,Mv%@H['Gq#kis+=Q;܇pf/Y6X˖-2֖al:R0EYqvK|\PtVU`֪ oF nY-e7cI? f^Tŵ1(-U? %-$N:'t/IPd&н/}2啗k$ tlOzt<:ٚZZ ohkCV=Z~-4- o \I6hY/a%n?ѢKZ@ >> #GƑoc]2γgUH[GH[GĸGF Q,!lc{++0k_®87$4cIcO~vō_+^K_ T㶱Fp_yh>O0v: ?J&%-ɜJ&b{v&ཝ HyLԟ'$ .28Q["0)qvKlT˚ .IvtD*)M0A 0&lf<#2eV   WaF @y%w #V` / u㷔o)47`+}!!~>YojjS/{s.)W~ $fͤMPg >O~<ǣ@[I*VC O'A)ddGkz1EGƩA"I^y'Z {({!"vdŗ!oo퍣?ZT{H!39PgM2 + +`/Uz%QL8{Oy!@*M)\y$s 4Ag -w9..JK||}.h.i鋑р Fx \ȶRp6Fd eb:Co-; f1LF"15,75l|[aR~\\t98WdP }=ͦzm% H?g\3Z<Ȍ iJ J?֕PHӄg0m5m׿d/WM },W 7// T[Bg}1ĭ}ʋSP֟Nj7fYR 2?ua 2:i`5rsjƕ&b)\(..tG=BuЏtN Dȩ`Tt uG[_(̙mxٲL6/'8d׾˦%%^@x۷U3-)1h@eV9boܸ.%k9.LʞAo 7ٛtߛ${˒7mpg\@5].p!p?0g`'u36ٻ&@@O] =Y̓ sJGGǰq3xOr zM1&'a5R&^Cn0$̉Vu4sV+`0Pg' ʼnc_Z69l'8a aOA$-x:i"&5o~"V/YʟNSD,]bZxg4%v.E6S<9|9(1ԌA'l+r˖ewx;w6 !h N7ͫO/Aߑ4ު f$sXD٥٥xXDrI+ 9Nҿbĉ4>~G"+ 2k6*hv*cƛ(pd K~`v[%n7;FӖ`RW:_hl8A!O_0~+("H_.]ci|cd~C2;~B}`Pd,IʚbdR뗍_dyc>A e@ahrv3k挌)M&6bp??)#FP>斶(Z!xuߟhuRK/ա2fh$1:~%3jIkJOS*d`I+= H&݋d_37 {)5I]rʢsOA IЃ%f3KOXÌqa(=B2:x_zw)j6$/_8Gh|ʹtP8&PP=fjLs5r- 6MVzdŒWJO^Q}1o,=+p>qee/PP۶axeBilY?m2p!VQ>SoWn,8gAn[,ȲqwFyF-6kחUEy9`~ BzAnzǏ%Ńiz]!Ys`dhwcIDAT>C &c#%j{rqy>KաhT is9j8nΒut #ݶèDư&')I7}u}{1D^.T!T;-)QZ Mn&+=M!AO)׶l/| 4/!ߡ)jà wC6y4/'Dqaȡg" r׬ICP5t[73. t]j=)V~k.EGZ%_{ '=:^ǵLE@dd$K̹0``&M̶eZ]~b_"[]~c V$=&Oc.N?#t북7&{+%NL-5շ2%[ѣ@1||;~>աX"n6Ҳp9h= sR"Wd(4(@\󭭩2kһ艫e62>,gJhܩMwdeN[8jJOSJOѻ'%%Sp\f\e 'w@pWwwNjofoA z F&W=Wᱻ9_ ą3GQd<譢¨4+T QB{} >^M4..3gg} Z"MnK6kT;2gE`{v30} 67/`p##}1^=}hErdAEv=-Fj<[E+-Bq\D/]옇77Ę񏣹IT͘Jitߢ ۝9 y;YŨDTyǏz@:H;{أTA65Afm;L2s_H?x-^عm'Oݻ2£5}J8 x Xayӟ]qO@G#\rzrd̝;Հ ܹsX aXnG=kwJOp`y}] fW =Նd*o8]0dpygNDccL$`KE@O$qJu@>{^*[k- # ;sл'L|0!4e-B3LJ Ymsm3{wTW\"Li0oʢmoaѫ.repCu?= 3Xi\ 'M7=ļljWg 3?/-潚Z4 ڷS!IP%a)+$#ƿ&chFCfiha$i;zO'3'gc1웨eɷ'=?^rm\sg 7AHƷEu]eQcyoYeц ٮݬ9Z(%:Aߖe"oazHs%%-)rҾH/{== "'Ay9^)YT^t6Asc/ڏ:2l8>XG@P5=z\K-;cq4L1>$xx>~Kt<{r8.q76֓RJg )f}Uuoz&;:p)3luP)Tn^ڛeO9hU%joLTx>XcP *{, ڽF`w|0k ߇?<ܵ-bdpώzoN #ep_ɝg1Gl%S08tdUJ̿sI\fO#G5| < %&\]5yǏI]1\V  O!a6 *H櫦mޟ<Ɲ櫧+<P@4/0n#X<C1i<;v{8 H}ޤ'tJU<> ~ )gdĞ{m={bdxlTuٵ[w=sp9q uX{GC_P2*4n<|&$|;{4dhmoEmKL!_9RR<-) 6a9d[o9 K^޹n^JO`)5 VTkMm\*{$ %Xl bШ8 g:McqN%1G _=_o@̵Ѱx¤Se.Q[NsE$y>`1?ٷ )K')}_ߐ0f'ᄟѹ~-t2źD??dCΦ_|ծytÕAjiOg*_|pq1WY%Y/(!‹//K%МCaɸ$!&m'EQy7N!O%(3PtUN0K iQ%bOB |ʈ~9/@NML5oʘXh{8 J|0eh9YFG:h8~_1DÖSc?n,9̇#XS|h&9%+֑i2}rkƥm§aI,=xe峻)SvWhbs!ڊr]Euҿv&-w7>ci9'|֊C!L,z/#mX`׮=3 ZP Mcu2'-!|{#^/ƛĊ39|\p䈰Ǝj96 XL?+N*!6-s,8FdL?H;5}G~Z@ 5 7IT TBpkmYOk̴wt,h^lk1翲p!*m, I7d7Hqh+=MREjVKDl-6*t4w۸ -͖Ξ^>!HG@sS#C!R@;9EȯJ +9 + g1ȑ99a BH y9D@{nӰ*|VBB`Gw77<`^fr2 v,~5]X\\Jkb=>cu7zow۰KaJ>:MM@ (cۙF8xZ-;wVDWҳg?X9b1fh <J·\7`L-csU#@sZ%LQXr]ɐҒWML h19D l)T[=Ix9r=g9C'@*\v>J2B`v3hy,?Bm`KfEGɗ5qkA_4 "m]=Z*nq2J0[S%gꢨҿM!TGCh7٨DO&]A.y(>mm8p..J-M0N1h:7)F%S L!~sc,SQ6,c'!J\<qtZ Z _`_> C _=B\Yk-Z:4jBrq0Q8wDco +P[N?]MDѭO|{5|5ȟNσk*k+"&'I kxܲ"g9vvn%crFkWzd8i+)Lr}%m'˘3[Zܮ%-pg?#zӞ kk=#;fޗClŤ1AՀ} s @%U I1qѼ,Tz⢟Rc7.ܨLN#jbg?. @ph{q]qZ4=:jzO< ]%.zxY0.(=~ /fwsAb3.K\Бu{7"Ӽl}dyǏtT?`W[SU1`Ppt6P<9a`v2rH%_US7i{ieB5H|E3JM|7򖸃l9݅;B :Nh7Ve4{Y\0 kUp B~ԇ{;+H{uSHxEں;0 !)|e4>o2k97_u=+07]j=P`~훨E\-ulpx~ҵdOapYl@L2.zP X/!a5K /#&jtq xrœsC LW4{~*9zE:Y٣#&nm-*qҊ! `/2swX"'af&u>5zS֓*'*O.L.h}{9#LvMv,nu#䢼O#Kb)rGp6Jl&տ.iqUXh"?B;~rڗwJU%$.&өdA!^dzx$ vޔeQ+֕+9~_|}#t8GMsȼs!GnNg"Zlxv-@l7]P$Hc)\HĶӧ0٧3}*jGr.͞+>&*՛wCr& Iq\Qq8F#2Φ7(Y$duVj`3qo2%qjsV='(O.BX͑%Jѧb4Ͼ>muGGG2(礒'1rWɭ.G#]Z$yjeK.6MKo_ \ߧӾO<0FrPAc#{1U Kry9zu'AݺZmpVK^=?.q pe@'$9mBt`Ii|6%B{L,ֆǬWV$Ě3(ZmBpU|?.#)`nѧ,>3y"m]_Mb];\Ʌ%=w漴^k'I ؅~}NMcbU\-1s1u퍌9 33S f #P>N[5Xo5yif)v,5tttR*9rhQB27%&m5B㛨au1>Gq$C5FM]] O 49xr>\$xwFip!/;J H!_>vm$|Ҏ Rs8'jqmM%,%ӞV_.mt|pKe,a[+-fɶ02i*uOiz!֊'f^+XR$n [RTɎ!5b0}MM()((/z%} dgl38~\ʏWY "h-N;Z@1M%W MYynH;rb}dr-nsn@4@S%s.__)dc5F5Dmo;L0\30%aj 彌) s$&$VhƀDЄ|b޸@ǘOᛥ_)F+ǓRTMx.hFݏsX>W"̘- dHK*ȣX;w wRwf^ ͩ3 R>k<UQ%Ą); l%IG @i.SsynETL\Bkin j,W3˗Ϡ2HV=PDvmuɅ/^6p4R%P9NY@:)k AnO[^[~ą8Nxz;:.fBQh>Yb5("җG!JrEG9Tݺԭ2,:yV,)Y:%a6 BӲ|}/%t#C4nEں␫х*qBccY[QV{Z/WWḍlO2c-8-N7%q(UϡQchR푯#`w :]=jm;rAx6%`=ʘ` Nx@G֦ifBDMx1TmW./[] HfZCg;=4{>D|@F*T].$[ΔHk_qUY}=B%u=8 IA"m]]K"~a}檒%݅g k3.H؈bB Q W"u05J]_a159Nr'׈u< ܳ_CÙӊv-(7Sg~/kcXsoXÖOT5 N@_VƝF~Vgtڞ5PGpQY# SD4= 5m,";c f/͞O8$&#4rVz&uy: bOGrEχ=r9W78s$ekd 4p=揝d r&@] .#@Tv;%aN݅ÕU AA.8V6wEѶ9UVdsՏUD5\`9 鿹, 6@|`_e/:4T6T& Rî>Wf7˕q'oEZ& ;w4㡞`߸P?|C| m,gqw79(70~AVא*VaG :0ٯBsyDuuu(EGQ#c,[FE'Ϣvc~EG(x) Id)+ ?-_-_3u,͞5;Wh{֛_^ܳ;Vh :Fw 鬤ߌpf<ONNI'q)FcML;QȚYBH~jh-H>a֛K}i6t [p-ɹEFWzM"֫yǏ~ÚNW{ b_7,9ڭ!gc桤0gd21qpuL`"Pc{L\LI]]tԶSaj5V >3i Ǩd:Z)JOSg%bjC?nՆdrOBxNW3}J*c`Ҕybdyڏ;ڏ;۹snr"iI :m],rTL<0$n7b T~fS\W8!Ep&HHx] KYi2w$a:m+/Ol<<"W ONڽ݅cb 6^cg/XN_w/=]XKcc#%fdakuJyDcM>Y9d̤]JOQ/TBMP vOP1bG"m\,͞_"F̡cƖ)?X~Ȍ!sF1q`L~jKi mk>Ͻ)!XXKA`~מ~kҤb}+U]wf曨GĀ儧B$䮕%;OC K Sq |bVrK}_<{aۘLS[)'{sRnjw^A|^N Z a5St/ۜm}2{?$5VԜ\ҩrnx<NJ1s|p3W9 YF . s(㗘}Y(I"ٌò5W4e iWz9p[" _O?kt\;~y<%8߰Dnfvj}t&s&5Z',-(՚eQ1O..y9Iz~[ѣP)-VX@25@ S\ l`_T Wt[i/iQ|VqbСXLG&b KyU۔֧=/FM|`,~;wW6͍n=b+oCjV1.dH }jEEK[5K0&$mլ\g$H[5ˠd@Z;gh9tid7)YɚTv˾v۫F|?SP7(a`4Jg%pS.8'_H:xiGmQ5_98vg}YIݲmU{^snT.kFVv  }NΗ\L+*X${ *y_~4xiƼxTc 5 P:FT*_'}7g"٥MRVv-x o=ksVw\¿VfUJ3>22(8XN $p cPO $Ϳہ?:*&jZfm@0] eF8`9PwnN|Ĕ>{zmD֮ `rœj(\Z2l.˃鉘ظGa`d䄹䔵twgoxAHO?2sT.=͂AHe΢~\(:{ 9\ȩmƠ kSvɏlkC?tG7xM[(pw9&>7^P+u]90Na}&v\-Y}W ^wps#qYOvܹՆ*ss;-UXZps-aV7HnhӤ]yjDEv#5w-`.bG^B@-2ThtZDbrœ݅K$4`1ST#?4,6~bQBY˫ĕ[b4Lჲ"cvUEh`&_9NɷKBlNiǺ&v 2^=_"m4{l4f<9ױ#E \uCV\{ ߺ^ٍC!Yn]ڭg-tDяN#I3Ez:ղ푬?w~vSi@;mxE/iq-QzyǏȍU*[.|0 dSаchnZe$! fa^vR #YVDثnPb t|YGӝ$ srhcЋS"ӑV8˯)o\a)\ -q̵w K5_=.]3v,jH_'`kz@pģX+ł%>я[3P[y Vz䞧8ҵ҃1(~U_ǹ?ȚH0(r${PyYqh ,[ҕnMMC)qb_a]ٹ|0Fc&'[1j,#/ܬv@/$a6Н`:Jŕ O?j)+gqB"=@g0GrvncQ#??:&E2߇ŔW]u|{Dž[?C@9WKe9YRV 5{wUrc^ˌ l. +eH|A8j[щp٦ CT[eAP F V=^ 9rºIxm۾OlOӉb C|'oÁf)RD.床L=`]DP[ꪛOl~_{>P^ͧSR(U5P$[Ev#L?tAټ\,M:̃45#jmiFMMuMM%Ks''MNCMbl]ue؅ikwa{M7[Ck*zZ\{he/Py #S(%r\Y[r[H2gU۾OiY[ԶO'ކ(zl/Vҕ/kS@ZO 40@'0BLv|8I x7Q[x]~x g_.ܘK;c1:ϵf@p1~j}gevOp:vN-4L吮Լot~{LzY[Qdj ^V\Q\@h6ߖ'ſ-ꪯ5^xiRqNqwa{M噝 w dF$P؞&,B=~rMx\.wQ.jUBյo}#Wp%^ׅs])[Rd46?bO9(U$}P4;cKnڪYR^ ٥'/(fz`mtbDv\vΑWd=[MmlXPg.bFPxqK(Ues VA3A2a3JCEb @[ 9e\N^E!M8ͭF,r57+xks=Bki|d9|в`r 8҂kW%" Y?ޱEs@X-w-'(Ge3>3>ĈdXoD涴ؑBF @*---d Jm^L(/GƖ-E$EZӉ/mqd eb䘝횻-EG429g%BuQ%_9ю+iY 2,/(J2}Xz.C͟-T],in5$L8ͭFc뜘bX^CFʧʂ[Re~z9t2G&k-:z'CUeDDUe%N?fʏX6`<8M]BԲD,l)>΋]KI3cbwH7dglQAE58/N-d;<cj*玷Z<[7ZZ#O θ3m_ ~i@sM\KXRbpV)('dl58[<e0%Nsx$,1c/ZI!TB;~}(^=3Qa{e:"&_~w .*q?s'-mPuqG<ݒ B#-k+&%]εRvlϷJ(&a" Y d' IxSimC^y 3VKv2kBCwn? ?̎#S''QU _xrœdG)P^Fk%>|4Qin5jvÚU>},G}Bs/_<`_Y[Q @CNLǬ s!2S'r*̞ABͲ 6mXg<*\hL!s^3z+DD.␜#:k0rJl8,K&e|[ۙ_9_7SG.(n[^6O'ވ;cI!'~cQS+Ϝٯ\pre ?zR Œh3\fÔDM΃;~8@&c Wy!~{ Tin50{o["K]t[wŨ V;M(=wITڟ+=9W 9liHaUҾ/Z1UuBSEe "s-jp5$=bL.:z}dI?6 (UQRUu ][=0 2lP;Jaӽv7-+-=5v5j%}F >|J0qlaEHKxA I!Ą0Z 7Ww)5jG p-Ƥ$cX=II"iKQwF= .!!''!pQgesǃ:xо߁Е48?@0 ]{]`mv{\qeAB\/&NS&~{ߟ޽Ύ SSڳ+u7g*rqu5g`22dBfw{WWWph!䞫)[Ƙ\KEoS1|qRI)}wJAoudBWH/U}Z-dOo }~斱9dbD)4]TPwTUGǣ^Wd8MrTR D-| |k ɘbϜ&s+ɟNd^jy]T]%|dА<皘\um0!/=w _su\Y,g̵`Ϻk^C @R҆l9ګh&'̱\gwNf<%aOO/}X ܆4dn_[M}Qa{7n5W ȶu<~BkB9ׯUfM=DWjT 9$̌anS`}GUZ78}enTY4ڻX. fQs^BΝ;Sui޷6}۲LySLf "9NXz+z CQ墵U^;92Z0}L蓁 s@:%``dglYH@s fgl,4 ZJUs5Vۻn2s1CҪl-C}BDÐk6cwdv1㸹$cx`)5 v-P͘KyF^y%qAWPQeGڥưmr?| Kd@S>>Aʠ ]=>涛nBHB \ Z RKi$bQBhm-zbK "KM&k `Q1r'u7sf~_2s.Ϝ9<9ϑ-#?z(>c//911D3P$Dg?ᝇ!,,L'0>++;ѣ.as<'xiO>fA@҅YK .H #Ԓ_\%P v.$U./.>[E: j⡚tzܲ7nj!:mn;б%![(^,ϚC&(3x"q ʶn޲`iPy2X"G򼉳4v@UfBA"zyPҹ.}Tw㾗87)k_1ERMHհfe!y:\{͊e ˀfB 4b?/ol2 7EHUAL[-x< `9jcdqq2ʊrŊ7p O)xE >yFOŽZ@Bdԩ(׻ ]ύg"%"D-l\_PHD t/"IziiD1j_չVXsm0-X56'#FFU!%c|Ɓ꣏>BΝKh_r\_qTRnCEb' 詚bm9eIL~% ):4 W_`W\{jfo+(: l5CHp+S 9:U@KI:9eP$Sl]LQlV;1ȑB.@a#p0" /; tWzW|Q~[W!J;1̢cw#tHo|=n3@9I%?2<Diĩ>._X/Q8,Ϙ33y93tNٓ9:^Ē n nib&fRFW{olj*Zi ygJɐEPP>>ŞϘ3GCUBoo/gO14\e0+eJ0b_oĸ8xOڐDn@ K@?wOXi3tb&b{܈ظ"OeҷՀ˿;*\M B3f}J I͏+002es4"lhB(3 srYssPfi IR{91vKOmy#4о bBE0c N"Ժۉ@d̙r Q?zA;!w3Vv5C ? Gy "cyė.l9#n܈nt+*Z#j UgNg}p5i475z>hnjDՙӠedNYf\sw֑8Vd &'pٶWK.aƳ\>6~{ܹİY<'ٛv0QH>~)F _5HL ZJdl\BQHl}z>dp$:~P52""Ji+ar ~"ָѶ;գ ?)äH\ IC("fz򙝔rJ-hG!5(TViC^ ",[o+)[B`8t;Vy͏2P5I&sl>?)&C?zq,. , X9c 7H]jK;W>s4ΜGq:~hn%ԃ###*3UMLЍ3-OxNVIRutIՙhjlܾ~<22=-gkXHrV ,D|N݃LJLӕ~E(|fdq3Ν%]9@%HĞu$e%IY k;IY V:oXH9]bM i"/]heɫVӮ% uꇪE}/ ϋ8-wz'„ o&@hȐ,'(@?ia][{9LZr%4GX6[ߐ.G:|sR#)+! ˳e,3@OZ9l{H4?$WM wWÅS*d̙s$eA Ϟ6MݤnA[tJ  3/60j I?Oqbh/ 7_Bw{j~*'g*k3o! yd4GOO7; uU̇<=Q^,6RYAKgOw&s7")+!h/=>LfOJmP[XRVAI -"to~k z;ed鄦 bʂ!c1Y "0YR@ʛ=: *e|Kx';,7˩Le6T )*ZT}ǐU~*T=1@x~Whwoe7vw߲!L.;#3Sx~׊sdYE5G M e{oO?So![ӏ+UGb۴iVV|I<2Rs!8u ,Yp,N9Y|fM K!%IיS@ Ϟ  )g,q+Fю_h/݂֜;}uLJ`G>@+A V¤⋧JuIψ Ƌڿڮw?=+\~Z"o^j_c#_.+ Z%>amˑK& 89ߜsp4ȩde69 HLH.z4[F[ txO|̭yP6%a7@ 3@|5>1'(ΛwK!d!~JpkzBxr&?.s_' I |2:dpP wtM;ށ |ŻO7ר+W mќ!#yrlXѣ4;/\`OBF &/gX݃\pS+ZHz09iϬ tRxuo:d \2#hfͯNuC.mo,OS []PF3 %s*4=UB&_T*O#|˥{7v_1|<2!NoVn˨Yy,˔Hr= LuL`ֳ7-'-{M _< ͢CYpV,ۺ!n-ٹTLbD~cƁ+@ dm\j`k5b! j'f{nHԺU/ʩ[l'f+ۺA@ĐsU(% l~-tl0u.U*}2xIR!s6b={c%\9%JPAurJ.){B/e67TRˊ3@a n=ݗ2,.Zs_L{ʄt<S`QfP~Ā V=%5g{t2&tkq'޻ %VgzWVa* 1 i7$^P՘Ç ;L­I=h.*ލFƚ48m+<^kY_X>{$!a=c}|7zB4ΘjxAYp@Q57d;M-WЍ?ĬB"1[S`)w)CUS77& C屸@9!猨b&rɗR>cp|~V2\CDfl"kw-dxˮoR^K ["G/Zﻙ)xP*B "bփRMq,OeqBkO[Jy7aN0@ /o|Y AmPjnsnvrWz̞]`oEQ<ո)GyeO5.!lv̲r}4?,Mɼиt"Xt^DghX6M:T5&ܙj`ېr,DJ0B=|xxէ1<p_-c Gf@r Ŧ oJYQ8ס>ٷSo^~UTz90C`!;JT9nZٸʶ2Hq0 2Q-[12 vHva0`I)6>f_1[c; B""a:X}M-Q5nl0DOpxM 1!=n;Цo"s8Zy;V/EMK ZQ@]-do?\R[@qVaQBhR^ }TA:B] ;JuwV֡j-+ C& > 88#I߲-e~fL,4; @$}شZeyW?;\?RJ6e0e1PSW xy]yy 8tm^ӠRB7'`pݘ=okr32̜SJ*ɁڡwCZUT{SR ݶ⽩ 6:jʳs o=H AOH.Y,ֆ˩K4ߐ6{ [BC0pEo<]gW+G,\7Iz 7ȖL֐Rc 6-C̟c 5Nkl^gGgJŜnsjH4{vjJt}Z"/ͣ4OΊ4k77ChI0%3s`֐lM1[SH'9W Wv"00--m?An"ܲ/u-JMi+LQ-=/5DP iޅ&w InyBpE?=)S1iR "tV~ݟjZs`ƜX׀$E'o*ۿ`bA|T0{lѥޛ:߫tߛ:=_0R$O#"ٖz/垬]vG\#b5Zn x-J ^${WQSW4C{{:|D,t?cal b 6r Z1m%)`0`|0ݎD$ԈFs}S+/uXuruD?>0s)n \Кj!\1п9@\BK_C/%_)n^|y'Df\âehEUL6޲+.zoSOa+ ]smT'GG!2~@*˦PT~w߱~O7Ju5S ka^hP{Ն)͖цGԂTQSga;,e[;oM Χal,,Q5:yJ¡SR?I}Wr+hhәibzA{PX hoӸa- QgR)`d3)kp~n[-Bn~h\iN7=TL98*EH>~ 3DKzѨ qJx0r"l6v"'024ur댅#R^06;%f)n;83_f>j6 au6e$O$`4m6.}K ~g'݉WNp x{jyrqYsacP&R@v^?կ@Ԉ4o=yZ^, 󓏟|ᖄ-'096^4>:aq5Z8Y',nmE[ \}09vʒ n "2q&y硑AԶ՞ut꽙P O:˭I2ہIZ7:i>XZ杇C+i+2?_mx얾 }Z"l {^#b ֆ_XdV4 QaU1"jk*1[Sa)wH,Eum uH11IZ&@ZED4,|1>j`X+Hy! E D׫ѱlXNg_O)sؖ r^^6/%sn:V%י0w@Ȓ/Аz-blsH3d@CM]R-ʤ2#n2ܠۊB0!,Xs9:Nɲm+ԣBΟkؿEӗ A;"0!" )X4} #N^#?:af@#pfd f굂_U AKCg)wi" /joCb< WENv& .$.ݱzI CN˰Z/YvrK=nϱ/xk"vbbs9&Mh }t3h*8XR=IB(!_pT$%"0mNN(@q/%,*&IH9w.`4ڏ>}t}˗X: CٿEΝKғ,w~U/.EMwxUI;`j~Zal9O>0$?ab\3+%!t&LCىP̼RB}S _+-'O ;„󚑑ݸ 1[cbM3ɂ&h`iaro9Ng56C h֔tRȒ[3ion>o֘DNgJ`)wHa1fkJ ʙ3qp-@1$PQ(~a<8g7g%XOq׏Zܠ@wO_Z ł&^qL;_rgbNgrfNe~;!?a~CE3 _j:3s3ڱj8јz's4ks"5:Eʭ_UrpJؗW ͐jƕk^nr=>]bu\,_줜X;|RK'U9u"ƺ&45r^b\|M耣?s4XWAH/gvjUM!gk'Lq? K,V/t|u0 +t mVAҗ{|~¬+_4ϣkX*"99qZAWm"f7"pOƪ {[(兂ȡgh {/YC- 3jHIm֋nifk8Vp\?#Q1g,eIY R:29o7$8蹵ЍwS,`M;z4Y%?I.;)|m8E/](a1[|mؗM|-{P[vBh3OyEmIם% RyR`ʶ!oݗ5XtZCUS ^)\ǥ~s]JqXhX9[ 90`RڷUL'V''aY:i `Ŕ|$-/]H䇅v3#x,b1r./ph,g#f9P7NH-t"{ϵ]0n 1 ٗ`H h#0I<<2zoY&5PqÛLl>|]au9uAűɄW3}@gSH 뇪xf- ;m?cצ'ֱJžBR5Ϋ+%.<0;Фn)wX9T5ylۅ1[>;z4_ I̽ *$N߬WRGlIR+ͣ1[S1,!`9׳;3QDOOU $2{ '# Z\#zbDu}E׈0m|OY//ٛ(X"0tWoExCX)|_מi-A-bP:i!UxVѮjzs=3I܅S.ޮ }79( 9FD52pjHZq*-VrUMBEGb%$J*!a_GB3ܶZX'oD!1}y.O"ݺ=]tp!tWDAAMLD9Ff,;uUܭ9:! E!`{P^[8 oStrx6`εD d޾~B=3)тO72z&a$e6Mnhh&C4T4 AKNW( {K%m?J1 ltj 2*,㛄qEyC>\:z@|&>,s;f'A. 5rhKƏ##?ZDwkd&kDh'&ػ+x|+d㒖I L3fJ Cs/s1޲KGanHu:bbs^߹ ݟ4T+J>]wIʄ?T&(l;f+3\;aI ԤÎ1w*B\8a| ~7>Z4VYwi**[vYMBe6~\%p̟YCUȺP-y;PH=nòHc!ͺkE˽H#;oߵ"Г}nV[i$T*s'XeWZE%7dew߿&p-""wHyjM1wOVZoY v*MIY 汖QpB۸&ۓ "5t@PK ݶhjz ڤX-J!ApGIsU"BooU.(Ș@dr&#uvH$Vpvn+ HW4#v m9Ҙw QǩOi,L"I\CdQ![-;rLlV+֔ԅN_ jJePHLf>:28qc1zrۡf\Kڔ9_*w'e%>\ E7 zu޶GCR`2h뇪|!CVi9k1-Jg>3%RPѼ@IY %$";yU νo'_0UyswOoJ2 ڑ7ym){C{fů>*ڮ/%'nj(EBe4'^k֏\Ō [hDݖ#yV$pغt,#Փ'DUې[6,tCC,;E*%xҲjM!@H ho#mh&gl'@ˏ%)+kS,-)2v~׼52HVIUZ~@HXIY Ġ:椬,A,4kzXaO ^R Fãn*U!`$K оC,L7K@\U`~1%2 EMʹWwt'ꙃvcVfC{|U@1]V1o|ˑ:m⤑ͷxˑFM Fn%YKLK d lA"FMikA_eV[*@)'R1hU]yjWm[}7?Bw#$(ͮ>&)!99 8¾rIEoGum[!-Gr2&FC}{Dz}N`4= 6Džr'942RQޡې&MՀ<2D&vpG 0՘{D $#u}mh&<<t bz!lÃ{i}h 'R%etD%^9&?Mۆ~ ɉYl 䏲A௺~O&eh뇪ѫ$^AR@/aaYܙ)Ȉ # @AdPP0 @ɓ"Ib:X#0.aYpCaV"!'t>Ae±[###{TzO䞓9hh]꣩Vng vʯ>j j&) jzoXڤ\]1Hg"DDc׊D\/anu1aT|Nj2ۡxL`Z<=`xhs~ȍiSܔ`ls~J={=LK;qӋDh7s&d!Q6iq|o^sޥEi˃MrФKU@rPFF~*)lJZ:N@DӒbqcCB'f%I*,c n&:GV0]x(3+CrP&փHhъd0sA{u;pK`d ~mb2ܺb諭EV˞P`>5@}эyfbzk;߶[4jKZSw.0Yܲ\2X J_@!R݁3h*L2sut_MH]$]V9zRU^Aղ 4T418-*E?ܴ8 KNsk9<)+@9y,-íipHl-䠌B_0V !!Λ4-)q1T )^PL6Ze4T4ߑ~n\J\;EE Jcí-POC&!& +eBF;*~Tz4l9tӳJ)Lr6suvZs+ 4|-qjh>6:/ ti ș7os`l2$lI}8g:2p>:w{./!az6|6"@~_@Mց`#݄^aXt_P:fBs8A8)#"M(@CUf:M9[ uZd%)XIY #狟F6ɟm/~ҤBs ZLikyeRS}PC>}¥ߌ"Vr<1z>f 'ߥ%\0Vղ܏;@ZZz,9 $IDLD$gp;ls5[.=3vtu|w,3M[Xg  F| {7&eZσk{A&˝{,'o He8~3} "`/Lj:lPͽ'ɕ9d TLdSrˮX/zob;iijF߁MgZZY3,&= 5t[P}ݼ޹~=:: c|=ШC.{ph8߯+ay̐oW 7I!ٰ,8 KBph=p_)/@0\{S@kϞ&Kk0=;V3C2Tizs/^H+yr&!N"-Gm.sx@D_>(ݮv zhCɱ1w 2TRI4TmXp0 fQ) smIB.?^e{X bo'*.-M~o$z=\n҄Nz#930<2a4ܿn; -4.yIHoyOFcG3PB 2=&nOJq֘AG0}r:$ה!`h(I\6'T@G'o`כ_)#%^#IA8o5/M!}CV&x&wSyؼ#WAGqhwkb dJӧ"(0>*.\$^$ :< }6FP/jm4A<T*Ё:| kE"i;wĢ DmC[ށ"96]l=xlD^ǽ:r5@G@Z0 -R|?Z^L!'AځA^Lr5aېyO?7,vy ôlڣ;vW R0y^$C rd*fi3c5G joՈڮMmWyB@!w.6̅?mQ~Z;A}w$PBlO~Iگ$y5R 1ykf<i3>&c SIV:LsiP295rwgDZܧMx:l=p #"L#۳%_޽v*]?k{ -^rOᄉlW0&=z1vM\Ĕ UD7 *.?m?nmMWP{s  GE ƅc;XB082B @t; VhjzRlLIrlL^GO/ptt*%A`ʄhͭ|l5GYgrO֬*0a:U` &#.WIң9ؐqWH#yj's B:6^kTxy|L1n8dMRS@3MD/l6TgYczuiKEj%=<4g/sh,<&"]XitIe3RfRubs'+S: f>wօ֎N8^4mlP@:] jB|<ܜ̦TX xFH/xЊ%U=rӟxu=r&0,<XJDGS+_8k`\YR5qzN9C>[<:꣩vz!a#G&D>uu*ͨElV`dx  'Tz 2fp<{`%_ɲh뤴)񀵉IIJ(7T[hyV&!\T>E8?t\ 'L΃[ ɗV6T4WpCj6]Ɯ=[-㉧ 1s֨W.%q ٦}n/d&sys2j"RD~x.o||%/! Ip)|ՌBN*Jʰ'e5 )'2hI*<=9(T 3HݘwvfJCw[ O $INJIY uށt bthgOY{Sc~[3fMJ2D{qq#Of` 0ӷ t/ܿ`H1gN-[exWM5XZr#.*j# P^N઻H(  d6|0sEΡ!Zdmny/.R̙~ LK+?Ȗ<=R ˠ<-!F5~@ύYs5j55T4o%.qCKm8=Zٴ ډ =۴ol{-Oyc%`;z} VQ Ag~I6?S.TD(l~ CAͧEx2wb[M;CۺHh{_ߴ w Ryhdә-C6%IY X!S69(Ck=wq:R2ˀфַz@0j1(-'/sѺRՃͯ>ZD-T7dz296NFA7 p[oZUzֲLd%_1\lm q8=Q@H?TÚ!,9M?kXx8G»ǙK1\$s$s [_>Jg)/Qm$DE1k"]!;:_If9B!LHYŁIzod>Tmya&#c|/gnn+ೈIP@eV # &7Nw>N4T4"ߢtROMy"LxIz)NM  [M 8918 MpD 75hBNtLxVRVY,r$*ǘmv#_1p#Y uEDPU!|P%k]#./Wvz)#T>Q|ɏee:&iǩݍ6 I:L 9yl7l9X BPVhwޅͭ覈 EE!4wQ  %.2zJ🎧J a9i5({<=~@9hy m689WMЈ nNOaZل ɻ /4_hdqUd؛:nG0 xF3Sd"AOotf0Yʡ~"bj92sɗnPZnM cXr)tFF0ZzĦ\$Ȱr; ,]w>~"g.||̟QhY**]k|Z;rr04oI;ޛ:Ћ6ؼtQ/Y?Te[dON\}q-m,7꣩%x;H꣩ M6{~rl &hā*Li& xtPa>WuXvHL`%Il")6,~޼3IHbbbpdD.;iBw_rit;տ`C+_/*&fWO|56ՈsTS2O\0^Ԟ_yx;9nlFC eWpL]9w΄ y,'adB oÑadLd4cv #oJ| t[]%٠LĘ0dN@fN@UrT #?)+AʱϢ%&e%蒲lKy!d GƳb 9VjȠ89H>~rPFyYtBa;Xh,^cM_}4&bf Ѯ%g.֢:[!1Zn®ӄ^)Vlju!DjJ 8z=gm?d-9@{K);ǴkV(tع9%¢W ;ۑ v@i(/ko0}Bwg;͏ +mV8D )> ̰bK/4)8y ZTfkJ HgwcaWi_ [?:kkA{s.,ͷTsHȱ\n[Ȱ?vqnEM2eG ZMZ7! ns]$f V M]aRBdw oAXDvz#wo =D+㥭_ʑSXInX}vo=XHi!,/y\0Is N[ [43 $BQ*"%`p^w0"VCE3iCCrsL1L.+bL ͅ3~l['_@SZˏƧXwVC`&lhE f'h'"Tx ' yt eI.m)=ܩ["t|2m6lV[ME 1:=֞?3jՁ;60j(8{(J]\NVu^SVfC9ΎHZ`t49(}~82`cw0#-?vN|MM% #].rJETx82 ]B?}q)@(s\,RHLI؆@bäSC`ߍQBƳ}վ*sRV+\/#!J6/!IcMع`|!B9WM-YY#}^"sPF@k+_8[xWaB)6$R[4IYX{ytFF)?Wz='#04Aٙ_ golu_Cy zspPx˶ܸ|vS4C 5DC$c-K=/zφlu_n0s+dِb Aw\K鈠UpRESEa-ЃAR(T&ey1(ogE!C4K_Gy,ˀp %sahh.snՀ SP5`DLт"[!l)Bk~;PT{cGD#ӂE`yr&D򅳅Y>j(cmWhvB;kd hHaԭ6P {~|iO':w 8z?#^^y }!a1g( S637􈳗1S'emϭ]Shv{+bbDljheEo M^<ҁD].}BL1cĐk;q2k-9͟u`eѧn|0}vpdر?v)R|0L!2MC fM+5'CƎ{2.r`Փ)6=KHͽz[ߛ%X2][Pdʩõ $lڒ ͧ7N ?lS1=.)"f ܷRmOskrdu>Nfu6|~{owF8mʝZp63-@![mo6F~d,rcO^0f=Sr-Apzןhۡ>/ͭmێ{/+_8K*!`%/aˑFs(T[w Ddn]7#`X}ZU' Ķ56an &x^ u"o;qBnkhŠ<-rtDF!;T5$[5SEMO5 C)}`Bd\냹r߉˓S/HϊM_TW#BO-\f"f)< o=k{ A{+G35ywpQv)7}P&f],Lu44grǸ}geL91=c&R(O$XJ,Ej2g9{*KYpb"M^͠l0]^+ 8T5P|_q-c@J:hfR._^ep5l@Z8Ef,j\3f͔>7pe@1}%)niuEϘ?W "MƄ,*4Jr*Gbփn&N|6 ]Ѷ^{u\-qtbOZ1[ó1=> H8`S^i Fn:a+= {fBUOu64v\t7 yOlJ-el`;$?.VKP/sv @𰮩Ɇ q꿪lIacpjc:&#D_\ZSȐbϸ\\n%ZGLw|W|.{Sl^XH>֖Z/e1iY]zVDuuE!ZUlZ*1]=.yelKNeA2Z/e8hc.7}:M C+il 9$k =pkUE qںܞn]ƕf}9PиYФw<%/WQbBD5vKHX!M(> I"˨t["n߀7fkrIPlx4bq\|e%`4) :PA#7ͩy^>ũlAo|8Ԛbb# W'Y6|}郢u%_"R&Da5bc<TsP]c1g 5d#=stF$Fo NuA~OK mhY3̄Ib`2yJ8T5|L W!SDUMFl S" y/whLw| Rf@a\LhS۱lo莣KH^Hm$eȒ1"s^#tSڵXMi/8Pk YDr_$g v^$–Uٗ21]2l]r-eL,JU"v7M¶M)^꾺xDj0|袍>uƎ{HzYQh-o=Hr={UQܲ&O'rhjlBC}h%tuuz+UZדŎɟ8q"?mkqwҤ )MT|roL,b qӸm*ⶑ!ݠ*h B&8jt bfB¡!m^j4YPCeaNC-j|4kW߇ؿϜؿA_ h4^^_ !h?#nV@JʈC$3yUWZ l:K"oy@,]C⻔& p9*ioYf g-x*Zޱ~sdHXw1KƌwhBP` Csbώ=*-[-(9H!G-_ͮ= |]tw<=+|h̓ɑPїz٧w3MUj>Xl'DOVw;xCqYfsw! K|waX7 ]w#&"!E /VCA5Š-.Jyqҧ{,ROR$5lJb 6XzC}*N)]|.%)9ɭNfjәiBg'_>44BQQo]9,4-\Z3s,"*TY.sHVvh>8k;~ht˳+LGm,fb2}c>H JdZ\bD7Y,ej]=@T2Ru*TGU qI1h T|Ago&pޅG=EFt@c~~>av%BNYA9:c9xr & ;*tƂ1pbu;$~sC8Hh&ce:::G;!&&ƭT P bc)k2DE{{;'#882J|GH<2BH,}JwӊOO@ @=9 0Rhƺh:a)wd,-V*G\ņ>B')}= Rj]^847WҘK [Sxj^s[٨U"ěP2~G)ifS[ neˋbRD5) 7FM"F=mgL 8Dvs%Cs@dmp{4߽ӣ@{o?)‡HO#jG4G6Q\WI1ٍ'%RXi9 3P߀>t:t:M|-?f!~^'tgۻ-&Ø8Q)vc%R r- tȢ+ك* 0fʜ!Pjj],cHyN1`qNcxC?eHOhyH^nR͘K`DNUK?GK8Յ 8<Jⳓ3ځ^*_}-VO@?~Qo^Klz&`ǡ֔bpQzڧC$s_==5jM)^WHe7FMB>ko:2Q0S9erǂب8wE{K ,u/CCcZs41x(2!kV dʕj= a9P\@MpzžLДCg\.6n[ܠ?` PiJh\u͂pP7U|/+X s*r8Z|ǟU"BnMW\Jd'#6*N\˔2 vpx,:2rklާqC'3e}pWFͣH{r3Se>"VXZ-gq"(Btkh\6[Xym<.G2\,9]ͦփno :0e:`Hxp!TLjxD^5q@ޏ MHXG K= 1OjN7Z]\Sxu:kƒ6QS37 WKqOyYX^DG½Ђ~o_GfZ!2;HX5 -&HXC%r*߲_l;uB&E`/{μu:R#6. &p(d,AT~@hu%d"TUT$bc \^uE ($55p #8id3eymtF,{>i;ײ7qD"2<9?h|%OB%7Н8hCRrR]Rrxg9Hn3 kVA}Yotfv I:OPc=i>% 򤜣Je9:0Y=-MT- T$W#6;DAJ 1-x<5fH&%D{ByՆ ψ1/oVhH^ >LPt@]D6L¾.|ߙ3  /.I=N6+ 0oK;oG]&K 7my܎IWqDY'|AΧDށH\=Zh{$<?iy^dV&^Z$HAnGp\{B\[%`<^k4 GmTyXknўF-2R1tE#fdǰP*L oN,~?{' !KUbZ*XRƦ1[obK@ Ck4^`/uPZ加`r$ː 2 /}e~3q[K;q3CUCڜsS/y<߯~hlӺqz֨ tiNO}k.H_f^@uI{P'^՚kCWպ&{:!{x͕wW!"wU1% N@vΗy@fto44¡!O]?fowSþ7K׮d}ЅM+b294]rc'mUP=t\X.2dvo)GC힋(G[kj+5)9I/LTXP*w,1BGU PzpZ`+}E8kX240TTŴJ#-A- Cs 1%`H'%h4ʷ#$$A_~MyjT{| yY cpNJg):#1*W Ó dT,$r4 }q ?D5 Wfv5r$ə g~>TǛK:[9Nmb nI> ͛xI:ORihd. ֻZ 5O3r5C{i{c^˺9NYXsG0m3)KP{&Rp:bt5Ng`k%.=2ױJ }fmO# +%|;K^&|mL+C'킹]ZM$.bP{r| Cvz?`9l6L'ͧx/4Cn+83ukv&lC3<:}0ќ˔Է-^^7̡i$z6tyD&Oɉy⨧GtFL+O~"xm|!ߵ{9xHϊ Xd+,ٚ'V -1%Jp MD;/gPq98s`RM"_@ΓQ(_mo4i2}xd֐bѬ>1 JSV'/?d|ubZ׿@ȍsr\]Gn`vKQxwYT^7!'_tFDE޳!j(ph-sBk {KgaOJ[1Т E +eIe-KR_hQt_38QϘ0g6<'ﹲ'_ /=:^{0f]F E;^$ UM=cZwa]Od`X.(tJCáZNysR80;1[ @҉Gla?b! YvP抮# 0dN5k7υEpjș3Dɗ62ZX(֔ݫj7 zc}j +ƃ3VH_7x>\7Zb <@TAC~T PZN22Zu `ewFZ} 0; `Cp m _#F_ "5NGO^;#\+l?pX$kҭ,Ҟpv}kU3!3X'?IW{JV* t ak`>",c1sOJbf_Zj`jF!AGP9` \"%R ƿiȑSELnrH<DZ:ʓAYm&^k1=R赁e[7HNg>#\68DUILj"ɿߡ8Mȕ'ȗШ4ܢq1VV=bBQ q#T!2B|xNw,. ˴ty0A>d vVs!#˼h|ulMav?>/aA @GeǷaK$d5ߤl'kW$,ې.YlVʝmV['7&艋KL*گFL`@vڮn +\{e[aDzi >_k,̝ f!d(rc|8-l8A ve0>SQ o} `73%.=u:Xt$CJa r1͉%?iPۓ rבF/q;j 0C{CZCC0 O !|Lv=):V%k܊rrh:qVarmNDزF?یJ7B?2bT ەȺ^Wh,shWN4]SB17u Y? Hx9 N\\Q>qIYm9bMI\~ܗsO3訩dF[RjWBЦ<^Nva Kvcz+sj}^ҝO`\Q. 9IFx wU!ŏEA2YI(5d$5U]W_Em}Փnl#E?&'7mƱ~3@97}Mk4ure4#}1Ј.j+u {I7.!Ov6-vCr6cI kEmܰ/avi %D\\Ȉl_O[k@SZ^~݅b;<"csu8mN>ߟwe!8$tmDxc\N\\r @|0>-5Y=rgwJM1rIrEF΍O/n]%_l/EH>~RNxo^r#a;'r +%``4T>M>Pš&p]|`/|u!,<;zavnBnkKh+OM&V2]n#' ՍlU09I:-,8H.nX%IJ{=ݶOM3鬞 m9X ?MC` >iE`A. 1~b qBFaEL$E$"K  ;p_QnL:$1Hs$ 4|v{EFfFSUQe#8niោe=p.c(,ې.PgO rXYTŴ\%梶ܖ__.s) Jn +t. WGI}\Sb %\npFZ$\n j靽}Q 82X _.0iamL;m㲜 3=zj"I^mȐtgh ~v9k_7 `mբR]pQ:us|"rm (wxotTN$}7RsZ c갱^9dm9ZXMxb #4C[ZLL@;}JK=:aGp/;z{=4~yܻn+\MbZR"g$,foXeu}|=Ц:Mq{'kem\򝸸ș#_-l,Ds}֮!?!aԄQV6] &8kX'&u¤ʝrL)0ukL˕E8&a|M\qhr1(Lh!|!Q%_Zx_SI{"_Ҳxds ,7]IN{0[|2. DYЛ1 @Ûr$$)0fhT^#c&{wO+OUG^-Ǟ([h04р7}=W4D˶v#l.7#ft X@EɉIxNRC#NY)G==h9SjsnG\#8Woq}d@vH^wܧ?8FnkD{&Lg$qZ0\ΥLOOE(54OQɖmݠ/ۺqNWOtv=*pyj"I*= MFx(˃G]IF5A=j2e<▁Zd"$x!⻛CCDLfȀ>z6taѸwB7Ţq}_SiL uÞ~Dj@J,0‚YB.54R}#C9_^2}Ί}AbzWłFMyz\ޛ:PDyA|@-g@x!#1rIGIH3d`J}5b#WF˗hadY1&T[0lmWya_L4]韛y^83dQGo{!3rl!~sRx1gηMl$Ȁ^ ,)>8ENr#AxY!c[N @Ym2PD,rG)(^}R޸EQ[$+dT8^jΥ̼T¾rgPcLKׂTuwoRa`%F-隔ttN {S6FM€H@H0Z?ykej<)2WG ͐Q]KrfUZ셽y7;"[ϓ9pu7=qh24GMڨvV=cr V_A3ݵc3';;mԹVV.SS%. sӸ] 'IZ<~=W´1KS3n\aBܶ{y\-x&B?搱VYl+sA@Ρ@zJ39;ÌvEㅩB h.\~,o,+J%Ƶ2 F0qO#4U_2"_ߍH\~:\"o_>2R/yVRF?BI@M x-s8%Qu!qwh&n:F>W/yҶO("LK570Znyi ~PҸ[|WiM>J kD=mh7`eŵAڢ,ƳN^+s‡'W,2MsLIopgzv~9k10"rd1D$]p[:1F#K5e_wݨj_s ^x_73G1$zPՐ;/\d~wlp`0vނV|d# Ph\:ٷC WR).BқmJ* ?f6)& IL#N=>֍U!xs={ V~ Ԣɒ(Bh4?>Pß&໿PDUHƷƗml3'~09:jQ.RVDwH9ZLxȏOw2 *-'! Rg#Iz?2,|ꌁ~<}~4w9%apD+"fi*p"<4 ]d~r>}I+G1;I?:8e ztOgO5ulJ[;ᆐj_7_tKx5uU귳&i@Isb09F11ݲT|]l@ʻ?EXu пVc搯 `dZĹsw-lM0s2\} &ʃ:xh].z9st0%(lkX81ID}! xrhzA2/*ƌ **'7'kEb)t{p"BFgܴ`&8ǽϦsn#MO{履MQ P$| zT|,,0RA;Kx$,񡽒uz.ctޖr5bBnشM[?9vpp~>)z ^J6ԢsuM_ÚejCnę&j!t?[1Hy˘=K*uX"v=4DJˏ||_4ڙ'QNWCUZ\(mHNsDH.{ՓoM3r2[_p@eHOCNE&]+tڣ%qI>Xls4C}*L=2b&nV(m`I]YLd% ]TROa=?Mmi@d3:*wj(с 6 _ :|h9SƳE;sn,Ռy` u~V{3Zlf)y VwMxq"%x;wmbJEuH?x`ץisSCRz_x5O{Ϋݒ[MXIւc%a@?mpOs$1K`m5KGx9 ʫ'CM"$ċ:X%xgPCK/@@N݆Zhr#ޔ)VܬυO T';i͜[y "os!#eoV;%R'fbFs2Q%9y ~~j8Hy4[7=x!քq7A8:l&k05aPHr4C#7~1CU׸Ҭtz۬kI{S@i:gO] %Mv@GghȍuM՘!5 ӺycBT:.o; }iCUSho`}i\i^,@6WF}:gO=yb ۶k4am.dp,k t+dǫM:P+KO-({ P[s^c}s/%=dj.Z_WJ/MJŅ/&@@nz"Z.(C/19 ]Z,ks 0fktY(i].T'pc]^r nLR&]%'#)9 W._)P+M}jS{S!X&|O$+k)w";tY|PLȼ@T8uF.ԁ|EE ւa|f6fk[ٴ>G1Eob/'\N3dML ɖAKs hooHGmi^sm= ^y!ǬC`Ē'1y.e7=6@ǎ^DEFQ 渫aለADڧ5aR|SiJ pҚ[H[_ I K)[{`9>7\krSx'›P_@s,GRsss^ 5_ ?1`'砈?z!(ոҖy|>dO&hӲ@Xvmb A~PPY*W@¢*(^*B*eRNMK-=$d}^sI23yLr!wv) Kv.ا.` J=C;'`\@riVXI@.}I^6T|.A|R[ cTT5U@o9UU^,nʊJ@*e{vTݨbseZ ɗI"e("^zc 9z>*zVJ&S uUP(D9V t;d|Ud/9Yl_K b۠jc0Ú.;!42puaA(GUIؕ `< 1NzXXjyT͟d' T )V2zO'mXrd-h䬾a3rLR&ϵ!3Uqr%oMB[ T9mEc[YOܹ<~'?k/ {$l-~~ tH(Fo MSOhF 6ehٌwX/7%}㰴&%/-Q7tHE au` g{o9LJ)*E}h-+Y|HڔLEH|) _ OJEc[$b)BRO'۵iV`9O|5&_ QmPKK#ãa0t"a-aiUhDqv ~%4oV9Q=r[&SUX:>uA6\871?GvߗїDgЎ-aGu< 4t0*!ڵkRh8^?8N{Cf ءݫ' U,T1R]_fܹdm>|bVQJ‘/RHZfZ'g.h b\5j ,%""}W}ͭp\[M+SyX/ Qa3^d:>w` 灁҇l~:ESd<@|}3l]!ʖzY:lr_Z3C)H=ϼ,;cjv K!Z^D]f$+Lm8Ali/%S.3h}[ф 1yC0If8Ϡz?B@R^ u/0UДVs:ˮp&uŊGț&!1 tMw1+T/x 0xRPu +h)3;6\z=: W)6f-nC)*4DzݢuJMR C'=fItfF% 'GA^A깒{ryO[5t;5vHٹ7~t*P9oX>˵>Z15Ƙm)bާ. fSjĨhg+NA,j4z|,BtߥvH oő"^ R^nɎ 1cd\}i0$JY-{"`lvDXG|a1WQ0DP5[s0H?5 CŧɀвĹ7믱6Z=%'y\%CkV4kWgb 8D$p\sIBu<%v [ҩA:;ymNۏO8<)dB!l?[ OJj82k)+8`F &s9B< T @͓/ؔg܆q|?#Vw?qڍ۾;Mg ovgƒsDPC?H&0%]9L*hRI.C\F-{EK "O&@ "0pU ֤rYXj0߇ ]um]/oIyIsa[bh;-+I*$hsd]fJM@ l@!gD#0Mg= w<$_ Q04h[pqOn\צ_̴ͬ% -]3QqHu.y.Bշކdo'd5qh!Tѩ!0몚tж@ AH Gws;T=7R+%-tvb *޽q w{7 OJeUU{(b)-T%fnyx@*V+eFBb*+*ͮ=7bAu(wja8{6 RJ׳UfkddFhpxrZj߇lbYmT*c]j+Nu7[[:bq6E\0ZkH;8[p̢NCo]`t*alzp "4]ĕ5 rqp 5JE=4]wn@ה{qZ}: V| YɬIefnzH\ܑ =;0QLa=@;lFNj SA4|Jz+6+w#_>.Kwm ' tߨ]:/{,߯AJBX"%AS-y~'j%VI3ՌK7ly,M+ ! a{& p$M 11wJd/ gR\ڼe; g{@Lc4-u t$_$"TdR7uـaJEfuڣ^|R!"d!8Hõ(6 cĹwO `[˕J[Zyoݧ.Pv~Ӧ[whU 2߭2w|".(#EV?PF>b:lƊH̝8_<&_(+$ɖkN묺̈́~m3=eD9Wx Q(ޚ07hmsv TUs;* #pTcnKEP\uCj[{ޫƧY(tm*  %"}Ϸs<R1Sh#Ny6Vcq8JN !1B#Igo]tvtͩ:QVαo7]w;W r $➟TZ._P$$_3V`%9cn`_ *#6F0$R!$R!$Q 6FcCEB"_y jj!sk_<9B9nwu4-PVY:f0B Wjm1qN._5gs!mW~"U06lgBrd5 EpYSh.J”|@߁-lF~JsGݡ_,5j旜\Aj6KsSpk`&fCksˑ *M*rNWym;xp;~Bv&!^j9pF:CQxfq |dx"Dxs- y  SHPH|Ebz}91P\Jw0 Up8‚HU㈍"@ ь`'AZ,V;ӹ(]pqL:cSN@QS'J{ Ʉ"aC!IYm.!M`{0HM,q AQ z("8H{hzr2|u5\O/Bג_>ξO]}X2L~F{F[q;kf9]<=".Fj!UCC[ڛ:`7Y` BOkQRqG:Cۘ2KL%_g;A>Nk YNK _({8OAo}z̋8!^6[QT fTV+VG+3|Q46l>FU6uW6oQ» RģOJ-sL2JrkXPp9"ޑjΰk8}4zA$Ғ~n,Wmfjez9?IxּLv8,m l&3+(DmCJ̹^|T;.Aw qsП䫂cCH k,:< Y%G [8 =CﴹhgdmojQ ybjB k{'):YR%0cXa3:5vB8L_dVa+ͨ$$ܯWph Kojgo!յiKe+|/%,Z6Cn: -~.y'<P2P^L"H%dL0A[b~9VVYrR n91:"ncBk)-Y!%L= 6,< P(hPPYUFmEBC"Op K(D؇f>fkhuU5smN-NBtBhku{? BbaMzqOdleol3wAp󼼝=aMn;ƯňT\/h̏)vwvl˫e6#|'FHA@t\#Ag!>Zt _( @ǭS!jG玵8jb( t 5JĐE ga D҉f Kt<ZDPWEsSalI" c{[jxIFWZf+`6aH+@cG4-54hMhZ.|OtQwԺJ`o|%{Ğ2L_'"_&(/ٮGs<,"6LG,t  *UM7 G|/R$_ H`q.` قڊ: N[n^l]Xk?L>dG_M>~Bjxoо"fń:ZLжP_>6\C@8g)1h @^́O؋T-;v_iAkd3q@gz#/$8j `y%.&qhooÕk^Z3(+J¾hGԨ()K\]kN@$PT8%Ar]מtk׌[TN9nGks~.Ahx(jd1[ବj,W|7%SĔ)W/0#!9='Z0]zoU < =عj69YձqXr*툹- #4I #+&~{L @cl]-F&fA X;r~;N 1*3]hoܧf;'==iȗ Ip| qe6ڰT}vxh=Ύv=yC҄|ܹ΀駸>< <9 n,0$ƍR@a0L@9Y&݌kۋ >`{)CR~P!u` ;bw~\Ÿ{Gב\Bԛ] Oc?ɷ0d=_oIB*3"c)pHHlB3ՈH[l>"ՙiaM?*y.h3@7?ss#p W".P*{qƺZD"2<rGhѠ  uk?rEzf]0VAS0ϦGip#ŸQ9 T?7%S"¢_߃Yp؀y$^.0Z[}enXq"f#yc$]/i29^!`+‘> Y9{u`{Ńcキx(R ;|PA$Y[O"w)`dm>!7਎ج0Ua^|SVɀ"~.y&m8,5+s"2I˴i@s9'с`9MLŊ<ÊyM{ۈon.5WiM1%Ϡ0DRݬ5tgAJO?bӈ'vxh?JeHb׵]RoXOSAR| -0aM?uϬO_w?S9kjBFlΟ06K =_9HAdz{N|_a-._÷VYk&ܹpo$CfMyҖx^_rrMWη +M:>߹I(.i%c/9%dWԟfӟzd*2NT|jV"gJ7bl\7:Tצ22n̯/b*kYNc2q+`Zp,Gf.!s@QĤ 2<29Oyं'œY3[d󓀉m'Tdh%+Z,\,ɗO&"exFcКs@7/Sc'ɺP3~94OUM_8#VGB9T|g3J m 8Zc Ǟߋ%w2 d1lI"`r(m@+S #ɽ5z&]!UE-Gہ0j.¬k\a~K`==S_ Y@GզpM;$f0X1nxwEv grxOTmFDL5_Ue0Xȣ%]k`>V {+iɥ(k@*-x2kY>w4wk K 5B.a;0pCU"V$L\ TY/v! L8sֻJe꓉/K-MQ^5I)? P9䦅O[ӆ_t62QJ4ƥFm耻$ώWi Kw{s\-v"_$׭dG#QQhID,5һz"*nێ^cG罒m{?p?%ң)H4-a\ke+ 87_ax $ GסdI&(T[_*:|p~$ID<3j3ܨ*Ec!*U֯Yz;L|!w|'_ b90t Q}7yd _GC٣A}Ekgr_w[1Dڹn1mH߼H5 ,g{U#r]~UB C&bdj"&'Iq0 @5g@ƽv,2uS F~N%33+?:P_ڊޜ;+!#ِ(I׻pjE&\t#_K&^D(*ShUL~+O 3RȔ $aV9jEHcZݲ2| iA,lY ?H$Ynu\`( _j_ji4wzg/Ӹz:FĕDcԊl.r#(gQ\Y^ LIPd&x{!r]dc>Ĕ]\B#Q7jhW?'VV:$RQb_s|UI[oאp[?> t"hh%񵄿'N8ҹ!h cAP9KevT%`-oǼ9@EଥAGH}~<+"1AIܮW^Q1ڪ{It@eZ"혵 <̉TB5wH7U ,Ie+tZ9䔌o!I]ES{|1Ix:Y SaPe |Ca{}%>l:;tԄVw]8e˒΍dgh$< _\~Sj ;[ebΚUs6(=c- t8 x̶hIq˗D5TMIOE0`jK}31#KnS_-H@,r)}+ihsr. CoGQ9"T%f j@,4!x{yL$8rUeu}y4 ;96a1t p.G}+)18w<%dYH+%X6 L{0ٖ;*$tlP$lm %EO@{1Z9k]•ciAx#wn{2k<-;QY3Xmě3eH!~xlֶz KcH߁=V8ˠ wxHp̍0,LW@C]vJ>$a ڥ&2,Z.w<s._˔~Shp93Q{ٛ~$Љԡ'v-IXp9zNf_To G ŬlMB,t>Q"jz/%'M{Gv;:@֩ސ41¦zXuh/ P@"3tt<)䎯{Va_Yܧ{"}x释 vO"w ZU%L0(OGe~mzDUZ5`1osblCo[DpYd:27n_*Q /]L _x`e2Z(RoGB~݄㸊:oƆ:N>yiNAhT9d*hcsY33^TL.I~I|?|`8+ )Bۡ/BNwGWoHLH@b2tmLҜM@8Ƒ~|\]$E0nLYiQ\e0jmV+L OӆR!J{546!RHTlےP>i;b4Vs\uj1{6Xd# W&(P"`p 0RY;ކRx#a;+$|8i<&¤mIۀ@0p!1֤yI#C @ "Ӷ` $ {p$aKA(n}R73Z\2KM@.6љ58ǝ|Ra|(SpȧT.h <$z wM$_HEP@JZG#8{4[]=< 1<ȝ`4j`;Z;IbH.jcl c:pS8x! 5Hm|)8چn] N'pXln?A{R} ~N˸+K'T*ڶiCƓhZ+'X8^Can3rڶݳ [Q(=5l08ヌ!ԋ+q\NF:T,m5/(𵞵C!sBw,<)7C!;@'Aڛ鬺ÍK${q|ѷc@_SJo0< n(s-Zu<|ҔSUiHUĔĕ!66Bv"释. ~ďF{o FF,f&֘X߀d$;b)fUaFxoW{ShnmZrn ME@ӫ_O"5(ĭ4k"wF?Cu%'. 9A݅_EU+`qk\뮆p0쀃y/C%c IHbن 3ڏ~, 8R xr}s+('?@BF,8i9unI'.\ &~98.[؁ ń_Pn,sfm;ajD"Z_܅ayj9f#E宍~׀Us6d;9e.[K#r6V1Ob?1JUomL,3>BGU3~1cW Ϗj6H xMKR#mmCKa)g^qrQRr0.# 3Ś8#Ԑ7ؚ8#,F907beVŊ N~=<\Ԭ ظeWxd`IT-*'EeM{&.*o';́3@Пj Eu-*R~e~&!#_am.X/"nB*~3 0$fx%l3˔v^yx{k^&gcңh)4` ^yKN FM`Za4!H=OL#8m |]VFų78) :Ѳ) #r  YvTa8+;p{=ѷ棾J: 8D J*=O.k{߱cDŽa=^+G$%anp\$_"S~h)xD| mJ̗*"~k|2vT) 3TצQwaX&ScxRyz}{@DtpjӒZ0MDT,;|Mb//-R⏓yq`%]+<̾.W2yOQD *~?S&<:"Hj<'i{9O* *409^@%-3t ,Ii(e‧ҹsG@zT!. MKE𴡐 Ba1ھ;z޺Vsj zϡ a>iU=$FrL)i5vڽVVL*P^П* mm"P|e jm-旜\5#ߓBIj9Zqˍ?M5nw#V߀_Yuqhg`HEB3(BHQ,RZ_hT-𢖾ścc;zbVFX @JG186LCFm`ƺ{1S'ɗ/#v=xc{?B~ 0C&Ke՜ W n 1.  R fD*yKe.=z%!^#J-mjjFGeD%OF;oW"l4_'⍍#+WPRE_cDV|q=4pH BP,JAa_-,03H,a֚MKXOҦK;W8rL0&l $CEݓeeE\" L(5נZZMȈTr[ʌp#p [C$<<*0^Z_~,)͘FnaT7W-S'1GOTPpa,kh"AüL`㰴|{KNnO0.{~%`] n%Op 1JS:Zfx}}oMÚnlp3-0M?Tfi(=I†;|߮IkMDc;Y6_Q ;xb]wJVta6;\X5gCw>olY7[vx@o%GB aXzO>mG>Z,k~ۀȎյtQDж!sR!OG\36ы2D-%'v@&cX0%a,D м=S] +_ޝ|R$孢0 ttu>w4W,mJ67s[7Y-QjZ"!#V;QϷ 5=&?'=/[`EWDž7,IcB2^6;Z&d.t  JDr&F˂fƩO)q=A6K[[+X?䤛5y oR0:Yc>Tv$Ù6(jik k9ፄE"ї#O:\'ː]yA92;[НsABFZ.!-U\bZT 1- 9[% FQ( 3̑E'}+{Pґp ʵl$UF$>ΕE][RH !J-g̛MøHP|K.2Qa)l}!]Z{O;彻A9 Z1Ⱦqj#u,Ep9qx3 xŎ0V pV&KMlPٶ>wY᦭_G=gLd?p ^.$b^9q+<Cc2o9k =>0۵ MRsu3)8CnxWu?1n6/~Hӵ:e%؅ZփL^5g=Wwc/[/99 bgܛBqi=uxr=%,| w<ֺ{ _ ])?=ХL{FC0hxj/7>l -bԇdJ9-}/DLx_í7pNB#/5?FjM1سlg <2QSh6m.xttzYp|&k-y;w|st˼ &v6XTaqۣؔgdق J=_8/SΙ07AY o!tgc4"< J0{Woב AX}xg{9$ez 6ֆ;彼t?t7n~=:0-okJf.NqV1E@:X\&k٣M֎YVN^ja@j.R5m]Y̶׷cآY^ߕo61͐R #\- DEФxt<"!/+@fa.@itFs>>yXSDR>rm)*) lYcUκ9kf<P.ٝWjf]cG$Ykv{zȝ;J '0C oB݂ㅑ} w|CUa)yM%J;$]\5WzZ\BAΆ> Ims_/oL? f/Xa!M !g{]𙚋 $_',۩?ommo=|/Vb[:3B|Y[ ;f2+^O_tހd__~nz)wkWxѿ嵛ݕ]g]8@\ĥ$ o3i`?{R6f$  oQ| w3$Ϗ$Z:"w("w("i1L/m5W1֞^mq<%~/ S8&_]2/\>ȷ%^9Ep|giӧw6/G_XGbF+r#yu\cXaH4&vk3@N@.4J.܏{\1@|0eI桎[ ^x3^Z<ݲ9$>.QL*x ڡ{!3Fl79_^/So>*\C\BФ9Ŧ'FB9|k.\`ϲ/,_[D*ېmo=Çߚ\ٿoE"es[d`CS7)2oWLԈ߼U﹞\SRӅ2E>e;a˓C0 ;{X"u#ޚ_rr?Y\ W_QI}ĵr#EuȈo7Cy1k =f|Bٞ(&7׋brd`9:>.NQonm_'_r-wjB}Ɍp+k8[Z|DsE;&YO wf(p@|H~L?PgԚDpƺx;\`/ychճ@ ؝cKRYk>ZwOGPU}>`a{ SҰ1g 4~ mH"&L9A;o/ Ѩ$14An*9|BڈV:7 ޳lglV|Pzm'lv;,F3˥MjI q\Ҭwgkִezܬ !us։TaMڮs9~8C܁:­e7G7tKX/ɊI/i(q,Cؕsm=v ܵ7&Wqth5hnwJ3\NT6{;r{[/u3oe{Z~5v9Z(*!2_C8?)^'gȇ@T͵ԯAUK͹}J7vlD* jdAh ncoтN#M.)|W6A^+,H,N@wnKزnL{X @_R@o^e3b>;f7DV~Сػr72pg}\Cs[6]Xc5vxs>% .t گ/Ow' x$_8,-O_܎0vBR7ˢ"i4ViY{xG 6x~̶:ҡ_ȬX^!Djo~>T~ p2T^A`̫ a"߲:-"C`_ vG %+}zޕ E0X]d ),l/#u#\D }S)"I* DYA1 6Yj.>lz<[Ņ1-yWzP{ڨ|u:!- < <|*& js#\ZE^P*l0OkgY~YvaP&0nAJFͳH LG~u["QTT0w#`EA |}JNi*Ȍ0$@!S7>Q(cwÓZPt-ܯg30M6_9Ǟb*n|AW:}R*i/|b;_!'6𷙀:ldbklC [6[;@fyRDC ڡB Kʟ?lղlнeNjūH@Rf9^1®f*(nwV WHZ[, Rt}m}u%΍ߜ53}7d0T$Nr My6L틶NqJp<$X[:V/G* 'tW5}[i)Ծ͸XDjf IBn|uz֑˰vh?ɶ68"1Z@nn)4]'Nj9'-LZh@=oqm㖨@7vd_ L;p@r^S85 է =`upr83 S&,OspGeBL< 7B&ƚ24pdN @BN4ysȲ sΨkq>XŌPAh)2$VvNi la(lmv  c5Xpe|O(3SU혋IL7$ sǐZP6ۀee߻s"B<0[Rmc˦sn]syWNA PN߯WXgEכGvhr՜ ZW~Ѹߧ}@>hPЄt@5H޵C歷C3Q(ȇVx[//&Yu nЯs};c[M L6///# S5! N)xΚs!= g|gV,긴ťH[\ڥR5 ѽjgWH.'Ǩ>tht[Znpy 2uTy);mn¹N=j IgAHr OػrDD&Uo:uEJH2GbT0\rsnI L$O/=ut(H鐊Yx}mAY4V:ɥE=lHڳ?}]:bn1.~'c^+š7#X5TvDh{}~.5sKűӤ$_ԆA06a`W]Qt-Fj 2㯳x%{ @g_-jcf~xA,dm>Bp|)0H/c=j4rn gs=J='BM5f/̃|c]|[׸aĕ85 N: GXynTǺ/b-fC?9#Ȥe=mq)ί8%b VF2k5T?Kz+#$gNV mN7u̹n0`"CaR1Z;rrKy<l)ylW/:c9EN51t+C}uq"~ wL4m.~$NԽm쇋K ALĎ0d4}J{'/99Yjط0ǁ@;WInHO?Cvu;kkD*p7ǟp= Ls;>!:mfHyכfA6./D:2'z%;]:|VPR+^M)m&=e~|`Zb9D&Pig%tx ڬ'2ճ |f삹sGpJ=(+tKO[9=G^amBnăhxAAW];,v:KC VdޥHp K W(qV8cEGb`U8. z6b$TC8.={ܑ ώnԶϙ_{&ȗ- /ضR v% 4Upu)epH>R_@rj!Bߘ0?e X`$UΒB(4`h}1)?2&S.Dyhϗz@:;>C& --v6m@X"V3儕z@|s|?O ``m(EU d;/`F.8i0q·q@tҪe['2A2- |cﻨ-%0!{/)] }Y[Kg+Ѵ^RPӑjwnaJM-SZq5N&;MXʹ_u_&3֓GVFO1f2i~lu;遗ܽﻀ>Hb=TcuEDJ@2W g,p7qL`#DM3-_ T n+:{%=@9#2\0 pW+PEBkK-6ڎډ&ǨIH9aB,"6-6=wxi#BW i,ǪPvt^x2#`ݘt@ !̹+ =s}'D硵vN>g@Fnvcސ7I믠`Β8F~Co{T-.8nW !spj#hK vy@ۙI(݊gfb#^Ld}N}JV8@q@:NHoIJ4GE({]_:m\#!_Ob UŀYf-Kv,G}h{g\`9&Is0R&ԆK0_ҶLJq"wUMF1䷾I`囤 w@KW!tΩ ௜RK1 sB-u1GfYL@x\"d=M4אZ ;:cFt.vmd0rШ% JCN#4 3"~̶}IĊ'Ki )K(*h,X=)Q_osn*("vev?C @K'=!ͮ!8츀S$^Zu Q70ز`.$^}l> ybT$_*-C?1C AV+ U!vA׹C6jrfT +| ;>E7]gN^6c…wЫk1= in~ұ۩sp GDE֠G{ ArKl zXK'LX,XۧE']Va ޣ_qX pvxRO(k_#\m=YYq=96/ 73^ H]G#רC2j]ȧ+3J{1)V2_މB)Y*ݺ5nG iCN1Ip yr]kAR@8TB !{=Pz}s1Txx!{LU#ǨE؏4 KDj>"d&RȎut_,/.LNYUg7CAg $^3(= 9?dU B}7,(^5gRp'| H8,#\3|:tyb2MLfs+.0@y w ɕxeo5rC6C'p1##`jK*a|Ϣܿ,EdQ$OjN̺}Αp OX6/H\,eۘon.~h\*FX(UA\װژAgolYSjgVl~F&Zr/s.$ -/_K8]*uC| c/N8%g f>3;&ե2+l=DĪ't]=M \: Rh՜ 's E ֵB)`p.xEe0Iکτ6mR@\5I#,fSLUḊx)M٦v&pjkrPG)a'B(˔ K2'sž/DEF" gجEѩhhdexǼkd&y>_wir-38v.~a`(u >GPv'=DH,khj{J(4q0+tGw&ԕ;wB^J|+k_[pЂ ~[GxhrkcL|Z I8sb*_;0_XKh0~]m8+rΐ;HG bM[ 7RWN qqN&rI!1)֦<1/S׃~ׇ@Us6<`CGH >p_&tgїHy?Qwr'KQC]0–=='pab~a˒j/1:Z|NMVal߷-a='?{T%C^뢰Wֶ!x 3>Kqo!` }VBFv>۳l60B&Hۧ?%b?lg^{Ôtk[ӻplt\zN_s^FI|1 M9~Q0KN{|MaSbQs%MD' NN`˒)`רՀ0ڶY3H~Dג0~ױ ={$HlH#ÑM=~W?9(蝐OPៃ'l3zS)_?l8jŏزuz/};@@YxѴ[glb~5䎯U$H%Gn%;-Mts̼9f'|j%/ ֿ );Qޡ@< LM,мxC[m3Vx;^p=cn?m;O}P&;y-&1Wa$8BϦz!>狭ʸ7BhB~)PYY[7$of#2IK@cOoF}n( `Khuǟ)v=fIxƬNSX5gJkL.p?ز@w֐1*sS?QTB6u+o *%'3cX A]7گ|t _{ֻ&`"1ޚf抮 0jh2U2n6e?I֚aIR-zߔg\v}T'Ƕ ]:"UUK7^3tfb5q \U\Sl:.Ɩ]E.iG7/99vm6Tozq#wo6!ǏZOOe7p aHDD(aGS V5@yoF9.A#䡪OUR25#-qX8($/93A$َ[ 6 q>gvϬm[vEydqvVr(ke_=%P&Z_sOaMz W_Do .{OatAcƈbH1PלaSe ּL8Dt*EK'pVgqtŏ^5qo}M߷BQ\ʃ|K,-ڸCUWyI̓ƊdrIdku9"b#&]:jZ'B$R{{OFTRGoO [D,9 >s6h[o#b"ШmCe]Ƹv˞K5=~0<\jl+ }d|㰴%'}!@NUI^   '!`(uEBt*[,ّ- gz:\K5 huC2^f_|Vڇk.!MK @ (x洘T(m'*!V穸AmQ,;jcg "C3#P6/TJzP 6,ߔg˔o7,H/S2苕^(Zvх w8c`c s:ȑ:(~߮7Co@XpA &bw&R@A>eJ$If%rigQ;"b-N8T@&JaBb ;[SwӋL;X"@4FEƁŰ统gG*Sm9,ް4$[|kAPg"^D*g5,؄< ֯"VY _~x*Y?OUׁ ʩXct"~?])߹|ey|MyFB1|g1ixȗ/$"T4L+t:?|= t=# _f^^O ˰ V;; r!%-tWeXuYoR& 2 wd(4=yvtbǸu ʊq~HG$ѳ{k됡P@>f#g(_T5k^)[!<^k/[$-V7ctbԭC:OmQr: Jiu綯D[J?orցG䐑})D]}c#Py3hrt19~tq]UJ>Pj!$glXТ fZF-HT I赝1h:1lP_DE8@&C"bd'~Fu`˽iŴߺRuْT D 8%;K=AB|?wwp4,kN1Сv:pp? B+lULC=C! `ttHjh;8~a%Ae=Y&,!W z-eh>-9a@5{GIa ^@-Nܧ I5)ۡaMG[RHR܆f7IB1핂7,)a;pvT,"tF˔{;o I 6[ mjED>q o'@6pǼt۾xx{RO(4?C|0Kx֍Hn0M૆n7WlcbR+*_}3NC/Fޫd~>@bncjM V^ vs{KKlp%J5UHT{`8.đ\6l)mIţc౞5q]@ɥkkB8D76a@0}cFj2󚗩ʺF4jYc<0x6s”KnX5g_{G lw{^n}&yLqU&}o; PUs"_W\ɓn>}=|D^("_.ARM;=W?a5oW  =JKzZ~v1@IAo@Kpb%vwv@ȮbY7{t]Y5>)rU/^EO͓J7,d NEGIw@. !& 1îAnǶ덨G}jQ~9|Bx473eHDf?PB:`Q0L@*RԬ85yA :Bໟv]3vJ;o^A:d٩ X૏!+OjA/!p" '"ЛIk;OksЇ$a$ H $QCV\.oi&G/a0 Vb@X0;Q[u$ʇ˦;0X9j˔wmu!iuEMytMczYuI0^z"('APM4tnMߗcz}Jןȩ=ۮxgv>>˟S`o(:mcp< ]ku|$dsq/͐C-82_TyQn[Npe<vF"!&2n" $Wi?~h[rb*xRȿ[PS߈?ߏKen鿍߯Aѥ2x:p-{9) ?hhՋ6}jbWmڋX-rWvĖ6/=G ICTϮX8%y\"&׭*D`(hT9?| ~㘀9W) h8>%H gNALx/ UB &,IP,WSp:iжӒp:_^M^U-tUr/|9HS\T a y&G ԼgkUQ6{$gG/ew޽le3ʼn}Pq>A{Χ!3?@u`3?xry]2Kxm\Ro6mpI¾ТOeB"#ՕCS\E!o΂7*<oCѦtmiʦZwT:Z "#J[~($% /4P<'x]@v 2M'~9|wM`W @o@*~} /.՗ʹKi7Fqy9(4/kD#_ccd4x{(wҁq5Zk>tގٲd".r i49O\,p-=o˦=M$>0hyzE[*5g$,bs%g0^"k KM"pwцN򵝽H×u^@ MyF.m2Mѿ~;Ed餖K`.*aͱ)Ϩ)x:Go}iWއTAJ/3as7-E+w6mK Æ6 y--={tEYN0Yc0f\, Gzm oިmX$DlSٰ(Ar5%29,& NWhnn=!d^δΠ1`If@jؕbg+wqSWm֙/Cu_ڭ;>dɠǭ`KKNjC4R ~!B^E{앴 2>F0">_>< 9+Jaqʆn/\[ޕ{f#Br:ȕ疉:i6GnAj8&"QQ  :=% jW0ֆ:Z=Mi2to~mcV]dt|Pw.m:or $ VP䫚L~~s{WV2WSrQzޕ+w+]cGlFKv\ma"|  ռ_䫩ECs 6PŃPb#Ô|Σ +>;W|MxBσ'48"Udu<{N2g!x`~T~""w-ޕ{ބ>灶~K xޕ{=l/fY~3@gr%@dc إW?̩n͝f xq2Í>!p(g p-Whеh⑿,6 Wn0 U7Ob%M'_1&dـ)89^*NIz%ޗ6 zv#8~KnHAB?۟2M~_4R*uH[\)z dqr뽰O: <6k[ EXPfr:q!!: V \*B&  ̿}/@#uD=58[^~ Gr" s.HDэN$@ \(Ȭ5FP^P^~( YTuA䲵5;}l*4\L;'9f #_rDfm#\}h:0@th)/sL{iEM?rםhkҦ>,UR<Lۃ۶9md&Ȝ3KPYAgf= 45j44{'%hpB }|DKvk3[16xiER Hpl>[ho {LJwt |A 㺙d̴}-/.pg^|"Sּh97!kOn z6eGIŎ|m>+mZs{RGGlFH?_I2<@n۴ Xo{W+(:٣mBN>a4[+ڡwx0[ә U,%bQ/V-#9QF<$)||َKx^-/k :B87o1a4gX&vp~2MokM}#sË( fdwzXY|C/4yysa՜ &&\Q ф Nx8*%RbY -Fѿ/̎9ز@w Hs9L 8  @lػrǖMgy ?F++Ws{2PK R$ܮ`&Xu&ٚzufY)ʐՆZ ]+TA;6 N=ny iC%+W';ybj]d,YLJP6zL0IڐEE>Q6I= ·s?si d):{`TB4Í=Aꑈ)Q  OXyWX']A|'/@&_Ic?x:D s&jl}s6;7,X1 @I̶ N({ KOcxұk1H?dq =0q&C3ݝV3.xdlpژT|Ԝ4!4pB|$]QslVfs]B:3hSԀD,B2"(C7;v?%~ Gjxą?MsW;j-9ED̒rIB&[MHsyX=- f9yDL歛es6 _k':yZLM[GgF ^\%/rrׂwڍO;cRµM+ANmÍ"MAh/sn&alm,MoBBqֻ4C5'/@J^7rOUEU=)No?[[Icxg4t˂ mW౑Lg,.eJ”-;1]A;ӏDBN/7) s9i v,`$ۦ2xb/9}㰴.^o@nҳkY*"Y!|*p|7?!+k":;$E +;6@*""T%gt89溇 / /6.$&KrgqO ƶ^ŤA׊;7#M&؟<(7<Ļu=8l24u_@H\ dùDc~}nj6^#bt&zM־o/aү-׮\wҘސe$*alolYh՜ m7jn&"A}t9טKe7NT~h3ѮFP஠EE nb@ѥ|B켇Zp0,.1Jv\m*ʸoVF@݂1Vˉ_3'M4ߚSx]S{~=zDA PzD*dƵkse_KߎvaRדq>`O`#Aѭ -~Df捻PqD(|0͏`93vIPجte>c:DpQozjxbvLfW|A{{{[5 \[7q#13{$̵Bǘ%9 ?'9Ɲxu>t7&@Aū0@}{qI8{7L2bbl=|nlCucjPTci\fXe@3sL|Q-;/]?2='0."Hp|'ƭ~V"=wuK.u~KKP]ڔ}$`pjl|x?*q?\.4~^+{S8Q-?c'eo"r 6;z}{Ϭ4:IUIC Syx2Tnoa!i}P`D*^cŋQGjr 6r?^jܘpPq {c4>]\o|TSaVvltΕ N0Og0`I†vt%4|}R˄_\3kٮ#\#!nu^K iX#g/`qC [fI#fσ)V op@  hK+;[<^[ wMmD,,>${\ 85X*[-"UJXKŽwDȲ_$Ρ8|0J}</eմm ҆}/_DEX_+ΠzX υ3yǏ{0G#OY~{@0o}B qJXVn&% ַu|*KTAX6 Ol`+vsn&B.o>KY|-lY;¹!X]]c/\1JL\v~[s [8ra ݲYC{KOܹ>ZiRVȳ\82 ϐM K3BƢq +5ݕrݲN"<徘;>%۷cman0/@~Y'g,Z Ϥ?[08[c⌱!pj҈٢HCW[F6ӴʱRwӾym4U{쉞2 y`eşHe5t(ѵSO@Jz<}bЭ݂nOЈ;,1x!WςNn ^ ^?u;!60TyQ'R sɆ6c˨$_OLYL5A]'3TóTb[Vvػ)i˺)"IE/Fcwmcw}ƢL [G8&v ؇N|t& /n學/BlW%µHZR ~0qrq.GuoB;w'" \=B{KRMum6w &H(J%$Z5kfN?5gϳ[VO얱,m xQ'¾-kRVx Xp!O6seyPųIC)u0iyhX[fT0 ^*M9&nq@?HhE.cߦ"Ȉ.3 BUUMDhXȗyh=^钜;n4syΚ)@iM*_%1d񘝍 Yf^HW4?e5/'zyf@U`z{>Ď\'8knHx7/RwЪ XT E@oH - ZќCYwnW9d޺Fb g솊(ͽ t4Y4KZyM0Zv`I7ۍd{(8=n f&l:@k4'h}no >k{Ēn =c5}qh}=AW(_Wf,Z$Vk@쯇D"?(rL1;ƔAJ]0YX24LU$twd?%1Ysa|5՟F`^xH|Մ"4I>1M֣o-ǹ# 4)4TM/ !DPp!Mo2L~]\U4^S{Jַi@o\F}ZWW)^LWzyX&E^J'z1J$/OI7K2:Rx5M R p\I#f'Uh,̒՚:x(XDDsͺVXڊPk ?̰xq9`!kqԚEӼ S,>_@PE T/G?,g'@y-VJχCA0R|ȧ4m y1O,aSz^V<% ~JzѡjJطVfb׷ik]5~=_pq~$a[}s"kEa'_.D|U[8ת|҂{h\t <_}(b5Y OB^y+GR?*$ug_(z 6`p#X&iԥ+h5@F"GX% *(S X|ڐ̻҄ԚMJ"Z4e񀚵X^=aW[V?{M?oO̞Km Vc+ckP|Km^:4]|' v]ŭj{AK͈H? zw}~S#4bvRFpI8I` + ŭRBRU:00O l`Fn=ii&{3i|_Fб^嫲Ɓjl\ 3oޗ݂ ֮nybRo^,DhHx1BB74ufvx$ [Qz^@/|[6}Yb?ʷn,j:]z^q ЬyF}!yhq z*re-|zsAJs˲LfFzy᫭mŬ1?Si1\@oAyn}]dߋH[U8QPk[Ә` @ pw&E/*2[sPEJZ[:Kq;K1fv٪1+qAG͙qɽqOOko,wUdk'=sG?C#J/"rXz#ѮIX\݂49yAb4x!yo -pѮw5&YUB~{MIT#B.I(Tp cU ʇ>ɮtQrᡖ2.>xI- VYozq7b' r9i% hy{fЗA_کSedNu:6~wAGd0ɘWZQ[g/rbH$@UJ<8U<<<;gh־$Ҳ:gF A{S0p1@/)i-[((Fy#叫?bD)\>ī}$@3l5xKȇh0I?"CcͰ Me5ALݜm͋ ڵ0<}?n4KV-mmw;z$\\(/#M<\&(+7ctAn;oCHwaxȽJ/@inN_xFF,B΀{YYFP+!k6;΃]lߗlO+7zO܂MC}c-hxϬmixf yUV޴${1wܬ0T0$3кF34Y x"ú@%sE=f]fpTFn+뎀ѭnz<"?SeJqN_J^25e!O胿k,BR>`x)ڮB* C%\Z3H BcNĨKNin+d} ]iC@E#պ/^+*nٜs;5yBY- ˇĔ3d,Z'Y 9e匼Ey5e:UՇ@,O8}im&}z .^l޷뛚A8)Bф;}}k?.h4y _A1Y Ԁ\]6S1/"ۮА]݂Z\; > 7]݂hTUD2W?,MdLHH Lv`WTzIIQIv2Va1K3,4`<@bP B*X@g{`-4Liѿg8>Zpz)R^/!ՕPkzZ?R{z=DC}aK*b[%}>JZDFEfD(pGx DAxH]'Cu(CBBHY9# fAnYnY`Ӵ5 g \?4% ߌG7Axā;3q Pq@k;4Z ]YkwYh-ؔg$ IOjo7J$?]g7E1M؝!Xz y8hֵn(nad$X-sAY+ b+3eܢ*"_,0+q!Ifʯ4BlW};rYhƐ+dZ!,d \ hٍ g\]_4*i{&oBuv^f7OY=?dn i ?o ,}Px $mWٙ\,JH -hg cԃ"1*~ ZQmҜ)104dq 6_oeqW7ɏM^DJ2;g׉V`wwĒ_v(J>,w F w T=]?8T<X,kv)2'kiKώ/yDk#\kͥIBt$Q qc{AܲyWŖmf|UMzl*dZTF&ֱFkL!Ys+ʮʯ 5`ք;HM@DZ(salEWP\?Pso/j+\3 K2JD,ɘok 7CZ̶r,X+s`7{3WRg#37lL)vЮiXwh[{Gу^" 9~s1(N%Af3)(++CHHd h⯂!@gtJ"s]oٳXD!XJR6;rYt]Xa6ioGL'xˡ=r>V$/1}Nf[IanM~Com:[#̹j=\ࠖ"lVI&qv#Yq0m Zf.n΄@}b{r7O?u{lLgR)dҵG>f`gTrpl tMfQsy{0 d;%SŤihy_b0Q߉yJj?btiEO/FV4U-s^o-=^$G'V|9 ^Ɉ2ЏwC\k:/ UHx ')JR])\wAbh5;gqZ|f_,45k$ZT2nx@4Ič<6uIr2d,Z +!ҋ(hLY9#ֵ}¡*`(V.5o`c ~; ;jG#zi/n&PR)S4S(E1樘l(a0>?)i).D[Q"0O]1a_MmUʲE.M_t,u)Uk5f܍4vayJ%s`-I=_>s)1[Avd ؄#UHv*,[V3_Tg# BCAG[@z&n랂kUlՖʗ^ Hi [JHy*%K\]3Qo}xU%n$,j zx:E-.S|#8(|Hp9Wd7Y_17^ vݢT0N `:Js>N[~%m':-/vY gځCacY$`4ߚogpy,Uv¦uK`-s>ޤ܅h[篧vWw=1!n@Tֻ9_zW;?mA5=r߫([sO2$P &Au(M-.~dρM,`k Y)&kwpθrcq#[rʵe`;:1X Fp0@ TA}YEgm`׭qB%q*.a]^6nȎgCjDEC/R/}1'Aaq [ȞJ8!|~upXd{ww~X #^nFsU NϞ̄yWZ(=U۠Hϥ='@vi۟yBL% , z} 0e3( I xXVXPEs^>sLkz;Bȷ_s{I"߄h2J6BirinE)G~J^rIpZ2uΆ @d]t!APgN0Qv%2uXw̜vQcySo4"Y5C{Fd o::kQc:s AA"_Y|[NX]Up'²AP&y!xg@`VJ/*q߰b1&3nѾp>lMCSH +~+ &^ (=)iE0%5 8]pY5SDܿwO&u񒌹ܹr35Iy0=2MիB. ځCEkl<.MYvBB/4G߮JV4G/yxx|_MH׊ $gΥާzLC[3Ѫ>"ꇟx7f%D+ǎ_v1PH o X>KRJujnn}RY ~OG||<?9U@Nт]3N {AkȜFkm=*49[#b|)BuERlp2HS|N#6#|#\;}{m' /b.bgyr)Ӵ0!]ځC)2 殇X |J<$ZCо|%_j"Qc=zj(F] JKVw4,^sqK#q|$ǘ"c8G?$/}dy~ ڱ _]B̈́3B_g#\37,KЖPo6{dYq%kgOO7򔴥l` uuu mMCmc s'5q\tl_@wAzX+qKs1wT* _z /d=Q] tר(xrc+mU3n] -@ί*RDoQЪjf/6ޕʼn,zRA|Ɔmmmý<= /|B%sS'xީЧ֎+.Aw f]Ro k_nCɖ|@ɖ|{^{o\K—S 0>{. |1zE⫲tA^YGKˁzIZppuy"^3w"wvy ;N+dz3$ u,nK\=8 ?2ҡ(o!'U='.7#z+,χ Zˤ4ߺ:iӵB*?W"GVEו >5՜Ŭ|my o_oC6ӓ afg,iqc'߻c`zءk/~m.\ط$N-~3'C 캱x/ޛi?}I^:+ Ws|b[IeT!K캕ԣqZ[=->0pnsˏb7?f<"5+-˄D$|iU۰{lFGc3Hj=Oqe4]ESWALX&g!@h-Oƒ[z M̓W17r{bC8+qqWL?76_ho7஘~tjW@ Ǻv௮u1Ejݨ ĕMS#o;-IkT,d2oǂ܉!@OjrŢ IGɧ`g,M }kAc~xgc)g!8Ti70P~^{Ȃ|<|<xTtb*.] |?{.h>8kE^{s.^IPHstvUjmD؅w):9-[+׀ mz۩7=䑥a+ ]`ϧǰcC]Ѩm }fn0t {~d@+s bVLo|YcGf-n]H3`ŅɧOiHDPc( ^ڋҒ6V֮^[ cqsn / &|\›r4Uny|:wSs#ĕ3g|",/bԶ3@<7P Q#D<s{Ҫ YJ\9 5WKsˈy.gjB7?ㆩ_φ@3w%#aϑ%aڌgnzQ:]+tTЎ`NBPYV@"OҶA c:G7#Wܲ aI߭`7^om3R$ i L?t˓h 1;#&. =CAf_;R: vҬN U|mb8)c58FFtKgXQ|[y2F}. o1v/zӢdOй؄ 502=wkovY7AFcX8` eja {pydq" `Ƚd.m4]|O׽nfA!m-߫շE!$=MBK"Pmu^a4G@`PP9Ml!{TQkq z=(w~ue @ &0ŀϧ[qO -=y+ob}kurs3܇/^3u3/-֕}\?R1XQ[ktRN1]qb  ߄:Pn @wah ^Aol=f _#C~:Lfq58! b$0wv{@ VT.-xJq5[>R7~8?EO/3J p3X>&pM|n!jw\@?"/-wqžkr 6Ԁ_wul:ܼTr_*ŏ/u7w4Wr洜${*3`Ԑ1q8s oyqU/q4 yjJ$>~XwM>R)CaH=u=) x5HQ76_M~\T̙z%R ܭ4߸EP8hq X'B咲ě9XVux$sO^:xw LvEh-YȄ }[ @M>P>e apvLJ %>zOww׫Σ ߻+GC[[ Qd~`׭y|s-uk5|n!7c.gG[+ϊ&6AIO]w*аuv^WL%N.0jqe;+ tfmo/Os'&ܲGҧ S-LVK=qȋizYNvCExYu-TE uޘ<^Ȩh45`i2TU/~ՋoמWcKBq[[0tb:o ]9N6arm+\]]YP"ٙwqU ܨ[~ry:o#'WHEt҄W֍bI0ɚ"_Mm45U"5ȨhikQSUnz>p$Blx5 Nvv3* jϕL.ݼVpְ"7@@_E |k"xob9cbhj/`l6vI|(Dp;>.#k>YShxet20]TZk҂5A!ܲN"T4U Y^({Wz@ɞ&!7WXs<#Y{{Q+}:bnLpg\(䏌xw?ٌ uZ*-"Qx4z bMG4EI]}]K3Ufj J?<8޻*޻fl pץf0Y}*_˞]{3`z&Gx,l+܏mru4n5"&ݢ?ՙiIs P3Rה: ׊c5AG;@_M聭gv)4X/Yt-M4`=,~^FJs˂#TZZ]U|<<=pQѸQZnalm"z&{m *s'_l+% maMm4/4N gx˩*_^4̓wWK͢hIQǙ/^h2]PubQ- uCEBmLAǟfvs@Hu7nNp楊TkAfIf?`jo9>y_9J$K4ގbH~|f)JT2TH.Fw᳗m.LLk'.kXuz +W˻7Vpg擕6E(<;擕,>>`G@!O#(D2QPC˰2^ 9l֏;ͪ\ciFʏF#H]Vt{a=+:$`Z~N?ݹǰ?#[(kU.箔5*@hm*PALg/C U{f17z)2oEW:?G-}cZ rt_  + Y:uux2 } `'iF'+;zHB3hen)q|\uGo>ӌ('1f0xx2 yzoLGo -O6n zy`,|E7*PDPG+މ}o`7>zm`,k/|̈́>0 $ycϾ;Q STnublC܃6jQ@\~,={?z Om?z\B@^Sdnhյ⩢$#шhsH{ȡ^3!0'bS2;DHVúwVW% źJ\@|Z"r 'l/npKS6--MVq,({G7fxR-U2^С. x2s&`Uӯ?ζ`\vB$_i_T7]vBPcqJZϢLbŁ6谅py,A7Zǿ/(w#;@KL2`gd@{%`g9x92ڟx}|2b %MrWqņ]Tnv"N673aAYo,AnPK;|AWvro Z'HSAWLT$ք4/_u9 &{I&o8 FA%$K212S#`ŘEO#(i;jΆ]G "h_xe=7z?Mn‚B~4B2n|H%`Of}]Y@TPS9:svwp k[=^[fGoVg$`$$s/{I#f;^k>"2~v_ơ x5>n='N<ٮkAOݑ5_YqFeAuD^c|]7L yۼG٠W't(|[+Fp3){azz"RTɵpMzk1s ss2pBoF9\DK16wgTZ9S,:1S|P>ƿ ̛D'HB+cDt"KXv]q)(Œ0s-T!\0Bױw͞ ҔQkC^uƞ<GIo '< $@ O?z#E/pW^C2}e N ̇Ay;˂٨Yeh6Wka>ڂ&'_7A İߊFUleD\9L{ez_$(D9;ޙa"}O;_%Wgvu^*LyܮsS$7ox.f@ `iinXh]'z043Gp]?VLƇ΁ X=c7Zb?ݒA0yx/8^J2f ],TV B@/[9hU[^G_֛ < '#ƷAp @pPrNWw7&3-p#J\GH_}hTeOQ5-7jЅ*c}F 0&D.c 18W'Q1{J,hKXmjEصLPZp&ka;f2M𻎜G !DtQsɗڶ*f{ /ҎG˴x]}MAyNe =0i7)I7<*Pmj8~El^()fj>LW;"OuEd2_V+[e^ZCG5uB59oV1/; ]Sv18yXvBBF}y$Ls4OPGy.,gBo {` eQZ?YC,/yM<ۅ$$j!/$b>xA %E a@*OH )@HBasӷ/K&s?njWr*/cwKL$iLPKmk.. vś}T,G/XL@0h) J*{ƭ[jkn n"P@uS Ÿ\TµwxƏS`dR_)?ofP7[^GڑU`jF[@Uh$ _BT'xx90pC H&t|ڻv#O[^yFscic7&8yny +p cZH3W=r \ɘg+qyBnnk1I|d>b{i)Cۋ]̜EL-vDt"G'ƢI/| R~5Fy5t*m"˩'+*{dY*!5;DBݮ˟\'ʭeh.u2:)[pc'Q%{3څ9 卑P@%lr:b)&SuR-[dOi_ 6#I@|rTjy練ҪGpi4CVs], & >3S-=k%[C׮O>Ǭlk [厚)t' /.] 2a%wgd." ao/OLklÎhXRʱvc zs=T0GXI%_:<J_DKr5^C[IB᯹i,կ=ޥޟmmQ5Rٮ;%r)[p #>v]0$k9L8j%yǮ3Lѷy&/I,w>B;Y72>xNBb+ޑD^(=h N6UKCZτZlO2=;c23[?Ǻ+\ohlІ.U(*8~]b09 _&SYAo.k{Ug)2~I~K\E~#[P @sU5?@~$: |\"yeCтfd.fϾh*MDvurrq{@-aZI--mR I]k k >=Gyk)'b$WW2Cd(],0 SvcJ+ S7f @R\=5A[38+~vl+BD$^F&=OܱNv{Hϔvmn+E\L|n[?k3lG9Z93QP(|X[GQ./1d̕J\HPf1t2{?>_qcCqY2M< …vkަ+ J;k S5oύ!,os5[[x>pyRWXe?a)#s5eͯ(fe 9:B͐(XQК N@n[HIb>j?חkzfmgʳ#n圆}+G)v'LNNkkluy4C;ߎ a!X>@fcs _.ĝAӈ? gYbq4~"& yfY ]؝\ s|SU߆zS(5"aO< ([|/|YWLpylVI Iln Ęstt)7P"b*vN:S;ÌHT$4|gߕ ޥqA}esa [@ttc \du]A/|}I3@ʚ%8Xf^Ey/_HxygȲ8GOxz^046XL2yd\S t͎DQ7e\,3*t!,flM\33ٹ}E۟, / 泝H&3kDs h=d?2B\!YLP@5}*\Å{~2O+;CIJu=Y\c Y|BSAO)('rh<g\x9c@=H߰ "2M(Y ^#\T*?&_JC+~.j׷ei`g9"X#N){gZ4 _ݚfK!wp<23[sBf =x Ț@(5+wtnz.n3ΧAo.@?]2h|j41XwށC6[[&h[`?qx&()m4>r!:47b%GԚ/v!J@ >|cH~W'j$ﭵ-F 5AIm?CZ?:YE&iey_1觻N+P };=pcS3[{(!πV x5v-=́Uobh`7d:o` `klA.k/|z>=@Zs!δIzMb-6uP(}}k ^/FqAE.>47a/>˞(ye3ۑ$3 L-,GkqW77Ҭ/%,] [٤9`LGˤRO531Bns(%=☏M2)|<,$ |[o +FG+M}f1|@Kçdϵ@GjNBpMV=֕.kӈyK~?*9i %`_l_8κ[t!,kr[09FNlD:+2]hQԕjlna/ΡcH$\ta |h + آCPO3gBu kMuQ043pnsW?ɶwޫ ?K!0NsZqFmiн~YrhknpJ_=<,3B?| ɶ߄\^:1{غ|ATct?˞Gk|aIps^$-ONQj<9Tl*ԣΡAq"-`eoJ]Pxu]ٽٕul#2s:f5~J1u i.0Z~3<o?kow6"X ՉWr. wwK33Z 8_0٘bl^P+V:m/93{a2skY`.x [oO\k; kuM+3x9HqC҅Iu9̲KT\i_ϴmwCinYx槓Qܲ"ڤ]N@+hWt*=>5@yH4X{[Eh&CWuQlٓM2k;`"CIP|]lY/ÃbvB nMhkswAj⇜ 4bFuPC$n$L`՟N\n G-(;ܙp5ve̅#> gi?/9ovY6'A72ךU뒓@S _ّkhjzD4M`*aCfcܼ5{̀7YևŇ:8'bbǡuKDu*d̕uLs"7Sw p4Iȧ:[^vJ&{_ K9:% vn.߼ #E_xPة8A\i$9 P,p_{km~GӰ2Lqmyt>#7TTHɲ}OػzCbܼǦ57/n8G_[fB_VX|3 ʣ/>ҙ;bH܃#1lZ5cBEd(D"U;M'~\ Ƀ||$WX12 ;X3Z#Oc{[H kexaQ$x{[ⷲNIwl-Vk%.s2~M[sfϾψ1w/y^[L i &axS`~Wpu E]+č`p|Wk]qY ~S.hۺ=w쟀G;M`hog]3]Y g(Ck/Ӛ6'MySRT;F8P6=tWSSI\@en42goLMs9|{^ 5zfsip#tTK?ߟ3S}IУG$"m4,qinQ[dﺎ捅I߭@#b|0hoG65ĿZ>x?ߍ!yznQf0TVa"XjB5%X/st6K59 ]b)vD8$\@ndѠmFi2$٫齣Ŀz&u 2x9/FmQ 2ue|7@7ɉ/$. 4͹K?(_gUϞw/\#Cn;߹;P{~@x]}Mѯ͛..Sko;(y8.]2yd_ <-dz<<ԶJ֑oad܃jG`? ȵYof1Y[v[V O>߂zAh([/O*mЗY@B*}E_-!,٤q%~ReQ+Lrf>*ӢR~^d*Ӆךgɔu .)i F#5]E3/0tY{~SS{wsjEjϛ@tIJ>Y0.{f߽{D\OvcJA8IGpg7_} o{O&c&.Zt3%z,ӺWj#n=|}}PWW/8פ&SB4:64{i`0q$(d,eӁ\Hmp  Vz)!Whl,]IrwQYa.߭'Yx Wi_=oicrߥr$9{_Sv{ўI1&K *S^'R:ۏ ][^ϳ|emz=`uv|U ~pLN:d*c5~|큦B ]$.+ŘH\Djc= rMjuc= 3֦Q#韤\hO_2b鄯/0{>)櫱Cc'[-mC"ho'I(F睧;MKlBFCkvߺYP0ajKxɗ Ƿ)2Bzj]X~d;_] HXOѩ$({AehoR ĺfs9>PX >^T={Dso?LZ }&qֽL J?!<!s5ۅVk!j|7==}[UvKwf/AsI#fpԼur\2,OI# :~>rǬiuWRc:nGt59ގv1#\Uq m/5‚|]$@T!|ׇԀG0"؀M(2߯zю>p}G 3zH&4ofiqk>Zk\|.GBYF@.WE9Fm1Z،GBY\3D&6'{L6H?,əhnv[Ԃ4@ sT%PKPLΘ>`[h$@0^d,IYT&\$.A>Rd3x͚{6\Ȝ)L ޥ5D+ߘ<xEod>byz._Y%gG}ĝ Vgp!5l#h{µA]n>/)i_[]qף{$l/ZmO ewy8).ErJFW,{1q{e9ẁW'--0#zsDK\ΘX҂7, X|I|IcDMr?i!Vɑ@nCXk;[3 4.][(n3A͕d6|υr:1;}Y0E.2 NPrR DxP$yKI@|c­3[/yC7O4A[Gz<=GG &xēmO@˖LW!2J򢚐cOaSqHl)1l$db|)D0%H&2A1OFFYꌏpk^MX Aߗmtp<'A ETDFwIPBч06/-lx\}#!wfQ5d#y2x((i&xd̽yJZ25>2EY@CcRh8%/%4pL`F!p4}uW]H$j* [Q? k*RX'<+{fߩ֕HrƛQ~2#iqMTO{к]Zb̞Hw SҊv #@Eɵer9EK2Z|u繘S`H_C".Tb#iwD,H \A^fݭ[J3ʦi'\xR#Gp"bkBECeOdهd<􈝨￟{ơa=44G[:[-8؁a=EFۥvZ(Q_ R+9 ]9!=GW4'Aa&:t44X&@D B%sF៮"y$U#2lf£=J, 0kӍmiZ2Wڊ 3]N70_BGm!TdvQMZ[uxP97:(;^[?zY0nE$eJGg52Wjby1ex#:|< xD7R fW JRSK*MBPxy2"Gj/b;KcIp'sZX1|ytM-kh(yl AHN^&3g pu1t2:tI bٷtI •r@{=9du|;^)j_B<')s[}{KQ ҹT4-4܎X8؏&)7Wτ! ^K %W/cU|ޢ>}ݺD6n)qټ|x5^\ e2Kg ڛ<椬h=rF<`_?g\"V RGN`;gyJ+o$R }b݀fxyodw EYK2ҚKUTVܔĜtzIbb0d=tbi|Kqt;=HhD))>X[ ^Qk*z,Y;>^!5ϰt޹c:{P;3"),SՓ_-2|j:eљ#0G|liȮQv u:37s}| pEڦ i #.f⮞/ݽȇna m]/| ; n~ei[r/e?3/$+3( q /"䊪ѭ:(9eO ~.c dQ m@?gW[ rA;=n~S "J\2A/`xyk0i4K-ہqW@ Tep}!\|uz0ĐչFROOIƶ-lF^W04<7S$cE_^:Y)5?g7cʁa̝М\\JOh9\.ETODz|rBԵXu F$xvh4qJ~1z%CvcHs/W۞?v^^3Å/Cis3AZWY=Zcb[CӁ\QDϺE~SAaLX*A1f`qS#.(WDBD?2?s(({GSrAK0{ fr$_ĹZ~8e$zV o?69{@tȬPr֠~vm25(sK׳^W_pb ȪؐIR jxn&2OշcVƢ5~Ƣcu [')g/6av tNFW_@GyW}^kY=*o|]E4x<$A/p;>r %Y$o ocVBш6\P;.+}yMb6yV'oB컬9 ~M"𩃵&#m#uSyYӥF!:92SS*Ӗ,fhrEiK'Tzav0E<lL}2n, } 6_4b-|o"Df|IܔU)+{L< 2emPˡyEݻ8}]K[Ek%7Ew]kqƭaM Vzhf~RE_=rF4,rFjƢKSVH5'vl3R^U洔mD782H[^s_y}:~BL [fnpgu^cx_Yz{$b*$v#Ш7ڝ!ߤ7<]]XSq dؤ7 }  ]Vql&;5ż^ZB|M[㙟L7QM-F~YϤ"/J>_1`0B"-k ,2 5,Kթ.z=&q7@h13.3ѿSS19)탋7Pu\&DD s 6Y܈~ 3]mgDAwS7msn&ɰs!|^_&aO9& mS&qpVgp}xg>K}r?%b[P=\]IU pшW +;O٤]?{{xx@4%{!VIDAT%SuH0Vωթ_ nr"c"qK2Md-.%} 5XWvJ S҉2'WƢǨbӐP{P͞tqԶCl(ht ڎ 9DLN0)g?_pag!ќ2v-D%0~Hz^ߎ_ umgKoƃg7 M0p+ ZoJY#R‚;B. [~E%_ !pu/h@_}..Rh*H*;0 * Q|$\GsR~o @ /[j]cҀY%%j$(1cJQ Y\NzFQh xAK$ruQcBs.|êV|BLaI}0;.dEh.oGx7 @-q_bE\+.V&~^d)+g3$e=fJC&mլͺ Do$BRId20+]E ].]:oȈ3'U˛̾hlh@39ΨQjG JTɝ% no  Pv?]MV0[0\,w_G?T]]Vn/ŇHz] $8w?/ p-s:"]&xMД)Sllg`l{構N(/+GXxMyh4زrEϙOGwPNIPV):PȯރMfM{ X6)RnX_0}_qG&@UJ9#}RɍPQzC岌)sUu9YT Xd_+6Gy? A?{?4F~ˠ NžG)Z1z1gvM/ٷ85"cxy{cO?0d˧nvn֯f34O( lv@Bi6 kpT? 3^"\c .w޶SUhse.ɓ?vu߆"؞-gl/Ғ=>^>bGpHp'pcLZhp}&?*|Ak(oYԿ]OrJT#ӢՈD/W;p:nv6rd|75oZpBW|emc.'U8f\ eƢZcV7f?͟I>9].rm?8}"ݻFTu˕9Я3x!;)G  z2=S>__W⇓&Z5ET"E`r9v@&vC$0]m6T(ݸ<%H[,s3 #[3;S<^)?y/@g@zn'lA욓lW щå#QyZBs+ĸy)UO5݉bjEE}9 X3Alu]Vf5@8(/+@M) !!Hu8+OhUcõ>SߟLtNZDWt nEdo a/~;` Ѝ9w膷z83T \\o~t򶃵U7k[TQzA/cF}动%` $AFݦoӵZ{׽zSK¶.e?Y%m'vZX,hnnsؗٗ.[1vA<yc9yeIVϫ٪MN4hU ,qew?XӤ8XbrbI8 \Pzˣ[ ̥*ݼ{)]QH}\$RWO9ˈF B=@↢6wK;dVZ' ca\vB..M.i;].Rc_od/z԰45:;?txgV+E'j]~H/,xX>E}WZ >>mչn\1gL^,'!cVF\jgAPeORT$5SyQF#] M3局S*_Xl"(2w4;ǧ͠Ε ؼxxF)ߡy ̚4I` *zJ-Y+3a]i|fRKc  70\.W+k#xZ1Wk8')i`4,ɘMc^4 jv|`^cBWѷTL@3}[E $Ƹo D0EH)Y+5f,R?zSi7MڞJ.ʷ&MC$+n\>P\ݬq+XX9q6<%M(6X-O6&_\0Z)i8i& o`zI7Yο:h ^,&_HB궓h ^U*W8|\6WnL& 1 sy#?)"WHzK7۳M0=0ge]3ib|Hk"_G sj 9̾)^CEXF&NZ+@4(򥐹{F3W=C)(c;nl%sS\um_mz9|YF*_%atk"ԍ{We/{&ѮN@69jD7zkHv_c"XVBWbat\z+aF*JԮrp3zϯro32G+92xճVZ9Y=kâ4哽<%Mk\BcǡuNqh"a9@ + ,oG@i{TNa LLMoo"N2n7#w}M{LT?$+kqx30,*Ckoص1x"XI [B}/ .waaqMP]@VseR{ 5~SX(tPj/V:O.zqD 7n2wxz O7(pv⨍|^9"θDW}z8]~'tX B)i.[9Gn*rRچB!}hS譭!rDbE+hx9Ypy9`<整U=MBigcWFfOs8G@(:*SRmB?TW ^?5/FIC-n;Gk ^8ϫ|tMU?^`v =MIH8TK^I򆡐9أв}hnݹ\e x@`tW0|~TM\ +$UU] ȭDYpO+ νsuXtK!s56[ZgBoλh~ĭkEVLjSO|HKYoOBML͵^2cd}Pg,ZIY9{c[Lz\]]-d!{D VičAMa Gd~ga%&P>hwA{c2L4/TR|kXCdO#]Qlؐl;65>F } M5nv /]tVmag QWI^s46?4-m %MK`p 7*@xzU&4/czge1o[dI ׾J@cBت?Fۉ2Aw6Zǿ"A}"яv\_+c~$# %w^I  \0xI|K7߁*Zت)t89'q#!ɞ&)³*x'h תl76"⍛`$IdN.gSIȣƽWIS̺|㬁մvW*kׯO[T}xS=w%st|x/9Ĵ% :,D &D/]4iikԾkۋ+‹+'Et^l|EIzKg=F+g$_n2,>#w6յu^)g5 DSoӴEtmm8{MIz)0%_>5.@e-HšOȗI?#;rù99 ;!hmGm ^XZTSV } Y/<0]N ʷv 0kΖ""$ BCwl IT sI5VJ@DW*VM%b@{;ѭA}It)+kʁa#Ƙ[GXcm쟊͓/"mgYEFchU;:I33w, ;ˏK>o@r 0Ey#^=M#voҶ|<>o7st$^m~ xGqF# F掟 ]|e->y aUHDld/NGLZkH'kζ?8~ t,/Z%tX[\]73Mpv>@@p0o /-yXg_`Uy װ2U⿩Cj-(+mNKSFOOos Oc?6l{zToU ~z+zlݟb SJ ?peI̎:sP vΣNVNPVVF 2CB {mJEsqkn`iLS 1{!k#S`:lttRƒVfXpO⬴DTO{ %EA*cr(""Z|uR18'+nli&,)!!w eiA9rWu`8-=8THV)l6t AA11Ihwqs8Uy1TE>Rm#/CmG9wmI*Te@]Zxmda" h,XB /5ֶn>*d޳MHг5\ &X*S8[з_?YA:@Uj#d F-{PH2]30e a)F{ĽAWJ{R J %[nV&wrk=T ds޸ 7-[X% a,W&c_ӷj[au-.BS{e90.琰t\pA&G?ѳ RQ O#G{TWG=GK,;-I o~ǝS yQϭh=z}̈́HښBb"y3Aa$3Q0~$*2I`$"$Fɽ]S͚zTv?&h"l2sc}@Q_+oҢPE,/5aKB(+9S[\N<6g6N< ٳ'] M~ѕs6?$; Vn)~ iqr܌1w;{b~kxQ:F\?N'쾹{ -.`ي  /h5~uVxie7˯!{vT/p7AM[F|Wo x>|}ƱcEC%e!5N26o+pkb:GH'=_f^ډVFU 1QJ`Kƿnx`kH1DFɓ'|οwbܸ[QyVؾnp~߁r&IHs&|u D Mj9~#͙bm{u I=III ].@H xsƨWCy1íQ 3_{0at _+D+)yag?<J龶vW~n9kƜyʱmDL$P ) (Tmk.6IE7QZ&ƍ=[,cCr gƜi߅+gGw/)ͷe!6j]K.m])ۓ!<d!8n17J)< 9&#Ie%K;-/#/#q3 L4Xɼb_iq8u]g"xXRmt^+9cC0翂2z}T{߱MmMn P @FoMnv&e#Ue)C|n8ra8 z;Q`#›gyA\]xݖ@KK zG뗁^GC{3!! 5k0+XӶqI όj?ǡ[ ís 臿?,S |kS\K9|;:; 7f4rBDoփ~x&׀$KECt?w]9-PIR$KfHU>PK~w'\?D ,pt[ڊcOP\:Η0t-L._{h@tHߋܯAOz?gl/@励X򘵹n8Z%&H勾$ 9-j>/  J~c._6-s<#Gi) ٪ϕ3.>߁w"1"¸qVz\O+5Ν xgO<>}<|{{%K19X$y4rnFc \:fcx}A$ܺŒ{ģCdDRUj&|cum] 31fV#9omeW$,*Lt[x o"JoBJJl__nIHE{O +`uIj=ؓ$l旻lMH3^ԶW=gr~ ~Wu&#ͷwqc qN-o%TmX<)!-nG֎vW28vg̣c*/8l/Zvow H1 )'m-|R$Pɢ`{s m)j?#7L}W[}'\6n q={)QϨ/ğN/n`TҌ5g>9sÙ о:*aZf ckv(8>q-uxu8EXx#S #oSOpBeLW+_jE S؜ !u*apLnaӈNޛls#߸/rWc@&Iؽ+KCx%5֒;V|>@tgzoQH^Nuc[KMxDWoijjWβ!a" pvdSc+;h8ǯ:k.-g]ۆ(g~V|HYW4 }knKGIֺMWHQ c^MXseo:+s@Xx^wux,_;}/hֶ>&#={\k%7& #q ÜԸI^P %Exw59l"+Sj`} ~yz<.{kJޏ=8*C΁WDA sGל{QJ~qKwV;|_b"HUHh)G D(IeNRuZp oT-po MKF/ Ih]@:"@N=P/ǾPYcc|YAQi^`޿ɠ!FU]g\wE !pu#wH#N׀{8eS$ރ@۹z?͖4FyS5gnx'uc mRpa  e(uϋ5Isg+{#b9"]b HKȠǐH ;KCߍa^d'Ab9QU'˅@&-&s0ko7,>|KM5_Ac@ YFx~3$WVE[J?pCgqpM#}z뷤 pLX=fdY|oo% {0@$˗n T`SsV`{ؽQTmP2XHar,U.x#&bۊ?'^mqgkuowr§:;V?-rA (ϋ1Qf]Ѐ7͉G8!SR(r2B1+.t w6 _zD r0 7}\Ap_zDy,ԬqDrM :DOwNe_o_a4!~~L_Gq,X4yG,"=26lg'0It`.:-k@݁?נR vDdUFہ%tVsƆJ}F =(Yj`f~W9-刐n>49[hYJ'SG ޕTyF9p[8XtKْ<W.:.G۬PX2^&P~t٤ԗ(Ϣ`W bDR jER$ErZ~qA@( A@9;fQp^g*g*'=m9cC*xkHcNg cfyS}xi:RP Ġ AP|馘$,&F{Z{f_ AS-xOPL;@(_&BobkF(VԈ/9юAc%'ky,4<~9p ZO e,_+((2p:k]ZdT=dGVs Q( i#KAL`V,-Wzӫ iqC dLHpo[e/ 7y6$JIHZm 9{ѠJ/3WImvnzLbH=5=i‡xp=˵8r.8\/舏FwĴyfBAa!m&V-4jdX@ ctjՇؚO6 'ГVPnIA6pJUMXCoaZ[Ďeͤ_~ϟK|y;YK>̓3jLeT@vzuV]V~CuGwuO=I_[`|J3ӉX^-%]K0"?mG 5d?(ANǺf~ym-fI+xCgeFb'ok#-,@p/7?wMSTˎ7LHU @.m@8G- H p A$Aց' DI` _dȚ$_yh!TNCjݜAi0磓dUu=[w2|xij9$z$@^b3<:aU #'']- `- !(Xğ;zb#5 D^3`HCU6E95VnG $ xn|2 Ӻ OTm0[87>*JbX.;əbi~9+ݡABpI`0s72x+A)h~%B3 o"LcѾo"9 tՌ")wio(N:kΑ%H.fv+aqER(* ʄ+<2.Qh\ 0ĮpLt;y 4\.W-h4Ht%U^ 0>kCUP#rZOZG(?PVu`;KT\[N|&Z,/O칶 @~Ao=GuXp6T=Ȗ{+T%*>?W{hlpwo:3/VD`TJf'WQN}e!u?'֥x0 >j0[\c΢Ȕ!㗄U/pݰr/lMI30EEo:x/u;6#䉩=wkLDȵCqۿەZҢ l@kC'wt/"#)2&Tl I<Ў%ptBq齵8W:0I & ޫ>τ넏7LߒvرzNƅi:8wXŞت0n"g8Z̯=R.\!X0 yGOߜD]R1 lGSX$RU+CWGo\2!~K j?w5ȶT\vKgO%Q ]\<{ʻXfF^ic$c{&VW55+ c+旓7 iqb Lj :Ii6cEϫ)8] QgPZ^ URXFȴ5qjvKp]o-߻m軣ۻ58~ uCw{o|a8daŸX7_~Qg3~_i>ǕaaŎU{,1bRц9fm 7o~ϭ^ufO.]b:vt45;<eݰd؀ tf%Q r}2"} %d!+ApTnNΊVkp1{jAA?1cBZXh+8mZCAd`.WJH#JI!a%Z=Q\RGr/yʏ2.)NL}g049!8X$`/xyx 3;uKm u6;)iR,ϛ>[pz̈5:Z e}T]c:VRtl#ىf娆µhTDEkMi'5P//' @=`&gmNYX7Ft1Ya4,׬ 4ΨpԽ\y>5 Od?hhkΞ15:q-oz8#gwPkBl;Q7|6cO-ؤ9tUsƆFs8@i~yCQ6xem ߥ Ι;%EO}g caT<,FwI ]:X?"w<.h ?nԪxmvÜT`[[)qo'7_~QVj.㖷}OCm\ 7͉w6n@@W抯Tmc3>7s'&&Łmq=AA{ z<7:ʄ}X|滒oKI 4n^(fEF>8ejLYI(V|Ej yOƄ8+u~3uJ˫dxd8/|Ǵ˄L9}q 6^7w_}MTZ 1ױ6I/ևBA?4#elX9o?8&M4a=]Pr[?q}q_-0hb Z6I\-+I?[dUP|^3[Daド12 m`"H 蚁=Y^x@Lq(qE_i )=\1~Q!wǸmS oEJ_@=OT2Lpui/D◪!UAfKm>sE@O<;n_`;TF&N[ "-rq;AdD8E3gvgM(rY3sb~uj;{ߦPIS"uh:vN=UyQ.}x*'3M~ub,(2D&|O ¢ʺoO 56e/ QOtEs #_XN齵Hف˛eV0Eo LTq m[%xÄ,)fo\420!w;Aܖ9}̥2ԫ>Tg C_gtTxH"PT''+%PO@?vub8m iq)y37$vt.^4ٵbu]YY3f.~ٞ_~4j J f=xaVcs~p!L+Rup; mrT2e+=ΑÔ[ףp$@a=OfŚEլ jojz{ _+pi拕x88(/ρVzш\o/6 To1^vgcW6?Sp@)>js \z[OK/Di~9w]"\|ՎI&ىbJ=mz+28l2enZ%"ڽ݇V"_(DDݣfyg@MwAzk@5rXbǪ,8ү[켴>l|Ls|@5!C9m,;-E*]qW^W(S ](S@Pt!@ P_n|݁rWT@b@׿}J]D0sn"!,;'9d#8 t>uP?-[P_{,XQu9|x£D6rǎc,Jۮz=@=@x'4lj$Fc07Ur oDrr!])Q\/Eh};G>q[&|UEĶ)S> 4?Jimd-+fmyP̙3C4AAϐ jq78z}s0-.xqn_^,Z|1I˼FuPwfk o0 ^eT\U'<>}-玎ѲIXv|ȵ-֟cIa^頋Y#jEĎE_X55NVnݣfg̶h L]cHt{{<>(k@iRHs~.]޷LsNtߖp)7e.Tb*Q>-c<3]OK=qg_8[vނ:ޫ ^ۜ`NDkz@AU*56 Nloj=F pf %CC7BbN.PACcИ*wa\i]t>yOhD0 W|xeD{?- H$;,mn!8op8BTa blARo-bM΢SN74=jN@׳s#gsǰaAΈ/+5?b.}Y?N#S(K:wu ׃z am lAXEŅq2$ɠؖԺy kWDGrtҺVڔ4‹9`P4]ŏ"5&}""}<̎A*J-w K51H6x fi{?7;<, z&Mowa=ݞŸ.?}^}WQ\dZ wj N'&z ohϊX;9_^ G3%P_QΪ+-Qu/Y[0TcJ Wz,^$03WɼZPYYp~ 0&/+++ctcqĆ:=œC#!~ևLHf 'F˦+Hߦf*;ƾ# EhH(&䔍5}h^Wn;U~?peap/ټR[ l{ؔA6:CĞoG[oR__Wv^9&i祝1qB2ۉ}\IKx_ z2\4*3<[7Nnb6 n}"mz>=@T0}r,::6J(OXPۡ%Q- Z#/>DzӢQ CEд^cTyi$WoX/v"놔anAa!U 9{N׃뎮i)_W]e7T)^ռ`OHNisyL8hI/S}tu ޻3 ][Aى ``hR6l}=[5=^X X2Upi^18c2P W}…f_- _w&$X7sLQiiU CH̾6ɶGjyʟv.ۧ- a>%v/]6;ƒ92 4hTM"LK"w @-/~Nn>X{7: u)~0_jn@lL v͓{m+u㤯#ԑ/vRc\r"Y+N|j-?[ ~W[cK>liK)륚Y|ݖw>2^P]m ZբAzFǸ`cWS,vD*ˬ{Ue'*aD_Á瞟 EX85ѻmf@pp0聾s\:%\ᤫ[dE~" 0@I*o5$-gI!w+U5r Hw[^1#4*t6<0mA8_% 1__]8KogEm']773b]D~ZZ.o)%`=׶@#yWL$Fc2n{M7{_%{CZn4 $;'RS8@ wpMX"zTr?g h49&MT"r2k|e q[UH/T8I7Pk 0a f瀣LFc9!_YQ\rC&r@Dyyc8ax{łB'gѢE}i\3/ޓ좻32 NA8Tl@!ډ111J??r7(Q[>&?-[rfv~/$Y@d4/o[x k_?n}NH,R{<{0{j3$u$!_rn4zR '.>7'&Da!UJՇ@|Ѷwޗ(Q%s& =NYSm&8u v;Ecc}ފ}ViAU|oa8n}#U820oE"kݶNR{p{Lj;W$Pq=PGY3UM %v /^uptZ A8Ipy$I8NC&~sJ!'ˏd?VZn?@p'Ռ]$Ad'c,;+Bhf"%5p57X{l@{Ka$ٽ0{nL(IkPn9k/SpՐRUbAѸ%)1quc}vcH4le mS@4>S|b7rP ]TW؝tzɷ'Eu*{|\f3kpzpձ@0î wȉ]GC0k`ȉ4El4s;"}JBm+~5og&3A?rD3Z~5.-MANs&9>Z:Wsx'5$ Q px!bo5URWuć=ح oEr\ak rxݜ)Ot<{]JP Hf)Ǟ"` E8HM[t!aE٦B6`uEHF.ny.6Vcr,kă .5{l8>Ѻ+}=_r_dFoàwp cl.e3%VFFJijHJtV@/ΞξT0n}h tJ\B?ּ_î)'t :RuRr-EP<ވm?a §^]-V-Zl0w#ݜihR RE&FЁԄST'dTGޑY)AK`K5"ݖ6t/j绣iP$ LM:#q:auMt'U~ʛ==LVW׉e"#aؿ.]b "N4O3(iW5v=2ax h",˃pp4ԇNLx!nd3/|dayhЄaa6^4uɐd&N8 5.WEHK󥦊.w&VS=*e$R^;7Wybaw7OǕf|2)%9;HO]F^ {UTM17pۖ=5x9@蹔%oᤒa:ڙ5g*b@'fp )ncvvmQŏ*,yG \̽8VN_\ɠ wQGk\N+ds6OD3O~/ Ja"_=77.> ,4^^(\ a(1 ouadMT)%#\ Py֥ tsid0BTq)rAy[8{s9LnPE⋚(?KP|4^j4$MΪfuTv"}Ix~tb nAXD灹AXW9RD8 gz쟟wzc)n=_e#|Ԏ>qN /5U庬̡ w2K:ߏsҗ(pUomˉ0W|!# `6QhDAL~ՆI^ A߬[tPyQܵ 5@W):\!6 اPsKp"Û:ǭJmrZ5~J{ sCL{DX<ݣT=jf~-03F*'i^E|@H_늙HH#e Jŗ| !$sZJxncEi1j$y[}"ʔ[ {V>.w3u`(Xfa\u[u)ɃB#qٞЮ~UjG:2u {݉OYU /7ʙڟ^c z6<_vO^#֤u a^`+bt na7/0n97KZb)h.L^V WJ)kp兩,̞KU/6^Y uqlXa[A .hR_{\ݤO9ٻvȳעp(Sli],K=C'! q{Ęa af_))_G>Q׉oQ.[jPU\{nPv-eq8Be Y 3~-0n9. qc]"+[\SDȸ嗩|Nފjs!y dz'}>^Pπ)7aB(?,j&pt&I$4ڰ|{7`;y; 3crceOi5<(+^sx!N2L'SUS8=Ze"be$#Œ;]űxXem+d+)r;W"t%辒 ~.ʔZO&+*}|Pp_xbuW+0سYCi@#0xÄ`ˠ~G׳ { g*.ۨU[T`EVB]oE iqדh9B)0k%#Px(eo|Mk?=jv3;VeG}.#APfGtIJ/|nq&zi}b?WbP%k㨪>{#2c]" )s_#]<5$Vn|T}d P"P$#ZZN2jH&/e<Ƥ/vo"*i $]Jga5jsB<@UKK ~`2#KpG3;+ef@M7A@mW3o}}'Ui춼 H=<񋡝?0nWaKIepD]3Rx?ۤ?,Y[[]wCe/-rPܼEKhLjyY,a衃OEҷ=$o{m]~}wۓ~)1=o>~h[7:z}NO3u$#^þ`QH #1ǘ[:@UZb<ۙoܭ͡sBkn/w_7ޠILE]~)/sxf٬FH]4:nlשSg߇a̸߬: j&Ml]J"׎ $~Ȉ.[c'衊+ۗ˩w?[cHbhoooWï]3麦˘Ba-iRgZxS^^]?+ 'Jk~= +W)ܙN)o ##i Vr+z|WTbGysWίMEIkfH9YY @G x!Ӗ)Җim;3Q@_nE( }zqSM =Jw: OEuub)GĬh`!^ۛgB /5Y {SO @~pKӳff7 3s d-_!BCYwܼq?C!oO[_;z)s9;Ek4_ d(Y.o[UmC]E~KET2֯ҷ`ojCӦo~nG;q@ +3 AAoJrz+w O=y/,m(~{|@!oipvWǬgL_R \/~}ӦKl_9܅tp?! ~G/ 1`7a\Y_A,OՄ3. FSΜ='x[[%2vV uu n5**ƿqm5 8jl_o7|Mo{ X[?1oUIc)U fnWh{-OTxa ٬WނɌͻPU[Op^X y1fdXz`ƿx[Myu[x"?!}u>øF~mhG;ܱ'YY-6_x'5ǿ~kr\߽1l3eS%e<ǿи{=~۵|]ȿ m ](lkQLvv?+§M5M &3BI5?@+|^x3T{[= 8`JpŷËŸ\{ ,6˲altv;y/"lݞǴnfps$V .;Vlo3'΋B''?c:]jÕ|J]m7V,^^_ٲv#ѣGf=% يH vqHh=mdcb7+\v)Rћ?4$o[VOk/+?+Lm_*'gςuʱKj4 "~DoݎKjnf74yΊ/W/wy8}sBu$tְu@u$LstT=Xj*pr9,~Jq(Jž+_f<'gs~W>~7~jj!j"J yvZؓ( ) Ka߫m-{gp+$e pD+bM~J^';?+O5=OT ֠T<_^~Yfu6{ Zt"|Y?,lO}g$+p=8t(E;;;;; ݣf|?)6MX@*v\y6G;_/mH` g\@ΉS$|cwAKrXXf0eS>חfHOU \=&|;; =MdD-?W,W P/ @sR+/%+u"oRof(`dxXWJfn|Mb?Q7'S=~ۤU| #xhS#y}={K*-j&)ASr;[7R#ø:~$O0vJ_摨6p>S=~%}.R|nYK[L1ZE9ϛ=_ ~GGC30/'rYx}**UI~#jn.Dݰ&{dɍYbƟ7{DEB~EO+^J_+1,,F=1tZA!P/UzruWO~pD}7ynOr Z#>`PT, ~|ހVtLXO3/ vn+`)yGJȤdγY\k2pLqmDhX0qf E_egp_ oA "#BKDFU A0ћ37Z4Q+ < P7.1T/%R(r?9"B~/ϟk='dd/Pu07xWUKBZF5/U庼_j`=\NȧZjZ-=Di%oK~ws7"o|t),8 ѾjVPeMvMyB8z@k}0 *j +@pwcsC%h[.?zV=ӟMN6>s *c-vV.S_l9E o |r_j]C b5 WRS/1$4!+ :h)`yG4$S);B?O~Ϝ#K+Dp!:Y~d}R@}m ~`j?phDvk N"OϿnFʋ=_i ƧS,/|I,^WTKl. %.<_6:;H}W/7(Z5.We\؋Qjh}yO? E&}x)3T$Pȧd+1WQ(别P]>a Sbqҷ諅_(?|sJgn~)pr`7P #s#Mw 7{D*3=B˛=3ky;}`%ZsR ܅vӨ8JfXԓ8_Q0q/^+X+xKw>NU_&VF10I֫?$ò u#mདྷ^!Dľ!*WQ~@rA 0%sJG5`L=oy.f!K~?ƚc^f(H_+MXY+*Y Q93p?,|I @?1F`L@|Hh0{Ӈt >bf}c1(5A §?Ru2) 8r~#4BX\H>ga>̹!$4اq Kt#0sx]~m{kw{o8%aP0fd`8Ov㪵47j,Ta7@#7Xb弯%'Bn]RTj99Qe* Zr?265Y$Yc` @2QU& N(U,tf]J #_LA[̓tVA:׳g(ih?0ߦ'ț=JfrUWoU,QD{p`?o\В2W\N~?_ڻ uye=s{s'#0!]PG*>L[Qn%ZH~-3a`WmyY|]M~ϔS/_J>eՑ j,SB_5LZ@Mf6KEpνDPi[FP/”^|usD3Y&Jsf{:傖|)G[wK)`nwVC$t P}"NA eœw܉ubOm#f~ƗX܂jQܷJg p֚U$CnDXh^7Y!Zzb*޺Or=sa/n &J_EFzo1]̹ <|>-HMeKOՖN<}ľ_wc<}^ﷱPvGqhM7ZӍ'R ױ'2 3OZ2 /V. ܾ\vv+ߗ'ig *,JE䠈_ We˅3?N|9=JAy>p/s,BCp#:t섡#oБ7#,<ÅT;z²ȄCk 픜?>h5`Yd;zz .<OjuW'4ko* T/W~Mn֯W*2$y䟗N'zG~MAR瞷ț="GVxeGD\^7naϡ׿/]IW \_IA{r9[Շ (mG`y[ɂbBkѫ_6] }P-pr2K(x.TJe]bкwgP%_%LM`>h邽 A viz<# n%?0$}ծ"R?@;^<9,ߏf`N͞%)lN_KVy >W BB_r{*_ n{H_ew~A1 '~3T,!/k6JR7|/_Mp#O;W2zj礔sM<`¯DO ?WRR VO4W3p וp(`bn?$yJ%˹͠O da+ug_ 3%qns>Kuȿ;'Nc< _Wx/̗, 7.ߣ%L^ݚ*Q\l4Tdkj8#RŲ}t궂U}&x [] Lfiyn `-{X2ï hquF4yQuZ8rۭb_," }(Sn 9RS8ݪ_xq 'fϵa.4qq$!lM%{0}E|yq^Wb#LIqVNR)P@/X% .Gr#펴r |Β]_n@h],VE(B$W+-L'EB @[<3AGʍ\)߰N H,̞7G!ud&s5/wHI@V*YtNe`BcCǑܫ/4 v_JB)uL).$3VO6u >}tWYUmO90.˛ʳX'o؋ͼEbiҹZ7!h,H0w5j!ଶ"`dkjdP"xͪ]c7}ծ!yTaqA!z޶3G1R.+J т^)^9)_ /%}%Py@~ 6zNN՗}]|(~IJp AKgLdma\U1:Q܉xU,ZA?8B,+ 40-J590[h| `l"ɽQ_r'XFKM4.!>_ޟ> ]0ºcEiHڕgƹ="8EkKfX38I/+k'K>ʽo+}W+?WPls!lbX8ut1[.YEH|+f٫ :]MlX *QTH/ۚYS8-`DrI+ @մS0롙4 pBP?ی4bnOH^dfڵ\\7B 뷕#TUț=BR|#^@l96T S+Rr .Ya< x:G칛W>UD R"bTmp}$HY^,1i/c.)ǞɽEw쌰0= d$^}љ Ծݲ/a1;vԧ'8 ( رʪvLQܽRX$̈G7`)egrǕLQk5zi<$t7Η1h:ܧMi h&y2x+X%T~jwF'PV~=!{|H<>q61¹!ηЃO ؒ"c K\_\ !`TMK\Zѹ@1ܜdMR?tzKfX ar<$U@'؀Rk[n{ 4ѧJ#BT 8u hc!W\ByxV`}{˒x޺(SnX_I 40m*q'Ѹtv~8a"m(:+I!XB_@:0hZ::&jO}߻Z@q!k_7T 23D2E4/@]KM-+ ]nؓ`bd)܍ ֦ҿ=!Ǽ0=un{pr cG#8m~蛜a!)=S4b;-gRYtQ\H6tQu.56u rV@ft_ R>..Vh,rV B+X-6t_mnn瀚(K!4NNf2P⣜^TUfEi Ka;snQ E`X2n(yoAoa0+Eco2}ܯ/yRj6ӘB^VnɗQG'%ޓĖ'/0DFفz60d6Y8bhBxX_ě+/Zo}g)^D5({DGl9 ^ G)//+M"S MLOsm* 8}'b_wW7lI|Ȉ/@=UT^?Z)5} {[QjV|O~T1sUCǎ8TN9l.>qb4l8#CLG,Wh@\ _~c/v"k)ZV| .3^ףHYbo)2fFr)NM}$q'WY|ZjF@ie?MɴlU#R#"48hhUmzp.Qb86 r#S<!JD(焏y[pQ²ZkI)%v bY&YGT zb痢[kQƒn j+98h;ƒz VK>T!W ) @Z {yORKܬ!"!"g_BL J$q׎ .5;?|Z`p],??'l,LE=BlU8̋(SnfMZU|5zB|RɵܷjLVmmp>tlކ0~MgISne 88ܔ_\ B1 E>%V|A悪\e!BϊNs_YdcU0{,'J|cUg2\Yfٸk q:/3\)_()}Pɤ4R#E Lc :+"(-eGfZy7ҙ~`5qhM7ZӭU|QrEr:!%K0/a^.13mI2 ]О׎үmtTp<<7{SD>}.%:E7dkj4}!yZX^YׁBϥ>oayxW6iӱU-mUl7[9 Fzk0ˊ@--rL|H/^Kszssnq[ H}%v[8K|7bYQF ~t2ŧV6 H9߉Xyj8uF5}Մ|nXMRWzTכczzV~ SAͭKJ 3+Zm + c,Wl7E?#_ Cu'{~7菇I_?ٯn.jS~9N@bS4hXyYa'g5H&)o qLUqح|+SW=;8 }UlJsb7tjY6_nqr$|(xN QL|MgLG2uöuE]>Bf_r\eDf|^|IrD *]dTMH˴Os+ c,$}wh,p *$ v%{-\e~O$[yIxUa~㢓ײu7@ _o /"ٜ&hS 2*gٺ/b9KȻrZt2L- DܷrIsƆZ}DZ Ҧn$V7Ko&`% Y1r*$-P-$u`dkC~-5XSDvYk {fK؊y'< zR4͑7#€&ڋ1Ok^u_kOo8W攮^UnMXDܐJ,:c%u *^ҥc7cHp(JϵֱkȄhjɹ>]̱c,d/+.79x2t[럮fgoo?"¡Ӓދ9cC/q6uc?O^Pf*N1'{%F(Obc[gzȒi3Q$bXr8}E E5UmfPןo  $C]FNXtޖRl]׽c`-/G@.x%!(*\uHADu,_X]bu%è| ]QzB .FZ@rV51.@GP3W>fg`y}@A 0hw?XSxr",%X6ucU<5i !ךd-mK~o nG8.%O<F1qF ֯>av!%^*ŗۯpCB %TE@}c)-jDq)܆f bu-`àw}mQ5|ˈɌ8!F~ݩdבsMUvEĚAswF_Ǧ6 %<.hs"w,w{D0hA'Y׵ YY1 !&J!&‚9ﻬv36Ro;8b8+fi DPB+I59c察\e4*~`ķgl("Bi*kе=ߒ_ pX?ٚ*#"Alr+f -qMt ;. 6 MJuw.]Pv N|t=dV53z"u2wq6G6\JuOFvQL/M|WlU EK!'-l "8%uV0|@2 +j#5z +\s-\+"Z!yZLψo1Mc2\9ۛ :folnt%嶆be.:hkn\e%O(b5ITעleUO#jr}|,|Xξ/f)Z~` t ײ{:7S}< :[Bo!zoȪg RпS mk_7#JɈ דH1)-\lEl`$jh!1Z5gC_OŽS?)ȹ+.lJ$`Pt3q+3irrgwjhk.k!yïha1@9F4JU ĵx5g0/͞2"_?~Cԍ=pMsq|Y?g*7?\ ?UztlU$rsXpYeB !ʔkWm3^ރYo$`+7qknsm[^fbN<3Wp,!q>\nXbNߚF@3x,@ ȃ|뫂c(\v;Ox8.BTH oKkҚ0 /+aރZ r8l)zàw ndVG{q[4sP veK 0n粗viA2vzѧLñQb?g*3vtuoi? 4TwOFnHu;3n_X+fqlJJ%C8Tl7 .@"cɌ|86X^ h'P @'6+&bV-='v35-+'̅}@ -ŐNN Sl tJX,kd/q)@&E\\ W|{&evqD-qeDAUKhVP#ĕ/+BDu62u; ŗ#YOxAAshl"h]k|gCVTd̙V?+}?97:>۟KOJEe۟;"./G[ƜNSȿi%\~iØ3q1glj}ƒGPp\Iq?D"fCU%[o?u^ p+Qt 5&R_.y?EnXOpV۠K0",)*"eGb&CVl Uc JO;N@M5u-=U[2.Gpk l3h+?^`Ŋ!i"G6je|,# 50Q#]#b[3q}nsBoI*锳Usn )<>AFd=>8!@ldc\T=/7Yds _%C+yhf?-d>YBWýr=gP*+I1K'= 9u7-9O@B᭲4?jSc$^ ՍNUI7.1 NH. gM%p@*P&sXzT[Er~7i5c=(H}G=*Sϖtcma564?u(02lgȎo桇L̿0 J4ԆdV4 ۦ?0Y-ݠ'sD 2ȉ/AoėEFLo ΪuFE/w/znh!=+I<+FhV[Ll2~ϲ8֟op޹Iy{5LY*ԴW*p-g~5Ernmdh~@ l+q ruz:Vۥu(t,nH;zaBJo@wX =*h2ӇK;۾_%ϡ.n!;~ <~t3_8uw;}?;}?CgC3sbjG%N8_V qV1yLĕ؜^7ɗc@Py ipzf>|rķ "-ɹA5"<[Y FX#8["]8wwn tTą#P@)41/mTPsLeHqY ֚l&?ڳ-M0g,aazpO~nL)AT7:Q-X2n)cBPt [XW5%1pE([ K AZ-ZԽ&lfeͪ)XB/jŶ*Gcϗx<HfxNcm3= `[kMRl6,/FY]udVx ^K'TÊ6W{N/[g* "!?U|D(gsIԓFLU%\Oε󦬲\.+˝>s !1rL&q`S6u$69e@q6U\rf<ӧ/7 侔Zwgn.g^ټ8> BEPoȼ(0^ۉt=ѹ2[{{xR n}H[~d.}ҚI23eR$X\cz_J!N̮l2|ϲ]Vm :C ㊔ri#g% ythҤ$A"XVx~_ +f'%^{UpSVht{Z,tN;QuԢ\YBVid~VwI"gR"{v "C3CULeIn @k*.6Ex)cXo{oϏ<( Vl(v* F̢FO9~P/;D'K_G.[!|5p6O5c۩'.SԮ$[O-]IeĺV ۵C1 7qmzJ½蜍{B "P3h~tRU[R'n⫀+¬^@-?uք磍 *n`&$&`C(V|tl>h`TgF+ɹVFkm(=W̊pbِeP“*_4?,ytBW|@0"&"A",2̰+ GM[7q^:EjEcRn]lɲ*Qk3Bbҍz1.,ۀs=Na!$ߎ5r@KK Wl$IrMeI4_~ʒh% w~VEZGfV c'wa7)a>w֮xc Jx"̝-Қʗa"}Y@WBpHtd4: $]'i0z|f W^yɹVPiC⪘h%)6zO Ǔl$g+%Qe]3kj<Ơbq _s @4{B&Wl7OZ )憾+ N 6XIB@"P7TEm+ ')]/\4ߎjyۄ\b۫NOXzjO$$sS3׽HMĽB 7ށ+;=*>: Sv-~䵝7j {Rhg%=nT<%r=uop(36&|Gi,5`Ck"='ONhZbϋ3Vp?K f`*4l*S!~ K=,v]a+ʔK.-Ps]\<0~d7~26d