Locale-Maketext-Gettext-1.32000755001750000144 014010010654 15605 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/Artistic000444001750000144 1373714010010654 17502 0ustar00imacatusers000000000000 The "Artistic License" Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder as specified below. "Copyright Holder" is whoever is named in the copyright or copyrights for the package. "You" is you, if you're thinking about copying or distributing this Package. "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as uunet.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) give non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. You may embed this Package's interpreter within an executable of yours (by linking); this shall be construed as a mere form of aggregation, provided that the complete Standard Version of the interpreter is so embedded. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whoever generated them, and may be sold commercially, and may be aggregated with this Package. If such scripts or library files are aggregated with this Package via the so-called "undump" or "unexec" methods of producing a binary executable image, then distribution of such an image shall neither be construed as a distribution of this Package nor shall it fall under the restrictions of Paragraphs 3 and 4, provided that you do not represent such an executable image as a Standard Version of this Package. 7. C subroutines (or comparably compiled subroutines in other languages) supplied by you and linked into this Package in order to emulate subroutines and variables of the language defined by this Package shall not be considered part of this Package, but are the equivalent of input as in Paragraph 6, provided these subroutines do not change the language in any way that would cause it to fail the regression tests for the language. 8. Aggregation of this Package with a commercial distribution is always permitted provided that the use of this Package is embedded; that is, when no overt attempt is made to make this Package's interfaces visible to the end user of the commercial distribution. Such use shall not be construed as a distribution of this Package. 9. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Locale-Maketext-Gettext-1.32/Build.PL000555001750000144 225714010010654 17247 0ustar00imacatusers000000000000#! /usr/bin/perl -w require 5.008; use strict; use warnings FATAL => 'all'; use Module::Build; my $build = Module::Build->new( dist_name => "Locale-Maketext-Gettext", dist_version => "1.32", dist_abstract => "Joins gettext and Maketext frameworks", dist_author => "imacat ", license => "perl", sign => 1, script_files => [ "script/maketext" ], requires => { "perl" => "5.8.0", }, add_to_cleanup => [ "t/test_native.po", "t/locale/en/LC_MESSAGES/test_native.mo" ], meta_merge => { "meta-spec" => { version => 2 }, resources => { homepage => "https://metacpan.org/release/Locale-Maketext-Gettext", repository => { type => "git", url => "git://github.com/imacat/Locale-Maketext-Gettext.git", web => "https://github.com/imacat/Locale-Maketext-Gettext", }, bugtracker => { "web" => "https://github.com/imacat/Locale-Maketext-Gettext/issues" } }, }, ); $build->create_build_script; __END__ Locale-Maketext-Gettext-1.32/Changes000444001750000144 7233214010010654 17264 0ustar00imacatusers000000000000Locale-Maketext-Gettext change log 2021-02-08 version 1.32 1. Makefile.PL, Build.PL: Added the CPAN distribution metadata. 2021-02-07 1. maketext: Fixed the version number. 2021-02-07 version 1.31 1. Updated .gitignore. 2. Added MANIFEST.SKIP. 3. MANIFEST, META.json, META.yml, SIGNATURE: Generated files removed from the Git repository. 4. COPYING: Removed the redundant and irrelevant GPL license. 5. BUGS, INSTALL, README, THANKS, TODO, README.md: Replaced the messy GNU-styled documents with a single Markdown README.md, and updated the URLs. 6. Gettext.pm, Functions.pm, maketext, 11-command-line.t, 12-cache.t, Changes: Various fixes to avoid JetBrains IDE problem detection. 2019-09-17 version 1.30 1. 12-cache.t: Fixed so that it works on MS-Win32. I forgot to issue binmode when copying the MO files. 2. 00-signature.t: Removed TEST_SIGNATURE, as this does not work on everybody who does not have my GPG public key, but me. 3. 03-errors.t: Removed the debugging output. 2019-09-09 version 1.29 Fix after 10 years. 1. Gettext.pm: Added support to purge the lexicon cache and reread the MO file on calling textdomain() when MO file is updated automatically. This enables MO file live update with persistent applications like Mojolicious or mod_perl. 2. Source is now on Github. See: https://github.com/imacat/Locale-Maketext-Gettext 2009-06-27 version 1.28 Build script fix. No code changes. 1. Build.PL: Removed the build_requires, as they are not required by the build process, but by the test process. The build process should not be blocked by them. Suggested by Ryan Niebur and Adam Kennedy (and Audrey Tang). 2009-04-28 version 1.27 Test suite fix. No code changes. 1. t/03-errors.t: Fixed the find_system_mo() subroutine to exclude MO files with special characters that might be considered as code by Locale::Maketext. 2. t/02-big-endian.t: Fixed the native-built MO file test and moved the $POfile and $MOfile file name assignment to the beginning, to ensure that their values are assigned even if GNU gettext is not installed and the test is skipped on the target test system. 2008-11-11 1. INSTALL: Fixed the grammar, changed "none" to "None.". 2008-04-22 version 1.26 Documentation fix. No code changes. 1. bin/maketext: Moved to script/maketext. 2008-04-21 1. TODO: Added. 2. Artistic and COPYING: Added. 3. INSTALL: Added. Installation instructions moved from README to INSTALL. 2008-04-11 version 1.25 Test suite fix. No code changes. 1. t/03-errors.t and t/08-f-errors.t: Added find_system_mo(), to select a system MO file that we can use. 2008-02-26 version 1.24 Test and build suite fix. No code changes. 1. t/02-big-endian.t: Added creating PO at run time, in order to work with GNU gettext < 0.15 whose msgfmt does not support msgctxt yet. This should work with both older and newer GNU gettext. 2. t/test_native.po: Removed. It is now generated by t/02-big-endian.t at run time. 3. Makefile.PL: Added "clean" to clean-up possible existing test_native.po and test_native.mo. 4. Build.PL: Added "add_to_cleanup" to clean-up possible existing test_native.po and test_native.mo. 5. Build.PL: Added "build_requires". 6. t/08-f-errors.t: Fixed so that it finds the newest MO file found on the system, in order to avoid legacy MO files. (gettext 0.10 in 1995?) 7. t/08-f-errors.t: Fixed test 38 so that it skips in the eval() block, and dumps the error on failure. 8. Changes: Added several missing change notes in version 1.23. 2008-02-19 version 1.23 Added support for GNU gettext pgettext() as pmaketext(), to translate text messages in a particular context. 1. Gettext.pm: Added the pmaketext() method as an equivalent of the pgettext() function in GNU gettext, to look up the text message in a particular context, according to the suggestion by Chris Travers. 2. Functions.pm: Added the pmaketext() function as an equivalent of the pgettext() function in GNU gettext, and the dpmaketext() function as an equivalent of the dpgettext() function in GNU gettext, to look up the text message in a particular context, according to the suggestion by Chris Travers. 3. Gettext.pm and Functions.pm: Fixed documentation and comments. Changed "perl" as "Perl". Removed contractions and replaced them with full sayings, in order to work with syntax highlighting. Removed emotional marks for the same reason. 4. Makefile.PL: Added conditional checks for whether LICENSE is available in ExtUtils::MakeMaker. 5. Gettext.pm and Functions.pm: Added xgettext keyword notation for dmaketext(), pmaketext() and dpmaketext(). 6. t/locale/*/LC_MESSAGES/*.mo, t/test_native.po: Added messages with contexts for pmaketext() testings. 7. t/*.t: Added tests for pmaketext() and dpmaketext(). 8. Gettext.pm: Fixed the failure_handler_auto() method to remove the message context from the message key before sending to the failure lexicon. The failure_handler_auto() method differs from its Locale::Maketext parent from now on. 2007-03-28 version 1.22 1. t/*-f-*.t: Moved Locale::Maketext::Gettext::Functions::_reset() from the end of each set of tests, to the front of each set of tests. If at the end of the test set, it would not be run if the eval{} block fails. 2. Gettext.pm, Functions.pm and maketext: Updated the URL of the GNU gettext manual in the their POD documents. 3. Functions.pm: The example in its POD document is updated to show more of the nature of Locale::Maketext. 2007-03-28 version 1.21 1. 04-encodings.t and 09-f-encodings.t: Inserted test#26 to test the $@ error message. It is an encode() error that is not affected by the Locale::Maketext $@ change with "local $@". 2. 06-racing.t: Added $LOOKUP_FAILURE as look-up failure flag. Added a simple subroutine to handle lookup failure. Test that to see if we are really die from lookup failure. 3. Gettext.pm, Functions.pm and 09-f-encodings.t: Renamed ENCODING_SET to USERSET_ENCODING. USERSET_ENCODING is set to the encoding user specified. Future test should use "exists", but not "defined", as user may supply undef on this. 4. Gettext.pm: Renaming _lmg_failure_handler_auto() to failure_handler_auto(). It should be OK to override it, and this help subclasses to employ our version. 5. Functions.pm: Note why we don't use $@ but @ as the prototypes of __(), N_(), maketext(). 6. Functions.pm: Removed unused global variable $ENCODING. 7. Functions.pm: Renamed %VARS to %PARAMS. Changed $KEY_ENCODING to $PARAMS{"KEY_ENCODING"}. Changed $DIE_FOR_LOOKUP_FAILURES to $PARAMS{"DIE_FOR_LOOKUP_FAILURES"}. Changed $ENCODE_FAILURE to $PARAMS{"ENCODE_FAILURE"}. 8. Gettext.pm and Functions.pm: Changed the returning line of encoding(), key_encoding() and die_for_lookup_failures() to one conditional line. This is more neat. 9. Functions.pm: Updated _reset(), resetting $PARAMS{"KEY_ENCODING"} to "US-ASCII" instead of undef, add resetting $PARAMS{"DIE_FOR_LOOKUP_FAILURES"} to 0; 10. Gettext.pm: Updated failure_handler_auto(), check if this method is revoked statically. 11. t/*-f-*.t: Added Locale::Maketext::Gettext::Functions::_reset() to the end of each set of tests, to reset the environment. 12. Gettext.pm: Added fail_with() as a wrapper to record the user set lookup failure handler, so that we can safely switch with die_for_lookup_failures(). A new attribute {"USERSET_FAIL"} is added to record it. All references to fail_with() in other places of the code are changed to SUPER::fail_with(). fail_with() is only for the user since it will update the registered user preference. 13. Gettext.pm and Functions.pm: In maketext(), check if the key is Perl utf8 text with Encode::is_utf8() first before decode() the key, so that user can safely run a multibyte-aware script. 14. Gettext.pm and Functions.pm: In maketext(), check if the key is Perl utf8 text with Encode::is_utf8() first before encode(), for empty/invalid lexicon with key_encoding() set but no output encoding, so that we can have a real pass through. In the case of an empty/invalid lexicon, the user should be responsible for the output encoding. Added $keyd as the decoded() $key, so that we can check the original $key later. 15. Functions.pm: In __(), removed unused variables $encoding, $lh_encoding and $key_encoding. 16. maketext: In parse_args(), check the return value of the eval { } block instead of $@, and remove the extra new line when writing the error in $@. 17. maketext: Added an example at the DESCRIPTION chapter of the POD documentation. 18. Gettext.pm: Added a note on the relation of fail_with() die_for_lookup_failures() at the description of the die_for_lookup_failures() method at the METHODS section of the POD documentation. 19. Makefile.PL: Added LICENSE attribute as "perl". 2007-03-28 version 1.20 Rewrite to follow the error handler design of Locale::Maketext, i.e. the fail_with() method, instead of our own. Clean up encoding mess. You may need to check if your application was depending on the previous wrong, hard-to-handle behavior on look up failures. The new behavior should be easier to deal with. 1. Gettext.pm: In the textdomain() function, make sure {"ENCODING"} is not set to undef when MO file does not exists. 2. Functions.pm: In the encoding() function, removed a piece of long gone, commented code. 3. Gettext.pm and Functions.pm: In the encoding(), textdomain() and the _get_handle() function, add a flag {"ENCODING_SET"} to tag if we should respect the encoding() setting of the user. If there is no user preferred encoding(), when obtaining language handle with _get_handle() or textdomain(), encoding() will change to the output encoding() to that of the corresponding MO file. 4. 09-f-encoding.t: Added "delete $VARS{"ENCODING_SET"}" in the end of each test to clean up the environment. 5. Gettext.pm: Update the version number to 1.20. 6. Functions.pm: Update the version number to 0.10. 7. t/99-pod.t: Added. 8. Makefile.PL: Stylish clean-up and update. Added "SIGN". 9. Build.PL: Added. 2007-03-27 1. Gettext.pm: Added _lmg_failure_handler_auto(), as a replacement of Locale::Maketext's failure_handler_auto(). Locale::Maketext's failure_handler_auto() until version 1.10 has problem with message keys without any brackets. See bug#33938 on rt.cpan.org. It's content was simply copied from failure_handler_auto(). 2. Gettext.pm: Removed classes Locale::Maketext::Gettext::_AUTO, Locale::Maketext::Gettext::_AUTO::i_default, Locale::Maketext::Gettext::_EMPTY and Locale::Maketext::Gettext::_EMPTY::i_default. We are using Locale::Maketext's fail_with() method to deal with look up errors rather than making dummy language handles and deal with them by ourselves. This simplify things, making the code more compatible with Locale::Maketext. As a result, Locale::Maketext's fail_with() method and {"fail"} attribute are working now. 3. Gettext.pm: In the maketext() method, removed the code that deal with look up errors by ourselves. Now we handle this with the {"fail"} attribute and the _lmg_failure_handler_auto() method, following the original Locale::Maketext's design. 4. Gettext.pm: In the textdomain() method, added clear_isa_scan() in the end to clear the ISA handler look up cache table. This way we are not affected by the cache of _lmg_failure_handler_auto() when switching domain with textdomain(). 5. Gettext.pm and Functions.pm: In encoding() and key_encoding(), feeding undef delete the property. This is to unify the practice of "exists" and "defined" tests. All tests should use "exists" instead of "defined" now. 6. Functions.pm: Added classes Locale::Maketext::Gettext::Functions::_EMPTY and Locale::Maketext::Gettext::Functions::_EMPTY::i_default as a dummy locale. 7. Functions.pm: Add _get_empty_handle() to return the dummy locale, with die_for_lookup_failures() properly set. This replaces the $_EMPTY setting in the beginning of the file. 8. Functions.pm: In the _get_handle() method added unset the key_encoding() before returning the language handle. key_encoding() is handled by Locale::Maketext::Gettext::Functions. Locale::Maketext::Gettext does not need to handle key_encoding(). This is to follow the nature of functional API that key_encoding() should apply to all the following session in functional API. 9. Gettext.pm and Functions.pm: In maketext(), stop playing magic with encoding() and key_encoding() that automatically encode() text back to key_encoding() when lookup fails. The result is too unpredictable. The application should specify which encoding they want themselves. 2007-03-22 version 1.18 Fixes for Perl 5.9. Locale::Maketext in Perl 5.9 does not set $@ as its error message. Tests replying on $@ may fail for this. But I should check the return value of the eval{} block rather than $@ anyway. 1. t/*.t: Addition of $r as the return value of the eval{} blocks. Addition of "return 1;" to the eval{} blocks to specify the return values. Changing tests "ok($@, "");" to "ok($r, 1);". Changing tests "ok($@, qr/maketext doesn't know how to say/);" and "ok($@, qr/does not map to/);" to "ok($r, undef)". This is to be refined. It is necessary to test if it fails by our expected reason rather than only knowing that it fails. 2. Update the version number of Locale::Maketext::Gettext to match the distribution version. 2005-04-27 version 1.17 1. Changes: Typo fixed. 2005-04-26 version 1.16 Test suite fixes. 1. 02-big-endian.t: In test 7, 8, $MOfile and $POfile are quoted when sending to the shell (backticks), to be safe to spaces and other special shell characters in their paths. 2. 11-command-line.t: In all tests $maketext is quoted when sending to the shell (backticks), to be safe to spaces and other special shell characters in its path. This should solve the CPAN tester failures 200029, 200332 and 200331. Thanks to Max Maischein for testing and reporting this. 3. Changes: File edited to widen line limit from 60 columns to 79 columns, to ease the reading. 4. THANKS: Updated. 2005-04-26 version 1.15 1. SIGNATURE: Included Modules::Signature gpg signature file added. 2. 00-signature.t: Added. 2005-04-21 version 1.14 1. maketext: Prototypes of the following subroutines are declared first now: main() and parse_args(). 2005-04-20 version 1.13 1. Changes: Addition of new unencoded UTF-8 tests is appended to the change log. 2. Changes: Addition of warning of key_encoding() is appended to the change log. 3. Changes: Typo fixed: "Vesion" should be "Version". 4. Changes: Typo fixed: 2005-04-10 should be 2005-04-20. 2005-04-20 version 1.12 Documentation fixes. 1. Update the copyright year on the updated files. 2. Changes: Version number added. 2005-04-19 version 1.11 1. Gettext.pm: Using undef as encoding or key_encoding. Methods encoding() and key_encoding() now check the number of arguments instead of the argument value. When undef, the unencoded UTF-8 text is returned. 2. Gettext.pm: Prototype of subroutine read_mo() is declared first now. 3. Gettext.pm: Deprecated subroutine readmo() is removed. 4. Functions.pm: Prototypes of the following subroutines are declared first now: bindtextdomain(), textdomain(), get_handle(), maketext(), __(), N_(), dmaketext(), reload_text(), encoding(), key_encoding(), encode_failure(), die_for_lookup_failures(), _declare_class(), _catclass(), _init_textdomain(), _get_langs(), _get_handle(), _reset(), _new_rid(), _k() and _lang(). 5. 07-f-basic.t: Locale environment variables are cleared before running tests, to avoid confusion from the user's current locale. 6. 10-f-switching.t: Locale environment variables are cleared before running tests, to avoid confusion from the user's current locale. 7. Gettext.pm: Default KEY_ENCODING to US-ASCII. It is always decoded to UTF-8 first when looked up in the _AUTO lexicon, to ensure that the resulted text is always in UTF-8. 8. Gettext.pm: Avoid caching undefined MO file encoding when MO file is not available. 9. Gettext.pm: New attribute "MO_ENCODING" is added to to record the encoding of the MO file. 10. Functions.pm: Default KEY_ENCODING to US-ASCII. It is always decoded to UTF-8 first when looked up in the _AUTO lexicon, to ensure that the resulted text is always in UTF-8. 11. 04-encodings.t: Tests 28-33 added to test returning unencoded UTF-8 text. 12. 09-f-encodings.t: Tests 28-33 added to test returning unencoded UTF-8 text. 13. Gettext.pm: Warning is added to the use of key_encoding(). 14. Functions.pm: Warning is added to the use of key_encoding(). 2005-04-05 1. Gettext.pm: Subroutine attribute "method" is tagged on the following methods: encoding(), key_encoding(), new(), subclass_init(), bindtextdomain(), textdomain(), maketext(), reload_text(), die_for_lookup_failures() and encode_failure(). 2003-05-12 1. Gettext.pm: key_encoding applied to "not found" keys only, so that it can be looked up in their original encoding in the %Lexicon. 2003-05-09 version 1.10 1. Functions.pm: _get_handle: Fallback language handler changed from the failed language handler $FLH to the empty lexicon $_EMPTY. This has no real effect, since lookup failures are always handled by $FLH, but not the current language handler $LH. But this matches the reality. 2003-05-08 1. Changes: typo (version 1.07 should be version 1.09) 2003-05-07 1. Changes: An excess blank line is removed. 2003-05-07 version 1.09 Test suite fix. 1. 02-big-endian.t: Fix on $MSGFMT so that it works on more platforms. 2003-05-07 version 1.08 Fixes mistakes from version 1.07 1. Return the interpreter line to the maketext script. It was a misunderstanding at 1.07 2. Content-Transfer-Encoding is fixed from 8bit to 7bit in the English MO files. 3. t/test_native.po: Added. 4. 02-big-endian.t: Test suite for native-built MO files are added. Please report your failures. 2003-05-05 version 1.07 Bug fixes. 1. Fix to the interpreter line in the maketext script so that it can be replaced with correct interpreter at make time. 2. 11-command-line.t: script location changed from lib/maketext to blib/script/maketext. 3. C locale is added to the test suite. 4. 11-command-line.t: Locales en, zh_TW, zh_CN are remove from the test suite, to avoid perl warnings from systems that did not install these locales. 5. 11-command-line.t: $ENV{"LANGUAGE"} controls added. 2003-05-04 version 1.06 1. Language function override is not available for L::M::G::F and the maketext script. I almost forgot this problem. Notice is added to the documentation. Suggestions are welcome. 2003-05-03 version 1.06 Introducing "maketext", a command line interface to Locale::Maketext::Gettext (and Locale::Maketext). 1. The maketext script is added, a command line interface to Locale::Maketext::Gettext (and Locale::Maketext). 2003-05-03 version 1.05 Test suites fixes. This fixes the failures reported from CPAN testers. Failures reported from CPAN testers are caused by Archive-Tar called by CPANPLUS, but not by Locale::Maketext::Gettext itself. Bug report concerning this problem is already submitted to Archive-Tar. 1. Test suite temporarily files test_dyn.mo are removed from MANIFEST. 2. File::Copy is used instead of link in the test suites to enable tests on platforms that does not support hard links (Win32, for example). 3. Temporarily files are cleaned up at the end of 05-switching.t and 10-f-switching.t. Upgrade is not required if you are using version 1.04. 2003-05-02 version 1.04 1. Support for MO files without encoding specified was added. I don't know there are MO files born without its encoding. ^^; 2. L::M::G::F: textdomain() now works for default system locale directories, too. For domains that are not bound with bindtextdomain(), it searches the system locale directories to find the domain MO files. Unlike textdomain() in L::M::G, it remembers the search result in order to build the index key. 3. Tests for default system locale directory search are added. It may be skipped, though. 2003-05-02 version 1.03 1. L::M::G: A algorithm bug about key_encoding with auto-lexicon was fixed. 2. L::M::G::F: I decide to give up mod_perl safety for encoding, key_encoding, encode_failure and die_for_lookup_failures(). POSIX::setlocale() didn't solve this problem, either. Use L::M::G if you need that. Suggestions and solutions are welcome. 3. L::M::G: FLH (Failure language handler) is added to help switching the die_for_lookup_failures() setting. Maketext can be slightly faster. 2003-05-01 Labor's Day! A Major rewrite to Locale::Maketext::Gettext::Functions. 1. Packages are declared by a random class ID, instead of by its text domain previously, in order for a text domain to be redeclared with different sets of languages infinitely. This solves the problem where languages cannot to be removed at run-time. You can add/remove languages/MO files at run time now. You can also bindtextdomain() to another directory after setting textdomain(). This is not possible to the object interface of Locale::Maketext::Gettext (and Locale::Maketext). 2. fork_and_test is removed from the test suite. It does not seem to be required by the current random class ID system anymore. 3. The used of ($t1..$t6) is replaced by ($_[0]..$_[5]) in to 05-switching.t. 4. Garbage collection is added. Language handles associated with abandoned localization classes are dropped in time, in order to reduce memory used. 2003-04-30 1. L::M::G::F: I forgot to document dmaketext, too. ^^; But, no, I will not put a third release today! 2. L::M::G::F: Fixes to documentation typos. 3. maketext() and __() are exchanged. maketext() is a wrapper to __() now. The speed of __() should be slightly faster. 2003-04-30 version 1.02 Documentation fixes. 1. L::M::G::F: Documentation fixes. get_handle was not included in the documentation. ^^; I forgot to put it in. 2. README was updated. L::M::G::F is included in the README. Also, the installation procedure is updated, too. I forgot to update it last time. 2003-04-30 version 1.01 Improvements to Locale::Maketext::Gettext::Functions. 1. L::M::G::F: Documentation fixes. Lots of errors sit there in the previous documentation. It's impossible to work if you follow the previous documentation. ^^; Ha ha... 2. L::M::G: Map the language i-default to the locale C. 3. L::M::G::F: Map the locale C to the language i-default. 4. fork_and_test is added to the test suite to test without polluting the package space. It is slow, though. ^^; 5. L::M::G::F: Several test suites are added. 6. L::M::G::F: Error tolerance is largely improved. 7. L::M::G: New method subclass_init() is added. Object initialization is moved from the new method to the subclass_init() method, so that another subclass may inherit it further. 8. L::M::G::F: The "experimental" warning is removed. Large amount of errors can be handled gracefully now. 2003-04-28 1. TestPkg/L10N.pm is renamed as T_L10N.pm. It is neater. A TestPkg/ subdirectory is not necessary. 2. Change log is fixed. I forgot to put the version number 0.07. 3. Also, the version number should become 1.00, for the joining of Locale::Maketext::Gettext::Functions. ^_*' 2003-04-28 version 0.07 (1.00) Introducing Locale::Maketext::Gettext::Functions, a functional interface to Locale::Maketext::Gettext. 1. The first Locale::Maketext::Gettext::Functions is out. It works! ^_*' But it is still experimental. It cannot deal with real world problems still. ^^; 2. Documentation was fixed so that it is neater. 2003-04-27 1. The name of the _AUTO lexicon package is shorten to Locale::Maketext::Gettext::_AUTO. 2. Documentation rearrange. 2003-04-27 version 0.06 Improvements. 1. textdomain() works for default system locale directories now. For domains that are not bound with bindtextdomain(), it searches the system locale directories to find the MO file. No test suite is available for this functionality. I cannot predict what MO files are available in your system locale directories. ^^; Please report bugs if it does not work. 2. Slave package Locale::Maketext::Gettext::_AUTO::L10N is added, in order to process the _AUTO Lexicon separately. This saves resources when user change the die_for_lookup_failures() setting. Changing die_for_lookup_failures() setting won't trigger copying and replacing your whole %Lexicon anymore. As an effect, the cached compiled result of the _AUTO lexicon is preserved and the compilation overhead from Locale::Maketext is greatly reduced. 3. read_mo() is added to retire the readmo(). Use of readmo() is deprecated. This idea is inspired by the implementation of readmo() as "parse_mo" in Locale::Maketext::Lexicon by Autrijus. There is far too much meta information to be returned other than its encoding. It's not possible to change the API for each new requirement. To enable sharing of the algorithm used in read_mo() with whoever need it, it's necessary to limit its function to read and return the raw data, leaving all the other jobs to its caller. 4. For the same reason, caching control is removed from read_mo(), too. read_mo() read the MO file and return the %Lexicon only. It really reads. Nothing more. ^_*' 2003-04-27 version 0.05 Bug and documentation fixes. 1. New method key_encoding was added. The _AUTO lexicon is itself not multibyte-safe. You can specify the encoding of your keys if you are using non-ASCII keys. This is not a solution, but a workaround. 2. New method encode_failure was added. The default action when encode fails changed from FB_CROAK to FB_DEFAULT. I have changed my mind. GNU gettext never fails. 3. The paragraph about Locale::Maketext::Lexicon at the NOTES section in the documentation is updated. The paragraph about msgunfmt is removed. 4. The README file was updated. 5. The strange line "exists ${"$class\::Lexicon"}{$key};" is removed. That problem seems to be solved. It is not required anymore. 2003-04-25 version 0.04 Documentation fixes. Upgrade is not required if you are using version 0.03. 2003-04-25 version 0.03 Bug fixes. 1. Fixed clashing of the die_for_lookup_failures() setting from multiple instances. 2. Change log is rewritten, to my own format. 3. A new racing test suite is added. The old racing test suite was renamed as t-switching. 4. Redundant initialization of $LH->{"LOCALEDIRS"} in bindtextdomain() is removed. 5. An old line at die_for_lookup_failures() which initialize a wrong $LH->{"LOCALE"} is removed. 6. Removed 2 incorrect notice in the documentation. There will not be infinite loops for bindtextdomain() and textdomain(), whatever value it takes. Apparently I had made a mistake. ^^; 7. Several typos in the comments are fixed. 8. Sanity checks to the MO file is moved into readmo(). Cache now has a higher precedence than the sanity checks, which conforms with the global design. 9. More documentation was added to the SYNOPSIS. 10. Sanity checks for whether a method is invoked as a static method are added. Maketext use static variables. We should not clash them. 11. As a result of the above, the maketext method is no more static. It is an instance method, meaning that MyPkg::L10N::en->maketext does not work anymore. 12. Instance lexicon is initialized in the new method. I almost forgot it. Thanks to the test suite. :p 2003-04-25 version 0.02 Class/object design fixes. 1. I did tell the difference from class variables to instance variables. Forgive me, I had no experience with object-oriented programming at all, not even OO for perl. :p Just a few Java books. Anyway, the problem with clashing class variables is fixed. Most class variables are moved into instance variables. 2. Solved the default output encoding problem by using the encoding of the MO file as the default encoding. 3. reload_text method is added to purge the MO file cache, so that applications do not need to be restarted when their MO file updates. 4. MO files of different byte orders are supported now. Big-endian MO files support is added. 5. die_for_lookup_failures() method was added. The default behavior changed to "never fails", as GNU gettext does. 6. A test suite is added. 2003-04-24 version 0.01 Locale-Maketext-Gettext-1.32/MANIFEST000444001750000144 165014010010654 17075 0ustar00imacatusers000000000000Artistic Build.PL Changes lib/Locale/Maketext/Gettext.pm lib/Locale/Maketext/Gettext/Functions.pm Makefile.PL MANIFEST This list of files MANIFEST.SKIP META.json META.yml README.md script/maketext t/00-signature.t t/01-basic.t t/02-big-endian.t t/03-errors.t t/04-encodings.t t/05-switching.t t/06-racing.t t/07-f-basic.t t/08-f-errors.t t/09-f-encodings.t t/10-f-switching.t t/11-command-line.t t/12-cache.t t/99-pod.t t/locale/C/LC_MESSAGES/test.mo t/locale/en/LC_MESSAGES/bad.mo t/locale/en/LC_MESSAGES/test.mo t/locale/en/LC_MESSAGES/test2.mo t/locale/en/LC_MESSAGES/test_be.mo t/locale/en/LC_MESSAGES/test_utf8.mo t/locale/zh_CN/LC_MESSAGES/test.mo t/locale/zh_CN/LC_MESSAGES/test_be.mo t/locale/zh_CN/LC_MESSAGES/test_utf8.mo t/locale/zh_TW/LC_MESSAGES/test.mo t/locale/zh_TW/LC_MESSAGES/test2.mo t/locale/zh_TW/LC_MESSAGES/test_be.mo t/locale/zh_TW/LC_MESSAGES/test_utf8.mo t/T_L10N.pm SIGNATURE Added here by Module::Build Locale-Maketext-Gettext-1.32/MANIFEST.SKIP000444001750000144 24314010010654 17617 0ustar00imacatusers000000000000^blib/ ^Makefile$ ^Makefile\.old$ ^Build$ ^_build/ ^MANIFEST\.bak$ ^MYMETA\.yml$ ^MYMETA\.json$ ^SIGNATURE$ ^pm_to_blib$ ^\.git/ ^\.gitignore$ ^\.idea/ ^excludes/ Locale-Maketext-Gettext-1.32/META.json000444001750000144 272714010010654 17373 0ustar00imacatusers000000000000{ "abstract" : "Joins gettext and Maketext frameworks", "author" : [ "imacat " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4224", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Locale-Maketext-Gettext", "prereqs" : { "configure" : { "requires" : { "Module::Build" : "0.42" } }, "runtime" : { "requires" : { "perl" : "v5.8.0" } } }, "provides" : { "Locale::Maketext::Gettext" : { "file" : "lib/Locale/Maketext/Gettext.pm", "version" : "1.32" }, "Locale::Maketext::Gettext::Functions" : { "file" : "lib/Locale/Maketext/Gettext/Functions.pm", "version" : "0.14" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/imacat/Locale-Maketext-Gettext/issues" }, "homepage" : "https://metacpan.org/release/Locale-Maketext-Gettext", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "git://github.com/imacat/Locale-Maketext-Gettext.git", "web" : "https://github.com/imacat/Locale-Maketext-Gettext" } }, "version" : "1.32", "x_serialization_backend" : "JSON::PP version 2.97001" } Locale-Maketext-Gettext-1.32/META.yml000444001750000144 171014010010654 17212 0ustar00imacatusers000000000000--- abstract: 'Joins gettext and Maketext frameworks' author: - 'imacat ' build_requires: {} configure_requires: Module::Build: '0.42' dynamic_config: 1 generated_by: 'Module::Build version 0.4224, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Locale-Maketext-Gettext provides: Locale::Maketext::Gettext: file: lib/Locale/Maketext/Gettext.pm version: '1.32' Locale::Maketext::Gettext::Functions: file: lib/Locale/Maketext/Gettext/Functions.pm version: '0.14' requires: perl: v5.8.0 resources: bugtracker: https://github.com/imacat/Locale-Maketext-Gettext/issues homepage: https://metacpan.org/release/Locale-Maketext-Gettext license: http://dev.perl.org/licenses/ repository: git://github.com/imacat/Locale-Maketext-Gettext.git version: '1.32' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Locale-Maketext-Gettext-1.32/Makefile.PL000555001750000144 225014010010654 17716 0ustar00imacatusers000000000000#! /usr/bin/perl -w require 5.008; use strict; use warnings FATAL => 'all'; use ExtUtils::MakeMaker; WriteMakefile( NAME => "Locale::Maketext::Gettext", VERSION => "1.32", ABSTRACT => "Joins gettext and Maketext frameworks", AUTHOR => "imacat ", PREREQ_PM => { }, LICENSE => "perl", SIGN => 1, EXE_FILES => [ "script/maketext" ], dist => { COMPRESS => "gzip -9", SUFFIX => ".gz", }, clean => { FILES => "t/test_native.po t/locale/en/LC_MESSAGES/test_native.mo", }, META_MERGE => { "meta-spec" => { version => 2 }, resources => { homepage => "https://metacpan.org/release/Locale-Maketext-Gettext", repository => { type => "git", url => "git://github.com/imacat/Locale-Maketext-Gettext.git", web => "https://github.com/imacat/Locale-Maketext-Gettext", }, bugtracker => { "web" => "https://github.com/imacat/Locale-Maketext-Gettext/issues" } }, }, ); __END__ Locale-Maketext-Gettext-1.32/README.md000444001750000144 1700414010010654 17243 0ustar00imacatusers000000000000Locale::Maketext::Gettext - Joins the gettext and Maketext frameworks ===================================================================== Locale::Maketext::Gettext joins the [GNU gettext] and [Maketext] frameworks. It is a subclass of Locale::Maketext that follows the way GNU gettext works. It works seamlessly, both in the sense of GNU gettext and Maketext. As a result, you enjoy both their advantages, and get rid of both their problems, too. You start as a usual GNU gettext localization project: Work on PO files with the help of translators, reviewers and Emacs. Turn them into MO files with `msgfmt`. Copy them into the appropriate locale directory, such as `/usr/share/locale/de/LC_MESSAGES/myapp.mo`. Then, build your Maketext localization class, with your base class changed from Locale::Maketext to Locale::Maketext::Gettext. That's all. ^_*' [GNU gettext]: https://www.gnu.org/software/gettext/ [Maketext]: https://perldoc.perl.org/Locale::Maketext Locale::Maketext::Gettext::Functions ------------------------------------ Locale::Maketext::Gettext::Functions is a functional interface to Locale::Maketext::Gettext (and Locale::Maketext). It works completely the GNU gettext way. It plays magic to Locale::Maketext. No more localization class/subclasses and language handles are required. The `maketext` script --------------------- The `maketext` script is a command-line interface to Locale::Maketext::Gettext (and Locale::Maketext). It can be used in shell scripts, etc, to translate, maketext and return the result. It enables Maketext to be integrated into other programming languages/systems, like bash/csh, python, PHP, C, etc. It works like the command-line program `gettext`. System Requirements ------------------- 1. Perl, version 5.8.0 or above. Locale::Maketext::Gettext uses the utf8 text internally that is only available since 5.8.0. You can run `perl -v` to see your current Perl version. If you don't have Perl, or if you have an older version of Perl, you can download and install/upgrade it from the [Perl website]. If you are using MS-Windows, you can download and install [ActiveState ActivePerl]. 2. Required Perl modules: None. 3. Optional Perl modules: None. [Perl website]: https://www.perl.org [ActiveState ActivePerl]: https://www.activestate.com Download -------- Locale::Maketext::Gettext is hosted is on… * [Locale-Maketext-Gettext on GitHub] * [Locale-Maketext-Gettext on MetaCPAN] [Locale-Maketext-Gettext on GitHub]: https://github.com/imacat/Locale-Maketext-Gettext [Locale-Maketext-Gettext on MetaCPAN]: https://metacpan.org/release/Locale-Maketext-Gettext Install ------- ### Install with [ExtUtils::MakeMaker] Locale-Maketext-Gettext uses standard Perl installation with ExtUtils::MakeMaker. Follow these steps: % perl Makefile.PL % make % make test % make install When running `make install`, make sure you have the privilege to write to the installation location. This usually requires the `root` privilege. If you are using ActivePerl under MS-Windows, you should use `nmake` instead of `make`. [nmake can be obtained from the Microsoft FTP site.] If you want to install into another location, you can set the `PREFIX`. For example, to install into your home when you are not `root`: % perl Makefile.PL PREFIX=/home/jessica Refer to the documentation of ExtUtils::MakeMaker for more installation options (by running `perldoc ExtUtils::MakeMaker`). ### Install with [Module::Build] You can install with Module::Build instead, if you prefer. Follow these steps: % perl Build.PL % ./Build % ./Build test % ./Build install When running `./Build install`, make sure you have the privilege to write to the installation location. This usually requires the `root` privilege. If you want to install into another location, you can set the `--prefix`. For example, to install into your home when you are not ``root``: % perl Build.PL --prefix=/home/jessica Refer to the documentation of Module::Build for more installation options (by running `perldoc Module::Build`). ### Install with the CPAN Shell You can install with the CPAN shell, if you prefer. CPAN shell takes care of ExtUtils::MakeMaker and Module::Build for you: % cpan Locale::Maketext::Gettext Make sure you have the privilege to write to the installation location. This usually requires the `root` privilege. Since CPAN shell 1.81 you can set `make_install_make_command` and `mbuild_install_build_command` in your CPAN configuration to switch to `root` just before install: % cpan cpan> o conf make_install_make_command "sudo make" cpan> o conf mbuild_install_build_command "sudo ./Build" cpan> install Locale::Maketext::Gettext If you want to install into another location, you can set `makepl_arg` and `mbuild_arg` in your CPAN configuration. For example, to install into your home when you are not `root`: % cpan cpan> o conf makepl_arg "PREFIX=/home/jessica" cpan> o conf mbuild_arg "--prefix=/home/jessica" cpan> install Locale::Maketext::Gettext Refer to the documentation of cpan for more CPAN shell commands (by running `perldoc cpan`). ### Install with the CPANPLUS Shell You can install with the CPANPLUS shell, if you prefer. CPANPLUS shell takes care of ExtUtils::MakeMaker and Module::Build for you: % cpanp -i Locale::Maketext::Gettext Make sure you have the privilege to write to the installation location. This usually requires the `root` privilege. If you want to install into another location, you can set `makemakerflags` and `buildflags` in your CPANPLUS configuration. For example, to install into your home when you are not `root`: % cpanp CPAN Terminal> s conf makemakerflags "PREFIX=/home/jessica" CPAN Terminal> s conf buildflags "--prefix=/home/jessica" CPAN Terminal> install Locale::Maketext::Gettext Refer to the documentation of `cpanp` for more CPANPLUS shell commands (by running `perldoc cpanp`). [ExtUtils::MakeMaker]: https://metacpan.org/release/ExtUtils-MakeMaker [nmake can be obtained from the Microsoft FTP site.]: ftp://ftp.microsoft.com/Softlib/MSLFILES/nmake15.exe [Module::Build]: https://metacpan.org/release/Module-Build Source ------ Source is now on Github. See https://github.com/imacat/Locale-Maketext-Gettext. Support ------- The Locale-Maketext-Gettext project is hosted on GitHub. Address your issues on the GitHub issue tracker https://github.com/imacat/Locale-Maketext-Gettext/issues. News, Changes and Updates ------------------------- Refer to the Changes for changes, bug fixes, updates, new functions, etc. Thanks ------ * Thanks to [Max Maischein] for reporting CPAN tester failures 200029, 200332 and 200331, that helps me find the shell character escape problem on my test suite. * Thanks to [Andreas Koenig] for reporting CPAN tester failures 387357 and submitting [rt bug 23956], informing me the base class Locale::Maketext has updated its error handling behavior in the Perl 5.9. * Thanks to [Chris Travers] for suggestion to implement `pgettext()` in GNU gettext as `pmaketext()`. [Max Maischein]: mailto:corion@corion.net [Andreas Koenig]: mailto:andk@cpan.org [rt bug 23956]: https://rt.cpan.org/Public/Bug/Display.html?id=23956 [Chris Travers]: mailto:chris.travers@gmail.com To Do ----- * Design a way to install the MO file through ExtUtils::MakeMaker and Module::Build. Copyright --------- Copyright (c) 2003-2021 imacat. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Locale-Maketext-Gettext-1.32/SIGNATURE000644001750000144 1060314010010654 17250 0ustar00imacatusers000000000000This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.83. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA256 b7fd9b73ea99602016a326e0b62e6646060d18febdd065ceca8bb482208c3d88 Artistic SHA256 ec27c91168de6ad03d0a2c95d7785400ce001bf345aebc08fd36cc23dea0e9f0 Build.PL SHA256 d5602ddc0e947a29e0f621496532fabb401bf7c3b2e89fc237de6cef0aef78a4 Changes SHA256 7c8b68fc5c6960701aea954484d00047a97a6d74540dbdee6b5a8744d255a4c8 MANIFEST SHA256 c957c3df311e2b98908c3f4c2d6967eb1eaa05a011af5dfe70a1be57c46f7504 MANIFEST.SKIP SHA256 fc8fcf4faa025e9b1b1d0d4a070ec04e586276be576bf835c2e32edb2abea788 META.json SHA256 bc509400a8098362bbce9e39141655818ed507f1796e99ba48d610a863574c4b META.yml SHA256 13840407488c43f9a793cbe332bf4ddf3571f393bf858a96297481bbf4ec71fb Makefile.PL SHA256 4f8f96228e663e03598d0c31350fd57b261c3ce838a9b08314d0c64705bf43e3 README.md SHA256 5b26a6ccac9c6195fcb565bd5ebac9f5b0b0820edc145c43ae3b239415b5d8fd lib/Locale/Maketext/Gettext.pm SHA256 aa44e1b2abb45855c9d366d76bea49bf4d9baf488f7c3c7f908278b4b1f95361 lib/Locale/Maketext/Gettext/Functions.pm SHA256 aa9812947f1a1e780ffccd5226a205fc3edabbf369799e733276f896133f83ac script/maketext SHA256 1153bcbc36976012b03dfc052bc26d7f8cb4ad8968434ef54139c06f48dad7f4 t/00-signature.t SHA256 5c53531732015047cb7abecb62776d7433d1ba5c203678a3916d7831a298c80c t/01-basic.t SHA256 81f69a3b538342d4f4fb88b3b5af90952a56a5d4a6f5b0f46d0b18908f7ab085 t/02-big-endian.t SHA256 9b1eaffcb01ee9b74fdce2bfd213e7b1fe6e78eafc5eda68d5d3e10fda2452cd t/03-errors.t SHA256 1bd874e88d181d25836067492f2d5b0dd4497423a08592014c2593a4370e596c t/04-encodings.t SHA256 74ae92180bad65f4aec1c14d8150d7f0c4546f7489647cdef99d51c2aac5d3cf t/05-switching.t SHA256 e51ef8f6c79fa50db8b60cf1e748e72a0cd2fbe6e239e267f64ee201ea3f6f99 t/06-racing.t SHA256 d4ef9bb37cd1358f3021aa5fc918d3e67da8a3e9d64e9991f42448c67d902203 t/07-f-basic.t SHA256 e1403fbdeb5997c2d619100fd61139fca7679c70a82e46aa86be9119388f6b33 t/08-f-errors.t SHA256 2fae2c278feb3367e729ca3f34a6246400b737ed05a3f9735c0b2e439e84defc t/09-f-encodings.t SHA256 5e3ec4d70133955afceb523555f0988abbad4b12c2bfdb100636c81d0b6d4f43 t/10-f-switching.t SHA256 5f54c3c72987271700fe07f59a823caf7d995ec593484734917e8fc75e4252a2 t/11-command-line.t SHA256 9719aa47817f5eb16833b1ecb38681303318916f7e28c3151a823ef2aea6ee61 t/12-cache.t SHA256 199347e5b382ea991a32513cdef2b45887ae3f3cd6610a2e7976e9a678423b04 t/99-pod.t SHA256 a6896a5a0033b68dd635c17609481ad042511c0ec9b951024e307bf32c215cd5 t/T_L10N.pm SHA256 ade5d2fd1cded6053165c83fe58d8d4f0e21034d27f21f2613332f9d998a6c9a t/locale/C/LC_MESSAGES/test.mo SHA256 134e6543ddc35b40abb4f2f8aaaa2d0513a27e267beaf9081e29d84eba94017d t/locale/en/LC_MESSAGES/bad.mo SHA256 ade5d2fd1cded6053165c83fe58d8d4f0e21034d27f21f2613332f9d998a6c9a t/locale/en/LC_MESSAGES/test.mo SHA256 d17abb30435054c3222dc777eb17bdfe4c520bca82f5a184fbb5d41e7b130da1 t/locale/en/LC_MESSAGES/test2.mo SHA256 942c2cf317892ec6555e69bf48ce05e5b4d496f80592bf27fb7d4d7c16e733ef t/locale/en/LC_MESSAGES/test_be.mo SHA256 e0ce0854dd2b50e7ba9a442aaeb70897df0848dcc80a86f38070abd857ea7713 t/locale/en/LC_MESSAGES/test_utf8.mo SHA256 69bd1be027d863809aa76878aeebd530068309642d8f9c1ec3831f4678de98c8 t/locale/zh_CN/LC_MESSAGES/test.mo SHA256 96e57c2fea26182cc4979c2d670d5672847e3f9d036e71cd893595260275eb74 t/locale/zh_CN/LC_MESSAGES/test_be.mo SHA256 2197525bb3eebdbb526b298d202b667888cac040150d9514283e4755d4315ed2 t/locale/zh_CN/LC_MESSAGES/test_utf8.mo SHA256 0624f1809bf815483062ee13bed2cb9810a48d123fc859746754476466ceb0d0 t/locale/zh_TW/LC_MESSAGES/test.mo SHA256 f59df5ca5a8e3c25b60141c46fb76aa1084e7b038e9550fc1828f909b11f9791 t/locale/zh_TW/LC_MESSAGES/test2.mo SHA256 b08fdcf10a88bd8306a91d7237d815e4f52e41d7f9c411c5d585422eed396b5e t/locale/zh_TW/LC_MESSAGES/test_be.mo SHA256 329b2e6a1cf5a30a2be39d6aaa86c498c471a30ebb31b151ec0fa779aed9dac1 t/locale/zh_TW/LC_MESSAGES/test_utf8.mo -----BEGIN PGP SIGNATURE----- iF0EARECAB0WIQSBin4eTeP7OclnnAOL2C5vMLlLXAUCYCARrAAKCRCL2C5vMLlL XDeeAJ4gDTJA+/M4+w1WyXDc5XPGQQY/kACfVDj2+g32fXHqgiVqOxPY2bJKGNw= =5hN7 -----END PGP SIGNATURE----- Locale-Maketext-Gettext-1.32/lib000755001750000144 014010010654 16353 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/lib/Locale000755001750000144 014010010654 17552 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/lib/Locale/Maketext000755001750000144 014010010654 21334 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/lib/Locale/Maketext/Gettext.pm000444001750000144 7042014010010654 23476 0ustar00imacatusers000000000000# Locale::Maketext::Gettext - Joins the gettext and Maketext frameworks # Copyright (c) 2003-2021 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. # First written: 2003/4/23 package Locale::Maketext::Gettext; use 5.008; use strict; use warnings; use base qw(Locale::Maketext Exporter); our ($VERSION, @EXPORT, @EXPORT_OK); $VERSION = 1.32; @EXPORT = qw(read_mo); @EXPORT_OK = @EXPORT; # Prototype declaration sub read_mo($); use Encode qw(encode decode FB_DEFAULT); use File::Spec::Functions qw(catfile); no strict qw(refs); our (%CACHE, $REREAD_MO, $MO_FILE); %CACHE = qw(); $REREAD_MO = 0; $MO_FILE = ""; our (@SYSTEM_LOCALEDIRS); @SYSTEM_LOCALEDIRS = qw(/usr/share/locale /usr/lib/locale /usr/local/share/locale /usr/local/lib/locale); # Set or retrieve the output encoding sub encoding : method { local ($_, %_); my $self; ($self, $_) = @_; # This is not a static method return if ref($self) eq ""; # Set the output encoding if (@_ > 1) { if (defined $_) { $self->{"ENCODING"} = $_; } else { delete $self->{"ENCODING"}; } $self->{"USERSET_ENCODING"} = $_; } # Return the encoding return exists $self->{"ENCODING"}? $self->{"ENCODING"}: undef; } # Specify the encoding used in the keys sub key_encoding : method { local ($_, %_); my $self; ($self, $_) = @_; # This is not a static method return if ref($self) eq ""; # Set the encoding used in the keys if (@_ > 1) { if (defined $_) { $self->{"KEY_ENCODING"} = $_; } else { delete $self->{"KEY_ENCODING"}; } } # Return the encoding return exists $self->{"KEY_ENCODING"}? $self->{"KEY_ENCODING"}: undef; } # Initialize the language handler sub new : method { local ($_, %_); my ($self, $class); $class = ref($_[0]) || $_[0]; $self = bless {}, $class; $self->subclass_init; $self->init; return $self; } # Initialize at the subclass level, so that it can be # inherited by calling $self->SUPER:subclass_init sub subclass_init : method { local ($_, %_); my ($self, $class); $self = $_[0]; $class = ref($self); # Initialize the instance lexicon $self->{"Lexicon"} = {}; # Initialize the LOCALEDIRS registry $self->{"LOCALEDIRS"} = {}; # Initialize the MO timestamp $self->{"REREAD_MO"} = $REREAD_MO; # Initialize the DIE_FOR_LOOKUP_FAILURES setting $self->{"DIE_FOR_LOOKUP_FAILURES"} = 0; $self->SUPER::fail_with($self->can("failure_handler_auto")); # Initialize the ENCODE_FAILURE setting $self->{"ENCODE_FAILURE"} = FB_DEFAULT; # Initialize the MO_FILE value of this instance $self->{"MO_FILE"} = ""; ${"$class\::MO_FILE"} = "" if !defined ${"$class\::MO_FILE"}; # Find the locale name, for this subclass $self->{"LOCALE"} = $class; $self->{"LOCALE"} =~ s/^.*:://; $self->{"LOCALE"} =~ s/(_)(.*)$/$1 . uc $2/e; # Map i_default to C $self->{"LOCALE"} = "C" if $self->{"LOCALE"} eq "i_default"; # Set the category. Currently this is always LC_MESSAGES $self->{"CATEGORY"} = "LC_MESSAGES"; # Default key encoding is US-ASCII $self->{"KEY_ENCODING"} = "US-ASCII"; return; } # Bind a text domain to a locale directory sub bindtextdomain : method { local ($_, %_); my ($self, $DOMAIN, $LOCALEDIR); ($self, $DOMAIN, $LOCALEDIR) = @_; # This is not a static method return if ref($self) eq ""; # Return null for this rare case return if !defined $LOCALEDIR && !exists ${$self->{"LOCALEDIRS"}}{$DOMAIN}; # Register the DOMAIN and its LOCALEDIR ${$self->{"LOCALEDIRS"}}{$DOMAIN} = $LOCALEDIR if defined $LOCALEDIR; # Return the registry return ${$self->{"LOCALEDIRS"}}{$DOMAIN}; } # Set the current text domain sub textdomain : method { local ($_, %_); my ($self, $class, $DOMAIN, $LOCALEDIR, $mo_file); ($self, $DOMAIN) = @_; # This is not a static method return if ref($self) eq ""; # Find the class name $class = ref($self); # Return the current domain return $self->{"DOMAIN"} if !defined $DOMAIN; # Set the timestamp of this read in this instance $self->{"REREAD_MO"} = $REREAD_MO; # Set the current domain $self->{"DOMAIN"} = $DOMAIN; # Clear it $self->{"Lexicon"} = {}; %{"$class\::Lexicon"} = qw(); $self->{"MO_FILE"} = ""; ${"$class\::MO_FILE"} = ""; # The format is "{LOCALEDIR}/{LOCALE}/{CATEGORY}/{DOMAIN}.mo" # Search the system locale directories if the domain was not # registered yet if (!exists ${$self->{"LOCALEDIRS"}}{$DOMAIN}) { undef $mo_file; foreach $LOCALEDIR (@SYSTEM_LOCALEDIRS) { $_ = catfile($LOCALEDIR, $self->{"LOCALE"}, $self->{"CATEGORY"}, "$DOMAIN.mo"); if (-f $_ && -r $_) { $mo_file = $_; last; } } # Not found at last return $DOMAIN if !defined $mo_file; # This domain was registered } else { $mo_file = catfile(${$self->{"LOCALEDIRS"}}{$DOMAIN}, $self->{"LOCALE"}, $self->{"CATEGORY"}, "$DOMAIN.mo"); } # Record it ${"$class\::MO_FILE"} = $mo_file; $self->{"MO_FILE"} = $mo_file; # Read the MO file # Cached if (!$self->_is_using_cache($mo_file)) { my ($enc, @stats, $mtime, $size); # Read it %_ = read_mo($mo_file); # Successfully read if (scalar(keys %_) > 0) { # Decode it # Find the encoding of that MO file if ($_{""} =~ /^Content-Type: text\/plain; charset=(.*)$/im) { $enc = $1; # Default to US-ASCII } else { $enc = "US-ASCII"; } # Set the current encoding to the encoding of the MO file $_{$_} = decode($enc, $_{$_}) foreach keys %_; } # Cache them @stats = stat $mo_file; if (@stats > 0) { ($mtime, $size) = @stats[9,7]; } else { ($mtime, $size) = (undef, undef); } $CACHE{$mo_file} = { "Lexicon" => {%_}, "encoding" => $enc, "mtime" => $mtime, "size" => $size, }; } # Respect the existing output encoding if (defined $CACHE{$mo_file}->{"encoding"}) { $self->{"MO_ENCODING"} = $CACHE{$mo_file}->{"encoding"}; } else { delete $self->{"MO_ENCODING"}; } # Respect the MO file encoding unless there is a user preference if (!exists $self->{"USERSET_ENCODING"}) { if (exists $self->{"MO_ENCODING"}) { $self->{"ENCODING"} = $self->{"MO_ENCODING"}; } else { delete $self->{"ENCODING"}; } } $self->{"Lexicon"} = $CACHE{$mo_file}->{"Lexicon"}; %{"$class\::Lexicon"} = %{$CACHE{$mo_file}->{"Lexicon"}}; $self->clear_isa_scan; return $DOMAIN; } # Return whether we are using our cache. sub _is_using_cache : method { local ($_, %_); my ($self, $mo_file, @stats, $mtime, $size); ($self, $mo_file) = @_; # NO if we do not have such a cache. return undef unless exists $CACHE{$mo_file}; @stats = stat $mo_file; # The MO file does not exist previously. if (!defined $CACHE{$mo_file}->{"mtime"} || !defined $CACHE{$mo_file}->{"size"}) { # Use the cache if the MO file still does not exist. return (@stats == 0); # The MO file exists previously. } else { # Use the cache if the MO file did not change. ($mtime, $size) = @stats[9,7]; return $mtime == $CACHE{$mo_file}->{"mtime"} && $size == $CACHE{$mo_file}->{"size"}; } } # Encode after maketext sub maketext : method { local ($_, %_); my ($self, $key, @param, $class, $keyd); ($self, $key, @param) = @_; # This is not a static method - NOW return if ref($self) eq ""; # Find the class name $class = ref($self); # MO file should be re-read if ($self->{"REREAD_MO"} < $REREAD_MO) { $self->{"REREAD_MO"} = $REREAD_MO; defined($_ = $self->textdomain) and $self->textdomain($_); } # If the instance lexicon is changed. # Maketext uses a class lexicon. We have to copy the instance # lexicon into the class lexicon. This is slow. Mass memory # copy sucks. Avoid create several language handles for a # single localization subclass whenever possible. # Maketext uses class lexicon in order to track the inheritance. # It is hard to change it. if (${"$class\::MO_FILE"} ne $self->{"MO_FILE"}) { ${"$class\::MO_FILE"} = $self->{"MO_FILE"}; %{"$class\::Lexicon"} = %{$self->{"Lexicon"}}; } # Decode the source text $keyd = $key; $keyd = decode($self->{"KEY_ENCODING"}, $keyd, $self->{"ENCODE_FAILURE"}) if exists $self->{"KEY_ENCODING"} && !Encode::is_utf8($key); # Maketext $_ = $self->SUPER::maketext($keyd, @param); # Output to the requested encoding if (exists $self->{"ENCODING"}) { $_ = encode($self->{"ENCODING"}, $_, $self->{"ENCODE_FAILURE"}); # Pass through the empty/invalid lexicon } elsif ( scalar(keys %{$self->{"Lexicon"}}) == 0 && exists $self->{"KEY_ENCODING"} && !Encode::is_utf8($key)) { $_ = encode($self->{"KEY_ENCODING"}, $_, $self->{"ENCODE_FAILURE"}); } return $_; } # Maketext with context sub pmaketext : method { local ($_, %_); my ($self, $context, $key, @param); ($self, $context, $key, @param) = @_; # This is not a static method - NOW return if ref($self) eq ""; # This is actually a wrapper to the maketext() method return $self->maketext("$context\x04$key", @param); } # Subroutine to read and parse the MO file # Refer to gettext documentation section 8.3 sub read_mo($) { local ($_, %_); my ($mo_file, $len, $FH, $content, $tmpl); $mo_file = $_[0]; # Avoid being stupid return unless -f $mo_file && -r $mo_file; # Read the MO file $len = (stat $mo_file)[7]; open $FH, $mo_file or return; # GNU gettext never fails! binmode $FH; defined($_ = read $FH, $content, $len) or return; close $FH or return; # Find the byte order of the MO file creator $_ = substr($content, 0, 4); # Little endian if ($_ eq "\xde\x12\x04\x95") { $tmpl = "V"; # Big endian } elsif ($_ eq "\x95\x04\x12\xde") { $tmpl = "N"; # Wrong magic number. Not a valid MO file. } else { return; } # Check the MO format revision number $_ = unpack $tmpl, substr($content, 4, 4); # There is only one revision now: revision 0. return if $_ > 0; my ($num, $offo, $offt); # Number of messages $num = unpack $tmpl, substr($content, 8, 4); # Offset to the beginning of the original messages $offo = unpack $tmpl, substr($content, 12, 4); # Offset to the beginning of the translated messages $offt = unpack $tmpl, substr($content, 16, 4); %_ = qw(); for ($_ = 0; $_ < $num; $_++) { my ($len, $off, $stro, $strt); # The first word is the length of the message $len = unpack $tmpl, substr($content, $offo+$_*8, 4); # The second word is the offset of the message $off = unpack $tmpl, substr($content, $offo+$_*8+4, 4); # Original message $stro = substr($content, $off, $len); # The first word is the length of the message $len = unpack $tmpl, substr($content, $offt+$_*8, 4); # The second word is the offset of the message $off = unpack $tmpl, substr($content, $offt+$_*8+4, 4); # Translated message $strt = substr($content, $off, $len); # Hash it $_{$stro} = $strt; } return %_; } # Method to purge the lexicon cache sub reload_text : method { local ($_, %_); # Purge the text cache %CACHE = qw(); $REREAD_MO = time; return; } # A wrapper to the fail_with() of Locale::Maketext, in order # to record the preferred failure handler of the user, so that # die_for_lookup_failures() knows where to return to. sub fail_with : method { local ($_, %_); my $self; ($self, $_) = @_; # This is not a static method return if ref($self) eq ""; # Set the current setting if (@_ > 1) { if (defined $_) { $self->{"USERSET_FAIL"} = $_; $self->SUPER::fail_with($_) if $self->{"DIE_FOR_LOOKUP_FAILURES"}; } else { delete $self->{"USERSET_FAIL"}; delete $self->{"fail"} if $self->{"DIE_FOR_LOOKUP_FAILURES"}; } } # Return the current setting return exists $self->{"USERSET_FAIL"}? $self->{"USERSET_FAIL"}: undef; } # Whether we should die for lookup failure # The default is no. GNU gettext never fails. sub die_for_lookup_failures : method { local ($_, %_); my $self; ($self, $_) = @_; # This is not a static method return if ref($self) eq ""; # Set the current setting if (@_ > 1) { if ($_) { $self->{"DIE_FOR_LOOKUP_FAILURES"} = 1; if (exists $self->{"USERSET_FAIL"}) { $self->{"fail"} = $self->{"USERSET_FAIL"}; } else { delete $self->{"fail"}; } } else { $self->SUPER::fail_with($self->can("failure_handler_auto")); $self->{"DIE_FOR_LOOKUP_FAILURES"} = 0; } } # Return the current setting return exists $self->{"DIE_FOR_LOOKUP_FAILURES"}? $self->{"DIE_FOR_LOOKUP_FAILURES"}: undef; } # What to do if the text is out of your output encoding # Refer to Encode on possible values of this check sub encode_failure : method { local ($_, %_); my $self; ($self, $_) = @_; # This is not a static method return if ref($self) eq ""; # Specify the action used in the keys $self->{"ENCODE_FAILURE"} = $_ if @_ > 1; # Return the encoding return $self->{"ENCODE_FAILURE"} if exists $self->{"ENCODE_FAILURE"}; return undef; } # Our local version of failure_handler_auto(), # Copied and rewritten from Locale::Maketext, with bug#33938 patch applied. # See https://github.com/Perl/perl5/issues/7767 sub failure_handler_auto : method { local ($_, %_); my ($self, $key, @param, $r); ($self, $key, @param) = @_; # This is not a static method return if ref($self) eq ""; # Remove the context # We assume there is no one using EOF either in the context or message. # That does not work in GNU gettext, anyway. $key =~ s/^[^\x04]*\x04//; $self->{"failure_lex"} = {} if !exists $self->{"failure_lex"}; ${$self->{"failure_lex"}}{$key} = $self->_compile($key) if !exists ${$self->{"failure_lex"}}{$key}; $_ = ${$self->{"failure_lex"}}{$key}; # A scalar result return $$_ if ref($_) eq "SCALAR"; return $_ unless ref($_) eq "CODE"; # A compiled subroutine { local $SIG{"__DIE__"}; $r = eval { $_ = &$_($self, @param); return 1; }; } # If we make it here, there was an exception thrown in the # call to $value, and so scream: if (!defined $r) { $_ = $@; # pretty up the error message s<\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?> <\n in bracket code [compiled line $1],>s; Carp::croak "Error in maketexting \"$key\":\n$_ as used"; } # OK return $_; } return 1; __END__ =head1 NAME Locale::Maketext::Gettext - Joins the gettext and Maketext frameworks =head1 SYNOPSIS In your localization class: package MyPackage::L10N; use base qw(Locale::Maketext::Gettext); return 1; In your application: use MyPackage::L10N; $LH = MyPackage::L10N->get_handle or die "What language?"; $LH->bindtextdomain("mypackage", "/home/user/locale"); $LH->textdomain("mypackage"); $LH->maketext("Hello, world!!"); If you want to have more control to the detail: # Change the output encoding $LH->encoding("UTF-8"); # Stick with the Maketext behavior on lookup failures $LH->die_for_lookup_failures(1); # Flush the MO file cache and re-read your updated MO files $LH->reload_text; # Set the encoding of your maketext keys, if not in English $LH->key_encoding("Big5"); # Set the action when encode fails $LH->encode_failure(Encode::FB_HTMLCREF); Use Locale::Maketext::Gettext to read and parse the MO file: use Locale::Maketext::Gettext; %Lexicon = read_mo($mo_file); =head1 DESCRIPTION Locale::Maketext::Gettext joins the GNU gettext and Maketext frameworks. It is a subclass of L that follows the way GNU gettext works. It works seamlessly, I. As a result, you I You start as a usual GNU gettext localization project: Work on PO files with the help of translators, reviewers and Emacs. Turn them into MO files with F. Copy them into the appropriate locale directory, such as F. Then, build your Maketext localization class, with your base class changed from L to Locale::Maketext::Gettext. That is all. =head1 METHODS =over =item $LH->bindtextdomain(DOMAIN, LOCALEDIR) Register a text domain with a locale directory. Returns C itself. If C is omitted, the registered locale directory of C is returned. This method always success. =item $LH->textdomain(DOMAIN) Set the current text domain. Returns the C itself. If C is omitted, the current text domain is returned. This method always success. =item $text = $LH->maketext($key, @param...) Lookup the $key in the current lexicon and return a translated message in the language of the user. This is the same method in L, with a wrapper that returns the text message Cd according to the current C. Refer to L for the maketext plural notation. =item $text = $LH->pmaketext($context, $key, @param...) Lookup the $key in a particular context in the current lexicon and return a translated message in the language of the user. Use "--keyword=pmaketext:1c,2" for the xgettext utility. =item $LH->language_tag Retrieve the language tag. This is the same method in L. It is readonly. =item $LH->encoding(ENCODING) Set or retrieve the output encoding. The default is the same encoding as the gettext MO file. You can specify C, to return the result in unencoded UTF-8. =item $LH->key_encoding(ENCODING) Specify the encoding used in your original text. The C method itself is not multibyte-safe to the _AUTO lexicon. If you are using your native non-English language as your original text and you are having troubles like: Unterminated bracket group, in: Then, specify the C to the encoding of your original text. Returns the current setting. B You should always use US-ASCII text keys. Using non-US-ASCII keys is always discouraged and is not guaranteed to be working. =item $LH->encode_failure(CHECK) Set the action when encode fails. This happens when the output text is out of the scope of your output encoding. For example, output Chinese into US-ASCII. Refer to L for the possible values of this C. The default is C, which is a safe choice that never fails. But part of your text may be lost, since that is what C does. Returns the current setting. =item $LH->die_for_lookup_failures(SHOULD_I_DIE) Maketext dies for lookup failures, but GNU gettext never fails. By default Lexicon::Maketext::Gettext follows the GNU gettext behavior. But if you are Maketext-styled, or if you need a better control over the failures (like me :p), set this to 1. Returns the current setting. Note that lookup failure handler you registered with fail_with() only work when die_for_lookup_failures() is enabled. if you disable die_for_lookup_failures(), maketext() never fails and lookup failure handler will be ignored. =item $LH->reload_text Purge the MO text cache. It purges the MO text cache from the base class Locale::Maketext::Gettext. The next time C is called, the MO file will be read and parse from the disk again. This is used when your MO file is updated, but you cannot shutdown and restart the application. For example, when you are a virtual host on a mod_perl-enabled Apache, or when your mod_perl-enabled Apache is too vital to be restarted for every update of your MO file, or if you are running a vital daemon, such as an X display server. =back =head1 FUNCTIONS =over =item %Lexicon = read_mo($mo_file); Read and parse the MO file. Returns the read %Lexicon. The returned lexicon is in its original encoding. If you need the meta information of your MO file, parse the entry C<$Lexicon{""}>. For example: /^Content-Type: text\/plain; charset=(.*)$/im; $encoding = $1; C is exported by default, but you need to C in order to use it. It is not exported from your localization class, but from the Locale::Maketext::Gettext package. =back =head1 NOTES B do not try to put any lexicon in your language subclass. When the C method is called, the current lexicon will be B, but not appended. This is to accommodate the way C works. Messages from the previous text domain should not stay in the current text domain. An essential benefit of this Locale::Maketext::Gettext over the original L is that: I but Perl source is not. GNU gettext is safe to Big5 characters like \xa5\x5c (Gong1). But if you follow the current L document and put your lexicon as a hash in the source of a localization subclass, you have to escape bytes like \x5c, \x40, \x5b, etc., in the middle of some natural multibyte characters. This breaks these characters in halves. Your non-technical translators and reviewers will be presented with unreadable mess, "Luan4Ma3". Sorry to say this, but it is weird for a localization framework to be not multibyte-safe. But, well, here comes Locale::Maketext::Gettext to rescue. With Locale::Maketext::Gettext, you can sit back and relax now, leaving all this mess to the excellent GNU gettext framework. The idea of Locale::Maketext::Gettext came from L, a great work by Autrijus. But it has several problems at that time (version 0.16). I was first trying to write a wrapper to fix it, but finally I dropped it and decided to make a solution towards L itself. L should be fine now if you obtain a version newer than 0.16. Locale::Maketext::Gettext also solved the problem of lack of the ability to handle the encoding in L. I implement this since this is what GNU gettext does. When %Lexicon is read from MO files by C, the encoding tagged in gettext MO files is used to C the text into the internal encoding of Perl. Then, when extracted by C, it is Cd by the current C value. The C can be set at run time, so that you can run a daemon and output to different encoding according to the language settings of individual users, without having to restart the application. This is an improvement to the L, and is essential to daemons and C applications. You should trust the encoding of your gettext MO file. GNU gettext C checks the illegal characters for you when you compile your MO file from your PO file. The encoding form your MO files are always good. If you try to output to a wrong encoding, part of your text may be lost, as C does. If you do not like this C, change the failure behavior with the method C. If you need the behavior of auto Traditional Chinese/Simplified Chinese conversion, as GNU gettext smartly does, do it yourself with L, too. There may be a solution for this in the future, but not now. If you set C to a domain that is not C to specific a locale directory yet, it will try search system locale directories. The current system locale directory search order is: /usr/share/locale, /usr/lib/locale, /usr/local/share/locale, /usr/local/lib/locale. Suggestions for this search order are welcome. B Imaketext(...) is not available anymore,> as the C method is no more static. That is a sure result, as %Lexicon is imported from foreign sources dynamically, but not statically hardcoded in Perl sources. But the documentation of L does not say that you can use it as a static method anyway. Maybe you were practicing this before. You had better check your existing code for this. If you try to invoke it statically, it returns C. C and C in GNU gettext are not implemented. It is not possible to temporarily change the current text domain in the current design of Locale::Maketext::Gettext. Besides, it is meaningless. Locale::Maketext is object-oriented. You can always raise a new language handle for another text domain. This is different from the situation of GNU gettext. Also, the category is always C. Of course it is. We are gettext and Maketext. Avoid creating different language handles with different textdomain on the same localization subclass. This currently works, but it violates the basic design of L. In L, %Lexicon is saved as a class variable, in order for the lexicon inheritance system to work. So, multiple language handles to a same localization subclass shares a same lexicon space. Their lexicon space clash. I tried to avoid this problem by saving a copy of the current lexicon as an instance variable, and replacing the class lexicon with the current instance lexicon whenever it is changed by another language handle instance. But this involves large scaled memory copy, which affects the performance seriously. This is discouraged. You are advised to use a single textdomain for a single localization class. The C is a workaround, not a solution. There is no solution to this problem yet. You should avoid using non-English language as your original text. You will get yourself into trouble if you mix several original text encodings, for example, joining several pieces of code from programmers all around the world, with their messages written in their own language and encodings. Solution suggestions are welcome. C in GNU gettext is implemented as C, in order to look up the text message translation in a particular context. Thanks to the suggestion from Chris Travers. =head1 BUGS GNU gettext never fails. I tries to achieve it as long as possible. The only reason that maketext may die unexpectedly now is "Unterminated bracket group". I cannot get a better solution to it currently. Suggestions are welcome. You are welcome to fix my English. I have done my best to this documentation, but I am not a native English speaker after all. ^^; =head1 SEE ALSO L, L, L, L, L, L. Also, please refer to the official GNU gettext manual at L. =head1 AUTHOR imacat =head1 COPYRIGHT Copyright (c) 2003-2021 imacat. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Locale-Maketext-Gettext-1.32/lib/Locale/Maketext/Gettext000755001750000144 014010010654 22760 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/lib/Locale/Maketext/Gettext/Functions.pm000444001750000144 5676114010010654 25462 0ustar00imacatusers000000000000# Locale::Maketext::Gettext::Functions - Functional interface to Locale::Maketext::Gettext # Copyright (c) 2003-2021 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. # First written: 2003/4/28 package Locale::Maketext::Gettext::Functions; use 5.008; use strict; use warnings; use base qw(Exporter); our ($VERSION, @EXPORT, @EXPORT_OK); $VERSION = 0.14; @EXPORT = qw( bindtextdomain textdomain get_handle maketext __ N_ dmaketext pmaketext dpmaketext reload_text read_mo encoding key_encoding encode_failure die_for_lookup_failures); @EXPORT_OK = @EXPORT; # Prototype declaration sub bindtextdomain($;$); sub textdomain(;$); sub get_handle(@); sub maketext(@); sub __(@); sub N_(@); sub dmaketext($$@); sub pmaketext($$@); sub dpmaketext($$$@); sub reload_text(); sub encoding(;$); sub key_encoding(;$); sub encode_failure(;$); sub die_for_lookup_failures(;$); sub _declare_class($); sub _cat_class(@); sub _init_textdomain($); sub _get_langs($$); sub _get_handle(); sub _get_empty_handle(); sub _reset(); sub _new_rid(); sub _k($); sub _lang($); use Encode qw(encode decode from_to FB_DEFAULT); use File::Spec::Functions qw(catdir catfile); use Locale::Maketext::Gettext qw(read_mo); our (%LOCALEDIRS, %RIDS, %CLASSES, %LANGS); our (%LHS, $_EMPTY, $LH, $DOMAIN, $CATEGORY, $BASE_CLASS, @LANGS, %PARAMS); our (@SYSTEM_LOCALEDIRS); %LHS = qw(); # The category is always LC_MESSAGES $CATEGORY = "LC_MESSAGES"; $BASE_CLASS = "Locale::Maketext::Gettext::_runtime"; # Current language parameters @LANGS = qw(); @SYSTEM_LOCALEDIRS = @Locale::Maketext::Gettext::SYSTEM_LOCALEDIRS; %PARAMS = qw(); $PARAMS{"KEY_ENCODING"} = "US-ASCII"; $PARAMS{"ENCODE_FAILURE"} = FB_DEFAULT; $PARAMS{"DIE_FOR_LOOKUP_FAILURES"} = 0; # Parameters for random class IDs our ($RID_LEN, @RID_CHARS); $RID_LEN = 8; @RID_CHARS = split //, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; # Bind a text domain to a locale directory sub bindtextdomain($;$) { local ($_, %_); my ($domain, $LOCALEDIR); ($domain, $LOCALEDIR) = @_; # Return the current registry return (exists $LOCALEDIRS{$domain}? $LOCALEDIRS{$domain}: undef) if !defined $LOCALEDIR; # Register the locale directory $LOCALEDIRS{$domain} = $LOCALEDIR; # Reinitialize the text domain _init_textdomain($domain); # Reset the current language handle _get_handle() if defined $DOMAIN && $domain eq $DOMAIN; # Return the locale directory return $LOCALEDIR; } # Set the current text domain sub textdomain(;$) { local ($_, %_); my ($new_domain); $new_domain = $_[0]; # Return the current text domain return $DOMAIN if !defined $new_domain; # Set the current text domain $DOMAIN = $new_domain; # Reinitialize the text domain _init_textdomain($DOMAIN); # Reset the current language handle _get_handle(); return $DOMAIN; } # Get a language handle sub get_handle(@) { local ($_, %_); # Register the current get_handle arguments @LANGS = @_; # Reset and return the current language handle return _get_handle(); } # Maketext, in its long name # Use @ instead of $@ in prototype, so that we can pass @_ to it. sub maketext(@) { return __($_[0], @_[1..$#_]); } # Maketext, in its shortcut name # Use @ instead of $@ in prototype, so that we can pass @_ to it. sub __(@) { local ($_, %_); my ($key, @param, $keyd); ($key, @param) = @_; # Reset the current language handle if it is not set yet _get_handle() if !defined $LH; # Decode the source text $keyd = $key; $keyd = decode($PARAMS{"KEY_ENCODING"}, $keyd, $PARAMS{"ENCODE_FAILURE"}) if exists $PARAMS{"KEY_ENCODING"} && !Encode::is_utf8($key); # Maketext $_ = $LH->maketext($keyd, @param); # Output to the requested encoding if (exists $PARAMS{"ENCODING"}) { $_ = encode($PARAMS{"ENCODING"}, $_, $PARAMS{"ENCODE_FAILURE"}); # Pass through the empty/invalid lexicon } elsif ( scalar(keys %{$LH->{"Lexicon"}}) == 0 && exists $PARAMS{"KEY_ENCODING"} && !Encode::is_utf8($key)) { $_ = encode($PARAMS{"KEY_ENCODING"}, $_, $PARAMS{"ENCODE_FAILURE"}); } return $_; } # Return the original text untouched, so that it can be cached # with xgettext # Use @ instead of $@ in prototype, so that we can pass @_ to it. sub N_(@) { # Watch out for this Perl magic! :p return $_[0] unless wantarray; return @_; } # Maketext in another text domain temporarily, # an equivalent to dgettext(). sub dmaketext($$@) { local ($_, %_); my ($domain, $key, @param, $lh0, $domain0, $text); ($domain, $key, @param) = @_; # Preserve the current status ($lh0, $domain0) = ($LH, $DOMAIN); # Reinitialize the text domain textdomain($domain); # Maketext $text = maketext($key, @param); # Return the current status ($LH, $DOMAIN) = ($lh0, $domain0); # Return the "made text" return $text; } # Maketext with context, # an equivalent to pgettext(). sub pmaketext($$@) { local ($_, %_); my ($context, $key, @param); ($context, $key, @param) = @_; # This is actually a wrapper to the maketext() function return maketext("$context\x04$key", @param); } # Maketext with context in another text domain temporarily, # an equivalent to dpgettext(). sub dpmaketext($$$@) { local ($_, %_); my ($domain, $context, $key, @param); ($domain, $context, $key, @param) = @_; # This is actually a wrapper to the dmaketext() function return dmaketext($domain, "$context\x04$key", @param); } # Purge the lexicon cache sub reload_text() { # reload_text is static. Locale::Maketext::Gettext->reload_text; } # Set the output encoding sub encoding(;$) { local ($_, %_); $_ = $_[0]; # Set the output encoding if (@_ > 0) { if (defined $_) { $PARAMS{"ENCODING"} = $_; } else { delete $PARAMS{"ENCODING"}; } $PARAMS{"USERSET_ENCODING"} = $_; } # Return the encoding return exists $PARAMS{"ENCODING"}? $PARAMS{"ENCODING"}: undef; } # Set the encoding of the original text sub key_encoding(;$) { local ($_, %_); $_ = $_[0]; # Set the encoding used in the keys if (@_ > 0) { if (defined $_) { $PARAMS{"KEY_ENCODING"} = $_; } else { delete $PARAMS{"KEY_ENCODING"}; } } # Return the encoding return exists $PARAMS{"KEY_ENCODING"}? $PARAMS{"KEY_ENCODING"}: undef; } # What to do if the text is out of your output encoding # Refer to Encode on possible values of this check sub encode_failure(;$) { local ($_, %_); $_ = $_[0]; # Set and return the current setting $PARAMS{"ENCODE_FAILURE"} = $_ if @_ > 0; # Return the current setting return $PARAMS{"ENCODE_FAILURE"}; } # Whether we should die for lookup failure # The default is no. GNU gettext never fails. sub die_for_lookup_failures(;$) { local ($_, %_); $_ = $_[0]; # Set the current setting if (@_ > 0) { $PARAMS{"DIE_FOR_LOOKUP_FAILURES"} = $_? 1: 0; $LH->die_for_lookup_failures($PARAMS{"DIE_FOR_LOOKUP_FAILURES"}); } # Return the current setting # Resetting the current language handle is not required # Lookup failures are handled by the fail handler directly return $PARAMS{"DIE_FOR_LOOKUP_FAILURES"}; } # Declare a class sub _declare_class($) { local ($_, %_); $_ = $_[0]; eval << "EOT"; package $_[0]; use base qw(Locale::Maketext::Gettext); our (\@ISA, %Lexicon); EOT } # Concatenate the class name sub _cat_class(@) { return join("::", @_);; } # Initialize a text domain sub _init_textdomain($) { local ($_, %_); my ($domain, $k, @langs, $langs); $domain = $_[0]; # Return if text domain not specified yet return if !defined $domain; # Obtain the available locales # A bound domain if (exists $LOCALEDIRS{$domain}) { @langs = _get_langs($LOCALEDIRS{$domain}, $domain); # Not bound } else { @langs = qw(); # Search the system locale directories foreach (@SYSTEM_LOCALEDIRS) { @langs = _get_langs($_, $domain); # Domain not found in this directory next if @langs == 0; $LOCALEDIRS{$domain} = $_; last; } # Not found at last return if !exists $LOCALEDIRS{$domain}; } $langs = join ",", sort @langs; # Obtain the registry key $k = _k($domain); # Available language list remains for this domain return if exists $LANGS{$k} && $LANGS{$k} eq $langs; # Register this new language list $LANGS{$k} = $langs; my ($rid, $class); # Garbage collection - drop abandoned language handles if (exists $CLASSES{$k}) { delete $LHS{$_} foreach grep /^$CLASSES{$k}/, keys %LHS; } # Get a new class ID $rid = _new_rid(); # Obtain the class name $class = _cat_class($BASE_CLASS, $rid); # Register the domain with this class $CLASSES{$k} = $class; # Declare this class _declare_class($class); # Declare its language subclasses _declare_class(_cat_class($class, $_)) foreach @langs; return; } # Search a locale directory and return the available languages sub _get_langs($$) { local ($_, %_); my ($dir, $domain, $DH, $entry, $MO_file); ($dir, $domain) = @_; @_ = qw(); { opendir $DH, $dir or last; while (defined($entry = readdir $DH)) { # Skip hidden entries next if $entry =~ /^\./; # Skip non-directories next unless -d catdir($dir, $entry); # Skip locales with dot "." (trailing encoding) next if $entry =~ /\./; # Get the MO file name $MO_file = catfile($dir, $entry, $CATEGORY, "$domain.mo"); # Skip if MO file is not available for this locale next if ! -f $MO_file && ! -r $MO_file; # Map C to i_default $entry = "i_default" if $entry eq "C"; # Add this language push @_, lc $entry; } close $DH or last; } return @_; } # Set the language handle with the current DOMAIN and @LANGS sub _get_handle() { local ($_, %_); my ($k, $class, $subclass); # Lexicon empty if text domain not specified, or not bound yet return _get_empty_handle if !defined $DOMAIN || !exists $LOCALEDIRS{$DOMAIN}; # Obtain the registry key $k = _k($DOMAIN); # Lexicon empty if text domain was not properly set yet return _get_empty_handle if !exists $CLASSES{$k}; # Get the localization class name $class = $CLASSES{$k}; # Get the language handle $LH = $class->get_handle(@LANGS); # Lexicon empty if failed get_handle() return _get_empty_handle if !defined $LH; # Obtain the subclass name of the got language handle $subclass = ref($LH); # Use the existing language handle whenever possible, to reduce # the initialization overhead if (exists $LHS{$subclass}) { $LH = $LHS{$subclass}; if (!exists $PARAMS{"USERSET_ENCODING"}) { if (exists $LH->{"MO_ENCODING"}) { $PARAMS{"ENCODING"} = $LH->{"MO_ENCODING"}; } else { delete $PARAMS{"ENCODING"}; } } return _lang($LH) } # Initialize it $LH->bindtextdomain($DOMAIN, $LOCALEDIRS{$DOMAIN}); $LH->textdomain($DOMAIN); # Respect the MO file encoding unless there is a user preference if (!exists $PARAMS{"USERSET_ENCODING"}) { if (exists $LH->{"MO_ENCODING"}) { $PARAMS{"ENCODING"} = $LH->{"MO_ENCODING"}; } else { delete $PARAMS{"ENCODING"}; } } # We handle the encoding() and key_encoding() ourselves. $LH->key_encoding(undef); $LH->encoding(undef); # Register it $LHS{$subclass} = $LH; return _lang($LH); } # Obtain the empty language handle sub _get_empty_handle() { local ($_, %_); if (!defined $_EMPTY) { $_EMPTY = Locale::Maketext::Gettext::Functions::_EMPTY->get_handle; $_EMPTY->key_encoding(undef); $_EMPTY->encoding(undef); } $LH = $_EMPTY; $LH->die_for_lookup_failures($PARAMS{"DIE_FOR_LOOKUP_FAILURES"}); return _lang($LH); } # Initialize everything sub _reset() { local ($_, %_); %LOCALEDIRS = qw(); undef $LH; undef $DOMAIN; @LANGS = qw(); %PARAMS = qw(); $PARAMS{"KEY_ENCODING"} = "US-ASCII"; $PARAMS{"ENCODE_FAILURE"} = FB_DEFAULT; $PARAMS{"DIE_FOR_LOOKUP_FAILURES"} = 0; return; } # Generate a new random ID sub _new_rid() { local ($_, %_); my ($id); do { for ($id = "", $_ = 0; $_ < $RID_LEN; $_++) { $id .= $RID_CHARS[int rand scalar @RID_CHARS]; } } while exists $RIDS{$id}; $RIDS{$id} = 1; return $id; } # Build the key for the domain registry sub _k($) { return join "\n", $LOCALEDIRS{$_[0]}, $CATEGORY, $_[0]; } # The language from a language handle. language_tag is not quite sane. sub _lang($) { local ($_, %_); $_ = $_[0]; $_ = ref($_); s/^.+:://; s/_/-/g; return $_; } # Public empty lexicon package Locale::Maketext::Gettext::Functions::_EMPTY; use 5.008; use strict; use warnings; use base qw(Locale::Maketext::Gettext); our $VERSION = 0.01; package Locale::Maketext::Gettext::Functions::_EMPTY::i_default; use 5.008; use strict; use warnings; use base qw(Locale::Maketext::Gettext); our $VERSION = 0.01; return 1; __END__ =head1 NAME Locale::Maketext::Gettext::Functions - Functional interface to Locale::Maketext::Gettext =head1 SYNOPSIS use Locale::Maketext::Gettext::Functions; bindtextdomain(DOMAIN, LOCALEDIR); textdomain(DOMAIN); get_handle("de"); print __("Hello, world!\n"); =head1 DESCRIPTION Locale::Maketext::Gettext::Functions is a functional interface to L (and L). It works exactly the GNU gettext way. It plays magic to L for you. No more localization class/subclasses and language handles are required at all. The C, C, C and C functions attempt to translate a text message into the native language of the user, by looking up the translation in an MO lexicon file. =head1 FUNCTIONS =over =item bindtextdomain(DOMAIN, LOCALEDIR) Register a text domain with a locale directory. Returns C itself. If C is omitted, the registered locale directory of C is returned. This method always success. =item textdomain(DOMAIN) Set the current text domain. Returns the C itself. if C is omitted, the current text domain is returned. This method always success. =item get_handle(@languages) Set the language of the user. It searches for an available language in the provided @languages list. If @languages was not provided, it looks checks environment variable LANG, and HTTP_ACCEPT_LANGUAGE when running as CGI. Refer to L for the magic of the C. =item $message = maketext($key, @param...) Attempts to translate a text message into the native language of the user, by looking up the translation in an MO lexicon file. Refer to L for the C plural grammar. =item $message = __($key, @param...) A synonym to C. This is a shortcut to C so that it is cleaner when you employ maketext to your existing project. =item ($key, @param...) = N_($key, @param...) Returns the original text untouched. This is to enable the text be caught with xgettext. =item $message = dmaketext($domain, $key, @param...) Temporarily switch to another text domain and attempts to translate a text message into the native language of the user in that text domain. Use "--keyword=dmaketext:2" for the xgettext utility. =item $message = pmaketext($context, $key, @param...) Attempts to translate a text message in a particular context into the native language of the user. Use "--keyword=pmaketext:1c,2" for the xgettext utility. =item $message = dpmaketext($domain, $context, $key, @param...) Temporarily switch to another text domain and attempts to translate a text message in a particular context into the native language of the user in that text domain. Use "--keyword=dpmaketext:2c,3" for the xgettext utility. =item encoding(ENCODING) Set or retrieve the output encoding. The default is the same encoding as the gettext MO file. You can specify C, to return the result in unencoded UTF-8. =item key_encoding(ENCODING) Specify the encoding used in your original text. The C method itself is not multibyte-safe to the _AUTO lexicon. If you are using your native non-English language as your original text and you are having troubles like: Unterminated bracket group, in: Then, specify the C to the encoding of your original text. Returns the current setting. B You should always use US-ASCII text keys. Using non-US-ASCII keys is always discouraged and is not guaranteed to be working. =item encode_failure(CHECK) Set the action when encode fails. This happens when the output text is out of the scope of your output encoding. For example, output Chinese into US-ASCII. Refer to L for the possible values of this C. The default is C, which is a safe choice that never fails. But part of your text may be lost, since that is what C does. Returns the current setting. =item die_for_lookup_failures(SHOULD_I_DIE) Maketext dies for lookup failures, but GNU gettext never fails. By default Lexicon::Maketext::Gettext follows the GNU gettext behavior. But if you are Maketext-styled, or if you need a better control over the failures (like me :p), set this to 1. Returns the current setting. =item reload_text() Purges the MO text cache. By default MO files are cached after they are read and parsed from the disk, to reduce I/O and parsing overhead on busy sites. reload_text() purges this cache, so that updated MO files can take effect at run-time. This is used when your MO file is updated, but you cannot shutdown and restart the application. for example, when you are a virtual host on a mod_perl-enabled Apache, or when your mod_perl-enabled Apache is too vital to be restarted for every update of your MO file, or if you are running a vital daemon, such as an X display server. =item %Lexicon = read_mo($MO_file) Read and parse the MO file. Returns the read %Lexicon. The returned lexicon is in its original encoding. If you need the meta information of your MO file, parse the entry C<$Lexicon{""}>. For example: /^Content-Type: text\/plain; charset=(.*)$/im; $encoding = $1; =back =head1 NOTES B Since localization classes are generated at run-time, it is not possible to override the Maketext language functions, like C or C. If that is your concern, use L instead. Suggestions are welcome. You can now add/remove languages/MO files at run-time. This is a major improvement over the original L (and L). This is done by registering localization classes with random IDs, so that the same text domain can be re-declared infinitely, whenever needed (language list changes, LOCALEDIR changes, etc.) This is not possible to the object-interface of L (and L). Language addition/removal takes effect only after C or C is called. It has no effect on C calls. This keeps a basic sanity in the lifetime of a running script. If you set C to a domain that is not C to specific a locale directory yet, it will try search system locale directories. The current system locale directory search order is: /usr/share/locale, /usr/lib/locale, /usr/local/share/locale, /usr/local/lib/locale. Suggestions are welcome. =head1 STORY The idea is that: I finally realized that, no matter how hard I try, I.> A common wrapper like: sub __ { return $LH->maketext(@_) }; always fails if $LH is not initialized yet. For this reason, C can hardly be employed in error handlers to output graceful error messages in the natural language of the user. So, I have to write something like this: sub __ { $LH = MyPkg::L10N->get_handle if !defined $LH; return $LH->maketext(@_); } But what if C itself fails? So, this becomes: sub __ { $LH = MyPkg::L10N->get_handle if !defined $LH; $LH = _AUTO->get_handle if !defined $LH; return $LH->maketext(@_); } package _AUTO; use base qw(Locale::Maketext); package _AUTO::i_default; use base qw(Locale::Maketext); %Lexicon = ( "_AUTO" => 1 ); Ya, this works. But, if I always have to do this in my every application, why should I not make a solution to the localization framework itself? This is a common problem to every localization projects. It should be solved at the localization framework level, but not at the application level. Another reason is that: I without the knowledge of object-oriented programming.> A localization framework should be neat and simple. It should lower down its barrier, be friendly to the beginners, in order to encourage the use of localization and globalization. Apparently the current practice of L does not satisfy this request. The third reason is: Since L imports the lexicon from foreign sources, the class source file is left empty. It exists only to help the C method looking for a proper language handle. Then, why not make it disappear, and be generated whenever needed? Why bother the programmers to put an empty class source file there? How neat can we be? imacat, 2003-04-29 =head1 BUGS Since maketext localization classes are generated at run time, Maketext language function override, like C or C, is not available here. Suggestions are welcome. C, C, C and C are not mod_perl-safe. These settings affect the whole process, including the following scripts it is going to run. This is the same as C in L. Always set them at the very beginning of your script if you are running under mod_perl. If you do not like it, use the object-oriented L instead. Suggestions are welcome. Smart translation between Traditional Chinese/Simplified Chinese, like what GNU gettext does, is not available yet. Suggestions are welcome. =head1 SEE ALSO L, L, L, L, L. Also, please refer to the official GNU gettext manual at L. =head1 AUTHOR imacat =head1 COPYRIGHT Copyright (c) 2003-2021 imacat. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Locale-Maketext-Gettext-1.32/script000755001750000144 014010010654 17111 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/script/maketext000444001750000144 1343014010010654 21034 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Command-line interface to Locale::Maketext::Gettext (and Locale::Maketext) # Copyright (c) 2003-2021 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. # First written: 2003/5/3 use 5.008; use strict; use warnings; use Getopt::Long qw(GetOptions); use Locale::Maketext::Gettext::Functions; our $VERSION = 0.06; # Prototype declaration sub main(); sub parse_args(); our ($THIS_FILE, $SHORT_HELP, $VER_STR, $SEARCH, $HELP); $THIS_FILE = $0; $THIS_FILE =~ s/^.*\///; $SHORT_HELP = "Try `$THIS_FILE --help' for more information."; $VER_STR = "$THIS_FILE v$VERSION by imacat "; $SEARCH = join " ", @Locale::Maketext::Gettext::Functions::SYSTEM_LOCALEDIRS; $HELP = << "EOT"; Usage: maketext [OPTION] [--domain=TEXTDOMAIN] MSGKEY [PARAM...] or: maketext [OPTION] -s MSGKEY [PARAM...] Maketext and display native language translation of a textual message. -d, --domain=TEXTDOMAIN retrieve translated messages from TEXTDOMAIN -h, --help display this help and exit -V, --version display version information and exit MSGKEY [PARAM...] retrieve translated message corresponding to MSGKEY from TEXTDOMAIN If the TEXTDOMAIN parameter is not given, the domain is determined from the environment variable TEXTDOMAIN. If the message catalog is not found in the regular directory, another location can be specified with the environment variable TEXTDOMAINDIR. When used with the -s option the program adds a new line to the end of the output so that it behaves like the `echo' or the `gettext' command. Standard search directories: $SEARCH Report bugs to . EOT our ($DOMAIN, $LOCALEDIR, $ECHO, $KEY, @PARAM); $ECHO = 0; # Main program main(); exit 0; # Main program sub main() { local ($_, %_); # Parse the arguments parse_args(); bindtextdomain($DOMAIN, $LOCALEDIR) if defined $DOMAIN && defined $LOCALEDIR; textdomain($DOMAIN) if defined $DOMAIN; print maketext($KEY, @PARAM); print "\n" if $ECHO; return; } # Parse the arguments sub parse_args() { local ($_, %_); # Get the arguments $_ = eval { local $SIG{__WARN__} = sub { die $_[0]; }; Getopt::Long::Configure("no_auto_abbrev"); GetOptions( "domain|d=s"=>\$DOMAIN, "s"=>sub { $ECHO = 1; }, "help|h"=>sub { print $HELP; exit 0; }, "version|V"=>sub { print "$VER_STR\n"; exit 0; }); return 1; }; die "$THIS_FILE: $@" if !defined $_; # The MSGKEY die "$THIS_FILE: missing arguments\n" if @ARGV == 0; $KEY = shift @ARGV; @PARAM = @ARGV; # Set the locale directory $LOCALEDIR = $ENV{"TEXTDOMAINDIR"} if exists $ENV{"TEXTDOMAINDIR"}; # Set the text domain $DOMAIN = $ENV{"TEXTDOMAIN"} if !defined $DOMAIN && exists $ENV{"TEXTDOMAIN"}; return; } __END__ =head1 NAME maketext - translate and make messages =head1 SYNOPSIS maketext [OPTION] [--domain=TEXTDOMAIN] MSGKEY [PARAM...] maketext [OPTION] -s MSGKEY [PARAM...] =head1 DESCRIPTION The C script translates a natural language message into the user's language, by looking up the translation in a message MO file, and process the plural transformation with Maketext. The C script is a command-line interface to L (and L). It can be used in shell scripts, etc, to translate, maketext and return the result. By this way, it enables Maketext to be integrated into other programming languages/systems, like bash/csh, python, PHP, C, etc. It works like the command-line program gettext. For example: % maketext -s "[*,_1,virus was,viruses were] found in [*,_2,file,files]." 0 1 0 viruses were found in 1 file. % maketext -s "[*,_1,virus was,viruses were] found in [*,_2,file,files]." 1 3 1 virus was found in 3 files. % =head1 OPTIONS =over =item -d,--domain=TEXTDOMAIN Retrieve translated messages from TEXTDOMAIN. =item -s Adds a new line to the end of the output so that it behaves like the `echo' or the `gettext' command. =item -h,--help Display the help messages. =item -V,--version Display version information and exit. =item MSGKEY The original text used to look up translated text. =item PARAM... Parameters to Maketext for the plural and other text functions. =back =head1 ENVIRONMENT =over =item TEXTDOMAIN TEXTDOMAIN is used to determine the text domain when the -d parameter is not given. =item TEXTDOMAINDIR TEXTDOMAINDIR is used to search the message catalog/MO file if it does not reside in the system locale directories. =back =head1 NOTES Maketext language function override, like C or C, is not available here. Suggestions are welcome. The current system locale directory search order is: /usr/share/locale, /usr/lib/locale, /usr/local/share/locale, /usr/local/lib/locale. Suggestions are welcome. =head1 BUGS Report bugs to imacat =head1 SEE ALSO L, L, L, L, L, L. Also, please refer to the official GNU gettext manual at L. =head1 AUTHOR imacat =head1 COPYRIGHT Copyright (c) 2003-2021 imacat. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Locale-Maketext-Gettext-1.32/t000755001750000144 014010010654 16050 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/00-signature.t000555001750000144 143314010010654 20614 0ustar00imacatusers000000000000#!/usr/bin/perl use strict; print "1..1\n"; if (!$ENV{TEST_SIGNATURE}) { print "ok 1 # skip Set the environment variable", " TEST_SIGNATURE to enable this test\n"; } elsif (!-s 'SIGNATURE') { print "ok 1 # skip No signature file found\n"; } elsif (!eval { require Module::Signature; 1 }) { print "ok 1 # skip ", "Next time around, consider install Module::Signature, ", "so you can verify the integrity of this distribution.\n"; } elsif (!eval { require Socket; Socket::inet_aton('pool.sks-keyservers.net') }) { print "ok 1 # skip ", "Cannot connect to the keyserver\n"; } else { (Module::Signature::verify() == Module::Signature::SIGNATURE_OK()) or print "not "; print "ok 1 # Valid signature\n"; } __END__ Locale-Maketext-Gettext-1.32/t/01-basic.t000555001750000144 620414010010654 17676 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Basic test suite # Copyright (c) 2003-2008 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 22 } use FindBin; use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); # Basic test suite use Encode qw(decode); use vars qw($META $n $k1 $k2 $s1 $s2); # bindtextdomain $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_ = $_->bindtextdomain("test"); return 1; }; # 1 ok($r, 1); # 2 ok($_, "$LOCALEDIR"); # textdomain $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_ = $_->textdomain; return 1; }; # 3 ok($r, 1); # 4 ok($_, "test"); # read_mo $META = << "EOT"; Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: English MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Plural-Forms: nplurals=2; plural=n != 1; EOT $r = eval { use Locale::Maketext::Gettext; $_ = catfile($LOCALEDIR, "en", "LC_MESSAGES", "test.mo"); %_ = read_mo($_); @_ = sort keys %_; $n = scalar(@_); $k1 = $_[0]; $k2 = $_[1]; $s1 = $_{$k1}; $s2 = $_{$k2}; return 1; }; # 5 ok($r, 1); # 6 ok($n, 4); # 7 ok($k1, ""); # 8 ok($k2, "Hello, world!"); # 9 ok($s1, $META); # 10 ok($s2, "Hiya :)"); # English $r = eval { require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_[0] = $_->maketext("Hello, world!"); $_[1] = $_->pmaketext("Menu|File|", "Hello, world!"); $_[2] = $_->pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 11 ok($r, 1); # 12 ok($_[0], "Hiya :)"); # 13 ok($_[1], "Hiya :) under the File menu"); # 14 ok($_[2], "Hiya :) under the View menu"); # Traditional Chinese $r = eval { require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_[0] = $_->maketext("Hello, world!"); $_[1] = $_->pmaketext("Menu|File|", "Hello, world!"); $_[2] = $_->pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 15 ok($r, 1); # 16 ok($_[0], "janC"); # 17 ok($_[1], "ɮ׿UjanC"); # 18 ok($_[2], "sUjanC"); # Simplified Chinese $r = eval { require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("zh-cn"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_[0] = $_->maketext("Hello, world!"); $_[1] = $_->pmaketext("Menu|File|", "Hello, world!"); $_[2] = $_->pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 19 ok($r, 1); # 20 ok($_[0], "Һá"); # 21 ok($_[1], "˵µĴҺá"); # 22 ok($_[2], "˵µĴҺá"); Locale-Maketext-Gettext-1.32/t/02-big-endian.t000555001750000144 666114010010654 20622 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test the big endian MO files # Copyright (c) 2003-2009 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 10 } use FindBin; use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); # Check reading big-endian PO files use vars qw($skip $POfile $MOfile $hasctxt); # English $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test_be", $LOCALEDIR); $_->textdomain("test_be"); $_ = $_->maketext("Hello, world!"); return 1; }; # 1 ok($r, 1); # 2 ok($_, "Hiya :)"); # Traditional Chinese $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test_be", $LOCALEDIR); $_->textdomain("test_be"); $_ = $_->maketext("Hello, world!"); return 1; }; # 3 ok($r, 1); # 4 ok($_, "janC"); # Simplified Chinese $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-cn"); $_->bindtextdomain("test_be", $LOCALEDIR); $_->textdomain("test_be"); $_ = $_->maketext("Hello, world!"); return 1; }; # 5 ok($r, 1); # 6 ok($_, "Һá"); # Native-built MO file { my $FH; $skip = 1; $POfile = catfile($FindBin::Bin, "test_native.po"); $MOfile = catfile($LOCALEDIR, "en", "LC_MESSAGES", "test_native.mo"); $_ = join "", `msgfmt --version 2>&1`; last unless $? == 0; last unless /GNU gettext/; last unless /GNU gettext.* (\d+)\.(\d+)/; # Gettext from 0.15 has msgctxt $hasctxt = $1 > 0 || ($1 == 0 && $2 >= 15); $_ = << "EOT"; # English PO file for the test_native project. # Copyright (C) 2003-2009 imacat # This file is distributed under the same license as the commonlib package. # imacat , 2003-%1\$04d. # msgid "" msgstr "" "Project-Id-Version: test_native 1.1\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: %1\$04d-%2\$02d-%3\$02d %4\$02d:%5\$02d+0800\\n" "PO-Revision-Date: %1\$04d-%2\$02d-%3\$02d %4\$02d:%5\$02d+0800\\n" "Last-Translator: imacat \\n" "Language-Team: English \\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=US-ASCII\\n" "Content-Transfer-Encoding: 7bit\\n" "Plural-Forms: nplurals=2; plural=n != 1;\\n" #: test_native.pl:100 msgid "Hello, world!" msgstr "Hiya :)" EOT $_ .= << "EOT" if $hasctxt; #: test_native.pl:103 msgctxt "Menu|File|" msgid "Hello, world!" msgstr "Hiya :) under the File menu" #: test_native.pl:106 msgctxt "Menu|View|" msgid "Hello, world!" msgstr "Hiya :) under the View menu" EOT @_ = localtime; $_[5] += 1900; $_[4]++; $_ = sprintf $_, @_[5,4,3,2,1,0]; open $FH, ">$POfile"; print $FH $_; close $FH; `msgfmt -o "$MOfile" "$POfile"`; last unless $? == 0; $skip = 0; $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test_native", $LOCALEDIR); $_->textdomain("test_native"); $_[0] = $_->maketext("Hello, world!"); $_[1] = $_->pmaketext("Menu|File|", "Hello, world!") if $hasctxt; $_[2] = $_->pmaketext("Menu|View|", "Hello, world!") if $hasctxt; return 1; }; } # 7 skip($skip, $r, 1); # 8 skip($skip, $_[0], "Hiya :)"); # 9 skip($skip || !$hasctxt, $_[1], "Hiya :) under the File menu"); # 10 skip($skip || !$hasctxt, $_[2], "Hiya :) under the View menu"); # Garbage collection unlink $POfile; unlink $MOfile; Locale-Maketext-Gettext-1.32/t/03-errors.t000555001750000144 1614014010010654 20153 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite for the behavior when something goes wrong # Copyright (c) 2003-2009 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 29 } use Encode qw(); use FindBin; use File::Basename qw(basename); use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($THIS_FILE $LOCALEDIR $r); $THIS_FILE = basename($0); $LOCALEDIR = catdir($FindBin::Bin, "locale"); sub find_system_mo(); # find_system_mo: Find a safe system MO to be tested sub find_system_mo() { local ($_, %_); my %cands; use Locale::Maketext::Gettext::Functions; # Find all the system MO files %cands = qw(); foreach my $dir (@Locale::Maketext::Gettext::Functions::SYSTEM_LOCALEDIRS) { my ($DH, @locales); next unless -d $dir; @locales = qw(); opendir $DH, $dir or die "$THIS_FILE: $dir: $!"; while (defined($_ = readdir $DH)) { my $dir1; $dir1 = catfile($dir, $_, "LC_MESSAGES"); push @locales, $_ if -d $dir1 && -r $dir1 && /^(?:en|zh_tw|zh_cn)$/i; } closedir $DH or die "$THIS_FILE: $dir: $!"; foreach my $loc (sort @locales) { my $dir1; $dir1 = catfile($dir, $loc, "LC_MESSAGES"); opendir $DH, $dir1 or die "$THIS_FILE: $dir1: $!"; while (defined($_ = readdir $DH)) { my ($file, $domain); $file = catfile($dir1, $_); next unless -f $file && -r $file && /^(.+)\.mo$/; $domain = $1; $cands{$file} = [$loc, $domain]; } closedir $DH or die "$THIS_FILE: $dir1: $!"; } } # Check each MO file, from the newest foreach my $file (sort { (stat $b)[9] <=> (stat $a)[9] } keys %cands) { my ($FH, $size, $content, $charset, $lang, $domain); $size = (stat $file)[7]; open $FH, $file or die "$THIS_FILE: $file: $!"; read $FH, $content, $size or die "$THIS_FILE: $file: $!"; close $FH or die "$THIS_FILE: $file: $!"; # Only take files whose meta information does not have special characters # that might be considered as code by Locale::Maketext next unless $content =~ /Project-Id-Version:([^\n\0\[\]~]+\n)+\0/; # Only take files that resolve to a valid character set next unless $content =~ /\s+charset=([^\n]+)/; $charset = $1; next unless defined Encode::resolve_alias($charset); # OK. We take this one ($lang, $domain) = @{$cands{$file}}; $lang = lc $lang; $lang =~ s/_/-/g; $lang = "i-default" if $lang eq "c"; return ($lang, $domain); } # Not found return (undef, undef); } # When something goes wrong use vars qw($dir $domain $lang $skip); # GNU gettext never fails! # bindtextdomain $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_ = $_->bindtextdomain("test"); return 1; }; # 1 ok($r, 1); # 2 ok($_, undef); # textdomain $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_ = $_->textdomain; return 1; }; # 3 ok($r, 1); # 4 ok($_, undef); # No text domain claimed yet $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_ = $_->maketext("Hello, world!"); return 1; }; # 5 ok($r, 1); # 6 ok($_, "Hello, world!"); # Non-existing LOCALEDIR $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", "/dev/null"); $_->textdomain("test"); $_ = $_->maketext("Hello, world!"); return 1; }; # 7 ok($r, 1); # 8 ok($_, "Hello, world!"); # Not-registered DOMAIN $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->textdomain("not_registered"); $_ = $_->maketext("Hello, world!"); return 1; }; # 9 ok($r, 1); # 10 ok($_, "Hello, world!"); # PO file not exists $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("no_such_domain", $LOCALEDIR); $_->textdomain("no_such_domain"); $_ = $_->maketext("Hello, world!"); return 1; }; # 11 ok($r, 1); # 12 ok($_, "Hello, world!"); # PO file invalid $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("bad", $LOCALEDIR); $_->textdomain("bad"); $_ = $_->maketext("Hello, world!"); return 1; }; # 13 ok($r, 1); # 14 ok($_, "Hello, world!"); # No such message $r = eval { require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_[0] = $_->maketext("[*,_1,non-existing message,non-existing messages]", 1); $_[1] = $_->maketext("[*,_1,non-existing message,non-existing messages]", 3); $_[2] = $_->pmaketext("Menu|View|", "[*,_1,non-existing message,non-existing messages]", 1); $_[3] = $_->pmaketext("Menu|View|", "[*,_1,non-existing message,non-existing messages]", 3); $_[4] = $_->pmaketext("Menu|None|", "Hello, world!"); return 1; }; # 15 ok($r, 1); # 16 ok($_[0], "1 non-existing message"); # 17 ok($_[1], "3 non-existing messages"); # 18 ok($_[2], "1 non-existing message"); # 19 ok($_[3], "3 non-existing messages"); # 20 ok($_[4], "Hello, world!"); # die_for_lookup_failures $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->die_for_lookup_failures(1); $_ = $_->maketext("non-existing message"); return 1; }; # To be refined - to know that we failed at maketext() # was ok($@, qr/maketext doesn't know how to say/); # 21 ok($r, undef); # multibyte keys $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->key_encoding("Big5"); $_ = $_->maketext("]]w^"); return 1; }; # 22 ok($r, 1); # 23 ok($_, "]]w^"); $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", "/dev/null"); $_->textdomain("test"); $_->key_encoding("Big5"); $_ = $_->maketext("]]w^"); return 1; }; # 24 ok($r, 1); # 25 ok($_, "]]w^"); # Call maketext before and after binding text domain $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->maketext("Hello, world!"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_ = $_->maketext("Hello, world!"); return 1; }; # 26 ok($r, 1); # 27 ok($_, "Hiya :)"); # Search system locale directories ($lang, $domain) = find_system_mo; $skip = defined $domain? 0: 1; $r = eval { return if $skip; require T_L10N; $_ = T_L10N->get_handle($lang); $_->textdomain($domain); print "OK 1111\n"; $_ = $_->maketext(""); # Skip if $Lexicon{""} does not exists $skip = 1 if $_ eq ""; return 1; }; # 28 skip($skip, $r, 1); # 29 skip($skip, $_, qr/Project-Id-Version:/); Locale-Maketext-Gettext-1.32/t/04-encodings.t000555001750000144 1247214010010654 20615 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite for different encodings # Copyright (c) 2003-2007 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 34 } use Encode qw(); use FindBin qw(); use File::Spec::Functions qw(catdir); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); # Different encodings # English # Find the default encoding $r = eval { require T_L10N; $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_ = $_->encoding; return 1; }; # 1 ok($r, 1); # 2 ok($_, "US-ASCII"); # Traditional Chinese # Find the default encoding $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_ = $_->encoding; return 1; }; # 3 ok($r, 1); # 4 ok($_, "Big5"); # Turn to Big5 $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->encoding("Big5"); $_ = $_->maketext("Hello, world!"); return 1; }; # 5 ok($r, 1); # 6 ok($_, "janC"); # Turn to UTF-8 $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->encoding("UTF-8"); $_ = $_->maketext("Hello, world!"); return 1; }; # 7 ok($r, 1); # 8 ok($_, "大家好。"); # Turn to UTF-16LE $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->encoding("UTF-16LE"); $_ = $_->maketext("Hello, world!"); return 1; }; # 9 ok($r, 1); # 10 ok($_, "'Y[}Y0"); # Find the default encoding, in UTF-8 $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test_utf8", $LOCALEDIR); $_->textdomain("test_utf8"); $_ = $_->encoding; return 1; }; # 11 ok($r, 1); # 12 ok($_, "UTF-8"); # Turn to UTF-8 $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test_utf8", $LOCALEDIR); $_->textdomain("test_utf8"); $_->encoding("UTF-8"); $_ = $_->maketext("Hello, world!"); return 1; }; # 13 ok($r, 1); # 14 ok($_, "大家好。"); # Turn to Big5 $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test_utf8", $LOCALEDIR); $_->textdomain("test_utf8"); $_->encoding("Big5"); $_ = $_->maketext("Hello, world!"); return 1; }; # 15 ok($r, 1); # 16 ok($_, "janC"); # Turn to UTF-16LE $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test_utf8", $LOCALEDIR); $_->textdomain("test_utf8"); $_->encoding("UTF-16LE"); $_ = $_->maketext("Hello, world!"); return 1; }; # 17 ok($r, 1); # 18 ok($_, "'Y[}Y0"); # Find the default encoding # Simplified Chinese $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-cn"); $_->bindtextdomain("test_utf8", $LOCALEDIR); $_->textdomain("test_utf8"); $_ = $_->encoding; return 1; }; # 19 ok($r, 1); # 20 ok($_, "UTF-8"); # Turn to GB2312 $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-cn"); $_->bindtextdomain("test_utf8", $LOCALEDIR); $_->textdomain("test_utf8"); $_->encoding("GB2312"); $_ = $_->maketext("Hello, world!"); return 1; }; # 21 ok($r, 1); # 22 ok($_, "Һá"); # Encode failure # FB_DEFAULT $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test2", $LOCALEDIR); $_->textdomain("test2"); $_->encoding("GB2312"); $_ = $_->maketext("Every story has a happy ending."); return 1; }; # 23 ok($r, 1); # 24 ok($_, "¶??֡"); # FB_CROAK $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test2", $LOCALEDIR); $_->textdomain("test2"); $_->encoding("GB2312"); $_->encode_failure(Encode::FB_CROAK); $_ = $_->maketext("Every story has a happy ending."); return 1; }; # 25 ok($r, undef); # 26 ok($@, qr/does not map to/); # FB_HTMLCREF $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test2", $LOCALEDIR); $_->textdomain("test2"); $_->encoding("GB2312"); $_->encode_failure(Encode::FB_HTMLCREF); $_ = $_->maketext("Every story has a happy ending."); return 1; }; # 27 ok($r, 1); # 28 ok($_, "¶麗結֡"); # Return the unencoded UTF-8 text $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->encoding(undef); $_ = $_->maketext("Hello, world!"); return 1; }; # 29 ok($r, 1); # 30 ok($_, "\x{5927}\x{5BB6}\x{597D}\x{3002}"); # 31 ok((Encode::is_utf8($_)? "utf8": "non-utf8"), "utf8"); # Return the unencoded UTF-8 text with auto lexicon $r = eval { require T_L10N; $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->encoding(undef); $_ = $_->maketext("Big watermelon"); return 1; }; # 32 ok($r, 1); # 33 ok($_, "Big watermelon"); # 34 ok((Encode::is_utf8($_)? "utf8": "non-utf8"), "utf8"); Locale-Maketext-Gettext-1.32/t/05-switching.t000555001750000144 765314010010654 20631 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite for switching between different settings # Copyright (c) 2003-2008 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 25 } use FindBin; use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); # Switching between different settings use File::Copy qw(copy); use vars qw($lh1 $lh2 $dir $f $f1 $f2); # 2 language handles of the same localization subclass $r = eval { require T_L10N; @_ = qw(); $lh1 = T_L10N->get_handle("en"); $lh1->bindtextdomain("test", $LOCALEDIR); $lh1->textdomain("test"); $lh2 = T_L10N->get_handle("en"); $lh2->bindtextdomain("test2", $LOCALEDIR); $lh2->textdomain("test2"); $_[0] = $lh1->maketext("Hello, world!"); $_[1] = $lh1->maketext("Every story has a happy ending."); $_[2] = $lh2->maketext("Hello, world!"); $_[3] = $lh2->maketext("Every story has a happy ending."); $_[4] = $lh1->maketext("Hello, world!"); $_[5] = $lh1->maketext("Every story has a happy ending."); return 1; }; # 1 ok($r, 1); # 2 ok($_[0], "Hiya :)"); # 3 ok($_[1], "Every story has a happy ending."); # 4 ok($_[2], "Hello, world!"); # 5 ok($_[3], "Pray it."); # 6 ok($_[4], "Hiya :)"); # 7 ok($_[5], "Every story has a happy ending."); # Switch between domains $r = eval { require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test", $LOCALEDIR); $_->bindtextdomain("test2", $LOCALEDIR); $_->textdomain("test"); $_[0] = $_->maketext("Hello, world!"); $_[1] = $_->maketext("Every story has a happy ending."); $_->textdomain("test2"); $_[2] = $_->maketext("Hello, world!"); $_[3] = $_->maketext("Every story has a happy ending."); $_->textdomain("test"); $_[4] = $_->maketext("Hello, world!"); $_[5] = $_->maketext("Every story has a happy ending."); return 1; }; # 8 ok($r, 1); # 9 ok($_[0], "Hiya :)"); # 10 ok($_[1], "Every story has a happy ending."); # 11 ok($_[2], "Hello, world!"); # 12 ok($_[3], "Pray it."); # 13 ok($_[4], "Hiya :)"); # 14 ok($_[5], "Every story has a happy ending."); # Switch between encodings $r = eval { require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("zh-tw"); $_->bindtextdomain("test", $LOCALEDIR); $_->textdomain("test"); $_->encoding("Big5"); $_[0] = $_->maketext("Hello, world!"); $_->encoding("UTF-8"); $_[1] = $_->maketext("Hello, world!"); $_->encoding("Big5"); $_[2] = $_->maketext("Hello, world!"); return 1; }; # 15 ok($r, 1); # 16 ok($_[0], "janC"); # 17 ok($_[1], "大家好。"); # 18 ok($_[2], "janC"); # Reload the text $r = eval { $dir = catdir($LOCALEDIR, "en", "LC_MESSAGES"); $f = catfile($dir, "test_reload.mo"); $f1 = catfile($dir, "test.mo"); $f2 = catfile($dir, "test2.mo"); unlink $f; copy $f1, $f or die "ERROR: $f1 $f: $!"; require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test_reload", $LOCALEDIR); $_->textdomain("test_reload"); $_[0] = $_->maketext("Hello, world!"); $_[1] = $_->maketext("Every story has a happy ending."); unlink $f; copy $f2, $f or die "ERROR: $f2 $f: $!"; $_[2] = $_->maketext("Hello, world!"); $_[3] = $_->maketext("Every story has a happy ending."); $_->reload_text; $_[4] = $_->maketext("Hello, world!"); $_[5] = $_->maketext("Every story has a happy ending."); unlink $f; return 1; }; # 19 ok($r, 1); # 20 ok($_[0], "Hiya :)"); # 21 ok($_[1], "Every story has a happy ending."); # 22 ok($_[2], "Hiya :)"); # 23 ok($_[3], "Every story has a happy ending."); # 24 ok($_[4], "Hello, world!"); # 25 ok($_[5], "Pray it."); # Garbage collection unlink catfile($LOCALEDIR, "en", "LC_MESSAGES", "test_reload.mo"); Locale-Maketext-Gettext-1.32/t/06-racing.t000555001750000144 1426514010010654 20113 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite for the hybrid racing condition # Copyright (c) 2003-2007 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 42 } use FindBin; use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r $LOOKUP_FAILURE); $LOCALEDIR = catdir($FindBin::Bin, "locale"); # Hybrid racing conditionr use vars qw($lh1 $lh2); $r = eval { undef $LOOKUP_FAILURE; require T_L10N; $lh1 = T_L10N->get_handle("zh-tw"); $lh1->fail_with(sub { $LOOKUP_FAILURE = 1; die; }); $lh1->bindtextdomain("test", $LOCALEDIR); $lh1->textdomain("test"); $lh1->encoding("Big5"); $lh1->die_for_lookup_failures(0); $lh2 = T_L10N->get_handle("zh-tw"); $lh2->fail_with(sub { $LOOKUP_FAILURE = 1; die; }); $lh2->bindtextdomain("test2", $LOCALEDIR); $lh2->textdomain("test2"); $lh2->encoding("UTF-8"); $lh2->die_for_lookup_failures(1); return 1; }; # 1 ok($r, 1); # Once $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Hello, world!"); return 1; }; # 2 ok($_, "janC"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Every story has a happy ending."); return 1; }; # 3 ok($_, "Every story has a happy ending."); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Hello, world!"); return 1; }; # 4 ok($r, undef); # 5 ok($LOOKUP_FAILURE, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Every story has a happy ending."); return 1; }; # 6 ok($_, "故事都有美麗的結局。"); # Again $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Hello, world!"); return 1; }; # 7 ok($_, "janC"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Every story has a happy ending."); return 1; }; # 8 ok($_, "Every story has a happy ending."); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Hello, world!"); return 1; }; # 9 ok($r, undef); # 10 ok($LOOKUP_FAILURE, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Every story has a happy ending."); return 1; }; # 11 ok($_, "故事都有美麗的結局。"); # Exchange everything! $r = eval { undef $LOOKUP_FAILURE; $lh1->bindtextdomain("test2", $LOCALEDIR); $lh1->textdomain("test2"); $lh1->encoding("UTF-8"); $lh1->die_for_lookup_failures(1); $lh2->bindtextdomain("test", $LOCALEDIR); $lh2->textdomain("test"); $lh2->encoding("Big5"); $lh2->die_for_lookup_failures(0); return 1; }; # 12 ok($r, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Hello, world!"); return 1; }; # 13 ok($r, undef); # 14 ok($LOOKUP_FAILURE, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Every story has a happy ending."); return 1; }; # 15 ok($_, "故事都有美麗的結局。"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Hello, world!"); return 1; }; # 16 ok($_, "janC"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Every story has a happy ending."); return 1; }; # 17 ok($_, "Every story has a happy ending."); # Exchange the text domains $r = eval { undef $LOOKUP_FAILURE; $lh1->textdomain("test"); $lh2->textdomain("test2"); return 1; }; # 18 ok($r, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Hello, world!"); return 1; }; # 19 ok($_, "大家好。"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Every story has a happy ending."); return 1; }; # 20 ok($r, undef); # 21 ok($LOOKUP_FAILURE, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Hello, world!"); return 1; }; # 22 ok($_, "Hello, world!"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Every story has a happy ending."); return 1; }; # 23 ok($_, "GƳRC"); # Exchange encodings $r = eval { undef $LOOKUP_FAILURE; $lh1->encoding("Big5"); $lh2->encoding("UTF-8"); return 1; }; # 24 ok($r, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Hello, world!"); return 1; }; # 25 ok($_, "janC"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Every story has a happy ending."); return 1; }; # 26 ok($r, undef); # 27 ok($LOOKUP_FAILURE, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Hello, world!"); return 1; }; # 28 ok($_, "Hello, world!"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Every story has a happy ending."); return 1; }; # 29 ok($_, "故事都有美麗的結局。"); # Exchange lookup-failure behaviors $r = eval { undef $LOOKUP_FAILURE; $lh1->die_for_lookup_failures(0); $lh2->die_for_lookup_failures(1); return 1; }; # 30 ok($r, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Hello, world!"); return 1; }; # 31 ok($_, "janC"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Every story has a happy ending."); return 1; }; # 32 ok($_, "Every story has a happy ending."); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Hello, world!"); return 1; }; # 33 ok($r, undef); # 34 ok($LOOKUP_FAILURE, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Every story has a happy ending."); return 1; }; # 35 ok($_, "故事都有美麗的結局。"); # Switch to an non-existing domain $r = eval { undef $LOOKUP_FAILURE; $lh1->textdomain("Big5"); $lh2->textdomain("GB2312"); return 1; }; # 36 ok($r, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Hello, world!"); return 1; }; # 37 ok($_, "Hello, world!"); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh1->maketext("Every story has a happy ending."); return 1; }; # 38 ok($_, "Every story has a happy ending."); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Hello, world!"); return 1; }; # 39 ok($r, undef); # 40 ok($LOOKUP_FAILURE, 1); $r = eval { undef $LOOKUP_FAILURE; $_ = $lh2->maketext("Every story has a happy ending."); return 1; }; # 41 ok($r, undef); # 42 ok($LOOKUP_FAILURE, 1); Locale-Maketext-Gettext-1.32/t/07-f-basic.t000555001750000144 1407214010010654 20151 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Basic test suite for the functional interface # Copyright (c) 2003-2008 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 41 } use FindBin; use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); delete $ENV{$_} foreach qw(LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES LC_NUMERIC LC_MONETARY LC_TIME LANG); # Basic test suite # bindtextdomain $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); $_ = bindtextdomain("test", $LOCALEDIR); return 1; }; # 1 ok($r, 1); # 2 ok($_, $LOCALEDIR); # textdomain $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); $_ = textdomain("test"); return 1; }; # 3 ok($r, 1); # 4 ok($_, "test"); # get_handle $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); return 1; }; # 5 ok($r, 1); # maketext $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_ = maketext("Hello, world!"); return 1; }; # 6 ok($r, 1); # 7 ok($_, "Hiya :)"); # __ (shortcut to maketext) $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_ = __("Hello, world!"); return 1; }; # 8 ok($r, 1); # 9 ok($_, "Hiya :)"); # N_ (do nothing) $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_ = N_("Hello, world!"); return 1; }; # 10 ok($r, 1); # 11 ok($_, "Hello, world!"); # N_ (do nothing) $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); # lAoɤjʡI :p ]From: xWRE^ @_ = N_("Hello, world!", "Cool!", "Big watermelon"); return 1; }; # 12 ok($r, 1); # 13 ok($_[0], "Hello, world!"); # 14 ok($_[1], "Cool!"); # 15 ok($_[2], "Big watermelon"); $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_ = N_("Hello, world!"); return 1; }; # 16 ok($r, 1); # 17 ok($_, "Hello, world!"); # maketext # English $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_[0] = __("Hello, world!"); $_[1] = pmaketext("Menu|File|", "Hello, world!"); $_[2] = pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 18 ok($r, 1); # 19 ok($_[0], "Hiya :)"); # 20 ok($_[1], "Hiya :) under the File menu"); # 21 ok($_[2], "Hiya :) under the View menu"); # Traditional Chinese $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); $_[0] = __("Hello, world!"); $_[1] = pmaketext("Menu|File|", "Hello, world!"); $_[2] = pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 22 ok($r, 1); # 23 ok($_[0], "janC"); # 24 ok($_[1], "ɮ׿UjanC"); # 25 ok($_[2], "sUjanC"); # Simplified Chinese $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-cn"); $_[0] = __("Hello, world!"); $_[1] = pmaketext("Menu|File|", "Hello, world!"); $_[2] = pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 26 ok($r, 1); # 27 ok($_[0], "Һá"); # 28 ok($_[1], "˵µĴҺá"); # 29 ok($_[2], "˵µĴҺá"); # maketext - by environment # English $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); $ENV{"LANG"} = "en"; get_handle(); $_[0] = __("Hello, world!"); $_[1] = pmaketext("Menu|File|", "Hello, world!"); $_[2] = pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 30 ok($r, 1); # 31 ok($_[0], "Hiya :)"); # 32 ok($_[1], "Hiya :) under the File menu"); # 33 ok($_[2], "Hiya :) under the View menu"); # Traditional Chinese $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); $ENV{"LANG"} = "zh-tw"; get_handle(); $_[0] = __("Hello, world!"); $_[1] = pmaketext("Menu|File|", "Hello, world!"); $_[2] = pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 34 ok($r, 1); # 35 ok($_[0], "janC"); # 36 ok($_[1], "ɮ׿UjanC"); # 37 ok($_[2], "sUjanC"); # Simplified Chinese $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); $ENV{"LANG"} = "zh-cn"; get_handle(); $_[0] = __("Hello, world!"); $_[1] = pmaketext("Menu|File|", "Hello, world!"); $_[2] = pmaketext("Menu|View|", "Hello, world!"); return 1; }; # 38 ok($r, 1); # 39 ok($_[0], "Һá"); # 40 ok($_[1], "˵µĴҺá"); # 41 ok($_[2], "˵µĴҺá"); Locale-Maketext-Gettext-1.32/t/08-f-errors.t000555001750000144 2100014010010654 20372 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite on the functional interface for the behavior when something goes wrong # Copyright (c) 2003-2008 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 39 } use Encode qw(); use FindBin; use File::Basename qw(basename); use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($THIS_FILE $LOCALEDIR $r); $THIS_FILE = basename($0); $LOCALEDIR = catdir($FindBin::Bin, "locale"); sub find_system_mo(); # find_system_mo: Find a safe system MO to be tested sub find_system_mo() { local ($_, %_); my %cands; use Locale::Maketext::Gettext::Functions; # Find all the system MO files %cands = qw(); foreach my $dir (@Locale::Maketext::Gettext::Functions::SYSTEM_LOCALEDIRS) { my ($DH, @langs); next unless -d $dir; @langs = qw(); opendir $DH, $dir or die "$THIS_FILE: $dir: $!"; while (defined($_ = readdir $DH)) { my $dir1; $dir1 = catfile($dir, $_, "LC_MESSAGES"); push @langs, $_ if -d $dir1 && -r $dir1; } closedir $DH or die "$THIS_FILE: $dir: $!"; foreach my $lang (sort @langs) { my $dir1; $dir1 = catfile($dir, $lang, "LC_MESSAGES"); opendir $DH, $dir1 or die "$THIS_FILE: $dir1: $!"; while (defined($_ = readdir $DH)) { my ($file, $domain); $file = catfile($dir1, $_); next unless -f $file && -r $file && /^(.+)\.mo$/; $domain = $1; $cands{$file} = [$lang, $domain]; } closedir $DH or die "$THIS_FILE: $dir1: $!"; } } # Check each MO file, from the newest foreach my $file (sort { (stat $b)[9] <=> (stat $a)[9] } keys %cands) { my ($FH, $size, $content, $charset, $lang, $domain); $size = (stat $file)[7]; open $FH, $file or die "$THIS_FILE: $file: $!"; read $FH, $content, $size or die "$THIS_FILE: $file: $!"; close $FH or die "$THIS_FILE: $file: $!"; next unless $content =~ /Project-Id-Version:/; next unless $content =~ /\s+charset=([^\n]+)/; $charset = $1; next unless defined Encode::resolve_alias($charset); # OK. We take this one ($lang, $domain) = @{$cands{$file}}; $lang = lc $lang; $lang =~ s/_/-/g; $lang = "i-default" if $lang eq "c"; return ($lang, $domain); } # Not found return (undef, undef); } # When something goes wrong use vars qw($dir $domain $lang $skip); # GNU gettext never fails! # bindtextdomain $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); $_ = bindtextdomain("test"); return 1; }; # 1 ok($r, 1); # 2 ok($_, undef); # textdomain $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); $_ = textdomain; return 1; }; # 3 ok($r, 1); # 4 ok($_, undef); # No text domain claimed yet $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); $_ = __("Hello, world!"); return 1; }; # 5 ok($r, 1); # 6 ok($_, "Hello, world!"); # Non-existing LOCALEDIR $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", "/dev/null"); textdomain("test"); $_ = __("Hello, world!"); return 1; }; # 7 ok($r, 1); # 8 ok($_, "Hello, world!"); # Not-registered DOMAIN $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); textdomain("not_registered"); $_ = __("Hello, world!"); return 1; }; # 9 ok($r, 1); # 10 ok($_, "Hello, world!"); # PO file not exists $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("no_such_domain", $LOCALEDIR); textdomain("no_such_domain"); $_ = __("Hello, world!"); return 1; }; # 11 ok($r, 1); # 12 ok($_, "Hello, world!"); # PO file invalid $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("bad", $LOCALEDIR); textdomain("bad"); $_ = __("Hello, world!"); return 1; }; # 13 ok($r, 1); # 14 ok($_, "Hello, world!"); # No such message $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_[0] = __("[*,_1,non-existing message,non-existing messages]", 1); $_[1] = __("[*,_1,non-existing message,non-existing messages]", 3); $_[2] = pmaketext("Menu|View|", "[*,_1,non-existing message,non-existing messages]", 1); $_[3] = pmaketext("Menu|View|", "[*,_1,non-existing message,non-existing messages]", 3); $_[4] = pmaketext("Menu|None|", "Hello, world!"); return 1; }; # 15 ok($r, 1); # 16 ok($_[0], "1 non-existing message"); # 17 ok($_[1], "3 non-existing messages"); # 18 ok($_[2], "1 non-existing message"); # 19 ok($_[3], "3 non-existing messages"); # 20 ok($_[4], "Hello, world!"); # get_handle before textdomain $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); get_handle("en"); bindtextdomain("test", $LOCALEDIR); textdomain("test"); $_ = __("Hello, world!"); return 1; }; # 21 ok($r, 1); # 22 ok($_, "Hiya :)"); # bindtextdomain after textdomain $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); get_handle("en"); textdomain("test2"); bindtextdomain("test2", $LOCALEDIR); $_ = __("Every story has a happy ending."); return 1; }; # 23 ok($r, 1); # 24 ok($_, "Pray it."); # multibyte keys $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); key_encoding("Big5"); $_ = maketext("]]w^"); return 1; }; # 25 ok($r, 1); # 26 ok($_, "]]w^"); $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", "/dev/null"); textdomain("test"); get_handle("zh-tw"); key_encoding("Big5"); $_ = maketext("]]w^"); return 1; }; # 27 ok($r, 1); # 28 ok($_, "]]w^"); # Maketext before and after binding text domain $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); __("Hello, world!"); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_ = __("Hello, world!"); return 1; }; # 29 ok($r, 1); # 30 ok($_, "Hiya :)"); # Switch to a domain that is not binded yet $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); get_handle("en"); bindtextdomain("test", $LOCALEDIR); textdomain("test"); textdomain("test2"); $_ = __("Hello, world!"); return 1; }; # 31 ok($r, 1); # 32 ok($_, "Hello, world!"); # N_: different context - string to array $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); @_ = N_("Hello, world!"); return 1; }; # 33 ok($r, 1); # 34 ok($_[0], "Hello, world!"); # 35 ok($_[1], undef); # N_: different context - array to string $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_ = N_("Hello, world!", "Cool!", "Big watermelon"); return 1; }; # 36 ok($r, 1); # 37 ok($_, "Hello, world!"); # Search system locale directories ($lang, $domain) = find_system_mo; $skip = defined $domain? 0: 1; $r = eval { return if $skip; use Locale::Maketext::Gettext::Functions; textdomain($domain); get_handle($lang); $_ = maketext(""); # Skip if $Lexicon{""} does not exists $skip = 1 if $_ eq ""; return 1; }; # 38 skip($skip, $r, 1, $@); # 39 skip($skip, $_, qr/Project-Id-Version:/); Locale-Maketext-Gettext-1.32/t/09-f-encodings.t000555001750000144 1416114010010654 21042 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite on the functional interface for different encodings # Copyright (c) 2003-2007 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 34 } use Encode qw(); use FindBin; use File::Spec::Functions qw(catdir); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); # Different encodings # English # Find the default encoding $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_ = encoding(); return 1; }; # 1 ok($r, 1); # 2 ok($_, "US-ASCII"); # Traditional Chinese # Find the default encoding $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); $_ = encoding(); return 1; }; # 3 ok($r, 1); # 4 ok($_, "Big5"); # Turn to Big5 $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); encoding("Big5"); $_ = maketext("Hello, world!"); return 1; }; # 5 ok($r, 1); # 6 ok($_, "janC"); # Turn to UTF-8 $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); encoding("UTF-8"); $_ = maketext("Hello, world!"); return 1; }; # 7 ok($r, 1); # 8 ok($_, "大家好。"); # Turn to UTF-16LE $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); encoding("UTF-16LE"); $_ = maketext("Hello, world!"); return 1; }; # 9 ok($r, 1); # 10 ok($_, "'Y[}Y0"); # Find the default encoding, in UTF-8 $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test_utf8", $LOCALEDIR); textdomain("test_utf8"); get_handle("zh-tw"); $_ = encoding(); return 1; }; # 11 ok($r, 1); # 12 ok($_, "UTF-8"); # Turn to UTF-8 $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test_utf8", $LOCALEDIR); textdomain("test_utf8"); get_handle("zh-tw"); encoding("UTF-8"); $_ = maketext("Hello, world!"); return 1; }; # 13 ok($r, 1); # 14 ok($_, "大家好。"); # Turn to Big5 $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test_utf8", $LOCALEDIR); textdomain("test_utf8"); get_handle("zh-tw"); encoding("Big5"); $_ = maketext("Hello, world!"); return 1; }; # 15 ok($r, 1); # 16 ok($_, "janC"); # Turn to UTF-16LE $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test_utf8", $LOCALEDIR); textdomain("test_utf8"); get_handle("zh-tw"); encoding("UTF-16LE"); $_ = maketext("Hello, world!"); return 1; }; # 17 ok($r, 1); # 18 ok($_, "'Y[}Y0"); # Find the default encoding # Simplified Chinese $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test_utf8", $LOCALEDIR); textdomain("test_utf8"); get_handle("zh-cn"); $_ = encoding(); return 1; }; # 19 ok($r, 1); # 20 ok($_, "UTF-8"); # Turn to GB2312 $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test_utf8", $LOCALEDIR); textdomain("test_utf8"); get_handle("zh-cn"); encoding("GB2312"); $_ = maketext("Hello, world!"); return 1; }; # 21 ok($r, 1); # 22 ok($_, "Һá"); # Encode failure # FB_DEFAULT $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test2", $LOCALEDIR); textdomain("test2"); get_handle("zh-tw"); encoding("GB2312"); $_ = maketext("Every story has a happy ending."); return 1; }; # 23 ok($r, 1); # 24 ok($_, "¶??֡"); # FB_CROAK $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test2", $LOCALEDIR); textdomain("test2"); get_handle("zh-tw"); encoding("GB2312"); encode_failure(Encode::FB_CROAK); $_ = maketext("Every story has a happy ending."); return 1; }; # 25 ok($r, undef); # 26 ok($@, qr/does not map to/); # FB_HTMLCREF $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test2", $LOCALEDIR); textdomain("test2"); get_handle("zh-tw"); encoding("GB2312"); encode_failure(Encode::FB_HTMLCREF); $_ = maketext("Every story has a happy ending."); return 1; }; # 27 ok($r, 1); # 28 ok($_, "¶麗結֡"); # Return the unencoded UTF-8 text $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); encoding(undef); $_ = maketext("Hello, world!"); return 1; }; # 29 ok($r, 1); # 30 ok($_, "\x{5927}\x{5BB6}\x{597D}\x{3002}"); # 31 ok((Encode::is_utf8($_)? "utf8": "non-utf8"), "utf8"); # Return the unencoded UTF-8 text with auto lexicon $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-tw"); encoding(undef); $_ = maketext("Big watermelon"); return 1; }; # 32 ok($r, 1); # 33 ok($_, "Big watermelon"); # 34 ok((Encode::is_utf8($_)? "utf8": "non-utf8"), "utf8"); Locale-Maketext-Gettext-1.32/t/10-f-switching.t000555001750000144 2512114010010654 21056 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite on the functional interface for switching between different settings # Copyright (c) 2003-2008 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 63 } use FindBin; use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; use vars qw($LOCALEDIR $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); delete $ENV{$_} foreach qw(LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES LC_NUMERIC LC_MONETARY LC_TIME LANG); # Switching between different settings use File::Copy qw(copy); use vars qw($dir1 $dir2 $dir3 $f1 $f11 $f12 $f2 $f21 $f3 $f31 $class); # dmaketext in the middle $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); get_handle("en"); bindtextdomain("test", $LOCALEDIR); bindtextdomain("test2", $LOCALEDIR); textdomain("test"); $_[0] = __("Hello, world!"); $_[1] = pmaketext("Menu|File|", "Hello, world!"); $_[2] = __("Every story has a happy ending."); $_[3] = pmaketext("Menu|File|", "Every story has a happy ending."); $_[4] = dmaketext("test2", "Hello, world!"); $_[5] = dpmaketext("test2", "Menu|File|", "Hello, world!"); $_[6] = dmaketext("test2", "Every story has a happy ending."); $_[7] = dpmaketext("test2", "Menu|File|", "Every story has a happy ending."); $_[8] = __("Hello, world!"); $_[9] = pmaketext("Menu|File|", "Hello, world!"); $_[10] = __("Every story has a happy ending."); $_[11] = pmaketext("Menu|File|", "Every story has a happy ending."); return 1; }; # 1 ok($r, 1); # 2 ok($_[0], "Hiya :)"); # 3 ok($_[1], "Hiya :) under the File menu"); # 4 ok($_[2], "Every story has a happy ending."); # 5 ok($_[3], "Every story has a happy ending."); # 6 ok($_[4], "Hello, world!"); # 6 ok($_[5], "Hello, world!"); # 8 ok($_[6], "Pray it."); # 9 ok($_[7], "Pray it under the File menu"); # 10 ok($_[8], "Hiya :)"); # 11 ok($_[9], "Hiya :) under the File menu"); # 12 ok($_[10], "Every story has a happy ending."); # 13 ok($_[11], "Every story has a happy ending."); # Switch between domains $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); bindtextdomain("test2", $LOCALEDIR); get_handle("en"); textdomain("test"); $_[0] = __("Hello, world!"); $_[1] = __("Every story has a happy ending."); textdomain("test2"); $_[2] = __("Hello, world!"); $_[3] = __("Every story has a happy ending."); textdomain("test"); $_[4] = __("Hello, world!"); $_[5] = __("Every story has a happy ending."); return 1; }; # 14 ok($r, 1); # 15 ok($_[0], "Hiya :)"); # 16 ok($_[1], "Every story has a happy ending."); # 17 ok($_[2], "Hello, world!"); # 18 ok($_[3], "Pray it."); # 19 ok($_[4], "Hiya :)"); # 20 ok($_[5], "Every story has a happy ending."); # Switch between languages $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_[0] = __("Hello, world!"); get_handle("zh-tw"); $_[1] = __("Hello, world!"); get_handle("zh-cn"); $_[2] = __("Hello, world!"); return 1; }; # 21 ok($r, 1); # 22 ok($_[0], "Hiya :)"); # 23 ok($_[1], "janC"); # 24 ok($_[2], "Һá"); # Switch between languages - by environment $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); $ENV{"LANG"} = "en"; get_handle(); $_[0] = __("Hello, world!"); $ENV{"LANG"} = "zh-tw"; get_handle(); $_[1] = __("Hello, world!"); $ENV{"LANG"} = "zh-cn"; get_handle(); $_[2] = __("Hello, world!"); return 1; }; # 25 ok($r, 1); # 26 ok($_[0], "Hiya :)"); # 27 ok($_[1], "janC"); # 28 ok($_[2], "Һá"); # Switch between different language methods $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("en"); $_[0] = __("Hello, world!"); $ENV{"LANG"} = "zh-tw"; get_handle(); $_[1] = __("Hello, world!"); get_handle("zh-cn"); $_[2] = __("Hello, world!"); $ENV{"LANG"} = "en"; get_handle(); $_[3] = __("Hello, world!"); return 1; }; # 29 ok($r, 1); # 30 ok($_[0], "Hiya :)"); # 31 ok($_[1], "janC"); # 32 ok($_[2], "Һá"); # 33 ok($_[3], "Hiya :)"); # Reuse of a same text domain class $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); $ENV{"LANG"} = "en"; bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle(); $_[0] = __("Hello, world!"); $_[1] = __("Every story has a happy ending."); $_[2] = ref($Locale::Maketext::Gettext::Functions::LH); $_[2] =~ s/^(.+)::.*?$/$1/; bindtextdomain("test2", $LOCALEDIR); textdomain("test2"); get_handle("zh-tw"); $_[3] = __("Hello, world!"); $_[4] = __("Every story has a happy ending."); bindtextdomain("test", "/dev/null"); textdomain("test"); get_handle("en"); $_[5] = __("Hello, world!"); $_[6] = __("Every story has a happy ending."); bindtextdomain("test", $LOCALEDIR); textdomain("test"); get_handle("zh-cn"); $_[7] = __("Hello, world!"); $_[8] = __("Every story has a happy ending."); $_[9] = ref($Locale::Maketext::Gettext::Functions::LH); $_[9] =~ s/^(.+)::.*?$/$1/; return 1; }; # 34 ok($r, 1); # 35 ok($_[0], "Hiya :)"); # 36 ok($_[1], "Every story has a happy ending."); # 37 ok($_[3], "Hello, world!"); # 38 ok($_[4], "GƳRC"); # 39 ok($_[5], "Hello, world!"); # 40 ok($_[6], "Every story has a happy ending."); # 41 ok($_[7], "Һá"); # 42 ok($_[8], "Every story has a happy ending."); # 43 ok($_[2], $_[9]); # Language addition/removal $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); $dir1 = catdir($LOCALEDIR, "en", "LC_MESSAGES"); $dir2 = catdir($LOCALEDIR, "zh_TW", "LC_MESSAGES"); $dir3 = catdir($LOCALEDIR, "zh_CN", "LC_MESSAGES"); $f1 = catfile($dir1, "test_dyn.mo"); $f11 = catfile($dir1, "test.mo"); $f2 = catfile($dir2, "test_dyn.mo"); $f21 = catfile($dir2, "test.mo"); $f3 = catfile($dir3, "test_dyn.mo"); $f31 = catfile($dir3, "test.mo"); unlink $f1; unlink $f2; unlink $f3; bindtextdomain("test_dyn", $LOCALEDIR); textdomain("test_dyn"); get_handle("zh-tw"); $_[0] = __("Hello, world!"); get_handle("zh-cn"); $_[1] = __("Hello, world!"); copy $f21, $f2 or die "ERROR: $f21 $f2: $!"; textdomain("test_dyn"); get_handle("zh-tw"); $_[2] = __("Hello, world!"); get_handle("zh-cn"); $_[3] = __("Hello, world!"); unlink $f2; copy $f31, $f3 or die "ERROR: $f31 $f3: $!"; textdomain("test_dyn"); get_handle("zh-tw"); $_[4] = __("Hello, world!"); get_handle("zh-cn"); $_[5] = __("Hello, world!"); copy $f21, $f2 or die "ERROR: $f21 $f2: $!"; textdomain("test_dyn"); get_handle("zh-tw"); $_[6] = __("Hello, world!"); get_handle("zh-cn"); $_[7] = __("Hello, world!"); unlink $f2; unlink $f3; textdomain("test_dyn"); get_handle("zh-tw"); $_[8] = __("Hello, world!"); get_handle("zh-cn"); $_[9] = __("Hello, world!"); unlink $f1; unlink $f2; unlink $f3; return 1; }; # 44 ok($r, 1); # 45 ok($_[0], "Hello, world!"); # 46 ok($_[1], "Hello, world!"); # 47 ok($_[2], "janC"); # 48 ok($_[3], "Hello, world!"); # 49 ok($_[4], "Hello, world!"); # 50 ok($_[5], "Һá"); # 51 ok($_[6], "janC"); # 52 ok($_[7], "Һá"); # 53 ok($_[8], "Hello, world!"); # 54 ok($_[9], "Hello, world!"); # Garbage collection - drop abandoned language handles $r = eval { use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); $dir1 = catdir($LOCALEDIR, "en", "LC_MESSAGES"); $dir2 = catdir($LOCALEDIR, "zh_TW", "LC_MESSAGES"); $dir3 = catdir($LOCALEDIR, "zh_CN", "LC_MESSAGES"); $f1 = catfile($dir1, "test_dyn.mo"); $f11 = catfile($dir1, "test.mo"); $f2 = catfile($dir2, "test_dyn.mo"); $f21 = catfile($dir2, "test.mo"); $f3 = catfile($dir3, "test_dyn.mo"); $f31 = catfile($dir3, "test.mo"); unlink $f1; unlink $f2; unlink $f3; copy $f11, $f1 or die "ERROR: $f11 $f1: $!"; copy $f21, $f2 or die "ERROR: $f21 $f2: $!"; textdomain("test_dyn"); get_handle("en"); get_handle("zh-tw"); get_handle("zh-cn"); $class = ref($Locale::Maketext::Gettext::Functions::LH); $class =~ s/^(.+)::.*?$/$1/; unlink $f2; copy $f31, $f3 or die "ERROR: $f31 $f3: $!"; textdomain("test_dyn"); get_handle("en"); get_handle("zh-tw"); get_handle("zh-cn"); @_ = grep /^$class/, keys %Locale::Maketext::Gettext::Functions::LHS; return 1; }; # 55 ok($r, 1); # 56 ok(scalar(@_), 0); # Reload the text $r = eval { $dir1 = catdir($LOCALEDIR, "en", "LC_MESSAGES"); $f1 = catfile($dir1, "test_reload.mo"); $f11 = catfile($dir1, "test.mo"); $f12 = catfile($dir1, "test2.mo"); unlink $f1; copy $f11, $f1 or die "ERROR: $f11 $f1: $!"; use Locale::Maketext::Gettext::Functions; Locale::Maketext::Gettext::Functions::_reset(); @_ = qw(); bindtextdomain("test_reload", $LOCALEDIR); textdomain("test_reload"); get_handle("en"); $_[0] = __("Hello, world!"); $_[1] = __("Every story has a happy ending."); unlink $f1; copy $f12, $f1 or die "ERROR: $f12 $f1: $!"; $_[2] = __("Hello, world!"); $_[3] = __("Every story has a happy ending."); reload_text; $_[4] = __("Hello, world!"); $_[5] = __("Every story has a happy ending."); unlink $f1; return 1; }; # 57 ok($r, 1); # 58 ok($_[0], "Hiya :)"); # 59 ok($_[1], "Every story has a happy ending."); # 60 ok($_[2], "Hiya :)"); # 61 ok($_[3], "Every story has a happy ending."); # 62 ok($_[4], "Hello, world!"); # 63 ok($_[5], "Pray it."); # Garbage collection unlink catfile($LOCALEDIR, "en", "LC_MESSAGES", "test_dyn.mo"); unlink catfile($LOCALEDIR, "zh_TW", "LC_MESSAGES", "test_dyn.mo"); unlink catfile($LOCALEDIR, "zh_CN", "LC_MESSAGES", "test_dyn.mo"); unlink catfile($LOCALEDIR, "en", "LC_MESSAGES", "test_reload.mo"); Locale-Maketext-Gettext-1.32/t/11-command-line.t000555001750000144 364414010010654 21166 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Test suite on the maketext script # Copyright (c) 2003-2007 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 10 } use FindBin; use File::Spec::Functions qw(catdir catfile updir); use lib $FindBin::Bin; our ($LOCALEDIR, $r, $maketext); $LOCALEDIR = catdir($FindBin::Bin, "locale"); $maketext = catdir($FindBin::Bin, updir, "blib", "script", "maketext"); # The maketext script # Ordinary text unchanged $r = eval { delete $ENV{"LANG"}; delete $ENV{"LANGUAGE"}; delete $ENV{"TEXTDOMAINDIR"}; delete $ENV{"TEXTDOMAIN"}; @_ = `"$maketext" "Hello, world!"`; return 1; }; # 1 ok($r, 1); # 2 ok($_[0], "Hello, world!"); # Specify the text domain by the -d argument # English $r = eval { $ENV{"LANG"} = "C"; $ENV{"LANGUAGE"} = "C"; $ENV{"TEXTDOMAINDIR"} = $LOCALEDIR; delete $ENV{"TEXTDOMAIN"}; @_ = `"$maketext" -d test "Hello, world!"`; return 1; }; # 3 ok($r, 1); # 4 ok($_[0], "Hiya :)"); # Specify the text domain by the environment variable # English $r = eval { $ENV{"LANG"} = "C"; $ENV{"LANGUAGE"} = "C"; $ENV{"TEXTDOMAINDIR"} = $LOCALEDIR; $ENV{"TEXTDOMAIN"} = "test"; @_ = `"$maketext" "Hello, world!"`; return 1; }; # 5 ok($r, 1); # 6 ok($_[0], "Hiya :)"); # The -s argument $r = eval { $ENV{"LANG"} = "C"; $ENV{"LANGUAGE"} = "C"; $ENV{"TEXTDOMAINDIR"} = $LOCALEDIR; $ENV{"TEXTDOMAIN"} = "test"; @_ = `"$maketext" -s "Hello, world!"`; return 1; }; # 7 ok($r, 1); # 8 ok($_[0], "Hiya :)\n"); # Maketext $r = eval { $ENV{"LANG"} = "C"; $ENV{"LANGUAGE"} = "C"; $ENV{"TEXTDOMAINDIR"} = $LOCALEDIR; $ENV{"TEXTDOMAIN"} = "test"; @_ = `"$maketext" -s "[*,_1,directory,directories]" 5`; return 1; }; # 9 ok($r, 1); # 10 ok($_[0], "5 directories\n"); Locale-Maketext-Gettext-1.32/t/12-cache.t000555001750000144 503114010010654 17657 0ustar00imacatusers000000000000#! /usr/bin/perl -w # Basic test suite # Copyright (c) 2019-2021 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. use 5.008; use strict; use warnings; use Test; BEGIN { plan tests => 4 } use FindBin; use File::Spec::Functions qw(catdir catfile); use lib $FindBin::Bin; our ($LOCALEDIR, $r); $LOCALEDIR = catdir($FindBin::Bin, "locale"); # bindtextdomain $r = eval { my ($mo_file0, $mo_file1, $size, $atime, $mtime0, $mtime1); my ($FH, $content); $mo_file0 = catfile($LOCALEDIR, "en", "LC_MESSAGES", "test.mo"); $mo_file1 = catfile($LOCALEDIR, "en", "LC_MESSAGES", "test-cache.mo"); ($atime, $mtime0, $size) = (stat $mo_file0)[8,9,7]; open $FH, $mo_file0 or die "$mo_file0: $!"; binmode $FH or die "$mo_file0: $!"; read $FH, $content, $size or die "$mo_file0: $!"; close $FH or die "$mo_file0: $!"; open $FH, ">$mo_file1" or die "$mo_file1: $!"; binmode $FH or die "$mo_file1: $!"; print $FH $content or die "$mo_file1: $!"; close $FH or die "$mo_file1: $!"; $mtime1 = (stat $mo_file1)[9]; utime $atime, $mtime0, $mo_file1 or die "$mo_file1: $!"; require T_L10N; @_ = qw(); $_ = T_L10N->get_handle("en"); $_->bindtextdomain("test-cache", $LOCALEDIR); $_->textdomain("test-cache"); $_[0] = $_->maketext("Hello, world!"); # Update the file but keep the size and mtime open $FH, "+<$mo_file1" or die "$mo_file1: $!"; binmode $FH or die "$mo_file1: $!"; read $FH, $content, $size or die "$mo_file1: $!"; $content =~ s/Hiya/HiYa/; seek $FH, 0, 0 or die "$mo_file1: $!"; print $FH $content or die "$mo_file1: $!"; close $FH or die "$mo_file1: $!"; utime $atime, $mtime0, $mo_file1 or die "$mo_file1: $!"; $_->textdomain("test-cache"); $_[1] = $_->maketext("Hello, world!"); # Update the mtime utime $atime, $mtime1, $mo_file1 or die "$mo_file1: $!"; $_->textdomain("test-cache"); $_[2] = $_->maketext("Hello, world!"); # Remove the file unlink $mo_file1 or die "$mo_file1: $!"; return 1; }; # 1 ok($r, 1); # 2 ok($_[0], "Hiya :)"); # 3 - cache not updated ok($_[1], "Hiya :)"); # 4 - cache updated ok($_[2], "HiYa :)"); Locale-Maketext-Gettext-1.32/t/99-pod.t000555001750000144 22114010010654 17371 0ustar00imacatusers000000000000#!/usr/bin/perl use Test::More; eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); Locale-Maketext-Gettext-1.32/t/T_L10N.pm000444001750000144 76214010010654 17465 0ustar00imacatusers000000000000# Test localization class and its subclasses # Copyright (c) 2003 imacat. All rights reserved. This program is free # software; you can redistribute it and/or modify it under the same terms # as Perl itself. package T_L10N; use base qw(Locale::Maketext::Gettext); return 1; package T_L10N::en; use base qw(Locale::Maketext::Gettext); return 1; package T_L10N::zh_tw; use base qw(Locale::Maketext::Gettext); return 1; package T_L10N::zh_cn; use base qw(Locale::Maketext::Gettext); return 1; Locale-Maketext-Gettext-1.32/t/locale000755001750000144 014010010654 17307 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/C000755001750000144 014010010654 17471 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/C/LC_MESSAGES000755001750000144 014010010654 21256 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/C/LC_MESSAGES/test.mo000444001750000144 114414010010654 22727 0ustar00imacatusers000000000000<\p qr$,HHello, world!Menu|File|Hello, world!Menu|View|Hello, world!Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: English MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Plural-Forms: nplurals=2; plural=n != 1; Hiya :)Hiya :) under the File menuHiya :) under the View menuLocale-Maketext-Gettext-1.32/t/locale/en000755001750000144 014010010654 17711 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/en/LC_MESSAGES000755001750000144 014010010654 21476 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/en/LC_MESSAGES/bad.mo000444001750000144 14414010010654 22675 0ustar00imacatusers0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Locale-Maketext-Gettext-1.32/t/locale/en/LC_MESSAGES/test.mo000444001750000144 114414010010654 23147 0ustar00imacatusers000000000000<\p qr$,HHello, world!Menu|File|Hello, world!Menu|View|Hello, world!Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: English MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Plural-Forms: nplurals=2; plural=n != 1; Hiya :)Hiya :) under the File menuHiya :) under the View menuLocale-Maketext-Gettext-1.32/t/locale/en/LC_MESSAGES/test2.mo000444001750000144 123414010010654 23231 0ustar00imacatusers000000000000<\pq**s[dEvery story has a happy ending.Menu|File|Every story has a happy ending.Menu|View|Every story has a happy ending.Project-Id-Version: test2 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: English MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Plural-Forms: nplurals=2; plural=n != 1; Pray it.Pray it under the File menuPray it under the View menuLocale-Maketext-Gettext-1.32/t/locale/en/LC_MESSAGES/test_be.mo000444001750000144 70614010010654 23600 0ustar00imacatusers000000000000,<P Q^_Hello, world!Project-Id-Version: test_be 1.0 POT-Creation-Date: 2003-04-24 21:52+0800 PO-Revision-Date: 2003-04-24 21:52+0800 Last-Translator: imacat Language-Team: English MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Plural-Forms: nplurals=2; plural=n != 1; Hiya :)Locale-Maketext-Gettext-1.32/t/locale/en/LC_MESSAGES/test_utf8.mo000444001750000144 114114010010654 24112 0ustar00imacatusers000000000000<\p qo!)EHello, world!Menu|File|Hello, world!Menu|View|Hello, world!Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: English MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Plural-Forms: nplurals=2; plural=n != 1; Hiya :)Hiya :) under the File menuHiya :) under the View menuLocale-Maketext-Gettext-1.32/t/locale/zh_CN000755001750000144 014010010654 20310 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/zh_CN/LC_MESSAGES000755001750000144 014010010654 22075 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/zh_CN/LC_MESSAGES/test.mo000444001750000144 113314010010654 23544 0ustar00imacatusers000000000000<\p qv(1FHello, world!Menu|File|Hello, world!Menu|View|Hello, world!Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: Simplified Chinese MIME-Version: 1.0 Content-Type: text/plain; charset=GB2312 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; Һá˵µĴҺá˵µĴҺáLocale-Maketext-Gettext-1.32/t/locale/zh_CN/LC_MESSAGES/test_be.mo000444001750000144 71414010010654 24176 0ustar00imacatusers000000000000,<P Qc_Hello, world!Project-Id-Version: test_be 1.0 POT-Creation-Date: 2003-04-24 21:52+0800 PO-Revision-Date: 2003-04-24 21:52+0800 Last-Translator: imacat Language-Team: Traditional Chinese MIME-Version: 1.0 Content-Type: text/plain; charset=GB2312 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; ҺáLocale-Maketext-Gettext-1.32/t/locale/zh_CN/LC_MESSAGES/test_utf8.mo000444001750000144 116214010010654 24514 0ustar00imacatusers000000000000<\p qu '4SHello, world!Menu|File|Hello, world!Menu|View|Hello, world!Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: Simplified Chinese MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; 大家好。档案菜单下的大家好。浏览菜单下的大家好。Locale-Maketext-Gettext-1.32/t/locale/zh_TW000755001750000144 014010010654 20342 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/zh_TW/LC_MESSAGES000755001750000144 014010010654 22127 5ustar00imacatusers000000000000Locale-Maketext-Gettext-1.32/t/locale/zh_TW/LC_MESSAGES/test.mo000444001750000144 113214010010654 23575 0ustar00imacatusers000000000000<\p qu'0EHello, world!Menu|File|Hello, world!Menu|View|Hello, world!Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: Traditional Chinese MIME-Version: 1.0 Content-Type: text/plain; charset=Big5 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; janCɮ׿UjanCsUjanCLocale-Maketext-Gettext-1.32/t/locale/zh_TW/LC_MESSAGES/test2.mo000444001750000144 126514010010654 23666 0ustar00imacatusers000000000000<\pq**v^ s Every story has a happy ending.Menu|File|Every story has a happy ending.Menu|View|Every story has a happy ending.Project-Id-Version: test2 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: Traditional Chinese MIME-Version: 1.0 Content-Type: text/plain; charset=Big5 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; GƳRCɮ׿UGƳRCsUGƳRCLocale-Maketext-Gettext-1.32/t/locale/zh_TW/LC_MESSAGES/test_be.mo000444001750000144 71214010010654 24226 0ustar00imacatusers000000000000,<P Qa_Hello, world!Project-Id-Version: test_be 1.0 POT-Creation-Date: 2003-04-24 21:52+0800 PO-Revision-Date: 2003-04-24 21:52+0800 Last-Translator: imacat Language-Team: Traditional Chinese MIME-Version: 1.0 Content-Type: text/plain; charset=Big5 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; janCLocale-Maketext-Gettext-1.32/t/locale/zh_TW/LC_MESSAGES/test_utf8.mo000444001750000144 116314010010654 24547 0ustar00imacatusers000000000000<\p qv (5THello, world!Menu|File|Hello, world!Menu|View|Hello, world!Project-Id-Version: test 1.1 Report-Msgid-Bugs-To: POT-Creation-Date: 2008-02-19 12:31+0800 PO-Revision-Date: 2008-02-19 12:31+0800 Last-Translator: imacat Language-Team: Traditional Chinese MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; 大家好。檔案選單下的大家好。瀏覽選單下的大家好。