[iOS] 翻訳機能付Twitterクライアント

2016.02.12

1 翻訳機能付Twitterクライアント

Twitterの検索は、非常に強力な情報収集元です。私も定期的に「何か面白い情報は無いかな」と、ゆるい感じで検索したりしています。 しかし、検索結果は、日本語で無いものも多く、わからない単語を確かめたりしていると、せっかくの、ゆるい感じが台無しです。

そこで、今回は、スワイプだけで翻訳してくれる、Twitter検索クライアントを作成しました。

実は、以前に同じようなものをXamarinで書いたことがあるのですが、今回は、Objectiv−Cです。

Microsoftの翻訳サービスにObjectiv-Cでアクセスしている例は、多分、本記事しかないと思います。

001

github サンプルコード(http://github.com/furuya02/TranslationTwitterSample)

公開されたコードには、翻訳「Microsoft Translator」の利用キーは含まれていません。 翻訳機能を動作させるためには、アクセスキーをご用意ください。

2 Twitterクライアント

Twitterクライアントは、ACAccountフレームワーク及び、SLRequestフレームワークを利用しています。

001

SLRequestフレームワーク利用することで、FacebookやTwitterへのアクセスが非常に簡単にできます。

また、ACAccountフレームワークでは、あらかじめ端末に設定してあるアカウント情報を引っ張ってきて使用することができます。

002

SLRequestフレームワークを使用して、Twitterの検索をしているコードは次の通りです。

指定されたワードについて、100件の検索をしています。 動作は非同期で、検索完了にデリゲートメソッドdidFinishLoadで、利用者側に完了を伝えるようになっています。

Twitter.m

// 検索のURL
NSURL *url = [NSURL URLWithString:@"https://api.twitter.com/1.1/search/tweets.json"];
NSDictionary *params = @{@"count" : @"100",@"q":word}; // word:検索文字 100件
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                        requestMethod:SLRequestMethodGET
                                                  URL:url
                                           parameters:params];
// アカウントをセット
request.account = _acaccount;

[request performRequestWithHandler:^(NSData *data,
                                     NSHTTPURLResponse *response,
                                     NSError *error) {
     if (data) {
         if (response.statusCode >= 200 && response.statusCode < 300) {

             // JSONデータをデコードして、Tweetクラスの配列に格納する
             NSError *error;
             NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data
                                                                          options:NSJSONReadingAllowFragments
                                                                            error:&error];
             NSArray *tweets = [result objectForKey:@"statuses"];
             for (NSDictionary *t in tweets) {
                 Tweet *tweet = [Tweet alloc];
                 tweet.created_at = [t objectForKey:@"created_at"];
                 tweet.text = [t objectForKey:@"text"];
                 tweet.tweetId = [t objectForKey:@"id"];
                 NSDictionary *user = [t objectForKey:@"user"];
                 tweet.profile_image_url = [user objectForKey:@"profile_image_url"];
                 tweet.name = [user objectForKey:@"name"];
                 tweet.screen_name = [user objectForKey:@"screen_name"];
                 [_tweets addObject:tweet];
             }

             dispatch_async(dispatch_get_main_queue(), ^{
                 [self.delegate didFinishLoad];
             });

         } else {
             NSLog(@"statusCode %ld",(long)response.statusCode);
         }
     }
 }];

また、ACAccountフレームワークで端末に設定されているTwitterのアカウント情報を取得するコードは、次のようになっています。 予め、アカウント情報が登録されていないと、このサンプルは機能しません。

また、アカウント情報は、複数設定可能ですが、単純に最初のものを選択しています。検索の場合、アカウントの権限等は関係ないためです。

Twitter.m

ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountTypeTwitter = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountTypeTwitter
                                      options:nil
                                   completion:^(BOOL granted, NSError *error) {
                                       if (granted) {
                                           NSArray *accountArray = [accountStore accountsWithAccountType:accountTypeTwitter];
                                           if (accountArray.count > 0) {
                                               _acaccount = [accountArray objectAtIndex:0];
                                           }
                                       }
                                   }];


3 翻訳

現時点での翻訳サービスは、googleとMicrosoftの2択のようです。googleの方は有料になってしまったようなので、今回は、Microsoftのサービスを使用しました。

Microsoftのオンライン機械翻訳サービスはエンドユーザー向けに「Bing Translator」という名前で提供されており、そのバックで動作しているのが「Microsoft Translator」のようです。

https://www.microsoft.com/en-us/translator/default.aspx

003

「Microsoft Translator」は、1ヶ月あたり200万文字まで無料で利用可能です。 004

(1) 利用手順

「Microsoft Translator」の利用するための手順は、下記のとおりです。

Live ID 取得

Windows Live IDが必要です。既に取得している場合は、この作業は必要ありません。

サブスクリプション登録

Microsoft Translator データに対して、サブスクリプション登録をします。

https://datamarket.azure.com/browse

006

アプリケーション登録

https://datamarket.azure.com/developer/applications/

007

「顧客の秘密(シークレットキー)」は自由に決定することができるようです。また、クライアントアプリを作成する場合「リダイレクトURL」には、無効なURLを指定します。 ここで設定した、「クライアントID(ClientId)」と「顧客の秘密(ClientSecret)」が、実装時に必要になります。

(2) 翻訳クラスの実装

「Microsoft Translator」には、読み上げや、辞書引きなど、いくつかの機能がありますが、今回は「テキスト翻訳」のみを実装しています。

httpの通信には、AFNetworkingを利用させて頂きました。

実装したコードは、下記のとおりです。ざっくり言ってしまうと、アクセストークを取得して、WebAPIをコールしているだけです。

詳しくは、下記のリンクをご参照ください。

https://msdn.microsoft.com/ja-jp/library/ff512421.aspx

ページの最後の方に、サンプルコードも(C#とPHP)あります。

アクセストークンの取得

Translator.m

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

// アクセストークン取得
NSDictionary* param = @{@"client_id" : clientId,
                        @"client_secret" : clientSecret,
                        @"scope" : @"http://api.microsofttranslator.com",
                        @"grant_type" : @"client_credentials"};
[manager POST:@"https://datamarket.accesscontrol.windows.net/v2/OAuth2-13"
   parameters:param success:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
       token = [responseObject objectForKey:@"access_token"];
   } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
       NSLog(@"Error: %@", error);
   }];

WebAPIコール

Translator.m

- (void)conversion:(NSString*)message {

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    // JSONでパースしない
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    // Authorizationヘッダの追加
    [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",token] forHTTPHeaderField:@"Authorization"];
    // %文字への変換
    NSString* encodeString = [message stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSString *url = [NSString stringWithFormat:@"http://api.microsofttranslator.com/v2/Http.svc/Translate?text=%@&to=ja",encodeString];
    [manager GET:url
      parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
          //NSData から NSString への変換
          NSString* str = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
          // XMLをパース
          NSCharacterSet *spr = [NSCharacterSet characterSetWithCharactersInString:@"<>"];
          NSArray *array = [str componentsSeparatedByCharactersInSet:spr];
          if(array.count == 5){
              [self.delegate didFinishConversion:[array objectAtIndex:2]];
          }else{
              [self.delegate didFinishConversion:@"ERROR"];
          }
      } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
          [self.delegate didFinishConversion:[NSString stringWithFormat:@"ERROR: %@",error]];
      }];
}

どちらのコードも、C#のサンプルコードをObjectiv-Cに書き換えただけです。

4 最後に

今回は、MicrosoftのサービスをiPhoneから利用してみました。 もちろん、料金との兼ね合いもありますが、色々面白そうなサービが一杯ありそうなので、また、使ってみたいと思います。