Improved lang handling

This commit is contained in:
Sergio Brighenti 2019-08-20 14:56:41 +02:00
parent d7913430fa
commit 5af7567b1a
12 changed files with 934 additions and 198 deletions

View file

@ -1,6 +1,9 @@
## v2.6
+ Added support to use AWS S3, Google Cloud Storage, Dropbox and FTP(s) accounts as storage location.
+ Fixed missing icon.
+ Fixed missing icon.
+ Added german and norwegian translations from [Weblate](https://hosted.weblate.org/projects/xbackbone/xbackbone/).
+ Improved lang detection.
+ Added ability to force system language.
## v2.5.3
+ Fixed bad css loading on Firefox (#35).

View file

@ -38,6 +38,7 @@ class AdminController extends Controller
'totalSize' => humanFileSize($totalSize),
'post_max_size' => ini_get('post_max_size'),
'upload_max_filesize' => ini_get('upload_max_filesize'),
'installed_lang' => $this->lang->getList(),
]);
}
@ -65,4 +66,26 @@ class AdminController extends Controller
return redirect($response, 'system');
}
/**
* @param Request $request
* @param Response $response
* @return Response
*/
public function applyLang(Request $request, Response $response): Response
{
$config = require BASE_DIR . 'config.php';
if ($request->getParam('lang') !== 'auto') {
$config['lang'] = $request->getParam('lang');
} else {
unset($config['lang']);
}
file_put_contents(BASE_DIR . 'config.php', '<?php' . PHP_EOL . 'return ' . var_export($config, true) . ';');
$this->session->alert(lang('lang_set', [$request->getParam('lang')]));
return redirect($response, 'system');
}
}

View file

@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Database\DB;
use App\Web\Lang;
use App\Web\Session;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\Filesystem;
@ -15,6 +16,7 @@ use Slim\Container;
* @property DB|null database
* @property Logger|null logger
* @property Filesystem|null storage
* @property Lang lang
*/
abstract class Controller
{

View file

@ -41,12 +41,7 @@ class Lang
*/
public static function build($lang = self::DEFAULT_LANG, $langPath = null): Lang
{
if (strlen($lang) !== 2) {
self::$lang = strtolower(substr($lang, 0, 2));
} else {
self::$lang = $lang;
}
self::$lang = $lang;
if ($langPath !== null) {
self::$langPath = $langPath;
@ -63,7 +58,7 @@ class Lang
*/
public static function recognize()
{
return substr(@$_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
return locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE']);
}
/**
@ -74,6 +69,27 @@ class Lang
return self::$lang;
}
/**
* @return array
*/
public static function getList()
{
$languages = [];
$default = count(include self::$langPath . self::DEFAULT_LANG . '.lang.php') - 1;
foreach (glob(self::$langPath . '*.lang.php') as $file) {
$dict = include $file;
$count = count($dict) - 1;
$prepend = "[{$count}/{$default}] ";
$languages[str_replace('.lang.php', '', basename($file))] = $prepend . $dict['lang'];
}
return $languages;
}
/**
* @param $key
@ -93,12 +109,16 @@ class Lang
*/
private function getString($key, $lang, $args): string
{
$redLang = strtolower(substr($lang, 0, 2));
if (array_key_exists($lang, $this->cache)) {
$transDict = $this->cache[$lang];
} elseif (file_exists(self::$langPath . $lang . '.lang.php')) {
$transDict = include self::$langPath . $lang . '.lang.php';
$this->cache[$lang] = $transDict;
} elseif (file_exists(self::$langPath . $redLang . '.lang.php')) {
$transDict = include self::$langPath . $redLang . '.lang.php';
$this->cache[$lang] = $transDict;
} else {
$transDict = [];
}

View file

@ -11,6 +11,8 @@ $app->group('', function () {
$this->get('/system/themes', \App\Controllers\ThemeController::class . ':getThemes')->setName('theme');
$this->post('/system/theme/apply', \App\Controllers\ThemeController::class . ':applyTheme')->setName('theme.apply');
$this->post('/system/lang/apply', \App\Controllers\AdminController::class . ':applyLang')->setName('lang.apply');
$this->post('/system/upgrade', \App\Controllers\UpgradeController::class . ':upgrade')->setName('system.upgrade');
$this->get('/system/checkForUpdates', \App\Controllers\UpgradeController::class . ':checkForUpdates')->setName('system.checkForUpdates');

View file

@ -105,13 +105,13 @@ $container['storage'] = function ($container) use (&$config) {
return new Filesystem(new DropboxAdapter($client), ['case_sensitive' => false]);
case 'ftp':
return new Filesystem(new FtpAdapter([
'host' => $config['storage']['host'],
'username' => $config['storage']['username'],
'password' => $config['storage']['password'],
'port' => $config['storage']['port'],
'root' => $config['storage']['path'],
'passive' => $config['storage']['passive'],
'ssl' => $config['storage']['ssl'],
'host' => $config['storage']['host'],
'username' => $config['storage']['username'],
'password' => $config['storage']['password'],
'port' => $config['storage']['port'],
'root' => $config['storage']['path'],
'passive' => $config['storage']['passive'],
'ssl' => $config['storage']['ssl'],
'timeout' => 30,
]));
case 'google-cloud':
@ -125,7 +125,10 @@ $container['storage'] = function ($container) use (&$config) {
}
};
$container['lang'] = function ($container) {
$container['lang'] = function ($container) use (&$config) {
if (isset($config['lang'])) {
return Lang::build($config['lang'], BASE_DIR . 'resources/lang/');
}
return Lang::build(Lang::recognize(), BASE_DIR . 'resources/lang/');
};

View file

@ -10,13 +10,14 @@
"league/flysystem": "^1.0.45",
"monolog/monolog": "^1.23",
"intervention/image": "^2.4",
"league/flysystem-aws-s3-v3": "^1.0",
"spatie/flysystem-dropbox": "^1.0",
"superbalist/flysystem-google-storage": "^7.2",
"ext-intl": "*",
"ext-json": "*",
"ext-gd": "*",
"ext-pdo": "*",
"ext-zip": "*",
"league/flysystem-aws-s3-v3": "^1.0",
"spatie/flysystem-dropbox": "^1.0",
"superbalist/flysystem-google-storage": "^7.2"
"ext-zip": "*"
},
"autoload": {
"files": [

248
composer.lock generated
View file

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d2c8e7bde7729d78cef484491535c639",
"content-hash": "b00b4789eb0530c6eb3a5280dae29c86",
"packages": [
{
"name": "aws/aws-sdk-php",
"version": "3.99.2",
"version": "3.109.7",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "c3c2877ac7d17125631106c1ee3532e9bf33df53"
"reference": "e8d3416f9b1e21029fc0eb63df075e325c690187"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c3c2877ac7d17125631106c1ee3532e9bf33df53",
"reference": "c3c2877ac7d17125631106c1ee3532e9bf33df53",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e8d3416f9b1e21029fc0eb63df075e325c690187",
"reference": "e8d3416f9b1e21029fc0eb63df075e325c690187",
"shasum": ""
},
"require": {
@ -87,7 +87,7 @@
"s3",
"sdk"
],
"time": "2019-06-05T18:07:37+00:00"
"time": "2019-08-19T18:08:45+00:00"
},
{
"name": "container-interop/container-interop",
@ -168,16 +168,16 @@
},
{
"name": "google/auth",
"version": "v1.5.1",
"version": "v1.5.2",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-auth-library-php.git",
"reference": "0f75e20e7392e863f5550ed2c2d3d50af21710fb"
"reference": "2ee962e5df3e9427fda859f1b0515d6d62c4afa5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/0f75e20e7392e863f5550ed2c2d3d50af21710fb",
"reference": "0f75e20e7392e863f5550ed2c2d3d50af21710fb",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/2ee962e5df3e9427fda859f1b0515d6d62c4afa5",
"reference": "2ee962e5df3e9427fda859f1b0515d6d62c4afa5",
"shasum": ""
},
"require": {
@ -215,20 +215,20 @@
"google",
"oauth2"
],
"time": "2019-04-16T18:48:28+00:00"
"time": "2019-07-22T21:01:31+00:00"
},
{
"name": "google/cloud-core",
"version": "v1.28.0",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-cloud-php-core.git",
"reference": "d32db261499d28268f9ed97834e7aca829df5b53"
"reference": "c7b8890cdab3761e341ecf8f5d7c141aa616978f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-cloud-php-core/zipball/d32db261499d28268f9ed97834e7aca829df5b53",
"reference": "d32db261499d28268f9ed97834e7aca829df5b53",
"url": "https://api.github.com/repos/googleapis/google-cloud-php-core/zipball/c7b8890cdab3761e341ecf8f5d7c141aa616978f",
"reference": "c7b8890cdab3761e341ecf8f5d7c141aa616978f",
"shasum": ""
},
"require": {
@ -243,7 +243,8 @@
},
"require-dev": {
"erusev/parsedown": "^1.6",
"google/gax": "^1.0",
"google/common-protos": "^1.0",
"google/gax": "^1.1",
"opis/closure": "^3",
"phpdocumentor/reflection": "^3.0",
"phpunit/phpunit": "^4.8|^5.0",
@ -275,24 +276,25 @@
"Apache-2.0"
],
"description": "Google Cloud PHP shared dependency, providing functionality useful to all components.",
"time": "2019-04-16T20:44:33+00:00"
"time": "2019-08-07T20:57:43+00:00"
},
{
"name": "google/cloud-storage",
"version": "v1.12.1",
"version": "v1.14.0",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-cloud-php-storage.git",
"reference": "a252e2012ea875e873b6d146159e54edb8fa4544"
"reference": "7315239270318e618f025791b20ac8cc2586ccf0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-cloud-php-storage/zipball/a252e2012ea875e873b6d146159e54edb8fa4544",
"reference": "a252e2012ea875e873b6d146159e54edb8fa4544",
"url": "https://api.github.com/repos/googleapis/google-cloud-php-storage/zipball/7315239270318e618f025791b20ac8cc2586ccf0",
"reference": "7315239270318e618f025791b20ac8cc2586ccf0",
"shasum": ""
},
"require": {
"google/cloud-core": "^1.28"
"google/cloud-core": "^1.31",
"google/crc32": "^0.1.0"
},
"require-dev": {
"erusev/parsedown": "^1.6",
@ -325,7 +327,103 @@
"Apache-2.0"
],
"description": "Cloud Storage Client for PHP",
"time": "2019-05-02T16:40:15+00:00"
"time": "2019-08-07T20:57:43+00:00"
},
{
"name": "google/crc32",
"version": "v0.1.0",
"source": {
"type": "git",
"url": "https://github.com/google/php-crc32.git",
"reference": "a8525f0dea6fca1893e1bae2f6e804c5f7d007fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/google/php-crc32/zipball/a8525f0dea6fca1893e1bae2f6e804c5f7d007fb",
"reference": "a8525f0dea6fca1893e1bae2f6e804c5f7d007fb",
"shasum": ""
},
"require": {
"php": ">=5.4"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^1.13 || v2.14.2",
"paragonie/random_compat": ">=2",
"phpunit/phpunit": "^4"
},
"type": "library",
"autoload": {
"psr-4": {
"Google\\CRC32\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Andrew Brampton",
"email": "bramp@google.com"
}
],
"description": "Various CRC32 implementations",
"homepage": "https://github.com/google/php-crc32",
"time": "2019-05-09T06:24:58+00:00"
},
{
"name": "graham-campbell/guzzle-factory",
"version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/GrahamCampbell/Guzzle-Factory.git",
"reference": "5953039c541533647110f8c8f48cbc428d51beb1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/GrahamCampbell/Guzzle-Factory/zipball/5953039c541533647110f8c8f48cbc428d51beb1",
"reference": "5953039c541533647110f8c8f48cbc428d51beb1",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.2",
"php": "^7.0"
},
"require-dev": {
"graham-campbell/analyzer": "^2.1",
"phpunit/phpunit": "^6.5|^7.0|^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"GrahamCampbell\\GuzzleFactory\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "graham@alt-three.com"
}
],
"description": "Provides A Simple Guzzle Factory With Good Defaults",
"keywords": [
"Graham Campbell",
"GrahamCampbell",
"Guzzle",
"Guzzle Factory",
"Guzzle-Factory",
"http"
],
"time": "2019-06-30T12:48:08+00:00"
},
{
"name": "guzzlehttp/guzzle",
@ -445,33 +543,37 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.5.2",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "9f83dded91781a01c63574e387eaa769be769115"
"reference": "239400de7a173fe9901b9ac7c06497751f00727a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
"reference": "9f83dded91781a01c63574e387eaa769be769115",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5"
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"ext-zlib": "*",
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"suggest": {
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.5-dev"
"dev-master": "1.6-dev"
}
},
"autoload": {
@ -508,7 +610,7 @@
"uri",
"url"
],
"time": "2018-12-04T20:46:45+00:00"
"time": "2019-07-01T23:21:34+00:00"
},
{
"name": "intervention/image",
@ -1134,24 +1236,24 @@
},
{
"name": "ralouphie/getallheaders",
"version": "2.0.5",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa"
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.3"
"php": ">=5.6"
},
"require-dev": {
"phpunit/phpunit": "~3.7.0",
"satooshi/php-coveralls": ">=1.0"
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
@ -1170,7 +1272,7 @@
}
],
"description": "A polyfill for getallheaders.",
"time": "2016-02-11T07:05:27+00:00"
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "rize/uri-template",
@ -1340,19 +1442,20 @@
},
{
"name": "spatie/dropbox-api",
"version": "1.9.0",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/dropbox-api.git",
"reference": "72a7c833ada88b8eb0af7cc1c561e02b0c9a5987"
"reference": "47c6a14bcdc639ba90f86f98b2ada38ac9cc8e30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/dropbox-api/zipball/72a7c833ada88b8eb0af7cc1c561e02b0c9a5987",
"reference": "72a7c833ada88b8eb0af7cc1c561e02b0c9a5987",
"url": "https://api.github.com/repos/spatie/dropbox-api/zipball/47c6a14bcdc639ba90f86f98b2ada38ac9cc8e30",
"reference": "47c6a14bcdc639ba90f86f98b2ada38ac9cc8e30",
"shasum": ""
},
"require": {
"graham-campbell/guzzle-factory": "^3.0",
"guzzlehttp/guzzle": "^6.2",
"php": "^7.1"
},
@ -1372,15 +1475,15 @@
"authors": [
{
"name": "Freek Van der Herten",
"role": "Developer",
"email": "freek@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
"homepage": "https://spatie.be"
},
{
"name": "Alex Vanderbist",
"role": "Developer",
"email": "alex.vanderbist@gmail.com",
"homepage": "https://spatie.be",
"role": "Developer"
"homepage": "https://spatie.be"
}
],
"description": "A minimal implementation of Dropbox API v2",
@ -1392,7 +1495,7 @@
"spatie",
"v2"
],
"time": "2019-05-21T12:13:37+00:00"
"time": "2019-07-04T19:04:14+00:00"
},
{
"name": "spatie/flysystem-dropbox",
@ -1429,9 +1532,9 @@
"authors": [
{
"name": "Alex Vanderbist",
"role": "Developer",
"email": "alex.vanderbist@gmail.com",
"homepage": "https://spatie.be",
"role": "Developer"
"homepage": "https://spatie.be"
}
],
"description": "Flysystem Adapter for the Dropbox v2 API",
@ -1495,16 +1598,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.11.0",
"version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "82ebae02209c21113908c229e9883c419720738a"
"reference": "550ebaac289296ce228a706d0867afc34687e3f4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
"reference": "82ebae02209c21113908c229e9883c419720738a",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
"reference": "550ebaac289296ce228a706d0867afc34687e3f4",
"shasum": ""
},
"require": {
@ -1516,7 +1619,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.11-dev"
"dev-master": "1.12-dev"
}
},
"autoload": {
@ -1533,12 +1636,12 @@
],
"authors": [
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Gert de Pagter",
"email": "backendtea@gmail.com"
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
@ -1549,7 +1652,7 @@
"polyfill",
"portable"
],
"time": "2019-02-06T07:57:58+00:00"
"time": "2019-08-06T08:03:45+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@ -1612,16 +1715,16 @@
},
{
"name": "twig/twig",
"version": "v2.10.0",
"version": "v2.11.3",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "5240e21982885b76629552d83b4ebb6d41ccde6b"
"reference": "699ed2342557c88789a15402de5eb834dedd6792"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/5240e21982885b76629552d83b4ebb6d41ccde6b",
"reference": "5240e21982885b76629552d83b4ebb6d41ccde6b",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/699ed2342557c88789a15402de5eb834dedd6792",
"reference": "699ed2342557c88789a15402de5eb834dedd6792",
"shasum": ""
},
"require": {
@ -1632,12 +1735,12 @@
"require-dev": {
"psr/container": "^1.0",
"symfony/debug": "^2.7",
"symfony/phpunit-bridge": "^3.4.19|^4.1.8"
"symfony/phpunit-bridge": "^3.4.19|^4.1.8|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.10-dev"
"dev-master": "2.11-dev"
}
},
"autoload": {
@ -1655,19 +1758,19 @@
"authors": [
{
"name": "Fabien Potencier",
"role": "Lead Developer",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
"homepage": "http://fabien.potencier.org"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
"role": "Project Founder",
"email": "armin.ronacher@active-4.com"
},
{
"name": "Twig Team",
"homepage": "https://twig.symfony.com/contributors",
"role": "Contributors"
"role": "Contributors",
"homepage": "https://twig.symfony.com/contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
@ -1675,7 +1778,7 @@
"keywords": [
"templating"
],
"time": "2019-05-14T12:03:52+00:00"
"time": "2019-06-18T15:37:11+00:00"
}
],
"packages-dev": [
@ -2768,6 +2871,7 @@
"prefer-lowest": false,
"platform": {
"php": ">=7.1",
"ext-intl": "*",
"ext-json": "*",
"ext-gd": "*",
"ext-pdo": "*",

View file

@ -260,6 +260,14 @@ $app->post('/', function (Request $request, Response $response) use (&$config) {
}
}
// if from older installations with no support of other than local driver
// update the config
if ($installed && isset($config['storage_dir'])) {
$config['storage']['driver'] = 'local';
$config['storage']['path'] = $config['storage_dir'];
unset($config['storage_dir']);
}
// Build the dns string and run the migrations
try {
@ -282,7 +290,7 @@ $app->post('/', function (Request $request, Response $response) use (&$config) {
cleanDirectory(__DIR__ . '/../resources/cache');
cleanDirectory(__DIR__ . '/../resources/sessions');
//removeDirectory(__DIR__ . '/../install');
removeDirectory(__DIR__ . '/../install');
// if is upgrading and existing installation, put it out maintenance
if ($installed) {

746
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
return [
'lang' => 'English',
'enforce_language' => 'Enforce language',
'yes' => 'Yes',
'no' => 'No',
'send' => 'Send',
@ -95,4 +96,10 @@ return [
'updates' => 'Updates',
'maintenance_in_progress' => 'Platform under maintenance, try again later...',
'cancel' => 'Cancel',
'auto_set' => 'Set automatically',
'translated_strings' => 'translated strings',
'total_strings' => 'total strings',
'lang_name' => 'language name',
'default_lang_behavior' => 'By default, it XBackbone will try to match the browser language (fallback is english).',
'lang_set' => 'System language enforced to "%s"',
];

View file

@ -75,8 +75,33 @@
</form>
</div>
</div>
<div class="card shadow-sm mb-3">
<div class="card-header"><i class="fas fa-language fa-fw"></i> {{ lang('enforce_language') }}</div>
<div class="card-body">
<form method="post" action="{{ route('lang.apply') }}">
<div class="form-group row">
<div class="col-sm-12">
<select class="form-control" id="lang" name="lang">
<option value="auto" selected>({{ lang('auto_set') }})</option>
{% for lang, name in installed_lang %}
<option value="{{ lang }}">{{ name }}</option>
{% endfor %}
</select>
<small>[{{ lang('translated_strings') }} / {{ lang('total_strings') }}] {{ lang('lang_name') }}. {{ lang('default_lang_behavior') }}</small>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<button type="submit" class="btn btn-outline-success" id="lang-apply">
<i class="fas fa-save fa-fw"></i> {{ lang('apply') }}
</button>
</div>
</div>
</form>
</div>
</div>
<div class="card shadow-sm">
<div class="card-header"><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('updates') }} <b>[BETA]</b></div>
<div class="card-header"><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('updates') }} <b>[BETA]</b> <span class="float-right">v{{ PLATFORM_VERSION }}</span></div>
<div class="card-body">
<div class="row">
<div class="col">