17 Commits

Author SHA1 Message Date
Milos Sen
f5c2e08f03 add sk translation 2026-08-09 04:44:20 +03:00
Milos Sen
42d4f44a70 rollback plugin name 1 2026-08-08 10:28:07 +03:00
Milos Sen
1a5b07273d change plugin name
Some checks failed
PHP Lint / lint (8.2) (pull_request) Has been cancelled
PHP Lint / lint (8.3) (pull_request) Has been cancelled
PHP Lint / lint (8.4) (pull_request) Has been cancelled
PHP CodeSniffer / phpcs (pull_request) Has been cancelled
2026-08-08 09:28:20 +03:00
Milos Sen
64d2ff3e98 change plugi name 2026-08-08 09:20:09 +03:00
Milos Sen
85a0d4f9ec change plugi name 2026-08-08 09:03:01 +03:00
Milos Sen
84c7b31dfb update comment 2026-08-08 06:53:11 +03:00
1499347b7b added workbench to list of skins 2026-08-07 19:41:40 +00:00
1d39bc03d8 Update SQL/postgres.initial.sql
makes the script safe to re-run against an already-migrated database
2026-08-06 05:10:47 +00:00
Laurent Dinclaux
8f45736b1b fix(skins): keep menu links visible and align native select look
The wrapper had width:100% which pushed the right-side menu links
(mail/contacts/settings/logout) out of #taskbar in Classic, and the
global custom select styling defeated Roundcube's native select
rendering — even when reset — because any background-image on a
<select> disables the native gradient/rounded corners.

- Scope the custom appearance/SVG-chevron CSS to Elastic and Larry
- Add a Classic-specific rule (width:auto, max-width, -2px nudge) that
  preserves Roundcube's native select look in #taskbar
- Drop the inline padding:0 imposed by the PHP renderer; let CSS own it
- Cap the Larry wrapper width to keep .button-logout in flow, and move
  the Larry-only styling out of the JS into the scoped CSS rule

Fixes #1
2026-05-12 17:02:32 +11:00
Laurent Dinclaux
8385197f11 chore: refresh composer.lock 2026-05-06 20:26:54 +11:00
Laurent Dinclaux
ca16e3ca39 ci: bump actions/checkout to v5 (Node 24) 2026-05-06 20:21:04 +11:00
Laurent Dinclaux
c194661fa3 fix: prevent username flash on load and remove select max-width 2026-05-06 20:11:10 +11:00
Laurent Dinclaux
e539c60e9b feat: use primary identity display name in switcher dropdown
The account switcher dropdown previously showed the IMAP username
(typically the email address) for the primary account. Now it falls
back to the identity's display name when available, matching the
behavior of secondary accounts which use their custom label.

Priority order: global_alias session var > primary identity display
name > IMAP username.
2026-05-06 17:37:50 +11:00
Laurent Dinclaux
bea25d8396 fix: prevent migration from running on fresh installs 2026-02-27 17:50:57 +11:00
Laurent Dinclaux
b4506a0a3e fix: disable mode select until email is entered 2026-02-27 17:44:15 +11:00
Laurent Dinclaux
54b96ef059 refactor: delegated form events and harden preconfig enforcement 2026-02-27 17:12:27 +11:00
Laurent Dinclaux
7de47160b6 fix: add dropdown chevron to account switcher 2026-02-27 17:10:26 +11:00
15 changed files with 421 additions and 109 deletions

View File

@@ -13,7 +13,7 @@ jobs:
matrix:
php-version: ['8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Setup PHP ${{ matrix.php-version }}
uses: shivammathur/setup-php@v2

View File

@@ -10,7 +10,7 @@ jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Setup PHP
uses: shivammathur/setup-php@v2

View File

@@ -86,3 +86,5 @@ CREATE TABLE IF NOT EXISTS `ident_switch`
INDEX `IX_ident_switch_iid`(`iid`),
INDEX `IX_ident_switch_parent_id`(`parent_id`)
);
INSERT INTO `system` (`name`, `value`) VALUES ('ident_switch-version', '2026021000');

View File

@@ -1,4 +1,13 @@
CREATE TABLE ident_switch
-- Patched version of SQL/postgres.initial.sql for gecka/ident-switch.
-- Commit this into your Gitea fork at the same path, replacing the
-- upstream file. Only two changes from upstream:
-- 1. CREATE TABLE / CREATE INDEX -> IF NOT EXISTS
-- 2. INSERT INTO system -> upsert via ON CONFLICT
-- This makes the script safe to re-run against an already-migrated
-- database, which happens on every container restart unless
-- /var/www/html is persisted (composer re-installs "fresh" each time).
CREATE TABLE IF NOT EXISTS ident_switch
(
id
serial
@@ -82,6 +91,9 @@ CREATE TABLE ident_switch
UNIQUE (user_id, label)
);
CREATE INDEX IX_ident_switch_user_id ON ident_switch(user_id);
CREATE INDEX IX_ident_switch_iid ON ident_switch(iid);
CREATE INDEX IX_ident_switch_parent_id ON ident_switch(parent_id);
CREATE INDEX IF NOT EXISTS IX_ident_switch_user_id ON ident_switch(user_id);
CREATE INDEX IF NOT EXISTS IX_ident_switch_iid ON ident_switch(iid);
CREATE INDEX IF NOT EXISTS IX_ident_switch_parent_id ON ident_switch(parent_id);
INSERT INTO system (name, value) VALUES ('ident_switch-version', '2026021000')
ON CONFLICT (name) DO UPDATE SET value = EXCLUDED.value;

View File

@@ -84,3 +84,5 @@ CREATE TABLE ident_switch
CREATE INDEX IX_ident_switch_user_id ON ident_switch(user_id);
CREATE INDEX IX_ident_switch_iid ON ident_switch(iid);
CREATE INDEX IX_ident_switch_parent_id ON ident_switch(parent_id);
INSERT INTO system (name, value) VALUES ('ident_switch-version', '2026021000');

View File

@@ -1,5 +1,5 @@
{
"name": "gecka/ident-switch",
"name": "senior/ident-switch",
"type": "roundcube-plugin",
"description": "This plugin allows users to switch between different accounts (including remote) in single Roundcube session.",
"homepage": "https://github.com/Gecka-Apps/roundcube-ident_switch",

4
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "46b2d3558cb304fde0539d1b85971382",
"content-hash": "c1389b5e002c6014eeddc8105bf77db1",
"packages": [
{
"name": "roundcube/plugin-installer",
@@ -154,5 +154,5 @@
"ext-ctype": "*"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.9.0"
}

View File

@@ -98,4 +98,4 @@ $config['ident_switch.preconfig_only'] = false;
* Useful for troubleshooting SMTP/Sieve routing and alias resolution.
* Default: false.
*/
$config['ident_switch.debug'] = false;
$config['ident_switch.debug'] = true;

View File

@@ -19,62 +19,30 @@ var ident_switch_portDefaults = {
sieve: { '': 4190, tls: 4190, ssl: 4190 }
};
$(function() {
/**
* Flag to ensure delegated event handlers are registered only once.
*/
var ident_switch_delegated = false;
/**
* Initialize the identity form: apply mode visibility, preconfig, placeholders.
* Called on each form render (initial page load + AJAX identity loads).
*/
function plugin_switchIdent_init() {
// Register delegated event handlers once (survive DOM replacements)
if (!ident_switch_delegated) {
ident_switch_delegated = true;
plugin_switchIdent_bindDelegatedEvents();
}
// Apply initial mode visibility
var initialMode = $("SELECT[name='_ident_switch.form.common.mode']").val() || 'primary';
plugin_switchIdent_mode_onChange(initialMode);
plugin_switchIdent_processPreconfig();
// Bind security change handlers
$.each(['imap', 'smtp', 'sieve'], function(i, proto) {
var secSel = "SELECT[name='_ident_switch.form." + proto + ".security']";
$(secSel).on('change', function() {
plugin_switchIdent_onSecurityChange(proto, $(this).val());
});
});
// Bind blur handlers for smart placeholder clearing
$.each(['imap', 'smtp', 'sieve'], function(i, proto) {
var portFld = $("INPUT[name='_ident_switch.form." + proto + ".port']");
portFld.on('blur', function() {
plugin_switchIdent_clearIfDefault($(this));
});
var hostFld = $("INPUT[name='_ident_switch.form." + proto + ".host']");
hostFld.on('blur', function() {
plugin_switchIdent_clearIfDefault($(this));
});
});
// IMAP host → update SMTP/Sieve host placeholders
$("INPUT[name='_ident_switch.form.imap.host']").on('change blur', function() {
var imapHost = $(this).val() || 'localhost';
$("INPUT[name='_ident_switch.form.smtp.host']").attr('placeholder', imapHost);
$("INPUT[name='_ident_switch.form.sieve.host']").attr('placeholder', imapHost);
});
// Bind auth change handlers for SMTP and Sieve custom credentials
// Apply initial auth visibility for SMTP and Sieve
$.each(['smtp', 'sieve'], function(i, proto) {
var authSel = "SELECT[name='_ident_switch.form." + proto + ".auth']";
$(authSel).on('change', function() {
plugin_switchIdent_onAuthChange(proto, $(this).val());
});
// Apply initial visibility
plugin_switchIdent_onAuthChange(proto, $(authSel).val());
});
// Delimiter mode handler
$("SELECT[name='_ident_switch.form.imap.delimiter_mode']").on('change', function() {
if ($(this).val() === 'manual') {
$('#ident-switch-delimiter-input').show();
} else {
$('#ident-switch-delimiter-input').hide();
$("INPUT[name='_ident_switch.form.imap.delimiter']").val('');
}
});
// Watch email field for dynamic preconfig application
$("INPUT[name='_email']").on('change blur', function() {
plugin_switchIdent_onEmailChange($(this).val());
var authVal = $("SELECT[name='_ident_switch.form." + proto + ".auth']").val();
plugin_switchIdent_onAuthChange(proto, authVal);
});
// Set initial placeholders from current field values
@@ -87,6 +55,72 @@ $(function() {
$("INPUT[name='_ident_switch.form.smtp.host']").attr('placeholder', initialImapHost);
$("INPUT[name='_ident_switch.form.sieve.host']").attr('placeholder', initialImapHost);
}
// Disable mode select until a valid email is entered
var $modeSelect = $("SELECT[name='_ident_switch.form.common.mode']");
if (initialEmail && initialEmail.indexOf('@') > 0) {
$modeSelect.prop('disabled', false);
plugin_switchIdent_onEmailChange(initialEmail);
} else {
$modeSelect.prop('disabled', true);
}
}
/**
* Register delegated event handlers on the document.
* These survive DOM replacements (AJAX form reloads).
*/
function plugin_switchIdent_bindDelegatedEvents() {
// Security change handlers
$.each(['imap', 'smtp', 'sieve'], function(i, proto) {
$(document).on('change', "SELECT[name='_ident_switch.form." + proto + ".security']", function() {
plugin_switchIdent_onSecurityChange(proto, $(this).val());
});
});
// Blur handlers for smart placeholder clearing
$.each(['imap', 'smtp', 'sieve'], function(i, proto) {
$(document).on('blur', "INPUT[name='_ident_switch.form." + proto + ".port']", function() {
plugin_switchIdent_clearIfDefault($(this));
});
$(document).on('blur', "INPUT[name='_ident_switch.form." + proto + ".host']", function() {
plugin_switchIdent_clearIfDefault($(this));
});
});
// IMAP host → update SMTP/Sieve host placeholders
$(document).on('change blur', "INPUT[name='_ident_switch.form.imap.host']", function() {
var imapHost = $(this).val() || 'localhost';
$("INPUT[name='_ident_switch.form.smtp.host']").attr('placeholder', imapHost);
$("INPUT[name='_ident_switch.form.sieve.host']").attr('placeholder', imapHost);
});
// Auth change handlers for SMTP and Sieve custom credentials
$.each(['smtp', 'sieve'], function(i, proto) {
$(document).on('change', "SELECT[name='_ident_switch.form." + proto + ".auth']", function() {
plugin_switchIdent_onAuthChange(proto, $(this).val());
});
});
// Delimiter mode handler
$(document).on('change', "SELECT[name='_ident_switch.form.imap.delimiter_mode']", function() {
if ($(this).val() === 'manual') {
$('#ident-switch-delimiter-input').show();
} else {
$('#ident-switch-delimiter-input').hide();
$("INPUT[name='_ident_switch.form.imap.delimiter']").val('');
}
});
// Watch email field for dynamic preconfig application
$(document).on('change blur', "INPUT[name='_email']", function() {
plugin_switchIdent_onEmailChange($(this).val());
});
}
// Run init on initial page load
$(function() {
plugin_switchIdent_init();
});
/**
@@ -193,32 +227,43 @@ function plugin_switchIdent_onAuthChange(proto, authVal) {
}
}
/**
* Apply or remove preconfig readonly state on form fields.
* Reads the hidden readonly field value and enables/disables fields accordingly.
*/
function plugin_switchIdent_processPreconfig() {
var disFld = $("INPUT[name='_ident_switch.form.common.readonly']");
disFld.parentsUntil("TABLE", "TR").hide();
var disVal = parseInt(disFld.val(), 10) || 0;
// All fields that can be locked by preconfig
var lockedFields = [
"INPUT[name='_ident_switch.form.imap.host']",
"SELECT[name='_ident_switch.form.imap.security']",
"INPUT[name='_ident_switch.form.imap.port']",
"INPUT[name='_ident_switch.form.smtp.host']",
"SELECT[name='_ident_switch.form.smtp.security']",
"INPUT[name='_ident_switch.form.smtp.port']",
"SELECT[name='_ident_switch.form.smtp.auth']",
"INPUT[name='_ident_switch.form.smtp.username']",
"INPUT[name='_ident_switch.form.smtp.password']",
"SELECT[name='_ident_switch.form.imap.delimiter_mode']",
"INPUT[name='_ident_switch.form.imap.delimiter']",
"INPUT[name='_ident_switch.form.sieve.host']",
"SELECT[name='_ident_switch.form.sieve.security']",
"INPUT[name='_ident_switch.form.sieve.port']",
"SELECT[name='_ident_switch.form.sieve.auth']",
"INPUT[name='_ident_switch.form.sieve.username']",
"INPUT[name='_ident_switch.form.sieve.password']"
];
// Reset all to enabled first (handles navigation from readonly to non-readonly)
$.each(lockedFields, function(_, sel) { $(sel).prop("disabled", false); });
$("INPUT[name='_ident_switch.form.imap.username']").prop("disabled", false);
if (disVal > 0) {
$("INPUT[name='_ident_switch.form.imap.host']").prop("disabled", true);
$("SELECT[name='_ident_switch.form.imap.security']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.imap.port']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.smtp.host']").prop("disabled", true);
$("SELECT[name='_ident_switch.form.smtp.security']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.smtp.port']").prop("disabled", true);
$("SELECT[name='_ident_switch.form.smtp.auth']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.smtp.username']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.smtp.password']").prop("disabled", true);
$("SELECT[name='_ident_switch.form.imap.delimiter_mode']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.imap.delimiter']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.sieve.host']").prop("disabled", true);
$("SELECT[name='_ident_switch.form.sieve.security']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.sieve.port']").prop("disabled", true);
$("SELECT[name='_ident_switch.form.sieve.auth']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.sieve.username']").prop("disabled", true);
$("INPUT[name='_ident_switch.form.sieve.password']").prop("disabled", true);
$.each(lockedFields, function(_, sel) { $(sel).prop("disabled", true); });
}
if (disVal === 2) {
$("INPUT[name='_ident_switch.form.imap.username']").prop("disabled", true);
@@ -236,6 +281,9 @@ function plugin_switchIdent_onEmailChange(email) {
var domain = email.substring(atPos + 1).toLowerCase();
if (!domain) return;
// Enable mode select now that we have a valid email
$("SELECT[name='_ident_switch.form.common.mode']").prop('disabled', false);
// Update label and username placeholders to match current email
$("INPUT[name='_ident_switch.form.common.label']").attr('placeholder', email);

View File

@@ -2,7 +2,7 @@
* ident_switch - Account switcher UI and new mail notifications.
*
* Places the hidden <select> from the footer into the appropriate
* skin location (Larry, Classic, Elastic), shows it, and registers
* skin location (Larry, Classic, Elastic, Workbench), shows it, and registers
* notification listeners for background mail checking.
*
* Copyright (C) 2016-2018 Boris Gulay
@@ -22,7 +22,6 @@ $(function() {
var $sw = $wrapper.find('#plugin-ident_switch-account');
var placed = false;
switch (rcmail.env.skin) {
case 'larry':
placed = plugin_switchIdent_addCbLarry($wrapper, $sw);
@@ -33,6 +32,9 @@ $(function() {
case 'elastic':
placed = plugin_switchIdent_addCbElastic($wrapper, $sw);
break;
case 'workbench':
placed = plugin_switchIdent_addCbElastic($wrapper, $sw);
break;
}
if (!placed) {
@@ -57,7 +59,7 @@ $(function() {
});
/**
* Place switcher in Larry skin: replace username in top-right corner.
* Place switcher in Larry skin: replace username in top-right corner of #topline.
*/
function plugin_switchIdent_addCbLarry($wrapper, $sw) {
var $topRight = $('#topline .topright');
@@ -65,12 +67,6 @@ function plugin_switchIdent_addCbLarry($wrapper, $sw) {
return false;
}
$sw.css({
'font-weight': 'bold',
'max-width': '200px',
'text-overflow': 'ellipsis'
});
$topRight.find('.username').hide();
$topRight.prepend($wrapper);
return true;
@@ -99,14 +95,13 @@ function plugin_switchIdent_addCbElastic($wrapper, $sw) {
}
$sw.css({
'background': 'transparent',
'background-color': 'transparent',
'border': 'none',
'font-weight': 'bold',
'color': 'inherit',
'box-shadow': 'none',
'max-width': '200px',
'text-overflow': 'ellipsis',
'padding': '0 0.25em'
'padding': '0 1.2em 0 0.25em'
});
// Hide original username text and elements

View File

@@ -15,6 +15,78 @@
width: 100%;
}
/* Account switcher <select>: hide native arrow, show SVG chevron.
Scoped to Elastic (.header-title.username) and Larry (#topline .topright) where
the switcher replaces a styled header label; Classic uses Roundcube's native
select rendering instead (see #taskbar rule below). */
.header-title.username .ident-switch-wrapper select,
#topline .topright .ident-switch-wrapper select {
cursor: pointer;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23ccc'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.3em center;
background-size: 10px 6px;
}
/*
* Prevent flash of original username before JS prepends the switcher.
* The JS hides these elements at DOMReady, but the CSS rules below hide them
* earlier (during initial render) — only loaded when the switcher will actually
* be shown, so users without secondary accounts keep the default username display.
*/
/* Elastic skin: switcher is prepended inside .header-title.username.
Hide the original username via visibility on the parent (affects the text
node), then re-show the wrapper. Unlike color/font-size, this preserves the
parent's flex/line-height context, keeping the wrapper vertically centered. */
.header-title.username {
visibility: hidden;
}
.header-title.username > *:not(.ident-switch-wrapper) {
display: none;
}
.header-title.username > .ident-switch-wrapper {
visibility: visible;
}
/* Larry skin: switcher is prepended next to .username inside #topline .topright */
#topline .topright > .username {
display: none;
}
/* Larry skin: blend the <select> into the dark #topline header (Larry styles a
<span> here, not a <select>, so without these the native white control sticks
out on the dark background). */
#topline .topright .ident-switch-wrapper {
width: auto;
}
#topline .topright .ident-switch-wrapper select {
background-color: transparent;
border: none;
box-shadow: none;
color: inherit;
font-weight: bold;
padding: 0 1.2em 0 0.25em;
text-overflow: ellipsis;
}
/* Classic skin: switcher is prepended inside #taskbar (right-aligned, nowrap, 24px tall).
Drop width:100% so it sits inline before the menu links instead of pushing them
off-screen. The select keeps Roundcube's default native rendering. */
#taskbar > .ident-switch-wrapper {
width: auto;
vertical-align: middle;
margin-right: 8px;
}
#taskbar > .ident-switch-wrapper select {
max-width: 180px;
position: relative;
top: -2px;
}
/* Unread badge */
.ident-switch-badge {
flex-shrink: 0;

View File

@@ -158,10 +158,6 @@ class ident_switch extends rcube_plugin
default => null,
};
if ($rc->task === 'mail') {
$this->include_stylesheet('ident_switch.css');
}
return $args;
}
@@ -188,7 +184,9 @@ class ident_switch extends rcube_plugin
$iid = intval($iid_s);
}
$accNames = [$_SESSION['global_alias'] ?? $rc->user->data['username']];
$primaryIdentity = $rc->user->get_identity();
$primaryName = !empty($primaryIdentity['name']) ? $primaryIdentity['name'] : null;
$accNames = [$_SESSION['global_alias'] ?? $primaryName ?? $rc->user->data['username']];
$accValues = [-1];
$accSelected = -1;
$iidMap = [0 => -1]; // primary account: iid 0 → select value -1
@@ -216,6 +214,7 @@ class ident_switch extends rcube_plugin
return;
}
$this->include_stylesheet('ident_switch.css');
$this->include_script('ident_switch-switch.js');
// Pass config to JS environment
@@ -223,7 +222,7 @@ class ident_switch extends rcube_plugin
$select = new html_select([
'id' => 'plugin-ident_switch-account',
'style' => 'display: none; padding: 0;',
'style' => 'display: none;',
'onchange' => 'plugin_switchIdent_switch(this.value);',
]);
$select->add($accNames, $accValues);

View File

@@ -177,6 +177,9 @@ class IdentSwitchChecker
$host = 'tls://' . $host;
}
$primaryIdentity = $rc->user->get_identity();
$primaryName = !empty($primaryIdentity['name']) ? $primaryIdentity['name'] : null;
return [
'iid' => 0,
'imap_host' => $host,
@@ -185,7 +188,7 @@ class IdentSwitchChecker
'username' => $rc->user->data['username'],
'password' => $_SESSION['password' . $postfix],
'email' => $rc->user->data['username'],
'label' => $_SESSION['global_alias'] ?? $rc->user->data['username'],
'label' => $_SESSION['global_alias'] ?? $primaryName ?? $rc->user->data['username'],
'notify_basic' => null,
'notify_sound' => null,
'notify_desktop' => null,

View File

@@ -736,6 +736,9 @@ class IdentSwitchForm
];
}
// Re-run JS init on each form render (handles AJAX identity loads)
$rc->output->add_script('plugin_switchIdent_init();', 'docready');
return $args;
}
@@ -926,11 +929,11 @@ class IdentSwitchForm
}
/**
* Fill in missing validated data from preconfig when identity is readonly.
* Enforce readonly preconfig values on validated data.
*
* When a preconfig has readonly=true, form fields are disabled in the
* browser and not submitted via POST. This fills the missing values
* from the preconfig on the server side.
* When a preconfig has readonly=true, this overwrites the validated
* data with preconfig values regardless of what the user submitted.
* This prevents tampering via browser devtools (re-enabling disabled fields).
*
* @param array $data Validated data from validate(), modified in place.
* @param string $email Email address of the identity.
@@ -947,26 +950,30 @@ class IdentSwitchForm
$record = ['email' => $email];
$preconfig->apply($record);
// Map simple preconfig record keys to validated data keys
// Force preconfig values (overwrite any tampered POST data)
$map = [
'ident_switch.form.imap.port' => 'imap.port',
'ident_switch.form.imap.delimiter' => 'imap.delimiter',
'ident_switch.form.imap.username' => 'imap.user',
'ident_switch.form.smtp.port' => 'smtp.port',
'ident_switch.form.sieve.port' => 'sieve.port',
];
foreach ($map as $recordKey => $dataKey) {
if (empty($data[$dataKey]) && isset($record[$recordKey])) {
if (isset($record[$recordKey])) {
$data[$dataKey] = $record[$recordKey];
}
}
// Compose hosts with security scheme (preconfig stores them separately)
// Force username if preconfig defines it
if (isset($record['ident_switch.form.imap.username'])) {
$data['imap.user'] = $record['ident_switch.form.imap.username'];
}
// Force hosts with security scheme
foreach (['imap', 'smtp', 'sieve'] as $proto) {
$hostKey = "ident_switch.form.{$proto}.host";
$secKey = "ident_switch.form.{$proto}.security";
if (empty($data["{$proto}.host"]) && !empty($record[$hostKey])) {
if (!empty($record[$hostKey])) {
$security = $record[$secKey] ?? '';
$data["{$proto}.host"] = self::compose_host_scheme($record[$hostKey], $security);
}

172
localization/sk_SK.inc Normal file
View File

@@ -0,0 +1,172 @@
<?php
/*
* Lokalizačný súbor pre plugin ident_switch
*/
$labels = array();
// Samostatný účet
$labels['form.caption'] = 'Samostatný účet';
$labels['form.description'] = 'Nakonfigurujte túto identitu ako samostatný účet s vlastnými pripojeniami na poštový server.';
$labels['form.preconfig_only_warning'] = 'Konfigurácia samostatného účtu nie je dostupná pre doménu %s.';
// Všeobecné
$labels['form.common.general'] = 'Všeobecné';
// Režim účtu
$labels['form.common.mode'] = 'Režim účtu';
$labels['form.common.mode.primary'] = 'Hlavný účet';
$labels['form.common.mode.separate'] = 'Samostatný účet';
$labels['form.common.mode.hint'] = 'Prepojte túto identitu s existujúcim účtom alebo ju nakonfigurujte ako samostatný účet s vlastným poštovým serverom.';
// Názov
$labels['form.common.label'] = 'Názov';
$labels['form.common.label.hint'] = 'Názov zobrazený v prepínači účtov. Ak je prázdne, použije sa e-mailová adresa.';
// Hodnota v poli 'Názov' je príliš dlhá (max. 32 znakov).
$labels['err.label.long'] = 'Hodnota v poli \'Názov\' je príliš dlhá (max. 32 znakov).';
// IMAP
$labels['form.imap.caption'] = 'IMAP';
// Server prichádzajúcej pošty
$labels['form.imap.host'] = 'Server prichádzajúcej pošty';
// Zabezpečenie
$labels['form.imap.security'] = 'Zabezpečenie';
// Port
$labels['form.imap.port'] = 'Port';
// Oddeľovač hierarchie priečinkov
$labels['form.imap.delimiter'] = 'Oddeľovač hierarchie priečinkov';
$labels['form.imap.delimiter.auto'] = 'Automaticky';
$labels['form.imap.delimiter.manual'] = 'Manuálne';
// Používateľské meno
$labels['form.imap.username'] = 'Používateľské meno';
// Heslo
$labels['form.imap.password'] = 'Heslo';
// Hodnota v poli 'Používateľské meno' je príliš dlhá (max. 64 znakov).
$labels['err.user.long'] = 'Hodnota v poli \'Používateľské meno\' je príliš dlhá (max. 64 znakov).';
// SMTP
$labels['form.smtp.caption'] = 'SMTP';
// Server odchádzajúcej pošty
$labels['form.smtp.host'] = 'Server odchádzajúcej pošty';
// Zabezpečenie
$labels['form.smtp.security'] = 'Zabezpečenie';
// Port
$labels['form.smtp.port'] = 'Port';
// Autorizácia
$labels['form.smtp.auth'] = 'Autorizácia';
// Ako IMAP
$labels['form.smtp.auth.imap'] = 'Ako IMAP';
// Žiadna
$labels['form.smtp.auth.none'] = 'Žiadna';
// Vlastná
$labels['form.smtp.auth.custom'] = 'Vlastná';
// Používateľské meno
$labels['form.smtp.username'] = 'Používateľské meno';
// Heslo
$labels['form.smtp.password'] = 'Heslo';
// Sieve
$labels['form.sieve.caption'] = 'Sieve';
// Názov hostiteľa servera
$labels['form.sieve.host'] = 'Názov hostiteľa servera';
// Zabezpečenie
$labels['form.sieve.security'] = 'Zabezpečenie';
// Port
$labels['form.sieve.port'] = 'Port';
// Autorizácia
$labels['form.sieve.auth'] = 'Autorizácia';
// Ako IMAP
$labels['form.sieve.auth.imap'] = 'Ako IMAP';
// Žiadna
$labels['form.sieve.auth.none'] = 'Žiadna';
// Vlastná
$labels['form.sieve.auth.custom'] = 'Vlastná';
// Používateľské meno
$labels['form.sieve.username'] = 'Používateľské meno';
// Heslo
$labels['form.sieve.password'] = 'Heslo';
// Upozornenia
$labels['form.notify.caption'] = 'Upozornenia';
// Kontrolovať novú poštu
$labels['form.notify.check'] = 'Kontrolovať novú poštu';
// Fokus / favicon
$labels['form.notify.basic'] = 'Fokus / favicon';
// Zvuk
$labels['form.notify.sound'] = 'Zvuk';
// Upozornenie na ploche
$labels['form.notify.desktop'] = 'Upozornenie na ploche';
// Použiť predvolené
$labels['form.notify.default'] = 'predvolené';
// Zapnuté
$labels['form.notify.on'] = 'Zapnuté';
// Vypnuté
$labels['form.notify.off'] = 'Vypnuté';
// Vyžaduje plugin newmail_notifier
$labels['form.notify.requires_newmail_notifier'] = 'Upozornenia vyžadujú plugin newmail_notifier. Prosím, povoľte ho alebo kontaktujte administrátora.';
// Možnosti zabezpečenia
$labels['form.security.none'] = 'Žiadne';
$labels['form.security.starttls'] = 'STARTTLS';
$labels['form.security.ssl'] = 'SSL/TLS';
$labels['form.security.none_warning'] = 'Nešifrované pripojenia nie sú bezpečné. Vaše prihlasovacie údaje a e-maily môžu byť zachytené. Vždy, keď je to možné, použite SSL/TLS alebo STARTTLS.';
// Chyby
// Hodnota v poli 'Názov hostiteľa servera' je príliš dlhá (max. 64 znakov).
$labels['err.host.long'] = 'Hodnota v poli \'Názov hostiteľa servera\' je príliš dlhá (max. 64 znakov).';
// Hodnota v poli 'Port' musí byť číslo.
$labels['err.port.num'] = 'Hodnota v poli \'Port\' musí byť číslo.';
// Hodnota v poli 'Port' musí byť medzi 1 a 65535.
$labels['err.port.range'] = 'Hodnota v poli \'Port\' musí byť medzi 1 a 65535.';
// Pripojenie IMAP zlyhalo.
$labels['err.imap.connect'] = 'Pripojenie IMAP zlyhalo. Skontrolujte adresu servera, port a prihlasovacie údaje.';
// Pripojenie SMTP zlyhalo.
$labels['err.smtp.connect'] = 'Pripojenie SMTP zlyhalo. Skontrolujte adresu servera, port a prihlasovacie údaje.';
// Pripojenie Sieve zlyhalo.
$labels['err.sieve.connect'] = 'Pripojenie Sieve zlyhalo. Skontrolujte adresu servera, port a prihlasovacie údaje.';