This change fixes this. Thanks Tom, sorry for the time it took to process your patch. PR: 17297 Submitted by: Tom Eugelink (tom at tbee dot org) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274730 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -176,6 +176,9 @@ Fixed bugs: | |||
| * <xmlproperty> now handles CDATA sections. BugZilla Report 17195 | |||
| * <translate> now translate tokens that are placed close together. | |||
| Bugzilla Report 17297 | |||
| Other changes: | |||
| -------------- | |||
| * Six new Clearcase tasks added. | |||
| @@ -0,0 +1 @@ | |||
| Diese ist eine Demo Datei für die translate_Aufgabe. | |||
| @@ -0,0 +1,10 @@ | |||
| This=Diese | |||
| is=ist | |||
| a=eine | |||
| demo=Demo | |||
| file=Datei | |||
| #note for people understanding german | |||
| # \u00fc = u umlaut | |||
| for=für | |||
| the=die | |||
| _task=_Aufgabe | |||
| @@ -0,0 +1 @@ | |||
| @This@ @is@ @a@ @demo@ @file@ @for@ @the@ translate@_task@. | |||
| @@ -0,0 +1,28 @@ | |||
| <?xml version="1.0"?> | |||
| <project name="translate-test" default="test1" basedir="."> | |||
| <property name="input.dir" value="input"/> | |||
| <property name="output.dir" value="output"/> | |||
| <property name="expected.dir" value="expected"/> | |||
| <target name="setup"> | |||
| <mkdir dir="${output.dir}/de"/> | |||
| </target> | |||
| <target name="test1" depends="setup"> | |||
| <translate toDir="${output.dir}/de" | |||
| starttoken="@" | |||
| endtoken="@" | |||
| bundle="${input.dir}/resources" | |||
| bundlelanguage="ger" | |||
| bundlecountry="de" | |||
| forceoverwrite="yes" | |||
| srcencoding="ISO8859_1" | |||
| destencoding="ISO8859_1" | |||
| bundleencoding="Cp1252"> | |||
| <fileset dir="${input.dir}"> | |||
| <include name="template.txt"/> | |||
| </fileset> | |||
| </translate> | |||
| </target> | |||
| <target name="cleanup"> | |||
| <delete dir="${output.dir}" quiet="true"/> | |||
| </target> | |||
| </project> | |||
| @@ -75,6 +75,7 @@ import org.apache.tools.ant.util.FileUtils; | |||
| * Translates text embedded in files using Resource Bundle files. | |||
| * | |||
| * @author Magesh Umasankar, Don Brown | |||
| * @author <a href="mailto:tom@tbee.org">Tom Eugelink</a> | |||
| */ | |||
| public class Translate extends MatchingTask { | |||
| @@ -507,52 +508,66 @@ public class Translate extends MatchingTask { | |||
| BufferedReader in | |||
| = new BufferedReader(new InputStreamReader(fis, srcEncoding)); | |||
| String line; | |||
| int stLength = startToken.length(); | |||
| int etLength = endToken.length(); | |||
| while ((line = in.readLine()) != null) { | |||
| int startIndex = -1; | |||
| int endIndex = -1; | |||
| outer: while (true) { | |||
| startIndex = line.indexOf(startToken, endIndex + etLength); | |||
| if (startIndex < 0 || | |||
| startIndex + stLength >= line.length()) { | |||
| break; | |||
| } | |||
| endIndex = line.indexOf(endToken, startIndex + stLength); | |||
| if (endIndex < 0) { | |||
| break; | |||
| } | |||
| String matches = line.substring(startIndex + stLength, | |||
| endIndex); | |||
| //If there is a white space or = or :, then | |||
| //it isn't to be treated as a valid key. | |||
| for (int k = 0; k < matches.length(); k++) { | |||
| char c = matches.charAt(k); | |||
| if (c == ':' || | |||
| c == '=' || | |||
| Character.isSpaceChar(c)) { | |||
| endIndex = endIndex - 1; | |||
| continue outer; | |||
| } | |||
| } | |||
| String replace = null; | |||
| replace = (String) resourceMap.get(matches); | |||
| //If the key hasn't been loaded into resourceMap, | |||
| //use the key itself as the value also. | |||
| if (replace == null) { | |||
| log("Warning: The key: " + matches | |||
| + " hasn't been defined.", | |||
| Project.MSG_DEBUG); | |||
| replace = matches; | |||
| } | |||
| line = line.substring(0, startIndex) | |||
| + replace | |||
| + line.substring(endIndex + etLength); | |||
| endIndex = startIndex + replace.length() + etLength; | |||
| if (endIndex + etLength >= line.length()) { | |||
| break; | |||
| } | |||
| } | |||
| // 2003-02-21 new replace algorithm by tbee (tbee@tbee.org) | |||
| // because it wasn't able to replace something like "@aaa;@bbb;" | |||
| // is there a startToken | |||
| // and there is still stuff following the startToken | |||
| int startIndex = line.indexOf(startToken); | |||
| while ( startIndex >= 0 && (startIndex+startToken.length()) <= line.length() ) | |||
| { | |||
| // the new value, this needs to be here | |||
| // because it is required to calculate the next position to search from | |||
| // at the end of the loop | |||
| String replace = null; | |||
| // we found a starttoken, is there an endtoken following? | |||
| // start at token+tokenlength because start and end token may be indentical | |||
| int endIndex = line.indexOf(endToken, startIndex + startToken.length()); | |||
| if (endIndex < 0) startIndex += 1; | |||
| else | |||
| { | |||
| // grab the token | |||
| String token = line.substring(startIndex + startToken.length(), endIndex); | |||
| // If there is a white space or = or :, then | |||
| // it isn't to be treated as a valid key. | |||
| boolean validToken = true; | |||
| for (int k = 0; k < token.length() && validToken; k++) | |||
| { | |||
| char c = token.charAt(k); | |||
| if ( c == ':' | |||
| || c == '=' | |||
| || Character.isSpaceChar(c) | |||
| ) | |||
| { | |||
| validToken = false; | |||
| } | |||
| } | |||
| if (!validToken) startIndex += 1; | |||
| else | |||
| { | |||
| // find the replace string | |||
| if (resourceMap.containsKey(token)) replace = (String)resourceMap.get(token); | |||
| else replace = token; | |||
| // generate the new line | |||
| line = line.substring(0, startIndex) | |||
| + replace | |||
| + line.substring(endIndex + endToken.length()); | |||
| // set start position for next search | |||
| startIndex += replace.length(); | |||
| } | |||
| } | |||
| // find next starttoken | |||
| startIndex = line.indexOf(startToken, startIndex); | |||
| } | |||
| out.write(line); | |||
| out.newLine(); | |||
| } | |||
| @@ -0,0 +1,133 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "Ant" and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.i18n; | |||
| import org.apache.tools.ant.BuildFileTest; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.IOException; | |||
| /** | |||
| * Tests the Translate task. | |||
| * | |||
| * @author <a href="mailto:antoine@antbuild.com">Antoine Levy-Lambert</a> | |||
| * @since Ant 1.6 | |||
| */ | |||
| public class TranslateTest extends BuildFileTest { | |||
| static private final int BUF_SIZE = 32768; | |||
| private final static String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/i18n/translate"; | |||
| public TranslateTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| configureProject(TASKDEFS_DIR + "/translate.xml"); | |||
| } | |||
| public void tearDown() { | |||
| executeTarget("cleanup"); | |||
| } | |||
| public void test1() { | |||
| executeTarget("test1"); | |||
| assertTrue("translation of "+ TASKDEFS_DIR + "/input/template.txt",compareFiles(TASKDEFS_DIR+"/expected/de/template.txt",TASKDEFS_DIR+"/output/de/template.txt")); | |||
| } | |||
| private boolean compareFiles(String name1, String name2) { | |||
| File file1 = new File(name1); | |||
| File file2 = new File(name2); | |||
| try { | |||
| if (!file1.exists() || !file2.exists()) { | |||
| System.out.println("One or both files do not exist:" + name1 + ", " + name2); | |||
| return false; | |||
| } | |||
| if (file1.length() != file2.length()) { | |||
| System.out.println("File size mismatch:" + name1 + "(" + file1.length() + "), " + | |||
| name2 + "(" + file2.length() + ")"); | |||
| return false; | |||
| } | |||
| // byte - byte compare | |||
| byte[] buffer1 = new byte[BUF_SIZE]; | |||
| byte[] buffer2 = new byte[BUF_SIZE]; | |||
| FileInputStream fis1 = new FileInputStream(file1); | |||
| FileInputStream fis2 = new FileInputStream(file2); | |||
| int index = 0; | |||
| int read = 0; | |||
| while ((read = fis1.read(buffer1)) != -1) { | |||
| fis2.read(buffer2); | |||
| for (int i = 0; i < read; ++i, ++index) { | |||
| if (buffer1[i] != buffer2[i]) { | |||
| System.out.println("Bytes mismatch:" + name1 + ", " + name2 + | |||
| " at byte " + index); | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| catch (IOException e) { | |||
| System.out.println("IOException comparing files: " + name1 + ", " + name2); | |||
| return false; | |||
| } | |||
| } | |||
| } | |||