Coldbox and VueJS untangled

Tag: cbi18n

cbi18n-json-resources: localization with JSON resources

This week I created my first official forgebox package: cbi18n-json-resources , a cbi18n JSON ResourceService. This module tries to improve the cbi18n Ortus module by offering

  • json resource files instead of java resources
  • locales organized by directory instead of partial filenames
  • optional default resource file(s)
  • hierarchical resources, so both en_GB and en_US can be handled by the same resource file, except for the different country-specific translations
  • and an interceptor for missing translations

So why this module instead of improving the cbi18n module itself?

Continue reading

Cfcookie or cookieStorage?

Coldbox has the cbstorages module which can be used as an API for accessing persistent storage such as cookie, session, application, cache and more. The question is: why should I use such storage if there is cfcookie or something simple as as session struct?

Let me explain with some code. I was working on updating the cbi18n module where we can use session, client, cookie or request scope to store the currently selected locale. In code this is getting ugly soon, with code like this

switch(instance.localeStorage){
  case "session" : { storage = session; break; }
  case "client"  : { storage = client; break;  }
  case "cookie"  : { storage = cookie; break;  }
  case "request" : { storage = request; break; }
}

and in other places in the code:

<!--- Storage of the Locale in the user storage --->
<cfif instance.localeStorage eq "session">
  <cfset session.DefaultLocale = arguments.locale>
<cfelseif instance.localeStorage eq "client">
  <cfset client.DefaultLocale = arguments.locale>
<cfelseif instance.localeStorage eq "request">
  <cfset request.DefaultLocale = arguments.locale>
<cfelse>
  <cfcookie name="DefaultLocale" value="#arguments.locale#" />
</cfif>
Continue reading

Internationalization (i18n) in a ColdBox REST API

When developing a ColdBox REST API we wanted to add multilingual capacities. Coldbox has a nice module cbi18n for this.  When you set a new locale using

i18n.setfwLocale(newLocale);

this locale will usually be saved in a cookie and sent back with every request. But for our REST API we are looking for a more standard way of content-negotiation. We want to set an Accept-language header on every request and return a Content-Language header for one of our supported languages. The Accept-language can contain multiple choices, and each choice can have language, country and a q factor which specifies a preference. Example:

Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5

In our case we are only serving two languages, English (en) and Dutch (nl) which is the default if no header is specified. So, in our header we need to find out which language (nl, en or something else) is requested and if it is not Dutch (nl) we serve English. In a later stage we might add German for some customers but for now these two languages are sufficient.

Coldbox interceptors are the perfect vehicle for this kind of logic. We define a LanguageInterceptor which has the following code:

// Language interceptor
component{
	property name = "i18n"				inject="i18n@cbi18n";
	
	void function configure(){
	}

	function preProcess( event, interceptData, buffer, rc, prc ) {
		var languageHeader =event.getHTTPHeader( "Accept-Language", "nl" );
		// get first language from comma separated list
		//cleanup for potential ;q weighting factor
		//plus cleanup for potential - dash separator
		var firstLanguage = listFirst(listFirst(listFirst(languageHeader),";"),"-");
		var newLocale = ( firstLanguage == "nl") ? "nl_NL" : "en_US";
		var contentLanguage = ( firstLanguage == 'nl') ? "nl-NL" : "en-US";
		i18n.setfwLocale(newLocale);
		event.setHTTPHeader( name = "Content-Language", value = contentLanguage );
	}
}

As you can see from the listfirst/listfirst/listfirst line, there is some parsing involved, because there might be multiple language entries separated by a comma. Each of these entries could have a q factor appended (after a ; character) and finally there might be a country designation after a . So finally we end up with nl, en or something else. Coldfusion locales are formattet as nl_NL or en_US for example, and in the Content Language returned everything should be formatted with a dash instead of an underscore.

Finally, don’t forget to register your interceptor in Coldbox.cfc or your ModuleConfig.cfc!

© 2021 ShiftInsert.nl

Theme by Anders NorenUp ↑