NAME
    Text::PO - Read and write PO files

SYNOPSIS
        use Text::PO;
        my $po = Text::PO->new;
        $po->debug( 2 );
        $po->parse( $poFile ) || die( $po->error, "\n" );
        my $hash = $po->as_hash;
        my $json = $po->as_json;
        # Add data:
        my $e = $po->add_element(
            msgid => 'Hello!',
            msgstr => 'Salut !',
        );
        $po->remove_element( $e );
        $po->elements->foreach(sub
        {
            my $e = shift( @_ ); # $_ is also available
            if( $e->msgid eq $other->msgid )
            {
                # do something
            }
        });
    
        # Write in a PO format to STDOUT
        $po->dump;
        # or to a file handle
        $po->dump( $io );
        # Synchronise data
        $po->sync( '/some/where/com.example.api.po' );
        $po->sync( $file_handle );
        # or merge
        $po->merge( '/some/where/com.example.api.po' );
        $po->merge( $file_handle );

VERSION
        v0.5.0

DESCRIPTION
    This module parse GNU PO (portable object) and POT (portable object
    template) files, making it possible to edit the localised text and write
    it back to a po file.

    Text::PO::MO reads and writes ".mo" (machine object) binary files.

    Thus, with those modules, you do not need to install "msgfmt", "msginit"
    of GNU. It is better if you have them though.

    Also, this distribution provides a way to export the "po" files in json
    format to be used from within JavaScript and a JavaScript class to load
    and use those files is also provided along with some command line
    scripts. See the "share" folder along with its own test units.

    Also, there is a script in "scripts" that can be used to transcode ".po"
    or "mo" files into json format and vice versa.

CONSTRUCTOR
  new
    Create a new Text::PO object acting as an accessor.

    One object should be created per po file, because it stores internally
    the po data for that file in the Text::PO object instantiated.

    Returns the object.

  METHODS
  add_element
    Given either a Text::PO::Element object, or an hash ref with keys like
    "msgid" and "msgstr", or given a "msgid" followed by an optional hash
    ref, "add_element" will add this to the stack of elements.

    It returns the newly created element if it did not already exist, or the
    existing one found. Thus if you try to add an element data that already
    exists, this will prevent it and return the existing element object
    found.

  added
    Returns an array object (Module::Generic::Array) of Text::PO::Element
    objects added during synchronisation.

  as_json
    This takes an optional hash reference of option parameters and return a
    json formatted string.

    All options take a boolean value. Possible options are:

    *   "indent"

        If true, JSON will indent the data.

        Default to false.

    *   "pretty"

        If true, this will return a human-readable json data.

    *   "sort"

        If true, this will instruct JSON to sort the keys. This makes it
        slower to generate.

        It defaults to false, which will use a pseudo random order set by
        perl.

    *   "utf8"

        If true, JSON will utf8 encode the data.

  as_hash
    Return the data parsed as an hash reference.

  as_json
    Return the PO data parsed as json data.

  charset
    Sets or gets the character encoding for the po data. This will affect
    the "charset" parameter in "Content-Type" meta information.

  content_encoding
    Sets or gets the meta field value for "Content-Encoding"

  content_type
    Sets or gets the meta field value for "Content-Type"

  current_lang
    Returns the current language environment variable set, trying "LANGUAGE"
    and "LANG"

  decode
    Given a string, this will decode it using the character set specified
    with "encoding"

  domain
    Sets or gets the domain (or namespace) for this PO. Something like
    "com.example.api"

  dump
    Given an optional filehandle, or STDOUT by default, it will print to
    that filehandle in a format suitable to the po file.

    Thus, one could create a perl script, read a po file, then redirect the
    output of the dump back to another po file like

        ./po_script.pl en_GB.po > new_en_GB.po

    It returns the Text::PO object used.

  elements
    Returns the array reference of all the Text::PO::Element objects

  encoding
    Sets or gets the character set encoding for the GNU PO file. Typically
    this should be "utf-8"

  exists
    Given a Text::PO::Element object, it will check if this object exists in
    its current stack. To achieve this, it will check if both the "msgid"
    and the "msgstr" exists and match. If you only want to check if the
    "msgid" exists, use the "msgid_only" option as explained below.

    It takes an optional hash or hash reference of options as follows:

    *   "msgid_only"

        Boolean. If true, this will check only if the "msgid" already
        exists, and not the corresponding "msgstr"

    It returns true of false accordingly.

  hash
    Returns the data of the po file as an hash reference with each key
    representing a string and its value the localised version.

  header
    Access the headers data for this po file. The data is an array
    reference.

  language
    Sets or gets the meta field value for "Language"

  language_team
    Sets or gets the meta field value for "Language-Team"

  last_translator
    Sets or gets the meta field value for "Last-Translator"

  merge
    This takes the same parameters as "sync" and will merge the current data
    with the target data and return the newly created Text::PO object

  meta
    This sets or return the given meta information. The meta field name
    provided is case insensitive and you can replace dashes ("-") with
    underscore (<_>)

        $po->meta( 'Project-Id-Version' => 'MyProject 1.0' );
        # or this will also work
        $po->meta( project_id_version => 'MyProject 1.0' );

    It can take a hash ref, a hash, or a single element. If a single element
    is provided, it return its corresponding value.

    This returns its internal hash of meta information.

  meta_keys
    This is an hash reference of meta information.

  mime_version
    Sets or gets the meta field value for "MIME-Version"

  new_element
    Provided with an hash or hash reference of property-value pairs, and
    this will pass those information to Text::PO::Element and return the new
    object.

  normalise_meta
    Given a meta field, this will return a normalised version of it, ie a
    field name with the right case and dash instead of underscore
    characters.

  parse
    Given a filepath to a po file or a file handle, this will parse the po
    file and return a new Text::PO object.

    For each new entry that "parse" find, it creates a Text::PO::Element
    object.

    The list of all elements found can then be accessed using "elements"

    It returns the current Text::PO object

  parse_date_to_object
    Provided with a date string and this returns a DateTime object

  parse_header_value
    Takes a header value such as "text/plain; charset="utf-8"" and this
    returns a "Text::PO::HeaderValue" object

  parse2hash
    Whether the pod file is stored as standard GNU po data or as json data,
    this method will read its data and return an hash reference of it.

  parse2object
    Takes a file path, parse the po file and loads its data onto the current
    object. It returns the current object.

  plural
    Sets or gets the plurality definition for this domain and locale used in
    the current object.

    If set, this will expect 2 parameters: 1) an integer representing the
    possible plurality for the given locale and 2) the expression that will
    be evaluated to assess which plural form to use.

    It returns an array reference representing those 2 values.

  plural_forms
    Sets or gets the meta field value for "Plural-Forms"

  po_revision_date
    Sets or gets the meta field value for "PO-Revision-Date"

  pot_creation_date
    Sets or gets the meta field value for "POT-Creation-Date"

  project_id_version
    Sets or gets the meta field value for "Project-Id-Version"

  quote
    Given a string, it will escape carriage return, double quote and return
    it,

  remove_duplicates
    Takes a boolean value to enable or disable the removal of duplicates in
    the po file.

  remove_element
    Given a Text::PO::Element and this will remove it from the object
    elements list.

    If the value provided is not an Text::PO::Element object it will return
    an error.

    It returns a true value representing the number of elements removed or 0
    if none could be found.

  removed
    Sets or gets this boolean value.

  report_bugs_to
    Sets or gets the meta field value for "Report-Msgid-Bugs-To"

  quote
    Takes a string and escape the characters that needs to be and returns
    it.

  remove_duplicates
    Takes a boolean value and if true, this will remove duplicate msgid.

  removed
    Returns an array object (Module::Generic::Array) of Text::PO::Element
    removed during synchronisation.

  source
    Sets or gets an hash reference of parameters providing information about
    the source of the data.

    It could have an attribute "handle" with a glob as value or an attribute
    "file" with a filepath as value.

  sync
        $po->sync( '/some/where/com.example.api.po' );
        # or
        $po->sync({ file => '/some/where/com.example.api.po' });
        # or
        $po->sync({ handle => $file_handle });
        # or, if source of data has been set previously by parse()
        $po->parse( '/some/where/com.example.api.po' );
        # Do some change to the data, then:
        $po->sync;

    Given a file or a file handle, it will read the po file, and our current
    object will synchronise against it.

    It takes an hash or hash reference passed as argument, as optional
    parameters with the following properties:

    *file*
        File path

    *handle*
        Opened file handle

    This means that our object is the source and the file or filehandle
    representing the target po file is the recipient of the synchronisation.

    This method will return an error a file is provided, already exists, but
    is either a symbolic link or not a regular file ("-f" test), or a file
    handle is provided, but not currently opened.

    If a file path is provided, and the file does not yet exist, it will
    attempt to create it or return an error if it cannot. In this case, it
    will use "dump" to write all its data to file.

    If the target file was created, it will return the current object,
    otherwise it returns the newly created Text::PO representing the data
    synchronised.

  sync_fh
    Takes a file handle as its unique argument and synchronise the object
    data with the file handle. This means, the file handle provided must be
    opened in both read and write mode.

    What it does is that, after creating a new Text::PO object, it will
    first call "parse" on the file handle to load its data, and then add all
    of the current object data to the newly created object, and finally dump
    all back to the file handle using "dump"

    It will set two array of data: one for the elements that did not exist
    in the recipient data and thus were added and one for those elements in
    the target data that did not exist in the source object and thus were
    removed.

    If the option *append* is specified, however, it will not remove those
    elements in the target that doe not exist in the source one. You can get
    the same result by calling the method "merge" instead of "sync"

    You can get the data of each of those 2 arrays by calling the methods
    "added" and "removed" respectively.

    It returns the newly created Text::PO object containing the synchronised
    data.

  unquote
    Takes a string, unescape it and returns it.

  use_json
    Takes a boolean value and if true, this will save the data as json
    instead of regular po format.

    Saving data as json makes it quicker to load, but also enable the data
    to be used by JavaScript.

PRIVATE METHODS
  _can_write_fh
    Given a filehandle, returns true if it can be written to it or false
    otherwise.

  _set_get_meta_date
    Takes a meta field name for a date-type field and sets its value, if one
    is provided, or returns a DateTime object.

    If a value is provided, even a string, it will be converted to a
    DateTime object and a DateTime::Format::Strptime will be attached to it
    as a formatter so the stringification of the object produces a date
    compliant with PO format.

  _set_get_meta_value
    Takes a meta field name and sets or gets its value.

AUTHOR
    Jacques Deguest <jack@deguest.jp>

SEE ALSO
    Text::PO::Element, Text::PO::MO, Text::PO::Gettext

    <https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html>,

    <https://en.wikipedia.org/wiki/Gettext>

    GNU documentation on header format
    <https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html
    >

COPYRIGHT & LICENSE
    Copyright (c) 2020-2021 DEGUEST Pte. Ltd.

    You can use, copy, modify and redistribute this package and associated
    files under the same terms as Perl itself.