Localización infinita, o cómo traducimos un mapa en tiempo real



¿Qué sucede cuando su producto comienza a venderse en otro país con su propio idioma y características culturales? Muy probablemente, la localización lo espera. En la mayoría de los casos, solo es necesario traducir los archivos de recursos para que los menús y los elementos de la interfaz estén en el idioma familiar para el usuario. Pero qué hacer si la base de lo que vende son datos, de los cuales hay muchos, llegan constantemente, en grandes volúmenes y requieren una traducción regular. Y no solo un idioma, sino varios idiomas a la vez.

Debajo del corte, encontrará una historia de cómo se resolvió este problema en 2GIS. Te diré con el ejemplo del último caso con Dubai, pero las prácticas son aplicables para cualquier idioma.

Sobre árabe


Toda esta historia comenzó con el hecho de que 2GIS se lanzó en Dubai, donde se usan dos idiomas: árabe e inglés.

La alta precisión de los datos es el valor más importante de la empresa. Se logra mediante el trabajo manual de cartógrafos y especialistas en el terreno. En Dubai, donde tanto los especialistas locales como los usuarios finales saben inglés, inicialmente solo se ingresaron los datos. En el proceso de crecimiento, decidieron no detenerse allí y agregar el idioma árabe.

Fiyi


Para el trabajo de los cartógrafos, tenemos nuestro propio software. Esta cosa se llama Fiji y sirve como un sistema maestro para recopilar datos de mapas. Ya escribimos cómo Fiji ayuda a los cartógrafos a editar casas y dibujar carreteras. Los datos cargados desde Fiji después del procesamiento y la preparación van al producto final para complacer a los usuarios. En el artículo, estoy hablando exactamente de lo que implementamos en Fiji para editar / almacenar / mostrar datos multilingües.

Términos


En el equipo usamos vocabulario específico. A continuación hay cuatro ejemplos ↓
El sistema admite trabajar con dos tipos de idiomas:

Idioma de metadatos : el idioma en el que se muestran todos los controles de usuario: IU, metadatos.

Idioma de datos : un idioma en el que se muestran los valores de los atributos de los geoobjetos, algunos directorios y clasificadores.

Las lenguas están ligadas a los territorios. Un territorio puede tener dos tipos de idiomas:

El idioma principal del territorio es el idioma adoptado oficialmente en ese territorio.

El idioma adicional del territorio es el idioma en el que queremos lanzar el producto. Viene además del principal.

Idiomas y dialectos


Los dialectos adoptados en diferentes regiones del país pueden variar significativamente. Por lo tanto, en algunos sistemas, el núcleo del lenguaje (= la versión básica) y los dialectos se almacenan por separado, y luego al descargar sus merjats. Para nosotros, este enfoque parecía muy complicado, por lo que decidimos considerar cada dialecto como un idioma independiente.

Matices relacionados con los idiomas y dialectos árabes. Para cada idioma, debe ingresar un indicador de dirección del carro con dos valores: de izquierda a derecha y de derecha a izquierda. Por defecto, el carro debe moverse de izquierda a derecha. Si el valor se establece de derecha a izquierda, debe cambiar la dirección del carro para todos los campos editables y multilingües. Aquí se escribió cómo se hizo esto en los productos finales. Teníamos que hacer lo mismo.

Ajustar a territorios


Nuestro mundo entero está dividido en ciertos territorios, que pueden ser países, regiones, regiones. Para cada territorio especificamos varios idiomas, uno de los cuales se considera el principal y el resto, adicional. La traducción se lleva a cabo desde el idioma principal a otros idiomas.

Por ejemplo, en el caso de Dubai, dejamos el inglés como idioma principal, porque tenía muchos datos. El árabe se hizo opcional.

Ingrese y cambie el idioma


Para que los cartógrafos trabajen cómodamente, rediseñamos nuestra interfaz en aquellos lugares donde se entiende la entrada multilingüe.



En esta imagen, puede ver que hemos dividido los idiomas en pestañas, donde el más a la izquierda es el idioma principal, y luego hay otros adicionales.

En las pestañas de idiomas adicionales, solo aquellos campos están disponibles para edición que tienen un indicador de la necesidad de traducción en la base de datos. Esto sirve como medida de protección y ayuda a centrar la atención del usuario en la traducción de los datos necesarios. Todo lo demás se edita en el idioma principal.



De hecho, la edición de datos en un idioma adicional puede ser necesaria solo si el cartógrafo mismo sabe varios idiomas y no quiere recurrir a la ayuda de un traductor. Para todos los demás, hay CrowdIn.

Crowdin, o transferencia de flujo


Por lo tanto, hemos permitido a nuestros cartógrafos completar datos en diferentes idiomas. Pero es mucho mejor entregar la tarea de traducción a profesionales.

Lo primero que viene a la mente al traducir la aplicación es entregar los archivos de recursos a los traductores y, después de transferirlos, volver a descargarlos.

En este asunto, la plataforma CrowdIn nos ayudó mucho. Le permite redirigir sus archivos a traductores profesionales. Lo único que quedaba era integrar los datos traducidos en nuestro sistema.

La situación se complica por el hecho de que los datos nos llegan en un flujo continuo, por lo tanto, nos gustaría recibir traducciones continuamente.

Optimizamos el sistema de la siguiente manera: si se realizan cambios en el idioma principal del territorio, cargamos los cambios para traducirlos a todos los idiomas adicionales de este territorio. Hacemos excepciones para los casos en que el cartógrafo mismo hizo la traducción. Aquí creemos que él comprende lo que está haciendo, y no hay necesidad de conectar un intérprete.

Para cada directorio u objeto de mapa, tenemos una versión de extremo a extremo, que se incrementa con cada actualización de datos. Entonces podemos obtener rápidamente todos los cambios de una versión específica.

El sistema de versiones es muy simple y eficiente, pero tiene un inconveniente significativo: de hecho, tenemos una sola cola y no podemos administrarla de ninguna manera. Nuestro máximo es omitir la versión. Es necesario cambiar a una cola normal, por ejemplo, a RabitMQ o Kafka, pero las manos aún no han llegado.

Para actualizar rápidamente el contenido, escribimos un pequeño servicio que funciona en tres transmisiones.

El primer flujo (Saver) elimina todos los datos que requieren traducción y genera archivos xml a partir de ellos.

El segundo (Exportar) los envía a CrowdIn y los coloca en el proyecto deseado, que indica el idioma principal desde el que estamos traduciendo y una lista de idiomas a los cuales traducir.

El tercero (Importar) sondea periódicamente la API CrowdIn para los archivos cuya traducción se ha realizado e instalado al 100%, e importa los archivos terminados a nuestra base de datos.



Sin un rastrillo no podría hacer. Nos topamos con nuestro sistema de versiones de datos.
Cuando descargamos la traducción de la palabra, la versión de los datos se actualizó y la palabra volvió a caer en la traducción.

Para evitar un bucle interminable de traducción, comenzamos a registrar datos. Cada palabra traducida está marcada, lo que elimina su envío repetido a CrowdIn.

Tutorial


Ahora te diré cómo sucede el trabajo con CrowdIn. Hay varias formas de trabajar con la plataforma, por ejemplo, puede cargar archivos en el repositorio de Git y CrowdIn los absorbe. Pero pensamos que trabajar a través de la API parece más conveniente.

CrowdIn tiene un tutorial bastante detallado, pero a continuación escribiré cómo lo hicimos.

Necesitamos obtener una clave API, que adjuntaremos a cada una de nuestras solicitudes, para que el sistema nos verifique. Vamos a la pestaña API en la configuración del proyecto y miramos lo que está escrito en la columna de clave API.



Esta clave debe agregarse al final de cada una de sus solicitudes de plataforma. Por ejemplo, así:
OBTENGA: https://api.crowdin.com/api/project/{myLitleProject}/download/all.zip?key={project-key}

2. Cree una carpeta donde subiremos los archivos dentro del proyecto.

 var uri = $"project/{_projectName}/add-directory?key={apiKey}"; var content = new MultipartFormDataContent { { new StringContent(crowdInDirectoryPath), "name" } }; return PostAsync(uri, content); 

