Best Practice mehrsprachige Website


176

Ich habe seit einigen Monaten mit dieser Frage zu kämpfen, aber ich war noch nicht in einer Situation, in der ich vorher alle möglichen Optionen ausloten musste. Im Moment ist es an der Zeit, die Möglichkeiten kennenzulernen und meine persönliche Präferenz für meine bevorstehenden Projekte zu entwickeln.

Lassen Sie mich zunächst die Situation skizzieren, nach der ich suche

Ich bin dabei, ein Content-Management-System zu aktualisieren / neu zu entwickeln, das ich seit einiger Zeit verwende. Ich bin jedoch der Meinung, dass die Mehrsprachigkeit eine große Verbesserung dieses Systems darstellt. Vorher habe ich keine Frameworks verwendet, aber ich werde Laraval4 für das kommende Projekt verwenden. Laravel scheint die beste Wahl für eine sauberere Art zu sein, PHP zu codieren. Sidenote: Laraval4 should be no factor in your answer. Ich suche nach allgemeinen Übersetzungsmethoden, die plattform- / rahmenunabhängig sind.

Was soll übersetzt werden?

Da das von mir gesuchte System so benutzerfreundlich wie möglich sein muss, sollte sich die Methode zur Verwaltung der Übersetzung im CMS befinden. Es sollte nicht erforderlich sein, eine FTP-Verbindung zu starten, um Übersetzungsdateien oder analysierte HTML- / PHP-Vorlagen zu ändern.

Darüber hinaus suche ich nach dem einfachsten Weg, mehrere Datenbanktabellen zu übersetzen, ohne dass zusätzliche Tabellen erstellt werden müssen.

Was habe ich mir ausgedacht?

Da ich schon selbst gesucht, gelesen und versucht habe. Ich habe einige Möglichkeiten. Aber ich habe immer noch nicht das Gefühl, eine Best-Practice-Methode für das erreicht zu haben, was ich wirklich suche. Im Moment habe ich mir das ausgedacht, aber diese Methode hat auch Nebenwirkungen.

  1. PHP-analysierte Vorlagen : Das Vorlagensystem sollte von PHP analysiert werden. Auf diese Weise kann ich die übersetzten Parameter in den HTML-Code einfügen, ohne die Vorlagen öffnen und ändern zu müssen. Außerdem gibt mir PHP-analysierte Vorlagen die Möglichkeit, 1 Vorlage für die gesamte Website zu haben, anstatt für jede Sprache (die ich zuvor hatte) einen Unterordner zu haben. Die Methode, um dieses Ziel zu erreichen, kann entweder Smarty, TemplatePower, Laravel's Blade oder ein anderer Vorlagenparser sein. Wie gesagt, dies sollte unabhängig von der schriftlichen Lösung sein.
  2. Datenbankgesteuert : Vielleicht muss ich das nicht noch einmal erwähnen. Die Lösung sollte jedoch datenbankgesteuert sein. Das CMS soll objektorientiert und MVC sein, daher müsste ich mir eine logische Datenstruktur für die Zeichenfolgen überlegen. Da meine Vorlagen strukturiert wären: templates / Controller / View.php wäre diese Struktur vielleicht am sinnvollsten : Controller.View.parameter. Die Datenbanktabelle hätte diese Felder lange mit einem valueFeld. Innerhalb der Vorlagen könnten wir eine Sortiermethode wie verwenden echo __('Controller.View.welcome', array('name', 'Joshua'))und der Parameter enthält Welcome, :name. So ist das Ergebnis Welcome, Joshua. Dies scheint ein guter Weg zu sein, da die Parameter wie: name für den Editor leicht zu verstehen sind.
  3. Geringe Datenbanklast : Natürlich würde das obige System eine Last der Datenbanklast verursachen, wenn diese Zeichenfolgen unterwegs geladen werden. Daher würde ich ein Caching-System benötigen, das die Sprachdateien neu rendert, sobald sie in der Verwaltungsumgebung bearbeitet / gespeichert werden. Da Dateien generiert werden, ist auch ein gutes Dateisystemlayout erforderlich. Ich denke, wir können mit languages/en_EN/Controller/View.phpoder .ini gehen, was auch immer am besten zu Ihnen passt. Vielleicht wird eine .ini am Ende sogar schneller analysiert. Diese Form sollte die Daten in der enthalten format parameter=value; . Ich denke, dies ist der beste Weg, dies zu tun, da jede gerenderte Ansicht eine eigene Sprachdatei enthalten kann, falls vorhanden. Sprachparameter sollten dann in eine bestimmte Ansicht und nicht in einem globalen Bereich geladen werden, um zu verhindern, dass sich Parameter gegenseitig überschreiben.
  4. Übersetzung der Datenbanktabelle : Dies ist in der Tat das, worüber ich mir am meisten Sorgen mache. Ich suche nach einer Möglichkeit, Übersetzungen von Nachrichten / Seiten / etc. Zu erstellen. schnellstens. Es ist eine Option, zwei Tabellen für jedes Modul zu haben (zum Beispiel Newsund News_translations), aber es scheint zu viel Arbeit zu sein, um ein gutes System zu erhalten. Eines der Dinge , die ich mit aufkam basiert auf einem data versioningSystem , das ich schrieb: Es gibt eine Datenbank Tabellenname ist Translations, hat diese Tabelle eine einzigartige Kombination aus language, tablenameundprimarykey. Zum Beispiel: en_En / News / 1 (Bezieht sich auf die englische Version der Nachricht mit ID = 1). Diese Methode hat jedoch zwei große Nachteile: Erstens wird diese Tabelle mit vielen Daten in der Datenbank ziemlich lang, und zweitens wäre es eine verdammt große Aufgabe, dieses Setup zum Durchsuchen der Tabelle zu verwenden. Zum Beispiel wäre die Suche nach dem SEO-Slug des Artikels eine Volltextsuche, die ziemlich dumm ist. Aber auf der anderen Seite: Es ist eine schnelle Möglichkeit, sehr schnell übersetzbare Inhalte in jeder Tabelle zu erstellen, aber ich glaube nicht, dass dieser Profi die Nachteile überwiegt.
  5. Front-End-Arbeit : Auch das Front-End würde einige Überlegungen erfordern. Natürlich würden wir die verfügbaren Sprachen in einer Datenbank speichern und die benötigten Sprachen (de) aktivieren. Auf diese Weise kann das Skript ein Dropdown-Menü zur Auswahl einer Sprache erstellen und das Back-End kann automatisch entscheiden, welche Übersetzungen mit dem CMS vorgenommen werden können. Die ausgewählte Sprache (z. B. en_EN) wird dann verwendet, wenn die Sprachdatei für eine Ansicht abgerufen oder die richtige Übersetzung für ein Inhaltselement auf der Website abgerufen wird.

Da sind sie also. Meine bisherigen Ideen. Sie enthalten noch nicht einmal Lokalisierungsoptionen für Daten usw., aber da mein Server PHP5.3.2 + unterstützt, ist es am besten, die intl-Erweiterung zu verwenden, wie hier erläutert: http://devzone.zend.com/1500/internationalization-in -php-53 / - aber dies wäre in jedem späteren Entwicklungsstadion von Nutzen. Im Moment geht es hauptsächlich darum, wie Sie die besten Methoden für die Übersetzung von Inhalten auf einer Website anwenden können.

Abgesehen von allem, was ich hier erklärt habe, habe ich noch eine andere Sache, die ich noch nicht entschieden habe. Es sieht nach einer einfachen Frage aus, aber tatsächlich hat es mir Kopfschmerzen bereitet:

URL-Übersetzung? Sollen wir das tun oder nicht? und auf welche Weise?

Also .. wenn ich diese URL habe: http://www.domain.com/about-usund Englisch ist meine Standardsprache. Sollte diese URL übersetzt werden, http://www.domain.com/over-onswenn ich Niederländisch als meine Sprache wähle? Oder sollten wir den einfachen Weg gehen und einfach den Inhalt der Seite ändern, die unter sichtbar ist /about. Das Letzte scheint keine gültige Option zu sein, da dadurch mehrere Versionen derselben URL generiert werden. Diese Indizierung des Inhalts schlägt fehl.

Eine andere Option ist http://www.domain.com/nl/about-usstattdessen. Dadurch wird für jeden Inhalt mindestens eine eindeutige URL generiert. Außerdem wäre es beispielsweise einfacher, in eine andere Sprache zu wechseln, http://www.domain.com/en/about-usund die angegebene URL ist sowohl für Google- als auch für Human-Besucher leichter zu verstehen. Was machen wir mit dieser Option mit den Standardsprachen? Sollte die Standardsprache die standardmäßig ausgewählte Sprache entfernen? Weiterleiten http://www.domain.com/en/about-usan http://www.domain.com/about-us... In meinen Augen ist dies die beste Lösung, denn wenn das CMS nur für eine Sprache eingerichtet ist, muss diese Sprachidentifikation nicht in der URL enthalten sein.

Eine dritte Option ist eine Kombination aus beiden Optionen: Verwenden der "sprachidentifikationslosen" -URL ( http://www.domain.com/about-us) für die Hauptsprache. Und verwenden Sie eine URL mit einem übersetzten SEO-Slug für Subsprachen: http://www.domain.com/nl/over-ons&http://www.domain.com/de/uber-uns

Ich hoffe, meine Frage bringt deine Köpfe zum Knacken, sie haben meine auf jeden Fall geknackt! Es hat mir schon geholfen, die Dinge hier als Frage zu klären. Hat mir die Möglichkeit gegeben, die Methoden zu überprüfen, die ich zuvor verwendet habe, und die Idee, die ich für mein bevorstehendes CMS habe.

Ich möchte mich bereits bei Ihnen dafür bedanken, dass Sie sich die Zeit genommen haben, diesen Text zu lesen!

// Edit #1::

Ich habe vergessen zu erwähnen: Die Funktion __ () ist ein Alias ​​zum Übersetzen einer bestimmten Zeichenfolge. Innerhalb dieser Methode sollte es offensichtlich eine Art Fallback-Methode geben, bei der der Standardtext geladen wird, wenn noch keine Übersetzungen verfügbar sind. Wenn die Übersetzung fehlt, sollte sie entweder eingefügt oder die Übersetzungsdatei neu generiert werden.


Antworten:


112

Prämisse des Themas

Eine mehrsprachige Site hat drei verschiedene Aspekte:

  • Schnittstellenübersetzung
  • Inhalt
  • URL-Routing

Während sie alle auf unterschiedliche Weise miteinander verbunden sind, werden sie aus CMS-Sicht mithilfe verschiedener UI-Elemente verwaltet und unterschiedlich gespeichert. Sie scheinen zuversichtlich zu sein, die ersten beiden umzusetzen und zu verstehen. Die Frage betraf den letzteren Aspekt: "URL-Übersetzung? Sollten wir das tun oder nicht? Und auf welche Weise?"

Woraus kann die URL bestehen?

Eine sehr wichtige Sache ist, keine Lust auf IDN zu bekommen . Bevorzugen Sie stattdessen die Transliteration (auch: Transkription und Romanisierung). Auf den ersten Blick scheint IDN eine praktikable Option für internationale URLs zu sein, funktioniert jedoch aus zwei Gründen nicht wie angekündigt:

  • Einige Browser wandeln die Nicht-ASCII-Zeichen wie 'ч'oder 'ž'in '%D1%87'und um'%C5%BE'
  • Wenn der Benutzer benutzerdefinierte Themen hat, enthält die Schriftart des Themas höchstwahrscheinlich keine Symbole für diese Buchstaben

Ich habe tatsächlich vor einigen Jahren in einem Yii-basierten Projekt (schreckliches Framework, IMHO) versucht, einen IDN-Ansatz zu finden. Ich bin auf beide oben genannten Probleme gestoßen, bevor ich diese Lösung gefunden habe. Ich vermute auch, dass es sich um einen Angriffsvektor handelt.

Verfügbare Optionen ... wie ich sie sehe.

Grundsätzlich haben Sie zwei Möglichkeiten, die wie folgt abstrahiert werden können:

  • http://site.tld/[:query]: wo [:query]bestimmt sowohl die Sprache als auch den Inhalt

  • http://site.tld/[:language]/[:query]: wobei ein [:language]Teil der URL die Wahl der Sprache definiert und [:query]nur zur Identifizierung des Inhalts verwendet wird

Abfrage ist Α und Ω ..

Nehmen wir an, Sie wählen http://site.tld/[:query].

In diesem Fall haben Sie eine primäre Sprachquelle: den Inhalt des [:query]Segments; und zwei zusätzliche Quellen:

  • Wert $_COOKIE['lang']für diesen bestimmten Browser
  • Liste der Sprachen im HTTP Accept-Language (1) , (2) Header

Zuerst müssen Sie die Abfrage einem der definierten Routing-Muster zuordnen (wenn Sie Laravel auswählen, lesen Sie hier ). Bei erfolgreicher Musterübereinstimmung müssen Sie dann die Sprache finden.

Sie müssten alle Segmente des Musters durchgehen. Finden Sie die möglichen Übersetzungen für alle diese Segmente und bestimmen Sie, welche Sprache verwendet wurde. Die zwei zusätzlichen Quellen (Cookie und Header) werden verwendet, um Routing-Konflikte zu lösen, wenn (nicht "wenn") sie auftreten.

Nehmen Sie zum Beispiel : http://site.tld/blog/novinka.

Das ist Transliteration von "блог, новинка", was auf Englisch ungefähr bedeutet "blog", "latest".

Wie Sie bereits feststellen können, wird "блог" auf Russisch als "Blog" transkribiert. Dies bedeutet, dass für den ersten Teil von [:query]Ihnen (im besten Fall ) eine ['en', 'ru']Liste möglicher Sprachen angezeigt wird. Dann nehmen Sie das nächste Segment - "novinka". Das könnte nur eine Sprache auf der Liste der Möglichkeiten haben : ['ru'].

Wenn die Liste ein Element enthält, haben Sie die Sprache erfolgreich gefunden.

Aber wenn Sie am Ende 2 (Beispiel: Russisch und Ukrainisch) oder mehr Möglichkeiten haben .. oder 0 Möglichkeiten, je nach Fall. Sie müssen Cookie und / oder Header verwenden, um die richtige Option zu finden.

Wenn alles andere fehlschlägt, wählen Sie die Standardsprache der Site.

Sprache als Parameter

Die Alternative ist die Verwendung einer URL, die definiert werden kann als http://site.tld/[:language]/[:query]. In diesem Fall müssen Sie beim Übersetzen von Abfragen die Sprache nicht erraten, da Sie zu diesem Zeitpunkt bereits wissen, welche Sprache Sie verwenden sollen.

Es gibt auch eine sekundäre Sprachquelle: den Cookie-Wert. Aber hier macht es keinen Sinn, mit dem Accept-Language-Header herumzuspielen, da Sie im Falle eines "Kaltstarts" (wenn der Benutzer die Site zum ersten Mal mit einer benutzerdefinierten Abfrage öffnet) nicht mit einer unbekannten Anzahl möglicher Sprachen zu tun haben.

Stattdessen haben Sie 3 einfache, priorisierte Optionen:

  1. Wenn das [:language]Segment festgelegt ist, verwenden Sie es
  2. Wenn $_COOKIE['lang']festgelegt, verwenden Sie es
  3. Verwenden Sie die Standardsprache

Wenn Sie über die Sprache verfügen, versuchen Sie einfach, die Abfrage zu übersetzen. Wenn die Übersetzung fehlschlägt, verwenden Sie den "Standardwert" für dieses bestimmte Segment (basierend auf den Routing-Ergebnissen).

Ist hier nicht eine dritte Option?

Ja, technisch kann man beiden Ansätze kombinieren, aber das würde den Prozess erschweren und nur Personen , die von manuell ändern URL wollen http://site.tld/en/newszu http://site.tld/de/newsund die News - Seite zu ändern , um Deutsch zu erwarten.

Aber selbst dieser Fall könnte wahrscheinlich mithilfe des Cookie-Werts (der Informationen über die vorherige Wahl der Sprache enthält) gemildert werden, um ihn mit weniger Magie und Hoffnung umzusetzen.

Welcher Ansatz ist zu verwenden?

Wie Sie vielleicht schon erraten haben, würde ich http://site.tld/[:language]/[:query]als sinnvollere Option empfehlen .

Auch in einer realen Wortsituation hätten Sie den 3. Hauptteil in der URL: "Titel". Wie im Namen des Produkts im Online-Shop oder als Überschrift des Artikels auf der Nachrichtenseite.

Beispiel: http://site.tld/en/news/article/121415/EU-as-global-reserve-currency

In diesem Fall '/news/article/121415'wäre die Abfrage und der 'EU-as-global-reserve-currency'Titel. Rein für SEO-Zwecke.

Kann es in Laravel gemacht werden?

Ein bisschen, aber nicht standardmäßig.

Ich bin nicht allzu vertraut damit, aber nach dem, was ich gesehen habe, verwendet Laravel einen einfachen musterbasierten Routing-Mechanismus. Um mehrsprachige URLs zu implementieren, müssen Sie wahrscheinlich die Kernklasse (n) erweitern , da mehrsprachiges Routing Zugriff auf verschiedene Speicherformen (Datenbank-, Cache- und / oder Konfigurationsdateien) benötigt.

Es ist geroutet. Was jetzt?

Als Ergebnis von allem würden Sie zwei wertvolle Informationen erhalten: aktuelle Sprache und übersetzte Abfragesegmente. Diese Werte können dann verwendet werden, um an die Klasse (n) zu senden, die das Ergebnis erzeugen.

Grundsätzlich wird die folgende URL: http://site.tld/ru/blog/novinka(oder die Version ohne '/ru') in so etwas wie verwandelt

$parameters = [
   'language' => 'ru',
   'classname' => 'blog',
   'method' => 'latest',
];

Was Sie nur für den Versand verwenden:

$instance = new {$parameter['classname']};
$instance->{'get'.$parameters['method']}( $parameters );

.. oder eine Variation davon, abhängig von der jeweiligen Implementierung.


1
Vielen Dank für einen weiteren Einblick! Sehr nachdenklich! Ich dachte daran, den Sprachparameter auch in der URL zu haben. Dies scheint einfach der beste Weg zu sein, um eine bestimmte Sprache zu identifizieren, nicht nur für den Benutzer, sondern auch für SEO-Zwecke. Für den Fall, dass ein Benutzer / en / news in / de / news ändert, war meine Idee, beispielsweise eine 301 (permanente) Weiterleitung nach / de / nachrichten durchzuführen. Nur um sicherzustellen, dass jede Sprache nur eine eindeutige URL pro Seite hat (wieder für SEO-Zwecke)
Joshua - Pendo

Es wird immer schwieriger, die beste Antwort auszuwählen. Derzeit gibt es ungefähr 3/4 Antworten, die jeweils mindestens einen Teil des Kopfgeldes verdienen. Zusammen ergeben sie eine solide Antwort auf alles, was ich gemeinsam klären wollte :)
Joshua - Pendo

Ich habe Ihre Antwort akzeptiert, um Ihnen mindestens einen zusätzlichen Vertreter für die detaillierte Antwort zu geben, die Sie bei der URL-Übersetzung gegeben haben. Hoch geschätzt! Das Kopfgeld ist jedoch für die Person unter Ihnen besser, da sie jeden Aspekt meiner Frage plattformunabhängig beantwortet hat.
Joshua - Pendo

51

Implementierung von i18n ohne Leistungseinbußen mit einem Vorprozessor, wie von Thomas Bley vorgeschlagen

