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

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

Go to download

Maven plugin to deal with i18n stuff in a project, mainly base on the i18n api (but not only).

There is a newer version: 4.0-beta-28
Show newest version
package org.nuiton.i18n.plugin.bundle;

/*-
 * #%L
 * I18n :: Maven Plugin
 * %%
 * Copyright (C) 2007 - 2024 Code Lutin, Ultreia.io
 * %%
 * 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%
 */

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import io.ultreia.java4all.i18n.spi.I18nResource;
import io.ultreia.java4all.i18n.spi.I18nTemplateDefinition;
import io.ultreia.java4all.i18n.spi.I18nTranslationSetDefinition;
import io.ultreia.java4all.i18n.spi.builder.I18nModule;
import io.ultreia.java4all.i18n.spi.builder.I18nTranslationSet;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
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.plugin.I18nMojoHelper;
import org.nuiton.i18n.plugin.I18nMojoWithI18nModuleSupport;
import org.nuiton.io.SortedProperties;
import org.nuiton.plugin.PluginHelper;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * Generate application bundle.
 * 

* This replace the {@code bundle} mojo using only i18n convention over configuration. *

* Created by tchemit on 31/10/2018. * * @author Tony Chemit - [email protected] * @since 4.0 */ @Mojo(name = "application-bundle", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_RESOURCES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) public class ApplicationBundleMojo extends I18nMojoWithI18nModuleSupport { /** * A flag to check that bundles are complete (no missing i18n translations). */ @Parameter(property = "i18n.checkBundle", defaultValue = "true") private boolean checkBundle; /** * A flag to show missing i18n translation. *

* Note : Need the {@link #checkBundle} to be activated). */ @Parameter(property = "i18n.showEmpty", defaultValue = "false") private boolean showEmpty; /** * A flag to make the build fails if there is some missing key values. *

* Note : This parameter should be used in a release profile to ensure bundles are complete. */ @Parameter(property = "i18n.failsIfAnyKeyMissingValue", defaultValue = "false") private boolean failsIfAnyKeyMissingValue; /** * A flag to make the build fails if there is some missing keys. *

* Note : This parameter should be used in a release profile to ensure bundles are complete. */ @Parameter(property = "i18n.failsIfAnyKeyMissingInBundle", defaultValue = "false") private boolean failsIfAnyKeyMissingInBundle; /** * Converter used to change format of bundles. */ @Parameter(property = "i18n.bundleFormatConverter") private String bundleFormatConverter; /** * Map of all available {@link BundleFormatConverter}. */ @Component(role = BundleFormatConverter.class) private Map bundleFormatConverters; /** * To categorize i18n keys (used by the i18n editor). *

* Values are comma separated like this: * {@code ui.config=observe.ui.config,ui=observe.ui, service=observe.service} *

* This is used by the I18n Editor as tabs in translation part. */ @Parameter(property = "i18n.keyCategories") private LinkedHashMap keyCategories; /** * Contains validation result after {@link I18nMojoHelper#checkBundle(Locale, Properties, boolean, BundleValidation)}. *

* May be null if validation is disabled. */ private BundleValidation bundleValidation; /** * Format converter to apply if */ private BundleFormatConverter converter; @Override public void init() throws Exception { super.init(); bundleValidation = new BundleValidation(getLocales()); if (StringUtils.isNotEmpty(bundleFormatConverter)) { // get converter from universe converter = bundleFormatConverters.get(bundleFormatConverter); if (converter == null) { // unknown converter throw new MojoExecutionException( String.format("There is no bundleFormatConverter named \"%s\", known ones are %s", bundleFormatConverter, bundleFormatConverters.keySet())); } } } @Override protected void doAction() throws Exception { String version = PluginHelper.removeSnapshotSuffix(getProject().getVersion()); I18nModule i18nModule = getI18nModule(); Charset encoding = getEncoding(); Set locales = getLocales(); String moduleName = i18nModule.getName(); String bundleOutputName = moduleName + "-i18n"; Log log = getLog(); if (isNotSilent()) { log.info(String.format("config - resources dir : %s", getBuildOutputDirectory())); log.info(String.format("config - package name : %s", i18nModule.getPackageName())); log.info(String.format("config - bundle name : %s", bundleOutputName)); log.info(String.format("config - encoding : %s", encoding)); if (bundleFormatConverter != null) { log.info(String.format("config - format converter : %s", bundleFormatConverter)); } log.info(String.format("config - locales : %s", locales)); log.info(String.format("config - version : %s", version)); } I18nMojoHelper helper = getHelper(); Set dependenciesTranslationsIds = getHelper().translationsToStr(i18nModule.getDependenciesTranslations(), "Load %d dependencies translations%s"); Set moduleTranslationsIds = getHelper().translationsToStr(i18nModule.getModuleTranslations(), "Load %d module translations%s"); Set translationIds = new TreeSet<>(); translationIds.addAll(dependenciesTranslationsIds); translationIds.addAll(moduleTranslationsIds); Set dependenciesTemplatesIds = getHelper().templatesToStr(i18nModule.getDependenciesTemplates(), "Load %d dependencies templates%s"); Set moduleTemplatesIds = getHelper().templatesToStr(i18nModule.getModuleTemplates(), "Load %d module templates%s"); Set templatesIds = new TreeSet<>(); templatesIds.addAll(dependenciesTemplatesIds); templatesIds.addAll(moduleTemplatesIds); Multimap dependencies = ArrayListMultimap.create(); Path translationsDirectory = getBuildOutputDirectory().toPath().resolve(I18nTranslationSetDefinition.I18N_CLASS_PATH); StringBuilder applicationTranslationIds = new StringBuilder(i18nModule.getId(bundleOutputName)); for (Locale locale : locales) { long t0 = System.nanoTime(); applicationTranslationIds.append(I18nResource.GROUP_ID_SEPARATOR).append(locale); SortedProperties propertiesOut = new SortedProperties(encoding.name(), false); List dependenciesTranslations = i18nModule.getDependenciesTranslations(locale); for (I18nTranslationSet dependenciesTranslation : dependenciesTranslations) { propertiesOut.putAll(dependenciesTranslation.getTranslations()); dependencies.put(locale, dependenciesTranslation.getDefinition().getId()); } int count = dependenciesTranslations.size(); I18nTranslationSet i18nTranslationFile = i18nModule.getModuleTranslation(locale); if (i18nTranslationFile != null) { propertiesOut.putAll(i18nTranslationFile.getTranslations()); dependencies.put(locale, i18nTranslationFile.getDefinition().getId()); count++; } if (count == 0) { log.warn(String.format("No bundle for locale %s", locale)); continue; } if (isNotSilent()) { log.info(String.format("generate bundle for locale %s from %d i18n resources (%d sentences)", locale, count, propertiesOut.size())); } // Apply conversion if necessary, depends on input bundleFormatConverter if (converter != null) { applyConversion(propertiesOut); } I18nTranslationSetDefinition applicationTranslationDefinition = new I18nTranslationSetDefinition(i18nModule.getPackageName(), bundleOutputName, locale); i18nModule.exportModuleTranslation(applicationTranslationDefinition, translationsDirectory, propertiesOut); if (isNotSilent() && isVerbose()) { log.info(String.format("bundle created in %s (%d sentences)", PluginHelper.convertTime(t0, System.nanoTime()), propertiesOut.size())); } if (checkBundle) { helper.checkBundle(locale, propertiesOut, showEmpty, bundleValidation); } } helper.failsIfAnyKeyMissingValue(failsIfAnyKeyMissingValue, bundleValidation); helper.failsIfAnyKeyMissingInBundle(failsIfAnyKeyMissingInBundle, bundleValidation); if (i18nModule.withDependenciesTemplates()) { Path templatesDirectory = getBuildOutputDirectory().toPath().resolve(I18nTemplateDefinition.I18N_CLASS_PATH); i18nModule.exportDependenciesTemplates(templatesDirectory); } String filename = getFilename(moduleName, "I18nApplicationDefinition"); String finalApplicationTranslationIds = applicationTranslationIds.toString(); Path target = generateJavaFile(i18nModule, "I18nApplicationDefinition", writer -> { String finalModuleName = moduleName + "-i18n"; String groupId = i18nModule.getPackageName(); String moduleTemplateStr = templatesIds.isEmpty() ? "" : templatesIds.stream().map(s -> "\"" + s + "\"").collect(Collectors.joining(",\n ")); String dependenciesTranslationStr = translationIds.isEmpty() ? "" : translationIds.stream().map(s -> "\"" + s + "\"").collect(Collectors.joining(",\n ")); String keyCategoriesStr = keyCategories.isEmpty() ? "ImmutableMap.of()" : "ImmutableMap.builder()" + keyCategories.entrySet().stream().map(s -> ".put(\"" + s.getKey() + "\",\"" + s.getValue() + "\")").collect(Collectors.joining("")) + ".build()"; String localesStr = getI18nModuleConfiguration().getLocales().stream().map(s -> "\"" + s.toString() + "\"").collect(Collectors.joining(",\n ")); String encodingStr = "Charset.forName(\"" + encoding + "\")"; String content = String.format( "package %1$s;\n\n" + "import com.google.auto.service.AutoService;\n" + "import com.google.common.collect.ImmutableMap;\n" + "import io.ultreia.java4all.i18n.spi.I18nApplicationDefinition;\n\n" + "import java.nio.charset.Charset;\n" + "import javax.annotation.Generated;\n\n" + "@AutoService(I18nApplicationDefinition.class)\n" + "@Generated(value = \"%5$s\", date = \"%6$s\")\n" + "public class %2$s extends I18nApplicationDefinition {\n\n" + " public %2$s() {\n" + " super(\"%1$s\", \"%4$s\", \"%3$s\",\n" + " %7$s, // encoding \n" + " \"%8$s\", // version\n" + " new String[]{%9$s}, // locales\n" + " %10$s, // keys categories\n" + " new String[]{\"%11$s\"}, // Application translations\n" + " new String[]{%12$s}, // Dependencies translations\n" + " new String[]{%13$s} // Application templates\n" + " );\n" + " }\n" + "}\n", groupId, filename, i18nModule.getConfiguration().getTemplateExtension(), finalModuleName, getClass().getName(), new Date(), encodingStr, version, localesStr, keyCategoriesStr, finalApplicationTranslationIds, dependenciesTranslationStr, moduleTemplateStr); try { writer.write(content); } catch (IOException e) { throw new RuntimeException("Can't generate java file content", e); } }); log.info(String.format("Application definition %s generated to %s", filename, target)); } /** * Apply conversion over {@code properties} with internal converter. * * @param properties Properties to walk through * @since 2.4 */ private void applyConversion(Properties properties) { for (Map.Entry entry : properties.entrySet()) { String convertedValue = converter.convert((String) entry.getValue()); properties.setProperty((String) entry.getKey(), convertedValue); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy