Last active
October 26, 2018 13:49
-
-
Save fbaierl/35a981a9849ea44e3d4fde04fbef46ca to your computer and use it in GitHub Desktop.
Java I18n wrapper for scaposer lib (Scala)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// dependencies: | |
// https://mvnrepository.com/artifact/tv.cntt/scaposer | |
// compile group: 'tv.cntt', name: 'scaposer_2.12', version: '1.11.0' | |
package internationalization; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import scala.collection.Seq; | |
import scala.util.Either; | |
import scaposer.ParseFailure; | |
import scaposer.Parser$; | |
import scaposer.Translation; | |
import java.io.File; | |
import java.io.IOException; | |
import java.nio.charset.Charset; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
import java.util.*; | |
public final class I18n { | |
private static final Logger LOG = LoggerFactory.getLogger(I18n.class); | |
/** | |
* The current language to translate to. | |
*/ | |
private static Locale _currentLocale = Locale.ENGLISH; | |
private static Map<Locale, scaposer.I18n> _dictionaries = new HashMap<>(); | |
/** | |
* Selects the current language as the default language to translate to. | |
* @param locale target language | |
*/ | |
public static void select(Locale locale){ | |
_currentLocale = locale; | |
} | |
public static String t(String singular){ | |
if(_dictionaries.containsKey(_currentLocale)){ | |
return _dictionaries.get(_currentLocale).t(singular); | |
} | |
return singular; // fallback | |
} | |
public static String tc(String ctx, String singular){ | |
if(_dictionaries.containsKey(_currentLocale)){ | |
return _dictionaries.get(_currentLocale).tc(ctx, singular); | |
} | |
return singular; // fallback | |
} | |
public static String tn(String singular, String plural, Long n) { | |
if(_dictionaries.containsKey(_currentLocale)){ | |
return _dictionaries.get(_currentLocale).tn(singular, plural, n); | |
} | |
return (n != 1) ? plural : singular; // fallback | |
} | |
public static String tcn(String ctx, String singular, String plural, Long n){ | |
if(_dictionaries.containsKey(_currentLocale)){ | |
return _dictionaries.get(_currentLocale).tcn(ctx, singular, plural, n); | |
} | |
return (n != 1) ? plural : singular; // fallback | |
} | |
public static Locale localeFromFileName(String fileName){ | |
String[] ns = fileName.split("\\."); | |
return Locale.forLanguageTag(ns[0]); | |
} | |
/** | |
* Loads all *.po files from the given <code>path</code>. | |
* <p> | |
* The files should follow this naming convention: | |
* <br> | |
* <code>*language_code*.*name*.po</code> | |
* <nr | |
* *name* is optional | |
* <br> | |
* example: <code>de.myComponent.po</code> & <code>de.myOtherComponent.po</code> & <code>de.po</code> | |
* </p> | |
* @param path the path to search for language files for | |
*/ | |
public static void init(String path){ | |
File dir = new File(path); | |
if(!dir.isDirectory()){ | |
throw new IllegalArgumentException("Path needs to point to a directory."); | |
} | |
String[] fileNames = dir.list((dir1, name) -> name.endsWith(".po")); | |
if(fileNames == null || fileNames.length == 0){ | |
LOG.warn("No translation files (*.po) found."); | |
return; | |
} | |
initPoFiles(path, fileNames); | |
} | |
private static void initPoFiles(String path, String[] fileNames){ | |
_dictionaries.clear(); | |
for(String name: fileNames){ | |
try { | |
Locale loc = localeFromFileName(name); | |
scaposer.I18n i18n = readPoFile(path + File.separator + name); | |
if(_dictionaries.containsKey(loc)){ | |
// if a dictionary already exists, combine them | |
_dictionaries.put(loc, _dictionaries.get(loc).$plus$plus(i18n)); | |
} else { | |
_dictionaries.put(loc, i18n); | |
} | |
} catch (IOException e) { | |
LOG.error("Error while reading translation file: " + path); | |
} catch (PoParseFailure poParseFailure) { | |
LOG.error("Error while parsing translation file: " + path + "; Error: " + poParseFailure.getMessage()); | |
} | |
} | |
} | |
private static scaposer.I18n readPoFile(String pathToFile) throws IOException, PoParseFailure { | |
byte[] encoded = Files.readAllBytes(Paths.get(pathToFile)); | |
String fileContent = new String(encoded, Charset.forName("UTF-8")); | |
return parsePoFile(fileContent); | |
} | |
private static scaposer.I18n parsePoFile(String fileContent) throws PoParseFailure { | |
final Either<ParseFailure, Seq<Translation>> parseFailureSeqEither = Parser$.MODULE$.parse(fileContent); | |
if(parseFailureSeqEither.isRight()){ | |
Seq<Translation> translationSeq = parseFailureSeqEither.right().get(); | |
return scaposer.I18n.apply(translationSeq); | |
}else { | |
throw new PoParseFailure (parseFailureSeqEither.left().toString()); | |
} | |
} | |
private static class PoParseFailure extends Exception { | |
PoParseFailure (String message) { | |
super(message); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment