Zmagam się z tym pytaniem już od kilku miesięcy, ale nie byłem w sytuacji, w której musiałbym wcześniej zbadać wszystkie możliwe opcje. W tej chwili czuję, że nadszedł czas, aby poznać możliwości i stworzyć własne preferencje do wykorzystania w nadchodzących projektach.
Pozwól mi najpierw naszkicować sytuację, której szukam
Mam zamiar zaktualizować / przeprojektować system zarządzania treścią, którego używam od dłuższego czasu. Jednak czuję, że wielojęzyczność to świetne ulepszenie tego systemu. Wcześniej nie korzystałem z żadnych frameworków, ale zamierzam używać Laraval4 w nadchodzącym projekcie. Laravel wydaje się najlepszym wyborem czystszego sposobu kodowania PHP. Sidenote: Laraval4 should be no factor in your answer
. Szukam ogólnych sposobów tłumaczenia, które są niezależne od platformy / frameworka.
Co należy przetłumaczyć
Ponieważ system, którego szukam, musi być jak najbardziej przyjazny dla użytkownika, sposób zarządzania tłumaczeniem powinien znajdować się wewnątrz CMS. Nie powinno być potrzeby nawiązywania połączenia FTP w celu modyfikacji plików tłumaczeń lub jakichkolwiek przeanalizowanych szablonów html / php.
Ponadto szukam najłatwiejszego sposobu przetłumaczenia wielu tabel bazy danych, być może bez konieczności tworzenia dodatkowych tabel.
Co ja sobie wymyśliłem
Ponieważ sam szukałem, czytałem i próbowałem rzeczy. Mam kilka opcji. Ale nadal nie czuję, że znalazłem metodę najlepszej praktyki dla tego, czego naprawdę szukam. Właśnie to wymyśliłem, ale ta metoda ma również skutki uboczne.
- Parsowane szablony PHP : system szablonów powinien być analizowany przez PHP. W ten sposób mogę wstawić przetłumaczone parametry do HTML bez konieczności otwierania szablonów i ich modyfikowania. Poza tym, przeanalizowane szablony PHP dają mi możliwość posiadania 1 szablonu dla całej witryny zamiast posiadania podfolderu dla każdego języka (który miałem wcześniej). Metodą osiągnięcia tego celu może być Smarty, TemplatePower, Laravel's Blade lub dowolny inny parser szablonów. Jak powiedziałem, powinno to być niezależne od pisemnego rozwiązania.
- Oparte na bazie danych : być może nie muszę o tym więcej wspominać. Ale rozwiązanie powinno być oparte na bazie danych. CMS ma być zorientowany obiektowo i MVC, więc musiałbym pomyśleć o logicznej strukturze danych dla łańcuchów. Jak moje szablony byłby skonstruowany: Szablony / Controller / view.php może struktura ta może sprawić, że największy sens:
Controller.View.parameter
. Tabela bazy danych miałaby te pola długie zvalue
polami. Wewnątrz szablonów moglibyśmy użyć metody sortowania, takiej jakecho __('Controller.View.welcome', array('name', 'Joshua'))
i parametr zawieraWelcome, :name
. Zatem wynik jestWelcome, Joshua
. Wydaje się, że jest to dobry sposób na zrobienie tego, ponieważ parametry takie jak: nazwa są łatwe do zrozumienia przez edytor. - Niskie obciążenie bazy danych : Oczywiście powyższy system spowodowałby duże obciążenie bazy danych, jeśli te ciągi są ładowane w ruchu. Dlatego potrzebowałbym systemu buforowania, który ponownie renderuje pliki językowe, gdy tylko zostaną edytowane / zapisane w środowisku administracyjnym. Ponieważ pliki są generowane, potrzebny jest również dobry układ systemu plików. Myślę, że możemy wybrać
languages/en_EN/Controller/View.php
lub .ini, cokolwiek Ci odpowiada. Być może .ini jest nawet analizowane szybciej. Ten plik powinien zawierać dane w formacieformat parameter=value;
. Myślę, że jest to najlepszy sposób na zrobienie tego, ponieważ każdy renderowany widok może zawierać własny plik językowy, jeśli istnieje. Parametry językowe należy następnie załadować do określonego widoku, a nie w zakresie globalnym, aby zapobiec wzajemnemu nadpisywaniu parametrów. - Tłumaczenie tabeli bazy danych : w rzeczywistości jest to rzecz, o którą najbardziej się martwię. Szukam sposobu na tworzenie tłumaczeń wiadomości / stron / itp. jak najszybciej. Posiadanie dwóch tabel dla każdego modułu (na przykład
News
iNews_translations
) jest opcją, ale uzyskanie dobrego systemu wymaga dużo pracy. Jedną z rzeczy wymyśliłem jest oparty nadata versioning
systemie pisałem: jest jedna nazwa tabeli bazy danychTranslations
, tabela ta ma unikalną kombinacjęlanguage
,tablename
aprimarykey
. Na przykład: en_En / News / 1 (odnosi się do angielskiej wersji pozycji wiadomości z ID = 1). Ale ta metoda ma dwie ogromne wady: po pierwsze ta tabela jest dość długa z dużą ilością danych w bazie danych, a po drugie użycie tej konfiguracji do przeszukiwania tabeli byłoby cholernie trudnym zadaniem. Np. Wyszukanie slug SEO elementu byłoby wyszukiwaniem pełnotekstowym, co jest dość głupie. Ale z drugiej strony: to szybki sposób na bardzo szybkie tworzenie treści do tłumaczenia w każdej tabeli, ale nie sądzę, aby ten zawodowiec przeważał nad oszustami. - Praca nad front- endem : również front-end wymagałby trochę przemyślenia. Oczywiście będziemy przechowywać dostępne języki w bazie danych i (dez) aktywować te, których potrzebujemy. W ten sposób skrypt może wygenerować listę rozwijaną umożliwiającą wybór języka, a zaplecze może automatycznie zdecydować, jakie tłumaczenia można wykonać za pomocą CMS. Wybrany język (np. En_EN) będzie następnie używany podczas pobierania pliku językowego do wyświetlenia lub do uzyskania odpowiedniego tłumaczenia elementu treści na stronie internetowej.
Więc oto one. Moje dotychczasowe pomysły. Nie zawierają jeszcze nawet opcji lokalizacji dat itp., Ale ponieważ mój serwer obsługuje PHP5.3.2 +, najlepszą opcją jest użycie rozszerzenia intl, jak wyjaśniono tutaj: http://devzone.zend.com/1500/internationalization-in -php-53 / - ale przydałoby się to na każdym późniejszym etapie rozwoju. Na razie głównym problemem jest jak najlepsze praktyki tłumaczenia treści na stronie internetowej.
Poza wszystkim, co tutaj wyjaśniłem, mam jeszcze jedną rzecz, na którą jeszcze nie zdecydowałem, wygląda na proste pytanie, ale w rzeczywistości przyprawia mnie o ból głowy:
Tłumaczenie adresu URL? Powinniśmy to zrobić czy nie? iw jaki sposób?
Więc… jeśli mam ten adres URL: http://www.domain.com/about-us
a moim domyślnym językiem jest angielski. Czy ten adres URL powinien być przetłumaczony na język http://www.domain.com/over-ons
niderlandzki jako mój język? A może powinniśmy pójść na prostszą drogę i po prostu zmienić zawartość strony widocznej pod adresem /about
. Ostatnia rzecz nie wydaje się poprawną opcją, ponieważ spowodowałoby to wygenerowanie wielu wersji tego samego adresu URL, a indeksowanie treści nie powiedzie się we właściwy sposób.
http://www.domain.com/nl/about-us
Zamiast tego jest używana inna opcja . To generuje co najmniej unikalny adres URL dla każdej treści. Byłoby to również łatwiejsze do przejścia na inny język, na przykład, http://www.domain.com/en/about-us
a podany adres URL jest łatwiejszy do zrozumienia zarówno dla użytkowników Google, jak i użytkowników. Korzystając z tej opcji, co robimy z domyślnymi językami? Czy język domyślny powinien usunąć język wybrany domyślnie? A więc przekierowanie http://www.domain.com/en/about-us
do http://www.domain.com/about-us
... Moim zdaniem jest to najlepsze rozwiązanie, ponieważ gdy CMS jest skonfigurowany tylko dla jednego języka, nie ma potrzeby posiadania tej identyfikacji języka w adresie URL.
Trzecia opcja to połączenie obu opcji: użycie -URL ( http://www.domain.com/about-us
) „bez identyfikacji języka” dla języka głównego. I użyj adresu URL z przetłumaczonym kodem SEO dla języków podrzędnych: http://www.domain.com/nl/over-ons
&http://www.domain.com/de/uber-uns
Mam nadzieję, że moje pytanie sprawi, że twoje głowy pękną, na pewno złamali moje! Pomogło mi to już w rozwiązaniu kwestii jako pytania tutaj. Dał mi możliwość przejrzenia metod, z których korzystałem wcześniej, oraz pomysłu na nadchodzący CMS.
Chciałbym już podziękować za poświęcenie czasu na przeczytanie tego tekstu!
// Edit #1
:
Zapomniałem wspomnieć: funkcja __ () jest aliasem do tłumaczenia podanego ciągu. W ramach tej metody oczywiście powinna istnieć metoda rezerwowa, w której domyślny tekst jest ładowany, gdy nie ma jeszcze dostępnych tłumaczeń. Jeśli brakuje tłumaczenia, należy je wstawić lub ponownie wygenerować plik tłumaczenia.
źródło
Odpowiedzi:
Założenie tematu
Istnieją trzy różne aspekty wielojęzycznej witryny:
Chociaż wszystkie są ze sobą połączone na różne sposoby, z punktu widzenia CMS są zarządzane za pomocą różnych elementów UI i przechowywane w inny sposób. Wydajesz się być pewien swojej implementacji i zrozumienia pierwszych dwóch. Pytanie dotyczyło tego ostatniego aspektu - „Tłumaczenie adresu URL? Powinniśmy to zrobić czy nie? Iw jaki sposób?”
Z czego można zrobić adres URL?
Bardzo ważną rzeczą jest to, aby nie polubić IDN . Zamiast tego preferuj transliterację (także: transkrypcję i latynizację). Chociaż na pierwszy rzut oka IDN wydaje się realną opcją dla międzynarodowych adresów URL, w rzeczywistości nie działa zgodnie z reklamą z dwóch powodów:
'ч'
lub'ž'
na'%D1%87'
i'%C5%BE'
Właściwie to próbowałem podejść do IDN kilka lat temu w projekcie opartym na Yii (okropny framework, IMHO). Napotkałem oba wyżej wymienione problemy przed zeskrobaniem tego rozwiązania. Podejrzewam też, że może to być wektor ataku.
Dostępne opcje ... tak jak ja je widzę.
Zasadniczo masz dwie możliwości, które można ująć w następujący sposób:
http://site.tld/[:query]
: gdzie[:query]
decyduje o wyborze języka i treścihttp://site.tld/[:language]/[:query]
: gdzie[:language]
część adresu URL określa wybór języka i[:query]
służy tylko do identyfikacji treściZapytanie to Α i Ω ..
Powiedzmy, że wybierasz
http://site.tld/[:query]
.W takim przypadku masz jedno główne źródło języka: zawartość
[:query]
segmentu; i dwa dodatkowe źródła:$_COOKIE['lang']
dla tej konkretnej przeglądarkiNajpierw musisz dopasować zapytanie do jednego ze zdefiniowanych wzorców routingu (jeśli wybierzesz Laravel, przeczytaj tutaj ). Po udanym dopasowaniu wzorca musisz znaleźć język.
Musiałbyś przejść przez wszystkie segmenty wzoru. Znajdź potencjalne tłumaczenia dla wszystkich tych segmentów i określ, który język został użyty. Dwa dodatkowe źródła (ciasteczko i nagłówek) byłyby używane do rozwiązywania konfliktów routingu, kiedy (a nie „jeśli”) się pojawią.
Weźmy na przykład:
http://site.tld/blog/novinka
.To jest transliteracja
"блог, новинка"
, która w języku angielskim oznacza w przybliżeniu"blog", "latest"
.Jak już zauważyłeś, w języku rosyjskim „блог” będzie transliterowane jako „blog”. Co oznacza, że pierwsza część
[:query]
Ciebie (w najlepszym przypadku ) zakończy się['en', 'ru']
listą możliwych języków. Następnie bierzesz następny odcinek - „novinka”. To może mieć tylko jeden język na liście możliwości:['ru']
.Jeśli lista zawiera jedną pozycję, język został pomyślnie znaleziony.
Ale jeśli otrzymasz 2 (na przykład: rosyjski i ukraiński) lub więcej możliwości ... lub 0 możliwości, w zależności od przypadku. Będziesz musiał użyć pliku cookie i / lub nagłówka, aby znaleźć właściwą opcję.
A jeśli wszystko inne zawiedzie, wybierasz domyślny język witryny.
Język jako parametr
Alternatywą jest użycie adresu URL, który można zdefiniować jako
http://site.tld/[:language]/[:query]
. W tym przypadku podczas tłumaczenia zapytania nie musisz zgadywać języka, ponieważ w tym momencie już wiesz, którego użyć.Istnieje również dodatkowe źródło języka: wartość pliku cookie. Ale tutaj nie ma sensu majstrować przy nagłówku Accept-Language, ponieważ nie masz do czynienia z nieznaną liczbą możliwych języków w przypadku „zimnego startu” (gdy użytkownik po raz pierwszy otwiera witrynę z niestandardowym zapytaniem).
Zamiast tego masz 3 proste opcje z priorytetami:
[:language]
segment jest ustawiony, użyj go$_COOKIE['lang']
jest ustawione, użyj goMając język, po prostu próbujesz przetłumaczyć zapytanie, a jeśli tłumaczenie się nie powiedzie, użyj „wartości domyślnej” dla tego konkretnego segmentu (na podstawie wyników routingu).
Czy nie ma tu trzeciej opcji?
Tak, technicznie można połączyć oba podejścia, ale to skomplikowałoby proces i byłoby przeznaczone tylko dla osób, które chcą ręcznie zmienić adres URL
http://site.tld/en/news
nahttp://site.tld/de/news
i oczekują, że strona z wiadomościami zmieni się na niemiecki.Ale nawet ten przypadek można prawdopodobnie złagodzić za pomocą wartości cookie (która zawierałaby informacje o wcześniejszym wyborze języka), aby zaimplementować ją z mniejszą magią i nadzieją.
Które podejście zastosować?
Jak można się już domyślić, poleciłbym
http://site.tld/[:language]/[:query]
jako bardziej rozsądną opcję.Również w prawdziwym przypadku miałbyś trzecią główną część w adresie URL: „tytuł”. Jak nazwa produktu w sklepie internetowym lub nagłówek artykułu w serwisie informacyjnym.
Przykład:
http://site.tld/en/news/article/121415/EU-as-global-reserve-currency
W tym przypadku
'/news/article/121415'
byłoby zapytaniem i'EU-as-global-reserve-currency'
tytułem. Wyłącznie do celów SEO.Czy można to zrobić w Laravel?
Niby, ale nie domyślnie.
Nie znam go zbyt dobrze, ale z tego, co widziałem, Laravel używa prostego mechanizmu routingu opartego na wzorcach. Aby zaimplementować wielojęzyczne adresy URL, prawdopodobnie będziesz musiał rozszerzyć podstawowe klasy , ponieważ wielojęzyczny routing wymaga dostępu do różnych form przechowywania (bazy danych, pamięci podręcznej i / lub plików konfiguracyjnych).
Jest rozbity. Co teraz?
W rezultacie otrzymujesz dwie cenne informacje: aktualny język i przetłumaczone segmenty zapytania. Wartości te można następnie wykorzystać do wysłania do klas, które dadzą wynik.
Zasadniczo następujący adres URL:
http://site.tld/ru/blog/novinka
(lub wersja bez'/ru'
) zostaje zamieniony na coś takiego jakKtórego po prostu używasz do wysyłki:
.. lub jego odmiany, w zależności od konkretnej realizacji.
źródło
Implementacja i18n bez wpływu na wydajność przy użyciu preprocesora, zgodnie z sugestią Thomasa Bleya
W pracy niedawno wdrożyliśmy i18n w kilku naszych nieruchomościach, a jedną z rzeczy, z którymi ciągle się borykaliśmy, był hit związany z tłumaczeniem w locie, po czym odkryłem świetny wpis na blogu Thomasa Bleya co zainspirowało sposób, w jaki używamy i18n do obsługi dużego ruchu przy minimalnych problemach z wydajnością.
Zamiast wywoływać funkcje dla każdej operacji tłumaczenia, co jak wiemy w PHP jest drogie, definiujemy nasze pliki podstawowe za pomocą symboli zastępczych, a następnie używamy preprocesora do buforowania tych plików (przechowujemy czas modyfikacji pliku, aby upewnić się, że obsługujemy najnowsze treści przez cały czas).
Tagi tłumaczeń
Thomas używa tagów
{tr}
i{/tr}
, aby określić, gdzie zaczynają się i kończą tłumaczenia. Ponieważ używamy TWIG, nie chcemy używać,{
aby uniknąć nieporozumień, więc używamy[%tr%]
i[%/tr%]
zamiast tego. Zasadniczo wygląda to tak:Zauważ, że Thomas sugeruje użycie w pliku podstawowego angielskiego. Nie robimy tego, ponieważ nie chcemy modyfikować wszystkich plików tłumaczeń, jeśli zmienimy wartość w języku angielskim.
Pliki INI
Następnie tworzymy plik INI dla każdego języka w formacie
placeholder = translated
:Byłoby trywialne, gdyby użytkownik mógł modyfikować je w CMS, po prostu uzyskać pary kluczy za pomocą przycisku
preg_split
on\n
lub=
i umożliwić CMS zapisywanie do plików INI.Składnik preprocesora
Zasadniczo Thomas sugeruje użycie funkcji „kompilatora” just-in-time (chociaż w rzeczywistości jest to preprocesor) w taki sposób, aby pobierać pliki tłumaczeń i tworzyć statyczne pliki PHP na dysku. W ten sposób zasadniczo buforujemy nasze przetłumaczone pliki zamiast wywoływać funkcję tłumaczenia dla każdego ciągu znaków w pliku:
Uwaga: nie sprawdziłem, czy regex działa, nie skopiowałem go z naszego serwera firmowego, ale możesz zobaczyć, jak działa operacja.
Jak to nazwać
Ponownie, ten przykład pochodzi od Thomasa Bleya, a nie ode mnie:
Przechowujemy język w pliku cookie (lub zmiennej sesji, jeśli nie możemy uzyskać pliku cookie), a następnie pobieramy go na każde żądanie. Możesz połączyć to z opcjonalnym
$_GET
parametrem, aby zastąpić język, ale nie sugeruję subdomeny na język ani strony na język, ponieważ utrudni to sprawdzenie, które strony są popularne i zmniejszy wartość przychodzących linki, ponieważ będą mniej rozpowszechnione.Dlaczego warto skorzystać z tej metody?
Podoba nam się ta metoda przetwarzania wstępnego z trzech powodów:
Pobieranie przetłumaczonej zawartości bazy danych
Po prostu dodajemy kolumnę na zawartość w naszej bazie danych o nazwie
language
, a następnie używamy metodyLANG
akcesora dla stałej, którą zdefiniowaliśmy wcześniej, więc nasze wywołania SQL (niestety przy użyciu ZF1) wyglądają następująco:Nasze artykuły mają związek klucz podstawowy nad
id
ilanguage
tak artykuł54
może istnieć we wszystkich językach. NaszeLANG
wartości domyślne to,en_US
jeśli nie określono.Tłumaczenie Slug URL
Połączyłbym tutaj dwie rzeczy, jedna to funkcja w twoim bootstrapie, która akceptuje
$_GET
parametr dla języka i przesłania zmienną cookie, a druga to routing, który akceptuje wiele informacji o błędach. Następnie możesz zrobić coś takiego w swoim routingu:Mogą być przechowywane w płaskim pliku, który można łatwo zapisać z panelu administracyjnego. JSON lub XML mogą zapewnić dobrą strukturę do ich obsługi.
Uwagi dotyczące kilku innych opcji
Tłumaczenie w locie oparte na PHP
Nie widzę żadnej przewagi nad tłumaczeniami wstępnie przetworzonymi.
Tłumaczenia front-endowe
Od dawna uważam, że są one interesujące, ale jest kilka zastrzeżeń. Na przykład, musisz udostępnić użytkownikowi całą listę fraz w swojej witrynie, które planujesz przetłumaczyć, może to być problematyczne, jeśli są obszary witryny, które ukrywasz lub do których nie masz dostępu.
Musiałbyś również założyć, że wszyscy twoi użytkownicy chcą i mogą używać Javascript w Twojej witrynie, ale z moich statystyk wynika, że około 2,5% naszych użytkowników działa bez niego (lub używa Noscript do blokowania korzystania z niego przez nasze witryny) .
Tłumaczenia oparte na bazie danych
Szybkość połączeń z bazą danych PHP nie ma o czym pisać, a to zwiększa i tak już wysoki narzut związany z wywoływaniem funkcji do przetłumaczenia na każdej frazie. W przypadku tego podejścia problemy z wydajnością i skalowalnością wydają się przytłaczające.
źródło
Why?
: proste ... Nie chcę, żeby przeszkadzały mi drobne zmiany w tekście, użytkownicy powinni móc to zrobić sami bez użycia edytora kodu i / lub programu ftp :).INI
pliki z tabeli bazy danych z 3-kolumnowąplaceholder
,replacement
,language
. Klawisz złożony naplaceholder
ilanguage
. Następnie dodaj kolejne 2 kolumny ztempfile
(ścieżka do szablonu) imodified
(DATETIME).Proponuję nie wymyślać koła i używać listy skrótów języków gettext i ISO. Czy widziałeś, jak i18n / l10n zaimplementowano w popularnych systemach CMS lub frameworkach?
Korzystając z gettext, uzyskasz potężne narzędzie, w którym wiele przypadków jest już zaimplementowanych, takich jak mnogie formy liczb. W języku angielskim masz tylko 2 opcje: liczbę pojedynczą i mnogą. Ale na przykład w języku rosyjskim są 3 formularze i nie jest to tak proste, jak w języku angielskim.
Wielu tłumaczy ma już doświadczenie w pracy z gettext.
Spójrz na CakePHP lub Drupal . Oba dostępne w wielu językach. CakePHP jako przykład lokalizacji interfejsu i Drupal jako przykład tłumaczenia treści.
Dla l10n użycie bazy danych w ogóle nie ma miejsca. Będzie mnóstwo zapytań. Standardowym podejściem jest pobranie wszystkich danych l10n do pamięci na wczesnym etapie (lub podczas pierwszego wywołania funkcji i10n, jeśli wolisz ładowanie z opóźnieniem). Może odczytywać z pliku .po lub z bazy danych wszystkie dane naraz. I niż tylko odczytać żądane ciągi z tablicy.
Jeśli potrzebujesz zaimplementować narzędzie online do tłumaczenia interfejsu, możesz mieć wszystkie te dane w DB, ale nadal zapisywać wszystkie dane do pliku, aby z nim pracować. Aby zmniejszyć ilość danych w pamięci, możesz podzielić wszystkie przetłumaczone wiadomości / ciągi na grupy, a następnie załadować tylko te grupy, których potrzebujesz, jeśli będzie to możliwe.
Więc masz rację w swoim # 3. Z jednym wyjątkiem: zwykle jest to jeden duży plik, a nie plik dla każdego kontrolera. Ponieważ dla wydajności najlepiej jest otworzyć jeden plik. Prawdopodobnie wiesz, że niektóre aplikacje internetowe o dużym obciążeniu kompilują cały kod PHP w jednym pliku, aby uniknąć operacji na plikach, gdy wywoływana jest funkcja include / require.
O adresach URL. Google pośrednio sugeruje użycie tłumaczenia:
Myślę też, że musisz przekierować użytkownika do domyślnego prefiksu języka, np. Http://examlpe.com/about-us przekieruje do http://examlpe.com/en/about-us. Ale jeśli Twoja witryna używa tylko jednego języka, w ogóle nie potrzebują przedrostków.
Sprawdź: http://www.audiomicro.com/trailer-hit-impact-psychodrama-sound-effects-836925 http://nl.audiomicro.com/aanhangwagen-hit-effect-psychodrama-geluidseffecten-836925 http: / /de.audiomicro.com/anhanger-hit-auswirkungen-psychodrama-sound-effekte-836925
Tłumaczenie treści jest trudniejszym zadaniem. Myślę, że będą to pewne różnice w przypadku różnych typów treści, np. Artykułów, pozycji menu itp. Ale w punkcie 4 jesteś we właściwej drodze. Zajrzyj do Drupala, aby mieć więcej pomysłów. Ma wystarczająco przejrzysty schemat bazy danych i wystarczająco dobry interfejs do tłumaczenia. Tak jak ty tworzysz artykuł i wybierasz dla niego język. A potem możesz przetłumaczyć go na inne języki.
Myślę, że to nie jest problem z błędami URL. Możesz po prostu stworzyć osobną tabelę dla ślimaków i będzie to słuszna decyzja. Również użycie odpowiednich indeksów nie stanowi problemu z zapytaniem do tabeli nawet przy dużej ilości danych. I nie było to wyszukiwanie pełnotekstowe, ale dopasowanie stringów, jeśli użyje typu danych varchar dla slug i możesz mieć indeks również w tym polu.
PS Przepraszam, ale mój angielski jest daleki od doskonałości.
źródło
To zależy od tego, ile treści ma Twoja witryna. Na początku korzystałem z bazy danych, tak jak wszyscy inni ludzie tutaj, ale skryptowanie wszystkich działań bazy danych może być czasochłonne. Nie mówię, że jest to metoda idealna, a zwłaszcza jeśli masz dużo tekstu, ale jeśli chcesz to zrobić szybko bez korzystania z bazy danych, ta metoda może działać, chociaż nie możesz pozwolić użytkownikom na wprowadzanie danych które będą używane jako pliki do tłumaczenia. Ale jeśli sam dodasz tłumaczenia, zadziała:
Powiedzmy, że masz ten tekst:
Możesz wprowadzić to do bazy danych z tłumaczeniami, ale możesz też zrobić to:
Teraz, jeśli Twoja witryna korzysta z plików cookie, masz na przykład:
Aby to ułatwić, przekształćmy go w kod, który można łatwo wykorzystać:
Jeśli Twoim językiem plików cookie jest walijski i masz ten fragment kodu:
Wynikiem tego będzie:
Jeśli musisz dodać wiele tłumaczeń do swojej witryny, a baza danych jest zbyt obciążająca, użycie tablicy może być idealnym rozwiązaniem.
źródło
lang.en.php
które zostaną uwzględnione i użyj,$lang['welcome']
które jest zadeklarowane w każdym pliku.Zasugeruję, abyś naprawdę nie polegał na bazie danych przy tłumaczeniu, może to być naprawdę kłopotliwe zadanie i może stanowić ekstremalny problem w przypadku kodowania danych.
Miałem podobny problem jakiś czas temu i napisałem kolejne zajęcia, aby rozwiązać mój problem
Obiekt: Locale \ Locale
Stosowanie
Jak to działa
{a:1}
jest zastępowany pierwszym argumentem przekazanym do metodyLocale::translate('key_name','arg1')
{a:2}
jest zastępowany drugim argumentem przekazanym do metodyLocale::translate('key_name','arg1','arg2')
Jak działa wykrywanie
geoip
jest zainstalowany, zwróci kod kraju do,geoip_country_code_by_name
a jeśli geoip nie jest zainstalowany, powrót doHTTP_ACCEPT_LANGUAGE
nagłówkaźródło
utf8_general_ci
sortowanie jest odpowiednim sposobem na zrobienie tego.Tylko odpowiedź podrzędna: absolutnie używaj przetłumaczonych adresów URL z identyfikatorem języka przed nimi: http://www.domain.com/nl/over-ons
Rozwiązania hybrydowe są zwykle skomplikowane, więc po prostu się go trzymam. Czemu? Ponieważ adres URL jest niezbędny dla SEO.
O tłumaczeniu db: Czy liczba języków jest mniej więcej ustalona? Czy raczej nieprzewidywalny i dynamiczny? Jeśli zostanie naprawiony, po prostu dodam nowe kolumny, w przeciwnym razie użyję wielu tabel.
Ale ogólnie, dlaczego nie skorzystać z Drupala? Wiem, że każdy chce zbudować swój własny CMS, bo jest szybszy, mniejszy itp. Itd. Ale to naprawdę zły pomysł!
źródło
Nie będę próbował zawężać odpowiedzi już udzielonych. Zamiast tego opowiem o tym, w jaki sposób mój własny framework OOP PHP obsługuje tłumaczenia.
Wewnętrznie mój framework używa kodów, takich jak en, fr, es, cn i tak dalej. Tablica zawiera języki obsługiwane przez witrynę: tablica ('en', 'fr', 'es', 'cn') Kod języka jest przekazywany za pośrednictwem $ _GET (lang = fr) i jeśli nie jest przekazywany lub nie jest ważny, to jest ustawiony na pierwszy język w tablicy. Dlatego w każdym momencie wykonywania programu i od samego początku znany jest aktualny język.
Warto zrozumieć, jakie treści należy przetłumaczyć w typowej aplikacji:
1) komunikaty o błędach z klas (lub kod proceduralny) 2) komunikaty o błędach z klas (lub kod proceduralny) 3) zawartość strony (zwykle przechowywana w bazie danych) 4) ciągi znaków dla całej witryny (takie jak nazwa witryny) 5) skrypt- określone ciągi
Pierwszy typ jest łatwy do zrozumienia. Zasadniczo mówimy o komunikatach typu „nie można połączyć się z bazą danych…”. Te komunikaty muszą zostać załadowane tylko wtedy, gdy wystąpi błąd. Moja klasa menedżera otrzymuje wywołanie od innych klas i używając informacji przekazanych jako parametry, po prostu przechodzi do odpowiedniego folderu klasy i pobiera plik błędu.
Drugi typ komunikatów o błędach jest bardziej podobny do komunikatów otrzymywanych, gdy weryfikacja formularza się nie powiodła. („Nie możesz zostawić ... pustego” lub „wybierz hasło składające się z więcej niż 5 znaków”). Ciągi muszą zostać załadowane przed uruchomieniem klasy, wiem co to jest
W przypadku rzeczywistej zawartości strony używam jednej tabeli na język, z każdą tabelą poprzedzoną kodem języka. Więc en_content to tabela z zawartością w języku angielskim, es_content to hiszpania, cn_content dla Chin, a fr_content to francuski.
Czwarty rodzaj ciągów ma znaczenie w całej witrynie. Jest to ładowane za pośrednictwem pliku konfiguracyjnego nazwanego przy użyciu kodu języka, czyli en_lang.php, es_lang.php i tak dalej. W globalnym pliku językowym będziesz musiał załadować przetłumaczone języki, takie jak tablica („angielski”, „chiński”, „hiszpański”, „francuski”) w globalnym pliku i tablicy w języku angielskim („angielski”, „chiński”, „ Espagnol ”,„ Francais ”) w pliku francuskim. Więc kiedy wypełnisz listę rozwijaną do wyboru języka, jest on we właściwym języku;)
Wreszcie masz ciągi znaków specyficzne dla skryptu. Jeśli więc napiszesz aplikację do gotowania, może to brzmieć: „Twój piekarnik nie był wystarczająco gorący”.
W moim cyklu aplikacji globalny plik językowy jest ładowany jako pierwszy. Znajdziesz tam nie tylko łańcuchy globalne (takie jak „Witryna Jacka”), ale także ustawienia niektórych klas. Zasadniczo wszystko, co jest zależne od języka lub kultury. Niektóre z łańcuchów zawierają maski dat (MMDDRRRR lub DDMMRRRR) lub kody języków ISO. W głównym pliku językowym umieszczam ciągi znaków dla poszczególnych klas, ponieważ jest ich tak mało.
Drugim i ostatnim plikiem językowym odczytywanym z dysku jest plik języka skryptowego. lang_en_home_welcome.php to plik językowy dla skryptu home / welcome. Skrypt jest definiowany przez tryb (dom) i akcję (powitanie). Każdy skrypt ma swój własny folder z plikami config i lang.
Skrypt pobiera zawartość z bazy danych, nazywając tabelę zawartości, jak wyjaśniono powyżej.
Jeśli coś pójdzie nie tak, menedżer wie, skąd wziąć zależny od języka plik błędów. Ten plik jest ładowany tylko w przypadku błędu.
Wniosek jest więc oczywisty. Pomyśl o problemach z tłumaczeniem, zanim zaczniesz tworzyć aplikację lub framework. Potrzebny jest również przepływ pracy programistycznej obejmujący tłumaczenia. W moim frameworku tworzę całą witrynę w języku angielskim, a następnie tłumaczę wszystkie odpowiednie pliki.
Tylko krótkie ostatnie słowo na temat sposobu implementacji ciągów tłumaczeniowych. Mój framework ma jeden globalny menedżer $, który uruchamia usługi dostępne dla każdej innej usługi. Na przykład usługa formularza przechwytuje usługę html i używa jej do napisania kodu HTML. Jedną z usług w moim systemie jest usługa tłumacza. $ translator-> set ($ service, $ code, $ string) ustawia ciąg dla bieżącego języka. Plik językowy jest listą takich oświadczeń. $ translator-> get ($ service, $ code) pobiera ciąg tłumaczenia. Kod $ może mieć postać numeryczną, np. 1, lub ciąg znaków, np. „No_connection”. Nie może być kolizji między usługami, ponieważ każda z nich ma własną przestrzeń nazw w obszarze danych tłumacza.
Publikuję to tutaj w nadziei, że pozwoli to komuś na ponowne wynalezienie koła, tak jak musiałem to zrobić kilka lat temu.
źródło
Miałem ten sam problem jakiś czas temu, zanim zacząłem używać frameworka Symfony .
Wystarczy użyć funkcji __ (), która ma parametry pageId (lub objectId, objectTable opisane w # 2), język docelowy i opcjonalny parametr języka rezerwowego (domyślnego). Domyślny język można ustawić w jakiejś globalnej konfiguracji, aby mieć łatwiejszy sposób na późniejszą zmianę.
Do przechowywania treści w bazie danych wykorzystałem następującą strukturę: (pageId, język, treść, zmienne).
pageId byłby FK do strony, którą chcesz przetłumaczyć. jeśli masz inne obiekty, takie jak wiadomości, galerie lub cokolwiek innego, po prostu podziel je na 2 pola objectId, objectTable.
język - oczywiście przechowuje ciąg języka ISO EN_en, LT_lt, EN_us itp.
content - tekst, który chcesz przetłumaczyć wraz z symbolami zastępującymi zmienne. Przykład „Witaj panie %% imię %%. Saldo Twojego konta to %% balance %%.”
zmienne - zmienne zakodowane w formacie JSON. PHP zapewnia funkcje do szybkiego ich analizowania. Przykład „imię i nazwisko: Laurynas, saldo: 15,23”.
wspomniałeś również o polu ślimaka. możesz dowolnie dodać go do tej tabeli, aby szybko go wyszukać.
Twoje wywołania bazy danych muszą być ograniczone do minimum dzięki buforowaniu tłumaczeń. Musi być przechowywany w tablicy PHP, ponieważ jest to najszybsza struktura w języku PHP. To, jak zrobisz to buforowanie, zależy od Ciebie. Z mojego doświadczenia wynika, że powinieneś mieć folder dla każdego obsługiwanego języka i tablicę dla każdego pageId. Po zaktualizowaniu tłumaczenia pamięć podręczna powinna zostać odbudowana. TYLKO zmieniona tablica powinna zostać ponownie wygenerowana.
myślę, że odpowiedziałem na to w # 2
Twój pomysł jest całkowicie logiczny. ten jest dość prosty i myślę, że nie sprawi żadnych problemów.
Adresy URL powinny być tłumaczone przy użyciu zapisanych informacji o błędach w tabeli tłumaczeń.
Ostatnie słowa
zawsze dobrze jest zbadać najlepsze praktyki, ale nie wynajdować koła na nowo. po prostu weź i użyj komponentów z dobrze znanych frameworków i używaj ich.
spójrz na komponent translacyjny Symfony . Może to być dla Ciebie dobra baza kodu.
źródło
W kółko zadawałem sobie podobne pytania, a potem zagubiłem się w formalnych językach ... ale żeby ci trochę pomóc, chciałbym podzielić się kilkoma spostrzeżeniami:
Polecam rzucić okiem na zaawansowany CMS
Typo3
boPHP
(wiem, że jest dużo rzeczy, ale myślę, że to jest najbardziej dojrzała)Plone
wPython
Jeśli stwierdzisz, że internet w 2013 roku powinien działać inaczej, zacznij od zera. Oznaczałoby to zebranie zespołu wysoko wykwalifikowanych / doświadczonych ludzi w celu zbudowania nowego CMS. Może zechcesz przyjrzeć się polimerowi w tym celu.
Jeśli chodzi o kodowanie i wielojęzyczne strony internetowe / obsługę języków ojczystych, myślę, że każdy programista powinien mieć wskazówkę dotyczącą Unicode. Jeśli nie znasz Unicode, z pewnością zepsujesz swoje dane. Nie idź z tysiącami kodów ISO. Oszczędzą ci tylko trochę pamięci. Ale możesz zrobić dosłownie wszystko z UTF-8, nawet przechowywać chińskie znaki. Ale w tym celu musiałbyś przechowywać 2 lub 4 bajtowe znaki, co sprawia, że jest to w zasadzie utf-16 lub utf-32.
Jeśli chodzi o kodowanie adresów URL, ponownie nie powinieneś mieszać kodowań i pamiętaj, że przynajmniej dla nazwy domeny istnieją reguły zdefiniowane przez różne lobby, które zapewniają aplikacje takie jak przeglądarka. np. domena może być bardzo podobna, na przykład:
ьankofamerica.com lub bankofamerica.com są takie same, ale różne;)
Oczywiście potrzebujesz systemu plików do pracy ze wszystkimi kodowaniami. Kolejny plus dla Unicode używającego systemu plików utf-8.
Jeśli chodzi o tłumaczenia, pomyśl o strukturze dokumentów. np. książka lub artykuł. Masz
docbook
specyfikacje do zrozumienia tych struktur. Ale w HTML chodzi tylko o bloki treści. Więc chciałbyś mieć tłumaczenie na tym poziomie, również na poziomie strony internetowej lub domeny. Więc jeśli blok nie istnieje, po prostu go tam nie ma, jeśli strona nie istnieje, zostaniesz przekierowany na wyższy poziom nawigacji. Jeśli domena ma mieć zupełnie inną strukturę nawigacji, to ... jest to zupełnie inna struktura do zarządzania. Można to już zrobić za pomocą Typo3.Jeśli chodzi o frameworki, najbardziej dojrzałe, jakie znam, do robienia ogólnych rzeczy, takich jak MVC (modne hasło, naprawdę go nienawidzę! Na przykład „wydajność”. Jeśli chcesz coś sprzedać, użyj słowa wydajność i bogactwo funkcji, a sprzedajesz ... co? do diabła) jest
Zend
. Okazało się, że dobrze jest wprowadzić standardy do koderów chaosu PHP. Ale typo3 ma również Framework oprócz CMS. Niedawno został przebudowany i teraz nazywa się flow3. Ramy obejmują oczywiście abstrakcję bazy danych, tworzenie szablonów i koncepcje buforowania, ale mają indywidualne mocne strony.Jeśli chodzi o buforowanie ... to może być strasznie skomplikowane / wielowarstwowe. W PHP pomyślisz o accelleratorze, opkodzie, ale także html, httpd, mysql, xml, css, js ... wszelkiego rodzaju pamięciach podręcznych. Oczywiście niektóre części powinny być przechowywane w pamięci podręcznej, a części dynamiczne, takie jak odpowiedzi na blogach, nie powinny. Niektóre powinny być wysyłane przez AJAX z wygenerowanymi adresami URL. JSON, hashbang itp.
Następnie chciałbyś, aby każdy mały komponent w Twojej witrynie był dostępny lub zarządzany tylko przez niektórych użytkowników , więc koncepcyjnie odgrywa dużą rolę.
Chciałbyś również sporządzić statystyki , być może masz system rozproszony / facebook lub facebooki itp. Jakiekolwiek oprogramowanie do zbudowania na twoich over-top cms ... więc potrzebujesz różnych typów baz danych w pamięci, bigdata, xml, cokolwiek .
Cóż, myślę, że na razie wystarczy. Jeśli nie słyszałeś o typo3 / plone lub wspomnianych frameworkach, masz wystarczająco dużo, aby się uczyć. Na tej ścieżce znajdziesz wiele rozwiązań na pytania, których jeszcze nie zadałeś.
Jeśli więc myślisz, stwórzmy nowy CMS, ponieważ jego 2013 i php i tak wkrótce umrą, to możesz dołączyć do innej grupy programistów, miejmy nadzieję, że się nie zgubisz.
Powodzenia!
A tak przy okazji. co powiesz na to, że ludzie nie będą już mieć żadnych witryn internetowych w przyszłości? i wszyscy będziemy w Google +? Mam nadzieję, że programiści staną się trochę bardziej kreatywni i zrobią coś pożytecznego (aby nie zostać przyswojonym przez mieszkańców)
//// Edytuj /// Pomyśl tylko o istniejącej aplikacji:
Jeśli masz php mysql CMS i chcesz osadzić obsługę wielu języków. możesz albo użyć swojej tabeli z dodatkową kolumną dla dowolnego języka, albo wstawić tłumaczenie z identyfikatorem obiektu i identyfikatorem języka w tej samej tabeli lub utworzyć identyczną tabelę dla dowolnego języka i wstawić tam obiekty, a następnie utworzyć sumę wyboru, jeśli chcesz wyświetlić je wszystkie. Do bazy danych użyj ogólnego utf8 ci i oczywiście we front / backend użyj utf8 text / encoding. Użyłem segmentów ścieżki URL dla adresów URL w sposób, który już wyjaśniłeś
domain.org/en/about możesz zmapować identyfikator języka do swojej tabeli treści. w każdym razie musisz mieć mapę parametrów dla swoich adresów URL, więc chciałbyś zdefiniować parametr, który ma być zmapowany z segmentu ścieżek w Twoim adresie URL, np.
domain.org/en/about/employees/IT/administrators/
konfiguracja wyszukiwania
pageid | url
1 | /about/employees/../ ..
1 | /../about/employees../../
odwzoruj parametry na segment ścieżek adresów URL „”
na przykład, to zostało już omówione w górnym poście.
I żeby nie zapominać, musiałbyś "przepisać" adres URL do generowanego pliku php, którym w większości przypadków byłby index.php
źródło
Praca w bazie danych:
Utwórz tabelę języków „języki”:
Pola:
Utwórz tabelę w bazie danych „zawartość”:
Pola:
Praca front-end:
Gdy użytkownik wybierze dowolny język z listy rozwijanej lub dowolnego obszaru, zapisz wybrany identyfikator języka w sesji, np.
$_SESSION['language']=1;
Teraz pobierz dane z tabeli bazy danych „zawartość” na podstawie identyfikatora języka przechowywanego w sesji.
Szczegóły można znaleźć tutaj http://skillrow.com/multilingual-website-in-php-2/
źródło
Jako osoba mieszkająca w Quebecu, gdzie prawie cała witryna jest francuska i angielska ... wypróbowałem wiele, jeśli nie większość, wielojęzycznych wtyczek do WP ... jedynym użytecznym rozwiązaniem, które działa nive z całą moją witryną, jest mQtranslate ... żyję i umieram z tym!
https://wordpress.org/plugins/mqtranslate/
źródło
A co z WORDPRESS +
MULTI-LANGUAGE SITE BASIS
(wtyczką)? strona będzie miała strukturę:Wtyczka zapewnia interfejs do tłumaczenia wszystkich fraz z prostą logiką:
wtedy można wyprowadzić:
echo translate('my_title', LNG); // LNG is auto-detected
ps jednak sprawdź, czy wtyczka jest nadal aktywna.
źródło
Naprawdę prostą opcją, która działa z każdą witryną, na której można przesłać JavaScript, jest www.multilingualizer.com
Pozwala umieścić cały tekst we wszystkich językach na jednej stronie, a następnie ukrywa języki, których użytkownik nie musi widzieć. Działa dobrze.
źródło