Git Product home page Git Product logo

scalingua's Introduction

Scalingua Build Status Latest version Join the chat at https://gitter.im/makkarpov/scalingua

Have you ever wondered that there is no gettext-like library for Scala? Scalingua is here to fix it! It comes with lightweight runtime library and full-featured compile-time macros and SBT plugin that will combine the powers of gettext and Scala in a single library.

Scalingua consists of four modules:

  • core — a minimal runtime components for internationalization. It's very lightweight (~ 30 kB) and provides basic functions like loading precompiled translations.
  • scalingua itself — library with macros that have these features:
    • String interpolator that makes internationalization of strings as easy as writing one letter before them;
    • Plural string interpolator that adds plural suffixes for you;
    • Macros for strings with contexts (msgctxt) and plural strings;
    • Macros leaves no dependency on scalingua library — you can include it in provided scope and it will not break anything;
    • Macros will extract all your strings to separate *.pot file every compilation run and keep this file up-to-date with during incremental compilation;
    • You can translate more complex formats like HTML — all placeholders will be escaped, so no XSS attacks are possible;
    • You can re-use existing macros from this library to implement custom translation utilities (e.g. create th interpolator that will translate HTML) or move I18n method to your Utils object, but in this case you will have dependency on scalingua
  • scalingua-sbt — SBT plugin with small but important task:
    • Automatically sets compiler parameters so you don't have to remember them;
    • Parses *.po files and compiles them to efficient binary files and Scala classes.
  • scalingua-play — Integration module for Play framework:
    • Dependency injection bindings to summon Messages through DI;
    • HTML output format with ready to use functions and interpolators;
    • Extraction of visitor language from request headers.

Getting started

scalingua's People

Contributors

funivan avatar makkarpov avatar olegych avatar przemekd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

scalingua's Issues

' (single quote) should not be escaped

eg a string like

t""" 'hello' """

produces a

msgstr " \'hello\' "

which is causing problems when loading the file with scaposer or saving file with poedit

Plural string interpolator

Since English plural version usually differs only in the suffix on one word, it's obvious to introduce interpolator that will expand to two strings, either detecting suffix from string like:

p"I have $n fox[es]"

Or by using specific pre-defined constants like:

case class Suffix(s: String)
object Suffix {
  val es = Suffix("es")
  val s = Suffix("s")
}

And use them later like:

p"I have $n fox$es"

Another issue is to distinguish n variable from all others. One possible solution is to create implicit class

implicit class LongExtension(val l: Long) extends AnyVal {
  @compileTimeOnly("All .nVar invocations should be removed at macros")
  def nVar: Long = throw new IllegalStateException("All .nVar invocations should be removed at macros")
}

And either detect n variable unambiguously (if there is only one number variable used in the interpolator) or annotate correct variable using .nVar suffix which will be matched by macros. If Scala supports annotations like p"Test ${n @nVar}" then it would be nice, but I haven't checked it yet.


Since English is not my native language, I may miss something. In this case — let me know, suggestions are always welcome.

Failure parsing .po files in SBT

[error] Caused by: java.lang.NoSuchMethodError: java_cup.runtime.SymbolFactory.newSymbol(Ljava/lang/String;ILjava_cup/runtime/Symbol;Ljava/lang/Object;)Ljava_cup/runtime/Symbol;
[error] 	at ru.makkarpov.scalingua.pofile.parse.PoParser$CUP$PoParser$actions.CUP$PoParser$do_action_part00000000(PoParser.java:427)
[error] 	at ru.makkarpov.scalingua.pofile.parse.PoParser$CUP$PoParser$actions.CUP$PoParser$do_action(PoParser.java:479)
[error] 	at ru.makkarpov.scalingua.pofile.parse.PoParser.do_action(PoParser.java:125)
[error] 	at java_cup.runtime.lr_parser.parse(lr_parser.java:699)
[error] 	at ru.makkarpov.scalingua.pofile.PoFile$.apply(PoFile.scala:52)
[error] 	at ru.makkarpov.scalingua.pofile.PoFile$.apply(PoFile.scala:48)
[error] 	at ru.makkarpov.scalingua.plugin.PoCompiler$.$anonfun$doCompiling$1(PoCompiler.scala:145)
[error] 	at ru.makkarpov.scalingua.plugin.PoCompiler$.catchErrors(PoCompiler.scala:69)
[error] 	at ru.makkarpov.scalingua.plugin.PoCompiler$.doCompiling(PoCompiler.scala:144)
[error] 	at ru.makkarpov.scalingua.plugin.Scalingua$.$anonfun$compileLocalesTask$1(Scalingua.scala:188)
[error] 	at ru.makkarpov.scalingua.plugin.Scalingua$.$anonfun$compileLocalesTask$1$adapted(Scalingua.scala:188)
[error] 	at ru.makkarpov.scalingua.plugin.Scalingua$.$anonfun$withGenContext$3(Scalingua.scala:157)
[error] 	at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
[error] 	at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
[error] 	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
[error] 	at ru.makkarpov.scalingua.plugin.Scalingua$.$anonfun$withGenContext$1(Scalingua.scala:151)
...

