Pular para conteúdo

Traduções

Toda cadeia visível ao usuário que um plugin exibe precisa ser traduzível, com catálogos para os quinze idiomas suportados — en, pl, de, fr, es, pt_PT, pt_BR, nl, sv, nb, da, fi, it, cs, sk — antes de o plugin ser considerado pronto. Esse é o mesmo padrão dos testes.

Catálogos

Cada plugin que tem alguma cadeia carrega um catálogo .ts por idioma na pasta Translations/ dele:

Translations/
  MyPlugin_en.ts
  MyPlugin_pl.ts
  MyPlugin_de.ts
  MyPlugin_fr.ts

Conecte-os à compilação via mte_add_plugin:

mte_add_plugin(NAME MyPlugin
    SOURCES Src/MyPlugin.cpp
    TRANSLATIONS
        Translations/MyPlugin_en.ts
        Translations/MyPlugin_pl.ts
        Translations/MyPlugin_de.ts
        Translations/MyPlugin_fr.ts
)

A compilação executa o lrelease para preparar os arquivos .qm; o TranslationManager os carrega por nome de catálogo em tempo de execução (os catálogos de plugin ficam sob Plugins/Translations/<Plugin>/).

Marcando cadeias para tradução

  • Prefira QObject::tr(...) (contexto = a classe) para as cadeias de interface normais.
  • O auxiliar tr_() envolve QCoreApplication::translate("<Context>", s) para cadeias fora de um QObject.

tr_() é invisível para o lupdate

O lupdate não consegue resolver o contexto dentro de tr_(), então esses catálogos são mantidos à mão. Mantenha o texto de <source> idêntico byte a byte à cadeia em tempo de execução, ou a tradução simplesmente não se aplica, sem avisar.

Acompanhando uma mudança de idioma com uma página aberta

O usuário pode mudar o idioma da interface em Preferências ▸ Geral sem reiniciar. O Qt então envia QEvent::LanguageChange a todos os widgets — mas uma árvore de widgets cujas cadeias foram definidas uma única vez, no código que a construiu, mantém o idioma antigo até a caixa de diálogo ser fechada e reaberta.

O PluginApi/Qt/Retranslator.h cuida disso sem escrever cada cadeia duas vezes. Ele registra como cada cadeia foi produzida e reproduz o registro quando o idioma muda:

#include <PluginApi/Qt/Retranslator.h>

QWidget* MyPage::createWidget(QWidget* parent)
{
    auto* page = new QWidget(parent);
    auto& rt   = MTE::plugin::Retranslator::installOn(page);

    m_watch = new QCheckBox(page);
    rt.add([this] { m_watch->setText(tr_("Watch open files")); });

    m_size = new QSpinBox(page);
    rt.row(form, m_size, [] { return tr_("Font size:"); });   // QFormLayout caption

    return page;
}
  • add() executa a lambda dele imediatamente, então o ponto de chamada se lê exatamente como a linha de "defina o texto" que ele substitui, e cada cadeia ainda aparece uma vez no seu código-fonte.
  • row() faz o mesmo para um rótulo de QFormLayout, que de outro modo fica inalcançável depois que o addRow() o consumiu.
  • installOn() é idempotente por widget; o gravador é filho daquele widget e morre com ele. Se sua página pode sobreviver a um widget que você capturou, guarde-o em um QPointer.

Como o PluginApi/Qt/ISettingsPage.h, este é um cabeçalho opcional do Qt: inclua-o apenas a partir de código que já constrói QWidgets (ele precisa de Qt6::Widgets). A parte do PluginApi livre de Qt não é afetada.

O que não é traduzido

Duas coisas permanecem no idioma em que o autor as escreveu, por design:

  • O name e a description do seu plugin, do plugin.json, como exibidos em Preferências ▸ Plug-ins. O manifesto é lido antes de o plugin ser carregado — é isso que permite que a página liste plugins desativados ou compilados contra outra versão da API — então não há catálogo em que procurá-los naquele momento.
  • Os rótulos de uma página de configurações ou painel acoplável declarativo (de Python). Eles são dados que o seu trabalhador envia ao host, não cadeias que o host possa resolver contra um catálogo.

Tudo o que um plugin registra em tempo de execução — títulos de comandos, entradas de menu, títulos de painéis, rótulos de páginas de configurações — é traduzido da forma comum descrita acima.

Três dessas cadeias são procuradas pelo host, não pelo seu código, no contexto compartilhado PluginMenus: cada segmento de um menuPath, cada title de comando e a category do comando. Distribua as três como entradas <source> no contexto PluginMenus dos seus próprios catálogos. A categoria é o que o usuário lê na coluna Categoria de Preferências ▸ Atalhos; quando ela falta no catálogo, a coluna mostra a palavra inglesa crua ao lado das linhas traduzidas do núcleo. Uma categoria que também é um título de menu (Search, Encoding) compartilha uma única entrada: mantenha nela o mnemônico & para o menu, o host o remove para a coluna.

Definição de pronto

A localização de um plugin só está pronta quando os quinze arquivos .ts existem, estão conectados, e o lrelease reporta 0 cadeias não terminadas.