Przejdź do treści

Tłumaczenia

Każdy widoczny dla użytkownika string pokazywany przez wtyczkę musi być tłumaczalny, z katalogami dla wszystkich piętnastu obsługiwanych języków — en, pl, de, fr, es, pt_PT, pt_BR, nl, sv, nb, da, fi, it, cs, sk — zanim wtyczkę można uznać za skończoną. To ta sama poprzeczka co testy.

Katalogi

Każda wtyczka mająca jakikolwiek string niesie po jednym katalogu .ts na język w swoim folderze Translations/:

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

Podepnij je do builda przez 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
)

Build uruchamia lrelease, aby przygotować pliki .qm; TranslationManager ładuje je w czasie działania po nazwie katalogu (katalogi wtyczek pod Plugins/Translations/<Plugin>/).

Oznaczanie stringów do tłumaczenia

  • Dla zwykłych stringów UI preferuj QObject::tr(...) (kontekst = klasa).
  • Helper tr_() opakowuje QCoreApplication::translate("<Context>", s) dla stringów poza QObject.

tr_() jest niewidoczny dla lupdate

lupdate nie potrafi rozwiązać kontekstu wewnątrz tr_(), więc te katalogi utrzymywane są ręcznie. Utrzymuj tekst <source> bajt w bajt identyczny ze stringiem w czasie działania, inaczej tłumaczenie po cichu się nie zastosuje.

Nadążanie za zmianą języka przy otwartej stronie

Użytkownik może zmienić język interfejsu w Preferencjach ▸ Ogólne bez restartu. Qt wysyła wtedy QEvent::LanguageChange do każdego widgetu — ale drzewo widgetów, którego stringi ustawiono raz, w kodzie budującym je, zostaje przy starym języku aż do zamknięcia i ponownego otwarcia okna.

PluginApi/Qt/Retranslator.h rozwiązuje to bez pisania każdego stringu dwa razy. Zapamiętuje, jak powstał każdy string, i odtwarza to nagranie przy zmianie języka:

#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() uruchamia swoją lambdę od razu, więc miejsce wywołania czyta się dokładnie jak zastępowana linia „ustaw tekst", a każdy string nadal pojawia się w źródle raz.
  • row() robi to samo dla podpisu w QFormLayout, do którego po addRow() nie da się już inaczej dotrzeć.
  • installOn() jest idempotentne dla danego widgetu; rejestrator jest jego dzieckiem i ginie razem z nim. Jeśli strona może przeżyć przechwycony widget, trzymaj go w QPointer.

Podobnie jak PluginApi/Qt/ISettingsPage.h, jest to opcjonalny nagłówek Qt: dołączaj go tylko z kodu, który i tak buduje QWidget-y (wymaga Qt6::Widgets). Część PluginApi wolna od Qt pozostaje nietknięta.

Co nie jest tłumaczone

Dwie rzeczy z założenia zostają w języku, w którym napisał je autor:

  • name i description Twojej wtyczki z plugin.json, pokazywane w Preferencjach ▸ Wtyczki. Manifest jest czytany zanim wtyczka zostanie załadowana — właśnie dzięki temu strona wymienia także wtyczki wyłączone lub zbudowane dla innej wersji API — więc w tym momencie nie ma katalogu, w którym można by je odszukać.
  • Etykiety deklaratywnej (pythonowej) strony ustawień lub panelu doku. Są to dane, które Twój worker wysyła do hosta, a nie stringi, które host mógłby dopasować do katalogu.

Wszystko, co wtyczka rejestruje w czasie działania — tytuły poleceń, pozycje menu, tytuły doków, podpisy na stronie ustawień — jest tłumaczone w zwykły sposób, opisany wyżej.

Trzy z tych stringów wyszukuje host, nie Twój kod, we wspólnym kontekście PluginMenus: każdy segment menuPath, title polecenia i category polecenia. Wszystkie trzy dostarcz jako wpisy <source> w kontekście PluginMenus własnych katalogów. Kategorię użytkownik czyta w kolumnie Kategoria okna Preferencje ▸ Skróty; gdy brakuje jej w katalogu, kolumna pokazuje surowe angielskie słowo obok przetłumaczonych wierszy rdzenia. Kategoria, która jest zarazem tytułem menu (Search, Encoding), dzieli z nim jeden wpis: zostaw w nim mnemonik & dla menu, host zdejmie go w kolumnie.

Definicja ukończenia

Lokalizacja wtyczki jest skończona dopiero wtedy, gdy wszystkie piętnaście plików .ts istnieje, jest podpiętych, a lrelease raportuje 0 unfinished.