Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
8.1 KiB

package AN::Tools::Words;
#
# This module contains methods used to handle storage related tasks
#
use strict;
use warnings;
use Data::Dumper;
use XML::Simple qw(:strict);
our $VERSION = "3.0.0";
my $THIS_FILE = "Words.pm";
# Setup for UTF-8 mode.
# use utf8;
# $ENV{'PERL_UNICODE'} = 1;
### Methods;
# key
# read
=pod
=encoding utf8
=head1 NAME
AN::Tools::Words
Provides all methods related to generating translated strings for users.
=head1 SYNOPSIS
use AN::Tools::Words;
# Get a common object handle on all AN::Tools modules.
my $an = AN::Tools->new();
# Access to methods using '$an->Words->X'.
#
# Example using 'read()';
my $foo_path = $an->Words->read({file => $an->data->{path}{words}{'an-tools.xml'}});
=head1 METHODS
Methods in this module;
=cut
sub new
{
my $class = shift;
my $self = {};
bless $self, $class;
return ($self);
}
# Get a handle on the AN::Tools object. I know that technically that is a sibling module, but it makes more
# sense in this case to think of it as a parent.
sub parent
{
my $self = shift;
my $parent = shift;
$self->{HANDLE}{TOOLS} = $parent if $parent;
return ($self->{HANDLE}{TOOLS});
}
#############################################################################################################
# Public methods #
#############################################################################################################
=head2 key
NOTE: This is likely not the method you want. This method does no parsing at all. It returns the raw string from the 'words' file. You probably want C<< $an->Words->string() >> if you want to inject variables and get a string back ready to display to the user.
This returns a string by its key name. Optionally, a language and/or a source file can be specified. When no file is specified, loaded files will be search in alphabetical order (including path) and the first match is returned.
If the requested string is not found, 'C<< #!not_found!# >>' is returned.
Example to retrieve 'C<< t_0001 >>';
my $string = $an->Words->key({key => 't_0001'});
Same, but specifying the key from Canadian english;
my $string = $an->Words->key({
key => 't_0001',
language => 'en_CA',
})
Same, but specifying a source file.
my $string = $an->Words->key({
key => 't_0001',
language => 'en_CA',
file => 'an-tools.xml',
})
Parameters;
=head3 key (required)
This is the key to return the string for.
=head3 language (optional)
This is the ISO code for the language you wish to read. For example, 'en_CA' to get the Canadian English string, or 'jp' for the Japanese string.
When no language is passed, 'C<< $an->data->{defaults}{languages}{output} >>' is used.
=head3 file (optional)
This is the specific file to read the string from. It should generally not be needed as string keys should not be reused. However, if it happens, this is a way to specify which file's version you want.
The file can be the file name, or a path. The specified file is search for by matching the the passed in string against the end of the file path. For example, 'C<< file => 'AN/an-tools.xml' >> will match the file 'c<< /usr/share/perl5/AN/an-tools.xml >>'.
=cut
sub key
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
# Setup default values
my $key = defined $parameter->{key} ? $parameter->{key} : "";
my $language = defined $parameter->{language} ? $parameter->{language} : $an->data->{defaults}{languages}{output};
my $file = defined $parameter->{file} ? $parameter->{file} : "";
my $string = "#!not_found!#";
my $error = 0;
#print $THIS_FILE." ".__LINE__."; [ Debug ] - key: [$key], language: [$language], file: [$file]\n";
if (not $key)
{
#print $THIS_FILE." ".__LINE__."; AN::Tools::Words->key()' called without a key name to read.\n";
$error = 1;
}
if (not $language)
{
#print $THIS_FILE." ".__LINE__."; AN::Tools::Words->key()' called without a language, and 'defaults::languages::output' is not set.\n";
$error = 2;
}
if (not $error)
{
foreach my $this_file (sort {$a cmp $b} keys %{$an->data->{words}})
{
#print $THIS_FILE." ".__LINE__."; [ Debug ] - this_file: [$this_file], file: [$file]\n";
# If they've specified a file and this doesn't match, skip it.
next if (($file) && ($this_file !~ /$file$/));
if (exists $an->data->{words}{$this_file}{language}{$language}{key}{$key}{content})
{
$string = $an->data->{words}{$this_file}{language}{$language}{key}{$key}{content};
#print $THIS_FILE." ".__LINE__."; [ Debug ] - string: [$string]\n";
last;
}
}
}
#print $THIS_FILE." ".__LINE__."; [ Debug ] - string: [$string]\n";
return($string);
}
=head2 read
This reads in a words file containing translated strings used to generated output for the user.
Example to read 'C<< an-tools.xml >>';
my $words_file = $an->data->{path}{words}{'an-words.xml'};
my $an->Words->read({file => $words_file}) or die "Failed to read: [$words_file]. Does the file exist?\n";
Successful read will return '0'. Non-0 is an error;
0 = OK
1 = Invalid file name or path
2 = File not found
3 = File not readable
4 = File found, failed to read for another reason. The error details will be printed.
NOTE: Read works are stored in 'C<< $an->data->{words}{<file_name>}{language}{<language>}{string}{content} >>'. Metadata, like what languages are provided, are stored under 'C<< $an->data->{words}{<file_name>}{meta}{...} >>'.
Parameters;
=head3 file (required)
This is the file to read.
=cut
sub read
{
my $self = shift;
my $parameter = shift;
my $an = $self->parent;
# Setup default values
my $file = defined $parameter->{file} ? $parameter->{file} : 0;
my $return_code = 0;
if (not $file)
{
# TODO: Log the problem, do not translate.
print $THIS_FILE." ".__LINE__."; [ Warning ] - AN::Tools::Words->read()' called without a file name to read.\n";
$return_code = 1;
}
elsif (not -e $file)
{
# TODO: Log the problem, do not translate.
print $THIS_FILE." ".__LINE__."; [ Warning ] - AN::Tools::Words->read()' asked to read: [$file] which was not found.\n";
$return_code = 2;
}
elsif (not -r $file)
{
# TODO: Log the problem, do not translate.
print $THIS_FILE." ".__LINE__."; [ Warning ] - AN::Tools::Words->read()' asked to read: [$file] which was not readable by: [".getpwuid($<)."/".getpwuid($>)."] (uid/euid: [".$<."/".$>."]).\n";
$return_code = 3;
}
else
{
# Read the file with XML::Simple
my $xml = XML::Simple->new();
eval { $an->data->{words}{$file} = $xml->XMLin($file, KeyAttr => { language => 'name', key => 'name' }, ForceArray => [ 'language', 'key' ]) };
if ($@)
{
chomp $@;
print $THIS_FILE." ".__LINE__."; [ Error ] - The was a problem reading: [$file]. The error was:\n";
print "===========================================================\n";
print $@."\n";
print "===========================================================\n";
$return_code = 4;
}
else
{
# Successfully read.
### Some debug stuff
# Read the meta data
#my $version = $an->data->{words}{$file}{meta}{version};
#my $languages = $an->data->{words}{$file}{meta}{languages};
#print $THIS_FILE." ".__LINE__."; [ Debug ] - Version: [$version], languages: [$languages]\n";
#foreach my $this_language (sort {$a cmp $b} keys %{$an->data->{words}{$file}{language}})
#{
# my $long_name = $an->data->{words}{$file}{language}{$this_language}{long_name};
# print $THIS_FILE." ".__LINE__."; [ Debug ] - this_language: [$this_language], long_name: [$long_name]\n";
# print $THIS_FILE." ".__LINE__."; [ Debug ] - "$this_language:t_0001: [".$an->data->{words}{$file}{language}{$this_language}{key}{t_0001}{content}."]\n";
#}
}
}
return($return_code);
}
# =head3
#
# Private Functions;
#
# =cut
#############################################################################################################
# Private functions #
#############################################################################################################
1;