empathon
9.04.2007, 16:01:43
Ja podobnie jak ~
bela używam symfony i uważam tamto rozwiązanie za optymalne. Zarówno pod względem przechowywania elementów interface i treści w bazie danych. Polecam zapoznanie się z tym jak jest to tam
rozwiązane
jezeli ktos sie zdecyduje na symfony, to radze pobierac przez metode doSelectWithI18n, bo samo doSelect nie pobiera danych z jezykow i za kazdym razem wali selecta.
cicik
12.04.2007, 21:45:21
Od jakiegoś czasu zastanawiam się na wielojęzykowością w moich projektach i patrząc na potrzeby moich klientów widzę cztery mechanizmy opisujące ich oczekiwania:
1. Klient chce mieć TYLKO z góry określoną liczbę języków.
W takich wypadkach robię po prostu jak kolega wyżej zaproponował, czyli kolumny w tabeli: tytul_pl, tytul_en etc.
2. Klient chce mieć stronę w kilku językach ale one generalnie są niezależne (różne działy etc.).
Wtedy po prostu robię kilka stron, którymi da się administrować z jednego panelu.
3. Klient chce mieć jedną stronę w kilku językach, każdy artykuł w różnych wersjach językowych.
Internauta przełącza się pomiędzy wersjami za pomocą linków (np. chorągiewek z flagami).
W bazie jest to zapisywane jako relacja n do n pomiędzy artykułami i językami gdzie w relacji łączącej jest zapisany tytuł i treść artykułu w odpowiednim języku.
4. Klient chce mieć stronę generalnie w jednym języku (menu etc.) ale poszczególne artykuły w kilku wersjach wyświetlanych na jednej stronie.
Baza jest podobna do tej z pkt. 3.
Przypadek 1. jest szczególną formą jednego z pozostałych.
faster
30.04.2007, 00:15:28
Cytat(bela @ 4.04.2007, 17:52:29 )

rozwiazanie powyzej jest fajne, ale ma jedna wade: dane w bazie sie powtarzaja
ja uzywam symfony i rozwiazania z tamtego frameworka, czyli mamy dwie tabele w jednej sa dane, ktore sie nie zmieniaja np id uzytkownika, data utworzenia a w drugiej teksty powiazane za pomoca klucza obcego i dodatkowo pole z jezykiem
Moim zdaniem, rozwiązanie zaproponowane prze Kayne jest bardziej wydajne. Wzrost ilości rekordów nie jest raczej problemem podczas, gdy odwoływanie się do dwóch tabel w celu uzyskania danych jest bardziej obciążające.
Rozważając ten problem myślałem początkowo o zastosowaniu właśnie tablic z tłumaczeniami (trochę podobne rozwiązanie jakie opisał bela) czyli mamy tablicę z danymi np. produkty czy też osoby a mamy również w systemie tablicę tlumaczenia (id,tabela,pole,jezyk,dane) i tam zapisujemy "tłumaczenia" wartości domyślnych. Jak słusznie można zauważyć rozwiązanie pozostawia wiele do życzenia

. Kayne natomiast otworzył mi oczy na proste i moim zdaniem bardzo wydajne i uniwersalne rozwiązanie (zmieniasz strukturę danych dodając kolejne pola nie martwisz się o języki - w bazie dodają się same).
Zastanawiałem się jeszcze nad problemem podczas obsługi na formularz i wieloma językami. Co sądzicie o takim mechanizmie: normalnie funkcjonuje domyślny formularz tylko w jednym języku, gdy chcemy dodać tłumaczenie klikamy na przycisk z wyborem języka i pojawia nam się okienko z formularzem z polami w danym języku

and so on ...
pozdro
... tak zrobię a potem podzielę się uwagami z pola boju
Siner
13.05.2007, 16:19:31
Ostatnio zastanawiam się nad wyglądem linków wielojęzykowej strony.
Z jednej strony ciekawym rozwiązaniem było by budowanie strony na zasadzie: "example.com/kontakt/" - dla polskiej wersji językowej, a "example.com/contact/" - w przypadku anglojezycznej wersji. Ale co w przypadku gdy np po niemiecku kontakt pisze się tak samo jak po polsku, można zawsze wczytywać język przeglądarki w takim wypadku i zapisywać go do sesji, ale czy to nie będzie "przyrost formy nad treścią"?
Dodatkowa sprawa to zapisywanie jak mają wyglądać linki w danym języku, pobieranie z bazy danych bądź pliku zawsze trochę zmniejszy trochę szybkość
No i jak na takie rzeczy reagują wyszukiwarki, bo zmniejsza to chyba to skuteczność trafności wyników.
Macie jakieś inne ciekawe sposoby na budowanie odnośników na stronach wielojęzykowych?
Nitryt14
13.05.2007, 17:23:59
Mam podobny problem jezykowy przy tworzeniu strony moich rodzicow.
Maja biuro projektowe, a na stronce chcą miec dane kontaktowe oraz opisy wraz ze zdjąciami budynków przez nich zaprojektowanych.
Wymyśliłem nastepujace rozwiazanie:
- dane stale takie jak dane kontaktowe, wszystkie podpisy (menu, strona główna etc.) przechowywał bym w plikach lang_xx.php
- a dane zmienne (opisy budynków, zdjęć etc.) dodawał bym do bazy danych przy czym każdy język... i tu sie pojawia problem czy lepiej żeby miał osobną baze (np. sim_pl etc.) czy wystarczy osobna tabela (np. opisy_pl etc.)
chyba ze by było jakieś jeszcze lepsze rozwiązanie.
kubarek
13.05.2007, 20:02:42
moja idea:
<?php
class language
{
function __construct($language='pl'){
$this->language=$language;
$this->get_data();
}
function __get($id){
return $this->data[$id];
}
function get_data(){
/* funkcja jakoś pobierze dane językowe, np z bazy danych mysql */
/* mogą być to dane zapisane już jako tablica w pliku php */
include 'plik_z_jezykiem_'.$this->language.'.php';
/* etc. */
$this->data=...
}
}
$l='pl';
$lang=new language($l);
?>
i w tym przypadku ( gdy zmienna $l zawiera 'pl' ), instrukcja $lang->10 może wyświetlić np. 'Witaj świecie', a po zmianie $l na en może pokazać 'Hello world', podobnie jak z np. $lang->1337
chodzi, o to, że każdy tekst ma przypisany swój unikalny id, ergo dodanie/usuwanie/modyfikowanie danych językowych nie będzie skomplikowane
to jest w przypadku jakichś stałych danych, np. komunikatów z błędami czy czegoś podobnego; nie myślałem na razie o tym, jak zrobić żeby działało dla artykułów w wielu językach
Mój sposób wygląda tak:Plik
Global_Lang.php:
<?php
$glang[] = 'polish';
$glang[] = 'english';
$glang[] = 'spanish';
?>
Folder
__language:
Zawiera pod foldery z plikami językowymi oraz z interfejseminterface.php:
<?php
$interface['val1'] = null;
$interface['val2'] = null;
$interface['val3'] = null;
//... itd są to indexy które muszą występować w każdym pliku językowym w tym folde
rze
?>
lang.polish.php:
<?php
$lang['val1'] = 'czesc';
$lang['val2'] = 'czas';
$lang['val3'] = 'zegnaj';
?>
lang.english.php:
<?php
$lang['val1'] = 'hello';
$lang['val2'] = 'time';
$lang['val3'] = 'goodbye';
?>
Klasa
Language zawiera funkcje laczaca wszystkie pliki w jedna statyczna tablice (tylko aktualnie wybranego jezyka),
podczas mapowania folderow i laczenia plikow sprawdza czy sie zgadzaja indexy z plikiem interface.php jesli cos jest nie tak
wywala ostrzeżenie lub error (Klasa Exceptions). Po zmapowaniu wszystkich plikow zapisujemy sobie zserializowana tablice do pliku compiled.lang.polish.php (aktualnie wybrany język). Dzieki temu nie musimy ponownie skanować folderów, poprostu dołączamy plik z tablicą. Sprawdza rowniez czy sa wszystkie pliki z jezykami (Global_lang.php)
Umożliwia również tworzenie nowych języków z poziomu www, pobiera podfoldery z folderu __language wraz z plikiem interface.php,
wyswietla wszystko w formularzu form w krokach jeden formularz to jeden podfolder. Do póki administrator nie uzupełni wszystkich kroków nowy język nie zostanie dodany do aplikacji, jeśli wszystko uzupełnił zapisujemy nowy język w pliku.php do każdego podfolderu.
W ten sposób wykorzystuje to do stałych wartości które chce mieć w różnych językach, np wyświetlanie komunikatów o błędach, czy jakieś stałe nazwy w linkach typu Rejestracja,Register itd.. Inaczej trzeba podejść gdy chcemy mieć wielojęzyczne artykuły tutaj po stronie artykułów trzeba mieć odpowiednie funkcje które do tabeli dodadzą nam nowy język nie trzeba będzie tłumaczyć każdego artykułu podczas dodawania języka tak jak do tej pory, tylko wyświetlenie komórki z domyślnym językiem. Chociaż może to odbywać się też w klasie Language który wygeneruje nam polecenie SQL.
Według mnie takie rozwiązanie daje możliwość swobodnego zarządzania językami.
Jestem w trakcie pisania, jak dokończe pokaże jak to wyszło.
Sedziwoj
14.05.2007, 09:51:22
A mnie tak ciągle zastanawia, dlaczego artykuły/newsy itp. idą z id języka do bazy danych, a już np. nazwy działów lecą do plików?
Przecież to są informacje które można modyfikować, jak jeszcze założymy że tych elementów nie można przez panel admina ruszać to można by było podciągnąć pod statyczne elementy, ale przy możliwości dodania języka?
Ale może niech ktoś, kto ma jakieś pojęcie o tym wypowie, bo ja sobie tak gdybam i tylko jedna rzecz przychodzi mi do głowy, która może determinować wybór, aby za każdym razem nie pobierało danych z bazy.
Tylko że baza ma służyć do przechowywania i sprawnej dystrybucji danych...
siemakuba
14.05.2007, 15:17:27
Pojawił się w tym wątku pomysł, aby trzymać dane zależnie od języków w odpowiednich tabelach, przykładowo:
Kod
articles_pl
articles_en
articles_de
Początkowo wydało mi się to niezbyt dobre rozwiązanie, ale po zastanowieniu, może to być całkiem słuszne. Dlaczego?
Co o tym myślicie? Mi wydaje się całkiem słuszne, choć na chwilę obecną to tylko teoria ;)
pozdr.
Sedziwoj
14.05.2007, 19:39:55
Ja bym szybciej jedną tabele `article` i w niej kolumny:
id|lang_id|... PRIMARY KEY (id,lang_id)
bo obie są unikalnym identyfikatorem, zakładając że mam powiązania miedzy artykułami w różnych językach.
A wybieranie to z automatu dodawany jeden warunek, jak nie ma rekordu z takimi warunkami to nie ma, a nie tworzy bóg wie ile tabel.
siemakuba
15.05.2007, 09:56:56
@Sedziwoj - masz oczywiście rację, zdaje się, że trochę się zapędziłem :)
Jedna tabela z oznaczeniem języka dla każdego rekordu to faktycznie bardziej elegenackie rozwiązanie.
pozdr.
Black-Berry
24.12.2007, 00:23:58
Dawno nie pisałem na forum dlatego pozdrawiam i witam wszystkich. Sporo siedziałem nad tym tematem i chciałbym pokazać swój sposób i prośić o ewentualny komentarz:
1. Tabela bazy sql "languages" zawiera pola: ID | name | short . Można ona pomiescić dowolną liczbę języków.
2. Przy starcie strony wybierany jest język o ID=1 który jest językiem głównym. Jego parametry zapisane są w sesji: $_SESSION["language"]="polish" $_SESSION["language_id"] = 1 $_SESSION["language_short"] = "pl". Teraz możemy dla całego serwisu wykożystywać te zmienne. Czasem przydają się wszystkie 3.
3. Kliknięcie na flagę języka zmajdującej się gdzieś na witrynie powodujemy zmianę tych 3 zmiennych.
4. Ładowane są odpowiednie pliki które zawierają definicje sztywne np: define( "_COM_NEWSLETTER_TITLE", "Newsletter" ); Zeby wszystko działało gładko każdy komponent ma swój plik z tłumaczeniem np "russian_newsletter.php". Każdy plik zawiera w nazwie język tak żeby przypadkiem sobie nie nadpisać przy wysyłaniu na serwer róznych plików językowych.
5. Każda tabela z tekstami wprowadzanymi do bazy zawiera pole "language" identyfikujący język. Nie tworzę osobnych tabel dla innych języków, dzięki temu przy dodaniu nowego języka nie muszę tworzyc nowych tabel dla każdego komponentu.
==================
6. Zauważyłem, że taki system pozwala na dużo ciekawych rozwiązań np:
--- Można używać języka o ID=1 jako języka głównego a resztę jako reference. Wtedy przy odpowiedniej konfiguracji serwisu jeśli jakieś tłumaczenie nie istnieje łąduje się język główny i informacja, że wyświetlony został język natywny.
--- Można wysłać do tłumacza cały folder lub plik z tłumaczeniami sztywnymi.
--- Zmienną $_SESSION["language_short"] dobrze wykożystuje się do obrazków. Serwis może dla róznych języków załadować np "logo_pl.jpg" lub "logo_en.jpg"
Nattfarinn
27.12.2007, 11:18:32
A ja się zastanawiam nad sensownością innego rozwiązania wielojęzykowości. Generalnie jeśli chodzi o treści statyczne (czy to formularze, czy proste zwroty na stronach wbudowane w szablon), to rozwiązanie na poziomie plików (sposób dowolny) wydaje się najsensowniejsze. Jeśli jednak chodzi o wielojęzykowość treści podlegających ciągłym zmianom takich jak na przykład artykuły, wiadomości i tym podobne sprawy, rozwiązanie praktycznie musi leżeć po stronie bazy danych.
Myślałem jednak nad rozwiązaniem tego w następujący sposób (to tylko czyste spekulacje, bo nie próbowałem tego wprowadzać w życie).
Tabela odpowiadająca za artykuły (w sensie produkty, bo przykładem będzie wielojęzykowość na potrzeby e-commerce) przechowywane w bazie wg. pewnego bliżej nieokreślonego, przykładowego schematu (typy pól nieistotne):
Tabela: products
Kod
Id produktu
Cena produktu
Kategoria produktu
Data dodania
Data wygaśnięcia
Id promocji
Stan magazynowy
Tabela: products_lang
Kod
Id produktu
Id/Skrót języka
Nazwa produktu
Szczegóły produktu
Czyli rozbicie samych produktów na dwie osobne tabele bazy, a samo pobieranie danych za pomocą funkcji/procedur czy widoków. Z jednej strony to trochę "brudzenie" rozbiciem na tabele, z drugiej strony nie powielamy danych. Jak wszystko: posiada zalety jak i wady.
To czy obecny język przechowujemy w zmiennej sesyjnej, czy też jako wartość bazy danych dla poszczególnych użytkowników zostawia się woli piszącego system i nie jest to rzecz istotna, dlatego nie roztrząsam tego problemu.
acztery
4.02.2008, 21:53:48
ja stosuję metodę zapisu do bazy każdy element ma swój prefix językowy na tej podstawię identyfikuję wszystko.
Strzałek
1.03.2008, 12:07:43
W
Doctrine jest plugin do i18n. Wielojęzykowość staje się wtedy bardzo przyjemna.
http://www.phpdoctrine.org/documentation/m...ation-with-i18n
Sh4dow
4.03.2008, 10:43:03
a jak w tym doctrine wyglada to tłumacznie ? Osobne tabele ? Bo przy jednej jezykowosci jakos to widze przy powiedzmy 6-10 prawdopodobnie zaczely by sie schody z iloscia rekordow, a nie mowiac juz o wiecej ilosci rekordow powiedzmy z wiadomosciami, opisami, cechami przedmiotow/produktow.
No i czy to by uwzglednialo powtarzajace sie frazy.
Pytam tak bo szukam jakiegos dobrego rozwiazania wielojezykowego i jedynie na chwile obecna gettext jakos dziala, ale to tez ma swoje ograniczenia.
Strzałek
14.03.2008, 13:08:25
Przykład z dokumentacji doctrine:
news:
id | content
news_translation:
id | title | lang
W tym przypadku dla newsów będą tytuły w różnych językach. A używając doctrine wyciąga sie je tak:
<?php
//po wykonaniu wcześniejszego Doctrine_Query
echo $items[0]->Translation['PL']->title; // 'Witaj Świecie' ?>
Możesz jednak zmodyfikować ten plugin aby działał on inaczej. Sam plugin nie jest jakoś specjalnie skomplikowany, jak i również pisanie pluginów dla Doctrine jest proste.
Tak w ogóle to polecam Doctrine. To naprawdę bardzo dobry ORM.
lusiek
22.05.2008, 09:10:58
(sorry za odkop)
Nie można po prostu użyć prefixów w bazie danych? np.
tabela
pl.news
en.news
w PHP:
<?php
//[...]
$lang_prefix = ('pl');
$sql="SELECT * FROM ".$lang_prefix."news ORDER BY dodano DESC";
//[...]
?>
empathon
22.05.2008, 12:00:40
Cytat(lusiek @ 22.05.2008, 10:10:58 )

(sorry za odkop)
Nie można po prostu użyć prefixów w bazie danych? np.
tabela
pl.news
en.news
w PHP:
<?php
//[...]
$lang_prefix = ('pl');
$sql="SELECT * FROM ".$lang_prefix."news ORDER BY dodano DESC";
//[...]
?>
Oczywiście, że możesz ale to mało elastyczne. Było to już wałkowane we wcześniejszych postach (nie przeczytałeś?).
Wiele danych będzie się powtarzać a dodanie kolejnej wersji językowej wymaga dodania tabeli.
Cytat
news
id | author_id | created_at | ...
news.translation
... | news_id | lang | title | content ...
Nie sensowniej?
.radex
23.05.2008, 17:52:07
Mam jeden prosty i sprawdzony sposób.
<?php
echo __
('Witaj Świecie!'); ?>
I tyle. Funkcja __ wyszukuje w specjalnej tablicy dany string i do niego przyporządkowuje odpowiednie tłumaczenie.
Tablice wyglądają np. tak:
plik langs/en/cnt_test.php :
$langArray['modules/controllers/test.php']['Witaj Świecie!'] = 'Hello World';
Zamiast ['modules/controllers/test.php'] może być [''] - wtedy dane tłumaczenie będzie obejmowało wszystkie pliki.
Sedziwoj
23.05.2008, 19:10:41
@radex_p
Co innego tłumaczenie statycznych rzeczy, co innego dynamicznie dodawanych.
.radex
23.05.2008, 19:52:53
Co masz na myśli? Te tablice z tłumaczeniami są (o ile dobrze zrozumiałem) statyczne.
EDIT:
Chyba już wiem, co miałeś na myśli. Napisałem "przyporządkowuje". __() nie dodaje tłumaczenia, tylko zwraca tłumaczenie stringa zawartego w argumencie.
Crozin
23.05.2008, 21:01:49
@radex_p - myślę, że chodziło o np. artykuł dodawany do serwisu. Który tłumaczysz na polski, angielski czy niderlandzki.
.radex
24.05.2008, 08:40:48
aaaaa..... Teraz już rozumiem
Sedziwoj
24.05.2008, 10:25:24
Dokładnie, bo można rozgraniczyć na dwa rodzaje, jeden to to co jest właściwie raz tworzone, czyli komunikaty, teksty np. "Dodaj komentarz" itp. co jest przez nas robione, drugie to są rzeczy dodawane dynamicznie, czyli artykuły, wiadomości czy co tam w aplikacji zaoferujemy. Te drugie są w bazie danych więc, oczywiste jest że wszystkie wersje językowe tam muszą być.
Co do pierwszych, no to już jak widać różne opinie, ja do opisu statusów wykorzystuję bazę danych, bo i tak muszą być w bazie przez FK. Co do tekstów, to można zrobić tak jak już było nieraz podane, przez funkcję, ale tak na prawdę skąd ona bierze te dane, to już inna sprawa, ważne jest że w kodzie widzimy tekst jaki ma się pojawić a nie jakiś jego znacznik.
Można by dyskutować, a co jak nie będzie działać baza danych? Ale tak na prawdę to jak nie działa, to już cała strona też, więc tylko komunikat o niemożliwości połączenia z bazą musi być w pliku zapisany.
joohn
29.05.2008, 11:32:28
Obecnie korzystam z Symfony i podoba mi sie jak to tam jest rozwiązane.
Przypomne:
Teksty statyczne - XML i funkcja __('tekst')
Teksty dynamiczne - dwie tabele, np. products (id, symbol, item_number) i products_i18n(id,lang,name,description)
Jedyny minus Symfony to jeżeli brak tłumaczenia dla danego obiektu (np. nazwy produktu), wyświetlany jest pusty string, a w mojej aplikacji chciałbym żeby jeśli np. brak tłumaczenia polskiego, było wyświetlane tłumaczenie angielskie domyślnie. Oczywiście da się tak zrobić modyfikując propelowy generator, no ale znów generuje to dodatkowe zapytania do bazy.
Swojego czasu napisałem własny ORM który wykorzystał rozwiązanie jakiego tu jeszcze nikt nie zaproponował

Miałem tabele w bazie danych:
stringsid (int)
lang
content (varchar255)
textsid (int)
lang
content(text)
gdzie id i lang były kluczem głównym. Jeżeli w którejkolwiek innej tabeli miał być content zależny od języka, oznaczałem to tak:
productsid
symbol
string_name (int)
text_description (int)
ORM w momencie pobierania obiektu z bazy danych, przed przygotowanie query, jeżeli napotkał pola z prefixem "string_" bądź "text_" robił joina z odpowiednia tabela strings bądż texts. Podobnie przy zapisie i uaktualnieniu danych.
Co sądzicie o takim rozwiązaniu? Jego zaleta to taka, że nie muszę projektować dodatkowych tabel _i18n, wystarczy że wszystkie pola zależne od języka będę oznaczał jako string_ bądż text_. Wada to oczywiście dodatkowy join w każdym zapytaniu (ale w symfony jest to samo), koniecznosc napisania wlasnego orm badz zmodyfikowania istniejacego, no i tak jak wcześniej napisałem, problem gdy chcemy korzystać z degradacji języka (czyli nie ma polskiego to angielski, nie ma angielskiego to niemiecki itp)
Sedziwoj
29.05.2008, 14:18:48
@joohn
Wada, to że wszystkie teksty są wrzucone do jednego worka, czyli tak na prawdę nie wiemy co to jest, tylko tyle że jakieś teksty.
rzymek01
29.05.2008, 20:01:46
Witam!
Podsumowując, moim zdaniem optymalnym rozwiązaniem:
dla
elementów stałych jest utworzenie przykładowej klasy Language:
- każdy język podzielony na części (moduły, sekcje odpowiadające skryptowi)
- format zapisu: php bądź ini
- wynikowo klasa wczytuje odpowiedni język z odpowiednią częścią/częściami, tzn. np. dla części newsów nie wczytuje langów dla części download
lub: wykorzystanie "modyfiera" Smarty, innego gotowego rozwiązania
dla
elementów dynamicznych (każdy język -> inna treść):
- możemy ograniczyć się do jednej tabeli (plus tabela lang, czytaj dalej)
- tabela, która w swoich kolumnach posiada wszystkie niezbędne info
[b]artykuly[/b]
id | autor_id | lang_id | tytul | zawartosc | ogladany | komentarzy | ocena | ...
-------------------------------------------------------------------------------------
1 | 476 | 1 | PHP 6 | content.. | 23 | 9 | 5 | ...
- w takim układzie do wyświetlenia przykładowo listy artykułów pl wystarczy dodać do where,np. lang=1 (gdzie 1 to np. pl):
SELECT tytul, ogladany, ocena FROM artykuly WHERE lang = 1
- przy tym rozwiązaniu każdy artykuł ma swoje komentarze (artykuł pl -> komentarze pl)
dla
elementów dynamicznych (każdy język -> taka sama treść):
- potrzebujemy dwóch tabeli (plus tabela lang, czytaj dalej)
- tabela główna, która nie zawiera treści artykułu, lecz inne info na jego temat
[b]artykuly[/b]
id | ogladany | komentarzy | ocena | ...
-----------------------------------------------------------------------------------------------
1 | 23 | 9 | 5 | ...
- tabela zawierająca treść artykułów w różnych wersjach językowych
[b]artykuly_lang[/b]
... | art_id | lang_id | tytul | zawartosc | ...
-----------------------------------------------------------------------------------------------
... | 1 | 1 | PHP 6 | content.. | ...
- przy tym rozwiązaniu komentarze dla każdego artykułu są zbiorcze (czyli mogą występować komenty w różnych językach)
EDIT:by
Sedziwoj: tabela z językami
[b]lang[/b]
id | short_name | name
--------------------------
1 | pl | Polski
Oczywiście, że istnieją inne rozwiązania jak np. tabele pl_news, en_news, lecz te sposoby, które przedstawiłem wydają mi się najbardziej elastyczne i uniwersalne.
Pozdrawiam!
Sedziwoj
30.05.2008, 08:44:00
@rzymek01
Jak masz kolumnę lang, to niech to będzie integer, po co męczyć bazę stringiem, do tego najlepiej lang_id, i tabela gdzie jest id|short_name|name czyli skrócona nazwa języka np. PL i pełna Polski.
rzymek01
30.05.2008, 13:39:42
racja, mój błąd

nie chciałem już mieszać, bo na początku chciałem zrobić lang_id
Blodo
6.07.2008, 05:56:10
Kolejny odkop no ale..
Ja uzywam dwoch tabel: jedna dla tzw. metadata czyli ID, kategoria; druga dla samych tlumaczen. Przypisuje im jezyk za pomoca lang_id w drugiej tabeli, I wyciagam z bazy za pomoca JOINa. Ogolnie ten skrypt co mam automatycznie wybiera jezyk przegladarki dla uzytkownika, lub - jezeli nie ma takiego jezyka w systemie - wybiera jezyk domyslny (angielski).
Zakladajac ze w bazie danych nie zawsze bedzie tlumaczenie dla kazdego artykulu w jezyku uzywanym w tym momencie przez uzytkownika, jak moznaby sformulowac zapytanie do SQLa tak aby przy wyciaganiu artykulow dla danej kategorii wyciagalo wszystkie artykuly w wersji jezykowej uzytkownika lub w wersji jezyka domyslnego jezeli poprzednie sie nie powiodlo? Poki co moim rozwiazaniem jest SELECT na wszystkie lang_id, i potem sprawdzanie co wyswietlic a co nie za pomoca PHP, ale to troche badziewne rozwiazanie IMO. Ktos sie natknal na taki problem?
Sedziwoj
7.07.2008, 08:00:55
@Blodo
Może coś w tym stylu:
SELECT * FROM base_data AS b LEFT JOIN lang_data AS l ON ( l.base_data_id = b.id AND l.lang_id = x) LEFT JOIN lang_data AS l2 ON (l2.lang_id = y AND l.id IS NULL);
x - id wybranego języka
y - id domyślnego języka
To jest na JOIN, ale mam parę pomysłów na inne rozwiązania, tylko raczej nie wydajniejsze.
Blodo
7.07.2008, 23:24:09
Hmm, dobry pomysl. Co prawda trzeba w php potem sprawdzic ktore pole z tabeli nie jest "NULL", no ale i tak lepiej niz bylo. Dzieki ci za to.
Sedziwoj
7.07.2008, 23:58:30
Cytat(Blodo @ 8.07.2008, 00:24:09 )

