Index: trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/Launcher.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/Launcher.java	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/Launcher.java	(revision 41284)
@@ -76,6 +76,7 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.logging.Level;
 import java.util.prefs.Preferences;
 
 import javax.swing.ImageIcon;
@@ -978,8 +979,7 @@
 		// Try to get theme from a plugin
 		File pluginsDir = new File(pluginsDirectory);
 		if (!pluginsDir.isAbsolute()) {
-			pluginsDir = new File(System.getProperty("user.dir"),
-					pluginsDirectory);
+                    pluginsDir = new File(getApplicationFolder(), pluginsDirectory);
 		}
 		if (pluginsDir.exists()) {
 			logger.info("search andami-theme in plugins folder.");
@@ -3004,69 +3004,88 @@
 	 * Swing are configured.
 	 * 
 	 */
-	private static void configureLocales(String[] args) {
-		// Configurar el locale
-		String localeStr = null;
+    private static void configureLocales(String[] args) {
+        // Configurar el locale
+        String localeStr = null;
 
-		localeStr = PluginServices.getArgumentByName("language");
-		if (localeStr == null) {
-			localeStr = andamiConfig.getLocaleLanguage();
-		}
-		localeStr = normalizeLanguageCode(localeStr);
-		locale = getLocale(localeStr, andamiConfig.getLocaleCountry(),
-				andamiConfig.getLocaleVariant());
-		Locale.setDefault(locale);
-		JComponent.setDefaultLocale(locale);
-		org.gvsig.i18n.Messages.addLocale(locale);
-		// add english and spanish as fallback languages
-		if (localeStr.equals("es") || localeStr.equals("ca")
-				|| localeStr.equals("gl") || localeStr.equals("eu")
-				|| localeStr.equals("va")) {
-			// prefer Spanish for languages spoken in Spain
-			org.gvsig.i18n.Messages.addLocale(new Locale("es"));
-			org.gvsig.i18n.Messages.addLocale(new Locale("en"));
-		} else {
-			// prefer English for the rest
-			org.gvsig.i18n.Messages.addLocale(new Locale("en"));
-			org.gvsig.i18n.Messages.addLocale(new Locale("es"));
-		}
+        localeStr = PluginServices.getArgumentByName("language");
+        if ( localeStr == null ) {
+            localeStr = andamiConfig.getLocaleLanguage();
+        }
+        localeStr = normalizeLanguageCode(localeStr);
+        locale = getLocale(localeStr, andamiConfig.getLocaleCountry(),
+                andamiConfig.getLocaleVariant());
+        Locale.setDefault(locale);
+        JComponent.setDefaultLocale(locale);
+        org.gvsig.i18n.Messages.addLocale(locale);
+        // add english and spanish as fallback languages
+        if ( localeStr.equals("es") || localeStr.equals("ca")
+                || localeStr.equals("gl") || localeStr.equals("eu")
+                || localeStr.equals("va") ) {
+            // prefer Spanish for languages spoken in Spain
+            org.gvsig.i18n.Messages.addLocale(new Locale("es"));
+            org.gvsig.i18n.Messages.addLocale(new Locale("en"));
+        } else {
+            // prefer English for the rest
+            org.gvsig.i18n.Messages.addLocale(new Locale("en"));
+            org.gvsig.i18n.Messages.addLocale(new Locale("es"));
+        }
 
         // Create classloader for the i18n resources in the
         // andami and user i18n folder. Those values will have
         // precedence over any other values added afterwards
-        File andamiI18nFolder =
-            new File(System.getProperty("user.dir"), "i18n");
+        File appI18nFolder  = new File(getApplicationFolder(), "i18n");
         File userI18nFolder = new File(getAppHomeDir(), "i18n");
-        if( !userI18nFolder.exists() ) {
-        	try {
-				FileUtils.forceMkdir(userI18nFolder);
-			} catch (IOException e) {
-				logger.info("Can't create i18n folder in gvSIG home ("+userI18nFolder+").",e);
-			}
+        if ( !userI18nFolder.exists() ) {
+            try {
+                FileUtils.forceMkdir(userI18nFolder);
+            } catch (IOException e) {
+                logger.info("Can't create i18n folder in gvSIG home (" + userI18nFolder + ").", e);
+            }
         }
-
         logger.info("Loading i18n resources from the application and user "
-            + "folders: {}, {}", andamiI18nFolder, userI18nFolder);
+                + "folders: {}, {}", appI18nFolder, userI18nFolder);
 
-        URL[] i18nURLs;
-        try {
-            i18nURLs =
-                new URL[] { userI18nFolder.toURI().toURL(),
-                    andamiI18nFolder.toURI().toURL() };
-            ClassLoader i18nClassLoader = new URLClassLoader(i18nURLs);
-            org.gvsig.i18n.Messages.addResourceFamily("text", i18nClassLoader,
+        URL[] i18nURLs = getURLsFromI18nFolders(userI18nFolder, appI18nFolder);
+        ClassLoader i18nClassLoader = new URLClassLoader(i18nURLs);
+        org.gvsig.i18n.Messages.addResourceFamily("text", i18nClassLoader,
                 "Andami Launcher");
-        } catch (MalformedURLException e) {
-            logger.error("Error loading i18n resources from the application "
-                + "and user folders: " + andamiI18nFolder + ", "
-                + userI18nFolder, e);
-        }
 
+        // Los ficheros de traducciones estan ahora fuera del jar, en la
+        // Carpeta i18n/andami de la instalacion, asi que esto ya no hace falta.
+        //
         // Finally load the andami own i18n resources
-        org.gvsig.i18n.Messages.addResourceFamily("org.gvsig.andami.text",
-            "Andami Launcher");
-	}
+        // org.gvsig.i18n.Messages.addResourceFamily("org.gvsig.andami.text",
+        // "Andami Launcher");
+    }
 
+        private static URL[] getURLsFromI18nFolders(File userFolder, File appFolder) {
+            List<URL> urls = new ArrayList<URL>();
+            File[] files = new File[] { userFolder, appFolder };
+            for( int n1=0; n1<files.length; n1++ ) {
+                File folder = files[n1];
+                try {
+                    urls.add(folder.toURI().toURL());
+                } catch (MalformedURLException ex) {
+                    logger.warn("Can't convert file to url (file="+userFolder.getAbsolutePath()+").", ex);
+                    return null;
+                }
+                File[] subFiles = folder.listFiles();
+                for( int n2=0; n2<subFiles.length; n2++ ) {
+                    File subFolder = subFiles[n2];
+                    if( subFolder.isDirectory() ) {
+                        try {
+                            urls.add(subFolder.toURI().toURL());
+                        } catch (MalformedURLException ex) {
+                            logger.warn("Can't convert file to url (file="+subFolder.getAbsolutePath()+").", ex);
+                            return null;
+                        }
+                    }
+                }
+            }
+            return urls.toArray(new URL[urls.size()]);
+        }
+        
 	/**
 	 * Gets Home Directory location of the application into users home folder.
 	 * 
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/PluginsManager.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/PluginsManager.java	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/PluginsManager.java	(revision 41284)
@@ -10,13 +10,13 @@
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
+ * MA 02110-1301, USA.
  *
  * For any additional information, do not hesitate to contact us
  * at info AT gvsig.com, or visit our website www.gvsig.com.
@@ -32,15 +32,19 @@
 import org.gvsig.installer.lib.api.PackageInfo;
 
 public interface PluginsManager {
+
     /**
-     * Return the associated pluginServices to the extension class passed as parameter.
+     * Return the associated pluginServices to the extension class passed as
+     * parameter.
+     *
      * @param extension
      * @return plugin services
      */
     public PluginServices getPlugin(Class<? extends IExtension> extension);
-	
+
     /**
      * Return the associated pluginServices to the object passed as parameter.
+     *
      * @param object
      * @return plugin services
      */
@@ -48,145 +52,154 @@
 
     /**
      * Return the associated pluginServices to the extension plugin.
+     *
      * @param pluginName, name of the plugin
      * @return plugin services
-     */	
+     */
     public PluginServices getPlugin(String pluginName);
-	
-	/**
-	 * Get the package info associated to the plugin of the extension.
-	 * 
-	 * @param extension extension of the plugin 
-	 * @return plugin package info 
-	 */
-	public PackageInfo getPackageInfo(Class<? extends IExtension> extension);
-	
-	/**
-	 * Get the package info associated to the plugin with the specified name.
-	 * 
-	 * @param pluginName, name of the plugin
-	 * @return plugin package info 
-	 */
-	public PackageInfo getPackageInfo(String pluginName);
 
-	/**
-	 * Get the package info associated to the application.
-	 * 
-	 * @return application package info
-	 */
-	public PackageInfo getPackageInfo();
-	
-	/**
-	 * Return the list of plugins loaded in the application
-	 * @return list of plugins
-	 */
-	public List<PluginServices> getPlugins();
-	
     /**
+     * Get the package info associated to the plugin of the extension.
+     *
+     * @param extension extension of the plugin
+     * @return plugin package info
+     */
+    public PackageInfo getPackageInfo(Class<? extends IExtension> extension);
+
+    /**
+     * Get the package info associated to the plugin with the specified name.
+     *
+     * @param pluginName, name of the plugin
+     * @return plugin package info
+     */
+    public PackageInfo getPackageInfo(String pluginName);
+
+    /**
+     * Get the package info associated to the application.
+     *
+     * @return application package info
+     */
+    public PackageInfo getPackageInfo();
+
+    /**
+     * Return the list of plugins loaded in the application
+     *
+     * @return list of plugins
+     */
+    public List<PluginServices> getPlugins();
+
+    /**
      * Gets the instance of the extension whose class is provided.
-     * 
+     *
      * @param extension, class of the extension to retrieve
-     * 
+     *
      * @return The instance of the extension, or null if the instance does
-     *         not exist.
+     * not exist.
      */
-	public IExtension getExtension(Class<? extends IExtension> extension);
-	
-	/**
-	 * Return an iterator over al extensions loaded in the application.
-	 * 
-	 * @return iterator over extensions
-	 */
-	public Iterator<IExtension> getExtensions();
-	
-	/**
-	 * Set an extension to control the visivility of all the extensions
-	 * of the application.
-	 * 
-	 * @param extension
-	 */
-	public void setExclusiveUIExtension(ExclusiveUIExtension extension);
-	
-	/**
-	 * Return the ExclusiveUIExtension installed in the application or
-	 * null.
-	 * @return
-	 */
-	public ExclusiveUIExtension getExclusiveUIExtension();
+    public IExtension getExtension(Class<? extends IExtension> extension);
 
-	
-	/**
-	 * @deprecated use {@link #translate(String)}
-	 * @see {@link #translate(String)}
-	 */
+    /**
+     * Return an iterator over al extensions loaded in the application.
+     *
+     * @return iterator over extensions
+     */
+    public Iterator<IExtension> getExtensions();
+
+    /**
+     * Set an extension to control the visivility of all the extensions
+     * of the application.
+     *
+     * @param extension
+     */
+    public void setExclusiveUIExtension(ExclusiveUIExtension extension);
+
+    /**
+     * Return the ExclusiveUIExtension installed in the application or
+     * null.
+     *
+     * @return
+     */
+    public ExclusiveUIExtension getExclusiveUIExtension();
+
+    /**
+     * @deprecated use {@link #translate(String)}
+     * @see {@link #translate(String)}
+     */
     public String getText(Object obj, String msg);
 
     /**
      * Translate the message key to the current language used
      * in the application.
-     *  
+     *
      * @param msg key to translate
-     * @return message traslated or the key 
+     * @return message traslated or the key
      */
     public String translate(String msg);
-    
+
     /**
      * Returns the main application folder, where the application is installed.
-     * 
+     *
      * @return the main application folder
      */
     public File getApplicationFolder();
 
     /**
      * Returns the default folder with the installable package bundles.
-     * 
+     *
      * @return the default folder with the installable package bundles
      */
     public File getInstallFolder();
 
     /**
      * Returns the application folder in the home of user.
-     * 
+     *
      * @return the main application folder
      */
     public File getApplicationHomeFolder();
 
+
     /**
+     * Returns the default folder where the internationalization files are installed.
+     *
+     * @return the default folder where the internationalization files are installed.
+     */
+    public File getApplicationI18nFolder();
+    
+    /**
      * Returns the plugins folder.
-     * 
+     *
      * @return the plugins folder
      * @deprecated use {@link #getPluginsFolders()}
      */
     public File getPluginsFolder();
-    
+
     /**
      * Returns a list of folder on the plugins are instaleds.
-     * 
+     *
      * @return list of folders File of the plugins.
      */
     public List<File> getPluginsFolders();
-    
 
     /**
      * @deprecated @see {@link #getPluginsFolders()}
      */
-	public File getPluginsDirectory();
-	
-	/**
-	 * This method allows plugins to require the execution of
-	 * tasks
-	 * 
-	 * @param task
-	 * @param in_event_thread
-	 * @param priority
-	 */
-	public void addAdditionalTask(Runnable task, boolean in_event_thread, int priority);
-	
-	/**
-	 * This method executes the tasks required by the plugins. 
-	 * 
-	 * @return
-	 */
-	public void executeAdditionalTasks();
+    public File getPluginsDirectory();
 
+    /**
+     * This method allows plugins to require the execution of
+     * tasks
+     *
+     * @param task
+     * @param in_event_thread
+     * @param priority
+     */
+    public void addAdditionalTask(Runnable task, boolean in_event_thread, int priority);
+
+    /**
+     * This method executes the tasks required by the plugins.
+     *
+     * @return
+     */
+    public void executeAdditionalTasks();
+
 }
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/installer/translations/TranslationsInstaller.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/installer/translations/TranslationsInstaller.java	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/installer/translations/TranslationsInstaller.java	(revision 41284)
@@ -33,6 +33,8 @@
 import java.util.zip.ZipInputStream;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
+import org.gvsig.andami.PluginsLocator;
+import org.gvsig.andami.PluginsManager;
 import org.gvsig.installer.lib.api.PackageInfo;
 import org.gvsig.installer.lib.api.execution.InstallPackageServiceException;
 import org.gvsig.installer.lib.spi.InstallerInfoFileException;
@@ -57,9 +59,10 @@
     }
 
     public void install(File applicationFolder, InputStream inputStream, PackageInfo packageInfo) throws InstallPackageServiceException {
-        File i18nFolder = new File(applicationFolder,"i18n");
+        PluginsManager pluginsManager = PluginsLocator.getManager();
+        File i18nFolder = pluginsManager.getApplicationI18nFolder();
         
-	logger.info("Installing package '"+packageInfo.getCode()+"' in '"+applicationFolder.getAbsolutePath()+"'.");
+	logger.info("Installing package '"+packageInfo.getCode()+"' in '"+i18nFolder.getAbsolutePath()+"'.");
         try {
             if (!i18nFolder.exists()) {
 		logger.warn("Can install package '"+packageInfo.getCode()+"', install folder '"+i18nFolder+"' does not exists.");
@@ -101,11 +104,14 @@
 
                 File file = new File(folder, entryName);
                 if (entry.isDirectory()) {
-                    logger.debug("ignore folders in 'translations' package (" + entryName+").");
+        		file.mkdirs();                    
                 } else {
                     if (file.exists()) {
-                            FileUtils.forceDelete(file);
+                         FileUtils.forceDelete(file);
                     }
+                    if( !file.getParentFile().exists() ) {
+                        FileUtils.forceMkdir(file.getParentFile());
+                    }
                     logger.debug("extracting " + file.getAbsolutePath());
                     FileOutputStream fos = new FileOutputStream(file);
                     while ((count = zis.read(data, 0, BUFFER)) != -1) {
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/installer/packagebuilder/options/ProgressOption.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/installer/packagebuilder/options/ProgressOption.java	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/installer/packagebuilder/options/ProgressOption.java	(revision 41284)
@@ -28,6 +28,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.OutputStream;
+import java.net.URL;
 
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
@@ -107,7 +108,9 @@
         this.progressPanel.bind(taskStatus);
 
         try {
-
+            String downloadURL = wizard.getPackageInfo().getDownloadURLAsString();
+            wizard.getPackageInfo().setDownloadURL("");
+            
             MakePackageService makePackageService =
                 InstallerLocator.getInstallerManager().createMakePackage(
                     wizard.getFolderToPackaging(), wizard.getPackageInfo());
@@ -119,8 +122,10 @@
             if (indexOutputStream != null) {
                 taskStatus.message(getText("_Creating_index"));
                 makePackageService.createPackageIndex(
-                     wizard.getDownloadURL(), indexOutputStream);
+                        wizard.getDownloadURL(), indexOutputStream);
             }
+            
+            wizard.getPackageInfo().setDownloadURL(downloadURL);
             taskStatus.terminate();
 
             // Set the finished text
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/impl/DefaultPluginsManager.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/impl/DefaultPluginsManager.java	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/src/main/java/org/gvsig/andami/impl/DefaultPluginsManager.java	(revision 41284)
@@ -76,7 +76,12 @@
 	}
 
 	public PluginServices getPlugin(Object obj) {
-            return this.getPlugin(obj.getClass());
+            if( obj instanceof IExtension ) {
+                return this.getPlugin(obj.getClass());
+            }
+            PluginClassLoader loader = (PluginClassLoader) obj.getClass().getClassLoader();
+            String pluginName = loader.getPluginName();
+            return this.getPlugin(pluginName);
 	}
 
         public PluginServices getPlugin(String pluginName) {
@@ -238,6 +243,11 @@
         }
         
     }
+
+    public File getApplicationI18nFolder() {
+        return new File(this.getApplicationFolder(),"i18n");
+    }
+
     
     
 }
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/pom.xml
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/pom.xml	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.framework/org.gvsig.andami/pom.xml	(revision 41284)
@@ -222,7 +222,7 @@
     <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-lang3</artifactId>
-        <scope>runtime</scope>
+        <scope>compile</scope>
     </dependency>
     <dependency>
       <groupId>org.swinglabs</groupId>
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/resources-plugin/config.xml
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/resources-plugin/config.xml	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/resources-plugin/config.xml	(revision 41284)
@@ -789,25 +789,14 @@
         icon="tools-devel-translations-package"
         accelerator=""
         />
-      <action 
-        name="tools-devel-consolidate-translations"
-        label="_Consolidate_all_translations" 
-        position="908500201" 
-        action-command="tools-devel-consolidate-translations"
-        icon="tools-devel-consolidate-translations"
-        tooltip="_Consolidate_all_translations" 
-        accelerator=""
-        />
 
+
       <menu 
         name="tools-devel-translations-package"
         text="tools/Development/_Translations_package" 
         />
-      <menu 
-        name="tools-devel-consolidate-translations"
-        text="tools/Development/_Consolidate_all_translations" 
-        />
 
+
     </extension>
 
     <extension class-name="org.gvsig.app.extension.ShowDevelInfoExtension"
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/java/org/gvsig/app/extension/TranslationsPackageExtension.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/java/org/gvsig/app/extension/TranslationsPackageExtension.java	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/java/org/gvsig/app/extension/TranslationsPackageExtension.java	(revision 41284)
@@ -57,8 +57,6 @@
                     application.translate("_Translations_package"),
                     WindowManager.MODE.WINDOW
             );
-        } else if ( "tools-devel-consolidate-translations".equalsIgnoreCase(actionCommand) ) {
-
         }
     }
 
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/resources-plugin/config.xml
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/resources-plugin/config.xml	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/resources-plugin/config.xml	(revision 41284)
@@ -25,16 +25,34 @@
 
 -->
 <plugin-config>
-  	<alternativeNames name="org.gvsig.i18n.extension"/>
-	<depends plugin-name="org.gvsig.app.mainplugin" />
-	<depends plugin-name="org.gvsig.coreplugin.app.mainplugin" />
-	<resourceBundle name="text" />
-	<libraries library-dir="lib" />
-	<extensions>
-		<extension class-name="org.gvsig.i18n.extension.I18nExtension"
-			description="Extensión de gestión de traducciones multiidioma" 
-			active="true" 
-			priority="1">
-		</extension>
-	</extensions>
+    <alternativeNames name="org.gvsig.i18n.extension"/>
+    <depends plugin-name="org.gvsig.app.mainplugin" />
+    <depends plugin-name="org.gvsig.coreplugin.app.mainplugin" />
+    <resourceBundle name="text" />
+    <libraries library-dir="lib" />
+    <extensions>
+        <extension class-name="org.gvsig.i18n.extension.I18nExtension"
+                           description="Extensión de gestión de traducciones multiidioma" 
+                           active="true" 
+                           priority="1">
+        </extension>
+        <extension class-name="org.gvsig.i18n.extension.ConsolideTranslationsExtension"
+                           description="Extensión para consolidar en andami todas las traducciones" 
+                           active="true" 
+                           priority="1">
+            <action 
+                name="tools-devel-consolidate-translations"
+                label="_Consolidate_all_translations" 
+                position="908500201" 
+                action-command="tools-devel-consolidate-translations"
+                icon="tools-devel-consolidate-translations"
+                tooltip="_Consolidate_all_translations" 
+                accelerator=""
+            />
+            <menu 
+                name="tools-devel-consolidate-translations"
+                text="tools/Development/_Consolidate_all_translations" 
+            />
+        </extension>
+    </extensions>
 </plugin-config>
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/java/org/gvsig/i18n/impl/TranslationsConsolider.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/java/org/gvsig/i18n/impl/TranslationsConsolider.java	(revision 0)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/java/org/gvsig/i18n/impl/TranslationsConsolider.java	(revision 41284)
@@ -0,0 +1,379 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.gvsig.i18n.impl;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.gvsig.andami.PluginServices;
+import org.gvsig.andami.PluginsLocator;
+import org.gvsig.andami.PluginsManager;
+import org.gvsig.i18n.I18nManager;
+import org.gvsig.tools.ToolsLocator;
+import org.gvsig.tools.task.SimpleTaskStatus;
+import org.gvsig.tools.task.TaskStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author usuario
+ */
+public class TranslationsConsolider {
+
+    private static final Logger logger = LoggerFactory.getLogger(TranslationsConsolider.class);
+
+    private I18nManager i18nManager = null;
+    private PluginsManager pluginsManager = null;
+    private Map<String, Map<String, String>> allTranslations = null;
+    private Locale currentLocale = null;
+    private Map<String, List<String>> keysInPlugins = null;
+
+    public TranslationsConsolider() {
+        this.pluginsManager = PluginsLocator.getManager();
+        this.allTranslations = new HashMap<String, Map<String, String>>();
+        this.currentLocale = this.getI18nManager().getCurrentLocale();
+        this.keysInPlugins = new HashMap<String, List<String>>();
+    }
+
+    public void setCurrentLocale(Locale locale) {
+        this.currentLocale = locale;
+    }
+
+    public Locale getCurrentLocale() {
+        return this.currentLocale;
+    }
+
+    public I18nManager getI18nManager() {
+        if ( this.i18nManager == null ) {
+            this.i18nManager = I18nManagerImpl.getInstance();
+        }
+        return this.i18nManager;
+    }
+
+    public void addKey(String key, String pluginCode) {
+        List<String> pluginCodes = this.keysInPlugins.get(key);
+        if ( pluginCodes == null ) {
+            pluginCodes = new ArrayList<String>();
+            this.keysInPlugins.put(key, pluginCodes);
+        }
+        if ( !StringUtils.isBlank(pluginCode) ) {
+            if ( !pluginCodes.contains(pluginCode) ) {
+                pluginCodes.add(pluginCode);
+            }
+        }
+    }
+
+    public void addLocale(Locale locale) {
+        if ( this.allTranslations.get(locale.toString()) == null ) {
+            this.allTranslations.put(locale.toString().toLowerCase(), new HashMap<String, String>());
+        }
+    }
+
+    public List<String> getPluginCodesOfKey(String key) {
+        List<String> pluginCodes = this.keysInPlugins.get(key);
+        return pluginCodes;
+    }
+
+    public Map<String, String> getTranslations(String locale) {
+        Map<String, String> translations = this.allTranslations.get(locale.toString().toLowerCase());
+        return translations;
+    }
+
+    public Map<String, String> getTranslations(Locale locale) {
+        return this.getTranslations(locale.toString());
+    }
+
+    public void add(Locale locale, String key, String value, String pluginCode) {
+        Map<String, String> translations = this.getTranslations(locale);
+        if ( !translations.containsKey(key) ) {
+            translations.put(key, value);
+            this.addKey(key, pluginCode);
+        }
+    }
+
+    public void add(Locale locale, Properties properties, String pluginCode) {
+        this.addLocale(locale);
+        Enumeration enumKeys = properties.keys();
+        while ( enumKeys.hasMoreElements() ) {
+            String key = (String) enumKeys.nextElement();
+            String value = properties.getProperty(key);
+            this.add(locale, key, value, pluginCode);
+        }
+    }
+
+    public List<Locale> getLocales() {
+        List<Locale> locales = new ArrayList<Locale>(this.allTranslations.size());
+        Iterator<String> itLocales = this.allTranslations.keySet().iterator();
+        while ( itLocales.hasNext() ) {
+            Locale locale = new Locale(itLocales.next().toString());
+            locales.add(locale);
+        }
+        return locales;
+    }
+
+    public List<String> getKeys() {
+        List<String> keys = new ArrayList<String>(this.keysInPlugins.size());
+        keys.addAll(this.keysInPlugins.keySet());
+        Collections.sort(keys);
+        return keys;
+    }
+
+    private String getResourceFileName(Locale locale) {
+        StringBuilder fileName = new StringBuilder();
+        fileName.append("text");
+        if ( !StringUtils.isBlank(locale.getLanguage()) ) {
+            fileName.append("_");
+            fileName.append(locale.getLanguage());
+        }
+        if ( !StringUtils.isBlank(locale.getCountry()) ) {
+            fileName.append("_");
+            fileName.append(locale.getCountry());
+        }
+        if ( !StringUtils.isBlank(locale.getVariant()) ) {
+            fileName.append("_");
+            fileName.append(locale.getVariant());
+        }
+        fileName.append(".properties");
+        return fileName.toString();
+    }
+
+    public String getTranslation(String locale, String key) {
+        Map<String, String> translations = this.getTranslations(locale);
+        if ( translations == null ) {
+            logger.warn("Can't locate the translations for locale '" + locale + "'.");
+            return null;
+        }
+        return translations.get(key);
+    }
+
+    public String getTranslation(Locale locale, String key) {
+        return this.getTranslation(locale.toString(), key);
+    }
+
+    public String get(String key) {
+        return this.getTranslation(currentLocale, key);
+    }
+
+    public void put(String key, String value) {
+        this.add(currentLocale, key, value, null);
+    }
+
+    public void consolide() throws IOException {
+        SimpleTaskStatus task = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("Consolide translations");
+        task.setAutoremove(true);
+        task.add();
+        try {
+            task.setTitle("Consolide translations");
+            int n = this.loadAllTranslations(task);
+            if( !task.isCancellationRequested() ) {
+                this.storeAsProperties(task, n);
+            }
+        } finally {
+            task.terminate();
+        }
+    }
+    
+    private int loadAllTranslations(SimpleTaskStatus task) {
+        task.message("searching locales");
+        Locale[] locales = this.getI18nManager().getInstalledLocales();
+
+        List<PluginServices> plugins = this.pluginsManager.getPlugins();
+        File appI18nFolder = pluginsManager.getApplicationI18nFolder();
+        File[] subfolders = appI18nFolder.listFiles(new FileFilter() {
+            public boolean accept(File file) {
+                return file.isDirectory();
+            }
+        });
+        int n = 1;
+        task.setRangeOfValues(0, plugins.size() + subfolders.length + locales.length + 1);
+
+        task.message("loading from andami.");
+        task.setCurValue(n++);
+        loadTranslation(locales, appI18nFolder, null);
+
+        for ( File subfolder : subfolders ) {
+            if( task.isCancellationRequested() ) {
+                return n;
+            }
+            task.setCurValue(n++);
+            if ( subfolder.isDirectory() ) {
+                task.message("loading " + subfolder.getName());
+                if ( "andami".equals(subfolder.getName()) ) {
+                    loadTranslation(locales, appI18nFolder, "org.gvsig.andami");
+                } else {
+                    loadTranslation(locales, appI18nFolder, null);
+                }
+            }
+        }
+
+        for ( PluginServices plugin : plugins ) {
+            if( task.isCancellationRequested() ) {
+                return n;
+            }
+            if ( plugin != null ) {
+                task.message("loading " + plugin.getPluginName());
+                task.setCurValue(n++);
+                loadTranslation(locales, plugin.getPluginDirectory(), plugin.getPluginName());
+            }
+        }
+        return n;
+    }
+
+    private void loadTranslation(Locale[] locales, File folder, String pluginCode) {
+        for ( Locale locale : locales ) {
+            File f1 = new File(folder, getResourceFileName(locale));
+            File f2 = new File(folder, "i18n/" + getResourceFileName(locale));
+            if ( !f1.exists() && !f2.exists() ) {
+                if ( "es".equals(locale.getLanguage()) ) {
+                    f1 = new File(folder, "text.properties");
+                    f2 = new File(folder, "i18n/text.properties");
+                }
+            }
+            if ( f1.exists() ) {
+                loadTranslation(locale, f1, pluginCode);
+            }
+            if ( f2.exists() ) {
+                loadTranslation(locale, f2, pluginCode);
+            }
+        }
+    }
+
+    private void loadTranslation(Locale locale, File f, String pluginCode) {
+        FileInputStream fins = null;
+        try {
+            Properties properties = new Properties();
+            fins = new FileInputStream(f);
+            properties.load(fins);
+            this.add(locale, properties, pluginCode);
+        } catch (IOException ex) {
+            logger.warn("Error processing property file '" + f.getAbsolutePath() + "'.", ex);
+        } finally {
+            IOUtils.closeQuietly(fins);
+        }
+    }
+
+    private void storeAsProperties(SimpleTaskStatus task, int pos) throws IOException {
+        task.message("Prepraring to store");
+        File folder = new File(this.pluginsManager.getApplicationI18nFolder(), "translations.all");
+        if( !folder.exists() ) {
+            FileUtils.forceMkdir(folder);
+        }
+        List<String> keys = this.getKeys();
+        List<Locale> locales = this.getLocales();
+        for ( Locale locale : locales ) {
+            task.setCurValue(pos++);
+            task.message("Storing "+locale.toString());
+            Map<String, String> translations = this.getTranslations(locale);
+            Properties properties = new Properties();
+            for ( String key : keys ) {
+                String value = this.getTranslation(locale, key);
+                if( value == null ) {
+                    value = "";
+                }
+                properties.setProperty(key, value);
+            }
+            File f = new File(folder, this.getResourceFileName(locale));
+            FileOutputStream fos = null;
+            try {
+                fos = new FileOutputStream(f);
+                properties.store(fos, null);
+            } catch (Exception ex) {
+                logger.warn("Can't write properties '" + f.getAbsolutePath() + "'.", ex);
+            } finally {
+                IOUtils.closeQuietly(fos);
+            }
+
+        }
+        task.message("Storing plugin information");
+        Properties properties = new Properties();
+        for ( String key : keys ) {
+            List<String> pluginCodes = this.keysInPlugins.get(key);
+            StringBuilder ss = null;
+            for ( String pluginCode : pluginCodes ) {
+                if ( ss == null ) {
+                    ss = new StringBuilder();
+                } else {
+                    ss.append(", ");
+                }
+                ss.append(pluginCode);
+            }
+            if ( ss == null ) {
+                properties.setProperty(key, "");
+            } else {
+                properties.setProperty(key, ss.toString());
+            }
+        }
+        FileOutputStream fos = null;
+        File f = new File(folder, "keysbyplugin.properties");
+        try {
+            fos = new FileOutputStream(f);
+            properties.store(fos, null);
+        } catch (Exception ex) {
+            logger.warn("Can't write properties '" + f.getAbsolutePath() + "'.", ex);
+        } finally {
+            IOUtils.closeQuietly(fos);
+        }
+        task.message("");
+    }
+
+    /*
+     def storeAsDBF(self):
+     maxl = 100
+     for k in self.keys():
+     if len(k) > maxl:
+     maxl = len(k)
+     #print "max key len: ", maxl
+        
+     folder = File(self.__pluginsManager.getApplicationFolder(),"i18n")
+     f = File(folder,"translations.dbf")
+     try:
+     f.delete()
+     except:
+     print "Can't delete file "+f.getAbsolutePath()
+     schema = createSchema() 
+     schema.append( "ID" , "Integer" , 7)
+     schema.append( "key" , "String" , maxl)
+     schema.append( "locale" , "String" , 30)
+     schema.append( "translation" , "String" , 200)
+     schema.append( "plugins" , "String" , 200)
+
+     table = createDBF( schema, File(folder,"translations.dbf"))
+
+     locales = self.getI18nManager().getInstalledLocales()
+     idCounter = 1
+     for key in self.keys():
+     for locale in locales:
+     pluginCodes = ""
+     for pluginCode in self.getPluginCodesOfKey(key):
+     pluginCodes += pluginCode + " "
+     pluginCodes = str(pluginCodes).strip()
+        
+     table.append(ID=idCounter, 
+     key=key, 
+     locale=locale.toString(), 
+     translation=self.getTranslation(locale, key),
+     plugins=pluginCodes
+     )
+     idCounter +=1
+     table.commit()
+  
+     */
+}
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/java/org/gvsig/i18n/extension/ConsolideTranslationsExtension.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/java/org/gvsig/i18n/extension/ConsolideTranslationsExtension.java	(revision 0)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/java/org/gvsig/i18n/extension/ConsolideTranslationsExtension.java	(revision 41284)
@@ -0,0 +1,89 @@
+/**
+ * gvSIG. Desktop Geographic Information System.
+ *
+ * Copyright (C) 2007-2013 gvSIG Association.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * For any additional information, do not hesitate to contact us
+ * at info AT gvsig.com, or visit our website www.gvsig.com.
+ */
+/*
+ * AUTHORS (In addition to CIT):
+ * 2008 {DiSiD Technologies}  {New extension for installation and update of text translations}
+ */
+package org.gvsig.i18n.extension;
+
+import javax.swing.JOptionPane;
+import org.gvsig.andami.PluginServices;
+import org.gvsig.andami.plugins.Extension;
+import org.gvsig.andami.ui.mdiFrame.MainFrame;
+import org.gvsig.i18n.impl.TranslationsConsolider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Texts localization management extension.
+ *
+ * @author <a href="mailto:dcervera@disid.com">David Cervera</a>
+ */
+public class ConsolideTranslationsExtension extends Extension {
+
+    private static final Logger logger = LoggerFactory.getLogger(ConsolideTranslationsExtension.class);
+
+    private boolean executing = false;
+
+    public synchronized void execute(String actionCommand) {
+        final MainFrame main = PluginServices.getMainFrame();
+
+        if ( "tools-devel-consolidate-translations".equalsIgnoreCase(actionCommand) ) {
+            if ( this.executing ) {
+                main.messageDialog("Process is running.", "Warning", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }
+            this.executing = true;
+            main.refreshControls();
+            Thread process = new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        TranslationsConsolider consolider = new TranslationsConsolider();
+                        consolider.consolide();
+                        main.messageDialog("Consolidation of translations terminated.", "Information", JOptionPane.INFORMATION_MESSAGE);
+                    } catch(Exception ex) {
+                        logger.warn("There was errors consolidating translations.",ex);
+                        main.messageDialog("There was errors consolidating translations.", "Warning", JOptionPane.WARNING_MESSAGE);
+                    } finally {
+                        executing = false;
+                        main.refreshControls();
+                    }
+                }
+            });
+            process.start();
+        }
+    }
+
+    public void initialize() {
+        // Do nothing
+    }
+
+    public boolean isEnabled() {
+        return ! this.executing;
+    }
+
+    public boolean isVisible() {
+        return true;
+    }
+}

