Merge branch 'master' of github.com:kivitendo/kivitendo-erp
[kivitendo-erp.git] / SL / Locale / String.pm
1 package SL::Locale::String;
2
3 use strict;
4
5 use parent qw(Rose::Object Exporter);
6
7 use Rose::Object::MakeMethods::Generic (
8   scalar => [ qw(untranslated) ],
9   array  => [ qw(args) ],
10 );
11
12 our @EXPORT = qw(t8);
13
14 use overload '""' => \&translated;
15
16 sub translated {
17   my ($self) = @_;
18   return $::locale ? $::locale->text($self->untranslated, $self->args) : $self->untranslated;
19 }
20
21 sub t8 {
22   shift if $_[0] eq __PACKAGE__;
23
24   my $string = shift;
25   return SL::Locale::String->new(untranslated => $string, args => [ @_ ]);
26 }
27
28 sub TO_JSON {
29   return $_[0]->translated;
30 }
31
32 1;
33 __END__
34
35 =pod
36
37 =encoding utf8
38
39 =head1 NAME
40
41 SL::Locale::String - Helper class for translating strings at a later
42 date (e.g. use at compile time, actual translation during execution
43 time)
44
45 =head1 SYNOPSIS
46
47   use SL::Locale::String;
48
49   use SL::Controller::Helper::Sorted;
50
51   __PACKAGE__->make_sorted(
52     ...
53     qty => { title => t8("Quantity") },
54  );
55
56 =head1 OVERVIEW
57
58 Every string that should be translated must be recognized by our
59 translation helper script C<script/locales.pl> somehow. It recognizes
60 certain function calls as translation instructions and extracts its
61 arguments for translation by developers/translators.
62
63 This works well for calls that occur during execution time: C<<
64 $::locale->text("Untranslated") >>. However, for untranslated strings
65 that need to be used at compile time this fails in subtle and not so
66 subtle ways. If it happens in a module that is C<use>d directly from
67 the dispatcher then C<$::locale> is not defined and such a call would
68 end in an error. For modules like controllers that are C<require>d
69 during execution time it seems to work, but in FastCGI situations this
70 means that the first call determines the language and all subsequent
71 calls end up using the same language no matter which language the user
72 has chosen.
73
74 This class solves the issue by providing a small function called L<t8>
75 which can be used instead of C<< $::locale->text() >>. It is
76 recognized by C<script/locales.pl>. The untranslated string given to
77 L<t8> is stored in an instance of C<SL::Locale::String> and translated
78 only when requested either by calling L<translated> or by
79 stringification.
80
81 Instances of this class can safely be handed over to C<<
82 $::locale->text() >> which knows how to handle them (and not to
83 re-translate them).
84
85 The function L<t8> is exported by default.
86
87 =head1 FUNCTIONS
88
89 =head2 EXPORTED FUNCTIONS
90
91 =over 4
92
93 =item C<t8 $untranslated_string>
94
95 Returns a new instance of C<SL::Locale::String> and sets its
96 L<untranslated> member to C<$untranslated_string>. This function is
97 exported and cannot be called as a class or instance method.
98
99 =back
100
101 =head2 INSTANCE FUNCTIONS
102
103 =over 4
104
105 =item C<untranslated [$new_untranslated]>
106
107 Gets or sets the untranslated string.
108
109 =item C<translated>
110
111 Returns the translated version of the untranslated string. Translation
112 occurs when this function is called and not when the object instance
113 is created.
114
115 This function is also called during stringification.
116
117 =back
118
119 =head1 BUGS
120
121 Nothing here yet.
122
123 =head1 AUTHOR
124
125 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
126
127 =cut