Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ul
- import java.{io, util}
- import collection.mutable.{HashMap};
- /**
- * Gettext support class
- * @param root translations root directory
- * @param domain translation domain (typically 'messages' or program name)
- * @param category translation category (typically "MESSAGES")
- * @param lang current translation language (default "en")
- * @param langDef original language (default "en")
- */
- class GetText(
- var root: String = "./locale",
- var domain: String = "messages",
- var category: String = "MESSAGES",
- var lang: String = "en",
- var langDef: String = "en"
- ) {
- /**
- * Translations catalog map in format [lang => [str => [tran1,...tranN]]]
- */
- val cat = new HashMap[String, HashMap[String, Array[Array[String]]]];
- load; // load/parse catalog
- /** Load all translations from root directory */
- def load:GetText = {
- try {
- for (langDir <- new io.File(root).list if (new io.File(root + io.File.separator + langDir).isDirectory)) { //iterate over all dirs in root
- try {
- println("Loading: " + (root + io.File.separator + langDir + io.File.separator +
- "LC_" + category + io.File.separator + domain + ".mo"))
- //try to load and parse .MO file
- val moBytes = scala.io.Source.fromFile(
- root + io.File.separator + langDir + io.File.separator +
- "LC_" + category + io.File.separator + domain + ".mo",
- "ISO-8859-1"
- ).map(_.toByte ).toArray;
- val moCat = parseMO( moBytes )
- cat(langDir) = moCat
- } catch { case _:Throwable => }
- }
- } catch { case _:Throwable => }
- this
- }
- /**
- * Parse .MO file contents
- * @param mo file contents in byte array
- * @return translations map
- */
- def parseMO( mo:Array[Byte] ):HashMap[String, Array[Array[String]]] = {
- val lcat = new HashMap[String, Array[Array[String]]];
- if (mo.length > 24) {
- // check magick for msb/lsb
- val magick = (((mo(0) & 0xff) * 256 + (mo(1) & 0xff)) * 256 + (mo(2) & 0xff)) * 256 + (mo(3) & 0xff);
- val msb = magick == 0x950412deL;
- if ((magick == 0x950412de) || (magick == 0xde120495)) {
- def u32( i:Int ):Int = if (msb)
- ((((mo(i) & 0xff) * 256 + (mo(i+1) & 0xff)) * 256 + (mo(i+2) & 0xff)) * 256 + (mo(i+3) & 0xff));
- else
- ((((mo(i+3) & 0xff) * 256 + (mo(i+2) & 0xff)) * 256 + (mo(i+1) & 0xff)) * 256 + (mo(i) & 0xff));
- val rev = u32(4); // revision
- val (revMaj, revMin) = (rev >> 16, rev % 65536); // major/minor revision
- // number of strings, offsets of original and translation strings tables
- val (sn, oto, ott) = (u32(8), u32(12), u32(16));
- if (sn > 1 && revMaj <= 1 && revMin <= 1) {
- for (sc <- 1 to sn-1) { // process all strings
- // original string(s) length, offset
- val (osl, oso) = ( u32( oto + 8 * sc ), u32( oto + 8 * sc + 4 ) );
- // translation string(s) length, offset
- val (tsl, tso) = ( u32( ott + 8 * sc ), u32( ott + 8 * sc + 4 ) );
- if (osl > 0 && tsl > 0) {
- // original string(s)
- val os = mo.slice( oso, oso + osl + 1);
- // extract all original forms
- var (oss, ossp) = (List[String](), 0);
- for (i <- 0 to os.length-1) {
- if ( os(i) == 0 ) {
- oss = oss ::: new String(os.slice(ossp, i), "utf8") :: Nil;
- ossp = i + 1;
- }
- }
- // translation string(s)
- val ts = mo.slice( tso, tso + tsl + 1);
- // extract all translation forms
- var (tss, tssp) = (List[String](), 0);
- for (i <- 0 to ts.length-1) {
- if ( ts(i) == 0 ) {
- tss = tss ::: new String(ts.slice(tssp, i), "utf8") :: Nil;
- tssp = i + 1;
- }
- }
- lcat( oss(0) ) = Array( oss.toArray, tss.toArray );
- }
- }
- }
- }
- }
- return lcat
- }
- /**
- * Parse .PO file
- * @param po sequence of strings from file
- * @return translations map
- */
- def parsePo( po:Seq[String] ): HashMap[String, Array[String]] = {
- val lcat = new HashMap[String, Array[String]];
- /* tranMap.clear // clear map
- localeDir = aLocaleDir
- domainName = aDomainName
- // search for translations
- try {
- for (langDir <- new File(localeDir).list()) {
- try {
- val poFile = new File(localeDir + File.separator + langDir + File.separator +
- messagesDir + File.separator + domainName + ".po")
- val moFile = new File(localeDir + File.separator + langDir + File.separator +
- messagesDir + File.separator + domainName + ".mo")
- if (poFile.exists()) { // parse .po file
- tranMap(langDir) = new HashMap[String, String]()
- val fi = new FileInputStream( poFile )
- val din = new Array[Byte](poFile.length().toInt)
- fi.read( din ); fi.close()
- val poStr = new String(din, poEncoding)
- val poRe = "(?msu:msgid +\"(.*?)\".*?msgstr +\"(.*?)\")".r
- for (m <- poRe.findAllIn( poStr ).matchData if ((m.groupCount == 2)&&(m.group(1).length > 0)))
- tranMap(langDir)(m.group(1)) = m.group(2);
- } else if (moFile.exists()) { // parse .mo file
- }
- } catch { case _=> if (logger != null) logger.log("Error loading localization directory " + langDir + ".") }
- }
- } catch { case _=> if (logger != null) logger.log("Error loading localization.") }
- */
- return lcat;
- }
- /**
- * Translation function
- * @param s original string
- * @param pl plural form
- * @param aLang translation language
- * @return translated string
- */
- def tr( s: String, pl: Int, aLang: String ): String = {
- try {
- return cat(aLang)(s)(1)(pl-1);
- } catch {
- case _:Throwable => return s;
- }
- }
- /**
- * Translation function
- * @param s original string
- * @param pl plural form
- * @return translated string
- */
- def tr( s: String, pl: Int ): String = { /// translation function
- try {
- return cat(lang)(s)(1)(pl-1);
- } catch {
- case _:Throwable => return s;
- }
- }
- /**
- * Translation function
- * @param s original string
- * @return translated string
- */
- def tr( s: String ): String = { /// translation function
- try {
- return cat(lang)(s)(1)(0);
- } catch {
- case _:Throwable => return s;
- }
- }
- def langs: Seq[String] = langDef :: (for ((l,t) <- cat) yield l).toList;
- def lang(l:String):String = {
- if (langs.contains(l)) l
- else if (displayLangs.contains(l)) langs(displayLangs.indexOf(l))
- else ""
- }
- def lang(l:Int):String = langs(l);
- def displayLangs:Seq[String] =
- (for (l <- langs) yield {
- val ls = l.split("_");
- val loc = if (ls.length == 1) new util.Locale(l) else new util.Locale(ls(0), ls(1));
- loc.getDisplayName(loc).capitalize;
- });
- def displayLang(l:String):String = {
- if (langs.contains(l)) displayLangs(langs.indexOf(l))
- else if (displayLangs.contains(l)) l
- else ""
- }
- def displayLang(l:Int):String = displayLangs(l);
- def langIndex(l:String):Int = {
- if (langs.contains(l)) langs.indexOf(l)
- else if (displayLangs.contains(l)) displayLangs.indexOf(l)
- else -1
- }
- }
- object GetText {
- var tran:GetText = null;
- def tr(s:String):String = {
- if (tran == null) s else tran.tr(s)
- }
- def lang = tran.lang
- def lang_=(l:String) = {tran.lang = l}
- def langs = tran.langs
- def load(path:String, domain:String, category:String, lang:String, langDef:String) = {
- tran = new GetText(path, domain, category, lang, langDef);
- }
- def load(path:String):Unit = {
- load(path, "messages", "MESSAGES", "en", "en")
- }
- def load:Unit = load("./locale");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement