Kotchasan Framework Documentation

Kotchasan Framework Documentation

Language Class - Multi-language Management System

EN 05 Feb 2026 06:23

Language Class - Multi-language Management System

The Language class is a multi-language management system that supports loading language files, retrieving translations, replacing placeholders, and string formatting.

Namespace

Kotchasan\Language

Overview

The Language class provides:

  • Load and manage language files (PHP and JS)
  • Retrieve translations from language keys
  • Auto-detect language from browser
  • Format strings with sprintf and placeholder replacement
  • Save language files
  • Translate content with {LNG_KEY} placeholders

Configuration

// In config file
define('INIT_LANGUAGE', 'auto');  // Auto-detect from browser
// or
define('INIT_LANGUAGE', 'th');  // Set default language

// Define supported languages
$cfg->languages = [
    'th' => 'ภาษาไทย',
    'en' => 'English'
];

Language File Structure

PHP Language File (language/th.php)

/* language/th.php */
return array(
  'Hello' => 'สวัสดี',
  'Welcome' => 'ยินดีต้อนรับ',
  'YEAR_OFFSET' => 543,
  'MONTH_LONG' => array(
    1 => 'มกราคม',
    2 => 'กุมภาพันธ์',
    // ...
  )
);

JavaScript Language File (language/th.js)

var Hello = 'สวัสดี';
var Welcome = 'ยินดีต้อนรับ';

Public Methods

get()

Retrieve translation from language key

public static function get(string $key, mixed $default = null, mixed $value = null): mixed

Parameters:

  • $key - language key or English text
  • $default - default value if key not found (default: null uses $key)
  • $value - if key is array, specify sub-key

Returns: Translation value or default value

Examples:

use Kotchasan\Language;

// Basic usage
echo Language::get('Hello');
// Output: "สวัสดี" (if Thai)

// With default value
echo Language::get('Unknown Key', 'Not found');
// Output: "Not found"

// Get from array
echo Language::get('MONTH_LONG', null, 1);
// Output: "มกราคม" (month 1)

// Without default (uses key as default)
echo Language::get('NonExistent');
// Output: "NonExistent"

Real-world Usage:

// Alert messages
function showAlert($type)
{
    $messages = [
        'success' => Language::get('Operation completed successfully'),
        'error' => Language::get('An error occurred'),
        'warning' => Language::get('Please check your input')
    ];

    return $messages[$type] ?? Language::get('Unknown message');
}

// Form labels
echo '<label>' . Language::get('Username') . '</label>';
echo '<label>' . Language::get('Password') . '</label>';

getItems()

Retrieve multiple translation keys at once

public static function getItems(array $keys = []): array

Parameters:

  • $keys - array of language keys

Returns: array of translations

Examples:

use Kotchasan\Language;

// Get multiple keys
$labels = Language::getItems([
    'username' => 'Username',
    'password' => 'Password',
    'email' => 'Email',
    'submit' => 'Submit'
]);

// Use in loop
foreach ($labels as $key => $label) {
    echo "<label>{$label}</label>";
}

// Without custom keys
$messages = Language::getItems(['Save', 'Cancel', 'Delete']);
// Result: ['Save' => 'บันทึก', 'Cancel' => 'ยกเลิก', 'Delete' => 'ลบ']

replace()

Replace placeholders in text

public static function replace(string $key, mixed $replace): string

Parameters:

  • $key - language key
  • $replace - replacement value (string, array, or object)

Returns: Text with replacements

Examples:

use Kotchasan\Language;

// Language file: 'Welcome user' => 'Welcome %s'
echo Language::replace('Welcome user', 'John');
// Output: "Welcome John"

// Array for multiple placeholders
// Language file: 'Order summary' => 'You ordered :item quantity :qty'
echo Language::replace('Order summary', [
    ':item' => 'iPhone',
    ':qty' => '2'
]);
// Output: "You ordered iPhone quantity 2"

// Nested language keys
echo Language::replace('items_count', [':count' => '10']);
// Output: "Found 10 items"

Real-world Usage:

// Notification system
function notify($template, $data)
{
    return Language::replace($template, $data);
}

// Usage
echo notify('User :name has :action the file :filename', [
    ':name' => 'John',
    ':action' => 'uploaded',
    ':filename' => 'document.pdf'
]);

sprintf()

Format string using sprintf

public static function sprintf(string $key, mixed ...$values): string

Parameters:

  • $key - language key
  • $values - values to format

Returns: Formatted string

Examples:

use Kotchasan\Language;

// Language file: 'Found results' => 'Found %d results'
echo Language::sprintf('Found results', 15);
// Output: "Found 15 results"

