Merge pull request #13531 from annando/language-detection

The language detection is now done in blocks
This commit is contained in:
Hypolite Petovan 2023-10-12 07:38:08 -04:00 committed by GitHub
commit 71ec402adc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 219 additions and 154 deletions

View file

@ -228,6 +228,7 @@ Called after the language detection. This can be used for alternative language d
- **text**: The text that is analyzed. - **text**: The text that is analyzed.
- **detected**: (input/output) Array of language codes detected in the related text. The array key is the language code, the array value the probability. - **detected**: (input/output) Array of language codes detected in the related text. The array key is the language code, the array value the probability.
- **uri-id**: The Uri-Id of the item. - **uri-id**: The Uri-Id of the item.
- **author-id**: The id of the author contact.
### addon_settings ### addon_settings
Called when generating the HTML for the addon settings page. Called when generating the HTML for the addon settings page.

View file

@ -28,9 +28,9 @@ Due to the large variety of operating systems and PHP platforms in existence we
### Requirements ### Requirements
* Apache with mod-rewrite enabled and "Options All" so you can use a local `.htaccess` file * Apache with mod-rewrite enabled and "Options All" so you can use a local `.htaccess` file
* PHP 7.3+ (PHP8 is not fully supported yet) * PHP 7.3+
* PHP *command line* access with register_argc_argv set to true in the php.ini file * PHP *command line* access with register_argc_argv set to true in the php.ini file
* Curl, GD, GMP, PDO, mbstrings, MySQLi, hash, xml, zip and OpenSSL extensions * Curl, GD, GMP, PDO, mbstrings, MySQLi, hash, xml, zip, IntlChar and OpenSSL extensions
* The POSIX module of PHP needs to be activated (e.g. [RHEL, CentOS](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) have disabled it) * The POSIX module of PHP needs to be activated (e.g. [RHEL, CentOS](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) have disabled it)
* Some form of email server or email gateway such that PHP mail() works. * Some form of email server or email gateway such that PHP mail() works.
If you cannot set up your own email server, you can use the [phpmailer](https://github.com/friendica/friendica-addons/tree/develop/phpmailer) addon and use a remote SMTP server. If you cannot set up your own email server, you can use the [phpmailer](https://github.com/friendica/friendica-addons/tree/develop/phpmailer) addon and use a remote SMTP server.

View file

@ -110,6 +110,7 @@ Dieser Hook kann dafür verwendet werden, alternative Erkennungsfunktionen einzu
'text' => Der analysierte Text. 'text' => Der analysierte Text.
'detected' => (Eingabe/Ausgabe) Das Array mit den erkannten Sprachen. Der Sprachcode ist der Array-Schlüssel, der Array-Wert ist der dezimale Wert für die Wahrscheinlichkeit. 'detected' => (Eingabe/Ausgabe) Das Array mit den erkannten Sprachen. Der Sprachcode ist der Array-Schlüssel, der Array-Wert ist der dezimale Wert für die Wahrscheinlichkeit.
'uri-id' => Die Uri-Id des Beitrags 'uri-id' => Die Uri-Id des Beitrags
'author-id' => Die Contact-id des Autors.
**'addon_settings'** - wird aufgerufen, wenn die HTML-Ausgabe der Addon-Einstellungsseite generiert wird. **'addon_settings'** - wird aufgerufen, wenn die HTML-Ausgabe der Addon-Einstellungsseite generiert wird.
$b ist die HTML-Ausgabe (String) der Addon-Einstellungsseite vor dem finalen "</form>"-Tag. $b ist die HTML-Ausgabe (String) der Addon-Einstellungsseite vor dem finalen "</form>"-Tag.

View file

@ -25,9 +25,9 @@ Requirements
--- ---
* Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale .htaccess-Datei nutzen kannst * Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale .htaccess-Datei nutzen kannst
* PHP 7.3+ (PHP 8 wird noch nicht komplett unterstützt) * PHP 7.3+
* PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei * PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei
* Curl, GD, GMP, PDO, MySQLi, xml, zip und OpenSSL-Erweiterung * Curl, GD, GMP, PDO, mbstrings, MySQLi, hash, xml, zip, IntlChar and OpenSSL-Erweiterung
* Das POSIX Modul muss aktiviert sein ([CentOS, RHEL](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) haben dies z.B. deaktiviert) * Das POSIX Modul muss aktiviert sein ([CentOS, RHEL](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) haben dies z.B. deaktiviert)
* Einen E-Mail Server, so dass PHP `mail()` funktioniert. * Einen E-Mail Server, so dass PHP `mail()` funktioniert.
Wenn kein eigener E-Mail Server zur Verfügung steht, kann alternativ das [phpmailer](https://github.com/friendica/friendica-addons/tree/develop/phpmailer) Addon mit einem externen SMTP Account verwendet werden. Wenn kein eigener E-Mail Server zur Verfügung steht, kann alternativ das [phpmailer](https://github.com/friendica/friendica-addons/tree/develop/phpmailer) Addon mit einem externen SMTP Account verwendet werden.

View file

@ -384,13 +384,11 @@ class Installer
$help = ''; $help = '';
$status = true; $status = true;
if (function_exists('apache_get_modules')) { if (function_exists('apache_get_modules') && !in_array('mod_rewrite', apache_get_modules())) {
if (!in_array('mod_rewrite', apache_get_modules())) {
$help = DI::l10n()->t('Error: Apache webserver mod-rewrite module is required but not installed.'); $help = DI::l10n()->t('Error: Apache webserver mod-rewrite module is required but not installed.');
$status = false; $status = false;
$returnVal = false; $returnVal = false;
} }
}
$this->addCheck(DI::l10n()->t('Apache mod_rewrite module'), $status, true, $help); $this->addCheck(DI::l10n()->t('Apache mod_rewrite module'), $status, true, $help);
$help = ''; $help = '';
@ -399,15 +397,25 @@ class Installer
$status = false; $status = false;
$help = DI::l10n()->t('Error: PDO or MySQLi PHP module required but not installed.'); $help = DI::l10n()->t('Error: PDO or MySQLi PHP module required but not installed.');
$returnVal = false; $returnVal = false;
} else { } elseif (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) {
if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) {
$status = false; $status = false;
$help = DI::l10n()->t('Error: The MySQL driver for PDO is not installed.'); $help = DI::l10n()->t('Error: The MySQL driver for PDO is not installed.');
$returnVal = false; $returnVal = false;
} }
}
$this->addCheck(DI::l10n()->t('PDO or MySQLi PHP module'), $status, true, $help); $this->addCheck(DI::l10n()->t('PDO or MySQLi PHP module'), $status, true, $help);
// Uncomment when IntlChar is installed in the check pipeline.
/*
$help = '';
$status = true;
if (!class_exists('IntlChar')) {
$status = false;
$help = DI::l10n()->t('Error: The IntlChar module is not installed.');
$returnVal = false;
}
$this->addCheck(DI::l10n()->t('IntlChar PHP module'), $status, true, $help);
*/
// check for XML DOM Documents being able to be generated // check for XML DOM Documents being able to be generated
$help = ''; $help = '';
$status = true; $status = true;

View file

@ -405,35 +405,35 @@ class L10n
'be' => 'беларуская мова', 'be' => 'беларуская мова',
'bn' => 'বাংলা', 'bn' => 'বাংলা',
'cy' => 'Cymraeg', 'cy' => 'Cymraeg',
'el-monoton' => 'Ελληνικά', 'el-monoton' => 'ελληνικά',
'eu' => 'euskara', 'eu' => 'euskara, euskera',
'fa' => 'فارسی', 'fa' => 'فارسی',
'ga' => 'Gaeilge', 'ga' => 'Gaeilge',
'gl' => 'Galego', 'gl' => 'galego',
'he' => 'עברית', 'he' => 'עברית',
'hi' => 'हिन्दी', 'hi' => 'हिन्दी, हिंदी',
'hr' => 'Hrvatski', 'hr' => 'hrvatski jezik',
'hy' => 'Հայերեն', 'hy' => 'Հայերեն',
'id' => 'bahasa Indonesia', 'id' => 'Bahasa Indonesia',
'jv' => 'Basa Jawa', 'jv' => 'basa Jawa',
'ka' => 'ქართული', 'ka' => 'ქართული',
'ko' => '한국', 'ko' => '한국어, 조선어',
'lt' => 'lietuvių', 'lt' => 'lietuvių kalba',
'lv' => 'latviešu', 'lv' => 'latviešu valoda',
'ms-Latn' => 'Bahasa Melayu', 'ms-Latn' => 'bahasa Melayu, بهاس ملايو‎',
'sr-Cyrl' => 'српски језик', 'sr-Cyrl' => 'српски језик',
'sk' => 'slovenský', 'sk' => 'slovenčina, slovenský jazyk',
'sl' => 'Slovenščina', 'sl' => 'slovenski jezik, slovenščina',
'sq' => 'Shqip', 'sq' => 'Shqip',
'sw' => 'Kiswahili', 'sw' => 'Kiswahili',
'ta' => 'தமிழ்', 'ta' => 'தமிழ்',
'th' => 'แบบไทย', 'th' => 'ไทย',
'tl' => 'Wikang Tagalog', 'tl' => 'Wikang Tagalog, ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔',
'tr' => 'Türkçe', 'tr' => 'Türkçe',
'pt-PT' => 'Português', 'pt-PT' => 'português',
'uk' => 'Українська', 'uk' => 'українська мова',
'uz' => 'Ўзбек', 'uz' => 'Oʻzbek, Ўзбек, أۇزبېك‎',
'vi' => 'Tiếng Việt', 'vi' => 'Việt Nam',
'zh-hant' => '繁體', 'zh-hant' => '繁體',
]; ];
$langs = array_merge($additional_langs, $langs); $langs = array_merge($additional_langs, $langs);

