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.
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
- 2. Solution Architecture
- 3. Preparation: Enabling Custom Functions
- 4. Writing the
cot_langfile_customFunction - 5. Naming and Location of Custom Language Files
- 6. Including Custom Strings in the Main Language File
- 7. Examples
- 8. For English and Other Languages
- 9. Checking the Work
- 10. Advantages of This Approach
- 11. Potential Problems and Their Solutions
- 12. Additional Tips
- 13. Why Not
datas/lang? - 14. Conclusion
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
langfolder 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
$Larray.
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.phpwhere "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$langvariable is not defined (unlikely, but for reliability), we take English as default.- Building the
$dirpath — 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_fileandis_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
trueorfalselets 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.phpplugins/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.phpplugins/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_existschecks if our function is defined. Iffunctions.custom.phpfor 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
- Create a custom language file with a test string.
- Add the function call in the main file.
- Open any page of the site in the corresponding language.
- 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.phpnor your custom files are overwritten by standard Cotonti updates (unless you manually replace thesystemfolder, butfunctions.custom.phpis 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_customcall 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.phpitself 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:
- Make sure the
customfuncsoption is enabled. - In
system/functions.custom.phpadd thecot_langfile_customfunction. - For each extension where you need custom strings, create the file
<name>.custom.<language>.lang.phpin thelangfolder of that extension. 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'); }- Fill the custom file with your strings.
That’s it. Happy working with Cotonti!
Reviews
No reviews yet
Comments (0)
Page Discussion in Telegram
Article multicategories
Additional categories where this article is shown as similar.Content author
Offline
Sodium Carbonate
Last logged: 2026-09-26 15:22
- Page published: 2026-08-11 14:41
- Last update: 2026-08-18 00:34
- Language:
Связанные статьи
User Function Guide functions.custom.php in Cotonti
Cotonti Custom Functions GuideThis guide provides a detailed description of four functions designed
Проверка владельца контента в Cotonti на PHP 8.5
Проверка владельца контента в Cotonti на PHP 8.5В Cotonti, управление доступом к контенту в
Русский