Vai al contenuto

Traduzioni

Ogni stringa visibile all'utente che un plugin mostra dev'essere traducibile, con cataloghi per tutte e quindici le lingue supportate — en, pl, de, fr, es, pt_PT, pt_BR, nl, sv, nb, da, fi, it, cs, sk — prima che il plugin possa dirsi finito. È lo stesso metro dei test.

Cataloghi

Ogni plugin che abbia una qualsiasi stringa porta un catalogo .ts per lingua nella propria cartella Translations/:

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

Collegali alla compilazione tramite 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
)

La compilazione esegue lrelease per predisporre i file .qm; TranslationManager li carica per nome di catalogo a tempo di esecuzione (i cataloghi dei plugin sotto Plugins/Translations/<Plugin>/).

Marcare le stringhe per la traduzione

  • Preferisci QObject::tr(...) (contesto = la classe) per le normali stringhe dell'interfaccia.
  • L'ausilio tr_() avvolge QCoreApplication::translate("<Context>", s) per le stringhe fuori da un QObject.

tr_() è invisibile a lupdate

lupdate non riesce a risolvere il contesto dentro tr_(), quindi quei cataloghi si mantengono a mano. Mantieni il testo <source> identico byte per byte alla stringa a tempo di esecuzione, altrimenti la traduzione silenziosamente non verrà applicata.

Seguire un cambio di lingua mentre una pagina è aperta

L'utente può cambiare la lingua dell'interfaccia in Preferenze ▸ Generale senza riavviare. Qt invia allora un QEvent::LanguageChange a ogni widget — ma un albero di widget le cui stringhe sono state impostate una volta sola, nel codice che lo ha costruito, conserva la lingua precedente finché la finestra non viene chiusa e riaperta.

PluginApi/Qt/Retranslator.h se ne occupa senza costringerti a scrivere ogni stringa due volte. Registra come ciascuna stringa è stata prodotta e riproduce la registrazione quando la lingua cambia:

#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() esegue la sua lambda immediatamente, così il punto di chiamata si legge esattamente come la riga «imposta il testo» che sostituisce, e ogni stringa compare comunque una sola volta nei tuoi sorgenti.
  • row() fa lo stesso per la didascalia di un QFormLayout, che altrimenti diventa irraggiungibile una volta che addRow() l'ha consumata.
  • installOn() è idempotente per ciascun widget; il registratore è figlio di quel widget e muore con esso. Se la tua pagina può sopravvivere a un widget che hai catturato, conservalo in un QPointer.

Come PluginApi/Qt/ISettingsPage.h, questa è un'intestazione Qt opzionale: includila solo da codice che già costruisce dei QWidget (richiede Qt6::Widgets). La parte di PluginApi priva di Qt non ne è toccata.

Che cosa non viene tradotto

Due cose restano, per scelta, nella lingua in cui il loro autore le ha scritte:

  • Il name e la description del tuo plugin da plugin.json, come mostrati in Preferenze ▸ Estensioni. Il manifest viene letto prima che il plugin sia caricato — è questo che permette alla pagina di elencare i plugin disabilitati o compilati per un'altra versione dell'API — quindi a quel punto non esiste alcun catalogo in cui cercarli.
  • Le etichette di una pagina delle impostazioni o di un pannello ancorabile dichiarativi (Python). Sono dati che il tuo worker invia all'host, non stringhe che l'host possa risolvere rispetto a un catalogo.

Tutto ciò che un plugin registra a tempo di esecuzione — titoli dei comandi, voci di menu, titoli dei pannelli, didascalie delle pagine delle impostazioni — viene tradotto nel modo consueto descritto sopra.

Tre di quelle stringhe le cerca l'host, non il tuo codice, nel contesto condiviso PluginMenus: ogni segmento di un menuPath, ogni title di comando e la category del comando. Distribuisci tutte e tre come voci <source> nel contesto PluginMenus dei tuoi cataloghi. La categoria è ciò che l'utente legge nella colonna Categoria di Preferenze ▸ Scorciatoie; quando manca dal catalogo, la colonna mostra la parola inglese grezza accanto alle righe tradotte del nucleo. Una categoria che è anche un titolo di menu (Search, Encoding) condivide una sola voce: conserva al suo interno il mnemonico & per il menu, l'host lo rimuove per la colonna.

Definizione di «finito»

La localizzazione di un plugin è finita solo quando tutti e quindici i file .ts esistono, sono collegati e lrelease riporta 0 stringhe non finite.