Custom localization files for standard Cotonti modules and plug-ins

The guide for safely adding custom localization strings to Cotonti, for any standard extension, directly into the folder with language and translation files, is simple and universal.

Rating based on reviews:
Total stars received: 0
Total reviews: 0
Average rating: 0
Filed under: User Blog

Guide to Safely Adding Custom Localization Strings in Cotonti

Goal
Learn to extract your own language strings from standard module and plugin files of Cotonti into separate files. This will prevent losing your translations when updating the core or extensions.

For whom
For beginners and experienced Cotonti users who want to organize localization and protect their data from being overwritten.

Final solution
We will create a small function cot_langfile_custom, place it in the file system/functions.custom.php, and then call it in any language file of a module or plugin. Custom strings will be stored in the same lang folder as the main translations, but in a separate file with the suffix .custom. This approach requires no modification of system functions, is fully compatible with Cotonti’s native mechanisms, and is safe during updates.

Table of Contents

1. The Problem: Losing Custom Strings on Update

Imagine you actively use the Page module. Over time you have added about 400 of your own strings to modules/page/lang/page.ru.lang.php: button labels, descriptions, messages for visitors. Everything works fine. But during the next update of Cotonti or the module itself, this file may be replaced with a new one from the distribution — and all your strings will vanish.

The reasonable solution is to extract custom strings into a separate file that will not be affected by updates. Ideally, this file should be loaded automatically together with the main language pack and respect the current interface language (Russian, English, etc.).

Cotonti provides several mechanisms for customizing language files, but they either require placing files in the remote datas/lang directory — which may seem illogical (custom strings of the Page module lying somewhere “out in the sticks”) — or they do not work directly for modules. We will take a different path — create a simple universal function that loads a companion file directly from the native lang folder.

2. Solution Architecture

We will use the special file system/functions.custom.php. It is loaded automatically by Cotonti if the “Use custom functions” (customfuncs) option is enabled in the configuration file. This is a standard and safe place for adding your own functions without modifying the core.

Our function cot_langfile_custom():

  • Accepts the extension name (e.g., 'page') and its type ('module' or 'plug').
  • Builds the path to the custom language file inside the lang folder of that extension.
  • Checks if the file exists, and if necessary uses the English version as a fallback.
  • Includes the file, adding all strings defined in it to the global $L array.

After that, in any main language file (e.g., page.ru.lang.php) it is enough to insert a single call line wrapped in a function existence check. This guarantees that even if functions.custom.php is not loaded (for example, the option is turned off), no error will occur.

3. Preparation: Enabling Custom Functions

In order for Cotonti to automatically load the file with custom functions system/functions.custom.php

you need to check on your site whether you have your own functions.custom.php file in the system folder.

1. If the file is missing, create/upload the functions.custom.php file into the system directory in the site root, i.e., the file should be located at the following path

 public_html/system/functions.custom.php

where "public_html" is the folder with any other name that contains all the site files.
2. Open functions.custom.php and add our custom function cot_langfile_custom — the code is below.
Now we need to know for sure that our functions.custom.php is loaded.
3. Open the Cotonti configuration file /datas/config.php and approximately at line 89 check the entry, which should look like:

$cfg['customfuncs'] = true;

If you have $cfg['customfuncs'] = false;, change it to true. Save the changes. Let's move on.

Now the system will automatically load functions.custom.php on every run.

4. Writing the cot_langfile_custom Function

Open or create the file system/functions.custom.php (it must be located in the root system folder of your site). Add the following code to it.


/**
 * Loads a custom language file for a module or plugin.
 *
 * Searches for a file named `{name}.custom.{lang}.lang.php` in the extension's `lang/` directory.
 * If the file for the current language is not found, it tries to load the file for the default language (usually 'en').
 *
 * @param string $name    Extension name (e.g., 'page', 'aliaspagepro').
 * @param string $type    Extension type: 'module' or 'plug'. Default 'plug'.
 * @param string $default Fallback language code if `$lang` is not set or the localized file is missing. Default 'en'.
 *
 * @return bool True if a custom language file was successfully loaded, false otherwise.
 */
function cot_langfile_custom($name, $type = 'plug', $default = 'en')
{
    // Get global configuration variables and current interface language
    global $cfg, $lang, $L;

    // Determine language code: use current UI language or fallback to default
    $langCode = isset($lang) ? $lang : $default;

    // Build path to the extension's lang directory
    if ($type === 'module') {
        $dir = $cfg['modules_dir'] . '/' . $name . '/lang';
    } else {
        $dir = $cfg['plugins_dir'] . '/' . $name . '/lang';
    }

    // Primary file for the current language
    $file = $dir . '/' . $name . '.custom.' . $langCode . '.lang.php';

    // If the file exists and is readable, load it
    if (is_file($file) && is_readable($file)) {
        include $file;
        return true;
    }

    // If the current language is not the default, try the default language file
    if ($langCode !== $default) {
        $fallback = $dir . '/' . $name . '.custom.' . $default . '.lang.php';
        if (is_file($fallback) && is_readable($fallback)) {
            include $fallback;
            return true;
        }
    }

    // Custom language file not found
    return false;
}

Explanation of each line:

  • global $cfg, $lang; — imports global configuration and current language variables.
  • $langCode = isset($lang) ? $lang : $default; — in case the $lang variable is not defined (unlikely, but for reliability), we take English as default.
  • Building the $dir path — using the standard module or plugin directories from Cotonti’s configuration.
  • $file = $dir . '/' . $name . '.custom.' . $langCode . '.lang.php'; — that’s the custom file name pattern: <extension_name>.custom.<language_code>.lang.php. Example: page.custom.ru.lang.php.
  • Check is_file and is_readable — ensures the file exists and is readable before inclusion.
  • Fallback — if the file for the desired language is absent, but an English one exists, load English.
  • Returning true or false lets you know whether the file was loaded (may be useful for debugging).

Place this code at the end of functions.custom.php if there is already something there, or create the file with this content.

5. Naming and Location of Custom Language Files

Now that the function is ready, you need to correctly name and place the files containing your strings.

For the Page module (and any other module) create files:

  • modules/page/lang/page.custom.ru.lang.php — Russian strings.
  • modules/page/lang/page.custom.en.lang.php — English strings.

For the Alias Page PRO plugin (plugin name aliaspagepro):

  • plugins/aliaspagepro/lang/aliaspagepro.custom.ru.lang.php
  • plugins/aliaspagepro/lang/aliaspagepro.custom.en.lang.php

General pattern:

<extension_path>/lang/<extension_name>.custom.<language_code>.lang.php

where <extension_name> matches the folder name of the module/plugin (as in the first parameter of the function call).

Important:

  • Files must start with a check defined('COT_CODE') or die('Wrong URL.');.
  • Inside, define any strings via $L['key'] = 'value';. Try to make keys unique by using an extension prefix, for example: $L['page_custom_login'] = 'Login';.

6. Including Custom Strings in the Main Language File

Now we need to tell the system to load our custom file when loading the main one. To do this, open the module/plugin language file, e.g.:

  • modules/page/lang/page.ru.lang.php
  • plugins/aliaspagepro/lang/aliaspagepro.ru.lang.php

And at the very end (or beginning, but better at the end so as not to interfere with the main strings) add the call:

if (function_exists('cot_langfile_custom')) {
    cot_langfile_custom('page', 'module');
}

Or for a plugin:

if (function_exists('cot_langfile_custom')) {
    cot_langfile_custom('aliaspagepro', 'plug');
}

What happens here:

  • function_exists checks if our function is defined. If functions.custom.php for some reason didn’t load, there will be no error — the custom strings simply won’t be picked up.
  • Then we call the function, passing the extension name and type (module/plug). The function will find the custom file for the current language and load it.

For multilingual sites, you need to add a similar line to every language file where you want custom translations. The function automatically picks the language code from the global $lang variable.

7. Examples

7.1. Page Module

File modules/page/lang/page.ru.lang.php (fragment at the end):

// ... standard module strings ...

// Custom strings
if (function_exists('cot_langfile_custom')) {
    cot_langfile_custom('page', 'module');
}

File modules/page/lang/page.custom.ru.lang.php:

<?php
defined('COT_CODE') or die('Wrong URL.');

$L['page_custom_contact'] = 'Свяжитесь с нами';
$L['page_custom_agree']   = 'Я принимаю условия';
// ... 400 more of your strings ...

Now when loading the Russian version of the site, all these strings will be available in templates via {PHP.L.page_custom_contact} or in code via $L['page_custom_contact'].

7.2. Alias Page PRO Plugin

File plugins/aliaspagepro/lang/aliaspagepro.ru.lang.php (fragment):

if (function_exists('cot_langfile_custom')) {
    cot_langfile_custom('aliaspagepro', 'plug');
}

File plugins/aliaspagepro/lang/aliaspagepro.custom.ru.lang.php:

<?php
defined('COT_CODE') or die('Wrong URL.');

$L['aliaspagepro_custom_label'] = 'My custom text';

8. For English and Other Languages

