Spring Message Resource Bundles - Suitable for white labelling and versioning? - spring-mvc

I wonder if anyone can help. We are putting together a Spring MVC & Webflow app, and want to put all screen text etc in a database backed message resource bundle. I've got a simple implementation of this working no problem. However, we need to support white labeling the application, including versioning of the text.
When I say 'white labeling' I mean that the core application needs to be branded for different commercial brands. The css elements of the branding is easy - we will be using Spring Themes. But the branding extends to different screen text. For example, brandX might ask "What is your name", and brandY might ask "Please enter your name".
In addition, we need to support versioning of the screen text per brand. This is give a consistent user journey and message to a customer - eg: if they see a given set of screen labels on day 1 and save their quote, they should see the same set of screen labels etc when they retrieve their quote on day 10, even if there have been 5 iterations of screen text for that brand in the mean time. (in reality the frequency of changes wont be that often, but we still need to support it)
I've been playing with this for a while, and in my early experimentation thought I could simply prefix the message keys in the resource bundle:
brandX.firstName = What is your firstname?
brandY.firstName = Please enter your firstname
But this feels wrong on several counts.
Unless we have a view per brand (which we might have to), then the view needs to somehow apply the prefix based on either something in the model or the theme. It feels wrong for the view to know about the model in order to select the right messages to display
I dont know how to apply versioning (other than adding it to the composite key = brandX.firstname.v2 = What is your firstname?)
All in all, I'm coming to the conclusion that this is not what message resource bundles are for - they are great for locale based internationalisation (which is what they are for!), but now I am trying to do something quite different with them. It feels that message resource bundles as a solution may not be right for my requirement.
Has anyone else done anything like this? How did you go about solving it?
Cheers
Nathan

I've done something similar to this with a themed web app that could be deployed with different themes or branding. I also needed to have slightly different labels depending on the "brand" being deployed.
The solution I used was to specify the same i18n code in the JSP page but to select the appropriate message bundle according the "brand" being used in the particular deployed instance. So instead of selecting different message bundles according to conventional (language-based) locale, I forced Spring to select a custom i18n bundle by specifying the custom locale via a org.springframework.web.servlet.i18n.CookieLocaleResolver. This in turn was configured by a particular property in the app's main properties file. Here's some of my dispatcher-servlet.xml file:
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="${i18n.code}"/><!-- value from app.properties -->
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
The only hand-cranking needed was in deployment of a particular branded version - a shell script did the deployment and it copied a particular properties file, e.g., cp app.properties.BRAND_X app.properties (the other file that needed manipulating was web.xml).
Edit: not sure about the versioning part but you could probably pull that out of the app.properties file as well but specify it in the JSP like:
<!-- custom tag that reads a properties file -->
<c:set var="version"><app:propertyLoader bundle="app" property="site.version"/></c:set>
<fmt:message key="form.firstName.${version}"/>

Related

How can I easily override SEO Sulu CMS page extension in Symfony?

I want to override the SeoStructureExtension with my own implementation, which will support OpenGraph (OG) tags.
What is the easiest way to override it and add additional inputs?
I am afraid to say that overriding the SeoStructureExtension file can not be achieved very easily... The fields it saves are hardcoded. So the first thing you would have to do is override the sulu_page.extension.seo service, which references this class. I would say your best bet to achieve this, is to decorate this service.
The other part you have to extend is the XML file describing the page_seo form. Luckily this part is a little bit easier. Your Sulu installation should already come with a config/forms folder, where you can put a file similar to the original page_seo form. Give it the same key (page_seo) and only add the new fields you want to add (the name of the properties have to match what you are implementing in the decorated service). If you e.g. want to add a new text field, this file would look something like this:
<?xml version="1.0" ?>
<form xmlns="http://schemas.sulu.io/template/template"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.sulu.io/template/template http://schemas.sulu.io/template/form-1.0.xsd"
>
<key>page_seo</key>
<properties>
<property name="ext/seo/ogTitle" type="text_line">
<meta>
<title lang="en">OG Title</title>
</meta>
</property>
</properties>
</form>
Mind the ext/seo/ prefix before ogTitle, which is need for the information to be passed to the SeoStructureExtension.
I also think that these fields might make sense to be added to the core of Sulu. I would be happy if you create an issue, explaining what fields exactly you need etc. Then we can discuss if we implement it in the core as well, so that you don't have to add this manually in future versions.

Custom type not showing up in rule config

