public function inPlaceEditLink($t, $withDiff = false, $key = null, $locale = null, $useDB = null, $group = null)
 {
     try {
         $this->suspendUsageLogging();
         $diff = '';
         if (!$t && $key) {
             if ($useDB === null) {
                 $useDB = $this->useDB;
             }
             list($namespace, $parsed_group, $item) = $this->parseKey($key);
             if ($group === null) {
                 $group = $parsed_group;
             } else {
                 $item = substr($key, strlen("{$group}."));
                 if ($namespace && $namespace !== '*') {
                     $group = substr($group, strlen("{$namespace}::"));
                 }
             }
             if ($this->manager && $group && $item && (!$this->manager->excludedPageEditGroup($group) || $withDiff)) {
                 if ($locale == null) {
                     $locale = $this->locale();
                 }
                 $t = $this->manager->missingKey($namespace, $group, $item, $locale, false, true);
                 if ($t && (!$t->exists || $t->value == '') && $namespace != '*') {
                     if (static::isLaravelNamespace($namespace)) {
                         // get the package definition, we don't have an override
                         $t->saved_value = parent::get($key, [], $locale);
                         $t->status = 0;
                         if ($withDiff) {
                             $diff = ' [' . $t->saved_value . ']';
                         }
                     }
                 }
             }
         }
         if ($t) {
             if ($withDiff && $diff === '') {
                 $diff = $t->saved_value == $t->value ? '' : ($t->saved_value === $t->value ? '' : ' [' . mb_renderDiffHtml($t->saved_value, $t->value) . ']');
             }
             $title = parent::get($this->packagePrefix . 'messages.enter-translation');
             if ($t->value === null) {
                 $t->value = '';
             }
             //$t->value = parent::get($key, $replace, $locale);
             $result = '<a href="#edit" class="vsch_editable status-' . ($t->status ?: 0) . ' locale-' . $t->locale . '" data-locale="' . $t->locale . '" ' . 'data-name="' . $t->locale . '|' . $t->key . '" id="' . $t->locale . "-" . str_replace('.', '-', $t->key) . '"  data-type="textarea" data-pk="' . ($t->id ?: 0) . '" ' . 'data-url="' . URL::action(ManagerServiceProvider::CONTROLLER_PREFIX . 'Vsch\\TranslationManager\\Controller@postEdit', array($t->group)) . '" ' . 'data-inputclass="editable-input" data-saved_value="' . htmlentities($t->saved_value, ENT_QUOTES, 'UTF-8', false) . '" ' . 'data-title="' . $title . ': [' . $t->locale . '] ' . $t->group . '.' . $t->key . '">' . ($t ? htmlentities($t->value, ENT_QUOTES, 'UTF-8', false) : '') . '</a> ' . $diff;
             return $result;
         }
         return '';
     } finally {
         $this->resumeUsageLogging();
     }
 }
    public function getIndex($group = null)
    {
        $locales = $this->locales;
        $currentLocale = \Lang::getLocale();
        $primaryLocale = $this->primaryLocale;
        $translatingLocale = $this->translatingLocale;
        $groups = array('' => noEditTrans($this->packagePrefix . 'messages.choose-group')) + $this->manager->getGroupList();
        if ($group != null && !array_key_exists($group, $groups)) {
            return \Redirect::action(ManagerServiceProvider::CONTROLLER_PREFIX . get_class($this) . '@getIndex');
        }
        $numChanged = $this->getTranslation()->where('group', $group)->where('status', Translation::STATUS_CHANGED)->count();
        // to allow proper handling of nested directory structure we need to copy the keys for the group for all missing
        // translations, otherwise we don't know what the group and key looks like.
        //$allTranslations = $this->getTranslation()->where('group', $group)->orderBy('key', 'asc')->get();
        $displayWhere = $this->displayLocales ? ' AND locale IN (\'' . implode("','", explode(',', $this->displayLocales)) . "')" : '';
        $ltm_translations = $this->manager->getTranslationsTableName();
        $allTranslations = $this->getTranslation()->hydrateRaw($sql = <<<SQL
SELECT * FROM {$ltm_translations} WHERE `group` = ? {$displayWhere}
UNION ALL
SELECT DISTINCT
    NULL id,
    NULL status,
    locale,
    `group`,
    `key`,
    NULL value,
    NULL created_at,
    NULL updated_at,
    NULL source,
    NULL saved_value,
    NULL is_deleted,
    NULL was_used
FROM
(SELECT * FROM (SELECT DISTINCT locale FROM {$ltm_translations} WHERE 1=1 {$displayWhere}) lcs
    CROSS JOIN (SELECT DISTINCT `group`, `key` FROM {$ltm_translations} WHERE `group` = ? {$displayWhere}) grp) m
WHERE NOT EXISTS(SELECT * FROM {$ltm_translations} t WHERE t.locale = m.locale AND t.`group` = m.`group` AND t.`key` = m.`key`)
ORDER BY `key` ASC
SQL
, [$group, $group], $this->getConnectionName());
        $numTranslations = count($allTranslations);
        $translations = array();
        foreach ($allTranslations as $translation) {
            $translations[$translation->key][$translation->locale] = $translation;
        }
        $this->manager->cacheGroupTranslations($group, $this->displayLocales, $translations);
        $stats = $this->getConnection()->select(<<<SQL
SELECT (mx.total_keys - lcs.total) missing, lcs.changed, lcs.cached, lcs.deleted, lcs.locale, lcs.`group`
FROM
    (SELECT sum(total) total, sum(changed) changed, sum(cached) cached, sum(deleted) deleted, `group`, locale
     FROM
         (SELECT count(value) total,
          sum(CASE WHEN status = 1 THEN 1 ELSE 0 END) changed,
          sum(CASE WHEN status = 2 AND value IS NOT NULL THEN 1 ELSE 0 END) cached,
         sum(is_deleted) deleted,
         `group`, locale
                FROM {$ltm_translations} lt WHERE 1=1 {$displayWhere} GROUP BY `group`, locale
          UNION ALL
          SELECT DISTINCT 0, 0, 0, 0, `group`, locale FROM (SELECT DISTINCT locale FROM {$ltm_translations} WHERE 1=1 {$displayWhere}) lc
              CROSS JOIN (SELECT DISTINCT `group` FROM {$ltm_translations}) lg) a
     GROUP BY `group`, locale) lcs
    JOIN (SELECT count(DISTINCT `key`) total_keys, `group` FROM {$ltm_translations} WHERE 1=1 {$displayWhere} GROUP BY `group`) mx
        ON lcs.`group` = mx.`group`
WHERE lcs.total < mx.total_keys OR lcs.changed > 0 OR lcs.cached > 0 OR lcs.deleted > 0
SQL
);
        // returned result set lists mising, changed, group, locale
        $summary = [];
        foreach ($stats as $stat) {
            if (!isset($summary[$stat->group])) {
                $item = $summary[$stat->group] = new \stdClass();
                $item->missing = '';
                $item->changed = '';
                $item->cached = '';
                $item->deleted = '';
                $item->group = $stat->group;
            }
            $item = $summary[$stat->group];
            if ($stat->missing) {
                $item->missing .= $stat->locale . ":" . $stat->missing . " ";
            }
            if ($stat->changed) {
                $item->changed .= $stat->locale . ":" . $stat->changed . " ";
            }
            if ($stat->cached) {
                $item->cached .= $stat->locale . ":" . $stat->cached . " ";
            }
            if ($stat->deleted) {
                $item->deleted .= $stat->locale . ":" . $stat->deleted . " ";
            }
        }
        $mismatches = null;
        $mismatchEnabled = $this->manager->config('mismatch_enabled');
        if ($mismatchEnabled) {
            // get mismatches
            $mismatches = $this->getConnection()->select(<<<SQL
SELECT DISTINCT lt.*, ft.ru, ft.en
FROM (SELECT * FROM {$ltm_translations} WHERE 1=1 {$displayWhere}) lt
    JOIN
    (SELECT DISTINCT mt.`key`, BINARY mt.ru ru, BINARY mt.en en
     FROM (SELECT lt.`group`, lt.`key`, group_concat(CASE lt.locale WHEN '{$primaryLocale}' THEN VALUE ELSE NULL END) en, group_concat(CASE lt.locale WHEN '{$translatingLocale}' THEN VALUE ELSE NULL END) ru
           FROM (SELECT value, `group`, `key`, locale FROM {$ltm_translations} WHERE 1=1 {$displayWhere}
                 UNION ALL
                 SELECT NULL, `group`, `key`, locale FROM ((SELECT DISTINCT locale FROM {$ltm_translations} WHERE 1=1 {$displayWhere}) lc
                     CROSS JOIN (SELECT DISTINCT `group`, `key` FROM {$ltm_translations} WHERE 1=1 {$displayWhere}) lg)
                ) lt
           GROUP BY `group`, `key`) mt
         JOIN (SELECT lt.`group`, lt.`key`, group_concat(CASE lt.locale WHEN '{$primaryLocale}' THEN VALUE ELSE NULL END) en, group_concat(CASE lt.locale WHEN '{$translatingLocale}' THEN VALUE ELSE NULL END) ru
               FROM (SELECT value, `group`, `key`, locale FROM {$ltm_translations} WHERE 1=1 {$displayWhere}
                     UNION ALL
                     SELECT NULL, `group`, `key`, locale FROM ((SELECT DISTINCT locale FROM {$ltm_translations} WHERE 1=1 {$displayWhere}) lc
                         CROSS JOIN (SELECT DISTINCT `group`, `key` FROM {$ltm_translations} WHERE 1=1 {$displayWhere}) lg)
                    ) lt
               GROUP BY `group`, `key`) ht ON mt.`key` = ht.`key`
     WHERE (mt.ru NOT LIKE BINARY ht.ru AND mt.en LIKE BINARY ht.en) OR (mt.ru LIKE BINARY ht.ru AND mt.en NOT LIKE BINARY ht.en)
    ) ft
        ON (lt.locale = '{$translatingLocale}' AND lt.value LIKE BINARY ft.ru) AND lt.`key` = ft.key
ORDER BY `key`, `group`
SQL
);
            $key = '';
            $rus = [];
            $ens = [];
            $rubases = [];
            // by key
            $enbases = [];
            // by key
            $extra = new \stdClass();
            $extra->key = '';
            $mismatches[] = $extra;
            foreach ($mismatches as $mismatch) {
                if ($mismatch->key !== $key) {
                    if ($key) {
                        // process diff for key
                        $txtru = '';
                        $txten = '';
                        if (count($ens) > 1) {
                            $maxen = 0;
                            foreach ($ens as $en => $cnt) {
                                if ($maxen < $cnt) {
                                    $maxen = $cnt;
                                    $txten = $en;
                                }
                            }
                            $enbases[$key] = $txten;
                        } else {
                            $txten = array_keys($ens)[0];
                            $enbases[$key] = $txten;
                        }
                        if (count($rus) > 1) {
                            $maxru = 0;
                            foreach ($rus as $ru => $cnt) {
                                if ($maxru < $cnt) {
                                    $maxru = $cnt;
                                    $txtru = $ru;
                                }
                            }
                            $rubases[$key] = $txtru;
                        } else {
                            $txtru = array_keys($rus)[0];
                            $rubases[$key] = $txtru;
                        }
                    }
                    $key = $mismatch->key;
                    $rus = [];
                    $ens = [];
                }
                if ($mismatch->key === '') {
                    break;
                }
                if (!isset($ens[$mismatch->en])) {
                    $ens[$mismatch->en] = 1;
                } else {
                    $ens[$mismatch->en]++;
                }
                if (!isset($rus[$mismatch->ru])) {
                    $rus[$mismatch->ru] = 1;
                } else {
                    $rus[$mismatch->ru]++;
                }
            }
            array_splice($mismatches, count($mismatches) - 1, 1);
            foreach ($mismatches as $mismatch) {
                $mismatch->en_value = $mismatch->ru;
                $mismatch->en = mb_renderDiffHtml($enbases[$mismatch->key], $mismatch->en);
                $mismatch->ru_value = $mismatch->ru;
                $mismatch->ru = mb_renderDiffHtml($rubases[$mismatch->key], $mismatch->ru);
            }
        }
        // returned result set lists group key ru, en columns for the locale translations, ru has different values for same values in en
        $displayLocales = array_intersect($locales, explode(',', $this->displayLocales));
        // need to put display locales first in the $locales list
        $locales = array_merge($displayLocales, array_diff($locales, $displayLocales));
        $displayLocales = array_combine($displayLocales, $displayLocales);
        $show_usage_enabled = $this->manager->config('log_key_usage_info', false);
        return \View::make($this->packagePrefix . 'index')->with('controller', ManagerServiceProvider::CONTROLLER_PREFIX . get_class($this))->with('package', $this->package)->with('public_prefix', ManagerServiceProvider::PUBLIC_PREFIX)->with('translations', $translations)->with('yandex_key', !!$this->manager->config('yandex_translator_key'))->with('locales', $locales)->with('primaryLocale', $primaryLocale)->with('currentLocale', $currentLocale)->with('translatingLocale', $translatingLocale)->with('displayLocales', $displayLocales)->with('groups', $groups)->with('group', $group)->with('numTranslations', $numTranslations)->with('numChanged', $numChanged)->with('adminEnabled', $this->manager->config('admin_enabled') && UserCan::admin_translations())->with('mismatchEnabled', $mismatchEnabled)->with('stats', $summary)->with('mismatches', $mismatches)->with('show_usage', $this->showUsageInfo && $show_usage_enabled)->with('usage_info_enabled', $show_usage_enabled)->with('connection_list', $this->connectionList)->with('transFilters', $this->transFilters)->with('connection_name', $this->getConnectionName());
    }