SL::Locale::String-Klasse für verzögerte Übersetzung hinzugefügt
authorMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 6 Sep 2012 08:00:17 +0000 (10:00 +0200)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 6 Sep 2012 09:02:57 +0000 (11:02 +0200)
SL/Controller/Helper/Sorted.pm
SL/Locale.pm
SL/Locale/String.pm [new file with mode: 0644]
scripts/locales.pl

index 8699f00..c9e5779 100644 (file)
@@ -22,7 +22,7 @@ sub make_sorted {
   while (my ($column, $spec) = each %specs) {
     next if $column =~ m/^[A-Z_]+$/;
 
-    $spec = $specs{$column} = { title => $spec } if !ref $spec;
+    $spec = $specs{$column} = { title => $spec } if (ref($spec) || '') ne 'HASH';
 
     $spec->{model}        ||= $specs{MODEL};
     $spec->{model_column} ||= $column;
index 5016900..8fa3780 100644 (file)
@@ -214,6 +214,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 {
diff --git a/SL/Locale/String.pm b/SL/Locale/String.pm
new file mode 100644 (file)
index 0000000..42ceb22
--- /dev/null
@@ -0,0 +1,120 @@
+package SL::Locale::String;
+
+use strict;
+
+use parent qw(Rose::Object Exporter);
+
+use Rose::Object::MakeMethods::Generic (
+  scalar => [ qw(untranslated) ],
+);
+
+our @EXPORT = qw(t8);
+
+use overload '""' => \&translated;
+
+sub translated {
+  my ($self) = @_;
+  return $::locale ? $::locale->text($self->untranslated) : $self->untranslated;
+}
+
+sub t8 {
+  my $string = $_[ ref($_[0]) || ($_[0] eq 'SL::Locale::String') ? 1 : 0 ];
+  return SL::Locale::String->new(untranslated => $string);
+}
+
+1;
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::Locale::String - Helper class for translating strings at a later
+date (e.g. use at compile time, actual translation during execution
+time)
+
+=head1 SYNOPSIS
+
+  use SL::Locale::String;
+
+  use SL::Controller::Helper::Sorted;
+
+  __PACKAGE__->make_sorted(
+    ...
+    qty => { title => t8("Quantity") },
+ );
+
+=head1 OVERVIEW
+
+Every string that should be translated must be recognized by our
+translation helper script C<script/locales.pl> somehow. It recognizes
+certain function calls as translation instructions and extracts its
+arguments for translation by developers/translators.
+
+This works well for calls that occur during execution time: C<<
+$::locale->text("Untranslated") >>. However, for untranslated strings
+that need to be used at compile time this fails in subtle and not so
+subtle ways. If it happens in a module that is C<use>d directly from
+the dispatcher then C<$::locale> is not defined and such a call would
+end in an error. For modules like controllers that are C<require>d
+during execution time it seems to work, but in FastCGI situations this
+means that the first call determines the language and all subsequent
+calls end up using the same language no matter which language the user
+has chosen.
+
+This class solves the issue by providing a small function called L<t8>
+which can be used instead of C<< $::locale->text() >>. It is
+recognized by C<script/locales.pl>. The untranslated string given to
+L<t8> is stored in an instance of C<SL::Locale::String> and translated
+only when requested either by calling L<translated> or by
+stringification.
+
+Instances of this class can safely be handed over to C<<
+$::locale->text() >> which knows how to handle them (and not to
+re-translate them).
+
+The function L<t8> is exported by default.
+
+=head1 FUNCTIONS
+
+=head2 EXPORTED FUNCTIONS
+
+=over 4
+
+=item C<t8 $untranslated_string>
+
+Returns a new instance of C<SL::Locale::String> and sets its
+L<untranslated> member to C<$untranslated_string>. This function is
+exported and cannot be called as a class or instance method.
+
+=back
+
+=head2 INSTANCE FUNCTIONS
+
+=over 4
+
+=item C<untranslated [$new_untranslated]>
+
+Gets or sets the untranslated string.
+
+=item C<translated>
+
+Returns the translated version of the untranslated string. Translation
+occurs when this function is called and not when the object instance
+is created.
+
+This function is also called during stringification.
+
+=back
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
index 0780a49..f663014 100755 (executable)
@@ -404,7 +404,7 @@ sub scanfile {
           }
         }
 
-        my ($found) = /locale->text.*?\(/;
+        my ($found) = / (?: locale->text | \b t8 ) \b .*? \(/x;
         $postmatch = "$'";
 
         if ($found) {