/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
* <p>
*/
package org.olat.core.util.i18n;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.olat.core.gui.render.StringOutput;
import org.olat.core.gui.render.URLBuilder;
import org.olat.core.gui.translator.Translator;
import org.olat.core.helpers.Settings;
import org.olat.core.logging.AssertException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.Util;
import org.olat.core.util.i18n.devtools.TranslationDevManager;
import org.olat.core.util.i18n.ui.InlineTranslationInterceptHandlerController;
import org.olat.test.OlatTestCase;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Description:<br>
* Testing i18n Translation Tool and Translation Developers Tools
*
* <P>
* Initial Date: 01.09.2008 <br>
* @author gnaegi
* @author rhaag
*/
public class I18nTest extends OlatTestCase {
private OLog log = Tracing.createLoggerFor(I18nTest.class);
@Autowired
private I18nManager i18nMgr;
@Autowired
private TranslationDevManager tDMgr;
private static final String testSourceBundle = "org.olat.core.util.i18n.junittestdata.devtools.source";
private static final String testTargetBundle = "org.olat.core.util.i18n.junittestdata.devtools.target";
private static final String testMoveTargetBundle = "org.olat.core.util.i18n.junittestdata.movetarget.source";
/**
* @see junit.framework.TestCase#setUp()
*/
@Before
public void setup() throws Exception {
//see prepareDevToolTests() !
Settings.setJUnitTest(true);
}
@After
public void tearDown() throws Exception {
String testNewBundle = "org.olat.core.util.i18n.junittestdata.new";
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
// only delete files when basedir available
if (baseDir == null) return;
File testFile = i18nMgr.getPropertiesFile(testLocale, testNewBundle, baseDir);
// delete not only new/_i18n/LocalStrings_de.properties, delete also _i18n and new itself
if (testFile.getParentFile().getParentFile().exists()) {
FileUtils.deleteDirsAndFiles(testFile.getParentFile().getParentFile(), true, true);
}
// don't do inline translation markup
i18nMgr.setMarkLocalizedStringsEnabled(null, false);
// cleanup dev tools test case files
removeDevToolTests();
}
protected void prepareDevToolTests(){
// create test fixure in devtools.source
// Roman: you can't check in a 'default' package (illegal package name in java)
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
// key 1
String key = "key.to.move";
I18nItem i18nItem = i18nMgr.getI18nItem(testSourceBundle, key, testLocale);
i18nMgr.saveOrUpdateI18nItem(i18nItem, "I have to go");
i18nMgr.setAnnotation(i18nItem, "an annotation");
i18nMgr.setKeyPriority(testSourceBundle, key, 100);
// key 2
key = "key.to.stay2";
i18nItem = i18nMgr.getI18nItem(testSourceBundle, key, testLocale);
i18nMgr.saveOrUpdateI18nItem(i18nItem, "hello $:key.to.move");
}
protected void removeDevToolTests(){
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
// cleanup devtools source/target files
// 1) source files
File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testSourceBundle);
File testSFile = i18nMgr.getPropertiesFile(testLocale, testSourceBundle, baseDir);
File sourcePath = testSFile.getParentFile().getParentFile();
FileUtils.deleteDirsAndFiles(sourcePath, true, true);
// 2) target files
baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testTargetBundle);
File testTFile = i18nMgr.getPropertiesFile(testLocale, testTargetBundle, baseDir);
File targetPath = testTFile.getParentFile().getParentFile();
FileUtils.deleteDirsAndFiles(targetPath, true, true);
// 3) move target files
baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testMoveTargetBundle);
File testMFile = i18nMgr.getPropertiesFile(testLocale, testMoveTargetBundle, baseDir);
File movePath = testMFile.getParentFile().getParentFile().getParentFile();
FileUtils.deleteDirsAndFiles(movePath, true, true);
}
@Test public void testRemoveDeletedKeysTest() {
// set languages that is used as reference: all keys there are the keys should not to be deleted
String[] referenceLanguages = new String[]{"de", "en"};
// set the languages that should be cleaned up
Set<String> targetLanguages = I18nModule.getTranslatableLanguageKeys();
//Set<String> targetLanguages = new HashSet<String>();
//targetLanguages.add("en");
tDMgr.removeDeletedKeys(false, referenceLanguages, targetLanguages);
}
@Test public void testMoveKeyTask() {
if (I18nModule.isTransToolEnabled()) {
prepareDevToolTests();
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
String ktm = "key.to.move";
i18nMgr.setCachingEnabled(true);
Properties sourcePropResolved = i18nMgr.getResolvedProperties(testLocale, testSourceBundle);
Properties sourceProp = i18nMgr.getPropertiesWithoutResolvingRecursively(testLocale, testSourceBundle);
String matchString = sourceProp.getProperty(ktm);
assertTrue(sourcePropResolved.getProperty("key.to.stay2").indexOf(matchString) != -1);
tDMgr.moveKeyToOtherBundle(testSourceBundle, testTargetBundle, ktm);
sourceProp = i18nMgr.getPropertiesWithoutResolvingRecursively(testLocale, testSourceBundle);
Properties targetProp = i18nMgr.getPropertiesWithoutResolvingRecursively(testLocale, testTargetBundle);
assertNull(sourceProp.getProperty(ktm));
assertNotNull(targetProp.getProperty(ktm));
Properties sourceMetaProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testSourceBundle);
Properties targetMetaProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testTargetBundle);
assertNull(sourceMetaProp.getProperty(ktm + I18nManager.METADATA_ANNOTATION_POSTFIX));
assertNull(sourceMetaProp.getProperty(ktm + I18nManager.METADATA_KEY_PRIORITY_POSTFIX));
assertTrue(targetMetaProp.containsKey(ktm + I18nManager.METADATA_ANNOTATION_POSTFIX));
assertEquals("100", targetMetaProp.getProperty(ktm + I18nManager.METADATA_KEY_PRIORITY_POSTFIX));
//check for changed references in value
//if correctly done, should still be resolvable
assertTrue(sourcePropResolved.getProperty("key.to.stay2").indexOf(matchString)!=-1);
tDMgr.logToFile("moveKey");
}
}
@Test public void testMovePackageTask(){
if (I18nModule.isTransToolEnabled()) {
prepareDevToolTests();
tDMgr.movePackageTask(testSourceBundle, testTargetBundle);
i18nMgr.clearCaches();
Properties sourceProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testSourceBundle);
assertTrue(sourceProp.isEmpty());
Properties targetProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testTargetBundle);
assertFalse(targetProp.isEmpty());
tDMgr.logToFile("movePackage");
}
}
@Test public void testMovePackageByMovingSingleKeysTask(){
if (I18nModule.isTransToolEnabled()) {
prepareDevToolTests();
tDMgr.movePackageByMovingSingleKeysTask(testSourceBundle, testTargetBundle);
i18nMgr.clearCaches();
Properties sourceProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testSourceBundle);
assertTrue(sourceProp.isEmpty());
Properties targetProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testTargetBundle);
assertFalse(targetProp.isEmpty());
tDMgr.logToFile("movePackageSingle");
}
}
@Test public void testMergePackageTask(){
if (I18nModule.isTransToolEnabled()) {
prepareDevToolTests();
tDMgr.mergePackageTask(testSourceBundle, testTargetBundle);
i18nMgr.clearCaches();
assertTrue(i18nMgr.getPropertiesWithoutResolvingRecursively(null, testSourceBundle).isEmpty());
//TODO: manipulate source/target first, merge and check if all is in target!
//try to merge existing key
}
}
@Test public void testRenameLanguageTask(){
if (I18nModule.isTransToolEnabled()) {
prepareDevToolTests();
// create source
Locale xxLocale = new Locale("xx");
String key = "key.to.move";
I18nItem i18nItem = i18nMgr.getI18nItem(testSourceBundle, key, xxLocale);
i18nMgr.saveOrUpdateI18nItem(i18nItem, "I have to go");
i18nMgr.setAnnotation(i18nItem, "an annotation");
i18nMgr.setKeyPriority(testSourceBundle, key, 100);
// copy to target
Locale yyLocale = new Locale("yy");
tDMgr.renameLanguageTask(xxLocale, yyLocale);
i18nMgr.clearCaches();
// test
Properties deletedProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(xxLocale, testSourceBundle);
assertTrue(deletedProperties.isEmpty());
Properties targetProp = i18nMgr.getPropertiesWithoutResolvingRecursively(yyLocale, testSourceBundle);
assertFalse(targetProp.isEmpty());
}
}
//TODO: RH: remove this or really test for correct finding?!
@Test public void testGetDouplicateKeys(){
tDMgr.getDouplicateKeys();
}
//TODO: RH: remove this or really test for correct finding?!
@Test public void testGetDouplicateValues(){
tDMgr.getDouplicateValues();
}
@Test public void testMoveLanguageTask(){
if (I18nModule.isTransToolEnabled()) {
prepareDevToolTests();
String srcPath = I18nModule.getTransToolApplicationLanguagesSrcDir().getAbsolutePath() + "/../../test/java/org/olat/core/util/i18n/junittestdata/devtools";
String targetPath = srcPath + "/../movetarget";
//only copy: target should exist
Locale mvLocale = i18nMgr.getLocaleOrDefault("de");
// test before move
Properties sourceProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(mvLocale, testSourceBundle);
assertFalse(sourceProperties.isEmpty());
Properties moveProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(mvLocale, testMoveTargetBundle);
assertTrue(moveProperties.isEmpty());
// copy
tDMgr.moveLanguageTask(mvLocale, srcPath, targetPath, false);
// test after copy
sourceProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(mvLocale, testSourceBundle);
assertFalse(sourceProperties.isEmpty());
moveProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(mvLocale, testMoveTargetBundle);
assertFalse(moveProperties.isEmpty());
// move
tDMgr.moveLanguageTask(mvLocale, srcPath, targetPath, true);
// test after move
sourceProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(mvLocale, testSourceBundle);
assertTrue(sourceProperties.isEmpty());
moveProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(mvLocale, testMoveTargetBundle);
assertFalse(moveProperties.isEmpty());
}
}
//remove after execution!
@Test
public void testRemoveXKeyTask(){
tDMgr.removeXKeysTask(false);
tDMgr.logToFile("XKeys");
}
//remove after execution!
@Test
public void testRemoveTodoKeyTask(){
tDMgr.removeTodoKeysTask(false);
tDMgr.logToFile("todoKeys");
}
//remove after execution!
@Test
public void testRemoveEmptyKeysTask(){
tDMgr.removeEmptyKeysTask(false);
tDMgr.logToFile("emptyKeys");
}
//remove after execution!
@Test
public void testRemoveReferenceLanguageCopiesTask(){
if (I18nModule.isTransToolEnabled()) {
tDMgr.removeReferenceLanguageCopiesTask(false);
tDMgr.logToFile("refLangCopied");
}
}
/**
* Test method i18nManager.searchForAvailableLanguages()
*/
@Test public void testSearchForAvailableLanguages() {
if (I18nModule.isTransToolEnabled()) {
// Try to load i18n files and a jar from the testdata dir
File testDataDir = new File(I18nModule.getTransToolApplicationLanguagesSrcDir(), "/../../test/java/org/olat/core/util/i18n/junittestdata/");
assertTrue(testDataDir.exists());
Set<String> foundLanguages = i18nMgr.searchForAvailableLanguages(testDataDir);
// Set must contain some LocalStrings file:
assertTrue(foundLanguages.contains("de"));
assertTrue(foundLanguages.contains("en"));
assertTrue(foundLanguages.contains("pt_BR"));
// Set must contain some LocaleStrings from the jar package
assertTrue(foundLanguages.contains("fr"));
assertTrue(foundLanguages.contains("zh_CN"));
// Final check
assertEquals(6, foundLanguages.size());
} else {
Set<String> foundLanguages = I18nModule.getAvailableLanguageKeys();
// Set must contain some LocaleStrings from the jar package
assertTrue(foundLanguages.contains("fr"));
assertTrue(foundLanguages.contains("zh_CN"));
}
}
/**
* Test method i18nManager.searchForBundleNamesContainingI18nFiles()
*/
@Test public void testSearchForBundleNamesContainingI18nFiles() {
long start = System.currentTimeMillis();
List<String> foundBundles = i18nMgr.searchForBundleNamesContainingI18nFiles();
long end = System.currentTimeMillis();
log.info("Searching for " + foundBundles.size() + " bundles on OLAT source path took me " + (end-start) + "ms", "testSearchForBundleNamesContainingI18nFiles");
// Must contain packages from core
assertTrue(foundBundles.contains("org.olat.core"));
assertTrue(foundBundles.contains("org.olat.core.gui.control"));
assertTrue(foundBundles.contains("org.olat.core.commons.fullWebApp"));
// Must contain packages from olat app
assertTrue(foundBundles.contains("org.olat"));
assertTrue(foundBundles.contains("org.olat.course"));
}
/**
* Test method i18nManager.buildI18nFilename()
*/
@Test public void testBuildI18nFilename() {
String overlay = I18nModule.getOverlayName();
String testFileName = i18nMgr.buildI18nFilename(new Locale("de"));
assertEquals("LocalStrings_de.properties", testFileName);
testFileName = i18nMgr.buildI18nFilename(new Locale("de","","__" + overlay));
assertEquals("LocalStrings_de__" + overlay + ".properties", testFileName);
testFileName = i18nMgr.buildI18nFilename(new Locale("de","CH"));
assertEquals("LocalStrings_de_CH.properties", testFileName);
testFileName = i18nMgr.buildI18nFilename(new Locale("de","CH","VENDOR"));
assertEquals("LocalStrings_de_CH_VENDOR.properties", testFileName);
testFileName = i18nMgr.buildI18nFilename(new Locale("de","CH","VENDOR__" + overlay));
assertEquals("LocalStrings_de_CH_VENDOR__" + overlay + ".properties", testFileName);
}
/**
* Test methods i18nManager.getLocaleOrFallback()
*/
@Test public void testGetLocaleOrFallback() {
// Normal case
Locale locale = i18nMgr.getLocaleOrDefault("de");
assertNotNull(locale);
assertEquals(i18nMgr.getLocaleOrNull("de"), locale);
// Unexisting locale case
locale = i18nMgr.getLocaleOrDefault("xy");
assertEquals(I18nModule.getDefaultLocale(), locale);
// Test trying to get overlay via getLocale method which should not return the overlay
Locale overlay = i18nMgr.getLocaleOrDefault("de__" + I18nModule.getOverlayName());
assertEquals(I18nModule.getDefaultLocale(), overlay);
overlay = i18nMgr.getLocaleOrDefault("zh_CN__" + I18nModule.getOverlayName());
assertEquals(I18nModule.getDefaultLocale(), overlay);
}
/**
* Test methods i18nManager.createLocal()
*/
@Test public void testCreateLocale() {
// standard locale
Locale loc = i18nMgr.createLocale("de");
assertNotNull(loc);
assertEquals("de",loc.getLanguage());
assertEquals("",loc.getCountry());
assertEquals("",loc.getVariant());
// with country
loc = i18nMgr.createLocale("de_CH");
assertNotNull(loc);
assertEquals("de", loc.getLanguage());
assertEquals("CH", loc.getCountry());
assertEquals("", loc.getVariant());
// with variant
loc = i18nMgr.createLocale("de_CH_ZH");
assertNotNull(loc);
assertEquals("de", loc.getLanguage());
assertEquals("CH", loc.getCountry());
assertEquals("ZH", loc.getVariant());
// with variant but no country
loc = i18nMgr.createLocale("de__VENDOR");
assertNotNull(loc);
assertEquals("de", loc.getLanguage());
assertEquals("", loc.getCountry());
assertEquals("VENDOR", loc.getVariant());
//
// With overlay
// with language
String overlay = I18nModule.getOverlayName();
loc = i18nMgr.createLocale("de");
Locale over = i18nMgr.createOverlay(loc);
assertEquals("de____" + overlay, over.toString());
assertEquals(i18nMgr.createOverlayKeyForLanguage(loc.toString()), i18nMgr.getLocaleKey(over));
// with country
loc = i18nMgr.createLocale("de_CH");
over = i18nMgr.createOverlay(loc);
assertEquals("de_CH___" + overlay, over.toString());
assertEquals(i18nMgr.createOverlayKeyForLanguage(loc.toString()), i18nMgr.getLocaleKey(over));
// with variant
loc = i18nMgr.createLocale("de_CH_ZH");
over = i18nMgr.createOverlay(loc);
assertEquals("de_CH_ZH__" + overlay, over.toString());
assertEquals(i18nMgr.createOverlayKeyForLanguage(loc.toString()), i18nMgr.getLocaleKey(over));
}
/**
* Test methods i18nManager.getLanguageTranslated() i18nManager.getLanguageInEnglish()
*/
@Test public void testGetLanguageIn() {
assertEquals("German", i18nMgr.getLanguageInEnglish("de", false));
assertEquals("Deutsch", i18nMgr.getLanguageTranslated("de", false));
assertEquals("English", i18nMgr.getLanguageInEnglish("en", false));
assertEquals("English", i18nMgr.getLanguageTranslated("en", false));
}
/**
* Test methods i18nManager.getLanguageTranslated() i18nManager.getLanguageInEnglish()
*/
@Test public void testGetPropertyFile() {
if (I18nModule.isTransToolEnabled()) {
File baseDir = I18nModule.getPropertyFilesBaseDir(i18nMgr.getLocaleOrDefault("de"), "org.olat.core");
assertNotNull(baseDir);
File file = i18nMgr.getPropertiesFile(i18nMgr.getLocaleOrDefault("de"), "org.olat.core", baseDir);
assertTrue(file.exists());
// test get metadata file
file = i18nMgr.getPropertiesFile(null, "org.olat.core", baseDir);
assertNotNull(file);
try {
file = i18nMgr.getPropertiesFile(i18nMgr.getLocaleOrDefault("de"), null, baseDir);
fail("exception expected for NULL bundle");
} catch (AssertException e) {
// do nothing, expected
}
// test with file that does not exist
file = i18nMgr.getPropertiesFile(i18nMgr.getLocaleOrDefault("de"), "hello.world", baseDir);
assertFalse(file.exists());
}
}
/**
* Test methods i18nManager.getProperties(), i18nManager.saveOrUpdateProperties() and i18nManager.deleteProperties()
*/
@Ignore
@Test public void testGetSaveOrUpdateAndDeleteProperties() {
// test with existing files
Properties props = i18nMgr.getResolvedProperties(i18nMgr.getLocaleOrDefault("de"), "org.olat.core");
assertNotNull(props);
assertTrue(props.size() > 0);
// test with non existing files
String testNewBundle = "org.olat.core.util.i18n.junittestdata.new";
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
File testFile = i18nMgr.getPropertiesFile(testLocale, testNewBundle, baseDir);
// clean first existing files from previous broken testcase
if (testFile.exists()) {
i18nMgr.deleteProperties(testLocale, testNewBundle);
}
props = i18nMgr.getResolvedProperties(testLocale, testNewBundle);
assertNotNull(props);
assertEquals(0, props.size());
// test deleting of non existing
assertFalse(testFile.exists());
i18nMgr.deleteProperties(testLocale, testNewBundle);
assertFalse(testFile.exists());
// test saving of non existing
props.setProperty("test.key", "Hello wörld !");
i18nMgr.saveOrUpdateProperties(props, testLocale, testNewBundle);
assertTrue(testFile.exists());
assertEquals("Hello wörld !", i18nMgr.getLocalizedString(testNewBundle, "test.key", null, testLocale, false, false));
// test saving of existing
props = new Properties();
props.setProperty("hello.world", "&%çest françias, ê alors");
i18nMgr.saveOrUpdateProperties(props, testLocale, testNewBundle);
assertTrue(testFile.exists());
assertEquals("&%çest françias, ê alors", i18nMgr.getLocalizedString(testNewBundle, "hello.world", null, testLocale, false, false));
assertFalse("Hello wörld !".equals(i18nMgr.getLocalizedString(testNewBundle, "test.key", null, testLocale, false, false)));
// test various special cases
props.setProperty("chinesetest", "请选择你的大学");
props.setProperty("specialtest", "that's like \"really\" bad");
props.setProperty("multiline", "bla\tbla\nsecond line");
props.setProperty("html", "<h1>Hello World</h1>");
props.setProperty("empty.property", "");
i18nMgr.saveOrUpdateProperties(props, testLocale, testNewBundle);
i18nMgr.clearCaches();
assertEquals("请选择你的大学", i18nMgr.getLocalizedString(testNewBundle, "chinesetest", null, testLocale, false, false));
assertEquals("that's like \"really\" bad", i18nMgr.getLocalizedString(testNewBundle, "specialtest", null, testLocale, false, false));
assertEquals("bla\tbla\nsecond line", i18nMgr.getLocalizedString(testNewBundle, "multiline", null, testLocale, false, false));
assertEquals("<h1>Hello World</h1>", i18nMgr.getLocalizedString(testNewBundle, "html", null, testLocale, false, false));
assertEquals("", i18nMgr.getLocalizedString(testNewBundle, "empty.property", null, testLocale, false, false));
assertEquals(null, i18nMgr.getLocalizedString(testNewBundle, "not.existing.property", null, testLocale, false, false));
// test deleting of existing
i18nMgr.deleteProperties(testLocale, testNewBundle);
assertFalse(testFile.exists());
assertFalse("Hello wörld !".equals(i18nMgr.getLocalizedString(testNewBundle, "test.key", null, testLocale, false, false)));
assertFalse("&%çest françias, ê alors".equals(i18nMgr.getLocalizedString(testNewBundle, "hello.world", null, testLocale, false, false)));
// clean up
if (testFile.exists()) {
i18nMgr.deleteProperties(testLocale, testNewBundle);
}
if (testFile.getParentFile().exists()) testFile.getParentFile().delete();
}
/**
* Test methods i18nManager.getBundlePriority(), i18nManager.getKeyPriority()
*/
@Test public void testGetBundleAndKeyPriority() {
// existing bundle prios
String bundleName = "org.olat.core.util.i18n.junittestdata";
Properties metadataProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(null, bundleName);
assertNotNull(metadataProperties);
assertTrue(metadataProperties.size() > 0);
assertEquals(900, i18nMgr.getBundlePriority(bundleName));
assertEquals(20, i18nMgr.getKeyPriority(metadataProperties, "no.need.to.translate.this", bundleName));
// default values
bundleName = "org.olat.core.util.i18n.junittestdata.subtest";
metadataProperties = i18nMgr.getPropertiesWithoutResolvingRecursively(null, bundleName);
assertNotNull(metadataProperties);
assertTrue(metadataProperties.size() == 0);
assertEquals(I18nManager.DEFAULT_BUNDLE_PRIORITY, i18nMgr.getBundlePriority("bla.bla")); // default priority
assertEquals(I18nManager.DEFAULT_KEY_PRIORITY, i18nMgr.getKeyPriority(metadataProperties, "no.need.to.translate.this", bundleName));
}
/**
* Test methods i18nManager.getAnnotation()
*/
@Test public void testGetAnnotation() {
// existing bundle prios
String bundleName = "org.olat.core.util.i18n.junittestdata";
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
List<I18nItem> items = i18nMgr.findExistingI18nItems(testLocale, bundleName, false);
for (I18nItem item : items) {
String annotation = i18nMgr.getAnnotation(item);
if (item.getKey().equals("no.need.to.translate.this")) {
assertEquals("this is an annotation", annotation);
} else {
assertNull(annotation);
}
}
}
/**
* Test methods i18nManager.countI18nItems() and i18nManager.countBundles()
*/
@Ignore
@Test public void testCountI18nItemsAndBundles() {
I18nModule.initBundleNames(); // remove dirty stuff from previous tests
int bundleCounter = I18nModule.getBundleNamesContainingI18nFiles().size();
String testNewBundle = "org.olat.core.util.i18n.junittestdata.new";
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
File testFile = i18nMgr.getPropertiesFile(testLocale, testNewBundle, baseDir);
// clean first existing files from previous broken testcase
if (testFile.exists()) {
i18nMgr.deleteProperties(testLocale, testNewBundle);
}
Properties props = i18nMgr.getResolvedProperties(testLocale, testNewBundle);
assertEquals(0, i18nMgr.countI18nItems(testLocale, testNewBundle, true));
assertEquals(0, i18nMgr.countI18nItems(testLocale, testNewBundle, false));
props.setProperty("key.1", "1");
props.setProperty("key.2", "2");
i18nMgr.saveOrUpdateProperties(props, testLocale, testNewBundle);
assertEquals(2, i18nMgr.countI18nItems(testLocale, testNewBundle, false));
assertEquals(0, i18nMgr.countI18nItems(i18nMgr.getLocaleOrDefault("en"), testNewBundle, false));
assertEquals(bundleCounter + 1, I18nModule.getBundleNamesContainingI18nFiles().size());
// test all bundles
int allCount = i18nMgr.countI18nItems(testLocale, null, true);
assertEquals(allCount, i18nMgr.countI18nItems(testLocale, null, false));
props.remove("key.1");
i18nMgr.saveOrUpdateProperties(props, testLocale, testNewBundle);
assertEquals(allCount-1, i18nMgr.countI18nItems(testLocale, null, false));
i18nMgr.deleteProperties(testLocale, testNewBundle);
assertEquals(allCount-2, i18nMgr.countI18nItems(testLocale, null, false));
assertEquals(bundleCounter, I18nModule.getBundleNamesContainingI18nFiles().size());
// count bundles tests
assertEquals(0, i18nMgr.countBundles("org.olat.core.util.i18n.nonexisting", true));
assertEquals(1, i18nMgr.countBundles("org.olat.core.util.i18n.ui", true));
// finds 4: regular: i18n.devtools, i18n.ui;
assertEquals(2, i18nMgr.countBundles("org.olat.core.util.i18n", true));
assertEquals(0, i18nMgr.countBundles("org.olat.core.util.i18n", false));
assertEquals(1, i18nMgr.countBundles("org.olat.core.util.i18n.ui", false));
assertTrue(0 < i18nMgr.countBundles(null, false));
// clean up
if (testFile.exists()) {
i18nMgr.deleteProperties(testLocale, testNewBundle);
}
if (testFile.getParentFile().exists()) {
testFile.getParentFile().delete();
}
}
/**
* Test methods i18nManager.findInKeys() i18nManager.findInValues()
*/
@Test public void testFindInKeysAndFindInValues() {
Locale testLocale = i18nMgr.getLocaleOrDefault("de");
// in keys speedtest
long start = System.currentTimeMillis();
List<I18nItem> foundTransItems = i18nMgr.findI18nItemsByKeySearch("menu", testLocale, testLocale, null, true);
long end = System.currentTimeMillis();
log.info("Searching for term 'menu' took me " + (end-start) + "ms, found " + foundTransItems.size() + " item", "testFindInKeys");
// in values speedtest
start = System.currentTimeMillis();
foundTransItems = i18nMgr.findI18nItemsByValueSearch("OLAT", testLocale, testLocale, null, true);
int uppercaseSize = foundTransItems.size();
end = System.currentTimeMillis();
log.info("Searching for term 'OLAT' took me " + (end-start) + "ms, found " + foundTransItems.size() + " item", "testFindInKeys");
// uppercase and lowercase must find the same values
foundTransItems = i18nMgr.findI18nItemsByValueSearch("olat", testLocale, testLocale, null, true);
assertEquals(uppercaseSize, foundTransItems.size());
// find in values and regexp tests: * is replaced with regexp,
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Eingabefehler aufgetreten", testLocale, testLocale, null, true).size());
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Eingabefehler*aufgetreten", testLocale, testLocale, null, true).size());
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Eingabefe*ler*aufgetreten", testLocale, testLocale, null, true).size());
assertEquals(2, i18nMgr.findI18nItemsByValueSearch("Bitte f*llen Sie dieses Feld aus", testLocale, testLocale, null, true).size());
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Bitte f*llen Sie dieses Feld aus", testLocale, testLocale, "org.olat.core", false).size());
// escape reserved regexp keywords
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("OpenOLAT", testLocale, testLocale, "org.olat.core", false).size());
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("nOLAT", testLocale, testLocale, "org.olat.core", false).size());
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("*learning", testLocale, testLocale, "org.olat.core", false).size());
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Eingaben</i> </br >*<b>bold</b>*<br>_<i>italic</i>_<br>* Listen", testLocale, testLocale, null, true).size());
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("dargestellt werden. Bitte rufen Sie", testLocale, testLocale, null, true).size());
// multi line value search
assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Die Aktion konnte nicht ausgef\u00FChrt werden", testLocale, testLocale, null, true).size());
}
/**
* Test methods i18nManager.findMissingI18nItems()
*/
@Test public void testFindMissingI18nItems() {
Locale sourceLocale = i18nMgr.getLocaleOrDefault("de");
Locale targetLocale = i18nMgr.getLocaleOrDefault("de");
String notExistsTestBundle = "org.olat.core.util.i18n.junittestdata.notexists";
assertEquals(0, i18nMgr.findMissingI18nItems(sourceLocale, targetLocale, null, true).size());
assertEquals(0, i18nMgr.findMissingI18nItems(sourceLocale, targetLocale, notExistsTestBundle, true).size());
assertEquals(0, i18nMgr.findMissingI18nItems(sourceLocale, targetLocale, notExistsTestBundle, false).size());
targetLocale = new Locale("xy");
int total = i18nMgr.findExistingI18nItems(sourceLocale, null, true).size();
assertEquals(total, i18nMgr.findMissingI18nItems(sourceLocale, targetLocale, null, true).size());
assertEquals(total, i18nMgr.findExistingAndMissingI18nItems(sourceLocale, targetLocale, null, true).size());
}
/**
* Test methods i18nManager inline translation tool and InlineTranslationInterceptHandlerController
*/
@Test public void testInlineTranslationReplaceLocalizationMarkupWithHTML() {
// enable inline translation markup
i18nMgr.setMarkLocalizedStringsEnabled(null, true);
Translator inlineTrans = Util.createPackageTranslator(InlineTranslationInterceptHandlerController.class, i18nMgr.getLocaleOrNull("de"));
URLBuilder inlineTranslationURLBuilder = new jUnitURLBuilder();
String testBundle = "org.olat.core.util.i18n.junittestdata";
String testKey = "no.need.to.translate.this";
String rawtext1 = "Lorem impsum<b>nice stuff</b>";
String rawtext2 = "Holderadio <ul>lsdfsdf<y asdf blblb";
String combinedKey = testBundle + ":" + testKey;
// test method that adds identifyers around the translation items
String plainVanillaWrapped = i18nMgr.getLocalizedString(testBundle, testKey, null, i18nMgr.getLocaleOrNull("de"), false, false);
String plainVanillaPlain = "just a test";
Pattern plainVanillaWrappedPattern = Pattern.compile(I18nManager.IDENT_PREFIX + combinedKey + ":([0-9]*?)" + I18nManager.IDENT_START_POSTFIX
+ plainVanillaPlain + I18nManager.IDENT_PREFIX + combinedKey + ":\\1" + I18nManager.IDENT_END_POSTFIX);
Matcher m = plainVanillaWrappedPattern.matcher(plainVanillaWrapped);
assertTrue(m.find());
// test find-replace translator identifyers with HTML markup
StringOutput inlineTransLink = new StringOutput();
String[] args = (combinedKey + ":1000000001").split(":");
InlineTranslationInterceptHandlerController.buildInlineTranslationLink(args, inlineTransLink, inlineTrans, inlineTranslationURLBuilder);
// Plain vanilla text
String convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(plainVanillaWrapped, inlineTranslationURLBuilder, inlineTrans);
assertEquals("<span class=\"o_translation_i18nitem\">" + inlineTransLink.toString() + plainVanillaPlain + "</span>", convertedToHTMLMarkup);
// Simple link
String linkOPEN = "<a href=\"http://www.olat.org/bla/blu:bli#bla\" title='funny title' class=\"o_css O_anothercss\">";
String linkCLOSE = "</a>";
String inlineSpanOPEN = "<span class=\"o_translation_i18nitem\">";
String inlineSpanCLOSE = "</span>";
String translatedWithinLink = linkOPEN + plainVanillaWrapped + linkCLOSE + rawtext1;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedWithinLink, inlineTranslationURLBuilder, inlineTrans);
String convertedWithinLinkExpected = inlineSpanOPEN + inlineTransLink.toString() + linkOPEN + plainVanillaPlain + linkCLOSE + inlineSpanCLOSE + rawtext1;
assertEquals(convertedWithinLinkExpected, convertedToHTMLMarkup);
// Simple link with span
String linkSpanOPEN = "<span class=\"bluber\">";
String linkSpanCLOSE = "</span>";
String translatedWithinLinkAndSpan = rawtext2 + linkOPEN + linkSpanOPEN + plainVanillaWrapped + linkSpanCLOSE + linkCLOSE;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedWithinLinkAndSpan, inlineTranslationURLBuilder, inlineTrans);
String convertedWithinLinkAndSpanExpected = rawtext2 + inlineSpanOPEN + inlineTransLink.toString() + linkOPEN + linkSpanOPEN + plainVanillaPlain + linkSpanCLOSE + linkCLOSE + inlineSpanCLOSE;
assertEquals(convertedWithinLinkAndSpanExpected, convertedToHTMLMarkup);
// Muliple links
String translatedWithinMultipleLinks = translatedWithinLink + translatedWithinLinkAndSpan + translatedWithinLinkAndSpan;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedWithinMultipleLinks, inlineTranslationURLBuilder, inlineTrans);
String convertedWithinMultipleLinksExpected = convertedWithinLinkExpected + convertedWithinLinkAndSpanExpected + convertedWithinLinkAndSpanExpected;
assertEquals(convertedWithinMultipleLinksExpected, convertedToHTMLMarkup);
// Input elements
String inputOPEN = "<input type='submit' class=\"bluber\" value=\"";
String inputCLOSE = "\" />";
String translatedWithinInput = inputOPEN + plainVanillaWrapped + inputCLOSE + rawtext1;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedWithinInput, inlineTranslationURLBuilder, inlineTrans);
String convertedWithinInputExpected = inlineSpanOPEN + inlineTransLink.toString() + inputOPEN + plainVanillaPlain + inputCLOSE + inlineSpanCLOSE + rawtext1;
assertEquals(convertedWithinInputExpected, convertedToHTMLMarkup);
// checkbox elements
String checkboxOPEN = "<input type='submit' class=\"bluber\" type=\"checkbox\" value=\"";
String checkboxCLOSE = "\" />";
String translatedWithinCheckbox = checkboxOPEN + plainVanillaWrapped + checkboxCLOSE + rawtext1;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedWithinCheckbox, inlineTranslationURLBuilder, inlineTrans);
String convertedWithinCheckboxExpected = checkboxOPEN + plainVanillaPlain + checkboxCLOSE + rawtext1;
assertEquals(convertedWithinCheckboxExpected, convertedToHTMLMarkup);
// Input and links mixed
String translatedWithinMultipleLinksAndInput = translatedWithinLink + rawtext1 + translatedWithinInput + translatedWithinLinkAndSpan + rawtext2 + translatedWithinInput + translatedWithinLinkAndSpan;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedWithinMultipleLinksAndInput, inlineTranslationURLBuilder, inlineTrans);
String convertedWithinMultipleLinksAndInputExpected = convertedWithinLinkExpected + rawtext1 + convertedWithinInputExpected + convertedWithinLinkAndSpanExpected + rawtext2 + convertedWithinInputExpected + convertedWithinLinkAndSpanExpected;
assertEquals(convertedWithinMultipleLinksAndInputExpected, convertedToHTMLMarkup);
// Within element attribute
String attributeOPEN = "<a href='sdfsdf' title=\"";
String attributeCLOSE = "\" class=\"o_bluber\">hello world</a>";
String translatedWithinAttribute = attributeOPEN + plainVanillaWrapped + attributeCLOSE + rawtext1;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedWithinAttribute, inlineTranslationURLBuilder, inlineTrans);
String convertedWithinAttributeExpected = attributeOPEN + plainVanillaPlain + attributeCLOSE + rawtext1;
assertEquals(convertedWithinAttributeExpected, convertedToHTMLMarkup);
// Ultimate test
String translatedUltimate = translatedWithinMultipleLinksAndInput + rawtext1 + translatedWithinAttribute + translatedWithinMultipleLinksAndInput + rawtext2 + translatedWithinInput + translatedWithinLinkAndSpan;
convertedToHTMLMarkup = InlineTranslationInterceptHandlerController.replaceLocalizationMarkupWithHTML(translatedUltimate, inlineTranslationURLBuilder, inlineTrans);
String convertedUltimateExpected = convertedWithinMultipleLinksAndInputExpected + rawtext1 + convertedWithinAttributeExpected + convertedWithinMultipleLinksAndInputExpected + rawtext2 + convertedWithinInputExpected + convertedWithinLinkAndSpanExpected;
assertEquals(convertedUltimateExpected, convertedToHTMLMarkup);
// don't do inline translation markup
i18nMgr.setMarkLocalizedStringsEnabled(null, false);
}
/**
* Test method i18nManager.getLocalizedString() with resolvePropertiesInternalKeys()
*/
@Test public void testResolvePropertiesInternalKeys() {
String bundleName = "org.olat.core.util.i18n.junittestdata.subtest";
Locale locale = Locale.GERMAN;
// first tests with cache enabled
i18nMgr.setCachingEnabled(true);
assertEquals("Hello world, this is just a test", i18nMgr.getLocalizedString(bundleName, "recursive.test", null, locale, false, true));
assertEquals("Hello world, this is just a test (dont translate it)", i18nMgr.getLocalizedString(bundleName, "recursive.test2", null, locale, false, true));
// test with . and ,
assertEquals("Hello world, this is just a test. Really dont translate it, because this is just a test.", i18nMgr.getLocalizedString(bundleName, "recursive.test3", null, locale, false, true));
// a combined word
assertEquals("Hello world, this is obersuperduper", i18nMgr.getLocalizedString(bundleName, "recursive.test4", null, locale, false, true));
// a endless loop that can't be resolved
assertEquals("Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop $org.olat.core.util.i18n.junittestdata.subtest:recursive.test5", i18nMgr.getLocalizedString(bundleName, "recursive.test5", null, locale, false, true));
// same tests without cache
i18nMgr.setCachingEnabled(false);
assertEquals("Hello world, this is just a test", i18nMgr.getLocalizedString(bundleName, "recursive.test", null, locale, false, true));
assertEquals("Hello world, this is just a test (dont translate it)", i18nMgr.getLocalizedString(bundleName, "recursive.test2", null, locale, false, true));
// test with . and ,
assertEquals("Hello world, this is just a test. Really dont translate it, because this is just a test.", i18nMgr.getLocalizedString(bundleName, "recursive.test3", null, locale, false, true));
// a combined word
assertEquals("Hello world, this is obersuperduper", i18nMgr.getLocalizedString(bundleName, "recursive.test4", null, locale, false, true));
// a endless loop that can't be resolved
assertEquals("Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop Loop $org.olat.core.util.i18n.junittestdata.subtest:recursive.test5", i18nMgr.getLocalizedString(bundleName, "recursive.test5", null, locale, false, true));
// note: it's ok that the results differ here. Important is that the loop
// eventually terminates. when caching is enabled, the resulst are
// accumulated from the previous iteration, this is different in non-caching
// mode. But this should not have a negative effect on real-world scenarios
i18nMgr.setCachingEnabled(true);
}
/**
* Description:<br>
* Dummy URL builder
* <P>
* Initial Date: 22.09.2008 <br>
* @author gnaegi
*/
private class jUnitURLBuilder extends URLBuilder {
public jUnitURLBuilder() {
super(null, null, null);
}
public void buildURI(StringOutput buf, String[] keys, String[] values) {
buf.append("http://do.test.com");
}
}
}