X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FLocale.pm;h=3b91502d5e2f990e11497512768396787f1572a4;hb=43816cb7289ee9225c3bb229d077bd87a75562cc;hp=8a2caa2c0bfb7e335b046f88eb94a075ea4508e5;hpb=abde405dfaab376a13e9a1e3e24cd715fa7de024;p=kivitendo-erp.git diff --git a/SL/Locale.pm b/SL/Locale.pm index 8a2caa2c0..3b91502d5 100644 --- a/SL/Locale.pm +++ b/SL/Locale.pm @@ -27,7 +27,8 @@ # 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, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1335, USA. #====================================================================== # # Translations and number/date formatting @@ -73,43 +74,52 @@ sub new { return $locales_by_country{$country} } +sub is_supported { + my ($country) = @_; + + return -f "locale/$country/all"; +} + sub _init { my $self = shift; my $country = shift; - $self->{charset} = Common::DEFAULT_CHARSET; $self->{countrycode} = $country; if ($country && -d "locale/$country") { - local *IN; - if (open(IN, "<", "locale/$country/all")) { - my $code = join("", ); + if (open my $in, "<", "locale/$country/all") { + local $/ = undef; + my $code = <$in>; eval($code); - close(IN); + close($in); } - if (open IN, "<", "locale/$country/charset") { - $self->{charset} = ; - close IN; - - chomp $self->{charset}; + if (-d "locale/$country/more") { + opendir my $dh, "locale/$country/more" or die "can't open locale/$country/more: $!"; + my @files = sort grep -f "locale/$country/more/$_", readdir $dh; + close $dh; + + for my $file (@files) { + if (open my $in, "<", "locale/$country/more/$file") { + local $/ = undef; + my $code = <$in>; + eval($code); + close($in); + $self->{texts}{$_} = $self->{more_texts}{$_} for keys %{ $self->{more_texts} }; + } + } } } - my $db_charset = $::lx_office_conf{system}->{dbcharset} || Common::DEFAULT_CHARSET; - $self->{is_utf8} = (any { lc($::lx_office_conf{system}->{dbcharset} || '') eq $_ } qw(utf8 utf-8 unicode)) ? 1 : 0; + binmode STDOUT, ":utf8"; + binmode STDERR, ":utf8"; - if ($self->{is_utf8}) { - binmode STDOUT, ":utf8"; - binmode STDERR, ":utf8"; - } - - $self->{iconv} = SL::Iconv->new($self->{charset}, $db_charset); - $self->{iconv_reverse} = SL::Iconv->new($db_charset, $self->{charset}); - $self->{iconv_english} = SL::Iconv->new('ASCII', $db_charset); - $self->{iconv_iso8859} = SL::Iconv->new('ISO-8859-15', $db_charset); - $self->{iconv_to_iso8859} = SL::Iconv->new($db_charset, 'ISO-8859-15'); - $self->{iconv_utf8} = SL::Iconv->new('UTF-8', $db_charset); + $self->{iconv} = SL::Iconv->new('UTF-8', 'UTF-8'); + $self->{iconv_reverse} = SL::Iconv->new('UTF-8', 'UTF-8'); + $self->{iconv_english} = SL::Iconv->new('ASCII', 'UTF-8'); + $self->{iconv_iso8859} = SL::Iconv->new('ISO-8859-15', 'UTF-8'); + $self->{iconv_to_iso8859} = SL::Iconv->new('UTF-8', 'ISO-8859-15'); + $self->{iconv_utf8} = SL::Iconv->new('UTF-8', 'UTF-8'); $self->_read_special_chars_file($country); @@ -121,12 +131,6 @@ sub _init { (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)); } -sub is_utf8 { - my $self = shift; - my $handle = shift; - return $self->{is_utf8} && (!$handle || $handle->is_utf8); -} - sub _handle_markup { my $self = shift; my $str = shift; @@ -214,6 +218,8 @@ sub text { my $self = shift; my $text = shift; + return $text->translated if (ref($text) || '') eq 'SL::Locale::String'; + if ($self->{texts}->{$text}) { $text = $self->{iconv}->convert($self->{texts}->{$text}); } else { @@ -326,7 +332,7 @@ sub date { } elsif ($myconfig->{dateformat} eq "yyyy-mm-dd") { # Use German syntax with the ISO date style "yyyy-mm-dd" because - # Lx-Office is mainly used in Germany or German speaking countries. + # kivitendo is mainly used in Germany or German speaking countries. if (defined $longformat && $longformat == 0) { $mm++; $dd = "0$dd" if ($dd < 10); @@ -381,8 +387,8 @@ sub parse_date { ($yy, $mm, $dd) = ($date =~ /(..)(..)(..)/); } - $dd *= 1; - $mm *= 1; + $_ ||= 0 for ($dd, $mm, $yy); + $_ *= 1 for ($dd, $mm, $yy); $yy = ($yy < 70) ? $yy + 2000 : $yy; $yy = ($yy >= 70 && $yy <= 99) ? $yy + 1900 : $yy; @@ -391,27 +397,60 @@ sub parse_date { } sub parse_date_to_object { - my $self = shift; - my ($yy, $mm, $dd) = $self->parse_date(@_); + my ($self, $string, %params) = @_; + + return undef if !defined $string; + + return DateTime->today_local if lc($string) eq 'today'; + return DateTime->today_local->subtract(days => 1) if lc($string) eq 'yesterday'; + + $params{dateformat} ||= $::myconfig{dateformat} || 'yy-mm-dd'; + $params{numberformat} ||= $::myconfig{numberformat} || '1,000.00'; + my $num_separator = $params{numberformat} =~ m{,\d+$} ? ',' : '.'; + + my ($date_str, $time_str) = split m{\s+}, $string, 2; + my ($yy, $mm, $dd) = $self->parse_date(\%params, $date_str); + + my ($hour, $minute, $second) = split m/:/, ($time_str || ''); + $second ||= '0'; + + ($second, my $millisecond) = split quotemeta($num_separator), $second, 2; + $_ ||= 0 for ($hour, $minute, $millisecond); + + $millisecond = substr $millisecond, 0, 3; + $millisecond .= '0' x (3 - length $millisecond); - return $yy && $mm && $dd ? DateTime->new(year => $yy, month => $mm, day => $dd) : undef; + return undef unless $yy && $mm && $dd; + return DateTime->new(year => $yy, month => $mm, day => $dd, hour => $hour * 1, minute => $minute * 1, second => $second * 1, nanosecond => $millisecond * 1000000); +} + +sub format_date_object_to_time { + my ($self, $datetime, %params) = @_; + + my $format = $::myconfig{timeformat} || 'hh:mm'; + $format =~ s/hh/\%H/; + $format =~ s/mm/\%M/; + $format =~ s/ss/\%S/; + + return $datetime->strftime($format); } sub format_date_object { my ($self, $datetime, %params) = @_; - my $format = $::myconfig{dateformat} || 'yyyy-mm-dd'; - $format =~ s/yyyy/\%Y/; - $format =~ s/yy/\%y/; + my $format = $params{dateformat} || $::myconfig{dateformat} || 'yyyy-mm-dd'; + my $num_separator = ($params{numberformat} || $::myconfig{numberformat} || '1,000.00') =~ m{,\d+$} ? ',' : '.'; + $format =~ s/yy(?:yy)?/\%Y/; $format =~ s/mm/\%m/; $format =~ s/dd/\%d/; my $precision = $params{precision} || 'day'; $precision =~ s/s$//; my %precision_spec_map = ( - second => '%H:%M:%S', - minute => '%H:%M', - hour => '%H', + millisecond => '%H:%M:%S' . $num_separator . '%3N', + second => '%H:%M:%S', + minute => '%H:%M', + hour => '%H', ); $format .= ' ' . $precision_spec_map{$precision} if $precision_spec_map{$precision}; @@ -428,13 +467,13 @@ sub reformat_date { my ($yy, $mm, $dd) = $self->parse_date($myconfig, $date); - $output_format =~ /d+/; + $output_format =~ /(d+)/; substr($output_format, $-[0], $+[0] - $-[0]) = - sprintf("%0" . (length($&)) . "d", $dd); + sprintf("%0" . (length($1)) . "d", $dd); - $output_format =~ /m+/; + $output_format =~ /(m+)/; substr($output_format, $-[0], $+[0] - $-[0]) = - sprintf("%0" . (length($&)) . "d", $mm); + sprintf("%0" . (length($1)) . "d", $mm); $output_format =~ /y+/; substr($output_format, $-[0], $+[0] - $-[0]) = $yy; @@ -461,9 +500,9 @@ sub format_date { $yy = $yy % 100 if 2 == $yy_len; my $format = ref $myconfig eq '' ? "$myconfig" : $myconfig->{dateformat}; - $format =~ s{ d+ }{ sprintf("%0" . (length($&)) . "d", $dd) }gex; - $format =~ s{ m+ }{ sprintf("%0" . (length($&)) . "d", $mm) }gex; - $format =~ s{ y+ }{ sprintf("%0${yy_len}d", $yy) }gex; + $format =~ s{ (d+) }{ sprintf("%0" . (length($1)) . "d", $dd) }gex; + $format =~ s{ (m+) }{ sprintf("%0" . (length($1)) . "d", $mm) }gex; + $format =~ s{ (y+) }{ sprintf("%0${yy_len}d", $yy) }gex; $main::lxdebug->leave_sub(); @@ -513,7 +552,7 @@ sub with_raw_io { $self->{raw_io_active} = 1; binmode $fh, ":raw"; $code->(); - binmode $fh, ":utf8" if $self->is_utf8; + binmode $fh, ":utf8"; $self->{raw_io_active} = 0; } @@ -538,7 +577,20 @@ sub get_local_time_zone { return $self->{local_time_zone}; } +sub language_join { + my ($self, $items, %params) = @_; + + $items ||= []; + $params{conjunction} ||= $::locale->text('and'); + my $num = scalar @{ $items }; + + return 0 == $num ? '' + : 1 == $num ? $items->[0] + : join(', ', @{ $items }[0..$num - 2]) . ' ' . $params{conjunction} . ' ' . $items->[$num - 1]; +} + 1; + __END__ =pod @@ -547,7 +599,7 @@ __END__ =head1 NAME -Locale - Functions for dealing with locale-dependant information +Locale - Functions for dealing with locale-dependent information =head1 SYNOPSIS @@ -580,7 +632,7 @@ TODO: Describe format_date =item C -Formats the C<$datetime> object accoring to the user's locale setting. +Formats the C<$datetime> object according to the user's locale setting. The parameter C can control whether or not the time component is formatted as well: @@ -603,16 +655,27 @@ Add hour:minute to the date. Add hour:minute:second to the date. +=item * C + +Add hour:minute:second.millisecond to the date. The decimal separator +is derived from the number format. + +=item * C + +The number format to use, e.g. C<1,000.00>. If unset the user's +current number format is used. + +=item * C + +The date format to use, e.g. C. If unset the user's current +date format is used. + =back =item C TODO: Describe get_local_time_zone -=item C - -TODO: Describe is_utf8 - =item C TODO: Describe lang_to_locale @@ -625,9 +688,14 @@ TODO: Describe new TODO: Describe parse_date -=item C +=item C + +Parses a date and optional timestamp in C<$string> and returns an +instance of L. The date and number formats used are the ones +the user has currently selected. They can be overriden by passing them +in as parameters to this function, though. -TODO: Describe parse_date_to_object +The time stamps can have up to millisecond precision. =item C