This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 7.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 8a74ed9e3561a0a33bf7e848a38dde1d64c67bbe Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Aug 15 15:59:43 2019 +0100 Back-port import code so bulk updates can be imported from 8.5.x --- .../tomcat/buildutil/translate/Constants.java | 29 ++++ .../apache/tomcat/buildutil/translate/Import.java | 135 ++++++++++++++++ .../apache/tomcat/buildutil/translate/Utils.java | 180 +++++++++++++++++++++ 3 files changed, 344 insertions(+) diff --git a/java/org/apache/tomcat/buildutil/translate/Constants.java b/java/org/apache/tomcat/buildutil/translate/Constants.java new file mode 100644 index 0000000..403daa6 --- /dev/null +++ b/java/org/apache/tomcat/buildutil/translate/Constants.java @@ -0,0 +1,29 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tomcat.buildutil.translate; + +public class Constants { + + public static final String L10N_PREFIX = "LocalStrings"; + public static final String L10N_SUFFIX = ".properties"; + + public static final String[] SEARCH_DIRS = new String[] { "java", "webapps" }; + + public static final String STORAGE_DIR = ".settings/translations"; + + public static final String END_PACKAGE_MARKER = ".zzz."; +} diff --git a/java/org/apache/tomcat/buildutil/translate/Import.java b/java/org/apache/tomcat/buildutil/translate/Import.java new file mode 100644 index 0000000..61ee9b1 --- /dev/null +++ b/java/org/apache/tomcat/buildutil/translate/Import.java @@ -0,0 +1,135 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tomcat.buildutil.translate; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.Properties; + +public class Import { + + private static final String LINE_SEP = System.getProperty("line.separator"); + + + public static void main(String... args) throws IOException { + File root = new File(Constants.STORAGE_DIR); + + for (File f : root.listFiles()) { + // Not robust but good enough + if (f.isFile() && f.getName().startsWith(Constants.L10N_PREFIX)) { + processFile(f); + } + } + } + + + @SuppressWarnings("null") + private static void processFile(File f) throws IOException { + String language = Utils.getLanguage(f.getName()); + + // Unlike the master branch, don't skip the original so we can import + // updates to the English translations + Properties props = Utils.load(f); + Object[] objKeys = props.keySet().toArray(); + Arrays.sort(objKeys); + + String currentPkg = null; + Writer w = null; + String currentGroup = "zzz"; + + for (Object objKey : objKeys) { + String key = (String) objKey; + CompositeKey cKey = new CompositeKey(key); + + if (!cKey.pkg.equals(currentPkg)) { + currentPkg = cKey.pkg; + if (w != null) { + w.close(); + } + File outFile = new File(currentPkg.replace('.', File.separatorChar), Constants.L10N_PREFIX + language + Constants.L10N_SUFFIX); + FileOutputStream fos = new FileOutputStream(outFile); + w = new OutputStreamWriter(fos, "UTF-8"); + insertLicense(w); + } + + if (!currentGroup.equals(cKey.group)) { + currentGroup = cKey.group; + w.write(LINE_SEP); + } + + w.write(cKey.key + "=" + Utils.formatValue(props.getProperty(key))); + w.write(LINE_SEP); + } + if (w != null) { + w.close(); + } + } + + + private static void insertLicense(Writer w) throws IOException { + w.write("# Licensed to the Apache Software Foundation (ASF) under one or more"); + w.write(LINE_SEP); + w.write("# contributor license agreements. See the NOTICE file distributed with"); + w.write(LINE_SEP); + w.write("# this work for additional information regarding copyright ownership."); + w.write(LINE_SEP); + w.write("# The ASF licenses this file to You under the Apache License, Version 2.0"); + w.write(LINE_SEP); + w.write("# (the \"License\"); you may not use this file except in compliance with"); + w.write(LINE_SEP); + w.write("# the License. You may obtain a copy of the License at"); + w.write(LINE_SEP); + w.write("#"); + w.write(LINE_SEP); + w.write("# http://www.apache.org/licenses/LICENSE-2.0";); + w.write(LINE_SEP); + w.write("#"); + w.write(LINE_SEP); + w.write("# Unless required by applicable law or agreed to in writing, software"); + w.write(LINE_SEP); + w.write("# distributed under the License is distributed on an \"AS IS\" BASIS,"); + w.write(LINE_SEP); + w.write("# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied."); + w.write(LINE_SEP); + w.write("# See the License for the specific language governing permissions and"); + w.write(LINE_SEP); + w.write("# limitations under the License."); + w.write(LINE_SEP); + } + private static class CompositeKey { + + public final String pkg; + public final String key; + public final String group; + + public CompositeKey(String in) { + int posPkg = in.indexOf(Constants.END_PACKAGE_MARKER); + pkg = in.substring(0, posPkg); + key = in.substring(posPkg + Constants.END_PACKAGE_MARKER.length()); + int posGroup = key.indexOf('.'); + if (posGroup == -1) { + group = ""; + } else { + group = key.substring(0, posGroup); + } + } + } +} diff --git a/java/org/apache/tomcat/buildutil/translate/Utils.java b/java/org/apache/tomcat/buildutil/translate/Utils.java new file mode 100644 index 0000000..50ea4ed --- /dev/null +++ b/java/org/apache/tomcat/buildutil/translate/Utils.java @@ -0,0 +1,180 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.apache.tomcat.buildutil.translate; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +public class Utils { + + private static final Pattern ADD_CONTINUATION = Pattern.compile("\\n", Pattern.MULTILINE); + private static final Pattern ESCAPE_LEADING_SPACE = Pattern.compile("^(\\s)", Pattern.MULTILINE); + private static final Pattern FIX_SINGLE_QUOTE = Pattern.compile("(?<!')'(?!')", Pattern.MULTILINE); + + private Utils() { + // Utility class. Hide default constructor. + } + + + static String getLanguage(String name) { + return name.substring(Constants.L10N_PREFIX.length(), name.length() - Constants.L10N_SUFFIX.length()); + } + + + static Properties load(File f) { + Properties props = new Properties(); + + FileInputStream fis = null; + Reader r = null; + try { + fis = new FileInputStream(f); + r = new InputStreamReader(fis, "UTF-8"); + props.load(r); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (r != null) { + try { + r.close(); + } catch (IOException e) { + // Ignore + } + } + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + // Ignore + } + } + } + return props; + } + + + static String formatValue(String in) { + String result = ADD_CONTINUATION.matcher(in).replaceAll("\\\\n\\\\\n"); + if (result.endsWith("\\\n")) { + result = result.substring(0, result.length() - 2); + } + result = ESCAPE_LEADING_SPACE.matcher(result).replaceAll("\\\\$1"); + + if (result.contains("\n\\\t")) { + result = result.replace("\n\\\t", "\n\\t"); + } + + if (result.contains("[{0}]")) { + result = FIX_SINGLE_QUOTE.matcher(result).replaceAll("''"); + } + return result; + } + + + static void processDirectory(File root, File dir, Map<String,Properties> translations) throws IOException { + for (File f : dir.listFiles()) { + if (f.isDirectory()) { + processDirectory(root, f, translations); + } else if (f.isFile()) { + processFile(root, f, translations); + } + } + } + + + static void processFile(File root, File f, Map<String,Properties> translations) throws IOException { + String name = f.getName(); + + // non-l10n files + if (!name.startsWith(Constants.L10N_PREFIX)) { + return; + } + + // Determine language + String language = Utils.getLanguage(name); + + String keyPrefix = getKeyPrefix(root, f); + Properties props = Utils.load(f); + + // Create a Map for the language if one does not exist. + Properties translation = translations.get(language); + if (translation == null) { + translation = new Properties(); + translations.put(language, translation); + } + + // Add the properties from this file to the combined file, prefixing the + // key with the package name to ensure uniqueness. + for (Object obj : props.keySet()) { + String key = (String) obj; + String value = props.getProperty(key); + + translation.put(keyPrefix + key, value); + } + } + + + static String getKeyPrefix(File root, File f) throws IOException { + String prefix = f.getParentFile().getCanonicalPath(); + prefix = prefix.substring(root.getCanonicalPath().length() + 1); + prefix = prefix.replace(File.separatorChar, '.'); + prefix = prefix + Constants.END_PACKAGE_MARKER; + return prefix; + } + + + static void export(String language, Properties translation, File storageDir) { + File out = new File(storageDir, Constants.L10N_PREFIX + language + Constants.L10N_SUFFIX); + FileOutputStream fos = null; + Writer w = null; + try { + fos = new FileOutputStream(out); + w = new OutputStreamWriter(fos, "UTF-8"); + String[] keys = translation.keySet().toArray(new String[0]); + Arrays.sort(keys); + for (Object key : keys) { + w.write(key + "=" + Utils.formatValue(translation.getProperty((String) key)) + "\n"); + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } finally { + if (w != null) { + try { + w.close(); + } catch (IOException e) { + // Ignore + } + } + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + // Ignore + } + } + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org