2

I have a following SDN 4 entities:

Decision, Characteristic and Value:

@NodeEntity
public class Value {

    private final static String SET_FOR = "SET_FOR";
    private final static String SET_ON = "SET_ON";

    @Relationship(type = SET_FOR, direction = Relationship.OUTGOING)
    private Decision decision;

    @Relationship(type = SET_ON, direction = Relationship.OUTGOING)
    private Characteristic characteristic;

    @Index(unique = false)
    private Object value;

    private String description;
...

}

I'd like to add a multi-language support for Value in order to be able provide a Value.value and Value.description at any language.

Could you please show a proper way to implement this with a current schema ?

Should I for example add an extra nodes there (associated with a Value node) that will represent value/description pair for every new language or it can be done by an introducing new language-specific properties inside of existing Value node ?

alexanoid
  • 24,051
  • 54
  • 210
  • 410

1 Answers1

5

There are many options for adding multi-language support through Spring Data Neo4j.

One approach, outlined in https://graphaware.com/neo4j/2016/09/29/internationalization-with-spring-neo4j.html (and authored by me), may give you a head start on implementing your solution.

After following the blog’s set up and configuration for your SDN project, for each of your Value objects you could use Cypher to define two MessageDefinitions, one with a code that matches the Value.value and another who’s code matches the Value.description. Going this route, you are essentially adding extra nodes (i.e.: MessageDefinition nodes) that are associated with a Value node that represent the value and description with an internationalized and localized message. In other words, the Value’s value and description properties serve as keys to corresponding MessageDefinition nodes.

With your project configured and desired MessageDefinitions defined in your Neo4j, you could use the following code in a controller or service to obtain your internationalized and localized values:

    Value value = valueRepository.findOne(id);

    Object arguments[] = new Object[] {};
    Locale locale = LocaleContextHolder.getLocale();

    String valueMessageKey = value.getValue();
    String i18Value = messageSource.getMessage(valueMessageKey, arguments, "defaultValue", locale);

    String descriptionMessageKey = value.getDescription();
    String i18Description = messageSource.getMessage(descriptionMessageKey, arguments, "defaultDescription", locale);

    System.out.println("i18Value: " + i18Value);
    System.out.println("i18Description: " + i18Description);

It’s worth noting that a weakness of this approach is that the MessageDefinition and Value objects are related through a matching node property, rather than an underlying Neo4j relationship, which is less efficient as it doesn’t take advantage of Neo4j’s core strength (ie: relationships). While this is something to be aware of, if it’s an actual issue or not is dependent on your use cases. If it is a deal breaker, the CypherMessageSource project could be modified to more closely match your requirements.

Looking at your sample code, please note that you may want to change the type of your Value.value property from Object to String so as to ensure that it is a reliable key.

Eric Spiegelberg
  • 602
  • 1
  • 8
  • 14
  • Thanks for your detailed answer! I need a time in order to understand and test it. I can't change the `Value.value` to `String` because according to my business logic it can be any type. Also, I want my users to provide functionality to dynamically set different internationalized and localized messages for description/value. Is it possible with SDN to dynamically operate with `MessageDefinitions` in order to do it ? – alexanoid May 17 '17 at 17:35
  • I am afraid I don't understand what you mean by "Is it possible with SDN to dynamically operate with MessageDefinitions in order to do it?" If you are asking if you could use SDN to create a domain object that maps to the underlying ``MessageDefinition``s and then manipulate the ``MessageDefinition`` as part of your application CRUD, yes, that is totally doable. – Eric Spiegelberg May 17 '17 at 21:49
  • Thanks Eric. Yes, you are correct. I'm asking about possibility with SDN to create a domain object that maps to the underlying MessageDefinition. Right now it is not clear to me how to deal with a dynamic properties.. for example I can define a domain object with en_US property declared but latter dynamically add to my MessageDefinition node another property.. let's say - fr_FR. How to deal with this new property at SDN domain entity object with no need to declare a new field and recompile the code ? – alexanoid May 23 '17 at 06:46
  • There is an upcoming @Properties annotation for maps, to be available in SDN5, that may be exactly what you want. In the mean time, I would forgo a SDN domain object that maps to an underlying MessageDefinition in favor of instead using Cypher to query for the desired properties. – Eric Spiegelberg May 25 '17 at 13:38