Witam,
Od jakiegoś czasu piszę duży projekt i doszedłem do wybierania języku. Chciałbym poznać Wasze zdanie jak ma działać taki system wielojęzykowości strony. Pobuszowałem po internecie i oto, co wymyśliłem.
- Pliki.
Trzymamy pliki językowe w plikach. Każdy język ma osobny katalog, każdy ma pliki o takiej samej nazwie jak reszta języków, w plikach tablice o takich samych kluczach. Wybieramy odpowiedni język, include odpowiedniego pliku i print. - Teksty w bazie danych.
Tworzymy dwa obiekty. Jeden (może być traktowany jako filter) pobiera dane z bazy danych i przerzuca je do klasy o nazwie np. LangWrapper. Używając magicznych metod __get() pobieramy tekst z klasy i __set() gdy nie ma potrzebnego tekstu należy do stworzyć - Open Power Template
Byłbym wdzięczny za propozycje rozwiązań.
Wojtek.
Myślę ze dobrym rozwiązaniem są pliki. Stosuje sie je w wielu cmsach i projektach.
Tłumaczenia w bazie danych to według mnie zaśmiecanie db i w dodatku majac wiele jezykow robi sie syf i przedluza sie czas wyszukiwania.
Tutaj nalezy zadac pytanie jak stworzyc taki plik. Czy ma byc to plik php w ktorym definiuje się zmienne/stałe czy zwykły plik tekstowy typu
Kod
ERROR_CONNECTION=bład przy polaczeniu z baza;
ERROR_SELECT_DB=bład przy wybieraniu bazy;
itp...
Nie wiem co jest bardziej wydajne, jednak jesli chcemy zeby naszych jezykow nikt nie "podgladal" no to php
Strzałek
2.04.2006, 09:19:58
jeżeli w projekcie masz zamiar używać OPT, to ja na twoim miejscu użył bym opt'owego i18n ;]
Smarty: {config_load file="text.conf" section=$language} no i posprzątane
Ja korzystam z modifiera SMARTY
{"Jakis_tam_komunikat"|lang:"admin"}
Przepuszczam to przez modifier lang z paramtrem admin.
TomASS
7.04.2006, 07:27:19
A ja się bawię "słownikiem" - mam plik lang_pl.php, lang_en.php itp..... w bazie trzymam dla jakiego użytkownika jaki plik załadować (oczywiście to może później sobie zrobić). W plikach tych mam tablicę $Lang:
<?php
$Lang['Enter'] = 'Wejście';
$Lang['Exit'] = 'Wyjście';
.
.
.
?>
i tak plik normalnie includuje....
eMartio
7.04.2006, 10:15:48
Ja z kolei napisałem sobie plugin do Smartego. Templejty tworzę normalnie, używając naszego narodowego języka. Mam również plik XML, który nazywa się identycznie jak nazwa szablonu czy też modułu szablonu i zawiera tłumaczenia tekstów z templejta w wielu językach.
Np.:
Moduł szablonu: menu.mod.tplKod
<div>
<a href="home.php" title="Moja strona domowa">strona domowa</a>
</div>
Plik XML zawierający tłumaczenie:Kod
<translations>
<translation>
<source>Moja</source>
<en>My</en>
</translation>
<translation>
<source>strona domowa</source>
<en>home site</en>
</translation>
</translations>
Plugin Smartego po skomiliowaniu szablonu zamienia wszystkie teksty, które są uwzględnione w pliku XML (sekcja
source) na żądany język.
Ma to dwie ogrome zalety:
- w połączniu z keszowaniem parsowanie xml-u nie jest aż tak uciążliwe dla systemu
- mój tłumacz nie musi znać się na php (aplikacja), HTML (templejty); ba! nawet nie zagląda do tych plików - ma swój katalog, do którego wrzuca pliki XML
Vengeance
9.04.2006, 17:09:41
I ma taką wadę, że języki są różne i różną mają gramatyke... twoim sposobem czesto zdażyć się może, że nie da się w prosty sposób przetłumaczyć danego zdania.
Fipaj
9.04.2006, 18:36:07
http://developer.gnome.org/projects/gtp/tr...-gnome/x22.html - pliki .po i ich dekoder napisany przez Bastiona to całkiem dobre rozwiązanie.
Fajnie też rozwiązał to NuLL, ale pliki .PO są bardzo popularne, istnieje też wiele programów służących do ich edycji, co upraszcza tworzenie nowych wersji językowych. gTranslator i KBabel, for example.
3rdeye
12.04.2006, 15:10:53
Cytat(TomASS @ 2006-04-07 06:27:19)
A ja się bawię "słownikiem" - mam plik lang_pl.php, lang_en.php itp..... w bazie trzymam dla jakiego użytkownika jaki plik załadować (oczywiście to może później sobie zrobić). W plikach tych mam tablicę $Lang:
<?php
$Lang['Enter'] = 'Wejście';
$Lang['Exit'] = 'Wyjście';
.
.
.
?>
i tak plik normalnie includuje....
wydaje mi się, że to jest dobry pomysł. ja tak robię.
choć lepszym sposobem jest napisanie
$lang = array(
'czesc' => 'eloza',
'czlowiek' => 'ziom'
);
może się czepiam, ale sposób pisania TomASS'a jest jednak bardzo nieefetywny. php to nie C w php'ie najlepiej robić wszystko w jednej komendzie. choć szacun dla Niego, Jego squadu i Jego samicy za sposób robienia słownika

podoba mi się

z resztą ten sposób jest użyty także w sugarCRM.
splatch
12.04.2006, 19:49:35
Ja ze swojej strony mogę polecić draft i18n z Mojavi 4, całość prezentuje się iście interesująco.. niestety w chwili obecnej serwer Mojavi leży..
yavaho
12.04.2006, 20:15:15
Ja mam strony wielojezykowe zrobione na podstawie bazy danych i dosłownie zero tekstu w kodzie html. Struktura plikow php wyglada podobnie jak bym smarty zastosowal.
Jeden minus to ze jest duzo zapytan do bazy i moze stanowic obciazenie przy wiekszym serwisie. Ale wtedy juz prosto mozna zastosowac cachowanie stron.
Ja osobiscie korzystam z plikow ini. Plik jezykowy globalny, + pomniejsze pliki jezykowe np: do konkretnego modulu. W Smarty korzystam z postfilter ktory podmienia odpowiednie ciagi znakow na wartosci np: [lang:mod_news,dodaj] na "Dodaj newsa"
ja wczytuje zawartosc pliku ini dla wybranego jezyka do tablicy (parse_ini_file) a potem po prostu:
{$lang[costam][costam]}
krzemian
16.04.2006, 13:53:05
Moim zdaniem prawda znowu leży po środku - wydaje mi się, że pliki są bardzo dobrym rozwiązaniem, jeśli chodzi o teksty formularzy itp. Jednak co, jeśli ktoś będzie chciał tłumaczyć całe artykuły, znajdujące się w bazie? Wtedy najlepszym rozwiązaniem byłoby połączenie systemu pliki+baza.
Wydaje mi się, że można by stworzyć tabele osobno dla każdego języka, np. en_articles, pl_articles itp., bo trzymanie tych danych w jednej tabeli nie miałoby raczej najmniejszego sensu, skoro i tak są one wykorzystywane naprzemiennie, a nie razem.
PS. Nie jedźcie po mnie za bardzo, bo ostatnio w php coś pisałem chyba z pół roku temu:) I wesołych świąt wam życzę.
NoiseMc
16.04.2006, 15:33:53
Cytat(krzemian @ 2006-04-16 12:53:05)
Wydaje mi się, że można by stworzyć tabele osobno dla każdego języka, np. en_articles, pl_articles itp., bo trzymanie tych danych w jednej tabeli nie miałoby raczej najmniejszego sensu, skoro i tak są one wykorzystywane naprzemiennie, a nie razem.
Ja osobiście trzymam wszystko w jednej tabeli, w której mam kolumnę "Lang" określającą w jakim języku jest dany wiersz czyli np:
ID | Tytul | Tresc | Lang
Potem w zalezności od wybranego języka wybieram potrzebne dane np.:
SELECT *
FROM tabela
WHERE Lang=$_GET['lang']
Jeżeli natomiast chodzi o stałe teksty typu: "Więcej", "Strona głowna" to trzymam je w XML - ach gdzie struktura plików jest następująca:
Kod
languages
en
Translation.xml
pl
Translation.xml
parsuję XML z wykorzystaniem PEAR::XML_Unserializer i podrzucam do smartów gdzie wyświetlam to:
<?php
{$Translation.StronaGlowna}
?>
Obecnie pracuję nad manadżerem do tłumaczeń - coś na zasadzie kompilacji XML - a do pliku w którym byłaby zserializowana tablica z tłumaczeniami. I jeżeli XML jest nowszy niż skompilowane dane to wtedy kompiluję jeszcze raz. Jeżeli nie to odczytuję i podstawiam zserializowaną tablicę
krzemian
16.04.2006, 17:07:31
Teraz tak myślę i doszedłem do wniosku, że twoj podejście jest chyba lepsze od mojego (jeśli chodzi o trzymanie w bazie, bo xml i pliki to dla mnie to samo - wszystko zależy od możliwości serwera itp) - zakładając, że chcę dodać kolejny język, przy twoim podejściu mogę (przynajmniej teoretycznie) dodać go z poziomu panelu, nie grzebiąc w strukturze baz.
Jabol
16.04.2006, 21:23:09
A co wy na to (suma kilku pomysłów):
<?php
function array_path_insert(&$array, $sep, $path, $value)
{
$path_el = split($sep, $path);
$arr_ref =& $array;
for($i = 0; $i < sizeof($path_el); $i++) {
$arr_ref =& $arr_ref[$path_el[$i]];
}
$arr_ref = $value;
}
foreach(file("translations/{$lang}.txt") as $line) {
/* define("TXT_".array_shift($chunks), eval(implode("=", $chunks))); // tak jakby chciać tutaj włożyć jakąś logikę */
/* define("TXT_".array_shift($chunks), str_replace('\n', "\n", implode("=", $chunks))); // tutaj jakby nie chcieć interpretować wszystkiego */
/* można też zrobić preg_replace z tablicami */
/* XXX: Ależ mi nachodzi pomysłów. Dla tablicowców-smartowców następna wersja. (funkcje znalazłem w komentarzach do manuala) */
}
$smarty->cośtam('lang', $trans);
?>
A plik translacji wyglądałby oczywiście
Kod
TEXT1=BlaBlaBla
TEXT2=Myślę więc jestem
TEXT3=W matematycie wiem, że 2*2=4!
Taka synteza paru pomysłów - prosta i szybka implementacja.
Do drugiej metody (tej z tablicami), wyglądałobyto oczywiście analogicznie
Kod
MAIN.TEXT1=BlaBlaBla
MAIN.TEXT2=Myślę więc jestem
MAIN.TEXT3=W matematycie wiem, że 2*2=4!
To oczywiście tylko dla małych tekstów dla tworzenia innojęzycznych wersji serwisów. Dla mniejszycg napisów, dla których nie chcemy marnować cennych id w bazie danych. Bo co do większych napisów zgadzam się z przedmówcami.
Bora
17.04.2006, 14:11:06
Cytat(Jabol @ 2006-04-16 21:23:09)
A plik translacji wyglądałby oczywiście
Kod
TEXT1=BlaBlaBla
TEXT2=Myślę więc jestem
TEXT3=W matematycie wiem, że 2*2=4!
Taka synteza paru pomysłów - prosta i szybka implementacja.
Do drugiej metody (tej z tablicami), wyglądałobyto oczywiście analogicznie
Kod
MAIN.TEXT1=BlaBlaBla
MAIN.TEXT2=Myślę więc jestem
MAIN.TEXT3=W matematycie wiem, że 2*2=4!
To nie lepiej użyć poprostu plików ini ?
Podczas moich praktyk w firmie gdzie brałem udział w tworzeniu aplikacji w springu (java) był stworzony plik (nie pamiętam jakie miał rozrzeszenie może .properties czy cuś) ale wyglądał on niej więcej :
main.welcome = Witam
main.menu = Menu
itp.
Fipaj
17.04.2006, 14:24:45
A co, jeśli w tłumaczonym tekście wystąpi znak "=" bądź przełamanie linii?
Ociu
17.04.2006, 15:28:25
Jabol: Muszę się zgodzić z Borą, wygląd pliku jest podobny do plików INI,a wprowadzenie tego w życie jest bardzije zamotane niż INI. Mój skrypt jest tylko silnikiem (albo słowo ostatnio bardzo popularne - frameworkiem) i nie ja go będe dalej rozwijał. Parse_ini_file jest w php4, pod które skrypt (niestety)...
Pewnie zaraz padnie pytanie: "Po co ten temat ?". Szukam jakieś alternatywy dla plików ini i wielkich tablic.
pozdrawiam
Cytat(Fipaj @ 2006-04-17 14:24:45)
A co, jeśli w tłumaczonym tekście wystąpi znak "=" bądź przełamanie linii?
Użyć encji. Przełamanie lini jest rozwiązane w plikach konfiguracyjnych smarty. Jeszcze jakieś trudne pytania?
Jabol
18.04.2006, 18:01:58
Cytat(Fipaj @ 2006-04-17 14:24:45)
A co, jeśli w tłumaczonym tekście wystąpi znak "=" bądź przełamanie linii?
Przeczytaj dokładnie to zauważysz, że oba problemy już są rozwiązane.
Osobiście w pewnym projekcie używałem też takiej opcji:
tabela: txts
pola:
id int
name varchar
pl text
de text
Tyle, że wiedziałem ile będzie języków... Teksty ogólne miały w name jakąś nazwę i je ładowałem do smarta i potem tylko
Kod
{$txts.PageName}
Teksty, które miały tam NULL były modułami innych modułów i z nich też były podlinkowane, także nie trzeba było się o nie martwić.
Prph
26.04.2006, 11:57:49
Witam,
Kilka dni temu pisalem klase opbsugujaca jezyk w moim frameworku. Wyglada to tak:
Klasa Language :
__construct($sLanguage = null)
1. jezeli podano w parametrze jezyk, ustaw go.
2. jezeli nie podano go, a ustnieje ciastko z nazwa jezyka (tlumaczenie strony w czasie trwania sesji), to zastosuja taki jezyk
3. w innym przypadku stosuj dod`myslny.
__get() dzieki ktorej w prtosty sposob korzysta,my z jezyka.
W pliku english.php mam tablice:
$aLanguage['main_menu_custam'] = 'SuperTurboMegaGigaUltraString ';
W aplikacji odwoluje sie do tego tak:
$oLanguage->main_menu_custam;
W szablonach wpisuje: {$LANGUAGE.MAIN_MENU_CUSTAM}.
Dziala :]
Neotion
27.04.2006, 07:20:49
Przepraszam będe pisał bez shifta bo siedze w szkole

w każdym razie:
wg. mnie najlepszym rozwiązaniem jest to które już oferuje pewien mod do php (nie pamiętam niestsety nazwy ale jest nawet jego opis gdzieś w manualu):
polega on na korzystaniu z tablic zawierających całe tłumaczenia stringów i wywoływanie tłumaczeń np poprzez funkcję
<?php
_("Tłumacz mnie");
?>
a przedtem na załądowaniu tej tablicy do pamięci. Potem wystarczy napisać sobie edytor w c++ (czy co tam chcecie) który wyciąga wszystkie stringi zawarte w tych funkcjach np. w podanym katalogu i przedstawia wygodny formularz do tłumaczenia. Za to w plikach .php pisazemy sobie jakimś językiem referencyjnym np. angielskim.
Pomysł programu pomocniczego to już idea barzeij wniesiona przeze mnie (albo plagiat czyjejś - nie pamiętam) ale takie rozwiązanie wydaje się wygodne i szybkie.
Bastion
27.04.2006, 07:35:10
takie wlasnie (podobne) rozwiaznie jest w klasie Babel, ktory korzysta z plikow .po / .mo z gettexta. nie trzeba pisac zadnego programu w c++, wystarczy skorzytac z progmau gettext
xgettext example01.php -L php -o pl_PL.po --keyword=_r --keyword=_p
i wycina do pliku po wszystkie ciagi tekstowe poprzedzone funkcja _r i _p
sadu
27.04.2006, 10:47:56
Odkopuje temat bo zastanawiam sie nad tym w jaki spsob, zgrabnie pobierac dane z tablicy z jezykami wewnatrz obiektu.
Moja tablica wyglada mnie wiecej tak:
<?php
'title' => 'Test'
)
);
?>
Trzymam ja w pliku pl_PL.lang.php i includuje w zaleznosci od ustawien lokalizacji.
Teraz aby moc uzywac tej tablicy w klasie, przekazuj ja do konstruktora:
<?php
$landSetting = 'pl_PL';
require_once($landSetting . '.lang.php');
$foo = new Foo($lang[$landSetting]);
class Foo {
var $_lang = null;
function Foo(&$lang) {
$this->_lang = &$lang;
}
}
?>
Robie tak bo nie chce uzywac globali.
Zastanawiam sie teraz, czy dalo by sie to jednak inaczej zapisac.
Moze zamiast przekazywania tablicy uzyc singletonu zawierajacego ta tablice i odwolywac sie do niej np tak:
<?php
Lang::getMsg('app.title', 'pl_PL')
?>
?
Ogolnie chodzi mi o to zeby wewnatrz obiektu moc sie dostac do pliku jezykowego bez uzywania global.
Ma ktos jakies pomysly?
splatch
5.05.2006, 21:36:48
Bardzo przydatny temat dla wszystkich którzy odwiedziają ten wątek:
http://forum.mojavi.org/index.php?showtopic=1502&st=0Są tam diagramy które ilustrują istotę działania. Polecam uwadze wszystkich.
AveNET
20.05.2006, 09:54:11
Mam taką tablicę
<?php
'Ave' => 'Łukasz Peroń',
'JK' => 'Jan Kowalski',
);
?>
Chciałbym żeby zamiast za każdym razem pisać (aby się wyświetliło Łukasz Peroń)
<?php
?>
żeby stosować krótką forme (taką jak niżej) ale o tym samym działaniu co powyższy kod
<?php
{%Ave%}
?>
Może ktoś ma pomysł jak to zrobić, wielkie THX
DeyV
20.05.2006, 21:20:50
Cytat(Seth @ 2006-05-05 13:20:27)
Ogolnie chodzi mi o to zeby wewnatrz obiektu moc sie dostac do pliku jezykowego bez uzywania global.
A może po prostu nie używać tablicy?
W końcu jest tyle "ładniejszych" rozwiązań?
Można np. przechowywać te dane w pliku pl_PL.ini (.php) który nie tylko jest szybciej parsowany, niż php, to na dodatek - łatwiejszy do generowania z utomatu.
Równie dobrze - można te dane przechowywać przecież w mini klasach, a wtedy korzystanie z sigletona staje się już banalne.
Choć osobiście najbardziej żałuję, że prace z plikami .po / .mo z gettexta jest w tej chwili tak skomplikowana, ponieważ najchętniej na nie przerzuciłbym cały ten problem - choćby z uwagi na wydajność i wszechstonność (obsluga liczb pojedynczych i mnogich, odmiany itp.)
g00fy
1.06.2006, 20:23:06
a co powiedzie o languagefactory::GetLang()
a pozniej w miejscach w tpl <? $lang->get('id_slowa');?>
?
nasty
4.06.2006, 19:22:50
Moim zdaniem, (ja tak zrobilem w moim programie ktory teraz pisze), w pliku php, zrobic array :
Angielskie:
<?php
"ok" => "OK",
"yes" => "Yes",
"no" => "No",
"user not found" => "User not found");
?>
Polskie:
<?php
"ok" => "OK",
"yes" => "Tak",
"no" => "Nie",
"user not found" => "U?ytkownik nie istnieje");
?>
Wyjasniam, texty w plikach sa zachowane w tej postaci, znaczy sie "key" od przeumaczonego slowa albo zdanie to jest to samo zdanie tylko ze po angielsku, wtedy bedziesz wyswietlal error np. user not found, to poszuka w array czy jest index z takim kluczem, jak tak to go wyswietli a jak nie to wyswietli to zdanie ktore pisales, ktore tez jest poprawne.
a oto funkcja to tumaczy:
<?php
function _($string) {
$language = $_CFG['system_language'];
require_once("i18n/lang.$language.php");
if(!empty($cp_Lang[$string])) { return $cp_Lang[$string];
} else {
return $string;
}
}
?>
t tak mozesz byc pewien ze nigdy nikt nie zobaczy bledu zwiazanego z nie znalezieniem polskiego (czy innego) odpowiednika.
DooBLER
3.12.2006, 09:13:15
Witam
Odgrzeję kotleta...
Piszę średniej wielkości aplikację i także stanąłem przed problemem wielojęzyczności.
Miałem zamiar rozwiązać to przy pomocy plików językowych zawierających tablice z całymi "zdaniami"
Jednak po przeczytaniu tego tematu zainteresowałem się plikami .po/.mo (zwłaszcza, że miałem z nimi już do czynienia przy okazji tłumaczenia jakiejś gry...)
I teraz mam prośbę do kogoś kto kożysta z tego sposobu tłumaczenia w php.
Proszę o jakieś fragmęty kodu jak się używa tych plików.
I jescze nasówa mi się pytanie czy na serwerze nie musi być coś doinstalowywane żeby obsługa tych plików była możliwa, bo jeśli tak to niestety ten sposób lokalizacji odpada
Pozdrawiam
cicik
3.12.2006, 17:03:29
Można też skorzystać z TMX, zunifikowany opis XMLowy.
Sh4dow
4.12.2006, 10:55:20
Nie wiem czy ktoś wogóle o tym słyszał czy używał, ale ja osobiscie pracuje z gettextem. Bardzo szybki, duzo narzedzi okienkowych, z webowymi jest gorzej, chociaz sam juz napisałem cos takiego ale jest jeszcze w wersji wczesnych beta, jesli nie masz tlumaczenia dla klucza, to pokazuje ci sie klucz, niby wymaga od uzytkownika zeby klucze byly pelnymi zdaniami, ale chociaz szablony dla widoku sa czytelniejsze. Problemy: trzeba przygotowywac pliki poprzez kompliacje.
Jeszcze jeden blad to to ze serverrobi cache plikow skompilowanych i przy czestej edycji nie widac poprawek. Ale sa sposoby na obejscie tego problemu
Właśnie o gettext była mowa, gdy wspominaliśmy o Babel oraz plikach .mo i .po
pawkow
21.03.2007, 20:27:11
Problem multijęzykowości rozwiązałem w prosty sposób. Mam taką strukturę katalogów:
Kod
| Languages
| -- Polish
| -- | -- global.php
| -- | -- header.php
| -- | -- footer.php
| -- | -- cośtam.php
| -- English
| -- | -- global.php
| -- | -- header.php
| -- | -- footer.php
| -- | -- cośtam.php
I w bazie mam np. artykuły: id, pl_title, eng_title, pl_body, eng_body
W cookies trzymam pl lub eng, i sprawdzam w aplikacji, czy jest pl, czy eng. Jeżeli nie ma lub jest inne, to korzystam z default (pl) i ładuję odpowiednie pliki językowe w odpowiednich częściach aplikacji, oraz pobieram odpowiednie treści z bazy danych. Proste, i wydajne
mike
21.03.2007, 20:30:23
Cytat(pawkow @ 21.03.2007, 20:27:11 )

Proste, i wydajne
Sposób najgorszy z możliwych.
Jakbym miał 5 wersji językowych i znalazł błąd w jednym z plików to by mnie coś trafiło przy poprawianiu.
Odradzam stanowczo takich rozwiązań.
pawkow
21.03.2007, 21:16:19
musiałbyś poprawić tylko jeden plik, czy się mylę ?
Zeman
3.04.2007, 21:34:22
Korzystam z autorskiego edytora i 2 pluginów multijezykowych:
1. pierwszy pozwala mi pisać w kodzie php coś takiego
<?php
echo('{*pl:To jest komputer**eng:This is computer*}'); ?>
i wypluwa kod php z zamienionym powyższym na mniej więcej
<?php
echo(''.lang_const_1
.''); ?>
oraz dodatkowy plik ze stałymi
2. drugi wyciąga wszystkie zastosowania powyższej postaci z wszystkich plików projektu i zestawia je w siatce
Suma sumarum w efekcie końcowym można powiedzieć że stosuję metodę podstawiania stałych i tworzenia plików postaci .../pl/index.php gdzie są stałe z tekstami.
Pozwiodronka,
Zeman.
Diabl0
4.04.2007, 01:17:23
Widzę że prawie każdy skupił się tylko na jednej (IMHO prostszej) stronie medalu jakim są teksty stałe. Tutaj w zasadzie pomysły są 2/3 (tablice, pliki ini i pokrewne własne formaty i ewentualnie i18n) różniące się tylko sposobem implementacji. Mnie natomiast interesuje ta ciekawsza strona medalu jaką jest:
Jak rozwiązujecie kwestie wielu języków w bazach danych.
Jak do tego podchodzicie robiąc projekt z założenia 2-językowy (np. pl i en) oraz jak to rozwiązujecie mając w planie pełną wielojęzykowość bez z góry określonej liczby języków. Interesuje mnie nie tylko jak kształtujecie samą bazę ale także typowe odwołania do niej.
W przypadku projektów 2-językowych korzystam głównie z typowej konstrukcji wielokolumnowej:
id | date | title_pl | title_en | content_pl | content_en
dorzucając do niej ewentualnie pole boolean valid_{$lang} określające czy dany język występuje w danym rekordzie.
Użycie w kodzie dość banalne:
$SQL = 'SELECT title_' . $_USER['lang'] . ', content_'' . $_USER['lang'] itd
Natomiast w przypadku projektów wielojęzykowych mam zawsze dylemat jak konstruować bazę danych.
Sedziwoj
4.04.2007, 01:31:24
Czy mi się wydaje czy to jest jeden 'artykuł' -> wiele wersji? Bo takie określenie podsuwa od razu sposób rozwiązania.
czyli tabele wiążącą 'artykuł' z treścią, coś w stylu:
artykul_id|tresc_id|jezyk_id
(czy coś podobnego, bo język można przecież określić na zbiorze, ale z drugiej strony może być w tabeli języków nazwa skrótowa jak i cała, też ułatwi sprawdzenie jakie języki obsługuje)
Ale to tak na z marszu piszę, do tego mam nikłe doświadczenie, więc lepiej niech ktoś lepszy w tych sprawach skomentuje...
Athlan
4.04.2007, 07:05:59
Moim zdaniem baza danych w zupełności odpada, bez sensu, przy dużych iloścach informacji czas działania aplikacji zwrasta, a nie o to chodzi. U mnie wszystkie pliki językowe siedzą w plikach:
/Application/Languages/Polish/Polish.Language.php - domyślny plik języka polskiego
/Application/Languages/Polish/Subgrupa_Polish.Language.php - inny plik języka polskiego, przykład:
/Application/Languages/Polish/Register_Polish.Language.php
Budowa takiego pliku jest następująca:
<?php
final class fr_Vlang extends VlangPattern
{
public $foo = 'C’est le foo.';
public $change_id = 'Polski';
public $change_sr = 'FR';
public $entry_add_true = 'L’entrée a été ajoutée avec succes! Afficher?';
public $entry_add_false = 'Erreur de base de données, entrée non ajoutée!';
public $entry_add_false_text = 'Copiez ici le code a ajouter!';
public $entry_add_false_token = 'L’identifiant d’autorisation est erroné!';
public $entry_link = 'Voici le lien vers votre entrée:';
public $entry_connection_lost = 'Impossible d’accéder au serveur, réessayez.';
// itd itd itd...
}
?>
Dodatkowo automatycznie wybierany jest domyślny język użytkownika. Aby wymusić priorytet języka, w jego folderze tworzymy plik Język.tmp z wartością w środku od 0.1 - 1, przykład:
/Application/Languages/Polish/Polish.tmp
Klasy:
http://framework.vgroup.pl/expose-409ea1a4...af9923731ec.htmhttp://framework.vgroup.pl/expose-d41766b6...fb6deba59c0.htmPrzykład działania wielojęzykowości możecie zobaczeć na www.cpaste.com... działa pięknie

Pozdrawiam, Athlan
Sedziwoj
4.04.2007, 10:02:09
Cytat(Athlan @ 4.04.2007, 08:05:59 )

Moim zdaniem baza danych w zupełności odpada, bez sensu, przy dużych iloścach informacji czas działania aplikacji zwrasta
Czyli Twoim zdaniem przy dużych ilościach informacji trzeba używać plików nie baz danych
Zeman
4.04.2007, 11:11:42
Cytat(Diabl0 @ 4.04.2007, 02:17:23 )

...
id | date | title_pl | title_en | content_pl | content_en
...
Użycie w kodzie dość banalne:
$SQL = 'SELECT title_' . $_USER['lang'] . ', content_'' . $_USER['lang'] itd
...
Natomiast w przypadku projektów wielojęzykowych mam zawsze dylemat jak konstruować bazę danych.
Takie podejście może być trochę męczące przy pisaniu zapytań. Ponadto nie bardzo daje możliwość utworzenia różnych danych dla różnych języków, mam na myśli przykładowo, że sklep oferuje w wersji polskiej pewną ilość produktów, w wersji angielskiej może niektórych produktów nie chcieć proponować. Jeszcze bardziej gdy wyobrazimy sobie produkty w sklepie i komentarze klientów, jakby nie patrzeć, nie możemy kazać komentować we wszystkich językach naraz

Osobiście preferuję nazwy tabel products_pl, products_eng, products_de, ....
i oczywiście 'SELECT id, title, .. FROM products_'.$lang.' ...'
Jeśli klient jednak przewiduje że każdy rekord będzie miał odzwierciedlenia we wszystkich językach, to niby można się pokusić o sposób id | date | title_pl | title_en | content_pl | content_en, choć osobiście pewnie bym zastosował coś innego, co to jeszcze nie wiem, bo nie miałem przypadku żeby każdy rekord miał być we wszystkich językach. Można niby tabelę "mapującą" products: products_pl_id, products_en_id, ...
Kayne
4.04.2007, 14:29:46
Hm... Jest trochę prostsze rozwiązanie, z którego ja korzystam. Może i jest przez to więcej rekordów w bazie danych... no ale cóż

Ogólnie koncepcja jest prosta. Mamy tabelę articles:
id | date | title | body | author |
langPole lang jest polem CHAR (2) w którym mamy podane np.: pl, en, fr...
Czyli pobranie artykułu po angielsku to po prostu:
<?php
$test = mysql_query('SELECT * FROM articles WHERE lang='en
'); ?>
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
Kayne
6.04.2007, 11:48:54
No, powtarzają się, ale jest to bardzo łatwe do zaimplementowania. Odpowiednia budowa tabel w bazie danych a będzie śmigać aż miło
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.