All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.i18n.plugin.bundle.BundleMojo Maven / Gradle / Ivy

/*
 * #%L
 * I18n :: Maven Plugin
 * 
 * $Id: BundleMojo.java 2007 2013-07-18 12:38:49Z tchemit $
 * $HeadURL: http://svn.nuiton.org/svn/i18n/tags/i18n-2.5.2/i18n-maven-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/BundleMojo.java $
 * %%
 * Copyright (C) 2007 - 2010 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

package org.nuiton.i18n.plugin.bundle;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.nuiton.i18n.bundle.I18nBundleEntry;
import org.nuiton.i18n.bundle.I18nBundleUtil;
import org.nuiton.i18n.init.DefaultI18nInitializer;
import org.nuiton.io.SortedProperties;
import org.nuiton.plugin.PluginHelper;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

/**
 * Generate an aggregate i18n bundle for all dependencies of the project.
 * 

* The main idea is to have a final unique i18n bundle for a application to * launch, this really improve i18n loading time to have a unique named bundle, * no need to seek in all dependencies... *

* Moreover, this permits also to deal with order of i18n keys, more precisly, * we want to use the higher level i18n key for an application. If the i18n * key is present on a library, we want to be able to override it in * application (or user wants it:)). *

* This goal permits this using the dependencies graph order of artifacts. * * @author tchemit * @since 0.12 */ @Mojo(name = "bundle", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, requiresProject = true, requiresDependencyResolution = ResolutionScope.RUNTIME) @Execute(goal = "collect-i18n-artifacts") public class BundleMojo extends AbstractMakeI18nBundleMojo { /** * A flag to generate the i18n definition file. *

* This file contains all generated bundles and the paths of all i18n * artifacts used to make it. * * @since 2.0 */ @Parameter(property = "i18n.generateDefinitionFile", defaultValue = "true") protected boolean generateDefinitionFile; /** * A flag to generate the i18n csv file wich contains all translation for * all locales. *

* Useful to translate from a language to another one. * * @since 2.5 */ @Parameter(property = "i18n.generateCsvFile", defaultValue = "false") protected boolean generateCsvFile; /** * Location of the csv file to generate if parameter * {@link #generateCsvFile} is on. * * @since 2.5 */ @Parameter(property = "i18n.bundleCsvFile", defaultValue = "${basedir}/target/${project.artifactId}-i18n.csv") protected File bundleCsvFile; /** * Char separator used when generating the csv bundle file if parameter * {@link #generateCsvFile} is on. * * @since 2.5 */ @Parameter(property = "i18n.bundleCsvSeparator", defaultValue = "\t") protected String bundleCsvSeparator; /** * Converter used to change format of bundles. * * @since 2.4 */ @Parameter(property = "i18n.bundleFormatConverter") protected String bundleFormatConverter; /** * Map of all availables {@link BundleFormatConverter}. * * @since 2.4 */ @Component(role = BundleFormatConverter.class) protected Map bundleFormatConverters; /** Format converter to apply if */ protected BundleFormatConverter converter; @Override public void init() throws Exception { super.init(); // add root bundle directory as resources of the project addResourceDir(bundleOutputDir, "**/*.properties"); if (generateCsvFile) { addResourceDir(bundleOutputDir, "**/*.csv"); } if (StringUtils.isNotEmpty(bundleFormatConverter)) { // get converter from universe converter = bundleFormatConverters.get(bundleFormatConverter); if (converter == null) { // unknown converter throw new MojoExecutionException( "There is no bundleFormatConverter named \"" + bundleFormatConverter + "\", known ones are " + bundleFormatConverters.keySet()); } } } @Override protected void doAction() throws Exception { long t00 = System.nanoTime(); String version = getProject().getVersion(); version = PluginHelper.removeSnapshotSuffix(version); String inputEncoding = getBundleInputEncoding(); String outputEncoding = getBundleOutputEncoding(); if (!silent) { getLog().info("config - resources dir : " + bundleOutputDir); getLog().info("config - package name : " + bundleOutputPackage); getLog().info("config - bundle name : " + bundleOutputName); getLog().info("config - input encoding : " + inputEncoding); getLog().info("config - output encoding : " + outputEncoding); if (bundleFormatConverter != null) { getLog().info("config - format converter : " + bundleFormatConverter); } getLog().info("config - locales : " + Arrays.toString(locales)); getLog().info("config - version : " + version); } Map bundleDico = new LinkedHashMap(locales.length); for (Locale locale : locales) { long t0 = System.nanoTime(); File bundleOut = getI18nFile(outputFolder, bundleOutputName, locale, false ); SortedProperties propertiesOut = new SortedProperties(outputEncoding, false); StringBuilder buffer = new StringBuilder(); URL[] urls = getCollectI18nResources(locale); if (urls.length == 0) { getLog().warn("no bundle for locale " + locale); continue; } if (!silent) { getLog().info("generate bundle for locale " + locale + " from " + urls.length + " i18n resource(s)"); } List bundlesUrls = new ArrayList(); Charset loadEncoding = Charset.forName(inputEncoding); for (URL url : urls) { long t000 = System.nanoTime(); I18nBundleEntry bundleEntry = new I18nBundleEntry(url, locale, null); bundleEntry.load(propertiesOut, loadEncoding); String strPath = bundleEntry.getPath().toString(); int index = strPath.indexOf("i18n/"); String str = strPath.substring(index); bundlesUrls.add(str); buffer.append(',').append(str); if (verbose) { getLog().info( "loaded " + bundleEntry.getPath() + " in " + PluginHelper.convertTime(t000, System.nanoTime())); } } if (!bundlesUrls.isEmpty()) { bundleDico.put(locale, buffer.substring(1)); if (!silent) { if (getLog().isDebugEnabled()) { getLog().debug(bundlesUrls.size() + " i18n resource(s) detected"); } for (String u : bundlesUrls) { getLog().info(u); } } } // Apply conversion if necessary, depends on input bundleFormatConverter if (converter != null) { applyConversion(propertiesOut); } propertiesOut.store(bundleOut); if (!silent && verbose) { getLog().info( "bundle created in " + PluginHelper.convertTime(t0, System.nanoTime()) + " (detected sentences : " + propertiesOut.size() + ")"); } if (checkBundle) { checkBundle(locale, propertiesOut, showEmpty, unsafeMapping); } } failsIfWarning(); if (generateDefaultLocale) { generateDefaultBundle(); } if (generateDefinitionFile) { generateDefinitionFile(version, bundleDico); } if (generateCsvFile) { generateCsvFile(); } if (!silent && verbose) { getLog().info("done in " + PluginHelper.convertTime(t00, System.nanoTime())); } } @Override protected File getBundleFile(File root, String artifactId, Locale locale, boolean create) throws IOException { return getI18nFile(root, artifactId, locale, create); } protected void generateDefinitionFile(String version, Map bundleDico) throws IOException { // ecriture du ficher des definitions i18n (permet de faire une // recherche exacte sur un fichier puis d'en deduire les bundles a // charger String f = String.format(DefaultI18nInitializer.UNIQUE_BUNDLE_DEF, bundleOutputName); File defOut = new File(outputFolder, f); if (!silent) { getLog().info("prepare i18n definition file in " + defOut.getAbsolutePath()); } SortedProperties p = new SortedProperties(encoding, false); p.setProperty(DefaultI18nInitializer.BUNDLE_DEF_LOCALES, bundles); p.setProperty(DefaultI18nInitializer.BUNDLE_DEF_VERSION, version); p.setProperty(DefaultI18nInitializer.BUNDLE_DEF_ENCODING, encoding); for (Entry e : bundleDico.entrySet()) { p.setProperty(DefaultI18nInitializer.BUNDLES_FOR_LOCALE + e.getKey().toString(), e.getValue()); } p.store(defOut); } @Override protected URL[] getCollectI18nResources(Locale locale) throws IOException { File file = getCollectOutputFile(locale, false); if (!file.exists()) { return I18nBundleUtil.EMPTY_URL_ARRAY; } URL[] urls = PluginHelper.getLinesAsURL(file); return urls; } /** * Apply conversion over {@code properties} with internal converter. * * @param properties Properties to walk through * @since 2.4 */ protected void applyConversion(Properties properties) { for (Entry entry : properties.entrySet()) { String convertedValue = converter.convert((String) entry.getValue()); properties.setProperty((String) entry.getKey(), convertedValue); } } /** * Generates a csv file with all translations. *

* First column is key, second is first locale translation, ... * * @throws IOException if any IO problem while the copy. * @since 2.5 */ protected void generateCsvFile() throws IOException { if (!bundleCsvFile.exists()) { createNewFile(bundleCsvFile); } Set allKeys = new HashSet(); Map bundlesByLocale = new LinkedHashMap(); for (Locale locale : locales) { File bundleFile = getBundleFile(outputFolder, bundleOutputName, locale, false ); SortedProperties properties = new SortedProperties(bundleOutputEncoding); properties.load(bundleFile); for (Object o : properties.keySet()) { allKeys.add((String) o); } bundlesByLocale.put(locale, properties); } List keys = new ArrayList(allKeys); Collections.sort(keys); BufferedWriter writer = new BufferedWriter(new FileWriter(bundleCsvFile)); try { // add header line StringBuilder builder = new StringBuilder("Key"); for (Locale locale : locales) { builder.append(bundleCsvSeparator).append(locale.getCountry()); } writer.write(builder.toString()); // for each key get all translations for all for (String key : keys) { writer.newLine(); builder = new StringBuilder(key); for (Locale locale : locales) { SortedProperties properties = bundlesByLocale.get(locale); Object value = properties.get(key); builder.append(bundleCsvSeparator).append("\""); builder.append(value == null ? "" : value); builder.append("\""); } writer.write(builder.toString()); } writer.close(); } finally { IOUtils.closeQuietly(writer); } if (!isSilent()) { getLog().info("Generate csv bundle file at " + bundleCsvFile); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy