Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [klasa PHP5] Klasa wspierająca wielojęzykowość, Klasa w teorii ma ułatwić dodawanie wielojęzykowych elementów tekstowy
everth
post
Post #1





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

Ostrzeżenie: (0%)
-----


Poniższa klasa powinna pomóc w tworzeniu wielojęzykowych stron.

Przy projektowaniu wzorowałem się na podobnej funkcji w bibliotece Qt4 - gdzie metoda tr() ułatwia znacznie tworzenie templatek z tłumaczeniami, właściwie bez ingerencji w kod. Moja klasa próbuje to (trochę nieporadnie, ale cóż) zaimplementować w PHP. Główne założenia:
  • niezależność od źródła danych (wydzielony interfejs dla modelu danych z tłumaczeniami)
  • łatwość użycia w kodzie (szybka skrótowa funkcja $U())
  • automatyczne tworzenie bazy na podstawie wpisów w kodzie (w trybie appendMode dodajemy unikatowe ID i (opcjonalnie) tłumaczenie)
  • dobra dokumentacja - na obecnym etapie podstawowa dokumentacja w phpDoc
  • elastyczność - klasa w zasadzie projektowana była dla statycznych elementów tekstowych (napisy na przyciskach, napisy w stopce, itd.), ale ponieważ są to ciągi tekstowe to z łatwością można sobie dostosować np. do przechowywania ścieżek do plików graficznych z różnymi napisami, przy odrobinie wysiłku można w ten sposób dodawać nawet artykuły wielojęzykowe (po prostu generujemy ID dla artykułu i zawijamy w funkcję $U() - np. $U('12334') - później tworzymy wersje językowe dla tego ID)

Przykładowa baza w sql na początku ma dwie kolumny - id z identyfikatorami oraz kolumnę aktualnego języka (np. "pl_PL"), dodając nową kolumnę - dodajemy nowy język, według mnie ułatwia to tworzenie i edycję arkusza z tłumaczeniami np. w Excelu lub Calcu (po przerzuceniu tabeli w CSV). Przykładowa struktura:
  1. CREATE TABLE `Translations` (
  2. `id` varchar(40) CHARACTER SET latin1 NOT NULL,
  3. `pl_PL` mediumtext, -- nie jestem w stanie określić jak długie mogą być ciągi tekstowe tutaj
  4. `en_GB` mediumtext,
  5. PRIMARY KEY (`id`)
  6. ) ENGINE=MyISAM DEFAULT CHARSET=utf8

Przykładowe użycie:
  1. //Z użyciem trybu appendMode (dodajemy UIDy oraz przykładowe tłumaczenia w polskim)
  2. $locale = new Translation($pdo);
  3. $locale->setLang('pl_PL');
  4. $locale->appendMode(1); //włączamy appendMode
  5. $locale->setup();
  6.  
  7. echo <<<EB
  8. <ul>
  9. <li>{$U('M_HOME','Główna')}</li>
  10. <li>{$U('M_ABOUT','O nim')}</li>
  11. <li>{$U('M_PORTFOLIO','Portfolio')}</li>
  12. </ul>
  13. EB;
  14.  
  15. //Bez appendMode - sam odczyt UIDów (w przypadku braku pusty string)
  16. $locale->__destruct(); //niestety obiekty Translation nie tolerują żadnego ponownego wywołania bez ręcznego zniszczenia poprzedniej instancji - a ponieważ obiekt tworzy co najmniej 2 referencje do siebie to metoda unset() zawodzi, niestety to obecnie najsłabsze ogniwo - nie powinno się tworzyć więcej niż jedną instancję w przebiegu skryptu!
  17. $locale = new Translation($pdo);
  18. $locale->setLang('pl_PL');
  19. $locale->setup();
  20. echo <<<EB
  21. <ul>
  22. <li>{$U('M_HOME')}</li>
  23. <li>{$U('M_ABOUT')}</li>
  24. <li>{$U('M_PORTFOLIO')}</li>
  25. </ul>
  26. EB;

Kod źródłowy Translation wraz z klasami pomocniczymi jest pod tym linkiem
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
everth
post
Post #2





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

Ostrzeżenie: (0%)
-----


  1. Akurat skrótowiec jest główną osią tego obiektu (patrz tr() i Qt4), zamiast wpisywać wszędzie ciąg $localise->getValue($index) (akurat też możesz to robić - po prostu wywołujesz w inicjalizacji obiektu metodę noWrapperFunction() jesli nie chcesz wrappera, zresztą nawet jak masz wrappera to możesz metodę wywołać ręcznie).
    Teraz wymyśliłem żeby zarządzanie tymi zewnętrznymi referencjami wydzielić w klasie singletonie TranslationInstanceDispatcher - zobaczę co z tego wyjdzie.


  2. Żadnego - po pierwsze z magiczną metodą __autoloader spotkałem się dopiero tutaj (IMG:style_emoticons/default/biggrin.gif) (jakieś 2 tygodnie temu) - wcześniej po prostu używałem require_once (cóż, na naukę nigdy nie jest za późno). Na razie jest to mi niepotrzebne - najpierw chcę doprowadzić tę klasę do w miarę stabilnego działania. Autoloader można dodać w każdej chwili.

----------------------------------------------------------------------------------------------------------------------------
Poprawiłem trochę kod. Wprowadziłem pewne zmiany zarówno w klasie Translation, jak i w klasie TranslationDb oraz TranslationModel. Poprawione źródła są tutaj

Poniżej trochę taki skrótowy changelog:
  1. za twoją radą @wookieweb poczytałem trochę o klasach i metodach statycznych. Rzeczywiście pomogło (IMG:style_emoticons/default/smile.gif) . Zaimplementowałem statyczną klasę TranslationInstanceDispatcher której zadaniem jest zarządzanie zewnętrznymi referencjami klasy Translation. Pomogło na tyle, że wreszcie można postawić w tym samym czasie dwie lub więcej instancji obiektu Translation bez narażenia się na konflikt zmiennych.
  2. Poprawiłem dokumentację zgodnie z sugestiami. Klasa TranslationYAML została udokumentowana (ale nie była jeszcze testowana!)
  3. Zmodyfikowałem interfejs TranslationModel - dodałem dwie metody: setup() której zadaniem jest przygotować obiekt do pracy (podobnie jak w klasie Translation) oraz cache() - metoda specyficzna na razie tylko dla klasy TranslationDb (na obecnym etapie poza klasą TranslationDb obydwie są zaślepione)
  4. Jak wyżej w klasie TranslationDb wprowadziłem tryb cache w którym cała tabela jest pobierana na samym początku (dokładnie w momencie wywołania metody setup()), późniejszy odczyt odbywa się z tablicy w pamięci PHP. Ten tryb obecnie jest domyślny, wyłączając go przechodzimy do starego odpytywania.
  5. Mniejsze bugi i niedopatrzenia na które natknąłem się poprawiając kod

Jutro (właściwie to dziś) jak będę w stanie to zobaczę na ten model domenowy.

Poniżej krótki przykład kilku instancji obiektu Translation:
Tabela i dane
  1. CREATE TABLE `Translations` (
  2. `id` varchar(40) CHARACTER SET latin1 NOT NULL,
  3. `pl_PL` mediumtext,
  4. `en_GB` tinytext,
  5. PRIMARY KEY (`id`)
  6. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  7. INSERT INTO `Translations` VALUES ('M_HOME','Główna','Home');
  8. INSERT INTO `Translations` VALUES ('M_ABOUT','O nim','About me');
  9. INSERT INTO `Translations` VALUES ('M_PORTFOLIO','Portfolio','My galleries');

Przykład użycia:
  1. //Dla języka polskiego
  2. $polish = new Translation($pdo);
  3. $polish->setLang('pl_PL');
  4. $polish->setup();
  5. echo <<<EB
  6. <ul>
  7. <li>{$U('M_HOME')}</li>
  8. <li>{$U('M_ABOUT')}</li>
  9. <li>{$U('M_PORTFOLIO')}</li>
  10. </ul>
  11. EB;
  12. //Dla Inglish by Polish (czyli mix)
  13. $english = new Translation($pdo);
  14. $english->setWrapperFunctionName('E'); //warto ustawić nazwę prefiksu żeby wiedzieć gdzie się odwołać
  15. $english->setLang('en_GB');
  16. $english->setup();
  17. echo <<<EB
  18. <ul>
  19. <li>{$E('M_HOME')}</li>
  20. <li>{$E('M_ABOUT')}</li>
  21. <li>{$U('M_ABOUT')}</li>
  22. <li>{$E('M_PORTFOLIO')}</li>
  23. </ul>
  24. EB;
  25. $polish->__destruct(); // niszczymy obiekt Translate ustawiony na polski, poniżej powinien wystąpić fatalError (Odwołujemy się do funkcji która już nie istnieje)
  26. echo <<<EB
  27. <ul>
  28. <li>{$U('M_HOME')}</li>
  29. <li>{$U('M_ABOUT')}</li>
  30. <li>{$U('M_PORTFOLIO')}</li>
  31. </ul>
  32. EB;


Ten post edytował everth 8.08.2010, 04:36:24
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 9.06.2026 - 17:45