Bei der Arbeit haben wir kürzlich die Implementierung von i18n für einige unserer Objekte durchlaufen, und eines der Dinge, mit denen wir immer wieder zu kämpfen hatten, war der Leistungseinbruch beim Umgang mit On-the-Fly-Übersetzungen. Dann entdeckte ich diesen großartigen Blog-Beitrag von Thomas Bley Dies hat die Art und Weise inspiriert, wie wir i18n verwenden, um große Verkehrslasten mit minimalen Leistungsproblemen zu bewältigen.

Anstatt Funktionen für jede Übersetzungsoperation aufzurufen, die, wie wir in PHP wissen, teuer ist, definieren wir unsere Basisdateien mit Platzhaltern und verwenden dann einen Vorprozessor, um diese Dateien zwischenzuspeichern (wir speichern die Zeit für die Dateiänderung, um sicherzustellen, dass wir sie bereitstellen jederzeit die neuesten Inhalte).

Die Übersetzungs-Tags

Thomas verwendet {tr}und {/tr}Tags, um zu definieren, wo Übersetzungen beginnen und enden. Aufgrund der Tatsache, dass wir TWIG verwenden, möchten wir nicht verwenden {, um Verwirrung zu vermeiden, also verwenden wir [%tr%]und [%/tr%]stattdessen. Im Grunde sieht das so aus:

`return [%tr%]formatted_value[%/tr%];`

Beachten Sie, dass Thomas vorschlägt, das Basis-Englisch in der Datei zu verwenden. Wir tun dies nicht, weil wir nicht alle Übersetzungsdateien ändern müssen, wenn wir den Wert in Englisch ändern.

Die INI-Dateien

Anschließend erstellen wir für jede Sprache eine INI-Datei im folgenden Format placeholder = translated:

// lang/fr.ini
formatted_value = number_format($value * Model_Exchange::getEurRate(), 2, ',', ' ') . '€'

// lang/en_gb.ini
formatted_value = '£' . number_format($value * Model_Exchange::getStgRate())

// lang/en_us.ini
formatted_value = '$' . number_format($value)

Es wäre trivial , damit ein Benutzer dieses innerhalb des CMS zu ändern, nur um die Keypairs durch einen preg_splitauf \noder =und macht das CMS in der Lage auf die INI - Dateien zu schreiben.

Die Vorprozessorkomponente

Im Wesentlichen schlägt Thomas vor, eine Just-in-Time-Funktion wie diese zu verwenden (obwohl es sich in Wahrheit um einen Präprozessor handelt), um Ihre Übersetzungsdateien zu übernehmen und statische PHP-Dateien auf der Festplatte zu erstellen. Auf diese Weise werden unsere übersetzten Dateien im Wesentlichen zwischengespeichert, anstatt für jede Zeichenfolge in der Datei eine Übersetzungsfunktion aufzurufen:

// This function was written by Thomas Bley, not by me
function translate($file) {
  $cache_file = 'cache/'.LANG.'_'.basename($file).'_'.filemtime($file).'.php';
  // (re)build translation?
  if (!file_exists($cache_file)) {
    $lang_file = 'lang/'.LANG.'.ini';
    $lang_file_php = 'cache/'.LANG.'_'.filemtime($lang_file).'.php';

    // convert .ini file into .php file
    if (!file_exists($lang_file_php)) {
      file_put_contents($lang_file_php, '<?php $strings='.
        var_export(parse_ini_file($lang_file), true).';', LOCK_EX);
    }
    // translate .php into localized .php file
    $tr = function($match) use (&$lang_file_php) {
      static $strings = null;
      if ($strings===null) require($lang_file_php);
      return isset($strings[ $match[1] ]) ? $strings[ $match[1] ] : $match[1];
    };
    // replace all {t}abc{/t} by tr()
    file_put_contents($cache_file, preg_replace_callback(
      '/\[%tr%\](.*?)\[%\/tr%\]/', $tr, file_get_contents($file)), LOCK_EX);
  }
  return $cache_file;
}

Hinweis: Ich habe nicht überprüft, ob der reguläre Ausdruck funktioniert. Ich habe ihn nicht von unserem Unternehmensserver kopiert, aber Sie können sehen, wie der Vorgang funktioniert.

Wie man es nennt

Auch dieses Beispiel stammt von Thomas Bley, nicht von mir:

// instead of
require("core/example.php");
echo (new example())->now();

// we write
define('LANG', 'en_us');
require(translate('core/example.php'));
echo (new example())->now();

Wir speichern die Sprache in einem Cookie (oder einer Sitzungsvariablen, wenn wir kein Cookie erhalten können) und rufen sie dann bei jeder Anfrage ab. Sie können dies mit einem optionalen $_GETParameter kombinieren , um die Sprache zu überschreiben. Ich empfehle jedoch keine Subdomain pro Sprache oder Seite pro Sprache, da dies die Erkennung der beliebtesten Seiten erschwert und den Wert eingehender Nachrichten verringert Links, da Sie sie kaum verbreitet haben.

Warum diese Methode verwenden?

Wir mögen diese Methode der Vorverarbeitung aus drei Gründen:

  1. Der enorme Leistungsgewinn besteht darin, dass nicht eine ganze Reihe von Funktionen für Inhalte aufgerufen werden, die sich selten ändern (mit diesem System werden 100.000 Besucher auf Französisch immer noch nur einmal einen Übersetzungsersatz ausführen).
  2. Es fügt unserer Datenbank keine Last hinzu, da es einfache Flatfiles verwendet und eine reine PHP-Lösung ist.
  3. Die Fähigkeit, PHP-Ausdrücke in unseren Übersetzungen zu verwenden.

Übersetzten Datenbankinhalt abrufen

Wir fügen einfach eine Spalte für den Inhalt unserer Datenbank hinzu, die aufgerufen wird language, und verwenden dann eine LANGZugriffsmethode für die Konstante, die wir zuvor definiert haben. Unsere SQL-Aufrufe (leider mit ZF1) sehen also folgendermaßen aus:

$query = select()->from($this->_name)
                 ->where('language = ?', User::getLang())
                 ->where('id       = ?', $articleId)
                 ->limit(1);

Unsere Artikel haben einen zusammengesetzten Primärschlüssel idund languagedaher 54kann der Artikel in allen Sprachen existieren. Unsere LANGStandardeinstellungen sind, en_USfalls nicht angegeben.

URL Slug Translation

Ich würde hier zwei Dinge kombinieren: Eine ist eine Funktion in Ihrem Bootstrap, die einen $_GETParameter für die Sprache akzeptiert und die Cookie-Variable überschreibt, und eine andere ist das Routing, das mehrere Slugs akzeptiert. Dann können Sie so etwas in Ihrem Routing tun:

"/wilkommen" => "/welcome/lang/de"
... etc ...

Diese können in einer flachen Datei gespeichert werden, in die Sie problemlos von Ihrem Admin-Panel aus schreiben können. JSON oder XML bieten möglicherweise eine gute Struktur für deren Unterstützung.

Hinweise zu einigen anderen Optionen

PHP-basierte On-The-Fly-Übersetzung

Ich kann nicht sehen, dass diese einen Vorteil gegenüber vorverarbeiteten Übersetzungen bieten.

Front-End-basierte Übersetzungen

Ich fand diese lange interessant, aber es gibt ein paar Einschränkungen. Sie müssen dem Benutzer beispielsweise die gesamte Liste der Phrasen auf Ihrer Website zur Verfügung stellen, die Sie übersetzen möchten. Dies kann problematisch sein, wenn Bereiche der Website verborgen bleiben oder ihnen kein Zugriff gewährt wird.

Sie müssten auch davon ausgehen, dass alle Ihre Benutzer bereit und in der Lage sind, Javascript auf Ihrer Website zu verwenden. Laut meinen Statistiken werden jedoch etwa 2,5% unserer Benutzer ohne Javascript ausgeführt (oder verwenden Noscript, um die Verwendung unserer Websites durch Noscript zu blockieren). .

Datenbankgesteuerte Übersetzungen

Die Datenbankkonnektivitätsgeschwindigkeiten von PHP sind nichts, worüber man nach Hause schreiben muss, und dies erhöht den ohnehin schon hohen Aufwand, eine Funktion für jede zu übersetzende Phrase aufzurufen. Die Leistungs- und Skalierbarkeitsprobleme scheinen bei diesem Ansatz überwältigend zu sein.


Ich sehe, dass ich Sie mit "Front-End-Übersetzungen" verwechselt habe. Ich meinte damit, die übersetzten Zeichenfolgen auf dem Bildschirm zu analysieren. Ich bin definitiv nicht auf der Suche nach einer Möglichkeit, es auf der Client-Seite zu übersetzen! Was ich meinte, war der einfachste Weg, die Sprachen im Front-End zu wechseln, aber das ist offensichtlich mit einem Cookie oder einer Benutzereinstellung :)
Joshua - Pendo

Oh, und von Database-Driven habe ich mich mehr auf die Methode zum Verwalten aller Übersetzungen konzentriert. Meine ideale Lösung wäre also ein Back-End, das Übersetzungen in eine Datenbank schreibt, gefolgt von einer Funktion, die die Vorverarbeitungskomponente generiert, die das PHP generiert Datei. Why?: simple .. Ich möchte mich nicht durch kleine Textänderungen stören lassen, die Benutzer sollten dies selbst tun können, ohne einen Code-Editor und / oder ein FTP-Programm zu verwenden :)
Joshua - Pendo

@PENDO Ich weiß, dass Sie nicht Front-End-Übersetzungen gemeint haben, das war ein kaum verhüllter Kommentar gegenüber dem Benutzer, der Front-End-Übersetzungs-Frameworks mit JS vorgeschlagen hat. ;)
Glitch Desire

@PENDO Ich stimme zu, ich würde das Backend wie von Ihnen vorgeschlagen verwenden, aber anstelle einer Datenbank würde ich aus Leistungsgründen eine flache Datei verwenden. Natürlich, hier der Kern Vorschlag ist Vorrendern die Vorlagen bei einer Änderung , damit Sie die ersetzen könnten .INIDateien mit einer 3-Spalten - Datenbanktabelle mit placeholder, replacement, language. Zusammengesetzter Schlüssel an placeholderund language. Dann haben Sie eine weitere 2-Spalte mit tempfile(Pfad zur Vorlage) undmodified (DATETIME).
Glitch Desire

1
@ PENDO Danke. Ich habe 250 zurückgesetzt und plane, es innerhalb von 24 Stunden an teresko zu vergeben, wenn die Website es mir erlaubt, da Sie beide Antworten als richtig ausgewählt haben und ich denke, eine Aufteilung würde Ihre Absichten am besten widerspiegeln.
Glitch Desire

14

Ich empfehle Ihnen, kein Rad zu erfinden und die Abkürzungsliste gettext und ISO-Sprachen zu verwenden. Haben Sie gesehen, wie i18n / l10n in gängigen CMS oder Frameworks implementiert wird?

Mit gettext verfügen Sie über ein leistungsstarkes Tool, bei dem viele Fälle bereits wie mehrere Zahlenformen implementiert sind. In Englisch haben Sie nur 2 Möglichkeiten: Singular und Plural. Aber auf Russisch gibt es zum Beispiel 3 Formen und es ist nicht so einfach wie auf Englisch.

Auch viele Übersetzer haben bereits Erfahrung mit gettext.

Schauen Sie sich CakePHP oder Drupal an . Beide mehrsprachig aktiviert. CakePHP als Beispiel für die Schnittstellenlokalisierung und Drupal als Beispiel für die Übersetzung von Inhalten.

Für l10n ist die Verwendung einer Datenbank überhaupt nicht der Fall. Es wird Tonnen auf Fragen sein. Der Standardansatz besteht darin, alle l10n-Daten frühzeitig in den Speicher zu bringen (oder beim ersten Aufruf der i10n-Funktion, wenn Sie ein verzögertes Laden bevorzugen). Es kann alle Daten gleichzeitig aus der .po-Datei oder aus der DB lesen. Und dann lesen Sie einfach die angeforderten Zeichenfolgen aus dem Array.

Wenn Sie ein Online-Tool zum Übersetzen der Benutzeroberfläche implementieren müssen, können Sie alle diese Daten in der Datenbank haben, aber trotzdem alle Daten in einer Datei speichern, um damit zu arbeiten. Um die Datenmenge im Speicher zu verringern, können Sie alle übersetzten Nachrichten / Zeichenfolgen in Gruppen aufteilen und dann nur die Gruppen laden, die Sie benötigen, wenn dies möglich ist.

Sie haben also vollkommen Recht mit Ihrer Nummer 3. Mit einer Ausnahme: Normalerweise handelt es sich um eine große Datei, nicht um eine Datei pro Controller oder so. Weil es für die Leistung am besten ist, eine Datei zu öffnen. Sie wissen wahrscheinlich, dass einige hochgeladene Webanwendungen den gesamten PHP-Code in einer Datei kompilieren, um Dateivorgänge zu vermeiden, wenn include / require aufgerufen wird.

Über URLs. Google schlägt indirekt vor , die Übersetzung zu verwenden:

um den französischen Inhalt klar anzugeben: http://example.ca/fr/vélo-de-montagne.html

Ich denke auch, dass Sie den Benutzer zum Standard-Sprachpräfix umleiten müssen, z http://examlpe.com/about-us leitet zu http://examlpe.com/de/about-us weiter. Wenn Ihre Website jedoch nur eine Sprache verwendet, verwenden Sie dies brauche überhaupt keine Präfixe.

Überprüfen Sie heraus: 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

Das Übersetzen von Inhalten ist eine schwierigere Aufgabe. Ich denke, es wird einige Unterschiede bei verschiedenen Arten von Inhalten geben, z. B. Artikel, Menüpunkte usw. Aber in # 4 sind Sie auf dem richtigen Weg. Werfen Sie einen Blick in Drupal, um weitere Ideen zu erhalten. Es hat ein klar genug DB-Schema und eine ausreichend gute Schnittstelle für die Übersetzung. Wie Sie Artikel erstellen und Sprache dafür auswählen. Und dann können Sie es später in andere Sprachen übersetzen.

Drupal-Übersetzungsschnittstelle

Ich denke, es ist kein Problem mit URL-Slugs. Sie können einfach eine separate Tabelle für Schnecken erstellen, und es ist die richtige Entscheidung. Auch bei Verwendung der richtigen Indizes ist es kein Problem, Tabellen auch bei großen Datenmengen abzufragen. Und es war keine Volltextsuche, sondern eine Zeichenfolgenübereinstimmung, wenn der Datentyp varchar für slug verwendet wird und Sie auch einen Index für dieses Feld haben können.

PS Entschuldigung, mein Englisch ist alles andere als perfekt.


Vielen Dank für die Zeit, die Sie für die Beantwortung meiner Frage benötigt haben. Ihr Englisch ist gut genug für mich zu verstehen! Ich werde dich schon für deine Bemühungen +1!
Joshua - Pendo

Jaroslaw nochmals vielen Dank für Ihre Antwort. Ich ging jedoch mit 2 anderen Antworten, die etwas vollständiger waren, und erläuterte die hinter dem Code verwendeten Methoden, anstatt darauf hinzuweisen, dass er bereits vorhanden ist.
Joshua - Pendo

2
Kein Problem. In der Tat sind die Antworten vollständiger und interessanter, auch für mich zu lesen. Aber ich hoffe, meine Antwort hat Ihnen auch etwas Nützliches gebracht.
Jaroslaw

12

Dies hängt davon ab, wie viel Inhalt Ihre Website enthält. Zuerst habe ich eine Datenbank wie alle anderen Leute hier verwendet, aber es kann zeitaufwändig sein, alle Funktionen einer Datenbank zu skripten. Ich sage nicht, dass dies eine ideale Methode ist, insbesondere wenn Sie viel Text haben. Wenn Sie dies jedoch schnell tun möchten, ohne eine Datenbank zu verwenden, kann diese Methode funktionieren. Sie können jedoch nicht zulassen, dass Benutzer Daten eingeben die als Übersetzungsdateien verwendet werden. Wenn Sie die Übersetzungen jedoch selbst hinzufügen, funktioniert dies:

Angenommen, Sie haben diesen Text:

Welcome!

Sie können dies in eine Datenbank mit Übersetzungen eingeben, aber Sie können auch Folgendes tun:

$welcome = array(
"English"=>"Welcome!",
"German"=>"Willkommen!",
"French"=>"Bienvenue!",
"Turkish"=>"Hoşgeldiniz!",
"Russian"=>"Добро пожаловать!",
"Dutch"=>"Welkom!",
"Swedish"=>"Välkommen!",
"Basque"=>"Ongietorri!",
"Spanish"=>"Bienvenito!"
"Welsh"=>"Croeso!");

Wenn Ihre Website ein Cookie verwendet, haben Sie beispielsweise Folgendes:

$_COOKIE['language'];

Um es einfach zu machen, transformieren wir es in einen Code, der einfach verwendet werden kann:

$language=$_COOKIE['language'];

Wenn Ihre Cookie-Sprache Walisisch ist und Sie diesen Code haben:

echo $welcome[$language];

Das Ergebnis davon wird sein:

Croeso!

Wenn Sie viele Übersetzungen für Ihre Website hinzufügen müssen und eine Datenbank zu aufwendig ist, kann die Verwendung eines Arrays eine ideale Lösung sein.


1
Dies ist nicht annähernd die Antwort, nach der ich gefragt habe. Anstatt alle Sprachen auf jeder Seite verfügbar zu haben, sollten Sie außerdem Dateien erstellen, wie lang.en.phpsie enthalten sind, und $lang['welcome']die in jeder Datei deklarierten verwenden.
Joshua - Pendo

7

Ich werde Ihnen vorschlagen, sich bei der Übersetzung nicht wirklich auf die Datenbank zu verlassen. Dies könnte eine sehr unübersichtliche Aufgabe sein und bei der Datencodierung ein extremes Problem darstellen.

Ich hatte vor einiger Zeit ein ähnliches Problem und schrieb folgenden Kurs, um mein Problem zu lösen

Objekt: Gebietsschema \ Gebietsschema

