MENU

一个简单的Language类来处理多语言支持

July 23, 2024 • 已被 306 位童鞋围观过 • 代码分享

支持读取 cookie["language"]或者是获取 $_GET["language"] 参数来判断当前语言选项

默认语言支持 中文 英文 法语 德语 等

如果不再支持的语言中 返回英文 且重写 cookie["Language"]

支持语言回退 变量替换等功能

<?php
namespace App\Utility;
class Language
{
    private $langData = [];
    private $currentLang;
    private $supportedLangs = [
        "en" => "English",
        "zh" => "中文简体",
        "fr" => "Français",
        "de" => "Deutsch"
    ];
    private $defaultLang = 'en';

    public function __construct()
    {
        $this->setLanguage();
        $this->loadLanguageData();
    }

    private function setLanguage()
    {
        $lang = $_GET['language'] ?? $_COOKIE['language'] ?? $this->defaultLang;
        $lang = strtolower(substr($lang, 0, 2)); // 只取前两个字符并转换为小写

        if (!array_key_exists($lang, $this->supportedLangs)) {
            $lang = $this->defaultLang;
        }

        $this->currentLang = $lang;
        setcookie('language', $lang, time() + (86400 * 30), "/"); // 设置 cookie,有效期 30 天
    }

    private function loadLanguageData()
    {
        $filePath = __DIR__ . "/lang/{$this->currentLang}.json";
        if (file_exists($filePath)) {
            $this->langData = json_decode(file_get_contents($filePath), true);
        } else {
            throw new Exception("Language file not found: {$this->currentLang}");
        }
    }

    public function get($key, $replacements = [], $default = null)
    {
        $value = $this->getFromLanguageData($key);
  
        if ($value === null && $this->currentLang !== $this->defaultLang) {
            // 语言回退:如果在当前语言中找不到,尝试在默认语言中查找
            $defaultFilePath = __DIR__ . "/lang/{$this->defaultLang}.json";
            $defaultLangData = json_decode(file_get_contents($defaultFilePath), true);
            $value = $this->getFromLanguageData($key, $defaultLangData);
        }

        if ($value === null) {
            return $default ?? $key;
        }

        // 变量替换
        if (is_string($value) && !empty($replacements)) {
            foreach ($replacements as $placeholder => $replacement) {
                $value = str_replace(":$placeholder", $replacement, $value);
            }
        }

        return $value;
    }

    private function getFromLanguageData($key, $data = null)
    {
        $keys = explode('.', $key);
        $value = $data ?? $this->langData;

        foreach ($keys as $nested) {
            if (isset($value[$nested])) {
                $value = $value[$nested];
            } else {
                return null;
            }
        }

        return $value;
    }

    //获取当前语言ID
    public function getCurrentLanguage(){
        return $this->currentLang;
    }
    //获取当前语言ID
    public function id(){
        return $this->currentLang;
    }
    //获取语言左右结构
    public function direction(){
        if($this->currentLang == "ar" || $this->currentLang == "fa"){
            return "rtl";
        }else{
            return "ltr";
        }
    }
    //获取当前语言名字
    public function getCurrentLanguageName(){
        return $this->supportedLangs[$this->currentLang];
    }
    //获取支持语言表
    public function getSupportedLanguages(){
        return $this->supportedLangs;
    }
}

使用示例如下:

Json数据

{
  "user": {
    "auth": {
      "register": {
        "password_mismatch": "Passwords do not match!",
        "email_exists": "Email already exists. Please use a different one!"
      }
    },
    "welcome": "Welcome, :name!"
  }
}
// 初始化语言类
$lang = new Language();

// 获取翻译
echo $lang->get('user.auth.register.password_mismatch');

// 使用变量替换
echo $lang->get('user.welcome', ['name' => 'John']);

// 获取当前语言代码
echo $lang->getCurrentLanguage();

// 获取当前语言名称
echo $lang->getCurrentLanguageName();

// 获取支持的语言列表
print_r($lang->getSupportedLanguages());

// 获取语言选项(适用于下拉菜单)
$languageOptions = $lang->getLanguageOptions();
foreach ($languageOptions as $option) {
    echo "<option value='{$option['code']}'" . ($option['selected'] ? ' selected' : '') . ">{$option['name']}</option>";
}

或者使用下面的这个类

<?php
namespace App\Utility;

#use EasySwoole\Component\Singleton;

class Language
{
    #use Singleton;

    /**
     * 语言包缓存
     * @var array
     */
    private $languageData = [];
  
    /**
     * 当前语言
     * @var string
     */
    private $currentLang = 'en';
  
    /**
     * 支持的语言列表
     * @var array
     */
    private $supportedLangs = [
        "en" => "English",
        "zh" => "中文简体",
        "fr" => "Français",
        "de" => "Deutsch"
    ];
  
    public function __construct()
    {
        // 预加载当前语言包
        $this->loadLanguage($this->currentLang);
    }
  
    /**
     * 设置当前语言
     * @param string $lang
     * @return bool
     */
   
    public function setLanguage(string $lang): bool
    {
        $lang = substr($lang, 0, 2);
        if (array_key_exists($lang, $this->supportedLangs)) {
            $this->currentLang = $lang;
            return $this->loadLanguage($lang);
        }
        return false;
    }

    /**
     * 加载语言包
     * @param string $lang
     * @return bool
    */
    public function loadLanguage(string $lang): bool
    {
        if (!array_key_exists($lang, $this->supportedLangs)) {
            return false;
        }
        $langFile = EASYSWOOLE_ROOT . "/App/Language/{$lang}.json";
        // 检查文件是否存在
        if (!file_exists($langFile)) {
            return false;
        }

        try {
            // 读取JSON文件
            $jsonContent = file_get_contents($langFile);
            if ($jsonContent === false) {
                throw new \Exception("Cannot read language file: $langFile");
            }
            // 解析JSON
            $data = json_decode($jsonContent, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                throw new \Exception("Invalid JSON in language file: " . json_last_error_msg());
            }

            // 更新缓存
            $this->languageData[$lang] = $data;

            return true;
        } catch (\Exception $e) {
            // 记录错误日志
            trigger_error("Language file error: " . $e->getMessage(), E_USER_WARNING);
            return false;
        }
    }

    /**
      * 获取翻译
      * @param string $key
      * @param array $params
      * @param string|null $lang
      * @return string
    */
    public function trans(string $key, array $params = [], ?string $lang = null): string
    {
        $useLang = $lang ?? $this->currentLang;
  
        if (!isset($this->languageData[$useLang])) {
            $this->loadLanguage($useLang);
        }
  
        $text = $this->get($key, $useLang);
  
        if (!empty($params)) {
            foreach ($params as $param => $value) {
                $text = str_replace(':' . $param, $value, $text);
            }
        }
  
        return $text;
    }
  
    /**
     * 获取语言文本
     * @param string $key
     * @param string|null $lang
     * @return string
     */
    private function get(string $key, ?string $lang = null): string
    {
        $useLang = $lang ?? $this->currentLang;
        $keys = explode('.', $key);
  
        $data = $this->languageData[$useLang] ?? [];
  
        foreach ($keys as $segment) {
            if (isset($data[$segment])) {
                $data = $data[$segment];
            } else {
                return $key;
            }
        }
        return is_string($data) ? $data : $key;
    }


    //获取当前语言ID
    public function id(){
        return $this->currentLang;
    }
  
    //获取语言左右结构
    public function direction(){
        if($this->currentLang == "ar" || $this->currentLang == "fa"){
            return "rtl";
        }else{
            return "ltr";
        }
    }
  
    //获取当前语言名字
    public function name(){
        return $this->supportedLangs[$this->currentLang];
    }
  
    //获取支持语言表
    public function support(){
        return $this->supportedLangs;
    }
}

使用方法如下

    // 设置语言
    $language = new Language();
    $language->setLanguage($lang);
    // 使用翻译
    $welcome = $language->trans('user.welcome', ['name' => 'John']);
Last Modified: October 31, 2024