Skip to content

Instantly share code, notes, and snippets.

@conradev
Last active February 6, 2016 15:51
Show Gist options
  • Save conradev/8436d3f316d5caed35b4 to your computer and use it in GitHub Desktop.
Save conradev/8436d3f316d5caed35b4 to your computer and use it in GitHub Desktop.
WFGoogleTranslateSessionManager
//
// WFGoogleTranslateSessionManager.h
//
// Created by Conrad Kramer on 2/9/15.
// Copyright (c) 2015 DeskConnect. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface WFGoogleTranslateSessionManager : NSObject
@property (nonatomic, readonly, strong) NSURLSession *session;
@property (nonatomic, copy, nullable) NSString *apiKey;
@property (nonatomic, copy, nullable) NSString *referer;
- (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
- (void)getAvailableLanguages:(void (^)(NSArray * __nullable languages, NSError * __nullable error))completion;
- (void)translateStrings:(NSArray<NSString *> *)strings fromLanguage:(nullable NSString *)from intoLanguage:(NSString *)to completion:(void (^)(NSArray<NSString *> * __nullable strings, NSError * __nullable error))completion;
- (void)detectLanguagesOfStrings:(NSArray<NSString *> *)strings completion:(void (^)(NSArray<NSString *> * __nullable languages, NSError * __nullable error))completion;
@end
extern NSString * const WFGoogleTranslateErrorDomain;
NS_ASSUME_NONNULL_END
//
// WFGoogleTranslateSessionManager.m
//
// Created by Conrad Kramer on 2/9/15.
// Copyright (c) 2015 DeskConnect. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "WFGoogleTranslateSessionManager.h"
NS_ASSUME_NONNULL_BEGIN
@interface WFGoogleTranslateSessionManager ()
@property (nonatomic, readonly, copy) NSURL *baseURL;
@end
NSString * const WFGoogleTranslateErrorDomain = @"WFGoogleTranslateErrorDomain";
static NSString * const WFGoogleTranslateBaseURLString = @"https://www.googleapis.com/language/translate/v2";
@implementation WFGoogleTranslateSessionManager
- (instancetype)init {
return [self initWithSessionConfiguration:nil];
}
- (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self)
return nil;
_session = [NSURLSession sessionWithConfiguration:(configuration ?: [NSURLSessionConfiguration defaultSessionConfiguration])];
_baseURL = [NSURL URLWithString:WFGoogleTranslateBaseURLString];
return self;
}
- (void)getAvailableLanguages:(void (^)(NSArray * __nullable languages, NSError * __nullable error))completion {
NSURL *url = [self.baseURL URLByAppendingPathComponent:@"languages"];
[self sendRequestWithURL:url withParameters:nil completion:^(NSDictionary *response, NSError *error) {
completion([response valueForKeyPath:@"data.languages.language"], error);
}];
}
- (void)detectLanguagesOfStrings:(NSArray<NSString *> *)strings completion:(void (^)(NSArray<NSString *> * __nullable languages, NSError * __nullable error))completion {
NSMutableArray<NSURLQueryItem *> *parameters = [NSMutableArray new];
for (NSString *string in strings)
[parameters addObject:[NSURLQueryItem queryItemWithName:@"q" value:string]];
NSURL *url = [self.baseURL URLByAppendingPathComponent:@"detect"];
[self sendRequestWithURL:url withParameters:parameters completion:^(NSDictionary *response, NSError *error) {
NSMutableArray *languages = [NSMutableArray new];
for (NSArray *possibilities in [response valueForKeyPath:@"data.detections.language"])
[languages addObject:possibilities.firstObject];
completion(languages, error);
}];
}
- (void)translateStrings:(NSArray<NSString *> *)strings fromLanguage:(nullable NSString *)from intoLanguage:(NSString *)to completion:(void (^)(NSArray<NSString *> * __nullable strings, NSError * __nullable error))completion {
if (!strings.count)
return completion(@[], nil);
NSMutableArray<NSURLQueryItem *> *parameters = [NSMutableArray new];
if (from)
[parameters addObject:[NSURLQueryItem queryItemWithName:@"source" value:from]];
[parameters addObject:[NSURLQueryItem queryItemWithName:@"target" value:to]];
for (NSString *string in strings)
[parameters addObject:[NSURLQueryItem queryItemWithName:@"q" value:string]];
[self sendRequestWithURL:self.baseURL withParameters:parameters completion:^(NSDictionary *response, NSError *error) {
NSArray<NSString *> *responseStrings = [response valueForKeyPath:@"data.translations.translatedText"];
if (!responseStrings.count)
return completion(nil, error);
// Decode HTML entities
dispatch_async(dispatch_get_main_queue(), ^{
NSError *innerError = error;
NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)};
NSMutableArray *cleanedStrings = [NSMutableArray new];
for (NSString *string in responseStrings) {
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:&innerError];
[cleanedStrings addObject:(attributedString.string ?: string)];
}
completion([cleanedStrings copy], innerError);
});
}];
}
- (void)sendRequestWithURL:(NSURL *)url withParameters:(nullable NSArray<NSURLQueryItem *> *)parameters completion:(void (^)(NSDictionary * __nullable response, NSError * __nullable error))completion {
NSMutableArray *queryItems = [NSMutableArray arrayWithArray:parameters];
if (self.apiKey)
[queryItems insertObject:[NSURLQueryItem queryItemWithName:@"key" value:self.apiKey] atIndex:0];
NSData *body = ({
NSURLComponents *components = [NSURLComponents new];
components.queryItems = queryItems;
[components.percentEncodedQuery dataUsingEncoding:NSUTF8StringEncoding];
});
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"GET" forHTTPHeaderField:@"X-HTTP-Method-Override"];
[request setValue:self.referer forHTTPHeaderField:@"Referer"];
[request setHTTPBody:body];
[[self.session dataTaskWithRequest:request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
if (!data.length)
return completion(nil, error);
NSDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSDictionary *errorObject = responseObject[@"error"];
if (errorObject) {
NSMutableDictionary *userInfo = [NSMutableDictionary new];
[userInfo setValue:errorObject[@"message"] forKey:NSLocalizedDescriptionKey];
NSInteger code = [errorObject[@"code"] integerValue];
error = [NSError errorWithDomain:WFGoogleTranslateErrorDomain code:code userInfo:userInfo];
}
completion(responseObject, error);
}] resume];
}
@end
NS_ASSUME_NONNULL_END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment