All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ligboy.translate.Translate Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
package org.ligboy.translate;

import okhttp3.Dns;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.ligboy.translate.exception.IllegalTokenKeyException;
import org.ligboy.translate.exception.RetrieveTokenKeyFailedException;
import org.ligboy.translate.exception.TranslateFailedException;
import org.ligboy.translate.model.TokenKey;
import org.ligboy.translate.model.TranslateResult;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

import java.io.IOException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.util.concurrent.TimeUnit;

/**
 * Translate API Wrapper
 * @author ligboy [email protected]
 */
@SuppressWarnings("WeakerAccess")
public class Translate {

    public static final String SOURCE_LANG_AUTO = "auto";

    private static final String DEFAULT_BASE_URL = "https://translate.google.cn";

    TokenGenerator mTokenGenerator;
    private TranslateService mService;

    Translate(Builder builder) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        HttpLoggingInterceptor.Level logLevel;
        switch (builder.logLevel) {
            case BASIC:
                logLevel = HttpLoggingInterceptor.Level.BASIC;
                break;
            case HEADERS:
                logLevel = HttpLoggingInterceptor.Level.HEADERS;
                break;
            case BODY:
                logLevel = HttpLoggingInterceptor.Level.BODY;
                break;
            case NONE:
            default:
                logLevel = HttpLoggingInterceptor.Level.NONE;
                break;
        }
        interceptor.setLevel(logLevel);
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .retryOnConnectionFailure(builder.retryOnConnectionFailure)
                .connectTimeout(builder.connectTimeout, builder.connectTimeoutTimeUnit)
                .writeTimeout(builder.writeTimeout, builder.writeTimeoutTimeUnit)
                .readTimeout(builder.readTimeout, builder.readTimeoutTimeUnit)
                .proxy(builder.proxy);
        if (builder.proxySelector != null) {
            clientBuilder.proxySelector(builder.proxySelector);
        }
        if (builder.dns != null) {
            clientBuilder.dns(builder.dns);
        }
        Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
                .client(clientBuilder.build())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(TranslateConverterFactory.DEFAULT)
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(builder.baseUrl == null ? DEFAULT_BASE_URL : builder.baseUrl);
        mService = retrofitBuilder.build().create(TranslateService.class);
        this.mTokenGenerator = builder.tokenGenerator;
    }

    /**
     * Refresh the token key.
     * @throws RetrieveTokenKeyFailedException If failed throw this Exception.
     */
    public void refreshTokenKey() throws RetrieveTokenKeyFailedException {
        Call tokenKeyCall = mService.getTokenKey();
        Response keyResponse;
        try {
            keyResponse = tokenKeyCall.execute();
        } catch (IOException e) {
            throw new RetrieveTokenKeyFailedException(e);
        }
        TokenKey tokenKey = keyResponse.body();
        if (keyResponse.isSuccessful() && tokenKey != null && tokenKey.getKey() != null) {
            mTokenGenerator = new TokenGenerator(tokenKey.getKey());
        } else {
            throw new RetrieveTokenKeyFailedException("Refresh token key failed.");
        }
    }

    /**
     * Translate text.
     * @param text The text be translated.
     * @param source The source Language. default "auto" - which means auto detecting the source language.
     * @param target The target Language.
     * @return The translated result.
     * @throws TranslateFailedException exception if translation requesting encountered errors.
     * @throws IllegalTokenKeyException exception if there something wrong with the token key.
     */
    @Nullable
    public TranslateResult translate(@NotNull String text, @Nullable String source, @NotNull String target)
                        throws TranslateFailedException, IllegalTokenKeyException {
        if (mTokenGenerator == null || mTokenGenerator.getTokenKey() == null) {
            throw new IllegalTokenKeyException("token key == null");
        }
        if (source == null) {
            source = Translate.SOURCE_LANG_AUTO;
        }
        final Call resultCall = mService.translate(source, target, text, mTokenGenerator.token(text));
        try {
            return resultCall.execute().body();
        } catch (IOException e) {
            throw new TranslateFailedException(e);
        }
    }

    /**
     * Get the {@link TokenGenerator}.
     * @return The TokenGenerator.
     */
    @Nullable
    public TokenGenerator getTokenGenerator() {
        return mTokenGenerator;
    }

    /**
     * Set the {@link TokenGenerator}.
     * @param tokenGenerator The TokenGenerator.
     */
    public void setTokenGenerator(@NotNull TokenGenerator tokenGenerator) {
        this.mTokenGenerator = tokenGenerator;
    }

    /**
     * Build a new {@link Translate}.
     */
    public static final class Builder {

        String baseUrl;
        TokenGenerator tokenGenerator;
        LogLevel logLevel;
        Proxy proxy;
        Dns dns;
        boolean retryOnConnectionFailure;
        long connectTimeout;
        TimeUnit connectTimeoutTimeUnit;
        long readTimeout;
        TimeUnit readTimeoutTimeUnit;
        long writeTimeout;
        TimeUnit writeTimeoutTimeUnit;
        ProxySelector proxySelector;

        public Builder() {
            logLevel = LogLevel.NONE;
            dns = Dns.SYSTEM;
            retryOnConnectionFailure = true;
            connectTimeout = 10_000;
            connectTimeoutTimeUnit = TimeUnit.MILLISECONDS;
            readTimeout = 10_000;
            readTimeoutTimeUnit = TimeUnit.MILLISECONDS;
            writeTimeout = 10_000;
            writeTimeoutTimeUnit = TimeUnit.MILLISECONDS;
        }

        /**
         * Set the API base URL.
         * @param baseUrl The base URL of server.
         * @return This {@link Builder}
         */
        public Builder baseUrl(String baseUrl) {
            this.baseUrl = baseUrl;
            return this;
        }

        /**
         * Set the {@link TokenGenerator}.
         * @param tokenGenerator The TokenGenerator.
         * @return This {@link Builder}
         */
        public Builder tokenGenerator(@NotNull TokenGenerator tokenGenerator) {
            this.tokenGenerator = tokenGenerator;
            return this;
        }

        /**
         * Set the level of logging.
         * 

Default {@link LogLevel#NONE} * @param logLevel The level of logging. * @return This {@link Builder} */ public Builder logLevel(LogLevel logLevel) { this.logLevel = logLevel; return this; } /** * Sets the DNS service used to lookup IP addresses for hostnames. * *

If unset, the {@link Dns#SYSTEM system-wide default} DNS will be used. * @param dns dns * @return This {@link Builder} */ public Builder dns(Dns dns) { if (dns == null) throw new NullPointerException("dns == null"); this.dns = dns; return this; } /** * Set is retry on connection failure. * @param retryOnConnectionFailure retryOnConnectionFailure * @return This {@link Builder} */ public Builder retryOnConnectionFailure(boolean retryOnConnectionFailure) { this.retryOnConnectionFailure = retryOnConnectionFailure; return this; } /** * Sets the default connect timeout for new connections. A value of 0 means no timeout, * otherwise values must be between 1 and {@link Integer#MAX_VALUE} when converted to * milliseconds. * @param timeout The timeout length. * @param unit The time unit. * @return This {@link Builder} */ public Builder connectTimeout(long timeout, TimeUnit unit) { this.connectTimeout = timeout; this.connectTimeoutTimeUnit = unit; return this; } /** * Sets the default read timeout for new connections. A value of 0 means no timeout, otherwise * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds. * @param timeout The timeout length. * @param unit The time unit. * @return This {@link Builder} */ public Builder readTimeout(long timeout, TimeUnit unit) { this.readTimeout = timeout; this.readTimeoutTimeUnit = unit; return this; } /** * Sets the default write timeout for new connections. A value of 0 means no timeout, otherwise * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds. * @param timeout The timeout length. * @param unit The time unit. * @return This {@link Builder} */ public Builder writeTimeout(long timeout, TimeUnit unit) { this.writeTimeout = timeout; this.writeTimeoutTimeUnit = unit; return this; } /** * Sets the HTTP proxy that will be used by connections created by this client. This takes * precedence over {@link #proxySelector}, which is only honored when this proxy is null (which * it is by default). To disable proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}. * @param proxy proxy * @return This {@link Builder} */ public Builder proxy(Proxy proxy) { this.proxy = proxy; return this; } /** * Sets the proxy selection policy to be used if no {@link #proxy proxy} is specified * explicitly. The proxy selector may return multiple proxies; in that case they will be tried * in sequence until a successful connection is established. * *

If unset, the {@link ProxySelector#getDefault() system-wide default} proxy selector will * be used. * @param proxySelector The proxy selection policy. * @return This {@link Builder} */ public Builder proxySelector(ProxySelector proxySelector) { this.proxySelector = proxySelector; return this; } /** * Create the {@link Translate} instance using the configured values. * @return This {@link Builder} */ public Translate build() { return new Translate(this); } } public enum LogLevel { /** No logs. */ NONE, /** * Logs request and response lines. * *

Example: *

{@code
         * --> POST /greeting http/1.1 (3-byte body)
         *
         * <-- 200 OK (22ms, 6-byte body)
         * }
*/ BASIC, /** * Logs request and response lines and their respective headers. * *

Example: *

{@code
         * --> POST /greeting http/1.1
         * Host: example.com
         * Content-Type: plain/text
         * Content-Length: 3
         * --> END POST
         *
         * <-- 200 OK (22ms)
         * Content-Type: plain/text
         * Content-Length: 6
         * <-- END HTTP
         * }
*/ HEADERS, /** * Logs request and response lines and their respective headers and bodies (if present). * *

Example: *

{@code
         * --> POST /greeting http/1.1
         * Host: example.com
         * Content-Type: plain/text
         * Content-Length: 3
         *
         * Hi?
         * --> END GET
         *
         * <-- 200 OK (22ms)
         * Content-Type: plain/text
         * Content-Length: 6
         *
         * Hello!
         * <-- END HTTP
         * }
*/ BODY } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy