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 | * <xmlproperty> now handles CDATA sections. BugZilla Report 17195 | ||||
* <translate> now translate tokens that are placed close together. | |||||
Bugzilla Report 17297 | |||||
Other changes: | Other changes: | ||||
-------------- | -------------- | ||||
* Six new Clearcase tasks added. | * 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. | * Translates text embedded in files using Resource Bundle files. | ||||
* | * | ||||
* @author Magesh Umasankar, Don Brown | * @author Magesh Umasankar, Don Brown | ||||
* @author <a href="mailto:tom@tbee.org">Tom Eugelink</a> | |||||
*/ | */ | ||||
public class Translate extends MatchingTask { | public class Translate extends MatchingTask { | ||||
@@ -507,52 +508,66 @@ public class Translate extends MatchingTask { | |||||
BufferedReader in | BufferedReader in | ||||
= new BufferedReader(new InputStreamReader(fis, srcEncoding)); | = new BufferedReader(new InputStreamReader(fis, srcEncoding)); | ||||
String line; | String line; | ||||
int stLength = startToken.length(); | |||||
int etLength = endToken.length(); | |||||
while ((line = in.readLine()) != null) { | 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.write(line); | ||||
out.newLine(); | 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; | |||||
} | |||||
} | |||||
} | |||||