Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Pro _ Wielojęzykowość

Napisany przez: Ociu 1.04.2006, 18:29:19

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.


Byłbym wdzięczny za propozycje rozwiązań.
Wojtek.

Napisany przez: pEbE 1.04.2006, 20:31:20

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

Napisany przez: 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 ;]

Napisany przez: sf 2.04.2006, 09:59:36

Smarty: {config_load file="text.conf" section=$language} no i posprzątane

Napisany przez: NuLL 7.04.2006, 00:59:47

Ja korzystam z modifiera SMARTY

  1. {"Jakis_tam_komunikat"|lang:"admin"}

Przepuszczam to przez modifier lang z paramtrem admin.

Napisany przez: 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:

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

i tak plik normalnie includuje....

Napisany przez: 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.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

Napisany przez: 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.

Napisany przez: Fipaj 9.04.2006, 18:36:07

http://developer.gnome.org/projects/gtp/translate-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.

Napisany przez: 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:

  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.

Napisany przez: 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..

Napisany przez: 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.

Napisany przez: Ace 13.04.2006, 08:45:23

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"

Napisany przez: dtb 13.04.2006, 14:54:21

ja wczytuje zawartosc pliku ini dla wybranego jezyka do tablicy (parse_ini_file) a potem po prostu:
{$lang[costam][costam]}

Napisany przez: 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ę.

Napisany przez: 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:
  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ę

Napisany przez: 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.

Napisany przez: Jabol 16.04.2006, 21:23:09

A co wy na to (suma kilku pomysłów):

  1. <?php
  2.  function array_path_insert(&$array, $sep, $path, $value)
  3.  {
  4.  $path_el = http://www.php.net/split($sep, $path);
  5.  
  6.  $arr_ref =& $array;
  7.  
  8.  for($i = 0; $i < http://www.php.net/sizeof($path_el); $i++)
  9.  {
  10.  $arr_ref =& $arr_ref[$path_el[$i]];
  11.  }
  12.  
  13.  $arr_ref = $value;
  14.  }
  15.  
  16. $trans=http://www.php.net/array();
  17.  
  18. foreach(http://www.php.net/file("translations/{$lang}.txt") as $line)
  19. {
  20. $chunks=http://www.php.net/explode("=", $line);
  21. http://www.php.net/define("TXT_".http://www.php.net/array_shift($chunks), http://www.php.net/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, '.', http://www.php.net/array_shift($chunks), http://www.php.net/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.

Napisany przez: 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.

Napisany przez: Fipaj 17.04.2006, 14:24:45

A co, jeśli w tłumaczonym tekście wystąpi znak "=" bądź przełamanie linii?

Napisany przez: 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

Napisany przez: sf 18.04.2006, 17:56:26

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?

Napisany przez: 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ć.

Napisany przez: 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 :]

Napisany przez: Neotion 27.04.2006, 07:20:49

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.

Napisany przez: 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

Napisany przez: sadu 27.04.2006, 10:47:56

moze pomoze:

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

pozdro

Napisany przez: Seth 5.05.2006, 13:20:27

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'] = http://www.php.net/array(
  3. 'app' => http://www.php.net/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

Napisany przez: 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=0

Są tam diagramy które ilustrują istotę działania. Polecam uwadze wszystkich.

Napisany przez: AveNET 20.05.2006, 09:54:11

Mam taką tablicę

  1. <?php
  2.  
  3. $lang=http://www.php.net/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. http://www.php.net/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

Napisany przez: 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.)

Napisany przez: g00fy 1.06.2006, 20:23:06

a co powiedzie o languagefactory::GetLang()
a pozniej w miejscach w tpl <? $lang->get('id_slowa');?>
?

Napisany przez: nasty_psycho 4.06.2006, 19:22:50

Moim zdaniem, (ja tak zrobilem w moim programie ktory teraz pisze), w pliku php, zrobic array :
Angielskie:

  1. <?php
  2. $cp_Lang = http://www.php.net/array(
  3. "ok" => "OK",
  4. "yes" => "Yes",
  5. "no" => "No",
  6. "user not found" => "User not found");
  7. ?>

