First question: how can I retrieve the translation of a text in a controller?
Second question: how can I retrieve the translation of a text in a template?
The api says that there is a .get method that translates a message:
http://www.playframework.org/documentation/api/2.0/java/play/i18n/Messages.html
However my application does not recognize this method. Opening in eclipse the Message.class shows that there is an .apply method in it, written in Scala and Java!?
object Messages {
/**
* Translates a message.
*
* Uses `java.text.MessageFormat` internally to format the message.
*
* #param key the message key
* #param args the message arguments
* #return the formatted message or a default rendering if the key wasn’t defined
*/
def apply(key: String, args: Any*)(implicit lang: Lang): String = {
Play.maybeApplication.flatMap { app =>
app.plugin[MessagesPlugin].map(_.api.translate(key, args)).getOrElse(throw new Exception("this plugin was not registered or disabled"))
}.getOrElse(noMatch(key, args))
}
Now eclipse tells me that I can invoke this method like this:
> String play.api.i18n.Messages.apply(String arg0, Seq<Object> arg1,
> Lang arg2)
But what should I enter as the "Seq" argument?
--The solution--
The problem was that I imported play.api.i18n.Messages instead of play.i18n.Messages ...
Having defined two message files (messages.de-DE and messages.en-UK) and using the following code everything works fine:
Controller:
import play.i18n.Messages;
import play.api.i18n.Lang;
Lang en = new Lang("en","GB");
play.i18n.Lang en_lang = new play.i18n.Lang(en);
Lang de = new Lang("de", "DE");
play.i18n.Lang de_lang = new play.i18n.Lang(de);
Logger.info(Messages.get("home.title"));
Logger.info(Messages.get(en_lang, "home.title"));
Logger.info(Messages.get(de_lang, "home.title"));
application.conf
application.langs="en-GB,de-DE"
Getting the translation inside the controller:
// in messages file
msg.key=Hello Translation
// in you controller
Messages.get("msg.key");
You can even pass parameters:
// in messages file
msg.key=Hello {0}, here is your translation
//in controller
Messages.get("msg.key", User.firstName);
From the view you can use: Messages("msg.key")
You can even apply HTML formatting (only applicable for views of course):
// in messages file
msg.key=Hello <strong>{0}</strong>, here is your translation
// in controller
Messages.get("msg.key", User.firstName);
//in view
#Html(objectInView)
Please note the following:
Currently it is not possible to define the language explicitly, see bug report: https://play.lighthouseapp.com/projects/82401/tickets/174-20-i18n-add-ability-to-define-implicit-lang-for-java-api
Similar question was asked before:
Access translated i18n messages from Scala templates (Play! Internationalization)
i18n error: controller and templates uses different implicit languages
Related
I am using adempiere 380 webui, i would like to show error message on any failure of adempiere process or onComplete of any document.
The code which i have written to show error popup working in desktop application. But in webui - jboss it printing in console of jboss.
I have accomplished this using AbstractADWindowPanel.java where i am checking process id or table then execute particular code in that and if error codition is true then i am displaying FDialog.ask("Print Message"); .
Is there any generic way to do this by which it can be used for all classes.
Since processes can be fully automated and run on the server, your code needs to be aware of the GUI being used so that the correct dialog script can be called. There are three options, a server process (no dialog), swing (ADialog) or ZK (FDialog). Generally, its discouraged to use dialogs in this way. Certainly, you wouldn't want a server process to block waiting for user input. But, if you know what your doing and really need to...
In the most recent releases, the process code includes a flag that tests which of the states its in so it can display errors. An example of how this is used is with the Migration Script saves to XML format. In the process, the GUI info is used to open the correct file dialog in swing or, in ZK, pass the request to the browser.
Here is a snippet of how it works from ProcessInfo.java in the current release
/**
* Get the interface type this process is being run from. The interface type
* can be used by the process to perform UI type actions from within the process
* or in the {#link #postProcess(boolean)}
* #return The InterfaceType which will be one of
* <li> {#link #INTERFACE_TYPE_NOT_SET}
* <li> {#link #INTERFACE_TYPE_SWING} or
* <li> {#link #INTERFACE_TYPE_ZK}
*/
public String getInterfaceType() {
if (interfaceType == null || interfaceType.isEmpty())
interfaceType = INTERFACE_TYPE_NOT_SET;
return interfaceType;
}
/**
* Sets the Interface Type
* #param uiType which must equal one of the following:
* <li> {#link #INTERFACE_TYPE_NOT_SET} (default)
* <li> {#link #INTERFACE_TYPE_SWING} or
* <li> {#link #INTERFACE_TYPE_ZK}
* The interface should be set by UI dialogs that start the process.
* #throws IllegalArgumentException if the interfaceType is not recognized.
*/
public void setInterfaceType(String uiType) {
// Limit value to known types
if (uiType.equals(INTERFACE_TYPE_NOT_SET)
||uiType.equals(INTERFACE_TYPE_ZK)
||uiType.equals(INTERFACE_TYPE_SWING) )
{
this.interfaceType = uiType;
}
else
{
throw new IllegalArgumentException("Unknown interface type " + uiType);
}
}
The call to setInterfaceType() is made when the process is launched by the ProcessModalDialog in swing or the AbstractZKForm or ProcessPanel in zk.
For other processes, the value is set by the AbstractFormController which is used by both interfaces. If the interface type is not set the loadProcessInfo method will try to figure it out as follows:
// Determine the interface type being used. Its set explicitly in the ProcessInfo data
// but we will fallback to testing the stack trace in case it wasn't. Note that the
// stack trace test may not be accurate as it depends on the calling class names.
// TODO Also note that we are only testing for ZK or Swing. If another UI is added, we'll
// have to fix this logic.
if (processInfo == null || processInfo.getInterfaceType().equals(ProcessInfo.INTERFACE_TYPE_NOT_SET))
{
// Need to know which interface is being used as the events may be different and the proper
// listeners have to be activated. Test the calling stack trace for "webui".
// If not found, assume the SWING interface
isSwing = true;
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
for (int i=1; i<stElements.length; i++) {
StackTraceElement ste = stElements[i];
if (ste.getClassName().contains("webui")
|| ste.getClassName().contains("zk.ui")) {
isSwing = false;
break;
}
}
log.warning("Process Info is null or interface type is not set. Testing isSwing = " + isSwing);
}
else
{
isSwing = processInfo.getInterfaceType().equals(ProcessInfo.INTERFACE_TYPE_SWING);
}
Finally, this can be used to control the dialogs within your process with a call similar to
if (ProcessInfo.INTERFACE_TYPE_SWING.equals(this.getProcessInfo().getInterfaceType()))
{
... Do something on a swing...
}
else ...
This post is about exposing C++ objects to the v8 javascript engine. To attach a C++ object to a javascript object, I make use of the GetInternalField() and External APIs. Before you can set or get any internal field, you have to call SetInternalFieldCount() on the corresponding ObjectTemplate. Since I want to expose a constructor function to the JS, I created a FunctionTemplate, set a C++ function that attache the native object to the JS object to that template, and finally SetInternalCount() on the InstanceTemplate() of that function template. Too much words for the description, here is what I did:
struct Point {
int x, y;
Local<FunctionTemplate> CreatePointContext(Isolate* isolate) {
Local<FunctionTemplate> constructor = FunctionTemplate::New(isolate, &ConstructorCallback);
constructor->InstanceTemplate()->SetInternalFieldCount(1); // I set internal field count here.
constructor->SetClassName(String::NewFromUtf8(isolate, "Point", NewStringType::kInternalized).ToLocalChecked());
auto prototype_t = constructor->PrototypeTemplate();
prototype_t->SetAccessor(String::NewFromUtf8(isolate, "x", NewStringType::kInternalized).ToLocalChecked(),
XGetterCallback);
return constructor;
};
// This callback is bound to the constructor to attach a C++ Point instance to js object.
static void ConstructorCallback(const FunctionCallbackInfo<Value>& args) {
auto isolate = args.GetIsolate();
Local<External> external = External::New(isolate, new Point);
args.Holder()->SetInternalField(0, external);
}
// This callback retrieves the C++ object and extract its 'x' field.
static void XGetterCallback(Local<String> property, const PropertyCallbackInfo<Value>& info) {
auto external = Local<External>::Cast(info.Holder()->GetInternalField(0)); // This line triggers an out-of-bound error.
auto point = reinterpret_cast<Point*>(external->Value());
info.GetReturnValue().Set(static_cast< double>(point->x));
}
// This function creates a context that install the Point function template.
Local<Context> CreatePointContext(Isolate* isolate) {
auto global = ObjectTemplate::New(isolate);
auto point_ctor = Point::CreateClassTemplate(isolate);
global->Set(isolate, "Point", point_ctor);
return Context::New(isolate, nullptr, global);
}
When I tried to run the following JS code with the exposed C++ object, I got Internal field out of bounds error.
var p = new Point();
p.x;
I wonder setting internal field count on the instance template of a function template has nothing to do with the object created by the new expression. If so, what is the correct way to set the internal field count of the object created by new while exposing the constructor function to javascript? I want to achieve the following 2 things:
In javascript, a Point function is avaible so we can var p = new Point;.
In C++ I can make sure the JS object has 1 internal field for our C++ Point to live in.
Edit: As #snek pointed out, I changed Holder() to This() and everything started to work. But later When I changed SetAccessor to SetAccessorProperty, it worked even with Holder.
Although the behaviour are very confusing, I think the major problem may not lie in the difference between Holder and This, but rather in SetAccessor and SetAccessorProperty. Why? Because in many docs I have read, Holder should be identical to This in most cases and I believe without using Signature and given that my testing js code is so simple (not with any magic property moving), in my case This should just be Holder.
Thus I decided to post another question about SetAccessor and SetAccessorProperty and leave this post as a reference.
For why I am so sure about in my case This() == Holder() should hold, here are some old threads:
https://groups.google.com/forum/#!topic/v8-users/fK9PBWxJxtQ
https://groups.google.com/forum/#!topic/v8-users/Axf4hF_RfZo
And what does the docs say?
/**
* If the callback was created without a Signature, this is the same
* value as This(). If there is a signature, and the signature didn't match
* This() but one of its hidden prototypes, this will be the respective
* hidden prototype.
*
* Note that this is not the prototype of This() on which the accessor
* referencing this callback was found (which in V8 internally is often
* referred to as holder [sic]).
*/
V8_INLINE Local<Object> Holder() const;
Note in my code there is not Signature, literally. So This and Holder should make no difference, but with SetAccessor, they made a difference.
I am using csv file for posting the data and checking the response back, where in find text, i want to use the same csv files.
In string body im using :{{DataSource1.Table#csv.objectId}} which is working fine for posting request.
same thing i passed in find text in validation rule, it doesn't work and i am getting failure for this validation rule.
In validation rule, i am using "Find Text" and passing {{DataSource1.Table#csv.objectId}}
The "Details" tab show this for the validation rule :
Find Text Validation The required text '{{DataSource1.Table#csv.objectId}}' did not appear in the HTML response. FindText={{DataSource1.Table#csv.objectId}}, IgnoreCase=True, UseRegularExpression=True, PassIfTextFound=True
Tried using custom validation rule and tried passing context parameter.Same issue.Validation rule for it is below:
Many places where a ".webtest" allows a context parameter (CP) have a "bind" facility on the property. For example, look at the Value property of a "Header" to a request, it has a drop-down list giving access to CPs.
Some properties of a ".webtest" allow CPs to be embedded in the text. For example the Url property of a request allows things like text{{CpOne}}moretext{{CpTwo}}etc.
Unfortunately there are some properties of a ".webtest" that only allow text and do not expand embedded CPs. I have not found any clear statement of which places allow bound CPs, which support embedded CPs and which allow neither. Also I have not found any built in support for CPs in user-written plugins or extraction rules or validation rules. My approach has been to try using CPs wherever I need them and, when they do not work, write my own code that does what is needed.
You might write your own validation rule as described in this Microsoft page. The code could be based on the following code which has not been tested.
public class FindCpValueInResponseBody : ValidateResponseUrl
{
public string CpWithTextToFind { get; set; }
public override void Validate(object sender, ValidationEventArgs e)
{
string TextToFind = e.WebTest.Context[CpWithTextToFind].ToString();
e.WebTest.AddCommentToResult("Looking for '" + TextToFind +"' (from CP '" + CpWithTextToFind + "').");
if (e.Response.BodyString.Contains(TextToFind))
{
e.IsValid = true;
e.Message = "Text '" + TextToFind + "' found.";
}
else
{
e.IsValid = false;
e.Message = "Text '" + TextToFind + "' not found.";
}
}
}
It should be a simple matter to enhance the above method to add the other properties of the built-in FindText validation rule; properties such as Pass if text found and Ignore case etc, should they be needed.
The above validation rule takes the context parameter name. So if the value is from a data source then the value should be something like DataSource1.Table#csv.objectId. Note that there are no curly braces (i.e. no { or }) and no leading or trailing whitespace.
I am busy writing my own JSF2 UIComponents and their relevant renderers. All of my UIComponents implements ClientBehaviorHolder. What I don't understand is how to really render ClientBehaviorHolder.
For example, the following code illustrates how ClientBehaviorHolder is rendered in Mojarra.
private static void renderHandler(FacesContext context,
UIComponent component,
Collection<ClientBehaviorContext.Parameter> params,
String handlerName,
Object handlerValue,
String behaviorEventName,
String submitTarget,
boolean needsSubmit,
boolean includeExec)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
String userHandler = getNonEmptyUserHandler(handlerValue);
List<ClientBehavior> behaviors = getClientBehaviors(component, behaviorEventName);
// Don't render behavior scripts if component is disabled
if ((null != behaviors) &&
(behaviors.size() > 0) &&
Util.componentIsDisabled(component)) {
behaviors = null;
}
if (params == null) {
params = Collections.emptyList();
}
String handler = null;
switch (getHandlerType(behaviors, params, userHandler, needsSubmit, includeExec)) {
case USER_HANDLER_ONLY:
handler = userHandler;
break;
case SINGLE_BEHAVIOR_ONLY:
handler = getSingleBehaviorHandler(context,
component,
behaviors.get(0),
params,
behaviorEventName,
submitTarget,
needsSubmit);
break;
case SUBMIT_ONLY:
handler = getSubmitHandler(context,
component,
params,
submitTarget,
true);
break;
case CHAIN:
handler = getChainedHandler(context,
component,
behaviors,
params,
behaviorEventName,
userHandler,
submitTarget,
needsSubmit);
break;
default:
assert(false);
}
writer.writeAttribute(handlerName, handler, null);
}
For submit handlers, Mojarra adds the mojarra.jsfcljs javascript, UIParameters and other scripts. For chain handlers, jsf.util.chain is used.
My question is:
How does one determine if we have to render handlers in chain or a single behaviour or user specific handler?
mojarra.jsfcljs is only unique to Mojarra. PrimeFaces have their own implementation, so does Apache Tomahawk. Question is: what does mojarra.jsfcljs do and what is its use? This is so that I can write one for my own? Also, where can I find the implementation of mojarra.jsfcljs?
What is the specification to render ClientBehaviorHolder?
My sincere thanks in advance.
How does one determine if we have to render handlers in chain or a single behaviour or user specific handler?
Imagine that the enduser (read: the JSF developer who's using your component) programmed:
<your:component onclick="return foo()" />
And you intented to ultimately render for your component's own purpose:
<someHtmlElement onclick="jsf.ajax.request(...); return false;" />
Then you can't just concatenate the enduser's onclick in front of your component's jsf.ajax.request() like so
<someHtmlElement onclick="return foo(); jsf.ajax.request(...); return false;" />
Even if it returned true, your component's jsf.ajax.request won't be invoked at all. You ultimately want to end up something like:
<someHtmlElement onclick="if returnsTrue('return foo();') { jsf.ajax.request(...); } return false;" />
That's exactly what jsf.util.chain() is doing under the covers.
mojarra.jsfcljs is only unique to Mojarra. PrimeFaces have their own implementation, so does Apache Tomahawk. Question is: what does mojarra.jsfcljs do and what is its use? This is so that I can write one for my own? Also, where can I find the implementation of mojarra.jsfcljs?
It's inside the jsf.js file. Easy way to find it is to open a JSF page with <f:ajax> embedded and look in the generated <head> source for the <script> with its URL. This file is by default minified. If you set javax.faces.PROJECT_STAGE context param to Development, then this will be served unminified. The task of the jsfcljs() function is to submit the parent form with the necessary parameters. Here's an extract of relevance coming from Mojarra 2.1.21.
/*
* This is called by command link and command button. It provides
* the form it is nested in, the parameters that need to be
* added and finally, the target of the action. This function
* will delete any parameters added <em>after</em> the form
* has been submitted to handle DOM caching issues.
*
* #param f - the target form
* #param pvp - associative array of parameter
* key/value pairs to be added to the form as hidden input
* fields.
* #param t - the target of the form submission
*/
mojarra.jsfcljs = function jsfcljs(f, pvp, t) {
What is the specification to render ClientBehaviorHolder?
Use ClientBehavior#getScript() to get the autogenerated script. It requires a ClientBehaviorContext argument which can be created using ClientBehaviorContext#createClientBehaviorContext(). It's in turn your responsibility to render it into the appropriate HTML attribute, such as onclick.
FacesContext context = FacesContext.getCurrentInstance();
UIComponent inputOrCommandComponent = ...; // Your component.
String event = "click"; // Just the particular HTML DOM event name you need to listen on.
ClientBehaviorContext clientBehaviorContext = ClientBehaviorContext.createClientBehaviorContext(context, component, event, component.getClientId(context), null);
StringBuilder builder = new StringBuilder();
for (ClientBehavior behavior : component.getClientBehaviors().get(event)) { // Collect all <f:ajax> declarations on the given event.
builder.append(behavior.getScript(clientBehaviorContext));
builder.append(';');
}
String script = builder.toString();
// Write it to the desired HTML attribute.
Note that you absolutely don't need to worry about writing JSF implementation specific scripts this way. They will be generated for you.
All with all, ClientBehaviorHolder is just an abstraction of ajax support. It allows developers to nest <f:ajax> in your component. All standard JSF UIInput and UICommand components implement it.
Let's say I have a command-object containing seven fields(String monday, String tuesday, ..) and I need to validate it just to check if at least one of them exists.
Because of working with Grails 1.3.7 I tried to use instance validation with extended-validation-plugin(not rich-domain) but I couldn't make it work. Basically, it does not recognise non-field validator inside of static constraints block.
static constraints = {
availabilitySelected(validator: {
...
})
...
and I get:
Exception Message: No such property: availabilitySelected
Is there any other smart way to do it? I just do not want to add validator for every single field in my command object.
Thanks
You can access the object being validated via the two / three parameter form of a custom validator.
myField(validator: { val, obj, errors -> if( obj.blah.empty && obj.blah.empty ) { errors.reject( ... ) } )
http://grails.org/doc/1.3.7/ref/Constraints/validator.html