<?php

  namespace Locale;

  class Locale{

// Following array stolen from Zend Framework
public $country_to_locale = array(
    'AD' => 'ca_AD',
    'AE' => 'ar_AE',
    'AF' => 'fa_AF',
    'AG' => 'en_AG',
    'AI' => 'en_AI',
    'AL' => 'sq_AL',
    'AM' => 'hy_AM',
    'AN' => 'pap_AN',
    'AO' => 'pt_AO',
    'AQ' => 'und_AQ',
    'AR' => 'es_AR',
    'AS' => 'sm_AS',
    'AT' => 'de_AT',
    'AU' => 'en_AU',
    'AW' => 'nl_AW',
    'AX' => 'sv_AX',
    'AZ' => 'az_Latn_AZ',
    'BA' => 'bs_BA',
    'BB' => 'en_BB',
    'BD' => 'bn_BD',
    'BE' => 'nl_BE',
    'BF' => 'mos_BF',
    'BG' => 'bg_BG',
    'BH' => 'ar_BH',
    'BI' => 'rn_BI',
    'BJ' => 'fr_BJ',
    'BL' => 'fr_BL',
    'BM' => 'en_BM',
    'BN' => 'ms_BN',
    'BO' => 'es_BO',
    'BR' => 'pt_BR',
    'BS' => 'en_BS',
    'BT' => 'dz_BT',
    'BV' => 'und_BV',
    'BW' => 'en_BW',
    'BY' => 'be_BY',
    'BZ' => 'en_BZ',
    'CA' => 'en_CA',
    'CC' => 'ms_CC',
    'CD' => 'sw_CD',
    'CF' => 'fr_CF',
    'CG' => 'fr_CG',
    'CH' => 'de_CH',
    'CI' => 'fr_CI',
    'CK' => 'en_CK',
    'CL' => 'es_CL',
    'CM' => 'fr_CM',
    'CN' => 'zh_Hans_CN',
    'CO' => 'es_CO',
    'CR' => 'es_CR',
    'CU' => 'es_CU',
    'CV' => 'kea_CV',
    'CX' => 'en_CX',
    'CY' => 'el_CY',
    'CZ' => 'cs_CZ',
    'DE' => 'de_DE',
    'DJ' => 'aa_DJ',
    'DK' => 'da_DK',
    'DM' => 'en_DM',
    'DO' => 'es_DO',
    'DZ' => 'ar_DZ',
    'EC' => 'es_EC',
    'EE' => 'et_EE',
    'EG' => 'ar_EG',
    'EH' => 'ar_EH',
    'ER' => 'ti_ER',
    'ES' => 'es_ES',
    'ET' => 'en_ET',
    'FI' => 'fi_FI',
    'FJ' => 'hi_FJ',
    'FK' => 'en_FK',
    'FM' => 'chk_FM',
    'FO' => 'fo_FO',
    'FR' => 'fr_FR',
    'GA' => 'fr_GA',
    'GB' => 'en_GB',
    'GD' => 'en_GD',
    'GE' => 'ka_GE',
    'GF' => 'fr_GF',
    'GG' => 'en_GG',
    'GH' => 'ak_GH',
    'GI' => 'en_GI',
    'GL' => 'iu_GL',
    'GM' => 'en_GM',
    'GN' => 'fr_GN',
    'GP' => 'fr_GP',
    'GQ' => 'fan_GQ',
    'GR' => 'el_GR',
    'GS' => 'und_GS',
    'GT' => 'es_GT',
    'GU' => 'en_GU',
    'GW' => 'pt_GW',
    'GY' => 'en_GY',
    'HK' => 'zh_Hant_HK',
    'HM' => 'und_HM',
    'HN' => 'es_HN',
    'HR' => 'hr_HR',
    'HT' => 'ht_HT',
    'HU' => 'hu_HU',
    'ID' => 'id_ID',
    'IE' => 'en_IE',
    'IL' => 'he_IL',
    'IM' => 'en_IM',
    'IN' => 'hi_IN',
    'IO' => 'und_IO',
    'IQ' => 'ar_IQ',
    'IR' => 'fa_IR',
    'IS' => 'is_IS',
    'IT' => 'it_IT',
    'JE' => 'en_JE',
    'JM' => 'en_JM',
    'JO' => 'ar_JO',
    'JP' => 'ja_JP',
    'KE' => 'en_KE',
    'KG' => 'ky_Cyrl_KG',
    'KH' => 'km_KH',
    'KI' => 'en_KI',
    'KM' => 'ar_KM',
    'KN' => 'en_KN',
    'KP' => 'ko_KP',
    'KR' => 'ko_KR',
    'KW' => 'ar_KW',
    'KY' => 'en_KY',
    'KZ' => 'ru_KZ',
    'LA' => 'lo_LA',
    'LB' => 'ar_LB',
    'LC' => 'en_LC',
    'LI' => 'de_LI',
    'LK' => 'si_LK',
    'LR' => 'en_LR',
    'LS' => 'st_LS',
    'LT' => 'lt_LT',
    'LU' => 'fr_LU',
    'LV' => 'lv_LV',
    'LY' => 'ar_LY',
    'MA' => 'ar_MA',
    'MC' => 'fr_MC',
    'MD' => 'ro_MD',
    'ME' => 'sr_Latn_ME',
    'MF' => 'fr_MF',
    'MG' => 'mg_MG',
    'MH' => 'mh_MH',
    'MK' => 'mk_MK',
    'ML' => 'bm_ML',
    'MM' => 'my_MM',
    'MN' => 'mn_Cyrl_MN',
    'MO' => 'zh_Hant_MO',
    'MP' => 'en_MP',
    'MQ' => 'fr_MQ',
    'MR' => 'ar_MR',
    'MS' => 'en_MS',
    'MT' => 'mt_MT',
    'MU' => 'mfe_MU',
    'MV' => 'dv_MV',
    'MW' => 'ny_MW',
    'MX' => 'es_MX',
    'MY' => 'ms_MY',
    'MZ' => 'pt_MZ',
    'NA' => 'kj_NA',
    'NC' => 'fr_NC',
    'NE' => 'ha_Latn_NE',
    'NF' => 'en_NF',
    'NG' => 'en_NG',
    'NI' => 'es_NI',
    'NL' => 'nl_NL',
    'NO' => 'nb_NO',
    'NP' => 'ne_NP',
    'NR' => 'en_NR',
    'NU' => 'niu_NU',
    'NZ' => 'en_NZ',
    'OM' => 'ar_OM',
    'PA' => 'es_PA',
    'PE' => 'es_PE',
    'PF' => 'fr_PF',
    'PG' => 'tpi_PG',
    'PH' => 'fil_PH',
    'PK' => 'ur_PK',
    'PL' => 'pl_PL',
    'PM' => 'fr_PM',
    'PN' => 'en_PN',
    'PR' => 'es_PR',
    'PS' => 'ar_PS',
    'PT' => 'pt_PT',
    'PW' => 'pau_PW',
    'PY' => 'gn_PY',
    'QA' => 'ar_QA',
    'RE' => 'fr_RE',
    'RO' => 'ro_RO',
    'RS' => 'sr_Cyrl_RS',
    'RU' => 'ru_RU',
    'RW' => 'rw_RW',
    'SA' => 'ar_SA',
    'SB' => 'en_SB',
    'SC' => 'crs_SC',
    'SD' => 'ar_SD',
    'SE' => 'sv_SE',
    'SG' => 'en_SG',
    'SH' => 'en_SH',
    'SI' => 'sl_SI',
    'SJ' => 'nb_SJ',
    'SK' => 'sk_SK',
    'SL' => 'kri_SL',
    'SM' => 'it_SM',
    'SN' => 'fr_SN',
    'SO' => 'sw_SO',
    'SR' => 'srn_SR',
    'ST' => 'pt_ST',
    'SV' => 'es_SV',
    'SY' => 'ar_SY',
    'SZ' => 'en_SZ',
    'TC' => 'en_TC',
    'TD' => 'fr_TD',
    'TF' => 'und_TF',
    'TG' => 'fr_TG',
    'TH' => 'th_TH',
    'TJ' => 'tg_Cyrl_TJ',
    'TK' => 'tkl_TK',
    'TL' => 'pt_TL',
    'TM' => 'tk_TM',
    'TN' => 'ar_TN',
    'TO' => 'to_TO',
    'TR' => 'tr_TR',
    'TT' => 'en_TT',
    'TV' => 'tvl_TV',
    'TW' => 'zh_Hant_TW',
    'TZ' => 'sw_TZ',
    'UA' => 'uk_UA',
    'UG' => 'sw_UG',
    'UM' => 'en_UM',
    'US' => 'en_US',
    'UY' => 'es_UY',
    'UZ' => 'uz_Cyrl_UZ',
    'VA' => 'it_VA',
    'VC' => 'en_VC',
    'VE' => 'es_VE',
    'VG' => 'en_VG',
    'VI' => 'en_VI',
    'VN' => 'vn_VN',
    'VU' => 'bi_VU',
    'WF' => 'wls_WF',
    'WS' => 'sm_WS',
    'YE' => 'ar_YE',
    'YT' => 'swb_YT',
    'ZA' => 'en_ZA',
    'ZM' => 'en_ZM',
    'ZW' => 'sn_ZW'
);

/**
 * Store the transaltion for specific languages
 *
 * @var array
 */
protected $translation = array();

/**
 * Current locale
 *
 * @var string
 */
protected $locale;

/**
 * Default locale
 *
 * @var string
 */
protected $default_locale;

/**
 *
 * @var string
 */
protected $locale_dir;

/**
 * Construct.
 *
 *
 * @param string $locale_dir            
 */
public function __construct($locale_dir)
{
    $this->locale_dir = $locale_dir;
}

/**
 * Set the user define localte
 *
 * @param string $locale            
 */
public function setLocale($locale = null)
{
    $this->locale = $locale;

    return $this;
}

/**
 * Get the user define locale
 *
 * @return string
 */
public function getLocale()
{
    return $this->locale;
}

/**
 * Get the Default locale
 *
 * @return string
 */
public function getDefaultLocale()
{
    return $this->default_locale;
}

/**
 * Set the default locale
 *
 * @param string $locale            
 */
public function setDefaultLocale($locale)
{
    $this->default_locale = $locale;

    return $this;
}

/**
 * Determine if transltion exist or translation key exist
 *
 * @param string $locale            
 * @param string $key            
 * @return boolean
 */
public function hasTranslation($locale, $key = null)
{
    if (null == $key && isset($this->translation[$locale])) {
        return true;
    } elseif (isset($this->translation[$locale][$key])) {
        return true;
    }

    return false;
}

/**
 * Get the transltion for required locale or transtion for key
 *
 * @param string $locale            
 * @param string $key            
 * @return array
 */
public function getTranslation($locale, $key = null)
{
    if (null == $key && $this->hasTranslation($locale)) {
        return $this->translation[$locale];
    } elseif ($this->hasTranslation($locale, $key)) {
        return $this->translation[$locale][$key];
    }

    return array();
}

/**
 * Set the transtion for required locale
 *
 * @param string $locale
 *            Language code
 * @param string $trans
 *            translations array
 */
public function setTranslation($locale, $trans = array())
{
    $this->translation[$locale] = $trans;
}

/**
 * Remove transltions for required locale
 *
 * @param string $locale            
 */
public function removeTranslation($locale = null)
{
    if (null === $locale) {
        unset($this->translation);
    } else {
        unset($this->translation[$locale]);
    }
}

/**
 * Initialize locale
 *
 * @param string $locale            
 */
public function init($locale = null, $default_locale = null)
{
    // check if previously set locale exist or not
    $this->init_locale();
    if ($this->locale != null) {
        return;
    }

    if ($locale == null || (! preg_match('#^[a-z]+_[a-zA-Z_]+$#', $locale) && ! preg_match('#^[a-z]+_[a-zA-Z]+_[a-zA-Z_]+$#', $locale))) {
        $this->detectLocale();
    } else {
        $this->locale = $locale;
    }

    $this->init_locale();
}

/**
 * Attempt to autodetect locale
 *
 * @return void
 */
private function detectLocale()
{
    $locale = false;

    // GeoIP
    if (function_exists('geoip_country_code_by_name') && isset($_SERVER['REMOTE_ADDR'])) {

        $country = geoip_country_code_by_name($_SERVER['REMOTE_ADDR']);

        if ($country) {

            $locale = isset($this->country_to_locale[$country]) ? $this->country_to_locale[$country] : false;
        }
    }

    // Try detecting locale from browser headers
    if (! $locale) {

        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {

            $languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);

            foreach ($languages as $lang) {

                $lang = str_replace('-', '_', trim($lang));

                if (strpos($lang, '_') === false) {

                    if (isset($this->country_to_locale[strtoupper($lang)])) {

                        $locale = $this->country_to_locale[strtoupper($lang)];
                    }
                } else {

                    $lang = explode('_', $lang);

                    if (count($lang) == 3) {
                        // language_Encoding_COUNTRY
                        $this->locale = strtolower($lang[0]) . ucfirst($lang[1]) . strtoupper($lang[2]);
                    } else {
                        // language_COUNTRY
                        $this->locale = strtolower($lang[0]) . strtoupper($lang[1]);
                    }

                    return;
                }
            }
        }
    }

    // Resort to default locale specified in config file
    if (! $locale) {
        $this->locale = $this->default_locale;
    }
}

