peoplemerge / recaptcha4j

Automatically exported from code.google.com/p/recaptcha4j
1 stars 1 forks source link

recaptcha4j does not support custom_translations option #6

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
It is not possible to pass custom_translations parameter to recaptcha.js 
through RecaptchaImpl.createRecaptchaHtml(String errorMessage, Properties 
options) method.

When options contains property "custom_translations" with value "{ 
instructions_visual : \"This is my text:\" }"

fetchJSOptions method yields:
<script type="text/javascript">
var RecaptchaOptions = {custom_translations:'{ instructions_visual : "This is 
my text:" }'};
</script>

This clearly cannot work because the value of custom_translations options is a 
string and not a dictionary as necessary.

I can see several solutions to this problem:

1) adding translations parameter to createRecaptchaHtml methods, of type 
Properties to be consistent. A downside is API bloat or breakage.

2) treating custom_translations option differently inside fetchJSOptions, 
namely dropping surrounding single quotes. Quick, but somewhat dirty.

3) since java.util.Properites extends Hashmap<Object,Object>, fetchJSOptions 
could support nested Properties objects, and write them out as JS dictionaries. 
for example: 

Properties translations = new Properties();
translations.setProperty("instructions_visual","This is my text:");
Properties options = new Properties();
options.set("custom_translations", translations);
String reCaptchaHtml = reCaptcha.createReCaptchaHtml(null, options);

Of course nesting can work on any property recursively, should that become 
useful with future extensions to reCaptcha API :)

Original issue reported on code.google.com by rafal.kr...@gmail.com on 3 Feb 2011 at 12:06

GoogleCodeExporter commented 9 years ago
In the example for solution 3 above 5th line should read:
options.put("custom_translations", translations);

To implement solution 3) replace ReCaptchaImpl.fetchJSOptions implementation 
with the following:

    /**
     * Produces javascript array with the RecaptchaOptions encoded.
     * 
     * @param properties
     * @return
     */
    private String fetchJSOptions(Properties properties) {

        if (properties == null || properties.size() == 0) {
            return "";
        }

        StringBuffer jsOptions = new StringBuffer();
        jsOptions.append("<script type=\"text/javascript\">\r\n" + 
            "var RecaptchaOptions = ");

        appendDictionary(jsOptions, properties);

        jsOptions.append(";\r\n</script>\r\n");

        return jsOptions.toString();
    } 

    /**
     * Appends javascript dictionary representation of a Properties object to given StringBuffer 
     * 
     * @param jsOptions the target StringBuffer object.
     * @param properties a Properties object.
     */
    private void appendDictionary(StringBuffer jsOptions, Properties properties)
    {
        jsOptions.append("\r\n{");
        for (Enumeration e = properties.keys(); e.hasMoreElements(); ) {
            Object property = e.nextElement();
            jsOptions.append((String)property).append(": ");

            Object value = properties.get(property);
            if(value instanceof Properties) {
                appendDictionary(jsOptions, (Properties)value);
            } else {
                jsOptions.append("'").append(value).append("'");
            }

            if (e.hasMoreElements()) {
                jsOptions.append(",\r\n");
            }
        }
        jsOptions.append("}");
    }

If you'd rather have it as a patch, let me know.

Original comment by rafal.kr...@gmail.com on 3 Feb 2011 at 12:52