mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Localization class, and other improvements
Language file format will almost certainly change
This commit is contained in:
parent
4639dd1c46
commit
db0bd18663
10 changed files with 253 additions and 9 deletions
|
@ -3,6 +3,7 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\NewsSync;
|
namespace JKingWeb\NewsSync;
|
||||||
|
|
||||||
const BASE = __DIR__.DIRECTORY_SEPARATOR;
|
const BASE = __DIR__.DIRECTORY_SEPARATOR;
|
||||||
|
const NS_BASE = __NAMESPACE__."\\";
|
||||||
|
|
||||||
spl_autoload_register(function ($class) {
|
spl_autoload_register(function ($class) {
|
||||||
if($class=="SimplePie") return;
|
if($class=="SimplePie") return;
|
||||||
|
|
8
locale/en.php
Normal file
8
locale/en.php
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
$string[] = [
|
||||||
|
"Exception.JKingWeb/NewsSync/Lang/Exception.defaultFileMissing" => "Default language file \"{0}\" missing",
|
||||||
|
"Exception.JKingWeb/NewsSync/Lang/Exception.fileMissing" => "Language file \"{0}\" is not available",
|
||||||
|
"Exception.JKingWeb/NewsSync/Lang/Exception.fileUnreadable" => "Insufficient permissions to read language file \"{0}\"",
|
||||||
|
"Exception.JKingWeb/NewsSync/Lang/Exception.fileCorrupt" => "Language file \"{0}\" is corrupt or does not conform to expected format",
|
||||||
|
"Exception.JKingWeb/NewsSync/Lang/Exception.stringMissing" => "Message string \"{msgID}\" missing from all loaded language files ({fileList})",
|
||||||
|
];
|
10
vendor/JKingWeb/NewsSync/Auth/AuthInterface.php
vendored
Normal file
10
vendor/JKingWeb/NewsSync/Auth/AuthInterface.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Auth;
|
||||||
|
|
||||||
|
Interface AuthInterface {
|
||||||
|
public function __construct($conf, $db);
|
||||||
|
public function auth(): bool;
|
||||||
|
public function authHTTP(): bool;
|
||||||
|
public function isAdmin(): bool;
|
||||||
|
}
|
25
vendor/JKingWeb/NewsSync/Auth/DriverInternal.php
vendored
Normal file
25
vendor/JKingWeb/NewsSync/Auth/DriverInternal.php
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Auth;
|
||||||
|
use JKingWeb\NewsSync;
|
||||||
|
|
||||||
|
class Internal implements AuthInterface {
|
||||||
|
protected $conf;
|
||||||
|
protected $db;
|
||||||
|
|
||||||
|
public function __construct($conf, $db) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function auth(): bool {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authHTTP(): bool {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAdmin(): bool {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
32
vendor/JKingWeb/NewsSync/Conf.php
vendored
32
vendor/JKingWeb/NewsSync/Conf.php
vendored
|
@ -3,7 +3,9 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\NewsSync;
|
namespace JKingWeb\NewsSync;
|
||||||
|
|
||||||
class Conf {
|
class Conf {
|
||||||
public $dbType = "SQLite3";
|
public $lang = "en";
|
||||||
|
|
||||||
|
public $dbClass = NS_BASE."Db\\DriverSQLite3";
|
||||||
public $dbSQLite3PDO = false;
|
public $dbSQLite3PDO = false;
|
||||||
public $dbSQLite3File = BASE."newssync.db";
|
public $dbSQLite3File = BASE."newssync.db";
|
||||||
public $dbPostgreSQLPDO = false;
|
public $dbPostgreSQLPDO = false;
|
||||||
|
@ -20,29 +22,41 @@ class Conf {
|
||||||
public $dbMySQLPort = 3306;
|
public $dbMySQLPort = 3306;
|
||||||
public $dbMySQLDb = "newssync";
|
public $dbMySQLDb = "newssync";
|
||||||
|
|
||||||
|
public $authClass = NS_BASE."Auth\\DriverInternal";
|
||||||
|
public $authPreferHTTP = false;
|
||||||
|
public $authProvision = false;
|
||||||
|
|
||||||
public $simplepieCache = BASE.".cache";
|
public $simplepieCache = BASE.".cache";
|
||||||
|
|
||||||
|
|
||||||
function __construct(string $import_file = "") {
|
public function __construct(string $import_file = "") {
|
||||||
if($import_file != "") $this->import($import_file);
|
if($import_file != "") $this->import_file($import_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
function import(string $file): bool {
|
public function importFile(string $file): self {
|
||||||
|
if(!file_exists($file)) throw new Conf\Exception("fileMissing");
|
||||||
|
if(!is_readable($file)) throw new Conf\Exception("fileUnreadable");
|
||||||
$json = @file_get_contents($file);
|
$json = @file_get_contents($file);
|
||||||
if($json===false) return false;
|
if($json===false) throw new Conf\Exception("fileUnreadable");
|
||||||
|
return $this->import($json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function import(string $json): self {
|
||||||
|
if($json=="") throw new Conf\Exception("blank");
|
||||||
$json = json_decode($json, true);
|
$json = json_decode($json, true);
|
||||||
if(!is_array(json)) return false;
|
if(!is_array($json)) throw new Conf\Exception("corrupt");
|
||||||
foreach($json as $key => $value) {
|
foreach($json as $key => $value) {
|
||||||
$this->$$key = $value;
|
$this->$$key = $value;
|
||||||
}
|
}
|
||||||
return true;
|
return $this;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function export(string $file = ""): string {
|
public function export(string $file = ""): string {
|
||||||
return json_encode($this, JSON_PRETTY_PRINT);
|
return json_encode($this, JSON_PRETTY_PRINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
function __toString(): string {
|
public function __toString(): string {
|
||||||
return $this->export();
|
return $this->export();
|
||||||
}
|
}
|
||||||
}
|
}
|
6
vendor/JKingWeb/NewsSync/Conf/Exception.php
vendored
Normal file
6
vendor/JKingWeb/NewsSync/Conf/Exception.php
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Conf;
|
||||||
|
|
||||||
|
class Exception extends \JKingWeb\NewsSync\Exception {
|
||||||
|
}
|
32
vendor/JKingWeb/NewsSync/Exception.php
vendored
Normal file
32
vendor/JKingWeb/NewsSync/Exception.php
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync;
|
||||||
|
|
||||||
|
class Exception extends \Exception {
|
||||||
|
|
||||||
|
const CODES = [
|
||||||
|
"Exception.Misc" => 10000,
|
||||||
|
"Lang/Exception.defaultFileMissing" => 10101,
|
||||||
|
"Lang/Exception.fileMissing" => 10102,
|
||||||
|
"Lang/Exception.fileUnreadable" => 10103,
|
||||||
|
"Lang/Exception.fileCorrupt" => 10104,
|
||||||
|
"Lang/Exception.stringMissing" => 10105,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(string $msgID = "", $vars = null, Throwable $e = null) {
|
||||||
|
if($msgID=="") {
|
||||||
|
$msg = "";
|
||||||
|
$code = 0;
|
||||||
|
} else {
|
||||||
|
$msg = "Exception.".str_replace("\\","/",get_called_class()).".$msgID";
|
||||||
|
$msg = Lang::msg($msg, $vars);
|
||||||
|
$codeID = str_replace("\\", "/", str_replace(NS_BASE, "", get_called_class()));
|
||||||
|
if(!array_key_exists($codeID,self::CODES)) {
|
||||||
|
$code = 0;
|
||||||
|
} else {
|
||||||
|
$code = self::CODES[$codeID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent::__construct($msg, $code, $e);
|
||||||
|
}
|
||||||
|
}
|
126
vendor/JKingWeb/NewsSync/Lang.php
vendored
Normal file
126
vendor/JKingWeb/NewsSync/Lang.php
vendored
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync;
|
||||||
|
|
||||||
|
class Lang {
|
||||||
|
const PATH = BASE."locale".DIRECTORY_SEPARATOR;
|
||||||
|
const DEFAULT = "en";
|
||||||
|
const REQUIRED = [
|
||||||
|
"Exception.JKingWeb/NewsSync/Lang/Exception.defaultFileMissing" => "Default language file ({0}) missing",
|
||||||
|
"Exception.JKingWeb/NewsSync/Lang/Exception.stringMissing" => "Message string \"{msgID}\" missing from all loaded language files ({fileList})"
|
||||||
|
];
|
||||||
|
|
||||||
|
static protected $requirementsMet = false;
|
||||||
|
static protected $synched = false;
|
||||||
|
static protected $wanted = "fr";
|
||||||
|
static protected $locale = "";
|
||||||
|
static protected $loaded = [];
|
||||||
|
static protected $strings = self::REQUIRED;
|
||||||
|
|
||||||
|
protected function __construct() {}
|
||||||
|
|
||||||
|
static public function set(string $locale = "", bool $immediate = false): string {
|
||||||
|
if(!self::$requirementsMet) self::checkRequirements();
|
||||||
|
if($locale=="") $locale = self::DEFAULT;
|
||||||
|
if($locale==self::$wanted) return $locale;
|
||||||
|
$list = self::listFiles();
|
||||||
|
if(!in_array(self::DEFAULT, $list)) throw new Lang\Exception("defaultFileMissing", self::DEFAULT);
|
||||||
|
self::$wanted = self::match($locale, $list);
|
||||||
|
self::$synched = false;
|
||||||
|
if($immediate) self::load();
|
||||||
|
return self::$wanted;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function get(): string {
|
||||||
|
return (self::$locale=="") ? self::DEFAULT : self::$locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function msg(string $msgID, $vars = null): string {
|
||||||
|
// if we're trying to load the system default language and it fails, we have a chicken and egg problem, so we catch the exception and load no language file instead
|
||||||
|
if(!self::$synched) try {self::load();} catch(Lang\Exception $e) {
|
||||||
|
if(self::$wanted==self::DEFAULT) {
|
||||||
|
self::set();
|
||||||
|
self::load();
|
||||||
|
} else {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!array_key_exists($msgID, self::$strings)) throw new Lang\Exception("stringMissing", ['msgID' => $msgID, 'fileList' => implode(", ",self::$loaded)]);
|
||||||
|
// variables fed to MessageFormatter must be contained in array
|
||||||
|
if($vars !== null && !is_array($vars)) $vars = [$vars];
|
||||||
|
return \MessageFormatter::formatMessage(self::$locale, self::$strings[$msgID], $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function list(string $locale = ""): array {
|
||||||
|
$out = [];
|
||||||
|
$files = self::listFiles();
|
||||||
|
foreach($files as $tag) {
|
||||||
|
$out[$tag] = \Locale::getDisplayName($tag, ($locale=="") ? $tag : $locale);
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function match(string $locale, array $list = null): string {
|
||||||
|
if($list===null) $list = self::listFiles();
|
||||||
|
$default = (self::$locale=="") ? self::DEFAULT : self::$locale;
|
||||||
|
return \Locale::lookup($list,$locale, true, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected function checkRequirements(): bool {
|
||||||
|
if(!extension_loaded("intl")) throw new FatalException("The \"Intl\" extension is required, but not loaded");
|
||||||
|
self::$requirementsMet = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected function listFiles(string $path = self::PATH): array {
|
||||||
|
$out = glob($path."*.php");
|
||||||
|
return array_map(function($file) {
|
||||||
|
$file = substr($file,strrpos($file,DIRECTORY_SEPARATOR)+1);
|
||||||
|
return strtolower(substr($file,0,strrpos($file,".")));
|
||||||
|
},$out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected function load(): bool {
|
||||||
|
self::$synched = true;
|
||||||
|
if(!self::$requirementsMet) self::checkRequirements();
|
||||||
|
// if we've yet to request a locale, just load the fallback strings and return
|
||||||
|
if(self::$wanted=="") {
|
||||||
|
self::$strings = self::REQUIRED;
|
||||||
|
self::$locale = self::$wanted;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// decompose the requested locale from specific to general, building a list of files to load
|
||||||
|
$tags = \Locale::parseLocale(self::$wanted);
|
||||||
|
$files = [];
|
||||||
|
$loaded = [];
|
||||||
|
$strings = [];
|
||||||
|
while(sizeof($tags) > 0) {
|
||||||
|
$files[] = \Locale::composeLocale($tags);
|
||||||
|
$tag = array_pop($tags);
|
||||||
|
}
|
||||||
|
// include the default locale as the base if the most general locale requested is not the default
|
||||||
|
if($tag != self::DEFAULT) $files[] = self::DEFAULT;
|
||||||
|
// save the list of files to be loaded for later reference
|
||||||
|
$loaded = $files;
|
||||||
|
// reduce the list of files to be loaded to the minimum necessary (e.g. if we go from "fr" to "fr_ca", we don't need to load "fr" or "en")
|
||||||
|
$files = [];
|
||||||
|
foreach($loaded as $file) {
|
||||||
|
if($file==self::$locale) break;
|
||||||
|
$files[] = $file;
|
||||||
|
}
|
||||||
|
// if we need to load all files, start with the fallback strings
|
||||||
|
if($files==$loaded) $strings[] = self::REQUIRED;
|
||||||
|
// read files in reverse order
|
||||||
|
$files = array_reverse($files);
|
||||||
|
foreach($files as $file) {
|
||||||
|
if(!file_exists(self::PATH."$file.php")) throw new Lang\Exception("fileMissing", $file);
|
||||||
|
if(!is_readable(self::PATH."$file.php")) throw new Lang\Exception("fileUnreadable", $file);
|
||||||
|
if(!@include(self::PATH."$file.php")) throw new Lang\Exception("fileCorrupt", $file);
|
||||||
|
}
|
||||||
|
// apply the results and return
|
||||||
|
self::$strings = call_user_func_array("array_replace_recursive", $strings);
|
||||||
|
self::$loaded = $loaded;
|
||||||
|
self::$locale = self::$wanted;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
6
vendor/JKingWeb/NewsSync/Lang/Exception.php
vendored
Normal file
6
vendor/JKingWeb/NewsSync/Lang/Exception.php
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Lang;
|
||||||
|
|
||||||
|
class Exception extends \JKingWeb\NewsSync\Exception {
|
||||||
|
}
|
16
vendor/JKingWeb/NewsSync/RuntimeData.php
vendored
Normal file
16
vendor/JKingWeb/NewsSync/RuntimeData.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync;
|
||||||
|
|
||||||
|
class RuntimeData {
|
||||||
|
protected $conf;
|
||||||
|
protected $db;
|
||||||
|
protected $auth;
|
||||||
|
|
||||||
|
public function __construct(Conf $conf) {
|
||||||
|
Lang::set();
|
||||||
|
$this->conf = $conf;
|
||||||
|
//$this->db = new Database($this);
|
||||||
|
//$this->auth = new Authenticator($this);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue