Select Git revision
I18NString.php
Forked from
Stud.IP / Stud.IP
Source project has a limited visibility.
-
Closes #1672 Merge request studip/studip!1076
Closes #1672 Merge request studip/studip!1076
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
I18NString.php 11.46 KiB
<?php
/**
* I18NString class
*/
class I18NString implements JsonSerializable
{
/**
* Text in default content language.
*
* @var string
*/
protected $base;
/**
* Text in additional languages.
*
* @var array|null
*/
protected $lang;
/**
* Database info for id, table, field.
*
* @var array
*/
protected $metadata;
/**
* Holds the language the content is translated into.
*
* @var string
*/
protected static $content_language = null;
/**
* Holds the language the content is translated into by default.
*
* @var string
*/
protected static $default_language = null;
/**
* Initialize a new I18NString instance.
*
* @param string $base Text in default content language.
* @param array $lang Text in additional languages.
* @param array $metadata Database info for id, table, field.
*/
public function __construct($base, $lang = null, $metadata = [])
{
$this->base = $base;
$this->lang = $lang;
$this->metadata = $metadata;
}
/**
* Return the text representation of this i18n field in selected language.
* The language is selected by self::content_language (with precendence)
* or by $_SESSION['_language'].
*
* @returns string
*/
public function __toString()
{
if (self::$content_language) {
return $this->localized(self::$content_language) ?? (string) $this->base;
} else {
if (isset($_SESSION['_language'])
&& $_SESSION['_language'] != self::getDefaultLanguage()
&& $this->translation($_SESSION['_language'])) {
return $this->translation($_SESSION['_language']);
}
}
return (string) $this->base;
}
/**
* Return the JSON representation of this i18n field in selected language.
*
* @return string
*/
public function jsonSerialize()
{
return (string) $this;
}
/**
* Sets the language the content is translated into.
*
* @param string $language
*/
public static function setContentLanguage($language)
{
self::$content_language = $language;
}
/**
* Returns the language the contnet is translated into.
*
* @return string The language the content is translated into.
*/
public static function getContentLanguage()
{
return self::$content_language ?: self::getDefaultLanguage();
}
/**
* Sets the default language the content is translated into. The default is
* normally defined by the first entry in $GLOBALS['CONTENT_LANGUAGES'] (see
* config_defaults.inc.php).
*
* @param string $language
*/
public static function setDefaultLanguage($language = null)
{
self::$default_language = $language ?: key($GLOBALS['CONTENT_LANGUAGES']);
}
/**
* Returns the language all values are translated into by default. The
* language ist normally defined in $GLOBALS['CONTENT_LANGUAGES'] (see
* config_defaults.inc.php).
*
* @return string The default language all values are translated into.
*/
public static function getDefaultLanguage()
{
return self::$default_language ?: key($GLOBALS['CONTENT_LANGUAGES']);
}
/**
* Sets the original (untranslated) value of this i18n field.
*
* @param string $text The original value.
* @return string The original value.
*/
public function setOriginal($text)
{
return $this->base = $text;
}
/**
* Sets all translations of this i18n field.
*
* @param array $lang An array with languages as keys and translations
* as values.
* @return array The array with translations.
*/
public function setTranslations($lang)
{
return $this->lang = $lang;
}
/**
* Sets the metadata (database info for id, table, field) of this i18n field.
*
* @param array $metadata Database info for id, table, field.
*/
public function setMetadata($metadata)
{
$this->metadata = $metadata;
}
/**
* Return the string in the default content language.
*
* @return string String in default content language.
*/
public function original()
{
return $this->base;
}
/**
* Return the string in the specified additional language.
*
* @param string The additional language.
* @return string The translated value.
*/
public function translation($lang)
{
return $this->toArray()[$lang];
}
/**
* Returns the string in the specified language (additional languages and
* default languages).
*
* @param string $lang Additional language or default language.
* @return string The localized string.
*/
public function localized($lang)
{
if ($lang == self::getDefaultLanguage()) {
return $this->base;
}
return $this->translation($lang);
}
/**
* Sets the translation for the given language. If the given language is
* the default language, sets the original.
*
* @param type $text The translated or original value.
* @param type $lang The additional or default language.
* @return string The translated or original value.
* @throws InvalidArgumentException
*/
public function setLocalized($text, $lang)
{
if ($lang == self::getDefaultLanguage()) {
return $this->setOriginal($text);
}
if (!Config::get()->CONTENT_LANGUAGES[$lang]) {
throw new InvalidArgumentException('Language not configured.');
}
return $this->lang[$lang] = $text;
}
/**
* Return an array containing the text in all additional languages.
*
* @return array The array with translations.
*/
public function toArray()
{
if (is_null($this->lang)) {
$object_id = $this->metadata['object_id'];
$table = $this->metadata['table'];
$field = $this->metadata['field'];
if (!$table || !$field) {
throw new RuntimeException('fetching translations not possible, metadata is missing');
}
$this->lang = self::fetchDataForField($object_id, $table, $field);
}
return $this->lang;
}
/**
* Trim all language strings
*
* @param string $symbols All symbols to trim.
* @return I18NString Returns this.
*/
public function trim($symbols = " \t\n\r\0\x0B")
{
foreach ($this->lang as &$lang) {
$lang = trim($lang, $symbols);
}
$this->base = trim($this->base, $symbols);
return $this;
}
/**
* Stores the i18n String manually in the database
*
*/
public function storeTranslations()
{
if (is_array($this->lang)) {
$db = DBManager::get();
$object_id = $this->metadata['object_id'];
$table = $this->metadata['table'];
$field = $this->metadata['field'];
if (!$object_id || !$table || !$field) {
throw new RuntimeException('store not possible, metadata is missing');
}
/* Replace translations */
$deleted = $db->execute("DELETE FROM i18n WHERE object_id = ? AND `table` = ? AND field = ?", [$object_id, $table, $field]);
$i18nSQL = $db->prepare("INSERT INTO `i18n` (`object_id`, `table`, `field`, `lang`, `value`) VALUES (?,?,?,?,?)");
foreach ($this->lang as $lang => $value) {
if (mb_strlen($value)) {
$i18nSQL->execute([$object_id, $table, $field, $lang, (string) $value]);
}
}
}
}
/**
* Removes all translations for this I18NString object.
*
*/
public function removeTranslations()
{
$this->lang = [];
$this->storeTranslations();
}
/**
* Returns an I18NString object by given object_id, table and field.
*
* @param string $object_id The id of the object with i18n fields.
* @param string $table The name of the table with the original values.
* @param string $field The name of the i18n field.
* @param string $base Sets the original value or retrieve it from database
* if null.
* @return I18NString The I18NString object.
*/
public static function load($object_id, $table, $field, $base = null)
{
$db = DBManager::get();
if (is_null($base)) {
// Find pk
SimpleORMap::tableScheme($table);
if (count(SimpleORMap::$schemes[$table]['pk']) > 1) {
throw new RuntimeException(sprintf('table %s has multiple primary key, not implemented yet', $table));
} else {
$pk = SimpleORMap::$schemes[$table]['pk'][0];
}
$base = $db->fetchColumn("SELECT `$field` FROM `$table` WHERE `$pk` = ?", [$object_id]);
}
return new self($base, self::fetchDataForField($object_id, $table, $field), compact('object_id', 'table', 'field'));
}
/**
* Retrieves all translations of one field.
*
* @param string $object_id The id of the object with i18n fields.
* @param string $table The name of the table with the original values.
* @param string $field The name of the i18n field.
* @return array An array with language as key and translation as value.
*/
public static function fetchDataForField($object_id, $table, $field)
{
$db = DBManager::get();
$values = $db->fetchPairs("SELECT `lang`, `value` FROM `i18n` WHERE `object_id` = ? AND `table` = ? AND `field` = ?", [$object_id, $table, $field]);
$data = [];
foreach (array_keys(Config::get()->CONTENT_LANGUAGES) as $lang) {
if ($lang != self::getDefaultLanguage()) {
$data[$lang] = mb_strlen($values[$lang]) ? $values[$lang] : null;
}
}
return $data;
}
/**
* Retrieves all translations of all fields for given object (by id) and
* table.
*
* @param string $object_id The id of the object with i18n fields.
* @param string $table The name of the table with the original values.
* @return array An array with all translations of all fields grouped by
* field.
*/
public static function fetchDataForRow($object_id, $table)
{
$db = DBManager::get();
return $db->fetchGrouped("SELECT `field`, `lang`, `value` FROM `i18n` WHERE `object_id` = ? AND `table` = ?", [$object_id, $table]);
}
/**
* Removes all translations by given object id and table name. Accepts the
* language as third parameter to remove only translations to this language.
*
* @param string $object_id The id of the sorm object.
* @param string $table The table name.
* @param string $lang Optional name of language.
* @return int The number of deleted translations.
*/
public static function removeAllTranslations($object_id, $table, $lang = null)
{
$db = DBManager::get();
if ($lang) {
return $db->execute('DELETE FROM `i18n` '
. 'WHERE `object_id` = ? AND `table` = ? AND `lang` = ?',
[$object_id, $table, $lang]);
}
return $db->execute('DELETE FROM `i18n` '
. 'WHERE `object_id` = ? AND `table` = ?',
[$object_id, $table]);
}
}