Lokalizowanie wtyczek
Lokalizowanie wtyczek pozwala na dodanie obsługi wielu języków w obrębie danej wtyczki. Jeżeli przykładowo aktywnie wybrany język w komunikatorze AQQ to angielski, wtyczka również może się do tego języka dostosować tj. wyśiwetlać komunikaty w tym języku jak i przeprowadzić lokalizacje wszystkich kontrolek wyświetlających tekst na formatkach. Proces ten nie jest skomplikowany do wdrożenia zatem zacznijmy.
Krok 1 - LangAPI
W celu dodania obsługi wielu języków należy pobrać plik LangAPI.pas i dodać go do używanych unitów zarówno w głównym unicie wtyczki jak również w unitach wszystkich formatek które mają zostać zlokalizowane.
Krok 2 - Pliki językowe
Pliki językowe powinny być oczywiście dystrybuowane razem z wtyczką. Powinny być umieszczone w katalogu o nazwie "Languages". W tym folderze umieszczamy podfoldery o nazwach składających się z kodów karajów. Podfolder dla języka polskiego powinien nazywać się zatem "PL" a dla języka angielskiego "EN". Dopiero w tych podfolderach umieszczamy pliki językowe. Są dwa rodzaje plików językowych.

W pliku Const.lng który występuje pojedynczo umieszczamy wszystkie komunikaty które będą wyświetlane użytkownikowi (czyli np. przez funkcje ShowMessage). Struktura pliku jest banalna. Jedna linia w pliku to jeden komunikat. Format to identyfikator=treść. Przykład:
Month1=styczeń
Month2=luty
Month3=marzec
Month4=kwiecień
Month5=maj
Month6=czerwiec


Drugi typ pliku językowego dotyczy formatek (okien). Nazwa takiego pliku powinna odzwierciedlać klasę okna. Czyli np. TfrmMain.lng jeżeli klasa okna to TfrmMain. Format pliku również jest banalnie prosty jest to tagid=treść. Atrybut "Tag" posiada większość kontrolek wizualnych które są zazwyczaj używane (etykiety, pola wyboru, przyciski etc.). W danej formatce każdej kontrolce która ma zostać zlokalizowana przypisujemy inny numer Tag. Następnie do tych numerów przypisujemy treść w pliku językowym. Przykładowy plik językowy dla formatki wygląda zatem następująco:

0001=Konferencja GG
0002=Zaznacz kontakty, które chcesz zaprosić do rozmowy konferencyjnej:
0003=Zaproś
0004=Anuluj


Jeżeli przygotowałeś swoje pliki językowe nadszedł czas na ich użycie.
Krok 3 - Przygotowanie wtyczki
Kolejnym krokiem będzie sprawdzenie aktualnie używanej przez AQQ lokalizacji. W tym celu posłuży nam funkcja:

AQQ_FUNCTION_GETLANGCODE

Należy wywołać tą funkcje tuż po starcie wtyczki. Następnie musimy ustawić ścieżkę do plików językowych które mają zostać użyte w trakcie lokalizacji co ilustruje poniższy przykładowy kod:

LangCode := PWideChar(PluginLink.CallService(AQQ_FUNCTION_GETLANGCODE, 0, 0));
LangPath := IncludeTrailingPathDelimiter(ExtractFilePath(PlugPath)) + 'Languages\GGNet\' + LangCode + '\';
if not DirectoryExists(LangPath) then
  begin
    LangCode := PWideChar(PluginLink.CallService(AQQ_FUNCTION_GETDEFLANGCODE, 0, 0));
    LangPath := IncludeTrailingPathDelimiter(ExtractFilePath(PlugPath)) + 'Languages\GGNet\' + LangCode + '\';
  end;

To przykładowy kod z wtyczki GG która swoje pliki językowe trzyma w folderze Languages\GGNet. Tam znajdują się wcześniej opisane podfoldery z lokalizacjami (podfoldery PL, EN). Wtyczka składa zatem ścieżkę do plików językowych. Jeżeli taki folder nie istnieje - wówczas jest ustawiana lokalizacja domyślna - polska lub angielska. Należy zaznaczyć, że jeżeli wtyczka korzysta z LangAPI to MUSI bezwzględnie posiadać lokalizacje przynajmniej dla języka polskiego oraz angielskiego.
Krok 4 - Komunikaty
Gdy zajdzie potrzeba wyświetlenia komunikatu można tego dokonać w taki sposób:

PluginLink.CallService(AQQ_FUNCTION_SHOWMESSAGE, 0, DWORD(PWideChar(GetLangStr('Month1'))));

W tym wypadku wyświetlony komunikat to "styczeń" (przy użyciu naszego pliku językowego Const.lng dla polskiej lokalizacji (folder PL).
Krok 4 - Formatki (okna)
Jeżeli chodzi o lokalizowanie okien wystarczy przy ich tworzeniu wywołać funkcje LangForm.

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  LangForm(Self);
end;

Spowoduje to zlokalizowanie całego okna według pliku językowego - w tym wypadku TfrmMain.lng. Jeżeli chcemy zlokalizować ramkę osadzoną w oknie wówczas stosujemy funkcje LangFrame a nie LangForm.
Krok 5 - Natychmiastowa zmiana języka
Gdy użytkownik zmieni aktywny język w trakcie działania programu wtyczka powinna również odświeżyć wszystkie swoje otwarte okna i korzystać z nowej lokalizacji. Aby tego dokonać należy skorzystać z notyfikacji AQQ_SYSTEM_LANGCODE_CHANGED. Przykładowy kod dla tej notyfikacji może wyglądać w ten sposób:

function OnLangCodeChanged(wParam: Windows.WPARAM; lParam: Windows.LPARAM): NativeInt; stdcall;
var
  LangCode: String;
  I: Integer;
begin

ClearLngCache;

LangCode := PWideChar(lParam); LangPath := IncludeTrailingPathDelimiter(ExtractFilePath(PlugPath)) + 'Languages\GGNet\' + LangCode + '\';
if not DirectoryExists(LangPath) then
  begin
    LangCode := PWideChar(PluginLink.CallService(AQQ_FUNCTION_GETDEFLANGCODE, 0, 0));
    LangPath := IncludeTrailingPathDelimiter(ExtractFilePath(PlugPath)) + 'Languages\GGNet\' + LangCode + '\';
  end;

for i := 0 to Screen.FormCount - 1 do
  begin
    LangForm(Screen.Forms[i]);
  end;

Najpierw jest czyszczony kesz wyświetlonych wcześniej komunikatów przy pomocy funkcji ClearLngCache. Kesz pozwala zredukować odczyty z plików językowych. Następnie znów składana jest ścieżka do nowej lokalizacji w podobny sposób do tego co robiliśmy już na samym początku. I na koniec zachodzi iteracja wszystkich otwartych okien i ich ponowna lokalizacja.
Końcowe uwagi
Brawo! Twoja wtyczka została zlokalizowana. Pamiętaj jednak o kilku rzeczach. Jeżeli tworzysz jakieś skróty w popmenu komunikatora AQQ to przy zmianie lokalizacji przez użytkownika musisz je na nowo zlokalizować ręcznie np. przy użyciu funkcji AQQ_CONTROLS_EDITPOPUPMENUITEM oraz funkcji GetLangStr z LangAPI.pas. Zapewne zastanawiasz się jak zlokalizować listy rozwijane Combo. Również musisz to zrobić ręcznie i korzystać z funkcji GetLangStr dodając kolejne opcje do listy. Po zmianie lokalizacji je również musisz odświeżyć samodzielnie. Jest to jednak drobny procent roboty której nie zrobi za Ciebie LangAPI.