/* * This file is part of the Illarion project. * * Copyright © 2015 - Illarion e.V. * * Illarion is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Illarion is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ package illarion.client.util.translation.yandex; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; import com.google.gson.stream.JsonReader; import illarion.client.util.translation.TranslationDirection; import illarion.client.util.translation.TranslationProvider; import org.jetbrains.annotations.Contract; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * This is the translation provider that utilizes Yandex for the translation. * * @author Martin Karing <nitram@illarion.org> */ public class YandexProvider implements TranslationProvider { @Nonnull private static final Logger log = LoggerFactory.getLogger(YandexProvider.class); @Nullable private final URL serviceUrl; @Nonnull private final String userAgent; private boolean operational; public YandexProvider() { URL url = null; try { url = new URL("https://translate.yandex.net/api/v1/tr.json/translate"); } catch (MalformedURLException e) { log.error("Failed to resolve the URL to the translator service. Service is not active.", e); } serviceUrl = url; userAgent = readUserAgent(); operational = false; } /** * Fetch the user agent that is used to request data from the service. * * @return the user agent that is supposed to be used */ @Nonnull private static String readUserAgent() { String selectedUserAgent = null; URL resource = Thread.currentThread().getContextClassLoader().getResource("user-agents.txt"); if (resource != null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream(), "UTF-8"))) { List<String> agents = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { agents.add(line); } Random rand = new Random(); selectedUserAgent = agents.get(rand.nextInt(agents.size())); } catch (UnsupportedEncodingException e) { log.error("Encoding required to read the user agents file is not supported.", e); } catch (IOException e) { log.error("Failed to read the user agents file.", e); } } return (selectedUserAgent == null) ? "Mozilla/5.0" : selectedUserAgent; } @Nullable @Override public String getTranslation(@Nonnull String original, @Nonnull TranslationDirection direction) { if (!isProviderWorking()) { return null; } StringBuilder queryBuilder = new StringBuilder(); queryBuilder.append(serviceUrl).append('?'); try { queryBuilder.append("text=").append(URLEncoder.encode(original, "UTF-8")); queryBuilder.append('&').append("lang=").append(getLang(direction)); queryBuilder.append("&srv=tr-text"); URL queryUrl = new URL(queryBuilder.toString()); URLConnection connection = queryUrl.openConnection(); connection.addRequestProperty("User-Agent", userAgent); try (JsonReader rd = new JsonReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8")))) { Gson gson = new GsonBuilder() .setDateFormat("yyyy-MM-dd HH:mm:ss") .create(); Response response = gson.fromJson(rd, Response.class); if (response != null) { List<String> result = response.getTexts(); if (result.size() == 1) { return result.get(0); } else if (result.size() > 1) { StringBuilder resultBuilder = new StringBuilder(); for (String text : result) { resultBuilder.append(text).append(' '); } return resultBuilder.toString().trim(); } } } catch (IOException e) { log.error("Error while reading from the service.", e); } catch (JsonParseException e) { log.error("Unexpected error while decoding json", e); } } catch (UnsupportedEncodingException e) { log.error("Error while encoding the text for transfer to the Yandex provider.", e); } catch (MalformedURLException e) { log.error("Generated URL for the query to Yandex appears to have a invalid format.", e); } catch (IOException e) { log.error("Failed to open connection for Yandex provider.", e); } // The provider is not working anymore. That either happens because the provider is unreachable or because // the provider is not accepting any more requests. Either way to reduce overhead the provider may shut down for // this session to reduce the overhead. operational = false; return null; } @Nonnull @Contract(pure = true) private static String getLang(@Nonnull TranslationDirection direction) { switch (direction) { case GermanToEnglish: return "de-en"; case EnglishToGerman: return "en-de"; } throw new UnsupportedOperationException("Unexpected translation direction received."); } @Override public boolean isProviderWorking() { return (serviceUrl != null) && operational; } }