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; | |||
} | |||
} | |||
} | |||