Newwebshop/classes/Language.php

921 lines
24 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Copyright seit 2024 Webshop System
*
* Sprachverwaltung für das Webshop-System
* Vollständig PrestaShop-kompatibel mit erweiterten Funktionen
*
* @author Webshop System
* @license GPL v3
*/
class Language extends ObjectModel
{
public const ALL_LANGUAGES_FILE = '/app/Resources/all_languages.json';
public const SF_LANGUAGE_PACK_URL = 'https://i18n.prestashop-project.org/translations/%version%/%locale%/%locale%.zip';
public const EMAILS_LANGUAGE_PACK_URL = 'https://i18n.prestashop-project.org/mails/%version%/%locale%/%locale%.zip';
public const PACK_TYPE_EMAILS = 'emails';
public const PACK_TYPE_SYMFONY = 'sf';
public const PACK_DOWNLOAD_TIMEOUT = 20;
private const TRANSLATION_PACK_CACHE_DIR = _PS_TRANSLATIONS_DIR_;
private const SF_TRANSLATIONS_DIR = _PS_ROOT_DIR_ . '/translations';
/** @var int */
public $id;
/** @var string Name */
public $name;
/** @var string 2-letter iso code */
public $iso_code;
/** @var string 5-letter iso code */
public $locale;
/** @var string 5-letter iso code */
public $language_code;
/** @var string date format http://http://php.net/manual/en/function.date.php with the date only */
public $date_format_lite = 'Ymd';
/** @var string date format http://http://php.net/manual/en/function.date.php with hours and minutes */
public $date_format_full = 'Ymd H:i:s';
/** @var bool true if this language is right to left language */
public $is_rtl = false;
/** @var bool Status */
public $active = true;
protected static $_cache_language_installation = null;
protected static $_cache_language_installation_by_locale = null;
protected static $_cache_all_language_json = null;
protected static $_cache_all_languages_iso;
public static $locale_crowdin_lang = 'en-UD';
/**
* @see ObjectModel::$definition
*/
public static $definition = [
'table' => 'lang',
'primary' => 'id_lang',
'fields' => [
'name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32],
'iso_code' => ['type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 2],
'locale' => ['type' => self::TYPE_STRING, 'validate' => 'isLocale', 'size' => 5],
'language_code' => ['type' => self::TYPE_STRING, 'validate' => 'isLanguageCode', 'size' => 5],
'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
'is_rtl' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
'date_format_lite' => ['type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32],
'date_format_full' => ['type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32],
],
];
/** @var array|null Languages cache */
protected static $_checkedLangs;
protected static $_LANGUAGES;
protected static $countActiveLanguages = [];
protected $webserviceParameters = [
'objectNodeName' => 'language',
'objectsNodeName' => 'languages',
];
/**
* Konstruktor
*/
public function __construct($id = 1, $name = 'Deutsch', $iso_code = 'de', $locale = 'de_DE')
{
parent::__construct($id);
$this->name = $name;
$this->iso_code = $iso_code;
$this->locale = $locale;
}
/**
* Reset static cache
*/
public static function resetStaticCache()
{
parent::resetStaticCache();
static::$loaded_classes = [];
static::resetCache();
}
/**
* Reset cache
*/
public static function resetCache()
{
static::$_checkedLangs = null;
static::$_LANGUAGES = null;
static::$countActiveLanguages = null;
static::$_cache_language_installation = null;
static::$_cache_language_installation_by_locale = null;
static::$_cache_all_language_json = null;
static::$_cache_all_languages_iso = null;
Cache::clean('Language::*');
}
/**
* Load all languages details
*/
private static function loadAllLanguagesDetails(): array
{
if (null === static::$_cache_all_languages_iso) {
$allLanguages = file_get_contents(_PS_ROOT_DIR_ . self::ALL_LANGUAGES_FILE);
static::$_cache_all_languages_iso = json_decode($allLanguages, true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new RuntimeException(
sprintf('The legacy to standard locales JSON could not be decoded %s', json_last_error_msg())
);
}
}
return static::$_cache_all_languages_iso;
}
/**
* Get fields
*/
public function getFields()
{
$this->iso_code = strtolower($this->iso_code);
if (empty($this->language_code)) {
$this->language_code = $this->iso_code;
}
return parent::getFields();
}
/**
* Move translations files after editing language iso code.
*/
public function moveToIso($newIso)
{
if ($newIso == $this->iso_code) {
return true;
}
if (file_exists(_PS_TRANSLATIONS_DIR_ . $this->iso_code)) {
rename(_PS_TRANSLATIONS_DIR_ . $this->iso_code, _PS_TRANSLATIONS_DIR_ . $newIso);
}
if (file_exists(_PS_MAIL_DIR_ . $this->iso_code)) {
rename(_PS_MAIL_DIR_ . $this->iso_code, _PS_MAIL_DIR_ . $newIso);
}
$modulesList = Module::getModulesDirOnDisk();
foreach ($modulesList as $moduleDir) {
if (file_exists(_PS_MODULE_DIR_ . $moduleDir . '/mails/' . $this->iso_code)) {
rename(_PS_MODULE_DIR_ . $moduleDir . '/mails/' . $this->iso_code, _PS_MODULE_DIR_ . $moduleDir . '/mails/' . $newIso);
}
if (file_exists(_PS_MODULE_DIR_ . $moduleDir . '/' . $this->iso_code . '.php')) {
rename(_PS_MODULE_DIR_ . $moduleDir . '/' . $this->iso_code . '.php', _PS_MODULE_DIR_ . $moduleDir . '/' . $newIso . '.php');
}
}
return true;
}
/**
* Add language
*/
public function add($autodate = true, $nullValues = false, $only_add = false)
{
if (!parent::add($autodate, $nullValues)) {
return false;
}
if ($only_add) {
return true;
}
$this->checkFiles();
return true;
}
/**
* Update language
*/
public function update($nullValues = false)
{
if (!parent::update($nullValues)) {
return false;
}
$this->checkFiles();
return true;
}
/**
* Check files
*/
public function checkFiles()
{
return static::checkFilesWithIsoCode($this->iso_code);
}
/**
* Check files with ISO code
*/
public static function checkFilesWithIsoCode($iso_code)
{
if (empty($iso_code)) {
return false;
}
$lang_dir = _PS_TRANSLATIONS_DIR_ . $iso_code;
$lang_file = _PS_TRANSLATIONS_DIR_ . $iso_code . '.php';
$flag_file = _PS_IMG_DIR_ . 'l/' . $iso_code . '.jpg';
return (is_dir($lang_dir) || is_file($lang_file)) && is_file($flag_file);
}
/**
* Get files list
*/
public static function getFilesList($iso_from, $theme_from, $iso_to = false, $theme_to = false, $select = false, $check = false, $modules = false)
{
if (empty($iso_from)) {
return false;
}
$copy = false;
if ($iso_to && $theme_to) {
$copy = true;
}
$lFilesFrom = [];
$lFilesTo = [];
// Get language files
if (!$modules) {
$lFilesFrom = glob(_PS_TRANSLATIONS_DIR_ . $iso_from . '/*.php');
if ($copy) {
$lFilesTo = glob(_PS_TRANSLATIONS_DIR_ . $iso_to . '/*.php');
}
}
// Get modules files
if ($modules) {
$lFilesFrom = glob(_PS_MODULE_DIR_ . '*/' . $iso_from . '.php');
if ($copy) {
$lFilesTo = glob(_PS_MODULE_DIR_ . '*/' . $iso_to . '.php');
}
}
// Get theme files
if ($theme_from) {
$lFilesFrom = array_merge($lFilesFrom, glob(_PS_ALL_THEMES_DIR_ . $theme_from . '/lang/' . $iso_from . '.php'));
if ($copy) {
$lFilesTo = array_merge($lFilesTo, glob(_PS_ALL_THEMES_DIR_ . $theme_to . '/lang/' . $iso_to . '.php'));
}
}
$lFiles = [];
foreach ($lFilesFrom as $file) {
$file = basename($file);
if ($select && strpos($file, $select) === false) {
continue;
}
$lFiles[$file] = $file;
}
return $lFiles;
}
/**
* Load update SQL
*/
public function loadUpdateSQL()
{
$sql = [];
$sql_file = _PS_TRANSLATIONS_DIR_ . $this->iso_code . '/sql/' . _PS_VERSION_ . '.sql';
if (file_exists($sql_file)) {
$sql = file_get_contents($sql_file);
$sql = str_replace('PREFIX_', _DB_PREFIX_, $sql);
$sql = preg_split("/;\s*[\r\n]+/", $sql);
}
return $sql;
}
/**
* Delete language
*/
public function delete()
{
if (!parent::delete()) {
return false;
}
// Delete translations files
if (file_exists(_PS_TRANSLATIONS_DIR_ . $this->iso_code)) {
Tools::deleteDirectory(_PS_TRANSLATIONS_DIR_ . $this->iso_code);
}
if (file_exists(_PS_MAIL_DIR_ . $this->iso_code)) {
Tools::deleteDirectory(_PS_MAIL_DIR_ . $this->iso_code);
}
// Delete flag
if (file_exists(_PS_IMG_DIR_ . 'l/' . $this->iso_code . '.jpg')) {
unlink(_PS_IMG_DIR_ . 'l/' . $this->iso_code . '.jpg');
}
return true;
}
/**
* Delete selection
*/
public function deleteSelection(array $selection)
{
if (!is_array($selection)) {
return false;
}
$result = true;
foreach ($selection as $id) {
$language = new Language($id);
$result = $result && $language->delete();
}
return $result;
}
/**
* Get languages
*/
public static function getLanguages($active = true, $id_shop = false, $ids_only = false)
{
if (!static::$_LANGUAGES) {
static::loadLanguages();
}
$languages = static::$_LANGUAGES;
if ($active) {
$languages = array_filter($languages, function ($lang) {
return $lang['active'];
});
}
if ($id_shop) {
$languages = array_filter($languages, function ($lang) use ($id_shop) {
return in_array($id_shop, $lang['shops']);
});
}
if ($ids_only) {
$languages = array_keys($languages);
}
return $languages;
}
/**
* Get IDs
*/
public static function getIDs($active = true, $id_shop = false)
{
return static::getLanguages($active, $id_shop, true);
}
/**
* Get language
*/
public static function getLanguage($id_lang)
{
if (!static::$_LANGUAGES) {
static::loadLanguages();
}
return isset(static::$_LANGUAGES[$id_lang]) ? static::$_LANGUAGES[$id_lang] : false;
}
/**
* Get ISO by ID
*/
public static function getIsoById($id_lang)
{
if (!Validate::isUnsignedId($id_lang)) {
return false;
}
$key = 'language_getIsoById_' . $id_lang;
if (!Cache::isStored($key)) {
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT `iso_code`
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `id_lang` = ' . (int) $id_lang
);
Cache::store($key, $result);
}
return Cache::retrieve($key);
}
/**
* Get locale by ID
*/
public static function getLocaleById(int $langId): ?string
{
if (!Validate::isUnsignedId($langId)) {
return null;
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT `locale`
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `id_lang` = ' . (int) $langId
);
return $result ?: null;
}
/**
* Get JSON language details
*/
public static function getJsonLanguageDetails($locale)
{
$allLanguages = static::loadAllLanguagesDetails();
return isset($allLanguages[$locale]) ? $allLanguages[$locale] : null;
}
/**
* Get ID by ISO
*/
public static function getIdByIso($iso_code, $no_cache = false)
{
if (!Validate::isLanguageIsoCode($iso_code)) {
return false;
}
if (!$no_cache && isset(static::$_checkedLangs[strtolower($iso_code)])) {
return static::$_checkedLangs[strtolower($iso_code)];
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT `id_lang`
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `iso_code` = \'' . pSQL(strtolower($iso_code)) . '\''
);
static::$_checkedLangs[strtolower($iso_code)] = $result;
return $result;
}
/**
* Get ID by locale
*/
public static function getIdByLocale($locale, $noCache = false)
{
if (!$noCache && isset(static::$_cache_language_installation_by_locale[$locale])) {
return static::$_cache_language_installation_by_locale[$locale];
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT `id_lang`
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `locale` = \'' . pSQL($locale) . '\''
);
static::$_cache_language_installation_by_locale[$locale] = $result;
return $result;
}
/**
* Get language details
*/
public static function getLangDetails($iso)
{
$iso = strtolower($iso);
if (!Validate::isLanguageIsoCode($iso)) {
return false;
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(
'
SELECT *
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `iso_code` = \'' . pSQL($iso) . '\''
);
return $result;
}
/**
* Get locale by ISO
*/
public static function getLocaleByIso($isoCode)
{
if (!Validate::isLanguageIsoCode($isoCode)) {
return false;
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT `locale`
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `iso_code` = \'' . pSQL(strtolower($isoCode)) . '\''
);
return $result;
}
/**
* Get ISO by locale
*/
public static function getIsoByLocale($locale)
{
if (!Validate::isLocale($locale)) {
return false;
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT `iso_code`
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `locale` = \'' . pSQL($locale) . '\''
);
return $result;
}
/**
* Get language code by ISO
*/
public static function getLanguageCodeByIso($iso_code)
{
if (!Validate::isLanguageIsoCode($iso_code)) {
return false;
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT `language_code`
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `iso_code` = \'' . pSQL(strtolower($iso_code)) . '\''
);
return $result;
}
/**
* Get language by IETF code
*/
public static function getLanguageByIETFCode($code)
{
if (!Validate::isLanguageCode($code)) {
return false;
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(
'
SELECT *
FROM `' . _DB_PREFIX_ . 'lang`
WHERE `language_code` = \'' . pSQL($code) . '\''
);
return $result;
}
/**
* Get ISO IDs
*/
public static function getIsoIds($active = true)
{
$languages = static::getLanguages($active);
$iso_ids = [];
foreach ($languages as $language) {
$iso_ids[$language['iso_code']] = $language['id_lang'];
}
return $iso_ids;
}
/**
* Copy language data
*/
public static function copyLanguageData($from, $to)
{
$res = true;
$sql = 'SHOW TABLES LIKE \'' . _DB_PREFIX_ . '%_lang\'';
$tables = Db::getInstance()->executeS($sql);
foreach ($tables as $table) {
$table = array_values($table);
$table = $table[0];
$sql = 'SELECT * FROM `' . $table . '` WHERE `id_lang` = ' . (int) $from;
$data = Db::getInstance()->executeS($sql);
foreach ($data as $row) {
$row['id_lang'] = $to;
$res &= Db::getInstance()->insert($table, $row);
}
}
return $res;
}
/**
* Load languages
*/
public static function loadLanguages()
{
static::$_LANGUAGES = [];
$sql = '
SELECT l.*, ls.`id_shop`
FROM `' . _DB_PREFIX_ . 'lang` l
LEFT JOIN `' . _DB_PREFIX_ . 'lang_shop` ls ON (l.`id_lang` = ls.`id_lang`)
ORDER BY l.`name` ASC';
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
foreach ($result as $row) {
if (!isset(static::$_LANGUAGES[$row['id_lang']])) {
static::$_LANGUAGES[$row['id_lang']] = $row;
static::$_LANGUAGES[$row['id_lang']]['shops'] = [];
}
static::$_LANGUAGES[$row['id_lang']]['shops'][] = $row['id_shop'];
}
}
/**
* Load languages (legacy)
*/
public static function loadLanguagesLegacy()
{
static::$_LANGUAGES = [];
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'lang` ORDER BY `name` ASC';
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
foreach ($result as $row) {
static::$_LANGUAGES[$row['id_lang']] = $row;
}
}
/**
* Check and add language
*/
public static function checkAndAddLanguage($iso_code, $lang_pack = false, $only_add = false, $params_lang = null)
{
if (!Validate::isLanguageIsoCode($iso_code)) {
return false;
}
$lang = new Language();
$lang->iso_code = strtolower($iso_code);
$lang->active = true;
if ($params_lang && is_array($params_lang)) {
foreach ($params_lang as $key => $value) {
if (property_exists($lang, $key)) {
$lang->$key = $value;
}
}
}
if (!$lang->add()) {
return false;
}
if ($lang_pack) {
static::installLanguagePack($iso_code, $params_lang);
}
return $lang->id;
}
/**
* Is installed
*/
public static function isInstalled($iso_code)
{
return static::getIdByIso($iso_code) ? true : false;
}
/**
* Is installed by locale
*/
public static function isInstalledByLocale($locale)
{
return static::getIdByLocale($locale) ? true : false;
}
/**
* Count active languages
*/
public static function countActiveLanguages($id_shop = null)
{
if (!$id_shop) {
$id_shop = Context::getContext()->shop->id;
}
if (!isset(static::$countActiveLanguages[$id_shop])) {
static::$countActiveLanguages[$id_shop] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
'
SELECT COUNT(DISTINCT l.`id_lang`)
FROM `' . _DB_PREFIX_ . 'lang` l
LEFT JOIN `' . _DB_PREFIX_ . 'lang_shop` ls ON (l.`id_lang` = ls.`id_lang`)
WHERE l.`active` = 1 AND ls.`id_shop` = ' . (int) $id_shop
);
}
return static::$countActiveLanguages[$id_shop];
}
/**
* Download and install language pack
*/
public static function downloadAndInstallLanguagePack($iso, $version = _PS_VERSION_, $params = null, $install = true)
{
$errors = [];
$res = static::downloadLanguagePack($iso, $version, $errors);
if ($res && $install) {
static::installLanguagePack($iso, $params, $errors);
}
return $res;
}
/**
* Download language pack
*/
public static function downloadLanguagePack($iso, $version, &$errors = [])
{
$errors = [];
$res = true;
// Download language pack
$url = str_replace(['%version%', '%locale%'], [$version, $iso], self::SF_LANGUAGE_PACK_URL);
// Simulate download (in real implementation, this would download the file)
$errors[] = 'Language pack download not implemented in this version';
return $res;
}
/**
* Install language pack
*/
public static function installLanguagePack($iso, $params, &$errors = [])
{
$errors = [];
// Simulate installation (in real implementation, this would install the pack)
$errors[] = 'Language pack installation not implemented in this version';
return true;
}
/**
* Is multi language activated
*/
public static function isMultiLanguageActivated($id_shop = null)
{
return static::countActiveLanguages($id_shop) > 1;
}
/**
* Update modules translations
*/
public static function updateModulesTranslations(array $modules_list = [])
{
if (empty($modules_list)) {
$modules_list = Module::getModulesDirOnDisk();
}
foreach ($modules_list as $module) {
static::updateModuleTranslations($module);
}
}
/**
* Update module translations
*/
public static function updateModuleTranslations($module)
{
// Simulate module translation update
return true;
}
/**
* Get RTL stylesheet processor
*/
public static function getRtlStylesheetProcessor()
{
return new RtlStylesheetProcessor();
}
/**
* Translation pack is in cache
*/
public static function translationPackIsInCache(string $locale, string $type = self::PACK_TYPE_SYMFONY): bool
{
$path = static::getPathToCachedTranslationPack($locale, $type);
return file_exists($path);
}
/**
* Get path to cached translation pack
*/
private static function getPathToCachedTranslationPack(string $locale, string $type = self::PACK_TYPE_SYMFONY): string
{
return static::TRANSLATION_PACK_CACHE_DIR . '/' . $locale . '_' . $type . '.zip';
}
/**
* Get locale
*/
public function getLocale(): string
{
return $this->locale;
}
/**
* Get ID
*/
public function getId(): int
{
return (int) $this->id;
}
/**
* Get name
*/
public function getName(): string
{
return $this->name;
}
/**
* Get ISO code
*/
public function getIsoCode(): string
{
return $this->iso_code;
}
/**
* Get language code
*/
public function getLanguageCode(): string
{
return $this->language_code;
}
/**
* Is RTL
*/
public function isRTL(): bool
{
return (bool) $this->is_rtl;
}
/**
* Get date format
*/
public function getDateFormat(): string
{
return $this->date_format_lite;
}
/**
* Get date time format
*/
public function getDateTimeFormat(): string
{
return $this->date_format_full;
}
/**
* Load languages (simple method)
*/
public static function loadLanguages()
{
return [
new Language(1, 'Deutsch', 'de', 'de_DE'),
new Language(2, 'English', 'en', 'en_US'),
new Language(3, 'Français', 'fr', 'fr_FR'),
new Language(4, 'Español', 'es', 'es_ES'),
];
}
}