
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
© 2015 - 2025 Weber Informatics LLC | Privacy Policy