BoxLang ๐Ÿš€ A New JVM Dynamic Language Learn More...

ColdBox i18n and Localization

v3.4.0+2 Modules

Total Downloads Latest Stable Version Apache2 License

ColdBox Platform Logo

Copyright Since 2005 ColdBox Platform by Luis Majano and Ortus Solutions, Corp
www.coldbox.org | www.ortussolutions.com

CBi18n - Internationalization & Localization for ColdBox

Professional internationalization (i18n) and localization support for ColdBox applications. CBi18n provides a comprehensive solution for building multilingual applications with support for both traditional Java .properties files and modern JSON resource bundles.

๐ŸŒŸ Features

  • Multi-Format Support: Java .properties and JSON resource bundles
  • Dynamic Locale Switching: Change user locales on-the-fly with persistent storage
  • Hierarchical Modules: Each ColdBox module can have its own resource bundles
  • Storage Integration: Leverages CBStorages for locale persistence (session, cookie, cache)
  • Thread-Safe Loading: Concurrent resource bundle loading with named locks
  • Placeholder Support: Dynamic value replacement in localized strings
  • Event-Driven: Emits interceptor events for missing translations
  • Convention-Based: Minimal configuration with sensible defaults
  • Global Helpers: Convenient functions available in all ColdBox components

๐Ÿ’ป Requirements

  • BoxLang: 1.0+
  • Lucee: 5.0+
  • Adobe ColdFusion: 2023+
  • ColdBox Platform: 6.0+
  • CBStorages: 3.0+ (automatically installed as dependency)

โšก Quick Start

1. Installation

# Install via CommandBox
box install cbi18n

2. Basic Configuration

// config/ColdBox.cfc
moduleSettings = {
    cbi18n: {
        defaultResourceBundle: "includes/i18n/main",
        defaultLocale: "en_US",
        localeStorage: "cookieStorage@cbstorages",
        unknownTranslation: "**NOT FOUND**"
    }
};

3. Create Resource Files

# Create your resource bundle files
# includes/i18n/main_en_US.properties
user.welcome=Welcome {1}!
user.logout=Logout

# includes/i18n/main_es_ES.properties
user.welcome=ยกBienvenido {1}!
user.logout=Cerrar Sesiรณn

4. Use in Your Application

// In handlers, views, layouts
var welcomeMsg = getResource("user.welcome", "", "", ["John"]);
// Or use the shorthand
var logoutText = $r("user.logout");

// Change user's locale dynamically
setFWLocale("es_ES");

๐Ÿ”ง WireBox Mappings

CBi18n automatically registers the following models in WireBox:

Service WireBox ID Description
i18n Service i18n@cbi18n Main service for locale management and resource retrieval
Resource Service resourceService@cbi18n Handles resource bundle loading and parsing

Custom Resource Service

You can override the default ResourceService by providing a customResourceService in your configuration:

moduleSettings = {
    cbi18n: {
        customResourceService: "MyCustomResourceService@mymodule"
    }
};

For more information, see Custom Resource Services.

โš™๏ธ Configuration

Configure CBi18n in your config/ColdBox.cfc under moduleSettings:

moduleSettings = {
    cbi18n: {
        // The base path of the default resource bundle to load
        // Path + resource name but excluding _locale.extension
        defaultResourceBundle: "includes/i18n/main",

        // The default locale of the application (Java format: lang_COUNTRY)
        defaultLocale: "en_US",

        // Storage service for user's locale persistence
        // Use any CBStorages service with full WireBox ID
        localeStorage: "cookieStorage@cbstorages",

        // Text displayed when a translation is not found
        unknownTranslation: "**NOT FOUND**",

        // Enable logging of missing translations to LogBox
        logUnknownTranslation: true,

        // Additional resource bundles to load
        resourceBundles: {
            "admin": "modules/admin/includes/i18n/admin",
            "emails": "includes/i18n/emails"
        },

        // Custom ResourceService implementation (optional)
        customResourceService: ""
    }
};

Module-Specific Configuration

Each ColdBox module can have its own resource bundles. Configure them in your ModuleConfig.cfc:

function configure(){
    cbi18n = {
        defaultLocale: "es_SV",
        resourceBundles: {
            // Alias => path within module
            "module@mymodule": "#moduleMapping#/includes/i18n/module"
        }
    };
}

