line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Yandex::Translate; |
2
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
101143
|
use strict; |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
161
|
|
4
|
5
|
|
|
5
|
|
30
|
use warnings; |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
173
|
|
5
|
5
|
|
|
5
|
|
1349
|
use utf8; |
|
5
|
|
|
|
|
43
|
|
|
5
|
|
|
|
|
34
|
|
6
|
|
|
|
|
|
|
|
7
|
5
|
|
|
5
|
|
2834
|
use HTML::Entities qw{encode_entities}; |
|
5
|
|
|
|
|
33464
|
|
|
5
|
|
|
|
|
443
|
|
8
|
5
|
|
|
5
|
|
3487
|
use HTTP::Tiny; |
|
5
|
|
|
|
|
240559
|
|
|
5
|
|
|
|
|
201
|
|
9
|
5
|
|
|
5
|
|
3390
|
use JSON; |
|
5
|
|
|
|
|
53187
|
|
|
5
|
|
|
|
|
26
|
|
10
|
5
|
|
|
5
|
|
641
|
use POSIX qw{:locale_h}; |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
40
|
|
11
|
5
|
|
|
5
|
|
2766
|
use URI::Escape qw{uri_escape_utf8}; |
|
5
|
|
|
|
|
6961
|
|
|
5
|
|
|
|
|
7915
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
# The “my” keyword is on a separate line so that the VERSION_FROM attribute |
15
|
|
|
|
|
|
|
# of ExtUtils::MakeMaker->WriteMakefile() will accurately detect $VERSION. |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
my |
18
|
|
|
|
|
|
|
$VERSION = '1.001'; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# |
21
|
|
|
|
|
|
|
# See https://tech.yandex.ru/translate/doc/dg/concepts/api-overview-docpage/ |
22
|
|
|
|
|
|
|
# for the supported language codes. |
23
|
|
|
|
|
|
|
# |
24
|
|
|
|
|
|
|
my %valid_lang = map { $_ => 1 } qw{ |
25
|
|
|
|
|
|
|
az sq am en ar hy af eu ba be bn my bg bs cy hu vi ht gl nl |
26
|
|
|
|
|
|
|
mrj el ka gu da he yi id ga it is es kk kn ca ky zh ko xh km |
27
|
|
|
|
|
|
|
lo la lv lt lb mg ms |
28
|
|
|
|
|
|
|
ml mt mk mi mr mhr mn de ne no pa pap fa pl pt ro ru ceb sr si |
29
|
|
|
|
|
|
|
sk sl sw su tg th tl ta tt te tr udm uz uk ur fi fr hi hr cs |
30
|
|
|
|
|
|
|
sv gd et eo jv ja |
31
|
|
|
|
|
|
|
}; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my %valid_format = map { $_ => 1 } qw { plain html }; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my %valid_options = map { $_ => 1 } qw { 1 }; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
my %valid_default_ui = map { $_ => 1 } qw{ en ru tr }; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# |
40
|
|
|
|
|
|
|
# Set the default UI to Russian if the locale is Russian; |
41
|
|
|
|
|
|
|
# Set the default UI to Turkish if the locale is Turkish; |
42
|
|
|
|
|
|
|
# otherwise, set it to English. |
43
|
|
|
|
|
|
|
# |
44
|
|
|
|
|
|
|
(my $default_ui = setlocale(LC_CTYPE) || 'en') =~ s/_.*$//; |
45
|
|
|
|
|
|
|
$default_ui = 'en' if (!exists $valid_default_ui{$default_ui}); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub new |
48
|
|
|
|
|
|
|
{ |
49
|
1
|
|
|
1
|
1
|
10
|
my $class = shift; |
50
|
1
|
|
33
|
|
|
16
|
my $self = { |
51
|
|
|
|
|
|
|
_key_ => shift, |
52
|
|
|
|
|
|
|
_text_ => shift, |
53
|
|
|
|
|
|
|
_from_lang_ => shift, |
54
|
|
|
|
|
|
|
_to_lang_ => shift, |
55
|
|
|
|
|
|
|
_ui_ => shift || $default_ui, |
56
|
|
|
|
|
|
|
_hint_ => shift, |
57
|
|
|
|
|
|
|
_format_ => shift, |
58
|
|
|
|
|
|
|
_options_ => shift, |
59
|
|
|
|
|
|
|
_base_ => 'https://translate.yandex.net/api/v1.5/tr.json', |
60
|
|
|
|
|
|
|
_post_ => undef, |
61
|
|
|
|
|
|
|
_http_ => HTTP::Tiny->new |
62
|
|
|
|
|
|
|
}; |
63
|
|
|
|
|
|
|
|
64
|
1
|
50
|
|
|
|
118
|
$self->{_text_} = uri_escape_utf8($self->{_text_}) if (defined $self->{_text_}); |
65
|
|
|
|
|
|
|
|
66
|
1
|
|
|
|
|
3
|
return bless $self, $class; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub set_key |
70
|
|
|
|
|
|
|
{ |
71
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $key ) = @_; |
72
|
0
|
0
|
|
|
|
0
|
$self->{_key_} = $key if (defined $key); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub set_ui |
76
|
|
|
|
|
|
|
{ |
77
|
3
|
|
|
3
|
1
|
1407
|
my ( $self, $ui ) = @_; |
78
|
3
|
50
|
33
|
|
|
21
|
$self->{_ui_} = (defined $ui && exists $valid_lang{$ui}) ? $ui : $default_ui; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub set_default_ui |
82
|
|
|
|
|
|
|
{ |
83
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $this_default_ui ) = @_; |
84
|
0
|
0
|
0
|
|
|
0
|
$default_ui = $this_default_ui if (defined $this_default_ui && exists $valid_default_ui{$this_default_ui}); |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# |
88
|
|
|
|
|
|
|
# Get a list of supported translation directions. |
89
|
|
|
|
|
|
|
# |
90
|
|
|
|
|
|
|
sub get_langs_list |
91
|
|
|
|
|
|
|
{ |
92
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
93
|
0
|
0
|
|
|
|
0
|
die "You must set API key\n" if (not defined $self->{ _key_ }); |
94
|
|
|
|
|
|
|
|
95
|
0
|
|
|
|
|
0
|
my $query = '/getLangs?'; |
96
|
0
|
|
|
|
|
0
|
$self->{_post_} = 'key='.$self->{_key_}.'&ui='.$self->{_ui_}; |
97
|
0
|
|
|
|
|
0
|
my $response = $self->{_http_}->get($self->{_base_} . $query . $self->{_post_}); |
98
|
|
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
0
|
die "Invalid API key\n" if ($response->{status} eq '401'); |
100
|
0
|
0
|
|
|
|
0
|
die "Blocked API key\n" if ($response->{status} eq '402'); |
101
|
0
|
0
|
|
|
|
0
|
die "Failed to get list of supported languages! (response code $response->{status})\n" unless ($response->{success}); |
102
|
|
|
|
|
|
|
|
103
|
0
|
0
|
0
|
|
|
0
|
if (defined wantarray && length $response->{content}) { |
104
|
0
|
|
|
|
|
0
|
my $json_respond = JSON->new->utf8->decode($response->{content}); |
105
|
0
|
0
|
|
|
|
0
|
return (wantarray) ? @{ $json_respond->{dirs} } : scalar(@{ $json_respond->{dirs} }); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub set_text |
110
|
|
|
|
|
|
|
{ |
111
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $text ) = @_; |
112
|
0
|
0
|
|
|
|
0
|
$self->{_text_} = uri_escape_utf8($text) if (defined $text); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub set_hint |
116
|
|
|
|
|
|
|
{ |
117
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $hint ) = @_; |
118
|
0
|
|
|
|
|
0
|
my @valid_hint_lang; |
119
|
0
|
0
|
0
|
|
|
0
|
if (defined $hint && ref($hint) eq 'ARRAY') { |
120
|
0
|
|
|
|
|
0
|
for (@{ $hint }) { |
|
0
|
|
|
|
|
0
|
|
121
|
0
|
0
|
|
|
|
0
|
push @valid_hint_lang, $_ if (exists $valid_lang{$_}); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
} |
124
|
0
|
0
|
|
|
|
0
|
$self->{_hint_} = (@valid_hint_lang) ? [ @valid_hint_lang ] : undef; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sub detect_lang |
128
|
|
|
|
|
|
|
{ |
129
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
130
|
0
|
0
|
|
|
|
0
|
die "You must set API key\n" if (not defined $self->{ _key_ }); |
131
|
0
|
0
|
|
|
|
0
|
die "You must set Text\n" if (not defined $self->{ _text_ }); |
132
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
0
|
my $query = '/detect?'; |
134
|
0
|
|
|
|
|
0
|
$self->{_post_} = 'key='.$self->{_key_}.'&text='.$self->{_text_}; |
135
|
0
|
0
|
|
|
|
0
|
$self->{_post_} .= '&hint='.join(',', @{ $self->{_hint_} }) if (defined $self->{_hint_}); |
|
0
|
|
|
|
|
0
|
|
136
|
0
|
|
|
|
|
0
|
my $response = $self->{_http_}->get($self->{_base_} . $query . $self->{_post_}); |
137
|
|
|
|
|
|
|
|
138
|
0
|
0
|
|
|
|
0
|
die "Invalid API key\n" if ($response->{status} eq '401'); |
139
|
0
|
0
|
|
|
|
0
|
die "Blocked API key\n" if ($response->{status} eq '402'); |
140
|
0
|
0
|
|
|
|
0
|
die "Exceeded the daily limit on the amount of translated text\n" if ($response->{status} eq '404'); |
141
|
0
|
0
|
|
|
|
0
|
die "Failed to detect the language! (response code $response->{status})\n" unless ($response->{success}); |
142
|
|
|
|
|
|
|
|
143
|
0
|
0
|
0
|
|
|
0
|
if (defined wantarray && length $response->{content}) { |
144
|
0
|
|
|
|
|
0
|
my $json_respond = JSON->new->utf8->decode($response->{content}); |
145
|
0
|
0
|
|
|
|
0
|
return (wantarray) ? ($json_respond->{lang}) : $json_respond->{lang}; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub set_from_lang |
150
|
|
|
|
|
|
|
{ |
151
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $from_lang ) = @_; |
152
|
0
|
0
|
0
|
|
|
0
|
$self->{_from_lang_} = $from_lang if (!defined $from_lang || exists $valid_lang{$from_lang}); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub set_to_lang |
156
|
|
|
|
|
|
|
{ |
157
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $to_lang ) = @_; |
158
|
0
|
0
|
0
|
|
|
0
|
$self->{_to_lang_} = $to_lang if (defined $to_lang && exists $valid_lang{$to_lang}); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub set_format |
162
|
|
|
|
|
|
|
{ |
163
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $format ) = @_; |
164
|
0
|
0
|
0
|
|
|
0
|
$self->{_format_} = $format if (!defined $format || exists $valid_format{$format}); |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub set_options |
168
|
|
|
|
|
|
|
{ |
169
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $options ) = @_; |
170
|
0
|
0
|
0
|
|
|
0
|
$self->{_options_} = $options if (!defined $options || exists $valid_options{$options}); |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub translate |
174
|
|
|
|
|
|
|
{ |
175
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
176
|
0
|
0
|
|
|
|
0
|
die "You must set API key\n" if (not defined $self->{ _key_ }); |
177
|
0
|
0
|
|
|
|
0
|
die "You must set Text\n" if (not defined $self->{ _text_ }); |
178
|
0
|
0
|
|
|
|
0
|
die "You must set source lang\n" if (not defined $self->{ _from_lang_ }); |
179
|
0
|
0
|
|
|
|
0
|
die "You must set destination lang\n" if (not defined $self->{ _to_lang_ }); |
180
|
|
|
|
|
|
|
|
181
|
0
|
|
|
|
|
0
|
my $query = '/translate?'; |
182
|
0
|
0
|
|
|
|
0
|
my $lang = (defined $self->{_from_lang_}) ? $self->{_from_lang_}.'-'.$self->{_to_lang_} : $self->{_to_lang_}; |
183
|
0
|
|
|
|
|
0
|
$self->{_post_} = 'key='.$self->{_key_}.'&text='.$self->{_text_}.'&lang='.$lang; |
184
|
0
|
0
|
|
|
|
0
|
$self->{_post_} .= '&format='.$self->{_format_} if (defined $self->{_format_}); |
185
|
0
|
0
|
|
|
|
0
|
$self->{_post_} .= '&options='.$self->{_options_} if (defined $self->{_options_}); |
186
|
0
|
|
|
|
|
0
|
my $response = $self->{_http_}->get($self->{_base_} . $query . $self->{_post_}); |
187
|
|
|
|
|
|
|
|
188
|
0
|
0
|
|
|
|
0
|
die "Invalid API key\n" if ($response->{status} eq '401'); |
189
|
0
|
0
|
|
|
|
0
|
die "Blocked API key\n" if ($response->{status} eq '402'); |
190
|
0
|
0
|
|
|
|
0
|
die "Exceeded the daily limit on the amount of translated text\n" if ($response->{status} eq '404'); |
191
|
0
|
0
|
|
|
|
0
|
die "Exceeded the maximum text size\n" if ($response->{status} eq '413'); |
192
|
0
|
0
|
|
|
|
0
|
die "The text cannot be translated\n" if ($response->{status} eq '422'); |
193
|
0
|
0
|
|
|
|
0
|
die "The specified translation direction is not supported\n" if ($response->{status} eq '501'); |
194
|
0
|
0
|
|
|
|
0
|
die "Failed to translate text! (response code $response->{status})\n" unless ($response->{success}); |
195
|
|
|
|
|
|
|
|
196
|
0
|
0
|
0
|
|
|
0
|
if (defined wantarray && length $response->{content}) { |
197
|
0
|
|
|
|
|
0
|
my $json_respond = JSON->new->utf8->decode($response->{content}); |
198
|
0
|
0
|
|
|
|
0
|
if (defined $self->{_options_}) { |
199
|
0
|
|
|
|
|
0
|
return ($json_respond->{detected}->{lang}, $json_respond->{text}[0]); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
else { |
202
|
0
|
0
|
|
|
|
0
|
return (wantarray) ? ($json_respond->{text}[0]) : $json_respond->{text}[0]; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# |
208
|
|
|
|
|
|
|
# See §2.7 of Пользовательское соглашение сервиса «API Яндекс.Переводчик» |
209
|
|
|
|
|
|
|
# at https://yandex.ru/legal/translate_api/ |
210
|
|
|
|
|
|
|
# |
211
|
|
|
|
|
|
|
# See §2.7 of Terms of Use of API Yandex.Translate Service |
212
|
|
|
|
|
|
|
# at https://yandex.com/legal/translate_api/ |
213
|
|
|
|
|
|
|
# |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub get_yandex_technology_reference |
216
|
|
|
|
|
|
|
{ |
217
|
3
|
|
|
3
|
1
|
13
|
my ( $self, $attribute ) = @_; |
218
|
3
|
50
|
|
|
|
9
|
if (defined wantarray) { |
219
|
3
|
|
|
|
|
7
|
my %yandex_attribute; |
220
|
3
|
50
|
33
|
|
|
11
|
if (defined $attribute && ref($attribute) eq 'HASH') { |
221
|
0
|
|
|
|
|
0
|
while (my ( $key, $value ) = each %{ $attribute }) { |
|
0
|
|
|
|
|
0
|
|
222
|
0
|
0
|
|
|
|
0
|
$yandex_attribute{$key} = $key.'="'.encode_entities($value).'"' if (lc $key ne 'href'); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# |
227
|
|
|
|
|
|
|
# Sort %yandex_attribute so that the same $yandex_attributes value |
228
|
|
|
|
|
|
|
# will consistently be produced for a given $attribute hash. |
229
|
|
|
|
|
|
|
# |
230
|
3
|
50
|
|
|
|
8
|
my $yandex_attributes = (%yandex_attribute) ? ' '.join(' ', map { $yandex_attribute{$_} } sort { $a cmp $b } keys %yandex_attribute) : ''; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
231
|
|
|
|
|
|
|
|
232
|
3
|
|
|
|
|
11
|
my %yandex_url = ( |
233
|
|
|
|
|
|
|
ru => 'http://translate.yandex.ru/', |
234
|
|
|
|
|
|
|
en => 'http://translate.yandex.com/', |
235
|
|
|
|
|
|
|
tr => 'http://translate.yandex.com.tr/', |
236
|
|
|
|
|
|
|
); |
237
|
3
|
|
|
|
|
8
|
my %yandex_text = ( |
238
|
|
|
|
|
|
|
ru => 'Переведено сервисом Яндекс.Переводчик', |
239
|
|
|
|
|
|
|
en => 'Powered by Yandex.Translate', |
240
|
|
|
|
|
|
|
tr => 'Tarafından desteklenmektedir Yandex.Çeviri', |
241
|
|
|
|
|
|
|
); |
242
|
3
|
50
|
|
|
|
10
|
my $yandex_url = (exists $yandex_url{$self->{_ui_}}) ? $yandex_url{$self->{_ui_}} : $yandex_url{$default_ui}; |
243
|
3
|
50
|
|
|
|
8
|
my $yandex_text = (exists $yandex_text{$self->{_ui_}}) ? $yandex_text{$self->{_ui_}} : $yandex_text{$default_ui}; |
244
|
3
|
|
|
|
|
12
|
my $yandex_element = ''.$yandex_text.''; |
245
|
3
|
50
|
|
|
|
14
|
return (wantarray) ? ($yandex_element) : $yandex_element; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
1; |
250
|
|
|
|
|
|
|
__END__ |