Hay un pequeño momento torpe. Estamos escribiendo un servicio, sería bueno si al principio verifica si la carpeta que necesitamos está presente antes de intentar crearla. CrowdIn no tiene una forma normal de verificar una carpeta, por lo que enviamos una solicitud de creación. Si no está allí, CrowdIn lo creará y devolverá el código 200. Si había una carpeta, no creará nada y devolverá el código 500.

3. Exportar archivos. La función de agregar archivo tiene muchas opciones y parámetros, cómo leer y dónde. A continuación se muestra un ejemplo de cómo cargamos datos con archivos xml.

Ejemplo
Ponemos todos los datos que vamos a traducir en archivos xml con la siguiente estructura.

 <LocalizableDocument> <LocalizableValues> <LocalizableValue><Attributes> <LocalizableAttributeValue> <AttributeName/> <Value/> </LocalizableAttributeValue> </Attributes> </LocalizableValue> </LocalizableValues> </LocalizableDocument> 

Para que CrowdIn analice qué datos del archivo deben traducirse, debe especificarse. Para hacer esto, debe escribir una matriz de parámetros de elementos traducibles con las rutas a los elementos necesarios del documento en el contenido. En nuestro caso, se veía así:

 var uri = $"project/{_projectName}/add-file?key={apiKey}"; var content = new MultipartFormDataContent { { new StringContent("/LocalizableDocument/LocalizableValues/LocalizableValue/Attributes/LocalizableAttributeValue/Value"), "translatable_elements[0]" } }; foreach (var filePath in filePaths) { var fileName = Path.GetFileName(filePath); var fileStream = File.OpenRead(filePath); var fileContent = new StreamContent(fileStream); content.Add(fileContent, $"files[{_crowdInDirectoryPath}/{fileName}]", fileName); } return PostAsync(uri, content); 


Tenga en cuenta: la documentación establece que CrowdIn puede masticar un máximo de 20 archivos a la vez, mientras que el tamaño de un archivo no debe exceder los 100 MB.

4. Descubrimos qué archivos hemos traducido completamente. Hacemos esto usando un comando para un idioma específico.

 var uri = $"project/{_projectName}/language-status?key={apiKey}"; var content = new MultipartFormDataContent {{ new StringContent(langCode), "language" } }; return PostAsync(uri, content); 

La plataforma nos devolverá algo como esto:

  <item> <node_type>directory</node_type> <id>29812</id> <name>Version 1.0</name> <files> <item> <node_type>file</node_type> <id>29827</id> <name>strings.xml</name> <node_type>file</node_type> <phrases>7</phrases> <translated>0</translated> <approved>0</approved> <words>32</words> <words_translated>0</words_translated> <words_approved>0</words_approved> </item> </files> </item> 

Aquí nos interesan los valores <traducido /> y <aprobado />. El primero indica el porcentaje de líneas traducidas en este archivo, el segundo muestra el porcentaje de valores aprobados si, además del traductor, un revisor también participa en el flujo de trabajo. Dependiendo de nuestro flujo de trabajo, por ejemplo, a 100 consideramos el documento traducido y aprobado. Ahora este archivo puede volver a importarse.

5. Importe el archivo nuevamente a nuestro sistema.
Esto se hace con una simple solicitud GET.

 https://api.crowdin.com/api/project/{_projectName}/export-file?file={_crowdInDirectoryPath}/{fileName}&language={langCode}&key={project-key} 

El archivo resultante se deserializa y los datos se importan a nuestro sistema.

En lugar de una conclusión


En términos generales, eso es todo. Por supuesto, todavía necesitábamos refinar la visualización de las firmas en el mapa de Fiji para que se mostraran en el idioma correcto, dependiendo del territorio que el cartógrafo gobierne ahora. Era necesario acordar con otros sistemas cómo les proporcionaremos datos multilingües, pero esta es otra historia.

Como resultado, recibimos el servicio en el espíritu de "encendido y olvidado". Los cartógrafos ingresan datos, los traductores traducen, el jeque está satisfecho, el servicio carga los datos cuando es necesario y resolvemos problemas más urgentes sin pensar en cómo funciona nuestro sistema en varios idiomas.

Source: https://habr.com/ru/post/es425283/


All Articles