He estado luchando con esta pregunta durante algunos meses, pero no he estado en una situación en la que necesite explorar todas las opciones posibles antes. En este momento, siento que es hora de conocer las posibilidades y crear mi propia preferencia personal para usar en mis próximos proyectos.
Permítanme primero esbozar la situación que estoy buscando.
Estoy a punto de actualizar / volver a desarrollar un sistema de gestión de contenido que he estado usando durante bastante tiempo. Sin embargo, siento que el lenguaje múltiple es una gran mejora para este sistema. Antes no usaba ningún framework, pero voy a usar Laraval4 para el próximo proyecto. Laravel parece la mejor opción de una forma más limpia de codificar PHP. Sidenote: Laraval4 should be no factor in your answer
. Estoy buscando formas generales de traducción que sean independientes de la plataforma / marco.
Lo que debe traducirse
Como el sistema que busco debe ser lo más fácil de usar posible, el método de gestión de la traducción debe estar dentro del CMS. No debería ser necesario iniciar una conexión FTP para modificar archivos de traducción o cualquier plantilla analizada html / php.
Además, estoy buscando la forma más fácil de traducir varias tablas de bases de datos, quizás sin la necesidad de crear tablas adicionales.
¿Qué se me ocurrió?
Como ya he estado buscando, leyendo y probando cosas yo mismo. Hay un par de opciones que tengo. Pero todavía no siento que haya alcanzado un método de mejores prácticas para lo que realmente estoy buscando. En este momento, esto es lo que se me ocurrió, pero este método también tiene efectos secundarios.
- Plantillas analizadas en PHP: PHP debe analizar el sistema de plantillas. De esta manera, puedo insertar los parámetros traducidos en el HTML sin tener que abrir las plantillas y modificarlas. Además de eso, las plantillas analizadas de PHP me dan la posibilidad de tener 1 plantilla para el sitio web completo en lugar de tener una subcarpeta para cada idioma (que he tenido antes). El método para alcanzar este objetivo puede ser Smarty, TemplatePower, Laravel's Blade o cualquier otro analizador de plantillas. Como dije, esto debería ser independiente de la solución escrita.
- Basada en la base de datos : tal vez no necesito mencionar esto nuevamente. Pero la solución debe ser impulsada por la base de datos. El CMS está destinado a ser orientado a objetos y MVC, por lo que necesitaría pensar en una estructura de datos lógica para las cadenas. Como mis plantillas se estructurarán: Plantillas / Controlador / view.php quizá Esta estructura tendría más sentido:
Controller.View.parameter
. La tabla de la base de datos tendría estos campos largos con unvalue
campo. Dentro de las plantillas podríamos usar algún método de clasificación comoecho __('Controller.View.welcome', array('name', 'Joshua'))
y el parámetro contieneWelcome, :name
. Así el resultado esWelcome, Joshua
. Esta parece una buena manera de hacerlo, porque los parámetros como: nombre son fáciles de entender por el editor. - Carga baja de la base de datos : por supuesto, el sistema anterior provocaría cargas de carga de la base de datos si estas cadenas se cargan sobre la marcha. Por lo tanto, necesitaría un sistema de almacenamiento en caché que vuelva a procesar los archivos de idioma tan pronto como se editen / guarden en el entorno de administración. Debido a que se generan archivos, también se necesita un buen diseño del sistema de archivos. Creo que podemos ir con
languages/en_EN/Controller/View.php
o .ini, lo que más te convenga. Quizás un .ini incluso se analice más rápido al final. Esto debe contener los datos en elformat parameter=value;
. Supongo que esta es la mejor manera de hacerlo, ya que cada vista que se representa puede incluir su propio archivo de idioma si existe. Los parámetros de idioma deben cargarse en una vista específica y no en un ámbito global para evitar que los parámetros se sobrescriban entre sí. - Traducción de la tabla de base de datos : de hecho, esto es lo que más me preocupa. Estoy buscando una manera de crear traducciones de Noticias / Páginas / etc. lo más rápido posible. Tener dos tablas para cada módulo (por ejemplo
News
yNews_translations
) es una opción, pero se siente mucho trabajo para obtener un buen sistema. Una de las cosas que se me ocurrió se basa en undata versioning
sistema que escribí: hay un nombre de tabla de base de datosTranslations
, esta tabla tiene una combinación única delanguage
,tablename
yprimarykey
. Por ejemplo: en_En / News / 1 (Refiriéndose a la versión en inglés del elemento News con ID = 1). Pero hay dos grandes desventajas en este método: en primer lugar, esta tabla tiende a ser bastante larga con una gran cantidad de datos en la base de datos y, en segundo lugar, sería un trabajo tremendo usar esta configuración para buscar en la tabla. Por ejemplo, buscar la babosa SEO del elemento sería una búsqueda de texto completo, lo cual es bastante tonto. Pero por otro lado: es una forma rápida de crear contenido traducible en cada tabla muy rápido, pero no creo que este profesional sobrepase los contras. - Trabajo front-end : también el front-end necesitaría algo de reflexión. Por supuesto, almacenaríamos los idiomas disponibles en una base de datos y (des) activaría los que necesitamos. De esta manera, el script puede generar un menú desplegable para seleccionar un idioma y el back-end puede decidir automáticamente qué traducciones se pueden hacer usando el CMS. El idioma elegido (por ejemplo, en_EN) se usaría al obtener el archivo de idioma para una vista o para obtener la traducción correcta para un elemento de contenido en el sitio web.
Entonces, ahí están. Mis ideas hasta ahora. Ni siquiera incluyen opciones de localización para fechas, etc. todavía, pero como mi servidor admite PHP5.3.2 +, la mejor opción es usar la extensión intl como se explica aquí: http://devzone.zend.com/1500/internationalization-in -php-53 / - pero esto sería útil en cualquier estadio posterior de desarrollo. Por ahora, el problema principal es cómo tener las mejores prácticas de traducción del contenido en un sitio web.
Además de todo lo que expliqué aquí, todavía tengo otra cosa que aún no he decidido, parece una pregunta simple, pero de hecho me ha estado dando dolores de cabeza:
Traducción de URL? ¿Deberíamos hacer esto o no? y de que manera
Entonces ... si tengo esta url: http://www.domain.com/about-us
y el inglés es mi idioma predeterminado. ¿Debería traducirse esta URL http://www.domain.com/over-ons
cuando elijo holandés como mi idioma? ¿O deberíamos ir por el camino fácil y simplemente cambiar el contenido de la página visible en /about
. Lo último no parece una opción válida porque eso generaría múltiples versiones de la misma URL, esta indexación del contenido fallará de la manera correcta.
Otra opción está usando en su http://www.domain.com/nl/about-us
lugar. Esto genera al menos una URL única para cada contenido. Además, sería más fácil ir a otro idioma, por ejemplo, http://www.domain.com/en/about-us
y la URL proporcionada es más fácil de entender tanto para los visitantes de Google como para los humanos. Con esta opción, ¿qué hacemos con los idiomas predeterminados? ¿Debería el idioma predeterminado eliminar el idioma seleccionado por defecto? Entonces, redirigir http://www.domain.com/en/about-us
a http://www.domain.com/about-us
... En mi opinión, esta es la mejor solución, porque cuando el CMS está configurado para un solo idioma, no es necesario tener esta identificación de idioma en la URL.
Y una tercera opción es una combinación de ambas opciones: usar el "idioma-identificación-menos" -URL ( http://www.domain.com/about-us
) para el idioma principal. Y use una URL con una babosa SEO traducida para sublenguajes: http://www.domain.com/nl/over-ons
&http://www.domain.com/de/uber-uns
Espero que mi pregunta haga que se te quiebren las cabezas, ¡seguro que me hicieron la mía! Ya me ayudó a resolver las cosas como una pregunta aquí. Me dio la posibilidad de revisar los métodos que he usado antes y la idea que tengo para mi próximo CMS.
¡Me gustaría agradecerle por tomarse el tiempo de leer este montón de texto!
// Edit #1
:
Olvidé mencionar: la función __ () es un alias para traducir una cadena dada. Dentro de este método, obviamente, debería haber algún tipo de método alternativo donde el texto predeterminado se carga cuando aún no hay traducciones disponibles. Si falta la traducción, debe insertarse o el archivo de traducción debe regenerarse.
fuente
Respuestas:
Premisa del tema
Hay tres aspectos distintos en un sitio multilingüe:
Si bien todos se interconectaron de diferentes maneras, desde el punto de vista del CMS se administran utilizando diferentes elementos de la IU y se almacenan de manera diferente. Parece que tiene confianza en su implementación y comprensión de los dos primeros. La pregunta era sobre el último aspecto: "¿Traducción de URL? ¿Deberíamos hacer esto o no? ¿Y de qué manera?"
¿De qué puede estar hecha la URL?
Una cosa muy importante es que no se entusiasme con IDN . En cambio, favorezca la transliteración (también: transcripción y romanización). Si bien a primera vista IDN parece una opción viable para las URL internacionales, en realidad no funciona como se anuncia por dos razones:
'ч'
o'ž'
en'%D1%87'
y'%C5%BE'
De hecho, intenté acercarme a IDN hace unos años en un proyecto basado en Yii (horrible framework, en mi humilde opinión). Encontré los dos problemas mencionados antes de desechar esa solución. Además, sospecho que podría ser un vector de ataque.
Opciones disponibles ... tal como las veo.
Básicamente tiene dos opciones, que podrían resumirse como:
http://site.tld/[:query]
: donde[:query]
determina la elección de idioma y contenidohttp://site.tld/[:language]/[:query]
: donde[:language]
parte de la URL define la elección del idioma y[:query]
se usa solo para identificar el contenidoLa consulta es Α y Ω ..
Digamos que eliges
http://site.tld/[:query]
.En ese caso, tiene una fuente principal de lenguaje: el contenido del
[:query]
segmento; y dos fuentes adicionales:$_COOKIE['lang']
para ese navegador en particularPrimero, debe hacer coincidir la consulta con uno de los patrones de enrutamiento definidos (si su elección es Laravel, lea aquí ). En una coincidencia exitosa de patrón, entonces necesita encontrar el idioma.
Tendría que pasar por todos los segmentos del patrón. Encuentre las posibles traducciones para todos esos segmentos y determine qué idioma se utilizó. Las dos fuentes adicionales (cookie y encabezado) se usarían para resolver conflictos de enrutamiento, cuando (no "si") surgen.
Tomemos, por ejemplo:
http://site.tld/blog/novinka
.Eso es transliteración de
"блог, новинка"
, que en inglés significa aproximadamente"blog", "latest"
.Como ya puede notar, en ruso "блог" será transcrito como "blog". Lo que significa que para la primera parte de
[:query]
usted (en el mejor de los casos ) terminará con una['en', 'ru']
lista de idiomas posibles. Luego tomas el siguiente segmento: "novinka". Eso podría tener solamente un idioma en la lista de posibilidades:['ru']
.Cuando la lista tiene un elemento, ha encontrado correctamente el idioma.
Pero si termina con 2 (ejemplo: ruso y ucraniano) o más posibilidades ... o 0 posibilidades, según sea el caso. Tendrá que usar cookies y / o encabezado para encontrar la opción correcta.
Y si todo lo demás falla, elige el idioma predeterminado del sitio.
Idioma como parámetro
La alternativa es usar URL, que se puede definir como
http://site.tld/[:language]/[:query]
. En este caso, al traducir una consulta, no necesita adivinar el idioma, porque en ese momento ya sabe cuál usar.También hay una fuente secundaria de lenguaje: el valor de la cookie. Pero aquí no tiene sentido meterse con el encabezado Accept-Language, porque no está tratando con una cantidad desconocida de idiomas posibles en caso de "arranque en frío" (cuando el usuario abre el sitio por primera vez con una consulta personalizada).
En cambio, tiene 3 opciones simples y priorizadas:
[:language]
segmento está configurado, úselo$_COOKIE['lang']
está configurado, úsaloCuando tenga el idioma, simplemente intente traducir la consulta, y si la traducción falla, use el "valor predeterminado" para ese segmento en particular (según los resultados de la ruta).
¿No hay aquí una tercera opción?
Sí, técnicamente es posible combinar ambos enfoques, pero eso complicaría el proceso y sólo dar cabida a las personas que quieren URL manualmente el cambio de
http://site.tld/en/news
ahttp://site.tld/de/news
y esperar que la página de noticias al cambio al Alemán.Pero incluso este caso probablemente podría mitigarse utilizando el valor de la cookie (que contendría información sobre la elección previa de idioma), para implementar con menos magia y esperanza.
¿Qué enfoque usar?
Como ya habrás adivinado, recomendaría
http://site.tld/[:language]/[:query]
como la opción más sensata.También en una situación de palabra real, tendría una tercera parte importante en la URL: "título". Como en el nombre del producto en la tienda en línea o título del artículo en el sitio de noticias.
Ejemplo:
http://site.tld/en/news/article/121415/EU-as-global-reserve-currency
En este caso
'/news/article/121415'
sería la consulta, y'EU-as-global-reserve-currency'
es el título. Puramente para fines de SEO.¿Se puede hacer en Laravel?
Un poco, pero no por defecto.
No estoy muy familiarizado con eso, pero por lo que he visto, Laravel utiliza un mecanismo de enrutamiento basado en patrones simples. Para implementar URL multilingües, probablemente tendrá que ampliar las clases principales , ya que el enrutamiento multilingüe necesita acceso a diferentes formas de almacenamiento (base de datos, caché y / o archivos de configuración).
Está enrutado. ¿Ahora que?
Como resultado de todo, terminaría con dos valiosas piezas de información: idioma actual y segmentos de consulta traducidos. Estos valores se pueden usar para enviarlos a la (s) clase (s) que producirán el resultado.
Básicamente, la siguiente URL:
http://site.tld/ru/blog/novinka
(o la versión sin'/ru'
) se convierte en algo así comoQue solo se usa para despachar:
.. o alguna variación, dependiendo de la implementación particular.
fuente
Implementando i18n sin el rendimiento alcanzado usando un preprocesador como lo sugiere Thomas Bley
En el trabajo, recientemente pasamos por la implementación de i18n en un par de nuestras propiedades, y una de las cosas con las que seguimos luchando fue el éxito en el desempeño de lidiar con la traducción sobre la marcha, luego descubrí esta gran publicación de blog de Thomas Bley que inspiró la forma en que usamos i18n para manejar grandes cargas de tráfico con problemas de rendimiento mínimos.
En lugar de llamar a funciones para cada operación de traducción, que como sabemos en PHP es costosa, definimos nuestros archivos base con marcadores de posición, luego usamos un preprocesador para almacenar en caché esos archivos (almacenamos el tiempo de modificación del archivo para asegurarnos de que estamos sirviendo el último contenido en todo momento).
Las etiquetas de traducción
Thomas usa
{tr}
y{/tr}
etiquetas para definir dónde comienzan y terminan las traducciones. Debido al hecho de que estamos usando TWIG, no queremos usarlo{
para evitar confusiones, así que usamos[%tr%]
y en su[%/tr%]
lugar. Básicamente, esto se ve así:Tenga en cuenta que Thomas sugiere usar el inglés base en el archivo. No hacemos esto porque no queremos tener que modificar todos los archivos de traducción si cambiamos el valor en inglés.
Los archivos INI
Luego, creamos un archivo INI para cada idioma, en el formato
placeholder = translated
:Sería trivial permitir que un usuario los modifique dentro del CMS, solo obtenga los pares de claves con un
preg_split
encendido\n
o=
y haciendo que el CMS pueda escribir en los archivos INI.El componente de preprocesador
Esencialmente, Thomas sugiere usar una función de 'compilador' justo a tiempo (aunque, en verdad, es un preprocesador) como esta para tomar sus archivos de traducción y crear archivos PHP estáticos en el disco. De esta manera, esencialmente almacenamos en caché nuestros archivos traducidos en lugar de llamar a una función de traducción para cada cadena en el archivo:
Nota: No verifiqué que la expresión regular funciona, no la copié del servidor de nuestra compañía, pero puede ver cómo funciona la operación.
Cómo llamarlo
De nuevo, este ejemplo es de Thomas Bley, no de mí:
Almacenamos el idioma en una cookie (o variable de sesión si no podemos obtener una cookie) y luego la recuperamos en cada solicitud. Puede combinar esto con un
$_GET
parámetro opcional para anular el idioma, pero no sugiero subdominio por idioma o página por idioma porque hará que sea más difícil ver qué páginas son populares y reducirá el valor de entrada enlaces ya que los tendrás más dispersos¿Por qué usar este método?
Nos gusta este método de preprocesamiento por tres razones:
Obtener contenido traducido de la base de datos
Simplemente agregamos una columna para el contenido en nuestra base de datos llamada
language
, luego usamos un método de acceso para laLANG
constante que definimos anteriormente, para que nuestras llamadas SQL (usando ZF1, lamentablemente) se vean así:Nuestros artículos tienen una clave principal compuesta
id
y,language
por lo tanto, el artículo54
puede existir en todos los idiomas. Nuestro valorLANG
predeterminado esen_US
si no se especifica.Traducción URL Slug
Combinaría dos cosas aquí, una es una función en su rutina de carga que acepta un
$_GET
parámetro para el idioma y anula la variable de la cookie, y otra es el enrutamiento que acepta múltiples babosas. Entonces puede hacer algo como esto en su enrutamiento:Estos podrían almacenarse en un archivo plano que podría escribirse fácilmente desde su panel de administración. JSON o XML pueden proporcionar una buena estructura para soportarlos.
Notas sobre algunas otras opciones
Traducción sobre la marcha basada en PHP
No veo que ofrezcan ninguna ventaja sobre las traducciones preprocesadas.
Traducciones basadas en front-end
Durante mucho tiempo he encontrado estos interesantes, pero hay algunas advertencias. Por ejemplo, debe poner a disposición del usuario la lista completa de frases en su sitio web que planea traducir, esto podría ser problemático si hay áreas del sitio que mantiene ocultas o no les ha permitido el acceso.
También debería suponer que todos sus usuarios están dispuestos y pueden usar Javascript en su sitio, pero según mis estadísticas, alrededor del 2.5% de nuestros usuarios se ejecutan sin él (o usan Noscript para bloquear el uso de nuestros sitios) .
Traducciones basadas en bases de datos
Las velocidades de conectividad de la base de datos de PHP no son nada del otro mundo, y esto se suma a la sobrecarga ya elevada de llamar a una función en cada frase para traducir. Los problemas de rendimiento y escalabilidad parecen abrumadores con este enfoque.
fuente
Why?
: simple .. No quiero molestarme con pequeños cambios en el texto, los usuarios deberían poder hacerlo ellos mismos sin usar un editor de código y / o un programa ftp :).INI
archivos de base de datos con una tabla de 3 columnas conplaceholder
,replacement
,language
. Tecla compuestaplaceholder
ylanguage
. Luego tenga otro 2-col contempfile
(ruta a la plantilla) ymodified
(DATETIME).Le sugiero que no invente una rueda y use gettext y la lista abreviada de idiomas ISO. ¿Has visto cómo se implementa i18n / l10n en marcos o CMS populares?
Usando gettext tendrás una herramienta poderosa donde muchos casos ya están implementados como formas plurales de números. En inglés solo tiene 2 opciones: singular y plural. Pero en ruso, por ejemplo, hay 3 formas y no es tan simple como en inglés.
Además, muchos traductores ya tienen experiencia para trabajar con gettext.
Echa un vistazo a CakePHP o Drupal . Ambos multilingües habilitados. CakePHP como ejemplo de localización de interfaz y Drupal como ejemplo de traducción de contenido.
Para l10n, usar la base de datos no es el caso en absoluto. Habrá toneladas de consultas. El enfoque estándar es obtener todos los datos de l10n en la memoria en una etapa temprana (o durante la primera llamada a la función i10n si prefiere la carga diferida). Puede leer desde el archivo .po o desde DB todos los datos a la vez. Y que solo lea las cadenas solicitadas de la matriz.
Si necesita implementar una herramienta en línea para traducir la interfaz, puede tener todos esos datos en la base de datos, pero aún así guardar todos los datos en el archivo para trabajar con ellos. Para reducir la cantidad de datos en la memoria, puede dividir todos los mensajes / cadenas traducidos en grupos y luego cargar solo los grupos que necesita si es posible.
Así que tienes toda la razón en tu # 3. Con una excepción: generalmente es un archivo grande, no un archivo por controlador, más o menos. Porque lo mejor para el rendimiento es abrir un archivo. Probablemente sepa que algunas aplicaciones web cargadas compilan todo el código PHP en un archivo para evitar operaciones de archivo cuando se llama a include / require.
Sobre las URL. Google sugiere indirectamente utilizar la traducción:
También creo que debe redirigir al usuario al prefijo de idioma predeterminado, por ejemplo, http://examlpe.com/about-us redirigirá a http://examlpe.com/en/about-us Pero si su sitio usa solo un idioma, entonces no necesita prefijos en absoluto.
Echa un vistazo: 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
Traducir contenido es una tarea más difícil. Creo que habrá algunas diferencias con los diferentes tipos de contenido, por ejemplo, artículos, elementos de menú, etc. Pero en el # 4 estás en el camino correcto. Echa un vistazo en Drupal para tener más ideas. Tiene un esquema de base de datos suficientemente claro y una interfaz lo suficientemente buena para traducir. Como si estuvieras creando un artículo y seleccionas el idioma. Y luego puedes traducirlo a otros idiomas.
Creo que no es un problema con los slugs de URL. Simplemente puede crear una tabla separada para las babosas y será la decisión correcta. También usando índices correctos no es problema consultar la tabla incluso con una gran cantidad de datos. Y no fue una búsqueda de texto completo, pero la coincidencia de cadenas si usará el tipo de datos varchar para slug y también puede tener un índice en ese campo.
PD: Perdón, mi inglés está lejos de ser perfecto.
fuente
Depende de cuánto contenido tenga su sitio web. Al principio, utilicé una base de datos como todas las demás personas aquí, pero puede llevar mucho tiempo escribir todos los trabajos de una base de datos. No digo que este sea un método ideal y especialmente si tiene mucho texto, pero si desea hacerlo rápido sin usar una base de datos, este método podría funcionar, sin embargo, no puede permitir que los usuarios ingresen datos que se usará como archivos de traducción. Pero si agrega las traducciones usted mismo, funcionará:
Digamos que tienes este texto:
Puede ingresar esto en una base de datos con traducciones, pero también puede hacer esto:
Ahora, si su sitio web utiliza una cookie, tiene esto, por ejemplo:
Para hacerlo más fácil, transformemos en un código que se pueda usar fácilmente:
Si su idioma de cookies es galés y tiene este código:
El resultado de esto será:
Si necesita agregar muchas traducciones para su sitio web y una base de datos consume demasiado, el uso de una matriz puede ser una solución ideal.
fuente
lang.en.php
que se incluirán y use el$lang['welcome']
que se declara en cada archivo.Le sugeriré que no dependa realmente de la base de datos para la traducción, podría ser una tarea realmente desordenada y podría ser un problema extremo en el caso de la codificación de datos.
Tuve un problema similar hace tiempo y escribí la siguiente clase para resolver mi problema
Objeto: Locale \ Locale
Uso
Cómo funciona
{a:1}
se reemplaza por el primer argumento pasado al métodoLocale::translate('key_name','arg1')
{a:2}
se reemplaza por el segundo argumento pasado al métodoLocale::translate('key_name','arg1','arg2')
Cómo funciona la detección
geoip
está instalado, devolverá el código de paísgeoip_country_code_by_name
y si geoip no está instalado, el respaldo alHTTP_ACCEPT_LANGUAGE
encabezadofuente
utf8_general_ci
clasificación es la forma adecuada de hacerlo.Solo una respuesta secundaria: utilice absolutamente las URL traducidas con un identificador de idioma delante de ellas: http://www.domain.com/nl/over-ons Las
soluciones Hybride tienden a complicarse, por lo que me quedaría con ellas. ¿Por qué? Porque la url es esencial para el SEO.
Acerca de la traducción db: ¿El número de idiomas es más o menos fijo? ¿O más bien impredecible y dinámico? Si se soluciona, simplemente agregaría nuevas columnas, de lo contrario iría con varias tablas.
Pero en general, ¿por qué no usar Drupal? Sé que todos quieren construir su propio CMS porque es más rápido, más ágil, etc. etc. ¡Pero eso es realmente una mala idea!
fuente
No voy a intentar refinar las respuestas ya dadas. En su lugar, le contaré sobre la forma en que mi propio marco PHP de OOP maneja las traducciones.
Internamente, mi framework usa códigos como en, fr, es, cn, etc. Una matriz contiene los idiomas admitidos por el sitio web: matriz ('en', 'fr', 'es', 'cn') El código de idioma se pasa a través de $ _GET (lang = fr) y, si no se pasa o no es válido, se establece en el primer idioma de la matriz. Entonces, en cualquier momento durante la ejecución del programa y desde el principio, se conoce el lenguaje actual.
Es útil comprender el tipo de contenido que debe traducirse en una aplicación típica:
1) mensajes de error de clases (o código de procedimiento) 2) mensajes sin error de clases (o código de procedimiento) 3) contenido de la página (generalmente almacenado en una base de datos) 4) cadenas de todo el sitio (como el nombre del sitio web) 5) script- cadenas específicas
El primer tipo es simple de entender. Básicamente, estamos hablando de mensajes como "no se pudo conectar a la base de datos ...". Estos mensajes solo necesitan cargarse cuando ocurre un error. Mi clase de administrador recibe una llamada de las otras clases y el uso de la información que se pasa como parámetros simplemente va a la carpeta de clase relevante y recupera el archivo de error.
El segundo tipo de mensaje de error es más parecido a los mensajes que recibe cuando la validación de un formulario salió mal. ("No puede dejar ... en blanco" o "elija una contraseña con más de 5 caracteres"). Las cadenas deben cargarse antes de que se ejecute la clase. Sé lo que es
Para el contenido real de la página, utilizo una tabla por idioma, cada tabla con el código del idioma como prefijo. Así que en_content es la tabla con contenido en inglés, es_content es para España, cn_content para China y fr_content es el material francés.
El cuarto tipo de cadena es relevante en todo su sitio web. Esto se carga a través de un archivo de configuración llamado usando el código para el idioma, es decir, en_lang.php, es_lang.php, etc. En el archivo de idioma global, deberá cargar los idiomas traducidos como array ('inglés', 'chino', 'español', 'francés') en el archivo global de inglés y array ('Anglais', 'Chinois', ' Espagnol ',' Francais ') en el archivo francés. Entonces, cuando llena un menú desplegable para la selección de idioma, está en el idioma correcto;)
Finalmente tienes las cadenas específicas del script. Entonces, si escribe una aplicación de cocción, podría ser "Su horno no estaba lo suficientemente caliente".
En mi ciclo de aplicación, el archivo de idioma global se carga primero. Allí encontrará no solo cadenas globales (como "Sitio web de Jack") sino también configuraciones para algunas de las clases. Básicamente todo lo que depende del idioma o la cultura. Algunas de las cadenas allí incluyen máscaras para fechas (MMDDYYYY o DDMMYYYY) o códigos de idioma ISO. En el archivo de idioma principal, incluyo cadenas para clases individuales porque hay muy pocas de ellas.
El segundo y último archivo de idioma que se lee del disco es el archivo de idioma del script. lang_en_home_welcome.php es el archivo de idioma para el script de inicio / bienvenida. Un script está definido por un modo (inicio) y una acción (bienvenido). Cada script tiene su propia carpeta con archivos de configuración y lang.
El script extrae el contenido de la base de datos nombrando la tabla de contenido como se explicó anteriormente.
Si algo sale mal, el administrador sabe dónde obtener el archivo de error dependiente del idioma. Ese archivo solo se carga en caso de error.
Entonces la conclusión es obvia. Piense en los problemas de traducción antes de comenzar a desarrollar una aplicación o marco. También necesita un flujo de trabajo de desarrollo que incorpore traducciones. Con mi marco, desarrollo todo el sitio en inglés y luego traduzco todos los archivos relevantes.
Solo una breve palabra final sobre la forma en que se implementan las cadenas de traducción. Mi marco tiene un único global, el $ manager, que ejecuta servicios disponibles para cualquier otro servicio. Entonces, por ejemplo, el servicio de formulario se apodera del servicio html y lo usa para escribir el html. Uno de los servicios en mi sistema es el servicio de traductor. $ translate-> set ($ service, $ code, $ string) establece una cadena para el idioma actual. El archivo de idioma es una lista de tales declaraciones. $ translate-> get ($ service, $ code) recupera una cadena de traducción. El código $ puede ser numérico como 1 o una cadena como 'no_connection'. No puede haber conflicto entre servicios porque cada uno tiene su propio espacio de nombres en el área de datos del traductor.
Publico esto aquí con la esperanza de salvar a alguien la tarea de reinventar la rueda como tenía que hacer hace unos años.
fuente
Tuve la misma sonda hace un tiempo, antes de comenzar a usar el framework Symfony .
Simplemente use una función __ () que tiene un parámetro pageId (u objectId, objectTable descrito en el n. ° 2), idioma de destino y un parámetro opcional de idioma de reserva (predeterminado). El idioma predeterminado podría establecerse en alguna configuración global para tener una forma más fácil de cambiarlo más tarde.
Para almacenar el contenido en la base de datos, utilicé la siguiente estructura: (pageId, idioma, contenido, variables).
pageId sería un FK a su página que desea traducir. Si tiene otros objetos, como noticias, galerías o lo que sea, simplemente divídalo en 2 campos objectId, objectTable.
idioma: obviamente, almacenaría la cadena de idioma ISO EN_en, LT_lt, EN_us, etc.
contenido: el texto que desea traducir junto con los comodines para la sustitución de variables. Ejemplo "Hola, señor. %% name %%. El saldo de su cuenta es %% balance %%".
variables: las variables codificadas por json. PHP proporciona funciones para analizar rápidamente estos. Ejemplo "nombre: Laurynas, saldo: 15.23".
Mencionaste también campo babosa. puedes agregarlo libremente a esta tabla solo para tener una forma rápida de buscarlo.
Las llamadas de su base de datos deben reducirse al mínimo con el almacenamiento en caché de las traducciones. Debe almacenarse en una matriz PHP, porque es la estructura más rápida en lenguaje PHP. Cómo va a hacer este almacenamiento en caché depende de usted. Según mi experiencia, debería tener una carpeta para cada idioma compatible y una matriz para cada ID de página. El caché debe reconstruirse después de actualizar la traducción. SOLO la matriz modificada debe regenerarse.
creo que respondí eso en el # 2
Tu idea es perfectamente lógica. Este es bastante simple y creo que no te hará ningún problema.
Las URL deben traducirse utilizando las babosas almacenadas en la tabla de traducción.
Ultimas palabras
Siempre es bueno investigar las mejores prácticas, pero no reinventar la rueda. simplemente tome y use los componentes de marcos conocidos y úselos.
Echa un vistazo al componente de traducción de Symfony . Podría ser un buen código base para ti.
fuente
Me he estado haciendo preguntas relacionadas una y otra vez, luego me perdí en los idiomas formales ... pero solo para ayudarte un poco, me gustaría compartir algunos hallazgos:
Recomiendo echar un vistazo a CMS avanzado
Typo3
paraPHP
(sé que hay muchas cosas, pero esa es la que creo que es más madura)Plone
enPython
Si descubre que la web en 2013 debería funcionar de manera diferente, comience desde cero. Eso significaría reunir un equipo de personas altamente calificadas / experimentadas para construir un nuevo CMS. Puede ser que desee echar un vistazo al polímero para ese propósito.
Si se trata de codificación y sitios web multilingües / soporte de idioma nativo, creo que cada programador debería tener una pista sobre Unicode. Si no conoce Unicode, seguramente arruinará sus datos. No vaya con los miles de códigos ISO. Solo te ahorrarán un poco de memoria. Pero puedes hacer literalmente todo con UTF-8 incluso almacenar caracteres chinos. Pero para eso necesitaría almacenar caracteres de 2 o 4 bytes que lo hacen básicamente un utf-16 o utf-32.
Si se trata de la codificación de URL, nuevamente no debe mezclar codificaciones y tener en cuenta que al menos para el nombre de dominio hay reglas definidas por diferentes grupos de presión que proporcionan aplicaciones como un navegador. Por ejemplo, un dominio podría ser muy similar a:
ьankofamerica.com o bankofamerica.com lo mismo pero diferente;)
Por supuesto, necesita el sistema de archivos para trabajar con todas las codificaciones. Otra ventaja para unicode usando el sistema de archivos utf-8.
Si se trata de traducciones, piense en la estructura de los documentos. Por ejemplo, un libro o un artículo. Tienes las
docbook
especificaciones para entender sobre esas estructuras. Pero en HTML se trata solo de bloques de contenido. Por lo tanto, le gustaría tener una traducción en ese nivel, también en el nivel de página web o de dominio. Entonces, si no existe un bloque, simplemente no está allí, si no existe una página web, se lo redirigirá al nivel de navegación superior. Si un dominio debe ser completamente diferente en la estructura de navegación, entonces ... es una estructura completamente diferente para administrar. Esto ya se puede hacer con Typo3.Si se trata de frameworks, los más maduros que conozco, para hacer cosas generales como MVC (palabra de moda ¡Realmente lo odio! Como "performance" Si quieres vender algo, usa la palabra performance y featurerich y vendes ... qué el infierno) es
Zend
. Ha demostrado ser bueno llevar estándares a los codificadores de php chaos. Pero, typo3 también tiene un Framework además del CMS. Recientemente se ha reconstruido y ahora se llama flow3. Los marcos, por supuesto, cubren la abstracción de la base de datos, las plantillas y los conceptos para el almacenamiento en caché, pero tienen fortalezas individuales.Si se trata de almacenamiento en caché ... eso puede ser tremendamente complicado / multicapa. En PHP pensará en acelerador, código de operación, pero también en html, httpd, mysql, xml, css, js ... cualquier tipo de caché. Por supuesto, algunas partes deben almacenarse en caché y las partes dinámicas, como las respuestas de blog, no. Algunos deben solicitarse a través de AJAX con las URL generadas. JSON, hashbangs, etc.
Luego, le gustaría tener cualquier pequeño componente en su sitio web para que sea accedido o administrado solo por ciertos usuarios , por lo que conceptualmente juega un papel importante.
También le gustaría hacer estadísticas , tal vez tener un sistema distribuido / un facebook de facebook, etc. cualquier software que se construya sobre sus cms superiores ... por lo que necesita diferentes tipos de bases de datos inmemory, bigdata, xml, lo que sea .
bueno, creo que eso es suficiente por ahora. Si no ha oído hablar de typo3 / plone o de los marcos mencionados, tiene suficiente para estudiar. En ese camino encontrarás muchas soluciones para preguntas que aún no has hecho.
Si luego piensa, hagamos un nuevo CMS porque es 2013 y php está a punto de morir de todos modos, entonces puede unirse a cualquier otro grupo de desarrolladores con la esperanza de no perderse.
¡Buena suerte!
Y por cierto. ¿Qué tal si la gente ya no tendrá sitios web en el futuro? y todos estaremos en google +? Espero que los desarrolladores se vuelvan un poco más creativos y hagan algo útil (para no ser asimilados por el borgle)
//// Editar /// Solo un poco para su aplicación existente:
Si tiene un CMS php mysql y desea incrustar soporte multilang. puede usar su tabla con una columna adicional para cualquier idioma o insertar la traducción con una identificación de objeto y una identificación de idioma en la misma tabla o crear una tabla idéntica para cualquier idioma e insertar objetos allí, luego haga una unión de selección si lo desea para que se muestren todos. Para la base de datos, use utf8 general ci y, por supuesto, en el frente / backend use utf8 text / encoding. He usado segmentos de ruta de URL para URL de la manera que ya explicaste como
domain.org/en/about puede asignar el ID de lang a su tabla de contenido. de todos modos, necesita tener un mapa de parámetros para sus URL, por lo que le gustaría definir un parámetro para mapear desde un segmento de ruta en su URL que sería, por ejemplo,
domain.org/en/about/employees/IT/administrators/
configuración de búsqueda
pageid | url
1 | /about/employees/../ ..
1 | /../about/employees../../
asignar parámetros a la ruta de URL ""
por decir, eso ya se ha cubierto en la publicación superior.
Y para no olvidar, necesitaría "reescribir" la url en su archivo php generador que en la mayoría de los casos sería index.php
fuente
Trabajo de base de datos:
Crear tabla de idiomas 'idiomas':
Campos:
Cree una tabla en la base de datos 'contenido':
Campos:
Trabajo frontal:
Cuando el usuario selecciona cualquier idioma del menú desplegable o cualquier área, guarde la identificación del idioma seleccionado en la sesión como,
$_SESSION['language']=1;
Ahora obtenga datos del 'contenido' de la tabla de la base de datos en función de la identificación del idioma almacenada en la sesión.
Los detalles se pueden encontrar aquí http://skillrow.com/multilingual-website-in-php-2/
fuente
Como persona que vive en Quebec, donde casi todo el sitio es francés e inglés ... he probado muchos, si no la mayoría, plugins multilingües para WP ... la única solución útil que funciona nivelada con todo mi sitio es mQtranslate ... ¡vivo y muero con eso!
https://wordpress.org/plugins/mqtranslate/
fuente
¿Qué pasa con WORDPRESS +
MULTI-LANGUAGE SITE BASIS
(complemento)? el sitio tendrá estructura:El complemento proporciona una interfaz para la traducción de todas las frases, con una lógica simple:
entonces se puede superar:
echo translate('my_title', LNG); // LNG is auto-detected
ps sin embargo, verifique si el complemento aún está activo.
fuente
Una opción realmente simple que funciona con cualquier sitio web donde pueda cargar Javascript es www.multilingualizer.com
Le permite poner todo el texto para todos los idiomas en una página y luego oculta los idiomas que el usuario no necesita ver. Funciona bien.
fuente