You need to repeat the steps:

  • Create similar custom files with English strings (e.g., page.custom.en.lang.php).
  • In the English language file (page.en.lang.php) add the same function call.

The cot_langfile_custom function uses the system $lang to choose the language. If for some reason the custom file for a language is missing, but the fallback is enabled, the English version will be loaded (or the language you specified as the third parameter when calling, default 'en').

9. Checking the Work

  1. Create a custom language file with a test string.
  2. Add the function call in the main file.
  3. Open any page of the site in the corresponding language.
  4. Make sure there are no errors and your string is displayed (if you output it somewhere).

No warnings should appear in the admin panel or logs.

10. Advantages of This Approach

  • No code duplication — write the function once, use in all extensions.
  • Files sit next to the main translations — logical and easy to find.
  • Update safety — neither functions.custom.php nor your custom files are overwritten by standard Cotonti updates (unless you manually replace the system folder, but functions.custom.php is specifically designed for user code).
  • Universality — works with any modules and plugins.
  • Simplicity — just one line in the main language file.
  • Multilingual compatibility — the correct language is automatically selected.

11. Potential Problems and Their Solutions

Problem 1: The file functions.custom.php is not loaded

Check the presence of the system/functions.custom.php file on the server.

If the option is off, you can enable it via the configuration file datas/config.php:

$cfg['customfuncs'] = true;

Problem 2: Custom strings are not visible

  • Make sure the cot_langfile_custom call is in the module language file, not in a template. The function must run before the strings are used.
  • Check the custom file name. It must strictly match the pattern: <extension_name>.custom.<language_code>.lang.php.
  • Ensure the file is not empty and contains no syntax errors. You can temporarily add echo 'test'; at the beginning of the file and see if the output appears on the page.

Problem 3: String name conflicts

Use unique prefixes for your keys to avoid overriding system strings. For example, page_custom_, myplugin_.

If something goes wrong, provoke an error

// Hard check: if the function does not exist, we will get a fatal error and see it
cot_langfile_custom('market', 'module');

// Additionally output which path was checked (if the function executed)
$testDir = Cot::$cfg['modules_dir'] . '/market/lang';
$testFile = $testDir . '/market.custom.' . $GLOBALS['lang'] . '.lang.php';
echo "<!-- DEBUG: Checked file: $testFile -->";
if (!file_exists($testFile)) {
    echo "<!-- DEBUG: FILE NOT FOUND! -->";
}

12. Additional Tips

  • Keep custom files in a version control system (Git) so you don’t lose them during server migration.
  • If you update the Cotonti core manually, remember that custom files should not be overwritten — they are new. However, functions.custom.php itself might be replaced, so always back up this file before updating.
  • You can use generator scripts for automatic creation of language files, but that is beyond the scope of this guide.

13. Why Not datas/lang?

The standard Cotonti method using datas/lang requires placing files along a path like datas/lang/ru/modules/page.custom.ru.lang.php. This is a working option, but it scatters module files across different branches of the file system. Many users find it more convenient when custom strings lie side-by-side with the original ones — it’s easier to navigate. Our solution does not contradict Cotonti’s ideology because we are not changing system files, but adding our own next to them.

14. Conclusion

Now you have a simple and reliable method to extend Cotonti language files without the risk of data loss. You can apply it to any existing or future projects.

Let’s recap the brief algorithm of actions:

  1. Make sure the customfuncs option is enabled.
  2. In system/functions.custom.php add the cot_langfile_custom function.
  3. For each extension where you need custom strings, create the file <name>.custom.<language>.lang.php in the lang folder of that extension.
  4. In the main language file (e.g., page.ru.lang.php) insert the line:

    if (function_exists('cot_langfile_custom')) {
        cot_langfile_custom('page', 'module');
    }
    
  5. Fill the custom file with your strings.

That’s it. Happy working with Cotonti!



Reviews

No reviews yet


Comments (0)

No comments yet
Only registered users can post new comments

Page Discussion in Telegram

Article multicategories

Additional categories where this article is shown as similar.

Content author

webitproff

Offline

Sodium Carbonate

Last logged: 2026-09-26 15:22

About me briefly
Support and development of web projects on the CMF Cotonti: private messengers via the website, open and closed small social networks, trading platforms and marketplaces, freelance and services exchange portal, catalogs of goods from wholesale suppliers, dropshipping platforms, online stores, and much more.
View developments and download
Public portfolio of my works and developments
Telegram for messages
@webitproff
Telegram channel
@s/aBuyFILE
  • Page published: 2026-08-11 14:41
  • Last update: 2026-08-18 00:34
  • Language:

Связанные статьи