View file

@ -2010,67 +2010,122 @@ class Item
*/ */
public static function getLanguageArray(string $body, int $count, int $uri_id = 0, int $author_id = 0): array public static function getLanguageArray(string $body, int $count, int $uri_id = 0, int $author_id = 0): array
{ {
$naked_body = BBCode::toSearchText($body, $uri_id); $searchtext = BBCode::toSearchText($body, $uri_id);
if ((count(explode(' ', $naked_body)) < 10) && (mb_strlen($naked_body) < 30) && $author_id) { if ((count(explode(' ', $searchtext)) < 10) && (mb_strlen($searchtext) < 30) && $author_id) {
$author = Contact::selectFirst(['about'], ['id' => $author_id]); $author = Contact::selectFirst(['about'], ['id' => $author_id]);
if (!empty($author['about'])) { if (!empty($author['about'])) {
$about = BBCode::toSearchText($author['about'], 0); $about = BBCode::toSearchText($author['about'], 0);
$about = self::getDominantLanguage($about); Logger::debug('About field added', ['author' => $author_id, 'body' => $searchtext, 'about' => $about]);
Logger::debug('About field added', ['author' => $author_id, 'body' => $naked_body, 'about' => $about]); $searchtext .= ' ' . $about;
$naked_body .= ' ' . $about;
} }
} }
if (empty($naked_body)) { if (empty($searchtext)) {
return []; return [];
} }
$naked_body = self::getDominantLanguage($naked_body);
$availableLanguages = DI::l10n()->getAvailableLanguages(true); $availableLanguages = DI::l10n()->getAvailableLanguages(true);
$availableLanguages = DI::l10n()->convertForLanguageDetection($availableLanguages); $availableLanguages = DI::l10n()->convertForLanguageDetection($availableLanguages);
$ld = new Language(array_keys($availableLanguages)); $ld = new Language(array_keys($availableLanguages));
$languages = $ld->detect($naked_body)->limit(0, $count)->close() ?: [];
$result = [];
foreach (self::splitByBlocks($searchtext) as $block) {
$languages = $ld->detect($block)->limit(0, $count)->close() ?: [];
$data = [ $data = [
'text' => $naked_body, 'text' => $block,
'detected' => $languages, 'detected' => $languages,
'uri-id' => $uri_id, 'uri-id' => $uri_id,
'author-id' => $author_id,
]; ];
Hook::callAll('detect_languages', $data); Hook::callAll('detect_languages', $data);
$languages = $data['detected'];
return $languages; foreach ($data['detected'] as $language => $quality) {
$result[$language] = max($result[$language] ?? 0, $quality * (strlen($block) / strlen($searchtext)));
}
}
arsort($result);
$result = array_slice($result, 0, $count);
return $result;
} }
/** /**
* Check if latin or non latin are dominant in the body and only return the dominant one * Split a string into different unicode blocks
* Currently the text is split into the latin and the non latin part.
* *
* @param string $body * @param string $body
* @return string * @return array
*/ */
private static function getDominantLanguage(string $body): string private static function splitByBlocks(string $body): array
{ {
$latin = ''; if (!class_exists('IntlChar')) {
$non_latin = ''; return [$body];
}
$blocks = [];
$previous_block = 0;
for ($i = 0; $i < mb_strlen($body); $i++) { for ($i = 0; $i < mb_strlen($body); $i++) {
$character = mb_substr($body, $i, 1); $character = mb_substr($body, $i, 1);
$ord = mb_ord($character); $previous = ($i > 0) ? mb_substr($body, $i - 1, 1) : '';
$next = ($i < mb_strlen($body)) ? mb_substr($body, $i + 1, 1) : '';
// We add the most common characters to both strings. if (!\IntlChar::isalpha($character)) {
if (($ord <= 64) || ($ord >= 91 && $ord <= 96) || ($ord >= 123 && $ord <= 191) || in_array($ord, [215, 247]) || ($ord >= 697 && $ord <= 735) || ($ord > 65535)) { if (($previous != '') && (\IntlChar::isalpha($previous))) {
$latin .= $character; $previous_block = self::getBlockCode($previous);
$non_latin .= $character; }
} elseif ($ord < 768) {
$latin .= $character; $block = (($next != '') && \IntlChar::isalpha($next)) ? self::getBlockCode($next) : $previous_block;
$blocks[$block] = ($blocks[$block] ?? '') . $character;
} else { } else {
$non_latin .= $character; $block = self::getBlockCode($character);
$blocks[$block] = ($blocks[$block] ?? '') . $character;
} }
} }
return (mb_strlen($latin) > mb_strlen($non_latin)) ? $latin : $non_latin;
foreach (array_keys($blocks) as $key) {
$blocks[$key] = trim($blocks[$key]);
if (empty($blocks[$key])) {
unset($blocks[$key]);
}
}
return array_values($blocks);
}
/**
* returns the block code for the given character
*
* @param string $character
* @return integer 0 = no alpha character (blank, signs, emojis, ...), 1 = latin character, 2 = character in every other language
*/
private static function getBlockCode(string $character): int
{
if (!\IntlChar::isalpha($character)) {
return 0;
}
return self::isLatin($character) ? 1 : 2;
}
/**
* Checks if the given character is in one of the latin code blocks
*
* @param string $character
* @return boolean
*/
private static function isLatin(string $character): bool
{
return in_array(\IntlChar::getBlockCode($character), [
\IntlChar::BLOCK_CODE_BASIC_LATIN, \IntlChar::BLOCK_CODE_LATIN_1_SUPPLEMENT,
\IntlChar::BLOCK_CODE_LATIN_EXTENDED_A, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_B,
\IntlChar::BLOCK_CODE_LATIN_EXTENDED_C, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_D,
\IntlChar::BLOCK_CODE_LATIN_EXTENDED_E, \IntlChar::BLOCK_CODE_LATIN_EXTENDED_ADDITIONAL
]);
} }
public static function getLanguageMessage(array $item): string public static function getLanguageMessage(array $item): string
@ -2079,7 +2134,7 @@ class Item
$used_languages = ''; $used_languages = '';
foreach (json_decode($item['language'], true) as $language => $reliability) { foreach (json_decode($item['language'], true) as $language => $reliability) {
$used_languages .= $iso639->languageByCode1($language) . ' (' . $language . "): " . number_format($reliability, 5) . '\n'; $used_languages .= $iso639->nativeByCode1(substr($language, 0, 2)) . ' (' . $iso639->languageByCode1(substr($language, 0, 2)) . ' - ' . $language . "): " . number_format($reliability, 5) . '\n';
} }
$used_languages = DI::l10n()->t('Detected languages in this post:\n%s', $used_languages); $used_languages = DI::l10n()->t('Detected languages in this post:\n%s', $used_languages);
return $used_languages; return $used_languages;

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2023.09-rc\n" "Project-Id-Version: 2023.09-rc\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-10-11 21:05+0200\n" "POT-Creation-Date: 2023-10-11 20:35+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -1769,7 +1769,7 @@ msgstr ""
msgid "Create new group" msgid "Create new group"
msgstr "" msgstr ""
#: src/Content/Item.php:331 src/Model/Item.php:3025 #: src/Content/Item.php:331 src/Model/Item.php:3080
msgid "event" msgid "event"
msgstr "" msgstr ""
@ -1777,7 +1777,7 @@ msgstr ""
msgid "status" msgid "status"
msgstr "" msgstr ""
#: src/Content/Item.php:340 src/Model/Item.php:3027 #: src/Content/Item.php:340 src/Model/Item.php:3082
#: src/Module/Post/Tag/Add.php:123 #: src/Module/Post/Tag/Add.php:123
msgid "photo" msgid "photo"
msgstr "" msgstr ""
@ -2188,8 +2188,8 @@ msgid ""
"<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s" "<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s"
msgstr "" msgstr ""
#: src/Content/Text/BBCode.php:994 src/Model/Item.php:3761 #: src/Content/Text/BBCode.php:994 src/Model/Item.php:3816
#: src/Model/Item.php:3767 src/Model/Item.php:3768 #: src/Model/Item.php:3822 src/Model/Item.php:3823
msgid "Link to source" msgid "Link to source"
msgstr "" msgstr ""
@ -2611,235 +2611,235 @@ msgstr ""
msgid "Generate encryption keys" msgid "Generate encryption keys"
msgstr "" msgstr ""
#: src/Core/Installer.php:389 #: src/Core/Installer.php:388
msgid "" msgid ""
"Error: Apache webserver mod-rewrite module is required but not installed." "Error: Apache webserver mod-rewrite module is required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:394 #: src/Core/Installer.php:392
msgid "Apache mod_rewrite module" msgid "Apache mod_rewrite module"
msgstr "" msgstr ""
#: src/Core/Installer.php:400 #: src/Core/Installer.php:398
msgid "Error: PDO or MySQLi PHP module required but not installed." msgid "Error: PDO or MySQLi PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:405 #: src/Core/Installer.php:402
msgid "Error: The MySQL driver for PDO is not installed." msgid "Error: The MySQL driver for PDO is not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:409 #: src/Core/Installer.php:405
msgid "PDO or MySQLi PHP module" msgid "PDO or MySQLi PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:417 #: src/Core/Installer.php:425
msgid "Error, XML PHP module required but not installed." msgid "Error, XML PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:421 #: src/Core/Installer.php:429
msgid "XML PHP module" msgid "XML PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:424 #: src/Core/Installer.php:432
msgid "libCurl PHP module" msgid "libCurl PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:425 #: src/Core/Installer.php:433
msgid "Error: libCURL PHP module required but not installed." msgid "Error: libCURL PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:431 #: src/Core/Installer.php:439
msgid "GD graphics PHP module" msgid "GD graphics PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:432 #: src/Core/Installer.php:440
msgid "" msgid ""
"Error: GD graphics PHP module with JPEG support required but not installed." "Error: GD graphics PHP module with JPEG support required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:438 #: src/Core/Installer.php:446
msgid "OpenSSL PHP module" msgid "OpenSSL PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:439 #: src/Core/Installer.php:447
msgid "Error: openssl PHP module required but not installed." msgid "Error: openssl PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:445 #: src/Core/Installer.php:453
msgid "mb_string PHP module" msgid "mb_string PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:446 #: src/Core/Installer.php:454
msgid "Error: mb_string PHP module required but not installed." msgid "Error: mb_string PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:452 #: src/Core/Installer.php:460
msgid "iconv PHP module" msgid "iconv PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:453 #: src/Core/Installer.php:461
msgid "Error: iconv PHP module required but not installed." msgid "Error: iconv PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:459 #: src/Core/Installer.php:467
msgid "POSIX PHP module" msgid "POSIX PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:460 #: src/Core/Installer.php:468
msgid "Error: POSIX PHP module required but not installed." msgid "Error: POSIX PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:466 #: src/Core/Installer.php:474
msgid "Program execution functions" msgid "Program execution functions"
msgstr "" msgstr ""
#: src/Core/Installer.php:467 #: src/Core/Installer.php:475
msgid "" msgid ""
"Error: Program execution functions (proc_open) required but not enabled." "Error: Program execution functions (proc_open) required but not enabled."
msgstr "" msgstr ""
#: src/Core/Installer.php:473 #: src/Core/Installer.php:481
msgid "JSON PHP module" msgid "JSON PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:474 #: src/Core/Installer.php:482
msgid "Error: JSON PHP module required but not installed." msgid "Error: JSON PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:480 #: src/Core/Installer.php:488
msgid "File Information PHP module" msgid "File Information PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:481 #: src/Core/Installer.php:489
msgid "Error: File Information PHP module required but not installed." msgid "Error: File Information PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:487 #: src/Core/Installer.php:495
msgid "GNU Multiple Precision PHP module" msgid "GNU Multiple Precision PHP module"
msgstr "" msgstr ""
#: src/Core/Installer.php:488 #: src/Core/Installer.php:496
msgid "Error: GNU Multiple Precision PHP module required but not installed." msgid "Error: GNU Multiple Precision PHP module required but not installed."
msgstr "" msgstr ""
#: src/Core/Installer.php:511 #: src/Core/Installer.php:519
msgid "" msgid ""
"The web installer needs to be able to create a file called \"local.config." "The web installer needs to be able to create a file called \"local.config.php"
"php\" in the \"config\" folder of your web server and it is unable to do so." "\" in the \"config\" folder of your web server and it is unable to do so."
msgstr "" msgstr ""
#: src/Core/Installer.php:512 #: src/Core/Installer.php:520
msgid "" msgid ""
"This is most often a permission setting, as the web server may not be able " "This is most often a permission setting, as the web server may not be able "
"to write files in your folder - even if you can." "to write files in your folder - even if you can."
msgstr "" msgstr ""
#: src/Core/Installer.php:513 #: src/Core/Installer.php:521
msgid "" msgid ""
"At the end of this procedure, we will give you a text to save in a file " "At the end of this procedure, we will give you a text to save in a file "
"named local.config.php in your Friendica \"config\" folder." "named local.config.php in your Friendica \"config\" folder."
msgstr "" msgstr ""
#: src/Core/Installer.php:514 #: src/Core/Installer.php:522
msgid "" msgid ""
"You can alternatively skip this procedure and perform a manual installation. " "You can alternatively skip this procedure and perform a manual installation. "
"Please see the file \"doc/INSTALL.md\" for instructions." "Please see the file \"doc/INSTALL.md\" for instructions."
msgstr "" msgstr ""
#: src/Core/Installer.php:517 #: src/Core/Installer.php:525
msgid "config/local.config.php is writable" msgid "config/local.config.php is writable"
msgstr "" msgstr ""
#: src/Core/Installer.php:537 #: src/Core/Installer.php:545
msgid "" msgid ""
"Friendica uses the Smarty3 template engine to render its web views. Smarty3 " "Friendica uses the Smarty3 template engine to render its web views. Smarty3 "
"compiles templates to PHP to speed up rendering." "compiles templates to PHP to speed up rendering."
msgstr "" msgstr ""
#: src/Core/Installer.php:538 #: src/Core/Installer.php:546
msgid "" msgid ""
"In order to store these compiled templates, the web server needs to have " "In order to store these compiled templates, the web server needs to have "
"write access to the directory view/smarty3/ under the Friendica top level " "write access to the directory view/smarty3/ under the Friendica top level "
"folder." "folder."
msgstr "" msgstr ""
#: src/Core/Installer.php:539 #: src/Core/Installer.php:547
msgid "" msgid ""
"Please ensure that the user that your web server runs as (e.g. www-data) has " "Please ensure that the user that your web server runs as (e.g. www-data) has "
"write access to this folder." "write access to this folder."
msgstr "" msgstr ""
#: src/Core/Installer.php:540 #: src/Core/Installer.php:548
msgid "" msgid ""
"Note: as a security measure, you should give the web server write access to " "Note: as a security measure, you should give the web server write access to "
"view/smarty3/ only--not the template files (.tpl) that it contains." "view/smarty3/ only--not the template files (.tpl) that it contains."
msgstr "" msgstr ""
#: src/Core/Installer.php:543 #: src/Core/Installer.php:551
msgid "view/smarty3 is writable" msgid "view/smarty3 is writable"
msgstr "" msgstr ""
#: src/Core/Installer.php:571 #: src/Core/Installer.php:579
msgid "" msgid ""
"Url rewrite in .htaccess seems not working. Make sure you copied .htaccess-" "Url rewrite in .htaccess seems not working. Make sure you copied .htaccess-"
"dist to .htaccess." "dist to .htaccess."
msgstr "" msgstr ""
#: src/Core/Installer.php:572 #: src/Core/Installer.php:580
msgid "" msgid ""
"In some circumstances (like running inside containers), you can skip this " "In some circumstances (like running inside containers), you can skip this "
"error." "error."
msgstr "" msgstr ""
#: src/Core/Installer.php:574 #: src/Core/Installer.php:582
msgid "Error message from Curl when fetching" msgid "Error message from Curl when fetching"
msgstr "" msgstr ""
#: src/Core/Installer.php:580 #: src/Core/Installer.php:588
msgid "Url rewrite is working" msgid "Url rewrite is working"
msgstr "" msgstr ""
#: src/Core/Installer.php:609 #: src/Core/Installer.php:617
msgid "" msgid ""
"The detection of TLS to secure the communication between the browser and the " "The detection of TLS to secure the communication between the browser and the "
"new Friendica server failed." "new Friendica server failed."
msgstr "" msgstr ""
#: src/Core/Installer.php:610 #: src/Core/Installer.php:618
msgid "" msgid ""
"It is highly encouraged to use Friendica only over a secure connection as " "It is highly encouraged to use Friendica only over a secure connection as "
"sensitive information like passwords will be transmitted." "sensitive information like passwords will be transmitted."
msgstr "" msgstr ""
#: src/Core/Installer.php:611 #: src/Core/Installer.php:619
msgid "Please ensure that the connection to the server is secure." msgid "Please ensure that the connection to the server is secure."
msgstr "" msgstr ""
#: src/Core/Installer.php:612 #: src/Core/Installer.php:620
msgid "No TLS detected" msgid "No TLS detected"
msgstr "" msgstr ""
#: src/Core/Installer.php:614 #: src/Core/Installer.php:622
msgid "TLS detected" msgid "TLS detected"
msgstr "" msgstr ""
#: src/Core/Installer.php:641 #: src/Core/Installer.php:649
msgid "ImageMagick PHP extension is not installed" msgid "ImageMagick PHP extension is not installed"
msgstr "" msgstr ""
#: src/Core/Installer.php:643 #: src/Core/Installer.php:651
msgid "ImageMagick PHP extension is installed" msgid "ImageMagick PHP extension is installed"
msgstr "" msgstr ""
#: src/Core/Installer.php:645 #: src/Core/Installer.php:653
msgid "ImageMagick supports GIF" msgid "ImageMagick supports GIF"
msgstr "" msgstr ""
#: src/Core/Installer.php:667 #: src/Core/Installer.php:675
msgid "Database already in use." msgid "Database already in use."
msgstr "" msgstr ""
#: src/Core/Installer.php:672 #: src/Core/Installer.php:680
msgid "Could not connect to database." msgid "Could not connect to database."
msgstr "" msgstr ""
@ -3392,81 +3392,81 @@ msgstr ""
msgid "Happy Birthday %s" msgid "Happy Birthday %s"
msgstr "" msgstr ""
#: src/Model/Item.php:2084 #: src/Model/Item.php:2139
#, php-format #, php-format
msgid "Detected languages in this post:\\n%s" msgid "Detected languages in this post:\\n%s"
msgstr "" msgstr ""
#: src/Model/Item.php:3029 #: src/Model/Item.php:3084
msgid "activity" msgid "activity"
msgstr "" msgstr ""
#: src/Model/Item.php:3031 #: src/Model/Item.php:3086
msgid "comment" msgid "comment"
msgstr "" msgstr ""
#: src/Model/Item.php:3034 src/Module/Post/Tag/Add.php:123 #: src/Model/Item.php:3089 src/Module/Post/Tag/Add.php:123
msgid "post" msgid "post"
msgstr "" msgstr ""
#: src/Model/Item.php:3204 #: src/Model/Item.php:3259
#, php-format #, php-format
msgid "%s is blocked" msgid "%s is blocked"
msgstr "" msgstr ""
#: src/Model/Item.php:3206 #: src/Model/Item.php:3261
#, php-format #, php-format
msgid "%s is ignored" msgid "%s is ignored"
msgstr "" msgstr ""
#: src/Model/Item.php:3208 #: src/Model/Item.php:3263
#, php-format #, php-format
msgid "Content from %s is collapsed" msgid "Content from %s is collapsed"
msgstr "" msgstr ""
#: src/Model/Item.php:3212 #: src/Model/Item.php:3267
#, php-format #, php-format
msgid "Content warning: %s" msgid "Content warning: %s"
msgstr "" msgstr ""
#: src/Model/Item.php:3668 #: src/Model/Item.php:3723
msgid "bytes" msgid "bytes"
msgstr "" msgstr ""
#: src/Model/Item.php:3699 #: src/Model/Item.php:3754
#, php-format #, php-format
msgid "%2$s (%3$d%%, %1$d vote)" msgid "%2$s (%3$d%%, %1$d vote)"
msgid_plural "%2$s (%3$d%%, %1$d votes)" msgid_plural "%2$s (%3$d%%, %1$d votes)"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Model/Item.php:3701 #: src/Model/Item.php:3756
#, php-format #, php-format
msgid "%2$s (%1$d vote)" msgid "%2$s (%1$d vote)"
msgid_plural "%2$s (%1$d votes)" msgid_plural "%2$s (%1$d votes)"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Model/Item.php:3706 #: src/Model/Item.php:3761
#, php-format #, php-format
msgid "%d voter. Poll end: %s" msgid "%d voter. Poll end: %s"
msgid_plural "%d voters. Poll end: %s" msgid_plural "%d voters. Poll end: %s"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Model/Item.php:3708 #: src/Model/Item.php:3763
#, php-format #, php-format
msgid "%d voter." msgid "%d voter."
msgid_plural "%d voters." msgid_plural "%d voters."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Model/Item.php:3710 #: src/Model/Item.php:3765
#, php-format #, php-format
msgid "Poll end: %s" msgid "Poll end: %s"
msgstr "" msgstr ""
#: src/Model/Item.php:3744 src/Model/Item.php:3745 #: src/Model/Item.php:3799 src/Model/Item.php:3800
msgid "View on separate page" msgid "View on separate page"
msgstr "" msgstr ""
@ -5351,9 +5351,9 @@ msgstr ""
#: src/Module/Admin/Summary.php:98 #: src/Module/Admin/Summary.php:98
msgid "" msgid ""
"The last update failed. Please run \"php bin/console.php dbstructure " "The last update failed. Please run \"php bin/console.php dbstructure update"
"update\" from the command line and have a look at the errors that might " "\" from the command line and have a look at the errors that might appear. "
"appear. (Some of the errors are possibly inside the logfile.)" "(Some of the errors are possibly inside the logfile.)"
msgstr "" msgstr ""
#: src/Module/Admin/Summary.php:102 #: src/Module/Admin/Summary.php:102
@ -5504,8 +5504,8 @@ msgstr ""
#, php-format #, php-format
msgid "" msgid ""
"Show some informations regarding the needed information to operate the node " "Show some informations regarding the needed information to operate the node "
"according e.g. to <a href=\"%s\" target=\"_blank\" rel=\"noopener " "according e.g. to <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
"noreferrer\">EU-GDPR</a>." "\">EU-GDPR</a>."
msgstr "" msgstr ""
#: src/Module/Admin/Tos.php:81 #: src/Module/Admin/Tos.php:81
@ -8856,8 +8856,8 @@ msgstr ""
#: src/Module/Profile/Profile.php:158 #: src/Module/Profile/Profile.php:158
#, php-format #, php-format
msgid "" msgid ""
"You're currently viewing your profile as <b>%s</b> <a href=\"%s\" " "You're currently viewing your profile as <b>%s</b> <a href=\"%s\" class="
"class=\"btn btn-sm pull-right\">Cancel</a>" "\"btn btn-sm pull-right\">Cancel</a>"
msgstr "" msgstr ""
#: src/Module/Profile/Profile.php:167 #: src/Module/Profile/Profile.php:167
@ -9405,8 +9405,8 @@ msgstr ""
#: src/Module/Security/TwoFactor/Verify.php:100 #: src/Module/Security/TwoFactor/Verify.php:100
#, php-format #, php-format
msgid "" msgid ""
"If you do not have access to your authentication code you can use a <a " "If you do not have access to your authentication code you can use a <a href="
"href=\"%s\">two-factor recovery code</a>." "\"%s\">two-factor recovery code</a>."
msgstr "" msgstr ""
#: src/Module/Security/TwoFactor/Verify.php:101 #: src/Module/Security/TwoFactor/Verify.php:101
@ -11047,8 +11047,8 @@ msgstr ""
#: src/Module/Settings/TwoFactor/Verify.php:149 #: src/Module/Settings/TwoFactor/Verify.php:149
#, php-format #, php-format
msgid "" msgid ""
"<p>Or you can open the following URL in your mobile device:</p><p><a " "<p>Or you can open the following URL in your mobile device:</p><p><a href="
"href=\"%s\">%s</a></p>" "\"%s\">%s</a></p>"
msgstr "" msgstr ""
#: src/Module/Settings/TwoFactor/Verify.php:156 #: src/Module/Settings/TwoFactor/Verify.php:156
@ -11157,9 +11157,9 @@ msgstr ""
msgid "" msgid ""
"At any point in time a logged in user can export their account data from the " "At any point in time a logged in user can export their account data from the "
"<a href=\"%1$s/settings/userexport\">account settings</a>. If the user wants " "<a href=\"%1$s/settings/userexport\">account settings</a>. If the user wants "
"to delete their account they can do so at <a href=\"%1$s/settings/" "to delete their account they can do so at <a href=\"%1$s/settings/removeme\">"
"removeme\">%1$s/settings/removeme</a>. The deletion of the account will be " "%1$s/settings/removeme</a>. The deletion of the account will be permanent. "
"permanent. Deletion of the data will also be requested from the nodes of the " "Deletion of the data will also be requested from the nodes of the "
"communication partners." "communication partners."
msgstr "" msgstr ""