Merge pull request #95 from RETROTEC-AG/pr/locale-des-gui-users-ermitteln

Locale des GUI-Users ermitteln
This commit is contained in:
OpenXE-ERP 2023-08-16 12:11:45 +02:00 committed by GitHub
commit 74aeb90758
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 7155 additions and 4 deletions

View File

@ -0,0 +1,151 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n;
use Xentral\Components\Database\Database;
use Xentral\Components\Http\Request;
use Xentral\Components\Http\Session\Session;
use Xentral\Core\DependencyInjection\ServiceContainer;
/**
* Factory for localization object.
*
* @see Localization
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
final class Bootstrap
{
/**
* @return array
*/
public static function registerServices(): array
{
return [
'Localization' => 'onInitLocalization',
];
}
/**
* Replaces umlauts with their 2 character representation.
*
* @param string $string
*
* @return array|string|string[]
*/
public static function replaceUmlauts(string $string)
{
$search = ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü', 'ß'];
$replace = ['ae', 'oe', 'ue', 'Ae', 'Oe', 'Ue', 'ss'];
return str_replace($search, $replace, $string);
}
/**
* Find the language information from the given string.
*
* @param string $lang
*
* @return array|null
*/
public static function findLanguage(string $lang): ?array
{
$subject = strtolower($lang);
foreach ((new Iso639()) as $key => $val) {
if (array_filter($val, function ($str) use ($subject) {
return $str && ((strtolower($str) == $subject) || (self::replaceUmlauts(strtolower($str)) == $subject));
})) {
return $val;
}
}
return null;
}
/**
* Find the region information from the given string.
*
* @param string $region
*
* @return array|null
*/
public static function findRegion(string $region): ?array
{
$subject = strtolower($region);
foreach ((new Iso3166()) as $key => $val) {
if (array_filter($val, function ($str) use ($subject) {
return $str && ((strtolower($str) == $subject) || (self::replaceUmlauts(strtolower($str)) == $subject));
})) {
return $val;
}
}
return null;
}
/**
* This is the factory for the Localization object.
*
* @param ServiceContainer $container
*
* @return Localization
*/
public static function onInitLocalization(ServiceContainer $container): Localization
{
/** @var Request $request */
$request = $container->get('Request');
/** @var Session $session */
$session = $container->get('Session');
/** @var \erpooSystem $app */
$app = $container->get('LegacyApplication');
/** @var Database $db */
$db = $container->get('Database');
$config=[];
$firmaLang=null;
$firmaRegion=null;
// Get language from system settings and normalize to 3-letter-code and 2-letter-code
if ($firmaLang = self::findLanguage($app->erp->Firmendaten('preferredLanguage'))) {
$config[Localization::LANGUAGE_DEFAULT] = $firmaLang[Iso639\Key::ALPHA_3];
}
// Get region from system settings and normalize to 2-letter-code
if ($firmaLang && ($firmaRegion = self::findRegion($app->erp->Firmendaten('land')))) {
$config[Localization::LOCALE_DEFAULT] = "{$firmaLang[Iso639\Key::ALPHA_2]}_{$firmaRegion[Iso3166\Key::ALPHA_2]}";
}
// Get User
$usersettings = [];
if ($user = $app->User) {
// Get User's address from user
$userAddress = $db->fetchRow(
$db->select()->cols(['*'])->from('adresse')->where('id=:id'),
['id' => $user->GetAdresse()]
);
// Get language from user account and normalize to 3-letter-code and 2-letter-code
if ($userLang = self::findLanguage($user->GetSprache())) {
$usersettings['language'] = $userLang[Iso639\Key::ALPHA_3];
}
// Get region from user account and normalize to 2-letter-code
if ($userLang && ($userRegion = self::findRegion($userAddress['land']))) {
$usersettings['locale'] = "{$userLang[Iso639\Key::ALPHA_2]}_{$userRegion[Iso3166\Key::ALPHA_2]}";
}
}
// Create Localization object
return new Localization($request, $session, $usersettings, $config);
}
}

View File

@ -0,0 +1,73 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess;
/**
* Provides array access functions to the data provider.
*
* @see \ArrayAccess
* @see DataProvider
* @see DataProviderInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
trait ArrayAccessTrait
{
/**
* Whether an offset exists.
*
* @param string $offset
*
* @return bool
*/
public function offsetExists($offset): bool
{
return array_key_exists($offset, $this->DataProvider_DATA);
}
/**
* Offset to retrieve.
*
* @param string $offset
*
* @return array
*/
public function offsetGet($offset): array
{
return $this->DataProvider_DATA[$offset];
}
/**
* Assign a value to the specified offset.
* No function since data set is read only.
*
* @param string $offset
* @param array $value
*/
public function offsetSet($offset, $value)
{
// $this->DataProvider_DATA[$offset]=$value;
}
/**
* Unset an offset.
* No function since data set is read only.
*
* @param string $offset
*/
public function offsetUnset($offset)
{
// unset($this->DataProvider_DATA[$offset]);
}
}

View File