Polskie:
  1. <?php
  2. $cp_Lang = http://www.php.net/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 = http://www.php.net/trim(http://www.php.net/strtolower($string));
  5. $language = $_CFG['system_language'];
  6. require_once("i18n/lang.$language.php");
  7.  
  8. if(!http://www.php.net/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.

Napisany przez: 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

Napisany przez: NuLL 3.12.2006, 12:55:27

http://forum.php.pl/index.php?showtopic=42371&hl=babel

Napisany przez: cicik 3.12.2006, 17:03:29

Można też skorzystać z TMX, zunifikowany opis XMLowy.

Napisany przez: 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

Napisany przez: DeyV 7.12.2006, 23:18:16

Właśnie o gettext była mowa, gdy wspominaliśmy o Babel oraz plikach .mo i .po smile.gif

Napisany przez: 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

Napisany przez: mike_mech 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ń.

Napisany przez: pawkow 21.03.2007, 21:16:19

musiałbyś poprawić tylko jeden plik, czy się mylę ?

Napisany przez: 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

  1. <?php
  2. http://www.php.net/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. http://www.php.net/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.

Napisany przez: 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.

Napisany przez: 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...

Napisany przez: 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:

  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-409ea1a412f8a48d3703baf9923731ec.htm
http://framework.vgroup.pl/expose-d41766b69aca6da4657ebfb6deba59c0.htm

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

Pozdrawiam, Athlan

Napisany przez: 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 blinksmiley.gif

Napisany przez: 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 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, ...

Napisany przez: 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óż 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 = http://www.php.net/mysql_query('SELECT * FROM articles WHERE lang='en');
  3. ?>

Napisany przez: bela 4.04.2007, 16: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

Napisany przez: 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 smile.gif

Napisany przez: 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 http://www.symfony-project.com/book/trunk/13-I18n-and-L10n wub.gif

Napisany przez: bela 9.04.2007, 19:52:04

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.

Napisany przez: 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.

Napisany przez: 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 smile.gif. 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 smile.gif and so on ...

pozdro

... tak zrobię a potem podzielę się uwagami z pola boju

Napisany przez: 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?

Napisany przez: 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.

Napisany przez: kubarek 13.05.2007, 20:02:42

moja idea:

  1. <?php
  2. class language
  3. {
  4.  
  5.  function __construct($language='pl'){
  6. $this->language=$language;
  7. $this->get_data();
  8.  }
  9.  
  10.  function __get($id){
  11. return $this->data[$id];
  12.  }
  13.  
  14.  function get_data(){
  15. /* funkcja jakoś pobierze dane językowe, np z bazy danych mysql */
  16. /* mogą być to dane zapisane już jako tablica w pliku php */
  17. http://www.php.net/mysql_query(); 
  18. include 'plik_z_jezykiem_'.$this->language.'.php';
  19. /* etc. */
  20. $this->data=...
  21.  }
  22.  
  23. }
  24.  
  25. $l='pl';
  26.  
  27. $lang=new language($l);
  28.  
  29. http://www.php.net/echo $lang->10;
  30. http://www.php.net/echo $lang->1337;
  31. ?>


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

Napisany przez: eai 14.05.2007, 09:41:24

Mój sposób wygląda tak:
Plik Global_Lang.php:

  1. <?php
  2.  
  3. $glang[] = 'polish';
  4. $glang[] = 'english';
  5. $glang[] = 'spanish';
  6.  
  7. ?>


Folder __language: Zawiera pod foldery z plikami językowymi oraz z interfejsem

interface.php:
  1. <?php
  2.  
  3. $interface['val1'] = null;
  4. $interface['val2'] = null;
  5. $interface['val3'] = null;
  6. //... itd są to indexy które muszą występować w każdym pliku językowym w tym folde
    rze
  7. ?>

lang.polish.php:
  1. <?php
  2.  
  3. $lang['val1'] = 'czesc';
  4. $lang['val2'] = 'czas';
  5. $lang['val3'] = 'zegnaj';
  6. ?>


lang.english.php:
  1. <?php
  2.  
  3. $lang['val1'] = 'hello';
  4. $lang['val2'] = 'time';
  5. $lang['val3'] = 'goodbye';
  6. ?>


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.

Napisany przez: 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...

Napisany przez: 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.

Napisany przez: 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.

Napisany przez: 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.

Napisany przez: 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"

Napisany przez: 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.

Napisany przez: 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.

Napisany przez: Strzałek 1.03.2008, 12:07:43

W http://phpdoctrine.org/ jest plugin do i18n. Wielojęzykowość staje się wtedy bardzo przyjemna.

http://www.phpdoctrine.org/documentation/manual/0_10?one-page#plugins:internationalization-with-i18n

Napisany przez: 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.

Napisany przez: 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:

  1. <?php
  2. //po wykonaniu wcześniejszego Doctrine_Query
  3.  
  4. http://www.php.net/echo $items[0]->Translation['PL']->title; // 'Witaj Świecie'
  5. ?>


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.

Napisany przez: 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:

  1. <?php
  2. //[...]
  3.  
  4. $lang_prefix = ('pl');
  5.  
  6.  
  7. $sql="SELECT * FROM ".$lang_prefix."news ORDER BY dodano DESC";
  8. //[...]
  9. ?>

Napisany przez: 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:
  1. <?php
  2. //[...]
  3.  
  4. $lang_prefix = ('pl');
  5. $sql="SELECT * FROM ".$lang_prefix."news ORDER BY dodano DESC";
  6. //[...]
  7. ?>

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?

Napisany przez: radex_p 23.05.2008, 17:52:07

Mam jeden prosty i sprawdzony sposób.

  1. <?php
  2. http://www.php.net/echo __('Witaj Świecie!');
  3. ?>


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.

Napisany przez: Sedziwoj 23.05.2008, 19:10:41

@radex_p
Co innego tłumaczenie statycznych rzeczy, co innego dynamicznie dodawanych.

Napisany przez: radex_p 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.

Napisany przez: 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. winksmiley.jpg

Napisany przez: radex_p 24.05.2008, 08:40:48

aaaaa..... Teraz już rozumiem tongue.gif

Napisany przez: 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.

Napisany przez: 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ł smile.gif
Miałem tabele w bazie danych:
strings
id (int)
lang
content (varchar255)
texts
id (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:

products
id
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)

Napisany przez: 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.

Napisany przez: 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:

lub: wykorzystanie "modyfiera" Smarty, innego gotowego rozwiązania


dla elementów dynamicznych (każdy język -> inna treść):dla elementów dynamicznych (każdy język -> taka sama treść):EDIT:
by Sedziwoj: tabela z językami
  1. [b]lang[/b]
  2. id | short_name | name
  3. --------------------------
  4. 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!

Napisany przez: 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.

Napisany przez: rzymek01 30.05.2008, 13:39:42

racja, mój błąd smile.gif

nie chciałem już mieszać, bo na początku chciałem zrobić lang_id

Napisany przez: 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?

Napisany przez: Sedziwoj 7.07.2008, 08:00:55

@Blodo
Może coś w tym stylu:

  1. 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.

Napisany przez: 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.

Napisany przez: 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.

Napisany przez: 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:

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.

Napisany przez: 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:

  1. <?php
  2. throw new exception (..)
  3. ?>

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

Napisany przez: 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:

  1. <?
  2. throw new Exception(myTransolator('invalidABCDE'));
  3. ?>

2) Napisać właśną klasę wyjątków, która robi to co kod powyżej, ale już wewnątrz siebie:
  1. <?
  2. class MyException extends Exception{
  3.  public function __construct($msg = '', $code = 0){
  4.    $this->msg = myTranslate($msg);
  5.    $this->code = $code;
  6.  }
  7. }
  8. ?>
Ale jeszcze raz zapytam: po co?

Napisany przez: 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

Napisany przez: 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.

Napisany przez: 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

Napisany przez: erix 2.07.2009, 10:27:14

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 http://pl.php.net/gettext.

Napisany przez: 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.

Napisany przez: viking 2.07.2009, 11:23:21

To zainteresuj się Zend Framework (i zanim napiszesz coś o gettext przeczytaj dokładnie dokumentację).

Napisany przez: 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 ?

Napisany przez: bim2 2.07.2009, 11:54:13

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. http://pl.php.net/gettext 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.

Napisany przez: 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.

Napisany przez: 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...

Napisany przez: Crozin 2.07.2009, 12:56:10

Zapewne da się ten komponent "wyciąć" z niego i stosować osobno.

Napisany przez: erix 2.07.2009, 14:18:37

Cytat
tak tylko aplikacja ma być przenośna, a gettext nie wszędzie jest zainstalowany.

Zobacz sobie, jak jest emulowane to rozszerzenie w Wordpressie.

Napisany przez: bim2 2.07.2009, 19:05:16

Wordpress jest najlepszym przykładem. smile.gif Ja także nie używam gettext(), jedynie się na tym wzoruje. Poszukać w google wystarczy "i18n php" i wyskoczy wiele różnych rozwiązań. Nawet na tym forum jakieś znalazłem smile.gif

Napisany przez: viking 3.07.2009, 06:19:05

Ewentualnie w PHP 5.3 jest coś takiego http://pl2.php.net/manual/en/class.messageformatter.php

Napisany przez: bim2 3.07.2009, 10:08:04

Tyle, że na php 5.3 na serwerach troche trzeba poczekać smile.gif Kolega robił update php wczoraj, ale na trójkę się nakłonić nie dał... nie wiem czemu ;/ ("bo wyszła dzisiaj")

Napisany przez: erix 3.07.2009, 12:22:11

Dziwisz się? Osobiście np. Fx-a zaktualizuje za może miesiąc; obie paczki są jeszcze za świeże, nie zostały wystarczająco przetestowane.

Wyjdzie 5.3.1, będzie można się nieco pobujać. [; Ale nie zmieni to faktu, że w ogóle na edycję 5.3 trzeba jeszcze poczekać co najmniej pół roku.

Napisany przez: omeck 7.07.2009, 00:52:47

Tak, do zalet gettext należy to, że jest lekki, szybki praktycznie ogólno dostępny... ale przekonaj klienta, żeby pobrał sobie z serwera pliczek z tłumaczeniami, pobrał i zainstalował sobie dodatkowe oprogramowanie np. poedit, wyedytował, a następnie wysyłał na serwer. Można też zrobić interfejs do aplikacji i generować np poprzez jakiś panel admina... jest jendno 'ale' - generowanie plików z tlumaczeniami, co wiąże się z dostepem do poleceń systemowych na serwerze... chyba malo ogolno dostępne, prawda? :-)
Dodatkowo: http://us2.php.net/manual/en/ref.gettext.php#50424 ;-)

Osobiście szczęśliwie korzystam z Zend_Translate oraz pliczków CSV - lekkie, proste, szybkie, wygodne i można bez zadnych przeszkód napisac do tego gui :-)

Napisany przez: Pr0100 7.07.2009, 02:07:41

Cytat
Tyle, że na php 5.3 na serwerach troche trzeba poczekać Kolega robił update php wczoraj, ale na trójkę się nakłonić nie dał... nie wiem czemu ;/ ("bo wyszła dzisiaj")


http://packages.debian.org/search?keywords=php5-cgi&searchon=names&suite=all&section=all

dziwisz się mu? winksmiley.jpg

PS: przepraszam za OT

Napisany przez: omeck 7.07.2009, 11:42:48

Cytat(Pr0100 @ 7.07.2009, 03:07:41 ) *
http://packages.debian.org/search?keywords=php5-cgi&searchon=names&suite=all&section=all

dziwisz się mu? winksmiley.jpg


Jeśli ktoś na gwałt potrzebuje paczki z PHP5.3 do Debiana, to jest dostępna na: http://www.dotdeb.org/2009/07/03/php-5-3-0-final-preview-packages-available-for-debian-lenny/. Koniecznie należy przeczytać "What are the changes from Dotdeb?"

PS: przepraszam za OT +1 ;-)

Napisany przez: erix 7.07.2009, 22:02:33

Cytat
do poleceń systemowych na serwerze... chyba malo ogolno dostępne, prawda? :-)

Serwery, których admini wiedzą, co to znaczy suPHP + jail dla procesu, nie mają zablokowanych poleceń systemowych. tongue.gif

Napisany przez: omeck 7.07.2009, 23:26:29

Cytat(erix @ 7.07.2009, 23:02:33 ) *
Serwery, których admini wiedzą, co to znaczy suPHP + jail dla procesu, nie mają zablokowanych poleceń systemowych. tongue.gif


Jaki to promil wszystkich adminów? :-)

Napisany przez: erix 8.07.2009, 11:55:59

Jakoś we wszystkich hostingach, z którymi mam do czynienia, polecenia systemowe nie są zablokowane.

Więc śmiem twierdzić, że to nie jest promil. tongue.gif

Napisany przez: witul 11.07.2009, 02:13:36

A ja stosuje podzial na baze i pliki:
np w cmsie zrobilem sobie ze jezyk jest subdomena serwisump, en.domena.pl czy de.domena.pl.
Szablony stron, teksty i inne elementy pisane sa osobno pod kazdy jezyk.
A jesli chodzi o statyczne teksty typu "Zapisz", "To pole jest wymagane" - wiadomo, pliki.

Napisany przez: jolam 20.08.2009, 10:39:40

Chciałam się poradzić w jednej sprawie dotyczącej spraw wielojęzykowości. Mam stronę w kilku językach, ale podstrony w tych językach niewiele różnią się od siebie. Strona zawiera głównie grafiki. To czy lepiej tłumaczyć fraz na tej stronie czy całą stronę. To znaczy, czy lepiej w kodzie tej strony, między grafikami mieć np $lang['tlumaczonytekst'], czy trzymać w bazie treść strony dla każdego języka i ładować odpowiednią stronę w zależności od wyboru usera? Teraz stosuje pierwsze rozwiązanie ale może tabela kolumnami textid, contentpl, contenten? Czy powinnam zastosować drugie rozwiązanie czy pozostac przy pierwszym?

pozdrawiam Jola

Zapomniałam napisać wprost, przy tej mojej metodzie z jedna stroną i tłumaczeniem fraz mam dużo małych zapytań do bazy. Gdybym zmieniła metodę to miałabym jedno duże zapytanie. Ale musiałabym mieć dwie treści i modyfikacje wprowadzać dwa razy i pamiętać o nich. Co lepsze?

Napisany przez: erix 20.08.2009, 11:53:20

A przeczytałaś cały wątek? tongue.gif

Napisany przez: rzymek01 20.08.2009, 11:57:10

W Twoim przypadku 1. sposób wydaje się lepszy, tylko od razu pobieraj wszystkie langi (dużo ich na pewno nie masz) albo zapisuj je w pliku (lub plikach jak chcesz podzielić na moduły)

Napisany przez: jolam 20.08.2009, 12:01:02

Oczywiście, że przeczytałam ten wątek, co za pytanie. Chcę się jedynie upewnić. Sposób 1 wydaje mi się wygodniejszy, dlatego go wybrałam. Ale obawiałam się o wydajność. Bo to kilka/kilkanaście zapytań do bazy, zamiast jednego dużego.

pozdrawiam Jola

Napisany przez: GregoryW 17.09.2009, 17:05:59

Korzystał ktoś kiedyś ze Smarty Multilanguage? Jeśli tak - jaką to ma wydajność?

Dzięki za info

Napisany przez: nospor 7.10.2009, 08:34:01

Pytanko/dylemat:

Zaznaczam od razu, że nie chodzi mi o artykuły/newsy. Chodzi mi o komunikaty w stylu: "dane zapisano", "Dodaj komentarz" etc.

Do tej pory miałem to w plikach .ini i było wszystko ok. Stanąłem jednak przed problemem, gdzie będę musiał dać klientowi możliwość edycji tych danych w panelu serwisu. Babranie się tu w edycję plików i do tego sensownie to grupować już nie jest takie fajne i przyjemne jak wówczas, gdyby to było wszystko bazie.
Do tego dochodzi problem, że ja mogę uaktualniać moduły i wraz z modułem mogą się uaktualnić pliki z tekstami. Jeśli klient by coś już zmodyfikował to ja przy aktualizacji bym mu to nadpisał.

A więc możliwe dwa rozwiązania:
1) pliki .ini
piszę jakiś systemik do aktualizacji danych. minusem będzie to, że gorzej się go będzie pisało niż dla DB
gdy klient zmodyfikuje jakiś zestaw danych, tworzony jest dodatkowy plik .ini z jego zmianami.
Gdy system będzie musiał odczytać jakiś tekst, szuka go najpierw w plikach zmodyfikowanych a jeśli tam go nie będzie, szuka w moich oryginalnych.
Jak widać trochę latania przy pobraniu tekstu tu będzie. Powiedzmy że bym zastosował cache to może by było znośnie.

2) tłumaczenia w bazie
O optymalność się nie martwie bo bym cacheowal.
Napisanie systemiku do edycji - w miarę proste.
Gdy ja dostarcze aktualizacje modułu z nowymi tekstami to wystarczy wykonać parę insertów i po sprawie - nic nikomu nie nadpiszę.
Minus - całe zarządzanie mam już na plikach .ini i bym musiał do bazy wrzucić wszystkie tłumaczenia jakie do tej pory mam.


Co Wy sądzicie o tym? Mieliście już do czynienia z taką właśnie sytuacją, że trzeba dać klientowi narzędzie do modyfikacji tekstów i mieć na uwadze kolejne aktualizacjie oprogramowania wraz z tekstami?

Napisany przez: vokiel 7.10.2009, 09:43:27

Jeszcze nie miałem takiej konieczności, jednak IMHO łatwiej byłoby w bazie.

Co do dodania już istniejących tłumaczeń do bazy, to w końcu tylko jednorazowa operacja. Ważne aby później było łatwiej korzystać z systemu.

W zasadzie, czy zrobisz to na ini, czy db, to i tak spełni swoje zadanie. Różnice mogą być w czasie potrzebnym na napisanie, a będą w przypadku późniejszych zmian.

Napisany przez: nospor 8.10.2009, 10:41:08

Rozpisałeś mi tutaj zaawansowany system w DB: akceptacja, zestawienia.... aż tak bardzo nie chciałem szaleć winksmiley.jpg
No nie rozwiałeś moich wątpliwości. To teoria, z której zdaję sobie sprawę. Mam nadzieję, że ktoś praktycznie miał z tym do czynienia.

edit:
dobra, robie na bazie. na plikach już mam to trzeba zadbac o nowe doświadczenia winksmiley.jpg

Napisany przez: nasty 9.10.2009, 02:19:28

A może zastosuj bazę i zrób małego bota co Ci wrzuci wszystko z tych .ini do bazy? smile.gif

Napisany przez: nospor 9.10.2009, 19:04:28

juz przepisałem ręcznie smile.gif

Napisany przez: bim2 11.10.2009, 20:19:02

Wszyscy się zastanawiają jak robić tłumaczenie, ale najprościej moim zdaniem zrobić podobnie jak ma wordpress. Sam tworzyłem teraz czterojęzyczny serwis i wychodzi, że najprościej jest dać np. w templatkach

