Kotchasan Framework Documentation
Language Class - Multi-language Management System
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\LanguageOverview
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): mixedParameters:
$key- language key or English text$default- default value if key not found (default:nulluses$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 = []): arrayParameters:
$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): stringParameters:
$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): stringParameters:
$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): stringParameters:
$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 languagename()
Get current language name
public static function name(): stringReturns: 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): stringParameters:
$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(): arrayReturns: 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): arrayParameters:
$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): stringParameters:
$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): voidParameters:
$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(): stringReturns: 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): boolParameters:
$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): intParameters:
$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: -1parse()
Translate language from Theme parsing (callback for preg_replace_callback)
public static function parse(array $match): stringParameters:
$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.php2. 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 translate3. 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