// Multiple parameters
// Language file: 'Price' => 'Price %s (%d items)'
echo Language::sprintf('Price', '$1,500', 5);
// Output: "Price $1,500 (5 items)"

// Format decimal
// Language file: 'Score' => 'Score: %.2f'
echo Language::sprintf('Score', 95.5678);
// Output: "Score: 95.57"

trans()

Translate content with {LNG_KEY} placeholders

public static function trans(string $content): string

Parameters:

  • $content - content to translate

Returns: Translated content

Examples:

use Kotchasan\Language;

$html = '<h1>{LNG_Welcome}</h1><p>{LNG_Hello}</p>';
echo Language::trans($html);
// Output: "<h1>Welcome</h1><p>Hello</p>"

// With template
$template = '
    <div class="alert">
        <strong>{LNG_Attention}</strong>
        <p>{LNG_Please complete the form}</p>
    </div>
';

echo Language::trans($template);

Real-world Usage:

// Email template
$emailTemplate = '
    <html>
    <body>
        <h2>{LNG_Dear user}</h2>
        <p>{LNG_Thank you for registration}</p>
        <p>{LNG_Please verify your email}</p>
    </body>
    </html>
';

$translatedEmail = Language::trans($emailTemplate);
// Send email in current language

name()

Get current language name

public static function name(): string

Returns: Language code (e.g., 'th', 'en')

Examples:

use Kotchasan\Language;

$currentLang = Language::name();
echo "Current language: {$currentLang}";
// Output: "Current language: th"

// Use in URL
$url = "/products?lang=" . Language::name();

// Select CSS by language
$cssFile = "styles-" . Language::name() . ".css";
echo "<link rel='stylesheet' href='{$cssFile}'>";

setName()

Set language to use

public static function setName(string $language): string

Parameters:

  • $language - language code (e.g., 'th', 'en')

Returns: Language name that was set

Examples:

use Kotchasan\Language;

// Switch to English
Language::setName('en');

echo Language::get('Hello');
// Output: "Hello" (English)

// Switch back to Thai
Language::setName('th');

echo Language::get('Hello');
// Output: "สวัสดี" (Thai)

Real-world Usage:

// Language switcher
if (isset($_GET['lang'])) {
    $allowedLangs = ['th', 'en', 'zh'];
    $lang = $_GET['lang'];

    if (in_array($lang, $allowedLangs)) {
        Language::setName($lang);
        // Redirect to remove lang parameter
        header('Location: ' . $_SERVER['PHP_SELF']);
        exit;
    }
}

installedLanguage()

Get list of installed languages

public static function installedLanguage(): array

Returns: array of language codes

Examples:

use Kotchasan\Language;

$languages = Language::installedLanguage();
print_r($languages);
// Output: ['th' => 'th', 'en' => 'en', 'zh' => 'zh']

// Create language selector
echo '<select name="language">';
foreach ($languages as $code) {
    $selected = ($code === Language::name()) ? 'selected' : '';
    echo "<option value='{$code}' {$selected}>{$code}</option>";
}
echo '</select>';

installed()

Load all language data from files

public static function installed(string $type): array

Parameters:

  • $type - file type ('php' or 'js')

Returns: array of all language data

Examples:

use Kotchasan\Language;

// Load PHP files
$phpLangs = Language::installed('php');

foreach ($phpLangs as $item) {
    echo "Key: {$item['key']}\n";
    echo "TH: {$item['th']}\n";
    echo "EN: {$item['en']}\n";
}

// Load JS files
$jsLangs = Language::installed('js');

save()

Save language file

public static function save(array $languages, string $type): string

Parameters:

  • $languages - language data to save
  • $type - file type ('php' or 'js')

Returns: error message (empty if successful)

Examples:

use Kotchasan\Language;

// Prepare language data
$languages = [
    [
        'id' => 0,
        'key' => 'Hello',
        'th' => 'สวัสดี',
        'en' => 'Hello'
    ],
    [
        'id' => 1,
        'key' => 'Goodbye',
        'th' => 'ลาก่อน',
        'en' => 'Goodbye'
    ]
];

// Save
$error = Language::save($languages, 'php');

if (empty($error)) {
    echo "Saved successfully";
} else {
    echo "Error: {$error}";
}

load()

Load language file

public static function load(string $lang): void

Parameters:

  • $lang - language code

Examples:

use Kotchasan\Language;

// Load Thai
Language::load('th');

echo Language::get('Hello');
// Output: "สวัสดี"

// Load English
Language::load('en');

echo Language::get('Hello');
// Output: "Hello"

languageFolder()

Get language folder path

public static function languageFolder(): string

Returns: language folder path

Examples:

use Kotchasan\Language;

$folder = Language::languageFolder();
echo $folder;
// Output: "/var/www/html/language/"