Kod
<p>__Tekst__</p>
<p>__Tekst ze zmienna %s czegos__($zmienna)</p>

Dzięki temu jest nawet możliwość poprawy literówek już na poziomie bazy danych, nie plików bo kluczem jest md5(). Tak więc, dzięki temu jestem w stanie poprosić kilkoro ludzi do poprawiania literówek i tworzenia tłumaczeń bez konieczności szukania tego po plikach.

Napisany przez: cojack 12.10.2009, 15:45:42

Dla statycznych tekstów najlepiej jest użyć gettext. A dla trzymanych w bazie to l18n

Napisany przez: bim2 13.10.2009, 14:23:49

Hmm, ja miast gettext korzystam z własnego sytemu z racji tego, że były problemy z tym gettext. Cachowało mi jakimś cudem plik i nie było możliwośći wgrania najnowszwego pliku. Co do danych typu newsy, mam kolumnę lang i później w zapytaniach where :langW: tzn. where lang = 'pl' winksmiley.jpg

Napisany przez: cojack 13.10.2009, 15:45:56

Dokładnie, to żadna sztuczka ta wielojęzyczność. Mi tam gettext działa bez problemu, tylko to trochę upierdliwe jest z tymi tłumaczeniami ;p trzeba się opisać jak głupi winksmiley.jpg

Napisany przez: Crozin 14.10.2009, 14:26:43

@bim2: chyba osobną tabelę łączoną w relacji 1-1 (z id oraz językiem), a nie samą kolumnę smile.gif

Napisany przez: bim2 14.10.2009, 16:08:10

No tak. smile.gif Zależy co masz. Jak mam stronę statyczną gdzie występuje tylko Tytuł i Treść to mam jedną tabelę, bo tytuł też tłumaczymy smile.gif A id takie samo.

Napisany przez: jmail 14.10.2009, 16:18:12

nie wiem czy ktoś już to pisał :F

ja mam różne języki zapisane w tablicach php winksmiley.jpg i je wrzucam do templatki tak jak pozostałe zmienne. Kwestia pobrania odpowiedniego pliku językowego

Napisany przez: bim2 14.10.2009, 20:58:38

jmail także tak miałem, ale po n serwisach to jest niewydajne w trakcie pisania tego. Musisz dodać sobie do tablicy wpis, później w templatkach {$lang.user} Tylko nie wiesz ci kryje się pod user jakbyś chciał coś zmienić/dodać.

Gettext jest najlepszym wyjściem i radzę Ci się na to przerzucić.

Napisany przez: jmail 14.10.2009, 21:05:19

no jak tam kto uważa. dla mnie to jest wygodne i wydajne nie miałem jakoś probolemów do tej pory i jakoś tam działało biggrin.gif ale przejrzę to co proponujesz i zobaczymy

Napisany przez: marcio 22.10.2009, 22:53:05

Ok przeczytalem caly watek wywnioskowalem troche z niego tworzac wlasny "Fw" mysle ze przyda sie standartowa implementacja wielojezykowosci.

Dla stalych tresci zrobie to porostu tak:

Mam komponent news i jego opis autor,data,tresc i tytul i katalog jego widokow czyli:

Kod
|components

||views

|||News

||||Admin

|PL

|Eng

||||User

|PL

|Eng


No i na podstawie zmiennej sesyjnej wczytam odpowiedni widok z odpowiedniego katalogu(implementacja wczytywania w klase View a jezyku w innej)

Wydaje mi sie to wygodne,elastyczne i shcludnie wyglada.




Co do tresci np zawsze naszych news'ow zrobie to tak jak pokazal to @rzymek01 w poscie http://forum.php.pl/index.php?s=&showtopic=44703&view=findpost&p=476814 podpunkt:

Cytat
dla elementów dynamicznych (każdy język -> taka sama treść):


Zaprezentowany rozniez przez Kayne.




Co jednak dla wyswietlania bledow w kilku jezykach bo tego nie zrozumialem albo nie doczytalem jak to osiagnac powiedzmy ze ktos chce sie zalogowac jak w przypadku danego jezyka wyswietlic komunikat w odpowiednim jezyku myslalem by zrobic katalog errors w katalogu widoku danego komponentu/pluginu a nim tablice typu:

  1.  
  2. $err['pl']['badpwd'] = 'Zle haslo';
  3.  
  4. $err['eng']['badpwd'] = 'Bad login';
  5.  


Wtedy w kontrolerze komponentu/pluginu robic:

  1.  
  2. if(blad podczac logowania) $view -> AddVar('error', $lang -> errors[$lang -> getLang()]['badpwd']);
  3.  


Wydaje mi sie rozsadne czy sie myle moze zabardzo zamotane i zaduzo jest kalogow plikow czy cos?


Napisany przez: bim2 23.10.2009, 20:56:24

Ja byłbym nadal za i18n, nawet dla błędów smile.gif czyli $lang->get('Wrong login.');

Napisany przez: marcio 23.10.2009, 22:32:06

Czyli jak i gdzie zapisywac bledy?

Bo nie rozumiem.


Napisany przez: bim2 24.10.2009, 10:55:48

Nigdzie. Piszesz błąd jaki wystapił a tłumaczenie działa na zasadzie tłumaczenia całych fraz. Tj. ja mam w bazie danych tabelę langs z kolumnami hash|pl|en|pt|es Hash to md5 frazy, a reszty się chyba łatwo domyślić. Wszędzie piszę domyślnie po polsku czyli jak mam błąd to robię

  1.  
  2. $form->addError($lang->get('Niepoprawne hasło.'));

I później sprawdzam czy w bazie jest hash = md5($fraza) Jeśli nie ma dodaję ją do bazy z hashem i wypełnionym polem pl. Później tłumaczenie to zmiana en pt lub es. smile.gif

Napisany przez: marcio 24.10.2009, 12:44:14

Wole to trzymac w plikach tongue.gif i zrobic tak jak ja to rozpisalem.

P.S ale dzieki za nastepna metode

Napisany przez: bim2 24.10.2009, 13:28:31

Po 5 zleceniach odechciewa się szukania języków po plikach, sprawdzania poprawiania. Po przerzuceniu się na ten sposób odczujesz wielką ulgę smile.gif Naprawdę, przestaw się już teraz będzie mniej problemów później :]

Napisany przez: marcio 24.10.2009, 14:01:15

Kazdy komponent/plugin bedzie mial katalog errors a w nim plik z o nazwie takiej samej jak nazwa komponentu/pluginu dane bede zapisywane tak jak podalem wyzej wiec na to samo wychodzi czy pliki czy baza jeden kit.

Tak samo biblioteka tez bedzie mogla miec wlasne bledy w roznych jezykach jesli zajdzie taka potrzeba np lib do upload'u/download'u


Napisany przez: bim2 24.10.2009, 14:22:18

Pomyśl, że chcesz później dodać kolejny język i dać możliwość grupie tłumaczy tłumaczenia tego. Jak to rozwiążesz?

Napisany przez: marcio 24.10.2009, 15:04:41

Dam im plik z errors i do tego pliki widokow a dane dynamiczne jak news'y etc.... to wiadomo.

Napisany przez: bim2 24.10.2009, 15:20:09

Taaak, rozdziel to dla kilku tłumaczy smile.gif Nie będzie tak łatwo. Zresztą przy n modułach kopiuj sobie wszystkie pliki itd.

Napisany przez: marcio 24.10.2009, 15:30:23

Mysle ze przy latwych stronach metoda moze sie sprawdzic jak nie zawsze bede mogl zmienic implementacje klasy language i tyle smile.gif

Napisany przez: Crozin 24.10.2009, 15:39:52

Trochę zeszliście Panowie z tematu... smile.gif

A co do tematu jak tym zarządzać, to... nie ma tematu - przygotowanie prostej aplikacji, która udostępniłaby jakiś w miarę przyjazny tłumaczowi interface to kwestia powiedzmy godzin, by było to w miarę dopracowane.

Jeżeli natomiast chodzi o format przechowywania danych w plikach tekstowych to wartym rozpatrzenia formatem jest oparty o XML XLIFF. Z własnego doświadczenia niewiele mogę powiedzieć o współpracy z tłumaczami przy wykorzystaniu tego formatu, ale ponoć istnieje trochę gotowych aplikacji do operowania na tym i inne firmy chętnie z tego korzystają.

Napisany przez: nowy_pehapowiec 12.01.2010, 18:15:56

Nie wiem na ile moje pytanie pasuje do reszty postów wątku ale:

Czyli lepiej tworzyć adresy z oznaczeniem języka jako subdomena czy nie?

www.strona.com/en/super/hiper/podstrona
czy
www.en.strona.com/super/hiper/podstrona

questionmark.gif

pozdro

Napisany przez: marcio 12.01.2010, 23:53:28

Co do subdomen czy ogolnie jezyka w url wiem jedno jest to o tyle lepsze ze poprzez url uwzgledniamy odrazu jezyk strony dla user'a bez zadnego wybierania tzn jak wysle link strony php.pl koledze ten nie zna jezyka pl wiec musi wybrac jezyk poprzez podanie mu adresu w stylu www.php.pl/index.php/en/ lub www.en.php.pl user nie musi juz nic zmieniac.

Wedlug mnie zalezy tez ile subdomen masz do dyspozycji i ile jezykow chcesz zaimplementowac.

Jednak sam wyslucham opini innych by wiedziec w czym jeszcze moze sie przydac.


Napisany przez: nowy_pehapowiec 13.01.2010, 06:06:22

Język w ogóle nie musi być widoczny w adresie. Dla użytkownika nie będzie to miało znaczenia, bo przed wyświetleniem czegokolwiek trzeba sprawdzić jakie języki akceptuje przeglądarka usera, w jakiej kolejności itd. A jak był na naszej stronie to odczytujemy jego ciasteczko. Czyli ten sam adres pokaże stronę w różnych językach w zależności od użytkownika. Ale myślę, że dla google lepiej rozróżniać język w adresie. Choć mechanizm pozostaje ten sam: użytkownik trafia na stronę strona.com i tam jest przekierowywany na np strona.com/pl/. Ale właśnie czy lepiej język do adres dodac jako subdomenę czy po nazwie domeny? Co o tym myślicie?

Napisany przez: bim2 25.04.2010, 11:50:43

Ja jestem za subdomenami, ale tylko ze względów estetycznych. Nie widzę różnicy między pl.strona.com en.strona.com a strona.com/pl/ strona.com/en/

Napisany przez: Crozin 25.04.2010, 13:20:35

Cytat
Język w ogóle nie musi być widoczny w adresie.
Dlaczego? Będę chciał koledze przesłać linka do jakiegoś artykułu w wersji angielskiej... No niestety będę musiał napisać: wejdź na URL i zmień sobie język na angielski, zamiast: wejdź na URL.

Napisany przez: melkorm 25.04.2010, 15:48:40

Język powinien być w adresie,a moim zdaniem najlepiej jak jest w subdomenie, szczególnie dla wyszukiwarek : szukamy na angielskim google mamy en.adresstrony.xx a na polskim pl.adresstrony.xx itp więc moim zdaniem jest to największa przewaga tego typu rozwiązania + indeksowanie treści, google będzie miało ten sam adres przy zmianie treści więc zaindeksuje tą treść raz (w przypadku braku języka w adresie).

P.S. Nie jestem w tym specjalistą i to są tylko moje luźne spostrzeżenia smile.gif
P.S. Szczerze chciałbym usłyszeć pogląd specjalisty od pozycjonowania na temat : "Językowość, a wyszukiwarka."

Napisany przez: nowy_pehapowiec 26.04.2010, 09:16:28

A może jednak w ogóle nie uwzględniać języka w adresie strony? Wystarczyłoby sprawdzić jaki jest język przeglądarki i na podstawie tego poprzez sesje albo ciasteczka automatycznie wyświetlać treść w odpowiednim języku. I też user nie musi nigdzie klikać, chyba, że zechce. Wtedy wszystkie linki przychodzące byłyby do jednej strony a nie byłyby rozdzielone na dwie strony o różnych adresach. Ale co z indeksacją strony? Czy google będzie raz indeksować dla en a raz dla pl?

pozdro

Napisany przez: Riklaunim 26.04.2010, 15:20:25

Będzie zmienna treść co jest trochę bez sensu. Można wykorzystać język przeglądarki, ale nie jest do pewne rozwiązanie. Najlepsze to dwie oddzielne pod/strony - łatwe zarządzanie i obie z nich mogą mieć różną zawartość.

Napisany przez: nowy_pehapowiec 26.04.2010, 15:47:53

Riklaunim treści przecież mogą być różne. W bazie mogą być pole z treścią w kilku językach. A i szablony i style mogą być ładowane różne dla różnych języków. I to nawet dobrze działa, ale ma ten minus zmiennej treści, o czym pisałeś. Czy wiesz jak google indeksuje taką stronę?

pozdrawiam

Napisany przez: Riklaunim 27.04.2010, 18:09:36

Cytat(nowy_pehapowiec @ 26.04.2010, 16:47:53 ) *
Riklaunim treści przecież mogą być różne. W bazie mogą być pole z treścią w kilku językach. A i szablony i style mogą być ładowane różne dla różnych języków. I to nawet dobrze działa, ale ma ten minus zmiennej treści, o czym pisałeś. Czy wiesz jak google indeksuje taką stronę?

pozdrawiam


Jeżeli pod jednym linkiem możesz mieć różne treści to poprawnie tego nie zindeksuje. Za dużo kombinujesz z tą wielojęzycznością. Jeżeli w ogóle to jest potrzebne to stawia się najprościej oddzielny serwis/stronę. A specyficzne przypadki jak międzynarodowe sklepy internetowe - stosują różne linki lub subdomeny w zależności od wersji językowej.

Napisany przez: nowy_pehapowiec 27.04.2010, 18:40:58

Tego chciałem się dowiedzieć, czy da się dobrze taką stronę zaindeksować -jeśli nie to sprawa jest oczywista. Ale chyba dla domyślnego języka nie ma potrzeby tworzenia subdomeny?
strona.com - dla poslkiej strony
en.strona.com - dla angielskiej
fr.strona.com - dla francuskiej

pozdro

Napisany przez: jareeny 30.04.2010, 18:38:54

według mnie, sprawdzać język przeglądarki można wtedy, kiedy się chce na wejściu ustawić domyślny język strony czyli:

język przeglądarki: polski, treść domyślna: polska
język przeglądarki: angielski - redirect na en.site.pl
język: chiński - redirect ch.site.pl

no a jeżeli domyślny język nie byłby polski no to

język przeglądarki: polski - redirect pl.site.com

obojętnie

Napisany przez: kuzdo 10.07.2010, 20:46:25

Witam,

Trochę odgrzebię temat, ale mam problem ze zrozumieniem pewnej rzeczy... Były tutaj podawane sposoby zapisywania dynamicznych treści do bazy i jedną z nich była jedna tabela z kolumną lang, w której był określony język wpisu... Co w przypadku, gdy użytkownik wejdzie w taki wpis, zobaczy, że jest też jego polska wersja i będzie chciał się na nią przełączyć, bo np. zna jako tako polski, a może być tam więcej informacji? ID takich wpisów jest inny, a subdomeny nie wchodzą w grę...

Pozdrawiam.

Napisany przez: vokiel 10.07.2010, 21:00:15

@kuzdo
Tu nie ma problemu. Masz np taka strukturę tabeli:

Kod
ID| ID_WPISU | TYTUL | TRESC | JEZYK |
1 | 1 | Tytuł PL | Treść PL | PL |
2 | 1 | Title EN |  Contents EN | EN |
3 | 1 | Название RU | Содержание RU | RU |

W takim wypadku możesz trzymać wpisy w trzech językach i łatwo między nimi przełączać. Ustawiasz taki sam ID_WPISU dla wszystkich trzech. Wyświetlając wpis pobierasz ID innych, dla których ID_WPISU jest taki sam, i generujesz linki do nich w stylu:
  1. <http://december.com/html/4/element/a.html href="wpis.php?id=2">zobacz wpis w en</http://december.com/html/4/element/a.html>
  2. <http://december.com/html/4/element/a.html href="wpis.php?id=3">zobacz wpis w ru</http://december.com/html/4/element/a.html>


Napisany przez: eai 10.07.2010, 21:01:52

Dlaczego? PrimaryKey to może być para kluczy. ID i LANG.

Kod
ID| JEZYK | | TYTUL | TRESC |
1 | PL | Tytuł PL | Treść PL
1 | EN | Title EN |  Contents EN
1 | RU | Название RU | Содержание RU


PrimaryKey: (ID, JEZYK)

Napisany przez: soomal 17.10.2010, 00:46:05

Rozważał ktoś na tych 8 stronach czy w wielu językach lepiej stosować nadmiarowe dane w tabelach czy normalizacje i podział na dwie tabele?
Chodzi mi o sytuację, gdy jakiś zasób ma cechy wspólne dla wielu wersji (np. grafika, przypisanie do kategorii, parametry systemowe) oraz różne (tytuł, opis, itd.).
Normalizacja w tym przypadku wydaje się mieć dużo wad: JOIN przy każdym zapytaniu, ograniczone stosowanie indeksów, jednak w cms firmy, w której pracuje tak właśnie sa zaimplementowane wersje językowe (!?)

Napisany przez: Dyktus 8.08.2011, 16:36:24

Wiem, że ostatnia odpowiedź była w zeszłym roku, lecz nie chcę zaśmiecać forum.

