File Coverage

blib/lib/Lingua/Translate/Bing.pm
Criterion Covered Total %
statement 28 30 93.3
branch n/a
condition n/a
subroutine 10 10 100.0
pod n/a
total 38 40 95.0


line stmt bran cond sub pod time code
1             package Lingua::Translate::Bing;
2              
3 1     1   32318 use 5.010;
  1         4  
  1         45  
4 1     1   7 use strict;
  1         1  
  1         35  
5 1     1   5 use warnings;
  1         7  
  1         38  
6 1     1   1092 use utf8;
  1         13  
  1         5  
7 1     1   37 use Carp;
  1         2  
  1         81  
8              
9 1     1   4803 use LWP::UserAgent;
  1         123237  
  1         34  
10 1     1   1064 use LWP::Protocol::https;
  1         166490  
  1         57  
11 1     1   1348 use JSON::XS;
  1         28975  
  1         102  
12 1     1   1147 use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
  1         2453  
  1         8  
13 1     1   1037 use SOAP::Lite; #+trace => 'debug';
  0            
  0            
14              
15             =head1 NAME
16              
17             Lingua::Translate::Bing - Class for accessing the functions of translation, provided by the "Bing Translation Api".
18              
19             =head1 VERSION
20              
21             Version 0.04
22              
23             =cut
24              
25             our $VERSION = '0.04';
26              
27              
28             =head1 SYNOPSIS
29              
30             use Lingua::Translate::Bing;
31              
32             my $translator = Lingua::Translate::Bing->new(client_id => "1111111", client_secret => "111111");
33              
34             print $translator->translate("Hello", "ru");
35             ...
36              
37              
38             =cut
39              
40              
41             =head1 CONSTRUCTORS
42              
43             =head2 new(%args)
44              
45             %args contains:
46              
47             =over 1
48              
49             =item client_id
50              
51             =item client_secret
52              
53             =back
54              
55             that you will must get in L.
56              
57             B
58             Microsoft offers free access to Bing Translator for no more than 2,000,000 characters/month.
59              
60             =cut
61              
62             sub new {
63             my ($class, %args) = @_;
64              
65             my $self = {
66             client_id => $args{'client_id'},
67             client_secret => $args{'client_secret'},
68             token_time => undef,
69             token_update_period => 600,
70             token => undef,
71             };
72             bless $self, $class;
73             return $self;
74             }
75              
76             =head2 getLanguagesForTranslate()
77              
78             Return array of supported languages.
79              
80             =cut
81              
82             sub getLanguagesForTranslate {
83             my ($self) = @_;
84             my $answer = $self->_sendRequest("GetLanguagesForTranslate", "appId" => "");
85             return $answer->{string};
86             }
87              
88             =head2 detect($text)
89              
90             Return text input language code.
91              
92             =over 1
93              
94             =item $text
95              
96             Undetected text.
97              
98             =back
99              
100             =cut
101              
102             sub detect {
103             my ($self, $text) = @_;
104             my $answer = $self->_sendRequest("Detect", "text" => $text);
105             return $answer;
106             }
107              
108             =head2 translate($text, $to, $from)
109              
110             Return translation of input text.
111              
112             =over 1
113              
114             =item $text
115              
116             Text for translation.
117              
118             =item $to
119              
120             Target language code.
121              
122             =item $from
123              
124             Language code of input text. Not requeried, but may by mistakes if don't set this argument. It will may be occure because detect method don't define correct language always.
125              
126             =back
127              
128             =cut
129              
130             sub translate {
131             my ($self, $text, $to, $from) = @_;
132             my $answer = $self->_sendRequest("Translate", "text" => $text, "from" => $from, "to" => $to, "contentType" =>
133             "text/plain");
134             return $answer;
135             }
136              
137             sub _setUpdateTokenPeriod {
138             my ($self, $period) = @_;
139             $self->{token_update_period} = $period;
140             return;
141             }
142              
143             sub _initAccessToken {
144             my ($self) = @_;
145             my $result;
146             my $browser = LWP::UserAgent->new();
147              
148             my $url = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
149             my $scope = "http://api.microsofttranslator.com";
150             my $grant_type = "client_credentials";
151              
152             my $response = $browser->post( $url,
153             [
154             'grant_type' => $grant_type,
155             'scope' => $scope,
156             'client_id' => $self->{client_id},
157             'client_secret' => $self->{client_secret}
158             ],
159             );
160             if ($response) {
161             my $content = $response->content;
162             my $json_xs = JSON::XS->new();
163             $result = $json_xs->decode($content)->{'access_token'};
164             }
165             unless (defined($result)) {
166             croak "Failed init access token";
167             }
168              
169             if ($result) {
170             $self->{token_time} = clock_gettime(CLOCK_MONOTONIC);
171             $result = "Bearer " . $result;
172             $self->{token} = $result;
173             }
174             return $result;
175             }
176              
177             sub _getAccessToken {
178             my ($self) = @_;
179            
180             if (!$self->{token} || (clock_gettime(CLOCK_MONOTONIC) - $self->{token_time} > $self->{token_update_period})) {
181             $self->_initAccessToken();
182             }
183             return $self->{token};
184             }
185              
186             sub _sendRequest {
187             my ($self, $function, %args) = @_;
188              
189             my $token = $self->_getAccessToken();
190             my $soap = SOAP::Lite->proxy('http://api.microsofttranslator.com/V2/Soap.svc')
191             ->on_action(sub {return
192             "\"http://api.microsofttranslator.com/V2/LanguageService/$function\""})
193             ->readable(1)
194             ->encodingStyle("")
195             ->encoding(undef)
196             ->default_ns(undef);
197              
198             $soap->transport->http_request->header("Authorization" => $token);
199             my $method = SOAP::Data->name($function)->attr({xmlns => 'http://api.microsofttranslator.com/V2'});
200             my @all_arguments = qw /appId locale languageCodes text from to contentType category/;
201             my @params;
202             foreach (@all_arguments) {
203             my ($key, $value) = ($_, $args{$_});
204             if (defined $value) {
205             my $argument = SOAP::Data->name($key)->uri(undef)->value($value)->type("");
206             push @params, $argument;
207             }
208             }
209             my $answer = $soap->call($method => @params);
210             return $answer->result;
211             }
212              
213             1;
214              
215             =head1 AUTHOR
216              
217             Milovidov Mikhail, C<< >>
218              
219             =head1 BUGS
220              
221             Please report any bugs or feature requests to C, or through
222             the web interface at L. I will be notified, and then you'll
223             automatically be notified of progress on your bug as I make changes.
224              
225              
226              
227              
228             =head1 SUPPORT
229              
230             You can find documentation for this module with the perldoc command.
231              
232             perldoc Lingua::Translate::Bing
233              
234              
235             You can also look for information at:
236              
237             =over 4
238              
239             =item * RT: CPAN's request tracker (report bugs here)
240              
241             L
242              
243             =item * AnnoCPAN: Annotated CPAN documentation
244              
245             L
246              
247             =item * CPAN Ratings
248              
249             L
250              
251             =item * Search CPAN
252              
253             L
254              
255             =back
256              
257             =head1 LICENSE AND COPYRIGHT
258              
259             Copyright 2012 Milovidov Mikhail.
260              
261             This program is free software; you can redistribute it and/or modify it
262             under the terms of either: the GNU General Public License as published
263             by the Free Software Foundation; or the Artistic License.
264              
265             See http://dev.perl.org/licenses/ for more information.
266              
267              
268             =cut
269              
270             1; # End of Lingua::Translate::Bing