/**
 * Check if config for selected locale exists
 *
 * @return void
 */
private function init_locale()
{
    if (! file_exists(sprintf('%s/%s.php', $this->locale_dir, $this->locale))) {
        $this->locale = $this->default_locale;
    }
}

/**
 * Load a Transtion into array
 *
 * @return void
 */
private function loadTranslation($locale = null, $force = false)
{
    if ($locale == null)
        $locale = $this->locale;

    if (! $this->hasTranslation($locale)) {
        $this->setTranslation($locale, include (sprintf('%s/%s.php', $this->locale_dir, $locale)));
    }
}

/**
 * Translate a key
 *
 * @param
 *            string Key to be translated
 * @param
 *            string optional arguments
 * @return string
 */
public function translate($key)
{
    $this->init();
    $this->loadTranslation($this->locale);

    if (! $this->hasTranslation($this->locale, $key)) {

        if ($this->locale !== $this->default_locale) {

            $this->loadTranslation($this->default_locale);

            if ($this->hasTranslation($this->default_locale, $key)) {

                $translation = $this->getTranslation($this->default_locale, $key);
            } else {
                // return key as it is or log error here
                return $key;
            }
        } else {
            return $key;
        }
    } else {
        $translation = $this->getTranslation($this->locale, $key);
    }
    // Replace arguments
    if (false !== strpos($translation, '{a:')) {
        $replace = array();
        $args = func_get_args();
        for ($i = 1, $max = count($args); $i < $max; $i ++) {
            $replace['{a:' . $i . '}'] = $args[$i];
        }
        // interpolate replacement values into the messsage then return
        return strtr($translation, $replace);
    }

    return $translation;
  }
}

Verwendung

 <?php
    ## /locale/en.php

    return array(
       'name' => 'Hello {a:1}'
       'name_full' => 'Hello {a:1} {a:2}'
   );

$locale = new Locale(__DIR__ . '/locale');
$locale->setLocale('en');// load en.php from locale dir
//want to work with auto detection comment $locale->setLocale('en');

echo $locale->translate('name', 'Foo');
echo $locale->translate('name', 'Foo', 'Bar');

Wie es funktioniert

{a:1}wird durch das erste an die Methode übergebene Argument ersetzt. wird durch das an die Methode übergebene Locale::translate('key_name','arg1') {a:2}zweite Argument ersetztLocale::translate('key_name','arg1','arg2')

Wie die Erkennung funktioniert

  • Wenn geoipinstalliert, wird standardmäßig der Ländercode von zurückgegeben, geoip_country_code_by_nameund wenn Geoip nicht installiert ist, wird der Fallback auf den HTTP_ACCEPT_LANGUAGEHeader zurückgesetzt

Inwiefern wäre eine Datenbank chaotisch? Wegen der möglichen Zeichen in verschiedenen Sprachen? Bisher habe ich hauptsächlich englische, französische, niederländische und deutsche Websites, so dass dies vorerst kein Problem ist. Vielen Dank für die Antwort, aber da es nur ein Teil der Antwort ist, wird es das Kopfgeld nicht gewinnen.
Joshua - Pendo

Nun, ich denke, Ihre Frage ist nur für Sie hilfreich. Es gibt einige Leute, die in Betracht ziehen würden, Sprachen wie Hindi, Thai, Chinesisch und Arabisch (diese Sprache benötigt mehr als 1 Byte, um ein Zeichen darzustellen) für Ihre erforderlichen Sprachen zu verwenden. Wenn Sie db verwenden, ist die utf8_general_ciSortierung die geeignete Methode.
Shushant

Ich stimme zu, ich habe dort selbst ein bisschen Spur bekommen. Vielen Dank für den Hinweis, auch Multi-Bit-Zeichen sind wichtig genug, um in dieser Frage erwähnt zu werden :)
Joshua - Pendo

5

Nur eine untergeordnete Antwort: Verwenden Sie unbedingt übersetzte URLs mit einer Sprachkennung vor sich: http://www.domain.com/nl/over-ons
Hybride-Lösungen werden in der Regel kompliziert, daher ich einfach dabei. Warum? Denn die URL ist für SEO unerlässlich.

Über die Datenbankübersetzung: Ist die Anzahl der Sprachen mehr oder weniger festgelegt? Oder eher unvorhersehbar und dynamisch? Wenn es behoben ist, würde ich nur neue Spalten hinzufügen, sonst mit mehreren Tabellen gehen.

Aber warum nicht generell Drupal verwenden? Ich weiß, dass jeder sein eigenes CMS erstellen möchte, weil es schneller, schlanker usw. usw. ist. Aber das ist wirklich eine schlechte Idee!


1
Danke für deine Antwort. Der Grund, warum ich Drupal / Joomla nicht verwenden möchte, ist einfach: Ich möchte sicherstellen, dass ich alle Vor- und Nachteile meines Systems kenne, pausierbare Fehler, wie der Code erstellt wird (und wichtig: nicht von 300 Programmierern zusammen erstellt). . Ich habe mehr als genug Gründe, mich nicht für Open Source zu entscheiden. Außerdem möchte ich, dass mein Unternehmen ein wichtiger Faktor für meine Kunden ist. Es ist eine schlechte Sache, dass sie zu jedem anderen Entwickler gehen und mich mit nichts zurücklassen können.
Joshua - Pendo

7
Ich denke, all diese Gründe sind in Tonnen von Artikeln umstritten. Ihre Kunden werden Sie hoffentlich nicht genau auswählen, da Sie ein proprietäres CMS haben, das niemand sonst warten kann. Aber das ist eine ganz andere Diskussion.
Remy

1
Ich verstehe Ihren Standpunkt, trotzdem bevorzuge ich ein System, für das ich alle Vor- und Nachteile kenne, und ich habe nichts dagegen, mich auf andere Arbeiten zu verlassen, wenn ich ein Plugin verwende.
Joshua - Pendo

1
Außerdem neige ich dazu, meine Arbeit gut genug zu dokumentieren, da ich eine "Ein-Mann-Armee" bin, die für mich arbeitet und es nicht schwer haben sollte, das System kennenzulernen.
Joshua - Pendo

Schlechte Idee ist es, Drupal zu wählen und sogar Google sagt, dass es ihnen egal ist, ob die URL übersetzt wird oder nicht. Es muss jedoch eine Gebietsschema-ID enthalten.
Undefinedman

4

Ich hatte vor einiger Zeit das gleiche Problem, bevor ich mit der Verwendung des Symfony- Frameworks begann.

  1. Verwenden Sie einfach eine Funktion __ () mit den Parametern pageId (oder objectId, objectTable, beschrieben in # 2), der Zielsprache und einem optionalen Parameter der Fallback-Sprache (Standard). Die Standardsprache kann in einigen globalen Konfigurationen festgelegt werden, um sie später einfacher ändern zu können.

  2. Zum Speichern des Inhalts in der Datenbank habe ich folgende Struktur verwendet: (Seiten-ID, Sprache, Inhalt, Variablen).

    • pageId wäre ein FK für Ihre Seite, die Sie übersetzen möchten. Wenn Sie andere Objekte haben, wie Nachrichten, Galerien oder was auch immer, teilen Sie diese einfach in zwei Felder auf: objectId, objectTable.

    • Sprache - offensichtlich würde es die ISO-Sprachzeichenfolge EN_en, LT_lt, EN_us usw. speichern.

    • Inhalt - Der Text, den Sie zusammen mit den Platzhaltern zum Ersetzen von Variablen übersetzen möchten. Beispiel "Hallo Herr. %% Name %%. Ihr Kontostand ist %% Kontostand %%."

    • Variablen - die json-codierten Variablen. PHP bietet Funktionen, um diese schnell zu analysieren. Beispiel "Name: Laurynas, Saldo: 15,23".

    • Sie haben auch Schneckenfeld erwähnt. Sie können es dieser Tabelle frei hinzufügen, um schnell danach suchen zu können.

  3. Ihre Datenbankaufrufe müssen durch Zwischenspeichern der Übersetzungen auf ein Minimum reduziert werden. Es muss im PHP-Array gespeichert werden, da es die schnellste Struktur in der PHP-Sprache ist. Wie Sie dieses Caching durchführen, liegt bei Ihnen. Nach meiner Erfahrung sollten Sie einen Ordner für jede unterstützte Sprache und ein Array für jede Seiten-ID haben. Der Cache sollte neu erstellt werden, nachdem Sie die Übersetzung aktualisiert haben. NUR das geänderte Array sollte neu generiert werden.

  4. Ich glaube, ich habe das in # 2 beantwortet

  5. Ihre Idee ist vollkommen logisch. Dieser ist ziemlich einfach und ich denke, wird Ihnen keine Probleme machen.

URLs sollten mit den in der Übersetzungstabelle gespeicherten Slugs übersetzt werden.

Letzte Worte

Es ist immer gut, die Best Practices zu erforschen, aber das Rad nicht neu zu erfinden. Nehmen Sie einfach die Komponenten aus bekannten Frameworks und verwenden Sie sie.

Schauen Sie sich die Symfony-Übersetzungskomponente an . Es könnte eine gute Codebasis für Sie sein.


Vielen Dank für den Kommentar, aswel a +1 für Ihre Zeit genommen. Laravel (in meinem Fall) verwendet einige Symfony-Teile, wenn ich mich nicht irre. Sie haben also absolut Recht, das Rad nicht neu zu erfinden. Ich habe mit dieser Frage (und dem Kopfgeld) begonnen, um einige Einblicke in die Art und Weise zu bekommen, wie andere die Übersetzungen machen. Ich fange an zu glauben, dass es viele Best Practices gibt :-)
Joshua - Pendo

