Initialized from version 1.28 (2009/6/27).
This commit is contained in:
		
							
								
								
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					Makefile
 | 
				
			||||||
 | 
					Makefile.old
 | 
				
			||||||
 | 
					blib
 | 
				
			||||||
 | 
					Build
 | 
				
			||||||
 | 
					_build
 | 
				
			||||||
 | 
					MYMETA.json
 | 
				
			||||||
 | 
					MYMETA.yml
 | 
				
			||||||
 | 
					pm_to_blib
 | 
				
			||||||
							
								
								
									
										131
									
								
								Artistic
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								Artistic
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								 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
 | 
				
			||||||
							
								
								
									
										4
									
								
								BUGS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								BUGS
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					Please send your bug reports to me directly, at
 | 
				
			||||||
 | 
					imacat@mail.imacat.idv.tw.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sorry that mailing list is not available yet till this time.
 | 
				
			||||||
							
								
								
									
										22
									
								
								Build.PL
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								Build.PL
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					#! /usr/bin/perl -w
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use Module::Build;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $build = Module::Build->new(
 | 
				
			||||||
 | 
					    dist_name       => "Locale-Maketext-Gettext",
 | 
				
			||||||
 | 
					    dist_version    => "1.28",
 | 
				
			||||||
 | 
					    dist_abstract   => "Joins gettext and Maketext frameworks",
 | 
				
			||||||
 | 
					    dist_author     => "imacat <imacat\@mail.imacat.idv.tw>",
 | 
				
			||||||
 | 
					    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" ],
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$build->create_build_script;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__END__
 | 
				
			||||||
							
								
								
									
										674
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										674
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,674 @@
 | 
				
			|||||||
 | 
					                    GNU GENERAL PUBLIC LICENSE
 | 
				
			||||||
 | 
					                       Version 3, 29 June 2007
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 | 
				
			||||||
 | 
					 Everyone is permitted to copy and distribute verbatim copies
 | 
				
			||||||
 | 
					 of this license document, but changing it is not allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            Preamble
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The GNU General Public License is a free, copyleft license for
 | 
				
			||||||
 | 
					software and other kinds of works.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The licenses for most software and other practical works are designed
 | 
				
			||||||
 | 
					to take away your freedom to share and change the works.  By contrast,
 | 
				
			||||||
 | 
					the GNU General Public License is intended to guarantee your freedom to
 | 
				
			||||||
 | 
					share and change all versions of a program--to make sure it remains free
 | 
				
			||||||
 | 
					software for all its users.  We, the Free Software Foundation, use the
 | 
				
			||||||
 | 
					GNU General Public License for most of our software; it applies also to
 | 
				
			||||||
 | 
					any other work released this way by its authors.  You can apply it to
 | 
				
			||||||
 | 
					your programs, too.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When we speak of free software, we are referring to freedom, not
 | 
				
			||||||
 | 
					price.  Our General Public Licenses are designed to make sure that you
 | 
				
			||||||
 | 
					have the freedom to distribute copies of free software (and charge for
 | 
				
			||||||
 | 
					them if you wish), that you receive source code or can get it if you
 | 
				
			||||||
 | 
					want it, that you can change the software or use pieces of it in new
 | 
				
			||||||
 | 
					free programs, and that you know you can do these things.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To protect your rights, we need to prevent others from denying you
 | 
				
			||||||
 | 
					these rights or asking you to surrender the rights.  Therefore, you have
 | 
				
			||||||
 | 
					certain responsibilities if you distribute copies of the software, or if
 | 
				
			||||||
 | 
					you modify it: responsibilities to respect the freedom of others.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  For example, if you distribute copies of such a program, whether
 | 
				
			||||||
 | 
					gratis or for a fee, you must pass on to the recipients the same
 | 
				
			||||||
 | 
					freedoms that you received.  You must make sure that they, too, receive
 | 
				
			||||||
 | 
					or can get the source code.  And you must show them these terms so they
 | 
				
			||||||
 | 
					know their rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Developers that use the GNU GPL protect your rights with two steps:
 | 
				
			||||||
 | 
					(1) assert copyright on the software, and (2) offer you this License
 | 
				
			||||||
 | 
					giving you legal permission to copy, distribute and/or modify it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  For the developers' and authors' protection, the GPL clearly explains
 | 
				
			||||||
 | 
					that there is no warranty for this free software.  For both users' and
 | 
				
			||||||
 | 
					authors' sake, the GPL requires that modified versions be marked as
 | 
				
			||||||
 | 
					changed, so that their problems will not be attributed erroneously to
 | 
				
			||||||
 | 
					authors of previous versions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Some devices are designed to deny users access to install or run
 | 
				
			||||||
 | 
					modified versions of the software inside them, although the manufacturer
 | 
				
			||||||
 | 
					can do so.  This is fundamentally incompatible with the aim of
 | 
				
			||||||
 | 
					protecting users' freedom to change the software.  The systematic
 | 
				
			||||||
 | 
					pattern of such abuse occurs in the area of products for individuals to
 | 
				
			||||||
 | 
					use, which is precisely where it is most unacceptable.  Therefore, we
 | 
				
			||||||
 | 
					have designed this version of the GPL to prohibit the practice for those
 | 
				
			||||||
 | 
					products.  If such problems arise substantially in other domains, we
 | 
				
			||||||
 | 
					stand ready to extend this provision to those domains in future versions
 | 
				
			||||||
 | 
					of the GPL, as needed to protect the freedom of users.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Finally, every program is threatened constantly by software patents.
 | 
				
			||||||
 | 
					States should not allow patents to restrict development and use of
 | 
				
			||||||
 | 
					software on general-purpose computers, but in those that do, we wish to
 | 
				
			||||||
 | 
					avoid the special danger that patents applied to a free program could
 | 
				
			||||||
 | 
					make it effectively proprietary.  To prevent this, the GPL assures that
 | 
				
			||||||
 | 
					patents cannot be used to render the program non-free.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The precise terms and conditions for copying, distribution and
 | 
				
			||||||
 | 
					modification follow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                       TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  0. Definitions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "This License" refers to version 3 of the GNU General Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Copyright" also means copyright-like laws that apply to other kinds of
 | 
				
			||||||
 | 
					works, such as semiconductor masks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "The Program" refers to any copyrightable work licensed under this
 | 
				
			||||||
 | 
					License.  Each licensee is addressed as "you".  "Licensees" and
 | 
				
			||||||
 | 
					"recipients" may be individuals or organizations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "modify" a work means to copy from or adapt all or part of the work
 | 
				
			||||||
 | 
					in a fashion requiring copyright permission, other than the making of an
 | 
				
			||||||
 | 
					exact copy.  The resulting work is called a "modified version" of the
 | 
				
			||||||
 | 
					earlier work or a work "based on" the earlier work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "covered work" means either the unmodified Program or a work based
 | 
				
			||||||
 | 
					on the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "propagate" a work means to do anything with it that, without
 | 
				
			||||||
 | 
					permission, would make you directly or secondarily liable for
 | 
				
			||||||
 | 
					infringement under applicable copyright law, except executing it on a
 | 
				
			||||||
 | 
					computer or modifying a private copy.  Propagation includes copying,
 | 
				
			||||||
 | 
					distribution (with or without modification), making available to the
 | 
				
			||||||
 | 
					public, and in some countries other activities as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To "convey" a work means any kind of propagation that enables other
 | 
				
			||||||
 | 
					parties to make or receive copies.  Mere interaction with a user through
 | 
				
			||||||
 | 
					a computer network, with no transfer of a copy, is not conveying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  An interactive user interface displays "Appropriate Legal Notices"
 | 
				
			||||||
 | 
					to the extent that it includes a convenient and prominently visible
 | 
				
			||||||
 | 
					feature that (1) displays an appropriate copyright notice, and (2)
 | 
				
			||||||
 | 
					tells the user that there is no warranty for the work (except to the
 | 
				
			||||||
 | 
					extent that warranties are provided), that licensees may convey the
 | 
				
			||||||
 | 
					work under this License, and how to view a copy of this License.  If
 | 
				
			||||||
 | 
					the interface presents a list of user commands or options, such as a
 | 
				
			||||||
 | 
					menu, a prominent item in the list meets this criterion.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. Source Code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "source code" for a work means the preferred form of the work
 | 
				
			||||||
 | 
					for making modifications to it.  "Object code" means any non-source
 | 
				
			||||||
 | 
					form of a work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "Standard Interface" means an interface that either is an official
 | 
				
			||||||
 | 
					standard defined by a recognized standards body, or, in the case of
 | 
				
			||||||
 | 
					interfaces specified for a particular programming language, one that
 | 
				
			||||||
 | 
					is widely used among developers working in that language.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "System Libraries" of an executable work include anything, other
 | 
				
			||||||
 | 
					than the work as a whole, that (a) is included in the normal form of
 | 
				
			||||||
 | 
					packaging a Major Component, but which is not part of that Major
 | 
				
			||||||
 | 
					Component, and (b) serves only to enable use of the work with that
 | 
				
			||||||
 | 
					Major Component, or to implement a Standard Interface for which an
 | 
				
			||||||
 | 
					implementation is available to the public in source code form.  A
 | 
				
			||||||
 | 
					"Major Component", in this context, means a major essential component
 | 
				
			||||||
 | 
					(kernel, window system, and so on) of the specific operating system
 | 
				
			||||||
 | 
					(if any) on which the executable work runs, or a compiler used to
 | 
				
			||||||
 | 
					produce the work, or an object code interpreter used to run it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The "Corresponding Source" for a work in object code form means all
 | 
				
			||||||
 | 
					the source code needed to generate, install, and (for an executable
 | 
				
			||||||
 | 
					work) run the object code and to modify the work, including scripts to
 | 
				
			||||||
 | 
					control those activities.  However, it does not include the work's
 | 
				
			||||||
 | 
					System Libraries, or general-purpose tools or generally available free
 | 
				
			||||||
 | 
					programs which are used unmodified in performing those activities but
 | 
				
			||||||
 | 
					which are not part of the work.  For example, Corresponding Source
 | 
				
			||||||
 | 
					includes interface definition files associated with source files for
 | 
				
			||||||
 | 
					the work, and the source code for shared libraries and dynamically
 | 
				
			||||||
 | 
					linked subprograms that the work is specifically designed to require,
 | 
				
			||||||
 | 
					such as by intimate data communication or control flow between those
 | 
				
			||||||
 | 
					subprograms and other parts of the work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Corresponding Source need not include anything that users
 | 
				
			||||||
 | 
					can regenerate automatically from other parts of the Corresponding
 | 
				
			||||||
 | 
					Source.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Corresponding Source for a work in source code form is that
 | 
				
			||||||
 | 
					same work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. Basic Permissions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  All rights granted under this License are granted for the term of
 | 
				
			||||||
 | 
					copyright on the Program, and are irrevocable provided the stated
 | 
				
			||||||
 | 
					conditions are met.  This License explicitly affirms your unlimited
 | 
				
			||||||
 | 
					permission to run the unmodified Program.  The output from running a
 | 
				
			||||||
 | 
					covered work is covered by this License only if the output, given its
 | 
				
			||||||
 | 
					content, constitutes a covered work.  This License acknowledges your
 | 
				
			||||||
 | 
					rights of fair use or other equivalent, as provided by copyright law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may make, run and propagate covered works that you do not
 | 
				
			||||||
 | 
					convey, without conditions so long as your license otherwise remains
 | 
				
			||||||
 | 
					in force.  You may convey covered works to others for the sole purpose
 | 
				
			||||||
 | 
					of having them make modifications exclusively for you, or provide you
 | 
				
			||||||
 | 
					with facilities for running those works, provided that you comply with
 | 
				
			||||||
 | 
					the terms of this License in conveying all material for which you do
 | 
				
			||||||
 | 
					not control copyright.  Those thus making or running the covered works
 | 
				
			||||||
 | 
					for you must do so exclusively on your behalf, under your direction
 | 
				
			||||||
 | 
					and control, on terms that prohibit them from making any copies of
 | 
				
			||||||
 | 
					your copyrighted material outside their relationship with you.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Conveying under any other circumstances is permitted solely under
 | 
				
			||||||
 | 
					the conditions stated below.  Sublicensing is not allowed; section 10
 | 
				
			||||||
 | 
					makes it unnecessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  No covered work shall be deemed part of an effective technological
 | 
				
			||||||
 | 
					measure under any applicable law fulfilling obligations under article
 | 
				
			||||||
 | 
					11 of the WIPO copyright treaty adopted on 20 December 1996, or
 | 
				
			||||||
 | 
					similar laws prohibiting or restricting circumvention of such
 | 
				
			||||||
 | 
					measures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When you convey a covered work, you waive any legal power to forbid
 | 
				
			||||||
 | 
					circumvention of technological measures to the extent such circumvention
 | 
				
			||||||
 | 
					is effected by exercising rights under this License with respect to
 | 
				
			||||||
 | 
					the covered work, and you disclaim any intention to limit operation or
 | 
				
			||||||
 | 
					modification of the work as a means of enforcing, against the work's
 | 
				
			||||||
 | 
					users, your or third parties' legal rights to forbid circumvention of
 | 
				
			||||||
 | 
					technological measures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  4. Conveying Verbatim Copies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey verbatim copies of the Program's source code as you
 | 
				
			||||||
 | 
					receive it, in any medium, provided that you conspicuously and
 | 
				
			||||||
 | 
					appropriately publish on each copy an appropriate copyright notice;
 | 
				
			||||||
 | 
					keep intact all notices stating that this License and any
 | 
				
			||||||
 | 
					non-permissive terms added in accord with section 7 apply to the code;
 | 
				
			||||||
 | 
					keep intact all notices of the absence of any warranty; and give all
 | 
				
			||||||
 | 
					recipients a copy of this License along with the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may charge any price or no price for each copy that you convey,
 | 
				
			||||||
 | 
					and you may offer support or warranty protection for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  5. Conveying Modified Source Versions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey a work based on the Program, or the modifications to
 | 
				
			||||||
 | 
					produce it from the Program, in the form of source code under the
 | 
				
			||||||
 | 
					terms of section 4, provided that you also meet all of these conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) The work must carry prominent notices stating that you modified
 | 
				
			||||||
 | 
					    it, and giving a relevant date.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) The work must carry prominent notices stating that it is
 | 
				
			||||||
 | 
					    released under this License and any conditions added under section
 | 
				
			||||||
 | 
					    7.  This requirement modifies the requirement in section 4 to
 | 
				
			||||||
 | 
					    "keep intact all notices".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) You must license the entire work, as a whole, under this
 | 
				
			||||||
 | 
					    License to anyone who comes into possession of a copy.  This
 | 
				
			||||||
 | 
					    License will therefore apply, along with any applicable section 7
 | 
				
			||||||
 | 
					    additional terms, to the whole of the work, and all its parts,
 | 
				
			||||||
 | 
					    regardless of how they are packaged.  This License gives no
 | 
				
			||||||
 | 
					    permission to license the work in any other way, but it does not
 | 
				
			||||||
 | 
					    invalidate such permission if you have separately received it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) If the work has interactive user interfaces, each must display
 | 
				
			||||||
 | 
					    Appropriate Legal Notices; however, if the Program has interactive
 | 
				
			||||||
 | 
					    interfaces that do not display Appropriate Legal Notices, your
 | 
				
			||||||
 | 
					    work need not make them do so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A compilation of a covered work with other separate and independent
 | 
				
			||||||
 | 
					works, which are not by their nature extensions of the covered work,
 | 
				
			||||||
 | 
					and which are not combined with it such as to form a larger program,
 | 
				
			||||||
 | 
					in or on a volume of a storage or distribution medium, is called an
 | 
				
			||||||
 | 
					"aggregate" if the compilation and its resulting copyright are not
 | 
				
			||||||
 | 
					used to limit the access or legal rights of the compilation's users
 | 
				
			||||||
 | 
					beyond what the individual works permit.  Inclusion of a covered work
 | 
				
			||||||
 | 
					in an aggregate does not cause this License to apply to the other
 | 
				
			||||||
 | 
					parts of the aggregate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  6. Conveying Non-Source Forms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may convey a covered work in object code form under the terms
 | 
				
			||||||
 | 
					of sections 4 and 5, provided that you also convey the
 | 
				
			||||||
 | 
					machine-readable Corresponding Source under the terms of this License,
 | 
				
			||||||
 | 
					in one of these ways:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Convey the object code in, or embodied in, a physical product
 | 
				
			||||||
 | 
					    (including a physical distribution medium), accompanied by the
 | 
				
			||||||
 | 
					    Corresponding Source fixed on a durable physical medium
 | 
				
			||||||
 | 
					    customarily used for software interchange.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Convey the object code in, or embodied in, a physical product
 | 
				
			||||||
 | 
					    (including a physical distribution medium), accompanied by a
 | 
				
			||||||
 | 
					    written offer, valid for at least three years and valid for as
 | 
				
			||||||
 | 
					    long as you offer spare parts or customer support for that product
 | 
				
			||||||
 | 
					    model, to give anyone who possesses the object code either (1) a
 | 
				
			||||||
 | 
					    copy of the Corresponding Source for all the software in the
 | 
				
			||||||
 | 
					    product that is covered by this License, on a durable physical
 | 
				
			||||||
 | 
					    medium customarily used for software interchange, for a price no
 | 
				
			||||||
 | 
					    more than your reasonable cost of physically performing this
 | 
				
			||||||
 | 
					    conveying of source, or (2) access to copy the
 | 
				
			||||||
 | 
					    Corresponding Source from a network server at no charge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Convey individual copies of the object code with a copy of the
 | 
				
			||||||
 | 
					    written offer to provide the Corresponding Source.  This
 | 
				
			||||||
 | 
					    alternative is allowed only occasionally and noncommercially, and
 | 
				
			||||||
 | 
					    only if you received the object code with such an offer, in accord
 | 
				
			||||||
 | 
					    with subsection 6b.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) Convey the object code by offering access from a designated
 | 
				
			||||||
 | 
					    place (gratis or for a charge), and offer equivalent access to the
 | 
				
			||||||
 | 
					    Corresponding Source in the same way through the same place at no
 | 
				
			||||||
 | 
					    further charge.  You need not require recipients to copy the
 | 
				
			||||||
 | 
					    Corresponding Source along with the object code.  If the place to
 | 
				
			||||||
 | 
					    copy the object code is a network server, the Corresponding Source
 | 
				
			||||||
 | 
					    may be on a different server (operated by you or a third party)
 | 
				
			||||||
 | 
					    that supports equivalent copying facilities, provided you maintain
 | 
				
			||||||
 | 
					    clear directions next to the object code saying where to find the
 | 
				
			||||||
 | 
					    Corresponding Source.  Regardless of what server hosts the
 | 
				
			||||||
 | 
					    Corresponding Source, you remain obligated to ensure that it is
 | 
				
			||||||
 | 
					    available for as long as needed to satisfy these requirements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    e) Convey the object code using peer-to-peer transmission, provided
 | 
				
			||||||
 | 
					    you inform other peers where the object code and Corresponding
 | 
				
			||||||
 | 
					    Source of the work are being offered to the general public at no
 | 
				
			||||||
 | 
					    charge under subsection 6d.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A separable portion of the object code, whose source code is excluded
 | 
				
			||||||
 | 
					from the Corresponding Source as a System Library, need not be
 | 
				
			||||||
 | 
					included in conveying the object code work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "User Product" is either (1) a "consumer product", which means any
 | 
				
			||||||
 | 
					tangible personal property which is normally used for personal, family,
 | 
				
			||||||
 | 
					or household purposes, or (2) anything designed or sold for incorporation
 | 
				
			||||||
 | 
					into a dwelling.  In determining whether a product is a consumer product,
 | 
				
			||||||
 | 
					doubtful cases shall be resolved in favor of coverage.  For a particular
 | 
				
			||||||
 | 
					product received by a particular user, "normally used" refers to a
 | 
				
			||||||
 | 
					typical or common use of that class of product, regardless of the status
 | 
				
			||||||
 | 
					of the particular user or of the way in which the particular user
 | 
				
			||||||
 | 
					actually uses, or expects or is expected to use, the product.  A product
 | 
				
			||||||
 | 
					is a consumer product regardless of whether the product has substantial
 | 
				
			||||||
 | 
					commercial, industrial or non-consumer uses, unless such uses represent
 | 
				
			||||||
 | 
					the only significant mode of use of the product.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Installation Information" for a User Product means any methods,
 | 
				
			||||||
 | 
					procedures, authorization keys, or other information required to install
 | 
				
			||||||
 | 
					and execute modified versions of a covered work in that User Product from
 | 
				
			||||||
 | 
					a modified version of its Corresponding Source.  The information must
 | 
				
			||||||
 | 
					suffice to ensure that the continued functioning of the modified object
 | 
				
			||||||
 | 
					code is in no case prevented or interfered with solely because
 | 
				
			||||||
 | 
					modification has been made.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you convey an object code work under this section in, or with, or
 | 
				
			||||||
 | 
					specifically for use in, a User Product, and the conveying occurs as
 | 
				
			||||||
 | 
					part of a transaction in which the right of possession and use of the
 | 
				
			||||||
 | 
					User Product is transferred to the recipient in perpetuity or for a
 | 
				
			||||||
 | 
					fixed term (regardless of how the transaction is characterized), the
 | 
				
			||||||
 | 
					Corresponding Source conveyed under this section must be accompanied
 | 
				
			||||||
 | 
					by the Installation Information.  But this requirement does not apply
 | 
				
			||||||
 | 
					if neither you nor any third party retains the ability to install
 | 
				
			||||||
 | 
					modified object code on the User Product (for example, the work has
 | 
				
			||||||
 | 
					been installed in ROM).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The requirement to provide Installation Information does not include a
 | 
				
			||||||
 | 
					requirement to continue to provide support service, warranty, or updates
 | 
				
			||||||
 | 
					for a work that has been modified or installed by the recipient, or for
 | 
				
			||||||
 | 
					the User Product in which it has been modified or installed.  Access to a
 | 
				
			||||||
 | 
					network may be denied when the modification itself materially and
 | 
				
			||||||
 | 
					adversely affects the operation of the network or violates the rules and
 | 
				
			||||||
 | 
					protocols for communication across the network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Corresponding Source conveyed, and Installation Information provided,
 | 
				
			||||||
 | 
					in accord with this section must be in a format that is publicly
 | 
				
			||||||
 | 
					documented (and with an implementation available to the public in
 | 
				
			||||||
 | 
					source code form), and must require no special password or key for
 | 
				
			||||||
 | 
					unpacking, reading or copying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  7. Additional Terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  "Additional permissions" are terms that supplement the terms of this
 | 
				
			||||||
 | 
					License by making exceptions from one or more of its conditions.
 | 
				
			||||||
 | 
					Additional permissions that are applicable to the entire Program shall
 | 
				
			||||||
 | 
					be treated as though they were included in this License, to the extent
 | 
				
			||||||
 | 
					that they are valid under applicable law.  If additional permissions
 | 
				
			||||||
 | 
					apply only to part of the Program, that part may be used separately
 | 
				
			||||||
 | 
					under those permissions, but the entire Program remains governed by
 | 
				
			||||||
 | 
					this License without regard to the additional permissions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When you convey a copy of a covered work, you may at your option
 | 
				
			||||||
 | 
					remove any additional permissions from that copy, or from any part of
 | 
				
			||||||
 | 
					it.  (Additional permissions may be written to require their own
 | 
				
			||||||
 | 
					removal in certain cases when you modify the work.)  You may place
 | 
				
			||||||
 | 
					additional permissions on material, added by you to a covered work,
 | 
				
			||||||
 | 
					for which you have or can give appropriate copyright permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Notwithstanding any other provision of this License, for material you
 | 
				
			||||||
 | 
					add to a covered work, you may (if authorized by the copyright holders of
 | 
				
			||||||
 | 
					that material) supplement the terms of this License with terms:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Disclaiming warranty or limiting liability differently from the
 | 
				
			||||||
 | 
					    terms of sections 15 and 16 of this License; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Requiring preservation of specified reasonable legal notices or
 | 
				
			||||||
 | 
					    author attributions in that material or in the Appropriate Legal
 | 
				
			||||||
 | 
					    Notices displayed by works containing it; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Prohibiting misrepresentation of the origin of that material, or
 | 
				
			||||||
 | 
					    requiring that modified versions of such material be marked in
 | 
				
			||||||
 | 
					    reasonable ways as different from the original version; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d) Limiting the use for publicity purposes of names of licensors or
 | 
				
			||||||
 | 
					    authors of the material; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    e) Declining to grant rights under trademark law for use of some
 | 
				
			||||||
 | 
					    trade names, trademarks, or service marks; or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    f) Requiring indemnification of licensors and authors of that
 | 
				
			||||||
 | 
					    material by anyone who conveys the material (or modified versions of
 | 
				
			||||||
 | 
					    it) with contractual assumptions of liability to the recipient, for
 | 
				
			||||||
 | 
					    any liability that these contractual assumptions directly impose on
 | 
				
			||||||
 | 
					    those licensors and authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  All other non-permissive additional terms are considered "further
 | 
				
			||||||
 | 
					restrictions" within the meaning of section 10.  If the Program as you
 | 
				
			||||||
 | 
					received it, or any part of it, contains a notice stating that it is
 | 
				
			||||||
 | 
					governed by this License along with a term that is a further
 | 
				
			||||||
 | 
					restriction, you may remove that term.  If a license document contains
 | 
				
			||||||
 | 
					a further restriction but permits relicensing or conveying under this
 | 
				
			||||||
 | 
					License, you may add to a covered work material governed by the terms
 | 
				
			||||||
 | 
					of that license document, provided that the further restriction does
 | 
				
			||||||
 | 
					not survive such relicensing or conveying.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you add terms to a covered work in accord with this section, you
 | 
				
			||||||
 | 
					must place, in the relevant source files, a statement of the
 | 
				
			||||||
 | 
					additional terms that apply to those files, or a notice indicating
 | 
				
			||||||
 | 
					where to find the applicable terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Additional terms, permissive or non-permissive, may be stated in the
 | 
				
			||||||
 | 
					form of a separately written license, or stated as exceptions;
 | 
				
			||||||
 | 
					the above requirements apply either way.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  8. Termination.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may not propagate or modify a covered work except as expressly
 | 
				
			||||||
 | 
					provided under this License.  Any attempt otherwise to propagate or
 | 
				
			||||||
 | 
					modify it is void, and will automatically terminate your rights under
 | 
				
			||||||
 | 
					this License (including any patent licenses granted under the third
 | 
				
			||||||
 | 
					paragraph of section 11).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  However, if you cease all violation of this License, then your
 | 
				
			||||||
 | 
					license from a particular copyright holder is reinstated (a)
 | 
				
			||||||
 | 
					provisionally, unless and until the copyright holder explicitly and
 | 
				
			||||||
 | 
					finally terminates your license, and (b) permanently, if the copyright
 | 
				
			||||||
 | 
					holder fails to notify you of the violation by some reasonable means
 | 
				
			||||||
 | 
					prior to 60 days after the cessation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Moreover, your license from a particular copyright holder is
 | 
				
			||||||
 | 
					reinstated permanently if the copyright holder notifies you of the
 | 
				
			||||||
 | 
					violation by some reasonable means, this is the first time you have
 | 
				
			||||||
 | 
					received notice of violation of this License (for any work) from that
 | 
				
			||||||
 | 
					copyright holder, and you cure the violation prior to 30 days after
 | 
				
			||||||
 | 
					your receipt of the notice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Termination of your rights under this section does not terminate the
 | 
				
			||||||
 | 
					licenses of parties who have received copies or rights from you under
 | 
				
			||||||
 | 
					this License.  If your rights have been terminated and not permanently
 | 
				
			||||||
 | 
					reinstated, you do not qualify to receive new licenses for the same
 | 
				
			||||||
 | 
					material under section 10.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  9. Acceptance Not Required for Having Copies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You are not required to accept this License in order to receive or
 | 
				
			||||||
 | 
					run a copy of the Program.  Ancillary propagation of a covered work
 | 
				
			||||||
 | 
					occurring solely as a consequence of using peer-to-peer transmission
 | 
				
			||||||
 | 
					to receive a copy likewise does not require acceptance.  However,
 | 
				
			||||||
 | 
					nothing other than this License grants you permission to propagate or
 | 
				
			||||||
 | 
					modify any covered work.  These actions infringe copyright if you do
 | 
				
			||||||
 | 
					not accept this License.  Therefore, by modifying or propagating a
 | 
				
			||||||
 | 
					covered work, you indicate your acceptance of this License to do so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  10. Automatic Licensing of Downstream Recipients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each time you convey a covered work, the recipient automatically
 | 
				
			||||||
 | 
					receives a license from the original licensors, to run, modify and
 | 
				
			||||||
 | 
					propagate that work, subject to this License.  You are not responsible
 | 
				
			||||||
 | 
					for enforcing compliance by third parties with this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  An "entity transaction" is a transaction transferring control of an
 | 
				
			||||||
 | 
					organization, or substantially all assets of one, or subdividing an
 | 
				
			||||||
 | 
					organization, or merging organizations.  If propagation of a covered
 | 
				
			||||||
 | 
					work results from an entity transaction, each party to that
 | 
				
			||||||
 | 
					transaction who receives a copy of the work also receives whatever
 | 
				
			||||||
 | 
					licenses to the work the party's predecessor in interest had or could
 | 
				
			||||||
 | 
					give under the previous paragraph, plus a right to possession of the
 | 
				
			||||||
 | 
					Corresponding Source of the work from the predecessor in interest, if
 | 
				
			||||||
 | 
					the predecessor has it or can get it with reasonable efforts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You may not impose any further restrictions on the exercise of the
 | 
				
			||||||
 | 
					rights granted or affirmed under this License.  For example, you may
 | 
				
			||||||
 | 
					not impose a license fee, royalty, or other charge for exercise of
 | 
				
			||||||
 | 
					rights granted under this License, and you may not initiate litigation
 | 
				
			||||||
 | 
					(including a cross-claim or counterclaim in a lawsuit) alleging that
 | 
				
			||||||
 | 
					any patent claim is infringed by making, using, selling, offering for
 | 
				
			||||||
 | 
					sale, or importing the Program or any portion of it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  11. Patents.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A "contributor" is a copyright holder who authorizes use under this
 | 
				
			||||||
 | 
					License of the Program or a work on which the Program is based.  The
 | 
				
			||||||
 | 
					work thus licensed is called the contributor's "contributor version".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A contributor's "essential patent claims" are all patent claims
 | 
				
			||||||
 | 
					owned or controlled by the contributor, whether already acquired or
 | 
				
			||||||
 | 
					hereafter acquired, that would be infringed by some manner, permitted
 | 
				
			||||||
 | 
					by this License, of making, using, or selling its contributor version,
 | 
				
			||||||
 | 
					but do not include claims that would be infringed only as a
 | 
				
			||||||
 | 
					consequence of further modification of the contributor version.  For
 | 
				
			||||||
 | 
					purposes of this definition, "control" includes the right to grant
 | 
				
			||||||
 | 
					patent sublicenses in a manner consistent with the requirements of
 | 
				
			||||||
 | 
					this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each contributor grants you a non-exclusive, worldwide, royalty-free
 | 
				
			||||||
 | 
					patent license under the contributor's essential patent claims, to
 | 
				
			||||||
 | 
					make, use, sell, offer for sale, import and otherwise run, modify and
 | 
				
			||||||
 | 
					propagate the contents of its contributor version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  In the following three paragraphs, a "patent license" is any express
 | 
				
			||||||
 | 
					agreement or commitment, however denominated, not to enforce a patent
 | 
				
			||||||
 | 
					(such as an express permission to practice a patent or covenant not to
 | 
				
			||||||
 | 
					sue for patent infringement).  To "grant" such a patent license to a
 | 
				
			||||||
 | 
					party means to make such an agreement or commitment not to enforce a
 | 
				
			||||||
 | 
					patent against the party.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you convey a covered work, knowingly relying on a patent license,
 | 
				
			||||||
 | 
					and the Corresponding Source of the work is not available for anyone
 | 
				
			||||||
 | 
					to copy, free of charge and under the terms of this License, through a
 | 
				
			||||||
 | 
					publicly available network server or other readily accessible means,
 | 
				
			||||||
 | 
					then you must either (1) cause the Corresponding Source to be so
 | 
				
			||||||
 | 
					available, or (2) arrange to deprive yourself of the benefit of the
 | 
				
			||||||
 | 
					patent license for this particular work, or (3) arrange, in a manner
 | 
				
			||||||
 | 
					consistent with the requirements of this License, to extend the patent
 | 
				
			||||||
 | 
					license to downstream recipients.  "Knowingly relying" means you have
 | 
				
			||||||
 | 
					actual knowledge that, but for the patent license, your conveying the
 | 
				
			||||||
 | 
					covered work in a country, or your recipient's use of the covered work
 | 
				
			||||||
 | 
					in a country, would infringe one or more identifiable patents in that
 | 
				
			||||||
 | 
					country that you have reason to believe are valid.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If, pursuant to or in connection with a single transaction or
 | 
				
			||||||
 | 
					arrangement, you convey, or propagate by procuring conveyance of, a
 | 
				
			||||||
 | 
					covered work, and grant a patent license to some of the parties
 | 
				
			||||||
 | 
					receiving the covered work authorizing them to use, propagate, modify
 | 
				
			||||||
 | 
					or convey a specific copy of the covered work, then the patent license
 | 
				
			||||||
 | 
					you grant is automatically extended to all recipients of the covered
 | 
				
			||||||
 | 
					work and works based on it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  A patent license is "discriminatory" if it does not include within
 | 
				
			||||||
 | 
					the scope of its coverage, prohibits the exercise of, or is
 | 
				
			||||||
 | 
					conditioned on the non-exercise of one or more of the rights that are
 | 
				
			||||||
 | 
					specifically granted under this License.  You may not convey a covered
 | 
				
			||||||
 | 
					work if you are a party to an arrangement with a third party that is
 | 
				
			||||||
 | 
					in the business of distributing software, under which you make payment
 | 
				
			||||||
 | 
					to the third party based on the extent of your activity of conveying
 | 
				
			||||||
 | 
					the work, and under which the third party grants, to any of the
 | 
				
			||||||
 | 
					parties who would receive the covered work from you, a discriminatory
 | 
				
			||||||
 | 
					patent license (a) in connection with copies of the covered work
 | 
				
			||||||
 | 
					conveyed by you (or copies made from those copies), or (b) primarily
 | 
				
			||||||
 | 
					for and in connection with specific products or compilations that
 | 
				
			||||||
 | 
					contain the covered work, unless you entered into that arrangement,
 | 
				
			||||||
 | 
					or that patent license was granted, prior to 28 March 2007.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Nothing in this License shall be construed as excluding or limiting
 | 
				
			||||||
 | 
					any implied license or other defenses to infringement that may
 | 
				
			||||||
 | 
					otherwise be available to you under applicable patent law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  12. No Surrender of Others' Freedom.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If conditions are imposed on you (whether by court order, agreement or
 | 
				
			||||||
 | 
					otherwise) that contradict the conditions of this License, they do not
 | 
				
			||||||
 | 
					excuse you from the conditions of this License.  If you cannot convey a
 | 
				
			||||||
 | 
					covered work so as to satisfy simultaneously your obligations under this
 | 
				
			||||||
 | 
					License and any other pertinent obligations, then as a consequence you may
 | 
				
			||||||
 | 
					not convey it at all.  For example, if you agree to terms that obligate you
 | 
				
			||||||
 | 
					to collect a royalty for further conveying from those to whom you convey
 | 
				
			||||||
 | 
					the Program, the only way you could satisfy both those terms and this
 | 
				
			||||||
 | 
					License would be to refrain entirely from conveying the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  13. Use with the GNU Affero General Public License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Notwithstanding any other provision of this License, you have
 | 
				
			||||||
 | 
					permission to link or combine any covered work with a work licensed
 | 
				
			||||||
 | 
					under version 3 of the GNU Affero General Public License into a single
 | 
				
			||||||
 | 
					combined work, and to convey the resulting work.  The terms of this
 | 
				
			||||||
 | 
					License will continue to apply to the part which is the covered work,
 | 
				
			||||||
 | 
					but the special requirements of the GNU Affero General Public License,
 | 
				
			||||||
 | 
					section 13, concerning interaction through a network will apply to the
 | 
				
			||||||
 | 
					combination as such.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  14. Revised Versions of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The Free Software Foundation may publish revised and/or new versions of
 | 
				
			||||||
 | 
					the GNU General Public License from time to time.  Such new versions will
 | 
				
			||||||
 | 
					be similar in spirit to the present version, but may differ in detail to
 | 
				
			||||||
 | 
					address new problems or concerns.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Each version is given a distinguishing version number.  If the
 | 
				
			||||||
 | 
					Program specifies that a certain numbered version of the GNU General
 | 
				
			||||||
 | 
					Public License "or any later version" applies to it, you have the
 | 
				
			||||||
 | 
					option of following the terms and conditions either of that numbered
 | 
				
			||||||
 | 
					version or of any later version published by the Free Software
 | 
				
			||||||
 | 
					Foundation.  If the Program does not specify a version number of the
 | 
				
			||||||
 | 
					GNU General Public License, you may choose any version ever published
 | 
				
			||||||
 | 
					by the Free Software Foundation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the Program specifies that a proxy can decide which future
 | 
				
			||||||
 | 
					versions of the GNU General Public License can be used, that proxy's
 | 
				
			||||||
 | 
					public statement of acceptance of a version permanently authorizes you
 | 
				
			||||||
 | 
					to choose that version for the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Later license versions may give you additional or different
 | 
				
			||||||
 | 
					permissions.  However, no additional obligations are imposed on any
 | 
				
			||||||
 | 
					author or copyright holder as a result of your choosing to follow a
 | 
				
			||||||
 | 
					later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  15. Disclaimer of Warranty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 | 
				
			||||||
 | 
					APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 | 
				
			||||||
 | 
					HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 | 
				
			||||||
 | 
					OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 | 
				
			||||||
 | 
					THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
				
			||||||
 | 
					PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 | 
				
			||||||
 | 
					IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 | 
				
			||||||
 | 
					ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  16. Limitation of Liability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
				
			||||||
 | 
					WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 | 
				
			||||||
 | 
					THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 | 
				
			||||||
 | 
					GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 | 
				
			||||||
 | 
					USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 | 
				
			||||||
 | 
					DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 | 
				
			||||||
 | 
					PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 | 
				
			||||||
 | 
					EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					SUCH DAMAGES.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  17. Interpretation of Sections 15 and 16.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the disclaimer of warranty and limitation of liability provided
 | 
				
			||||||
 | 
					above cannot be given local legal effect according to their terms,
 | 
				
			||||||
 | 
					reviewing courts shall apply local law that most closely approximates
 | 
				
			||||||
 | 
					an absolute waiver of all civil liability in connection with the
 | 
				
			||||||
 | 
					Program, unless a warranty or assumption of liability accompanies a
 | 
				
			||||||
 | 
					copy of the Program in return for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                     END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            How to Apply These Terms to Your New Programs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you develop a new program, and you want it to be of the greatest
 | 
				
			||||||
 | 
					possible use to the public, the best way to achieve this is to make it
 | 
				
			||||||
 | 
					free software which everyone can redistribute and change under these terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To do so, attach the following notices to the program.  It is safest
 | 
				
			||||||
 | 
					to attach them to the start of each source file to most effectively
 | 
				
			||||||
 | 
					state the exclusion of warranty; and each file should have at least
 | 
				
			||||||
 | 
					the "copyright" line and a pointer to where the full notice is found.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <one line to give the program's name and a brief idea of what it does.>
 | 
				
			||||||
 | 
					    Copyright (C) <year>  <name of author>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Also add information on how to contact you by electronic and paper mail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If the program does terminal interaction, make it output a short
 | 
				
			||||||
 | 
					notice like this when it starts in an interactive mode:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <program>  Copyright (C) <year>  <name of author>
 | 
				
			||||||
 | 
					    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
				
			||||||
 | 
					    This is free software, and you are welcome to redistribute it
 | 
				
			||||||
 | 
					    under certain conditions; type `show c' for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The hypothetical commands `show w' and `show c' should show the appropriate
 | 
				
			||||||
 | 
					parts of the General Public License.  Of course, your program's commands
 | 
				
			||||||
 | 
					might be different; for a GUI interface, you would use an "about box".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You should also get your employer (if you work as a programmer) or school,
 | 
				
			||||||
 | 
					if any, to sign a "copyright disclaimer" for the program, if necessary.
 | 
				
			||||||
 | 
					For more information on this, and how to apply and follow the GNU GPL, see
 | 
				
			||||||
 | 
					<http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The GNU General Public License does not permit incorporating your program
 | 
				
			||||||
 | 
					into proprietary programs.  If your program is a subroutine library, you
 | 
				
			||||||
 | 
					may consider it more useful to permit linking proprietary applications with
 | 
				
			||||||
 | 
					the library.  If this is what you want to do, use the GNU Lesser General
 | 
				
			||||||
 | 
					Public License instead of this License.  But first, please read
 | 
				
			||||||
 | 
					<http://www.gnu.org/philosophy/why-not-lgpl.html>.
 | 
				
			||||||
							
								
								
									
										581
									
								
								Changes
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										581
									
								
								Changes
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,581 @@
 | 
				
			|||||||
 | 
					Locale-Maketext-Gettext change log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 <ryanryan52@gmail.com> and
 | 
				
			||||||
 | 
						    Adam Kennedy <adamkennedybackup@gmail.com>
 | 
				
			||||||
 | 
						    (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 grammer, 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 lagacy 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-awared 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 outputing
 | 
				
			||||||
 | 
						    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 failurs.  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: Adition 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
 | 
				
			||||||
 | 
						    <corion@corion.net> 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 taged 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 binded 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 algorism 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 binded 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 seperately.  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 infomation 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
 | 
				
			||||||
							
								
								
									
										146
									
								
								INSTALL
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								INSTALL
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
				
			|||||||
 | 
					Locale-Maketext-Gettext Installation Guide
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Table of Contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   * System Requirements
 | 
				
			||||||
 | 
					   * Installation Instruction
 | 
				
			||||||
 | 
					     ** Install with ExtUtils::MakeMaker
 | 
				
			||||||
 | 
					     ** Install with Module::Build
 | 
				
			||||||
 | 
					     ** Install with the CPAN Shell
 | 
				
			||||||
 | 
					     ** Install with the CPANPLUS Shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* 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 Perl website.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					http://www.perl.com/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      If you are using MS-Windows, you can download and install
 | 
				
			||||||
 | 
					ActiveState ActivePerl.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					http://www.activestate.com/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   2. Required Perl modules: None.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   3. Optional Perl modules: None.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Installation Instruction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					** Install with ExtUtils::MakeMaker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arclog 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 priviledge to
 | 
				
			||||||
 | 
					write to the installation location.  This usually requires the root
 | 
				
			||||||
 | 
					priviledge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    If you are using ActivePerl under MS-Windows, you should use
 | 
				
			||||||
 | 
					nmake instead of make. nmake can be obtained from the Microsoft FTP
 | 
				
			||||||
 | 
					site.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ftp://ftp.microsoft.com/Softlib/MSLFILES/nmake15.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 docuemntation 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 priviledge to
 | 
				
			||||||
 | 
					write to the installation location.  This usually requires the root
 | 
				
			||||||
 | 
					priviledge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 docuemntation 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 priviledge to write to the installation
 | 
				
			||||||
 | 
					location.  This usually requires the root priviledge.  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 the
 | 
				
			||||||
 | 
					"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 docuemntation 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 priviledge to write to the installation
 | 
				
			||||||
 | 
					location.  This usually requires the root priviledge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    If you want to install into another location, you can set the
 | 
				
			||||||
 | 
					"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 docuemntation of cpanp for more CPANPLUS shell
 | 
				
			||||||
 | 
					commands (by running perldoc cpanp).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					imacat
 | 
				
			||||||
 | 
					2008-11-11
 | 
				
			||||||
 | 
					imacat@mail.imacat.idv.tw
 | 
				
			||||||
 | 
					http://www.imacat.idv.tw/
 | 
				
			||||||
							
								
								
									
										43
									
								
								MANIFEST
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								MANIFEST
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					Artistic
 | 
				
			||||||
 | 
					BUGS
 | 
				
			||||||
 | 
					Build.PL
 | 
				
			||||||
 | 
					Changes
 | 
				
			||||||
 | 
					COPYING
 | 
				
			||||||
 | 
					INSTALL
 | 
				
			||||||
 | 
					lib/Locale/Maketext/Gettext.pm
 | 
				
			||||||
 | 
					lib/Locale/Maketext/Gettext/Functions.pm
 | 
				
			||||||
 | 
					Makefile.PL
 | 
				
			||||||
 | 
					MANIFEST			This list of files
 | 
				
			||||||
 | 
					META.yml
 | 
				
			||||||
 | 
					README
 | 
				
			||||||
 | 
					script/maketext
 | 
				
			||||||
 | 
					SIGNATURE
 | 
				
			||||||
 | 
					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/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
 | 
				
			||||||
 | 
					THANKS
 | 
				
			||||||
 | 
					TODO
 | 
				
			||||||
							
								
								
									
										21
									
								
								META.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								META.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					--- #YAML:1.0
 | 
				
			||||||
 | 
					name:               Locale-Maketext-Gettext
 | 
				
			||||||
 | 
					version:            1.28
 | 
				
			||||||
 | 
					abstract:           Joins gettext and Maketext frameworks
 | 
				
			||||||
 | 
					author:
 | 
				
			||||||
 | 
					    - imacat <imacat@mail.imacat.idv.tw>
 | 
				
			||||||
 | 
					license:            perl
 | 
				
			||||||
 | 
					distribution_type:  module
 | 
				
			||||||
 | 
					configure_requires:
 | 
				
			||||||
 | 
					    ExtUtils::MakeMaker:  0
 | 
				
			||||||
 | 
					build_requires:
 | 
				
			||||||
 | 
					    ExtUtils::MakeMaker:  0
 | 
				
			||||||
 | 
					requires:  {}
 | 
				
			||||||
 | 
					no_index:
 | 
				
			||||||
 | 
					    directory:
 | 
				
			||||||
 | 
					        - t
 | 
				
			||||||
 | 
					        - inc
 | 
				
			||||||
 | 
					generated_by:       ExtUtils::MakeMaker version 6.52
 | 
				
			||||||
 | 
					meta-spec:
 | 
				
			||||||
 | 
					    url:      http://module-build.sourceforge.net/META-spec-v1.4.html
 | 
				
			||||||
 | 
					    version:  1.4
 | 
				
			||||||
							
								
								
									
										32
									
								
								Makefile.PL
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								Makefile.PL
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					#! /usr/bin/perl -w
 | 
				
			||||||
 | 
					require 5.008;
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use ExtUtils::MakeMaker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LICENSE is only availabe since ExtUtils::MakeMaker 6.30_01
 | 
				
			||||||
 | 
					use vars qw(%license $eummver);
 | 
				
			||||||
 | 
					%license = qw();
 | 
				
			||||||
 | 
					$eummver = $ExtUtils::MakeMaker::VERSION;
 | 
				
			||||||
 | 
					$eummver =~ s/_//;
 | 
				
			||||||
 | 
					%license = (LICENSE => "perl") if $eummver > 6.30;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WriteMakefile(
 | 
				
			||||||
 | 
					    NAME        => "Locale-Maketext-Gettext",
 | 
				
			||||||
 | 
					    VERSION     => "1.28",
 | 
				
			||||||
 | 
					    ABSTRACT    => "Joins gettext and Maketext frameworks",
 | 
				
			||||||
 | 
					    AUTHOR      => "imacat <imacat\@mail.imacat.idv.tw>",
 | 
				
			||||||
 | 
					    %license,
 | 
				
			||||||
 | 
					    PREREQ_PM   => { },
 | 
				
			||||||
 | 
					    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",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__END__
 | 
				
			||||||
							
								
								
									
										54
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					Locale::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 an 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. ^_*'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Read INSTALL for instructions on how to install
 | 
				
			||||||
 | 
					Locale::Maketext::Gettext.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* News, Changes and Updates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Refer to the Changes for changes, bug fixes, updates, new functions, etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Copyright
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
							
								
								
									
										65
									
								
								SIGNATURE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								SIGNATURE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					This file contains message digests of all files listed in MANIFEST,
 | 
				
			||||||
 | 
					signed via the Module::Signature module, version 0.55.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SHA1 be0627fff2e8aef3d2a14d5d7486babc8a4873ba Artistic
 | 
				
			||||||
 | 
					SHA1 f044bfe71c57b6f25c659bc0a6067aa854bc8343 BUGS
 | 
				
			||||||
 | 
					SHA1 7d6278e57e33472b167335a5435081f307f0dc70 Build.PL
 | 
				
			||||||
 | 
					SHA1 8624bcdae55baeef00cd11d5dfcfa60f68710a02 COPYING
 | 
				
			||||||
 | 
					SHA1 5863e86e8a20bbb63b3fd295520b861fa87db0c7 Changes
 | 
				
			||||||
 | 
					SHA1 e9345adfeb32db567cd1be52f3f27307943a36bc INSTALL
 | 
				
			||||||
 | 
					SHA1 c7d9c9b334b816e6f06473647cd9a054152a44c9 MANIFEST
 | 
				
			||||||
 | 
					SHA1 39589ded15e1d09a79c41391392d249de3708f4a META.yml
 | 
				
			||||||
 | 
					SHA1 ec92e11b76afaa05f67d83a6e32056505a45c99e Makefile.PL
 | 
				
			||||||
 | 
					SHA1 b699f73f5fa33123b2f4f1b210665e295900c74d README
 | 
				
			||||||
 | 
					SHA1 3db402b52e04cf5a6e60291c23aac8c16f2db810 THANKS
 | 
				
			||||||
 | 
					SHA1 85dd5ac895cc0a5b95827060999578d8ce8d41dd TODO
 | 
				
			||||||
 | 
					SHA1 f9deac7b12cc6a3cb18b7f5282f9e6a1e1a624b9 lib/Locale/Maketext/Gettext.pm
 | 
				
			||||||
 | 
					SHA1 b88b6bad1e8cb0ba825594c233c006c1b297646f lib/Locale/Maketext/Gettext/Functions.pm
 | 
				
			||||||
 | 
					SHA1 f89afd70fdcbaeeab44fada7ed3087d5c7f6f018 script/maketext
 | 
				
			||||||
 | 
					SHA1 525f414c7a0aadc61240a4b0959ca2cda7514c75 t/00-signature.t
 | 
				
			||||||
 | 
					SHA1 7bc2bf2d3ef2befd48a457fb3d90c7c7bdcc4854 t/01-basic.t
 | 
				
			||||||
 | 
					SHA1 73ce1e3ba168373318655b3f4fbca1847e49fd75 t/02-big-endian.t
 | 
				
			||||||
 | 
					SHA1 4b07656e4c35bfce793c96b59bb9ae2917be335e t/03-errors.t
 | 
				
			||||||
 | 
					SHA1 8a28c721b5eefe607c300192c8cb8e8107f419be t/04-encodings.t
 | 
				
			||||||
 | 
					SHA1 c16af7bbe1d9bd7ce8644c19f968231b94156c12 t/05-switching.t
 | 
				
			||||||
 | 
					SHA1 0212e5b50d6886601b0a4ad82d3c656975009a73 t/06-racing.t
 | 
				
			||||||
 | 
					SHA1 2ddb628b67ae35033fad4331c5323928d7dd7395 t/07-f-basic.t
 | 
				
			||||||
 | 
					SHA1 a4491ef77b899c4988b8ab34fb8f945a8d06c285 t/08-f-errors.t
 | 
				
			||||||
 | 
					SHA1 8fb7ecbce36daaf81ac9c197dab6834b25233cc5 t/09-f-encodings.t
 | 
				
			||||||
 | 
					SHA1 2c1641cc6fff792fb83826486050acab23a1db51 t/10-f-switching.t
 | 
				
			||||||
 | 
					SHA1 4afe4980e7ed4d326009b8257e01320abfb33d14 t/11-command-line.t
 | 
				
			||||||
 | 
					SHA1 b85626024d610808bd0909989dcfb9fb20a40485 t/99-pod.t
 | 
				
			||||||
 | 
					SHA1 97dad77dee7f751d09efdb6900b077d68c853d46 t/T_L10N.pm
 | 
				
			||||||
 | 
					SHA1 676b87d7a8edc735ba676d2901827eb52532b418 t/locale/C/LC_MESSAGES/test.mo
 | 
				
			||||||
 | 
					SHA1 80ca74a96bd6f83bd903ebfd021b87c9184582eb t/locale/en/LC_MESSAGES/bad.mo
 | 
				
			||||||
 | 
					SHA1 676b87d7a8edc735ba676d2901827eb52532b418 t/locale/en/LC_MESSAGES/test.mo
 | 
				
			||||||
 | 
					SHA1 fbd67646ebb39a99c1ab5aa985addd7f7ab27561 t/locale/en/LC_MESSAGES/test2.mo
 | 
				
			||||||
 | 
					SHA1 99b05048a1243bb75622a3c6e8a7c8e9f59a9151 t/locale/en/LC_MESSAGES/test_be.mo
 | 
				
			||||||
 | 
					SHA1 5d3e312b86526ebe164589b1f7fbf96f01823b0c t/locale/en/LC_MESSAGES/test_utf8.mo
 | 
				
			||||||
 | 
					SHA1 42eece65e0ceae8267000b42692212c260a49b36 t/locale/zh_CN/LC_MESSAGES/test.mo
 | 
				
			||||||
 | 
					SHA1 746c06a73e4eb641eb006c90ed938c4b98cfc2ec t/locale/zh_CN/LC_MESSAGES/test_be.mo
 | 
				
			||||||
 | 
					SHA1 8db66e4035d1f55cd27186e02c0386709c2fc3d0 t/locale/zh_CN/LC_MESSAGES/test_utf8.mo
 | 
				
			||||||
 | 
					SHA1 6aa98d6675c91555309d58a93ff59cb205cbdd7b t/locale/zh_TW/LC_MESSAGES/test.mo
 | 
				
			||||||
 | 
					SHA1 bcc89cdc393507d51b5a76e40954db72914b60d8 t/locale/zh_TW/LC_MESSAGES/test2.mo
 | 
				
			||||||
 | 
					SHA1 20f810c6229d0bd4064b27f9b3d86b61a20f0821 t/locale/zh_TW/LC_MESSAGES/test_be.mo
 | 
				
			||||||
 | 
					SHA1 eb13887b005e3c3e9fab774dfea22de5c01ad1ef t/locale/zh_TW/LC_MESSAGES/test_utf8.mo
 | 
				
			||||||
 | 
					-----BEGIN PGP SIGNATURE-----
 | 
				
			||||||
 | 
					Version: GnuPG v1.4.9 (GNU/Linux)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					iEYEARECAAYFAkpFc8MACgkQi9gubzC5S1w3kQCfY4bdMI9M6+sTT+y//sHibPDP
 | 
				
			||||||
 | 
					LUUAnRvtrXrg1Tov/anLHx0Xur3TmAQQ
 | 
				
			||||||
 | 
					=Au1F
 | 
				
			||||||
 | 
					-----END PGP SIGNATURE-----
 | 
				
			||||||
							
								
								
									
										24
									
								
								THANKS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								THANKS
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					Thanks to Sean M. Burke, for writing such a great localization framework as
 | 
				
			||||||
 | 
					Locale::Maketext, especially for his ideas about the plural forms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thanks to the GNU group, for writing such a great localization framework as
 | 
				
			||||||
 | 
					GNU gettext, especially for the completeness and simplicity of its design.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thanks for Autrijus Tang <autrijus@autrijus.org> for writing
 | 
				
			||||||
 | 
					Locale::Maketext::Lexicon.  It inspires me to import %Lexicon from other
 | 
				
			||||||
 | 
					sources.  Also thanks for approving such a project that is a competition to
 | 
				
			||||||
 | 
					his own Locale::Maketext::Lexicon. :p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thanks to Max Maischein <corion@corion.net> for reporting CPAN tester failures
 | 
				
			||||||
 | 
					200029, 200332 and 200331, that helps me finding the shell character escaping
 | 
				
			||||||
 | 
					problem on my test suite.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thanks to Andreas Koenig <andk@cpan.org> 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 <chris.travers@gmail.com> for suggestion on
 | 
				
			||||||
 | 
					implementing pgettext() in GNU gettext as pmaketext().
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, well, :p thanks to Larry Wall, for writing such a
 | 
				
			||||||
 | 
					great programming language, as Perl.
 | 
				
			||||||
							
								
								
									
										4
									
								
								TODO
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								TODO
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					Locale-Maketext-Gettext TODO list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Design a way for MO file installation through ExtUtils::MakeMaker
 | 
				
			||||||
 | 
					  and Module::Build.
 | 
				
			||||||
							
								
								
									
										814
									
								
								lib/Locale/Maketext/Gettext.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										814
									
								
								lib/Locale/Maketext/Gettext.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,814 @@
 | 
				
			|||||||
 | 
					# Locale::Maketext::Gettext - Joins the gettext and Maketext frameworks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					# First written: 2003-04-23
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package Locale::Maketext::Gettext;
 | 
				
			||||||
 | 
					use 5.008;
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use base qw(Locale::Maketext Exporter);
 | 
				
			||||||
 | 
					use vars qw($VERSION @ISA %Lexicon @EXPORT @EXPORT_OK);
 | 
				
			||||||
 | 
					$VERSION = 1.28;
 | 
				
			||||||
 | 
					@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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use vars qw(%Lexicons %ENCODINGS $REREAD_MO $MOFILE);
 | 
				
			||||||
 | 
					$REREAD_MO = 0;
 | 
				
			||||||
 | 
					$MOFILE = "";
 | 
				
			||||||
 | 
					use vars qw(@SYSTEM_LOCALEDIRS);
 | 
				
			||||||
 | 
					@SYSTEM_LOCALEDIRS = qw(/usr/share/locale /usr/lib/locale
 | 
				
			||||||
 | 
					    /usr/local/share/locale /usr/local/lib/locale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# encoding: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# key_encoding: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# new: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# subclass_init: 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 MOFILE value of this instance
 | 
				
			||||||
 | 
					    $self->{"MOFILE"} = "";
 | 
				
			||||||
 | 
					    ${"$class\::MOFILE"} = "" if !defined ${"$class\::MOFILE"};
 | 
				
			||||||
 | 
					    # 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# bindtextdomain: 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};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# textdomain: Set the current text domain
 | 
				
			||||||
 | 
					sub textdomain : method {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    my ($self, $class, $DOMAIN, $LOCALEDIR, $MOfile);
 | 
				
			||||||
 | 
					    ($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->{"MOFILE"} = "";
 | 
				
			||||||
 | 
					    ${"$class\::MOFILE"} = "";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # 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 $MOfile;
 | 
				
			||||||
 | 
					        foreach $LOCALEDIR (@SYSTEM_LOCALEDIRS) {
 | 
				
			||||||
 | 
					            $_ = catfile($LOCALEDIR, $self->{"LOCALE"},
 | 
				
			||||||
 | 
					                $self->{"CATEGORY"}, "$DOMAIN.mo");
 | 
				
			||||||
 | 
					            if (-f $_ && -r $_) {
 | 
				
			||||||
 | 
					                $MOfile = $_;
 | 
				
			||||||
 | 
					                last;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        # Not found at last
 | 
				
			||||||
 | 
					        return $DOMAIN if !defined $MOfile;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # This domain was registered
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        $MOfile = catfile(${$self->{"LOCALEDIRS"}}{$DOMAIN},
 | 
				
			||||||
 | 
					            $self->{"LOCALE"}, $self->{"CATEGORY"}, "$DOMAIN.mo");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Record it
 | 
				
			||||||
 | 
					    ${"$class\::MOFILE"} = $MOfile;
 | 
				
			||||||
 | 
					    $self->{"MOFILE"} = $MOfile;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Read the MO file
 | 
				
			||||||
 | 
					    # Cached
 | 
				
			||||||
 | 
					    if (!exists $ENCODINGS{$MOfile} || !exists $Lexicons{$MOfile}) {
 | 
				
			||||||
 | 
					        my $enc;
 | 
				
			||||||
 | 
					        # Read it
 | 
				
			||||||
 | 
					        %_ = read_mo($MOfile);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 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
 | 
				
			||||||
 | 
					        $Lexicons{$MOfile} = \%_;
 | 
				
			||||||
 | 
					        $ENCODINGS{$MOfile} = $enc;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Respect the existing output encoding
 | 
				
			||||||
 | 
					    if (defined $ENCODINGS{$MOfile}) {
 | 
				
			||||||
 | 
					        $self->{"MO_ENCODING"} = $ENCODINGS{$MOfile};
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        delete $self->{"MO_ENCODING"};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    # Respect the MO file encoding unless there is a user preferrence
 | 
				
			||||||
 | 
					    if (!exists $self->{"USERSET_ENCODING"}) {
 | 
				
			||||||
 | 
					        if (exists $self->{"MO_ENCODING"}) {
 | 
				
			||||||
 | 
					            $self->{"ENCODING"} = $self->{"MO_ENCODING"};
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            delete $self->{"ENCODING"};
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $self->{"Lexicon"} = $Lexicons{$MOfile};
 | 
				
			||||||
 | 
					    %{"$class\::Lexicon"} = %{$Lexicons{$MOfile}};
 | 
				
			||||||
 | 
					    $self->clear_isa_scan;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return $DOMAIN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# maketext: 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\::MOFILE"} ne $self->{"MOFILE"}) {
 | 
				
			||||||
 | 
					        ${"$class\::MOFILE"} = $self->{"MOFILE"};
 | 
				
			||||||
 | 
					        %{"$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 $_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# pmaketext: Maketext with context
 | 
				
			||||||
 | 
					sub pmaketext : method {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    my ($self, $ctxt, $key, @param);
 | 
				
			||||||
 | 
					    ($self, $ctxt, $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("$ctxt\x04$key", @param);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# read_mo: Subroutine to read and parse the MO file
 | 
				
			||||||
 | 
					#          Refer to gettext documentation section 8.3
 | 
				
			||||||
 | 
					sub read_mo($) {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    my ($MOfile, $len, $FH, $content, $tmpl);
 | 
				
			||||||
 | 
					    $MOfile = $_[0];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Avild being stupid
 | 
				
			||||||
 | 
					    return unless -f $MOfile && -r $MOfile;
 | 
				
			||||||
 | 
					    # Read the MO file
 | 
				
			||||||
 | 
					    $len = (stat $MOfile)[7];
 | 
				
			||||||
 | 
					    open $FH, $MOfile   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 %_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# reload_text: Method to purge the lexicon cache
 | 
				
			||||||
 | 
					sub reload_text : method {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Purge the text cache
 | 
				
			||||||
 | 
					    %Lexicons = qw();
 | 
				
			||||||
 | 
					    %ENCODINGS = qw();
 | 
				
			||||||
 | 
					    $REREAD_MO = time;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# fail_with: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# die_for_lookup_failures: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# encode_failure: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# failure_handler_auto: Our local version of failure_handler_auto(),
 | 
				
			||||||
 | 
					#   Copied and rewritten from Locale::Maketext, with bug#33938 patch applied.
 | 
				
			||||||
 | 
					#   See http://rt.perl.org/rt3//Public/Bug/Display.html?id=33938
 | 
				
			||||||
 | 
					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";
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # 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($MOfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 DESCRIPTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Locale::Maketext::Gettext joins the GNU gettext and Maketext
 | 
				
			||||||
 | 
					frameworks.  It is a subclass of L<Locale::Maketext(3)|Locale::Maketext/3>
 | 
				
			||||||
 | 
					that follows the way GNU gettext works.  It works seamlessly, I<both
 | 
				
			||||||
 | 
					in the sense of GNU gettext and Maketext>.  As a result, you I<enjoy
 | 
				
			||||||
 | 
					both their advantages, and get rid of both their problems, too.>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You start as an usual GNU gettext localization project:  Work on
 | 
				
			||||||
 | 
					PO files with the help of translators, reviewers and Emacs.  Turn
 | 
				
			||||||
 | 
					them into MO files with F<msgfmt>.  Copy them into the appropriate
 | 
				
			||||||
 | 
					locale directory, such as
 | 
				
			||||||
 | 
					F</usr/share/locale/de/LC_MESSAGES/myapp.mo>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then, build your Maketext localization class, with your base class
 | 
				
			||||||
 | 
					changed from L<Locale::Maketext(3)|Locale::Maketext/3> 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<LOCALEDIR>
 | 
				
			||||||
 | 
					itself.  If C<LOCALEDIR> is omitted, the registered locale directory
 | 
				
			||||||
 | 
					of C<DOMAIN> is returned.  This method always success.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item $LH->textdomain(DOMAIN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Set the current text domain.  Returns the C<DOMAIN> itself.  If
 | 
				
			||||||
 | 
					C<DOMAIN> 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<Locale::Maketext(3)|Locale::Maketext/3>, with a wrapper that
 | 
				
			||||||
 | 
					returns the text message C<encode>d according to the current
 | 
				
			||||||
 | 
					C<encoding>.  Refer to L<Locale::Maketext(3)|Locale::Maketext/3> for
 | 
				
			||||||
 | 
					the maketext plural notation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item $text = $LH->pmaketext($ctxt, $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<Locale::Maketext(3)|Locale::Maketext/3>.  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<undef>, to return
 | 
				
			||||||
 | 
					the result in unencoded UTF-8.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item $LH->key_encoding(ENCODING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Specify the encoding used in your original text.  The C<maketext>
 | 
				
			||||||
 | 
					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<key_encoding> to the encoding of your original
 | 
				
			||||||
 | 
					text.  Returns the current setting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					B<WARNING:> 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 exmaple, output
 | 
				
			||||||
 | 
					Chinese into US-ASCII.  Refer to L<Encode(3)|Encode/3> for the
 | 
				
			||||||
 | 
					possible values of this C<CHECK>.  The default is C<FB_DEFAULT>,
 | 
				
			||||||
 | 
					which is a safe choice that never fails.  But part of your text may
 | 
				
			||||||
 | 
					be lost, since that is what C<FB_DEFAULT> 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<maketext> 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 co-hoster 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($MOfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Read and parse the MO file.  Returns the read %Lexicon.  The returned
 | 
				
			||||||
 | 
					lexicon is in its original encoding.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you need the meta infomation of your MO file, parse the entry
 | 
				
			||||||
 | 
					C<$Lexicon{""}>.  For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /^Content-Type: text\/plain; charset=(.*)$/im;
 | 
				
			||||||
 | 
					  $encoding = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C<read_mo()> is exported by default, but you need to C<use
 | 
				
			||||||
 | 
					Locale::Maketext::Gettext> in order to use it.  It is not exported
 | 
				
			||||||
 | 
					from your localization class, but from the Locale::Maketext::Gettext
 | 
				
			||||||
 | 
					package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=back
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 NOTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					B<WARNING:> do not try to put any lexicon in your language subclass.
 | 
				
			||||||
 | 
					When the C<textdomain> method is called, the current lexicon will be
 | 
				
			||||||
 | 
					B<replaced>, but not appended.  This is to accommodate the way
 | 
				
			||||||
 | 
					C<textdomain> 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<Locale::Maketext(3)|Locale::Maketext/3> is that: 
 | 
				
			||||||
 | 
					I<GNU gettext is multibyte safe,> but Perl source is not.  GNU gettext
 | 
				
			||||||
 | 
					is safe to Big5 characters like \xa5\x5c (Gong1).  But if you follow
 | 
				
			||||||
 | 
					the current L<Locale::Maketext(3)|Locale::Maketext/3> 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::Getttext came from
 | 
				
			||||||
 | 
					L<Locale::Maketext::Lexicon(3)|Locale::Maketext::Lexicon/3>, 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<Locale::Maketext(3)|Locale::Maketext/3> itself.
 | 
				
			||||||
 | 
					L<Locale::Maketext::Lexicon(3)|Locale::Maketext::Lexicon/3> 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<Locale::Maketext(3)|Locale::Maketext/3>.  I implement this since
 | 
				
			||||||
 | 
					this is what GNU gettext does.  When %Lexicon is read from MO files
 | 
				
			||||||
 | 
					by C<read_mo()>, the encoding tagged in gettext MO files is used to
 | 
				
			||||||
 | 
					C<decode> the text into the internal encoding of Perl.  Then, when
 | 
				
			||||||
 | 
					extracted by C<maketext>, it is C<encode>d by the current
 | 
				
			||||||
 | 
					C<encoding> value.  The C<encoding> 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<Locale::Maketext(3)|Locale::Maketext/3>, and is essential to
 | 
				
			||||||
 | 
					daemons and C<mod_perl> applications.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should trust the encoding of your gettext MO file.  GNU gettext
 | 
				
			||||||
 | 
					C<msgfmt> 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<FB_DEFAULT> does.  If you do not like this
 | 
				
			||||||
 | 
					C<FB_DEFAULT>, change the failure behavior with the method
 | 
				
			||||||
 | 
					C<encode_failure>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you need the behavior of auto Traditional Chinese/Simplfied
 | 
				
			||||||
 | 
					Chinese conversion, as GNU gettext smartly does, do it yourself with
 | 
				
			||||||
 | 
					L<Encode::HanExtra(3)|Encode::HanExtra/3>, too.  There may be a
 | 
				
			||||||
 | 
					solution for this in the future, but not now.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you set C<textdomain> to a domain that is not C<bindtextdomain> 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<NOTICE:> I<MyPackage::L10N::en-E<gt>maketext(...) is not available
 | 
				
			||||||
 | 
					anymore,> as the C<maketext> 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<Locale::Maketext(3)|Locale::Maketext/3> 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<undef>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C<dgettext> and C<dcgettext> 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<LC_MESSAGES>.  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<Locale::Maketext(3)|Locale::Maketext/3>.  In
 | 
				
			||||||
 | 
					L<Locale::Maketext(3)|Locale::Maketext/3>, %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
 | 
				
			||||||
 | 
					proformance seriously.  This is discouraged.  You are adviced to use
 | 
				
			||||||
 | 
					a single textdomain for a single localization class.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The C<key_encoding> 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<pgettext> in GNU gettext is implemented as C<pmaketext>, 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<Locale::Maketext(3)|Locale::Maketext/3>,
 | 
				
			||||||
 | 
					L<Locale::Maketext::TPJ13(3)|Locale::Maketext::TPJ13/3>,
 | 
				
			||||||
 | 
					L<Locale::Maketext::Lexicon(3)|Locale::Maketext::Lexicon/3>,
 | 
				
			||||||
 | 
					L<Encode(3)|Encode/3>, L<bindtextdomain(3)|bindtextdomain/3>,
 | 
				
			||||||
 | 
					L<textdomain(3)|textdomain/3>.  Also, please refer to the official GNU
 | 
				
			||||||
 | 
					gettext manual at L<http://www.gnu.org/software/gettext/manual/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 AUTHOR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					imacat <imacat@mail.imacat.idv.tw>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 COPYRIGHT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
							
								
								
									
										781
									
								
								lib/Locale/Maketext/Gettext/Functions.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										781
									
								
								lib/Locale/Maketext/Gettext/Functions.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,781 @@
 | 
				
			|||||||
 | 
					# Locale::Maketext::Gettext::Functions - Functional interface to Locale::Maketext::Gettext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					# First written: 2003-04-28
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package Locale::Maketext::Gettext::Functions;
 | 
				
			||||||
 | 
					use 5.008;
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use base qw(Exporter);
 | 
				
			||||||
 | 
					use vars qw($VERSION @EXPORT @EXPORT_OK);
 | 
				
			||||||
 | 
					$VERSION = 0.13;
 | 
				
			||||||
 | 
					@EXPORT = qw();
 | 
				
			||||||
 | 
					push @EXPORT, qw(bindtextdomain textdomain get_handle maketext __ N_);
 | 
				
			||||||
 | 
					push @EXPORT, qw(dmaketext pmaketext dpmaketext);
 | 
				
			||||||
 | 
					push @EXPORT, qw(reload_text read_mo encoding key_encoding encode_failure);
 | 
				
			||||||
 | 
					push @EXPORT, qw(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 _catclass(@);
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					use vars qw(%LOCALEDIRS %RIDS %CLASSES %LANGS);
 | 
				
			||||||
 | 
					use vars qw(%LHS $_EMPTY $LH $DOMAIN $CATEGORY $CLASSBASE @LANGS %PARAMS);
 | 
				
			||||||
 | 
					use vars qw(@SYSTEM_LOCALEDIRS);
 | 
				
			||||||
 | 
					%LHS = qw();
 | 
				
			||||||
 | 
					# The category is always LC_MESSAGES
 | 
				
			||||||
 | 
					$CATEGORY = "LC_MESSAGES";
 | 
				
			||||||
 | 
					$CLASSBASE = "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
 | 
				
			||||||
 | 
					use vars qw($RID_LEN @RID_CHARS);
 | 
				
			||||||
 | 
					$RID_LEN = 8;
 | 
				
			||||||
 | 
					@RID_CHARS = split //,
 | 
				
			||||||
 | 
					    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# bindtextdomain: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# textdomain: 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_handle: 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: 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 $_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# N_: Return the original text untouched, so that it can be catched
 | 
				
			||||||
 | 
					#     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 @_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dmaketext: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# pmaketext: Maketext with context,
 | 
				
			||||||
 | 
					#            an equivalent to pgettext().
 | 
				
			||||||
 | 
					sub pmaketext($$@) {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    my ($ctxt, $key, @param);
 | 
				
			||||||
 | 
					    ($ctxt, $key, @param) = @_;
 | 
				
			||||||
 | 
					    # This is actually a wrapper to the maketext() function
 | 
				
			||||||
 | 
					    return maketext("$ctxt\x04$key", @param);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dpmaketext: Maketext with context in another text domain temporarily,
 | 
				
			||||||
 | 
					#             an equivalent to dpgettext().
 | 
				
			||||||
 | 
					sub dpmaketext($$$@) {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    my ($domain, $ctxt, $key, @param);
 | 
				
			||||||
 | 
					    ($domain, $ctxt, $key, @param) = @_;
 | 
				
			||||||
 | 
					    # This is actually a wrapper to the dmaketext() function
 | 
				
			||||||
 | 
					    return dmaketext($domain, "$ctxt\x04$key", @param);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# reload_text: Purge the lexicon cache
 | 
				
			||||||
 | 
					sub reload_text() {
 | 
				
			||||||
 | 
					    # reload_text is static.
 | 
				
			||||||
 | 
					    Locale::Maketext::Gettext->reload_text;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# encoding: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# key_encoding: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# encode_failure: 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"};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# die_for_lookup_failures: 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_class: Declare a class
 | 
				
			||||||
 | 
					sub _declare_class($) {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    $_ = $_[0];
 | 
				
			||||||
 | 
					    eval << "EOT";
 | 
				
			||||||
 | 
					package $_[0];
 | 
				
			||||||
 | 
					use base qw(Locale::Maketext::Gettext);
 | 
				
			||||||
 | 
					use vars qw(\@ISA %Lexicon);
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _catclass: Catenate the class name
 | 
				
			||||||
 | 
					sub _catclass(@) {
 | 
				
			||||||
 | 
					    return join("::", @_);;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _init_textdomain: 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 binded domain
 | 
				
			||||||
 | 
					    if (exists $LOCALEDIRS{$domain}) {
 | 
				
			||||||
 | 
					        @langs = _get_langs($LOCALEDIRS{$domain}, $domain);
 | 
				
			||||||
 | 
					    # Not binded
 | 
				
			||||||
 | 
					    } 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 = _catclass($CLASSBASE, $rid);
 | 
				
			||||||
 | 
					    # Register the domain with this class
 | 
				
			||||||
 | 
					    $CLASSES{$k} = $class;
 | 
				
			||||||
 | 
					    # Declare this class
 | 
				
			||||||
 | 
					    _declare_class($class);
 | 
				
			||||||
 | 
					    # Declare its language subclasses
 | 
				
			||||||
 | 
					    _declare_class(_catclass($class, $_))
 | 
				
			||||||
 | 
					        foreach @langs;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _get_langs: Search a locale directory and return the available languages
 | 
				
			||||||
 | 
					sub _get_langs($$) {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    my ($dir, $domain, $DH, $entry, $MOfile);
 | 
				
			||||||
 | 
					    ($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
 | 
				
			||||||
 | 
					            $MOfile = catfile($dir, $entry, $CATEGORY, "$domain.mo");
 | 
				
			||||||
 | 
					            # Skip if MO file is not available for this locale
 | 
				
			||||||
 | 
					            next if ! -f $MOfile && ! -r $MOfile;
 | 
				
			||||||
 | 
					            # Map C to i_default
 | 
				
			||||||
 | 
					            $entry = "i_default" if $entry eq "C";
 | 
				
			||||||
 | 
					            # Add this language
 | 
				
			||||||
 | 
					            push @_, lc $entry;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        close $DH           or last;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return @_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _get_handle: 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 binded 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 preferrence
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _get_empty_handle: 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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _reset: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _new_rid: 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _k: Build the key for the domain registry
 | 
				
			||||||
 | 
					sub _k($) {
 | 
				
			||||||
 | 
					    return join "\n", $LOCALEDIRS{$_[0]}, $CATEGORY, $_[0];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# _lang: The langage 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);
 | 
				
			||||||
 | 
					use vars qw($VERSION @ISA %Lexicon);
 | 
				
			||||||
 | 
					$VERSION = 0.01;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package Locale::Maketext::Gettext::Functions::_EMPTY::i_default;
 | 
				
			||||||
 | 
					use 5.008;
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use base qw(Locale::Maketext::Gettext);
 | 
				
			||||||
 | 
					use vars qw($VERSION @ISA %Lexicon);
 | 
				
			||||||
 | 
					$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<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> (and
 | 
				
			||||||
 | 
					L<Locale::Maketext(3)|Locale::Maketext/3>).  It works exactly the GNU
 | 
				
			||||||
 | 
					gettext way.  It plays magic to
 | 
				
			||||||
 | 
					L<Locale::Maketext(3)|Locale::Maketext/3> for you.  No more
 | 
				
			||||||
 | 
					localization class/subclasses and language handles are required at
 | 
				
			||||||
 | 
					all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The C<maketext>, C<dmaketext>, C<pmaketext> and C<dpmaketext>
 | 
				
			||||||
 | 
					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<LOCALEDIR>
 | 
				
			||||||
 | 
					itself.  If C<LOCALEDIR> is omitted, the registered locale directory
 | 
				
			||||||
 | 
					of C<DOMAIN> is returned.  This method always success.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item textdomain(DOMAIN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Set the current text domain.  Returns the C<DOMAIN> itself.  if
 | 
				
			||||||
 | 
					C<DOMAIN> 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<Locale::Maketext(3)|Locale::Maketext/3> for the magic of the
 | 
				
			||||||
 | 
					C<get_handle>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=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<Locale::Maketext(3)|Locale::Maketext/3> for the C<maketext> plural
 | 
				
			||||||
 | 
					grammer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item $message = __($key, @param...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A synonym to C<maketext()>.  This is a shortcut to C<maketext()> 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
 | 
				
			||||||
 | 
					catched 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($ctxt, $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, $ctxt, $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<undef>, to return
 | 
				
			||||||
 | 
					the result in unencoded UTF-8.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item key_encoding(ENCODING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Specify the encoding used in your original text.  The C<maketext>
 | 
				
			||||||
 | 
					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<key_encoding> to the encoding of your original
 | 
				
			||||||
 | 
					text.  Returns the current setting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					B<WARNING:> 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 exmaple, output
 | 
				
			||||||
 | 
					Chinese into US-ASCII.  Refer to L<Encode(3)|Encode/3> for the
 | 
				
			||||||
 | 
					possible values of this C<CHECK>.  The default is C<FB_DEFAULT>,
 | 
				
			||||||
 | 
					which is a safe choice that never fails.  But part of your text may
 | 
				
			||||||
 | 
					be lost, since that is what C<FB_DEFAULT> 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 co-hoster 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($MOfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Read and parse the MO file.  Returns the read %Lexicon.  The returned
 | 
				
			||||||
 | 
					lexicon is in its original encoding.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you need the meta infomation of your MO file, parse the entry
 | 
				
			||||||
 | 
					C<$Lexicon{""}>.  For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /^Content-Type: text\/plain; charset=(.*)$/im;
 | 
				
			||||||
 | 
					  $encoding = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=back
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 NOTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					B<NOTE:> Since localization classes are generated at run-time, it is
 | 
				
			||||||
 | 
					not possible to override the Maketext language functions, like
 | 
				
			||||||
 | 
					C<quant> or C<numerate>.  If that is your concern, use
 | 
				
			||||||
 | 
					L<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> instead.
 | 
				
			||||||
 | 
					Suggestions are welcome.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can now add/remove languages/MO files at run-time.  This is a
 | 
				
			||||||
 | 
					major improvement over the original
 | 
				
			||||||
 | 
					L<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> (and
 | 
				
			||||||
 | 
					L<Locale::Maketext(3)|Locale::Maketext/3>).  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<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> (and
 | 
				
			||||||
 | 
					L<Locale::Maketext(3)|Locale::Maketext/3>).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Language addition/removal takes effect only after C<bindtextdomain>
 | 
				
			||||||
 | 
					or C<textdomain> is called.  It has no effect on C<maketext> calls.
 | 
				
			||||||
 | 
					This keeps a basic sanity in the lifetime of a running script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you set C<textdomain> to a domain that is not C<bindtextdomain> 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<I can never get a never-failure C<maketext>.>  A common wrapper
 | 
				
			||||||
 | 
					like:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sub __ { return $LH->maketext(@_) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always fails if $LH is not initialized yet.  For this reason, 
 | 
				
			||||||
 | 
					C<maketext> 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<get_handle> 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<Programmers should be able to use
 | 
				
			||||||
 | 
					C<maketext> 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<Locale::Maketext(3)|Locale::Maketext/3>
 | 
				
			||||||
 | 
					does not satisfy this request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The third reason is:  Since 
 | 
				
			||||||
 | 
					L<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> imports
 | 
				
			||||||
 | 
					the lexicon from foreign sources, the class source file is left
 | 
				
			||||||
 | 
					empty.  It exists only to help the C<get_handle> 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<quant> or C<numerate>, is
 | 
				
			||||||
 | 
					not available here.  Suggestions are welcome.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C<encoding>, C<key_encoding>, C<encode_failure> and
 | 
				
			||||||
 | 
					C<die_for_lookup_failures> 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<setlocale> in
 | 
				
			||||||
 | 
					L<POSIX(3)|POSIX/3>.  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<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> 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<Locale::Maketext(3)|Locale::Maketext/3>,
 | 
				
			||||||
 | 
					L<Locale::Maketext::TPJ13(3)|Locale::Maketext::TPJ13/3>,
 | 
				
			||||||
 | 
					L<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3>,
 | 
				
			||||||
 | 
					L<bindtextdomain(3)|bindtextdomain/3>, L<textdomain(3)|textdomain/3>.
 | 
				
			||||||
 | 
					Also, please refer to the official GNU gettext manual at
 | 
				
			||||||
 | 
					L<http://www.gnu.org/software/gettext/manual/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 AUTHOR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					imacat <imacat@mail.imacat.idv.tw>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 COPYRIGHT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
							
								
								
									
										215
									
								
								script/maketext
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										215
									
								
								script/maketext
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,215 @@
 | 
				
			|||||||
 | 
					#! /usr/bin/perl -w
 | 
				
			||||||
 | 
					# Command-line interface to Locale::Maketext::Gettext (and Locale::Maketext)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					# First written: 2003-05-03
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use 5.008;
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use Getopt::Long qw(GetOptions);
 | 
				
			||||||
 | 
					use Locale::Maketext::Gettext::Functions;
 | 
				
			||||||
 | 
					use vars qw($VERSION);
 | 
				
			||||||
 | 
					$VERSION = 0.05;
 | 
				
			||||||
 | 
					# Prototype declaration
 | 
				
			||||||
 | 
					sub main();
 | 
				
			||||||
 | 
					sub parse_args();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use vars qw($THIS_FILE $SHORTHELP $VERSTR $SEARCH $HELP);
 | 
				
			||||||
 | 
					$THIS_FILE = $0;
 | 
				
			||||||
 | 
					$THIS_FILE =~ s/^.*\///;
 | 
				
			||||||
 | 
					$SHORTHELP = "Try `$THIS_FILE --help' for more information.";
 | 
				
			||||||
 | 
					$VERSTR = "$THIS_FILE v$VERSION by imacat <imacat\@mail.imacat.idv.tw>";
 | 
				
			||||||
 | 
					$SEARCH = join " ", @Locale::Maketext::Gettext::Functions::SYSTEM_LOCALEDIRS;
 | 
				
			||||||
 | 
					$HELP = << "EOT";
 | 
				
			||||||
 | 
					Usage: maketext [OPTION] [--domain=TEXTDOMAIN] MSGKEY [PARAM...]
 | 
				
			||||||
 | 
					or:    maketext [OPTION] -s MSGID [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 <imacat\@mail.imacat.idv.tw>.
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use vars qw($DOMAIN $LOCALEDIR $ECHO $KEY @PARAM);
 | 
				
			||||||
 | 
					$ECHO = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Main program
 | 
				
			||||||
 | 
					main();
 | 
				
			||||||
 | 
					exit 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# main: 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_args: Parse the arguments
 | 
				
			||||||
 | 
					sub parse_args() {
 | 
				
			||||||
 | 
					    local ($_, %_);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Get the arguments <20><><EFBFBD>o<EFBFBD>Ѽ<EFBFBD>
 | 
				
			||||||
 | 
					    $_ = 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 "$VERSTR\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 MSGID [PARAM...]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 DESCRIPTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The C<maketext> 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<maketext> script is a command-line interface to
 | 
				
			||||||
 | 
					L<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> (and
 | 
				
			||||||
 | 
					L<Locale::Maketext(3)|Locale::Maketext/3>).  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 catelog/MO file if it
 | 
				
			||||||
 | 
					does not reside in the system locale directories.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=back
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 NOTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Maketext language function override, like C<quant> or C<numerate>, 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 <imacat@mail.imacat.idv.tw>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 SEE ALSO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					L<Locale::Maketext(3)|Locale::Maketext/3>,
 | 
				
			||||||
 | 
					L<Locale::Maketext::TPJ13(3)|Locale::Maketext::TPJ13/3>,
 | 
				
			||||||
 | 
					L<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3>,
 | 
				
			||||||
 | 
					L<Locale::Maketext::Gettext::Functions(3)|Locale::Maketext::Gettext::Functions/3>,
 | 
				
			||||||
 | 
					L<bindtextdomain(3)|bindtextdomain/3>, L<textdomain(3)|textdomain/3>.
 | 
				
			||||||
 | 
					Also, please refer to the official GNU gettext manual at
 | 
				
			||||||
 | 
					L<http://www.gnu.org/software/gettext/manual/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 AUTHOR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					imacat <imacat@mail.imacat.idv.tw>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 COPYRIGHT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
							
								
								
									
										22
									
								
								t/00-signature.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								t/00-signature.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/perl
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					print "1..1\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!-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('pgp.mit.edu') }) {
 | 
				
			||||||
 | 
					    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__
 | 
				
			||||||
							
								
								
									
										150
									
								
								t/01-basic.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										150
									
								
								t/01-basic.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					#! /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 <imacat\@mail.imacat.idv.tw>
 | 
				
			||||||
 | 
					Language-Team: English <imacat\@mail.imacat.idv.tw>
 | 
				
			||||||
 | 
					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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 17
 | 
				
			||||||
 | 
					ok($_[1], "<22>ɮ<C9AE><D7BF><EFBFBD><EFBFBD>U<EFBFBD><55><EFBFBD>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 18
 | 
				
			||||||
 | 
					ok($_[2], "<22>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>U<EFBFBD><55><EFBFBD>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 21
 | 
				
			||||||
 | 
					ok($_[1], "<22><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>µĴ<C2B5><C4B4>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 22
 | 
				
			||||||
 | 
					ok($_[2], "<22><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>µĴ<C2B5><C4B4>Һá<D2BA>");
 | 
				
			||||||
							
								
								
									
										143
									
								
								t/02-big-endian.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										143
									
								
								t/02-big-endian.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					#! /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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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 <imacat\@mail.imacat.idv.tw>, 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 <imacat\@mail.imacat.idv.tw>\\n"
 | 
				
			||||||
 | 
					"Language-Team: English <imacat\@mail.imacat.idv.tw>\\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;
 | 
				
			||||||
							
								
								
									
										283
									
								
								t/03-errors.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										283
									
								
								t/03-errors.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,283 @@
 | 
				
			|||||||
 | 
					#! /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("<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					# 22
 | 
				
			||||||
 | 
					ok($r, 1);
 | 
				
			||||||
 | 
					# 23
 | 
				
			||||||
 | 
					ok($_, "<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$r = eval {
 | 
				
			||||||
 | 
					    require T_L10N;
 | 
				
			||||||
 | 
					    $_ = T_L10N->get_handle("zh-tw");
 | 
				
			||||||
 | 
					    $_->bindtextdomain("test", "/dev/null");
 | 
				
			||||||
 | 
					    $_->textdomain("test");
 | 
				
			||||||
 | 
					    $_->key_encoding("Big5");
 | 
				
			||||||
 | 
					    $_ = $_->maketext("<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					# 24
 | 
				
			||||||
 | 
					ok($r, 1);
 | 
				
			||||||
 | 
					# 25
 | 
				
			||||||
 | 
					ok($_, "<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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;
 | 
				
			||||||
 | 
					print "($lang, $domain)\n";
 | 
				
			||||||
 | 
					$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:/);
 | 
				
			||||||
							
								
								
									
										266
									
								
								t/04-encodings.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										266
									
								
								t/04-encodings.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,266 @@
 | 
				
			|||||||
 | 
					#! /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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22><><EFBFBD>¶<EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD>?<3F><>?<3F>֡<EFBFBD>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22><><EFBFBD>¶<EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD>麗<3B><>結<3B>֡<EFBFBD>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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");
 | 
				
			||||||
							
								
								
									
										157
									
								
								t/05-switching.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										157
									
								
								t/05-switching.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					#! /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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 17
 | 
				
			||||||
 | 
					ok($_[1], "大家好。");
 | 
				
			||||||
 | 
					# 18
 | 
				
			||||||
 | 
					ok($_[2], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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");
 | 
				
			||||||
							
								
								
									
										317
									
								
								t/06-racing.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										317
									
								
								t/06-racing.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,317 @@
 | 
				
			|||||||
 | 
					#! /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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					$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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					$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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					$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($_, "<22>G<EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					$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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					$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);
 | 
				
			||||||
							
								
								
									
										275
									
								
								t/07-f-basic.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										275
									
								
								t/07-f-basic.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,275 @@
 | 
				
			|||||||
 | 
					#! /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");
 | 
				
			||||||
 | 
					    # <20><><EFBFBD>l<EFBFBD><6C><EFBFBD>A<EFBFBD>o<EFBFBD>ɤj<C9A4><6A><EFBFBD>ʡI :p <20>]From: <20>x<EFBFBD>W<EFBFBD>R<EFBFBD>E<EFBFBD><45><EFBFBD>^
 | 
				
			||||||
 | 
					    @_ = 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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 24
 | 
				
			||||||
 | 
					ok($_[1], "<22>ɮ<C9AE><D7BF><EFBFBD><EFBFBD>U<EFBFBD><55><EFBFBD>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 25
 | 
				
			||||||
 | 
					ok($_[2], "<22>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>U<EFBFBD><55><EFBFBD>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 28
 | 
				
			||||||
 | 
					ok($_[1], "<22><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>µĴ<C2B5><C4B4>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 29
 | 
				
			||||||
 | 
					ok($_[2], "<22><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>µĴ<C2B5><C4B4>Һá<D2BA>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 36
 | 
				
			||||||
 | 
					ok($_[1], "<22>ɮ<C9AE><D7BF><EFBFBD><EFBFBD>U<EFBFBD><55><EFBFBD>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 37
 | 
				
			||||||
 | 
					ok($_[2], "<22>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>U<EFBFBD><55><EFBFBD>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 40
 | 
				
			||||||
 | 
					ok($_[1], "<22><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>µĴ<C2B5><C4B4>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 41
 | 
				
			||||||
 | 
					ok($_[2], "<22><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>µĴ<C2B5><C4B4>Һá<D2BA>");
 | 
				
			||||||
							
								
								
									
										344
									
								
								t/08-f-errors.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										344
									
								
								t/08-f-errors.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,344 @@
 | 
				
			|||||||
 | 
					#! /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("<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					# 25
 | 
				
			||||||
 | 
					ok($r, 1);
 | 
				
			||||||
 | 
					# 26
 | 
				
			||||||
 | 
					ok($_, "<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$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("<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					# 27
 | 
				
			||||||
 | 
					ok($r, 1);
 | 
				
			||||||
 | 
					# 28
 | 
				
			||||||
 | 
					ok($_, "<22>]<5D><><EFBFBD>]<5D>w<EFBFBD>^");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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:/);
 | 
				
			||||||
							
								
								
									
										282
									
								
								t/09-f-encodings.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										282
									
								
								t/09-f-encodings.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,282 @@
 | 
				
			|||||||
 | 
					#! /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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22><><EFBFBD>¶<EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD>?<3F><>?<3F>֡<EFBFBD>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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($_, "<22><><EFBFBD>¶<EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD>麗<3B><>結<3B>֡<EFBFBD>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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");
 | 
				
			||||||
							
								
								
									
										416
									
								
								t/10-f-switching.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										416
									
								
								t/10-f-switching.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,416 @@
 | 
				
			|||||||
 | 
					#! /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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 24
 | 
				
			||||||
 | 
					ok($_[2], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 28
 | 
				
			||||||
 | 
					ok($_[2], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 32
 | 
				
			||||||
 | 
					ok($_[2], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 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], "<22>G<EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C");
 | 
				
			||||||
 | 
					# 39
 | 
				
			||||||
 | 
					ok($_[5], "Hello, world!");
 | 
				
			||||||
 | 
					# 40
 | 
				
			||||||
 | 
					ok($_[6], "Every story has a happy ending.");
 | 
				
			||||||
 | 
					# 41
 | 
				
			||||||
 | 
					ok($_[7], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 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], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 48
 | 
				
			||||||
 | 
					ok($_[3], "Hello, world!");
 | 
				
			||||||
 | 
					# 49
 | 
				
			||||||
 | 
					ok($_[4], "Hello, world!");
 | 
				
			||||||
 | 
					# 50
 | 
				
			||||||
 | 
					ok($_[5], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 51
 | 
				
			||||||
 | 
					ok($_[6], "<22>j<EFBFBD>a<EFBFBD>n<EFBFBD>C");
 | 
				
			||||||
 | 
					# 52
 | 
				
			||||||
 | 
					ok($_[7], "<22><><EFBFBD>Һá<D2BA>");
 | 
				
			||||||
 | 
					# 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");
 | 
				
			||||||
							
								
								
									
										92
									
								
								t/11-command-line.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										92
									
								
								t/11-command-line.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					#! /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;
 | 
				
			||||||
 | 
					use vars qw($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");
 | 
				
			||||||
							
								
								
									
										5
									
								
								t/99-pod.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								t/99-pod.t
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					#!/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();
 | 
				
			||||||
							
								
								
									
										24
									
								
								t/T_L10N.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								t/T_L10N.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					# 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;
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								t/locale/C/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/C/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								t/locale/en/LC_MESSAGES/bad.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								t/locale/en/LC_MESSAGES/bad.mo
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test2.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test2.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test_be.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test_be.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test_utf8.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/en/LC_MESSAGES/test_utf8.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/zh_CN/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/zh_CN/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/zh_CN/LC_MESSAGES/test_be.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/zh_CN/LC_MESSAGES/test_be.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/zh_CN/LC_MESSAGES/test_utf8.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/zh_CN/LC_MESSAGES/test_utf8.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test2.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test2.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test_be.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test_be.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test_utf8.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								t/locale/zh_TW/LC_MESSAGES/test_utf8.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user