diff --git a/htroot/ConfigBasic.html b/htroot/ConfigBasic.html index daef4777a..20b7e0832 100644 --- a/htroot/ConfigBasic.html +++ b/htroot/ConfigBasic.html @@ -33,14 +33,15 @@
  • ok Select a language for the interface:
    - -   -   - - - - - +   +   +   +   + + + + +
  • diff --git a/htroot/ConfigBasic.java b/htroot/ConfigBasic.java index 378ee2e07..cc382fe23 100644 --- a/htroot/ConfigBasic.java +++ b/htroot/ConfigBasic.java @@ -31,11 +31,13 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.List; import java.util.regex.Pattern; import net.yacy.cora.protocol.Domains; import net.yacy.cora.protocol.HeaderFramework; import net.yacy.cora.protocol.RequestHeader; +import net.yacy.data.Translator; import net.yacy.data.WorkTables; import net.yacy.http.YaCyHttpServer; import net.yacy.kelondro.workflow.InstantBusyThread; @@ -63,7 +65,7 @@ public class ConfigBasic { final Switchboard sb = (Switchboard) env; final serverObjects prop = new serverObjects(); final File langPath = new File(sb.getAppPath("locale.source", "locales").getAbsolutePath()); - String lang = env.getConfig("locale.language", "default"); + String lang = env.getConfig("locale.language", "browser"); final int authentication = sb.adminAuthenticated(header); if (authentication < 2) { @@ -269,6 +271,7 @@ public class ConfigBasic { prop.put("defaultPort", env.getLocalPort()); prop.put("withsslenabled", env.getConfigBool("server.https", false) ? 1 : 0); lang = env.getConfig("locale.language", "default"); // re-assign lang, may have changed + prop.put("lang_browser", "0"); // for client browser language dependent prop.put("lang_de", "0"); prop.put("lang_fr", "0"); prop.put("lang_cn", "0"); @@ -281,6 +284,28 @@ public class ConfigBasic { } else { prop.put("lang_" + lang, "1"); } + // set label class (green background) for active translation + if (lang.equals("browser")) { + List l = Translator.activeTranslations(); + prop.put("active_cn", l.contains("cn") ? "label-success" : ""); + prop.put("active_de", l.contains("de") ? "label-success" : ""); + prop.put("active_fr", l.contains("fr") ? "label-success" : ""); + prop.put("active_hi", l.contains("hi") ? "label-success" : ""); + prop.put("active_jp", l.contains("jp") ? "label-success" : ""); + prop.put("active_ru", l.contains("ru") ? "label-success" : ""); + prop.put("active_uk", l.contains("uk") ? "label-success" : ""); + prop.put("active_en", "label-success"); + + } else { + prop.put("active_de", ""); + prop.put("active_fr", ""); + prop.put("active_hi", ""); + prop.put("active_cn", ""); + prop.put("active_ru", ""); + prop.put("active_uk", ""); + prop.put("active_en", ""); + prop.put("active_jp", ""); + } return prop; } } diff --git a/htroot/ConfigLanguage_p.java b/htroot/ConfigLanguage_p.java index eff442e69..bd08db5c6 100644 --- a/htroot/ConfigLanguage_p.java +++ b/htroot/ConfigLanguage_p.java @@ -81,7 +81,7 @@ public class ConfigLanguage_p { * read from the language directory. This is very important to prevent * directory traversal attacks! */ - if (langFiles.contains(selectedLanguage) || selectedLanguage.startsWith("default")) { + if (langFiles.contains(selectedLanguage) || selectedLanguage.startsWith("default") || selectedLanguage.startsWith("browser")) { new TranslatorXliff().changeLang(env, langPath, selectedLanguage); } @@ -142,27 +142,28 @@ public class ConfigLanguage_p { final Map langNames = Translator.langMap(env); //virtual entry - prop.put("langlist_0_file", "default"); - prop.put("langlist_0_name", ((langNames.get("default") == null) ? "default" : langNames.get("default"))); + prop.put("langlist_0_file", "browser"); + prop.put("langlist_0_name", ((langNames.get("browser") == null) ? "browser" : langNames.get("browser"))); prop.put("langlist_0_selected", "selected=\"selected\""); + prop.put("langlist_1_file", "default"); + prop.put("langlist_1_name", ((langNames.get("default") == null) ? "default" : langNames.get("default"))); - int count = 0; - for (final String langFile : langFiles) { - //+1 because of the virtual entry "default" at top + int count = 2; //+2 because of the virtual entry "browser" and "default" at top + for (final String langFile : langFiles) { final String langKey = langFile.substring(0, langFile.length() -4); final String langName = langNames.get(langKey); - prop.put("langlist_" + (count + 1) + "_file", langFile); - prop.put("langlist_" + (count + 1) + "_name", ((langName == null) ? langKey : langName)); + prop.put("langlist_" + (count) + "_file", langFile); + prop.put("langlist_" + (count) + "_name", ((langName == null) ? langKey : langName)); if(env.getConfig("locale.language", "default").equals(langKey)) { - prop.put("langlist_" + (count + 1) + "_selected", "selected=\"selected\""); + prop.put("langlist_" + (count) + "_selected", "selected=\"selected\""); prop.put("langlist_0_selected", " "); // reset Default } else { - prop.put("langlist_" + (count + 1) + "_selected", " "); + prop.put("langlist_" + (count) + "_selected", " "); } count++; } - prop.put("langlist", (count + 1)); + prop.put("langlist", (count)); //is done by Translationtemplate //langName = (String) langNames.get(env.getConfig("locale.language", "default")); diff --git a/source/net/yacy/data/Translator.java b/source/net/yacy/data/Translator.java index ac14a0f7e..1aa63e57f 100644 --- a/source/net/yacy/data/Translator.java +++ b/source/net/yacy/data/Translator.java @@ -40,6 +40,7 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -53,6 +54,7 @@ import net.yacy.document.SentenceReader; import net.yacy.kelondro.util.FileUtils; import net.yacy.kelondro.util.Formatter; import net.yacy.peers.Seed; +import net.yacy.search.Switchboard; import net.yacy.search.SwitchboardConstants; import net.yacy.server.serverSwitch; import net.yacy.utils.translation.ExtensionsFileFilter; @@ -274,6 +276,7 @@ public class Translator { public static Map langMap(@SuppressWarnings("unused") final serverSwitch env) { final String[] ms = CommonPattern.COMMA.split( + "browser/Browser Language," + "default/English,de/Deutsch,fr/Français,nl/Nederlands,it/Italiano,es/Español,pt/Portugês,fi/Suomi,se/Svenska,dk/Dansk," + "gr/Eλληvικα,sk/Slovensky,cn/汉语/漢語," + "ru/Русский,uk/Українська," + @@ -294,6 +297,9 @@ public class Translator { if ("default".equals(lang) || "default.lng".equals(lang)) { env.setConfig("locale.language", "default"); ret = true; + } else if ("browser".equals(lang) || "browser.lng".equals(lang)) { + env.setConfig("locale.language", "browser"); + ret = true; } else { final String htRootPath = env.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT); final File sourceDir = new File(env.getAppPath(), htRootPath); @@ -319,4 +325,24 @@ public class Translator { public static List langFiles(File langPath) { return FileUtils.getDirListing(langPath, Translator.LANG_FILENAME_FILTER); } + + /** + * Helper to collect a list of available translations + * This looks in the locale directory for the subdirectories created on translation + * @return list of language-codes of available/active translations + */ + public static List activeTranslations() { + Switchboard sb = Switchboard.getSwitchboard(); + File localePath; + if (sb != null) + localePath = sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"); + else + localePath = new File ("DATA/LOCALE/htroot"); + List dirlist = new ArrayList(); // get list of language subdirectories + File[] list = localePath.listFiles(); + for (File f : list) { + if (f.isDirectory()) dirlist.add(f.getName()); // filter directories to add to result + } + return dirlist; + } } diff --git a/source/net/yacy/http/servlets/YaCyDefaultServlet.java b/source/net/yacy/http/servlets/YaCyDefaultServlet.java index 22a06538c..99f592b5f 100644 --- a/source/net/yacy/http/servlets/YaCyDefaultServlet.java +++ b/source/net/yacy/http/servlets/YaCyDefaultServlet.java @@ -811,7 +811,15 @@ public class YaCyDefaultServlet extends HttpServlet { protected void handleTemplate(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { Switchboard sb = Switchboard.getSwitchboard(); - String localeSelection = sb.getConfig("locale.language", "default"); + String localeSelection = sb.getConfig("locale.language", "browser"); + if (localeSelection.endsWith("browser")) { + String lng = request.getLocale().getLanguage(); + if (lng.equalsIgnoreCase("en")) { // because en is handled as "default" in localizer + localeSelection = "default"; + } else { + localeSelection = lng; + } + } File targetFile = getLocalizedFile(target, localeSelection); File targetClass = rewriteClassFile(_resourceBase.addPath(target).getFile()); String targetExt = target.substring(target.lastIndexOf('.') + 1); @@ -994,6 +1002,7 @@ public class YaCyDefaultServlet extends HttpServlet { templatePatterns.put("navigation-advanced_authorized", authorized ? 1 : 0); templatePatterns.put(SwitchboardConstants.GREETING_HOMEPAGE, sb.getConfig(SwitchboardConstants.GREETING_HOMEPAGE, "")); templatePatterns.put(SwitchboardConstants.GREETING_SMALL_IMAGE, sb.getConfig(SwitchboardConstants.GREETING_SMALL_IMAGE, "")); + templatePatterns.put("clientlanguage", localeSelection); String mimeType = Classification.ext2mime(targetExt, MimeTypes.Type.TEXT_HTML.asString()); diff --git a/source/net/yacy/server/http/TemplateEngine.java b/source/net/yacy/server/http/TemplateEngine.java index 5158772b2..863455fb8 100644 --- a/source/net/yacy/server/http/TemplateEngine.java +++ b/source/net/yacy/server/http/TemplateEngine.java @@ -213,6 +213,7 @@ public final class TemplateEngine { byte[] replacement; int bb; final ByteBuffer structure = new ByteBuffer(); + final String clientbrowserlang = pattern.get("clientlanguage"); // preferred language or null (used for include files) while (transferUntil(pis, out, hashChar)) { bb = pis.read(); keyStream.reset(); @@ -416,7 +417,7 @@ public final class TemplateEngine { BufferedReader br = null; try{ //br = new BufferedReader(new InputStreamReader(new FileInputStream( filename ))); //Simple Include - br = new BufferedReader( new InputStreamReader(new FileInputStream( HTTPDFileHandler.getLocalizedFile(UTF8.String(filename))), StandardCharsets.UTF_8) ); //YaCy (with Locales) + br = new BufferedReader( new InputStreamReader(new FileInputStream( HTTPDFileHandler.getLocalizedFile(UTF8.String(filename), clientbrowserlang)), StandardCharsets.UTF_8) ); //YaCy (with Locales) //Read the Include String line = ""; while ((line = br.readLine()) != null) { diff --git a/source/net/yacy/yacy.java b/source/net/yacy/yacy.java index 4dcbb98f3..db7bbce51 100644 --- a/source/net/yacy/yacy.java +++ b/source/net/yacy/yacy.java @@ -37,6 +37,8 @@ import java.io.PrintWriter; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import java.util.concurrent.Semaphore; @@ -54,6 +56,7 @@ import net.yacy.cora.protocol.http.HTTPClient; import net.yacy.cora.sorting.Array; import net.yacy.cora.util.ConcurrentLog; import net.yacy.crawler.retrieval.Response; +import net.yacy.data.Translator; import net.yacy.document.Document; import net.yacy.gui.YaCyApp; import net.yacy.gui.framework.Browser; @@ -337,29 +340,43 @@ public final class yacy { //regenerate Locales from Translationlist, if needed final File locale_source = sb.getAppPath("locale.source", "locales"); final String lang = sb.getConfig("locale.language", ""); - if (!lang.equals("") && !lang.equals("default")) { //locale is used - String currentRev = null; - try{ - final BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"), lang+"/version" )))); - currentRev = br.readLine(); // may return null - br.close(); - }catch(final IOException e){ - //Error - } + // on lang=browser all active translation should be checked (because any could be requested by client) + List langlist; + if (lang.endsWith("browser")) + langlist = Translator.activeTranslations(); // get all translated languages + else { + langlist = new ArrayList(); + langlist.add(lang); + } + for (String tmplang : langlist) { + if (!tmplang.equals("") && !tmplang.equals("default") && !tmplang.equals("browser")) { //locale is used + String currentRev = null; + try { + final BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"), tmplang + "/version")))); + currentRev = br.readLine(); // may return null + br.close(); + } catch (final IOException e) { + //Error + } - if (currentRev == null || !currentRev.equals(sb.getConfig(Seed.VERSION, ""))) try { //is this another version?! - final File sourceDir = new File(sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT)); - final File destDir = new File(sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"), lang); - if (new TranslatorXliff().translateFilesRecursive(sourceDir, destDir, new File(locale_source, lang + ".lng"), "html,template,inc", "locale")){ //translate it - //write the new Versionnumber - final BufferedWriter bw = new BufferedWriter(new PrintWriter(new FileWriter(new File(destDir, "version")))); - bw.write(sb.getConfig(Seed.VERSION, "Error getting Version")); - bw.close(); + if (currentRev == null || !currentRev.equals(sb.getConfig(Seed.VERSION, ""))) { + try { //is this another version?! + final File sourceDir = new File(sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT)); + final File destDir = new File(sb.getDataPath("locale.translated_html", "DATA/LOCALE/htroot"), tmplang); + if (new TranslatorXliff().translateFilesRecursive(sourceDir, destDir, new File(locale_source, tmplang + ".lng"), "html,template,inc", "locale")) { //translate it + //write the new Versionnumber + final BufferedWriter bw = new BufferedWriter(new PrintWriter(new FileWriter(new File(destDir, "version")))); + bw.write(sb.getConfig(Seed.VERSION, "Error getting Version")); + bw.close(); + } + } catch (final IOException e) { + } } - } catch (final IOException e) {} + } } // initialize number formatter with this locale - Formatter.setLocale(lang); + if (!lang.equals("browser")) // "default" is handled by .setLocale() + Formatter.setLocale(lang); // registering shutdown hook ConcurrentLog.config("STARTUP", "Registering Shutdown Hook");