Implementing google translation api in swift 3 iOS
Asked Answered
R

2

5

Hi i am new to iOS development and i am trying to implement google translation API within my app. I found some sample code online from GitHub https://github.com/prine/ROGoogleTranslate. I downloaded the sample code and followed the instructions provided by obtaining an api key from google cloud translate and placing it within the code however the code is not working, iv looked at the comments on the GitHub site and found that it has worked for other developers. I really don't know what i am doing wrong in the code.

ROGoogleTranslateParams.swift

import Foundation

public struct ROGoogleTranslateParams {

    public init() {

    }

    public init(source:String, target:String, text:String) {
        self.source = source
        self.target = target
        self.text = text
    }

    public var source = "de"
    public var target = "en"
    public var text = "Hallo"
}


/// Offers easier access to the Google Translate API
open class ROGoogleTranslate {

    /// Store here the Google Translate API Key
    public var apiKey = "YOUR_API_KEY"

    ///
    /// Initial constructor
    ///
    public init() {

    }

    ///
    /// Translate a phrase from one language into another
    ///
    /// - parameter params:   ROGoogleTranslate Struct contains all the needed parameters to translate with the Google Translate API
    /// - parameter callback: The translated string will be returned in the callback
    ///
    open func translate(params:ROGoogleTranslateParams, callback:@escaping (_ translatedText:String) -> ()) {

        guard apiKey != "" else {
            print("Warning: You should set the api key before calling the translate method.")
            return
        }

        if let urlEncodedText = params.text.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) {
            if let url = URL(string: "https://translation.googleapis.com/language/translate/v2?key=\(self.apiKey)&q=\(urlEncodedText)&source=\(params.source)&target=\(params.target)&format=text") {

                let httprequest = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
                    guard error == nil else {
                        print("Something went wrong: \(error?.localizedDescription)")
                        return
                    }

                    if let httpResponse = response as? HTTPURLResponse {

                        guard httpResponse.statusCode == 200 else {

                            if let data = data {
                                print("Response [\(httpResponse.statusCode)] - \(data)")
                            }

                            return
                        }

                        do {
                            // Pyramid of optional json retrieving. I know with SwiftyJSON it would be easier, but I didn't want to add an external library
                            if let data = data {
                                if let json = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
                                    if let jsonData = json["data"] as? [String : Any] {
                                        if let translations = jsonData["translations"] as? [NSDictionary] {
                                            if let translation = translations.first as? [String : Any] {
                                                if let translatedText = translation["translatedText"] as? String {
                                                    callback(translatedText)
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } catch {
                            print("Serialization failed: \(error.localizedDescription)")
                        }
                    }
                })

                httprequest.resume()
            }
        }
    }
}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet var text:UITextField!
    @IBOutlet var fromLanguage:UITextField!
    @IBOutlet var toLanguage:UITextField!
    @IBOutlet var translation:UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func translate(_ sender: UIButton) {



        let translator = ROGoogleTranslate()
        translator.apiKey = "YOUR_API_KEY" // Add your API Key here

        var params = ROGoogleTranslateParams()
        params.source = fromLanguage.text ?? "de"
        params.target = toLanguage.text ?? "en"
        params.text = text.text ?? "Hallo"

        translator.translate(params: params) { (result) in
            DispatchQueue.main.async {
                self.translation.text = "\(result)"
            }
        }
    }
}

These are classes are used. The result i get when i press the 'translate' button is the following: Response [403] - 355 bytes

your help is appreciated. The code is available to download from the url provided Thank you

Rationalize answered 24/2, 2017 at 22:38 Comment(2)
Don't post your API keys!Brenner
Is there any other reason for a 403 error? My credentials appear to be ok, and I've entered my bank information.Charmaincharmaine
H
6

I'm the author of the library you mentioned above :). I guess you get the 403 because your Google Api Account is not yet activated correctly. Google has changed the policy of the Translation api and its not free anymore. So you problably didn't add the credit card informations in the Api account and therefor get the 403 error?

Heiduc answered 27/2, 2017 at 14:7 Comment(2)
Do you have library for Objective-c as well?Chessa
@Rationalize please don't forget to accept the answer (green tick it) if it resolved your problem.Baumann
E
1

Try this "POST" method function not the 'Get' method as you implemented -

open func translateTest(params: GoogleAITranslateParams, targetLanguage: String, callback:@escaping (_ translatedText:String) -> ()) {

    guard apiKey != "" else {
        return
    }

    var request = URLRequest(url: URL(string: "https://translation.googleapis.com/language/translate/v2?key=\(self.apiKey)")!)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue(Bundle.main.bundleIdentifier ?? "", forHTTPHeaderField: "X-Ios-Bundle-Identifier")

        let jsonRequest = [
            "q": params.text,
            "source": "en",
            "target": targetLanguage,
            "format": "text"
            ] as [String : Any]

        if let jsonData = try? JSONSerialization.data(withJSONObject: jsonRequest, options: .prettyPrinted) {
            request.httpBody = jsonData
            let task: URLSessionDataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
                guard error == nil else {
                    print("Something went wrong: \(String(describing: error?.localizedDescription))")
                    return
                }

                if let httpResponse = response as? HTTPURLResponse {

                    guard httpResponse.statusCode == 200 else {
                        if let data = data {
                            print("Response [\(httpResponse.statusCode)] - \(data)")
                        }
                        return
                    }

                    do {
                        if let data = data {
                            if let json = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
                                if let jsonData = json["data"] as? [String : Any] {
                                    if let translations = jsonData["translations"] as? [NSDictionary] {
                                        if let translation = translations.first as? [String : Any] {
                                            if let translatedText = translation["translatedText"] as? String {
                                                callback(translatedText)
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } catch {
                        print("Serialization failed: \(error.localizedDescription)")
                    }
                }
            }

            task.resume()
        }
}
Ethbinium answered 19/4, 2018 at 7:5 Comment(6)
Please have a look at the other answer.Fermentation
@L.Guthardt i have already checked the other answers and also the question. I have also faced this problem and got a solution by changing the API call structure.Ethbinium
But the purpose of an answer is not to solve just a problem. but only OP's problem. And the issue has been solved, because Prine explained the cause of the issue: Account is not yet activated correctly [...] add the credit card informations in the Api account. So the issue what this question is about has been solved.Fermentation
"Account is not yet activated correctly" is not the real reason for the issue!Ethbinium
Account is not yet activated correctly is just the result of didn't add the credit card informations in the Api account. And the account not being activated correctly results in the 403 error. This is for sure since Prine is the author of the lib, he is the one who knows ths stuff behind.Fermentation
@RahulSinghaRoy 1+ .. It's working for me thank you , need to implement post method.Railing

© 2022 - 2024 — McMap. All rights reserved.