Hmm, dobry pomysl. Co prawda trzeba w php potem sprawdzic ktore pole z tabeli nie jest "NULL", no ale i tak lepiej niz bylo. Dzieki ci za to.
No to zrób jeszcze jedno użyj CASE... i wtedy w php nic nie robisz, tylko wyświetlasz.
Albitos
19.08.2008, 15:17:06
Wybaczcie, że odgrzewam temat. Baardzo długo zastanawiałem się nad rozwiązaniem wielojęzykowości w moich skryptach. Końcowo doszedłem do wniosku, że idealnym rozwiązaniem będzie wykorzystanie systemu wbudowanego w OPT oraz kilku ciekawych ulepszeń. Po pierwsze, wszystkie stałe językowe przechowywane są w kategoriach niezależnych od czegokolwiek. Grupujesz jak chcesz, potem wczytujesz te grupy. Wczytanie jednej stałej z grupy powoduje wczytanie wszystkich z danej grupy.
Załóżmy, że mamy takie grupy:
- navigation
- contact
- home
- global
Teraz struktura plików:
languages/pl/
navigation.php
contact.php
home.php
global.php
languages/en/
navigation.php
contact.php
home.php
global.php
Każdy plik PHP składa się z tablicy $lang, która zawiera stałe. Dlaczego akurat tablica, a nie jakiś XML/YAML? Otóż z bardzo banalnego powodu. W pewnym momencie, kiedy pracowałem nad grą internetową (http://orodlin.pl) okazało się, że stałych odpowiedzialnych za niektóre akcje jest bardzo dużo (w jednym pliku ponad 500), natomiast wykorzystywana jest tylko jedna. Ładowanie wszytkich takich danych przy pomocy parsera byłoby całkowicie bezcelowe - marnotrawstwo pamięci.
Dlatego zamiast tablicy stworzyłem obiekt implementujący interfejs ArrayAccess, który pobiera potrzebne stałe prosto z bazy danych. Muszę przyznać, że jestem z takiego rozwiązania bardzo zadowolony. Wszystkie stałe są pogrupowane w logiczne kategorie, w razie konieczności przechowania większych ilości danych, używam odpowiedniego obiektu bez modyfikowania samego systemu językowego.
Pozostał tylko jeden zasadniczy problem - rozbicie wszystkich stałych na kilka plików wymusza wczytanie za każdym razem kilku plików. Ten problem rozwiązałem, używając cache. Wszystkie stałe, o ile nie pochodzą z dynamicznych tablic (tych obiektów implementujących ArrayAccess) zapisuję przy pomocy jednej wielkiej zserializowanej tablicy i zapisuję w pliku. Każda akcja w kontrolerze ma taki swój własny plik. W ten sposób kilka plików ładowanych jest tylko za pierwszym razem.
Jestem w trakcie pisania pluginu do OPT który będzie realizował taki system. Mam nadzieję, że wszystkim się spodoba. Tymczasem chciałbym poznać wszystkich opinie, co sądzą o takim rozwiązaniu.
EDIT: Co do danych dynamicznych, w Orodlinie istnieje założenie, że gra = jeden język. W innych projektach, gdy muszę mieć różne wersje językowe dynamicznych danych (np. artykułów), po prostu w tabeli dodaję pole określające język.
tomek_swat
12.10.2008, 20:13:47
mam pytanie jak sobie radzicie z wersją językową przechwyconych wyjątków, w każdej klasie jest:
<?php
throw new exception (..)
?>
i jak to uzależnić od wyboru języka, ja trzymam wszystkie klasy w folderze /classes i właśnie rozwiązanie tego problemu sprawia mi kłopoty?
pzdr
Crozin
12.10.2008, 21:15:54
Ale w jakim celu tłumaczyć wyjątki? One są raczej informacją dla programu/skryptu, a nie użytkownika.
Możesz:
1) Przeklazać już odpowiednio przetłumaczony wyjątek:
<?
throw new Exception(myTransolator('invalidABCDE'));
?>
2) Napisać właśną klasę wyjątków, która robi to co kod powyżej, ale już wewnątrz siebie:
<?
class MyException extends Exception{
public function __construct($msg = '', $code = 0){
$this->msg = myTranslate($msg);
$this->code = $code;
}
}
?>
Ale jeszcze raz zapytam: po co?
tomek_swat
13.10.2008, 11:43:50
załóżmy, że mam klasę Config, która jest Singletonem i pobiera z pliku .ini wersję jęzkową systemu
jezyk = "pl" i w zależności od tego klasa Lang, parsuję odpowieni plik .ini z folderu gdzie znajdują się odpowiednie wersję językowe
co jeśli w pliku settings.php parsowanym przez klasę Config, użytkownik wpiszę język, który nie jest uwzględniony w folderze w którym znajdują się wersję językowe? pozostaję wypluć wyjątek, tu właśnie pojawia się w problem w jakim on ma być języku i jak ten język zaimplementować w klasie Lang i Config?
pzdr
Sedziwoj
13.10.2008, 15:23:27
Nie zawsze wyjątki są najlepsze, powinieneś sprawdzić czy dany język istnieje jeśli nie to ustawiany jest domyślny. Jeśli gdzieś w serwisie jest użyte coś, czego nie ma w pliku językowym to jest błąd, i taka informacja też nie musi być rozpowszechniana po prostu wymuszenie przez moduł językowy załadowania informacji o błędzie/braku informacji, to już jest statyczna informacja niezależna od błędu, no i log dla nas aby dojść co się sypnęło.
test_next
2.07.2009, 10:12:06
Witam,
tak pobieżnie przeglądając odpowiedzi nie widziałem sposobu z definiowaniem zmiennych językowych jako stałe np. define('HELLO_WORLD","Hello world"); echo HELLO_WORLD. Co o tym sądzicie?
Pozdrawiam
Mało przenośne. Co w sytuacji, gdy np. stała konfiguracyjna będzie nosiła tę samą nazwę jak językowa?
Poza tym, wg Twojego schematu idealny byłby
gettext" title="Zobacz w manualu PHP" target="_manual.
test_next
2.07.2009, 11:12:29
tak tylko aplikacja ma być przenośna, a gettext nie wszędzie jest zainstalowany.
No i jeszcze wchodzi w grę licencja tego typu rozwiązań - odpada GPL.
viking
2.07.2009, 11:23:21
To zainteresuj się Zend Framework (i zanim napiszesz coś o gettext przeczytaj dokładnie dokumentację).
test_next
2.07.2009, 11:51:36
To include GNU gettext support in your PHP build you must add the option --with-gettext[=DIR]
przeczytałem i ?
Nie miałem siły przeglądać całego watku, ale moim zdaniem najlepszym wyjściem jest podany 3 posty wyżej przez erixa sposób.
gettext" title="Zobacz w manualu PHP" target="_manual Oczywiście jakaś nakładka na to co by zapamiętała jakie frazy używam w systemie i generacja pliku .po A później już z górki :]
Przez 2 lata używałem zwykłych zmiennych includowanych do klasy języków i metodą get() pobierania ich. Ale to nie jest wyjście. Ciężko się połapać w tym wszystkim.
viking
2.07.2009, 11:56:40
Cytat(test_next @ 2.07.2009, 12:51:36 )

To include GNU gettext support in your PHP build you must add the option --with-gettext[=DIR]
przeczytałem i ?
Mówiłem o ZF.
Cytat
The Zend_Translate Gettext Adapter is not implemented using PHP's gettext extension. You can use the Gettext Adapter even if you do not have the PHP gettext extension installed. Also the Adapter is thread-safe and the PHP gettext extension is currently not thread-safe.
test_next
2.07.2009, 12:02:54
viking: ok, ale aplikacja jest dosyć rozbudowana i nie ma już sensu przenosić jej na zend'a...
Crozin
2.07.2009, 12:56:10
Zapewne da się ten komponent "wyciąć" z niego i stosować osobno.
Cytat
tak tylko aplikacja ma być przenośna, a gettext nie wszędzie jest zainstalowany.
Zobacz sobie, jak jest emulowane to rozszerzenie w Wordpressie.
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.