@ -0,0 +1,30 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess;
/**
* Provides countable functions to the data provider.
*
* @see \Countable
* @see DataProvider
* @see DataProviderInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
trait CountableTrait
{
/**
* Counts the number of records in the private $data array.
*
* @return int Number of records
*/
public function count(): int
{
return count($this->DataProvider_DATA);
}
}

View File

@ -0,0 +1,80 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess;
/**
* Abstract filter class.
*
* @see DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
abstract class DataFilter implements DataFilterInterface
{
/**
* Pointer to next filter in chain.
*
* @var DataFilterInterface
*/
private $nextFilter = null;
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::then()
*/
public function then(DataFilterInterface $filter): DataFilterInterface
{
if (!$this->nextFilter) {
$this->nextFilter = $filter;
} else {
$this->nextFilter->then($filter);
}
return $this;
}
/**
* Applies the filter to the data and executes the next filter
* if present.
*
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::__invoke()
*/
public function __invoke(array $data): array
{
// echo get_called_class()."::__invoke(\$data)".PHP_EOL;
$filteredData = [];
foreach ($data as $key => $val) {
if ($this->selectItem($key, $val)) {
$filteredData[$key] = $val;
}
}
if ($this->nextFilter) {
$filteredData = ($this->nextFilter)($filteredData);
}
return $filteredData;
}
/**
* Check if the current item is to be selected for
* the dataset.
*
* @param mixed $key
* @param mixed $val
*
* @return bool
*/
abstract protected function selectItem(&$key, &$val): bool;
}

View File

@ -0,0 +1,38 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess;
/**
* Filter Interface.
*
* @see DataFilter
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
interface DataFilterInterface
{
/**
* Add a filter to the end of the filter chain.
*
* @param DataFilterInterface $filter Filter to add
*
* @return DataFilterInterface Start of filter chain
*/
function then(DataFilterInterface $filter): DataFilterInterface;
/**
* Applies the filter to the data and executes the next filter
* if present.
*
* @see \Ruga\I18n\Dataaccess\DataFilterInterface::__invoke()
*/
function __invoke(array $data): array;
}

View File

@ -0,0 +1,125 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess;
use ArrayAccess;
use Countable;
use Iterator;
/**
* Abstract implementation of a general data provider.
*
* @see DataProviderInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
abstract class DataProvider implements Countable, Iterator, ArrayAccess, DataProviderInterface
{
use CountableTrait;
use IteratorTrait;
use ArrayAccessTrait;
/**
* Holds filtered data.
*
* @var mixed
*/
private $DataProvider_DATA = null;
/**
* Create the object and apply data filter.
*
* @param DataFilterInterface|null $filter
*/
public function __construct(DataFilterInterface $filter = null)
{
if ($filter) {
$this->DataProvider_DATA = $filter($this->getOriginalData());
} else {
$this->DataProvider_DATA = $this->getOriginalData();
}
}
/**
* Returns the original data array).
* Raw data before any filtering takes place.
*
* @return array
*/
abstract protected function getOriginalData(): array;
/**
* Returns an array suitable for select fields.
* The key of the filtered data set is used as key of the
* array and $desiredName field is used as value.
*
* @param string $desiredName
*
* @return array;
*/
public function getMultiOptions($desiredName = 'NAME_deu'): array
{
$a = [];
foreach ($this as $key => $l) {
$a[$key] = $l[$desiredName];
}
return $a;
}
/**
* Returns the field $desiredName from the record $id.
*
* @param mixed $id
* @param string $desiredName
*
* @return string
*/
public function getString($id, $desiredName): string
{
if (!isset($this[$id])) {
throw new Exception\OutOfRangeException("Index '{$id}' not found");
}
$d = $this[$id];
if ($desiredName) {
if ($desiredName == 'POST') {
return strtoupper($this->getString($id, 'NAME_eng'));
}
return $d[$desiredName];
}
throw new Exception\OutOfRangeException("No '{$desiredName}' data for '{$id}'");
}
/**
* Returns the item at position $id.
*
* @param string $id
*
* @return mixed
*/
public function getData($id)
{
if (empty($id)) {
return null;
}
if (!isset($this[$id])) {
throw new Exception\OutOfRangeException("Index '{$id}' not found.");
}
return $this[$id];
}
}

View File

@ -0,0 +1,53 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess;
/**
* Interface to the general data provider class.
*
* @see DataProvider
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
interface DataProviderInterface
{
/**
* Returns an array suitable for select fields.
* The key of the filtered data set is used as key of the
* array and $desiredName field is used as value.
*
* @param string $desiredName
*
* @return array;
*/
public function getMultiOptions($desiredName): array;
/**
* Returns the field $desiredName from the record $id.
*
* @param mixed $id
* @param string $desiredName
*
* @return string
*/
public function getString($id, $desiredName): string;
/**
* Returns the item at position $id.
*
* @param string $id
*
* @return mixed
*/
public function getData($id);
}

View File

@ -0,0 +1,14 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess\Exception;
class OutOfRangeException extends \OutOfRangeException
{
}