Property changes on: trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.i18n.app/org.gvsig.i18n.app.mainplugin/src/main/java/org/gvsig/i18n/extension/ConsolideTranslationsExtension.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.installer/org.gvsig.installer.lib/org.gvsig.installer.lib.impl/src/main/java/org/gvsig/installer/lib/impl/info/InstallerInfoFileWriter.java
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.installer/org.gvsig.installer.lib/org.gvsig.installer.lib.impl/src/main/java/org/gvsig/installer/lib/impl/info/InstallerInfoFileWriter.java	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.installer/org.gvsig.installer.lib/org.gvsig.installer.lib.impl/src/main/java/org/gvsig/installer/lib/impl/info/InstallerInfoFileWriter.java	(revision 41284)
@@ -33,8 +33,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.net.URL;
 import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
 
 import org.gvsig.installer.lib.api.PackageInfo;
 import org.gvsig.installer.lib.api.PackageInfoWriter;
@@ -114,9 +114,11 @@
             properties.setProperty(InstallerInfoTags.DEPENDENCIES, toStr(installInfo.getDependencies()));
             properties.setProperty(InstallerInfoTags.SOURCES_URL, toStr(installInfo.getSourcesURL()));
             properties.setProperty(InstallerInfoTags.WEB_URL, toStr(installInfo.getWebURL()));
