Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wielojęzykowość
Forum PHP.pl > Forum > PHP > Pro
Stron: 1, 2, 3, 4
Ociu
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.
pEbE
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
jeżeli w projekcie masz zamiar używać OPT, to ja na twoim miejscu użył bym opt'owego i18n ;]
sf
Smarty: {config_load file="text.conf" section=$language} no i posprzątane
NuLL
Ja korzystam z modifiera SMARTY
  1. {"Jakis_tam_komunikat"|lang:"admin"}

Przepuszczam to przez modifier lang z paramtrem admin.
TomASS
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:

  1. <?php
  2. $Lang['Enter'] = 'Wejście';
  3. $Lang['Exit'] = 'Wyjście';
  4. .
  5. .
  6. .
  7. ?>

i tak plik normalnie includuje....
eMartio
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.tpl
Kod
<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
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
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
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:

  1. <?php
  2. $Lang['Enter'] = 'Wejście';
  3. $Lang['Exit'] = 'Wyjście';
  4. .
  5. .
  6. .
  7. ?>

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 biggrin.gif podoba mi się biggrin.gif

z resztą ten sposób jest użyty także w sugarCRM.
splatch
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
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.
Ace
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"
dtb
ja wczytuje zawartosc pliku ini dla wybranego jezyka do tablicy (parse_ini_file) a potem po prostu:
{$lang[costam][costam]}
krzemian
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
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:
  1. ID | Tytul | Tresc | Lang

Potem w zalezności od wybranego języka wybieram potrzebne dane np.:
  1. SELECT *
  2. FROM tabela
  3. 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:
  1. <?php
  2. {$Translation.StronaGlowna}
  3. ?>

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
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
A co wy na to (suma kilku pomysłów):
  1. <?php
  2.  function array_path_insert(&$array, $sep, $path, $value)
  3.  {
  4.  $path_el = split($sep, $path);
  5.  
  6.  $arr_ref =& $array;
  7.  
  8.  for($i = 0; $i < sizeof($path_el); $i++)
  9.  {
  10.  $arr_ref =& $arr_ref[$path_el[$i]];
  11.  }
  12.  
  13.  $arr_ref = $value;
  14.  }
  15.  
  16. $trans=array();
  17.  
  18. foreach(file("translations/{$lang}.txt") as $line)
  19. {
  20. $chunks=explode("=", $line);
  21. define("TXT_".array_shift($chunks), implode("=", $chunks));
  22. /* define("TXT_".array_shift($chunks), eval(implode("=", $chunks))); // tak jakby chciać tutaj włożyć jakąś logikę */
  23. /* define("TXT_".array_shift($chunks), str_replace('\n', "\n", implode("=", $chunks))); // tutaj jakby nie chcieć interpretować wszystkiego */
  24. /* można też zrobić preg_replace z tablicami */
  25. /* XXX: Ależ mi nachodzi pomysłów. Dla tablicowców-smartowców następna wersja. (funkcje znalazłem w komentarzach do manuala) */
  26. array_path_insert($trans, '.', array_shift($chunks), implode("=", $chunks));
  27. }
  28. $smarty->cośtam('lang', $trans);
  29. ?>
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
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
A co, jeśli w tłumaczonym tekście wystąpi znak "=" bądź przełamanie linii?
Ociu
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
sf
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
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
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
Przepraszam będe pisał bez shifta bo siedze w szkole smile.gif

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ę
  1. <?php
  2. _("Tłumacz mnie");
  3. ?>
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
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
moze pomoze:

http://www.tutorialized.com/tutorial/Multi...ge-System/12488

pozdro
Seth
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:
  1. <?php
  2. $lang['pl_PL'] = array(
  3. 'app' => array(
  4.  'title' => 'Test'
  5. )
  6.  );
  7. ?>


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:

  1. <?php
  2. $landSetting = 'pl_PL';
  3.  
  4. require_once($landSetting . '.lang.php');
  5.  
  6. $foo = new Foo($lang[$landSetting]);
  7.  
  8. class Foo {
  9.  var $_lang = null;
  10.  
  11.  
  12.  function Foo(&$lang) {
  13. $this->_lang = &$lang;
  14.  }
  15. }
  16. ?>


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:

  1. <?php
  2. Lang::getMsg('app.title', 'pl_PL')
  3. ?>

?


Ogolnie chodzi mi o to zeby wewnatrz obiektu moc sie dostac do pliku jezykowego bez uzywania global.

Ma ktos jakies pomysly? smile.gif
splatch
Bardzo przydatny temat dla wszystkich którzy odwiedziają ten wątek: http://forum.mojavi.org/index.php?showtopic=1502&st=0

Są tam diagramy które ilustrują istotę działania. Polecam uwadze wszystkich.
AveNET
Mam taką tablicę
  1. <?php
  2.  
  3. $lang=array (
  4.  
  5. 'Ave' => 'Łukasz Peroń',
  6. 'JK' => 'Jan Kowalski',
  7.  
  8. );
  9.  
  10. ?>


Chciałbym żeby zamiast za każdym razem pisać (aby się wyświetliło Łukasz Peroń)
  1. <?php
  2. echo $lang['Ave'];
  3. ?>


żeby stosować krótką forme (taką jak niżej) ale o tym samym działaniu co powyższy kod

  1. <?php
  2. {%Ave%}
  3. ?>


Może ktoś ma pomysł jak to zrobić, wielkie THX
DeyV
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
a co powiedzie o languagefactory::GetLang()
a pozniej w miejscach w tpl <? $lang->get('id_slowa');?>
?
nasty
Moim zdaniem, (ja tak zrobilem w moim programie ktory teraz pisze), w pliku php, zrobic array :
Angielskie:
  1. <?php
  2. $cp_Lang = array(
  3. "ok" => "OK",
  4. "yes" => "Yes",
  5. "no" => "No",
  6. "user not found" => "User not found");
  7. ?>

Polskie:
  1. <?php
  2. $cp_Lang = array(
  3. "ok" => "OK",
  4. "yes" => "Tak",
  5. "no" => "Nie",
  6. "user not found" => "U?ytkownik nie istnieje");
  7. ?>

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:
  1. <?php
  2. function _($string) {
  3.  
  4. $string = trim(strtolower($string));
  5. $language = $_CFG['system_language'];
  6. require_once("i18n/lang.$language.php");
  7.  
  8. if(!empty($cp_Lang[$string])) {
  9. return $cp_Lang[$string];
  10. } else {
  11. return $string;
  12. }
  13.  
  14. }
  15. ?>

t tak mozesz byc pewien ze nigdy nikt nie zobaczy bledu zwiazanego z nie znalezieniem polskiego (czy innego) odpowiednika.
DooBLER
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
Można też skorzystać z TMX, zunifikowany opis XMLowy.
Sh4dow
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
DeyV
Właśnie o gettext była mowa, gdy wspominaliśmy o Babel oraz plikach .mo i .po smile.gif
pawkow
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
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
musiałbyś poprawić tylko jeden plik, czy się mylę ?
Zeman
Korzystam z autorskiego edytora i 2 pluginów multijezykowych:

1. pierwszy pozwala mi pisać w kodzie php coś takiego
  1. <?php
  2. echo('{*pl:To jest komputer**eng:This is computer*}');
  3. ?>

i wypluwa kod php z zamienionym powyższym na mniej więcej
  1. <?php
  2. echo(''.lang_const_1.'');
  3. ?>
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
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
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
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:

  1. <?php
  2.  
  3. final class fr_Vlang extends VlangPattern
  4. {
  5. public $foo = 'C’est le foo.';
  6.  
  7. public $change_id = 'Polski';
  8. public $change_sr = 'FR';
  9.  
  10. public $entry_add_true = 'L’entrée a été ajoutée avec succes! Afficher?';
  11. public $entry_add_false = 'Erreur de base de données, entrée non ajoutée!';
  12. public $entry_add_false_text = 'Copiez ici le code a ajouter!';
  13. public $entry_add_false_token = 'L’identifiant d’autorisation est erroné!';
  14. public $entry_link = 'Voici le lien vers votre entrée:';
  15. public $entry_connection_lost = 'Impossible d’accéder au serveur, réessayez.';
  16.  
  17. // itd itd itd...
  18.  
  19. }
  20. ?>


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.htm
http://framework.vgroup.pl/expose-d41766b6...fb6deba59c0.htm

Przykład działania wielojęzykowości możecie zobaczeć na www.cpaste.com... działa pięknie smile.gif

Pozdrawiam, Athlan
Sedziwoj
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 blinksmiley.gif
Zeman
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 winksmiley.jpg

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
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óż winksmiley.jpg

Ogólnie koncepcja jest prosta. Mamy tabelę articles:

id | date | title | body | author |lang

Pole lang jest polem CHAR (2) w którym mamy podane np.: pl, en, fr...

Czyli pobranie artykułu po angielsku to po prostu:

  1. <?php
  2. $test = mysql_query('SELECT * FROM articles WHERE lang='en');
  3. ?>
bela
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
No, powtarzają się, ale jest to bardzo łatwe do zaimplementowania. Odpowiednia budowa tabel w bazie danych a będzie śmigać aż miło smile.gif
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-2019 Invision Power Services, Inc.