Storage Options

Leverage any CBStorages service for locale persistence:

  • cookieStorage@cbstorages - Browser cookies (default)
  • sessionStorage@cbstorages - Server session
  • cacheStorage@cbstorages - Distributed cache
  • clientStorage@cbstorages - Client variables

๐Ÿ“– Usage Examples

Basic Resource Retrieval

// Simple resource lookup
var message = getResource("welcome.message");

// With default value
var title = getResource("page.title", "Default Title");

// Using shorthand alias
var error = $r("validation.required");

Dynamic Value Replacement

// Resource: user.greeting=Hello {1}, you have {2} messages
var greeting = getResource(
    "user.greeting",
    "",
    "",
    ["John", "5"]
); // Returns: "Hello John, you have 5 messages"

Locale Management

// Get current user's locale
var currentLocale = getFWLocale(); // e.g., "en_US"

// Change user's locale (automatically loads resource bundles)
setFWLocale("es_ES");

// Get resource in specific locale
var spanishTitle = getResource("page.title", "", "es_ES");

Working with Multiple Bundles

// Get resource from specific bundle
var adminMsg = getResource("dashboard.title", "", "", [], "admin");

// Bundle structure in memory:
// {
//   "default": { "en_US": {...}, "es_ES": {...} },
//   "admin": { "en_US": {...}, "es_ES": {...} }
// }

File Format Examples

Java Properties Format

# main_en_US.properties
user.welcome=Welcome {1}!
user.logout=Logout
error.required=This field is required

JSON Format

# main_en_US.json
{
  "user": {
    "welcome": "Welcome {1}!",
    "logout": "Logout"
  },
  "error": {
    "required": "This field is required"
  }
}

๐Ÿ”— Interceptors

This module announces an onUnknownTranslation interception. The data announced is a struct with the following format:

{
	resource 	= ...,
	locale 		= ... ,
	bundle  	= ...
}

๐Ÿ› ๏ธ Global Helper Functions

CBi18n injects the following helper functions into all ColdBox components (handlers, views, layouts, interceptors):

Locale Management

/**
 * Get the user's currently set locale or default locale
 * @return string Current locale (e.g., "en_US")
 */
function getFWLocale()

/**
 * Set the locale for a specific user
 * @locale The locale to set (Java format: en_US)
 * @dontLoadRBFlag Skip loading resource bundle for the locale
 * @return i18n Service instance
 */
function setFWLocale(string locale="", boolean dontloadRBFlag=false)

Resource Retrieval

/**
 * Retrieve a resource from a resource bundle with replacements
 * @resource The resource key to retrieve
 * @defaultValue Default value if resource not found
 * @locale Specific locale to use (defaults to user's locale)
 * @values Array/struct/string of replacement values
 * @bundle Bundle alias for multiple resource bundles
 * @return string Localized resource string
 */
function getResource(
    required resource,
    defaultValue,
    locale,
    values,
    bundle
)

// Shorthand alias for getResource()
function $r(...)

Service Access

/**
 * Get direct access to the i18n service
 * @return i18n@cbi18n service instance
 */
function i18n()

/**
 * Get direct access to the resource service
 * @return resourceService@cbi18n service instance
 */
function resourceService()

๐Ÿ“š Documentation & Resources

Official Documentation

Community & Support

Additional Resources

๐Ÿ“„ License

Apache License, Version 2.0. See LICENSE file for details.


About Ortus Solutions

CBi18n is a professional open-source project by Ortus Solutions.


Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp

www.coldbox.org | www.ortussolutions.com


โœ๏ธ HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, its not for you.

"Therefore being justified by faith, we have peace with God through our Lord Jesus Christ: By whom also we have access by faith into this grace wherein we stand, and rejoice in hope of the glory of God. And not only so, but we glory in tribulations also: knowing that tribulation worketh patience; And patience, experience; and experience, hope: And hope maketh not ashamed; because the love of God is shed abroad in our hearts by the Holy Ghost which is given unto us." Romans 5:5

๐Ÿž THE DAILY BREAD

"I am the way, and the truth, and the life; no one comes to the Father, but by me (JESUS)" John 14:1-12

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

