Merge pull request #13597 from annando/ISO-639-1

Use ISO-639-1 for the language detection
This commit is contained in:
Hypolite Petovan 2023-11-03 11:07:01 -07:00 committed by GitHub
commit c222775bdb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 254 additions and 232 deletions

View file

@ -35,13 +35,13 @@ final class Channel extends Timeline
*/
public function getTimelines(int $uid): Timelines
{
$language = User::getLanguageCode($uid);
$languages = $this->l10n->getAvailableLanguages(true);
$iso639 = new \Matriphe\ISO639\ISO639;
$native = $iso639->nativeByCode1(User::getLanguageCode($uid));
$tabs = [
new ChannelEntity(ChannelEntity::FORYOU, $this->l10n->t('For you'), $this->l10n->t('Posts from contacts you interact with and who interact with you'), 'y'),
new ChannelEntity(ChannelEntity::WHATSHOT, $this->l10n->t('What\'s Hot'), $this->l10n->t('Posts with a lot of interactions'), 'h'),
new ChannelEntity(ChannelEntity::LANGUAGE, $languages[$language], $this->l10n->t('Posts in %s', $languages[$language]), 'g'),
new ChannelEntity(ChannelEntity::LANGUAGE, $native, $this->l10n->t('Posts in %s', $native), 'g'),
new ChannelEntity(ChannelEntity::FOLLOWERS, $this->l10n->t('Followers'), $this->l10n->t('Posts from your followers that you don\'t follow'), 'f'),
new ChannelEntity(ChannelEntity::SHARERSOFSHARERS, $this->l10n->t('Sharers of sharers'), $this->l10n->t('Posts from accounts that are followed by accounts that you follow'), 'r'),
new ChannelEntity(ChannelEntity::IMAGE, $this->l10n->t('Images'), $this->l10n->t('Posts with images'), 'i'),

View file

@ -378,7 +378,7 @@ class L10n
*
* @return array
*/
public function getAvailableLanguages(bool $additional = false): array
public function getAvailableLanguages(): array
{
$langs = [];
$strings_file_paths = glob('view/lang/*/strings.php');
@ -392,107 +392,94 @@ class L10n
$path_array = explode('/', $strings_file_path);
$langs[$path_array[2]] = self::LANG_NAMES[$path_array[2]] ?? $path_array[2];
}
if ($additional) {
// See https://github.com/friendica/friendica/issues/10511
// Persian is manually added to language detection until a persian translation is provided for the interface, at
// which point it will be automatically available through `getAvailableLanguages()` and this should be removed.
// Additionally some more languages are added to that list that are used in the Fediverse.
$additional_langs = [
'af' => 'Afrikaans',
'az-Latn' => 'azərbaycan dili',
'bs-Latn' => 'bosanski jezik',
'be' => 'беларуская мова',
'bn' => 'বাংলা',
'cy' => 'Cymraeg',
'el-monoton' => 'ελληνικά',
'eu' => 'euskara, euskera',
'fa' => 'فارسی',
'ga' => 'Gaeilge',
'gl' => 'galego',
'he' => 'עברית',
'hi' => 'हिन्दी, हिंदी',
'hr' => 'hrvatski jezik',
'hy' => 'Հայերեն',
'id' => 'Bahasa Indonesia',
'jv' => 'basa Jawa',
'ka' => 'ქართული',
'ko' => '한국어, 조선어',
'lt' => 'lietuvių kalba',
'lv' => 'latviešu valoda',
'ms-Latn' => 'bahasa Melayu, بهاس ملايو‎',
'sr-Cyrl' => 'српски језик',
'sk' => 'slovenčina, slovenský jazyk',
'sl' => 'slovenski jezik, slovenščina',
'sq' => 'Shqip',
'sw' => 'Kiswahili',
'ta' => 'தமிழ்',
'th' => 'ไทย',
'tl' => 'Wikang Tagalog, ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔',
'tr' => 'Türkçe',
'pt-PT' => 'português',
'uk' => 'українська мова',
'uz' => 'Oʻzbek, Ўзбек, أۇزبېك‎',
'vi' => 'Việt Nam',
'zh-hant' => '繁體',
];
$langs = array_merge($additional_langs, $langs);
ksort($langs);
}
}
return $langs;
}
/**
* The language detection routine uses some slightly different language codes.
* This function changes the language array accordingly.
* Get language codes that are detectable by our language detection routines.
* Languages are excluded that aren't used often and that tend to false detections.
* The listed codes are a collection of both the official ISO 639-1 codes and
* the codes that are used by our built-in language detection routine.
* When the detection is done, the result only consists of the official ISO 639-1 codes.
*
* @param array $languages
* @return array
*/
public function convertForLanguageDetection(array $languages): array
public function getDetectableLanguages(): array
{
foreach ($languages as $key => $language) {
$newkey = $this->convertCodeForLanguageDetection($key);
if ($newkey != $key) {
if (!isset($languages[$newkey])) {
$languages[$newkey] = $language;
}
unset($languages[$key]);
}
$additional_langs = [
'af', 'az', 'az-Cyrl', 'az-Latn', 'be', 'bn', 'bs', 'bs-Cyrl', 'bs-Latn',
'cy', 'da', 'el', 'el-monoton', 'el-polyton', 'en', 'eu', 'fa', 'fi',
'ga', 'gl', 'gu', 'he', 'hi', 'hr', 'hy', 'id', 'in', 'iu', 'iw', 'jv', 'jw',
'ka', 'km', 'ko', 'lt', 'lv', 'mo', 'ms', 'ms-Arab', 'ms-Latn', 'nb', 'nn', 'no',
'pt', 'pt-PT', 'pt-BR', 'ro', 'sa', 'sk', 'sl', 'sq', 'sr', 'sr-Cyrl', 'sr-Latn', 'sw',
'ta', 'th', 'tl', 'tr', 'ug', 'uk', 'uz', 'vi', 'zh', 'zh-Hant', 'zh-Hans',
];
if (in_array('cld2', get_loaded_extensions())) {
$additional_langs = array_merge($additional_langs,
['dv', 'kn', 'lo', 'ml', 'or', 'pa', 'sd', 'si', 'te', 'yi']);
}
ksort($languages);
$langs = array_merge($additional_langs, array_keys($this->getAvailableLanguages()));
sort($langs);
return $langs;
}
/**
* Return a list of supported languages with their two byte language codes.
*
* @param bool $international If set to true, additionally the international language name is returned as well.
* @return array
*/
public function getLanguageCodes(bool $international = false): array
{
$iso639 = new \Matriphe\ISO639\ISO639;
$languages = [];
foreach ($this->getDetectableLanguages() as $code) {
$code = $this->toISO6391($code);
$native = $iso639->nativeByCode1($code);
$language = $iso639->languageByCode1($code);
if ($native != $language && $international) {
$languages[$code] = $this->t('%s (%s)', $native, $language);
} else {
$languages[$code] = $native;
}
}
return $languages;
}
/**
* The language detection routine uses some slightly different language codes.
* This function changes the language codes accordingly.
* Convert the language code to ISO639-1
* It also converts old codes to their new counterparts.
*
* @param string $language
* @param string $code
* @return string
*/
public function convertCodeForLanguageDetection(string $language): string
public function toISO6391(string $code): string
{
switch ($language) {
case 'da-dk':
return 'da';
case 'en-us':
case 'en-gb':
return 'en';
case 'fi-fi':
return 'fi';
case 'nb-no':
return 'nb';
case 'pt-br':
return 'pt-BR';
case 'zh-cn':
return 'zh-Hans';
default:
return $language;
if ((strlen($code) > 2) && (substr($code, 2, 1) == '-')) {
$code = substr($code, 0, 2);
}
if (in_array($code, ['nb', 'nn'])) {
$code = 'no';
}
if ($code == 'in') {
$code = 'id';
}
if ($code == 'iw') {
$code = 'he';
}
if ($code == 'jw') {
$code = 'jv';
}
if ($code == 'mo') {
$code = 'ro';
}
return $code;
}
/**

View file

@ -2034,15 +2034,12 @@ class Item
return [];
}
$availableLanguages = DI::l10n()->getAvailableLanguages(true);
$availableLanguages = DI::l10n()->convertForLanguageDetection($availableLanguages);
$ld = new Language(array_keys($availableLanguages));
$ld = new Language(DI::l10n()->getDetectableLanguages());
$result = [];
foreach (self::splitByBlocks($searchtext) as $block) {
$languages = $ld->detect($block)->limit(0, $count)->close() ?: [];
$languages = $ld->detect($block)->close() ?: [];
$data = [
'text' => $block,
@ -2057,10 +2054,32 @@ class Item
}
}
arsort($result);
$result = array_slice($result, 0, $count);
$result = self::compactLanguages($result);
return $result;
arsort($result);
return array_slice($result, 0, $count);
}
/**
* Concert the language code in the detection result to ISO 639-1.
* On duplicates the system uses the higher quality value.
*
* @param array $result
* @return array
*/
private static function compactLanguages(array $result): array
{
$languages = [];
foreach ($result as $language => $quality) {
if ($quality == 0) {
continue;
}
$code = DI::l10n()->toISO6391($language);
if (empty($languages[$code]) || ($languages[$code] < $quality)) {
$languages[$code] = $quality;
}
}
return $languages;
}
/**
@ -2143,7 +2162,15 @@ class Item
$used_languages = '';
foreach (json_decode($item['language'], true) as $language => $reliability) {
$used_languages .= $iso639->nativeByCode1(substr($language, 0, 2)) . ' (' . $iso639->languageByCode1(substr($language, 0, 2)) . ' - ' . $language . "): " . number_format($reliability, 5) . '\n';
$code = DI::l10n()->toISO6391($language);
$native = $iso639->nativeByCode1($code);
$language = $iso639->languageByCode1($code);
if ($native != $language) {
$used_languages .= DI::l10n()->t('%s (%s - %s): %s', $native, $language, $code, number_format($reliability, 5)) . '\n';
} else {
$used_languages .= DI::l10n()->t('%s (%s): %s', $native, $code, number_format($reliability, 5)) . '\n';
}
}
$used_languages = DI::l10n()->t('Detected languages in this post:\n%s', $used_languages);
return $used_languages;

View file

@ -35,9 +35,6 @@ use Friendica\Model\Verb;
use Friendica\Protocol\Activity;
use Friendica\Protocol\Relay;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings;
// Channel
class Engagement
{

View file

@ -127,7 +127,6 @@ class User
case 'community':
return User::ACCOUNT_TYPE_COMMUNITY;
}
return null;
}
@ -569,14 +568,12 @@ class User
public static function getLanguageCode(int $uid): string
{
$owner = self::getOwnerDataById($uid);
$languages = DI::l10n()->getAvailableLanguages(true);
if (in_array($owner['language'], array_keys($languages))) {
$language = $owner['language'];
} else {
$language = DI::config()->get('system', 'language');
}
$language = DI::l10n()->toISO6391($owner['language']);
if (in_array($language, array_keys(DI::l10n()->getLanguageCodes()))) {
return $language;
}
return DI::l10n()->toISO6391(DI::config()->get('system', 'language'));
}
/**
* Authenticate a user with a clear text password

View file

@ -304,7 +304,7 @@ class Timeline extends BaseModule
} elseif ($this->selectedTab == ChannelEntity::AUDIO) {
$condition = ["`media-type` & ?", 4];
} elseif ($this->selectedTab == ChannelEntity::LANGUAGE) {
$condition = ["JSON_EXTRACT(JSON_KEYS(language), '$[0]') = ?", $this->l10n->convertCodeForLanguageDetection(User::getLanguageCode($uid))];
$condition = ["JSON_EXTRACT(JSON_KEYS(language), '$[0]') = ?", User::getLanguageCode($uid)];
} elseif (is_numeric($this->selectedTab)) {
$condition = $this->getUserChannelConditions($this->selectedTab, $this->session->getLocalUserId());
}
@ -421,7 +421,6 @@ class Timeline extends BaseModule
{
$conditions = [];
$languages = $this->pConfig->get($uid, 'channel', 'languages', [User::getLanguageCode($uid)]);
$languages = $this->l10n->convertForLanguageDetection($languages);
foreach ($languages as $language) {
$conditions[] = "JSON_EXTRACT(JSON_KEYS(language), '$[0]') = ?";
$condition[] = $language;

View file

@ -260,7 +260,7 @@ class Display extends BaseSettings
$bookmarked_timelines = $this->pConfig->get($uid, 'system', 'network_timelines', $this->getAvailableTimelines($uid, true)->column('code'));
$enabled_timelines = $this->pConfig->get($uid, 'system', 'enabled_timelines', $this->getAvailableTimelines($uid, false)->column('code'));
$channel_languages = $this->pConfig->get($uid, 'channel', 'languages', [User::getLanguageCode($uid)]);
$languages = $this->l10n->getAvailableLanguages(true);
$languages = $this->l10n->getLanguageCodes(true);
$timelines = [];
foreach ($this->getAvailableTimelines($uid) as $timeline) {

View file

@ -242,7 +242,7 @@ class Temporal
// First day of the week (0 = Sunday)
$firstDay = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'calendar', 'first_day_of_week', 0);
$lang = substr(DI::l10n()->getCurrentLang(), 0, 2);
$lang = DI::l10n()->toISO6391(DI::l10n()->getCurrentLang());
// Check if the detected language is supported by the picker
if (!in_array($lang,

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 2023.09-rc\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-01 14:57+0100\n"
"POT-Creation-Date: 2023-11-03 05:35+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -961,7 +961,7 @@ msgstr ""
msgid "Enter user nickname: "
msgstr ""
#: src/Console/User.php:182 src/Model/User.php:739
#: src/Console/User.php:182 src/Model/User.php:736
#: src/Module/Api/Twitter/ContactEndpoint.php:74
#: src/Module/Moderation/Users/Active.php:71
#: src/Module/Moderation/Users/Blocked.php:71
@ -1749,7 +1749,7 @@ msgstr ""
#: src/Content/GroupManager.php:152 src/Content/Nav.php:278
#: src/Content/Text/HTML.php:880 src/Content/Widget.php:537
#: src/Model/User.php:1301
#: src/Model/User.php:1298
msgid "Groups"
msgstr ""
@ -1770,7 +1770,7 @@ msgstr ""
msgid "Create new group"
msgstr ""
#: src/Content/Item.php:332 src/Model/Item.php:3089
#: src/Content/Item.php:332 src/Model/Item.php:3116
msgid "event"
msgstr ""
@ -1778,7 +1778,7 @@ msgstr ""
msgid "status"
msgstr ""
#: src/Content/Item.php:341 src/Model/Item.php:3091
#: src/Content/Item.php:341 src/Model/Item.php:3118
#: src/Module/Post/Tag/Add.php:123
msgid "photo"
msgstr ""
@ -2189,8 +2189,8 @@ msgid ""
"<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s"
msgstr ""
#: src/Content/Text/BBCode.php:994 src/Model/Item.php:3822
#: src/Model/Item.php:3828 src/Model/Item.php:3829
#: src/Content/Text/BBCode.php:994 src/Model/Item.php:3849
#: src/Model/Item.php:3855 src/Model/Item.php:3856
msgid "Link to source"
msgstr ""
@ -2733,8 +2733,8 @@ msgstr ""
#: src/Core/Installer.php:516
msgid ""
"The web installer needs to be able to create a file called \"local.config."
"php\" in the \"config\" folder of your web server and it is unable to do so."
"The web installer needs to be able to create a file called \"local.config.php"
"\" in the \"config\" folder of your web server and it is unable to do so."
msgstr ""
#: src/Core/Installer.php:517
@ -2852,158 +2852,163 @@ msgstr ""
msgid "Could not connect to database."
msgstr ""
#: src/Core/L10n.php:507 src/Model/Event.php:430
#: src/Core/L10n.php:446
#, php-format
msgid "%s (%s)"
msgstr ""
#: src/Core/L10n.php:494 src/Model/Event.php:430
#: src/Module/Settings/Display.php:278
msgid "Monday"
msgstr ""
#: src/Core/L10n.php:507 src/Model/Event.php:431
#: src/Core/L10n.php:494 src/Model/Event.php:431
#: src/Module/Settings/Display.php:279
msgid "Tuesday"
msgstr ""
#: src/Core/L10n.php:507 src/Model/Event.php:432
#: src/Core/L10n.php:494 src/Model/Event.php:432
#: src/Module/Settings/Display.php:280
msgid "Wednesday"
msgstr ""
#: src/Core/L10n.php:507 src/Model/Event.php:433
#: src/Core/L10n.php:494 src/Model/Event.php:433
#: src/Module/Settings/Display.php:281
msgid "Thursday"
msgstr ""
#: src/Core/L10n.php:507 src/Model/Event.php:434
#: src/Core/L10n.php:494 src/Model/Event.php:434
#: src/Module/Settings/Display.php:282
msgid "Friday"
msgstr ""
#: src/Core/L10n.php:507 src/Model/Event.php:435
#: src/Core/L10n.php:494 src/Model/Event.php:435
#: src/Module/Settings/Display.php:283
msgid "Saturday"
msgstr ""
#: src/Core/L10n.php:507 src/Model/Event.php:429
#: src/Core/L10n.php:494 src/Model/Event.php:429
#: src/Module/Settings/Display.php:277
msgid "Sunday"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:450
#: src/Core/L10n.php:498 src/Model/Event.php:450
msgid "January"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:451
#: src/Core/L10n.php:498 src/Model/Event.php:451
msgid "February"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:452
#: src/Core/L10n.php:498 src/Model/Event.php:452
msgid "March"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:453
#: src/Core/L10n.php:498 src/Model/Event.php:453
msgid "April"
msgstr ""
#: src/Core/L10n.php:511 src/Core/L10n.php:530 src/Model/Event.php:441
#: src/Core/L10n.php:498 src/Core/L10n.php:517 src/Model/Event.php:441
msgid "May"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:454
#: src/Core/L10n.php:498 src/Model/Event.php:454
msgid "June"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:455
#: src/Core/L10n.php:498 src/Model/Event.php:455
msgid "July"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:456
#: src/Core/L10n.php:498 src/Model/Event.php:456
msgid "August"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:457
#: src/Core/L10n.php:498 src/Model/Event.php:457
msgid "September"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:458
#: src/Core/L10n.php:498 src/Model/Event.php:458
msgid "October"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:459
#: src/Core/L10n.php:498 src/Model/Event.php:459
msgid "November"
msgstr ""
#: src/Core/L10n.php:511 src/Model/Event.php:460
#: src/Core/L10n.php:498 src/Model/Event.php:460
msgid "December"
msgstr ""
#: src/Core/L10n.php:526 src/Model/Event.php:422
#: src/Core/L10n.php:513 src/Model/Event.php:422
msgid "Mon"
msgstr ""
#: src/Core/L10n.php:526 src/Model/Event.php:423
#: src/Core/L10n.php:513 src/Model/Event.php:423
msgid "Tue"
msgstr ""
#: src/Core/L10n.php:526 src/Model/Event.php:424
#: src/Core/L10n.php:513 src/Model/Event.php:424
msgid "Wed"
msgstr ""
#: src/Core/L10n.php:526 src/Model/Event.php:425
#: src/Core/L10n.php:513 src/Model/Event.php:425
msgid "Thu"
msgstr ""
#: src/Core/L10n.php:526 src/Model/Event.php:426
#: src/Core/L10n.php:513 src/Model/Event.php:426
msgid "Fri"
msgstr ""
#: src/Core/L10n.php:526 src/Model/Event.php:427
#: src/Core/L10n.php:513 src/Model/Event.php:427
msgid "Sat"
msgstr ""
#: src/Core/L10n.php:526 src/Model/Event.php:421
#: src/Core/L10n.php:513 src/Model/Event.php:421
msgid "Sun"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:437
#: src/Core/L10n.php:517 src/Model/Event.php:437
msgid "Jan"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:438
#: src/Core/L10n.php:517 src/Model/Event.php:438
msgid "Feb"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:439
#: src/Core/L10n.php:517 src/Model/Event.php:439
msgid "Mar"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:440
#: src/Core/L10n.php:517 src/Model/Event.php:440
msgid "Apr"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:442
#: src/Core/L10n.php:517 src/Model/Event.php:442
msgid "Jun"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:443
#: src/Core/L10n.php:517 src/Model/Event.php:443
msgid "Jul"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:444
#: src/Core/L10n.php:517 src/Model/Event.php:444
msgid "Aug"
msgstr ""
#: src/Core/L10n.php:530
#: src/Core/L10n.php:517
msgid "Sep"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:446
#: src/Core/L10n.php:517 src/Model/Event.php:446
msgid "Oct"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:447
#: src/Core/L10n.php:517 src/Model/Event.php:447
msgid "Nov"
msgstr ""
#: src/Core/L10n.php:530 src/Model/Event.php:448
#: src/Core/L10n.php:517 src/Model/Event.php:448
msgid "Dec"
msgstr ""
@ -3401,81 +3406,91 @@ msgstr ""
msgid "Happy Birthday %s"
msgstr ""
#: src/Model/Item.php:2148
#: src/Model/Item.php:2170
#, php-format
msgid "%s (%s - %s): %s"
msgstr ""
#: src/Model/Item.php:2172
#, php-format
msgid "%s (%s): %s"
msgstr ""
#: src/Model/Item.php:2175
#, php-format
msgid "Detected languages in this post:\\n%s"
msgstr ""
#: src/Model/Item.php:3093
#: src/Model/Item.php:3120
msgid "activity"
msgstr ""
#: src/Model/Item.php:3095
#: src/Model/Item.php:3122
msgid "comment"
msgstr ""
#: src/Model/Item.php:3098 src/Module/Post/Tag/Add.php:123
#: src/Model/Item.php:3125 src/Module/Post/Tag/Add.php:123
msgid "post"
msgstr ""
#: src/Model/Item.php:3268
#: src/Model/Item.php:3295
#, php-format
msgid "%s is blocked"
msgstr ""
#: src/Model/Item.php:3270
#: src/Model/Item.php:3297
#, php-format
msgid "%s is ignored"
msgstr ""
#: src/Model/Item.php:3272
#: src/Model/Item.php:3299
#, php-format
msgid "Content from %s is collapsed"
msgstr ""
#: src/Model/Item.php:3276
#: src/Model/Item.php:3303
#, php-format
msgid "Content warning: %s"
msgstr ""
#: src/Model/Item.php:3729
#: src/Model/Item.php:3756
msgid "bytes"
msgstr ""
#: src/Model/Item.php:3760
#: src/Model/Item.php:3787
#, php-format
msgid "%2$s (%3$d%%, %1$d vote)"
msgid_plural "%2$s (%3$d%%, %1$d votes)"
msgstr[0] ""
msgstr[1] ""
#: src/Model/Item.php:3762
#: src/Model/Item.php:3789
#, php-format
msgid "%2$s (%1$d vote)"
msgid_plural "%2$s (%1$d votes)"
msgstr[0] ""
msgstr[1] ""
#: src/Model/Item.php:3767
#: src/Model/Item.php:3794
#, php-format
msgid "%d voter. Poll end: %s"
msgid_plural "%d voters. Poll end: %s"
msgstr[0] ""
msgstr[1] ""
#: src/Model/Item.php:3769
#: src/Model/Item.php:3796
#, php-format
msgid "%d voter."
msgid_plural "%d voters."
msgstr[0] ""
msgstr[1] ""
#: src/Model/Item.php:3771
#: src/Model/Item.php:3798
#, php-format
msgid "Poll end: %s"
msgstr ""
#: src/Model/Item.php:3805 src/Model/Item.php:3806
#: src/Model/Item.php:3832 src/Model/Item.php:3833
msgid "View on separate page"
msgstr ""
@ -3633,145 +3648,145 @@ msgstr ""
msgid "Contact information and Social Networks"
msgstr ""
#: src/Model/User.php:226 src/Model/User.php:1214
#: src/Model/User.php:225 src/Model/User.php:1211
msgid "SERIOUS ERROR: Generation of security keys failed."
msgstr ""
#: src/Model/User.php:648 src/Model/User.php:681
#: src/Model/User.php:645 src/Model/User.php:678
msgid "Login failed"
msgstr ""
#: src/Model/User.php:713
#: src/Model/User.php:710
msgid "Not enough information to authenticate"
msgstr ""
#: src/Model/User.php:834
#: src/Model/User.php:831
msgid "Password can't be empty"
msgstr ""
#: src/Model/User.php:876
#: src/Model/User.php:873
msgid "Empty passwords are not allowed."
msgstr ""
#: src/Model/User.php:880
#: src/Model/User.php:877
msgid ""
"The new password has been exposed in a public data dump, please choose "
"another."
msgstr ""
#: src/Model/User.php:884
#: src/Model/User.php:881
msgid "The password length is limited to 72 characters."
msgstr ""
#: src/Model/User.php:888
#: src/Model/User.php:885
msgid "The password can't contain white spaces nor accentuated letters"
msgstr ""
#: src/Model/User.php:1097
#: src/Model/User.php:1094
msgid "Passwords do not match. Password unchanged."
msgstr ""
#: src/Model/User.php:1104
#: src/Model/User.php:1101
msgid "An invitation is required."
msgstr ""
#: src/Model/User.php:1108
#: src/Model/User.php:1105
msgid "Invitation could not be verified."
msgstr ""
#: src/Model/User.php:1116
#: src/Model/User.php:1113
msgid "Invalid OpenID url"
msgstr ""
#: src/Model/User.php:1129 src/Security/Authentication.php:241
#: src/Model/User.php:1126 src/Security/Authentication.php:241
msgid ""
"We encountered a problem while logging in with the OpenID you provided. "
"Please check the correct spelling of the ID."
msgstr ""
#: src/Model/User.php:1129 src/Security/Authentication.php:241
#: src/Model/User.php:1126 src/Security/Authentication.php:241
msgid "The error message was:"
msgstr ""
#: src/Model/User.php:1135
#: src/Model/User.php:1132
msgid "Please enter the required information."
msgstr ""
#: src/Model/User.php:1149
#: src/Model/User.php:1146
#, php-format
msgid ""
"system.username_min_length (%s) and system.username_max_length (%s) are "
"excluding each other, swapping values."
msgstr ""
#: src/Model/User.php:1156
#: src/Model/User.php:1153
#, php-format
msgid "Username should be at least %s character."
msgid_plural "Username should be at least %s characters."
msgstr[0] ""
msgstr[1] ""
#: src/Model/User.php:1160
#: src/Model/User.php:1157
#, php-format
msgid "Username should be at most %s character."
msgid_plural "Username should be at most %s characters."
msgstr[0] ""
msgstr[1] ""
#: src/Model/User.php:1168
#: src/Model/User.php:1165
msgid "That doesn't appear to be your full (First Last) name."
msgstr ""
#: src/Model/User.php:1173
#: src/Model/User.php:1170
msgid "Your email domain is not among those allowed on this site."
msgstr ""
#: src/Model/User.php:1177
#: src/Model/User.php:1174
msgid "Not a valid email address."
msgstr ""
#: src/Model/User.php:1180
#: src/Model/User.php:1177
msgid "The nickname was blocked from registration by the nodes admin."
msgstr ""
#: src/Model/User.php:1184 src/Model/User.php:1190
#: src/Model/User.php:1181 src/Model/User.php:1187
msgid "Cannot use that email."
msgstr ""
#: src/Model/User.php:1196
#: src/Model/User.php:1193
msgid "Your nickname can only contain a-z, 0-9 and _."
msgstr ""
#: src/Model/User.php:1204 src/Model/User.php:1261
#: src/Model/User.php:1201 src/Model/User.php:1258
msgid "Nickname is already registered. Please choose another."
msgstr ""
#: src/Model/User.php:1248 src/Model/User.php:1252
#: src/Model/User.php:1245 src/Model/User.php:1249
msgid "An error occurred during registration. Please try again."
msgstr ""
#: src/Model/User.php:1275
#: src/Model/User.php:1272
msgid "An error occurred creating your default profile. Please try again."
msgstr ""
#: src/Model/User.php:1282
#: src/Model/User.php:1279
msgid "An error occurred creating your self contact. Please try again."
msgstr ""
#: src/Model/User.php:1287
#: src/Model/User.php:1284
msgid "Friends"
msgstr ""
#: src/Model/User.php:1291
#: src/Model/User.php:1288
msgid ""
"An error occurred creating your default contact circle. Please try again."
msgstr ""
#: src/Model/User.php:1335
#: src/Model/User.php:1332
msgid "Profile Photos"
msgstr ""
#: src/Model/User.php:1515
#: src/Model/User.php:1512
#, php-format
msgid ""
"\n"
@ -3779,7 +3794,7 @@ msgid ""
"\t\t\tthe administrator of %2$s has set up an account for you."
msgstr ""
#: src/Model/User.php:1518
#: src/Model/User.php:1515
#, php-format
msgid ""
"\n"
@ -3815,12 +3830,12 @@ msgid ""
"\t\tThank you and welcome to %4$s."
msgstr ""
#: src/Model/User.php:1550 src/Model/User.php:1656
#: src/Model/User.php:1547 src/Model/User.php:1653
#, php-format
msgid "Registration details for %s"
msgstr ""
#: src/Model/User.php:1570
#: src/Model/User.php:1567
#, php-format
msgid ""
"\n"
@ -3836,12 +3851,12 @@ msgid ""
"\t\t"
msgstr ""
#: src/Model/User.php:1589
#: src/Model/User.php:1586
#, php-format
msgid "Registration at %s"
msgstr ""
#: src/Model/User.php:1613
#: src/Model/User.php:1610
#, php-format
msgid ""
"\n"
@ -3850,7 +3865,7 @@ msgid ""
"\t\t\t"
msgstr ""
#: src/Model/User.php:1621
#: src/Model/User.php:1618
#, php-format
msgid ""
"\n"
@ -3871,8 +3886,8 @@ msgid ""
"profile\n"
"\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n"
"\n"
"\t\t\tWe recommend adding a profile photo, adding some profile "
"\"keywords\" (very useful\n"
"\t\t\tWe recommend adding a profile photo, adding some profile \"keywords"
"\" (very useful\n"
"\t\t\tin making new friends) - and perhaps what country you live in; if you "
"do not wish\n"
"\t\t\tto be more specific than that.\n"
@ -3888,7 +3903,7 @@ msgid ""
"\t\t\tThank you and welcome to %2$s."
msgstr ""
#: src/Model/User.php:1683
#: src/Model/User.php:1680
msgid ""
"User with delegates can't be removed, please remove delegate users first"
msgstr ""
@ -5362,9 +5377,9 @@ msgstr ""
#: src/Module/Admin/Summary.php:98
msgid ""
"The last update failed. Please run \"php bin/console.php dbstructure "
"update\" from the command line and have a look at the errors that might "
"appear. (Some of the errors are possibly inside the logfile.)"
"The last update failed. Please run \"php bin/console.php dbstructure update"
"\" from the command line and have a look at the errors that might appear. "
"(Some of the errors are possibly inside the logfile.)"
msgstr ""
#: src/Module/Admin/Summary.php:102
@ -5515,8 +5530,8 @@ msgstr ""
#, php-format
msgid ""
"Show some informations regarding the needed information to operate the node "
"according e.g. to <a href=\"%s\" target=\"_blank\" rel=\"noopener "
"noreferrer\">EU-GDPR</a>."
"according e.g. to <a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer"
"\">EU-GDPR</a>."
msgstr ""
#: src/Module/Admin/Tos.php:81
@ -8849,8 +8864,8 @@ msgstr ""
#: src/Module/Profile/Profile.php:158
#, php-format
msgid ""
"You're currently viewing your profile as <b>%s</b> <a href=\"%s\" "
"class=\"btn btn-sm pull-right\">Cancel</a>"
"You're currently viewing your profile as <b>%s</b> <a href=\"%s\" class="
"\"btn btn-sm pull-right\">Cancel</a>"
msgstr ""
#: src/Module/Profile/Profile.php:167
@ -9398,8 +9413,8 @@ msgstr ""
#: src/Module/Security/TwoFactor/Verify.php:100
#, php-format
msgid ""
"If you do not have access to your authentication code you can use a <a "
"href=\"%s\">two-factor recovery code</a>."
"If you do not have access to your authentication code you can use a <a href="
"\"%s\">two-factor recovery code</a>."
msgstr ""
#: src/Module/Security/TwoFactor/Verify.php:101
@ -11050,8 +11065,8 @@ msgstr ""
#: src/Module/Settings/TwoFactor/Verify.php:152
#, php-format
msgid ""
"<p>Or you can open the following URL in your mobile device:</p><p><a "
"href=\"%s\">%s</a></p>"
"<p>Or you can open the following URL in your mobile device:</p><p><a href="
"\"%s\">%s</a></p>"
msgstr ""
#: src/Module/Settings/TwoFactor/Verify.php:159
@ -11160,9 +11175,9 @@ msgstr ""
msgid ""
"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 "
"to delete their account they can do so at <a href=\"%1$s/settings/"
"removeme\">%1$s/settings/removeme</a>. The deletion of the account will be "
"permanent. Deletion of the data will also be requested from the nodes of the "
"to delete their account they can do so at <a href=\"%1$s/settings/removeme\">"
"%1$s/settings/removeme</a>. The deletion of the account will be permanent. "
"Deletion of the data will also be requested from the nodes of the "
"communication partners."
msgstr ""