Cbi18n
Collection of skills for the ColdBox Platform and Claude Plugin
npx -y skills add ColdBox/skills --skill cbi18nAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use this skill when adding internationalization (i18n) and localization (l10n) to a ColdBox/BoxLang application with the cbi18n module. Covers installation, resource bundle formats (.properties and JSON), locale management, translation helpers ($r / getResource), positional and named substitutions, multiple bundles, locale switching, and date/number formatting.
SKILL.md
5.7 KB, as published. Nobody here has run it
CBi18n Skill
When to Use This Skill
Load this skill when:
- Adding multi-language support to a ColdBox application
- Creating or reading
.properties/ JSON resource bundle files - Getting and setting the active locale
- Using
getResource()/$r()helpers for translations - Passing value substitutions (positional
{1}or named{name}) - Switching locale based on user preference or URL parameter
- Formatting dates, numbers, and currency per locale
Language Mode Reference
| Concept | BoxLang (.bx) | CFML (.cfc) |
|---|---|---|
| Mixin helpers | getResource(), $r(), getFWLocale(), setFWLocale() | same — available in handlers/views |
Installation & Configuration
box install cbi18n
// config/ColdBox.cfc
moduleSettings = {
cbi18n = {
defaultResourceBundle = "includes/i18n/main", // path WITHOUT locale/extension
defaultLocale = "en_US",
localeStorage = "cookieStorage@cbstorages",
unknownTranslation = "**NOT FOUND**",
logUnknownTranslation = true,
resourceBundles = {
admin = "includes/i18n/admin",
emails = "includes/i18n/emails"
}
}
}
Resource Bundle Files
Java .properties Format (recommended)
# includes/i18n/main_en_US.properties
welcome.message=Welcome, {1}!
user.login=Login
user.logout=Logout
btn.submit=Submit
btn.cancel=Cancel
error.required=The field {1} is required
error.email=Please provide a valid email address
# includes/i18n/main_es_ES.properties
welcome.message=¡Bienvenido, {1}!
user.login=Iniciar Sesión
user.logout=Cerrar Sesión
btn.submit=Enviar
btn.cancel=Cancelar
error.required=El campo {1} es requerido
error.email=Por favor proporcione un email válido
JSON Format
{
"welcome" : { "message" : "Welcome, {1}!" },
"btn" : { "submit" : "Submit", "cancel" : "Cancel" }
}
Core API
Mixin Helpers (handlers, views, layouts)
<!--- Simple translation --->
#getResource( "btn.submit" )#
<!--- Short alias --->
#$r( "btn.submit" )#
<!--- Positional substitution --->
#getResource( resource = "welcome.message", values = [ "John" ] )#
<!--- Named substitution (if using {name} tokens) --->
#getResource( resource = "user.greeting", values = { name : "John", age : 30 } )#
<!--- From a non-default bundle --->
#getResource( resource = "dashboard.title", bundle = "admin" )#
Locale Management
// Get current locale
var locale = getFWLocale() // returns "en_US"
// Set locale (persisted in configured storage)
setFWLocale( "es_ES" )
// Set with timezone
setFWLocale( "es_ES", "Europe/Madrid" )
Production Patterns
Language Switch Handler
class Language extends coldbox.system.EventHandler {
function changeLocale( event, rc, prc ) {
// Validate locale before setting — prevent arbitrary values
var supported = [ "en_US", "es_ES", "fr_FR", "de_DE" ]
var requested = rc.locale ?: "en_US"
if ( !supported.findNoCase( requested ) ) {
requested = "en_US"
}
setFWLocale( requested )
// Redirect back to referring page
var referer = event.getHTTPHeader( "Referer", event.buildLink( "main.index" ) )
relocate( url = referer )
}
}
Locale Selector in View
<form action="#event.buildLink('language.changeLocale')#" method="POST">
#csrf()#
<select name="locale" onchange="this.form.submit()">
<option value="en_US" #getFWLocale() eq "en_US" ? "selected" : ""#>English</option>
<option value="es_ES" #getFWLocale() eq "es_ES" ? "selected" : ""#>Español</option>
<option value="fr_FR" #getFWLocale() eq "fr_FR" ? "selected" : ""#>Français</option>
</select>
</form>
Programmatic Injection
class UserProfileHandler extends coldbox.system.EventHandler {
@inject("i18n@cbi18n")
property name="i18n";
function show( event, rc, prc ) {
// Use i18n service directly when view helpers are unavailable
prc.welcomeTitle = i18n.getResource(
resource = "welcome.message",
values = [ prc.user.getFirstName() ]
)
event.setView( "users/show" )
}
}
Formatted Dates / Numbers per Locale
// Use Java locale-aware formatting
var jLocale = createObject( "java", "java.util.Locale" )
.init( getFWLocale().listFirst( "_" ), getFWLocale().listLast( "_" ) )
var formatter = createObject( "java", "java.text.DateFormat" )
.getDateInstance( createObject( "java", "java.text.DateFormat" ).SHORT, jLocale )
var formatted = formatter.format( now().getTime() )
Best Practices
- Never hardcode user-facing strings — always use resource bundles
- Use positional substitutions for dynamic content:
{1},{2}(1-indexed) - Validate locale on input — restrict to a known supported list
- Keep bundle keys hierarchical —
error.requirednoterrRequired— for readability - Log missing translations (
logUnknownTranslation = true) in development to catch gaps - Test all supported locales before deploying multilingual routes