Coldbox Modules and I18n

Hi All,

I am starting a new project where I want to use modules to add
functionality in a dynamic way. I am looking at about 15-20 modules.
One requirement for the site is to have i18N in place, and use
getResource for every text.

I was reading about modules and i18N and I saw a ticket in Assembla
stating that it is not implemented at the moment to let each module
have it's own ResourceBundle file.

I want to be able to create a module, together with it's own
resourceBundle, so that if a client wants to update a site, they can
just drop the module folder and reinit.

Right now, I see the need to add the folder to modules, but also edit
the ResourceBundle to create the new keys.

According to the ticket, this was removed from the 3.5 build and moved
back to the backlog.

Is there a workaround for this? Or is there anything I can do, to help
speed up this process, since it would make my live (well, my life as a
programmer, anyway) a whole lot easier? I would like to help, but I am
going to need some pointers on what is the best way to do this.

By the way, my project is going to be an CRM application, I am
thinking of some kind of application like SugarCRM. I am thinking of
making this an open-source project.

So if anybody has a need for an application like this, maybe we can
share some ideas for this project. I am not looking for any help at
the moment, don't worry :wink: I would just appreciate some input!

Please let me know, if I can do anything to help!

Kind regards,


Hi Erik-Jan,

You can store key-value in database. Below all sample code is provided.
We are storing simple value, complex value and html templates in database.

coldbox.button.add -> Add Post

then create a interceptor

Here is example of my i18n service

// Constructor public I18Nservice function init(){ return this; }

public void function onDIComplete(){
variables.log = Logbox.getLogger(getMetadata(this).name);

var query1 = new Query(); var query2 = new Query();

var qryI18N1 = “”;
var qryI18N2 = “”;

query1.setSQL("SELECT * FROM base_i18n WHERE Locale = ‘en_GB’ ");
qryI18N1 = query1.execute().getresult();

query2.setSQL("SELECT * FROM base_i18n WHERE Locale = ‘fr_FR’ ");
qryI18N2 = query2.execute().getresult();

<cfset Coldbox.setSetting(“RBundles”, RBundles)>

my orm entity

component entityname=“Corei18n”
serializable=“false” {

property name=“i18nID” fieldtype=“id” ormtype=“int” generator=“native”;
// i18n parent …
property name=“i18nParentID” type=“numeric” ormtype=“int” default=“0”;
property name=“i18nKey” type=“string” ormtype=“string”;
property name=“i18nName” type=“string” ormtype=“string”;
property name=“i18nValue” type=“string” ormtype=“string”;
property name=“SectionName” type=“string” ormtype=“string” required=“true”;
property name=“HTMLTemplate” type=“string” ormtype=“text”;
property name=“TextTemplate” type=“string” ormtype=“text”;
property name=“Locale” type=“string” ormtype=“string” required=“true”;
property name=“IsComplex” type=“boolean” ormtype=“boolean” default=“0”;

public i18n function init(){

return this;


Create RequestContextDecorator and add below method

if(len(arguments.localeArg) > 1){ var locale = arguments.localeArg; }else{ var locale = request.currentLocale; } var strtRBundle = getController().getSetting("RBundles");

strtRBundle = strtRBundle[locale];
var rbString = strtRBundle[code];
}catch(any e){
var rbString = code;

// time to parameterise this string
if (!refind("{.+}", rbString, 1))
return rbString;

var params = rematch("({.*?}}?)", rbString);
var i = 1;
for (; i <= arrayLen(params); i++) {
var param = params[i];
var arg = rereplace(param, “{|}”, “”, “all”);
rbString = replace(rbString, param, args[i]);

return rbString;

Finally we are calling like this.

event.i18n(code=“coldbox.button.add”, localeArg=“fr_FR”) will return french text and so on…

Great plugin Sana, maybe you should commit this to ForgeBox :slight_smile:

Luis F. Majano
Ortus Solutions, Corp

ColdBox Platform:
Linked In:
IECFUG Manager:


Hey Sana!

Great work! :slight_smile:

What I also would suggest is defining a site level ‘allowed locales’ as list and looping them in loadBundle method instead of hardcoded locales.

JM2C. :slight_smile:



Hi Sana,

Thanks a lot for your respons! I will take a look at your code and
implement it in my application! I think I can use an XML file with all
resource keys per module, and insert them in the database via an
install function when the module is loaded. That way, all modules can
contain their own resource keys.

Thanks for the suggestion.

Kind regards,