// Check language file exists
$langFile = $folder . 'th.php';
if (file_exists($langFile)) {
    echo "Thai language file exists";
}

arrayKeyExists()

Check if language variable is an array with given key

public static function arrayKeyExists(string $name, string $key): bool

Parameters:

  • $name - language variable name
  • $key - key to check

Returns: true if exists, false otherwise

Examples:

use Kotchasan\Language;

// Check if MONTH_LONG[1] exists
if (Language::arrayKeyExists('MONTH_LONG', 1)) {
    echo Language::get('MONTH_LONG', null, 1);
    // Output: "มกราคม"
}

// Check before use
if (Language::arrayKeyExists('COLORS', 'red')) {
    $color = Language::get('COLORS', null, 'red');
} else {
    $color = 'Unknown color';
}

keyExists()

Check if language key exists in array

public static function keyExists(array $languages, string $key): int

Parameters:

  • $languages - array of language data
  • $key - key to search for

Returns: index of key (or -1 if not found)

Examples:

use Kotchasan\Language;

$languages = [
    ['id' => 0, 'key' => 'Hello', 'th' => 'สวัสดี'],
    ['id' => 1, 'key' => 'Goodbye', 'th' => 'ลาก่อน']
];

$index = Language::keyExists($languages, 'Hello');
echo $index;
// Output: 0

$index = Language::keyExists($languages, 'Unknown');
echo $index;
// Output: -1

parse()

Translate language from Theme parsing (callback for preg_replace_callback)

public static function parse(array $match): string

Parameters:

  • $match - array from regex match

Returns: translation value

Examples:

use Kotchasan\Language;

// Use with preg_replace_callback
$content = '{LNG_Hello} {LNG_World}';

$translated = preg_replace_callback(
    '/{LNG_([^}]+)}/',
    [Language::class, 'parse'],
    $content
);

echo $translated;
// Output: "Hello World"

Complete Usage Examples

1. Complete Multi-language System

use Kotchasan\Language;

class LanguageManager
{
    /**
     * Initialize language system
     */
    public static function init()
    {
        // Check query parameter
        if (isset($_GET['switch_lang'])) {
            $lang = $_GET['switch_lang'];
            if (in_array($lang, ['th', 'en', 'zh'])) {
                Language::setName($lang);
                header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
                exit;
            }
        }
    }

    /**
     * Create language switcher HTML
     */
    public static function createSwitcher()
    {
        $languages = [
            'th' => 'ภาษาไทย',
            'en' => 'English',
            'zh' => '中文'
        ];

        $current = Language::name();
        $html = '<div class="language-switcher">';

        foreach ($languages as $code => $name) {
            $active = ($code === $current) ? 'active' : '';
            $url = '?switch_lang=' . $code;
            $html .= "<a href='{$url}' class='{$active}'>{$name}</a>";
        }

        $html .= '</div>';
        return $html;
    }

    /**
     * Translate text with parameters
     */
    public static function trans($key, $params = [])
    {
        $text = Language::get($key);

        foreach ($params as $placeholder => $value) {
            $text = str_replace($placeholder, $value, $text);
        }

        return $text;
    }
}

// Usage
LanguageManager::init();

echo LanguageManager::createSwitcher();
echo LanguageManager::trans('Welcome :name', [':name' => 'John']);

2. Form Validation Messages

use Kotchasan\Language;

class FormValidator
{
    private $errors = [];

    public function validate($data, $rules)
    {
        foreach ($rules as $field => $rule) {
            if ($rule === 'required' && empty($data[$field])) {
                $this->errors[$field] = Language::sprintf(
                    'field_required',
                    ucfirst($field)
                );
            }

            if ($rule === 'email' && !filter_var($data[$field], FILTER_VALIDATE_EMAIL)) {
                $this->errors[$field] = Language::get('invalid_email');
            }

            if (is_array($rule) && isset($rule['min'])) {
                if (strlen($data[$field]) < $rule['min']) {
                    $this->errors[$field] = Language::sprintf(
                        'min_length',
                        ucfirst($field),
                        $rule['min']
                    );
                }
            }
        }

        return empty($this->errors);
    }

    public function getErrors()
    {
        return $this->errors;
    }

    public function getErrorsHtml()
    {
        $html = '<ul class="errors">';
        foreach ($this->errors as $error) {
            $html .= "<li>{$error}</li>";
        }
        $html .= '</ul>';
        return $html;
    }
}

// Language files:
// 'field_required' => 'Please enter %s'
// 'invalid_email' => 'Invalid email address'
// 'min_length' => '%s must be at least %d characters'

3. Multi-language Content Management

use Kotchasan\Language;

