From 32edddb11bcc204628fbdaddf3b0d0e86530f6f8 Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Wed, 08 Jun 2016 15:18:05 +0000
Subject: [PATCH] OPENDJ-2955 Use i18n in rest2ldap

---
 opendj-rest2ldap/pom.xml                                                                                |   23 ++
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java             |   63 ++++-
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/AuthzIdTemplate.java                |   14 
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Utils.java                          |   14 +
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ca_ES.properties           |   15 +
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ja.properties              |   15 +
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_es.properties              |   15 +
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Authorizations.java                 |    6 
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Rfc7662AccessTokenResolver.java     |   13 
 opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolverTestCase.java |    2 
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_pl.properties              |   15 +
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/FileAccessTokenResolver.java        |    6 
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_fr.properties              |   15 +
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_CN.properties           |   15 +
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties                 |  110 ++++++++++
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java             |   23 -
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java                                |   35 ++
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolver.java         |   13 
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_TW.properties           |   15 +
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java          |   76 +-----
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java                |   17 -
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/JSONConstantAttributeMapper.java          |   16 
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java                |   14 
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPCollectionResourceProvider.java       |   28 +-
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java                            |   38 +-
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_de.properties              |   15 +
 opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ko.properties              |   15 +
 27 files changed, 463 insertions(+), 183 deletions(-)

diff --git a/opendj-rest2ldap/pom.xml b/opendj-rest2ldap/pom.xml
index f293562..f04c4de 100644
--- a/opendj-rest2ldap/pom.xml
+++ b/opendj-rest2ldap/pom.xml
@@ -60,6 +60,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.forgerock.commons</groupId>
+            <artifactId>i18n-core</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.forgerock.openig</groupId>
             <artifactId>openig-oauth2-resource-server-filter</artifactId>
             <version>${openig.version}</version>
@@ -81,6 +86,24 @@
     <build>
         <plugins>
             <plugin>
+                <groupId>org.forgerock.commons</groupId>
+                <artifactId>i18n-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>generate-messages</goal>
+                        </goals>
+                        <configuration>
+                            <messageFiles>
+                                <messageFile>org/forgerock/opendj/rest2ldap/rest2ldap.properties</messageFile>
+                            </messageFiles>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <extensions>true</extensions>
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
index 547dac0..d211438 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
@@ -15,12 +15,14 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 import static org.forgerock.opendj.ldap.Attributes.emptyAttribute;
 import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
-import static org.forgerock.opendj.rest2ldap.Utils.i18n;
 import static org.forgerock.opendj.rest2ldap.Utils.isNullOrEmpty;
+import static org.forgerock.opendj.rest2ldap.Utils.newBadRequestException;
+import static org.forgerock.opendj.rest2ldap.Utils.newNotSupportedException;
 import static org.forgerock.opendj.rest2ldap.WritabilityPolicy.READ_WRITE;
 
 import java.util.ArrayList;
@@ -31,7 +33,6 @@
 import org.forgerock.json.JsonPointer;
 import org.forgerock.json.JsonValue;
 import org.forgerock.json.resource.BadRequestException;
-import org.forgerock.json.resource.NotSupportedException;
 import org.forgerock.json.resource.PatchOperation;
 import org.forgerock.json.resource.ResourceException;
 import org.forgerock.opendj.ldap.Attribute;
@@ -108,14 +109,12 @@
                 public List<Attribute> apply(Attribute newLDAPAttribute) throws ResourceException {
                     if (!writabilityPolicy.canCreate(ldapAttributeName)) {
                         if (!newLDAPAttribute.isEmpty() && !writabilityPolicy.discardWrites()) {
-                            throw new BadRequestException(i18n("The request cannot be processed because it attempts "
-                                    + "to create the read-only field '%s'", path));
+                            throw newBadRequestException(ERR_CREATION_READ_ONLY_FIELD.get(path));
                         }
                         return Collections.emptyList();
                     } else if (newLDAPAttribute.isEmpty()) {
                         if (isRequired) {
-                            throw new BadRequestException(i18n("The request cannot be processed because it attempts "
-                                    + "to remove the required field '%s'", path));
+                            throw newBadRequestException(ERR_REMOVE_REQUIRED_FIELD.get("create", path));
                         }
                         return Collections.emptyList();
                     }
@@ -148,9 +147,7 @@
              * if it is configured to discard writes.
              */
             if (!writabilityPolicy.canWrite(ldapAttributeName)) {
-                throw new BadRequestException(i18n(
-                        "The request cannot be processed because it attempts to modify "
-                                + "the read-only field '%s'", path));
+                throw newBadRequestException(ERR_MODIFY_READ_ONLY_FIELD.get("patch", path));
             }
 
             switch (field.size()) {
@@ -164,16 +161,12 @@
                 if (attributeIsSingleValued()) {
                     if (v.isList()) {
                         // Single-valued field violation.
-                        throw new BadRequestException(i18n(
-                                "The request cannot be processed because an array of values was "
-                                        + "provided for the single valued field '%s'", path));
+                        throw newBadRequestException(ERR_ARRAY_FOR_SINGLE_VALUED_FIELD.get(path));
                     }
                 } else if (!v.isList() && !operation.isIncrement()
                         && !(v.isNull() && (operation.isReplace() || operation.isRemove()))) {
                     // Multi-valued field violation.
-                    throw new BadRequestException(i18n(
-                            "The request cannot be processed because an array of values was "
-                                    + "not provided for the multi-valued field '%s'", path));
+                    throw newBadRequestException(ERR_NO_ARRAY_FOR_MULTI_VALUED_FIELD.get(path));
                 }
                 break;
             case 1:
@@ -189,25 +182,16 @@
                 if (fieldName.equals("-") && operation.isAdd()) {
                     // Append a single value.
                     if (attributeIsSingleValued()) {
-                        throw new BadRequestException(i18n(
-                                "The request cannot be processed because it attempts to append a "
-                                        + "value to the single valued field '%s'", path));
+                        throw newBadRequestException(ERR_PATCH_APPEND_IN_SINGLE_VALUED_FIELD.get(path));
                     } else if (v.isList()) {
-                        throw new BadRequestException(i18n(
-                                "The request cannot be processed because it attempts to "
-                                        + "perform an indexed append of an array of values to "
-                                        + "the multi-valued field '%s'", path.child(fieldName)));
+                        throw newBadRequestException(
+                                ERR_PATCH_INDEXED_APPEND_TO_MULTI_VALUED_FIELD.get(path.child(fieldName)));
                     }
                 } else if (fieldName.matches("[0-9]+")) {
                     // Array index - not allowed.
-                    throw new NotSupportedException(i18n(
-                            "The request cannot be processed because it included "
-                                    + "an indexed patch operation '%s' which is not supported "
-                                    + "by this resource provider", path.child(fieldName)));
+                    throw newNotSupportedException(ERR_PATCH_INDEXED_OPERATION.get(path.child(fieldName)));
                 } else {
-                    throw new BadRequestException(i18n(
-                            "The request cannot be processed because it included "
-                                    + "an unrecognized field '%s'", path.child(fieldName)));
+                    throw newBadRequestException(ERR_UNRECOGNIZED_FIELD.get(path.child(fieldName)));
                 }
                 break;
             default:
@@ -215,9 +199,7 @@
                  * The patch operation targets the child of a sub-field. This is
                  * not possible for a LDAP attribute mapper.
                  */
-                throw new BadRequestException(i18n(
-                        "The request cannot be processed because it included "
-                                + "an unrecognized field '%s'", path.child(field.get(0))));
+                throw newBadRequestException(ERR_UNRECOGNIZED_FIELD.get(path.child(field.get(0))));
             }
 
             // Check that the values are compatible with the type of patch operation.
@@ -232,10 +214,7 @@
                 modType =
                         attributeIsSingleValued() ? ModificationType.REPLACE : ModificationType.ADD;
                 if (newValues.isEmpty()) {
-                    throw new BadRequestException(i18n(
-                            "The request cannot be processed because it included "
-                                    + "an add patch operation but no value(s) for field '%s'", path
-                                    .child(field.get(0))));
+                    throw newBadRequestException(ERR_PATCH_ADD_NO_VALUE_FOR_FIELD.get(path.child(field.get(0))));
                 }
             } else if (operation.isRemove()) {
                 modType = ModificationType.DELETE;
@@ -244,10 +223,7 @@
             } else if (operation.isIncrement()) {
                 modType = ModificationType.INCREMENT;
             } else {
-                throw new NotSupportedException(i18n(
-                        "The request cannot be processed because it included "
-                                + "an unsupported type of patch operation '%s'", operation
-                                .getOperation()));
+                throw newNotSupportedException(ERR_PATCH_UNSUPPORTED_OPERATION.get(operation.getOperation()));
             }
 
             // Create the modification.
@@ -255,9 +231,7 @@
                 // Deleting the attribute.
                 if (isRequired) {
                     return Promises.<List<Modification>, ResourceException> newExceptionPromise(
-                            new BadRequestException(i18n(
-                                "The request cannot be processed because it attempts to remove the required field '%s'",
-                                path)));
+                            newBadRequestException(ERR_REMOVE_REQUIRED_FIELD.get("update", path)));
                 } else {
                     return Promises.newResultPromise(
                         singletonList(new Modification(modType, emptyAttribute(ldapAttributeName))));
@@ -300,9 +274,7 @@
                             // No change.
                             return Collections.emptyList();
                         }
-                        throw new BadRequestException(i18n(
-                            "The request cannot be processed because it attempts to modify the read-only field '%s'",
-                            path));
+                        throw newBadRequestException(ERR_MODIFY_READ_ONLY_FIELD.get("update", path));
                     }
 
                     if (oldLDAPAttribute.isEmpty() && newLDAPAttribute.isEmpty()) {
@@ -314,9 +286,7 @@
                     } else if (newLDAPAttribute.isEmpty()) {
                         // The attribute is being deleted - this is not allowed if the attribute is required.
                         if (isRequired) {
-                            throw new BadRequestException(i18n(
-                                "The request cannot be processed because it attempts to remove the required field '%s'",
-                                path));
+                            throw newBadRequestException(ERR_REMOVE_REQUIRED_FIELD.get("update", path));
                         }
                         return singletonList(new Modification(ModificationType.REPLACE, newLDAPAttribute));
                     } else {
@@ -359,15 +329,11 @@
         if (attributeIsSingleValued()) {
             if (v != null && v.isList()) {
                 // Single-valued field violation.
-                throw new BadRequestException(i18n(
-                        "The request cannot be processed because an array of values was "
-                                + "provided for the single valued field '%s'", path));
+                throw newBadRequestException(ERR_ARRAY_FOR_SINGLE_VALUED_FIELD.get(path));
             }
         } else if (v != null && !v.isList()) {
             // Multi-valued field violation.
-            throw new BadRequestException(i18n(
-                    "The request cannot be processed because an array of values was "
-                            + "not provided for the multi-valued field '%s'", path));
+            throw newBadRequestException(ERR_NO_ARRAY_FOR_MULTI_VALUED_FIELD.get(path));
         }
     }
 
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/JSONConstantAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/JSONConstantAttributeMapper.java
index 7d1f0a5..53fdd62 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/JSONConstantAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/JSONConstantAttributeMapper.java
@@ -15,10 +15,11 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static org.forgerock.opendj.ldap.Filter.alwaysFalse;
 import static org.forgerock.opendj.ldap.Filter.alwaysTrue;
-import static org.forgerock.opendj.rest2ldap.Utils.i18n;
 import static org.forgerock.opendj.rest2ldap.Utils.isNullOrEmpty;
+import static org.forgerock.opendj.rest2ldap.Utils.newBadRequestException;
 import static org.forgerock.opendj.rest2ldap.Utils.toFilter;
 import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
 
@@ -28,7 +29,6 @@
 
 import org.forgerock.json.JsonPointer;
 import org.forgerock.json.JsonValue;
-import org.forgerock.json.resource.BadRequestException;
 import org.forgerock.json.resource.PatchOperation;
 import org.forgerock.json.resource.ResourceException;
 import org.forgerock.opendj.ldap.Attribute;
@@ -58,8 +58,8 @@
     Promise<List<Attribute>, ResourceException> create(final Connection connection, final JsonPointer path,
             final JsonValue v) {
         if (!isNullOrEmpty(v) && !v.getObject().equals(value.getObject())) {
-            return Promises.<List<Attribute>, ResourceException> newExceptionPromise(new BadRequestException(i18n(
-                    "The request cannot be processed because it attempts to create the read-only field '%s'", path)));
+            return Promises.<List<Attribute>, ResourceException> newExceptionPromise(
+                    newBadRequestException(ERR_CREATION_READ_ONLY_FIELD.get(path)));
         } else {
             return Promises.newResultPromise(Collections.<Attribute> emptyList());
         }
@@ -112,8 +112,8 @@
     @Override
     Promise<List<Modification>, ResourceException> patch(final Connection connection, final JsonPointer path,
             final PatchOperation operation) {
-        return Promises.<List<Modification>, ResourceException> newExceptionPromise(new BadRequestException(i18n(
-                "The request cannot be processed because it attempts to patch the read-only field '%s'", path)));
+        return Promises.<List<Modification>, ResourceException> newExceptionPromise(
+                newBadRequestException(ERR_PATCH_READ_ONLY_FIELD.get(path)));
     }
 
     @Override
@@ -125,8 +125,8 @@
     Promise<List<Modification>, ResourceException> update(
             final Connection connection, final JsonPointer path, final Entry e, final JsonValue v) {
         if (!isNullOrEmpty(v) && !v.getObject().equals(value.getObject())) {
-            return Promises.<List<Modification>, ResourceException> newExceptionPromise(new BadRequestException(i18n(
-                    "The request cannot be processed because it attempts to modify the read-only field '%s'", path)));
+            return Promises.<List<Modification>, ResourceException> newExceptionPromise(
+                    newBadRequestException(ERR_MODIFY_READ_ONLY_FIELD.get("update", path)));
         } else {
             return Promises.newResultPromise(Collections.<Modification> emptyList());
         }
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPCollectionResourceProvider.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPCollectionResourceProvider.java
index c150a44..e0ff373 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPCollectionResourceProvider.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPCollectionResourceProvider.java
@@ -15,6 +15,7 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static java.util.Arrays.asList;
 import static org.forgerock.opendj.ldap.Filter.alwaysFalse;
 import static org.forgerock.opendj.ldap.Filter.alwaysTrue;
@@ -24,7 +25,8 @@
 import static org.forgerock.opendj.ldap.requests.Requests.newSearchRequest;
 import static org.forgerock.opendj.rest2ldap.ReadOnUpdatePolicy.CONTROLS;
 import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
-import static org.forgerock.opendj.rest2ldap.Utils.i18n;
+import static org.forgerock.opendj.rest2ldap.Utils.newBadRequestException;
+import static org.forgerock.opendj.rest2ldap.Utils.newNotSupportedException;
 import static org.forgerock.opendj.rest2ldap.Utils.toFilter;
 
 import java.nio.charset.StandardCharsets;
@@ -135,7 +137,7 @@
     public Promise<ActionResponse, ResourceException> actionCollection(
             final Context context, final ActionRequest request) {
         return Promises.<ActionResponse, ResourceException> newExceptionPromise(
-                                                            new NotSupportedException("Not yet implemented"));
+                                                            newNotSupportedException(ERR_NOT_YET_IMPLEMENTED.get()));
     }
 
     @Override
@@ -146,7 +148,7 @@
             return passwordModify(context, resourceId, request);
         }
         return Promises.<ActionResponse, ResourceException> newExceptionPromise(
-                new NotSupportedException("The action '" + actionId + "' is not supported"));
+                newNotSupportedException(ERR_ACTION_NOT_SUPPORTED.get(actionId)));
     }
 
     private Promise<ActionResponse, ResourceException> passwordModify(
@@ -154,12 +156,12 @@
         if (!context.containsContext(ClientContext.class)
                 || !context.asContext(ClientContext.class).isSecure()) {
             return Promises.newExceptionPromise(ResourceException.newResourceException(
-                    ResourceException.FORBIDDEN, "Password modify requires a secure connection."));
+                    ResourceException.FORBIDDEN, ERR_PASSWORD_MODIFY_SECURE_CONNECTION.get().toString()));
         }
         if (!context.containsContext(SecurityContext.class)
                 || context.asContext(SecurityContext.class).getAuthenticationId() == null) {
             return Promises.newExceptionPromise(ResourceException.newResourceException(
-                    ResourceException.FORBIDDEN, "Password modify requires user to be authenticated."));
+                    ResourceException.FORBIDDEN, ERR_PASSWORD_MODIFY_USER_AUTHENTICATED.get().toString()));
         }
 
         final JsonValue jsonContent = request.getContent();
@@ -169,8 +171,8 @@
             oldPassword = jsonContent.get("oldPassword").asString();
             newPassword = jsonContent.get("newPassword").asString();
         } catch (JsonValueException e) {
-            return Promises.newExceptionPromise(
-                    ResourceException.newResourceException(ResourceException.BAD_REQUEST, e.getLocalizedMessage(), e));
+            final ResourceException ex = newBadRequestException(ERR_PASSWORD_MODIFY_REQUEST_IS_INVALID.get(), e);
+            return Promises.newExceptionPromise(ex);
         }
 
         final Connection connection = context.asContext(AuthenticatedConnectionContext.class).getConnection();
@@ -844,8 +846,7 @@
 
     private void ensureMVCCSupported() throws NotSupportedException {
         if (etagAttribute == null) {
-            throw new NotSupportedException(
-                    i18n("Multi-version concurrency control is not supported by this resource"));
+            throw newNotSupportedException(ERR_MVCC_NOT_SUPPORTED.get());
         }
     }
 
@@ -854,13 +855,10 @@
             ensureMVCCSupported();
             final String actualRevision = entry.parseAttribute(etagAttribute).asString();
             if (actualRevision == null) {
-                throw new PreconditionFailedException(i18n(
-                        "The resource could not be accessed because it did not contain any "
-                                + "version information, when the version '%s' was expected", expectedRevision));
+                throw new PreconditionFailedException(ERR_MVCC_NO_VERSION_INFORMATION.get(expectedRevision).toString());
             } else if (!expectedRevision.equals(actualRevision)) {
-                throw new PreconditionFailedException(i18n(
-                        "The resource could not be accessed because the expected version '%s' "
-                                + "does not match the current version '%s'", expectedRevision, actualRevision));
+                throw new PreconditionFailedException(
+                        ERR_MVCC_VERSIONS_MISMATCH.get(expectedRevision, actualRevision).toString());
             }
         }
     }
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java
index 508d424..984dd69 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java
@@ -15,10 +15,11 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static org.forgerock.json.resource.PatchOperation.operation;
 import static org.forgerock.opendj.ldap.Filter.alwaysFalse;
 import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
-import static org.forgerock.opendj.rest2ldap.Utils.i18n;
+import static org.forgerock.opendj.rest2ldap.Utils.newBadRequestException;
 import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
 
 import java.util.AbstractMap.SimpleImmutableEntry;
@@ -31,7 +32,6 @@
 
 import org.forgerock.json.JsonPointer;
 import org.forgerock.json.JsonValue;
-import org.forgerock.json.resource.BadRequestException;
 import org.forgerock.json.resource.PatchOperation;
 import org.forgerock.json.resource.ResourceException;
 import org.forgerock.opendj.ldap.Attribute;
@@ -196,9 +196,7 @@
                 final String fieldName = field.get(0);
                 final Mapping mapping = getMapping(fieldName);
                 if (mapping == null) {
-                    throw new BadRequestException(i18n(
-                            "The request cannot be processed because it included "
-                                    + "an unrecognized field '%s'", path.child(fieldName)));
+                    throw newBadRequestException(ERR_UNRECOGNIZED_FIELD.get(path.child(fieldName)));
                 }
                 final PatchOperation subOperation =
                         operation(operation.getOperation(), field.relativePointer(), v);
@@ -314,16 +312,11 @@
             if (v.isMap()) {
                 for (final String attribute : v.asMap().keySet()) {
                     if (missingMappings.remove(toLowerCase(attribute)) == null) {
-                        throw new BadRequestException(i18n(
-                                "The request cannot be processed because it included "
-                                        + "an unrecognized field '%s'", path.child(attribute)));
+                        throw newBadRequestException(ERR_UNRECOGNIZED_FIELD.get(path.child(attribute)));
                     }
                 }
             } else {
-                throw new BadRequestException(i18n(
-                        "The request cannot be processed because it included "
-                                + "the field '%s' whose value is the wrong type: "
-                                + "an object is expected", path));
+                throw newBadRequestException(ERR_FIELD_WRONG_TYPE.get(path));
             }
         }
         return missingMappings;
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java
index 140a94c..b599436 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java
@@ -15,11 +15,12 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static org.forgerock.opendj.ldap.LdapException.newLdapException;
 import static org.forgerock.opendj.ldap.requests.Requests.newSearchRequest;
 import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
 import static org.forgerock.opendj.rest2ldap.Utils.ensureNotNull;
-import static org.forgerock.opendj.rest2ldap.Utils.i18n;
+import static org.forgerock.opendj.rest2ldap.Utils.newBadRequestException;
 
 import java.util.ArrayList;
 import java.util.LinkedHashSet;
@@ -31,7 +32,6 @@
 
 import org.forgerock.json.JsonPointer;
 import org.forgerock.json.JsonValue;
-import org.forgerock.json.resource.BadRequestException;
 import org.forgerock.json.resource.ResourceException;
 import org.forgerock.opendj.ldap.Attribute;
 import org.forgerock.opendj.ldap.AttributeDescription;
@@ -206,15 +206,12 @@
                     }
 
                     if (primaryKeyAttribute == null || primaryKeyAttribute.isEmpty()) {
-                        promise.handleException(new BadRequestException(
-                                i18n("The request cannot be processed because the reference field '%s' contains "
-                                        + "a value which does not contain a primary key", path)));
+                        promise.handleException(newBadRequestException(ERR_REFERENCE_FIELD_NO_PRIMARY_KEY.get(path)));
                     }
 
                     if (primaryKeyAttribute.size() > 1) {
-                        promise.handleException(new BadRequestException(
-                                i18n("The request cannot be processed because the reference field '%s' contains "
-                                        + "a value which contains multiple primary keys", path)));
+                        promise.handleException(
+                                newBadRequestException(ERR_REFERENCE_FIELD_MULTIPLE_PRIMARY_KEYS.get(path)));
                     }
 
                     // Now search for the referenced entry in to get its DN.
@@ -237,15 +234,11 @@
                                       try {
                                           throw error;
                                       } catch (final EntryNotFoundException e) {
-                                          re = new BadRequestException(i18n(
-                                                  "The request cannot be processed because the resource "
-                                                  + "'%s' referenced in field '%s' does not exist",
+                                          re = newBadRequestException(ERR_REFERENCE_FIELD_DOES_NOT_EXIST.get(
                                                   primaryKeyValue.toString(), path));
                                       } catch (final MultipleEntriesFoundException e) {
-                                          re = new BadRequestException(i18n(
-                                                  "The request cannot be processed because the resource "
-                                                  + "'%s' referenced in field '%s' is ambiguous",
-                                                  primaryKeyValue.toString(), path));
+                                          re = newBadRequestException(
+                                                  ERR_REFERENCE_FIELD_AMBIGUOUS.get(primaryKeyValue.toString(), path));
                                       } catch (final LdapException e) {
                                           re = asResourceException(e);
                                       }
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
index 32fba74..4aa085f 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
@@ -15,6 +15,7 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static java.util.Arrays.asList;
 import static org.forgerock.json.resource.ResourceException.newResourceException;
 import static org.forgerock.opendj.ldap.Connections.newCachedConnectionPool;
@@ -26,6 +27,9 @@
 import static org.forgerock.opendj.ldap.schema.CoreSchema.getEntryUUIDAttributeType;
 import static org.forgerock.opendj.rest2ldap.ReadOnUpdatePolicy.CONTROLS;
 import static org.forgerock.opendj.rest2ldap.Utils.ensureNotNull;
+import static org.forgerock.opendj.rest2ldap.Utils.newBadRequestException;
+import static org.forgerock.opendj.rest2ldap.Utils.newLocalizedIllegalArgumentException;
+import static org.forgerock.opendj.rest2ldap.Utils.newJsonValueException;
 import static org.forgerock.util.time.Duration.*;
 
 import java.io.IOException;
@@ -39,8 +43,6 @@
 import java.util.concurrent.TimeUnit;
 
 import org.forgerock.json.JsonValue;
-import org.forgerock.json.JsonValueException;
-import org.forgerock.json.resource.BadRequestException;
 import org.forgerock.json.resource.CollectionResourceProvider;
 import org.forgerock.json.resource.ResourceException;
 import org.forgerock.opendj.ldap.AssertionFailureException;
@@ -170,7 +172,7 @@
         public CollectionResourceProvider build() {
             ensureNotNull(baseDN);
             if (rootMapper == null) {
-                throw new IllegalStateException("No mappings provided");
+                throw new IllegalStateException(ERR_CONFIG_NO_MAPPINGS_PROVIDED.get().toString());
             }
             return new LDAPCollectionResourceProvider(baseDN, rootMapper, nameStrategy, etagAttribute,
                     new Config(readOnUpdatePolicy, useSubtreeDelete, usePermissiveModify, schema),
@@ -215,8 +217,8 @@
                     useServerNaming(namingStrategy.get("dnAttribute").required().asString(),
                             namingStrategy.get("idAttribute").required().asString());
                 } else {
-                    throw new IllegalArgumentException(
-                            "Illegal naming strategy. Must be one of: clientDNNaming, clientNaming, or serverNaming");
+                    throw newLocalizedIllegalArgumentException(ERR_CONFIG_UNKNOWN_NAMING_CONFIGURATION.get(
+                            namingStrategy.asString(), "clientDNNaming, clientNaming or serverNaming"));
                 }
             }
 
@@ -586,8 +588,8 @@
             } else if (mapper.isDefined("object")) {
                 return configureObjectMapper(mapper.get("object"));
             } else {
-                throw new JsonValueException(mapper,
-                        "Illegal mapping: must contain constant, simple, or object");
+                throw newJsonValueException(mapper, ERR_CONFIG_NO_MAPPING_IN_CONFIGURATION.get(
+                        "constant, simple, reference or object"));
             }
         }
 
@@ -613,9 +615,8 @@
                 } else if (writability.equalsIgnoreCase("readWrite")) {
                     return WritabilityPolicy.READ_WRITE;
                 } else {
-                    throw new JsonValueException(mapper,
-                            "Illegal writability: must be one of readOnly, readOnlyDiscardWrites, "
-                                    + "createOnly, createOnlyDiscardWrites, or readWrite");
+                    throw newJsonValueException(mapper, ERR_CONFIG_UNKNOWN_WRITABILITY.get(writability,
+                                "readOnly, readOnlyDiscardWrites, createOnly, createOnlyDiscardWrites, or readWrite"));
                 }
             } else {
                 return WritabilityPolicy.READ_WRITE;
@@ -632,7 +633,7 @@
                 final AttributeDescription idAttribute, final boolean isServerProvided) {
             this.dnAttribute = AttributeDescription.create(dnAttribute);
             if (this.dnAttribute.equals(idAttribute)) {
-                throw new IllegalArgumentException("DN and ID attributes must be different");
+                throw newLocalizedIllegalArgumentException(ERR_CONFIG_NAMING_STRATEGY_DN_AND_ID_NOT_DIFFERENT.get());
             }
             this.idAttribute = ensureNotNull(idAttribute);
             this.isServerProvided = isServerProvided;
@@ -659,8 +660,7 @@
                 final Entry entry) throws ResourceException {
             if (isServerProvided) {
                 if (resourceId != null) {
-                    throw new BadRequestException("Resources cannot be created with a "
-                            + "client provided resource ID");
+                    throw newBadRequestException(ERR_CLIENT_PROVIDER_RESOURCE_ID_MISSING.get());
                 }
             } else {
                 entry.addAttribute(new LinkedAttribute(idAttribute, ByteString.valueOfUtf8(resourceId)));
@@ -703,8 +703,7 @@
             } else if (entry.getAttribute(attribute) != null) {
                 entry.setName(baseDN.child(rdn(entry.parseAttribute(attribute).asString())));
             } else {
-                throw new BadRequestException("Resources cannot be created without a "
-                        + "client provided resource ID");
+                throw newBadRequestException(ERR_CLIENT_PROVIDER_RESOURCE_ID_MISSING.get());
             }
         }
 
@@ -937,7 +936,7 @@
                                 simple.get("bindPassword").required().asString().toCharArray());
                 options.set(AUTHN_BIND_REQUEST, bindRequest);
             } else {
-                throw new IllegalArgumentException("Only simple authentication is supported");
+                throw newLocalizedIllegalArgumentException(ERR_CONFIG_INVALID_AUTHENTICATION.get());
             }
         }
 
@@ -995,7 +994,7 @@
                 secondary = parseLDAPServers(secondaryLDAPServers, connectionPoolSize, options);
             }
         } else if (!secondaryLDAPServers.isNull()) {
-            throw new IllegalArgumentException("Invalid secondaryLDAPServers configuration");
+            throw newLocalizedIllegalArgumentException(ERR_CONFIG_INVALID_SECONDARY_LDAP_SERVER.get());
         }
 
         // Create fail-over.
@@ -1010,10 +1009,7 @@
             final String name, final int depth) {
         // Protect against infinite recursion in the configuration.
         if (depth > 100) {
-            throw new IllegalArgumentException(
-                    "The LDAP server configuration '"
-                            + name
-                            + "' could not be parsed because of potential circular inheritance dependencies");
+            throw newLocalizedIllegalArgumentException(ERR_CONFIG_SERVER_CIRCULAR_DEPENDENCIES.get(name));
         }
 
         final JsonValue current = configuration.get(name).required();
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java
index b994823..3e312f7 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java
@@ -16,17 +16,21 @@
 
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static org.forgerock.http.util.Json.readJsonLenient;
 import static org.forgerock.json.JsonValueFunctions.duration;
 import static org.forgerock.json.JsonValueFunctions.enumConstant;
 import static org.forgerock.json.JsonValueFunctions.setOf;
 import static org.forgerock.opendj.rest2ldap.Rest2LDAP.configureConnectionFactory;
+import static org.forgerock.opendj.rest2ldap.Utils.newLocalizedIllegalArgumentException;
+import static org.forgerock.opendj.rest2ldap.Utils.newJsonValueException;
 import static org.forgerock.opendj.rest2ldap.authz.AuthenticationStrategies.*;
 import static org.forgerock.opendj.rest2ldap.authz.Authorizations.*;
 import static org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.*;
 import static org.forgerock.opendj.rest2ldap.authz.CredentialExtractors.*;
 import static org.forgerock.util.Reject.checkNotNull;
 import static org.forgerock.util.Utils.closeSilently;
+import static org.forgerock.util.Utils.joinAsString;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -57,7 +61,6 @@
 import org.forgerock.http.io.Buffer;
 import org.forgerock.http.protocol.Headers;
 import org.forgerock.json.JsonValue;
-import org.forgerock.json.JsonValueException;
 import org.forgerock.json.resource.RequestHandler;
 import org.forgerock.json.resource.Router;
 import org.forgerock.json.resource.http.CrestHttp;
@@ -112,16 +115,39 @@
 
     /** Define the method which should be used to resolve an OAuth2 access token. */
     private enum OAuth2ResolverType {
-        RFC7662,
-        OPENAM,
-        CTS,
-        FILE
+        RFC7662, OPENAM, CTS, FILE;
+
+        private static String listValues() {
+            final List<String> values = new ArrayList<>();
+            for (final OAuth2ResolverType value : OAuth2ResolverType.values()) {
+                values.add(value.name().toLowerCase());
+            }
+            return joinAsString(",", values);
+        }
     }
 
     @VisibleForTesting
     enum Policy { OAUTH2, BASIC, ANONYMOUS }
 
-    private enum BindStrategy { SIMPLE, SEARCH, SASL_PLAIN }
+    private enum BindStrategy {
+        SIMPLE("simple"),
+        SEARCH("search"),
+        SASL_PLAIN("sasl-plain");
+
+        private final String jsonField;
+
+        BindStrategy(final String jsonField) {
+            this.jsonField = jsonField;
+        }
+
+        private static String listValues() {
+            final List<String> values = new ArrayList<>();
+            for (final BindStrategy mapping : BindStrategy.values()) {
+                values.add(mapping.jsonField);
+            }
+            return joinAsString(",", values);
+        }
+    }
 
     /**
      * Default constructor called by the HTTP Framework which will use the default configuration file location.
@@ -154,8 +180,7 @@
                     CrestHttp.newHttpHandler(configureRest2Ldap(configuration)),
                     buildAuthorizationFilter(configuration.get("authorization").required()));
         } catch (final Exception e) {
-            // TODO i18n, once supported in opendj-rest2ldap
-            final String errorMsg = "Unable to start Rest2Ldap Http Application";
+            final String errorMsg = ERR_FAIL_PARSE_CONFIGURATION.get(e.getLocalizedMessage()).toString();
             LOG.error(errorMsg, e);
             stop();
             throw new HttpApplicationException(errorMsg, e);
@@ -267,7 +292,9 @@
         case FILE:
             return newFileAccessTokenResolver(configuration.get("file").get("folderPath").required().asString());
         default:
-            throw new JsonValueException(resolver, "is not a supported access token resolver");
+            throw newJsonValueException(resolver,
+                                        ERR_CONFIG_OAUTH2_UNSUPPORTED_ACCESS_TOKEN_RESOLVER.get(
+                                                resolver.getObject(), OAuth2ResolverType.listValues()));
         }
     }
 
@@ -280,8 +307,8 @@
                                                  rfc7662.get("clientId").required().asString(),
                                                  rfc7662.get("clientSecret").required().asString());
         } catch (final URISyntaxException e) {
-            throw new IllegalArgumentException("The token introspection endpoint '"
-                    + introspectionEndPointURL + "' URL has an invalid syntax: " + e.getLocalizedMessage(), e);
+            throw new IllegalArgumentException(ERR_CONIFG_OAUTH2_INVALID_INTROSPECT_URL.get(
+                    introspectionEndPointURL, e.getLocalizedMessage()).toString(), e);
         }
     }
 
@@ -289,15 +316,14 @@
         try {
             final Duration expiration = expirationJson.as(duration());
             if (expiration.isZero() || expiration.isUnlimited()) {
-                throw new JsonValueException(expirationJson, "The cache expiration duration cannot be "
-                        + (expiration.isZero() ? "zero" : "unlimited."));
+                throw newJsonValueException(expirationJson,
+                                            expiration.isZero() ? ERR_CONIFG_OAUTH2_CACHE_ZERO_DURATION.get()
+                                                                : ERR_CONIFG_OAUTH2_CACHE_UNLIMITED_DURATION.get());
             }
             return expiration;
         } catch (final Exception e) {
-            throw new JsonValueException(expirationJson,
-                      "Malformed duration value '" + expirationJson.toString() + "' for cache expiration. "
-                    + "The duration syntax supports all human readable notations from day ('days'', 'day'', 'd'') "
-                    + "to nanosecond ('nanoseconds', 'nanosecond', 'nanosec', 'nanos', 'nano', 'ns')");
+            throw newJsonValueException(expirationJson,
+                                        ERR_CONFIG_OAUTH2_CACHE_INVALID_DURATION.get(expirationJson.toString()));
         }
     }
 
@@ -381,7 +407,8 @@
         case SASL_PLAIN:
             return buildSASLBindStrategy(config);
         default:
-            throw new IllegalArgumentException("Unsupported strategy '" + strategy + "'");
+            throw newLocalizedIllegalArgumentException(ERR_CONFIG_UNSUPPORTED_BIND_STRATEGY.get(
+                    strategy, BindStrategy.listValues()));
         }
     }
 
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
index b6d3d4a..dc36f31 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
@@ -15,13 +15,14 @@
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
 import org.forgerock.json.JsonPointer;
 import org.forgerock.json.JsonValue;
-import org.forgerock.json.resource.BadRequestException;
 import org.forgerock.json.resource.ResourceException;
 import org.forgerock.opendj.ldap.Attribute;
 import org.forgerock.opendj.ldap.AttributeDescription;
@@ -124,10 +125,8 @@
                 return newResultPromise(toFilter(type, ldapAttributeName.toString(), va));
             } catch (final Exception e) {
                 // Invalid assertion value - bad request.
-                return newExceptionPromise((ResourceException) new BadRequestException(i18n(
-                        "The request cannot be processed because it contained an "
-                                + "illegal filter assertion value '%s' for field '%s'",
-                        String.valueOf(valueAssertion), path), e));
+                return newExceptionPromise((ResourceException) newBadRequestException(
+                        ERR_ILLEGAL_FILTER_ASSERTION_VALUE.get(String.valueOf(valueAssertion), path), e));
             }
         } else {
             // This attribute mapper does not support partial filtering.
@@ -141,9 +140,8 @@
         try {
             return newResultPromise(jsonToAttribute(newValues, ldapAttributeName, encoder()));
         } catch (final Exception ex) {
-            return newExceptionPromise((ResourceException) new BadRequestException(i18n(
-                    "The request cannot be processed because an error occurred while "
-                            + "encoding the values for the field '%s': %s", path, ex.getMessage())));
+            return newExceptionPromise((ResourceException) newBadRequestException(
+                    ERR_ENCODING_VALUES_FOR_FIELD.get(path, ex.getMessage())));
         }
     }
 
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
index e810f21..b67dda7 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
@@ -11,10 +11,11 @@
  * Header, with the fields enclosed by brackets [] replaced by your own identifying
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
- * Copyright 2012-2015 ForgeRock AS.
+ * Copyright 2012-2016 ForgeRock AS.
  */
 package org.forgerock.opendj.rest2ldap;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static javax.xml.bind.DatatypeConverter.parseDateTime;
 import static javax.xml.bind.DatatypeConverter.printDateTime;
 import static org.forgerock.opendj.ldap.Filter.alwaysFalse;
@@ -32,7 +33,12 @@
 import java.util.List;
 import java.util.Locale;
 
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.json.JsonValue;
+import org.forgerock.json.JsonValueException;
+import org.forgerock.json.resource.BadRequestException;
+import org.forgerock.json.resource.NotSupportedException;
 import org.forgerock.opendj.ldap.Attribute;
 import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
@@ -152,8 +158,7 @@
             }
             return a;
         } else {
-            throw new IllegalArgumentException("Unrecognized type of JSON value: "
-                    + value.getClass().getName());
+            throw newLocalizedIllegalArgumentException(ERR_UNRECOGNIZED_JSON_VALUE.get(value.getClass().getName()));
         }
     }
 
@@ -169,8 +174,8 @@
                         return ByteString.valueOfObject(value);
                     }
                 } else {
-                    throw new IllegalArgumentException("Unrecognized type of JSON value: "
-                            + value.getClass().getName());
+                    throw newLocalizedIllegalArgumentException(
+                            ERR_UNRECOGNIZED_JSON_VALUE.get(value.getClass().getName()));
                 }
             }
         };
@@ -208,6 +213,26 @@
         return s != null ? s.toLowerCase(Locale.ENGLISH) : null;
     }
 
+    static NotSupportedException newNotSupportedException(final LocalizableMessage message) {
+        return new NotSupportedException(message.toString());
+    }
+
+    static JsonValueException newJsonValueException(final JsonValue value, final LocalizableMessage message) {
+        return new JsonValueException(value, message.toString());
+    }
+
+    static LocalizedIllegalArgumentException newLocalizedIllegalArgumentException(final LocalizableMessage message) {
+        return new LocalizedIllegalArgumentException(message);
+    }
+
+    static BadRequestException newBadRequestException(final LocalizableMessage message) {
+        return newBadRequestException(message, null);
+    }
+
+    static BadRequestException newBadRequestException(final LocalizableMessage message, final Throwable cause) {
+        return new BadRequestException(message.toString(), cause);
+    }
+
     private static <T> List<T> asList(final Collection<T> c) {
         if (c instanceof List) {
             return (List<T>) c;
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Authorizations.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Authorizations.java
index 16ad36a..9324c98 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Authorizations.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Authorizations.java
@@ -15,6 +15,7 @@
  */
 package org.forgerock.opendj.rest2ldap.authz;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.asConditionalFilter;
 import static org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.newConditionalFilter;
 import static org.forgerock.util.promise.Promises.newResultPromise;
@@ -266,8 +267,9 @@
                 try {
                     authz.put(template.getSecurityContextID(), template.formatAsAuthzId(token.asJsonValue()));
                 } catch (final IllegalArgumentException e) {
-                    return newResultPromise(
-                            new Response().setStatus(Status.FORBIDDEN).setCause(e).setEntity("Invalid configuration"));
+                    return newResultPromise(new Response().setStatus(Status.FORBIDDEN)
+                                                          .setCause(e)
+                                                          .setEntity(ERR_AUTHZID_DECODER_RESPONSE.get().toString()));
                 }
                 final Context securityContext = new SecurityContext(context, token.getToken(), authz);
                 return next.handle(securityContext, request);
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/AuthzIdTemplate.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/AuthzIdTemplate.java
index 589bb5b..096ad78 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/AuthzIdTemplate.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/AuthzIdTemplate.java
@@ -15,6 +15,8 @@
  */
 package org.forgerock.opendj.rest2ldap.authz;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
+import static org.forgerock.opendj.rest2ldap.authz.Utils.newIllegalArgumentException;
 import static org.forgerock.util.Utils.joinAsString;
 
 import java.util.ArrayList;
@@ -87,8 +89,8 @@
                     return type;
                 }
             }
-            throw new IllegalArgumentException("Invalid authorization ID template: '" + template + "'. Templates must "
-                       + "start with one of the following elements: " + joinAsString(",", getSupportedStartKeys()));
+            throw newIllegalArgumentException(
+                    ERR_CONFIG_INVALID_AUTHZID_TEMPLATE.get(template, joinAsString(",", getSupportedStartKeys())));
         }
 
         private static List<String> getSupportedStartKeys() {
@@ -162,16 +164,12 @@
             final String key = keys.get(i);
             final JsonValue value = principals.get(new JsonPointer(key));
             if (value == null) {
-                throw new IllegalArgumentException(String.format(
-                        "The request could not be authorized because the required "
-                                + "security principal '%s' could not be determined", key));
+                throw newIllegalArgumentException(ERR_AUTHZID_DECODER_PRINCIPAL_CANNOT_BE_DETERMINED.get(key));
             }
 
             final Object object = value.getObject();
             if (!isJSONPrimitive(object)) {
-                throw new IllegalArgumentException(String.format(
-                        "The request could not be authorized because the required "
-                                + "security principal '%s' had an invalid data type", key));
+                throw newIllegalArgumentException(ERR_AUTHZID_DECODER_PRINCIPAL_INVALID_DATA_TYPE.get(key));
             }
             values[i] = String.valueOf(object);
         }
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolver.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolver.java
index 253726a..0a0e957 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolver.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolver.java
@@ -15,8 +15,10 @@
  */
 package org.forgerock.opendj.rest2ldap.authz;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static org.forgerock.opendj.ldap.requests.Requests.newSingleEntrySearchRequest;
 import static org.forgerock.opendj.rest2ldap.authz.Utils.close;
+import static org.forgerock.opendj.rest2ldap.authz.Utils.newAccessTokenException;
 import static org.forgerock.util.Reject.checkNotNull;
 
 import java.io.IOException;
@@ -78,8 +80,7 @@
 
                     final String tokenName = getRequiredFirstValue(accessToken.get("tokenName"));
                     if (!tokenName.equals("access_token")) {
-                        throw new AccessTokenException(
-                                "The token '" + token + "' must be an access token, but it is a \"" + tokenName + "\"");
+                        throw newAccessTokenException(ERR_OAUTH2_CTS_INVALID_TOKEN_TYPE.get(token, tokenName));
                     }
 
                     return new AccessTokenInfo(accessToken, token,
@@ -89,14 +90,12 @@
             }, new Function<LdapException, AccessTokenInfo, AccessTokenException>() {
                 @Override
                 public AccessTokenInfo apply(final LdapException e) throws AccessTokenException {
-                    throw new AccessTokenException("Unable to find the token '" + token + "' in the CTS because: "
-                            + e.getMessage(), e);
+                    throw newAccessTokenException(ERR_OAUTH2_CTS_TOKEN_NOT_FOUND.get(token, e.getMessage()), e);
                 }
             }).thenCatchRuntimeException(new Function<RuntimeException, AccessTokenInfo, AccessTokenException>() {
                 @Override
                 public AccessTokenInfo apply(final RuntimeException e) throws AccessTokenException {
-                    throw new AccessTokenException("Unable to resolve access token '" + token
-                            + "' due to the following reason: " + e.getMessage(), e);
+                    throw newAccessTokenException(ERR_OAUTH2_CTS_TOKEN_RESOLUTION.get(token, e.getMessage()), e);
                 }
             }).thenFinally(close(connectionHolder));
     }
@@ -109,7 +108,7 @@
         try {
             return new JsonValue(Json.readJson(accessTokenJson));
         } catch (final IOException e) {
-            throw new AccessTokenException("Json of token '" + token + "' is malformed");
+            throw newAccessTokenException(ERR_OAUTH2_CTS_INVALID_JSON_TOKEN.get(token));
         }
     }
 }
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/FileAccessTokenResolver.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/FileAccessTokenResolver.java
index dca7987..65f16a1 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/FileAccessTokenResolver.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/FileAccessTokenResolver.java
@@ -15,6 +15,8 @@
  */
 package org.forgerock.opendj.rest2ldap.authz;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
+import static org.forgerock.opendj.rest2ldap.authz.Utils.newAccessTokenException;
 import static org.forgerock.util.Reject.checkNotNull;
 import static org.forgerock.util.promise.Promises.newExceptionPromise;
 import static org.forgerock.util.promise.Promises.newResultPromise;
@@ -48,7 +50,7 @@
         try (final InputStream stream = new FileInputStream(new File(folderPath, token))) {
             accessToken = new JsonValue(Json.readJsonLenient(stream));
         } catch (final IOException e) {
-            return newExceptionPromise(new AccessTokenException("Unable to find token file '" + token + "'", e));
+            return newExceptionPromise(newAccessTokenException(ERR_OAUTH2_FILE_NO_TOKEN.get(token) , e));
         }
 
         try {
@@ -58,7 +60,7 @@
             return newResultPromise(result);
         } catch (final JsonValueException e) {
             return newExceptionPromise(
-                    new AccessTokenException("Malformed token file '" + token + "': '" + e.getMessage() + "'.", e));
+                    newAccessTokenException(ERR_OAUTH2_FILE_INVALID_JSON_TOKEN.get(token, e.getMessage()), e));
         }
     }
 }
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Rfc7662AccessTokenResolver.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Rfc7662AccessTokenResolver.java
index 4277291..9c22fb7 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Rfc7662AccessTokenResolver.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Rfc7662AccessTokenResolver.java
@@ -15,7 +15,9 @@
  */
 package org.forgerock.opendj.rest2ldap.authz;
 
+import static org.forgerock.opendj.rest2ldap.Rest2ldapMessages.*;
 import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.forgerock.opendj.rest2ldap.authz.Utils.newAccessTokenException;
 import static org.forgerock.util.Reject.checkNotNull;
 
 import java.io.IOException;
@@ -99,19 +101,18 @@
             public AccessTokenInfo apply(final Response response) throws AccessTokenException {
                 final Status status = response.getStatus();
                 if (!Status.OK.equals(status)) {
-                    throw new AccessTokenException(
-                            "Authorization server returned an error: " + status, response.getCause());
+                    throw newAccessTokenException(
+                            ERR_OAUTH2_RFC7662_RETURNED_ERROR.get(status), response.getCause());
                 }
 
                 try (final Entity entity = response.getEntity()) {
                     final JsonValue jsonResponse = asJson(entity);
                     if (!jsonResponse.get(RFC_7662_RESPONSE_ACTIVE_FIELD).defaultTo(Boolean.FALSE).asBoolean()) {
-                        throw new AccessTokenException(
-                                "Access token returned by authorization server is not currently active");
+                        throw newAccessTokenException(ERR_OAUTH2_RFC7662_TOKEN_NOT_ACTIVE.get());
                     }
                     return buildAccessTokenFromJson(jsonResponse, tokenSent);
                 } catch (final JsonValueException e) {
-                    throw new AccessTokenException("Invalid or malformed access token: " + e.getMessage(), e);
+                    throw newAccessTokenException(ERR_OAUTH2_RFC7662_INVALID_JSON_TOKEN.get(e.getMessage()), e);
                 }
             }
         };
@@ -129,7 +130,7 @@
             return new JsonValue(entity.getJson());
         } catch (final IOException e) {
             // Do not use Entity.toString(), we probably don't want to fully output the content here
-            throw new AccessTokenException("Cannot read response content as JSON", e);
+            throw newAccessTokenException(ERR_OAUTH2_RFC7662_CANNOT_READ_RESPONSE.get(), e);
         }
     }
 }
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Utils.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Utils.java
index a5cf1a8..65d1ca6 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Utils.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Utils.java
@@ -21,8 +21,10 @@
 import java.io.Closeable;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.forgerock.authz.modules.oauth2.AccessTokenException;
 import org.forgerock.http.protocol.Response;
 import org.forgerock.http.protocol.Status;
+import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.json.resource.ResourceException;
 import org.forgerock.util.promise.NeverThrowsException;
 import org.forgerock.util.promise.Promise;
@@ -32,6 +34,18 @@
 
     private Utils() { }
 
+    static IllegalArgumentException newIllegalArgumentException(final LocalizableMessage message) {
+        return new IllegalArgumentException(message.toString());
+    }
+
+    static AccessTokenException newAccessTokenException(final LocalizableMessage message) {
+        return newAccessTokenException(message, null);
+    }
+
+    static AccessTokenException newAccessTokenException(final LocalizableMessage message, final Exception cause) {
+        return new AccessTokenException(message.toString(), cause);
+    }
+
     static Runnable close(final AtomicReference<? extends Closeable> holder) {
         return new Runnable() {
             @Override
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties
new file mode 100644
index 0000000..d1ea5cd
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties
@@ -0,0 +1,110 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
+
+# Configuration errors
+ERR_FAIL_PARSE_CONFIGURATION_1=Unable to start Rest2Ldap Http Application due to the configuration error: '%s'
+ERR_CONFIG_OAUTH2_UNSUPPORTED_ACCESS_TOKEN_RESOLVER_2= '%s'is not a supported access token resolver. Must be one of '%s'
+ERR_CONIFG_OAUTH2_INVALID_INTROSPECT_URL_3=The token introspection endpoint '%s' is not a valid URL: '%s'
+ERR_CONIFG_OAUTH2_CACHE_ZERO_DURATION_4=The cache expiration duration cannot be zero
+ERR_CONIFG_OAUTH2_CACHE_UNLIMITED_DURATION_5=The cache expiration duration cannot be unlimited
+ERR_CONFIG_OAUTH2_CACHE_INVALID_DURATION_6=Malformed duration value '%s' for cache expiration. \
+ The duration syntax supports all human readable notations from day ('days'', 'day'', 'd'') to nanosecond \
+ ('nanoseconds', 'nanosecond', 'nanosec', 'nanos', 'nano', 'ns')
+ERR_CONFIG_UNSUPPORTED_BIND_STRATEGY_7=Unsupported bind strategy '%s'. Must be one of '%s'
+ERR_CONFIG_INVALID_AUTHZID_TEMPLATE_8=Invalid authorization ID template: '%s'.\
+ Templates must start with one of the following elements: '%s'
+ERR_CONFIG_INVALID_AUTHENTICATION_9=Only simple authentication is supported
+ERR_CONFIG_INVALID_SECONDARY_LDAP_SERVER_10=secondaryLDAPServers configuration must contain a json array
+ERR_CONFIG_SERVER_CIRCULAR_DEPENDENCIES_11=The LDAP server configuration '%s' could not be parsed because of \
+ potential circular inheritance dependencies
+ERR_CONFIG_NAMING_STRATEGY_DN_AND_ID_NOT_DIFFERENT_12=Naming strategy DN and ID must be different
+ERR_CONFIG_NO_MAPPINGS_PROVIDED_13=No mappings provided in configuration
+ERR_CONFIG_NO_MAPPING_IN_CONFIGURATION_14=Unknown mapping. The configuration mapping must be one of '%s'
+ERR_CONFIG_UNKNOWN_WRITABILITY_15=Unknown writability '%s'. Must be one of %s
+ERR_CONFIG_UNKNOWN_NAMING_CONFIGURATION_16=Unknown naming strategy '%s'. Must be one of %s
+
+# Runtime errors
+ERR_AUTHZID_DECODER_PRINCIPAL_CANNOT_BE_DETERMINED_17=The request could not be authorized because the required \
+ security principal '%s' could not be determined
+ERR_AUTHZID_DECODER_PRINCIPAL_INVALID_DATA_TYPE_18=The request could not be authorized because the required \
+ security principal '%s' had an invalid data type
+ERR_AUTHZID_DECODER_RESPONSE_19=Invalid configuration
+ERR_RESOLVING_AUTHZID_TEMPLATE_20=Unable to resolve oauthzid template placeholders for access token '%s': '%s'
+# Runtime errors > OAuth2 > CTS Resolver
+ERR_OAUTH2_CTS_INVALID_TOKEN_TYPE_21=The token '%s' must be an access token, but it is a '%s'
+ERR_OAUTH2_CTS_TOKEN_NOT_FOUND_22=Unable to find the token '%s' in the CTS because: '%s'
+ERR_OAUTH2_CTS_TOKEN_RESOLUTION_23=Unable to resolve access token '%s' due to the following reason: '%s'
+ERR_OAUTH2_CTS_INVALID_JSON_TOKEN_24=Json of token '%s' is malformed
+# Runtime errors > OAuth2 > File Resolver
+ERR_OAUTH2_FILE_NO_TOKEN_25=Unable to find token file '%s'
+ERR_OAUTH2_FILE_INVALID_JSON_TOKEN_26=Malformed token file '%s'. Details: '%s'
+# Runtime errors > OAuth2 > RFC-7662 Resolver
+ERR_OAUTH2_RFC7662_RETURNED_ERROR_27=Authorization server returned an error: '%s'
+ERR_OAUTH2_RFC7662_TOKEN_NOT_ACTIVE_28=Access token returned by authorization server is not currently active
+ERR_OAUTH2_RFC7662_INVALID_JSON_TOKEN_29=Invalid or malformed access token: '%s'
+ERR_OAUTH2_RFC7662_CANNOT_READ_RESPONSE_30=Cannot read response content as JSON
+
+# Runtime rest to ldap processing
+ERR_CREATION_READ_ONLY_FIELD_31=The create request cannot be processed because it attempts to create the \
+ read-only field '%s'
+ERR_REMOVE_REQUIRED_FIELD_32=The %s request cannot be processed because it attempts to remove the required field '%s'
+ERR_MODIFY_READ_ONLY_FIELD_33=The %s request cannot be processed because it attempts to modify the read-only field '%s'
+ERR_PATCH_READ_ONLY_FIELD_34=The patch request cannot be processed because it attempts to patch the read-only field '%s'
+ERR_ARRAY_FOR_SINGLE_VALUED_FIELD_35=The request cannot be processed because an array of values was \
+ provided for the single valued field '%s'
+ERR_NO_ARRAY_FOR_MULTI_VALUED_FIELD_36=The request cannot be processed because an array of values was \
+ not provided for the multi-valued field '%s'
+ERR_PATCH_APPEND_IN_SINGLE_VALUED_FIELD_37=The patch request cannot be processed because it attempts to append a \
+ value to the single valued field '%s'
+ERR_PATCH_INDEXED_APPEND_TO_MULTI_VALUED_FIELD_38=The patch request cannot be processed because it attempts to perform \
+ an indexed append of an array of values to the multi-valued field '%s'
+ERR_PATCH_INDEXED_OPERATION_39=The patch request cannot be processed because it included an indexed patch \
+ operation '%s' which is not supported by this resource provider
+ERR_UNRECOGNIZED_FIELD_40=The request cannot be processed because it included an unrecognized field '%s'
+ERR_FIELD_WRONG_TYPE_41=The request cannot be processed because it included the field '%s' whose value \
+ is the wrong type: an object is expected
+ERR_PATCH_ADD_NO_VALUE_FOR_FIELD_42=The patch request cannot be processed because it included an add patch operation \
+ but no value(s) for field '%s'
+ERR_PATCH_UNSUPPORTED_OPERATION_43=The patch request cannot be processed because it included an unsupported \
+ type of patch operation '%s'
+ERR_MVCC_NOT_SUPPORTED_44=Multi-version concurrency control is not supported by this resource
+ERR_MVCC_NO_VERSION_INFORMATION_45=The resource could not be accessed because it did not contain any version \
+ information, when the version '%s' was expected
+ERR_MVCC_VERSIONS_MISMATCH_46=The resource could not be accessed because the expected version '%s' does \
+ not match the current version '%s'
+ERR_REFERENCE_FIELD_NO_PRIMARY_KEY_47=The request cannot be processed because the reference field '%s' \
+ contains a value which does not contain a primary key
+ERR_REFERENCE_FIELD_MULTIPLE_PRIMARY_KEYS_48=The request cannot be processed because the reference field \
+ '%s' contains a value which contains multiple primary keys
+ERR_REFERENCE_FIELD_DOES_NOT_EXIST_49=The request cannot be processed because the resource '%s' referenced \
+ in field '%s' does not exist
+ERR_REFERENCE_FIELD_AMBIGUOUS_50=The request cannot be processed because the resource '%s' referenced in \
+ field '%s' is ambiguous
+ERR_ILLEGAL_FILTER_ASSERTION_VALUE_51=The request cannot be processed because it contained an illegal \
+ filter assertion value '%s' for field '%s'
+ERR_ENCODING_VALUES_FOR_FIELD_52=The request cannot be processed because an error occurred while encoding \
+ the values for the field '%s': '%s'
+ERR_UNRECOGNIZED_JSON_VALUE_53=Unrecognized type of JSON value: '%s'
+ERR_CLIENT_PROVIDER_RESOURCE_ID_MISSING_54=Resources cannot be created without a client provided resource ID
+ERR_NOT_YET_IMPLEMENTED_55=Not yet implemented
+ERR_ACTION_NOT_SUPPORTED_56=The action '%s' is not supported
+ERR_PASSWORD_MODIFY_SECURE_CONNECTION_57=Password modify requires a secure connection
+ERR_PASSWORD_MODIFY_USER_AUTHENTICATED_58=Password modify requires user to be authenticated
+ERR_DECODING_CONTROL_59=Unable to decode ldap control: '%s'
+ERR_ERROR_RESPONSE_60=An error occurred while processing the request '%s': '%s' (details: '%s')
+ERR_RUNTIME_EXCEPTION_61=A runtime exception occurred wile processing the request '%s': '%s'
+ERR_PASSWORD_MODIFY_REQUEST_IS_INVALID_62=The password modify request has been rejected because it is invalid. \
+ A password modify request may contain two string valued fields 'oldPassword' and 'newPassword'
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ca_ES.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ca_ES.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ca_ES.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_de.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_de.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_de.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_es.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_es.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_es.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_fr.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_fr.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_fr.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ja.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ja.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ja.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ko.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ko.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_ko.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_pl.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_pl.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_pl.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_CN.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_CN.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_CN.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_TW.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_TW.properties
new file mode 100644
index 0000000..99be5ab
--- /dev/null
+++ b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap_zh_TW.properties
@@ -0,0 +1,15 @@
+#
+# The contents of this file are subject to the terms of the Common Development and
+# Distribution License (the License). You may not use this file except in compliance with the
+# License.
+#
+# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+# specific language governing permission and limitations under the License.
+#
+# When distributing Covered Software, include this CDDL Header Notice in each file and include
+# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+# Header, with the fields enclosed by brackets [] replaced by your own identifying
+# information: "Portions Copyright [year] [name of copyright owner]".
+#
+# Copyright 2016 ForgeRock AS.
+#
diff --git a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolverTestCase.java b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolverTestCase.java
index ee9959f..b455206 100644
--- a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolverTestCase.java
+++ b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/authz/CtsAccessTokenResolverTestCase.java
@@ -122,7 +122,7 @@
     }
 
     @Test(expectedExceptions = ExecutionException.class, expectedExceptionsMessageRegExp =
-                  ".*The token 'test-token' must be an access token, but it is a \"refresh_token\"")
+                  ".*The token 'test-token' must be an access token, but it is a 'refresh_token'")
     public void testInvalidTokenType() throws Exception {
         final SearchResultEntry entry = mock(SearchResultEntry.class);
         final Attribute attribute = mock(Attribute.class);

--
Gitblit v1.10.0