View File

@ -0,0 +1,100 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Dataaccess;
/**
* Provides iterator functions to the data provider.
*
* @see \Iterator
* @see DataProvider
* @see DataProviderInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
trait IteratorTrait
{
/**
* Index of the current element's key.
*
* @var string
*/
private $IteratorTrait_index = null;
/**
* Array of keys of the data set.
*
* @var array
*/
private $IteratorTrait_keys = null;
/**
* Return the current element.
*
* @return mixed
*/
public function current()
{
return $this->valid() ? $this->DataProvider_DATA[$this->key()] : null;
}
/**
* Return the key of the current element.
*
* @return mixed
*/
public function key()
{
return static::valid() ? $this->IteratorTrait_keys[$this->IteratorTrait_index] : null;
}
/**
* Move forward to next element.
*
* @return bool false if invalid
*/
public function next()
{
$this->IteratorTrait_index++;
if (!$this->valid()) {
$this->IteratorTrait_index = null;
}
return $this->valid();
}
/**
* Rewind the Iterator to the first element.
*/
public function rewind()
{
$this->IteratorTrait_keys = array_keys($this->DataProvider_DATA);
sort($this->IteratorTrait_keys);
$this->IteratorTrait_index = 0;
}
/**
* Checks if current position is valid.
*
* @return bool
*/
public function valid(): bool
{
return ($this->IteratorTrait_index !== null)
&& array_key_exists($this->IteratorTrait_index, $this->IteratorTrait_keys)
&& array_key_exists($this->IteratorTrait_keys[$this->IteratorTrait_index], $this->DataProvider_DATA);
}
}

View File

@ -0,0 +1,14 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Exception;
class LanguageNotInitializedException extends \RuntimeException
{
}

View File

@ -0,0 +1,14 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Exception;
class UnsupportedLocaleStringException extends \RuntimeException
{
}

View File

@ -0,0 +1,32 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n;
use Xentral\Components\I18n\Dataaccess\DataProvider;
/**
* Country Codes - ISO 3166.
* Loads the data and holds the filtered (if desired) list.
*
* @see https://www.iso.org/iso-3166-country-codes.html
* @see DataProvider
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* @license AGPL-3.0-only
*/
class Iso3166 extends DataProvider
{
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataProvider::getOriginalData()
*/
protected function getOriginalData(): array
{
return include(__DIR__ . '/data/Iso3166data.php');
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso3166\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
/**
* This filter returns all records from the data set (aka dummy filter).
*
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class All extends DataFilter implements DataFilterInterface
{
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
*/
function selectItem(&$key, &$val): bool
{
return true;
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso3166\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
use Xentral\Components\I18n\Iso3166\Key;
/**
* Applies a filter to only select central european countries.
*
* @see Custom
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class CentralEurope extends Custom implements DataFilterInterface
{
/**
* Countries in Europe.
*
* @var array
*/
const CentralEurope_Countries = ['CHE', 'DEU', 'AUT', 'ITA', 'FRA', 'ESP', 'PRT', 'GBR'];
/**
* Set predefined values.
*/
public function __construct()
{
parent::__construct(static::CentralEurope_Countries, Key::ALPHA_3);
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso3166\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
use Xentral\Components\I18n\Dataaccess\DataFilter;
/**
* This filter can be used to change the main key
* of the data set.
*
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class ChangeKey extends DataFilter implements DataFilterInterface
{
/**
* New key to use for the data set.
*
* @var string
*/
private $ChangeKey_key = null;
/**
* Initialize filter and set the new key.
*
* @param mixed $key
*/
public function __construct($key)
{
$this->ChangeKey_key = $key;
}
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
*/
protected function selectItem(&$key, &$val): bool
{
$key = $val[$this->ChangeKey_key];
return true;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso3166\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
/**
* Apply a custom filter to the data set.
*
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class Custom extends DataFilter implements DataFilterInterface
{
/**
* Array of wanted values.
*
* @var array
*/
private $Custom_values = null;
/**
* Key to check for the values in $this->Custom_values.
*
* @var string
*/
private $Custom_key = null;
/**
* Set values for filter.
*
* @param array $values
* @param mixed $key
*/
public function __construct(array $values, $key)
{
$this->Custom_values = $values;
$this->Custom_key = $key;
}
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
*/
protected function selectItem(&$key, &$val): bool
{
$needle = $val[$this->Custom_key];
return in_array($needle, $this->Custom_values);
}
}

View File

@ -0,0 +1,32 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso3166\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
use Xentral\Components\I18n\Iso3166\Key;
/**
* Applies a filter to only select european countries.
*
* @see Custom
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class Europe extends Custom implements DataFilterInterface
{
/**
* Set predefined values.
*/
public function __construct()
{
parent::__construct(['150'], Key::REGION_CODE);
}
}

View File

@ -0,0 +1,75 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso3166;
/**
* Keys for the iso3166 list.
*
* @see \Xentral\Components\I18n\Iso3166
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
abstract class Key/* extends Ruga_Enum*/
{
/** Key: Alpha-2 code */
const ALPHA_2 = 'A2';
/** Key: Alpha-3 code */
const ALPHA_3 = 'A3';
/** Key: Numeric code */
const NUMERIC = 'NUM';
/** Key: Top Level Domain */
const TLD = 'TLD';
/** Key: Currency Code */
const CURRENCY_CODE = 'CURRENCY_CODE';
const TELEPHONE_CODE = 'TEL_CODE';
const REGION = 'REGION';
const REGION_CODE = 'REGION_CODE';
const SUBREGION = 'SUBREGION';
const SUBREGION_CODE = 'SUBREGION_CODE';
const INTERMEDIATEREGION = 'INTERMEDIATEREGION';
const INTERMEDIATEREGION_CODE = 'INTERMEDIATEREGION_CODE';
const NAME_eng = 'NAME_eng';
const NAME_fra = 'NAME_fra';
const NAME_deu = 'NAME_deu';
/** Key: Postal country name */
const POST = 'POST';
const DEFAULT = self::ALPHA_3;
protected static $fullnameMap = [
self::ALPHA_2 => 'ISO 3166 Alpha-2',
self::ALPHA_3 => 'ISO 3166 Alpha-3',
self::NUMERIC => 'ISO 3166 Numerisch',
self::TLD => 'Top Level Domain',
self::CURRENCY_CODE => 'Währung',
self::TELEPHONE_CODE => 'Landesvorwahl',
self::REGION => 'Region',
self::REGION_CODE => 'Region Code',
self::SUBREGION => 'Unter-Region',
self::SUBREGION_CODE => 'Unter-Region Code',
self::INTERMEDIATEREGION => 'Intermediate-Region',
self::INTERMEDIATEREGION_CODE => 'Intermediate-Region Code',
self::NAME_eng => 'Englische Bezeichnung',
self::NAME_fra => 'Französische Bezeichnung',
self::NAME_deu => 'Deutsche Bezeichnung',
self::POST => 'Landesbezeichung Postadresse',
];
}

View File

@ -0,0 +1,32 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso3166;
/**
* Names for the iso3166 list.
*
* @see \Xentral\Components\I18n\Iso3166
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
abstract class Name/* extends Ruga_Enum */
{
/** Englisch */
const ENG = 'NAME_eng';
/** Französisch */
const FRA = 'NAME_fra';
/** Deutsch */
const DEU = 'NAME_deu';
protected static $fullnameMap = [
self::ENG => 'Englische Bezeichnung',
self::FRA => 'Französische Bezeichnung',
self::DEU => 'Deutsche Bezeichnung',
];
}

View File

@ -0,0 +1,73 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n;
use Xentral\Components\I18n\Dataaccess\DataProvider;
use Xentral\Components\I18n\Dataaccess\Exception\OutOfRangeException;
/**
* Codes for the Representation of Names of Languages - ISO 639.
* Loads the data and holds the filtered (if desired) list.
*
* @see https://www.iso.org/iso-639-language-codes.html
* @see DataProvider
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class Iso639 extends DataProvider
{
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataProvider::getOriginalData()
*/
protected function getOriginalData(): array
{
return include(__DIR__ . '/data/Iso639data.php');
}
/**
* Returns the field $desiredName from the record $id.
*
* @param mixed $id
* @param string $desiredName
* @param null $default
*
* @return string
*/
public function find($id, $desiredName, $default = null): string
{
$id = strtolower($id);
try {
return $this->getString($id, $desiredName);
} catch (OutOfRangeException $e) {
try {
return (new \Xentral\Components\I18n\Iso639(
(new \Xentral\Components\I18n\Iso639\Filter\All())
->then(new \Xentral\Components\I18n\Iso639\Filter\ChangeKey(\Xentral\Components\I18n\Iso639\Key::ALPHA_2))
))->getString($id, $desiredName);
} catch (OutOfRangeException $e) {
try {
$id = strtoupper($id);
return (new \Xentral\Components\I18n\Iso639(
(new \Xentral\Components\I18n\Iso639\Filter\All())
->then(new \Xentral\Components\I18n\Iso639\Filter\ChangeKey(\Xentral\Components\I18n\Iso639\Key::ONELETTER))
))->getString($id, $desiredName);
} catch (OutOfRangeException $e) {
if ($default === null) {
throw $e;
} else {
return $this->getString($default, $desiredName);
}
}
}
}
}
}

View File

@ -0,0 +1,32 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso639\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
/**
* This filter returns all records from the data set (aka dummy filter).
*
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class All extends DataFilter implements DataFilterInterface
{
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
*/
function selectItem(&$key, &$val): bool
{
return true;
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso639\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
use Xentral\Components\I18n\Iso639\Key;
/**
* Applies a filter to only select central european countries.
*
* @see Custom
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class CentralEurope extends Custom implements DataFilterInterface
{
/**
* Countries in Europe.
*
* @var array
*/
const CentralEurope_Languages = ['deu', 'fra', 'ita', 'roh', 'spa', 'por', 'eng'];
/**
* Set predefined values.
*/
public function __construct()
{
parent::__construct(static::CentralEurope_Languages, Key::ALPHA_3);
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso639\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
use Xentral\Components\I18n\Dataaccess\DataFilter;
/**
* This filter can be used to change the main key
* of the data set.
*
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class ChangeKey extends DataFilter implements DataFilterInterface
{
/**
* New key to use for the data set.
*
* @var string
*/
private $ChangeKey_key = null;
/**
* Initialize filter and set the new key.
*
* @param mixed $key
*/
public function __construct($key)
{
$this->ChangeKey_key = $key;
}
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
*/
protected function selectItem(&$key, &$val): bool
{
$key = $val[$this->ChangeKey_key] ?? null;
return true;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso639\Filter;
use Xentral\Components\I18n\Dataaccess\DataFilter;
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
/**
* Apply a custom filter to the data set.
*
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
class Custom extends DataFilter implements DataFilterInterface
{
/**
* Array of wanted values.
*
* @var array
*/
private $Custom_values = null;
/**
* Key to check for the values in $this->Custom_values.
*
* @var string
*/
private $Custom_key = null;
/**
* Set values for filter.
*
* @param array $values
* @param mixed $key
*/
public function __construct(array $values, $key)
{
$this->Custom_values = $values;
$this->Custom_key = $key;
}
/**
* {@inheritDoc}
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
*/
protected function selectItem(&$key, &$val): bool
{
$needle = $val[$this->Custom_key];
return in_array($needle, $this->Custom_values);
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso639;
/**
* Keys for the iso639 list.
*
* @see \Xentral\Components\I18n\Iso639
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
abstract class Key/* extends Ruga_Enum*/
{
/** Key: Alpha-2 code */
const ALPHA_2 = '639-1';
const ISO639_1 = '639-1';
/** Key: Alpha-3 code */
const ALPHA_3 = '639-2';
const ISO639_2 = '639-2';
/** Key: Top Level Domain */
const ONELETTER = '1L';
/** Key: Name */
const NAME_eng = 'NAME_eng';
const NAME_fra = 'NAME_fra';
const NAME_deu = 'NAME_deu';
const DEFAULT = self::ALPHA_3;
protected static $fullnameMap = [
self::ALPHA_2 => 'ISO 639 Alpha-2',
self::ALPHA_3 => 'ISO 639 Alpha-3',
self::ONELETTER => 'ISO 639 Alpha-1',
self::NAME_eng => 'Englische Bezeichnung',
self::NAME_fra => 'Französische Bezeichnung',
self::NAME_deu => 'Deutsche Bezeichnung',
];
}

View File

@ -0,0 +1,33 @@
<?php
/**
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n\Iso639;
/**
* Names for the iso639 list.
*
* @see \Xentral\Components\I18n\Iso639
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
abstract class Name/* extends Ruga_Enum */
{
/** Englisch */
const ENG = 'NAME_eng';
/** Französisch */
const FRA = 'NAME_fra';
/** Deutsch */
const DEU = 'NAME_deu';
protected static $fullnameMap = [
self::ENG => 'Englische Bezeichnung',
self::FRA => 'Französische Bezeichnung',
self::DEU => 'Deutsche Bezeichnung',
];
}

View File

@ -0,0 +1,244 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n;
use Locale;
use Xentral\Components\Http\Request;
use Xentral\Components\Http\Session\Session;
use Xentral\Components\I18n\Exception\LanguageNotInitializedException;
use Xentral\Components\I18n\Exception\UnsupportedLocaleStringException;
/**
* Provides a central service for localization.
*
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
final class Localization implements LocalizationInterface
{
private array $config;
private ?Request $request;
private ?Session $session;
private array $usersettings = [];
private array $language = [];
private array $locale = [];
public function __construct(?Request $request, ?Session $session, array $usersettings = [], array $config = [])
{
$this->request = $request;
$this->session = $session;
$this->usersettings = $usersettings;
$this->config = $config;
$this->process();
}
public function process()
{
// Hardcoded defaults if config is not available
$localeDefault = $this->config[Localization::LOCALE_DEFAULT] ?? 'de_DE';
$localeAttrName = $this->config[Localization::LOCALE_ATTRIBUTE_NAME] ?? 'locale';
$langDefault = $this->config[Localization::LANGUAGE_DEFAULT] ?? 'deu';
$langAttrName = $this->config[Localization::LANGUAGE_ATTRIBUTE_NAME] ?? 'language';
$segmentName = 'i18n';
// Get the locale from the session, if available
if ($this->session && ($locale = $this->session->getValue($segmentName, $localeAttrName))) {
} else {
// Get locale from request, fallback to the user's browser preference
if ($this->request) {
$locale = $this->request->attributes->get(
$localeAttrName,
Locale::acceptFromHttp(
$this->request->getHeader('Accept-Language', $localeDefault)
) ?? $localeDefault
);
} else {
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? $localeDefault);
}
}
// Get locale from user
// This overrides all previous attempts to find a locale
if (array_key_exists('locale', $this->usersettings)) {
$locale = $this->usersettings['locale'];
}
// Get locale from query string
// This overrides all previous attempts to find a locale
if ($this->request) {
$locale = $this->request->getParam($localeAttrName, $locale ?? $localeDefault);
} else {
$locale = $_GET[$localeAttrName] ?? $locale ?? $localeDefault;
}
// Get the language from the session, if available
if ($this->session && ($language = $this->session->getValue($segmentName, $langAttrName))) {
} else {
// Get language from request, fallback to the current locale
if ($this->request) {
$language = $this->request->attributes->get($langAttrName, Locale::getPrimaryLanguage($locale));
} else {
$language = Locale::getPrimaryLanguage($locale);
}
}
// Get language from user
// This overrides all previous attempts to find a language
if (array_key_exists('language', $this->usersettings)) {
$language = $this->usersettings['language'];
}
// Get language from query string
// This overrides all previous attempts to find a language
if ($this->request) {
$language = $this->request->getParam($langAttrName, $language ?? $langDefault);
} else {
$language = $language ?? $langDefault;
}
// Check language against the data from Iso639 (and normalize to 3-letter-code)
$language = (new Iso639())->find($language, Iso639\Key::DEFAULT, $langDefault);
// Store the locale and language to the LocalizationInterface
$this->setLanguage($language);
$this->setLocale($locale);
// Store the locale and language to the session
if ($this->session) {
$this->session->setValue($segmentName, $localeAttrName, $locale);
$this->session->setValue($segmentName, $langAttrName, $language);
}
// Store the locale and language as a request attribute
if ($this->request) {
$this->request->attributes->set($localeAttrName, $locale);
$this->request->attributes->set($langAttrName, $language);
}
// Set the default locale
Locale::setDefault($locale);
// error_log(self::class . ": {$locale}");
}
/**
* Set the language.
*
* @param string $language
*/
public function setLanguage(string $language)
{
$this->language[Iso639\Key::DEFAULT] = (new \Xentral\Components\I18n\Iso639())->find(
$language,
Iso639\Key::DEFAULT
);
}
/**
* Return the language string as defined by $key.
*
* @param string|null $key A constant from Iso639\Key
*
* @return string
*/
public function getLanguage(string $key = null): string
{
if (!$key) {
$key = Iso639\Key::DEFAULT;
}
if (!($this->language[$key] ?? null)) {
if (!($this->language[Iso639\Key::DEFAULT] ?? null)) {
throw new LanguageNotInitializedException("Language is not set for key '" . Iso639\Key::DEFAULT . "'");
}
$this->language[$key] = (new \Xentral\Components\I18n\Iso639())->find(
$this->language[Iso639\Key::DEFAULT],
$key
);
}
return $this->language[$key];
}
/**
* Set the locale.
*
* @param string $locale
*/
public function setLocale(string $locale)
{
$parsedLocale = Locale::parseLocale($locale);
$locale = Locale::composeLocale([
'language' => $parsedLocale['language'],
'region' => $parsedLocale['region'],
]);
if(!$locale) throw new UnsupportedLocaleStringException("The given locale string '{$locale}' is not supported");
$this->locale[Iso3166\Key::DEFAULT] = $locale;
}
/**
* Return the locale string as defined by $key.
*
* @param string|null $key A constant from Iso3166\Key
*
* @return string
*/
public function getLocale(string $key = null): string
{
return $this->locale[Iso3166\Key::DEFAULT];
}
/**
* Return a new localization object using the given adresse array as source for language and region.
*
* @param array $adresse
*
* @return $this
*/
public function withAdresse(array $adresse): self
{
$localization = clone $this;
// Find language from address array or keep current language
if (!$lang = Bootstrap::findLanguage($adresse['sprache'])) {
$lang = Bootstrap::findLanguage($this->getLanguage());
}
if ($lang) {
$localization->setLanguage($lang[Iso639\Key::ALPHA_3]);
}
// Find region from address or keep current region
if (!$region = Bootstrap::findRegion($adresse['land'])) {
$parsedLocale = Locale::parseLocale($this->getLocale());
$region = Bootstrap::findRegion($parsedLocale['region']);
}
if ($lang && $region) {
$localization->setLocale("{$lang[Iso639\Key::ALPHA_2]}_{$region[Iso3166\Key::ALPHA_2]}");
}
return $localization;
}
}

View File

@ -0,0 +1,62 @@
<?php
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Xentral\Components\I18n;
/**
* Interface LocalizationInterface
*
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
*/
interface LocalizationInterface
{
const LOCALE_DEFAULT = 'locale_default';
const LOCALE_ATTRIBUTE_NAME = 'locale_attr_name';
const LANGUAGE_DEFAULT = 'language_default';
const LANGUAGE_ATTRIBUTE_NAME = 'language_attr_name';
/**
* Set the language.
*
* @param string $language
*/
public function setLanguage(string $language);
/**
* Return the language string as defined by $key.
*
* @param string|null $key A constant from Iso639\Key
*
* @return string
*/
public function getLanguage(string $key = null): string;
/**
* Set the locale.
*
* @param string $locale
*/
public function setLocale(string $locale);
/**
* Return the locale string as defined by $key.
*
* @param string|null $key A constant from Iso3166\Key
*
* @return string
*/
public function getLocale(string $key = null): string;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,159 @@
<?php
/*
* Data extracted from https://www.iso.org/iso-639-language-codes.html
*/
return [
'aar' => [
'639-2' => 'aar',
'639-1' => 'aa',
'NAME_eng' => 'Afar',
'NAME_fra' => 'afar',
'NAME_deu' => 'Danakil-Sprache',
],
'abk' => [
'639-2' => 'abk',
'639-1' => 'ab',
'NAME_eng' => 'Abkhazian',
'NAME_fra' => 'abkhaze',
'NAME_deu' => 'Abchasisch',
],
'ace' => [
'639-2' => 'ace',
'639-1' => null,
'NAME_eng' => 'Achinese',
'NAME_fra' => 'aceh',
'NAME_deu' => 'Aceh-Sprache',
],
'ach' => [
'639-2' => 'ach',
'639-1' => null,
'NAME_eng' => 'Acoli',
'NAME_fra' => 'acoli',
'NAME_deu' => 'Acholi-Sprache',
],
'ada' => [
'639-2' => 'ada',
'639-1' => null,
'NAME_eng' => 'Adangme',
'NAME_fra' => 'adangme',
'NAME_deu' => 'Adangme-Sprache',
],
'ady' => [
'639-2' => 'ady',
'639-1' => null,
'NAME_eng' => 'Adyghe',
'NAME_fra' => 'adyghé',
'NAME_deu' => 'Adygisch',
],
'afa' => [
'639-2' => 'afa',
'639-1' => null,
'NAME_eng' => 'Afro-Asiatic languages',
'NAME_fra' => 'afro-asiatiques, langues',
'NAME_deu' => 'Hamitosemitische Sprachen (Andere)',
],
'afh' => [
'639-2' => 'afh',
'639-1' => null,
'NAME_eng' => 'Afrihili',
'NAME_fra' => 'afrihili',
'NAME_deu' => 'Afrihili',
],
'afr' => [
'639-2' => 'afr',
'639-1' => 'af',
'NAME_eng' => 'Afrikaans',
'NAME_fra' => 'afrikaans',
'NAME_deu' => 'Afrikaans',
],
'ain' => [
'639-2' => 'ain',
'639-1' => null,
'NAME_eng' => 'Ainu',
'NAME_fra' => 'aïnou',
'NAME_deu' => 'Ainu-Sprache',
],
'aka' => [
'639-2' => 'aka',
'639-1' => 'ak',
'NAME_eng' => 'Akan',
'NAME_fra' => 'akan',
'NAME_deu' => 'Akan-Sprache',
],
'akk' => [
'639-2' => 'akk',
'639-1' => null,
'NAME_eng' => 'Akkadian',
'NAME_fra' => 'akkadien',
'NAME_deu' => 'Akkadisch',
],
'sqi' => [
'639-2' => 'sqi',
'639-1' => 'sq',
'NAME_eng' => 'Albanian',
'NAME_fra' => 'albanais',
'NAME_deu' => 'Albanisch',
'639-2-B' => 'alb',
],
'deu' => [
'639-2' => 'deu',
'639-1' => 'de',
'NAME_eng' => 'German',
'NAME_fra' => 'allemand',
'NAME_deu' => 'Deutsch',
'639-2-B' => 'ger',
'1L' => 'D',
],
'eng' => [
'639-2' => 'eng',
'639-1' => 'en',
'NAME_eng' => 'English',
'NAME_fra' => 'anglais',
'NAME_deu' => 'Englisch',
'1L' => 'E',
],
'fra' => [
'639-2' => 'fra',
'639-1' => 'fr',
'NAME_eng' => 'French',
'NAME_fra' => 'français',
'NAME_deu' => 'Französisch',
'639-2-B' => 'fre',
'1L' => 'F',
],
'ita' => [
'639-2' => 'ita',
'639-1' => 'it',
'NAME_eng' => 'Italian',
'NAME_fra' => 'italien',
'NAME_deu' => 'Italienisch',
'1L' => 'I',
],
'spa' => [
'639-2' => 'spa',
'639-1' => 'es',
'NAME_eng' => 'Spanish',
'NAME_fra' => 'espagnol',
'NAME_deu' => 'Spanisch',
],
'por' => [
'639-2' => 'por',
'639-1' => 'pt',
'NAME_eng' => 'Portuguese',
'NAME_fra' => 'portugais',
'NAME_deu' => 'Portugiesisch',
],
'roh' => [
'639-2' => 'roh',
'639-1' => 'rm',
'NAME_eng' => 'Romansh',
'NAME_fra' => 'romanche',
'NAME_deu' => 'Rätoromanisch',
],
'dut' => ['639-2' => 'dut', '639-1' => 'nl', 'NAME_eng' => 'Dutch', 'NAME_fra' => 'néerlandais', 'NAME_deu' => 'Niederländisch', 'NAME_deu_alt' => 'Holländisch'],
'swe' => ['639-2' => 'swe', '639-1' => 'sv', 'NAME_eng' => 'Swedish', 'NAME_fra' => 'suédois', 'NAME_deu' => 'Schwedisch'],
'dan' => ['639-2' => 'dan', '639-1' => 'da', 'NAME_eng' => 'Danish', 'NAME_fra' => 'danois', 'NAME_deu' => 'Dänisch'],
'nor' => ['639-2' => 'nor', '639-1' => 'no', 'NAME_eng' => 'Norwegian', 'NAME_fra' => 'norvégien', 'NAME_deu' => 'Norwegisch'],
];

View File

@ -97,7 +97,11 @@
<td>{|Sprache|}:</td>
<td><select name="sprachebevorzugen" id="sprachebevorzugen">[SPRACHEBEVORZUGEN]</select></td>
</tr>
<tr>
<tr>
<td>{|Sprache und Region|}:</td>
<td><input type="text" name="locale" id="locale" value="[LOCALE]" size="40" disabled="disabled"></td>
</tr>
<tr>
<td>{|Eigene Kalenderfarbe|}:</td>
<td><input type="text" name="defaultcolor" id="defaultcolor" value="[DEFAULTCOLOR]" size="80"></td>
<td></td>

View File

@ -1711,6 +1711,13 @@ $this->app->Tpl->Add('TODOFORUSER',"<tr><td width=\"90%\">".$tmp[$i]['aufgabe'].
$this->app->Tpl->Set('STARTSEITE', $settings['startseite']);
$this->app->Tpl->Set('DEFAULTCOLOR', $settings['defaultcolor']);
$this->app->Tpl->Set('SPRACHEBEVORZUGEN', $this->languageSelectOptions($settings['sprachebevorzugen']));
/** @var \Xentral\Components\I18n\Localization $localization */
if($localization=$this->app->Container->get('Localization')) {
$this->app->Tpl->Set('LOCALE', $localization->getLocale());
} else {
$this->app->Tpl->Set('LOCALE', 'Fehler!');
}
if($settings['chat_popup']){
$this->app->Tpl->Set('CHAT_POPUP', ' checked="checked" ');

View File

@ -149,11 +149,12 @@ $(document).ready(function(){
<tr valign="top"><td>{|Liefersperre Grund|}:</td><td>[LIEFERSPERREGRUND][MSGLIEFERSPERREGRUND]</td></tr>
<tr><td colspan="2"><br></td></tr>
<tr><td>{|Sprache f&uuml;r Belege|}:</td><td>[SPRACHE][MSGSPRACHE]</td></tr>
<tr><td>{|Sprache und Region|}:</td><td>[LOCALE][MSGLOCALE]</td></tr>
<tr><td>{|Kundenfreigabe|}:</td><td>[KUNDENFREIGABE][MSGKUNDENFREIGABE] </td></tr>
<tr><td colspan="2"><br></td></tr>
<tr><td>{|Folgebest&auml;tigungsperre|}:</td><td>[FOLGEBESTAETIGUNGSPERRE][MSGFOLGEBESTAETIGUNGSPERRE]</td></tr>
<tr><td>{|Trackingmailsperre|}:</td><td>[TRACKINGSPERRE][MSGTRACKINGSPERRE]</td></tr>
<tr><td>{|Folgebest&auml;tigungsperre|}:</td><td>[FOLGEBESTAETIGUNGSPERRE][MSGFOLGEBESTAETIGUNGSPERRE]</td></tr>
<tr><td>{|Trackingmailsperre|}:</td><td>[TRACKINGSPERRE][MSGTRACKINGSPERRE]</td></tr>
<tr><td>{|Marketingsperre|}:</td><td>[MARKETINGSPERRE][MSGMARKETINGSPERRE]</td></tr>
<tr><td>{|Lead|}:</td><td>[LEAD][MSGLEAD]</td></tr>

View File

@ -1,4 +1,7 @@
<?php
use Xentral\Components\Database\Database;
include ("_gen/widget.gen.adresse.php");
class WidgetAdresse extends WidgetGenAdresse
@ -284,7 +287,20 @@ class WidgetAdresse extends WidgetGenAdresse
$field = new HTMLSelect("sprache",0,"sprache",false,false,"1");
$field->AddOptionsSimpleArray($sprachenOptions);
$this->form->NewField($field);
/** @var \Xentral\Components\I18n\Localization $localization */
$localization=$this->app->Container->get('Localization');
/** @var Database $db */
$db = $this->app->Container->get('Database');
$adresse = $db->fetchRow(
$db->select()->cols(['*'])->from('adresse')->where('id=:id'),
['id' => $id]
);
$localization=$localization->withAdresse($adresse);
$field = new HTMLInput("locale","text",$localization->getLocale(), size: '10', disabled: 'disabled');
$this->form->NewField($field);
$field = new HTMLInput("vorname","hidden","");
$this->form->NewField($field);