/**
* Copyright (C) 2011 BonitaSoft S.A.
* BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
* 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 2.0 of the License, or
* (at your option) any later version.
* <p>
* 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.
* <p>
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.console.common.server.i18n;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.bonitasoft.web.toolkit.client.common.i18n.AbstractI18n;
import org.bonitasoft.web.toolkit.client.common.texttemplate.Arg;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
* @author Séverin Moussel
* @author Fabio Lombardi
* @author Emmanuel Duchastenier
*/
public class I18n extends AbstractI18n {
/**
* Property that can be set to override the default i18n *.po files, or to provide translations for new languages.
* Points to a folder that contains .po files
*/
public static final String I18N_CUSTOM_DIR_PROPERTY = "org.bonitasoft.i18n.folder";
private static File I18N_CUSTOM_DIR = getI18nCustomDirectory();
private I18n() {
// Singleton
}
public static I18n getInstance() {
if (I18N_instance == null) {
I18N_instance = new I18n();
}
return (I18n) I18N_instance;
}
// For test matters only:
void refresh() {
I18N_CUSTOM_DIR = getI18nCustomDirectory();
}
private static File getI18nCustomDirectory() {
String customI18nFolder = System.getProperty(I18N_CUSTOM_DIR_PROPERTY);
return customI18nFolder != null ? new File(customI18nFolder) : null;
}
@Override
public void loadLocale(final LOCALE locale) {
Map<String, String> results = loadLocale(getStreams(locale));
if (I18N_CUSTOM_DIR != null) {
results.putAll(loadLocale(locale, FileUtils.listDir(I18N_CUSTOM_DIR)));
}
setLocale(locale, results);
}
private Map<String, String> loadLocale(List<InputStream> streams) {
TreeMap<String, String> treeMap = new TreeMap<>();
for (InputStream stream : streams) {
treeMap.putAll(parsePoResource(stream));
}
return treeMap;
}
private TreeMap<String, String> loadLocale(final LOCALE locale, List<File> files) {
TreeMap<String, String> treeMap = new TreeMap<>();
for (File file : getLocaleFiles(locale, files)) {
treeMap.putAll(parsePoFile(file));
}
return treeMap;
}
List<InputStream> getStreams(LOCALE locale) {
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
try {
Resource[] resources = patternResolver.getResources("classpath:/i18n/" + getLocaleRegexForResource(locale));
List<InputStream> streams = new ArrayList<>(resources.length);
for (Resource resource : resources) {
InputStream stream = resource.getInputStream();
streams.add(stream);
}
return streams;
} catch (IOException e) {
e.printStackTrace();
return Collections.emptyList();
}
}
private Map<String, String> parsePoFile(final File file) {
return POParser.parse(file);
}
private Map<String, String> parsePoResource(final InputStream stream) {
return POParser.parsePOFromStream(stream);
}
private List<File> getLocaleFiles(final LOCALE locale, List<File> files) {
return FileUtils.getMatchingFiles(makeLocaleRegex(locale), files);
}
private String makeLocaleRegex(final LOCALE locale) {
return "(.*)" + locale.toString().trim() + ".po";
}
private String getLocaleRegexForResource(final LOCALE locale) {
return "*" + locale.toString().trim() + ".po";
}
public static Map<String, String> getAvailableLocalesFor(String application) {
final Map<String, String> results = new LinkedHashMap<>();
final Map<String, String> locales = getLocales();
for (final String locale : locales.keySet()) {
if (localeExists(locale, application)) {
results.put(locale, locales.get(locale));
}
}
return results;
}
/**
* @return available locale file for a specified application (i.e application_locale.po)
*/
private static boolean localeExists(String locale, String application) {
final String fileName = application + "_" + locale + ".po";
final File file = new File(I18N_CUSTOM_DIR, fileName);
return file.exists() || I18n.class.getResource("/i18n/" + fileName) != null;
}
@Override
protected String getText(String string) {
return string;
// throw new RuntimeException("On server side, we absolutely need to pass locale");
}
@Override
protected String getText(String string, Arg... args) {
return string;
// throw new RuntimeException("On server side, we absolutely need to pass locale");
}
}