Trying to add a folder rule which should specialize cm:content to our custom type my:content (which inherits from cm:content).
We have configured the following in share-config-custom.xml:
<type name="cm:content">
<subtype name="my:content"/>
</type>
Our type shows up correctly in the specialize type action in the document library, but when trying to specify a rule the listbox that should contain our type remains empty. :(
What could we be missing?
You need to add to web-client-config-custom.xml in alfresco/extension
<config evaluator="string-compare" condition="Action Wizards"
replace="true">
<subtypes>
<type name="my:content" />
</subtypes>
<specialise-types>
<type name="my:content" />
</specialise-types>
</config>
And then the trick is to provide title & description for the types in the content model or via messages/properties; otherwise they will not be there.
Wrote about similar issues here: http://experiencewithalfresco.blogspot.dk/2012/08/remember-to-define-title-and.html
For adding custom messages you need to create custom-message-context.xml
<beans>
<bean id="mycompany.resources" class="org.springframework.extensions.surf.util.ResourceBundleBootstrapComponent">
<property name="resourceBundles">
<list>
<value>alfresco.messages.custom</value>
</list>
</property>
Then create custom.properties file and place it in /shared/classes/alfresco/message folder.
And for adding custom type to rule your config should be working only thing to make sure is config inside which you have put sub-type related config is proper.
Disclaimer: This answer is for Alfresco 6.2.2+.
Answering an old thread. For me, I tried this thread all vague answers on Alfresco Hub and nothing worked out.
I have been through this nightmare. Its frustrating and I don't know why Alfresco team relies on "Display Label" instead of "Name".
As shown in the screenshot, I was missing Display Label. As soon as I edited my custom type and provided Display Label, all worked as expected.
If I would have designed it, I would include, Name and Display Label both in the drop down in my rule window.
Hope it helps someone like me.

Why a scorm package cannot be reverse engineered to open and edit its contents?

I have a set of scorm learning courses and I want to edit them, to add new pages and content, not just alter existing ones. So, after searching the web I couldn't find a way to edit any scorm content in any existing tool.
Do you experts know what are the reasons for not having an scorm editing tool?
PS: It's scorm 2004 packages.
Content packages are just zips containing two major pieces - the imsmanifest.xml and the content. The manifest file tells the LMS how the content is organized (like the table of contents in a book) and what resources make up the content/course (like a packing slip). And the content is what the LMS shows to the learner as the course, basically SCOs (generally web pages, swf, etc) and assets (images, pdf, supporting stuff).
What Brian G is saying is that the resources that make up the content might not be able to be modified, they could be swfs from a flash project or some other compiled software.
But that doesn't mean you can't add sequencing or other content, you just need to unzip the content package, modify the manifest right, add your new SCOs, and zip up your new content as a package.
Say for instance you have a package that has 3 SCOs and you want to add an intro page. You can do that by adding another <item> to the <organization> and then the path to what the LMS would deliver <resource> under <resources>.
<organizations default="course">
<organization identifier="course">
<title>The course</title>
<!-- add another item for your intro -->
<item identifier="intro" identifierref="INTRO">
<title>Introduction</title>
</item>
<item identifier="sco1" identifierref="SCO1">
<title>SCO 1<title>
</item>
<item identifier="sco2" identifierref="SCO2">
<title>SCO 2<title>
</item>
<item identifier="sco3" identifierref="SCO3">
<title>SCO 3<title>
</item>
</organization>
</organizations>
<resources>
<resource identifier="INTRO" type="webcontent" adlcp:scormType="sco" href="scos/my_intro.html">
<file href="scos/my_intro.html" />
<!-- possible other needed files, or other resources needed -->
<dependency identifierref="APIWRAPPER" />
</resource>
<resource identifier="SCO1" type="webcontent" adlcp:scormType="sco" href="scos/sco1.html">
<file href="scos/sco1.html" />
</resource>
<!-- other sco resources -->
<resource identifier="APIWRAPPER" type="webcontent" adlcp:scormType="asset">
<file href="assets/APIWrapper.js" />
</resource>
</resources>
ADL modified an open source project to do content packaging. It's called Reload and it is designed to help you create the manifest and package your content. It also will open existing packages and allow you to make edits. You can download it here http://www.adlnet.gov/wp-content/uploads/2011/07/ADL_SCORM_2004_RELOAD_Editor_1_1.zip .. There's also more resources and info on ADL's site: http://www.adlnet.gov/scorm/ .
The CAM book in the SCORM Document Suite has all the gritty details about packaging your content. The SN book goes over everything to know about sequencing. You can find the books here: http://www.adlnet.gov/wp-content/uploads/2011/07/SCORM_2004_4ED_v1_1_Doc_Suite.zip
Another resource by ADL are the Content Developer and ISD guides. They have tips, guidance, and examples for developers working with SCORM. http://www.adlnet.gov/scorm-users-guides-for-instructional-designers-and-programmers-are-now-available/
What you call SCORM Content is in fact simply Web Content that can communicate to a LMS using SCORM API. So your question is exactly equivalent to "Why a webpage cannot be reverse engineered to edit its contents" or "Why a Flash movie cannot be reverse engineered".
The correct answer is "Because whoever created the files didn't want you to". And also "They can be hacked.. to some limited extent..".
Most e-learning courses (that's what SCORM is usually used for) are produced in one of the rapid authoring tools, e.g. Adobe Captivate, Articulate Storyline, Articulate Presenter, Lectora and others. These tools use source files that contain all course content, metadata, resources, images, media etc. They output a mix of Flash and HTML files that can be edited to the same extent you can hack anything you see on web, but without sources your question is like asking "Why this nice image I downloaded cannot be reverse egineered into vectors and layers and opened in Photoshop".
In fact, some tools (like CourseLab) use exact same XML file for storing/editing contents and displaying the contents. Only in the former case it is loaded into the editor, and in the latter case it is played back via a JS-based player.
If you outline the exact problem that you're facing (right now it seems like you're just venting your frustration), people might be able to help you better.
I think you're misunderstanding what SCORM is - it's just an API and data model for SCO <-> LMS communication. How the content itself is developed isn't part of the SCORM standard, that's up to the individual developer to decide and implement.

Is it possible to create a constraint based on another defined type in Alfresco?

I can find anything that would suggest this is possible or otherwise I have the following declared models.
The product:
<type name="syn:produit">
<title>Produit</title>
<parent>cm:cmobject</parent>
<properties>
<!-- properties defined -->
</properties>
</type>
product order:
<type name="syn:produitCommande">
<title></title>
<parent>cm:object</parent>
<properties>
<propert name="productType">
</property>
</properties>
</type>
I would like to constraint the productType of the syn:produitCommande to a list of syn:produit. Is it possible to do this OOTB (I think no is the answer to that), I have seen example codes of dynamic constraints but a lot of "That's a bad idea" warnings that goes with the code. I need advice on how to proceed with resolving this issue with possible code examples. (Not entirely understood the text on how to build the custom constraint yet.)
Fist to answer your question, there is No XML config where you can configure that.
A DB example from the forum is here
I probably wouldn't make a custom constraint if it's only for UI usage.
My approach would be to make a custom form control (in share) which loads a search (through Ajax in json format) from the Repository.
It really is bad idea.
There will be various problems as with each type fix set of properties attached so you cannot configure this thing though model for sure.
I think you have a requirement where you don't want to fix the type of document on creation.
you want to provide the option to user to allow change type of document after it is created right?In that case you can create all your custom content types in model and there is one action called change type in alfresco share which you can configure to showup all your custom content types.In that way even after creating the content you will be able to change its content type.

How can I add a classic portlet at the root of the portal when my product is installed?

What is the simplest way to do this? I added it in the portlets.xml file in profiles/default. It is now available in the "Add portlet" dropdown when I go to ##manage-portlets. But I need it automatically created.
Is it possible to explicitly specify the set of portlets I want on the right and left columns inside my profiles/default?
You can register your classic portlet trough the portlets.Classic portlet, configured with a template and macro name, using an assignment element in your portlets.xml file:
<assignment
manager="plone.rightcolumn"
category="context"
key="/"
type="portlets.Classic"
name="my-classic-portlet"
visible="1">
<property name="template">templatename</property>
<property name="macro">macroname-found-in-template</property>
</assignment>
See the Portlets section of the GenericSetup manual on Plone.org or the original PLIP for details on Portlet assignments and GenericSetup.
The properties match the portlet dataprovider interface, see the Classic Portlet source code for the interface definition for the Classic Portlet.
The portlets.xml file does a few different things and there's a difference between registering a kind of portlet that can be added and actually adding a portlet, both of which can be done in portlets.xml. You need to use an "assignment" element to add a portlet:
<assignment
manager="plone.rightcolumn"
category="context"
key="/plone"
type="plone.portlet.static.Static"
name="foo-portlet">
<property name="header">Foo Portlet Title</property>
<property name="text">Foo portlet contents...</property>
</assignment>
For a not experienced product developer (even the others too) the easiest way to achieve this kind of automation is:
do manual configuration o
assignment like a any other common
plone user/administrator, going in
the portal's root and adding the
portlets you want.
go in zmi -> portal_setup -> export
tab
select portlet step and export it
use portlets.xml in the tar.gz just
got.
this xml contains all what you need: registrations and assignments... actually, even a little more stuff so may be a good thing to make a clean of what unneeded in it.

Resources