Skorzystałem z opisanych tu sposobów tzn. mam plik załóżmy pl.php

Kod
$lg['mail_tytul']='Tytul maila';
$lg['mail_tresc']='Treść maila Witaj ...';
$lg['web_mail']='kontakt@kontakt.pl';


itd. oczywiście jest też plik en.php w którym są te informacje po angielsku.

Jak można zrobić coś takiego by np. w treści maila było

Cytat
Witaj [IMIE]. Oto dane do zalogowania:
Login: [LOGIN]
Hasło: takie jakie ustawiłeś przy zakładaniu konta


oczywiście korzystam z podstawowej funkcji mail()
Kod
mail($email, $lg['mail_tytul'], $lg['mail_tresc'], 'From: <'.$lg['web_mail'].'>');


W jaki sposób przyłączyć do $lg['mail_tresc'] w odpowiednich miejscach login i ewentualnie imię ?

Nakierujcie chociaż może dojdę do reszty sam. Szukałem oczywiście jednak nie znalazłem nic co by pasowało, lub też po prostu mogłem to przeoczyć.

Napisany przez: nospor 8.08.2011, 16:39:30

str_replace()

Napisany przez: dreaken 14.08.2011, 10:19:53

Do maili najlepiej zrobić sobie specjalny systemik który będzie obsługiwał do nich szablony, a w szablonie maila użyć systemu językowego to nie problem.

Napisany przez: dstp 26.01.2012, 12:23:41

przekopałem cały temat, ale nie znalazłem odpowiedzi na swoje pytanie.. piszę prosty sklep internetowy i stanąłem przy wrzucania produktów z panelu administracyjnego. Mam kilka języków w sklepie i chciałbym, żeby do każdego produktu można było dodać opis i cenę w innym języku. Myślałem, żeby dodać kolumnę do tabeli "LANG", coś takiego:

id | cat | name | desc | price | LANG

i przy dodawaniu produktu wrzucać tyle rekordów ile jest języków, tylko w ostatniej kolumnie zmieniać LANG

chyba, że znacie jakieś lepsze rozwiązanie

Napisany przez: Adi32 15.06.2012, 10:58:36

Witajcie.

Przekopałem się przez temat i kilka razy padła odpowiedź na moje pytanie ale może jednak coś się zmieniło gdyż temat dawno zamarł.

Stworzyłem w miarę uniwersalny sklep w którym admin (owner) ma możliwość dodawania dowolnej ilości języków, treści stałych jak i opisów produktów, newsów itp i jest to rozwiązane wydaje mi się w najlepszy możliwy sposób.

Ogólne teksty na stronie:

Tabela jezyk = id | nazwa | skrot
Tabela fraza = id_jezyk | fraza // id jezyk 0 to opis frazy w języku polskim

Dla produktów, kategorii i newsów jest

Tabela produkt id,nazwa i inne | id_jezyk

Użytkownik ma domyślny język w sesji.
Tabele związane z językiem są cachowane więc baza nie jęczy.

Dzięki temu wszystko dzieje się szybko. Admin ma możliwość zmieniać tłumaczenia przez CMS dla każdego języka i frazy.
Jeżeli chodzi o produkty to rozwiązania są 2:
1 - dla innego języka inny produkt
2 - produkt ten sam ale opis, nazwa, cena (waluta, vat) z tabeli łączonej

ale to już zależy od klienta, mam zrobione 2 opcje łatwo przełączalne.

Co o tym myślicie?

Napisany przez: erix 25.07.2012, 08:46:27

A jak rozwiązujesz tłumaczenie treści z bazy? Tzn. produkty i opisy w innych językach.

Bo cache cachem, ale nieskończonej pojemności też nie ma.

Napisany przez: Regz 22.10.2015, 07:44:08

Ostatnio napisałem na szybkości coś takiego co do samego wyboru języka, może komuś się przyda wink.gif

  1. $langs_array = ['pl', 'en', 'fr'];
  2. $default_lang = 'pl';
  3.  
  4. if(http://www.php.net/isset($_SESSION['SESSION_LANG'])):
  5. if(!http://www.php.net/in_array($_SESSION['SESSION_LANG'], $langs_array)):
  6. $_SESSION['SESSION_LANG'] = $default_lang;
  7. endif;
  8. else:
  9. $input = http://www.php.net/strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']);
  10.  
  11. $pattern = '/;q=([0-1]{0,1}.\d{0,4})/i';
  12.  
  13. $user_languages = [];
  14.  
  15. foreach(http://www.php.net/explode(',', $input) as $lang):
  16. $user_languages[] = http://www.php.net/preg_replace($pattern,'',$lang);
  17. endforeach;
  18.  
  19. http://www.php.net/unset($input, $pattern, $lang);
  20.  
  21. $selected_language = '';
  22.  
  23. foreach($user_languages as $lang):
  24. if(http://www.php.net/in_array($lang, $langs_array)):
  25. $selected_language = $lang;
  26. break;
  27. endif;
  28. endforeach;
  29.  
  30. if(http://www.php.net/empty($selected_language)):
  31. $_SESSION['SESSION_LANG'] = $default_lang;
  32. else:
  33. $_SESSION['SESSION_LANG'] = $selected_language;
  34. endif;
  35.  
  36. http://www.php.net/unset($user_languages, $selected_language);
  37. endif;
  38.  
  39. $lang = filter_input(INPUT_GET, 'lang');
  40.  
  41. if(!http://www.php.net/empty($lang)):
  42. if(http://www.php.net/in_array($lang, $langs_array)):
  43. $_SESSION['SESSION_LANG'] = $lang;
  44. else:
  45. $_SESSION['SESSION_LANG'] = $default_lang;
  46. endif;
  47. endif;
  48.  
  49. include $_SESSION['SESSION_LANG'] . '/index.php';
  50.  
  51. http://www.php.net/unset($lang);
  52.  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)