4

Ich werde nicht versuchen, die bereits gegebenen Antworten zu verfeinern. Stattdessen erzähle ich Ihnen, wie mein eigenes OOP PHP-Framework mit Übersetzungen umgeht.

Intern verwendet mein Framework Codes wie en, fr, es, cn und so weiter. Ein Array enthält die von der Website unterstützten Sprachen: array ('en', 'fr', 'es', 'cn') Der Sprachcode wird über $ _GET (lang = fr) übergeben und wenn er nicht übergeben oder ungültig ist, wird er übergeben wird auf die erste Sprache im Array gesetzt. Während der Programmausführung und von Anfang an ist die aktuelle Sprache bekannt.

Es ist hilfreich zu verstehen, welche Art von Inhalten in einer typischen Anwendung übersetzt werden müssen:

1) Fehlermeldungen von Klassen (oder Verfahrenscode) 2) Nicht-Fehlermeldungen von Klassen (oder Verfahrenscode) 3) Seiteninhalt (normalerweise in einer Datenbank gespeichert) 4) Site-weite Zeichenfolgen (wie Website-Name) 5) Skript- bestimmte Zeichenfolgen

Der erste Typ ist einfach zu verstehen. Grundsätzlich handelt es sich um Nachrichten wie "Verbindung zur Datenbank konnte nicht hergestellt werden ...". Diese Nachrichten müssen nur geladen werden, wenn ein Fehler auftritt. Meine Manager-Klasse erhält einen Aufruf von den anderen Klassen und verwendet die als Parameter übergebenen Informationen einfach, um in den relevanten Klassenordner zu gelangen und die Fehlerdatei abzurufen.

Die zweite Art von Fehlermeldung ähnelt eher den Meldungen, die Sie erhalten, wenn die Validierung eines Formulars fehlgeschlagen ist. ("Sie können nicht ... leer lassen" oder "Bitte wählen Sie ein Passwort mit mehr als 5 Zeichen"). Die Zeichenfolgen müssen geladen werden, bevor die Klasse ausgeführt wird. Ich weiß, was ist

Für den eigentlichen Seiteninhalt verwende ich eine Tabelle pro Sprache, wobei jeder Tabelle der Code für die Sprache vorangestellt ist. En_content ist also die Tabelle mit englischsprachigem Inhalt, es_content ist für Spanien, cn_content für China und fr_content ist das französische Zeug.

Die vierte Art von Zeichenfolge ist auf Ihrer Website relevant. Dies wird über eine Konfigurationsdatei geladen, die mit dem Code für die Sprache en_lang.php, es_lang.php usw. benannt ist. In der globalen Sprachdatei müssen Sie die übersetzten Sprachen wie Array ('Englisch', 'Chinesisch', 'Spanisch', 'Französisch') in die globale englische Datei und das Array ('Anglais', 'Chinois', 'laden). Espagnol ',' Francais ') in der französischen Akte. Wenn Sie also ein Dropdown-Menü für die Sprachauswahl ausfüllen, ist es in der richtigen Sprache;)

Schließlich haben Sie die skriptspezifischen Zeichenfolgen. Wenn Sie also eine Kochanwendung schreiben, lautet diese möglicherweise "Ihr Ofen war nicht heiß genug".

In meinem Anwendungszyklus wird zuerst die globale Sprachdatei geladen. Dort finden Sie nicht nur globale Zeichenfolgen (wie "Jack's Website"), sondern auch Einstellungen für einige der Klassen. Grundsätzlich alles, was sprach- oder kulturabhängig ist. Einige der darin enthaltenen Zeichenfolgen enthalten Datumsmasken (MMTTJJJJ oder TTMMJJJJ) oder ISO-Sprachcodes. In der Hauptsprachendatei füge ich Zeichenfolgen für einzelne Klassen hinzu, da es so wenige davon gibt.

Die zweite und letzte Sprachdatei, die von der Festplatte gelesen wird, ist die Skriptsprachendatei. lang_en_home_welcome.php ist die Sprachdatei für das Home / Welcome-Skript. Ein Skript wird durch einen Modus (Home) und eine Aktion (Welcome) definiert. Jedes Skript hat einen eigenen Ordner mit Konfigurations- und Lang-Dateien.

Das Skript ruft den Inhalt aus der Datenbank ab und benennt die Inhaltstabelle wie oben erläutert.

Wenn etwas schief geht, weiß der Manager, wo er die sprachabhängige Fehlerdatei erhält. Diese Datei wird nur im Fehlerfall geladen.

Die Schlussfolgerung liegt also auf der Hand. Denken Sie über die Übersetzungsprobleme nach, bevor Sie mit der Entwicklung einer Anwendung oder eines Frameworks beginnen. Sie benötigen außerdem einen Entwicklungsworkflow, der Übersetzungen enthält. Mit meinem Framework entwickle ich die gesamte Site auf Englisch und übersetze dann alle relevanten Dateien.

Nur ein kurzes letztes Wort zur Implementierung der Übersetzungszeichenfolgen. Mein Framework hat einen einzigen globalen, den $ -Manager, der Dienste ausführt, die für jeden anderen Dienst verfügbar sind. So greift beispielsweise der Formulardienst auf den HTML-Dienst zu und verwendet ihn zum Schreiben des HTML-Dienstes. Einer der Dienste auf meinem System ist der Übersetzerservice. $ translator-> set ($ service, $ code, $ string) legt einen String für die aktuelle Sprache fest. Die Sprachdatei ist eine Liste solcher Anweisungen. $ translator-> get ($ service, $ code) ruft eine Übersetzungszeichenfolge ab. Der $ -Code kann numerisch wie 1 oder eine Zeichenfolge wie 'no_connection' sein. Es kann keine Konflikte zwischen Diensten geben, da jeder seinen eigenen Namespace im Datenbereich des Übersetzers hat.

Ich poste dies hier in der Hoffnung, dass es jemandem die Aufgabe erspart, das Rad neu zu erfinden, wie ich es vor einigen langen Jahren tun musste.


1

Ich habe mir immer wieder verwandte Fragen gestellt und mich dann in formalen Sprachen verirrt ... aber nur um Ihnen ein wenig zu helfen, möchte ich einige Erkenntnisse mitteilen:

Ich empfehle, einen Blick auf das erweiterte CMS zu werfen

Typo3für PHP (ich weiß, dass es viele Sachen gibt, aber das ist das, was ich für am ausgereiftesten halte)

Plone im Python

Wenn Sie herausfinden, dass das Web 2013 anders funktionieren sollte, beginnen Sie bei Null. Das würde bedeuten, ein Team hochqualifizierter / erfahrener Leute zusammenzustellen, um ein neues CMS zu erstellen. Vielleicht möchten Sie zu diesem Zweck einen Blick auf Polymer werfen.

Wenn es um Codierung und mehrsprachige Websites / Unterstützung für Muttersprachen geht, sollte jeder Programmierer eine Ahnung von Unicode haben. Wenn Sie Unicode nicht kennen, werden Sie Ihre Daten mit Sicherheit durcheinander bringen. Gehen Sie nicht mit den Tausenden von ISO-Codes. Sie sparen Ihnen nur etwas Speicher. Aber Sie können buchstäblich alles mit UTF-8 machen, sogar chinesische Zeichen speichern. Dafür müssten Sie jedoch entweder 2- oder 4-Byte-Zeichen speichern, was es im Grunde zu einem utf-16 oder utf-32 macht.

Wenn es um URL-Codierung geht, sollten Sie auch hier keine Codierungen mischen und sich darüber im Klaren sein, dass zumindest für den Domainnamen Regeln definiert sind, die von verschiedenen Lobbys definiert werden und Anwendungen wie einen Browser bereitstellen. zB könnte eine Domain sehr ähnlich sein wie:

ьankofamerica.com oder bankofamerica.com gleich, aber anders;)

Natürlich benötigen Sie das Dateisystem, um mit allen Codierungen arbeiten zu können. Ein weiteres Plus für Unicode mit dem utf-8-Dateisystem.

Wenn es um Übersetzungen geht, denken Sie an die Struktur von Dokumenten. zB ein Buch oder ein Artikel. Sie haben die docbookSpezifikationen, um diese Strukturen zu verstehen. Aber in HTML geht es nur um Inhaltsblöcke. Sie möchten also eine Übersetzung auf dieser Ebene, auch auf Webseiten- oder Domain-Ebene. Wenn ein Block nicht vorhanden ist, ist er einfach nicht vorhanden. Wenn eine Webseite nicht vorhanden ist, werden Sie zur oberen Navigationsebene weitergeleitet. Wenn eine Domain in der Navigationsstruktur völlig anders sein sollte, dann ist es eine völlig andere Struktur, die verwaltet werden muss. Dies ist bereits mit Typo3 möglich.

Wenn es um Frameworks geht, die ausgereiftesten, die ich kenne, um allgemeine Dinge wie MVC zu machen (Schlagwort, ich hasse es wirklich! Wie "Leistung" Wenn Sie etwas verkaufen möchten, verwenden Sie das Wort Leistung und featurerich und Sie verkaufen ... was zum Teufel) ist Zend. Es hat sich als eine gute Sache erwiesen, Standards für PHP-Chaos-Codierer bereitzustellen. Typo3 hat aber neben dem CMS auch ein Framework. Vor kurzem wurde es neu entwickelt und heißt jetzt flow3. Die Frameworks umfassen natürlich Datenbankabstraktion, Template und Konzepte für das Caching, haben aber individuelle Stärken.

Wenn es um Caching geht ... kann das furchtbar kompliziert / vielschichtig sein. In PHP denken Sie an Accellerator, Opcode, aber auch an HTML, httpd, MySQL, XML, CSS, JS ... alle Arten von Caches. Natürlich sollten einige Teile zwischengespeichert werden und dynamische Teile wie Blog-Antworten nicht. Einige sollten über AJAX mit generierten URLs angefordert werden. JSON, Hashbangs usw.

Dann möchten Sie, dass eine kleine Komponente auf Ihrer Website nur von bestimmten Benutzern aufgerufen oder verwaltet wird , was konzeptionell eine große Rolle spielt.

Außerdem möchten Sie Statistiken erstellen, vielleicht ein verteiltes System / ein Facebook von Facebook usw. haben. Jede Software, die auf Ihren Over-the-Top-CMS erstellt werden soll. Sie benötigen also verschiedene Arten von Datenbanken, Speicher, BigData, XML, was auch immer .

Nun, ich denke das ist genug für jetzt. Wenn Sie weder von Tippfehler3 / Plone noch von den genannten Frameworks gehört haben, haben Sie genug zu lernen. Auf diesem Weg finden Sie viele Lösungen für Fragen, die Sie noch nicht gestellt haben.

Wenn Sie dann denken, lassen Sie uns ein neues CMS erstellen, weil sein 2013 und PHP sowieso bald sterben werden, dann können Sie sich gerne einer anderen Gruppe von Entwicklern anschließen, die hoffentlich nicht verloren gehen.

Viel Glück!

Und übrigens. Wie wäre es, wenn die Leute in Zukunft keine Websites mehr haben? und wir werden alle auf google + sein? Ich hoffe, die Entwickler werden etwas kreativer und tun etwas Nützliches (um sich nicht von der Borgle assimilieren zu lassen).

//// Bearbeiten /// Nur ein kleiner Gedanke für Ihre bestehende Anwendung:

Wenn Sie ein PHP-MySQL-CMS haben und Multilang-Unterstützung einbetten möchten. Sie können entweder Ihre Tabelle mit einer zusätzlichen Spalte für eine beliebige Sprache verwenden oder die Übersetzung mit einer Objekt-ID und einer Sprach-ID in dieselbe Tabelle einfügen oder eine identische Tabelle für eine beliebige Sprache erstellen und dort Objekte einfügen und dann eine ausgewählte Vereinigung erstellen, wenn Sie möchten um sie alle anzeigen zu lassen. Verwenden Sie für die Datenbank utf8 general ci und natürlich im Front / Backend utf8 text / encoding. Ich habe URL-Pfadsegmente für URLs so verwendet, wie Sie es bereits erklärt haben

domain.org/en/about können Sie die lang-ID Ihrer Inhaltstabelle zuordnen. Auf jeden Fall benötigen Sie eine Zuordnung von Parametern für Ihre URLs, damit Sie einen Parameter definieren möchten, der aus einem Pfadsegment in Ihrer URL zugeordnet werden soll, z

domain.org/en/about/employees/IT/administrators/

Lookup-Konfiguration

pageid | URL

1 | /about/employees/../ ..

1 | /../about/employees../../

Zuordnen von Parametern zum URL-Pfadsegment ""

$parameterlist[lang] = array(0=>"nl",1=>"en"); // default nl if 0
$parameterlist[branch] = array(1=>"IT",2=>"DESIGN"); // default nl if 0
$parameterlist[employertype] = array(1=>"admin",1=>"engineer"); //could be a sql result 

$websiteconfig[]=$userwhatever;
$websiteconfig[]=$parameterlist;
$someparameterlist[] = array("branch"=>$someid);
$someparameterlist[] = array("employertype"=>$someid);
function getURL($someparameterlist){ 
// todo foreach someparameter lookup pathsegment 
return path;
}

per say, das ist schon im oberen Beitrag behandelt worden.

Und um nicht zu vergessen, müssten Sie die URL in Ihre generierende PHP-Datei "umschreiben", die in den meisten Fällen index.php wäre


Vielen Dank für den Kommentar, es gibt sicherlich Dinge, über die ich nachdenken sollte. Ich benutze die utf8-Codierung bereits seit ein paar Jahren, ich hatte einmal Probleme mit dem Charakter ;-) Auf der anderen Seite sollte die Art von CMS / Framework kein Faktor in Ihrer Antwort sein, da ich nach einem suchte Plattformunabhängige Methode, als würden wir von Grund auf neu codieren.
Joshua - Pendo

Wenn Sie wirklich von Grund auf neu programmieren möchten, empfehle ich einen Blick auf Dartlang und Polymer. Da dartlang im Browser arbeitet und 32- und 64-Bit-Unterstützung bietet und für die meisten Zwecke auf der Serverseite verwendet werden kann und einen dart2js-Compiler hat, lohnt es sich wirklich, ihn zu untersuchen. Wenn Leute über Plattformunabhängigkeit sprechen, denken sie an Java ... wir wissen, was das bedeutet. Buildprocess ... Ich denke, ich würde JSON für den Austausch verwenden. Generierte Website-Clientseite mit Hashbangs und Serverseite. Tun Sie alles, was Sie wollen, um die Zusammenarbeit sicherzustellen.
Dr. Dama

Die Datenbanklayout- und Generierungslogik ist die Hauptaufgabe. Nobodys werden das hier für Sie tun ... aber die Idee selbst ist das, was zählt. Da mir Lobbys egal sind, aber um Dinge zu erledigen, hoffe ich, dass Sie Modelle erstellen und einige Dinge teilen können. Ich arbeite gerade an ähnlichen Aufgaben. Aber ich plane immer noch. Ich betrachte Typo3 als Backend und erstelle eine neue Client-Struktur. Das mehrsprachige Muster wird im Backend gelöst und teilt Informationen auf spezielle Weise für Suchmaschinen / Webservices. Wie auch immer, es ist alles kontextsensitiv und eine kontinuierliche Bauaufgabe
Dr. Dama

-1

Datenbankarbeit:

Sprachtabelle 'Sprachen' erstellen:

Felder:

language_id(primary and auto increamented)

language_name

created_at

created_by

updated_at

updated_by

Erstellen Sie eine Tabelle in der Datenbank 'Inhalt':

Felder:

content_id(primary and auto incremented)

main_content

header_content

footer_content

leftsidebar_content

rightsidebar_content

language_id(foreign key: referenced to languages table)

created_at

created_by

updated_at

updated_by

Frontend-Arbeit:

Wenn der Benutzer eine Sprache aus der Dropdown-Liste oder einem Bereich auswählt, speichern Sie die ausgewählte Sprach-ID in einer Sitzung wie:

$_SESSION['language']=1;

Rufen Sie nun Daten aus der Datenbanktabelle 'content' basierend auf der in der Sitzung gespeicherten Sprach-ID ab.

Details finden Sie hier http://skillrow.com/multilingual-website-in-php-2/


1
Dies ist ein Weg zur einfachen Sprachintegration, der dann benötigt wurde. Haben Sie überhaupt versucht, die vollständigen Beiträge zu lesen und Antworten zu geben?
Joshua - Pendo

-2

Als eine Person, die in Quebec lebt, wo fast alle Websites französisch und englisch sind ... habe ich viele, wenn nicht die meisten mehrsprachigen Plugins für WP ausprobiert ... die einzige nützliche Lösung, die mit all meinen Websites funktioniert, ist mQtranslate ... Ich lebe und sterbe damit!

https://wordpress.org/plugins/mqtranslate/


1
Ja gut, WP war kein Faktor der Frage. Dies könnte ein Kommentar gewesen sein
Joshua - Pendo

-3

Was ist mit WORDPRESS + MULTI-LANGUAGE SITE BASIS(Plugin)? Die Site wird folgende Struktur haben:

  • example.com/ eng / category1 / ....
  • example.com/ eng / my-page ....
  • example.com/ rus / category1 / ....
  • example.com/ rus / my-page ....

Das Plugin bietet eine Schnittstelle für die Übersetzung aller Phrasen mit einfacher Logik:

(ENG) my_title - "Hello user"
(SPA) my_title - "Holla usuario"

dann kann es ausgegeben werden:
echo translate('my_title', LNG); // LNG is auto-detected

ps Überprüfen Sie jedoch, ob das Plugin noch aktiv ist.


3
und ist nicht "Holla userio" in Spanisch ist "Hola Usuario"
bheatcoker

1
Lol Holla userio, das war lustig!
Spekdrum

Aus dem Grund, dass ich kein Spanisch konnte (nur verwendetes Beispiel), beeilen Sie sich, um abzustimmen !! :)
T.Todua

-5

Eine wirklich einfache Option, die mit jeder Website funktioniert, auf die Sie Javascript hochladen können, ist www.multilingualizer.com

Sie können den gesamten Text für alle Sprachen auf einer Seite platzieren und dann die Sprachen ausblenden, die der Benutzer nicht sehen muss. Funktioniert gut.


Achtung, SEO wäre sehr schlecht! Außerdem laden Sie den gesamten Inhalt, während Sie nur einen Teil davon benötigen, was wirklich eine schlechte Praxis ist.
Hafenkranich

seltsame Sachen, dass die Seite nur in Englisch ist ... warum verwenden sie ihre Lösung nicht?
eduardo.lopes
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.