Guide to Getting Template Path and Name in Cotonti
This guide discusses in detail three practical ways to get the path and name of a template file. The developer and the layout designer need to know which template file is being used.
Guide to Getting Template Path and Name in Cotonti
Table of Contents
- Introduction
- Chapter 1. Cotonti Template Architecture
- Chapter 2. Method 1: The
cot_tpl_url()Function – Getting Template URL by Name - Chapter 3. Method 2: The
cot_debug_tpl_url()Function – Automatic Detection of the Current Template - Chapter 4. Method 3: Assigning the Path to a Template Tag via
$t->assign() - Chapter 5. Comparison of Methods
- Chapter 6. Practical Scenarios and Recommendations
- Chapter 7. Placing Functions in
system/functions.custom.php - Conclusion
- Appendix A. Full Function Listings
- Appendix B. Usage Examples in Different Modules
- Appendix C. Code to Place in
functions.custom.php
Introduction
Cotonti is a flexible content management system in which templates play a key role in shaping the appearance of the site. Developers and layout designers often need to determine which template file is used to display a particular page or part of it. Knowing the path to the template helps to quickly make edits, debug layout, include additional resources, and create development tools.
This guide covers three practical ways to obtain the path and name of a template file:
- The
cot_tpl_url()function — forms an absolute URL to the template file by its name, passed manually. - The
cot_debug_tpl_url()function — automatically determines the current template by analyzing the PHP call stack. - Assigning the path via
$t->assign()— passing the path from the extension PHP code to the template through the XTemplate mechanism.
Each method has its own features, advantages, and limitations. The guide will help you choose the right option for your specific task, as well as explain how to properly place user-defined functions in system/functions.custom.php so that they are available system‑wide.
Important: In the examples, we will show the path to the template as text, not as a clickable link. The .tpl file is not meant to be opened directly in a browser: it contains HTML markup with XTemplate tags that must be processed by the engine. Therefore, linking to such a file is useless and misleading. The path should be displayed for information purposes, e.g., during debugging or documentation.
Chapter 1. Cotonti Template Architecture
Before proceeding to the methods of obtaining the path, it is necessary to understand the basic principles of working with templates in Cotonti.
1.1. The cot_tplfile() Function
The central function for determining the path to a template file is cot_tplfile(). It is declared in the file system/functions.php and has the following signature:
function cot_tplfile($base, $type = 'module', $admin = null)Parameters:
$base– a string or array specifying the template name. If the string contains a dot, it is split into parts. For example,'forums.editpost'becomes the array['forums', 'editpost'].$type– the type of extension:'plug'(plugin),'module'(module), or'core'(core). Default is'module'.$admin– a flag indicating whether to look for the template in the admin theme. Ifnull(default), Cotonti automatically determines whether the template is administrative (by checking for the presence ofadminin the name).
What the function does:
- Normalises the passed template name into an array of parts.
- Determines the extension code (the first element of the array) and the remaining parts.
- Depending on the extension type and the
$adminflag, builds a list of directories to search:- The user's current theme (may be overridden).
- The admin theme (for admin templates).
- The module/plugin folder (fallback).
- Iterates over the list of directories and looks for a file whose name is formed from the parts of
$basejoined with dots, with the extension.tpl. For example, for['forums', 'editpost'], it will look forforums.editpost.tpl. - Returns the relative path to the found file (e.g.,
themes/mytheme/modules/forums/editpost.tpl) ornullif the file is not found.
Call examples:
$tpl = cot_tplfile('index'); // -> themes/.../index.tpl
$tpl = cot_tplfile('page.add'); // -> themes/.../page.add.tpl
$tpl = cot_tplfile(['users', 'edit', '5'], 'module');
$tpl = cot_tplfile('myplugin.admin', 'plug', true);Note that the function returns a path relative to the site root, without a leading slash and without a base URL. To use it in HTML (e.g., in an href or src attribute), you need to convert it to an absolute URL.
1.2. The XTemplate Class and Its Role
After determining the path to the template file, an instance of the XTemplate class is created, which is responsible for parsing and rendering the template:
$t = new XTemplate($tpl_file);The XTemplate class (a Cotonti extension) stores the path to the template file internally. This is used in the second method (cot_debug_tpl_url) to obtain the current template. In different versions, the property that stores the path may have different names: filename, file, tpl_name, etc. Therefore, in the cot_debug_tpl_url() function, we iterate over possible names using the Reflection API.
1.3. Site Base URL $sys['abs_url']
The global variable $sys['abs_url'] contains the base URL of the site, e.g., https://example.com/. It usually ends with a slash. To correctly form an absolute URL, you need to combine the base URL and the relative path, avoiding duplicate slashes. In our functions, we use rtrim($absUrl, '/') and ltrim($filePath, '/').
Chapter 2. Method 1: The cot_tpl_url() Function – Getting Template URL by Name
2.1. Purpose and Principle of Operation
The cot_tpl_url() function is a convenient wrapper around cot_tplfile(). It takes the same arguments as cot_tplfile(), but instead of a relative path it returns the full absolute URL to the template file. This is useful when the developer knows exactly which template they need and wants to obtain its address for display in text, saving in configuration, or using as a resource path.
The function:
- Calls
cot_tplfile($base, $type, $admin)to find the file. - If the file is not found, returns
null. - Gets the base URL from
$sys['abs_url'](or computes it from$_SERVERif not set). - Combines the base URL and the path, removing extra slashes.
- Returns a ready string like
https://example.com/themes/mytheme/modules/page/page.news.tpl.
2.2. Function Parameters
function cot_tpl_url($base, $type = 'module', $admin = null)$base— the template name (string with dots or array of parts). For example,'page.news'or['page', 'news'].$type— the extension type:'plug','module','core'.$admin— iftrue, it will search in the admin theme; ifnull, auto‑detection by name.
2.3. Examples of Calling in Templates
Inside any .tpl file, you can call the function via the {PHP|...} tag and output the result as text:
<!-- Show the URL of the page template -->
<p>Page template: {PHP|cot_tpl_url('page')}</p>
<!-- Show the URL of a specific category template -->
<p>Template for category "News": {PHP|cot_tpl_url(['page', 'news'])}</p>
<!-- For a plugin -->
<p>Template for plugin recentitems: {PHP|cot_tpl_url('recentitems', 'plug')}</p>You can also call the function in the PHP code of an extension:
$url = cot_tpl_url('forums.editpost');
echo "Template path: " . $url;It is not recommended to create a link like <a href="{PHP|cot_tpl_url('page')}">Open</a>, because the browser cannot correctly open a .tpl file. Instead, output the path as text or in a title/data-* attribute for storage.
Correct syntax:
Calling a function (via the pipe symbol
|): {PHP|function_name(arguments)}
Example call in a template: {PHP|cot_debug_tpl_url()}Access to a PHP global variable (via dot): {PHP.variable_name}
Example in a template: {PHP.sys.abs_url} (for$sys['abs_url'])Template variable: {VAR_NAME}
Example in a template: {TPL_DIR}
2.4. When to Use
This method is ideal when:
- The template name is known in advance and does not depend on the current context.
- You need to get the URL of a specific file to include resources (e.g., a CSS file located next to the template).
- You are creating an admin panel where you want to show the path to the template for editing (e.g., copy the path and open the file in FTP or file manager).
Example: In the Cotonti admin panel, you can display a list of template files with their absolute paths so that the administrator can easily find the desired file on the server.
2.5. Limitations and Peculiarities
- Requires manual specification of the template name. If the name is unknown or determined dynamically, you will have to compute it yourself.
- Does not automatically detect the current template. If you need to know which template is used for the current page, this method is not suitable.
- Depends on the correctness of the
cot_tplfile()search. If the file is not found (e.g., due to a typo), the function will returnnull.
Chapter 3. Method 2: The cot_debug_tpl_url() Function – Automatic Detection of the Current Template
3.1. Purpose
The cot_debug_tpl_url() function solves the problem of determining the current template in which it is called. This is especially useful during debugging: you insert the function call anywhere in a .tpl file (e.g., in the footer) and see the full URL of that file without knowing its name in advance.
This approach does not require editing the core and is independent of a specific module or plugin.
3.2. How It Works: debug_backtrace() and Reflection API
The function uses two important PHP features:
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT)– returns the call stack as an array. Thanks to theDEBUG_BACKTRACE_PROVIDE_OBJECTflag, each frame contains theobjectkey if the call occurred inside a method of some object. In our case, whencot_debug_tpl_url()is called inside a template, it executes in the context of anXTemplatemethod (e.g.,parse()ortext()). Therefore, the stack will definitely have a frame with anXTemplateobject.- Reflection API – allows access to protected and private properties of an object. The path to the template file is stored in a private property of the
XTemplateobject. UsingReflectionObject, we iterate over possible property names (filename,file,tpl_name,template) and retrieve the value.
Algorithm:
- Get the base URL.
- Get the call stack.
- Look for a frame with an
XTemplateobject in the stack. - Extract the template file path from that object (using Reflection).
- Build the absolute URL and return it.
3.3. Usage Examples
In any .tpl file:
<!-- Output the current template as text -->
<div>Current template: {PHP|cot_debug_tpl_url()}</div>
<!-- Use in a data-* attribute for JavaScript -->
<body data-tpl="{PHP|cot_debug_tpl_url()}">For debugging, this call is often placed in footer.tpl or header.tpl so that you can see which template is loaded on each page. Do not make it a link – it is just text.
3.4. When to Use
- During development and debugging – when you need to quickly understand which template file is responsible for the current block of the page.
- When building developer tools – for example, a panel that highlights the template name.
- When the template name is unknown or determined dynamically (e.g., depending on category or user).
3.5. Limitations and Recommendations
- Performance. The function uses
debug_backtrace(), which can slow down execution when called frequently. It is not recommended to call it in a loop on a production site. Use only for debugging or in admin mode. - Dependence on the internal structure of XTemplate. If in the future the property storing the path is renamed, the function may stop working. Therefore, it includes a fallback iteration over all properties with substrings
fileortpl. - Accuracy. The function returns the last
XTemplateobject found in the stack, which usually corresponds to the currently processed template. However, in some cases (e.g., nested templates) it may return a different one. For most debugging tasks, this is sufficient.
Chapter 4. Method 3: Assigning the Path to a Template Tag via $t->assign()
4.1. Purpose
This method is used by extension developers (modules, plugins) when the path to the template has already been obtained in PHP code to create an XTemplate object. Instead of calling any functions in the template, we pass the path as a regular template variable. This is the most explicit and controlled way.
4.2. Implementation Example in PHP Code
Consider a fragment from the real market module:
// 1. Define the parts of the template name
$tpl_ExtCode = 'market'; // module code
$tpl_PartExt = 'edit'; // template part (action)
$tpl_PartExtSecond = Cot::$structure['market'][$item['fieldmrkt_cat']]['tpl']; // extra part from structure
// 2. Get the path to the template file
$extTplFile = cot_tplfile(
[
$tpl_ExtCode,
$tpl_PartExt,
$tpl_PartExtSecond
],
'module',
true
);
// 3. Check if the file was found
if (empty($extTplFile)) {
cot_error('Template not found');
}
// 4. Save the path to a variable
$tpl_Path = $extTplFile;
// 5. Create an XTemplate object
$t = new XTemplate($extTplFile);
// ... further processing ...
// 6. Assign the path to the template
$t->assign('TPL_PATH', $tpl_Path);As a result, the template variable {TPL_PATH} becomes available, containing the relative path to the template file.
4.3. Output in Template
In the corresponding .tpl file (e.g., market.edit.tpl), you can output the path:
<!-- Simply output the path -->
<p>Template path: {TPL_PATH}</p>
<!-- Use in a data-* attribute -->
<div class="debug-info" data-tpl="{TPL_PATH}">Note that {TPL_PATH} contains a relative path (without the base URL). To get the absolute URL, you can either form the full URL in PHP code beforehand, or use the combination {PHP.sys.abs_url}/{TPL_PATH} in the template.
4.4. When to Use
- Inside extensions, when you are already working with an
XTemplateobject and want to pass additional information to the template. - For creating utility templates (e.g., admin panels) where you need to output information about the template itself.
- When maximum control over what is passed to the template is required, without extra calculations in the template.
4.5. Advantages and Disadvantages
Advantages:
- Full explicitness: you define the variable and its value yourself.
- Does not require Reflection or backtrace, works fast.
- You can pass not only the path but also any other metadata (name, parts, etc.).
- Compatible with all versions of PHP and Cotonti.
Disadvantages:
- Requires modifying the PHP code of the extension for each template where it is needed.
- Not universal: if you want to insert template information into a common
footer.tpl, you will have to pass the path in every PHP controller to the correspondingXTemplateobject.
Chapter 5. Comparison of Methods
| Criteria | cot_tpl_url() | cot_debug_tpl_url() | $t->assign('TPL_PATH', ...) |
|---|---|---|---|
| Automatic detection of current template | No, requires name | Yes | No, set in PHP |
| Flexibility | Allows specifying any template | Only current | Depends on code |
| Performance | High (call to cot_tplfile) | Low (backtrace + Reflection) | High |
| PHP version dependency | No | Requires PHP 8.1+ (without setAccessible) | No |
| Where to use | Anywhere in template or PHP | Any template for debugging | In extension PHP code |
| Requires core modification | No | No | No |
| Return format | Absolute URL | Absolute URL | Relative path (usually) |
| Convenience for layout designers | Need to know template name | Just insert a call | Needs developer to add variable |
Recommendations:
- If you are developing an extension and want to show the template path inside it – use Method 3 (assign).
- If you need to quickly debug the current page and find out which template is used – use Method 2 (cot_debug_tpl_url).
- If you need to get the URL of a specific template by name (e.g., for display in documentation or passing to configuration) – use Method 1 (cot_tpl_url).
Chapter 6. Practical Scenarios and Recommendations
6.1. Layout Debugging
Task: A layout designer is editing a theme and wants to see which .tpl file is responsible for a particular block of the page.
Solution: Insert the following code into footer.tpl (or header.tpl):
<div class="debug-tpl">
Current template: {PHP|cot_debug_tpl_url()}
</div>This will allow you to see the path to the current template on any page of the site. Remember to remove or hide this block after finishing work.
6.2. Including Template Assets
Task: In the plugin template recentitems.tpl, you need to include a CSS file located alongside the template in the theme folder.
Solution with Method 3 (preferred): In PHP code, get the URL of the template folder and assign it to the template.
$tpl_dir = dirname(cot_tplfile('recentitems', 'plug'));
$t->assign('TPL_DIR', $tpl_dir);In the template:
<link rel="stylesheet" href="{PHP.sys.abs_url}/{TPL_DIR}/css/recentitems.css">Using cot_tpl_url() for such purposes is less reliable because the path may be dynamic.
An alternative approach, where the full URL is formed in PHP code:
$tpl_dir = dirname(cot_tplfile('recentitems', 'plug'));
$t->assign('RECENTITEMS_CSS_URL', $sys['abs_url'] . $tpl_dir . '/css/recentitems.css');
In the template:
<link rel="stylesheet" href="{RECENTITEMS_CSS_URL}">6.3. Creating Documentation
Task: On a utility page, you need to display a list of all used templates with their absolute paths (for copying).
Solution: Use cot_tpl_url() for each known template:
$templates = [
'index', 'page', 'page.list', 'forums.topics', 'users.profile'
];
foreach ($templates as $tpl_name) {
$url = cot_tpl_url($tpl_name);
echo "Template $tpl_name: $url<br>";
}6.4. Developing Extensions
Task: In the market module, you need to show the path to the currently edited template in the admin section.
Solution: Use Method 3, as shown in the example above. In PHP code, get the path via cot_tplfile(), store it in a variable, and pass it to the template via $t->assign().
Additional tip: If you want the variable to be available in all templates of the module, you can assign it at the beginning of the controller and use it in each subtemplate.
Chapter 7. Placing Functions in system/functions.custom.php
7.1. What Is functions.custom.php
Cotonti provides the ability to add user-defined functions without modifying the core. For this purpose, the file system/functions.custom.php is used. If such a file exists, Cotonti automatically loads it during initialisation. This allows developers to add their own functions that will be available throughout the system, including templates.
7.2. Including the File
To add the functions cot_tpl_url() and cot_debug_tpl_url(), follow these steps:
- Create the file
system/functions.custom.phpif it does not already exist. - Open the file and add the function code (provided in Appendix A or C).
- Save the file.
Cotonti will automatically detect this file and include it on startup. No additional actions are required for inclusion.
Important: Do not edit the system/functions.php file directly, as it will be overwritten when Cotonti is updated. Always place your custom functions in functions.custom.php.
7.3. Organization Recommendations
- Keep all user-defined functions in a single file
functions.custom.phpfor easier maintenance. - Use unique prefixes for function names to avoid conflicts with the core and extensions.
- Add documentation to each function (PHPDoc comments) for easier understanding.
- Always check if a function is already defined before declaring it (use
if (!function_exists('...'))).
Example file structure:
<?php
/**
* Cotonti custom functions
*/
if (!function_exists('cot_tpl_url')) {
function cot_tpl_url($base, $type = 'module', $admin = null) {
// ...
}
}
if (!function_exists('cot_debug_tpl_url')) {
function cot_debug_tpl_url() {
// ...
}
}Conclusion
Cotonti provides a flexible template system, and obtaining the template path can be done in different ways depending on the context:
cot_tpl_url()– for getting the URL of a specific template by name.cot_debug_tpl_url()– for automatic detection of the current template (handy for debugging).$t->assign()– for explicitly passing the path to the template from extension PHP code.
Each method has its strengths. Developers are advised to combine them depending on the task. Layout designers will most often benefit from the second method (for quick debugging) and the first (for including resources if the template is known). When developing extensions, the third method is the most appropriate, as it gives full control and does not depend on global state.
Placing user-defined functions in system/functions.custom.php ensures that they will not be lost when updating the engine and will be available everywhere.
Appendix A. Full Function Listings
A.1. cot_tpl_url()
/**
* Returns the absolute URL to the template file.
*
* Uses cot_tplfile() to search for the file and adds the site base URL.
*
* @param string|array $base Template name (as in cot_tplfile)
* @param string $type Extension type: 'plug', 'module' or 'core'
* @param bool|null $admin Whether to use the admin theme (default auto-detect)
* @return string|null Absolute URL to the template, or null if not found
*/
function cot_tpl_url($base, $type = 'module', $admin = null)
{
// Get the file path via the standard function
$filePath = cot_tplfile($base, $type, $admin);
if ($filePath === null) {
return null;
}
// Determine the site base URL
global $sys;
$absUrl = isset($sys['abs_url']) ? $sys['abs_url'] : '';
if (empty($absUrl)) {
// If base URL is not set, compute from $_SERVER
$absUrl = 'http' . (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/';
}
// Remove extra slashes
if (preg_match('#^(/|[A-Za-z]:[\\\\/])#', $filePath)) {
// If the path is absolute (starts with '/' or 'C:\'), return null
return null;
}
return rtrim($absUrl, '/') . '/' . ltrim($filePath, '/');
}A.2. cot_debug_tpl_url()
/**
* Returns the absolute URL of the current template file.
*
* The function analyses the call stack, finds the XTemplate object
* that is currently processing the template, extracts the template file
* path via Reflection API, and adds the site base URL.
*
* @return string|null Absolute URL of the current template, or null if unable to determine.
*/
function cot_debug_tpl_url()
{
global $sys;
// Base URL
$absUrl = isset($sys['abs_url']) ? rtrim($sys['abs_url'], '/') : '';
// Get call stack with objects
$backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
foreach ($backtrace as $frame) {
if (isset($frame['object']) && $frame['object'] instanceof XTemplate) {
$tplFile = null;
$ref = new ReflectionObject($frame['object']);
// List of possible property names with the template path
$candidateProperties = ['filename', 'file', 'tpl_name', 'template'];
foreach ($candidateProperties as $propName) {
if ($ref->hasProperty($propName)) {
$prop = $ref->getProperty($propName);
// In PHP 8.1+ setAccessible() is not needed
$tplFile = $prop->getValue($frame['object']);
break;
}
}
// Fallback: search for a property with 'file' or 'tpl' in the name
if ($tplFile === null) {
foreach ($ref->getProperties() as $prop) {
$name = $prop->getName();
if (stripos($name, 'file') !== false || stripos($name, 'tpl') !== false) {
$tplFile = $prop->getValue($frame['object']);
break;
}
}
}
if (!empty($tplFile)) {
return $absUrl . '/' . ltrim($tplFile, '/');
}
}
}
return null;
}Appendix B. Usage Examples in Different Modules
News list page (module page)
In the page.list.tpl file, you can insert:
<!-- Show the path to the current template -->
<div class="debug">Template: {PHP|cot_debug_tpl_url()}</div>
<!-- Show the URL of the "page" template -->
<div>Common template URL: {PHP|cot_tpl_url('page.list')}</div>Forum – topics
In forums.topics.tpl:
<!-- Automatic path -->
<p>Current template: {PHP|cot_debug_tpl_url()}</p>Comments plugin
In the plugin PHP code:
$tpl_path = cot_tplfile('comments', 'plug');
$t->assign('COMMENTS_TPL_PATH', $tpl_path);In the template:
<footer>Comments: {COMMENTS_TPL_PATH}</footer>Appendix C. Code to Place in functions.custom.php
Below is the full code that you can copy into the system/functions.custom.php file.
<?php
/**
* Cotonti custom functions
*/
if (!function_exists('cot_tpl_url')) {
/**
* Returns the absolute URL to the template file.
*
* @param string|array $base Template name (as in cot_tplfile)
* @param string $type Extension type: 'plug', 'module' or 'core'
* @param bool|null $admin Whether to use the admin theme (default auto-detect)
* @return string|null Absolute URL to the template, or null if not found
*/
function cot_tpl_url($base, $type = 'module', $admin = null)
{
// Get the file path via the standard function
$filePath = cot_tplfile($base, $type, $admin);
if ($filePath === null) {
return null;
}
// Determine the site base URL
global $sys;
$absUrl = isset($sys['abs_url']) ? $sys['abs_url'] : '';
if (empty($absUrl)) {
// If base URL is not set, compute from $_SERVER
$absUrl = 'http' . (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/';
}
// Remove extra slashes
if (preg_match('#^(/|[A-Za-z]:[\\\\/])#', $filePath)) {
// If the path is absolute (starts with '/' or 'C:\'), return null
return null;
}
return rtrim($absUrl, '/') . '/' . ltrim($filePath, '/');
}
}
if (!function_exists('cot_debug_tpl_url')) {
/**
* Returns the absolute URL of the current template file.
*
* @return string|null Absolute URL of the current template, or null if unable to determine.
*/
function cot_debug_tpl_url()
{
global $sys;
// Base URL
$absUrl = isset($sys['abs_url']) ? rtrim($sys['abs_url'], '/') : '';
// Get call stack with objects
$backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
foreach ($backtrace as $frame) {
if (isset($frame['object']) && $frame['object'] instanceof XTemplate) {
$tplFile = null;
$ref = new ReflectionObject($frame['object']);
// List of possible property names with the template path
$candidateProperties = ['filename', 'file', 'tpl_name', 'template'];
foreach ($candidateProperties as $propName) {
if ($ref->hasProperty($propName)) {
$prop = $ref->getProperty($propName);
// In PHP 8.1+ setAccessible() is not needed
$tplFile = $prop->getValue($frame['object']);
break;
}
}
// Fallback: search for a property with 'file' or 'tpl' in the name
if ($tplFile === null) {
foreach ($ref->getProperties() as $prop) {
$name = $prop->getName();
if (stripos($name, 'file') !== false || stripos($name, 'tpl') !== false) {
$tplFile = $prop->getValue($frame['object']);
break;
}
}
}
if (!empty($tplFile)) {
return $absUrl . '/' . ltrim($tplFile, '/');
}
}
}
return null;
}
}After saving the file, the functions will be available throughout Cotonti, including templates.
We hope this guide helps you work effectively with Cotonti templates. Use the suggested methods according to your tasks.
Reviews
No reviews yet
Comments (0)
Page Discussion in Telegram
Related Posts
Content author
Online
Sodium Carbonate
Last logged: 2026-08-20 12:58
- Page published: 2026-08-20 10:12
- Last update: 2026-08-20 11:53
- Language:
Русский