class ContentManager
{
    /**
     * Save multi-language content
     */
    public function saveContent($contentId, $multilangData)
    {
        $languages = Language::installedLanguage();

        foreach ($languages as $lang) {
            if (isset($multilangData[$lang])) {
                $this->saveContentForLanguage(
                    $contentId,
                    $lang,
                    $multilangData[$lang]
                );
            }
        }
    }

    /**
     * Get content in current language
     */
    public function getContent($contentId)
    {
        $lang = Language::name();
        $content = $this->loadContentForLanguage($contentId, $lang);

        // Fallback to default language
        if (empty($content)) {
            $content = $this->loadContentForLanguage($contentId, 'th');
        }

        return $content;
    }

    /**
     * Check if all translations exist
     */
    public function hasAllTranslations($contentId)
    {
        $languages = Language::installedLanguage();

        foreach ($languages as $lang) {
            $content = $this->loadContentForLanguage($contentId, $lang);
            if (empty($content)) {
                return false;
            }
        }

        return true;
    }
}

4. Language Editor

use Kotchasan\Language;

class LanguageEditor
{
    /**
     * Load language data for editing
     */
    public function load()
    {
        return Language::installed('php');
    }

    /**
     * Save changes
     */
    public function save($languages)
    {
        $error = Language::save($languages, 'php');

        if (empty($error)) {
            // Also save JS file
            Language::save($languages, 'js');
            return ['success' => true];
        }

        return ['success' => false, 'message' => $error];
    }

    /**
     * Add new language key
     */
    public function addKey($key, $translations)
    {
        $languages = $this->load();

        $newItem = [
            'id' => count($languages),
            'key' => $key
        ];

        foreach ($translations as $lang => $value) {
            $newItem[$lang] = $value;
        }

        $languages[] = $newItem;

        return $this->save($languages);
    }

    /**
     * Delete language key
     */
    public function deleteKey($key)
    {
        $languages = $this->load();

        $newLanguages = array_filter($languages, function($item) use ($key) {
            return $item['key'] !== $key;
        });

        // Re-index
        $indexed = array_values($newLanguages);
        for ($i = 0; $i < count($indexed); $i++) {
            $indexed[$i]['id'] = $i;
        }

        return $this->save($indexed);
    }
}

Best Practices

1. Organize Language Files

// ✅ Good: Group by category
<?php
return [
    // Common
    'Save' => 'Save',
    'Cancel' => 'Cancel',
    'Delete' => 'Delete',

    // User Management
    'User not found' => 'User not found',
    'Invalid password' => 'Invalid password',

    // Products
    'Product added' => 'Product added',
    'Out of stock' => 'Out of stock'
];

// ✅ Good: Separate files for large sections
// language/th/common.php
// language/th/users.php
// language/th/products.php

2. Use Placeholders

// ✅ Good: Use named placeholders
'Order total' => 'Total: :amount (:items items)'

Language::replace('Order total', [
    ':amount' => '$1,500',
    ':items' => '5'
]);

// ✅ Good: Use sprintf for numbers
'Items count' => 'Found %d items'
Language::sprintf('Items count', 15);

// ❌ Bad: Hard-coded text
echo "Found " . $count . " items";  // Cannot translate

3. Fallback and Default Values

// ✅ Good: Specify default value
$message = Language::get('custom_message', 'Default message');

// ✅ Good: Fallback to another language
$text = Language::get('new_feature');
if ($text === 'new_feature') {  // No translation
    Language::setName('en');  // Try another language
    $text = Language::get('new_feature');
    Language::setName('th');  // Switch back
}

4. Performance

// ✅ Good: Cache language data
class CachedLanguage
{
    private static $cache = [];

    public static function get($key, $default = null)
    {
        $lang = Language::name();
        $cacheKey = $lang . '_' . $key;

        if (!isset(self::$cache[$cacheKey])) {
            self::$cache[$cacheKey] = Language::get($key, $default);
        }

        return self::$cache[$cacheKey];
    }
}

// ✅ Good: Get multiple values at once
$labels = Language::getItems([
    'Save', 'Cancel', 'Delete', 'Edit'
]);

// ❌ Bad: Call one by one
$save = Language::get('Save');
$cancel = Language::get('Cancel');
$delete = Language::get('Delete');

Summary

The Language class is a multi-language management system that:

  • ✅ Full multi-language support
  • ✅ Auto-detect language from browser
  • ✅ Manage PHP and JS files
  • ✅ Versatile string formatting
  • ✅ Built-in language editor
  • 📁 Default folder: language/
  • 🌐 Default language: Thai (th)

Suitable for:

  • Multi-language websites
  • CMS systems
  • International applications
  • Systems requiring user customization

File Size: 506 lines
Public Methods: 16 methods
Supports: PHP and JavaScript language files