I'm using sbt version 1.1.4 with

addSbtPlugin("ru.makkarpov" % "scalingua-sbt" % "0.8.1")

in my plugins.sbt. And

.enablePlugins(Scalingua)
.settings(
...
  libraryDependencies += "ru.makkarpov" %% "scalingua" % "0.8.1",
...
)

in my build.sbt

Resource not found for language ...

I created in IDEA new empty project.

  • plugins.sbt: addSbtPlugin("ru.makkarpov" %% "scalingua-sbt" % "1.1.1")
  • dependency and plugin:
ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.10"

lazy val root = (project in file("."))
  .enablePlugins(Scalingua)
  .settings(
    name := "scala-i18n",
    libraryDependencies += "ru.makkarpov" %% "scalingua" % "1.1.1"
  )
  • implicits:
object SomeGlobal {
  implicit val messages = Messages.compiled()
  implicit val langId = LanguageId("ru-RU")
  implicit val language = Language.$providedLanguage
}
  • Main:
import SomeGlobal._
import ru.makkarpov.scalingua.I18n._

object Main {
  def main(args: Array[String]): Unit = {
    val name = "leonid"
    println(t"Hello $name!")
  }
}
  • po files:

image

i have next problem when run application:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at Main$.main(Main.scala:7)
	at Main.main(Main.scala)
Caused by: java.lang.IllegalArgumentException: Resource not found for language ru_RU
	at locales.Language_ru_RU$.<clinit>(Language_ru_RU.scala:12)
	at locales.Languages$.<init>(Languages.scala:8)
	at locales.Languages$.<clinit>(Languages.scala:7)
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1155)
	at java.base/jdk.internal.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:42)
	at java.base/jdk.internal.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:185)
	at java.base/java.lang.reflect.Field.acquireFieldAccessor(Field.java:1132)
	at java.base/java.lang.reflect.Field.getFieldAccessor(Field.java:1113)
	at java.base/java.lang.reflect.Field.get(Field.java:425)
	at org.portablescala.reflect.LoadableModuleClass.loadModule(LoadableModuleClass.scala:17)
	at ru.makkarpov.scalingua.Messages$.compiled(Messages.scala:32)
	at SomeGlobal$.<clinit>(SomeGlobal.scala:4)
	... 2 more

would you suggest what i am doing wrong?

java 8 (52)

I tried to compile under 8 JVM and got the following error:

[info] welcome to sbt 1.8.0 (Amazon.com Inc. Java 1.8.0_352)
...
[IJ] compile
...
[error] java.lang.UnsupportedClassVersionError: ru/makkarpov/scalingua/pofile/parse/PoParser has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0

is it possible to build scalingua for java 8?

Play! integration module

Even if it will be a very simple, it is needed to avoid writing functions like RequestHeader => Language and HTML output format by hand every time.

  • Implicit conversion from RequestHeader to LanguageId
  • OutputFormat[Html]
  • Injectable Messages
  • Separate I18n object that will contain interpolators for HTML and implicits for LanguageId.
  • Tests for all above.

Module should be placed under "ru.makkarpov" % "scalingua-play" % "x.x.x". Each version should target one specific Play! version, and version list should be maintained at README.md file.

  • Update README.md

Scala.js support?

I am wondering if it's possible to add Scala.js support for this library?

msgcat fails with input file 'target/i18n/scala.pot' doesn't contain a header entry with a charset specification

As a part of our build process we concatenate the extracted Scala strings with strings extracted from JS files. It seems like msgcat is expecting to see something like:

msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"

At the top of the file. That is what the JS extractor adds and if I add it to the scala.pot file msgcat seems to work correctly.

Any chance you can add something along those lines as a standard header?

Testing of PoFile and SBT plugins

Definitely needed to do some testing of PoFile (which ScalaTest could do perfectly, but I too lazy to create it) and of SBT plugins (which needs external scripts to do tests correctly).

  • PoFile
  • SBT plugin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.