• Stars
    star
    124
  • Rank 288,207 (Top 6 %)
  • Language
    Scala
  • License
    MIT License
  • Created over 12 years ago
  • Updated 11 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Library to compute localized messages of your Play application on client side

Play JsMessages library Build Status

This library allows you to compute localized messages on client-side, in Play projects.

Basically, play-jsmessages takes the i18n messages of your Play application, sends them to the client-side as a JSON object and defines a JavaScript function returning a message value from a given language and the message key and arguments.

Take a look at the Scala and Java samples to see it in action.

Installation (using sbt)

Add a dependency on the following artifact:

libraryDependencies += "org.julienrf" %% "play-jsmessages" % "5.0.0"

The current 5.0.0 version is compatible with Play 2.8 and Scala 2.12 and 2.13.

Previous versions are available here:

API Documentation

You can browse the online scaladoc.

Quick start

Select which messages you want to support on client-side

Get a JsMessagesFactory

The JsMessagesFactory class is the starting point: it allows you to select which messages of your application you want to support on client-side. You can use all the messages of the application or just a subset of them.

The simplest way to get a JsMessagesFactory is via dependency injection:

import jsmessages.JsMessagesFactory
import javax.inject.Inject

class Application @Inject() (jsMessagesFactory: JsMessagesFactory) extends Controller {

}

The equivalent Java code is the following:

import jsmessages.JsMessagesFactory;
import javax.inject.Inject;

public class Application extends Controller {

  @Inject
  public Application(JsMessagesFactory jsMessagesFactory) {

  }

}

The constructor of the JsMessagesFactory itself needs to be injected a play.api.i18n.MessagesApi parameter. By default, Play defines a binding that uses a play.api.i18n.DefaultMessagesApi, but you can disable this binding if you want to use something else.

For more control, you can also manually instantiate your JsMessagesFactory:

val jsMessagesFactory = new JsMessagesFactory(someMessagesApi)

The equivalent Java code is the following:

JsMessagesFactory jsMessagesFactory = new JsMessagesFactory(someMessagesApi);

Note that, in Scala, you may want to use the JsMessagesFactoryComponents trait that provides a jsMessagesFactory: JsMessagesFactory member using an abstract messagesApi: MessagesApi member.

Select which messages to use

You can either use all your i18n messages:

val jsMessages = jsMessagesFactory.all

Or, just an extensive subset:

val jsMessages = jsMessagesFactory.subset("error.required", "error.number")

Or, finally, an intensive subset:

val jsMessages = jsMessagesFactory.filtering(_.startsWith("error."))

The equivalent Java code of the above expressions are the following:

import jsmessages.JsMessages;
import play.libs.Scala;
JsMessages jsMessages = jsMessagesFactory.all();
JsMessages jsMessages = jsMessagesFactory.subset(Scala.varargs("error.required", "error.number"));
JsMessages jsMessages = jsMessagesFactory.filtering(new scala.runtime.AbstractFunction1<String, Boolean>() {
  @Override
  public Boolean apply(String key) {
    return key.startsWith("error.");
  }
});

Generate a JavaScript asset …

… for the client’s preferred language

Then, you typically want to define an action returning a JavaScript resource containing all the machinery to compute localized messages from client-side, using the client’s preferred lang:

val messages = Action { implicit request =>
  Ok(jsMessages(Some("window.Messages")))
}

Note that for this to work the apply method of jsMessages needs to have an implicit play.api.i18n.Messages value. You can get one by mixing the play.api.i18n.I18nSupport trait in your controller.

Or in Java:

@Inject
private MessagesApi messagesApi;

public Result messages(Http.Request request) {
    return ok(jsMessages.apply(Scala.Option("window.Messages"), this.messagesApi.preferred(request)));
}

The above code creates a Play action that returns a JavaScript program containing the localized messages of the application for the client language and defining a global function window.Messages. This function returns a localized message given its key and its arguments:

console.log(Messages('greeting', 'Julien')); // will print e.g. "Hello, Julien!" or "Bonjour Julien!"

The JavaScript function can also be supplied alternative keys that will be used if the main key is not defined. Keys will be tried in order until a defined key is found:

alert(Messages(['greeting', 'saluting'], 'Julien'));

The JavaScript function stores the messages map in a messages property that is publicly accessible so you can update the messages without reloading the page:

// Update a single message
Messages.messages['greeting'] = 'Hi there {0}!';
// Update all messages
Messages.messages = {
  'greeting': 'Hello, {0}!'
}

… for all the languages

Alternatively, you can use the all method to generate a JavaScript program containing all the messages of the application instead of just those of the client’s current language, making it possible to switch the language from client-side without reloading the page:

val messages = Action {
  Ok(jsMessages.all(Some("window.Messages")))
}

The equivalent Java code is the following:

public Result messages() {
    return ok(jsMessages.all(Scala.Option("window.Messages")));
}

In this case, the generated JavaScript function takes an additional parameter corresponding to the language to use:

console.log(Messages('en', 'greeting', 'Julien')); // "Hello, Julien!"
console.log(Messages('fr', 'greeting', 'Julien')); // "Bonjour Julien!"

Moreover, the messages property of the JavaScript function is a map of languages indexing maps of messages.

The JavaScript function can also be partially applied to fix its first parameter:

val messagesFr = Messages('fr'); // Use only the 'fr' messages
console.log(messagesFr('greeting', 'Julien')); // "Bonjour Julien!"

Note: if you pass undefined as the language parameter, it will use the default messages.

Changelog

  • 5.0.0

    • Play 2.8.x compatibility.
  • 4.0.0

    • Play 2.7.x compatibility, cross-compiled for Scala 2.13.
  • 3.0.0

    • Play 2.6.x compatibility. All tests moved to scalatest+play and dependency injection.
  • 2.0.0

    • Play 2.4.x compatibility.
  • 1.6.2

    • Play 2.3.x compatibility.
  • 1.6.1

    • Fix crash when undefined is passed as the language parameter (thanks to Paul Dijou).
  • 1.6.0

    • Big changes in the API ;
    • Make it possible to return messages of all languages (thanks to Paul Dijou) ;
    • Discard methods returning HTML, keep just JavaScript.
  • 1.5.2

    • Export the messages property on client-side (thanks to Paul Dijou).
  • 1.5.1

    • Play 2.2.x compatibility.
  • 1.5.0

    • Fix the subset method of the Java API (thanks to Seppel Hardt) ;
    • Refactor the whole API in order to make it more extensible (thanks to Jacques Bachellerie).

License

This content is released under the MIT License.

More Repositories

1

play-json-derived-codecs

Scala
192
star
2

scalm

Elm-inspired Scala library for writing web user interfaces
Scala
119
star
3

enum

Scala
68
star
4

effects-without-monads-but-with-dotty

Scala
38
star
5

chooze

Scala
19
star
6

pfe-samples

Code samples of the book Play Framework Essentials
Java
18
star
7

faithful

Lightweight Scala.js promise implementation that does not violate parametricity
Scala
18
star
8

lms-tutorial

Scala
12
star
9

play-jsonp-filter

JSONP filter for Play framework
Scala
11
star
10

mergical

Merge your iCal feeds
JavaScript
10
star
11

composite-ui-play2

Scala
8
star
12

twitterstream

Sample application inspired from the twitterstream Play 2.0 sample
Scala
7
star
13

arrows-typelevel-summit-2017

JavaScript
7
star
14

glitter

Embedded Scala DSL for HTML templates
Scala
7
star
15

play-table

Table module for Play! framework
Java
7
star
16

reactivemongo-derived-codecs

Scala
7
star
17

scala-lessons

Scala
6
star
18

play-products

Scala
6
star
19

di-with-play2

Dependency injection example using Play2
Scala
6
star
20

closely

Find useful amenities (drinking water, waste bin, pharmacy, etc.) close to you
JavaScript
5
star
21

play-macro-templates

Using Scala macros to dynamically call Play templates
Scala
5
star
22

play-custom-pathbinder

Scala
4
star
23

endpoints-problemdetailserrors

Scala
3
star
24

play-forms

Scala
2
star
25

happy-numbers

My solution to the Tony Morris “Happy Numbers” exercise
Scala
2
star
26

dotty-endpoints

Scala
2
star
27

etoffe

Lightweight markup language processor written in Scala
Scala
2
star
28

Alaska

Scala vs Haskell
Haskell
2
star
29

EquiDist

2
star
30

play-table-sample

Sample application for the Play! table module
Java
2
star
31

julienrf.github.com

HTML
2
star
32

jQuery-rant

JavaScript
2
star
33

play-endpoints

Scala
2
star
34

play-modules

Scala
1
star
35

pac-js

JavaScript
1
star
36

play-glitter-sample

Sample application for the Play! glitter module
Scala
1
star
37

blueprintr

Scala
1
star
38

resilience

TeX
1
star
39

play-plovr

Plovr integration into Play! framework 1.x
Java
1
star
40

play-glitter

Glitter module for Play! framework
Scala
1
star
41

pac-gwt

A PAC framework on top of GWT
Java
1
star
42

selector3

JavaScript
1
star
43

tp-scala

Scala
1
star
44

Debate-it

Debate platform
Python
1
star
45

tyco

Reusable components to build web sites
Scala
1
star
46

el

Reduce the boilerplate to build DOM fragments
JavaScript
1
star