File Coverage

blib/lib/NetSDS/Util/Translit.pm
Criterion Covered Total %
statement 33 98 33.6
branch 0 4 0.0
condition 0 7 0.0
subroutine 11 14 78.5
pod 2 2 100.0
total 46 125 36.8


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # FILE: Translit.pm
4             #
5             # DESCRIPTION: Cyrillic transliteration routines
6             #
7             # NOTE: This module ported from Wono framework "as is"
8             # AUTHOR: Michael Bochkaryov (Rattler), <misha@rattler.kiev.ua>
9             # COMPANY: Net.Style
10             # VERSION: 1.044
11             # CREATED: 03.08.2008 15:04:22 EEST
12             #===============================================================================
13              
14             =head1 NAME
15              
16             NetSDS::Util::Translit - transliteration routines
17              
18             =head1 SYNOPSIS
19              
20             use NetSDS::Const;
21             use NetSDS::Util::Translit;
22              
23             # Transliterate cyrillic string
24             $trans_string = trans_cyr_lat($cyr_string);
25              
26             # Reverse transliteration to russian language
27             $rus_string = trans_lat_cyr("Vsem privet", LANG_RU);
28              
29             =head1 DESCRIPTION
30              
31             C<NetSDS::Util::Translit> module contains routines for bidirectional
32             cyrillic text transliteration. Now it supports russian and ukrainian
33             languages processing.
34              
35             =cut
36              
37             package NetSDS::Util::Translit;
38              
39 2     2   7926 use 5.8.0;
  2         9  
  2         116  
40 2     2   13 use warnings 'all';
  2         5  
  2         85  
41 2     2   11 use strict;
  2         5  
  2         72  
42              
43 2     2   10 use base 'Exporter';
  2         6  
  2         355  
44              
45 2     2   14 use version; our $VERSION = '1.044';
  2         5  
  2         30  
46              
47 2     2   186 use NetSDS::Util::String;
  2         6  
  2         294  
48              
49             our @EXPORT = qw(
50             trans_cyr_lat
51             trans_lat_cyr
52             );
53              
54 2     2   14 use constant LANG_BE => 'be';
  2         11  
  2         155  
55 2     2   223 use constant LANG_EN => 'en';
  2         5  
  2         135  
56 2     2   12 use constant LANG_RU => 'ru';
  2         5  
  2         88  
57 2     2   10 use constant LANG_UK => 'uk';
  2         4  
  2         109  
58              
59 2     2   11 use constant DEFAULT_LANG => LANG_RU;
  2         3  
  2         3839  