3.4.0 - 2025-09-18

Added

  • setFwLocale should allow only valid values as well by @GunnarLieb
  • getFwLocale should check if the requested locale is valid, else, default to the default one, this protects against cookie corruption
  • BoxLang Prime Support
  • Updated Github actions
  • Adobe 2025 Support
  • Copilot Instructions

3.3.0 - 2025-02-19

Added

  • BoxLang certification
  • Adobe 2023 certification
  • Updated Github actions
  • ColdBox 7 testing

[3.2.0] => 2022-NOV-16

Added

  • Updated to use latest cb7 announce()

[3.1.0] => 2022-NOV-15

Added

  • New ColdBox 7 delegate: Resourceful@cbi18n

[3.0.0] => 2022-OCT-10

Added

  • New module template updates

Changed

  • Dropped 2016 Support

[2.2.0] => 2022-JAN-11

Added

  • Migration to github actions
  • CFFormatting

Fixed

  • Currently each time ColdBox framework gets reinited (?fwreinit=1) or server restarted, user-selected locale gets reset to the default locale.

[2.1.0] => 2021-JAN-20

Fixed

  • Missing cbStorages dependency on the box.json causes failures upon installation

Added

  • Added a shortcut compatiblity layer so v1 apps don't crash on choosing localeStorage. Basically, we map the incoming locale storage from the old approach: session,client,cookie,request to the cbStorages equivalent

[2.0.0] => 2021-JAN-19

Added

  • ACF2016, ACF2018 Support
  • Complete migration to script thanks to @wpdebruin
  • Fallback mechanism for resource selection from base, to language, to country variants thanks to @wpdebruin
  • Migration to leverage cbStorages for locale storage thanks to @wpdebruin
  • Interceptor for missing translations onUnknownTranslation thanks to @wpdebruin
  • CookieStorage is now used as the default for storing locales
  • Support for flat or embedded JSON resource bundles as well as Java resource bundles via extension detection properties json thanks to @wpdebruin
  • New i18n() mixin helper to get easy access to i18n methods
  • New resoureService() mixin helper to get easy access to the resource service model
  • The extension of the file (.properties, .json) is what determines the resource type to use
  • Github autopublishing of changelogs
  • New CI procedures based on new ColdBox modules
  • More formatting goodness and watchers

Removed

  • Old approach to top level i18n settings. You know will use the normal moduleSettings with a cbi18n key for settings
  • On modules, you will use also the cbi18n top level key for configuration for each module
  • ACF11, Lucee 4.5 Support
  • DefaultLocale in storage now renamed to CurrentLocale
  • dontloadRBFlag removed as it was never used anymore.

Fixed

  • Lots of fixes on localization methods using old Java classes that didn't exist anymore
  • Lots of fixes on streamlining the java classes used for localization

[1.5.0]

  • Improvement : Updated to new template style
  • Improvement : ColdBox 5 updates
  • Improvement : Moved i18n listener to afterAspectsLoad to avoid module loading collisions
  • Bug : Invalid instance scope usage in models

[1.4.0]

  • Few docuementation fixes
  • Fix implementation of getTZoffset() thanks to Seb Duggan
  • CCM-47 Case sensitivity resolved for resource service thanks to @wpdebruin
  • Updated TestBox version

[1.3.2]

  • Unified workbench
  • Encapsulation of module bundle resources

[1.3.1]

  • Varscoping fixes
  • Travis updates

[1.3.0]

  • Implements the ability to add a custom Resource Service for distributed i18n
  • Fixes issues with non-ISO characters in properties files

[1.2.0]

  • New configuration setting for logging when no translation is found logUnknownTranslation
  • Adding Travis CI support

[1.1.0]

  • Updated build process
  • Updated docs and instructions

[1.0.2]

  • Fixes on getRBKeys() and getRBString() to load correct file paths.

[1.0.1]

  • production ignore lists
  • Unloading of helpers

[1.0.0]

  • Create first module version

$ box install cbi18n

No collaborators yet.
   
  • {{ getFullDate("2014-05-09T21:24:51Z") }}
  • {{ getFullDate("2025-09-18T16:27:09Z") }}
  • 18,180
  • 568,957