That’s a nice UI, but have you internationalized your JavaScriptLovemore NalubeDeveloperUniversity of Cape Town17 June 2010
OverviewEvil ‘n’ Good codeDifficulties of i18n-sing JSWhy Sakai's needs are uniqueRESTful access to a Sakai Message bundleDEMO: Course Evaluations and the SMS Credits Transfer tool211th Sakai Conference - June 15-17, 2010
Sample nasty codeCommon evil case:Good case:var response = xhr.status;alert("You have an error caused by" + response);var response = xhr.status;alert(messageLocator.getString( “ui.site.error”, response);311th Sakai Conference - June 15-17, 2010
Difficulties of i18n-sing JSCannot rely on browser localeMost users are unaware of the presence of this browser settingJS alone cannot get Sakai Preferences locale settingDo we have to re-create message bundles?Inconsistencies, more effort, harder to maintainnavigator.language /* Mozilla */|| navigator.userLanguage /* IE */ 411th Sakai Conference - June 15-17, 2010
Why Sakai's needs are different2 stages of language customization:User preferenceServer configurationSakai’s own locale lookup is used in many toolsExtend this ability to client side toolsDate formats vary511th Sakai Conference - June 15-17, 2010
Fun stuffSteps to follow11th Sakai Conference - June 15-17, 20106
Step 1: RESTful access to a Sakai Message bundleTool level Entity Providercreates a fixed URI for getting a message bundleIn a webapp, make a provider class:ResourceLoader resourceLoader = new ResourceLoader(MESSAGES_BUNDLE_DIR); // eg. where  MESSAGES_BUNDLE_DIR = 	"org.sakaiproject.evaluation.tool.bundle.messages";             *** NEEDS TO BE A FOLDER!return the key-value equivalents ofresourceLoader.entrySet().iterator();in (for example) HashMap711th Sakai Conference - June 15-17, 2010
Step 2: RESTful access to a Sakai Message bundlePOM modificationscreates a fixed URI for getting a message bundleDepend on Entity Broker:811th Sakai Conference - June 15-17, 2010
Step 3: RESTful access to a Sakai Message bundleCall Ajax file at JS doc ready:       $.ajax({            url: “/direct/evals-resources/bundle.json”,            global: false,            cache: true,            dataType : "json",            success: function(messageBundleJSON){                messageBundle = messageBundleJSON.data;            }        }); 911th Sakai Conference - June 15-17, 2010
Step 4: RESTful access to a Sakai Message bundleStart using:var removalString = fluid.messageLocator( messageBundle )(["administrate.general.enable.response.removal"]);  *** For values with variable replacers like {0}  	as in removeitem.removed.user.message: "Item ({0}) has been removed",// Decoding the key "removeitem.removed.user.message". //RESULT  removalString = "Item (3) has been removed"var removalString =	fluid.messageLocator( messageBundle )(["removeitem.removed.user.message"], 3 );1011th Sakai Conference - June 15-17, 2010
Step 4.5: RESTful access to a Sakai Message bundleSimpler way to use:Get a language string like this://retrieve the message strings for key        messageLocator: function(key, params){            return fluid.messageLocator( messageBundle )([key], params);                    },var alertError = evalTemplateUtils.messageLocator("evalsettings.email.sent.from", 	helpEmail.toLowerCase()));//if helpEmail.toLowerCase() = help@sakaiproject.org//prints: All emails will be sent from help@sakaiproject.org1111th Sakai Conference - June 15-17, 2010
Course EvaluationsSMS Credits TransferDemo11th Sakai Conference - June 15-17, 201012
More info.http://blogs.uct.ac.za/blog/lovemores-world/2009/09/28/consuming-a-sakai-java-messages-resource-bundle-in-javascript-with-fluid-i8nSMS code: https://source.sakaiproject.org/contrib//sms/sms/trunk/user-tool/

That’s a nice UI, but have you internationalized your Javascript?

  • 1.
    That’s a niceUI, but have you internationalized your JavaScriptLovemore NalubeDeveloperUniversity of Cape Town17 June 2010
  • 2.
    OverviewEvil ‘n’ GoodcodeDifficulties of i18n-sing JSWhy Sakai's needs are uniqueRESTful access to a Sakai Message bundleDEMO: Course Evaluations and the SMS Credits Transfer tool211th Sakai Conference - June 15-17, 2010
  • 3.
    Sample nasty codeCommonevil case:Good case:var response = xhr.status;alert("You have an error caused by" + response);var response = xhr.status;alert(messageLocator.getString( “ui.site.error”, response);311th Sakai Conference - June 15-17, 2010
  • 4.
    Difficulties of i18n-singJSCannot rely on browser localeMost users are unaware of the presence of this browser settingJS alone cannot get Sakai Preferences locale settingDo we have to re-create message bundles?Inconsistencies, more effort, harder to maintainnavigator.language /* Mozilla */|| navigator.userLanguage /* IE */ 411th Sakai Conference - June 15-17, 2010
  • 5.
    Why Sakai's needsare different2 stages of language customization:User preferenceServer configurationSakai’s own locale lookup is used in many toolsExtend this ability to client side toolsDate formats vary511th Sakai Conference - June 15-17, 2010
  • 6.
    Fun stuffSteps tofollow11th Sakai Conference - June 15-17, 20106
  • 7.
    Step 1: RESTfulaccess to a Sakai Message bundleTool level Entity Providercreates a fixed URI for getting a message bundleIn a webapp, make a provider class:ResourceLoader resourceLoader = new ResourceLoader(MESSAGES_BUNDLE_DIR); // eg. where  MESSAGES_BUNDLE_DIR = "org.sakaiproject.evaluation.tool.bundle.messages";             *** NEEDS TO BE A FOLDER!return the key-value equivalents ofresourceLoader.entrySet().iterator();in (for example) HashMap711th Sakai Conference - June 15-17, 2010
  • 8.
    Step 2: RESTfulaccess to a Sakai Message bundlePOM modificationscreates a fixed URI for getting a message bundleDepend on Entity Broker:811th Sakai Conference - June 15-17, 2010
  • 9.
    Step 3: RESTfulaccess to a Sakai Message bundleCall Ajax file at JS doc ready:       $.ajax({            url: “/direct/evals-resources/bundle.json”,            global: false,            cache: true,            dataType : "json",            success: function(messageBundleJSON){                messageBundle = messageBundleJSON.data;            }        }); 911th Sakai Conference - June 15-17, 2010
  • 10.
    Step 4: RESTfulaccess to a Sakai Message bundleStart using:var removalString = fluid.messageLocator( messageBundle )(["administrate.general.enable.response.removal"]);  *** For values with variable replacers like {0}  as in removeitem.removed.user.message: "Item ({0}) has been removed",// Decoding the key "removeitem.removed.user.message". //RESULT  removalString = "Item (3) has been removed"var removalString = fluid.messageLocator( messageBundle )(["removeitem.removed.user.message"], 3 );1011th Sakai Conference - June 15-17, 2010
  • 11.
    Step 4.5: RESTfulaccess to a Sakai Message bundleSimpler way to use:Get a language string like this://retrieve the message strings for key messageLocator: function(key, params){ return fluid.messageLocator( messageBundle )([key], params); },var alertError = evalTemplateUtils.messageLocator("evalsettings.email.sent.from", helpEmail.toLowerCase()));//if helpEmail.toLowerCase() = help@sakaiproject.org//prints: All emails will be sent from help@sakaiproject.org1111th Sakai Conference - June 15-17, 2010
  • 12.
    Course EvaluationsSMS CreditsTransferDemo11th Sakai Conference - June 15-17, 201012
  • 13.