60              
61             my %PREP = (
62             LANG_RU() => {
63             'а' => 'a',
64             'б' => 'b',
65             'в' => 'v',
66             'г' => 'g',
67             'д' => 'd',
68             'е' => 'e',
69             'Ñ‘' => 'yo',
70             'ж' => 'zh',
71             'з' => 'z',
72             'и' => 'i',
73             'й' => 'j',
74             'к' => 'k',
75             'л' => 'l',
76             'м' => 'm',
77             'н' => 'n',
78             'о' => 'o',
79             'п' => 'p',
80             'Ñ€' => 'r',
81             'с' => 's',
82             'Ñ‚' => 't',
83             'у' => 'u',
84             'Ñ„' => 'f',
85             'Ñ…' => 'kh',
86             'ц' => 'tc',
87             'ч' => 'ch',
88             'ш' => 'sh',
89             'щ' => 'sch',
90             'ÑŠ' => '"',
91             'Ñ‹' => 'y',
92             'ые' => 'yje',
93             'Ñ‹Ñ‘' => 'yjo',
94             'ыу' => 'yiu',
95             'Ñ‹ÑŽ' => 'yju',
96             'ыя' => 'yja',
97             'ÑŒ' => "'",
98             'ье' => 'jie',
99             'ьё' => 'jio',
100             'ью' => 'jiu',
101             'ья' => 'jia',
102             'э' => 'ye',
103             'ÑŽ' => 'yu',
104             'я' => 'ya',
105             },
106              
107             LANG_UK() => {
108             "'" => '"',
109             'а' => 'a',
110             'б' => 'b',
111             'в' => 'v',
112             'Ò‘' => 'g',
113             'г' => 'h',
114             'д' => 'd',
115             'е' => 'e',
116             'Ñ”' => 'ye',
117             'ж' => 'zh',
118             'з' => 'z',
119             'Ñ–' => 'i',
120             'и' => 'y',
121             'Ñ—' => 'yi',
122             'й' => 'j',
123             'к' => 'k',
124             'л' => 'l',
125             'м' => 'm',
126             'н' => 'n',
127             'о' => 'o',
128             'п' => 'p',
129             'Ñ€' => 'r',
130             'с' => 's',
131             'Ñ‚' => 't',
132             'у' => 'u',
133             'Ñ„' => 'f',
134             'Ñ…' => 'kh',
135             'ц' => 'tc',
136             'ч' => 'ch',
137             'ш' => 'sh',
138             'щ' => 'sch',
139             'ÑŒ' => "'",
140             'ÑŽ' => 'yu',
141             'я' => 'ya',
142             },
143              
144             LANG_BE() => {
145             "'" => '"',
146             'а' => 'a',
147             'б' => 'b',
148             'в' => 'v',
149             'Ò‘' => 'g',
150             'г' => 'h',
151             'д' => 'd',
152             'е' => 'ye',
153             'Ñ‘' => 'yo',
154             'ж' => 'zh',
155             'з' => 'z',
156             'Ñ–' => 'i',
157             'и' => 'i',
158             'Ñ—' => 'yi',
159             'й' => 'j',
160             'к' => 'k',
161             'л' => 'l',
162             'м' => 'm',
163             'н' => 'n',
164             'о' => 'o',
165             'п' => 'p',
166             'Ñ€' => 'r',
167             'с' => 's',
168             'Ñ‚' => 't',
169             'у' => 'u',
170             'Ñž' => 'w',
171             'Ñ„' => 'f',
172             'Ñ…' => 'kh',
173             'ц' => 'tc',
174             'ч' => 'ch',
175             'ш' => 'sh',
176             'щ' => 'sch',
177             'Ñ‹' => 'y',
178             'ые' => 'yje',
179             'Ñ‹Ñ‘' => 'yjo',
180             'ыу' => 'yiu',
181             'Ñ‹ÑŽ' => 'yju',
182             'ыя' => 'yja',
183             'ÑŒ' => "'",
184             'ье' => 'jie',
185             'ьё' => 'jio',
186             'ью' => 'jiu',
187             'ья' => 'jia',
188             'э' => 'e',
189             'ÑŽ' => 'yu',
190             'я' => 'ya',
191             },
192             );
193              
194             my %TO_LAT = ();
195              
196             my %TO_CYR = ();
197              
198             #*********************************************************************************************
199             sub _prep_translit {
200 0     0     my ($lang) = @_;
201              
202 0 0         return if ( $PREP{prepared}->{$lang} );
203              
204 0           my $rfw = {};
205 0           my $rbw = {};
206 0           while ( my ( $fw, $bw ) = each %{ $PREP{$lang} } ) {
  0            
207 0           $fw = str_encode($fw);
208 0           $bw = str_encode($bw);
209 0           my $lf = length($fw);
210 0           my $lb = length($bw);
211 0 0 0       if ( ( $lf == 1 ) and ( $lb == 1 ) ) {
212 0           $rfw->{0}->{ uc($fw) } = uc($bw);
213 0           $rfw->{0}->{ ucfirst($fw) } = ucfirst($bw);
214 0           $rfw->{0}->{$fw} = $bw;
215              
216 0           $rbw->{0}->{ uc($bw) } = uc($fw);
217 0           $rbw->{0}->{ ucfirst($bw) } = ucfirst($fw);
218 0           $rbw->{0}->{$bw} = $fw;
219             } else {
220 0           $rfw->{$lf}->{ uc($fw) } = uc($bw);
221 0           $rfw->{$lf}->{ ucfirst($fw) } = ucfirst($bw);
222 0           $rfw->{$lf}->{$fw} = $bw;
223              
224 0           $rbw->{$lb}->{ uc($bw) } = uc($fw);
225 0           $rbw->{$lb}->{ ucfirst($bw) } = ucfirst($fw);
226 0           $rbw->{$lb}->{$bw} = $fw;
227             }
228             } ## end while ( my ( $fw, $bw ) =...
229              
230 0           $TO_LAT{$lang} = [];
231 0           foreach my $ord ( reverse sort { $a <=> $b } keys %{$rfw} ) {
  0            
  0            
232 0           my $tra = $rfw->{$ord};
233 0           my $fnd = join( '|', keys %{$tra} );
  0            
234 0           push( @{ $TO_LAT{$lang} }, [ $fnd, $tra ] );
  0            
235             }
236              
237 0           $TO_CYR{$lang} = [];
238 0           foreach my $ord ( reverse sort { $a <=> $b } keys %{$rbw} ) {
  0            
  0            
239 0           my $tra = $rbw->{$ord};
240 0           my $fnd = join( '|', keys %{$tra} );
  0            
241 0           push( @{ $TO_CYR{$lang} }, [ $fnd, $tra ] );
  0            
242             }
243              
244 0           $PREP{prepared}->{$lang} = 1;
245             } ## end sub _prep_translit
246              
247             #*********************************************************************************************
248              
249             =head1 EXPORTS
250              
251             =over
252              
253             =item B<trans_cyr_lat($text[, $lang])> - transliterate string
254              
255             Convert text from cyrillic to latin encoding.
256              
257             Language may be set if not default one.
258              
259             $lat = trans_cyr_lat($string);
260              
261             =cut
262              
263             #-----------------------------------------------------------------------
264             sub trans_cyr_lat {
265 0     0 1   my ( $text, $lang ) = @_;
266              
267 0   0       $lang ||= DEFAULT_LANG();
268              
269 0           _prep_translit($lang);
270              
271 0           $text = str_encode($text);
272              
273 0           foreach my $row ( @{ $TO_LAT{$lang} } ) {
  0            
274 0           my ( $fnd, $has ) = @{$row};
  0            
275 0           $text =~ s/($row->[0])/$row->[1]->{$1}/ge;
  0            
276             }
277 0           $text =~ s/[^\x{0}-\x{7f}]+/\?/g;
278              
279 0           return str_decode($text);
280             }
281              
282             #*********************************************************************************************
283              
284             =item B<trans_lat_cyr($text[, $lang])> - reverse transliteration
285              
286             This function transliterate string from latin encoding to cyrillic one.
287              
288             Target language may be set if not default one.
289              
290             $cyr = trans_lat_cyr("Sam baran", "ru");
291              
292             =cut
293              
294             #-----------------------------------------------------------------------
295             sub trans_lat_cyr {
296 0     0 1   my ( $text, $lang ) = @_;
297              
298 0   0       $lang ||= DEFAULT_LANG();
299              
300 0           _prep_translit($lang);
301              
302 0           $text = str_encode($text);
303              
304 0           $text =~ s/[^\x{0}-\x{7f}]+/\?/g;
305 0           foreach my $row ( @{ $TO_CYR{$lang} } ) {
  0            
306 0           my ( $fnd, $has ) = @{$row};
  0            
307 0           $text =~ s/($row->[0])/$row->[1]->{$1}/sg;
308             }
309              
310 0           return str_decode($text);
311             }
312              
313             1;
314             __END__
315              
316             =back
317              
318             =head1 EXAMPLES
319              
320             None yet
321              
322             =head1 BUGS
323              
324             Unknown yet
325              
326             =head1 TODO
327              
328             Implement examples and tests.
329              
330             =head1 SEE ALSO
331              
332             L<Encode>, L<perlunicode>
333              
334             =head1 AUTHORS
335              
336             Valentyn Solomko <pere@pere.org.ua>
337              
338             =cut