1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tralay.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include <com/sun/star/xml/sax/SAXException.hpp>
33 #include <transex3/vosapp.hxx>
35 #include <osl/file.hxx>
38 #include "layoutparse.hxx"
39 #include "helpmerge.hxx"
40 #include "xmlparse.hxx"
42 // Convert a rtl::OUString to a byte string.
43 #define OUSTRING_CSTR( str ) \
44 rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr()
46 #define STRING( str ) String( str, RTL_TEXTENCODING_UTF8 )
47 #define BSTRING( str ) ByteString( str, RTL_TEXTENCODING_UTF8 )
49 using ::rtl::OUString
;
51 using namespace ::osl
;
52 using namespace ::com::sun::star
;
53 using namespace ::com::sun::star::uno
;
56 class TranslateLayout
: public Application
65 std::vector
< ByteString
> mLanguages
;
66 std::list
< ByteString
> mFiles
;
70 virtual ~TranslateLayout();
71 ByteString
GetCommandLineParam( int i
);
72 ByteString
GetOptionArgument( int const i
);
73 void ExceptionalMain();
76 void MergeLanguage( ByteString
const& language
);
77 void ParseCommandLine();
80 using Application::GetCommandLineParam
;
85 fprintf( stderr
, "Usage: tralay [OPTION]... XML-FILE\n" );
86 fprintf( stderr
, "\nOptions:\n" );
87 fprintf( stderr
, " -h,--help show this help\n" );
88 fprintf( stderr
, " -l,--language=LANG process this language\n" );
89 fprintf( stderr
, " -m,--merge=DATABASE.SDF translation database\n" );
90 fprintf( stderr
, "\nExamples:\n" );
91 fprintf( stderr
, " tralay -l en-US -o localize.sdf zoom.xml # Extract\n" );
92 fprintf( stderr
, " tralay -m localize.sdf -l de -l nl -o out zoom.xml # Merge/translate\n" );
96 static ByteString
ConvertSystemPath( const ByteString
& rPath
)
98 if( rPath
.CompareTo( ".", 1 ) == 0 )
100 OUString
sPath( rPath
.GetBuffer(), rPath
.Len(), RTL_TEXTENCODING_UTF8
);
102 ::rtl::OUString curDirPth
, sURL
;
103 osl_getProcessWorkingDir( &curDirPth
.pData
);
105 ::osl::FileBase::getAbsoluteFileURL( curDirPth
, sPath
, sURL
);
106 ::osl::FileBase::getSystemPathFromFileURL( sURL
, sPath
);
108 return ByteString( rtl::OUStringToOString( sPath
, RTL_TEXTENCODING_UTF8
) );
116 ByteString
TranslateLayout::GetCommandLineParam( int i
)
118 return ByteString( OUSTRING_CSTR( Application::GetCommandLineParam( sal::static_int_cast
< USHORT
>( i
) ) ) );
121 ByteString
TranslateLayout::GetOptionArgument( int const i
)
123 if ( i
>= GetCommandLineParamCount() )
125 ByteString arg
= GetCommandLineParam( i
);
126 if ( !arg
.CompareTo( "-", 1 ) )
128 fprintf( stderr
, "Option needs an argument: %s, found: %s\n",
129 GetCommandLineParam( i
- 1 ).GetBuffer(),
136 void TranslateLayout::ParseCommandLine()
138 for ( int i
= 0; i
< GetCommandLineParamCount(); i
++ )
140 ByteString aParam
= GetCommandLineParam( i
);
141 if ( aParam
.Equals( "-h" ) || aParam
.Equals( "--help" ) )
143 else if ( aParam
.Equals( "-l" ) || aParam
.Equals( "--language" ) )
144 mLanguages
.push_back ( GetOptionArgument( ++i
) );
145 else if ( aParam
.Equals( "-m" ) || aParam
.Equals( "--merge" ) )
148 mLocalize
= GetOptionArgument( ++i
);
150 else if ( aParam
.Equals( "-o" ) || aParam
.Equals( "--output" ) )
151 mOutput
= ConvertSystemPath( GetOptionArgument( ++i
) );
152 else if ( !aParam
.CompareTo( "-", 1 ) )
154 fprintf( stderr
, "error: No such option: %s\n", aParam
.GetBuffer() );
158 mFiles
.push_back( ConvertSystemPath( aParam
) );
160 if ( !mFiles
.size() )
162 fprintf( stderr
, "error: No XML-FILE found\n" );
168 findAttribute( XMLAttributeList
* lst
, String
const& name
)
170 for ( ULONG i
= 0; i
< lst
->Count(); i
++ )
171 if ( lst
->GetObject( i
)->Equals( name
) )
172 return lst
->GetObject( i
);
177 translateAttribute( XMLAttributeList
* lst
,
178 String
const& name
, String
const& translation
)
180 if ( XMLAttribute
* a
= findAttribute( lst
, name
) )
181 return lst
->Replace ( new XMLAttribute( name
.Copy( 1 ), translation
), a
);
186 translateElement( XMLElement
* element
, ByteString
const& lang
,
187 ResData
* resData
, MergeDataFile
& mergeData
)
189 XMLAttributeList
* attributes
= element
->GetAttributeList();
190 std::vector
<XMLAttribute
*> interesting( interestingAttributes( attributes
) );
193 if( !interesting
.empty() )
195 std::vector
<XMLAttribute
*>::iterator
i( interesting
.begin() );
196 ByteString id
= BSTRING( (*i
++)->GetValue() );
197 for ( ; i
!= interesting
.end(); ++i
)
199 ByteString attributeId
= id
;
200 attributeId
+= BSTRING ( **i
);
201 resData
->sGId
= attributeId
;
202 resData
->sId
= element
->GetOldref();
204 if ( PFormEntrys
* entry
= mergeData
.GetPFormEntrys( resData
) )
206 ByteString translation
;
207 entry
->GetText( translation
, STRING_TYP_TEXT
, lang
, true );
208 // ByteString original = removeContent( element );
209 if ( !translation
.Len() )
211 translation
= original
;
213 translation
= BSTRING( ( *i
)->GetValue() );
215 delete translateAttribute( attributes
, **i
, STRING( translation
) );
221 static bool is_dir( ByteString
const& name
)
224 OUString
sFileURL( name
.GetBuffer(), name
.Len(), RTL_TEXTENCODING_UTF8
);
225 FileBase::getFileURLFromSystemPath( sFileURL
, sFileURL
);
226 if( DirectoryItem::get( sFileURL
, aItem
) == FileBase::E_None
)
228 FileStatus
aStatus(FileStatusMask_Type
);
229 if( aItem
.getFileStatus( aStatus
) == FileBase::E_None
)
231 if( aStatus
.getFileType() == FileStatus::Directory
)
238 static void make_directory( ByteString
const& name
)
240 OUString
sFileURL( name
.GetBuffer(), name
.Len(), RTL_TEXTENCODING_UTF8
);
241 FileBase::getFileURLFromSystemPath( sFileURL
, sFileURL
);
242 Directory::create( sFileURL
);
245 static void insertMarker( XMLParentNode
*p
, ByteString
const& file
)
247 if ( XMLChildNodeList
* lst
= p
->GetChildList() )
251 // Skip newline, if possible.
252 if ( lst
->Count() > 1
253 && lst
->GetObject( 2 )->GetNodeType() == XML_NODE_TYPE_DEFAULT
)
255 OUString marker
= OUString::createFromAscii( "\n NOTE: This file has been generated automagically by transex3/layout/tralay,\n from source template: " )
257 + OUString::createFromAscii( ".\n Do not edit, changes will be lost.\n" );
258 lst
->Insert( new XMLComment( marker
, 0 ), i
);
262 void TranslateLayout::MergeLanguage( ByteString
const& language
)
264 ByteString xmlFile
= mFiles
.front();
266 MergeDataFile
mergeData( mLocalize
, xmlFile
,
267 FALSE
, RTL_TEXTENCODING_MS_1252
);
269 DirEntry
aFile( xmlFile
);
270 SimpleXMLParser aParser
;
271 LayoutXMLFile
* layoutXml
= new LayoutXMLFile( mMergeMode
);
272 if ( !aParser
.Execute( aFile
.GetFull() , STRING( xmlFile
), layoutXml
) )
274 fprintf(stderr
, "error: parsing: %s\n", xmlFile
.GetBuffer() );
278 layoutXml
->Extract();
279 insertMarker( layoutXml
, xmlFile
);
281 ResData
resData( "", "", "" );
282 resData
.sResTyp
= mProject
; /* mGid1 ?? */
283 resData
.sFilename
= xmlFile
;
285 XMLHashMap
* xmlStrings
= layoutXml
->GetStrings();
286 for ( XMLHashMap::iterator i
= xmlStrings
->begin(); i
!= xmlStrings
->end();
289 if ( LangHashMap
* languageMap
= i
->second
)
290 if ( XMLElement
* element
= ( *languageMap
)[ "en-US" ] )
291 translateElement( element
, language
, &resData
, mergeData
);
295 ByteString outFile
= "/dev/stdout";
297 ByteString outFile
= "\\\\.\\CON";
302 if ( is_dir( outFile
) )
304 ByteString outDir
= mOutput
;
305 outDir
.Append( "/" ).Append( language
);
306 if ( !is_dir( outDir
) )
307 make_directory( outDir
);
309 outFile
.Append( "/" ).Append( xmlFile
);
312 layoutXml
->Write( outFile
);
316 void TranslateLayout::Merge()
318 if ( mLanguages
.size() )
319 for ( std::vector
<ByteString
>::iterator i
= mLanguages
.begin();
320 i
!= mLanguages
.end(); ++i
)
323 MergeLanguage( mLanguage
);
326 void TranslateLayout::CreateSDF()
328 ByteString xmlFile
= mFiles
.front();
330 ByteString sdf
= "/dev/stdout";
332 ByteString sdf
= "\\\\.\\CON";
336 Export::SetLanguages( mLanguages
);
337 HelpParser::CreateSDF( sdf
, mProject
, mRoot
, xmlFile
,
338 new LayoutXMLFile( mMergeMode
), mGid1
);
341 void TranslateLayout::ExceptionalMain()
344 if ( mLanguages
.size() )
345 mLanguage
= mLanguages
.front();
352 void TranslateLayout::Main()
358 catch ( xml::sax::SAXException
& rExc
)
360 OString
aStr( OUStringToOString( rExc
.Message
,
361 RTL_TEXTENCODING_ASCII_US
) );
363 if (rExc
.WrappedException
>>= exc
)
365 aStr
+= OString( " >>> " );
366 aStr
+= OUStringToOString( exc
.Message
, RTL_TEXTENCODING_ASCII_US
);
368 fprintf( stderr
, "error: parsing: '%s'\n", aStr
.getStr() );
369 OSL_ENSURE( 0, aStr
.getStr() );
371 catch ( uno::Exception
& rExc
)
373 OString
aStr( OUStringToOString( rExc
.Message
,
374 RTL_TEXTENCODING_ASCII_US
) );
375 fprintf( stderr
, "error: UNO: '%s'\n", aStr
.getStr() );
376 OSL_ENSURE( 0, aStr
.getStr() );
380 TranslateLayout::TranslateLayout()
383 , mLanguage( "en-US" )
384 , mLocalize( "localize.sdf" )
386 , mProject( "layout" )
388 , mMergeMode( false )
394 TranslateLayout::~TranslateLayout()