Exemple #1
0
int QAChecker::Check(CatalogItemPtr item)
{
    int issues = 0;

    for (auto& c: m_checks)
    {
        if (item->GetString().empty() || (item->HasPlural() && item->GetPluralString().empty()))
            continue;

        if (c->CheckItem(item))
            issues++;
    }

    return issues;
}
Exemple #2
0
 void Update(const CatalogItemPtr& item) override
 {
     auto text = CommentDialog::RemoveStartHash(item->GetComment());
     text.Trim();
     m_comment->SetLanguage(m_parent->GetCurrentLanguage());
     m_comment->SetAndWrapText(text);
 }
Exemple #3
0
    bool CheckString(CatalogItemPtr item, const wxString& source, const wxString& translation) override
    {
        if (u_isupper(source[0]) && u_islower(translation[0]))
        {
            item->SetIssue(CatalogItem::Issue::Warning, _("The translation should start as a sentence."));
            return true;
        }

        if (u_islower(source[0]) && u_isupper(translation[0]))
        {
            if (m_lang != "de")
            {
                item->SetIssue(CatalogItem::Issue::Warning, _("The translation should start with a lowercase character."));
                return true;
            }
            // else: German nouns start uppercased, this would cause too many false positives
        }

        return false;
    }
Exemple #4
0
 void Update(const CatalogItemPtr& item) override
 {
 #ifdef __WXMSW__
     auto add = _("Add comment");
     auto edit = _("Edit comment");
 #else
     auto add = _("Add Comment");
     auto edit = _("Edit Comment");
 #endif
     m_btn->SetLabel(item->HasComment() ? edit : add);
 }
Exemple #5
0
 void Update(const CatalogItemPtr& item) override
 {
     auto comment = wxJoin(item->GetExtractedComments(), '\n', '\0');
     if (comment.StartsWith("TRANSLATORS:") || comment.StartsWith("translators:"))
     {
         comment.Remove(0, 12);
         if (!comment.empty() && comment[0] == ' ')
             comment.Remove(0, 1);
     }
     m_comment->SetAndWrapLabel(comment);
 }
Exemple #6
0
    bool CheckItem(CatalogItemPtr item) override
    {
        if (!item->HasPlural())
            return false;

        bool foundTranslated = false;
        bool foundEmpty = false;
        for (auto& s: item->GetTranslations())
        {
            if (s.empty())
                foundEmpty = true;
            else
                foundTranslated = true;
        }

        if (foundEmpty && foundTranslated)
        {
            item->SetIssue(CatalogItem::Issue::Warning, _("Not all plural forms are translated."));
            return true;
        }

        return false;
    }
Exemple #7
0
void SuggestionsSidebarBlock::QueryProvider(SuggestionsBackend& backend, const CatalogItemPtr& item, uint64_t queryId)
{
    m_pendingQueries++;

    // we need something to talk to GUI thread through that is guaranteed
    // to exist, and the app object is a good choice:
    auto backendPtr = &backend;
    std::weak_ptr<SuggestionsSidebarBlock> weakSelf = std::dynamic_pointer_cast<SuggestionsSidebarBlock>(shared_from_this());

    m_provider->SuggestTranslation
    (
        backend,
        m_parent->GetCurrentSourceLanguage(),
        m_parent->GetCurrentLanguage(),
        item->GetString().ToStdWstring(),

        // when receiving data
        [=](const SuggestionsList& hits){
            call_on_main_thread([weakSelf,queryId,hits]{
                auto self = weakSelf.lock();
                // maybe this call is already out of date:
                if (!self || self->m_latestQueryId != queryId)
                    return;
                self->UpdateSuggestions(hits);
                if (--self->m_pendingQueries == 0)
                    self->OnQueriesFinished();
            });
        },

        // on error:
        [=](std::exception_ptr e){
            call_on_main_thread([weakSelf,queryId,backendPtr,e]{
                auto self = weakSelf.lock();
                // maybe this call is already out of date:
                if (!self || self->m_latestQueryId != queryId)
                    return;
                self->ReportError(backendPtr, e);
                if (--self->m_pendingQueries == 0)
                    self->OnQueriesFinished();
            });
        }
    );
}
Exemple #8
0
bool QACheck::CheckItem(CatalogItemPtr item)
{
    if (!item->GetTranslation().empty() && CheckString(item, item->GetString(), item->GetTranslation()))
        return true;

    if (item->HasPlural())
    {
        unsigned count = item->GetNumberOfTranslations();
        for (unsigned i = 1; i < count; i++)
        {
            auto t = item->GetTranslation(i);
            if (!t.empty() && CheckString(item, item->GetPluralString(), t))
                return true;
        }
    }

    return false;
}
Exemple #9
0
    bool CheckString(CatalogItemPtr item, const wxString& source, const wxString& translation) override
    {
        if (u_isspace(source[0]) && !u_isspace(translation[0]))
        {
            item->SetIssue(CatalogItem::Issue::Warning, _(L"The translation doesn’t start with a space."));
            return true;
        }

        if (!u_isspace(source[0]) && u_isspace(translation[0]))
        {
            item->SetIssue(CatalogItem::Issue::Warning, _(L"The translation starts with a space, but the source text doesn’t."));
            return true;
        }

        if (source.Last() == '\n' && translation.Last() != '\n')
        {
            item->SetIssue(CatalogItem::Issue::Warning, _(L"The translation is missing a newline at the end."));
            return true;
        }

        if (source.Last() != '\n' && translation.Last() == '\n')
        {
            item->SetIssue(CatalogItem::Issue::Warning, _(L"The translation ends with a newline, but the source text doesn’t."));
            return true;
        }

        if (u_isspace(source.Last()) && !u_isspace(translation.Last()))
        {
            item->SetIssue(CatalogItem::Issue::Warning, _(L"The translation is missing a space at the end."));
            return true;
        }

        if (!u_isspace(source.Last()) && u_isspace(translation.Last()))
        {
            item->SetIssue(CatalogItem::Issue::Warning, _(L"The translation ends with a space, but the source text doesn’t."));
            return true;
        }

        return false;
    }
Exemple #10
0
    bool CheckString(CatalogItemPtr item, const wxString& source, const wxString& translation) override
    {
        const UChar32 s_last = source.Last();
        const UChar32 t_last = translation.Last();
        const bool s_punct = u_ispunct(s_last);
        const bool t_punct = u_ispunct(t_last);

        if (u_getIntPropertyValue(s_last, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_CLOSE ||
            u_getIntPropertyValue(t_last, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_CLOSE)
        {
            // too many reordering related false positives for brackets
            // e.g. "your {site} account" -> "váš účet na {site}"
            if ((wchar_t)u_getBidiPairedBracket(s_last) != (wchar_t)source[0])
            {
                return false;
            }
            else
            {
                // OTOH, it's desirable to check strings fully enclosed in brackets like "(unsaved)"
                if (source.find_first_of((wchar_t)s_last, 1) != source.size() - 1)
                {
                    // it's more complicated, possibly something like "your {foo} on {bar}"
                    return false;
                }
            }
        }

        if (u_hasBinaryProperty(s_last, UCHAR_QUOTATION_MARK) || (!s_punct && u_hasBinaryProperty(t_last, UCHAR_QUOTATION_MARK)))
        {
            // quoted fragments can move around, e.g., so ignore quotes in reporting:
            //      >> Invalid value for ‘{fieldName}’​ field
            //      >> Valor inválido para el campo ‘{fieldName}’
            // TODO: count quote characters to check if used correctly in translation; don't check position
            return false;
        }

        if (s_punct && !t_punct)
        {
            item->SetIssue(CatalogItem::Issue::Warning,
                           wxString::Format(_(L"The translation should end with “%s”."), wxString(wxUniChar(s_last))));
            return true;
        }
        else if (!s_punct && t_punct)
        {
            item->SetIssue(CatalogItem::Issue::Warning,
                           wxString::Format(_(L"The translation should not end with “%s”."), wxString(wxUniChar(t_last))));
            return true;
        }
        else if (s_punct && t_punct && s_last != t_last)
        {
            if (t_last == L'…' && source.EndsWith("..."))
            {
                // as a special case, allow translating ... (3 dots) as … (ellipsis)
            }
            else if (u_hasBinaryProperty(s_last, UCHAR_QUOTATION_MARK) && u_hasBinaryProperty(t_last, UCHAR_QUOTATION_MARK))
            {
                // don't check for correct quotes for now, accept any quotations marks as equal
            }
            else if (IsEquivalent(s_last, t_last))
            {
                // some characters are mostly equivalent and we shouldn't warn about them
            }
            else
            {
                item->SetIssue(CatalogItem::Issue::Warning,
                               wxString::Format(_(L"The translation ends with “%s”, but the source text ends with “%s”."),
                                                wxString(wxUniChar(t_last)), wxString(wxUniChar(s_last))));
                return true;
            }
        }

        return false;
    }
Exemple #11
0
 void Update(const CatalogItemPtr& item) override
 {
     auto text = CommentDialog::RemoveStartHash(item->GetComment());
     text.Trim();
     m_comment->SetAndWrapLabel(text);
 }
Exemple #12
0
 bool ShouldShowForItem(const CatalogItemPtr& item) const override
 {
     return item->HasComment();
 }
Exemple #13
0
 void Update(const CatalogItemPtr& item) override
 {
     auto txt = wxJoin(item->GetOldMsgid(), ' ', '\0');
     m_text->SetAndWrapLabel(txt);
 }
Exemple #14
0
 bool ShouldShowForItem(const CatalogItemPtr& item) const override
 {
     return item->HasOldMsgid();
 }
Exemple #15
0
 void Update(const CatalogItemPtr& item) override
 {
     m_text->SetAndWrapLabel(item->GetOldMsgid());
 }