Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Algorytm do wersji językowej
Forum PHP.pl > Forum > PHP > Object-oriented programming
daves
Witam,

Chcę się z wami skonsultować i usłyszeć opinie nt. mojego rozwiązania.

Tworzę system wielojęzyczny przy użyciu Zenda i szablonów SMARTY.
Najważniejszym założeniem z jakiego wyszedłem był globalny dostęp do danych językowych ale przy założeniu, że czynności związane z odczytaniem odpowiedniego tekstu będą możliwie zminimalizowane.
Chcąc stworzyć automatyczny system wielojęzyczny zastosowałem takie oto rozwiązanie.
- Stworzyłem klasę w pełni statyczną, którą inicjuję już w samym bootstrapie i inicjuję dane w odpowiednim języku.
- Pozwoliłem sobie na dostęp do tej klasy za pomocą odwołania statycznego TKlasa::get('firstname') gdzie wywoływana będzie metoda __callStatic i tam odpowiednio obsłużona.
- Jako, że nie chciałem za każdym razem tworzyć obiektu i przekazywać do View postanowiłem stworzyć obiekt już w samym szablonie z odpowiednią ilością danych w tablicy assocjacyjnej przy użyciu ASSIGNE a następnie standarowe odczytanie wartości.

Wiem, że temat był maglowany setki razy ale takiego rozwiązania nie znalazłem.
Dlaczego tak? Ano dlatego, że przy tworzeniu nowego szablonu nie muszę się martwić o dostęp do tekstu i nie trzeba wykonywać nadmiarowych czynności.
Jest tylko inicjalizacja na samym pocżątku, potem w szablonie assigne i następnie odczyt np. labela.

Tutaj chciałbym usłyszeć waszą opinię, czy takie rozwiązanie jest możliwie optymalne, czy i gdzie mogę spodziewać się problemów lub też co mógłbym zmienić by to ulepszyć.

Pozdrawiam
DS
Sephirus
Jeśli przy inicjalizacji tej statycznej klasy ustawiasz jej rodzaj języka i ładujesz (leniwie czy nie) odpowiednie pliki jezykowe (o ile masz to w plikach) to nie widzę raczej "bardziej optymalnego" rozwiązania.

Rozumiem też, z tego co napisałeś, że assignowanie do smarty jest wykonywane automatycznie a w samym szablonie potem odwołujesz się do zapisanej już zmiennej językowej o poprawnej wartości?

Jesli tak to raczej nie widzę tu problemów - chyba że za każdym razem ładujesz wszystko a jest tego dużo - wówczas pasowało by ewentualnie podzielić dane językowe na części odpowiadające jakimś częściom aplikacji plus jedna częsć "wspólna"... skrajnym przypadkiem było by ładowanie zawsze dwóch plików językowych:
- plik językowy wspólny (z jakimiś ogólnymi tekstami używanymi prawie wszędzie)
- plik językowy akcji/kontrolera (z tekstami używanimi tylko w danym kontrolerze/akcji)

wydaje mi się że to jedyny problem do jakiego można się przyczepić (czyli ładowanie wszystkiego naraz) - jeśli oczywiście tak to robisz smile.gif
Orzeszekk
wg mnie głównym problemem wersji językowych to to, jak przedstawic np elementy charakterystyczne np różnie liczone liczby ( 1 kreska, 2 kreski, 5 kresek) a w angielskim (1 line , n lines), a to w jaką klasę sobie tam opakujesz to już szczegół.

APC ma funkcję apc_define_set czy apc_define_constants, jakos tak, pozwala ona zapisac cały set stałych do jednej komórki w apc, i nastepnie przy kolejnym uzyciu skryptu ją wywołać co jak czytalem jest szybsze niż define. Możesz sobie leniwie ładować taki set z pliku a następnie przy kolejnych uruchomieniach skryptu ładowac go z pamieci oczywiscie odpowiedni dla danego języka. Tylko trzeba sprawdzic czy takie cos faktycznie jest szybsze niż define.

Dzis uczylem sie z net frameworka, w ksiazce do egzaminu znalazlem informacje ze system językowy w ktorym do dokonywania tłumaczen musi sie uzywac jezyka programowania jest do kitu - nie dasz strony do przetlumaczenia komus obcemu. Plik jezykowy powinien byc w jakims prostym formacie, np yaml lub xml, i dla lepszej wydajnosci wg mnie powinien byc tlumaczony do postaci klas przy pierwszym odczytaniu.
to nic trudnego stworzyc generator kodu klasy zawierajacej dane stałe.

nastepnie przy uruchomieniu skryptu w bootstrapie wklejasz komponent językowy do klasy Lang ktora ma metody get i set
Lang::set(new LanguagePL());

chcac odczytac jakiś resource językowy robisz Lang::get()::TEXT_IN_FRONT_CONTROLLER.

Get zwraca ci klase zawierajaca dany język.
wg mnie zaleta takiego rozwiazania jest to ze w lepszych IDE będziesz mial podpowiadanie skladni i nie pomylisz sie w nazwie.
Jesli potrzebujesz cos wykonac przy inicjalizacji, dziedzisz po klasie LanguagePL i nadpisujesz konstruktor, i zapisujesz to w innym pliku.

W takim systemie aktualizacja systemu językowego następuje przy usuniecie tych wygenerowanych klas(cache).

Dla plikow kontrolerow mozna zrobic drugi kontener ktory bedzie zwracal np plik dla danego kontrolera w odpowiedniej wersji:

Lang::getController('my_front_controller')::TEXT_IN_MY_CONTROLLER.

Zaletą tego jest ze jesli masz autoloading klas (a pewnie masz), to taka klasa ze wszystkimi specyficznymi tekstami załaduje ci sie dopiero w momencie gdy będzie potrzebna, w innym wypadku nie zaladuje sie nigdy.

Jesli jednak bardzo ci zalezy na tym by po nieznalezieniu danego tlumaczenia zaladowal sie tekst po angielsku, to wystarczy przerobic ten generator klas php aby przy inicjalizacji tworzyl tablice asocjacyjną, i dostęp przez jakies get('nazwa_stringa'). Wtedy tam mozna dorobic doczytanie pliku podstawowego jesli w obecnym dany wpis nie zostanie znaleziony.

gdybym mial to robic to tak wlasnie bym to zrobil, ale nie zamierzam nigdy wiecej robic projektow bez uzycia frameworkow a tam zazwyczaj w jakis mądry sposob jest to rozwiązane. W SF2 jest bardzo ciekawy komponent do tłumaczen, i mozna go uzyc nie uzywajac reszty frameworka, moze zainteresuj sie tym.

pamietaj, programowanie jest jak seks: jeden błąd i musisz to pielęgnować całe życie.

Crozin
Cytat
wg mnie głównym problemem wersji językowych to to, jak przedstawic np elementy charakterystyczne np różnie liczone liczby ( 1 kreska, 2 kreski, 5 kresek) a w angielskim (1 line , n lines), a to w jaką klasę sobie tam opakujesz to już szczegół.
Przecież takie rzeczy masz już gotowe: MessageFormatter.
Cytat
Dzis uczylem sie z net frameworka, w ksiazce do egzaminu znalazlem informacje ze system językowy w ktorym do dokonywania tłumaczen musi sie uzywac jezyka programowania jest do kitu - nie dasz strony do przetlumaczenia komus obcemu. Plik jezykowy powinien byc w jakims prostym formacie, np yaml lub xml, i dla lepszej wydajnosci wg mnie powinien byc tlumaczony do postaci klas przy pierwszym odczytaniu.
to nic trudnego stworzyc generator kodu klasy zawierajacej dane stałe.
Tutaj standardem jest XLIFF lub PO.
Orzeszekk
Cytat(Crozin @ 10.02.2012, 23:24:00 ) *
Przecież takie rzeczy masz już gotowe: MessageFormatter.


Całe frameworki do globalizacji aplikacji również są gotowe smile.gif

Taka mala dygresja: Wydaje mi się że php przyzwyczail nas do nas że nic w nim nie ma i ludzie jeśli czegoś potrzebują to od razu piszą swoje rozwiazanie lub szukaja napisanej przez kogoś klasy do tego.

Teraz gdy nowe wersje php mają dużo wbudowanych modułów, ludzie nadal postępują w stary sposób, i nawet nie próbuja tego szukać wśród modułów PHP smile.gif

Cytat(Crozin)
Tutaj standardem jest XLIFF lub PO.

Tak, to był XLIFF, jak zobaczyłem nazwe to sobie przypomnialem i on jest w NET 4 użyty. Tylko że to i tak podzbiór XML-a z tego co pamiętam.

Niezależnie od tego, jakbyś to nie robił, pamiętaj o jednym - rób to z głową biggrin.gif Żebyś tego swojego systemu językowego kiedyś nie znienawidził i nie przeklinał go, a żeby służył ci dobrze i zmniejszał nakład pracy zamiast go zwiększać smile.gif

Teraz doczytałem że to ma być pod Smarty. No to może stworzyć po prostu generator plików smarty który będzie generował pliki szablonów smarty oddzielnie dla każdego języka? Załóżmy że wymyślisz sobie że w smarty elementy językowe bedziesz osadzał tagiem {%NAZWA_STAŁEJ%}. Niech generator zamieni po prostu weźmie ten szablon podstawowy gdzie masz tagi zamiast międzynarodowych tekstów, niech zamieni każdy taki tag na jego wartość w danym języku i niech zapisze szablon dla odpowiedniego języka w odpowiednim miejscu. i voila. będziesz miał więcej statycznego tekstu i szablony będą szybciej działać.

Niech ten generator sprawdza czy szablony dla danego jezyka istnieja a gdy nie istnieja niech tworzy je od nowa. W ten sposob odswiezenie wersji językowych bedzie wymagalo jedynie usuniecia folderu z keszem.

Ten generator niech będzie obiektem proxy i niech udostępnia np metodę render ktora sprawdza czy dany szablon istnieje i w razie czego je generuje a nastepnie dopiero wtedy je wyswietla, i uzywaj tej metody render zamiast metody ktora normalnie uzywasz by zrenderowac templatke smarty.

Ja uzywam takiego kesza w plikach całych fragmentów stron, i mam dostęp do tych keszowanych klas widoków właśnie poprzez obiekt proxy który sprawdza czy istnieje cache i jest swiezy, a jesli nie istnieje lub jest nieswiezy to renderuje widok normalnie, zapisuje wynik do plików i na koniec w obu przypadkach włącza do kodu strony ten gotowy fragment z pliku.
Przejrzystosc nie zmalała, w zasadzie dzieje sie to transparentnie, bo wciąż wywołuje render tylko innego obiektu niz pierwotnie i nic po za tym, a przecietny czas generowania cache-owanych częściami stron spadł mi o kilka razy (z np 200 -400 ms na 40-60ms).

Nie bawiłem się nigdy smarty ale myślę że nie powinno być z wykonaniem tego problemu. W razie czego zawsze można przerzucic się na Twig, jest podobny ze składni a tam pewnie sie bedzie dalo to zrobic.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.