# Copyright 2002-2008 Josh Clark and Global Moxie, LLC. This code cannot be 
# redistributed without permission from globalmoxie.com.  For more
# information, consult your Big Medium license.
#
# $Id: Language.pm 3043 2008-03-31 14:00:38Z josh $

package BigMed::Language;
use strict;
use utf8;
use Carp;
use base qw(Locale::Maketext);
use vars qw(%Lexicon);

#The default language class is BigMed::Language::en.
#If a language file is not found for the requested language, it will
#get the en file.
BigMed::Language->fallback_languages('en-US');

my %Custom;

sub customize_lang {
    my $obj = shift;
    ref $obj && $obj->isa('BigMed::Language')
      or croak "Customize is an object method.";
    my $custom_class = ref $obj;
    my $language     = $obj->language_tag;
    no strict 'refs';

    if ( $custom_class !~ /\_custom$/ ) {

        #not previously customized.
        #create a class, based on current class but with _custom appended
        #any subsequent calls to customize either the original or the custom
        #language will customize the custom lexicon. The original language
        #lexicon is left untouched.

        $language .= "-custom";
        my $old_class = $custom_class;
        $custom_class .= "_custom";
        @{ $custom_class . "::ISA" } = ($old_class);

    }

    my $lexicon_name = $custom_class . "::Lexicon";
    if ( !$Custom{$custom_class} ) {

        #for the benefit of persistent environments like mod_perl,
        #make sure that the global Lexicon array is empty the
        #first time that we're populating it.
        %$lexicon_name = ();
        $Custom{$custom_class} = 1;
    }
    %$lexicon_name = ( %$lexicon_name, @_ );
    BigMed::Language->get_handle($language);    #handle for the custom class
}

sub list {
    #when passed a list of maketext arguments (arrays should be refs),
    #generates a html-formatted list from the results
    my $obj = shift;
    my $text = '';
    foreach my $item (@_) {
        my @args = ref $item eq "ARRAY" ? @$item : ($item);
        $text .= '%BM<li>%' . $obj->maketext(@args) . "%BM</li>%\n";
    }
    $text = "%BM<ul>%$text%BM</ul>%" if $text;
    $text;
}

1;

__END__

=head1 NAME

BigMed::Language - Big Medium localization framework

=head1 SYNOPSIS

    my $lang = BigMed::Language->get_handle('en')
      or die "Could not create 'en' language tag";
    
    print $lang->maketext('Hello World!');
    
    $lang->customize_lang('Hello World!' => 'Hi earth.');

=head1 DESCRIPTION

BigMed::Language processes text snippets into the appropriate language and
also enables code to add and customize snippet values for any of the 
available languages.

BigMed::Language objects handle the language processing for the Big Medium
control panel but can also be subclassed to allow language processing for
other aspects (site format vocabulary, for example).

=head1 METHODS

BigMed::Language is a subclass of Locale::Maketext and inherits all of its
methods. Following is a list of the relevant methods for the Big Medium
application.

=over 4

=item * BigMed::Language->get_handle($language_tag)

This constructor method returns a language object for the language-tag
attribute. If the requested language is not available, US English ('en-US')
is returned as the fallback.

=item * $lang->maketext($key, ...parameters...)

Returns the language string corresponding to the $key argument, processing
the parameters if any as appropriate. If the key does not exist in the
language lexicon (or any ancestor lexicons), the key will be returned as-is.
If the key string contains brackets, the string is processed according
to Locale::Maketext's bracket notation.

The key can also be a code reference, in which case the code is called with
the BigMed::Language object and parameters as arguments:
&$key($lang, ...parameters...)

B<Note for translators and others providing localized strings:>
This method returns strings that are not escaped and anticipates that they
will need to be escaped for whatever context they are being displayed
to the user. If the final localized string contains text that should not
be escaped later (e.g., HTML strings), those portions of the string should
be surrounded by %BM ... % like so:

    This string contains %BM<strong>%html tags%BM</strong>%

=item * $lang->list(@keys)

Accepts an array of lexicon keys (or references to key/parameter arrays)
and returns all of the translated values in a xhtml-formatted unordered
list. For example:

    my $en = BigMed::Language->get_handle('en');
    my $number = 'two';
    my $params = 1;
    my $list = $en->list(
        "This is the first item.",
        ["This is item number [_1].", $number],
        ["The third item accepts [quant, _1, parameter].", 1],
    );

...would put this string into $list, assuming the translations were
the same as the keys:

    %BM<ul>%%BM<li>%This is the first item.%BM</li>%
    %BM<li>%This is item number two.%BM</li>%
    %BM<li>%The third item accepts 1 parameter.%BM</li>%
    %BM</ul>%

=item * $lang->customize_lang(%new_items)

Returns a custom language object, based on the $lang object but adding or
overriding the $lang Lexicon with the entries in the argument hash, where
the key is the language key and the value is the Lexicon value.

Subsequent customize_lang calls on either the custom object, or the original
$lang object will add/adjust the Language for all custom objects. This
method enables plug-ins to add additional language keys to the lexicon.

=back

=head1 SEE ALSO

=over 4

=item * Locale::Maketext

=back

=head1 AUTHOR & COPYRIGHTS

This module and all Big Medium modules are copyright Josh Clark
and Global Moxie. All rights reserved.

Use of this module and the Big Medium content
management system are governed by Global Moxie's software licenses
and may not be used outside of the terms and conditions outlined
there.

For more information, visit the Global Moxie website at
L<http://globalmoxie.com/>.

Big Medium and Global Moxie are service marks of Global Moxie
and Josh Clark. All rights reserved.

=cut

