Plugin translations and language catalogs
Put plugin interface text in language catalogs. Use English and German JSON catalogs, namespaced keys and translated output in views.
1. Add catalogs
Section titled “1. Add catalogs”example.hello/ src/ translations/ en.json de.jsonIf you supply translation catalogs, en.json is required. Each file contains a flat JSON object of string keys and string values. Locale filenames include en.json, de.json and de_CH.json; do not nest translations in objects.
Use your plugin ID as a namespace. For src/translations/en.json:
{ "plugin.example.hello.title": "Hello Example", "plugin.example.hello.greeting": "Greeting", "plugin.example.hello.saved": "Your changes have been saved."}For src/translations/de.json:
{ "plugin.example.hello.title": "Hallo Beispiel", "plugin.example.hello.greeting": "Begrüssung", "plugin.example.hello.saved": "Deine Änderungen wurden gespeichert."}Use the same stable keys in every language. Do not reuse keys owned by Core or another plugin.
2. Use labels in providers
Section titled “2. Use labels in providers”Registry definitions pair a translation key with a usable fallback:
{ 'translationKey' = "plugin.example.hello.title", 'defaultName' = "Hello Example"}These are label fields within a navigation, settings or integration definition, not a complete definition. Integration descriptions similarly use descriptionKey and defaultDescription. Keep fallbacks meaningful even before catalog import.
3. Render translated text
Section titled “3. Render translated text”In a view, resolve the label and encode it for its output context:
<cfoutput> <label for="greeting"> #encodeForHtml(request.t( "plugin.example.hello.greeting", "Greeting" ))# </label></cfoutput>Controllers can use request.t(key, fallback) for page titles and messages during a request. Translation does not perform HTML escaping: use encodeForHtml for text and encodeForHtmlAttribute for attribute values. Do not cache one user’s translated text globally.
Translate interface labels, not user-entered settings or customer data.
4. Import and edit
Section titled “4. Import and edit”Enable the plugin through Settings → Plugins. NetSeller imports its catalogs after migrations succeed. Values are imported for languages that exist in the installation; supplying a JSON file does not create a new language.
Administrators can edit imported labels under Settings → Languages, in the Plugins translation area.
Catalog updates
Section titled “Catalog updates”Deploy changed catalogs and enable the plugin again; if it is enabled, disable it first. Application reinitialization alone does not import the files.
Import writes the supplied values again, including values previously edited in the backoffice. Preserve customer-specific wording before reimporting. Keys removed from all of the plugin’s catalogs are removed from its imported translations during synchronization.
Disabling a plugin retains translations. Deleting its plugin data removes the plugin-owned keys and values.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
| Activation reports a catalog error | Valid JSON, flat string values, supported locale filename and an English source catalog. |
| A new label still shows its fallback | Matching key, successful activation/import, and the language’s presence in the installation. |
| Activation reports a key ownership conflict | Use your own plugin namespace; do not claim another plugin’s or Core’s key. |
| Backoffice wording changed after an update | Catalog import replaces supplied values; restore the intended wording after import. |
Example: integration labels
Section titled “Example: integration labels”The bexio integration ships en.json, de.json, fr.json and it.json. Its keys use the namespace plugin.bexio.integration., for example:
{ "plugin.bexio.integration.connection_connected": "Connected", "plugin.bexio.integration.connection_not_connected": "Not connected"}This keeps interface states translatable without translating external account names or stored connection data. Use your own plugin ID in equivalent keys; do not copy the bexio namespace into another plugin.