-            properties.setProperty(InstallerInfoTags.DOWNLOAD_URL, toStr(installInfo.getDownloadURLAsString()));
             properties.setProperty(InstallerInfoTags.OWNER_URL, toStr(installInfo.getOwnerURL()));
             properties.setProperty(InstallerInfoTags.MODEL_VERSION, toStr(installInfo.getModelVersion()));
+            if( !StringUtils.isBlank(installInfo.getDownloadURLAsString()) ) {
+                properties.setProperty(InstallerInfoTags.DOWNLOAD_URL, toStr(installInfo.getDownloadURLAsString()));
+            }
             
             properties.store(os, "");
             os.close();
Index: trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.installer/org.gvsig.installer.lib/org.gvsig.installer.lib.impl/pom.xml
===================================================================
--- trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.installer/org.gvsig.installer.lib/org.gvsig.installer.lib.impl/pom.xml	(revision 41283)
+++ trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.installer/org.gvsig.installer.lib/org.gvsig.installer.lib.impl/pom.xml	(revision 41284)
@@ -19,6 +19,11 @@
         <artifactId>commons-io</artifactId>
       <scope>compile</scope>
     </dependency>
+        <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-lang3</artifactId>
+        <scope>compile</scope>
+    </dependency>
     <dependency>
       <groupId>org.gvsig</groupId>
       <artifactId>org.gvsig.installer.lib.api</artifactId>
