Plik do tłumaczenia aplikacji

0

Cześć, właśnie zacząłem pisać aplikacje desktopową i wpadłem na pomysł aby zrobić aplikacje, którą każdy może przetłumaczyć na swój język. Do spolszczenia będą wszystkie kontrolki na formie (labelki, buttony, itd..), więc użyłem do tego pliku .xml, w którym gromadzę całe tłumaczenie, wygląda on tak.

<?xml version="1.0" encoding="utf-8"?>
  <language value="pl">
	  <key id="LoginGroup" value="Logowanie" />
	  <key id="LoginLabel" value="Login />
    <key id="PasswordLabel" value="Hasło" />
  </language>

Użytkownik po odpaleniu aplikacji będzie mógł wybrać język i w tym momencie muszę jakoś mieć dostęp do wszystkich kontrolek na wszystkich formach. Próbowałem to zrobić przy użyciu refleksji na form ale wszystkie kontrolki są prywatne. Próbowałem też robić w ten sposób

            var t = Type.GetType("Form1");
            var form = (Form1)Activator.CreateInstance(t);
            form.Controls.Find("LoginLabel", true)[0].Text = "razdwa";

ale niestety żadnych zmian na formach. Może macie pomysł w jaki inny sposób mogę zmieniać tekst na wszystkich kontrolkach w aplikacji? Z góry dzięki!

3

Po pierwsze zmiany raczej są, tylko Ty nie wyświetlasz tego dynamicznie utworzonego forma. ;]
Po drugie, jeżeli już się tak bawić, to klasa okienka powinna dostać z zewnątrz, albo móc pobrać sobie swoje zależności, nie odwrotnie.
Po trzecie, użyj wbudowanego w .NET mechanizmu Resources.

0

Z plikami .resx myślałem ale chce dać możliwość łatwego przetłumaczenia aplikacji dla każdego użytkownika a tutaj nie wiem czy to wyjdzie.

Mógłbyś zademonstrować co masz na myśli? Po drugie, jeżeli już się tak bawić, to klasa okienka powinna dostać z zewnątrz, albo móc pobrać sobie swoje zależności, nie odwrotnie.

Dzięki!

0

Udało mi się dostać do kontrolek gdy w Form1 zrobiłem metode ChangeLanguage(Form form), której przekazuje przez referencję Form1. Wtedy wszystko pięknie działa ale zastanawiam się jak to będzie wyglądać, gdy będę miał otwartych 10 Form'ów a z Form1 będę zmieniał język na wszystkich...

2
Słaby gracz napisał(a):

Z plikami .resx myślałem ale chce dać możliwość łatwego przetłumaczenia aplikacji dla każdego użytkownika a tutaj nie wiem czy to wyjdzie.

resx to przecież też XML tylko o określonej strukturze. :)

Mógłbyś zademonstrować co masz na myśli? Po drugie, jeżeli już się tak bawić, to klasa okienka powinna dostać z zewnątrz, albo móc pobrać sobie swoje zależności, nie odwrotnie.

Chodzi mi o to, że jak już bardzo chcesz ręcznie, to robisz to np. tak:

  1. Obiekt MyFormResources z właściwościami ButtonSaveText, LabelInfoText, itd, wczytujesz z pliku.
  2. Ten obiekt przypisujesz do właściwości klasy MyForm (albo przekazujesz przez konstruktor), a tam już jest taka logika:
public MyFormResources
{
    set 
    {
        this.buttonSave.Text = value.ButtonSaveText;
        this.labelInfo.Text = value.LabelInfoText;
    }
}

Ale najlepiej chyba zrobić tak, jak działa standardowy mechanizm - jedna globalna klasa z wszystkimi zasobami, kod GUI się do niej odwołuje (this.buttonSave.Text = GlobalResourcesMagicManager.MyFormButtonSaveText;), a zmiana języka to operacja tylko w ramach tej klasy. Np. wywołujesz GlobalResourcesMagicManager.SetLanguage("de") i ona wtedy wczytuje plik z językiem niemieckim, i od tej pory jej właściwości zwracają niemieckie teksty.

0

Zrobiłem to trochę na inny sposób, trochę dziwny ale działa :). Mianowicie stworzyłem statyczną listę form'ów, która jest uzupełniana form'em przy każdym jego wywołaniu i przy każdej zmianie języka wykonywana funkcja bierze z listy każdego form'a, wyszukuje w nim wszystkie kontrolki jakie są i tłumaczy. W sumie po twojemu też jest fajnie :P, dzięki!

0

Oj zupełnie nie tak. Po pierwsze - mógłbyś zapoznać się z wbudowanymi mechanizmami (ja tego nie zrobiłem). Po drugie, jeśli chcesz robić po swojemu, to nie tak. Stwórz sobie tego xmla, ale inaczej:

    <LoginGroup>Logowanie</LoginGroup>
    <PasswordLabel>Hasło</PasswordLabel>

Czyli zamiast atrybutów w taki sposób. Tak jest wg mnie czytelniej.
Następnie, musisz mieć jakiś obiekt (singleton), który zwraca Ci odpowiedni string. Ten obiekt musi najpierw zaczytać całego tego XMLa najlepiej do jakiegoś słownika tak, że kluczem jest np. "PasswordLabel", a wartością "Hasło".
Obiekt ma jakąś metodę, np. Translate, która przyjmuje klucz i zwraca wartość:

 
  passLabel.Text = Translator.Get.Translate("PasswordLabel", "Pass");

Translator - tak nazwałem tą klasę do tłumaczenia
Get - właściwość klasy, która zwraca Ci instancję singletona
Translate - metoda, która zwraca Ci tłumaczenie. W pierwszym parametrze przyjmuje klucz, w drugim może np. przyjąć domyślną wartość - zwróci ją, jeśli takiego klucza nie ma.

Formy muszą mieć jakąś metodę, w której przypisują sobie teksty statycznych kontrolek. Metoda jest wywoływana w konstruktorze albo jakoś tak.

0

@Juhas, przy takim podejściu bardzo łatwo o błędy w postaci literówek. Naprawdę lepiej każdy zasób opakować w jakąś właściwość.

1 użytkowników online, w tym zalogowanych: 0, gości: 1